Merge branch 'bp_random2' into 'next'

xorshift* PRNG

This needs testing to ensure I didn't mess anything up switching function names around.

Our PRNG sucks. This is probably obvious. I wish I had known better at the time I implemented it, but oh well.

The replacement is an xorshift* PRNG variant with period 2^32 - 1 (meaning that the PRNG state will loop after four billion calls ... that's not likely to happen), versus the old PRNG's period of about 2^22 (?). The output is also much more random and less predictable; the old PRNG would fall into a predictable loop of output after about 4000 numbers were generated, which isn't much.

The PRNG here also outputs numbers as fixed point from [0,1) (that's 0 to FRACUNIT-1, in other words) instead of single bytes at a time. This makes it much easier to calculate things for, say, P_RandomRange and P_RandomKey. A new macro, P_RandomChance(p), is now in use that returns true _p_ percent of the time, where _p_ is a fixed_t probability from 0 (0%) to FRACUNIT (100%).

This doesn't affect netgames at all; the code for seed saving and restoring is identical (aside from a check to prevent seed being set to 0, which breaks xorshift PRNGs). Demos break, but A: _duh_ and B: they're already broken by all the changes to physics to accommodate slopes.

P_Random is deprecated in Lua, as the function was renamed to P_RandomByte. Aside from that, nothing special.

See merge request !64
This commit is contained in:
Inuyasha 2016-04-24 18:03:13 -04:00
commit b288d8a399
17 changed files with 302 additions and 250 deletions

View file

@ -808,7 +808,7 @@ static boolean IsNameGood(char *name, INT32 playernum)
else if (len == 1) // Agh!
{
// Last ditch effort...
sprintf(name, "%d", M_Random() & 7);
sprintf(name, "%d", M_RandomKey(10));
if (!IsNameGood (name, playernum))
return false;
}
@ -3583,7 +3583,7 @@ retryscramble:
for (i = 0; i < playercount; i++)
{
if (repick)
newteam = (INT16)((M_Random() % 2) + 1);
newteam = (INT16)((M_RandomByte() % 2) + 1);
// One team has the most players they can get, assign the rest to the other team.
if (red == maxcomposition || blue == maxcomposition)
@ -3628,7 +3628,7 @@ retryscramble:
{
if (repick)
{
newteam = (INT16)((M_Random() % 2) + 1);
newteam = (INT16)((M_RandomByte() % 2) + 1);
repick = false;
}
else

View file

@ -2349,7 +2349,7 @@ mapthing_t *G_FindCTFStart(INT32 playernum)
return NULL;
}
if ((!players[playernum].ctfteam && numredctfstarts && (!numbluectfstarts || P_Random() & 1)) || players[playernum].ctfteam == 1) //red
if ((!players[playernum].ctfteam && numredctfstarts && (!numbluectfstarts || P_RandomChance(FRACUNIT/2))) || players[playernum].ctfteam == 1) //red
{
if (!numredctfstarts)
{
@ -5487,7 +5487,7 @@ ATTRNORETURN void FUNCNORETURN G_StopMetalRecording(void)
UINT8 i;
WRITEUINT8(demo_p, DEMOMARKER); // add the demo end marker
for (i = 0; i < 16; i++, p++)
*p = P_Random(); // This MD5 was chosen by fair dice roll and most likely < 50% correct.
*p = P_RandomByte(); // This MD5 was chosen by fair dice roll and most likely < 50% correct.
#else
WRITEUINT8(demo_p, DEMOMARKER); // add the demo end marker
md5_buffer((char *)p+16, demo_p - (p+16), (void *)p); // make a checksum of everything after the checksum in the file.
@ -5569,7 +5569,7 @@ boolean G_CheckDemoStatus(void)
UINT8 i;
WRITEUINT8(demo_p, DEMOMARKER); // add the demo end marker
for (i = 0; i < 16; i++, p++)
*p = P_Random(); // This MD5 was chosen by fair dice roll and most likely < 50% correct.
*p = P_RandomByte(); // This MD5 was chosen by fair dice roll and most likely < 50% correct.
#else
WRITEUINT8(demo_p, DEMOMARKER); // add the demo end marker
md5_buffer((char *)p+16, demo_p - (p+16), p); // make a checksum of everything after the checksum in the file.

View file

@ -384,12 +384,12 @@ INT32 HW3S_I_StartSound(const void *origin_p, source3D_data_t *source_parm, chan
/*if (gamemode != heretic)
{
if (sfx_id >= sfx_sawup && sfx_id <= sfx_sawhit)
pitch += 8 - (M_Random()&15);
pitch += 8 - (M_RandomByte()&15);
else if (sfx_id != sfx_itemup && sfx_id != sfx_tink)
pitch += 16 - (M_Random()&31);
pitch += 16 - (M_RandomByte()&31);
}
else*/
pitch = 128 + (M_Random() & 7) - (M_Random() & 7);
pitch = 128 + (M_RandomByte() & 7) - (M_RandomByte() & 7);
}
#endif

View file

@ -871,7 +871,7 @@ void HWR_DoCoronasLighting(FOutVector *outVerts, gr_vissprite_t *spr)
size = p_lspr->corona_radius * ((outVerts[0].z+120.0f)/950.0f); // d'ou vienne ces constante ?
break;
case ROCKET_SPR:
p_lspr->corona_color = (((M_Random()>>1)&0xff)<<24)|0x0040ff;
p_lspr->corona_color = (((M_RandomByte()>>1)&0xff)<<24)|0x0040ff;
// don't need a break
case CORONA_SPR:
size = p_lspr->corona_radius * ((outVerts[0].z+60.0f)/100.0f); // d'ou vienne ces constante ?
@ -974,7 +974,7 @@ void HWR_DrawCoronas(void)
size = p_lspr->corona_radius * ((cz+120.0f)/950.0f); // d'ou vienne ces constante ?
break;
case ROCKET_SPR:
Surf.FlatColor.s.alpha = (UINT8)((M_Random()>>1)&0xff);
Surf.FlatColor.s.alpha = (UINT8)((M_RandomByte()>>1)&0xff);
// don't need a break
case CORONA_SPR:
size = p_lspr->corona_radius * ((cz+60.0f)/100.0f); // d'ou vienne ces constante ?

View file

@ -96,17 +96,17 @@ static int lib_evalMath(lua_State *L)
// M_RANDOM
//////////////
static int lib_pRandom(lua_State *L)
static int lib_pRandomFixed(lua_State *L)
{
NOHUD
lua_pushinteger(L, P_Random());
lua_pushfixed(L, P_RandomFixed());
return 1;
}
static int lib_pSignedRandom(lua_State *L)
static int lib_pRandomByte(lua_State *L)
{
NOHUD
lua_pushinteger(L, P_SignedRandom());
lua_pushinteger(L, P_RandomByte());
return 1;
}
@ -134,6 +134,30 @@ static int lib_pRandomRange(lua_State *L)
return 1;
}
// Deprecated, macros, etc.
static int lib_pRandom(lua_State *L)
{
NOHUD
LUA_Deprecated(L, "P_Random", "P_RandomByte");
lua_pushinteger(L, P_RandomByte());
return 1;
}
static int lib_pSignedRandom(lua_State *L)
{
NOHUD
lua_pushinteger(L, P_SignedRandom());
return 1;
}
static int lib_pRandomChance(lua_State *L)
{
fixed_t p = luaL_checkfixed(L, 1);
NOHUD
lua_pushboolean(L, P_RandomChance(p));
return 1;
}
// P_MAPUTIL
///////////////
@ -1934,10 +1958,13 @@ static luaL_Reg lib[] = {
{"EvalMath", lib_evalMath},
// m_random
{"P_Random",lib_pRandom},
{"P_SignedRandom",lib_pSignedRandom},
{"P_RandomFixed",lib_pRandomFixed},
{"P_RandomByte",lib_pRandomByte},
{"P_RandomKey",lib_pRandomKey},
{"P_RandomRange",lib_pRandomRange},
{"P_Random",lib_pRandom}, // DEPRECATED
{"P_SignedRandom",lib_pSignedRandom}, // MACRO
{"P_RandomChance",lib_pRandomChance}, // MACRO
// p_maputil
{"P_AproxDistance",lib_pAproxDistance},

View file

@ -598,9 +598,9 @@ void Command_CauseCfail_f(void)
}
P_UnsetThingPosition(players[consoleplayer].mo);
P_Random();
P_Random();
P_Random();
P_RandomFixed();
P_RandomByte();
P_RandomFixed();
players[consoleplayer].mo->x = 0;
players[consoleplayer].mo->y = 123311; //cfail cansuled kthxbye
players[consoleplayer].mo->z = 123311;

View file

@ -10,7 +10,7 @@
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file m_random.c
/// \brief LCG PRNG originally created for XMOD
/// \brief RNG for client effects and PRNG for game actions
#include "doomdef.h"
#include "doomtype.h"
@ -19,48 +19,57 @@
#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.
/** Provides a random fixed point number. Distribution is uniform.
* As with all M_Random functions, not synched in netgames.
*
* \return A random byte, 0 to 255.
* \return A random fixed point number from [0,1).
*/
UINT8 M_Random(void)
fixed_t M_RandomFixed(void)
{
return (rand() & 255);
#if RAND_MAX < 65535
// Compensate for insufficient randomness.
fixed_t rndv = (rand()&1)<<15;
return rand()^rndv;
#else
return (rand() & 0xFFFF);
#endif
}
/** Provides a random signed byte. Distribution is uniform.
* As with all M_*Random functions, not synched in netgames.
/** Provides a random byte. Distribution is uniform.
* As with all M_Random functions, not synched in netgames.
*
* \return A random byte, -128 to 127.
* \sa M_Random
* \return A random integer from [0, 255].
*/
INT32 M_SignedRandom(void)
UINT8 M_RandomByte(void)
{
return M_Random() - 128;
return (rand() & 0xFF);
}
/** 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.
/** Provides a random integer for picking random elements from an array.
* Distribution is uniform.
* As with all M_Random functions, not synched in netgames.
*
* \return A random number, 0 to arg1-1.
* \param a Number of items in array.
* \return A random integer from [0,a).
*/
INT32 M_RandomKey(INT32 a)
{
return (INT32)((rand()/((unsigned)RAND_MAX+1.0f))*a);
}
/** Provides a random number in between a specific range.
/** Provides a random integer in a given range.
* Distribution is uniform.
* As with all M_*Random functions, not synched in netgames.
* As with all M_Random functions, not synched in netgames.
*
* \return A random number, arg1 to arg2.
* \param a Lower bound.
* \param b Upper bound.
* \return A random integer from [a,b].
*/
INT32 M_RandomRange(INT32 a, INT32 b)
{
@ -74,54 +83,65 @@ INT32 M_RandomRange(INT32 a, INT32 b)
// ------------------------
// Holds the current seed.
static UINT32 randomseed = 0;
static UINT32 randomseed = 0xBADE4404;
// Holds the INITIAL seed value. Used for demos, possibly other debugging.
static UINT32 initialseed = 0;
static UINT32 initialseed = 0xBADE4404;
/**
* 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.
/** Provides a random fixed point number.
* This is a variant of an xorshift PRNG; state fits in a 32 bit integer structure.
*
* \return A random byte, 0 to 255.
* \return A random fixed point number from [0,1).
*/
#ifndef DEBUGRANDOM
UINT8 P_Random(void)
ATTRINLINE static fixed_t FUNCINLINE __internal_prng__(void)
{
#else
UINT8 P_RandomD(const char *rfile, INT32 rline)
{
CONS_Printf("P_Random() at: %sp %d\n", rfile, rline);
#endif
randomseed = (randomseed*746151647)+48205429;
return (UINT8)((randomseed >> 17)&255);
randomseed ^= randomseed >> 13;
randomseed ^= randomseed >> 11;
randomseed ^= randomseed << 21;
return ( (randomseed*36548569) >> 4) & (FRACUNIT-1);
}
/** Provides a random number from -128 to 127.
/** Provides a random fixed point number. Distribution is uniform.
* Literally a wrapper for the internal PRNG function.
*
* \return A random fixed point number from [0,1).
*/
#ifndef DEBUGRANDOM
fixed_t P_RandomFixed(void)
{
#else
UINT8 P_RandomFixedD(const char *rfile, INT32 rline)
{
CONS_Printf("P_RandomFixed() at: %sp %d\n", rfile, rline);
#endif
return __internal_prng__();
}
/** Provides a random byte. Distribution is uniform.
* If you're curious, (&0xFF00) >> 8 gives the same result
* as a fixed point multiplication by 256.
*
* \return Random integer from [0, 255].
* \sa __internal_prng__
*/
#ifndef DEBUGRANDOM
UINT8 P_RandomByte(void)
{
#else
UINT8 P_RandomByteD(const char *rfile, INT32 rline)
{
CONS_Printf("P_RandomByte() at: %sp %d\n", rfile, rline);
#endif
return (UINT8)((__internal_prng__()&0xFF00)>>8);
}
/** Provides a random integer for picking random elements from an array.
* Distribution is uniform.
* NOTE: Maximum range is 65536.
*
* \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_Printf("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
* \param a Number of items in array.
* \return A random integer from [0,a).
* \sa __internal_prng__
*/
#ifndef DEBUGRANDOM
INT32 P_RandomKey(INT32 a)
@ -131,16 +151,17 @@ INT32 P_RandomKeyD(const char *rfile, INT32 rline, INT32 a)
{
CONS_Printf("P_RandomKey() at: %sp %d\n", rfile, rline);
#endif
INT32 prandom = P_Random(); // note: forcing explicit function call order
prandom |= P_Random() << 8; // (function call order is not strictly defined)
return (INT32)((prandom/65536.0f)*a);
return (INT32)((__internal_prng__() * a) >> FRACBITS);
}
/** Provides a random number in between a specific range.
* Distribution is uniform, also calls for two numbers for bigger output range.
/** Provides a random integer in a given range.
* Distribution is uniform.
* NOTE: Maximum range is 65536.
*
* \return A random number, arg1 to arg2.
* \sa P_Random
* \param a Lower bound.
* \param b Upper bound.
* \return A random integer from [a,b].
* \sa __internal_prng__
*/
#ifndef DEBUGRANDOM
INT32 P_RandomRange(INT32 a, INT32 b)
@ -150,21 +171,27 @@ INT32 P_RandomRangeD(const char *rfile, INT32 rline, INT32 a, INT32 b)
{
CONS_Printf("P_RandomRange() at: %sp %d\n", rfile, rline);
#endif
INT32 prandom = P_Random(); // note: forcing explicit function call order
prandom |= P_Random() << 8; // (function call order is not strictly defined)
return (INT32)((prandom/65536.0f)*(b-a+1))+a;
return (INT32)((__internal_prng__() * (b-a+1)) >> FRACBITS) + a;
}
/** Provides a random byte without saving what the seed would be.
* Used just to debug the PRNG.
// ----------------------
// PRNG seeds & debugging
// ----------------------
/** Peeks to see what the next result from the PRNG will be.
* Used for debugging.
*
* \return A 'random' byte, 0 to 255.
* \sa P_Random
* \return A 'random' fixed point number from [0,1).
* \sa __internal_prng__
*/
UINT8 P_RandomPeek(void)
fixed_t P_RandomPeek(void)
{
UINT32 r = (randomseed*746151647)+48205429;
return (UINT8)((r >> 17)&255);
UINT32 r = randomseed;
fixed_t ret = __internal_prng__();
randomseed = r;
return ret;
}
/** Gets the current random seed. Used by netgame savegames.
@ -213,6 +240,9 @@ void P_SetRandSeedD(const char *rfile, INT32 rline, UINT32 seed)
{
CONS_Printf("P_SetRandSeed() at: %sp %d\n", rfile, rline);
#endif
// xorshift requires a nonzero seed
// this should never happen, but just in case it DOES, we check
if (!seed) seed = 0xBADE4404;
randomseed = initialseed = seed;
}
@ -222,5 +252,5 @@ void P_SetRandSeedD(const char *rfile, INT32 rline, UINT32 seed)
*/
UINT32 M_RandomizedSeed(void)
{
return ((totalplaytime & 0xFFFF) << 16)|(rand() & 0xFFFF);
return ((totalplaytime & 0xFFFF) << 16)|M_RandomFixed();
}

View file

@ -20,32 +20,42 @@
//#define DEBUGRANDOM
// M_Random functions pull random numbers of various types that aren't network synced.
// P_Random functions pulls random bytes from a LCG PRNG that is network synced.
// P_Random functions pulls random bytes from a PRNG that is network synced.
// RNG functions
UINT8 M_Random(void);
INT32 M_SignedRandom(void);
INT32 M_RandomKey(INT32 a);
INT32 M_RandomRange(INT32 a, INT32 b);
fixed_t M_RandomFixed(void);
UINT8 M_RandomByte(void);
INT32 M_RandomKey(INT32 a);
INT32 M_RandomRange(INT32 a, INT32 b);
// PRNG functions
#ifdef DEBUGRANDOM
#define P_Random() P_RandomD(__FILE__, __LINE__)
#define P_SignedRandom() P_SignedRandomD(__FILE__, __LINE__)
#define P_RandomKey(c) P_RandomKeyD(__FILE__, __LINE__, c)
#define P_RandomFixed() P_RandomFixedD(__FILE__, __LINE__)
#define P_RandomByte() P_RandomByteD(__FILE__, __LINE__)
#define P_RandomKey(c) P_RandomKeyD(__FILE__, __LINE__, c)
#define P_RandomRange(c, d) P_RandomRangeD(__FILE__, __LINE__, c, d)
UINT8 P_RandomD(const char *rfile, INT32 rline);
INT32 P_SignedRandomD(const char *rfile, INT32 rline);
INT32 P_RandomKeyD(const char *rfile, INT32 rline, INT32 a);
INT32 P_RandomRangeD(const char *rfile, INT32 rline, INT32 a, INT32 b);
fixed_t P_RandomFixedD(const char *rfile, INT32 rline);
UINT8 P_RandomByteD(const char *rfile, INT32 rline);
INT32 P_RandomKeyD(const char *rfile, INT32 rline, INT32 a);
INT32 P_RandomRangeD(const char *rfile, INT32 rline, INT32 a, INT32 b);
#else
UINT8 P_Random(void);
INT32 P_SignedRandom(void);
INT32 P_RandomKey(INT32 a);
INT32 P_RandomRange(INT32 a, INT32 b);
fixed_t P_RandomFixed(void);
UINT8 P_RandomByte(void);
INT32 P_RandomKey(INT32 a);
INT32 P_RandomRange(INT32 a, INT32 b);
#endif
UINT8 P_RandomPeek(void);
// Macros for other functions
#define M_SignedRandom() ((INT32)M_RandomByte() - 128) // [-128, 127] signed byte, originally a
#define P_SignedRandom() ((INT32)P_RandomByte() - 128) // function of its own, moved to a macro
#define M_RandomChance(p) (M_RandomFixed() < p) // given fixed point probability, p, between 0 (0%)
#define P_RandomChance(p) (P_RandomFixed() < p) // and FRACUNIT (100%), returns true p% of the time
// Debugging
fixed_t P_RandomPeek(void);
// Working with the seed for PRNG
#ifdef DEBUGRANDOM

View file

@ -386,7 +386,7 @@ boolean P_CheckMissileRange(mobj_t *actor)
if (actor->type == MT_EGGMOBILE && dist > 160)
dist = 160;
if (P_Random() < dist)
if (P_RandomByte() < dist)
return false;
return true;
@ -486,7 +486,7 @@ static boolean P_TryWalk(mobj_t *actor)
{
if (!P_Move(actor, actor->info->speed))
return false;
actor->movecount = P_Random() & 15;
actor->movecount = P_RandomByte() & 15;
return true;
}
@ -539,7 +539,7 @@ void P_NewChaseDir(mobj_t *actor)
}
// try other directions
if (P_Random() > 200 || abs(deltay) > abs(deltax))
if (P_RandomChance(25*FRACUNIT/32) || abs(deltay) > abs(deltax))
{
tdir = d[1];
d[1] = d[2];
@ -577,7 +577,7 @@ void P_NewChaseDir(mobj_t *actor)
}
// randomly determine direction of search
if (P_Random() & 1)
if (P_RandomChance(FRACUNIT/2))
{
for (tdir = DI_EAST; tdir <= DI_SOUTHEAST; tdir++)
{
@ -632,7 +632,7 @@ boolean P_LookForPlayers(mobj_t *actor, boolean allaround, boolean tracer, fixed
// BP: first time init, this allow minimum lastlook changes
if (actor->lastlook < 0)
actor->lastlook = P_Random();
actor->lastlook = P_RandomByte();
actor->lastlook %= MAXPLAYERS;
@ -707,7 +707,7 @@ static boolean P_LookForShield(mobj_t *actor)
// BP: first time init, this allow minimum lastlook changes
if (actor->lastlook < 0)
actor->lastlook = P_Random();
actor->lastlook = P_RandomByte();
actor->lastlook %= MAXPLAYERS;
@ -2293,12 +2293,7 @@ void A_SkullAttack(mobj_t *actor)
if (locvar1 == 1)
actor->angle += ANGLE_180;
else if (locvar1 == 2)
{
if (P_Random() & 1)
actor->angle += ANGLE_90;
else
actor->angle -= ANGLE_90;
}
actor->angle += (P_RandomChance(FRACUNIT/2)) ? ANGLE_90 : -ANGLE_90;
an = actor->angle >> ANGLETOFINESHIFT;
@ -2398,9 +2393,9 @@ void A_BossScream(mobj_t *actor)
explodetype = (mobjtype_t)locvar2;
if (actor->eflags & MFE_VERTICALFLIP)
z = actor->z + actor->height - mobjinfo[explodetype].height - FixedMul((P_Random()<<(FRACBITS-2)) - 8*FRACUNIT, actor->scale);
z = actor->z + actor->height - mobjinfo[explodetype].height - FixedMul((P_RandomByte()<<(FRACBITS-2)) - 8*FRACUNIT, actor->scale);
else
z = actor->z + FixedMul((P_Random()<<(FRACBITS-2)) - 8*FRACUNIT, actor->scale);
z = actor->z + FixedMul((P_RandomByte()<<(FRACBITS-2)) - 8*FRACUNIT, actor->scale);
mo = P_SpawnMobj(x, y, z, explodetype);
if (actor->eflags & MFE_VERTICALFLIP)
@ -3461,7 +3456,7 @@ void A_BubbleSpawn(mobj_t *actor)
return; // don't make bubble!
}
prandom = P_Random();
prandom = P_RandomByte();
if (leveltime % (3*TICRATE) < 8)
bubble = P_SpawnMobj(actor->x, actor->y, actor->z + (actor->height / 2), MT_EXTRALARGEBUBBLE);
@ -3509,7 +3504,7 @@ void A_FanBubbleSpawn(mobj_t *actor)
return; // don't make bubble!
}
prandom = P_Random();
prandom = P_RandomByte();
if ((prandom & 0x7) == 0x7)
bubble = P_SpawnMobj(actor->x, actor->y, hz, MT_SMALLBUBBLE);
@ -3550,7 +3545,7 @@ void A_BubbleRise(mobj_t *actor)
// Move around slightly to make it look like it's bending around the water
if (!locvar1)
{
UINT8 prandom = P_Random();
UINT8 prandom = P_RandomByte();
if (!(prandom & 0x7)) // *****000
{
P_InstaThrust(actor, prandom & 0x70 ? actor->angle + ANGLE_90 : actor->angle,
@ -3833,7 +3828,7 @@ void A_ThrownRing(mobj_t *actor)
// first time init, this allow minimum lastlook changes
if (actor->lastlook < 0)
actor->lastlook = P_Random();
actor->lastlook = P_RandomByte();
actor->lastlook %= MAXPLAYERS;
@ -3913,7 +3908,7 @@ void A_SetSolidSteam(mobj_t *actor)
#endif
actor->flags &= ~MF_NOCLIP;
actor->flags |= MF_SOLID;
if (!(P_Random() & 7))
if (P_RandomChance(FRACUNIT/8))
{
if (actor->info->deathsound)
S_StartSound(actor, actor->info->deathsound); // Hiss!
@ -4055,7 +4050,7 @@ void A_JetChase(mobj_t *actor)
if (actor->reactiontime)
actor->reactiontime--;
if (P_Random() % 32 == 1)
if (P_RandomChance(FRACUNIT/32))
{
actor->momx = actor->momx / 2;
actor->momy = actor->momy / 2;
@ -4416,7 +4411,7 @@ void A_JetgThink(mobj_t *actor)
if (actor->target)
{
if (P_Random() <= 32 && !actor->reactiontime)
if (P_RandomChance(FRACUNIT/8) && !actor->reactiontime)
P_SetMobjState(actor, actor->info->missilestate);
else
A_JetChase (actor);
@ -4469,10 +4464,10 @@ void A_MouseThink(mobj_t *actor)
{
if (twodlevel || actor->flags2 & MF2_TWOD)
{
if (P_Random() & 1)
if (P_RandomChance(FRACUNIT/2))
actor->angle += ANGLE_180;
}
else if (P_Random() & 1)
else if (P_RandomChance(FRACUNIT/2))
actor->angle += ANGLE_90;
else
actor->angle -= ANGLE_90;
@ -4878,7 +4873,7 @@ void A_RockSpawn(mobj_t *actor)
type = MT_ROCKCRUMBLE1 + (sides[line->sidenum[0]].rowoffset >> FRACBITS);
if (line->flags & ML_NOCLIMB)
randomoomph = P_Random() * (FRACUNIT/32);
randomoomph = P_RandomByte() * (FRACUNIT/32);
else
randomoomph = 0;
@ -5172,7 +5167,7 @@ void A_CrawlaCommanderThink(mobj_t *actor)
if (locvar1)
{
if (actor->health < 2 && P_Random() < 2)
if (actor->health < 2 && P_RandomChance(FRACUNIT/128))
P_SpawnMissile(actor, actor->target, locvar1);
}
@ -5187,8 +5182,8 @@ void A_CrawlaCommanderThink(mobj_t *actor)
actor->threshold = 0;
// Roam around, somewhat in the player's direction.
actor->angle += (P_Random()<<10);
actor->angle -= (P_Random()<<10);
actor->angle += (P_RandomByte()<<10);
actor->angle -= (P_RandomByte()<<10);
if (actor->health > 1)
P_InstaThrust(actor, actor->angle, FixedMul(10*FRACUNIT, actor->scale));
@ -5204,7 +5199,7 @@ void A_CrawlaCommanderThink(mobj_t *actor)
actor->threshold = 1;
}
}
actor->reactiontime = 2*TICRATE + P_Random()/2;
actor->reactiontime = 2*TICRATE + P_RandomByte()/2;
}
if (actor->health == 1)
@ -5222,8 +5217,8 @@ void A_CrawlaCommanderThink(mobj_t *actor)
}
else
{
UINT8 prandom = P_Random();
actor->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y) + (P_Random() & 1 ? -prandom : +prandom);
UINT8 prandom = P_RandomByte();
actor->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y) + (P_RandomChance(FRACUNIT/2) ? -prandom : +prandom);
P_InstaThrust(actor, actor->angle, FixedDiv(FixedMul(locvar2, actor->scale), 3*FRACUNIT/2));
actor->momz = FixedMul(locvar2, actor->scale); // Bounce up in air
}
@ -5552,7 +5547,7 @@ void A_MixUp(mobj_t *actor)
{
if (counter > 255) // fail-safe to avoid endless loop
break;
prandom = P_Random();
prandom = P_RandomByte();
prandom %= numplayers; // I love modular arithmetic, don't you?
if (prandom) // Make sure it's not a useless mix
break;
@ -5701,7 +5696,7 @@ void A_RecyclePowers(mobj_t *actor)
{
UINT8 tempint;
i = j + ((P_Random() + leveltime) % (numplayers - j));
i = j + ((P_RandomByte() + leveltime) % (numplayers - j));
tempint = postscramble[j];
postscramble[j] = postscramble[i];
postscramble[i] = tempint;
@ -5814,7 +5809,7 @@ void A_Boss1Chase(mobj_t *actor)
{
if (actor->health > actor->info->damage)
{
if (P_Random() & 1)
if (P_RandomChance(FRACUNIT/2))
P_SetMobjState(actor, actor->info->missilestate);
else
P_SetMobjState(actor, actor->info->meleestate);
@ -5833,7 +5828,7 @@ void A_Boss1Chase(mobj_t *actor)
// ?
nomissile:
// possibly choose another target
if (multiplayer && P_Random() < 2)
if (multiplayer && P_RandomChance(FRACUNIT/128))
{
if (P_LookForPlayers(actor, true, false, 0))
return; // got a new target
@ -5871,7 +5866,7 @@ nomissile:
deltay = actor->target->y - actor->y;
actor->movedir = diags[((deltay < 0)<<1) + (deltax > 0)];
actor->movecount = P_Random() & 15;
actor->movecount = P_RandomByte() & 15;
}
}
@ -5897,13 +5892,13 @@ void A_Boss2Chase(mobj_t *actor)
// Startup randomness
if (actor->reactiontime <= -666)
actor->reactiontime = 2*TICRATE + P_Random();
actor->reactiontime = 2*TICRATE + P_RandomByte();
// When reactiontime hits zero, he will go the other way
if (--actor->reactiontime <= 0)
{
reverse = true;
actor->reactiontime = 2*TICRATE + P_Random();
actor->reactiontime = 2*TICRATE + P_RandomByte();
}
P_SetTarget(&actor->target, P_GetClosestAxis(actor));
@ -5990,12 +5985,12 @@ void A_Boss2Chase(mobj_t *actor)
if (actor->info->attacksound)
S_StartAttackSound(actor, actor->info->attacksound);
if (P_Random() & 1)
if (P_RandomChance(FRACUNIT/2))
{
goop->momx *= 2;
goop->momy *= 2;
}
else if (P_Random() > 128)
else if (P_RandomChance(129*FRACUNIT/256))
{
goop->momx *= 3;
goop->momy *= 3;
@ -6153,7 +6148,7 @@ void A_Boss7Chase(mobj_t *actor)
{
A_FaceTarget(actor);
P_SetMobjState(actor, S_BLACKEGG_SHOOT1);
actor->movecount = TICRATE + P_Random()/2;
actor->movecount = TICRATE + P_RandomByte()/2;
return;
}
@ -6162,7 +6157,7 @@ void A_Boss7Chase(mobj_t *actor)
if (actor->reactiontime <= 0 && actor->z == actor->floorz)
{
// Here, we'll call P_Random() and decide what kind of attack to do
// Here, we'll call P_RandomByte() and decide what kind of attack to do
switch(actor->threshold)
{
case 0: // Lob cannon balls
@ -6170,7 +6165,7 @@ void A_Boss7Chase(mobj_t *actor)
{
A_FaceTarget(actor);
P_SetMobjState(actor, actor->info->xdeathstate);
actor->movecount = 7*TICRATE + P_Random();
actor->movecount = 7*TICRATE + P_RandomByte();
break;
}
actor->threshold++;
@ -6180,9 +6175,9 @@ void A_Boss7Chase(mobj_t *actor)
P_SetMobjState(actor, S_BLACKEGG_SHOOT1);
if (actor->health > actor->info->damage)
actor->movecount = TICRATE + P_Random()/3;
actor->movecount = TICRATE + P_RandomByte()/3;
else
actor->movecount = TICRATE + P_Random()/2;
actor->movecount = TICRATE + P_RandomByte()/2;
break;
case 2: // Homing Missile
A_FaceTarget(actor);
@ -6266,8 +6261,8 @@ void A_Boss2PogoSFX(mobj_t *actor)
}
else
{
UINT8 prandom = P_Random();
actor->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y) + (P_Random() & 1 ? -prandom : +prandom);
UINT8 prandom = P_RandomByte();
actor->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y) + (P_RandomChance(FRACUNIT/2) ? -prandom : +prandom);
P_InstaThrust(actor, actor->angle, FixedMul(FixedMul(actor->info->speed,(locvar2)), actor->scale));
}
if (actor->info->activesound) S_StartSound(actor, actor->info->activesound);
@ -6307,10 +6302,10 @@ void A_Boss2PogoTarget(mobj_t *actor)
// Target hit, retreat!
if (actor->target->player->powers[pw_flashing] > TICRATE || actor->flags2 & MF2_FRET)
{
UINT8 prandom = P_Random();
UINT8 prandom = P_RandomByte();
actor->z++; // unstick from the floor
actor->momz = FixedMul(locvar1, actor->scale); // Bounce up in air
actor->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y) + (P_Random() & 1 ? -prandom : +prandom); // Pick a direction, and randomize it.
actor->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y) + (P_RandomChance(FRACUNIT/2) ? -prandom : +prandom); // Pick a direction, and randomize it.
P_InstaThrust(actor, actor->angle+ANGLE_180, FixedMul(FixedMul(actor->info->speed,(locvar2)), actor->scale)); // Move at wandering speed
}
// Try to land on top of the player.
@ -6347,10 +6342,10 @@ void A_Boss2PogoTarget(mobj_t *actor)
// Wander semi-randomly towards the player to get closer.
else
{
UINT8 prandom = P_Random();
UINT8 prandom = P_RandomByte();
actor->z++; // unstick from the floor
actor->momz = FixedMul(locvar1, actor->scale); // Bounce up in air
actor->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y) + (P_Random() & 1 ? -prandom : +prandom); // Pick a direction, and randomize it.
actor->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y) + (P_RandomChance(FRACUNIT/2) ? -prandom : +prandom); // Pick a direction, and randomize it.
P_InstaThrust(actor, actor->angle, FixedMul(FixedMul(actor->info->speed,(locvar2)), actor->scale)); // Move at wandering speed
}
// Boing!
@ -7084,7 +7079,7 @@ void A_SmokeTrailer(mobj_t *actor)
P_SetObjectMomZ(th, FRACUNIT, false);
th->destscale = actor->scale;
P_SetScale(th, actor->scale);
th->tics -= P_Random() & 3;
th->tics -= P_RandomByte() & 3;
if (th->tics < 1)
th->tics = 1;
}
@ -7183,7 +7178,7 @@ void A_ChangeAngleRelative(mobj_t *actor)
// rather than the ranges, so <0 and >360 work as possible values. -Red
INT32 locvar1 = var1;
INT32 locvar2 = var2;
//angle_t angle = (P_Random()+1)<<24;
//angle_t angle = (P_RandomByte()+1)<<24;
const fixed_t amin = locvar1*FRACUNIT;
const fixed_t amax = locvar2*FRACUNIT;
//const angle_t amin = FixedAngle(locvar1*FRACUNIT);
@ -7217,7 +7212,7 @@ void A_ChangeAngleAbsolute(mobj_t *actor)
{
INT32 locvar1 = var1;
INT32 locvar2 = var2;
//angle_t angle = (P_Random()+1)<<24;
//angle_t angle = (P_RandomByte()+1)<<24;
const fixed_t amin = locvar1*FRACUNIT;
const fixed_t amax = locvar2*FRACUNIT;
//const angle_t amin = FixedAngle(locvar1*FRACUNIT);
@ -7825,7 +7820,7 @@ void A_RandomState(mobj_t *actor)
return;
#endif
P_SetMobjState(actor, P_Random()&1 ? locvar1 : locvar2);
P_SetMobjState(actor, P_RandomChance(FRACUNIT/2) ? locvar1 : locvar2);
}
// Function: A_RandomStateRange
@ -8516,34 +8511,32 @@ void A_SearchForPlayers(mobj_t *actor)
// Function: A_CheckRandom
//
// Description: Calls a state by chance (around 1/var1).
// Description: Calls a state by chance.
//
// var1 = denominator (can't exceed 100)
// var1:
// lower 16 bits = denominator
// upper 16 bits = numerator (defaults to 1 if zero)
// var2 = state number
//
void A_CheckRandom(mobj_t *actor)
{
INT32 locvar1 = var1;
INT32 locvar2 = var2;
INT32 i, chance;
INT32 rndadd = 0;
fixed_t chance = FRACUNIT;
#ifdef HAVE_BLUA
if (LUA_CallAction("A_CheckRandom", actor))
return;
#endif
if ((locvar1 & 0xFFFF) == 0)
return;
if(locvar1 > 100)
locvar1 = 100;
// The PRNG doesn't suck anymore, OK?
if (locvar1 >> 16)
chance *= (locvar1 >> 16);
chance /= (locvar1 & 0xFFFF);
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i])
rndadd += abs((int)players[i].mo->x) + abs((int)players[i].mo->y) + abs((int)players[i].mo->z);
rndadd = rndadd % 10000; //additional component to enlarge random number
chance = (P_Random() + rndadd) % locvar1;
if (chance == 0)
if (P_RandomChance(chance))
P_SetMobjState(actor, locvar2);
}
@ -9890,7 +9883,7 @@ void A_BrakChase(mobj_t *actor)
S_StartSound(actor, (sfxenum_t)locvar2);
// make active sound
if (actor->type != MT_CYBRAKDEMON && actor->info->activesound && P_Random() < 3)
if (actor->type != MT_CYBRAKDEMON && actor->info->activesound && P_RandomChance(3*FRACUNIT/256))
{
S_StartSound(actor, actor->info->activesound);
}

View file

@ -1253,7 +1253,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
if (special->target && special->target->state == &states[S_BLACKEGG_SHOOT1])
{
if (special->target->health <= 2 && (P_Random() & 1))
if (special->target->health <= 2 && P_RandomChance(FRACUNIT/2))
P_SetMobjState(special->target, special->target->info->missilestate);
else
P_SetMobjState(special->target, special->target->info->raisestate);
@ -2203,29 +2203,17 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source)
default:
if (target->info->doomednum)
prandom = target->info->doomednum%5; // "Random" animal for new enemies.
else
prandom = P_RandomKey(5); // No placable object, just use a random number.
switch(prandom)
{
switch(target->info->doomednum%5)
{
default: item = MT_BUNNY; break;
case 1: item = MT_BIRD; break;
case 2: item = MT_MOUSE; break;
case 3: item = MT_COW; break;
case 4: item = MT_CHICKEN; break;
}
}
else
{
prandom = P_Random();
if (prandom < 51)
item = MT_BUNNY;
else if (prandom < 102)
item = MT_BIRD;
else if (prandom < 153)
item = MT_MOUSE;
else if (prandom < 204)
item = MT_COW;
else
item = MT_CHICKEN;
}
break;
}
@ -3103,7 +3091,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
// Killing dead. Just for kicks.
// Require source and inflictor be player. Don't hurt for firing rings.
if (cv_killingdead.value && (source && source->player) && (inflictor && inflictor->player) && P_Random() < 80)
if (cv_killingdead.value && (source && source->player) && (inflictor && inflictor->player) && P_RandomChance(5*FRACUNIT/16))
P_DamageMobj(source, target, target, 1);
// do the damage
@ -3617,7 +3605,7 @@ void P_PlayerFlagBurst(player_t *player, boolean toss)
P_InstaThrust(flag, player->mo->angle, FixedMul(6*FRACUNIT, player->mo->scale));
else
{
angle_t fa = P_Random()*FINEANGLES/256;
angle_t fa = P_RandomByte()*FINEANGLES/256;
flag->momx = FixedMul(FINECOSINE(fa), FixedMul(6*FRACUNIT, player->mo->scale));
if (!(twodlevel || (player->mo->flags2 & MF2_TWOD)))
flag->momy = FixedMul(FINESINE(fa), FixedMul(6*FRACUNIT, player->mo->scale));

View file

@ -51,7 +51,7 @@ void T_FireFlicker(fireflicker_t *flick)
if (--flick->count)
return;
amount = (INT16)((UINT8)(P_Random() & 3) * 16);
amount = (INT16)((UINT8)(P_RandomByte() & 3) * 16);
if (flick->sector->lightlevel - amount < flick->minlight)
flick->sector->lightlevel = (INT16)flick->minlight;
@ -235,7 +235,7 @@ strobe_t *P_SpawnAdjustableStrobeFlash(sector_t *minsector, sector_t *maxsector,
flash->minlight = 0;
if (!inSync)
flash->count = (P_Random() & 7) + 1;
flash->count = (P_RandomByte() & 7) + 1;
else
flash->count = 1;

View file

@ -652,9 +652,9 @@ void P_EmeraldManager(void)
break;
if (leveltime < TICRATE) // Start of map
spawnpoints[j]->threshold = 60*TICRATE + P_Random() * (TICRATE/5);
spawnpoints[j]->threshold = 60*TICRATE + P_RandomByte() * (TICRATE/5);
else
spawnpoints[j]->threshold = P_Random() * (TICRATE/5);
spawnpoints[j]->threshold = P_RandomByte() * (TICRATE/5);
break;
}
@ -683,26 +683,26 @@ void P_ExplodeMissile(mobj_t *mo)
explodemo = P_SpawnMobj(mo->x, mo->y, mo->z, MT_EXPLODE);
P_SetScale(explodemo, mo->scale);
explodemo->destscale = mo->destscale;
explodemo->momx += (P_Random() % 32) * FixedMul(FRACUNIT/8, explodemo->scale);
explodemo->momy += (P_Random() % 32) * FixedMul(FRACUNIT/8, explodemo->scale);
explodemo->momx += (P_RandomByte() % 32) * FixedMul(FRACUNIT/8, explodemo->scale);
explodemo->momy += (P_RandomByte() % 32) * FixedMul(FRACUNIT/8, explodemo->scale);
S_StartSound(explodemo, sfx_pop);
explodemo = P_SpawnMobj(mo->x, mo->y, mo->z, MT_EXPLODE);
P_SetScale(explodemo, mo->scale);
explodemo->destscale = mo->destscale;
explodemo->momx += (P_Random() % 64) * FixedMul(FRACUNIT/8, explodemo->scale);
explodemo->momy -= (P_Random() % 64) * FixedMul(FRACUNIT/8, explodemo->scale);
explodemo->momx += (P_RandomByte() % 64) * FixedMul(FRACUNIT/8, explodemo->scale);
explodemo->momy -= (P_RandomByte() % 64) * FixedMul(FRACUNIT/8, explodemo->scale);
S_StartSound(explodemo, sfx_dmpain);
explodemo = P_SpawnMobj(mo->x, mo->y, mo->z, MT_EXPLODE);
P_SetScale(explodemo, mo->scale);
explodemo->destscale = mo->destscale;
explodemo->momx -= (P_Random() % 128) * FixedMul(FRACUNIT/8, explodemo->scale);
explodemo->momy += (P_Random() % 128) * FixedMul(FRACUNIT/8, explodemo->scale);
explodemo->momx -= (P_RandomByte() % 128) * FixedMul(FRACUNIT/8, explodemo->scale);
explodemo->momy += (P_RandomByte() % 128) * FixedMul(FRACUNIT/8, explodemo->scale);
S_StartSound(explodemo, sfx_pop);
explodemo = P_SpawnMobj(mo->x, mo->y, mo->z, MT_EXPLODE);
P_SetScale(explodemo, mo->scale);
explodemo->destscale = mo->destscale;
explodemo->momx -= (P_Random() % 96) * FixedMul(FRACUNIT/8, explodemo->scale);
explodemo->momy -= (P_Random() % 96) * FixedMul(FRACUNIT/8, explodemo->scale);
explodemo->momx -= (P_RandomByte() % 96) * FixedMul(FRACUNIT/8, explodemo->scale);
explodemo->momy -= (P_RandomByte() % 96) * FixedMul(FRACUNIT/8, explodemo->scale);
S_StartSound(explodemo, sfx_cybdth);
// Hack: Release an animal.
@ -2405,12 +2405,12 @@ static boolean P_ZMovement(mobj_t *mo)
// If deafed, give the tumbleweed another random kick if it runs out of steam.
mom.z += P_MobjFlip(mo)*FixedMul(6*FRACUNIT, mo->scale);
if (P_Random() & 1)
if (P_RandomChance(FRACUNIT/2))
mom.x += FixedMul(6*FRACUNIT, mo->scale);
else
mom.x -= FixedMul(6*FRACUNIT, mo->scale);
if (P_Random() & 1)
if (P_RandomChance(FRACUNIT/2))
mom.y += FixedMul(6*FRACUNIT, mo->scale);
else
mom.y -= FixedMul(6*FRACUNIT, mo->scale);
@ -2886,7 +2886,7 @@ static boolean P_SceneryZMovement(mobj_t *mo)
for (i = 0; i < 4; ++i) // split into four
{
prandom = P_Random();
prandom = P_RandomByte();
explodemo = P_SpawnMobj(mo->x, mo->y, mo->z, MT_SMALLBUBBLE);
explodemo->momx += ((prandom & 0x0F) << (FRACBITS-2)) * (i & 2 ? -1 : 1);
explodemo->momy += ((prandom & 0xF0) << (FRACBITS-6)) * (i & 1 ? -1 : 1);
@ -3218,13 +3218,13 @@ void P_MobjCheckWater(mobj_t *mobj)
// Create tons of bubbles
for (i = 0; i < bubblecount; i++)
{
// P_Random()s are called individually to allow consistency
// P_RandomByte()s are called individually to allow consistency
// across various compilers, since the order of function calls
// in C is not part of the ANSI specification.
prandom[0] = P_Random();
prandom[1] = P_Random();
prandom[2] = P_Random();
prandom[3] = P_Random();
prandom[0] = P_RandomByte();
prandom[1] = P_RandomByte();
prandom[2] = P_RandomByte();
prandom[3] = P_RandomByte();
bubbletype = MT_SMALLBUBBLE;
if (!(prandom[0] & 0x3)) // medium bubble chance up to 64 from 32
@ -3826,7 +3826,7 @@ boolean P_BossTargetPlayer(mobj_t *actor, boolean closest)
// first time init, this allow minimum lastlook changes
if (actor->lastlook < 0)
actor->lastlook = P_Random();
actor->lastlook = P_RandomByte();
actor->lastlook &= PLAYERSMASK;
for( ; ; actor->lastlook = (actor->lastlook+1) & PLAYERSMASK)
@ -4707,7 +4707,7 @@ static void P_Boss7Thinker(mobj_t *mobj)
if (mobj->state == &states[S_BLACKEGG_STND] && mobj->tics == mobj->state->tics)
{
mobj->reactiontime += P_Random();
mobj->reactiontime += P_RandomByte();
if (mobj->health <= mobj->info->damage)
mobj->reactiontime /= 4;
@ -4901,7 +4901,7 @@ static void P_Boss7Thinker(mobj_t *mobj)
if (mobj->tracer && mobj->tracer->type == MT_BOSS3WAYPOINT
&& mobj->tracer->spawnpoint && (mobj->tracer->spawnpoint->options & 7) == waypointNum)
{
if (P_Random() & 1)
if (P_RandomChance(FRACUNIT/2))
waypointNum++;
else
waypointNum--;
@ -4913,7 +4913,7 @@ static void P_Boss7Thinker(mobj_t *mobj)
}
if (waypointNum == 0 && mobj->health <= mobj->info->damage)
waypointNum = 1 + (P_Random() & 1);
waypointNum = 1 + (P_RandomFixed() & 1);
// scan the thinkers to find
// the waypoint to use
@ -5013,7 +5013,7 @@ static void P_Boss7Thinker(mobj_t *mobj)
P_SetMobjState(mobj, mobj->info->spawnstate);
}
else if (mobj->state == &states[mobj->info->deathstate] && mobj->tics == mobj->state->tics)
S_StartSound(0, sfx_bedie1 + (P_Random() & 1));
S_StartSound(0, sfx_bedie1 + (P_RandomFixed() & 1));
}
@ -5440,7 +5440,7 @@ static void P_Boss9Thinker(mobj_t *mobj)
// An incoming attack is detected! What should we do?!
// Go into vector form!
mobj->movedir = ANGLE_11hh - FixedAngle(FixedMul(AngleFixed(ANGLE_11hh), FixedDiv((mobj->info->spawnhealth - mobj->health)<<FRACBITS, (mobj->info->spawnhealth-1)<<FRACBITS)));
if (P_Random()&1)
if (P_RandomChance(FRACUNIT/2))
mobj->movedir = InvAngle(mobj->movedir);
mobj->threshold = 6 + (FixedMul(24<<FRACBITS, FixedDiv((mobj->info->spawnhealth - mobj->health)<<FRACBITS, (mobj->info->spawnhealth-1)<<FRACBITS))>>FRACBITS);
if (mobj->info->activesound)
@ -6042,20 +6042,20 @@ static void P_KoopaThinker(mobj_t *koopa)
P_XYMovement(koopa);
if (P_Random() < 8 && koopa->z <= koopa->floorz)
if (P_RandomChance(FRACUNIT/32) && koopa->z <= koopa->floorz)
koopa->momz = FixedMul(5*FRACUNIT, koopa->scale);
if (koopa->z > koopa->floorz)
koopa->momz += FixedMul(FRACUNIT/4, koopa->scale);
if (P_Random() < 4)
if (P_RandomChance(FRACUNIT/64))
{
mobj_t *flame;
flame = P_SpawnMobj(koopa->x - koopa->radius + FixedMul(5*FRACUNIT, koopa->scale), koopa->y, koopa->z + (P_Random()<<(FRACBITS-2)), MT_KOOPAFLAME);
flame = P_SpawnMobj(koopa->x - koopa->radius + FixedMul(5*FRACUNIT, koopa->scale), koopa->y, koopa->z + (P_RandomByte()<<(FRACBITS-2)), MT_KOOPAFLAME);
flame->momx = -FixedMul(flame->info->speed, flame->scale);
S_StartSound(flame, sfx_koopfr);
}
else if (P_Random() > 250)
else if (P_RandomChance(5*FRACUNIT/256))
{
mobj_t *hammer;
hammer = P_SpawnMobj(koopa->x - koopa->radius, koopa->y, koopa->z + koopa->height, MT_HAMMER);
@ -6499,11 +6499,11 @@ void P_MobjThinker(mobj_t *mobj)
fixed_t ns;
mobj_t *mo2;
i = P_Random();
z = mobj->subsector->sector->floorheight + ((P_Random()&63)*FRACUNIT);
i = P_RandomByte();
z = mobj->subsector->sector->floorheight + ((P_RandomByte()&63)*FRACUNIT);
for (j = 0; j < 2; j++)
{
const angle_t fa = (P_Random()*FINEANGLES/16) & FINEMASK;
const angle_t fa = (P_RandomByte()*FINEANGLES/16) & FINEMASK;
ns = 64 * FRACUNIT;
x = mobj->x + FixedMul(FINESINE(fa),ns);
y = mobj->y + FixedMul(FINECOSINE(fa),ns);
@ -6513,7 +6513,7 @@ void P_MobjThinker(mobj_t *mobj)
mo2->momx = FixedMul(FINESINE(fa),ns);
mo2->momy = FixedMul(FINECOSINE(fa),ns);
i = P_Random();
i = P_RandomByte();
if (i % 5 == 0)
P_SpawnMobj(x, y, z, MT_CHICKEN);
@ -7999,7 +7999,7 @@ void P_SpawnPrecipitation(void)
continue;
rainmo = P_SpawnSnowMobj(x, y, height, MT_SNOWFLAKE);
mrand = M_Random();
mrand = M_RandomByte();
if (mrand < 64)
P_SetPrecipMobjState(rainmo, S_SNOW3);
else if (mrand < 144)
@ -9167,12 +9167,12 @@ ML_NOCLIMB : Direction not controllable
{
mobj->momz += FixedMul(16*FRACUNIT, mobj->scale);
if (P_Random() & 1)
if (P_RandomChance(FRACUNIT/2))
mobj->momx += FixedMul(16*FRACUNIT, mobj->scale);
else
mobj->momx -= FixedMul(16*FRACUNIT, mobj->scale);
if (P_Random() & 1)
if (P_RandomChance(FRACUNIT/2))
mobj->momy += FixedMul(16*FRACUNIT, mobj->scale);
else
mobj->momy -= FixedMul(16*FRACUNIT,mobj->scale);

View file

@ -2059,7 +2059,7 @@ void P_SwitchWeather(INT32 weathernum)
precipmobj = (precipmobj_t *)think;
precipmobj->flags = mobjinfo[MT_SNOWFLAKE].flags;
z = M_Random();
z = M_RandomByte();
if (z < 64)
z = 2;

View file

@ -363,7 +363,7 @@ static void P_DoAutobalanceTeams(void)
{
if (totalred > totalblue)
{
i = M_Random() % red;
i = M_RandomKey(red);
NetPacket.packet.newteam = 2;
NetPacket.packet.playernum = redarray[i];
NetPacket.packet.verification = true;
@ -375,7 +375,7 @@ static void P_DoAutobalanceTeams(void)
if (totalblue > totalred)
{
i = M_Random() % blue;
i = M_RandomKey(blue);
NetPacket.packet.newteam = 1;
NetPacket.packet.playernum = bluearray[i];
NetPacket.packet.verification = true;

View file

@ -2172,9 +2172,9 @@ static void P_DoBubbleBreath(player_t *player)
if (!(player->mo->eflags & MFE_UNDERWATER) || ((player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL && !(player->pflags & PF_NIGHTSMODE)) || player->spectator)
return;
if (!(P_Random() % 16))
if (P_RandomChance(FRACUNIT/16))
bubble = P_SpawnMobj(player->mo->x, player->mo->y, zh, MT_SMALLBUBBLE);
else if (!(P_Random() % 96))
else if (P_RandomChance(3*FRACUNIT/256))
bubble = P_SpawnMobj(player->mo->x, player->mo->y, zh, MT_MEDIUMBUBBLE);
if (bubble)
{
@ -6620,7 +6620,7 @@ static void P_MovePlayer(player_t *player)
// Little water sound while touching water - just a nicety.
if ((player->mo->eflags & MFE_TOUCHWATER) && !(player->mo->eflags & MFE_UNDERWATER) && !player->spectator)
{
if (P_Random() & 1 && leveltime % TICRATE == 0)
if (P_RandomChance(FRACUNIT/2) && leveltime % TICRATE == 0)
S_StartSound(player->mo, sfx_floush);
}
@ -8439,7 +8439,7 @@ static boolean P_SpectatorJoinGame(player_t *player)
else if (redscore > bluescore)
changeto = 2;
else
changeto = (P_Random() & 1) + 1;
changeto = (P_RandomFixed() & 1) + 1;
if (player->mo)
{
@ -8690,7 +8690,7 @@ void P_PlayerThink(player_t *player)
// Add some extra randomization.
if (cmd->forwardmove)
P_Random();
P_RandomFixed();
#ifdef PARANOIA
if (player->playerstate == PST_REBORN)

View file

@ -592,9 +592,13 @@ static void ST_drawDebugInfo(void)
if (cv_debug & DBG_RANDOMIZER) // randomizer testing
{
fixed_t peekres = P_RandomPeek();
peekres *= 10000; // Change from fixed point
peekres >>= FRACBITS; // to displayable decimal
V_DrawRightAlignedString(320, height - 16, V_MONOSPACE, va("Init: %08x", P_GetInitSeed()));
V_DrawRightAlignedString(320, height - 8, V_MONOSPACE, va("Seed: %08x", P_GetRandSeed()));
V_DrawRightAlignedString(320, height, V_MONOSPACE, va("== : %8d", P_RandomPeek()));
V_DrawRightAlignedString(320, height, V_MONOSPACE, va("== : .%04d", peekres));
height -= 32;
}

View file

@ -1991,7 +1991,7 @@ Unoptimized version
for (y = 0; y < height; y++)
{
if (M_Random() < 32)
if (M_RandomChance(FRACUNIT/8)) // 12.5%
heatshifter[y] = true;
}