Show keys in travel help wrapped in single quotes
[aNetHack.git] / src / do_wear.c
blobe588e5413967d4070d81c83f8be2056ec130fee6
1 /* NetHack 3.6 do_wear.c $NHDT-Date: 1455667557 2016/02/17 00:05:57 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.90 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed. See license for details. */
5 #include "hack.h"
7 static NEARDATA const char see_yourself[] = "see yourself";
8 static NEARDATA const char unknown_type[] = "Unknown type of %s (%d)";
9 static NEARDATA const char c_armor[] = "armor", c_suit[] = "suit",
10 c_shirt[] = "shirt", c_cloak[] = "cloak",
11 c_gloves[] = "gloves", c_boots[] = "boots",
12 c_helmet[] = "helmet", c_shield[] = "shield",
13 c_weapon[] = "weapon", c_sword[] = "sword",
14 c_axe[] = "axe", c_that_[] = "that";
16 static NEARDATA const long takeoff_order[] = {
17 WORN_BLINDF, W_WEP, WORN_SHIELD, WORN_GLOVES, LEFT_RING,
18 RIGHT_RING, WORN_CLOAK, WORN_HELMET, WORN_AMUL, WORN_ARMOR,
19 WORN_SHIRT, WORN_BOOTS, W_SWAPWEP, W_QUIVER, 0L
22 STATIC_DCL void FDECL(on_msg, (struct obj *));
23 STATIC_DCL void FDECL(toggle_stealth, (struct obj *, long, BOOLEAN_P));
24 STATIC_DCL void FDECL(toggle_displacement, (struct obj *, long, BOOLEAN_P));
25 STATIC_PTR int NDECL(Armor_on);
26 STATIC_PTR int NDECL(Boots_on);
27 STATIC_PTR int NDECL(Cloak_on);
28 STATIC_PTR int NDECL(Helmet_on);
29 STATIC_PTR int NDECL(Gloves_on);
30 STATIC_DCL void FDECL(wielding_corpse, (struct obj *, BOOLEAN_P));
31 STATIC_PTR int NDECL(Shield_on);
32 STATIC_PTR int NDECL(Shirt_on);
33 STATIC_DCL void NDECL(Amulet_on);
34 STATIC_DCL void FDECL(learnring, (struct obj *, BOOLEAN_P));
35 STATIC_DCL void FDECL(Ring_off_or_gone, (struct obj *, BOOLEAN_P));
36 STATIC_PTR int FDECL(select_off, (struct obj *));
37 STATIC_DCL struct obj *NDECL(do_takeoff);
38 STATIC_PTR int NDECL(take_off);
39 STATIC_DCL int FDECL(menu_remarm, (int));
40 STATIC_DCL void FDECL(count_worn_stuff, (struct obj **, BOOLEAN_P));
41 STATIC_PTR int FDECL(armor_or_accessory_off, (struct obj *));
42 STATIC_PTR int FDECL(accessory_or_armor_on, (struct obj *));
43 STATIC_DCL void FDECL(already_wearing, (const char *));
44 STATIC_DCL void FDECL(already_wearing2, (const char *, const char *));
46 void
47 off_msg(otmp)
48 struct obj *otmp;
50 if (flags.verbose)
51 You("were wearing %s.", doname(otmp));
54 /* for items that involve no delay */
55 STATIC_OVL void
56 on_msg(otmp)
57 struct obj *otmp;
59 if (flags.verbose) {
60 char how[BUFSZ];
61 /* call xname() before obj_is_pname(); formatting obj's name
62 might set obj->dknown and that affects the pname test */
63 const char *otmp_name = xname(otmp);
65 how[0] = '\0';
66 if (otmp->otyp == TOWEL)
67 Sprintf(how, " around your %s", body_part(HEAD));
68 You("are now wearing %s%s.",
69 obj_is_pname(otmp) ? the(otmp_name) : an(otmp_name), how);
73 /* starting equipment gets auto-worn at beginning of new game,
74 and we don't want stealth or displacement feedback then */
75 static boolean initial_don = FALSE; /* manipulated in set_wear() */
77 /* putting on or taking off an item which confers stealth;
78 give feedback and discover it iff stealth state is changing */
79 STATIC_OVL
80 void
81 toggle_stealth(obj, oldprop, on)
82 struct obj *obj;
83 long oldprop; /* prop[].extrinsic, with obj->owornmask stripped by caller */
84 boolean on;
86 if (on ? initial_don : context.takeoff.cancelled_don)
87 return;
89 if (!oldprop /* extrinsic stealth from something else */
90 && !HStealth /* intrinsic stealth */
91 && !BStealth) { /* stealth blocked by something */
92 if (obj->otyp == RIN_STEALTH)
93 learnring(obj, TRUE);
94 else
95 makeknown(obj->otyp);
97 if (on) {
98 if (!is_boots(obj))
99 You("move very quietly.");
100 else if (Levitation || Flying)
101 You("float imperceptibly.");
102 else
103 You("walk very quietly.");
104 } else {
105 You("sure are noisy.");
110 /* putting on or taking off an item which confers displacement;
111 give feedback and discover it iff displacement state is changing *and*
112 hero is able to see self (or sense monsters) */
113 STATIC_OVL
114 void
115 toggle_displacement(obj, oldprop, on)
116 struct obj *obj;
117 long oldprop; /* prop[].extrinsic, with obj->owornmask stripped by caller */
118 boolean on;
120 if (on ? initial_don : context.takeoff.cancelled_don)
121 return;
123 if (!oldprop /* extrinsic displacement from something else */
124 && !(u.uprops[DISPLACED].intrinsic) /* (theoretical) */
125 && !(u.uprops[DISPLACED].blocked) /* (also theoretical) */
126 /* we don't use canseeself() here because it augments vision
127 with touch, which isn't appropriate for deciding whether
128 we'll notice that monsters have trouble spotting the hero */
129 && ((!Blind /* see anything */
130 && !u.uswallow /* see surroundings */
131 && !Invisible) /* see self */
132 /* actively sensing nearby monsters via telepathy or extended
133 monster detection overrides vision considerations because
134 hero also senses self in this situation */
135 || (Unblind_telepat
136 || (Blind_telepat && Blind)
137 || Detect_monsters))) {
138 makeknown(obj->otyp);
140 You_feel("that monsters%s have difficulty pinpointing your location.",
141 on ? "" : " no longer");
146 * The Type_on() functions should be called *after* setworn().
147 * The Type_off() functions call setworn() themselves.
148 * [Blindf_on() is an exception and calls setworn() itself.]
151 STATIC_PTR
153 Boots_on(VOID_ARGS)
155 long oldprop =
156 u.uprops[objects[uarmf->otyp].oc_oprop].extrinsic & ~WORN_BOOTS;
158 switch (uarmf->otyp) {
159 case LOW_BOOTS:
160 case IRON_SHOES:
161 case HIGH_BOOTS:
162 case JUMPING_BOOTS:
163 case KICKING_BOOTS:
164 break;
165 case WATER_WALKING_BOOTS:
166 if (u.uinwater)
167 spoteffects(TRUE);
168 /* (we don't need a lava check here since boots can't be
169 put on while feet are stuck) */
170 break;
171 case SPEED_BOOTS:
172 /* Speed boots are still better than intrinsic speed, */
173 /* though not better than potion speed */
174 if (!oldprop && !(HFast & TIMEOUT)) {
175 makeknown(uarmf->otyp);
176 You_feel("yourself speed up%s.",
177 (oldprop || HFast) ? " a bit more" : "");
179 break;
180 case ELVEN_BOOTS:
181 toggle_stealth(uarmf, oldprop, TRUE);
182 break;
183 case FUMBLE_BOOTS:
184 if (!oldprop && !(HFumbling & ~TIMEOUT))
185 incr_itimeout(&HFumbling, rnd(20));
186 break;
187 case LEVITATION_BOOTS:
188 if (!oldprop && !HLevitation && !BLevitation) {
189 makeknown(uarmf->otyp);
190 float_up();
191 spoteffects(FALSE);
192 } else {
193 float_vs_flight(); /* maybe toggle (BFlying & I_SPECIAL) */
195 break;
196 default:
197 impossible(unknown_type, c_boots, uarmf->otyp);
199 return 0;
203 Boots_off(VOID_ARGS)
205 struct obj *otmp = uarmf;
206 int otyp = otmp->otyp;
207 long oldprop = u.uprops[objects[otyp].oc_oprop].extrinsic & ~WORN_BOOTS;
209 context.takeoff.mask &= ~W_ARMF;
210 /* For levitation, float_down() returns if Levitation, so we
211 * must do a setworn() _before_ the levitation case.
213 setworn((struct obj *) 0, W_ARMF);
214 switch (otyp) {
215 case SPEED_BOOTS:
216 if (!Very_fast && !context.takeoff.cancelled_don) {
217 makeknown(otyp);
218 You_feel("yourself slow down%s.", Fast ? " a bit" : "");
220 break;
221 case WATER_WALKING_BOOTS:
222 /* check for lava since fireproofed boots make it viable */
223 if ((is_pool(u.ux, u.uy) || is_lava(u.ux, u.uy))
224 && !Levitation && !Flying && !is_clinger(youmonst.data)
225 && !context.takeoff.cancelled_don
226 /* avoid recursive call to lava_effects() */
227 && !iflags.in_lava_effects) {
228 /* make boots known in case you survive the drowning */
229 makeknown(otyp);
230 spoteffects(TRUE);
232 break;
233 case ELVEN_BOOTS:
234 toggle_stealth(otmp, oldprop, FALSE);
235 break;
236 case FUMBLE_BOOTS:
237 if (!oldprop && !(HFumbling & ~TIMEOUT))
238 HFumbling = EFumbling = 0;
239 break;
240 case LEVITATION_BOOTS:
241 if (!oldprop && !HLevitation && !BLevitation
242 && !context.takeoff.cancelled_don) {
243 (void) float_down(0L, 0L);
244 makeknown(otyp);
245 } else {
246 float_vs_flight(); /* maybe toggle (BFlying & I_SPECIAL) */
248 break;
249 case LOW_BOOTS:
250 case IRON_SHOES:
251 case HIGH_BOOTS:
252 case JUMPING_BOOTS:
253 case KICKING_BOOTS:
254 break;
255 default:
256 impossible(unknown_type, c_boots, otyp);
258 context.takeoff.cancelled_don = FALSE;
259 return 0;
262 STATIC_PTR int
263 Cloak_on(VOID_ARGS)
265 long oldprop =
266 u.uprops[objects[uarmc->otyp].oc_oprop].extrinsic & ~WORN_CLOAK;
268 switch (uarmc->otyp) {
269 case ORCISH_CLOAK:
270 case DWARVISH_CLOAK:
271 case CLOAK_OF_MAGIC_RESISTANCE:
272 case ROBE:
273 case LEATHER_CLOAK:
274 break;
275 case CLOAK_OF_PROTECTION:
276 makeknown(uarmc->otyp);
277 break;
278 case ELVEN_CLOAK:
279 toggle_stealth(uarmc, oldprop, TRUE);
280 break;
281 case CLOAK_OF_DISPLACEMENT:
282 toggle_displacement(uarmc, oldprop, TRUE);
283 break;
284 case MUMMY_WRAPPING:
285 /* Note: it's already being worn, so we have to cheat here. */
286 if ((HInvis || EInvis) && !Blind) {
287 newsym(u.ux, u.uy);
288 You("can %s!", See_invisible ? "no longer see through yourself"
289 : see_yourself);
291 break;
292 case CLOAK_OF_INVISIBILITY:
293 /* since cloak of invisibility was worn, we know mummy wrapping
294 wasn't, so no need to check `oldprop' against blocked */
295 if (!oldprop && !HInvis && !Blind) {
296 makeknown(uarmc->otyp);
297 newsym(u.ux, u.uy);
298 pline("Suddenly you can%s yourself.",
299 See_invisible ? " see through" : "not see");
301 break;
302 case OILSKIN_CLOAK:
303 pline("%s very tightly.", Tobjnam(uarmc, "fit"));
304 break;
305 /* Alchemy smock gives poison _and_ acid resistance */
306 case ALCHEMY_SMOCK:
307 EAcid_resistance |= WORN_CLOAK;
308 break;
309 default:
310 impossible(unknown_type, c_cloak, uarmc->otyp);
312 return 0;
316 Cloak_off(VOID_ARGS)
318 struct obj *otmp = uarmc;
319 int otyp = otmp->otyp;
320 long oldprop = u.uprops[objects[otyp].oc_oprop].extrinsic & ~WORN_CLOAK;
322 context.takeoff.mask &= ~W_ARMC;
323 /* For mummy wrapping, taking it off first resets `Invisible'. */
324 setworn((struct obj *) 0, W_ARMC);
325 switch (otyp) {
326 case ORCISH_CLOAK:
327 case DWARVISH_CLOAK:
328 case CLOAK_OF_PROTECTION:
329 case CLOAK_OF_MAGIC_RESISTANCE:
330 case OILSKIN_CLOAK:
331 case ROBE:
332 case LEATHER_CLOAK:
333 break;
334 case ELVEN_CLOAK:
335 toggle_stealth(otmp, oldprop, FALSE);
336 break;
337 case CLOAK_OF_DISPLACEMENT:
338 toggle_displacement(otmp, oldprop, FALSE);
339 break;
340 case MUMMY_WRAPPING:
341 if (Invis && !Blind) {
342 newsym(u.ux, u.uy);
343 You("can %s.", See_invisible ? "see through yourself"
344 : "no longer see yourself");
346 break;
347 case CLOAK_OF_INVISIBILITY:
348 if (!oldprop && !HInvis && !Blind) {
349 makeknown(CLOAK_OF_INVISIBILITY);
350 newsym(u.ux, u.uy);
351 pline("Suddenly you can %s.",
352 See_invisible ? "no longer see through yourself"
353 : see_yourself);
355 break;
356 /* Alchemy smock gives poison _and_ acid resistance */
357 case ALCHEMY_SMOCK:
358 EAcid_resistance &= ~WORN_CLOAK;
359 break;
360 default:
361 impossible(unknown_type, c_cloak, otyp);
363 return 0;
366 STATIC_PTR
368 Helmet_on(VOID_ARGS)
370 switch (uarmh->otyp) {
371 case FEDORA:
372 case HELMET:
373 case DENTED_POT:
374 case ELVEN_LEATHER_HELM:
375 case DWARVISH_IRON_HELM:
376 case ORCISH_HELM:
377 case HELM_OF_TELEPATHY:
378 break;
379 case HELM_OF_BRILLIANCE:
380 adj_abon(uarmh, uarmh->spe);
381 break;
382 case CORNUTHAUM:
383 /* people think marked wizards know what they're talking
384 * about, but it takes trained arrogance to pull it off,
385 * and the actual enchantment of the hat is irrelevant.
387 ABON(A_CHA) += (Role_if(PM_WIZARD) ? 1 : -1);
388 context.botl = 1;
389 makeknown(uarmh->otyp);
390 break;
391 case HELM_OF_OPPOSITE_ALIGNMENT:
392 /* changing alignment can toggle off active artifact
393 properties, including levitation; uarmh could get
394 dropped or destroyed here */
395 uchangealign((u.ualign.type != A_NEUTRAL)
396 ? -u.ualign.type
397 : (uarmh->o_id % 2) ? A_CHAOTIC : A_LAWFUL,
399 /* makeknown(uarmh->otyp); -- moved below, after xname() */
400 /*FALLTHRU*/
401 case DUNCE_CAP:
402 if (uarmh && !uarmh->cursed) {
403 if (Blind)
404 pline("%s for a moment.", Tobjnam(uarmh, "vibrate"));
405 else
406 pline("%s %s for a moment.", Tobjnam(uarmh, "glow"),
407 hcolor(NH_BLACK));
408 curse(uarmh);
410 context.botl = 1; /* reveal new alignment or INT & WIS */
411 if (Hallucination) {
412 pline("My brain hurts!"); /* Monty Python's Flying Circus */
413 } else if (uarmh && uarmh->otyp == DUNCE_CAP) {
414 You_feel("%s.", /* track INT change; ignore WIS */
415 ACURR(A_INT)
416 <= (ABASE(A_INT) + ABON(A_INT) + ATEMP(A_INT))
417 ? "like sitting in a corner"
418 : "giddy");
419 } else {
420 /* [message moved to uchangealign()] */
421 makeknown(HELM_OF_OPPOSITE_ALIGNMENT);
423 break;
424 default:
425 impossible(unknown_type, c_helmet, uarmh->otyp);
427 return 0;
431 Helmet_off(VOID_ARGS)
433 context.takeoff.mask &= ~W_ARMH;
435 switch (uarmh->otyp) {
436 case FEDORA:
437 case HELMET:
438 case DENTED_POT:
439 case ELVEN_LEATHER_HELM:
440 case DWARVISH_IRON_HELM:
441 case ORCISH_HELM:
442 break;
443 case DUNCE_CAP:
444 context.botl = 1;
445 break;
446 case CORNUTHAUM:
447 if (!context.takeoff.cancelled_don) {
448 ABON(A_CHA) += (Role_if(PM_WIZARD) ? -1 : 1);
449 context.botl = 1;
451 break;
452 case HELM_OF_TELEPATHY:
453 /* need to update ability before calling see_monsters() */
454 setworn((struct obj *) 0, W_ARMH);
455 see_monsters();
456 return 0;
457 case HELM_OF_BRILLIANCE:
458 if (!context.takeoff.cancelled_don)
459 adj_abon(uarmh, -uarmh->spe);
460 break;
461 case HELM_OF_OPPOSITE_ALIGNMENT:
462 /* changing alignment can toggle off active artifact
463 properties, including levitation; uarmh could get
464 dropped or destroyed here */
465 uchangealign(u.ualignbase[A_CURRENT], 2);
466 break;
467 default:
468 impossible(unknown_type, c_helmet, uarmh->otyp);
470 setworn((struct obj *) 0, W_ARMH);
471 context.takeoff.cancelled_don = FALSE;
472 return 0;
475 STATIC_PTR
477 Gloves_on(VOID_ARGS)
479 long oldprop =
480 u.uprops[objects[uarmg->otyp].oc_oprop].extrinsic & ~WORN_GLOVES;
482 switch (uarmg->otyp) {
483 case LEATHER_GLOVES:
484 break;
485 case GAUNTLETS_OF_FUMBLING:
486 if (!oldprop && !(HFumbling & ~TIMEOUT))
487 incr_itimeout(&HFumbling, rnd(20));
488 break;
489 case GAUNTLETS_OF_POWER:
490 makeknown(uarmg->otyp);
491 context.botl = 1; /* taken care of in attrib.c */
492 break;
493 case GAUNTLETS_OF_DEXTERITY:
494 adj_abon(uarmg, uarmg->spe);
495 break;
496 default:
497 impossible(unknown_type, c_gloves, uarmg->otyp);
499 return 0;
502 STATIC_OVL void
503 wielding_corpse(obj, voluntary)
504 struct obj *obj;
505 boolean voluntary; /* taking gloves off on purpose? */
507 char kbuf[BUFSZ];
509 if (!obj || obj->otyp != CORPSE)
510 return;
511 if (obj != uwep && (obj != uswapwep || !u.twoweap))
512 return;
514 if (touch_petrifies(&mons[obj->corpsenm]) && !Stone_resistance) {
515 You("now wield %s in your bare %s.",
516 corpse_xname(obj, (const char *) 0, CXN_ARTICLE),
517 makeplural(body_part(HAND)));
518 Sprintf(kbuf, "%s gloves while wielding %s",
519 voluntary ? "removing" : "losing", killer_xname(obj));
520 instapetrify(kbuf);
521 /* life-saved; can't continue wielding cockatrice corpse though */
522 remove_worn_item(obj, FALSE);
527 Gloves_off(VOID_ARGS)
529 long oldprop =
530 u.uprops[objects[uarmg->otyp].oc_oprop].extrinsic & ~WORN_GLOVES;
531 boolean on_purpose = !context.mon_moving && !uarmg->in_use;
533 context.takeoff.mask &= ~W_ARMG;
535 switch (uarmg->otyp) {
536 case LEATHER_GLOVES:
537 break;
538 case GAUNTLETS_OF_FUMBLING:
539 if (!oldprop && !(HFumbling & ~TIMEOUT))
540 HFumbling = EFumbling = 0;
541 break;
542 case GAUNTLETS_OF_POWER:
543 makeknown(uarmg->otyp);
544 context.botl = 1; /* taken care of in attrib.c */
545 break;
546 case GAUNTLETS_OF_DEXTERITY:
547 if (!context.takeoff.cancelled_don)
548 adj_abon(uarmg, -uarmg->spe);
549 break;
550 default:
551 impossible(unknown_type, c_gloves, uarmg->otyp);
553 setworn((struct obj *) 0, W_ARMG);
554 context.takeoff.cancelled_don = FALSE;
555 (void) encumber_msg(); /* immediate feedback for GoP */
557 /* prevent wielding cockatrice when not wearing gloves */
558 if (uwep && uwep->otyp == CORPSE)
559 wielding_corpse(uwep, on_purpose);
561 /* KMH -- ...or your secondary weapon when you're wielding it
562 [This case can't actually happen; twoweapon mode won't
563 engage if a corpse has been set up as the alternate weapon.] */
564 if (u.twoweap && uswapwep && uswapwep->otyp == CORPSE)
565 wielding_corpse(uswapwep, on_purpose);
567 return 0;
570 STATIC_PTR int
571 Shield_on(VOID_ARGS)
573 /* no shield currently requires special handling when put on, but we
574 keep this uncommented in case somebody adds a new one which does */
575 switch (uarms->otyp) {
576 case SMALL_SHIELD:
577 case ELVEN_SHIELD:
578 case URUK_HAI_SHIELD:
579 case ORCISH_SHIELD:
580 case DWARVISH_ROUNDSHIELD:
581 case LARGE_SHIELD:
582 case SHIELD_OF_REFLECTION:
583 break;
584 default:
585 impossible(unknown_type, c_shield, uarms->otyp);
588 return 0;
592 Shield_off(VOID_ARGS)
594 context.takeoff.mask &= ~W_ARMS;
596 /* no shield currently requires special handling when taken off, but we
597 keep this uncommented in case somebody adds a new one which does */
598 switch (uarms->otyp) {
599 case SMALL_SHIELD:
600 case ELVEN_SHIELD:
601 case URUK_HAI_SHIELD:
602 case ORCISH_SHIELD:
603 case DWARVISH_ROUNDSHIELD:
604 case LARGE_SHIELD:
605 case SHIELD_OF_REFLECTION:
606 break;
607 default:
608 impossible(unknown_type, c_shield, uarms->otyp);
611 setworn((struct obj *) 0, W_ARMS);
612 return 0;
615 STATIC_PTR int
616 Shirt_on(VOID_ARGS)
618 /* no shirt currently requires special handling when put on, but we
619 keep this uncommented in case somebody adds a new one which does */
620 switch (uarmu->otyp) {
621 case HAWAIIAN_SHIRT:
622 case T_SHIRT:
623 break;
624 default:
625 impossible(unknown_type, c_shirt, uarmu->otyp);
628 return 0;
632 Shirt_off(VOID_ARGS)
634 context.takeoff.mask &= ~W_ARMU;
636 /* no shirt currently requires special handling when taken off, but we
637 keep this uncommented in case somebody adds a new one which does */
638 switch (uarmu->otyp) {
639 case HAWAIIAN_SHIRT:
640 case T_SHIRT:
641 break;
642 default:
643 impossible(unknown_type, c_shirt, uarmu->otyp);
646 setworn((struct obj *) 0, W_ARMU);
647 return 0;
650 /* This must be done in worn.c, because one of the possible intrinsics
651 * conferred is fire resistance, and we have to immediately set
652 * HFire_resistance in worn.c since worn.c will check it before returning.
654 STATIC_PTR
656 Armor_on(VOID_ARGS)
658 return 0;
662 Armor_off(VOID_ARGS)
664 context.takeoff.mask &= ~W_ARM;
665 setworn((struct obj *) 0, W_ARM);
666 context.takeoff.cancelled_don = FALSE;
667 return 0;
670 /* The gone functions differ from the off functions in that if you die from
671 * taking it off and have life saving, you still die.
674 Armor_gone()
676 context.takeoff.mask &= ~W_ARM;
677 setnotworn(uarm);
678 context.takeoff.cancelled_don = FALSE;
679 return 0;
682 STATIC_OVL void
683 Amulet_on()
685 /* make sure amulet isn't wielded; can't use remove_worn_item()
686 here because it has already been set worn in amulet slot */
687 if (uamul == uwep)
688 setuwep((struct obj *) 0);
689 else if (uamul == uswapwep)
690 setuswapwep((struct obj *) 0);
691 else if (uamul == uquiver)
692 setuqwep((struct obj *) 0);
694 switch (uamul->otyp) {
695 case AMULET_OF_ESP:
696 case AMULET_OF_LIFE_SAVING:
697 case AMULET_VERSUS_POISON:
698 case AMULET_OF_REFLECTION:
699 case AMULET_OF_MAGICAL_BREATHING:
700 case FAKE_AMULET_OF_YENDOR:
701 break;
702 case AMULET_OF_UNCHANGING:
703 if (Slimed)
704 make_slimed(0L, (char *) 0);
705 break;
706 case AMULET_OF_CHANGE: {
707 int orig_sex = poly_gender();
709 if (Unchanging)
710 break;
711 change_sex();
712 /* Don't use same message as polymorph */
713 if (orig_sex != poly_gender()) {
714 makeknown(AMULET_OF_CHANGE);
715 You("are suddenly very %s!",
716 flags.female ? "feminine" : "masculine");
717 context.botl = 1;
718 } else
719 /* already polymorphed into single-gender monster; only
720 changed the character's base sex */
721 You("don't feel like yourself.");
722 pline_The("amulet disintegrates!");
723 if (orig_sex == poly_gender() && uamul->dknown
724 && !objects[AMULET_OF_CHANGE].oc_name_known
725 && !objects[AMULET_OF_CHANGE].oc_uname)
726 docall(uamul);
727 useup(uamul);
728 break;
730 case AMULET_OF_STRANGULATION:
731 if (can_be_strangled(&youmonst)) {
732 makeknown(AMULET_OF_STRANGULATION);
733 Strangled = 6L;
734 context.botl = TRUE;
735 pline("It constricts your throat!");
737 break;
738 case AMULET_OF_RESTFUL_SLEEP: {
739 long newnap = (long) rnd(100), oldnap = (HSleepy & TIMEOUT);
741 /* avoid clobbering FROMOUTSIDE bit, which might have
742 gotten set by previously eating one of these amulets */
743 if (newnap < oldnap || oldnap == 0L)
744 HSleepy = (HSleepy & ~TIMEOUT) | newnap;
745 } break;
746 case AMULET_OF_YENDOR:
747 break;
751 void
752 Amulet_off()
754 context.takeoff.mask &= ~W_AMUL;
756 switch (uamul->otyp) {
757 case AMULET_OF_ESP:
758 /* need to update ability before calling see_monsters() */
759 setworn((struct obj *) 0, W_AMUL);
760 see_monsters();
761 return;
762 case AMULET_OF_LIFE_SAVING:
763 case AMULET_VERSUS_POISON:
764 case AMULET_OF_REFLECTION:
765 case AMULET_OF_CHANGE:
766 case AMULET_OF_UNCHANGING:
767 case FAKE_AMULET_OF_YENDOR:
768 break;
769 case AMULET_OF_MAGICAL_BREATHING:
770 if (Underwater) {
771 /* HMagical_breathing must be set off
772 before calling drown() */
773 setworn((struct obj *) 0, W_AMUL);
774 if (!breathless(youmonst.data) && !amphibious(youmonst.data)
775 && !Swimming) {
776 You("suddenly inhale an unhealthy amount of %s!",
777 hliquid("water"));
778 (void) drown();
780 return;
782 break;
783 case AMULET_OF_STRANGULATION:
784 if (Strangled) {
785 Strangled = 0L;
786 context.botl = TRUE;
787 if (Breathless)
788 Your("%s is no longer constricted!", body_part(NECK));
789 else
790 You("can breathe more easily!");
792 break;
793 case AMULET_OF_RESTFUL_SLEEP:
794 setworn((struct obj *) 0, W_AMUL);
795 /* HSleepy = 0L; -- avoid clobbering FROMOUTSIDE bit */
796 if (!ESleepy && !(HSleepy & ~TIMEOUT))
797 HSleepy &= ~TIMEOUT; /* clear timeout bits */
798 return;
799 case AMULET_OF_YENDOR:
800 break;
802 setworn((struct obj *) 0, W_AMUL);
803 return;
806 /* handle ring discovery; comparable to learnwand() */
807 STATIC_OVL void
808 learnring(ring, observed)
809 struct obj *ring;
810 boolean observed;
812 int ringtype = ring->otyp;
814 /* if effect was observeable then we usually discover the type */
815 if (observed) {
816 /* if we already know the ring type which accomplishes this
817 effect (assumes there is at most one type for each effect),
818 mark this ring as having been seen (no need for makeknown);
819 otherwise if we have seen this ring, discover its type */
820 if (objects[ringtype].oc_name_known)
821 ring->dknown = 1;
822 else if (ring->dknown)
823 makeknown(ringtype);
824 #if 0 /* see learnwand() */
825 else
826 ring->eknown = 1;
827 #endif
830 /* make enchantment of charged ring known (might be +0) and update
831 perm invent window if we've seen this ring and know its type */
832 if (ring->dknown && objects[ringtype].oc_name_known) {
833 if (objects[ringtype].oc_charged)
834 ring->known = 1;
835 update_inventory();
839 void
840 Ring_on(obj)
841 register struct obj *obj;
843 long oldprop = u.uprops[objects[obj->otyp].oc_oprop].extrinsic;
844 int old_attrib, which;
845 boolean observable;
847 /* make sure ring isn't wielded; can't use remove_worn_item()
848 here because it has already been set worn in a ring slot */
849 if (obj == uwep)
850 setuwep((struct obj *) 0);
851 else if (obj == uswapwep)
852 setuswapwep((struct obj *) 0);
853 else if (obj == uquiver)
854 setuqwep((struct obj *) 0);
856 /* only mask out W_RING when we don't have both
857 left and right rings of the same type */
858 if ((oldprop & W_RING) != W_RING)
859 oldprop &= ~W_RING;
861 switch (obj->otyp) {
862 case RIN_TELEPORTATION:
863 case RIN_REGENERATION:
864 case RIN_SEARCHING:
865 case RIN_HUNGER:
866 case RIN_AGGRAVATE_MONSTER:
867 case RIN_POISON_RESISTANCE:
868 case RIN_FIRE_RESISTANCE:
869 case RIN_COLD_RESISTANCE:
870 case RIN_SHOCK_RESISTANCE:
871 case RIN_CONFLICT:
872 case RIN_TELEPORT_CONTROL:
873 case RIN_POLYMORPH:
874 case RIN_POLYMORPH_CONTROL:
875 case RIN_FREE_ACTION:
876 case RIN_SLOW_DIGESTION:
877 case RIN_SUSTAIN_ABILITY:
878 case MEAT_RING:
879 break;
880 case RIN_STEALTH:
881 toggle_stealth(obj, oldprop, TRUE);
882 break;
883 case RIN_WARNING:
884 see_monsters();
885 break;
886 case RIN_SEE_INVISIBLE:
887 /* can now see invisible monsters */
888 set_mimic_blocking(); /* do special mimic handling */
889 see_monsters();
891 if (Invis && !oldprop && !HSee_invisible && !Blind) {
892 newsym(u.ux, u.uy);
893 pline("Suddenly you are transparent, but there!");
894 learnring(obj, TRUE);
896 break;
897 case RIN_INVISIBILITY:
898 if (!oldprop && !HInvis && !BInvis && !Blind) {
899 learnring(obj, TRUE);
900 newsym(u.ux, u.uy);
901 self_invis_message();
903 break;
904 case RIN_LEVITATION:
905 if (!oldprop && !HLevitation && !BLevitation) {
906 float_up();
907 learnring(obj, TRUE);
908 spoteffects(FALSE); /* for sinks */
909 } else {
910 float_vs_flight(); /* maybe toggle (BFlying & I_SPECIAL) */
912 break;
913 case RIN_GAIN_STRENGTH:
914 which = A_STR;
915 goto adjust_attrib;
916 case RIN_GAIN_CONSTITUTION:
917 which = A_CON;
918 goto adjust_attrib;
919 case RIN_ADORNMENT:
920 which = A_CHA;
921 adjust_attrib:
922 old_attrib = ACURR(which);
923 ABON(which) += obj->spe;
924 observable = (old_attrib != ACURR(which));
925 /* if didn't change, usually means ring is +0 but might
926 be because nonzero couldn't go below min or above max;
927 learn +0 enchantment if attribute value is not stuck
928 at a limit [and ring has been seen and its type is
929 already discovered, both handled by learnring()] */
930 if (observable || !extremeattr(which))
931 learnring(obj, observable);
932 context.botl = 1;
933 break;
934 case RIN_INCREASE_ACCURACY: /* KMH */
935 u.uhitinc += obj->spe;
936 break;
937 case RIN_INCREASE_DAMAGE:
938 u.udaminc += obj->spe;
939 break;
940 case RIN_PROTECTION_FROM_SHAPE_CHAN:
941 rescham();
942 break;
943 case RIN_PROTECTION:
944 /* usually learn enchantment and discover type;
945 won't happen if ring is unseen or if it's +0
946 and the type hasn't been discovered yet */
947 observable = (obj->spe != 0);
948 learnring(obj, observable);
949 if (obj->spe)
950 find_ac(); /* updates botl */
951 break;
955 STATIC_OVL void
956 Ring_off_or_gone(obj, gone)
957 register struct obj *obj;
958 boolean gone;
960 long mask = (obj->owornmask & W_RING);
961 int old_attrib, which;
962 boolean observable;
964 context.takeoff.mask &= ~mask;
965 if (!(u.uprops[objects[obj->otyp].oc_oprop].extrinsic & mask))
966 impossible("Strange... I didn't know you had that ring.");
967 if (gone)
968 setnotworn(obj);
969 else
970 setworn((struct obj *) 0, obj->owornmask);
972 switch (obj->otyp) {
973 case RIN_TELEPORTATION:
974 case RIN_REGENERATION:
975 case RIN_SEARCHING:
976 case RIN_HUNGER:
977 case RIN_AGGRAVATE_MONSTER:
978 case RIN_POISON_RESISTANCE:
979 case RIN_FIRE_RESISTANCE:
980 case RIN_COLD_RESISTANCE:
981 case RIN_SHOCK_RESISTANCE:
982 case RIN_CONFLICT:
983 case RIN_TELEPORT_CONTROL:
984 case RIN_POLYMORPH:
985 case RIN_POLYMORPH_CONTROL:
986 case RIN_FREE_ACTION:
987 case RIN_SLOW_DIGESTION:
988 case RIN_SUSTAIN_ABILITY:
989 case MEAT_RING:
990 break;
991 case RIN_STEALTH:
992 toggle_stealth(obj, (EStealth & ~mask), FALSE);
993 break;
994 case RIN_WARNING:
995 see_monsters();
996 break;
997 case RIN_SEE_INVISIBLE:
998 /* Make invisible monsters go away */
999 if (!See_invisible) {
1000 set_mimic_blocking(); /* do special mimic handling */
1001 see_monsters();
1004 if (Invisible && !Blind) {
1005 newsym(u.ux, u.uy);
1006 pline("Suddenly you cannot see yourself.");
1007 learnring(obj, TRUE);
1009 break;
1010 case RIN_INVISIBILITY:
1011 if (!Invis && !BInvis && !Blind) {
1012 newsym(u.ux, u.uy);
1013 Your("body seems to unfade%s.",
1014 See_invisible ? " completely" : "..");
1015 learnring(obj, TRUE);
1017 break;
1018 case RIN_LEVITATION:
1019 if (!BLevitation) {
1020 (void) float_down(0L, 0L);
1021 if (!Levitation)
1022 learnring(obj, TRUE);
1023 } else {
1024 float_vs_flight(); /* maybe toggle (BFlying & I_SPECIAL) */
1026 break;
1027 case RIN_GAIN_STRENGTH:
1028 which = A_STR;
1029 goto adjust_attrib;
1030 case RIN_GAIN_CONSTITUTION:
1031 which = A_CON;
1032 goto adjust_attrib;
1033 case RIN_ADORNMENT:
1034 which = A_CHA;
1035 adjust_attrib:
1036 old_attrib = ACURR(which);
1037 ABON(which) -= obj->spe;
1038 observable = (old_attrib != ACURR(which));
1039 /* same criteria as Ring_on() */
1040 if (observable || !extremeattr(which))
1041 learnring(obj, observable);
1042 context.botl = 1;
1043 break;
1044 case RIN_INCREASE_ACCURACY: /* KMH */
1045 u.uhitinc -= obj->spe;
1046 break;
1047 case RIN_INCREASE_DAMAGE:
1048 u.udaminc -= obj->spe;
1049 break;
1050 case RIN_PROTECTION:
1051 /* might have been put on while blind and we can now see
1052 or perhaps been forgotten due to amnesia */
1053 observable = (obj->spe != 0);
1054 learnring(obj, observable);
1055 if (obj->spe)
1056 find_ac(); /* updates botl */
1057 break;
1058 case RIN_PROTECTION_FROM_SHAPE_CHAN:
1059 /* If you're no longer protected, let the chameleons
1060 * change shape again -dgk
1062 restartcham();
1063 break;
1067 void
1068 Ring_off(obj)
1069 struct obj *obj;
1071 Ring_off_or_gone(obj, FALSE);
1074 void
1075 Ring_gone(obj)
1076 struct obj *obj;
1078 Ring_off_or_gone(obj, TRUE);
1081 void
1082 Blindf_on(otmp)
1083 register struct obj *otmp;
1085 boolean already_blind = Blind, changed = FALSE;
1087 /* blindfold might be wielded; release it for wearing */
1088 if (otmp->owornmask & W_WEAPON)
1089 remove_worn_item(otmp, FALSE);
1090 setworn(otmp, W_TOOL);
1091 on_msg(otmp);
1093 if (Blind && !already_blind) {
1094 changed = TRUE;
1095 if (flags.verbose)
1096 You_cant("see any more.");
1097 /* set ball&chain variables before the hero goes blind */
1098 if (Punished)
1099 set_bc(0);
1100 } else if (already_blind && !Blind) {
1101 changed = TRUE;
1102 /* "You are now wearing the Eyes of the Overworld." */
1103 if (u.uroleplay.blind) {
1104 /* this can only happen by putting on the Eyes of the Overworld;
1105 that shouldn't actually produce a permanent cure, but we
1106 can't let the "blind from birth" conduct remain intact */
1107 pline("For the first time in your life, you can see!");
1108 u.uroleplay.blind = FALSE;
1109 } else
1110 You("can see!");
1112 if (changed) {
1113 /* blindness has just been toggled */
1114 if (Blind_telepat || Infravision)
1115 see_monsters();
1116 vision_full_recalc = 1; /* recalc vision limits */
1117 if (!Blind)
1118 learn_unseen_invent();
1119 context.botl = 1;
1123 void
1124 Blindf_off(otmp)
1125 register struct obj *otmp;
1127 boolean was_blind = Blind, changed = FALSE;
1129 if (!otmp) {
1130 impossible("Blindf_off without otmp");
1131 return;
1133 context.takeoff.mask &= ~W_TOOL;
1134 setworn((struct obj *) 0, otmp->owornmask);
1135 off_msg(otmp);
1137 if (Blind) {
1138 if (was_blind) {
1139 /* "still cannot see" makes no sense when removing lenses
1140 since they can't have been the cause of your blindness */
1141 if (otmp->otyp != LENSES)
1142 You("still cannot see.");
1143 } else {
1144 changed = TRUE; /* !was_blind */
1145 /* "You were wearing the Eyes of the Overworld." */
1146 You_cant("see anything now!");
1147 /* set ball&chain variables before the hero goes blind */
1148 if (Punished)
1149 set_bc(0);
1151 } else if (was_blind) {
1152 if (!gulp_blnd_check()) {
1153 changed = TRUE; /* !Blind */
1154 You("can see again.");
1157 if (changed) {
1158 /* blindness has just been toggled */
1159 if (Blind_telepat || Infravision)
1160 see_monsters();
1161 vision_full_recalc = 1; /* recalc vision limits */
1162 if (!Blind)
1163 learn_unseen_invent();
1164 context.botl = 1;
1168 /* called in moveloop()'s prologue to set side-effects of worn start-up items;
1169 also used by poly_obj() when a worn item gets transformed */
1170 void
1171 set_wear(obj)
1172 struct obj *obj; /* if null, do all worn items; otherwise just obj itself */
1174 initial_don = !obj;
1176 if (!obj ? ublindf != 0 : (obj == ublindf))
1177 (void) Blindf_on(ublindf);
1178 if (!obj ? uright != 0 : (obj == uright))
1179 (void) Ring_on(uright);
1180 if (!obj ? uleft != 0 : (obj == uleft))
1181 (void) Ring_on(uleft);
1182 if (!obj ? uamul != 0 : (obj == uamul))
1183 (void) Amulet_on();
1185 if (!obj ? uarmu != 0 : (obj == uarmu))
1186 (void) Shirt_on();
1187 if (!obj ? uarm != 0 : (obj == uarm))
1188 (void) Armor_on();
1189 if (!obj ? uarmc != 0 : (obj == uarmc))
1190 (void) Cloak_on();
1191 if (!obj ? uarmf != 0 : (obj == uarmf))
1192 (void) Boots_on();
1193 if (!obj ? uarmg != 0 : (obj == uarmg))
1194 (void) Gloves_on();
1195 if (!obj ? uarmh != 0 : (obj == uarmh))
1196 (void) Helmet_on();
1197 if (!obj ? uarms != 0 : (obj == uarms))
1198 (void) Shield_on();
1200 initial_don = FALSE;
1203 /* check whether the target object is currently being put on (or taken off--
1204 also checks for doffing) */
1205 boolean
1206 donning(otmp)
1207 struct obj *otmp;
1209 /* long what = (occupation == take_off) ? context.takeoff.what : 0L; */
1210 long what = context.takeoff.what; /* if nonzero, occupation is implied */
1211 boolean result = FALSE;
1213 /* 'W' and 'T' set afternmv, 'A' sets context.takeoff.what */
1214 if (otmp == uarm)
1215 result = (afternmv == Armor_on || afternmv == Armor_off
1216 || what == WORN_ARMOR);
1217 else if (otmp == uarmu)
1218 result = (afternmv == Shirt_on || afternmv == Shirt_off
1219 || what == WORN_SHIRT);
1220 else if (otmp == uarmc)
1221 result = (afternmv == Cloak_on || afternmv == Cloak_off
1222 || what == WORN_CLOAK);
1223 else if (otmp == uarmf)
1224 result = (afternmv == Boots_on || afternmv == Boots_off
1225 || what == WORN_BOOTS);
1226 else if (otmp == uarmh)
1227 result = (afternmv == Helmet_on || afternmv == Helmet_off
1228 || what == WORN_HELMET);
1229 else if (otmp == uarmg)
1230 result = (afternmv == Gloves_on || afternmv == Gloves_off
1231 || what == WORN_GLOVES);
1232 else if (otmp == uarms)
1233 result = (afternmv == Shield_on || afternmv == Shield_off
1234 || what == WORN_SHIELD);
1236 return result;
1239 /* check whether the target object is currently being taken off,
1240 so that stop_donning() and steal() can vary messages */
1241 boolean
1242 doffing(otmp)
1243 struct obj *otmp;
1245 long what = context.takeoff.what;
1246 boolean result = FALSE;
1248 /* 'T' (also 'W') sets afternmv, 'A' sets context.takeoff.what */
1249 if (otmp == uarm)
1250 result = (afternmv == Armor_off || what == WORN_ARMOR);
1251 else if (otmp == uarmu)
1252 result = (afternmv == Shirt_off || what == WORN_SHIRT);
1253 else if (otmp == uarmc)
1254 result = (afternmv == Cloak_off || what == WORN_CLOAK);
1255 else if (otmp == uarmf)
1256 result = (afternmv == Boots_off || what == WORN_BOOTS);
1257 else if (otmp == uarmh)
1258 result = (afternmv == Helmet_off || what == WORN_HELMET);
1259 else if (otmp == uarmg)
1260 result = (afternmv == Gloves_off || what == WORN_GLOVES);
1261 else if (otmp == uarms)
1262 result = (afternmv == Shield_off || what == WORN_SHIELD);
1264 return result;
1267 void
1268 cancel_don()
1270 /* the piece of armor we were donning/doffing has vanished, so stop
1271 * wasting time on it (and don't dereference it when donning would
1272 * otherwise finish)
1274 context.takeoff.cancelled_don =
1275 (afternmv == Boots_on || afternmv == Helmet_on
1276 || afternmv == Gloves_on || afternmv == Armor_on);
1277 afternmv = 0;
1278 nomovemsg = (char *) 0;
1279 multi = 0;
1280 context.takeoff.delay = 0;
1281 context.takeoff.what = 0L;
1284 /* called by steal() during theft from hero; interrupt donning/doffing */
1286 stop_donning(stolenobj)
1287 struct obj *stolenobj; /* no message if stolenobj is already being doffing */
1289 char buf[BUFSZ];
1290 struct obj *otmp;
1291 boolean putting_on;
1292 int result = 0;
1294 for (otmp = invent; otmp; otmp = otmp->nobj)
1295 if ((otmp->owornmask & W_ARMOR) && donning(otmp))
1296 break;
1297 /* at most one item will pass donning() test at any given time */
1298 if (!otmp)
1299 return 0;
1301 /* donning() returns True when doffing too; doffing() is more specific */
1302 putting_on = !doffing(otmp);
1303 /* cancel_don() looks at afternmv; it also serves as cancel_doff() */
1304 cancel_don();
1305 /* don't want <armor>_on() or <armor>_off() being called
1306 by unmul() since the on or off action isn't completing */
1307 afternmv = 0;
1308 if (putting_on || otmp != stolenobj) {
1309 Sprintf(buf, "You stop %s %s.",
1310 putting_on ? "putting on" : "taking off",
1311 thesimpleoname(otmp));
1312 } else {
1313 buf[0] = '\0'; /* silently stop doffing stolenobj */
1314 result = -multi; /* remember this before calling unmul() */
1316 unmul(buf);
1317 /* while putting on, item becomes worn immediately but side-effects are
1318 deferred until the delay expires; when interrupted, make it unworn
1319 (while taking off, item stays worn until the delay expires; when
1320 interrupted, leave it worn) */
1321 if (putting_on)
1322 remove_worn_item(otmp, FALSE);
1324 return result;
1327 /* both 'clothes' and 'accessories' now include both armor and accessories;
1328 TOOL_CLASS is for eyewear, FOOD_CLASS is for MEAT_RING */
1329 static NEARDATA const char clothes[] = {
1330 ARMOR_CLASS, RING_CLASS, AMULET_CLASS, TOOL_CLASS, FOOD_CLASS, 0
1332 static NEARDATA const char accessories[] = {
1333 RING_CLASS, AMULET_CLASS, TOOL_CLASS, FOOD_CLASS, ARMOR_CLASS, 0
1335 STATIC_VAR NEARDATA int Narmorpieces, Naccessories;
1337 /* assign values to Narmorpieces and Naccessories */
1338 STATIC_OVL void
1339 count_worn_stuff(which, accessorizing)
1340 struct obj **which; /* caller wants this when count is 1 */
1341 boolean accessorizing;
1343 struct obj *otmp;
1345 Narmorpieces = Naccessories = 0;
1347 #define MOREWORN(x,wtyp) do { if (x) { wtyp++; otmp = x; } } while (0)
1348 otmp = 0;
1349 MOREWORN(uarmh, Narmorpieces);
1350 MOREWORN(uarms, Narmorpieces);
1351 MOREWORN(uarmg, Narmorpieces);
1352 MOREWORN(uarmf, Narmorpieces);
1353 /* for cloak/suit/shirt, we only count the outermost item so that it
1354 can be taken off without confirmation if final count ends up as 1 */
1355 if (uarmc)
1356 MOREWORN(uarmc, Narmorpieces);
1357 else if (uarm)
1358 MOREWORN(uarm, Narmorpieces);
1359 else if (uarmu)
1360 MOREWORN(uarmu, Narmorpieces);
1361 if (!accessorizing)
1362 *which = otmp; /* default item iff Narmorpieces is 1 */
1364 otmp = 0;
1365 MOREWORN(uleft, Naccessories);
1366 MOREWORN(uright, Naccessories);
1367 MOREWORN(uamul, Naccessories);
1368 MOREWORN(ublindf, Naccessories);
1369 if (accessorizing)
1370 *which = otmp; /* default item iff Naccessories is 1 */
1371 #undef MOREWORN
1374 /* take off one piece or armor or one accessory;
1375 shared by dotakeoff('T') and doremring('R') */
1376 STATIC_OVL int
1377 armor_or_accessory_off(obj)
1378 struct obj *obj;
1380 if (!(obj->owornmask & (W_ARMOR | W_ACCESSORY))) {
1381 You("are not wearing that.");
1382 return 0;
1384 if (obj == uskin
1385 || ((obj == uarm) && uarmc)
1386 || ((obj == uarmu) && (uarmc || uarm))) {
1387 char why[QBUFSZ], what[QBUFSZ];
1389 why[0] = what[0] = '\0';
1390 if (obj != uskin) {
1391 if (uarmc)
1392 Strcat(what, cloak_simple_name(uarmc));
1393 if ((obj == uarmu) && uarm) {
1394 if (uarmc)
1395 Strcat(what, " and ");
1396 Strcat(what, suit_simple_name(uarm));
1398 Sprintf(why, " without taking off your %s first", what);
1399 } else {
1400 Strcpy(why, "; it's embedded");
1402 You_cant("take that off%s.", why);
1403 return 0;
1406 reset_remarm(); /* clear context.takeoff.mask and context.takeoff.what */
1407 (void) select_off(obj);
1408 if (!context.takeoff.mask)
1409 return 0;
1410 /* none of armoroff()/Ring_/Amulet/Blindf_off() use context.takeoff.mask */
1411 reset_remarm();
1413 if (obj->owornmask & W_ARMOR) {
1414 (void) armoroff(obj);
1415 } else if (obj == uright || obj == uleft) {
1416 /* Sometimes we want to give the off_msg before removing and
1417 * sometimes after; for instance, "you were wearing a moonstone
1418 * ring (on right hand)" is desired but "you were wearing a
1419 * square amulet (being worn)" is not because of the redundant
1420 * "being worn".
1422 off_msg(obj);
1423 Ring_off(obj);
1424 } else if (obj == uamul) {
1425 Amulet_off();
1426 off_msg(obj);
1427 } else if (obj == ublindf) {
1428 Blindf_off(obj); /* does its own off_msg */
1429 } else {
1430 impossible("removing strange accessory?");
1431 if (obj->owornmask)
1432 remove_worn_item(obj, FALSE);
1434 return 1;
1437 /* the 'T' command */
1439 dotakeoff()
1441 struct obj *otmp = (struct obj *) 0;
1443 count_worn_stuff(&otmp, FALSE);
1444 if (!Narmorpieces && !Naccessories) {
1445 /* assert( GRAY_DRAGON_SCALES > YELLOW_DRAGON_SCALE_MAIL ); */
1446 if (uskin)
1447 pline_The("%s merged with your skin!",
1448 uskin->otyp >= GRAY_DRAGON_SCALES
1449 ? "dragon scales are"
1450 : "dragon scale mail is");
1451 else
1452 pline("Not wearing any armor or accessories.");
1453 return 0;
1455 if (Narmorpieces != 1 || ParanoidRemove)
1456 otmp = getobj(clothes, "take off");
1457 if (!otmp)
1458 return 0;
1460 return armor_or_accessory_off(otmp);
1463 /* the 'R' command */
1465 doremring()
1467 struct obj *otmp = 0;
1469 count_worn_stuff(&otmp, TRUE);
1470 if (!Naccessories && !Narmorpieces) {
1471 pline("Not wearing any accessories or armor.");
1472 return 0;
1474 if (Naccessories != 1 || ParanoidRemove)
1475 otmp = getobj(accessories, "remove");
1476 if (!otmp)
1477 return 0;
1479 return armor_or_accessory_off(otmp);
1482 /* Check if something worn is cursed _and_ unremovable. */
1484 cursed(otmp)
1485 register struct obj *otmp;
1487 /* Curses, like chickens, come home to roost. */
1488 if ((otmp == uwep) ? welded(otmp) : (int) otmp->cursed) {
1489 boolean use_plural = (is_boots(otmp) || is_gloves(otmp)
1490 || otmp->otyp == LENSES || otmp->quan > 1L);
1492 You("can't. %s cursed.", use_plural ? "They are" : "It is");
1493 otmp->bknown = TRUE;
1494 return 1;
1496 return 0;
1500 armoroff(otmp)
1501 register struct obj *otmp;
1503 register int delay = -objects[otmp->otyp].oc_delay;
1505 if (cursed(otmp))
1506 return 0;
1507 if (delay) {
1508 nomul(delay);
1509 multi_reason = "disrobing";
1510 if (is_helmet(otmp)) {
1511 /* ick... */
1512 nomovemsg = !strcmp(helm_simple_name(otmp), "hat")
1513 ? "You finish taking off your hat."
1514 : "You finish taking off your helmet.";
1515 afternmv = Helmet_off;
1516 } else if (is_gloves(otmp)) {
1517 nomovemsg = "You finish taking off your gloves.";
1518 afternmv = Gloves_off;
1519 } else if (is_boots(otmp)) {
1520 nomovemsg = "You finish taking off your boots.";
1521 afternmv = Boots_off;
1522 } else {
1523 nomovemsg = "You finish taking off your suit.";
1524 afternmv = Armor_off;
1526 } else {
1527 /* Be warned! We want off_msg after removing the item to
1528 * avoid "You were wearing ____ (being worn)." However, an
1529 * item which grants fire resistance might cause some trouble
1530 * if removed in Hell and lifesaving puts it back on; in this
1531 * case the message will be printed at the wrong time (after
1532 * the messages saying you died and were lifesaved). Luckily,
1533 * no cloak, shield, or fast-removable armor grants fire
1534 * resistance, so we can safely do the off_msg afterwards.
1535 * Rings do grant fire resistance, but for rings we want the
1536 * off_msg before removal anyway so there's no problem. Take
1537 * care in adding armors granting fire resistance; this code
1538 * might need modification.
1539 * 3.2 (actually 3.1 even): that comment is obsolete since
1540 * fire resistance is not required for Gehennom so setworn()
1541 * doesn't force the resistance granting item to be re-worn
1542 * after being lifesaved anymore.
1544 if (is_cloak(otmp))
1545 (void) Cloak_off();
1546 else if (is_shield(otmp))
1547 (void) Shield_off();
1548 else
1549 setworn((struct obj *) 0, otmp->owornmask & W_ARMOR);
1550 off_msg(otmp);
1552 context.takeoff.mask = context.takeoff.what = 0L;
1553 return 1;
1556 STATIC_OVL void
1557 already_wearing(cc)
1558 const char *cc;
1560 You("are already wearing %s%c", cc, (cc == c_that_) ? '!' : '.');
1563 STATIC_OVL void
1564 already_wearing2(cc1, cc2)
1565 const char *cc1, *cc2;
1567 You_cant("wear %s because you're wearing %s there already.", cc1, cc2);
1571 * canwearobj checks to see whether the player can wear a piece of armor
1573 * inputs: otmp (the piece of armor)
1574 * noisy (if TRUE give error messages, otherwise be quiet about it)
1575 * output: mask (otmp's armor type)
1578 canwearobj(otmp, mask, noisy)
1579 struct obj *otmp;
1580 long *mask;
1581 boolean noisy;
1583 int err = 0;
1584 const char *which;
1586 which = is_cloak(otmp)
1587 ? c_cloak
1588 : is_shirt(otmp)
1589 ? c_shirt
1590 : is_suit(otmp)
1591 ? c_suit
1592 : 0;
1593 if (which && cantweararm(youmonst.data)
1594 /* same exception for cloaks as used in m_dowear() */
1595 && (which != c_cloak || youmonst.data->msize != MZ_SMALL)
1596 && (racial_exception(&youmonst, otmp) < 1)) {
1597 if (noisy)
1598 pline_The("%s will not fit on your body.", which);
1599 return 0;
1600 } else if (otmp->owornmask & W_ARMOR) {
1601 if (noisy)
1602 already_wearing(c_that_);
1603 return 0;
1606 if (welded(uwep) && bimanual(uwep) && (is_suit(otmp) || is_shirt(otmp))) {
1607 if (noisy)
1608 You("cannot do that while holding your %s.",
1609 is_sword(uwep) ? c_sword : c_weapon);
1610 return 0;
1613 if (is_helmet(otmp)) {
1614 if (uarmh) {
1615 if (noisy)
1616 already_wearing(an(helm_simple_name(uarmh)));
1617 err++;
1618 } else if (Upolyd && has_horns(youmonst.data) && !is_flimsy(otmp)) {
1619 /* (flimsy exception matches polyself handling) */
1620 if (noisy)
1621 pline_The("%s won't fit over your horn%s.",
1622 helm_simple_name(otmp),
1623 plur(num_horns(youmonst.data)));
1624 err++;
1625 } else
1626 *mask = W_ARMH;
1627 } else if (is_shield(otmp)) {
1628 if (uarms) {
1629 if (noisy)
1630 already_wearing(an(c_shield));
1631 err++;
1632 } else if (uwep && bimanual(uwep)) {
1633 if (noisy)
1634 You("cannot wear a shield while wielding a two-handed %s.",
1635 is_sword(uwep) ? c_sword : (uwep->otyp == BATTLE_AXE)
1636 ? c_axe
1637 : c_weapon);
1638 err++;
1639 } else if (u.twoweap) {
1640 if (noisy)
1641 You("cannot wear a shield while wielding two weapons.");
1642 err++;
1643 } else
1644 *mask = W_ARMS;
1645 } else if (is_boots(otmp)) {
1646 if (uarmf) {
1647 if (noisy)
1648 already_wearing(c_boots);
1649 err++;
1650 } else if (Upolyd && slithy(youmonst.data)) {
1651 if (noisy)
1652 You("have no feet..."); /* not body_part(FOOT) */
1653 err++;
1654 } else if (Upolyd && youmonst.data->mlet == S_CENTAUR) {
1655 /* break_armor() pushes boots off for centaurs,
1656 so don't let dowear() put them back on... */
1657 if (noisy)
1658 pline("You have too many hooves to wear %s.",
1659 c_boots); /* makeplural(body_part(FOOT)) yields
1660 "rear hooves" which sounds odd */
1661 err++;
1662 } else if (u.utrap
1663 && (u.utraptype == TT_BEARTRAP || u.utraptype == TT_INFLOOR
1664 || u.utraptype == TT_LAVA
1665 || u.utraptype == TT_BURIEDBALL)) {
1666 if (u.utraptype == TT_BEARTRAP) {
1667 if (noisy)
1668 Your("%s is trapped!", body_part(FOOT));
1669 } else if (u.utraptype == TT_INFLOOR || u.utraptype == TT_LAVA) {
1670 if (noisy)
1671 Your("%s are stuck in the %s!",
1672 makeplural(body_part(FOOT)), surface(u.ux, u.uy));
1673 } else { /*TT_BURIEDBALL*/
1674 if (noisy)
1675 Your("%s is attached to the buried ball!",
1676 body_part(LEG));
1678 err++;
1679 } else
1680 *mask = W_ARMF;
1681 } else if (is_gloves(otmp)) {
1682 if (uarmg) {
1683 if (noisy)
1684 already_wearing(c_gloves);
1685 err++;
1686 } else if (welded(uwep)) {
1687 if (noisy)
1688 You("cannot wear gloves over your %s.",
1689 is_sword(uwep) ? c_sword : c_weapon);
1690 err++;
1691 } else
1692 *mask = W_ARMG;
1693 } else if (is_shirt(otmp)) {
1694 if (uarm || uarmc || uarmu) {
1695 if (uarmu) {
1696 if (noisy)
1697 already_wearing(an(c_shirt));
1698 } else {
1699 if (noisy)
1700 You_cant("wear that over your %s.",
1701 (uarm && !uarmc) ? c_armor
1702 : cloak_simple_name(uarmc));
1704 err++;
1705 } else
1706 *mask = W_ARMU;
1707 } else if (is_cloak(otmp)) {
1708 if (uarmc) {
1709 if (noisy)
1710 already_wearing(an(cloak_simple_name(uarmc)));
1711 err++;
1712 } else
1713 *mask = W_ARMC;
1714 } else if (is_suit(otmp)) {
1715 if (uarmc) {
1716 if (noisy)
1717 You("cannot wear armor over a %s.", cloak_simple_name(uarmc));
1718 err++;
1719 } else if (uarm) {
1720 if (noisy)
1721 already_wearing("some armor");
1722 err++;
1723 } else
1724 *mask = W_ARM;
1725 } else {
1726 /* getobj can't do this after setting its allow_all flag; that
1727 happens if you have armor for slots that are covered up or
1728 extra armor for slots that are filled */
1729 if (noisy)
1730 silly_thing("wear", otmp);
1731 err++;
1733 /* Unnecessary since now only weapons and special items like pick-axes get
1734 * welded to your hand, not armor
1735 if (welded(otmp)) {
1736 if (!err++) {
1737 if (noisy) weldmsg(otmp);
1741 return !err;
1744 STATIC_OVL int
1745 accessory_or_armor_on(obj)
1746 struct obj *obj;
1748 long mask = 0L;
1749 boolean armor, ring, eyewear;
1751 if (obj->owornmask & (W_ACCESSORY | W_ARMOR)) {
1752 already_wearing(c_that_);
1753 return 0;
1755 armor = (obj->oclass == ARMOR_CLASS);
1756 ring = (obj->oclass == RING_CLASS || obj->otyp == MEAT_RING);
1757 eyewear = (obj->otyp == BLINDFOLD || obj->otyp == TOWEL
1758 || obj->otyp == LENSES);
1759 /* checks which are performed prior to actually touching the item */
1760 if (armor) {
1761 if (!canwearobj(obj, &mask, TRUE))
1762 return 0;
1764 if (obj->otyp == HELM_OF_OPPOSITE_ALIGNMENT
1765 && qstart_level.dnum == u.uz.dnum) { /* in quest */
1766 if (u.ualignbase[A_CURRENT] == u.ualignbase[A_ORIGINAL])
1767 You("narrowly avoid losing all chance at your goal.");
1768 else /* converted */
1769 You("are suddenly overcome with shame and change your mind.");
1770 u.ublessed = 0; /* lose your god's protection */
1771 makeknown(obj->otyp);
1772 context.botl = 1; /*for AC after zeroing u.ublessed */
1773 return 1;
1775 } else {
1776 /* accessory */
1777 if (ring) {
1778 char answer, qbuf[QBUFSZ];
1779 int res = 0;
1781 if (nolimbs(youmonst.data)) {
1782 You("cannot make the ring stick to your body.");
1783 return 0;
1785 if (uleft && uright) {
1786 There("are no more %s%s to fill.",
1787 humanoid(youmonst.data) ? "ring-" : "",
1788 makeplural(body_part(FINGER)));
1789 return 0;
1791 if (uleft) {
1792 mask = RIGHT_RING;
1793 } else if (uright) {
1794 mask = LEFT_RING;
1795 } else {
1796 do {
1797 Sprintf(qbuf, "Which %s%s, Right or Left?",
1798 humanoid(youmonst.data) ? "ring-" : "",
1799 body_part(FINGER));
1800 answer = yn_function(qbuf, "rl", '\0');
1801 switch (answer) {
1802 case '\0':
1803 return 0;
1804 case 'l':
1805 case 'L':
1806 mask = LEFT_RING;
1807 break;
1808 case 'r':
1809 case 'R':
1810 mask = RIGHT_RING;
1811 break;
1813 } while (!mask);
1815 if (uarmg && uarmg->cursed) {
1816 res = !uarmg->bknown;
1817 uarmg->bknown = 1;
1818 You("cannot remove your gloves to put on the ring.");
1819 return res; /* uses move iff we learned gloves are cursed */
1821 if (uwep) {
1822 res = !uwep->bknown; /* check this before calling welded() */
1823 if ((mask == RIGHT_RING || bimanual(uwep)) && welded(uwep)) {
1824 const char *hand = body_part(HAND);
1826 /* welded will set bknown */
1827 if (bimanual(uwep))
1828 hand = makeplural(hand);
1829 You("cannot free your weapon %s to put on the ring.",
1830 hand);
1831 return res; /* uses move iff we learned weapon is cursed */
1834 } else if (obj->oclass == AMULET_CLASS) {
1835 if (uamul) {
1836 already_wearing("an amulet");
1837 return 0;
1839 } else if (eyewear) {
1840 if (ublindf) {
1841 if (ublindf->otyp == TOWEL)
1842 Your("%s is already covered by a towel.",
1843 body_part(FACE));
1844 else if (ublindf->otyp == BLINDFOLD) {
1845 if (obj->otyp == LENSES)
1846 already_wearing2("lenses", "a blindfold");
1847 else
1848 already_wearing("a blindfold");
1849 } else if (ublindf->otyp == LENSES) {
1850 if (obj->otyp == BLINDFOLD)
1851 already_wearing2("a blindfold", "some lenses");
1852 else
1853 already_wearing("some lenses");
1854 } else {
1855 already_wearing(something); /* ??? */
1857 return 0;
1859 } else {
1860 /* neither armor nor accessory */
1861 You_cant("wear that!");
1862 return 0;
1866 if (!retouch_object(&obj, FALSE))
1867 return 1; /* costs a turn even though it didn't get worn */
1869 if (armor) {
1870 int delay;
1872 obj->known = 1; /* since AC is shown on the status line */
1873 /* if the armor is wielded, release it for wearing */
1874 if (obj->owornmask & W_WEAPON)
1875 remove_worn_item(obj, FALSE);
1876 setworn(obj, mask);
1877 delay = -objects[obj->otyp].oc_delay;
1878 if (delay) {
1879 nomul(delay);
1880 multi_reason = "dressing up";
1881 if (is_boots(obj))
1882 afternmv = Boots_on;
1883 if (is_helmet(obj))
1884 afternmv = Helmet_on;
1885 if (is_gloves(obj))
1886 afternmv = Gloves_on;
1887 if (obj == uarm)
1888 afternmv = Armor_on;
1889 nomovemsg = "You finish your dressing maneuver.";
1890 } else {
1891 if (is_cloak(obj))
1892 (void) Cloak_on();
1893 if (is_shield(obj))
1894 (void) Shield_on();
1895 if (is_shirt(obj))
1896 (void) Shirt_on();
1897 on_msg(obj);
1899 context.takeoff.mask = context.takeoff.what = 0L;
1900 } else { /* not armor */
1901 boolean give_feedback = FALSE;
1903 /* [releasing wielded accessory handled in Xxx_on()] */
1904 if (ring) {
1905 setworn(obj, mask);
1906 Ring_on(obj);
1907 give_feedback = TRUE;
1908 } else if (obj->oclass == AMULET_CLASS) {
1909 setworn(obj, W_AMUL);
1910 Amulet_on();
1911 /* no feedback here if amulet of change got used up */
1912 give_feedback = (uamul != 0);
1913 } else if (eyewear) {
1914 /* setworn() handled by Blindf_on() */
1915 Blindf_on(obj);
1916 /* message handled by Blindf_on(); leave give_feedback False */
1918 /* feedback for ring or for amulet other than 'change' */
1919 if (give_feedback && is_worn(obj))
1920 prinv((char *) 0, obj, 0L);
1922 return 1;
1925 /* the 'W' command */
1927 dowear()
1929 struct obj *otmp;
1931 /* cantweararm() checks for suits of armor, not what we want here;
1932 verysmall() or nohands() checks for shields, gloves, etc... */
1933 if ((verysmall(youmonst.data) || nohands(youmonst.data))) {
1934 pline("Don't even bother.");
1935 return 0;
1937 if (uarm && uarmu && uarmc && uarmh && uarms && uarmg && uarmf
1938 && uleft && uright && uamul && ublindf) {
1939 /* 'W' message doesn't mention accessories */
1940 You("are already wearing a full complement of armor.");
1941 return 0;
1943 otmp = getobj(clothes, "wear");
1944 return otmp ? accessory_or_armor_on(otmp) : 0;
1947 /* the 'P' command */
1949 doputon()
1951 struct obj *otmp;
1953 if (uleft && uright && uamul && ublindf
1954 && uarm && uarmu && uarmc && uarmh && uarms && uarmg && uarmf) {
1955 /* 'P' message doesn't mention armor */
1956 Your("%s%s are full, and you're already wearing an amulet and %s.",
1957 humanoid(youmonst.data) ? "ring-" : "",
1958 makeplural(body_part(FINGER)),
1959 (ublindf->otyp == LENSES) ? "some lenses" : "a blindfold");
1960 return 0;
1962 otmp = getobj(accessories, "put on");
1963 return otmp ? accessory_or_armor_on(otmp) : 0;
1966 /* calculate current armor class */
1967 void
1968 find_ac()
1970 int uac = mons[u.umonnum].ac; /* base armor class for current form */
1972 /* armor class from worn gear */
1973 if (uarm)
1974 uac -= ARM_BONUS(uarm);
1975 if (uarmc)
1976 uac -= ARM_BONUS(uarmc);
1977 if (uarmh)
1978 uac -= ARM_BONUS(uarmh);
1979 if (uarmf)
1980 uac -= ARM_BONUS(uarmf);
1981 if (uarms)
1982 uac -= ARM_BONUS(uarms);
1983 if (uarmg)
1984 uac -= ARM_BONUS(uarmg);
1985 if (uarmu)
1986 uac -= ARM_BONUS(uarmu);
1987 if (uleft && uleft->otyp == RIN_PROTECTION)
1988 uac -= uleft->spe;
1989 if (uright && uright->otyp == RIN_PROTECTION)
1990 uac -= uright->spe;
1992 /* armor class from other sources */
1993 if (HProtection & INTRINSIC)
1994 uac -= u.ublessed;
1995 uac -= u.uspellprot;
1997 /* [The magic binary numbers 127 and -128 should be replaced with the
1998 * mystic decimal numbers 99 and -99 which require no explanation to
1999 * the uninitiated and would cap the width of a status line value at
2000 * one less character.]
2002 if (uac < -128)
2003 uac = -128; /* u.uac is an schar */
2004 else if (uac > 127)
2005 uac = 127; /* for completeness */
2007 if (uac != u.uac) {
2008 u.uac = uac;
2009 context.botl = 1;
2013 void
2014 glibr()
2016 register struct obj *otmp;
2017 int xfl = 0;
2018 boolean leftfall, rightfall, wastwoweap = FALSE;
2019 const char *otherwep = 0, *thiswep, *which, *hand;
2021 leftfall = (uleft && !uleft->cursed
2022 && (!uwep || !welded(uwep) || !bimanual(uwep)));
2023 rightfall = (uright && !uright->cursed && (!welded(uwep)));
2024 if (!uarmg && (leftfall || rightfall) && !nolimbs(youmonst.data)) {
2025 /* changed so cursed rings don't fall off, GAN 10/30/86 */
2026 Your("%s off your %s.",
2027 (leftfall && rightfall) ? "rings slip" : "ring slips",
2028 (leftfall && rightfall) ? makeplural(body_part(FINGER))
2029 : body_part(FINGER));
2030 xfl++;
2031 if (leftfall) {
2032 otmp = uleft;
2033 Ring_off(uleft);
2034 dropx(otmp);
2036 if (rightfall) {
2037 otmp = uright;
2038 Ring_off(uright);
2039 dropx(otmp);
2043 otmp = uswapwep;
2044 if (u.twoweap && otmp) {
2045 /* secondary weapon doesn't need nearly as much handling as
2046 primary; when in two-weapon mode, we know it's one-handed
2047 with something else in the other hand and also that it's
2048 a weapon or weptool rather than something unusual, plus
2049 we don't need to compare its type with the primary */
2050 otherwep = is_sword(otmp) ? c_sword : weapon_descr(otmp);
2051 if (otmp->quan > 1L)
2052 otherwep = makeplural(otherwep);
2053 hand = body_part(HAND);
2054 which = "left ";
2055 Your("%s %s%s from your %s%s.", otherwep, xfl ? "also " : "",
2056 otense(otmp, "slip"), which, hand);
2057 xfl++;
2058 wastwoweap = TRUE;
2059 setuswapwep((struct obj *) 0); /* clears u.twoweap */
2060 if (canletgo(otmp, ""))
2061 dropx(otmp);
2063 otmp = uwep;
2064 if (otmp && !welded(otmp)) {
2065 long savequan = otmp->quan;
2067 /* nice wording if both weapons are the same type */
2068 thiswep = is_sword(otmp) ? c_sword : weapon_descr(otmp);
2069 if (otherwep && strcmp(thiswep, makesingular(otherwep)))
2070 otherwep = 0;
2071 if (otmp->quan > 1L) {
2072 /* most class names for unconventional wielded items
2073 are ok, but if wielding multiple apples or rations
2074 we don't want "your foods slip", so force non-corpse
2075 food to be singular; skipping makeplural() isn't
2076 enough--we need to fool otense() too */
2077 if (!strcmp(thiswep, "food"))
2078 otmp->quan = 1L;
2079 else
2080 thiswep = makeplural(thiswep);
2082 hand = body_part(HAND);
2083 which = "";
2084 if (bimanual(otmp))
2085 hand = makeplural(hand);
2086 else if (wastwoweap)
2087 which = "right "; /* preceding msg was about left */
2088 pline("%s %s%s %s%s from your %s%s.",
2089 !strncmp(thiswep, "corpse", 6) ? "The" : "Your",
2090 otherwep ? "other " : "", thiswep, xfl ? "also " : "",
2091 otense(otmp, "slip"), which, hand);
2092 /* xfl++; */
2093 otmp->quan = savequan;
2094 setuwep((struct obj *) 0);
2095 if (canletgo(otmp, ""))
2096 dropx(otmp);
2100 struct obj *
2101 some_armor(victim)
2102 struct monst *victim;
2104 register struct obj *otmph, *otmp;
2106 otmph = (victim == &youmonst) ? uarmc : which_armor(victim, W_ARMC);
2107 if (!otmph)
2108 otmph = (victim == &youmonst) ? uarm : which_armor(victim, W_ARM);
2109 if (!otmph)
2110 otmph = (victim == &youmonst) ? uarmu : which_armor(victim, W_ARMU);
2112 otmp = (victim == &youmonst) ? uarmh : which_armor(victim, W_ARMH);
2113 if (otmp && (!otmph || !rn2(4)))
2114 otmph = otmp;
2115 otmp = (victim == &youmonst) ? uarmg : which_armor(victim, W_ARMG);
2116 if (otmp && (!otmph || !rn2(4)))
2117 otmph = otmp;
2118 otmp = (victim == &youmonst) ? uarmf : which_armor(victim, W_ARMF);
2119 if (otmp && (!otmph || !rn2(4)))
2120 otmph = otmp;
2121 otmp = (victim == &youmonst) ? uarms : which_armor(victim, W_ARMS);
2122 if (otmp && (!otmph || !rn2(4)))
2123 otmph = otmp;
2124 return otmph;
2127 /* used for praying to check and fix levitation trouble */
2128 struct obj *
2129 stuck_ring(ring, otyp)
2130 struct obj *ring;
2131 int otyp;
2133 if (ring != uleft && ring != uright) {
2134 impossible("stuck_ring: neither left nor right?");
2135 return (struct obj *) 0;
2138 if (ring && ring->otyp == otyp) {
2139 /* reasons ring can't be removed match those checked by select_off();
2140 limbless case has extra checks because ordinarily it's temporary */
2141 if (nolimbs(youmonst.data) && uamul
2142 && uamul->otyp == AMULET_OF_UNCHANGING && uamul->cursed)
2143 return uamul;
2144 if (welded(uwep) && (ring == uright || bimanual(uwep)))
2145 return uwep;
2146 if (uarmg && uarmg->cursed)
2147 return uarmg;
2148 if (ring->cursed)
2149 return ring;
2151 /* either no ring or not right type or nothing prevents its removal */
2152 return (struct obj *) 0;
2155 /* also for praying; find worn item that confers "Unchanging" attribute */
2156 struct obj *
2157 unchanger()
2159 if (uamul && uamul->otyp == AMULET_OF_UNCHANGING)
2160 return uamul;
2161 return 0;
2164 STATIC_PTR
2166 select_off(otmp)
2167 register struct obj *otmp;
2169 struct obj *why;
2170 char buf[BUFSZ];
2172 if (!otmp)
2173 return 0;
2174 *buf = '\0'; /* lint suppression */
2176 /* special ring checks */
2177 if (otmp == uright || otmp == uleft) {
2178 if (nolimbs(youmonst.data)) {
2179 pline_The("ring is stuck.");
2180 return 0;
2182 why = 0; /* the item which prevents ring removal */
2183 if (welded(uwep) && (otmp == uright || bimanual(uwep))) {
2184 Sprintf(buf, "free a weapon %s", body_part(HAND));
2185 why = uwep;
2186 } else if (uarmg && uarmg->cursed) {
2187 Sprintf(buf, "take off your %s", c_gloves);
2188 why = uarmg;
2190 if (why) {
2191 You("cannot %s to remove the ring.", buf);
2192 why->bknown = TRUE;
2193 return 0;
2196 /* special glove checks */
2197 if (otmp == uarmg) {
2198 if (welded(uwep)) {
2199 You("are unable to take off your %s while wielding that %s.",
2200 c_gloves, is_sword(uwep) ? c_sword : c_weapon);
2201 uwep->bknown = TRUE;
2202 return 0;
2203 } else if (Glib) {
2204 You_cant("take off the slippery %s with your slippery %s.",
2205 c_gloves, makeplural(body_part(FINGER)));
2206 return 0;
2209 /* special boot checks */
2210 if (otmp == uarmf) {
2211 if (u.utrap && u.utraptype == TT_BEARTRAP) {
2212 pline_The("bear trap prevents you from pulling your %s out.",
2213 body_part(FOOT));
2214 return 0;
2215 } else if (u.utrap && u.utraptype == TT_INFLOOR) {
2216 You("are stuck in the %s, and cannot pull your %s out.",
2217 surface(u.ux, u.uy), makeplural(body_part(FOOT)));
2218 return 0;
2221 /* special suit and shirt checks */
2222 if (otmp == uarm || otmp == uarmu) {
2223 why = 0; /* the item which prevents disrobing */
2224 if (uarmc && uarmc->cursed) {
2225 Sprintf(buf, "remove your %s", cloak_simple_name(uarmc));
2226 why = uarmc;
2227 } else if (otmp == uarmu && uarm && uarm->cursed) {
2228 Sprintf(buf, "remove your %s", c_suit);
2229 why = uarm;
2230 } else if (welded(uwep) && bimanual(uwep)) {
2231 Sprintf(buf, "release your %s",
2232 is_sword(uwep) ? c_sword : (uwep->otyp == BATTLE_AXE)
2233 ? c_axe
2234 : c_weapon);
2235 why = uwep;
2237 if (why) {
2238 You("cannot %s to take off %s.", buf, the(xname(otmp)));
2239 why->bknown = TRUE;
2240 return 0;
2243 /* basic curse check */
2244 if (otmp == uquiver || (otmp == uswapwep && !u.twoweap)) {
2245 ; /* some items can be removed even when cursed */
2246 } else {
2247 /* otherwise, this is fundamental */
2248 if (cursed(otmp))
2249 return 0;
2252 if (otmp == uarm)
2253 context.takeoff.mask |= WORN_ARMOR;
2254 else if (otmp == uarmc)
2255 context.takeoff.mask |= WORN_CLOAK;
2256 else if (otmp == uarmf)
2257 context.takeoff.mask |= WORN_BOOTS;
2258 else if (otmp == uarmg)
2259 context.takeoff.mask |= WORN_GLOVES;
2260 else if (otmp == uarmh)
2261 context.takeoff.mask |= WORN_HELMET;
2262 else if (otmp == uarms)
2263 context.takeoff.mask |= WORN_SHIELD;
2264 else if (otmp == uarmu)
2265 context.takeoff.mask |= WORN_SHIRT;
2266 else if (otmp == uleft)
2267 context.takeoff.mask |= LEFT_RING;
2268 else if (otmp == uright)
2269 context.takeoff.mask |= RIGHT_RING;
2270 else if (otmp == uamul)
2271 context.takeoff.mask |= WORN_AMUL;
2272 else if (otmp == ublindf)
2273 context.takeoff.mask |= WORN_BLINDF;
2274 else if (otmp == uwep)
2275 context.takeoff.mask |= W_WEP;
2276 else if (otmp == uswapwep)
2277 context.takeoff.mask |= W_SWAPWEP;
2278 else if (otmp == uquiver)
2279 context.takeoff.mask |= W_QUIVER;
2281 else
2282 impossible("select_off: %s???", doname(otmp));
2284 return 0;
2287 STATIC_OVL struct obj *
2288 do_takeoff()
2290 struct obj *otmp = (struct obj *) 0;
2291 struct takeoff_info *doff = &context.takeoff;
2293 if (doff->what == W_WEP) {
2294 if (!cursed(uwep)) {
2295 setuwep((struct obj *) 0);
2296 You("are empty %s.", body_part(HANDED));
2297 u.twoweap = FALSE;
2299 } else if (doff->what == W_SWAPWEP) {
2300 setuswapwep((struct obj *) 0);
2301 You("no longer have a second weapon readied.");
2302 u.twoweap = FALSE;
2303 } else if (doff->what == W_QUIVER) {
2304 setuqwep((struct obj *) 0);
2305 You("no longer have ammunition readied.");
2306 } else if (doff->what == WORN_ARMOR) {
2307 otmp = uarm;
2308 if (!cursed(otmp))
2309 (void) Armor_off();
2310 } else if (doff->what == WORN_CLOAK) {
2311 otmp = uarmc;
2312 if (!cursed(otmp))
2313 (void) Cloak_off();
2314 } else if (doff->what == WORN_BOOTS) {
2315 otmp = uarmf;
2316 if (!cursed(otmp))
2317 (void) Boots_off();
2318 } else if (doff->what == WORN_GLOVES) {
2319 otmp = uarmg;
2320 if (!cursed(otmp))
2321 (void) Gloves_off();
2322 } else if (doff->what == WORN_HELMET) {
2323 otmp = uarmh;
2324 if (!cursed(otmp))
2325 (void) Helmet_off();
2326 } else if (doff->what == WORN_SHIELD) {
2327 otmp = uarms;
2328 if (!cursed(otmp))
2329 (void) Shield_off();
2330 } else if (doff->what == WORN_SHIRT) {
2331 otmp = uarmu;
2332 if (!cursed(otmp))
2333 (void) Shirt_off();
2334 } else if (doff->what == WORN_AMUL) {
2335 otmp = uamul;
2336 if (!cursed(otmp))
2337 Amulet_off();
2338 } else if (doff->what == LEFT_RING) {
2339 otmp = uleft;
2340 if (!cursed(otmp))
2341 Ring_off(uleft);
2342 } else if (doff->what == RIGHT_RING) {
2343 otmp = uright;
2344 if (!cursed(otmp))
2345 Ring_off(uright);
2346 } else if (doff->what == WORN_BLINDF) {
2347 if (!cursed(ublindf))
2348 Blindf_off(ublindf);
2349 } else {
2350 impossible("do_takeoff: taking off %lx", doff->what);
2353 return otmp;
2356 /* occupation callback for 'A' */
2357 STATIC_PTR
2359 take_off(VOID_ARGS)
2361 register int i;
2362 register struct obj *otmp;
2363 struct takeoff_info *doff = &context.takeoff;
2365 if (doff->what) {
2366 if (doff->delay > 0) {
2367 doff->delay--;
2368 return 1; /* still busy */
2369 } else {
2370 if ((otmp = do_takeoff()))
2371 off_msg(otmp);
2373 doff->mask &= ~doff->what;
2374 doff->what = 0L;
2377 for (i = 0; takeoff_order[i]; i++)
2378 if (doff->mask & takeoff_order[i]) {
2379 doff->what = takeoff_order[i];
2380 break;
2383 otmp = (struct obj *) 0;
2384 doff->delay = 0;
2386 if (doff->what == 0L) {
2387 You("finish %s.", doff->disrobing);
2388 return 0;
2389 } else if (doff->what == W_WEP) {
2390 doff->delay = 1;
2391 } else if (doff->what == W_SWAPWEP) {
2392 doff->delay = 1;
2393 } else if (doff->what == W_QUIVER) {
2394 doff->delay = 1;
2395 } else if (doff->what == WORN_ARMOR) {
2396 otmp = uarm;
2397 /* If a cloak is being worn, add the time to take it off and put
2398 * it back on again. Kludge alert! since that time is 0 for all
2399 * known cloaks, add 1 so that it actually matters...
2401 if (uarmc)
2402 doff->delay += 2 * objects[uarmc->otyp].oc_delay + 1;
2403 } else if (doff->what == WORN_CLOAK) {
2404 otmp = uarmc;
2405 } else if (doff->what == WORN_BOOTS) {
2406 otmp = uarmf;
2407 } else if (doff->what == WORN_GLOVES) {
2408 otmp = uarmg;
2409 } else if (doff->what == WORN_HELMET) {
2410 otmp = uarmh;
2411 } else if (doff->what == WORN_SHIELD) {
2412 otmp = uarms;
2413 } else if (doff->what == WORN_SHIRT) {
2414 otmp = uarmu;
2415 /* add the time to take off and put back on armor and/or cloak */
2416 if (uarm)
2417 doff->delay += 2 * objects[uarm->otyp].oc_delay;
2418 if (uarmc)
2419 doff->delay += 2 * objects[uarmc->otyp].oc_delay + 1;
2420 } else if (doff->what == WORN_AMUL) {
2421 doff->delay = 1;
2422 } else if (doff->what == LEFT_RING) {
2423 doff->delay = 1;
2424 } else if (doff->what == RIGHT_RING) {
2425 doff->delay = 1;
2426 } else if (doff->what == WORN_BLINDF) {
2427 doff->delay = 2;
2428 } else {
2429 impossible("take_off: taking off %lx", doff->what);
2430 return 0; /* force done */
2433 if (otmp)
2434 doff->delay += objects[otmp->otyp].oc_delay;
2436 /* Since setting the occupation now starts the counter next move, that
2437 * would always produce a delay 1 too big per item unless we subtract
2438 * 1 here to account for it.
2440 if (doff->delay > 0)
2441 doff->delay--;
2443 set_occupation(take_off, doff->disrobing, 0);
2444 return 1; /* get busy */
2447 /* clear saved context to avoid inappropriate resumption of interrupted 'A' */
2448 void
2449 reset_remarm()
2451 context.takeoff.what = context.takeoff.mask = 0L;
2452 context.takeoff.disrobing[0] = '\0';
2455 /* the 'A' command -- remove multiple worn items */
2457 doddoremarm()
2459 int result = 0;
2461 if (context.takeoff.what || context.takeoff.mask) {
2462 You("continue %s.", context.takeoff.disrobing);
2463 set_occupation(take_off, context.takeoff.disrobing, 0);
2464 return 0;
2465 } else if (!uwep && !uswapwep && !uquiver && !uamul && !ublindf && !uleft
2466 && !uright && !wearing_armor()) {
2467 You("are not wearing anything.");
2468 return 0;
2471 add_valid_menu_class(0); /* reset */
2472 if (flags.menu_style != MENU_TRADITIONAL
2473 || (result = ggetobj("take off", select_off, 0, FALSE,
2474 (unsigned *) 0)) < -1)
2475 result = menu_remarm(result);
2477 if (context.takeoff.mask) {
2478 /* default activity for armor and/or accessories,
2479 possibly combined with weapons */
2480 (void) strncpy(context.takeoff.disrobing, "disrobing", CONTEXTVERBSZ);
2481 /* specific activity when handling weapons only */
2482 if (!(context.takeoff.mask & ~W_WEAPON))
2483 (void) strncpy(context.takeoff.disrobing, "disarming",
2484 CONTEXTVERBSZ);
2485 (void) take_off();
2487 /* The time to perform the command is already completely accounted for
2488 * in take_off(); if we return 1, that would add an extra turn to each
2489 * disrobe.
2491 return 0;
2494 STATIC_OVL int
2495 menu_remarm(retry)
2496 int retry;
2498 int n, i = 0;
2499 menu_item *pick_list;
2500 boolean all_worn_categories = TRUE;
2502 if (retry) {
2503 all_worn_categories = (retry == -2);
2504 } else if (flags.menu_style == MENU_FULL) {
2505 all_worn_categories = FALSE;
2506 n = query_category("What type of things do you want to take off?",
2507 invent, WORN_TYPES | ALL_TYPES, &pick_list,
2508 PICK_ANY);
2509 if (!n)
2510 return 0;
2511 for (i = 0; i < n; i++) {
2512 if (pick_list[i].item.a_int == ALL_TYPES_SELECTED)
2513 all_worn_categories = TRUE;
2514 else
2515 add_valid_menu_class(pick_list[i].item.a_int);
2517 free((genericptr_t) pick_list);
2518 } else if (flags.menu_style == MENU_COMBINATION) {
2519 all_worn_categories = FALSE;
2520 if (ggetobj("take off", select_off, 0, TRUE, (unsigned *) 0) == -2)
2521 all_worn_categories = TRUE;
2524 n = query_objlist("What do you want to take off?", &invent,
2525 (SIGNAL_NOMENU | USE_INVLET | INVORDER_SORT),
2526 &pick_list, PICK_ANY,
2527 all_worn_categories ? is_worn : is_worn_by_type);
2528 if (n > 0) {
2529 for (i = 0; i < n; i++)
2530 (void) select_off(pick_list[i].item.a_obj);
2531 free((genericptr_t) pick_list);
2532 } else if (n < 0 && flags.menu_style != MENU_COMBINATION) {
2533 There("is nothing else you can remove or unwield.");
2535 return 0;
2538 /* hit by destroy armor scroll/black dragon breath/monster spell */
2540 destroy_arm(atmp)
2541 register struct obj *atmp;
2543 register struct obj *otmp;
2544 #define DESTROY_ARM(o) \
2545 ((otmp = (o)) != 0 && (!atmp || atmp == otmp) \
2546 && (!obj_resists(otmp, 0, 90)) \
2547 ? (otmp->in_use = TRUE) \
2548 : FALSE)
2550 if (DESTROY_ARM(uarmc)) {
2551 if (donning(otmp))
2552 cancel_don();
2553 Your("%s crumbles and turns to dust!", cloak_simple_name(uarmc));
2554 (void) Cloak_off();
2555 useup(otmp);
2556 } else if (DESTROY_ARM(uarm)) {
2557 if (donning(otmp))
2558 cancel_don();
2559 Your("armor turns to dust and falls to the %s!", surface(u.ux, u.uy));
2560 (void) Armor_gone();
2561 useup(otmp);
2562 } else if (DESTROY_ARM(uarmu)) {
2563 if (donning(otmp))
2564 cancel_don();
2565 Your("shirt crumbles into tiny threads and falls apart!");
2566 (void) Shirt_off();
2567 useup(otmp);
2568 } else if (DESTROY_ARM(uarmh)) {
2569 if (donning(otmp))
2570 cancel_don();
2571 Your("%s turns to dust and is blown away!", helm_simple_name(uarmh));
2572 (void) Helmet_off();
2573 useup(otmp);
2574 } else if (DESTROY_ARM(uarmg)) {
2575 if (donning(otmp))
2576 cancel_don();
2577 Your("gloves vanish!");
2578 (void) Gloves_off();
2579 useup(otmp);
2580 selftouch("You");
2581 } else if (DESTROY_ARM(uarmf)) {
2582 if (donning(otmp))
2583 cancel_don();
2584 Your("boots disintegrate!");
2585 (void) Boots_off();
2586 useup(otmp);
2587 } else if (DESTROY_ARM(uarms)) {
2588 if (donning(otmp))
2589 cancel_don();
2590 Your("shield crumbles away!");
2591 (void) Shield_off();
2592 useup(otmp);
2593 } else {
2594 return 0; /* could not destroy anything */
2597 #undef DESTROY_ARM
2598 stop_occupation();
2599 return 1;
2602 void
2603 adj_abon(otmp, delta)
2604 register struct obj *otmp;
2605 register schar delta;
2607 if (uarmg && uarmg == otmp && otmp->otyp == GAUNTLETS_OF_DEXTERITY) {
2608 if (delta) {
2609 makeknown(uarmg->otyp);
2610 ABON(A_DEX) += (delta);
2612 context.botl = 1;
2614 if (uarmh && uarmh == otmp && otmp->otyp == HELM_OF_BRILLIANCE) {
2615 if (delta) {
2616 makeknown(uarmh->otyp);
2617 ABON(A_INT) += (delta);
2618 ABON(A_WIS) += (delta);
2620 context.botl = 1;
2624 /* decide whether a worn item is covered up by some other worn item,
2625 used for dipping into liquid and applying grease;
2626 some criteria are different than select_off()'s */
2627 boolean
2628 inaccessible_equipment(obj, verb, only_if_known_cursed)
2629 struct obj *obj;
2630 const char *verb; /* "dip" or "grease", or null to avoid messages */
2631 boolean only_if_known_cursed; /* ignore covering unless known to be cursed */
2633 static NEARDATA const char need_to_take_off_outer_armor[] =
2634 "need to take off %s to %s %s.";
2635 char buf[BUFSZ];
2636 boolean anycovering = !only_if_known_cursed; /* more comprehensible... */
2637 #define BLOCKSACCESS(x) (anycovering || ((x)->cursed && (x)->bknown))
2639 if (!obj || !obj->owornmask)
2640 return FALSE; /* not inaccessible */
2642 /* check for suit covered by cloak */
2643 if (obj == uarm && uarmc && BLOCKSACCESS(uarmc)) {
2644 if (verb) {
2645 Strcpy(buf, yname(uarmc));
2646 You(need_to_take_off_outer_armor, buf, verb, yname(obj));
2648 return TRUE;
2650 /* check for shirt covered by suit and/or cloak */
2651 if (obj == uarmu
2652 && ((uarm && BLOCKSACCESS(uarm)) || (uarmc && BLOCKSACCESS(uarmc)))) {
2653 if (verb) {
2654 char cloaktmp[QBUFSZ], suittmp[QBUFSZ];
2655 /* if sameprefix, use yname and xname to get "your cloak and suit"
2656 or "Manlobbi's cloak and suit"; otherwise, use yname and yname
2657 to get "your cloak and Manlobbi's suit" or vice versa */
2658 boolean sameprefix = (uarm && uarmc
2659 && !strcmp(shk_your(cloaktmp, uarmc),
2660 shk_your(suittmp, uarm)));
2662 *buf = '\0';
2663 if (uarmc)
2664 Strcat(buf, yname(uarmc));
2665 if (uarm && uarmc)
2666 Strcat(buf, " and ");
2667 if (uarm)
2668 Strcat(buf, sameprefix ? xname(uarm) : yname(uarm));
2669 You(need_to_take_off_outer_armor, buf, verb, yname(obj));
2671 return TRUE;
2673 /* check for ring covered by gloves */
2674 if ((obj == uleft || obj == uright) && uarmg && BLOCKSACCESS(uarmg)) {
2675 if (verb) {
2676 Strcpy(buf, yname(uarmg));
2677 You(need_to_take_off_outer_armor, buf, verb, yname(obj));
2679 return TRUE;
2681 /* item is not inaccessible */
2682 return FALSE;
2685 /*do_wear.c*/