Skip to content

Card eligibility: how the tiers and the ban list were derived

Decision record for what can appear on a bingo card. The wiki page Bingo lists the resulting species and deliberately carries no rationale; this is where the reasoning lives.

Two separate questions are answered here, and they are answered with different measurements. Conflating them is the single easiest mistake to make in this area:

Question Measured on Why
Which tier is a species in? raw rarity weight It is what the mod itself compares against its thresholds.
Should a species be banned as too rare? real spawn chance Raw rarity is not comparable across biomes, so it cannot answer "is this findable".

1. Why Pixelmon forces a choice here

Pixelmon has no rarity buckets. Cobblemon labels each spawn common / uncommon / rare / ultra-rare; Pixelmon stores a bare float rarity per spawn entry, spanning roughly 0.01 to 300 across about 1,775 entries. So the tiers have to be cut somewhere, and the cut is ours.

The cuts: 60 / 10 / 1

Inclusive lower bounds, checked highest-first. Anything below 1 is ULTRA_RARE.

These are not new numbers. They are exactly the cuts the pixelmonhunt sidemod already uses in its RarityConfig on this network. Reusing them was deliberate: two features on the same server telling a player that Lapras is "rare" and "uncommon" respectively is a worse outcome than either cut being slightly off. Change them in both or neither.

They live in config.yml as common-threshold / uncommon-threshold / rare-threshold.

A species takes its HIGHEST rarity

Matching HuntTarget.getRarity(). A Pokemon that is abundant in one biome and scarce in another is as findable as its best biome, so the maximum is what a player actually experiences.

Three filters on which entries count

  • Only the standard pool. legendaries and megas are not ordinary catches, and fishing, curry, grass, headbutt, rocksmash, sweetscent, caverock and forage are trigger-only. A card square for something reachable only by fishing is exactly the unfairness this work exists to remove.
  • Structure-gated entries are excluded. 130 stock entries carry a condition.structures. Letting them set a tier inflates 21 species: Mismagius reads 130 (COMMON) but is 0.5 in the open world, and Gimmighoul reads 100 while having no open-world spawn at all. Gimmighoul's bare rarity: 100 is the most misleading number in the spawn data.
  • Datapacks are merged, and on main that is load-bearing. A datapack file replaces the jar file at the same path wholesale. main ships snowbird_pixelmon_biome_spawn_compat.zip, which overrides 21 files under spawning/standard, so reading the jar alone describes a server that does not exist.

Current result

851 eligible species: 304 COMMON / 257 UNCOMMON / 225 RARE / 65 ULTRA_RARE.


2. rarity is NOT a chance

This is the trap that invalidated an earlier version of the ban list.

SelectionAlgorithm.choose() gathers everything suitable at a location right now, sums their rarities, and picks proportionally:

chance(species) = rarity(species) / SUM(rarity of everything competing there)

So a rarity of 0.5 is a rounding error in a crowded jungle and a large share in a sparse biome. Ranking species by the bare float is invalid the moment it crosses biomes, which is precisely what "which Pokemon are too rare to put on a card" does.

Raw rarity is still the right input for tiering, because that is the number the mod itself compares against its thresholds. It is the wrong input for banning.


3. How the "too rare" bans were derived

Computed with ~/PycharmProjects/PixelmonWiki/scripts/max_spawn_chance.py, which is the server's answer rather than Pixelmon's:

  • loader.load_data() returns the effective tree, datapacks merged and server config applied.
  • biome_availability() is populated from the biome mod jars in server/mods, so a biome nothing generates is not counted as somewhere to hunt. 173 biomes generate here; 180 more are referenced by spawn data but never generate.
  • A bucket is (biome, time, method): the set of things that can be picked in one draw. A species' headline number is its best bucket, the most favourable place and time a player could deliberately travel to.

The clamp: more than 2 standard deviations below the mean, in LOG space

n = 888, geometric mean 4.1247%, log10 sd 0.9798, giving a floor of 0.0453%, about 91x below typical.

Log space is required, not stylistic. Chance spans 0.0007% to 100%. A linear mean - 2sd lands at -40% and therefore excludes nothing at all.

What changed when the measurement was corrected

The earlier raw-rarity clamp got 11 of 14 right (Baxcalibur really is the rarest at 0.0007%), but 3 were wrong and are now retired: Dusknoir (0.1389%), Grimmsnarl (0.0799%) and Vanilluxe (0.0467%). It also missed 15. Current count: 26.

Retired bans need an explicit list

The emitter deliberately carries over unrecognised entries, to protect an operator's hand-picked species from being deleted by a regeneration. That means a ban this tooling invented could never be withdrawn by it, so retired species are named in an explicit RETIRED list.


4. The other exclusion groups

