From 17f8482e734513b4dc10657a1bc586854cccd20f Mon Sep 17 00:00:00 2001 From: "nethack.rankin" Date: Thu, 30 Nov 2006 05:54:47 +0000 Subject: [PATCH] dipping and greasing (trunk only) From a bug report: you can dip a worn item such as shirt or suit into a potion of polymorph and it will become unworn--but as of a couple of days ago, unworn only if the transformed object's new form can't be worn in the same slot--even if it is covered by a cursed worn item (suit or cloak). It didn't seem like trying to fix that special case would be very worthwhile; this fixes the more general situation of "you could dip worn items even though they were covered up by other worn items". In the same report: you could apply grease to rings while wearing cursed gloves. The code already prevented greasing a suit when it was covered by a cloak (regardless of whether that cloak was cursed), and a shirt when it was covered by a suit or cloak or both. This moves that code into a separate routine which is used for dipping as well as for applying grease, and now handles rings vs gloves. Since covered rings, shirt, or suit are no longer eligible to be dipped or greased, this also makes "?" for the pick-an-item prompt leave such things out of the list of likely candidates. --- doc/fixes35.0 | 1 + include/extern.h | 1 + src/apply.c | 21 ++---------------- src/do_wear.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++ src/invent.c | 10 ++++----- src/potion.c | 3 ++- 6 files changed, 68 insertions(+), 26 deletions(-) diff --git a/doc/fixes35.0 b/doc/fixes35.0 index 52f614a19..1af89bbbf 100644 --- a/doc/fixes35.0 +++ b/doc/fixes35.0 @@ -173,6 +173,7 @@ shopkeepers shouldn't refer to non-male character as "cad" tweak levitation timeout if trap is being triggered on same turn it is to end if Rider corpse revival fails, usually try again later instead of rotting away worn item transformed by polymorph remains worn if feasible +can't dip or apply grease to a worn item that's covered by another worn item Platform- and/or Interface-Specific Fixes diff --git a/include/extern.h b/include/extern.h index bba1600d7..c1f0a2b44 100644 --- a/include/extern.h +++ b/include/extern.h @@ -429,6 +429,7 @@ E void NDECL(reset_remarm); E int NDECL(doddoremarm); E int FDECL(destroy_arm, (struct obj *)); E void FDECL(adj_abon, (struct obj *,SCHAR_P)); +E boolean FDECL(inaccessible_equipment, (struct obj *,const char *,BOOLEAN_P)); /* ### dog.c ### */ diff --git a/src/apply.c b/src/apply.c index a53a38932..7483aa46c 100644 --- a/src/apply.c +++ b/src/apply.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)apply.c 3.5 2006/10/21 */ +/* SCCS Id: @(#)apply.c 3.5 2006/11/29 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1897,15 +1897,12 @@ struct obj **optr; } static NEARDATA const char lubricables[] = { ALL_CLASSES, ALLOW_NONE, 0 }; -static NEARDATA const char need_to_remove_outer_armor[] = - "need to remove %s to grease %s."; STATIC_OVL void use_grease(obj) struct obj *obj; { struct obj *otmp; - char buf[BUFSZ]; if (Glib) { pline("%s from your %s.", Tobjnam(obj, "slip"), @@ -1925,21 +1922,7 @@ struct obj *obj; } otmp = getobj(lubricables, "grease"); if (!otmp) return; - if ((otmp->owornmask & WORN_ARMOR) && uarmc) { - Strcpy(buf, yname(uarmc)); - You(need_to_remove_outer_armor, buf, yname(otmp)); - return; - } -#ifdef TOURIST - if ((otmp->owornmask & WORN_SHIRT) && (uarmc || uarm)) { - Strcpy(buf, uarmc ? yname(uarmc) : ""); - if (uarmc && uarm) - Strcat(strcat(buf, " and "), xname(uarm)); - else Strcat(buf, uarm ? yname(uarm) : ""); - You(need_to_remove_outer_armor, buf, yname(otmp)); - return; - } -#endif + if (inaccessible_equipment(otmp, "grease", FALSE)) return; consume_obj_charge(obj, TRUE); if (otmp != &zeroobj) { diff --git a/src/do_wear.c b/src/do_wear.c index 827d6a9a1..9b0090cdd 100644 --- a/src/do_wear.c +++ b/src/do_wear.c @@ -2227,4 +2227,62 @@ register schar delta; } } +/* decide whether a worn item is covered up by some other worn item, + used for dipping into liquid and applying grease; + some criteria are different than select_off()'s */ +boolean +inaccessible_equipment(obj, verb, only_if_cursed) +struct obj *obj; +const char *verb; /* "dip" or "grease", or null to avoid messages */ +boolean only_if_cursed; /* true => ignore non-cursed covering gear */ +{ + static NEARDATA const char need_to_take_off_outer_armor[] = + "need to take off %s to %s %s."; + char buf[BUFSZ]; + + if (!obj || !obj->owornmask) return FALSE; /* not inaccessible */ + + /* check for suit covered by cloak */ + if (obj == uarm && uarmc && (uarmc->cursed || !only_if_cursed)) { + if (verb) { + Strcpy(buf, yname(uarmc)); + You(need_to_take_off_outer_armor, buf, verb, yname(obj)); + } + return TRUE; + } +#ifdef TOURIST + /* check for shirt covered by suit and/or cloak */ + if (obj == uarmu && ((uarm && (uarm->cursed || !only_if_cursed)) || + (uarmc && (uarmc->cursed || !only_if_cursed)))) { + if (verb) { + char cloaktmp[QBUFSZ], suittmp[QBUFSZ]; + /* if sameprefix, use yname and xname to get "your cloak and suit" + or "Manlobbi's cloak and suit"; otherwise, use yname and yname + to get "your cloak and Manlobbi's suit" or vice versa */ + boolean sameprefix = (uarm && uarmc && + !strcmp(shk_your(cloaktmp, uarmc), + shk_your(suittmp, uarm))); + + *buf = '\0'; + if (uarmc) Strcat(buf, yname(uarmc)); + if (uarm && uarmc) Strcat(buf, " and "); + if (uarm) Strcat(buf, sameprefix ? xname(uarm) : yname(uarm)); + You(need_to_take_off_outer_armor, buf, verb, yname(obj)); + } + return TRUE; + } +#endif + /* check for ring covered by gloves */ + if ((obj == uleft || obj == uright) && + uarmg && (uarmg->cursed || !only_if_cursed)) { + if (verb) { + Strcpy(buf, yname(uarmg)); + You(need_to_take_off_outer_armor, buf, verb, yname(obj)); + } + return TRUE; + } + /* item is not inaccessible */ + return FALSE; +} + /*do_wear.c*/ diff --git a/src/invent.c b/src/invent.c index 7692bcfae..b14d436fb 100644 --- a/src/invent.c +++ b/src/invent.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)invent.c 3.5 2006/07/08 */ +/* SCCS Id: @(#)invent.c 3.5 2006/11/29 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -847,11 +847,7 @@ register const char *let,*word; /* ugly check: remove inappropriate things */ if ((taking_off(word) && (!(otmp->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL)) - || (otmp==uarm && uarmc) -#ifdef TOURIST - || (otmp==uarmu && (uarm || uarmc)) -#endif - )) + || inaccessible_equipment(otmp, (const char *)0, FALSE))) || (putting_on(word) && (otmp->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL))) /* already worn */ @@ -861,6 +857,8 @@ register const char *let,*word; #endif || (!strcmp(word, "ready") && (otmp == uwep || (otmp == uswapwep && u.twoweap))) + || ((!strcmp(word, "dip") || !strcmp(word, "grease")) && + inaccessible_equipment(otmp, (const char *)0 , FALSE)) ) { foo--; foox++; diff --git a/src/potion.c b/src/potion.c index 67759b4c6..06b184940 100644 --- a/src/potion.c +++ b/src/potion.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)potion.c 3.5 2006/08/18 */ +/* SCCS Id: @(#)potion.c 3.5 2006/11/29 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1693,6 +1693,7 @@ dodip() allowall[0] = ALL_CLASSES; allowall[1] = '\0'; if(!(obj = getobj(allowall, "dip"))) return(0); + if (inaccessible_equipment(obj, "dip", FALSE)) return 0; here = levl[u.ux][u.uy].typ; /* Is there a fountain to dip into here? */ -- 2.40.0