1212#include " CommonFramework/Notifications/ProgramNotifications.h"
1313#include " CommonFramework/Tools/StatsTracking.h"
1414#include " CommonFramework/ImageTools/SolidColorTest.h"
15+ #include " CommonFramework/ImageTools/ImageBoxes.h"
16+ #include " CommonFramework/ImageTools/ImageFilter.h"
17+ #include " CommonFramework/OCR/OCR_NumberReader.h"
1518#include " NintendoSwitch/Commands/NintendoSwitch_Commands_PushButtons.h"
1619#include " NintendoSwitch/Commands/NintendoSwitch_Commands_Superscalar.h"
20+ #include " NintendoSwitch/Programs/NintendoSwitch_GameEntry.h"
1721#include " NintendoSwitch/Programs/NintendoSwitch_SnapshotDumper.h"
1822#include " PokemonSwSh/Inference/PokemonSwSh_IvJudgeReader.h"
1923#include " PokemonSV/Inference/Battles/PokemonSV_NormalBattleMenus.h"
2024#include " PokemonSV/Inference/Dialogs/PokemonSV_DialogDetector.h"
2125#include " PokemonSV/Inference/Overworld/PokemonSV_OverworldDetector.h"
22- // #include "PokemonSV/Inference/Overworld/PokemonSV_StationaryOverworldWatcher.h"
26+ #include " PokemonSV/Inference/Overworld/PokemonSV_StationaryOverworldWatcher.h"
2327#include " PokemonSV/Inference/PokemonSV_MainMenuDetector.h"
2428#include " PokemonSV/Inference/Map/PokemonSV_MapMenuDetector.h"
29+ #include " PokemonSV/PokemonSV_Settings.h"
2530#include " PokemonSV/Programs/PokemonSV_Navigation.h"
2631#include " PokemonSV/Programs/PokemonSV_GameEntry.h"
2732#include " PokemonSV/Programs/PokemonSV_SaveGame.h"
@@ -380,7 +385,7 @@ bool confirm_marker_present(
380385
381386 int ret = wait_until (
382387 console, context,
383- std::chrono::seconds (10 ),
388+ std::chrono::seconds (5 ),
384389 {marker, battle}
385390 );
386391 switch (ret){
@@ -454,9 +459,11 @@ void overworld_navigation(
454459 }
455460 }
456461 }
462+ context.wait_for_all_requests ();
457463 if (should_realign){
458464 try {
459465 realign_player (info, console, context, PlayerRealignMode::REALIGN_OLD_MARKER);
466+
460467 }catch (UnexpectedBattleException&){
461468 pbf_wait (context, 30 * TICKS_PER_SECOND); // catch exception to allow the battle callback to take over.
462469 }
@@ -479,10 +486,9 @@ void overworld_navigation(
479486 if (auto_heal){
480487 auto_heal_from_menu_or_overworld (info, console, context, 0 , true );
481488 }
482-
489+ context. wait_for_all_requests ();
483490 try {
484491 realign_player (info, console, context, PlayerRealignMode::REALIGN_OLD_MARKER);
485-
486492 if (!confirm_marker_present (info, console, context)){
487493 // if marker not present, don't keep walking forward.
488494 return ;
@@ -682,7 +688,7 @@ void do_action_and_monitor_for_battles(
682688 {battle_menu}
683689 );
684690 if (ret == 0 ){ // battle detected
685- throw OperationFailedException (
691+ throw UnexpectedBattleException (
686692 ErrorReport::SEND_ERROR_REPORT, console,
687693 " do_action_and_monitor_for_battles(): Detected battle. Failed to complete action." ,
688694 true
@@ -713,52 +719,65 @@ void handle_unexpected_battles(
713719 }
714720}
715721
716- // void handle_when_stationary_in_overworld(
717- // const ProgramInfo& info,
718- // ConsoleHandle& console,
719- // BotBaseContext& context,
720- // std::function<
721- // void(const ProgramInfo& info,
722- // ConsoleHandle& console,
723- // BotBaseContext& context)
724- // >&& action,
725- // std::function<
726- // void(const ProgramInfo& info,
727- // ConsoleHandle& console,
728- // BotBaseContext& context)
729- // >&& recovery_action,
730- // size_t seconds_stationary,
731- // uint16_t minutes_timeout
732- // ){
733- // StationaryOverworldWatcher stationary_overworld(COLOR_RED, {0.865, 0.82, 0.08, 0.1}, seconds_stationary);
734- // WallClock start = current_time();
735- // while (true){
736- // if (current_time() - start > std::chrono::minutes(minutes_timeout)){
737- // throw OperationFailedException(
738- // ErrorReport::SEND_ERROR_REPORT, console,
739- // "handle_when_stationary_in_overworld(): Failed to complete action after 5 minutes.",
740- // true
741- // );
742- // }
743-
744- // int ret = run_until(
745- // console, context,
746- // [&](BotBaseContext& context){
747- // context.wait_for_all_requests();
748- // action(info, console, context);
749- // },
750- // {stationary_overworld}
751- // );
752- // if (ret < 0){
753- // // successfully completed action without being stuck in a position where the overworld is stationary.
754- // return;
755- // }else if (ret == 0){
756- // // if stationary in overworld, run recovery action then try action again
757- // context.wait_for_all_requests();
758- // recovery_action(info, console, context);
759- // }
760- // }
761- // }
722+ void handle_when_stationary_in_overworld (
723+ const ProgramInfo& info,
724+ ConsoleHandle& console,
725+ BotBaseContext& context,
726+ std::function<
727+ void (const ProgramInfo& info,
728+ ConsoleHandle& console,
729+ BotBaseContext& context)
730+ >&& action,
731+ std::function<
732+ void(const ProgramInfo& info,
733+ ConsoleHandle& console,
734+ BotBaseContext& context)
735+ >&& recovery_action,
736+ size_t seconds_stationary,
737+ uint16_t minutes_timeout,
738+ size_t max_failures
739+ ){
740+
741+ WallClock start = current_time ();
742+ size_t num_failures = 0 ;
743+ while (true ){
744+ if (current_time () - start > std::chrono::minutes (minutes_timeout)){
745+ throw OperationFailedException (
746+ ErrorReport::SEND_ERROR_REPORT, console,
747+ " handle_when_stationary_in_overworld(): Failed to complete action after " + std::to_string (minutes_timeout) + " minutes." ,
748+ true
749+ );
750+ }
751+ StationaryOverworldWatcher stationary_overworld (COLOR_RED, {0.865 , 0.825 , 0.08 , 0.1 }, seconds_stationary);
752+
753+ int ret = run_until (
754+ console, context,
755+ [&](BotBaseContext& context){
756+ context.wait_for_all_requests ();
757+ action (info, console, context);
758+ },
759+ {stationary_overworld}
760+ );
761+ if (ret < 0 ){
762+ // successfully completed action without being stuck in a position where the overworld is stationary.
763+ return ;
764+ }else if (ret == 0 ){
765+ // if stationary in overworld, run recovery action then try action again
766+ console.log (" Detected stationary overworld." );
767+ num_failures++;
768+ if (num_failures > max_failures){
769+ throw OperationFailedException (
770+ ErrorReport::SEND_ERROR_REPORT, console,
771+ " handle_when_stationary_in_overworld(): Failed to complete action within " + std::to_string (max_failures) + " attempts." ,
772+ true
773+ );
774+ }
775+ context.wait_for_all_requests ();
776+ recovery_action (info, console, context);
777+ }
778+ }
779+ }
780+
762781
763782void wait_for_gradient_arrow (
764783 const ProgramInfo& info,
@@ -860,6 +879,8 @@ bool check_ride_active(const ProgramInfo& info, ConsoleHandle& console, BotBaseC
860879}
861880
862881void get_on_ride (const ProgramInfo& info, ConsoleHandle& console, BotBaseContext& context){
882+ pbf_press_button (context, BUTTON_PLUS, 20 , 20 );
883+
863884 WallClock start = current_time ();
864885 while (!check_ride_active (info, console, context)){
865886 if (current_time () - start > std::chrono::minutes (3 )){
@@ -1065,6 +1086,28 @@ void move_cursor_towards_flypoint_and_go_there(
10651086}
10661087
10671088
1089+
1090+ void check_num_sunflora_found (SingleSwitchProgramEnvironment& env, BotBaseContext& context, int expected_number){
1091+ context.wait_for_all_requests ();
1092+ VideoSnapshot screen = env.console .video ().snapshot ();
1093+ ImageFloatBox num_sunflora_box = {0.27 , 0.02 , 0.04 , 0.055 };
1094+ int number = OCR::read_number_waterfill (env.console , extract_box_reference (screen, num_sunflora_box), 0xff000000 , 0xff808080 );
1095+
1096+ if (number != expected_number){
1097+ throw OperationFailedException (
1098+ ErrorReport::SEND_ERROR_REPORT,
1099+ env.logger (),
1100+ " The number of sunflora found is different than expected."
1101+ );
1102+ }else {
1103+ env.console .log (" Number of sunflora found: " + std::to_string (number));
1104+ }
1105+
1106+
1107+ }
1108+
1109+
1110+
10681111}
10691112}
10701113}
0 commit comments