Add Pokemon form support to seeding (Alolan, regional variants, etc.)
Pokemon forms with dex IDs >= 10000 (e.g., Alolan Rattata = 10091) were being collected in encounter data but missing from pokemon.json, causing them to be silently dropped during DB seeding. Now fetch_all_pokemon() also fetches form entries that appear in encounter data, with clean display names like "Rattata (Alola)" and correct form-specific types. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,10 +1,11 @@
|
||||
---
|
||||
# nuzlocke-tracker-f44d
|
||||
title: Add Pokemon forms support to seeding
|
||||
status: todo
|
||||
status: completed
|
||||
type: task
|
||||
priority: normal
|
||||
created_at: 2026-02-06T10:11:23Z
|
||||
updated_at: 2026-02-06T10:11:23Z
|
||||
updated_at: 2026-02-07T13:30:57Z
|
||||
---
|
||||
|
||||
The current seeding only fetches base Pokemon species. It should also include alternate forms (Alolan, Galarian, Mega, regional variants, etc.) which have different types and stats.
|
||||
|
||||
@@ -85,71 +85,9 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Eterna City",
|
||||
"order": 2,
|
||||
"encounters": [
|
||||
{
|
||||
"national_dex": 129,
|
||||
"pokemon_name": "magikarp",
|
||||
"method": "old-rod",
|
||||
"encounter_rate": 100,
|
||||
"min_level": 3,
|
||||
"max_level": 15
|
||||
},
|
||||
{
|
||||
"national_dex": 54,
|
||||
"pokemon_name": "psyduck",
|
||||
"method": "surf",
|
||||
"encounter_rate": 90,
|
||||
"min_level": 20,
|
||||
"max_level": 30
|
||||
},
|
||||
{
|
||||
"national_dex": 130,
|
||||
"pokemon_name": "gyarados",
|
||||
"method": "super-rod",
|
||||
"encounter_rate": 55,
|
||||
"min_level": 30,
|
||||
"max_level": 55
|
||||
},
|
||||
{
|
||||
"national_dex": 129,
|
||||
"pokemon_name": "magikarp",
|
||||
"method": "good-rod",
|
||||
"encounter_rate": 55,
|
||||
"min_level": 10,
|
||||
"max_level": 25
|
||||
},
|
||||
{
|
||||
"national_dex": 339,
|
||||
"pokemon_name": "barboach",
|
||||
"method": "good-rod",
|
||||
"encounter_rate": 45,
|
||||
"min_level": 10,
|
||||
"max_level": 25
|
||||
},
|
||||
{
|
||||
"national_dex": 340,
|
||||
"pokemon_name": "whiscash",
|
||||
"method": "super-rod",
|
||||
"encounter_rate": 45,
|
||||
"min_level": 30,
|
||||
"max_level": 55
|
||||
},
|
||||
{
|
||||
"national_dex": 55,
|
||||
"pokemon_name": "golduck",
|
||||
"method": "surf",
|
||||
"encounter_rate": 10,
|
||||
"min_level": 20,
|
||||
"max_level": 40
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Pastoria City",
|
||||
"order": 3,
|
||||
"order": 2,
|
||||
"encounters": [
|
||||
{
|
||||
"national_dex": 129,
|
||||
@@ -235,7 +173,7 @@
|
||||
},
|
||||
{
|
||||
"name": "Sunyshore City",
|
||||
"order": 4,
|
||||
"order": 3,
|
||||
"encounters": [
|
||||
{
|
||||
"national_dex": 129,
|
||||
@@ -321,7 +259,7 @@
|
||||
},
|
||||
{
|
||||
"name": "Pokemon League",
|
||||
"order": 5,
|
||||
"order": 4,
|
||||
"encounters": [
|
||||
{
|
||||
"national_dex": 129,
|
||||
@@ -399,12 +337,12 @@
|
||||
},
|
||||
{
|
||||
"name": "Oreburgh Mine",
|
||||
"order": 6,
|
||||
"order": 5,
|
||||
"encounters": [],
|
||||
"children": [
|
||||
{
|
||||
"name": "Oreburgh Mine (1F)",
|
||||
"order": 7,
|
||||
"order": 6,
|
||||
"encounters": [
|
||||
{
|
||||
"national_dex": 74,
|
||||
@@ -434,7 +372,7 @@
|
||||
},
|
||||
{
|
||||
"name": "Oreburgh Mine (B1F)",
|
||||
"order": 8,
|
||||
"order": 7,
|
||||
"encounters": [
|
||||
{
|
||||
"national_dex": 74,
|
||||
@@ -466,7 +404,7 @@
|
||||
},
|
||||
{
|
||||
"name": "Valley Windworks",
|
||||
"order": 9,
|
||||
"order": 8,
|
||||
"encounters": [
|
||||
{
|
||||
"national_dex": 129,
|
||||
@@ -600,7 +538,7 @@
|
||||
},
|
||||
{
|
||||
"name": "Eterna Forest",
|
||||
"order": 10,
|
||||
"order": 9,
|
||||
"encounters": [
|
||||
{
|
||||
"national_dex": 406,
|
||||
@@ -756,6 +694,68 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Eterna City",
|
||||
"order": 10,
|
||||
"encounters": [
|
||||
{
|
||||
"national_dex": 129,
|
||||
"pokemon_name": "magikarp",
|
||||
"method": "old-rod",
|
||||
"encounter_rate": 100,
|
||||
"min_level": 3,
|
||||
"max_level": 15
|
||||
},
|
||||
{
|
||||
"national_dex": 54,
|
||||
"pokemon_name": "psyduck",
|
||||
"method": "surf",
|
||||
"encounter_rate": 90,
|
||||
"min_level": 20,
|
||||
"max_level": 30
|
||||
},
|
||||
{
|
||||
"national_dex": 130,
|
||||
"pokemon_name": "gyarados",
|
||||
"method": "super-rod",
|
||||
"encounter_rate": 55,
|
||||
"min_level": 30,
|
||||
"max_level": 55
|
||||
},
|
||||
{
|
||||
"national_dex": 129,
|
||||
"pokemon_name": "magikarp",
|
||||
"method": "good-rod",
|
||||
"encounter_rate": 55,
|
||||
"min_level": 10,
|
||||
"max_level": 25
|
||||
},
|
||||
{
|
||||
"national_dex": 339,
|
||||
"pokemon_name": "barboach",
|
||||
"method": "good-rod",
|
||||
"encounter_rate": 45,
|
||||
"min_level": 10,
|
||||
"max_level": 25
|
||||
},
|
||||
{
|
||||
"national_dex": 340,
|
||||
"pokemon_name": "whiscash",
|
||||
"method": "super-rod",
|
||||
"encounter_rate": 45,
|
||||
"min_level": 30,
|
||||
"max_level": 55
|
||||
},
|
||||
{
|
||||
"national_dex": 55,
|
||||
"pokemon_name": "golduck",
|
||||
"method": "surf",
|
||||
"encounter_rate": 10,
|
||||
"min_level": 20,
|
||||
"max_level": 40
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Fuego Ironworks",
|
||||
"order": 11,
|
||||
|
||||
@@ -8724,5 +8724,145 @@
|
||||
"ghost"
|
||||
],
|
||||
"sprite_url": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/1025.png"
|
||||
},
|
||||
{
|
||||
"national_dex": 10016,
|
||||
"name": "Basculin (Blue Striped)",
|
||||
"types": [
|
||||
"water"
|
||||
],
|
||||
"sprite_url": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/10016.png"
|
||||
},
|
||||
{
|
||||
"national_dex": 10091,
|
||||
"name": "Rattata (Alola)",
|
||||
"types": [
|
||||
"dark",
|
||||
"normal"
|
||||
],
|
||||
"sprite_url": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/10091.png"
|
||||
},
|
||||
{
|
||||
"national_dex": 10092,
|
||||
"name": "Raticate (Alola)",
|
||||
"types": [
|
||||
"dark",
|
||||
"normal"
|
||||
],
|
||||
"sprite_url": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/10092.png"
|
||||
},
|
||||
{
|
||||
"national_dex": 10101,
|
||||
"name": "Sandshrew (Alola)",
|
||||
"types": [
|
||||
"ice",
|
||||
"steel"
|
||||
],
|
||||
"sprite_url": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/10101.png"
|
||||
},
|
||||
{
|
||||
"national_dex": 10103,
|
||||
"name": "Vulpix (Alola)",
|
||||
"types": [
|
||||
"ice"
|
||||
],
|
||||
"sprite_url": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/10103.png"
|
||||
},
|
||||
{
|
||||
"national_dex": 10105,
|
||||
"name": "Diglett (Alola)",
|
||||
"types": [
|
||||
"ground",
|
||||
"steel"
|
||||
],
|
||||
"sprite_url": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/10105.png"
|
||||
},
|
||||
{
|
||||
"national_dex": 10106,
|
||||
"name": "Dugtrio (Alola)",
|
||||
"types": [
|
||||
"ground",
|
||||
"steel"
|
||||
],
|
||||
"sprite_url": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/10106.png"
|
||||
},
|
||||
{
|
||||
"national_dex": 10107,
|
||||
"name": "Meowth (Alola)",
|
||||
"types": [
|
||||
"dark"
|
||||
],
|
||||
"sprite_url": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/10107.png"
|
||||
},
|
||||
{
|
||||
"national_dex": 10109,
|
||||
"name": "Geodude (Alola)",
|
||||
"types": [
|
||||
"rock",
|
||||
"electric"
|
||||
],
|
||||
"sprite_url": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/10109.png"
|
||||
},
|
||||
{
|
||||
"national_dex": 10110,
|
||||
"name": "Graveler (Alola)",
|
||||
"types": [
|
||||
"rock",
|
||||
"electric"
|
||||
],
|
||||
"sprite_url": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/10110.png"
|
||||
},
|
||||
{
|
||||
"national_dex": 10112,
|
||||
"name": "Grimer (Alola)",
|
||||
"types": [
|
||||
"poison",
|
||||
"dark"
|
||||
],
|
||||
"sprite_url": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/10112.png"
|
||||
},
|
||||
{
|
||||
"national_dex": 10114,
|
||||
"name": "Exeggutor (Alola)",
|
||||
"types": [
|
||||
"grass",
|
||||
"dragon"
|
||||
],
|
||||
"sprite_url": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/10114.png"
|
||||
},
|
||||
{
|
||||
"national_dex": 10123,
|
||||
"name": "Oricorio (Pom Pom)",
|
||||
"types": [
|
||||
"electric",
|
||||
"flying"
|
||||
],
|
||||
"sprite_url": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/10123.png"
|
||||
},
|
||||
{
|
||||
"national_dex": 10124,
|
||||
"name": "Oricorio (Pau)",
|
||||
"types": [
|
||||
"psychic",
|
||||
"flying"
|
||||
],
|
||||
"sprite_url": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/10124.png"
|
||||
},
|
||||
{
|
||||
"national_dex": 10125,
|
||||
"name": "Oricorio (Sensu)",
|
||||
"types": [
|
||||
"ghost",
|
||||
"flying"
|
||||
],
|
||||
"sprite_url": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/10125.png"
|
||||
},
|
||||
{
|
||||
"national_dex": 10126,
|
||||
"name": "Lycanroc (Midnight)",
|
||||
"types": [
|
||||
"rock"
|
||||
],
|
||||
"sprite_url": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/10126.png"
|
||||
}
|
||||
]
|
||||
@@ -19,7 +19,8 @@ from app.seeds.special_encounters import SPECIAL_ENCOUNTERS
|
||||
|
||||
REPO_ROOT = Path(__file__).parents[4] # backend/src/app/seeds -> repo root
|
||||
POKEAPI_DIR = REPO_ROOT / "data" / "pokeapi" / "data" / "api" / "v2"
|
||||
DATA_DIR = Path(__file__).parent / "data"
|
||||
SEEDS_DIR = Path(__file__).parent
|
||||
DATA_DIR = SEEDS_DIR / "data"
|
||||
|
||||
|
||||
def load_resource(endpoint: str, resource_id: int) -> dict:
|
||||
@@ -704,6 +705,170 @@ ROUTE_ORDER: dict[str, list[str]] = {
|
||||
"Artisan Cave",
|
||||
"Altering Cave",
|
||||
],
|
||||
"platinum": [
|
||||
"Canalave City",
|
||||
"Pastoria City",
|
||||
"Sunyshore City",
|
||||
"Pokemon League",
|
||||
"Oreburgh Mine",
|
||||
"Oreburgh Mine (1F)",
|
||||
"Oreburgh Mine (B1F)",
|
||||
"Valley Windworks",
|
||||
"Eterna Forest",
|
||||
"Eterna City",
|
||||
"Fuego Ironworks",
|
||||
"Mt Coronet",
|
||||
"Mt Coronet (1F Route 207)",
|
||||
"Mt Coronet (2F)",
|
||||
"Mt Coronet (3F)",
|
||||
"Mt Coronet (Exterior Snowfall)",
|
||||
"Mt Coronet (Exterior Blizzard)",
|
||||
"Mt Coronet (4F)",
|
||||
"Mt Coronet (4F Small Room)",
|
||||
"Mt Coronet (5F)",
|
||||
"Mt Coronet (6F)",
|
||||
"Mt Coronet (1F From Exterior)",
|
||||
"Mt Coronet (1F Route 216)",
|
||||
"Mt Coronet (1F Route 211)",
|
||||
"Mt Coronet (B1F)",
|
||||
"Great Marsh",
|
||||
"Great Marsh (Area 1)",
|
||||
"Great Marsh (Area 2)",
|
||||
"Great Marsh (Area 3)",
|
||||
"Great Marsh (Area 4)",
|
||||
"Great Marsh (Area 5)",
|
||||
"Great Marsh (Area 6)",
|
||||
"Solaceon Ruins",
|
||||
"Solaceon Ruins (2F)",
|
||||
"Solaceon Ruins (1F)",
|
||||
"Solaceon Ruins (B1F A)",
|
||||
"Solaceon Ruins (B1F B)",
|
||||
"Solaceon Ruins (B1F C)",
|
||||
"Solaceon Ruins (B2F A)",
|
||||
"Solaceon Ruins (B2F B)",
|
||||
"Solaceon Ruins (B2F C)",
|
||||
"Solaceon Ruins (B3F A)",
|
||||
"Solaceon Ruins (B3F B)",
|
||||
"Solaceon Ruins (B3F C)",
|
||||
"Solaceon Ruins (B3F D)",
|
||||
"Solaceon Ruins (B3F E)",
|
||||
"Solaceon Ruins (B4F A)",
|
||||
"Solaceon Ruins (B4F B)",
|
||||
"Solaceon Ruins (B4F C)",
|
||||
"Solaceon Ruins (B4F D)",
|
||||
"Solaceon Ruins (B5F)",
|
||||
"Victory Road",
|
||||
"Victory Road (1F)",
|
||||
"Victory Road (2F)",
|
||||
"Victory Road (B1F)",
|
||||
"Victory Road (Inside B1F)",
|
||||
"Victory Road (Inside)",
|
||||
"Victory Road (Inside Exit)",
|
||||
"Ravaged Path",
|
||||
"Oreburgh Gate",
|
||||
"Oreburgh Gate (1F)",
|
||||
"Oreburgh Gate (B1F)",
|
||||
"Stark Mountain (Entrance)",
|
||||
"Stark Mountain (Inside)",
|
||||
"Stark Mountain",
|
||||
"Turnback Cave",
|
||||
"Turnback Cave (Pillar 1)",
|
||||
"Turnback Cave (Pillar 2)",
|
||||
"Turnback Cave (Pillar 3)",
|
||||
"Turnback Cave (Before Pillar 1)",
|
||||
"Turnback Cave (Between Pillars 1 And 2)",
|
||||
"Turnback Cave (Between Pillars 2 And 3)",
|
||||
"Turnback Cave (After Pillar 3)",
|
||||
"Snowpoint Temple",
|
||||
"Snowpoint Temple (1F)",
|
||||
"Snowpoint Temple (B1F)",
|
||||
"Snowpoint Temple (B2F)",
|
||||
"Snowpoint Temple (B3F)",
|
||||
"Snowpoint Temple (B4F)",
|
||||
"Snowpoint Temple (B5F)",
|
||||
"Wayward Cave",
|
||||
"Wayward Cave (1F)",
|
||||
"Wayward Cave (B1F)",
|
||||
"Ruin Maniac Cave",
|
||||
"Ruin Maniac Cave (0 9 Different Unown Caught)",
|
||||
"Ruin Maniac Cave (10 25 Different Unown Caught)",
|
||||
"Trophy Garden",
|
||||
"Iron Island (1F)",
|
||||
"Iron Island (B1F Left)",
|
||||
"Iron Island (B1F Right)",
|
||||
"Iron Island (B2F Right)",
|
||||
"Iron Island (B2F Left)",
|
||||
"Iron Island (B3F)",
|
||||
"Iron Island",
|
||||
"Old Chateau",
|
||||
"Old Chateau (Entrance)",
|
||||
"Old Chateau (Dining Room)",
|
||||
"Old Chateau (2F Private Room)",
|
||||
"Old Chateau (2F)",
|
||||
"Old Chateau (2F Leftmost Room)",
|
||||
"Old Chateau (2F Left Room)",
|
||||
"Old Chateau (2F Middle Room)",
|
||||
"Old Chateau (2F Right Room)",
|
||||
"Old Chateau (2F Rightmost Room)",
|
||||
"Lake Verity",
|
||||
"Lake Verity (Before Galactic Intervention)",
|
||||
"Lake Verity (After Galactic Intervention)",
|
||||
"Lake Valor",
|
||||
"Lake Acuity",
|
||||
"Valor Lakefront",
|
||||
"Acuity Lakefront",
|
||||
"Route 201",
|
||||
"Route 202",
|
||||
"Route 203",
|
||||
"Route 204",
|
||||
"Route 204 (South Towards Jubilife City)",
|
||||
"Route 204 (North Towards Floaroma Town)",
|
||||
"Route 205",
|
||||
"Route 205 (South Towards Floaroma Town)",
|
||||
"Route 205 (East Towards Eterna City)",
|
||||
"Route 206",
|
||||
"Route 207",
|
||||
"Route 208",
|
||||
"Route 209",
|
||||
"Lost Tower",
|
||||
"Lost Tower (1F)",
|
||||
"Lost Tower (2F)",
|
||||
"Lost Tower (3F)",
|
||||
"Lost Tower (4F)",
|
||||
"Lost Tower (5F)",
|
||||
"Route 210",
|
||||
"Route 210 (South Towards Solaceon Town)",
|
||||
"Route 210 (West Towards Celestic Town)",
|
||||
"Route 211",
|
||||
"Route 211 (West Towards Eterna City)",
|
||||
"Route 211 (East Towards Celestic Town)",
|
||||
"Route 212",
|
||||
"Route 212 (North Towards Hearthome City)",
|
||||
"Route 212 (East Towards Pastoria City)",
|
||||
"Route 213",
|
||||
"Route 214",
|
||||
"Route 215",
|
||||
"Route 216",
|
||||
"Route 217",
|
||||
"Route 218",
|
||||
"Route 219",
|
||||
"Route 221",
|
||||
"Route 222",
|
||||
"Route 224",
|
||||
"Route 225",
|
||||
"Route 227",
|
||||
"Route 228",
|
||||
"Route 229",
|
||||
"Twinleaf Town",
|
||||
"Celestic Town",
|
||||
"Resort Area",
|
||||
"Sea Route 220",
|
||||
"Sea Route 223",
|
||||
"Sea Route 226",
|
||||
"Sea Route 230",
|
||||
"Sendoff Spring",
|
||||
"Maniac Tunnel"
|
||||
]
|
||||
}
|
||||
|
||||
# Aliases — version groups sharing same route progression
|
||||
@@ -975,22 +1140,42 @@ def process_version(version_name: str, vg_info: dict, vg_key: str) -> list[dict]
|
||||
return routes
|
||||
|
||||
|
||||
def format_form_name(poke_data: dict) -> str:
|
||||
"""Convert a PokeAPI pokemon form entry to a clean display name.
|
||||
|
||||
e.g. 'rattata-alola' (species: 'rattata') -> 'Rattata (Alola)'
|
||||
"""
|
||||
species_name = poke_data["species"]["name"]
|
||||
full_name = poke_data["name"]
|
||||
if full_name.startswith(species_name + "-"):
|
||||
form_suffix = full_name[len(species_name) + 1:]
|
||||
base = species_name.title().replace("-", " ")
|
||||
suffix = form_suffix.title().replace("-", " ")
|
||||
return f"{base} ({suffix})"
|
||||
return full_name.title().replace("-", " ")
|
||||
|
||||
|
||||
def fetch_all_pokemon() -> list[dict]:
|
||||
"""Fetch all Pokemon species from the local PokeAPI data."""
|
||||
"""Fetch all Pokemon species + encountered forms from the local PokeAPI data."""
|
||||
pokemon_dir = POKEAPI_DIR / "pokemon-species"
|
||||
|
||||
# Get all species IDs (directories with numeric names, excluding forms 10000+)
|
||||
# Get all base species IDs
|
||||
all_species = []
|
||||
for entry in pokemon_dir.iterdir():
|
||||
if entry.is_dir() and entry.name.isdigit():
|
||||
dex = int(entry.name)
|
||||
if dex < 10000: # Exclude alternate forms
|
||||
if dex < 10000:
|
||||
all_species.append(dex)
|
||||
|
||||
# Also include form IDs that appear in encounter data
|
||||
form_ids = sorted(d for d in all_pokemon_dex if d >= 10000)
|
||||
|
||||
all_species.sort()
|
||||
print(f"\n--- Fetching {len(all_species)} Pokemon species ---")
|
||||
print(f"\n--- Fetching {len(all_species)} Pokemon species + {len(form_ids)} forms ---")
|
||||
|
||||
pokemon_list = []
|
||||
|
||||
# Fetch base species
|
||||
for i, dex in enumerate(all_species, 1):
|
||||
poke = load_resource("pokemon", dex)
|
||||
types = [t["type"]["name"] for t in poke["types"]]
|
||||
@@ -1000,9 +1185,22 @@ def fetch_all_pokemon() -> list[dict]:
|
||||
"types": types,
|
||||
"sprite_url": f"https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/{dex}.png",
|
||||
})
|
||||
|
||||
if i % 100 == 0 or i == len(all_species):
|
||||
print(f" Fetched {i}/{len(all_species)}")
|
||||
print(f" Fetched {i}/{len(all_species)} species")
|
||||
|
||||
# Fetch forms (from pokemon endpoint, with form-aware naming)
|
||||
for form_dex in form_ids:
|
||||
poke = load_resource("pokemon", form_dex)
|
||||
types = [t["type"]["name"] for t in poke["types"]]
|
||||
pokemon_list.append({
|
||||
"national_dex": form_dex,
|
||||
"name": format_form_name(poke),
|
||||
"types": types,
|
||||
"sprite_url": f"https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/{form_dex}.png",
|
||||
})
|
||||
|
||||
if form_ids:
|
||||
print(f" Fetched {len(form_ids)} forms")
|
||||
|
||||
return sorted(pokemon_list, key=lambda x: x["national_dex"])
|
||||
|
||||
@@ -1081,8 +1279,9 @@ def fetch_evolution_data(seeded_dex: set[int]) -> list[dict]:
|
||||
print(f"\n--- Fetching evolution chains ---")
|
||||
|
||||
# First, get the evolution chain URL for each pokemon species
|
||||
# Skip form IDs (>= 10000) — they don't have pokemon-species entries
|
||||
chain_ids: set[int] = set()
|
||||
dex_sorted = sorted(seeded_dex)
|
||||
dex_sorted = sorted(d for d in seeded_dex if d < 10000)
|
||||
|
||||
for i, dex in enumerate(dex_sorted, 1):
|
||||
species = load_resource("pokemon-species", dex)
|
||||
|
||||
Reference in New Issue
Block a user