Skip to content

FRLG AutoStory 00.21-00.22: Route 6 to Vermilion, the S.S. Anne and HM01 - #222

Draft
dayfine wants to merge 45 commits into
frlg/stage5-billfrom
frlg/stage6-vermilion
Draft

dayfine wants to merge 45 commits into
frlg/stage5-billfrom
frlg/stage6-vermilion

Conversation

@dayfine

@dayfine dayfine commented Nov 3, 2026 •

Copy link
Copy Markdown
Owner

Depends on #219

Adds the next two FRLG AutoStory rows after 00.20. 00.21 goes from Cerulean's Pokemon Center through the burgled house (the only way south without Cut, so the Rocket in its yard is fought), then Route 5, the Underground Path and Route 6 to Vermilion's Center; on Route 6 it walks down column 15 through the grass on legs to walls, out of Keigo's and Elijah's lines, and fights only Jeff, who stands across the one way south. 00.22 shows the S.S. Ticket at the harbor, fights the rival below the Captain's door, gets HM01 from the Captain and walks off as the ship sails, back to the Center; Cut isn't taught yet. Along the way the map generator reads tileset paths from metatiles.h (the S.S. Anne's didn't follow the symbol), a "new_game" flag set hides the S.S. Anne rival, and story routes no longer plan Surf, which they did across Vermilion's harbor. Tested with new OverworldMaps and AutoStory Simulation tests and the existing AutoStory/Overworld suites, all green locally; nothing has run on the console yet.

WhiteDialogDetector now also requires the dialog's blue top frame, so the S.S. Anne's white hull no longer reads as a message and stops a walk (console B, 00.22); new WhiteDialogDetector image test, frames in dayfine/CommandLineTests#10.

The win-chance sim now plays the battle loop's in-battle Antidote and logs how its battles are lost (foe out, seeded/poisoned/asleep, accuracy down, out of Potions); the S.S. Anne rival's 40% is real for Bite/Water Pulse/Bubble/Withdraw, lost to the Ivysaur's Leech Seed (new AutoStoryBattleSim test).

The battle loop no longer takes a send-out flash for a move prompt's YES/NO (it needs the box's frame now; m68's NO then YES set the lead to Lv31, 88 max HP for 78), takes a lone "no PP left" as a Disable, and at high risk uses the win-chance sim's own Potion rule (poison, likely Leech Seed, the foe's HP bar), which also tops up before a knockout; S.S. Anne rival 31.4%/38.5% with an Antidote, about unchanged, most losses still to the seeded Ivysaur (images in dayfine/CommandLineTests#11).

Rows 00.23-00.25 continue to Lt. Surge: HM01 Cut to the Oddish and TM28 Dig over Withdraw, a new CUT_TREE step for Vermilion's gym tree, Dwayne, Baily and Tucker (the two who look around are met by a step onto their line's second tile and a wait), the trash cans searched by counting each can's message pages (a wrong second can resets, and the search goes on from there), a Route 6 GRIND until the sim beats Surge 50% (Dig takes it from 6% to 47% at Lv28), a save in front of Surge, and Surge; tested with new AutoStoryTrashCans, AutoStory Simulation (00.23-00.25 walks, every can-to-can walk past the trainers where they stand after their battles) and OverworldMaps tests, nothing on the console yet.

The summary's KNOWN MOVES reader now knows the Oddish line's moves (it read none of the Oddish's, so 00.23's Cut teach stopped as unread) and ends the moves at the first slot with no type badge, so a move it can't name keeps its row instead of cutting off the rest; new SummaryMovesReader image test, frame in dayfine/CommandLineTests#11.

