1 /* NetHack 3.6 worn.c $NHDT-Date: 1446887541 2015/11/07 09:12:21 $ $NHDT-Branch: master $:$NHDT-Revision: 1.47 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed. See license for details. */
7 STATIC_DCL
void FDECL(m_lose_armor
, (struct monst
*, struct obj
*));
8 STATIC_DCL
void FDECL(m_dowear_type
,
9 (struct monst
*, long, BOOLEAN_P
, BOOLEAN_P
));
10 STATIC_DCL
int FDECL(extra_pref
, (struct monst
*, struct obj
*));
15 } worn
[] = { { W_ARM
, &uarm
},
25 { W_SWAPWEP
, &uswapwep
},
26 { W_QUIVER
, &uquiver
},
33 /* This only allows for one blocking item per property */
34 #define w_blocks(o, m) \
35 ((o->otyp == MUMMY_WRAPPING && ((m) &W_ARMC)) \
37 : (o->otyp == CORNUTHAUM && ((m) &W_ARMH) && !Role_if(PM_WIZARD)) \
40 /* note: monsters don't have clairvoyance, so your role
41 has no significant effect on their use of w_blocks() */
43 /* Updated to use the extrinsic and blocked fields. */
46 register struct obj
*obj
;
49 register const struct worn
*wp
;
50 register struct obj
*oobj
;
53 if ((mask
& (W_ARM
| I_SPECIAL
)) == (W_ARM
| I_SPECIAL
)) {
54 /* restoring saved game; no properties are conferred via skin */
56 /* assert( !uarm ); */
59 u
.uroleplay
.nudist
= FALSE
;
60 for (wp
= worn
; wp
->w_mask
; wp
++)
61 if (wp
->w_mask
& mask
) {
63 if (oobj
&& !(oobj
->owornmask
& wp
->w_mask
))
64 impossible("Setworn: mask = %ld.", wp
->w_mask
);
66 if (u
.twoweap
&& (oobj
->owornmask
& (W_WEP
| W_SWAPWEP
)))
68 oobj
->owornmask
&= ~wp
->w_mask
;
69 if (wp
->w_mask
& ~(W_SWAPWEP
| W_QUIVER
)) {
70 /* leave as "x = x <op> y", here and below, for broken
72 p
= objects
[oobj
->otyp
].oc_oprop
;
73 u
.uprops
[p
].extrinsic
=
74 u
.uprops
[p
].extrinsic
& ~wp
->w_mask
;
75 if ((p
= w_blocks(oobj
, mask
)) != 0)
76 u
.uprops
[p
].blocked
&= ~wp
->w_mask
;
78 set_artifact_intrinsic(oobj
, 0, mask
);
83 obj
->owornmask
|= wp
->w_mask
;
84 /* Prevent getting/blocking intrinsics from wielding
85 * potions, through the quiver, etc.
86 * Allow weapon-tools, too.
87 * wp_mask should be same as mask at this point.
89 if (wp
->w_mask
& ~(W_SWAPWEP
| W_QUIVER
)) {
90 if (obj
->oclass
== WEAPON_CLASS
|| is_weptool(obj
)
92 p
= objects
[obj
->otyp
].oc_oprop
;
93 u
.uprops
[p
].extrinsic
=
94 u
.uprops
[p
].extrinsic
| wp
->w_mask
;
95 if ((p
= w_blocks(obj
, mask
)) != 0)
96 u
.uprops
[p
].blocked
|= wp
->w_mask
;
99 set_artifact_intrinsic(obj
, 1, mask
);
107 /* called e.g. when obj is destroyed */
108 /* Updated to use the extrinsic and blocked fields. */
111 register struct obj
*obj
;
113 register const struct worn
*wp
;
118 if (obj
== uwep
|| obj
== uswapwep
)
120 for (wp
= worn
; wp
->w_mask
; wp
++)
121 if (obj
== *(wp
->w_obj
)) {
123 p
= objects
[obj
->otyp
].oc_oprop
;
124 u
.uprops
[p
].extrinsic
= u
.uprops
[p
].extrinsic
& ~wp
->w_mask
;
125 obj
->owornmask
&= ~wp
->w_mask
;
127 set_artifact_intrinsic(obj
, 0, wp
->w_mask
);
128 if ((p
= w_blocks(obj
, wp
->w_mask
)) != 0)
129 u
.uprops
[p
].blocked
&= ~wp
->w_mask
;
134 /* return a bitmask of the equipment slot(s) a given item might be worn in */
139 int otyp
= obj
->otyp
;
140 /* practically any item can be wielded or quivered; it's up to
141 our caller to handle such things--we assume "normal" usage */
142 long res
= 0L; /* default: can't be worn anywhere */
144 switch (obj
->oclass
) {
146 res
= W_AMUL
; /* WORN_AMUL */
149 res
= W_RINGL
| W_RINGR
; /* W_RING, BOTH_SIDES */
152 switch (objects
[otyp
].oc_armcat
) {
155 break; /* WORN_ARMOR */
158 break; /* WORN_SHIELD */
161 break; /* WORN_HELMET */
164 break; /* WORN_GLOVES */
167 break; /* WORN_BOOTS */
170 break; /* WORN_CLOAK */
173 break; /* WORN_SHIRT */
177 res
= W_WEP
| W_SWAPWEP
;
178 if (objects
[otyp
].oc_merge
)
182 if (otyp
== BLINDFOLD
|| otyp
== TOWEL
|| otyp
== LENSES
)
183 res
= W_TOOL
; /* WORN_BLINDF */
184 else if (is_weptool(obj
) || otyp
== TIN_OPENER
)
185 res
= W_WEP
| W_SWAPWEP
;
186 else if (otyp
== SADDLE
)
190 if (obj
->otyp
== MEAT_RING
)
191 res
= W_RINGL
| W_RINGR
;
213 if (!mon
->invis_blkd
) {
215 newsym(mon
->mx
, mon
->my
); /* make it disappear */
217 see_wsegs(mon
); /* and any tail too */
222 mon_adjust_speed(mon
, adjust
, obj
)
224 int adjust
; /* positive => increase speed, negative => decrease */
225 struct obj
*obj
; /* item to make known if effect can be seen */
228 boolean give_msg
= !in_mklev
, petrify
= FALSE
;
229 unsigned int oldspeed
= mon
->mspeed
;
233 mon
->permspeed
= MFAST
;
234 give_msg
= FALSE
; /* special case monster creation */
237 if (mon
->permspeed
== MSLOW
)
240 mon
->permspeed
= MFAST
;
242 case 0: /* just check for worn speed boots */
245 if (mon
->permspeed
== MFAST
)
248 mon
->permspeed
= MSLOW
;
251 mon
->permspeed
= MSLOW
;
252 give_msg
= FALSE
; /* (not currently used) */
254 case -3: /* petrification */
255 /* take away intrinsic speed but don't reduce normal speed */
256 if (mon
->permspeed
== MFAST
)
260 case -4: /* green slime */
261 if (mon
->permspeed
== MFAST
)
267 for (otmp
= mon
->minvent
; otmp
; otmp
= otmp
->nobj
)
268 if (otmp
->owornmask
&& objects
[otmp
->otyp
].oc_oprop
== FAST
)
270 if (otmp
) /* speed boots */
273 mon
->mspeed
= mon
->permspeed
;
275 /* no message if monster is immobile (temp or perm) or unseen */
276 if (give_msg
&& (mon
->mspeed
!= oldspeed
|| petrify
) && mon
->data
->mmove
277 && !(mon
->mfrozen
|| mon
->msleeping
) && canseemon(mon
)) {
278 /* fast to slow (skipping intermediate state) or vice versa */
279 const char *howmuch
=
280 (mon
->mspeed
+ oldspeed
== MFAST
+ MSLOW
) ? "much " : "";
283 /* mimic the player's petrification countdown; "slowing down"
284 even if fast movement rate retained via worn speed boots */
286 pline("%s is slowing down.", Monnam(mon
));
287 } else if (adjust
> 0 || mon
->mspeed
== MFAST
)
288 pline("%s is suddenly moving %sfaster.", Monnam(mon
), howmuch
);
290 pline("%s seems to be moving %sslower.", Monnam(mon
), howmuch
);
292 /* might discover an object if we see the speed change happen */
298 /* armor put on or taken off; might be magical variety */
300 update_mon_intrinsics(mon
, obj
, on
, silently
)
303 boolean on
, silently
;
308 int which
= (int) objects
[obj
->otyp
].oc_oprop
;
310 unseen
= !canseemon(mon
);
317 mon
->minvis
= !mon
->invis_blkd
;
320 boolean save_in_mklev
= in_mklev
;
323 mon_adjust_speed(mon
, 0, obj
);
324 in_mklev
= save_in_mklev
;
327 /* properties handled elsewhere */
331 /* properties which have no effect for monsters */
336 /* properties which should have an effect but aren't implemented */
340 /* properties which maybe should have an effect but don't */
347 if (which
<= 8) { /* 1 thru 8 correspond to MR_xxx mask values */
348 /* FIRE,COLD,SLEEP,DISINT,SHOCK,POISON,ACID,STONE */
349 mask
= (uchar
) (1 << (which
- 1));
350 mon
->mintrinsics
|= (unsigned short) mask
;
357 mon
->minvis
= mon
->perminvis
;
360 boolean save_in_mklev
= in_mklev
;
363 mon_adjust_speed(mon
, 0, obj
);
364 in_mklev
= save_in_mklev
;
375 mask
= (uchar
) (1 << (which
- 1));
376 /* If the monster doesn't have this resistance intrinsically,
377 check whether any other worn item confers it. Note that
378 we don't currently check for anything conferred via simply
379 carrying an object. */
380 if (!(mon
->data
->mresists
& mask
)) {
381 for (otmp
= mon
->minvent
; otmp
; otmp
= otmp
->nobj
)
383 && (int) objects
[otmp
->otyp
].oc_oprop
== which
)
386 mon
->mintrinsics
&= ~((unsigned short) mask
);
395 /* obj->owornmask has been cleared by this point, so we can't use it.
396 However, since monsters don't wield armor, we don't have to guard
397 against that and can get away with a blanket worn-mask value. */
398 switch (w_blocks(obj
, ~0L)) {
400 mon
->invis_blkd
= on
? 1 : 0;
401 mon
->minvis
= on
? 0 : mon
->perminvis
;
407 if (!on
&& mon
== u
.usteed
&& obj
->otyp
== SADDLE
)
408 dismount_steed(DISMOUNT_FELL
);
410 /* if couldn't see it but now can, or vice versa, update display */
411 if (!silently
&& (unseen
^ !canseemon(mon
)))
412 newsym(mon
->mx
, mon
->my
);
417 register struct monst
*mon
;
419 register struct obj
*obj
;
420 int base
= mon
->data
->ac
;
421 long mwflags
= mon
->misc_worn_check
;
423 for (obj
= mon
->minvent
; obj
; obj
= obj
->nobj
) {
424 if (obj
->owornmask
& mwflags
)
425 base
-= ARM_BONUS(obj
);
426 /* since ARM_BONUS is positive, subtracting it increases AC */
432 * weapons are handled separately;
433 * rings and eyewear aren't used by monsters
436 /* Wear the best object of each type that the monster has. During creation,
437 * the monster can put everything on at once; otherwise, wearing takes time.
438 * This doesn't affect monster searching for objects--a monster may very well
439 * search for objects it would not want to wear, because we don't want to
440 * check which_armor() each round.
442 * We'll let monsters put on shirts and/or suits under worn cloaks, but
443 * not shirts under worn suits. This is somewhat arbitrary, but it's
444 * too tedious to have them remove and later replace outer garments,
445 * and preventing suits under cloaks makes it a little bit too easy for
446 * players to influence what gets worn. Putting on a shirt underneath
447 * already worn body armor is too obviously buggy...
450 m_dowear(mon
, creation
)
451 register struct monst
*mon
;
454 #define RACE_EXCEPTION TRUE
455 /* Note the restrictions here are the same as in dowear in do_wear.c
456 * except for the additional restriction on intelligence. (Players
457 * are always intelligent, even if polymorphed).
459 if (verysmall(mon
->data
) || nohands(mon
->data
) || is_animal(mon
->data
))
461 /* give mummies a chance to wear their wrappings
462 * and let skeletons wear their initial armor */
463 if (mindless(mon
->data
)
464 && (!creation
|| (mon
->data
->mlet
!= S_MUMMY
465 && mon
->data
!= &mons
[PM_SKELETON
])))
468 m_dowear_type(mon
, W_AMUL
, creation
, FALSE
);
469 /* can't put on shirt if already wearing suit */
470 if (!cantweararm(mon
->data
) && !(mon
->misc_worn_check
& W_ARM
))
471 m_dowear_type(mon
, W_ARMU
, creation
, FALSE
);
472 /* treating small as a special case allows
473 hobbits, gnomes, and kobolds to wear cloaks */
474 if (!cantweararm(mon
->data
) || mon
->data
->msize
== MZ_SMALL
)
475 m_dowear_type(mon
, W_ARMC
, creation
, FALSE
);
476 m_dowear_type(mon
, W_ARMH
, creation
, FALSE
);
477 if (!MON_WEP(mon
) || !bimanual(MON_WEP(mon
)))
478 m_dowear_type(mon
, W_ARMS
, creation
, FALSE
);
479 m_dowear_type(mon
, W_ARMG
, creation
, FALSE
);
480 if (!slithy(mon
->data
) && mon
->data
->mlet
!= S_CENTAUR
)
481 m_dowear_type(mon
, W_ARMF
, creation
, FALSE
);
482 if (!cantweararm(mon
->data
))
483 m_dowear_type(mon
, W_ARM
, creation
, FALSE
);
485 m_dowear_type(mon
, W_ARM
, creation
, RACE_EXCEPTION
);
489 m_dowear_type(mon
, flag
, creation
, racialexception
)
493 boolean racialexception
;
495 struct obj
*old
, *best
, *obj
;
497 int unseen
= !canseemon(mon
);
502 return; /* probably putting previous item on */
504 /* Get a copy of monster's name before altering its visibility */
505 Strcpy(nambuf
, See_invisible
? Monnam(mon
) : mon_nam(mon
));
507 old
= which_armor(mon
, flag
);
508 if (old
&& old
->cursed
)
510 if (old
&& flag
== W_AMUL
)
511 return; /* no such thing as better amulets */
514 for (obj
= mon
->minvent
; obj
; obj
= obj
->nobj
) {
517 if (obj
->oclass
!= AMULET_CLASS
518 || (obj
->otyp
!= AMULET_OF_LIFE_SAVING
519 && obj
->otyp
!= AMULET_OF_REFLECTION
))
522 goto outer_break
; /* no such thing as better amulets */
534 /* changing alignment is not implemented for monsters;
535 priests and minions could change alignment but wouldn't
536 want to, so they reject helms of opposite alignment */
537 if (obj
->otyp
== HELM_OF_OPPOSITE_ALIGNMENT
538 && (mon
->ispriest
|| mon
->isminion
))
540 /* (flimsy exception matches polyself handling) */
541 if (has_horns(mon
->data
) && !is_flimsy(obj
))
559 if (racialexception
&& (racial_exception(mon
, obj
) < 1))
565 /* I'd like to define a VISIBLE_ARM_BONUS which doesn't assume the
566 * monster knows obj->spe, but if I did that, a monster would keep
567 * switching forever between two -2 caps since when it took off one
568 * it would forget spe and once again think the object is better
569 * than what it already has.
571 if (best
&& (ARM_BONUS(best
) + extra_pref(mon
, best
)
572 >= ARM_BONUS(obj
) + extra_pref(mon
, obj
)))
577 if (!best
|| best
== old
)
580 /* same auto-cursing behavior as for hero */
581 autocurse
= ((best
->otyp
== HELM_OF_OPPOSITE_ALIGNMENT
582 || best
->otyp
== DUNCE_CAP
) && !best
->cursed
);
583 /* if wearing a cloak, account for the time spent removing
584 and re-wearing it when putting on a suit or shirt */
585 if ((flag
== W_ARM
|| flag
== W_ARMU
) && (mon
->misc_worn_check
& W_ARMC
))
587 /* when upgrading a piece of armor, account for time spent
588 taking off current one */
590 m_delay
+= objects
[old
->otyp
].oc_delay
;
592 if (old
) /* do this first to avoid "(being worn)" */
595 if (canseemon(mon
)) {
599 Sprintf(buf
, " removes %s and", distant_name(old
, doname
));
602 pline("%s%s puts on %s.", Monnam(mon
), buf
,
603 distant_name(best
, doname
));
605 pline("%s %s %s %s for a moment.", s_suffix(Monnam(mon
)),
606 simpleonames(best
), otense(best
, "glow"),
609 m_delay
+= objects
[best
->otyp
].oc_delay
;
610 mon
->mfrozen
= m_delay
;
615 update_mon_intrinsics(mon
, old
, FALSE
, creation
);
616 mon
->misc_worn_check
|= flag
;
617 best
->owornmask
|= flag
;
620 update_mon_intrinsics(mon
, best
, TRUE
, creation
);
621 /* if couldn't see it but now can, or vice versa, */
622 if (!creation
&& (unseen
^ !canseemon(mon
))) {
623 if (mon
->minvis
&& !See_invisible
) {
624 pline("Suddenly you cannot see %s.", nambuf
);
625 makeknown(best
->otyp
);
626 } /* else if (!mon->minvis) pline("%s suddenly appears!",
630 #undef RACE_EXCEPTION
633 which_armor(mon
, flag
)
637 if (mon
== &youmonst
) {
654 impossible("bad flag in which_armor");
658 register struct obj
*obj
;
660 for (obj
= mon
->minvent
; obj
; obj
= obj
->nobj
)
661 if (obj
->owornmask
& flag
)
663 return (struct obj
*) 0;
667 /* remove an item of armor and then drop it */
669 m_lose_armor(mon
, obj
)
673 mon
->misc_worn_check
&= ~obj
->owornmask
;
675 update_mon_intrinsics(mon
, obj
, FALSE
, FALSE
);
678 obj_extract_self(obj
);
679 place_object(obj
, mon
->mx
, mon
->my
);
680 /* call stackobj() if we ever drop anything that can merge */
681 newsym(mon
->mx
, mon
->my
);
684 /* all objects with their bypass bit set should now be reset to normal */
688 struct obj
*otmp
, *nobj
;
691 for (otmp
= fobj
; otmp
; otmp
= nobj
) {
696 /* bypass will have inhibited any stacking, but since it's
697 * used for polymorph handling, the objects here probably
698 * have been transformed and won't be stacked in the usual
699 * manner afterwards; so don't bother with this.
700 * [Changing the fobj chain mid-traversal would also be risky.]
703 if (objects
[otmp
->otyp
].oc_merge
) {
706 (void) get_obj_location(otmp
, &ox
, &oy
, 0);
713 for (otmp
= invent
; otmp
; otmp
= otmp
->nobj
)
715 for (otmp
= migrating_objs
; otmp
; otmp
= otmp
->nobj
)
717 for (mtmp
= fmon
; mtmp
; mtmp
= mtmp
->nmon
) {
718 if (DEADMONSTER(mtmp
))
720 for (otmp
= mtmp
->minvent
; otmp
; otmp
= otmp
->nobj
)
723 for (mtmp
= migrating_mons
; mtmp
; mtmp
= mtmp
->nmon
) {
724 for (otmp
= mtmp
->minvent
; otmp
; otmp
= otmp
->nobj
)
727 /* billobjs and mydogs chains don't matter here */
728 context
.bypasses
= FALSE
;
736 context
.bypasses
= TRUE
;
739 /* set or clear the bypass bit in a list of objects */
741 bypass_objlist(objchain
, on
)
742 struct obj
*objchain
;
743 boolean on
; /* TRUE => set, FALSE => clear */
746 context
.bypasses
= TRUE
;
748 objchain
->bypass
= on
? 1 : 0;
749 objchain
= objchain
->nobj
;
753 /* return the first object without its bypass bit set; set that bit
754 before returning so that successive calls will find further objects */
756 nxt_unbypassed_obj(objchain
)
757 struct obj
*objchain
;
760 if (!objchain
->bypass
) {
761 bypass_obj(objchain
);
764 objchain
= objchain
->nobj
;
770 mon_break_armor(mon
, polyspot
)
774 register struct obj
*otmp
;
775 struct permonst
*mdat
= mon
->data
;
776 boolean vis
= cansee(mon
->mx
, mon
->my
);
777 boolean handless_or_tiny
= (nohands(mdat
) || verysmall(mdat
));
778 const char *pronoun
= mhim(mon
), *ppronoun
= mhis(mon
);
780 if (breakarm(mdat
)) {
781 if ((otmp
= which_armor(mon
, W_ARM
)) != 0) {
782 if ((Is_dragon_scales(otmp
) && mdat
== Dragon_scales_to_pm(otmp
))
783 || (Is_dragon_mail(otmp
) && mdat
== Dragon_mail_to_pm(otmp
)))
784 ; /* no message here;
785 "the dragon merges with his scaly armor" is odd
786 and the monster's previous form is already gone */
788 pline("%s breaks out of %s armor!", Monnam(mon
), ppronoun
);
790 You_hear("a cracking sound.");
793 if ((otmp
= which_armor(mon
, W_ARMC
)) != 0) {
794 if (otmp
->oartifact
) {
796 pline("%s %s falls off!", s_suffix(Monnam(mon
)),
797 cloak_simple_name(otmp
));
800 m_lose_armor(mon
, otmp
);
803 pline("%s %s tears apart!", s_suffix(Monnam(mon
)),
804 cloak_simple_name(otmp
));
806 You_hear("a ripping sound.");
810 if ((otmp
= which_armor(mon
, W_ARMU
)) != 0) {
812 pline("%s shirt rips to shreds!", s_suffix(Monnam(mon
)));
814 You_hear("a ripping sound.");
817 } else if (sliparm(mdat
)) {
818 if ((otmp
= which_armor(mon
, W_ARM
)) != 0) {
820 pline("%s armor falls around %s!", s_suffix(Monnam(mon
)),
826 m_lose_armor(mon
, otmp
);
828 if ((otmp
= which_armor(mon
, W_ARMC
)) != 0) {
830 if (is_whirly(mon
->data
))
831 pline("%s %s falls, unsupported!", s_suffix(Monnam(mon
)),
832 cloak_simple_name(otmp
));
834 pline("%s shrinks out of %s %s!", Monnam(mon
), ppronoun
,
835 cloak_simple_name(otmp
));
839 m_lose_armor(mon
, otmp
);
841 if ((otmp
= which_armor(mon
, W_ARMU
)) != 0) {
843 if (sliparm(mon
->data
))
844 pline("%s seeps right through %s shirt!", Monnam(mon
),
847 pline("%s becomes much too small for %s shirt!",
848 Monnam(mon
), ppronoun
);
852 m_lose_armor(mon
, otmp
);
855 if (handless_or_tiny
) {
856 /* [caller needs to handle weapon checks] */
857 if ((otmp
= which_armor(mon
, W_ARMG
)) != 0) {
859 pline("%s drops %s gloves%s!", Monnam(mon
), ppronoun
,
860 MON_WEP(mon
) ? " and weapon" : "");
863 m_lose_armor(mon
, otmp
);
865 if ((otmp
= which_armor(mon
, W_ARMS
)) != 0) {
867 pline("%s can no longer hold %s shield!", Monnam(mon
),
870 You_hear("a clank.");
873 m_lose_armor(mon
, otmp
);
876 if (handless_or_tiny
|| has_horns(mdat
)) {
877 if ((otmp
= which_armor(mon
, W_ARMH
)) != 0
878 /* flimsy test for horns matches polyself handling */
879 && (handless_or_tiny
|| !is_flimsy(otmp
))) {
881 pline("%s helmet falls to the %s!", s_suffix(Monnam(mon
)),
882 surface(mon
->mx
, mon
->my
));
884 You_hear("a clank.");
887 m_lose_armor(mon
, otmp
);
890 if (handless_or_tiny
|| slithy(mdat
) || mdat
->mlet
== S_CENTAUR
) {
891 if ((otmp
= which_armor(mon
, W_ARMF
)) != 0) {
893 if (is_whirly(mon
->data
))
894 pline("%s boots fall away!", s_suffix(Monnam(mon
)));
896 pline("%s boots %s off %s feet!", s_suffix(Monnam(mon
)),
897 verysmall(mdat
) ? "slide" : "are pushed", ppronoun
);
901 m_lose_armor(mon
, otmp
);
904 if (!can_saddle(mon
)) {
905 if ((otmp
= which_armor(mon
, W_SADDLE
)) != 0) {
908 m_lose_armor(mon
, otmp
);
910 pline("%s saddle falls off.", s_suffix(Monnam(mon
)));
914 } else if (mon
== u
.usteed
&& !can_ride(mon
)) {
916 You("can no longer ride %s.", mon_nam(mon
));
917 if (touch_petrifies(u
.usteed
->data
) && !Stone_resistance
&& rnl(3)) {
920 You("touch %s.", mon_nam(u
.usteed
));
921 Sprintf(buf
, "falling off %s", an(u
.usteed
->data
->mname
));
924 dismount_steed(DISMOUNT_FELL
);
929 /* bias a monster's preferences towards armor that has special benefits. */
935 /* currently only does speed boots, but might be expanded if monsters
936 * get to use more armor abilities
939 if (obj
->otyp
== SPEED_BOOTS
&& mon
->permspeed
!= MFAST
)
946 * Exceptions to things based on race.
947 * Correctly checks polymorphed player race.
949 * 0 No exception, normal rules apply.
950 * 1 If the race/object combination is acceptable.
951 * -1 If the race/object combination is unacceptable.
954 racial_exception(mon
, obj
)
958 const struct permonst
*ptr
= raceptr(mon
);
960 /* Acceptable Exceptions: */
961 /* Allow hobbits to wear elven armor - LoTR */
962 if (ptr
== &mons
[PM_HOBBIT
] && is_elven_armor(obj
))
964 /* Unacceptable Exceptions: */
965 /* Checks for object that certain races should never use go here */