Add starter, gift, and fossil encounters to seed data

Define special encounter data (starters, gifts, fossils) in a new
special_encounters module and merge them into route seed JSON during
generation. Add new route locations to ROUTE_ORDER for cities that
previously had no wild encounters (Saffron City, Pewter City, etc.).
Show colored method badges in the EncounterModal UI for special
encounter types.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-07 13:50:49 +01:00
parent 73d4a1831c
commit d488c252b8
21 changed files with 7430 additions and 5384 deletions

View File

@@ -15,6 +15,8 @@ import re
import sys
from pathlib import Path
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"
@@ -461,6 +463,7 @@ ROUTE_ORDER: dict[str, list[str]] = {
"Route 22",
"Route 2",
"Viridian Forest",
"Pewter City",
"Route 3",
"Mt Moon",
"Route 4",
@@ -480,6 +483,8 @@ ROUTE_ORDER: dict[str, list[str]] = {
"Route 8",
"Route 7",
"Celadon City",
"Saffron City",
"Lavender Town",
"Route 16",
"Route 17",
"Route 18",
@@ -553,6 +558,7 @@ ROUTE_ORDER: dict[str, list[str]] = {
"Ilex Forest",
"National Park",
"Route 35",
"Goldenrod City",
"Route 36",
"Route 37",
"Ecruteak City",
@@ -589,6 +595,7 @@ ROUTE_ORDER: dict[str, list[str]] = {
"Route 1",
"Viridian City",
"Viridian Forest",
"Pewter City",
"Route 2",
"Route 3",
"Mt Moon",
@@ -637,6 +644,7 @@ ROUTE_ORDER: dict[str, list[str]] = {
"Petalburg Woods",
"Rusturf Tunnel",
"Route 116",
"Rustboro City",
"Route 105",
"Route 106",
"Dewford Town",
@@ -653,6 +661,7 @@ ROUTE_ORDER: dict[str, list[str]] = {
"Route 112",
"Fiery Path",
"Jagged Pass",
"Lavaridge Town",
"Route 113",
"Route 114",
"Meteor Falls",
@@ -813,6 +822,29 @@ def aggregate_encounters(raw_encounters: list[dict]) -> list[dict]:
return sorted(result, key=lambda x: (-x["encounter_rate"], x["pokemon_name"]))
def merge_special_encounters(routes: list[dict], special_data: dict[str, list[dict]]) -> list[dict]:
"""Merge special encounters into existing routes or create new ones."""
# Build lookup: route name -> route dict (including children)
route_map: dict[str, dict] = {}
for r in routes:
route_map[r["name"]] = r
for child in r.get("children", []):
route_map[child["name"]] = child
for location_name, encounters in special_data.items():
for enc in encounters:
all_pokemon_dex.add(enc["national_dex"])
if location_name in route_map:
route_map[location_name]["encounters"].extend(encounters)
else:
new_route = {"name": location_name, "order": 0, "encounters": encounters}
routes.append(new_route)
route_map[location_name] = new_route
return routes
def process_version(version_name: str, vg_info: dict, vg_key: str) -> list[dict]:
"""Process all locations for a specific game version.
@@ -911,6 +943,11 @@ def process_version(version_name: str, vg_info: dict, vg_key: str) -> list[dict]
"encounters": aggregated,
})
# Merge special encounters (starters, gifts, fossils)
special_data = SPECIAL_ENCOUNTERS.get(vg_key, {})
if special_data:
routes = merge_special_encounters(routes, special_data)
# Sort routes by game progression order
routes = sort_routes_by_progression(routes, vg_key)