The TEACH step now goes through the TM's own scene ("Machine set!", " learned !", pokefirered pokemon_special_anim.c) with A and never B, which cancels the teach; 00.23's Cut onto the Oddish stopped there and gave up. Free slot and forget path, TM and HM, are covered by AutoStoryTeachScreens sim cases and a new TeachScreenReader image test (frame in dayfine/CommandLineTests#11).

On the forget path the step now presses A on every look of the scene until the TM CASE returns: console B read the forget's "Poof!" box (which waits for A) as "learned" and stopped pressing for 5 minutes on TM28 Dig; leave() waits for a scene once, so a stuck one gives up instead of looping (AutoStoryTeachScreens sim cases).

An open leg over a map connection, held a tile longer for the game's stall there, can end a tile further when the game doesn't stall (00.24, Route 6 south into Vermilion: north 1 onto the Center's door stopped below it); a warp walked back that way is now held a tile further, stopping at the fade (OverworldSim test walks the exact plan with and without the stall). 00.24 also checks Lt. Surge's win chance in the Center first and skips the trip to Route 6 when it already passes (AutoStoryGrind and 00.24 sim tests).

The Lt. Surge loss (m73, sim 79%) came from the Raichu's Double Team at full HP and Dig's two turns, neither in the sim; it now scores Double Team as pret's AI_CV_EvasionUp and plays two-turn moves (charge turn, under ground), giving m73's lead 58% (82% at Lv31) (Vermilion Gym sim tests).

Story action table (core stage 3, from #213): the GAME if-chain in StoryExecutor::game() is now four table rows (close_trainer_card, leave_gift_summary, cut_tree, trash_cans) plus the GAME default for captures, PC and abilities; the executor has no per-kind virtuals left. The AutoStoryStepTable parity tests check each row against the if-chain it replaces.

Sim on the story action table (core stage 8): the full-run simulation and row_step_on_sim() no longer dispatch by kind themselves. StoryMapsSim (the whole story on the story maps, formerly the test's FakeGame) and OverworldStepSim (a row's steps on the OverworldSim; row_step_on_sim() now runs through it) bind make_story_action_table() and run through TableExecutor, stubbing the actions that need the console; stub_report() lists each row's stubbed steps, and a new AutoStory Simulation test checks the whole story stubs exactly the steps whose action needs the console. Checked at #258's tip: the full-run step trace (1395 lines incl. outcomes and saves) and all 17 StoryReplay reports are byte-identical, and the FRLG and Pokemon:: results are unchanged apart from the new passing test.

Interrupts between steps in the sim: StoryMapsSim binds the same table; StorySimKnobs::dialog_before pops up a dialog before a step, which stops a walk or a talk until it is cleared, and clear_interrupts = false keeps the old behaviour. Two new AutoStory Simulation tests: a dialog before every step (red before the binding), and dialogs before one step in five over 5 seeds, 0/5 runs through before and 5/5 after. Full-run trace and replay reports unchanged.

🤖 Generated with Claude Code

https://claude.ai/code/session_01AKYzhrMnPK61XHWEch4a6E

dayfine and others added 4 commits November 3, 2026 14:49
… own

walked_route() and row_step_on_sim() move unchanged out of the simulation
tests, which are near the length limit, so the next stage's row tests can
use them from a file of their own.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AKYzhrMnPK61XHWEch4a6E
00.21 goes from Cerulean's Pokemon Center through the burgled house,
fights the Rocket in its yard (TM28), then down Route 5, through the
Underground Path and Route 6 to Vermilion's Pokemon Center. On Route 6 it
walks down column 15 through the grass, on legs to walls, out of Keigo's
and Elijah's lines, and fights Jeff, who stands across the only way south.

00.22 shows the S.S. Ticket at the harbor, goes aboard, fights the rival
below the Captain's door, gets HM01 from the Captain and walks off the
ship as it sails, back to the Center.

The maps: the burgled house, Route 5, the Underground Path, Route 6,
Vermilion City and its Center, and the S.S. Anne's exterior, 1F and 2F
corridors and Captain's office. The generator now reads a tileset's
attributes path from metatiles.h (gTileset_SSAnne's folder is ss_anne),
and a "new_game" flag set hides the S.S. Anne's rival, who stands on the
Captain's door until his scene. Story routes no longer plan Surf: the
harbor's water was the shorter way to the pier.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AKYzhrMnPK61XHWEch4a6E
The 1F corridor frame, with no dialog on screen, reads as a white dialog today.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AKYzhrMnPK61XHWEch4a6E
The detector looked only at three white strips inside the dialog box, so a
large white area with no box, like the S.S. Anne's hull below the 1F
corridor, read as a dialog and stopped the walker's leg. It now also requires
the strip on the box's top frame not to be bright white. All real dialog
images have a light blue frame there (sum of RGB 600-690); the hull is 765.

Group the naming screen's test suites so add_tests() stays under 50 lines.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AKYzhrMnPK61XHWEch4a6E
…osses

The S.S. Anne rival came out at 40% for a Lv27 Wartortle with 15 Potions.
The sim's math matches the decomp; the battles are lost to the Ivysaur,
seeded and poisoned, where Bite (15-18 of its 56 HP) can't outpace Leech
Seed's 9 HP a turn back. The sim left out the in-battle Antidote the
battle loop uses (once, after two poisoned turns): it now plays it, and
the refusal log names the foe and the lead's state in the battles lost.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AKYzhrMnPK61XHWEch4a6E
dayfine and others added 13 commits November 3, 2026 16:30
…Potions

Console B, m68 (the S.S. Anne rival): the send-out flash on the ship's
white floor read as the move prompt's YES/NO, and the decisions took the
first for "Delete a move to make room for PROTECT?" (Lv31): NO, and the
second for "Stop learning?": YES. The lead was then figured at Lv31
(78 -> 88 max HP). A battle YES/NO now needs the box's slate frame, and a
YES/NO with no move the lead can have reached is NO, changing nothing;
"Stop learning?" is due only within the turn.

"no PP left" read 37 s after the last move zeroed that move's PP: it now
counts only soon after the choice, and the first read is taken as a
Disable (Kadabra's), the second as no PP.

At BattleRisk::HIGH the loop's Potion is the win-chance sim's own_turn(),
with the lead's poison, the chance a foe's Leech Seed hit it, and the
foe's HP from its bar. own_turn() also tops up before a knockout when the
foe's turn is small and leaves nothing lasting, and a stronger foe is to
come (task PokemonAutomation#77 step 1); neutral on the S.S. Anne rival (31.4% -> 31.7%).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AKYzhrMnPK61XHWEch4a6E
00.23 teaches HM01 Cut to the Oddish and TM28 Dig in place of Withdraw,
cuts Vermilion's gym tree (a new CUT_TREE GAME step), fights Dwayne,
Baily and Tucker, and searches the trash cans: two pages to a can's
message mean the first switch (or a reset after it), one page the second
(or trash), so the search counts pages, guesses one can beside the first
and starts over from where it stands after a reset. Dwayne and Baily look
around, so each is met by a step onto the second tile of his line and a
wait (TRAINER_WAIT_VARIANT). 00.24 grinds on Route 6 until the sim beats
Surge 50% of the time, heals, and saves in front of him; 00.25 fights him
and heals. The gym map writes the beams off, as the story finds them
after the switches; the sim learns to cut trees, which grow back on a
warp.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AKYzhrMnPK61XHWEch4a6E
The KNOWN MOVES reader had no names for the Oddish line's moves, so ABSORB
matched nothing, the reader stopped at the top row and 00.23's Cut teach
found no moves. Add the Oddish line's level-up moves, and end the moves at
the first slot with no type badge instead of the first name not read: an
unnamed move now keeps its row with an empty name.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AKYzhrMnPK61XHWEch4a6E
Console B, 00.23: HM01 to the Oddish (two free slots) stopped on the
TM's scene, "Machine set!", which the reader didn't place, and gave up
mashing B, which cancels the teach (pokefirered Task_MachineSet). The
fake game now runs that scene for TMs and HMs, free slot or forget, and
errs on B there; the capture's image test expects tm_scene/machine_set.
Only the names are added; the reader and step don't use them yet.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AKYzhrMnPK61XHWEch4a6E
The reader places the TM's scene (pale blue diamonds on both sides) and
reads "Machine set!" and "learned" in its message box. After A on the
member, and after the pick on KNOWN MOVES, the step presses A through
the scene until "learned" shows, then waits for the TM CASE; B there
would cancel the teach. A scene the reader misses (two looks of
"other") gets the same A presses. leave() finishes a scene before
backing out. The moves read after the teach still decide.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AKYzhrMnPK61XHWEch4a6E
Console B, TM28 Dig over Withdraw: the forget's "1, 2, and... Poof!"
read as "learned", the step stopped pressing and waited 5 minutes,
leave() starting the scene's wait again on each look.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AKYzhrMnPK61XHWEch4a6E
pokefirered: after a forget, "1, 2, and... Poof!", "<MON> forgot <OLD>."
and "And..." end in \p and wait for A; "<MON> learned <MOVE>!" runs on
its own. Console B read "Poof!" as "learned", so the step stopped
pressing; and leave() restarted the scene's wait on each of its looks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AKYzhrMnPK61XHWEch4a6E
…tion

On console B (row 00.24) the open leg south 14 from Route 6 into Vermilion
City, held a tile longer for the stall on a connection, ended a tile further
south: the game didn't hold the player up there. West 8 then ran along
row 8 and north 1 onto the Pokemon Center's door stopped below it ("no fade
in and out"). Until a leg to a wall or a warp places the player again, a
warp walked back that way is now held a tile further (RouteStep::warp_slack,
with_warp_slack() in run_route()), stopping at the fade. The overworld sim
can now leave out the stall (SimScript::connections_stall); the new sim test
walks the exact plan both ways.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AKYzhrMnPK61XHWEch4a6E
On console B row 00.24's grind found the chance against Lt. Surge already
79% at Lv29 and fought nothing, but the row had walked out to Route 6's
grass and still walked back. A GAME step in the Center now reads the lead
first (grind_check_step(), grind_reached_already()); when it passes it
sets a run flag that the walk out, the grind and the way back skip_if.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AKYzhrMnPK61XHWEch4a6E
Console B lost to Lt. Surge's Raichu at a 79% sim chance: the Raichu used
Double Team at full HP while each Dig spent a turn under ground. The sim
now scores Double Team as pret AI_CV_EvasionUp does, and plays two-turn
moves (charge turn, no choice the next, semi-invulnerable for Dig/Fly/
Dive/Bounce); the planner counts a two-turn move at half its damage a
turn. m73's lead now wins 58%; 82% at Lv31.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AKYzhrMnPK61XHWEch4a6E
…overworld for 60 s

Lt. Surge's win puts Oak's aide on Vermilion City's (25, 7) until talked
to; the story's maps don't have him, and the walk to the Center went west
along row 7 into him (console B, 2026-11-03). It now goes along row 10 to
the water and up column 14.

After losing to Surge the battle loop pressed + and B for 8 minutes with
no battle screen and no START menu. BattleEndWatch::overworld_lost() stops
it 60 s after the last battle screen once START has looked.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AKYzhrMnPK61XHWEch4a6E
dayfine and others added 4 commits November 7, 2026 07:00
The merge added add_tests_AutoStoryExport, which put add_tests() at 51 lines, over the code-health limit. Group the two Vermilion suites under add_tests_AutoStoryRows, the shape stage7 already uses.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013VUubhHeYSMGSSDXZkKZss
dayfine and others added 4 commits November 9, 2026 00:19
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013VUubhHeYSMGSSDXZkKZss
The GAME if-chain in StoryExecutor::game() becomes four rows keyed by
variant (close_trainer_card, leave_gift_summary, cut_tree, trash_cans)
and the GAME default for the rest (captures, PC, abilities), so the
console executor has no per-kind virtuals left. The parity tests check
each row against the if-chain it replaces.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013VUubhHeYSMGSSDXZkKZss
# Conflicts:
#	SerialPrograms/Source/VideoGames/PokemonFRLG/Programs/AutoStory/PokemonFRLG_AutoStorySimulation_Tests.cpp
dayfine and others added 15 commits November 9, 2026 02:09
The full-run simulation (the test's FakeGame) and row_step_on_sim()
dispatched by kind themselves, beside the table the console and the
replay run. StoryMapsSim (the whole story on the story maps) and
OverworldStepSim (a row's steps on the OverworldSim) now bind
make_story_action_table() and run through TableExecutor, stubbing the
actions that need the console; row_step_on_sim() runs its step through
OverworldStepSim. SimStubs lists each row's stubbed steps
(stub_report()), and a test checks that the whole story stubs exactly
the steps whose action needs the console.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013VUubhHeYSMGSSDXZkKZss
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013VUubhHeYSMGSSDXZkKZss
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013VUubhHeYSMGSSDXZkKZss

# Conflicts:
#	SerialPrograms/Source/VideoGames/PokemonFRLG/Programs/AutoStory/PokemonFRLG_AutoStoryEvents.cpp
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013VUubhHeYSMGSSDXZkKZss
Binds the FRLG between-step interrupts (step_interrupts()) to the story
maps simulation. StorySimKnobs::dialog_before pops a dialog up before a
step; until it is pressed through it stops a step that walks or talks,
as on the console. With clear_interrupts (the default) the executor's
look finds it and closes it; off, it stays up as before the binding.

Tests: a dialog before every step (red before the binding: the walk
after the first one failed), and dialogs before one step in five over 5
seeds, 0 of 5 runs through before and 5 of 5 after.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013VUubhHeYSMGSSDXZkKZss
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013VUubhHeYSMGSSDXZkKZss

# Conflicts:
#	SerialPrograms/Source/VideoGames/PokemonFRLG/Programs/AutoStory/PokemonFRLG_AutoStoryEvents.cpp
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013VUubhHeYSMGSSDXZkKZss
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant