Skip to content

Commit 55062de

Browse files
committed
use inference to confirm we are in the Mystery Gift window
1 parent 35e77b3 commit 55062de

File tree

4 files changed

+116
-23
lines changed

4 files changed

+116
-23
lines changed

SerialPrograms/Source/NintendoSwitch/DevPrograms/TestProgramSwitch.cpp

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@
138138
#include "PokemonHome/Inference/PokemonHome_BallReader.h"
139139
#include "PokemonSwSh/MaxLair/Inference/PokemonSwSh_MaxLair_Detect_PathSide.h"
140140
#include "PokemonSwSh/MaxLair/Inference/PokemonSwSh_MaxLair_Detect_PathMap.h"
141+
#include "NintendoSwitch/Inference/NintendoSwitch_SelectedSettingDetector.h"
141142

142143
#include <QPixmap>
143144
#include <QVideoFrame>
@@ -256,6 +257,36 @@ void TestProgram::program(MultiSwitchProgramEnvironment& env, CancellableScope&
256257
VideoOverlaySet overlays(overlay);
257258

258259

260+
261+
#if 0
262+
bool switch2 = true;
263+
ImageFloatBox key1_box;
264+
ImageFloatBox other_setting1;
265+
ImageFloatBox other_setting2;
266+
267+
if (!switch2){
268+
key1_box = {0.037322, 0.451172, 0.009879, 0.113281};
269+
other_setting1 = {0.01, 0.451172, 0.009879, 0.113281};
270+
other_setting2 = {0.02, 0.451172, 0.009879, 0.113281};
271+
}else if (switch2){
272+
key1_box = {0.062706, 0.510763, 0.009901, 0.097847};
273+
other_setting1 = {0.02, 0.510763, 0.009901, 0.097847};
274+
other_setting2 = {0.04, 0.510763, 0.009901, 0.097847};
275+
}
276+
277+
SelectedSettingWatcher key1_selected(key1_box, other_setting1, other_setting2, other_setting1);
278+
int ret = wait_until(
279+
console, context,
280+
Milliseconds(5000),
281+
{key1_selected}
282+
);
283+
if (ret < 0){ // failed to detect Key 1 being highlighted. Reset game and re-try
284+
console.log("claim_mystery_gift: Failed to detect the Mystery Gift window. Reset game and re-try.", COLOR_YELLOW);
285+
reset_game(env.program_info(), console, context);
286+
}
287+
288+
#endif
289+
259290
#if 0
260291
auto screenshot = feed.snapshot();
261292

@@ -342,7 +373,7 @@ void TestProgram::program(MultiSwitchProgramEnvironment& env, CancellableScope&
342373
#endif
343374

344375

345-
#if 1
376+
#if 0
346377
auto screenshot = feed.snapshot();
347378

348379
PokemonHome::BallReader reader(console);
@@ -607,7 +638,7 @@ void TestProgram::program(MultiSwitchProgramEnvironment& env, CancellableScope&
607638
// context->issue_gyro_rotate_x(&scope, duration, duration, 0s, 0x1000);
608639
// context->issue_nop(&scope, 60h);
609640

610-
#if 1
641+
#if 0
611642
auto duration = 15ms;
612643
for (size_t c = 0; c < 65536; c += 1){
613644
context->issue_gyro_accel_x(&scope, 0s, duration, 0s, (uint16_t)(688 + 0*c % 2));
@@ -655,7 +686,7 @@ void TestProgram::program(MultiSwitchProgramEnvironment& env, CancellableScope&
655686
#if 0
656687
// ImageRGB32 image(IMAGE_PATH);
657688
auto image = feed.snapshot();
658-
#if 1
689+
#if 0
659690
ImageRGB32 image(IMAGE_PATH);
660691
// auto image = feed.snapshot();
661692

SerialPrograms/Source/NintendoSwitch/Inference/NintendoSwitch_SelectedSettingDetector.cpp

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@
99
#include "NintendoSwitch_SelectedSettingDetector.h"
1010

1111
//
12-
//#include <iostream>
13-
//using std::cout;
14-
//using std::endl;
12+
// #include <iostream>
13+
// using std::cout;
14+
// using std::endl;
1515

1616
namespace PokemonAutomation{
1717
namespace NintendoSwitch{
@@ -21,24 +21,26 @@ SelectedSettingWatcher::~SelectedSettingWatcher() = default;
2121
SelectedSettingWatcher::SelectedSettingWatcher(
2222
ImageFloatBox selected_box,
2323
ImageFloatBox not_selected_box1,
24-
ImageFloatBox not_selected_box2
24+
ImageFloatBox not_selected_box2,
25+
ImageFloatBox representative_background
2526
)
2627
: VisualInferenceCallback("SelectedSettingWatcher")
2728
, m_selected_box(selected_box)
2829
, m_not_selected_box1(not_selected_box1)
2930
, m_not_selected_box2(not_selected_box2)
31+
, m_representative_background(representative_background)
3032
{}
3133

3234
void SelectedSettingWatcher::make_overlays(VideoOverlaySet& items) const{
3335
items.add(COLOR_RED, m_selected_box);
3436
items.add(COLOR_BLUE, m_not_selected_box1);
3537
items.add(COLOR_BLUE, m_not_selected_box2);
38+
items.add(COLOR_GREEN, m_representative_background);
3639
}
3740

38-
bool is_white_theme(const ImageViewRGB32& screen){
39-
ImageFloatBox window_top(0.60, 0.02, 0.35, 0.05);
40-
ImageStats stats_window_top = image_stats(extract_box_reference(screen, window_top));
41-
bool white_theme = stats_window_top.average.sum() > 500;
41+
bool SelectedSettingWatcher::is_white_theme(const ImageViewRGB32& screen){
42+
ImageStats stats_window_background = image_stats(extract_box_reference(screen, m_representative_background));
43+
bool white_theme = stats_window_background.average.sum() > 500;
4244
return white_theme;
4345
}
4446

SerialPrograms/Source/NintendoSwitch/Inference/NintendoSwitch_SelectedSettingDetector.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,20 @@ class SelectedSettingWatcher : public VisualInferenceCallback{
2020
SelectedSettingWatcher(
2121
ImageFloatBox selected_box,
2222
ImageFloatBox not_selected_box1,
23-
ImageFloatBox not_selected_box2
23+
ImageFloatBox not_selected_box2,
24+
ImageFloatBox representative_background = {0.60, 0.02, 0.35, 0.05}
2425
);
2526
virtual ~SelectedSettingWatcher();
2627

2728
virtual void make_overlays(VideoOverlaySet& items) const override;
2829

30+
bool is_white_theme(const ImageViewRGB32& screen);
31+
2932
// return true if the area within the selected_box is highlighted, compared with the area within unselected_box
3033
// This compares the brightness of the selected_box with the unselected_box.
3134
// selected_box: the box where we expect the screen should be highlighted
3235
// not_selected_box 1 and 2: the boxes where we expect the screen should NOT be highlighted. These acts as the control, for comparison.
36+
// representative_background: box around an area that would represent the background. for determining whether this is white or dark mode.
3337
// the average sum of selected_box should be greater than the absolute difference of average sum between unselected_box 1 and 2.
3438
virtual bool process_frame(const ImageViewRGB32& screen, WallClock timestamp) override;
3539

@@ -38,6 +42,7 @@ class SelectedSettingWatcher : public VisualInferenceCallback{
3842
ImageFloatBox m_selected_box;
3943
ImageFloatBox m_not_selected_box1;
4044
ImageFloatBox m_not_selected_box2;
45+
ImageFloatBox m_representative_background;
4146
};
4247

4348

SerialPrograms/Source/PokemonSV/Programs/Farming/PokemonSV_ClaimMysteryGift.cpp

Lines changed: 66 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
*
55
*/
66

7+
#include "CommonTools/Async/InferenceRoutines.h"
78
#include "CommonFramework/GlobalSettingsPanel.h"
89
#include "CommonFramework/Notifications/ProgramNotifications.h"
910
#include "CommonFramework/VideoPipeline/VideoFeed.h"
@@ -12,9 +13,12 @@
1213
#include "NintendoSwitch/Commands/NintendoSwitch_Commands_PushButtons.h"
1314
#include "Pokemon/Pokemon_Strings.h"
1415
#include "PokemonSwSh/Inference/PokemonSwSh_IvJudgeReader.h"
16+
#include "NintendoSwitch/Inference/NintendoSwitch_SelectedSettingDetector.h"
17+
#include "NintendoSwitch/Inference/NintendoSwitch_ConsoleTypeDetector.h"
1518
#include "PokemonSV/Inference/PokemonSV_MainMenuDetector.h"
1619
#include "PokemonSV/Inference/Overworld/PokemonSV_DirectionDetector.h"
1720
#include "PokemonSV/Programs/PokemonSV_GameEntry.h"
21+
#include "PokemonSV/Programs/PokemonSV_SaveGame.h"
1822
#include "PokemonSV/Programs/PokemonSV_MenuNavigation.h"
1923
#include "PokemonSV/Programs/PokemonSV_WorldNavigation.h"
2024
#include "PokemonSV/Programs/AutoStory/PokemonSV_AutoStory.h"
@@ -133,17 +137,68 @@ void ClaimMysteryGift::enter_mystery_gift_code(SingleSwitchProgramEnvironment& e
133137
}
134138

135139
void ClaimMysteryGift::claim_mystery_gift(SingleSwitchProgramEnvironment& env, ProControllerContext& context, int menu_index){
136-
137-
enter_menu_from_overworld(env.program_info(), env.console, context, menu_index);
138-
pbf_press_button(context, BUTTON_A, 20, 4 * TICKS_PER_SECOND);
139-
pbf_press_dpad(context, DPAD_UP, 20, 105);
140-
pbf_press_button(context, BUTTON_A, 20, 4 * TICKS_PER_SECOND);
141-
pbf_press_dpad(context, DPAD_DOWN, 20, 105);
142-
pbf_press_button(context, BUTTON_A, 20, 4 * TICKS_PER_SECOND);
143-
pbf_press_button(context, BUTTON_A, 20, 10 * TICKS_PER_SECOND);
144-
clear_dialog(env.console, context, ClearDialogMode::STOP_TIMEOUT, 10);
145-
146-
enter_mystery_gift_code(env, context);
140+
save_game_from_menu_or_overworld(env.program_info(), env.console, context, false);
141+
142+
size_t max_attempts = 5;
143+
for (size_t i = 0; i < max_attempts; i++){
144+
enter_menu_from_overworld(env.program_info(), env.console, context, menu_index);
145+
pbf_press_button(context, BUTTON_A, 20, 4 * TICKS_PER_SECOND);
146+
pbf_press_dpad(context, DPAD_UP, 20, 105);
147+
pbf_press_button(context, BUTTON_A, 20, 4 * TICKS_PER_SECOND);
148+
pbf_press_dpad(context, DPAD_DOWN, 20, 105);
149+
pbf_press_button(context, BUTTON_A, 20, 4 * TICKS_PER_SECOND);
150+
pbf_press_button(context, BUTTON_A, 20, 10 * TICKS_PER_SECOND);
151+
clear_dialog(env.console, context, ClearDialogMode::STOP_TIMEOUT, 10, {CallbackEnum::PROMPT_DIALOG});
152+
153+
context.wait_for_all_requests();
154+
context.wait_for(Milliseconds(300));
155+
// we expect to be within Mystery Gift window, with the keyboard visible and "1" being highlighted
156+
//
157+
158+
ConsoleType console_type = env.console.state().console_type();
159+
160+
if (console_type == ConsoleType::Unknown){
161+
env.console.log("Unknown Switch type. Try to detect.");
162+
console_type = detect_console_type_from_in_game(env.console, context);
163+
}
164+
165+
ImageFloatBox key1_box;
166+
ImageFloatBox other_setting1;
167+
ImageFloatBox other_setting2;
168+
ImageFloatBox background;
169+
170+
if (is_switch1(console_type)){
171+
key1_box = {0.037322, 0.451172, 0.009879, 0.113281};
172+
other_setting1 = {0.01, 0.451172, 0.009879, 0.113281};
173+
other_setting2 = {0.02, 0.451172, 0.009879, 0.113281};
174+
background = {0.0, 0.451172, 0.009879, 0.113281};
175+
}else if (is_switch2(console_type)){
176+
key1_box = {0.062706, 0.510763, 0.009901, 0.097847};
177+
other_setting1 = {0.02, 0.510763, 0.009901, 0.097847};
178+
other_setting2 = {0.04, 0.510763, 0.009901, 0.097847};
179+
background = {0.0, 0.510763, 0.009901, 0.097847};
180+
}else{
181+
throw UserSetupError(
182+
env.console,
183+
"Please select a valid Switch console type."
184+
);
185+
}
186+
187+
SelectedSettingWatcher key1_selected(key1_box, other_setting1, other_setting2, background);
188+
int ret = wait_until(
189+
env.console, context,
190+
Milliseconds(5000),
191+
{key1_selected}
192+
);
193+
if (ret < 0){ // failed to detect Key 1 being highlighted. Reset game and re-try
194+
env.console.log("claim_mystery_gift: Failed to detect the Mystery Gift window. Reset game and re-try.", COLOR_YELLOW);
195+
reset_game(env.program_info(), env.console, context);
196+
continue;
197+
}
198+
199+
enter_mystery_gift_code(env, context);
200+
return;
201+
}
147202
}
148203

149204
void ClaimMysteryGift::run_autostory_until_pokeportal_unlocked(SingleSwitchProgramEnvironment& env, ProControllerContext& context){

0 commit comments

Comments
 (0)