/* ** 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.h $* * * * $Author:: Vss_sync $* * * * $Modtime:: 8/29/01 10:24p $* * * * $Revision:: 3 $* * * *---------------------------------------------------------------------------------------------* * Functions: * * Pick_Random_Number -- Picks a random number between two values (inclusive). * * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #if _MSC_VER >= 1000 #pragma once #endif // _MSC_VER >= 1000 #ifndef RANDOM_H #define RANDOM_H /* ** This class functions like a 'magic' int value that returns a random number ** every time it is read. To set the "random seed" for this, just assign a number ** to the object (just as you would if it were a true 'int' value). Take note that although ** this class will return an 'int', the actual significance of the random number is ** limited to 15 bits (0..32767). */ class RandomClass { public: RandomClass(unsigned seed=0); operator int(void) {return(operator()());}; int operator() (void); int operator() (int minval, int maxval); enum { SIGNIFICANT_BITS=15 // Random number bit significance. }; protected: unsigned long Seed; /* ** Internal working constants that are used to generate the next ** random number. */ enum { MULT_CONSTANT=0x41C64E6D, // K multiplier value. ADD_CONSTANT=0x00003039, // K additive value. THROW_AWAY_BITS=10 // Low bits to throw away. }; }; /* ** This class functions like a 'magic' number where it returns a different value every ** time it is read. It is nearly identical in function to the RandomClass, but has the ** following improvements. ** ** 1> It generates random numbers very quickly. No multiplies are ** used in the algorithm. ** ** 2> The return value is a full 32 bits rather than 15 bits of ** the RandomClass. ** ** 3> The bit pattern won't ever repeat. (actually it will repeat ** in about 10 to the 50th power times). */ // WARNING!!!! // This random number generator starts breaking down in 64 dimensions // behaving very badly in that domain // HY 6/14/01 class Random2Class { public: Random2Class(unsigned seed=0); operator int(void) {return(operator()());}; int operator() (void); int operator() (int minval, int maxval); enum { SIGNIFICANT_BITS=32 // Random number bit significance. }; protected: int Index1; int Index2; int Table[250]; }; /* ** This class functions like a 'magic' number where it returns a different value every ** time it is read. It is nearly identical in function to the RandomClass and Random2Class, ** but has the following improvements. ** ** 1> The random number returned is very strongly random. Approaching cryptographic ** quality. ** ** 2> The return value is a full 32 bits rather than 15 bits of ** the RandomClass. ** ** 3> The bit pattern won't repeat until 2^32 times. */ // WARNING!!!! // This random number generator starts breaking down in 3 dimensions // exhibiting a strange bias // HY 6/14/01 class Random3Class { public: Random3Class(unsigned seed1=0, unsigned seed2=0); operator int(void) {return(operator()());}; int operator() (void); int operator() (int minval, int maxval); enum { SIGNIFICANT_BITS=32 // Random number bit significance. }; protected: static int Mix1[20]; static int Mix2[20]; int Seed; int Index; }; /* ** This class functions like a 'magic' number where it returns a different value every ** time it is read. It is based on the paper "Mersenne Twister: A 623-Dimensionally ** Equidistributed Uniform Pseudo-Random Number Generator ** by Makoto Matsumoto and Takuji Nishimura, ACM Transactions on Modeling and ** Computer Simulation, Vol 8, No 1, January 1998, Pages 3-30 ** Hector Yee ** ** 1> The random number returned is very strongly random ** ** 2> The return value is a full 32 bits rather than 15 bits of ** the RandomClass. ** ** 3> The bit pattern won't repeat until 2^19937 -1 times ** */ // WARNING!!!! // Do not use for cryptography. This random number generator is good for numerical // simulation. Optimized, it's 4 times faster than rand() // http://www.math.keio.ac.jp/~matumoto/emt.html // HY 6/14/01 class Random4Class { public: Random4Class(unsigned int seed=4357); operator int(void) {return(operator()());}; int operator() (void); int operator() (int minval, int maxval); float Get_Float(); enum { SIGNIFICANT_BITS=32 // Random number bit significance. }; protected: unsigned int mt[624]; // state vector int mti; // index }; /*********************************************************************************************** * Pick_Random_Number -- Picks a random number between two values (inclusive). * * * * This is a utility template that works with one of the random number classes. Given a * * random number generator, this routine will return with a value that lies between the * * minimum and maximum values specified (subject to the bit precision limitations of the * * random number generator itself). * * * * INPUT: generator -- Reference to the random number generator to use for the pick * * process. * * * * minval -- The minimum legal return value (inclusive). * * * * maxval -- The maximum legal return value (inclusive). * * * * OUTPUT: Returns with a random number between the minval and maxval (inclusive). * * * * WARNINGS: none * * * * HISTORY: * * 05/23/1997 JLB : Created. * *=============================================================================================*/ template int Pick_Random_Number(T & generator, int minval, int maxval) { /* ** Test for shortcut case where the range is null and thus ** the number to return is actually implicit from the ** parameters. */ if (minval == maxval) return(minval); /* ** Ensure that the min and max range values are in proper order. */ if (minval > maxval) { int temp = minval; minval = maxval; maxval = temp; } /* ** Find the highest bit that fits within the magnitude of the ** range of random numbers desired. Notice that the scan is ** limited to the range of significant bits returned by the ** random number algorithm. */ int magnitude = maxval - minval; int highbit = T::SIGNIFICANT_BITS-1; while ((magnitude & (1 << highbit)) == 0 && highbit > 0) { highbit--; } /* ** Create a full bit mask pattern that has all bits set that just ** barely covers the magnitude of the number range desired. */ int mask = ~( (~0L) << (highbit+1)); /* ** Keep picking random numbers until it fits within the magnitude desired. With a ** good random number generator, it will have to perform this loop an average ** of one and a half times. */ int pick = magnitude+1; while (pick > magnitude) { pick = generator() & mask; } /* ** Finally, bias the random number pick to the start of the range ** requested. */ return(pick + minval); } #endif