/src/z-rand.c
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}