From d736cbd751b224c95bcc6498606fbce8b57103b0 Mon Sep 17 00:00:00 2001 From: PatR Date: Thu, 28 Oct 2021 01:05:18 -0700 Subject: [PATCH] fix github issue #603 - guarding prize items Reported by Vivit-R with comments by several others. The prize item in one of the closets off the Sokoban treasure zoo is sometimes missing, most likely picked up by an elf who won't be dissuaded by the presence of engraved Elbereth or a scroll of scare monster. This fix prevents monsters from targetting the mines' and sokoban's prizes for pickup (or for eating). Once the hero picks either of the prizes up, they stop being prizes and will be ordinary monster fodder if dropped/stolen/stashed. One of the comments by copperwater suggested this approach as a possible way to fix things. I had already implemented it from scratch before noticing that. It handles the usual monster behavior toward items, but there could easily be some unusual cases still susceptible to taking the prize before the hero gets to it. Those are the breaks. Fixes #603 --- doc/fixes37.0 | 3 +++ src/dogmove.c | 4 +++- src/mon.c | 12 ++++++++++++ src/monmove.c | 5 +++++ 4 files changed, 23 insertions(+), 1 deletion(-) diff --git a/doc/fixes37.0 b/doc/fixes37.0 index e21072f9d..25d694010 100644 --- a/doc/fixes37.0 +++ b/doc/fixes37.0 @@ -674,6 +674,9 @@ don't give lance or mattock as starting equipment when creating soldiers fixup for the insect "legs" (some extraneous walls inside solid stone) on the baalz level didn't work as intended if that level was flipped handle flipped level when fixing up the baalz level "eyes" too +prevent normal monster activity from picking up the mines' luckstone or the + Sokoban amulet/bag before hero has done so; relying on scare monster + and/or engraved Elbereth wasn't sufficient to guard the Sokoban prize Fixes to 3.7.0-x Problems that Were Exposed Via git Repository diff --git a/src/dogmove.c b/src/dogmove.c index 16c0b9d12..1fc4a02e0 100644 --- a/src/dogmove.c +++ b/src/dogmove.c @@ -441,7 +441,9 @@ dog_invent(struct monst *mtmp, struct edog *edog, int udist) #ifdef MAIL_STRUCTURES && obj->otyp != SCR_MAIL #endif - ) { + /* avoid special items; once hero picks them up, they'll cease + being special and become eligible for normal monst activity */ + && !(is_mines_prize(obj) || is_soko_prize(obj))) { int edible = dogfood(mtmp, obj); if ((edible <= CADAVER diff --git a/src/mon.c b/src/mon.c index 40299b0db..36488ce78 100644 --- a/src/mon.c +++ b/src/mon.c @@ -1191,6 +1191,12 @@ meatobj(struct monst* mtmp) /* for gelatinous cubes */ for (otmp = g.level.objects[mtmp->mx][mtmp->my]; otmp; otmp = otmp2) { otmp2 = otmp->nexthere; + /* avoid special items; once hero picks them up, they'll cease + being special, becoming eligible for engulf and devore if + dropped again */ + if (is_mines_prize(otmp) || is_soko_prize(otmp)) + continue; + /* touch sensitive items */ if (otmp->otyp == CORPSE && is_rider(&mons[otmp->corpsenm])) { int ox = otmp->ox, oy = otmp->oy; @@ -1493,6 +1499,12 @@ mpickstuff(register struct monst* mtmp, register const char* str) for (otmp = g.level.objects[mtmp->mx][mtmp->my]; otmp; otmp = otmp2) { otmp2 = otmp->nexthere; + + /* avoid special items; once hero picks them up, they'll cease + being special, becoming eligible for normal pickup */ + if (is_mines_prize(otmp) || is_soko_prize(otmp)) + continue; + /* Nymphs take everything. Most monsters don't pick up corpses. */ if (!str ? searches_for_item(mtmp, otmp) : !!(index(str, otmp->oclass))) { diff --git a/src/monmove.c b/src/monmove.c index b9426a444..59158224a 100644 --- a/src/monmove.c +++ b/src/monmove.c @@ -1184,6 +1184,11 @@ m_move(register struct monst* mtmp, register int after) down on move overhead by filtering out most common item */ if (otmp->otyp == ROCK) continue; + /* avoid special items; once hero picks them up, they'll + cease being special */ + if (is_mines_prize(otmp) || is_soko_prize(otmp)) + continue; + xx = otmp->ox; yy = otmp->oy; /* Nymphs take everything. Most other creatures should not