Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
74 commits
Select commit Hold shift + click to select a range
c3c16c8
BDSP navigation: the walker, with battles passed in
dayfine Nov 1, 2026
155bf55
Merge bdsp/nav-v4 (#127: run the BDSP tests) into bdsp/walk-v4
dayfine Nov 1, 2026
bf77fbe
Merge bdsp/nav-v4 into bdsp/walk-v4: the maps move onto the shared Ma…
dayfine Nov 1, 2026
de7c108
BDSP navigation: the walker plans on the story world
dayfine Nov 1, 2026
c3ee13c
Merge branch 'bdsp/nav-v4' into bdsp/walk-v4
dayfine Nov 1, 2026
090783f
BDSP navigation: the walker calls the planner's slide_to_wall()
dayfine Nov 1, 2026
d20ad68
Merge bdsp/nav-v4 (b798ef3ec: CI and code-health fixes) into bdsp/wal…
dayfine Nov 1, 2026
d5046f2
BDSP navigation: the walker calls the story world's free functions
dayfine Nov 1, 2026
6daf606
BDSP walker: formatting the code-health check asks for
dayfine Nov 1, 2026
91dfd2e
BDSP walker: the story language behind a getter and a setter
dayfine Nov 1, 2026
2bb2fb9
BDSP walker: walks take a JoystickPosition, and options instead of bools
dayfine Nov 1, 2026
b678b4a
BDSP walker: walk_route() and its helpers move to PlannedRoute
dayfine Nov 1, 2026
6a24b56
BDSP walker: walk_route() as a RouteWalker with one function per deci…
dayfine Nov 1, 2026
c459094
BDSP walker: the transition watchers take only what their callers set
dayfine Nov 1, 2026
352c9fc
BDSP walker: LegWalk is a plain struct
dayfine Nov 1, 2026
9322b6c
Merge bdsp/nav-v4 (#122 at b966c5d93) into bdsp/walk-v4
dayfine Nov 1, 2026
aeb36c8
BDSP walker: credit #1717 for the pieces adapted from it
dayfine Nov 1, 2026
bea9a8a
Merge bdsp/nav-v4 (CRLF Segment 00 tests header) into bdsp/walk-v4
dayfine Nov 1, 2026
ba95847
BDSP walker: new files in CRLF
dayfine Nov 1, 2026
4cec241
BDSP walker: give up after the third dialogue the map does not explain
dayfine Nov 2, 2026
33761c2
BDSP walker: a scene at a map's edge stands in for the missing banner
dayfine Nov 2, 2026
b95836c
BDSP walker: wait for the scene's first line before failing on a miss…
dayfine Nov 2, 2026
608a99c
BDSP walker: no banner read is a warning; only a wrong banner fails
dayfine Nov 2, 2026
31816e5
BDSP walker: arriving with no banner read at all is a warning too
dayfine Nov 2, 2026
d839fb9
BDSP walker: time wall legs at the plan's pace, walk or run
dayfine Nov 2, 2026
a3b6900
Merge bdsp/nav-v4 forward
dayfine Nov 2, 2026
04656c2
Merge bdsp/nav-v4 forward
dayfine Nov 2, 2026
8d0840b
Merge the BDSP chain forward
dayfine Nov 2, 2026
1ce3bb1
BDSP walker: watch for the new map's banner a while after the last leg
dayfine Nov 2, 2026
7d6180f
Merge the BDSP chain forward
dayfine Nov 2, 2026
9712a58
Merge the BDSP chain forward
dayfine Nov 2, 2026
d964429
Merge the BDSP chain forward
dayfine Nov 2, 2026
ec50ad2
BDSP AutoStory walk: turn with a 50 ms D-pad tap
dayfine Nov 2, 2026
ac97a4d
BDSP AutoStory walk: after a trainer on a wall leg, judge the walk on
dayfine Nov 2, 2026
b6990c8
BDSP AutoStory walk: after a trainer on an open leg, plan from the ta…
dayfine Nov 2, 2026
eee7d46
BDSP AutoStory walk: turn an open leg with a tap too short to step
dayfine Nov 2, 2026
433501b
BDSP AutoStory walk: a straight stick walk goes on the D-pad
dayfine Nov 2, 2026
ac5f55d
BDSP AutoStory walk: put the route walker's console steps behind RouteIO
dayfine Nov 2, 2026
e8a5efc
BDSP AutoStory walk: test the route walker on scripted console outcomes
dayfine Nov 2, 2026
5286265
Merge bdsp/walk-v4-routeio into bdsp/walk-v4
dayfine Nov 2, 2026
8a4342f
BDSP AutoStory walk: a quiet tap followed by a moving one counted as …
dayfine Nov 2, 2026
d4ec93b
Merge origin/bdsp/nav-v4 into bdsp/walk-v4
dayfine Nov 2, 2026
9ddc2fb
Merge bdsp/nav-v4 into bdsp/walk-v4
dayfine Nov 2, 2026
2a87f19
Merge bdsp/maps-v4 (coord events) into bdsp/walk-v4
dayfine Nov 2, 2026
ace8659
Merge bdsp/nav-v4 into bdsp/walk-v4
dayfine Nov 2, 2026
b22e947
Merge bdsp/nav-v4 (e531694c5: verify mode from #122) into bdsp/walk-v4
dayfine Nov 3, 2026
89f673f
Merge commit '8805523710a2ed6298583cc53652316116f0fc6e' into HEAD
dayfine Nov 5, 2026
166b859
Merge origin/bdsp/nav-v4 into bdsp/walk-v4
dayfine Nov 6, 2026
0d6adc7
BDSP AutoStory walk: align with PR #231 lint conventions
dayfine Nov 6, 2026
a90341b
Merge origin/bdsp/nav-v4 into bdsp/walk-v4
dayfine Nov 7, 2026
f02108f
Merge remote-tracking branch 'origin/bdsp/nav-v4' into bdsp/walk-v4
dayfine Nov 7, 2026
9c480af
BDSP walk: track encounter origin and lag recovery during tap walks
dayfine Nov 8, 2026
654e8f0
Merge origin/bdsp/nav-v4 into bdsp/walk-v4
dayfine Nov 8, 2026
44f8445
Merge remote-tracking branch 'origin/bdsp/nav-v4' into bdsp/walk-v4
dayfine Nov 8, 2026
070078e
BDSP AutoStory walk: adopt wall recovery for interrupted open and wal…
dayfine Nov 8, 2026
940a183
Merge remote-tracking branch 'origin/bdsp/nav-v4' into bdsp/walk-v4
dayfine Nov 8, 2026
a086675
Merge origin/bdsp/nav-v4 into bdsp/walk-v4
dayfine Nov 8, 2026
e909042
Merge remote-tracking branch 'origin/bdsp/nav-v4' into HEAD
dayfine Nov 9, 2026
4421529
Merge bdsp/nav-v4 into bdsp/walk-v4
dayfine Nov 9, 2026
3cf5d3f
Merge bdsp/nav-v4 into bdsp/walk-v4
dayfine Nov 9, 2026
9e05c38
Merge bdsp/nav-v4 into bdsp/walk-v4
dayfine Nov 9, 2026
5819bc0
BDSP: fold #226 fixes into the walk and location reader
dayfine Nov 9, 2026
8156495
Merge bdsp/nav-v4 into bdsp/walk-v4
dayfine Nov 9, 2026
0493764
Merge bdsp/nav-v4 into bdsp/walk-v4
dayfine Nov 9, 2026
a369dcf
BDSP AutoStory: WarpFadeWatch follows a warp's fade on the shared Tra…
dayfine Nov 9, 2026
049be80
Merge bdsp/nav-v4 (merge of #122 b3aa69e19) into bdsp/walk-v4
dayfine Nov 9, 2026
b6e936f
BDSP: time a walk's screen events in its result
dayfine Nov 9, 2026
e6fd052
BDSP: place a wild battle on an open leg's taps by its screen events
dayfine Nov 9, 2026
e03448d
BDSP: default-initialize the walk's event log directly (its construct…
dayfine Nov 9, 2026
53fd828
BDSP: count record_tap_battle()'s taps from 1, 0 for a step before th…
dayfine Nov 9, 2026
2310a11
BDSP: time a tap battle's step with a signed tap count
dayfine Nov 9, 2026
4f76548
BDSP: the route walker places an open leg's battle by its screen events
dayfine Nov 9, 2026
c1ae800
Merge bdsp/nav-v4 into bdsp/walk-v4
dayfine Nov 9, 2026
9e2f426
Merge bdsp/nav-v4 into bdsp/walk-v4
dayfine Nov 9, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/* BDSP Transition Watchers
*
* From: https://github.com/PokemonAutomation/
*
* Adapted from PokemonAutomation/Arduino-Source#1717 by Developer-Butters.
*/

#include "PokemonBDSP_TransitionWatchers.h"

namespace PokemonAutomation{
namespace NintendoSwitch{
namespace PokemonBDSP{


WhiteScreenOverWatcher::WhiteScreenOverWatcher(Color color, const ImageFloatBox& box)
: VisualInferenceCallback("WhiteScreenOverWatcher")
, m_on(color, box, WhiteScreenWatcher::FinderType::PRESENT, std::chrono::milliseconds(100))
, m_off(color, box, WhiteScreenWatcher::FinderType::GONE, std::chrono::milliseconds(100))
{}
void WhiteScreenOverWatcher::make_overlays(VideoOverlaySet& items) const{
m_on.make_overlays(items);
}
bool WhiteScreenOverWatcher::process_frame(const ImageViewRGB32& frame, WallClock timestamp){
if (m_white_is_over.load(std::memory_order_acquire)){
return true;
}
if (!m_has_been_white){
m_has_been_white = m_on.process_frame(frame, timestamp);
return false;
}
bool is_over = m_off.process_frame(frame, timestamp);
if (!is_over){
return false;
}
m_white_is_over.store(true, std::memory_order_release);
return true;
}
bool WhiteScreenOverWatcher::white_is_over(const ImageViewRGB32& frame){
return m_white_is_over.load(std::memory_order_acquire);
}


} // namespace PokemonBDSP
} // namespace NintendoSwitch
} // namespace PokemonAutomation
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/* BDSP Transition Watchers
*
* From: https://github.com/PokemonAutomation/
*
* Adapted from PokemonAutomation/Arduino-Source#1717 by Developer-Butters.
*/

#ifndef PokemonAutomation_PokemonBDSP_TransitionWatchers_H
#define PokemonAutomation_PokemonBDSP_TransitionWatchers_H

#include "CommonTools/VisualDetectors/BlackScreenDetector.h"

namespace PokemonAutomation{
namespace NintendoSwitch{
namespace PokemonBDSP{


// AutoStory-specific transition handling; shared watchers retain upstream behavior.
// A white screen (RGB sum over 500, stddev sum under 10) in `box`,
// present or gone for `duration`.
class WhiteScreenWatcher : public DetectorToFinder<WhiteScreenDetector>{
public:
WhiteScreenWatcher(Color color, const ImageFloatBox& box, FinderType finder_type, std::chrono::milliseconds duration)
: DetectorToFinder("WhiteScreenWatcher", finder_type, duration, color, box, 500, 10)
{}
};

// The screen in `box` went white for 100 ms, then stopped being white for
// 100 ms: an encounter's flash.
class WhiteScreenOverWatcher : public VisualInferenceCallback{
public:
WhiteScreenOverWatcher(Color color, const ImageFloatBox& box);

bool white_is_over(const ImageViewRGB32& frame);

virtual void make_overlays(VideoOverlaySet& items) const override;

virtual bool process_frame(const ImageViewRGB32& frame, WallClock timestamp) override;

private:
WhiteScreenWatcher m_on;
WhiteScreenWatcher m_off;
bool m_has_been_white = false;
std::atomic<bool> m_white_is_over = false;
};


} // namespace PokemonBDSP
} // namespace NintendoSwitch
} // namespace PokemonAutomation
#endif
4 changes: 4 additions & 0 deletions SerialPrograms/Source/PokemonBDSP/PokemonBDSP_Tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@

#include "Common/Cpp/TestRunners/UnitTestDatabase.h"
#include "Programs/AutoStory/PokemonBDSP_AutoStory_Maps_Tests.h"
#include "Programs/AutoStory/PokemonBDSP_AutoStory_PlannedRoute_Tests.h"
#include "Programs/AutoStory/PokemonBDSP_AutoStory_RoutePlanner_Tests.h"
#include "Programs/AutoStory/PokemonBDSP_AutoStory_Segment00_Tests.h"
#include "Programs/AutoStory/PokemonBDSP_AutoStory_StoryMaps_Tests.h"
#include "Programs/AutoStory/PokemonBDSP_AutoStory_StoryWorld_Tests.h"
#include "Programs/AutoStory/PokemonBDSP_AutoStory_Walk_Tests.h"
#include "PokemonBDSP_Tests.h"

namespace PokemonAutomation{
Expand All @@ -24,6 +26,8 @@ void add_tests(UnitTestDatabase& database){
add_tests_AutoStory_RoutePlanner(database);
add_tests_AutoStory_StoryMaps(database);
add_tests_AutoStory_Segment00(database);
add_tests_AutoStory_Walk(database);
add_tests_AutoStory_PlannedRoute(database);
}


Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
/* BDSP AutoStory - Overworld Detector
*
* From: https://github.com/PokemonAutomation/
*
* Adapted from PokemonAutomation/Arduino-Source#1717 by Developer-Butters.
*/

#include "CommonFramework/ImageTools/ImageStats.h"
#include "CommonFramework/VideoPipeline/VideoOverlayScopes.h"

#include "CommonTools/Async/InferenceRoutines.h"
#include "CommonTools/Images/SolidColorTest.h"

#include "PokemonBDSP_AutoStory_OverworldDetector.h"

using namespace std::chrono_literals;

namespace PokemonAutomation{
namespace NintendoSwitch{
namespace PokemonBDSP{


// ---------------------------------------------------------------------------
// OverworldDetector
// ---------------------------------------------------------------------------

OverworldDetector::OverworldDetector(Color color)
: m_color(color)
, m_battle_menu(BattleType::STANDARD, color){
}

void OverworldDetector::make_overlays(VideoOverlaySet& items) const {
m_dialog.make_overlays(items);
m_battle_menu.make_overlays(items);
m_menu.make_overlays(items);
}

bool OverworldDetector::detect(const ImageViewRGB32& screen){
// We are in the overworld when none of the overlay screens are present.
if (m_dialog.detect(screen)){
return false;
}
if (m_battle_menu.detect(screen)){
return false;
}
if (m_menu.detect(screen)){
return false;
}
return true;
}


// ---------------------------------------------------------------------------
// OverworldWatcher
// ---------------------------------------------------------------------------

OverworldWatcher::OverworldWatcher(Color color)
: OverworldDetector(color)
, VisualInferenceCallback("OverworldWatcher"){
}

void OverworldWatcher::make_overlays(VideoOverlaySet& items) const {
OverworldDetector::make_overlays(items);
}

bool OverworldWatcher::process_frame(const ImageViewRGB32& frame, WallClock /*timestamp*/){
return detect(frame);
}


// ---------------------------------------------------------------------------
// PoketchButtonDetector
// ---------------------------------------------------------------------------

PoketchButtonDetector::PoketchButtonDetector(Color color)
: m_color(color)
, m_button(0.968, 0.170, 0.022, 0.120){
}

void PoketchButtonDetector::make_overlays(VideoOverlaySet& items) const {
items.add(m_color, m_button);
}

bool PoketchButtonDetector::detect(const ImageViewRGB32& screen){
ImageStats stats = image_stats(extract_box_reference(screen, m_button));
// The button is a glossy red with a highlight, so allow a wide stddev.
return is_solid(stats, {0.74, 0.10, 0.16}, 0.12, 80);
}

PoketchButtonWatcher::PoketchButtonWatcher(Color color)
: PoketchButtonDetector(color)
, VisualInferenceCallback("PoketchButtonWatcher"){
}

void PoketchButtonWatcher::make_overlays(VideoOverlaySet& items) const {
PoketchButtonDetector::make_overlays(items);
}

bool PoketchButtonWatcher::process_frame(const ImageViewRGB32& frame, WallClock){
return detect(frame);
}


static bool look_for_poketch_button(VideoStream& stream, ProControllerContext& context){
context.wait_for_all_requests();
PoketchButtonWatcher watcher;
return wait_until(stream, context, 2s, {{watcher}}) == 0;
}

bool ensure_poketch_visible(VideoStream& stream, ProControllerContext& context){
for (size_t attempt = 0; attempt < 3; attempt++){
if (look_for_poketch_button(stream, context)){
return true;
}
stream.log("[AutoStory] Poketch button not found. Attempt " + std::to_string(attempt + 1) + " of 3.",
COLOR_ORANGE);

if (attempt == 0){
// Most likely hidden: one tap shows it.
pbf_press_button(context, BUTTON_R, 205ms, 0ms);
}else{
// Long press hides it, then a tap shows it at the normal size.
pbf_press_button(context, BUTTON_R, 1548ms, 0ms);
pbf_wait(context, 1418ms);
pbf_press_button(context, BUTTON_R, 143ms, 0ms);
}
}

// Check the result of the last press sequence.
return look_for_poketch_button(stream, context);
}


} // namespace PokemonBDSP
} // namespace NintendoSwitch
} // namespace PokemonAutomation
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/* BDSP AutoStory - Overworld Detector
*
* From: https://github.com/PokemonAutomation/
*
* Adapted from PokemonAutomation/Arduino-Source#1717 by Developer-Butters.
*
* Detects that the player is in the free-roaming overworld state:
* no dialog box, no battle menu, and no in-game menu open.
*
* BDSP does not ship a standalone OverworldDetector in PokemonBDSP/Inference/,
* so this composite detector is defined here for AutoStory use.
*
* Reuses:
* - ShortDialogDetector (PokemonBDSP_DialogDetector.h) — absence required
* - BattleMenuDetector (PokemonBDSP_BattleMenuDetector.h) — absence required
* - MenuDetector (PokemonBDSP_MenuDetector.h) — absence required
*
*/

#ifndef PokemonAutomation_PokemonBDSP_AutoStory_OverworldDetector_H
#define PokemonAutomation_PokemonBDSP_AutoStory_OverworldDetector_H

#include "Common/Cpp/Color.h"

#include "CommonFramework/Tools/VideoStream.h"

#include "CommonTools/InferenceCallbacks/VisualInferenceCallback.h"
#include "CommonTools/VisualDetector.h"

#include "NintendoSwitch/Commands/NintendoSwitch_Commands_PushButtons.h"

#include "PokemonBDSP/Inference/Battles/PokemonBDSP_BattleMenuDetector.h"
#include "PokemonBDSP/Inference/PokemonBDSP_DialogDetector.h"
#include "PokemonBDSP/Inference/PokemonBDSP_MenuDetector.h"

namespace PokemonAutomation{
namespace NintendoSwitch{
namespace PokemonBDSP{


// Static (single-frame) version — use when you already have a frame.
class OverworldDetector : public StaticScreenDetector {
public:
OverworldDetector(Color color = COLOR_CYAN);

virtual void make_overlays(VideoOverlaySet& items) const override;

// Returns true when none of: short dialog, battle menu, or in-game menu
// are present on the given frame.
virtual bool detect(const ImageViewRGB32& screen) override;

private:
Color m_color;
ShortDialogDetector m_dialog;
BattleMenuDetector m_battle_menu;
MenuDetector m_menu;
};


// Watcher (callback) version — use with run_until<> or wait_until().
class OverworldWatcher : public OverworldDetector, public VisualInferenceCallback {
public:
OverworldWatcher(Color color = COLOR_CYAN);

virtual void make_overlays(VideoOverlaySet& items) const override;
virtual bool process_frame(const ImageViewRGB32& frame, WallClock timestamp) override;
};


// Detects the big red button on the right edge of the Poketch overlay.
// Present only while the Poketch is shown at its normal size.
class PoketchButtonDetector : public StaticScreenDetector {
public:
PoketchButtonDetector(Color color = COLOR_RED);

virtual void make_overlays(VideoOverlaySet& items) const override;
virtual bool detect(const ImageViewRGB32& screen) override;

private:
Color m_color;
ImageFloatBox m_button;
};

// Inference watcher tracking the visibility of the Poketch button on screen.
class PoketchButtonWatcher : public PoketchButtonDetector, public VisualInferenceCallback {
public:
PoketchButtonWatcher(Color color = COLOR_RED);

virtual void make_overlays(VideoOverlaySet& items) const override;
virtual bool process_frame(const ImageViewRGB32& frame, WallClock timestamp) override;
};

// Tries up to 3 times to get the Poketch button on screen using R presses.
// Returns true if the button was seen.
bool ensure_poketch_visible(VideoStream& stream, ProControllerContext& context);


} // namespace PokemonBDSP
} // namespace NintendoSwitch
} // namespace PokemonAutomation
#endif
Loading
Loading