skidd13@7935: /* $Id$ */ skidd13@7935: rubidium@9111: /** @file random_func.hpp Pseudo random number generator. */ skidd13@7935: skidd13@7935: #ifndef RANDOM_FUNC_HPP skidd13@7935: #define RANDOM_FUNC_HPP skidd13@7935: skidd13@8126: #if defined(__APPLE__) skidd13@8126: /* Apple already has Random declared */ skidd13@8126: #define Random OTTD_Random skidd13@8126: #endif /* __APPLE__ */ skidd13@8126: skidd13@7935: /************** skidd13@7935: * Warning: DO NOT enable this unless you understand what it does skidd13@7935: * skidd13@7935: * If enabled, in a network game all randoms will be dumped to the skidd13@7935: * stdout if the first client joins (or if you are a client). This skidd13@7935: * is to help finding desync problems. skidd13@7935: * skidd13@7935: * Warning: DO NOT enable this unless you understand what it does skidd13@7935: **************/ skidd13@7935: skidd13@7935: //#define RANDOM_DEBUG skidd13@7935: skidd13@7935: rubidium@8434: /** rubidium@8434: * Structure to encapsulate the pseudo random number generators. rubidium@8434: */ rubidium@8434: struct Randomizer { rubidium@8434: /** The state of the randomizer */ rubidium@8434: uint32 state[2]; rubidium@8434: rubidium@8434: /** rubidium@8434: * Generate the next pseudo random number rubidium@8434: * @return the random number rubidium@8434: */ rubidium@8434: uint32 Next(); rubidium@8434: rubidium@8434: /** rubidium@8434: * Generate the next pseudo random number scaled to max rubidium@8434: * @param max the maximum value of the returned random number rubidium@8434: * @return the random number rubidium@8434: */ rubidium@8434: uint32 Next(uint16 max); rubidium@8434: rubidium@8434: /** rubidium@8434: * (Re)set the state of the random number generator. rubidium@8434: * @param seed the new state rubidium@8434: */ rubidium@8434: void SetSeed(uint32 seed); rubidium@8434: }; rubidium@8434: extern Randomizer _random; ///< Random used in the game state calculations rubidium@8434: extern Randomizer _interactive_random; ///< Random used every else where is does not (directly) influence the game state rubidium@8434: frosch@9928: /** Stores the state of all random number generators */ frosch@9928: struct SavedRandomSeeds { frosch@9928: Randomizer random; frosch@9928: Randomizer interactive_random; frosch@9928: }; frosch@9928: frosch@9928: /** Saves the current seeds frosch@9928: * @param storage Storage for saving frosch@9928: */ frosch@9928: static inline void SaveRandomSeeds(SavedRandomSeeds *storage) frosch@9928: { frosch@9928: storage->random = _random; frosch@9928: storage->interactive_random = _interactive_random; frosch@9928: } frosch@9928: frosch@9928: /** Restores previously saved seeds frosch@9928: * @param storage Storage where SaveRandomSeeds() stored th seeds frosch@9928: */ frosch@9928: static inline void RestoreRandomSeeds(const SavedRandomSeeds &storage) frosch@9928: { frosch@9928: _random = storage.random; frosch@9928: _interactive_random = storage.interactive_random; frosch@9928: } frosch@9928: skidd13@7935: void SetRandomSeed(uint32 seed); skidd13@7935: #ifdef RANDOM_DEBUG skidd13@7935: #define Random() DoRandom(__LINE__, __FILE__) skidd13@7935: uint32 DoRandom(int line, const char *file); skidd13@7935: #define RandomRange(max) DoRandomRange(max, __LINE__, __FILE__) skidd13@7935: uint DoRandomRange(uint max, int line, const char *file); skidd13@7935: #else skidd13@9576: static FORCEINLINE uint32 Random() skidd13@9576: { skidd13@9576: return _random.Next(); skidd13@9576: } skidd13@9576: skidd13@9576: static FORCEINLINE uint32 RandomRange(uint16 max) skidd13@9576: { skidd13@9576: return _random.Next(max); skidd13@9576: } skidd13@7935: #endif skidd13@7935: skidd13@9576: static FORCEINLINE uint32 InteractiveRandom() skidd13@9576: { skidd13@9576: return _interactive_random.Next(); skidd13@9576: } skidd13@9576: skidd13@9576: static FORCEINLINE uint32 InteractiveRandomRange(uint16 max) skidd13@9576: { skidd13@9576: return _interactive_random.Next(max); skidd13@9576: } skidd13@7935: skidd13@7967: /** skidd13@7967: * Checks if a given randomize-number is below a given probability. skidd13@7967: * skidd13@7967: * This function is used to check if the given probability by the fraction of (a/b) skidd13@7967: * is greater than low 16 bits of the given randomize-number v. skidd13@7967: * skidd13@7967: * Do not use this function twice on the same random 16 bits as it will yield skidd13@7967: * the same result. One can use a random number for two calls to Chance16I, skidd13@7967: * where one call sends the low 16 bits and the other the high 16 bits. skidd13@7967: * skidd13@7967: * @param a The numerator of the fraction skidd13@7967: * @param b The denominator of the fraction, must of course not be null skidd13@7967: * @param r The given randomize-number skidd13@7967: * @return True if v is less or equals (a/b) skidd13@7967: */ skidd13@9575: static FORCEINLINE bool Chance16I(const uint a, const uint b, const uint32 r) skidd13@7967: { skidd13@7967: assert(b != 0); smatz@8575: return (uint16)r < (uint16)(((a << 16) + b / 2) / b); skidd13@7967: } skidd13@7967: skidd13@7967: /** skidd13@7967: * Flips a coin with a given probability. skidd13@7967: * skidd13@7967: * This macro can be used to get true or false randomized according to a skidd13@7967: * given probability. The parameter a and b create a percent value with skidd13@7967: * (a/b). The macro returns true in (a/b) percent. skidd13@7967: * skidd13@7967: * @see Chance16I() skidd13@7967: * @param a The numerator of the fraction skidd13@7967: * @param b The denominator of the fraction skidd13@7967: * @return True in (a/b) percent skidd13@7967: */ skidd13@9575: static FORCEINLINE bool Chance16(const uint a, const uint b) skidd13@7967: { skidd13@7967: return Chance16I(a, b, Random()); skidd13@7967: } skidd13@7967: skidd13@7967: /** skidd13@7967: * Flips a coin with a given probability and saves the randomize-number in a variable. skidd13@7967: * skidd13@7967: * This function uses the same parameters as Chance16. The third parameter skidd13@7967: * must be a variable the randomize-number from Random() is saved in. skidd13@7967: * skidd13@7967: * The low 16 bits of r will already be used and can therefor not be passed to skidd13@7967: * Chance16I. One can only send the high 16 bits to Chance16I. skidd13@7967: * skidd13@7967: * @see Chance16I() skidd13@7967: * @param a The numerator of the fraction skidd13@7967: * @param b The denominator of the fraction skidd13@7967: * @param r The variable to save the randomize-number from Random() skidd13@7967: * @return True in (a/b) percent skidd13@7967: */ skidd13@9575: static FORCEINLINE bool Chance16R(const uint a, const uint b, uint32 &r) skidd13@7967: { skidd13@7967: r = Random(); skidd13@7967: return Chance16I(a, b, r); skidd13@7967: } skidd13@7967: skidd13@7935: #endif /* RANDOM_FUNC_HPP */