Permalink
Switch branches/tags
Nothing to show
Find file
Fetching contributors…
Cannot retrieve contributors at this time
2186 lines (2038 sloc) 54.6 KB
/* SCCS Id: @(#)do_wear.c 3.4 2003/11/14 */
/* 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;
static NEARDATA long 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_PTR int NDECL(Shield_on);
#ifdef TOURIST
STATIC_PTR int NDECL(Shirt_on);
#endif
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;
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 && !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:
case LEATHER_CLOAK:
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 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()
{
int otyp = uarmc->otyp;
long oldprop = u.uprops[objects[otyp].oc_oprop].extrinsic & ~WORN_CLOAK;
takeoff_mask &= ~W_ARMC;
/* 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:
case LEATHER_CLOAK:
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) {
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);
}
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()
{
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:
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;
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);
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;
(void) encumber_msg(); /* immediate feedback for GoP */
/* Prevent wielding cockatrice when not wearing gloves */
if (uwep && uwep->otyp == CORPSE &&
touch_petrifies(&mons[uwep->corpsenm])) {
char kbuf[BUFSZ];
You("wield the %s in your bare %s.",
corpse_xname(uwep, TRUE), makeplural(body_part(HAND)));
Strcpy(kbuf, an(corpse_xname(uwep, TRUE)));
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 in your bare %s.",
corpse_xname(uswapwep, TRUE), body_part(HAND));
Strcpy(kbuf, an(corpse_xname(uswapwep, TRUE)));
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()
{
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;
}
#ifdef TOURIST
STATIC_OVL int
Shirt_on()
{
/*
switch (uarmu->otyp) {
case HAWAIIAN_SHIRT:
case T_SHIRT:
break;
default: impossible(unknown_type, c_shirt, uarmu->otyp);
}
*/
return 0;
}
int
Shirt_off()
{
takeoff_mask &= ~W_ARMU;
/*
switch (uarmu->otyp) {
case HAWAIIAN_SHIRT:
case T_SHIRT:
break;
default: impossible(unknown_type, c_shirt, uarmu->otyp);
}
*/
setworn((struct obj *)0, W_ARMU);
return 0;
}
#endif /*TOURIST*/
/* This must be done in worn.c, because one of the possible intrinsics conferred
* 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()
{
takeoff_mask &= ~W_ARM;
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()
{
takeoff_mask &= ~W_ARM;
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()
{
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) {
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, which;
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_LEVITATION:
if (!oldprop && !HLevitation) {
float_up();
makeknown(RIN_LEVITATION);
spoteffects(FALSE); /* for sinks */
}
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;
if (ACURR(which) != old_attrib ||
(objects[obj->otyp].oc_name_known &&
old_attrib != 25 && old_attrib != 3)) {
flags.botl = 1;
makeknown(obj->otyp);
obj->known = 1;
update_inventory();
}
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:
if (obj->spe || objects[RIN_PROTECTION].oc_name_known) {
flags.botl = 1;
makeknown(RIN_PROTECTION);
obj->known = 1;
update_inventory();
}
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;
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_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_LEVITATION:
(void) float_down(0L, 0L);
if (!Levitation) makeknown(RIN_LEVITATION);
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;
if (ACURR(which) != old_attrib) {
flags.botl = 1;
makeknown(obj->otyp);
obj->known = 1;
update_inventory();
}
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 forgotten it due to amnesia */
if (obj->spe) {
flags.botl = 1;
makeknown(RIN_PROTECTION);
obj->known = 1;
update_inventory();
}
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;
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) {
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()
{
#ifdef TOURIST
if (uarmu) (void) Shirt_on();
#endif
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();
}
/* 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) ? taking_off : 0L; */
long what = taking_off; /* if nonzero, occupation is implied */
boolean result = FALSE;
if (otmp == uarm)
result = (afternmv == Armor_on || afternmv == Armor_off ||
what == WORN_ARMOR);
#ifdef TOURIST
else if (otmp == uarmu)
result = (afternmv == Shirt_on || afternmv == Shirt_off ||
what == WORN_SHIRT);
#endif
else if (otmp == uarmc)
result = (afternmv == Cloak_on || afternmv == Cloak_off ||
what == WORN_CLOAK);
else if (otmp == uarmf)
result = (afternmv == Boots_on || afternmv == Boots_off ||
what == WORN_BOOTS);
else if (otmp == uarmh)
result = (afternmv == Helmet_on || afternmv == Helmet_off ||
what == WORN_HELMET);
else if (otmp == uarmg)
result = (afternmv == Gloves_on || afternmv == Gloves_off ||
what == WORN_GLOVES);
else if (otmp == uarms)
result = (afternmv == Shield_on || afternmv == Shield_off ||
what == WORN_SHIELD);
return result;
}
void
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;
todelay = 0;
taking_off = 0L;
}
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;
#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.%s", (iflags.cmdassist &&
(uleft || uright || uamul || ublindf)) ?
" Use 'R' command to remove accessories." : "");
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;
}
reset_remarm(); /* clear takeoff_mask and taking_off */
(void) select_off(otmp);
if (!takeoff_mask) return 0;
reset_remarm(); /* armoroff() doesn't use takeoff_mask */
(void) armoroff(otmp);
return(1);
}
/* the 'R' command */
int
doremring()
{
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 ||
#ifdef TOURIST
uarmu ||
#endif
uarms || uarmh || uarmg || uarmf)) ?
" Use 'T' command to take off armor." : "");
return(0);
}
if (Accessories != 1) 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 takeoff_mask and taking_off */
(void) select_off(otmp);
if (!takeoff_mask) return 0;
reset_remarm(); /* not used by Ring_/Amulet_/Blindf_off() */
if (otmp == uright || otmp == uleft) {
/* Sometimes we want to give the off_msg before removing and
* sometimes after; for instance, "you were wearing a moonstone
* ring (on right hand)" is desired but "you were wearing a
* 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) {
You("can't. %s cursed.",
(is_boots(otmp) || is_gloves(otmp) || otmp->quan > 1L)
? "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);
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) &&
(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)
#ifdef TOURIST
|| is_shirt(otmp)
#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 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.",
c_helmet, 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)) {
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) 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 (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 */
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);
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();
#ifdef TOURIST
if (is_shirt(otmp)) (void) Shirt_on();
#endif
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, "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(otmp == uwep)
setuwep((struct obj *)0);
if(otmp == uswapwep)
setuswapwep((struct obj *) 0);
if(otmp == uquiver)
setuqwep((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);
}
if (otmp->oartifact && !touch_artifact(otmp, &youmonst))
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 (otmp->oartifact && !touch_artifact(otmp, &youmonst))
return 1;
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);
}
if (otmp->oartifact && !touch_artifact(otmp, &youmonst))
return 1;
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;
const char *otherwep = 0;
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) {
otherwep = is_sword(otmp) ? c_sword :
makesingular(oclass_names[(int)otmp->oclass]);
Your("%s %sslips from your %s.",
otherwep,
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)) {
const char *thiswep;
/* nice wording if both weapons are the same type */
thiswep = is_sword(otmp) ? c_sword :
makesingular(oclass_names[(int)otmp->oclass]);
if (otherwep && strcmp(thiswep, otherwep)) otherwep = 0;
/* changed so cursed weapons don't fall, GAN 10/30/86 */
Your("%s%s %sslips from your %s.",
otherwep ? "other " : "", thiswep,
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);
if (carried(otmph)) update_inventory();
}
}
/* 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;
}
/* occupation callback for 'A' */
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
#ifdef TOURIST
|| otmp == uarmu
#endif
) {
why = 0; /* the item which prevents disrobing */
if (uarmc && uarmc->cursed) {
Sprintf(buf, "remove your %s", cloak_simple_name(uarmc));
why = uarmc;
#ifdef TOURIST
} else if (otmp == uarmu && uarm && uarm->cursed) {
Sprintf(buf, "remove your %s", c_suit);
why = uarm;
#endif
} else if (welded(uwep) && bimanual(uwep)) {
Sprintf(buf, "release your %s",
is_sword(uwep) ? c_sword :
(uwep->otyp == BATTLE_AXE) ? c_axe : c_weapon);
why = uwep;
}
if (why) {
You("cannot %s to take off %s.", buf, the(xname(otmp)));
why->bknown = TRUE;
return 0;
}
}
/* 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) 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)) (void) Shirt_off();
#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 const char *disrobing = "";
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 %s.", 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 */
}
/* clear saved context to avoid inappropriate resumption of interrupted 'A' */
void
reset_remarm()
{
taking_off = takeoff_mask = 0L;
disrobing = nul;
}
/* the 'A' command -- remove multiple worn items */
int
doddoremarm()
{
int result = 0;
if (taking_off || takeoff_mask) {
You("continue %s.", disrobing);
set_occupation(take_off, 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 (takeoff_mask) {
/* default activity for armor and/or accessories,
possibly combined with weapons */
disrobing = "disrobing";
/* specific activity when handling weapons only */
if (!(takeoff_mask & ~(W_WEP|W_SWAPWEP|W_QUIVER)))
disrobing = "disarming";
(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)))
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);
#ifdef TOURIST
} else if (DESTROY_ARM(uarmu)) {
if (donning(otmp)) cancel_don();
Your("shirt crumbles into tiny threads and falls apart!");
(void) Shirt_off();
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)) {
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);
}
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*/