// SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 2012-2014 by Matthew "Inuyasha" Walsh. // Copyright (C) 1999-2014 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. // See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- /// \file m_random.c /// \brief LCG PRNG originally created for XMOD #include "doomdef.h" #include "doomtype.h" #include "doomstat.h" // totalplaytime #include "m_random.h" #include "m_fixed.h" // --------------------------- // RNG functions (not synched) // --------------------------- /** Provides a random byte. * Used outside the p_xxx game code and not synchronized in netgames. This is * for anything that doesn't need to be synced, e.g. precipitation. * * \return A random byte, 0 to 255. */ UINT8 M_Random(void) { return (rand() & 255); } /** Provides a random signed byte. Distribution is uniform. * As with all M_*Random functions, not synched in netgames. * * \return A random byte, -128 to 127. * \sa M_Random */ INT32 M_SignedRandom(void) { return M_Random() - 128; } /** Provides a random number in between 0 and the given number - 1. * Distribution is uniform. Use for picking random elements from an array. * As with all M_*Random functions, not synched in netgames. * * \return A random number, 0 to arg1-1. */ INT32 M_RandomKey(INT32 a) { return (INT32)((rand()/((unsigned)RAND_MAX+1.0f))*a); } /** Provides a random number in between a specific range. * Distribution is uniform. * As with all M_*Random functions, not synched in netgames. * * \return A random number, arg1 to arg2. */ INT32 M_RandomRange(INT32 a, INT32 b) { return (INT32)((rand()/((unsigned)RAND_MAX+1.0f))*(b-a+1))+a; } // ------------------------ // PRNG functions (synched) // ------------------------ // Holds the current seed. static UINT32 randomseed = 0; // Holds the INITIAL seed value. Used for demos, possibly other debugging. static UINT32 initialseed = 0; /** * Provides a random byte and sets the seed appropriately. * The nature of this PRNG allows it to cycle through about two million numbers * before it finally starts repeating numeric sequences. * That's more than good enough for our purposes. * * \return A random byte, 0 to 255. */ #ifndef DEBUGRANDOM UINT8 P_Random(void) { #else UINT8 P_RandomD(const char *rfile, INT32 rline) { CONS_Debug(DBG_RANDOMIZER, "P_Random() at: %sp %d\n", rfile, rline); #endif randomseed = (randomseed*746151647)+48205429; return (UINT8)((randomseed >> 17)&255); } /** Provides a random number from -128 to 127. * Distribution is uniform. * * \return Random number from -128 to 127. * \sa P_Random */ #ifndef DEBUGRANDOM INT32 P_SignedRandom(void) { #else INT32 P_SignedRandomD(const char *rfile, INT32 rline) { CONS_Debug(DBG_RANDOMIZER, "P_SignedRandom() at: %sp %d\n", rfile, rline); #endif return P_Random() - 128; } /** Provides a random number in between 0 and the given number - 1. * Distribution is uniform, also calls for two numbers for bigger output range. * Use for picking random elements from an array. * * \return A random number, 0 to arg1-1. * \sa P_Random */ #ifndef DEBUGRANDOM INT32 P_RandomKey(INT32 a) { #else INT32 P_RandomKeyD(const char *rfile, INT32 rline, INT32 a) { CONS_Debug(DBG_RANDOMIZER, "P_RandomKey() at: %sp %d\n", rfile, rline); #endif return (INT32)(((P_Random()|(P_Random() << 8))/65536.0f)*a); } /** Provides a random number in between a specific range. * Distribution is uniform, also calls for two numbers for bigger output range. * * \return A random number, arg1 to arg2. * \sa P_Random */ #ifndef DEBUGRANDOM INT32 P_RandomRange(INT32 a, INT32 b) { #else INT32 P_RandomRangeD(const char *rfile, INT32 rline, INT32 a, INT32 b) { CONS_Debug(DBG_RANDOMIZER, "P_RandomRange() at: %sp %d\n", rfile, rline); #endif return (INT32)(((P_Random()|(P_Random() << 8))/65536.0f)*(b-a+1))+a; } /** Provides a random byte without saving what the seed would be. * Used just to debug the PRNG. * * \return A 'random' byte, 0 to 255. * \sa P_Random */ UINT8 P_RandomPeek(void) { UINT32 r = (randomseed*746151647)+48205429; return (UINT8)((r >> 17)&255); } /** Gets the current random seed. Used by netgame savegames. * * \return Current random seed. * \sa P_SetRandSeed */ UINT32 P_GetRandSeed(void) { return randomseed; } /** Gets the initial random seed. Used by demos. * * \return Initial random seed. * \sa P_SetRandSeed */ UINT32 P_GetInitSeed(void) { return initialseed; } /** Sets the random seed. * Used at the beginning of the game, and also for netgames. * * \param rindex New random index. * \sa P_GetRandSeed */ void P_SetRandSeed(UINT32 seed) { randomseed = initialseed = seed; } /** Gets a randomized seed for setting the random seed. * * \sa P_GetRandSeed */ UINT32 M_RandomizedSeed(void) { return ((totalplaytime & 0xFFFF) << 16)|(rand() & 0xFFFF); }