95 lines
2.8 KiB
C++
95 lines
2.8 KiB
C++
/*
|
|
This file is part of Warzone 2100.
|
|
Copyright (C) 1999-2004 Eidos Interactive
|
|
Copyright (C) 2005-2013 Warzone 2100 Project
|
|
|
|
Warzone 2100 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 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
Warzone 2100 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 Warzone 2100; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
#include "random.h"
|
|
#include "lib/netplay/netplay.h"
|
|
|
|
static MersenneTwister gamePseudorandomNumberGenerator;
|
|
|
|
MersenneTwister::MersenneTwister(uint32_t seed)
|
|
: offset(624)
|
|
{
|
|
// Set state to something pseudorandom. Exact constants aren't important here.
|
|
state[0] = seed;
|
|
for (unsigned i = 1; i != 624; ++i)
|
|
{
|
|
state[i] = 0x6C078965*(state[i - 1] ^ state[i - 1]>>30) + i;
|
|
}
|
|
}
|
|
|
|
uint32_t MersenneTwister::u32()
|
|
{
|
|
if (offset == 624)
|
|
{
|
|
generate();
|
|
}
|
|
|
|
uint32_t ret = state[offset++];
|
|
|
|
// Give better than 624 dimensional equidistribution for lower bits.
|
|
// Don't change the constants unless you know what you're doing.
|
|
// Can skip this step if it noticably affects performance (which it probably doesn't), since we aren't doing Monte-Carlo simulations.
|
|
ret ^= ret>>11;
|
|
ret ^= ret<<7 & 0x9D2C5680;
|
|
ret ^= ret<<15 & 0xEFC60000;
|
|
ret ^= ret>>18;
|
|
|
|
return ret;
|
|
}
|
|
|
|
void MersenneTwister::generate()
|
|
{
|
|
offset = 0;
|
|
|
|
// Don't change these constants, unless you have verified that the period is still 2**19937 - 1.
|
|
// Discards the lower 31 bits of state[0], since the state is 19937 = 624*32 - 31 bits.
|
|
// Loop tripled, to avoid using %624 everywhere.
|
|
for (unsigned i = 0; i != 227; ++i)
|
|
{
|
|
int v = (state[i]&0x80000000) | (state[i + 1 ]&0x7FFFFFFF);
|
|
state[i] = state[i + 397 ] ^ v>>1 ^ ((v&0x00000001)*0x9908B0DF);
|
|
}
|
|
for (unsigned i = 227; i != 623; ++i)
|
|
{
|
|
int v = (state[i]&0x80000000) | (state[i + 1 ]&0x7FFFFFFF);
|
|
state[i] = state[i + 397 - 624] ^ v>>1 ^ ((v&0x00000001)*0x9908B0DF);
|
|
}
|
|
for (unsigned i = 623; i != 624; ++i) // Very short loop.
|
|
{
|
|
int v = (state[i]&0x80000000) | (state[i + 1 - 624]&0x7FFFFFFF);
|
|
state[i] = state[i + 397 - 624] ^ v>>1 ^ ((v&0x00000001)*0x9908B0DF);
|
|
}
|
|
}
|
|
|
|
void gameSRand(uint32_t seed)
|
|
{
|
|
gamePseudorandomNumberGenerator = MersenneTwister(seed);
|
|
}
|
|
|
|
uint32_t gameRandU32()
|
|
{
|
|
return gamePseudorandomNumberGenerator.u32();
|
|
}
|
|
|
|
int32_t gameRand(uint32_t limit)
|
|
{
|
|
syncDebug("Used a random number.");
|
|
return gamePseudorandomNumberGenerator.u32()%limit;
|
|
}
|