Skip to content

Commit bcef130

Browse files
authored
Reorganize FRLG RNG programs (#1248)
* fix frlg rng timing check for static encounters * reorganize FRLG RNG code * fix safari zone time checks * fix mismatched int types * include cmath
1 parent 59bcbdc commit bcef130

28 files changed

Lines changed: 2031 additions & 2065 deletions

SerialPrograms/Source/Pokemon/Pokemon_AdvRng.cpp

Lines changed: 559 additions & 136 deletions
Large diffs are not rendered by default.

SerialPrograms/Source/Pokemon/Pokemon_AdvRng.h

Lines changed: 144 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <stdint.h>
1111
#include <utility>
1212
#include <vector>
13+
#include <stdexcept>
1314
#include "Pokemon_StatsCalculation.h"
1415

1516
namespace PokemonAutomation{
@@ -28,6 +29,25 @@ struct AdvIVs{
2829
uint8_t spatk = 0;
2930
uint8_t spdef = 0;
3031
uint8_t speed = 0;
32+
33+
uint8_t& operator[](int index){
34+
switch (index){
35+
case 0:
36+
return hp;
37+
case 1:
38+
return attack;
39+
case 2:
40+
return defense;
41+
case 3:
42+
return speed;
43+
case 4:
44+
return spatk;
45+
case 5:
46+
return spdef;
47+
default:
48+
throw std::runtime_error("Invalid IVs index. Please report this as a bug.");
49+
}
50+
}
3151
};
3252

3353
enum class AdvNature{
@@ -79,12 +99,19 @@ enum class AdvShinyType{
7999
};
80100

81101
enum class AdvRngMethod{
82-
Method1,
83-
Method2,
84-
Method4,
102+
Method1, // egg normal
103+
Method2, // egg split
104+
Method3, // egg alternate
105+
Method4, // egg mixed
85106
Any
86107
};
87108

109+
enum class AdvEggCompatibility{
110+
low,
111+
medium,
112+
high
113+
};
114+
88115
struct AdvRngState{
89116
uint16_t seed;
90117
uint64_t advance;
@@ -94,10 +121,18 @@ struct AdvRngState{
94121
uint32_t s2;
95122
uint32_t s3;
96123
uint32_t s4;
124+
uint32_t s5;
97125

98126
bool operator<(const AdvRngState& rhs) const noexcept{
99127
return this->advance < rhs.advance;
100128
}
129+
130+
bool operator==(const AdvRngState& rhs) const noexcept{
131+
return (
132+
this->advance == rhs.advance
133+
&& this->seed == rhs.seed\
134+
);
135+
}
101136
};
102137

103138
struct AdvEncounterSlot{
@@ -125,6 +160,15 @@ struct AdvWildPokemonResult{
125160
uint8_t level;
126161
};
127162

163+
struct AdvEggResult{
164+
uint32_t pid;
165+
uint8_t gender;
166+
AdvNature nature;
167+
AdvAbility ability;
168+
AdvIVs ivs;
169+
AdvIVs inherited_ivs;
170+
};
171+
128172
struct AdvObservedPokemon{
129173
std::string species;
130174
AdvGender gender;
@@ -155,9 +199,22 @@ void level_up_observed_pokemon(AdvObservedPokemon& pokemon, const StatReads& new
155199
// returns the appropriate NatureAdjustments for an AdvNature
156200
Pokemon::NatureAdjustments nature_to_adjustment(AdvNature nature);
157201

202+
Pokemon::AdvNature string_to_nature(const std::string& nature_string);
203+
std::string nature_to_string(const AdvNature& nature);
204+
205+
std::string gender_to_string(const AdvGender& gender);
206+
207+
AdvGender gender_from_gender_value(uint8_t gender_value, int16_t threshold);
208+
158209
// returns search filters that correspond with observed stats
159210
AdvRngFilters observation_to_filters(const AdvObservedPokemon& observation, const BaseStats& basestats, AdvRngMethod method = AdvRngMethod::Method1);
160211

212+
AdvPokemonResult egg_to_pokemon(
213+
AdvEggResult& egg_result,
214+
AdvIVs& parentA_ivs,
215+
AdvIVs& parentB_ivs
216+
);
217+
161218
class AdvRngSearcher{
162219
public:
163220
uint16_t seed;
@@ -230,6 +287,90 @@ class AdvRngWildSearcher{
230287
};
231288

232289

290+
class AdvRngEggSearcher{
291+
public:
292+
uint16_t held_seed;
293+
AdvRngState held_state;
294+
295+
uint16_t pickup_seed;
296+
AdvRngState pickup_state;
297+
298+
AdvRngEggSearcher(uint16_t held_seed, AdvRngState held_state, uint16_t pickup_seed, AdvRngState pickup_state);
299+
AdvRngEggSearcher(
300+
uint16_t held_seed, uint64_t min_seed_advances,
301+
uint16_t pickup_seed, uint64_t min_pickup_advances,
302+
AdvRngMethod method = AdvRngMethod::Any
303+
);
304+
305+
void set_held_seed(uint16_t seed);
306+
void set_held_state_advances(uint64_t advances);
307+
void advance_held_state();
308+
309+
void set_pickup_seed(uint16_t seed);
310+
void set_pickup_state_advances(uint64_t advances);
311+
void advance_pickup_state();
312+
313+
AdvEggResult generate_egg();
314+
AdvPokemonResult generate_pokemon(AdvIVs& parentA_ivs, AdvIVs& parentB_ivs);
315+
316+
std::vector<std::pair<AdvRngState, AdvRngState>> search(
317+
AdvRngFilters& target,
318+
const std::vector<uint16_t>& held_seeds,
319+
uint64_t min_held_advances,
320+
uint64_t max_held_advances,
321+
const std::vector<uint16_t>& pickup_seeds,
322+
uint64_t min_pickup_advances,
323+
uint64_t max_pickup_advances,
324+
AdvIVs& parentA_ivs,
325+
AdvIVs& parentB_ivs,
326+
AdvEggCompatibility compatibility,
327+
int16_t gender_threshold = 126,
328+
uint16_t tid_xor_sid = 0
329+
);
330+
331+
private:
332+
333+
void search_held_advances_range(
334+
std::vector<std::pair<AdvRngState, AdvRngState>>& hits,
335+
AdvRngFilters& target,
336+
uint64_t min_held_advances,
337+
uint64_t max_held_advances,
338+
const std::vector<uint16_t>& pickup_seeds,
339+
uint64_t min_pickup_advances,
340+
uint64_t max_pickup_advances,
341+
AdvIVs& parentA_ivs,
342+
AdvIVs& parentB_ivs,
343+
AdvEggCompatibility compatibility,
344+
int16_t gender_threshold,
345+
uint16_t tid_xor_sid
346+
);
347+
348+
void search_pickups(
349+
std::vector<std::pair<AdvRngState, AdvRngState>>& hits,
350+
AdvRngFilters& target,
351+
uint16_t held_pid_half,
352+
const std::vector<uint16_t>& pickup_seeds,
353+
uint64_t min_pickup_advances,
354+
uint64_t max_pickup_advances,
355+
AdvIVs& parentA_ivs,
356+
AdvIVs& parentB_ivs,
357+
int16_t gender_threshold,
358+
uint16_t tid_xor_sid
359+
);
360+
361+
void search_pickup_advances_range(
362+
std::vector<std::pair<AdvRngState, AdvRngState>>& hits,
363+
AdvRngFilters& target,
364+
uint16_t held_pid_half,
365+
uint64_t min_pickup_advances,
366+
uint64_t max_pickup_advances,
367+
AdvIVs& parentA_ivs,
368+
AdvIVs& parentB_ivs,
369+
int16_t gender_threshold,
370+
uint16_t tid_xor_sid
371+
);
372+
};
373+
233374

234375
}
235376
}

SerialPrograms/Source/PokemonFRLG/Inference/PokemonFRLG_SelectionArrowDetector.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,28 @@ ImageFloatBox SelectionArrowDetector::arrow_box_for_position(SelectionArrowPosit
6060
throw InternalProgramError(nullptr, PA_CURRENT_FUNCTION, "Invalid FRLG Safari Selection Arrow Position");
6161
}
6262

63+
ImageFloatBox SelectionArrowDetector::arrow_box_for_position(SelectionArrowPositionNoDexMenu position){
64+
// Safari Zone menu has the same 7 slots as the overworld menu; RETIRE occupies slot 0,
65+
// shifting POKEDEX..EXIT each down one relative to the overworld enum.
66+
switch (position){
67+
case SelectionArrowPositionNoDexMenu::POKEMON:
68+
return ImageFloatBox(0.727692, 0.0523077, 0.0369231, 0.0778846);
69+
case SelectionArrowPositionNoDexMenu::BAG:
70+
return ImageFloatBox(0.727692, 0.1457692, 0.0369231, 0.0778846);
71+
case SelectionArrowPositionNoDexMenu::TRAINER:
72+
return ImageFloatBox(0.727692, 0.2392307, 0.0369231, 0.0778846);
73+
case SelectionArrowPositionNoDexMenu::SAVE:
74+
return ImageFloatBox(0.727692, 0.3378846, 0.0369231, 0.0778846);
75+
case SelectionArrowPositionNoDexMenu::OPTION:
76+
return ImageFloatBox(0.727692, 0.4261538, 0.0369231, 0.0778846);
77+
case SelectionArrowPositionNoDexMenu::EXIT:
78+
return ImageFloatBox(0.727692, 0.5248076, 0.0369231, 0.0778846);
79+
default:
80+
break;
81+
}
82+
throw InternalProgramError(nullptr, PA_CURRENT_FUNCTION, "Invalid FRLG Safari Selection Arrow Position");
83+
}
84+
6385
ImageFloatBox SelectionArrowDetector::arrow_box_for_position(SelectionArrowPositionConfirmationMenu position){
6486
switch (position){
6587
case SelectionArrowPositionConfirmationMenu::YES:

SerialPrograms/Source/PokemonFRLG/Inference/PokemonFRLG_SelectionArrowDetector.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,16 @@ enum class SelectionArrowPositionSafariMenu {
2626
EXIT
2727
};
2828

29+
const int NO_DEX_START_MENU_OPTION_COUNT = 6;
30+
enum class SelectionArrowPositionNoDexMenu{
31+
POKEMON,
32+
BAG,
33+
TRAINER,
34+
SAVE,
35+
OPTION,
36+
EXIT
37+
};
38+
2939
const int START_MENU_OPTION_COUNT = 7;
3040
enum class SelectionArrowPositionStartMenu{
3141
POKEDEX,
@@ -72,6 +82,8 @@ class SelectionArrowDetector : public StaticScreenDetector{
7282

7383
static ImageFloatBox arrow_box_for_position(SelectionArrowPositionSafariMenu position);
7484

85+
static ImageFloatBox arrow_box_for_position(SelectionArrowPositionNoDexMenu position);
86+
7587
static ImageFloatBox arrow_box_for_position(SelectionArrowPositionConfirmationMenu position);
7688

7789
const ImageFloatBox& last_detected() const { return m_last_detected; }

SerialPrograms/Source/PokemonFRLG/PokemonFRLG_Navigation.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -650,6 +650,8 @@ void open_party_menu_from_overworld(ConsoleHandle& console, ProControllerContext
650650
case 0:
651651
if (menu_context == StartMenuContext::SAFARI_ZONE){
652652
ret = move_cursor_to_position(console, context, SelectionArrowPositionSafariMenu::POKEMON);
653+
} else if (menu_context == StartMenuContext::NO_DEX){
654+
ret = move_cursor_to_position(console, context, SelectionArrowPositionNoDexMenu::POKEMON);
653655
} else {
654656
ret = move_cursor_to_position(console, context, SelectionArrowPositionStartMenu::POKEMON);
655657
}
@@ -709,6 +711,8 @@ void open_bag_from_overworld(ConsoleHandle& console, ProControllerContext& conte
709711
case 0:
710712
if (menu_context == StartMenuContext::SAFARI_ZONE){
711713
ret = move_cursor_to_position(console, context, SelectionArrowPositionSafariMenu::BAG);
714+
} else if (menu_context == StartMenuContext::NO_DEX){
715+
ret = move_cursor_to_position(console, context, SelectionArrowPositionNoDexMenu::BAG);
712716
} else {
713717
ret = move_cursor_to_position(console, context, SelectionArrowPositionStartMenu::BAG);
714718
}

SerialPrograms/Source/PokemonFRLG/PokemonFRLG_Navigation.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,8 @@ bool exit_wild_battle(ConsoleHandle& console, ProControllerContext& context, boo
7272
// Starting from the start menu, a sub-screen of the start menu, or the overworld, navigate to the party screen
7373
enum class StartMenuContext {
7474
STANDARD,
75-
SAFARI_ZONE
75+
SAFARI_ZONE,
76+
NO_DEX,
7677
};
7778
void open_party_menu_from_overworld(ConsoleHandle& console, ProControllerContext& context, StartMenuContext menu_context = StartMenuContext::STANDARD);
7879

SerialPrograms/Source/PokemonFRLG/Programs/PokemonFRLG_StartMenuNavigation.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,16 @@ bool move_cursor_to_position(ConsoleHandle& console, ProControllerContext& conte
134134
);
135135
}
136136

137+
bool move_cursor_to_position(ConsoleHandle& console, ProControllerContext& context, SelectionArrowPositionNoDexMenu destination){
138+
return move_cursor_impl(
139+
console, context,
140+
MENU_ARROW_BOX,
141+
NO_DEX_START_MENU_OPTION_COUNT,
142+
[](int i){ return SelectionArrowDetector::arrow_box_for_position(static_cast<SelectionArrowPositionNoDexMenu>(i)); },
143+
static_cast<int>(destination)
144+
);
145+
}
146+
137147
void save_game_to_overworld(ConsoleHandle& console, ProControllerContext& context){
138148

139149
WallClock start = current_time();

SerialPrograms/Source/PokemonFRLG/Programs/PokemonFRLG_StartMenuNavigation.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,13 @@ bool move_cursor_to_position(
4747
SelectionArrowPositionSafariMenu destination
4848
);
4949

50+
// Starting from the start menu before the PokeDex has been received, move the selection arrow to the specified position.
51+
// Return true if successful, false otherwise (e.g. if selection arrow is not detected).
52+
bool move_cursor_to_position(
53+
ConsoleHandle& console, ProControllerContext& context,
54+
SelectionArrowPositionNoDexMenu destination
55+
);
56+
5057
// Starting from either the overworld or the main menu, save the game.
5158
// This function returns in the overworld.
5259
void save_game_to_overworld(ConsoleHandle& console, ProControllerContext& context);

0 commit comments

Comments
 (0)