1    | /*	SCCS Id: @(#)worn.c	3.3	2000/02/19	*/
2    | /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3    | /* NetHack may be freely redistributed.  See license for details. */
4    | 
5    | #include "hack.h"
6    | 
7    | STATIC_DCL void FDECL(m_lose_armor, (struct monst *,struct obj *));
8    | STATIC_DCL void FDECL(m_dowear_type, (struct monst *,long,BOOLEAN_P));
9    | 
10   | const struct worn {
11   | 	long w_mask;
12   | 	struct obj **w_obj;
13   | } worn[] = {
14   | 	{ W_ARM, &uarm },
15   | 	{ W_ARMC, &uarmc },
16   | 	{ W_ARMH, &uarmh },
17   | 	{ W_ARMS, &uarms },
18   | 	{ W_ARMG, &uarmg },
19   | 	{ W_ARMF, &uarmf },
20   | #ifdef TOURIST
21   | 	{ W_ARMU, &uarmu },
22   | #endif
23   | 	{ W_RINGL, &uleft },
24   | 	{ W_RINGR, &uright },
25   | 	{ W_WEP, &uwep },
26   | 	{ W_SWAPWEP, &uswapwep },
27   | 	{ W_QUIVER, &uquiver },
28   | 	{ W_AMUL, &uamul },
29   | 	{ W_TOOL, &ublindf },
30   | 	{ W_BALL, &uball },
31   | 	{ W_CHAIN, &uchain },
32   | 	{ 0, 0 }
33   | };
34   | 
35   | /* This only allows for one blocking item per property */
36   | #define w_blocks(o,m) \
37   | 		((o->otyp == MUMMY_WRAPPING && ((m) & W_ARMC)) ? INVIS : \
38   | 		 (o->otyp == CORNUTHAUM && ((m) & W_ARMH) && \
39   | 			!Role_if(PM_WIZARD)) ? CLAIRVOYANT : 0)
40   | 		/* note: monsters don't have clairvoyance, so your role
41   | 		   has no significant effect on their use of w_blocks() */
42   | 
43   | 
44   | /* Updated to use the extrinsic and blocked fields. */
45   | void
46   | setworn(obj, mask)
47   | register struct obj *obj;
48   | long mask;
49   | {
50   | 	register const struct worn *wp;
51   | 	register struct obj *oobj;
52   | 	register int p;
53   | 
54   | 	if ((mask & (W_ARM|I_SPECIAL)) == (W_ARM|I_SPECIAL)) {
55   | 	    /* restoring saved game; no properties are conferred via skin */
56   | 	    uskin = obj;
57   | 	 /* assert( !uarm ); */
58   | 	} else {
59   | 	    for(wp = worn; wp->w_mask; wp++) if(wp->w_mask & mask) {
60   | 		oobj = *(wp->w_obj);
61   | 		if(oobj && !(oobj->owornmask & wp->w_mask))
62   | 			impossible("Setworn: mask = %ld.", wp->w_mask);
63   | 		if(oobj) {
64   | 		    if (u.twoweap && (oobj->owornmask & (W_WEP|W_SWAPWEP)))
65   | 			u.twoweap = 0;
66   | 		    oobj->owornmask &= ~wp->w_mask;
67   | 		    if (wp->w_mask & ~(W_SWAPWEP|W_QUIVER)) {
68   | 			/* leave as "x = x <op> y", here and below, for broken
69   | 			 * compilers */
70   | 			p = objects[oobj->otyp].oc_oprop;
71   | 			u.uprops[p].extrinsic =
72   | 					u.uprops[p].extrinsic & ~wp->w_mask;
73   | 			if ((p = w_blocks(oobj,mask)) != 0)
74   | 			    u.uprops[p].blocked &= ~wp->w_mask;
75   | 			if (oobj->oartifact)
76   | 			    set_artifact_intrinsic(oobj, 0, mask);
77   | 		    }
78   | 		}
79   | 		*(wp->w_obj) = obj;
80   | 		if(obj) {
81   | 		    obj->owornmask |= wp->w_mask;
82   | 		    /* Prevent getting/blocking intrinsics from wielding
83   | 		     * potions, through the quiver, etc.
84   | 		     * Allow weapon-tools, too.
85   | 		     * wp_mask should be same as mask at this point.
86   | 		     */
87   | 		    if (wp->w_mask & ~(W_SWAPWEP|W_QUIVER)) {
88   | 			if (obj->oclass == WEAPON_CLASS || is_weptool(obj) ||
89   | 					    mask != W_WEP) {
90   | 			    p = objects[obj->otyp].oc_oprop;
91   | 			    u.uprops[p].extrinsic =
92   | 					u.uprops[p].extrinsic | wp->w_mask;
93   | 			    if ((p = w_blocks(obj, mask)) != 0)
94   | 				u.uprops[p].blocked |= wp->w_mask;
95   | 			}
96   | 			if (obj->oartifact)
97   | 			    set_artifact_intrinsic(obj, 1, mask);
98   | 		    }
99   | 		}
100  | 	    }
101  | 	}
102  | 	update_inventory();
103  | }
104  | 
105  | /* called e.g. when obj is destroyed */
106  | /* Updated to use the extrinsic and blocked fields. */
107  | void
108  | setnotworn(obj)
109  | register struct obj *obj;
110  | {
111  | 	register const struct worn *wp;
112  | 	register int p;
113  | 
114  | 	if (!obj) return;
115  | 	if (obj == uwep || obj == uswapwep) u.twoweap = 0;
116  | 	for(wp = worn; wp->w_mask; wp++)
117  | 		if(obj == *(wp->w_obj)) {
118  | 			*(wp->w_obj) = 0;
119  | 			p = objects[obj->otyp].oc_oprop;
120  | 			u.uprops[p].extrinsic = u.uprops[p].extrinsic & ~wp->w_mask;
121  | 			obj->owornmask &= ~wp->w_mask;
122  | 			if (obj->oartifact)
123  | 			    set_artifact_intrinsic(obj, 0, wp->w_mask);
124  | 			if ((p = w_blocks(obj,wp->w_mask)) != 0)
125  | 			    u.uprops[p].blocked &= ~wp->w_mask;
126  | 		}
127  | 	update_inventory();
128  | }
129  | 
130  | void
131  | mon_set_minvis(mon)
132  | struct monst *mon;
133  | {
134  | 	mon->perminvis = 1;
135  | 	if (!mon->invis_blkd) {
136  | 	    mon->minvis = 1;
137  | 	    newsym(mon->mx, mon->my);		/* make it disappear */
138  | 	    if (mon->wormno) see_wsegs(mon);	/* and any tail too */
139  | 	}
140  | }
141  | 
142  | void
143  | mon_adjust_speed(mon, adjust)
144  | struct monst *mon;
145  | int adjust;	/* positive => increase speed, negative => decrease */
146  | {
147  |     struct obj *otmp;
148  | 
149  |     switch (adjust) {
150  |      case  2:
151  | 	mon->permspeed = MFAST;
152  | 	break;
153  |      case  1:
154  | 	if (mon->permspeed == MSLOW) mon->permspeed = 0;
155  | 	else mon->permspeed = MFAST;
156  | 	break;
157  |      case  0:			/* just check for worn speed boots */
158  | 	break;
159  |      case -1:
160  | 	if (mon->permspeed == MFAST) mon->permspeed = 0;
161  | 	else mon->permspeed = MSLOW;
162  | 	break;
163  |      case -2:
164  | 	mon->permspeed = MSLOW;
165  | 	break;
166  |     }
167  | 
168  |     for (otmp = mon->minvent; otmp; otmp = otmp->nobj)
169  | 	if (otmp->owornmask && objects[otmp->otyp].oc_oprop == FAST)
170  | 	    break;
171  |     if (otmp)		/* speed boots */
172  | 	mon->mspeed = MFAST;
173  |     else
174  | 	mon->mspeed = mon->permspeed;
175  | }
176  | 
177  | /* armor put on or taken off; might be magical variety */
178  | void
179  | update_mon_intrinsics(mon, obj, on)
180  | struct monst *mon;
181  | struct obj *obj;
182  | boolean on;
183  | {
184  |     int unseen;
185  |     uchar mask;
186  |     struct obj *otmp;
187  |     int which = (int) objects[obj->otyp].oc_oprop;
188  | 
189  |     unseen = !canseemon(mon);
190  |     if (!which) goto maybe_blocks;
191  | 
192  |     if (on) {
193  | 	switch (which) {
194  | 	 case INVIS:
195  | 	    mon->minvis = !mon->invis_blkd;
196  | 	    break;
197  | 	 case FAST:
198  | 	    mon_adjust_speed(mon, 0);
199  | 	    break;
200  | 	/* properties handled elsewhere */
201  | 	 case ANTIMAGIC:
202  | 	 case REFLECTING:
203  | 	    break;
204  | 	/* properties which have no effect for monsters */
205  | 	 case CLAIRVOYANT:
206  | 	 case STEALTH:
207  | 	 case TELEPAT:
208  | 	    break;
209  | 	/* properties which should have an effect but aren't implemented */
210  | 	 case LEVITATION:
211  | 	 case WWALKING:
212  | 	    break;
213  | 	/* properties which maybe should have an effect but don't */
214  | 	 case DISPLACED:
215  | 	 case FUMBLING:
216  | 	 case JUMPING:
217  | 	 case PROTECTION:
218  | 	    break;
219  | 	 default:
220  | 	    if (which <= 8) {	/* 1 thru 8 correspond to MR_xxx mask values */
221  | 		/* FIRE,COLD,SLEEP,DISINT,SHOCK,POISON,ACID,STONE */
222  | 		mask = (uchar) (1 << (which - 1));
223  | 		mon->mintrinsics |= (unsigned short) mask;
224  | 	    }
225  | 	    break;
226  | 	}
227  |     } else {	    /* off */
228  | 	switch (which) {
229  | 	 case INVIS:
230  | 	    mon->minvis = mon->perminvis;
231  | 	    break;
232  | 	 case FAST:
233  | 	    mon_adjust_speed(mon, 0);
234  | 	    break;
235  | 	 case FIRE_RES:
236  | 	 case COLD_RES:
237  | 	 case SLEEP_RES:
238  | 	 case DISINT_RES:
239  | 	 case SHOCK_RES:
240  | 	 case POISON_RES:
241  | 	 case ACID_RES:
242  | 	 case STONE_RES:
243  | 	    mask = (uchar) (1 << (which - 1));
244  | 	    /* If the monster doesn't have this resistance intrinsically,
245  | 	       check whether any other worn item confers it.  Note that
246  | 	       we don't currently check for anything conferred via simply
247  | 	       carrying an object. */
248  | 	    if (!(mon->data->mresists & mask)) {
249  | 		for (otmp = mon->minvent; otmp; otmp = otmp->nobj)
250  | 		    if (otmp->owornmask &&
251  | 			    (int) objects[otmp->otyp].oc_oprop == which)
252  | 			break;
253  | 		if (!otmp)
254  | 		    mon->mintrinsics &= ~((unsigned short) mask);
255  | 	    }
256  | 	    break;
257  | 	 default:
258  | 	    break;
259  | 	}
260  |     }
261  | 
262  |  maybe_blocks:
263  |     /* obj->owornmask has been cleared by this point, so we can't use it.
264  |        However, since monsters don't wield armor, we don't have to guard
265  |        against that and can get away with a blanket worn-mask value. */
266  |     switch (w_blocks(obj,~0L)) {
267  |      case INVIS:
268  | 	mon->invis_blkd = on ? 1 : 0;
269  | 	mon->minvis = on ? 0 : mon->perminvis;
270  | 	break;
271  |      default:
272  | 	break;
273  |     }
274  | 
275  | #ifdef STEED
276  | 	if (!on && mon == u.usteed && obj->otyp == SADDLE)
277  | 	    dismount_steed(DISMOUNT_FELL);
278  | #endif
279  | 
280  |     /* if couldn't see it but now can, or vice versa, update display */
281  |     if (unseen ^ !canseemon(mon))
282  | 	newsym(mon->mx, mon->my);
283  | }
284  | 
285  | int
286  | find_mac(mon)
287  | register struct monst *mon;
288  | {
289  | 	register struct obj *obj;
290  | 	int base = mon->data->ac;
291  | 	long mwflags = mon->misc_worn_check;
292  | 
293  | 	for (obj = mon->minvent; obj; obj = obj->nobj) {
294  | 	    if (obj->owornmask & mwflags)
295  | 		base -= ARM_BONUS(obj);
296  | 		/* since ARM_BONUS is positive, subtracting it increases AC */
297  | 	}
298  | 	return base;
299  | }
300  | 
301  | /* weapons are handled separately; rings and eyewear aren't used by monsters */
302  | 
303  | /* Wear the best object of each type that the monster has.  During creation,
304  |  * the monster can put everything on at once; otherwise, wearing takes time.
305  |  * This doesn't affect monster searching for objects--a monster may very well
306  |  * search for objects it would not want to wear, because we don't want to
307  |  * check which_armor() each round.
308  |  *
309  |  * We'll let monsters put on shirts and/or suits under worn cloaks, but
310  |  * not shirts under worn suits.  This is somewhat arbitrary, but it's
311  |  * too tedious to have them remove and later replace outer garments,
312  |  * and preventing suits under cloaks makes it a little bit too easy for
313  |  * players to influence what gets worn.  Putting on a shirt underneath
314  |  * already worn body armor is too obviously buggy...
315  |  */
316  | void
317  | m_dowear(mon, creation)
318  | register struct monst *mon;
319  | boolean creation;
320  | {
321  | 	/* Note the restrictions here are the same as in dowear in do_wear.c
322  | 	 * except for the additional restriction on intelligence.  (Players
323  | 	 * are always intelligent, even if polymorphed).
324  | 	 */
325  | 	if (verysmall(mon->data) || nohands(mon->data) || is_animal(mon->data))
326  | 		return;
327  | 	/* give mummies a chance to wear their wrappings */
328  | 	if (mindless(mon->data) && (mon->data->mlet != S_MUMMY || !creation))
329  | 		return;
330  | 
331  | 	m_dowear_type(mon, W_AMUL, creation);
332  | #ifdef TOURIST
333  | 	/* can't put on shirt if already wearing suit */
334  | 	if (!cantweararm(mon->data) || (mon->misc_worn_check & W_ARM))
335  | 	    m_dowear_type(mon, W_ARMU, creation);
336  | #endif
337  | 	/* treating small as a special case allows
338  | 	   hobbits, gnomes, and kobolds to wear cloaks */
339  | 	if (!cantweararm(mon->data) || mon->data->msize == MZ_SMALL)
340  | 	    m_dowear_type(mon, W_ARMC, creation);
341  | 	m_dowear_type(mon, W_ARMH, creation);
342  | 	if (!MON_WEP(mon) || !bimanual(MON_WEP(mon)))
343  | 	    m_dowear_type(mon, W_ARMS, creation);
344  | 	m_dowear_type(mon, W_ARMG, creation);
345  | 	if (!slithy(mon->data) && mon->data->mlet != S_CENTAUR)
346  | 	    m_dowear_type(mon, W_ARMF, creation);
347  | 	if (!cantweararm(mon->data))
348  | 	    m_dowear_type(mon, W_ARM, creation);
349  | }
350  | 
351  | STATIC_OVL void
352  | m_dowear_type(mon, flag, creation)
353  | struct monst *mon;
354  | long flag;
355  | boolean creation;
356  | {
357  | 	struct obj *old, *best, *obj;
358  | 	int m_delay = 0;
359  | 
360  | 	if (mon->mfrozen) return; /* probably putting previous item on */
361  | 
362  | 	old = which_armor(mon, flag);
363  | 	if (old && old->cursed) return;
364  | 	if (old && flag == W_AMUL) return; /* no such thing as better amulets */
365  | 	best = old;
366  | 
367  | 	for(obj = mon->minvent; obj; obj = obj->nobj) {
368  | 	    switch(flag) {
369  | 		case W_AMUL:
370  | 		    if (obj->oclass != AMULET_CLASS ||
371  | 			    (obj->otyp != AMULET_OF_LIFE_SAVING &&
372  | 				obj->otyp != AMULET_OF_REFLECTION))
373  | 			continue;
374  | 		    best = obj;
375  | 		    goto outer_break; /* no such thing as better amulets */
376  | #ifdef TOURIST
377  | 		case W_ARMU:
378  | 		    if (!is_shirt(obj)) continue;
379  | 		    break;
380  | #endif
381  | 		case W_ARMC:
382  | 		    if (!is_cloak(obj)) continue;
383  | 		    break;
384  | 		case W_ARMH:
385  | 		    if (!is_helmet(obj)) continue;
386  | 		    break;
387  | 		case W_ARMS:
388  | 		    if (!is_shield(obj)) continue;
389  | 		    break;
390  | 		case W_ARMG:
391  | 		    if (!is_gloves(obj)) continue;
392  | 		    break;
393  | 		case W_ARMF:
394  | 		    if (!is_boots(obj)) continue;
395  | 		    break;
396  | 		case W_ARM:
397  | 		    if (!is_suit(obj)) continue;
398  | 		    break;
399  | 	    }
400  | 	    if (obj->owornmask) continue;
401  | 	    /* I'd like to define a VISIBLE_ARM_BONUS which doesn't assume the
402  | 	     * monster knows obj->spe, but if I did that, a monster would keep
403  | 	     * switching forever between two -2 caps since when it took off one
404  | 	     * it would forget spe and once again think the object is better
405  | 	     * than what it already has.
406  | 	     */
407  | 	    if (best && (ARM_BONUS(best) >= ARM_BONUS(obj))) continue;
408  | 	    best = obj;
409  | 	}
410  | outer_break:
411  | 	if (!best || best == old) return;
412  | 
413  | 	/* if wearing a cloak, account for the time spent removing
414  | 	   and re-wearing it when putting on a suit or shirt */
415  | 	if ((flag == W_ARM
416  | #ifdef TOURIST
417  | 	  || flag == W_ARMU
418  | #endif
419  | 			  ) && (mon->misc_worn_check & W_ARMC))
420  | 	    m_delay += 2;
421  | 	/* when upgrading a piece of armor, account for time spent
422  | 	   taking off current one */
423  | 	if (old)
424  | 	    m_delay += objects[old->otyp].oc_delay;
425  | 
426  | 	if (old) /* do this first to avoid "(being worn)" */
427  | 	    old->owornmask = 0L;
428  | 	if (!creation) {
429  | 	    if (canseemon(mon)) {
430  | 		char buf[BUFSZ];
431  | 
432  | 		if (old)
433  | 		    Sprintf(buf, " removes %s and", distant_name(old, doname));
434  | 		else
435  | 		    buf[0] = '\0';
436  | 		pline("%s%s puts on %s.", Monnam(mon),
437  | 		      buf, distant_name(best,doname));
438  | 	    } /* can see it */
439  | 	    m_delay += objects[best->otyp].oc_delay;
440  | 	    mon->mfrozen = m_delay;
441  | 	    if (mon->mfrozen) mon->mcanmove = 0;
442  | 	}
443  | 	if (old)
444  | 	    update_mon_intrinsics(mon, old, FALSE);
445  | 	mon->misc_worn_check |= flag;
446  | 	best->owornmask |= flag;
447  | 	update_mon_intrinsics(mon, best, TRUE);
448  | }
449  | 
450  | struct obj *
451  | which_armor(mon, flag)
452  | struct monst *mon;
453  | long flag;
454  | {
455  | 	register struct obj *obj;
456  | 
457  | 	for(obj = mon->minvent; obj; obj = obj->nobj)
458  | 		if (obj->owornmask & flag) return obj;
459  | 	return((struct obj *)0);
460  | }
461  | 
462  | /* remove an item of armor and then drop it */
463  | STATIC_OVL void
464  | m_lose_armor(mon, obj)
465  | struct monst *mon;
466  | struct obj *obj;
467  | {
468  | 	mon->misc_worn_check &= ~obj->owornmask;
469  | 	obj->owornmask = 0L;
470  | 	update_mon_intrinsics(mon, obj, FALSE);
471  | 
472  | 	obj_extract_self(obj);
473  | 	place_object(obj, mon->mx, mon->my);
474  | 	/* call stackobj() if we ever drop anything that can merge */
475  | 	newsym(mon->mx, mon->my);
476  | }
477  | 
478  | void
479  | mon_break_armor(mon)
480  | struct monst *mon;
481  | {
482  | 	register struct obj *otmp;
483  | 	struct permonst *mdat = mon->data;
484  | 	boolean vis = cansee(mon->mx, mon->my);
485  | 	const char *pronoun = him[pronoun_gender(mon)],
486  | 			*ppronoun = his[pronoun_gender(mon)];
487  | 
488  | 	if (breakarm(mdat)) {
489  | 	    if ((otmp = which_armor(mon, W_ARM)) != 0) {
490  | 		if (vis)
491  | 		    pline("%s breaks out of %s armor!", Monnam(mon), ppronoun);
492  | 		else
493  | 		    You_hear("a cracking sound.");
494  | 		m_useup(mon, otmp);
495  | 	    }
496  | 	    if ((otmp = which_armor(mon, W_ARMC)) != 0) {
497  | 		if (otmp->oartifact) {
498  | 		    if (vis)
499  | 			pline("%s cloak falls off!", s_suffix(Monnam(mon)));
500  | 		    m_lose_armor(mon, otmp);
501  | 		} else {
502  | 		    if (vis)
503  | 			pline("%s cloak tears apart!", s_suffix(Monnam(mon)));
504  | 		    else
505  | 			You_hear("a ripping sound.");
506  | 		    m_useup(mon, otmp);
507  | 		}
508  | 	    }
509  | #ifdef TOURIST
510  | 	    if ((otmp = which_armor(mon, W_ARMU)) != 0) {
511  | 		if (vis)
512  | 		    pline("%s shirt rips to shreds!", s_suffix(Monnam(mon)));
513  | 		else
514  | 		    You_hear("a ripping sound.");
515  | 		m_useup(mon, otmp);
516  | 	    }
517  | #endif
518  | 	} else if (sliparm(mdat)) {
519  | 	    if ((otmp = which_armor(mon, W_ARM)) != 0) {
520  | 		if (vis)
521  | 		    pline("%s armor falls around %s!",
522  | 				 s_suffix(Monnam(mon)), pronoun);
523  | 		else
524  | 		    You_hear("a thud.");
525  | 		m_lose_armor(mon, otmp);
526  | 	    }
527  | 	    if ((otmp = which_armor(mon, W_ARMC)) != 0) {
528  | 		if (vis) {
529  | 		    if (is_whirly(mon->data))
530  | 			pline("%s cloak falls, unsupported!",
531  | 				     s_suffix(Monnam(mon)));
532  | 		    else
533  | 			pline("%s shrinks out of %s cloak!", Monnam(mon),
534  | 								ppronoun);
535  | 		}
536  | 		m_lose_armor(mon, otmp);
537  | 	    }
538  | #ifdef TOURIST
539  | 	    if ((otmp = which_armor(mon, W_ARMU)) != 0) {
540  | 		if (vis) {
541  | 		    if (sliparm(mon->data))
542  | 			pline("%s seeps right through %s shirt!",
543  | 					Monnam(mon), ppronoun);
544  | 		    else
545  | 			pline("%s becomes much too small for %s shirt!",
546  | 					Monnam(mon), ppronoun);
547  | 		}
548  | 		m_lose_armor(mon, otmp);
549  | 	    }
550  | #endif
551  | 	}
552  | 	if (nohands(mdat) || verysmall(mdat)) {
553  | 	    if ((otmp = which_armor(mon, W_ARMG)) != 0) {
554  | 		if (vis)
555  | 		    pline("%s drops %s gloves%s!", Monnam(mon), ppronoun,
556  | 					MON_WEP(mon) ? " and weapon" : "");
557  | 		possibly_unwield(mon);
558  | 		m_lose_armor(mon, otmp);
559  | 	    }
560  | 	    if ((otmp = which_armor(mon, W_ARMS)) != 0) {
561  | 		if (vis)
562  | 		    pline("%s can no longer hold %s shield!", Monnam(mon),
563  | 								ppronoun);
564  | 		else
565  | 		    You_hear("a clank.");
566  | 		m_lose_armor(mon, otmp);
567  | 	    }
568  | 	    if ((otmp = which_armor(mon, W_ARMH)) != 0) {
569  | 		if (vis)
570  | 		    pline("%s helmet falls to the %s!",
571  | 			  s_suffix(Monnam(mon)), surface(mon->mx, mon->my));
572  | 		else
573  | 		    You_hear("a clank.");
574  | 		m_lose_armor(mon, otmp);
575  | 	    }
576  | 	}
577  | 	if (nohands(mdat) || verysmall(mdat) || slithy(mdat) ||
578  | 	    mdat->mlet == S_CENTAUR) {
579  | 	    if ((otmp = which_armor(mon, W_ARMF)) != 0) {
580  | 		if (vis) {
581  | 		    if (is_whirly(mon->data))
582  | 			pline("%s boots fall away!",
583  | 				       s_suffix(Monnam(mon)));
584  | 		    else pline("%s boots %s off %s feet!",
585  | 			s_suffix(Monnam(mon)),
586  | 			verysmall(mdat) ? "slide" : "are pushed", ppronoun);
587  | 		}
588  | 		m_lose_armor(mon, otmp);
589  | 	    }
590  | 	}
591  | #ifdef STEED
592  | 	if (!can_saddle(mon)) {
593  | 	    if ((otmp = which_armor(mon, W_SADDLE)) != 0) {
594  | 		m_lose_armor(mon, otmp);
595  | 		if (vis)
596  | 		    pline("%s saddle falls off.", s_suffix(Monnam(mon)));
597  | 	    }
598  | 	    if (mon == u.usteed)
599  | 		goto noride;
600  | 	} else if (mon == u.usteed && !can_ride(mon)) {
601  | 	noride:
602  | 	    You("can no longer ride %s.", mon_nam(mon));
603  | 	    if (touch_petrifies(u.usteed->data) &&
604  | 			!Stone_resistance && rnl(3)) {
605  | 		char buf[BUFSZ];
606  | 
607  | 		You("touch %s.", mon_nam(u.usteed));
608  | 		Sprintf(buf, "falling off %s",
609  | 				an(u.usteed->data->mname));
610  | 		instapetrify(buf);
611  | 	    }
612  | 	    dismount_steed(DISMOUNT_FELL);
613  | 	}
614  | #endif
615  | 	return;
616  | }
617  | 
618  | /*worn.c*/