foxygit / doom Log in
commit eccc7950039820344a10a3a330ea39637c301370
Author:     Jonathan Dowland <jon+github@alcopop.org>
AuthorDate: Thu Jul 21 07:49:55 2016 +0100
Commit:     Jonathan Dowland <jon+github@alcopop.org>
CommitDate: Thu Jul 21 18:49:06 2016 +0100

    Add P_SubRandom and fix P_Random ambiguities

    Doom/Heretic/Hexen frequently make use of a construct like

        P_Random() - P_Random()

    The order of evaluation of which is undefined in C. Watcom always evaluated
    left-to-right. Add a P_SubRandom routine inspired by the same solution
    implemented in Eternity that encapsulates this order of evaluation and use that
    in place of the above. Thanks @haleyjd

    Clean up other occurrences of undefined evaluation order with P_Random,
    including where the new P_SubRandom() would be used ambiguously (!), almost all
    of which was in the Heretic and Hexen code. (@haleyjd had already cleaned up
    Strife)

    Fixes #404
---
 src/doom/m_random.c    |  7 +++++
 src/doom/m_random.h    |  3 +-
 src/doom/p_enemy.c     | 10 +++---
 src/doom/p_map.c       |  4 +--
 src/doom/p_mobj.c      |  6 ++--
 src/doom/p_pspr.c      | 10 +++---
 src/heretic/m_random.c |  6 ++++
 src/heretic/m_random.h |  3 ++
 src/heretic/p_enemy.c  | 68 +++++++++++++++++++++++++----------------
 src/heretic/p_inter.c  |  6 ++--
 src/heretic/p_map.c    |  4 +--
 src/heretic/p_mobj.c   | 24 +++++++--------
 src/heretic/p_pspr.c   | 20 ++++++------
 src/heretic/p_user.c   |  2 +-
 src/hexen/a_action.c   | 45 +++++++++++++++------------
 src/hexen/m_random.c   |  6 ++++
 src/hexen/m_random.h   |  3 ++
 src/hexen/p_enemy.c    | 82 ++++++++++++++++++++++++++++++++------------------
 src/hexen/p_map.c      |  4 +--
 src/hexen/p_mobj.c     | 28 ++++++++---------
 src/hexen/p_pspr.c     | 27 ++++++++++++-----
 21 files changed, 226 insertions(+), 142 deletions(-)

diff --git a/src/doom/m_random.c b/src/doom/m_random.c
index 8e3b4e18..b4f59b33 100644
--- a/src/doom/m_random.c
+++ b/src/doom/m_random.c
@@ -63,3 +63,10 @@ void M_ClearRandom (void)
 {
     rndindex = prndindex = 0;
 }
+
+// inspired by the same routine in Eternity, thanks haleyjd
+int P_SubRandom (void)
+{
+    int r = P_Random();
+    return r - P_Random();
+}
diff --git a/src/doom/m_random.h b/src/doom/m_random.h
index aa6291ae..902691f1 100644
--- a/src/doom/m_random.h
+++ b/src/doom/m_random.h
@@ -24,7 +24,6 @@
 #include "doomtype.h"


-
 // Returns a number from 0 to 255,
 // from a lookup table.
 int M_Random (void);
@@ -35,5 +34,7 @@ int P_Random (void);
 // Fix randoms for demos.
 void M_ClearRandom (void);

+// Defined version of P_Random() - P_Random()
+int P_SubRandom (void);

 #endif
diff --git a/src/doom/p_enemy.c b/src/doom/p_enemy.c
index 8980ff24..49e30b49 100644
--- a/src/doom/p_enemy.c
+++ b/src/doom/p_enemy.c
@@ -777,7 +777,7 @@ void A_FaceTarget (mobj_t* actor)
 				    actor->target->y);

     if (actor->target->flags & MF_SHADOW)
-	actor->angle += (P_Random()-P_Random())<<21;
+	actor->angle += P_SubRandom() << 21;
 }


@@ -798,7 +798,7 @@ void A_PosAttack (mobj_t* actor)
     slope = P_AimLineAttack (actor, angle, MISSILERANGE);

     S_StartSound (actor, sfx_pistol);
-    angle += (P_Random()-P_Random())<<20;
+    angle += P_SubRandom() << 20;
     damage = ((P_Random()%5)+1)*3;
     P_LineAttack (actor, angle, MISSILERANGE, slope, damage);
 }
@@ -821,7 +821,7 @@ void A_SPosAttack (mobj_t* actor)

     for (i=0 ; i<3 ; i++)
     {
-	angle = bangle + ((P_Random()-P_Random())<<20);
+	angle = bangle + (P_SubRandom() << 20);
 	damage = ((P_Random()%5)+1)*3;
 	P_LineAttack (actor, angle, MISSILERANGE, slope, damage);
     }
@@ -842,7 +842,7 @@ void A_CPosAttack (mobj_t* actor)
     bangle = actor->angle;
     slope = P_AimLineAttack (actor, bangle, MISSILERANGE);

-    angle = bangle + ((P_Random()-P_Random())<<20);
+    angle = bangle + (P_SubRandom() << 20);
     damage = ((P_Random()%5)+1)*3;
     P_LineAttack (actor, angle, MISSILERANGE, slope, damage);
 }
@@ -1877,7 +1877,7 @@ void A_BrainExplode (mobj_t* mo)
     int		z;
     mobj_t*	th;

-    x = mo->x + (P_Random () - P_Random ())*2048;
+    x = mo->x +  P_SubRandom() * 2048;
     y = mo->y;
     z = 128 + P_Random()*2*FRACUNIT;
     th = P_SpawnMobj (x,y,z, MT_ROCKET);
diff --git a/src/doom/p_map.c b/src/doom/p_map.c
index 2dbabd01..005a8155 100644
--- a/src/doom/p_map.c
+++ b/src/doom/p_map.c
@@ -1351,8 +1351,8 @@ boolean PIT_ChangeSector (mobj_t*	thing)
 			  thing->y,
 			  thing->z + thing->height/2, MT_BLOOD);

-	mo->momx = (P_Random() - P_Random ())<<12;
-	mo->momy = (P_Random() - P_Random ())<<12;
+	mo->momx = P_SubRandom() << 12;
+	mo->momy = P_SubRandom() << 12;
     }

     // keep checking (crush other things)
