mirror of
https://github.com/veekun/pokedex.git
synced 2024-08-20 18:16:34 +00:00
Make great strides towards an actual game-aware API
Huzzah! Also, I decided to namespace identifiers. For now. We'll see how it goes.
This commit is contained in:
parent
aa32cf0b53
commit
969d671c48
2 changed files with 470 additions and 380 deletions
|
@ -17,6 +17,7 @@ from pathlib import Path
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
from camel import Camel
|
||||||
from classtools import reify
|
from classtools import reify
|
||||||
from construct import *
|
from construct import *
|
||||||
|
|
||||||
|
@ -92,364 +93,364 @@ GAME_RELEASE_MD5SUM_INDEX = {
|
||||||
|
|
||||||
|
|
||||||
GROWTH_RATES = {
|
GROWTH_RATES = {
|
||||||
0: 'medium',
|
0: 'growth-rate.medium',
|
||||||
3: 'medium-slow',
|
3: 'growth-rate.medium-slow',
|
||||||
4: 'fast',
|
4: 'growth-rate.fast',
|
||||||
5: 'slow',
|
5: 'growth-rate.slow',
|
||||||
}
|
}
|
||||||
|
|
||||||
EVOLUTION_TRIGGERS = {
|
EVOLUTION_TRIGGERS = {
|
||||||
1: 'level-up',
|
1: 'evolution-trigger.level-up',
|
||||||
2: 'use-item',
|
2: 'evolution-trigger.use-item',
|
||||||
3: 'trade',
|
3: 'evolution-trigger.trade',
|
||||||
}
|
}
|
||||||
|
|
||||||
# TODO these are loci, not enums, so hardcoding all their identifiers here
|
# TODO these are loci, not enums, so hardcoding all their identifiers here
|
||||||
# makes me nonspecifically uncomfortable
|
# makes me nonspecifically uncomfortable
|
||||||
POKEMON_IDENTIFIERS = {
|
POKEMON_IDENTIFIERS = {
|
||||||
1: 'bulbasaur',
|
1: 'pokemon.bulbasaur',
|
||||||
2: 'ivysaur',
|
2: 'pokemon.ivysaur',
|
||||||
3: 'venusaur',
|
3: 'pokemon.venusaur',
|
||||||
4: 'charmander',
|
4: 'pokemon.charmander',
|
||||||
5: 'charmeleon',
|
5: 'pokemon.charmeleon',
|
||||||
6: 'charizard',
|
6: 'pokemon.charizard',
|
||||||
7: 'squirtle',
|
7: 'pokemon.squirtle',
|
||||||
8: 'wartortle',
|
8: 'pokemon.wartortle',
|
||||||
9: 'blastoise',
|
9: 'pokemon.blastoise',
|
||||||
10: 'caterpie',
|
10: 'pokemon.caterpie',
|
||||||
11: 'metapod',
|
11: 'pokemon.metapod',
|
||||||
12: 'butterfree',
|
12: 'pokemon.butterfree',
|
||||||
13: 'weedle',
|
13: 'pokemon.weedle',
|
||||||
14: 'kakuna',
|
14: 'pokemon.kakuna',
|
||||||
15: 'beedrill',
|
15: 'pokemon.beedrill',
|
||||||
16: 'pidgey',
|
16: 'pokemon.pidgey',
|
||||||
17: 'pidgeotto',
|
17: 'pokemon.pidgeotto',
|
||||||
18: 'pidgeot',
|
18: 'pokemon.pidgeot',
|
||||||
19: 'rattata',
|
19: 'pokemon.rattata',
|
||||||
20: 'raticate',
|
20: 'pokemon.raticate',
|
||||||
21: 'spearow',
|
21: 'pokemon.spearow',
|
||||||
22: 'fearow',
|
22: 'pokemon.fearow',
|
||||||
23: 'ekans',
|
23: 'pokemon.ekans',
|
||||||
24: 'arbok',
|
24: 'pokemon.arbok',
|
||||||
25: 'pikachu',
|
25: 'pokemon.pikachu',
|
||||||
26: 'raichu',
|
26: 'pokemon.raichu',
|
||||||
27: 'sandshrew',
|
27: 'pokemon.sandshrew',
|
||||||
28: 'sandslash',
|
28: 'pokemon.sandslash',
|
||||||
29: 'nidoran-f',
|
29: 'pokemon.nidoran-f',
|
||||||
30: 'nidorina',
|
30: 'pokemon.nidorina',
|
||||||
31: 'nidoqueen',
|
31: 'pokemon.nidoqueen',
|
||||||
32: 'nidoran-m',
|
32: 'pokemon.nidoran-m',
|
||||||
33: 'nidorino',
|
33: 'pokemon.nidorino',
|
||||||
34: 'nidoking',
|
34: 'pokemon.nidoking',
|
||||||
35: 'clefairy',
|
35: 'pokemon.clefairy',
|
||||||
36: 'clefable',
|
36: 'pokemon.clefable',
|
||||||
37: 'vulpix',
|
37: 'pokemon.vulpix',
|
||||||
38: 'ninetales',
|
38: 'pokemon.ninetales',
|
||||||
39: 'jigglypuff',
|
39: 'pokemon.jigglypuff',
|
||||||
40: 'wigglytuff',
|
40: 'pokemon.wigglytuff',
|
||||||
41: 'zubat',
|
41: 'pokemon.zubat',
|
||||||
42: 'golbat',
|
42: 'pokemon.golbat',
|
||||||
43: 'oddish',
|
43: 'pokemon.oddish',
|
||||||
44: 'gloom',
|
44: 'pokemon.gloom',
|
||||||
45: 'vileplume',
|
45: 'pokemon.vileplume',
|
||||||
46: 'paras',
|
46: 'pokemon.paras',
|
||||||
47: 'parasect',
|
47: 'pokemon.parasect',
|
||||||
48: 'venonat',
|
48: 'pokemon.venonat',
|
||||||
49: 'venomoth',
|
49: 'pokemon.venomoth',
|
||||||
50: 'diglett',
|
50: 'pokemon.diglett',
|
||||||
51: 'dugtrio',
|
51: 'pokemon.dugtrio',
|
||||||
52: 'meowth',
|
52: 'pokemon.meowth',
|
||||||
53: 'persian',
|
53: 'pokemon.persian',
|
||||||
54: 'psyduck',
|
54: 'pokemon.psyduck',
|
||||||
55: 'golduck',
|
55: 'pokemon.golduck',
|
||||||
56: 'mankey',
|
56: 'pokemon.mankey',
|
||||||
57: 'primeape',
|
57: 'pokemon.primeape',
|
||||||
58: 'growlithe',
|
58: 'pokemon.growlithe',
|
||||||
59: 'arcanine',
|
59: 'pokemon.arcanine',
|
||||||
60: 'poliwag',
|
60: 'pokemon.poliwag',
|
||||||
61: 'poliwhirl',
|
61: 'pokemon.poliwhirl',
|
||||||
62: 'poliwrath',
|
62: 'pokemon.poliwrath',
|
||||||
63: 'abra',
|
63: 'pokemon.abra',
|
||||||
64: 'kadabra',
|
64: 'pokemon.kadabra',
|
||||||
65: 'alakazam',
|
65: 'pokemon.alakazam',
|
||||||
66: 'machop',
|
66: 'pokemon.machop',
|
||||||
67: 'machoke',
|
67: 'pokemon.machoke',
|
||||||
68: 'machamp',
|
68: 'pokemon.machamp',
|
||||||
69: 'bellsprout',
|
69: 'pokemon.bellsprout',
|
||||||
70: 'weepinbell',
|
70: 'pokemon.weepinbell',
|
||||||
71: 'victreebel',
|
71: 'pokemon.victreebel',
|
||||||
72: 'tentacool',
|
72: 'pokemon.tentacool',
|
||||||
73: 'tentacruel',
|
73: 'pokemon.tentacruel',
|
||||||
74: 'geodude',
|
74: 'pokemon.geodude',
|
||||||
75: 'graveler',
|
75: 'pokemon.graveler',
|
||||||
76: 'golem',
|
76: 'pokemon.golem',
|
||||||
77: 'ponyta',
|
77: 'pokemon.ponyta',
|
||||||
78: 'rapidash',
|
78: 'pokemon.rapidash',
|
||||||
79: 'slowpoke',
|
79: 'pokemon.slowpoke',
|
||||||
80: 'slowbro',
|
80: 'pokemon.slowbro',
|
||||||
81: 'magnemite',
|
81: 'pokemon.magnemite',
|
||||||
82: 'magneton',
|
82: 'pokemon.magneton',
|
||||||
83: 'farfetchd',
|
83: 'pokemon.farfetchd',
|
||||||
84: 'doduo',
|
84: 'pokemon.doduo',
|
||||||
85: 'dodrio',
|
85: 'pokemon.dodrio',
|
||||||
86: 'seel',
|
86: 'pokemon.seel',
|
||||||
87: 'dewgong',
|
87: 'pokemon.dewgong',
|
||||||
88: 'grimer',
|
88: 'pokemon.grimer',
|
||||||
89: 'muk',
|
89: 'pokemon.muk',
|
||||||
90: 'shellder',
|
90: 'pokemon.shellder',
|
||||||
91: 'cloyster',
|
91: 'pokemon.cloyster',
|
||||||
92: 'gastly',
|
92: 'pokemon.gastly',
|
||||||
93: 'haunter',
|
93: 'pokemon.haunter',
|
||||||
94: 'gengar',
|
94: 'pokemon.gengar',
|
||||||
95: 'onix',
|
95: 'pokemon.onix',
|
||||||
96: 'drowzee',
|
96: 'pokemon.drowzee',
|
||||||
97: 'hypno',
|
97: 'pokemon.hypno',
|
||||||
98: 'krabby',
|
98: 'pokemon.krabby',
|
||||||
99: 'kingler',
|
99: 'pokemon.kingler',
|
||||||
100: 'voltorb',
|
100: 'pokemon.voltorb',
|
||||||
101: 'electrode',
|
101: 'pokemon.electrode',
|
||||||
102: 'exeggcute',
|
102: 'pokemon.exeggcute',
|
||||||
103: 'exeggutor',
|
103: 'pokemon.exeggutor',
|
||||||
104: 'cubone',
|
104: 'pokemon.cubone',
|
||||||
105: 'marowak',
|
105: 'pokemon.marowak',
|
||||||
106: 'hitmonlee',
|
106: 'pokemon.hitmonlee',
|
||||||
107: 'hitmonchan',
|
107: 'pokemon.hitmonchan',
|
||||||
108: 'lickitung',
|
108: 'pokemon.lickitung',
|
||||||
109: 'koffing',
|
109: 'pokemon.koffing',
|
||||||
110: 'weezing',
|
110: 'pokemon.weezing',
|
||||||
111: 'rhyhorn',
|
111: 'pokemon.rhyhorn',
|
||||||
112: 'rhydon',
|
112: 'pokemon.rhydon',
|
||||||
113: 'chansey',
|
113: 'pokemon.chansey',
|
||||||
114: 'tangela',
|
114: 'pokemon.tangela',
|
||||||
115: 'kangaskhan',
|
115: 'pokemon.kangaskhan',
|
||||||
116: 'horsea',
|
116: 'pokemon.horsea',
|
||||||
117: 'seadra',
|
117: 'pokemon.seadra',
|
||||||
118: 'goldeen',
|
118: 'pokemon.goldeen',
|
||||||
119: 'seaking',
|
119: 'pokemon.seaking',
|
||||||
120: 'staryu',
|
120: 'pokemon.staryu',
|
||||||
121: 'starmie',
|
121: 'pokemon.starmie',
|
||||||
122: 'mr-mime',
|
122: 'pokemon.mr-mime',
|
||||||
123: 'scyther',
|
123: 'pokemon.scyther',
|
||||||
124: 'jynx',
|
124: 'pokemon.jynx',
|
||||||
125: 'electabuzz',
|
125: 'pokemon.electabuzz',
|
||||||
126: 'magmar',
|
126: 'pokemon.magmar',
|
||||||
127: 'pinsir',
|
127: 'pokemon.pinsir',
|
||||||
128: 'tauros',
|
128: 'pokemon.tauros',
|
||||||
129: 'magikarp',
|
129: 'pokemon.magikarp',
|
||||||
130: 'gyarados',
|
130: 'pokemon.gyarados',
|
||||||
131: 'lapras',
|
131: 'pokemon.lapras',
|
||||||
132: 'ditto',
|
132: 'pokemon.ditto',
|
||||||
133: 'eevee',
|
133: 'pokemon.eevee',
|
||||||
134: 'vaporeon',
|
134: 'pokemon.vaporeon',
|
||||||
135: 'jolteon',
|
135: 'pokemon.jolteon',
|
||||||
136: 'flareon',
|
136: 'pokemon.flareon',
|
||||||
137: 'porygon',
|
137: 'pokemon.porygon',
|
||||||
138: 'omanyte',
|
138: 'pokemon.omanyte',
|
||||||
139: 'omastar',
|
139: 'pokemon.omastar',
|
||||||
140: 'kabuto',
|
140: 'pokemon.kabuto',
|
||||||
141: 'kabutops',
|
141: 'pokemon.kabutops',
|
||||||
142: 'aerodactyl',
|
142: 'pokemon.aerodactyl',
|
||||||
143: 'snorlax',
|
143: 'pokemon.snorlax',
|
||||||
144: 'articuno',
|
144: 'pokemon.articuno',
|
||||||
145: 'zapdos',
|
145: 'pokemon.zapdos',
|
||||||
146: 'moltres',
|
146: 'pokemon.moltres',
|
||||||
147: 'dratini',
|
147: 'pokemon.dratini',
|
||||||
148: 'dragonair',
|
148: 'pokemon.dragonair',
|
||||||
149: 'dragonite',
|
149: 'pokemon.dragonite',
|
||||||
150: 'mewtwo',
|
150: 'pokemon.mewtwo',
|
||||||
151: 'mew',
|
151: 'pokemon.mew',
|
||||||
}
|
}
|
||||||
|
|
||||||
TYPE_IDENTIFIERS = {
|
TYPE_IDENTIFIERS = {
|
||||||
0: 'normal',
|
0: 'type.normal',
|
||||||
1: 'fighting',
|
1: 'type.fighting',
|
||||||
2: 'flying',
|
2: 'type.flying',
|
||||||
3: 'poison',
|
3: 'type.poison',
|
||||||
4: 'ground',
|
4: 'type.ground',
|
||||||
5: 'rock',
|
5: 'type.rock',
|
||||||
#6: 'bird',
|
#6: 'type.bird',
|
||||||
7: 'bug',
|
7: 'type.bug',
|
||||||
8: 'ghost',
|
8: 'type.ghost',
|
||||||
9: 'steel',
|
9: 'type.steel',
|
||||||
20: 'fire',
|
20: 'type.fire',
|
||||||
21: 'water',
|
21: 'type.water',
|
||||||
22: 'grass',
|
22: 'type.grass',
|
||||||
23: 'electric',
|
23: 'type.electric',
|
||||||
24: 'psychic',
|
24: 'type.psychic',
|
||||||
25: 'ice',
|
25: 'type.ice',
|
||||||
26: 'dragon',
|
26: 'type.dragon',
|
||||||
27: 'dark',
|
27: 'type.dark',
|
||||||
}
|
}
|
||||||
|
|
||||||
MOVE_IDENTIFIERS = {
|
MOVE_IDENTIFIERS = {
|
||||||
# TODO stupid hack for initial moveset
|
# TODO stupid hack for initial moveset
|
||||||
0: '--',
|
0: '--',
|
||||||
|
|
||||||
1: 'pound',
|
1: 'move.pound',
|
||||||
2: 'karate-chop',
|
2: 'move.karate-chop',
|
||||||
3: 'double-slap',
|
3: 'move.double-slap',
|
||||||
4: 'comet-punch',
|
4: 'move.comet-punch',
|
||||||
5: 'mega-punch',
|
5: 'move.mega-punch',
|
||||||
6: 'pay-day',
|
6: 'move.pay-day',
|
||||||
7: 'fire-punch',
|
7: 'move.fire-punch',
|
||||||
8: 'ice-punch',
|
8: 'move.ice-punch',
|
||||||
9: 'thunder-punch',
|
9: 'move.thunder-punch',
|
||||||
10: 'scratch',
|
10: 'move.scratch',
|
||||||
11: 'vice-grip',
|
11: 'move.vice-grip',
|
||||||
12: 'guillotine',
|
12: 'move.guillotine',
|
||||||
13: 'razor-wind',
|
13: 'move.razor-wind',
|
||||||
14: 'swords-dance',
|
14: 'move.swords-dance',
|
||||||
15: 'cut',
|
15: 'move.cut',
|
||||||
16: 'gust',
|
16: 'move.gust',
|
||||||
17: 'wing-attack',
|
17: 'move.wing-attack',
|
||||||
18: 'whirlwind',
|
18: 'move.whirlwind',
|
||||||
19: 'fly',
|
19: 'move.fly',
|
||||||
20: 'bind',
|
20: 'move.bind',
|
||||||
21: 'slam',
|
21: 'move.slam',
|
||||||
22: 'vine-whip',
|
22: 'move.vine-whip',
|
||||||
23: 'stomp',
|
23: 'move.stomp',
|
||||||
24: 'double-kick',
|
24: 'move.double-kick',
|
||||||
25: 'mega-kick',
|
25: 'move.mega-kick',
|
||||||
26: 'jump-kick',
|
26: 'move.jump-kick',
|
||||||
27: 'rolling-kick',
|
27: 'move.rolling-kick',
|
||||||
28: 'sand-attack',
|
28: 'move.sand-attack',
|
||||||
29: 'headbutt',
|
29: 'move.headbutt',
|
||||||
30: 'horn-attack',
|
30: 'move.horn-attack',
|
||||||
31: 'fury-attack',
|
31: 'move.fury-attack',
|
||||||
32: 'horn-drill',
|
32: 'move.horn-drill',
|
||||||
33: 'tackle',
|
33: 'move.tackle',
|
||||||
34: 'body-slam',
|
34: 'move.body-slam',
|
||||||
35: 'wrap',
|
35: 'move.wrap',
|
||||||
36: 'take-down',
|
36: 'move.take-down',
|
||||||
37: 'thrash',
|
37: 'move.thrash',
|
||||||
38: 'double-edge',
|
38: 'move.double-edge',
|
||||||
39: 'tail-whip',
|
39: 'move.tail-whip',
|
||||||
40: 'poison-sting',
|
40: 'move.poison-sting',
|
||||||
41: 'twineedle',
|
41: 'move.twineedle',
|
||||||
42: 'pin-missile',
|
42: 'move.pin-missile',
|
||||||
43: 'leer',
|
43: 'move.leer',
|
||||||
44: 'bite',
|
44: 'move.bite',
|
||||||
45: 'growl',
|
45: 'move.growl',
|
||||||
46: 'roar',
|
46: 'move.roar',
|
||||||
47: 'sing',
|
47: 'move.sing',
|
||||||
48: 'supersonic',
|
48: 'move.supersonic',
|
||||||
49: 'sonic-boom',
|
49: 'move.sonic-boom',
|
||||||
50: 'disable',
|
50: 'move.disable',
|
||||||
51: 'acid',
|
51: 'move.acid',
|
||||||
52: 'ember',
|
52: 'move.ember',
|
||||||
53: 'flamethrower',
|
53: 'move.flamethrower',
|
||||||
54: 'mist',
|
54: 'move.mist',
|
||||||
55: 'water-gun',
|
55: 'move.water-gun',
|
||||||
56: 'hydro-pump',
|
56: 'move.hydro-pump',
|
||||||
57: 'surf',
|
57: 'move.surf',
|
||||||
58: 'ice-beam',
|
58: 'move.ice-beam',
|
||||||
59: 'blizzard',
|
59: 'move.blizzard',
|
||||||
60: 'psybeam',
|
60: 'move.psybeam',
|
||||||
61: 'bubble-beam',
|
61: 'move.bubble-beam',
|
||||||
62: 'aurora-beam',
|
62: 'move.aurora-beam',
|
||||||
63: 'hyper-beam',
|
63: 'move.hyper-beam',
|
||||||
64: 'peck',
|
64: 'move.peck',
|
||||||
65: 'drill-peck',
|
65: 'move.drill-peck',
|
||||||
66: 'submission',
|
66: 'move.submission',
|
||||||
67: 'low-kick',
|
67: 'move.low-kick',
|
||||||
68: 'counter',
|
68: 'move.counter',
|
||||||
69: 'seismic-toss',
|
69: 'move.seismic-toss',
|
||||||
70: 'strength',
|
70: 'move.strength',
|
||||||
71: 'absorb',
|
71: 'move.absorb',
|
||||||
72: 'mega-drain',
|
72: 'move.mega-drain',
|
||||||
73: 'leech-seed',
|
73: 'move.leech-seed',
|
||||||
74: 'growth',
|
74: 'move.growth',
|
||||||
75: 'razor-leaf',
|
75: 'move.razor-leaf',
|
||||||
76: 'solar-beam',
|
76: 'move.solar-beam',
|
||||||
77: 'poison-powder',
|
77: 'move.poison-powder',
|
||||||
78: 'stun-spore',
|
78: 'move.stun-spore',
|
||||||
79: 'sleep-powder',
|
79: 'move.sleep-powder',
|
||||||
80: 'petal-dance',
|
80: 'move.petal-dance',
|
||||||
81: 'string-shot',
|
81: 'move.string-shot',
|
||||||
82: 'dragon-rage',
|
82: 'move.dragon-rage',
|
||||||
83: 'fire-spin',
|
83: 'move.fire-spin',
|
||||||
84: 'thunder-shock',
|
84: 'move.thunder-shock',
|
||||||
85: 'thunderbolt',
|
85: 'move.thunderbolt',
|
||||||
86: 'thunder-wave',
|
86: 'move.thunder-wave',
|
||||||
87: 'thunder',
|
87: 'move.thunder',
|
||||||
88: 'rock-throw',
|
88: 'move.rock-throw',
|
||||||
89: 'earthquake',
|
89: 'move.earthquake',
|
||||||
90: 'fissure',
|
90: 'move.fissure',
|
||||||
91: 'dig',
|
91: 'move.dig',
|
||||||
92: 'toxic',
|
92: 'move.toxic',
|
||||||
93: 'confusion',
|
93: 'move.confusion',
|
||||||
94: 'psychic',
|
94: 'move.psychic',
|
||||||
95: 'hypnosis',
|
95: 'move.hypnosis',
|
||||||
96: 'meditate',
|
96: 'move.meditate',
|
||||||
97: 'agility',
|
97: 'move.agility',
|
||||||
98: 'quick-attack',
|
98: 'move.quick-attack',
|
||||||
99: 'rage',
|
99: 'move.rage',
|
||||||
100: 'teleport',
|
100: 'move.teleport',
|
||||||
101: 'night-shade',
|
101: 'move.night-shade',
|
||||||
102: 'mimic',
|
102: 'move.mimic',
|
||||||
103: 'screech',
|
103: 'move.screech',
|
||||||
104: 'double-team',
|
104: 'move.double-team',
|
||||||
105: 'recover',
|
105: 'move.recover',
|
||||||
106: 'harden',
|
106: 'move.harden',
|
||||||
107: 'minimize',
|
107: 'move.minimize',
|
||||||
108: 'smokescreen',
|
108: 'move.smokescreen',
|
||||||
109: 'confuse-ray',
|
109: 'move.confuse-ray',
|
||||||
110: 'withdraw',
|
110: 'move.withdraw',
|
||||||
111: 'defense-curl',
|
111: 'move.defense-curl',
|
||||||
112: 'barrier',
|
112: 'move.barrier',
|
||||||
113: 'light-screen',
|
113: 'move.light-screen',
|
||||||
114: 'haze',
|
114: 'move.haze',
|
||||||
115: 'reflect',
|
115: 'move.reflect',
|
||||||
116: 'focus-energy',
|
116: 'move.focus-energy',
|
||||||
117: 'bide',
|
117: 'move.bide',
|
||||||
118: 'metronome',
|
118: 'move.metronome',
|
||||||
119: 'mirror-move',
|
119: 'move.mirror-move',
|
||||||
120: 'self-destruct',
|
120: 'move.self-destruct',
|
||||||
121: 'egg-bomb',
|
121: 'move.egg-bomb',
|
||||||
122: 'lick',
|
122: 'move.lick',
|
||||||
123: 'smog',
|
123: 'move.smog',
|
||||||
124: 'sludge',
|
124: 'move.sludge',
|
||||||
125: 'bone-club',
|
125: 'move.bone-club',
|
||||||
126: 'fire-blast',
|
126: 'move.fire-blast',
|
||||||
127: 'waterfall',
|
127: 'move.waterfall',
|
||||||
128: 'clamp',
|
128: 'move.clamp',
|
||||||
129: 'swift',
|
129: 'move.swift',
|
||||||
130: 'skull-bash',
|
130: 'move.skull-bash',
|
||||||
131: 'spike-cannon',
|
131: 'move.spike-cannon',
|
||||||
132: 'constrict',
|
132: 'move.constrict',
|
||||||
133: 'amnesia',
|
133: 'move.amnesia',
|
||||||
134: 'kinesis',
|
134: 'move.kinesis',
|
||||||
135: 'soft-boiled',
|
135: 'move.soft-boiled',
|
||||||
136: 'high-jump-kick',
|
136: 'move.high-jump-kick',
|
||||||
137: 'glare',
|
137: 'move.glare',
|
||||||
138: 'dream-eater',
|
138: 'move.dream-eater',
|
||||||
139: 'poison-gas',
|
139: 'move.poison-gas',
|
||||||
140: 'barrage',
|
140: 'move.barrage',
|
||||||
141: 'leech-life',
|
141: 'move.leech-life',
|
||||||
142: 'lovely-kiss',
|
142: 'move.lovely-kiss',
|
||||||
143: 'sky-attack',
|
143: 'move.sky-attack',
|
||||||
144: 'transform',
|
144: 'move.transform',
|
||||||
145: 'bubble',
|
145: 'move.bubble',
|
||||||
146: 'dizzy-punch',
|
146: 'move.dizzy-punch',
|
||||||
147: 'spore',
|
147: 'move.spore',
|
||||||
148: 'flash',
|
148: 'move.flash',
|
||||||
149: 'psywave',
|
149: 'move.psywave',
|
||||||
150: 'splash',
|
150: 'move.splash',
|
||||||
151: 'acid-armor',
|
151: 'move.acid-armor',
|
||||||
152: 'crabhammer',
|
152: 'move.crabhammer',
|
||||||
153: 'explosion',
|
153: 'move.explosion',
|
||||||
154: 'fury-swipes',
|
154: 'move.fury-swipes',
|
||||||
155: 'bonemerang',
|
155: 'move.bonemerang',
|
||||||
156: 'rest',
|
156: 'move.rest',
|
||||||
157: 'rock-slide',
|
157: 'move.rock-slide',
|
||||||
158: 'hyper-fang',
|
158: 'move.hyper-fang',
|
||||||
159: 'sharpen',
|
159: 'move.sharpen',
|
||||||
160: 'conversion',
|
160: 'move.conversion',
|
||||||
161: 'tri-attack',
|
161: 'move.tri-attack',
|
||||||
162: 'super-fang',
|
162: 'move.super-fang',
|
||||||
163: 'slash',
|
163: 'move.slash',
|
||||||
164: 'substitute',
|
164: 'move.substitute',
|
||||||
165: 'struggle',
|
165: 'move.struggle',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1178,11 +1179,11 @@ evos_moves_struct = Struct(
|
||||||
Embedded(Switch(
|
Embedded(Switch(
|
||||||
'evo_arguments',
|
'evo_arguments',
|
||||||
lambda ctx: ctx.evo_trigger, {
|
lambda ctx: ctx.evo_trigger, {
|
||||||
'level-up': Struct(
|
'evolution-trigger.level-up': Struct(
|
||||||
'---',
|
'---',
|
||||||
ULInt8('evo_level'),
|
ULInt8('evo_level'),
|
||||||
),
|
),
|
||||||
'use-item': Struct(
|
'evolution-trigger.use-item': Struct(
|
||||||
'---',
|
'---',
|
||||||
# TODO item enum too wow!
|
# TODO item enum too wow!
|
||||||
ULInt8('evo_item'),
|
ULInt8('evo_item'),
|
||||||
|
@ -1190,7 +1191,7 @@ evos_moves_struct = Struct(
|
||||||
ULInt8('evo_level'),
|
ULInt8('evo_level'),
|
||||||
),
|
),
|
||||||
# TODO ??? always seems to be 1 here too
|
# TODO ??? always seems to be 1 here too
|
||||||
'trade': Struct(
|
'evolution-trigger.trade': Struct(
|
||||||
'---',
|
'---',
|
||||||
ULInt8('evo_level'),
|
ULInt8('evo_level'),
|
||||||
),
|
),
|
||||||
|
@ -1280,8 +1281,14 @@ class RBYCart:
|
||||||
Return a dict of raw file offsets. The keys are the names used in the
|
Return a dict of raw file offsets. The keys are the names used in the
|
||||||
pokered project.
|
pokered project.
|
||||||
"""
|
"""
|
||||||
|
# The base stats are always in the same place in RBY, and only slightly
|
||||||
|
# off in RG. Not sure why! But it hopefully means recompilation
|
||||||
|
# doesn't affect them.
|
||||||
addresses = {
|
addresses = {
|
||||||
# These seem to always be the same. Not sure why!
|
# These ones have, thusfar, defied automatic detection, as they're
|
||||||
|
# just part of a big old block of data — so I can't just look for
|
||||||
|
# code nearby.
|
||||||
|
# TODO these are for rby; fix for rg, and maybe y?
|
||||||
'BaseStats': unbank('0E:43DE'),
|
'BaseStats': unbank('0E:43DE'),
|
||||||
'MewBaseStats': unbank('01:425B'),
|
'MewBaseStats': unbank('01:425B'),
|
||||||
}
|
}
|
||||||
|
@ -1624,6 +1631,7 @@ class RBYCart:
|
||||||
def pokemon_records(self):
|
def pokemon_records(self):
|
||||||
"""List of pokemon_structs."""
|
"""List of pokemon_structs."""
|
||||||
self.stream.seek(self.addrs['BaseStats'])
|
self.stream.seek(self.addrs['BaseStats'])
|
||||||
|
print(self.stream.read(100).hex())
|
||||||
records = Array(self.NUM_POKEMON - 1, pokemon_struct).parse_stream(self.stream)
|
records = Array(self.NUM_POKEMON - 1, pokemon_struct).parse_stream(self.stream)
|
||||||
# Mew's data is, awkwardly, stored separately
|
# Mew's data is, awkwardly, stored separately
|
||||||
self.stream.seek(self.addrs['MewBaseStats'])
|
self.stream.seek(self.addrs['MewBaseStats'])
|
||||||
|
@ -1713,13 +1721,16 @@ class WriterWrapper:
|
||||||
return getattr(self.locus, key)
|
return getattr(self.locus, key)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main(root):
|
||||||
# TODO does this need to take arguments? or like, sprite mode i guess
|
# TODO does this need to take arguments? or like, sprite mode i guess
|
||||||
carts = []
|
carts = []
|
||||||
for filename in sys.argv[1:]:
|
for filename in sys.argv[1:]:
|
||||||
cart = RBYCart(Path(filename))
|
cart = RBYCart(Path(filename))
|
||||||
carts.append(cart)
|
carts.append(cart)
|
||||||
|
|
||||||
|
root /= carts[0].game
|
||||||
|
root.mkdir(exist_ok=True)
|
||||||
|
|
||||||
#loader = RBYLoader(*carts)
|
#loader = RBYLoader(*carts)
|
||||||
pokemons = OrderedDict([
|
pokemons = OrderedDict([
|
||||||
(POKEMON_IDENTIFIERS[id + 1], schema.Pokemon())
|
(POKEMON_IDENTIFIERS[id + 1], schema.Pokemon())
|
||||||
|
@ -1788,11 +1799,10 @@ def main():
|
||||||
evolutions.append(evo)
|
evolutions.append(evo)
|
||||||
writer.evolutions = evolutions
|
writer.evolutions = evolutions
|
||||||
|
|
||||||
|
with (root / 'pokemon.yaml').open('w') as f:
|
||||||
from camel import Camel
|
f.write(Camel([schema.POKEDEX_TYPES]).dump(pokemons))
|
||||||
print(Camel([schema.POKEDEX_TYPES]).dump(pokemons))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
# TODO yeah fix this up
|
||||||
|
main(Path('pokedex/data'))
|
||||||
|
|
|
@ -3,21 +3,40 @@
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
from pprint import pprint
|
from pprint import pprint
|
||||||
|
import types
|
||||||
|
|
||||||
import camel
|
import camel
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class _Attribute:
|
class _Attribute:
|
||||||
name = None
|
name = None
|
||||||
_creation_order = 0
|
_creation_order = 0
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self._creation_order = _Attribute._creation_order
|
self._creation_order = _Attribute._creation_order
|
||||||
_Attribute._creation_order += 1
|
_Attribute._creation_order += 1
|
||||||
|
|
||||||
|
def __get__(self, inst, owner):
|
||||||
|
# TODO this is intended for the glom object, not a slice
|
||||||
|
return self.Glommed(self, inst)
|
||||||
|
|
||||||
def __set_name__(self, cls, name):
|
def __set_name__(self, cls, name):
|
||||||
self.name = name
|
self.name = name
|
||||||
|
|
||||||
|
class Glommed:
|
||||||
|
def __init__(self, prop, obj):
|
||||||
|
self.prop = prop
|
||||||
|
self.obj = obj
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "<{} of {!r}.{}: {!r}>".format(
|
||||||
|
type(self).__qualname__,
|
||||||
|
self.obj,
|
||||||
|
self.prop.name,
|
||||||
|
{game: getattr(slice, self.prop.name) for game, slice in self.obj._slices.items()},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
# TODO classtools, key sort by _creation_order
|
# TODO classtools, key sort by _creation_order
|
||||||
|
|
||||||
|
|
||||||
|
@ -55,20 +74,48 @@ class _ForwardDeclaration:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class Slice:
|
||||||
|
is_slice = True
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class LocusMeta(type):
|
class LocusMeta(type):
|
||||||
def __init__(cls, name, bases, attrs):
|
# This is purely a backport of Python 3.6 functionality, and is taken from
|
||||||
for key, attr in attrs.items():
|
# PEP 487. Once the minimum version supported is 3.6, this metaclass can
|
||||||
if hasattr(attr, '__set_name__'):
|
# go away entirely.
|
||||||
attr.__set_name__(cls, key)
|
if not hasattr(object, '__init_subclass__'):
|
||||||
|
def __new__(cls, *args, **kwargs):
|
||||||
super().__init__(name, bases, attrs)
|
if len(args) != 3:
|
||||||
# TODO uhh yeah figure this out. possibly related to attrs
|
return super().__new__(cls, *args)
|
||||||
cls.index = {}
|
name, bases, ns = args
|
||||||
|
init = ns.get('__init_subclass__')
|
||||||
# TODO need default values
|
if isinstance(init, types.FunctionType):
|
||||||
|
ns['__init_subclass__'] = classmethod(init)
|
||||||
|
else:
|
||||||
|
init = None
|
||||||
|
self = super().__new__(cls, name, bases, ns)
|
||||||
|
for k, v in self.__dict__.items():
|
||||||
|
func = getattr(v, '__set_name__', None)
|
||||||
|
if func is not None:
|
||||||
|
func(self, k)
|
||||||
|
sup = super(self, self)
|
||||||
|
if hasattr(sup, '__init_subclass__'):
|
||||||
|
sup.__init_subclass__(**kwargs)
|
||||||
|
return self
|
||||||
|
|
||||||
|
|
||||||
class Locus(metaclass=LocusMeta):
|
class Locus(metaclass=LocusMeta):
|
||||||
|
_attributes = {}
|
||||||
|
|
||||||
|
def __init_subclass__(cls, **kwargs):
|
||||||
|
# super().__init_subclass__(**kwargs)
|
||||||
|
cls._attributes = cls._attributes.copy()
|
||||||
|
for key, value in cls.__dict__.items():
|
||||||
|
if isinstance(value, _Attribute):
|
||||||
|
cls._attributes[key] = value
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
cls = type(self)
|
cls = type(self)
|
||||||
|
|
||||||
|
@ -78,6 +125,25 @@ class Locus(metaclass=LocusMeta):
|
||||||
|
|
||||||
setattr(self, key, value)
|
setattr(self, key, value)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "<{}: {}>".format(
|
||||||
|
type(self).__qualname__,
|
||||||
|
self.identifier,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class VersionedLocus(Locus):
|
||||||
|
def __init_subclass__(cls, **kwargs):
|
||||||
|
super(VersionedLocus, cls).__init_subclass__(**kwargs)
|
||||||
|
|
||||||
|
if not issubclass(cls, Slice):
|
||||||
|
class Sliced(cls, Slice):
|
||||||
|
base_class = cls
|
||||||
|
|
||||||
|
# TODO this is a circular reference; do i care?
|
||||||
|
cls.Sliced = Sliced
|
||||||
|
|
||||||
|
cls._slices = {}
|
||||||
|
|
||||||
# TODO seems to me that each of these, regardless of whether they have any
|
# TODO seems to me that each of these, regardless of whether they have any
|
||||||
# additional data attached or not, are restricted to a fixed extra-game-ular
|
# additional data attached or not, are restricted to a fixed extra-game-ular
|
||||||
|
@ -91,10 +157,9 @@ MoveSet = _ForwardDeclaration()
|
||||||
Pokedex = _ForwardDeclaration()
|
Pokedex = _ForwardDeclaration()
|
||||||
|
|
||||||
|
|
||||||
|
class Pokémon(VersionedLocus):
|
||||||
|
# TODO version, language. but those are kind of meta-fields; do they need
|
||||||
class Pokemon(Locus):
|
# treating specially?
|
||||||
# TODO version, language. but those are kind of meta-fields; do they need treating specially?
|
|
||||||
# TODO in old games, names are unique per game; in later games, they differ
|
# TODO in old games, names are unique per game; in later games, they differ
|
||||||
# per language. what do i do about that?
|
# per language. what do i do about that?
|
||||||
name = _Value(str)
|
name = _Value(str)
|
||||||
|
@ -125,19 +190,34 @@ class Pokemon(Locus):
|
||||||
# TODO should this be written in hex, maybe?
|
# TODO should this be written in hex, maybe?
|
||||||
game_index = _Value(int)
|
game_index = _Value(int)
|
||||||
|
|
||||||
|
Pokemon = Pokémon
|
||||||
|
|
||||||
|
|
||||||
class Repository:
|
class Repository:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
# type -> identifier -> list of objects
|
# type -> identifier -> object
|
||||||
self.objects = defaultdict(lambda: defaultdict(set))
|
self.objects = defaultdict(lambda: {})
|
||||||
# type -> property -> value -> list of objects
|
# type -> property -> value -> list of objects
|
||||||
self.index = defaultdict(lambda: defaultdict(lambda: defaultdict(set)))
|
self.index = defaultdict(lambda: defaultdict(lambda: defaultdict(set)))
|
||||||
|
|
||||||
def add(self, obj):
|
def add(self, obj):
|
||||||
# TODO this should be declared by the type itself, obviously
|
# TODO this should be declared by the type itself, obviously
|
||||||
cls = type(obj)
|
cls = type(obj)
|
||||||
self.objects[cls][obj.identifier].add(obj)
|
# TODO both branches here should check for duplicates
|
||||||
self.index[cls][cls.name][obj.name].add(obj)
|
if isinstance(obj, Slice):
|
||||||
|
cls = cls.base_class
|
||||||
|
if obj.identifier not in self.objects[cls]:
|
||||||
|
glom = cls()
|
||||||
|
glom.identifier = obj.identifier
|
||||||
|
self.objects[cls][obj.identifier] = glom
|
||||||
|
else:
|
||||||
|
glom = self.objects[cls][obj.identifier]
|
||||||
|
# TODO this... feels special-cased, but i guess, it is?
|
||||||
|
glom._slices[obj.game] = obj
|
||||||
|
else:
|
||||||
|
self.objects[cls][obj.identifier] = obj
|
||||||
|
# TODO this is more complex now that names are multi-language
|
||||||
|
#self.index[cls][cls.name][obj.name].add(obj)
|
||||||
|
|
||||||
def fetch(self, cls, identifier):
|
def fetch(self, cls, identifier):
|
||||||
# TODO wrap in a... multi-thing
|
# TODO wrap in a... multi-thing
|
||||||
|
@ -161,7 +241,8 @@ def _dump_locus(locus):
|
||||||
|
|
||||||
@POKEDEX_TYPES.loader('pokemon', version=None)
|
@POKEDEX_TYPES.loader('pokemon', version=None)
|
||||||
def _load_locus(data, version):
|
def _load_locus(data, version):
|
||||||
cls = Pokemon
|
cls = Pokemon.Sliced
|
||||||
|
# TODO wrap with a writer thing?
|
||||||
obj = cls()
|
obj = cls()
|
||||||
for key, value in data.items():
|
for key, value in data.items():
|
||||||
key = key.replace('-', '_')
|
key = key.replace('-', '_')
|
||||||
|
@ -176,26 +257,24 @@ def _temp_main():
|
||||||
|
|
||||||
# just testing for now
|
# just testing for now
|
||||||
cam = camel.Camel([POKEDEX_TYPES])
|
cam = camel.Camel([POKEDEX_TYPES])
|
||||||
PATH = 'pokedex/data/gen1/red/en/pokemon.yaml'
|
PATH = 'pokedex/data/ww-red/pokemon.yaml'
|
||||||
with open(PATH) as f:
|
with open(PATH) as f:
|
||||||
all_pokemon = cam.load(f.read())
|
all_pokemon = cam.load(f.read())
|
||||||
for identifier, pokemon in all_pokemon.items():
|
for identifier, pokemon in all_pokemon.items():
|
||||||
# TODO i don't reeeally like this, but configuring a camel to do it
|
# TODO i don't reeeally like this, but configuring a camel to do it
|
||||||
# is a little unwieldy
|
# is a little unwieldy
|
||||||
pokemon.version = 'red'
|
pokemon.game = 'ww-red'
|
||||||
pokemon.language = 'en'
|
|
||||||
# TODO this in particular seems extremely clumsy, but identifiers ARE fundamentally keys...
|
# TODO this in particular seems extremely clumsy, but identifiers ARE fundamentally keys...
|
||||||
pokemon.identifier = identifier
|
pokemon.identifier = identifier
|
||||||
|
|
||||||
repository.add(pokemon)
|
repository.add(pokemon)
|
||||||
PATH = 'pokedex/data/gen1/red/fr/pokemon.yaml'
|
PATH = 'pokedex/data/ww-blue/pokemon.yaml'
|
||||||
with open(PATH) as f:
|
with open(PATH) as f:
|
||||||
all_pokemon = cam.load(f.read())
|
all_pokemon = cam.load(f.read())
|
||||||
for identifier, pokemon in all_pokemon.items():
|
for identifier, pokemon in all_pokemon.items():
|
||||||
# TODO i don't reeeally like this, but configuring a camel to do it
|
# TODO i don't reeeally like this, but configuring a camel to do it
|
||||||
# is a little unwieldy
|
# is a little unwieldy
|
||||||
pokemon.version = 'red'
|
pokemon.game = 'ww-blue'
|
||||||
pokemon.language = 'fr'
|
|
||||||
# TODO this in particular seems extremely clumsy, but identifiers ARE fundamentally keys...
|
# TODO this in particular seems extremely clumsy, but identifiers ARE fundamentally keys...
|
||||||
pokemon.identifier = identifier
|
pokemon.identifier = identifier
|
||||||
|
|
||||||
|
@ -206,11 +285,12 @@ def _temp_main():
|
||||||
# - but what about the vast majority of properties that are the same in every language and only vary by version?
|
# - but what about the vast majority of properties that are the same in every language and only vary by version?
|
||||||
# - what about later games, where only some properties vary by language? in the extreme case, xy/oras are single games!
|
# - what about later games, where only some properties vary by language? in the extreme case, xy/oras are single games!
|
||||||
|
|
||||||
eevee = repository.fetch(Pokemon, 'eevee')
|
# TODO should this prepend the prefix automatically... eh
|
||||||
|
eevee = repository.fetch(Pokemon, 'pokemon.eevee')
|
||||||
pprint(eevee)
|
pprint(eevee)
|
||||||
return
|
# TODO i feel like this should work: eevee = repository.Pokemon['eevee']
|
||||||
eevee = Pokemon['eevee']
|
|
||||||
print(eevee.name)
|
print(eevee.name)
|
||||||
|
print(eevee.types)
|
||||||
|
|
||||||
|
|
||||||
# TODO alright so we need to figure out the "index" part, and how you
|
# TODO alright so we need to figure out the "index" part, and how you
|
||||||
|
|
Loading…
Reference in a new issue