Run the forced-shiny, trap, forced-item, Celebi, Suicune, roaming and Bug-Catching Contest battle types. Roaming battles keep their struct's DVs and HP byte, and every other battle makes CleanUpBattleRAM's roaming roll. The contest shows PARKBALL×, counts down Park Balls, ends when they run out, keeps its catch outside the party and asks before switching. Scripts load the special types with loadvar, and while a contest runs, encounters use BugCatchingContestBattleScript and ContestMons. Validated with 596 unit tests, 155 browser tests (including the contest menu and switch screen), native/reference builds and reference/vendor/release checks. National Park's contest event, the roaming release and the Ilex Forest Celebi event come with their maps. Closes #28 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
b547ca29ff
commit
8fae1f0c0f
15 files changed
+787
-42
No files matched your search
+10
-2
@@ -263,8 +263,16 @@ set it. A status heal after a full turn therefore penalises a paralysed
|
||||
or burned enemy again, as the original does. Kurt's balls keep their
|
||||
documented bugs (Heavy Ball bank, Fast Ball's three bytes, Moon Ball's
|
||||
BURN_HEAL compare, Love Ball's same gender). The Heavy Ball is refused for
|
||||
Kadabra and Sunflora, whose original weight read runs into VRAM. The
|
||||
Bug-Catching Contest's Park Ball count and contest Pokémon remain gaps.
|
||||
Kadabra and Sunflora, whose original weight read runs into VRAM.
|
||||
|
||||
Special battle types follow `LoadEnemyMon`, `TryToRunAwayFromBattle`,
|
||||
`BattleMenu`, `CheckContestBattleOver`, `PokeBallEffect`,
|
||||
`BugContest_SetCaughtContestMon` and `BattleEnd_HandleRoamMons`. The
|
||||
contest's Park Balls and caught Pokémon (`BugContest`) and a roaming
|
||||
Pokémon's struct (`RoamMon`) are passed in and updated by the battle. The
|
||||
world keeps the contest in its script state while one runs, and switches
|
||||
encounters to `BugCatchingContestBattleScript` and `ContestMons`. It has
|
||||
no roaming Pokémon yet.
|
||||
|
||||
`engine/pokemon/stats_screen.asm`: the stats screen's three pages (HP,
|
||||
status, types, experience to the next level; item and moves with PP; ID,
|
||||
|
||||
+9
-2
@@ -311,7 +311,14 @@ The numbered sections below keep their full scope. Each one opens with a checkli
|
||||
- For Kadabra and Sunflora the original Heavy Ball scan runs off the wrong bank into VRAM, so that throw is refused.
|
||||
- `tests/reference-capture.spec.ts` runs the unmodified `PokeBallEffect` over 6,153 more states per browser: every species for the Heavy, Fast, Moon and Love Balls, level pairs for the Level Ball and fishing for the Lure Ball.
|
||||
- There is no Safari Ball to port: `SAFARI_BALL` is Moon Stone's item number and never reaches `PokeBallEffect`.
|
||||
- Card #28 stays in progress for the Bug-Catching Contest's battle type (Park Ball count, contest Pokémon) and the other special battle types.
|
||||
|
||||
## Implemented: special battle types
|
||||
|
||||
- The battle engine runs every remaining wild battle type. The Red Gyarados (`BATTLETYPE_FORCESHINY`) has shiny DVs; Ho-Oh, Lugia and Snorlax (`FORCEITEM`) hold their first item without the item rolls, even when reloaded after a catch. The player cannot run from those, the trap battles, Celebi or Suicune. Celebi has its own appearance text and sets `BATTLERESULT_CAUGHT_CELEBI` when caught.
|
||||
- Roaming battles take and return a `wRoamMon` struct: the DVs are drawn once, Speed/Special first, and only the HP's low byte is kept. A win or a catch removes the Pokémon from the map. Every other battle ends with `CleanUpBattleRAM`'s one-in-sixteen roll to move the roaming Pokémon. The result reports it, but nothing roams yet: Raikou, Entei and Suicune are released in the Burned Tower.
|
||||
- In the Bug-Catching Contest the menu shows PARKBALL× with the count, and RUN always works. Each throw takes a Park Ball rather than an item from the pack, and the battle ends as a draw when the last one misses. A catch goes to the contest, not the party; a second catch shows both Pokémon and asks to switch. While a contest runs (`bugContest` in the script state), encounters use `BugCatchingContestBattleScript` and its `ContestMons` table, as `RandomEncounter` does.
|
||||
- Scripts can load the forced-shiny, trap, forced-item, Suicune and contest types with `loadvar VAR_BATTLETYPE`.
|
||||
- Still to come with their maps: National Park's contest event (registration, timer, judging; the contest state is not saved), Raikou's, Entei's and Suicune's roaming, and the Ilex Forest Celebi event with `CheckCaughtCelebi`.
|
||||
|
||||
## Native battles: current state
|
||||
|
||||
@@ -395,7 +402,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, Cherrygrove, Route 30's trainers, Mr. Pokémon's house, the Cherrygrove rival battle, the return to Elm, capture, the catching tutorial, the PC, the introduction's naming and clock screens, and switching and healing items in battle run now. The opening milestone is complete within the recorded acceptance boundaries. The start menu, party menu and pack now run outside battle, and Pokémon evolve. Field moves from the menu, SEL/Select and MOVE PKMN W/O MAIL run too, and the Pokégear's clock, map and phone cards, with calls to Mom and Elm, Mom's bank at home and her purchases, the trainer card with the play time, the options, Fly, Dig, Teleport and the Escape Rope, and Headbutt and Rock Smash with their encounters, every remaining field item, the fishing rods, MAIL, moving items with Select and the MOVE screen's other Pokémon. Kurt's balls are thrown too. Next: the Bug-Catching Contest and the other special battle types (board #28).
|
||||
Meeting Mom, Elm's introduction, the starter, the aide's Potion, Route 29, Cherrygrove, Route 30's trainers, Mr. Pokémon's house, the Cherrygrove rival battle, the return to Elm, capture, the catching tutorial, the PC, the introduction's naming and clock screens, and switching and healing items in battle run now. The opening milestone is complete within the recorded acceptance boundaries. The start menu, party menu and pack now run outside battle, and Pokémon evolve. Field moves from the menu, SEL/Select and MOVE PKMN W/O MAIL run too, and the Pokégear's clock, map and phone cards, with calls to Mom and Elm, Mom's bank at home and her purchases, the trainer card with the play time, the options, Fly, Dig, Teleport and the Escape Rope, and Headbutt and Rock Smash with their encounters, every remaining field item, the fishing rods, MAIL, moving items with Select and the MOVE screen's other Pokémon. Kurt's balls are thrown too, and the battle engine handles every special battle type (board #28 is complete). Next: Route 31 to Violet City (board #31).
|
||||
|
||||
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.
|
||||
|
||||
|
||||
@@ -1276,3 +1276,34 @@ Next on #28: the Bug-Catching Contest battle type (Park Ball count,
|
||||
`BugContest_SetCaughtContestMon`) and the other special battle types.
|
||||
Neither is reachable yet: National Park and the legendary encounters
|
||||
are not enabled.
|
||||
|
||||
## Special battle types: 2026-10-03
|
||||
|
||||
Same session; finishes card #28.
|
||||
|
||||
- `BattleOptions.battleType` takes FORCESHINY, TRAP, FORCEITEM, CELEBI,
|
||||
SUICUNE, CONTEST (with `contest`) and ROAMING (with `roamer`); invalid
|
||||
combinations raise `UnsupportedBattle` before any draw. `loadvar
|
||||
VAR_BATTLETYPE` passes the script-set ones; CleanUpBattleRAM's clear
|
||||
follows `startbattle`.
|
||||
- `run()` ends with `BattleEnd_HandleRoamMons`: one extra BattleRandom
|
||||
after every non-roaming battle (`updateRoamMons` in the outcome). The
|
||||
world ignores the flag until roaming Pokémon exist.
|
||||
- Contest: `{ kind: "action", parkBalls }` drives the PARKBALL× button;
|
||||
`{ kind: "contestswitch" }` is answered like Yes/No (world, keyboard and
|
||||
DOM). `ScriptState.bugContest` is runtime-only (not saved);
|
||||
`readmem wParkBallsRemaining` reads it. The fixture scenario `contest`
|
||||
covers it in `tests/battle-world.test.ts` and
|
||||
`tests/battle-browser.spec.ts`. The browser test found that the switch
|
||||
text was missing from the text box; it is fixed.
|
||||
- `tests/battle-types.test.ts` covers each type with the local ROM, plus
|
||||
a synthetic `loadvar` script.
|
||||
|
||||
Validation: 596 unit tests passed (3 skipped); without the ROM 141 passed,
|
||||
458 skipped. Browser suite: 155 passed, 19 skipped. Both builds,
|
||||
reference/release/vendor checks and `git diff --check` passed.
|
||||
|
||||
Left for the map cards: National Park's contest event (GiveParkBalls,
|
||||
timer, out-of-balls/time-up scripts, judging, saving the contest state),
|
||||
Burned Tower's roaming release with UpdateRoamMons/JumpRoamMons and
|
||||
roaming encounters, and Ilex Forest's CelebiShrineEvent/CheckCaughtCelebi.
|
||||
Reference in new issue
Block a user