3 from sqlalchemy
import Column
, ForeignKey
, MetaData
, Table
4 from sqlalchemy
.ext
.declarative
import declarative_base
5 from sqlalchemy
.ext
.associationproxy
import association_proxy
6 from sqlalchemy
.orm
import backref
, relation
7 from sqlalchemy
.types
import *
8 from sqlalchemy
.databases
.mysql
import *
10 from pokedex
.db
import rst
13 TableBase
= declarative_base(metadata
=metadata
)
15 class Ability(TableBase
):
16 __tablename__
= 'abilities'
17 id = Column(Integer
, primary_key
=True, nullable
=False)
18 name
= Column(Unicode(24), nullable
=False)
19 flavor_text
= Column(Unicode(64), nullable
=False)
20 effect
= Column(Unicode(255), nullable
=False)
22 class ContestEffect(TableBase
):
23 __tablename__
= 'contest_effects'
24 id = Column(Integer
, primary_key
=True, nullable
=False)
25 appeal
= Column(SmallInteger
, nullable
=False)
26 jam
= Column(SmallInteger
, nullable
=False)
27 flavor
= Column(Unicode(255), nullable
=False)
28 effect
= Column(Unicode(255), nullable
=False)
30 class EggGroup(TableBase
):
31 __tablename__
= 'egg_groups'
32 id = Column(Integer
, primary_key
=True, nullable
=False)
33 name
= Column(Unicode(16), nullable
=False)
35 class Encounter(TableBase
):
36 """Rows in this table represent encounters with wild Pokémon.
38 Within a given area in a given game, encounters are differentiated by the
39 slot they are in and a world condition.
41 Groups of slots belong to encounter types; these are what the player is
42 doing to get an encounter, such as surfing or walking through tall grass.
44 Within an encounter type, slots are defined primarily by rarity. Each slot
45 can also be affected by a world condition; for example, the 20% slot for
46 walking in tall grass is affected by whether a swarm is in effect in the
47 areas. "There is a swarm" and "there is not a swarm" are conditions, and
48 together they make a condition group. However, since "not a swarm" is a
49 base state rather than any sort of new state, it is omitted and instead
50 referred to by a NULL.
52 A slot (20% walking in grass) and single world condition (NULL, i.e. no
53 swarm) are thus enough to define a specific encounter.
55 Well, okay, almost: each slot actually appears twice.
58 __tablename__
= 'encounters'
59 id = Column(Integer
, primary_key
=True, nullable
=False)
60 version_id
= Column(Integer
, ForeignKey('versions.id'), nullable
=False, autoincrement
=False)
61 location_area_id
= Column(Integer
, ForeignKey('location_areas.id'), nullable
=False, autoincrement
=False)
62 encounter_type_slot_id
= Column(Integer
, ForeignKey('encounter_type_slots.id'), nullable
=False, autoincrement
=False)
63 encounter_condition_id
= Column(Integer
, ForeignKey('encounter_conditions.id'), nullable
=True, autoincrement
=False)
64 pokemon_id
= Column(Integer
, ForeignKey('pokemon.id'), nullable
=False, autoincrement
=False)
65 min_level
= Column(Integer
, nullable
=False, autoincrement
=False)
66 max_level
= Column(Integer
, nullable
=False, autoincrement
=False)
68 class EncounterCondition(TableBase
):
69 """Rows in this table represent something different about the world that
70 can affect what Pokémon are encountered.
73 __tablename__
= 'encounter_conditions'
74 id = Column(Integer
, primary_key
=True, nullable
=False)
75 encounter_condition_group_id
= Column(Integer
, ForeignKey('encounter_condition_groups.id'), primary_key
=False, nullable
=False, autoincrement
=False)
76 name
= Column(Unicode(64), nullable
=False)
78 class EncounterConditionGroup(TableBase
):
79 """Rows in this table represent a group of mutually exclusive conditions,
80 such as morning/day/night. "Conditions" that are part of the default state
81 of the world, such as "not during a swarm" or "not using the PokéRadar",
82 are not included in this table and are referred to by NULLs in other
86 __tablename__
= 'encounter_condition_groups'
87 id = Column(Integer
, primary_key
=True, nullable
=False)
88 name
= Column(Unicode(64), nullable
=False)
90 class EncounterType(TableBase
):
91 """Rows in this table represent ways the player can enter a wild encounter;
92 i.e. surfing, fishing, or walking through tall grass.
95 __tablename__
= 'encounter_types'
96 id = Column(Integer
, primary_key
=True, nullable
=False)
97 name
= Column(Unicode(64), nullable
=False)
99 class EncounterTypeSlot(TableBase
):
100 """Rows in this table represent an abstract "slot" within an encounter
101 type, associated with both a condition group and a rarity.
103 Note that there are two encounters per slot, so the rarities will only add
107 __tablename__
= 'encounter_type_slots'
108 id = Column(Integer
, primary_key
=True, nullable
=False)
109 encounter_type_id
= Column(Integer
, ForeignKey('encounter_types.id'), primary_key
=False, nullable
=False, autoincrement
=False)
110 encounter_condition_group_id
= Column(Integer
, ForeignKey('encounter_condition_groups.id'), primary_key
=False, nullable
=True, autoincrement
=False)
111 rarity
= Column(Integer
, nullable
=False, autoincrement
=False)
113 class EvolutionChain(TableBase
):
114 __tablename__
= 'evolution_chains'
115 id = Column(Integer
, primary_key
=True, nullable
=False)
116 growth_rate_id
= Column(Integer
, ForeignKey('growth_rates.id'), nullable
=False)
117 steps_to_hatch
= Column(Integer
, nullable
=False)
118 baby_trigger_item
= Column(Unicode(12))
120 class EvolutionMethod(TableBase
):
121 __tablename__
= 'evolution_methods'
122 id = Column(Integer
, primary_key
=True, nullable
=False)
123 name
= Column(Unicode(64), nullable
=False)
124 description
= Column(Unicode(255), nullable
=False)
126 class Generation(TableBase
):
127 __tablename__
= 'generations'
128 id = Column(Integer
, primary_key
=True, nullable
=False)
129 name
= Column(Unicode(16), nullable
=False)
130 main_region
= Column(Unicode(16), nullable
=False)
132 class GrowthRate(TableBase
):
133 """`formula` is written in LaTeX math notation."""
134 __tablename__
= 'growth_rates'
135 id = Column(Integer
, primary_key
=True, nullable
=False)
136 name
= Column(Unicode(20), nullable
=False)
137 formula
= Column(Unicode(500), nullable
=False)
139 class Item(TableBase
):
140 __tablename__
= 'items'
141 id = Column(Integer
, primary_key
=True, nullable
=False)
142 name
= Column(Unicode(16), nullable
=False)
144 class Language(TableBase
):
145 __tablename__
= 'languages'
146 id = Column(Integer
, primary_key
=True, nullable
=False)
147 name
= Column(Unicode(16), nullable
=False)
149 class Location(TableBase
):
150 __tablename__
= 'locations'
151 id = Column(Integer
, primary_key
=True, nullable
=False)
152 generation_id
= Column(Integer
, ForeignKey('generations.id'), nullable
=False)
153 name
= Column(Unicode(64), nullable
=False)
155 class LocationArea(TableBase
):
156 __tablename__
= 'location_areas'
157 id = Column(Integer
, primary_key
=True, nullable
=False)
158 location_id
= Column(Integer
, ForeignKey('locations.id'), nullable
=False)
159 internal_id
= Column(Integer
, nullable
=False)
160 name
= Column(Unicode(64), nullable
=True)
162 class Machine(TableBase
):
163 __tablename__
= 'machines'
164 machine_number
= Column(Integer
, primary_key
=True, nullable
=False, autoincrement
=False)
165 generation_id
= Column(Integer
, ForeignKey('generations.id'), primary_key
=True, nullable
=False, autoincrement
=False)
166 move_id
= Column(Integer
, ForeignKey('moves.id'), nullable
=False)
168 class MoveDamageClass(TableBase
):
169 __tablename__
= 'move_damage_classes'
170 id = Column(Integer
, primary_key
=True, nullable
=False)
171 name
= Column(Unicode(8), nullable
=False)
172 description
= Column(Unicode(64), nullable
=False)
174 class MoveEffect(TableBase
):
175 __tablename__
= 'move_effects'
176 id = Column(Integer
, primary_key
=True, nullable
=False)
177 priority
= Column(SmallInteger
, nullable
=False)
178 short_effect
= Column(Unicode(128), nullable
=False)
179 effect
= Column(Unicode(5120), nullable
=False)
181 class MoveTarget(TableBase
):
182 __tablename__
= 'move_targets'
183 id = Column(Integer
, primary_key
=True, nullable
=False)
184 name
= Column(Unicode(32), nullable
=False)
185 description
= Column(Unicode(128), nullable
=False)
187 class Move(TableBase
):
188 __tablename__
= 'moves'
189 id = Column(Integer
, primary_key
=True, nullable
=False)
190 name
= Column(Unicode(12), nullable
=False)
191 generation_id
= Column(Integer
, ForeignKey('generations.id'), nullable
=False)
192 type_id
= Column(Integer
, ForeignKey('types.id'), nullable
=False)
193 power
= Column(SmallInteger
)
194 pp
= Column(SmallInteger
, nullable
=False)
195 accuracy
= Column(SmallInteger
)
196 target_id
= Column(Integer
, ForeignKey('move_targets.id'), nullable
=False)
197 damage_class_id
= Column(Integer
, ForeignKey('move_damage_classes.id'), nullable
=False)
198 effect_id
= Column(Integer
, ForeignKey('move_effects.id'), nullable
=False)
199 effect_chance
= Column(Integer
)
200 contest_type
= Column(Unicode(8), nullable
=False)
201 contest_effect_id
= Column(Integer
, ForeignKey('contest_effects.id'), nullable
=True)
202 super_contest_effect_id
= Column(Integer
, nullable
=False)
204 class Pokemon(TableBase
):
205 """The core to this whole mess.
207 Note that I use both 'forme' and 'form' in both code and the database. I
208 only use 'forme' when specifically referring to Pokémon that have multiple
209 distinct species as forms—i.e., different stats or movesets. 'Form' is a
210 more general term referring to any variation within a species, including
211 purely cosmetic forms like Unown.
213 __tablename__
= 'pokemon'
214 id = Column(Integer
, primary_key
=True, nullable
=False)
215 name
= Column(Unicode(20), nullable
=False)
216 forme_name
= Column(Unicode(16))
217 forme_base_pokemon_id
= Column(Integer
, ForeignKey('pokemon.id'))
218 generation_id
= Column(Integer
, ForeignKey('generations.id'))
219 evolution_chain_id
= Column(Integer
, ForeignKey('evolution_chains.id'))
220 evolution_parent_pokemon_id
= Column(Integer
, ForeignKey('pokemon.id'))
221 evolution_method_id
= Column(Integer
, ForeignKey('evolution_methods.id'))
222 evolution_parameter
= Column(Unicode(32))
223 height
= Column(Integer
, nullable
=False)
224 weight
= Column(Integer
, nullable
=False)
225 species
= Column(Unicode(16), nullable
=False)
226 color
= Column(Unicode(6), nullable
=False)
227 pokemon_shape_id
= Column(Integer
, ForeignKey('pokemon_shapes.id'), nullable
=False)
228 habitat
= Column(Unicode(16), nullable
=False)
229 gender_rate
= Column(Integer
, nullable
=False)
230 capture_rate
= Column(Integer
, nullable
=False)
231 base_experience
= Column(Integer
, nullable
=False)
232 base_happiness
= Column(Integer
, nullable
=False)
233 gen1_internal_id
= Column(Integer
)
234 is_baby
= Column(Boolean
, nullable
=False)
235 has_gen4_fem_sprite
= Column(Boolean
, nullable
=False)
236 has_gen4_fem_back_sprite
= Column(Boolean
, nullable
=False)
238 ### Stuff to handle alternate Pokémon forms
241 def national_id(self
):
242 """Returns the National Pokédex number for this Pokémon. Use this
243 instead of the id directly; alternate formes may make the id incorrect.
246 if self
.forme_base_pokemon_id
:
247 return self
.forme_base_pokemon_id
252 """Returns the name of this Pokémon, including its Forme, if any."""
255 return "%s %s" %
(self
.forme_name
.capitalize(), self
.name
)
259 def normal_form(self
):
260 """Returns the normal form for this Pokémon; i.e., this will return
261 regular Deoxys when called on any Deoxys form.
264 if self
.forme_base_pokemon
:
265 return self
.forme_base_pokemon
269 class PokemonAbility(TableBase
):
270 __tablename__
= 'pokemon_abilities'
271 pokemon_id
= Column(Integer
, ForeignKey('pokemon.id'), primary_key
=True, nullable
=False, autoincrement
=False)
272 ability_id
= Column(Integer
, ForeignKey('abilities.id'), nullable
=False)
273 slot
= Column(Integer
, primary_key
=True, nullable
=False, autoincrement
=False)
275 class PokemonDexNumber(TableBase
):
276 __tablename__
= 'pokemon_dex_numbers'
277 pokemon_id
= Column(Integer
, ForeignKey('pokemon.id'), primary_key
=True, nullable
=False, autoincrement
=False)
278 generation_id
= Column(Integer
, ForeignKey('generations.id'), primary_key
=True, nullable
=False, autoincrement
=False)
279 pokedex_number
= Column(Integer
, nullable
=False)
281 class PokemonEggGroup(TableBase
):
282 __tablename__
= 'pokemon_egg_groups'
283 pokemon_id
= Column(Integer
, ForeignKey('pokemon.id'), primary_key
=True, nullable
=False, autoincrement
=False)
284 egg_group_id
= Column(Integer
, ForeignKey('egg_groups.id'), primary_key
=True, nullable
=False, autoincrement
=False)
286 class PokemonFlavorText(TableBase
):
287 __tablename__
= 'pokemon_flavor_text'
288 pokemon_id
= Column(Integer
, ForeignKey('pokemon.id'), primary_key
=True, nullable
=False, autoincrement
=False)
289 version_id
= Column(Integer
, ForeignKey('versions.id'), primary_key
=True, nullable
=False, autoincrement
=False)
290 flavor_text
= Column(Unicode(255), nullable
=False)
292 class PokemonFormGroup(TableBase
):
293 __tablename__
= 'pokemon_form_groups'
294 pokemon_id
= Column(Integer
, ForeignKey('pokemon.id'), primary_key
=True, nullable
=False, autoincrement
=False)
295 description
= Column(Unicode(512), nullable
=False)
297 class PokemonFormSprite(TableBase
):
298 __tablename__
= 'pokemon_form_sprites'
299 id = Column(Integer
, primary_key
=True, nullable
=False)
300 pokemon_id
= Column(Integer
, ForeignKey('pokemon.id'), primary_key
=True, nullable
=False, autoincrement
=False)
301 name
= Column(Unicode(16), nullable
=True)
303 class PokemonItem(TableBase
):
304 __tablename__
= 'pokemon_items'
305 pokemon_id
= Column(Integer
, ForeignKey('pokemon.id'), primary_key
=True, nullable
=False, autoincrement
=False)
306 version_id
= Column(Integer
, ForeignKey('versions.id'), primary_key
=True, nullable
=False, autoincrement
=False)
307 item_id
= Column(Integer
, ForeignKey('items.id'), primary_key
=True, nullable
=False, autoincrement
=False)
308 rarity
= Column(Integer
, nullable
=False)
310 class PokemonMove(TableBase
):
311 __tablename__
= 'pokemon_moves'
312 pokemon_id
= Column(Integer
, ForeignKey('pokemon.id'), primary_key
=True, nullable
=False, autoincrement
=False)
313 version_group_id
= Column(Integer
, ForeignKey('version_groups.id'), primary_key
=True, nullable
=False, autoincrement
=False)
314 move_id
= Column(Integer
, ForeignKey('moves.id'), primary_key
=True, nullable
=False, autoincrement
=False, index
=True)
315 pokemon_move_method_id
= Column(Integer
, ForeignKey('pokemon_move_methods.id'), primary_key
=True, nullable
=False, autoincrement
=False)
316 level
= Column(Integer
, primary_key
=True, nullable
=True, autoincrement
=False)
317 order
= Column(Integer
, nullable
=True)
319 class PokemonMoveMethod(TableBase
):
320 __tablename__
= 'pokemon_move_methods'
321 id = Column(Integer
, primary_key
=True, nullable
=False, autoincrement
=False)
322 name
= Column(Unicode(64), nullable
=False)
323 description
= Column(Unicode(255), nullable
=False)
325 class PokemonName(TableBase
):
326 __tablename__
= 'pokemon_names'
327 pokemon_id
= Column(Integer
, ForeignKey('pokemon.id'), primary_key
=True, nullable
=False, autoincrement
=False)
328 language_id
= Column(Integer
, ForeignKey('languages.id'), primary_key
=True, nullable
=False, autoincrement
=False)
329 name
= Column(Unicode(16), nullable
=False)
331 class PokemonShape(TableBase
):
332 __tablename__
= 'pokemon_shapes'
333 id = Column(Integer
, primary_key
=True, nullable
=False)
334 name
= Column(Unicode(24), nullable
=False)
335 awesome_name
= Column(Unicode(16), nullable
=False)
337 class PokemonStat(TableBase
):
338 __tablename__
= 'pokemon_stats'
339 pokemon_id
= Column(Integer
, ForeignKey('pokemon.id'), primary_key
=True, nullable
=False, autoincrement
=False)
340 stat_id
= Column(Integer
, ForeignKey('stats.id'), primary_key
=True, nullable
=False, autoincrement
=False)
341 base_stat
= Column(Integer
, nullable
=False)
342 effort
= Column(Integer
, nullable
=False)
344 class PokemonType(TableBase
):
345 __tablename__
= 'pokemon_types'
346 pokemon_id
= Column(Integer
, ForeignKey('pokemon.id'), primary_key
=True, nullable
=False, autoincrement
=False)
347 type_id
= Column(Integer
, ForeignKey('types.id'), nullable
=False)
348 slot
= Column(Integer
, primary_key
=True, nullable
=False, autoincrement
=False)
350 class Stat(TableBase
):
351 __tablename__
= 'stats'
352 id = Column(Integer
, primary_key
=True, nullable
=False)
353 name
= Column(Unicode(16), nullable
=False)
355 class TypeEfficacy(TableBase
):
356 __tablename__
= 'type_efficacy'
357 damage_type_id
= Column(Integer
, ForeignKey('types.id'), primary_key
=True, nullable
=False, autoincrement
=False)
358 target_type_id
= Column(Integer
, ForeignKey('types.id'), primary_key
=True, nullable
=False, autoincrement
=False)
359 damage_factor
= Column(Integer
, nullable
=False)
361 class Type(TableBase
):
362 __tablename__
= 'types'
363 id = Column(Integer
, primary_key
=True, nullable
=False)
364 name
= Column(Unicode(8), nullable
=False)
365 abbreviation
= Column(Unicode(3), nullable
=False)
367 class VersionGroup(TableBase
):
368 __tablename__
= 'version_groups'
369 id = Column(Integer
, primary_key
=True, nullable
=False)
370 generation_id
= Column(Integer
, ForeignKey('generations.id'), nullable
=False)
372 class Version(TableBase
):
373 __tablename__
= 'versions'
374 id = Column(Integer
, primary_key
=True, nullable
=False)
375 version_group_id
= Column(Integer
, ForeignKey('version_groups.id'), nullable
=False)
376 name
= Column(Unicode(32), nullable
=False)
379 ### Relations down here, to avoid ordering problems
380 Encounter
.pokemon
= relation(Pokemon
, backref
='encounters')
381 Encounter
.version
= relation(Version
, backref
='encounters')
382 Encounter
.location_area
= relation(LocationArea
, backref
='encounters')
383 Encounter
.slot
= relation(EncounterTypeSlot
, backref
='encounters')
384 Encounter
.condition
= relation(EncounterCondition
, backref
='encounters')
386 EncounterCondition
.group
= relation(EncounterConditionGroup
,
387 backref
='conditions')
389 EncounterTypeSlot
.type = relation(EncounterType
, backref
='slots')
391 EvolutionChain
.growth_rate
= relation(GrowthRate
, backref
='evolution_chains')
393 Generation
.versions
= relation(Version
, secondary
=VersionGroup
.__table__
)
395 LocationArea
.location
= relation(Location
, backref
='areas')
397 Machine
.generation
= relation(Generation
)
399 Move
.damage_class
= relation(MoveDamageClass
, backref
='moves')
400 Move
.move_effect
= relation(MoveEffect
, backref
='moves')
401 Move
.generation
= relation(Generation
, backref
='moves')
402 Move
.machines
= relation(Machine
, backref
='move')
403 Move
.target
= relation(MoveTarget
, backref
='moves')
404 Move
.type = relation(Type
, backref
='moves')
406 Move
.effect
= rst
.MoveEffectProperty()
407 Move
.priority
= association_proxy('move_effect', 'priority')
408 Move
.short_effect
= association_proxy('move_effect', 'short_effect')
410 Pokemon
.abilities
= relation(Ability
, secondary
=PokemonAbility
.__table__
,
411 order_by
=PokemonAbility
.slot
,
413 Pokemon
.formes
= relation(Pokemon
, primaryjoin
=Pokemon
.id==Pokemon
.forme_base_pokemon_id
,
414 backref
=backref('forme_base_pokemon',
415 remote_side
=[Pokemon
.id]))
416 Pokemon
.dex_numbers
= relation(PokemonDexNumber
, backref
='pokemon')
417 Pokemon
.egg_groups
= relation(EggGroup
, secondary
=PokemonEggGroup
.__table__
,
418 order_by
=PokemonEggGroup
.egg_group_id
,
420 Pokemon
.evolution_chain
= relation(EvolutionChain
, backref
='pokemon')
421 Pokemon
.evolution_method
= relation(EvolutionMethod
)
422 Pokemon
.evolution_children
= relation(Pokemon
, primaryjoin
=Pokemon
.id==Pokemon
.evolution_parent_pokemon_id
,
423 backref
=backref('evolution_parent',
424 remote_side
=[Pokemon
.id]))
425 Pokemon
.flavor_text
= relation(PokemonFlavorText
, backref
='pokemon')
426 Pokemon
.foreign_names
= relation(PokemonName
, backref
='pokemon')
427 Pokemon
.items
= relation(PokemonItem
)
428 Pokemon
.generation
= relation(Generation
, backref
='pokemon')
429 Pokemon
.shape
= relation(PokemonShape
, backref
='pokemon')
430 Pokemon
.stats
= relation(PokemonStat
, backref
='pokemon')
431 Pokemon
.types
= relation(Type
, secondary
=PokemonType
.__table__
)
433 PokemonDexNumber
.generation
= relation(Generation
)
435 PokemonFlavorText
.version
= relation(Version
)
437 PokemonItem
.item
= relation(Item
, backref
='pokemon')
438 PokemonItem
.version
= relation(Version
)
440 PokemonFormGroup
.pokemon
= relation(Pokemon
, backref
=backref('form_group',
442 PokemonFormSprite
.pokemon
= relation(Pokemon
, backref
='form_sprites')
444 PokemonMove
.pokemon
= relation(Pokemon
, backref
='pokemon_moves')
445 PokemonMove
.version_group
= relation(VersionGroup
)
446 PokemonMove
.move
= relation(Move
, backref
='pokemon_moves')
447 PokemonMove
.method
= relation(PokemonMoveMethod
)
449 PokemonName
.language
= relation(Language
)
451 PokemonStat
.stat
= relation(Stat
)
453 Type
.damage_efficacies
= relation(TypeEfficacy
,
455 ==TypeEfficacy
.damage_type_id
,
456 backref
='damage_type')
457 Type
.target_efficacies
= relation(TypeEfficacy
,
459 ==TypeEfficacy
.target_type_id
,
460 backref
='target_type')
462 Version
.version_group
= relation(VersionGroup
, backref
='versions')
463 Version
.generation
= association_proxy('version_group', 'generation')
465 VersionGroup
.generation
= relation(Generation
, backref
='version_groups')