26 { |
26 { |
27 this->state[0] = seed; |
27 this->state[0] = seed; |
28 this->state[1] = seed; |
28 this->state[1] = seed; |
29 } |
29 } |
30 |
30 |
31 #ifdef MERSENNE_TWISTER |
|
32 // Source code for Mersenne Twister. |
|
33 // A Random number generator with much higher quality random numbers. |
|
34 |
|
35 #define N (624) // length of _mt_state vector |
|
36 #define M (397) // a period parameter |
|
37 #define K (0x9908B0DFU) // a magic constant |
|
38 #define hiBit(u) ((u) & 0x80000000U) // mask all but highest bit of u |
|
39 #define loBit(u) ((u) & 0x00000001U) // mask all but lowest bit of u |
|
40 #define loBits(u) ((u) & 0x7FFFFFFFU) // mask the highest bit of u |
|
41 #define mixBits(u, v) (hiBit(u)|loBits(v)) // move hi bit of u to hi bit of v |
|
42 |
|
43 static uint32 _mt_state[N+1]; // _mt_state vector + 1 extra to not violate ANSI C |
|
44 static uint32 *_mt_next; // _mt_next random value is computed from here |
|
45 static int _mt_left = -1; // can *_mt_next++ this many times before reloading |
|
46 |
|
47 void SetRandomSeed(register uint32 seed) |
|
48 { |
|
49 register uint32 *s = _mt_state; |
|
50 _mt_left = 0; |
|
51 |
|
52 seed |= 1U; |
|
53 seed &= 0xFFFFFFFFU; |
|
54 |
|
55 *s = seed; |
|
56 |
|
57 for (register uint i = N; i != 0; i--) { |
|
58 seed *= 69069U; |
|
59 *s++; |
|
60 *s = seed & 0xFFFFFFFFU; |
|
61 } |
|
62 } |
|
63 |
|
64 static uint32 ReloadRandom() |
|
65 { |
|
66 if (_mt_left < -1) SetRandomSeed(4357U); |
|
67 |
|
68 _mt_left = N - 1; |
|
69 _mt_next = _mt_state + 1; |
|
70 |
|
71 register uint32 *p0 = _mt_state; |
|
72 register uint32 *p2 = _mt_state + 2; |
|
73 register uint32 *pM = _mt_state + M; |
|
74 |
|
75 register uint32 s0 = _mt_state[0]; |
|
76 register uint32 s1 = _mt_state[1]; |
|
77 |
|
78 register uint i = 0; |
|
79 |
|
80 for (i = (N - M + 1); i != 0; i--) { |
|
81 s0 = s1; |
|
82 s1 = *p2; |
|
83 *p0 = *pM ^ (mixBits(s0, s1) >> 1) ^ (loBit(s1) ? K : 0U); |
|
84 *p0++; |
|
85 *p2++; |
|
86 *pM++; |
|
87 } |
|
88 |
|
89 pM = _mt_state; |
|
90 |
|
91 for (i = M; i != 0; i--) { |
|
92 s0 = s1; |
|
93 s1 = *p2; |
|
94 *p0 = *pM ^ (mixBits(s0, s1) >> 1) ^ (loBit(s1) ? K : 0U); |
|
95 *p0++; |
|
96 *p2++; |
|
97 *pM++; |
|
98 } |
|
99 |
|
100 s1 = _mt_state[0]; |
|
101 *p0 = *pM ^ (mixBits(s0, s1) >> 1) ^ (loBit(s1) ? K : 0U); |
|
102 |
|
103 s1 ^= (s1 >> 11); |
|
104 s1 ^= (s1 << 7) & 0x9D2C5680U; |
|
105 s1 ^= (s1 << 15) & 0xEFC60000U; |
|
106 s1 ^= (s1 >> 18); |
|
107 return s1; |
|
108 } |
|
109 |
|
110 uint32 Random() |
|
111 { |
|
112 _mt_left--; |
|
113 if (_mt_left < 0) return ReloadRandom(); |
|
114 |
|
115 uint32 y = *_mt_next; |
|
116 *_mt_next++; |
|
117 |
|
118 y ^= (y >> 11); |
|
119 y ^= (y << 7) & 0x9D2C5680U; |
|
120 y ^= (y << 15) & 0xEFC60000U; |
|
121 y ^= (y >> 18); |
|
122 return y; |
|
123 } |
|
124 |
|
125 #else /* MERSENNE_TWISTER */ |
|
126 void SetRandomSeed(uint32 seed) |
31 void SetRandomSeed(uint32 seed) |
127 { |
32 { |
128 _random.SetSeed(seed); |
33 _random.SetSeed(seed); |
129 _interactive_random.SetSeed(seed * 0x1234567); |
34 _interactive_random.SetSeed(seed * 0x1234567); |
130 } |
35 } |
140 printf("Random [%d/%d] %s:%d\n",_frame_counter, (byte)_current_player, file, line); |
45 printf("Random [%d/%d] %s:%d\n",_frame_counter, (byte)_current_player, file, line); |
141 } |
46 } |
142 |
47 |
143 return _random.Next(); |
48 return _random.Next(); |
144 } |
49 } |
145 #endif /* RANDOM_DEBUG */ |
|
146 #endif /* MERSENNE_TWISTER */ |
|
147 |
50 |
148 #if defined(RANDOM_DEBUG) && !defined(MERSENNE_TWISTER) |
|
149 uint DoRandomRange(uint max, int line, const char *file) |
51 uint DoRandomRange(uint max, int line, const char *file) |
150 { |
52 { |
151 return GB(DoRandom(line, file), 0, 16) * max >> 16; |
53 return GB(DoRandom(line, file), 0, 16) * max >> 16; |
152 } |
54 } |
153 #endif /* RANDOM_DEBUG & !MERSENNE_TWISTER */ |
55 #endif /* RANDOM_DEBUG */ |