diff --git a/SerialPrograms/Source/VideoGames/PokemonFRLG/PokemonFRLG_Panels.cpp b/SerialPrograms/Source/VideoGames/PokemonFRLG/PokemonFRLG_Panels.cpp index 430858dd9d..829a795624 100644 --- a/SerialPrograms/Source/VideoGames/PokemonFRLG/PokemonFRLG_Panels.cpp +++ b/SerialPrograms/Source/VideoGames/PokemonFRLG/PokemonFRLG_Panels.cpp @@ -39,6 +39,7 @@ #include "Programs/TestPrograms/PokemonFRLG_ReadBattleLevelUp.h" #include "Programs/TestPrograms/PokemonFRLG_ReadTrainerId.h" #include "Programs/TestPrograms/PokemonFRLG_ReadEncounter.h" +#include "Programs/TestPrograms/PokemonFRLG_ReadBoxInfo.h" #include "Programs/TestPrograms/PokemonFRLG_SafariOptimalActionTest.h" #include "Programs/TestPrograms/PokemonFRLG_TestPartyInference.h" @@ -100,6 +101,7 @@ std::vector PanelListFactory::make_panels() const{ ret.emplace_back(make_SingleSwitchProgram()); ret.emplace_back(make_SingleSwitchProgram()); ret.emplace_back(make_SingleSwitchProgram()); + ret.emplace_back(make_SingleSwitchProgram()); ret.emplace_back(make_SingleSwitchProgram()); ret.emplace_back(make_SingleSwitchProgram()); } diff --git a/SerialPrograms/Source/VideoGames/PokemonFRLG/Programs/TestPrograms/PokemonFRLG_ReadBoxInfo.cpp b/SerialPrograms/Source/VideoGames/PokemonFRLG/Programs/TestPrograms/PokemonFRLG_ReadBoxInfo.cpp new file mode 100644 index 0000000000..5925c1f33f --- /dev/null +++ b/SerialPrograms/Source/VideoGames/PokemonFRLG/Programs/TestPrograms/PokemonFRLG_ReadBoxInfo.cpp @@ -0,0 +1,109 @@ +/* Read Box Info + * + * From: https://github.com/PokemonAutomation/ + * + */ + +#include +#include +#include "CommonFramework/VideoPipeline/VideoFeed.h" +#include "CommonFramework/VideoPipeline/VideoOverlayScopes.h" +#include "Pokemon/Pokemon_Strings.h" +#include "Pokemon/Inference/Pokemon_NameReader.h" +#include "VideoGames/PokemonFRLG/Inference/Box/PokemonFRLG_BoxCellOccupiedDetector.h" +#include "VideoGames/PokemonFRLG/Inference/Box/PokemonFRLG_BoxCellReader.h" +#include "VideoGames/PokemonFRLG/Inference/Box/PokemonFRLG_BoxGenderReader.h" +#include "VideoGames/PokemonFRLG/Inference/Box/PokemonFRLG_BoxSelectionModeDetector.h" +#include "PokemonFRLG_ReadBoxInfo.h" + +namespace PokemonAutomation{ +namespace NintendoSwitch{ +namespace PokemonFRLG{ + +ReadBoxInfo_Descriptor::ReadBoxInfo_Descriptor() + : SingleSwitchProgramDescriptor( + "PokemonFRLG:ReadBoxInfo", + Pokemon::STRING_POKEMON + " FRLG", "Read Box Info", "", + "Start on the box screen. Read one frame and log the selection hand, " + "cursor location, occupancy, species, level, and gender. ", + PanelQualityStanding::DEVELOPER, + ProgramControllerClass::StandardController_NoRestrictions, + FeedbackType::REQUIRED, + AllowCommandsWhenRunning::DISABLE_COMMANDS + ) +{} + +ReadBoxInfo::ReadBoxInfo() + : LANGUAGE( + "Game Language:", + Pokemon::PokemonNameReader::instance().languages(), + LockMode::LOCK_WHILE_RUNNING, true + ) +{ + PA_ADD_OPTION(LANGUAGE); +} + +void ReadBoxInfo::program(SingleSwitchProgramEnvironment& env, CancellableScope& scope){ + BoxSelectionModeDetector selection_detector(COLOR_YELLOW); + BoxCellOccupiedDetector occupied_detector(COLOR_GREEN); + BoxCellReader cell_reader(COLOR_RED); + BoxGenderReader gender_reader(COLOR_BLUE); + VideoOverlaySet overlays(env.console.overlay()); + selection_detector.make_overlays(overlays); + occupied_detector.make_overlays(overlays); + cell_reader.make_overlays(overlays); + gender_reader.make_overlays(overlays); + + env.log("Reading FRLG box inference from one frame..."); + const VideoSnapshot screen = env.console.video().snapshot(); + if (!screen){ + env.log("Box inference: no video frame available.", COLOR_RED); + return; + } + + const auto selection = selection_detector.detect(screen); + const bool occupied = occupied_detector.detect(screen); + const std::string species = cell_reader.read_name(env.logger(), LANGUAGE, screen); + const int level = cell_reader.read_level(env.logger(), screen); + const auto gender = gender_reader.read(screen); + + // Print the report after OCR diagnostics so the results stay together. + std::ostringstream report; + report << "========== FRLG Box Inference ==========\n" + << "Selection hand\n" + << " Detected: " << (selection ? "Yes" : "No") << '\n'; + if (selection){ + report << " Mode: " << (selection->mode == BoxSelectionMode::Normal ? "Normal (white)" : "Relocate (gold)") << '\n' + << " Hand: " << (selection->closed ? "Closed" : "Open") << '\n' + << " Location: "; + switch (selection->location){ + case BoxSelectionLocation::Grid: + report << "Grid - row " << selection->row + 1 << ", column " << selection->column + 1 << " (1-based)"; + break; + case BoxSelectionLocation::BoxTile: + report << "Box title"; + break; + case BoxSelectionLocation::OpenPartyButton: + report << "Party Pokemon button"; + break; + case BoxSelectionLocation::CloseBoxButton: + report << "Close Box button"; + break; + } + report << '\n'; + }else{ + report << " Mode/hand/location: Unknown\n"; + } + report << "Selected Pokemon panel\n" + << " Occupied: " << (occupied ? "Yes" : "No") << '\n' + << " Species: " << (species.empty() ? "(empty or unreadable)" : species) << '\n' + << " Level: " << (level == -1 ? "(empty or unreadable: -1)" : std::to_string(level)) << '\n' + << " Gender: " << Pokemon::gender_to_string(gender) << '\n' + << "========================================"; + env.log(report.str(), COLOR_BLUE); + scope.wait_for(std::chrono::seconds(10)); +} + +} +} +} diff --git a/SerialPrograms/Source/VideoGames/PokemonFRLG/Programs/TestPrograms/PokemonFRLG_ReadBoxInfo.h b/SerialPrograms/Source/VideoGames/PokemonFRLG/Programs/TestPrograms/PokemonFRLG_ReadBoxInfo.h new file mode 100644 index 0000000000..141b719a9b --- /dev/null +++ b/SerialPrograms/Source/VideoGames/PokemonFRLG/Programs/TestPrograms/PokemonFRLG_ReadBoxInfo.h @@ -0,0 +1,37 @@ +/* Read Box Info + * + * From: https://github.com/PokemonAutomation/ + * + */ + +#ifndef PokemonAutomation_PokemonFRLG_ReadBoxInfo_H +#define PokemonAutomation_PokemonFRLG_ReadBoxInfo_H + +#include "CommonTools/Options/LanguageOCROption.h" +#include "NintendoSwitch/NintendoSwitch_SingleSwitchProgram.h" + +namespace PokemonAutomation{ +namespace NintendoSwitch{ +namespace PokemonFRLG{ + +class ReadBoxInfo_Descriptor : public SingleSwitchProgramDescriptor{ +public: + ReadBoxInfo_Descriptor(); +}; + +class ReadBoxInfo : public SingleSwitchProgramInstance{ +public: + using Descriptor = ReadBoxInfo_Descriptor; + ReadBoxInfo(); + + virtual void start_program_border_check(VideoStream& stream, FeedbackType feedback_type) override{} + virtual void program(SingleSwitchProgramEnvironment& env, CancellableScope& scope) override; + +private: + OCR::LanguageOCROption LANGUAGE; +}; + +} +} +} +#endif diff --git a/SerialPrograms/cmake/SourceFiles.cmake b/SerialPrograms/cmake/SourceFiles.cmake index 5c5468e44d..26456c8e8d 100644 --- a/SerialPrograms/cmake/SourceFiles.cmake +++ b/SerialPrograms/cmake/SourceFiles.cmake @@ -1826,6 +1826,8 @@ file(GLOB LIBRARY_SOURCES Source/VideoGames/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_ShinyHunt-Overworld.h Source/VideoGames/PokemonFRLG/Programs/TestPrograms/PokemonFRLG_ReadBattleLevelUp.cpp Source/VideoGames/PokemonFRLG/Programs/TestPrograms/PokemonFRLG_ReadBattleLevelUp.h + Source/VideoGames/PokemonFRLG/Programs/TestPrograms/PokemonFRLG_ReadBoxInfo.cpp + Source/VideoGames/PokemonFRLG/Programs/TestPrograms/PokemonFRLG_ReadBoxInfo.h Source/VideoGames/PokemonFRLG/Programs/TestPrograms/PokemonFRLG_ReadEncounter.cpp Source/VideoGames/PokemonFRLG/Programs/TestPrograms/PokemonFRLG_ReadEncounter.h Source/VideoGames/PokemonFRLG/Programs/TestPrograms/PokemonFRLG_ReadStats.cpp