Angband
Macros | Functions | Variables
z-rand.c File Reference

A Random Number Generator for Angband. More...

#include "z-rand.h"

Macros

#define M1   3
 This file provides a pseudo-random number generator. More...
 
#define M2   24
 
#define M3   10
 
#define MAT0POS(t, v)   (v ^ (v >> t))
 
#define MAT0NEG(t, v)   (v ^ (v << (-(t))))
 
#define Identity(v)   (v)
 
#define V0   STATE[state_i]
 
#define VM1   STATE[(state_i + M1) & 0x0000001fU]
 
#define VM2   STATE[(state_i + M2) & 0x0000001fU]
 
#define VM3   STATE[(state_i + M3) & 0x0000001fU]
 
#define VRm1   STATE[(state_i + 31) & 0x0000001fU]
 
#define newV0   STATE[(state_i + 31) & 0x0000001fU]
 
#define newV1   STATE[state_i]
 
#define LCRNG(X)   ((X) * 1103515245 + 12345)
 Simple RNG, implemented with a linear congruent algorithm. More...
 
#define RANDNOR_NUM   256
 The number of entries in the "Rand_normal_table". More...
 
#define RANDNOR_STD   64
 The standard deviation of the "Rand_normal_table". More...
 

Functions

static u32b WELLRNG1024a (void)
 
void Rand_state_init (u32b seed)
 Initialize the complex RNG using a new seed. More...
 
void Rand_init (void)
 Initialise the RNG. More...
 
u32b Rand_div (u32b m)
 Extract a "random" number from 0 to m - 1, via division. More...
 
s16b Rand_normal (int mean, int stand)
 Generate a random integer number of NORMAL distribution. More...
 
int damroll (int num, int sides)
 Generates damage for "2d6" style dice rolls. More...
 
int damcalc (int num, int sides, aspect dam_aspect)
 Calculation helper function for damroll. More...
 
int rand_range (int A, int B)
 Generates a random signed long integer X where A <= X <= B. More...
 
static int simulate_division (int dividend, int divisor)
 Perform division, possibly rounding up or down depending on the size of the remainder and chance. More...
 
s16b m_bonus (int max, int level)
 Help determine an "enchantment bonus" for an object. More...
 
s16b m_bonus_calc (int max, int level, aspect bonus_aspect)
 Calculation helper function for m_bonus. More...
 
int randcalc (random_value v, int level, aspect rand_aspect)
 Calculation helper function for random_value structs. More...
 
bool randcalc_valid (random_value v, int test)
 Test to see if a value is within a random_value's range. More...
 
bool randcalc_varies (random_value v)
 Test to see if a random_value actually varies. More...
 
void rand_fix (u32b val)
 
int getpid (void)
 
u32b Rand_simple (u32b m)
 Another simple RNG that does not use any of the above state (so can be used without disturbing the game's RNG state) More...
 

Variables

u32b state_i = 0
 The state used by the "complex" RNG. More...
 
u32b STATE [RAND_DEG]
 
u32b z0
 
u32b z1
 
u32b z2
 
bool Rand_quick = true
 Whether to use the simple RNG or not. More...
 
u32b Rand_value
 The current "seed" of the simple RNG. More...
 
static bool rand_fixed = false
 
static u32b rand_fixval = 0
 
static s16b Rand_normal_table [RANDNOR_NUM]
 The normal distribution table for the "Rand_normal()" function (below) More...
 

Detailed Description

A Random Number Generator for Angband.

Copyright (c) 1997 Ben Harrison, Randy Hutson

See below for copyright on the WELL random number generator.

This work is free software; you can redistribute it and/or modify it under the terms of either:

a) the GNU General Public License as published by the Free Software Foundation, version 2, or

b) the "Angband licence": This software may be copied and distributed for educational, research, and not for profit purposes provided that this copyright and statement are included in all such copies. Other copyrights may also apply.

Macro Definition Documentation

#define Identity (   v)    (v)

Referenced by WELLRNG1024a().

#define LCRNG (   X)    ((X) * 1103515245 + 12345)

Simple RNG, implemented with a linear congruent algorithm.

Referenced by Rand_div(), Rand_simple(), and Rand_state_init().

#define M1   3

This file provides a pseudo-random number generator.

This code provides both a "quick" random number generator (4 bytes of state), and a "complex" random number generator (128 + 4 bytes of state).

The complex RNG (used for most game entropy) is provided by the WELL102a algorithm, used with permission. See below for copyright information about the WELL implementation.

To use of the "simple" RNG, activate it via "Rand_quick = true" and "Rand_value = seed". After that it will be automatically used instead of the "complex" RNG. When you are done, you can de-activate it via "Rand_quick = false". You can also choose a new seed.

#define M2   24
#define M3   10
#define MAT0NEG (   t,
 
)    (v ^ (v << (-(t))))

Referenced by WELLRNG1024a().

#define MAT0POS (   t,
 
)    (v ^ (v >> t))

Referenced by WELLRNG1024a().

