UCRP_TRACKHAZARD: Optimise implementation to not be 100 booleans

Much like player->availabilities, use a set of bits on UINT8.
This commit is contained in:
toaster 2023-10-16 18:04:23 +01:00
parent d4e3d8433d
commit f0d1813752
3 changed files with 51 additions and 18 deletions

View file

@ -402,7 +402,7 @@ struct roundconditions_t
boolean landmine_dunk; boolean landmine_dunk;
boolean hit_midair; boolean hit_midair;
boolean hittrackhazard[MAX_LAPS+1]; UINT8 hittrackhazard[((MAX_LAPS+1)/8) + 1];
mobjeflag_t wet_player; mobjeflag_t wet_player;

View file

@ -1630,27 +1630,57 @@ boolean M_CheckCondition(condition_t *cn, player_t *player)
if (player->laps <= (requiredlap - cn->requirement)) if (player->laps <= (requiredlap - cn->requirement))
return false; return false;
const boolean desired = (cn->requirement == 1); UINT8 requiredbit = 1<<(requiredlap & 7);
requiredlap /= 8;
if (cn->extrainfo1 == -1) if (cn->extrainfo1 == -1)
{ {
// Using cn->requirement as the first if (cn->requirement == 0)
// counted lap means that for conditions
// that require you to get hit every lap,
// that doesn't count POSITION -
// but if you can't get hit by a track
// hazard at all during the race,
// you're forbidden from getting hurt
// by a track hazard during POSITION.
for (; requiredlap >= cn->requirement; requiredlap--)
{ {
if (player->roundconditions.hittrackhazard[requiredlap] != desired) // The "don't get hit on any lap" check is trivial.
for (; requiredlap > 0; requiredlap--)
{
if (player->roundconditions.hittrackhazard[requiredlap] != 0)
return false; return false;
} }
return true; return (player->roundconditions.hittrackhazard[0] == 0);
} }
return (player->roundconditions.hittrackhazard[requiredlap] == desired); // The following is my attempt at a major optimisation.
// The naive version was MAX_LAP bools, which is ridiculous.
// Check the highest relevant byte for all necessary bits.
// We only do this if an == 0xFF/0xFE check wouldn't satisfy.
if (requiredbit != 7)
{
// Last bit MAYBE not needed, POSITION doesn't count.
const UINT8 finalbit = (requiredlap == 0) ? 1 : 0;
while (requiredbit != finalbit)
{
if (!(player->roundconditions.hittrackhazard[requiredlap] & requiredbit))
return false;
requiredbit /= 2;
}
if (requiredlap == 0)
return true;
requiredlap--;
}
// All bytes between the top and the bottom need to be checked for saturation.
for (; requiredlap > 0; requiredlap--)
{
if (player->roundconditions.hittrackhazard[requiredlap] != 0xFF)
return false;
}
// Last bit not needed, POSITION doesn't count.
return (player->roundconditions.hittrackhazard[0] == 0xFE);
}
return (!(player->roundconditions.hittrackhazard[requiredlap] & requiredbit) != (cn->requirement == 1));
} }
case UCRP_WETPLAYER: case UCRP_WETPLAYER:

View file

@ -2632,12 +2632,15 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
} }
else if (!(inflictor && inflictor->player) else if (!(inflictor && inflictor->player)
&& player->laps <= numlaps && player->laps <= numlaps
&& damagetype != DMG_DEATHPIT && damagetype != DMG_DEATHPIT)
&& player->roundconditions.hittrackhazard[player->laps] == false)
{ {
player->roundconditions.hittrackhazard[player->laps] = true; const UINT8 requiredbit = 1<<(player->laps & 7);
if (!(player->roundconditions.hittrackhazard[player->laps/8] & requiredbit))
{
player->roundconditions.hittrackhazard[player->laps/8] |= requiredbit;
player->roundconditions.checkthisframe = true; player->roundconditions.checkthisframe = true;
} }
}
// Instant-Death // Instant-Death
if ((damagetype & DMG_DEATHMASK)) if ((damagetype & DMG_DEATHMASK))