-
Notifications
You must be signed in to change notification settings - Fork 141
Description
Reported by Bentwing on Discord
The reported behavior is that a burning Zombie moves toward the stairs 5 "steps" in the time it takes the player to go up, then back down the stairs.
This is difficult to reproduce, so the following analysis is based on reading the code, not reproducing the behavior seen.
ANALYSIS
When a monster is hunting the player, and the player leaves the level, the monster gains a new status STATUS_ENTERS_LEVEL_IN:
BrogueCE/src/brogue/RogueMain.c
Line 609 in 2e0ea9a
| monst->status[STATUS_ENTERS_LEVEL_IN] = clamp(mapToStairs[monst->loc.x][monst->loc.y] * monst->movementSpeed / 100 + 1, 1, 150); |
This status tracks the number of steps the monster will take while the player is on another level. In the normal case, the status will count down and the monster will enter the level:
Lines 1955 to 1956 in 2e0ea9a
| } else if (monst->status[STATUS_ENTERS_LEVEL_IN] == 1) { | |
| monsterEntersLevel(monst, n); |
If the player returns to the level before the monster makes it all the way to the stairs, monsters on that level are restored to their locations and states via restoreMosnter():
BrogueCE/src/brogue/Architect.c
Line 3501 in 2e0ea9a
| void restoreMonster(creature *monst, short **mapToStairs, short **mapToPit) { |
A monster that has STATUS_ENTERS_LEVEL_IN must be handled differently, since it will have traversed some distance while the player was away:
BrogueCE/src/brogue/Architect.c
Line 3510 in 2e0ea9a
| if (monst->status[STATUS_ENTERS_LEVEL_IN] > 0) { |
Once a new location is computed for the monster, the final placement location is chosen via getQualifyingPathLocNear(), which picks a legal location for the monster given a set of flags:
BrogueCE/src/brogue/Architect.c
Lines 3542 to 3543 in 2e0ea9a
| pos qualifiedPosition = getQualifyingPathLocNear((pos){ *x, *y }, true, T_DIVIDES_LEVEL & avoidedFlagsForMonster(&(monst->info)), 0, | |
| avoidedFlagsForMonster(&(monst->info)), (HAS_MONSTER | HAS_PLAYER | HAS_STAIRS | IS_IN_MACHINE), true); |
This is unproven, but I believe what is happening is the following:
- A burning zombie generates gas which is ignited around it. The zombie moves slowly, but the gas is generated quickly. So on any given turn, the zombie is often surrounded by a halo of 1-2 tiles of burning gas.
- Burning gas has the terrain flag
T_IS_FIRE. - The call to
getQualifyingPathLocNear()passes a set of flags returned fromavoidedFlagsForMonster() - Zombies are not immune to fire, so the flag set forces the selection of a tile which is NOT on fire.
- The closest tile to the desired location, which is not on fire, is several spaces closer to the player than what would be expected in normal gameplay.
POTENTIAL FIX:
Allow tiles which the monster would already be willing to step into (eg. monsters on fire will continue to walk through fire).