When the game is saved in any Doom engine game, monster and missile targets are not registered in the save game file, so any monsters which were active at the time of saving the game become dormant upon loading the game again. However, their location and angle when the game was saved is preserved.
Demonstrating the effect
Here is one way to see the anomalous behavior:
- Start a new game of Doom II (MAP01) on I'm too young to die.
- When the program loads, you will be looking at two Zombiemen with their backs to you. Ignore them for now; instead, walk west along the short corridor until you reach the balcony.
- Fire a bullet. Two grunting sounds will now indicate that you have attracted the Zombiemen's attention.
- Save the game.
- Load the game you just saved.
- (Optional) Stand still for a minute or two and listen. One would expect to hear the breathing noise made by Zombiemen as they walk around, but all is quiet.
- Carefully move back along the corridor to the starting point, keeping your eye on the opening to the north. As you move into each Zombiemen's line of sight, one of two things will happen:
- If he is facing you, he will become active and start moving again.
- If he is not facing you, you will see him standing still.
So, even though the Zombiemen woke up in step 3, they "fell asleep" during step 5.
Some distinguishable effects become evident because of the bug. The target of an incomplete Arch-vile attack, for example, is not preserved in a saved game because of the bug. This means loading a saved game that includes such a situation will render the Arch-vile attack harmless apart from the flame animation on the Arch-vile's ex-target, which is displayed all the way through (as the corresponding flame thing had been spawned there as an effect of the attack). Similarly, the target of a Revenant's missile is not stored in the save game data. Therefore, the missiles will no longer follow anything after it is restored.
The cause of this effect can be found in the Doom source code in p_saveg.c, in the functions P_ArchiveThinkers and P_UnarchiveThinkers.
In the Doom source code, the mobj_t structure is used to represent game objects such as monsters. Monster targets are stored in these structures as a field named target, which is a pointer to another mobj_t that the monster is currently targeting.
The Doom engine saves games by directly writing the raw structures used in memory to disk. When reloading saved games, pointers such as the target field are no longer valid (as the layout of structures within memory is different). When loading a game, the P_UnarchiveThinkers function deliberately sets targets on all map objects to NULL in order to avoid crashes due to accessing invalid areas of memory. A null target indicates that a monster has no current target, causing active monsters to return to sleep.
A number of source ports have fixed the save game exploit, producing save game files with monsters that will continue to hound their previous target upon reloading the saved game. Mocha Doom has the ability to restore monsters' targets from vanilla save files.