The game uses pseudo-random number generator (aka RNG) for random events, success checks, damage rolls, etc.
The generator state is saved with the game. The game is guaranteed to reproduce outcome of all checks exactly if you repeat all your actions in the same order. For example if you saved the game, pressed 'end turn' and some random event occurs, say The Antarans come, then you can’t avoid them by simply reloading and ending turn again. The exact same event will repeat no matter how many times you reload. On the other hand you can change the result by reloading, triggering a random check (e.g. diplomatic demands require passing such check for success), and then ending the turn. Since an extra random check have occurred the antaran roll will likely happen differently.
This reproducible randomness is crucial to how network synchronization works in MOO2. When patching the game either ensure same rolls are done in a symmetrical manner in multiplayer or restore the RNG state after use. As a side effect this feature tends to make bugs reproducible.
The Algorithm
The RNG works off a rng_seed
, a 32 bit game-global integer. Technically this is a state
rather than a seed, but for this RNG they are the same and the code uses the term seed.
The Random(n)
function returns a random unsigned 32 bit integer number from 1 to n:
uint32_t rng_seed; uint32_t Random(uint32_t n) { if (n == 0) return 1; uint32_t step = MAX_UINT32 / n; while (1) { rng_seed = 1103515245 * rng_seed + 12345; if (rng_seed < step * n) return rng_state / step + 1; } }
The seed is initialized from the clock when starting a new game unless /seed=
command line switch is used.