diff --git a/src/doom/p_mobj.c b/src/doom/p_mobj.c
index 67874d48..3091de17 100644
--- a/src/doom/p_mobj.c
+++ b/src/doom/p_mobj.c
@@ -867,7 +867,7 @@ P_SpawnPuff
 {
     mobj_t*	th;

-    z += ((P_Random()-P_Random())<<10);
+    z += (P_SubRandom() << 10);

     th = P_SpawnMobj (x,y,z, MT_PUFF);
     th->momz = FRACUNIT;
@@ -895,7 +895,7 @@ P_SpawnBlood
 {
     mobj_t*	th;

-    z += ((P_Random()-P_Random())<<10);
+    z += (P_SubRandom() << 10);
     th = P_SpawnMobj (x,y,z, MT_BLOOD);
     th->momz = FRACUNIT*2;
     th->tics -= P_Random()&3;
@@ -980,7 +980,7 @@ P_SpawnMissile

     // fuzzy player
     if (dest->flags & MF_SHADOW)
-	an += (P_Random()-P_Random())<<20;
+	an += P_SubRandom() << 20;

     th->angle = an;
     an >>= ANGLETOFINESHIFT;
diff --git a/src/doom/p_pspr.c b/src/doom/p_pspr.c
index 274d35db..097cace2 100644
--- a/src/doom/p_pspr.c
+++ b/src/doom/p_pspr.c
@@ -470,7 +470,7 @@ A_Punch
 	damage *= 10;

     angle = player->mo->angle;
-    angle += (P_Random()-P_Random())<<18;
+    angle += P_SubRandom() << 18;
     slope = P_AimLineAttack (player->mo, angle, MELEERANGE);
     P_LineAttack (player->mo, angle, MELEERANGE, slope, damage);

@@ -500,7 +500,7 @@ A_Saw

     damage = 2*(P_Random ()%10+1);
     angle = player->mo->angle;
-    angle += (P_Random()-P_Random())<<18;
+    angle += P_SubRandom() << 18;

     // use meleerange + 1 se the puff doesn't skip the flash
     slope = P_AimLineAttack (player->mo, angle, MELEERANGE+1);
@@ -643,7 +643,7 @@ P_GunShot
     angle = mo->angle;

     if (!accurate)
-	angle += (P_Random()-P_Random())<<18;
+	angle += P_SubRandom() << 18;

     P_LineAttack (mo, angle, MISSILERANGE, bulletslope, damage);
 }
@@ -726,11 +726,11 @@ A_FireShotgun2
     {
 	damage = 5*(P_Random ()%3+1);
 	angle = player->mo->angle;
-	angle += (P_Random()-P_Random())<<ANGLETOFINESHIFT;
+	angle += P_SubRandom() << ANGLETOFINESHIFT;
 	P_LineAttack (player->mo,
 		      angle,
 		      MISSILERANGE,
-		      bulletslope + ((P_Random()-P_Random())<<5), damage);
+		      bulletslope + (P_SubRandom() << 5), damage);
     }
 }

diff --git a/src/heretic/m_random.c b/src/heretic/m_random.c
index 53b0f4df..7d535b84 100644
--- a/src/heretic/m_random.c
+++ b/src/heretic/m_random.c
@@ -68,3 +68,9 @@ void M_ClearRandom(void)
     rndindex = prndindex = 0;
 }

+// inspired by the same routine in Eternity, thanks haleyjd
+int P_SubRandom (void)
+{
+    int r = P_Random();
+    return r - P_Random();
+}
diff --git a/src/heretic/m_random.h b/src/heretic/m_random.h
index 817d7579..d7ec2d18 100644
--- a/src/heretic/m_random.h
+++ b/src/heretic/m_random.h
@@ -30,5 +30,8 @@ void M_ClearRandom(void);

 extern int rndindex;

+// Defined version of P_Random() - P_Random()
+int P_SubRandom (void);
+
 #endif // HERETIC_M_RANDOM_H

diff --git a/src/heretic/p_enemy.c b/src/heretic/p_enemy.c
index 55608c54..9c13145c 100644
--- a/src/heretic/p_enemy.c
+++ b/src/heretic/p_enemy.c
@@ -813,7 +813,7 @@ void A_FaceTarget(mobj_t * actor)
                                    actor->target->y);
     if (actor->target->flags & MF_SHADOW)
     {                           // Target is a ghost
-        actor->angle += (P_Random() - P_Random()) << 21;
+        actor->angle += P_SubRandom() << 21;
     }
 }

@@ -840,12 +840,16 @@ void A_Pain(mobj_t * actor)
 void A_DripBlood(mobj_t * actor)
 {
     mobj_t *mo;
+    int r1,r2;

-    mo = P_SpawnMobj(actor->x + ((P_Random() - P_Random()) << 11),
-                     actor->y + ((P_Random() - P_Random()) << 11), actor->z,
+    r1 = P_SubRandom();
+    r2 = P_SubRandom();
+
+    mo = P_SpawnMobj(actor->x + (r1 << 11),
+                     actor->y + (r2 << 11), actor->z,
                      MT_BLOOD);
-    mo->momx = (P_Random() - P_Random()) << 10;
-    mo->momy = (P_Random() - P_Random()) << 10;
+    mo->momx = P_SubRandom() << 10;
+    mo->momy = P_SubRandom() << 10;
     mo->flags2 |= MF2_LOGRAV;
 }

@@ -889,12 +893,12 @@ void A_ImpExplode(mobj_t * actor)
     mobj_t *mo;

     mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_IMPCHUNK1);
-    mo->momx = (P_Random() - P_Random()) << 10;
-    mo->momy = (P_Random() - P_Random()) << 10;
+    mo->momx = P_SubRandom() << 10;
+    mo->momy = P_SubRandom() << 10;
     mo->momz = 9 * FRACUNIT;
     mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_IMPCHUNK2);
-    mo->momx = (P_Random() - P_Random()) << 10;
-    mo->momy = (P_Random() - P_Random()) << 10;
+    mo->momx = P_SubRandom() << 10;
+    mo->momy = P_SubRandom() << 10;
     mo->momz = 9 * FRACUNIT;
     if (actor->special1.i == 666)
     {                           // Extreme death crash
@@ -912,9 +916,13 @@ void A_BeastPuff(mobj_t * actor)
 {
     if (P_Random() > 64)
     {
-        P_SpawnMobj(actor->x + ((P_Random() - P_Random()) << 10),
-                    actor->y + ((P_Random() - P_Random()) << 10),
-                    actor->z + ((P_Random() - P_Random()) << 10), MT_PUFFY);
+        int r1,r2,r3;
+        r1 = P_SubRandom();
+        r2 = P_SubRandom();
+        r3 = P_SubRandom();
+        P_SpawnMobj(actor->x + (r1 << 10),
+                    actor->y + (r2 << 10),
+                    actor->z + (r3 << 10), MT_PUFFY);
     }
 }

@@ -1179,8 +1187,8 @@ void A_Feathers(mobj_t * actor)
         mo = P_SpawnMobj(actor->x, actor->y, actor->z + 20 * FRACUNIT,
                          MT_FEATHER);
         mo->target = actor;
-        mo->momx = (P_Random() - P_Random()) << 8;
-        mo->momy = (P_Random() - P_Random()) << 8;
+        mo->momx = P_SubRandom() << 8;
+        mo->momy = P_SubRandom() << 8;
         mo->momz = FRACUNIT + (P_Random() << 9);
         P_SetMobjState(mo, S_FEATHER1 + (P_Random() & 7));
     }