Total excluded: 163. The config blacklisted-spawns holds 152 of them; the other 11 are Ultra Beasts, which are excluded in code and deliberately absent from the list.

Group Count How it was derived
Legendary 71 legendary form tag
Mythical 23 mythical form tag
Ultra Beast 11 ultrabeast form tag, code-excluded
Paradox 20 Pokedex number, by hand
Structure-only 2 no open-world entry in any pool
Trigger-only (curry) 10 set subtraction across the spawn pools
Too rare 26 measured spawn chance, see above

Legendary, mythical and Ultra Beast are THREE DISJOINT SETS

ReforgedBingo.isBlacklisted() checks isLegendary() || isUltraBeast(). Pixelmon builds LEGENDARIES, MYTHICALS and ULTRA_BEASTS from three separate form tags with zero overlap, so mythicals were entirely unfiltered: Mew, Celebi, Jirachi, Arceus, Darkrai and 18 more could land on a card. The tell was in the stock config all along, which blacklisted exactly one species: hoopa, a mythical. That was the hole being patched by hand.

Paradox is a FOURTH group, with no tag at all

Nothing in code excluded them, and there is no paradox tag or list in the jar to generate from (the only paradox/ directory holds 4 DLC research triggers, not the set). They are enumerated by dex: 984-989, 990-995, 1005, 1006, 1009, 1010, 1020-1023.

Four of them (Gouging Fire, Raging Bolt, Iron Boulder, Iron Crown) have zero spawn entries. Since generateNewCard() draws over the whole registry with no notion of spawnability, each was an uncompletable square that killed its row, its column and possibly a diagonal.

The curry-only ten

Azurill, Bonsly, Budew, Chingling, Elekid, Happiny, Igglybuff, Mime Jr., Smoochum, Tyrogue. Derived by subtracting the union of the other eleven sets under data/pixelmon/spawning/ from curry: every species in the curry set and no other.

⚠️ These are NOT dead squares, unlike the four Paradox mons. PokemonCatchListener also subscribes to EggHatchEvent.Post, so hatching a bred baby marks the square. They were banned because reaching one means a curry cook or a breeding chain, not because it is impossible, so the Paradox "unobtainable" reasoning must not be reused here.

Ditto and Gimmighoul

The only two species in the standard pool with no open-world spawn whatsoever: every entry for both carries a condition.structures (Ditto is haunted-tower-only; Gimmighoul needs a pyramid, ruined portal, graveyard, haunted tower or waypoint). Catchable, so this is a playability call rather than a dead square.

They live in the generator's INDIVIDUAL list rather than a derived group, so that regenerating the derived lists after a Pixelmon bump cannot silently drop a hand-made choice.


5. maximum-evolution is off by one against its own comment

The stock comment claims 1 allows middle evolutions like Charmeleon. The check is:

if (value.getDefaultForm().getPreEvolutions().size() >= maximumEvolution) return false;

>= N REJECT, so N allows stages 0 to N-1. A value of 1 therefore allows base forms only, and final evolutions need 3, not 2.

Live value was raised 1 to 3 on 2026-08-08. At 1 it was excluding 465 of 904 standard-pool species, thirty times what the blacklist removed.

⚠️ Opening that gate makes cards HARDER until bucket quotas land. The stock mod draws uniformly (getRandomSpecies(); canPickPokemon() only rejects, never steers), so a 25-square card then expects roughly 8.8 common / 7.4 uncommon / 6.6 rare / 2.2 ultra-rare. The rarity quota in snowbird.2 and later is what makes it fair again, which is why the two belong in the same change window, quota first.


6. Names cannot miss on a separator, but a wrong name is silent

Registry lookup runs StringHelper.toID(): lowercase, then strip every non-alphanumeric. So Ho-Oh, ho-oh and hooh are one key.

But getBlacklistedSpawns() does fromNameOrDex(...).orElse(null) and skips nulls, so a genuinely wrong name is dropped with no error at all. That is why the list is generated from data/pixelmon/species/*.json rather than typed, and why the wiki generator asserts every blacklist entry resolves.


7. Regenerating

Step Command
Tier every species ./scripts/categorize_bingo_spawns.py (repo root of Minecraft-Server-Project)
Measure real spawn chance ~/PycharmProjects/PixelmonWiki/.venv/bin/python scripts/max_spawn_chance.py
Rebuild the config blacklist scripts/build_bingo_rewards_config.py, pushed by scripts/push_bingo_rewards_to_main.sh
Rebuild the wiki page ~/PycharmProjects/PixelmonWiki/.venv/bin/python scripts/live/live_update_bingo.py

Full method for the rarity work: documentation/mods/bingo-spawn-rarity.md.

Re-run all of it after a Pixelmon bump. The tiers, the ban list and the Paradox enumeration are all keyed to the species and spawn data of one Pixelmon version.