resuming interrupted 'A' command

[ Caveat:  compiles ok on branch code but only play tested on trunk code;
  the do_wear.c diff is a lot different between the two variants and the
  trunk one includes some whitespace cleanup. ]

     <email deleted> reported that having a spellcasting monster
destroy some armor while you're in the midst of using 'A' to take that
armor off would result in a crash.  The problem was actually more
widespread than that:  having a nymph steal worn items (accessories as
well as armor), or a succubus remove them, or being interrupted by monster
activity and then reading a scroll of destroy armor prior to resuming 'A'
could all produce a similar crash.  'A' relied on stale context and could
attempt to manipulate an equipment slot which had become empty, ultimately
leading to an attempt to dereference a null pointer.

     The 'R' command didn't have this problem since any accessory gets
removed immediately.  The 'T' command already had handling for this:
there's only one item to deal with and multi-turn take off only applies
to some of the slots; the donning() check followed by cancel_don() took
care of those.  Only 'A' was vulnerable to the problem and it wouldn't
necessarily need to be interrupted and resumed; loss of the current
multi-turn item or any pending item would be enough--but I'm not sure
whether such item loss could occur without also interrupting the current
activity, so resumption of previous 'A' was probably a requirement for
triggering the crash.

     This makes shield and shirt handling be similar to other types of
