RANDOM.CPP (9815B)
1 // 2 // Copyright 2020 Electronic Arts Inc. 3 // 4 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free 5 // software: you can redistribute it and/or modify it under the terms of 6 // the GNU General Public License as published by the Free Software Foundation, 7 // either version 3 of the License, or (at your option) any later version. 8 9 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed 10 // in the hope that it will be useful, but with permitted additional restrictions 11 // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT 12 // distributed with this program. You should have received a copy of the 13 // GNU General Public License along with permitted additional restrictions 14 // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection 15 16 /* $Header: /CounterStrike/RANDOM.CPP 1 3/03/97 10:25a Joe_bostic $ */ 17 /*********************************************************************************************** 18 *** 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 *** 19 *********************************************************************************************** 20 * * 21 * Project Name : Command & Conquer * 22 * * 23 * File Name : RAND.CPP * 24 * * 25 * Programmer : Joe L. Bostic * 26 * * 27 * Start Date : 02/28/96 * 28 * * 29 * Last Update : February 28, 1996 [JLB] * 30 * * 31 *---------------------------------------------------------------------------------------------* 32 * Functions: * 33 * RandomClass::RandomClass -- Constructor for the random number class. * 34 * RandomClass::operator() -- Fetches the next random number in the sequence. * 35 * RandomClass::operator() -- Ranged random number generator. * 36 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 37 38 #include "random.h" 39 #ifdef RANDOM_COUNT 40 #include <stdio.h> 41 extern long Frame; 42 #endif 43 44 /*********************************************************************************************** 45 * RandomClass::RandomClass -- Constructor for the random number class. * 46 * * 47 * This constructor can take an integer as a parameter. This allows the class to be * 48 * constructed by assigning an integer to an existing object. The compiler creates a * 49 * temporary with the constructor and then performs a copy constructor operation. * 50 * * 51 * INPUT: seed -- The optional starting seed value to use. * 52 * * 53 * OUTPUT: none * 54 * * 55 * WARNINGS: none * 56 * * 57 * HISTORY: * 58 * 02/27/1996 JLB : Created. * 59 *=============================================================================================*/ 60 RandomClass::RandomClass(unsigned seed) : 61 Seed(seed) 62 { 63 #ifdef RANDOM_COUNT 64 Count1 = 0; 65 Count2 = 0; 66 #endif 67 } 68 69 70 /*********************************************************************************************** 71 * RandomClass::operator() -- Fetches the next random number in the sequence. * 72 * * 73 * This routine will fetch the next random number in the sequence. * 74 * * 75 * INPUT: none * 76 * * 77 * OUTPUT: Returns with the next random number. * 78 * * 79 * WARNINGS: This routine modifies the seed value so that subsequent calls will not return * 80 * the same value. Take note that this routine only returns 15 bits of * 81 * random number. * 82 * * 83 * HISTORY: * 84 * 02/27/1996 JLB : Created. * 85 *=============================================================================================*/ 86 int RandomClass::operator ()(void) 87 { 88 #ifdef RANDOM_COUNT 89 Count1++; 90 printf("Frame %d: Random Count1:%d Count2:%d (%x)\n",Frame,Count1,Count2,Seed); 91 #endif 92 93 /* 94 ** Transform the seed value into the next number in the sequence. 95 */ 96 Seed = (Seed * MULT_CONSTANT) + ADD_CONSTANT; 97 98 /* 99 ** Extract the 'random' bits from the seed and return that value as the 100 ** random number result. 101 */ 102 return((Seed >> THROW_AWAY_BITS) & (~((~0) << SIGNIFICANT_BITS))); 103 } 104 105 106 /*********************************************************************************************** 107 * RandomClass::operator() -- Ranged random number generator. * 108 * * 109 * This function will return with a random number within the range specified. This replaces * 110 * the functionality of IRandom() in the old library. * 111 * * 112 * INPUT: minval -- The minimum value to return from the function. * 113 * * 114 * maxval -- The maximum value to return from the function. * 115 * * 116 * OUTPUT: Returns with a random number that falls between the minval and maxval (inclusive). * 117 * * 118 * WARNINGS: The range specified must fall within the maximum bit significance of the * 119 * random number algorithm (15 bits), otherwise the value returned will be * 120 * decidedly non-random. * 121 * * 122 * HISTORY: * 123 * 02/27/1996 JLB : Created. * 124 *=============================================================================================*/ 125 int RandomClass::operator() (int minval, int maxval) 126 { 127 #ifdef RANDOM_COUNT 128 Count2++; 129 printf("Frame %d: Random Count1:%d Count2:%d (%x)\n",Frame,Count1,Count2,Seed); 130 #endif 131 132 /* 133 ** Test for shortcut case where the range is null and thus 134 ** the number to return is actually implicit from the 135 ** parameters. 136 */ 137 if (minval == maxval) return(minval); 138 139 /* 140 ** Ensure that the min and max range values are in proper order. 141 */ 142 if (minval > maxval) { 143 int temp = minval; 144 minval = maxval; 145 maxval = temp; 146 } 147 148 /* 149 ** Find the highest bit that fits within the magnitude of the 150 ** range of random numbers desired. Notice that the scan is 151 ** limited to the range of significant bits returned by the 152 ** random number algorithm. 153 */ 154 int magnitude = maxval - minval; 155 int highbit = SIGNIFICANT_BITS-1; 156 while ((magnitude & (1 << highbit)) == 0 && highbit > 0) { 157 highbit--; 158 } 159 160 /* 161 ** Create a full bit mask pattern that has all bits set that just 162 ** barely covers the magnitude of the number range desired. 163 */ 164 int mask = ~( (~0L) << (highbit+1) ); 165 166 /* 167 ** Keep picking random numbers until it fits within the magnitude desired. 168 */ 169 int pick = magnitude+1; 170 while (pick > magnitude) { 171 pick = operator()() & mask; 172 } 173 174 /* 175 ** Finally, bias the random number pick to the start of the range 176 ** requested. 177 */ 178 return(pick + minval); 179 } 180