steed vs "no monster to remove"

Noticed whlie testing the steed-in-pit fix.  The EXTRA_SANITY_CHECKS
for remove_monster() are being tripped if riding hero has steed killed
out from under him because the steed is not on the map.  This started
out simple but got a bit complicated.  It seems to be sufficient but
I'm not very confident about it.

Being engulfed while mounted gave "placing monster over another?" due
to a change made along with EXTRA_SANITY_CHECKS but not conditional on
it.  (The change was to issue a warning about an actual problem which
was previously undiagnosed.)  I think bumping the engulfer off the map
in favor of the former steed only worked because some u.uswallow code
eventually used the hero's location to put the engulfer back.  I didn't
pursue that to try to figure what really happened, just prevent it.

The DISMOUNT_BONES handling was being executed even if the steed was
dead.  DISMOUNT_BONES only happens if the hero is dead.  Since I don't
know whether it's possible for dead hero and dead steed to happen at
the same time, move it inside the steed-not-dead block just in case.
This commit is contained in:
PatR
2018-11-29 12:15:14 -08:00
parent 4ab1c12f03
commit be327d9822
2 changed files with 40 additions and 13 deletions
+2
View File
@@ -246,6 +246,8 @@ ensure tmp_at() structures are initialized for all code paths when swallowed
trapped-vs-levitation/flying change broke Sting releasing hero from web trapped-vs-levitation/flying change broke Sting releasing hero from web
life-saving while poly'd and Unchanging wasn't restoring u.mh (HP as monster) life-saving while poly'd and Unchanging wasn't restoring u.mh (HP as monster)
change in searching stopped finding unseen monsters except hiders and eels change in searching stopped finding unseen monsters except hiders and eels
buliding with EXTRA_SANITY_CHECKS enabled would issue "no monster to remove"
warning if steed was killed out from under the hero
tty: turn off an optimization that is the suspected cause of Windows reported tty: turn off an optimization that is the suspected cause of Windows reported
partial status lines following level changes partial status lines following level changes
tty: ensure that current status fields are always copied to prior status tty: ensure that current status fields are always copied to prior status
+38 -13
View File
@@ -1,4 +1,4 @@
/* NetHack 3.6 steed.c $NHDT-Date: 1542765364 2018/11/21 01:56:04 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.57 $ */ /* NetHack 3.6 steed.c $NHDT-Date: 1543522486 2018/11/29 20:14:46 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.58 $ */
/* Copyright (c) Kevin Hugo, 1998-1999. */ /* Copyright (c) Kevin Hugo, 1998-1999. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -481,7 +481,7 @@ int reason; /* Player was thrown off etc. */
{ {
struct monst *mtmp; struct monst *mtmp;
struct obj *otmp; struct obj *otmp;
coord cc; coord cc, steedcc;
const char *verb = "fall"; const char *verb = "fall";
boolean repair_leg_damage = (Wounded_legs != 0L); boolean repair_leg_damage = (Wounded_legs != 0L);
unsigned save_utrap = u.utrap; unsigned save_utrap = u.utrap;
@@ -548,19 +548,44 @@ int reason; /* Player was thrown off etc. */
/* Release the steed and saddle */ /* Release the steed and saddle */
u.usteed = 0; u.usteed = 0;
u.ugallop = 0L; u.ugallop = 0L;
/*
/* Set player and steed's position. Try moving the player first * rloc(), rloc_to(), and monkilled()->mondead()->m_detach() all
unless we're in the midst of creating a bones file. */ * expect mtmp to be on the map or else have mtmp->mx be 0, but
if (reason == DISMOUNT_BONES) { * setting the latter to 0 here would interfere with dropping
/* move the steed to an adjacent square */ * the saddle. Prior to 3.6.2, being off the map didn't matter.
if (enexto(&cc, u.ux, u.uy, mtmp->data)) *
rloc_to(mtmp, cc.x, cc.y); * place_monster() expects mtmp to be alive and not be u.usteed.
else /* evidently no room nearby; move steed elsewhere */ *
(void) rloc(mtmp, FALSE); * Unfortunately, <u.ux,u.uy> (former steed's implicit location)
return; * might now be occupied by an engulfer, so we can't just put mtmp
* at that spot. An engulfer's previous spot will be unoccupied
* but we don't know where that was and even if we did, it might
* be hostile terrain.
*/
steedcc.x = u.ux, steedcc.y = u.uy;
if (m_at(u.ux, u.uy))
(void) enexto(&steedcc, u.ux, u.uy, mtmp->data);
if (!m_at(steedcc.x, steedcc.y)) {
if (mtmp->mhp < 1)
mtmp->mhp = 0; /* make sure it isn't negative */
mtmp->mhp++; /* force at least one hit point, possibly resurrecting */
place_monster(mtmp, steedcc.x, steedcc.y);
mtmp->mhp--; /* take the extra hit point away: cancel resurrection */
} else {
impossible("Dismounting: can't place former steed on map.");
} }
if (!DEADMONSTER(mtmp)) { if (!DEADMONSTER(mtmp)) {
place_monster(mtmp, u.ux, u.uy); /* Set player and steed's position. Try moving the player first
unless we're in the midst of creating a bones file. */
if (reason == DISMOUNT_BONES) {
/* move the steed to an adjacent square */
if (enexto(&cc, u.ux, u.uy, mtmp->data))
rloc_to(mtmp, cc.x, cc.y);
else /* evidently no room nearby; move steed elsewhere */
(void) rloc(mtmp, FALSE);
return;
}
if (!u.uswallow && !u.ustuck && have_spot) { if (!u.uswallow && !u.ustuck && have_spot) {
struct permonst *mdat = mtmp->data; struct permonst *mdat = mtmp->data;