@@ -1475,8 +1483,8 @@ void A_BlueSpark(mobj_t * actor)
     for (i = 0; i < 2; i++)
     {
         mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_SOR2FXSPARK);
-        mo->momx = (P_Random() - P_Random()) << 9;
-        mo->momy = (P_Random() - P_Random()) << 9;
+        mo->momx = P_SubRandom() << 9;
+        mo->momy = P_SubRandom() << 9;
         mo->momz = FRACUNIT + (P_Random() << 8);
     }
 }
@@ -1755,10 +1763,14 @@ void A_MinotaurAtk3(mobj_t * actor)
 void A_MntrFloorFire(mobj_t * actor)
 {
     mobj_t *mo;
+    int r1, r2;
+
+    r1 = P_SubRandom();
+    r2 = P_SubRandom();

     actor->z = actor->floorz;
-    mo = P_SpawnMobj(actor->x + ((P_Random() - P_Random()) << 10),
-                     actor->y + ((P_Random() - P_Random()) << 10), ONFLOORZ,
+    mo = P_SpawnMobj(actor->x + (r1 << 10),
+                     actor->y + (r2 << 10), ONFLOORZ,
                      MT_MNTRFX3);
     mo->target = actor->target;
     mo->momx = 1;               // Force block checking
@@ -2122,8 +2134,8 @@ void P_DropItem(mobj_t * source, mobjtype_t type, int special, int chance)
     }
     mo = P_SpawnMobj(source->x, source->y,
                      source->z + (source->height >> 1), type);
-    mo->momx = (P_Random() - P_Random()) << 8;
-    mo->momy = (P_Random() - P_Random()) << 8;
+    mo->momx = P_SubRandom() << 8;
+    mo->momy = P_SubRandom() << 8;
     mo->momz = FRACUNIT * 5 + (P_Random() << 10);
     mo->flags |= MF_DROPPED;
     mo->health = special;
@@ -2233,8 +2245,8 @@ void A_PodPain(mobj_t * actor)
         goo = P_SpawnMobj(actor->x, actor->y,
                           actor->z + 48 * FRACUNIT, MT_PODGOO);
         goo->target = actor;
-        goo->momx = (P_Random() - P_Random()) << 9;
-        goo->momy = (P_Random() - P_Random()) << 9;
+        goo->momx = P_SubRandom() << 9;
+        goo->momy = P_SubRandom() << 9;
         goo->momz = FRACUNIT / 2 + (P_Random() << 9);
     }
 }
