From 04d501f750523ee9e8c96613059401580391ed65 Mon Sep 17 00:00:00 2001 From: jwalz Date: Sat, 5 Jan 2002 21:05:49 +0000 Subject: [PATCH] *** empty log message *** --- src/do_wear.c | 2004 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 2004 insertions(+) create mode 100644 src/do_wear.c diff --git a/src/do_wear.c b/src/do_wear.c new file mode 100644 index 000000000..182de2ad0 --- /dev/null +++ b/src/do_wear.c @@ -0,0 +1,2004 @@ +/* SCCS Id: @(#)do_wear.c 3.3 2001/12/06 */ +/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ +/* NetHack may be freely redistributed. See license for details. */ + +#include "hack.h" + +#ifndef OVLB + +STATIC_DCL long takeoff_mask, taking_off; + +#else /* OVLB */ + +STATIC_OVL NEARDATA long takeoff_mask = 0L, taking_off = 0L; + +static NEARDATA int todelay; +static boolean cancelled_don = FALSE; + +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", +#ifdef TOURIST + *c_shirt = "shirt", +#endif + *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, +#ifdef TOURIST + WORN_SHIRT, +#endif + WORN_BOOTS, W_SWAPWEP, W_QUIVER, 0L }; + +STATIC_DCL void FDECL(on_msg, (struct obj *)); +STATIC_PTR int NDECL(Armor_on); +STATIC_PTR int NDECL(Boots_on); +STATIC_DCL int NDECL(Cloak_on); +STATIC_PTR int NDECL(Helmet_on); +STATIC_PTR int NDECL(Gloves_on); +STATIC_DCL void NDECL(Amulet_on); +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) +register struct obj *otmp; +{ + if(flags.verbose) + You("were wearing %s.", doname(otmp)); +} + +/* for items that involve no delay */ +STATIC_OVL void +on_msg(otmp) +register struct obj *otmp; +{ + if (flags.verbose) { + char how[BUFSZ]; + + 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(xname(otmp)) : an(xname(otmp)), + how); + } +} + +/* + * The Type_on() functions should be called *after* setworn(). + * The Type_off() functions call setworn() themselves. + */ + +STATIC_PTR +int +Boots_on() +{ + 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); + 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: + if (!oldprop && !HStealth && !BStealth) { + makeknown(uarmf->otyp); + You("walk very quietly."); + } + break; + case FUMBLE_BOOTS: + if (!oldprop && !(HFumbling & ~TIMEOUT)) + incr_itimeout(&HFumbling, rnd(20)); + break; + case LEVITATION_BOOTS: + if (!oldprop && !HLevitation) { + makeknown(uarmf->otyp); + float_up(); + spoteffects(FALSE); + } + break; + default: impossible(unknown_type, c_boots, uarmf->otyp); + } + return 0; +} + +int +Boots_off() +{ + int otyp = uarmf->otyp; + long oldprop = u.uprops[objects[otyp].oc_oprop].extrinsic & ~WORN_BOOTS; + + + /* 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 && !cancelled_don) { + makeknown(otyp); + You_feel("yourself slow down%s.", + Fast ? " a bit" : ""); + } + break; + case WATER_WALKING_BOOTS: + if (is_pool(u.ux,u.uy) && !Levitation && !Flying && + !is_clinger(youmonst.data) && !cancelled_don) { + makeknown(otyp); + /* make boots known in case you survive the drowning */ + spoteffects(TRUE); + } + break; + case ELVEN_BOOTS: + if (!oldprop && !HStealth && !BStealth && !cancelled_don) { + makeknown(otyp); + You("sure are noisy."); + } + break; + case FUMBLE_BOOTS: + if (!oldprop && !(HFumbling & ~TIMEOUT)) + HFumbling = EFumbling = 0; + break; + case LEVITATION_BOOTS: + if (!oldprop && !HLevitation && !cancelled_don) { + (void) float_down(0L, 0L); + makeknown(otyp); + } + break; + case LOW_BOOTS: + case IRON_SHOES: + case HIGH_BOOTS: + case JUMPING_BOOTS: + case KICKING_BOOTS: + break; + default: impossible(unknown_type, c_boots, otyp); + } + cancelled_don = FALSE; + return 0; +} + +STATIC_OVL int +Cloak_on() +{ + long oldprop = + u.uprops[objects[uarmc->otyp].oc_oprop].extrinsic & ~WORN_CLOAK; + + switch(uarmc->otyp) { + case ELVEN_CLOAK: + case CLOAK_OF_PROTECTION: + case CLOAK_OF_DISPLACEMENT: + makeknown(uarmc->otyp); + break; + case ORCISH_CLOAK: + case DWARVISH_CLOAK: + case CLOAK_OF_MAGIC_RESISTANCE: + case ROBE: + break; + case MUMMY_WRAPPING: + /* Note: it's already being worn, so we have to cheat here. */ + if ((HInvis || EInvis || pm_invisible(youmonst.data)) && !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 fits very tightly.",The(xname(uarmc))); + 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() +{ + int otyp = uarmc->otyp; + long oldprop = u.uprops[objects[otyp].oc_oprop].extrinsic & ~WORN_CLOAK; + + + /* For mummy wrapping, taking it off first resets `Invisible'. */ + setworn((struct obj *)0, W_ARMC); + switch (otyp) { + case ELVEN_CLOAK: + case ORCISH_CLOAK: + case DWARVISH_CLOAK: + case CLOAK_OF_PROTECTION: + case CLOAK_OF_MAGIC_RESISTANCE: + case CLOAK_OF_DISPLACEMENT: + case OILSKIN_CLOAK: + case ROBE: + 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() +{ + 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); + flags.botl = 1; + makeknown(uarmh->otyp); + break; + case HELM_OF_OPPOSITE_ALIGNMENT: + if (u.ualign.type == A_NEUTRAL) + u.ualign.type = rn2(2) ? A_CHAOTIC : A_LAWFUL; + else u.ualign.type = -(u.ualign.type); + u.ublessed = 0; /* lose your god's protection */ + /* makeknown(uarmh->otyp); -- moved below, after xname() */ + /*FALLTHRU*/ + case DUNCE_CAP: + if (!uarmh->cursed) { + pline("%s %s%s for a moment.", The(xname(uarmh)), + Blind ? "vibrates" : "glows ", + Blind ? (const char *)"" : hcolor(Black)); + curse(uarmh); + } + flags.botl = 1; /* reveal new alignment or INT & WIS */ + if (Hallucination) { + pline("My brain hurts!"); /* Monty Python's Flying Circus */ + } else if (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 { + Your("mind oscillates briefly."); + makeknown(HELM_OF_OPPOSITE_ALIGNMENT); + } + break; + default: impossible(unknown_type, c_helmet, uarmh->otyp); + } + return 0; +} + +int +Helmet_off() +{ + 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: + flags.botl = 1; + break; + case CORNUTHAUM: + if (!cancelled_don) { + ABON(A_CHA) += (Role_if(PM_WIZARD) ? -1 : 1); + flags.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 (!cancelled_don) adj_abon(uarmh, -uarmh->spe); + break; + case HELM_OF_OPPOSITE_ALIGNMENT: + u.ualign.type = u.ualignbase[A_CURRENT]; + u.ublessed = 0; /* lose the other god's protection */ + flags.botl = 1; + break; + default: impossible(unknown_type, c_helmet, uarmh->otyp); + } + setworn((struct obj *)0, W_ARMH); + cancelled_don = FALSE; + return 0; +} + +STATIC_PTR +int +Gloves_on() +{ + 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); + flags.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; +} + +int +Gloves_off() +{ + 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)) + HFumbling = EFumbling = 0; + break; + case GAUNTLETS_OF_POWER: + makeknown(uarmg->otyp); + flags.botl = 1; /* taken care of in attrib.c */ + break; + case GAUNTLETS_OF_DEXTERITY: + if (!cancelled_don) adj_abon(uarmg, -uarmg->spe); + break; + default: impossible(unknown_type, c_gloves, uarmg->otyp); + } + setworn((struct obj *)0, W_ARMG); + cancelled_don = FALSE; + + /* Prevent wielding cockatrice when not wearing gloves */ + if (uwep && uwep->otyp == CORPSE && + touch_petrifies(&mons[uwep->corpsenm])) { + char kbuf[BUFSZ]; + + You("wield the %s corpse in your bare %s.", + mons[uwep->corpsenm].mname, makeplural(body_part(HAND))); + Sprintf(kbuf, "%s corpse", an(mons[uwep->corpsenm].mname)); + instapetrify(kbuf); + uwepgone(); /* life-saved still doesn't allow touching cockatrice */ + } + + /* KMH -- ...or your secondary weapon when you're wielding it */ + if (u.twoweap && uswapwep && uswapwep->otyp == CORPSE && + touch_petrifies(&mons[uswapwep->corpsenm])) { + char kbuf[BUFSZ]; + + You("wield the %s corpse in your bare %s.", + mons[uswapwep->corpsenm].mname, body_part(HAND)); + + Sprintf(kbuf, "%s corpse", an(mons[uswapwep->corpsenm].mname)); + instapetrify(kbuf); + uswapwepgone(); /* lifesaved still doesn't allow touching cockatrice */ + } + + return 0; +} + +/* +STATIC_OVL int +Shield_on() +{ + 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() +{ +/* + 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; +} + +/* 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() +{ + return 0; +} + +int +Armor_off() +{ + setworn((struct obj *)0, W_ARM); + 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() +{ + setnotworn(uarm); + cancelled_don = FALSE; + return 0; +} + +STATIC_OVL void +Amulet_on() +{ + 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) { + Slimed = 0; + flags.botl = 1; + } + 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"); + flags.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: + makeknown(AMULET_OF_STRANGULATION); + pline("It constricts your throat!"); + Strangled = 6; + break; + case AMULET_OF_RESTFUL_SLEEP: + HSleeping = rnd(100); + break; + case AMULET_OF_YENDOR: + break; + } +} + +void +Amulet_off() +{ + 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) { + You("can breathe more easily!"); + Strangled = 0; + } + break; + case AMULET_OF_RESTFUL_SLEEP: + setworn((struct obj *)0, W_AMUL); + if (!ESleeping) + HSleeping = 0; + return; + case AMULET_OF_YENDOR: + break; + } + setworn((struct obj *)0, W_AMUL); + return; +} + +void +Ring_on(obj) +register struct obj *obj; +{ + long oldprop = u.uprops[objects[obj->otyp].oc_oprop].extrinsic; + int old_attrib; + + + if (obj == uwep) setuwep((struct obj *) 0); + if (obj == uswapwep) setuswapwep((struct obj *) 0); + 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_STEALTH: + 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_WARNING: + see_monsters(); + break; + case RIN_SEE_INVISIBLE: + /* can now see invisible monsters */ + set_mimic_blocking(); /* do special mimic handling */ + see_monsters(); +#ifdef INVISIBLE_OBJECTS + see_objects(); +#endif + + if (Invis && !oldprop && !HSee_invisible && + !perceives(youmonst.data) && !Blind) { + newsym(u.ux,u.uy); + pline("Suddenly you are transparent, but there!"); + makeknown(RIN_SEE_INVISIBLE); + } + break; + case RIN_INVISIBILITY: + if (!oldprop && !HInvis && !BInvis && !Blind) { + makeknown(RIN_INVISIBILITY); + newsym(u.ux,u.uy); + self_invis_message(); + } + break; + case RIN_ADORNMENT: + old_attrib = ACURR(A_CHA); + ABON(A_CHA) += obj->spe; + flags.botl = 1; + if (ACURR(A_CHA) != old_attrib || + (objects[RIN_ADORNMENT].oc_name_known && + old_attrib != 25 && old_attrib != 3)) { + makeknown(RIN_ADORNMENT); + obj->known = TRUE; + } + break; + case RIN_LEVITATION: + if(!oldprop && !HLevitation) { + float_up(); + makeknown(RIN_LEVITATION); + obj->known = TRUE; + spoteffects(FALSE); /* for sinks */ + } + break; + case RIN_GAIN_STRENGTH: + old_attrib = ACURR(A_STR); + ABON(A_STR) += obj->spe; + flags.botl = 1; + if (ACURR(A_STR) != old_attrib || + (objects[RIN_GAIN_STRENGTH].oc_name_known && + old_attrib != STR19(25) && old_attrib != 3)) { + makeknown(RIN_GAIN_STRENGTH); + obj->known = TRUE; + } + break; + case RIN_GAIN_CONSTITUTION: + old_attrib = ACURR(A_CON); + ABON(A_CON) += obj->spe; + flags.botl = 1; + if (ACURR(A_CON) != old_attrib || + objects[RIN_GAIN_CONSTITUTION].oc_name_known) { + makeknown(RIN_GAIN_CONSTITUTION); + obj->known = TRUE; + } + 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: + flags.botl = 1; + if (obj->spe || objects[RIN_PROTECTION].oc_name_known) { + makeknown(RIN_PROTECTION); + obj->known = TRUE; + update_inventory(); + } + break; + } +} + +STATIC_OVL void +Ring_off_or_gone(obj,gone) +register struct obj *obj; +boolean gone; +{ + register long mask = obj->owornmask & W_RING; + int old_attrib; + + 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_STEALTH: + 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_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(); +#ifdef INVISIBLE_OBJECTS + see_objects(); +#endif + } + + if (Invisible && !Blind) { + newsym(u.ux,u.uy); + pline("Suddenly you cannot see yourself."); + makeknown(RIN_SEE_INVISIBLE); + } + break; + case RIN_INVISIBILITY: + if (!Invis && !BInvis && !Blind) { + newsym(u.ux,u.uy); + Your("body seems to unfade%s.", + See_invisible ? " completely" : ".."); + makeknown(RIN_INVISIBILITY); + } + break; + case RIN_ADORNMENT: + old_attrib = ACURR(A_CHA); + ABON(A_CHA) -= obj->spe; + if (ACURR(A_CHA) != old_attrib) makeknown(RIN_ADORNMENT); + flags.botl = 1; + break; + case RIN_LEVITATION: + (void) float_down(0L, 0L); + if (!Levitation) makeknown(RIN_LEVITATION); + break; + case RIN_GAIN_STRENGTH: + old_attrib = ACURR(A_STR); + ABON(A_STR) -= obj->spe; + if (ACURR(A_STR) != old_attrib) makeknown(RIN_GAIN_STRENGTH); + flags.botl = 1; + break; + case RIN_GAIN_CONSTITUTION: + old_attrib = ACURR(A_CON); + ABON(A_CON) -= obj->spe; + flags.botl = 1; + if (ACURR(A_CON) != old_attrib) makeknown(RIN_GAIN_CONSTITUTION); + 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: + /* 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; + + if (otmp == uwep) + setuwep((struct obj *) 0); + if (otmp == uswapwep) + setuswapwep((struct obj *) 0); + if (otmp == uquiver) + setuqwep((struct obj *) 0); + 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 */ + flags.botl = 1; + } +} + +void +Blindf_off(otmp) +register struct obj *otmp; +{ + boolean was_blind = Blind, changed = FALSE; + + 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) { + 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 */ + flags.botl = 1; + } +} + +/* called in main to set intrinsics of worn start-up items */ +void +set_wear() +{ + if (uarm) (void) Armor_on(); + if (uarmc) (void) Cloak_on(); + if (uarmf) (void) Boots_on(); + if (uarmg) (void) Gloves_on(); + if (uarmh) (void) Helmet_on(); +/* if (uarms) (void) Shield_on(); */ +} + +boolean +donning(otmp) +register struct obj *otmp; +{ + return((boolean)((otmp == uarmf && (afternmv == Boots_on || afternmv == Boots_off)) + || (otmp == uarmh && (afternmv == Helmet_on || afternmv == Helmet_off)) + || (otmp == uarmg && (afternmv == Gloves_on || afternmv == Gloves_off)) + || (otmp == uarm && (afternmv == Armor_on || afternmv == Armor_off)))); +} + +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) + */ + cancelled_don = (afternmv == Boots_on || afternmv == Helmet_on || + afternmv == Gloves_on || afternmv == Armor_on); + afternmv = 0; + nomovemsg = (char *)0; + multi = 0; +} + +static NEARDATA const char clothes[] = {ARMOR_CLASS, 0}; +static NEARDATA const char accessories[] = {RING_CLASS, AMULET_CLASS, TOOL_CLASS, FOOD_CLASS, 0}; + +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; +#ifdef TOURIST + } else if (uarmu) { + armorpieces++; + otmp = uarmu; +#endif + } + 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."); + return 0; + } + if (armorpieces > 1) + otmp = getobj(clothes, "take off"); + if (otmp == 0) 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) +#ifdef TOURIST + || ((otmp == uarmu) && (uarmc || uarm)) +#endif + ) { + 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 */ + (void) armoroff(otmp); + return(1); +} + +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."); + return(0); + } + if (Accessories != 1) otmp = getobj(accessories, "take off"); + if(!otmp) return(0); + if(!(otmp->owornmask & (W_RING | W_AMUL | W_TOOL))) { + 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); + } + /* 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->oclass == AMULET_CLASS) { + Amulet_off(); + off_msg(otmp); + } else Blindf_off(otmp); /* does its own off_msg */ + 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) { + You("can't. %s to be cursed.", + (is_boots(otmp) || is_gloves(otmp) || otmp->quan > 1L) + ? "They seem" : "It seems"); + 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); + if (is_helmet(otmp)) { + nomovemsg = "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): this comment is obsolete since + * fire resistance is not needed for Gehennom. + */ + 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); + } + takeoff_mask = taking_off = 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 : +#ifdef TOURIST + is_shirt(otmp) ? c_shirt : +#endif + 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)) { + 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) && + (otmp == uarm +#ifdef TOURIST + || otmp == uarmu +#endif + )) { + 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(c_helmet)); + 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 (u.utrap && (u.utraptype == TT_BEARTRAP || + u.utraptype == TT_INFLOOR)) { + if (u.utraptype == TT_BEARTRAP) { + if (noisy) Your("%s is trapped!", body_part(FOOT)); + } else { + if (noisy) Your("%s are stuck in the %s!", + makeplural(body_part(FOOT)), + surface(u.ux, u.uy)); + } + 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; +#ifdef TOURIST + } 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; +#endif + } 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) pline(silly_thing_to, "wear"); + 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 (otmp->oartifact && !touch_artifact(otmp, &youmonst)) + 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 */ + You("narrowly avoid losing all chance at your goal."); + u.ublessed = 0; /* lose your god's protection */ + makeknown(otmp->otyp); + flags.botl = 1; + return 1; + } + + otmp->known = TRUE; + if(otmp == uwep) + setuwep((struct obj *)0); + if (otmp == uswapwep) + setuswapwep((struct obj *) 0); + if (otmp == uquiver) + setuqwep((struct obj *) 0); + setworn(otmp, mask); + delay = -objects[otmp->otyp].oc_delay; + if(delay){ + nomul(delay); + 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(); */ + on_msg(otmp); + } + takeoff_mask = taking_off = 0L; + return(1); +} + +int +doputon() +{ + register 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, "wear"); + 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(otmp == uwep) + setuwep((struct obj *)0); + 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); + } + setworn(otmp, mask); + Ring_on(otmp); + } else if (otmp->oclass == AMULET_CLASS) { + if(uamul) { + already_wearing("an amulet"); + return(0); + } + setworn(otmp, W_AMUL); + if (otmp->otyp == AMULET_OF_CHANGE) { + Amulet_on(); + /* Don't do a prinv() since the amulet is now gone */ + return(1); + } + Amulet_on(); + } 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); + } + Blindf_on(otmp); + return(1); + } + if (is_worn(otmp)) + prinv((char *)0, otmp, 0L); + return(1); +} + +#endif /* OVLB */ + +#ifdef OVL0 + +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); +#ifdef TOURIST + if(uarmu) uac -= ARM_BONUS(uarmu); +#endif + 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; + flags.botl = 1; + } +} + +#endif /* OVL0 */ +#ifdef OVLB + +void +glibr() +{ + register struct obj *otmp; + int xfl = 0; + boolean leftfall, rightfall; + + 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", + makeplural(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) { + Your("%s %sslips from your %s.", + is_sword(otmp) ? c_sword : + makesingular(oclass_names[(int)otmp->oclass]), + xfl ? "also " : "", + makeplural(body_part(HAND))); + setuswapwep((struct obj *)0); + xfl++; + if (otmp->otyp != LOADSTONE || !otmp->cursed) + dropx(otmp); + } + otmp = uwep; + if (otmp && !welded(otmp)) { + /* changed so cursed weapons don't fall, GAN 10/30/86 */ + Your("%s %sslips from your %s.", + is_sword(otmp) ? c_sword : + makesingular(oclass_names[(int)otmp->oclass]), + xfl ? "also " : "", + makeplural(body_part(HAND))); + setuwep((struct obj *)0); + if (otmp->otyp != LOADSTONE || !otmp->cursed) + 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); +#ifdef TOURIST + if (!otmph) + otmph = (victim == &youmonst) ? uarmu : which_armor(victim, W_ARMU); +#endif + + 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); +} + +/* erode some arbitrary armor worn by the victim */ +void +erode_armor(victim, acid_dmg) +struct monst *victim; +boolean acid_dmg; +{ + struct obj *otmph = some_armor(victim); + + if (otmph && (otmph != uarmf)) { + erode_obj(otmph, acid_dmg, FALSE); + } +} + +STATIC_PTR +int +select_off(otmp) +register struct obj *otmp; +{ + 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(uarmg && uarmg->cursed && (otmp==uright || otmp==uleft)) { + uarmg->bknown = TRUE; + You("cannot remove your gloves to take off the ring."); + return(0); + } + if(otmp == uarmf && u.utrap && (u.utraptype == TT_BEARTRAP || + u.utraptype == TT_INFLOOR)) { + return (0); + } + if((otmp==uarm +#ifdef TOURIST + || 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); + } +#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); + } +#endif + + if(otmp == uarm) takeoff_mask |= WORN_ARMOR; + else if(otmp == uarmc) takeoff_mask |= WORN_CLOAK; + else if(otmp == uarmf) takeoff_mask |= WORN_BOOTS; + else if(otmp == uarmg) takeoff_mask |= WORN_GLOVES; + else if(otmp == uarmh) takeoff_mask |= WORN_HELMET; + else if(otmp == uarms) takeoff_mask |= WORN_SHIELD; +#ifdef TOURIST + else if(otmp == uarmu) takeoff_mask |= WORN_SHIRT; +#endif + else if(otmp == uleft) takeoff_mask |= LEFT_RING; + else if(otmp == uright) takeoff_mask |= RIGHT_RING; + else if(otmp == uamul) takeoff_mask |= WORN_AMUL; + else if(otmp == ublindf) takeoff_mask |= WORN_BLINDF; + else if(otmp == uwep) takeoff_mask |= W_WEP; + else if(otmp == uswapwep) takeoff_mask |= W_SWAPWEP; + else if(otmp == uquiver) takeoff_mask |= W_QUIVER; + + else impossible("select_off: %s???", doname(otmp)); + + return(0); +} + +STATIC_OVL struct obj * +do_takeoff() +{ + register struct obj *otmp = (struct obj *)0; + + if (taking_off == W_WEP) { + if(!cursed(uwep)) { + setuwep((struct obj *) 0); + You("are empty %s.", body_part(HANDED)); + u.twoweap = FALSE; + } + } else if (taking_off == W_SWAPWEP) { + setuswapwep((struct obj *) 0); + You("no longer have a second weapon readied."); + u.twoweap = FALSE; + } else if (taking_off == W_QUIVER) { + setuqwep((struct obj *) 0); + You("no longer have ammunition readied."); + } else if (taking_off == WORN_ARMOR) { + otmp = uarm; + if(!cursed(otmp)) (void) Armor_off(); + } else if (taking_off == WORN_CLOAK) { + otmp = uarmc; + if(!cursed(otmp)) (void) Cloak_off(); + } else if (taking_off == WORN_BOOTS) { + otmp = uarmf; + if(!cursed(otmp)) (void) Boots_off(); + } else if (taking_off == WORN_GLOVES) { + otmp = uarmg; + if(!cursed(otmp)) (void) Gloves_off(); + } else if (taking_off == WORN_HELMET) { + otmp = uarmh; + if(!cursed(otmp)) (void) Helmet_off(); + } else if (taking_off == WORN_SHIELD) { + otmp = uarms; + if(!cursed(otmp)) (void) Shield_off(); +#ifdef TOURIST + } else if (taking_off == WORN_SHIRT) { + otmp = uarmu; + if(!cursed(otmp)) + setworn((struct obj *)0, uarmu->owornmask & W_ARMOR); +#endif + } else if (taking_off == WORN_AMUL) { + otmp = uamul; + if(!cursed(otmp)) Amulet_off(); + } else if (taking_off == LEFT_RING) { + otmp = uleft; + if(!cursed(otmp)) Ring_off(uleft); + } else if (taking_off == RIGHT_RING) { + otmp = uright; + if(!cursed(otmp)) Ring_off(uright); + } else if (taking_off == WORN_BLINDF) { + if (!cursed(ublindf)) Blindf_off(ublindf); + } else impossible("do_takeoff: taking off %lx", taking_off); + + return(otmp); +} + +STATIC_PTR +int +take_off() +{ + register int i; + register struct obj *otmp; + + if(taking_off) { + if(todelay > 0) { + + todelay--; + return(1); /* still busy */ + } else if((otmp = do_takeoff())) off_msg(otmp); + + takeoff_mask &= ~taking_off; + taking_off = 0L; + } + + for(i = 0; takeoff_order[i]; i++) + if(takeoff_mask & takeoff_order[i]) { + taking_off = takeoff_order[i]; + break; + } + + otmp = (struct obj *) 0; + todelay = 0; + + if (taking_off == 0L) { + You("finish disrobing."); + return 0; + } else if (taking_off == W_WEP) { + todelay = 1; + } else if (taking_off == W_SWAPWEP) { + todelay = 1; + } else if (taking_off == W_QUIVER) { + todelay = 1; + } else if (taking_off == 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) todelay += 2 * objects[uarmc->otyp].oc_delay + 1; + } else if (taking_off == WORN_CLOAK) { + otmp = uarmc; + } else if (taking_off == WORN_BOOTS) { + otmp = uarmf; + } else if (taking_off == WORN_GLOVES) { + otmp = uarmg; + } else if (taking_off == WORN_HELMET) { + otmp = uarmh; + } else if (taking_off == WORN_SHIELD) { + otmp = uarms; +#ifdef TOURIST + } else if (taking_off == WORN_SHIRT) { + otmp = uarmu; + /* add the time to take off and put back on armor and/or cloak */ + if (uarm) todelay += 2 * objects[uarm->otyp].oc_delay; + if (uarmc) todelay += 2 * objects[uarmc->otyp].oc_delay + 1; +#endif + } else if (taking_off == WORN_AMUL) { + todelay = 1; + } else if (taking_off == LEFT_RING) { + todelay = 1; + } else if (taking_off == RIGHT_RING) { + todelay = 1; + } else if (taking_off == WORN_BLINDF) { + todelay = 2; + } else { + impossible("take_off: taking off %lx", taking_off); + return 0; /* force done */ + } + + if (otmp) todelay += 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 (todelay>0) todelay--; + + set_occupation(take_off, "disrobing", 0); + return(1); /* get busy */ +} + +#endif /* OVLB */ +#ifdef OVL1 + +void +reset_remarm() +{ + taking_off = takeoff_mask = 0L; +} + +#endif /* OVL1 */ +#ifdef OVLB + +int +doddoremarm() +{ + int result = 0; + + if (taking_off || takeoff_mask) { + You("continue disrobing."); + set_occupation(take_off, "disrobing", 0); + (void) take_off(); + 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 (takeoff_mask) + (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; +} + +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))) + + if (DESTROY_ARM(uarmc)) { + Your("%s crumbles and turns to dust!", cloak_simple_name(uarmc)); + (void) Cloak_off(); + useup(otmp); + } else if (DESTROY_ARM(uarm)) { + /* may be disintegrated by spell or dragon breath... */ + 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); +#ifdef TOURIST + } else if (DESTROY_ARM(uarmu)) { + Your("shirt crumbles into tiny threads and falls apart!"); + useup(otmp); +#endif + } else if (DESTROY_ARM(uarmh)) { + if (donning(otmp)) cancel_don(); + Your("helmet turns to dust and is blown away!"); + (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)) { + Your("shield crumbles away!"); + (void) Shield_off(); + useup(otmp); + } else return(0); /* could not destroy anything */ + +#undef DESTROY_ARM + 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); + } + flags.botl = 1; + } + if (uarmh && uarmh == otmp && otmp->otyp == HELM_OF_BRILLIANCE) { + if (delta) { + makeknown(uarmh->otyp); + ABON(A_INT) += (delta); + ABON(A_WIS) += (delta); + } + flags.botl = 1; + } +} + +#endif /* OVLB */ + +/*do_wear.c*/