Leviathan  0.8.0.0
Leviathan game engine
Random.cpp
Go to the documentation of this file.
1 /********************************************************************
2  created: 2012/11/21
3  created: 21:11:2012 16:22
4  filename: Random.cpp
5  file path: Engine
6  file base: Random
7  file ext: cpp
8  author: Henri Hyyryläinen
9 
10  purpose: Platform independent random number generator, based on implementation of
11 Mersenne twister. Code written based on pseudocode on
12  http://en.wikipedia.org/wiki/Mersenne_twister MT19937 algorithm.
13 *********************************************************************/
14 // ------------------------------------ //
15 #include "Random.h"
16 
17 #include "../Logger.h"
18 #ifndef _WIN32
19 #include <sys/time.h>
20 #else
21 #include "WindowsInclude.h"
22 #endif
23 using namespace Leviathan;
24 // ------------------------------------ //
26 {
27  Index = 0;
28 
29  // no seed provided so we must use current system time as seed //
30 #ifdef _WIN32
31  // structures to get time //
32  SYSTEMTIME time;
33  GetSystemTime(&time);
34  // just mash something together from current time //
35  Seed =
36  2500 + time.wDay * 25 + time.wHour * 15 + time.wMilliseconds * 50 + time.wSecond * 2;
37 #else
38  timespec time;
39 
40  clock_gettime(CLOCK_REALTIME, &time);
41 
42  Seed = time.tv_nsec + time.tv_sec * 2;
43 
44 #endif
45 
46  // initialize numbers //
47  _InitializeGenerator();
48 }
49 
51 {
52  // just save values and initialize it //
53  Index = 0;
54  Seed = seed;
55 
56  _InitializeGenerator();
57 }
58 
60 {
61  // we don't really need to delete anything //
62 
63  // check is static access this and set to null if it is //
64  if(staticaccess == this)
65  staticaccess = NULL;
66 }
67 
69 {
70  return staticaccess;
71 }
72 
73 Random* Leviathan::Random::staticaccess = NULL;
74 // ------------------------------------ //
76 {
77  return Seed;
78 }
79 // ------------------------------------ //
81 {
82  // gets the number from index //
83 
84  if(Index == 0) {
85  // needs new set of numbers //
86  _GenerateNumbers();
87  }
88 
89  int y = MT[Index];
90 
91  // randomize the result more here //
92 
93  y = y ^ (y >> 11);
94  y = y ^ ((y << 7) & (0x9d2c5680));
95  y = y ^ ((y << 15) & (0xefc60000));
96  y = y ^ (y >> 18);
97 
98  // increase index //
99  Index = (Index + 1) % RANDOM_STORAGE_SIZE;
100  return y;
101 }
102 
103 int Leviathan::Random::GetNumber(int min, int max)
104 {
105  // New, hopefully better approach for smaller ranges
106  // See stuff here:
107  // https://stackoverflow.com/questions/1202687/how-do-i-get-a-specific-range-of-numbers-from-rand
108  return static_cast<int>(min + (GetNumber() / (RANDOM_MAX_POSSIBLE / (max - min + 1) + 1.0f)));
109 }
110 
111 float Leviathan::Random::GetNumber(float min, float max)
112 {
113  // same as above but with floats //
114 
115  // get number and sample it to be between given values //
116  // basically get percentage of max value and then get difference of min and max and
117  // multiply that by percents and add it to min to get value between min and max
118  return min + (((float)GetNumber() / RANDOM_MAX_POSSIBLE) * (max - min));
119 }
120 
122 {
123  return 2.f * GetNumber(0.f, 1.f) - 1.f;
124 }
125 // ------------------------------------ //
127 {
128  // this acts the same as generating new object with the provided seed //
129  Seed = seed;
130  Index = 0;
131  _InitializeGenerator();
132 }
133 
135 {
136  Index = index % RANDOM_STORAGE_SIZE;
137 }
138 
140 {
141  return Index;
142 }
143 
145 {
146  if(staticaccess != NULL)
147  Logger::Get()->Info("Random: old static access replaced by new");
148  staticaccess = this;
149 }
150 // ------------------------------------ //
151 void Leviathan::Random::_InitializeGenerator()
152 {
153  MT[0] = Seed;
154 
155  for(int i = 1; i < RANDOM_STORAGE_SIZE; i++) {
156  MT[i] = (1812433253 * (MT[i - 1] ^ (MT[i - 1]) >> 30) + i);
157  }
158 }
159 
160 void Leviathan::Random::_GenerateNumbers()
161 {
162  // generates new set of numbers //
163 
164  for(int i = 0; i < RANDOM_STORAGE_SIZE; i++) {
165  int y = MT[i] =
166  (MT[i] & 0x80000000) + (MT[(i + i) % RANDOM_STORAGE_SIZE] & 0x7fffffff);
167 
168  MT[i] = MT[(i + 397) % RANDOM_STORAGE_SIZE] ^ (y >> 1);
169  if((y % 2) != 0) {
170  // odd number //
171  MT[i] = MT[i] ^ (0x9908b0df);
172  }
173  }
174 }
#define RANDOM_STORAGE_SIZE
Definition: Random.h:10
DLLEXPORT void Info(const std::string &data) override
Definition: Logger.cpp:164
Random number generator based on Mersenne Twister.
Definition: Random.h:15
DLLEXPORT void SetIndex(int index)
Definition: Random.cpp:134
DLLEXPORT float SymmetricRandom()
Definition: Random.cpp:121
DLLEXPORT int GetIndex()
Definition: Random.cpp:139
DLLEXPORT int GetNumber()
Definition: Random.cpp:80
DLLEXPORT void SetAsMain()
Definition: Random.cpp:144
static DLLEXPORT Logger * Get()
Definition: Logger.cpp:106
DLLEXPORT ~Random()
Definition: Random.cpp:59
static DLLEXPORT Random * Get()
Definition: Random.cpp:68
#define DLLEXPORT
Definition: Include.h:84
DLLEXPORT int GetSeed()
Definition: Random.cpp:75
The access mask controls which registered functions and classes a script sees.
Definition: GameModule.h:12
DLLEXPORT Random()
Definition: Random.cpp:25
DLLEXPORT void SetSeed(int seed)
Definition: Random.cpp:126
#define RANDOM_MAX_POSSIBLE
Definition: Random.h:9