Skip to content

Commit

Permalink
Segment 11 (Olive roll) and update AutoStoryTools (#510)
Browse files Browse the repository at this point in the history
* Segment 11 (Olive roll) and update AutoStoryTools

* move change_date() to NintendoSwitch_DateReader.h
  • Loading branch information
jw098 authored Nov 16, 2024
1 parent e5cf988 commit 7c27a02
Show file tree
Hide file tree
Showing 8 changed files with 855 additions and 54 deletions.
4 changes: 3 additions & 1 deletion SerialPrograms/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1459,7 +1459,9 @@ file(GLOB MAIN_SOURCES
Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_09.cpp
Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_09.h
Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_10.cpp
Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_10.h
Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_10.h
Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_11.cpp
Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_11.h
Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory.cpp
Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory.h
Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStoryTools.cpp
Expand Down
2 changes: 2 additions & 0 deletions SerialPrograms/SerialPrograms.pro
Original file line number Diff line number Diff line change
Expand Up @@ -729,6 +729,7 @@ SOURCES += \
Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_08.cpp \
Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_09.cpp \
Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_10.cpp \
Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_11.cpp \
Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory.cpp \
Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStoryTools.cpp \
Source/PokemonSV/Programs/AutoStory/PokemonSV_MenuOption.cpp \
Expand Down Expand Up @@ -1832,6 +1833,7 @@ HEADERS += \
Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_08.h \
Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_09.h \
Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_10.h \
Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_11.h \
Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory.h \
Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStoryTools.h \
Source/PokemonSV/Programs/AutoStory/PokemonSV_MenuOption.h \
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "Common/Qt/StringToolsQt.h"
#include "CommonFramework/Exceptions/OperationFailedException.h"
#include "CommonFramework/Exceptions/FatalProgramException.h"
#include "CommonFramework/InferenceInfra/InferenceRoutines.h"
#include "CommonFramework/ImageTypes/ImageRGB32.h"
#include "CommonFramework/ImageTools/ImageStats.h"
#include "CommonFramework/ImageTools/ImageFilter.h"
Expand All @@ -18,6 +19,9 @@
#include "CommonFramework/OCR/OCR_RawOCR.h"
#include "CommonFramework/OCR/OCR_NumberReader.h"
#include "CommonFramework/OCR/OCR_StringNormalization.h"
#include "PokemonSwSh/Commands/PokemonSwSh_Commands_DateSpam.h"
#include "NintendoSwitch/NintendoSwitch_Settings.h"
#include "NintendoSwitch/Inference/NintendoSwitch_DetectHome.h"
#include "NintendoSwitch/Commands/NintendoSwitch_Commands_PushButtons.h"
#include "NintendoSwitch/Commands/NintendoSwitch_Commands_Superscalar.h"
#include "NintendoSwitch_DateReader.h"
Expand Down Expand Up @@ -568,6 +572,54 @@ void DateReader::set_date(
);
}

void change_date(
SingleSwitchProgramEnvironment& env, BotBaseContext& context,
const DateTime& date
){
while (true){
context.wait_for_all_requests();

HomeWatcher home;
DateChangeWatcher date_reader;
int ret = wait_until(
env.console, context, std::chrono::seconds(120),
{
home,
date_reader
}
);
switch (ret){
case 0:
home_to_date_time(context, true, false);
pbf_press_button(context, BUTTON_A, 10, 30);
context.wait_for_all_requests();
continue;
case 1:{
env.log("Detected date change.");

// Set the date
VideoOverlaySet overlays(env.console.overlay());
date_reader.make_overlays(overlays);
date_reader.set_date(env.program_info(), env.console, context, date);

// Commit the date.
pbf_press_button(context, BUTTON_A, 20, 30);

// Re-enter the game.
pbf_press_button(context, BUTTON_HOME, 20, ConsoleSettings::instance().SETTINGS_TO_HOME_DELAY);

return;
}
default:
throw OperationFailedException(
ErrorReport::SEND_ERROR_REPORT,
env.logger(),
"Failed to set date"
);
}
}
}




Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "CommonFramework/ImageTools/ImageBoxes.h"
#include "CommonFramework/InferenceInfra/VisualInferenceCallback.h"
#include "CommonFramework/Inference/VisualDetector.h"
#include "NintendoSwitch/NintendoSwitch_SingleSwitchProgram.h"

namespace PokemonAutomation{
struct ProgramInfo;
Expand Down Expand Up @@ -101,6 +102,14 @@ class DateChangeWatcher : public DetectorToFinder<DateReader>{
{}
};

// starting from Home screen, change the date to the desired date
// then go back to the home screen
void change_date(
SingleSwitchProgramEnvironment& env,
BotBaseContext& context,
const DateTime& date
);



}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,21 @@
#include "CommonFramework/Notifications/ProgramNotifications.h"
#include "CommonFramework/Tools/StatsTracking.h"
#include "CommonFramework/ImageTools/SolidColorTest.h"
#include "CommonFramework/ImageTools/ImageBoxes.h"
#include "CommonFramework/ImageTools/ImageFilter.h"
#include "CommonFramework/OCR/OCR_NumberReader.h"
#include "NintendoSwitch/Commands/NintendoSwitch_Commands_PushButtons.h"
#include "NintendoSwitch/Commands/NintendoSwitch_Commands_Superscalar.h"
#include "NintendoSwitch/Programs/NintendoSwitch_GameEntry.h"
#include "NintendoSwitch/Programs/NintendoSwitch_SnapshotDumper.h"
#include "PokemonSwSh/Inference/PokemonSwSh_IvJudgeReader.h"
#include "PokemonSV/Inference/Battles/PokemonSV_NormalBattleMenus.h"
#include "PokemonSV/Inference/Dialogs/PokemonSV_DialogDetector.h"
#include "PokemonSV/Inference/Overworld/PokemonSV_OverworldDetector.h"
// #include "PokemonSV/Inference/Overworld/PokemonSV_StationaryOverworldWatcher.h"
#include "PokemonSV/Inference/Overworld/PokemonSV_StationaryOverworldWatcher.h"
#include "PokemonSV/Inference/PokemonSV_MainMenuDetector.h"
#include "PokemonSV/Inference/Map/PokemonSV_MapMenuDetector.h"
#include "PokemonSV/PokemonSV_Settings.h"
#include "PokemonSV/Programs/PokemonSV_Navigation.h"
#include "PokemonSV/Programs/PokemonSV_GameEntry.h"
#include "PokemonSV/Programs/PokemonSV_SaveGame.h"
Expand Down Expand Up @@ -380,7 +385,7 @@ bool confirm_marker_present(

int ret = wait_until(
console, context,
std::chrono::seconds(10),
std::chrono::seconds(5),
{marker, battle}
);
switch (ret){
Expand Down Expand Up @@ -454,9 +459,11 @@ void overworld_navigation(
}
}
}
context.wait_for_all_requests();
if (should_realign){
try {
realign_player(info, console, context, PlayerRealignMode::REALIGN_OLD_MARKER);

}catch (UnexpectedBattleException&){
pbf_wait(context, 30 * TICKS_PER_SECOND); // catch exception to allow the battle callback to take over.
}
Expand All @@ -479,10 +486,9 @@ void overworld_navigation(
if (auto_heal){
auto_heal_from_menu_or_overworld(info, console, context, 0, true);
}

context.wait_for_all_requests();
try {
realign_player(info, console, context, PlayerRealignMode::REALIGN_OLD_MARKER);

if (!confirm_marker_present(info, console, context)){
// if marker not present, don't keep walking forward.
return;
Expand Down Expand Up @@ -682,7 +688,7 @@ void do_action_and_monitor_for_battles(
{battle_menu}
);
if (ret == 0){ // battle detected
throw OperationFailedException(
throw UnexpectedBattleException(
ErrorReport::SEND_ERROR_REPORT, console,
"do_action_and_monitor_for_battles(): Detected battle. Failed to complete action.",
true
Expand Down Expand Up @@ -713,52 +719,65 @@ void handle_unexpected_battles(
}
}

// void handle_when_stationary_in_overworld(
// const ProgramInfo& info,
// ConsoleHandle& console,
// BotBaseContext& context,
// std::function<
// void(const ProgramInfo& info,
// ConsoleHandle& console,
// BotBaseContext& context)
// >&& action,
// std::function<
// void(const ProgramInfo& info,
// ConsoleHandle& console,
// BotBaseContext& context)
// >&& recovery_action,
// size_t seconds_stationary,
// uint16_t minutes_timeout
// ){
// StationaryOverworldWatcher stationary_overworld(COLOR_RED, {0.865, 0.82, 0.08, 0.1}, seconds_stationary);
// WallClock start = current_time();
// while (true){
// if (current_time() - start > std::chrono::minutes(minutes_timeout)){
// throw OperationFailedException(
// ErrorReport::SEND_ERROR_REPORT, console,
// "handle_when_stationary_in_overworld(): Failed to complete action after 5 minutes.",
// true
// );
// }

// int ret = run_until(
// console, context,
// [&](BotBaseContext& context){
// context.wait_for_all_requests();
// action(info, console, context);
// },
// {stationary_overworld}
// );
// if (ret < 0){
// // successfully completed action without being stuck in a position where the overworld is stationary.
// return;
// }else if (ret == 0){
// // if stationary in overworld, run recovery action then try action again
// context.wait_for_all_requests();
// recovery_action(info, console, context);
// }
// }
// }
void handle_when_stationary_in_overworld(
const ProgramInfo& info,
ConsoleHandle& console,
BotBaseContext& context,
std::function<
void(const ProgramInfo& info,
ConsoleHandle& console,
BotBaseContext& context)
>&& action,
std::function<
void(const ProgramInfo& info,
ConsoleHandle& console,
BotBaseContext& context)
>&& recovery_action,
size_t seconds_stationary,
uint16_t minutes_timeout,
size_t max_failures
){

WallClock start = current_time();
size_t num_failures = 0;
while (true){
if (current_time() - start > std::chrono::minutes(minutes_timeout)){
throw OperationFailedException(
ErrorReport::SEND_ERROR_REPORT, console,
"handle_when_stationary_in_overworld(): Failed to complete action after " + std::to_string(minutes_timeout) + " minutes.",
true
);
}
StationaryOverworldWatcher stationary_overworld(COLOR_RED, {0.865, 0.825, 0.08, 0.1}, seconds_stationary);

int ret = run_until(
console, context,
[&](BotBaseContext& context){
context.wait_for_all_requests();
action(info, console, context);
},
{stationary_overworld}
);
if (ret < 0){
// successfully completed action without being stuck in a position where the overworld is stationary.
return;
}else if (ret == 0){
// if stationary in overworld, run recovery action then try action again
console.log("Detected stationary overworld.");
num_failures++;
if (num_failures > max_failures){
throw OperationFailedException(
ErrorReport::SEND_ERROR_REPORT, console,
"handle_when_stationary_in_overworld(): Failed to complete action within " + std::to_string(max_failures) + " attempts.",
true
);
}
context.wait_for_all_requests();
recovery_action(info, console, context);
}
}
}


void wait_for_gradient_arrow(
const ProgramInfo& info,
Expand Down Expand Up @@ -860,6 +879,8 @@ bool check_ride_active(const ProgramInfo& info, ConsoleHandle& console, BotBaseC
}

void get_on_ride(const ProgramInfo& info, ConsoleHandle& console, BotBaseContext& context){
pbf_press_button(context, BUTTON_PLUS, 20, 20);

WallClock start = current_time();
while (!check_ride_active(info, console, context)){
if (current_time() - start > std::chrono::minutes(3)){
Expand Down Expand Up @@ -1065,6 +1086,28 @@ void move_cursor_towards_flypoint_and_go_there(
}



void check_num_sunflora_found(SingleSwitchProgramEnvironment& env, BotBaseContext& context, int expected_number){
context.wait_for_all_requests();
VideoSnapshot screen = env.console.video().snapshot();
ImageFloatBox num_sunflora_box = {0.27, 0.02, 0.04, 0.055};
int number = OCR::read_number_waterfill(env.console, extract_box_reference(screen, num_sunflora_box), 0xff000000, 0xff808080);

if (number != expected_number){
throw OperationFailedException(
ErrorReport::SEND_ERROR_REPORT,
env.logger(),
"The number of sunflora found is different than expected."
);
}else{
env.console.log("Number of sunflora found: " + std::to_string(number));
}


}



}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#ifndef PokemonAutomation_PokemonSV_AutoStoryTools_H
#define PokemonAutomation_PokemonSV_AutoStoryTools_H

#include "Common/Cpp/DateTime.h"
#include "NintendoSwitch/NintendoSwitch_SingleSwitchProgram.h"
#include "CommonFramework/Tools/StatsTracking.h"
#include "CommonFramework/Language.h"
Expand Down Expand Up @@ -191,6 +192,8 @@ void handle_unexpected_battles(
// if stationary in overworld for an amount of time (seconds_stationary), run `recovery_action` then try `action` again
// return once successfully completed `action`
// throw exception if fails to complete `action` within a certain amount of time (minutes_timeout).
// NOTE: if using this function to wrap overworld_navigation(), keep in mind that
// 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.
void handle_when_stationary_in_overworld(
const ProgramInfo& info,
ConsoleHandle& console,
Expand All @@ -205,8 +208,9 @@ void handle_when_stationary_in_overworld(
ConsoleHandle& console,
BotBaseContext& context)
>&& recovery_action,
size_t seconds_stationary = 5,
uint16_t minutes_timeout = 5
size_t seconds_stationary = 6,
uint16_t minutes_timeout = 5,
size_t max_attempts = 2
);

void wait_for_gradient_arrow(
Expand Down Expand Up @@ -283,6 +287,9 @@ void move_cursor_towards_flypoint_and_go_there(
MoveCursor move_cursor_near_flypoint
);


void check_num_sunflora_found(SingleSwitchProgramEnvironment& env, BotBaseContext& context, int expected_number);

}
}
}
Expand Down
Loading

0 comments on commit 7c27a02

Please sign in to comment.