From 60381a04160940930c36a23a4ddf1aecdb1deda2 Mon Sep 17 00:00:00 2001 From: kichithewolf Date: Fri, 10 Jan 2025 12:02:56 -0500 Subject: [PATCH 01/11] kichi's dev token --- SerialPrograms/Source/CommonFramework/GlobalSettingsPanel.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/SerialPrograms/Source/CommonFramework/GlobalSettingsPanel.cpp b/SerialPrograms/Source/CommonFramework/GlobalSettingsPanel.cpp index c53c8899d..c0bb6fa32 100644 --- a/SerialPrograms/Source/CommonFramework/GlobalSettingsPanel.cpp +++ b/SerialPrograms/Source/CommonFramework/GlobalSettingsPanel.cpp @@ -42,6 +42,7 @@ const std::set TOKENS{ "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08", // jw's token. "e8d168bc482e96553ea9f9ecaea5a817474dbccc2a6a228a6bde67f2b2aa2889", // James' token. "7555b7c63481cad42306718c67e7f9def5bfd1da8f6cd299ccd3d7dc95f307ae", // Kuro's token. + "3d475b46d121fc24559d100de2426feaa53cd6578aac2817c4857a610ccde2dd", // kichi's token. }; From 96efeb119217cec81881e2ad5d360904b8335cd0 Mon Sep 17 00:00:00 2001 From: kichithewolf Date: Fri, 10 Jan 2025 14:01:32 -0500 Subject: [PATCH 02/11] pokemon emerald game dropdown/panels --- SerialPrograms/CMakeLists.txt | 6 + SerialPrograms/Source/PanelLists.cpp | 2 + .../PokemonEmerald/PokemonEmerald_Panels.cpp | 43 +++++++ .../PokemonEmerald/PokemonEmerald_Panels.h | 29 +++++ .../PokemonEmerald_Settings.cpp | 99 +++++++++++++++ .../PokemonEmerald/PokemonEmerald_Settings.h | 57 +++++++++ .../PokemonEmerald_StarterReset.cpp | 116 ++++++++++++++++++ .../PokemonEmerald_StarterReset.h | 44 +++++++ 8 files changed, 396 insertions(+) create mode 100644 SerialPrograms/Source/PokemonEmerald/PokemonEmerald_Panels.cpp create mode 100644 SerialPrograms/Source/PokemonEmerald/PokemonEmerald_Panels.h create mode 100644 SerialPrograms/Source/PokemonEmerald/PokemonEmerald_Settings.cpp create mode 100644 SerialPrograms/Source/PokemonEmerald/PokemonEmerald_Settings.h create mode 100644 SerialPrograms/Source/PokemonEmerald/Programs/ShinyHunting/PokemonEmerald_StarterReset.cpp create mode 100644 SerialPrograms/Source/PokemonEmerald/Programs/ShinyHunting/PokemonEmerald_StarterReset.h diff --git a/SerialPrograms/CMakeLists.txt b/SerialPrograms/CMakeLists.txt index ba3c9a52a..1dac22ec2 100644 --- a/SerialPrograms/CMakeLists.txt +++ b/SerialPrograms/CMakeLists.txt @@ -1075,6 +1075,12 @@ file(GLOB MAIN_SOURCES Source/PokemonBDSP/Programs/Trading/PokemonBDSP_TradeRoutines.h Source/PokemonBDSP/Resources/PokemonBDSP_NameDatabase.cpp Source/PokemonBDSP/Resources/PokemonBDSP_NameDatabase.h + Source/PokemonEmerald/Programs/ShinyHunting/PokemonEmerald_StarterReset.cpp + Source/PokemonEmerald/Programs/ShinyHunting/PokemonEmerald_StarterReset.h + Source/PokemonEmerald/PokemonEmerald_Panels.cpp + Source/PokemonEmerald/PokemonEmerald_Panels.h + Source/PokemonEmerald/PokemonEmerald_Settings.cpp + Source/PokemonEmerald/PokemonEmerald_Settings.h Source/PokemonHome/Inference/PokemonHome_BallReader.cpp Source/PokemonHome/Inference/PokemonHome_BallReader.h Source/PokemonHome/Inference/PokemonHome_BoxGenderDetector.cpp diff --git a/SerialPrograms/Source/PanelLists.cpp b/SerialPrograms/Source/PanelLists.cpp index ad73de5ba..9f9efe5d4 100644 --- a/SerialPrograms/Source/PanelLists.cpp +++ b/SerialPrograms/Source/PanelLists.cpp @@ -16,6 +16,7 @@ #include "PokemonSwSh/PokemonSwSh_Panels.h" #include "PokemonHome/PokemonHome_Panels.h" #include "PokemonBDSP/PokemonBDSP_Panels.h" +#include "PokemonEmerald/PokemonEmerald_Panels.h" #include "PokemonLA/PokemonLA_Panels.h" #include "PokemonSV/PokemonSV_Panels.h" #include "ZeldaTotK/ZeldaTotK_Panels.h" @@ -47,6 +48,7 @@ ProgramSelect::ProgramSelect(QWidget& parent, PanelHolder& holder) add(std::make_unique()); add(std::make_unique()); add(std::make_unique()); + add(std::make_unique()); add(std::make_unique()); diff --git a/SerialPrograms/Source/PokemonEmerald/PokemonEmerald_Panels.cpp b/SerialPrograms/Source/PokemonEmerald/PokemonEmerald_Panels.cpp new file mode 100644 index 000000000..e748c8321 --- /dev/null +++ b/SerialPrograms/Source/PokemonEmerald/PokemonEmerald_Panels.cpp @@ -0,0 +1,43 @@ +/* Pokemon Emerald Panels + * + * From: https://github.com/PokemonAutomation/Arduino-Source + * + */ + +#include "Pokemon/Pokemon_Strings.h" +#include "PokemonEmerald_Panels.h" + +//#include "PokemonSV_Settings.h" + +#include "Programs/ShinyHunting/PokemonEmerald_StarterReset.h" + +namespace PokemonAutomation{ +namespace NintendoSwitch{ +namespace PokemonEmerald{ + + + +PanelListFactory::PanelListFactory() + : PanelListDescriptor("Pokemon Emerald") +{} + +std::vector PanelListFactory::make_panels() const{ + std::vector ret; + + // ret.emplace_back("---- Settings ----"); TODO: Add device selection? + // ret.emplace_back(make_settings()); + + //ret.emplace_back("---- General ----"); + + ret.emplace_back("---- Shiny Hunting ----"); + ret.emplace_back(make_single_switch_program()); + + return ret; +} + + + + +} +} +} diff --git a/SerialPrograms/Source/PokemonEmerald/PokemonEmerald_Panels.h b/SerialPrograms/Source/PokemonEmerald/PokemonEmerald_Panels.h new file mode 100644 index 000000000..bd1f9a93a --- /dev/null +++ b/SerialPrograms/Source/PokemonEmerald/PokemonEmerald_Panels.h @@ -0,0 +1,29 @@ +/* Pokemon Emerald Panels + * + * From: https://github.com/PokemonAutomation/Arduino-Source + * + */ + +#ifndef PokemonAutomation_PokemonEmerald_Panels_H +#define PokemonAutomation_PokemonEmerald_Panels_H + +#include "CommonFramework/Panels/PanelList.h" + +namespace PokemonAutomation{ +namespace NintendoSwitch{ +namespace PokemonEmerald{ + + + +class PanelListFactory : public PanelListDescriptor{ +public: + PanelListFactory(); + virtual std::vector make_panels() const; +}; + + + +} +} +} +#endif diff --git a/SerialPrograms/Source/PokemonEmerald/PokemonEmerald_Settings.cpp b/SerialPrograms/Source/PokemonEmerald/PokemonEmerald_Settings.cpp new file mode 100644 index 000000000..5212fe969 --- /dev/null +++ b/SerialPrograms/Source/PokemonEmerald/PokemonEmerald_Settings.cpp @@ -0,0 +1,99 @@ +/* Pokemon Emerald Settings + * + * From: https://github.com/PokemonAutomation/Arduino-Source + * + */ + +#include "Common/NintendoSwitch/NintendoSwitch_ControllerDefs.h" +#include "CommonFramework/Globals.h" + +#include "PokemonEmerald_Settings.h" + +namespace PokemonAutomation{ +namespace NintendoSwitch{ +namespace PokemonEmerald{ + + + +GameSettings& GameSettings::instance(){ + static GameSettings settings; + return settings; +} +GameSettings::GameSettings() + : BatchOption(LockMode::LOCK_WHILE_RUNNING) + , m_menu_navigation("Menu Navigation Timings:") + , GAME_TO_HOME_DELAY( + "Game to Home Delay:
Delay from pressing home to entering the the Switch home menu.", + LockMode::LOCK_WHILE_RUNNING, + TICKS_PER_SECOND, + "125" + ) + , m_start_game_timings("Start Game Timings:") + , START_GAME_MASH( + "1. Start Game Mash:
Mash A for this long to start the game.", + LockMode::LOCK_WHILE_RUNNING, + TICKS_PER_SECOND, + "2 * TICKS_PER_SECOND" + ) + , START_GAME_WAIT( + "2. Start Game Wait:
Wait this long for the game to load.", + LockMode::LOCK_WHILE_RUNNING, + TICKS_PER_SECOND, + "60 * TICKS_PER_SECOND" + ) + , ENTER_GAME_MASH( + "3. Enter Game Mash:
Mash A for this long to enter the game.", + LockMode::LOCK_WHILE_RUNNING, + TICKS_PER_SECOND, + "5 * TICKS_PER_SECOND" + ) + , ENTER_GAME_WAIT( + "4. Enter Game Wait:
Wait this long for the game to enter the overworld.", + LockMode::LOCK_WHILE_RUNNING, + TICKS_PER_SECOND, + "60 * TICKS_PER_SECOND" + ) +{ + PA_ADD_STATIC(m_start_game_timings); + PA_ADD_OPTION(START_GAME_MASH); + PA_ADD_OPTION(START_GAME_WAIT); + PA_ADD_OPTION(ENTER_GAME_MASH); + PA_ADD_OPTION(ENTER_GAME_WAIT); +} + + + + + +GameSettings_Descriptor::GameSettings_Descriptor() + : PanelDescriptor( + Color(), + "PokemonEmerald:GlobalSettings", + "Pokemon Emerald", "Pokemon Emerald Settings", + "ComputerControl/blob/master/Wiki/Programs/PokemonEmerald/EmeraldSettings.md", + "Global Pokemon Emerald Settings" + ) +{} + + + +GameSettingsPanel::GameSettingsPanel(const GameSettings_Descriptor& descriptor) + : SettingsPanelInstance(descriptor) + , settings(GameSettings::instance()) +{ + PA_ADD_OPTION(settings); +} + + + + + +} +} +} + + + + + + diff --git a/SerialPrograms/Source/PokemonEmerald/PokemonEmerald_Settings.h b/SerialPrograms/Source/PokemonEmerald/PokemonEmerald_Settings.h new file mode 100644 index 000000000..f81c5b9c5 --- /dev/null +++ b/SerialPrograms/Source/PokemonEmerald/PokemonEmerald_Settings.h @@ -0,0 +1,57 @@ +/* Pokemon Emerald Settings + * + * From: https://github.com/PokemonAutomation/Arduino-Source + * + */ + +#ifndef PokemonAutomation_PokemonEmerald_Settings_H +#define PokemonAutomation_PokemonEmerald_Settings_H + +#include "Common/Cpp/Options/StaticTextOption.h" +#include "Common/Cpp/Options/BooleanCheckBoxOption.h" +#include "Common/Cpp/Options/FloatingPointOption.h" +#include "Common/Cpp/Options/TimeExpressionOption.h" +#include "CommonFramework/Panels/SettingsPanel.h" + +namespace PokemonAutomation{ +namespace NintendoSwitch{ +namespace PokemonEmerald{ + + +class GameSettings : public BatchOption{ + GameSettings(); +public: + static GameSettings& instance(); + + SectionDividerOption m_menu_navigation; + TimeExpressionOption GAME_TO_HOME_DELAY; + + SectionDividerOption m_start_game_timings; + TimeExpressionOption START_GAME_MASH; + TimeExpressionOption START_GAME_WAIT; + TimeExpressionOption ENTER_GAME_MASH; + TimeExpressionOption ENTER_GAME_WAIT; + +}; + + + + +class GameSettings_Descriptor : public PanelDescriptor{ +public: + GameSettings_Descriptor(); +}; + + +class GameSettingsPanel : public SettingsPanelInstance{ +public: + GameSettingsPanel(const GameSettings_Descriptor& descriptor); +private: + GameSettings& settings; +}; + + +} +} +} +#endif diff --git a/SerialPrograms/Source/PokemonEmerald/Programs/ShinyHunting/PokemonEmerald_StarterReset.cpp b/SerialPrograms/Source/PokemonEmerald/Programs/ShinyHunting/PokemonEmerald_StarterReset.cpp new file mode 100644 index 000000000..28890d173 --- /dev/null +++ b/SerialPrograms/Source/PokemonEmerald/Programs/ShinyHunting/PokemonEmerald_StarterReset.cpp @@ -0,0 +1,116 @@ +/* Emerald Starter Reset + * + * From: https://github.com/PokemonAutomation/Arduino-Source + * + */ + +#include "Common/Cpp/PrettyPrint.h" +#include "CommonFramework/Notifications/ProgramNotifications.h" +#include "CommonFramework/Tools/StatsTracking.h" +#include "NintendoSwitch/Commands/NintendoSwitch_Commands_PushButtons.h" +#include "NintendoSwitch/Commands/NintendoSwitch_Commands_Superscalar.h" +#include "PokemonEmerald_StarterReset.h" + +namespace PokemonAutomation{ +namespace NintendoSwitch{ +namespace PokemonEmerald{ + +StarterReset_Descriptor::StarterReset_Descriptor() + : SingleSwitchProgramDescriptor( + "PokemonEmerald:StarterReset", + "Pokemon Emerald", "Starter Reset", + "ComputerControl/blob/master/Wiki/Programs/PokemonEmerald/StarterReset.md", + "Soft reset for a shiny starter. Battery cannot be dry.", + FeedbackType::VIDEO_AUDIO, + AllowCommandsWhenRunning::DISABLE_COMMANDS, + PABotBaseLevel::PABOTBASE_12KB + ) +{} + +struct StarterReset_Descriptor::Stats : public StatsTracker{ + Stats() + : dupe_attempts(m_stats["Dupe Attempts"]) + { + m_display_order.emplace_back("Dupe Attempts"); + } + std::atomic& dupe_attempts; +}; +std::unique_ptr StarterReset_Descriptor::make_stats() const{ + return std::unique_ptr(new Stats()); +} + +StarterReset::StarterReset() + : ATTEMPTS( + "Duplication Attempts:
The number of times you wish to run this routine.", + LockMode::UNLOCK_WHILE_RUNNING, + 100 + ) + , GO_HOME_WHEN_DONE(false) + , NOTIFICATION_STATUS_UPDATE("Status Update", true, false, std::chrono::seconds(3600)) + , NOTIFICATIONS({ + &NOTIFICATION_STATUS_UPDATE, + &NOTIFICATION_PROGRAM_FINISH, + // &NOTIFICATION_ERROR_FATAL, + }) +{ + PA_ADD_OPTION(ATTEMPTS); + PA_ADD_OPTION(GO_HOME_WHEN_DONE); + PA_ADD_OPTION(NOTIFICATIONS); +} + +void StarterReset::program(SingleSwitchProgramEnvironment& env, BotBaseContext& context){ + StarterReset_Descriptor::Stats& stats = env.current_stats(); + + /* + * Stand in front of birch's bag. + * + * text speed fast + * + * have to do the SR method instead of run away + * + * cannot have dry battery + */ + + uint32_t c = 0; + + + /* + start at birch bag + + starter selection + + wild zig appears, shiny check (audio?) + + go starter + + now shiny check + + track starter shiny, zig shiny, number of attempts, errors + + if not shiny, soft reset + + soft reset checks for dry battery and returns true or false! + + */ + + + + while (c < ATTEMPTS){ + env.log("Current Attempts: " + tostr_u_commas(c)); + + // increment counter, increment stats + c++; + stats.dupe_attempts++; + env.update_stats(); + send_program_status_notification(env, NOTIFICATION_STATUS_UPDATE); + + } + + GO_HOME_WHEN_DONE.run_end_of_program(context); + send_program_finished_notification(env, NOTIFICATION_PROGRAM_FINISH); +} + +} +} +} + diff --git a/SerialPrograms/Source/PokemonEmerald/Programs/ShinyHunting/PokemonEmerald_StarterReset.h b/SerialPrograms/Source/PokemonEmerald/Programs/ShinyHunting/PokemonEmerald_StarterReset.h new file mode 100644 index 000000000..28089655b --- /dev/null +++ b/SerialPrograms/Source/PokemonEmerald/Programs/ShinyHunting/PokemonEmerald_StarterReset.h @@ -0,0 +1,44 @@ +/* Emerald Starter Reset + * + * From: https://github.com/PokemonAutomation/Arduino-Source + * + */ + +#ifndef PokemonAutomation_PokemonEmerald_StarterReset_H +#define PokemonAutomation_PokemonEmerald_StarterReset_H + +#include "Common/Cpp/Options/SimpleIntegerOption.h" +#include "CommonFramework/Notifications/EventNotificationsTable.h" +#include "NintendoSwitch/NintendoSwitch_SingleSwitchProgram.h" +#include "NintendoSwitch/Options/NintendoSwitch_GoHomeWhenDoneOption.h" + +namespace PokemonAutomation{ +namespace NintendoSwitch{ +namespace PokemonEmerald{ + +class StarterReset_Descriptor : public SingleSwitchProgramDescriptor{ +public: + StarterReset_Descriptor(); + struct Stats; + virtual std::unique_ptr make_stats() const override; +}; + +class StarterReset : public SingleSwitchProgramInstance{ +public: + StarterReset(); + virtual void program(SingleSwitchProgramEnvironment& env, BotBaseContext& context) override; + +private: + SimpleIntegerOption ATTEMPTS; + GoHomeWhenDoneOption GO_HOME_WHEN_DONE; + EventNotificationOption NOTIFICATION_STATUS_UPDATE; + EventNotificationsOption NOTIFICATIONS; +}; + +} +} +} +#endif + + + From eb36c8d3da9627aa5cc1d2c980114c14f02d87b5 Mon Sep 17 00:00:00 2001 From: kichithewolf Date: Fri, 10 Jan 2025 20:21:48 -0500 Subject: [PATCH 03/11] rename to rse, starter reset test --- SerialPrograms/CMakeLists.txt | 16 +- SerialPrograms/Source/PanelLists.cpp | 4 +- .../PokemonEmerald_StarterReset.cpp | 116 ---------- .../Sounds/PokemonRSE_ShinySoundDetector.cpp | 41 ++++ .../Sounds/PokemonRSE_ShinySoundDetector.h | 36 ++++ .../PokemonRSE/PokemonRSE_Navigation.cpp | 46 ++++ .../Source/PokemonRSE/PokemonRSE_Navigation.h | 29 +++ .../PokemonRSE_Panels.cpp} | 10 +- .../PokemonRSE_Panels.h} | 8 +- .../PokemonRSE_Settings.cpp} | 24 ++- .../PokemonRSE_Settings.h} | 11 +- .../ShinyHunting/PokemonRSE_StarterReset.cpp | 198 ++++++++++++++++++ .../ShinyHunting/PokemonRSE_StarterReset.h} | 18 +- 13 files changed, 406 insertions(+), 151 deletions(-) delete mode 100644 SerialPrograms/Source/PokemonEmerald/Programs/ShinyHunting/PokemonEmerald_StarterReset.cpp create mode 100644 SerialPrograms/Source/PokemonRSE/Inference/Sounds/PokemonRSE_ShinySoundDetector.cpp create mode 100644 SerialPrograms/Source/PokemonRSE/Inference/Sounds/PokemonRSE_ShinySoundDetector.h create mode 100644 SerialPrograms/Source/PokemonRSE/PokemonRSE_Navigation.cpp create mode 100644 SerialPrograms/Source/PokemonRSE/PokemonRSE_Navigation.h rename SerialPrograms/Source/{PokemonEmerald/PokemonEmerald_Panels.cpp => PokemonRSE/PokemonRSE_Panels.cpp} (78%) rename SerialPrograms/Source/{PokemonEmerald/PokemonEmerald_Panels.h => PokemonRSE/PokemonRSE_Panels.h} (68%) rename SerialPrograms/Source/{PokemonEmerald/PokemonEmerald_Settings.cpp => PokemonRSE/PokemonRSE_Settings.cpp} (75%) rename SerialPrograms/Source/{PokemonEmerald/PokemonEmerald_Settings.h => PokemonRSE/PokemonRSE_Settings.h} (82%) create mode 100644 SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_StarterReset.cpp rename SerialPrograms/Source/{PokemonEmerald/Programs/ShinyHunting/PokemonEmerald_StarterReset.h => PokemonRSE/Programs/ShinyHunting/PokemonRSE_StarterReset.h} (71%) diff --git a/SerialPrograms/CMakeLists.txt b/SerialPrograms/CMakeLists.txt index 1dac22ec2..996769af2 100644 --- a/SerialPrograms/CMakeLists.txt +++ b/SerialPrograms/CMakeLists.txt @@ -1075,12 +1075,6 @@ file(GLOB MAIN_SOURCES Source/PokemonBDSP/Programs/Trading/PokemonBDSP_TradeRoutines.h Source/PokemonBDSP/Resources/PokemonBDSP_NameDatabase.cpp Source/PokemonBDSP/Resources/PokemonBDSP_NameDatabase.h - Source/PokemonEmerald/Programs/ShinyHunting/PokemonEmerald_StarterReset.cpp - Source/PokemonEmerald/Programs/ShinyHunting/PokemonEmerald_StarterReset.h - Source/PokemonEmerald/PokemonEmerald_Panels.cpp - Source/PokemonEmerald/PokemonEmerald_Panels.h - Source/PokemonEmerald/PokemonEmerald_Settings.cpp - Source/PokemonEmerald/PokemonEmerald_Settings.h Source/PokemonHome/Inference/PokemonHome_BallReader.cpp Source/PokemonHome/Inference/PokemonHome_BallReader.h Source/PokemonHome/Inference/PokemonHome_BoxGenderDetector.cpp @@ -1297,6 +1291,16 @@ file(GLOB MAIN_SOURCES Source/PokemonLA/Resources/PokemonLA_PokemonSprites.h Source/PokemonLA/Resources/PokemonLA_WeatherAndTimeIcons.cpp Source/PokemonLA/Resources/PokemonLA_WeatherAndTimeIcons.h + Source/PokemonRSE/Inference/Sounds/PokemonRSE_ShinySoundDetector.cpp + Source/PokemonRSE/Inference/Sounds/PokemonRSE_ShinySoundDetector.h + Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_StarterReset.cpp + Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_StarterReset.h + Source/PokemonRSE/PokemonRSE_Navigation.cpp + Source/PokemonRSE/PokemonRSE_Navigation.h + Source/PokemonRSE/PokemonRSE_Panels.cpp + Source/PokemonRSE/PokemonRSE_Panels.h + Source/PokemonRSE/PokemonRSE_Settings.cpp + Source/PokemonRSE/PokemonRSE_Settings.h Source/PokemonSV/Inference/Battles/PokemonSV_BattleBallReader.cpp Source/PokemonSV/Inference/Battles/PokemonSV_BattleBallReader.h Source/PokemonSV/Inference/Battles/PokemonSV_EncounterWatcher.cpp diff --git a/SerialPrograms/Source/PanelLists.cpp b/SerialPrograms/Source/PanelLists.cpp index 9f9efe5d4..6b168b587 100644 --- a/SerialPrograms/Source/PanelLists.cpp +++ b/SerialPrograms/Source/PanelLists.cpp @@ -16,8 +16,8 @@ #include "PokemonSwSh/PokemonSwSh_Panels.h" #include "PokemonHome/PokemonHome_Panels.h" #include "PokemonBDSP/PokemonBDSP_Panels.h" -#include "PokemonEmerald/PokemonEmerald_Panels.h" #include "PokemonLA/PokemonLA_Panels.h" +#include "PokemonRSE/PokemonRSE_Panels.h" #include "PokemonSV/PokemonSV_Panels.h" #include "ZeldaTotK/ZeldaTotK_Panels.h" #include "PanelLists.h" @@ -48,7 +48,7 @@ ProgramSelect::ProgramSelect(QWidget& parent, PanelHolder& holder) add(std::make_unique()); add(std::make_unique()); add(std::make_unique()); - add(std::make_unique()); + add(std::make_unique()); add(std::make_unique()); diff --git a/SerialPrograms/Source/PokemonEmerald/Programs/ShinyHunting/PokemonEmerald_StarterReset.cpp b/SerialPrograms/Source/PokemonEmerald/Programs/ShinyHunting/PokemonEmerald_StarterReset.cpp deleted file mode 100644 index 28890d173..000000000 --- a/SerialPrograms/Source/PokemonEmerald/Programs/ShinyHunting/PokemonEmerald_StarterReset.cpp +++ /dev/null @@ -1,116 +0,0 @@ -/* Emerald Starter Reset - * - * From: https://github.com/PokemonAutomation/Arduino-Source - * - */ - -#include "Common/Cpp/PrettyPrint.h" -#include "CommonFramework/Notifications/ProgramNotifications.h" -#include "CommonFramework/Tools/StatsTracking.h" -#include "NintendoSwitch/Commands/NintendoSwitch_Commands_PushButtons.h" -#include "NintendoSwitch/Commands/NintendoSwitch_Commands_Superscalar.h" -#include "PokemonEmerald_StarterReset.h" - -namespace PokemonAutomation{ -namespace NintendoSwitch{ -namespace PokemonEmerald{ - -StarterReset_Descriptor::StarterReset_Descriptor() - : SingleSwitchProgramDescriptor( - "PokemonEmerald:StarterReset", - "Pokemon Emerald", "Starter Reset", - "ComputerControl/blob/master/Wiki/Programs/PokemonEmerald/StarterReset.md", - "Soft reset for a shiny starter. Battery cannot be dry.", - FeedbackType::VIDEO_AUDIO, - AllowCommandsWhenRunning::DISABLE_COMMANDS, - PABotBaseLevel::PABOTBASE_12KB - ) -{} - -struct StarterReset_Descriptor::Stats : public StatsTracker{ - Stats() - : dupe_attempts(m_stats["Dupe Attempts"]) - { - m_display_order.emplace_back("Dupe Attempts"); - } - std::atomic& dupe_attempts; -}; -std::unique_ptr StarterReset_Descriptor::make_stats() const{ - return std::unique_ptr(new Stats()); -} - -StarterReset::StarterReset() - : ATTEMPTS( - "Duplication Attempts:
The number of times you wish to run this routine.", - LockMode::UNLOCK_WHILE_RUNNING, - 100 - ) - , GO_HOME_WHEN_DONE(false) - , NOTIFICATION_STATUS_UPDATE("Status Update", true, false, std::chrono::seconds(3600)) - , NOTIFICATIONS({ - &NOTIFICATION_STATUS_UPDATE, - &NOTIFICATION_PROGRAM_FINISH, - // &NOTIFICATION_ERROR_FATAL, - }) -{ - PA_ADD_OPTION(ATTEMPTS); - PA_ADD_OPTION(GO_HOME_WHEN_DONE); - PA_ADD_OPTION(NOTIFICATIONS); -} - -void StarterReset::program(SingleSwitchProgramEnvironment& env, BotBaseContext& context){ - StarterReset_Descriptor::Stats& stats = env.current_stats(); - - /* - * Stand in front of birch's bag. - * - * text speed fast - * - * have to do the SR method instead of run away - * - * cannot have dry battery - */ - - uint32_t c = 0; - - - /* - start at birch bag - - starter selection - - wild zig appears, shiny check (audio?) - - go starter - - now shiny check - - track starter shiny, zig shiny, number of attempts, errors - - if not shiny, soft reset - - soft reset checks for dry battery and returns true or false! - - */ - - - - while (c < ATTEMPTS){ - env.log("Current Attempts: " + tostr_u_commas(c)); - - // increment counter, increment stats - c++; - stats.dupe_attempts++; - env.update_stats(); - send_program_status_notification(env, NOTIFICATION_STATUS_UPDATE); - - } - - GO_HOME_WHEN_DONE.run_end_of_program(context); - send_program_finished_notification(env, NOTIFICATION_PROGRAM_FINISH); -} - -} -} -} - diff --git a/SerialPrograms/Source/PokemonRSE/Inference/Sounds/PokemonRSE_ShinySoundDetector.cpp b/SerialPrograms/Source/PokemonRSE/Inference/Sounds/PokemonRSE_ShinySoundDetector.cpp new file mode 100644 index 000000000..252551fd7 --- /dev/null +++ b/SerialPrograms/Source/PokemonRSE/Inference/Sounds/PokemonRSE_ShinySoundDetector.cpp @@ -0,0 +1,41 @@ +/* Shiny Sound Detector + * + * From: https://github.com/PokemonAutomation/Arduino-Source + * + */ + +#include "CommonFramework/Inference/SpectrogramMatcher.h" +#include "CommonFramework/Inference/AudioTemplateCache.h" +#include "CommonFramework/Tools/ConsoleHandle.h" +#include "PokemonRSE/PokemonRSE_Settings.h" +#include "PokemonRSE_ShinySoundDetector.h" + +namespace PokemonAutomation{ +namespace NintendoSwitch{ +namespace PokemonRSE{ + + +ShinySoundDetector::ShinySoundDetector(ConsoleHandle& console, DetectedCallback detected_callback) + // Use a yellow as the detection color because the shiny animation is yellow. + : AudioPerSpectrumDetectorBase("ShinySoundDetector", "Shiny sound", COLOR_YELLOW, console, detected_callback) +{} + + +float ShinySoundDetector::get_score_threshold() const{ + return (float)GameSettings::instance().SHINY_SOUND_THRESHOLD; +} + +std::unique_ptr ShinySoundDetector::build_spectrogram_matcher(size_t sample_rate){ + return std::make_unique( + "Shiny Sound", + AudioTemplateCache::instance().get_throw("PokemonRSE/ShinySound", sample_rate), + SpectrogramMatcher::Mode::SPIKE_CONV, sample_rate, + GameSettings::instance().SHINY_SOUND_LOW_FREQUENCY + ); +} + + + +} +} +} diff --git a/SerialPrograms/Source/PokemonRSE/Inference/Sounds/PokemonRSE_ShinySoundDetector.h b/SerialPrograms/Source/PokemonRSE/Inference/Sounds/PokemonRSE_ShinySoundDetector.h new file mode 100644 index 000000000..64c3e7d9a --- /dev/null +++ b/SerialPrograms/Source/PokemonRSE/Inference/Sounds/PokemonRSE_ShinySoundDetector.h @@ -0,0 +1,36 @@ +/* Shiny Sound Detector + * + * From: https://github.com/PokemonAutomation/Arduino-Source + * + */ + +#ifndef PokemonAutomation_PokemonRSE_ShinySoundDetector_H +#define PokemonAutomation_PokemonRSE_ShinySoundDetector_H + +#include "CommonFramework/Inference/AudioPerSpectrumDetectorBase.h" + +namespace PokemonAutomation{ +namespace NintendoSwitch{ +namespace PokemonRSE{ + + +class ShinySoundDetector : public AudioPerSpectrumDetectorBase{ +public: + // Warning: The callback will be called from the audio inference thread. + ShinySoundDetector(ConsoleHandle& console, DetectedCallback detected_callback); + + // Implement AudioPerSpectrumDetectorBase::get_score_threshold() + virtual float get_score_threshold() const override; + +protected: + // Implement AudioPerSpectrumDetectorBase::build_spectrogram_matcher() + virtual std::unique_ptr build_spectrogram_matcher(size_t sample_rate) override; +}; + + + + +} +} +} +#endif diff --git a/SerialPrograms/Source/PokemonRSE/PokemonRSE_Navigation.cpp b/SerialPrograms/Source/PokemonRSE/PokemonRSE_Navigation.cpp new file mode 100644 index 000000000..f86d87eea --- /dev/null +++ b/SerialPrograms/Source/PokemonRSE/PokemonRSE_Navigation.cpp @@ -0,0 +1,46 @@ +/* Pokemon RSE Navigation + * + * From: https://github.com/PokemonAutomation/Arduino-Source + * + * Soft reset, menus, etc. + * + */ + +#include "CommonFramework/Exceptions/OperationFailedException.h" +#include "CommonFramework/Exceptions/UnexpectedBattleException.h" +#include "CommonFramework/InferenceInfra/InferenceRoutines.h" +#include "NintendoSwitch/NintendoSwitch_Settings.h" +#include "NintendoSwitch/Commands/NintendoSwitch_Commands_PushButtons.h" +#include "NintendoSwitch/Commands/NintendoSwitch_Commands_Superscalar.h" +#include "PokemonRSE_Navigation.h" + +namespace PokemonAutomation{ +namespace NintendoSwitch{ +namespace PokemonRSE{ + + +void soft_reset(const ProgramInfo& info, ConsoleHandle& console, BotBaseContext& context){ + // A + B + Select + Start + pbf_press_button(context, BUTTON_B | BUTTON_Y | BUTTON_MINUS | BUTTON_PLUS, 10, 180); + + pbf_mash_button(context, BUTTON_PLUS, 500); + context.wait_for_all_requests(); + + pbf_press_button(context, BUTTON_A, 20, 40); + + //Wait for game to load in + pbf_wait(context, 300); + context.wait_for_all_requests(); +} + + + + + + + + + +} +} +} diff --git a/SerialPrograms/Source/PokemonRSE/PokemonRSE_Navigation.h b/SerialPrograms/Source/PokemonRSE/PokemonRSE_Navigation.h new file mode 100644 index 000000000..70b3eac8a --- /dev/null +++ b/SerialPrograms/Source/PokemonRSE/PokemonRSE_Navigation.h @@ -0,0 +1,29 @@ +/* Pokemon RSE Navigation + * + * From: https://github.com/PokemonAutomation/Arduino-Source + * + * Soft reset, menus, etc. + * + */ + +#ifndef PokemonAutomation_PokemonRSE_Navigation_H +#define PokemonAutomation_PokemonRSE_Navigation_H + +#include "Common/NintendoSwitch/NintendoSwitch_ControllerDefs.h" + +namespace PokemonAutomation{ + struct ProgramInfo; + class ConsoleHandle; + class BotBaseContext; +namespace NintendoSwitch{ +namespace PokemonRSE{ + +// Press A+B+Select+Start at the same time to soft reset, then re-enters the game. +// This assumes no dry battery. Adding detection for that is a TODO. +void soft_reset(const ProgramInfo& info, ConsoleHandle& console, BotBaseContext& context); + + +} +} +} +#endif diff --git a/SerialPrograms/Source/PokemonEmerald/PokemonEmerald_Panels.cpp b/SerialPrograms/Source/PokemonRSE/PokemonRSE_Panels.cpp similarity index 78% rename from SerialPrograms/Source/PokemonEmerald/PokemonEmerald_Panels.cpp rename to SerialPrograms/Source/PokemonRSE/PokemonRSE_Panels.cpp index e748c8321..a3e7ed1d9 100644 --- a/SerialPrograms/Source/PokemonEmerald/PokemonEmerald_Panels.cpp +++ b/SerialPrograms/Source/PokemonRSE/PokemonRSE_Panels.cpp @@ -1,24 +1,24 @@ -/* Pokemon Emerald Panels +/* Pokemon RSE Panels * * From: https://github.com/PokemonAutomation/Arduino-Source * */ #include "Pokemon/Pokemon_Strings.h" -#include "PokemonEmerald_Panels.h" +#include "PokemonRSE_Panels.h" //#include "PokemonSV_Settings.h" -#include "Programs/ShinyHunting/PokemonEmerald_StarterReset.h" +#include "Programs/ShinyHunting/PokemonRSE_StarterReset.h" namespace PokemonAutomation{ namespace NintendoSwitch{ -namespace PokemonEmerald{ +namespace PokemonRSE{ PanelListFactory::PanelListFactory() - : PanelListDescriptor("Pokemon Emerald") + : PanelListDescriptor("Pokemon Ruby, Sapphire, and Emerald") {} std::vector PanelListFactory::make_panels() const{ diff --git a/SerialPrograms/Source/PokemonEmerald/PokemonEmerald_Panels.h b/SerialPrograms/Source/PokemonRSE/PokemonRSE_Panels.h similarity index 68% rename from SerialPrograms/Source/PokemonEmerald/PokemonEmerald_Panels.h rename to SerialPrograms/Source/PokemonRSE/PokemonRSE_Panels.h index bd1f9a93a..d5a36d12e 100644 --- a/SerialPrograms/Source/PokemonEmerald/PokemonEmerald_Panels.h +++ b/SerialPrograms/Source/PokemonRSE/PokemonRSE_Panels.h @@ -1,17 +1,17 @@ -/* Pokemon Emerald Panels +/* Pokemon RSE Panels * * From: https://github.com/PokemonAutomation/Arduino-Source * */ -#ifndef PokemonAutomation_PokemonEmerald_Panels_H -#define PokemonAutomation_PokemonEmerald_Panels_H +#ifndef PokemonAutomation_PokemonRSE_Panels_H +#define PokemonAutomation_PokemonRSE_Panels_H #include "CommonFramework/Panels/PanelList.h" namespace PokemonAutomation{ namespace NintendoSwitch{ -namespace PokemonEmerald{ +namespace PokemonRSE{ diff --git a/SerialPrograms/Source/PokemonEmerald/PokemonEmerald_Settings.cpp b/SerialPrograms/Source/PokemonRSE/PokemonRSE_Settings.cpp similarity index 75% rename from SerialPrograms/Source/PokemonEmerald/PokemonEmerald_Settings.cpp rename to SerialPrograms/Source/PokemonRSE/PokemonRSE_Settings.cpp index 5212fe969..f9ba49e18 100644 --- a/SerialPrograms/Source/PokemonEmerald/PokemonEmerald_Settings.cpp +++ b/SerialPrograms/Source/PokemonRSE/PokemonRSE_Settings.cpp @@ -1,4 +1,4 @@ -/* Pokemon Emerald Settings +/* Pokemon RSE Settings * * From: https://github.com/PokemonAutomation/Arduino-Source * @@ -7,11 +7,11 @@ #include "Common/NintendoSwitch/NintendoSwitch_ControllerDefs.h" #include "CommonFramework/Globals.h" -#include "PokemonEmerald_Settings.h" +#include "PokemonRSE_Settings.h" namespace PokemonAutomation{ namespace NintendoSwitch{ -namespace PokemonEmerald{ +namespace PokemonRSE{ @@ -53,6 +53,16 @@ GameSettings::GameSettings() TICKS_PER_SECOND, "60 * TICKS_PER_SECOND" ) + , SHINY_SOUND_THRESHOLD( + "Shiny Sound Threshold:
Maximum error coefficient to trigger a shiny detection.", + LockMode::LOCK_WHILE_RUNNING, + 0.87, 0, 1.0 + ) + , SHINY_SOUND_LOW_FREQUENCY( + "Shiny Sound Low Frequency (Hz):
High pass filter frequency for shiny sound.", + LockMode::LOCK_WHILE_RUNNING, + 5000, 0, 48000 + ) { PA_ADD_STATIC(m_start_game_timings); PA_ADD_OPTION(START_GAME_MASH); @@ -68,10 +78,10 @@ GameSettings::GameSettings() GameSettings_Descriptor::GameSettings_Descriptor() : PanelDescriptor( Color(), - "PokemonEmerald:GlobalSettings", - "Pokemon Emerald", "Pokemon Emerald Settings", - "ComputerControl/blob/master/Wiki/Programs/PokemonEmerald/EmeraldSettings.md", - "Global Pokemon Emerald Settings" + "PokemonRSE:GlobalSettings", + "Pokemon RSE", "Pokemon RSE Settings", + "ComputerControl/blob/master/Wiki/Programs/PokemonRSE/RSESettings.md", + "Global Pokemon RSE Settings" ) {} diff --git a/SerialPrograms/Source/PokemonEmerald/PokemonEmerald_Settings.h b/SerialPrograms/Source/PokemonRSE/PokemonRSE_Settings.h similarity index 82% rename from SerialPrograms/Source/PokemonEmerald/PokemonEmerald_Settings.h rename to SerialPrograms/Source/PokemonRSE/PokemonRSE_Settings.h index f81c5b9c5..5fa34d01f 100644 --- a/SerialPrograms/Source/PokemonEmerald/PokemonEmerald_Settings.h +++ b/SerialPrograms/Source/PokemonRSE/PokemonRSE_Settings.h @@ -1,11 +1,11 @@ -/* Pokemon Emerald Settings +/* Pokemon RSE Settings * * From: https://github.com/PokemonAutomation/Arduino-Source * */ -#ifndef PokemonAutomation_PokemonEmerald_Settings_H -#define PokemonAutomation_PokemonEmerald_Settings_H +#ifndef PokemonAutomation_PokemonRSE_Settings_H +#define PokemonAutomation_PokemonRSE_Settings_H #include "Common/Cpp/Options/StaticTextOption.h" #include "Common/Cpp/Options/BooleanCheckBoxOption.h" @@ -15,7 +15,7 @@ namespace PokemonAutomation{ namespace NintendoSwitch{ -namespace PokemonEmerald{ +namespace PokemonRSE{ class GameSettings : public BatchOption{ @@ -32,6 +32,9 @@ class GameSettings : public BatchOption{ TimeExpressionOption ENTER_GAME_MASH; TimeExpressionOption ENTER_GAME_WAIT; + FloatingPointOption SHINY_SOUND_THRESHOLD; + FloatingPointOption SHINY_SOUND_LOW_FREQUENCY; + }; diff --git a/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_StarterReset.cpp b/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_StarterReset.cpp new file mode 100644 index 000000000..efc4bc879 --- /dev/null +++ b/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_StarterReset.cpp @@ -0,0 +1,198 @@ +/* RS Starter Reset + * + * From: https://github.com/PokemonAutomation/Arduino-Source + * + */ + +#include "Common/Cpp/PrettyPrint.h" +#include "CommonFramework/Exceptions/OperationFailedException.h" +#include "CommonFramework/InferenceInfra/InferenceRoutines.h" +#include "CommonFramework/Notifications/ProgramNotifications.h" +#include "CommonFramework/Tools/VideoResolutionCheck.h" +#include "CommonFramework/Tools/StatsTracking.h" +#include "NintendoSwitch/Commands/NintendoSwitch_Commands_PushButtons.h" +#include "NintendoSwitch/Commands/NintendoSwitch_Commands_Superscalar.h" +#include "PokemonRSE/Inference/Sounds/PokemonRSE_ShinySoundDetector.h" +#include "PokemonRSE/PokemonRSE_Navigation.h" +#include "PokemonRSE_StarterReset.h" + +namespace PokemonAutomation{ +namespace NintendoSwitch{ +namespace PokemonRSE{ + +StarterReset_Descriptor::StarterReset_Descriptor() + : SingleSwitchProgramDescriptor( + "PokemonRSE:StarterReset", + "Pokemon RSE", "Starter Reset", + "ComputerControl/blob/master/Wiki/Programs/PokemonRSE/StarterReset.md", + "Soft reset for a shiny starter.", + //FeedbackType::VIDEO_AUDIO, + FeedbackType::NONE, + AllowCommandsWhenRunning::DISABLE_COMMANDS, + PABotBaseLevel::PABOTBASE_12KB + ) +{} + +struct StarterReset_Descriptor::Stats : public StatsTracker{ + Stats() + : resets(m_stats["Resets"]) + , poochyena(m_stats["Shiny Poochyena"]) + , shinystarter(m_stats["Shiny Starter"]) + { + m_display_order.emplace_back("Resets"); + m_display_order.emplace_back("Shiny Poochyena"); + m_display_order.emplace_back("Shiny Starter"); + } + std::atomic& resets; + std::atomic& poochyena; + std::atomic& shinystarter; +}; +std::unique_ptr StarterReset_Descriptor::make_stats() const{ + return std::unique_ptr(new Stats()); +} + +StarterReset::StarterReset() + : TARGET( + "Starter:
", + { + {Target::treecko, "treecko", "Treecko"}, + {Target::torchic, "torchic", "Torchic"}, + {Target::mudkip, "mudkip", "Mudkip"}, + }, + LockMode::LOCK_WHILE_RUNNING, + Target::treecko + ) + , NOTIFICATION_STATUS_UPDATE("Status Update", true, false, std::chrono::seconds(3600)) + , NOTIFICATIONS({ + &NOTIFICATION_STATUS_UPDATE, + &NOTIFICATION_PROGRAM_FINISH, + // &NOTIFICATION_ERROR_FATAL, + }) +{ + PA_ADD_OPTION(TARGET); + PA_ADD_OPTION(NOTIFICATIONS); +} + +void StarterReset::program(SingleSwitchProgramEnvironment& env, BotBaseContext& context){ + //assert_16_9_720p_min(env.logger(), env.console); + StarterReset_Descriptor::Stats& stats = env.current_stats(); + + /* + * Stand in front of birch's bag. + * + * text speed fast + * + * have to do the SR method instead of run away + * + * ONLY FOR RS, emerald has rng anyway + * + * This assumes no dry battery. If you have a dry battery, just do RNG. + */ + + /* + start at birch bag + + starter selection + + wild pooch appears, shiny check (audio?) + + go starter + + now shiny check + + track starter shiny, zig shiny, number of attempts, errors + + if not shiny, soft reset + + soft reset checks for dry battery and returns true or false! + + */ + + bool shiny_starter = false; + while (!shiny_starter) { + + float shiny_coefficient = 1.0; + ShinySoundDetector pooch_detector(env.console, [&](float error_coefficient) -> bool{ + // Warning: This callback will be run from a different thread than this function. + shiny_coefficient = error_coefficient; + return true; + }); + + int ret = run_until( + env.console, context, + [&](BotBaseContext& context){ + env.log("Opening bag and selecting starter."); + pbf_press_button(context, BUTTON_A, 40, 180); + + switch (TARGET) { + case Target::treecko: + pbf_press_dpad(context, DPAD_LEFT, 40, 100); + break; + case Target::torchic: + //Default cursor position, do nothing. + break; + case Target::mudkip: + pbf_press_dpad(context, DPAD_RIGHT, 40, 100); + break; + default: + OperationFailedException::fire( + env.console, ErrorReport::SEND_ERROR_REPORT, + "StarterReset: Invalid target." + ); + break; + } + pbf_mash_button(context, BUTTON_A, 540); + env.log("Starter selected. Checking for shiny Poochyena."); + + //Wait for battle to start and for Pooch battle cry + pbf_wait(context, 400); + + context.wait_for_all_requests(); + + }, + {{pooch_detector}} + ); + pooch_detector.throw_if_no_sound(); + if (ret == 0){ + env.log("Shiny Poochyena detected!"); + stats.poochyena++; + } + + ShinySoundDetector starter_detector(env.console, [&](float error_coefficient) -> bool{ + // Warning: This callback will be run from a different thread than this function. + shiny_coefficient = error_coefficient; + return true; + }); + + int ret2 = run_until( + env.console, context, + [&](BotBaseContext& context){ + env.log("Sending out selected starter."); + //Press A to send out your selected starter + pbf_press_button(context, BUTTON_A, 40, 400); + }, + {{starter_detector}} + ); + starter_detector.throw_if_no_sound(); + if (ret2 == 0){ + env.log("Shiny starter detected!"); + stats.shinystarter++; + shiny_starter = true; + break; + + } + + env.log("Soft resetting."); + soft_reset(env.program_info(), env.console, context); + stats.resets++; + } + + //TODO: if system set to nintendo switch, have go home when done option + + send_program_finished_notification(env, NOTIFICATION_PROGRAM_FINISH); +} + +} +} +} + diff --git a/SerialPrograms/Source/PokemonEmerald/Programs/ShinyHunting/PokemonEmerald_StarterReset.h b/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_StarterReset.h similarity index 71% rename from SerialPrograms/Source/PokemonEmerald/Programs/ShinyHunting/PokemonEmerald_StarterReset.h rename to SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_StarterReset.h index 28089655b..70a21e013 100644 --- a/SerialPrograms/Source/PokemonEmerald/Programs/ShinyHunting/PokemonEmerald_StarterReset.h +++ b/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_StarterReset.h @@ -1,20 +1,19 @@ -/* Emerald Starter Reset +/* RS Starter Reset * * From: https://github.com/PokemonAutomation/Arduino-Source * */ -#ifndef PokemonAutomation_PokemonEmerald_StarterReset_H -#define PokemonAutomation_PokemonEmerald_StarterReset_H +#ifndef PokemonAutomation_PokemonRSE_StarterReset_H +#define PokemonAutomation_PokemonRSE_StarterReset_H #include "Common/Cpp/Options/SimpleIntegerOption.h" #include "CommonFramework/Notifications/EventNotificationsTable.h" #include "NintendoSwitch/NintendoSwitch_SingleSwitchProgram.h" -#include "NintendoSwitch/Options/NintendoSwitch_GoHomeWhenDoneOption.h" namespace PokemonAutomation{ namespace NintendoSwitch{ -namespace PokemonEmerald{ +namespace PokemonRSE{ class StarterReset_Descriptor : public SingleSwitchProgramDescriptor{ public: @@ -29,8 +28,13 @@ class StarterReset : public SingleSwitchProgramInstance{ virtual void program(SingleSwitchProgramEnvironment& env, BotBaseContext& context) override; private: - SimpleIntegerOption ATTEMPTS; - GoHomeWhenDoneOption GO_HOME_WHEN_DONE; + enum class Target{ + treecko, + torchic, + mudkip, + }; + EnumDropdownOption TARGET; + EventNotificationOption NOTIFICATION_STATUS_UPDATE; EventNotificationsOption NOTIFICATIONS; }; From 347a94fbd473d359349b4efe73935a6f83bbf4b8 Mon Sep 17 00:00:00 2001 From: kichithewolf Date: Sat, 11 Jan 2025 15:25:34 -0500 Subject: [PATCH 04/11] configurable button timings, test sound listener --- SerialPrograms/CMakeLists.txt | 2 + .../PokemonRSE/PokemonRSE_Navigation.cpp | 5 +- .../Source/PokemonRSE/PokemonRSE_Panels.cpp | 20 +- .../Source/PokemonRSE/PokemonRSE_Settings.cpp | 36 ++-- .../Source/PokemonRSE/PokemonRSE_Settings.h | 7 +- .../ShinyHunting/PokemonRSE_StarterReset.cpp | 137 ++++++------ .../ShinyHunting/PokemonRSE_StarterReset.h | 6 + .../TestPrograms/PokemonRSE_SoundListener.cpp | 202 ++++++++++++++++++ .../TestPrograms/PokemonRSE_SoundListener.h | 48 +++++ 9 files changed, 368 insertions(+), 95 deletions(-) create mode 100644 SerialPrograms/Source/PokemonRSE/Programs/TestPrograms/PokemonRSE_SoundListener.cpp create mode 100644 SerialPrograms/Source/PokemonRSE/Programs/TestPrograms/PokemonRSE_SoundListener.h diff --git a/SerialPrograms/CMakeLists.txt b/SerialPrograms/CMakeLists.txt index 996769af2..ed4cba286 100644 --- a/SerialPrograms/CMakeLists.txt +++ b/SerialPrograms/CMakeLists.txt @@ -1295,6 +1295,8 @@ file(GLOB MAIN_SOURCES Source/PokemonRSE/Inference/Sounds/PokemonRSE_ShinySoundDetector.h Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_StarterReset.cpp Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_StarterReset.h + Source/PokemonRSE/Programs/TestPrograms/PokemonRSE_SoundListener.cpp + Source/PokemonRSE/Programs/TestPrograms/PokemonRSE_SoundListener.h Source/PokemonRSE/PokemonRSE_Navigation.cpp Source/PokemonRSE/PokemonRSE_Navigation.h Source/PokemonRSE/PokemonRSE_Panels.cpp diff --git a/SerialPrograms/Source/PokemonRSE/PokemonRSE_Navigation.cpp b/SerialPrograms/Source/PokemonRSE/PokemonRSE_Navigation.cpp index f86d87eea..f53a3e48a 100644 --- a/SerialPrograms/Source/PokemonRSE/PokemonRSE_Navigation.cpp +++ b/SerialPrograms/Source/PokemonRSE/PokemonRSE_Navigation.cpp @@ -12,6 +12,7 @@ #include "NintendoSwitch/NintendoSwitch_Settings.h" #include "NintendoSwitch/Commands/NintendoSwitch_Commands_PushButtons.h" #include "NintendoSwitch/Commands/NintendoSwitch_Commands_Superscalar.h" +#include "PokemonRSE/PokemonRSE_Settings.h" #include "PokemonRSE_Navigation.h" namespace PokemonAutomation{ @@ -23,13 +24,13 @@ void soft_reset(const ProgramInfo& info, ConsoleHandle& console, BotBaseContext& // A + B + Select + Start pbf_press_button(context, BUTTON_B | BUTTON_Y | BUTTON_MINUS | BUTTON_PLUS, 10, 180); - pbf_mash_button(context, BUTTON_PLUS, 500); + pbf_mash_button(context, BUTTON_PLUS, GameSettings::instance().START_BUTTON_MASH); context.wait_for_all_requests(); pbf_press_button(context, BUTTON_A, 20, 40); //Wait for game to load in - pbf_wait(context, 300); + pbf_wait(context, GameSettings::instance().ENTER_GAME_WAIT); context.wait_for_all_requests(); } diff --git a/SerialPrograms/Source/PokemonRSE/PokemonRSE_Panels.cpp b/SerialPrograms/Source/PokemonRSE/PokemonRSE_Panels.cpp index a3e7ed1d9..29c683a02 100644 --- a/SerialPrograms/Source/PokemonRSE/PokemonRSE_Panels.cpp +++ b/SerialPrograms/Source/PokemonRSE/PokemonRSE_Panels.cpp @@ -4,12 +4,14 @@ * */ +#include "CommonFramework/GlobalSettingsPanel.h" #include "Pokemon/Pokemon_Strings.h" #include "PokemonRSE_Panels.h" -//#include "PokemonSV_Settings.h" +#include "PokemonRSE_Settings.h" #include "Programs/ShinyHunting/PokemonRSE_StarterReset.h" +#include "Programs/TestPrograms/PokemonRSE_SoundListener.h" namespace PokemonAutomation{ namespace NintendoSwitch{ @@ -24,13 +26,21 @@ PanelListFactory::PanelListFactory() std::vector PanelListFactory::make_panels() const{ std::vector ret; - // ret.emplace_back("---- Settings ----"); TODO: Add device selection? - // ret.emplace_back(make_settings()); + ret.emplace_back("---- Settings ----"); //TODO: Add device selection? + ret.emplace_back(make_settings()); //ret.emplace_back("---- General ----"); - ret.emplace_back("---- Shiny Hunting ----"); - ret.emplace_back(make_single_switch_program()); + //ret.emplace_back("---- Shiny Hunting ----"); + + + if (PreloadSettings::instance().DEVELOPER_MODE){ + ret.emplace("---- WIP: Shiny Hunting (Audio only) ----"); + ret.emplace_back(make_single_switch_program()); + + ret.emplace_back("---- Developer Tools ----"); + ret.emplace_back(make_single_switch_program()); + } return ret; } diff --git a/SerialPrograms/Source/PokemonRSE/PokemonRSE_Settings.cpp b/SerialPrograms/Source/PokemonRSE/PokemonRSE_Settings.cpp index f9ba49e18..6c9459125 100644 --- a/SerialPrograms/Source/PokemonRSE/PokemonRSE_Settings.cpp +++ b/SerialPrograms/Source/PokemonRSE/PokemonRSE_Settings.cpp @@ -28,31 +28,20 @@ GameSettings::GameSettings() TICKS_PER_SECOND, "125" ) - , m_start_game_timings("Start Game Timings:") - , START_GAME_MASH( - "1. Start Game Mash:
Mash A for this long to start the game.", + , m_soft_reset_timings("Soft Reset Timings:") + , START_BUTTON_MASH( + "1. Start Button Mash:
Mash Start for this long after a soft reset to get to the main menu.", LockMode::LOCK_WHILE_RUNNING, TICKS_PER_SECOND, - "2 * TICKS_PER_SECOND" - ) - , START_GAME_WAIT( - "2. Start Game Wait:
Wait this long for the game to load.", - LockMode::LOCK_WHILE_RUNNING, - TICKS_PER_SECOND, - "60 * TICKS_PER_SECOND" - ) - , ENTER_GAME_MASH( - "3. Enter Game Mash:
Mash A for this long to enter the game.", - LockMode::LOCK_WHILE_RUNNING, - TICKS_PER_SECOND, - "5 * TICKS_PER_SECOND" + "4 * TICKS_PER_SECOND" ) , ENTER_GAME_WAIT( - "4. Enter Game Wait:
Wait this long for the game to enter the overworld.", + "2. Enter Game Wait:
Wait this long for the game to load.", LockMode::LOCK_WHILE_RUNNING, TICKS_PER_SECOND, - "60 * TICKS_PER_SECOND" + "3 * TICKS_PER_SECOND" ) + , m_shiny_audio_settings("Shiny Audio Settings:") , SHINY_SOUND_THRESHOLD( "Shiny Sound Threshold:
Maximum error coefficient to trigger a shiny detection.", LockMode::LOCK_WHILE_RUNNING, @@ -64,11 +53,12 @@ GameSettings::GameSettings() 5000, 0, 48000 ) { - PA_ADD_STATIC(m_start_game_timings); - PA_ADD_OPTION(START_GAME_MASH); - PA_ADD_OPTION(START_GAME_WAIT); - PA_ADD_OPTION(ENTER_GAME_MASH); + PA_ADD_STATIC(m_soft_reset_timings); + PA_ADD_OPTION(START_BUTTON_MASH); PA_ADD_OPTION(ENTER_GAME_WAIT); + PA_ADD_STATIC(m_shiny_audio_settings); + PA_ADD_OPTION(SHINY_SOUND_THRESHOLD); + PA_ADD_OPTION(SHINY_SOUND_LOW_FREQUENCY); } @@ -79,7 +69,7 @@ GameSettings_Descriptor::GameSettings_Descriptor() : PanelDescriptor( Color(), "PokemonRSE:GlobalSettings", - "Pokemon RSE", "Pokemon RSE Settings", + "Pokemon RSE", "Pokemon Settings", "ComputerControl/blob/master/Wiki/Programs/PokemonRSE/RSESettings.md", "Global Pokemon RSE Settings" ) diff --git a/SerialPrograms/Source/PokemonRSE/PokemonRSE_Settings.h b/SerialPrograms/Source/PokemonRSE/PokemonRSE_Settings.h index 5fa34d01f..f7962638b 100644 --- a/SerialPrograms/Source/PokemonRSE/PokemonRSE_Settings.h +++ b/SerialPrograms/Source/PokemonRSE/PokemonRSE_Settings.h @@ -26,12 +26,11 @@ class GameSettings : public BatchOption{ SectionDividerOption m_menu_navigation; TimeExpressionOption GAME_TO_HOME_DELAY; - SectionDividerOption m_start_game_timings; - TimeExpressionOption START_GAME_MASH; - TimeExpressionOption START_GAME_WAIT; - TimeExpressionOption ENTER_GAME_MASH; + SectionDividerOption m_soft_reset_timings; + TimeExpressionOption START_BUTTON_MASH; TimeExpressionOption ENTER_GAME_WAIT; + SectionDividerOption m_shiny_audio_settings; FloatingPointOption SHINY_SOUND_THRESHOLD; FloatingPointOption SHINY_SOUND_LOW_FREQUENCY; diff --git a/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_StarterReset.cpp b/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_StarterReset.cpp index efc4bc879..9ee171898 100644 --- a/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_StarterReset.cpp +++ b/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_StarterReset.cpp @@ -25,7 +25,7 @@ StarterReset_Descriptor::StarterReset_Descriptor() "PokemonRSE:StarterReset", "Pokemon RSE", "Starter Reset", "ComputerControl/blob/master/Wiki/Programs/PokemonRSE/StarterReset.md", - "Soft reset for a shiny starter.", + "(Audio only) Soft reset for a shiny starter. WIP, audio recognition does not work well.", //FeedbackType::VIDEO_AUDIO, FeedbackType::NONE, AllowCommandsWhenRunning::DISABLE_COMMANDS, @@ -62,11 +62,34 @@ StarterReset::StarterReset() LockMode::LOCK_WHILE_RUNNING, Target::treecko ) + , POOCH_WAIT( + "Battle start wait:
Time for battle to start and for Poochyena to appear. Make sure to add extra time in case the Poochyena is shiny.", + LockMode::LOCK_WHILE_RUNNING, + TICKS_PER_SECOND, + "6 * TICKS_PER_SECOND" + ) + , STARTER_WAIT( + "Send out starter wait:
After pressing A to send out your selected starter, wait this long for the animation. Make sure to add extra time in case it is shiny.", + LockMode::LOCK_WHILE_RUNNING, + TICKS_PER_SECOND, + "6 * TICKS_PER_SECOND" + ) + , NOTIFICATION_SHINY_POOCH( + "Shiny Poochyena", + false, false, + {"Notifs"} + ) + , NOTIFICATION_SHINY_STARTER( + "Shiny Starter", + true, false, + {"Notifs", "Showcase"} + ) , NOTIFICATION_STATUS_UPDATE("Status Update", true, false, std::chrono::seconds(3600)) , NOTIFICATIONS({ + &NOTIFICATION_SHINY_POOCH, + &NOTIFICATION_SHINY_STARTER, &NOTIFICATION_STATUS_UPDATE, &NOTIFICATION_PROGRAM_FINISH, - // &NOTIFICATION_ERROR_FATAL, }) { PA_ADD_OPTION(TARGET); @@ -78,74 +101,51 @@ void StarterReset::program(SingleSwitchProgramEnvironment& env, BotBaseContext& StarterReset_Descriptor::Stats& stats = env.current_stats(); /* - * Stand in front of birch's bag. - * - * text speed fast + * Settings: Text Speed fast. + * Setup: Stand in front of the Professor's bag and save the game. * - * have to do the SR method instead of run away + * Required to fight, so have to do the SR method instead of run away + * Soft reset programs are only for Ruby/Sapphire, as Emerald has the 0 seed issue. * - * ONLY FOR RS, emerald has rng anyway - * - * This assumes no dry battery. If you have a dry battery, just do RNG. - */ - - /* - start at birch bag - - starter selection - - wild pooch appears, shiny check (audio?) - - go starter - - now shiny check - - track starter shiny, zig shiny, number of attempts, errors - - if not shiny, soft reset - - soft reset checks for dry battery and returns true or false! - + * This also assumes no dry battery. */ bool shiny_starter = false; while (!shiny_starter) { - float shiny_coefficient = 1.0; ShinySoundDetector pooch_detector(env.console, [&](float error_coefficient) -> bool{ - // Warning: This callback will be run from a different thread than this function. - shiny_coefficient = error_coefficient; return true; }); + env.log("Opening bag and selecting starter."); + pbf_press_button(context, BUTTON_A, 40, 180); + + switch (TARGET) { + case Target::treecko: + pbf_press_dpad(context, DPAD_LEFT, 40, 100); + break; + case Target::torchic: + //Default cursor position, do nothing. + break; + case Target::mudkip: + pbf_press_dpad(context, DPAD_RIGHT, 40, 100); + break; + default: + OperationFailedException::fire( + env.console, ErrorReport::SEND_ERROR_REPORT, + "StarterReset: Invalid target." + ); + break; + } + pbf_mash_button(context, BUTTON_A, 540); + env.log("Starter selected. Checking for shiny Poochyena."); + + int ret = run_until( env.console, context, [&](BotBaseContext& context){ - env.log("Opening bag and selecting starter."); - pbf_press_button(context, BUTTON_A, 40, 180); - - switch (TARGET) { - case Target::treecko: - pbf_press_dpad(context, DPAD_LEFT, 40, 100); - break; - case Target::torchic: - //Default cursor position, do nothing. - break; - case Target::mudkip: - pbf_press_dpad(context, DPAD_RIGHT, 40, 100); - break; - default: - OperationFailedException::fire( - env.console, ErrorReport::SEND_ERROR_REPORT, - "StarterReset: Invalid target." - ); - break; - } - pbf_mash_button(context, BUTTON_A, 540); - env.log("Starter selected. Checking for shiny Poochyena."); - //Wait for battle to start and for Pooch battle cry - pbf_wait(context, 400); + pbf_wait(context, POOCH_WAIT); context.wait_for_all_requests(); @@ -156,20 +156,26 @@ void StarterReset::program(SingleSwitchProgramEnvironment& env, BotBaseContext& if (ret == 0){ env.log("Shiny Poochyena detected!"); stats.poochyena++; + send_program_status_notification(env, NOTIFICATION_SHINY_POOCH, "Shiny Poochyena found."); + } + else { + env.log("Poochyena is not shiny."); } ShinySoundDetector starter_detector(env.console, [&](float error_coefficient) -> bool{ - // Warning: This callback will be run from a different thread than this function. - shiny_coefficient = error_coefficient; return true; }); + //Press A to send out your selected starter + env.log("Sending out selected starter."); + pbf_press_button(context, BUTTON_A, 40, 40); + int ret2 = run_until( env.console, context, [&](BotBaseContext& context){ - env.log("Sending out selected starter."); - //Press A to send out your selected starter - pbf_press_button(context, BUTTON_A, 40, 400); + env.log("Wait for starter to come out."); + pbf_wait(context, STARTER_WAIT); + context.wait_for_all_requests(); }, {{starter_detector}} ); @@ -177,12 +183,21 @@ void StarterReset::program(SingleSwitchProgramEnvironment& env, BotBaseContext& if (ret2 == 0){ env.log("Shiny starter detected!"); stats.shinystarter++; + + send_program_status_notification(env, NOTIFICATION_SHINY_STARTER, "Shiny starter found!"); + shiny_starter = true; break; - + } + else { + env.log("Starter is not shiny."); } env.log("Soft resetting."); + send_program_status_notification( + env, NOTIFICATION_STATUS_UPDATE, + "Soft resetting." + ); soft_reset(env.program_info(), env.console, context); stats.resets++; } diff --git a/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_StarterReset.h b/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_StarterReset.h index 70a21e013..b92ee48ea 100644 --- a/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_StarterReset.h +++ b/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_StarterReset.h @@ -8,6 +8,7 @@ #define PokemonAutomation_PokemonRSE_StarterReset_H #include "Common/Cpp/Options/SimpleIntegerOption.h" +#include "Common/Cpp/Options/TimeExpressionOption.h" #include "CommonFramework/Notifications/EventNotificationsTable.h" #include "NintendoSwitch/NintendoSwitch_SingleSwitchProgram.h" @@ -35,6 +36,11 @@ class StarterReset : public SingleSwitchProgramInstance{ }; EnumDropdownOption TARGET; + TimeExpressionOption POOCH_WAIT; + TimeExpressionOption STARTER_WAIT; + + EventNotificationOption NOTIFICATION_SHINY_POOCH; + EventNotificationOption NOTIFICATION_SHINY_STARTER; EventNotificationOption NOTIFICATION_STATUS_UPDATE; EventNotificationsOption NOTIFICATIONS; }; diff --git a/SerialPrograms/Source/PokemonRSE/Programs/TestPrograms/PokemonRSE_SoundListener.cpp b/SerialPrograms/Source/PokemonRSE/Programs/TestPrograms/PokemonRSE_SoundListener.cpp new file mode 100644 index 000000000..5463aa934 --- /dev/null +++ b/SerialPrograms/Source/PokemonRSE/Programs/TestPrograms/PokemonRSE_SoundListener.cpp @@ -0,0 +1,202 @@ +/* Sound Listener + * + * From: https://github.com/PokemonAutomation/Arduino-Source + * + */ + +#include +#include +#include +#include +#include +#include +#include "Common/Cpp/Exceptions.h" +#include "Common/Cpp/Containers/AlignedVector.tpp" +#include "CommonFramework/AudioPipeline/AudioFeed.h" +#include "CommonFramework/AudioPipeline/AudioTemplate.h" +#include "CommonFramework/InferenceInfra/InferenceSession.h" +#include "CommonFramework/Inference/AudioTemplateCache.h" +#include "CommonFramework/Inference/SpectrogramMatcher.h" +#include "CommonFramework/Tools/StatsTracking.h" +#include "NintendoSwitch/Commands/NintendoSwitch_Commands_PushButtons.h" +#include "NintendoSwitch/NintendoSwitch_Settings.h" +#include "Pokemon/Pokemon_Strings.h" +#include "PokemonRSE/PokemonRSE_Settings.h" +#include "PokemonRSE/Inference/Sounds/PokemonRSE_ShinySoundDetector.h" +#include "PokemonRSE_SoundListener.h" + +#include + +namespace PokemonAutomation{ +namespace NintendoSwitch{ +namespace PokemonRSE{ + using namespace Pokemon; + + +SoundListener_Descriptor::SoundListener_Descriptor() + : SingleSwitchProgramDescriptor( + "PokemonRSE:SoundListener", + STRING_POKEMON + " RSE", "Sound Listener", + "", + "Test sound detectors listening to audio stream.", + FeedbackType::NONE, AllowCommandsWhenRunning::ENABLE_COMMANDS, + PABotBaseLevel::PABOTBASE_12KB + ) +{} + + +SoundListener::SoundListener() + : SOUND_TYPE("Which Sound to Detect", + { + {SoundType::SHINY, "shiny", "Shiny Sound"}, + }, + LockMode::LOCK_WHILE_RUNNING, + SoundType::SHINY + ) + , STOP_ON_DETECTED_SOUND( + "Stop on the detected sound
Stop program when the sound is detected.", + LockMode::LOCK_WHILE_RUNNING, + false + ) +{ + PA_ADD_OPTION(SOUND_TYPE); + PA_ADD_OPTION(STOP_ON_DETECTED_SOUND); +} + + +// void search_alpha_roar_from_audio_dump(); + +void SoundListener::program(SingleSwitchProgramEnvironment& env, BotBaseContext& context){ + // search_alpha_roar_from_audio_dump(); + // return; + + std::cout << "Running audio test program." << std::endl; + + std::shared_ptr detector; + auto action = [&](float error_coefficient) -> bool{ + // This lambda function will be called when the sound is detected. + // Its return will determine whether to stop the program: + return STOP_ON_DETECTED_SOUND; + }; + + SoundType type = SOUND_TYPE; + switch (type){ + case SoundType::SHINY: + detector = std::make_shared(env.console, action); + break; + default: + throw InternalProgramError( + &env.logger(), PA_CURRENT_FUNCTION, + "Not such sound detector as sound type " + std::to_string((size_t)type) + ); + return; + } + + InferenceSession session( + context, env.console, + {{*detector, std::chrono::milliseconds(20)}} + ); + context.wait_until_cancel(); + + std::cout << "Audio test program Sound listener finished." << std::endl; +} + + +// A function used to search for the alpha roar on LA audio dump. +// But we didn't find the shound sound :P +void search_alpha_roar_from_audio_dump(){ + + const size_t SAMPLE_RATE = 48000; + + SpectrogramMatcher matcher( + "Alpha Roar", + AudioTemplateCache::instance().get_throw("PokemonBDSP/AlphaRoar", SAMPLE_RATE), + SpectrogramMatcher::Mode::RAW, SAMPLE_RATE, + 100.0 + ); + + // std::string file_listFile = "./scripts/short_audio_files.txt"; + std::string file_listFile = "1.txt"; + // std::string file_listFile = "./scripts/all_audio_files.txt"; + std::ifstream fin(file_listFile.c_str()); + std::vector file_list; + while(!fin.eof()){ + std::string line; + std::getline(fin, line); + file_list.push_back(line); + fin >> std::ws; + } + std::cout << "File num " << file_list.size() << std::endl; + + std::map closest_files; + + std::ofstream fout("file_check_output.txt"); + + for(size_t fileIdx = 0; fileIdx < file_list.size(); fileIdx++){ + matcher.clear(); + + + const auto& path = file_list[fileIdx]; + std::ostringstream os; + os << "File " << fileIdx << "/" << file_list.size() << " " << path << " "; + AudioTemplate audio = loadAudioTemplate(path); + if (audio.numWindows() == 0){ + os << "Fail" << std::endl; + fout << os.str(); + std::cout << os.str() << std::flush; + continue; + } + + // audio.scale(2.0); + + os << "#W " << audio.numWindows() << " "; + + // match! + float minScore = FLT_MAX; + std::vector new_spectrums; + size_t numStreamWindows = std::max(matcher.numMatchedWindows(), audio.numWindows()); + for(size_t audioIdx = 0; audioIdx < numStreamWindows; audioIdx++){ + new_spectrums.clear(); + AlignedVector freqVector(audio.numFrequencies()); + if (audioIdx < audio.numWindows()){ + const float * freq = audio.getWindow(audioIdx); + memcpy(freqVector.data(), freq, sizeof(float) * audio.numFrequencies()); + }else{ + // add zero-freq window + } + new_spectrums.emplace_back( + audioIdx, SAMPLE_RATE, + std::make_unique>(std::move(freqVector)) + ); + float score = matcher.match(new_spectrums); + minScore = std::min(score, minScore); + } // end audio Idx + + os << "dist " << minScore << std::endl; + fout << os.str(); + std::cout << os.str() << std::flush; + + closest_files.emplace(minScore, path); + } + + fout.close(); + + auto it = closest_files.begin(); + std::cout << "--------------" << std::endl; + fout.open("file_check_output_sorted.txt"); + for(int i = 0; it != closest_files.end(); i++, it++){ + if (i < 40) + std::cout << it->first << ", " << it->second << std::endl; + fout << it->first << ", " << it->second << std::endl; + } + fout.close(); + return; +} + + + + + +} +} +} diff --git a/SerialPrograms/Source/PokemonRSE/Programs/TestPrograms/PokemonRSE_SoundListener.h b/SerialPrograms/Source/PokemonRSE/Programs/TestPrograms/PokemonRSE_SoundListener.h new file mode 100644 index 000000000..e178618d9 --- /dev/null +++ b/SerialPrograms/Source/PokemonRSE/Programs/TestPrograms/PokemonRSE_SoundListener.h @@ -0,0 +1,48 @@ +/* Sound Listener + * + * From: https://github.com/PokemonAutomation/Arduino-Source + * + * Debug program to test all kinds of sound detectors. + */ + +#ifndef PokemonAutomation_PokemonRSE_SoundListener_H +#define PokemonAutomation_PokemonRSE_SoundListener_H + +#include "Common/Cpp/Options/BooleanCheckBoxOption.h" +#include "Common/Cpp/Options/EnumDropdownOption.h" +#include "NintendoSwitch/NintendoSwitch_SingleSwitchProgram.h" +#include "NintendoSwitch/Options/NintendoSwitch_GoHomeWhenDoneOption.h" + +namespace PokemonAutomation{ +namespace NintendoSwitch{ +namespace PokemonRSE{ + + +class SoundListener_Descriptor : public SingleSwitchProgramDescriptor{ +public: + SoundListener_Descriptor(); +}; + + +class SoundListener : public SingleSwitchProgramInstance{ +public: + SoundListener(); + + virtual void program(SingleSwitchProgramEnvironment& env, BotBaseContext& context) override; + +private: + enum class SoundType{ + SHINY, + }; + + EnumDropdownOption SOUND_TYPE; + BooleanCheckBoxOption STOP_ON_DETECTED_SOUND; +}; + + + + +} +} +} +#endif From c62ae24c6d6e67c31ff6c0d104a79b6fff017158 Mon Sep 17 00:00:00 2001 From: kichithewolf Date: Sat, 11 Jan 2025 16:56:15 -0500 Subject: [PATCH 05/11] audio only feedback type, rename program --- SerialPrograms/CMakeLists.txt | 4 +-- .../Source/CommonFramework/Globals.h | 1 + .../Panels/UI/PanelElements.cpp | 6 +++++ .../Source/PokemonRSE/PokemonRSE_Panels.cpp | 8 +++--- .../Source/PokemonRSE/PokemonRSE_Settings.cpp | 2 +- ...t.cpp => PokemonRSE_AudioStarterReset.cpp} | 27 +++++++++---------- ...Reset.h => PokemonRSE_AudioStarterReset.h} | 12 ++++----- 7 files changed, 33 insertions(+), 27 deletions(-) rename SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/{PokemonRSE_StarterReset.cpp => PokemonRSE_AudioStarterReset.cpp} (87%) rename SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/{PokemonRSE_StarterReset.h => PokemonRSE_AudioStarterReset.h} (77%) diff --git a/SerialPrograms/CMakeLists.txt b/SerialPrograms/CMakeLists.txt index ed4cba286..8977fe35b 100644 --- a/SerialPrograms/CMakeLists.txt +++ b/SerialPrograms/CMakeLists.txt @@ -1293,8 +1293,8 @@ file(GLOB MAIN_SOURCES Source/PokemonLA/Resources/PokemonLA_WeatherAndTimeIcons.h Source/PokemonRSE/Inference/Sounds/PokemonRSE_ShinySoundDetector.cpp Source/PokemonRSE/Inference/Sounds/PokemonRSE_ShinySoundDetector.h - Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_StarterReset.cpp - Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_StarterReset.h + Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_AudioStarterReset.cpp + Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_AudioStarterReset.h Source/PokemonRSE/Programs/TestPrograms/PokemonRSE_SoundListener.cpp Source/PokemonRSE/Programs/TestPrograms/PokemonRSE_SoundListener.h Source/PokemonRSE/PokemonRSE_Navigation.cpp diff --git a/SerialPrograms/Source/CommonFramework/Globals.h b/SerialPrograms/Source/CommonFramework/Globals.h index 139d8e6d5..e8091dcfd 100644 --- a/SerialPrograms/Source/CommonFramework/Globals.h +++ b/SerialPrograms/Source/CommonFramework/Globals.h @@ -69,6 +69,7 @@ enum class FeedbackType{ NONE, OPTIONAL_, // Naming conflict with macro. REQUIRED, + AUDIO, VIDEO_AUDIO, }; diff --git a/SerialPrograms/Source/CommonFramework/Panels/UI/PanelElements.cpp b/SerialPrograms/Source/CommonFramework/Panels/UI/PanelElements.cpp index 298751958..e10c3204a 100644 --- a/SerialPrograms/Source/CommonFramework/Panels/UI/PanelElements.cpp +++ b/SerialPrograms/Source/CommonFramework/Panels/UI/PanelElements.cpp @@ -81,6 +81,12 @@ CollapsibleGroupBox* make_panel_header( header ); break; + case FeedbackType::AUDIO: + text = new QLabel( + "(This program requires audio feedback. Please make sure you choose the correct audio device.)", + header + ); + break; case FeedbackType::VIDEO_AUDIO: text = new QLabel( "(This program requires video and audio feedback. Please make sure you choose the correct capture device, as well as the correct audio device.)", diff --git a/SerialPrograms/Source/PokemonRSE/PokemonRSE_Panels.cpp b/SerialPrograms/Source/PokemonRSE/PokemonRSE_Panels.cpp index 29c683a02..b1fa83f5b 100644 --- a/SerialPrograms/Source/PokemonRSE/PokemonRSE_Panels.cpp +++ b/SerialPrograms/Source/PokemonRSE/PokemonRSE_Panels.cpp @@ -10,7 +10,7 @@ #include "PokemonRSE_Settings.h" -#include "Programs/ShinyHunting/PokemonRSE_StarterReset.h" +#include "Programs/ShinyHunting/PokemonRSE_AudioStarterReset.h" #include "Programs/TestPrograms/PokemonRSE_SoundListener.h" namespace PokemonAutomation{ @@ -20,7 +20,7 @@ namespace PokemonRSE{ PanelListFactory::PanelListFactory() - : PanelListDescriptor("Pokemon Ruby, Sapphire, and Emerald") + : PanelListDescriptor("Pokemon Ruby and Sapphire, Pokemon Emerald") {} std::vector PanelListFactory::make_panels() const{ @@ -35,8 +35,8 @@ std::vector PanelListFactory::make_panels() const{ if (PreloadSettings::instance().DEVELOPER_MODE){ - ret.emplace("---- WIP: Shiny Hunting (Audio only) ----"); - ret.emplace_back(make_single_switch_program()); + ret.emplace_back("---- WIP: Shiny Hunting (Audio only) ----"); + ret.emplace_back(make_single_switch_program()); ret.emplace_back("---- Developer Tools ----"); ret.emplace_back(make_single_switch_program()); diff --git a/SerialPrograms/Source/PokemonRSE/PokemonRSE_Settings.cpp b/SerialPrograms/Source/PokemonRSE/PokemonRSE_Settings.cpp index 6c9459125..a34d8ef00 100644 --- a/SerialPrograms/Source/PokemonRSE/PokemonRSE_Settings.cpp +++ b/SerialPrograms/Source/PokemonRSE/PokemonRSE_Settings.cpp @@ -45,7 +45,7 @@ GameSettings::GameSettings() , SHINY_SOUND_THRESHOLD( "Shiny Sound Threshold:
Maximum error coefficient to trigger a shiny detection.", LockMode::LOCK_WHILE_RUNNING, - 0.87, 0, 1.0 + 0.97, 0, 1.0 ) , SHINY_SOUND_LOW_FREQUENCY( "Shiny Sound Low Frequency (Hz):
High pass filter frequency for shiny sound.", diff --git a/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_StarterReset.cpp b/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_AudioStarterReset.cpp similarity index 87% rename from SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_StarterReset.cpp rename to SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_AudioStarterReset.cpp index 9ee171898..4fa45a7e3 100644 --- a/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_StarterReset.cpp +++ b/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_AudioStarterReset.cpp @@ -14,26 +14,25 @@ #include "NintendoSwitch/Commands/NintendoSwitch_Commands_Superscalar.h" #include "PokemonRSE/Inference/Sounds/PokemonRSE_ShinySoundDetector.h" #include "PokemonRSE/PokemonRSE_Navigation.h" -#include "PokemonRSE_StarterReset.h" +#include "PokemonRSE_AudioStarterReset.h" namespace PokemonAutomation{ namespace NintendoSwitch{ namespace PokemonRSE{ -StarterReset_Descriptor::StarterReset_Descriptor() +AudioStarterReset_Descriptor::AudioStarterReset_Descriptor() : SingleSwitchProgramDescriptor( - "PokemonRSE:StarterReset", - "Pokemon RSE", "Starter Reset", - "ComputerControl/blob/master/Wiki/Programs/PokemonRSE/StarterReset.md", - "(Audio only) Soft reset for a shiny starter. WIP, audio recognition does not work well.", - //FeedbackType::VIDEO_AUDIO, - FeedbackType::NONE, + "PokemonRSE:AudioStarterReset", + "Pokemon RSE", "[RS] Starter Reset - Audio only", + "ComputerControl/blob/master/Wiki/Programs/PokemonRSE/AudioStarterReset.md", + "Soft reset for a shiny starter. Ruby and Sapphire only. WIP, audio recognition does not work well.", + FeedbackType::AUDIO, AllowCommandsWhenRunning::DISABLE_COMMANDS, PABotBaseLevel::PABOTBASE_12KB ) {} -struct StarterReset_Descriptor::Stats : public StatsTracker{ +struct AudioStarterReset_Descriptor::Stats : public StatsTracker{ Stats() : resets(m_stats["Resets"]) , poochyena(m_stats["Shiny Poochyena"]) @@ -47,11 +46,11 @@ struct StarterReset_Descriptor::Stats : public StatsTracker{ std::atomic& poochyena; std::atomic& shinystarter; }; -std::unique_ptr StarterReset_Descriptor::make_stats() const{ +std::unique_ptr AudioStarterReset_Descriptor::make_stats() const{ return std::unique_ptr(new Stats()); } -StarterReset::StarterReset() +AudioStarterReset::AudioStarterReset() : TARGET( "Starter:
", { @@ -96,9 +95,9 @@ StarterReset::StarterReset() PA_ADD_OPTION(NOTIFICATIONS); } -void StarterReset::program(SingleSwitchProgramEnvironment& env, BotBaseContext& context){ +void AudioStarterReset::program(SingleSwitchProgramEnvironment& env, BotBaseContext& context){ //assert_16_9_720p_min(env.logger(), env.console); - StarterReset_Descriptor::Stats& stats = env.current_stats(); + AudioStarterReset_Descriptor::Stats& stats = env.current_stats(); /* * Settings: Text Speed fast. @@ -133,7 +132,7 @@ void StarterReset::program(SingleSwitchProgramEnvironment& env, BotBaseContext& default: OperationFailedException::fire( env.console, ErrorReport::SEND_ERROR_REPORT, - "StarterReset: Invalid target." + "AudioStarterReset: Invalid target." ); break; } diff --git a/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_StarterReset.h b/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_AudioStarterReset.h similarity index 77% rename from SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_StarterReset.h rename to SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_AudioStarterReset.h index b92ee48ea..6e4537afd 100644 --- a/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_StarterReset.h +++ b/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_AudioStarterReset.h @@ -4,8 +4,8 @@ * */ -#ifndef PokemonAutomation_PokemonRSE_StarterReset_H -#define PokemonAutomation_PokemonRSE_StarterReset_H +#ifndef PokemonAutomation_PokemonRSE_AudioStarterReset_H +#define PokemonAutomation_PokemonRSE_AudioStarterReset_H #include "Common/Cpp/Options/SimpleIntegerOption.h" #include "Common/Cpp/Options/TimeExpressionOption.h" @@ -16,16 +16,16 @@ namespace PokemonAutomation{ namespace NintendoSwitch{ namespace PokemonRSE{ -class StarterReset_Descriptor : public SingleSwitchProgramDescriptor{ +class AudioStarterReset_Descriptor : public SingleSwitchProgramDescriptor{ public: - StarterReset_Descriptor(); + AudioStarterReset_Descriptor(); struct Stats; virtual std::unique_ptr make_stats() const override; }; -class StarterReset : public SingleSwitchProgramInstance{ +class AudioStarterReset : public SingleSwitchProgramInstance{ public: - StarterReset(); + AudioStarterReset(); virtual void program(SingleSwitchProgramEnvironment& env, BotBaseContext& context) override; private: From 0b2b030950f54635543d371dda3d6315e0ec8b22 Mon Sep 17 00:00:00 2001 From: kichithewolf Date: Sun, 12 Jan 2025 15:35:32 -0500 Subject: [PATCH 06/11] shiny reset, battle menu+shiny number detect --- SerialPrograms/CMakeLists.txt | 6 + .../Dialogs/PokemonRSE_DialogDetector.cpp | 73 +++++++ .../Dialogs/PokemonRSE_DialogDetector.h | 99 ++++++++++ .../PokemonRSE_ShinyNumberDetector.cpp | 62 ++++++ .../PokemonRSE_ShinyNumberDetector.h | 35 ++++ .../Source/PokemonRSE/PokemonRSE_Panels.cpp | 4 +- .../ShinyHunting/PokemonRSE_StarterReset.cpp | 184 ++++++++++++++++++ .../ShinyHunting/PokemonRSE_StarterReset.h | 52 +++++ 8 files changed, 514 insertions(+), 1 deletion(-) create mode 100644 SerialPrograms/Source/PokemonRSE/Inference/Dialogs/PokemonRSE_DialogDetector.cpp create mode 100644 SerialPrograms/Source/PokemonRSE/Inference/Dialogs/PokemonRSE_DialogDetector.h create mode 100644 SerialPrograms/Source/PokemonRSE/Inference/PokemonRSE_ShinyNumberDetector.cpp create mode 100644 SerialPrograms/Source/PokemonRSE/Inference/PokemonRSE_ShinyNumberDetector.h create mode 100644 SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_StarterReset.cpp create mode 100644 SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_StarterReset.h diff --git a/SerialPrograms/CMakeLists.txt b/SerialPrograms/CMakeLists.txt index 8977fe35b..ea60511b2 100644 --- a/SerialPrograms/CMakeLists.txt +++ b/SerialPrograms/CMakeLists.txt @@ -1291,10 +1291,16 @@ file(GLOB MAIN_SOURCES Source/PokemonLA/Resources/PokemonLA_PokemonSprites.h Source/PokemonLA/Resources/PokemonLA_WeatherAndTimeIcons.cpp Source/PokemonLA/Resources/PokemonLA_WeatherAndTimeIcons.h + Source/PokemonRSE/Inference/Dialogs/PokemonRSE_DialogDetector.cpp + Source/PokemonRSE/Inference/Dialogs/PokemonRSE_DialogDetector.h Source/PokemonRSE/Inference/Sounds/PokemonRSE_ShinySoundDetector.cpp Source/PokemonRSE/Inference/Sounds/PokemonRSE_ShinySoundDetector.h + Source/PokemonRSE/Inference/PokemonRSE_ShinyNumberDetector.cpp + Source/PokemonRSE/Inference/PokemonRSE_ShinyNumberDetector.h Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_AudioStarterReset.cpp Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_AudioStarterReset.h + Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_StarterReset.cpp + Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_StarterReset.h Source/PokemonRSE/Programs/TestPrograms/PokemonRSE_SoundListener.cpp Source/PokemonRSE/Programs/TestPrograms/PokemonRSE_SoundListener.h Source/PokemonRSE/PokemonRSE_Navigation.cpp diff --git a/SerialPrograms/Source/PokemonRSE/Inference/Dialogs/PokemonRSE_DialogDetector.cpp b/SerialPrograms/Source/PokemonRSE/Inference/Dialogs/PokemonRSE_DialogDetector.cpp new file mode 100644 index 000000000..6cca901b5 --- /dev/null +++ b/SerialPrograms/Source/PokemonRSE/Inference/Dialogs/PokemonRSE_DialogDetector.cpp @@ -0,0 +1,73 @@ +/* Dialog Detector + * + * From: https://github.com/PokemonAutomation/Arduino-Source + * + */ + +#include "CommonFramework/ImageTools/SolidColorTest.h" +#include "CommonFramework/VideoPipeline/VideoOverlayScopes.h" +#include "PokemonRSE_DialogDetector.h" + +namespace PokemonAutomation{ +namespace NintendoSwitch{ +namespace PokemonRSE{ + +/* +DialogDetector::DialogDetector(Color color) + : m_left_box(0.155, 0.727, 0.015, 0.168) + , m_right_box(0.837, 0.729, 0.008, 0.161) +{} +void DialogDetector::make_overlays(VideoOverlaySet& items) const{ + items.add(COLOR_RED, m_left_box); + items.add(COLOR_RED, m_right_box); +} +bool DialogDetector::detect(const ImageViewRGB32& screen) const{ + ImageViewRGB32 left_image = extract_box_reference(screen, m_left_box); + ImageViewRGB32 right_image = extract_box_reference(screen, m_right_box); + if (is_solid(left_image, { 0.335, 0.331, 0.332 }) && is_solid(right_image, { 0.335, 0.331, 0.332 })){ + return true; + } + return false; +} + + +BattleDialogDetector::BattleDialogDetector(Color color) + : m_left_box(0.155, 0.727, 0.015, 0.168) + , m_right_box(0.837, 0.729, 0.008, 0.161) +{} +void BattleDialogDetector::make_overlays(VideoOverlaySet& items) const{ + items.add(COLOR_RED, m_left_box); + items.add(COLOR_RED, m_right_box); +} +bool BattleDialogDetector::detect(const ImageViewRGB32& screen) const{ + ImageViewRGB32 left_image = extract_box_reference(screen, m_left_box); + ImageViewRGB32 right_image = extract_box_reference(screen, m_right_box); + if (is_solid(left_image, { 0.25, 0.38, 0.369 }) && is_solid(right_image, { 0.25, 0.38, 0.369 })){ + return true; + } + return false; +} +*/ + +BattleMenuDetector::BattleMenuDetector(Color color) + : m_left_box(0.155, 0.727, 0.015, 0.168) + , m_right_box(0.821, 0.725, 0.030, 0.181) +{} +void BattleMenuDetector::make_overlays(VideoOverlaySet& items) const{ + items.add(COLOR_RED, m_left_box); + items.add(COLOR_RED, m_right_box); +} +bool BattleMenuDetector::detect(const ImageViewRGB32& screen) const{ + ImageViewRGB32 left_image = extract_box_reference(screen, m_left_box); + ImageViewRGB32 right_image = extract_box_reference(screen, m_right_box); + if (is_solid(left_image, { 0.335, 0.331, 0.332 }) && is_solid(right_image, { 0.25, 0.38, 0.369 })){ + return true; + } + return false; +} + + + +} +} +} diff --git a/SerialPrograms/Source/PokemonRSE/Inference/Dialogs/PokemonRSE_DialogDetector.h b/SerialPrograms/Source/PokemonRSE/Inference/Dialogs/PokemonRSE_DialogDetector.h new file mode 100644 index 000000000..2e21c0b57 --- /dev/null +++ b/SerialPrograms/Source/PokemonRSE/Inference/Dialogs/PokemonRSE_DialogDetector.h @@ -0,0 +1,99 @@ +/* Dialog Detector + * + * From: https://github.com/PokemonAutomation/Arduino-Source + * + */ + +#ifndef PokemonAutomation_PokemonRSE_DialogDetector_H +#define PokemonAutomation_PokemonRSE_DialogDetector_H + +#include +#include +//#include "CommonFramework/Logging/Logger.h" +#include "CommonFramework/VideoPipeline/VideoOverlayScopes.h" +#include "Common/Cpp/Color.h" +#include "CommonFramework/ImageTools/ImageBoxes.h" +#include "CommonFramework/InferenceInfra/VisualInferenceCallback.h" +#include "CommonFramework/Inference/VisualDetector.h" + +namespace PokemonAutomation{ + class CancellableScope; + class VideoFeed; +namespace NintendoSwitch{ +namespace PokemonRSE{ + +/* +// Detect that a dialog box is on screen by looking for the white of the box +class DialogDetector : public StaticScreenDetector{ +public: + DialogDetector(Color color); + + virtual void make_overlays(VideoOverlaySet& items) const override; + virtual bool detect(const ImageViewRGB32& screen) const override; + +private: + ImageFloatBox m_left_box; + ImageFloatBox m_right_box; +}; +class DialogWatcher : public DetectorToFinder{ +public: + DialogWatcher(Color color) + : DetectorToFinder("DialogWatcher", std::chrono::milliseconds(250), color) + {} +}; + + + +// Battle dialog boxes are teal +class BattleDialogDetector : public StaticScreenDetector{ +public: + BattleDialogDetector(Color color); + + virtual void make_overlays(VideoOverlaySet& items) const override; + virtual bool detect(const ImageViewRGB32& screen) const override; + +private: + ImageFloatBox m_left_box; + ImageFloatBox m_right_box; +}; +class BattleDialogWatcher : public DetectorToFinder{ +public: + BattleDialogWatcher(Color color) + : DetectorToFinder("BattleDialogWatcher", std::chrono::milliseconds(250), color) + {} +}; +*/ + + +// Battle menu is up when it is white on the left and teal on the right +class BattleMenuDetector : public StaticScreenDetector{ +public: + BattleMenuDetector(Color color); + + virtual void make_overlays(VideoOverlaySet& items) const override; + virtual bool detect(const ImageViewRGB32& screen) const override; + +private: + ImageFloatBox m_left_box; + ImageFloatBox m_right_box; +}; +class BattleMenuWatcher : public DetectorToFinder{ +public: + BattleMenuWatcher(Color color) + : DetectorToFinder("BattleMenuWatcher", std::chrono::milliseconds(250), color) + {} +}; + + + +// advancedialogdetector Detect that the dialog arrow is in the dialog box by filtering for the red arrow + +// when given a choice popup, there is no advance arrow + + + +} +} +} + +#endif diff --git a/SerialPrograms/Source/PokemonRSE/Inference/PokemonRSE_ShinyNumberDetector.cpp b/SerialPrograms/Source/PokemonRSE/Inference/PokemonRSE_ShinyNumberDetector.cpp new file mode 100644 index 000000000..4c5002fd9 --- /dev/null +++ b/SerialPrograms/Source/PokemonRSE/Inference/PokemonRSE_ShinyNumberDetector.cpp @@ -0,0 +1,62 @@ +/* Shiny Number Detector + * + * From: https://github.com/PokemonAutomation/Arduino-Source + * + */ + +#include "Common/Cpp/Color.h" +#include "CommonFramework/ImageTools/ImageBoxes.h" +#include "CommonFramework/ImageTools/ImageFilter.h" +#include "CommonFramework/ImageTypes/ImageRGB32.h" +#include "CommonFramework/ImageTools/ImageStats.h" +#include "CommonFramework/ImageTypes/ImageViewRGB32.h" +#include "CommonFramework/VideoPipeline/VideoOverlayScopes.h" +#include "PokemonRSE_ShinyNumberDetector.h" + +#include +using std::cout; +using std::endl; + +namespace PokemonAutomation{ +namespace NintendoSwitch{ +namespace PokemonRSE{ + +ShinyNumberDetector::ShinyNumberDetector() + : m_box_number(0.136, 0.156, 0.123, 0.072) +{} + +bool ShinyNumberDetector::read(Logger& logger, const ImageViewRGB32& frame){ + const bool replace_color_within_range = true; + + //Filter out background + ImageRGB32 filtered_region = filter_rgb32_range( + extract_box_reference(frame, m_box_number), + combine_rgb(138, 97, 221), combine_rgb(200, 181, 239), Color(0), replace_color_within_range + ); + ImageStats stats = image_stats(filtered_region); + + /* + filtered_region.save("./filtered_only.png"); + cout << stats.average.r << endl; + cout << stats.average.g << endl; + cout << stats.average.b << endl; + */ + + /* + Shiny: + R: 196.632, G: 196.771, B: 145.863 + Not shiny: + R: 181.862, G: 180.686, B: 193.999 + */ + + if (stats.average.b + 20 < stats.average.r){ + return true; + } + return false; +} + + +} +} +} + diff --git a/SerialPrograms/Source/PokemonRSE/Inference/PokemonRSE_ShinyNumberDetector.h b/SerialPrograms/Source/PokemonRSE/Inference/PokemonRSE_ShinyNumberDetector.h new file mode 100644 index 000000000..54c36a1bf --- /dev/null +++ b/SerialPrograms/Source/PokemonRSE/Inference/PokemonRSE_ShinyNumberDetector.h @@ -0,0 +1,35 @@ +/* Shiny Number Detector + * + * From: https://github.com/PokemonAutomation/Arduino-Source + * + */ + +#ifndef PokemonAutomation_PokemonRSE_ShinyNumberDetector_H +#define PokemonAutomation_PokemonRSE_ShinyNumberDetector_H + +#include "Common/Cpp/AbstractLogger.h" +#include "CommonFramework/VideoPipeline/VideoOverlayScopes.h" + +namespace PokemonAutomation{ +namespace NintendoSwitch{ +namespace PokemonRSE{ + +// In the summary screen, the dex number will be yellow if a shiny, white if not. +// Additionally, the background behind the sprite will be white if shiny, grey if not. +// Number is easier to check as background as scan lines. +class ShinyNumberDetector{ +public: + ShinyNumberDetector(); + + bool read(Logger& logger, const ImageViewRGB32& frame); + +private: + ImageFloatBox m_box_number; +}; + + + +} +} +} +#endif diff --git a/SerialPrograms/Source/PokemonRSE/PokemonRSE_Panels.cpp b/SerialPrograms/Source/PokemonRSE/PokemonRSE_Panels.cpp index b1fa83f5b..9c151bb66 100644 --- a/SerialPrograms/Source/PokemonRSE/PokemonRSE_Panels.cpp +++ b/SerialPrograms/Source/PokemonRSE/PokemonRSE_Panels.cpp @@ -11,6 +11,7 @@ #include "PokemonRSE_Settings.h" #include "Programs/ShinyHunting/PokemonRSE_AudioStarterReset.h" +#include "Programs/ShinyHunting/PokemonRSE_StarterReset.h" #include "Programs/TestPrograms/PokemonRSE_SoundListener.h" namespace PokemonAutomation{ @@ -31,7 +32,8 @@ std::vector PanelListFactory::make_panels() const{ //ret.emplace_back("---- General ----"); - //ret.emplace_back("---- Shiny Hunting ----"); + ret.emplace_back("---- Shiny Hunting ----"); + ret.emplace_back(make_single_switch_program()); if (PreloadSettings::instance().DEVELOPER_MODE){ diff --git a/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_StarterReset.cpp b/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_StarterReset.cpp new file mode 100644 index 000000000..d86a84515 --- /dev/null +++ b/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_StarterReset.cpp @@ -0,0 +1,184 @@ +/* RS Starter Reset + * + * From: https://github.com/PokemonAutomation/Arduino-Source + * + */ + +#include "Common/Cpp/PrettyPrint.h" +#include "CommonFramework/Exceptions/OperationFailedException.h" +#include "CommonFramework/InferenceInfra/InferenceRoutines.h" +#include "CommonFramework/Notifications/ProgramNotifications.h" +#include "CommonFramework/Tools/VideoResolutionCheck.h" +#include "CommonFramework/Tools/StatsTracking.h" +#include "CommonFramework/VideoPipeline/VideoFeed.h" +#include "NintendoSwitch/Commands/NintendoSwitch_Commands_PushButtons.h" +#include "NintendoSwitch/Commands/NintendoSwitch_Commands_Superscalar.h" +#include "PokemonRSE/Inference/Dialogs/PokemonRSE_DialogDetector.h" +#include "PokemonRSE/Inference/PokemonRSE_ShinyNumberDetector.h" +#include "PokemonRSE/PokemonRSE_Navigation.h" +#include "PokemonRSE_StarterReset.h" + +namespace PokemonAutomation{ +namespace NintendoSwitch{ +namespace PokemonRSE{ + +StarterReset_Descriptor::StarterReset_Descriptor() + : SingleSwitchProgramDescriptor( + "PokemonRSE:StarterReset", + "Pokemon RSE", "[RS] Starter Reset", + "ComputerControl/blob/master/Wiki/Programs/PokemonRSE/StarterReset.md", + "Soft reset for a shiny starter. Ruby and Sapphire only.", + FeedbackType::REQUIRED, + AllowCommandsWhenRunning::DISABLE_COMMANDS, + PABotBaseLevel::PABOTBASE_12KB + ) +{} + +struct StarterReset_Descriptor::Stats : public StatsTracker{ + Stats() + : resets(m_stats["Resets"]) + , shinystarter(m_stats["Shiny Starter"]) + { + m_display_order.emplace_back("Resets"); + m_display_order.emplace_back("Shiny Starter"); + } + std::atomic& resets; + std::atomic& shinystarter; +}; +std::unique_ptr StarterReset_Descriptor::make_stats() const{ + return std::unique_ptr(new Stats()); +} + +StarterReset::StarterReset() + : TARGET( + "Starter:
", + { + {Target::treecko, "treecko", "Treecko"}, + {Target::torchic, "torchic", "Torchic"}, + {Target::mudkip, "mudkip", "Mudkip"}, + }, + LockMode::LOCK_WHILE_RUNNING, + Target::treecko + ) + , STARTER_WAIT( + "Send out starter wait:
After pressing A to send out your selected starter, wait this long for the animation. Make sure to add extra time in case it is shiny.", + LockMode::LOCK_WHILE_RUNNING, + TICKS_PER_SECOND, + "6 * TICKS_PER_SECOND" + ) + , NOTIFICATION_SHINY_STARTER( + "Shiny Starter", + true, true, ImageAttachmentMode::JPG, + {"Notifs", "Showcase"} + ) + , NOTIFICATION_STATUS_UPDATE("Status Update", true, false, std::chrono::seconds(3600)) + , NOTIFICATIONS({ + &NOTIFICATION_SHINY_STARTER, + &NOTIFICATION_STATUS_UPDATE, + &NOTIFICATION_PROGRAM_FINISH, + }) +{ + PA_ADD_OPTION(TARGET); + PA_ADD_OPTION(NOTIFICATIONS); +} + +void StarterReset::program(SingleSwitchProgramEnvironment& env, BotBaseContext& context){ + //assert_16_9_720p_min(env.logger(), env.console); + StarterReset_Descriptor::Stats& stats = env.current_stats(); + + /* + * Settings: Text Speed fast. + * Setup: Stand in front of the Professor's bag and save the game. + * + * Required to fight, so have to do the SR method instead of run away + * Soft reset programs are only for Ruby/Sapphire, as Emerald has the 0 seed issue. + * + * This also assumes no dry battery. + */ + + bool shiny_starter = false; + while (!shiny_starter) { + env.log("Opening bag and selecting starter."); + pbf_press_button(context, BUTTON_A, 40, 180); + + switch (TARGET) { + case Target::treecko: + pbf_press_dpad(context, DPAD_LEFT, 40, 100); + break; + case Target::torchic: + //Default cursor position, do nothing. + break; + case Target::mudkip: + pbf_press_dpad(context, DPAD_RIGHT, 40, 100); + break; + default: + OperationFailedException::fire( + env.console, ErrorReport::SEND_ERROR_REPORT, + "StarterReset: Invalid target." + ); + break; + } + pbf_mash_button(context, BUTTON_A, 540); + context.wait_for_all_requests(); + + env.log("Starting battle."); + + //Now mash B until the battle menu appears + BattleMenuWatcher battle_menu(COLOR_RED); + int ret = run_until( + env.console, context, + [](BotBaseContext& context){ + pbf_mash_button(context, BUTTON_B, 1000); + }, + {battle_menu} + ); + context.wait_for_all_requests(); + if (ret != 0){ + env.console.log("Failed to detect battle menu.", COLOR_RED); + } + else { + env.log("Battle menu detected."); + } + + //Open the summary and check the color of the number + pbf_press_dpad(context, DPAD_DOWN, 40, 80); + pbf_press_button(context, BUTTON_A, 40, 80); + pbf_press_button(context, BUTTON_A, 40, 80); + pbf_press_dpad(context, DPAD_DOWN, 40, 80); + pbf_press_button(context, BUTTON_A, 40, 80); + + //pbf_press_dpad(context, DPAD_DOWN, 40, 80); + + pbf_wait(context, 125); + context.wait_for_all_requests(); + + VideoSnapshot screen = env.console.video().snapshot(); + ShinyNumberDetector shiny_checker; + shiny_starter = shiny_checker.read(env.console.logger(), screen); + + if (shiny_starter) { + env.log("Shiny starter detected!"); + stats.shinystarter++; + send_program_status_notification(env, NOTIFICATION_SHINY_STARTER, "Shiny starter found!", screen, true); + } + else { + env.log("Starter is not shiny."); + env.log("Soft resetting."); + send_program_status_notification( + env, NOTIFICATION_STATUS_UPDATE, + "Soft resetting." + ); + soft_reset(env.program_info(), env.console, context); + stats.resets++; + } + } + + //TODO: if system set to nintendo switch, have go home when done option + + send_program_finished_notification(env, NOTIFICATION_PROGRAM_FINISH); +} + +} +} +} + diff --git a/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_StarterReset.h b/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_StarterReset.h new file mode 100644 index 000000000..0a4b8962d --- /dev/null +++ b/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_StarterReset.h @@ -0,0 +1,52 @@ +/* RS Starter Reset + * + * From: https://github.com/PokemonAutomation/Arduino-Source + * + */ + +#ifndef PokemonAutomation_PokemonRSE_StarterReset_H +#define PokemonAutomation_PokemonRSE_StarterReset_H + +#include "Common/Cpp/Options/SimpleIntegerOption.h" +#include "Common/Cpp/Options/TimeExpressionOption.h" +#include "CommonFramework/Notifications/EventNotificationsTable.h" +#include "NintendoSwitch/NintendoSwitch_SingleSwitchProgram.h" + +namespace PokemonAutomation{ +namespace NintendoSwitch{ +namespace PokemonRSE{ + +class StarterReset_Descriptor : public SingleSwitchProgramDescriptor{ +public: + StarterReset_Descriptor(); + struct Stats; + virtual std::unique_ptr make_stats() const override; +}; + +class StarterReset : public SingleSwitchProgramInstance{ +public: + StarterReset(); + virtual void program(SingleSwitchProgramEnvironment& env, BotBaseContext& context) override; + +private: + enum class Target{ + treecko, + torchic, + mudkip, + }; + EnumDropdownOption TARGET; + + TimeExpressionOption STARTER_WAIT; + + EventNotificationOption NOTIFICATION_SHINY_STARTER; + EventNotificationOption NOTIFICATION_STATUS_UPDATE; + EventNotificationsOption NOTIFICATIONS; +}; + +} +} +} +#endif + + + From 6643e9d448c2543e46e34799803cd2112dd1dae4 Mon Sep 17 00:00:00 2001 From: kichithewolf Date: Sun, 12 Jan 2025 17:04:06 -0500 Subject: [PATCH 07/11] dev mode locks --- SerialPrograms/Source/PanelLists.cpp | 5 ++++- SerialPrograms/Source/PokemonRSE/PokemonRSE_Panels.cpp | 2 +- SerialPrograms/Source/PokemonRSE/PokemonRSE_Settings.cpp | 4 ++-- .../Programs/ShinyHunting/PokemonRSE_StarterReset.cpp | 2 +- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/SerialPrograms/Source/PanelLists.cpp b/SerialPrograms/Source/PanelLists.cpp index 6b168b587..de6fafbf1 100644 --- a/SerialPrograms/Source/PanelLists.cpp +++ b/SerialPrograms/Source/PanelLists.cpp @@ -12,6 +12,7 @@ #include "CommonFramework/PersistentSettings.h" #include "CommonFramework/Windows/DpiScaler.h" #include "CommonFramework/Panels/UI/PanelListWidget.h" +#include "CommonFramework/GlobalSettingsPanel.h" #include "NintendoSwitch/NintendoSwitch_Panels.h" #include "PokemonSwSh/PokemonSwSh_Panels.h" #include "PokemonHome/PokemonHome_Panels.h" @@ -48,7 +49,9 @@ ProgramSelect::ProgramSelect(QWidget& parent, PanelHolder& holder) add(std::make_unique()); add(std::make_unique()); add(std::make_unique()); - add(std::make_unique()); + if (PreloadSettings::instance().DEVELOPER_MODE) { + add(std::make_unique()); + } add(std::make_unique()); diff --git a/SerialPrograms/Source/PokemonRSE/PokemonRSE_Panels.cpp b/SerialPrograms/Source/PokemonRSE/PokemonRSE_Panels.cpp index 9c151bb66..fe4dea57b 100644 --- a/SerialPrograms/Source/PokemonRSE/PokemonRSE_Panels.cpp +++ b/SerialPrograms/Source/PokemonRSE/PokemonRSE_Panels.cpp @@ -27,7 +27,7 @@ PanelListFactory::PanelListFactory() std::vector PanelListFactory::make_panels() const{ std::vector ret; - ret.emplace_back("---- Settings ----"); //TODO: Add device selection? + ret.emplace_back("---- Settings ----"); ret.emplace_back(make_settings()); //ret.emplace_back("---- General ----"); diff --git a/SerialPrograms/Source/PokemonRSE/PokemonRSE_Settings.cpp b/SerialPrograms/Source/PokemonRSE/PokemonRSE_Settings.cpp index a34d8ef00..fb7216a11 100644 --- a/SerialPrograms/Source/PokemonRSE/PokemonRSE_Settings.cpp +++ b/SerialPrograms/Source/PokemonRSE/PokemonRSE_Settings.cpp @@ -57,8 +57,8 @@ GameSettings::GameSettings() PA_ADD_OPTION(START_BUTTON_MASH); PA_ADD_OPTION(ENTER_GAME_WAIT); PA_ADD_STATIC(m_shiny_audio_settings); - PA_ADD_OPTION(SHINY_SOUND_THRESHOLD); - PA_ADD_OPTION(SHINY_SOUND_LOW_FREQUENCY); + //PA_ADD_OPTION(SHINY_SOUND_THRESHOLD); + //PA_ADD_OPTION(SHINY_SOUND_LOW_FREQUENCY); } diff --git a/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_StarterReset.cpp b/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_StarterReset.cpp index d86a84515..5e065b832 100644 --- a/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_StarterReset.cpp +++ b/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_StarterReset.cpp @@ -83,7 +83,7 @@ StarterReset::StarterReset() } void StarterReset::program(SingleSwitchProgramEnvironment& env, BotBaseContext& context){ - //assert_16_9_720p_min(env.logger(), env.console); + assert_16_9_720p_min(env.logger(), env.console); StarterReset_Descriptor::Stats& stats = env.current_stats(); /* From 59beefa3efee4db1fef6b2219157852f0218b43b Mon Sep 17 00:00:00 2001 From: kichithewolf Date: Mon, 13 Jan 2025 22:40:41 -0500 Subject: [PATCH 08/11] more dialog infra, improve audio starter reset FeedbackType update, finally got audio working --- .../Source/CommonFramework/Globals.h | 2 +- .../Panels/UI/PanelElements.cpp | 7 +-- .../Dialogs/PokemonRSE_DialogDetector.cpp | 49 +++++++++++++++-- .../Dialogs/PokemonRSE_DialogDetector.h | 27 +++++++--- .../PokemonRSE_ShinyNumberDetector.cpp | 12 +++-- .../PokemonRSE_ShinyNumberDetector.h | 3 +- .../Source/PokemonRSE/PokemonRSE_Panels.cpp | 4 +- .../PokemonRSE_AudioStarterReset.cpp | 53 +++++++++++-------- .../ShinyHunting/PokemonRSE_StarterReset.cpp | 12 +++-- 9 files changed, 116 insertions(+), 53 deletions(-) diff --git a/SerialPrograms/Source/CommonFramework/Globals.h b/SerialPrograms/Source/CommonFramework/Globals.h index e8091dcfd..86b8e35e4 100644 --- a/SerialPrograms/Source/CommonFramework/Globals.h +++ b/SerialPrograms/Source/CommonFramework/Globals.h @@ -69,8 +69,8 @@ enum class FeedbackType{ NONE, OPTIONAL_, // Naming conflict with macro. REQUIRED, - AUDIO, VIDEO_AUDIO, + VIDEO_AUDIO_GBA, }; diff --git a/SerialPrograms/Source/CommonFramework/Panels/UI/PanelElements.cpp b/SerialPrograms/Source/CommonFramework/Panels/UI/PanelElements.cpp index e10c3204a..3f3bbec1b 100644 --- a/SerialPrograms/Source/CommonFramework/Panels/UI/PanelElements.cpp +++ b/SerialPrograms/Source/CommonFramework/Panels/UI/PanelElements.cpp @@ -81,13 +81,8 @@ CollapsibleGroupBox* make_panel_header( header ); break; - case FeedbackType::AUDIO: - text = new QLabel( - "(This program requires audio feedback. Please make sure you choose the correct audio device.)", - header - ); - break; case FeedbackType::VIDEO_AUDIO: + case FeedbackType::VIDEO_AUDIO_GBA: text = new QLabel( "(This program requires video and audio feedback. Please make sure you choose the correct capture device, as well as the correct audio device.)", header diff --git a/SerialPrograms/Source/PokemonRSE/Inference/Dialogs/PokemonRSE_DialogDetector.cpp b/SerialPrograms/Source/PokemonRSE/Inference/Dialogs/PokemonRSE_DialogDetector.cpp index 6cca901b5..866718c71 100644 --- a/SerialPrograms/Source/PokemonRSE/Inference/Dialogs/PokemonRSE_DialogDetector.cpp +++ b/SerialPrograms/Source/PokemonRSE/Inference/Dialogs/PokemonRSE_DialogDetector.cpp @@ -5,9 +5,18 @@ */ #include "CommonFramework/ImageTools/SolidColorTest.h" +#include "CommonFramework/ImageTools/ImageBoxes.h" +#include "CommonFramework/ImageTools/ImageFilter.h" +#include "CommonFramework/ImageTypes/ImageRGB32.h" +#include "CommonFramework/ImageTools/ImageStats.h" +#include "CommonFramework/ImageTypes/ImageViewRGB32.h" #include "CommonFramework/VideoPipeline/VideoOverlayScopes.h" #include "PokemonRSE_DialogDetector.h" +#include +using std::cout; +using std::endl; + namespace PokemonAutomation{ namespace NintendoSwitch{ namespace PokemonRSE{ @@ -29,11 +38,11 @@ bool DialogDetector::detect(const ImageViewRGB32& screen) const{ } return false; } - +*/ BattleDialogDetector::BattleDialogDetector(Color color) - : m_left_box(0.155, 0.727, 0.015, 0.168) - , m_right_box(0.837, 0.729, 0.008, 0.161) + : m_left_box(0.158, 0.725, 0.011, 0.176) + , m_right_box(0.827, 0.722, 0.013, 0.178) {} void BattleDialogDetector::make_overlays(VideoOverlaySet& items) const{ items.add(COLOR_RED, m_left_box); @@ -42,12 +51,12 @@ void BattleDialogDetector::make_overlays(VideoOverlaySet& items) const{ bool BattleDialogDetector::detect(const ImageViewRGB32& screen) const{ ImageViewRGB32 left_image = extract_box_reference(screen, m_left_box); ImageViewRGB32 right_image = extract_box_reference(screen, m_right_box); - if (is_solid(left_image, { 0.25, 0.38, 0.369 }) && is_solid(right_image, { 0.25, 0.38, 0.369 })){ + if (is_solid(left_image, { 0.335, 0.331, 0.332 }) && is_solid(right_image, { 0.335, 0.331, 0.332 })){ return true; } return false; } -*/ + BattleMenuDetector::BattleMenuDetector(Color color) : m_left_box(0.155, 0.727, 0.015, 0.168) @@ -67,6 +76,36 @@ bool BattleMenuDetector::detect(const ImageViewRGB32& screen) const{ } +AdvanceDialogDetector::AdvanceDialogDetector(Color color) + : m_dialog_box(0.156, 0.715, 0.686, 0.193) +{} +void AdvanceDialogDetector::make_overlays(VideoOverlaySet& items) const{ + items.add(COLOR_RED, m_dialog_box); +} +bool AdvanceDialogDetector::detect(const ImageViewRGB32& screen) const{ + const bool replace_color_within_range = false; + + //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 + ); + ImageStats stats = image_stats(filtered_region); + + /* + filtered_region.save("./filtered_only.png"); + cout << stats.average.r << endl; + cout << stats.average.g << endl; + cout << stats.average.b << endl; + */ + + if ((stats.average.r > stats.average.b + 200) && (stats.average.r > stats.average.g + 200)){ + return true; + } + return false; +} + + } } diff --git a/SerialPrograms/Source/PokemonRSE/Inference/Dialogs/PokemonRSE_DialogDetector.h b/SerialPrograms/Source/PokemonRSE/Inference/Dialogs/PokemonRSE_DialogDetector.h index 2e21c0b57..6567edda5 100644 --- a/SerialPrograms/Source/PokemonRSE/Inference/Dialogs/PokemonRSE_DialogDetector.h +++ b/SerialPrograms/Source/PokemonRSE/Inference/Dialogs/PokemonRSE_DialogDetector.h @@ -41,8 +41,7 @@ class DialogWatcher : public DetectorToFinder{ : DetectorToFinder("DialogWatcher", std::chrono::milliseconds(250), color) {} }; - - +*/ // Battle dialog boxes are teal class BattleDialogDetector : public StaticScreenDetector{ @@ -62,10 +61,9 @@ class BattleDialogWatcher : public DetectorToFinder{ : DetectorToFinder("BattleDialogWatcher", std::chrono::milliseconds(250), color) {} }; -*/ -// Battle menu is up when it is white on the left and teal on the right +// Battle menu is up when it is white on the right and teal on the left class BattleMenuDetector : public StaticScreenDetector{ public: BattleMenuDetector(Color color); @@ -86,10 +84,27 @@ class BattleMenuWatcher : public DetectorToFinder{ -// advancedialogdetector Detect that the dialog arrow is in the dialog box by filtering for the red arrow +// Detect the red advancement arrow by filtering for red. +// This works for now, I don't think there's colored text? +// TODO: Change this to detect that the dialog arrow is in the dialog box by filtering for the red arrow +class AdvanceDialogDetector : public StaticScreenDetector{ +public: + AdvanceDialogDetector(Color color); -// when given a choice popup, there is no advance arrow + virtual void make_overlays(VideoOverlaySet& items) const override; + virtual bool detect(const ImageViewRGB32& screen) const override; +private: + ImageFloatBox m_dialog_box; +}; +class AdvanceDialogWatcher : public DetectorToFinder{ +public: + AdvanceDialogWatcher(Color color) + : DetectorToFinder("AdvanceDialogWatcher", std::chrono::milliseconds(250), color) + {} +}; + +// when given a choice popup, there is no advance arrow } diff --git a/SerialPrograms/Source/PokemonRSE/Inference/PokemonRSE_ShinyNumberDetector.cpp b/SerialPrograms/Source/PokemonRSE/Inference/PokemonRSE_ShinyNumberDetector.cpp index 4c5002fd9..59ba5b802 100644 --- a/SerialPrograms/Source/PokemonRSE/Inference/PokemonRSE_ShinyNumberDetector.cpp +++ b/SerialPrograms/Source/PokemonRSE/Inference/PokemonRSE_ShinyNumberDetector.cpp @@ -13,18 +13,20 @@ #include "CommonFramework/VideoPipeline/VideoOverlayScopes.h" #include "PokemonRSE_ShinyNumberDetector.h" -#include -using std::cout; -using std::endl; +//#include +//using std::cout; +//using std::endl; namespace PokemonAutomation{ namespace NintendoSwitch{ namespace PokemonRSE{ -ShinyNumberDetector::ShinyNumberDetector() +ShinyNumberDetector::ShinyNumberDetector(Color color) : m_box_number(0.136, 0.156, 0.123, 0.072) {} - +void ShinyNumberDetector::make_overlays(VideoOverlaySet& items) const{ + items.add(COLOR_RED, m_box_number); +} bool ShinyNumberDetector::read(Logger& logger, const ImageViewRGB32& frame){ const bool replace_color_within_range = true; diff --git a/SerialPrograms/Source/PokemonRSE/Inference/PokemonRSE_ShinyNumberDetector.h b/SerialPrograms/Source/PokemonRSE/Inference/PokemonRSE_ShinyNumberDetector.h index 54c36a1bf..2d6971b7b 100644 --- a/SerialPrograms/Source/PokemonRSE/Inference/PokemonRSE_ShinyNumberDetector.h +++ b/SerialPrograms/Source/PokemonRSE/Inference/PokemonRSE_ShinyNumberDetector.h @@ -19,8 +19,9 @@ namespace PokemonRSE{ // Number is easier to check as background as scan lines. class ShinyNumberDetector{ public: - ShinyNumberDetector(); + ShinyNumberDetector(Color color); + virtual void make_overlays(VideoOverlaySet& items) const; bool read(Logger& logger, const ImageViewRGB32& frame); private: diff --git a/SerialPrograms/Source/PokemonRSE/PokemonRSE_Panels.cpp b/SerialPrograms/Source/PokemonRSE/PokemonRSE_Panels.cpp index fe4dea57b..c566c90c5 100644 --- a/SerialPrograms/Source/PokemonRSE/PokemonRSE_Panels.cpp +++ b/SerialPrograms/Source/PokemonRSE/PokemonRSE_Panels.cpp @@ -34,12 +34,10 @@ std::vector PanelListFactory::make_panels() const{ ret.emplace_back("---- Shiny Hunting ----"); ret.emplace_back(make_single_switch_program()); + ret.emplace_back(make_single_switch_program()); if (PreloadSettings::instance().DEVELOPER_MODE){ - ret.emplace_back("---- WIP: Shiny Hunting (Audio only) ----"); - ret.emplace_back(make_single_switch_program()); - ret.emplace_back("---- Developer Tools ----"); ret.emplace_back(make_single_switch_program()); } diff --git a/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_AudioStarterReset.cpp b/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_AudioStarterReset.cpp index 4fa45a7e3..95ebf74e8 100644 --- a/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_AudioStarterReset.cpp +++ b/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_AudioStarterReset.cpp @@ -12,6 +12,7 @@ #include "CommonFramework/Tools/StatsTracking.h" #include "NintendoSwitch/Commands/NintendoSwitch_Commands_PushButtons.h" #include "NintendoSwitch/Commands/NintendoSwitch_Commands_Superscalar.h" +#include "PokemonRSE/Inference/Dialogs/PokemonRSE_DialogDetector.h" #include "PokemonRSE/Inference/Sounds/PokemonRSE_ShinySoundDetector.h" #include "PokemonRSE/PokemonRSE_Navigation.h" #include "PokemonRSE_AudioStarterReset.h" @@ -23,10 +24,10 @@ namespace PokemonRSE{ AudioStarterReset_Descriptor::AudioStarterReset_Descriptor() : SingleSwitchProgramDescriptor( "PokemonRSE:AudioStarterReset", - "Pokemon RSE", "[RS] Starter Reset - Audio only", + "Pokemon RSE", "[RS] Starter Reset", "ComputerControl/blob/master/Wiki/Programs/PokemonRSE/AudioStarterReset.md", - "Soft reset for a shiny starter. Ruby and Sapphire only. WIP, audio recognition does not work well.", - FeedbackType::AUDIO, + "Soft reset for a shiny starter. Ruby and Sapphire only.", + FeedbackType::VIDEO_AUDIO_GBA, AllowCommandsWhenRunning::DISABLE_COMMANDS, PABotBaseLevel::PABOTBASE_12KB ) @@ -101,8 +102,12 @@ void AudioStarterReset::program(SingleSwitchProgramEnvironment& env, BotBaseCont /* * Settings: Text Speed fast. + * Full screen, no filter? The device I'm using to test has similar looking output, but I don't have switch online+. + * If on a retro handheld, make sure the screen matches that of NSO+ and that there is an overlay to avoid the black border check. + * * Setup: Stand in front of the Professor's bag and save the game. * + * * Required to fight, so have to do the SR method instead of run away * Soft reset programs are only for Ruby/Sapphire, as Emerald has the 0 seed issue. * @@ -137,29 +142,33 @@ void AudioStarterReset::program(SingleSwitchProgramEnvironment& env, BotBaseCont break; } pbf_mash_button(context, BUTTON_A, 540); + context.wait_for_all_requests(); env.log("Starter selected. Checking for shiny Poochyena."); - - int ret = run_until( + AdvanceDialogWatcher pooch_appeared(COLOR_YELLOW); + int res = run_until( env.console, context, - [&](BotBaseContext& context){ - //Wait for battle to start and for Pooch battle cry - pbf_wait(context, POOCH_WAIT); - - context.wait_for_all_requests(); - + [&](BotBaseContext& context) { + int ret = wait_until( + env.console, context, + std::chrono::seconds(20), + {{pooch_detector}} + ); + pooch_detector.throw_if_no_sound(); + if (ret == 0){ + env.log("Shiny Poochyena detected!"); + stats.poochyena++; + send_program_status_notification(env, NOTIFICATION_SHINY_POOCH, "Shiny Poochyena found."); + } + else { + env.log("Poochyena is not shiny."); + } }, - {{pooch_detector}} + {{pooch_appeared}} ); - pooch_detector.throw_if_no_sound(); - if (ret == 0){ - env.log("Shiny Poochyena detected!"); - stats.poochyena++; - send_program_status_notification(env, NOTIFICATION_SHINY_POOCH, "Shiny Poochyena found."); - } - else { - env.log("Poochyena is not shiny."); - } + if (res == 0) { + env.log("Advance arrow detected. Pressing A."); + } //res != if pooch is shiny ShinySoundDetector starter_detector(env.console, [&](float error_coefficient) -> bool{ return true; @@ -201,7 +210,7 @@ void AudioStarterReset::program(SingleSwitchProgramEnvironment& env, BotBaseCont stats.resets++; } - //TODO: if system set to nintendo switch, have go home when done option + //if system set to nintendo switch, have go home when done option? send_program_finished_notification(env, NOTIFICATION_PROGRAM_FINISH); } diff --git a/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_StarterReset.cpp b/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_StarterReset.cpp index 5e065b832..cff7105e6 100644 --- a/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_StarterReset.cpp +++ b/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_StarterReset.cpp @@ -25,10 +25,10 @@ namespace PokemonRSE{ StarterReset_Descriptor::StarterReset_Descriptor() : SingleSwitchProgramDescriptor( "PokemonRSE:StarterReset", - "Pokemon RSE", "[RS] Starter Reset", + "Pokemon RSE", "[RS] Starter Reset - Video only", "ComputerControl/blob/master/Wiki/Programs/PokemonRSE/StarterReset.md", "Soft reset for a shiny starter. Ruby and Sapphire only.", - FeedbackType::REQUIRED, + FeedbackType::VIDEO_AUDIO_GBA, AllowCommandsWhenRunning::DISABLE_COMMANDS, PABotBaseLevel::PABOTBASE_12KB ) @@ -88,6 +88,9 @@ void StarterReset::program(SingleSwitchProgramEnvironment& env, BotBaseContext& /* * Settings: Text Speed fast. + * Full screen, no filter? The device I'm using to test has similar looking output, but I don't have switch online+. + * If on a retro handheld, make sure the screen matches that of NSO+ and that there is an overlay to avoid the black border check. + * * Setup: Stand in front of the Professor's bag and save the game. * * Required to fight, so have to do the SR method instead of run away @@ -147,13 +150,14 @@ void StarterReset::program(SingleSwitchProgramEnvironment& env, BotBaseContext& pbf_press_dpad(context, DPAD_DOWN, 40, 80); pbf_press_button(context, BUTTON_A, 40, 80); + //Check second party member - used for testing with hacked in shiny starter //pbf_press_dpad(context, DPAD_DOWN, 40, 80); pbf_wait(context, 125); context.wait_for_all_requests(); VideoSnapshot screen = env.console.video().snapshot(); - ShinyNumberDetector shiny_checker; + ShinyNumberDetector shiny_checker(COLOR_YELLOW); shiny_starter = shiny_checker.read(env.console.logger(), screen); if (shiny_starter) { @@ -173,7 +177,7 @@ void StarterReset::program(SingleSwitchProgramEnvironment& env, BotBaseContext& } } - //TODO: if system set to nintendo switch, have go home when done option + //if system set to nintendo switch, have go home when done option? send_program_finished_notification(env, NOTIFICATION_PROGRAM_FINISH); } From 4bf59318451658cd0bf8c6d8f0993c31bc707bd8 Mon Sep 17 00:00:00 2001 From: kichithewolf Date: Tue, 14 Jan 2025 14:34:12 -0500 Subject: [PATCH 09/11] working audio starter detection --- .../Dialogs/PokemonRSE_DialogDetector.cpp | 2 +- .../Dialogs/PokemonRSE_DialogDetector.h | 1 + .../Source/PokemonRSE/PokemonRSE_Panels.cpp | 4 +- .../PokemonRSE_AudioStarterReset.cpp | 103 +++++++++--------- .../PokemonRSE_AudioStarterReset.h | 3 - 5 files changed, 58 insertions(+), 55 deletions(-) diff --git a/SerialPrograms/Source/PokemonRSE/Inference/Dialogs/PokemonRSE_DialogDetector.cpp b/SerialPrograms/Source/PokemonRSE/Inference/Dialogs/PokemonRSE_DialogDetector.cpp index 866718c71..528e8acda 100644 --- a/SerialPrograms/Source/PokemonRSE/Inference/Dialogs/PokemonRSE_DialogDetector.cpp +++ b/SerialPrograms/Source/PokemonRSE/Inference/Dialogs/PokemonRSE_DialogDetector.cpp @@ -59,7 +59,7 @@ bool BattleDialogDetector::detect(const ImageViewRGB32& screen) const{ BattleMenuDetector::BattleMenuDetector(Color color) - : m_left_box(0.155, 0.727, 0.015, 0.168) + : m_left_box(0.439, 0.717, 0.021, 0.192) , m_right_box(0.821, 0.725, 0.030, 0.181) {} void BattleMenuDetector::make_overlays(VideoOverlaySet& items) const{ diff --git a/SerialPrograms/Source/PokemonRSE/Inference/Dialogs/PokemonRSE_DialogDetector.h b/SerialPrograms/Source/PokemonRSE/Inference/Dialogs/PokemonRSE_DialogDetector.h index 6567edda5..6f62f066a 100644 --- a/SerialPrograms/Source/PokemonRSE/Inference/Dialogs/PokemonRSE_DialogDetector.h +++ b/SerialPrograms/Source/PokemonRSE/Inference/Dialogs/PokemonRSE_DialogDetector.h @@ -64,6 +64,7 @@ class BattleDialogWatcher : public DetectorToFinder{ // Battle menu is up when it is white on the right and teal on the left +// For emerald the test is more flush to the left, so we target the right of the battle menu box class BattleMenuDetector : public StaticScreenDetector{ public: BattleMenuDetector(Color color); diff --git a/SerialPrograms/Source/PokemonRSE/PokemonRSE_Panels.cpp b/SerialPrograms/Source/PokemonRSE/PokemonRSE_Panels.cpp index c566c90c5..711f78978 100644 --- a/SerialPrograms/Source/PokemonRSE/PokemonRSE_Panels.cpp +++ b/SerialPrograms/Source/PokemonRSE/PokemonRSE_Panels.cpp @@ -33,11 +33,13 @@ std::vector PanelListFactory::make_panels() const{ //ret.emplace_back("---- General ----"); ret.emplace_back("---- Shiny Hunting ----"); - ret.emplace_back(make_single_switch_program()); ret.emplace_back(make_single_switch_program()); if (PreloadSettings::instance().DEVELOPER_MODE){ + ret.emplace_back("---- Test ----"); + ret.emplace_back(make_single_switch_program()); + ret.emplace_back("---- Developer Tools ----"); ret.emplace_back(make_single_switch_program()); } diff --git a/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_AudioStarterReset.cpp b/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_AudioStarterReset.cpp index 95ebf74e8..6e1e9f5e1 100644 --- a/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_AudioStarterReset.cpp +++ b/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_AudioStarterReset.cpp @@ -10,6 +10,7 @@ #include "CommonFramework/Notifications/ProgramNotifications.h" #include "CommonFramework/Tools/VideoResolutionCheck.h" #include "CommonFramework/Tools/StatsTracking.h" +#include "CommonFramework/VideoPipeline/VideoFeed.h" #include "NintendoSwitch/Commands/NintendoSwitch_Commands_PushButtons.h" #include "NintendoSwitch/Commands/NintendoSwitch_Commands_Superscalar.h" #include "PokemonRSE/Inference/Dialogs/PokemonRSE_DialogDetector.h" @@ -62,26 +63,14 @@ AudioStarterReset::AudioStarterReset() LockMode::LOCK_WHILE_RUNNING, Target::treecko ) - , POOCH_WAIT( - "Battle start wait:
Time for battle to start and for Poochyena to appear. Make sure to add extra time in case the Poochyena is shiny.", - LockMode::LOCK_WHILE_RUNNING, - TICKS_PER_SECOND, - "6 * TICKS_PER_SECOND" - ) - , STARTER_WAIT( - "Send out starter wait:
After pressing A to send out your selected starter, wait this long for the animation. Make sure to add extra time in case it is shiny.", - LockMode::LOCK_WHILE_RUNNING, - TICKS_PER_SECOND, - "6 * TICKS_PER_SECOND" - ) , NOTIFICATION_SHINY_POOCH( "Shiny Poochyena", - false, false, + false, false, ImageAttachmentMode::JPG, {"Notifs"} ) , NOTIFICATION_SHINY_STARTER( "Shiny Starter", - true, false, + true, true, ImageAttachmentMode::JPG, {"Notifs", "Showcase"} ) , NOTIFICATION_STATUS_UPDATE("Status Update", true, false, std::chrono::seconds(3600)) @@ -116,8 +105,9 @@ void AudioStarterReset::program(SingleSwitchProgramEnvironment& env, BotBaseCont bool shiny_starter = false; while (!shiny_starter) { - + float shiny_coefficient = 1.0; ShinySoundDetector pooch_detector(env.console, [&](float error_coefficient) -> bool{ + shiny_coefficient = error_coefficient; return true; }); @@ -143,71 +133,84 @@ void AudioStarterReset::program(SingleSwitchProgramEnvironment& env, BotBaseCont } pbf_mash_button(context, BUTTON_A, 540); context.wait_for_all_requests(); - env.log("Starter selected. Checking for shiny Poochyena."); + env.log("Starter selected. Checking for shiny Poochyena."); AdvanceDialogWatcher pooch_appeared(COLOR_YELLOW); + int res = run_until( env.console, context, [&](BotBaseContext& context) { int ret = wait_until( env.console, context, std::chrono::seconds(20), - {{pooch_detector}} + {{pooch_appeared}} ); - pooch_detector.throw_if_no_sound(); - if (ret == 0){ - env.log("Shiny Poochyena detected!"); - stats.poochyena++; - send_program_status_notification(env, NOTIFICATION_SHINY_POOCH, "Shiny Poochyena found."); - } - else { - env.log("Poochyena is not shiny."); + if (ret == 0) { + env.log("Advance arrow detected."); } + pbf_wait(context, 125); + context.wait_for_all_requests(); }, - {{pooch_appeared}} + {{pooch_detector}} ); - if (res == 0) { - env.log("Advance arrow detected. Pressing A."); - } //res != if pooch is shiny + pooch_detector.throw_if_no_sound(); + if (res == 0){ + env.log("Shiny Poochyena detected!"); + stats.poochyena++; + env.update_stats(); + send_program_status_notification(env, NOTIFICATION_SHINY_POOCH, "Shiny Poochyena found.", env.console.video().snapshot(), false); + } + else { + env.log("Poochyena is not shiny."); + } + context.wait_for_all_requests(); + float shiny_coefficient2 = 1.0; ShinySoundDetector starter_detector(env.console, [&](float error_coefficient) -> bool{ + shiny_coefficient2 = error_coefficient; return true; }); - //Press A to send out your selected starter - env.log("Sending out selected starter."); - pbf_press_button(context, BUTTON_A, 40, 40); - - int ret2 = run_until( + BattleMenuWatcher battle_menu(COLOR_RED); + int res2 = run_until( env.console, context, - [&](BotBaseContext& context){ - env.log("Wait for starter to come out."); - pbf_wait(context, STARTER_WAIT); + [&](BotBaseContext& context) { + env.log("Sending out selected starter."); + pbf_press_button(context, BUTTON_A, 40, 40); + + int ret = wait_until( + env.console, context, + std::chrono::seconds(20), + {{battle_menu}} + ); + if (ret == 0) { + env.log("Battle menu detecteed!"); + } + pbf_wait(context, 125); context.wait_for_all_requests(); }, {{starter_detector}} ); starter_detector.throw_if_no_sound(); - if (ret2 == 0){ + context.wait_for_all_requests(); + if (res2 == 0){ env.log("Shiny starter detected!"); stats.shinystarter++; - - send_program_status_notification(env, NOTIFICATION_SHINY_STARTER, "Shiny starter found!"); - + env.update_stats(); + send_program_status_notification(env, NOTIFICATION_SHINY_STARTER, "Shiny starter found!", env.console.video().snapshot(), true); shiny_starter = true; - break; } else { env.log("Starter is not shiny."); + env.log("Soft resetting."); + send_program_status_notification( + env, NOTIFICATION_STATUS_UPDATE, + "Soft resetting." + ); + soft_reset(env.program_info(), env.console, context); + stats.resets++; + env.update_stats(); } - - env.log("Soft resetting."); - send_program_status_notification( - env, NOTIFICATION_STATUS_UPDATE, - "Soft resetting." - ); - soft_reset(env.program_info(), env.console, context); - stats.resets++; } //if system set to nintendo switch, have go home when done option? diff --git a/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_AudioStarterReset.h b/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_AudioStarterReset.h index 6e4537afd..a142575f6 100644 --- a/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_AudioStarterReset.h +++ b/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_AudioStarterReset.h @@ -36,9 +36,6 @@ class AudioStarterReset : public SingleSwitchProgramInstance{ }; EnumDropdownOption TARGET; - TimeExpressionOption POOCH_WAIT; - TimeExpressionOption STARTER_WAIT; - EventNotificationOption NOTIFICATION_SHINY_POOCH; EventNotificationOption NOTIFICATION_SHINY_STARTER; EventNotificationOption NOTIFICATION_STATUS_UPDATE; From b67a8c85f4d54d47f00909a52b44d7dfc896ec9f Mon Sep 17 00:00:00 2001 From: kichithewolf Date: Tue, 14 Jan 2025 16:17:29 -0500 Subject: [PATCH 10/11] gba black borders --- SerialPrograms/CMakeLists.txt | 2 + .../Inference/BlackBorderGBADetector.cpp | 75 +++++++++++++++++++ .../Inference/BlackBorderGBADetector.h | 34 +++++++++ .../Tools/BlackBorderCheck.cpp | 24 ++++-- .../NintendoSwitch_SwitchSystemOption.cpp | 4 +- .../PokemonRSE/PokemonRSE_Navigation.cpp | 13 +++- .../Source/PokemonRSE/PokemonRSE_Navigation.h | 2 +- .../Source/PokemonRSE/PokemonRSE_Settings.cpp | 2 +- .../PokemonRSE_AudioStarterReset.cpp | 5 +- 9 files changed, 147 insertions(+), 14 deletions(-) create mode 100644 SerialPrograms/Source/CommonFramework/Inference/BlackBorderGBADetector.cpp create mode 100644 SerialPrograms/Source/CommonFramework/Inference/BlackBorderGBADetector.h diff --git a/SerialPrograms/CMakeLists.txt b/SerialPrograms/CMakeLists.txt index ea60511b2..dab2a5f22 100644 --- a/SerialPrograms/CMakeLists.txt +++ b/SerialPrograms/CMakeLists.txt @@ -387,6 +387,8 @@ file(GLOB MAIN_SOURCES Source/CommonFramework/Inference/AudioTemplateCache.h Source/CommonFramework/Inference/BlackBorderDetector.cpp Source/CommonFramework/Inference/BlackBorderDetector.h + Source/CommonFramework/Inference/BlackBorderGBADetector.cpp + Source/CommonFramework/Inference/BlackBorderGBADetector.h Source/CommonFramework/Inference/BlackScreenDetector.cpp Source/CommonFramework/Inference/BlackScreenDetector.h Source/CommonFramework/Inference/DetectionDebouncer.h diff --git a/SerialPrograms/Source/CommonFramework/Inference/BlackBorderGBADetector.cpp b/SerialPrograms/Source/CommonFramework/Inference/BlackBorderGBADetector.cpp new file mode 100644 index 000000000..7218252ae --- /dev/null +++ b/SerialPrograms/Source/CommonFramework/Inference/BlackBorderGBADetector.cpp @@ -0,0 +1,75 @@ +/* Black Border Detector + * + * From: https://github.com/PokemonAutomation/Arduino-Source + * + */ + +#include "CommonFramework/ImageTools/ImageStats.h" +#include "CommonFramework/ImageTools/SolidColorTest.h" +#include "CommonFramework/VideoPipeline/VideoOverlayScopes.h" +#include "BlackBorderGBADetector.h" + +#include +using std::cout; +using std::endl; + +namespace PokemonAutomation{ + + +BlackBorderGBADetector::BlackBorderGBADetector() + : m_top(0.126, 0.055, 0.748, 0.006) + , m_bottom(0.124, 0.940, 0.751, 0.004) + , m_left(0.126, 0.055, 0.002, 0.888) + , m_right(0.871, 0.055, 0.003, 0.888) +// , m_body(0.100, 0.100, 0.800, 0.800) +{} + +void BlackBorderGBADetector::make_overlays(VideoOverlaySet& items) const{ + items.add(COLOR_RED, m_top); + items.add(COLOR_RED, m_bottom); + items.add(COLOR_RED, m_left); + items.add(COLOR_RED, m_right); +// items.add(COLOR_RED, m_body); +} +bool BlackBorderGBADetector::detect(const ImageViewRGB32& screen) const{ + const double MAX_SUM = 50; + const double MAX_STDDEV = 20; + + ImageStats top = image_stats(extract_box_reference(screen, m_top)); +// cout << "top = " << top.average << top.stddev << endl; +// extract_box(screen, m_top).save("top.png"); + if (!is_black(top, MAX_SUM, MAX_STDDEV)){ + return false; + } + ImageStats bottom = image_stats(extract_box_reference(screen, m_bottom)); +// cout << "bottom = " << bottom.average << bottom.stddev << endl; + if (!is_black(bottom, MAX_SUM, MAX_STDDEV)){ + return false; + } + ImageStats left = image_stats(extract_box_reference(screen, m_left)); +// cout << "left = " << left.average << left.stddev << endl; + if (!is_black(left, MAX_SUM, MAX_STDDEV)){ + return false; + } + ImageStats right = image_stats(extract_box_reference(screen, m_right)); +// cout << "right = " << right.average << right.stddev << endl; + if (!is_black(right, MAX_SUM, MAX_STDDEV)){ + return false; + } +// ImageStats body = image_stats(extract_box_reference(screen, m_body)); +// cout << "body = " << body.average << body.stddev << endl; +// if (is_black(right, 30, 30)){ +// return false; +// } + + +// for (int c = 0; c < screen.width(); c++){ +// QRgb pixel = screen.pixel(c, 0); +// cout << "(" << qRed(pixel) << "," << qGreen(pixel) << "," << qBlue(pixel) << ")"; +// } + + return true; +} + + +} diff --git a/SerialPrograms/Source/CommonFramework/Inference/BlackBorderGBADetector.h b/SerialPrograms/Source/CommonFramework/Inference/BlackBorderGBADetector.h new file mode 100644 index 000000000..7c05fcf1b --- /dev/null +++ b/SerialPrograms/Source/CommonFramework/Inference/BlackBorderGBADetector.h @@ -0,0 +1,34 @@ +/* Black Screen Detector + * + * From: https://github.com/PokemonAutomation/Arduino-Source + * + */ + +#ifndef PokemonAutomation_CommonFramework_BlackBorderGBADetector_H +#define PokemonAutomation_CommonFramework_BlackBorderGBADetector_H + +#include "CommonFramework/ImageTools/ImageBoxes.h" +#include "CommonFramework/Inference/VisualDetector.h" + +namespace PokemonAutomation{ + + +class BlackBorderGBADetector : public StaticScreenDetector{ +public: + BlackBorderGBADetector(); + + virtual void make_overlays(VideoOverlaySet& items) const override; + virtual bool detect(const ImageViewRGB32& screen) const override; + +private: + ImageFloatBox m_top; + ImageFloatBox m_bottom; + ImageFloatBox m_left; + ImageFloatBox m_right; +// ImageFloatBox m_body; +}; + + + +} +#endif diff --git a/SerialPrograms/Source/CommonFramework/Tools/BlackBorderCheck.cpp b/SerialPrograms/Source/CommonFramework/Tools/BlackBorderCheck.cpp index de3ab674c..499d81781 100644 --- a/SerialPrograms/Source/CommonFramework/Tools/BlackBorderCheck.cpp +++ b/SerialPrograms/Source/CommonFramework/Tools/BlackBorderCheck.cpp @@ -10,6 +10,7 @@ #include "CommonFramework/VideoPipeline/VideoOverlayScopes.h" #include "CommonFramework/Tools/ConsoleHandle.h" #include "CommonFramework/Inference/BlackBorderDetector.h" +#include "CommonFramework/Inference/BlackBorderGBADetector.h" #include "BlackBorderCheck.h" namespace PokemonAutomation{ @@ -23,18 +24,29 @@ void start_program_video_check(ConsoleHandle& console, FeedbackType feedback){ VideoSnapshot screen = console.video().snapshot(); if (!screen){ - if (feedback == FeedbackType::REQUIRED || feedback == FeedbackType::VIDEO_AUDIO){ + if (feedback == FeedbackType::REQUIRED || feedback == FeedbackType::VIDEO_AUDIO || feedback == FeedbackType::VIDEO_AUDIO_GBA){ throw UserSetupError(console, "This program requires video feedback. Please make sure the video is working."); } return; } - BlackBorderDetector detector; - VideoOverlaySet set(console); - detector.make_overlays(set); + if (feedback != FeedbackType::VIDEO_AUDIO_GBA) { //GB, GBC in fullscreen will reach the top and bottom of the screen + BlackBorderDetector detector; + VideoOverlaySet set(console); + detector.make_overlays(set); - if (detector.detect(screen)){ - throw UserSetupError(console, "Black border detected! Please set your screen size to 100% in the TV Settings on your Nintendo Switch."); + if (detector.detect(screen)) { + throw UserSetupError(console, "Black border detected! Please set your screen size to 100% in the TV Settings on your Nintendo Switch."); + } + } + else { + BlackBorderGBADetector detector; + VideoOverlaySet set(console); + detector.make_overlays(set); + + if (detector.detect(screen)) { + throw UserSetupError(console, "Black border detected! Please set your screen size to 100% in the TV Settings on your Nintendo Switch."); + } } } void start_program_video_check(FixedLimitVector& consoles, FeedbackType feedback){ diff --git a/SerialPrograms/Source/NintendoSwitch/Framework/NintendoSwitch_SwitchSystemOption.cpp b/SerialPrograms/Source/NintendoSwitch/Framework/NintendoSwitch_SwitchSystemOption.cpp index e85f6a690..6c8778656 100644 --- a/SerialPrograms/Source/NintendoSwitch/Framework/NintendoSwitch_SwitchSystemOption.cpp +++ b/SerialPrograms/Source/NintendoSwitch/Framework/NintendoSwitch_SwitchSystemOption.cpp @@ -22,13 +22,13 @@ Color pick_color(FeedbackType feedback, PABotBaseLevel size){ case PABotBaseLevel::PABOTBASE_12KB: if (feedback == FeedbackType::REQUIRED){ return COLOR_DARKGREEN; - }else if (feedback == FeedbackType::VIDEO_AUDIO){ + }else if (feedback == FeedbackType::VIDEO_AUDIO || feedback == FeedbackType::VIDEO_AUDIO_GBA){ return COLOR_GREEN2; }else{ return COLOR_BLUE; } case PABotBaseLevel::PABOTBASE_31KB: - return (feedback == FeedbackType::REQUIRED || feedback == FeedbackType::VIDEO_AUDIO) ? COLOR_PURPLE : COLOR_RED; + return (feedback == FeedbackType::REQUIRED || feedback == FeedbackType::VIDEO_AUDIO || feedback == FeedbackType::VIDEO_AUDIO_GBA) ? COLOR_PURPLE : COLOR_RED; } return Color(); } diff --git a/SerialPrograms/Source/PokemonRSE/PokemonRSE_Navigation.cpp b/SerialPrograms/Source/PokemonRSE/PokemonRSE_Navigation.cpp index f53a3e48a..2311d8faa 100644 --- a/SerialPrograms/Source/PokemonRSE/PokemonRSE_Navigation.cpp +++ b/SerialPrograms/Source/PokemonRSE/PokemonRSE_Navigation.cpp @@ -9,6 +9,7 @@ #include "CommonFramework/Exceptions/OperationFailedException.h" #include "CommonFramework/Exceptions/UnexpectedBattleException.h" #include "CommonFramework/InferenceInfra/InferenceRoutines.h" +#include "CommonFramework/Inference/BlackScreenDetector.h" #include "NintendoSwitch/NintendoSwitch_Settings.h" #include "NintendoSwitch/Commands/NintendoSwitch_Commands_PushButtons.h" #include "NintendoSwitch/Commands/NintendoSwitch_Commands_Superscalar.h" @@ -30,7 +31,17 @@ void soft_reset(const ProgramInfo& info, ConsoleHandle& console, BotBaseContext& pbf_press_button(context, BUTTON_A, 20, 40); //Wait for game to load in - pbf_wait(context, GameSettings::instance().ENTER_GAME_WAIT); + BlackScreenOverWatcher detector(COLOR_RED, {0.282, 0.064, 0.448, 0.871}); + int ret = wait_until( + console, context, + std::chrono::milliseconds(GameSettings::instance().ENTER_GAME_WAIT * (1000 / TICKS_PER_SECOND)), + {{detector}} + ); + if (ret == 0){ + console.log("Entered game!"); + }else{ + console.log("Timed out waiting to enter game.", COLOR_RED); + } context.wait_for_all_requests(); } diff --git a/SerialPrograms/Source/PokemonRSE/PokemonRSE_Navigation.h b/SerialPrograms/Source/PokemonRSE/PokemonRSE_Navigation.h index 70b3eac8a..954727c4e 100644 --- a/SerialPrograms/Source/PokemonRSE/PokemonRSE_Navigation.h +++ b/SerialPrograms/Source/PokemonRSE/PokemonRSE_Navigation.h @@ -19,7 +19,7 @@ namespace NintendoSwitch{ namespace PokemonRSE{ // Press A+B+Select+Start at the same time to soft reset, then re-enters the game. -// This assumes no dry battery. Adding detection for that is a TODO. +// This assumes no dry battery. void soft_reset(const ProgramInfo& info, ConsoleHandle& console, BotBaseContext& context); diff --git a/SerialPrograms/Source/PokemonRSE/PokemonRSE_Settings.cpp b/SerialPrograms/Source/PokemonRSE/PokemonRSE_Settings.cpp index fb7216a11..424d39c5a 100644 --- a/SerialPrograms/Source/PokemonRSE/PokemonRSE_Settings.cpp +++ b/SerialPrograms/Source/PokemonRSE/PokemonRSE_Settings.cpp @@ -33,7 +33,7 @@ GameSettings::GameSettings() "1. Start Button Mash:
Mash Start for this long after a soft reset to get to the main menu.", LockMode::LOCK_WHILE_RUNNING, TICKS_PER_SECOND, - "4 * TICKS_PER_SECOND" + "5 * TICKS_PER_SECOND" ) , ENTER_GAME_WAIT( "2. Enter Game Wait:
Wait this long for the game to load.", diff --git a/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_AudioStarterReset.cpp b/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_AudioStarterReset.cpp index 6e1e9f5e1..7fcd4a783 100644 --- a/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_AudioStarterReset.cpp +++ b/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_AudioStarterReset.cpp @@ -86,7 +86,7 @@ AudioStarterReset::AudioStarterReset() } void AudioStarterReset::program(SingleSwitchProgramEnvironment& env, BotBaseContext& context){ - //assert_16_9_720p_min(env.logger(), env.console); + assert_16_9_720p_min(env.logger(), env.console); AudioStarterReset_Descriptor::Stats& stats = env.current_stats(); /* @@ -96,7 +96,6 @@ void AudioStarterReset::program(SingleSwitchProgramEnvironment& env, BotBaseCont * * Setup: Stand in front of the Professor's bag and save the game. * - * * Required to fight, so have to do the SR method instead of run away * Soft reset programs are only for Ruby/Sapphire, as Emerald has the 0 seed issue. * @@ -207,9 +206,9 @@ void AudioStarterReset::program(SingleSwitchProgramEnvironment& env, BotBaseCont env, NOTIFICATION_STATUS_UPDATE, "Soft resetting." ); - soft_reset(env.program_info(), env.console, context); stats.resets++; env.update_stats(); + soft_reset(env.program_info(), env.console, context); } } From db42cdbd359f292acbc808dc7f7ce9cba07bfee9 Mon Sep 17 00:00:00 2001 From: kichithewolf Date: Tue, 14 Jan 2025 17:25:57 -0500 Subject: [PATCH 11/11] update notifications, unblock settings --- SerialPrograms/Source/PokemonRSE/PokemonRSE_Panels.cpp | 2 +- SerialPrograms/Source/PokemonRSE/PokemonRSE_Settings.cpp | 4 ++-- .../ShinyHunting/PokemonRSE_AudioStarterReset.cpp | 8 ++++---- .../Programs/ShinyHunting/PokemonRSE_StarterReset.cpp | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/SerialPrograms/Source/PokemonRSE/PokemonRSE_Panels.cpp b/SerialPrograms/Source/PokemonRSE/PokemonRSE_Panels.cpp index 711f78978..b112bd936 100644 --- a/SerialPrograms/Source/PokemonRSE/PokemonRSE_Panels.cpp +++ b/SerialPrograms/Source/PokemonRSE/PokemonRSE_Panels.cpp @@ -38,7 +38,7 @@ std::vector PanelListFactory::make_panels() const{ if (PreloadSettings::instance().DEVELOPER_MODE){ ret.emplace_back("---- Test ----"); - ret.emplace_back(make_single_switch_program()); + ret.emplace_back(make_single_switch_program()); //outdated early test program ret.emplace_back("---- Developer Tools ----"); ret.emplace_back(make_single_switch_program()); diff --git a/SerialPrograms/Source/PokemonRSE/PokemonRSE_Settings.cpp b/SerialPrograms/Source/PokemonRSE/PokemonRSE_Settings.cpp index 424d39c5a..129ef531d 100644 --- a/SerialPrograms/Source/PokemonRSE/PokemonRSE_Settings.cpp +++ b/SerialPrograms/Source/PokemonRSE/PokemonRSE_Settings.cpp @@ -57,8 +57,8 @@ GameSettings::GameSettings() PA_ADD_OPTION(START_BUTTON_MASH); PA_ADD_OPTION(ENTER_GAME_WAIT); PA_ADD_STATIC(m_shiny_audio_settings); - //PA_ADD_OPTION(SHINY_SOUND_THRESHOLD); - //PA_ADD_OPTION(SHINY_SOUND_LOW_FREQUENCY); + PA_ADD_OPTION(SHINY_SOUND_THRESHOLD); + PA_ADD_OPTION(SHINY_SOUND_LOW_FREQUENCY); } diff --git a/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_AudioStarterReset.cpp b/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_AudioStarterReset.cpp index 7fcd4a783..1b5050d73 100644 --- a/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_AudioStarterReset.cpp +++ b/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_AudioStarterReset.cpp @@ -25,7 +25,7 @@ namespace PokemonRSE{ AudioStarterReset_Descriptor::AudioStarterReset_Descriptor() : SingleSwitchProgramDescriptor( "PokemonRSE:AudioStarterReset", - "Pokemon RSE", "[RS] Starter Reset", + "Pokemon RSE", "Starter Reset (Ruby/Sapphire)", "ComputerControl/blob/master/Wiki/Programs/PokemonRSE/AudioStarterReset.md", "Soft reset for a shiny starter. Ruby and Sapphire only.", FeedbackType::VIDEO_AUDIO_GBA, @@ -92,7 +92,7 @@ void AudioStarterReset::program(SingleSwitchProgramEnvironment& env, BotBaseCont /* * Settings: Text Speed fast. * Full screen, no filter? The device I'm using to test has similar looking output, but I don't have switch online+. - * If on a retro handheld, make sure the screen matches that of NSO+ and that there is an overlay to avoid the black border check. + * If on a retro handheld, make sure the screen matches that of NSO+. * * Setup: Stand in front of the Professor's bag and save the game. * @@ -157,7 +157,7 @@ void AudioStarterReset::program(SingleSwitchProgramEnvironment& env, BotBaseCont env.log("Shiny Poochyena detected!"); stats.poochyena++; env.update_stats(); - send_program_status_notification(env, NOTIFICATION_SHINY_POOCH, "Shiny Poochyena found.", env.console.video().snapshot(), false); + send_program_notification(env, NOTIFICATION_SHINY_POOCH, COLOR_YELLOW, "Shiny Poochyena found", {}, "", env.console.video().snapshot(), true); } else { env.log("Poochyena is not shiny."); @@ -196,7 +196,7 @@ void AudioStarterReset::program(SingleSwitchProgramEnvironment& env, BotBaseCont env.log("Shiny starter detected!"); stats.shinystarter++; env.update_stats(); - send_program_status_notification(env, NOTIFICATION_SHINY_STARTER, "Shiny starter found!", env.console.video().snapshot(), true); + send_program_notification(env, NOTIFICATION_SHINY_STARTER, COLOR_YELLOW, "Shiny starter found!", {}, "", env.console.video().snapshot(), true); shiny_starter = true; } else { diff --git a/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_StarterReset.cpp b/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_StarterReset.cpp index cff7105e6..c990d8017 100644 --- a/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_StarterReset.cpp +++ b/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_StarterReset.cpp @@ -89,7 +89,7 @@ void StarterReset::program(SingleSwitchProgramEnvironment& env, BotBaseContext& /* * Settings: Text Speed fast. * Full screen, no filter? The device I'm using to test has similar looking output, but I don't have switch online+. - * If on a retro handheld, make sure the screen matches that of NSO+ and that there is an overlay to avoid the black border check. + * If on a retro handheld, make sure the screen matches that of NSO+. * * Setup: Stand in front of the Professor's bag and save the game. *