Skip to content

Commit 7c27a02

Browse files
authored
Segment 11 (Olive roll) and update AutoStoryTools (#510)
* Segment 11 (Olive roll) and update AutoStoryTools * move change_date() to NintendoSwitch_DateReader.h
1 parent e5cf988 commit 7c27a02

File tree

8 files changed

+855
-54
lines changed

8 files changed

+855
-54
lines changed

SerialPrograms/CMakeLists.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1459,7 +1459,9 @@ file(GLOB MAIN_SOURCES
14591459
Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_09.cpp
14601460
Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_09.h
14611461
Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_10.cpp
1462-
Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_10.h
1462+
Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_10.h
1463+
Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_11.cpp
1464+
Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_11.h
14631465
Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory.cpp
14641466
Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory.h
14651467
Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStoryTools.cpp

SerialPrograms/SerialPrograms.pro

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -729,6 +729,7 @@ SOURCES += \
729729
Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_08.cpp \
730730
Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_09.cpp \
731731
Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_10.cpp \
732+
Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_11.cpp \
732733
Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory.cpp \
733734
Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStoryTools.cpp \
734735
Source/PokemonSV/Programs/AutoStory/PokemonSV_MenuOption.cpp \
@@ -1832,6 +1833,7 @@ HEADERS += \
18321833
Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_08.h \
18331834
Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_09.h \
18341835
Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_10.h \
1836+
Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_11.h \
18351837
Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory.h \
18361838
Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStoryTools.h \
18371839
Source/PokemonSV/Programs/AutoStory/PokemonSV_MenuOption.h \

SerialPrograms/Source/NintendoSwitch/Inference/NintendoSwitch_DateReader.cpp

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "Common/Qt/StringToolsQt.h"
99
#include "CommonFramework/Exceptions/OperationFailedException.h"
1010
#include "CommonFramework/Exceptions/FatalProgramException.h"
11+
#include "CommonFramework/InferenceInfra/InferenceRoutines.h"
1112
#include "CommonFramework/ImageTypes/ImageRGB32.h"
1213
#include "CommonFramework/ImageTools/ImageStats.h"
1314
#include "CommonFramework/ImageTools/ImageFilter.h"
@@ -18,6 +19,9 @@
1819
#include "CommonFramework/OCR/OCR_RawOCR.h"
1920
#include "CommonFramework/OCR/OCR_NumberReader.h"
2021
#include "CommonFramework/OCR/OCR_StringNormalization.h"
22+
#include "PokemonSwSh/Commands/PokemonSwSh_Commands_DateSpam.h"
23+
#include "NintendoSwitch/NintendoSwitch_Settings.h"
24+
#include "NintendoSwitch/Inference/NintendoSwitch_DetectHome.h"
2125
#include "NintendoSwitch/Commands/NintendoSwitch_Commands_PushButtons.h"
2226
#include "NintendoSwitch/Commands/NintendoSwitch_Commands_Superscalar.h"
2327
#include "NintendoSwitch_DateReader.h"
@@ -568,6 +572,54 @@ void DateReader::set_date(
568572
);
569573
}
570574

575+
void change_date(
576+
SingleSwitchProgramEnvironment& env, BotBaseContext& context,
577+
const DateTime& date
578+
){
579+
while (true){
580+
context.wait_for_all_requests();
581+
582+
HomeWatcher home;
583+
DateChangeWatcher date_reader;
584+
int ret = wait_until(
585+
env.console, context, std::chrono::seconds(120),
586+
{
587+
home,
588+
date_reader
589+
}
590+
);
591+
switch (ret){
592+
case 0:
593+
home_to_date_time(context, true, false);
594+
pbf_press_button(context, BUTTON_A, 10, 30);
595+
context.wait_for_all_requests();
596+
continue;
597+
case 1:{
598+
env.log("Detected date change.");
599+
600+
// Set the date
601+
VideoOverlaySet overlays(env.console.overlay());
602+
date_reader.make_overlays(overlays);
603+
date_reader.set_date(env.program_info(), env.console, context, date);
604+
605+
// Commit the date.
606+
pbf_press_button(context, BUTTON_A, 20, 30);
607+
608+
// Re-enter the game.
609+
pbf_press_button(context, BUTTON_HOME, 20, ConsoleSettings::instance().SETTINGS_TO_HOME_DELAY);
610+
611+
return;
612+
}
613+
default:
614+
throw OperationFailedException(
615+
ErrorReport::SEND_ERROR_REPORT,
616+
env.logger(),
617+
"Failed to set date"
618+
);
619+
}
620+
}
621+
}
622+
571623

572624

573625

SerialPrograms/Source/NintendoSwitch/Inference/NintendoSwitch_DateReader.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "CommonFramework/ImageTools/ImageBoxes.h"
1212
#include "CommonFramework/InferenceInfra/VisualInferenceCallback.h"
1313
#include "CommonFramework/Inference/VisualDetector.h"
14+
#include "NintendoSwitch/NintendoSwitch_SingleSwitchProgram.h"
1415

1516
namespace PokemonAutomation{
1617
struct ProgramInfo;
@@ -101,6 +102,14 @@ class DateChangeWatcher : public DetectorToFinder<DateReader>{
101102
{}
102103
};
103104

105+
// starting from Home screen, change the date to the desired date
106+
// then go back to the home screen
107+
void change_date(
108+
SingleSwitchProgramEnvironment& env,
109+
BotBaseContext& context,
110+
const DateTime& date
111+
);
112+
104113

105114

106115
}

SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStoryTools.cpp

Lines changed: 94 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,21 @@
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

763782
void wait_for_gradient_arrow(
764783
const ProgramInfo& info,
@@ -860,6 +879,8 @@ bool check_ride_active(const ProgramInfo& info, ConsoleHandle& console, BotBaseC
860879
}
861880

862881
void 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
}

SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStoryTools.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#ifndef PokemonAutomation_PokemonSV_AutoStoryTools_H
88
#define PokemonAutomation_PokemonSV_AutoStoryTools_H
99

10+
#include "Common/Cpp/DateTime.h"
1011
#include "NintendoSwitch/NintendoSwitch_SingleSwitchProgram.h"
1112
#include "CommonFramework/Tools/StatsTracking.h"
1213
#include "CommonFramework/Language.h"
@@ -191,6 +192,8 @@ void handle_unexpected_battles(
191192
// if stationary in overworld for an amount of time (seconds_stationary), run `recovery_action` then try `action` again
192193
// return once successfully completed `action`
193194
// throw exception if fails to complete `action` within a certain amount of time (minutes_timeout).
195+
// NOTE: if using this function to wrap overworld_navigation(), keep in mind that
196+
// confirm_marker_present() will keep the player still for 5 seconds before moving. Therefore, seconds_stationary should be greater than 5 seconds in this case.
194197
void handle_when_stationary_in_overworld(
195198
const ProgramInfo& info,
196199
ConsoleHandle& console,
@@ -205,8 +208,9 @@ void handle_when_stationary_in_overworld(
205208
ConsoleHandle& console,
206209
BotBaseContext& context)
207210
>&& recovery_action,
208-
size_t seconds_stationary = 5,
209-
uint16_t minutes_timeout = 5
211+
size_t seconds_stationary = 6,
212+
uint16_t minutes_timeout = 5,
213+
size_t max_attempts = 2
210214
);
211215

212216
void wait_for_gradient_arrow(
@@ -283,6 +287,9 @@ void move_cursor_towards_flypoint_and_go_there(
283287
MoveCursor move_cursor_near_flypoint
284288
);
285289

290+
291+
void check_num_sunflora_found(SingleSwitchProgramEnvironment& env, BotBaseContext& context, int expected_number);
292+
286293
}
287294
}
288295
}

0 commit comments

Comments
 (0)