armor instead of relying on the fact that none of them need to have any
attribute adjustments when put on or taken off.  However, there are
still assumptions (the `cancelled_don' stuff) that some slots don't have
any eligible items requiring more than a single turn to use; that should
probably be changed.
This commit is contained in:
nethack.rankin
2003-11-15 10:25:09 +00:00
parent 23d3a146d9
commit e989ae0b96
4 changed files with 210 additions and 108 deletions

View File

@@ -89,6 +89,8 @@ rotting corpses grammar fix
allow successful teleport to more locations on debug mode level teleport menu allow successful teleport to more locations on debug mode level teleport menu
trapped monster repeatedly switched between ranged and hand-to-hand weapon trapped monster repeatedly switched between ranged and hand-to-hand weapon
silver items such as wands avoided all the silver checks in hmon_hitmon() silver items such as wands avoided all the silver checks in hmon_hitmon()
resuming an interrupted 'A' command could cause crash if pending worn item(s)
were stolen or destroyed
Platform- and/or Interface-Specific Fixes Platform- and/or Interface-Specific Fixes

View File

@@ -374,6 +374,9 @@ E int NDECL(Gloves_off);
E int NDECL(Boots_off); E int NDECL(Boots_off);
E int NDECL(Cloak_off); E int NDECL(Cloak_off);
E int NDECL(Shield_off); E int NDECL(Shield_off);
#ifdef TOURIST
E int NDECL(Shirt_off);
#endif
E void NDECL(Amulet_off); E void NDECL(Amulet_off);
E void FDECL(Ring_on, (struct obj *)); E void FDECL(Ring_on, (struct obj *));
E void FDECL(Ring_off, (struct obj *)); E void FDECL(Ring_off, (struct obj *));

View File

@@ -1,4 +1,4 @@
/* SCCS Id: @(#)do_wear.c 3.4 2003/05/25 */ /* SCCS Id: @(#)do_wear.c 3.4 2003/11/14 */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -35,6 +35,10 @@ STATIC_PTR int NDECL(Boots_on);
STATIC_DCL int NDECL(Cloak_on); STATIC_DCL int NDECL(Cloak_on);
STATIC_PTR int NDECL(Helmet_on); STATIC_PTR int NDECL(Helmet_on);
STATIC_PTR int NDECL(Gloves_on); STATIC_PTR int NDECL(Gloves_on);
STATIC_PTR int NDECL(Shield_on);
#ifdef TOURIST
STATIC_PTR int NDECL(Shirt_on);
#endif
STATIC_DCL void NDECL(Amulet_on); STATIC_DCL void NDECL(Amulet_on);
STATIC_DCL void FDECL(Ring_off_or_gone, (struct obj *, BOOLEAN_P)); STATIC_DCL void FDECL(Ring_off_or_gone, (struct obj *, BOOLEAN_P));
STATIC_PTR int FDECL(select_off, (struct obj *)); STATIC_PTR int FDECL(select_off, (struct obj *));
@@ -128,7 +132,7 @@ Boots_off()
int otyp = uarmf->otyp; int otyp = uarmf->otyp;
long oldprop = u.uprops[objects[otyp].oc_oprop].extrinsic & ~WORN_BOOTS; long oldprop = u.uprops[objects[otyp].oc_oprop].extrinsic & ~WORN_BOOTS;
context.takeoff.mask &= ~W_ARMF;
/* For levitation, float_down() returns if Levitation, so we /* For levitation, float_down() returns if Levitation, so we
* must do a setworn() _before_ the levitation case. * must do a setworn() _before_ the levitation case.
*/ */
@@ -150,7 +154,8 @@ Boots_off()
} }
break; break;
case ELVEN_BOOTS: case ELVEN_BOOTS:
if (!oldprop && !HStealth && !BStealth && !context.takeoff.cancelled_don) { if (!oldprop && !HStealth && !BStealth &&
!context.takeoff.cancelled_don) {
makeknown(otyp); makeknown(otyp);
You("sure are noisy."); You("sure are noisy.");
} }
@@ -232,7 +237,7 @@ Cloak_off()
int otyp = uarmc->otyp; int otyp = uarmc->otyp;
long oldprop = u.uprops[objects[otyp].oc_oprop].extrinsic & ~WORN_CLOAK; long oldprop = u.uprops[objects[otyp].oc_oprop].extrinsic & ~WORN_CLOAK;
context.takeoff.mask &= ~W_ARMC;
/* For mummy wrapping, taking it off first resets `Invisible'. */ /* For mummy wrapping, taking it off first resets `Invisible'. */
setworn((struct obj *)0, W_ARMC); setworn((struct obj *)0, W_ARMC);
switch (otyp) { switch (otyp) {
@@ -333,6 +338,8 @@ Helmet_on()
int int
Helmet_off() Helmet_off()
{ {
context.takeoff.mask &= ~W_ARMH;
switch(uarmh->otyp) { switch(uarmh->otyp) {
case FEDORA: case FEDORA:
case HELMET: case HELMET:
@@ -402,6 +409,8 @@ Gloves_off()
long oldprop = long oldprop =
u.uprops[objects[uarmg->otyp].oc_oprop].extrinsic & ~WORN_GLOVES; u.uprops[objects[uarmg->otyp].oc_oprop].extrinsic & ~WORN_GLOVES;
context.takeoff.mask &= ~W_ARMG;
switch(uarmg->otyp) { switch(uarmg->otyp) {
case LEATHER_GLOVES: case LEATHER_GLOVES:
break; break;
@@ -450,11 +459,11 @@ Gloves_off()
return 0; return 0;
} }
/*
STATIC_OVL int STATIC_OVL int
Shield_on() Shield_on()
{ {
switch(uarms->otyp) { /*
switch (uarms->otyp) {
case SMALL_SHIELD: case SMALL_SHIELD:
case ELVEN_SHIELD: case ELVEN_SHIELD:
case URUK_HAI_SHIELD: case URUK_HAI_SHIELD:
@@ -465,15 +474,16 @@ Shield_on()
break; break;
default: impossible(unknown_type, c_shield, uarms->otyp); default: impossible(unknown_type, c_shield, uarms->otyp);
} }
*/
return 0; return 0;
} }
*/
int int
Shield_off() Shield_off()
{ {
context.takeoff.mask &= ~W_ARMS;
/* /*
switch(uarms->otyp) { switch (uarms->otyp) {
case SMALL_SHIELD: case SMALL_SHIELD:
case ELVEN_SHIELD: case ELVEN_SHIELD:
case URUK_HAI_SHIELD: case URUK_HAI_SHIELD:
@@ -489,6 +499,38 @@ Shield_off()
return 0; return 0;
} }
#ifdef TOURIST
STATIC_OVL int
Shirt_on()
{
/*
switch (uarmu->otyp) {
case HAWAIIAN_SHIRT:
case T_SHIRT:
break;
default: impossible(unknown_type, c_shirt, uarmu->otyp);
}
*/
return 0;
}
int
Shirt_off()
{
context.takeoff.mask &= ~W_ARMU;
/*
switch (uarmu->otyp) {
case HAWAIIAN_SHIRT:
case T_SHIRT:
break;
default: impossible(unknown_type, c_shirt, uarmu->otyp);
}
*/
setworn((struct obj *)0, W_ARMU);
return 0;
}
#endif /*TOURIST*/
/* This must be done in worn.c, because one of the possible intrinsics conferred /* This must be done in worn.c, because one of the possible intrinsics conferred
* is fire resistance, and we have to immediately set HFire_resistance in worn.c * is fire resistance, and we have to immediately set HFire_resistance in worn.c
* since worn.c will check it before returning. * since worn.c will check it before returning.
@@ -503,6 +545,7 @@ Armor_on()
int int
Armor_off() Armor_off()
{ {
context.takeoff.mask &= ~W_ARM;
setworn((struct obj *)0, W_ARM); setworn((struct obj *)0, W_ARM);
context.takeoff.cancelled_don = FALSE; context.takeoff.cancelled_don = FALSE;
return 0; return 0;
@@ -514,6 +557,7 @@ Armor_off()
int int
Armor_gone() Armor_gone()
{ {
context.takeoff.mask &= ~W_ARM;
setnotworn(uarm); setnotworn(uarm);
context.takeoff.cancelled_don = FALSE; context.takeoff.cancelled_don = FALSE;
return 0; return 0;
@@ -573,6 +617,8 @@ Amulet_on()
void void
Amulet_off() Amulet_off()
{ {
context.takeoff.mask &= ~W_AMUL;
switch(uamul->otyp) { switch(uamul->otyp) {
case AMULET_OF_ESP: case AMULET_OF_ESP:
/* need to update ability before calling see_monsters() */ /* need to update ability before calling see_monsters() */
@@ -729,9 +775,10 @@ Ring_off_or_gone(obj,gone)
register struct obj *obj; register struct obj *obj;
boolean gone; boolean gone;
{ {
register long mask = obj->owornmask & W_RING; long mask = (obj->owornmask & W_RING);
int old_attrib, which; int old_attrib, which;
context.takeoff.mask &= ~mask;
if(!(u.uprops[objects[obj->otyp].oc_oprop].extrinsic & mask)) if(!(u.uprops[objects[obj->otyp].oc_oprop].extrinsic & mask))
impossible("Strange... I didn't know you had that ring."); impossible("Strange... I didn't know you had that ring.");
if(gone) setnotworn(obj); if(gone) setnotworn(obj);
@@ -882,6 +929,7 @@ register struct obj *otmp;
{ {
boolean was_blind = Blind, changed = FALSE; boolean was_blind = Blind, changed = FALSE;
context.takeoff.mask &= ~W_TOOL;
setworn((struct obj *)0, otmp->owornmask); setworn((struct obj *)0, otmp->owornmask);
off_msg(otmp); off_msg(otmp);
@@ -916,22 +964,51 @@ register struct obj *otmp;
void void
set_wear() set_wear()
{ {
#ifdef TOURIST
if (uarmu) (void) Shirt_on();
#endif
if (uarm) (void) Armor_on(); if (uarm) (void) Armor_on();
if (uarmc) (void) Cloak_on(); if (uarmc) (void) Cloak_on();
if (uarmf) (void) Boots_on(); if (uarmf) (void) Boots_on();
if (uarmg) (void) Gloves_on(); if (uarmg) (void) Gloves_on();
if (uarmh) (void) Helmet_on(); if (uarmh) (void) Helmet_on();
/* if (uarms) (void) Shield_on(); */ if (uarms) (void) Shield_on();
} }
/* check whether the target object is currently being put on (or taken off) */
boolean boolean
donning(otmp) donning(otmp) /* also checks for doffing */
register struct obj *otmp; register struct obj *otmp;
{ {
return((boolean)((otmp == uarmf && (afternmv == Boots_on || afternmv == Boots_off)) /* long what = (occupation == take_off) ? context.takeoff.what : 0L; */
|| (otmp == uarmh && (afternmv == Helmet_on || afternmv == Helmet_off)) long what = context.takeoff.what; /* if nonzero, occupation is implied */
|| (otmp == uarmg && (afternmv == Gloves_on || afternmv == Gloves_off)) boolean result = FALSE;
|| (otmp == uarm && (afternmv == Armor_on || afternmv == Armor_off))));
if (otmp == uarm)
result = (afternmv == Armor_on || afternmv == Armor_off ||
what == WORN_ARMOR);
#ifdef TOURIST
else if (otmp == uarmu)
result = (afternmv == Shirt_on || afternmv == Shirt_off ||
what == WORN_SHIRT);
#endif
else if (otmp == uarmc)
result = (afternmv == Cloak_on || afternmv == Cloak_off ||
what == WORN_CLOAK);
else if (otmp == uarmf)
result = (afternmv == Boots_on || afternmv == Boots_off ||
what == WORN_BOOTS);
else if (otmp == uarmh)
result = (afternmv == Helmet_on || afternmv == Helmet_off ||
what == WORN_HELMET);
else if (otmp == uarmg)
result = (afternmv == Gloves_on || afternmv == Gloves_off ||
what == WORN_GLOVES);
else if (otmp == uarms)
result = (afternmv == Shield_on || afternmv == Shield_off ||
what == WORN_SHIELD);
return result;
} }
void void
@@ -941,11 +1018,15 @@ cancel_don()
* wasting time on it (and don't dereference it when donning would * wasting time on it (and don't dereference it when donning would
* otherwise finish) * otherwise finish)
*/ */
context.takeoff.cancelled_don = (afternmv == Boots_on || afternmv == Helmet_on || context.takeoff.cancelled_don = (afternmv == Boots_on ||
afternmv == Gloves_on || afternmv == Armor_on); afternmv == Helmet_on ||
afternmv == Gloves_on ||
afternmv == Armor_on);
afternmv = 0; afternmv = 0;
nomovemsg = (char *)0; nomovemsg = (char *)0;
multi = 0; multi = 0;
context.takeoff.delay = 0;
context.takeoff.what = 0L;
} }
static NEARDATA const char clothes[] = {ARMOR_CLASS, 0}; static NEARDATA const char clothes[] = {ARMOR_CLASS, 0};
@@ -1362,7 +1443,10 @@ dowear()
nomovemsg = "You finish your dressing maneuver."; nomovemsg = "You finish your dressing maneuver.";
} else { } else {
if(is_cloak(otmp)) (void) Cloak_on(); if(is_cloak(otmp)) (void) Cloak_on();
/* if(is_shield(otmp)) (void) Shield_on(); */ if (is_shield(otmp)) (void) Shield_on();
#ifdef TOURIST
if (is_shirt(otmp)) (void) Shirt_on();
#endif
on_msg(otmp); on_msg(otmp);
} }
context.takeoff.mask = context.takeoff.what = 0L; context.takeoff.mask = context.takeoff.what = 0L;
@@ -1773,57 +1857,59 @@ register struct obj *otmp;
STATIC_OVL struct obj * STATIC_OVL struct obj *
do_takeoff() do_takeoff()
{ {
register struct obj *otmp = (struct obj *)0; struct obj *otmp = (struct obj *)0;
struct takeoff_info *doff = &context.takeoff;
if (context.takeoff.what == W_WEP) { if (doff->what == W_WEP) {
if(!cursed(uwep)) { if (!cursed(uwep)) {
setuwep((struct obj *) 0); setuwep((struct obj *) 0);
You("are empty %s.", body_part(HANDED)); You("are empty %s.", body_part(HANDED));
u.twoweap = FALSE; u.twoweap = FALSE;
} }
} else if (context.takeoff.what == W_SWAPWEP) { } else if (doff->what == W_SWAPWEP) {
setuswapwep((struct obj *) 0); setuswapwep((struct obj *) 0);
You("no longer have a second weapon readied."); You("no longer have a second weapon readied.");
u.twoweap = FALSE; u.twoweap = FALSE;
} else if (context.takeoff.what == W_QUIVER) { } else if (doff->what == W_QUIVER) {
setuqwep((struct obj *) 0); setuqwep((struct obj *) 0);
You("no longer have ammunition readied."); You("no longer have ammunition readied.");
} else if (context.takeoff.what == WORN_ARMOR) { } else if (doff->what == WORN_ARMOR) {
otmp = uarm; otmp = uarm;
if(!cursed(otmp)) (void) Armor_off(); if (!cursed(otmp)) (void) Armor_off();
} else if (context.takeoff.what == WORN_CLOAK) { } else if (doff->what == WORN_CLOAK) {
otmp = uarmc; otmp = uarmc;
if(!cursed(otmp)) (void) Cloak_off(); if (!cursed(otmp)) (void) Cloak_off();
} else if (context.takeoff.what == WORN_BOOTS) { } else if (doff->what == WORN_BOOTS) {
otmp = uarmf; otmp = uarmf;
if(!cursed(otmp)) (void) Boots_off(); if (!cursed(otmp)) (void) Boots_off();
} else if (context.takeoff.what == WORN_GLOVES) { } else if (doff->what == WORN_GLOVES) {
otmp = uarmg; otmp = uarmg;
if(!cursed(otmp)) (void) Gloves_off(); if (!cursed(otmp)) (void) Gloves_off();
} else if (context.takeoff.what == WORN_HELMET) { } else if (doff->what == WORN_HELMET) {
otmp = uarmh; otmp = uarmh;
if(!cursed(otmp)) (void) Helmet_off(); if (!cursed(otmp)) (void) Helmet_off();
} else if (context.takeoff.what == WORN_SHIELD) { } else if (doff->what == WORN_SHIELD) {
otmp = uarms; otmp = uarms;
if(!cursed(otmp)) (void) Shield_off(); if (!cursed(otmp)) (void) Shield_off();
#ifdef TOURIST #ifdef TOURIST
} else if (context.takeoff.what == WORN_SHIRT) { } else if (doff->what == WORN_SHIRT) {
otmp = uarmu; otmp = uarmu;
if(!cursed(otmp)) if (!cursed(otmp)) (void) Shirt_off();
setworn((struct obj *)0, uarmu->owornmask & W_ARMOR);
#endif #endif
} else if (context.takeoff.what == WORN_AMUL) { } else if (doff->what == WORN_AMUL) {
otmp = uamul; otmp = uamul;
if(!cursed(otmp)) Amulet_off(); if (!cursed(otmp)) Amulet_off();
} else if (context.takeoff.what == LEFT_RING) { } else if (doff->what == LEFT_RING) {
otmp = uleft; otmp = uleft;
if(!cursed(otmp)) Ring_off(uleft); if (!cursed(otmp)) Ring_off(uleft);
} else if (context.takeoff.what == RIGHT_RING) { } else if (doff->what == RIGHT_RING) {
otmp = uright; otmp = uright;
if(!cursed(otmp)) Ring_off(uright); if (!cursed(otmp)) Ring_off(uright);
} else if (context.takeoff.what == WORN_BLINDF) { } else if (doff->what == WORN_BLINDF) {
if (!cursed(ublindf)) Blindf_off(ublindf); if (!cursed(ublindf)) Blindf_off(ublindf);
} else impossible("do_takeoff: taking off %lx", context.takeoff.what); } else {
impossible("do_takeoff: taking off %lx", doff->what);
}
return(otmp); return(otmp);
} }
@@ -1834,84 +1920,83 @@ take_off()
{ {
register int i; register int i;
register struct obj *otmp; register struct obj *otmp;
struct takeoff_info *doff = &context.takeoff;
if (context.takeoff.what) { if (doff->what) {
if (context.takeoff.delay > 0) { if (doff->delay > 0) {
context.takeoff.delay--; doff->delay--;
return(1); /* still busy */ return(1); /* still busy */
} else { } else {
if ((otmp = do_takeoff())) off_msg(otmp); if ((otmp = do_takeoff())) off_msg(otmp);
} }
context.takeoff.mask &= ~context.takeoff.what; doff->mask &= ~doff->what;
context.takeoff.what = 0L; doff->what = 0L;
} }
for(i = 0; takeoff_order[i]; i++) for(i = 0; takeoff_order[i]; i++)
if(context.takeoff.mask & takeoff_order[i]) { if(doff->mask & takeoff_order[i]) {
context.takeoff.what = takeoff_order[i]; doff->what = takeoff_order[i];
break; break;
} }
otmp = (struct obj *) 0; otmp = (struct obj *) 0;
context.takeoff.delay = 0; doff->delay = 0;
if (context.takeoff.what == 0L) { if (doff->what == 0L) {
You("finish %s.", context.takeoff.disrobing); You("finish %s.", doff->disrobing);
return 0; return 0;
} else if (context.takeoff.what == W_WEP) { } else if (doff->what == W_WEP) {
context.takeoff.delay = 1; doff->delay = 1;
} else if (context.takeoff.what == W_SWAPWEP) { } else if (doff->what == W_SWAPWEP) {
context.takeoff.delay = 1; doff->delay = 1;
} else if (context.takeoff.what == W_QUIVER) { } else if (doff->what == W_QUIVER) {
context.takeoff.delay = 1; doff->delay = 1;
} else if (context.takeoff.what == WORN_ARMOR) { } else if (doff->what == WORN_ARMOR) {
otmp = uarm; otmp = uarm;
/* If a cloak is being worn, add the time to take it off and put /* If a cloak is being worn, add the time to take it off and put
* it back on again. Kludge alert! since that time is 0 for all * it back on again. Kludge alert! since that time is 0 for all
* known cloaks, add 1 so that it actually matters... * known cloaks, add 1 so that it actually matters...
*/ */
if (uarmc) context.takeoff.delay += 2 * objects[uarmc->otyp].oc_delay + 1; if (uarmc) doff->delay += 2 * objects[uarmc->otyp].oc_delay + 1;
} else if (context.takeoff.what == WORN_CLOAK) { } else if (doff->what == WORN_CLOAK) {
otmp = uarmc; otmp = uarmc;
} else if (context.takeoff.what == WORN_BOOTS) { } else if (doff->what == WORN_BOOTS) {
otmp = uarmf; otmp = uarmf;
} else if (context.takeoff.what == WORN_GLOVES) { } else if (doff->what == WORN_GLOVES) {
otmp = uarmg; otmp = uarmg;
} else if (context.takeoff.what == WORN_HELMET) { } else if (doff->what == WORN_HELMET) {
otmp = uarmh; otmp = uarmh;
} else if (context.takeoff.what == WORN_SHIELD) { } else if (doff->what == WORN_SHIELD) {
otmp = uarms; otmp = uarms;
#ifdef TOURIST #ifdef TOURIST
} else if (context.takeoff.what == WORN_SHIRT) { } else if (doff->what == WORN_SHIRT) {
otmp = uarmu; otmp = uarmu;
/* add the time to take off and put back on armor and/or cloak */ /* add the time to take off and put back on armor and/or cloak */
if (uarm) context.takeoff.delay += 2 * objects[uarm->otyp].oc_delay; if (uarm) doff->delay += 2 * objects[uarm->otyp].oc_delay;
if (uarmc) context.takeoff.delay += 2 * objects[uarmc->otyp].oc_delay + 1; if (uarmc) doff->delay += 2 * objects[uarmc->otyp].oc_delay + 1;
#endif #endif
} else if (context.takeoff.what == WORN_AMUL) { } else if (doff->what == WORN_AMUL) {
context.takeoff.delay = 1; doff->delay = 1;
} else if (context.takeoff.what == LEFT_RING) { } else if (doff->what == LEFT_RING) {
context.takeoff.delay = 1; doff->delay = 1;
} else if (context.takeoff.what == RIGHT_RING) { } else if (doff->what == RIGHT_RING) {
context.takeoff.delay = 1; doff->delay = 1;
} else if (context.takeoff.what == WORN_BLINDF) { } else if (doff->what == WORN_BLINDF) {
context.takeoff.delay = 2; doff->delay = 2;
} else { } else {
impossible("take_off: taking off %lx", context.takeoff.what); impossible("take_off: taking off %lx", doff->what);
return 0; /* force done */ return 0; /* force done */
} }
if (otmp) context.takeoff.delay += objects[otmp->otyp].oc_delay; if (otmp) doff->delay += objects[otmp->otyp].oc_delay;
/* Since setting the occupation now starts the counter next move, that /* Since setting the occupation now starts the counter next move, that
* would always produce a delay 1 too big per item unless we subtract * would always produce a delay 1 too big per item unless we subtract
* 1 here to account for it. * 1 here to account for it.
*/ */
if (context.takeoff.delay>0) context.takeoff.delay--; if (doff->delay > 0) doff->delay--;
set_occupation(take_off, set_occupation(take_off, doff->disrobing, 0);
(context.takeoff.disrobing[0]) ?
context.takeoff.disrobing : (char *)0, 0);
return(1); /* get busy */ return(1); /* get busy */
} }
@@ -2002,6 +2087,7 @@ int retry;
return 0; return 0;
} }
/* hit by destroy armor scroll/black dragon breath/monster spell */
int int
destroy_arm(atmp) destroy_arm(atmp)
register struct obj *atmp; register struct obj *atmp;
@@ -2012,11 +2098,12 @@ register struct obj *atmp;
(!obj_resists(otmp, 0, 90))) (!obj_resists(otmp, 0, 90)))
if (DESTROY_ARM(uarmc)) { if (DESTROY_ARM(uarmc)) {
Your("%s crumbles and turns to dust!", cloak_simple_name(uarmc)); if (donning(otmp)) cancel_don();
Your("%s crumbles and turns to dust!",
cloak_simple_name(uarmc));
(void) Cloak_off(); (void) Cloak_off();
useup(otmp); useup(otmp);
} else if (DESTROY_ARM(uarm)) { } else if (DESTROY_ARM(uarm)) {
/* may be disintegrated by spell or dragon breath... */
if (donning(otmp)) cancel_don(); if (donning(otmp)) cancel_don();
Your("armor turns to dust and falls to the %s!", Your("armor turns to dust and falls to the %s!",
surface(u.ux,u.uy)); surface(u.ux,u.uy));
@@ -2024,7 +2111,9 @@ register struct obj *atmp;
useup(otmp); useup(otmp);
#ifdef TOURIST #ifdef TOURIST
} else if (DESTROY_ARM(uarmu)) { } else if (DESTROY_ARM(uarmu)) {
if (donning(otmp)) cancel_don();
Your("shirt crumbles into tiny threads and falls apart!"); Your("shirt crumbles into tiny threads and falls apart!");
(void) Shirt_off();
useup(otmp); useup(otmp);
#endif #endif
} else if (DESTROY_ARM(uarmh)) { } else if (DESTROY_ARM(uarmh)) {
@@ -2044,12 +2133,16 @@ register struct obj *atmp;
(void) Boots_off(); (void) Boots_off();
useup(otmp); useup(otmp);
} else if (DESTROY_ARM(uarms)) { } else if (DESTROY_ARM(uarms)) {
if (donning(otmp)) cancel_don();
Your("shield crumbles away!"); Your("shield crumbles away!");
(void) Shield_off(); (void) Shield_off();
useup(otmp); useup(otmp);
} else return(0); /* could not destroy anything */ } else {
return 0; /* could not destroy anything */
}
#undef DESTROY_ARM #undef DESTROY_ARM
stop_occupation();
return(1); return(1);
} }

View File

@@ -1,4 +1,4 @@
/* SCCS Id: @(#)steal.c 3.4 2002/09/07 */ /* SCCS Id: @(#)steal.c 3.4 2003/11/14 */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -195,6 +195,10 @@ boolean unchain_ball; /* whether to unpunish or just unwield */
else if (obj == uarmg) (void) Gloves_off(); else if (obj == uarmg) (void) Gloves_off();
else if (obj == uarmh) (void) Helmet_off(); else if (obj == uarmh) (void) Helmet_off();
else if (obj == uarms) (void) Shield_off(); else if (obj == uarms) (void) Shield_off();
#ifdef TOURIST
else if (obj == uarmu) (void) Shirt_off();
#endif
/* catchall -- should never happen */
else setworn((struct obj *)0, obj->owornmask & W_ARMOR); else setworn((struct obj *)0, obj->owornmask & W_ARMOR);
} else if (obj->owornmask & W_AMUL) { } else if (obj->owornmask & W_AMUL) {
Amulet_off(); Amulet_off();