/* $Id: random.hpp,v 1.15 2005/10/11 15:54:24 chfreund Exp $ */ #ifndef _RANDOM_HPP_ #define _RANDOM_HPP_ #include #include "serializable.hpp" #include "vector.hpp" /*! This class provides a stream of random numbers. Its seed is serialized and communicated by the World class. \attention There is one global object of this class #rnd which should be used for all global random number events. If you need a random number locally, use a separate instance of the Random class instead. Original MWC code by George Marsaglia, see http://www.cs.yorku.ca/~oz/marsaglia-rng.html . */ class Random : public Serializable { public: //! If no argument is given, the random number generator will be initialized //! with a combination of the current time and the PID. Random( const unsigned int seed = 0 ); //! \return Random unsigned integer \a x: 0 <= \a x <= 2^32-1 Uint32 getUint32(); //! \return Random unsigned integer \a x: \a a <= \a x <= \a b Uint32 getUint32Between( const Uint32 a, const Uint32 b ); //! \return Random signed integer \a x: \a a <= \a x <= \a b Sint32 getSint32Between( const Sint32 a, const Sint32 b ); //! \return Random real \a x: 0 <= \a x <= 1 real getNormedReal(); //! \return Random color represented as an \c Uint32 betweeen (and //! including) \a colA and \a colB. Each of the three color components is //! treated separately. Uint32 getColor( Uint32 colA, Uint32 colB ); //! \return The number of calls of any random number method. Uint32 getCounter( void ) { return m_counter; } //! \return Random vector with the given length. Vector getVector( const real length ); virtual Uint32 getSerializeBufferSize() const; virtual void serialize( Uint8*& bufferPointer ) const; virtual void deserialize( Uint8*& bufferPointer ); private: Uint32 m_z, //!< One of two variables that are used for computing the next //! random number. m_w, //!< One of two variables that are used for computing the next //! random number. m_counter; //!< Counts the number of random number calls for //! debugging purposes. }; inline Uint32 Random::getUint32() { m_z = 36969 * (m_z & 65535) + (m_z >> 16); m_w = 18000 * (m_w & 65535) + (m_w >> 16); m_counter++; return (m_z << 16) + m_w; } inline real Random::getNormedReal() { return getUint32() * 2.3283064370808e-10; } inline Uint32 Random::getUint32Between( const Uint32 a, const Uint32 b ) { return ((a < b) ? a + (getUint32() % (b-a+1)) : a); } inline Sint32 Random::getSint32Between( const Sint32 a, const Sint32 b ) { return ((a < b) ? a + (getUint32() % (b-a+1)) : a); } inline Uint32 Random::getColor( const Uint32 colA, const Uint32 colB ) { const Uint32 rA = (colA >> 16) & 0xff, rB = (colB >> 16) & 0xff, gA = (colA >> 8) & 0xff, gB = (colB >> 8) & 0xff, bA = (colA ) & 0xff, bB = (colB ) & 0xff; /* return ((rA < rB ? getBetween( rA, rB ) : rA) << 16) + ((gA < gB ? getBetween( gA, gB ) : gA) << 8) + ((bA < bB ? getBetween( bA, bB ) : bA) ); */ return (getUint32Between( rA, rB ) << 16) + (getUint32Between( gA, gB ) << 8) + (getUint32Between( bA, bB ) ); } inline Vector Random::getVector( const real length ) { Vector r; r.setAngle( getNormedReal() * 2 * M_PI, length ); return r; } extern Random localRnd; #endif // _RANDOM_HPP_