diff --git a/SerialPrograms/Source/PokemonFRLG/Programs/RngManipulation/PokemonFRLG_EggRng.cpp b/SerialPrograms/Source/PokemonFRLG/Programs/RngManipulation/PokemonFRLG_EggRng.cpp
index 1c496b7215..629e337a6a 100644
--- a/SerialPrograms/Source/PokemonFRLG/Programs/RngManipulation/PokemonFRLG_EggRng.cpp
+++ b/SerialPrograms/Source/PokemonFRLG/Programs/RngManipulation/PokemonFRLG_EggRng.cpp
@@ -143,6 +143,16 @@ EggRng::EggRng()
LockMode::LOCK_WHILE_RUNNING,
GameVersion::firered
)
+ , SOUND(
+ "Sound:
"
+ "Your in-game sound setting. This affects the possible seeds.",
+ {
+ {SoundSetting::Mono, "mono", "Mono"},
+ {SoundSetting::Stereo, "stereo", "Stereo"}
+ },
+ LockMode::LOCK_WHILE_RUNNING,
+ SoundSetting::Mono
+ )
, m_target_settings("Target Settings")
, EGG_SPECIES(
"Egg Species:",
@@ -166,42 +176,6 @@ EggRng::EggRng()
"70FE", "70FE",
true
)
- , HELD_SEED_LIST(
- "Nearby Held Seeds:
"
- "This box should contain a list of seeds (in order) around and including your held seed, with one seed on each line",
- LockMode::LOCK_WHILE_RUNNING,
- "D000\n199A\n77A1\nAABC\n280C\n70FE\nB573\n02F2\n8084\nA533\nED1E",
- "D000\n199A\n77A1\nAABC\n280C\n70FE\nB573\n02F2\n8084\nA533\nED1E",
- true
- )
- , HELD_SEED_BUTTON(
- "Held Seed Button:
",
- {
- {SeedButton::A, "A", "A"},
- {SeedButton::Start, "Start", "Start"},
- {SeedButton::L, "L", "L (L=A)"},
- },
- LockMode::LOCK_WHILE_RUNNING,
- SeedButton::A
- )
- , HELD_EXTRA_BUTTON(
- "Held Seed Extra Button:
"
- "Additional button presses that affect the seed.",
- {
- {BlackoutButton::None, "None", "None"},
- {BlackoutButton::L, "L", "Blackout L"},
- {BlackoutButton::R, "R", "Blackout R"},
- },
- LockMode::LOCK_WHILE_RUNNING,
- BlackoutButton::None
- )
- , HELD_SEED_DELAY(
- "Held Seed Delay Time (ms):
"
- "The delay between starting the game and advancing past the title screen. Set this to match your held seed.
"
- "If using Ten Lines, select Nintendo Switch 1 as your console even if using a Switch 2.",
- LockMode::LOCK_WHILE_RUNNING,
- 31338, 30400 // default, min
- )
, HELD_ADVANCES(
"Held Advances:
The total number of RNG advances for your held target.",
LockMode::LOCK_WHILE_RUNNING,
@@ -215,48 +189,18 @@ EggRng::EggRng()
"70FE", "70FE",
true
)
- , PICKUP_SEED_LIST(
- "Nearby Pickup Seeds:
"
- "This box should contain a list of seeds (in order) around and including your held seed, with one seed on each line",
- LockMode::LOCK_WHILE_RUNNING,
- "D000\n199A\n77A1\nAABC\n280C\n70FE\nB573\n02F2\n8084\nA533\nED1E",
- "D000\n199A\n77A1\nAABC\n280C\n70FE\nB573\n02F2\n8084\nA533\nED1E",
- true
- )
- , PICKUP_SEED_BUTTON(
- "Pickup Seed Button:
",
- {
- {SeedButton::A, "A", "A"},
- {SeedButton::Start, "Start", "Start"},
- {SeedButton::L, "L", "L (L=A)"},
- },
- LockMode::LOCK_WHILE_RUNNING,
- SeedButton::A
- )
- , PICKUP_EXTRA_BUTTON(
- "Pickup Seed Extra Button:
"
- "Additional button presses that affect the seed.",
- {
- {BlackoutButton::None, "None", "None"},
- {BlackoutButton::L, "L", "Blackout L"},
- {BlackoutButton::R, "R", "Blackout R"},
- },
- LockMode::LOCK_WHILE_RUNNING,
- BlackoutButton::None
- )
- , PICKUP_SEED_DELAY(
- "Pickup Seed Delay Time (ms):
"
- "The delay between starting the game and advancing past the title screen. Set this to match your held seed.
"
- "If using Ten Lines, select Nintendo Switch 1 as your console even if using a Switch 2.",
- LockMode::LOCK_WHILE_RUNNING,
- 31338, 30400 // default, min
- )
, PICKUP_ADVANCES(
"Pickup Advances:
The total number of RNG advances for your pickup target.",
LockMode::LOCK_WHILE_RUNNING,
10000, 700, 1000000000 // default, min
)
, m_program_settings("Program Settings")
+ , SEED_RADIUS(
+ "Nearby Seed Radius:
"
+ "The number of nearby seeds on each side of the target to search when identifying which seed was hit.",
+ LockMode::LOCK_WHILE_RUNNING,
+ 5, 1 // default, min
+ )
, STARTING_POINT(
"Starting Point:",
{
@@ -319,25 +263,19 @@ EggRng::EggRng()
PA_ADD_OPTION(m_game_info);
PA_ADD_OPTION(LANGUAGE);
PA_ADD_OPTION(GAME_VERSION);
+ PA_ADD_OPTION(SOUND);
PA_ADD_OPTION(m_target_settings);
PA_ADD_OPTION(EGG_SPECIES);
PA_ADD_OPTION(COMPATIBILITY);
PA_ADD_OPTION(PARENT_IVS);
PA_ADD_OPTION(m_held_settings);
PA_ADD_OPTION(HELD_SEED);
- PA_ADD_OPTION(HELD_SEED_LIST);
- PA_ADD_OPTION(HELD_SEED_BUTTON);
- PA_ADD_OPTION(HELD_EXTRA_BUTTON);
- PA_ADD_OPTION(HELD_SEED_DELAY);
PA_ADD_OPTION(HELD_ADVANCES);
PA_ADD_OPTION(m_pickup_settings);
PA_ADD_OPTION(PICKUP_SEED);
- PA_ADD_OPTION(PICKUP_SEED_LIST);
- PA_ADD_OPTION(PICKUP_SEED_BUTTON);
- PA_ADD_OPTION(PICKUP_EXTRA_BUTTON);
- PA_ADD_OPTION(PICKUP_SEED_DELAY);
PA_ADD_OPTION(PICKUP_ADVANCES);
PA_ADD_OPTION(m_program_settings);
+ PA_ADD_OPTION(SEED_RADIUS);
PA_ADD_OPTION(STARTING_POINT);
PA_ADD_OPTION(MAX_RESETS);
PA_ADD_OPTION(MAX_BALL_THROWS);
@@ -404,6 +342,8 @@ bool EggRng::reset_and_check_seed(
const uint64_t& SEED_DELAY = frame_target.seed_delay;
const std::vector& SEED_VALUES = frame_target.seed_values;
const int16_t& SEED_POSITION = frame_target.seed_position;
+ const SeedButton& SEED_BUTTON = frame_target.seed_button;
+ const BlackoutButton& EXTRA_BUTTON = frame_target.extra_button;
static const int64_t FIXED_SEED_OFFSET = -845; // ms, approximate
const int64_t FIXED_ADVANCES_OFFSET = pickup_frame ? -246 : 135; // frames, approximate
@@ -439,9 +379,8 @@ bool EggRng::reset_and_check_seed(
// Step 1: reset and perform blind sequence
env.log("Resetting Game...");
reset_and_perform_blind_sequence(
- env.console, context, target,
- pickup_frame ? PICKUP_SEED_BUTTON : HELD_SEED_BUTTON,
- pickup_frame ? PICKUP_EXTRA_BUTTON : HELD_EXTRA_BUTTON,
+ env.console, context, target,
+ SEED_BUTTON, EXTRA_BUTTON,
timings, launch_delay, false, PROFILE
);
stats.resets++;
@@ -792,35 +731,37 @@ void EggRng::program(SingleSwitchProgramEnvironment& env, ProControllerContext&
SPECIES_LIST.emplace(slot.species);
}
+ const SeedsDatabase seeds_db(seeds_json_path(GAME_VERSION == GameVersion::firered, LANGUAGE));
+
// held timings
const uint16_t TARGET_HELD_SEED = parse_seed(env.console, HELD_SEED);
- const std::vector HELD_SEED_VALUES = parse_seed_list(env.console, HELD_SEED_LIST);
- const int16_t HELD_SEED_POSITION = seed_position_in_list(TARGET_HELD_SEED, HELD_SEED_VALUES);
- if (HELD_SEED_POSITION == -1){
+ const SeedMatch held_match = seeds_db.find_seed(TARGET_HELD_SEED, SOUND, SEED_RADIUS);
+ if (!held_match.found){
OperationFailedException::fire(
ErrorReport::SEND_ERROR_REPORT,
- "EggRng(): Held Seed is missing from the list of nearby seeds.",
+ "EggRng(): Held Seed was not found in the seed database for this game version, language, and sound setting.",
env.console
- );
+ );
}
- env.log("Target Held Seed Value: " + to_hex_string(TARGET_HELD_SEED));
+ env.log("Target Held Seed Value: " + to_hex_string(TARGET_HELD_SEED)
+ + " (delay " + std::to_string(held_match.seed_delay) + "ms, button mode " + held_match.button_mode + ")");
// pickup timings
const uint16_t TARGET_PICKUP_SEED = parse_seed(env.console, PICKUP_SEED);
- const std::vector PICKUP_SEED_VALUES = parse_seed_list(env.console, PICKUP_SEED_LIST);
- const int16_t PICKUP_SEED_POSITION = seed_position_in_list(TARGET_PICKUP_SEED, PICKUP_SEED_VALUES);
- if (PICKUP_SEED_POSITION == -1){
+ const SeedMatch pickup_match = seeds_db.find_seed(TARGET_PICKUP_SEED, SOUND, SEED_RADIUS);
+ if (!pickup_match.found){
OperationFailedException::fire(
ErrorReport::SEND_ERROR_REPORT,
- "EggRng(): Pickup Seed is missing from the list of nearby seeds.",
+ "EggRng(): Pickup Seed was not found in the seed database for this game version, language, and sound setting.",
env.console
- );
+ );
}
- env.log("Target Pickup Seed Value: " + to_hex_string(TARGET_PICKUP_SEED));
+ env.log("Target Pickup Seed Value: " + to_hex_string(TARGET_PICKUP_SEED)
+ + " (delay " + std::to_string(pickup_match.seed_delay) + "ms, button mode " + pickup_match.button_mode + ")");
EggFrameTargets frame_targets{
- { HELD_SEED_DELAY, HELD_SEED_VALUES, HELD_SEED_POSITION },
- { PICKUP_SEED_DELAY, PICKUP_SEED_VALUES, PICKUP_SEED_POSITION }
+ { held_match.seed_delay, held_match.seed_values, held_match.seed_position, held_match.seed_button, held_match.extra_button },
+ { pickup_match.seed_delay, pickup_match.seed_values, pickup_match.seed_position, pickup_match.seed_button, pickup_match.extra_button }
};
// searchers
diff --git a/SerialPrograms/Source/PokemonFRLG/Programs/RngManipulation/PokemonFRLG_EggRng.h b/SerialPrograms/Source/PokemonFRLG/Programs/RngManipulation/PokemonFRLG_EggRng.h
index 2e2fc59ddf..1d1d31815c 100644
--- a/SerialPrograms/Source/PokemonFRLG/Programs/RngManipulation/PokemonFRLG_EggRng.h
+++ b/SerialPrograms/Source/PokemonFRLG/Programs/RngManipulation/PokemonFRLG_EggRng.h
@@ -23,6 +23,7 @@
#include "PokemonFRLG_RngStatsDatabase.h"
#include "PokemonFRLG_RngDisplays.h"
#include "PokemonFRLG_RngLoopRoutines.h"
+#include "PokemonFRLG_SeedsDatabase.h"
namespace PokemonAutomation{
namespace NintendoSwitch{
@@ -146,6 +147,7 @@ class EggRng : public SingleSwitchProgramInstance, public ConfigOption::Listener
SectionDividerOption m_game_info;
OCR::LanguageOCROption LANGUAGE;
EnumDropdownOption GAME_VERSION;
+ EnumDropdownOption SOUND;
SectionDividerOption m_target_settings;
PokemonNameSelectOption EGG_SPECIES;
@@ -153,22 +155,15 @@ class EggRng : public SingleSwitchProgramInstance, public ConfigOption::Listener
ParentIVsTable PARENT_IVS;
SectionDividerOption m_held_settings;
- StringOption HELD_SEED;
- TextEditOption HELD_SEED_LIST;
- EnumDropdownOption HELD_SEED_BUTTON;
- EnumDropdownOption HELD_EXTRA_BUTTON;
- SimpleIntegerOption HELD_SEED_DELAY;
+ StringOption HELD_SEED;
SimpleIntegerOptionHELD_ADVANCES;
SectionDividerOption m_pickup_settings;
- StringOption PICKUP_SEED;
- TextEditOption PICKUP_SEED_LIST;
- EnumDropdownOption PICKUP_SEED_BUTTON;
- EnumDropdownOption PICKUP_EXTRA_BUTTON;
- SimpleIntegerOption PICKUP_SEED_DELAY;
+ StringOption PICKUP_SEED;
SimpleIntegerOptionPICKUP_ADVANCES;
SectionDividerOption m_program_settings;
+ SimpleIntegerOption SEED_RADIUS;
EnumDropdownOption STARTING_POINT;
SimpleIntegerOption MAX_RESETS;
SimpleIntegerOption MAX_RARE_CANDIES;
diff --git a/SerialPrograms/Source/PokemonFRLG/Programs/RngManipulation/PokemonFRLG_GiftRng.cpp b/SerialPrograms/Source/PokemonFRLG/Programs/RngManipulation/PokemonFRLG_GiftRng.cpp
index 6bb33be2f9..523a6dc47f 100644
--- a/SerialPrograms/Source/PokemonFRLG/Programs/RngManipulation/PokemonFRLG_GiftRng.cpp
+++ b/SerialPrograms/Source/PokemonFRLG/Programs/RngManipulation/PokemonFRLG_GiftRng.cpp
@@ -67,6 +67,15 @@ GiftRng::GiftRng()
, m_game_info(
"Game Information"
)
+ , GAME_VERSION(
+ "Game Version:",
+ {
+ {GameVersion::firered, "firered", "FireRed"},
+ {GameVersion::leafgreen, "leafgreen", "LeafGreen"}
+ },
+ LockMode::LOCK_WHILE_RUNNING,
+ GameVersion::firered
+ )
, LANGUAGE(
"Game Language:",
{
@@ -80,6 +89,16 @@ GiftRng::GiftRng()
LockMode::LOCK_WHILE_RUNNING,
true
)
+ , SOUND(
+ "Sound:
"
+ "Your in-game sound setting. This affects the possible seeds.",
+ {
+ {SoundSetting::Mono, "mono", "Mono"},
+ {SoundSetting::Stereo, "stereo", "Stereo"}
+ },
+ LockMode::LOCK_WHILE_RUNNING,
+ SoundSetting::Mono
+ )
, m_target_settings(
"Target Settings — Get these from an RNG search tool"
)
@@ -113,43 +132,6 @@ GiftRng::GiftRng()
"70FE", "70FE",
true
)
- , SEED_LIST(
- "Nearby Seeds:
"
- "This box should contain a list of seeds (in order) around and including your target seed, with one seed on each line",
- LockMode::LOCK_WHILE_RUNNING,
- "D000\n199A\n77A1\nAABC\n280C\n70FE\nB573\n02F2\n8084\nA533\nED1E",
- "D000\n199A\n77A1\nAABC\n280C\n70FE\nB573\n02F2\n8084\nA533\nED1E",
- true
- )
- , SEED_BUTTON(
- "Seed Button:",
- {
- {SeedButton::A, "A", "A"},
- {SeedButton::Start, "Start", "Start"},
- {SeedButton::L, "L", "L (L=A)"},
- },
- LockMode::LOCK_WHILE_RUNNING,
- SeedButton::A
- )
- , EXTRA_BUTTON(
- "Extra Button:
"
- "Additional button presses that affect the seed.",
- {
- {BlackoutButton::None, "None", "None"},
- {BlackoutButton::L, "L", "Blackout L"},
- {BlackoutButton::R, "R", "Blackout R"},
- },
- LockMode::LOCK_WHILE_RUNNING,
- BlackoutButton::None
- )
- , SEED_DELAY(
- "Seed Delay Time (ms):
"
- "The delay between starting the game and advancing past the title screen. Set this to match your target seed.
"
- "If using Ten Lines for seed info, select Nintendo Switch 1 as your console even if using a Switch 2.
"
- "Warning: values close to 30500ms can sometimes cause problems, and you may need to manually increase your initial seed calibration or pick a new target.",
- LockMode::LOCK_WHILE_RUNNING,
- 31338, 30400 // default, min
- )
, ADVANCES(
"Advances:
The total number of RNG advances for your target.",
LockMode::LOCK_WHILE_RUNNING,
@@ -165,6 +147,12 @@ GiftRng::GiftRng()
LockMode::LOCK_WHILE_RUNNING,
false // default
)
+ , SEED_RADIUS(
+ "Nearby Seed Radius:
"
+ "The number of nearby seeds on each side of the target to search when identifying which seed was hit.",
+ LockMode::LOCK_WHILE_RUNNING,
+ 5, 1 // default, min
+ )
, MAX_RESETS(
"Max Resets:",
LockMode::UNLOCK_WHILE_RUNNING,
@@ -207,17 +195,16 @@ GiftRng::GiftRng()
PA_ADD_OPTION(RNG_FILTERS);
PA_ADD_OPTION(RNG_CALIBRATION);
PA_ADD_OPTION(m_game_info);
+ PA_ADD_OPTION(GAME_VERSION);
PA_ADD_OPTION(LANGUAGE);
+ PA_ADD_OPTION(SOUND);
PA_ADD_OPTION(m_target_settings);
PA_ADD_OPTION(TARGET);
PA_ADD_OPTION(SEED);
- PA_ADD_OPTION(SEED_LIST);
- PA_ADD_OPTION(SEED_BUTTON);
- PA_ADD_OPTION(EXTRA_BUTTON);
- PA_ADD_OPTION(SEED_DELAY);
PA_ADD_OPTION(ADVANCES);
PA_ADD_OPTION(m_program_settings);
PA_ADD_OPTION(USE_TEACHY_TV);
+ PA_ADD_OPTION(SEED_RADIUS);
PA_ADD_OPTION(MAX_RESETS);
PA_ADD_OPTION(MAX_RARE_CANDIES);
PA_ADD_OPTION(PROFILE);
@@ -241,12 +228,18 @@ void GiftRng::program(SingleSwitchProgramEnvironment& env, ProControllerContext&
RNG_CALIBRATION.reset_hits();
const uint16_t TARGET_SEED = parse_seed(env.console, SEED);
- const std::vector SEED_VALUES = parse_seed_list(env.console, SEED_LIST);
- const int16_t SEED_POSITION = seed_position_in_list(TARGET_SEED, SEED_VALUES);
-
- if (SEED_POSITION == -1){
- throw UserSetupError(env.console, "The target Seed is missing from the list of nearby seeds.");
+ SeedsDatabase seeds_db(seeds_json_path(GAME_VERSION == GameVersion::firered, LANGUAGE));
+ const SeedMatch seed_match = seeds_db.find_seed(TARGET_SEED, SOUND, SEED_RADIUS);
+ if (!seed_match.found){
+ throw UserSetupError(env.console, "The target Seed was not found in the seed database for this game version, language, and sound setting.");
}
+ const std::vector SEED_VALUES = seed_match.seed_values;
+ const int16_t SEED_POSITION = seed_match.seed_position;
+ const uint64_t SEED_DELAY = seed_match.seed_delay;
+ const SeedButton SEED_BUTTON = seed_match.seed_button;
+ const BlackoutButton EXTRA_BUTTON = seed_match.extra_button;
+ env.log("Seed delay: " + std::to_string(SEED_DELAY) + "ms, button mode: " + seed_match.button_mode
+ + ", column: " + seed_match.column_name);
BaseStats BASE_STATS;
int16_t GENDER_THRESHOLD = -1;
diff --git a/SerialPrograms/Source/PokemonFRLG/Programs/RngManipulation/PokemonFRLG_GiftRng.h b/SerialPrograms/Source/PokemonFRLG/Programs/RngManipulation/PokemonFRLG_GiftRng.h
index 5356f09ef0..a20c749915 100644
--- a/SerialPrograms/Source/PokemonFRLG/Programs/RngManipulation/PokemonFRLG_GiftRng.h
+++ b/SerialPrograms/Source/PokemonFRLG/Programs/RngManipulation/PokemonFRLG_GiftRng.h
@@ -21,6 +21,7 @@
#include "PokemonFRLG_BlindNavigation.h"
#include "PokemonFRLG_RngCalibration.h"
#include "PokemonFRLG_RngDisplays.h"
+#include "PokemonFRLG_SeedsDatabase.h"
namespace PokemonAutomation{
namespace NintendoSwitch{
@@ -43,6 +44,10 @@ class GiftRng : public SingleSwitchProgramInstance{
) override{}
private:
+ enum class GameVersion{
+ firered,
+ leafgreen
+ };
SectionDividerOption m_calibration_displays;
RngTargetDisplay RNG_TARGET;
@@ -50,19 +55,18 @@ class GiftRng : public SingleSwitchProgramInstance{
RngCalibrationDisplay RNG_CALIBRATION;
SectionDividerOption m_game_info;
+ EnumDropdownOption GAME_VERSION;
OCR::LanguageOCROption LANGUAGE;
+ EnumDropdownOption SOUND;
SectionDividerOption m_target_settings;
EnumDropdownOption TARGET;
- StringOption SEED;
- TextEditOption SEED_LIST;
- EnumDropdownOption SEED_BUTTON;
- EnumDropdownOption EXTRA_BUTTON;
- SimpleIntegerOption SEED_DELAY;
+ StringOption SEED;
SimpleIntegerOptionADVANCES;
SectionDividerOption m_program_settings;
BooleanCheckBoxOption USE_TEACHY_TV;
+ SimpleIntegerOption SEED_RADIUS;
SimpleIntegerOption MAX_RESETS;
SimpleIntegerOption MAX_RARE_CANDIES;
SimpleIntegerOption PROFILE;
diff --git a/SerialPrograms/Source/PokemonFRLG/Programs/RngManipulation/PokemonFRLG_RngLoopRoutines.h b/SerialPrograms/Source/PokemonFRLG/Programs/RngManipulation/PokemonFRLG_RngLoopRoutines.h
index 7e217cc69c..89dc40eeee 100644
--- a/SerialPrograms/Source/PokemonFRLG/Programs/RngManipulation/PokemonFRLG_RngLoopRoutines.h
+++ b/SerialPrograms/Source/PokemonFRLG/Programs/RngManipulation/PokemonFRLG_RngLoopRoutines.h
@@ -17,6 +17,7 @@
#include "CommonFramework/Notifications/EventNotificationOption.h"
#include "NintendoSwitch/NintendoSwitch_SingleSwitchProgram.h"
#include "Pokemon/Pokemon_AdvRng.h"
+#include "PokemonFRLG_BlindNavigation.h"
#include "PokemonFRLG_RngCalibration.h"
#include "PokemonFRLG_RngStatsDatabase.h"
@@ -50,11 +51,14 @@ struct EggCalibrationHistories{
}
};
-// Per-frame seed configuration: the nearby-seed list, the target's position in it, and the seed delay.
+// Per-frame seed configuration: the nearby-seed list, the target's position in it, the seed
+// delay, and the button combination (derived from the seed database) that reaches the seed.
struct EggFrameTarget{
uint64_t seed_delay;
std::vector seed_values;
int16_t seed_position;
+ SeedButton seed_button;
+ BlackoutButton extra_button;
};
struct EggFrameTargets{
EggFrameTarget held;
diff --git a/SerialPrograms/Source/PokemonFRLG/Programs/RngManipulation/PokemonFRLG_RoamingLegendaryRng.cpp b/SerialPrograms/Source/PokemonFRLG/Programs/RngManipulation/PokemonFRLG_RoamingLegendaryRng.cpp
index f7ccdad480..3ee66efd53 100644
--- a/SerialPrograms/Source/PokemonFRLG/Programs/RngManipulation/PokemonFRLG_RoamingLegendaryRng.cpp
+++ b/SerialPrograms/Source/PokemonFRLG/Programs/RngManipulation/PokemonFRLG_RoamingLegendaryRng.cpp
@@ -67,6 +67,15 @@ RoamingLegendaryRng::RoamingLegendaryRng()
, m_game_info(
"Game Information"
)
+ , GAME_VERSION(
+ "Game Version:",
+ {
+ {GameVersion::firered, "firered", "FireRed"},
+ {GameVersion::leafgreen, "leafgreen", "LeafGreen"}
+ },
+ LockMode::LOCK_WHILE_RUNNING,
+ GameVersion::firered
+ )
, LANGUAGE(
"Game Language:",
{
@@ -80,6 +89,16 @@ RoamingLegendaryRng::RoamingLegendaryRng()
LockMode::LOCK_WHILE_RUNNING,
true
)
+ , SOUND(
+ "Sound:
"
+ "Your in-game sound setting. This affects the possible seeds.",
+ {
+ {SoundSetting::Mono, "mono", "Mono"},
+ {SoundSetting::Stereo, "stereo", "Stereo"}
+ },
+ LockMode::LOCK_WHILE_RUNNING,
+ SoundSetting::Mono
+ )
, m_target_settings(
"Target Settings — Get these from an RNG search tool"
)
@@ -100,43 +119,6 @@ RoamingLegendaryRng::RoamingLegendaryRng()
"70FE", "70FE",
true
)
- , SEED_LIST(
- "Nearby Seeds:
"
- "This box should contain a list of seeds (in order) around and including your target seed, with one seed on each line",
- LockMode::LOCK_WHILE_RUNNING,
- "D000\n199A\n77A1\nAABC\n280C\n70FE\nB573\n02F2\n8084\nA533\nED1E",
- "D000\n199A\n77A1\nAABC\n280C\n70FE\nB573\n02F2\n8084\nA533\nED1E",
- true
- )
- , SEED_BUTTON(
- "Seed Button:",
- {
- {SeedButton::A, "A", "A"},
- {SeedButton::Start, "Start", "Start"},
- {SeedButton::L, "L", "L (L=A)"},
- },
- LockMode::LOCK_WHILE_RUNNING,
- SeedButton::A
- )
- , EXTRA_BUTTON(
- "Extra Button:
"
- "Additional button presses that affect the seed.",
- {
- {BlackoutButton::None, "None", "None"},
- {BlackoutButton::L, "L", "Blackout L"},
- {BlackoutButton::R, "R", "Blackout R"},
- },
- LockMode::LOCK_WHILE_RUNNING,
- BlackoutButton::None
- )
- , SEED_DELAY(
- "Seed Delay Time (ms):
"
- "The delay between starting the game and advancing past the title screen. Set this to match your target seed.
"
- "If using Ten Lines for seed info, select Nintendo Switch 1 as your console even if using a Switch 2.
"
- "Warning: values close to 30500ms can sometimes cause problems, and you may need to manually increase your initial seed calibration or pick a new target.",
- LockMode::LOCK_WHILE_RUNNING,
- 31338, 30400 // default, min
- )
, ADVANCES(
"Advances:
The total number of RNG advances for your target.",
LockMode::LOCK_WHILE_RUNNING,
@@ -152,6 +134,12 @@ RoamingLegendaryRng::RoamingLegendaryRng()
LockMode::LOCK_WHILE_RUNNING,
false // default
)
+ , SEED_RADIUS(
+ "Nearby Seed Radius:
"
+ "The number of nearby seeds on each side of the target to search when identifying which seed was hit.",
+ LockMode::LOCK_WHILE_RUNNING,
+ 5, 1 // default, min
+ )
, MAX_RESETS(
"Max Resets:",
LockMode::UNLOCK_WHILE_RUNNING,
@@ -202,17 +190,16 @@ RoamingLegendaryRng::RoamingLegendaryRng()
PA_ADD_OPTION(RNG_FILTERS);
PA_ADD_OPTION(RNG_CALIBRATION);
PA_ADD_OPTION(m_game_info);
+ PA_ADD_OPTION(GAME_VERSION);
PA_ADD_OPTION(LANGUAGE);
+ PA_ADD_OPTION(SOUND);
PA_ADD_OPTION(m_target_settings);
PA_ADD_OPTION(TARGET);
PA_ADD_OPTION(SEED);
- PA_ADD_OPTION(SEED_LIST);
- PA_ADD_OPTION(SEED_BUTTON);
- PA_ADD_OPTION(EXTRA_BUTTON);
- PA_ADD_OPTION(SEED_DELAY);
PA_ADD_OPTION(ADVANCES);
PA_ADD_OPTION(m_program_settings);
PA_ADD_OPTION(USE_TEACHY_TV);
+ PA_ADD_OPTION(SEED_RADIUS);
PA_ADD_OPTION(MAX_RESETS);
PA_ADD_OPTION(MAX_RARE_CANDIES);
PA_ADD_OPTION(MAX_BALL_THROWS);
@@ -237,12 +224,18 @@ void RoamingLegendaryRng::program(SingleSwitchProgramEnvironment& env, ProContro
RNG_CALIBRATION.reset_hits();
const uint16_t TARGET_SEED = parse_seed(env.console, SEED);
- const std::vector SEED_VALUES = parse_seed_list(env.console, SEED_LIST);
- const int16_t SEED_POSITION = seed_position_in_list(TARGET_SEED, SEED_VALUES);
-
- if (SEED_POSITION == -1){
- throw UserSetupError(env.console, "The target Seed is missing from the list of nearby seeds.");
+ SeedsDatabase seeds_db(seeds_json_path(GAME_VERSION == GameVersion::firered, LANGUAGE));
+ const SeedMatch seed_match = seeds_db.find_seed(TARGET_SEED, SOUND, SEED_RADIUS);
+ if (!seed_match.found){
+ throw UserSetupError(env.console, "The target Seed was not found in the seed database for this game version, language, and sound setting.");
}
+ const std::vector SEED_VALUES = seed_match.seed_values;
+ const int16_t SEED_POSITION = seed_match.seed_position;
+ const uint64_t SEED_DELAY = seed_match.seed_delay;
+ const SeedButton SEED_BUTTON = seed_match.seed_button;
+ const BlackoutButton EXTRA_BUTTON = seed_match.extra_button;
+ env.log("Seed delay: " + std::to_string(SEED_DELAY) + "ms, button mode: " + seed_match.button_mode
+ + ", column: " + seed_match.column_name);
BaseStats BASE_STATS;
int16_t GENDER_THRESHOLD = -1;
diff --git a/SerialPrograms/Source/PokemonFRLG/Programs/RngManipulation/PokemonFRLG_RoamingLegendaryRng.h b/SerialPrograms/Source/PokemonFRLG/Programs/RngManipulation/PokemonFRLG_RoamingLegendaryRng.h
index d12267a9fb..36d4d290fd 100644
--- a/SerialPrograms/Source/PokemonFRLG/Programs/RngManipulation/PokemonFRLG_RoamingLegendaryRng.h
+++ b/SerialPrograms/Source/PokemonFRLG/Programs/RngManipulation/PokemonFRLG_RoamingLegendaryRng.h
@@ -21,6 +21,7 @@
#include "PokemonFRLG_BlindNavigation.h"
#include "PokemonFRLG_RngCalibration.h"
#include "PokemonFRLG_RngDisplays.h"
+#include "PokemonFRLG_SeedsDatabase.h"
namespace PokemonAutomation{
namespace NintendoSwitch{
@@ -43,6 +44,10 @@ class RoamingLegendaryRng : public SingleSwitchProgramInstance{
) override{}
private:
+ enum class GameVersion{
+ firered,
+ leafgreen
+ };
SectionDividerOption m_calibration_displays;
RngTargetDisplay RNG_TARGET;
@@ -50,19 +55,18 @@ class RoamingLegendaryRng : public SingleSwitchProgramInstance{
RngCalibrationDisplay RNG_CALIBRATION;
SectionDividerOption m_game_info;
+ EnumDropdownOption GAME_VERSION;
OCR::LanguageOCROption LANGUAGE;
+ EnumDropdownOption SOUND;
SectionDividerOption m_target_settings;
EnumDropdownOption TARGET;
- StringOption SEED;
- TextEditOption SEED_LIST;
- EnumDropdownOption SEED_BUTTON;
- EnumDropdownOption EXTRA_BUTTON;
- SimpleIntegerOption SEED_DELAY;
+ StringOption SEED;
SimpleIntegerOptionADVANCES;
SectionDividerOption m_program_settings;
BooleanCheckBoxOption USE_TEACHY_TV;
+ SimpleIntegerOption SEED_RADIUS;
SimpleIntegerOption MAX_RESETS;
SimpleIntegerOption MAX_RARE_CANDIES;
SimpleIntegerOption MAX_BALL_THROWS;
diff --git a/SerialPrograms/Source/PokemonFRLG/Programs/RngManipulation/PokemonFRLG_SeedsDatabase.cpp b/SerialPrograms/Source/PokemonFRLG/Programs/RngManipulation/PokemonFRLG_SeedsDatabase.cpp
new file mode 100644
index 0000000000..e0603f03c9
--- /dev/null
+++ b/SerialPrograms/Source/PokemonFRLG/Programs/RngManipulation/PokemonFRLG_SeedsDatabase.cpp
@@ -0,0 +1,182 @@
+/* Seeds Database
+ *
+ * From: https://github.com/PokemonAutomation/
+ *
+ */
+
+#include "Common/Cpp/Exceptions.h"
+#include "Common/Cpp/Json/JsonValue.h"
+#include "Common/Cpp/Json/JsonObject.h"
+#include "Common/Cpp/Json/JsonArray.h"
+#include "CommonFramework/Globals.h"
+#include "PokemonFRLG_SeedsDatabase.h"
+
+namespace PokemonAutomation{
+namespace NintendoSwitch{
+namespace PokemonFRLG{
+
+
+std::string seeds_json_path(bool firered, Language language){
+ std::string version = firered ? "FR" : "LG";
+ std::string lang = (language == Language::Japanese) ? "Jpn" : "Eng";
+ return "PokemonFRLG/RngSeeds/" + version + "_" + lang + ".json";
+}
+
+
+namespace{
+
+uint16_t parse_hex_seed(const std::string& text, const std::string& path){
+ try{
+ size_t consumed = 0;
+ unsigned long value = std::stoul(text, &consumed, 16);
+ if (consumed != text.size() || value > 0xFFFF){
+ throw FileException(nullptr, PA_CURRENT_FUNCTION, "Invalid seed value: " + text, path);
+ }
+ return uint16_t(value);
+ }catch (const std::invalid_argument&){
+ throw FileException(nullptr, PA_CURRENT_FUNCTION, "Invalid seed value: " + text, path);
+ }catch (const std::out_of_range&){
+ throw FileException(nullptr, PA_CURRENT_FUNCTION, "Invalid seed value: " + text, path);
+ }
+}
+
+// Column names have the form " /