Skip to content

BDSP navigation v4: the walker, with battles passed in - #129

Draft
dayfine wants to merge 49 commits into
bdsp/nav-v4from
bdsp/walk-v4
Draft

dayfine wants to merge 49 commits into
bdsp/nav-v4from
bdsp/walk-v4

Conversation

@dayfine

@dayfine dayfine commented Nov 1, 2026 •

Copy link
Copy Markdown
Owner

Depends on #127 (base bdsp/nav-v4); the diff shows only this PR's change.

The BDSP walker on #127's StoryWorld, with battles passed in, its console steps behind a RouteIO so its decisions can be unit tested.

  • Plans on StoryWorld instead of MapSet/TileGrid. Refactored for code health without changing its steps: options structs instead of long parameter lists and bools, walk_route moved unchanged into PokemonBDSP_AutoStory_PlannedRoute and split into a RouteWalker with one function per decision (git diff --color-moved=dimmed-zebra on b678b4a).
  • RouteIO holds every console call the walker makes; ConsoleRouteIO is today's code, and tests use a scripted one.
  • Fixes from console runs: straight walks and turns go on the D-pad (a 40–80 ms tap only turns; stick taps stopped between tiles, r57–r61); a quiet tap followed by a moving one counts as a step (r67); after a trainer on an open or wall leg the walk replans from the taps and the sight line (r54, r55); no banner read is a warning, only a wrong banner fails; a route gives up after the third dialogue the map does not explain (r14).
  • The transition watchers, the overworld detector and the battle dialog watcher are adapted from [WIP] BDSP Autostory PokemonAutomation/Arduino-Source#1717 by Developer-Butters and credited.

Testing

🤖 Generated with Claude Code

https://claude.ai/code/session_01AKYzhrMnPK61XHWEch4a6E

Walks the planned routes on the BDSP story maps: Walk holds a direction
and stops on what the screen shows (a dialogue, a transition, a wall),
RouteWalk walks a plan's legs, tracks the tiles the player may be on and
plans again after a trainer, and leaves buildings by indoors() and the
door's fade. The walker sees wild battles and trainers start but does
not fight them: a WildBattleEscape runs from a wild battle and a
RouteTrainerFight fights a trainer, both passed in by the program.

Adapted from PokemonAutomation#1717 by Developer-Butters,
kept nearly as written: the AutoStory OverworldDetector and
TransitionWatchers, which the walker uses to see the overworld and an
encounter's white flash.

Tests: indoors() on synthetic screens and screenshots, the door's fade,
and the location banner reads.

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 1, 2026
dayfine and others added 4 commits November 1, 2026 13:38
…pData

