From c72ed6261224cc0a1b8aa72f6af966715970ff60 Mon Sep 17 00:00:00 2001 From: Christian Heller Date: Wed, 20 Nov 2013 06:04:10 +0100 Subject: [PATCH] Improved (and simplified) pseudo-randomness. --- src/main.c | 8 +++++--- src/main.h | 1 + src/map.c | 3 +-- src/misc.c | 23 +++++++++++++++++------ src/misc.h | 6 ++++++ src/rrand.c | 23 ----------------------- src/rrand.h | 23 ----------------------- 7 files changed, 30 insertions(+), 57 deletions(-) delete mode 100644 src/rrand.c delete mode 100644 src/rrand.h diff --git a/src/main.c b/src/main.c index 86f8507..478f764 100644 --- a/src/main.c +++ b/src/main.c @@ -20,10 +20,9 @@ #include "map.h" /* for struct Map, init_map() */ #include "misc.h" /* for update_log(), find_passable_pos(), save_game(), * try_calloc(), check_tempfile(), check_xor_files(), - * load_interface_conf(), load_game() + * load_interface_conf(), load_game(), rrand() */ #include "wincontrol.h" /* get_win_by_id(), get_winconf_by_win() */ -#include "rrand.h" /* for rrand(), rrand_seed() */ #include "rexit.h" /* for exit_game(), exit_err() */ #include "command_db.h" /* for init_command_db(), is_command_id_shortdsc() */ #include "control.h" /* for control_by_id(), player_control(), @@ -127,12 +126,14 @@ int main(int argc, char *argv[]) exit_err(write_uint32_bigendian(world.seed, file), err_w); try_fclose_unlink_rename(file, recordfile_tmp, recordfile, f_name); } + world.mapseed = world.seed; } /* Generate map from seed and, if newly generated world, start positions of * actors. */ - rrand_seed(world.seed); + uint32_t restore_seed = world.seed; + world.seed = world.mapseed; struct Map map = init_map(); world.map = ↦ set_cleanup_flag(CLEANUP_MAP); @@ -148,6 +149,7 @@ int main(int argc, char *argv[]) set_cleanup_flag(CLEANUP_MAP_OBJECTS); world.turn = 1; } + world.seed = restore_seed; /* Initialize window system and windows. */ WINDOW * screen = initscr(); diff --git a/src/main.h b/src/main.h index 687dfc8..f3670b2 100644 --- a/src/main.h +++ b/src/main.h @@ -25,6 +25,7 @@ struct World struct KeyBiData kb_wingeom; /* Window geometry config keybindings. */ struct KeyBiData kb_winkeys; /* Window keybinding config keybindings.*/ uint32_t seed; /* Randomness seed. */ + uint32_t mapseed; /* Initial randomness seed used for map.*/ uint32_t turn; /* Current game turn. */ uint16_t score; /* Player's score. */ char * log; /* Pointer to the game log string. */ diff --git a/src/map.c b/src/map.c index 1615818..b8c8733 100644 --- a/src/map.c +++ b/src/map.c @@ -1,9 +1,8 @@ #include "map.h" #include /* for uint16_t, uint32_t */ -#include "misc.h" /* for try_malloc(), center_offset() */ +#include "misc.h" /* for try_malloc(), center_offset(), rrand() */ #include "map_objects.h" /* for get_player() */ #include "yx_uint16.h" /* for yx_uint16 and dir enums */ -#include "rrand.h" /* for rrand() */ #include "windows.h" /* for struct Win */ #include "main.h" /* for world global */ #include "wincontrol.h" /* for get_win_by_id() */ diff --git a/src/misc.c b/src/misc.c index 0e8abe9..e71770d 100644 --- a/src/misc.c +++ b/src/misc.c @@ -5,7 +5,7 @@ #include /* for unlink(), acess() */ #include /* for size_t, calloc(), free() */ #include /* for strlen(), strcmp(), memcpy() */ -#include /* for uint8_t, uint16_t */ +#include /* for uint8_t, uint16_t, uint32_t */ #include "readwrite.h" /* for [read/write]_uint[8/16/32][_bigendian](), * try_fopen(), try_fclose(), get_linemax() */ @@ -16,7 +16,6 @@ #include "map.h" /* for Map struct, is_passable() */ #include "main.h" /* for world global */ #include "yx_uint16.h" /* for yx_uint16 struct */ -#include "rrand.h" /* for rrand(), rrand_seed() */ #include "rexit.h" /* for exit_err() */ #include "wincontrol.h" /* for init_winconfs(), init_wins(), free_winconfs(), * sorted_wintoggle_and_activate() @@ -26,6 +25,15 @@ +extern uint16_t rrand() +{ + /* Constants as recommended by POSIX.1-2001 (see man page rand(3)). */ + world.seed = ((world.seed * 1103515245) + 12345) % 4294967296; + return (world.seed >> 16); /* Ignore less random least significant bits. */ +} + + + extern char * trouble_msg(char * parent, char * child) { char * p1 = "Trouble in "; @@ -229,7 +237,6 @@ extern void turn_over(char action) } try_fclose_unlink_rename(file_new, recordfile_tmp, recordfile, f_name); } - rrand_seed(world.seed * world.turn); struct MapObj * player = get_player(); struct MapObj * map_object = player; @@ -279,11 +286,13 @@ extern void save_game() char * savefile = "savefile"; FILE * file = try_fopen(savefile_tmp, "w", f_name); char line[12]; - sprintf(line, "%d\n", world.seed); + sprintf(line, "%u\n", world.mapseed); + try_fwrite(line, strlen(line), 1, file, f_name); + sprintf(line, "%u\n", world.seed); try_fwrite(line, strlen(line), 1, file, f_name); - sprintf(line, "%d\n", world.turn); + sprintf(line, "%u\n", world.turn); try_fwrite(line, strlen(line), 1, file, f_name); - sprintf(line, "%d\n", world.score); + sprintf(line, "%u\n", world.score); try_fwrite(line, strlen(line), 1, file, f_name); write_map_objects(file); try_fclose_unlink_rename(file, savefile_tmp, savefile, f_name); @@ -299,6 +308,8 @@ extern void load_game() uint16_t linemax = get_linemax(file, f_name); char line[linemax + 1]; try_fgets(line, linemax + 1, file, f_name); + world.mapseed = atoi(line); + try_fgets(line, linemax + 1, file, f_name); world.seed = atoi(line); try_fgets(line, linemax + 1, file, f_name); world.turn = atoi(line); diff --git a/src/misc.h b/src/misc.h index fad27f6..bc3e274 100644 --- a/src/misc.h +++ b/src/misc.h @@ -14,6 +14,12 @@ struct Map; +/* Return 16-bit number pseudo-randomly generated via Linear Congruential + * Generator algorithm with some proven constants. Use instead of rand() to + * ensure portability of the same pseudo-randomness across systems. + */ +extern uint16_t rrand(); + /* Returns message: "Trouble in ".parent." with ".child."." (try_*() helper) */ extern char * trouble_msg(char * parent, char * child); diff --git a/src/rrand.c b/src/rrand.c deleted file mode 100644 index e2b459b..0000000 --- a/src/rrand.c +++ /dev/null @@ -1,23 +0,0 @@ -#include "rrand.h" -#include /* for uint16_t, uint32_t */ - - - -static uint32_t seed = 0; - - - -extern uint16_t rrand() -{ - /* Constants as recommended by POSIX.1-2001 (see man page rand(3)). */ - seed = ((seed * 1103515245) + 12345) % 2147483647; - - return (seed >> 16); /* Ignore less random least significant 16 bits. */ -} - - - -extern void rrand_seed(uint32_t new_seed) -{ - seed = new_seed; -} diff --git a/src/rrand.h b/src/rrand.h deleted file mode 100644 index 056be9b..0000000 --- a/src/rrand.h +++ /dev/null @@ -1,23 +0,0 @@ -/* rrand.h - * - * Provide pseudo-random numbers via a Linear Congruential Generator algorithm - * with some proven constants. Use these functions instead of rand() and - * srand() to ensure portable pseudo-randomness portability. - */ - -#ifndef RRAND_H -#define RRAND_H - -#include /* for uint32_t */ - - - -/* Return 16-bit number pseudo-randomly generated. */ -extern uint16_t rrand(); - -/* Set seed that rrand() starts from. */ -extern void rrand_seed(uint32_t new_seed); - - - -#endif -- 2.30.2