Status: planning
Goal
Keep the roster pinned to dex #1-151 (base forms only) but bring the engine up to current-gen Showdown mechanics. The flavor we're after: vintage roster + modern fight feel.
Scope
In:
- Modern stats / movepools / move BPs / accuracies (re-synced from current @pkmn/sim).
- Abilities (data-driven from each species's
[Ability1, Ability2, HiddenAbility]).
- Items (Choice band/specs/scarf, Life Orb, Leftovers, berries, etc.).
- Weather (Rain / Sun / Sand / Hail).
- Whatever new move mechanics from the audit are worth keeping (Knock Off, U-turn, Substitute, hazards, screens, etc.).
Out:
- Mega Evolution, Z-moves, Dynamax / Gigantamax, Terastalization. These are competitive-meta gimmicks bolted on top of the core engine — they're not the "feel" we want.
- Alolan / Galarian / Hisuian / Paldean regional forms. Same-dex-number ≠ same-mon; we keep base forms only.
- Doubles / triples / multi-battle mechanics (Helping Hand, Wide Guard, Follow Me, ally-side effects).
- Gen-1 nostalgia mechanics (1/256 miss bug, freeze never thaws, etc.) — we want modern, not authentic-vintage.
- Hand-curating ability or moveset tables. If Showdown's data doesn't say it, we don't ship it.
Plan
Step 1 — Re-sync upstream from current gen
- Flip
tools/data-sync/refresh-upstream/refresh.js from GEN = 1 to current (Gen 9 today). Keep the dex 1-151 + base-form filter intact.
- Extend
dumpSpecies to emit each species's abilities triple ({0, 1, H}).
- Extend
dumpMoves to capture the fields the static dump can carry that we currently drop (e.g. breaksProtect, forceSwitch, selfSwitch, sleepUsable, multihit, thawsTarget, etc.). Showdown's JS callbacks still aren't dumpable; those go on the manualMoveFlags table.
- Run
make sync and let validation fail loudly on every unknown flag / volatile. That failure list IS the audit input.
Step 2 — Move + mechanic audit
- For every move that's new (or whose flags / effects diff from the Gen-1 version), categorize:
- (a) already modeled — just relabel the flag.
- (b) needs new flag / volatile / state — file a sub-ticket.
- (c) out of scope — add to a curated denylist in
transform.go so the move is filtered from learnsets rather than failing validation.
- Output a triage doc (
docs/modernization-audit.md or similar) listing each bucket and the sub-tickets in (b), roughly priority-ranked by "how many Gen-1 mons learn this and how impactful is it."
- Likely top of (b): Knock Off, U-turn / Volt Switch, Substitute, Stealth Rock / Spikes, Reflect / Light Screen, Protect, Foul Play, Body Press, Taunt, Encore, Disable.
Step 3 — Weather
- Engine field
BattleState.Weather struct { Kind, TurnsLeft int }.
- Modifier hook table (
onSourceModifyDamage, onModifySpD, etc.) — same shape we'll reuse for abilities + items.
- 4 effects (Rain / Sun / Sand / Hail) + setter moves (Rain Dance / Sunny Day / Sandstorm / Hail) + residuals.
- Acceptance: Charizard's Fire Blast hits harder in Sun, Rhydon takes Sandstorm residual immunity, Politoed's Drizzle ability triggers Rain on switch-in (once abilities ship).
Step 4 — Abilities
- Data field on
engine.Pokemon populated from species's ability triple + picker selection (default = slot 0).
- Effect resolver wired into the same hook table weather built.
- First batch (~20 abilities) covers the most-impactful Gen-1 species: Intimidate (Tauros / Gyarados / Arcanine), Levitate (Gengar / Misdreavus-not-in-scope), Thick Fat (Snorlax / Dewgong), Sturdy (Onix / Geodude), Drizzle (Politoed via post-Gen-1 ability but Politoed is #186 — skip; Kyogre — out of dex), etc.
- Stretch: hidden abilities optionally pickable in the picker room.
Step 5 — Items
- Same hook table again. Held item slot in
TeamPick + picker UI.
- First batch: Choice Band / Specs / Scarf, Life Orb, Leftovers, Black Sludge, Focus Sash, Assault Vest, Eviolite, common berries (Sitrus, Lum, type-resist).
Step 6 — New move mechanics
- Burn down the (b) bucket from the audit in priority order.
Open questions
- @pkmn/sim version pin: do we float on the latest minor, or pin to a specific Showdown gen-9 patch? Argue: pin, so Gen 9 balance tweaks don't drift in silently.
- Picker UI changes: ability + item slots add two more dropdowns per Pokemon. Default to "first slot" so old picks still work without changes.
- Determinism: weather turn counters, hazard state, switch-in triggers all need to be part of the serialized
BattleState so replay-from-seed still holds.
Depends on
Tracking
This is the meta issue. Step 2 will fan out into per-mechanic sub-tickets.
Status: planning
Goal
Keep the roster pinned to dex #1-151 (base forms only) but bring the engine up to current-gen Showdown mechanics. The flavor we're after: vintage roster + modern fight feel.
Scope
In:
[Ability1, Ability2, HiddenAbility]).Out:
Plan
Step 1 — Re-sync upstream from current gen
tools/data-sync/refresh-upstream/refresh.jsfromGEN = 1to current (Gen 9 today). Keep the dex 1-151 + base-form filter intact.dumpSpeciesto emit each species'sabilitiestriple ({0, 1, H}).dumpMovesto capture the fields the static dump can carry that we currently drop (e.g.breaksProtect,forceSwitch,selfSwitch,sleepUsable,multihit,thawsTarget, etc.). Showdown's JS callbacks still aren't dumpable; those go on themanualMoveFlagstable.make syncand let validation fail loudly on every unknown flag / volatile. That failure list IS the audit input.Step 2 — Move + mechanic audit
transform.goso the move is filtered from learnsets rather than failing validation.docs/modernization-audit.mdor similar) listing each bucket and the sub-tickets in (b), roughly priority-ranked by "how many Gen-1 mons learn this and how impactful is it."Step 3 — Weather
BattleState.Weather struct { Kind, TurnsLeft int }.onSourceModifyDamage,onModifySpD, etc.) — same shape we'll reuse for abilities + items.Step 4 — Abilities
engine.Pokemonpopulated from species's ability triple + picker selection (default = slot 0).Step 5 — Items
TeamPick+ picker UI.Step 6 — New move mechanics
Open questions
BattleStateso replay-from-seed still holds.Depends on
Tracking
This is the meta issue. Step 2 will fan out into per-mechanic sub-tickets.