4 * Copyright (c) 1997 Ben Harrison, and others
6 * This software may be copied and distributed for educational, research,
7 * and not for profit purposes provided that this copyright and statement
8 * are included in all such copies. Other copyrights may also apply.
12 /* Purpose: a simple random number generator -BEN- */
20 * Angband 2.7.9 introduced a new (optimized) random number generator,
21 * based loosely on the old "random.c" from Berkeley but with some major
22 * optimizations and algorithm changes. See below for more details.
24 * Code by myself (benh@phial.com) and Randy (randy@stat.tamu.edu).
26 * This code provides (1) a "decent" RNG, based on the "BSD-degree-63-RNG"
27 * used in Angband 2.7.8, but rather optimized, and (2) a "simple" RNG,
28 * based on the simple "LCRNG" currently used in Angband, but "corrected"
29 * to give slightly better values. Both of these are available in two
30 * flavors, first, the simple "mod" flavor, which is fast, but slightly
31 * biased at high values, and second, the simple "div" flavor, which is
32 * less fast (and potentially non-terminating) but which is not biased
33 * and is much less subject to low-bit-non-randomness problems.
35 * You can select your favorite flavor by proper definition of the
36 * "randint0()" macro in the "defines.h" file.
38 * Note that, in Angband 2.8.0, the "state" table will be saved in the
39 * savefile, so a special "initialization" phase will be necessary.
41 * Note the use of the "simple" RNG, first you activate it via
42 * "Rand_quick = TRUE" and "Rand_value = seed" and then it is used
43 * automatically used instead of the "complex" RNG, and when you are
44 * done, you de-activate it via "Rand_quick = FALSE" or choose a new
45 * seed via "Rand_value = seed".
48 * RNG algorithm was fully rewritten. Upper comment is OLD.
58 * Current "state" table for the RNG
59 * Only index 0 to 3 are used
61 u32b Rand_state[RAND_DEG] = {
70 * Initialize Xorshift Algorithm state
72 static void Rand_Xorshift_seed(u32b seed, u32b* state)
76 /* Initialize Xorshift Algorithm RNG */
77 for (i = 1; i <= 4; ++ i) {
78 seed = 1812433253UL * (seed ^ (seed >> 30)) + i;
86 static u32b Rand_Xorshift(u32b* state)
88 u32b t = state[0] ^ (state[0] << 11);
94 state[3] = (state[3] ^ (state[3] >> 19)) ^ (t ^ (t >> 8));
99 static const u32b Rand_Xorshift_max = 0xFFFFFFFF;
102 * Initialize the RNG using a new seed
104 void Rand_state_set(u32b seed)
106 Rand_Xorshift_seed(seed, Rand_state);
109 void Rand_state_init(void)
113 FILE *fp = fopen(RNG_DEVICE, "r");
116 fread(buf, sizeof(buf[0]), 4, fp);
117 } while ((buf[0] | buf[1] | buf[2] | buf[3]) == 0);
118 memcpy(Rand_state, buf, sizeof(buf));
124 u32b seed = (time(NULL));
126 /* Mutate the seed on Unix machines */
127 seed = ((seed >> 3) * (getpid() << 1));
130 Rand_state_set(seed);
136 * Backup the RNG state
138 void Rand_state_backup(u32b* backup_state)
142 for (i = 0; i < 4; ++ i) {
143 backup_state[i] = Rand_state[i];
148 * Restore the RNG state
150 void Rand_state_restore(u32b* backup_state)
154 for (i = 0; i < 4; ++ i) {
155 Rand_state[i] = backup_state[i];
161 * Extract a "random" number from 0 to m-1, via "division"
163 static s32b Rand_div_impl(s32b m, u32b* state)
169 /* Hack -- simple case */
170 if (m <= 1) return (0);
172 scaling = Rand_Xorshift_max / m;
176 ret = Rand_Xorshift(state);
177 } while (ret >= past);
179 return ret / scaling;
182 s32b Rand_div(s32b m)
184 return Rand_div_impl(m, Rand_state);
191 * The number of entries in the "randnor_table"
193 #define RANDNOR_NUM 256
196 * The standard deviation of the "randnor_table"
198 #define RANDNOR_STD 64
201 * The normal distribution table for the "randnor()" function (below)
203 static s16b randnor_table[RANDNOR_NUM] =
205 206, 613, 1022, 1430, 1838, 2245, 2652, 3058,
206 3463, 3867, 4271, 4673, 5075, 5475, 5874, 6271,
207 6667, 7061, 7454, 7845, 8234, 8621, 9006, 9389,
208 9770, 10148, 10524, 10898, 11269, 11638, 12004, 12367,
209 12727, 13085, 13440, 13792, 14140, 14486, 14828, 15168,
210 15504, 15836, 16166, 16492, 16814, 17133, 17449, 17761,
211 18069, 18374, 18675, 18972, 19266, 19556, 19842, 20124,
212 20403, 20678, 20949, 21216, 21479, 21738, 21994, 22245,
214 22493, 22737, 22977, 23213, 23446, 23674, 23899, 24120,
215 24336, 24550, 24759, 24965, 25166, 25365, 25559, 25750,
216 25937, 26120, 26300, 26476, 26649, 26818, 26983, 27146,
217 27304, 27460, 27612, 27760, 27906, 28048, 28187, 28323,
218 28455, 28585, 28711, 28835, 28955, 29073, 29188, 29299,
219 29409, 29515, 29619, 29720, 29818, 29914, 30007, 30098,
220 30186, 30272, 30356, 30437, 30516, 30593, 30668, 30740,
221 30810, 30879, 30945, 31010, 31072, 31133, 31192, 31249,
223 31304, 31358, 31410, 31460, 31509, 31556, 31601, 31646,
224 31688, 31730, 31770, 31808, 31846, 31882, 31917, 31950,
225 31983, 32014, 32044, 32074, 32102, 32129, 32155, 32180,
226 32205, 32228, 32251, 32273, 32294, 32314, 32333, 32352,
227 32370, 32387, 32404, 32420, 32435, 32450, 32464, 32477,
228 32490, 32503, 32515, 32526, 32537, 32548, 32558, 32568,
229 32577, 32586, 32595, 32603, 32611, 32618, 32625, 32632,
230 32639, 32645, 32651, 32657, 32662, 32667, 32672, 32677,
232 32682, 32686, 32690, 32694, 32698, 32702, 32705, 32708,
233 32711, 32714, 32717, 32720, 32722, 32725, 32727, 32729,
234 32731, 32733, 32735, 32737, 32739, 32740, 32742, 32743,
235 32745, 32746, 32747, 32748, 32749, 32750, 32751, 32752,
236 32753, 32754, 32755, 32756, 32757, 32757, 32758, 32758,
237 32759, 32760, 32760, 32761, 32761, 32761, 32762, 32762,
238 32763, 32763, 32763, 32764, 32764, 32764, 32764, 32765,
239 32765, 32765, 32765, 32766, 32766, 32766, 32766, 32767,
245 * Generate a random integer number of NORMAL distribution
247 * The table above is used to generate a pseudo-normal distribution,
248 * in a manner which is much faster than calling a transcendental
249 * function to calculate a true normal distribution.
251 * Basically, entry 64*N in the table above represents the number of
252 * times out of 32767 that a random variable with normal distribution
253 * will fall within N standard deviations of the mean. That is, about
254 * 68 percent of the time for N=1 and 95 percent of the time for N=2.
256 * The table above contains a "faked" final entry which allows us to
257 * pretend that all values in a normal distribution are strictly less
258 * than four standard deviations away from the mean. This results in
259 * "conservative" distribution of approximately 1/32768 values.
261 * Note that the binary search takes up to 16 quick iterations.
263 s16b randnor(int mean, int stand)
269 s16b high = RANDNOR_NUM;
272 if (stand < 1) return (mean);
274 /* Roll for probability */
275 tmp = (s16b)randint0(32768);
280 int mid = (low + high) >> 1;
282 /* Move right if forced */
283 if (randnor_table[mid] < tmp)
288 /* Move left otherwise */
295 /* Convert the index into an offset */
296 offset = (long)stand * (long)low / RANDNOR_STD;
298 /* One half should be negative */
299 if (randint0(100) < 50) return (mean - offset);
301 /* One half should be positive */
302 return (mean + offset);
308 * Generates damage for "2d6" style dice rolls
310 s16b damroll(int num, int sides)
313 for (i = 0; i < num; i++) sum += randint1(sides);
319 * Same as above, but always maximal
321 s16b maxroll(int num, int sides)
323 return (num * sides);
328 * Given a numerator and a denominator, supply a properly rounded result,
329 * using the RNG to smooth out remainders. -LM-
331 s32b div_round(s32b n, s32b d)
335 /* Refuse to divide by zero */
342 if ((ABS(n) % ABS(d)) > randint0(ABS(d)))
344 /* Increase the absolute value */
345 if (n * d > 0L) tmp += 1L;
357 * Extract a "random" number from 0 to m-1, using the RNG.
359 * This function should be used when generating random numbers in
360 * "external" program parts like the main-*.c files. It preserves
361 * the current RNG state to prevent influences on game-play.
363 * Could also use rand() from <stdlib.h> directly. XXX XXX XXX
365 s32b Rand_external(s32b m)
367 static bool initialized = FALSE;
368 static u32b Rand_state_external[4];
372 /* Initialize with new seed */
373 u32b seed = time(NULL);
374 Rand_Xorshift_seed(seed, Rand_state_external);
378 return Rand_div_impl(m, Rand_state_external);