armor & busy hands

Fix some inconsistencies in armor handling.  The 'T' command
wouldn't let you take off a suit or shirt if you were wielding a
cursed two-handed weapon, which makes sense; however, the 'A'
command neglected to impose the same restriction.  Also, the 'W'
command had some code intended to prevent you from donning a suit
or shirt while wielding such a cursed weapon, but it didn't work.

     This patch fixes the 'A' command's checks for whether an
item can be removed and it makes the 'T' and 'R' commands use the
same code as 'A' instead of maintaining multiple sets of checks.
It also fixes the trivial 'W' problem and attempts to prevent the
sequence of 1) get interrupted while removing a set of equipment
including suit and/or shirt; 2) wield a cursed two-handed weapon
or have already wielded one become cursed; 3) resume removing
armor via 'A' but I haven't tried to trigger that situation to
confirm the bug or this fix.
This commit is contained in:
nethack.rankin
2002-08-05 09:54:07 +00:00
parent 4bdcf771b2
commit 855ddbc550
4 changed files with 113 additions and 112 deletions

View File

@@ -182,6 +182,8 @@ invoking or applying an artifact must pass a touch_artifact check
document 'D'rop BUCX behavior in the Guidebook
remove levitation boots over a portal, the portal teleport is delayed until
your next command is typed.
armor vs cursed two-handed weapon anomalies: with 'T', couldn't remove armor,
but with 'A', could remove it, and with 'W', could put it on
Platform- and/or Interface-Specific Fixes

View File

