Battle PACK opens the Balls pocket and runs PokeBallEffect: the Poké, Great, Ultra and Master Ball multipliers, the original HP arithmetic (including the overflow above 341 maximum HP), the sleep/freeze bonus (BRN/PSN/PAR add nothing), HELD_CATCH_CHANCE and the catch draw. GetPokeBallWobble draws per shake from WobbleProbabilities and picks the break-free text. Trainer battles block the ball but still use it and the turn. A catch reloads the Pokémon as LoadEnemyMon does (the wild item roll is redrawn, then the item restored), keeps its HP, status, item and DVs, restores the moves and PP it appeared with, adds it to the party with SetCaughtData, registers it and offers a nickname with InitName's default. A catch with six Pokémon needs the PC and is refused. catchtutorial runs BATTLETYPE_TUTORIAL as "DUDE": no send-out, an automatic catch that keeps nothing and prompts that continue on their own. Both Route 29 triggers, declining and the Dude's repeat offer run from the ROM. The text reader now handles TX_LOW. PLAN.md gains a status overview and done/remaining checklists; the README, help dialog, routine map and handoff describe the milestone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
333 lines
18 KiB
Markdown
333 lines
18 KiB
Markdown
# Recovered Claude session
|
|
|
|
Recovered on 2026-09-23 from the local Claude Code transcript
|
|
`~/.claude/projects/-Users-kawa-Crystal/4ac88f30-29e6-4fd5-a4b2-b6a318dd83b3.jsonl`.
|
|
The session stopped at its usage limit at 09:54 UTC, during research, without a final handoff.
|
|
|
|
## Resumed increment: completed 2026-09-23
|
|
|
|
The movement increment below is complete. The remaining sections preserve the
|
|
original recovery context.
|
|
|
|
- Added directional two-tile ledge jumps with the existing arc/shadow animation.
|
|
Unsupported terrain, invalid destinations and occupied landings remain refused.
|
|
- Corrected directional mats to wait for exit input. Warp arrivals keep their
|
|
actual coordinates and appropriate facing; doors, stairs and caves animate a
|
|
downward exit. Removing the old inward teleport also corrected Elm's scripted
|
|
introduction position.
|
|
- Mid-walk, mid-jump and mid-connection saves retain the source position. Landing
|
|
scenes rewind to the actual source of a jump, rather than the intervening wall.
|
|
- Restored compatibility with early version-3 saves lacking the money field.
|
|
- Replaced the scratch diagnostic with synthetic movement regressions and
|
|
optional-ROM tests covering five Route 29 ledge types. Route 29 is enabled only
|
|
inside that test fixture, not in production.
|
|
- Fixed the battle test suite's eager ROM read so missing-ROM runs really skip
|
|
private tests. Updated browser stair inputs and added an exit-mat save/reload
|
|
flow. Updated the roadmap and architecture to distinguish the existing battle
|
|
code from its unfinished integration.
|
|
|
|
Final checks: 75 unit tests passed with the local ROM; without it, 55 passed and
|
|
20 private tests skipped. All 24 Chromium/WebKit browser tests passed. Native and
|
|
reference builds, release isolation, pinned-reference checks, vendor checks and
|
|
`git diff --check` passed. No commit or push was made.
|
|
|
|
Next: validate the overworld-to-battle browser flow and complete Route 29's
|
|
remaining script, capture/tutorial and item interactions before enabling the
|
|
route. Player turn timing also remains a documented comparison gap.
|
|
|
|
## Scope and current state
|
|
|
|
The original request was to read ARCHITECTURE.md, PLAN.md and PRESENTATION_PLAN.md
|
|
and continue the native port. The working tree contains substantial uncommitted
|
|
work from multiple increments; preserve it when continuing.
|
|
|
|
- Opening scenes, scripted movement, starter selection, naming, the aide's Potion
|
|
and version 3 saves are implemented and documented.
|
|
- Native battle modules, ROM tables, damage/type parity tests, encounter handling,
|
|
battle UI and whiteout handling have been added. These later changes are not
|
|
fully reflected in the architecture and roadmap documents.
|
|
- Only the original six maps are enabled in `NATIVE_MAPS`. Route 29 (`24:3`)
|
|
remains disabled. Passing battle unit tests does not establish a playable
|
|
Route 29 encounter or the full opening quest.
|
|
|
|
## Exact stopping point
|
|
|
|
Claude was preparing to revise player movement in `src/game/world/world.ts`.
|
|
Its last investigation concerned spawn facing after warps. It had not implemented
|
|
the planned ledge/warp revision.
|
|
|
|
The pinned local PRET checkout contains the relevant routines:
|
|
|
|
- `engine/overworld/player_movement.asm`: `.TryStep`, `.TryJump`,
|
|
`.CheckLandPerms`, `.CheckWarp` and the direction tables.
|
|
- `engine/overworld/tile_events.asm`: `CheckWarpCollision` and
|
|
`CheckDirectionalWarp`.
|
|
- `engine/overworld/player_object.asm`: `SpawnPlayer`.
|
|
- `engine/overworld/map_objects.asm`: movement/turn timing.
|
|
|
|
Research found that ledge tops have land permission; the jump check uses the
|
|
current tile and facing after an ordinary step fails. Doors use collision `$71`,
|
|
downward warp mats `$70`, and stairs `$7a`. Directional warp mats require their
|
|
designated input rather than an immediate warp simply upon entry. Verify these
|
|
rules against the local routines before changing the existing movement flow.
|
|
|
|
`tests/zz-scratch.test.ts` is Claude's unfinished diagnostic: it logs local-ROM
|
|
warp and ledge collisions, contains no assertions and unconditionally requires
|
|
the private ROM. Replace it with meaningful optional-ROM or synthetic tests
|
|
before treating the suite as ready for public CI.
|
|
|
|
## Validation after recovery
|
|
|
|
Run against the current working tree with the local ROM and reference checkout:
|
|
|
|
- `npm test`: 45 passed, including the assertion-free scratch diagnostic.
|
|
- `npm run build`: passed.
|
|
- `npm run test:e2e`: 22 passed across Chromium and WebKit, including native
|
|
damage/type comparisons against original routines in the reference emulator.
|
|
- `npm run check:reference`: ROM, pinned rebuild and profile addresses match.
|
|
- `npm run check:release`: native output excludes emulator and game assets.
|
|
- `npm run check:vendor`: passed.
|
|
|
|
These checks do not establish complete battle behavior, browser battle UI flows,
|
|
Route 29 progression or physical-device compatibility. No gameplay source was
|
|
changed during session recovery.
|
|
|
|
## Original next-increment notes (movement now completed)
|
|
|
|
Finish ledge and directional-warp movement with focused regression tests,
|
|
including interrupted movement/save behavior and preservation of the existing
|
|
opening scenes. Audit Route 29 callbacks, scripts and unsupported destinations
|
|
before enabling it. Then test wild encounters and battle controls through the
|
|
browser, including win, escape, loss and save/reload, and reconcile the roadmap
|
|
with the verified behavior.
|
|
|
|
## Battle integration increment: 2026-09-23 (resumed from Codex)
|
|
|
|
Codex committed and pushed `c08d250`, then stopped mid-increment with the
|
|
keyboard/D-pad battle test failing. Claude Code completed it:
|
|
|
|
- Browser battle flows run through the real UI via `tests/battle-fixture.ts`
|
|
(encounter selection only; production maps stay gated): win with level-up and
|
|
Smokescreen, escape, whiteout, keyboard/D-pad menus, mid-battle backup restore
|
|
and unsupported-effect rollback. `tests/battle-world.test.ts` covers the same
|
|
at world level, plus pending stat experience and whiteout callback rollback.
|
|
- Saves accept stored stats between the no-stat-exp and full-stat-exp values,
|
|
since `GiveExperiencePoints` awards stat experience without `CalcMonStats`.
|
|
- A script warp (e.g. whiteout) validates its destination and commits healing,
|
|
money loss and destination callbacks together; aborts restore state and map.
|
|
- Keyboard and on-screen D-pad navigate battle menus (`battle-selected`); A
|
|
continues messages, B leaves the move list.
|
|
- Fixed a phone-width layout bug: a long notice sat in the Play button's auto
|
|
grid column and crushed the status text, pushing the game panel off-screen.
|
|
Below 720px the notice now has its own row.
|
|
- Test fixes: the navigation test now presses A through the intro message, and
|
|
uses a real pointer click on the D-pad (synthetic pointer events cannot be
|
|
captured).
|
|
|
|
Final checks: 82 unit tests with the local ROM (55 passed, 27 skipped without
|
|
it); 36 Chromium/WebKit browser tests; native and reference builds; release,
|
|
vendor and reference checks; `git diff --check`. Not committed.
|
|
|
|
Next: Route 29 (`24:3`) scripts, catching tutorial and items before enabling it;
|
|
then capture, switching and PACK in battle.
|
|
|
|
## Route 29 and Cherrygrove increment: 2026-09-23
|
|
|
|
Enabled Route 29, its Route 46 gate, Cherrygrove City and its five buildings.
|
|
Item balls, the Pokémon Center nurse and the Poké Mart were each ported by a
|
|
Sonnet sub-agent in an isolated worktree, reviewed against the disassembly and
|
|
merged; the rest was done directly.
|
|
|
|
- Fruit trees run `FruitTreeScript`; a native `CheckDailyResetTimer` clears
|
|
the daily engine flags once per game day. `VAR_BOXSPACE` reads an empty box.
|
|
- Item balls run `FindItemInBallScript` with a native `TryReceiveItem`.
|
|
- The nurse runs `PokecenterNurseScript`; `HealParty` now applies
|
|
`ComputeMaxPP`'s PP Up clamp. `EnterMapWarp`'s spawn recording makes
|
|
whiteouts return to the last Pokémon Center entered.
|
|
- Standard marts run natively (`StandardMart`/`BuyMenu`/`SellMenu`).
|
|
- Battle command `recoil` (Struggle) was the only refusal found by a local
|
|
stress run of 360 Route 29 battles across starters and times of day.
|
|
- Save format 3 gained `fruitTrees`, `dailyReset` and `lastSpawnMap`
|
|
(migrated by absence).
|
|
- The phone-width status bar layout and parity test map counts were fixed.
|
|
|
|
Still refused: `catchtutorial` and Cherrygrove's rival scene (both after the
|
|
Mystery Egg), Route 30/46. NPCs do not roam yet.
|
|
|
|
Next: NPC roaming movement (`map_objects.asm` random walk/spin, radius and
|
|
visibility rules, deterministic RNG in tests), trainer sight lines and trainer
|
|
battles, Route 30 and Mr. Pokémon, capture and the catching tutorial.
|
|
|
|
## Trainer AI continuation: 2026-09-24
|
|
|
|
The trainer foundation was subsequently committed through `3e92936`. The next
|
|
AI increment translates Opportunist, Aggressive and Risky scoring, including
|
|
the ROM's stall/reckless/risky tables and Aggressive/Risky's deterministic
|
|
pre-variation damage estimate. Smart is now the only refused move-scoring layer,
|
|
so the rival remains gated. Continue with Smart before the rival, or with
|
|
trainer sight lines and normal trainer-object scripts for the already-supported
|
|
Youngster and Bug Catcher classes on Route 30.
|
|
|
|
## AI layer review: 2026-09-24 (resumed from Codex)
|
|
|
|
Claude Code checked Codex's uncommitted Opportunist, Aggressive and Risky layers
|
|
against `engine/battle/ai/scoring.asm`. The HP thresholds, `AI_50_50` (≥128),
|
|
`79 percent - 1` (200), last-wins ties, the power < 2 and reckless exclusions,
|
|
the strict-borrow KO test and the constant-damage paths all match.
|
|
|
|
One fix: `AIDamageCalc` goes through `EnemyAttackDamage` and
|
|
`BattleCommand_DamageCalc`, and both read `wCriticalHit`. A flag left over from
|
|
an earlier move therefore selects unboosted stats (ignoring screens) and
|
|
doubles the estimate. `enemyAIDamage` now reads the native `criticalHit`
|
|
instead of hard-coding `false`. It also reuses `truncate`. A local-ROM test
|
|
fixes the estimate at 4, 3 (Reflect) and 6 (leftover critical).
|
|
|
|
Known side effects of `AIDamageCalc` that are not modelled: it overwrites
|
|
`wCurDamage`, `wTypeModifier`, `wAttackMissed` and `hBattleTurn`. `CheckTurn`
|
|
resets the modifier and miss flag before each move. Whether the `wCurDamage`
|
|
overwrite can reach Counter/Mirror Coat still needs checking before those
|
|
effects are ported.
|
|
|
|
Final checks: 147 unit tests with the local ROM; 42 Chromium/WebKit browser
|
|
tests; native and reference builds; reference, release and vendor checks;
|
|
`git diff --check`. Not committed.
|
|
|
|
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.
|
|
|
|
## Reflect and Light Screen: 2026-09-24
|
|
|
|
Completed the battle gap found in the Route 30 stress run. `screen` now runs
|
|
both moves from ROM effect scripts. Independent five-turn counters include
|
|
the setup turn, do not refresh on repeated use, survive enemy send-outs and
|
|
expire with ROM text in `HandleScreens` order. The existing damage path handles
|
|
physical/special defense and critical stage rules.
|
|
|
|
Seven new local-ROM regressions cover player and enemy use, PP on failure,
|
|
concurrent durations, expiration order, send-out persistence and damage stats.
|
|
Also moved the NPC test's eager ROM read into `beforeAll`, restoring its
|
|
intended skip behavior when no ROM is available.
|
|
|
|
Checks: 167 unit tests with the local ROM; 76 passed and 91 skipped without it;
|
|
44 Chromium/WebKit browser tests; native and reference builds; reference,
|
|
release and vendor checks; `git diff --check`. Screen routines were reviewed
|
|
against pinned PRET source, not compared by executing the original routines.
|
|
Changes are uncommitted.
|
|
|
|
Next: Mr. Pokémon's house and the Mystery Egg; Smart AI before enabling the
|
|
rival; capture and the catching tutorial. Joey's post-Egg phone scripts remain
|
|
unsupported.
|
|
|
|
## Mr. Pokémon and the return to Elm: 2026-09-24 (resumed from Codex)
|
|
|
|
Codex had enabled Mr. Pokémon's house and added `NameRival`, `blackoutmod`,
|
|
`reloadmap`, the queued Elm call and the no-handler Smart AI subset. It
|
|
stopped with all four quest browser tests failing and without docs. Claude
|
|
Code finished the increment:
|
|
|
|
- The rival scene needed `special FadeOutMusic` (audio only, now accepted).
|
|
- The quest fixture's constant `() => 0` RNG hung `BattleCommand_DamageVariation`,
|
|
which redraws until the byte is at least 217. The fixture now uses a seeded LCG.
|
|
Relocating to Cherrygrove had also carried the house's moved Mr. Pokémon and
|
|
Oak onto the Guide Gent and rival (ids 2 and 3), producing an unrestorable
|
|
save. The fixture now clears objects and starts off the Guide Gent's tile.
|
|
- The browser test expected `specialPhoneCall` 1; `SPECIALCALL_ROBBED` is 2.
|
|
- `NameRival` yielded a naming choice with zero pages, because `promptbutton`
|
|
had already flushed them. The dialogue never reached its last page, so the
|
|
officer scene soft-locked. It now shows the ROM's "RIVAL'S NAME?" and reads
|
|
the "SILVER" default from ROM. As in `InitName`, blank names of any number of
|
|
spaces take the default. The naming input's accessible label no longer says
|
|
"Nickname".
|
|
- Elm's call now runs the ROM's `CheckSpecialPhoneCall.script` →
|
|
`Script_ReceivePhoneCall` wrapper. It reads the condition and caller script
|
|
from `SpecialPhoneCallList` instead of hard-coding id 2, adds `memcall`, and
|
|
shows `HangUp`'s timed "Click!". Ringing and the caller name box are still
|
|
not presented.
|
|
- Added tests: the rival scene for all three starters and both triggers, a
|
|
`CANLOSE` loss, reload after each scene, the Elm call (indoors, outdoors,
|
|
mid-call reload), the officer naming (named, blank, all-space, reload at
|
|
the naming screen), the Egg handover and the aide's Poké Balls, plus a
|
|
browser naming-field test.
|
|
|
|
Checks: 191 unit tests with the local ROM (80 passed, 111 skipped without it);
|
|
50 Chromium/WebKit browser tests; native and reference builds; reference,
|
|
release and vendor checks; `git diff --check`. Not committed.
|
|
|
|
Next: capture and the Route 29 catching tutorial (`catchtutorial`), the
|
|
first remaining refusal in the opening quest. Then the ringing presentation,
|
|
player switching and items in battle. Joey's post-Egg phone scripts remain
|
|
unsupported.
|
|
|
|
## Capture and the catching tutorial: 2026-09-24
|
|
|
|
Continued the roadmap with the first refusal remaining in the opening quest.
|
|
|
|
- Battle PACK opens the Balls pocket and runs `PokeBallEffect`: the Poké,
|
|
Great, Ultra and Master Ball multipliers, the original HP arithmetic
|
|
(including the overflow above 341 maximum HP), the sleep/freeze bonus
|
|
(BRN/PSN/PAR add nothing), `HELD_CATCH_CHANCE` and the catch draw.
|
|
`GetPokeBallWobble` draws per shake from `WobbleProbabilities` and picks
|
|
the break-free text. Trainer battles block the ball but still use it and
|
|
the turn. `catchRate` is exported for pure vectors.
|
|
- A catch reloads the Pokémon as `LoadEnemyMon` does (the wild item roll is
|
|
redrawn, then the original item restored), keeps HP/status/item/DVs,
|
|
restores the moves and PP it appeared with, adds it to the party with
|
|
`SetCaughtData`, registers it and offers a nickname (`InitName` default
|
|
for blank names). `NewDexDataText` shows when the Pokédex is owned.
|
|
`caughtData` is now shared with `givepoke`.
|
|
- `catchtutorial` runs `BATTLETYPE_TUTORIAL`: "DUDE" from the ROM as
|
|
`<PLAYER>`, no send-out, an automatic catch that keeps nothing, and
|
|
prompts that continue on their own. Both Route 29 triggers, declining and
|
|
`CatchingTutorialDudeScript`'s repeat offer run from the ROM.
|
|
- Text: `TX_LOW` ($05) is read as a line break (`ItemUsedText` needs it).
|
|
- UI: PACK lists the Balls pocket (B closes it); the in-battle nickname
|
|
prompt reuses the naming field. The help dialog and README describe the
|
|
current milestone.
|
|
- Refused: a catch with six Pokémon (the PC is not ported), other balls,
|
|
non-ball items in battle and a transformed target.
|
|
- Stress (local, not committed): 2,160 wild battles, 2,047 catches, no
|
|
refusals.
|
|
|
|
Checks: 207 unit tests with the local ROM (82 passed, 125 skipped without
|
|
it); 54 Chromium/WebKit browser tests; native and reference builds;
|
|
reference, release and vendor checks; `git diff --check`. The existing
|
|
keyboard/D-pad test now steps through the enabled PACK button. No
|
|
emulator comparison of the capture routines was run. Not committed.
|
|
|
|
Next: the PC and boxes (catching with a full party, `SendMonIntoBox`, Bill's
|
|
call), then player switching and other items in battle, and party and bag
|
|
menus. The Dude's back picture, ball animation and Pokédex page are not
|
|
presented.
|