diff options
-rw-r--r-- | src/core/random_func.cpp | 46 | ||||
-rw-r--r-- | src/core/random_func.hpp | 39 | ||||
-rw-r--r-- | src/genworld.cpp | 2 | ||||
-rw-r--r-- | src/misc.cpp | 4 | ||||
-rw-r--r-- | src/network/network.cpp | 8 | ||||
-rw-r--r-- | src/oldloader.cpp | 2 |
6 files changed, 61 insertions, 40 deletions
diff --git a/src/core/random_func.cpp b/src/core/random_func.cpp index b0939229e..f74309a6e 100644 --- a/src/core/random_func.cpp +++ b/src/core/random_func.cpp @@ -6,20 +6,26 @@ #include "random_func.hpp" #include "bitmath_func.hpp" -uint32 _random_seeds[2][2]; +Randomizer _random, _interactive_random; -uint32 InteractiveRandom() +uint32 Randomizer::Next() { - const uint32 s = _random_seeds[1][0]; - const uint32 t = _random_seeds[1][1]; + const uint32 s = this->state[0]; + const uint32 t = this->state[1]; - _random_seeds[1][0] = s + ROR(t ^ 0x1234567F, 7) + 1; - return _random_seeds[1][1] = ROR(s, 3) - 1; + this->state[0] = s + ROR(t ^ 0x1234567F, 7) + 1; + return this->state[1] = ROR(s, 3) - 1; } -uint InteractiveRandomRange(uint max) +uint32 Randomizer::Next(uint16 max) { - return GB(InteractiveRandom(), 0, 16) * max >> 16; + return GB(this->Next(), 0, 16) * max >> 16; +} + +void Randomizer::SetSeed(uint32 seed) +{ + this->state[0] = seed; + this->state[1] = seed; } #ifdef MERSENNE_TWISTER @@ -119,28 +125,21 @@ uint32 Random() #else /* MERSENNE_TWISTER */ void SetRandomSeed(uint32 seed) { - _random_seeds[0][0] = seed; - _random_seeds[0][1] = seed; - _random_seeds[1][0] = seed * 0x1234567; - _random_seeds[1][1] = _random_seeds[1][0]; + _random.SetSeed(seed); + _interactive_random.SetSeed(seed * 0x1234567); } #ifdef RANDOM_DEBUG #include "../network/network_data.h" uint32 DoRandom(int line, const char *file) { - if (_networking && (DEREF_CLIENT(0)->status != STATUS_INACTIVE || !_network_server)) + if (_networking && (DEREF_CLIENT(0)->status != STATUS_INACTIVE || !_network_server)) { printf("Random [%d/%d] %s:%d\n",_frame_counter, (byte)_current_player, file, line); -#else /* RANDOM_DEBUG */ -uint32 Random() -{ -#endif /* RANDOM_DEBUG */ - const uint32 s = _random_seeds[0][0]; - const uint32 t = _random_seeds[0][1]; + } - _random_seeds[0][0] = s + ROR(t ^ 0x1234567F, 7) + 1; - return _random_seeds[0][1] = ROR(s, 3) - 1; + return _random->Next() } +#endif /* RANDOM_DEBUG */ #endif /* MERSENNE_TWISTER */ #if defined(RANDOM_DEBUG) && !defined(MERSENNE_TWISTER) @@ -148,9 +147,4 @@ uint DoRandomRange(uint max, int line, const char *file) { return GB(DoRandom(line, file), 0, 16) * max >> 16; } -#else /* RANDOM_DEBUG & !MERSENNE_TWISTER */ -uint RandomRange(uint max) -{ - return GB(Random(), 0, 16) * max >> 16; -} #endif /* RANDOM_DEBUG & !MERSENNE_TWISTER */ diff --git a/src/core/random_func.hpp b/src/core/random_func.hpp index f3d35d987..d941f283c 100644 --- a/src/core/random_func.hpp +++ b/src/core/random_func.hpp @@ -27,6 +27,35 @@ // Doesn't work with network yet. // #define MERSENNE_TWISTER +/** + * Structure to encapsulate the pseudo random number generators. + */ +struct Randomizer { + /** The state of the randomizer */ + uint32 state[2]; + + /** + * Generate the next pseudo random number + * @return the random number + */ + uint32 Next(); + + /** + * Generate the next pseudo random number scaled to max + * @param max the maximum value of the returned random number + * @return the random number + */ + uint32 Next(uint16 max); + + /** + * (Re)set the state of the random number generator. + * @param seed the new state + */ + void SetSeed(uint32 seed); +}; +extern Randomizer _random; ///< Random used in the game state calculations +extern Randomizer _interactive_random; ///< Random used every else where is does not (directly) influence the game state + void SetRandomSeed(uint32 seed); #ifdef RANDOM_DEBUG #define Random() DoRandom(__LINE__, __FILE__) @@ -34,12 +63,12 @@ void SetRandomSeed(uint32 seed); #define RandomRange(max) DoRandomRange(max, __LINE__, __FILE__) uint DoRandomRange(uint max, int line, const char *file); #else - uint32 Random(); - uint RandomRange(uint max); + static inline uint32 Random() { return _random.Next(); } + static inline uint32 RandomRange(uint16 max) { return _random.Next(max); } #endif -uint32 InteractiveRandom(); // Used for random sequences that are not the same on the other end of the multiplayer link -uint InteractiveRandomRange(uint max); +static inline uint32 InteractiveRandom() { return _interactive_random.Next(); } +static inline uint32 InteractiveRandomRange(uint16 max) { return _interactive_random.Next(max); } /** * Checks if a given randomize-number is below a given probability. @@ -100,6 +129,4 @@ static inline bool Chance16R(const uint a, const uint b, uint32 &r) return Chance16I(a, b, r); } -extern uint32 _random_seeds[2][2]; - #endif /* RANDOM_FUNC_HPP */ diff --git a/src/genworld.cpp b/src/genworld.cpp index f33df1a25..08768e024 100644 --- a/src/genworld.cpp +++ b/src/genworld.cpp @@ -90,7 +90,7 @@ static void *_GenerateWorld(void *arg) if (_network_dedicated) DEBUG(net, 0, "Generating map, please wait..."); /* Set the Random() seed to generation_seed so we produce the same map with the same seed */ if (_patches.generation_seed == GENERATE_NEW_SEED) _patches.generation_seed = _patches_newgame.generation_seed = InteractiveRandom(); - _random_seeds[0][0] = _random_seeds[0][1] = _patches.generation_seed; + _random.SetSeed(_patches.generation_seed); SetGeneratingWorldProgress(GWP_MAP_INIT, 2); SetObjectToPlace(SPR_CURSOR_ZZZ, PAL_NONE, VHM_NONE, WC_MAIN_WINDOW, 0); diff --git a/src/misc.cpp b/src/misc.cpp index 599a3563d..4d828c9b7 100644 --- a/src/misc.cpp +++ b/src/misc.cpp @@ -205,8 +205,8 @@ static const SaveLoadGlobVarList _date_desc[] = { SLEG_CONDVAR(_cur_tileloop_tile, SLE_UINT32, 6, SL_MAX_VERSION), SLEG_VAR(_disaster_delay, SLE_UINT16), SLEG_VAR(_station_tick_ctr, SLE_UINT16), - SLEG_VAR(_random_seeds[0][0], SLE_UINT32), - SLEG_VAR(_random_seeds[0][1], SLE_UINT32), + SLEG_VAR(_random.state[0], SLE_UINT32), + SLEG_VAR(_random.state[1], SLE_UINT32), SLEG_CONDVAR(_cur_town_ctr, SLE_FILE_U8 | SLE_VAR_U32, 0, 9), SLEG_CONDVAR(_cur_town_ctr, SLE_UINT32, 10, SL_MAX_VERSION), SLEG_VAR(_cur_player_tick_index, SLE_FILE_U8 | SLE_VAR_U32), diff --git a/src/network/network.cpp b/src/network/network.cpp index 1cd128181..b8a53feb5 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -1235,9 +1235,9 @@ static bool NetworkDoClientLoop() if (_sync_frame != 0) { if (_sync_frame == _frame_counter) { #ifdef NETWORK_SEND_DOUBLE_SEED - if (_sync_seed_1 != _random_seeds[0][0] || _sync_seed_2 != _random_seeds[0][1]) { + if (_sync_seed_1 != _random.state[0] || _sync_seed_2 != _random.state[1]) { #else - if (_sync_seed_1 != _random_seeds[0][0]) { + if (_sync_seed_1 != _random.state[0]) { #endif NetworkError(STR_NETWORK_ERR_DESYNC); DebugDumpCommands("ddc:serr:%d;%d\n", _date, _date_fract); @@ -1332,9 +1332,9 @@ void NetworkGameLoop() // Then we make the frame StateGameLoop(); - _sync_seed_1 = _random_seeds[0][0]; + _sync_seed_1 = _random.state[0]; #ifdef NETWORK_SEND_DOUBLE_SEED - _sync_seed_2 = _random_seeds[0][1]; + _sync_seed_2 = _random.state[1]; #endif NetworkServer_Tick(send_frame); diff --git a/src/oldloader.cpp b/src/oldloader.cpp index e5606f65f..ec5f7b9e0 100644 --- a/src/oldloader.cpp +++ b/src/oldloader.cpp @@ -1456,7 +1456,7 @@ static const OldChunks main_chunk[] = { OCL_VAR ( OC_FILE_U16 | OC_VAR_U32, 1, &_date ), OCL_VAR ( OC_UINT16, 1, &_date_fract ), OCL_NULL( 600 ), ///< TextEffects - OCL_VAR ( OC_UINT32, 2, &_random_seeds[0] ), + OCL_VAR ( OC_UINT32, 2, &_random.state ), OCL_ASSERT( 0x264 ), OCL_CHUNK( 70, LoadOldTown ), |