Brings in maps-v4 and nav/story-steps under nav-v4. Conflicts were the
test registration and the source list: the walker's entries are kept,
nav-v4's removed Data files and MapGrid tests stay removed. The walker
follows in the next commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AKYzhrMnPK61XHWEch4a6E
The walker takes a StoryWorld where it took a Pokemon::MapSet or
TileGrid, and the planner's types from PokemonBDSP. Its copy of the world
uncovers the tiles to avoid and blocks what it finds in the way, as it set
them UNKNOWN and BLOCKED before. Nothing else changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AKYzhrMnPK61XHWEch4a6E
Follows the rename in #127; the walker's own walk_to_wall() is unchanged.

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 1, 2026 14:41
Follows #127: standable(), step() and describe() take the world first.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AKYzhrMnPK61XHWEch4a6E
namespace X{ with no space, and if bodies on their own lines. No code
changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AKYzhrMnPK61XHWEch4a6E
Code health rejects the non-const extern g_story_language. The program
sets the language once before the story runs, so it now calls
set_story_language(), and readers call story_language().

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AKYzhrMnPK61XHWEch4a6E
Code health: walk_until() took 8 parameters, walk_until_dpad() 9 with a
defaulted bool, walk_expecting() 9, and walk_until_impl() 12 with four
bools over 126 lines. Every walk now takes the stick as one
JoystickPosition. walk_until_dpad() takes DpadWalkOptions (arrived, and a
DpadPace for B held) and walk_expecting() a WalkExpectation (the stop,
and arrived). The walk loop is a WalkUntil class in the .cpp, with
what it presses and how battles end it as enums. Behaviour is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AKYzhrMnPK61XHWEch4a6E
RouteWalk.cpp was 926 lines, and splitting walk_route() into functions
would take it past the 1000-line limit. walk_route(), walk_waypoints(),
talk_to_npc(), RouteTrainerFight and the route-log helpers they use move
unchanged to PokemonBDSP_AutoStory_PlannedRoute.{h,cpp}. RouteWalk exposes
route_ms_per_tile() and route_stick() for them.

Review with: git diff --color-moved HEAD~1

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

Code health: walk_route() was 475 lines nested 7 deep with 11
parameters, walk_waypoints() and talk_to_npc() had 10. walk_route() is now
a RouteWalker class: planning, a leg to a wall, an open leg, the banner
check, the trainers after a leg and each replan are their own functions,
with the same steps in the same order. The trainers and their fight go
together in RouteTrainers; where a walk goes is a RouteWalkPlan,
WaypointWalkPlan or NpcTalk.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AKYzhrMnPK61XHWEch4a6E
Code health: WhiteScreenWatcher and BlackScreenFlashWatcher had 8
parameters. Every caller used the default thresholds and durations, so
WhiteScreenWatcher takes the colour, box, finder type and duration, and
WhiteScreenOverWatcher the colour and box; the values are the old
defaults. BlackScreenFlashWatcher had no callers and is removed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AKYzhrMnPK61XHWEch4a6E
Code health asks for public data without methods: the banner checks and
the run options are free functions of a LegWalk.

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 1, 2026 15:17
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AKYzhrMnPK61XHWEch4a6E
…m it

The transition watchers, the overworld detector and Walk.cpp's
BattleDialogWatcher come from PokemonAutomation#1717 by
Developer-Butters; their headers now say so. The transition watchers get
the repo's header block, include guard and one namespace per line.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AKYzhrMnPK61XHWEch4a6E
#129's new .cpp and .h files were LF; they are CRLF like the rest of
the repo. Line endings only: git diff --ignore-cr-at-eol shows nothing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AKYzhrMnPK61XHWEch4a6E
r14 walked into Barry's Route 201 warning, which no map records, took it
for an unknown trainer, replanned into it again and looped for minutes.
A route now fails on the third such stop instead.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AKYzhrMnPK61XHWEch4a6E
dayfine and others added 17 commits November 1, 2026 18:26
B held with the D-pad runs once the player has the Running Shoes: r27
ran 35 tiles north in about 5.75 s, and the walking count put the stop
11 tiles short of the wall. Legs that reach their wall log the pace.

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
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
Sandgem's banner showed about a second after the walk ended (r35).

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
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
A 100 ms stick tap stepped about 0.6 tile off the grid (r49: a tile west of
Sandgem's Center door). 40 to 80 ms D-pad taps only turned, on the console.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AKYzhrMnPK61XHWEch4a6E
…ps and the sight line

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AKYzhrMnPK61XHWEch4a6E
The 160 ms turn tap's step was guessed from the screen and counted a tile it
had not walked (r60: a column off below Jubilife's Center).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AKYzhrMnPK61XHWEch4a6E
The stick stops between tiles (a 100 ms tap moved ~0.6 tile), and walks after
stick holds ran a column off (r57 to r61). Diagonals stay on the stick.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AKYzhrMnPK61XHWEch4a6E
No behaviour change. RouteWalker (walk_route(), talk_to_npc()) now does
everything on the console through a RouteIO: walks to a wall, D-pad tap
walks, presses and waits, the dialogue watch, the at-the-wall holding
check, screen looks and its log and failures. ConsoleRouteIO is today's
code: holding_against_wall() moved unchanged into RouteIO.cpp, and each
call site makes the same controller commands, waits and reads as before.
walk_route() and talk_to_npc() keep their signatures and build a
ConsoleRouteIO; overloads take a RouteIO so tests can script the console.

route_turn() and the walker's taps, A presses and waits are now a
RouteInput (kind, direction, hold, release, count, whether to wait for
them), pressed by press_route_input(); route_turn_tap() is the D-pad tap
route_turn() turns with.

Review with:
git diff --color-moved=dimmed-zebra --color-moved-ws=allow-indentation-change HEAD~1 HEAD

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AKYzhrMnPK61XHWEch4a6E
ScriptedRouteIO plays a strict script of console calls and outcomes; a
call the script does not expect fails the test. New tests:

- A trainer's line freezes the at-the-wall check (DIALOG), the battle
  runs, and the walk on reaches the wall (BLOCKED): the walker goes on
  (r54: it judged the stale DIALOG and failed).
- Logan (Route 202, (26, 4), looking south) stops an open leg west along
  row 5 after 3 taps: the replan starts from (27, 5) and (26, 5), and its
  legs never walk into him from either (r55).
- A wall leg out of time whose check also runs out of time counts as at
  the wall only when the holding check says so.
- route_turn() turns with one D-pad tap of at most 80 ms (40 to 80 ms
  only turned on the console; a 100 ms stick tap stepped 0.6 tile).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AKYzhrMnPK61XHWEch4a6E
dayfine and others added 7 commits November 2, 2026 00:26
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AKYzhrMnPK61XHWEch4a6E
…a step

A tap whose view barely changed (the president walking off as we turned)
was counted as not moving, so "east 2" read "moved 1" while the console
showed both tiles walked (r67). What blocks one tap still blocks the next,
so a quiet tap that a moving tap follows moved too.

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
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AKYzhrMnPK61XHWEch4a6E
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

autostory AutoStory programs game:bdsp Brilliant Diamond/Shining Pearl navigation Maps, planner, walker

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant