Angband
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 Rand_sample (int mean, int upper, int lower, int stand_u, int stand_l)
Choose an integer from a distribution where we know the mean and approximate upper and lower bounds. 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:

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.

## ◆ Identity

 #define Identity ( v ) (v)

Referenced by WELLRNG1024a().

## ◆ LCRNG

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

Simple RNG, implemented with a linear congruent algorithm.

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

## ◆ M1

 #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.

## ◆ M2

 #define M2   24

## ◆ M3

 #define M3   10

## ◆ MAT0NEG

 #define MAT0NEG ( t, v ) (v ^ (v << (-(t))))

Referenced by WELLRNG1024a().

## ◆ MAT0POS

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

Referenced by WELLRNG1024a().

## ◆ newV0

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

Referenced by WELLRNG1024a().

## ◆ newV1

 #define newV1   STATE[state_i]

Referenced by WELLRNG1024a().

## ◆ RANDNOR_NUM

 #define RANDNOR_NUM   256

The number of entries in the "Rand_normal_table".

Referenced by Rand_normal().

## ◆ RANDNOR_STD

 #define RANDNOR_STD   64

The standard deviation of the "Rand_normal_table".

Referenced by Rand_normal().

## ◆ V0

 #define V0   STATE[state_i]

Referenced by WELLRNG1024a().

## ◆ VM1

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

Referenced by WELLRNG1024a().

## ◆ VM2

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

Referenced by WELLRNG1024a().

## ◆ VM3

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

Referenced by WELLRNG1024a().

## ◆ VRm1

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

Referenced by WELLRNG1024a().

## ◆ damcalc()

 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().

## ◆ damroll()

 int damroll ( int num, int sides )

Generates damage for "2d6" style dice rolls.

Emulate a number `num` of dice rolls of dice with `sides` sides.

References i, num, and randint1.

## ◆ getpid()

 int getpid ( void )

Referenced by rand_fix(), Rand_init(), and Rand_simple().

## ◆ m_bonus()

 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.

## ◆ 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().

## ◆ Rand_div()

 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().

## ◆ rand_fix()

 void rand_fix ( u32b val )

References getpid(), rand_fixed, and rand_fixval.

Referenced by setup_tests().

## ◆ Rand_init()

 void Rand_init ( void )

Initialise the RNG.

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

Referenced by init_angband().

## ◆ Rand_normal()

 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.

## ◆ rand_range()

 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().

## ◆ Rand_sample()

 int Rand_sample ( int mean, int upper, int lower, int stand_u, int stand_l )

Choose an integer from a distribution where we know the mean and approximate upper and lower bounds.

Generate a signed random integer following a normal distribution, where `upper` and `lower` are approximate bounds, and `stand_u and`stand_l` are ten times the number of standard deviations from the mean we are assuming the bounds are.

We divide the imagined distribution into two halves, above and below the mean, and then treat the bounds as if they are the given number of standard deviations from the mean in the appropriate direction. Note that `stand_u` and `stand_l` are 10 times the number of standart deviations we are asking for. The function chooses an integer from a normal distribution, and then scales it to fit the target distribution.

References mean(), and Rand_normal().

Referenced by design_artifact().

## ◆ Rand_simple()

 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(), and LCRNG.

Referenced by savefile_save().

## ◆ Rand_state_init()

 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().

## ◆ randcalc()

 int randcalc ( random_value v, int level, aspect rand_aspect )

Calculation helper function for random_value structs.

## ◆ randcalc_valid()

 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().

## ◆ randcalc_varies()

 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().

## ◆ simulate_division()

 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().

## ◆ WELLRNG1024a()

 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().

## ◆ rand_fixed

 bool rand_fixed = false
static

Referenced by Rand_div(), and rand_fix().

## ◆ rand_fixval

 u32b rand_fixval = 0
static

Referenced by Rand_div(), and rand_fix().

## ◆ Rand_normal_table

 s16b Rand_normal_table[RANDNOR_NUM]
static

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

Referenced by Rand_normal().

## ◆ Rand_quick

 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().

## ◆ Rand_value

 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(), randname_make(), rd_randomizer(), and wr_randomizer().

## ◆ STATE

 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().

## ◆ state_i

 u32b state_i = 0

The state used by the "complex" RNG.

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

## ◆ z0

 u32b z0

## ◆ z1

 u32b z1

## ◆ z2

 u32b z2