From 0fa7994d389cfc8a509a88e4d7f98c83140d5674 Mon Sep 17 00:00:00 2001 From: Dalton-V Date: Sat, 31 Oct 2026 21:34:02 -0500 Subject: [PATCH 1/2] Add PokemonFRLG BoxSorter --- .../PokemonFRLG/PokemonFRLG_Panels.cpp | 6 +- .../BoxOrganization/PokemonFRLG_BoxSorter.cpp | 106 ++++++++++++++++++ .../BoxOrganization/PokemonFRLG_BoxSorter.h | 52 +++++++++ SerialPrograms/cmake/SourceFiles.cmake | 2 + 4 files changed, 163 insertions(+), 3 deletions(-) create mode 100644 SerialPrograms/Source/VideoGames/PokemonFRLG/Programs/BoxOrganization/PokemonFRLG_BoxSorter.cpp create mode 100644 SerialPrograms/Source/VideoGames/PokemonFRLG/Programs/BoxOrganization/PokemonFRLG_BoxSorter.h diff --git a/SerialPrograms/Source/VideoGames/PokemonFRLG/PokemonFRLG_Panels.cpp b/SerialPrograms/Source/VideoGames/PokemonFRLG/PokemonFRLG_Panels.cpp index 829a795624..7db5e9c999 100644 --- a/SerialPrograms/Source/VideoGames/PokemonFRLG/PokemonFRLG_Panels.cpp +++ b/SerialPrograms/Source/VideoGames/PokemonFRLG/PokemonFRLG_Panels.cpp @@ -10,14 +10,13 @@ #include "PokemonFRLG_Panels.h" #include "PokemonFRLG_Settings.h" - +#include "Programs/BoxOrganization/PokemonFRLG_BoxSorter.h" #include "Programs/Farming/PokemonFRLG_EliteFourFarmer.h" #include "Programs/Farming/PokemonFRLG_HeldItemFarmer-SafariZone.h" #include "Programs/Farming/PokemonFRLG_ItemDuplication.h" #include "Programs/Farming/PokemonFRLG_NuggetBridgeFarmer.h" #include "Programs/Farming/PokemonFRLG_PickupFarmer.h" #include "Programs/Farming/PokemonFRLG_EvTrainer.h" - #include "Programs/ShinyHunting/PokemonFRLG_GiftReset.h" #include "Programs/ShinyHunting/PokemonFRLG_LegendaryReset.h" #include "Programs/ShinyHunting/PokemonFRLG_LegendaryRunAway.h" @@ -91,7 +90,8 @@ std::vector PanelListFactory::make_panels() const{ ret.emplace_back(make_SingleSwitchProgram()); if (IS_BETA_VERSION || STATIC_GLOBALS.DEVELOPER_MODE){ -// ret.emplace_back("---- Untested/Beta/WIP ----"); + ret.emplace_back("---- Untested/Beta/WIP ----"); + ret.emplace_back(make_SingleSwitchProgram()); } if (STATIC_GLOBALS.DEVELOPER_MODE){ diff --git a/SerialPrograms/Source/VideoGames/PokemonFRLG/Programs/BoxOrganization/PokemonFRLG_BoxSorter.cpp b/SerialPrograms/Source/VideoGames/PokemonFRLG/Programs/BoxOrganization/PokemonFRLG_BoxSorter.cpp new file mode 100644 index 0000000000..d6386442b5 --- /dev/null +++ b/SerialPrograms/Source/VideoGames/PokemonFRLG/Programs/BoxOrganization/PokemonFRLG_BoxSorter.cpp @@ -0,0 +1,106 @@ +/* Box Sorter + * + * From: https://github.com/PokemonAutomation/ + * + */ + +#include +#include "Common/Cpp/Exceptions.h" +#include "CommonFramework/Notifications/ProgramNotifications.h" +#include "CommonTools/StartupChecks/StartProgramChecks.h" +#include "Pokemon/Pokemon_CollectedPokemonInfo.h" +#include "Pokemon/Pokemon_Strings.h" +#include "PokemonFRLG_BoxOrganization.h" +#include "VideoGames/PokemonFRLG/PokemonFRLG_Navigation.h" +#include "PokemonFRLG_BoxSorter.h" + +namespace PokemonAutomation{ +namespace NintendoSwitch{ +namespace PokemonFRLG{ + +using namespace Pokemon; + +namespace{ + +constexpr uint16_t MAX_BOXES = 14; + +} + +BoxSorter_Descriptor::BoxSorter_Descriptor() + : SingleSwitchProgramDescriptor( + "PokemonFRLG:BoxSorter", + Pokemon::STRING_POKEMON + " FRLG", "Box Sorter", + "Programs/PokemonFRLG/BoxSorter.html", + "Sort boxes of " + STRING_POKEMON + ". Start in Move " + STRING_POKEMON + + " with an empty hand in the first box to sort. Uses English species names.", + ProgramControllerClass::StandardController_NoRestrictions, + FeedbackType::REQUIRED, + AllowCommandsWhenRunning::DISABLE_COMMANDS + ) +{} + + +std::unique_ptr BoxSorter_Descriptor::make_stats() const{ + return std::unique_ptr(new Stats()); +} + +BoxSorter::BoxSorter() + : NUM_BOXES( + "Number of Boxes to Sort:
Starting with the current box and continuing to the right.", + LockMode::LOCK_WHILE_RUNNING, 1, 1, MAX_BOXES + ) + , SORT_TABLE( + "Sort Order Rules:
Sort order rules will be applied top to bottom.", + {SortingRuleType::DexNo, SortingRuleType::Level, SortingRuleType::Gender, SortingRuleType::Shiny} + ) + , DRY_RUN( + "Dry Run:
Scan boxes and write <output_file>.json and " + "<output_file>-sorted.json without moving any " + STRING_POKEMON + ".", + LockMode::LOCK_WHILE_RUNNING, false + ) + , NOTIFICATIONS({&NOTIFICATION_PROGRAM_FINISH, &NOTIFICATION_ERROR_FATAL}) +{ + PA_ADD_OPTION(NUM_BOXES); + PA_ADD_OPTION(SORT_TABLE); + PA_ADD_OPTION(DRY_RUN); + PA_ADD_OPTION(NOTIFICATIONS); +} + +void BoxSorter::program(SingleSwitchProgramEnvironment& env, ProControllerContext& context){ + home_black_border_check(env.console, context); + + const std::vector preferences = SORT_TABLE.preferences(); + if (preferences.empty()){ + throw UserSetupError(env.console, "Select at least one sorting rule."); + } + + auto& stats = env.current_stats(); + BoxOrganizationScan scan = scan_box_data(env, context, preferences, (uint16_t)NUM_BOXES); + const auto& boxes_data = scan.boxes_data; + + // Stable ordering avoids unnecessary moves for Pokemon with identical sort keys. + auto boxes_sorted = boxes_data; + std::stable_sort(boxes_sorted.begin(), boxes_sorted.end()); + const BoxSortingPlan plan = make_box_sorting_plan(boxes_data, boxes_sorted); + stats.compares += plan.compares; + env.update_stats(); + save_boxes_data_to_json(boxes_data, "frlg-box_order.json"); + save_boxes_data_to_json(boxes_sorted, "frlg-box_order-sorted.json"); + env.log("Saved current and sorted box catalogues."); + + if (DRY_RUN){ + env.log("Dry run complete."); + send_program_finished_notification(env, NOTIFICATION_PROGRAM_FINISH); + return; + } + + env.log("Start sorting..."); + execute_box_sorting_plan(env, context, plan, scan.cursor, scan.mode); + + send_program_finished_notification(env, NOTIFICATION_PROGRAM_FINISH); +} + + +} +} +} diff --git a/SerialPrograms/Source/VideoGames/PokemonFRLG/Programs/BoxOrganization/PokemonFRLG_BoxSorter.h b/SerialPrograms/Source/VideoGames/PokemonFRLG/Programs/BoxOrganization/PokemonFRLG_BoxSorter.h new file mode 100644 index 0000000000..af5234576c --- /dev/null +++ b/SerialPrograms/Source/VideoGames/PokemonFRLG/Programs/BoxOrganization/PokemonFRLG_BoxSorter.h @@ -0,0 +1,52 @@ +/* Box Sorter + * + * From: https://github.com/PokemonAutomation/ + * + */ + +#ifndef PokemonAutomation_PokemonFRLG_BoxSorter_H +#define PokemonAutomation_PokemonFRLG_BoxSorter_H + +#include +#include "Common/Cpp/Options/BooleanCheckBoxOption.h" +#include "Common/Cpp/Options/SimpleIntegerOption.h" +#include "CommonFramework/Notifications/EventNotificationsTable.h" +#include "NintendoSwitch/NintendoSwitch_SingleSwitchProgram.h" +#include "Pokemon/Options/Pokemon_BoxSortingTable.h" + +namespace PokemonAutomation{ +namespace NintendoSwitch{ +namespace PokemonFRLG{ + +struct BoxOrganizationStats; + +class BoxSorter_Descriptor : public SingleSwitchProgramDescriptor{ +public: + BoxSorter_Descriptor(); + + using Stats = BoxOrganizationStats; + virtual std::unique_ptr make_stats() const override; +}; + + +class BoxSorter : public SingleSwitchProgramInstance{ +public: + using Descriptor = BoxSorter_Descriptor; + BoxSorter(); + + virtual void program(SingleSwitchProgramEnvironment& env, ProControllerContext& context) override; + virtual void start_program_border_check(VideoStream&, FeedbackType) override{} + + +private: + SimpleIntegerOption NUM_BOXES; + Pokemon::BoxSortingTable SORT_TABLE; + BooleanCheckBoxOption DRY_RUN; + EventNotificationsOption NOTIFICATIONS; +}; + + +} +} +} +#endif diff --git a/SerialPrograms/cmake/SourceFiles.cmake b/SerialPrograms/cmake/SourceFiles.cmake index eef6a10969..b7b5b7e9e1 100644 --- a/SerialPrograms/cmake/SourceFiles.cmake +++ b/SerialPrograms/cmake/SourceFiles.cmake @@ -1763,6 +1763,8 @@ file(GLOB LIBRARY_SOURCES Source/VideoGames/PokemonFRLG/PokemonFRLG_Tests.h Source/VideoGames/PokemonFRLG/Programs/BoxOrganization/PokemonFRLG_BoxOrganization.cpp Source/VideoGames/PokemonFRLG/Programs/BoxOrganization/PokemonFRLG_BoxOrganization.h + Source/VideoGames/PokemonFRLG/Programs/BoxOrganization/PokemonFRLG_BoxSorter.cpp + Source/VideoGames/PokemonFRLG/Programs/BoxOrganization/PokemonFRLG_BoxSorter.h Source/VideoGames/PokemonFRLG/Programs/Farming/PokemonFRLG_EliteFourFarmer.cpp Source/VideoGames/PokemonFRLG/Programs/Farming/PokemonFRLG_EliteFourFarmer.h Source/VideoGames/PokemonFRLG/Programs/Farming/PokemonFRLG_EvTrainer.cpp From 93c14a64d19dffc5ca7d2704524dd088bdc9c5c7 Mon Sep 17 00:00:00 2001 From: Dalton-V Date: Tue, 3 Nov 2026 18:03:56 -0600 Subject: [PATCH 2/2] Build fixes --- .../Programs/BoxOrganization/PokemonFRLG_BoxOrganization.h | 1 + .../Programs/BoxOrganization/PokemonFRLG_BoxSorter.cpp | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/SerialPrograms/Source/VideoGames/PokemonFRLG/Programs/BoxOrganization/PokemonFRLG_BoxOrganization.h b/SerialPrograms/Source/VideoGames/PokemonFRLG/Programs/BoxOrganization/PokemonFRLG_BoxOrganization.h index 637f482724..4f9e85c806 100644 --- a/SerialPrograms/Source/VideoGames/PokemonFRLG/Programs/BoxOrganization/PokemonFRLG_BoxOrganization.h +++ b/SerialPrograms/Source/VideoGames/PokemonFRLG/Programs/BoxOrganization/PokemonFRLG_BoxOrganization.h @@ -15,6 +15,7 @@ #include "NintendoSwitch/NintendoSwitch_SingleSwitchProgram.h" #include "Pokemon/Pokemon_BoxCursor.h" #include "Pokemon/Pokemon_CollectedPokemonInfo.h" +#include "VideoGames/PokemonFRLG/Inference/Box/PokemonFRLG_BoxSelectionModeDetector.h" namespace PokemonAutomation{ namespace NintendoSwitch{ diff --git a/SerialPrograms/Source/VideoGames/PokemonFRLG/Programs/BoxOrganization/PokemonFRLG_BoxSorter.cpp b/SerialPrograms/Source/VideoGames/PokemonFRLG/Programs/BoxOrganization/PokemonFRLG_BoxSorter.cpp index d6386442b5..fdf5b5f545 100644 --- a/SerialPrograms/Source/VideoGames/PokemonFRLG/Programs/BoxOrganization/PokemonFRLG_BoxSorter.cpp +++ b/SerialPrograms/Source/VideoGames/PokemonFRLG/Programs/BoxOrganization/PokemonFRLG_BoxSorter.cpp @@ -33,6 +33,7 @@ BoxSorter_Descriptor::BoxSorter_Descriptor() "Programs/PokemonFRLG/BoxSorter.html", "Sort boxes of " + STRING_POKEMON + ". Start in Move " + STRING_POKEMON + " with an empty hand in the first box to sort. Uses English species names.", + PanelQualityStanding::OFFICIAL_BETA, ProgramControllerClass::StandardController_NoRestrictions, FeedbackType::REQUIRED, AllowCommandsWhenRunning::DISABLE_COMMANDS @@ -54,8 +55,8 @@ BoxSorter::BoxSorter() {SortingRuleType::DexNo, SortingRuleType::Level, SortingRuleType::Gender, SortingRuleType::Shiny} ) , DRY_RUN( - "Dry Run:
Scan boxes and write <output_file>.json and " - "<output_file>-sorted.json without moving any " + STRING_POKEMON + ".", + "Dry Run:
Scan boxes and write frlg-box_order.json and " + "frlg-box_order-sorted.json without moving any " + STRING_POKEMON + ".", LockMode::LOCK_WHILE_RUNNING, false ) , NOTIFICATIONS({&NOTIFICATION_PROGRAM_FINISH, &NOTIFICATION_ERROR_FATAL})