From 4f781e78504aa54439e97c94eeea5fbb3e9acb6c Mon Sep 17 00:00:00 2001 From: PatR Date: Sun, 26 Jun 2022 12:22:09 -0700 Subject: [PATCH] fix #K3627 - impossible placing long worm at <0,0> When migrating, a long worm is removed from the map to take off the tail, then its head is put back to be treated like other monsters. If that occurred when being forced to re-migrate during failure to arrive from a prior migration, it wouldn't have valid coordinates and the place_monster attempt produced an impossible warning. (Other types of monsters don't get removed and put back so didn't trigger the problem.) The routine to format a monster when the data is suspect mistakenly thought it was dealing with a long worm tail because the monster didn't match level.monsters[0][0], so the warning inaccurately reported the problem as "placing long worm tail". --- doc/fixes3-7-0.txt | 4 ++++ src/do_name.c | 2 +- src/dog.c | 6 ++++-- src/mon.c | 6 ++++++ 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/doc/fixes3-7-0.txt b/doc/fixes3-7-0.txt index 6b1696bc8..f0805d252 100644 --- a/doc/fixes3-7-0.txt +++ b/doc/fixes3-7-0.txt @@ -937,6 +937,10 @@ the u.ustuck hierarchy is: swallowed by ustuck, hero poly'd into sticky form when a vampire gains levels and grows into a vampire lord, change its cham field (shapechanger base type) from vampire to vampire lord so that if it revives in base form it won't revert to plain vampire +a migrating long worm that couldn't arrive could be placed at <0,0> while + setting up another migration attempt to the level, triggering + impossible "trying to place long worm tail at <0,0> mstate:8 on level" + (message is confused; it should say "long worm" without tail) Fixes to 3.7.0-x Problems that Were Exposed Via git Repository diff --git a/src/do_name.c b/src/do_name.c index 8febc88fd..7dc882553 100644 --- a/src/do_name.c +++ b/src/do_name.c @@ -2186,7 +2186,7 @@ minimal_monnam(struct monst *mon, boolean ckloc) Sprintf(outbuf, "[Invalid mon->data %s >= %s]", fmt_ptr((genericptr_t) mon->data), fmt_ptr((genericptr_t) &mons[NUMMONS])); - } else if (ckloc && ptr == &mons[PM_LONG_WORM] + } else if (ckloc && ptr == &mons[PM_LONG_WORM] && mon->mx && g.level.monsters[mon->mx][mon->my] != mon) { Sprintf(outbuf, "%s <%d,%d>", pmname(&mons[PM_LONG_WORM_TAIL], Mgender(mon)), diff --git a/src/dog.c b/src/dog.c index ee8e635cc..d4be1a07d 100644 --- a/src/dog.c +++ b/src/dog.c @@ -609,8 +609,10 @@ mon_leave(struct monst *mtmp) more segments than can fit in that field gets truncated */ num_segs = min(cnt, MAX_NUM_WORMS - 1); wormgone(mtmp); - /* put the head back */ - place_monster(mtmp, mx, my); + /* put the head back; note: mtmp might not be on the map if this + is happening during a failed attempt to migrate to this level */ + if (mx) + place_monster(mtmp, mx, my); } return num_segs; diff --git a/src/mon.c b/src/mon.c index cfae1214e..6d781bad9 100644 --- a/src/mon.c +++ b/src/mon.c @@ -3293,6 +3293,12 @@ m_into_limbo(struct monst *mtmp) static void migrate_mon(struct monst *mtmp, xchar target_lev, xchar xyloc) { + if (!mtmp->mx) { + /* this was a failed arrival attempt from a prior migration; + force mtmp to temporarily have a valid location when starting + its new migration */ + mtmp->mx = u.ux, mtmp->my = u.uy; + } unstuck(mtmp); mdrop_special_objs(mtmp); migrate_to_level(mtmp, target_lev, xyloc, (coord *) 0);