Fix some issues found with fuzz testing
authorPasi Kallinen <paxed@alt.org>
Wed, 7 Dec 2016 15:53:03 +0000 (17:53 +0200)
committerPasi Kallinen <paxed@alt.org>
Wed, 7 Dec 2016 15:53:08 +0000 (17:53 +0200)
Mostly to do with relocating monsters when the level is already full,
and unsticking a monster if it gets relocated.

include/extern.h
src/dog.c
src/mhitm.c
src/mon.c
src/wizard.c

index 300af5e06e1196e2ca3be9cadae46e02a5eed38b..3ab3e6ce4b399748564b28339c56867cac187a1b 100644 (file)
@@ -1351,6 +1351,7 @@ E void FDECL(unstuck, (struct monst *));
 E void FDECL(killed, (struct monst *));
 E void FDECL(xkilled, (struct monst *, int));
 E void FDECL(mon_to_stone, (struct monst *));
+E void FDECL(m_into_limbo, (struct monst *));
 E void FDECL(mnexto, (struct monst *));
 E void FDECL(maybe_mnexto, (struct monst *));
 E boolean FDECL(mnearto, (struct monst *, XCHAR_P, XCHAR_P, BOOLEAN_P));
index fba99840765372684993d38576b62e5201298fb8..0b9d2ae9fc9a1c86f8369d8a67c6d05d66ac1fd9 100644 (file)
--- a/src/dog.c
+++ b/src/dog.c
@@ -430,9 +430,10 @@ boolean with_you;
 
     mtmp->mx = 0; /*(already is 0)*/
     mtmp->my = xyflags;
-    if (xlocale)
-        (void) mnearto(mtmp, xlocale, ylocale, FALSE);
-    else {
+    if (xlocale) {
+        if (!mnearto(mtmp, xlocale, ylocale, FALSE))
+            goto fail_mon_placement;
+    } else {
         if (!rloc(mtmp, TRUE)) {
             /*
              * Failed to place migrating monster,
@@ -440,6 +441,7 @@ boolean with_you;
              * Dump the monster's cargo and leave the monster dead.
              */
             struct obj *obj;
+fail_mon_placement:
             while ((obj = mtmp->minvent) != 0) {
                 obj_extract_self(obj);
                 obj_no_longer_held(obj);
index 2b67b47b004be0e4c41460107be2f5bfdbba30d7..39407c3a851bcb895dcb53eeb67ae62096879eef 100644 (file)
@@ -744,6 +744,7 @@ register struct attack *mattk;
         if (cansee(dx, dy))
             pline("%s is regurgitated!", Monnam(mdef));
 
+        remove_monster(dx,dy);
         place_monster(magr, ax, ay);
         place_monster(mdef, dx, dy);
         newsym(ax, ay);
index f387655e786a92c40f7ca973d0504d514c4b344a..23ebcdb45c70b2c8826f5d02e12b4d4db8a9f211 100644 (file)
--- a/src/mon.c
+++ b/src/mon.c
@@ -2029,6 +2029,8 @@ struct monst *mdef;
     /* hero is thrown from his steed when it disappears */
     if (mdef == u.usteed)
         dismount_steed(DISMOUNT_GENERIC);
+    /* stuck to you? release */
+    unstuck(mdef);
     /* drop special items like the Amulet so that a dismissed Kop or nurse
        can't remove them from the game */
     mdrop_special_objs(mdef);
@@ -2449,6 +2451,16 @@ struct monst *mtmp;
     return TRUE;
 }
 
+/* drop monster into "limbo" - that is, migrate to the current level */
+void
+m_into_limbo(mtmp)
+struct monst *mtmp;
+{
+    unstuck(mtmp);
+    mdrop_special_objs(mtmp);
+    migrate_to_level(mtmp, ledger_no(&u.uz), MIGR_APPROX_XY, NULL);
+}
+
 /* make monster mtmp next to you (if possible);
    might place monst on far side of a wall or boulder */
 void
@@ -2465,7 +2477,11 @@ struct monst *mtmp;
         return;
     }
 
-    if (!enexto(&mm, u.ux, u.uy, mtmp->data))
+    if (!enexto(&mm, u.ux, u.uy, mtmp->data)) {
+        m_into_limbo(mtmp);
+        return;
+    }
+    if (!isok(mm.x, mm.y))
         return;
     rloc_to(mtmp, mm.x, mm.y);
     if (!in_mklev && (mtmp->mstrategy & STRAT_APPEARMSG)) {
@@ -2534,6 +2550,8 @@ boolean move_other; /* make sure mtmp gets to x, y! so move m_at(x, y) */
          */
         if (!enexto(&mm, newx, newy, mtmp->data))
             return FALSE;
+        if (!isok(mm.x,mm.y))
+            return FALSE;
         newx = mm.x;
         newy = mm.y;
     }
@@ -2545,12 +2563,10 @@ boolean move_other; /* make sure mtmp gets to x, y! so move m_at(x, y) */
         othermon->mx = othermon->my = 0;
         (void) mnearto(othermon, x, y, FALSE);
         if (othermon->mx == 0 && othermon->my == 0) {
-            /* reloc failed, dump monster into "limbo"
-               (aka migrate to current level) */
+            /* reloc failed */
             othermon->mx = oldx;
             othermon->my = oldy;
-            mdrop_special_objs(othermon);
-            migrate_to_level(othermon, ledger_no(&u.uz), MIGR_APPROX_XY, NULL);
+            m_into_limbo(othermon);
         }
     }
 
index 6ab8e57bd869c06ef03ff7486fcf0a5fa6e61c0c..3f58433c89646b1cc4bb6110005c4a1e0a1eeadc 100644 (file)
@@ -380,7 +380,10 @@ register struct monst *mtmp;
             if (!rn2(3 + mtmp->mhp / 10))
                 (void) rloc(mtmp, TRUE);
         } else if (sx && (mtmp->mx != sx || mtmp->my != sy)) {
-            (void) mnearto(mtmp, sx, sy, TRUE);
+            if (!mnearto(mtmp, sx, sy, TRUE)) {
+                m_into_limbo(mtmp);
+                return 0;
+            }
         }
         /* if you're not around, cast healing spells */
         if (distu(mtmp->mx, mtmp->my) > (BOLT_LIM * BOLT_LIM))
@@ -433,7 +436,8 @@ register struct monst *mtmp;
                 return 0;
             }
         } else { /* a monster has it - 'port beside it. */
-            (void) mnearto(mtmp, tx, ty, FALSE);
+            if (!mnearto(mtmp, tx, ty, FALSE))
+                m_into_limbo(mtmp);
             return 0;
         }
     }