/* ** Command & Conquer Renegade(tm) ** Copyright 2025 Electronic Arts Inc. ** ** This program is free software: you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation, either version 3 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program. If not, see . */ /*********************************************************************************************** *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S *** *********************************************************************************************** * * * Project Name : Command & Conquer * * * * $Archive:: /VSS_Sync/wwlib/random.cpp $* * * * $Author:: Vss_sync $* * * * $Modtime:: 8/29/01 10:24p $* * * * $Revision:: 2 $* * * *---------------------------------------------------------------------------------------------* * Functions: * * RandomClass::RandomClass -- Constructor for the random number class. * * RandomClass::operator() -- Fetches the next random number in the sequence. * * RandomClass::operator() -- Ranged random number generator. * * Random2Class::Random2Class -- Constructor for the random class. * * Random2Class::operator -- Generates a random number between two values. * * Random2Class::operator -- Randomizer function that returns value. * * Random3Class::Random3Class -- Initializer for the random number generator. * * Random3Class::operator -- Generates a random number between two values. * * Random3Class::operator -- Random number generator function. * * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #include "always.h" #include "random.h" // Timing tests for random these random number generators in seconds for // 10000000 iterations. Testing done by Hector Yee, 6/20/01 // using DIEHARD and multidimensional Monte-Carlo Integration /* Time for Random=0.156000 Time for Random2=0.250000 Time for Random3=1.281000 Time for Random4=0.375000 Time for Built in Rand()=0.813000 Results from DIEHARD battery of tests A p-value of 0.0 or 1.0 means it fails. Anything inbetween is ok. R0 - FAILED almost all tests, didn't complete squeeze test R2 - Passed all tests, p-value 0.6 R3 - Failed 11 of 253 tests, p-value 1.0 R4 - Passed all tests, p-value 0.2588 Rand() - FAILED almost all tests, didn't complete squeeze test Results from Montecarlo Integration 2-96 dimensions R0 - starts breaking in 24 dimensions R2 - Ok, but will repeat with short period. Huge spike at 300000 samples in 64 dimensions R3 - Strong bias from 2 dimensions up R4 - Ok Rand() - starts breaking in 24 dimensions */ /*********************************************************************************************** * RandomClass::RandomClass -- Constructor for the random number class. * * * * This constructor can take an integer as a parameter. This allows the class to be * * constructed by assigning an integer to an existing object. The compiler creates a * * temporary with the constructor and then performs a copy constructor operation. * * * * INPUT: seed -- The optional starting seed value to use. * * * * OUTPUT: none * * * * WARNINGS: none * * * * HISTORY: * * 02/27/1996 JLB : Created. * *=============================================================================================*/ RandomClass::RandomClass(unsigned seed) : Seed(seed) { } /*********************************************************************************************** * RandomClass::operator() -- Fetches the next random number in the sequence. * * * * This routine will fetch the next random number in the sequence. * * * * INPUT: none * * * * OUTPUT: Returns with the next random number. * * * * WARNINGS: This routine modifies the seed value so that subsequent calls will not return * * the same value. Take note that this routine only returns 15 bits of * * random number. * * * * HISTORY: * * 02/27/1996 JLB : Created. * *=============================================================================================*/ int RandomClass::operator ()(void) { /* ** Transform the seed value into the next number in the sequence. */ Seed = (Seed * MULT_CONSTANT) + ADD_CONSTANT; /* ** Extract the 'random' bits from the seed and return that value as the ** random number result. */ return((Seed >> THROW_AWAY_BITS) & (~((~0) << SIGNIFICANT_BITS))); } /*********************************************************************************************** * RandomClass::operator() -- Ranged random number generator. * * * * This function will return with a random number within the range specified. This replaces * * the functionality of IRandom() in the old library. * * * * INPUT: minval -- The minimum value to return from the function. * * * * maxval -- The maximum value to return from the function. * * * * OUTPUT: Returns with a random number that falls between the minval and maxval (inclusive). * * * * WARNINGS: The range specified must fall within the maximum bit significance of the * * random number algorithm (15 bits), otherwise the value returned will be * * decidedly non-random. * * * * HISTORY: * * 02/27/1996 JLB : Created. * *=============================================================================================*/ int RandomClass::operator() (int minval, int maxval) { return(Pick_Random_Number(*this, minval, maxval)); } /*********************************************************************************************** * Random2Class::Random2Class -- Constructor for the random class. * * * * This will initialize the random class object with the seed value specified. * * * * INPUT: seed -- The seed value used to scramble the random number generator. * * * * OUTPUT: none * * * * WARNINGS: none * * * * HISTORY: * * 05/14/1997 JLB : Created. * *=============================================================================================*/ Random2Class::Random2Class(unsigned seed) : Index1(0), Index2(103) { Random3Class random(seed); for (int index = 0; index < ARRAY_SIZE(Table); index++) { Table[index] = random; } } /*********************************************************************************************** * Random2Class::operator -- Randomizer function that returns value. * * * * This is the random number generator function. It will generate a random number and * * return the value. * * * * INPUT: none * * * * OUTPUT: Returns with a random number. * * * * WARNINGS: none * * * * HISTORY: * * 05/20/1997 JLB : Created. * *=============================================================================================*/ int Random2Class::operator() (void) { Table[Index1] ^= Table[Index2]; int val = Table[Index1]; Index1++; Index2++; if (Index1 >= ARRAY_SIZE(Table)) Index1 = 0; if (Index2 >= ARRAY_SIZE(Table)) Index2 = 0; return(val); } /*********************************************************************************************** * Random2Class::operator -- Generates a random number between two values. * * * * This routine will generate a random number between the two values specified. It uses * * a method that will not bias the values in any way. * * * * INPUT: minval -- The minium return value (inclusive). * * * * maxval -- The maximum return value (inclusive). * * * * OUTPUT: Returns with a random number that falls between the two values (inclusive). * * * * WARNINGS: none * * * * HISTORY: * * 05/20/1997 JLB : Created. * *=============================================================================================*/ int Random2Class::operator() (int minval, int maxval) { return(Pick_Random_Number(*this, minval, maxval)); } /* ** This is the seed table for the Random3Class generator. These ensure ** that the algorithm is not vulnerable to being primed with a weak seed ** and thus prevents the algorithm from breaking down as a result. */ int Random3Class::Mix1[20] = { 0x0baa96887, 0x01e17d32c, 0x003bcdc3c, 0x00f33d1b2, 0x076a6491d, 0x0c570d85d, 0x0e382b1e3, 0x078db4362, 0x07439a9d4, 0x09cea8ac5, 0x089537c5c, 0x02588f55d, 0x0415b5e1d, 0x0216e3d95, 0x085c662e7, 0x05e8ab368, 0x03ea5cc8c, 0x0d26a0f74, 0x0f3a9222b, 0x048aad7e4 }; int Random3Class::Mix2[20] = { 0x04b0f3b58, 0x0e874f0c3, 0x06955c5a6, 0x055a7ca46, 0x04d9a9d86, 0x0fe28a195, 0x0b1ca7865, 0x06b235751, 0x09a997a61, 0x0aa6e95c8, 0x0aaa98ee1, 0x05af9154c, 0x0fc8e2263, 0x0390f5e8c, 0x058ffd802, 0x0ac0a5eba, 0x0ac4874f6, 0x0a9df0913, 0x086be4c74, 0x0ed2c123b }; /*********************************************************************************************** * Random3Class::Random3Class -- Initializer for the random number generator. * * * * This initializes the random number generator with the seed values specified. Due to a * * peculiarity of the random number design, the second seed value can be used to find the * * Nth random number generated by this algorithm. The second seed is used as the Nth index * * value. * * * * INPUT: seed1 -- The seed value to inialize the generator with. It is suggest that some * * random value based on user input seed this value. * * * * seed2 -- The auxiliary seed value. This adds randomness and thus allows this * * algorithm to use a 64 bit seed. This second seed also serves as an index * * into the algorithm such that the value passed as 'seed2' is will prime * * the generator to return that Nth random number when it is called. * * * * OUTPUT: none * * * * WARNINGS: As with all random number generators. Randomness is only as strong as the * * initial seed value. * * * * HISTORY: * * 05/20/1997 JLB : Created. * *=============================================================================================*/ Random3Class::Random3Class(unsigned seed1, unsigned seed2) : Seed(seed1), Index(seed2) { } /*********************************************************************************************** * Random3Class::operator -- Random number generator function. * * * * This routine generates a random number. The number returned is strongly random and is * * nearly good enough for cryptography. * * * * INPUT: none * * * * OUTPUT: Returns with a 32bit random number. * * * * WARNINGS: none * * * * HISTORY: * * 05/20/1997 JLB : Created. * *=============================================================================================*/ int Random3Class::operator() (void) { int loword = Seed; int hiword = Index++; for (int i = 0; i < 4; i++) { int hihold = hiword; int temp = hihold ^ Mix1[i]; int itmpl = temp & 0xffff; int itmph = temp >> 16; temp = itmpl * itmpl + ~(itmph * itmph); temp = (temp >> 16) | (temp << 16); hiword = loword ^ ((temp ^ Mix2[i]) + itmpl * itmph); loword = hihold; } return(hiword); } /*********************************************************************************************** * Random3Class::operator -- Generates a random number between two values. * * * * This routine will generate a random number between the two values specified. It uses * * a method that will not bias the values in any way. * * * * INPUT: minval -- The minium return value (inclusive). * * * * maxval -- The maximum return value (inclusive). * * * * OUTPUT: Returns with a random number that falls between the two values (inclusive). * * * * WARNINGS: none * * * * HISTORY: * * 05/20/1997 JLB : Created. * *=============================================================================================*/ int Random3Class::operator() (int minval, int maxval) { return(Pick_Random_Number(*this, minval, maxval)); } // Random4 // Hector Yee 6/11/01 /* Period parameters */ #define N 624 #define M 397 #define MATRIX_A 0x9908b0df /* constant vector a */ #define UPPER_MASK 0x80000000 /* most significant w-r bits */ #define LOWER_MASK 0x7fffffff /* least significant r bits */ /* Tempering parameters */ #define TEMPERING_MASK_B 0x9d2c5680 #define TEMPERING_MASK_C 0xefc60000 #define TEMPERING_SHIFT_U(y) (y >> 11) #define TEMPERING_SHIFT_S(y) (y << 7) #define TEMPERING_SHIFT_T(y) (y << 15) #define TEMPERING_SHIFT_L(y) (y >> 18) Random4Class::Random4Class(unsigned int seed) { /* setting initial seeds to mt[N] using */ /* the generator Line 25 of Table 1 in */ /* [KNUTH 1981, The Art of Computer Programming */ /* Vol. 2 (2nd Ed.), pp102] */ if (!seed) seed=4375; mt[0]= seed & 0xffffffff; for (mti=1; mti= N) { /* generate N words at one time */ int kk; for (kk=0;kk> 1) ^ mag01[y & 0x1]; } for (;kk> 1) ^ mag01[y & 0x1]; } y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK); mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1]; mti = 0; } y = mt[mti++]; y ^= TEMPERING_SHIFT_U(y); y ^= TEMPERING_SHIFT_S(y) & TEMPERING_MASK_B; y ^= TEMPERING_SHIFT_T(y) & TEMPERING_MASK_C; y ^= TEMPERING_SHIFT_L(y); int *x=(int *)&y; return *x; } int Random4Class::operator() (int minval, int maxval) { return(Pick_Random_Number(*this, minval, maxval)); } float Random4Class::Get_Float() { int x=(*this)(); unsigned int *y=(unsigned int *) &x; return (*y)*2.3283064370807973754314699618685e-10f; }