Open Route 30 with map trainers and multi-Pokémon trainer battles
Map trainers run the ROM's TalkToTrainerScript and SeenByTrainerScript. _CheckTrainerBattle runs before tile events at the end of each step and on idle ticks; TrainerWalkToPlayer builds wMovementBuffer natively, and writeobjectxy keeps the trainer where it stopped. The interpreter gains the trainer header commands, wRunningTrainerBattleScript and hidden items (HiddenItemScript). Trainers with several Pokémon send out the next one through EnemyPartyMonEntrance and FindMonInOTPartyToSwitchIntoBattle, including its BattleRandom fallback. AI_SwitchOrTryItem, CheckAbleToSwitch and AI_Switch are translated with their original bugs, and wPlayerUsedMoves is recorded. The Shift-mode switch offer, trainer items, Pursuit on a switch, Perish Song and Spikes remain refused. Route 30 and its Berry house are enabled; Mr. Pokémon's house and Route 31 stay closed. A refused trainer sighting does not restart until the player moves, so a rollback cannot trap the player in view. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
0d1bedb3b1
commit
e00dfab42e
18 files changed
+1156
-62
No files matched your search
@@ -48,4 +48,4 @@ Asset caches and the ROM reader remain in memory for lazy extraction. Neither RO
|
||||
|
||||
The native viewport follows its available CSS dimensions and draws additional world tiles at a bounded pixel resolution. Beyond a map's edge it draws the connected map with the current tileset, as the original connection strips do, and the border block elsewhere. Resizing also redraws paused sessions. The local minimap caches terrain from the loaded map and updates its marker from the same world position used by the player; the Map tab shares that view. It is a current-area map, not a full region atlas. Leaving Game pauses the session and releases held input; returning requires explicit play. The reference player retains its own fixed-screen styling.
|
||||
|
||||
`game/battle` now holds the native battle core and ROM-backed battle tables. Browser tests cover the overworld-to-battle flow using a test-only encounter fixture; Route 29 uses ROM encounter tables. Scripted single-Pokémon trainer battles share that core, with ROM trainer decoders and explicit AI support checks; test fixtures exercise these without opening new production maps. Introduce future modules with working features: `game/audio`, then `features/link` and `features/walking`. Party and bag models live in `game/party`; scripts change them only on their draft state. Rules must not import UI/browser modules. Transports and step providers must not write directly into world state.
|
||||
`game/battle` now holds the native battle core and ROM-backed battle tables. Browser tests cover the overworld-to-battle flow using a test-only encounter fixture; Route 29 uses ROM encounter tables. Trainer battles share that core, with ROM trainer decoders, the trainer's send-out and switch AI, and explicit AI support checks. Map trainers (sight and talk) are started by `game/world` and run the ROM's own trainer scripts. Introduce future modules with working features: `game/audio`, then `features/link` and `features/walking`. Party and bag models live in `game/party`; scripts change them only on their draft state. Rules must not import UI/browser modules. Transports and step providers must not write directly into world state.
|
||||
+12
-2
@@ -73,8 +73,18 @@ Native saves are version 3. Version 2 added scene values by owning map, phone co
|
||||
|
||||
`game/battle/ai.ts` translates `AIChooseMove`, `AI_Redundant` and the Basic, Setup, Types, Offensive, Opportunist, Aggressive, Cautious, Status and Risky layers. It preserves the original random tie selection, known redundancy quirks, HP thresholds, exclusions and the deterministic pre-variation damage estimate used by Aggressive and Risky. Smart remains refused, including the rival's AI. Synthetic scoring vectors establish the tested branches; original-engine AI execution parity is still pending.
|
||||
|
||||
`loadtrainer`, `winlosstext` and `startbattle` now run single-Pokémon trainer battles through the existing battle UI. Tests cover Joey's ROM party/text/reward, RUN refusal, trainer experience, Amulet Coin, CANLOSE behavior, money limits, transactional rollback and midbattle restore. Chromium and WebKit exercise the UI with a test-only script. Production map gates are unchanged. Trainer items, party switching, sight lines, trainer-object interaction and the rival round trip remain unported.
|
||||
`loadtrainer`, `winlosstext` and `startbattle` run scripted trainer battles through the existing battle UI. Tests cover Joey's ROM party/text/reward, RUN refusal, trainer experience, Amulet Coin, CANLOSE behavior, money limits, transactional rollback and midbattle restore. Chromium and WebKit exercise the UI with a test-only script.
|
||||
|
||||
## Map trainers
|
||||
|
||||
`home/trainers.asm` and `engine/events/trainer_scripts.asm`: talking to an `OBJECTTYPE_TRAINER` object runs `TalkToTrainerScript` with the object's header copied as `wTempTrainer`; `_CheckTrainerBattle` runs `SeenByTrainerScript` with `wSeenTrainerDistance`. The world checks sight in `PlayerEvents` order: before warps, coordinate events and encounters at the end of a step (a seen player's tile events are then skipped, as `DisableEvents` does), and on idle ticks before scene scripts and input. Walls and objects do not block sight. `TrainerWalkToPlayer`/`ComputePathToWalkToPlayer` build the raw `wMovementBuffer` bytes, which `applymovementlasttalked` decodes with the normal movement reader. `wRunningTrainerBattleScript` lives in the script run: zero at the start, set by `loadmem` after the battle so `endifjustbattled` ends the after-script. Trainer commands without a map trainer are refused. `MomTriesToBuySomething` after scripted battles does nothing while Mom's savings (not ported) are zero.
|
||||
|
||||
`engine/battle/core.asm` and `engine/battle/ai/items.asm`, `switch.asm`: when a trainer's Pokémon faints and others remain, `UpdateBattleStateAndExperienceAfterEnemyFaint` zeroes its party HP and runs `NewEnemyMonStatus`; `EnemyPartyMonEntrance` then sends out the Pokémon chosen by `FindMonInOTPartyToSwitchIntoBattle`. When every candidate is threatened it draws `BattleRandom & 7`, which tests pin. `AI_SwitchOrTryItem` runs before either side moves: `CheckAbleToSwitch`, the Often/Rarely/Sometimes thresholds, `AI_TrySwitch` and `AI_Switch` (withdraw text, HP and status back to the party). `CheckTypeMatchup` ignores the type its switch-AI callers load and uses `BATTLE_VARS_MOVE_TYPE`, so every such matchup uses the enemy's chosen move type; `FindEnemyMonsWithASuperEffectiveMove` never resets its result between Pokémon; `FindEnemyMonsWithAtLeastQuarterMaxHP` rotates HP bits instead of multiplying. All three bugs are kept. `UsedMoveText` records `wPlayerUsedMoves`. Refused: the Shift-mode offer to switch (`OfferSwitch`), `AskUseNextPokemon` with other Pokémon left, Pursuit on a switching Pokémon, Perish Song, Spikes, and trainer items. Side effects of the type scans on the move structs (overwritten types and animation) are not modelled; the next `ParseEnemyAction`/`ParsePlayerAction` reloads them.
|
||||
|
||||
`BGEVENT_ITEM` runs `HiddenItemScript` with `wHiddenItemData`; `SetMemEvent` sets the item's flag.
|
||||
|
||||
A trainer sighting whose script is refused is not restarted until the player moves. This is a native safeguard, not original behavior.
|
||||
|
||||
## Next slice
|
||||
|
||||
Route 29 and Cherrygrove are enabled with item balls, fruit trees and the daily reset, the Pokémon Center nurse and the recorded whiteout spawn. NPCs roam. Next: trainer sight lines and trainer battles, capture with the catching tutorial, and party, bag and Pokégear menus over the native models. Other specials stay refused until translated.
|
||||
Route 29, Cherrygrove and Route 30 are enabled with item balls, hidden items, fruit trees and the daily reset, the Pokémon Center nurse, the recorded whiteout spawn and map trainers. NPCs roam. Next: Mr. Pokémon's house and the Mystery Egg, capture with the catching tutorial, Reflect/Light Screen, and party, bag and Pokégear menus over the native models. Other specials stay refused until translated.
|
||||
+15
-5
@@ -49,7 +49,7 @@ The emulator-backed prototype is now at `/reference.html`. The default applicati
|
||||
|
||||
## Done: Route 29 and Cherrygrove City
|
||||
|
||||
- Route 29, its Route 46 gate, Cherrygrove City and its five buildings are enabled. Route 30 and Route 46 remain closed.
|
||||
- Route 29, its Route 46 gate, Cherrygrove City and its five buildings are enabled. Route 46 remains closed.
|
||||
- Item balls run the ROM's `FindItemInBallScript`. Fruit trees run `FruitTreeScript`, with picked trees saved and regrown by a native `CheckDailyResetTimer` that clears the daily engine flags once per game day.
|
||||
- The Pokémon Center nurse runs `PokecenterNurseScript`: `HealParty` (with `ComputeMaxPP`'s PP Up clamp), `CheckPokerus` and the phone-call checks. Entering a Center from a town or route records the whiteout spawn, as `EnterMapWarp` does.
|
||||
- Standard Poké Marts run `pokemart` natively from `StandardMart`, `BuyMenu` and `SellMenu`: stock from the ROM's `Marts` table, `ItemAttributes` prices, half-price selling and the original texts, with keyboard, D-pad and pointer menus. Special mart types remain refused.
|
||||
@@ -65,11 +65,21 @@ The emulator-backed prototype is now at `/reference.html`. The default applicati
|
||||
- Native move scoring for Basic, Setup, Types, Offensive, Opportunist, Aggressive, Cautious, Status and Risky, with deterministic tie selection and the original pre-variation damage estimate. Smart remains refused.
|
||||
- Scripted single-Pokémon trainer battles support the challenge, sending out, RUN refusal, experience, win/loss text and prize money, including Amulet Coin. Script results, party changes and rewards commit together; interrupted saves replay from committed state.
|
||||
- Local-ROM tests and Chromium/WebKit tests exercise Youngster Joey through a test-only script. No new maps or trainer encounters are enabled in normal play.
|
||||
- Next: Smart AI, trainer party switching/items, trainer sight lines and normal trainer-object scripts, then the rival and Route 30 story. The rival remains refused because Smart AI is not yet translated.
|
||||
- Next: Smart AI, trainer items and player switching, then the rival and the rest of the Route 30 story. The rival remains refused because Smart AI is not yet translated.
|
||||
|
||||
## Implemented: Route 30 trainers
|
||||
|
||||
- Map trainers run the ROM's `TalkToTrainerScript` and `SeenByTrainerScript`. `_CheckTrainerBattle` runs before tile events after each step and on every idle tick: the first unbeaten trainer facing the player in line within its sight range spots them. The native `TrainerWalkToPlayer` path is played from `wMovementBuffer`, and `writeobjectxy` keeps the trainer where it stopped (saved with the map's moved objects).
|
||||
- New script commands: `loadtemptrainer`, `trainertext`, `trainerflagaction`, `scripttalkafter`, `endifjustbattled`, `checkjustbattled`, `writeobjectxy`, `encountermusic` (silent) and `loadmem` for `wRunningTrainerBattleScript`.
|
||||
- Trainers with several Pokémon: `HandleEnemyMonFaint` sends out the next one through `EnemySwitch_SetMode`, `FindMonInOTPartyToSwitchIntoBattle` (including its `BattleRandom` fallback) and `NewEnemyMonStatus`. `AI_SwitchOrTryItem` translates `CheckAbleToSwitch` with its original bugs (every matchup uses the enemy's move type; the quarter-HP test rotates bits) and `AI_Switch`. The player's used moves are recorded for it.
|
||||
- Hidden items (`BGEVENT_ITEM`) run `HiddenItemScript`.
|
||||
- Route 30 and its Berry house are enabled. Mr. Pokémon's house and Route 31 stay closed; Youngster Joey (after the Egg) needs phone registration and stays hidden until then, as in the original.
|
||||
- A refused trainer script does not restart until the player moves, so a rollback cannot trap the player in a trainer's sight.
|
||||
- A local stress run of 1,080 Route 30 battles (three starters, four levels, three times of day, both trainers and wild encounters) found one refusal: Chikorita's Reflect at level 12 (`screen`, not yet ported).
|
||||
|
||||
## In progress: native battles
|
||||
|
||||
The battle core, ROM tables, encounter hooks, battle UI and whiteout hooks are present. Unit tests cover wins, escape, loss, experience and move learning; reference tests compare damage and type effectiveness. Browser tests drive a test-only wild encounter through the real UI: victory with level-up and move learning, escape, whiteout, keyboard and on-screen D-pad menu navigation, mid-battle backup restore, and rollback of unsupported effects. Real Route 29 encounters now use the ROM's encounter tables. Capture, switching, items in battle, trainer battles and the rest of the opening quest remain unfinished.
|
||||
The battle core, ROM tables, encounter hooks, battle UI and whiteout hooks are present. Unit tests cover wins, escape, loss, experience and move learning; reference tests compare damage and type effectiveness. Browser tests drive a test-only wild encounter through the real UI: victory with level-up and move learning, escape, whiteout, keyboard and on-screen D-pad menu navigation, mid-battle backup restore, and rollback of unsupported effects. Real Route 29 encounters now use the ROM's encounter tables. Capture, player switching, items in battle and the rest of the opening quest remain unfinished.
|
||||
|
||||
This is still not a complete new game. Party/bag/Pokégear menus, story progression beyond Cherrygrove, decorations, animated terrain, surfing and audio remain unfinished. Save slots, a Johto/Kanto atlas, Pokédex records, online Link, friends and real-world steps come later.
|
||||
|
||||
@@ -77,7 +87,7 @@ This is still not a complete new game. Party/bag/Pokégear menus, story progress
|
||||
|
||||
Map headers, location names, connection offsets, connected-border drawing, coordinate events, scene scripts, map callbacks and scripted movement are in place (see above). Next: enable connected transitions as their maps are ported; add dynamic warps, elevators, ice, currents, remaining forced movement, surfing, cycling, cut trees and boulders. Player turn timing still needs a reference comparison.
|
||||
|
||||
Port decorations, tile changes (`changeblock`), the remaining NPC movement types (followers, bouncing, Strength boulders), trainer sight lines and the remaining movement commands. Complete terrain animation, layering and special palettes. Record deviations from the original until a comparison test closes them.
|
||||
Port decorations, tile changes (`changeblock`), the remaining NPC movement types (followers, bouncing, Strength boulders) and the remaining movement commands. Complete terrain animation, layering and special palettes. Record deviations from the original until a comparison test closes them.
|
||||
|
||||
Acceptance: representative outdoor/interior/cave/connected-map traces produce matching positions, collisions, transitions and event changes in native and reference engines. Do not enable an area merely because its image can be decoded.
|
||||
|
||||
@@ -87,7 +97,7 @@ Introduce native player, party, Pokémon, inventory, money and quest models. Rea
|
||||
|
||||
Expand script calls, choices, scene state, inventory commands and native special handlers. Translate routines reached through assembly calls into explicit native services; never fall back to emulator execution in the shipping game.
|
||||
|
||||
Meeting Mom, Elm's introduction, the starter, the aide's Potion, Route 29 and Cherrygrove run now. Next: trainer sight lines and trainer battles, Route 30 and Mr. Pokémon, the Mystery Egg round trip with the catching tutorial and the rival battle; then the introduction's naming and clock screens.
|
||||
Meeting Mom, Elm's introduction, the starter, the aide's Potion, Route 29, Cherrygrove and Route 30's trainers run now. Next: Mr. Pokémon's house, the Mystery Egg round trip with the catching tutorial and the rival battle; then the introduction's naming and clock screens.
|
||||
|
||||
Complete and validate the native battle engine: deterministic randomness, stats, move selection, accuracy/critical checks, damage, status, turn order, switching, fainting, experience, capture and rewards. Compare controlled seeds and states with the original, including integer rounding and overflow behavior.
|
||||
|
||||
|
||||
@@ -195,3 +195,34 @@ tests; native and reference builds; reference, release and vendor checks;
|
||||
Next (unchanged): Smart AI before the rival, or trainer sight lines and
|
||||
normal trainer-object scripts for Route 30's Youngster and Bug Catcher.
|
||||
|
||||
## Route 30 trainers: 2026-09-24
|
||||
|
||||
Chose option 2 from the review above: trainer sight lines and trainer-object
|
||||
scripts. Both Route 30 trainers have two Pokémon, so the increment also ports
|
||||
the trainer's send-out and switch AI. Route 30 and its Berry house are now
|
||||
enabled in production.
|
||||
|
||||
- World: `_CheckTrainerBattle` at step end (before warps, coordinate events and
|
||||
encounters) and on idle ticks; `TalkToTrainer` for `OBJECTTYPE_TRAINER`;
|
||||
`BGEVENT_ITEM` hidden items. A refused sighting is not restarted until the
|
||||
player moves (native safeguard against a rollback loop).
|
||||
- Interpreter: `loadtemptrainer`, `trainertext`, `trainerflagaction`,
|
||||
`scripttalkafter`, `endifjustbattled`, `checkjustbattled`, `writeobjectxy`,
|
||||
`encountermusic`, `loadmem wRunningTrainerBattleScript`, `readmem
|
||||
wHiddenItemID`, and callasm `TrainerWalkToPlayer`/`SetMemEvent`.
|
||||
`applymovementlasttalked wMovementBuffer` decodes the native buffer.
|
||||
- Battle: multi-Pokémon trainer parties (`HandleEnemyMonFaint`,
|
||||
`EnemyPartyMonEntrance`, `FindMonInOTPartyToSwitchIntoBattle` with its
|
||||
`BattleRandom` fallback), `AI_SwitchOrTryItem`/`CheckAbleToSwitch`/`AI_Switch`
|
||||
with the original type-matchup, `e`-carry and quarter-HP bugs, and
|
||||
`wPlayerUsedMoves`. `BattleTrainer` now requires `switchFlags`.
|
||||
- Stress (local, not committed): 1,080 Route 30 battles; the only refusal was
|
||||
Chikorita's Reflect at level 12 (`screen`), a pre-existing gap.
|
||||
|
||||
Final checks: 160 unit tests with the local ROM; 44 Chromium/WebKit browser
|
||||
tests including the Route 30 sighting through the UI; native and reference
|
||||
builds; reference, release and vendor checks; `git diff --check`. Not committed.
|
||||
|
||||
Next: Mr. Pokémon's house (Oak, Pokédex, Mystery Egg) and the return to Elm;
|
||||
Reflect/Light Screen; then Smart AI before the rival. Joey (after the Egg)
|
||||
needs `askforphonenumber` and the phone standard scripts.
|
||||
Reference in new issue
Block a user