Overhauled evolution. #42
[zzz-pokedex.git] / pokedex / db / tables.py
1 # encoding: utf8
2
3 from sqlalchemy import Column, ForeignKey, MetaData, Table
4 from sqlalchemy.ext.declarative import declarative_base
5 from sqlalchemy.ext.associationproxy import association_proxy
6 from sqlalchemy.orm import backref, eagerload_all, relation
7 from sqlalchemy.orm.session import Session
8 from sqlalchemy.sql import and_
9 from sqlalchemy.types import *
10
11 from pokedex.db import rst
12
13 metadata = MetaData()
14 TableBase = declarative_base(metadata=metadata)
15
16 class Ability(TableBase):
17 __tablename__ = 'abilities'
18 __singlename__ = 'ability'
19 id = Column(Integer, primary_key=True, nullable=False)
20 name = Column(Unicode(24), nullable=False)
21 generation_id = Column(Integer, ForeignKey('generations.id'), nullable=False)
22 effect = Column(rst.RstTextColumn(5120), nullable=False)
23 short_effect = Column(rst.RstTextColumn(255), nullable=False)
24
25 class AbilityFlavorText(TableBase):
26 __tablename__ = 'ability_flavor_text'
27 ability_id = Column(Integer, ForeignKey('abilities.id'), primary_key=True, nullable=False, autoincrement=False)
28 version_group_id = Column(Integer, ForeignKey('version_groups.id'), primary_key=True, nullable=False, autoincrement=False)
29 flavor_text = Column(Unicode(64), nullable=False)
30
31 class Berry(TableBase):
32 __tablename__ = 'berries'
33 id = Column(Integer, primary_key=True, nullable=False)
34 item_id = Column(Integer, ForeignKey('items.id'), nullable=False)
35 firmness_id = Column(Integer, ForeignKey('berry_firmness.id'), nullable=False)
36 natural_gift_power = Column(Integer, nullable=True)
37 natural_gift_type_id = Column(Integer, ForeignKey('types.id'), nullable=True)
38 size = Column(Integer, nullable=False)
39 max_harvest = Column(Integer, nullable=False)
40 growth_time = Column(Integer, nullable=False)
41 soil_dryness = Column(Integer, nullable=False)
42 smoothness = Column(Integer, nullable=False)
43
44 class BerryFirmness(TableBase):
45 __tablename__ = 'berry_firmness'
46 id = Column(Integer, primary_key=True, nullable=False)
47 name = Column(Unicode(10), nullable=False)
48
49 class BerryFlavor(TableBase):
50 __tablename__ = 'berry_flavors'
51 berry_id = Column(Integer, ForeignKey('berries.id'), primary_key=True, nullable=False, autoincrement=False)
52 contest_type_id = Column(Integer, ForeignKey('contest_types.id'), primary_key=True, nullable=False, autoincrement=False)
53 flavor = Column(Integer, nullable=False)
54
55 class ContestCombo(TableBase):
56 __tablename__ = 'contest_combos'
57 first_move_id = Column(Integer, ForeignKey('moves.id'), primary_key=True, nullable=False, autoincrement=False)
58 second_move_id = Column(Integer, ForeignKey('moves.id'), primary_key=True, nullable=False, autoincrement=False)
59
60 class ContestEffect(TableBase):
61 __tablename__ = 'contest_effects'
62 id = Column(Integer, primary_key=True, nullable=False)
63 appeal = Column(SmallInteger, nullable=False)
64 jam = Column(SmallInteger, nullable=False)
65 flavor_text = Column(Unicode(64), nullable=False)
66 effect = Column(Unicode(255), nullable=False)
67
68 class ContestType(TableBase):
69 __tablename__ = 'contest_types'
70 id = Column(Integer, primary_key=True, nullable=False)
71 name = Column(Unicode(6), nullable=False)
72 flavor = Column(Unicode(6), nullable=False)
73 color = Column(Unicode(6), nullable=False)
74
75 class EggGroup(TableBase):
76 __tablename__ = 'egg_groups'
77 id = Column(Integer, primary_key=True, nullable=False)
78 name = Column(Unicode(16), nullable=False)
79
80 class Encounter(TableBase):
81 """Rows in this table represent encounters with wild Pokémon. Bear with
82 me, here.
83
84 Within a given area in a given game, encounters are differentiated by the
85 "slot" they are in and the state of the game world.
86
87 What the player is doing to get an encounter, such as surfing or walking
88 through tall grass, is called terrain. Each terrain has its own set of
89 encounter slots.
90
91 Within a terrain, slots are defined primarily by rarity. Each slot can
92 also be affected by world conditions; for example, the 20% slot for walking
93 in tall grass is affected by whether a swarm is in effect in that area.
94 "Is there a swarm?" is a condition; "there is a swarm" and "there is not a
95 swarm" are the possible values of this condition.
96
97 A slot (20% walking in grass) and any appropriate world conditions (no
98 swarm) are thus enough to define a specific encounter.
99
100 Well, okay, almost: each slot actually appears twice.
101 """
102
103 __tablename__ = 'encounters'
104 id = Column(Integer, primary_key=True, nullable=False)
105 version_id = Column(Integer, ForeignKey('versions.id'), nullable=False, autoincrement=False)
106 location_area_id = Column(Integer, ForeignKey('location_areas.id'), nullable=False, autoincrement=False)
107 encounter_slot_id = Column(Integer, ForeignKey('encounter_slots.id'), nullable=False, autoincrement=False)
108 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), nullable=False, autoincrement=False)
109 min_level = Column(Integer, nullable=False, autoincrement=False)
110 max_level = Column(Integer, nullable=False, autoincrement=False)
111
112 class EncounterCondition(TableBase):
113 """Rows in this table represent varying conditions in the game world, such
114 as time of day.
115 """
116
117 __tablename__ = 'encounter_conditions'
118 id = Column(Integer, primary_key=True, nullable=False)
119 name = Column(Unicode(64), nullable=False)
120
121 class EncounterConditionValue(TableBase):
122 """Rows in this table represent possible states for a condition; for
123 example, the state of 'swarm' could be 'swarm' or 'no swarm'.
124 """
125
126 __tablename__ = 'encounter_condition_values'
127 id = Column(Integer, primary_key=True, nullable=False)
128 encounter_condition_id = Column(Integer, ForeignKey('encounter_conditions.id'), primary_key=False, nullable=False, autoincrement=False)
129 name = Column(Unicode(64), nullable=False)
130 is_default = Column(Boolean, nullable=False)
131
132 class EncounterConditionValueMap(TableBase):
133 """Maps encounters to the specific conditions under which they occur."""
134
135 __tablename__ = 'encounter_condition_value_map'
136 encounter_id = Column(Integer, ForeignKey('encounters.id'), primary_key=True, nullable=False, autoincrement=False)
137 encounter_condition_value_id = Column(Integer, ForeignKey('encounter_condition_values.id'), primary_key=True, nullable=False, autoincrement=False)
138
139 class EncounterTerrain(TableBase):
140 """Rows in this table represent ways the player can enter a wild encounter,
141 e.g., surfing, fishing, or walking through tall grass.
142 """
143
144 __tablename__ = 'encounter_terrain'
145 id = Column(Integer, primary_key=True, nullable=False)
146 name = Column(Unicode(64), nullable=False)
147
148 class EncounterSlot(TableBase):
149 """Rows in this table represent an abstract "slot" within a terrain,
150 associated with both some set of conditions and a rarity.
151
152 Note that there are two encounters per slot, so the rarities will only add
153 up to 50.
154 """
155
156 __tablename__ = 'encounter_slots'
157 id = Column(Integer, primary_key=True, nullable=False)
158 version_group_id = Column(Integer, ForeignKey('version_groups.id'), nullable=False, autoincrement=False)
159 encounter_terrain_id = Column(Integer, ForeignKey('encounter_terrain.id'), primary_key=False, nullable=False, autoincrement=False)
160 slot = Column(Integer, nullable=True)
161 rarity = Column(Integer, nullable=False)
162
163 class EncounterSlotCondition(TableBase):
164 """Lists all conditions that affect each slot."""
165
166 __tablename__ = 'encounter_slot_conditions'
167 encounter_slot_id = Column(Integer, ForeignKey('encounter_slots.id'), primary_key=True, nullable=False, autoincrement=False)
168 encounter_condition_id = Column(Integer, ForeignKey('encounter_conditions.id'), primary_key=True, nullable=False, autoincrement=False)
169
170 class EvolutionChain(TableBase):
171 __tablename__ = 'evolution_chains'
172 id = Column(Integer, primary_key=True, nullable=False)
173 growth_rate_id = Column(Integer, ForeignKey('growth_rates.id'), nullable=False)
174 steps_to_hatch = Column(Integer, nullable=False)
175 baby_trigger_item = Column(Unicode(12))
176
177 class EvolutionMethod(TableBase):
178 __tablename__ = 'evolution_methods'
179 id = Column(Integer, primary_key=True, nullable=False)
180 name = Column(Unicode(64), nullable=False)
181 description = Column(Unicode(255), nullable=False)
182
183 class EvolutionTrigger(TableBase):
184 __tablename__ = 'evolution_triggers'
185 id = Column(Integer, primary_key=True, nullable=False)
186 identifier = Column(Unicode(16), nullable=False)
187
188 class Experience(TableBase):
189 __tablename__ = 'experience'
190 growth_rate_id = Column(Integer, ForeignKey('growth_rates.id'), primary_key=True, nullable=False)
191 level = Column(Integer, primary_key=True, nullable=False, autoincrement=False)
192 experience = Column(Integer, nullable=False)
193
194 class Generation(TableBase):
195 __tablename__ = 'generations'
196 id = Column(Integer, primary_key=True, nullable=False)
197 main_region_id = Column(Integer, ForeignKey('regions.id'))
198 canonical_pokedex_id = Column(Integer, ForeignKey('pokedexes.id'))
199 name = Column(Unicode(16), nullable=False)
200
201 class GrowthRate(TableBase):
202 """`formula` is written in LaTeX math notation."""
203 __tablename__ = 'growth_rates'
204 id = Column(Integer, primary_key=True, nullable=False)
205 name = Column(Unicode(20), nullable=False)
206 formula = Column(Unicode(500), nullable=False)
207
208 class Item(TableBase):
209 __tablename__ = 'items'
210 __singlename__ = 'item'
211 id = Column(Integer, primary_key=True, nullable=False)
212 name = Column(Unicode(16), nullable=False)
213 category_id = Column(Integer, ForeignKey('item_categories.id'), nullable=False)
214 cost = Column(Integer, nullable=False)
215 fling_power = Column(Integer, nullable=True)
216 fling_effect_id = Column(Integer, ForeignKey('item_fling_effects.id'), nullable=True)
217 effect = Column(rst.RstTextColumn(5120), nullable=False)
218
219 @property
220 def appears_underground(self):
221 return any(flag.identifier == u'underground' for flag in self.flags)
222
223 class ItemCategory(TableBase):
224 __tablename__ = 'item_categories'
225 id = Column(Integer, primary_key=True, nullable=False)
226 pocket_id = Column(Integer, ForeignKey('item_pockets.id'), nullable=False)
227 name = Column(Unicode(16), nullable=False)
228
229 class ItemFlag(TableBase):
230 __tablename__ = 'item_flags'
231 id = Column(Integer, primary_key=True, nullable=False)
232 identifier = Column(Unicode(24), nullable=False)
233 name = Column(Unicode(64), nullable=False)
234
235 class ItemFlagMap(TableBase):
236 __tablename__ = 'item_flag_map'
237 item_id = Column(Integer, ForeignKey('items.id'), primary_key=True, autoincrement=False, nullable=False)
238 item_flag_id = Column(Integer, ForeignKey('item_flags.id'), primary_key=True, autoincrement=False, nullable=False)
239
240 class ItemFlavorText(TableBase):
241 __tablename__ = 'item_flavor_text'
242 item_id = Column(Integer, ForeignKey('items.id'), primary_key=True, autoincrement=False, nullable=False)
243 version_group_id = Column(Integer, ForeignKey('version_groups.id'), primary_key=True, autoincrement=False, nullable=False)
244 flavor_text = Column(Unicode(255), nullable=False)
245
246 class ItemFlingEffect(TableBase):
247 __tablename__ = 'item_fling_effects'
248 id = Column(Integer, primary_key=True, nullable=False)
249 effect = Column(Unicode(255), nullable=False)
250
251 class ItemInternalID(TableBase):
252 __tablename__ = 'item_internal_ids'
253 item_id = Column(Integer, ForeignKey('items.id'), primary_key=True, autoincrement=False, nullable=False)
254 generation_id = Column(Integer, ForeignKey('generations.id'), primary_key=True, autoincrement=False, nullable=False)
255 internal_id = Column(Integer, nullable=False)
256
257 class ItemPocket(TableBase):
258 __tablename__ = 'item_pockets'
259 id = Column(Integer, primary_key=True, nullable=False)
260 identifier = Column(Unicode(16), nullable=False)
261 name = Column(Unicode(16), nullable=False)
262
263 class Language(TableBase):
264 __tablename__ = 'languages'
265 id = Column(Integer, primary_key=True, nullable=False)
266 iso639 = Column(Unicode(2), nullable=False)
267 iso3166 = Column(Unicode(2), nullable=False)
268 name = Column(Unicode(16), nullable=False)
269
270 class Location(TableBase):
271 __tablename__ = 'locations'
272 __singlename__ = 'location'
273 id = Column(Integer, primary_key=True, nullable=False)
274 region_id = Column(Integer, ForeignKey('regions.id'))
275 name = Column(Unicode(64), nullable=False)
276
277 class LocationArea(TableBase):
278 __tablename__ = 'location_areas'
279 id = Column(Integer, primary_key=True, nullable=False)
280 location_id = Column(Integer, ForeignKey('locations.id'), nullable=False)
281 internal_id = Column(Integer, nullable=False)
282 name = Column(Unicode(64), nullable=True)
283
284 class LocationAreaEncounterRate(TableBase):
285 __tablename__ = 'location_area_encounter_rates'
286 location_area_id = Column(Integer, ForeignKey('location_areas.id'), primary_key=True, nullable=False, autoincrement=False)
287 encounter_terrain_id = Column(Integer, ForeignKey('encounter_terrain.id'), primary_key=True, nullable=False, autoincrement=False)
288 version_id = Column(Integer, ForeignKey('versions.id'), primary_key=True, autoincrement=False)
289 rate = Column(Integer, nullable=True)
290
291 class Machine(TableBase):
292 __tablename__ = 'machines'
293 machine_number = Column(Integer, primary_key=True, nullable=False, autoincrement=False)
294 version_group_id = Column(Integer, ForeignKey('version_groups.id'), primary_key=True, nullable=False, autoincrement=False)
295 item_id = Column(Integer, ForeignKey('items.id'), nullable=False)
296 move_id = Column(Integer, ForeignKey('moves.id'), nullable=False)
297
298 @property
299 def is_hm(self):
300 return self.machine_number >= 100
301
302 class MoveBattleStyle(TableBase):
303 __tablename__ = 'move_battle_styles'
304 id = Column(Integer, primary_key=True, nullable=False)
305 name = Column(Unicode(8), nullable=False)
306
307 class MoveEffectCategory(TableBase):
308 __tablename__ = 'move_effect_categories'
309 id = Column(Integer, primary_key=True, nullable=False)
310 name = Column(Unicode(64), nullable=False)
311 can_affect_user = Column(Boolean, nullable=False)
312
313 class MoveEffectCategoryMap(TableBase):
314 __tablename__ = 'move_effect_category_map'
315 move_effect_id = Column(Integer, ForeignKey('move_effects.id'), primary_key=True, nullable=False)
316 move_effect_category_id = Column(Integer, ForeignKey('move_effect_categories.id'), primary_key=True, nullable=False)
317 affects_user = Column(Boolean, primary_key=True, nullable=False)
318
319 class MoveDamageClass(TableBase):
320 __tablename__ = 'move_damage_classes'
321 id = Column(Integer, primary_key=True, nullable=False)
322 name = Column(Unicode(8), nullable=False)
323 description = Column(Unicode(64), nullable=False)
324
325 class MoveEffect(TableBase):
326 __tablename__ = 'move_effects'
327 id = Column(Integer, primary_key=True, nullable=False)
328 priority = Column(SmallInteger, nullable=False)
329 short_effect = Column(Unicode(256), nullable=False)
330 effect = Column(Unicode(5120), nullable=False)
331
332 class MoveFlag(TableBase):
333 __tablename__ = 'move_flags'
334 move_id = Column(Integer, ForeignKey('moves.id'), primary_key=True, nullable=False, autoincrement=False)
335 move_flag_type_id = Column(Integer, ForeignKey('move_flag_types.id'), primary_key=True, nullable=False, autoincrement=False)
336
337 class MoveFlagType(TableBase):
338 __tablename__ = 'move_flag_types'
339 id = Column(Integer, primary_key=True, nullable=False)
340 name = Column(Unicode(32), nullable=False)
341 description = Column(rst.RstTextColumn(128), nullable=False)
342
343 class MoveFlavorText(TableBase):
344 __tablename__ = 'move_flavor_text'
345 move_id = Column(Integer, ForeignKey('moves.id'), primary_key=True, nullable=False, autoincrement=False)
346 version_group_id = Column(Integer, ForeignKey('version_groups.id'), primary_key=True, nullable=False, autoincrement=False)
347 flavor_text = Column(Unicode(255), nullable=False)
348
349 class MoveName(TableBase):
350 __tablename__ = 'move_names'
351 move_id = Column(Integer, ForeignKey('moves.id'), primary_key=True, nullable=False, autoincrement=False)
352 language_id = Column(Integer, ForeignKey('languages.id'), primary_key=True, nullable=False, autoincrement=False)
353 name = Column(Unicode(16), nullable=False)
354
355 class MoveTarget(TableBase):
356 __tablename__ = 'move_targets'
357 id = Column(Integer, primary_key=True, nullable=False)
358 name = Column(Unicode(32), nullable=False)
359 description = Column(Unicode(128), nullable=False)
360
361 class Move(TableBase):
362 __tablename__ = 'moves'
363 __singlename__ = 'move'
364 id = Column(Integer, primary_key=True, nullable=False)
365 name = Column(Unicode(12), nullable=False)
366 generation_id = Column(Integer, ForeignKey('generations.id'), nullable=False)
367 type_id = Column(Integer, ForeignKey('types.id'), nullable=False)
368 power = Column(SmallInteger)
369 pp = Column(SmallInteger, nullable=False)
370 accuracy = Column(SmallInteger)
371 target_id = Column(Integer, ForeignKey('move_targets.id'), nullable=False)
372 damage_class_id = Column(Integer, ForeignKey('move_damage_classes.id'), nullable=False)
373 effect_id = Column(Integer, ForeignKey('move_effects.id'), nullable=False)
374 effect_chance = Column(Integer)
375 contest_type_id = Column(Integer, ForeignKey('contest_types.id'), nullable=True)
376 contest_effect_id = Column(Integer, ForeignKey('contest_effects.id'), nullable=True)
377 super_contest_effect_id = Column(Integer, ForeignKey('super_contest_effects.id'), nullable=False)
378
379 class Nature(TableBase):
380 __tablename__ = 'natures'
381 __singlename__ = 'nature'
382 id = Column(Integer, primary_key=True, nullable=False)
383 name = Column(Unicode(8), nullable=False)
384 decreased_stat_id = Column(Integer, ForeignKey('stats.id'), nullable=False)
385 increased_stat_id = Column(Integer, ForeignKey('stats.id'), nullable=False)
386 hates_flavor_id = Column(Integer, ForeignKey('contest_types.id'), nullable=False)
387 likes_flavor_id = Column(Integer, ForeignKey('contest_types.id'), nullable=False)
388
389 class NatureBattleStylePreference(TableBase):
390 __tablename__ = 'nature_battle_style_preferences'
391 nature_id = Column(Integer, ForeignKey('natures.id'), primary_key=True, nullable=False)
392 move_battle_style_id = Column(Integer, ForeignKey('move_battle_styles.id'), primary_key=True, nullable=False)
393 low_hp_preference = Column(Integer, nullable=False)
394 high_hp_preference = Column(Integer, nullable=False)
395
396 class NaturePokeathlonStat(TableBase):
397 __tablename__ = 'nature_pokeathlon_stats'
398 nature_id = Column(Integer, ForeignKey('natures.id'), primary_key=True, nullable=False)
399 pokeathlon_stat_id = Column(Integer, ForeignKey('pokeathlon_stats.id'), primary_key=True, nullable=False)
400 max_change = Column(Integer, nullable=False)
401
402 class PokeathlonStat(TableBase):
403 __tablename__ = 'pokeathlon_stats'
404 id = Column(Integer, primary_key=True, nullable=False)
405 name = Column(Unicode(8), nullable=False)
406
407 class Pokedex(TableBase):
408 __tablename__ = 'pokedexes'
409 id = Column(Integer, primary_key=True, nullable=False)
410 region_id = Column(Integer, ForeignKey('regions.id'), nullable=True)
411 name = Column(Unicode(16), nullable=False)
412 description = Column(Unicode(512))
413
414 class PokedexVersionGroup(TableBase):
415 __tablename__ = 'pokedex_version_groups'
416 pokedex_id = Column(Integer, ForeignKey('pokedexes.id'), primary_key=True, nullable=False, autoincrement=False)
417 version_group_id = Column(Integer, ForeignKey('version_groups.id'), primary_key=True, nullable=False, autoincrement=False)
418
419 class Pokemon(TableBase):
420 """The core to this whole mess.
421
422 Note that I use both 'forme' and 'form' in both code and the database. I
423 only use 'forme' when specifically referring to Pokémon that have multiple
424 distinct species as forms—i.e., different stats or movesets. 'Form' is a
425 more general term referring to any variation within a species, including
426 purely cosmetic forms like Unown.
427 """
428 __tablename__ = 'pokemon'
429 __singlename__ = 'pokemon'
430 id = Column(Integer, primary_key=True, nullable=False)
431 name = Column(Unicode(20), nullable=False)
432 forme_name = Column(Unicode(16))
433 forme_base_pokemon_id = Column(Integer, ForeignKey('pokemon.id'))
434 generation_id = Column(Integer, ForeignKey('generations.id'))
435 evolution_chain_id = Column(Integer, ForeignKey('evolution_chains.id'))
436 height = Column(Integer, nullable=False)
437 weight = Column(Integer, nullable=False)
438 species = Column(Unicode(16), nullable=False)
439 color_id = Column(Integer, ForeignKey('pokemon_colors.id'), nullable=False)
440 pokemon_shape_id = Column(Integer, ForeignKey('pokemon_shapes.id'), nullable=False)
441 habitat_id = Column(Integer, ForeignKey('pokemon_habitats.id'), nullable=True)
442 gender_rate = Column(Integer, nullable=False)
443 capture_rate = Column(Integer, nullable=False)
444 base_experience = Column(Integer, nullable=False)
445 base_happiness = Column(Integer, nullable=False)
446 is_baby = Column(Boolean, nullable=False)
447 has_gen4_fem_sprite = Column(Boolean, nullable=False)
448 has_gen4_fem_back_sprite = Column(Boolean, nullable=False)
449
450 ### Stuff to handle alternate Pokémon forms
451
452 @property
453 def national_id(self):
454 """Returns the National Pokédex number for this Pokémon. Use this
455 instead of the id directly; alternate formes may make the id incorrect.
456 """
457
458 if self.forme_base_pokemon_id:
459 return self.forme_base_pokemon_id
460 return self.id
461
462 @property
463 def full_name(self):
464 """Returns the name of this Pokémon, including its Forme, if any."""
465
466 if self.forme_name:
467 return "%s %s" % (self.forme_name.title(), self.name)
468 return self.name
469
470 @property
471 def normal_form(self):
472 """Returns the normal form for this Pokémon; i.e., this will return
473 regular Deoxys when called on any Deoxys form.
474 """
475
476 if self.forme_base_pokemon:
477 return self.forme_base_pokemon
478
479 return self
480
481 ### Not forms!
482
483 def stat(self, stat_name):
484 """Returns a PokemonStat record for the given stat name (or Stat row
485 object). Uses the normal has-many machinery, so all the stats are
486 effectively cached.
487 """
488 if isinstance(stat_name, Stat):
489 stat_name = stat_name.name
490
491 for pokemon_stat in self.stats:
492 if pokemon_stat.stat.name == stat_name:
493 return pokemon_stat
494
495 return None
496
497 class PokemonAbility(TableBase):
498 __tablename__ = 'pokemon_abilities'
499 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False)
500 ability_id = Column(Integer, ForeignKey('abilities.id'), nullable=False)
501 slot = Column(Integer, primary_key=True, nullable=False, autoincrement=False)
502
503 class PokemonColor(TableBase):
504 __tablename__ = 'pokemon_colors'
505 id = Column(Integer, primary_key=True, nullable=False, autoincrement=False)
506 name = Column(Unicode(6), nullable=False)
507
508 class PokemonDexNumber(TableBase):
509 __tablename__ = 'pokemon_dex_numbers'
510 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False)
511 pokedex_id = Column(Integer, ForeignKey('pokedexes.id'), primary_key=True, nullable=False, autoincrement=False)
512 pokedex_number = Column(Integer, nullable=False)
513
514 class PokemonEggGroup(TableBase):
515 __tablename__ = 'pokemon_egg_groups'
516 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False)
517 egg_group_id = Column(Integer, ForeignKey('egg_groups.id'), primary_key=True, nullable=False, autoincrement=False)
518
519 class PokemonEvolution(TableBase):
520 __tablename__ = 'pokemon_evolution'
521 from_pokemon_id = Column(Integer, ForeignKey('pokemon.id'), nullable=False)
522 to_pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False)
523 evolution_trigger_id = Column(Integer, ForeignKey('evolution_triggers.id'), nullable=False)
524 trigger_item_id = Column(Integer, ForeignKey('items.id'), nullable=True)
525 minimum_level = Column(Integer, nullable=True)
526 gender = Column(Enum('male', 'female', name='pokemon_evolution_gender'), nullable=True)
527 location_id = Column(Integer, ForeignKey('locations.id'), nullable=True)
528 held_item_id = Column(Integer, ForeignKey('items.id'), nullable=True)
529 time_of_day = Column(Enum('morning', 'day', 'night', name='pokemon_evolution_time_of_day'), nullable=True)
530 known_move_id = Column(Integer, ForeignKey('moves.id'), nullable=True)
531 minimum_happiness = Column(Integer, nullable=True)
532 minimum_beauty = Column(Integer, nullable=True)
533 relative_physical_stats = Column(Integer, nullable=True)
534 party_pokemon_id = Column(Integer, ForeignKey('pokemon.id'), nullable=True)
535
536 class PokemonFlavorText(TableBase):
537 __tablename__ = 'pokemon_flavor_text'
538 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False)
539 version_id = Column(Integer, ForeignKey('versions.id'), primary_key=True, nullable=False, autoincrement=False)
540 flavor_text = Column(Unicode(255), nullable=False)
541
542 class PokemonFormGroup(TableBase):
543 __tablename__ = 'pokemon_form_groups'
544 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False)
545 is_battle_only = Column(Boolean, nullable=False)
546 description = Column(Unicode(512), nullable=False)
547
548 class PokemonFormSprite(TableBase):
549 __tablename__ = 'pokemon_form_sprites'
550 id = Column(Integer, primary_key=True, nullable=False)
551 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False)
552 introduced_in_version_group_id = Column(Integer, ForeignKey('version_groups.id'), primary_key=True, nullable=False, autoincrement=False)
553 name = Column(Unicode(16), nullable=True)
554 is_default = Column(Boolean, nullable=True)
555
556 class PokemonHabitat(TableBase):
557 __tablename__ = 'pokemon_habitats'
558 id = Column(Integer, primary_key=True, nullable=False, autoincrement=False)
559 name = Column(Unicode(16), nullable=False)
560
561 class PokemonItem(TableBase):
562 __tablename__ = 'pokemon_items'
563 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False)
564 version_id = Column(Integer, ForeignKey('versions.id'), primary_key=True, nullable=False, autoincrement=False)
565 item_id = Column(Integer, ForeignKey('items.id'), primary_key=True, nullable=False, autoincrement=False)
566 rarity = Column(Integer, nullable=False)
567
568 class PokemonMove(TableBase):
569 __tablename__ = 'pokemon_moves'
570 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False)
571 version_group_id = Column(Integer, ForeignKey('version_groups.id'), primary_key=True, nullable=False, autoincrement=False)
572 move_id = Column(Integer, ForeignKey('moves.id'), primary_key=True, nullable=False, autoincrement=False, index=True)
573 pokemon_move_method_id = Column(Integer, ForeignKey('pokemon_move_methods.id'), primary_key=True, nullable=False, autoincrement=False)
574 level = Column(Integer, primary_key=True, nullable=True, autoincrement=False)
575 order = Column(Integer, nullable=True)
576
577 class PokemonMoveMethod(TableBase):
578 __tablename__ = 'pokemon_move_methods'
579 id = Column(Integer, primary_key=True, nullable=False, autoincrement=False)
580 name = Column(Unicode(64), nullable=False)
581 description = Column(Unicode(255), nullable=False)
582
583 class PokemonName(TableBase):
584 __tablename__ = 'pokemon_names'
585 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False)
586 language_id = Column(Integer, ForeignKey('languages.id'), primary_key=True, nullable=False, autoincrement=False)
587 name = Column(Unicode(16), nullable=False)
588
589 class PokemonShape(TableBase):
590 __tablename__ = 'pokemon_shapes'
591 id = Column(Integer, primary_key=True, nullable=False)
592 name = Column(Unicode(24), nullable=False)
593 awesome_name = Column(Unicode(16), nullable=False)
594
595 class PokemonStat(TableBase):
596 __tablename__ = 'pokemon_stats'
597 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False)
598 stat_id = Column(Integer, ForeignKey('stats.id'), primary_key=True, nullable=False, autoincrement=False)
599 base_stat = Column(Integer, nullable=False)
600 effort = Column(Integer, nullable=False)
601
602 class PokemonType(TableBase):
603 __tablename__ = 'pokemon_types'
604 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False)
605 type_id = Column(Integer, ForeignKey('types.id'), nullable=False)
606 slot = Column(Integer, primary_key=True, nullable=False, autoincrement=False)
607
608 class Region(TableBase):
609 """Major areas of the world: Kanto, Johto, etc."""
610 __tablename__ = 'regions'
611 id = Column(Integer, primary_key=True, nullable=False)
612 name = Column(Unicode(16), nullable=False)
613
614 class Stat(TableBase):
615 __tablename__ = 'stats'
616 id = Column(Integer, primary_key=True, nullable=False)
617 name = Column(Unicode(16), nullable=False)
618
619 class SuperContestCombo(TableBase):
620 __tablename__ = 'super_contest_combos'
621 first_move_id = Column(Integer, ForeignKey('moves.id'), primary_key=True, nullable=False, autoincrement=False)
622 second_move_id = Column(Integer, ForeignKey('moves.id'), primary_key=True, nullable=False, autoincrement=False)
623
624 class SuperContestEffect(TableBase):
625 __tablename__ = 'super_contest_effects'
626 id = Column(Integer, primary_key=True, nullable=False)
627 appeal = Column(SmallInteger, nullable=False)
628 flavor_text = Column(Unicode(64), nullable=False)
629
630 class TypeEfficacy(TableBase):
631 __tablename__ = 'type_efficacy'
632 damage_type_id = Column(Integer, ForeignKey('types.id'), primary_key=True, nullable=False, autoincrement=False)
633 target_type_id = Column(Integer, ForeignKey('types.id'), primary_key=True, nullable=False, autoincrement=False)
634 damage_factor = Column(Integer, nullable=False)
635
636 class Type(TableBase):
637 __tablename__ = 'types'
638 __singlename__ = 'type'
639 id = Column(Integer, primary_key=True, nullable=False)
640 name = Column(Unicode(8), nullable=False)
641 abbreviation = Column(Unicode(3), nullable=False)
642 generation_id = Column(Integer, ForeignKey('generations.id'), nullable=False)
643 damage_class_id = Column(Integer, ForeignKey('move_damage_classes.id'), nullable=False) ## ??? is none; everything else is physical or special
644
645 class VersionGroup(TableBase):
646 __tablename__ = 'version_groups'
647 id = Column(Integer, primary_key=True, nullable=False)
648 generation_id = Column(Integer, ForeignKey('generations.id'), nullable=False)
649
650 class VersionGroupRegion(TableBase):
651 __tablename__ = 'version_group_regions'
652 version_group_id = Column(Integer, ForeignKey('version_groups.id'), primary_key=True, nullable=False)
653 region_id = Column(Integer, ForeignKey('regions.id'), primary_key=True, nullable=False)
654
655 class Version(TableBase):
656 __tablename__ = 'versions'
657 id = Column(Integer, primary_key=True, nullable=False)
658 version_group_id = Column(Integer, ForeignKey('version_groups.id'), nullable=False)
659 name = Column(Unicode(32), nullable=False)
660
661
662 ### Relations down here, to avoid ordering problems
663 Ability.flavor_text = relation(AbilityFlavorText, order_by=AbilityFlavorText.version_group_id, backref='abilities')
664 Ability.generation = relation(Generation, backref='abilities')
665
666 AbilityFlavorText.version_group = relation(VersionGroup)
667
668 Berry.berry_firmness = relation(BerryFirmness, backref='berries')
669 Berry.firmness = association_proxy('berry_firmness', 'name')
670 Berry.flavors = relation(BerryFlavor, order_by=BerryFlavor.contest_type_id, backref='berry')
671 Berry.natural_gift_type = relation(Type)
672
673 BerryFlavor.contest_type = relation(ContestType)
674
675 ContestCombo.first = relation(Move, primaryjoin=ContestCombo.first_move_id==Move.id,
676 backref='contest_combo_first')
677 ContestCombo.second = relation(Move, primaryjoin=ContestCombo.second_move_id==Move.id,
678 backref='contest_combo_second')
679
680 Encounter.location_area = relation(LocationArea, backref='encounters')
681 Encounter.pokemon = relation(Pokemon, backref='encounters')
682 Encounter.version = relation(Version, backref='encounters')
683 Encounter.slot = relation(EncounterSlot, backref='encounters')
684
685 EncounterConditionValue.condition = relation(EncounterCondition, backref='values')
686
687 Encounter.condition_value_map = relation(EncounterConditionValueMap, backref='encounter')
688 Encounter.condition_values = association_proxy('condition_value_map', 'condition_value')
689 EncounterConditionValueMap.condition_value = relation(EncounterConditionValue,
690 backref='encounter_map')
691
692 EncounterSlot.terrain = relation(EncounterTerrain, backref='slots')
693
694 EncounterSlot.condition_map = relation(EncounterSlotCondition, backref='slot')
695 EncounterSlot.conditions = association_proxy('condition_map', 'condition')
696 EncounterSlotCondition.condition = relation(EncounterCondition,
697 backref='slot_map')
698
699 EvolutionChain.growth_rate = relation(GrowthRate, backref='evolution_chains')
700
701 Experience.growth_rate = relation(GrowthRate, backref='experience_table')
702
703 Generation.canonical_pokedex = relation(Pokedex, backref='canonical_for_generation')
704 Generation.versions = relation(Version, secondary=VersionGroup.__table__)
705 Generation.main_region = relation(Region)
706
707 GrowthRate.max_experience_obj = relation(Experience, primaryjoin=and_(Experience.growth_rate_id == GrowthRate.id, Experience.level == 100), uselist=False)
708 GrowthRate.max_experience = association_proxy('max_experience_obj', 'experience')
709
710 Item.berry = relation(Berry, uselist=False, backref='item')
711 Item.flags = relation(ItemFlag, secondary=ItemFlagMap.__table__)
712 Item.flavor_text = relation(ItemFlavorText, order_by=ItemFlavorText.version_group_id.asc(), backref='item')
713 Item.fling_effect = relation(ItemFlingEffect, backref='items')
714 Item.machines = relation(Machine, order_by=Machine.version_group_id.asc())
715 Item.category = relation(ItemCategory)
716 Item.pocket = association_proxy('category', 'pocket')
717
718 ItemCategory.items = relation(Item, order_by=Item.name)
719 ItemCategory.pocket = relation(ItemPocket)
720
721 ItemFlavorText.version_group = relation(VersionGroup)
722
723 ItemPocket.categories = relation(ItemCategory, order_by=ItemCategory.name)
724
725 Location.region = relation(Region, backref='locations')
726
727 LocationArea.location = relation(Location, backref='areas')
728
729 Machine.item = relation(Item)
730 Machine.version_group = relation(VersionGroup)
731
732 Move.contest_effect = relation(ContestEffect, backref='moves')
733 Move.contest_combo_next = association_proxy('contest_combo_first', 'second')
734 Move.contest_combo_prev = association_proxy('contest_combo_second', 'first')
735 Move.contest_type = relation(ContestType, backref='moves')
736 Move.damage_class = relation(MoveDamageClass, backref='moves')
737 Move.flags = association_proxy('move_flags', 'flag')
738 Move.flavor_text = relation(MoveFlavorText, order_by=MoveFlavorText.version_group_id, backref='move')
739 Move.foreign_names = relation(MoveName, backref='pokemon')
740 Move.generation = relation(Generation, backref='moves')
741 Move.machines = relation(Machine, backref='move')
742 Move.move_effect = relation(MoveEffect, backref='moves')
743 Move.move_flags = relation(MoveFlag, backref='move')
744 Move.super_contest_effect = relation(SuperContestEffect, backref='moves')
745 Move.super_contest_combo_next = association_proxy('super_contest_combo_first', 'second')
746 Move.super_contest_combo_prev = association_proxy('super_contest_combo_second', 'first')
747 Move.target = relation(MoveTarget, backref='moves')
748 Move.type = relation(Type, backref='moves')
749
750 Move.effect = rst.MoveEffectProperty('effect')
751 Move.priority = association_proxy('move_effect', 'priority')
752 Move.short_effect = rst.MoveEffectProperty('short_effect')
753
754 MoveEffect.category_map = relation(MoveEffectCategoryMap)
755 MoveEffect.categories = association_proxy('category_map', 'category')
756 MoveEffectCategoryMap.category = relation(MoveEffectCategory)
757
758 MoveFlag.flag = relation(MoveFlagType)
759
760 MoveFlavorText.version_group = relation(VersionGroup)
761
762 MoveName.language = relation(Language)
763
764 Nature.decreased_stat = relation(Stat, primaryjoin=Nature.decreased_stat_id==Stat.id,
765 backref='decreasing_natures')
766 Nature.increased_stat = relation(Stat, primaryjoin=Nature.increased_stat_id==Stat.id,
767 backref='increasing_natures')
768 Nature.hates_flavor = relation(ContestType, primaryjoin=Nature.hates_flavor_id==ContestType.id,
769 backref='hating_natures')
770 Nature.likes_flavor = relation(ContestType, primaryjoin=Nature.likes_flavor_id==ContestType.id,
771 backref='liking_natures')
772 Nature.battle_style_preferences = relation(NatureBattleStylePreference,
773 order_by=NatureBattleStylePreference.move_battle_style_id,
774 backref='nature')
775 Nature.pokeathlon_effects = relation(NaturePokeathlonStat, order_by=NaturePokeathlonStat.pokeathlon_stat_id)
776
777 NatureBattleStylePreference.battle_style = relation(MoveBattleStyle, backref='nature_preferences')
778
779 NaturePokeathlonStat.pokeathlon_stat = relation(PokeathlonStat, backref='nature_effects')
780
781 Pokedex.region = relation(Region, backref='pokedexes')
782 Pokedex.version_groups = relation(VersionGroup, secondary=PokedexVersionGroup.__table__, backref='pokedexes')
783
784 Pokemon.abilities = relation(Ability, secondary=PokemonAbility.__table__,
785 order_by=PokemonAbility.slot,
786 backref='pokemon')
787 Pokemon.formes = relation(Pokemon, primaryjoin=Pokemon.id==Pokemon.forme_base_pokemon_id,
788 backref=backref('forme_base_pokemon',
789 remote_side=[Pokemon.id]))
790 Pokemon.pokemon_color = relation(PokemonColor, backref='pokemon')
791 Pokemon.color = association_proxy('pokemon_color', 'name')
792 Pokemon.dex_numbers = relation(PokemonDexNumber, backref='pokemon')
793 Pokemon.default_form_sprite = relation(PokemonFormSprite,
794 primaryjoin=and_(
795 Pokemon.id==PokemonFormSprite.pokemon_id,
796 PokemonFormSprite.is_default==True,
797 ),
798 uselist=False)
799 Pokemon.egg_groups = relation(EggGroup, secondary=PokemonEggGroup.__table__,
800 order_by=PokemonEggGroup.egg_group_id,
801 backref='pokemon')
802 Pokemon.evolution_chain = relation(EvolutionChain, backref='pokemon')
803 Pokemon.evolution_method = relation(EvolutionMethod)
804 Pokemon.evolution_children = relation(Pokemon,
805 secondary=PokemonEvolution.__table__,
806 primaryjoin=Pokemon.id==PokemonEvolution.from_pokemon_id,
807 secondaryjoin=PokemonEvolution.to_pokemon_id==Pokemon.id,
808 backref=backref('evolution_parent',
809 remote_side=[Pokemon.id],
810 uselist=False,
811 ),
812 )
813 Pokemon.flavor_text = relation(PokemonFlavorText, order_by=PokemonFlavorText.version_id.asc(), backref='pokemon')
814 Pokemon.foreign_names = relation(PokemonName, backref='pokemon')
815 Pokemon.pokemon_habitat = relation(PokemonHabitat, backref='pokemon')
816 Pokemon.habitat = association_proxy('pokemon_habitat', 'name')
817 Pokemon.items = relation(PokemonItem, backref='pokemon')
818 Pokemon.generation = relation(Generation, backref='pokemon')
819 Pokemon.shape = relation(PokemonShape, backref='pokemon')
820 Pokemon.stats = relation(PokemonStat, backref='pokemon')
821 Pokemon.types = relation(Type, secondary=PokemonType.__table__, order_by=PokemonType.slot.asc())
822
823 PokemonDexNumber.pokedex = relation(Pokedex)
824
825 PokemonEvolution.from_pokemon = relation(Pokemon,
826 primaryjoin=PokemonEvolution.from_pokemon_id==Pokemon.id,
827 backref='child_evolutions',
828 )
829 PokemonEvolution.to_pokemon = relation(Pokemon,
830 primaryjoin=PokemonEvolution.to_pokemon_id==Pokemon.id,
831 backref=backref('parent_evolution', uselist=False),
832 )
833 PokemonEvolution.child_evolutions = relation(PokemonEvolution,
834 primaryjoin=PokemonEvolution.from_pokemon_id==PokemonEvolution.to_pokemon_id,
835 foreign_keys=[PokemonEvolution.to_pokemon_id],
836 backref=backref('parent_evolution',
837 remote_side=[PokemonEvolution.from_pokemon_id],
838 uselist=False,
839 ),
840 )
841 PokemonEvolution.trigger = relation(EvolutionTrigger, backref='evolutions')
842 PokemonEvolution.trigger_item = relation(Item,
843 primaryjoin=PokemonEvolution.trigger_item_id==Item.id,
844 backref='triggered_evolutions',
845 )
846 PokemonEvolution.held_item = relation(Item,
847 primaryjoin=PokemonEvolution.held_item_id==Item.id,
848 backref='required_for_evolutions',
849 )
850 PokemonEvolution.location = relation(Location, backref='triggered_evolutions')
851 PokemonEvolution.known_move = relation(Move, backref='triggered_evolutions')
852 PokemonEvolution.party_pokemon = relation(Pokemon,
853 primaryjoin=PokemonEvolution.party_pokemon_id==Pokemon.id,
854 backref='triggered_evolutions',
855 )
856
857 PokemonFlavorText.version = relation(Version)
858
859 PokemonItem.item = relation(Item, backref='pokemon')
860 PokemonItem.version = relation(Version)
861
862 PokemonFormGroup.pokemon = relation(Pokemon, backref=backref('form_group',
863 uselist=False))
864 PokemonFormSprite.pokemon = relation(Pokemon, backref='form_sprites')
865 PokemonFormSprite.introduced_in = relation(VersionGroup)
866
867 PokemonMove.pokemon = relation(Pokemon, backref='pokemon_moves')
868 PokemonMove.version_group = relation(VersionGroup)
869 PokemonMove.machine = relation(Machine, backref='pokemon_moves',
870 primaryjoin=and_(Machine.version_group_id==PokemonMove.version_group_id,
871 Machine.move_id==PokemonMove.move_id),
872 foreign_keys=[Machine.version_group_id, Machine.move_id],
873 uselist=False)
874 PokemonMove.move = relation(Move, backref='pokemon_moves')
875 PokemonMove.method = relation(PokemonMoveMethod)
876
877 PokemonName.language = relation(Language)
878
879 PokemonStat.stat = relation(Stat)
880
881 # This is technically a has-many; Generation.main_region_id -> Region.id
882 Region.generation = relation(Generation, uselist=False)
883 Region.version_group_regions = relation(VersionGroupRegion, backref='region',
884 order_by='VersionGroupRegion.version_group_id')
885 Region.version_groups = association_proxy('version_group_regions', 'version_group')
886
887 SuperContestCombo.first = relation(Move, primaryjoin=SuperContestCombo.first_move_id==Move.id,
888 backref='super_contest_combo_first')
889 SuperContestCombo.second = relation(Move, primaryjoin=SuperContestCombo.second_move_id==Move.id,
890 backref='super_contest_combo_second')
891
892 Type.damage_efficacies = relation(TypeEfficacy,
893 primaryjoin=Type.id
894 ==TypeEfficacy.damage_type_id,
895 backref='damage_type')
896 Type.target_efficacies = relation(TypeEfficacy,
897 primaryjoin=Type.id
898 ==TypeEfficacy.target_type_id,
899 backref='target_type')
900
901 Type.generation = relation(Generation, backref='types')
902 Type.damage_class = relation(MoveDamageClass, backref='types')
903
904 Version.version_group = relation(VersionGroup, backref='versions')
905 Version.generation = association_proxy('version_group', 'generation')
906
907 VersionGroup.generation = relation(Generation, backref='version_groups')
908 VersionGroup.version_group_regions = relation(VersionGroupRegion, backref='version_group')
909 VersionGroup.regions = association_proxy('version_group_regions', 'region')