Index   Main   Namespaces   Classes   Hierarchy   Annotated   Files   Compound   Global   Pages  

SgRandom.h

Go to the documentation of this file.
00001 //----------------------------------------------------------------------------
00002 /** @file SgRandom.h
00003     Random numbers.
00004 */
00005 //----------------------------------------------------------------------------
00006 
00007 #ifndef SG_RANDOM_H
00008 #define SG_RANDOM_H
00009 
00010 #include <algorithm>
00011 #include <list>
00012 #include <boost/random/mersenne_twister.hpp>
00013 #include "SgArray.h"
00014 
00015 //----------------------------------------------------------------------------
00016 
00017 /** Random number generator.
00018     Uses a Mersenne Twister, because this is faster than std::rand() and
00019     game playing programs usually need faster random numbers more than
00020     high quality ones. All random generators are internally registered to
00021     make it possible to change the random seed for all of them.
00022 
00023     SgRandom is thread-safe (w.r.t. different instances) after construction
00024     (the constructor is not thread-safe, because it uses a global variable
00025     for registration).
00026 */
00027 class SgRandom
00028 {
00029 public:
00030     SgRandom();
00031 
00032     ~SgRandom();
00033 
00034     /** Return the global random number generator.
00035         The global generator is stored as a static variable in this function
00036         to ensure that it is initialized at first call if SgRandom is used
00037         in global variables of other compilation units.
00038         @note The global random number generator is not thread-safe.
00039     */
00040     static SgRandom& Global();
00041 
00042     /** Set random seed for all existing and future instances of SgRandom.
00043         @param seed The seed. If negative, no seed will be set. If zero, a
00044         non-deterministic random seed will be used (e.g. derived from the
00045         current time).
00046         Also calls std::srand()
00047         @note This function is not thread-safe.
00048     */
00049     static void SetSeed(int seed);
00050 
00051     /** Get random seed.
00052         See SetSeed(int) for the special meaning of zero and negative values.
00053     */
00054     static int Seed();
00055 
00056     /** Get a random integer.
00057         Uses a fast random generator (the Mersenne Twister boost::mt19937),
00058         because in games and Monte Carlo simulations, speed is more important
00059         than quality.
00060     */
00061     unsigned int Int();
00062 
00063     /** Get a random integer in [0..range - 1]. */
00064     int Int(int range);
00065 
00066     /** Get a random integer in [min, max - 1] */
00067     int Range(int min, int max);
00068 
00069     /** Maximum value. */
00070     unsigned int Max();
00071 
00072     /** convert percentage between 0 and 99 to a threshold for RandomEvent.
00073         Use as in following example:
00074         const unsigned int percent80 = PercentageThreshold(80);
00075     */
00076     unsigned int PercentageThreshold(int percentage);
00077 
00078     /** return true if random number SgRandom() <= threshold */
00079     bool RandomEvent(unsigned int threshold);
00080 
00081 private:
00082     struct GlobalData
00083     {
00084         /** The random seed.
00085             Zero means not to set a random seed.
00086         */
00087         boost::mt19937::result_type m_seed;
00088 
00089         std::list<SgRandom*> m_allGenerators;
00090 
00091         GlobalData();
00092     };
00093 
00094     /** Return global data.
00095         Global data is stored as a static variable in this function to ensure
00096         that it is initialized at first call if SgRandom is used in global
00097         variables of other compilation units.
00098     */
00099     static GlobalData& GetGlobalData();
00100 
00101     boost::mt19937 m_generator;
00102 
00103     void SetSeed();
00104 };
00105 
00106 inline unsigned int SgRandom::Int()
00107 {
00108     return m_generator();
00109 }
00110 
00111 inline int SgRandom::Int(int range)
00112 {
00113     SG_ASSERT(range > 0);
00114     SG_ASSERT(static_cast<unsigned int>(range) <= SgRandom::Max());
00115     int i = Int() % range;
00116     SG_ASSERTRANGE(i, 0, range - 1);
00117     return i;
00118 }
00119 
00120 inline unsigned int SgRandom::Max()
00121 {
00122     return m_generator.max();
00123 }
00124 
00125 inline unsigned int SgRandom::PercentageThreshold(int percentage)
00126 {
00127     return (m_generator.max() / 100) * percentage;
00128 }
00129 
00130 inline bool SgRandom::RandomEvent(unsigned int threshold)
00131 {
00132     return Int() <= threshold;
00133 }
00134 
00135 inline int SgRandom::Range(int min, int max)
00136 {
00137     return min + Int(max - min);
00138 }
00139 
00140 //----------------------------------------------------------------------------
00141 
00142 /** Get a random float in [min, max].
00143     Used std::rand()
00144 */
00145 float SgRandomFloat(float min, float max);
00146 
00147 //----------------------------------------------------------------------------
00148 
00149 #endif // SG_RANDOM_H


17 Jun 2010 Doxygen 1.4.7