Refactor/RNG system (#476)
* Extract rng manipulation to its own file * clang format * Get CPU cycles since game start to use for RNG * change a few things * clang format * Implement suggestions from @ricfehr3 * clang format * Fix rebase issue * clang format * Create RngInfo struct to hold seed and step * clang format * Make a note about rng_restore system not having been tested properly yet * Apply suggestions from @ricfehr3 Co-authored-by: Rickey <ric@rf3.xyz> * clang format --------- Co-authored-by: MathisMartin31 <mathis.martin31@gmail.com> Co-authored-by: Rickey <ric@rf3.xyz>
This commit is contained in:
co-authored by
Rickey
MathisMartin31
parent
e3f680d6d0
commit
c2844a5d32
+2
-1
@@ -4,6 +4,7 @@
|
||||
#include "game.h"
|
||||
#include "graphic_utils.h"
|
||||
#include "list.h"
|
||||
#include "random.h"
|
||||
#include "stdbool.h"
|
||||
#include "util.h"
|
||||
|
||||
@@ -139,7 +140,7 @@ enum BlindType roll_blind_type(bool showdown)
|
||||
}
|
||||
|
||||
// roll a random blind among the unbeaten ones
|
||||
int random_blind_idx = get_rand() % list_get_len(p_unbeaten_blinds);
|
||||
int random_blind_idx = rng_get_u32() % list_get_len(p_unbeaten_blinds);
|
||||
Blind* random_blind = list_get_at_idx(p_unbeaten_blinds, random_blind_idx);
|
||||
|
||||
return random_blind->type;
|
||||
|
||||
+9
-20
@@ -21,6 +21,7 @@
|
||||
#include "joker.h"
|
||||
#include "layout.h"
|
||||
#include "list.h"
|
||||
#include "random.h"
|
||||
#include "save.h"
|
||||
#include "selection_grid.h"
|
||||
#include "soundbank.h"
|
||||
@@ -299,7 +300,8 @@ static ContainedHandTypes _contained_hands = {0};
|
||||
// Initialization of the global vars
|
||||
// clang-format off
|
||||
GameVariables g_game_vars = {
|
||||
.timer = 0, .rng_seed = 0, .rng_step = 0,
|
||||
.timer = 0,
|
||||
.rng_info = {0, 0},
|
||||
|
||||
.round = 0, .ante = 0, .money = 0,
|
||||
|
||||
@@ -629,6 +631,8 @@ static inline void jokers_update_loop(void)
|
||||
|
||||
void game_update()
|
||||
{
|
||||
rng_update();
|
||||
|
||||
g_game_vars.timer++;
|
||||
|
||||
jokers_update_loop();
|
||||
@@ -654,12 +658,6 @@ void game_change_state(enum GameState new_game_state)
|
||||
}
|
||||
}
|
||||
|
||||
u32 get_rand()
|
||||
{
|
||||
g_game_vars.rng_step++;
|
||||
return rand();
|
||||
}
|
||||
|
||||
CardObject** get_hand_array(void)
|
||||
{
|
||||
return hand;
|
||||
@@ -1429,7 +1427,7 @@ static inline void deck_shuffle(void)
|
||||
{
|
||||
for (int i = deck_top; i > 0; i--)
|
||||
{
|
||||
int j = get_rand() % (i + 1);
|
||||
int j = rng_get_u32() % (i + 1);
|
||||
Card* temp = deck[i];
|
||||
deck[i] = deck[j];
|
||||
deck[j] = temp;
|
||||
@@ -1505,14 +1503,6 @@ static void game_round_on_init(void)
|
||||
game_playing_selection_grid.selection = GAME_PLAYING_INIT_SEL;
|
||||
}
|
||||
|
||||
// General functions
|
||||
static inline void set_seed(int seed)
|
||||
{
|
||||
srand(seed);
|
||||
g_game_vars.rng_seed = seed;
|
||||
g_game_vars.rng_step = 0;
|
||||
}
|
||||
|
||||
// Playing state functions
|
||||
static void game_playing_discard_on_pressed(void)
|
||||
{
|
||||
@@ -1670,7 +1660,7 @@ static bool game_playing_hand_row_on_selection_changed(
|
||||
*/
|
||||
play_sfx(
|
||||
SFX_CARD_FOCUS,
|
||||
MM_BASE_PITCH_RATE + get_rand() % CARD_FOCUS_SFX_PITCH_OFFSET_RANGE,
|
||||
MM_BASE_PITCH_RATE + rng_get_u32() % CARD_FOCUS_SFX_PITCH_OFFSET_RANGE,
|
||||
SFX_DEFAULT_VOLUME
|
||||
);
|
||||
}
|
||||
@@ -1690,7 +1680,7 @@ static bool game_playing_hand_row_on_selection_changed(
|
||||
*/
|
||||
play_sfx(
|
||||
SFX_CARD_FOCUS,
|
||||
MM_BASE_PITCH_RATE + get_rand() % CARD_FOCUS_SFX_PITCH_OFFSET_RANGE,
|
||||
MM_BASE_PITCH_RATE + rng_get_u32() % CARD_FOCUS_SFX_PITCH_OFFSET_RANGE,
|
||||
SFX_DEFAULT_VOLUME
|
||||
);
|
||||
}
|
||||
@@ -3020,8 +3010,7 @@ static void game_playing_on_update(void)
|
||||
|
||||
void game_start(void)
|
||||
{
|
||||
// set_seed(9); // 9 is a full house
|
||||
set_seed(g_game_vars.rng_seed);
|
||||
rng_shuffle_seed();
|
||||
|
||||
affine_background_change_background(AFFINE_BG_GAME);
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "game/main_menu.h"
|
||||
#include "graphic_utils.h"
|
||||
#include "layout.h"
|
||||
#include "random.h"
|
||||
#include "soundbank.h"
|
||||
#include "timer.h"
|
||||
#include "util.h"
|
||||
@@ -128,4 +129,5 @@ void game_over_on_exit(void)
|
||||
{
|
||||
condition = END_CONDITION_NONE;
|
||||
game_reset();
|
||||
rng_shuffle_seed();
|
||||
}
|
||||
|
||||
@@ -127,14 +127,6 @@ void game_main_menu_on_update(void)
|
||||
main_menu_ace->sprite_object->trotation = lu_sin((g_game_vars.timer << 8) / 2) / 3;
|
||||
card_object_update(main_menu_ace);
|
||||
|
||||
// Seed randomization
|
||||
g_game_vars.rng_seed++;
|
||||
// If the keys have changed, make it more pseudo-random
|
||||
if (key_curr_state() != key_prev_state())
|
||||
{
|
||||
g_game_vars.rng_seed *= 2;
|
||||
}
|
||||
|
||||
selection_grid_process_input(&main_menu_selection_grid);
|
||||
}
|
||||
|
||||
|
||||
+4
-3
@@ -17,6 +17,7 @@
|
||||
#include "joker.h"
|
||||
#include "layout.h"
|
||||
#include "list.h"
|
||||
#include "random.h"
|
||||
#include "save.h"
|
||||
#include "soundbank.h"
|
||||
#include "timer.h"
|
||||
@@ -196,7 +197,7 @@ static inline int game_shop_get_rand_available_joker_id(void)
|
||||
return UNDEFINED;
|
||||
|
||||
int matching_joker_ids[jokers_avail_size];
|
||||
int fallback_random_idx = get_rand() % jokers_avail_size;
|
||||
int fallback_random_idx = rng_get_u32() % jokers_avail_size;
|
||||
int fallback_random_joker_id = UNDEFINED;
|
||||
int match_count = 0;
|
||||
|
||||
@@ -215,8 +216,8 @@ static inline int game_shop_get_rand_available_joker_id(void)
|
||||
}
|
||||
}
|
||||
|
||||
int selected_joker_id =
|
||||
(match_count > 0) ? matching_joker_ids[get_rand() % match_count] : fallback_random_joker_id;
|
||||
int selected_joker_id = (match_count > 0) ? matching_joker_ids[rng_get_u32() % match_count]
|
||||
: fallback_random_joker_id;
|
||||
|
||||
return selected_joker_id;
|
||||
}
|
||||
|
||||
+2
-1
@@ -5,6 +5,7 @@
|
||||
#include "graphic_utils.h"
|
||||
#include "joker_gfx.h"
|
||||
#include "pool.h"
|
||||
#include "random.h"
|
||||
#include "soundbank.h"
|
||||
#include "util.h"
|
||||
|
||||
@@ -368,7 +369,7 @@ Sprite* joker_object_get_sprite(JokerObject* joker_object)
|
||||
int joker_get_random_rarity()
|
||||
{
|
||||
int joker_rarity = 0;
|
||||
int rarity_roll = get_rand() % 100;
|
||||
int rarity_roll = rng_get_u32() % 100;
|
||||
if (rarity_roll < COMMON_JOKER_CHANCE)
|
||||
{
|
||||
joker_rarity = COMMON_JOKER;
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "joker.h"
|
||||
#include "list.h"
|
||||
#include "pool.h"
|
||||
#include "random.h"
|
||||
#include "util.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
@@ -563,7 +564,7 @@ static u32 misprint_joker_effect(
|
||||
|
||||
*joker_effect = &shared_joker_effect;
|
||||
|
||||
(*joker_effect)->mult = get_rand() % (MISPRINT_MAX_MULT + 1);
|
||||
(*joker_effect)->mult = rng_get_u32() % (MISPRINT_MAX_MULT + 1);
|
||||
|
||||
return JOKER_EFFECT_FLAG_MULT;
|
||||
}
|
||||
@@ -776,7 +777,7 @@ static u32 reserved_parking_joker_effect(
|
||||
|
||||
u32 effect_flags_ret = JOKER_EFFECT_FLAG_NONE;
|
||||
|
||||
if ((get_rand() % 2 == 0) && card_is_face(scored_card))
|
||||
if ((rng_get_u32() % 2 == 0) && card_is_face(scored_card))
|
||||
{
|
||||
*joker_effect = &shared_joker_effect;
|
||||
|
||||
@@ -798,7 +799,7 @@ static u32 business_card_joker_effect(
|
||||
|
||||
u32 effect_flags_ret = JOKER_EFFECT_FLAG_NONE;
|
||||
|
||||
if ((get_rand() % 2 == 0) && card_is_face(scored_card))
|
||||
if ((rng_get_u32() % 2 == 0) && card_is_face(scored_card))
|
||||
{
|
||||
*joker_effect = &shared_joker_effect;
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "gbalatro_sys8.h"
|
||||
#include "graphic_utils.h"
|
||||
#include "joker.h"
|
||||
#include "random.h"
|
||||
#include "save.h"
|
||||
#include "sprite.h"
|
||||
|
||||
@@ -24,6 +25,8 @@
|
||||
|
||||
void init()
|
||||
{
|
||||
rng_init();
|
||||
|
||||
irq_init(NULL);
|
||||
irq_add(II_VBLANK, mmVBlank);
|
||||
irq_add(II_HBLANK, affine_background_hblank);
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
#include "random.h"
|
||||
|
||||
#include "game_variables.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <tonc.h>
|
||||
|
||||
// Accumulate timer 1 into a bigger variable so we can generate more diverse seeds
|
||||
static u32 timer_acc = 0;
|
||||
|
||||
// Timers usage docs: https://gbadev.net/tonc/timers.html
|
||||
void rng_init(void)
|
||||
{
|
||||
REG_TM1D = 0;
|
||||
REG_TM1CNT = TM_FREQ_1 | TM_ENABLE; // using timer with x1 prescale
|
||||
}
|
||||
|
||||
void rng_update(void)
|
||||
{
|
||||
timer_acc += (u32)REG_TM1D;
|
||||
}
|
||||
|
||||
void rng_set_seed(u32 seed)
|
||||
{
|
||||
g_game_vars.rng_info.seed = seed % (MAX_SEED + 1);
|
||||
g_game_vars.rng_info.step = 0;
|
||||
srand(g_game_vars.rng_info.seed);
|
||||
}
|
||||
|
||||
void rng_shuffle_seed(void)
|
||||
{
|
||||
rng_set_seed(timer_acc);
|
||||
}
|
||||
|
||||
u32 rng_get_u32(void)
|
||||
{
|
||||
g_game_vars.rng_info.step++;
|
||||
return rand();
|
||||
}
|
||||
|
||||
void rng_restore(RngInfo info)
|
||||
{
|
||||
g_game_vars.rng_info = info;
|
||||
|
||||
srand(g_game_vars.rng_info.seed);
|
||||
for (u32 i = 0; i < g_game_vars.rng_info.step; i++)
|
||||
{
|
||||
(void)rng_get_u32();
|
||||
}
|
||||
}
|
||||
+6
-16
@@ -105,8 +105,8 @@ typedef struct JokerObjectSaveData
|
||||
* 2 | 'L' | ' ' | 'D' | 'A' | - | -
|
||||
* 3 | 'T' | 'A' | ' ' | '-' | - | -
|
||||
* 4 | T[0] | T[1] | T[2] | T[3] | GLOB TIMER | The global timer used for animations thoughout the game
|
||||
* 5 | SED[0] | SED[1] | SED[2] | SED[3] | RNG SEED | The seed used for RNG, either randomly shuffled or chosen by the player at game start
|
||||
* 6 | STP[0] | STP[1] | STP[2] | STP[3] | RNG STEP | The current position in the RNG sequence for the given seed, since the start of the run
|
||||
* 5 | RNG[0] | RNG[1] | RNG[2] | RNG[3] | RNG INFO | RNG Info struct, containing the seed used for RNG, either randomly shuffled or chosen by the player
|
||||
* 6 | RNG[4] | RNG[5] | RNG[6] | RNG[7] | - | at game start, and the current position in the RNG sequence for the given seed, since the start of the run
|
||||
* 7 | RND[0] | RND[1] | RND[2] | RND[3] | ROUND | What Round we are about to start
|
||||
* 8 | ANT[0] | ANT[1] | ANT[2] | ANT[3] | ANTE | What Ante we are on
|
||||
* 9 | MNY[0] | MNY[1] | MNY[2] | MNY[3] | MONEY | How much money we currently have left
|
||||
@@ -127,8 +127,7 @@ typedef struct SaveGame
|
||||
{
|
||||
char tag_internal[SAVE_LABEL_SIZE];
|
||||
s32 timer;
|
||||
u32 rng_seed;
|
||||
u32 rng_step;
|
||||
RngInfo rng_info;
|
||||
int round;
|
||||
int ante;
|
||||
int money;
|
||||
@@ -168,8 +167,7 @@ static const SaveOptions SaveOptions_default = {
|
||||
static const SaveGame SaveGame_default = {
|
||||
.tag_internal = "-INTERNAL DATA -",
|
||||
.timer = 0,
|
||||
.rng_seed = 0,
|
||||
.rng_step = 0,
|
||||
.rng_info = {0, 0},
|
||||
.round = 0,
|
||||
.ante = 0,
|
||||
.money = 0,
|
||||
@@ -328,8 +326,7 @@ void save_game(void)
|
||||
// Fixed data
|
||||
|
||||
game.timer = g_game_vars.timer;
|
||||
game.rng_seed = g_game_vars.rng_seed;
|
||||
game.rng_step = g_game_vars.rng_step;
|
||||
game.rng_info = g_game_vars.rng_info;
|
||||
game.round = g_game_vars.round;
|
||||
game.ante = g_game_vars.ante;
|
||||
game.money = g_game_vars.money;
|
||||
@@ -370,17 +367,10 @@ void load_game(void)
|
||||
read_sram(GAME_ADDRESS, (u8*)&game, sizeof(game));
|
||||
|
||||
g_game_vars.timer = game.timer;
|
||||
g_game_vars.rng_seed = game.rng_seed;
|
||||
g_game_vars.rng_step = game.rng_step;
|
||||
rng_restore(game.rng_info);
|
||||
g_game_vars.round = game.round;
|
||||
g_game_vars.ante = game.ante;
|
||||
g_game_vars.money = game.money;
|
||||
|
||||
// TODO: load Jokers from stored minimal data
|
||||
|
||||
// return to where we were in the random sequence so that the run stays reproducible
|
||||
for (u32 i = 0; i < g_game_vars.rng_step; i++)
|
||||
{
|
||||
(void)rand();
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -5,6 +5,7 @@
|
||||
#include "game_variables.h"
|
||||
#include "graphic_utils.h"
|
||||
#include "pool.h"
|
||||
#include "random.h"
|
||||
#include "soundbank.h"
|
||||
#include "util.h"
|
||||
|
||||
@@ -330,7 +331,7 @@ void sprite_object_set_focus(SpriteObject* sprite_object, bool focus)
|
||||
|
||||
play_sfx(
|
||||
SFX_CARD_FOCUS,
|
||||
MM_BASE_PITCH_RATE + get_rand() % CARD_FOCUS_SFX_PITCH_OFFSET_RANGE,
|
||||
MM_BASE_PITCH_RATE + rng_get_u32() % CARD_FOCUS_SFX_PITCH_OFFSET_RANGE,
|
||||
SFX_DEFAULT_VOLUME
|
||||
);
|
||||
sprite_object->ty = sprite_object->ty + int2fx((focus ? -1 : 1) * SPRITE_FOCUS_RAISE_PX);
|
||||
|
||||
Reference in New Issue
Block a user