As of a few minutes ago, porydex.com has finally been fully updated with the Pokémon Showdown usage stats data from the last few years!

The multi-year hiatus is finally over! Porydex is now up to date and shall remain up to date for at least the rest of the Scarlet/Violet generation.

And that’s pretty much the only outwardly exciting Porydex thing I accomplished.

But inwardly

Transforming the data of the Pokémon games into something that cleanly fits into a relational database like MySQL is an endless challenge. Even things that seem basic and obvious in terms of how it gets stored has the potential to invoke hidden complexity.

For example, egg groups. Pokémon can be in up to two egg groups, so in the grand spreadsheet that is Porydex, we just need the Pokémon table to have two columns for egg group, right? EXCEPT!!! In Sword/Shield, a handful of Pokémon that were previously in only one egg group gained a second egg group—which means more possible breeding partners, which means Porydex needs to account for it in the egg move breeding chain calculator. So now, the grand spreadsheet needs to store egg groups per Pokémon per game.

Or how about alternate forms? Did you know there are 20 mostly-duplicate copies of Scatterbug and Spewpa in Scarlet/Violet, each with copypastes of the same moveset, base stats, types, and so on—except each one evolves into a visually distinct Vivillon? “Yeah, I knew that, that’s how Vivillon has always worked,” you might say. To which I’d say, actually, in X/Y, there was only a single copy of Scatterbug and Spewpa, and its fancy distinct evolution logic was handled some other way.

That seems to be a trend in recent games: implementing alternate forms by turning them into duplicate mons with minor changes to the original. For the most part, that’s good and convenient. Two-Segment Dundunsparce and Three-Segment Dudunsparce are exact replicas, except for differing height and weight. Same for Maushold. And same for… Koraidon and Miraidon? Who have five different forms each, because each upgrade level of the ride forms has its own entry in the game’s Pokémon list?

And as we go deeper, the nuances get weirder.

Quick! How many forms does Arceus have? If you said 18, one for each type, then you must not have known that Legends: Arceus introduced a 19th form, exactly the same as the default Normal-type form. I’m pretty sure that’s the form used by the Legend Plate in that game. Or maybe you were forgetting the sprite for ???-type Arceus that existed in the 4th generation games, back when Curse was a ???-type move.

Or how many forms does Burmy have? If you said 3, correct! What about Wormadam? If you said 3 again, correct again! What about Mothim? If you said 1, you would have been correct… until 8th generation, which has 3 duplicate Mothim forms, for the sake of keeping track of which Burmy form it evolved from.

Should Porydex add those non-functional extra forms just so it can be a more complete reflection of the games? So far, I’ve decided no. Even if I did make it a goal to more accurately reflect the alternate form breakdowns in the game, there are still times that the games themselves don’t go far enough!

How many forms does Alcremie have? If you said 63, you’re living in reality, which unfortunately is not where the games’ internal coding is living. In the games, there’s 1 form of Milcery, with only 9 evolutions—Alcremie only has 9 forms, based on how the player spins, not based on the 7 sweets it can be holding to customize the sub-form it evolves into.

And so, Porydex has to take creative liberties and interpret the data in whatever ways I deem reasonable. For the most part, it works. The original system designed by veekun is still holding strong: a three-tiered system, in which species are broken down into functionally distinct forms (e.g. Meowth being broken down into Alolan Meowth vs Galarian Meowth), and functionally distinct forms are broken down into cosmetically distinct forms (e.g. Unown being broken down into each of its 28 cosmetic forms).

But the border between functional and cosmetic is fuzzy, and changes every generation. I used to put height and weight on the “functional” level, because of things like Grass Knot. Weight wasn’t just cosmetic—Grass Knot used in Ultra Sun/Ultra Moon would have different base power for Alolan Raticate vs. Totem Raticate.

But then 9th gen gave us Dudunsparce and Maushold and Koraidon and Miraidon, none of which I wanted to bother with duplicating at the functional layer, so I moved height/weight to the cosmetic layer. This conveniently also gave me the ability to “fix” the heights of Gigantamax forms, which were also cosmetic (only differing in height and in access to a single extra move in-battle).

But, I already had the Totems in the functional layer, where they no longer belonged… so I wanted to move them. And also, I wanted to remove ???-type Arceus, which I included in my original design of Porydex because I somehow thought it was a good idea. (That must have been my brain having a ???-type thought.)

So, that’s what I was actually doing for a few weeks this month. Removing those forms from the Porydex database, and then renumbering all the remaining forms so there wouldn’t be any gaps in the internal ID list. Because, once again, I had become obsessive and/or compulsive about a very silly minor thing.

Oh and also while all that was happening, I was moving porydex.com onto a new server, because the old one was very old and a little bit unstable. I’m not the most proficient with servers and Ubuntu and command line junk, so it took some time to get the new server stabilized. I don’t want to assume it’s fully there yet, but at least it’s not sending me crash reports every hour or two anymore.

So uh in conclusion enjoy the stats, nerds