Blindfold removal fix
[slashemextended.git] / src / worn.c
blob3644141bce5ce0964e955b908ebeaecfbb6c72e4
1 /* SCCS Id: @(#)worn.c 3.4 2003/01/08 */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed. See license for details. */
5 #include "hack.h"
7 STATIC_DCL void m_lose_armor(struct monst *,struct obj *);
8 STATIC_DCL void m_dowear_type(struct monst *,long, BOOLEAN_P, BOOLEAN_P);
9 STATIC_DCL int extra_pref(struct monst *, struct obj *);
11 const struct worn {
12 long w_mask;
13 struct obj **w_obj;
14 } worn[] = {
15 { W_ARM, &uarm },
16 { W_ARMC, &uarmc },
17 { W_ARMH, &uarmh },
18 { W_ARMS, &uarms },
19 { W_ARMG, &uarmg },
20 { W_ARMF, &uarmf },
21 { W_ARMU, &uarmu },
22 { W_RINGL, &uleft },
23 { W_RINGR, &uright },
24 { W_WEP, &uwep },
25 { W_SWAPWEP, &uswapwep },
26 { W_QUIVER, &uquiver },
27 { W_AMUL, &uamul },
28 { W_IMPLANT, &uimplant },
29 { W_TOOL, &ublindf },
30 { W_BALL, &uball },
31 { W_CHAIN, &uchain },
32 { W_SADDLE, &usaddle },
33 { 0, 0 }
36 /* this only allows for one blocking property per item */
37 /* KMH -- Added Hobbits & stealth */
38 /* This only allows for one blocking item per property */
39 #define w_blocks(o,m) \
40 ((o->otyp == MUMMY_WRAPPING && ((m) & W_ARMC)) ? INVIS : \
41 (o->otyp == CORNUTHAUM && ((m) & W_ARMH) && \
42 !Role_if(PM_WIZARD)) ? CLAIRVOYANT : \
43 (is_boots(o) && o->otyp != ELVEN_BOOTS && ((m) & W_ARMF) && \
44 Role_if(PM_HOBBIT)) ? STEALTH : 0)
45 /* note: monsters don't have clairvoyance, so your role
46 has no significant effect on their use of w_blocks() */
48 /* KMH, intrinsic patch.
49 * Updated to use the extrinsic and blocked fields.
51 void
52 setworn(obj, mask)
53 register struct obj *obj;
54 long mask;
56 register const struct worn *wp;
57 register struct obj *oobj;
58 register int p, q;
60 if ((mask & (W_ARM|I_SPECIAL)) == (W_ARM|I_SPECIAL)) {
61 /* restoring saved game; no properties are conferred via skin */
62 uskin = obj;
63 /* assert( !uarm ); */
64 } else {
65 for(wp = worn; wp->w_mask; wp++) if(wp->w_mask & mask) {
66 oobj = *(wp->w_obj);
67 if(oobj && !(oobj->owornmask & wp->w_mask))
68 pline("Setworn: mask = %ld.", wp->w_mask);
69 if(oobj) {
70 if (u.twoweap && (oobj->owornmask & (W_WEP|W_SWAPWEP)) && uwep && bimanual(uwep) ) {
71 if (uswapwep)
72 unwield(uswapwep, FALSE);
73 u.twoweap = 0;
75 oobj->owornmask &= ~wp->w_mask;
76 if (wp->w_mask & ~(W_SWAPWEP|W_QUIVER)) {
77 /* leave as "x = x <op> y", here and below, for broken
78 * compilers */
79 p = objects[oobj->otyp].oc_oprop;
80 u.uprops[p].extrinsic =
81 u.uprops[p].extrinsic & ~wp->w_mask;
83 q = oobj->enchantment;
84 if (q) {
85 u.uprops[oobj->enchantment].extrinsic = u.uprops[oobj->enchantment].extrinsic & ~wp->w_mask;
88 if ((p = w_blocks(oobj,mask)) != 0)
89 u.uprops[p].blocked &= ~wp->w_mask;
90 if (oobj->oartifact)
91 set_artifact_intrinsic(oobj, 0, mask);
94 *(wp->w_obj) = obj;
95 if(obj) {
96 obj->owornmask |= wp->w_mask;
97 /* Prevent getting/blocking intrinsics from wielding
98 * potions, through the quiver, etc.
99 * Allow weapon-tools, too.
100 * wp_mask should be same as mask at this point.
102 if (wp->w_mask & ~(W_SWAPWEP|W_QUIVER)) {
103 if (obj->oclass == WEAPON_CLASS || is_weptool(obj) ||
104 mask != W_WEP) {
105 p = objects[obj->otyp].oc_oprop;
106 u.uprops[p].extrinsic =
107 u.uprops[p].extrinsic | wp->w_mask;
109 q = obj->enchantment;
110 if (q) {
111 u.uprops[obj->enchantment].extrinsic = u.uprops[obj->enchantment].extrinsic | wp->w_mask;
114 if ((p = w_blocks(obj, mask)) != 0)
115 u.uprops[p].blocked |= wp->w_mask;
117 if (obj->oartifact)
118 set_artifact_intrinsic(obj, 1, mask);
123 update_inventory();
126 /* called e.g. when obj is destroyed */
127 /* KMH, intrinsic patch.
128 * Updated to use the extrinsic and blocked fields.
130 void
131 setnotworn(obj)
132 register struct obj *obj;
134 register const struct worn *wp;
135 register int p, q;
137 if (!obj) return;
138 if (obj == uwep || obj == uswapwep) {
139 if (uswapwep)
140 unwield(uswapwep, FALSE);
141 if (uwep && bimanual(uwep)) u.twoweap = 0;
143 for(wp = worn; wp->w_mask; wp++)
144 if(obj == *(wp->w_obj)) {
145 *(wp->w_obj) = 0;
146 p = objects[obj->otyp].oc_oprop;
147 u.uprops[p].extrinsic = u.uprops[p].extrinsic & ~wp->w_mask;
149 q = obj->enchantment;
150 if (q) {
151 u.uprops[obj->enchantment].extrinsic = u.uprops[obj->enchantment].extrinsic & ~wp->w_mask;
154 obj->owornmask &= ~wp->w_mask;
155 if (obj->oartifact)
156 set_artifact_intrinsic(obj, 0, wp->w_mask);
157 if ((p = w_blocks(obj,wp->w_mask)) != 0)
158 u.uprops[p].blocked &= ~wp->w_mask;
160 update_inventory();
163 void
164 mon_set_minvis(mon)
165 struct monst *mon;
167 mon->perminvis = 1;
168 if (!mon->invis_blkd) {
169 mon->minvis = 1;
170 if (!rn2(100)) mon->minvisreal = 1;
171 newsym(mon->mx, mon->my); /* make it disappear */
172 if (mon->wormno) see_wsegs(mon); /* and any tail too */
176 void
177 mon_adjust_speed(mon, adjust, obj)
178 struct monst *mon;
179 int adjust; /* positive => increase speed, negative => decrease */
180 struct obj *obj; /* item to make known if effect can be seen */
182 struct obj *otmp;
183 boolean give_msg = !in_mklev, petrify = FALSE;
184 unsigned int oldspeed = mon->mspeed;
186 if (mercedesride(ART_SENATOR_S_SPEED, mon) && adjust < 0) {
187 pline("%s doesn't slow down!", Monnam(mon));
188 return;
191 switch (adjust) {
192 case 2:
193 mon->permspeed = MFAST;
194 give_msg = FALSE; /* special case monster creation */
195 break;
196 case 1:
197 if (mon->permspeed == MSLOW) mon->permspeed = 0;
198 else mon->permspeed = MFAST;
199 break;
200 case 0: /* just check for worn speed boots */
201 break;
202 case -1:
203 if (mon->permspeed == MFAST) mon->permspeed = 0;
204 else mon->permspeed = MSLOW;
205 break;
206 case -2:
207 mon->permspeed = MSLOW;
208 give_msg = FALSE; /* (not currently used) */
209 break;
210 case -3: /* petrification */
211 /* take away intrinsic speed but don't reduce normal speed */
212 if (mon->permspeed == MFAST) mon->permspeed = 0;
213 petrify = TRUE;
214 break;
217 for (otmp = mon->minvent; otmp; otmp = otmp->nobj)
218 if (otmp->owornmask && objects[otmp->otyp].oc_oprop == FAST)
219 break;
220 if (otmp) /* speed boots */
221 mon->mspeed = MFAST;
222 else
223 mon->mspeed = mon->permspeed;
225 if (give_msg && (mon->mspeed != oldspeed || petrify) && canseemon(mon)) {
226 /* fast to slow (skipping intermediate state) or vice versa */
227 const char *howmuch = (mon->mspeed + oldspeed == MFAST + MSLOW) ?
228 "much " : "";
230 if (petrify) {
231 /* mimic the player's petrification countdown; "slowing down"
232 even if fast movement rate retained via worn speed boots */
233 if (flags.verbose) pline("%s is slowing down.", Monnam(mon));
234 } else if (adjust > 0 || mon->mspeed == MFAST)
235 pline("%s is suddenly moving %sfaster.", Monnam(mon), howmuch);
236 else
237 pline("%s seems to be moving %sslower.", Monnam(mon), howmuch);
239 /* might discover an object if we see the speed change happen, but
240 avoid making possibly forgotten book known when casting its spell */
241 if (obj != 0 && obj->dknown &&
242 objects[obj->otyp].oc_class != SPBOOK_CLASS)
243 makeknown(obj->otyp);
247 /* armor put on or taken off; might be magical variety */
248 void
249 update_mon_intrinsics(mon, obj, on, silently)
250 struct monst *mon;
251 struct obj *obj;
252 boolean on, silently;
254 int unseen;
255 unsigned long mask;
256 struct obj *otmp;
257 int which = (int) objects[obj->otyp].oc_oprop;
259 unseen = !canseemon(mon);
260 if (!which) goto maybe_blocks;
262 if (on) {
263 switch (which) {
264 case INVIS:
265 mon->minvis = !mon->invis_blkd;
266 break;
267 case FAST:
269 boolean save_in_mklev = in_mklev;
270 if (silently) in_mklev = TRUE;
271 mon_adjust_speed(mon, 0, obj);
272 in_mklev = save_in_mklev;
273 break;
275 /* properties handled elsewhere */
276 case ANTIMAGIC:
277 case REFLECTING:
278 break;
279 /* properties which have no effect for monsters */
280 case CLAIRVOYANT:
281 case STEALTH:
282 case TELEPAT:
283 break;
284 /* properties which should have an effect but aren't implemented */
285 case LEVITATION:
286 case WWALKING:
287 break;
288 /* properties which maybe should have an effect but don't */
289 case DISPLACED:
290 case FUMBLING:
291 case JUMPING:
292 case PROTECTION:
293 break;
294 case DRAIN_RES:
295 mon->mintrinsics |= MR_DRAIN;
296 break;
297 default:
298 if (which <= 8) { /* 1 thru 8 correspond to MR_xxx mask values */
299 /* FIRE,COLD,SLEEP,DISINT,SHOCK,POISON,ACID,STONE */
300 mask = (uchar) (1 << (which - 1));
301 mon->mintrinsics |= (unsigned short) mask;
303 break;
305 } else { /* off */
306 switch (which) {
307 case INVIS:
308 mon->minvis = mon->perminvis;
309 break;
310 case FAST:
312 boolean save_in_mklev = in_mklev;
313 if (silently) in_mklev = TRUE;
314 mon_adjust_speed(mon, 0, obj);
315 in_mklev = save_in_mklev;
316 break;
318 case DRAIN_RES:
319 mask = MR_DRAIN;
320 goto maybe_loose;
321 case FIRE_RES:
322 case COLD_RES:
323 case SLEEP_RES:
324 case DISINT_RES:
325 case SHOCK_RES:
326 case POISON_RES:
327 case ACID_RES:
328 case STONE_RES:
329 mask = (uchar) (1 << (which - 1));
330 maybe_loose:
331 /* If the monster doesn't have this resistance intrinsically,
332 check whether any other worn item confers it. Note that
333 we don't currently check for anything conferred via simply
334 carrying an object. */
335 if (!(mon->data->mresists & mask)) {
336 for (otmp = mon->minvent; otmp; otmp = otmp->nobj)
337 if (otmp->owornmask &&
338 (int) objects[otmp->otyp].oc_oprop == which)
339 break;
340 if (!otmp)
341 mon->mintrinsics &= ~mask;
343 break;
344 default:
345 break;
349 maybe_blocks:
350 /* obj->owornmask has been cleared by this point, so we can't use it.
351 However, since monsters don't wield armor, we don't have to guard
352 against that and can get away with a blanket worn-mask value. */
353 switch (w_blocks(obj,~0L)) {
354 case INVIS:
355 mon->invis_blkd = on ? 1 : 0;
356 mon->minvis = on ? 0 : mon->perminvis;
357 break;
358 default:
359 break;
362 if (!on && mon == u.usteed && obj->otyp == LEATHER_SADDLE)
363 dismount_steed(DISMOUNT_FELL);
364 if (!on && mon == u.usteed && obj->otyp == INKA_SADDLE)
365 dismount_steed(DISMOUNT_FELL);
366 if (!on && mon == u.usteed && obj->otyp == TANK_SADDLE)
367 dismount_steed(DISMOUNT_FELL);
368 if (!on && mon == u.usteed && obj->otyp == BARDING)
369 dismount_steed(DISMOUNT_FELL);
370 if (!on && mon == u.usteed && obj->otyp == MESH_SADDLE)
371 dismount_steed(DISMOUNT_FELL);
372 if (!on && mon == u.usteed && obj->otyp == SEATBELT_SADDLE)
373 dismount_steed(DISMOUNT_FELL);
375 /* if couldn't see it but now can, or vice versa, update display */
376 if (!silently && (unseen ^ !canseemon(mon)))
377 newsym(mon->mx, mon->my);
381 find_mac(mon)
382 register struct monst *mon;
384 register struct obj *obj;
385 int base = mon->data->ac;
386 long mwflags = mon->misc_worn_check;
388 if (mon->egotype_armorer) base -= 5;
389 if (mon->egotype_tank) base -= 10;
391 /* soresu monster lightsaber form */
392 if (which_armor(mon, W_ARM)) {
393 struct obj *monarmor = which_armor(mon, W_ARM);
394 if (monarmor && (monarmor->otyp >= ROBE && monarmor->otyp <= ROBE_OF_WEAKNESS) ) {
395 struct obj *monweapon;
396 if (MON_WEP(mon)) {
397 monweapon = MON_WEP(mon);
398 if (monweapon) {
399 if (is_lightsaber(monweapon) && monweapon->lamplit) base -= 10;
400 if (mon->data->geno & G_UNIQ) base -= 10;
406 if (fordride(TANK_SADDLE, mon)) base -= 5;
407 if (fordride(BARDING, mon)) base -= 3;
409 if (mercedesride(ART_DEATH_SQUAD_MOBILE, mon)) base -= 5;
411 if (FemtrapActiveMarleen && humanoid(mon->data) && is_female(mon->data) ) {
412 if (SuperFemtrapMarleen) base -= (10 + mon->m_lev);
413 else base -= mon->m_lev;
416 for (obj = mon->minvent; obj; obj = obj->nobj) {
417 if (obj->owornmask & mwflags)
418 base -= ARM_BONUS(obj);
419 /* since ARM_BONUS is positive, subtracting it increases AC */
422 if (is_wagon(mon->mx, mon->my)) base -= 10;
424 if (uarm && uarm->oartifact == ART_INTERNAL_VIEW && base < 10) {
425 int acamount = base - 10; /* example: base = -10, i.e. 20 points of AC */
426 if (acamount < 0) acamount *= -1; /* acamount would now be 20 */
428 acamount *= 7;
429 acamount /= 10;
430 /* acamount is 14 now */
432 base = 10 - acamount; /* -4 instead of -10 */
435 if (!mon->mtame && !mon->mpeaceful && uwep && uwep->oartifact == ART_ROARBEAR && base < 10) {
436 int acamount = base - 10;
437 if (acamount < 0) acamount *= -1;
439 acamount /= 2;
441 base = 10 - acamount;
445 if (!mon->mtame && !mon->mpeaceful && uwep && uwep->oartifact == ART_BRUTISH_CLAYMORE && base < 10) {
446 int acamount = base - 10;
447 if (acamount < 0) acamount *= -1;
449 acamount /= 2;
451 base = 10 - acamount;
455 if (!mon->mtame && !mon->mpeaceful && uwep && uwep->oartifact == ART_GAIA_HAMMER && base < 10) {
456 int acamount = base - 10;
457 if (acamount < 0) acamount *= -1;
459 acamount /= 2;
461 base = 10 - acamount;
465 if (!mon->mtame && !mon->mpeaceful && uwep && uwep->oartifact == ART_SHINING_SILVER_KATANA && base < 10) {
466 int acamount = base - 10;
467 if (acamount < 0) acamount *= -1;
469 acamount /= 2;
471 base = 10 - acamount;
475 if (!mon->mtame && !mon->mpeaceful && uwep && uwep->oartifact == ART_ZANTETSU && base < 10) {
476 int acamount = base - 10;
477 if (acamount < 0) acamount *= -1;
479 acamount /= 2;
481 base = 10 - acamount;
485 if (!mon->mtame && !mon->mpeaceful && uarmg && uarmg->oartifact == ART_GLOVES_OF_VESDA && base < 10) {
486 int acamount = base - 10;
487 if (acamount < 0) acamount *= -1;
489 acamount /= 2;
491 base = 10 - acamount;
495 if (uarm && uarm->oartifact == ART_ETH_ITH && base < 10) {
496 int acamount = base - 10;
497 if (acamount < 0) acamount *= -1;
499 acamount /= 2;
501 base = 10 - acamount;
505 /* Monsters with too good AC should not be completely unhittable. --Amy */
506 if (!rn2(20)) {
507 int absoluteac = (-(base - 10));
508 if (absoluteac < 0) absoluteac *= -1;
509 if ((absoluteac / 2) > 0) base += rnd(absoluteac / 2);
510 else base += 1;
511 if (base > 10) base = 10;
514 return base;
517 /* weapons are handled separately; rings and eyewear aren't used by monsters */
519 /* Wear the best object of each type that the monster has. During creation,
520 * the monster can put everything on at once; otherwise, wearing takes time.
521 * This doesn't affect monster searching for objects--a monster may very well
522 * search for objects it would not want to wear, because we don't want to
523 * check which_armor() each round.
525 * We'll let monsters put on shirts and/or suits under worn cloaks, but
526 * not shirts under worn suits. This is somewhat arbitrary, but it's
527 * too tedious to have them remove and later replace outer garments,
528 * and preventing suits under cloaks makes it a little bit too easy for
529 * players to influence what gets worn. Putting on a shirt underneath
530 * already worn body armor is too obviously buggy...
532 void
533 m_dowear(mon, creation)
534 register struct monst *mon;
535 boolean creation;
537 #define RACE_EXCEPTION TRUE
538 /* Note the restrictions here are the same as in dowear in do_wear.c
539 * except for the additional restriction on intelligence. (Players
540 * are always intelligent, even if polymorphed).
542 /*if (verysmall(mon->data) || nohands(mon->data) || is_animal(mon->data))
543 return;*/
544 /* give mummies a chance to wear their wrappings
545 * and let skeletons wear their initial armor */
546 /* well screw it, just let mindless creatures wear everything! --Amy */
547 /*if (mindless(mon->data) && (!creation ||
548 (mon->data->mlet != S_MUMMY && mon->data != &mons[PM_SKELETON])))
549 return;*/
551 m_dowear_type(mon, W_AMUL, creation, FALSE);
553 if (!creation && is_animal(mon->data)) return;
555 /* can't put on shirt if already wearing suit */
556 if ( (!cantweararm(mon->data) || (creation && !verysmall(mon->data) && (mon->data->msize <= MZ_LARGE) ) ) || (mon->misc_worn_check & W_ARM) || mon->data->msize == MZ_SMALL)
557 m_dowear_type(mon, W_ARMU, creation, FALSE);
558 /* treating small as a special case allows
559 hobbits, gnomes, and kobolds to wear cloaks */
560 if ( (!cantweararm(mon->data) || (creation && !verysmall(mon->data) && (mon->data->msize <= MZ_LARGE) ) ) || mon->data->msize == MZ_SMALL)
561 m_dowear_type(mon, W_ARMC, creation, FALSE);
562 m_dowear_type(mon, W_ARMH, creation, FALSE);
564 /* shield needs to be checked below: certain types can be used with a two-hander --Amy */
565 m_dowear_type(mon, W_ARMS, creation, FALSE);
566 m_dowear_type(mon, W_ARMG, creation, FALSE);
567 if ((!slithy(mon->data) && mon->data->mlet != S_CENTAUR) || !issoviet)
568 m_dowear_type(mon, W_ARMF, creation, FALSE);
569 if (!cantweararm(mon->data) || (creation && !verysmall(mon->data) && (mon->data->msize <= MZ_LARGE) ) )
570 m_dowear_type(mon, W_ARM, creation, FALSE);
571 else
572 m_dowear_type(mon, W_ARM, creation, RACE_EXCEPTION);
575 STATIC_OVL void
576 m_dowear_type(mon, flag, creation, racialexception)
577 struct monst *mon;
578 long flag;
579 boolean creation;
580 boolean racialexception;
582 struct obj *old, *best, *obj;
583 int m_delay = 0;
584 int unseen = !canseemon(mon);
585 char nambuf[BUFSZ];
587 if (mon->mfrozen) return; /* probably putting previous item on */
589 /* Get a copy of monster's name before altering its visibility */
590 strcpy(nambuf, See_invisible ? Monnam(mon) : mon_nam(mon));
592 old = which_armor(mon, flag);
594 /* hostile monsters may occasionally cheat and simply shake off a cursed item --Amy
595 * In Soviet Russia, curses are absolute. No one may be able to ever take off a cursed item, not even monsters who
596 * are, by definition, completely unable to remove curses and therefore have zero chance to ever switch to
597 * something else. Because it's such an ingenious strategy to carry around a -10 leather armor and give it to
598 * a monster who will then forever have shitty AC. */
599 if (old && old->cursed && (issoviet || mon->mpeaceful || mon->mtame || rn2(5)) ) return;
600 if (old && flag == W_AMUL) return; /* no such thing as better amulets */
601 best = old;
603 for(obj = mon->minvent; obj; obj = obj->nobj) {
604 switch(flag) {
605 case W_AMUL:
606 if (obj->oclass != AMULET_CLASS ||
607 (obj->otyp != AMULET_OF_MONSTER_SAVING && obj->otyp != AMULET_OF_DATA_STORAGE &&
608 obj->otyp != AMULET_OF_REFLECTION))
609 continue;
610 best = obj;
611 goto outer_break; /* no such thing as better amulets */
612 case W_ARMU:
613 if (!is_shirt(obj)) continue;
614 break;
615 case W_RING:
616 if (obj->otyp != RIN_TIMELY_BACKUP) continue;
617 best = obj;
618 goto outer_break; /* no such thing as better rings */
619 case W_RINGL:
620 if (obj->otyp != RIN_TIMELY_BACKUP) continue;
621 best = obj;
622 goto outer_break; /* no such thing as better rings */
623 case W_RINGR:
624 if (obj->otyp != RIN_TIMELY_BACKUP) continue;
625 best = obj;
626 goto outer_break; /* no such thing as better rings */
627 case W_ARMC:
628 if (!is_cloak(obj)) continue;
629 break;
630 case W_ARMH:
631 if (!is_helmet(obj)) continue;
632 /* (flimsy exception matches polyself handling) */
633 if (!creation && has_horns(mon->data) && !is_flimsy(obj)) continue;
634 break;
635 case W_ARMS:
636 if (MON_WEP(mon) && bimanual(MON_WEP(mon)) && obj->otyp != GRIM_SHIELD) continue;
637 if (!is_shield(obj)) continue;
638 break;
639 case W_ARMG:
640 if (!is_gloves(obj)) continue;
641 break;
642 case W_ARMF:
643 if (!is_boots(obj)) continue;
644 break;
645 case W_ARM:
646 if (!is_suit(obj)) continue;
647 if (!creation && racialexception && (racial_exception(mon, obj) < 1)) continue;
648 break;
650 if (obj->owornmask) continue;
651 /* I'd like to define a VISIBLE_ARM_BONUS which doesn't assume the
652 * monster knows obj->spe, but if I did that, a monster would keep
653 * switching forever between two -2 caps since when it took off one
654 * it would forget spe and once again think the object is better
655 * than what it already has.
658 if (FemtrapActiveKatia && mon->data->msound == MS_FART_LOUD && itemhasappearance(obj, APP_BLOCK_HEELED_BOOTS)) best = obj;
660 if (best && (ARM_BONUS(best) + extra_pref(mon,best) >= ARM_BONUS(obj) + extra_pref(mon,obj)))
661 continue;
662 if (FemtrapActiveKatia && mon->data->msound == MS_FART_LOUD && best && itemhasappearance(best, APP_BLOCK_HEELED_BOOTS)) continue;
664 best = obj;
666 outer_break:
667 if (!best || best == old) return;
669 /* if wearing a cloak, account for the time spent removing
670 and re-wearing it when putting on a suit or shirt */
671 if ((flag == W_ARM
672 || flag == W_ARMU
673 ) && (mon->misc_worn_check & W_ARMC))
674 m_delay += 2;
675 /* when upgrading a piece of armor, account for time spent
676 taking off current one */
677 if (old)
678 m_delay += objects[old->otyp].oc_delay;
680 if (old) /* do this first to avoid "(being worn)" */
681 old->owornmask = 0L;
682 if (!creation) {
683 if (canseemon(mon)) {
684 char buf[BUFSZ];
686 if (old)
687 sprintf(buf, " removes %s and", distant_name(old, doname));
688 else
689 buf[0] = '\0';
690 pline("%s%s puts on %s.", Monnam(mon),
691 buf, distant_name(best,doname));
692 } /* can see it */
693 m_delay += objects[best->otyp].oc_delay;
694 mon->mfrozen = m_delay;
695 if (mon->mfrozen) mon->mcanmove = 0;
697 if (old)
698 update_mon_intrinsics(mon, old, FALSE, creation);
699 mon->misc_worn_check |= flag;
700 best->owornmask |= flag;
701 update_mon_intrinsics(mon, best, TRUE, creation);
702 /* if couldn't see it but now can, or vice versa, */
703 if (!creation && (unseen ^ !canseemon(mon))) {
704 if ((mon->minvis && !See_invisible) || mon->minvisreal) {
705 pline("Suddenly you cannot see %s.", nambuf);
706 makeknown(best->otyp);
707 } /* else if (!mon->minvis) pline("%s suddenly appears!", Amonnam(mon)); */
710 #undef RACE_EXCEPTION
712 struct obj *
713 which_armor(mon, flag)
714 struct monst *mon;
715 long flag;
717 register struct obj *obj;
719 for(obj = mon->minvent; obj; obj = obj->nobj)
720 if (obj->owornmask & flag) return obj;
721 return((struct obj *)0);
724 /* remove an item of armor and then drop it */
725 STATIC_OVL void
726 m_lose_armor(mon, obj)
727 struct monst *mon;
728 struct obj *obj;
730 mon->misc_worn_check &= ~obj->owornmask;
731 if (obj->owornmask)
732 update_mon_intrinsics(mon, obj, FALSE, FALSE);
733 obj->owornmask = 0L;
735 obj_extract_self(obj);
736 place_object(obj, mon->mx, mon->my);
737 /* call stackobj() if we ever drop anything that can merge */
738 newsym(mon->mx, mon->my);
741 /* all objects with their bypass bit set should now be reset to normal */
742 void
743 clear_bypasses()
745 struct obj *otmp, *nobj;
746 struct monst *mtmp;
748 for (otmp = fobj; otmp; otmp = nobj) {
749 nobj = otmp->nobj;
750 if (otmp->bypass) {
751 otmp->bypass = 0;
752 /* bypass will have inhibited any stacking, but since it's
753 used for polymorph handling, the objects here probably
754 have been transformed and won't be stacked in the usual
755 manner afterwards; so don't bother with this */
756 #if 0
757 if (objects[otmp->otyp].oc_merge) {
758 xchar ox, oy;
760 (void) get_obj_location(otmp, &ox, &oy, 0);
761 stack_object(otmp);
762 newsym(ox, oy);
764 #endif /*0*/
767 /* invent and mydogs chains shouldn't matter here */
768 for (otmp = migrating_objs; otmp; otmp = otmp->nobj)
769 otmp->bypass = 0;
770 for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
771 if (DEADMONSTER(mtmp)) continue;
772 for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj)
773 otmp->bypass = 0;
775 for (mtmp = migrating_mons; mtmp; mtmp = mtmp->nmon) {
776 for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj)
777 otmp->bypass = 0;
779 flags.bypasses = FALSE;
782 void
783 bypass_obj(obj)
784 struct obj *obj;
786 obj->bypass = 1;
787 flags.bypasses = TRUE;
790 void
791 mon_break_armor(mon, polyspot)
792 struct monst *mon;
793 boolean polyspot;
795 register struct obj *otmp;
796 struct permonst *mdat = mon->data;
797 boolean vis = cansee(mon->mx, mon->my);
798 boolean handless_or_tiny = (nohands(mdat) || verysmall(mdat));
799 const char *pronoun = mhim(mon),
800 *ppronoun = mhis(mon);
802 if (breakarm(mdat)) {
803 if ((otmp = which_armor(mon, W_ARM)) != 0) {
804 if ((Is_dragon_scales(otmp) &&
805 mdat == Dragon_scales_to_pm(otmp)) ||
806 (Is_dragon_mail(otmp) && mdat == Dragon_mail_to_pm(otmp)))
807 ; /* no message here;
808 "the dragon merges with his scaly armor" is odd
809 and the monster's previous form is already gone */
810 else if (vis)
811 pline("%s breaks out of %s armor!", Monnam(mon), ppronoun);
812 else
813 You_hear("a cracking sound.");
814 m_useup(mon, otmp);
816 if ((otmp = which_armor(mon, W_ARMC)) != 0) {
817 if (otmp->oartifact) {
818 if (vis)
819 pline("%s %s falls off!", s_suffix(Monnam(mon)),
820 cloak_simple_name(otmp));
821 if (polyspot) bypass_obj(otmp);
822 m_lose_armor(mon, otmp);
823 } else {
824 if (vis)
825 pline("%s %s tears apart!", s_suffix(Monnam(mon)),
826 cloak_simple_name(otmp));
827 else
828 You_hear("a ripping sound.");
829 m_useup(mon, otmp);
832 if ((otmp = which_armor(mon, W_ARMU)) != 0) {
833 if (vis)
834 pline("%s shirt rips to shreds!", s_suffix(Monnam(mon)));
835 else
836 You_hear("a ripping sound.");
837 m_useup(mon, otmp);
839 } else if (sliparm(mdat)) {
840 if ((otmp = which_armor(mon, W_ARM)) != 0) {
841 if (vis)
842 pline("%s armor falls around %s!",
843 s_suffix(Monnam(mon)), pronoun);
844 else
845 You_hear("a thud.");
846 if (polyspot) bypass_obj(otmp);
847 m_lose_armor(mon, otmp);
849 if ((otmp = which_armor(mon, W_ARMC)) != 0) {
850 if (vis) {
851 if (is_whirly(mon->data))
852 pline("%s %s falls, unsupported!",
853 s_suffix(Monnam(mon)), cloak_simple_name(otmp));
854 else
855 pline("%s shrinks out of %s %s!", Monnam(mon),
856 ppronoun, cloak_simple_name(otmp));
858 if (polyspot) bypass_obj(otmp);
859 m_lose_armor(mon, otmp);
861 if ((otmp = which_armor(mon, W_ARMU)) != 0) {
862 if (vis) {
863 if (sliparm(mon->data))
864 pline("%s seeps right through %s shirt!",
865 Monnam(mon), ppronoun);
866 else
867 pline("%s becomes much too small for %s shirt!",
868 Monnam(mon), ppronoun);
870 if (polyspot) bypass_obj(otmp);
871 m_lose_armor(mon, otmp);
874 if (handless_or_tiny) {
875 /* [caller needs to handle weapon checks] */
876 if ((otmp = which_armor(mon, W_ARMG)) != 0) {
877 if (vis)
878 pline("%s drops %s gloves%s!", Monnam(mon), ppronoun,
879 MON_WEP(mon) ? " and weapon" : "");
880 if (polyspot) bypass_obj(otmp);
881 m_lose_armor(mon, otmp);
883 if ((otmp = which_armor(mon, W_ARMS)) != 0) {
884 if (vis)
885 pline("%s can no longer hold %s shield!", Monnam(mon),
886 ppronoun);
887 else
888 You_hear("a clank.");
889 if (polyspot) bypass_obj(otmp);
890 m_lose_armor(mon, otmp);
893 if (handless_or_tiny || has_horns(mdat)) {
894 if ((otmp = which_armor(mon, W_ARMH)) != 0 &&
895 /* flimsy test for horns matches polyself handling */
896 (handless_or_tiny || !is_flimsy(otmp))) {
897 if (vis)
898 pline("%s helmet falls to the %s!",
899 s_suffix(Monnam(mon)), surface(mon->mx, mon->my));
900 else
901 You_hear("a clank.");
902 if (polyspot) bypass_obj(otmp);
903 m_lose_armor(mon, otmp);
906 if (handless_or_tiny || slithy(mdat) || mdat->mlet == S_CENTAUR) {
907 if ((otmp = which_armor(mon, W_ARMF)) != 0) {
908 if (vis) {
909 if (is_whirly(mon->data))
910 pline("%s boots fall away!",
911 s_suffix(Monnam(mon)));
912 else pline("%s boots %s off %s feet!",
913 s_suffix(Monnam(mon)),
914 verysmall(mdat) ? "slide" : "are pushed", ppronoun);
916 if (polyspot) bypass_obj(otmp);
917 m_lose_armor(mon, otmp);
920 if (!can_saddle(mon)) {
921 if ((otmp = which_armor(mon, W_SADDLE)) != 0) {
922 if (polyspot) bypass_obj(otmp);
923 m_lose_armor(mon, otmp);
924 if (vis)
925 pline("%s saddle falls off.", s_suffix(Monnam(mon)));
927 if (mon == u.usteed)
928 goto noride;
929 } else if (mon == u.usteed && !can_ride(mon)) {
930 noride:
931 You("can no longer ride %s.", mon_nam(mon));
932 if (touch_petrifies(u.usteed->data) && (!Stone_resistance || (!IntStone_resistance && !rn2(20)) ) && !(uarmg && !FingerlessGloves && uarmu && uarm && uarmc) && rnl(3)) {
933 char buf[BUFSZ];
935 You("touch %s.", mon_nam(u.usteed));
936 sprintf(buf, "falling off a petrifying steed");
937 instapetrify(buf);
939 dismount_steed(DISMOUNT_FELL);
941 return;
944 /* bias a monster's preferences towards armor that has special benefits. */
945 /* currently only does speed boots, but might be expanded if monsters get to
946 use more armor abilities */
947 static int
948 extra_pref(mon, obj)
949 struct monst *mon;
950 struct obj *obj;
952 if (obj) {
953 if (obj->otyp == SPEED_BOOTS && mon->permspeed != MFAST)
954 return 20;
956 return 0;
960 * Exceptions to things based on race. Correctly checks polymorphed player race.
961 * Returns:
962 * 0 No exception, normal rules apply.
963 * 1 If the race/object combination is acceptable.
964 * -1 If the race/object combination is unacceptable.
967 racial_exception(mon, obj)
968 struct monst *mon;
969 struct obj *obj;
971 const struct permonst *ptr = raceptr(mon);
973 /* Acceptable Exceptions: */
974 /* Allow hobbits to wear elven armor - LoTR */
975 if (is_hobbit(ptr) && is_elven_armor(obj))
976 return 1;
978 /* sporkhack gnomish suit - somehow never got worn by actual gnomes... --Amy */
979 if (is_gnome(ptr) && is_gnomish_armor(obj))
980 return 1;
982 /* Unacceptable Exceptions: */
983 /* Checks for object that certain races should never use go here */
984 /* return -1; */
986 return 0;
988 /*worn.c*/