Demon speed bug


Demon speed bug demonstration

The demon speed bug is an oversight in the interaction of the Nightmare! skill level (or -fast parameter) and the savegame loading code. It can result in extremely slow demons that seem frozen in place, or in extremely fast demons that will freeze the entire game.


The demon has the duration of its states (other than spawn/idle, death and resurrection sequence) halved in nightmare mode. This makes it all-around faster and more aggressive, since it will move and attack twice as often in the same duration.

This effect is obtained by overwriting the state table in memory, halving the duration of each concerned state when starting a nightmare game. To prevent halving again and again until the demon is infinitely fast by starting a new game, a check is first made to verify that the skill level chosen previously (and stored in the gameskill variable) is not also nightmare. Inversely, if the previous skill level was nightmare but a new game is started that is at a lower difficulty, then the demon states durations are doubled to restore them to the normal value.

The bug comes from the fact that when a game is loaded, the gameskill variable is overwritten with the value of the saved skill level before the check to see if the state lengths have to be changed is made. Therefore, when loading a nightmare save, it will seem to the relevant part of the code that the previous game was already in nightmare, and inversely when loading a non-nightmare save, it will seem that the previous game was already not in nightmare. As a result, no changes are effected.

Therefore, it is possible to load a nightmare save game (therefore setting gameskill to nightmare without changing the demon speed), then starting a new game at another skill level to double the state length, resulting in a demon that becomes increasingly slow. The geometrical growth of the state duration can result in a demon that is practically frozen in place: for example, doubling ten times is the same as multiplying by over a thousand (2^10=1024), resulting in a chase state lasting about a full minute instead of 2/35th of a second (2048/35 ~= 58.51).

Inversely, if is possible by loading a normal save and starting a nightmare game repeatedly to halve these lengths, making demons faster and faster. Of particular interest is the chase state sequence (S_SARG_RUN1 to S_SARG_RUN8), where each of the individual states that comprise it lasts only two tics. After two halving, their duration is reduced to zero, possibly resulting in an infinite loop as the whole sequence can be looped an infinite amount of times in a single tic. (This is bound to happen if the demon is awake, but cannot reach the player, for example because a door has not finished opening. Being unable to start attacking, it will continue to chase forever without any delay allowing the game to process anything else.)


Several approaches can be used to prevent the bug. The simplest would be to change the save loading code so that it writes the loaded skill level in d_skill instead of gameskill, as happens when starting a new game from the menu. Boom instead decided to use an additional variable to keep track of whether the previous game was in nightmare mode. ZDoom prefers to halve each demon mobj's countdown for the next state in the relevant condition, achieving the same result without modifying the state table.