mirror of
https://github.com/EQEmu/Server.git
synced 2026-05-16 18:52:22 +00:00
Switch random function to std::mt19937
Added class EQEmu::Random Functions: EQEmu::Random::Int(int low, int high) EQEmu::Random::Real(double low, double high) EQEmu::Random::Roll(int required) EQEmu::Random::Roll(double required) EQEmu::Random::Reseed() For zone, you will access the random object through the zone object ex. zone->random.Int(0, 100); Int returns a random int between low and high Real returns a random double between low and high Roll(int) returns true if Int(0, 99) < required is true Roll(double) returns true if Real(0.0, 1.0) <= required is true
This commit is contained in:
@@ -168,6 +168,7 @@ SET(common_headers
|
||||
ptimer.h
|
||||
queue.h
|
||||
races.h
|
||||
random.h
|
||||
rdtsc.h
|
||||
rulesys.h
|
||||
ruletypes.h
|
||||
|
||||
@@ -54,20 +54,6 @@
|
||||
#include <errno.h>
|
||||
#endif
|
||||
|
||||
static bool WELLRNG_init = false;
|
||||
static int state_i = 0;
|
||||
static unsigned int STATE[R];
|
||||
static unsigned int z0, z1, z2;
|
||||
unsigned int (*WELLRNG19937)(void);
|
||||
static unsigned int case_1 (void);
|
||||
static unsigned int case_2 (void);
|
||||
static unsigned int case_3 (void);
|
||||
static unsigned int case_4 (void);
|
||||
static unsigned int case_5 (void);
|
||||
static unsigned int case_6 (void);
|
||||
uint32 rnd_hash(time_t t, clock_t c);
|
||||
void oneseed(const uint32 seed);
|
||||
|
||||
void CoutTimestamp(bool ms) {
|
||||
time_t rawtime;
|
||||
struct tm* gmt_t;
|
||||
@@ -179,41 +165,6 @@ const char * itoa(int num, char* a,int b) {
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* generate a random integer in the range low-high this
|
||||
* should be used instead of the rand()%limit method
|
||||
*/
|
||||
int MakeRandomInt(int low, int high)
|
||||
{
|
||||
if(low >= high)
|
||||
return(low);
|
||||
|
||||
//return (rand()%(high-low+1) + (low));
|
||||
if(!WELLRNG_init) {
|
||||
WELLRNG_init = true;
|
||||
oneseed( rnd_hash( time(nullptr), clock() ) );
|
||||
WELLRNG19937 = case_1;
|
||||
}
|
||||
unsigned int randomnum = ((WELLRNG19937)());
|
||||
if(randomnum == 0xffffffffUL)
|
||||
return high;
|
||||
return int ((randomnum / (double)0xffffffffUL) * (high - low + 1) + low);
|
||||
}
|
||||
|
||||
double MakeRandomFloat(double low, double high)
|
||||
{
|
||||
if(low >= high)
|
||||
return(low);
|
||||
|
||||
//return (rand() / (double)RAND_MAX * (high - low) + low);
|
||||
if(!WELLRNG_init) {
|
||||
WELLRNG_init = true;
|
||||
oneseed( rnd_hash( time(nullptr), clock() ) );
|
||||
WELLRNG19937 = case_1;
|
||||
}
|
||||
return ((WELLRNG19937)() / (double)0xffffffffUL * (high - low) + low);
|
||||
}
|
||||
|
||||
uint32 rnd_hash( time_t t, clock_t c )
|
||||
{
|
||||
// Get a uint32 from t and c
|
||||
@@ -239,111 +190,6 @@ uint32 rnd_hash( time_t t, clock_t c )
|
||||
return ( h1 + differ++ ) ^ h2;
|
||||
}
|
||||
|
||||
void oneseed( const uint32 seed )
|
||||
{
|
||||
// Initialize generator state with seed
|
||||
// See Knuth TAOCP Vol 2, 3rd Ed, p.106 for multiplier.
|
||||
// In previous versions, most significant bits (MSBs) of the seed affect
|
||||
// only MSBs of the state array. Modified 9 Jan 2002 by Makoto Matsumoto.
|
||||
register int j = 0;
|
||||
STATE[j] = seed & 0xffffffffUL;
|
||||
for (j = 1; j < R; j++)
|
||||
{
|
||||
STATE[j] = ( 1812433253UL * ( STATE[j-1] ^ (STATE[j-1] >> 30) ) + j ) & 0xffffffffUL;
|
||||
}
|
||||
}
|
||||
|
||||
// WELL RNG code
|
||||
|
||||
/* ***************************************************************************** */
|
||||
/* Copyright: Francois Panneton and Pierre L'Ecuyer, University of Montreal */
|
||||
/* Makoto Matsumoto, Hiroshima University */
|
||||
/* Notice: This code can be used freely for personal, academic, */
|
||||
/* or non-commercial purposes. For commercial purposes, */
|
||||
/* please contact P. L'Ecuyer at: lecuyer@iro.UMontreal.ca */
|
||||
/* A modified "maximally equidistributed" implementation */
|
||||
/* by Shin Harase, Hiroshima University. */
|
||||
/* ***************************************************************************** */
|
||||
|
||||
unsigned int case_1 (void){
|
||||
// state_i == 0
|
||||
z0 = (VRm1Under & MASKL) | (VRm2Under & MASKU);
|
||||
z1 = MAT0NEG (-25, V0) ^ MAT0POS (27, VM1);
|
||||
z2 = MAT3POS (9, VM2) ^ MAT0POS (1, VM3);
|
||||
newV1 = z1 ^ z2;
|
||||
newV0Under = MAT1 (z0) ^ MAT0NEG (-9, z1) ^ MAT0NEG (-21, z2) ^ MAT0POS (21, newV1);
|
||||
state_i = R - 1;
|
||||
WELLRNG19937 = case_3;
|
||||
return (STATE[state_i] ^ (newVM2Over & BITMASK));
|
||||
}
|
||||
|
||||
static unsigned int case_2 (void){
|
||||
// state_i == 1
|
||||
z0 = (VRm1 & MASKL) | (VRm2Under & MASKU);
|
||||
z1 = MAT0NEG (-25, V0) ^ MAT0POS (27, VM1);
|
||||
z2 = MAT3POS (9, VM2) ^ MAT0POS (1, VM3);
|
||||
newV1 = z1 ^ z2;
|
||||
newV0 = MAT1 (z0) ^ MAT0NEG (-9, z1) ^ MAT0NEG (-21, z2) ^ MAT0POS (21, newV1);
|
||||
state_i = 0;
|
||||
WELLRNG19937 = case_1;
|
||||
return (STATE[state_i] ^ (newVM2 & BITMASK));
|
||||
}
|
||||
|
||||
static unsigned int case_3 (void){
|
||||
// state_i+M1 >= R
|
||||
z0 = (VRm1 & MASKL) | (VRm2 & MASKU);
|
||||
z1 = MAT0NEG (-25, V0) ^ MAT0POS (27, VM1Over);
|
||||
z2 = MAT3POS (9, VM2Over) ^ MAT0POS (1, VM3Over);
|
||||
newV1 = z1 ^ z2;
|
||||
newV0 = MAT1 (z0) ^ MAT0NEG (-9, z1) ^ MAT0NEG (-21, z2) ^ MAT0POS (21, newV1);
|
||||
state_i--;
|
||||
if (state_i + M1 < R)
|
||||
WELLRNG19937 = case_5;
|
||||
return (STATE[state_i] ^ (newVM2Over & BITMASK));
|
||||
}
|
||||
|
||||
static unsigned int case_4 (void){
|
||||
// state_i+M3 >= R
|
||||
z0 = (VRm1 & MASKL) | (VRm2 & MASKU);
|
||||
z1 = MAT0NEG (-25, V0) ^ MAT0POS (27, VM1);
|
||||
z2 = MAT3POS (9, VM2) ^ MAT0POS (1, VM3Over);
|
||||
newV1 = z1 ^ z2;
|
||||
newV0 = MAT1 (z0) ^ MAT0NEG (-9, z1) ^ MAT0NEG (-21, z2) ^ MAT0POS (21, newV1);
|
||||
state_i--;
|
||||
if (state_i + M3 < R)
|
||||
WELLRNG19937 = case_6;
|
||||
return (STATE[state_i] ^ (newVM2 & BITMASK));
|
||||
}
|
||||
|
||||
static unsigned int case_5 (void){
|
||||
// state_i+M2 >= R
|
||||
z0 = (VRm1 & MASKL) | (VRm2 & MASKU);
|
||||
z1 = MAT0NEG (-25, V0) ^ MAT0POS (27, VM1);
|
||||
z2 = MAT3POS (9, VM2Over) ^ MAT0POS (1, VM3Over);
|
||||
newV1 = z1 ^ z2;
|
||||
newV0 = MAT1 (z0) ^ MAT0NEG (-9, z1) ^ MAT0NEG (-21, z2) ^ MAT0POS (21, newV1);
|
||||
state_i--;
|
||||
if (state_i + M2 < R)
|
||||
WELLRNG19937 = case_4;
|
||||
return (STATE[state_i] ^ (newVM2Over & BITMASK));
|
||||
}
|
||||
|
||||
static unsigned int case_6 (void){
|
||||
// 2 <= state_i <= (R - M3 - 1)
|
||||
z0 = (VRm1 & MASKL) | (VRm2 & MASKU);
|
||||
z1 = MAT0NEG (-25, V0) ^ MAT0POS (27, VM1);
|
||||
z2 = MAT3POS (9, VM2) ^ MAT0POS (1, VM3);
|
||||
newV1 = z1 ^ z2;
|
||||
newV0 = MAT1 (z0) ^ MAT0NEG (-9, z1) ^ MAT0NEG (-21, z2) ^ MAT0POS (21, newV1);
|
||||
state_i--;
|
||||
if (state_i == 1)
|
||||
WELLRNG19937 = case_2;
|
||||
return (STATE[state_i] ^ (newVM2 & BITMASK));
|
||||
}
|
||||
|
||||
// end WELL RNG code
|
||||
|
||||
|
||||
float EQ13toFloat(int d)
|
||||
{
|
||||
return ( float(d)/float(1<<2));
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
#ifndef __random_h__
|
||||
#define __random_h__
|
||||
|
||||
#include <random>
|
||||
#include <utility>
|
||||
|
||||
/* This uses mt19937 seeded with the std::random_device
|
||||
* The idea is to have this be included as a member of another class
|
||||
* so mocking out for testing is easier
|
||||
* If you need to reseed random.Reseed()
|
||||
* Eventually this should be derived from an abstract base class
|
||||
*/
|
||||
|
||||
namespace EQEmu {
|
||||
class Random {
|
||||
public:
|
||||
// AKA old MakeRandomInt
|
||||
const int Int(int low, int high)
|
||||
{
|
||||
if (low > high)
|
||||
std::swap(low, high);
|
||||
return std::uniform_int_distribution<int>(low, high)(m_gen); // [low, high]
|
||||
}
|
||||
|
||||
// AKA old MakeRandomFloat
|
||||
const double Real(double low, double high)
|
||||
{
|
||||
if (low > high)
|
||||
std::swap(low, high);
|
||||
return std::uniform_real_distribution<double>(low, high)(m_gen); // [low, high)
|
||||
}
|
||||
|
||||
// example Roll(50) would have a 50% success rate
|
||||
// Roll(100) 100%, etc
|
||||
// valid values 0-100 (well, higher works too but ...)
|
||||
const bool Roll(const int required)
|
||||
{
|
||||
return Int(0, 99) < required;
|
||||
}
|
||||
|
||||
// valid values 0.0 - 1.0
|
||||
const bool Roll(const double required)
|
||||
{
|
||||
return Real(0.0, 1.0) <= required;
|
||||
}
|
||||
|
||||
void Reseed()
|
||||
{
|
||||
// We could do the seed_seq thing here too if we need better seeding
|
||||
// but that is mostly overkill for us, so just seed once
|
||||
std::random_device rd;
|
||||
m_gen.seed(rd());
|
||||
}
|
||||
|
||||
Random()
|
||||
{
|
||||
Reseed();
|
||||
}
|
||||
|
||||
private:
|
||||
std::mt19937 m_gen;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif /* !__random_h__ */
|
||||
|
||||
Reference in New Issue
Block a user