diff --git a/SerialPrograms/Source/PokemonSV/Programs/Farming/PokemonSV_MaterialFarmerTools.cpp b/SerialPrograms/Source/PokemonSV/Programs/Farming/PokemonSV_MaterialFarmerTools.cpp
index df86938e4..d99be14e4 100644
--- a/SerialPrograms/Source/PokemonSV/Programs/Farming/PokemonSV_MaterialFarmerTools.cpp
+++ b/SerialPrograms/Source/PokemonSV/Programs/Farming/PokemonSV_MaterialFarmerTools.cpp
@@ -68,7 +68,7 @@ MaterialFarmerOptions::MaterialFarmerOptions(
, RUN_TIME_IN_MINUTES(
"Run Duration:
Run the material farmer for this many minutes.",
LockMode::UNLOCK_WHILE_RUNNING,
- 70
+ 32
)
// , SAVE_GAME_BEFORE_SANDWICH(
// "Save Game before each round:",
@@ -165,7 +165,14 @@ void MaterialFarmerOptions::value_changed(void* object){
}
-
+// return new start time, so that minutes remaining is rounded up to a multiple of 32
+WallClock new_start_time_after_reset(WallClock old_start_time, uint16_t run_time_in_minutes){
+ auto farming_time_remaining = minutes_remaining(old_start_time, std::chrono::minutes(run_time_in_minutes));
+ // round up the time to multiple of 32 (30 minutes per sandwich, plus 2 minutes for sandwich making)
+ size_t desired_minutes_remaining = ((farming_time_remaining.count()/32)+1)*32;
+ WallClock new_start_time = current_time() + std::chrono::minutes(desired_minutes_remaining) - std::chrono::minutes(run_time_in_minutes);
+ return new_start_time;
+}
void run_material_farmer(
@@ -184,88 +191,128 @@ void run_material_farmer(
WallClock last_sandwich_time = WallClock::min();
LetsGoHpWatcher hp_watcher(COLOR_RED);
+ // ensure we save before running the material farmer.
+ // but no need to save if already saving prior to each sandwich
+ if (!(options.SANDWICH_OPTIONS.enabled() && options.SANDWICH_OPTIONS.SAVE_GAME_BEFORE_SANDWICH)){
+ save_game_from_overworld(env.program_info(), console, context);
+ }
+
/*
- Use Let's Go along the path. Fly back to pokecenter when it reaches the end of the path.
- Keeping repeating this for RUN_TIME_IN_MINUTES minutes
*/
+ size_t consecutive_failures = 0;
+ size_t max_consecutive_failures = 15;
while (true){
- // check time left on material farming
- auto farming_time_remaining = minutes_remaining(start_time, std::chrono::minutes(options.RUN_TIME_IN_MINUTES));
- console.log(
- "Time left in Material Farming: " +
- std::to_string(farming_time_remaining.count()) + " min",
- COLOR_PURPLE
- );
- if (farming_time_remaining < std::chrono::minutes(0)){
- console.log("Time's up. Stop the Material farming program.", COLOR_RED);
- break;
- }
-
- // Check time left on sandwich
- if (options.SANDWICH_OPTIONS.enabled()){
- auto sandwich_time_remaining = minutes_remaining(last_sandwich_time, std::chrono::minutes(options.TIME_PER_SANDWICH));
+ try{
+ while (true){
+ // check time left on material farming
+ auto farming_time_remaining = minutes_remaining(start_time, std::chrono::minutes(options.RUN_TIME_IN_MINUTES));
console.log(
- "Time left on sandwich: " +
- std::to_string(sandwich_time_remaining.count()) + " min",
+ "Time left in Material Farming: " +
+ std::to_string(farming_time_remaining.count()) + " min",
COLOR_PURPLE
- );
- if (sandwich_time_remaining < std::chrono::minutes(0)){
- console.log("Sandwich not active. Make a sandwich.");
- last_sandwich_time = make_sandwich_material_farm(env, console, context, options, stats);
- console.overlay().add_log("Sandwich made.");
-
- // Log time remaining in Material farming
- farming_time_remaining = minutes_remaining(start_time, std::chrono::minutes(options.RUN_TIME_IN_MINUTES));
- console.log(
- "Time left in Material Farming: " +
- std::to_string(farming_time_remaining.count()) + " min",
- COLOR_PURPLE
- );
- // Log time remaining on Sandwich
- sandwich_time_remaining = minutes_remaining(last_sandwich_time, std::chrono::minutes(options.TIME_PER_SANDWICH));
+ );
+ if (farming_time_remaining < std::chrono::minutes(0)){
+ console.log("Time's up. Stop the Material farming program.", COLOR_RED);
+ return;
+ }
+
+ // Check time left on sandwich
+ if (options.SANDWICH_OPTIONS.enabled()){
+ auto sandwich_time_remaining = minutes_remaining(last_sandwich_time, std::chrono::minutes(options.TIME_PER_SANDWICH));
console.log(
"Time left on sandwich: " +
std::to_string(sandwich_time_remaining.count()) + " min",
COLOR_PURPLE
- );
+ );
+ if (sandwich_time_remaining < std::chrono::minutes(0)){
+ console.log("Sandwich not active. Make a sandwich.");
+ last_sandwich_time = make_sandwich_material_farm(env, console, context, options, stats);
+ console.overlay().add_log("Sandwich made.");
+
+ // Log time remaining in Material farming
+ farming_time_remaining = minutes_remaining(start_time, std::chrono::minutes(options.RUN_TIME_IN_MINUTES));
+ console.log(
+ "Time left in Material Farming: " +
+ std::to_string(farming_time_remaining.count()) + " min",
+ COLOR_PURPLE
+ );
+ // Log time remaining on Sandwich
+ sandwich_time_remaining = minutes_remaining(last_sandwich_time, std::chrono::minutes(options.TIME_PER_SANDWICH));
+ console.log(
+ "Time left on sandwich: " +
+ std::to_string(sandwich_time_remaining.count()) + " min",
+ COLOR_PURPLE
+ );
+ }
}
+
+ // heal before starting Let's go
+ console.log("Heal before starting Let's go", COLOR_PURPLE);
+ console.log("Heal threshold: " + tostr_default(options.AUTO_HEAL_PERCENT), COLOR_PURPLE);
+ check_hp(env, console, context, options, hp_watcher, stats);
+
+ /*
+ - Starts from pokemon center.
+ - Flies to start position. Runs a Let's Go iteration.
+ - Then returns to pokemon center, regardless of whether
+ it completes the action or gets caught in a battle
+ */
+ run_from_battles_and_back_to_pokecenter(env, console, context, stats,
+ [&](ProgramEnvironment& env, ConsoleHandle& console, BotBaseContext& context){
+ // Move to starting position for Let's Go hunting path
+ console.log("Move to starting position for Let's Go hunting path.", COLOR_PURPLE);
+ move_to_start_position_for_letsgo1(console, context);
+
+ // run let's go while updating the HP watcher
+ console.log("Starting Let's Go hunting path.", COLOR_PURPLE);
+ run_until(
+ console, context,
+ [&](BotBaseContext& context){
+ run_lets_go_iteration(console, context, encounter_tracker, options.NUM_FORWARD_MOVES_PER_LETS_GO_ITERATION);
+ },
+ {hp_watcher}
+ );
+ }
+ );
+
+ context.wait_for_all_requests();
}
+ }catch (OperationFailedException& e){
+ stats.m_errors++;
+ env.update_stats();
+ e.send_notification(env, options.NOTIFICATION_ERROR_RECOVERABLE);
- // heal before starting Let's go
- console.log("Heal before starting Let's go", COLOR_PURPLE);
- console.log("Heal threshold: " + tostr_default(options.AUTO_HEAL_PERCENT), COLOR_PURPLE);
- check_hp(env, console, context, options, hp_watcher, stats);
-
- /*
- - Starts from pokemon center.
- - Flies to start position. Runs a Let's Go iteration.
- - Then returns to pokemon center, regardless of whether
- it completes the action or gets caught in a battle
- */
- run_from_battles_and_back_to_pokecenter(env, console, context, stats,
- [&](ProgramEnvironment& env, ConsoleHandle& console, BotBaseContext& context){
- // Move to starting position for Let's Go hunting path
- console.log("Move to starting position for Let's Go hunting path.", COLOR_PURPLE);
- move_to_start_position_for_letsgo1(console, context);
-
- // run let's go while updating the HP watcher
- console.log("Starting Let's Go hunting path.", COLOR_PURPLE);
- run_until(
- console, context,
- [&](BotBaseContext& context){
- run_lets_go_iteration(console, context, encounter_tracker, options.NUM_FORWARD_MOVES_PER_LETS_GO_ITERATION);
- },
- {hp_watcher}
- );
- }
- );
-
- context.wait_for_all_requests();
- }
+ // save screenshot after operation failed,
+ // dump_snapshot(console);
+
+ if (options.SAVE_DEBUG_VIDEO){
+ // Take a video to give more context for debugging
+ pbf_press_button(context, BUTTON_CAPTURE, 2 * TICKS_PER_SECOND, 2 * TICKS_PER_SECOND);
+ context.wait_for_all_requests();
+ }
+ consecutive_failures++;
+ if (consecutive_failures >= max_consecutive_failures){
+ throw e;
+ }
+
+ env.log("Reset game to handle recoverable error.");
+ reset_game(env.program_info(), console, context);
+ stats.m_game_resets++;
+ env.update_stats();
+ // update start time, so that minutes remaining is rounded up to a multiple of 32
+ start_time = new_start_time_after_reset(start_time, options.RUN_TIME_IN_MINUTES);
+ // also update last sandwich time
+ last_sandwich_time = WallClock::min();
+ }
+ }
}
+
+
void check_hp(
ProgramEnvironment& env,
ConsoleHandle& console,
@@ -290,8 +337,8 @@ void check_hp(
-// start at North Province (Area 3) Pokecenter. make sandwich then go back to Pokecenter to reset position
-// return the time that the sandwich was made
+// make sandwich then go back to Pokecenter to reset position
+// if gets caught up in a battle, try again.
WallClock make_sandwich_material_farm(
ProgramEnvironment& env,
ConsoleHandle& console,
@@ -299,60 +346,11 @@ WallClock make_sandwich_material_farm(
MaterialFarmerOptions& options,
MaterialFarmerStats& stats
){
+
if (options.SANDWICH_OPTIONS.SAVE_GAME_BEFORE_SANDWICH){
save_game_from_overworld(env.program_info(), console, context);
}
- WallClock last_sandwich_time;
- size_t consecutive_failures = 0;
- size_t max_consecutive_failures = 10;
- while (true){
- try{
- last_sandwich_time = try_make_sandwich_material_farm(env, console, context, options, stats);
- break;
- }catch(OperationFailedException& e){
- stats.m_errors++;
- env.update_stats();
- e.send_notification(env, options.NOTIFICATION_ERROR_RECOVERABLE);
-
- // save screenshot after operation failed,
- dump_snapshot(console);
-
- if (options.SAVE_DEBUG_VIDEO){
- // Take a video to give more context for debugging
- pbf_press_button(context, BUTTON_CAPTURE, 2 * TICKS_PER_SECOND, 2 * TICKS_PER_SECOND);
- context.wait_for_all_requests();
- }
-
- consecutive_failures++;
- if (consecutive_failures >= max_consecutive_failures){
- throw OperationFailedException(
- ErrorReport::SEND_ERROR_REPORT, console,
- "Failed to make sandwich "+ std::to_string(max_consecutive_failures) + " times in a row.",
- true
- );
- }
-
- env.log("Failed to make sandwich. Reset game to handle recoverable error.");
- reset_game(env.program_info(), console, context);
- stats.m_game_resets++;
- env.update_stats();
- }
- }
-
- return last_sandwich_time;
-}
-
-
-// make sandwich then go back to Pokecenter to reset position
-// if gets caught up in a battle, try again.
-WallClock try_make_sandwich_material_farm(
- ProgramEnvironment& env,
- ConsoleHandle& console,
- BotBaseContext& context,
- MaterialFarmerOptions& options,
- MaterialFarmerStats& stats
-){
WallClock last_sandwich_time = WallClock::min();
while(last_sandwich_time == WallClock::min()){
run_from_battles_and_back_to_pokecenter(env, console, context, stats,
@@ -373,7 +371,7 @@ WallClock try_make_sandwich_material_farm(
// make sandwich
picnic_from_overworld(env.program_info(), console, context);
- pbf_move_left_joystick(context, 128, 0, 30, 40);
+ pbf_move_left_joystick(context, 128, 0, 100, 40); // walk forward to picnic table
enter_sandwich_recipe_list(env.program_info(), console, context);
make_sandwich_option(env, console, context, options.SANDWICH_OPTIONS);
last_sandwich_time = current_time();
@@ -468,7 +466,9 @@ void move_to_start_position_for_letsgo1(
pbf_move_left_joystick(context, 128, 0, 300, 10);
// look right, towards the start position
- pbf_move_right_joystick(context, 255, 128, 130, 10);
+ DirectionDetector direction;
+ direction.change_direction(console, context, 5.76);
+ // pbf_move_right_joystick(context, 255, 128, 130, 10);
pbf_move_left_joystick(context, 128, 0, 10, 10);
// get on ride
@@ -498,7 +498,8 @@ void move_to_start_position_for_letsgo1(
pbf_press_button(context, BUTTON_B, 50, 10);
// look right
- pbf_move_right_joystick(context, 255, 128, 20, 10);
+ // pbf_move_right_joystick(context, 255, 128, 20, 10);
+ direction.change_direction(console, context, 5.46);
// move forward slightly
pbf_move_left_joystick(context, 128, 0, 50, 10);
diff --git a/SerialPrograms/Source/PokemonSV/Programs/Farming/PokemonSV_MaterialFarmerTools.h b/SerialPrograms/Source/PokemonSV/Programs/Farming/PokemonSV_MaterialFarmerTools.h
index 7ea587d12..3569dad53 100644
--- a/SerialPrograms/Source/PokemonSV/Programs/Farming/PokemonSV_MaterialFarmerTools.h
+++ b/SerialPrograms/Source/PokemonSV/Programs/Farming/PokemonSV_MaterialFarmerTools.h
@@ -109,14 +109,6 @@ WallClock make_sandwich_material_farm(
MaterialFarmerStats& stats
);
-WallClock try_make_sandwich_material_farm(
- ProgramEnvironment& env,
- ConsoleHandle& console,
- BotBaseContext& context,
- MaterialFarmerOptions& options,
- MaterialFarmerStats& stats
-);
-
void move_to_start_position_for_letsgo0(ConsoleHandle& console, BotBaseContext& context);
void move_to_start_position_for_letsgo1(ConsoleHandle& console, BotBaseContext& context);
diff --git a/SerialPrograms/Source/PokemonSV/Programs/PokemonSV_Navigation.cpp b/SerialPrograms/Source/PokemonSV/Programs/PokemonSV_Navigation.cpp
index 3a953daae..44f6466fd 100644
--- a/SerialPrograms/Source/PokemonSV/Programs/PokemonSV_Navigation.cpp
+++ b/SerialPrograms/Source/PokemonSV/Programs/PokemonSV_Navigation.cpp
@@ -681,14 +681,13 @@ void fly_to_closest_pokecenter_on_map(const ProgramInfo& info, ConsoleHandle& co
true
);
}
- }catch (OperationFailedException&){ // pokecenter was detected, but failed to fly there
+ }catch (OperationFailedException& e){
try_count++;
if (try_count >= MAX_TRY_COUNT){
- throw OperationFailedException(
- ErrorReport::SEND_ERROR_REPORT, console,
- "fly_to_closest_pokecenter_on_map(): At max warpable map level, pokecenter was detected, but failed to fly there.",
- true
- );
+ // either:
+ // - pokecenter was detected, but failed to fly there.
+ // - could not find pokecenter icon.
+ throw e;
}
console.log("Failed to find the fly menuitem. Restart the closest Pokecenter travel process.");
press_Bs_to_back_to_overworld(info, console, context);
diff --git a/SerialPrograms/Source/PokemonSV/Programs/Sandwiches/PokemonSV_SandwichRoutines.cpp b/SerialPrograms/Source/PokemonSV/Programs/Sandwiches/PokemonSV_SandwichRoutines.cpp
index d12a29454..8b578a965 100644
--- a/SerialPrograms/Source/PokemonSV/Programs/Sandwiches/PokemonSV_SandwichRoutines.cpp
+++ b/SerialPrograms/Source/PokemonSV/Programs/Sandwiches/PokemonSV_SandwichRoutines.cpp
@@ -84,6 +84,8 @@ bool enter_sandwich_recipe_list(const ProgramInfo& info, ConsoleHandle& console,
switch (ret){
case 0:
console.log("Detected picnic. Maybe button A press dropped.");
+ // walk forward and press A again
+ pbf_move_left_joystick(context, 128, 0, 100, 40);
pbf_press_button(context, BUTTON_A, 20, 80);
continue;
case 1: