Skip to content

FRLG AutoStory stage 1: core navigation and battles - #213

Draft
dayfine wants to merge 1 commit into
nav/story-stepsfrom
frlg/stage1-core
Draft

dayfine wants to merge 1 commit into
nav/story-stepsfrom
frlg/stage1-core

Conversation

@dayfine

@dayfine dayfine commented Nov 3, 2026

Copy link
Copy Markdown
Owner

Depends on #122

FRLG AutoStory stage 1: the FireRed overworld walker (wild steps, obstacles, interrupted legs) and AutoStory from a new game to the Boulder Badge, with its battle logic. This is one squashed commit whose tree equals frlg/autostory-mvp; it replaces #117, #118, #119 and #120. The FRLG stack was consolidated into stage PRs so fixes need fewer merges, and will be split again for upstream.

🤖 Generated with Claude Code

https://claude.ai/code/session_01AKYzhrMnPK61XHWEch4a6E

Squash of fork PRs #117, #118, #119 and #120 (frlg/autostory-mvp at b8a58dd).

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

dayfine commented Nov 5, 2026 •

Copy link
Copy Markdown
Owner Author

The offline battle work is now merged in PokemonSimulation. Use this single handoff on main: FRLG AutoStory battle conditions, strategies and win rates. It embeds all 69 trainer fights, recorded/prepared entry conditions and rates, full opponent teams, A/B/C rules and openings, move-learning decisions, required rests, and League PP requirements.

Interface direction: AutoStory owns each game plan. Replay that actual plan as semantic logs to produce its ordered battle history, entering conditions and versioned policies; PokemonSimulation validates/simulates that history and returns a quality report. The 69 Pokeguy fights are a reference fixture, not the list or route every plan must adopt. This also applies to future Fire/Grass starter plans that catch, train and evolve supporters. The proposed replay/result/quality contract is documented in PokemonSimulation PR #39.

I reviewed this PR at 891b8f97e2e1399011431942c18079c532a19b5d. The recommendations below are follow-up implementation work, not changes already made to this PR.

1. Move simulation/analysis ownership out of Arduino-Source

Paths below are under SerialPrograms/Source/VideoGames/PokemonFRLG/Programs/AutoStory/ unless otherwise noted.

