@@ -41,6 +41,8 @@ language
4141#include " CommonTools/StartupChecks/StartProgramChecks.h"
4242#include " NintendoSwitch/Commands/NintendoSwitch_Commands_PushButtons.h"
4343#include " Pokemon/Pokemon_Strings.h"
44+ #include " Pokemon/Resources/Pokemon_PokemonNames.h"
45+ #include " Pokemon/Resources/Pokemon_PokemonSlugs.h"
4446#include " PokemonHome/Inference/PokemonHome_BoxGenderDetector.h"
4547#include " PokemonHome/Inference/PokemonHome_BallReader.h"
4648#include " PokemonHome_BoxSorting.h"
@@ -261,28 +263,28 @@ std::ostream& operator<<(std::ostream& os, const std::optional<Pokemon>& pokemon
261263 return os;
262264}
263265
266+ // Move the red cursor to the first slot of the box
267+ // If the cursor is not add the first slot, move the cursor to the left and up one row at a time until it is at the first slot.
264268bool go_to_first_slot (SingleSwitchProgramEnvironment& env, ProControllerContext& context, uint16_t VIDEO_DELAY){
265-
266- ImageFloatBox cursor_check (0.07 , 0.15 , 0.01 , 0.01 ); // cursor position of the first slot of the box
269+ ImageFloatBox first_slot_cursor_box (0.07 , 0.15 , 0.01 , 0.01 ); // cursor position of the first slot of the box
267270 VideoSnapshot screen = env.console .video ().snapshot ();
268- FloatPixel image_value = image_stats (extract_box_reference (screen, cursor_check )).average ;
269- env.console .log (" Cursor color detection: " + image_value .to_string ());
271+ FloatPixel first_slot_cursor_color = image_stats (extract_box_reference (screen, first_slot_cursor_box )).average ;
272+ env.console .log (" Cursor color detection: " + first_slot_cursor_color .to_string ());
270273 VideoOverlaySet BoxRender (env.console );
274+ BoxRender.add (COLOR_BLUE, first_slot_cursor_box);
271275
272- BoxRender.add (COLOR_BLUE, cursor_check);
273- if (image_value.r <= image_value.g + image_value.b ){
274-
276+ // If the cursor is not at the first slot
277+ if (first_slot_cursor_color.r <= first_slot_cursor_color.g + first_slot_cursor_color.b ){
275278 bool cursor_found = false ;
276-
277279 for (uint8_t rows = 0 ; rows < 7 ; rows++){
278280 for (uint8_t column = 0 ; column < 5 ; column++){
279281 pbf_press_dpad (context, DPAD_LEFT, 10 , VIDEO_DELAY);
280282 context.wait_for_all_requests ();
281283 screen = env.console .video ().snapshot ();
282- image_value = image_stats (extract_box_reference (screen, cursor_check )).average ;
283- env.console .log (" Cursor color detection: " + image_value .to_string ());
284+ first_slot_cursor_color = image_stats (extract_box_reference (screen, first_slot_cursor_box )).average ;
285+ env.console .log (" Cursor color detection: " + first_slot_cursor_color .to_string ());
284286
285- if (image_value .r > image_value .g + image_value .b ){
287+ if (first_slot_cursor_color .r > first_slot_cursor_color .g + first_slot_cursor_color .b ){
286288 cursor_found = true ;
287289 break ;
288290 }
@@ -291,10 +293,10 @@ bool go_to_first_slot(SingleSwitchProgramEnvironment& env, ProControllerContext&
291293 pbf_press_dpad (context, DPAD_UP, 10 , VIDEO_DELAY);
292294 context.wait_for_all_requests ();
293295 screen = env.console .video ().snapshot ();
294- image_value = image_stats (extract_box_reference (screen, cursor_check )).average ;
295- env.console .log (" Cursor color detection: " + image_value .to_string ());
296+ first_slot_cursor_color = image_stats (extract_box_reference (screen, first_slot_cursor_box )).average ;
297+ env.console .log (" Cursor color detection: " + first_slot_cursor_color .to_string ());
296298
297- if (image_value .r > image_value .g + image_value .b ){
299+ if (first_slot_cursor_color .r > first_slot_cursor_color .g + first_slot_cursor_color .b ){
298300 cursor_found = true ;
299301 break ;
300302 }
@@ -410,7 +412,10 @@ void do_sort(
410412 BoxSorting_Descriptor::Stats& stats,
411413 Cursor& cur_cursor,
412414 uint16_t GAME_DELAY
413- ){
415+ ){
416+ env.log (" Start sorting..." );
417+ env.add_overlay_log (" Start Sorting..." );
418+
414419 std::ostringstream ss;
415420 // this need to be separated into functions when I will redo the whole thing but I just wanted it to work
416421
@@ -528,38 +533,38 @@ void BoxSorting::program(SingleSwitchProgramEnvironment& env, ProControllerConte
528533 box_render.clear ();
529534
530535 Cursor dest_cursor;
531- std::vector<size_t > first_poke_slot;
532536 Cursor nav_cursor = {0 , 0 , 0 };
533- bool find_first_poke;
534537
535538 // cycle through each box
536- for (size_t box_nb = 0 ; box_nb < BOX_NUMBER; box_nb ++){
537-
538- if (box_nb != 0 ){
539+ for (size_t box_idx = 0 ; box_idx < BOX_NUMBER; box_idx ++){
540+ if (box_idx != 0 ){
541+ // Press button R to move to next box
539542 pbf_press_button (context, BUTTON_R, 10 , VIDEO_DELAY+100 );
540- context.wait_for_all_requests ();
541543 }else {
542544 // Moving the cursor until it goes to the first slot
543545 if (!go_to_first_slot (env, context, VIDEO_DELAY)){
544546 env.console .log (" ERROR: Could not move cursor to the first slot, please consider adjusting delay\n " , COLOR_RED);
545547 return ;
546548 }
547- context.wait_for_all_requests ();
548549 }
549550
551+ context.wait_for_all_requests ();
552+ const std::string log_msg = " Checking box " + std::to_string (box_idx+1 ) + " /" + std::to_string (BOX_NUMBER);
553+ env.log (log_msg);
554+ env.console .overlay ().add_log (log_msg);
555+
550556 screen = env.console .video ().snapshot ();
551557
552558 // Box grid to find empty slots (red boxes) and fill boxes_data with value to check or not for pokemon dex number
553559
554560 ss << " \n " ;
555561
556- first_poke_slot = {0 , 0 };
557- find_first_poke = false ;
562+ std::array< size_t , 2 > first_poke_slot = {0 , 0 };
563+ bool find_first_poke = false ;
558564
565+ int num_empty_slots = 0 ;
559566 for (size_t row = 0 ; row < MAX_ROWS; row++){
560-
561567 for (size_t column = 0 ; column < MAX_COLUMNS; column++){
562-
563568 ImageFloatBox slot_box (0.06 + (0.072 * column), 0.2 + (0.1035 * row), 0.03 , 0.057 );
564569 int current_box_value = (int )image_stddev (extract_box_reference (screen, slot_box)).sum ();
565570
@@ -569,6 +574,7 @@ void BoxSorting::program(SingleSwitchProgramEnvironment& env, ProControllerConte
569574 if (current_box_value < 10 ){
570575 box_render.add (COLOR_RED, slot_box);
571576 stats.empty ++;
577+ num_empty_slots++;
572578 env.update_stats ();
573579 boxes_data.push_back (std::nullopt ); // empty optional to make sorting easier later
574580 ss << " \u274c " ; // "X"
@@ -590,16 +596,18 @@ void BoxSorting::program(SingleSwitchProgramEnvironment& env, ProControllerConte
590596 }
591597 ss << " \n " ;
592598 }
593-
594599 env.console .log (ss.str ());
600+ env.add_overlay_log (" Empty: " + std::to_string (num_empty_slots) + " /30" );
595601 ss.str (" " );
596602
597603 // moving cursor to the first pokemon slot
598604 dest_cursor = {0 , first_poke_slot[1 ], first_poke_slot[0 ]};
599605 nav_cursor = move_cursor_to (env, context, nav_cursor, dest_cursor, GAME_DELAY);
600606
601- // enter the summary screen
602- if (find_first_poke == true ){
607+ // enter the summary screen to read pokemon info
608+ if (find_first_poke){
609+ env.add_overlay_log (" Checking Summary..." );
610+
603611 pbf_press_button (context, BUTTON_A, 10 , GAME_DELAY);
604612 context.wait_for_all_requests ();
605613 box_render.clear ();
@@ -621,50 +629,55 @@ void BoxSorting::program(SingleSwitchProgramEnvironment& env, ProControllerConte
621629 // cycle through each summary of the current box and fill pokemon information
622630 for (size_t row = 0 ; row < MAX_ROWS; row++){
623631 for (size_t column = 0 ; column < MAX_COLUMNS; column++){
632+ if (!boxes_data[get_index (box_idx, row, column)].has_value ()){
633+ continue ;
634+ }
624635
625- if (boxes_data[get_index (box_nb, row, column)].has_value ()){
626- screen = env.console .video ().snapshot ();
636+ screen = env.console .video ().snapshot ();
627637
628- int national_dex_number = OCR::read_number_waterfill (env.console , extract_box_reference (screen, national_dex_number_box), 0xff808080 , 0xffffffff );
629- if (national_dex_number < 0 || national_dex_number > 1025 ) {
630- dump_image (env.console , ProgramInfo (), " ReadSummary_national_dex_number" , screen);
631- }
632- boxes_data[get_index (box_nb , row, column)]->national_dex_number = (uint16_t )national_dex_number;
638+ int national_dex_number = OCR::read_number_waterfill (env.console , extract_box_reference (screen, national_dex_number_box), 0xff808080 , 0xffffffff );
639+ if (national_dex_number <= 0 || national_dex_number > 1025 ) { // Current last pokemon is pecharunt
640+ dump_image (env.console , ProgramInfo (), " ReadSummary_national_dex_number" , screen);
641+ }
642+ boxes_data[get_index (box_idx , row, column)]->national_dex_number = (uint16_t )national_dex_number;
633643
634- int shiny_stddev_value = (int )image_stddev (extract_box_reference (screen, shiny_symbol_box)).sum ();
635- bool is_shiny = shiny_stddev_value > 30 ;
636- boxes_data[get_index (box_nb , row, column)]->shiny = is_shiny;
637- env.console .log (" Shiny detection stddev:" + std::to_string (shiny_stddev_value) + " is shiny:" + std::to_string (is_shiny));
644+ int shiny_stddev_value = (int )image_stddev (extract_box_reference (screen, shiny_symbol_box)).sum ();
645+ bool is_shiny = shiny_stddev_value > 30 ;
646+ boxes_data[get_index (box_idx , row, column)]->shiny = is_shiny;
647+ env.console .log (" Shiny detection stddev:" + std::to_string (shiny_stddev_value) + " is shiny:" + std::to_string (is_shiny));
638648
639- int gmax_stddev_value = (int )image_stddev (extract_box_reference (screen, gmax_symbol_box)).sum ();
640- bool is_gmax = gmax_stddev_value > 30 ;
641- boxes_data[get_index (box_nb , row, column)]->gmax = is_gmax;
642- env.console .log (" Gmax detection stddev:" + std::to_string (gmax_stddev_value) + " is gmax:" + std::to_string (is_gmax));
649+ int gmax_stddev_value = (int )image_stddev (extract_box_reference (screen, gmax_symbol_box)).sum ();
650+ bool is_gmax = gmax_stddev_value > 30 ;
651+ boxes_data[get_index (box_idx , row, column)]->gmax = is_gmax;
652+ env.console .log (" Gmax detection stddev:" + std::to_string (gmax_stddev_value) + " is gmax:" + std::to_string (is_gmax));
643653
644- BallReader ball_reader (env.console );
645- boxes_data[get_index (box_nb , row, column)]->ball_slug = ball_reader.read_ball (screen);
654+ BallReader ball_reader (env.console );
655+ boxes_data[get_index (box_idx , row, column)]->ball_slug = ball_reader.read_ball (screen);
646656
647- BoxGenderDetector::make_overlays (box_render);
648- StatsHuntGenderFilter gender = BoxGenderDetector::detect (screen);
649- env.console .log (" Gender: " + gender_to_string (gender), COLOR_GREEN);
650- boxes_data[get_index (box_nb , row, column)]->gender = gender;
657+ BoxGenderDetector::make_overlays (box_render);
658+ StatsHuntGenderFilter gender = BoxGenderDetector::detect (screen);
659+ env.console .log (" Gender: " + gender_to_string (gender), COLOR_GREEN);
660+ boxes_data[get_index (box_idx , row, column)]->gender = gender;
651661
652- int ot_id = OCR::read_number_waterfill (env.console , extract_box_reference (screen, ot_id_box), 0xff808080 , 0xffffffff );
653- if (ot_id < 0 || ot_id > 999'999 ) {
654- dump_image (env.console , ProgramInfo (), " ReadSummary_OT" , screen);
655- }
656- boxes_data[get_index (box_nb , row, column)]->ot_id = ot_id;
662+ int ot_id = OCR::read_number_waterfill (env.console , extract_box_reference (screen, ot_id_box), 0xff808080 , 0xffffffff );
663+ if (ot_id < 0 || ot_id > 999'999 ) {
664+ dump_image (env.console , ProgramInfo (), " ReadSummary_OT" , screen);
665+ }
666+ boxes_data[get_index (box_idx , row, column)]->ot_id = ot_id;
657667
658- // NOTE edit when adding new struct members (detections go here likely)
668+ const std::string& species_slug = NATIONAL_DEX_SLUGS ()[national_dex_number-1 ];
669+ const std::string& display_name = get_pokemon_name (species_slug).display_name ();
670+ env.add_overlay_log (" Read " + display_name);
659671
660- // level_box
661- // ot_box
662- // nature_box
663- // ability_box
672+ // NOTE edit when adding new struct members (detections go here likely)
664673
665- pbf_press_button (context, BUTTON_R, 10 , VIDEO_DELAY+15 );
666- context.wait_for_all_requests ();
667- }
674+ // level_box
675+ // ot_box
676+ // nature_box
677+ // ability_box
678+
679+ pbf_press_button (context, BUTTON_R, 10 , VIDEO_DELAY+15 );
680+ context.wait_for_all_requests ();
668681 }
669682 }
670683
@@ -675,7 +688,7 @@ void BoxSorting::program(SingleSwitchProgramEnvironment& env, ProControllerConte
675688 // print box information
676689 for (size_t row = 0 ; row < MAX_ROWS; row++){
677690 for (size_t column = 0 ; column < MAX_COLUMNS; column++){
678- ss << boxes_data[get_index (box_nb , row, column)] << " " ;
691+ ss << boxes_data[get_index (box_idx , row, column)] << " " ;
679692 }
680693 ss << std::endl;
681694 }
@@ -694,7 +707,7 @@ void BoxSorting::program(SingleSwitchProgramEnvironment& env, ProControllerConte
694707 dest_cursor = {0 , 0 , 0 };
695708 nav_cursor = move_cursor_to (env, context, nav_cursor, dest_cursor, GAME_DELAY);
696709 context.wait_for_all_requests ();
697- }
710+ } // end if (find_first_poke){
698711
699712 // copy boxes data to sort
700713 std::vector<std::optional<Pokemon>> boxes_sorted = boxes_data;
0 commit comments