From 9c554895b1af9fd67bd7f9d6aabb2158fff4289c Mon Sep 17 00:00:00 2001 From: nhmall Date: Sat, 9 Nov 2024 14:06:43 -0500 Subject: [PATCH] adjust wish for cockatrice corpse Wishing is powerful, so if you cannot safely handle a cockatrice corpse, then have a wish for one result in the corpse materializing on the floor rather than in your inventory. Resolves #1320 --- include/extern.h | 1 + include/obj.h | 1 + src/invent.c | 6 ++++++ src/pickup.c | 12 ++++++++++-- src/zap.c | 12 ++++++++++-- 5 files changed, 28 insertions(+), 4 deletions(-) diff --git a/include/extern.h b/include/extern.h index 8422224f4..ceafb5000 100644 --- a/include/extern.h +++ b/include/extern.h @@ -2363,6 +2363,7 @@ extern int loot_mon(struct monst *, int *, boolean *) NO_NNARGS; extern int dotip(void); extern struct autopickup_exception *check_autopickup_exceptions(struct obj *) NONNULLARG1; extern boolean autopick_testobj(struct obj *, boolean) NONNULLARG1; +extern boolean u_safe_from_fatal_corpse(struct obj *obj) NONNULLARG1; /* ### pline.c ### */ diff --git a/include/obj.h b/include/obj.h index abdd3c735..f43d94f81 100644 --- a/include/obj.h +++ b/include/obj.h @@ -162,6 +162,7 @@ struct obj { * 1 for others (format as "next boulder") */ int usecount; /* overloaded for various things that tally */ #define spestudied usecount /* # of times a spellbook has been studied */ +#define wishedfor usecount /* flag for hold_another_object() if from wish */ unsigned oeaten; /* nutrition left in food, if partly eaten */ long age; /* creation date */ long owornmask; /* bit mask indicating which equipment slot(s) an diff --git a/src/invent.c b/src/invent.c index 2e696214a..00ccd045c 100644 --- a/src/invent.c +++ b/src/invent.c @@ -1230,6 +1230,12 @@ hold_another_object( dropped, avoid perminv update when temporarily adding it */ obj = addinv_core0(obj, (struct obj *) 0, FALSE); goto drop_it; + } else if (obj->otyp == CORPSE + && !u_safe_from_fatal_corpse(obj) + && obj->wishedfor) { + obj->wishedfor = 0; + obj = addinv_core0(obj, (struct obj *) 0, FALSE); + goto drop_it; } else { long oquan = obj->quan; int prev_encumbr = near_capacity(); /* before addinv() */ diff --git a/src/pickup.c b/src/pickup.c index 75e685b97..b68761a39 100644 --- a/src/pickup.c +++ b/src/pickup.c @@ -261,12 +261,20 @@ query_classes( return TRUE; } +boolean +u_safe_from_fatal_corpse(struct obj *obj) +{ + if (uarmg || obj->otyp != CORPSE + || !touch_petrifies(&mons[obj->corpsenm]) || Stone_resistance) + return TRUE; + return FALSE; +} + /* check whether hero is bare-handedly touching a cockatrice corpse */ staticfn boolean fatal_corpse_mistake(struct obj *obj, boolean remotely) { - if (uarmg || remotely || obj->otyp != CORPSE - || !touch_petrifies(&mons[obj->corpsenm]) || Stone_resistance) + if (u_safe_from_fatal_corpse(obj) || remotely) return FALSE; if (poly_when_stoned(gy.youmonst.data) && polymon(PM_STONE_GOLEM)) { diff --git a/src/zap.c b/src/zap.c index 37531eeab..78baab25e 100644 --- a/src/zap.c +++ b/src/zap.c @@ -6189,14 +6189,22 @@ makewish(void) /* TODO? maybe generate a second event describing what was received since these just echo player's request rather than show actual result */ - const char *verb = ((Is_airlevel(&u.uz) || u.uinwater) ? "slip" : "drop"), + if (otmp->otyp == CORPSE && !u_safe_from_fatal_corpse(otmp)) + otmp->wishedfor = 1; + + const char *verb = ((Is_airlevel(&u.uz) || u.uinwater) + ? "slip" + : (otmp->otyp == CORPSE && otmp->wishedfor) + ? "materialize" : "drop"), *oops_msg = (u.uswallow ? "Oops! %s out of your reach!" : (Is_airlevel(&u.uz) || Is_waterlevel(&u.uz) || levl[u.ux][u.uy].typ < IRONBARS || levl[u.ux][u.uy].typ >= ICE) ? "Oops! %s away from you!" - : "Oops! %s to the floor!"); + : !(otmp->otyp == CORPSE && otmp->wishedfor) + ? "Oops! %s to the floor!" + : "Careful! %s on the floor!"); /* The(aobjnam()) is safe since otmp is unidentified -dlc */ (void) hold_another_object(otmp, oops_msg, The(aobjnam(otmp, verb)),