@@ -2404,8 +2416,10 @@ void A_ESound(mobj_t * mo)
 void A_SpawnTeleGlitter(mobj_t * actor)
 {
     mobj_t *mo;
+    int r;

-    mo = P_SpawnMobj(actor->x + ((P_Random() & 31) - 16) * FRACUNIT,
+    r = P_Random();
+    mo = P_SpawnMobj(actor->x + ((r & 31) - 16) * FRACUNIT,
                      actor->y + ((P_Random() & 31) - 16) * FRACUNIT,
                      actor->subsector->sector->floorheight, MT_TELEGLITTER);
     mo->momz = FRACUNIT / 4;
@@ -2420,8 +2434,10 @@ void A_SpawnTeleGlitter(mobj_t * actor)
 void A_SpawnTeleGlitter2(mobj_t * actor)
 {
     mobj_t *mo;
+    int r;

-    mo = P_SpawnMobj(actor->x + ((P_Random() & 31) - 16) * FRACUNIT,
+    r = P_Random();
+    mo = P_SpawnMobj(actor->x + ((r & 31) - 16) * FRACUNIT,
                      actor->y + ((P_Random() & 31) - 16) * FRACUNIT,
                      actor->subsector->sector->floorheight, MT_TELEGLITTER2);
     mo->momz = FRACUNIT / 4;
@@ -2560,8 +2576,8 @@ void A_SkullPop(mobj_t * actor)
     mo = P_SpawnMobj(actor->x, actor->y, actor->z + 48 * FRACUNIT,
                      MT_BLOODYSKULL);
     //mo->target = actor;
-    mo->momx = (P_Random() - P_Random()) << 9;
-    mo->momy = (P_Random() - P_Random()) << 9;
+    mo->momx = P_SubRandom() << 9;
+    mo->momy = P_SubRandom() << 9;
     mo->momz = FRACUNIT * 2 + (P_Random() << 6);
     // Attach player mobj to bloody skull
     player = actor->player;
diff --git a/src/heretic/p_inter.c b/src/heretic/p_inter.c
index 81150f00..190bf85c 100644
--- a/src/heretic/p_inter.c
+++ b/src/heretic/p_inter.c
@@ -988,9 +988,9 @@ void P_TouchWhirlwind(mobj_t * target)
 {
     int randVal;

-    target->angle += (P_Random() - P_Random()) << 20;
-    target->momx += (P_Random() - P_Random()) << 10;
-    target->momy += (P_Random() - P_Random()) << 10;
+    target->angle += P_SubRandom() << 20;
+    target->momx += P_SubRandom() << 10;
+    target->momy += P_SubRandom() << 10;
     if (leveltime & 16 && !(target->flags2 & MF2_BOSS))
     {
         randVal = P_Random();
diff --git a/src/heretic/p_map.c b/src/heretic/p_map.c
index 6f1e64d7..8afcf860 100644
--- a/src/heretic/p_map.c
+++ b/src/heretic/p_map.c
@@ -1656,8 +1656,8 @@ boolean PIT_ChangeSector(mobj_t * thing)
         // spray blood in a random direction
         mo = P_SpawnMobj(thing->x, thing->y, thing->z + thing->height / 2,
                          MT_BLOOD);
-        mo->momx = (P_Random() - P_Random()) << 12;
-        mo->momy = (P_Random() - P_Random()) << 12;
+        mo->momx = P_SubRandom() << 12;
+        mo->momy = P_SubRandom() << 12;
     }

     return true;                // keep checking (crush other things)
diff --git a/src/heretic/p_mobj.c b/src/heretic/p_mobj.c
index 732a46bc..00e6a33c 100644
--- a/src/heretic/p_mobj.c
+++ b/src/heretic/p_mobj.c
@@ -1192,7 +1192,7 @@ void P_SpawnPuff(fixed_t x, fixed_t y, fixed_t z)
 {
     mobj_t *puff;

-    z += ((P_Random() - P_Random()) << 10);
+    z += (P_SubRandom() << 10);
     puff = P_SpawnMobj(x, y, z, PuffType);
     if (puff->info->attacksound)
     {
@@ -1225,7 +1225,7 @@ void P_SpawnBlood (fixed_t x, fixed_t y, fixed_t z, int damage)
 {
 	mobj_t  *th;

-	z += ((P_Random()-P_Random())<<10);
+	z += (P_SubRandom()<<10);
 	th = P_SpawnMobj (x,y,z, MT_BLOOD);
 	th->momz = FRACUNIT*2;
 	th->tics -= P_Random()&3;
@@ -1249,8 +1249,8 @@ void P_BloodSplatter(fixed_t x, fixed_t y, fixed_t z, mobj_t * originator)

     mo = P_SpawnMobj(x, y, z, MT_BLOODSPLATTER);
     mo->target = originator;
-    mo->momx = (P_Random() - P_Random()) << 9;
-    mo->momy = (P_Random() - P_Random()) << 9;
+    mo->momx = P_SubRandom() << 9;
+    mo->momy = P_SubRandom() << 9;
     mo->momz = FRACUNIT * 2;
 }

@@ -1265,9 +1265,9 @@ void P_RipperBlood(mobj_t * mo)
     mobj_t *th;
     fixed_t x, y, z;

-    x = mo->x + ((P_Random() - P_Random()) << 12);
-    y = mo->y + ((P_Random() - P_Random()) << 12);
-    z = mo->z + ((P_Random() - P_Random()) << 12);
+    x = mo->x + (P_SubRandom() << 12);
+    y = mo->y + (P_SubRandom() << 12);
+    z = mo->z + (P_SubRandom() << 12);
     th = P_SpawnMobj(x, y, z, MT_BLOOD);
     th->flags |= MF_NOGRAVITY;
     th->momx = mo->momx >> 1;
@@ -1317,8 +1317,8 @@ int P_HitFloor(mobj_t * thing)
             P_SpawnMobj(thing->x, thing->y, ONFLOORZ, MT_SPLASHBASE);
             mo = P_SpawnMobj(thing->x, thing->y, ONFLOORZ, MT_SPLASH);
             mo->target = thing;
-            mo->momx = (P_Random() - P_Random()) << 8;
-            mo->momy = (P_Random() - P_Random()) << 8;
+            mo->momx = P_SubRandom() << 8;
+            mo->momy = P_SubRandom() << 8;
             mo->momz = 2 * FRACUNIT + (P_Random() << 8);
             S_StartSound(mo, sfx_gloop);
             return (FLOOR_WATER);
@@ -1332,8 +1332,8 @@ int P_HitFloor(mobj_t * thing)
             P_SpawnMobj(thing->x, thing->y, ONFLOORZ, MT_SLUDGESPLASH);
             mo = P_SpawnMobj(thing->x, thing->y, ONFLOORZ, MT_SLUDGECHUNK);
             mo->target = thing;
-            mo->momx = (P_Random() - P_Random()) << 8;
-            mo->momy = (P_Random() - P_Random()) << 8;
+            mo->momx = P_SubRandom() << 8;
+            mo->momy = P_SubRandom() << 8;
             mo->momz = FRACUNIT + (P_Random() << 8);
             return (FLOOR_SLUDGE);
     }
@@ -1414,7 +1414,7 @@ mobj_t *P_SpawnMissile(mobj_t * source, mobj_t * dest, mobjtype_t type)
     an = R_PointToAngle2(source->x, source->y, dest->x, dest->y);
     if (dest->flags & MF_SHADOW)
     {                           // Invisible target
-        an += (P_Random() - P_Random()) << 21;
+        an += P_SubRandom() << 21;
     }
     th->angle = an;
     an >>= ANGLETOFINESHIFT;
diff --git a/src/heretic/p_pspr.c b/src/heretic/p_pspr.c
index 813dd6a2..7daeebc8 100644
--- a/src/heretic/p_pspr.c
+++ b/src/heretic/p_pspr.c
@@ -896,7 +896,7 @@ void A_StaffAttackPL1(player_t * player, pspdef_t * psp)

     damage = 5 + (P_Random() & 15);
     angle = player->mo->angle;
-    angle += (P_Random() - P_Random()) << 18;
+    angle += P_SubRandom() << 18;
     slope = P_AimLineAttack(player->mo, angle, MELEERANGE);
     PuffType = MT_STAFFPUFF;
     P_LineAttack(player->mo, angle, MELEERANGE, slope, damage);
@@ -925,7 +925,7 @@ void A_StaffAttackPL2(player_t * player, pspdef_t * psp)
     // P_inter.c:P_DamageMobj() handles target momentums
     damage = 18 + (P_Random() & 63);
     angle = player->mo->angle;
-    angle += (P_Random() - P_Random()) << 18;
+    angle += P_SubRandom() << 18;
     slope = P_AimLineAttack(player->mo, angle, MELEERANGE);
     PuffType = MT_STAFFPUFF2;
     P_LineAttack(player->mo, angle, MELEERANGE, slope, damage);
@@ -959,7 +959,7 @@ void A_FireBlasterPL1(player_t * player, pspdef_t * psp)
     angle = mo->angle;
     if (player->refire)
     {
-        angle += (P_Random() - P_Random()) << 18;
+        angle += P_SubRandom() << 18;
     }
     PuffType = MT_BLASTERPUFF1;
     P_LineAttack(mo, angle, MISSILERANGE, bulletslope, damage);
@@ -1005,7 +1005,7 @@ void A_FireGoldWandPL1(player_t * player, pspdef_t * psp)
     angle = mo->angle;
     if (player->refire)
     {
-        angle += (P_Random() - P_Random()) << 18;
+        angle += P_SubRandom() << 18;
     }
     PuffType = MT_GOLDWANDPUFF1;
     P_LineAttack(mo, angle, MISSILERANGE, bulletslope, damage);
@@ -1397,8 +1397,8 @@ void A_BoltSpark(mobj_t * bolt)
     if (P_Random() > 50)
     {
         spark = P_SpawnMobj(bolt->x, bolt->y, bolt->z, MT_CRBOWFX4);
-        spark->x += (P_Random() - P_Random()) << 10;
-        spark->y += (P_Random() - P_Random()) << 10;
+        spark->x += P_SubRandom() << 10;
+        spark->y += P_SubRandom() << 10;
     }
 }

@@ -1696,8 +1696,8 @@ void A_FirePhoenixPL2(player_t * player, pspdef_t * psp)
     }
     pmo = player->mo;
     angle = pmo->angle;
-    x = pmo->x + ((P_Random() - P_Random()) << 9);
-    y = pmo->y + ((P_Random() - P_Random()) << 9);
+    x = pmo->x + (P_SubRandom() << 9);
+    y = pmo->y + (P_SubRandom() << 9);
     z = pmo->z + 26 * FRACUNIT + ((player->lookdir) << FRACBITS) / 173;
     if (pmo->flags2 & MF2_FEETARECLIPPED)
     {
@@ -1773,14 +1773,14 @@ void A_GauntletAttack(player_t * player, pspdef_t * psp)
     {
         damage = HITDICE(2);
         dist = 4 * MELEERANGE;
-        angle += (P_Random() - P_Random()) << 17;
+        angle += P_SubRandom() << 17;
         PuffType = MT_GAUNTLETPUFF2;
     }
     else
     {
         damage = HITDICE(2);
         dist = MELEERANGE + 1;
-        angle += (P_Random() - P_Random()) << 18;
+        angle += P_SubRandom() << 18;
         PuffType = MT_GAUNTLETPUFF1;
     }
     slope = P_AimLineAttack(player->mo, angle, dist);
diff --git a/src/heretic/p_user.c b/src/heretic/p_user.c
index f4011eee..9c22d0b7 100644
--- a/src/heretic/p_user.c
+++ b/src/heretic/p_user.c
@@ -421,7 +421,7 @@ void P_ChickenPlayerThink(player_t * player)
     pmo = player->mo;
     if (!(pmo->momx + pmo->momy) && P_Random() < 160)
     {                           // Twitch view angle
-        pmo->angle += (P_Random() - P_Random()) << 19;
+        pmo->angle += P_SubRandom() << 19;
     }
     if ((pmo->z <= pmo->floorz) && (P_Random() < 32))
     {                           // Jump and noise
diff --git a/src/hexen/a_action.c b/src/hexen/a_action.c
index 1923ff70..737f72f6 100644
--- a/src/hexen/a_action.c
+++ b/src/hexen/a_action.c
@@ -126,11 +126,14 @@ int orbitTableY[256] = {
 void A_DripBlood(mobj_t *actor)
 {
 	mobj_t *mo;
+    int r;

-	mo = P_SpawnMobj(actor->x+((P_Random()-P_Random())<<11),
-		actor->y+((P_Random()-P_Random())<<11), actor->z, MT_BLOOD);
-	mo->momx = (P_Random()-P_Random())<<10;
-	mo->momy = (P_Random()-P_Random())<<10;
+    r = P_SubRandom();
+
+	mo = P_SpawnMobj(actor->x+(r<<11),
+		actor->y+(P_SubRandom()<<11), actor->z, MT_BLOOD);
+	mo->momx = P_SubRandom()<<10;
+	mo->momy = P_SubRandom()<<10;
 	mo->flags2 |= MF2_LOGRAV;
 }
 */
@@ -153,8 +156,8 @@ void A_PotteryExplode(mobj_t * actor)
         if (mo)
         {
             mo->momz = ((P_Random() & 7) + 5) * (3 * FRACUNIT / 4);
-            mo->momx = (P_Random() - P_Random()) << (FRACBITS - 6);
-            mo->momy = (P_Random() - P_Random()) << (FRACBITS - 6);
+            mo->momx = P_SubRandom() << (FRACBITS - 6);
+            mo->momy = P_SubRandom() << (FRACBITS - 6);
         }
     }
     S_StartSound(mo, SFX_POTTERY_EXPLODE);
@@ -265,8 +268,8 @@ void A_CorpseExplode(mobj_t * actor)
         if (mo)
         {
             mo->momz = ((P_Random() & 7) + 5) * (3 * FRACUNIT / 4);
-            mo->momx = (P_Random() - P_Random()) << (FRACBITS - 6);
-            mo->momy = (P_Random() - P_Random()) << (FRACBITS - 6);
+            mo->momx = P_SubRandom() << (FRACBITS - 6);
+            mo->momy = P_SubRandom() << (FRACBITS - 6);
         }
     }
     // Spawn a skull
@@ -275,8 +278,8 @@ void A_CorpseExplode(mobj_t * actor)
     if (mo)
     {
         mo->momz = ((P_Random() & 7) + 5) * (3 * FRACUNIT / 4);
-        mo->momx = (P_Random() - P_Random()) << (FRACBITS - 6);
-        mo->momy = (P_Random() - P_Random()) << (FRACBITS - 6);
+        mo->momx = P_SubRandom() << (FRACBITS - 6);
+        mo->momy = P_SubRandom() << (FRACBITS - 6);
         S_StartSound(mo, SFX_FIRED_DEATH);
     }
     P_RemoveMobj(actor);
@@ -300,8 +303,8 @@ void A_LeafSpawn(mobj_t * actor)
         // see ISO-IEC 9899-1999, [6.5.2.2.10]
         mobjtype_t type = MT_LEAF1 + (P_Random() & 1);
         fixed_t z = actor->z + (P_Random() << 14);
-        fixed_t y = actor->y + ((P_Random() - P_Random()) << 14);
-        fixed_t x = actor->x + ((P_Random() - P_Random()) << 14);
+        fixed_t y = actor->y + (P_SubRandom() << 14);
+        fixed_t x = actor->x + (P_SubRandom() << 14);

         mo = P_SpawnMobj(x, y, z, type);
         if (mo)
@@ -1040,8 +1043,8 @@ void P_SpawnDirt(mobj_t * actor, fixed_t radius)
     angle = P_Random() << 5;    // <<24 >>19
     x = actor->x + FixedMul(radius, finecosine[angle]);
     y = actor->y + FixedMul(radius, finesine[angle]);
-//      x = actor->x + ((P_Random()-P_Random())%radius)<<FRACBITS;
-//      y = actor->y + ((P_Random()-P_Random()<<FRACBITS)%radius);
+//      x = actor->x + (P_SubRandom()%radius)<<FRACBITS;
+//      y = actor->y + ((P_SubRandom()<<FRACBITS)%radius);
     z = actor->z + (P_Random() << 9) + FRACUNIT;
     switch (P_Random() % 6)
     {
@@ -1165,19 +1168,23 @@ void A_SoAExplode(mobj_t * actor)
 {
     mobj_t *mo;
     int i;
+    int r1,r2,r3;

     for (i = 0; i < 10; i++)
     {
-        mo = P_SpawnMobj(actor->x + ((P_Random() - 128) << 12),
-                         actor->y + ((P_Random() - 128) << 12),
-                         actor->z + (P_Random() * actor->height / 256),
+        r1 = P_Random();
+        r2 = P_Random();
+        r3 = P_Random();
+        mo = P_SpawnMobj(actor->x + ((r1 - 128) << 12),
+                         actor->y + ((r2 - 128) << 12),
+                         actor->z + (r3 * actor->height / 256),
                          MT_ZARMORCHUNK);
         P_SetMobjState(mo, mo->info->spawnstate + i);
         if (mo)
         {
             mo->momz = ((P_Random() & 7) + 5) * FRACUNIT;
-            mo->momx = (P_Random() - P_Random()) << (FRACBITS - 6);
-            mo->momy = (P_Random() - P_Random()) << (FRACBITS - 6);
+            mo->momx = P_SubRandom() << (FRACBITS - 6);
+            mo->momy = P_SubRandom() << (FRACBITS - 6);
         }
     }
     if (actor->args[0])
diff --git a/src/hexen/m_random.c b/src/hexen/m_random.c
index 43ad64ee..422b1a5d 100644
--- a/src/hexen/m_random.c
+++ b/src/hexen/m_random.c
@@ -72,3 +72,9 @@ void M_ClearRandom(void)
     rndindex = prndindex = 0;
 }

+// inspired by the same routine in Eternity, thanks haleyjd
+int P_SubRandom (void)
+{
+    int r = P_Random();
+    return r - P_Random();
+}
diff --git a/src/hexen/m_random.h b/src/hexen/m_random.h
index a0e8db09..2de76300 100644
--- a/src/hexen/m_random.h
+++ b/src/hexen/m_random.h
@@ -30,5 +30,8 @@ void M_ClearRandom(void);

 extern int rndindex;

+// Defined version of P_Random() - P_Random()
+int P_SubRandom (void);
+
 #endif // HEXEN_M_RANDOM_H

diff --git a/src/hexen/p_enemy.c b/src/hexen/p_enemy.c
index 38f3a2b5..212bf506 100644
--- a/src/hexen/p_enemy.c
+++ b/src/hexen/p_enemy.c
@@ -820,7 +820,7 @@ void A_FaceTarget(mobj_t * actor)
                                    actor->target->y);
     if (actor->target->flags & MF_SHADOW)
     {                           // Target is a ghost
-        actor->angle += (P_Random() - P_Random()) << 21;
+        actor->angle += P_SubRandom() << 21;
     }
 }

@@ -1481,10 +1481,13 @@ void A_MinotaurAtk3(mobj_t * actor)
 void A_MntrFloorFire(mobj_t * actor)
 {
     mobj_t *mo;
+    int r;
+
+    r = P_SubRandom();

     actor->z = actor->floorz;
-    mo = P_SpawnMobj(actor->x + ((P_Random() - P_Random()) << 10),
-                     actor->y + ((P_Random() - P_Random()) << 10), ONFLOORZ,
+    mo = P_SpawnMobj(actor->x + (r << 10),
+                     actor->y + (P_SubRandom() << 10), ONFLOORZ,
                      MT_MNTRFX3);
     mo->target = actor->target;
     mo->momx = 1;               // Force block checking
@@ -1597,8 +1600,8 @@ void P_DropItem(mobj_t *source, mobjtype_t type, int special, int chance)
 	}
 	mo = P_SpawnMobj(source->x, source->y,
 		source->z+(source->height>>1), type);
-	mo->momx = (P_Random()-P_Random())<<8;
-	mo->momy = (P_Random()-P_Random())<<8;
+	mo->momx = P_SubRandom()<<8;
+	mo->momy = P_SubRandom()<<8;
 	mo->momz = FRACUNIT*5+(P_Random()<<10);
 	mo->flags2 |= MF2_DROPPED;
 	mo->health = special;
@@ -1773,8 +1776,8 @@ void A_SkullPop(mobj_t * actor)
     mo = P_SpawnMobj(actor->x, actor->y, actor->z + 48 * FRACUNIT,
                      MT_BLOODYSKULL);
     //mo->target = actor;
-    mo->momx = (P_Random() - P_Random()) << 9;
-    mo->momy = (P_Random() - P_Random()) << 9;
+    mo->momx = P_SubRandom() << 9;
+    mo->momy = P_SubRandom() << 9;
     mo->momz = FRACUNIT * 2 + (P_Random() << 6);
     // Attach player mobj to bloody skull
     player = actor->player;
@@ -2408,8 +2411,9 @@ void A_SerpentHeadPop(mobj_t * actor)
 void A_SerpentSpawnGibs(mobj_t * actor)
 {
     mobj_t *mo;
+    int r = P_Random();

-    mo = P_SpawnMobj(actor->x + ((P_Random() - 128) << 12),
+    mo = P_SpawnMobj(actor->x + ((r - 128) << 12),
                      actor->y + ((P_Random() - 128) << 12),
                      actor->floorz + FRACUNIT, MT_SERPENT_GIB1);
     if (mo)
@@ -2418,7 +2422,8 @@ void A_SerpentSpawnGibs(mobj_t * actor)
         mo->momy = (P_Random() - 128) << 6;
         mo->floorclip = 6 * FRACUNIT;
     }
-    mo = P_SpawnMobj(actor->x + ((P_Random() - 128) << 12),
+    r = P_Random();
+    mo = P_SpawnMobj(actor->x + ((r - 128) << 12),
                      actor->y + ((P_Random() - 128) << 12),
                      actor->floorz + FRACUNIT, MT_SERPENT_GIB2);
     if (mo)
@@ -2427,7 +2432,8 @@ void A_SerpentSpawnGibs(mobj_t * actor)
         mo->momy = (P_Random() - 128) << 6;
         mo->floorclip = 6 * FRACUNIT;
     }
-    mo = P_SpawnMobj(actor->x + ((P_Random() - 128) << 12),
+    r = P_Random();
+    mo = P_SpawnMobj(actor->x + ((r - 128) << 12),
                      actor->y + ((P_Random() - 128) << 12),
                      actor->floorz + FRACUNIT, MT_SERPENT_GIB3);
     if (mo)
@@ -2779,15 +2785,21 @@ void A_BishopPuff(mobj_t * actor)
 void A_BishopPainBlur(mobj_t * actor)
 {
     mobj_t *mo;
+    int r1,r2,r3;

     if (P_Random() < 64)
     {
         P_SetMobjState(actor, S_BISHOP_BLUR1);
         return;
     }
-    mo = P_SpawnMobj(actor->x + ((P_Random() - P_Random()) << 12), actor->y
-                     + ((P_Random() - P_Random()) << 12),
-                     actor->z + ((P_Random() - P_Random()) << 11),
+
+    r1 = P_SubRandom();
+    r2 = P_SubRandom();
+    r3 = P_SubRandom();
+
+    mo = P_SpawnMobj(actor->x + (r1 << 12), actor->y
+                     + (r2 << 12),
+                     actor->z + (r3 << 11),
                      MT_BISHOPPAINBLUR);
     if (mo)
     {
@@ -3027,14 +3039,18 @@ void A_DragonFX2(mobj_t * actor)
 {
     mobj_t *mo;
     int i;
+    int r1,r2,r3;
     int delay;

     delay = 16 + (P_Random() >> 3);
     for (i = 1 + (P_Random() & 3); i; i--)
     {
-        mo = P_SpawnMobj(actor->x + ((P_Random() - 128) << 14),
-                         actor->y + ((P_Random() - 128) << 14),
-                         actor->z + ((P_Random() - 128) << 12),
+        r1 = P_Random();
+        r2 = P_Random();
+        r3 = P_Random();
+        mo = P_SpawnMobj(actor->x + ((r1 - 128) << 14),
+                         actor->y + ((r2 - 128) << 14),
+                         actor->z + ((r3 - 128) << 12),
                          MT_DRAGON_FX2);
         if (mo)
         {
@@ -4764,7 +4780,8 @@ void A_CheckFloor(mobj_t * actor)

 void A_FreezeDeath(mobj_t * actor)
 {
-    actor->tics = 75 + P_Random() + P_Random();
+    int r = P_Random();
+    actor->tics = 75 + r + P_Random();
     actor->flags |= MF_SOLID | MF_SHOOTABLE | MF_NOBLOOD;
     actor->flags2 |= MF2_PUSHABLE | MF2_TELESTOMP | MF2_PASSMOBJ | MF2_SLIDE;
     actor->height <<= 2;
@@ -4832,6 +4849,7 @@ void A_IceCheckHeadDone(mobj_t * actor)
 void A_FreezeDeathChunks(mobj_t * actor)
 {
     int i;
+    int r1,r2,r3;
     mobj_t *mo;

     if (actor->momx || actor->momy || actor->momz)
@@ -4843,35 +4861,41 @@ void A_FreezeDeathChunks(mobj_t * actor)

     for (i = 12 + (P_Random() & 15); i >= 0; i--)
     {
+        r1 = P_Random();
+        r2 = P_Random();
+        r3 = P_Random();
         mo = P_SpawnMobj(actor->x +
-                         (((P_Random() - 128) * actor->radius) >> 7),
+                         (((r1 - 128) * actor->radius) >> 7),
                          actor->y +
-                         (((P_Random() - 128) * actor->radius) >> 7),
-                         actor->z + (P_Random() * actor->height / 255),
+                         (((r2 - 128) * actor->radius) >> 7),
+                         actor->z + (r3 * actor->height / 255),
                          MT_ICECHUNK);
         P_SetMobjState(mo, mo->info->spawnstate + (P_Random() % 3));
         if (mo)
         {
             mo->momz = FixedDiv(mo->z - actor->z, actor->height) << 2;
-            mo->momx = (P_Random() - P_Random()) << (FRACBITS - 7);
-            mo->momy = (P_Random() - P_Random()) << (FRACBITS - 7);
+            mo->momx = P_SubRandom() << (FRACBITS - 7);
+            mo->momy = P_SubRandom() << (FRACBITS - 7);
             A_IceSetTics(mo);   // set a random tic wait
         }
     }
     for (i = 12 + (P_Random() & 15); i >= 0; i--)
     {
+        r1 = P_Random();
+        r2 = P_Random();
+        r3 = P_Random();
         mo = P_SpawnMobj(actor->x +
-                         (((P_Random() - 128) * actor->radius) >> 7),
+                         (((r1 - 128) * actor->radius) >> 7),
                          actor->y +
-                         (((P_Random() - 128) * actor->radius) >> 7),
-                         actor->z + (P_Random() * actor->height / 255),
+                         (((r2 - 128) * actor->radius) >> 7),
+                         actor->z + (r3 * actor->height / 255),
                          MT_ICECHUNK);
         P_SetMobjState(mo, mo->info->spawnstate + (P_Random() % 3));
         if (mo)
         {
             mo->momz = FixedDiv(mo->z - actor->z, actor->height) << 2;
-            mo->momx = (P_Random() - P_Random()) << (FRACBITS - 7);
-            mo->momy = (P_Random() - P_Random()) << (FRACBITS - 7);
+            mo->momx = P_SubRandom() << (FRACBITS - 7);
+            mo->momy = P_SubRandom() << (FRACBITS - 7);
             A_IceSetTics(mo);   // set a random tic wait
         }
     }
@@ -4881,8 +4905,8 @@ void A_FreezeDeathChunks(mobj_t * actor)
                          MT_ICECHUNK);
         P_SetMobjState(mo, S_ICECHUNK_HEAD);
         mo->momz = FixedDiv(mo->z - actor->z, actor->height) << 2;
-        mo->momx = (P_Random() - P_Random()) << (FRACBITS - 7);
-        mo->momy = (P_Random() - P_Random()) << (FRACBITS - 7);
+        mo->momx = P_SubRandom() << (FRACBITS - 7);
+        mo->momy = P_SubRandom() << (FRACBITS - 7);
         mo->flags2 |= MF2_ICEDAMAGE;    // used to force blue palette
         mo->flags2 &= ~MF2_FLOORCLIP;
         mo->player = actor->player;
diff --git a/src/hexen/p_map.c b/src/hexen/p_map.c
index b1c542ca..4fa3d5e9 100644
--- a/src/hexen/p_map.c
+++ b/src/hexen/p_map.c
@@ -2277,8 +2277,8 @@ boolean PIT_ChangeSector(mobj_t * thing)
         {
             mo = P_SpawnMobj(thing->x, thing->y, thing->z + thing->height / 2,
                              MT_BLOOD);
-            mo->momx = (P_Random() - P_Random()) << 12;
-            mo->momy = (P_Random() - P_Random()) << 12;
+            mo->momx = P_SubRandom() << 12;
+            mo->momy = P_SubRandom() << 12;
         }
     }

diff --git a/src/hexen/p_mobj.c b/src/hexen/p_mobj.c
index b868da8c..2ec15952 100644
--- a/src/hexen/p_mobj.c
+++ b/src/hexen/p_mobj.c
@@ -1755,7 +1755,7 @@ void P_SpawnPuff(fixed_t x, fixed_t y, fixed_t z)
 {
     mobj_t *puff;

-    z += ((P_Random() - P_Random()) << 10);
+    z += (P_SubRandom() << 10);
     puff = P_SpawnMobj(x, y, z, PuffType);
     if (linetarget && puff->info->seesound)
     {                           // Hit thing sound
@@ -1792,7 +1792,7 @@ void P_SpawnBlood (fixed_t x, fixed_t y, fixed_t z, int damage)
 {
 	mobj_t	*th;

-	z += ((P_Random()-P_Random())<<10);
+	z += (P_SubRandom()<<10);
 	th = P_SpawnMobj (x,y,z, MT_BLOOD);
 	th->momz = FRACUNIT*2;
 	th->tics -= P_Random()&3;
@@ -1816,8 +1816,8 @@ void P_BloodSplatter(fixed_t x, fixed_t y, fixed_t z, mobj_t * originator)

     mo = P_SpawnMobj(x, y, z, MT_BLOODSPLATTER);
     mo->target = originator;
-    mo->momx = (P_Random() - P_Random()) << 10;
-    mo->momy = (P_Random() - P_Random()) << 10;
+    mo->momx = P_SubRandom() << 10;
+    mo->momy = P_SubRandom() << 10;
     mo->momz = 3 * FRACUNIT;
 }

@@ -1847,9 +1847,9 @@ void P_RipperBlood(mobj_t * mo)
     mobj_t *th;
     fixed_t x, y, z;

-    x = mo->x + ((P_Random() - P_Random()) << 12);
-    y = mo->y + ((P_Random() - P_Random()) << 12);
-    z = mo->z + ((P_Random() - P_Random()) << 12);
+    x = mo->x + (P_SubRandom() << 12);
+    y = mo->y + (P_SubRandom() << 12);
+    z = mo->z + (P_SubRandom() << 12);
     th = P_SpawnMobj(x, y, z, MT_BLOOD);
 //      th->flags |= MF_NOGRAVITY;
     th->momx = mo->momx >> 1;
@@ -1935,8 +1935,8 @@ int P_HitFloor(mobj_t * thing)
             {
                 mo = P_SpawnMobj(thing->x, thing->y, ONFLOORZ, MT_SPLASH);
                 mo->target = thing;
-                mo->momx = (P_Random() - P_Random()) << 8;
-                mo->momy = (P_Random() - P_Random()) << 8;
+                mo->momx = P_SubRandom() << 8;
+                mo->momy = P_SubRandom() << 8;
                 mo->momz = 2 * FRACUNIT + (P_Random() << 8);
                 mo = P_SpawnMobj(thing->x, thing->y, ONFLOORZ, MT_SPLASHBASE);
                 if (thing->player)
@@ -1978,8 +1978,8 @@ int P_HitFloor(mobj_t * thing)
                 mo = P_SpawnMobj(thing->x, thing->y, ONFLOORZ,
                                  MT_SLUDGECHUNK);
                 mo->target = thing;
-                mo->momx = (P_Random() - P_Random()) << 8;
-                mo->momy = (P_Random() - P_Random()) << 8;
+                mo->momx = P_SubRandom() << 8;
+                mo->momy = P_SubRandom() << 8;
                 mo->momz = FRACUNIT + (P_Random() << 8);
                 mo = P_SpawnMobj(thing->x, thing->y, ONFLOORZ,
                                  MT_SLUDGESPLASH);
@@ -2066,7 +2066,7 @@ mobj_t *P_SpawnMissile(mobj_t * source, mobj_t * dest, mobjtype_t type)
     an = R_PointToAngle2(source->x, source->y, dest->x, dest->y);
     if (dest->flags & MF_SHADOW)
     {                           // Invisible target
-        an += (P_Random() - P_Random()) << 21;
+        an += P_SubRandom() << 21;
     }
     th->angle = an;
     an >>= ANGLETOFINESHIFT;
@@ -2108,7 +2108,7 @@ mobj_t *P_SpawnMissileXYZ(fixed_t x, fixed_t y, fixed_t z,
     an = R_PointToAngle2(source->x, source->y, dest->x, dest->y);
     if (dest->flags & MF_SHADOW)
     {                           // Invisible target
-        an += (P_Random() - P_Random()) << 21;
+        an += P_SubRandom() << 21;
     }
     th->angle = an;
     an >>= ANGLETOFINESHIFT;
@@ -2449,7 +2449,7 @@ mobj_t *P_SpawnKoraxMissile(fixed_t x, fixed_t y, fixed_t z,
     an = R_PointToAngle2(x, y, dest->x, dest->y);
     if (dest->flags & MF_SHADOW)
     {                           // Invisible target
-        an += (P_Random() - P_Random()) << 21;
+        an += P_SubRandom() << 21;
     }
     th->angle = an;
     an >>= ANGLETOFINESHIFT;
diff --git a/src/hexen/p_pspr.c b/src/hexen/p_pspr.c
index bc8947cd..8605e7b7 100644
--- a/src/hexen/p_pspr.c
+++ b/src/hexen/p_pspr.c
@@ -861,12 +861,16 @@ void A_FSwordAttack2(mobj_t * actor)
 void A_FSwordFlames(mobj_t * actor)
 {
     int i;
+    int r1,r2,r3;

     for (i = 1 + (P_Random() & 3); i; i--)
     {
-        P_SpawnMobj(actor->x + ((P_Random() - 128) << 12), actor->y
-                    + ((P_Random() - 128) << 12),
-                    actor->z + ((P_Random() - 128) << 11), MT_FSWORD_FLAME);
+        r1 = P_Random();
+        r2 = P_Random();
+        r3 = P_Random();
+        P_SpawnMobj(actor->x + ((r1 - 128) << 12), actor->y
+                    + ((r2 - 128) << 12),
+                    actor->z + ((r3 - 128) << 11), MT_FSWORD_FLAME);
     }
 }

@@ -979,6 +983,7 @@ void A_LightningZap(mobj_t * actor)
 {
     mobj_t *mo;
     fixed_t deltaZ;
+    int r1,r2;

     A_LightningClip(actor);

@@ -996,8 +1001,10 @@ void A_LightningZap(mobj_t * actor)
     {
         deltaZ = -10 * FRACUNIT;
     }
-    mo = P_SpawnMobj(actor->x + ((P_Random() - 128) * actor->radius / 256),
-                     actor->y + ((P_Random() - 128) * actor->radius / 256),
+    r1 = P_Random();
+    r2 = P_Random();
+    mo = P_SpawnMobj(actor->x + ((r1 - 128) * actor->radius / 256),
+                     actor->y + ((r2 - 128) * actor->radius / 256),
                      actor->z + deltaZ, MT_LIGHTNING_ZAP);
     if (mo)
     {
@@ -1388,8 +1395,10 @@ void A_FAxeAttack(player_t * player, pspdef_t * psp)
     int slope;
     int i;
     int useMana;
+    int r;

-    damage = 40 + (P_Random() & 15) + (P_Random() & 7);
+    r = P_Random();
+    damage = 40 + (r & 15) + (P_Random() & 7);
     power = 0;
     if (player->mana[MANA_1] > 0)
     {
@@ -1741,7 +1750,7 @@ void A_CFlameAttack(player_t *player, pspdef_t *psp)
 	angle = pmo->angle;
 	if(player->refire)
 	{
-		angle += (P_Random()-P_Random())<<17;
+		angle += P_SubRandom()<<17;
 	}
 	P_AimLineAttack(pmo, angle, CFLAMERANGE); // Correctly set linetarget
 	if(!linetarget)
@@ -1851,6 +1860,7 @@ void A_CHolyAttack2(mobj_t * actor)
 {
     int j;
     int i;
+    int r;
     mobj_t *mo;
     mobj_t *tail, *next;

@@ -1873,8 +1883,9 @@ void A_CHolyAttack2(mobj_t * actor)
                 mo->special2.i = (32 + (P_Random() & 7)) << 16;   // lower-left
                 break;
             case 3:
+                r = P_Random();
                 mo->special2.i =
-                    ((32 + (P_Random() & 7)) << 16) + 32 + (P_Random() & 7);
+                    ((32 + (r & 7)) << 16) + 32 + (P_Random() & 7);
                 break;
         }
         mo->z = actor->z;