diff --git a/docs/SESSION_HANDOFF.md b/docs/SESSION_HANDOFF.md index 9bb12ac..9cf62ec 100644 --- a/docs/SESSION_HANDOFF.md +++ b/docs/SESSION_HANDOFF.md @@ -1,6 +1,6 @@ # Recovered Claude session -Latest continuation: see **Headbutt and Rock Smash: 2026-10-02** +Latest continuation: see **Field items, fishing, Select and MAIL: 2026-10-03** at the end of this file. Earlier sections are historical snapshots. Recovered on 2026-09-23 from the local Claude Code transcript @@ -1094,3 +1094,74 @@ card to Fait). Not pushed. Manual check: card #51 in "A tester" (the shake and tree battles against the original), with `test-saves/headbutt.crystal-save.json` from `tests/human-test-saves.test.ts`; importing it and headbutting was checked once in Chromium and WebKit. + +## Field items, fishing, Select and MAIL: 2026-10-03 + +Resumed with "continue the plan" on a clean tree after `10e1560`, taking +board card #27 in four commits (none pushed): + +- `4cb4676`: Repel, Super Repel and Max Repel (`wRepelEffect`, the step + countdown where `CountStep` calls `DoRepelStep`, `RepelWoreOffScript`, + `CheckRepelEffect` after `ChooseWildEncounter`), the Coin Case and Blue + Card balances, Sacred Ash (`SacredAshScript`, queued), the Normal and + Gorgeous Box trophies (`DecorationIDs`), the Itemfinder + (`CheckForHiddenItems` in the world), the Card Key, Basement Key and + Squirtbottle (their maps are not open; tested with a start-menu run and + the interpreter). `text_ram` of the player's, rival's and Mom's names now + reads the text context. Saves gained `repel`, `coins` and + `blueCardBalance`. New `tests/field-items.test.ts` and the shared + `tests/menu-driver.ts`. +- `397dcef`: the three rods (`FishFunction` in the world, `scripts/fish.ts` + for `Fish`/`TimeFishGroups`, the map header's `fishGroup`), `loademote`, + `loadmem hBGMapMode`, `Fishing_CheckFacingUp`, `PutTheRodAway` (after the + pending text), the actor's fishing action and the renderer's fishing + frames (`LoadFishingGFX` tiles in VRAM bank 1; facing offsets are now + signed, which the up and left rods need), `BATTLETYPE_FISH`'s "The hooked + … attacked!". Wild Magikarp battle now: `CalcMagikarpLength` (compared + with the original over 1,509 cases in `tests/reference-parity.spec.ts`) + and `LoadEnemyMon`'s rerolls, Lake of Rage bug included. Unown are still + refused. Swarms need trainer calls. The four directions were checked in + close-up screenshots. +- `e2dc5ba`: Select in the start menu's pack (`SwitchItemsInBag`: move, + merge stacks under 99, B ends the move; GIVE's and the PC's packs ignore + Select) with the prompt and a marked row in the UI; left and right on the + MOVE screen (`.cycle_left`/`.cycle_right`, skipping Eggs) through a `menu` + effect with `sides`. The pack's cursor now stays on the last row chosen. +- `5c1ac9d` (`Closes #27`; the hook moved it to Fait): MAIL. `party/mail.ts` + holds the `mailmsg` struct; it lives on the holding `PartyMon` and in + the state's `mailbox`. Giving MAIL opens a two-line entry (the naming + effect's `mail` mode), the submenu's MAIL reads (a native letter panel, + `#mail-view`) or takes it (to the PC or into the pack), Bill's PC says + "Remove MAIL." for deposits and releases, and the player's PC MAIL BOX + reads, packs and attaches. A scripted `givepoke` with MAIL is refused. + Checked visually at desktop and 390px widths. + +Checks: 460 unit tests with the local ROM (3 skipped; 136 passed, 327 +skipped without it; new `tests/mail.test.ts`); 131 Chromium/WebKit +browser tests passed, 19 skipped intentionally (new Old Rod, Select and +MAIL flows); native and reference builds; reference, vendor and release +checks; `git diff --check`. "Tin Tower pillars" in +`tests/overworld-parity.spec.ts` failed once in Chromium during a full run +and passed alone and in the later full runs: timing under load. No CI or +physical-device run. + +Gaps found on the way, not on #27: +- The TM/HM pocket does not exist yet (`receiveItem` throws for TMs and + the pack shows an empty TM pocket). Falkner gives TM31, so it is needed + with or before #31; no card names it. +- The MAIL stationery (`MailGFXPointers`) and the Portrait MAIL's picture + are not drawn, and the mail entry leaves out ``, ``, ``, + `` and the 'd-'v ligatures. +- `CountStep`'s poison, happiness, egg, Day-Care and bike steps are not + ported; only the Repel step is. +- #29's description still lists "MAIL storage"; the PC's MAIL BOX was done + here, so only its printing remains there. + +Manual checks: cards #52 (fishing against the original), #53 (touch +screens, part of #40) and #54 (screen reader, related to #38) in +"A tester", with `test-saves/field-items.crystal-save.json` from +`tests/human-test-saves.test.ts`; importing it and fishing with the Super +Rod was checked once in Chromium and WebKit. + +Next: the remaining battle commands, move effects and Smart AI handlers +(board #28). diff --git a/tests/human-test-saves.test.ts b/tests/human-test-saves.test.ts index 59ba7bb..7fedb3a 100644 --- a/tests/human-test-saves.test.ts +++ b/tests/human-test-saves.test.ts @@ -66,6 +66,31 @@ describe.skipIf(!existsSync(romPath) || !process.env.MAKE_TEST_SAVES)( write("fly-teleport", world); }); + it("writes field-items: New Bark Town's shore with rods, MAIL and a Repel", () => { + const a = assets(); + // Cyndaquil facing the sea with the Old Rod. + const world = foundationFixture(a, "fishing"); + world.state.party.push( + generatePartyMon(a.pokemon, { + species: 16, // PIDGEY + level: 4, + item: 0, + otId: world.playerId, + ot: "CHRIS", + dvs: 0x9abc, + caughtData: 0, + }), + ); + world.state.bag.items = [ + { item: 0x12, quantity: 5 }, // POTION + { item: 0x9e, quantity: 2 }, // FLOWER_MAIL + { item: 0x14, quantity: 1 }, // REPEL + ]; + world.state.bag.keyItems.push(0x3b, 0x3d); // GOOD_ROD, SUPER_ROD + expect(world.mapId).toBe("24:4"); + write("field-items", world); + }); + it("writes headbutt: Route 29 facing a Headbutt tree", () => { // Totodile with Headbutt and Tackle, below the first reachable tree. const world = foundationFixture(assets(), "headbutt");