fix #H7591 - migrating monsters vs full levels

During level change, when a monster from mydogs (monsters accompaying
hero, usually pets) couldn't be placed because the level was full, it
was set to migrate to that level (in order to get another chance to
arrive if hero left and returned).  The code sequence
 mon_arrive()-> mnexto()-> m_into_limbo()-> migrate_to_level()-> relmon()
tried to remove the monster from the map, but it wasn't necessarily on
the map (depending upon whether it couldn't arrive at all, or arrived
at the hero's spot and couldn't be moved out of the hero's way).  The
EXTRA_SANITY_CHECKS for remove_monster() issued impossible "no monster
to remove".  relmon() now checks whether monster is already off the map.

While investigating that, I discovered that pets set to re-migrate
to the same level to try again on hero's next visit didn't work at all.
migrating_mons gets processed after mydogs so moving something from
the latter to the former after arrival failure just resulted in
immediate second failure when the more general list was handled during
the hero's current arrival.  And failure to arrive from migrating_mons
would kill the monster instead of scheduling another attempt.

The sanest fix for that turned out to be to have all monsters who
can't arrive be put back on the migrating_mons list to try again upon
hero's next visit.  Pets still fail twice but are no longer discarded
during the second time, and now do arrive when hero leaves and comes
back provided he or she has opened up some space before leaving.  If
there's still no space on the next visit, monsters who can't arrive
then are scheduled to try again on the visit after that.

Recent fix for invalid corpses becomes moot.  Monsters aren't killed
during arrival failure so there are no resulting corpses to deal with.
This commit is contained in:
PatR
2018-11-24 01:45:09 -08:00
parent 531ccca7d9
commit cc5bb44a9a
5 changed files with 70 additions and 77 deletions

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 rm.h $NHDT-Date: 1432512776 2015/05/25 00:12:56 $ $NHDT-Branch: master $:$NHDT-Revision: 1.41 $ */
/* NetHack 3.6 rm.h $NHDT-Date: 1543052680 2018/11/24 09:44:40 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.59 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Pasi Kallinen, 2017. */
/* NetHack may be freely redistributed. See license for details. */
@@ -631,13 +631,17 @@ extern dlevel_t level; /* structure describing the current level */
(level.monsters[x][y] != (struct monst *) 0 \
&& (level.monsters[x][y])->mburied)
#ifdef EXTRA_SANITY_CHECKS
#define place_worm_seg(m, x, y) do { \
if (level.monsters[x][y] && level.monsters[x][y] != m) impossible("place_worm_seg over mon"); \
level.monsters[x][y] = m; \
#define place_worm_seg(m, x, y) \
do { \
if (level.monsters[x][y] && level.monsters[x][y] != m) \
impossible("place_worm_seg over mon"); \
level.monsters[x][y] = m; \
} while(0)
#define remove_monster(x, y) do { \
if (!level.monsters[x][y]) impossible("no monster to remove"); \
level.monsters[x][y] = (struct monst *) 0; \
#define remove_monster(x, y) \
do { \
if (!level.monsters[x][y]) \
impossible("no monster to remove"); \
level.monsters[x][y] = (struct monst *) 0; \
} while(0)
#else
#define place_worm_seg(m, x, y) level.monsters[x][y] = m