/* NetHack 3.6 do_wear.c $NHDT-Date: 1432512763 2015/05/25 00:12:43 $ $NHDT-Branch: master $:$NHDT-Revision: 1.81 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ #include "hack.h" static NEARDATA const char see_yourself[] = "see yourself"; static NEARDATA const char unknown_type[] = "Unknown type of %s (%d)"; static NEARDATA const char c_armor[] = "armor", c_suit[] = "suit", c_shirt[] = "shirt", c_cloak[] = "cloak", c_gloves[] = "gloves", c_boots[] = "boots", c_helmet[] = "helmet", c_shield[] = "shield", c_weapon[] = "weapon", c_sword[] = "sword", c_axe[] = "axe", c_that_[] = "that"; static NEARDATA const long takeoff_order[] = { WORN_BLINDF, W_WEP, WORN_SHIELD, WORN_GLOVES, LEFT_RING, RIGHT_RING, WORN_CLOAK, WORN_HELMET, WORN_AMUL, WORN_ARMOR, WORN_SHIRT, WORN_BOOTS, W_SWAPWEP, W_QUIVER, 0L }; STATIC_DCL void FDECL(on_msg, (struct obj *)); STATIC_DCL void FDECL(toggle_stealth, (struct obj *, long, BOOLEAN_P)); STATIC_DCL void FDECL(toggle_displacement, (struct obj *, long, BOOLEAN_P)); STATIC_PTR int NDECL(Armor_on); STATIC_PTR int NDECL(Boots_on); STATIC_PTR int NDECL(Cloak_on); STATIC_PTR int NDECL(Helmet_on); STATIC_PTR int NDECL(Gloves_on); STATIC_DCL void FDECL(wielding_corpse, (struct obj *, BOOLEAN_P)); STATIC_PTR int NDECL(Shield_on); STATIC_PTR int NDECL(Shirt_on); STATIC_DCL void NDECL(Amulet_on); STATIC_DCL void FDECL(learnring, (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_DCL struct obj *NDECL(do_takeoff); STATIC_PTR int NDECL(take_off); STATIC_DCL int FDECL(menu_remarm, (int)); STATIC_DCL void FDECL(already_wearing, (const char *)); STATIC_DCL void FDECL(already_wearing2, (const char *, const char *)); void off_msg(otmp) struct obj *otmp; { if (flags.verbose) You("were wearing %s.", doname(otmp)); } /* for items that involve no delay */ STATIC_OVL void on_msg(otmp) struct obj *otmp; { if (flags.verbose) { char how[BUFSZ]; /* call xname() before obj_is_pname(); formatting obj's name might set obj->dknown and that affects the pname test */ const char *otmp_name = xname(otmp); how[0] = '\0'; if (otmp->otyp == TOWEL) Sprintf(how, " around your %s", body_part(HEAD)); You("are now wearing %s%s.", obj_is_pname(otmp) ? the(otmp_name) : an(otmp_name), how); } } /* starting equipment gets auto-worn at beginning of new game, and we don't want stealth or displacement feedback then */ static boolean initial_don = FALSE; /* manipulated in set_wear() */ /* putting on or taking off an item which confers stealth; give feedback and discover it iff stealth state is changing */ STATIC_OVL void toggle_stealth(obj, oldprop, on) struct obj *obj; long oldprop; /* prop[].extrinsic, with obj->owornmask stripped by caller */ boolean on; { if (on ? initial_don : context.takeoff.cancelled_don) return; if (!oldprop && /* extrinsic stealth from something else */ !HStealth && /* intrinsic stealth */ !BStealth) { /* stealth blocked by something */ if (obj->otyp == RIN_STEALTH) learnring(obj, TRUE); else makeknown(obj->otyp); if (on) { if (!is_boots(obj)) You("move very quietly."); else if (Levitation || Flying) You("float imperceptibly."); else You("walk very quietly."); } else { You("sure are noisy."); } } } /* putting on or taking off an item which confers displacement; give feedback and discover it iff displacement state is changing *and* hero is able to see self (or sense monsters) */ STATIC_OVL void toggle_displacement(obj, oldprop, on) struct obj *obj; long oldprop; /* prop[].extrinsic, with obj->owornmask stripped by caller */ boolean on; { if (on ? initial_don : context.takeoff.cancelled_don) return; if (!oldprop && /* extrinsic displacement from something else */ !(u.uprops[DISPLACED].intrinsic) && /* (theoretical) */ !(u.uprops[DISPLACED].blocked) && /* (also theoretical) */ /* we don't use canseeself() here because it augments vision with touch, which isn't appropriate for deciding whether we'll notice that monsters have trouble spotting the hero */ ((!Blind && /* see anything */ !u.uswallow && /* see surroundings */ !Invisible) || /* see self */ /* actively sensing nearby monsters via telepathy or extended monster detection overrides vision considerations because hero also senses self in this situation */ (Unblind_telepat || (Blind_telepat && Blind) || Detect_monsters))) { makeknown(obj->otyp); You_feel("that monsters%s have difficulty pinpointing your location.", on ? "" : " no longer"); } } /* * The Type_on() functions should be called *after* setworn(). * The Type_off() functions call setworn() themselves. * [Blindf_on() is an exception and calls setworn() itself.] */ STATIC_PTR int Boots_on(VOID_ARGS) { long oldprop = u.uprops[objects[uarmf->otyp].oc_oprop].extrinsic & ~WORN_BOOTS; switch (uarmf->otyp) { case LOW_BOOTS: case IRON_SHOES: case HIGH_BOOTS: case JUMPING_BOOTS: case KICKING_BOOTS: break; case WATER_WALKING_BOOTS: if (u.uinwater) spoteffects(TRUE); /* (we don't need a lava check here since boots can't be put on while feet are stuck) */ break; case SPEED_BOOTS: /* Speed boots are still better than intrinsic speed, */ /* though not better than potion speed */ if (!oldprop && !(HFast & TIMEOUT)) { makeknown(uarmf->otyp); You_feel("yourself speed up%s.", (oldprop || HFast) ? " a bit more" : ""); } break; case ELVEN_BOOTS: toggle_stealth(uarmf, oldprop, TRUE); break; case FUMBLE_BOOTS: if (!oldprop && !(HFumbling & ~TIMEOUT)) incr_itimeout(&HFumbling, rnd(20)); break; case LEVITATION_BOOTS: if (!oldprop && !HLevitation && !BLevitation) { makeknown(uarmf->otyp); float_up(); spoteffects(FALSE); } else { float_vs_flight(); /* maybe toggle (BFlying & I_SPECIAL) */ } break; default: impossible(unknown_type, c_boots, uarmf->otyp); } return 0; } int Boots_off(VOID_ARGS) { struct obj *otmp = uarmf; int otyp = otmp->otyp; 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 * must do a setworn() _before_ the levitation case. */ setworn((struct obj *) 0, W_ARMF); switch (otyp) { case SPEED_BOOTS: if (!Very_fast && !context.takeoff.cancelled_don) { makeknown(otyp); You_feel("yourself slow down%s.", Fast ? " a bit" : ""); } break; case WATER_WALKING_BOOTS: /* check for lava since fireproofed boots make it viable */ if ((is_pool(u.ux, u.uy) || is_lava(u.ux, u.uy)) && !Levitation && !Flying && !is_clinger(youmonst.data) && !context.takeoff.cancelled_don && /* avoid recursive call to lava_effects() */ !iflags.in_lava_effects) { /* make boots known in case you survive the drowning */ makeknown(otyp); spoteffects(TRUE); } break; case ELVEN_BOOTS: toggle_stealth(otmp, oldprop, FALSE); break; case FUMBLE_BOOTS: if (!oldprop && !(HFumbling & ~TIMEOUT)) HFumbling = EFumbling = 0; break; case LEVITATION_BOOTS: if (!oldprop && !HLevitation && !BLevitation && !context.takeoff.cancelled_don) { (void) float_down(0L, 0L); makeknown(otyp); } else { float_vs_flight(); /* maybe toggle (BFlying & I_SPECIAL) */ } break; case LOW_BOOTS: case IRON_SHOES: case HIGH_BOOTS: case JUMPING_BOOTS: case KICKING_BOOTS: break; default: impossible(unknown_type, c_boots, otyp); } context.takeoff.cancelled_don = FALSE; return 0; } STATIC_PTR int Cloak_on(VOID_ARGS) { long oldprop = u.uprops[objects[uarmc->otyp].oc_oprop].extrinsic & ~WORN_CLOAK; switch (uarmc->otyp) { case ORCISH_CLOAK: case DWARVISH_CLOAK: case CLOAK_OF_MAGIC_RESISTANCE: case ROBE: case LEATHER_CLOAK: break; case CLOAK_OF_PROTECTION: makeknown(uarmc->otyp); break; case ELVEN_CLOAK: toggle_stealth(uarmc, oldprop, TRUE); break; case CLOAK_OF_DISPLACEMENT: toggle_displacement(uarmc, oldprop, TRUE); break; case MUMMY_WRAPPING: /* Note: it's already being worn, so we have to cheat here. */ if ((HInvis || EInvis) && !Blind) { newsym(u.ux, u.uy); You("can %s!", See_invisible ? "no longer see through yourself" : see_yourself); } break; case CLOAK_OF_INVISIBILITY: /* since cloak of invisibility was worn, we know mummy wrapping wasn't, so no need to check `oldprop' against blocked */ if (!oldprop && !HInvis && !Blind) { makeknown(uarmc->otyp); newsym(u.ux, u.uy); pline("Suddenly you can%s yourself.", See_invisible ? " see through" : "not see"); } break; case OILSKIN_CLOAK: pline("%s very tightly.", Tobjnam(uarmc, "fit")); break; /* Alchemy smock gives poison _and_ acid resistance */ case ALCHEMY_SMOCK: EAcid_resistance |= WORN_CLOAK; break; default: impossible(unknown_type, c_cloak, uarmc->otyp); } return 0; } int Cloak_off(VOID_ARGS) { struct obj *otmp = uarmc; int otyp = otmp->otyp; 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'. */ setworn((struct obj *) 0, W_ARMC); switch (otyp) { case ORCISH_CLOAK: case DWARVISH_CLOAK: case CLOAK_OF_PROTECTION: case CLOAK_OF_MAGIC_RESISTANCE: case OILSKIN_CLOAK: case ROBE: case LEATHER_CLOAK: break; case ELVEN_CLOAK: toggle_stealth(otmp, oldprop, FALSE); break; case CLOAK_OF_DISPLACEMENT: toggle_displacement(otmp, oldprop, FALSE); break; case MUMMY_WRAPPING: if (Invis && !Blind) { newsym(u.ux, u.uy); You("can %s.", See_invisible ? "see through yourself" : "no longer see yourself"); } break; case CLOAK_OF_INVISIBILITY: if (!oldprop && !HInvis && !Blind) { makeknown(CLOAK_OF_INVISIBILITY); newsym(u.ux, u.uy); pline("Suddenly you can %s.", See_invisible ? "no longer see through yourself" : see_yourself); } break; /* Alchemy smock gives poison _and_ acid resistance */ case ALCHEMY_SMOCK: EAcid_resistance &= ~WORN_CLOAK; break; default: impossible(unknown_type, c_cloak, otyp); } return 0; } STATIC_PTR int Helmet_on(VOID_ARGS) { switch (uarmh->otyp) { case FEDORA: case HELMET: case DENTED_POT: case ELVEN_LEATHER_HELM: case DWARVISH_IRON_HELM: case ORCISH_HELM: case HELM_OF_TELEPATHY: break; case HELM_OF_BRILLIANCE: adj_abon(uarmh, uarmh->spe); break; case CORNUTHAUM: /* people think marked wizards know what they're talking * about, but it takes trained arrogance to pull it off, * and the actual enchantment of the hat is irrelevant. */ ABON(A_CHA) += (Role_if(PM_WIZARD) ? 1 : -1); context.botl = 1; makeknown(uarmh->otyp); break; case HELM_OF_OPPOSITE_ALIGNMENT: /* changing alignment can toggle off active artifact properties, including levitation; uarmh could get dropped or destroyed here */ uchangealign((u.ualign.type != A_NEUTRAL) ? -u.ualign.type : (uarmh->o_id % 2) ? A_CHAOTIC : A_LAWFUL, 1); /* makeknown(uarmh->otyp); -- moved below, after xname() */ /*FALLTHRU*/ case DUNCE_CAP: if (uarmh && !uarmh->cursed) { if (Blind) pline("%s for a moment.", Tobjnam(uarmh, "vibrate")); else pline("%s %s for a moment.", Tobjnam(uarmh, "glow"), hcolor(NH_BLACK)); curse(uarmh); } context.botl = 1; /* reveal new alignment or INT & WIS */ if (Hallucination) { pline("My brain hurts!"); /* Monty Python's Flying Circus */ } else if (uarmh && uarmh->otyp == DUNCE_CAP) { You_feel("%s.", /* track INT change; ignore WIS */ ACURR(A_INT) <= (ABASE(A_INT) + ABON(A_INT) + ATEMP(A_INT)) ? "like sitting in a corner" : "giddy"); } else { /* [message moved to uchangealign()] */ makeknown(HELM_OF_OPPOSITE_ALIGNMENT); } break; default: impossible(unknown_type, c_helmet, uarmh->otyp); } return 0; } int Helmet_off(VOID_ARGS) { context.takeoff.mask &= ~W_ARMH; switch (uarmh->otyp) { case FEDORA: case HELMET: case DENTED_POT: case ELVEN_LEATHER_HELM: case DWARVISH_IRON_HELM: case ORCISH_HELM: break; case DUNCE_CAP: context.botl = 1; break; case CORNUTHAUM: if (!context.takeoff.cancelled_don) { ABON(A_CHA) += (Role_if(PM_WIZARD) ? -1 : 1); context.botl = 1; } break; case HELM_OF_TELEPATHY: /* need to update ability before calling see_monsters() */ setworn((struct obj *) 0, W_ARMH); see_monsters(); return 0; case HELM_OF_BRILLIANCE: if (!context.takeoff.cancelled_don) adj_abon(uarmh, -uarmh->spe); break; case HELM_OF_OPPOSITE_ALIGNMENT: /* changing alignment can toggle off active artifact properties, including levitation; uarmh could get dropped or destroyed here */ uchangealign(u.ualignbase[A_CURRENT], 2); break; default: impossible(unknown_type, c_helmet, uarmh->otyp); } setworn((struct obj *) 0, W_ARMH); context.takeoff.cancelled_don = FALSE; return 0; } STATIC_PTR int Gloves_on(VOID_ARGS) { long oldprop = u.uprops[objects[uarmg->otyp].oc_oprop].extrinsic & ~WORN_GLOVES; switch (uarmg->otyp) { case LEATHER_GLOVES: break; case GAUNTLETS_OF_FUMBLING: if (!oldprop && !(HFumbling & ~TIMEOUT)) incr_itimeout(&HFumbling, rnd(20)); break; case GAUNTLETS_OF_POWER: makeknown(uarmg->otyp); context.botl = 1; /* taken care of in attrib.c */ break; case GAUNTLETS_OF_DEXTERITY: adj_abon(uarmg, uarmg->spe); break; default: impossible(unknown_type, c_gloves, uarmg->otyp); } return 0; } STATIC_OVL void wielding_corpse(obj, voluntary) struct obj *obj; boolean voluntary; /* taking gloves off on purpose? */ { char kbuf[BUFSZ]; if (!obj || obj->otyp != CORPSE) return; if (obj != uwep && (obj != uswapwep || !u.twoweap)) return; if (touch_petrifies(&mons[obj->corpsenm]) && !Stone_resistance) { You("now wield %s in your bare %s.", corpse_xname(obj, (const char *) 0, CXN_ARTICLE), makeplural(body_part(HAND))); Sprintf(kbuf, "%s gloves while wielding %s", voluntary ? "removing" : "losing", killer_xname(obj)); instapetrify(kbuf); /* life-saved; can't continue wielding cockatrice corpse though */ remove_worn_item(obj, FALSE); } } int Gloves_off(VOID_ARGS) { long oldprop = u.uprops[objects[uarmg->otyp].oc_oprop].extrinsic & ~WORN_GLOVES; boolean on_purpose = !context.mon_moving && !uarmg->in_use; context.takeoff.mask &= ~W_ARMG; switch (uarmg->otyp) { case LEATHER_GLOVES: break; case GAUNTLETS_OF_FUMBLING: if (!oldprop && !(HFumbling & ~TIMEOUT)) HFumbling = EFumbling = 0; break; case GAUNTLETS_OF_POWER: makeknown(uarmg->otyp); context.botl = 1; /* taken care of in attrib.c */ break; case GAUNTLETS_OF_DEXTERITY: if (!context.takeoff.cancelled_don) adj_abon(uarmg, -uarmg->spe); break; default: impossible(unknown_type, c_gloves, uarmg->otyp); } setworn((struct obj *) 0, W_ARMG); context.takeoff.cancelled_don = FALSE; (void) encumber_msg(); /* immediate feedback for GoP */ /* prevent wielding cockatrice when not wearing gloves */ if (uwep && uwep->otyp == CORPSE) wielding_corpse(uwep, on_purpose); /* KMH -- ...or your secondary weapon when you're wielding it [This case can't actually happen; twoweapon mode won't engage if a corpse has been set up as the alternate weapon.] */ if (u.twoweap && uswapwep && uswapwep->otyp == CORPSE) wielding_corpse(uswapwep, on_purpose); return 0; } STATIC_PTR int Shield_on(VOID_ARGS) { /* switch (uarms->otyp) { case SMALL_SHIELD: case ELVEN_SHIELD: case URUK_HAI_SHIELD: case ORCISH_SHIELD: case DWARVISH_ROUNDSHIELD: case LARGE_SHIELD: case SHIELD_OF_REFLECTION: break; default: impossible(unknown_type, c_shield, uarms->otyp); } */ return 0; } int Shield_off(VOID_ARGS) { context.takeoff.mask &= ~W_ARMS; /* switch (uarms->otyp) { case SMALL_SHIELD: case ELVEN_SHIELD: case URUK_HAI_SHIELD: case ORCISH_SHIELD: case DWARVISH_ROUNDSHIELD: case LARGE_SHIELD: case SHIELD_OF_REFLECTION: break; default: impossible(unknown_type, c_shield, uarms->otyp); } */ setworn((struct obj *) 0, W_ARMS); return 0; } STATIC_PTR int Shirt_on(VOID_ARGS) { /* switch (uarmu->otyp) { case HAWAIIAN_SHIRT: case T_SHIRT: break; default: impossible(unknown_type, c_shirt, uarmu->otyp); } */ return 0; } int Shirt_off(VOID_ARGS) { 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; } /* 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 * since worn.c will check it before returning. */ STATIC_PTR int Armor_on(VOID_ARGS) { return 0; } int Armor_off(VOID_ARGS) { context.takeoff.mask &= ~W_ARM; setworn((struct obj *) 0, W_ARM); context.takeoff.cancelled_don = FALSE; return 0; } /* The gone functions differ from the off functions in that if you die from * taking it off and have life saving, you still die. */ int Armor_gone() { context.takeoff.mask &= ~W_ARM; setnotworn(uarm); context.takeoff.cancelled_don = FALSE; return 0; } STATIC_OVL void Amulet_on() { /* make sure amulet isn't wielded; can't use remove_worn_item() here because it has already been set worn in amulet slot */ if (uamul == uwep) setuwep((struct obj *) 0); else if (uamul == uswapwep) setuswapwep((struct obj *) 0); else if (uamul == uquiver) setuqwep((struct obj *) 0); switch (uamul->otyp) { case AMULET_OF_ESP: case AMULET_OF_LIFE_SAVING: case AMULET_VERSUS_POISON: case AMULET_OF_REFLECTION: case AMULET_OF_MAGICAL_BREATHING: case FAKE_AMULET_OF_YENDOR: break; case AMULET_OF_UNCHANGING: if (Slimed) make_slimed(0L, (char *) 0); break; case AMULET_OF_CHANGE: { int orig_sex = poly_gender(); if (Unchanging) break; change_sex(); /* Don't use same message as polymorph */ if (orig_sex != poly_gender()) { makeknown(AMULET_OF_CHANGE); You("are suddenly very %s!", flags.female ? "feminine" : "masculine"); context.botl = 1; } else /* already polymorphed into single-gender monster; only changed the character's base sex */ You("don't feel like yourself."); pline_The("amulet disintegrates!"); if (orig_sex == poly_gender() && uamul->dknown && !objects[AMULET_OF_CHANGE].oc_name_known && !objects[AMULET_OF_CHANGE].oc_uname) docall(uamul); useup(uamul); break; } case AMULET_OF_STRANGULATION: if (can_be_strangled(&youmonst)) { makeknown(AMULET_OF_STRANGULATION); pline("It constricts your throat!"); Strangled = 6L; } break; case AMULET_OF_RESTFUL_SLEEP: { long newnap = (long) rnd(100), oldnap = (HSleepy & TIMEOUT); /* avoid clobbering FROMOUTSIDE bit, which might have gotten set by previously eating one of these amulets */ if (newnap < oldnap || oldnap == 0L) HSleepy = (HSleepy & ~TIMEOUT) | newnap; } break; case AMULET_OF_YENDOR: break; } } void Amulet_off() { context.takeoff.mask &= ~W_AMUL; switch (uamul->otyp) { case AMULET_OF_ESP: /* need to update ability before calling see_monsters() */ setworn((struct obj *) 0, W_AMUL); see_monsters(); return; case AMULET_OF_LIFE_SAVING: case AMULET_VERSUS_POISON: case AMULET_OF_REFLECTION: case AMULET_OF_CHANGE: case AMULET_OF_UNCHANGING: case FAKE_AMULET_OF_YENDOR: break; case AMULET_OF_MAGICAL_BREATHING: if (Underwater) { /* HMagical_breathing must be set off before calling drown() */ setworn((struct obj *) 0, W_AMUL); if (!breathless(youmonst.data) && !amphibious(youmonst.data) && !Swimming) { You("suddenly inhale an unhealthy amount of water!"); (void) drown(); } return; } break; case AMULET_OF_STRANGULATION: if (Strangled) { if (Breathless) Your("%s is no longer constricted!", body_part(NECK)); else You("can breathe more easily!"); Strangled = 0L; } break; case AMULET_OF_RESTFUL_SLEEP: setworn((struct obj *) 0, W_AMUL); /* HSleepy = 0L; -- avoid clobbering FROMOUTSIDE bit */ if (!ESleepy && !(HSleepy & ~TIMEOUT)) HSleepy &= ~TIMEOUT; /* clear timeout bits */ return; case AMULET_OF_YENDOR: break; } setworn((struct obj *) 0, W_AMUL); return; } /* handle ring discovery; comparable to learnwand() */ STATIC_OVL void learnring(ring, observed) struct obj *ring; boolean observed; { int ringtype = ring->otyp; /* if effect was observeable then we usually discover the type */ if (observed) { /* if we already know the ring type which accomplishes this effect (assumes there is at most one type for each effect), mark this ring as having been seen (no need for makeknown); otherwise if we have seen this ring, discover its type */ if (objects[ringtype].oc_name_known) ring->dknown = 1; else if (ring->dknown) makeknown(ringtype); #if 0 /* see learnwand() */ else ring->eknown = 1; #endif } /* make enchantment of charged ring known (might be +0) and update perm invent window if we've seen this ring and know its type */ if (ring->dknown && objects[ringtype].oc_name_known) { if (objects[ringtype].oc_charged) ring->known = 1; update_inventory(); } } void Ring_on(obj) register struct obj *obj; { long oldprop = u.uprops[objects[obj->otyp].oc_oprop].extrinsic; int old_attrib, which; boolean observable; /* make sure ring isn't wielded; can't use remove_worn_item() here because it has already been set worn in a ring slot */ if (obj == uwep) setuwep((struct obj *) 0); else if (obj == uswapwep) setuswapwep((struct obj *) 0); else if (obj == uquiver) setuqwep((struct obj *) 0); /* only mask out W_RING when we don't have both left and right rings of the same type */ if ((oldprop & W_RING) != W_RING) oldprop &= ~W_RING; switch (obj->otyp) { case RIN_TELEPORTATION: case RIN_REGENERATION: case RIN_SEARCHING: case RIN_HUNGER: case RIN_AGGRAVATE_MONSTER: case RIN_POISON_RESISTANCE: case RIN_FIRE_RESISTANCE: case RIN_COLD_RESISTANCE: case RIN_SHOCK_RESISTANCE: case RIN_CONFLICT: case RIN_TELEPORT_CONTROL: case RIN_POLYMORPH: case RIN_POLYMORPH_CONTROL: case RIN_FREE_ACTION: case RIN_SLOW_DIGESTION: case RIN_SUSTAIN_ABILITY: case MEAT_RING: break; case RIN_STEALTH: toggle_stealth(obj, oldprop, TRUE); break; case RIN_WARNING: see_monsters(); break; case RIN_SEE_INVISIBLE: /* can now see invisible monsters */ set_mimic_blocking(); /* do special mimic handling */ see_monsters(); if (Invis && !oldprop && !HSee_invisible && !Blind) { newsym(u.ux, u.uy); pline("Suddenly you are transparent, but there!"); learnring(obj, TRUE); } break; case RIN_INVISIBILITY: if (!oldprop && !HInvis && !BInvis && !Blind) { learnring(obj, TRUE); newsym(u.ux, u.uy); self_invis_message(); } break; case RIN_LEVITATION: if (!oldprop && !HLevitation && !BLevitation) { float_up(); learnring(obj, TRUE); spoteffects(FALSE); /* for sinks */ } else { float_vs_flight(); /* maybe toggle (BFlying & I_SPECIAL) */ } break; case RIN_GAIN_STRENGTH: which = A_STR; goto adjust_attrib; case RIN_GAIN_CONSTITUTION: which = A_CON; goto adjust_attrib; case RIN_ADORNMENT: which = A_CHA; adjust_attrib: old_attrib = ACURR(which); ABON(which) += obj->spe; observable = (old_attrib != ACURR(which)); /* if didn't change, usually means ring is +0 but might be because nonzero couldn't go below min or above max; learn +0 enchantment if attribute value is not stuck at a limit [and ring has been seen and its type is already discovered, both handled by learnring()] */ if (observable || !extremeattr(which)) learnring(obj, observable); context.botl = 1; break; case RIN_INCREASE_ACCURACY: /* KMH */ u.uhitinc += obj->spe; break; case RIN_INCREASE_DAMAGE: u.udaminc += obj->spe; break; case RIN_PROTECTION_FROM_SHAPE_CHAN: rescham(); break; case RIN_PROTECTION: /* usually learn enchantment and discover type; won't happen if ring is unseen or if it's +0 and the type hasn't been discovered yet */ observable = (obj->spe != 0); learnring(obj, observable); if (obj->spe) find_ac(); /* updates botl */ break; } } STATIC_OVL void Ring_off_or_gone(obj, gone) register struct obj *obj; boolean gone; { long mask = (obj->owornmask & W_RING); int old_attrib, which; boolean observable; context.takeoff.mask &= ~mask; if (!(u.uprops[objects[obj->otyp].oc_oprop].extrinsic & mask)) impossible("Strange... I didn't know you had that ring."); if (gone) setnotworn(obj); else setworn((struct obj *) 0, obj->owornmask); switch (obj->otyp) { case RIN_TELEPORTATION: case RIN_REGENERATION: case RIN_SEARCHING: case RIN_HUNGER: case RIN_AGGRAVATE_MONSTER: case RIN_POISON_RESISTANCE: case RIN_FIRE_RESISTANCE: case RIN_COLD_RESISTANCE: case RIN_SHOCK_RESISTANCE: case RIN_CONFLICT: case RIN_TELEPORT_CONTROL: case RIN_POLYMORPH: case RIN_POLYMORPH_CONTROL: case RIN_FREE_ACTION: case RIN_SLOW_DIGESTION: case RIN_SUSTAIN_ABILITY: case MEAT_RING: break; case RIN_STEALTH: toggle_stealth(obj, (EStealth & ~mask), FALSE); break; case RIN_WARNING: see_monsters(); break; case RIN_SEE_INVISIBLE: /* Make invisible monsters go away */ if (!See_invisible) { set_mimic_blocking(); /* do special mimic handling */ see_monsters(); } if (Invisible && !Blind) { newsym(u.ux, u.uy); pline("Suddenly you cannot see yourself."); learnring(obj, TRUE); } break; case RIN_INVISIBILITY: if (!Invis && !BInvis && !Blind) { newsym(u.ux, u.uy); Your("body seems to unfade%s.", See_invisible ? " completely" : ".."); learnring(obj, TRUE); } break; case RIN_LEVITATION: if (!BLevitation) { (void) float_down(0L, 0L); if (!Levitation) learnring(obj, TRUE); } else { float_vs_flight(); /* maybe toggle (BFlying & I_SPECIAL) */ } break; case RIN_GAIN_STRENGTH: which = A_STR; goto adjust_attrib; case RIN_GAIN_CONSTITUTION: which = A_CON; goto adjust_attrib; case RIN_ADORNMENT: which = A_CHA; adjust_attrib: old_attrib = ACURR(which); ABON(which) -= obj->spe; observable = (old_attrib != ACURR(which)); /* same criteria as Ring_on() */ if (observable || !extremeattr(which)) learnring(obj, observable); context.botl = 1; break; case RIN_INCREASE_ACCURACY: /* KMH */ u.uhitinc -= obj->spe; break; case RIN_INCREASE_DAMAGE: u.udaminc -= obj->spe; break; case RIN_PROTECTION: /* might have been put on while blind and we can now see or perhaps been forgotten due to amnesia */ observable = (obj->spe != 0); learnring(obj, observable); if (obj->spe) find_ac(); /* updates botl */ break; case RIN_PROTECTION_FROM_SHAPE_CHAN: /* If you're no longer protected, let the chameleons * change shape again -dgk */ restartcham(); break; } } void Ring_off(obj) struct obj *obj; { Ring_off_or_gone(obj, FALSE); } void Ring_gone(obj) struct obj *obj; { Ring_off_or_gone(obj, TRUE); } void Blindf_on(otmp) register struct obj *otmp; { boolean already_blind = Blind, changed = FALSE; /* blindfold might be wielded; release it for wearing */ if (otmp->owornmask & (W_WEP | W_SWAPWEP | W_QUIVER)) remove_worn_item(otmp, FALSE); setworn(otmp, W_TOOL); on_msg(otmp); if (Blind && !already_blind) { changed = TRUE; if (flags.verbose) You_cant("see any more."); /* set ball&chain variables before the hero goes blind */ if (Punished) set_bc(0); } else if (already_blind && !Blind) { changed = TRUE; /* "You are now wearing the Eyes of the Overworld." */ You("can see!"); } if (changed) { /* blindness has just been toggled */ if (Blind_telepat || Infravision) see_monsters(); vision_full_recalc = 1; /* recalc vision limits */ if (!Blind) learn_unseen_invent(); context.botl = 1; } } void Blindf_off(otmp) register struct obj *otmp; { boolean was_blind = Blind, changed = FALSE; context.takeoff.mask &= ~W_TOOL; setworn((struct obj *) 0, otmp->owornmask); off_msg(otmp); if (Blind) { if (was_blind) { /* "still cannot see" makes no sense when removing lenses since they can't have been the cause of your blindness */ if (otmp->otyp != LENSES) You("still cannot see."); } else { changed = TRUE; /* !was_blind */ /* "You were wearing the Eyes of the Overworld." */ You_cant("see anything now!"); /* set ball&chain variables before the hero goes blind */ if (Punished) set_bc(0); } } else if (was_blind) { if (!gulp_blnd_check()) { changed = TRUE; /* !Blind */ You("can see again."); } } if (changed) { /* blindness has just been toggled */ if (Blind_telepat || Infravision) see_monsters(); vision_full_recalc = 1; /* recalc vision limits */ if (!Blind) learn_unseen_invent(); context.botl = 1; } } /* called in moveloop()'s prologue to set side-effects of worn start-up items; also used by poly_obj() when a worn item gets transformed */ void set_wear(obj) struct obj *obj; /* if null, do all worn items; otherwise just obj itself */ { initial_don = !obj; if (!obj ? ublindf != 0 : (obj == ublindf)) (void) Blindf_on(ublindf); if (!obj ? uright != 0 : (obj == uright)) (void) Ring_on(uright); if (!obj ? uleft != 0 : (obj == uleft)) (void) Ring_on(uleft); if (!obj ? uamul != 0 : (obj == uamul)) (void) Amulet_on(); if (!obj ? uarmu != 0 : (obj == uarmu)) (void) Shirt_on(); if (!obj ? uarm != 0 : (obj == uarm)) (void) Armor_on(); if (!obj ? uarmc != 0 : (obj == uarmc)) (void) Cloak_on(); if (!obj ? uarmf != 0 : (obj == uarmf)) (void) Boots_on(); if (!obj ? uarmg != 0 : (obj == uarmg)) (void) Gloves_on(); if (!obj ? uarmh != 0 : (obj == uarmh)) (void) Helmet_on(); if (!obj ? uarms != 0 : (obj == uarms)) (void) Shield_on(); initial_don = FALSE; } /* check whether the target object is currently being put on (or taken off) */ boolean donning(otmp) /* also checks for doffing */ register struct obj *otmp; { /* long what = (occupation == take_off) ? context.takeoff.what : 0L; */ long what = context.takeoff.what; /* if nonzero, occupation is implied */ boolean result = FALSE; /* 'W' and 'T' set afternmv, 'A' sets context.takeoff.what */ if (otmp == uarm) result = (afternmv == Armor_on || afternmv == Armor_off || what == WORN_ARMOR); else if (otmp == uarmu) result = (afternmv == Shirt_on || afternmv == Shirt_off || what == WORN_SHIRT); 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; } /* check whether the target object is currently being taken off, so that stop_donning() and steal() can vary messages */ boolean doffing(otmp) struct obj *otmp; { long what = context.takeoff.what; boolean result = FALSE; /* 'T' (also 'W') sets afternmv, 'A' sets context.takeoff.what */ if (otmp == uarm) result = (afternmv == Armor_off || what == WORN_ARMOR); else if (otmp == uarmu) result = (afternmv == Shirt_off || what == WORN_SHIRT); else if (otmp == uarmc) result = (afternmv == Cloak_off || what == WORN_CLOAK); else if (otmp == uarmf) result = (afternmv == Boots_off || what == WORN_BOOTS); else if (otmp == uarmh) result = (afternmv == Helmet_off || what == WORN_HELMET); else if (otmp == uarmg) result = (afternmv == Gloves_off || what == WORN_GLOVES); else if (otmp == uarms) result = (afternmv == Shield_off || what == WORN_SHIELD); return result; } void cancel_don() { /* the piece of armor we were donning/doffing has vanished, so stop * wasting time on it (and don't dereference it when donning would * otherwise finish) */ context.takeoff.cancelled_don = (afternmv == Boots_on || afternmv == Helmet_on || afternmv == Gloves_on || afternmv == Armor_on); afternmv = 0; nomovemsg = (char *) 0; multi = 0; context.takeoff.delay = 0; context.takeoff.what = 0L; } /* called by steal() during theft from hero; interrupt donning/doffing */ int stop_donning(stolenobj) struct obj *stolenobj; /* no message if stolenobj is already being doffing */ { char buf[BUFSZ]; struct obj *otmp; boolean putting_on; int result = 0; for (otmp = invent; otmp; otmp = otmp->nobj) if ((otmp->owornmask & W_ARMOR) && donning(otmp)) break; /* at most one item will pass donning() test at any given time */ if (!otmp) return 0; /* donning() returns True when doffing too; doffing() is more specific */ putting_on = !doffing(otmp); /* cancel_don() looks at afternmv; it also serves as cancel_doff() */ cancel_don(); /* don't want _on() or _off() being called by unmul() since the on or off action isn't completing */ afternmv = 0; if (putting_on || otmp != stolenobj) { Sprintf(buf, "You stop %s %s.", putting_on ? "putting on" : "taking off", thesimpleoname(otmp)); } else { buf[0] = '\0'; /* silently stop doffing stolenobj */ result = -multi; /* remember this before calling unmul() */ } unmul(buf); /* while putting on, item becomes worn immediately but side-effects are deferred until the delay expires; when interrupted, make it unworn (while taking off, item stays worn until the delay expires; when interrupted, leave it worn) */ if (putting_on) remove_worn_item(otmp, FALSE); return result; } 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() { register struct obj *otmp = (struct obj *) 0; int armorpieces = 0; #define MOREARM(x) \ if (x) { \ armorpieces++; \ otmp = x; \ } MOREARM(uarmh); MOREARM(uarms); MOREARM(uarmg); MOREARM(uarmf); if (uarmc) { armorpieces++; otmp = uarmc; } else if (uarm) { armorpieces++; otmp = uarm; } else if (uarmu) { armorpieces++; otmp = uarmu; } if (!armorpieces) { /* assert( GRAY_DRAGON_SCALES > YELLOW_DRAGON_SCALE_MAIL ); */ if (uskin) pline_The("%s merged with your skin!", uskin->otyp >= GRAY_DRAGON_SCALES ? "dragon scales are" : "dragon scale mail is"); else pline("Not wearing any armor.%s", (iflags.cmdassist && (uleft || uright || uamul || ublindf)) ? " Use 'R' command to remove accessories." : ""); return 0; } if (armorpieces > 1 || ParanoidRemove) otmp = getobj(clothes, "take off"); if (!otmp) return 0; if (!(otmp->owornmask & W_ARMOR)) { You("are not wearing that."); return 0; } /* note: the `uskin' case shouldn't be able to happen here; dragons can't wear any armor so will end up with `armorpieces == 0' above */ if (otmp == uskin || ((otmp == uarm) && uarmc) || ((otmp == uarmu) && (uarmc || uarm))) { char why[BUFSZ], what[BUFSZ]; why[0] = what[0] = '\0'; if (otmp != uskin) { if (uarmc) Strcat(what, cloak_simple_name(uarmc)); if ((otmp == uarmu) && uarm) { if (uarmc) Strcat(what, " and "); Strcat(what, suit_simple_name(uarm)); } Sprintf(why, " without taking off your %s first", what); } You_cant("take that off%s.", why); return 0; } reset_remarm(); /* clear context.takeoff.mask and context.takeoff.what */ (void) select_off(otmp); if (!context.takeoff.mask) return 0; reset_remarm(); /* armoroff() doesn't use context.takeoff.mask */ (void) armoroff(otmp); return (1); } /* the 'R' command */ int doremring() { register struct obj *otmp = 0; int Accessories = 0; #define MOREACC(x) \ if (x) { \ Accessories++; \ otmp = x; \ } MOREACC(uleft); MOREACC(uright); MOREACC(uamul); MOREACC(ublindf); if (!Accessories) { pline("Not wearing any accessories.%s", (iflags.cmdassist && (uarm || uarmc || uarmu || uarms || uarmh || uarmg || uarmf)) ? " Use 'T' command to take off armor." : ""); return (0); } if (Accessories > 1 || ParanoidRemove) otmp = getobj(accessories, "remove"); if (!otmp) return 0; if (!(otmp->owornmask & (W_RING | W_AMUL | W_TOOL))) { You("are not wearing that."); return 0; } reset_remarm(); /* clear context.takeoff.mask and context.takeoff.what */ (void) select_off(otmp); if (!context.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 * square amulet (being worn)" is not because of the redundant * "being worn". */ off_msg(otmp); Ring_off(otmp); } else if (otmp == uamul) { Amulet_off(); off_msg(otmp); } else if (otmp == ublindf) { Blindf_off(otmp); /* does its own off_msg */ } else { impossible("removing strange accessory?"); } return (1); } /* Check if something worn is cursed _and_ unremovable. */ int cursed(otmp) register struct obj *otmp; { /* Curses, like chickens, come home to roost. */ if ((otmp == uwep) ? welded(otmp) : (int) otmp->cursed) { boolean use_plural = (is_boots(otmp) || is_gloves(otmp) || otmp->otyp == LENSES || otmp->quan > 1L); You("can't. %s cursed.", use_plural ? "They are" : "It is"); otmp->bknown = TRUE; return (1); } return (0); } int armoroff(otmp) register struct obj *otmp; { register int delay = -objects[otmp->otyp].oc_delay; if (cursed(otmp)) return (0); if (delay) { nomul(delay); multi_reason = "disrobing"; if (is_helmet(otmp)) { /* ick... */ nomovemsg = !strcmp(helm_simple_name(otmp), "hat") ? "You finish taking off your hat." : "You finish taking off your helmet."; afternmv = Helmet_off; } else if (is_gloves(otmp)) { nomovemsg = "You finish taking off your gloves."; afternmv = Gloves_off; } else if (is_boots(otmp)) { nomovemsg = "You finish taking off your boots."; afternmv = Boots_off; } else { nomovemsg = "You finish taking off your suit."; afternmv = Armor_off; } } else { /* Be warned! We want off_msg after removing the item to * avoid "You were wearing ____ (being worn)." However, an * item which grants fire resistance might cause some trouble * if removed in Hell and lifesaving puts it back on; in this * case the message will be printed at the wrong time (after * the messages saying you died and were lifesaved). Luckily, * no cloak, shield, or fast-removable armor grants fire * resistance, so we can safely do the off_msg afterwards. * Rings do grant fire resistance, but for rings we want the * off_msg before removal anyway so there's no problem. Take * care in adding armors granting fire resistance; this code * might need modification. * 3.2 (actually 3.1 even): that comment is obsolete since * fire resistance is not required for Gehennom so setworn() * doesn't force the resistance granting item to be re-worn * after being lifesaved anymore. */ if (is_cloak(otmp)) (void) Cloak_off(); else if (is_shield(otmp)) (void) Shield_off(); else setworn((struct obj *) 0, otmp->owornmask & W_ARMOR); off_msg(otmp); } context.takeoff.mask = context.takeoff.what = 0L; return (1); } STATIC_OVL void already_wearing(cc) const char *cc; { You("are already wearing %s%c", cc, (cc == c_that_) ? '!' : '.'); } STATIC_OVL void already_wearing2(cc1, cc2) const char *cc1, *cc2; { You_cant("wear %s because you're wearing %s there already.", cc1, cc2); } /* * canwearobj checks to see whether the player can wear a piece of armor * * inputs: otmp (the piece of armor) * noisy (if TRUE give error messages, otherwise be quiet about it) * output: mask (otmp's armor type) */ int canwearobj(otmp, mask, noisy) struct obj *otmp; long *mask; boolean noisy; { int err = 0; const char *which; which = is_cloak(otmp) ? c_cloak : is_shirt(otmp) ? c_shirt : is_suit(otmp) ? c_suit : 0; if (which && cantweararm(youmonst.data) && /* same exception for cloaks as used in m_dowear() */ (which != c_cloak || youmonst.data->msize != MZ_SMALL) && (racial_exception(&youmonst, otmp) < 1)) { if (noisy) pline_The("%s will not fit on your body.", which); return 0; } else if (otmp->owornmask & W_ARMOR) { if (noisy) already_wearing(c_that_); return 0; } if (welded(uwep) && bimanual(uwep) && (is_suit(otmp) || is_shirt(otmp))) { if (noisy) You("cannot do that while holding your %s.", is_sword(uwep) ? c_sword : c_weapon); return 0; } if (is_helmet(otmp)) { if (uarmh) { if (noisy) already_wearing(an(helm_simple_name(uarmh))); err++; } else if (Upolyd && has_horns(youmonst.data) && !is_flimsy(otmp)) { /* (flimsy exception matches polyself handling) */ if (noisy) pline_The("%s won't fit over your horn%s.", helm_simple_name(otmp), plur(num_horns(youmonst.data))); err++; } else *mask = W_ARMH; } else if (is_shield(otmp)) { if (uarms) { if (noisy) already_wearing(an(c_shield)); err++; } else if (uwep && bimanual(uwep)) { if (noisy) You("cannot wear a shield while wielding a two-handed %s.", is_sword(uwep) ? c_sword : (uwep->otyp == BATTLE_AXE) ? c_axe : c_weapon); err++; } else if (u.twoweap) { if (noisy) You("cannot wear a shield while wielding two weapons."); err++; } else *mask = W_ARMS; } else if (is_boots(otmp)) { if (uarmf) { if (noisy) already_wearing(c_boots); err++; } else if (Upolyd && slithy(youmonst.data)) { if (noisy) You("have no feet..."); /* not body_part(FOOT) */ err++; } else if (Upolyd && youmonst.data->mlet == S_CENTAUR) { /* break_armor() pushes boots off for centaurs, so don't let dowear() put them back on... */ if (noisy) pline("You have too many hooves to wear %s.", c_boots); /* makeplural(body_part(FOOT)) yields "rear hooves" which sounds odd */ err++; } else if (u.utrap && (u.utraptype == TT_BEARTRAP || u.utraptype == TT_INFLOOR || u.utraptype == TT_LAVA || u.utraptype == TT_BURIEDBALL)) { if (u.utraptype == TT_BEARTRAP) { if (noisy) Your("%s is trapped!", body_part(FOOT)); } else if (u.utraptype == TT_INFLOOR || u.utraptype == TT_LAVA) { if (noisy) Your("%s are stuck in the %s!", makeplural(body_part(FOOT)), surface(u.ux, u.uy)); } else { /*TT_BURIEDBALL*/ if (noisy) Your("%s is attached to the buried ball!", body_part(LEG)); } err++; } else *mask = W_ARMF; } else if (is_gloves(otmp)) { if (uarmg) { if (noisy) already_wearing(c_gloves); err++; } else if (welded(uwep)) { if (noisy) You("cannot wear gloves over your %s.", is_sword(uwep) ? c_sword : c_weapon); err++; } else *mask = W_ARMG; } else if (is_shirt(otmp)) { if (uarm || uarmc || uarmu) { if (uarmu) { if (noisy) already_wearing(an(c_shirt)); } else { if (noisy) You_cant("wear that over your %s.", (uarm && !uarmc) ? c_armor : cloak_simple_name(uarmc)); } err++; } else *mask = W_ARMU; } else if (is_cloak(otmp)) { if (uarmc) { if (noisy) already_wearing(an(cloak_simple_name(uarmc))); err++; } else *mask = W_ARMC; } else if (is_suit(otmp)) { if (uarmc) { if (noisy) You("cannot wear armor over a %s.", cloak_simple_name(uarmc)); err++; } else if (uarm) { if (noisy) already_wearing("some armor"); err++; } else *mask = W_ARM; } else { /* getobj can't do this after setting its allow_all flag; that happens if you have armor for slots that are covered up or extra armor for slots that are filled */ if (noisy) silly_thing("wear", otmp); err++; } /* Unnecessary since now only weapons and special items like pick-axes get * welded to your hand, not armor if (welded(otmp)) { if (!err++) { if (noisy) weldmsg(otmp); } } */ return !err; } /* the 'W' command */ int dowear() { struct obj *otmp; int delay; long mask = 0; /* cantweararm checks for suits of armor */ /* verysmall or nohands checks for shields, gloves, etc... */ if ((verysmall(youmonst.data) || nohands(youmonst.data))) { pline("Don't even bother."); return (0); } otmp = getobj(clothes, "wear"); if (!otmp) return (0); if (!canwearobj(otmp, &mask, TRUE)) return (0); if (!retouch_object(&otmp, FALSE)) return 1; /* costs a turn even though it didn't get worn */ if (otmp->otyp == HELM_OF_OPPOSITE_ALIGNMENT && qstart_level.dnum == u.uz.dnum) { /* in quest */ if (u.ualignbase[A_CURRENT] == u.ualignbase[A_ORIGINAL]) You("narrowly avoid losing all chance at your goal."); else /* converted */ You("are suddenly overcome with shame and change your mind."); u.ublessed = 0; /* lose your god's protection */ makeknown(otmp->otyp); context.botl = 1; return 1; } otmp->known = 1; /* since AC is shown on the status line */ /* if the armor is wielded, release it for wearing */ if (otmp->owornmask & (W_WEP | W_SWAPWEP | W_QUIVER)) remove_worn_item(otmp, FALSE); setworn(otmp, mask); delay = -objects[otmp->otyp].oc_delay; if (delay) { nomul(delay); multi_reason = "dressing up"; if (is_boots(otmp)) afternmv = Boots_on; if (is_helmet(otmp)) afternmv = Helmet_on; if (is_gloves(otmp)) afternmv = Gloves_on; if (otmp == uarm) afternmv = Armor_on; nomovemsg = "You finish your dressing maneuver."; } else { if (is_cloak(otmp)) (void) Cloak_on(); if (is_shield(otmp)) (void) Shield_on(); if (is_shirt(otmp)) (void) Shirt_on(); on_msg(otmp); } context.takeoff.mask = context.takeoff.what = 0L; return (1); } int doputon() { struct obj *otmp; long mask = 0L; if (uleft && uright && uamul && ublindf) { Your("%s%s are full, and you're already wearing an amulet and %s.", humanoid(youmonst.data) ? "ring-" : "", makeplural(body_part(FINGER)), ublindf->otyp == LENSES ? "some lenses" : "a blindfold"); return (0); } otmp = getobj(accessories, "put on"); if (!otmp) return (0); if (otmp->owornmask & (W_RING | W_AMUL | W_TOOL)) { already_wearing(c_that_); return (0); } if (welded(otmp)) { weldmsg(otmp); return (0); } #if 0 /* defer til Xxx_on(); various failures below now leave item wielded */ /* accessory might be wielded; release it for wearing */ if (otmp->owornmask & (W_WEP|W_SWAPWEP|W_QUIVER)) remove_worn_item(otmp, FALSE); #endif if (otmp->oclass == RING_CLASS || otmp->otyp == MEAT_RING) { if (nolimbs(youmonst.data)) { You("cannot make the ring stick to your body."); return (0); } if (uleft && uright) { There("are no more %s%s to fill.", humanoid(youmonst.data) ? "ring-" : "", makeplural(body_part(FINGER))); return (0); } if (uleft) mask = RIGHT_RING; else if (uright) mask = LEFT_RING; else do { char qbuf[QBUFSZ]; char answer; Sprintf(qbuf, "Which %s%s, Right or Left?", humanoid(youmonst.data) ? "ring-" : "", body_part(FINGER)); if (!(answer = yn_function(qbuf, "rl", '\0'))) return (0); switch (answer) { case 'l': case 'L': mask = LEFT_RING; break; case 'r': case 'R': mask = RIGHT_RING; break; } } while (!mask); if (uarmg && uarmg->cursed) { uarmg->bknown = TRUE; You("cannot remove your gloves to put on the ring."); return (0); } if (welded(uwep) && bimanual(uwep)) { /* welded will set bknown */ You("cannot free your weapon hands to put on the ring."); return (0); } if (welded(uwep) && mask == RIGHT_RING) { /* welded will set bknown */ You("cannot free your weapon hand to put on the ring."); return (0); } if (!retouch_object(&otmp, FALSE)) return 1; /* costs a turn even though it didn't get worn */ setworn(otmp, mask); Ring_on(otmp); } else if (otmp->oclass == AMULET_CLASS) { if (uamul) { already_wearing("an amulet"); return (0); } if (!retouch_object(&otmp, FALSE)) return 1; setworn(otmp, W_AMUL); Amulet_on(); /* finished now if an amulet of change got used up */ if (!uamul) return 1; } else { /* it's a blindfold, towel, or lenses */ if (ublindf) { if (ublindf->otyp == TOWEL) Your("%s is already covered by a towel.", body_part(FACE)); else if (ublindf->otyp == BLINDFOLD) { if (otmp->otyp == LENSES) already_wearing2("lenses", "a blindfold"); else already_wearing("a blindfold"); } else if (ublindf->otyp == LENSES) { if (otmp->otyp == BLINDFOLD) already_wearing2("a blindfold", "some lenses"); else already_wearing("some lenses"); } else already_wearing(something); /* ??? */ return (0); } if (otmp->otyp != BLINDFOLD && otmp->otyp != TOWEL && otmp->otyp != LENSES) { You_cant("wear that!"); return (0); } if (!retouch_object(&otmp, FALSE)) return 1; Blindf_on(otmp); return (1); } if (is_worn(otmp)) prinv((char *) 0, otmp, 0L); return (1); } void find_ac() { int uac = mons[u.umonnum].ac; if (uarm) uac -= ARM_BONUS(uarm); if (uarmc) uac -= ARM_BONUS(uarmc); if (uarmh) uac -= ARM_BONUS(uarmh); if (uarmf) uac -= ARM_BONUS(uarmf); if (uarms) uac -= ARM_BONUS(uarms); if (uarmg) uac -= ARM_BONUS(uarmg); if (uarmu) uac -= ARM_BONUS(uarmu); if (uleft && uleft->otyp == RIN_PROTECTION) uac -= uleft->spe; if (uright && uright->otyp == RIN_PROTECTION) uac -= uright->spe; if (HProtection & INTRINSIC) uac -= u.ublessed; uac -= u.uspellprot; if (uac < -128) uac = -128; /* u.uac is an schar */ if (uac != u.uac) { u.uac = uac; context.botl = 1; } } void glibr() { register struct obj *otmp; int xfl = 0; boolean leftfall, rightfall, wastwoweap = FALSE; const char *otherwep = 0, *thiswep, *which, *hand; leftfall = (uleft && !uleft->cursed && (!uwep || !welded(uwep) || !bimanual(uwep))); rightfall = (uright && !uright->cursed && (!welded(uwep))); if (!uarmg && (leftfall || rightfall) && !nolimbs(youmonst.data)) { /* changed so cursed rings don't fall off, GAN 10/30/86 */ Your("%s off your %s.", (leftfall && rightfall) ? "rings slip" : "ring slips", (leftfall && rightfall) ? makeplural(body_part(FINGER)) : body_part(FINGER)); xfl++; if (leftfall) { otmp = uleft; Ring_off(uleft); dropx(otmp); } if (rightfall) { otmp = uright; Ring_off(uright); dropx(otmp); } } otmp = uswapwep; if (u.twoweap && otmp) { /* secondary weapon doesn't need nearly as much handling as primary; when in two-weapon mode, we know it's one-handed with something else in the other hand and also that it's a weapon or weptool rather than something unusual, plus we don't need to compare its type with the primary */ otherwep = is_sword(otmp) ? c_sword : weapon_descr(otmp); if (otmp->quan > 1L) otherwep = makeplural(otherwep); hand = body_part(HAND); which = "left "; Your("%s %s%s from your %s%s.", otherwep, xfl ? "also " : "", otense(otmp, "slip"), which, hand); xfl++; wastwoweap = TRUE; setuswapwep((struct obj *) 0); /* clears u.twoweap */ if (canletgo(otmp, "")) dropx(otmp); } otmp = uwep; if (otmp && !welded(otmp)) { long savequan = otmp->quan; /* nice wording if both weapons are the same type */ thiswep = is_sword(otmp) ? c_sword : weapon_descr(otmp); if (otherwep && strcmp(thiswep, makesingular(otherwep))) otherwep = 0; if (otmp->quan > 1L) { /* most class names for unconventional wielded items are ok, but if wielding multiple apples or rations we don't want "your foods slip", so force non-corpse food to be singular; skipping makeplural() isn't enough--we need to fool otense() too */ if (!strcmp(thiswep, "food")) otmp->quan = 1L; else thiswep = makeplural(thiswep); } hand = body_part(HAND); which = ""; if (bimanual(otmp)) hand = makeplural(hand); else if (wastwoweap) which = "right "; /* preceding msg was about left */ pline("%s %s%s %s%s from your %s%s.", !strncmp(thiswep, "corpse", 6) ? "The" : "Your", otherwep ? "other " : "", thiswep, xfl ? "also " : "", otense(otmp, "slip"), which, hand); /* xfl++; */ otmp->quan = savequan; setuwep((struct obj *) 0); if (canletgo(otmp, "")) dropx(otmp); } } struct obj * some_armor(victim) struct monst *victim; { register struct obj *otmph, *otmp; otmph = (victim == &youmonst) ? uarmc : which_armor(victim, W_ARMC); if (!otmph) otmph = (victim == &youmonst) ? uarm : which_armor(victim, W_ARM); if (!otmph) otmph = (victim == &youmonst) ? uarmu : which_armor(victim, W_ARMU); otmp = (victim == &youmonst) ? uarmh : which_armor(victim, W_ARMH); if (otmp && (!otmph || !rn2(4))) otmph = otmp; otmp = (victim == &youmonst) ? uarmg : which_armor(victim, W_ARMG); if (otmp && (!otmph || !rn2(4))) otmph = otmp; otmp = (victim == &youmonst) ? uarmf : which_armor(victim, W_ARMF); if (otmp && (!otmph || !rn2(4))) otmph = otmp; otmp = (victim == &youmonst) ? uarms : which_armor(victim, W_ARMS); if (otmp && (!otmph || !rn2(4))) otmph = otmp; return (otmph); } /* used for praying to check and fix levitation trouble */ struct obj * stuck_ring(ring, otyp) struct obj *ring; int otyp; { if (ring != uleft && ring != uright) { impossible("stuck_ring: neither left nor right?"); return (struct obj *) 0; } if (ring && ring->otyp == otyp) { /* reasons ring can't be removed match those checked by select_off(); limbless case has extra checks because ordinarily it's temporary */ if (nolimbs(youmonst.data) && uamul && uamul->otyp == AMULET_OF_UNCHANGING && uamul->cursed) return uamul; if (welded(uwep) && (ring == uright || bimanual(uwep))) return uwep; if (uarmg && uarmg->cursed) return uarmg; if (ring->cursed) return ring; } /* either no ring or not right type or nothing prevents its removal */ return (struct obj *) 0; } /* also for praying; find worn item that confers "Unchanging" attribute */ struct obj * unchanger() { if (uamul && uamul->otyp == AMULET_OF_UNCHANGING) return uamul; return 0; } STATIC_PTR int select_off(otmp) register struct obj *otmp; { struct obj *why; char buf[BUFSZ]; if (!otmp) return 0; *buf = '\0'; /* lint suppresion */ /* special ring checks */ 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; } } /* special glove checks */ 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; } } /* special boot checks */ 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; } } /* special suit and shirt checks */ if (otmp == uarm || otmp == uarmu) { why = 0; /* the item which prevents disrobing */ if (uarmc && uarmc->cursed) { Sprintf(buf, "remove your %s", cloak_simple_name(uarmc)); why = uarmc; } else if (otmp == uarmu && uarm && uarm->cursed) { Sprintf(buf, "remove your %s", c_suit); why = uarm; } 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; } } /* basic curse check */ if (otmp == uquiver || (otmp == uswapwep && !u.twoweap)) { ; /* some items can be removed even when cursed */ } else { /* otherwise, this is fundamental */ if (cursed(otmp)) return 0; } if (otmp == uarm) context.takeoff.mask |= WORN_ARMOR; else if (otmp == uarmc) context.takeoff.mask |= WORN_CLOAK; else if (otmp == uarmf) context.takeoff.mask |= WORN_BOOTS; else if (otmp == uarmg) context.takeoff.mask |= WORN_GLOVES; else if (otmp == uarmh) context.takeoff.mask |= WORN_HELMET; else if (otmp == uarms) context.takeoff.mask |= WORN_SHIELD; else if (otmp == uarmu) context.takeoff.mask |= WORN_SHIRT; else if (otmp == uleft) context.takeoff.mask |= LEFT_RING; else if (otmp == uright) context.takeoff.mask |= RIGHT_RING; else if (otmp == uamul) context.takeoff.mask |= WORN_AMUL; else if (otmp == ublindf) context.takeoff.mask |= WORN_BLINDF; else if (otmp == uwep) context.takeoff.mask |= W_WEP; else if (otmp == uswapwep) context.takeoff.mask |= W_SWAPWEP; else if (otmp == uquiver) context.takeoff.mask |= W_QUIVER; else impossible("select_off: %s???", doname(otmp)); return (0); } STATIC_OVL struct obj * do_takeoff() { struct obj *otmp = (struct obj *) 0; struct takeoff_info *doff = &context.takeoff; if (doff->what == W_WEP) { if (!cursed(uwep)) { setuwep((struct obj *) 0); You("are empty %s.", body_part(HANDED)); u.twoweap = FALSE; } } else if (doff->what == W_SWAPWEP) { setuswapwep((struct obj *) 0); You("no longer have a second weapon readied."); u.twoweap = FALSE; } else if (doff->what == W_QUIVER) { setuqwep((struct obj *) 0); You("no longer have ammunition readied."); } else if (doff->what == WORN_ARMOR) { otmp = uarm; if (!cursed(otmp)) (void) Armor_off(); } else if (doff->what == WORN_CLOAK) { otmp = uarmc; if (!cursed(otmp)) (void) Cloak_off(); } else if (doff->what == WORN_BOOTS) { otmp = uarmf; if (!cursed(otmp)) (void) Boots_off(); } else if (doff->what == WORN_GLOVES) { otmp = uarmg; if (!cursed(otmp)) (void) Gloves_off(); } else if (doff->what == WORN_HELMET) { otmp = uarmh; if (!cursed(otmp)) (void) Helmet_off(); } else if (doff->what == WORN_SHIELD) { otmp = uarms; if (!cursed(otmp)) (void) Shield_off(); } else if (doff->what == WORN_SHIRT) { otmp = uarmu; if (!cursed(otmp)) (void) Shirt_off(); } else if (doff->what == WORN_AMUL) { otmp = uamul; if (!cursed(otmp)) Amulet_off(); } else if (doff->what == LEFT_RING) { otmp = uleft; if (!cursed(otmp)) Ring_off(uleft); } else if (doff->what == RIGHT_RING) { otmp = uright; if (!cursed(otmp)) Ring_off(uright); } else if (doff->what == WORN_BLINDF) { if (!cursed(ublindf)) Blindf_off(ublindf); } else { impossible("do_takeoff: taking off %lx", doff->what); } return (otmp); } /* occupation callback for 'A' */ STATIC_PTR int take_off(VOID_ARGS) { register int i; register struct obj *otmp; struct takeoff_info *doff = &context.takeoff; if (doff->what) { if (doff->delay > 0) { doff->delay--; return (1); /* still busy */ } else { if ((otmp = do_takeoff())) off_msg(otmp); } doff->mask &= ~doff->what; doff->what = 0L; } for (i = 0; takeoff_order[i]; i++) if (doff->mask & takeoff_order[i]) { doff->what = takeoff_order[i]; break; } otmp = (struct obj *) 0; doff->delay = 0; if (doff->what == 0L) { You("finish %s.", doff->disrobing); return 0; } else if (doff->what == W_WEP) { doff->delay = 1; } else if (doff->what == W_SWAPWEP) { doff->delay = 1; } else if (doff->what == W_QUIVER) { doff->delay = 1; } else if (doff->what == WORN_ARMOR) { otmp = uarm; /* 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 * known cloaks, add 1 so that it actually matters... */ if (uarmc) doff->delay += 2 * objects[uarmc->otyp].oc_delay + 1; } else if (doff->what == WORN_CLOAK) { otmp = uarmc; } else if (doff->what == WORN_BOOTS) { otmp = uarmf; } else if (doff->what == WORN_GLOVES) { otmp = uarmg; } else if (doff->what == WORN_HELMET) { otmp = uarmh; } else if (doff->what == WORN_SHIELD) { otmp = uarms; } else if (doff->what == WORN_SHIRT) { otmp = uarmu; /* add the time to take off and put back on armor and/or cloak */ if (uarm) doff->delay += 2 * objects[uarm->otyp].oc_delay; if (uarmc) doff->delay += 2 * objects[uarmc->otyp].oc_delay + 1; } else if (doff->what == WORN_AMUL) { doff->delay = 1; } else if (doff->what == LEFT_RING) { doff->delay = 1; } else if (doff->what == RIGHT_RING) { doff->delay = 1; } else if (doff->what == WORN_BLINDF) { doff->delay = 2; } else { impossible("take_off: taking off %lx", doff->what); return 0; /* force done */ } if (otmp) doff->delay += objects[otmp->otyp].oc_delay; /* Since setting the occupation now starts the counter next move, that * would always produce a delay 1 too big per item unless we subtract * 1 here to account for it. */ if (doff->delay > 0) doff->delay--; set_occupation(take_off, doff->disrobing, 0); return (1); /* get busy */ } /* clear saved context to avoid inappropriate resumption of interrupted 'A' */ void reset_remarm() { context.takeoff.what = context.takeoff.mask = 0L; context.takeoff.disrobing[0] = '\0'; } /* the 'A' command -- remove multiple worn items */ int doddoremarm() { int result = 0; if (context.takeoff.what || context.takeoff.mask) { You("continue %s.", context.takeoff.disrobing); set_occupation(take_off, context.takeoff.disrobing, 0); return 0; } else if (!uwep && !uswapwep && !uquiver && !uamul && !ublindf && !uleft && !uright && !wearing_armor()) { You("are not wearing anything."); return 0; } add_valid_menu_class(0); /* reset */ if (flags.menu_style != MENU_TRADITIONAL || (result = ggetobj("take off", select_off, 0, FALSE, (unsigned *) 0)) < -1) result = menu_remarm(result); if (context.takeoff.mask) { /* default activity for armor and/or accessories, possibly combined with weapons */ (void) strncpy(context.takeoff.disrobing, "disrobing", CONTEXTVERBSZ); /* specific activity when handling weapons only */ if (!(context.takeoff.mask & ~(W_WEP | W_SWAPWEP | W_QUIVER))) (void) strncpy(context.takeoff.disrobing, "disarming", CONTEXTVERBSZ); (void) take_off(); } /* The time to perform the command is already completely accounted for * in take_off(); if we return 1, that would add an extra turn to each * disrobe. */ return 0; } STATIC_OVL int menu_remarm(retry) int retry; { int n, i = 0; menu_item *pick_list; boolean all_worn_categories = TRUE; if (retry) { all_worn_categories = (retry == -2); } else if (flags.menu_style == MENU_FULL) { all_worn_categories = FALSE; n = query_category("What type of things do you want to take off?", invent, WORN_TYPES | ALL_TYPES, &pick_list, PICK_ANY); if (!n) return 0; for (i = 0; i < n; i++) { if (pick_list[i].item.a_int == ALL_TYPES_SELECTED) all_worn_categories = TRUE; else add_valid_menu_class(pick_list[i].item.a_int); } free((genericptr_t) pick_list); } else if (flags.menu_style == MENU_COMBINATION) { all_worn_categories = FALSE; if (ggetobj("take off", select_off, 0, TRUE, (unsigned *) 0) == -2) all_worn_categories = TRUE; } n = query_objlist("What do you want to take off?", invent, SIGNAL_NOMENU | USE_INVLET | INVORDER_SORT, &pick_list, PICK_ANY, all_worn_categories ? is_worn : is_worn_by_type); if (n > 0) { for (i = 0; i < n; i++) (void) select_off(pick_list[i].item.a_obj); free((genericptr_t) pick_list); } else if (n < 0 && flags.menu_style != MENU_COMBINATION) { There("is nothing else you can remove or unwield."); } return 0; } /* hit by destroy armor scroll/black dragon breath/monster spell */ int destroy_arm(atmp) register struct obj *atmp; { register struct obj *otmp; #define DESTROY_ARM(o) \ ((otmp = (o)) != 0 && (!atmp || atmp == otmp) \ && (!obj_resists(otmp, 0, 90)) \ ? (otmp->in_use = TRUE) \ : FALSE) if (DESTROY_ARM(uarmc)) { if (donning(otmp)) cancel_don(); Your("%s crumbles and turns to dust!", cloak_simple_name(uarmc)); (void) Cloak_off(); useup(otmp); } else if (DESTROY_ARM(uarm)) { if (donning(otmp)) cancel_don(); Your("armor turns to dust and falls to the %s!", surface(u.ux, u.uy)); (void) Armor_gone(); useup(otmp); } else if (DESTROY_ARM(uarmu)) { if (donning(otmp)) cancel_don(); Your("shirt crumbles into tiny threads and falls apart!"); (void) Shirt_off(); useup(otmp); } else if (DESTROY_ARM(uarmh)) { if (donning(otmp)) cancel_don(); Your("%s turns to dust and is blown away!", helm_simple_name(uarmh)); (void) Helmet_off(); useup(otmp); } else if (DESTROY_ARM(uarmg)) { if (donning(otmp)) cancel_don(); Your("gloves vanish!"); (void) Gloves_off(); useup(otmp); selftouch("You"); } else if (DESTROY_ARM(uarmf)) { if (donning(otmp)) cancel_don(); Your("boots disintegrate!"); (void) Boots_off(); useup(otmp); } else if (DESTROY_ARM(uarms)) { if (donning(otmp)) cancel_don(); Your("shield crumbles away!"); (void) Shield_off(); useup(otmp); } else { return 0; /* could not destroy anything */ } #undef DESTROY_ARM stop_occupation(); return (1); } void adj_abon(otmp, delta) register struct obj *otmp; register schar delta; { if (uarmg && uarmg == otmp && otmp->otyp == GAUNTLETS_OF_DEXTERITY) { if (delta) { makeknown(uarmg->otyp); ABON(A_DEX) += (delta); } context.botl = 1; } if (uarmh && uarmh == otmp && otmp->otyp == HELM_OF_BRILLIANCE) { if (delta) { makeknown(uarmh->otyp); ABON(A_INT) += (delta); ABON(A_WIS) += (delta); } context.botl = 1; } } /* 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_known_cursed) struct obj *obj; const char *verb; /* "dip" or "grease", or null to avoid messages */ boolean only_if_known_cursed; /* ignore covering unless known to be cursed */ { static NEARDATA const char need_to_take_off_outer_armor[] = "need to take off %s to %s %s."; char buf[BUFSZ]; boolean anycovering = !only_if_known_cursed; /* more comprehensible... */ #define BLOCKSACCESS(x) (anycovering || ((x)->cursed && (x)->bknown)) if (!obj || !obj->owornmask) return FALSE; /* not inaccessible */ /* check for suit covered by cloak */ if (obj == uarm && uarmc && BLOCKSACCESS(uarmc)) { if (verb) { Strcpy(buf, yname(uarmc)); You(need_to_take_off_outer_armor, buf, verb, yname(obj)); } return TRUE; } /* check for shirt covered by suit and/or cloak */ if (obj == uarmu && ((uarm && BLOCKSACCESS(uarm)) || (uarmc && BLOCKSACCESS(uarmc)))) { 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; } /* check for ring covered by gloves */ if ((obj == uleft || obj == uright) && uarmg && BLOCKSACCESS(uarmg)) { 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*/