NHDT->ANH, nethack->anethack, nhdat->anhdat
[aNetHack.git] / src / do_wear.c
blobbbba0a176daaa7e373470eb7f80e044f7aa365ec
1 /* aNetHack 0.0.1 do_wear.c $ANH-Date: 1455667557 2016/02/17 00:05:57 $ $ANH-Branch: master $:$ANH-Revision: 1.90 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* aNetHack 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 if (!otmp) {
1488 impossible("cursed without otmp");
1489 return 0;
1491 /* Curses, like chickens, come home to roost. */
1492 if ((otmp == uwep) ? welded(otmp) : (int) otmp->cursed) {
1493 boolean use_plural = (is_boots(otmp) || is_gloves(otmp)
1494 || otmp->otyp == LENSES || otmp->quan > 1L);
1496 You("can't. %s cursed.", use_plural ? "They are" : "It is");
1497 otmp->bknown = TRUE;
1498 return 1;
1500 return 0;
1504 armoroff(otmp)
1505 register struct obj *otmp;
1507 register int delay = -objects[otmp->otyp].oc_delay;
1509 if (cursed(otmp))
1510 return 0;
1511 if (delay) {
1512 nomul(delay);
1513 multi_reason = "disrobing";
1514 if (is_helmet(otmp)) {
1515 /* ick... */
1516 nomovemsg = !strcmp(helm_simple_name(otmp), "hat")
1517 ? "You finish taking off your hat."
1518 : "You finish taking off your helmet.";
1519 afternmv = Helmet_off;
1520 } else if (is_gloves(otmp)) {
1521 nomovemsg = "You finish taking off your gloves.";
1522 afternmv = Gloves_off;
1523 } else if (is_boots(otmp)) {
1524 nomovemsg = "You finish taking off your boots.";
1525 afternmv = Boots_off;
1526 } else {
1527 nomovemsg = "You finish taking off your suit.";
1528 afternmv = Armor_off;
1530 } else {
1531 /* Be warned! We want off_msg after removing the item to
1532 * avoid "You were wearing ____ (being worn)." However, an
1533 * item which grants fire resistance might cause some trouble
1534 * if removed in Hell and lifesaving puts it back on; in this
1535 * case the message will be printed at the wrong time (after
1536 * the messages saying you died and were lifesaved). Luckily,
1537 * no cloak, shield, or fast-removable armor grants fire
1538 * resistance, so we can safely do the off_msg afterwards.
1539 * Rings do grant fire resistance, but for rings we want the
1540 * off_msg before removal anyway so there's no problem. Take
1541 * care in adding armors granting fire resistance; this code
1542 * might need modification.
1543 * 3.2 (actually 3.1 even): that comment is obsolete since
1544 * fire resistance is not required for Gehennom so setworn()
1545 * doesn't force the resistance granting item to be re-worn
1546 * after being lifesaved anymore.
1548 if (is_cloak(otmp))
1549 (void) Cloak_off();
1550 else if (is_shield(otmp))
1551 (void) Shield_off();
1552 else
1553 setworn((struct obj *) 0, otmp->owornmask & W_ARMOR);
1554 off_msg(otmp);
1556 context.takeoff.mask = context.takeoff.what = 0L;
1557 return 1;
1560 STATIC_OVL void
1561 already_wearing(cc)
1562 const char *cc;
1564 You("are already wearing %s%c", cc, (cc == c_that_) ? '!' : '.');
1567 STATIC_OVL void
1568 already_wearing2(cc1, cc2)
1569 const char *cc1, *cc2;
1571 You_cant("wear %s because you're wearing %s there already.", cc1, cc2);
1575 * canwearobj checks to see whether the player can wear a piece of armor
1577 * inputs: otmp (the piece of armor)
1578 * noisy (if TRUE give error messages, otherwise be quiet about it)
1579 * output: mask (otmp's armor type)
1582 canwearobj(otmp, mask, noisy)
1583 struct obj *otmp;
1584 long *mask;
1585 boolean noisy;
1587 int err = 0;
1588 const char *which;
1590 which = is_cloak(otmp)
1591 ? c_cloak
1592 : is_shirt(otmp)
1593 ? c_shirt
1594 : is_suit(otmp)
1595 ? c_suit
1596 : 0;
1597 if (which && cantweararm(youmonst.data)
1598 /* same exception for cloaks as used in m_dowear() */
1599 && (which != c_cloak || youmonst.data->msize != MZ_SMALL)
1600 && (racial_exception(&youmonst, otmp) < 1)) {
1601 if (noisy)
1602 pline_The("%s will not fit on your body.", which);
1603 return 0;
1604 } else if (otmp->owornmask & W_ARMOR) {
1605 if (noisy)
1606 already_wearing(c_that_);
1607 return 0;
1610 if (welded(uwep) && bimanual(uwep) && (is_suit(otmp) || is_shirt(otmp))) {
1611 if (noisy)
1612 You("cannot do that while holding your %s.",
1613 is_sword(uwep) ? c_sword : c_weapon);
1614 return 0;
1617 if (is_helmet(otmp)) {
1618 if (uarmh) {
1619 if (noisy)
1620 already_wearing(an(helm_simple_name(uarmh)));
1621 err++;
1622 } else if (Upolyd && has_horns(youmonst.data) && !is_flimsy(otmp)) {
1623 /* (flimsy exception matches polyself handling) */
1624 if (noisy)
1625 pline_The("%s won't fit over your horn%s.",
1626 helm_simple_name(otmp),
1627 plur(num_horns(youmonst.data)));
1628 err++;
1629 } else
1630 *mask = W_ARMH;
1631 } else if (is_shield(otmp)) {
1632 if (uarms) {
1633 if (noisy)
1634 already_wearing(an(c_shield));
1635 err++;
1636 } else if (uwep && bimanual(uwep)) {
1637 if (noisy)
1638 You("cannot wear a shield while wielding a two-handed %s.",
1639 is_sword(uwep) ? c_sword : (uwep->otyp == BATTLE_AXE)
1640 ? c_axe
1641 : c_weapon);
1642 err++;
1643 } else if (u.twoweap) {
1644 if (noisy)
1645 You("cannot wear a shield while wielding two weapons.");
1646 err++;
1647 } else
1648 *mask = W_ARMS;
1649 } else if (is_boots(otmp)) {
1650 if (uarmf) {
1651 if (noisy)
1652 already_wearing(c_boots);
1653 err++;
1654 } else if (Upolyd && slithy(youmonst.data)) {
1655 if (noisy)
1656 You("have no feet..."); /* not body_part(FOOT) */
1657 err++;
1658 } else if (Upolyd && youmonst.data->mlet == S_CENTAUR) {
1659 /* break_armor() pushes boots off for centaurs,
1660 so don't let dowear() put them back on... */
1661 if (noisy)
1662 pline("You have too many hooves to wear %s.",
1663 c_boots); /* makeplural(body_part(FOOT)) yields
1664 "rear hooves" which sounds odd */
1665 err++;
1666 } else if (u.utrap
1667 && (u.utraptype == TT_BEARTRAP || u.utraptype == TT_INFLOOR
1668 || u.utraptype == TT_LAVA
1669 || u.utraptype == TT_BURIEDBALL)) {
1670 if (u.utraptype == TT_BEARTRAP) {
1671 if (noisy)
1672 Your("%s is trapped!", body_part(FOOT));
1673 } else if (u.utraptype == TT_INFLOOR || u.utraptype == TT_LAVA) {
1674 if (noisy)
1675 Your("%s are stuck in the %s!",
1676 makeplural(body_part(FOOT)), surface(u.ux, u.uy));
1677 } else { /*TT_BURIEDBALL*/
1678 if (noisy)
1679 Your("%s is attached to the buried ball!",
1680 body_part(LEG));
1682 err++;
1683 } else
1684 *mask = W_ARMF;
1685 } else if (is_gloves(otmp)) {
1686 if (uarmg) {
1687 if (noisy)
1688 already_wearing(c_gloves);
1689 err++;
1690 } else if (welded(uwep)) {
1691 if (noisy)
1692 You("cannot wear gloves over your %s.",
1693 is_sword(uwep) ? c_sword : c_weapon);
1694 err++;
1695 } else
1696 *mask = W_ARMG;
1697 } else if (is_shirt(otmp)) {
1698 if (uarm || uarmc || uarmu) {
1699 if (uarmu) {
1700 if (noisy)
1701 already_wearing(an(c_shirt));
1702 } else {
1703 if (noisy)
1704 You_cant("wear that over your %s.",
1705 (uarm && !uarmc) ? c_armor
1706 : cloak_simple_name(uarmc));
1708 err++;
1709 } else
1710 *mask = W_ARMU;
1711 } else if (is_cloak(otmp)) {
1712 if (uarmc) {
1713 if (noisy)
1714 already_wearing(an(cloak_simple_name(uarmc)));
1715 err++;
1716 } else
1717 *mask = W_ARMC;
1718 } else if (is_suit(otmp)) {
1719 if (uarmc) {
1720 if (noisy)
1721 You("cannot wear armor over a %s.", cloak_simple_name(uarmc));
1722 err++;
1723 } else if (uarm) {
1724 if (noisy)
1725 already_wearing("some armor");
1726 err++;
1727 } else
1728 *mask = W_ARM;
1729 } else {
1730 /* getobj can't do this after setting its allow_all flag; that
1731 happens if you have armor for slots that are covered up or
1732 extra armor for slots that are filled */
1733 if (noisy)
1734 silly_thing("wear", otmp);
1735 err++;
1737 /* Unnecessary since now only weapons and special items like pick-axes get
1738 * welded to your hand, not armor
1739 if (welded(otmp)) {
1740 if (!err++) {
1741 if (noisy) weldmsg(otmp);
1745 return !err;
1748 STATIC_OVL int
1749 accessory_or_armor_on(obj)
1750 struct obj *obj;
1752 long mask = 0L;
1753 boolean armor, ring, eyewear;
1755 if (obj->owornmask & (W_ACCESSORY | W_ARMOR)) {
1756 already_wearing(c_that_);
1757 return 0;
1759 armor = (obj->oclass == ARMOR_CLASS);
1760 ring = (obj->oclass == RING_CLASS || obj->otyp == MEAT_RING);
1761 eyewear = (obj->otyp == BLINDFOLD || obj->otyp == TOWEL
1762 || obj->otyp == LENSES);
1763 /* checks which are performed prior to actually touching the item */
1764 if (armor) {
1765 if (!canwearobj(obj, &mask, TRUE))
1766 return 0;
1768 if (obj->otyp == HELM_OF_OPPOSITE_ALIGNMENT
1769 && qstart_level.dnum == u.uz.dnum) { /* in quest */
1770 if (u.ualignbase[A_CURRENT] == u.ualignbase[A_ORIGINAL])
1771 You("narrowly avoid losing all chance at your goal.");
1772 else /* converted */
1773 You("are suddenly overcome with shame and change your mind.");
1774 u.ublessed = 0; /* lose your god's protection */
1775 makeknown(obj->otyp);
1776 context.botl = 1; /*for AC after zeroing u.ublessed */
1777 return 1;
1779 } else {
1780 /* accessory */
1781 if (ring) {
1782 char answer, qbuf[QBUFSZ];
1783 int res = 0;
1785 if (nolimbs(youmonst.data)) {
1786 You("cannot make the ring stick to your body.");
1787 return 0;
1789 if (uleft && uright) {
1790 There("are no more %s%s to fill.",
1791 humanoid(youmonst.data) ? "ring-" : "",
1792 makeplural(body_part(FINGER)));
1793 return 0;
1795 if (uleft) {
1796 mask = RIGHT_RING;
1797 } else if (uright) {
1798 mask = LEFT_RING;
1799 } else {
1800 do {
1801 Sprintf(qbuf, "Which %s%s, Right or Left?",
1802 humanoid(youmonst.data) ? "ring-" : "",
1803 body_part(FINGER));
1804 answer = yn_function(qbuf, "rl", '\0');
1805 switch (answer) {
1806 case '\0':
1807 return 0;
1808 case 'l':
1809 case 'L':
1810 mask = LEFT_RING;
1811 break;
1812 case 'r':
1813 case 'R':
1814 mask = RIGHT_RING;
1815 break;
1817 } while (!mask);
1819 if (uarmg && uarmg->cursed) {
1820 res = !uarmg->bknown;
1821 uarmg->bknown = 1;
1822 You("cannot remove your gloves to put on the ring.");
1823 return res; /* uses move iff we learned gloves are cursed */
1825 if (uwep) {
1826 res = !uwep->bknown; /* check this before calling welded() */
1827 if ((mask == RIGHT_RING || bimanual(uwep)) && welded(uwep)) {
1828 const char *hand = body_part(HAND);
1830 /* welded will set bknown */
1831 if (bimanual(uwep))
1832 hand = makeplural(hand);
1833 You("cannot free your weapon %s to put on the ring.",
1834 hand);
1835 return res; /* uses move iff we learned weapon is cursed */
1838 } else if (obj->oclass == AMULET_CLASS) {
1839 if (uamul) {
1840 already_wearing("an amulet");
1841 return 0;
1843 } else if (eyewear) {
1844 if (ublindf) {
1845 if (ublindf->otyp == TOWEL)
1846 Your("%s is already covered by a towel.",
1847 body_part(FACE));
1848 else if (ublindf->otyp == BLINDFOLD) {
1849 if (obj->otyp == LENSES)
1850 already_wearing2("lenses", "a blindfold");
1851 else
1852 already_wearing("a blindfold");
1853 } else if (ublindf->otyp == LENSES) {
1854 if (obj->otyp == BLINDFOLD)
1855 already_wearing2("a blindfold", "some lenses");
1856 else
1857 already_wearing("some lenses");
1858 } else {
1859 already_wearing(something); /* ??? */
1861 return 0;
1863 } else {
1864 /* neither armor nor accessory */
1865 You_cant("wear that!");
1866 return 0;
1870 if (!retouch_object(&obj, FALSE))
1871 return 1; /* costs a turn even though it didn't get worn */
1873 if (armor) {
1874 int delay;
1876 obj->known = 1; /* since AC is shown on the status line */
1877 /* if the armor is wielded, release it for wearing */
1878 if (obj->owornmask & W_WEAPON)
1879 remove_worn_item(obj, FALSE);
1880 setworn(obj, mask);
1881 delay = -objects[obj->otyp].oc_delay;
1882 if (delay) {
1883 nomul(delay);
1884 multi_reason = "dressing up";
1885 if (is_boots(obj))
1886 afternmv = Boots_on;
1887 if (is_helmet(obj))
1888 afternmv = Helmet_on;
1889 if (is_gloves(obj))
1890 afternmv = Gloves_on;
1891 if (obj == uarm)
1892 afternmv = Armor_on;
1893 nomovemsg = "You finish your dressing maneuver.";
1894 } else {
1895 if (is_cloak(obj))
1896 (void) Cloak_on();
1897 if (is_shield(obj))
1898 (void) Shield_on();
1899 if (is_shirt(obj))
1900 (void) Shirt_on();
1901 on_msg(obj);
1903 context.takeoff.mask = context.takeoff.what = 0L;
1904 } else { /* not armor */
1905 boolean give_feedback = FALSE;
1907 /* [releasing wielded accessory handled in Xxx_on()] */
1908 if (ring) {
1909 setworn(obj, mask);
1910 Ring_on(obj);
1911 give_feedback = TRUE;
1912 } else if (obj->oclass == AMULET_CLASS) {
1913 setworn(obj, W_AMUL);
1914 Amulet_on();
1915 /* no feedback here if amulet of change got used up */
1916 give_feedback = (uamul != 0);
1917 } else if (eyewear) {
1918 /* setworn() handled by Blindf_on() */
1919 Blindf_on(obj);
1920 /* message handled by Blindf_on(); leave give_feedback False */
1922 /* feedback for ring or for amulet other than 'change' */
1923 if (give_feedback && is_worn(obj))
1924 prinv((char *) 0, obj, 0L);
1926 return 1;
1929 /* the 'W' command */
1931 dowear()
1933 struct obj *otmp;
1935 /* cantweararm() checks for suits of armor, not what we want here;
1936 verysmall() or nohands() checks for shields, gloves, etc... */
1937 if ((verysmall(youmonst.data) || nohands(youmonst.data))) {
1938 pline("Don't even bother.");
1939 return 0;
1941 if (uarm && uarmu && uarmc && uarmh && uarms && uarmg && uarmf
1942 && uleft && uright && uamul && ublindf) {
1943 /* 'W' message doesn't mention accessories */
1944 You("are already wearing a full complement of armor.");
1945 return 0;
1947 otmp = getobj(clothes, "wear");
1948 return otmp ? accessory_or_armor_on(otmp) : 0;
1951 /* the 'P' command */
1953 doputon()
1955 struct obj *otmp;
1957 if (uleft && uright && uamul && ublindf
1958 && uarm && uarmu && uarmc && uarmh && uarms && uarmg && uarmf) {
1959 /* 'P' message doesn't mention armor */
1960 Your("%s%s are full, and you're already wearing an amulet and %s.",
1961 humanoid(youmonst.data) ? "ring-" : "",
1962 makeplural(body_part(FINGER)),
1963 (ublindf->otyp == LENSES) ? "some lenses" : "a blindfold");
1964 return 0;
1966 otmp = getobj(accessories, "put on");
1967 return otmp ? accessory_or_armor_on(otmp) : 0;
1970 /* calculate current armor class */
1971 void
1972 find_ac()
1974 int uac = mons[u.umonnum].ac; /* base armor class for current form */
1976 /* armor class from worn gear */
1977 if (uarm)
1978 uac -= ARM_BONUS(uarm);
1979 if (uarmc)
1980 uac -= ARM_BONUS(uarmc);
1981 if (uarmh)
1982 uac -= ARM_BONUS(uarmh);
1983 if (uarmf)
1984 uac -= ARM_BONUS(uarmf);
1985 if (uarms)
1986 uac -= ARM_BONUS(uarms);
1987 if (uarmg)
1988 uac -= ARM_BONUS(uarmg);
1989 if (uarmu)
1990 uac -= ARM_BONUS(uarmu);
1991 if (uleft && uleft->otyp == RIN_PROTECTION)
1992 uac -= uleft->spe;
1993 if (uright && uright->otyp == RIN_PROTECTION)
1994 uac -= uright->spe;
1996 /* armor class from other sources */
1997 if (HProtection & INTRINSIC)
1998 uac -= u.ublessed;
1999 uac -= u.uspellprot;
2001 /* [The magic binary numbers 127 and -128 should be replaced with the
2002 * mystic decimal numbers 99 and -99 which require no explanation to
2003 * the uninitiated and would cap the width of a status line value at
2004 * one less character.]
2006 if (uac < -128)
2007 uac = -128; /* u.uac is an schar */
2008 else if (uac > 127)
2009 uac = 127; /* for completeness */
2011 if (uac != u.uac) {
2012 u.uac = uac;
2013 context.botl = 1;
2017 void
2018 glibr()
2020 register struct obj *otmp;
2021 int xfl = 0;
2022 boolean leftfall, rightfall, wastwoweap = FALSE;
2023 const char *otherwep = 0, *thiswep, *which, *hand;
2025 leftfall = (uleft && !uleft->cursed
2026 && (!uwep || !welded(uwep) || !bimanual(uwep)));
2027 rightfall = (uright && !uright->cursed && (!welded(uwep)));
2028 if (!uarmg && (leftfall || rightfall) && !nolimbs(youmonst.data)) {
2029 /* changed so cursed rings don't fall off, GAN 10/30/86 */
2030 Your("%s off your %s.",
2031 (leftfall && rightfall) ? "rings slip" : "ring slips",
2032 (leftfall && rightfall) ? makeplural(body_part(FINGER))
2033 : body_part(FINGER));
2034 xfl++;
2035 if (leftfall) {
2036 otmp = uleft;
2037 Ring_off(uleft);
2038 dropx(otmp);
2040 if (rightfall) {
2041 otmp = uright;
2042 Ring_off(uright);
2043 dropx(otmp);
2047 otmp = uswapwep;
2048 if (u.twoweap && otmp) {
2049 /* secondary weapon doesn't need nearly as much handling as
2050 primary; when in two-weapon mode, we know it's one-handed
2051 with something else in the other hand and also that it's
2052 a weapon or weptool rather than something unusual, plus
2053 we don't need to compare its type with the primary */
2054 otherwep = is_sword(otmp) ? c_sword : weapon_descr(otmp);
2055 if (otmp->quan > 1L)
2056 otherwep = makeplural(otherwep);
2057 hand = body_part(HAND);
2058 which = "left ";
2059 Your("%s %s%s from your %s%s.", otherwep, xfl ? "also " : "",
2060 otense(otmp, "slip"), which, hand);
2061 xfl++;
2062 wastwoweap = TRUE;
2063 setuswapwep((struct obj *) 0); /* clears u.twoweap */
2064 if (canletgo(otmp, ""))
2065 dropx(otmp);
2067 otmp = uwep;
2068 if (otmp && !welded(otmp)) {
2069 long savequan = otmp->quan;
2071 /* nice wording if both weapons are the same type */
2072 thiswep = is_sword(otmp) ? c_sword : weapon_descr(otmp);
2073 if (otherwep && strcmp(thiswep, makesingular(otherwep)))
2074 otherwep = 0;
2075 if (otmp->quan > 1L) {
2076 /* most class names for unconventional wielded items
2077 are ok, but if wielding multiple apples or rations
2078 we don't want "your foods slip", so force non-corpse
2079 food to be singular; skipping makeplural() isn't
2080 enough--we need to fool otense() too */
2081 if (!strcmp(thiswep, "food"))
2082 otmp->quan = 1L;
2083 else
2084 thiswep = makeplural(thiswep);
2086 hand = body_part(HAND);
2087 which = "";
2088 if (bimanual(otmp))
2089 hand = makeplural(hand);
2090 else if (wastwoweap)
2091 which = "right "; /* preceding msg was about left */
2092 pline("%s %s%s %s%s from your %s%s.",
2093 !strncmp(thiswep, "corpse", 6) ? "The" : "Your",
2094 otherwep ? "other " : "", thiswep, xfl ? "also " : "",
2095 otense(otmp, "slip"), which, hand);
2096 /* xfl++; */
2097 otmp->quan = savequan;
2098 setuwep((struct obj *) 0);
2099 if (canletgo(otmp, ""))
2100 dropx(otmp);
2104 struct obj *
2105 some_armor(victim)
2106 struct monst *victim;
2108 register struct obj *otmph, *otmp;
2110 otmph = (victim == &youmonst) ? uarmc : which_armor(victim, W_ARMC);
2111 if (!otmph)
2112 otmph = (victim == &youmonst) ? uarm : which_armor(victim, W_ARM);
2113 if (!otmph)
2114 otmph = (victim == &youmonst) ? uarmu : which_armor(victim, W_ARMU);
2116 otmp = (victim == &youmonst) ? uarmh : which_armor(victim, W_ARMH);
2117 if (otmp && (!otmph || !rn2(4)))
2118 otmph = otmp;
2119 otmp = (victim == &youmonst) ? uarmg : which_armor(victim, W_ARMG);
2120 if (otmp && (!otmph || !rn2(4)))
2121 otmph = otmp;
2122 otmp = (victim == &youmonst) ? uarmf : which_armor(victim, W_ARMF);
2123 if (otmp && (!otmph || !rn2(4)))
2124 otmph = otmp;
2125 otmp = (victim == &youmonst) ? uarms : which_armor(victim, W_ARMS);
2126 if (otmp && (!otmph || !rn2(4)))
2127 otmph = otmp;
2128 return otmph;
2131 /* used for praying to check and fix levitation trouble */
2132 struct obj *
2133 stuck_ring(ring, otyp)
2134 struct obj *ring;
2135 int otyp;
2137 if (ring != uleft && ring != uright) {
2138 impossible("stuck_ring: neither left nor right?");
2139 return (struct obj *) 0;
2142 if (ring && ring->otyp == otyp) {
2143 /* reasons ring can't be removed match those checked by select_off();
2144 limbless case has extra checks because ordinarily it's temporary */
2145 if (nolimbs(youmonst.data) && uamul
2146 && uamul->otyp == AMULET_OF_UNCHANGING && uamul->cursed)
2147 return uamul;
2148 if (welded(uwep) && (ring == uright || bimanual(uwep)))
2149 return uwep;
2150 if (uarmg && uarmg->cursed)
2151 return uarmg;
2152 if (ring->cursed)
2153 return ring;
2155 /* either no ring or not right type or nothing prevents its removal */
2156 return (struct obj *) 0;
2159 /* also for praying; find worn item that confers "Unchanging" attribute */
2160 struct obj *
2161 unchanger()
2163 if (uamul && uamul->otyp == AMULET_OF_UNCHANGING)
2164 return uamul;
2165 return 0;
2168 STATIC_PTR
2170 select_off(otmp)
2171 register struct obj *otmp;
2173 struct obj *why;
2174 char buf[BUFSZ];
2176 if (!otmp)
2177 return 0;
2178 *buf = '\0'; /* lint suppression */
2180 /* special ring checks */
2181 if (otmp == uright || otmp == uleft) {
2182 if (nolimbs(youmonst.data)) {
2183 pline_The("ring is stuck.");
2184 return 0;
2186 why = 0; /* the item which prevents ring removal */
2187 if (welded(uwep) && (otmp == uright || bimanual(uwep))) {
2188 Sprintf(buf, "free a weapon %s", body_part(HAND));
2189 why = uwep;
2190 } else if (uarmg && uarmg->cursed) {
2191 Sprintf(buf, "take off your %s", c_gloves);
2192 why = uarmg;
2194 if (why) {
2195 You("cannot %s to remove the ring.", buf);
2196 why->bknown = TRUE;
2197 return 0;
2200 /* special glove checks */
2201 if (otmp == uarmg) {
2202 if (welded(uwep)) {
2203 You("are unable to take off your %s while wielding that %s.",
2204 c_gloves, is_sword(uwep) ? c_sword : c_weapon);
2205 uwep->bknown = TRUE;
2206 return 0;
2207 } else if (Glib) {
2208 You_cant("take off the slippery %s with your slippery %s.",
2209 c_gloves, makeplural(body_part(FINGER)));
2210 return 0;
2213 /* special boot checks */
2214 if (otmp == uarmf) {
2215 if (u.utrap && u.utraptype == TT_BEARTRAP) {
2216 pline_The("bear trap prevents you from pulling your %s out.",
2217 body_part(FOOT));
2218 return 0;
2219 } else if (u.utrap && u.utraptype == TT_INFLOOR) {
2220 You("are stuck in the %s, and cannot pull your %s out.",
2221 surface(u.ux, u.uy), makeplural(body_part(FOOT)));
2222 return 0;
2225 /* special suit and shirt checks */
2226 if (otmp == uarm || otmp == uarmu) {
2227 why = 0; /* the item which prevents disrobing */
2228 if (uarmc && uarmc->cursed) {
2229 Sprintf(buf, "remove your %s", cloak_simple_name(uarmc));
2230 why = uarmc;
2231 } else if (otmp == uarmu && uarm && uarm->cursed) {
2232 Sprintf(buf, "remove your %s", c_suit);
2233 why = uarm;
2234 } else if (welded(uwep) && bimanual(uwep)) {
2235 Sprintf(buf, "release your %s",
2236 is_sword(uwep) ? c_sword : (uwep->otyp == BATTLE_AXE)
2237 ? c_axe
2238 : c_weapon);
2239 why = uwep;
2241 if (why) {
2242 You("cannot %s to take off %s.", buf, the(xname(otmp)));
2243 why->bknown = TRUE;
2244 return 0;
2247 /* basic curse check */
2248 if (otmp == uquiver || (otmp == uswapwep && !u.twoweap)) {
2249 ; /* some items can be removed even when cursed */
2250 } else {
2251 /* otherwise, this is fundamental */
2252 if (cursed(otmp))
2253 return 0;
2256 if (otmp == uarm)
2257 context.takeoff.mask |= WORN_ARMOR;
2258 else if (otmp == uarmc)
2259 context.takeoff.mask |= WORN_CLOAK;
2260 else if (otmp == uarmf)
2261 context.takeoff.mask |= WORN_BOOTS;
2262 else if (otmp == uarmg)
2263 context.takeoff.mask |= WORN_GLOVES;
2264 else if (otmp == uarmh)
2265 context.takeoff.mask |= WORN_HELMET;
2266 else if (otmp == uarms)
2267 context.takeoff.mask |= WORN_SHIELD;
2268 else if (otmp == uarmu)
2269 context.takeoff.mask |= WORN_SHIRT;
2270 else if (otmp == uleft)
2271 context.takeoff.mask |= LEFT_RING;
2272 else if (otmp == uright)
2273 context.takeoff.mask |= RIGHT_RING;
2274 else if (otmp == uamul)
2275 context.takeoff.mask |= WORN_AMUL;
2276 else if (otmp == ublindf)
2277 context.takeoff.mask |= WORN_BLINDF;
2278 else if (otmp == uwep)
2279 context.takeoff.mask |= W_WEP;
2280 else if (otmp == uswapwep)
2281 context.takeoff.mask |= W_SWAPWEP;
2282 else if (otmp == uquiver)
2283 context.takeoff.mask |= W_QUIVER;
2285 else
2286 impossible("select_off: %s???", doname(otmp));
2288 return 0;
2291 STATIC_OVL struct obj *
2292 do_takeoff()
2294 struct obj *otmp = (struct obj *) 0;
2295 struct takeoff_info *doff = &context.takeoff;
2297 if (doff->what == W_WEP) {
2298 if (!cursed(uwep)) {
2299 setuwep((struct obj *) 0);
2300 You("are empty %s.", body_part(HANDED));
2301 u.twoweap = FALSE;
2303 } else if (doff->what == W_SWAPWEP) {
2304 setuswapwep((struct obj *) 0);
2305 You("no longer have a second weapon readied.");
2306 u.twoweap = FALSE;
2307 } else if (doff->what == W_QUIVER) {
2308 setuqwep((struct obj *) 0);
2309 You("no longer have ammunition readied.");
2310 } else if (doff->what == WORN_ARMOR) {
2311 otmp = uarm;
2312 if (!cursed(otmp))
2313 (void) Armor_off();
2314 } else if (doff->what == WORN_CLOAK) {
2315 otmp = uarmc;
2316 if (!cursed(otmp))
2317 (void) Cloak_off();
2318 } else if (doff->what == WORN_BOOTS) {
2319 otmp = uarmf;
2320 if (!cursed(otmp))
2321 (void) Boots_off();
2322 } else if (doff->what == WORN_GLOVES) {
2323 otmp = uarmg;
2324 if (!cursed(otmp))
2325 (void) Gloves_off();
2326 } else if (doff->what == WORN_HELMET) {
2327 otmp = uarmh;
2328 if (!cursed(otmp))
2329 (void) Helmet_off();
2330 } else if (doff->what == WORN_SHIELD) {
2331 otmp = uarms;
2332 if (!cursed(otmp))
2333 (void) Shield_off();
2334 } else if (doff->what == WORN_SHIRT) {
2335 otmp = uarmu;
2336 if (!cursed(otmp))
2337 (void) Shirt_off();
2338 } else if (doff->what == WORN_AMUL) {
2339 otmp = uamul;
2340 if (!cursed(otmp))
2341 Amulet_off();
2342 } else if (doff->what == LEFT_RING) {
2343 otmp = uleft;
2344 if (!cursed(otmp))
2345 Ring_off(uleft);
2346 } else if (doff->what == RIGHT_RING) {
2347 otmp = uright;
2348 if (!cursed(otmp))
2349 Ring_off(uright);
2350 } else if (doff->what == WORN_BLINDF) {
2351 if (!cursed(ublindf))
2352 Blindf_off(ublindf);
2353 } else {
2354 impossible("do_takeoff: taking off %lx", doff->what);
2357 return otmp;
2360 /* occupation callback for 'A' */
2361 STATIC_PTR
2363 take_off(VOID_ARGS)
2365 register int i;
2366 register struct obj *otmp;
2367 struct takeoff_info *doff = &context.takeoff;
2369 if (doff->what) {
2370 if (doff->delay > 0) {
2371 doff->delay--;
2372 return 1; /* still busy */
2373 } else {
2374 if ((otmp = do_takeoff()))
2375 off_msg(otmp);
2377 doff->mask &= ~doff->what;
2378 doff->what = 0L;
2381 for (i = 0; takeoff_order[i]; i++)
2382 if (doff->mask & takeoff_order[i]) {
2383 doff->what = takeoff_order[i];
2384 break;
2387 otmp = (struct obj *) 0;
2388 doff->delay = 0;
2390 if (doff->what == 0L) {
2391 You("finish %s.", doff->disrobing);
2392 return 0;
2393 } else if (doff->what == W_WEP) {
2394 doff->delay = 1;
2395 } else if (doff->what == W_SWAPWEP) {
2396 doff->delay = 1;
2397 } else if (doff->what == W_QUIVER) {
2398 doff->delay = 1;
2399 } else if (doff->what == WORN_ARMOR) {
2400 otmp = uarm;
2401 /* If a cloak is being worn, add the time to take it off and put
2402 * it back on again. Kludge alert! since that time is 0 for all
2403 * known cloaks, add 1 so that it actually matters...
2405 if (uarmc)
2406 doff->delay += 2 * objects[uarmc->otyp].oc_delay + 1;
2407 } else if (doff->what == WORN_CLOAK) {
2408 otmp = uarmc;
2409 } else if (doff->what == WORN_BOOTS) {
2410 otmp = uarmf;
2411 } else if (doff->what == WORN_GLOVES) {
2412 otmp = uarmg;
2413 } else if (doff->what == WORN_HELMET) {
2414 otmp = uarmh;
2415 } else if (doff->what == WORN_SHIELD) {
2416 otmp = uarms;
2417 } else if (doff->what == WORN_SHIRT) {
2418 otmp = uarmu;
2419 /* add the time to take off and put back on armor and/or cloak */
2420 if (uarm)
2421 doff->delay += 2 * objects[uarm->otyp].oc_delay;
2422 if (uarmc)
2423 doff->delay += 2 * objects[uarmc->otyp].oc_delay + 1;
2424 } else if (doff->what == WORN_AMUL) {
2425 doff->delay = 1;
2426 } else if (doff->what == LEFT_RING) {
2427 doff->delay = 1;
2428 } else if (doff->what == RIGHT_RING) {
2429 doff->delay = 1;
2430 } else if (doff->what == WORN_BLINDF) {
2431 doff->delay = 2;
2432 } else {
2433 impossible("take_off: taking off %lx", doff->what);
2434 return 0; /* force done */
2437 if (otmp)
2438 doff->delay += objects[otmp->otyp].oc_delay;
2440 /* Since setting the occupation now starts the counter next move, that
2441 * would always produce a delay 1 too big per item unless we subtract
2442 * 1 here to account for it.
2444 if (doff->delay > 0)
2445 doff->delay--;
2447 set_occupation(take_off, doff->disrobing, 0);
2448 return 1; /* get busy */
2451 /* clear saved context to avoid inappropriate resumption of interrupted 'A' */
2452 void
2453 reset_remarm()
2455 context.takeoff.what = context.takeoff.mask = 0L;
2456 context.takeoff.disrobing[0] = '\0';
2459 /* the 'A' command -- remove multiple worn items */
2461 doddoremarm()
2463 int result = 0;
2465 if (context.takeoff.what || context.takeoff.mask) {
2466 You("continue %s.", context.takeoff.disrobing);
2467 set_occupation(take_off, context.takeoff.disrobing, 0);
2468 return 0;
2469 } else if (!uwep && !uswapwep && !uquiver && !uamul && !ublindf && !uleft
2470 && !uright && !wearing_armor()) {
2471 You("are not wearing anything.");
2472 return 0;
2475 add_valid_menu_class(0); /* reset */
2476 if (flags.menu_style != MENU_TRADITIONAL
2477 || (result = ggetobj("take off", select_off, 0, FALSE,
2478 (unsigned *) 0)) < -1)
2479 result = menu_remarm(result);
2481 if (context.takeoff.mask) {
2482 /* default activity for armor and/or accessories,
2483 possibly combined with weapons */
2484 (void) strncpy(context.takeoff.disrobing, "disrobing", CONTEXTVERBSZ);
2485 /* specific activity when handling weapons only */
2486 if (!(context.takeoff.mask & ~W_WEAPON))
2487 (void) strncpy(context.takeoff.disrobing, "disarming",
2488 CONTEXTVERBSZ);
2489 (void) take_off();
2491 /* The time to perform the command is already completely accounted for
2492 * in take_off(); if we return 1, that would add an extra turn to each
2493 * disrobe.
2495 return 0;
2498 STATIC_OVL int
2499 menu_remarm(retry)
2500 int retry;
2502 int n, i = 0;
2503 menu_item *pick_list;
2504 boolean all_worn_categories = TRUE;
2506 if (retry) {
2507 all_worn_categories = (retry == -2);
2508 } else if (flags.menu_style == MENU_FULL) {
2509 all_worn_categories = FALSE;
2510 n = query_category("What type of things do you want to take off?",
2511 invent, WORN_TYPES | ALL_TYPES, &pick_list,
2512 PICK_ANY);
2513 if (!n)
2514 return 0;
2515 for (i = 0; i < n; i++) {
2516 if (pick_list[i].item.a_int == ALL_TYPES_SELECTED)
2517 all_worn_categories = TRUE;
2518 else
2519 add_valid_menu_class(pick_list[i].item.a_int);
2521 free((genericptr_t) pick_list);
2522 } else if (flags.menu_style == MENU_COMBINATION) {
2523 all_worn_categories = FALSE;
2524 if (ggetobj("take off", select_off, 0, TRUE, (unsigned *) 0) == -2)
2525 all_worn_categories = TRUE;
2528 n = query_objlist("What do you want to take off?", &invent,
2529 (SIGNAL_NOMENU | USE_INVLET | INVORDER_SORT),
2530 &pick_list, PICK_ANY,
2531 all_worn_categories ? is_worn : is_worn_by_type);
2532 if (n > 0) {
2533 for (i = 0; i < n; i++)
2534 (void) select_off(pick_list[i].item.a_obj);
2535 free((genericptr_t) pick_list);
2536 } else if (n < 0 && flags.menu_style != MENU_COMBINATION) {
2537 There("is nothing else you can remove or unwield.");
2539 return 0;
2542 /* hit by destroy armor scroll/black dragon breath/monster spell */
2544 destroy_arm(atmp)
2545 register struct obj *atmp;
2547 register struct obj *otmp;
2548 #define DESTROY_ARM(o) \
2549 ((otmp = (o)) != 0 && (!atmp || atmp == otmp) \
2550 && (!obj_resists(otmp, 0, 90)) \
2551 ? (otmp->in_use = TRUE) \
2552 : FALSE)
2554 if (DESTROY_ARM(uarmc)) {
2555 if (donning(otmp))
2556 cancel_don();
2557 Your("%s crumbles and turns to dust!", cloak_simple_name(uarmc));
2558 (void) Cloak_off();
2559 useup(otmp);
2560 } else if (DESTROY_ARM(uarm)) {
2561 if (donning(otmp))
2562 cancel_don();
2563 Your("armor turns to dust and falls to the %s!", surface(u.ux, u.uy));
2564 (void) Armor_gone();
2565 useup(otmp);
2566 } else if (DESTROY_ARM(uarmu)) {
2567 if (donning(otmp))
2568 cancel_don();
2569 Your("shirt crumbles into tiny threads and falls apart!");
2570 (void) Shirt_off();
2571 useup(otmp);
2572 } else if (DESTROY_ARM(uarmh)) {
2573 if (donning(otmp))
2574 cancel_don();
2575 Your("%s turns to dust and is blown away!", helm_simple_name(uarmh));
2576 (void) Helmet_off();
2577 useup(otmp);
2578 } else if (DESTROY_ARM(uarmg)) {
2579 if (donning(otmp))
2580 cancel_don();
2581 Your("gloves vanish!");
2582 (void) Gloves_off();
2583 useup(otmp);
2584 selftouch("You");
2585 } else if (DESTROY_ARM(uarmf)) {
2586 if (donning(otmp))
2587 cancel_don();
2588 Your("boots disintegrate!");
2589 (void) Boots_off();
2590 useup(otmp);
2591 } else if (DESTROY_ARM(uarms)) {
2592 if (donning(otmp))
2593 cancel_don();
2594 Your("shield crumbles away!");
2595 (void) Shield_off();
2596 useup(otmp);
2597 } else {
2598 return 0; /* could not destroy anything */
2601 #undef DESTROY_ARM
2602 stop_occupation();
2603 return 1;
2606 void
2607 adj_abon(otmp, delta)
2608 register struct obj *otmp;
2609 register schar delta;
2611 if (uarmg && uarmg == otmp && otmp->otyp == GAUNTLETS_OF_DEXTERITY) {
2612 if (delta) {
2613 makeknown(uarmg->otyp);
2614 ABON(A_DEX) += (delta);
2616 context.botl = 1;
2618 if (uarmh && uarmh == otmp && otmp->otyp == HELM_OF_BRILLIANCE) {
2619 if (delta) {
2620 makeknown(uarmh->otyp);
2621 ABON(A_INT) += (delta);
2622 ABON(A_WIS) += (delta);
2624 context.botl = 1;
2628 /* decide whether a worn item is covered up by some other worn item,
2629 used for dipping into liquid and applying grease;
2630 some criteria are different than select_off()'s */
2631 boolean
2632 inaccessible_equipment(obj, verb, only_if_known_cursed)
2633 struct obj *obj;
2634 const char *verb; /* "dip" or "grease", or null to avoid messages */
2635 boolean only_if_known_cursed; /* ignore covering unless known to be cursed */
2637 static NEARDATA const char need_to_take_off_outer_armor[] =
2638 "need to take off %s to %s %s.";
2639 char buf[BUFSZ];
2640 boolean anycovering = !only_if_known_cursed; /* more comprehensible... */
2641 #define BLOCKSACCESS(x) (anycovering || ((x)->cursed && (x)->bknown))
2643 if (!obj || !obj->owornmask)
2644 return FALSE; /* not inaccessible */
2646 /* check for suit covered by cloak */
2647 if (obj == uarm && uarmc && BLOCKSACCESS(uarmc)) {
2648 if (verb) {
2649 Strcpy(buf, yname(uarmc));
2650 You(need_to_take_off_outer_armor, buf, verb, yname(obj));
2652 return TRUE;
2654 /* check for shirt covered by suit and/or cloak */
2655 if (obj == uarmu
2656 && ((uarm && BLOCKSACCESS(uarm)) || (uarmc && BLOCKSACCESS(uarmc)))) {
2657 if (verb) {
2658 char cloaktmp[QBUFSZ], suittmp[QBUFSZ];
2659 /* if sameprefix, use yname and xname to get "your cloak and suit"
2660 or "Manlobbi's cloak and suit"; otherwise, use yname and yname
2661 to get "your cloak and Manlobbi's suit" or vice versa */
2662 boolean sameprefix = (uarm && uarmc
2663 && !strcmp(shk_your(cloaktmp, uarmc),
2664 shk_your(suittmp, uarm)));
2666 *buf = '\0';
2667 if (uarmc)
2668 Strcat(buf, yname(uarmc));
2669 if (uarm && uarmc)
2670 Strcat(buf, " and ");
2671 if (uarm)
2672 Strcat(buf, sameprefix ? xname(uarm) : yname(uarm));
2673 You(need_to_take_off_outer_armor, buf, verb, yname(obj));
2675 return TRUE;
2677 /* check for ring covered by gloves */
2678 if ((obj == uleft || obj == uright) && uarmg && BLOCKSACCESS(uarmg)) {
2679 if (verb) {
2680 Strcpy(buf, yname(uarmg));
2681 You(need_to_take_off_outer_armor, buf, verb, yname(obj));
2683 return TRUE;
2685 /* item is not inaccessible */
2686 return FALSE;
2689 /*do_wear.c*/