From 431bff5555b5cc122371faf74229b14af04c5800 Mon Sep 17 00:00:00 2001 From: kichithewolf Date: Tue, 3 Mar 2026 09:41:50 -0500 Subject: [PATCH 1/8] retry A press --- .../ShinyHunting/PokemonFRLG_GiftReset.cpp | 25 ++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_GiftReset.cpp b/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_GiftReset.cpp index 5fbcc9f68..66727120b 100644 --- a/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_GiftReset.cpp +++ b/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_GiftReset.cpp @@ -100,7 +100,30 @@ void GiftReset::obtain_pokemon(SingleSwitchProgramEnvironment& env, ProControlle */ env.log("Obtaining Pokemon."); - pbf_press_button(context, BUTTON_A, 320ms, 640ms); + AdvanceWhiteDialogWatcher adv_white_start(COLOR_RED); + + int rets = run_until( + env.console, context, + [](ProControllerContext& context){ + for (int i = 0; i < 10; i++){ + pbf_press_button(context, BUTTON_A, 320ms, 640ms); + pbf_wait(context, 2000ms); + context.wait_for_all_requests(); + } + }, + { adv_white_start } + ); + context.wait_for_all_requests(); + if (rets < 0){ + env.update_stats(); + env.log("obtain_pokemon(): Unable to start starter dialog after 10 attempts.", COLOR_RED); + OperationFailedException::fire( + ErrorReport::SEND_ERROR_REPORT, + "obtain_pokemon(): Unable to start starter dialog after 10 attempts.", + env.console + ); + } + env.log("Initial A press completed."); bool seen_selection_arrow = false; //bool seen_nickname_arrow = false; From 730e503ab7ab85edd22d892b170b5d3ff6071b87 Mon Sep 17 00:00:00 2001 From: kichithewolf Date: Tue, 3 Mar 2026 11:20:51 -0500 Subject: [PATCH 2/8] FRLG tests, adjust dialog detectors --- .../Dialogs/PokemonFRLG_DialogDetector.cpp | 28 +++++++-------- .../Source/Tests/PokemonFRLG_Tests.cpp | 36 +++++++++++++++++++ .../Source/Tests/PokemonFRLG_Tests.h | 24 +++++++++++++ SerialPrograms/Source/Tests/TestMap.cpp | 2 ++ SerialPrograms/cmake/SourceFiles.cmake | 2 ++ 5 files changed, 78 insertions(+), 14 deletions(-) create mode 100644 SerialPrograms/Source/Tests/PokemonFRLG_Tests.cpp create mode 100644 SerialPrograms/Source/Tests/PokemonFRLG_Tests.h diff --git a/SerialPrograms/Source/PokemonFRLG/Inference/Dialogs/PokemonFRLG_DialogDetector.cpp b/SerialPrograms/Source/PokemonFRLG/Inference/Dialogs/PokemonFRLG_DialogDetector.cpp index 733d07391..e9c660bb4 100644 --- a/SerialPrograms/Source/PokemonFRLG/Inference/Dialogs/PokemonFRLG_DialogDetector.cpp +++ b/SerialPrograms/Source/PokemonFRLG/Inference/Dialogs/PokemonFRLG_DialogDetector.cpp @@ -39,9 +39,9 @@ bool WhiteDialogDetector::detect(const ImageViewRGB32& screen){ ImageViewRGB32 right_image = extract_box_reference(screen, m_right_box); ImageViewRGB32 top_image = extract_box_reference(screen, m_top_box); ImageViewRGB32 bottom_image = extract_box_reference(screen, m_bottom_box); - if (is_solid(right_image, { 0.25, 0.38, 0.369 }) - && is_solid(top_image, { 0.25, 0.38, 0.369 }) - && is_solid(bottom_image, { 0.25, 0.38, 0.369 }) + if (is_solid(right_image, { 0.333333, 0.333333, 0.333333 }) + && is_solid(top_image, { 0.333333, 0.333333, 0.333333 }) + && is_solid(bottom_image, { 0.333333, 0.333333, 0.333333 }) ){ return true; } @@ -81,11 +81,11 @@ bool AdvanceWhiteDialogDetector::detect(const ImageViewRGB32& screen){ ImageViewRGB32 top_image = extract_box_reference(screen, m_top_box); ImageViewRGB32 bottom_image = extract_box_reference(screen, m_bottom_box); - if (is_solid(right_image, { 0.25, 0.38, 0.369 }) - && is_solid(top_image, { 0.25, 0.38, 0.369 }) - && is_solid(bottom_image, { 0.25, 0.38, 0.369 }) - && (stats.average.r > stats.average.b + 200) - && (stats.average.r > stats.average.g + 200) + if (is_solid(right_image, { 0.333333, 0.333333, 0.333333 }) + && is_solid(top_image, { 0.333333, 0.333333, 0.333333 }) + && is_solid(bottom_image, { 0.333333, 0.333333, 0.333333 }) + && (stats.average.r > stats.average.b + 180) + && (stats.average.r > stats.average.g + 180) ) { return true; @@ -110,10 +110,10 @@ bool SelectionDialogDetector::detect(const ImageViewRGB32& screen){ ImageViewRGB32 top_image = extract_box_reference(screen, m_top_box); ImageViewRGB32 bottom_image = extract_box_reference(screen, m_bottom_box); ImageViewRGB32 selection_image = extract_box_reference(screen, m_selection_box); - if (is_solid(right_image, { 0.25, 0.38, 0.369 }) - && is_solid(top_image, { 0.25, 0.38, 0.369 }) - && is_solid(bottom_image, { 0.25, 0.38, 0.369 }) - && is_solid(selection_image, { 0.25, 0.38, 0.369 }) + if (is_solid(right_image, { 0.333333, 0.333333, 0.333333 }) + && is_solid(top_image, { 0.333333, 0.333333, 0.333333 }) + && is_solid(bottom_image, { 0.333333, 0.333333, 0.333333 }) + && is_solid(selection_image, { 0.333333, 0.333333, 0.333333 }) ){ return true; } @@ -205,8 +205,8 @@ bool AdvanceBattleDialogDetector::detect(const ImageViewRGB32& screen){ if (is_solid(dialog_top_image, { 0.176, 0.357, 0.467 }) && is_solid(dialog_right_image, { 0.176, 0.357, 0.467 }) - && (stats.average.r > stats.average.b + 200) - && (stats.average.r > stats.average.g + 200) + && (stats.average.r > stats.average.b + 180) + && (stats.average.r > stats.average.g + 180) ) { return true; diff --git a/SerialPrograms/Source/Tests/PokemonFRLG_Tests.cpp b/SerialPrograms/Source/Tests/PokemonFRLG_Tests.cpp new file mode 100644 index 000000000..fec1b19a9 --- /dev/null +++ b/SerialPrograms/Source/Tests/PokemonFRLG_Tests.cpp @@ -0,0 +1,36 @@ +/* PokemonFRLG Tests + * + * From: https://github.com/PokemonAutomation/ + * + */ + + +#include "CommonFramework/Logging/Logger.h" +#include "PokemonFRLG/Inference/Dialogs/PokemonFRLG_DialogDetector.h" +#include "PokemonFRLG_Tests.h" +#include "TestUtils.h" +#include "CommonFramework/Language.h" +#include "CommonFramework/ImageTools/ImageBoxes.h" +#include "CommonFramework/Recording/StreamHistorySession.h" +#include "NintendoSwitch/Controllers/SerialPABotBase/NintendoSwitch_SerialPABotBase_WiredController.h" +#include "NintendoSwitch/NintendoSwitch_ConsoleHandle.h" + +#include +using std::cout; +using std::cerr; +using std::endl; + +namespace PokemonAutomation{ + +using namespace NintendoSwitch; +using namespace NintendoSwitch::PokemonFRLG; + +int test_pokemonFRLG_AdvanceWhiteDialogDetector(const ImageViewRGB32& image, bool target){ + auto overlay = DummyVideoOverlay(); + AdvanceWhiteDialogDetector detector(COLOR_RED); + bool result = detector.detect(image); + TEST_RESULT_EQUAL(result, target); + return 0; +} + +} diff --git a/SerialPrograms/Source/Tests/PokemonFRLG_Tests.h b/SerialPrograms/Source/Tests/PokemonFRLG_Tests.h new file mode 100644 index 000000000..13deb4b61 --- /dev/null +++ b/SerialPrograms/Source/Tests/PokemonFRLG_Tests.h @@ -0,0 +1,24 @@ +/* PokemonFRLG Tests + * + * From: https://github.com/PokemonAutomation/ + * + * + */ + + +#ifndef PokemonAutomation_Tests_PokemonFRLG_Tests_H +#define PokemonAutomation_Tests_PokemonFRLG_Tests_H + +#include +#include + +namespace PokemonAutomation{ + +class ImageViewRGB32; + + +int test_pokemonFRLG_AdvanceWhiteDialogDetector(const ImageViewRGB32& image, bool target); + +} + +#endif diff --git a/SerialPrograms/Source/Tests/TestMap.cpp b/SerialPrograms/Source/Tests/TestMap.cpp index 0b4e5159c..07cf488e4 100644 --- a/SerialPrograms/Source/Tests/TestMap.cpp +++ b/SerialPrograms/Source/Tests/TestMap.cpp @@ -9,6 +9,7 @@ #include "CommonFramework_Tests.h" #include "Kernels_Tests.h" #include "NintendoSwitch_Tests.h" +#include "PokemonFRLG_Tests.h" #include "PokemonHome_Tests.h" #include "PokemonLA_Tests.h" #include "PokemonLZA_Tests.h" @@ -308,6 +309,7 @@ const std::map TEST_MAP = { {"PokemonLZA_HyperspaceCalorieDetector", std::bind(image_int_detector_helper, test_pokemonLZA_HyperspaceCalorieDetector, _1)}, {"PokemonLZA_FlavorPowerScreenDetector", test_pokemonLZA_FlavorPowerScreenDetector}, {"PokemonLZA_DonutBerriesReader", test_pokemonLZA_DonutBerriesReader}, + {"PokemonFRLG_AdvanceWhiteDialogDetector", std::bind(image_bool_detector_helper, test_pokemonFRLG_AdvanceWhiteDialogDetector, _1)}, }; TestFunction find_test_function(const std::string& test_space, const std::string& test_name){ diff --git a/SerialPrograms/cmake/SourceFiles.cmake b/SerialPrograms/cmake/SourceFiles.cmake index badf7c142..e084f5b64 100644 --- a/SerialPrograms/cmake/SourceFiles.cmake +++ b/SerialPrograms/cmake/SourceFiles.cmake @@ -2660,6 +2660,8 @@ file(GLOB LIBRARY_SOURCES Source/Tests/Kernels_Tests.h Source/Tests/NintendoSwitch_Tests.cpp Source/Tests/NintendoSwitch_Tests.h + Source/Tests/PokemonFRLG_Tests.cpp + Source/Tests/PokemonFRLG_Tests.h Source/Tests/PokemonHome_Tests.cpp Source/Tests/PokemonHome_Tests.h Source/Tests/PokemonLA_Tests.cpp From d8d5e008bbcf824aab6a98d9f4776c0a33d95841 Mon Sep 17 00:00:00 2001 From: kichithewolf Date: Tue, 3 Mar 2026 13:30:19 -0500 Subject: [PATCH 3/8] arrow color adjustment --- .../Inference/Dialogs/PokemonFRLG_DialogDetector.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SerialPrograms/Source/PokemonFRLG/Inference/Dialogs/PokemonFRLG_DialogDetector.cpp b/SerialPrograms/Source/PokemonFRLG/Inference/Dialogs/PokemonFRLG_DialogDetector.cpp index e9c660bb4..54321d557 100644 --- a/SerialPrograms/Source/PokemonFRLG/Inference/Dialogs/PokemonFRLG_DialogDetector.cpp +++ b/SerialPrograms/Source/PokemonFRLG/Inference/Dialogs/PokemonFRLG_DialogDetector.cpp @@ -66,7 +66,7 @@ bool AdvanceWhiteDialogDetector::detect(const ImageViewRGB32& screen){ //Filter out background ImageRGB32 filtered_region = filter_rgb32_range( extract_box_reference(screen, m_dialog_box), - combine_rgb(185, 0, 1), combine_rgb(255, 32, 33), Color(0), replace_color_within_range + combine_rgb(164, 0, 0), combine_rgb(255, 114, 87), Color(0), replace_color_within_range ); ImageStats stats = image_stats(filtered_region); @@ -189,7 +189,7 @@ bool AdvanceBattleDialogDetector::detect(const ImageViewRGB32& screen){ //Filter out background ImageRGB32 filtered_region = filter_rgb32_range( extract_box_reference(screen, m_dialog_box), - combine_rgb(185, 0, 1), combine_rgb(255, 32, 33), Color(0), replace_color_within_range + combine_rgb(164, 0, 0), combine_rgb(255, 114, 87), Color(0), replace_color_within_range ); ImageStats stats = image_stats(filtered_region); From 235e7e85eaae44432f3f545eb56ebdfd8c253d5b Mon Sep 17 00:00:00 2001 From: kichithewolf Date: Tue, 3 Mar 2026 15:17:51 -0500 Subject: [PATCH 4/8] Update PokemonFRLG_GiftReset.cpp --- .../ShinyHunting/PokemonFRLG_GiftReset.cpp | 40 ++++++++++--------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_GiftReset.cpp b/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_GiftReset.cpp index 66727120b..361653d7e 100644 --- a/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_GiftReset.cpp +++ b/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_GiftReset.cpp @@ -100,31 +100,33 @@ void GiftReset::obtain_pokemon(SingleSwitchProgramEnvironment& env, ProControlle */ env.log("Obtaining Pokemon."); - AdvanceWhiteDialogWatcher adv_white_start(COLOR_RED); - - int rets = run_until( - env.console, context, - [](ProControllerContext& context){ - for (int i = 0; i < 10; i++){ - pbf_press_button(context, BUTTON_A, 320ms, 640ms); - pbf_wait(context, 2000ms); - context.wait_for_all_requests(); - } - }, - { adv_white_start } - ); - context.wait_for_all_requests(); - if (rets < 0){ - env.update_stats(); - env.log("obtain_pokemon(): Unable to start starter dialog after 10 attempts.", COLOR_RED); + if (TARGET == Target::starters) { + AdvanceWhiteDialogWatcher adv_white_start(COLOR_RED); + int rets = run_until( + env.console, context, + [](ProControllerContext& context) { + for (int i = 0; i < 10; i++) { + pbf_press_button(context, BUTTON_A, 320ms, 640ms); + pbf_wait(context, 2000ms); + context.wait_for_all_requests(); + } + }, + { adv_white_start } + ); + context.wait_for_all_requests(); + if (rets < 0) { + env.update_stats(); + env.log("obtain_pokemon(): Unable to start starter dialog after 10 attempts.", COLOR_RED); OperationFailedException::fire( ErrorReport::SEND_ERROR_REPORT, "obtain_pokemon(): Unable to start starter dialog after 10 attempts.", env.console ); + } + env.log("Initial A press completed."); + } else { + pbf_press_button(context, BUTTON_A, 320ms, 640ms); } - env.log("Initial A press completed."); - bool seen_selection_arrow = false; //bool seen_nickname_arrow = false; while (true){ From 92491571cf42208603ff19389b6d592120ffc391 Mon Sep 17 00:00:00 2001 From: kichithewolf Date: Tue, 3 Mar 2026 15:36:29 -0500 Subject: [PATCH 5/8] shiny symbol test (no adjustments) --- SerialPrograms/Source/Tests/PokemonFRLG_Tests.cpp | 10 ++++++++++ SerialPrograms/Source/Tests/PokemonFRLG_Tests.h | 2 ++ SerialPrograms/Source/Tests/TestMap.cpp | 1 + 3 files changed, 13 insertions(+) diff --git a/SerialPrograms/Source/Tests/PokemonFRLG_Tests.cpp b/SerialPrograms/Source/Tests/PokemonFRLG_Tests.cpp index fec1b19a9..e80e12a64 100644 --- a/SerialPrograms/Source/Tests/PokemonFRLG_Tests.cpp +++ b/SerialPrograms/Source/Tests/PokemonFRLG_Tests.cpp @@ -7,6 +7,7 @@ #include "CommonFramework/Logging/Logger.h" #include "PokemonFRLG/Inference/Dialogs/PokemonFRLG_DialogDetector.h" +#include "PokemonFRLG/Inference/PokemonFRLG_ShinySymbolDetector.h" #include "PokemonFRLG_Tests.h" #include "TestUtils.h" #include "CommonFramework/Language.h" @@ -33,4 +34,13 @@ int test_pokemonFRLG_AdvanceWhiteDialogDetector(const ImageViewRGB32& image, boo return 0; } +int test_pokemonFRLG_ShinySymbolDetector(const ImageViewRGB32& image, bool target){ + auto& logger = global_logger_command_line(); + auto overlay = DummyVideoOverlay(); + ShinySymbolDetector detector(COLOR_RED); + bool result = detector.read(logger, image); + TEST_RESULT_EQUAL(result, target); + return 0; +} + } diff --git a/SerialPrograms/Source/Tests/PokemonFRLG_Tests.h b/SerialPrograms/Source/Tests/PokemonFRLG_Tests.h index 13deb4b61..7d49c9d99 100644 --- a/SerialPrograms/Source/Tests/PokemonFRLG_Tests.h +++ b/SerialPrograms/Source/Tests/PokemonFRLG_Tests.h @@ -19,6 +19,8 @@ class ImageViewRGB32; int test_pokemonFRLG_AdvanceWhiteDialogDetector(const ImageViewRGB32& image, bool target); +int test_pokemonFRLG_ShinySymbolDetector(const ImageViewRGB32& image, bool target); + } #endif diff --git a/SerialPrograms/Source/Tests/TestMap.cpp b/SerialPrograms/Source/Tests/TestMap.cpp index 07cf488e4..220fc4b09 100644 --- a/SerialPrograms/Source/Tests/TestMap.cpp +++ b/SerialPrograms/Source/Tests/TestMap.cpp @@ -310,6 +310,7 @@ const std::map TEST_MAP = { {"PokemonLZA_FlavorPowerScreenDetector", test_pokemonLZA_FlavorPowerScreenDetector}, {"PokemonLZA_DonutBerriesReader", test_pokemonLZA_DonutBerriesReader}, {"PokemonFRLG_AdvanceWhiteDialogDetector", std::bind(image_bool_detector_helper, test_pokemonFRLG_AdvanceWhiteDialogDetector, _1)}, + {"PokemonFRLG_ShinySymbolDetector", std::bind(image_bool_detector_helper, test_pokemonFRLG_ShinySymbolDetector, _1)}, }; TestFunction find_test_function(const std::string& test_space, const std::string& test_name){ From 3c57ec83de60edba1cdd5f8fca067f8fcc5b9a80 Mon Sep 17 00:00:00 2001 From: kichithewolf Date: Tue, 3 Mar 2026 18:45:58 -0500 Subject: [PATCH 6/8] black border check --- .../Source/PokemonFRLG/PokemonFRLG_Navigation.cpp | 14 ++++++++++++++ .../Source/PokemonFRLG/PokemonFRLG_Navigation.h | 3 +++ .../ShinyHunting/PokemonFRLG_GiftReset.cpp | 2 ++ .../ShinyHunting/PokemonFRLG_LegendaryReset.cpp | 2 ++ .../ShinyHunting/PokemonFRLG_LegendaryRunAway.cpp | 2 ++ .../ShinyHunting/PokemonFRLG_PrizeCornerReset.cpp | 2 ++ 6 files changed, 25 insertions(+) diff --git a/SerialPrograms/Source/PokemonFRLG/PokemonFRLG_Navigation.cpp b/SerialPrograms/Source/PokemonFRLG/PokemonFRLG_Navigation.cpp index 867c0a5ae..59ebf9483 100644 --- a/SerialPrograms/Source/PokemonFRLG/PokemonFRLG_Navigation.cpp +++ b/SerialPrograms/Source/PokemonFRLG/PokemonFRLG_Navigation.cpp @@ -10,6 +10,8 @@ #include "CommonTools/Random.h" #include "CommonTools/Async/InferenceRoutines.h" #include "CommonTools/VisualDetectors/BlackScreenDetector.h" +#include "CommonTools/StartupChecks/StartProgramChecks.h" +#include "NintendoSwitch/Programs/NintendoSwitch_GameEntry.h" #include "NintendoSwitch/Commands/NintendoSwitch_Commands_PushButtons.h" #include "NintendoSwitch/Controllers/Procon/NintendoSwitch_ProController.h" #include "NintendoSwitch/NintendoSwitch_ConsoleHandle.h" @@ -333,6 +335,18 @@ void flee_battle(ConsoleHandle& console, ProControllerContext& context){ } } +void home_black_border_check(ConsoleHandle& console, ProControllerContext& context){ + console.log("Going to home to check for black border."); + go_home(console, context); + ensure_at_home(console, context); + context.wait_for_all_requests(); + StartProgramChecks::check_border(console); + console.log("Returning to game."); + resume_game_from_home(console, context); + context.wait_for_all_requests(); + console.log("Entered game."); +} + } } diff --git a/SerialPrograms/Source/PokemonFRLG/PokemonFRLG_Navigation.h b/SerialPrograms/Source/PokemonFRLG/PokemonFRLG_Navigation.h index 8647d2b9b..783ecfcd7 100644 --- a/SerialPrograms/Source/PokemonFRLG/PokemonFRLG_Navigation.h +++ b/SerialPrograms/Source/PokemonFRLG/PokemonFRLG_Navigation.h @@ -36,6 +36,9 @@ bool handle_encounter(ConsoleHandle& console, ProControllerContext& context, boo // Run from battle. Cursor must start on the FIGHT button. Assumes fleeing will always work. (Smoke Ball) void flee_battle(ConsoleHandle& console, ProControllerContext& context); +// Go to home to check that scaling is 100%. Then resume game. +void home_black_border_check(ConsoleHandle& console, ProControllerContext& context); + } } } diff --git a/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_GiftReset.cpp b/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_GiftReset.cpp index 361653d7e..fd1dd0cc5 100644 --- a/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_GiftReset.cpp +++ b/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_GiftReset.cpp @@ -335,6 +335,8 @@ void GiftReset::program(SingleSwitchProgramEnvironment& env, ProControllerContex GiftReset_Descriptor::Stats& stats = env.current_stats(); + home_black_border_check(env.console, context); + /* * Settings: Text Speed fast. Default borders. * Setup: 5 pokemon in your party. None for starter. Stand in front of the pokemon. Save the game. diff --git a/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_LegendaryReset.cpp b/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_LegendaryReset.cpp index 22ffef956..9a1777dae 100644 --- a/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_LegendaryReset.cpp +++ b/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_LegendaryReset.cpp @@ -80,6 +80,8 @@ LegendaryReset::LegendaryReset() void LegendaryReset::program(SingleSwitchProgramEnvironment& env, ProControllerContext& context){ LegendaryReset_Descriptor::Stats& stats = env.current_stats(); + home_black_border_check(env.console, context); + /* * Settings: Text Speed fast. Default borders. Audio required. * Setup: Stand in front of target. Save the game. diff --git a/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_LegendaryRunAway.cpp b/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_LegendaryRunAway.cpp index 232678a62..b172280ea 100644 --- a/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_LegendaryRunAway.cpp +++ b/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_LegendaryRunAway.cpp @@ -243,6 +243,8 @@ void LegendaryRunAway::reset_lugia(SingleSwitchProgramEnvironment& env, ProContr void LegendaryRunAway::program(SingleSwitchProgramEnvironment& env, ProControllerContext& context){ LegendaryRunAway_Descriptor::Stats& stats = env.current_stats(); + home_black_border_check(env.console, context); + /* * Settings: Text Speed fast. Default borders. Battle animations off. Audio required. * Smoke Ball or fast pokemon required. diff --git a/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_PrizeCornerReset.cpp b/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_PrizeCornerReset.cpp index 9a4d1fd0b..182d6caf2 100644 --- a/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_PrizeCornerReset.cpp +++ b/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_PrizeCornerReset.cpp @@ -136,6 +136,8 @@ void PrizeCornerReset::obtain_prize(SingleSwitchProgramEnvironment& env, ProCont void PrizeCornerReset::program(SingleSwitchProgramEnvironment& env, ProControllerContext& context){ PrizeCornerReset_Descriptor::Stats& stats = env.current_stats(); + home_black_border_check(env.console, context); + /* * Settings: Text Speed fast. Default borders. * Setup: Have a party of 5. Stand in front of the prize redemption. Save game. Move cursor back to top. From 99baf6549d779e670ee40b9878f6cb8f6d4e8a1d Mon Sep 17 00:00:00 2001 From: kichithewolf Date: Tue, 3 Mar 2026 19:56:22 -0500 Subject: [PATCH 7/8] fix white dialog detection --- .../Dialogs/PokemonFRLG_DialogDetector.cpp | 20 +++++++++---------- .../Source/Tests/PokemonFRLG_Tests.cpp | 8 ++++++++ .../Source/Tests/PokemonFRLG_Tests.h | 2 ++ SerialPrograms/Source/Tests/TestMap.cpp | 1 + 4 files changed, 21 insertions(+), 10 deletions(-) diff --git a/SerialPrograms/Source/PokemonFRLG/Inference/Dialogs/PokemonFRLG_DialogDetector.cpp b/SerialPrograms/Source/PokemonFRLG/Inference/Dialogs/PokemonFRLG_DialogDetector.cpp index 54321d557..9b284b201 100644 --- a/SerialPrograms/Source/PokemonFRLG/Inference/Dialogs/PokemonFRLG_DialogDetector.cpp +++ b/SerialPrograms/Source/PokemonFRLG/Inference/Dialogs/PokemonFRLG_DialogDetector.cpp @@ -39,9 +39,9 @@ bool WhiteDialogDetector::detect(const ImageViewRGB32& screen){ ImageViewRGB32 right_image = extract_box_reference(screen, m_right_box); ImageViewRGB32 top_image = extract_box_reference(screen, m_top_box); ImageViewRGB32 bottom_image = extract_box_reference(screen, m_bottom_box); - if (is_solid(right_image, { 0.333333, 0.333333, 0.333333 }) - && is_solid(top_image, { 0.333333, 0.333333, 0.333333 }) - && is_solid(bottom_image, { 0.333333, 0.333333, 0.333333 }) + if (is_white(right_image) + && is_white(top_image) + && is_white(bottom_image) ){ return true; } @@ -81,9 +81,9 @@ bool AdvanceWhiteDialogDetector::detect(const ImageViewRGB32& screen){ ImageViewRGB32 top_image = extract_box_reference(screen, m_top_box); ImageViewRGB32 bottom_image = extract_box_reference(screen, m_bottom_box); - if (is_solid(right_image, { 0.333333, 0.333333, 0.333333 }) - && is_solid(top_image, { 0.333333, 0.333333, 0.333333 }) - && is_solid(bottom_image, { 0.333333, 0.333333, 0.333333 }) + if (is_white(right_image) + && is_white(top_image) + && is_white(bottom_image) && (stats.average.r > stats.average.b + 180) && (stats.average.r > stats.average.g + 180) ) @@ -110,10 +110,10 @@ bool SelectionDialogDetector::detect(const ImageViewRGB32& screen){ ImageViewRGB32 top_image = extract_box_reference(screen, m_top_box); ImageViewRGB32 bottom_image = extract_box_reference(screen, m_bottom_box); ImageViewRGB32 selection_image = extract_box_reference(screen, m_selection_box); - if (is_solid(right_image, { 0.333333, 0.333333, 0.333333 }) - && is_solid(top_image, { 0.333333, 0.333333, 0.333333 }) - && is_solid(bottom_image, { 0.333333, 0.333333, 0.333333 }) - && is_solid(selection_image, { 0.333333, 0.333333, 0.333333 }) + if (is_white(right_image) + && is_white(top_image) + && is_white(bottom_image) + && is_white(selection_image) ){ return true; } diff --git a/SerialPrograms/Source/Tests/PokemonFRLG_Tests.cpp b/SerialPrograms/Source/Tests/PokemonFRLG_Tests.cpp index e80e12a64..c1a2469d4 100644 --- a/SerialPrograms/Source/Tests/PokemonFRLG_Tests.cpp +++ b/SerialPrograms/Source/Tests/PokemonFRLG_Tests.cpp @@ -43,4 +43,12 @@ int test_pokemonFRLG_ShinySymbolDetector(const ImageViewRGB32& image, bool targe return 0; } +int test_pokemonFRLG_SelectionDialogDetector(const ImageViewRGB32& image, bool target){ + auto overlay = DummyVideoOverlay(); + SelectionDialogDetector detector(COLOR_RED); + bool result = detector.detect(image); + TEST_RESULT_EQUAL(result, target); + return 0; +} + } diff --git a/SerialPrograms/Source/Tests/PokemonFRLG_Tests.h b/SerialPrograms/Source/Tests/PokemonFRLG_Tests.h index 7d49c9d99..a023c5961 100644 --- a/SerialPrograms/Source/Tests/PokemonFRLG_Tests.h +++ b/SerialPrograms/Source/Tests/PokemonFRLG_Tests.h @@ -21,6 +21,8 @@ int test_pokemonFRLG_AdvanceWhiteDialogDetector(const ImageViewRGB32& image, boo int test_pokemonFRLG_ShinySymbolDetector(const ImageViewRGB32& image, bool target); +int test_pokemonFRLG_SelectionDialogDetector(const ImageViewRGB32& image, bool target); + } #endif diff --git a/SerialPrograms/Source/Tests/TestMap.cpp b/SerialPrograms/Source/Tests/TestMap.cpp index 220fc4b09..add3aab95 100644 --- a/SerialPrograms/Source/Tests/TestMap.cpp +++ b/SerialPrograms/Source/Tests/TestMap.cpp @@ -311,6 +311,7 @@ const std::map TEST_MAP = { {"PokemonLZA_DonutBerriesReader", test_pokemonLZA_DonutBerriesReader}, {"PokemonFRLG_AdvanceWhiteDialogDetector", std::bind(image_bool_detector_helper, test_pokemonFRLG_AdvanceWhiteDialogDetector, _1)}, {"PokemonFRLG_ShinySymbolDetector", std::bind(image_bool_detector_helper, test_pokemonFRLG_ShinySymbolDetector, _1)}, + {"PokemonFRLG_SelectionDialogDetector", std::bind(image_bool_detector_helper, test_pokemonFRLG_SelectionDialogDetector, _1)}, }; TestFunction find_test_function(const std::string& test_space, const std::string& test_name){ From 4c0c80e95e632ff69505cb9a3d28f723fa8ce8d8 Mon Sep 17 00:00:00 2001 From: kichithewolf Date: Wed, 4 Mar 2026 20:42:30 -0500 Subject: [PATCH 8/8] tick precise not required, take video, audio warn --- .../ShinyHunting/PokemonFRLG_GiftReset.cpp | 7 ++++++- .../ShinyHunting/PokemonFRLG_GiftReset.h | 3 +++ .../ShinyHunting/PokemonFRLG_LegendaryReset.cpp | 8 +++++++- .../ShinyHunting/PokemonFRLG_LegendaryReset.h | 5 +++++ .../PokemonFRLG_LegendaryRunAway.cpp | 17 +++++++++++++++-- .../ShinyHunting/PokemonFRLG_LegendaryRunAway.h | 5 +++++ .../PokemonFRLG_PrizeCornerReset.cpp | 7 ++++++- .../ShinyHunting/PokemonFRLG_PrizeCornerReset.h | 3 +++ 8 files changed, 50 insertions(+), 5 deletions(-) diff --git a/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_GiftReset.cpp b/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_GiftReset.cpp index fd1dd0cc5..9e0606c7d 100644 --- a/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_GiftReset.cpp +++ b/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_GiftReset.cpp @@ -30,7 +30,7 @@ GiftReset_Descriptor::GiftReset_Descriptor() Pokemon::STRING_POKEMON + " FRLG", "Gift Reset", "Programs/PokemonFRLG/GiftReset.html", "Soft reset for a shiny gift Pokemon.", - ProgramControllerClass::StandardController_RequiresPrecision, + ProgramControllerClass::StandardController_NoRestrictions, FeedbackType::REQUIRED, AllowCommandsWhenRunning::DISABLE_COMMANDS ) @@ -67,6 +67,7 @@ GiftReset::GiftReset() LockMode::LOCK_WHILE_RUNNING, Target::starters ) + , TAKE_VIDEO("Take Video:
Record a video when the shiny is found.", LockMode::UNLOCK_WHILE_RUNNING, true) , GO_HOME_WHEN_DONE(true) , NOTIFICATION_SHINY( "Shiny found", @@ -81,6 +82,7 @@ GiftReset::GiftReset() }) { PA_ADD_OPTION(TARGET); + PA_ADD_OPTION(TAKE_VIDEO); PA_ADD_OPTION(GO_HOME_WHEN_DONE); PA_ADD_OPTION(NOTIFICATIONS); } @@ -373,6 +375,9 @@ void GiftReset::program(SingleSwitchProgramEnvironment& env, ProControllerContex screen, true ); + if (TAKE_VIDEO){ + pbf_press_button(context, BUTTON_CAPTURE, 2000ms, 0ms); + } break; }else{ env.log("Pokemon is not shiny."); diff --git a/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_GiftReset.h b/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_GiftReset.h index 2da5fa7f2..e1a5e3c56 100644 --- a/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_GiftReset.h +++ b/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_GiftReset.h @@ -7,6 +7,7 @@ #ifndef PokemonAutomation_PokemonFRLG_GiftReset_H #define PokemonAutomation_PokemonFRLG_GiftReset_H +#include "Common/Cpp/Options/BooleanCheckBoxOption.h" #include "CommonFramework/Notifications/EventNotificationsTable.h" #include "NintendoSwitch/NintendoSwitch_SingleSwitchProgram.h" #include "NintendoSwitch/Options/NintendoSwitch_GoHomeWhenDoneOption.h" @@ -47,6 +48,8 @@ class GiftReset : public SingleSwitchProgramInstance{ }; EnumDropdownOption TARGET; + BooleanCheckBoxOption TAKE_VIDEO; + GoHomeWhenDoneOption GO_HOME_WHEN_DONE; EventNotificationOption NOTIFICATION_SHINY; diff --git a/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_LegendaryReset.cpp b/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_LegendaryReset.cpp index 9a1777dae..f447d0d00 100644 --- a/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_LegendaryReset.cpp +++ b/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_LegendaryReset.cpp @@ -29,7 +29,7 @@ LegendaryReset_Descriptor::LegendaryReset_Descriptor() Pokemon::STRING_POKEMON + " FRLG", "Legendary Reset", "Programs/PokemonFRLG/LegendaryReset.html", "Shiny hunt legendary Pokemon using soft resets.", - ProgramControllerClass::StandardController_RequiresPrecision, + ProgramControllerClass::StandardController_NoRestrictions, FeedbackType::REQUIRED, AllowCommandsWhenRunning::DISABLE_COMMANDS ) @@ -59,6 +59,7 @@ LegendaryReset::LegendaryReset() LockMode::LOCK_WHILE_RUNNING, false ) + , TAKE_VIDEO("Take Video:
Record a video when the shiny is found.", LockMode::UNLOCK_WHILE_RUNNING, true) , GO_HOME_WHEN_DONE(true) , NOTIFICATION_SHINY( "Shiny found", @@ -72,7 +73,9 @@ LegendaryReset::LegendaryReset() &NOTIFICATION_PROGRAM_FINISH, }) { + PA_ADD_STATIC(SHINY_REQUIRES_AUDIO); PA_ADD_OPTION(WALK_UP); + PA_ADD_OPTION(TAKE_VIDEO); PA_ADD_OPTION(GO_HOME_WHEN_DONE); PA_ADD_OPTION(NOTIFICATIONS); } @@ -140,6 +143,9 @@ void LegendaryReset::program(SingleSwitchProgramEnvironment& env, ProControllerC env.console.video().snapshot(), true ); + if (TAKE_VIDEO){ + pbf_press_button(context, BUTTON_CAPTURE, 2000ms, 0ms); + } break; } diff --git a/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_LegendaryReset.h b/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_LegendaryReset.h index 624f6c822..a3aa9d641 100644 --- a/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_LegendaryReset.h +++ b/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_LegendaryReset.h @@ -12,6 +12,8 @@ #include "NintendoSwitch/Options/NintendoSwitch_GoHomeWhenDoneOption.h" #include "Common/Cpp/Options/EnumDropdownOption.h" #include "Common/Cpp/Options/SimpleIntegerOption.h" +#include "Common/Cpp/Options/BooleanCheckBoxOption.h" +#include "PokemonLA/Options/PokemonLA_ShinyDetectedAction.h" namespace PokemonAutomation{ namespace NintendoSwitch{ @@ -35,7 +37,10 @@ class LegendaryReset : public SingleSwitchProgramInstance{ ) override{} private: + PokemonLA::ShinyRequiresAudioText SHINY_REQUIRES_AUDIO; + BooleanCheckBoxOption WALK_UP; + BooleanCheckBoxOption TAKE_VIDEO; GoHomeWhenDoneOption GO_HOME_WHEN_DONE; diff --git a/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_LegendaryRunAway.cpp b/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_LegendaryRunAway.cpp index b172280ea..e5b58d3a1 100644 --- a/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_LegendaryRunAway.cpp +++ b/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_LegendaryRunAway.cpp @@ -30,7 +30,7 @@ LegendaryRunAway_Descriptor::LegendaryRunAway_Descriptor() Pokemon::STRING_POKEMON + " FRLG", "Legendary Run Away", "Programs/PokemonFRLG/LegendaryRunAway.html", "Shiny hunt legendary Pokemon using the run away method.", - ProgramControllerClass::StandardController_RequiresPrecision, + ProgramControllerClass::StandardController_NoRestrictions, FeedbackType::REQUIRED, AllowCommandsWhenRunning::DISABLE_COMMANDS ) @@ -64,6 +64,7 @@ LegendaryRunAway::LegendaryRunAway() LockMode::LOCK_WHILE_RUNNING, Target::hooh ) + , TAKE_VIDEO("Take Video:
Record a video when the shiny is found.", LockMode::UNLOCK_WHILE_RUNNING, true) , GO_HOME_WHEN_DONE(true) , NOTIFICATION_SHINY( "Shiny found", @@ -100,7 +101,9 @@ LegendaryRunAway::LegendaryRunAway() "550 ms" ) { + PA_ADD_STATIC(SHINY_REQUIRES_AUDIO); PA_ADD_OPTION(TARGET); + PA_ADD_OPTION(TAKE_VIDEO); PA_ADD_OPTION(GO_HOME_WHEN_DONE); PA_ADD_OPTION(NOTIFICATIONS); PA_ADD_STATIC(m_advanced_options); @@ -266,7 +269,17 @@ void LegendaryRunAway::program(SingleSwitchProgramEnvironment& env, ProControlle if (legendary_shiny){ stats.shinies++; env.update_stats(); - send_program_notification(env, NOTIFICATION_SHINY, COLOR_YELLOW, "Shiny found!", {}, "", env.console.video().snapshot(), true); + send_program_notification(env, + NOTIFICATION_SHINY, + COLOR_YELLOW, + "Shiny found!", + {}, "", + env.console.video().snapshot(), + true + ); + if (TAKE_VIDEO){ + pbf_press_button(context, BUTTON_CAPTURE, 2000ms, 0ms); + } break; } env.log("No shiny found."); diff --git a/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_LegendaryRunAway.h b/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_LegendaryRunAway.h index 5f54b6266..ebd3a4f07 100644 --- a/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_LegendaryRunAway.h +++ b/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_LegendaryRunAway.h @@ -14,6 +14,8 @@ #include "Common/Cpp/Options/EnumDropdownOption.h" #include "Common/Cpp/Options/SimpleIntegerOption.h" #include "Common/Cpp/Options/TimeDurationOption.h" +#include "Common/Cpp/Options/BooleanCheckBoxOption.h" +#include "PokemonLA/Options/PokemonLA_ShinyDetectedAction.h" namespace PokemonAutomation{ namespace NintendoSwitch{ @@ -46,6 +48,9 @@ class LegendaryRunAway : public SingleSwitchProgramInstance{ void reset_hooh(SingleSwitchProgramEnvironment& env, ProControllerContext& context); void reset_lugia(SingleSwitchProgramEnvironment& env, ProControllerContext& context); + PokemonLA::ShinyRequiresAudioText SHINY_REQUIRES_AUDIO; + BooleanCheckBoxOption TAKE_VIDEO; + GoHomeWhenDoneOption GO_HOME_WHEN_DONE; EventNotificationOption NOTIFICATION_SHINY; diff --git a/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_PrizeCornerReset.cpp b/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_PrizeCornerReset.cpp index 182d6caf2..3d5bee819 100644 --- a/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_PrizeCornerReset.cpp +++ b/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_PrizeCornerReset.cpp @@ -31,7 +31,7 @@ PrizeCornerReset_Descriptor::PrizeCornerReset_Descriptor() Pokemon::STRING_POKEMON + " FRLG", "Prize Corner Reset", "Programs/PokemonFRLG/PrizeCornerReset.html", "Redeem and soft reset for a shiny Game Corner prize.", - ProgramControllerClass::StandardController_RequiresPrecision, + ProgramControllerClass::StandardController_NoRestrictions, FeedbackType::REQUIRED, AllowCommandsWhenRunning::DISABLE_COMMANDS ) @@ -68,6 +68,7 @@ PrizeCornerReset::PrizeCornerReset() LockMode::LOCK_WHILE_RUNNING, 0 ) + , TAKE_VIDEO("Take Video:
Record a video when the shiny is found.", LockMode::UNLOCK_WHILE_RUNNING, true) , GO_HOME_WHEN_DONE(true) , NOTIFICATION_SHINY( "Shiny found", @@ -82,6 +83,7 @@ PrizeCornerReset::PrizeCornerReset() }) { PA_ADD_OPTION(SLOT); + PA_ADD_OPTION(TAKE_VIDEO); PA_ADD_OPTION(GO_HOME_WHEN_DONE); PA_ADD_OPTION(NOTIFICATIONS); } @@ -167,6 +169,9 @@ void PrizeCornerReset::program(SingleSwitchProgramEnvironment& env, ProControlle screen, true ); + if (TAKE_VIDEO){ + pbf_press_button(context, BUTTON_CAPTURE, 2000ms, 0ms); + } break; }else{ env.log("Prize is not shiny."); diff --git a/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_PrizeCornerReset.h b/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_PrizeCornerReset.h index 1fc518c5e..e19024115 100644 --- a/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_PrizeCornerReset.h +++ b/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_PrizeCornerReset.h @@ -12,6 +12,7 @@ #include "NintendoSwitch/Options/NintendoSwitch_GoHomeWhenDoneOption.h" #include "Common/Cpp/Options/EnumDropdownOption.h" #include "Common/Cpp/Options/SimpleIntegerOption.h" +#include "Common/Cpp/Options/BooleanCheckBoxOption.h" namespace PokemonAutomation{ namespace NintendoSwitch{ @@ -39,6 +40,8 @@ class PrizeCornerReset : public SingleSwitchProgramInstance{ IntegerEnumDropdownOption SLOT; + BooleanCheckBoxOption TAKE_VIDEO; + GoHomeWhenDoneOption GO_HOME_WHEN_DONE; EventNotificationOption NOTIFICATION_SHINY;