#define newV0   STATE[(state_i + 31) & 0x0000001fU]

Referenced by WELLRNG1024a().

#define newV1   STATE[state_i]

Referenced by WELLRNG1024a().

#define RANDNOR_NUM   256

The number of entries in the "Rand_normal_table".

Referenced by Rand_normal().

#define RANDNOR_STD   64

The standard deviation of the "Rand_normal_table".

Referenced by Rand_normal().

#define V0   STATE[state_i]

Referenced by WELLRNG1024a().

#define VM1   STATE[(state_i + M1) & 0x0000001fU]

Referenced by WELLRNG1024a().

#define VM2   STATE[(state_i + M2) & 0x0000001fU]

Referenced by WELLRNG1024a().

#define VM3   STATE[(state_i + M3) & 0x0000001fU]

Referenced by WELLRNG1024a().

#define VRm1   STATE[(state_i + 31) & 0x0000001fU]

Referenced by WELLRNG1024a().

Function Documentation

int damcalc ( int  num,
int  sides,
aspect  dam_aspect 
)

Calculation helper function for damroll.

References AVERAGE, damroll(), EXTREMIFY, MAXIMISE, MINIMISE, num, and RANDOMISE.

Referenced by randcalc().

int damroll ( int  num,
int  sides 
)
int getpid ( void  )

Referenced by Rand_init(), and Rand_simple().

s16b m_bonus ( int  max,
int  level 
)

Help determine an "enchantment bonus" for an object.

Function used to determine enchantment bonuses, see function header for a more complete description.

To avoid floating point but still provide a smooth distribution of bonuses, we simply round the results of division in such a way as to "average" the correct floating point value.

This function has been changed. It uses "Rand_normal()" to choose values from a normal distribution, whose mean moves from zero towards the max as the level increases, and whose standard deviation is equal to 1/4 of the max, and whose values are forced to lie between zero and the max, inclusive.

Since the "level" rarely passes 100 before Morgoth is dead, it is very rare to get the "full" enchantment on an object, even a deep levels.

It is always possible (albeit unlikely) to get the "full" enchantment.

A sample distribution of values from "m_bonus(10, N)" is shown below:

N 0 1 2 3 4 5 6 7 8 9 10


0 66.37 13.01 9.73 5.47 2.89 1.31 0.72 0.26 0.12 0.09 0.03 8 46.85 24.66 12.13 8.13 4.20 2.30 1.05 0.36 0.19 0.08 0.05 16 30.12 27.62 18.52 10.52 6.34 3.52 1.95 0.90 0.31 0.15 0.05 24 22.44 15.62 30.14 12.92 8.55 5.30 2.39 1.63 0.62 0.28 0.11 32 16.23 11.43 23.01 22.31 11.19 7.18 4.46 2.13 1.20 0.45 0.41 40 10.76 8.91 12.80 29.51 16.00 9.69 5.90 3.43 1.47 0.88 0.65 48 7.28 6.81 10.51 18.27 27.57 11.76 7.85 4.99 2.80 1.22 0.94 56 4.41 4.73 8.52 11.96 24.94 19.78 11.06 7.18 3.68 1.96 1.78 64 2.81 3.07 5.65 9.17 13.01 31.57 13.70 9.30 6.04 3.04 2.64 72 1.87 1.99 3.68 7.15 10.56 20.24 25.78 12.17 7.52 4.42 4.62 80 1.02 1.23 2.78 4.75 8.37 12.04 27.61 18.07 10.28 6.52 7.33 88 0.70 0.57 1.56 3.12 6.34 10.06 15.76 30.46 12.58 8.47 10.38 96 0.27 0.60 1.25 2.28 4.30 7.60 10.77 22.52 22.51 11.37 16.53 104 0.22 0.42 0.77 1.36 2.62 5.33 8.93 13.05 29.54 15.23 22.53 112 0.15 0.20 0.56 0.87 2.00 3.83 6.86 10.06 17.89 27.31 30.27 120 0.03 0.11 0.31 0.46 1.31 2.48 4.60 7.78 11.67 25.53 45.72 128 0.02 0.01 0.13 0.33 0.83 1.41 3.24 6.17 9.57 14.22 64.07

References MAX_RAND_DEPTH, Rand_normal(), simulate_division(), and value.

Referenced by add_curse(), apply_curse(), apply_magic_armour(), apply_magic_weapon(), build_room_of_chambers(), do_cmd_lock_door(), effect_handler_CURSE_ARMOR(), effect_handler_CURSE_WEAPON(), and m_bonus_calc().

s16b m_bonus_calc ( int  max,
int  level,
aspect  bonus_aspect 
)

Calculation helper function for m_bonus.

References AVERAGE, EXTREMIFY, m_bonus(), MAX_RAND_DEPTH, MAXIMISE, MINIMISE, and RANDOMISE.

Referenced by randcalc().

u32b Rand_div ( u32b  m)

Extract a "random" number from 0 to m - 1, via division.

Generates a random unsigned long integer X where "0 <= X < M" holds.

