Skip to content

FRLG AutoStory: run Starter RNG in the program (option, off by default) - #184

Closed
dayfine wants to merge 37 commits into
frlg/rng-callable-stepsfrom
frlg/autostory-rng-loop
Closed

dayfine wants to merge 37 commits into
frlg/rng-callable-stepsfrom
frlg/autostory-rng-loop

Conversation

@dayfine

@dayfine dayfine commented Nov 3, 2026 •

Copy link
Copy Markdown
Owner

Depends on #183 (base frlg/rng-callable-steps; the diff shows only this change).

AutoStory's RNG plan (#182) stops twice and leaves SID Helper and Starter RNG to the user. A new option, "Run Starter RNG in AutoStory" (off by default; off keeps today's stops), runs both in the program. At 00.01, when the RNG plan's SID is empty, it types the name, runs SID Helper's steps from the keyboard and reads the TID off the Trainer Card, then goes on at 00.01b. At the end of 00.04, saved under Squirtle's ball, it runs the plan's attempts with StarterRngAttempts and feeds each outcome to RngPlanTracker. A hit that isn't shiny goes on to the next attempt, since each attempt resets to the save itself. A miss is retried, at most 2 times, then the loop moves on to the next attempt still shiny for a SID left; it stops only when none is left. A shiny is identified against the target: only a shiny on the target narrows the SIDs. One off the target confirms nothing and logs outcome=shiny_off_target next=stop. Either shiny goes on to the rival's battle (00.04b from the rival's trigger), saves after it as the manual path does, and runs on to the end checkpoint. If Starter RNG refuses an attempt's timings, the loop logs it and skips to the next attempt (starter_rng=setup_error). Anything else, including a setup error such as "No sound detected.", stops the run with the save still under the ball. Each attempt has a 3-hour cap and the loop a 12-hour cap. Every attempt logs an RngPlan: result line, and a shiny that leaves one SID logs RngPlan: confirmed ... candidate=k of=N.

Reading the log: every line of the loop starts with RngPlan:, in this order. First tid= (where the TID came from), then sid_helper (SID Helper's candidates), then one attempt= line per planned attempt (seed, advances and the SIDs it is shiny for). For each try of an attempt, a state line at its start and after every reset gives the attempt and try counts, resets, seed, advances, the attempt's SIDs, the SIDs ruled out, the try's and the loop's time against their caps, and the calibration. The state lines also show on the overlay log. After each try, a result line gives the outcome, Starter RNG's own outcome (attempt_deadline, out_of_resets, no_matches and wild_shiny are told apart, though all count as a miss; setup_error is an attempt that couldn't run), the nature, IVs and PID when known, and next=retry|next_attempt|confirm|stop. Last, confirmed with candidate=k of=N, when a shiny leaves one SID. The exact formats are in the comment above rng_log_tid() in RngManipulation/PokemonFRLG_RngPlanLog.h.

Tested with the new PokemonFRLG::StarterRngLoop suite (the loop's decisions on scripted outcomes and a fake clock) and PokemonFRLG::AutoStoryRngLoop (end messages and the rows after a shiny), run with a test runner linked against a local full build alongside RngSteps, RngTargetSearch, the RngPlan suites, AutoStory and AutoStorySimulation (82 passed, before the move below). Code health shows 0 failures. Not run on a Switch yet.

The loop moved unchanged from AutoStory/PokemonFRLG_AutoStoryRngLoop into RngManipulation/PokemonFRLG_StarterRngLoop and PokemonFRLG_StarterRngConsoleSteps in 9f01402; AutoStoryRngLoop keeps the story glue (StarterRngPlanned, the end message, rows_after_starter_rng): git diff --color-moved=dimmed-zebra --color-moved-ws=allow-indentation-change 8ff380d27 9f014021d.

  • One short line per reset on the stream's overlay log, e.g. Starter RNG try 27/50: seed e66e (+1 frame late), advance 1677 (target 1670, +7). Missed. (rng_reset_line(), tested in PokemonFRLG::StarterRngLoop); the long RngPlan: state lines stay in the file log only.

🤖 Generated with Claude Code

https://claude.ai/code/session_01AKYzhrMnPK61XHWEch4a6E

dayfine and others added 2 commits November 2, 2026 16:15
A new option, Run Starter RNG in AutoStory (off by default), runs what
the two RNG stops leave to the user:
- At 00.01, with the RNG plan's SID empty: SID Helper's steps on the
  player's keyboard, then the TID read off the Trainer Card; the run goes
  on at 00.01b.
- At the end of 00.04, saved under Squirtle's ball: the RNG plan's
  attempts, each with StarterRngAttempts, fed to RngPlanTracker. A shiny
  goes on to the rival's battle (00.04b from the rival's trigger), which
  saves, and the rest of the run. A hit without a shiny moves on to the
  next attempt, a miss retries it, up to 2 retries; every attempt has a
  3-hour cap and the loop a 12-hour one. Otherwise the run stops with the
  save under the ball and what to do next.

Every attempt logs an "RngPlan: result" line, and a shiny that leaves one
SID logs "RngPlan: confirmed ... candidate=k of=N". The loop's decisions
run against injected steps in the new AutoStoryRngLoop tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AKYzhrMnPK61XHWEch4a6E
The loop now logs, and shows on the overlay log, an "RngPlan: state"
line at the start of every try of an attempt and after every reset:
attempt and try counts, resets, seed, advances, the attempt's SIDs, the
SIDs ruled out, the try's and the loop's time against their caps, and
the calibration. StarterRngAttempts reports each reset through a new
on_reset hook in its settings (StarterRng passes none), so RngManipulation
still doesn't depend on AutoStory.

"RngPlan: result" gains the try, Starter RNG's own outcome, the nature,
IVs and PID when known, and what the loop does next; its outcomes are
lower case. The RngPlan header lists every line in the order a run logs
them, and the new lines' formats are unit-tested.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AKYzhrMnPK61XHWEch4a6E
dayfine added a commit that referenced this pull request Nov 3, 2026
…he next step

rng_log_result() takes an RngResultLog: the try, Starter RNG's own
outcome, the nature, IVs and PID when known, and what comes next
(rng_plan_next()). Outcomes are lower case. RngPlanTracker gains
attempt_count(). The header lists every RngPlan: line in the order a run
logs them, including the loop's state line.

Moved here from #184, which uses it, so that each PR owns its files.

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

# Conflicts:
#	SerialPrograms/Source/VideoGames/PokemonFRLG/Programs/AutoStory/PokemonFRLG_AutoStoryRngPlan.cpp
#	SerialPrograms/Source/VideoGames/PokemonFRLG/Programs/AutoStory/PokemonFRLG_AutoStoryRngPlan.h
#	SerialPrograms/Source/VideoGames/PokemonFRLG/Programs/AutoStory/PokemonFRLG_AutoStoryRngPlan_Tests.cpp
dayfine added a commit that referenced this pull request Nov 3, 2026
Called after each reset with the resets so far and the calibration that
reset was timed with, for a caller that logs the attempts (AutoStory,
#184). StarterRng passes none, so it runs as before.

Moved here from #184, which uses it, so that each PR owns its files.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AKYzhrMnPK61XHWEch4a6E
dayfine added a commit that referenced this pull request Nov 3, 2026
A shiny after a reset ended the attempts as "shiny" without knowing
whether it was the target or another advance; AutoStory (#184) needs to
know before it uses the shiny to narrow the SID. With the new
identify_shiny setting, StarterRngAttempts reads the shiny's summary and
searches near the target as an attempt's first stage does, and ends as
shiny_on_target (the target is among the states its stats match, with
the target's PID, nature and IVs), shiny_off_target, or shiny when none
match. StarterRng leaves it off and stops on the shiny as before.

identify_shiny() is unit-tested in PokemonFRLG::RngSteps.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AKYzhrMnPK61XHWEch4a6E
dayfine and others added 9 commits November 2, 2026 16:58
…move on

Starter RNG's attempts now tell whether a shiny was the target
(identify_shiny, #183). Only a shiny on the target narrows the SIDs; one
off it, or not known to be on it, ends the loop as SHINY_OFF_TARGET with
no SID confirmed and no "RngPlan: confirmed" line. Its result line says
outcome=shiny_off_target next=stop. Either shiny goes on with the story.

The result line names a try that ran past its deadline attempt_deadline,
apart from out_of_resets, no_matches and wild_shiny; all still count as a
miss. An attempt missed more often than the retries allow moves on to the
next one still shiny for a SID left (#182), and the run stops only when
none is left (MISSED_EVERY_ATTEMPT_LEFT). A shiny for none of the SIDs
left no longer says "one of" an empty list.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AKYzhrMnPK61XHWEch4a6E
Starter RNG refuses timings it can't press (a title screen or in-game
wait too short, a negative delay) with a UserSetupError, or a failure
that sends no error report (check_timings()). That ended the whole run;
on console B it did for seed 11A3, whose title screen wait was under
30 s. The console steps now turn such a refusal into a UserSetupError,
and the loop logs it ("RngPlan: attempt <i> can't run: ...") and records
the attempt as unusable (#182): the result line says
outcome=unusable starter_rng=setup_error, and the next attempt still
shiny for a SID left runs. A game failure (one that sends an error
report) still ends the run.

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

The loop marked an attempt unusable and moved on for any UserSetupError,
so "No sound detected." (no audio input on the panel) burned every
attempt. Starter RNG's refused timings now come through as
StarterRngTimingsRefused, the only error the loop skips an attempt for;
any other error, a UserSetupError included, ends the program.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AKYzhrMnPK61XHWEch4a6E
The loop doesn't know about the story, so it moves out of AutoStory:
StarterRngLoop (the steps interface, limits, run_starter_rng_plan and its
state line, with its tests) and StarterRngConsoleSteps (the console steps
and RngPlanLogger). AutoStoryRngLoop keeps the story glue: StarterRngPlanned,
the loop's end message, which names AutoStory's checkpoints, and
rows_after_starter_rng. Code is moved unchanged; the message keeps its own
copy of the short SID-list helper.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AKYzhrMnPK61XHWEch4a6E
When the in-program Starter RNG loop ends on a shiny that leaves one SID,
write it into RNG_PLAN.SID, so it is kept with the program's settings and
the next run skips SID Helper's steps. Log it, say so in the loop's message
and the finish message, and mention it in the SID option's text.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AKYzhrMnPK61XHWEch4a6E
dayfine and others added 10 commits November 2, 2026 19:58
…t back

Starter RNG in AutoStory started every program run from a zero
calibration and dropped what it learned. It now starts from the RNG plan's
calibration (the console's seed and CSF offsets, and Starter RNG's own
in-game offset, STARTER_INGAME) and saves each reset's calibration back,
so a stopped run keeps it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AKYzhrMnPK61XHWEch4a6E
Each reset now puts one line on the log and the stream's overlay log, as
"Starter RNG try 27/50: seed e66e (+1 frame late), advance 1677 (target
1670, +7). Missed." (rng_reset_line()). The long "RngPlan: state" lines
stay in the log only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AKYzhrMnPK61XHWEch4a6E
# Conflicts:
#	SerialPrograms/cmake/SourceFiles.cmake
dayfine and others added 12 commits November 2, 2026 22:01
# Conflicts:
#	SerialPrograms/cmake/SourceFiles.cmake
…r RUN in a dark cave) into frlg/autostory-rng-loop
…mpts out of step) into frlg/autostory-rng-loop
…rlg/autostory-rng-loop

# Conflicts:
#	SerialPrograms/Source/VideoGames/PokemonFRLG/Programs/AutoStory/PokemonFRLG_AutoStory.cpp
…lg/autostory-rng-loop

# Conflicts:
#	SerialPrograms/cmake/SourceFiles.cmake
…rlg/autostory-rng-loop

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AKYzhrMnPK61XHWEch4a6E
…t name) into frlg/autostory-rng-loop

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

# Conflicts:
#	SerialPrograms/Source/VideoGames/PokemonFRLG/Programs/AutoStory/PokemonFRLG_AutoStory.cpp
@dayfine

dayfine commented Nov 3, 2026

Copy link
Copy Markdown
Owner Author

Superseded by #214 (FRLG stack consolidated into stage PRs; will be resplit for upstream).

@dayfine dayfine closed this Nov 3, 2026
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