PageRenderTime 36ms CodeModel.GetById 15ms app.highlight 17ms RepoModel.GetById 1ms app.codeStats 0ms

/src/z-rand.c

https://bitbucket.org/ekolis/jackband
C | 589 lines | 258 code | 113 blank | 218 comment | 35 complexity | b9584478f1b37cc65b0db5926a38f721 MD5 | raw file
  1/*
  2 * File: z-rand.c
  3 * Purpose: A simple RNG for Angband
  4 *
  5 * Copyright (c) 1997 Ben Harrison, Randy Hutson
  6 *
  7 * This work is free software; you can redistribute it and/or modify it
  8 * under the terms of either:
  9 *
 10 * a) the GNU General Public License as published by the Free Software
 11 *    Foundation, version 2, or
 12 *
 13 * b) the "Angband licence":
 14 *    This software may be copied and distributed for educational, research,
 15 *    and not for profit purposes provided that this copyright and statement
 16 *    are included in all such copies.  Other copyrights may also apply.
 17 */
 18#include "z-rand.h"
 19
 20
 21
 22/*
 23 * This file provides an optimized random number generator.
 24 *
 25 *
 26 * This code provides both a "quick" random number generator (4 bytes of
 27 * state), and a "decent" random number generator (256 bytes of state),
 28 * both available in two flavors, first, the simple "mod" flavor, which
 29 * is fast, but slightly biased at high values, and second, the simple
 30 * "div" flavor, which is less fast (and potentially non-terminating)
 31 * but which is not biased and is much less subject to non-randomness
 32 * problems in the low bits.  Note the "randint0()" macro in "z-rand.h",
 33 * which must specify a "default" flavor.
 34 *
 35 * Note the use of the "simple" RNG, first you activate it via
 36 * "Rand_quick = TRUE" and "Rand_value = seed" and then it is used
 37 * automatically used instead of the "complex" RNG, and when you are
 38 * done, you de-activate it via "Rand_quick = FALSE" or choose a new
 39 * seed via "Rand_value = seed".
 40 *
 41 *
 42 * This (optimized) random number generator is based loosely on the old
 43 * "random.c" file from Berkeley but with some major optimizations and
 44 * algorithm changes.  See below for more details.
 45 */
 46
 47
 48
 49
 50/*
 51 * Random Number Generator -- Linear Congruent RNG
 52 */
 53#define LCRNG(X)        ((X) * 1103515245 + 12345)
 54
 55
 56
 57/*
 58 * Use the "simple" LCRNG
 59 */
 60bool Rand_quick = TRUE;
 61
 62
 63/*
 64 * Current "value" of the "simple" RNG
 65 */
 66u32b Rand_value;
 67
 68
 69/*
 70 * Current "index" for the "complex" RNG
 71 */
 72u16b Rand_place;
 73
 74/*
 75 * Current "state" table for the "complex" RNG
 76 */
 77u32b Rand_state[RAND_DEG];
 78
 79
 80
 81/*
 82 * Initialize the "complex" RNG using a new seed
 83 */
 84void Rand_state_init(u32b seed)
 85{
 86	int i, j;
 87
 88	/* Seed the table */
 89	Rand_state[0] = seed;
 90
 91	/* Propagate the seed */
 92	for (i = 1; i < RAND_DEG; i++) Rand_state[i] = LCRNG(Rand_state[i-1]);
 93
 94	/* Cycle the table ten times per degree */
 95	for (i = 0; i < RAND_DEG * 10; i++)
 96	{
 97		/* Acquire the next index */
 98		j = Rand_place + 1;
 99		if (j == RAND_DEG) j = 0;
100
101		/* Update the table, extract an entry */
102		Rand_state[j] += Rand_state[Rand_place];
103
104		/* Advance the index */
105		Rand_place = j;
106	}
107}
108
109
110/*
111 * Extract a "random" number from 0 to m-1, via "division"
112 *
113 * This method selects "random" 28-bit numbers, and then uses
114 * division to drop those numbers into "m" different partitions,
115 * plus a small non-partition to reduce bias, taking as the final
116 * value the first "good" partition that a number falls into.
117 *
118 * This method has no bias, and is much less affected by patterns
119 * in the "low" bits of the underlying RNG's.
120 */
121u32b Rand_div(u32b m)
122{
123	u32b r, n;
124
125	/* Division by zero will result if m is larger than 0x10000000 */
126	assert(m <= 0x10000000);
127
128	/* Hack -- simple case */
129	if (m <= 1) return (0);
130
131	/* Partition size */
132	n = (0x10000000 / m);
133
134	/* Use a simple RNG */
135	if (Rand_quick)
136	{
137		/* Wait for it */
138		while (1)
139		{
140			/* Cycle the generator */
141			r = (Rand_value = LCRNG(Rand_value));
142
143			/* Mutate a 28-bit "random" number */
144			r = ((r >> 4) & 0x0FFFFFFF) / n;
145
146			/* Done */
147			if (r < m) break;
148		}
149	}
150
151	/* Use a complex RNG */
152	else
153	{
154		/* Wait for it */
155		while (1)
156		{
157			int j;
158
159			/* Acquire the next index */
160			j = Rand_place + 1;
161			if (j == RAND_DEG) j = 0;
162
163			/* Update the table, extract an entry */
164			r = (Rand_state[j] += Rand_state[Rand_place]);
165
166			/* Hack -- extract a 28-bit "random" number */
167			r = ((r >> 4) & 0x0FFFFFFF) / n;
168
169			/* Advance the index */
170			Rand_place = j;
171
172			/* Done */
173			if (r < m) break;
174		}
175	}
176
177	/* Use the value */
178	return (r);
179}
180
181
182
183
184/*
185 * The number of entries in the "Rand_normal_table"
186 */
187#define RANDNOR_NUM	256
188
189/*
190 * The standard deviation of the "Rand_normal_table"
191 */
192#define RANDNOR_STD	64
193
194/*
195 * The normal distribution table for the "Rand_normal()" function (below)
196 */
197static s16b Rand_normal_table[RANDNOR_NUM] =
198{
199	206,     613,     1022,    1430,		1838,    2245,     2652,     3058,
200	3463,    3867,    4271,    4673,    5075,    5475,     5874,     6271,
201	6667,    7061,    7454,    7845,    8234,    8621,     9006,     9389,
202	9770,    10148,   10524,   10898,   11269,	11638,	 12004,	  12367,
203	12727,   13085,   13440,   13792,   14140,	14486,	 14828,	  15168,
204	15504,   15836,   16166,   16492,   16814,	17133,	 17449,	  17761,
205	18069,   18374,   18675,   18972,   19266,	19556,	 19842,	  20124,
206	20403,   20678,   20949,   21216,   21479,	21738,	 21994,	  22245,
207
208	22493,   22737,   22977,   23213,   23446,	23674,	 23899,	  24120,
209	24336,   24550,   24759,   24965,   25166,	25365,	 25559,	  25750,
210	25937,   26120,   26300,   26476,   26649,	26818,	 26983,	  27146,
211	27304,   27460,   27612,   27760,   27906,	28048,	 28187,	  28323,
212	28455,   28585,   28711,   28835,   28955,	29073,	 29188,	  29299,
213	29409,   29515,   29619,   29720,   29818,	29914,	 30007,	  30098,
214	30186,   30272,   30356,   30437,   30516,	30593,	 30668,	  30740,
215	30810,   30879,   30945,   31010,   31072,	31133,	 31192,	  31249,
216
217	31304,   31358,   31410,   31460,   31509,	31556,	 31601,	  31646,
218	31688,   31730,   31770,   31808,   31846,	31882,	 31917,	  31950,
219	31983,   32014,   32044,   32074,   32102,	32129,	 32155,	  32180,
220	32205,   32228,   32251,   32273,   32294,	32314,	 32333,	  32352,
221	32370,   32387,   32404,   32420,   32435,	32450,	 32464,	  32477,
222	32490,   32503,   32515,   32526,   32537,	32548,	 32558,	  32568,
223	32577,   32586,   32595,   32603,   32611,	32618,	 32625,	  32632,
224	32639,   32645,   32651,   32657,   32662,	32667,	 32672,	  32677,
225
226	32682,   32686,   32690,   32694,   32698,	32702,	 32705,	  32708,
227	32711,   32714,   32717,   32720,   32722,	32725,	 32727,	  32729,
228	32731,   32733,   32735,   32737,   32739,	32740,	 32742,	  32743,
229	32745,   32746,   32747,   32748,   32749,	32750,	 32751,	  32752,
230	32753,   32754,   32755,   32756,   32757,	32757,	 32758,	  32758,
231	32759,   32760,   32760,   32761,   32761,	32761,	 32762,	  32762,
232	32763,   32763,   32763,   32764,   32764,	32764,	 32764,	  32765,
233	32765,   32765,   32765,   32766,   32766,	32766,	 32766,	  32767,
234};
235
236
237
238/*
239 * Generate a random integer number of NORMAL distribution
240 *
241 * The table above is used to generate a psuedo-normal distribution,
242 * in a manner which is much faster than calling a transcendental
243 * function to calculate a true normal distribution.
244 *
245 * Basically, entry 64*N in the table above represents the number of
246 * times out of 32767 that a random variable with normal distribution
247 * will fall within N standard deviations of the mean.  That is, about
248 * 68 percent of the time for N=1 and 95 percent of the time for N=2.
249 *
250 * The table above contains a "faked" final entry which allows us to
251 * pretend that all values in a normal distribution are strictly less
252 * than four standard deviations away from the mean.  This results in
253 * "conservative" distribution of approximately 1/32768 values.
254 *
255 * Note that the binary search takes up to 16 quick iterations.
256 */
257s16b Rand_normal(int mean, int stand)
258{
259	s16b tmp;
260	s16b offset;
261
262	s16b low = 0;
263	s16b high = RANDNOR_NUM;
264
265	/* Paranoia */
266	if (stand < 1) return (mean);
267
268	/* Roll for probability */
269	tmp = (s16b)randint0(32768);
270
271	/* Binary Search */
272	while (low < high)
273	{
274		int mid = (low + high) >> 1;
275
276		/* Move right if forced */
277		if (Rand_normal_table[mid] < tmp)
278		{
279			low = mid + 1;
280		}
281
282		/* Move left otherwise */
283		else
284		{
285			high = mid;
286		}
287	}
288
289	/* Convert the index into an offset */
290	offset = (long)stand * (long)low / RANDNOR_STD;
291
292	/* One half should be negative */
293	if (randint0(100) < 50) return (mean - offset);
294
295	/* One half should be positive */
296	return (mean + offset);
297}
298
299
300/*
301 * Extract a "random" number from 0 to m-1, using the "simple" RNG.
302 *
303 * This function should be used when generating random numbers in
304 * "external" program parts like the main-*.c files.  It preserves
305 * the current RNG state to prevent influences on game-play.
306 */
307u32b Rand_simple(u32b m)
308{
309	static bool initialized = FALSE;
310	static u32b simple_rand_value;
311	bool old_rand_quick;
312	u32b old_rand_value;
313	u32b result;
314
315
316	/* Save RNG state */
317	old_rand_quick = Rand_quick;
318	old_rand_value = Rand_value;
319
320	/* Use "simple" RNG */
321	Rand_quick = TRUE;
322
323	if (initialized)
324	{
325		/* Use stored seed */
326		Rand_value = simple_rand_value;
327	}
328	else
329	{
330		/* Initialize with new seed */
331		Rand_value = time(NULL);
332		initialized = TRUE;
333	}
334
335	/* Get a random number */
336	result = randint0(m);
337
338	/* Store the new seed */
339	simple_rand_value = Rand_value;
340
341	/* Restore RNG state */
342	Rand_quick = old_rand_quick;
343	Rand_value = old_rand_value;
344
345	/* Use the value */
346	return (result);
347}
348
349
350
351/*
352 * Generates damage for "2d6" style dice rolls
353 */
354int damroll(int num, int sides)
355{
356	int i;
357	int sum = 0;
358
359/*	assert(sides > 0); */
360	if (sides <= 0) return (0);
361
362	for (i = 0; i < num; i++)
363		sum += randint1(sides);
364
365	return (sum);
366}
367
368
369
370/*
371 * Calculation helper function for damroll
372 */
373int damcalc(int num, int sides, aspect dam_aspect)
374{
375	int val = 0;
376
377	switch (dam_aspect)
378	{
379		case MAXIMISE:
380		case EXTREMIFY:
381		{
382			val = num * sides;
383			break;
384		}
385		case RANDOMISE:
386		{
387			val = damroll(num, sides);
388			break;
389		}
390		case MINIMISE:
391		{
392			val = num;
393			break;
394		}
395		case AVERAGE:
396		{
397			val = num * (sides + 1) / 2;
398			break;
399		}
400	}
401
402	return (val);
403}
404
405
406
407/**
408 * Generates a random signed long integer X where `A` <= X <= `B`.
409 * The integer X falls along a uniform distribution.
410 *
411 * Note that "rand_range(0, N-1)" == "randint0(N)".
412 */
413int rand_range(int A, int B)
414{
415	if (A == B) return A;
416	assert(A < B);
417
418	return A + (s32b)Rand_div(1 + B - A);
419}
420
421/*
422 * Help determine an "enchantment bonus" for an object.
423 *
424 * To avoid floating point but still provide a smooth distribution of bonuses,
425 * we simply round the results of division in such a way as to "average" the
426 * correct floating point value.
427 *
428 * This function has been changed.  It uses "Rand_normal()" to choose values
429 * from a normal distribution, whose mean moves from zero towards the max as
430 * the level increases, and whose standard deviation is equal to 1/4 of the
431 * max, and whose values are forced to lie between zero and the max, inclusive.
432 *
433 * Since the "level" rarely passes 100 before Morgoth is dead, it is very
434 * rare to get the "full" enchantment on an object, even a deep levels.
435 *
436 * It is always possible (albeit unlikely) to get the "full" enchantment.
437 *
438 * A sample distribution of values from "m_bonus(10, N)" is shown below:
439 *
440 *   N       0     1     2     3     4     5     6     7     8     9    10
441 * ---    ----  ----  ----  ----  ----  ----  ----  ----  ----  ----  ----
442 *   0   66.37 13.01  9.73  5.47  2.89  1.31  0.72  0.26  0.12  0.09  0.03
443 *   8   46.85 24.66 12.13  8.13  4.20  2.30  1.05  0.36  0.19  0.08  0.05
444 *  16   30.12 27.62 18.52 10.52  6.34  3.52  1.95  0.90  0.31  0.15  0.05
445 *  24   22.44 15.62 30.14 12.92  8.55  5.30  2.39  1.63  0.62  0.28  0.11
446 *  32   16.23 11.43 23.01 22.31 11.19  7.18  4.46  2.13  1.20  0.45  0.41
447 *  40   10.76  8.91 12.80 29.51 16.00  9.69  5.90  3.43  1.47  0.88  0.65
448 *  48    7.28  6.81 10.51 18.27 27.57 11.76  7.85  4.99  2.80  1.22  0.94
449 *  56    4.41  4.73  8.52 11.96 24.94 19.78 11.06  7.18  3.68  1.96  1.78
450 *  64    2.81  3.07  5.65  9.17 13.01 31.57 13.70  9.30  6.04  3.04  2.64
451 *  72    1.87  1.99  3.68  7.15 10.56 20.24 25.78 12.17  7.52  4.42  4.62
452 *  80    1.02  1.23  2.78  4.75  8.37 12.04 27.61 18.07 10.28  6.52  7.33
453 *  88    0.70  0.57  1.56  3.12  6.34 10.06 15.76 30.46 12.58  8.47 10.38
454 *  96    0.27  0.60  1.25  2.28  4.30  7.60 10.77 22.52 22.51 11.37 16.53
455 * 104    0.22  0.42  0.77  1.36  2.62  5.33  8.93 13.05 29.54 15.23 22.53
456 * 112    0.15  0.20  0.56  0.87  2.00  3.83  6.86 10.06 17.89 27.31 30.27
457 * 120    0.03  0.11  0.31  0.46  1.31  2.48  4.60  7.78 11.67 25.53 45.72
458 * 128    0.02  0.01  0.13  0.33  0.83  1.41  3.24  6.17  9.57 14.22 64.07
459 */
460s16b m_bonus(int max, int level)
461{
462	int bonus, stand, extra, value;
463
464
465	/* Paranoia -- enforce maximal "level" */
466	if (level > MAX_DEPTH - 1) level = MAX_DEPTH - 1;
467
468
469	/* The "bonus" moves towards the max */
470	bonus = ((max * level) / MAX_DEPTH);
471
472	/* Hack -- determine fraction of error */
473	extra = ((max * level) % MAX_DEPTH);
474
475	/* Hack -- simulate floating point computations */
476	if (randint0(MAX_DEPTH) < extra) bonus++;
477
478
479	/* The "stand" is equal to one quarter of the max */
480	stand = (max / 4);
481
482	/* Hack -- determine fraction of error */
483	extra = (max % 4);
484
485	/* Hack -- simulate floating point computations */
486	if (randint0(4) < extra) stand++;
487
488
489	/* Choose an "interesting" value */
490	value = Rand_normal(bonus, stand);
491
492	/* Enforce the minimum value */
493	if (value < 0) return (0);
494
495	/* Enforce the maximum value */
496	if (value > max) return (max);
497
498	/* Result */
499	return (value);
500}
501
502/*
503 * Calculation helper function for m_bonus
504 */
505s16b m_bonus_calc(int max, int level, aspect bonus_aspect)
506{
507	int val = 0;
508
509	switch (bonus_aspect)
510	{
511		case EXTREMIFY:
512		case MAXIMISE:
513		{
514			val = max;
515			break;
516		}
517		case RANDOMISE:
518		{
519			val = m_bonus(max, level);
520			break;
521		}
522		case MINIMISE:
523		{
524			val = 0;
525			break;
526		}
527		case AVERAGE:
528		{
529			val = max * level / MAX_DEPTH;
530			break;
531		}
532	}
533
534	return (val);
535}
536
537/*
538 * Calculation helper function for random_value structs
539 */
540int randcalc(random_value v, int level, aspect rand_aspect)
541{
542	int total;
543	
544	if (rand_aspect == EXTREMIFY)
545	{
546		int min, max;
547		
548		min = randcalc(v, level, MINIMISE);
549		max = randcalc(v, level, MAXIMISE);
550		
551		if (abs(min) > abs(max))
552			total = min;
553		else
554			total = max;
555	}
556	else
557	{
558		total = v.base +
559		        damcalc(v.dice, v.sides, rand_aspect) +
560		        m_bonus_calc(v.m_bonus, level, rand_aspect);
561	}
562
563	return total;
564}
565
566/*
567 * Test to see if a value is within a random_value's range
568 */
569bool randcalc_valid(random_value v, int test)
570{
571	if (test < randcalc(v, 0, MINIMISE))
572		return FALSE;
573
574	if (test > randcalc(v, 0, MAXIMISE))
575		return FALSE;
576
577	return TRUE;
578}
579
580/*
581 * Test to see if a random_value actually varies
582 */
583bool randcalc_varies(random_value v)
584{
585	if (randcalc(v, 0, MINIMISE) == randcalc(v, 0, MAXIMISE))
586		return FALSE;
587
588	return TRUE;
589}