Verify random battle and capture routines against the original engine
Checks / web (push) Canceled after 0s
Checks / web (push) Canceled after 0s
This commit is contained in:
1 parent
be7575a4d0
commit
00972bad10
9 files changed
+978
-74
No files matched your search
+42
-2
@@ -48,6 +48,26 @@ The opening scenes currently run end to end from the ROM: Mom's Pokégear, weekd
|
||||
|
||||
The same suite compares 400 damage cases and 400 type-effectiveness cases per browser against the original battle routines, 300 `CalcMonStats` cases (with and without stat experience, including levels above 100 that reach the 999 cap) and every `CalcExpAtLevel` value for the six growth rates and levels 1–100. Battle unit tests cover win, escape, loss, experience, level-up and move-learning flows, and `tests/playthrough.test.ts` plays the whole opening quest from a new game through `GameWorld`'s inputs, with save/reload after each stage. This establishes parity only for the compared routines and inputs. It does not prove complete gameplay, rendering, battles, audio, timing or physical-device parity. Extend controlled comparisons as each subsystem is translated.
|
||||
|
||||
`tests/reference-random.spec.ts` also executes the unpatched
|
||||
`BattleCommand_Critical`, `BattleCommand_CheckHit` and
|
||||
`BattleCommand_DamageVariation` routines. The original Link RNG and the native
|
||||
random callback start from the same ten-byte stream. Each case compares the
|
||||
result, modified accuracy, miss damage and final RNG stream/cursor, covering
|
||||
skipped draws and rejection sampling across stream regeneration. Each browser
|
||||
runs 2,560 critical cases, 2,914 accuracy cases and 2,149 damage-variation cases.
|
||||
Critical coverage includes every random byte at all five reachable stages,
|
||||
Focus Energy, Scope Lens and the species-specific items. Accuracy coverage
|
||||
includes all stage pairs, Foresight, BrightPowder, perfect accuracy, X Accuracy,
|
||||
rain/Thunder, Dream Eater, drain/substitute failure and Jump Kick miss damage.
|
||||
Damage coverage includes 0/1's no-draw path, rounding and 16-bit boundaries.
|
||||
Mutating each command's threshold or divisor makes its comparison fail.
|
||||
|
||||
These are isolated command comparisons using controlled Link RNG inputs, not
|
||||
a claim of Link battle support or matching the hardware-timed non-Link RNG.
|
||||
Protect's text path and the refused Lock-On/Fly/Dig paths are outside these
|
||||
fixtures. Capture decision comparisons are described below; whole-battle
|
||||
reference comparisons remain open.
|
||||
|
||||
## Validation
|
||||
|
||||
```sh
|
||||
@@ -153,8 +173,28 @@ division by zero. Pure vectors cover the catch formula; local-ROM tests
|
||||
cover capture, every break-free message, Master Ball draws, blank
|
||||
nicknames, the blocked trainer ball, full-party rollback, both tutorial
|
||||
triggers, declining and the repeat offer, and mid-battle reloads. Browser
|
||||
tests cover PACK, catching and naming. No emulator comparison of the
|
||||
capture routines has been run.
|
||||
tests cover PACK, catching and naming.
|
||||
|
||||
`tests/reference-capture.spec.ts` compares the production capture decision
|
||||
and shake loop with `PokeBallEffect`'s calculation and the original
|
||||
`GetPokeBallWobble`. Each browser runs 3,220 capture cases and 7,424 shake
|
||||
cases: every catch-rate byte and supported multiplier, HP scaling and
|
||||
wrapping, status bonuses, success-draw equality, every random byte at each
|
||||
wobble-table entry, early/later escapes, and the Master Ball/tutorial
|
||||
bypasses. Final rates, outcomes, shake counts and random-draw counts match.
|
||||
The native decision and shake loop are private helpers called by the actual
|
||||
ball-use path; existing capture integration tests still exercise that path.
|
||||
|
||||
Unlike the battle commands, capture calls hardware `Random`. This fixture
|
||||
patches its entry in the private in-page ROM copy to consume supplied bytes,
|
||||
enters after the capture UI setup, and inserts a return after the decision.
|
||||
The catch arithmetic, ball multipliers and wobble routine are unmodified.
|
||||
It does not compare hardware RNG timing, animation, caught-mon reloading,
|
||||
party/PC writes, or a whole battle. No real held item has `HELD_CATCH_CHANCE`,
|
||||
so that synthetic effect remains covered by pure vectors only. Maximum HP
|
||||
342 and 683 are omitted from emulator execution because their divisor is
|
||||
zero; synthetic tests verify the native refusal. Deliberate mutations of
|
||||
success equality, formula rounding and shake equality fail the comparisons.
|
||||
|
||||
## Switching, battle items and the stats screen
|
||||
|
||||
|
||||
+3
-2
@@ -235,14 +235,15 @@ their scripts and story progression are supported.
|
||||
- [x] Player switching and every non-ball battle item, with the stats screen
|
||||
- [x] The PC and boxes (catching with a full party)
|
||||
- [x] The introduction's naming and clock screens
|
||||
- [ ] Controlled-seed comparisons with the original for random-driven routines (accuracy, criticals, damage variation, capture). Damage, types, stats and experience curves are compared.
|
||||
- [x] Controlled-seed comparisons with the original for accuracy, criticals and damage variation, including random-stream consumption. Damage, types, stats and experience curves are also compared.
|
||||
- [x] Controlled-input comparisons of capture odds, success and ball shakes with the original, including random-draw counts. Hardware RNG timing and the full capture sequence remain outside this comparison.
|
||||
- [x] Acceptance: one continuous playthrough of the opening quest with save/reload (`tests/playthrough.test.ts`, driven through the world's inputs rather than the browser UI)
|
||||
|
||||
Introduce native player, party, Pokémon, inventory, money and quest models. Read species, moves, growth curves, evolutions, encounters, trainers and items through typed ROM decoders. Define serialization/migrations before persisting new systems.
|
||||
|
||||
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. Next: controlled-seed comparisons of the random-driven battle routines.
|
||||
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. Next: party and bag menus outside battle, MOVE PKMN W/O MAIL and evolution.
|
||||
|
||||
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.
|
||||
|
||||
|
||||
+81
-1
@@ -1,6 +1,6 @@
|
||||
# Recovered Claude session
|
||||
|
||||
Latest continuation: see **Battle items, hBattleTurn and the stats screen: 2026-09-30**
|
||||
Latest continuation: see **Controlled capture comparisons: 2026-09-30**
|
||||
at the end of this file. Earlier sections are historical snapshots.
|
||||
|
||||
Recovered on 2026-09-23 from the local Claude Code transcript
|
||||
@@ -607,3 +607,83 @@ without it); 97 Chromium/WebKit browser tests passed, 19 skipped
|
||||
intentionally; native and reference builds; reference, release and
|
||||
vendor checks; `git diff --check`. Committed and pushed to `main` as
|
||||
`b13e09e`.
|
||||
|
||||
## Controlled random battle comparisons: 2026-09-30
|
||||
|
||||
Resumed from `be7575a` with a clean working tree. The user requested a bounded
|
||||
increment suitable for a limited session. Continued PLAN section 2 with
|
||||
accuracy, criticals and damage variation; capture stays as the next item.
|
||||
|
||||
- `tests/reference-random.spec.ts` runs the original, unpatched
|
||||
`BattleCommand_Critical`, `BattleCommand_CheckHit` and
|
||||
`BattleCommand_DamageVariation` in the reference emulator. The native
|
||||
commands receive the same ten-byte Link RNG stream. Results include the
|
||||
final RNG stream/cursor, so extra or missing draws are detected too.
|
||||
- Per browser: 2,560 critical cases (all random bytes at all five reachable
|
||||
stages and held-item exceptions), 2,914 accuracy cases (all stage pairs,
|
||||
Foresight, BrightPowder, bypasses, Dream Eater/substitute and Jump Kick
|
||||
miss damage), and 2,149 variation cases (0/1, rounding, 16-bit boundaries,
|
||||
rejected draws and RNG stream regeneration).
|
||||
- Shared ROM input and symbol helpers moved from `reference-parity.spec.ts`
|
||||
into `tests/reference-fixture.ts`. No ROM bytes or extracted assets added.
|
||||
- Deliberately changing critical `<` to `<=`, accuracy `>=` to `>`, and the
|
||||
damage divisor from 255 to 256 each made its comparison fail. All three
|
||||
mutations were reverted; no production gameplay change was needed.
|
||||
|
||||
Boundary: these compare isolated commands with controlled random inputs.
|
||||
They do not compare a whole battle, the hardware-timed non-Link RNG, or the
|
||||
Protect text path. Lock-On/Fly/Dig remain refused. This does not enable Link
|
||||
battles or later maps.
|
||||
|
||||
Checks: 337 unit tests passed with the local ROM; 131 passed and 206
|
||||
skipped with an absent ROM. All 103 Chromium/WebKit browser tests passed,
|
||||
with the existing 19 intentional WebKit skips. Native and reference builds,
|
||||
reference, vendor and release checks, and `git diff --check` passed. No CI
|
||||
or physical-device run. This increment was initially left uncommitted and
|
||||
is included in the subsequent capture-comparison delivery below.
|
||||
|
||||
Next: controlled-input capture comparisons (`PokeBallEffect` and
|
||||
`GetPokeBallWobble`), then the party/bag menus outside battle, MOVE PKMN W/O
|
||||
MAIL and evolution. Keep section 2's capture checklist open until verified.
|
||||
|
||||
|
||||
## Controlled capture comparisons: 2026-09-30
|
||||
|
||||
Continued PLAN section 2 from the existing uncommitted accuracy, critical and
|
||||
damage-variation comparisons. Preserved that work and completed its next
|
||||
capture-comparison item.
|
||||
|
||||
- `tests/reference-capture.spec.ts` compares the native capture decision with
|
||||
the calculation inside `PokeBallEffect`, then its shake loop with
|
||||
`GetPokeBallWobble`. Per browser: 3,220 capture cases and 7,424 shake cases,
|
||||
including supported ball multipliers, all catch-rate bytes, HP scaling and
|
||||
overflow, status bonuses, equality boundaries, every random byte at each
|
||||
wobble-table entry, every escape count and guaranteed catches. Final rate,
|
||||
caught/escaped outcome, shake count and random-draw count agree.
|
||||
- Capture uses hardware `Random`, not `BattleRandom`. The private in-page ROM
|
||||
copy replaces `Random` with a supplied-byte reader; the fixture enters
|
||||
after the UI setup and inserts a return after `wWildMon` is written.
|
||||
Catch arithmetic, multipliers and `GetPokeBallWobble` remain unmodified.
|
||||
- Extracted `rollCapture` and `ballWobbles` as private production helpers
|
||||
called by `pokeBallEffect`, without changing gameplay behavior. Added
|
||||
maximum HP 683 beside 342 in the synthetic divide-by-zero regression.
|
||||
- Deliberately changing success `<=` to `<`, formula floor to ceiling, and
|
||||
shake `>=` to `>` each failed the comparisons. Mutations were reverted.
|
||||
|
||||
Boundary: isolated capture decision/shakes with supplied random bytes, not
|
||||
hardware RNG timing, animation, caught-mon reloading, party/PC writes or a
|
||||
whole battle. No actual item has `HELD_CATCH_CHANCE`; that effect remains
|
||||
covered by pure vectors. Native division-by-zero refusal remains in place;
|
||||
the emulator fixture omits the hanging HP inputs. No additional balls or
|
||||
maps are enabled.
|
||||
|
||||
Checks: 337 unit tests passed with the local ROM; 131 passed and 206 skipped
|
||||
with an absent ROM. All 107 Chromium/WebKit browser tests passed, with the
|
||||
existing 19 intentional WebKit skips. The four new capture tests skip cleanly
|
||||
without a ROM. Native and reference builds, reference, vendor and release
|
||||
checks, and `git diff --check` passed. No CI or physical-device run.
|
||||
The accuracy, critical, damage-variation and capture comparisons are delivered
|
||||
together, preserving the previously uncommitted work.
|
||||
|
||||
Next: party and bag menus outside battle, MOVE PKMN W/O MAIL and evolution.
|
||||
PLAN section 2 is complete within its recorded acceptance boundaries.
|
||||
Reference in new issue
Block a user