From 8f8c5eb89bf43ab2db17d21e768d4b40ac4230af Mon Sep 17 00:00:00 2001 From: kichithewolf Date: Thu, 13 Feb 2025 19:34:08 -0500 Subject: [PATCH 1/2] emerald mew hunt (no timings yet) --- SerialPrograms/CMakeLists.txt | 2 + SerialPrograms/SerialPrograms.pro | 2 + .../Source/PokemonRSE/PokemonRSE_Panels.cpp | 2 + .../ShinyHunting/PokemonRSE_ShinyHunt-Mew.cpp | 235 ++++++++++++++++++ .../ShinyHunting/PokemonRSE_ShinyHunt-Mew.h | 54 ++++ 5 files changed, 295 insertions(+) create mode 100644 SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_ShinyHunt-Mew.cpp create mode 100644 SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_ShinyHunt-Mew.h diff --git a/SerialPrograms/CMakeLists.txt b/SerialPrograms/CMakeLists.txt index a3ae492b29..0f9bae21c1 100644 --- a/SerialPrograms/CMakeLists.txt +++ b/SerialPrograms/CMakeLists.txt @@ -1349,6 +1349,8 @@ file(GLOB MAIN_SOURCES Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_LegendaryHunt-Emerald.h Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_ShinyHunt-Deoxys.cpp Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_ShinyHunt-Deoxys.h + Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_ShinyHunt-Mew.cpp + Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_ShinyHunt-Mew.h Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_StarterReset.cpp Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_StarterReset.h Source/PokemonRSE/Programs/TestPrograms/PokemonRSE_SoundListener.cpp diff --git a/SerialPrograms/SerialPrograms.pro b/SerialPrograms/SerialPrograms.pro index e20efbbb59..9458654c72 100644 --- a/SerialPrograms/SerialPrograms.pro +++ b/SerialPrograms/SerialPrograms.pro @@ -666,6 +666,7 @@ SOURCES += \ Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_AudioStarterReset.cpp \ Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_LegendaryHunt-Emerald.cpp \ Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_ShinyHunt-Deoxys.cpp \ + Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_ShinyHunt-Mew.cpp \ Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_StarterReset.cpp \ Source/PokemonRSE/Programs/TestPrograms/PokemonRSE_SoundListener.cpp \ Source/PokemonSV/Inference/Battles/PokemonSV_BattleBallReader.cpp \ @@ -1832,6 +1833,7 @@ HEADERS += \ Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_AudioStarterReset.h \ Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_LegendaryHunt-Emerald.h \ Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_ShinyHunt-Deoxys.h \ + Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_ShinyHunt-Mew.h \ Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_StarterReset.h \ Source/PokemonRSE/Programs/TestPrograms/PokemonRSE_SoundListener.h \ Source/PokemonSV/Inference/Battles/PokemonSV_BattleBallReader.h \ diff --git a/SerialPrograms/Source/PokemonRSE/PokemonRSE_Panels.cpp b/SerialPrograms/Source/PokemonRSE/PokemonRSE_Panels.cpp index 9d873c8d94..96870153cc 100644 --- a/SerialPrograms/Source/PokemonRSE/PokemonRSE_Panels.cpp +++ b/SerialPrograms/Source/PokemonRSE/PokemonRSE_Panels.cpp @@ -13,6 +13,7 @@ #include "Programs/ShinyHunting/PokemonRSE_AudioStarterReset.h" #include "Programs/ShinyHunting/PokemonRSE_LegendaryHunt-Emerald.h" #include "Programs/ShinyHunting/PokemonRSE_ShinyHunt-Deoxys.h" +#include "Programs/ShinyHunting/PokemonRSE_ShinyHunt-Mew.h" #include "Programs/ShinyHunting/PokemonRSE_StarterReset.h" #include "Programs/TestPrograms/PokemonRSE_SoundListener.h" @@ -41,6 +42,7 @@ std::vector PanelListFactory::make_panels() const{ ret.emplace_back("---- Shiny Hunting (Emerald) ----"); ret.emplace_back(make_single_switch_program()); ret.emplace_back(make_single_switch_program()); + ret.emplace_back(make_single_switch_program()); if (PreloadSettings::instance().DEVELOPER_MODE){ diff --git a/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_ShinyHunt-Mew.cpp b/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_ShinyHunt-Mew.cpp new file mode 100644 index 0000000000..f8a25c4fb5 --- /dev/null +++ b/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_ShinyHunt-Mew.cpp @@ -0,0 +1,235 @@ +/* E Shiny Mew + * + * From: https://github.com/PokemonAutomation/Arduino-Source + * + */ + +#include "Common/Cpp/PrettyPrint.h" +#include "CommonFramework/Exceptions/OperationFailedException.h" +#include "CommonTools/Async/InferenceRoutines.h" +#include "CommonTools/VisualDetectors/BlackScreenDetector.h" +#include "CommonFramework/Notifications/ProgramNotifications.h" +#include "CommonFramework/ProgramStats/StatsTracking.h" +#include "CommonFramework/VideoPipeline/VideoFeed.h" +#include "Pokemon/Pokemon_Strings.h" +#include "NintendoSwitch/Commands/NintendoSwitch_Commands_PushButtons.h" +#include "NintendoSwitch/Commands/NintendoSwitch_Commands_Superscalar.h" +#include "PokemonRSE/Inference/Dialogs/PokemonRSE_DialogDetector.h" +#include "PokemonRSE/PokemonRSE_Navigation.h" +#include "PokemonRSE_ShinyHunt-Mew.h" + +namespace PokemonAutomation{ +namespace NintendoSwitch{ +namespace PokemonRSE{ + +ShinyHuntMew_Descriptor::ShinyHuntMew_Descriptor() + : SingleSwitchProgramDescriptor( + "PokemonRSE:ShinyHuntMew", + Pokemon::STRING_POKEMON + " RSE", "Shiny Hunt - Mew", + "ComputerControl/blob/master/Wiki/Programs/PokemonRSE/ShinyHuntMew.md", + "Use the Run Away method to shiny hunt Mew in Emerald.", + FeedbackType::VIDEO_AUDIO, + AllowCommandsWhenRunning::DISABLE_COMMANDS, + {SerialPABotBase::OLD_NINTENDO_SWITCH_DEFAULT_REQUIREMENTS} + ) +{} + +struct ShinyHuntMew_Descriptor::Stats : public StatsTracker{ + Stats() + : resets(m_stats["Resets"]) + , shinies(m_stats["Shinies"]) + { + m_display_order.emplace_back("Resets"); + m_display_order.emplace_back("Shinies"); + } + std::atomic& resets; + std::atomic& shinies; +}; +std::unique_ptr ShinyHuntMew_Descriptor::make_stats() const{ + return std::unique_ptr(new Stats()); +} + +ShinyHuntMew::ShinyHuntMew() + : NOTIFICATION_SHINY( + "Shiny Found", + true, true, ImageAttachmentMode::JPG, + {"Notifs", "Showcase"} + ) + , NOTIFICATION_STATUS_UPDATE("Status Update", true, false, std::chrono::seconds(3600)) + , NOTIFICATIONS({ + &NOTIFICATION_SHINY, + &NOTIFICATION_STATUS_UPDATE, + &NOTIFICATION_PROGRAM_FINISH, + }) + , m_advanced_options( + "Advanced Options: You should not need to touch anything below here." + ) + , MEW_WAIT_TIME( + "Mew wait time:
Wait this long after entering for Mew to hide in the grass.", + LockMode::LOCK_WHILE_RUNNING, + "100 ms" + ) + , DOOR_TO_GRASS_TIME( + "Door to grass time:
Time it takes to run from the door to the edge of the tall grass. Three steps up.", + LockMode::LOCK_WHILE_RUNNING, + "100 ms" + ) + , RIGHT_GRASS_1_TIME( + "First Right time:
Time it takes to turn right and take three steps. This follows the edge of the grass.", + LockMode::LOCK_WHILE_RUNNING, + "100 ms" + ) + , UP_GRASS_1_TIME( + "Move Up time::
Time it takes turn up and take one step.", + LockMode::LOCK_WHILE_RUNNING, + "100 ms" + ) + , RIGHT_GRASS_2_TIME( + "Second Right time:
Time it takes to turn right and take two steps.", + LockMode::LOCK_WHILE_RUNNING, + "100 ms" + ) + , FACE_UP_TIME( + "Face Up time:
Time it takes to tap the up button and face up, without taking a step.", + LockMode::LOCK_WHILE_RUNNING, + "100 ms" + ) +{ + PA_ADD_OPTION(NOTIFICATIONS); + PA_ADD_STATIC(m_advanced_options); + PA_ADD_OPTION(MEW_WAIT_TIME); + PA_ADD_OPTION(DOOR_TO_GRASS_TIME); + PA_ADD_OPTION(RIGHT_GRASS_1_TIME); + PA_ADD_OPTION(UP_GRASS_1_TIME); + PA_ADD_OPTION(RIGHT_GRASS_2_TIME); + PA_ADD_OPTION(FACE_UP_TIME); +} + +void ShinyHuntMew::enter_mew(SingleSwitchProgramEnvironment& env, ProControllerContext& context) { + BlackScreenOverWatcher enter_area(COLOR_RED, {0.282, 0.064, 0.448, 0.871}); + int ret = run_until( + env.console, context, + [](ProControllerContext& context){ + pbf_press_dpad(context, DPAD_UP, 250, 20); + pbf_wait(context, 300); + }, + {enter_area} + ); + context.wait_for_all_requests(); + if (ret != 0){ + env.log("Failed to enter area.", COLOR_RED); + OperationFailedException::fire( + ErrorReport::SEND_ERROR_REPORT, + "Failed to enter area.", + env.console + ); + } + else { + env.log("Entered area."); + } + + //Wait for Mew ! animation to finish + pbf_wait(context, MEW_WAIT_TIME); + context.wait_for_all_requests(); + + //DO NOT pause while running! + //Run up toward the extra tall grass - 3 steps + ssf_press_button(context, BUTTON_B, 0ms, DOOR_TO_GRASS_TIME); + pbf_press_dpad(context, DPAD_UP, DOOR_TO_GRASS_TIME, 0ms); + + //Turn right, take 3 steps + ssf_press_button(context, BUTTON_B, 0ms, RIGHT_GRASS_1_TIME); + pbf_press_dpad(context, DPAD_RIGHT, RIGHT_GRASS_1_TIME, 0ms); + + //Turn up, take 1 step + ssf_press_button(context, BUTTON_B, 0ms, UP_GRASS_1_TIME); + pbf_press_dpad(context, DPAD_UP, UP_GRASS_1_TIME, 0ms); + + //Turn right, take 2 steps + ssf_press_button(context, BUTTON_B, 0ms, RIGHT_GRASS_2_TIME); + pbf_press_dpad(context, DPAD_RIGHT, RIGHT_GRASS_2_TIME, 0ms); + + //Turn up. Start battle. + ssf_press_button(context, BUTTON_B, 0ms, FACE_UP_TIME); + pbf_press_dpad(context, DPAD_RIGHT, FACE_UP_TIME, 0ms); + + context.wait_for_all_requests(); +} + +void ShinyHuntMew::exit_mew(SingleSwitchProgramEnvironment& env, ProControllerContext& context) { + //We can simply reuse the values from enter_mew + ssf_press_button(context, BUTTON_B, 0ms, RIGHT_GRASS_2_TIME); + pbf_press_dpad(context, DPAD_LEFT, RIGHT_GRASS_2_TIME, 0ms); + + ssf_press_button(context, BUTTON_B, 0ms, UP_GRASS_1_TIME); + pbf_press_dpad(context, DPAD_DOWN, UP_GRASS_1_TIME, 0ms); + + ssf_press_button(context, BUTTON_B, 0ms, RIGHT_GRASS_1_TIME); + pbf_press_dpad(context, DPAD_LEFT, RIGHT_GRASS_1_TIME, 0ms); + + ssf_press_button(context, BUTTON_B, 0ms, DOOR_TO_GRASS_TIME); + pbf_press_dpad(context, DPAD_DOWN, DOOR_TO_GRASS_TIME, 0ms); + + BlackScreenOverWatcher exit_area(COLOR_RED, {0.282, 0.064, 0.448, 0.871}); + int ret = run_until( + env.console, context, + [](ProControllerContext& context){ + pbf_press_dpad(context, DPAD_DOWN, 250, 20); + pbf_wait(context, 300); + }, + {exit_area} + ); + context.wait_for_all_requests(); + if (ret != 0){ + env.log("Failed to exit area.", COLOR_RED); + OperationFailedException::fire( + ErrorReport::SEND_ERROR_REPORT, + "Failed to exit area.", + env.console + ); + } + else { + env.log("Exited area."); + } +} + +void ShinyHuntMew::program(SingleSwitchProgramEnvironment& env, ProControllerContext& context){ + ShinyHuntMew_Descriptor::Stats& stats = env.current_stats(); + + /* + * Requires more precision to ensure a Mew encounter every time. + * Movement is very configurable due to this. + * Enter on the left side, run up and hug the grass to the edge just after the flower on the right + * This but without the bike: + * https://old.reddit.com/r/ShinyPokemon/comments/1c773oi/gen3_discuss_is_this_the_fastest_way_to_encounter/ + */ + + while (true) { + enter_mew(env, context); + + bool legendary_shiny = handle_encounter(env.console, context, true); + if (legendary_shiny) { + stats.shinies++; + env.update_stats(); + send_program_notification(env, NOTIFICATION_SHINY, COLOR_YELLOW, "Shiny found!", {}, "", env.console.video().snapshot(), true); + break; + } + env.log("No shiny found."); + flee_battle(env.console, context); + + //Close dialog + pbf_mash_button(context, BUTTON_B, 250); + context.wait_for_all_requests(); + + exit_mew(env, context); + + stats.resets++; + env.update_stats(); + } + + send_program_finished_notification(env, NOTIFICATION_PROGRAM_FINISH); +} + +} +} +} diff --git a/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_ShinyHunt-Mew.h b/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_ShinyHunt-Mew.h new file mode 100644 index 0000000000..3b922f4060 --- /dev/null +++ b/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_ShinyHunt-Mew.h @@ -0,0 +1,54 @@ +/* E Shiny Mew + * + * From: https://github.com/PokemonAutomation/Arduino-Source + * + */ + +#ifndef PokemonAutomation_PokemonRSE_ShinyHuntMew_H +#define PokemonAutomation_PokemonRSE_ShinyHuntMew_H + +#include "Common/Cpp/Options/StaticTextOption.h" +#include "Common/Cpp/Options/TimeDurationOption.h" +#include "CommonFramework/Notifications/EventNotificationsTable.h" +#include "NintendoSwitch/NintendoSwitch_SingleSwitchProgram.h" + +namespace PokemonAutomation{ +namespace NintendoSwitch{ +namespace PokemonRSE{ + +class ShinyHuntMew_Descriptor : public SingleSwitchProgramDescriptor{ +public: + ShinyHuntMew_Descriptor(); + struct Stats; + virtual std::unique_ptr make_stats() const override; +}; + +class ShinyHuntMew : public SingleSwitchProgramInstance{ +public: + ShinyHuntMew(); + virtual void program(SingleSwitchProgramEnvironment& env, ProControllerContext& context) override; + +private: + EventNotificationOption NOTIFICATION_SHINY; + EventNotificationOption NOTIFICATION_STATUS_UPDATE; + EventNotificationsOption NOTIFICATIONS; + + SectionDividerOption m_advanced_options; + + MillisecondsOption MEW_WAIT_TIME; + MillisecondsOption DOOR_TO_GRASS_TIME; + MillisecondsOption RIGHT_GRASS_1_TIME; + MillisecondsOption UP_GRASS_1_TIME; + MillisecondsOption RIGHT_GRASS_2_TIME; + MillisecondsOption FACE_UP_TIME; + + void enter_mew(SingleSwitchProgramEnvironment& env, ProControllerContext& context); + void exit_mew(SingleSwitchProgramEnvironment& env, ProControllerContext& context); + +}; + +} +} +} +#endif + From 0fd34c53131e7aa240c9a33de659337c04abbc3f Mon Sep 17 00:00:00 2001 From: kichithewolf Date: Tue, 18 Feb 2025 14:19:12 -0500 Subject: [PATCH 2/2] mew timings --- .../ShinyHunting/PokemonRSE_ShinyHunt-Mew.cpp | 31 ++++++++----------- .../ShinyHunting/PokemonRSE_ShinyHunt-Mew.h | 6 ++++ 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_ShinyHunt-Mew.cpp b/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_ShinyHunt-Mew.cpp index f8a25c4fb5..459c940b86 100644 --- a/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_ShinyHunt-Mew.cpp +++ b/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_ShinyHunt-Mew.cpp @@ -67,32 +67,32 @@ ShinyHuntMew::ShinyHuntMew() , MEW_WAIT_TIME( "Mew wait time:
Wait this long after entering for Mew to hide in the grass.", LockMode::LOCK_WHILE_RUNNING, - "100 ms" + "2000 ms" ) , DOOR_TO_GRASS_TIME( "Door to grass time:
Time it takes to run from the door to the edge of the tall grass. Three steps up.", LockMode::LOCK_WHILE_RUNNING, - "100 ms" + "400 ms" ) , RIGHT_GRASS_1_TIME( "First Right time:
Time it takes to turn right and take three steps. This follows the edge of the grass.", LockMode::LOCK_WHILE_RUNNING, - "100 ms" + "450 ms" ) , UP_GRASS_1_TIME( "Move Up time::
Time it takes turn up and take one step.", LockMode::LOCK_WHILE_RUNNING, - "100 ms" + "200 ms" ) , RIGHT_GRASS_2_TIME( "Second Right time:
Time it takes to turn right and take two steps.", LockMode::LOCK_WHILE_RUNNING, - "100 ms" + "260 ms" ) , FACE_UP_TIME( "Face Up time:
Time it takes to tap the up button and face up, without taking a step.", LockMode::LOCK_WHILE_RUNNING, - "100 ms" + "150 ms" ) { PA_ADD_OPTION(NOTIFICATIONS); @@ -150,25 +150,20 @@ void ShinyHuntMew::enter_mew(SingleSwitchProgramEnvironment& env, ProControllerC pbf_press_dpad(context, DPAD_RIGHT, RIGHT_GRASS_2_TIME, 0ms); //Turn up. Start battle. - ssf_press_button(context, BUTTON_B, 0ms, FACE_UP_TIME); - pbf_press_dpad(context, DPAD_RIGHT, FACE_UP_TIME, 0ms); + pbf_press_dpad(context, DPAD_UP, FACE_UP_TIME, 0ms); context.wait_for_all_requests(); } void ShinyHuntMew::exit_mew(SingleSwitchProgramEnvironment& env, ProControllerContext& context) { - //We can simply reuse the values from enter_mew - ssf_press_button(context, BUTTON_B, 0ms, RIGHT_GRASS_2_TIME); - pbf_press_dpad(context, DPAD_LEFT, RIGHT_GRASS_2_TIME, 0ms); + ssf_press_button(context, BUTTON_B, 0, 50); + pbf_press_dpad(context, DPAD_DOWN, 50, 20); - ssf_press_button(context, BUTTON_B, 0ms, UP_GRASS_1_TIME); - pbf_press_dpad(context, DPAD_DOWN, UP_GRASS_1_TIME, 0ms); + ssf_press_button(context, BUTTON_B, 0, 90); + pbf_press_dpad(context, DPAD_LEFT, 90, 20); - ssf_press_button(context, BUTTON_B, 0ms, RIGHT_GRASS_1_TIME); - pbf_press_dpad(context, DPAD_LEFT, RIGHT_GRASS_1_TIME, 0ms); - - ssf_press_button(context, BUTTON_B, 0ms, DOOR_TO_GRASS_TIME); - pbf_press_dpad(context, DPAD_DOWN, DOOR_TO_GRASS_TIME, 0ms); + ssf_press_button(context, BUTTON_B, 0, 100); + pbf_press_dpad(context, DPAD_DOWN, 100, 20); BlackScreenOverWatcher exit_area(COLOR_RED, {0.282, 0.064, 0.448, 0.871}); int ret = run_until( diff --git a/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_ShinyHunt-Mew.h b/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_ShinyHunt-Mew.h index 3b922f4060..a2194603b2 100644 --- a/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_ShinyHunt-Mew.h +++ b/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_ShinyHunt-Mew.h @@ -28,6 +28,12 @@ class ShinyHuntMew : public SingleSwitchProgramInstance{ ShinyHuntMew(); virtual void program(SingleSwitchProgramEnvironment& env, ProControllerContext& context) override; + virtual void start_program_border_check( + CancellableScope& scope, + VideoStream& stream, + FeedbackType feedback_type + ) override{} + private: EventNotificationOption NOTIFICATION_SHINY; EventNotificationOption NOTIFICATION_STATUS_UPDATE;