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. */
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
*);
25 { W_SWAPWEP
, &uswapwep
},
26 { W_QUIVER
, &uquiver
},
28 { W_IMPLANT
, &uimplant
},
32 { W_SADDLE
, &usaddle
},
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.
53 register struct obj
*obj
;
56 register const struct worn
*wp
;
57 register struct obj
*oobj
;
60 if ((mask
& (W_ARM
|I_SPECIAL
)) == (W_ARM
|I_SPECIAL
)) {
61 /* restoring saved game; no properties are conferred via skin */
63 /* assert( !uarm ); */
65 for(wp
= worn
; wp
->w_mask
; wp
++) if(wp
->w_mask
& mask
) {
67 if(oobj
&& !(oobj
->owornmask
& wp
->w_mask
))
68 pline("Setworn: mask = %ld.", wp
->w_mask
);
70 if (u
.twoweap
&& (oobj
->owornmask
& (W_WEP
|W_SWAPWEP
)) && uwep
&& bimanual(uwep
) ) {
72 unwield(uswapwep
, FALSE
);
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
79 p
= objects
[oobj
->otyp
].oc_oprop
;
80 u
.uprops
[p
].extrinsic
=
81 u
.uprops
[p
].extrinsic
& ~wp
->w_mask
;
83 q
= oobj
->enchantment
;
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
;
91 set_artifact_intrinsic(oobj
, 0, mask
);
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
) ||
105 p
= objects
[obj
->otyp
].oc_oprop
;
106 u
.uprops
[p
].extrinsic
=
107 u
.uprops
[p
].extrinsic
| wp
->w_mask
;
109 q
= obj
->enchantment
;
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
;
118 set_artifact_intrinsic(obj
, 1, mask
);
126 /* called e.g. when obj is destroyed */
127 /* KMH, intrinsic patch.
128 * Updated to use the extrinsic and blocked fields.
132 register struct obj
*obj
;
134 register const struct worn
*wp
;
138 if (obj
== uwep
|| obj
== 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
)) {
146 p
= objects
[obj
->otyp
].oc_oprop
;
147 u
.uprops
[p
].extrinsic
= u
.uprops
[p
].extrinsic
& ~wp
->w_mask
;
149 q
= obj
->enchantment
;
151 u
.uprops
[obj
->enchantment
].extrinsic
= u
.uprops
[obj
->enchantment
].extrinsic
& ~wp
->w_mask
;
154 obj
->owornmask
&= ~wp
->w_mask
;
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
;
168 if (!mon
->invis_blkd
) {
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 */
177 mon_adjust_speed(mon
, adjust
, obj
)
179 int adjust
; /* positive => increase speed, negative => decrease */
180 struct obj
*obj
; /* item to make known if effect can be seen */
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
));
193 mon
->permspeed
= MFAST
;
194 give_msg
= FALSE
; /* special case monster creation */
197 if (mon
->permspeed
== MSLOW
) mon
->permspeed
= 0;
198 else mon
->permspeed
= MFAST
;
200 case 0: /* just check for worn speed boots */
203 if (mon
->permspeed
== MFAST
) mon
->permspeed
= 0;
204 else mon
->permspeed
= MSLOW
;
207 mon
->permspeed
= MSLOW
;
208 give_msg
= FALSE
; /* (not currently used) */
210 case -3: /* petrification */
211 /* take away intrinsic speed but don't reduce normal speed */
212 if (mon
->permspeed
== MFAST
) mon
->permspeed
= 0;
217 for (otmp
= mon
->minvent
; otmp
; otmp
= otmp
->nobj
)
218 if (otmp
->owornmask
&& objects
[otmp
->otyp
].oc_oprop
== FAST
)
220 if (otmp
) /* speed boots */
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
) ?
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
);
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 */
249 update_mon_intrinsics(mon
, obj
, on
, silently
)
252 boolean on
, silently
;
257 int which
= (int) objects
[obj
->otyp
].oc_oprop
;
259 unseen
= !canseemon(mon
);
260 if (!which
) goto maybe_blocks
;
265 mon
->minvis
= !mon
->invis_blkd
;
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
;
275 /* properties handled elsewhere */
279 /* properties which have no effect for monsters */
284 /* properties which should have an effect but aren't implemented */
288 /* properties which maybe should have an effect but don't */
295 mon
->mintrinsics
|= MR_DRAIN
;
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
;
308 mon
->minvis
= mon
->perminvis
;
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
;
329 mask
= (uchar
) (1 << (which
- 1));
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
)
341 mon
->mintrinsics
&= ~mask
;
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)) {
355 mon
->invis_blkd
= on
? 1 : 0;
356 mon
->minvis
= on
? 0 : mon
->perminvis
;
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
);
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
;
397 monweapon
= MON_WEP(mon
);
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 */
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;
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;
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;
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;
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;
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;
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;
501 base
= 10 - acamount
;
505 /* Monsters with too good AC should not be completely unhittable. --Amy */
507 int absoluteac
= (-(base
- 10));
508 if (absoluteac
< 0) absoluteac
*= -1;
509 if ((absoluteac
/ 2) > 0) base
+= rnd(absoluteac
/ 2);
511 if (base
> 10) base
= 10;
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...
533 m_dowear(mon
, creation
)
534 register struct monst
*mon
;
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))
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])))
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
);
572 m_dowear_type(mon
, W_ARM
, creation
, RACE_EXCEPTION
);
576 m_dowear_type(mon
, flag
, creation
, racialexception
)
580 boolean racialexception
;
582 struct obj
*old
, *best
, *obj
;
584 int unseen
= !canseemon(mon
);
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 */
603 for(obj
= mon
->minvent
; obj
; obj
= obj
->nobj
) {
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
))
611 goto outer_break
; /* no such thing as better amulets */
613 if (!is_shirt(obj
)) continue;
616 if (obj
->otyp
!= RIN_TIMELY_BACKUP
) continue;
618 goto outer_break
; /* no such thing as better rings */
620 if (obj
->otyp
!= RIN_TIMELY_BACKUP
) continue;
622 goto outer_break
; /* no such thing as better rings */
624 if (obj
->otyp
!= RIN_TIMELY_BACKUP
) continue;
626 goto outer_break
; /* no such thing as better rings */
628 if (!is_cloak(obj
)) continue;
631 if (!is_helmet(obj
)) continue;
632 /* (flimsy exception matches polyself handling) */
633 if (!creation
&& has_horns(mon
->data
) && !is_flimsy(obj
)) continue;
636 if (MON_WEP(mon
) && bimanual(MON_WEP(mon
)) && obj
->otyp
!= GRIM_SHIELD
) continue;
637 if (!is_shield(obj
)) continue;
640 if (!is_gloves(obj
)) continue;
643 if (!is_boots(obj
)) continue;
646 if (!is_suit(obj
)) continue;
647 if (!creation
&& racialexception
&& (racial_exception(mon
, obj
) < 1)) continue;
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
)))
662 if (FemtrapActiveKatia
&& mon
->data
->msound
== MS_FART_LOUD
&& best
&& itemhasappearance(best
, APP_BLOCK_HEELED_BOOTS
)) continue;
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 */
673 ) && (mon
->misc_worn_check
& W_ARMC
))
675 /* when upgrading a piece of armor, account for time spent
676 taking off current one */
678 m_delay
+= objects
[old
->otyp
].oc_delay
;
680 if (old
) /* do this first to avoid "(being worn)" */
683 if (canseemon(mon
)) {
687 sprintf(buf
, " removes %s and", distant_name(old
, doname
));
690 pline("%s%s puts on %s.", Monnam(mon
),
691 buf
, distant_name(best
,doname
));
693 m_delay
+= objects
[best
->otyp
].oc_delay
;
694 mon
->mfrozen
= m_delay
;
695 if (mon
->mfrozen
) mon
->mcanmove
= 0;
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
713 which_armor(mon
, 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 */
726 m_lose_armor(mon
, obj
)
730 mon
->misc_worn_check
&= ~obj
->owornmask
;
732 update_mon_intrinsics(mon
, obj
, FALSE
, FALSE
);
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 */
745 struct obj
*otmp
, *nobj
;
748 for (otmp
= fobj
; otmp
; otmp
= nobj
) {
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 */
757 if (objects
[otmp
->otyp
].oc_merge
) {
760 (void) get_obj_location(otmp
, &ox
, &oy
, 0);
767 /* invent and mydogs chains shouldn't matter here */
768 for (otmp
= migrating_objs
; otmp
; otmp
= otmp
->nobj
)
770 for (mtmp
= fmon
; mtmp
; mtmp
= mtmp
->nmon
) {
771 if (DEADMONSTER(mtmp
)) continue;
772 for (otmp
= mtmp
->minvent
; otmp
; otmp
= otmp
->nobj
)
775 for (mtmp
= migrating_mons
; mtmp
; mtmp
= mtmp
->nmon
) {
776 for (otmp
= mtmp
->minvent
; otmp
; otmp
= otmp
->nobj
)
779 flags
.bypasses
= FALSE
;
787 flags
.bypasses
= TRUE
;
791 mon_break_armor(mon
, 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 */
811 pline("%s breaks out of %s armor!", Monnam(mon
), ppronoun
);
813 You_hear("a cracking sound.");
816 if ((otmp
= which_armor(mon
, W_ARMC
)) != 0) {
817 if (otmp
->oartifact
) {
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
);
825 pline("%s %s tears apart!", s_suffix(Monnam(mon
)),
826 cloak_simple_name(otmp
));
828 You_hear("a ripping sound.");
832 if ((otmp
= which_armor(mon
, W_ARMU
)) != 0) {
834 pline("%s shirt rips to shreds!", s_suffix(Monnam(mon
)));
836 You_hear("a ripping sound.");
839 } else if (sliparm(mdat
)) {
840 if ((otmp
= which_armor(mon
, W_ARM
)) != 0) {
842 pline("%s armor falls around %s!",
843 s_suffix(Monnam(mon
)), pronoun
);
846 if (polyspot
) bypass_obj(otmp
);
847 m_lose_armor(mon
, otmp
);
849 if ((otmp
= which_armor(mon
, W_ARMC
)) != 0) {
851 if (is_whirly(mon
->data
))
852 pline("%s %s falls, unsupported!",
853 s_suffix(Monnam(mon
)), cloak_simple_name(otmp
));
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) {
863 if (sliparm(mon
->data
))
864 pline("%s seeps right through %s shirt!",
865 Monnam(mon
), ppronoun
);
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) {
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) {
885 pline("%s can no longer hold %s shield!", Monnam(mon
),
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
))) {
898 pline("%s helmet falls to the %s!",
899 s_suffix(Monnam(mon
)), surface(mon
->mx
, mon
->my
));
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) {
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
);
925 pline("%s saddle falls off.", s_suffix(Monnam(mon
)));
929 } else if (mon
== u
.usteed
&& !can_ride(mon
)) {
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)) {
935 You("touch %s.", mon_nam(u
.usteed
));
936 sprintf(buf
, "falling off a petrifying steed");
939 dismount_steed(DISMOUNT_FELL
);
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 */
953 if (obj
->otyp
== SPEED_BOOTS
&& mon
->permspeed
!= MFAST
)
960 * Exceptions to things based on race. Correctly checks polymorphed player race.
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
)
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
))
978 /* sporkhack gnomish suit - somehow never got worn by actual gnomes... --Amy */
979 if (is_gnome(ptr
) && is_gnomish_armor(obj
))
982 /* Unacceptable Exceptions: */
983 /* Checks for object that certain races should never use go here */