summaryrefslogtreecommitdiff
path: root/common/GameUI/Random.cpp
blob: ec179868c4aee7e995d50af6e0fa1565f82137ed (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Basic random number generator
//
// $NoKeywords: $
//===========================================================================//


#include <time.h>
#include "Random.h"

// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"

#define IA 16807
#define IM 2147483647
#define IQ 127773
#define IR 2836
#define NTAB 32
#define NDIV (1+(IM-1)/NTAB)

static long idum = 0;

void SeedRandomNumberGenerator(long lSeed)
{
	if (lSeed)
	{
		idum = lSeed;
	}
	else
	{
		idum = -time(NULL);
	}
	if (1000 < idum)
	{
		idum = -idum;
	}
	else if (-1000 < idum)
	{
		idum -= 22261048;
	}
}

long ran1(void)
{
	int j;
	long k;
	static long iy=0;
	static long iv[NTAB];
	
	if (idum <= 0 || !iy)
	{
		if (-(idum) < 1) idum=1;
		else idum = -(idum);
		for (j=NTAB+7;j>=0;j--)
		{
			k=(idum)/IQ;
			idum=IA*(idum-k*IQ)-IR*k;
			if (idum < 0) idum += IM;
			if (j < NTAB) iv[j] = idum;
		}
		iy=iv[0];
	}
	k=(idum)/IQ;
	idum=IA*(idum-k*IQ)-IR*k;
	if (idum < 0) idum += IM;
	j=iy/NDIV;
	iy=iv[j];
	iv[j] = idum;

	return iy;
}

// fran1 -- return a random floating-point number on the interval [0,1)
//
#define AM (1.0/IM)
#define EPS 1.2e-7
#define RNMX (1.0-EPS)
float fran1(void)
{
	float temp = (float)AM*ran1();
	if (temp > RNMX) return (float)RNMX;
	else return temp;
}

#ifndef _XBOX
float RandomFloat( float flLow, float flHigh )
{
	if (idum == 0)
	{
		SeedRandomNumberGenerator(0);
	}

	float fl = fran1(); // float in [0,1)
	return (fl * (flHigh-flLow)) + flLow; // float in [low,high)
}
#endif

long RandomLong( long lLow, long lHigh )
{
	if (idum == 0)
	{
		SeedRandomNumberGenerator(0);
	}

	unsigned long maxAcceptable;
	unsigned long x = lHigh-lLow+1;
	unsigned long n;
	if (x <= 0 || MAX_RANDOM_RANGE < x-1)
	{
		return lLow;
	}

	// The following maps a uniform distribution on the interval [0,MAX_RANDOM_RANGE]
	// to a smaller, client-specified range of [0,x-1] in a way that doesn't bias
	// the uniform distribution unfavorably. Even for a worst case x, the loop is
	// guaranteed to be taken no more than half the time, so for that worst case x,
	// the average number of times through the loop is 2. For cases where x is
	// much smaller than MAX_RANDOM_RANGE, the average number of times through the
	// loop is very close to 1.
	//
	maxAcceptable = MAX_RANDOM_RANGE - ((MAX_RANDOM_RANGE+1) % x );
	do
	{
		n = ran1();
	} while (n > maxAcceptable);

	return lLow + (n % x);
}