Imports the current Win32 source for the pod-racing game 'Red Planet', built on the MUNGA engine and its L4 (Win32/DirectX) platform layer: - MUNGA / MUNGA_L4: cross-platform engine core and Win32 backend - RP / RP_L4: Red Planet game logic and Win32 application - DivLoader, Setup1: asset loader and installer project - lib, MUNGA_L4/openal, MUNGA_L4/sos: third-party audio dependencies Removed stale Subversion metadata and added .gitignore/.gitattributes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
177 lines
4.6 KiB
C++
177 lines
4.6 KiB
C++
#include "munga.h"
|
|
#pragma hdrstop
|
|
|
|
#include "random.h"
|
|
|
|
int RandomGenerator::Numbers[250];
|
|
int RandomGenerator::Index = -1;
|
|
|
|
RandomGenerator Random;
|
|
|
|
//
|
|
//###########################################################################
|
|
//###########################################################################
|
|
//
|
|
void RandomGenerator::Init()
|
|
{
|
|
int i, msb, mask;
|
|
|
|
//
|
|
//--------------------------------------------------------------------
|
|
// After making sure the table is built only once, initialize the
|
|
// Borland C++ random numbers with the low word of the current time in
|
|
// milliseconds, and initialize the index pointer
|
|
//--------------------------------------------------------------------
|
|
//
|
|
char *seed_spec = getenv("RANDOM");
|
|
unsigned seed;
|
|
if (seed_spec)
|
|
{
|
|
seed = (unsigned)atol(seed_spec);
|
|
}
|
|
else
|
|
{
|
|
seed = (unsigned)time(NULL);
|
|
}
|
|
#if defined(TEST_CLASS)
|
|
cout << "Random Seed = " << seed << endl;
|
|
#endif
|
|
srand(seed);
|
|
Index = 0;
|
|
|
|
//
|
|
//------------------------------------------------------------------
|
|
// Load the random number buffer, then go thru and set the sign bit
|
|
// randomly, increasing the range of random numbers from 0..32767 to
|
|
// 0..65535
|
|
//------------------------------------------------------------------
|
|
//
|
|
for (i=0; i<250; i++)
|
|
{
|
|
Numbers[i] = rand();
|
|
}
|
|
|
|
//
|
|
//--------------------------------------------------------------------
|
|
// In order to preserve a good random number mix for the XOR function,
|
|
// mask and set the bits of 16 words in a descending manner as in
|
|
// 1xx..., 01xx..., 001xx..., 0001xx..., ...
|
|
//--------------------------------------------------------------------
|
|
//
|
|
mask = RAND_MAX >> 1;
|
|
msb = mask + 1;
|
|
int rand_size;
|
|
for (rand_size=0; !(msb&(1<<rand_size)); ++rand_size);
|
|
i = 14;
|
|
while (rand_size--)
|
|
{
|
|
Verify(i<ELEMENTS(Numbers));
|
|
Numbers[i] &= mask;
|
|
Numbers[i] |= msb;
|
|
mask >>= 1;
|
|
msb >>= 1;
|
|
i += 11;
|
|
}
|
|
}
|
|
|
|
//
|
|
//###########################################################################
|
|
//###########################################################################
|
|
//
|
|
int RandomGenerator::GetRandomInt()
|
|
{
|
|
int indent, result;
|
|
|
|
//
|
|
//------------------------------------------------------------------
|
|
// The random number generated will be the result of an XOR with the
|
|
// element 103 positions further (wrapping around) in the table
|
|
//------------------------------------------------------------------
|
|
//
|
|
indent = (Index>=147)?Index-147:Index+103;
|
|
result = Numbers[Index]^Numbers[indent];
|
|
|
|
//
|
|
//------------------------------------------------------------------------
|
|
// Replace the current random number with the new one generated, increment
|
|
// the buffer index pointer, and return the number
|
|
//------------------------------------------------------------------------
|
|
//
|
|
Numbers[Index] = result;
|
|
if (++Index == ELEMENTS(Numbers))
|
|
Index=0;
|
|
return result;
|
|
}
|
|
|
|
//
|
|
//###########################################################################
|
|
//###########################################################################
|
|
//
|
|
RandomGenerator::operator Scalar()
|
|
{
|
|
Scalar result;
|
|
|
|
result = GetRandomInt();
|
|
result /= (float)(RAND_MAX + 1);
|
|
return result;
|
|
}
|
|
|
|
//
|
|
//###########################################################################
|
|
//###########################################################################
|
|
//
|
|
int RandomGenerator::operator ()(int range)
|
|
{
|
|
int result, max;
|
|
|
|
max = RAND_MAX - ((RAND_MAX + 1)%range);
|
|
do
|
|
{
|
|
result = GetRandomInt();
|
|
} while (result>max);
|
|
return result%range;
|
|
}
|
|
|
|
//
|
|
//###########################################################################
|
|
//###########################################################################
|
|
//
|
|
Die::Die(int n)
|
|
{
|
|
dieSides = (n>1)?n:2;
|
|
highestRandom = RAND_MAX - ((RAND_MAX+1)%dieSides);
|
|
}
|
|
|
|
//
|
|
//###########################################################################
|
|
//###########################################################################
|
|
//
|
|
Die::operator int()
|
|
{
|
|
int result;
|
|
|
|
//
|
|
//------------------------------------------------------------------------
|
|
// In order to not skew the probabilities to the low numbers, make sure
|
|
// that the random # used is not greater than the limit determined for the
|
|
// number of sides.
|
|
//------------------------------------------------------------------------
|
|
//
|
|
do
|
|
{
|
|
result = Random.GetInt();
|
|
} while (result>highestRandom);
|
|
|
|
//
|
|
//-------------------------------------------------------------------
|
|
// Once the base random number is determined, do modulus division and
|
|
// increment by 1 to map into the die range.
|
|
//-------------------------------------------------------------------
|
|
//
|
|
return result % dieSides + 1;
|
|
}
|
|
|
|
#if defined(TEST_CLASS)
|
|
#include "random.tcp"
|
|
#endif
|