Files Recommended disposition
PokemonFRLG_AutoStoryWinChance.{h,cpp} Retire the native Monte Carlo implementation and runtime story_win_chance()/win_chance_refusal() calls. Offline estimation, adaptive sampling and probability reports belong in PokemonSimulation. These files exist at this head even where introduced by a parent PR; make changes in their owning PR.
PokemonFRLG_AutoStoryBattleSim.{h,cpp} Retire the duplicated battle/NPC simulation after replacing its live callers. BattleDecisions.cpp currently uses own_battler, trainer_battler, damage selection and Potion helpers, and FoeTracker.cpp uses sim_trainer/ai_next_foe. Extract the small runtime decision/tracking interfaces first; deleting this module outright would break real execution.
PokemonFRLG_AutoStoryDamage.{h,cpp} Move authoritative damage/stat analysis here as well. First relocate the Stats value type needed by party/summary code. A live controller may still need a narrow deterministic estimator or exported damage/threat tables; choose and validate that interface instead of retaining a second full mechanics engine. The current header explicitly excludes abilities and held items, so it cannot validate Torrent-dependent plans.
PokemonFRLG_AutoStoryBattleSim_Tests.cpp Move pure damage, NPC-AI and win-probability cases to PokemonSimulation, checking their expectations against the Gen 3 engine. Preserve the useful console-failure cases as native controller-seam regressions, especially the m51 Potion loop; do not discard those with the simulator.
BattleData/*.json, PokemonFRLG_AutoStoryBattleData.{h,cpp}, devtools/maps/frlg_battle_data.py Make Python/pret the canonical data-generation source and export a versioned runtime subset. Keep the loader, trainer/map IDs, move/PP metadata and OCR species/name vocabulary actually needed by C++. Do not remove all these assets before migrating their runtime consumers.
PokemonFRLG_AutoStorySimulation_Tests.cpp Keep. Despite its name, this runs the real story/checkpoint/route machinery against a fake game; it is not the Pokémon Monte Carlo simulator. Also keep party/items/prompt/evolution, detection, navigation and reanchoring regressions.

Arduino-Source owns the game plan and its console execution, and should export the history produced by its planning replay. PokemonSimulation owns battle-mechanics analysis, NPC simulation, reference-data generation and evaluation of the supplied history. A replay exporter, general history importer and quality grader still need implementation; the Markdown handoff is a reference specification, not an already-shipping C++ plan bundle. An optional runtime data export must not reverse ownership of the game plan. Runtime action selection must remain responsive to the actual battle, rather than treating an offline win rate or opening move as a button script. Update build/test registrations as the old modules are removed.

2. Replace LOW/HIGH policy selection with explicit per-fight plans

BattleData.cpp::default_battle_risk() currently makes rivals/leaders/bosses HIGH, and BattleDecisions.cpp::trainer_attack_slot() uses that flag to select different algorithms. Difficulty and action complexity are different: Brock/Liam are A, Misty and the Cerulean/S.S. Anne rivals are B, while Koga is C.

Give the actual AutoStory plan explicit fight records keyed by stable fight/trainer ID, connected to STORY_TRAINERS/AutoStoryTable.cpp, and emit them in its replay. Do not maintain a second independently authored route in PokemonSimulation. Each entry should identify the game/route profile, entry variant, observed A/B/C tier, runtime policy, exact preconditions, C goals where applicable, and the offline result's policy/source revision and uncertainty. Keep any acceptance/risk threshold separate; a point estimate just above the old 70% cutoff is not a reliability guarantee.

  • A: attack selection with move-name/PP/accuracy/expected-KO handling. Important: A is an observed classification in the published results; B recovery remains the default runtime even for A-labeled fights. Do not disable recovery and reuse these rates without an ablation.
  • B: the default recovery controller: effective attacks plus appropriate HP/status/PP recovery. It is more than “Potion below yellow.” Select medicine size against incoming damage; avoid healing that the next hit undoes; account for statuses, residuals, priority, remaining PP and item availability.
  • C: explicitly opt into C2 over B for Tower rival, Koga, Erika, Silph rival, Silph Giovanni, Sabrina, Route 22 rival, Lorelei, Bruno, Agatha, Lance and Champion. Choose and export the actual per-fight setup goals in the AutoStory plan; the handoff gives evaluated reference goals for its matching entries, not a generic boss recipe or a substitute for the producer's policy. Preserve boosts across opposing Pokémon, repair Speed/accuracy drops, budget survival across several setup turns, use Guard Spec only where configured, and support the distinct Torrent-target/extra-Sp.-Atk compensation rules.

The current executable action vocabulary is only RUN/POTION/ANTIDOTE/MOVE. Extend TurnAction, Supplies, item selection and BattleLoop::take_turn() to support a general verified item action: Super/Hyper/Full Restore, cures, PP items, X Special/Speed/Accuracy and Guard Spec as required. Keep policy computation separate from screen/controller execution. Commit PP, item counts and stage changes only after the game confirms an action; preserve Disable/refusal and move-learning/evolution protections.

Track the active opponent and its current HP/status, player HP/status/PP, stages and relevant effects. foe_out() currently reconstructs the foe at full HP each turn, while FoeTracker predicts replacements through the old simulator. Replace those assumptions with observations/explicit uncertainty; source party order is not guaranteed send-out order. Resolve move names to observed UI slots rather than copying the handoff's display order.

For the currently implemented stage through Brock, the known lab rival, Liam and Brock entries are A-labeled with B-default execution; none requires C. The Forest route explicitly meets Rick, so do not silently assign him Sammy's benchmark. Use the handoff's complete per-fight labels for matching trainers, and mark additional/unmatched encounters as unvalidated.

3. Make hard-fight preconditions an entry gate

Before starting a hard fight, verify trainer/variant, actual species and level, numeric HP/max HP and status, raw summary stats, moves and remaining PP, held item, earned badges and the full required battle bag. Log expected versus observed values and the plan revision. Nature/IV/EV assumptions must fit the actual starter: match visible summary stats/level and track earned EVs or a compatible profile range; IVs need not be directly OCR-readable. An unread value is not a successful check. If they differ, recover/re-read or stop for an offline estimate of the actual state rather than attaching the handoff's probability to it.

Two concrete fixes are needed here:

  • AutoStoryTable.cpp currently has ready_for_brock, but get_ready() can skip the nurse once nurse_before_battle() is satisfied. The adopted prepared Brock entry requires full HP, clear status and full PP, not merely green HP or sufficient total attack PP. Make required rests unconditional contract steps and verify their results.
  • recover_after_battle() sets hp_fill = 1.0 after one 20-HP Potion. That is not evidence of full HP. Preserve an accurate HP estimate/bounds and re-read it before validating a full-HP or Torrent condition. Similarly, half-PP guesses for unread summary values must not pass an exact hard-fight preflight.

The six adopted rests are Sammy, Liam, Brock, Josh, Cerulean rival and S.S. Anne rival. They restore HP/status/PP, never the bag. Later C full-heal alternatives remain pending; automatically healing every boss would change the measured Torrent/setup conditions.

These are the current ten lowest prepared-variant point estimates; verify the complete card in the linked handoff, not just the abbreviated condition here:

Fight Tier Level / HP on entry Win rate Condition especially worth checking
Lt. Surge B 28 / 79 of 79 56.2% Raw Speed 47; Water Pulse 19 PP. Speed 54 was a separate diagnostic, not this plan.
Koga C 39 / 34 of 122 70.1% Torrent active; C2 Sp. Atk target +1 and Guard Spec disabled; Surf 11 PP.
Cerulean rival B 21 / 61 of 61 75.5% Full rest: Water Gun 25, Mega Kick 5, Bite 25, Water Pulse 20 PP.
S.S. Anne rival B 27 / 76 of 76 75.7% Cabin rest before the rival; same full PP set above; verify the recovery bag too.
Tower rival C 36 / 38 of 114 90.0% Exactly at Torrent threshold; target Sp. Atk +2, or +4 when Torrent is inactive.
Erika C 44 / 35 of 137 91.5% Surf only 1 PP, Blizzard 5; C2 accuracy target +2.
Lorelei C 51 / 159 of 159 94.3% Bite 25 / Surf 15 / Blizzard 5 / Strength 15 PP; Sp. Atk target +4.
Agatha C 53 / 45 of 165 95.3% Torrent active; Surf 9 PP; compensate with extra Sp. Atk if Torrent is off.
Route 22 rival (late, before Victory Road) C 49 / 153 of 153 95.6% Surf 4 / Blizzard 3 PP; Sp. Atk +2 and accuracy +2 goals.
Champion C 55 / 171 of 171 95.6% Surf 13 / Blizzard 5 PP after the recorded pre-Champion Elixir; verify remaining setup/healing stock.

Brock/Liam each had 120/120 wins in the full-rest samples without HP medicine in their entry bags; that is not proof of a 100% true win rate. Bruno is still C even though it is outside this top ten: preserve its opening Torrent/equivalent-power plan rather than applying a universal heal. The handoff includes simultaneous intervals, the known B finishing-hit priority limitation, and the unproven whole-League PP reserve.

Evaluate the quality of the exported plan

Make the quality profile configurable: a minimum per-fight success probability (for example 60% or 70%, not a selected default), the required fraction of fights at or above 90%, and an explicitly defined easy/near-certain quota. Return the weakest fights, fractions, trials/uncertainty, coverage/input failures and the AutoStory event that produced each condition. Grade with simultaneous bounds: pass when lower bounds certify a requirement, fail when upper bounds rule it out, otherwise sample further or report inconclusive. Stop against these criteria instead of spending a fixed 1,000 trials on every fight.

Keep “zero losses in n samples,” a user-selected near-certain threshold such as 99%/99.9%, and a genuine guaranteed-100% result separate. Finite Monte Carlo cannot certify literal 100%; an exact quota needs a proof/exhaustive capability or an explicit change in its interpretation. The X/Y quota values remain unchosen.

Export the whole party and real capture/training/evolution/item/EXP/EV history for supporter plans. Unknown policies, unsupported capture/team objectives and uncovered branches must be reported, not silently simplified to the solo lead. Separate required-story fights from optional/training battles when defining quota denominators. Independent entering-condition scores and carried full-route simulation are distinct scopes: random battle outcomes must eventually update HP/PP/bag/party before later replay steps, rather than a fake executor returning success and inventing fresh snapshots.

Applicability and implementation order

These numbers describe the LeafGreen Pokeguy profile (Mild; selected IVs 28/25/16/31/21/27 in HP/Atk/Def/SpA/SpD/Spe order, reconciled EVs/EXP). This PR describes FireRed, defaults simulation stats to Hardy/IV15/EV0, extrapolates summary stats, and explicitly fights wild Pokémon in the Forest. Its actual levels, EVs, HP and bag therefore need reconciliation before any probability transfer. Verify version/trainer identity and route differences; do not force the real starter into the benchmark profile by assumption.

Suggested sequence: add a native AutoStory planning replay that emits its battle history/preconditions/policies; add a generic importer/validator and configurable quality report in PokemonSimulation; wire the producer's B-default/C-opt-in live decisions and verified item execution to that same contract; migrate old simulation callers and remove duplicated mechanics/Monte Carlo. Then add carried replay, branch coverage and full-party/capture support, and validate implemented console stages. Keep native controller regressions in Arduino-Source and mathematical/sampling tests here. Re-estimate any changed policy/profile in PokemonSimulation. The 69 independent rates do not yet prove a continuous full-route run, and the observed pre-Champion Elixir does not establish a sufficient stochastic PP budget.

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