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
This commit is contained in:
PatR
2021-10-28 01:05:18 -07:00
parent 5b91f81533
commit d736cbd751
4 changed files with 23 additions and 1 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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))) {

View File

@@ -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