"Characteristic" text, here called stat hints.
[zzz-pokedex.git] / pokedex / db / tables.py
1 # encoding: utf8
2
3 u"""The Pokédex schema
4
5 Columns have a info dictionary with these keys:
6 - description: The description of the column
7 - official: True if the values appear in games or official material; False if
8 they are fan-created or fan-written. This flag is currently only set for
9 official text columns.
10 - markup: The format of a text column. Can be one of:
11 - plaintext: Normal Unicode text (widely used in names)
12 - markdown: Veekun's Markdown flavor (generally used in effect descriptions)
13 - gametext: Transcription of in-game text that strives to be both
14 human-readable and represent the original text exactly.
15 - identifier: A fan-made identifier in the [-_a-z0-9]* format. Not intended
16 for translation.
17 - latex: A formula in LaTeX syntax.
18 - foreign: If set, the column contains foreign (non-English) text.
19
20 """
21 # XXX: Check if "gametext" is set correctly everywhere
22
23 # XXX: Some columns paradoxically have official=True and markup='identifier'.
24 # This is when one column is used as both the English name (lowercased) and
25 # an identifier. This should be fixed.
26
27 from sqlalchemy import Column, ForeignKey, MetaData, PrimaryKeyConstraint, Table
28 from sqlalchemy.ext.declarative import declarative_base
29 from sqlalchemy.ext.associationproxy import association_proxy
30 from sqlalchemy.orm import backref, eagerload_all, relation
31 from sqlalchemy.orm.session import Session
32 from sqlalchemy.sql import and_
33 from sqlalchemy.types import *
34
35 from pokedex.db import markdown
36
37 metadata = MetaData()
38 TableBase = declarative_base(metadata=metadata)
39
40 class Ability(TableBase):
41 u"""An ability a Pokémon can have, such as Static or Pressure.
42 """
43 __tablename__ = 'abilities'
44 __singlename__ = 'ability'
45 id = Column(Integer, primary_key=True, nullable=False,
46 info=dict(description="This ability's unique ID; matches the games' internal ID"))
47 name = Column(Unicode(24), nullable=False,
48 info=dict(description="The official English name of this ability", official=True, format='plaintext'))
49 generation_id = Column(Integer, ForeignKey('generations.id'), nullable=False,
50 info=dict(description="The ID of the generation this ability was introduced in", detail=True))
51 effect = Column(markdown.MarkdownColumn(5120), nullable=False,
52 info=dict(description="A detailed description of this ability's effect", format='markdown'))
53 short_effect = Column(markdown.MarkdownColumn(255), nullable=False,
54 info=dict(description="A short summary of this ability's effect", format='markdown'))
55
56 class AbilityChangelog(TableBase):
57 """History of changes to abilities across main game versions."""
58 __tablename__ = 'ability_changelog'
59 ability_id = Column(Integer, ForeignKey('abilities.id'), primary_key=True, nullable=False,
60 info=dict(description="The ID of the ability that changed"))
61 changed_in_version_group_id = Column(Integer, ForeignKey('version_groups.id'), primary_key=True, nullable=False,
62 info=dict(description="The ID of the version group in which the ability changed"))
63 effect = Column(markdown.MarkdownColumn(255), nullable=False,
64 info=dict(description="A description of the old behavior", format='markdown'))
65
66 class AbilityFlavorText(TableBase):
67 u"""In-game flavor text of an ability
68 """
69 __tablename__ = 'ability_flavor_text'
70 ability_id = Column(Integer, ForeignKey('abilities.id'), primary_key=True, nullable=False, autoincrement=False,
71 info=dict(description="The ID of the ability"))
72 version_group_id = Column(Integer, ForeignKey('version_groups.id'), primary_key=True, nullable=False, autoincrement=False,
73 info=dict(description="The ID of the version group this flavor text is taken from"))
74 flavor_text = Column(Unicode(64), nullable=False,
75 info=dict(description="The actual flavor text", official=True, format='gametext'))
76
77 class AbilityName(TableBase):
78 u"""Non-English official name of an ability
79 """
80 __tablename__ = 'ability_names'
81 ability_id = Column(Integer, ForeignKey('abilities.id'), primary_key=True, nullable=False, autoincrement=False,
82 info=dict(description="The ID of the ability"))
83 language_id = Column(Integer, ForeignKey('languages.id'), primary_key=True, nullable=False, autoincrement=False,
84 info=dict(description="The ID of the language"))
85 name = Column(Unicode(16), nullable=False,
86 info=dict(description="The ID of the language", official=True, foreign=True, format='plaintext'))
87
88 class Berry(TableBase):
89 u"""A Berry, consumable item that grows on trees
90
91 For data common to all items, such as the name, see the corresponding item entry.
92 """
93 __tablename__ = 'berries'
94 id = Column(Integer, primary_key=True, nullable=False,
95 info=dict(description="This Berry's in-game number"))
96 item_id = Column(Integer, ForeignKey('items.id'), nullable=False,
97 info=dict(description="The ID of the item that represents this Berry"))
98 firmness_id = Column(Integer, ForeignKey('berry_firmness.id'), nullable=False,
99 info=dict(description="The ID of this Berry's firmness category"))
100 natural_gift_power = Column(Integer, nullable=True,
101 info=dict(description="Natural Gift's power when used with this Berry"))
102 natural_gift_type_id = Column(Integer, ForeignKey('types.id'), nullable=True,
103 info=dict(description="The ID of the Type that Natural Gift has when used with this Berry"))
104 size = Column(Integer, nullable=False,
105 info=dict(description=u"The size of this Berry, in millimeters"))
106 max_harvest = Column(Integer, nullable=False,
107 info=dict(description="The maximum number of these berries that can grow on one tree in Generation IV"))
108 growth_time = Column(Integer, nullable=False,
109 info=dict(description="Time it takes the tree to grow one stage, in hours. Berry trees go through four of these growth stages before they can be picked."))
110 soil_dryness = Column(Integer, nullable=False,
111 info=dict(description="The speed at which this Berry dries out the soil as it grows. A higher rate means the soil dries more quickly."))
112 smoothness = Column(Integer, nullable=False,
113 info=dict(description="The smoothness of this Berry, used in making Pokéblocks or Poffins"))
114
115 class BerryFirmness(TableBase):
116 u"""A Berry firmness, such as "hard" or "very soft".
117 """
118 __tablename__ = 'berry_firmness'
119 id = Column(Integer, primary_key=True, nullable=False,
120 info=dict(description="A unique ID for this firmness"))
121 name = Column(Unicode(10), nullable=False,
122 info=dict(description="The games' English label for this firmness level", official=True, format='plaintext'))
123
124 class BerryFlavor(TableBase):
125 u"""A Berry flavor level.
126 """
127 __tablename__ = 'berry_flavors'
128 berry_id = Column(Integer, ForeignKey('berries.id'), primary_key=True, nullable=False, autoincrement=False,
129 info=dict(description="The ID of the berry"))
130 contest_type_id = Column(Integer, ForeignKey('contest_types.id'), primary_key=True, nullable=False, autoincrement=False,
131 info=dict(description="The ID of the flavor"))
132 flavor = Column(Integer, nullable=False,
133 info=dict(description="The level of the flavor in the berry"))
134
135 class ContestCombo(TableBase):
136 u"""Combo of two moves in a Contest.
137 """
138 __tablename__ = 'contest_combos'
139 first_move_id = Column(Integer, ForeignKey('moves.id'), primary_key=True, nullable=False, autoincrement=False,
140 info=dict(description="The ID of the first move in the combo"))
141 second_move_id = Column(Integer, ForeignKey('moves.id'), primary_key=True, nullable=False, autoincrement=False,
142 info=dict(description="The ID of the second and final move in the combo"))
143
144 class ContestEffect(TableBase):
145 u"""Effect of a move when used in a Contest.
146 """
147 __tablename__ = 'contest_effects'
148 id = Column(Integer, primary_key=True, nullable=False,
149 info=dict(description="A unique ID for this effect"))
150 appeal = Column(SmallInteger, nullable=False,
151 info=dict(description="The base number of hearts the user of this move gets"))
152 jam = Column(SmallInteger, nullable=False,
153 info=dict(description="The base number of hearts the user's opponent loses"))
154 flavor_text = Column(Unicode(64), nullable=False,
155 info=dict(description="The English in-game description of this effect", official=True, format='gametext'))
156 effect = Column(Unicode(255), nullable=False,
157 info=dict(description="A detailed description of the effect", format='markdown'))
158
159 class ContestType(TableBase):
160 u"""A Contest type, such as "cool" or "smart", and their associated Berry flavors and Pokéblock colors.
161 """
162 __tablename__ = 'contest_types'
163 id = Column(Integer, primary_key=True, nullable=False,
164 info=dict(description="A unique ID for this Contest type"))
165 name = Column(Unicode(6), nullable=False,
166 info=dict(description="The English name of the Contest type", official=True, format='identifier'))
167 flavor = Column(Unicode(6), nullable=False,
168 info=dict(description="The English name of the corresponding Berry flavor", official=True, format='identifier'))
169 color = Column(Unicode(6), nullable=False,
170 info=dict(description=u"The English name of the corresponding Pokéblock color", official=True, format='identifier'))
171
172 class EggGroup(TableBase):
173 u"""An Egg group. Usually, two Pokémon can breed if they share an Egg Group.
174
175 (exceptions are the Ditto and No Eggs groups)
176 """
177 __tablename__ = 'egg_groups'
178 id = Column(Integer, primary_key=True, nullable=False,
179 info=dict(description="A unique ID for this group"))
180 name = Column(Unicode(16), nullable=False,
181 info=dict(description=u"The English name of this egg group, from Earl's Pokémon Academy in Pokémon Stadium 2. "
182 u"And no, these haven't officially been used anywhere else.", official=True, format='identifier'))
183
184 class Encounter(TableBase):
185 u"""Encounters with wild Pokémon.
186
187 Bear with me, here.
188
189 Within a given area in a given game, encounters are differentiated by the
190 "slot" they are in and the state of the game world.
191
192 What the player is doing to get an encounter, such as surfing or walking
193 through tall grass, is called terrain. Each terrain has its own set of
194 encounter slots.
195
196 Within a terrain, slots are defined primarily by rarity. Each slot can
197 also be affected by world conditions; for example, the 20% slot for walking
198 in tall grass is affected by whether a swarm is in effect in that area.
199 "Is there a swarm?" is a condition; "there is a swarm" and "there is not a
200 swarm" are the possible values of this condition.
201
202 A slot (20% walking in grass) and any appropriate world conditions (no
203 swarm) are thus enough to define a specific encounter.
204
205 Well, okay, almost: each slot actually appears twice.
206 """
207
208 __tablename__ = 'encounters'
209 id = Column(Integer, primary_key=True, nullable=False,
210 info=dict(description="A unique ID for this encounter"))
211 version_id = Column(Integer, ForeignKey('versions.id'), nullable=False, autoincrement=False,
212 info=dict(description="The ID of the version this applies to"))
213 location_area_id = Column(Integer, ForeignKey('location_areas.id'), nullable=False, autoincrement=False,
214 info=dict(description="The ID of the location of this encounter"))
215 encounter_slot_id = Column(Integer, ForeignKey('encounter_slots.id'), nullable=False, autoincrement=False,
216 info=dict(description="The ID of the encounter slot, which determines terrain and rarity"))
217 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), nullable=False, autoincrement=False,
218 info=dict(description=u"The ID of the encountered Pokémon"))
219 min_level = Column(Integer, nullable=False, autoincrement=False,
220 info=dict(description=u"The minimum level of the encountered Pokémon"))
221 max_level = Column(Integer, nullable=False, autoincrement=False,
222 info=dict(description=u"The maxmum level of the encountered Pokémon"))
223
224 class EncounterCondition(TableBase):
225 u"""A conditions in the game world that affects Pokémon encounters, such as time of day.
226 """
227
228 __tablename__ = 'encounter_conditions'
229 id = Column(Integer, primary_key=True, nullable=False,
230 info=dict(description="A unique ID for this condition"))
231 name = Column(Unicode(64), nullable=False,
232 info=dict(description="An English label for the condition", format='plaintext'))
233
234 class EncounterConditionValue(TableBase):
235 u"""A possible state for a condition; for example, the state of 'swarm' could be 'swarm' or 'no swarm'.
236 """
237
238 __tablename__ = 'encounter_condition_values'
239 id = Column(Integer, primary_key=True, nullable=False,
240 info=dict(description="A numeric ID"))
241 encounter_condition_id = Column(Integer, ForeignKey('encounter_conditions.id'), primary_key=False, nullable=False, autoincrement=False,
242 info=dict(description="The ID of the encounter condition this is a value of"))
243 name = Column(Unicode(64), nullable=False,
244 info=dict(description="An English label for this value", format='plaintext'))
245 is_default = Column(Boolean, nullable=False,
246 info=dict(description='Set if this value is the default state for the condition'))
247
248 class EncounterConditionValueMap(TableBase):
249 u"""Maps encounters to the specific conditions under which they occur.
250 """
251 __tablename__ = 'encounter_condition_value_map'
252 encounter_id = Column(Integer, ForeignKey('encounters.id'), primary_key=True, nullable=False, autoincrement=False,
253 info=dict(description="The ID of the encounter"))
254 encounter_condition_value_id = Column(Integer, ForeignKey('encounter_condition_values.id'), primary_key=True, nullable=False, autoincrement=False,
255 info=dict(description="The ID of the encounter condition value"))
256
257 class EncounterTerrain(TableBase):
258 u"""A way the player can enter a wild encounter, e.g., surfing, fishing, or walking through tall grass.
259 """
260
261 __tablename__ = 'encounter_terrain'
262 id = Column(Integer, primary_key=True, nullable=False,
263 info=dict(description="A unique ID for the terrain"))
264 name = Column(Unicode(64), nullable=False,
265 info=dict(description="An English label for this terrain", format='plaintext'))
266
267 class EncounterSlot(TableBase):
268 u"""An abstract "slot" within a terrain, associated with both some set of conditions and a rarity.
269
270 Note that there are two encounters per slot, so the rarities will only add
271 up to 50.
272 """
273
274 __tablename__ = 'encounter_slots'
275 id = Column(Integer, primary_key=True, nullable=False,
276 info=dict(description="A unique ID for this slot"))
277 version_group_id = Column(Integer, ForeignKey('version_groups.id'), nullable=False, autoincrement=False,
278 info=dict(description="The ID of the version group this slot is in"))
279 encounter_terrain_id = Column(Integer, ForeignKey('encounter_terrain.id'), primary_key=False, nullable=False, autoincrement=False,
280 info=dict(description="The ID of the terrain"))
281 slot = Column(Integer, nullable=True,
282 info=dict(description="This slot's order for the location and terrain"))
283 rarity = Column(Integer, nullable=False,
284 info=dict(description="The chance of the encounter as a percentage"))
285
286 class EvolutionChain(TableBase):
287 u"""A family of Pokémon that are linked by evolution
288 """
289 __tablename__ = 'evolution_chains'
290 id = Column(Integer, primary_key=True, nullable=False,
291 info=dict(description="A numeric ID"))
292 growth_rate_id = Column(Integer, ForeignKey('growth_rates.id'), nullable=False,
293 info=dict(description="ID of the growth rate for this family"))
294 baby_trigger_item_id = Column(Integer, ForeignKey('items.id'), nullable=True,
295 info=dict(description="Item that a parent must hold while breeding to produce a baby"))
296
297 class EvolutionTrigger(TableBase):
298 u"""An evolution type, such as "level" or "trade".
299 """
300 __tablename__ = 'evolution_triggers'
301 id = Column(Integer, primary_key=True, nullable=False,
302 info=dict(description="A numeric ID"))
303 identifier = Column(Unicode(16), nullable=False,
304 info=dict(description="An English identifier", format='identifier'))
305
306 class Experience(TableBase):
307 u"""EXP needed for a certain level with a certain growth rate
308 """
309 __tablename__ = 'experience'
310 growth_rate_id = Column(Integer, ForeignKey('growth_rates.id'), primary_key=True, nullable=False,
311 info=dict(description="ID of the growth rate"))
312 level = Column(Integer, primary_key=True, nullable=False, autoincrement=False,
313 info=dict(description="The level"))
314 experience = Column(Integer, nullable=False,
315 info=dict(description="The number of EXP points needed to get to that level"))
316
317 class Generation(TableBase):
318 u"""A Generation of the Pokémon franchise
319 """
320 __tablename__ = 'generations'
321 id = Column(Integer, primary_key=True, nullable=False,
322 info=dict(description="A numeric ID"))
323 main_region_id = Column(Integer, ForeignKey('regions.id'),
324 info=dict(description="ID of the region this generation's main games take place in"))
325 canonical_pokedex_id = Column(Integer, ForeignKey('pokedexes.id'),
326 info=dict(description=u"ID of the Pokédex this generation's main games use by default"))
327 name = Column(Unicode(16), nullable=False,
328 info=dict(description=u'An English name of this generation, such as "Generation IV"', format='plaintext'))
329
330 class GrowthRate(TableBase):
331 u"""Growth rate of a Pokémon, i.e. the EXP → level function.
332 """
333 __tablename__ = 'growth_rates'
334 id = Column(Integer, primary_key=True, nullable=False,
335 info=dict(description="A numeric ID"))
336 name = Column(Unicode(20), nullable=False,
337 info=dict(description="A name for the", format='identifier'))
338 formula = Column(Unicode(500), nullable=False,
339 info=dict(description="The formula", format='latex'))
340
341 class Item(TableBase):
342 u"""An Item from the games, like "Poké Ball" or "Bicycle".
343 """
344 __tablename__ = 'items'
345 __singlename__ = 'item'
346 id = Column(Integer, primary_key=True, nullable=False,
347 info=dict(description="A numeric ID"))
348 name = Column(Unicode(20), nullable=False,
349 info=dict(description="The English name of the item", official=True, format='plaintext'))
350 category_id = Column(Integer, ForeignKey('item_categories.id'), nullable=False,
351 info=dict(description="ID of a category this item belongs to"))
352 cost = Column(Integer, nullable=False,
353 info=dict(description=u"Cost of the item when bought. Items sell for half this price."))
354 fling_power = Column(Integer, nullable=True,
355 info=dict(description=u"Power of the move Fling when used with this item."))
356 fling_effect_id = Column(Integer, ForeignKey('item_fling_effects.id'), nullable=True,
357 info=dict(description=u"ID of the fling-effect of the move Fling when used with this item. Note that these are different from move effects."))
358 short_effect = Column(Unicode(256), nullable=False,
359 info=dict(description="A short summary of the effect", format='plaintext'))
360 effect = Column(markdown.MarkdownColumn(5120), nullable=False,
361 info=dict(description=u"Detailed English description of the item's effect.", format='markdown'))
362
363 @property
364 def appears_underground(self):
365 u"""True if the item appears underground, as specified by the appropriate flag
366 """
367 return any(flag.identifier == u'underground' for flag in self.flags)
368
369 class ItemCategory(TableBase):
370 u"""An item category
371 """
372 # XXX: This is fanon, right?
373 __tablename__ = 'item_categories'
374 id = Column(Integer, primary_key=True, nullable=False,
375 info=dict(description="A numeric ID"))
376 pocket_id = Column(Integer, ForeignKey('item_pockets.id'), nullable=False,
377 info=dict(description="ID of the pocket these items go to"))
378 name = Column(Unicode(16), nullable=False,
379 info=dict(description="English name of the category", format='plaintext'))
380
381 class ItemFlag(TableBase):
382 u"""An item attribute such as "consumable" or "holdable".
383 """
384 __tablename__ = 'item_flags'
385 id = Column(Integer, primary_key=True, nullable=False,
386 info=dict(description="A numeric ID"))
387 identifier = Column(Unicode(24), nullable=False,
388 info=dict(description="Identifier of the flag", format='identifier'))
389 name = Column(Unicode(64), nullable=False,
390 info=dict(description="Short English description of the flag", format='plaintext'))
391
392 class ItemFlagMap(TableBase):
393 u"""Maps an item flag to its item.
394 """
395 __tablename__ = 'item_flag_map'
396 item_id = Column(Integer, ForeignKey('items.id'), primary_key=True, autoincrement=False, nullable=False,
397 info=dict(description="The ID of the item"))
398 item_flag_id = Column(Integer, ForeignKey('item_flags.id'), primary_key=True, autoincrement=False, nullable=False,
399 info=dict(description="The ID of the item flag"))
400
401 class ItemFlavorText(TableBase):
402 u"""An in-game description of an item
403 """
404 __tablename__ = 'item_flavor_text'
405 item_id = Column(Integer, ForeignKey('items.id'), primary_key=True, autoincrement=False, nullable=False,
406 info=dict(description="The ID of the item"))
407 version_group_id = Column(Integer, ForeignKey('version_groups.id'), primary_key=True, autoincrement=False, nullable=False,
408 info=dict(description="ID of the version group that sports this text"))
409 flavor_text = Column(Unicode(255), nullable=False,
410 info=dict(description="The flavor text itself", official=True, format='gametext'))
411
412 class ItemFlingEffect(TableBase):
413 u"""An effect of the move Fling when used with a specific item
414 """
415 __tablename__ = 'item_fling_effects'
416 id = Column(Integer, primary_key=True, nullable=False,
417 info=dict(description="A numeric ID"))
418 effect = Column(Unicode(255), nullable=False,
419 info=dict(description="English description of the effect", format='plaintext'))
420
421 class ItemInternalID(TableBase):
422 u"""The internal ID number a game uses for an item
423 """
424 __tablename__ = 'item_internal_ids'
425 item_id = Column(Integer, ForeignKey('items.id'), primary_key=True, autoincrement=False, nullable=False,
426 info=dict(description="The database ID of the item"))
427 generation_id = Column(Integer, ForeignKey('generations.id'), primary_key=True, autoincrement=False, nullable=False,
428 info=dict(description="ID of the generation of games"))
429 internal_id = Column(Integer, nullable=False,
430 info=dict(description="Internal ID of the item in the generation"))
431
432 class ItemName(TableBase):
433 u"""A non-English name of an item
434 """
435 __tablename__ = 'item_names'
436 item_id = Column(Integer, ForeignKey('items.id'), primary_key=True, nullable=False, autoincrement=False,
437 info=dict(description="The ID of the item"))
438 language_id = Column(Integer, ForeignKey('languages.id'), primary_key=True, nullable=False, autoincrement=False,
439 info=dict(description="The ID of the language"))
440 name = Column(Unicode(16), nullable=False,
441 info=dict(description="The name of the item in this language", foreign=True, format='plaintext'))
442
443 class ItemPocket(TableBase):
444 u"""A pocket that categorizes items
445 """
446 __tablename__ = 'item_pockets'
447 id = Column(Integer, primary_key=True, nullable=False,
448 info=dict(description="A numeric ID"))
449 identifier = Column(Unicode(16), nullable=False,
450 info=dict(description="An identifier of this pocket", format='identifier'))
451 name = Column(Unicode(16), nullable=False,
452 info=dict(description="A numeric ID", format='plaintext'))
453
454 class Language(TableBase):
455 u"""A language the Pokémon games have been transleted into; except English
456 """
457 __tablename__ = 'languages'
458 id = Column(Integer, primary_key=True, nullable=False,
459 info=dict(description="A numeric ID"))
460 iso639 = Column(Unicode(2), nullable=False,
461 info=dict(description="The two-letter code of the country where this language is spoken. Note that it is not unique."))
462 iso3166 = Column(Unicode(2), nullable=False,
463 info=dict(description="The two-letter code of the language. Note that it is not unique."))
464 name = Column(Unicode(16), nullable=False,
465 info=dict(description="The English name of the language", format='plaintext'))
466
467 class Location(TableBase):
468 u"""A place in the Pokémon world
469 """
470 __tablename__ = 'locations'
471 __singlename__ = 'location'
472 id = Column(Integer, primary_key=True, nullable=False,
473 info=dict(description="A numeric ID"))
474 region_id = Column(Integer, ForeignKey('regions.id'),
475 info=dict(description="ID of the region this location is in"))
476 name = Column(Unicode(64), nullable=False,
477 info=dict(description="English name of the location", official=True, format='plaintext'))
478
479 class LocationArea(TableBase):
480 u"""A sub-area of a location
481 """
482 __tablename__ = 'location_areas'
483 id = Column(Integer, primary_key=True, nullable=False,
484 info=dict(description="A numeric ID"))
485 location_id = Column(Integer, ForeignKey('locations.id'), nullable=False,
486 info=dict(description="ID of the location this area is part of"))
487 internal_id = Column(Integer, nullable=False,
488 info=dict(description="ID the games ude for this area"))
489 name = Column(Unicode(64), nullable=True,
490 info=dict(description="An English name of the area, if applicable", format='plaintext'))
491
492 class LocationAreaEncounterRate(TableBase):
493 # XXX: What's this exactly? Someone add the docstring & revise the descriptions
494 __tablename__ = 'location_area_encounter_rates'
495 location_area_id = Column(Integer, ForeignKey('location_areas.id'), primary_key=True, nullable=False, autoincrement=False,
496 info=dict(description="ID of the area"))
497 encounter_terrain_id = Column(Integer, ForeignKey('encounter_terrain.id'), primary_key=True, nullable=False, autoincrement=False,
498 info=dict(description="ID of the terrain"))
499 version_id = Column(Integer, ForeignKey('versions.id'), primary_key=True, autoincrement=False,
500 info=dict(description="ID of the version"))
501 rate = Column(Integer, nullable=True,
502 info=dict(description="The encounter rate")) # units?
503
504 class LocationInternalID(TableBase):
505 u"""IDs the games use internally for locations
506 """
507 __tablename__ = 'location_internal_ids'
508 location_id = Column(Integer, ForeignKey('locations.id'), nullable=False, primary_key=True,
509 info=dict(description="Database ID of the locaion"))
510 generation_id = Column(Integer, ForeignKey('generations.id'), nullable=False, primary_key=True,
511 info=dict(description="ID of the generation this entry to"))
512 internal_id = Column(Integer, nullable=False,
513 info=dict(description="Internal game ID of the location"))
514
515 class Machine(TableBase):
516 u"""A TM or HM; numbered item that can teach a move to a Pokémon
517 """
518 __tablename__ = 'machines'
519 machine_number = Column(Integer, primary_key=True, nullable=False, autoincrement=False,
520 info=dict(description="Number of the machine for TMs, or 100 + the munber for HMs"))
521 version_group_id = Column(Integer, ForeignKey('version_groups.id'), primary_key=True, nullable=False, autoincrement=False,
522 info=dict(description="Versions this entry applies to"))
523 item_id = Column(Integer, ForeignKey('items.id'), nullable=False,
524 info=dict(description="ID of the corresponding Item"))
525 move_id = Column(Integer, ForeignKey('moves.id'), nullable=False,
526 info=dict(description="ID of the taught move"))
527
528 @property
529 def is_hm(self):
530 u"""True if this machine is a HM, False if it's a TM
531 """
532 return self.machine_number >= 100
533
534 class MoveBattleStyle(TableBase):
535 u"""A battle style of a move""" # XXX: Explain better
536 __tablename__ = 'move_battle_styles'
537 id = Column(Integer, primary_key=True, nullable=False,
538 info=dict(description="A numeric ID"))
539 name = Column(Unicode(8), nullable=False,
540 info=dict(description="An English name for this battle style", format='plaintext'))
541
542 class MoveEffectCategory(TableBase):
543 u"""Category of a move effect
544 """
545 __tablename__ = 'move_effect_categories'
546 id = Column(Integer, primary_key=True, nullable=False,
547 info=dict(description="A numeric ID"))
548 name = Column(Unicode(64), nullable=False,
549 info=dict(description="English name of the category", format='plaintext'))
550 can_affect_user = Column(Boolean, nullable=False,
551 info=dict(description="Set if the user can be affected"))
552
553 class MoveEffectCategoryMap(TableBase):
554 u"""Maps a move effect category to a move effect
555 """
556 __tablename__ = 'move_effect_category_map'
557 move_effect_id = Column(Integer, ForeignKey('move_effects.id'), primary_key=True, nullable=False,
558 info=dict(description="ID of the move effect"))
559 move_effect_category_id = Column(Integer, ForeignKey('move_effect_categories.id'), primary_key=True, nullable=False,
560 info=dict(description="ID of the category"))
561 affects_user = Column(Boolean, primary_key=True, nullable=False,
562 info=dict(description="Set if the user is affected"))
563
564 class MoveDamageClass(TableBase):
565 u"""Any of the damage classes moves can have, i.e. physical, special, or non-damaging.
566 """
567 __tablename__ = 'move_damage_classes'
568 id = Column(Integer, primary_key=True, nullable=False,
569 info=dict(description="A numeric ID"))
570 name = Column(Unicode(16), nullable=False,
571 info=dict(description="An English name of the class", format='plaintext'))
572 description = Column(Unicode(64), nullable=False,
573 info=dict(description="An English description of the class", format='plaintext'))
574
575 class MoveEffect(TableBase):
576 u"""An effect of a move
577 """
578 __tablename__ = 'move_effects'
579 id = Column(Integer, primary_key=True, nullable=False,
580 info=dict(description="A numeric ID"))
581 short_effect = Column(Unicode(256), nullable=False,
582 info=dict(description="A short summary of the effect", format='plaintext'))
583 effect = Column(Unicode(5120), nullable=False,
584 info=dict(description="A detailed description of the effect", format='plaintext'))
585
586 class MoveEffectChangelog(TableBase):
587 """History of changes to move effects across main game versions."""
588 __tablename__ = 'move_effect_changelog'
589 effect_id = Column(Integer, ForeignKey('move_effects.id'), primary_key=True, nullable=False,
590 info=dict(description="The ID of the effect that changed"))
591 changed_in_version_group_id = Column(Integer, ForeignKey('version_groups.id'), primary_key=True, nullable=False,
592 info=dict(description="The ID of the version group in which the effect changed"))
593 effect = Column(markdown.MarkdownColumn(512), nullable=False,
594 info=dict(description="A description of the old behavior", format='markdown'))
595
596 class MoveFlag(TableBase):
597 u"""Maps a move flag to a move
598 """
599 # XXX: Other flags have a ___Flag class for the actual flag and ___FlagMap for the map,
600 # these, somewhat confusingly, have MoveFlagType and MoveFlag
601 __tablename__ = 'move_flags'
602 move_id = Column(Integer, ForeignKey('moves.id'), primary_key=True, nullable=False, autoincrement=False,
603 info=dict(description="ID of the move"))
604 move_flag_type_id = Column(Integer, ForeignKey('move_flag_types.id'), primary_key=True, nullable=False, autoincrement=False,
605 info=dict(description="ID of the flag"))
606
607 class MoveFlagType(TableBase):
608 u"""A Move attribute such as "snatchable" or "contact".
609 """
610 __tablename__ = 'move_flag_types'
611 id = Column(Integer, primary_key=True, nullable=False,
612 info=dict(description="A numeric ID"))
613 identifier = Column(Unicode(16), nullable=False,
614 info=dict(description="A short identifier for the flag", format='identifier'))
615 name = Column(Unicode(32), nullable=False,
616 info=dict(description="An English name for the flag", format='plaintext'))
617 description = Column(markdown.MarkdownColumn(128), nullable=False,
618 info=dict(description="A short English description of the flag", format='markdown'))
619
620 class MoveFlavorText(TableBase):
621 u"""In-game description of a move
622 """
623 __tablename__ = 'move_flavor_text'
624 move_id = Column(Integer, ForeignKey('moves.id'), primary_key=True, nullable=False, autoincrement=False,
625 info=dict(description="ID of the move"))
626 version_group_id = Column(Integer, ForeignKey('version_groups.id'), primary_key=True, nullable=False, autoincrement=False,
627 info=dict(description="ID of the version group this text appears in"))
628 flavor_text = Column(Unicode(255), nullable=False,
629 info=dict(description="The English flavor text", official=True, format='gametext'))
630
631 class MoveMeta(TableBase):
632 u"""Metadata for move effects, sorta-kinda ripped straight from the game"""
633 __tablename__ = 'move_meta'
634 move_id = Column(Integer, ForeignKey('moves.id'), primary_key=True, nullable=False, autoincrement=False)
635 meta_category_id = Column(Integer, ForeignKey('move_meta_categories.id'), nullable=False)
636 meta_ailment_id = Column(Integer, ForeignKey('move_meta_ailments.id'), nullable=False)
637 min_hits = Column(Integer, nullable=True, index=True)
638 max_hits = Column(Integer, nullable=True, index=True)
639 min_turns = Column(Integer, nullable=True, index=True)
640 max_turns = Column(Integer, nullable=True, index=True)
641 recoil = Column(Integer, nullable=False, index=True)
642 healing = Column(Integer, nullable=False, index=True)
643 crit_rate = Column(Integer, nullable=False, index=True)
644 ailment_chance = Column(Integer, nullable=False, index=True)
645 flinch_chance = Column(Integer, nullable=False, index=True)
646 stat_chance = Column(Integer, nullable=False, index=True)
647
648 class MoveMetaAilment(TableBase):
649 u"""Common status ailments moves can inflict on a single Pokémon, including
650 major ailments like paralysis and minor ailments like trapping.
651 """
652 __tablename__ = 'move_meta_ailments'
653 id = Column(Integer, primary_key=True, nullable=False)
654 name = Column(Unicode(24), nullable=False)
655
656 class MoveMetaCategory(TableBase):
657 u"""Very general categories that loosely group move effects."""
658 __tablename__ = 'move_meta_categories'
659 id = Column(Integer, primary_key=True, nullable=False)
660 description = Column(Unicode(64), nullable=False)
661
662 class MoveMetaStatChange(TableBase):
663 u"""Stat changes moves (may) make."""
664 __tablename__ = 'move_meta_stat_changes'
665 move_id = Column(Integer, ForeignKey('moves.id'), primary_key=True, nullable=False, autoincrement=False)
666 stat_id = Column(Integer, ForeignKey('stats.id'), primary_key=True, nullable=False, autoincrement=False)
667 change = Column(Integer, nullable=False, index=True)
668
669 class MoveName(TableBase):
670 u"""Non-English name of a move
671 """
672 __tablename__ = 'move_names'
673 move_id = Column(Integer, ForeignKey('moves.id'), primary_key=True, nullable=False, autoincrement=False,
674 info=dict(description="ID of the move"))
675 language_id = Column(Integer, ForeignKey('languages.id'), primary_key=True, nullable=False, autoincrement=False,
676 info=dict(description="ID of the language"))
677 name = Column(Unicode(16), nullable=False,
678 info=dict(description="ID of the language", foreign=True, format='plaintext'))
679
680 class MoveTarget(TableBase):
681 u"""Targetting or "range" of a move, e.g. "Affects all opponents" or "Affects user".
682 """
683 __tablename__ = 'move_targets'
684 id = Column(Integer, primary_key=True, nullable=False,
685 info=dict(description="A numeric ID"))
686 name = Column(Unicode(32), nullable=False,
687 info=dict(description="An English name", format='plaintext'))
688 description = Column(Unicode(128), nullable=False,
689 info=dict(description="An English description", format='plaintext'))
690
691 class Move(TableBase):
692 u"""A Move: technique or attack a Pokémon can learn to use
693 """
694 __tablename__ = 'moves'
695 __singlename__ = 'move'
696 id = Column(Integer, primary_key=True, nullable=False,
697 info=dict(description="A numeric ID"))
698 name = Column(Unicode(24), nullable=False,
699 info=dict(description="The English name of the move", official=True, format='plaintext'))
700 generation_id = Column(Integer, ForeignKey('generations.id'), nullable=False,
701 info=dict(description="ID of the generation this move first appeared in"))
702 type_id = Column(Integer, ForeignKey('types.id'), nullable=False,
703 info=dict(description="ID of the move's elemental type"))
704 power = Column(SmallInteger, nullable=False,
705 info=dict(description="Base power of the move"))
706 pp = Column(SmallInteger, nullable=True,
707 info=dict(description="Base PP (Power Points) of the move, nullable if not applicable (e.g. Struggle and Shadow moves)."))
708 accuracy = Column(SmallInteger, nullable=True,
709 info=dict(description="Accuracy of the move; NULL means it never misses"))
710 priority = Column(SmallInteger, nullable=False,
711 info=dict(description="The move's priority bracket"))
712 target_id = Column(Integer, ForeignKey('move_targets.id'), nullable=False,
713 info=dict(description="ID of the target (range) of the move"))
714 damage_class_id = Column(Integer, ForeignKey('move_damage_classes.id'), nullable=False,
715 info=dict(description="ID of the damage class (physical/special) of the move"))
716 effect_id = Column(Integer, ForeignKey('move_effects.id'), nullable=False,
717 info=dict(description="ID of the move's effect"))
718 effect_chance = Column(Integer, nullable=True,
719 info=dict(description="The chance for a secondary effect. What this is a chance of is specified by the move's effect."))
720 contest_type_id = Column(Integer, ForeignKey('contest_types.id'), nullable=True,
721 info=dict(description="ID of the move's Contest type (e.g. cool or smart)"))
722 contest_effect_id = Column(Integer, ForeignKey('contest_effects.id'), nullable=True,
723 info=dict(description="ID of the move's Contest effect"))
724 super_contest_effect_id = Column(Integer, ForeignKey('super_contest_effects.id'), nullable=True,
725 info=dict(description="ID of the move's Super Contest effect"))
726
727 class MoveChangelog(TableBase):
728 """History of changes to moves across main game versions."""
729 __tablename__ = 'move_changelog'
730 move_id = Column(Integer, ForeignKey('moves.id'), primary_key=True, nullable=False,
731 info=dict(description="ID of the move that changed"))
732 changed_in_version_group_id = Column(Integer, ForeignKey('version_groups.id'), primary_key=True, nullable=False,
733 info=dict(description="ID of the version group in which the move changed"))
734 type_id = Column(Integer, ForeignKey('types.id'), nullable=True,
735 info=dict(description="Prior type of the move, or NULL if unchanged"))
736 power = Column(SmallInteger, nullable=True,
737 info=dict(description="Prior base power of the move, or NULL if unchanged"))
738 pp = Column(SmallInteger, nullable=True,
739 info=dict(description="Prior base PP of the move, or NULL if unchanged"))
740 accuracy = Column(SmallInteger, nullable=True,
741 info=dict(description="Prior accuracy of the move, or NULL if unchanged"))
742 effect_id = Column(Integer, ForeignKey('move_effects.id'), nullable=True,
743 info=dict(description="Prior ID of the effect, or NULL if unchanged"))
744 effect_chance = Column(Integer, nullable=True,
745 info=dict(description="Prior effect chance, or NULL if unchanged"))
746
747 class Nature(TableBase):
748 u"""A nature a Pokémon can have, such as Calm or Brave
749 """
750 __tablename__ = 'natures'
751 __singlename__ = 'nature'
752 id = Column(Integer, primary_key=True, nullable=False,
753 info=dict(description="A numeric ID"))
754 name = Column(Unicode(8), nullable=False,
755 info=dict(description="An English name of the nature", official=True, format='plaintext'))
756 decreased_stat_id = Column(Integer, ForeignKey('stats.id'), nullable=False,
757 info=dict(description="ID of the stat that this nature decreases by 10% (if decreased_stat_id is the same, the effects cancel out)"))
758 increased_stat_id = Column(Integer, ForeignKey('stats.id'), nullable=False,
759 info=dict(description="ID of the stat that this nature increases by 10% (if decreased_stat_id is the same, the effects cancel out)"))
760 hates_flavor_id = Column(Integer, ForeignKey('contest_types.id'), nullable=False,
761 info=dict(description=u"ID of the Berry flavor the Pokémon hates (if likes_flavor_id is the same, the effects cancel out)"))
762 likes_flavor_id = Column(Integer, ForeignKey('contest_types.id'), nullable=False,
763 info=dict(description=u"ID of the Berry flavor the Pokémon likes (if hates_flavor_id is the same, the effects cancel out)"))
764
765 @property
766 def is_neutral(self):
767 u"""Returns True iff this nature doesn't alter a Pokémon's stats,
768 bestow taste preferences, etc.
769 """
770 return self.increased_stat_id == self.decreased_stat_id
771
772 class NatureBattleStylePreference(TableBase):
773 u"""Battle Palace move preference
774
775 Specifies how likely a Pokémon with a specific Nature is to use a move of
776 a particular battl style in Battle Palace or Battle Tent
777 """
778 __tablename__ = 'nature_battle_style_preferences'
779 nature_id = Column(Integer, ForeignKey('natures.id'), primary_key=True, nullable=False,
780 info=dict(description=u"ID of the Pokémon's nature"))
781 move_battle_style_id = Column(Integer, ForeignKey('move_battle_styles.id'), primary_key=True, nullable=False,
782 info=dict(description="ID of the battle style"))
783 low_hp_preference = Column(Integer, nullable=False,
784 info=dict(description=u"Chance of using the move, in percent, if HP is under ½"))
785 high_hp_preference = Column(Integer, nullable=False,
786 info=dict(description=u"Chance of using the move, in percent, if HP is over ½"))
787
788 class NatureName(TableBase):
789 u"""Non-english name of a Nature
790 """
791 __tablename__ = 'nature_names'
792 nature_id = Column(Integer, ForeignKey('natures.id'), primary_key=True, nullable=False, autoincrement=False,
793 info=dict(description="ID of the nature"))
794 language_id = Column(Integer, ForeignKey('languages.id'), primary_key=True, nullable=False, autoincrement=False,
795 info=dict(description="ID of the language"))
796 name = Column(Unicode(8), nullable=False,
797 info=dict(description="The nature's foreign name", foreign=True, format='plaintext'))
798
799 class NaturePokeathlonStat(TableBase):
800 u"""Specifies how a Nature affects a Pokéathlon stat
801 """
802 __tablename__ = 'nature_pokeathlon_stats'
803 nature_id = Column(Integer, ForeignKey('natures.id'), primary_key=True, nullable=False,
804 info=dict(description="ID of the nature"))
805 pokeathlon_stat_id = Column(Integer, ForeignKey('pokeathlon_stats.id'), primary_key=True, nullable=False,
806 info=dict(description="ID of the stat"))
807 max_change = Column(Integer, nullable=False,
808 info=dict(description="Maximum change"))
809
810 class PokeathlonStat(TableBase):
811 u"""A Pokéathlon stat, such as "Stamina" or "Jump".
812 """
813 __tablename__ = 'pokeathlon_stats'
814 id = Column(Integer, primary_key=True, nullable=False,
815 info=dict(description="A numeric ID"))
816 name = Column(Unicode(8), nullable=False,
817 info=dict(description="The English name of the stat", official=True, format='plaintext'))
818
819 class Pokedex(TableBase):
820 u"""A collection of Pokémon species ordered in a particular way
821 """
822 __tablename__ = 'pokedexes'
823 id = Column(Integer, primary_key=True, nullable=False,
824 info=dict(description="A numeric ID"))
825 region_id = Column(Integer, ForeignKey('regions.id'), nullable=True,
826 info=dict(description=u"ID of the region this Pokédex is used in, or None if it's global"))
827 name = Column(Unicode(16), nullable=False,
828 info=dict(description=u"An English name of the Pokédex", format='plaintext'))
829 description = Column(Unicode(512),
830 info=dict(description=u"A longer description of the Pokédex", format='plaintext'))
831
832 class Pokemon(TableBase):
833 u"""A species of Pokémon. The core to this whole mess.
834 """
835 __tablename__ = 'pokemon'
836 __singlename__ = 'pokemon'
837 id = Column(Integer, primary_key=True, nullable=False,
838 info=dict(description=u"A numeric ID"))
839 name = Column(Unicode(20), nullable=False,
840 info=dict(description=u"The English name of the Pokémon", official=True, format='plaintext'))
841 generation_id = Column(Integer, ForeignKey('generations.id'),
842 info=dict(description=u"ID of the generation this species first appeared in"))
843 evolution_chain_id = Column(Integer, ForeignKey('evolution_chains.id'),
844 info=dict(description=u"ID of the species' evolution chain (a.k.a. family)"))
845 height = Column(Integer, nullable=False,
846 info=dict(description=u"The height of the Pokémon, in decimeters (tenths of a meter)"))
847 weight = Column(Integer, nullable=False,
848 info=dict(description=u"The weight of the Pokémon, in tenths of a kilogram (decigrams)"))
849 species = Column(Unicode(16), nullable=False,
850 info=dict(description=u'The short English flavor text, such as "Seed" or "Lizard"; usually affixed with the word "Pokémon"',
851 official=True, format='plaintext'))
852 color_id = Column(Integer, ForeignKey('pokemon_colors.id'), nullable=False,
853 info=dict(description=u"ID of this Pokémon's Pokédex color, as used for a gimmick search function in the games."))
854 pokemon_shape_id = Column(Integer, ForeignKey('pokemon_shapes.id'), nullable=True,
855 info=dict(description=u"ID of this Pokémon's body shape, as used for a gimmick search function in the games."))
856 habitat_id = Column(Integer, ForeignKey('pokemon_habitats.id'), nullable=True,
857 info=dict(description=u"ID of this Pokémon's habitat, as used for a gimmick search function in the games."))
858 gender_rate = Column(Integer, nullable=False,
859 info=dict(description=u"The chance of this Pokémon being female, in eighths; or -1 for genderless"))
860 capture_rate = Column(Integer, nullable=False,
861 info=dict(description=u"The base capture rate; up to 255"))
862 base_experience = Column(Integer, nullable=False,
863 info=dict(description=u"The base EXP gained when defeating this Pokémon")) # XXX: Is this correct?
864 base_happiness = Column(Integer, nullable=False,
865 info=dict(description=u"The tameness when caught by a normal ball"))
866 is_baby = Column(Boolean, nullable=False,
867 info=dict(description=u"True iff the Pokémon is a baby, i.e. a lowest-stage Pokémon that cannot breed but whose evolved form can."))
868 hatch_counter = Column(Integer, nullable=False,
869 info=dict(description=u"Initial hatch counter: one must walk 255 × (hatch_counter + 1) steps before this Pokémon's egg hatches, unless utilizing bonuses like Flame Body's"))
870 has_gender_differences = Column(Boolean, nullable=False,
871 info=dict(description=u"Set iff the species exhibits enough sexual dimorphism to have separate sets of sprites in Gen IV and beyond."))
872 order = Column(Integer, nullable=False, index=True,
873 info=dict(description=u"Order for sorting. Almost national order, except families and forms are grouped together."))
874
875 ### Stuff to handle alternate Pokémon forms
876
877 @property
878 def form(self):
879 u"""Returns the Pokémon's form, using its default form as fallback."""
880
881 return self.unique_form or self.default_form
882
883 @property
884 def is_base_form(self):
885 u"""Returns True iff the Pokémon is the base form for its species,
886 e.g. Land Shaymin.
887 """
888
889 return self.unique_form is None or self.unique_form.is_default
890
891 @property
892 def form_name(self):
893 u"""Returns the Pokémon's form name if it represents a particular form
894 and that form has a name, or None otherwise.
895 """
896
897 # If self.unique_form is None, the short-circuit "and" will go ahead
898 # and return that. Otherwise, it'll return the form's name, which may
899 # also be None.
900 return self.unique_form and self.unique_form.name
901
902 @property
903 def full_name(self):
904 u"""Returns the Pokémon's name, including its form if applicable."""
905
906 if self.form_name:
907 return '{0} {1}'.format(self.form_name, self.name)
908 else:
909 return self.name
910
911 @property
912 def normal_form(self):
913 u"""Returns the normal form for this Pokémon; i.e., this will return
914 regular Deoxys when called on any Deoxys form.
915 """
916
917 if self.unique_form:
918 return self.unique_form.form_base_pokemon
919 return self
920
921 ### Not forms!
922
923 def stat(self, stat_name):
924 u"""Returns a PokemonStat record for the given stat name (or Stat row
925 object). Uses the normal has-many machinery, so all the stats are
926 effectively cached.
927 """
928 if isinstance(stat_name, Stat):
929 stat_name = stat_name.name
930
931 for pokemon_stat in self.stats:
932 if pokemon_stat.stat.name == stat_name:
933 return pokemon_stat
934
935 raise KeyError(u'No stat named %s' % stat_name)
936
937 @property
938 def better_damage_class(self):
939 u"""Returns the MoveDamageClass that this Pokémon is best suited for,
940 based on its attack stats.
941
942 If the attack stats are about equal (within 5), returns None. The
943 value None, not the damage class called 'None'.
944 """
945 phys = self.stat(u'Attack')
946 spec = self.stat(u'Special Attack')
947
948 diff = phys.base_stat - spec.base_stat
949
950 if diff > 5:
951 return phys.stat.damage_class
952 elif diff < -5:
953 return spec.stat.damage_class
954 else:
955 return None
956
957 class PokemonAbility(TableBase):
958 u"""Maps an ability to a Pokémon that can have it
959 """
960 __tablename__ = 'pokemon_abilities'
961 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False,
962 info=dict(description=u"ID of the Pokémon"))
963 ability_id = Column(Integer, ForeignKey('abilities.id'), nullable=False,
964 info=dict(description=u"ID of the ability"))
965 # XXX having both a method and a slot is kind of gross. "slot" is a
966 # misnomer, anyway: duplicate abilities don't appear in slot 2.
967 # Probably should replace that with "order".
968 is_dream = Column(Boolean, nullable=False, index=True,
969 info=dict(description=u"Whether this is a Dream World ability"))
970 slot = Column(Integer, primary_key=True, nullable=False, autoincrement=False,
971 info=dict(description=u"The ability slot, i.e. 1 or 2 for gen. IV"))
972
973 class PokemonColor(TableBase):
974 u"""The "Pokédex color" of a Pokémon species. Usually based on the Pokémon's color.
975 """
976 __tablename__ = 'pokemon_colors'
977 id = Column(Integer, primary_key=True, nullable=False, autoincrement=False,
978 info=dict(description=u"ID of the Pokémon"))
979 name = Column(Unicode(6), nullable=False,
980 info=dict(description=u"The English name of the color", official=True, format='identifier'))
981
982 class PokemonDexNumber(TableBase):
983 u"""The number of a Pokémon in a particular Pokédex (e.g. Jigglypuff is #138 in Hoenn's 'dex)
984 """
985 __tablename__ = 'pokemon_dex_numbers'
986 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False,
987 info=dict(description=u"ID of the Pokémon"))
988 pokedex_id = Column(Integer, ForeignKey('pokedexes.id'), primary_key=True, nullable=False, autoincrement=False,
989 info=dict(description=u"ID of the Pokédex"))
990 pokedex_number = Column(Integer, nullable=False,
991 info=dict(description=u"Number of the Pokémon in that the Pokédex"))
992
993 class PokemonEggGroup(TableBase):
994 u"""Maps an Egg group to a Pokémon; each Pokémon belongs to one or two egg groups
995 """
996 __tablename__ = 'pokemon_egg_groups'
997 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False,
998 info=dict(description=u"ID of the Pokémon"))
999 egg_group_id = Column(Integer, ForeignKey('egg_groups.id'), primary_key=True, nullable=False, autoincrement=False,
1000 info=dict(description=u"ID of the egg group"))
1001
1002 class PokemonEvolution(TableBase):
1003 u"""A required action ("trigger") and the conditions under which the trigger
1004 must occur to cause a Pokémon to evolve.
1005
1006 Any condition may be null if it does not apply for a particular Pokémon.
1007 """
1008 __tablename__ = 'pokemon_evolution'
1009 from_pokemon_id = Column(Integer, ForeignKey('pokemon.id'), nullable=False,
1010 info=dict(description=u"The ID of the pre-evolution Pokémon."))
1011 to_pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False,
1012 info=dict(description=u"The ID of the post-evolution Pokémon."))
1013 evolution_trigger_id = Column(Integer, ForeignKey('evolution_triggers.id'), nullable=False,
1014 info=dict(description=u"The ID of the evolution trigger."))
1015 trigger_item_id = Column(Integer, ForeignKey('items.id'), nullable=True,
1016 info=dict(description=u"The ID of the item that must be used on the Pokémon."))
1017 minimum_level = Column(Integer, nullable=True,
1018 info=dict(description=u"The minimum level for the Pokémon."))
1019 gender = Column(Enum('male', 'female', name='pokemon_evolution_gender'), nullable=True,
1020 info=dict(description=u"The Pokémon's required gender, or None if gender doesn't matter"))
1021 location_id = Column(Integer, ForeignKey('locations.id'), nullable=True,
1022 info=dict(description=u"The ID of the location the evolution must be triggered at."))
1023 held_item_id = Column(Integer, ForeignKey('items.id'), nullable=True,
1024 info=dict(description=u"The ID of the item the Pokémon must hold."))
1025 time_of_day = Column(Enum('day', 'night', name='pokemon_evolution_time_of_day'), nullable=True,
1026 info=dict(description=u"The required time of day."))
1027 known_move_id = Column(Integer, ForeignKey('moves.id'), nullable=True,
1028 info=dict(description=u"The ID of the move the Pokémon must know."))
1029 minimum_happiness = Column(Integer, nullable=True,
1030 info=dict(description=u"The minimum happiness value the Pokémon must have."))
1031 minimum_beauty = Column(Integer, nullable=True,
1032 info=dict(description=u"The minimum Beauty value the Pokémon must have."))
1033 relative_physical_stats = Column(Integer, nullable=True,
1034 info=dict(description=u"The required relation between the Pokémon's Attack and Defense stats, as sgn(atk-def)."))
1035 party_pokemon_id = Column(Integer, ForeignKey('pokemon.id'), nullable=True,
1036 info=dict(description=u"The ID of the Pokémon that must be present in the party."))
1037 trade_pokemon_id = Column(Integer, ForeignKey('pokemon.id'), nullable=True,
1038 info=dict(description=u"The ID of the Pokémon for which this Pokémon must be traded."))
1039
1040 class PokemonFlavorText(TableBase):
1041 u"""In-game Pokédex descrption of a Pokémon.
1042 """
1043 __tablename__ = 'pokemon_flavor_text'
1044 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False,
1045 info=dict(description=u"ID of the Pokémon"))
1046 version_id = Column(Integer, ForeignKey('versions.id'), primary_key=True, nullable=False, autoincrement=False,
1047 info=dict(description=u"ID of the version that has this flavor text"))
1048 flavor_text = Column(Unicode(255), nullable=False,
1049 info=dict(description=u"ID of the version that has this flavor text", official=True, format='gametext'))
1050
1051 class PokemonForm(TableBase):
1052 u"""An individual form of a Pokémon.
1053
1054 Pokémon that do not have separate forms are still given a single row to
1055 represent their single form.
1056 """
1057 __tablename__ = 'pokemon_forms'
1058 __singlename__ = 'pokemon_form'
1059 id = Column(Integer, primary_key=True, nullable=False,
1060 info=dict(description=u'A unique ID for this form.'))
1061 name = Column(Unicode(16), nullable=True,
1062 info=dict(description=u"This form's name, e.g. \"Plant\" for Plant Cloak Burmy.", official=True, format='plaintext'))
1063 form_base_pokemon_id = Column(Integer, ForeignKey('pokemon.id'), nullable=False, autoincrement=False,
1064 info=dict(description=u'The ID of the base Pokémon for this form.'))
1065 unique_pokemon_id = Column(Integer, ForeignKey('pokemon.id'), autoincrement=False,
1066 info=dict(description=u'The ID of a Pokémon that represents specifically this form, for Pokémon with functionally-different forms like Wormadam.'))
1067 introduced_in_version_group_id = Column(Integer, ForeignKey('version_groups.id'), autoincrement=False,
1068 info=dict(description=u'The ID of the version group in which this form first appeared.'))
1069 is_default = Column(Boolean, nullable=False,
1070 info=dict(description=u'Set for exactly one form used as the default for each species.'))
1071 order = Column(Integer, nullable=False, autoincrement=False,
1072 info=dict(description=u'The order in which forms should be sorted. Multiple forms may have equal order, in which case they should fall back on sorting by name.'))
1073
1074 @property
1075 def pokemon(self):
1076 u"""Returns the Pokémon for this form, using the form base as fallback.
1077 """
1078
1079 return self.unique_pokemon or self.form_base_pokemon
1080
1081 @property
1082 def full_name(self):
1083 u"""Returns the full name of this form, e.g. "Plant Cloak"."""
1084
1085 if not self.name:
1086 return None
1087 elif self.form_group and self.form_group.term:
1088 return '{0} {1}'.format(self.name, self.form_group.term)
1089 else:
1090 return self.name
1091
1092 @property
1093 def pokemon_name(self):
1094 u"""Returns the name of this Pokémon with this form, e.g. "Plant
1095 Burmy".
1096 """
1097
1098 if self.name:
1099 return '{0} {1}'.format(self.name, self.form_base_pokemon.name)
1100 else:
1101 return self.form_base_pokemon.name
1102
1103 class PokemonFormGroup(TableBase):
1104 u"""Information about a Pokémon's forms as a group."""
1105 __tablename__ = 'pokemon_form_groups'
1106 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False,
1107 info=dict(description=u"ID of the base form Pokémon"))
1108 term = Column(Unicode(16), nullable=True,
1109 info=dict(description=u"The term for this Pokémon's forms, e.g. \"Cloak\" for Burmy or \"Forme\" for Deoxys.", official=True, format='plaintext'))
1110 is_battle_only = Column(Boolean, nullable=False,
1111 info=dict(description=u"Set iff the forms only change in battle"))
1112 description = Column(markdown.MarkdownColumn(1024), nullable=False,
1113 info=dict(description=u"English description of how the forms work", format='markdown'))
1114
1115 class PokemonFormPokeathlonStat(TableBase):
1116 u"""A Pokémon form's performance in one Pokéathlon stat."""
1117 __tablename__ = 'pokemon_form_pokeathlon_stats'
1118 pokemon_form_id = Column(Integer, ForeignKey('pokemon_forms.id'), primary_key=True, nullable=False, autoincrement=False,
1119 info=dict(description=u'The ID of the Pokémon form.'))
1120 pokeathlon_stat_id = Column(Integer, ForeignKey('pokeathlon_stats.id'), primary_key=True, nullable=False, autoincrement=False,
1121 info=dict(description=u'The ID of the Pokéathlon stat.'))
1122 minimum_stat = Column(Integer, nullable=False, autoincrement=False,
1123 info=dict(description=u'The minimum value for this stat for this Pokémon form.'))
1124 base_stat = Column(Integer, nullable=False, autoincrement=False,
1125 info=dict(description=u'The default value for this stat for this Pokémon form.'))
1126 maximum_stat = Column(Integer, nullable=False, autoincrement=False,
1127 info=dict(description=u'The maximum value for this stat for this Pokémon form.'))
1128
1129 class PokemonHabitat(TableBase):
1130 u"""The habitat of a Pokémon, as given in the FireRed/LeafGreen version Pokédex
1131 """
1132 __tablename__ = 'pokemon_habitats'
1133 id = Column(Integer, primary_key=True, nullable=False, autoincrement=False,
1134 info=dict(description=u"A numeric ID"))
1135 name = Column(Unicode(16), nullable=False,
1136 info=dict(description=u"The English name of the habitat", official=True, format='plaintext'))
1137
1138 class PokemonInternalID(TableBase):
1139 u"""The number of a Pokémon a game uses internally
1140 """
1141 __tablename__ = 'pokemon_internal_ids'
1142 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, autoincrement=False, nullable=False,
1143 info=dict(description=u"Database ID of the Pokémon"))
1144 generation_id = Column(Integer, ForeignKey('generations.id'), primary_key=True, autoincrement=False, nullable=False,
1145 info=dict(description=u"Database ID of the generation"))
1146 internal_id = Column(Integer, nullable=False,
1147 info=dict(description=u"Internal ID the generation's games use for the Pokémon"))
1148
1149 class PokemonItem(TableBase):
1150 u"""Record of an item a Pokémon can hold in the wild
1151 """
1152 __tablename__ = 'pokemon_items'
1153 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False,
1154 info=dict(description=u"ID of the Pokémon"))
1155 version_id = Column(Integer, ForeignKey('versions.id'), primary_key=True, nullable=False, autoincrement=False,
1156 info=dict(description=u"ID of the version this applies to"))
1157 item_id = Column(Integer, ForeignKey('items.id'), primary_key=True, nullable=False, autoincrement=False,
1158 info=dict(description=u"ID of the item"))
1159 rarity = Column(Integer, nullable=False,
1160 info=dict(description=u"Chance of the Pokémon holding the item, in percent"))
1161
1162 class PokemonMove(TableBase):
1163 u"""Record of a move a Pokémon can learn
1164 """
1165 __tablename__ = 'pokemon_moves'
1166 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), nullable=False, index=True,
1167 info=dict(description=u"ID of the Pokémon"))
1168 version_group_id = Column(Integer, ForeignKey('version_groups.id'), nullable=False, index=True,
1169 info=dict(description=u"ID of the version group this applies to"))
1170 move_id = Column(Integer, ForeignKey('moves.id'), nullable=False, index=True,
1171 info=dict(description=u"ID of the move"))
1172 pokemon_move_method_id = Column(Integer, ForeignKey('pokemon_move_methods.id'), nullable=False, index=True,
1173 info=dict(description=u"ID of the method this move is learned by"))
1174 level = Column(Integer, nullable=True, index=True,
1175 info=dict(description=u"Level the move is learned at, if applicable"))
1176 order = Column(Integer, nullable=True,
1177 info=dict(description=u"A sort key to produce the correct ordering when all else is equal")) # XXX: This needs a better description
1178
1179 __table_args__ = (
1180 PrimaryKeyConstraint('pokemon_id', 'version_group_id', 'move_id', 'pokemon_move_method_id', 'level'),
1181 {},
1182 )
1183
1184 class PokemonMoveMethod(TableBase):
1185 u"""A method a move can be learned by, such as "Level up" or "Tutor".
1186 """
1187 __tablename__ = 'pokemon_move_methods'
1188 id = Column(Integer, primary_key=True, nullable=False, autoincrement=False,
1189 info=dict(description=u"A numeric ID"))
1190 name = Column(Unicode(64), nullable=False,
1191 info=dict(description=u"An English name of the method", format='plaintext'))
1192 description = Column(Unicode(255), nullable=False,
1193 info=dict(description=u"A detailed description of how the method works", format='plaintext'))
1194
1195 class PokemonName(TableBase):
1196 u"""A non-English name of a Pokémon.
1197 """
1198 __tablename__ = 'pokemon_names'
1199 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False,
1200 info=dict(description=u"ID of the Pokémon"))
1201 language_id = Column(Integer, ForeignKey('languages.id'), primary_key=True, nullable=False, autoincrement=False,
1202 info=dict(description=u"ID of the language"))
1203 name = Column(Unicode(16), nullable=False,
1204 info=dict(description=u"Name of the Pokémon in the language", foreign=True, format='plaintext'))
1205
1206 class PokemonShape(TableBase):
1207 u"""The shape of a Pokémon's body, as used in generation IV Pokédexes.
1208 """
1209 __tablename__ = 'pokemon_shapes'
1210 id = Column(Integer, primary_key=True, nullable=False,
1211 info=dict(description=u"A numeric ID"))
1212 name = Column(Unicode(24), nullable=False,
1213 info=dict(description=u"A boring English name of the body shape", format='plaintext'))
1214 awesome_name = Column(Unicode(16), nullable=False,
1215 info=dict(description=u"A splendiferous, technically English, name of the body shape", format='plaintext'))
1216
1217 class PokemonStat(TableBase):
1218 u"""A stat value of a Pokémon
1219 """
1220 __tablename__ = 'pokemon_stats'
1221 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False,
1222 info=dict(description=u"ID of the Pokémon"))
1223 stat_id = Column(Integer, ForeignKey('stats.id'), primary_key=True, nullable=False, autoincrement=False,
1224 info=dict(description=u"ID of the stat"))
1225 base_stat = Column(Integer, nullable=False,
1226 info=dict(description=u"The base stat"))
1227 effort = Column(Integer, nullable=False,
1228 info=dict(description=u"The effort increase in this stat gained when this Pokémon is defeated"))
1229
1230 class PokemonType(TableBase):
1231 u"""Maps a type to a Pokémon. Each Pokémon has 1 or 2 types.
1232 """
1233 __tablename__ = 'pokemon_types'
1234 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False,
1235 info=dict(description=u"ID of the Pokémon"))
1236 type_id = Column(Integer, ForeignKey('types.id'), nullable=False,
1237 info=dict(description=u"ID of the type"))
1238 slot = Column(Integer, primary_key=True, nullable=False, autoincrement=False,
1239 info=dict(description=u"The type's slot, 1 or 2, used to sort types if there are two of them"))
1240
1241 class Region(TableBase):
1242 u"""Major areas of the world: Kanto, Johto, etc.
1243 """
1244 __tablename__ = 'regions'
1245 id = Column(Integer, primary_key=True, nullable=False,
1246 info=dict(description=u"A numeric ID"))
1247 name = Column(Unicode(16), nullable=False,
1248 info=dict(description=u"The English name of the region", official=True, format='plaintext'))
1249
1250 class Stat(TableBase):
1251 u"""A Stat, such as Attack or Speed
1252 """
1253 __tablename__ = 'stats'
1254 id = Column(Integer, primary_key=True, nullable=False,
1255 info=dict(description=u"A numeric ID"))
1256 damage_class_id = Column(Integer, ForeignKey('move_damage_classes.id'), nullable=True,
1257 info=dict(description=u"For offensive and defensive stats, the damage this stat relates to; otherwise None (the NULL value)"))
1258 name = Column(Unicode(16), nullable=False,
1259 info=dict(description=u"The English name of the stat", official=True, format='plaintext'))
1260
1261 class StatHint(TableBase):
1262 u"""Flavor text for genes that appears in a Pokémon's summary. Sometimes
1263 called "characteristics".
1264 """
1265 __tablename__ = 'stat_hints'
1266 id = Column(Integer, primary_key=True, nullable=False)
1267 stat_id = Column(Integer, ForeignKey('stats.id'), nullable=False)
1268 gene_mod_5 = Column(Integer, nullable=False, index=True)
1269 text = Column(Unicode(24), nullable=False, index=True, unique=True,
1270 info=dict(description=u"The English text displayed", official=True, format='plaintext'))
1271
1272 class SuperContestCombo(TableBase):
1273 u"""Combo of two moves in a Super Contest.
1274 """
1275 __tablename__ = 'super_contest_combos'
1276 first_move_id = Column(Integer, ForeignKey('moves.id'), primary_key=True, nullable=False, autoincrement=False,
1277 info=dict(description=u"The ID of the first move in the combo."))
1278 second_move_id = Column(Integer, ForeignKey('moves.id'), primary_key=True, nullable=False, autoincrement=False,
1279 info=dict(description=u"The ID of the second and last move."))
1280
1281 class SuperContestEffect(TableBase):
1282 u"""An effect a move can have when used in the Super Contest
1283 """
1284 __tablename__ = 'super_contest_effects'
1285 id = Column(Integer, primary_key=True, nullable=False,
1286 info=dict(description=u"This effect's unique ID."))
1287 appeal = Column(SmallInteger, nullable=False,
1288 info=dict(description=u"The number of hearts the user gains."))
1289 flavor_text = Column(Unicode(64), nullable=False,
1290 info=dict(description=u"An English description of the effect.", format='plaintext'))
1291
1292 class TypeEfficacy(TableBase):
1293 u"""The damage multiplier used when a move of a particular type damages a
1294 Pokémon of a particular other type.
1295 """
1296 __tablename__ = 'type_efficacy'
1297 damage_type_id = Column(Integer, ForeignKey('types.id'), primary_key=True, nullable=False, autoincrement=False,
1298 info=dict(description=u"The ID of the damaging type."))
1299 target_type_id = Column(Integer, ForeignKey('types.id'), primary_key=True, nullable=False, autoincrement=False,
1300 info=dict(description=u"The ID of the defending Pokémon's type."))
1301 damage_factor = Column(Integer, nullable=False,
1302 info=dict(description=u"The multiplier, as a percentage of damage inflicted."))
1303
1304 class Type(TableBase):
1305 u"""Any of the elemental types Pokémon and moves can have."""
1306 __tablename__ = 'types'
1307 __singlename__ = 'type'
1308 id = Column(Integer, primary_key=True, nullable=False,
1309 info=dict(description=u"A unique ID for this type."))
1310 name = Column(Unicode(8), nullable=False,
1311 info=dict(description=u"This type's English name.", format='plaintext'))
1312 abbreviation = Column(Unicode(3), nullable=False,
1313 info=dict(description=u"An arbitrary 3-letter abbreviation of this type.", format='plaintext')) # XXX: Or is it not arbitrary?
1314 generation_id = Column(Integer, ForeignKey('generations.id'), nullable=False,
1315 info=dict(description=u"The ID of the generation this type first appeared in."))
1316 damage_class_id = Column(Integer, ForeignKey('move_damage_classes.id'), nullable=True,
1317 info=dict(description=u"The ID of the damage class this type's moves had before Generation IV, null if not applicable (e.g. ???)."))
1318
1319 class TypeName(TableBase):
1320 u"""An official non-English name of an elemental type."""
1321 __tablename__ = 'type_names'
1322 type_id = Column(Integer, ForeignKey('types.id'), primary_key=True, nullable=False, autoincrement=False,
1323 info=dict(description=u"The ID of the type."))
1324 language_id = Column(Integer, ForeignKey('languages.id'), primary_key=True, nullable=False, autoincrement=False,
1325 info=dict(description=u"The ID of the language."))
1326 name = Column(Unicode(16), nullable=False,
1327 info=dict(description=u"The name of the type in this language.", foreign=True, format='plaintext'))
1328
1329 class VersionGroup(TableBase):
1330 u"""A group of versions, containing either two paired versions (such as Red
1331 and Blue) or a single game (such as Yellow.)
1332 """
1333 __tablename__ = 'version_groups'
1334 id = Column(Integer, primary_key=True, nullable=False,
1335 info=dict(description=u"This version group's unique ID."))
1336 generation_id = Column(Integer, ForeignKey('generations.id'), nullable=False,
1337 info=dict(description=u"The ID of the generation the games in this group belong to."))
1338 pokedex_id = Column(Integer, ForeignKey('pokedexes.id'), nullable=False,
1339 info=dict(description=u"The ID of the regional Pokédex used in this version group."))
1340
1341 class VersionGroupRegion(TableBase):
1342 u"""Maps a version group to a region that appears in it."""
1343 __tablename__ = 'version_group_regions'
1344 version_group_id = Column(Integer, ForeignKey('version_groups.id'), primary_key=True, nullable=False,
1345 info=dict(description=u"The ID of the version group."))
1346 region_id = Column(Integer, ForeignKey('regions.id'), primary_key=True, nullable=False,
1347 info=dict(description=u"The ID of the region."))
1348
1349 class Version(TableBase):
1350 u"""An individual main-series Pokémon game."""
1351 __tablename__ = 'versions'
1352 id = Column(Integer, primary_key=True, nullable=False,
1353 info=dict(description=u"A unique ID for this version."))
1354 version_group_id = Column(Integer, ForeignKey('version_groups.id'), nullable=False,
1355 info=dict(description=u"The ID of the version group this game belongs to."))
1356 name = Column(Unicode(32), nullable=False,
1357 info=dict(description=u'The English "version" name for this game, e.g. "Red", without the rest of the title.', official=True, format='plaintext'))
1358
1359
1360 ### Relations down here, to avoid ordering problems
1361 Ability.changelog = relation(AbilityChangelog,
1362 order_by=AbilityChangelog.changed_in_version_group_id.desc(),
1363 backref='ability',
1364 )
1365 Ability.flavor_text = relation(AbilityFlavorText, order_by=AbilityFlavorText.version_group_id, backref='ability')
1366 Ability.foreign_names = relation(AbilityName, backref='ability')
1367 Ability.generation = relation(Generation, backref='abilities')
1368 Ability.all_pokemon = relation(Pokemon,
1369 secondary=PokemonAbility.__table__,
1370 order_by=Pokemon.order,
1371 back_populates='all_abilities',
1372 )
1373 Ability.pokemon = relation(Pokemon,
1374 secondary=PokemonAbility.__table__,
1375 primaryjoin=and_(
1376 PokemonAbility.ability_id == Ability.id,
1377 PokemonAbility.is_dream == False
1378 ),
1379 order_by=Pokemon.order,
1380 back_populates='abilities',
1381 )
1382 Ability.dream_pokemon = relation(Pokemon,
1383 secondary=PokemonAbility.__table__,
1384 primaryjoin=and_(
1385 PokemonAbility.ability_id == Ability.id,
1386 PokemonAbility.is_dream == True
1387 ),
1388 order_by=Pokemon.order,
1389 back_populates='dream_ability',
1390 )
1391
1392 AbilityChangelog.changed_in = relation(VersionGroup, backref='ability_changelog')
1393
1394 AbilityFlavorText.version_group = relation(VersionGroup)
1395
1396 AbilityName.language = relation(Language)
1397
1398 Berry.berry_firmness = relation(BerryFirmness, backref='berries')
1399 Berry.firmness = association_proxy('berry_firmness', 'name')
1400 Berry.flavors = relation(BerryFlavor, order_by=BerryFlavor.contest_type_id, backref='berry')
1401 Berry.natural_gift_type = relation(Type)
1402
1403 BerryFlavor.contest_type = relation(ContestType)
1404
1405 ContestCombo.first = relation(Move, primaryjoin=ContestCombo.first_move_id==Move.id,
1406 backref='contest_combo_first')
1407 ContestCombo.second = relation(Move, primaryjoin=ContestCombo.second_move_id==Move.id,
1408 backref='contest_combo_second')
1409
1410 Encounter.location_area = relation(LocationArea, backref='encounters')
1411 Encounter.pokemon = relation(Pokemon, backref='encounters')
1412 Encounter.version = relation(Version, backref='encounters')
1413 Encounter.slot = relation(EncounterSlot, backref='encounters')
1414
1415 EncounterConditionValue.condition = relation(EncounterCondition, backref='values')
1416
1417 Encounter.condition_value_map = relation(EncounterConditionValueMap, backref='encounter')
1418 Encounter.condition_values = association_proxy('condition_value_map', 'condition_value')
1419 EncounterConditionValueMap.condition_value = relation(EncounterConditionValue,
1420 backref='encounter_map')
1421
1422 EncounterSlot.terrain = relation(EncounterTerrain, backref='slots')
1423 EncounterSlot.version_group = relation(VersionGroup)
1424
1425 EvolutionChain.growth_rate = relation(GrowthRate, backref='evolution_chains')
1426 EvolutionChain.baby_trigger_item = relation(Item, backref='evolution_chains')
1427 EvolutionChain.pokemon = relation(Pokemon, order_by=Pokemon.order, back_populates='evolution_chain')
1428
1429 Experience.growth_rate = relation(GrowthRate, backref='experience_table')
1430
1431 Generation.canonical_pokedex = relation(Pokedex, backref='canonical_for_generation')
1432 Generation.versions = relation(Version, secondary=VersionGroup.__table__)
1433 Generation.main_region = relation(Region)
1434
1435 GrowthRate.max_experience_obj = relation(Experience, primaryjoin=and_(Experience.growth_rate_id == GrowthRate.id, Experience.level == 100), uselist=False)
1436 GrowthRate.max_experience = association_proxy('max_experience_obj', 'experience')
1437
1438 Item.berry = relation(Berry, uselist=False, backref='item')
1439 Item.flags = relation(ItemFlag, secondary=ItemFlagMap.__table__)
1440 Item.flavor_text = relation(ItemFlavorText, order_by=ItemFlavorText.version_group_id.asc(), backref='item')
1441 Item.fling_effect = relation(ItemFlingEffect, backref='items')
1442 Item.foreign_names = relation(ItemName, backref='item')
1443 Item.machines = relation(Machine, order_by=Machine.version_group_id.asc())
1444 Item.category = relation(ItemCategory)
1445 Item.pocket = association_proxy('category', 'pocket')
1446
1447 ItemCategory.items = relation(Item, order_by=Item.name)
1448 ItemCategory.pocket = relation(ItemPocket)
1449
1450 ItemFlavorText.version_group = relation(VersionGroup)
1451
1452 ItemInternalID.item = relation(Item, backref='internal_ids')
1453 ItemInternalID.generation = relation(Generation)
1454
1455 ItemName.language = relation(Language)
1456
1457 ItemPocket.categories = relation(ItemCategory, order_by=ItemCategory.name)
1458
1459 Location.region = relation(Region, backref='locations')
1460
1461 LocationArea.location = relation(Location, backref='areas')
1462
1463 LocationInternalID.location = relation(Location, backref='internal_ids')
1464 LocationInternalID.generation = relation(Generation)
1465
1466 Machine.item = relation(Item)
1467 Machine.version_group = relation(VersionGroup)
1468
1469 Move.changelog = relation(MoveChangelog,
1470 order_by=MoveChangelog.changed_in_version_group_id.desc(),
1471 backref='move',
1472 )
1473 Move.contest_effect = relation(ContestEffect, backref='moves')
1474 Move.contest_combo_next = association_proxy('contest_combo_first', 'second')
1475 Move.contest_combo_prev = association_proxy('contest_combo_second', 'first')
1476 Move.contest_type = relation(ContestType, backref='moves')
1477 Move.damage_class = relation(MoveDamageClass, backref='moves')
1478 Move.flags = association_proxy('move_flags', 'flag')
1479 Move.flavor_text = relation(MoveFlavorText, order_by=MoveFlavorText.version_group_id, backref='move')
1480 Move.foreign_names = relation(MoveName, backref='move')
1481 Move.generation = relation(Generation, backref='moves')
1482 Move.machines = relation(Machine, backref='move')
1483 Move.meta = relation(MoveMeta, uselist=False, backref='move')
1484 Move.meta_stat_changes = relation(MoveMetaStatChange)
1485 Move.move_effect = relation(MoveEffect, backref='moves')
1486 Move.move_flags = relation(MoveFlag, backref='move')
1487 Move.super_contest_effect = relation(SuperContestEffect, backref='moves')
1488 Move.super_contest_combo_next = association_proxy('super_contest_combo_first', 'second')
1489 Move.super_contest_combo_prev = association_proxy('super_contest_combo_second', 'first')
1490 Move.target = relation(MoveTarget, backref='moves')
1491 Move.type = relation(Type, back_populates='moves')
1492
1493 Move.effect = markdown.MoveEffectProperty('effect')
1494 Move.short_effect = markdown.MoveEffectProperty('short_effect')
1495
1496 MoveChangelog.changed_in = relation(VersionGroup, backref='move_changelog')
1497 MoveChangelog.move_effect = relation(MoveEffect, backref='move_changelog')
1498 MoveChangelog.type = relation(Type, backref='move_changelog')
1499
1500 MoveChangelog.effect = markdown.MoveEffectProperty('effect')
1501 MoveChangelog.short_effect = markdown.MoveEffectProperty('short_effect')
1502
1503 MoveEffect.category_map = relation(MoveEffectCategoryMap)
1504 MoveEffect.categories = association_proxy('category_map', 'category')
1505 MoveEffect.changelog = relation(MoveEffectChangelog,
1506 order_by=MoveEffectChangelog.changed_in_version_group_id.desc(),
1507 backref='move_effect',
1508 )
1509 MoveEffectCategoryMap.category = relation(MoveEffectCategory)
1510
1511 MoveEffectChangelog.changed_in = relation(VersionGroup, backref='move_effect_changelog')
1512
1513 MoveFlag.flag = relation(MoveFlagType)
1514
1515 MoveFlavorText.version_group = relation(VersionGroup)
1516
1517 MoveMeta.category = relation(MoveMetaCategory, backref='move_meta')
1518 MoveMeta.ailment = relation(MoveMetaAilment, backref='move_meta')
1519
1520 MoveMetaStatChange.stat = relation(Stat, backref='move_meta_stat_changes')
1521
1522 MoveName.language = relation(Language)
1523
1524 Nature.foreign_names = relation(NatureName, backref='nature')
1525 Nature.decreased_stat = relation(Stat, primaryjoin=Nature.decreased_stat_id==Stat.id,
1526 backref='decreasing_natures')
1527 Nature.increased_stat = relation(Stat, primaryjoin=Nature.increased_stat_id==Stat.id,
1528 backref='increasing_natures')
1529 Nature.hates_flavor = relation(ContestType, primaryjoin=Nature.hates_flavor_id==ContestType.id,
1530 backref='hating_natures')
1531 Nature.likes_flavor = relation(ContestType, primaryjoin=Nature.likes_flavor_id==ContestType.id,
1532 backref='liking_natures')
1533 Nature.battle_style_preferences = relation(NatureBattleStylePreference,
1534 order_by=NatureBattleStylePreference.move_battle_style_id,
1535 backref='nature')
1536 Nature.pokeathlon_effects = relation(NaturePokeathlonStat, order_by=NaturePokeathlonStat.pokeathlon_stat_id)
1537
1538 NatureBattleStylePreference.battle_style = relation(MoveBattleStyle, backref='nature_preferences')
1539
1540 NatureName.language = relation(Language)
1541
1542 NaturePokeathlonStat.pokeathlon_stat = relation(PokeathlonStat, backref='nature_effects')
1543
1544 Pokedex.region = relation(Region, backref='pokedexes')
1545 Pokedex.version_groups = relation(VersionGroup, order_by=VersionGroup.id, back_populates='pokedex')
1546
1547 Pokemon.all_abilities = relation(Ability,
1548 secondary=PokemonAbility.__table__,
1549 order_by=PokemonAbility.slot,
1550 )
1551 Pokemon.abilities = relation(Ability,
1552 secondary=PokemonAbility.__table__,
1553 primaryjoin=and_(
1554 Pokemon.id == PokemonAbility.pokemon_id,
1555 PokemonAbility.is_dream == False,
1556 ),
1557 order_by=PokemonAbility.slot,
1558 )
1559 Pokemon.dream_ability = relation(Ability,
1560 secondary=PokemonAbility.__table__,
1561 primaryjoin=and_(
1562 Pokemon.id == PokemonAbility.pokemon_id,
1563 PokemonAbility.is_dream == True,
1564 ),
1565 uselist=False,
1566 )
1567 Pokemon.pokemon_color = relation(PokemonColor, backref='pokemon')
1568 Pokemon.color = association_proxy('pokemon_color', 'name')
1569 Pokemon.dex_numbers = relation(PokemonDexNumber, order_by=PokemonDexNumber.pokedex_id.asc(), backref='pokemon')
1570 Pokemon.egg_groups = relation(EggGroup, secondary=PokemonEggGroup.__table__,
1571 order_by=PokemonEggGroup.egg_group_id,
1572 backref=backref('pokemon', order_by=Pokemon.order))
1573 Pokemon.evolution_chain = relation(EvolutionChain, back_populates='pokemon')
1574 Pokemon.child_pokemon = relation(Pokemon,
1575 primaryjoin=Pokemon.id==PokemonEvolution.from_pokemon_id,
1576 secondary=PokemonEvolution.__table__,
1577 secondaryjoin=PokemonEvolution.to_pokemon_id==Pokemon.id,
1578 backref=backref('parent_pokemon', uselist=False),
1579 )
1580 Pokemon.flavor_text = relation(PokemonFlavorText, order_by=PokemonFlavorText.version_id.asc(), backref='pokemon')
1581 Pokemon.foreign_names = relation(PokemonName, backref='pokemon')
1582 Pokemon.forms = relation(PokemonForm, primaryjoin=Pokemon.id==PokemonForm.form_base_pokemon_id,
1583 order_by=(PokemonForm.order.asc(), PokemonForm.name.asc()))
1584 Pokemon.default_form = relation(PokemonForm,
1585 primaryjoin=and_(Pokemon.id==PokemonForm.form_base_pokemon_id, PokemonForm.is_default==True),
1586 uselist=False,
1587 )
1588 Pokemon.pokemon_habitat = relation(PokemonHabitat, backref='pokemon')
1589 Pokemon.habitat = association_proxy('pokemon_habitat', 'name')
1590 Pokemon.items = relation(PokemonItem, backref='pokemon')
1591 Pokemon.generation = relation(Generation, backref='pokemon')
1592 Pokemon.shape = relation(PokemonShape, backref='pokemon')
1593 Pokemon.stats = relation(PokemonStat, backref='pokemon', order_by=PokemonStat.stat_id.asc())
1594 Pokemon.types = relation(Type, secondary=PokemonType.__table__,
1595 order_by=PokemonType.slot.asc(),
1596 back_populates='pokemon')
1597
1598 PokemonDexNumber.pokedex = relation(Pokedex)
1599
1600 PokemonEvolution.from_pokemon = relation(Pokemon,
1601 primaryjoin=PokemonEvolution.from_pokemon_id==Pokemon.id,
1602 backref='child_evolutions',
1603 )
1604 PokemonEvolution.to_pokemon = relation(Pokemon,
1605 primaryjoin=PokemonEvolution.to_pokemon_id==Pokemon.id,
1606 backref=backref('parent_evolution', uselist=False),
1607 )
1608 PokemonEvolution.child_evolutions = relation(PokemonEvolution,
1609 primaryjoin=PokemonEvolution.from_pokemon_id==PokemonEvolution.to_pokemon_id,
1610 foreign_keys=[PokemonEvolution.to_pokemon_id],
1611 backref=backref('parent_evolution',
1612 remote_side=[PokemonEvolution.from_pokemon_id],
1613 uselist=False,
1614 ),
1615 )
1616 PokemonEvolution.trigger = relation(EvolutionTrigger, backref='evolutions')
1617 PokemonEvolution.trigger_item = relation(Item,
1618 primaryjoin=PokemonEvolution.trigger_item_id==Item.id,
1619 backref='triggered_evolutions',
1620 )
1621 PokemonEvolution.held_item = relation(Item,
1622 primaryjoin=PokemonEvolution.held_item_id==Item.id,
1623 backref='required_for_evolutions',
1624 )
1625 PokemonEvolution.location = relation(Location, backref='triggered_evolutions')
1626 PokemonEvolution.known_move = relation(Move, backref='triggered_evolutions')
1627 PokemonEvolution.party_pokemon = relation(Pokemon,
1628 primaryjoin=PokemonEvolution.party_pokemon_id==Pokemon.id,
1629 backref='triggered_evolutions',
1630 )
1631 PokemonEvolution.trade_pokemon = relation(Pokemon,
1632 primaryjoin=PokemonEvolution.trade_pokemon_id==Pokemon.id,
1633 )
1634
1635 PokemonFlavorText.version = relation(Version)
1636
1637 PokemonForm.form_base_pokemon = relation(Pokemon, primaryjoin=PokemonForm.form_base_pokemon_id==Pokemon.id)
1638 PokemonForm.unique_pokemon = relation(Pokemon, backref=backref('unique_form', uselist=False),
1639 primaryjoin=PokemonForm.unique_pokemon_id==Pokemon.id)
1640 PokemonForm.version_group = relation(VersionGroup)
1641 PokemonForm.form_group = association_proxy('form_base_pokemon', 'form_group')
1642 PokemonForm.pokeathlon_stats = relation(PokemonFormPokeathlonStat,
1643 order_by=PokemonFormPokeathlonStat.pokeathlon_stat_id,
1644 backref='pokemon_form')
1645
1646 PokemonFormGroup.pokemon = relation(Pokemon, backref=backref('form_group',
1647 uselist=False))
1648
1649 PokemonFormPokeathlonStat.pokeathlon_stat = relation(PokeathlonStat)
1650
1651 PokemonItem.item = relation(Item, backref='pokemon')
1652 PokemonItem.version = relation(Version)
1653
1654 PokemonMove.pokemon = relation(Pokemon, backref='pokemon_moves')
1655 PokemonMove.version_group = relation(VersionGroup)
1656 PokemonMove.machine = relation(Machine, backref='pokemon_moves',
1657 primaryjoin=and_(Machine.version_group_id==PokemonMove.version_group_id,
1658 Machine.move_id==PokemonMove.move_id),
1659 foreign_keys=[Machine.version_group_id, Machine.move_id],
1660 uselist=False)
1661 PokemonMove.move = relation(Move, backref='pokemon_moves')
1662 PokemonMove.method = relation(PokemonMoveMethod)
1663
1664 PokemonName.language = relation(Language, lazy='joined')
1665
1666 PokemonStat.stat = relation(Stat)
1667
1668 # This is technically a has-many; Generation.main_region_id -> Region.id
1669 Region.generation = relation(Generation, uselist=False)
1670 Region.version_group_regions = relation(VersionGroupRegion, backref='region',
1671 order_by='VersionGroupRegion.version_group_id')
1672 Region.version_groups = association_proxy('version_group_regions', 'version_group')
1673
1674 Stat.damage_class = relation(MoveDamageClass, backref='stats')
1675
1676 StatHint.stat = relation(Stat, backref='hints')
1677
1678 SuperContestCombo.first = relation(Move, primaryjoin=SuperContestCombo.first_move_id==Move.id,
1679 backref='super_contest_combo_first')
1680 SuperContestCombo.second = relation(Move, primaryjoin=SuperContestCombo.second_move_id==Move.id,
1681 backref='super_contest_combo_second')
1682
1683 Type.damage_efficacies = relation(TypeEfficacy,
1684 primaryjoin=Type.id
1685 ==TypeEfficacy.damage_type_id,
1686 backref='damage_type')
1687 Type.target_efficacies = relation(TypeEfficacy,
1688 primaryjoin=Type.id
1689 ==TypeEfficacy.target_type_id,
1690 backref='target_type')
1691
1692 Type.generation = relation(Generation, backref='types')
1693 Type.damage_class = relation(MoveDamageClass, backref='types')
1694 Type.foreign_names = relation(TypeName, backref='type')
1695 Type.pokemon = relation(Pokemon, secondary=PokemonType.__table__,
1696 order_by=Pokemon.order,
1697 back_populates='types')
1698 Type.moves = relation(Move, back_populates='type', order_by=Move.name)
1699
1700 TypeName.language = relation(Language)
1701
1702 Version.version_group = relation(VersionGroup, back_populates='versions')
1703 Version.generation = association_proxy('version_group', 'generation')
1704
1705 VersionGroup.versions = relation(Version, order_by=Version.id, back_populates='version_group')
1706 VersionGroup.generation = relation(Generation, backref='version_groups')
1707 VersionGroup.version_group_regions = relation(VersionGroupRegion, backref='version_group')
1708 VersionGroup.regions = association_proxy('version_group_regions', 'region')
1709 VersionGroup.pokedex = relation(Pokedex, back_populates='version_groups')