Legendary and Mythical are official terms which, while generally not
present in the game data, are more or less consistently applied in
promotional material. They're also useful categorizations to fans,
so it seems reasonable to include them here.
The legendary Pokémon are:
Articuno, Zapdos, Moltres, Mewtwo,
Raikou, Entei, Suicune, Lugia, Ho-Oh,
Regirock, Regice, Registeel,
Latias, Latios, Kyogre, Groudon, Rayquaza,
Uxie, Mesprit, Azelf, Dialga, Palkia, Giratina,
Heatran, Regigigas, Cresselia,
Cobalion, Terrakion, Virizion,
Tornadus, Thundurus, Landorus,
Reshiram, Zekrom, Kyurem,
Xerneas, Yveltal, Zygarde,
Tapu Koko, Tapu Lele, Tapu Bulu, Tapu Fini,
Cosmog, Cosmoem, Solgaleo, Lunala, Necrozma.
The mythical Pokémon are: Mew, Celebi, Jirachi, Deoxys, Phione, Manaphy,
Darkrai, Shaymin, Arceus, Victini, Keldeo, Meloetta, Genesect,
Diancie, Hoopa, Volcanion, Magearna, Marshadow, Zeraora.
A bug in the text dumper caused み to be replaced with a narrow
non-breaking space and the actual nbsp character in the unicode private
use area to go untranslated.
Only affected OR/AS.
Fix with a simple text replace on the affected entries.
import csv
in_ = open("../pokedex/data/csv/pokemon_species_flavor_text.csv", "r")
out = open("fixed.csv", "w")
r = csv.reader(in_, lineterminator='\n')
w = csv.writer(out, lineterminator='\n')
for row in r:
text = row[3]
if row[1] in {'25', '26'}:
text = text.replace("\u202f", "\u307f") # nbsp => mi
text = text.replace("\ue07f", "\u202f") # e07f => nbsp
w.writerow((row[0], row[1], row[2], text))
out.close()
Fixes#308
The initial import of data from S/M and US/UM only included held items for Moon
and Ultra Sun. (Presumably those were the only games eevee had access to?)
I now have all four games and I've verified that the data file which
contains held items is completely identical between Sun and Moon, and between
Ultra Sun and Ultra Moon.
So we can just copy the held items from the other two games.
pokedex=> insert into pokemon_items (select pokemon_id, 27, item_id, rarity from pokemon_items where version_id=28);
INSERT 0 356
Time: 220.560 ms
pokedex=> insert into pokemon_items (select pokemon_id, 30, item_id, rarity from pokemon_items where version_id=29);
INSERT 0 362
Time: 102.063 ms
- Add exception handling for SQLite, PostgreSQL, and MySQL.
Sqlalchemy gives different exceptions for each database engine so I have
seperated each exception for each engine.
The error message passed by each engine is also different so that is
checked as well.
- Once the function gets one of those exceptions the following message
is outputed and the program ends: `ERROR: Table 'TABLENAME' already
exists in the database. Did you mean to use 'pokedex load -D'`
- If the error is not that a table already exists, then the output will
just be the full error from sqlalchemy. That way if someone runs into
that error it can be reported as an issue and whoever can help would see
the full error.
---
Resolves part of issue #16
Filtering on pokemon name was broken. Not sure why, since the search CLI
was added way after the i18n stuff was added. The error is related to
AssociationProxy, which figures because nothing about association
proxies ever seems to work right. I don't know enough about SQLAlchemy
internals to know if what it was trying to do was supposed to
work, or how to fix it if so. So, fix it by using the same boring
join-based filtering that spline-pokedex uses.
Running `pokedex search --name=gloom` caused the following error with
PostgreSQL and SQLAlchemy 1.3.5:
sqlalchemy.exc.ProgrammingError: (psycopg2.ProgrammingError) can't adapt type 'ColumnAssociationProxyInstance'
...and this error with SQLite.
sqlalchemy.exc.InterfaceError: (sqlite3.InterfaceError) Error binding parameter 4 - probably unsupported type.
[parameters: (9, 9, 9, 9, ColumnAssociationProxyInstance(AssociationProxy('names_local', 'name')), 'gloom')]
Additionaly, the following error would happen with PostgreSQL and SQLAlchemy 0.9.7,
but that's probably unrelated:
sqlalchemy.exc.ProgrammingError: (ProgrammingError) subquery in FROM must have an alias
LINE 4: FROM pokemon_species, (SELECT pokemon_species_names.name AS ...
^
Fixes#296
Gen III contest effects were part of the initial data import from brown
veekun and so have probably never gotten a proper rip.
This commit re-rips contest effect stats, types, combos, and the mapping
between contest effects and moves.
None of the stats changed (jam & appeal); a few moves got assigned
different contest effects (specifically: smokescreen, flash, spite, and
shadow ball); and several combos changed.
For example, Hail was listed as comboing into the following moves
(this is also what Bulbapedia says):
Ice Beam, Blizzard, Aurora Beam, Haze, Powder Snow, Icy Wind,
Ice Ball, Weather Ball, Sheer Cold, Icicle Spear
However, the actual list is much shorter:
Blizzard, Powder Snow, Weather Ball
I verified on my Ruby cart that Hail->Ice Beam and Hail->Icy Wind are
not real combos, and that Hail->Blizzard is.
n.b. There are a bunch of unused contest effects in the game: out of 48
effects, 15 are not used by any move. The pokedex doesn't currently
include these. I elected not to add them, partly because i didn't want
to have to rip flavor text for them, but mostly because if i were going
to go that route i would probably reassign contest_effects.id to match
their internal ids, which would have made for uglier diffs.
Fixes#280
- link to nonexistant `[]{move:shield}` in Color Change (changed to protect)
- invalid syntax `[move:sandstorm]` in Primordial Sea
- invalid syntax `[move:sandstorm]` in Desolate Land
- invalid syntax `[move:sandstorm]` in Delta Stream
Found by test_markdown_values, which is not run by default because it is
slow. It can be run manually with
py.test pokedex/tests/test_strings.py --all
Pikachu's Cap forms and Cosplay forms had overlapping orders because i
forgot about Cosplay Pikachu when i set the form_order for the cap
forms.
??? Arceus had form_order=3 so it would go after all the other forms,
which had form_order=2. These were assigned distinct form_orders 2
through 17 at some point during a recent dump, but ??? Arceus was
missed.
Fixes#282
This commit adds Korean translations for egg groups, generations, languages, regions, stats, and version names. Also the ??? and shadow types.
It also fills in some missing foreign version names for S/M and US/UM (from Bulbapedia).
Roserade and Roselia were mistakenly sharing dex number 72. Presumably
an error from the original X/Y spreadsheet. I guess we never reripped
these after 3DS rom dumping became possible.
Regardless of how it happened, add a test and some database constraints
to ensure that it doesn't happen again.
- Add a test for gaps in pokedex numbers
- Add uniqueness constraints to pokemon_dex_numbers. A species can
only appear once per pokedex, and a number cannot be used more than
once per pokedex.
Cosplay Pikachu was listed as being encountered in contest-hall, but
that's a Sinnoh location. In OR/AS, the contest halls are not a
first-class location but rather just treated as part of the town or city
they are in. Cosplay Pikachu is given to the player after they
participate in their first contest, so its location can be any of the
four cities with a contest hall.
The Sinnoh starter that the player obtains in OR/AS is on Hoenn Route
101, not Sinnoh Route 201 (probably a copy/paste error).
Add a test to make sure that encounter regions always match the
region(s) that their game takes place in.
Add Japanese translations of the generation names, thanks to @SethETaron. I think this marks our first unofficial Japanese translation. 🎉
Also, fix some issues with Gen VII:
* generation names were missing for every language
* the identifier was incorrect — it was sun-moon instead of generation-vii
Fixes#250, #251, and #252.
Python 3 doesn't allow the ur'' prefix for raw unicode strings.
We want a unicode string here so that we get a unicode regexp,
so drop the r and do the escaping explicitly (the regexp in question
is pretty simple, fortunately).
Unova Routes 19-23 were added in B/W 2 and i forgot to prefix them when
we added the locations. Kalos Victory Road used to have a prefix but it
got dropped when i re-ripped X/Y locations. Kalos Pokemon League gets a
prefix too, since both Sinnoh and Alola also have Pokemon Leagues.
Add a test to ensure that we don't forget again in the future.
Also require location area identifiers to be unique to their location.
I almost added a duplicate pokemon-league location when adding S/M
locations. This should help.
The previous commit added a nullable subtitle field to location_names.
This caused a test in test_schema.py to fail because the name field
wasn't also nullable.
A comment above the test says, "If there's more than one text column in a
translation table they have to be nullable, to support missing
translations", but i don't think that logic holds in this case.
The idea is that we might have a translation for the subtitle, but not
the name, or vice versa, so both need to be nullable in case one or the
other is missing. But in this particular case that doesn't make sense:
if you don't have a name, you don't have a location; it may or may not
have a subtitle, but a location will always have a name.
Therefore, add an exception to the test.
Using the following steps:
* Unroll the previous commit with bulk CSV changes (b7500e92f0)
* remove and re-initialize the database
* follow the steps in that commit
* Only select location_area_prose in English
(there's a bunch of czech translations tracked separately in pokedex/data/csv/translations/cs.csv)
This change implies no functionality, but it was easiest to just
make it - sqlite insists on quoting spaces, though it's not needed.
Not rolling it back, since theoretically someone could run into the
same thing again in the future.
I'm going to record gift-pokemon as having no encounter slot, which I
believe is correct by-and-large (since you always get the same mon).
There are a few randomized gift pokemon which do have some type
of encounter slot (eg. Crystal's Odd Egg). Those aren't tracked (yet).
This commit adds Sun & Moon location names from the text dump, for all
official languages: the usual ja, en, fr, it, de, es, ko, and now
zh-Hans (simplified Chinese) and zh-Hant (traditional Chinese).
Fixes#230
Updates #198
Starting in Gen VI, locations have been able to have an optional
subtitle. In-game, the subtitle is displayed on a second line under the
main name.
In X/Y this is used to give some locations an alternate,
flavorful name; for example, Kalos Route 2 is also known as Avance
Trail. In S/M this is mainly used to divide some large locations like
Hau'oli City into separate sections: e.g., the Beachfront, the Shopping
District, and the Marina.
This commit just adds the column; there are no data changes.
I suppose we'll need to go back and re-rip X/Y location names now.
This commit adds OR/AS location names from the text dump, for all
official languages (ja, en, fr, it, de, ko).
It also updates the names of any pre-existing locations from R/S/E to
use the names from OR/AS. Mostly this only affects the French
translations, which i think were added manually.
"Inside of Truck" was renamed to "???" in all languages, which is dumb,
but whatever.
"Team Magma Hideout" is in fact a different location from the
already-existing "Magma Hideout" - Magma Hideout was from Emerald and
resided in Jagged Pass, while Team Aqua Hideout and Team Magma Hideout
are located outside Lilycove City.
Kalos locations are untouched. I assume they didn't change, but didn't
verify this.
Updates #141
When you open a file in Python 3, it defaults to using the system charset to encode the file, which is typically UTF-8 on linux systems (good) but Windows-1251 on Windows (bad).
We need to add explicit encoding=utf-8 arguments to open() calls when we open CSV files for reading or writing. To complicate matters, the csv module works only with byte strings in Python 2, and only with unicode strings in Python 3, so we can't just blindly use `io.open` everywhere.
The schema has changed a little in the past, uh, seven years.
Works well enough to parse and display one of my pokemon in the gts
plugin.
Updates veekun/spline-pokedex#72
PyPy (>= 3.6) was consistently erroring out during `pokedex load`,
with the error
OperationalError: (_sqlite3.OperationalError) cannot commit transaction - SQL statements in progress (Background on this error at: http://sqlalche.me/e/e3q8)
It turns out PyPy was not garbage collecting something, causing a
database cursor to be left open. See the giant comment block for
details.
* SQLAlchemy 1.0 introduced "baked queries" - a way to construct Query
objects so that they can be cached and reused.
* SQLAlchemy 1.2 changed lazyloaded columns to use baked queries under the
hood.
* Our MultilangQuery class attempts to set _default_language_id right
before the query is executed by overriding the __iter__ method.
* Baked queries bypass the __iter__ method and call a lower-level
method, _execute_and_instances, directly.
* This caused problems where _default_language_id wouldn't get set
correctly on lazyloaded columns.
* To fix, make MultilangQuery override the _execute_and_instances
method instead of __iter__.
* This is really just a stopgap: the root cause is that query params
are not preserved across lazyloads.
Tested with SQLAlchemy 0.9.7, 1.1.18, and 1.2.5.
Updates #236.
Made by running a script to compare an old version of moves.csv[1] with
the current version.
[1]: cb5276773b
Hidden power changed from variable power to 100.
We can't represent NULLs in the changelog,
so set the power to 1 instead.
A few effect chances changed from NULL to 100.
We can't represent this either, but i don't think it matters.
leer: effect_chance changed from NULL to 100
hidden-power: power changed from 1 to 60
chatter: effect_chance changed from NULL to 100
v-create: effect_chance changed from NULL to 100
Here's the complete list of changes:
swords-dance: pp changed from 30 to 20
whirlwind: accuracy changed from 100 to NULL
vine-whip: power changed from 35 to 45
vine-whip: pp changed from 15 to 25
pin-missile: power changed from 14 to 25
pin-missile: accuracy changed from 85 to 95
roar: accuracy changed from 100 to NULL
flamethrower: power changed from 95 to 90
hydro-pump: power changed from 120 to 110
surf: power changed from 95 to 90
ice-beam: power changed from 95 to 90
blizzard: power changed from 120 to 110
submission: pp changed from 25 to 20
growth: pp changed from 40 to 20
thunderbolt: power changed from 95 to 90
thunder: power changed from 120 to 110
minimize: pp changed from 20 to 10
barrier: pp changed from 30 to 20
lick: power changed from 20 to 30
smog: power changed from 20 to 30
fire-blast: power changed from 120 to 110
skull-bash: power changed from 100 to 130
skull-bash: pp changed from 15 to 10
glare: accuracy changed from 90 to 100
poison-gas: accuracy changed from 80 to 90
bubble: power changed from 20 to 40
psywave: accuracy changed from 80 to 100
acid-armor: pp changed from 40 to 20
crabhammer: power changed from 90 to 100
struggle: target_id changed from 10 to 8
thief: power changed from 40 to 60
thief: pp changed from 10 to 25
snore: power changed from 40 to 50
cotton-spore: target_id changed from 10 to 11
sweet-kiss: type_id changed from 1 to 18
perish-song: target_id changed from 12 to 14
charm: type_id changed from 1 to 18
fury-cutter: power changed from 20 to 40
heal-bell: target_id changed from 4 to 13
moonlight: type_id changed from 1 to 18
hidden-power: power changed from 1 to 60
future-sight: power changed from 100 to 120
heat-wave: power changed from 100 to 95
will-o-wisp: accuracy changed from 75 to 85
smellingsalt: power changed from 60 to 70
follow-me: priority changed from 3 to 2
nature-power: target_id changed from 1 to 10
knock-off: power changed from 20 to 65
poison-fang: effect_chance changed from 30 to 50
meteor-mash: power changed from 100 to 90
meteor-mash: accuracy changed from 85 to 90
aromatherapy: target_id changed from 4 to 13
air-cutter: power changed from 55 to 60
overheat: power changed from 140 to 130
rock-tomb: power changed from 50 to 60
rock-tomb: pp changed from 10 to 15
rock-tomb: accuracy changed from 80 to 95
extrasensory: pp changed from 30 to 20
muddy-water: power changed from 95 to 90
covet: pp changed from 40 to 25
wake-up-slap: power changed from 60 to 70
tailwind: pp changed from 30 to 15
assurance: power changed from 50 to 60
psycho-shift: accuracy changed from 90 to 100
aura-sphere: power changed from 90 to 80
air-slash: pp changed from 20 to 15
dragon-pulse: power changed from 90 to 85
power-gem: power changed from 70 to 80
energy-ball: power changed from 80 to 90
draco-meteor: power changed from 140 to 130
leaf-storm: power changed from 140 to 130
gunk-shot: accuracy changed from 70 to 80
chatter: power changed from 60 to 65
magma-storm: power changed from 120 to 100
wonder-room: priority changed from -7 to 0
rage-powder: priority changed from 3 to 2
magic-room: priority changed from -7 to 0
storm-throw: power changed from 40 to 60
synchronoise: power changed from 70 to 120
synchronoise: pp changed from 15 to 10
low-sweep: power changed from 60 to 65
hex: power changed from 50 to 65
incinerate: power changed from 30 to 60
water-pledge: power changed from 50 to 80
fire-pledge: power changed from 50 to 80
grass-pledge: power changed from 50 to 80
struggle-bug: power changed from 30 to 50
frost-breath: power changed from 40 to 60
sacred-sword: pp changed from 20 to 15
hurricane: power changed from 120 to 110
techno-blast: power changed from 85 to 120
Fixes#127Fixes#136
Merge pull request #162 from rubendal/master
The Cosplay Pikachu form change mechanic is similar to Rotom:
when it changes form it learns a special move, possibly forgetting
its old special move if it had already changed form.
Renamed the "Rotom Form" pokemon move method to "Form Change"
and updated the description accordingly.
Merge pull request #189 from phmatray/patch-1
The pokemon_name field in pokemon_form_names is sadly not rippable and has to be created by hand, being an unofficial amalgam of the species name and form name. Looks like Zhorken made a typo when adding the French form names originally.
Merge pull request #180 from seii/veekun-issue-103
Background: When I originally ripped FR/LG encounters, i gave them
their own set of location areas instead of reusing the ones from R/B/Y.
My reasoning was that location areas aren't really consistent across games,
and we have to name them by hand anyway, so it would be better to take care
of merging them in the presentation layer than the database layer.
The other devs disagreed with me, and all other rips have reused location areas.
This set of commits removes the separate location areas for FR/LG, merging them
with the existing location areas. Mostly straightforward, except:
- My original rip collapsed the three upper floors of the Pokémon Mansion into
a single unnamed area, since they had the same encounters. But R/B/Y had
slightly different encounters on each floor, so we have to re-duplicate these
floors.
- I'm not sure how we ended up with four Victory Roads in Kanto, but we did.
One of them (kanto-victory-road-1) is the G/S/C victory road, which has a
completely different layout so it makes sense having its own set of location
areas. As for the other three, one was used by R/B/Y (kanto-victory-road-2),
one by FireRed (kanto-victory-road-3), and one by LeafGreen
(kanto-victory-road-4). We can merge these.
Also, a few locations had inconsistent names:
- Routes 19, 20 & 21 => Sea Routes 19, 20 & 21
- Route 2 unnamed area => Route 2 south, towards Viridan City
- Safari Zone center => Safari Zone middle
Thanks to seii for doing all the hard work.
Fixes#103Fixes#156
There was a mix up with B1F and 1F in FireRed and LeafGreen.
Both floors got labeled as 1F during the location area cleanup,
and the B1F encounters were copied to 2F and 3F instead of the 1F
encounters.
This broke my database import:
```
psycopg2.DataError: extra data after last expected column
CONTEXT: COPY pokemon_shape_prose, line 21: "6,9,Upright,Sciurine,Pokémon with a bipedal, tailed form"
```