This method selects "random" 28-bit numbers, and then uses division to drop those numbers into "m" different partitions, plus a small non-partition to reduce bias, taking as the final value the first "good" partition that a number falls into.

This method has no bias, and is much less affected by patterns in the "low" bits of the underlying RNG's. However, it is potentially non-terminating.

References LCRNG, rand_fixed, rand_fixval, Rand_quick, Rand_value, and WELLRNG1024a().

Referenced by rand_range().

void rand_fix ( u32b  val)

References rand_fixed, and rand_fixval.

Referenced by setup_tests().

void Rand_init ( void  )

Initialise the RNG.

References getpid(), NULL, Rand_quick, and Rand_state_init().

Referenced by init_angband().

s16b Rand_normal ( int  mean,
int  stand 
)

Generate a random integer number of NORMAL distribution.

Generate a signed random integer within stand standard deviations of mean, following a normal distribution.

The table above is used to generate a psuedo-normal distribution, in a manner which is much faster than calling a transcendental function to calculate a true normal distribution.

Basically, entry 64 * N in the table above represents the number of times out of 32767 that a random variable with normal distribution will fall within N standard deviations of the mean. That is, about 68 percent of the time for N=1 and 95 percent of the time for N=2.

The table above contains a "faked" final entry which allows us to pretend that all values in a normal distribution are strictly less than four standard deviations away from the mean. This results in "conservative" distribution of approximately 1/32768 values.

Note that the binary search takes up to 16 quick iterations.

References one_in_, Rand_normal_table, randint0, RANDNOR_NUM, and RANDNOR_STD.

Referenced by cavern_gen(), classic_gen(), gauntlet_gen(), get_ahw(), hard_centre_gen(), labyrinth_chunk(), labyrinth_gen(), lair_gen(), m_bonus(), modified_gen(), mon_hp(), moria_gen(), and set_pit_type().

int rand_range ( int  A,
int  B 
)

Generates a random signed long integer X where A <= X <= B.

Generates a random signed long integer X where "A <= X <= B" Note that "rand_range(0, N-1)" == "randint0(N)".

The integer X falls along a uniform distribution.

Note that "rand_range(0, N-1)" == "randint0(N)".

References Rand_div().

Referenced by build_crossed(), build_store(), cavern_chunk(), cavern_gen(), classic_gen(), gauntlet_gen(), hard_centre_gen(), lair_gen(), modified_gen(), mon_create_drop_count(), moria_gen(), player_outfit(), and store_create_random().

u32b Rand_simple ( u32b  m)

Another simple RNG that does not use any of the above state (so can be used without disturbing the game's RNG state)

Generate a semi-random number from 0 to m-1, in a way that doesn't affect gameplay.

References getpid(), LCRNG, and NULL.

Referenced by savefile_save().

void Rand_state_init ( u32b  seed)

Initialize the complex RNG using a new seed.

Initialise the RNG state with the given seed.

References i, LCRNG, RAND_DEG, STATE, and state_i.

Referenced by Rand_init().

int randcalc ( random_value  v,
int  level,
aspect  rand_aspect 
)
bool randcalc_valid ( random_value  v,
int  test 
)

Test to see if a value is within a random_value's range.

References MAXIMISE, MINIMISE, and randcalc().

bool randcalc_varies ( random_value  v)

Test to see if a random_value actually varies.

References MAXIMISE, MINIMISE, and randcalc().

Referenced by object_has_standard_to_h().

static int simulate_division ( int  dividend,
int  divisor 
)
static

Perform division, possibly rounding up or down depending on the size of the remainder and chance.

References randint0.

Referenced by m_bonus().

static u32b WELLRNG1024a ( void  )
static

References Identity, MAT0NEG, MAT0POS, newV0, newV1, STATE, state_i, V0, VM1, VM2, VM3, VRm1, z0, z1, and z2.

Referenced by Rand_div().

Variable Documentation

bool rand_fixed = false
static

Referenced by Rand_div(), and rand_fix().

u32b rand_fixval = 0
static

Referenced by Rand_div(), and rand_fix().

s16b Rand_normal_table[RANDNOR_NUM]
static

The normal distribution table for the "Rand_normal()" function (below)

Referenced by Rand_normal().

bool Rand_quick = true

Whether to use the simple RNG or not.

Whether we are currently using the "quick" method or not.

Referenced by do_randart(), flavor_init(), Rand_div(), Rand_init(), and rd_randomizer().

u32b Rand_value

The current "seed" of the simple RNG.

The state used by the "quick" RNG.

Referenced by do_randart(), flavor_init(), Rand_div(), rd_randomizer(), and wr_randomizer().

u32b STATE[RAND_DEG]
Initial value:
= {0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0}

Referenced by Rand_state_init(), rd_randomizer(), WELLRNG1024a(), and wr_randomizer().

u32b state_i = 0

The state used by the "complex" RNG.

Referenced by Rand_state_init(), rd_randomizer(), WELLRNG1024a(), and wr_randomizer().

u32b z0
u32b z1
u32b z2