00001
00002
00003
00004
00005
00018 #ifndef HRANDOM_H
00019 #define HRANDOM_H
00020
00057 class HRandom : public HObjNoCopy
00058 {
00059 typedef HObjNoCopy base_class;
00060 static StringPtr ClassName(void) { return "HRandom"; }
00061
00062 enum {
00063 kPeriod = 397,
00064 kLength = 624
00065 } bogus;
00066
00067
00068
00069 protected:
00070 int32 m_nLeft;
00071 uint32 m_uSeed;
00072 uint32 * m_puNext;
00073 uint32 m_uState[kLength+1];
00074
00075
00076
00077 public:
00078 HRandom(uint32 uSeed = 0) : m_nLeft(-1), m_uSeed(0), m_puNext(NULL)
00079 { if (uSeed) SetSeed(uSeed); }
00080
00081 ~HRandom(void)
00082 { }
00083
00084
00085
00086 protected:
00092 uint32
00093 reload(void)
00094 {
00095 int32 ndx;
00096 uint32 uS0,
00097 uS1;
00098 uint32 * pu0 = m_uState;
00099 uint32 * pu2 = &m_uState[2];
00100 uint32 * puM = &m_uState[kPeriod];
00101
00102 if (m_nLeft < -1)
00103 HError::Throw(ERR_NOT_INITIALIZED, __FILE__, __LINE__);
00104
00105 #define hiBit(u) ((u) & 0x80000000U) // mask all but highest bit of u
00106 #define loBit(u) ((u) & 0x00000001U) // mask all but lowest bit of u
00107 #define loBits(u) ((u) & 0x7FFFFFFFU) // mask the highest bit of u
00108 #define mixBits(u,v) (hiBit(u) | loBits(v)) // move hi bit of u to hi bit of v
00109
00110 m_nLeft = kLength - 1;
00111 m_puNext = m_uState + 1;
00112
00113 uS0 = m_uState[0];
00114 uS1 = m_uState[1];
00115 for (ndx = (kLength - kPeriod) + 1; --ndx; uS0 = uS1, uS1 = *pu2++)
00116 *pu0++ = *puM++ ^ (mixBits(uS0, uS1) >> 1) ^ (loBit(uS1) ? 0x9908B0DFU : 0U);
00117
00118 for (puM = m_uState, ndx = kPeriod; --ndx; uS0 = uS1, uS1 = *pu2++)
00119 *pu0++ = *puM++ ^ (mixBits(uS0, uS1) >> 1) ^ (loBit(uS1) ? 0x9908B0DFU : 0U);
00120
00121 uS1 = m_uState[0];
00122 *pu0 = *puM ^ (mixBits(uS0, uS1) >> 1) ^ (loBit(uS1) ? 0x9908B0DFU : 0U);
00123 uS1 ^= (uS1 >> 11);
00124 uS1 ^= (uS1 << 7) & 0x9D2C5680U;
00125 uS1 ^= (uS1 << 15) & 0xEFC60000U;
00126
00127 return uS1 ^ (uS1 >> 18);
00128 }
00129
00130
00131
00132 public:
00138 uint32 Get(void)
00139 {
00140 uint32 uiRnd;
00141
00142 if (--m_nLeft >= 0)
00143 {
00144 uiRnd = *m_puNext++;
00145 uiRnd ^= (uiRnd >> 11);
00146 uiRnd ^= (uiRnd << 7) & 0x9D2C5680U;
00147 uiRnd ^= (uiRnd << 15) & 0xEFC60000U;
00148 uiRnd ^= (uiRnd >> 18);
00149 }
00150 else
00151 uiRnd = reload();
00152
00153 return uiRnd;
00154 }
00161 uint32 Get(uint32 uMax)
00162 {
00163 uint32 uRnd = Get();
00164
00165 if (uMax == 1)
00166 uRnd &= 0x01;
00167 else if (uMax < uint32(INT32_MAX))
00168 uRnd %= uMax;
00169
00170 return uRnd;
00171 }
00187 int32 Get(uint32 uCount, uint32 uDieSize, int32 nBonus = 0)
00188 {
00189 int32 nRnd = nBonus * uCount;
00190
00191 if (uCount > 0 && uDieSize > 0)
00192 {
00193 ASSERT(uCount < uint32(INT32_MAX));
00194 ASSERT(uDieSize < uint32(INT32_MAX));
00195
00196 while (uCount-- > 0)
00197 nRnd += Get(uDieSize) + 1;
00198 }
00199
00200 return nRnd;
00201 }
00207 uint32 GetSeed(void) const
00208 { return m_uSeed; }
00215 ErrCode SetSeed(uint32 uSeed)
00216 {
00217 uint32 * puState = m_uState;
00218
00219 DEBUG_LOG("HRandom::SetSeed() => seed value is %lu\n", uSeed);
00220
00221 m_uSeed = uSeed;
00222 uSeed |= 1U;
00223 for (int32 ndx = 0; ndx < kLength; ++ndx)
00224 {
00225 *puState++ = uSeed;
00226 uSeed *= 69069U;
00227 }
00228
00229
00230
00231
00232
00233 m_nLeft = 0;
00234 return HError::NoError();
00235 }
00236 };
00237
00238 #endif // HRANDOM_H
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261