@@ -1,4 +1,4 @@
/* SCCS Id: @(#)do_wear.c 3.4 2002/03/28 */
/* SCCS Id: @(#)do_wear.c 3.4 2002/08/03 */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -966,6 +966,7 @@ cancel_don()
static NEARDATA const char clothes[] = {ARMOR_CLASS, 0};
static NEARDATA const char accessories[] = {RING_CLASS, AMULET_CLASS, TOOL_CLASS, FOOD_CLASS, 0};
/* the 'T' command */
int
dotakeoff()
{
@@ -1016,41 +1017,17 @@ dotakeoff()
You_cant("take that off.");
return 0;
}
if (otmp == uarmg && welded(uwep)) {
You("seem unable to take off the gloves while holding your %s.",
is_sword(uwep) ? c_sword : c_weapon);
uwep->bknown = TRUE;
return 0;
} else if (welded(uwep) && bimanual(uwep) &&
(otmp == uarm
#ifdef TOURIST
|| otmp == uarmu
#endif
)) {
You("seem unable to take off %s while holding your %s.",
the(xname(otmp)), is_sword(uwep) ? c_sword : c_weapon);
uwep->bknown = TRUE;
return 0;
}
if (otmp == uarmg && Glib) {
You_cant("remove the slippery gloves with your slippery fingers.");
return 0;
}
if (otmp == uarmf && u.utrap && (u.utraptype == TT_BEARTRAP ||
u.utraptype == TT_INFLOOR)) { /* -3. */
if(u.utraptype == TT_BEARTRAP)
pline_The("bear trap prevents you from pulling your %s out.",
body_part(FOOT));
else
You("are stuck in the %s, and cannot pull your %s out.",
surface(u.ux, u.uy), makeplural(body_part(FOOT)));
return(0);
}
reset_remarm(); /* since you may change ordering */
reset_remarm(); /* clear takeoff_mask and taking_off */
(void) select_off(otmp);
if (!takeoff_mask) return 0;
reset_remarm(); /* armoroff() doesn't use takeoff_mask */
(void) armoroff(otmp);
return(1);
}
/* the 'R' command */
int
doremring()
{
@@ -1073,32 +1050,13 @@ doremring()
You("are not wearing that.");
return(0);
}
if(cursed(otmp)) return(0);
if(otmp->oclass == RING_CLASS || otmp->otyp == MEAT_RING) {
if (nolimbs(youmonst.data)) {
pline("It seems to be stuck.");
return(0);
}
if (uarmg && uarmg->cursed) {
uarmg->bknown = TRUE;
You(
"seem unable to remove your ring without taking off your gloves.");
return(0);
}
if (welded(uwep) && bimanual(uwep)) {
uwep->bknown = TRUE;
You(
"seem unable to remove the ring while your hands hold your %s.",
is_sword(uwep) ? c_sword : c_weapon);
return(0);
}
if (welded(uwep) && otmp==uright) {
uwep->bknown = TRUE;
You(
"seem unable to remove the ring while your right hand holds your %s.",
is_sword(uwep) ? c_sword : c_weapon);
return(0);
}
reset_remarm(); /* clear takeoff_mask and taking_off */
(void) select_off(otmp);
if (!takeoff_mask) return 0;
reset_remarm(); /* not used by Ring_/Amulet_/Blindf_off() */
if (otmp == uright || otmp == uleft) {
/* Sometimes we want to give the off_msg before removing and
* sometimes after; for instance, "you were wearing a moonstone
* ring (on right hand)" is desired but "you were wearing a
@@ -1107,10 +1065,14 @@ doremring()
*/
off_msg(otmp);
Ring_off(otmp);
} else if(otmp->oclass == AMULET_CLASS) {
} else if (otmp == uamul) {
Amulet_off();
off_msg(otmp);
} else Blindf_off(otmp); /* does its own off_msg */
} else if (otmp == ublindf) {
Blindf_off(otmp); /* does its own off_msg */
} else {
impossible("removing strange accessory?");
}
return(1);
}
@@ -1121,9 +1083,9 @@ register struct obj *otmp;
{
/* Curses, like chickens, come home to roost. */
if((otmp == uwep) ? welded(otmp) : (int)otmp->cursed) {
You("can't. %s to be cursed.",
You("can't. %s cursed.",
(is_boots(otmp) || is_gloves(otmp) || otmp->quan > 1L)
? "They seem" : "It seems");
? "They are" : "It is");
otmp->bknown = TRUE;
return(1);
}
@@ -1228,11 +1190,11 @@ boolean noisy;
}
if (welded(uwep) && bimanual(uwep) &&
(otmp == uarm
(is_suit(otmp)
#ifdef TOURIST
|| otmp == uarmu
|| is_shirt(otmp)
#endif
)) {
)) {
if (noisy)
You("cannot do that while holding your %s.",
is_sword(uwep) ? c_sword : c_weapon);
@@ -1660,45 +1622,82 @@ int
select_off(otmp)
register struct obj *otmp;
{
struct obj *why;
char buf[BUFSZ];
if(!otmp) return(0);
if(cursed(otmp)) return(0);
if((otmp->oclass==RING_CLASS || otmp->otyp == MEAT_RING)
&& nolimbs(youmonst.data))
return(0);
if(welded(uwep) && (otmp==uarmg || otmp==uright || (otmp==uleft
&& bimanual(uwep)))) {
You("cannot free a weapon hand to take off the ring.");
return(0);
if (!otmp) return 0;
*buf = '\0'; /* lint suppresion */
if (otmp == uright || otmp == uleft) {
if (nolimbs(youmonst.data)) {
pline_The("ring is stuck.");
return 0;
}
why = 0; /* the item which prevents ring removal */
if (welded(uwep) && (otmp == uright || bimanual(uwep))) {
Sprintf(buf, "free a weapon %s", body_part(HAND));
why = uwep;
} else if (uarmg && uarmg->cursed) {
Sprintf(buf, "take off your %s", c_gloves);
why = uarmg;
}
if (why) {
You("cannot %s to remove the ring.", buf);
why->bknown = TRUE;
return 0;
}
}
if(uarmg && uarmg->cursed && (otmp==uright || otmp==uleft)) {
uarmg->bknown = TRUE;
You("cannot remove your gloves to take off the ring.");
return(0);
if (otmp == uarmg) {
if (welded(uwep)) {
You("are unable to take off your %s while wielding that %s.",
c_gloves, is_sword(uwep) ? c_sword : c_weapon);
uwep->bknown = TRUE;
return 0;
} else if (Glib) {
You_cant("take off the slippery %s with your slippery %s.",
c_gloves, makeplural(body_part(FINGER)));
return 0;
}
}
if(otmp == uarmf && u.utrap && (u.utraptype == TT_BEARTRAP ||
u.utraptype == TT_INFLOOR)) {
return (0);
if (otmp == uarmf) {
if (u.utrap && u.utraptype == TT_BEARTRAP) {
pline_The("bear trap prevents you from pulling your %s out.",
body_part(FOOT));
return 0;
} else if (u.utrap && u.utraptype == TT_INFLOOR) {
You("are stuck in the %s, and cannot pull your %s out.",
surface(u.ux, u.uy), makeplural(body_part(FOOT)));
return 0;
}
}
if((otmp==uarm
if (otmp == uarm
#ifdef TOURIST
|| otmp==uarmu
|| otmp == uarmu
#endif
) && uarmc && uarmc->cursed) {
Strcpy(buf, the(xname(uarmc)));
You("cannot remove %s to take off %s.", buf, the(xname(otmp)));
uarmc->bknown = TRUE;
return(0);
}
) {
why = 0; /* the item which prevents disrobing */
if (uarmc && uarmc->cursed) {
Sprintf(buf, "remove your %s", cloak_simple_name(uarmc));
why = uarmc;
#ifdef TOURIST
if(otmp==uarmu && uarm && uarm->cursed) {
Strcpy(buf, the(xname(uarm)));
You("cannot remove %s to take off %s.", buf, the(xname(otmp)));
uarm->bknown = TRUE;
return(0);
}
} else if (otmp == uarmu && uarm && uarm->cursed) {
Sprintf(buf, "remove your %s", c_suit);
why = uarm;
#endif
} else if (welded(uwep) && bimanual(uwep)) {
Sprintf(buf, "release your %s",
is_sword(uwep) ? c_sword :
(uwep->otyp == BATTLE_AXE) ? c_axe : c_weapon);
why = uwep;
}
if (why) {
You("cannot %s to take off %s.", buf, the(xname(otmp)));
why->bknown = TRUE;
return 0;
}
}
/* fundamental, but other impediments are checked first */
if (cursed(otmp)) return 0;
if(otmp == uarm) takeoff_mask |= WORN_ARMOR;
else if(otmp == uarmc) takeoff_mask |= WORN_CLOAK;
@@ -1787,13 +1786,13 @@ take_off()
register int i;
register struct obj *otmp;
if(taking_off) {
if(todelay > 0) {
if (taking_off) {
if (todelay > 0) {
todelay--;
return(1); /* still busy */
} else if((otmp = do_takeoff())) off_msg(otmp);
} else {
if ((otmp = do_takeoff())) off_msg(otmp);
}
takeoff_mask &= ~taking_off;
taking_off = 0L;
}
@@ -1865,18 +1864,13 @@ take_off()
return(1); /* get busy */
}
#endif /* OVLB */
#ifdef OVL1
void
reset_remarm()
{
taking_off = takeoff_mask = 0L;
}
#endif /* OVL1 */
#ifdef OVLB
/* the 'A' command */
int
doddoremarm()
{

View File

@@ -1,4 +1,4 @@
/* SCCS Id: @(#)mkobj.c 3.4 2001/12/03 */
/* SCCS Id: @(#)mkobj.c 3.4 2002/08/02 */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -709,18 +709,21 @@ register struct obj *otmp;
{
otmp->blessed = 0;
otmp->cursed = 1;
if (otmp->otyp == LUCKSTONE
|| (otmp->oartifact && spec_ability(otmp, SPFX_LUCK)))
/* welded two-handed weapon interferes with some armor removal */
if (otmp == uwep && bimanual(uwep)) reset_remarm();
/* some cursed items need immediate updating */
if (carried(otmp) && (otmp->otyp == LUCKSTONE ||
(otmp->oartifact && spec_ability(otmp, SPFX_LUCK))))
set_moreluck();
else if (otmp->otyp == BAG_OF_HOLDING)
otmp->owt = weight(otmp);
else if (otmp->otyp == FIGURINE) {
if (otmp->corpsenm != NON_PM
&& !dead_species(otmp->corpsenm,TRUE)
&& !dead_species(otmp->corpsenm,TRUE)
&& (carried(otmp) || mcarried(otmp)))
attach_fig_transform_timeout(otmp);
}
return;
return;
}
void

View File

@@ -1,4 +1,4 @@
/* SCCS Id: @(#)wield.c 3.4 2002/05/13 */
/* SCCS Id: @(#)wield.c 3.4 2002/08/03 */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -260,6 +260,8 @@ dowield()
return (0);
} else if (welded(uwep)) {
weldmsg(uwep);
/* previously interrupted armor removal mustn't be resumed */
reset_remarm();
return (0);
}