Files
RP412/MUNGA/RANDOM.cpp
T
CydandClaude Opus 4.8 4abbf8879f Initial import of Red Planet v4.10 Win32 source
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>
2026-06-30 07:59:51 -05:00

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