1919#include " PokemonSV/Inference/Overworld/PokemonSV_StationaryOverworldWatcher.h"
2020#include " PokemonSV/Inference/PokemonSV_MainMenuDetector.h"
2121#include " PokemonSV/Programs/PokemonSV_MenuNavigation.h"
22- #include " PokemonSV/Programs/PokemonSV_WorldNavigation.h"
2322#include " PokemonSV/Programs/PokemonSV_GameEntry.h"
2423#include " PokemonSV/Programs/PokemonSV_SaveGame.h"
2524#include " PokemonSV/Programs/Battles/PokemonSV_Battles.h"
@@ -41,178 +40,7 @@ namespace PokemonSV{
4140
4241
4342
44- // spam A button to choose the first move
45- // throw exception if wipeout or if your lead faints.
46- void run_battle_press_A (
47- VideoStream& stream,
48- ProControllerContext& context,
49- BattleStopCondition stop_condition,
50- std::unordered_set<CallbackEnum> enum_optional_callbacks,
51- bool detect_wipeout
52- ){
53- int16_t num_times_seen_overworld = 0 ;
54- size_t consecutive_move_select = 0 ;
55- while (true ){
56- NormalBattleMenuWatcher battle (COLOR_BLUE);
57- SwapMenuWatcher fainted (COLOR_PURPLE);
58- OverworldWatcher overworld (stream.logger (), COLOR_CYAN);
59- AdvanceDialogWatcher dialog (COLOR_RED);
60- DialogArrowWatcher dialog_arrow (COLOR_RED, stream.overlay (), {0.850 , 0.820 , 0.020 , 0.050 }, 0.8365 , 0.846 );
61- GradientArrowWatcher next_pokemon (COLOR_BLUE, GradientArrowType::RIGHT, {0.50 , 0.51 , 0.30 , 0.10 });
62- MoveSelectWatcher move_select_menu (COLOR_YELLOW);
63-
64- std::vector<PeriodicInferenceCallback> callbacks;
65- std::vector<CallbackEnum> enum_all_callbacks;
66- // mandatory callbacks: Battle, Overworld, Advance Dialog, Swap menu, Move select
67- // optional callbacks: DIALOG_ARROW, NEXT_POKEMON
68-
69- // merge the mandatory and optional callbacks as a set, to avoid duplicates. then convert to vector
70- std::unordered_set<CallbackEnum> enum_all_callbacks_set{CallbackEnum::BATTLE, CallbackEnum::OVERWORLD, CallbackEnum::ADVANCE_DIALOG, CallbackEnum::SWAP_MENU, CallbackEnum::MOVE_SELECT}; // mandatory callbacks
71- enum_all_callbacks_set.insert (enum_optional_callbacks.begin (), enum_optional_callbacks.end ()); // append the mandatory and optional callback sets together
72- enum_all_callbacks.assign (enum_all_callbacks_set.begin (), enum_all_callbacks_set.end ());
73-
74- for (const CallbackEnum& enum_callback : enum_all_callbacks){
75- switch (enum_callback){
76- case CallbackEnum::ADVANCE_DIALOG:
77- callbacks.emplace_back (dialog);
78- break ;
79- case CallbackEnum::OVERWORLD:
80- callbacks.emplace_back (overworld);
81- break ;
82- case CallbackEnum::DIALOG_ARROW:
83- callbacks.emplace_back (dialog_arrow);
84- break ;
85- case CallbackEnum::BATTLE:
86- callbacks.emplace_back (battle);
87- break ;
88- case CallbackEnum::NEXT_POKEMON: // to detect the "next pokemon" prompt.
89- callbacks.emplace_back (next_pokemon);
90- break ;
91- case CallbackEnum::SWAP_MENU: // detecting Swap Menu implies your lead fainted.
92- callbacks.emplace_back (fainted);
93- break ;
94- case CallbackEnum::MOVE_SELECT:
95- callbacks.emplace_back (move_select_menu);
96- break ;
97- default :
98- throw InternalProgramError (nullptr , PA_CURRENT_FUNCTION, " run_battle_press_A: Unknown callback requested." );
99- }
100- }
101- context.wait_for_all_requests ();
102-
103- int ret = wait_until (
104- stream, context,
105- std::chrono::seconds (90 ),
106- callbacks
107- );
108- context.wait_for (std::chrono::milliseconds (100 ));
109- if (ret < 0 ){
110- OperationFailedException::fire (
111- ErrorReport::SEND_ERROR_REPORT,
112- " run_battle_press_A(): Timed out. Did not detect expected stop condition." ,
113- stream
114- );
115- }
11643
117- CallbackEnum enum_callback = enum_all_callbacks[ret];
118- switch (enum_callback){
119- case CallbackEnum::BATTLE: // battle
120- stream.log (" Detected battle menu." );
121- consecutive_move_select = 0 ;
122- pbf_press_button (context, BUTTON_A, 20 , 105 );
123- break ;
124- case CallbackEnum::MOVE_SELECT:
125- stream.log (" Detected move select. Spam first move" );
126- consecutive_move_select++;
127- select_top_move (stream, context, consecutive_move_select);
128- break ;
129- case CallbackEnum::OVERWORLD: // overworld
130- stream.log (" Detected overworld, battle over." );
131- num_times_seen_overworld++;
132- if (stop_condition == BattleStopCondition::STOP_OVERWORLD){
133- return ;
134- }
135- if (num_times_seen_overworld > 30 ){
136- OperationFailedException::fire (
137- ErrorReport::SEND_ERROR_REPORT,
138- " run_battle_press_A(): Stuck in overworld. Did not detect expected stop condition." ,
139- stream
140- );
141- }
142- break ;
143- case CallbackEnum::ADVANCE_DIALOG: // advance dialog
144- stream.log (" Detected dialog." );
145-
146- if (detect_wipeout){
147- context.wait_for_all_requests ();
148- WipeoutDetector wipeout;
149- VideoSnapshot screen = stream.video ().snapshot ();
150- // dump_snapshot(console);
151- if (wipeout.detect (screen)){
152- OperationFailedException::fire (
153- ErrorReport::SEND_ERROR_REPORT,
154- " run_battle_press_A(): Detected wipeout. All pokemon fainted." ,
155- stream
156- );
157- }
158- }
159-
160- if (stop_condition == BattleStopCondition::STOP_DIALOG){
161- return ;
162- }
163- pbf_press_button (context, BUTTON_A, 20 , 105 );
164- break ;
165- case CallbackEnum::DIALOG_ARROW: // dialog arrow
166- stream.log (" run_battle_press_A: Detected dialog arrow." );
167- pbf_press_button (context, BUTTON_A, 20 , 105 );
168- break ;
169- case CallbackEnum::NEXT_POKEMON:
170- stream.log (" run_battle_press_A: Detected prompt for bringing in next pokemon. Keep current pokemon." );
171- pbf_mash_button (context, BUTTON_B, 100 );
172- break ;
173- case CallbackEnum::SWAP_MENU:
174- OperationFailedException::fire (
175- ErrorReport::SEND_ERROR_REPORT,
176- " run_battle_press_A(): Lead pokemon fainted." ,
177- stream
178- );
179- default :
180- throw InternalProgramError (nullptr , PA_CURRENT_FUNCTION, " run_battle_press_A: Unknown callback triggered." );
181-
182- }
183- }
184- }
185-
186- void run_trainer_battle_press_A (
187- VideoStream& stream,
188- ProControllerContext& context,
189- BattleStopCondition stop_condition,
190- std::unordered_set<CallbackEnum> enum_optional_callbacks,
191- bool detect_wipeout
192- ){
193- enum_optional_callbacks.insert (CallbackEnum::NEXT_POKEMON); // always check for the "Next pokemon" prompt when in trainer battles
194- run_battle_press_A (stream, context, stop_condition, enum_optional_callbacks, detect_wipeout);
195- }
196-
197- void run_wild_battle_press_A (
198- VideoStream& stream,
199- ProControllerContext& context,
200- BattleStopCondition stop_condition,
201- std::unordered_set<CallbackEnum> enum_optional_callbacks,
202- bool detect_wipeout
203- ){
204- run_battle_press_A (stream, context, stop_condition, enum_optional_callbacks, detect_wipeout);
205- }
206-
207- void select_top_move (VideoStream& stream, ProControllerContext& context, size_t consecutive_move_select){
208- if (consecutive_move_select > 3 ){
209- // to handle case where move is disabled/out of PP/taunted
210- stream.log (" Failed to select a move 3 times. Choosing a different move." , COLOR_RED);
211- pbf_press_dpad (context, DPAD_DOWN, 20 , 40 );
212- }
213- pbf_mash_button (context, BUTTON_A, 100 );
214-
215- }
21644
21745void clear_tutorial (VideoStream& stream, ProControllerContext& context, uint16_t seconds_timeout){
21846 bool seen_tutorial = false ;
@@ -1060,7 +888,7 @@ void realign_player_from_landmark(
1060888 pbf_move_left_joystick (context, move_x1, move_y1, move_duration1, 1 * TICKS_PER_SECOND);
1061889
1062890 // move cursor to pokecenter
1063- if (!detect_closest_pokecenter_and_move_map_cursor_there (info, stream, context, 0.29 )){
891+ if (!detect_closest_flypoint_and_move_map_cursor_there (info, stream, context, FlyPoint::POKECENTER , 0.29 )){
1064892 OperationFailedException::fire (
1065893 ErrorReport::SEND_ERROR_REPORT,
1066894 " realign_player_from_landmark(): No visible pokecenter found on map." ,
@@ -1133,7 +961,8 @@ void move_cursor_towards_flypoint_and_go_there(
1133961 const ProgramInfo& info,
1134962 VideoStream& stream,
1135963 ProControllerContext& context,
1136- MoveCursor move_cursor_near_flypoint
964+ MoveCursor move_cursor_near_flypoint,
965+ FlyPoint fly_point
1137966){
1138967 WallClock start = current_time ();
1139968
@@ -1173,7 +1002,7 @@ void move_cursor_towards_flypoint_and_go_there(
11731002 uint16_t move_duration1 = move_cursor_near_flypoint.move_duration ;
11741003 pbf_move_left_joystick (context, move_x1, move_y1, move_duration1, 1 * TICKS_PER_SECOND);
11751004
1176- if (!fly_to_visible_closest_pokecenter_cur_zoom_level (info, stream, context)){
1005+ if (!fly_to_visible_closest_flypoint_cur_zoom_level (info, stream, context, fly_point )){
11771006 OperationFailedException::fire (
11781007 ErrorReport::SEND_ERROR_REPORT,
11791008 " move_cursor_towards_flypoint_and_go_there(): No visible pokecenter found on map." ,
0 commit comments