From: PatR Date: Tue, 16 Mar 2021 18:20:16 +0000 (-0700) Subject: fix pull request #468 - scroll of earth panic X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c6e6d65e43ea326ea49e8acee7bbc29fce3de1dc;p=nethack fix pull request #468 - scroll of earth panic If a monster read a scroll of earth and got killed in the process, there would be an "dealloc_obj: obj not free" panic when trying to use up the scroll. It was dropped to the ground with any other possessions and no longer in the monster's inventory at the time m_useup() was called. Use up the scroll before performing its effects. The patch does something similar for potion of polymorph, but if newcham() can kill the monster then there are other problems besides trying to use up the potion. I kept that in anyway. Fixes #468 --- diff --git a/doc/fixes37.0 b/doc/fixes37.0 index 5ffc200a9..61bf23a2f 100644 --- a/doc/fixes37.0 +++ b/doc/fixes37.0 @@ -412,7 +412,7 @@ remove superfluous "All" from "All foos are already nonexistent." when blessed You mime dip intoing something. mounted hero falling out of saddle shouldn't hit ground and take damage when levitating or flying (if done without steed's help) - +avoid "obj not free" panic if monster kills itself by reading scroll of earth Fixes to 3.7.0-x Problems that Were Exposed Via git Repository ------------------------------------------------------------------ diff --git a/src/muse.c b/src/muse.c index f2008ff6d..a4eea23cb 100644 --- a/src/muse.c +++ b/src/muse.c @@ -1577,7 +1577,7 @@ use_offensive(struct monst* mtmp) /* don't use monster fields after killing it */ boolean confused = (mtmp->mconf ? TRUE : FALSE); int mmx = mtmp->mx, mmy = mtmp->my; - boolean is_cursed = otmp->cursed; + boolean is_cursed = otmp->cursed, is_blessed = otmp->blessed; mreadmsg(mtmp, otmp); /* Identify the scroll */ @@ -1595,27 +1595,29 @@ use_offensive(struct monst* mtmp) makeknown(otmp->otyp); } + /* could be fatal to monster, so use up the scroll before + there's a chance that monster's inventory will be dropped */ + m_useup(mtmp, otmp); + /* Loop through the surrounding squares */ for (x = mmx - 1; x <= mmx + 1; x++) { for (y = mmy - 1; y <= mmy + 1; y++) { /* Is this a suitable spot? */ if (isok(x, y) && !closed_door(x, y) && !IS_ROCK(levl[x][y].typ) && !IS_AIR(levl[x][y].typ) - && (((x == mmx) && (y == mmy)) ? !otmp->blessed - : !otmp->cursed) + && (((x == mmx) && (y == mmy)) ? !is_blessed : !is_cursed) && (x != u.ux || y != u.uy)) { (void) drop_boulder_on_monster(x, y, confused, FALSE); } } } - m_useup(mtmp, otmp); /* Attack the player */ if (distmin(mmx, mmy, u.ux, u.uy) == 1 && !is_cursed) { drop_boulder_on_player(confused, !is_cursed, FALSE, TRUE); } return (DEADMONSTER(mtmp)) ? 1 : 2; - } + } /* case MUSE_SCR_EARTH */ #if 0 case MUSE_SCR_FIRE: { boolean vis = cansee(mtmp->mx, mtmp->my); @@ -2136,12 +2138,12 @@ use_misc(struct monst* mtmp) return 2; case MUSE_POT_POLYMORPH: mquaffmsg(mtmp, otmp); + m_useup(mtmp, otmp); if (vismon) pline("%s suddenly mutates!", Monnam(mtmp)); (void) newcham(mtmp, muse_newcham_mon(mtmp), FALSE, FALSE); if (oseen) makeknown(POT_POLYMORPH); - m_useup(mtmp, otmp); return 2; case MUSE_BAG: return mloot_container(mtmp, otmp, vismon);