shithub: choc

Download patch

ref: eccc7950039820344a10a3a330ea39637c301370
parent: d3c8f7316df2491ce3bb1244f22defdb745cc418
author: Jonathan Dowland <jon+github@alcopop.org>
date: Thu Jul 21 03:49:55 EDT 2016

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

--- a/src/doom/m_random.c
+++ b/src/doom/m_random.c
@@ -63,3 +63,10 @@
 {
     rndindex = prndindex = 0;
 }
+
+// inspired by the same routine in Eternity, thanks haleyjd
+int P_SubRandom (void)
+{
+    int r = P_Random();
+    return r - P_Random();
+}
--- 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 @@
 // Fix randoms for demos.
 void M_ClearRandom (void);
 
+// Defined version of P_Random() - P_Random()
+int P_SubRandom (void);
 
 #endif
--- a/src/doom/p_enemy.c
+++ b/src/doom/p_enemy.c
@@ -777,7 +777,7 @@
 				    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 @@
     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 @@
 
     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 @@
     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 @@
     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);
--- a/src/doom/p_map.c
+++ b/src/doom/p_map.c
@@ -1351,8 +1351,8 @@
 			  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)	
--- a/src/doom/p_mobj.c
+++ b/src/doom/p_mobj.c
@@ -867,7 +867,7 @@
 {
     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 @@
 {
     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 @@
 
     // fuzzy player
     if (dest->flags & MF_SHADOW)
-	an += (P_Random()-P_Random())<<20;	
+	an += P_SubRandom() << 20;
 
     th->angle = an;
     an >>= ANGLETOFINESHIFT;
--- a/src/doom/p_pspr.c
+++ b/src/doom/p_pspr.c
@@ -470,7 +470,7 @@
 	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 @@
 
     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 @@
     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 @@
     {
 	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);
     }
 }
 
--- a/src/heretic/m_random.c
+++ b/src/heretic/m_random.c
@@ -68,3 +68,9 @@
     rndindex = prndindex = 0;
 }
 
+// inspired by the same routine in Eternity, thanks haleyjd
+int P_SubRandom (void)
+{
+    int r = P_Random();
+    return r - P_Random();
+}
--- a/src/heretic/m_random.h
+++ b/src/heretic/m_random.h
@@ -30,5 +30,8 @@
 
 extern int rndindex;
 
+// Defined version of P_Random() - P_Random()
+int P_SubRandom (void);
+
 #endif // HERETIC_M_RANDOM_H
 
--- a/src/heretic/p_enemy.c
+++ b/src/heretic/p_enemy.c
@@ -813,7 +813,7 @@
                                    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_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 @@
     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 @@
 {
     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 @@
         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 @@
     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_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 @@
     }
     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 @@
         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_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_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 @@
     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;
--- a/src/heretic/p_inter.c
+++ b/src/heretic/p_inter.c
@@ -988,9 +988,9 @@
 {
     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();
--- a/src/heretic/p_map.c
+++ b/src/heretic/p_map.c
@@ -1656,8 +1656,8 @@
         // 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)   
--- a/src/heretic/p_mobj.c
+++ b/src/heretic/p_mobj.c
@@ -1192,7 +1192,7 @@
 {
     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 @@
 {
 	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 @@
 
     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 @@
     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 @@
             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 @@
             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 @@
     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;
--- a/src/heretic/p_pspr.c
+++ b/src/heretic/p_pspr.c
@@ -896,7 +896,7 @@
 
     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 @@
     // 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 @@
     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 @@
     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 @@
     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 @@
     }
     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,7 +1773,7 @@
     {
         damage = HITDICE(2);
         dist = 4 * MELEERANGE;
-        angle += (P_Random() - P_Random()) << 17;
+        angle += P_SubRandom() << 17;
         PuffType = MT_GAUNTLETPUFF2;
     }
     else
@@ -1780,7 +1780,7 @@
     {
         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);
--- a/src/heretic/p_user.c
+++ b/src/heretic/p_user.c
@@ -421,7 +421,7 @@
     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
--- a/src/hexen/a_action.c
+++ b/src/hexen/a_action.c
@@ -126,11 +126,14 @@
 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 @@
         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 @@
         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 @@
     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 @@
         // 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 @@
     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 @@
 {
     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])
--- a/src/hexen/m_random.c
+++ b/src/hexen/m_random.c
@@ -72,3 +72,9 @@
     rndindex = prndindex = 0;
 }
 
+// inspired by the same routine in Eternity, thanks haleyjd
+int P_SubRandom (void)
+{
+    int r = P_Random();
+    return r - P_Random();
+}
--- a/src/hexen/m_random.h
+++ b/src/hexen/m_random.h
@@ -30,5 +30,8 @@
 
 extern int rndindex;
 
+// Defined version of P_Random() - P_Random()
+int P_SubRandom (void);
+
 #endif // HEXEN_M_RANDOM_H
 
--- a/src/hexen/p_enemy.c
+++ b/src/hexen/p_enemy.c
@@ -820,7 +820,7 @@
                                    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_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 @@
 	}
 	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 @@
     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_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 @@
         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 @@
         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,6 +2785,7 @@
 void A_BishopPainBlur(mobj_t * actor)
 {
     mobj_t *mo;
+    int r1,r2,r3;
 
     if (P_Random() < 64)
     {
@@ -2785,9 +2792,14 @@
         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 @@
 {
     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_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_FreezeDeathChunks(mobj_t * actor)
 {
     int i;
+    int r1,r2,r3;
     mobj_t *mo;
 
     if (actor->momx || actor->momy || actor->momz)
@@ -4843,35 +4861,41 @@
 
     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 @@
                          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;
--- a/src/hexen/p_map.c
+++ b/src/hexen/p_map.c
@@ -2277,8 +2277,8 @@
         {
             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;
         }
     }
 
--- a/src/hexen/p_mobj.c
+++ b/src/hexen/p_mobj.c
@@ -1755,7 +1755,7 @@
 {
     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 @@
 {
 	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 @@
 
     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 @@
     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 @@
             {
                 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 @@
                 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 @@
     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 @@
     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 @@
     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;
--- a/src/hexen/p_pspr.c
+++ b/src/hexen/p_pspr.c
@@ -861,12 +861,16 @@
 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 @@
 {
     mobj_t *mo;
     fixed_t deltaZ;
+    int r1,r2;
 
     A_LightningClip(actor);
 
@@ -996,8 +1001,10 @@
     {
         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 @@
     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 @@
 	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 @@
 {
     int j;
     int i;
+    int r;
     mobj_t *mo;
     mobj_t *tail, *next;
 
@@ -1873,8 +1883,9 @@
                 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;