Add B/W move metadata. #389
[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 SuperContestCombo(TableBase):
1262 u"""Combo of two moves in a Super Contest.
1263 """
1264 __tablename__ = 'super_contest_combos'
1265 first_move_id = Column(Integer, ForeignKey('moves.id'), primary_key=True, nullable=False, autoincrement=False,
1266 info=dict(description=u"The ID of the first move in the combo."))
1267 second_move_id = Column(Integer, ForeignKey('moves.id'), primary_key=True, nullable=False, autoincrement=False,
1268 info=dict(description=u"The ID of the second and last move."))
1269
1270 class SuperContestEffect(TableBase):
1271 u"""An effect a move can have when used in the Super Contest
1272 """
1273 __tablename__ = 'super_contest_effects'
1274 id = Column(Integer, primary_key=True, nullable=False,
1275 info=dict(description=u"This effect's unique ID."))
1276 appeal = Column(SmallInteger, nullable=False,
1277 info=dict(description=u"The number of hearts the user gains."))
1278 flavor_text = Column(Unicode(64), nullable=False,
1279 info=dict(description=u"An English description of the effect.", format='plaintext'))
1280
1281 class TypeEfficacy(TableBase):
1282 u"""The damage multiplier used when a move of a particular type damages a
1283 Pokémon of a particular other type.
1284 """
1285 __tablename__ = 'type_efficacy'
1286 damage_type_id = Column(Integer, ForeignKey('types.id'), primary_key=True, nullable=False, autoincrement=False,
1287 info=dict(description=u"The ID of the damaging type."))
1288 target_type_id = Column(Integer, ForeignKey('types.id'), primary_key=True, nullable=False, autoincrement=False,
1289 info=dict(description=u"The ID of the defending Pokémon's type."))
1290 damage_factor = Column(Integer, nullable=False,
1291 info=dict(description=u"The multiplier, as a percentage of damage inflicted."))
1292
1293 class Type(TableBase):
1294 u"""Any of the elemental types Pokémon and moves can have."""
1295 __tablename__ = 'types'
1296 __singlename__ = 'type'
1297 id = Column(Integer, primary_key=True, nullable=False,
1298 info=dict(description=u"A unique ID for this type."))
1299 name = Column(Unicode(8), nullable=False,
1300 info=dict(description=u"This type's English name.", format='plaintext'))
1301 abbreviation = Column(Unicode(3), nullable=False,
1302 info=dict(description=u"An arbitrary 3-letter abbreviation of this type.", format='plaintext')) # XXX: Or is it not arbitrary?
1303 generation_id = Column(Integer, ForeignKey('generations.id'), nullable=False,
1304 info=dict(description=u"The ID of the generation this type first appeared in."))
1305 damage_class_id = Column(Integer, ForeignKey('move_damage_classes.id'), nullable=True,
1306 info=dict(description=u"The ID of the damage class this type's moves had before Generation IV, null if not applicable (e.g. ???)."))
1307
1308 class TypeName(TableBase):
1309 u"""An official non-English name of an elemental type."""
1310 __tablename__ = 'type_names'
1311 type_id = Column(Integer, ForeignKey('types.id'), primary_key=True, nullable=False, autoincrement=False,
1312 info=dict(description=u"The ID of the type."))
1313 language_id = Column(Integer, ForeignKey('languages.id'), primary_key=True, nullable=False, autoincrement=False,
1314 info=dict(description=u"The ID of the language."))
1315 name = Column(Unicode(16), nullable=False,
1316 info=dict(description=u"The name of the type in this language.", foreign=True, format='plaintext'))
1317
1318 class VersionGroup(TableBase):
1319 u"""A group of versions, containing either two paired versions (such as Red
1320 and Blue) or a single game (such as Yellow.)
1321 """
1322 __tablename__ = 'version_groups'
1323 id = Column(Integer, primary_key=True, nullable=False,
1324 info=dict(description=u"This version group's unique ID."))
1325 generation_id = Column(Integer, ForeignKey('generations.id'), nullable=False,
1326 info=dict(description=u"The ID of the generation the games in this group belong to."))
1327 pokedex_id = Column(Integer, ForeignKey('pokedexes.id'), nullable=False,
1328 info=dict(description=u"The ID of the regional Pokédex used in this version group."))
1329
1330 class VersionGroupRegion(TableBase):
1331 u"""Maps a version group to a region that appears in it."""
1332 __tablename__ = 'version_group_regions'
1333 version_group_id = Column(Integer, ForeignKey('version_groups.id'), primary_key=True, nullable=False,
1334 info=dict(description=u"The ID of the version group."))
1335 region_id = Column(Integer, ForeignKey('regions.id'), primary_key=True, nullable=False,
1336 info=dict(description=u"The ID of the region."))
1337
1338 class Version(TableBase):
1339 u"""An individual main-series Pokémon game."""
1340 __tablename__ = 'versions'
1341 id = Column(Integer, primary_key=True, nullable=False,
1342 info=dict(description=u"A unique ID for this version."))
1343 version_group_id = Column(Integer, ForeignKey('version_groups.id'), nullable=False,
1344 info=dict(description=u"The ID of the version group this game belongs to."))
1345 name = Column(Unicode(32), nullable=False,
1346 info=dict(description=u'The English "version" name for this game, e.g. "Red", without the rest of the title.', official=True, format='plaintext'))
1347
1348
1349 ### Relations down here, to avoid ordering problems
1350 Ability.changelog = relation(AbilityChangelog,
1351 order_by=AbilityChangelog.changed_in_version_group_id.desc(),
1352 backref='ability',
1353 )
1354 Ability.flavor_text = relation(AbilityFlavorText, order_by=AbilityFlavorText.version_group_id, backref='ability')
1355 Ability.foreign_names = relation(AbilityName, backref='ability')
1356 Ability.generation = relation(Generation, backref='abilities')
1357 Ability.all_pokemon = relation(Pokemon,
1358 secondary=PokemonAbility.__table__,
1359 order_by=Pokemon.order,
1360 back_populates='all_abilities',
1361 )
1362 Ability.pokemon = relation(Pokemon,
1363 secondary=PokemonAbility.__table__,
1364 primaryjoin=and_(
1365 PokemonAbility.ability_id == Ability.id,
1366 PokemonAbility.is_dream == False
1367 ),
1368 order_by=Pokemon.order,
1369 back_populates='abilities',
1370 )
1371 Ability.dream_pokemon = relation(Pokemon,
1372 secondary=PokemonAbility.__table__,
1373 primaryjoin=and_(
1374 PokemonAbility.ability_id == Ability.id,
1375 PokemonAbility.is_dream == True
1376 ),
1377 order_by=Pokemon.order,
1378 back_populates='dream_ability',
1379 )
1380
1381 AbilityChangelog.changed_in = relation(VersionGroup, backref='ability_changelog')
1382
1383 AbilityFlavorText.version_group = relation(VersionGroup)
1384
1385 AbilityName.language = relation(Language)
1386
1387 Berry.berry_firmness = relation(BerryFirmness, backref='berries')
1388 Berry.firmness = association_proxy('berry_firmness', 'name')
1389 Berry.flavors = relation(BerryFlavor, order_by=BerryFlavor.contest_type_id, backref='berry')
1390 Berry.natural_gift_type = relation(Type)
1391
1392 BerryFlavor.contest_type = relation(ContestType)
1393
1394 ContestCombo.first = relation(Move, primaryjoin=ContestCombo.first_move_id==Move.id,
1395 backref='contest_combo_first')
1396 ContestCombo.second = relation(Move, primaryjoin=ContestCombo.second_move_id==Move.id,
1397 backref='contest_combo_second')
1398
1399 Encounter.location_area = relation(LocationArea, backref='encounters')
1400 Encounter.pokemon = relation(Pokemon, backref='encounters')
1401 Encounter.version = relation(Version, backref='encounters')
1402 Encounter.slot = relation(EncounterSlot, backref='encounters')
1403
1404 EncounterConditionValue.condition = relation(EncounterCondition, backref='values')
1405
1406 Encounter.condition_value_map = relation(EncounterConditionValueMap, backref='encounter')
1407 Encounter.condition_values = association_proxy('condition_value_map', 'condition_value')
1408 EncounterConditionValueMap.condition_value = relation(EncounterConditionValue,
1409 backref='encounter_map')
1410
1411 EncounterSlot.terrain = relation(EncounterTerrain, backref='slots')
1412 EncounterSlot.version_group = relation(VersionGroup)
1413
1414 EvolutionChain.growth_rate = relation(GrowthRate, backref='evolution_chains')
1415 EvolutionChain.baby_trigger_item = relation(Item, backref='evolution_chains')
1416 EvolutionChain.pokemon = relation(Pokemon, order_by=Pokemon.order, back_populates='evolution_chain')
1417
1418 Experience.growth_rate = relation(GrowthRate, backref='experience_table')
1419
1420 Generation.canonical_pokedex = relation(Pokedex, backref='canonical_for_generation')
1421 Generation.versions = relation(Version, secondary=VersionGroup.__table__)
1422 Generation.main_region = relation(Region)
1423
1424 GrowthRate.max_experience_obj = relation(Experience, primaryjoin=and_(Experience.growth_rate_id == GrowthRate.id, Experience.level == 100), uselist=False)
1425 GrowthRate.max_experience = association_proxy('max_experience_obj', 'experience')
1426
1427 Item.berry = relation(Berry, uselist=False, backref='item')
1428 Item.flags = relation(ItemFlag, secondary=ItemFlagMap.__table__)
1429 Item.flavor_text = relation(ItemFlavorText, order_by=ItemFlavorText.version_group_id.asc(), backref='item')
1430 Item.fling_effect = relation(ItemFlingEffect, backref='items')
1431 Item.foreign_names = relation(ItemName, backref='item')
1432 Item.machines = relation(Machine, order_by=Machine.version_group_id.asc())
1433 Item.category = relation(ItemCategory)
1434 Item.pocket = association_proxy('category', 'pocket')
1435
1436 ItemCategory.items = relation(Item, order_by=Item.name)
1437 ItemCategory.pocket = relation(ItemPocket)
1438
1439 ItemFlavorText.version_group = relation(VersionGroup)
1440
1441 ItemInternalID.item = relation(Item, backref='internal_ids')
1442 ItemInternalID.generation = relation(Generation)
1443
1444 ItemName.language = relation(Language)
1445
1446 ItemPocket.categories = relation(ItemCategory, order_by=ItemCategory.name)
1447
1448 Location.region = relation(Region, backref='locations')
1449
1450 LocationArea.location = relation(Location, backref='areas')
1451
1452 LocationInternalID.location = relation(Location, backref='internal_ids')
1453 LocationInternalID.generation = relation(Generation)
1454
1455 Machine.item = relation(Item)
1456 Machine.version_group = relation(VersionGroup)
1457
1458 Move.changelog = relation(MoveChangelog,
1459 order_by=MoveChangelog.changed_in_version_group_id.desc(),
1460 backref='move',
1461 )
1462 Move.contest_effect = relation(ContestEffect, backref='moves')
1463 Move.contest_combo_next = association_proxy('contest_combo_first', 'second')
1464 Move.contest_combo_prev = association_proxy('contest_combo_second', 'first')
1465 Move.contest_type = relation(ContestType, backref='moves')
1466 Move.damage_class = relation(MoveDamageClass, backref='moves')
1467 Move.flags = association_proxy('move_flags', 'flag')
1468 Move.flavor_text = relation(MoveFlavorText, order_by=MoveFlavorText.version_group_id, backref='move')
1469 Move.foreign_names = relation(MoveName, backref='move')
1470 Move.generation = relation(Generation, backref='moves')
1471 Move.machines = relation(Machine, backref='move')
1472 Move.meta = relation(MoveMeta, uselist=False, backref='move')
1473 Move.meta_stat_changes = relation(MoveMetaStatChange)
1474 Move.move_effect = relation(MoveEffect, backref='moves')
1475 Move.move_flags = relation(MoveFlag, backref='move')
1476 Move.super_contest_effect = relation(SuperContestEffect, backref='moves')
1477 Move.super_contest_combo_next = association_proxy('super_contest_combo_first', 'second')
1478 Move.super_contest_combo_prev = association_proxy('super_contest_combo_second', 'first')
1479 Move.target = relation(MoveTarget, backref='moves')
1480 Move.type = relation(Type, back_populates='moves')
1481
1482 Move.effect = markdown.MoveEffectProperty('effect')
1483 Move.short_effect = markdown.MoveEffectProperty('short_effect')
1484
1485 MoveChangelog.changed_in = relation(VersionGroup, backref='move_changelog')
1486 MoveChangelog.move_effect = relation(MoveEffect, backref='move_changelog')
1487 MoveChangelog.type = relation(Type, backref='move_changelog')
1488
1489 MoveChangelog.effect = markdown.MoveEffectProperty('effect')
1490 MoveChangelog.short_effect = markdown.MoveEffectProperty('short_effect')
1491
1492 MoveEffect.category_map = relation(MoveEffectCategoryMap)
1493 MoveEffect.categories = association_proxy('category_map', 'category')
1494 MoveEffect.changelog = relation(MoveEffectChangelog,
1495 order_by=MoveEffectChangelog.changed_in_version_group_id.desc(),
1496 backref='move_effect',
1497 )
1498 MoveEffectCategoryMap.category = relation(MoveEffectCategory)
1499
1500 MoveEffectChangelog.changed_in = relation(VersionGroup, backref='move_effect_changelog')
1501
1502 MoveFlag.flag = relation(MoveFlagType)
1503
1504 MoveFlavorText.version_group = relation(VersionGroup)
1505
1506 MoveMeta.category = relation(MoveMetaCategory, backref='move_meta')
1507 MoveMeta.ailment = relation(MoveMetaAilment, backref='move_meta')
1508
1509 MoveMetaStatChange.stat = relation(Stat, backref='move_meta_stat_changes')
1510
1511 MoveName.language = relation(Language)
1512
1513 Nature.foreign_names = relation(NatureName, backref='nature')
1514 Nature.decreased_stat = relation(Stat, primaryjoin=Nature.decreased_stat_id==Stat.id,
1515 backref='decreasing_natures')
1516 Nature.increased_stat = relation(Stat, primaryjoin=Nature.increased_stat_id==Stat.id,
1517 backref='increasing_natures')
1518 Nature.hates_flavor = relation(ContestType, primaryjoin=Nature.hates_flavor_id==ContestType.id,
1519 backref='hating_natures')
1520 Nature.likes_flavor = relation(ContestType, primaryjoin=Nature.likes_flavor_id==ContestType.id,
1521 backref='liking_natures')
1522 Nature.battle_style_preferences = relation(NatureBattleStylePreference,
1523 order_by=NatureBattleStylePreference.move_battle_style_id,
1524 backref='nature')
1525 Nature.pokeathlon_effects = relation(NaturePokeathlonStat, order_by=NaturePokeathlonStat.pokeathlon_stat_id)
1526
1527 NatureBattleStylePreference.battle_style = relation(MoveBattleStyle, backref='nature_preferences')
1528
1529 NatureName.language = relation(Language)
1530
1531 NaturePokeathlonStat.pokeathlon_stat = relation(PokeathlonStat, backref='nature_effects')
1532
1533 Pokedex.region = relation(Region, backref='pokedexes')
1534 Pokedex.version_groups = relation(VersionGroup, order_by=VersionGroup.id, back_populates='pokedex')
1535
1536 Pokemon.all_abilities = relation(Ability,
1537 secondary=PokemonAbility.__table__,
1538 order_by=PokemonAbility.slot,
1539 )
1540 Pokemon.abilities = relation(Ability,
1541 secondary=PokemonAbility.__table__,
1542 primaryjoin=and_(
1543 Pokemon.id == PokemonAbility.pokemon_id,
1544 PokemonAbility.is_dream == False,
1545 ),
1546 order_by=PokemonAbility.slot,
1547 )
1548 Pokemon.dream_ability = relation(Ability,
1549 secondary=PokemonAbility.__table__,
1550 primaryjoin=and_(
1551 Pokemon.id == PokemonAbility.pokemon_id,
1552 PokemonAbility.is_dream == True,
1553 ),
1554 uselist=False,
1555 )
1556 Pokemon.pokemon_color = relation(PokemonColor, backref='pokemon')
1557 Pokemon.color = association_proxy('pokemon_color', 'name')
1558 Pokemon.dex_numbers = relation(PokemonDexNumber, order_by=PokemonDexNumber.pokedex_id.asc(), backref='pokemon')
1559 Pokemon.egg_groups = relation(EggGroup, secondary=PokemonEggGroup.__table__,
1560 order_by=PokemonEggGroup.egg_group_id,
1561 backref=backref('pokemon', order_by=Pokemon.order))
1562 Pokemon.evolution_chain = relation(EvolutionChain, back_populates='pokemon')
1563 Pokemon.child_pokemon = relation(Pokemon,
1564 primaryjoin=Pokemon.id==PokemonEvolution.from_pokemon_id,
1565 secondary=PokemonEvolution.__table__,
1566 secondaryjoin=PokemonEvolution.to_pokemon_id==Pokemon.id,
1567 backref=backref('parent_pokemon', uselist=False),
1568 )
1569 Pokemon.flavor_text = relation(PokemonFlavorText, order_by=PokemonFlavorText.version_id.asc(), backref='pokemon')
1570 Pokemon.foreign_names = relation(PokemonName, backref='pokemon')
1571 Pokemon.forms = relation(PokemonForm, primaryjoin=Pokemon.id==PokemonForm.form_base_pokemon_id,
1572 order_by=(PokemonForm.order.asc(), PokemonForm.name.asc()))
1573 Pokemon.default_form = relation(PokemonForm,
1574 primaryjoin=and_(Pokemon.id==PokemonForm.form_base_pokemon_id, PokemonForm.is_default==True),
1575 uselist=False,
1576 )
1577 Pokemon.pokemon_habitat = relation(PokemonHabitat, backref='pokemon')
1578 Pokemon.habitat = association_proxy('pokemon_habitat', 'name')
1579 Pokemon.items = relation(PokemonItem, backref='pokemon')
1580 Pokemon.generation = relation(Generation, backref='pokemon')
1581 Pokemon.shape = relation(PokemonShape, backref='pokemon')
1582 Pokemon.stats = relation(PokemonStat, backref='pokemon', order_by=PokemonStat.stat_id.asc())
1583 Pokemon.types = relation(Type, secondary=PokemonType.__table__,
1584 order_by=PokemonType.slot.asc(),
1585 back_populates='pokemon')
1586
1587 PokemonDexNumber.pokedex = relation(Pokedex)
1588
1589 PokemonEvolution.from_pokemon = relation(Pokemon,
1590 primaryjoin=PokemonEvolution.from_pokemon_id==Pokemon.id,
1591 backref='child_evolutions',
1592 )
1593 PokemonEvolution.to_pokemon = relation(Pokemon,
1594 primaryjoin=PokemonEvolution.to_pokemon_id==Pokemon.id,
1595 backref=backref('parent_evolution', uselist=False),
1596 )
1597 PokemonEvolution.child_evolutions = relation(PokemonEvolution,
1598 primaryjoin=PokemonEvolution.from_pokemon_id==PokemonEvolution.to_pokemon_id,
1599 foreign_keys=[PokemonEvolution.to_pokemon_id],
1600 backref=backref('parent_evolution',
1601 remote_side=[PokemonEvolution.from_pokemon_id],
1602 uselist=False,
1603 ),
1604 )
1605 PokemonEvolution.trigger = relation(EvolutionTrigger, backref='evolutions')
1606 PokemonEvolution.trigger_item = relation(Item,
1607 primaryjoin=PokemonEvolution.trigger_item_id==Item.id,
1608 backref='triggered_evolutions',
1609 )
1610 PokemonEvolution.held_item = relation(Item,
1611 primaryjoin=PokemonEvolution.held_item_id==Item.id,
1612 backref='required_for_evolutions',
1613 )
1614 PokemonEvolution.location = relation(Location, backref='triggered_evolutions')
1615 PokemonEvolution.known_move = relation(Move, backref='triggered_evolutions')
1616 PokemonEvolution.party_pokemon = relation(Pokemon,
1617 primaryjoin=PokemonEvolution.party_pokemon_id==Pokemon.id,
1618 backref='triggered_evolutions',
1619 )
1620 PokemonEvolution.trade_pokemon = relation(Pokemon,
1621 primaryjoin=PokemonEvolution.trade_pokemon_id==Pokemon.id,
1622 )
1623
1624 PokemonFlavorText.version = relation(Version)
1625
1626 PokemonForm.form_base_pokemon = relation(Pokemon, primaryjoin=PokemonForm.form_base_pokemon_id==Pokemon.id)
1627 PokemonForm.unique_pokemon = relation(Pokemon, backref=backref('unique_form', uselist=False),
1628 primaryjoin=PokemonForm.unique_pokemon_id==Pokemon.id)
1629 PokemonForm.version_group = relation(VersionGroup)
1630 PokemonForm.form_group = association_proxy('form_base_pokemon', 'form_group')
1631 PokemonForm.pokeathlon_stats = relation(PokemonFormPokeathlonStat,
1632 order_by=PokemonFormPokeathlonStat.pokeathlon_stat_id,
1633 backref='pokemon_form')
1634
1635 PokemonFormGroup.pokemon = relation(Pokemon, backref=backref('form_group',
1636 uselist=False))
1637
1638 PokemonFormPokeathlonStat.pokeathlon_stat = relation(PokeathlonStat)
1639
1640 PokemonItem.item = relation(Item, backref='pokemon')
1641 PokemonItem.version = relation(Version)
1642
1643 PokemonMove.pokemon = relation(Pokemon, backref='pokemon_moves')
1644 PokemonMove.version_group = relation(VersionGroup)
1645 PokemonMove.machine = relation(Machine, backref='pokemon_moves',
1646 primaryjoin=and_(Machine.version_group_id==PokemonMove.version_group_id,
1647 Machine.move_id==PokemonMove.move_id),
1648 foreign_keys=[Machine.version_group_id, Machine.move_id],
1649 uselist=False)
1650 PokemonMove.move = relation(Move, backref='pokemon_moves')
1651 PokemonMove.method = relation(PokemonMoveMethod)
1652
1653 PokemonName.language = relation(Language, lazy='joined')
1654
1655 PokemonStat.stat = relation(Stat)
1656
1657 # This is technically a has-many; Generation.main_region_id -> Region.id
1658 Region.generation = relation(Generation, uselist=False)
1659 Region.version_group_regions = relation(VersionGroupRegion, backref='region',
1660 order_by='VersionGroupRegion.version_group_id')
1661 Region.version_groups = association_proxy('version_group_regions', 'version_group')
1662
1663 Stat.damage_class = relation(MoveDamageClass, backref='stats')
1664
1665 SuperContestCombo.first = relation(Move, primaryjoin=SuperContestCombo.first_move_id==Move.id,
1666 backref='super_contest_combo_first')
1667 SuperContestCombo.second = relation(Move, primaryjoin=SuperContestCombo.second_move_id==Move.id,
1668 backref='super_contest_combo_second')
1669
1670 Type.damage_efficacies = relation(TypeEfficacy,
1671 primaryjoin=Type.id
1672 ==TypeEfficacy.damage_type_id,
1673 backref='damage_type')
1674 Type.target_efficacies = relation(TypeEfficacy,
1675 primaryjoin=Type.id
1676 ==TypeEfficacy.target_type_id,
1677 backref='target_type')
1678
1679 Type.generation = relation(Generation, backref='types')
1680 Type.damage_class = relation(MoveDamageClass, backref='types')
1681 Type.foreign_names = relation(TypeName, backref='type')
1682 Type.pokemon = relation(Pokemon, secondary=PokemonType.__table__,
1683 order_by=Pokemon.order,
1684 back_populates='types')
1685 Type.moves = relation(Move, back_populates='type', order_by=Move.name)
1686
1687 TypeName.language = relation(Language)
1688
1689 Version.version_group = relation(VersionGroup, back_populates='versions')
1690 Version.generation = association_proxy('version_group', 'generation')
1691
1692 VersionGroup.versions = relation(Version, order_by=Version.id, back_populates='version_group')
1693 VersionGroup.generation = relation(Generation, backref='version_groups')
1694 VersionGroup.version_group_regions = relation(VersionGroupRegion, backref='version_group')
1695 VersionGroup.regions = association_proxy('version_group_regions', 'region')
1696 VersionGroup.pokedex = relation(Pokedex, back_populates='version_groups')