1 /* NetHack 3.6 uhitm.c $NHDT-Date: 1446887537 2015/11/07 09:12:17 $ $NHDT-Branch: master $:$NHDT-Revision: 1.151 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed. See license for details. */
7 STATIC_DCL boolean
FDECL(known_hitum
, (struct monst
*, struct obj
*, int *,
8 int, int, struct attack
*));
9 STATIC_DCL boolean
FDECL(theft_petrifies
, (struct obj
*));
10 STATIC_DCL
void FDECL(steal_it
, (struct monst
*, struct attack
*));
11 STATIC_DCL boolean
FDECL(hitum
, (struct monst
*, struct attack
*));
12 STATIC_DCL boolean
FDECL(hmon_hitmon
, (struct monst
*, struct obj
*, int));
13 STATIC_DCL
int FDECL(joust
, (struct monst
*, struct obj
*));
14 STATIC_DCL
void NDECL(demonpet
);
15 STATIC_DCL boolean
FDECL(m_slips_free
, (struct monst
* mtmp
,
16 struct attack
*mattk
));
17 STATIC_DCL
int FDECL(explum
, (struct monst
*, struct attack
*));
18 STATIC_DCL
void FDECL(start_engulf
, (struct monst
*));
19 STATIC_DCL
void NDECL(end_engulf
);
20 STATIC_DCL
int FDECL(gulpum
, (struct monst
*, struct attack
*));
21 STATIC_DCL boolean
FDECL(hmonas
, (struct monst
*));
22 STATIC_DCL
void FDECL(nohandglow
, (struct monst
*));
23 STATIC_DCL boolean
FDECL(shade_aware
, (struct obj
*));
25 extern boolean notonhead
; /* for long worms */
26 /* The below might become a parameter instead if we use it a lot */
28 /* Used to flag attacks caused by Stormbringer's maliciousness. */
29 static boolean override_confirmation
= FALSE
;
31 #define PROJECTILE(obj) ((obj) && is_ammo(obj))
34 erode_armor(mdef
, hurt
)
40 /* What the following code does: it keeps looping until it
41 * finds a target for the rust monster.
42 * Head, feet, etc... not covered by metal, or covered by
43 * rusty metal, are not targets. However, your body always
44 * is, no matter what covers it.
49 target
= which_armor(mdef
, W_ARMH
);
51 || erode_obj(target
, xname(target
), hurt
, EF_GREASE
)
56 target
= which_armor(mdef
, W_ARMC
);
58 (void) erode_obj(target
, xname(target
), hurt
,
59 EF_GREASE
| EF_VERBOSE
);
62 if ((target
= which_armor(mdef
, W_ARM
)) != (struct obj
*) 0) {
63 (void) erode_obj(target
, xname(target
), hurt
,
64 EF_GREASE
| EF_VERBOSE
);
65 } else if ((target
= which_armor(mdef
, W_ARMU
))
66 != (struct obj
*) 0) {
67 (void) erode_obj(target
, xname(target
), hurt
,
68 EF_GREASE
| EF_VERBOSE
);
72 target
= which_armor(mdef
, W_ARMS
);
74 || erode_obj(target
, xname(target
), hurt
, EF_GREASE
)
79 target
= which_armor(mdef
, W_ARMG
);
81 || erode_obj(target
, xname(target
), hurt
, EF_GREASE
)
86 target
= which_armor(mdef
, W_ARMF
);
88 || erode_obj(target
, xname(target
), hurt
, EF_GREASE
)
93 break; /* Out of while loop */
97 /* FALSE means it's OK to attack */
99 attack_checks(mtmp
, wep
)
100 register struct monst
*mtmp
;
101 struct obj
*wep
; /* uwep for attack(), null for kick_monster() */
105 /* if you're close enough to attack, alert any waiting monster */
106 mtmp
->mstrategy
&= ~STRAT_WAITMASK
;
108 if (u
.uswallow
&& mtmp
== u
.ustuck
)
111 if (context
.forcefight
) {
112 /* Do this in the caller, after we checked that the monster
113 * didn't die from the blow. Reason: putting the 'I' there
114 * causes the hero to forget the square's contents since
115 * both 'I' and remembered contents are stored in .glyph.
116 * If the monster dies immediately from the blow, the 'I' will
117 * not stay there, so the player will have suddenly forgotten
118 * the square's contents for no apparent reason.
119 if (!canspotmon(mtmp)
120 && !glyph_is_invisible(levl[bhitpos.x][bhitpos.y].glyph))
121 map_invisible(bhitpos.x, bhitpos.y);
126 /* Put up an invisible monster marker, but with exceptions for
127 * monsters that hide and monsters you've been warned about.
128 * The former already prints a warning message and
129 * prevents you from hitting the monster just via the hidden monster
130 * code below; if we also did that here, similar behavior would be
131 * happening two turns in a row. The latter shows a glyph on
132 * the screen, so you know something is there.
134 if (!canspotmon(mtmp
) && !glyph_is_warning(glyph_at(bhitpos
.x
, bhitpos
.y
))
135 && !glyph_is_invisible(levl
[bhitpos
.x
][bhitpos
.y
].glyph
)
136 && !(!Blind
&& mtmp
->mundetected
&& hides_under(mtmp
->data
))) {
137 pline("Wait! There's %s there you can't see!", something
);
138 map_invisible(bhitpos
.x
, bhitpos
.y
);
139 /* if it was an invisible mimic, treat it as if we stumbled
140 * onto a visible mimic
142 if (mtmp
->m_ap_type
&& !Protection_from_shape_changers
143 /* applied pole-arm attack is too far to get stuck */
144 && distu(mtmp
->mx
, mtmp
->my
) <= 2) {
145 if (!u
.ustuck
&& !mtmp
->mflee
&& dmgtype(mtmp
->data
, AD_STCK
))
148 wakeup(mtmp
); /* always necessary; also un-mimics mimics */
152 if (mtmp
->m_ap_type
&& !Protection_from_shape_changers
&& !sensemon(mtmp
)
153 && !glyph_is_warning(glyph_at(bhitpos
.x
, bhitpos
.y
))) {
154 /* If a hidden mimic was in a square where a player remembers
155 * some (probably different) unseen monster, the player is in
156 * luck--he attacks it even though it's hidden.
158 if (glyph_is_invisible(levl
[mtmp
->mx
][mtmp
->my
].glyph
)) {
162 stumble_onto_mimic(mtmp
);
166 if (mtmp
->mundetected
&& !canseemon(mtmp
)
167 && !glyph_is_warning(glyph_at(bhitpos
.x
, bhitpos
.y
))
168 && (hides_under(mtmp
->data
) || mtmp
->data
->mlet
== S_EEL
)) {
169 mtmp
->mundetected
= mtmp
->msleeping
= 0;
170 newsym(mtmp
->mx
, mtmp
->my
);
171 if (glyph_is_invisible(levl
[mtmp
->mx
][mtmp
->my
].glyph
)) {
175 if (!((Blind
? Blind_telepat
: Unblind_telepat
) || Detect_monsters
)) {
178 if (Blind
|| (is_pool(mtmp
->mx
, mtmp
->my
) && !Underwater
))
179 pline("Wait! There's a hidden monster there!");
180 else if ((obj
= level
.objects
[mtmp
->mx
][mtmp
->my
]) != 0)
181 pline("Wait! There's %s hiding under %s!",
182 an(l_monnam(mtmp
)), doname(obj
));
188 * make sure to wake up a monster from the above cases if the
189 * hero can sense that the monster is there.
191 if ((mtmp
->mundetected
|| mtmp
->m_ap_type
) && sensemon(mtmp
)) {
192 mtmp
->mundetected
= 0;
196 if (flags
.confirm
&& mtmp
->mpeaceful
&& !Confusion
&& !Hallucination
198 /* Intelligent chaotic weapons (Stormbringer) want blood */
199 if (wep
&& wep
->oartifact
== ART_STORMBRINGER
) {
200 override_confirmation
= TRUE
;
203 if (canspotmon(mtmp
)) {
204 Sprintf(qbuf
, "Really attack %s?", mon_nam(mtmp
));
205 if (!paranoid_query(ParanoidHit
, qbuf
)) {
216 * It is unchivalrous for a knight to attack the defenseless or from behind.
222 if (u
.ualign
.record
<= -10)
225 if (Role_if(PM_KNIGHT
) && u
.ualign
.type
== A_LAWFUL
226 && (!mtmp
->mcanmove
|| mtmp
->msleeping
227 || (mtmp
->mflee
&& !mtmp
->mavenge
))) {
230 } else if (Role_if(PM_SAMURAI
) && mtmp
->mpeaceful
) {
231 /* attacking peaceful creatures is bad for the samurai's giri */
232 You("dishonorably attack the innocent!");
238 find_roll_to_hit(mtmp
, aatyp
, weapon
, attk_count
, role_roll_penalty
)
239 register struct monst
*mtmp
;
240 uchar aatyp
; /* usually AT_WEAP or AT_KICK */
241 struct obj
*weapon
; /* uwep or uswapwep or NULL */
242 int *attk_count
, *role_roll_penalty
;
246 *role_roll_penalty
= 0; /* default is `none' */
248 tmp
= 1 + Luck
+ abon() + find_mac(mtmp
) + u
.uhitinc
249 + maybe_polyd(youmonst
.data
->mlevel
, u
.ulevel
);
251 /* some actions should occur only once during multiple attacks */
252 if (!(*attk_count
)++) {
253 /* knight's chivalry or samurai's giri */
257 /* adjust vs. (and possibly modify) monster state */
263 if (mtmp
->msleeping
) {
267 if (!mtmp
->mcanmove
) {
275 /* role/race adjustments */
276 if (Role_if(PM_MONK
) && !Upolyd
) {
278 tmp
-= (*role_roll_penalty
= urole
.spelarmr
);
279 else if (!uwep
&& !uarms
)
280 tmp
+= (u
.ulevel
/ 3) + 2;
282 if (is_orc(mtmp
->data
)
283 && maybe_polyd(is_elf(youmonst
.data
), Race_if(PM_ELF
)))
286 /* encumbrance: with a lot of luggage, your agility diminishes */
287 if ((tmp2
= near_capacity()) != 0)
288 tmp
-= (tmp2
* 2) - 1;
293 * hitval applies if making a weapon attack while wielding a weapon;
294 * weapon_hit_bonus applies if doing a weapon attack even bare-handed
295 * or if kicking as martial artist
297 if (aatyp
== AT_WEAP
|| aatyp
== AT_CLAW
) {
299 tmp
+= hitval(weapon
, mtmp
);
300 tmp
+= weapon_hit_bonus(weapon
);
301 } else if (aatyp
== AT_KICK
&& martial_bonus()) {
302 tmp
+= weapon_hit_bonus((struct obj
*) 0);
308 /* try to attack; return False if monster evaded;
309 u.dx and u.dy must be set */
312 register struct monst
*mtmp
;
314 register struct permonst
*mdat
= mtmp
->data
;
316 /* This section of code provides protection against accidentally
317 * hitting peaceful (like '@') and tame (like 'd') monsters.
318 * Protection is provided as long as player is not: blind, confused,
319 * hallucinating or stunned.
320 * changes by wwp 5/16/85
321 * More changes 12/90, -dkh-. if its tame and safepet, (and protected
322 * 07/92) then we assume that you're not trying to attack. Instead,
323 * you'll usually just swap places if this is a movement command
325 /* Intelligent chaotic weapons (Stormbringer) want blood */
326 if (is_safepet(mtmp
) && !context
.forcefight
) {
327 if (!uwep
|| uwep
->oartifact
!= ART_STORMBRINGER
) {
328 /* there are some additional considerations: this won't work
329 * if in a shop or Punished or you miss a random roll or
330 * if you can walk thru walls and your pet cannot (KAA) or
331 * if your pet is a long worm (unless someone does better).
332 * there's also a chance of displacing a "frozen" monster.
333 * sleeping monsters might magically walk in their sleep.
335 boolean foo
= (Punished
|| !rn2(7) || is_longworm(mtmp
->data
)),
339 for (p
= in_rooms(mtmp
->mx
, mtmp
->my
, SHOPBASE
); *p
; p
++)
340 if (tended_shop(&rooms
[*p
- ROOMOFFSET
])) {
345 if (inshop
|| foo
|| (IS_ROCK(levl
[u
.ux
][u
.uy
].typ
)
346 && !passes_walls(mtmp
->data
))) {
349 monflee(mtmp
, rnd(6), FALSE
, FALSE
);
350 Strcpy(buf
, y_monnam(mtmp
));
351 buf
[0] = highc(buf
[0]);
352 You("stop. %s is in the way!", buf
);
353 context
.travel
= context
.travel1
= context
.mv
= context
.run
= 0;
355 } else if ((mtmp
->mfrozen
|| (!mtmp
->mcanmove
)
356 || (mtmp
->data
->mmove
== 0)) && rn2(6)) {
357 pline("%s doesn't seem to move!", Monnam(mtmp
));
358 context
.travel
= context
.travel1
= context
.mv
= context
.run
= 0;
365 /* possibly set in attack_checks;
366 examined in known_hitum, called via hitum or hmonas below */
367 override_confirmation
= FALSE
;
368 /* attack_checks() used to use <u.ux+u.dx,u.uy+u.dy> directly, now
369 it uses bhitpos instead; it might map an invisible monster there */
370 bhitpos
.x
= u
.ux
+ u
.dx
;
371 bhitpos
.y
= u
.uy
+ u
.dy
;
372 if (attack_checks(mtmp
, uwep
))
375 if (Upolyd
&& noattacks(youmonst
.data
)) {
376 /* certain "pacifist" monsters don't attack */
377 You("have no way to attack monsters physically.");
378 mtmp
->mstrategy
&= ~STRAT_WAITMASK
;
382 if (check_capacity("You cannot fight while so heavily loaded.")
383 /* consume extra nutrition during combat; maybe pass out */
387 if (u
.twoweap
&& !can_twoweapon())
394 You("begin bashing monsters with %s.",
395 yobjnam(uwep
, (char *) 0));
396 else if (!cantwield(youmonst
.data
))
397 You("begin %sing monsters with your %s %s.",
398 Role_if(PM_MONK
) ? "strik" : "bash",
399 uarmg
? "gloved" : "bare", /* Del Lamb */
400 makeplural(body_part(HAND
)));
403 exercise(A_STR
, TRUE
); /* you're exercising muscles */
404 /* andrew@orca: prevent unlimited pick-axe attacks */
407 /* Is the "it died" check actually correct? */
408 if (mdat
->mlet
== S_LEPRECHAUN
&& !mtmp
->mfrozen
&& !mtmp
->msleeping
409 && !mtmp
->mconf
&& mtmp
->mcansee
&& !rn2(7)
410 && (m_move(mtmp
, 0) == 2 /* it died */
411 || mtmp
->mx
!= u
.ux
+ u
.dx
412 || mtmp
->my
!= u
.uy
+ u
.dy
)) /* it moved */
418 (void) hitum(mtmp
, youmonst
.data
->mattk
);
419 mtmp
->mstrategy
&= ~STRAT_WAITMASK
;
422 /* see comment in attack_checks() */
423 /* we only need to check for this if we did an attack_checks()
424 * and it returned 0 (it's okay to attack), and the monster didn't
427 if (context
.forcefight
&& mtmp
->mhp
> 0 && !canspotmon(mtmp
)
428 && !glyph_is_invisible(levl
[u
.ux
+ u
.dx
][u
.uy
+ u
.dy
].glyph
)
429 && !(u
.uswallow
&& mtmp
== u
.ustuck
))
430 map_invisible(u
.ux
+ u
.dx
, u
.uy
+ u
.dy
);
435 /* really hit target monster; returns TRUE if it still lives */
437 known_hitum(mon
, weapon
, mhit
, rollneeded
, armorpenalty
, uattk
)
438 register struct monst
*mon
;
441 int rollneeded
, armorpenalty
; /* for monks */
442 struct attack
*uattk
;
444 register boolean malive
= TRUE
;
446 if (override_confirmation
) {
447 /* this may need to be generalized if weapons other than
448 Stormbringer acquire similar anti-social behavior... */
450 Your("bloodthirsty blade attacks!");
454 missum(mon
, uattk
, (rollneeded
+ armorpenalty
> dieroll
));
456 int oldhp
= mon
->mhp
, x
= u
.ux
+ u
.dx
, y
= u
.uy
+ u
.dy
;
457 long oldweaphit
= u
.uconduct
.weaphit
;
460 if (weapon
&& (weapon
->oclass
== WEAPON_CLASS
|| is_weptool(weapon
)))
461 u
.uconduct
.weaphit
++;
463 /* we hit the monster; be careful: it might die or
464 be knocked into a different location */
465 notonhead
= (mon
->mx
!= x
|| mon
->my
!= y
);
466 malive
= hmon(mon
, weapon
, HMON_MELEE
);
468 /* monster still alive */
469 if (!rn2(25) && mon
->mhp
< mon
->mhpmax
/ 2
470 && !(u
.uswallow
&& mon
== u
.ustuck
)) {
471 /* maybe should regurgitate if swallowed? */
472 monflee(mon
, !rn2(3) ? rnd(100) : 0, FALSE
, TRUE
);
474 if (u
.ustuck
== mon
&& !u
.uswallow
&& !sticks(youmonst
.data
))
477 /* Vorpal Blade hit converted to miss */
478 /* could be headless monster or worm tail */
479 if (mon
->mhp
== oldhp
) {
481 /* a miss does not break conduct */
482 u
.uconduct
.weaphit
= oldweaphit
;
484 if (mon
->wormno
&& *mhit
)
485 cutworm(mon
, x
, y
, weapon
);
491 /* hit target monster; returns TRUE if it still lives */
495 struct attack
*uattk
;
497 boolean malive
, wep_was_destroyed
= FALSE
;
498 struct obj
*wepbefore
= uwep
;
499 int armorpenalty
, attknum
= 0, x
= u
.ux
+ u
.dx
, y
= u
.uy
+ u
.dy
,
500 tmp
= find_roll_to_hit(mon
, uattk
->aatyp
, uwep
,
501 &attknum
, &armorpenalty
);
502 int mhit
= (tmp
> (dieroll
= rnd(20)) || u
.uswallow
);
505 exercise(A_DEX
, TRUE
);
506 malive
= known_hitum(mon
, uwep
, &mhit
, tmp
, armorpenalty
, uattk
);
507 /* second attack for two-weapon combat; won't occur if Stormbringer
508 overrode confirmation (assumes Stormbringer is primary weapon)
509 or if the monster was killed or knocked to different location */
510 if (u
.twoweap
&& !override_confirmation
&& malive
&& m_at(x
, y
) == mon
) {
511 tmp
= find_roll_to_hit(mon
, uattk
->aatyp
, uswapwep
, &attknum
,
513 mhit
= (tmp
> (dieroll
= rnd(20)) || u
.uswallow
);
514 malive
= known_hitum(mon
, uswapwep
, &mhit
, tmp
, armorpenalty
, uattk
);
516 if (wepbefore
&& !uwep
)
517 wep_was_destroyed
= TRUE
;
518 (void) passive(mon
, mhit
, malive
, AT_WEAP
, wep_was_destroyed
);
522 /* general "damage monster" routine; return True if mon still alive */
524 hmon(mon
, obj
, thrown
)
527 int thrown
; /* HMON_xxx (0 => hand-to-hand, other => ranged) */
529 boolean result
, anger_guards
;
531 anger_guards
= (mon
->mpeaceful
532 && (mon
->ispriest
|| mon
->isshk
|| is_watch(mon
->data
)));
533 result
= hmon_hitmon(mon
, obj
, thrown
);
534 if (mon
->ispriest
&& !rn2(2))
537 (void) angry_guards(!!Deaf
);
543 hmon_hitmon(mon
, obj
, thrown
)
546 int thrown
; /* HMON_xxx (0 => hand-to-hand, other => ranged) */
549 struct permonst
*mdat
= mon
->data
;
550 int barehand_silver_rings
= 0;
551 /* The basic reason we need all these booleans is that we don't want
552 * a "hit" message when a monster dies, so we have to know how much
553 * damage it did _before_ outputting a hit message, but any messages
554 * associated with the damage don't come out until _after_ outputting
557 boolean hittxt
= FALSE
, destroyed
= FALSE
, already_killed
= FALSE
;
558 boolean get_dmg_bonus
= TRUE
;
559 boolean ispoisoned
= FALSE
, needpoismsg
= FALSE
, poiskilled
= FALSE
,
561 boolean silvermsg
= FALSE
, silverobj
= FALSE
;
562 boolean valid_weapon_attack
= FALSE
;
563 boolean unarmed
= !uwep
&& !uarm
&& !uarms
;
564 boolean hand_to_hand
= (thrown
== HMON_MELEE
565 /* not grapnels; applied implies uwep */
566 || (thrown
== HMON_APPLIED
&& is_pole(uwep
)));
570 char unconventional
[BUFSZ
]; /* substituted for word "attack" in msg */
571 char saved_oname
[BUFSZ
];
573 unconventional
[0] = '\0';
574 saved_oname
[0] = '\0';
577 if (!obj
) { /* attack with bare hands */
578 if (mdat
== &mons
[PM_SHADE
])
580 else if (martial_bonus())
581 tmp
= rnd(4); /* bonus for martial arts */
584 valid_weapon_attack
= (tmp
> 1);
585 /* blessed gloves give bonuses when fighting 'bare-handed' */
586 if (uarmg
&& uarmg
->blessed
587 && (is_undead(mdat
) || is_demon(mdat
) || is_vampshifter(mon
)))
589 /* So do silver rings. Note: rings are worn under gloves, so you
590 * don't get both bonuses.
593 if (uleft
&& objects
[uleft
->otyp
].oc_material
== SILVER
)
594 barehand_silver_rings
++;
595 if (uright
&& objects
[uright
->otyp
].oc_material
== SILVER
)
596 barehand_silver_rings
++;
597 if (barehand_silver_rings
&& mon_hates_silver(mon
)) {
603 Strcpy(saved_oname
, cxname(obj
));
604 if (obj
->oclass
== WEAPON_CLASS
|| is_weptool(obj
)
605 || obj
->oclass
== GEM_CLASS
) {
606 /* is it not a melee weapon? */
607 if (/* if you strike with a bow... */
609 /* or strike with a missile in your hand... */
610 || (!thrown
&& (is_missile(obj
) || is_ammo(obj
)))
611 /* or use a pole at short range and not mounted... */
612 || (!thrown
&& !u
.usteed
&& is_pole(obj
))
613 /* or throw a missile without the proper bow... */
614 || (is_ammo(obj
) && (thrown
!= HMON_THROWN
615 || !ammo_and_launcher(obj
, uwep
)))) {
616 /* then do only 1-2 points of damage */
617 if (mdat
== &mons
[PM_SHADE
] && !shade_glare(obj
))
621 if (objects
[obj
->otyp
].oc_material
== SILVER
622 && mon_hates_silver(mon
)) {
625 /* if it will already inflict dmg, make it worse */
626 tmp
+= rnd((tmp
) ? 20 : 10);
628 if (!thrown
&& obj
== uwep
&& obj
->otyp
== BOOMERANG
629 && rnl(4) == 4 - 1) {
630 boolean more_than_1
= (obj
->quan
> 1L);
632 pline("As you hit %s, %s%s breaks into splinters.",
633 mon_nam(mon
), more_than_1
? "one of " : "",
636 uwepgone(); /* set unweapon */
639 obj
= (struct obj
*) 0;
641 if (mdat
!= &mons
[PM_SHADE
])
645 tmp
= dmgval(obj
, mon
);
646 /* a minimal hit doesn't exercise proficiency */
647 valid_weapon_attack
= (tmp
> 1);
648 if (!valid_weapon_attack
|| mon
== u
.ustuck
|| u
.twoweap
) {
649 ; /* no special bonuses */
650 } else if (mon
->mflee
&& Role_if(PM_ROGUE
) && !Upolyd
651 /* multi-shot throwing is too powerful here */
653 You("strike %s from behind!", mon_nam(mon
));
654 tmp
+= rnd(u
.ulevel
);
656 } else if (dieroll
== 2 && obj
== uwep
657 && obj
->oclass
== WEAPON_CLASS
659 || (Role_if(PM_SAMURAI
) && obj
->otyp
== KATANA
661 && ((wtype
= uwep_skill_type()) != P_NONE
662 && P_SKILL(wtype
) >= P_SKILLED
)
663 && ((monwep
= MON_WEP(mon
)) != 0
664 && !is_flimsy(monwep
)
666 monwep
, 50 + 15 * greatest_erosion(obj
),
669 * 2.5% chance of shattering defender's weapon when
670 * using a two-handed weapon; less if uwep is rusted.
671 * [dieroll == 2 is most successful non-beheading or
672 * -bisecting hit, in case of special artifact damage;
673 * the percentage chance is (1/20)*(50/100).]
675 setmnotwielded(mon
, monwep
);
676 mon
->weapon_check
= NEED_WEAPON
;
677 pline("%s from the force of your blow!",
678 Yobjnam2(monwep
, "shatter"));
679 m_useupall(mon
, monwep
);
680 /* If someone just shattered MY weapon, I'd flee! */
682 monflee(mon
, d(2, 3), TRUE
, TRUE
);
688 && artifact_hit(&youmonst
, mon
, obj
, &tmp
, dieroll
)) {
689 if (mon
->mhp
<= 0) /* artifact killed monster */
695 if (objects
[obj
->otyp
].oc_material
== SILVER
696 && mon_hates_silver(mon
)) {
700 if (u
.usteed
&& !thrown
&& tmp
> 0
701 && weapon_type(obj
) == P_LANCE
&& mon
!= u
.ustuck
) {
702 jousting
= joust(mon
, obj
);
703 /* exercise skill even for minimal damage hits */
705 valid_weapon_attack
= TRUE
;
707 if (thrown
== HMON_THROWN
708 && (is_ammo(obj
) || is_missile(obj
))) {
709 if (ammo_and_launcher(obj
, uwep
)) {
710 /* Elves and Samurai do extra damage using
711 * their bows&arrows; they're highly trained.
713 if (Role_if(PM_SAMURAI
) && obj
->otyp
== YA
714 && uwep
->otyp
== YUMI
)
716 else if (Race_if(PM_ELF
) && obj
->otyp
== ELVEN_ARROW
717 && uwep
->otyp
== ELVEN_BOW
)
720 if (obj
->opoisoned
&& is_poisonable(obj
))
724 } else if (obj
->oclass
== POTION_CLASS
) {
726 obj
= splitobj(obj
, 1L);
728 setuwep((struct obj
*) 0);
730 potionhit(mon
, obj
, TRUE
);
732 return FALSE
; /* killed */
734 /* in case potion effect causes transformation */
736 tmp
= (mdat
== &mons
[PM_SHADE
]) ? 0 : 1;
738 if (mdat
== &mons
[PM_SHADE
] && !shade_aware(obj
)) {
740 Strcpy(unconventional
, cxname(obj
));
743 case BOULDER
: /* 1d20 */
744 case HEAVY_IRON_BALL
: /* 1d25 */
745 case IRON_CHAIN
: /* 1d4+1 */
746 tmp
= dmgval(obj
, mon
);
749 if (breaktest(obj
)) {
750 You("break %s. That's bad luck!", ysimple_name(obj
));
753 obj
= (struct obj
*) 0;
754 unarmed
= FALSE
; /* avoid obj==0 confusion */
755 get_dmg_bonus
= FALSE
;
760 case EXPENSIVE_CAMERA
:
761 You("succeed in destroying %s. Congratulations!",
763 release_camera_demon(obj
, u
.ux
, u
.uy
);
766 case CORPSE
: /* fixed by polder@cs.vu.nl */
767 if (touch_petrifies(&mons
[obj
->corpsenm
])) {
770 You("hit %s with %s.", mon_nam(mon
),
771 corpse_xname(obj
, (const char *) 0,
772 obj
->dknown
? CXN_PFX_THE
775 if (!munstone(mon
, TRUE
))
776 minstapetrify(mon
, TRUE
);
777 if (resists_ston(mon
))
779 /* note: hp may be <= 0 even if munstoned==TRUE */
780 return (boolean
) (mon
->mhp
> 0);
782 } else if (touch_petrifies(mdat
)) {
783 ; /* maybe turn the corpse into a statue? */
786 tmp
= (obj
->corpsenm
>= LOW_PM
? mons
[obj
->corpsenm
].msize
790 #define useup_eggs(o) \
793 obfree(o, (struct obj *) 0); \
796 o = (struct obj *) 0; \
799 long cnt
= obj
->quan
;
801 tmp
= 1; /* nominal physical damage */
802 get_dmg_bonus
= FALSE
;
803 hittxt
= TRUE
; /* message always given */
804 /* egg is always either used up or transformed, so next
805 hand-to-hand attack should yield a "bashing" mesg */
808 if (obj
->spe
&& obj
->corpsenm
>= LOW_PM
) {
810 change_luck((schar
) - (obj
->quan
));
815 if (touch_petrifies(&mons
[obj
->corpsenm
])) {
816 /*learn_egg_type(obj->corpsenm);*/
817 pline("Splat! You hit %s with %s %s egg%s!",
819 obj
->known
? "the" : cnt
> 1L ? "some" : "a",
820 obj
->known
? mons
[obj
->corpsenm
].mname
823 obj
->known
= 1; /* (not much point...) */
825 if (!munstone(mon
, TRUE
))
826 minstapetrify(mon
, TRUE
);
827 if (resists_ston(mon
))
829 return (boolean
) (mon
->mhp
> 0);
830 } else { /* ordinary egg(s) */
832 (obj
->corpsenm
!= NON_PM
&& obj
->known
)
833 ? the(mons
[obj
->corpsenm
].mname
)
834 : (cnt
> 1L) ? "some" : "an";
835 You("hit %s with %s egg%s.", mon_nam(mon
), eggp
,
837 if (touch_petrifies(mdat
) && !stale_egg(obj
)) {
838 pline_The("egg%s %s alive any more...", plur(cnt
),
839 (cnt
== 1L) ? "isn't" : "aren't");
841 obj_stop_timers(obj
);
843 obj
->oclass
= GEM_CLASS
;
846 obj
->known
= obj
->dknown
= obj
->bknown
= 0;
847 obj
->owt
= weight(obj
);
849 place_object(obj
, mon
->mx
, mon
->my
);
853 exercise(A_WIS
, FALSE
);
859 case CLOVE_OF_GARLIC
: /* no effect against demons */
860 if (is_undead(mdat
) || is_vampshifter(mon
)) {
861 monflee(mon
, d(2, 4), FALSE
, TRUE
);
868 if (can_blnd(&youmonst
, mon
,
869 (uchar
) (obj
->otyp
== BLINDING_VENOM
874 pline(obj
->otyp
== CREAM_PIE
? "Splat!"
876 } else if (obj
->otyp
== BLINDING_VENOM
) {
877 pline_The("venom blinds %s%s!", mon_nam(mon
),
878 mon
->mcansee
? "" : " further");
880 char *whom
= mon_nam(mon
);
881 char *what
= The(xname(obj
));
883 if (!thrown
&& obj
->quan
> 1L)
884 what
= An(singular(obj
, xname
));
885 /* note: s_suffix returns a modifiable buffer */
887 && mdat
!= &mons
[PM_FLOATING_EYE
])
888 whom
= strcat(strcat(s_suffix(whom
), " "),
889 mbodypart(mon
, FACE
));
890 pline("%s %s over %s!", what
,
891 vtense(what
, "splash"), whom
);
896 if (((int) mon
->mblinded
+ tmp
) > 127)
899 mon
->mblinded
+= tmp
;
901 pline(obj
->otyp
== CREAM_PIE
? "Splat!" : "Splash!");
905 obfree(obj
, (struct obj
*) 0);
909 get_dmg_bonus
= FALSE
;
912 case ACID_VENOM
: /* thrown (or spit) */
913 if (resists_acid(mon
)) {
914 Your("venom hits %s harmlessly.", mon_nam(mon
));
917 Your("venom burns %s!", mon_nam(mon
));
918 tmp
= dmgval(obj
, mon
);
921 obfree(obj
, (struct obj
*) 0);
925 get_dmg_bonus
= FALSE
;
928 /* non-weapons can damage because of their weight */
929 /* (but not too much) */
930 tmp
= obj
->owt
/ 100;
931 if (is_wet_towel(obj
)) {
932 /* wielded wet towel should probably use whip skill
933 (but not by setting objects[TOWEL].oc_skill==P_WHIP
934 because that would turn towel into a weptool) */
936 if (rn2(obj
->spe
+ 1)) /* usually lose some wetness */
937 dry_a_towel(obj
, -1, TRUE
);
946 * Things like silver wands can arrive here so
947 * so we need another silver check.
949 if (objects
[obj
->otyp
].oc_material
== SILVER
950 && mon_hates_silver(mon
)) {
960 /****** NOTE: perhaps obj is undefined!! (if !thrown && BOOMERANG)
961 * *OR* if attacking bare-handed!! */
963 if (get_dmg_bonus
&& tmp
> 0) {
965 /* If you throw using a propellor, you don't get a strength
966 * bonus but you do get an increase-damage bonus.
968 if (thrown
!= HMON_THROWN
|| !obj
|| !uwep
969 || !ammo_and_launcher(obj
, uwep
))
973 if (valid_weapon_attack
) {
976 /* to be valid a projectile must have had the correct projector */
977 wep
= PROJECTILE(obj
) ? uwep
: obj
;
978 tmp
+= weapon_dam_bonus(wep
);
979 /* [this assumes that `!thrown' implies wielded...] */
980 wtype
= thrown
? weapon_type(wep
) : uwep_skill_type();
985 int nopoison
= (10 - (obj
->owt
/ 10));
989 if (Role_if(PM_SAMURAI
)) {
990 You("dishonorably use a poisoned weapon!");
991 adjalign(-sgn(u
.ualign
.type
));
992 } else if (u
.ualign
.type
== A_LAWFUL
&& u
.ualign
.record
> -10) {
993 You_feel("like an evil coward for using a poisoned weapon.");
996 if (obj
&& !rn2(nopoison
)) {
997 /* remove poison now in case obj ends up in a bones file */
998 obj
->opoisoned
= FALSE
;
999 /* defer "obj is no longer poisoned" until after hit message */
1002 if (resists_poison(mon
))
1010 /* make sure that negative damage adjustment can't result
1011 in inadvertently boosting the victim's hit points */
1013 if (mdat
== &mons
[PM_SHADE
]) {
1015 const char *what
= *unconventional
? unconventional
: "attack";
1017 Your("%s %s harmlessly through %s.", what
,
1018 vtense(what
, "pass"), mon_nam(mon
));
1028 tmp
+= d(2, (obj
== uwep
) ? 10 : 2); /* [was in dmgval()] */
1029 You("joust %s%s", mon_nam(mon
), canseemon(mon
) ? exclam(tmp
) : ".");
1031 pline("%s shatters on impact!", Yname2(obj
));
1032 /* (must be either primary or secondary weapon to get here) */
1033 u
.twoweap
= FALSE
; /* untwoweapon() is too verbose here */
1035 uwepgone(); /* set unweapon */
1036 /* minor side-effect: broken lance won't split puddings */
1040 /* avoid migrating a dead monster */
1041 if (mon
->mhp
> tmp
) {
1042 mhurtle(mon
, u
.dx
, u
.dy
, 1);
1043 mdat
= mon
->data
; /* in case of a polymorph trap */
1044 if (DEADMONSTER(mon
))
1045 already_killed
= TRUE
;
1048 } else if (unarmed
&& tmp
> 1 && !thrown
&& !obj
&& !Upolyd
) {
1049 /* VERY small chance of stunning opponent if unarmed. */
1050 if (rnd(100) < P_SKILL(P_BARE_HANDED_COMBAT
) && !bigmonst(mdat
)
1051 && !thick_skinned(mdat
)) {
1052 if (canspotmon(mon
))
1053 pline("%s %s from your powerful strike!", Monnam(mon
),
1054 makeplural(stagger(mon
->data
, "stagger")));
1055 /* avoid migrating a dead monster */
1056 if (mon
->mhp
> tmp
) {
1057 mhurtle(mon
, u
.dx
, u
.dy
, 1);
1058 mdat
= mon
->data
; /* in case of a polymorph trap */
1059 if (DEADMONSTER(mon
))
1060 already_killed
= TRUE
;
1066 if (!already_killed
)
1068 /* adjustments might have made tmp become less than what
1069 a level draining artifact has already done to max HP */
1070 if (mon
->mhp
> mon
->mhpmax
)
1071 mon
->mhp
= mon
->mhpmax
;
1074 if (mon
->mtame
&& tmp
> 0) {
1075 /* do this even if the pet is being killed (affects revival) */
1076 abuse_dog(mon
); /* reduces tameness */
1077 /* flee if still alive and still tame; if already suffering from
1078 untimed fleeing, no effect, otherwise increases timed fleeing */
1079 if (mon
->mtame
&& !destroyed
)
1080 monflee(mon
, 10 * rnd(tmp
), FALSE
, FALSE
);
1082 if ((mdat
== &mons
[PM_BLACK_PUDDING
] || mdat
== &mons
[PM_BROWN_PUDDING
])
1083 /* pudding is alive and healthy enough to split */
1084 && mon
->mhp
> 1 && !mon
->mcan
1085 /* iron weapon using melee or polearm hit */
1086 && obj
&& obj
== uwep
&& objects
[obj
->otyp
].oc_material
== IRON
1088 if (clone_mon(mon
, 0, 0)) {
1089 pline("%s divides as you hit it!", Monnam(mon
));
1094 if (!hittxt
/*( thrown => obj exists )*/
1096 || (thrown
&& m_shot
.n
> 1 && m_shot
.o
== obj
->otyp
))) {
1098 hit(mshot_xname(obj
), mon
, exclam(tmp
));
1099 else if (!flags
.verbose
)
1102 You("%s %s%s", Role_if(PM_BARBARIAN
) ? "smite" : "hit",
1103 mon_nam(mon
), canseemon(mon
) ? exclam(tmp
) : ".");
1108 char *whom
= mon_nam(mon
);
1109 char silverobjbuf
[BUFSZ
];
1111 if (canspotmon(mon
)) {
1112 if (barehand_silver_rings
== 1)
1113 fmt
= "Your silver ring sears %s!";
1114 else if (barehand_silver_rings
== 2)
1115 fmt
= "Your silver rings sear %s!";
1116 else if (silverobj
&& saved_oname
[0]) {
1117 Sprintf(silverobjbuf
, "Your %s%s %s %%s!",
1118 strstri(saved_oname
, "silver") ? "" : "silver ",
1119 saved_oname
, vtense(saved_oname
, "sear"));
1122 fmt
= "The silver sears %s!";
1124 *whom
= highc(*whom
); /* "it" -> "It" */
1125 fmt
= "%s is seared!";
1127 /* note: s_suffix returns a modifiable buffer */
1128 if (!noncorporeal(mdat
) && !amorphous(mdat
))
1129 whom
= strcat(s_suffix(whom
), " flesh");
1132 /* if a "no longer poisoned" message is coming, it will be last;
1133 obj->opoisoned was cleared above and any message referring to
1134 "poisoned <obj>" has now been given; we want just "<obj>" for
1135 last message, so reformat while obj is still accessible */
1137 Strcpy(saved_oname
, cxname(obj
));
1139 /* [note: thrown obj might go away during killed/xkilled call] */
1142 pline_The("poison doesn't seem to affect %s.", mon_nam(mon
));
1144 pline_The("poison was deadly...");
1145 if (!already_killed
)
1147 destroyed
= TRUE
; /* return FALSE; */
1148 } else if (destroyed
) {
1149 if (!already_killed
)
1150 killed(mon
); /* takes care of most messages */
1151 } else if (u
.umconf
&& hand_to_hand
) {
1153 if (!mon
->mconf
&& !resist(mon
, SPBOOK_CLASS
, 0, NOTELL
)) {
1155 if (!mon
->mstun
&& mon
->mcanmove
&& !mon
->msleeping
1157 pline("%s appears confused.", Monnam(mon
));
1161 Your("%s %s no longer poisoned.", saved_oname
,
1162 vtense(saved_oname
, "are"));
1164 return destroyed
? FALSE
: TRUE
;
1174 * The things in this list either
1177 * 2) are dealt with properly by other routines
1178 * when it comes to shades.
1180 if (obj
->otyp
== BOULDER
1181 || obj
->otyp
== HEAVY_IRON_BALL
1182 || obj
->otyp
== IRON_CHAIN
/* dmgval handles those first three */
1183 || obj
->otyp
== MIRROR
/* silver in the reflective surface */
1184 || obj
->otyp
== CLOVE_OF_GARLIC
/* causes shades to flee */
1185 || objects
[obj
->otyp
].oc_material
== SILVER
)
1190 /* check whether slippery clothing protects from hug or wrap attack */
1191 /* [currently assumes that you are the attacker] */
1193 m_slips_free(mdef
, mattk
)
1195 struct attack
*mattk
;
1199 if (mattk
->adtyp
== AD_DRIN
) {
1200 /* intelligence drain attacks the head */
1201 obj
= which_armor(mdef
, W_ARMH
);
1203 /* grabbing attacks the body */
1204 obj
= which_armor(mdef
, W_ARMC
); /* cloak */
1206 obj
= which_armor(mdef
, W_ARM
); /* suit */
1208 obj
= which_armor(mdef
, W_ARMU
); /* shirt */
1211 /* if monster's cloak/armor is greased, your grab slips off; this
1212 protection might fail (33% chance) when the armor is cursed */
1213 if (obj
&& (obj
->greased
|| obj
->otyp
== OILSKIN_CLOAK
)
1214 && (!obj
->cursed
|| rn2(3))) {
1216 mattk
->adtyp
== AD_WRAP
? "slip off of"
1217 : "grab, but cannot hold onto",
1218 s_suffix(mon_nam(mdef
)), obj
->greased
? "greased" : "slippery",
1219 /* avoid "slippery slippery cloak"
1220 for undiscovered oilskin cloak */
1221 (obj
->greased
|| objects
[obj
->otyp
].oc_name_known
)
1223 : cloak_simple_name(obj
));
1225 if (obj
->greased
&& !rn2(2)) {
1226 pline_The("grease wears off.");
1234 /* used when hitting a monster with a lance while mounted;
1235 1: joust hit; 0: ordinary hit; -1: joust but break lance */
1238 struct monst
*mon
; /* target */
1239 struct obj
*obj
; /* weapon */
1241 int skill_rating
, joust_dieroll
;
1243 if (Fumbling
|| Stunned
)
1245 /* sanity check; lance must be wielded in order to joust */
1246 if (obj
!= uwep
&& (obj
!= uswapwep
|| !u
.twoweap
))
1249 /* if using two weapons, use worse of lance and two-weapon skills */
1250 skill_rating
= P_SKILL(weapon_type(obj
)); /* lance skill */
1251 if (u
.twoweap
&& P_SKILL(P_TWO_WEAPON_COMBAT
) < skill_rating
)
1252 skill_rating
= P_SKILL(P_TWO_WEAPON_COMBAT
);
1253 if (skill_rating
== P_ISRESTRICTED
)
1254 skill_rating
= P_UNSKILLED
; /* 0=>1 */
1256 /* odds to joust are expert:80%, skilled:60%, basic:40%, unskilled:20% */
1257 if ((joust_dieroll
= rn2(5)) < skill_rating
) {
1258 if (joust_dieroll
== 0 && rnl(50) == (50 - 1) && !unsolid(mon
->data
)
1259 && !obj_resists(obj
, 0, 100))
1260 return -1; /* hit that breaks lance */
1261 return 1; /* successful joust */
1263 return 0; /* no joust bonus; revert to ordinary attack */
1267 * Send in a demon pet for the hero. Exercise wisdom.
1269 * This function used to be inline to damageum(), but the Metrowerks compiler
1270 * (DR4 and DR4.5) screws up with an internal error 5 "Expression Too
1272 * Pulling it out makes it work.
1278 struct permonst
*pm
;
1281 pline("Some hell-p has arrived!");
1282 i
= !rn2(6) ? ndemon(u
.ualign
.type
) : NON_PM
;
1283 pm
= i
!= NON_PM
? &mons
[i
] : youmonst
.data
;
1284 if ((dtmp
= makemon(pm
, u
.ux
, u
.uy
, NO_MM_FLAGS
)) != 0)
1285 (void) tamedog(dtmp
, (struct obj
*) 0);
1286 exercise(A_WIS
, TRUE
);
1290 theft_petrifies(otmp
)
1293 if (uarmg
|| otmp
->otyp
!= CORPSE
1294 || !touch_petrifies(&mons
[otmp
->corpsenm
]) || Stone_resistance
)
1297 #if 0 /* no poly_when_stoned() critter has theft capability */
1298 if (poly_when_stoned(youmonst
.data
) && polymon(PM_STONE_GOLEM
)) {
1299 display_nhwindow(WIN_MESSAGE
, FALSE
); /* --More-- */
1304 /* stealing this corpse is fatal... */
1305 instapetrify(corpse_xname(otmp
, "stolen", CXN_ARTICLE
));
1306 /* apparently wasn't fatal after all... */
1311 * Player uses theft attack against monster.
1313 * If the target is wearing body armor, take all of its possessions;
1314 * otherwise, take one object. [Is this really the behavior we want?]
1317 steal_it(mdef
, mattk
)
1319 struct attack
*mattk
;
1321 struct obj
*otmp
, *stealoid
, **minvent_ptr
;
1325 return; /* nothing to take */
1327 /* look for worn body armor */
1328 stealoid
= (struct obj
*) 0;
1329 if (could_seduce(&youmonst
, mdef
, mattk
)) {
1330 /* find armor, and move it to end of inventory in the process */
1331 minvent_ptr
= &mdef
->minvent
;
1332 while ((otmp
= *minvent_ptr
) != 0)
1333 if (otmp
->owornmask
& W_ARM
) {
1335 panic("steal_it: multiple worn suits");
1336 *minvent_ptr
= otmp
->nobj
; /* take armor out of minvent */
1338 stealoid
->nobj
= (struct obj
*) 0;
1340 minvent_ptr
= &otmp
->nobj
;
1342 *minvent_ptr
= stealoid
; /* put armor back into minvent */
1345 if (stealoid
) { /* we will be taking everything */
1346 if (gender(mdef
) == (int) u
.mfemale
&& youmonst
.data
->mlet
== S_NYMPH
)
1347 You("charm %s. She gladly hands over her possessions.",
1350 You("seduce %s and %s starts to take off %s clothes.",
1351 mon_nam(mdef
), mhe(mdef
), mhis(mdef
));
1354 while ((otmp
= mdef
->minvent
) != 0) {
1356 break; /* no longer have ability to steal */
1357 /* take the object away from the monster */
1358 obj_extract_self(otmp
);
1359 if ((unwornmask
= otmp
->owornmask
) != 0L) {
1360 mdef
->misc_worn_check
&= ~unwornmask
;
1361 if (otmp
->owornmask
& W_WEP
)
1362 setmnotwielded(mdef
, otmp
);
1363 otmp
->owornmask
= 0L;
1364 update_mon_intrinsics(mdef
, otmp
, FALSE
, FALSE
);
1366 if (otmp
== stealoid
) /* special message for final item */
1367 pline("%s finishes taking off %s suit.", Monnam(mdef
),
1370 /* give the object to the character */
1371 otmp
= hold_another_object(otmp
, "You snatched but dropped %s.",
1372 doname(otmp
), "You steal: ");
1373 if (otmp
->where
!= OBJ_INVENT
)
1375 if (theft_petrifies(otmp
))
1376 break; /* stop thieving even though hero survived */
1377 /* more take-away handling, after theft message */
1378 if (unwornmask
& W_WEP
) { /* stole wielded weapon */
1379 possibly_unwield(mdef
, FALSE
);
1380 } else if (unwornmask
& W_ARMG
) { /* stole worn gloves */
1381 mselftouch(mdef
, (const char *) 0, TRUE
);
1382 if (mdef
->mhp
<= 0) /* it's now a statue */
1383 return; /* can't continue stealing */
1387 break; /* only taking one item */
1392 damageum(mdef
, mattk
)
1393 register struct monst
*mdef
;
1394 register struct attack
*mattk
;
1396 register struct permonst
*pd
= mdef
->data
;
1397 int armpro
, tmp
= d((int) mattk
->damn
, (int) mattk
->damd
);
1400 armpro
= magic_negation(mdef
);
1401 /* since hero can't be cancelled, only defender's armor applies */
1402 negated
= !(rn2(10) >= 3 * armpro
);
1404 if (is_demon(youmonst
.data
) && !rn2(13) && !uwep
1405 && u
.umonnum
!= PM_SUCCUBUS
&& u
.umonnum
!= PM_INCUBUS
1406 && u
.umonnum
!= PM_BALROG
) {
1410 switch (mattk
->adtyp
) {
1413 pline("%s %s for a moment.", Monnam(mdef
),
1414 makeplural(stagger(pd
, "stagger")));
1425 case AD_WERE
: /* no special effect on monsters */
1426 case AD_HEAL
: /* likewise */
1429 if (mattk
->aatyp
== AT_WEAP
) {
1432 } else if (mattk
->aatyp
== AT_KICK
) {
1433 if (thick_skinned(pd
))
1435 if (pd
== &mons
[PM_SHADE
]) {
1436 if (!(uarmf
&& uarmf
->blessed
)) {
1437 impossible("bad shade attack function flow?");
1440 tmp
= rnd(4); /* bless damage */
1442 /* add ring(s) of increase damage */
1443 if (u
.udaminc
> 0) {
1444 /* applies even if damage was 0 */
1446 } else if (tmp
> 0) {
1447 /* ring(s) might be negative; avoid converting
1448 0 to non-0 or positive to non-positive */
1461 pline("%s is %s!", Monnam(mdef
), on_fire(pd
, mattk
));
1462 if (pd
== &mons
[PM_STRAW_GOLEM
] || pd
== &mons
[PM_PAPER_GOLEM
]) {
1464 pline("%s burns completely!", Monnam(mdef
));
1468 /* Don't return yet; keep hp<1 and tmp=0 for pet msg */
1470 tmp
+= destroy_mitem(mdef
, SCROLL_CLASS
, AD_FIRE
);
1471 tmp
+= destroy_mitem(mdef
, SPBOOK_CLASS
, AD_FIRE
);
1472 if (resists_fire(mdef
)) {
1474 pline_The("fire doesn't heat %s!", mon_nam(mdef
));
1475 golemeffects(mdef
, AD_FIRE
, tmp
);
1476 shieldeff(mdef
->mx
, mdef
->my
);
1479 /* only potions damage resistant players in destroy_item */
1480 tmp
+= destroy_mitem(mdef
, POTION_CLASS
, AD_FIRE
);
1488 pline("%s is covered in frost!", Monnam(mdef
));
1489 if (resists_cold(mdef
)) {
1490 shieldeff(mdef
->mx
, mdef
->my
);
1492 pline_The("frost doesn't chill %s!", mon_nam(mdef
));
1493 golemeffects(mdef
, AD_COLD
, tmp
);
1496 tmp
+= destroy_mitem(mdef
, POTION_CLASS
, AD_COLD
);
1504 pline("%s is zapped!", Monnam(mdef
));
1505 tmp
+= destroy_mitem(mdef
, WAND_CLASS
, AD_ELEC
);
1506 if (resists_elec(mdef
)) {
1508 pline_The("zap doesn't shock %s!", mon_nam(mdef
));
1509 golemeffects(mdef
, AD_ELEC
, tmp
);
1510 shieldeff(mdef
->mx
, mdef
->my
);
1513 /* only rings damage resistant players in destroy_item */
1514 tmp
+= destroy_mitem(mdef
, RING_CLASS
, AD_ELEC
);
1517 if (resists_acid(mdef
))
1521 if (!munstone(mdef
, TRUE
))
1522 minstapetrify(mdef
, TRUE
);
1528 steal_it(mdef
, mattk
);
1532 /* This you as a leprechaun, so steal
1533 real gold only, no lesser coins */
1535 struct obj
*mongold
= findgold(mdef
->minvent
);
1537 obj_extract_self(mongold
);
1538 if (merge_choice(invent
, mongold
) || inv_cnt(FALSE
) < 52) {
1540 Your("purse feels heavier.");
1542 You("grab %s's gold, but find no room in your knapsack.",
1548 exercise(A_DEX
, TRUE
);
1554 if (!negated
&& tmp
< mdef
->mhp
) {
1557 canseemon(mdef
) || (u
.uswallow
&& u
.ustuck
== mdef
);
1558 /* record the name before losing sight of monster */
1559 Strcpy(nambuf
, Monnam(mdef
));
1560 if (u_teleport_mon(mdef
, FALSE
) && u_saw_mon
1561 && !(canseemon(mdef
) || (u
.uswallow
&& u
.ustuck
== mdef
)))
1562 pline("%s suddenly disappears!", nambuf
);
1566 if (can_blnd(&youmonst
, mdef
, mattk
->aatyp
, (struct obj
*) 0)) {
1567 if (!Blind
&& mdef
->mcansee
)
1568 pline("%s is blinded.", Monnam(mdef
));
1570 tmp
+= mdef
->mblinded
;
1573 mdef
->mblinded
= tmp
;
1578 if (night() && !rn2(10) && !mdef
->mcan
) {
1579 if (pd
== &mons
[PM_CLAY_GOLEM
]) {
1581 pline("Some writing vanishes from %s head!",
1582 s_suffix(mon_nam(mdef
)));
1584 /* Don't return yet; keep hp<1 and tmp=0 for pet msg */
1593 if (!negated
&& !rn2(3) && !resists_drli(mdef
)) {
1595 pline("%s suddenly seems weaker!", Monnam(mdef
));
1596 mdef
->mhpmax
-= xtmp
;
1597 if ((mdef
->mhp
-= xtmp
) <= 0 || !mdef
->m_lev
) {
1598 pline("%s dies!", Monnam(mdef
));
1606 if (pd
== &mons
[PM_IRON_GOLEM
]) {
1607 pline("%s falls to pieces!", Monnam(mdef
));
1610 erode_armor(mdef
, ERODE_RUST
);
1614 erode_armor(mdef
, ERODE_CORRODE
);
1618 if (pd
== &mons
[PM_WOOD_GOLEM
] || pd
== &mons
[PM_LEATHER_GOLEM
]) {
1619 pline("%s falls to pieces!", Monnam(mdef
));
1622 erode_armor(mdef
, ERODE_ROT
);
1626 if (!negated
&& !rn2(4))
1627 xdrainenergym(mdef
, TRUE
);
1633 if (!negated
&& !rn2(8)) {
1634 Your("%s was poisoned!", mpoisons_subj(&youmonst
, mattk
));
1635 if (resists_poison(mdef
))
1636 pline_The("poison doesn't seem to affect %s.", mon_nam(mdef
));
1639 Your("poison was deadly...");
1649 if (notonhead
|| !has_head(pd
)) {
1650 pline("%s doesn't seem harmed.", Monnam(mdef
));
1652 if (!Unchanging
&& pd
== &mons
[PM_GREEN_SLIME
]) {
1654 You("suck in some slime and don't feel very well.");
1655 make_slimed(10L, (char *) 0);
1660 if (m_slips_free(mdef
, mattk
))
1663 if ((helmet
= which_armor(mdef
, W_ARMH
)) != 0 && rn2(8)) {
1664 pline("%s %s blocks your attack to %s head.",
1665 s_suffix(Monnam(mdef
)), helm_simple_name(helmet
),
1670 (void) eat_brains(&youmonst
, mdef
, TRUE
, &tmp
);
1674 if (!negated
&& !sticks(pd
))
1675 u
.ustuck
= mdef
; /* it's now stuck to you */
1679 if (!u
.ustuck
&& !rn2(10)) {
1680 if (m_slips_free(mdef
, mattk
)) {
1683 You("swing yourself around %s!", mon_nam(mdef
));
1686 } else if (u
.ustuck
== mdef
) {
1687 /* Monsters don't wear amulets of magical breathing */
1688 if (is_pool(u
.ux
, u
.uy
) && !is_swimmer(pd
)
1689 && !amphibious(pd
)) {
1690 You("drown %s...", mon_nam(mdef
));
1692 } else if (mattk
->aatyp
== AT_HUGS
)
1693 pline("%s is being crushed.", Monnam(mdef
));
1697 You("brush against %s %s.", s_suffix(mon_nam(mdef
)),
1698 mbodypart(mdef
, LEG
));
1704 if (!negated
&& mdef
->mcanmove
&& !rn2(3) && tmp
< mdef
->mhp
) {
1706 pline("%s is frozen by you!", Monnam(mdef
));
1707 paralyze_monst(mdef
, rnd(10));
1711 if (!negated
&& !mdef
->msleeping
&& sleep_monst(mdef
, rnd(10), -1)) {
1713 pline("%s is put to sleep by you!", Monnam(mdef
));
1719 break; /* physical damage only */
1720 if (!rn2(4) && !slimeproof(pd
)) {
1721 if (!munslime(mdef
, TRUE
) && mdef
->mhp
> 0) {
1722 /* this assumes newcham() won't fail; since hero has
1723 a slime attack, green slimes haven't been geno'd */
1724 You("turn %s into slime.", mon_nam(mdef
));
1725 if (newcham(mdef
, &mons
[PM_GREEN_SLIME
], FALSE
, FALSE
))
1728 /* munslime attempt could have been fatal */
1730 return 2; /* skip death message */
1734 case AD_ENCH
: /* KMH -- remove enchantment (disenchanter) */
1735 /* there's no msomearmor() function, so just do damage */
1736 /* if (negated) break; */
1739 if (!negated
&& mdef
->mspeed
!= MSLOW
) {
1740 unsigned int oldspeed
= mdef
->mspeed
;
1742 mon_adjust_speed(mdef
, -1, (struct obj
*) 0);
1743 if (mdef
->mspeed
!= oldspeed
&& canseemon(mdef
))
1744 pline("%s slows down.", Monnam(mdef
));
1749 if (canseemon(mdef
))
1750 pline("%s looks confused.", Monnam(mdef
));
1759 mdef
->mstrategy
&= ~STRAT_WAITFORU
; /* in case player is very fast */
1760 if ((mdef
->mhp
-= tmp
) < 1) {
1761 if (mdef
->mtame
&& !cansee(mdef
->mx
, mdef
->my
)) {
1762 You_feel("embarrassed for a moment.");
1764 xkilled(mdef
, 0); /* !tmp but hp<1: already killed */
1765 } else if (!flags
.verbose
) {
1778 register struct monst
*mdef
;
1779 register struct attack
*mattk
;
1781 register int tmp
= d((int) mattk
->damn
, (int) mattk
->damd
);
1784 switch (mattk
->adtyp
) {
1785 boolean resistance
; /* only for cold/fire/elec */
1788 if (!resists_blnd(mdef
)) {
1789 pline("%s is blinded by your flash of light!", Monnam(mdef
));
1790 mdef
->mblinded
= min((int) mdef
->mblinded
+ tmp
, 127);
1795 if (haseyes(mdef
->data
) && mdef
->mcansee
) {
1796 pline("%s is affected by your flash of light!", Monnam(mdef
));
1801 resistance
= resists_cold(mdef
);
1804 resistance
= resists_fire(mdef
);
1807 resistance
= resists_elec(mdef
);
1810 pline("%s gets blasted!", Monnam(mdef
));
1812 if (mdef
->mhp
<= 0) {
1817 shieldeff(mdef
->mx
, mdef
->my
);
1818 if (is_golem(mdef
->data
))
1819 golemeffects(mdef
, (int) mattk
->adtyp
, tmp
);
1821 pline_The("blast doesn't seem to affect %s.", mon_nam(mdef
));
1835 map_location(u
.ux
, u
.uy
, TRUE
);
1836 tmp_at(DISP_ALWAYS
, mon_to_glyph(&youmonst
));
1837 tmp_at(mdef
->mx
, mdef
->my
);
1839 You("engulf %s!", mon_nam(mdef
));
1848 tmp_at(DISP_END
, 0);
1855 register struct monst
*mdef
;
1856 register struct attack
*mattk
;
1858 #ifdef LINT /* static char msgbuf[BUFSZ]; */
1861 static char msgbuf
[BUFSZ
]; /* for nomovemsg */
1864 register int dam
= d((int) mattk
->damn
, (int) mattk
->damd
);
1867 struct permonst
*pd
= mdef
->data
;
1869 /* Not totally the same as for real monsters. Specifically, these
1870 * don't take multiple moves. (It's just too hard, for too little
1871 * result, to program monsters which attack from inside you, which
1872 * would be necessary if done accurately.) Instead, we arbitrarily
1873 * kill the monster immediately for AD_DGST and we regurgitate them
1874 * after exactly 1 round of attack otherwise. -KAA
1877 if (!engulf_target(&youmonst
, mdef
))
1880 if (u
.uhunger
< 1500 && !u
.uswallow
) {
1881 for (otmp
= mdef
->minvent
; otmp
; otmp
= otmp
->nobj
)
1882 (void) snuff_lit(otmp
);
1884 /* engulfing a cockatrice or digesting a Rider or Medusa */
1885 fatal_gulp
= (touch_petrifies(pd
) && !Stone_resistance
)
1886 || (mattk
->adtyp
== AD_DGST
1887 && (is_rider(pd
) || (pd
== &mons
[PM_MEDUSA
]
1888 && !Stone_resistance
)));
1890 if ((mattk
->adtyp
== AD_DGST
&& !Slow_digestion
) || fatal_gulp
)
1891 eating_conducts(pd
);
1893 if (fatal_gulp
&& !is_rider(pd
)) { /* petrification */
1895 const char *mname
= pd
->mname
;
1897 if (!type_is_pname(pd
))
1899 You("englut %s.", mon_nam(mdef
));
1900 Sprintf(kbuf
, "swallowing %s whole", mname
);
1904 switch (mattk
->adtyp
) {
1906 /* eating a Rider or its corpse is fatal */
1908 pline("Unfortunately, digesting any of it is fatal.");
1910 Sprintf(killer
.name
, "unwisely tried to eat %s",
1912 killer
.format
= NO_KILLER_PREFIX
;
1914 return 0; /* lifesaved */
1917 if (Slow_digestion
) {
1922 /* Use up amulet of life saving */
1923 if (!!(otmp
= mlifesaver(mdef
)))
1924 m_useup(mdef
, otmp
);
1928 if (mdef
->mhp
> 0) { /* monster lifesaved */
1929 You("hurriedly regurgitate the sizzling in your %s.",
1930 body_part(STOMACH
));
1932 tmp
= 1 + (pd
->cwt
>> 8);
1933 if (corpse_chance(mdef
, &youmonst
, TRUE
)
1934 && !(mvitals
[monsndx(pd
)].mvflags
& G_NOCORPSE
)) {
1935 /* nutrition only if there can be a corpse */
1936 u
.uhunger
+= (pd
->cnutrit
+ 1) / 2;
1939 Sprintf(msgbuf
, "You totally digest %s.", mon_nam(mdef
));
1941 /* setting afternmv = end_engulf is tempting,
1942 * but will cause problems if the player is
1943 * attacked (which uses his real location) or
1944 * if his See_invisible wears off
1946 You("digest %s.", mon_nam(mdef
));
1950 multi_reason
= "digesting something";
1954 if (pd
== &mons
[PM_GREEN_SLIME
]) {
1955 Sprintf(msgbuf
, "%s isn't sitting well with you.",
1958 make_slimed(5L, (char *) 0);
1961 exercise(A_CON
, TRUE
);
1966 if (youmonst
.data
== &mons
[PM_FOG_CLOUD
]) {
1967 pline("%s is laden with your moisture.", Monnam(mdef
));
1968 if (amphibious(pd
) && !flaming(pd
)) {
1970 pline("%s seems unharmed.", Monnam(mdef
));
1973 pline("%s is pummeled with your debris!", Monnam(mdef
));
1976 pline("%s is covered with your goo!", Monnam(mdef
));
1977 if (resists_acid(mdef
)) {
1978 pline("It seems harmless to %s.", mon_nam(mdef
));
1983 if (can_blnd(&youmonst
, mdef
, mattk
->aatyp
,
1984 (struct obj
*) 0)) {
1986 pline("%s can't see in there!", Monnam(mdef
));
1988 dam
+= mdef
->mblinded
;
1991 mdef
->mblinded
= dam
;
1997 pline_The("air around %s crackles with electricity.",
1999 if (resists_elec(mdef
)) {
2000 pline("%s seems unhurt.", Monnam(mdef
));
2003 golemeffects(mdef
, (int) mattk
->adtyp
, dam
);
2009 if (resists_cold(mdef
)) {
2010 pline("%s seems mildly chilly.", Monnam(mdef
));
2013 pline("%s is freezing to death!", Monnam(mdef
));
2014 golemeffects(mdef
, (int) mattk
->adtyp
, dam
);
2020 if (resists_fire(mdef
)) {
2021 pline("%s seems mildly hot.", Monnam(mdef
));
2024 pline("%s is burning to a crisp!", Monnam(mdef
));
2025 golemeffects(mdef
, (int) mattk
->adtyp
, dam
);
2031 xdrainenergym(mdef
, TRUE
);
2036 if ((mdef
->mhp
-= dam
) <= 0) {
2038 if (mdef
->mhp
<= 0) /* not lifesaved */
2041 You("%s %s!", is_animal(youmonst
.data
) ? "regurgitate" : "expel",
2043 if (Slow_digestion
|| is_animal(youmonst
.data
)) {
2044 pline("Obviously, you didn't like %s taste.",
2045 s_suffix(mon_nam(mdef
)));
2053 missum(mdef
, mattk
, wouldhavehit
)
2054 register struct monst
*mdef
;
2055 register struct attack
*mattk
;
2056 boolean wouldhavehit
;
2058 if (wouldhavehit
) /* monk is missing due to penalty for wearing suit */
2059 Your("armor is rather cumbersome...");
2061 if (could_seduce(&youmonst
, mdef
, mattk
))
2062 You("pretend to be friendly to %s.", mon_nam(mdef
));
2063 else if (canspotmon(mdef
) && flags
.verbose
)
2064 You("miss %s.", mon_nam(mdef
));
2067 if (!mdef
->msleeping
&& mdef
->mcanmove
)
2071 /* attack monster as a monster. */
2074 register struct monst
*mon
;
2076 struct attack
*mattk
, alt_attk
;
2078 boolean altwep
= FALSE
, weapon_used
= FALSE
;
2079 int i
, tmp
, armorpenalty
, sum
[NATTK
], nsum
= 0, dhit
= 0, attknum
= 0;
2081 for (i
= 0; i
< NATTK
; i
++) {
2083 mattk
= getmattk(youmonst
.data
, i
, sum
, &alt_attk
);
2084 switch (mattk
->aatyp
) {
2087 /* Certain monsters don't use weapons when encountered as enemies,
2088 * but players who polymorph into them have hands or claws and
2089 * thus should be able to use weapons. This shouldn't prohibit
2090 * the use of most special abilities, either.
2091 * If monster has multiple claw attacks, only one can use weapon.
2094 /* Potential problem: if the monster gets multiple weapon attacks,
2095 * we currently allow the player to get each of these as a weapon
2096 * attack. Is this really desirable?
2098 /* approximate two-weapon mode */
2099 weapon
= (altwep
&& uswapwep
) ? uswapwep
: uwep
;
2100 altwep
= !altwep
; /* toggle for next attack */
2101 tmp
= find_roll_to_hit(mon
, AT_WEAP
, weapon
, &attknum
,
2103 dhit
= (tmp
> (dieroll
= rnd(20)) || u
.uswallow
);
2104 /* Enemy dead, before any special abilities used */
2105 if (!known_hitum(mon
, weapon
, &dhit
, tmp
, armorpenalty
, mattk
)) {
2110 /* might be a worm that gets cut in half */
2111 if (m_at(u
.ux
+ u
.dx
, u
.uy
+ u
.dy
) != mon
)
2112 return (boolean
) (nsum
!= 0);
2113 /* Do not print "You hit" message, since known_hitum
2116 if (dhit
&& mattk
->adtyp
!= AD_SPEL
&& mattk
->adtyp
!= AD_PHYS
)
2117 sum
[i
] = damageum(mon
, mattk
);
2120 if (uwep
&& !cantwield(youmonst
.data
) && !weapon_used
)
2124 if (uwep
&& youmonst
.data
->mlet
== S_LICH
&& !weapon_used
)
2132 tmp
= find_roll_to_hit(mon
, mattk
->aatyp
, (struct obj
*) 0,
2133 &attknum
, &armorpenalty
);
2134 dhit
= (tmp
> (dieroll
= rnd(20)) || u
.uswallow
);
2139 && (compat
= could_seduce(&youmonst
, mon
, mattk
))) {
2141 mon
->mcansee
&& haseyes(mon
->data
) ? "smile at"
2144 compat
== 2 ? "engagingly" : "seductively");
2145 /* doesn't anger it; no wakeup() */
2146 sum
[i
] = damageum(mon
, mattk
);
2150 /* maybe this check should be in damageum()? */
2151 if (mon
->data
== &mons
[PM_SHADE
]
2152 && !(mattk
->aatyp
== AT_KICK
&& uarmf
2153 && uarmf
->blessed
)) {
2154 Your("attack passes harmlessly through %s.",
2158 if (mattk
->aatyp
== AT_KICK
)
2159 You("kick %s.", mon_nam(mon
));
2160 else if (mattk
->aatyp
== AT_BITE
)
2161 You("bite %s.", mon_nam(mon
));
2162 else if (mattk
->aatyp
== AT_STNG
)
2163 You("sting %s.", mon_nam(mon
));
2164 else if (mattk
->aatyp
== AT_BUTT
)
2165 You("butt %s.", mon_nam(mon
));
2166 else if (mattk
->aatyp
== AT_TUCH
)
2167 You("touch %s.", mon_nam(mon
));
2168 else if (mattk
->aatyp
== AT_TENT
)
2169 Your("tentacles suck %s.", mon_nam(mon
));
2171 You("hit %s.", mon_nam(mon
));
2172 sum
[i
] = damageum(mon
, mattk
);
2174 missum(mon
, mattk
, (tmp
+ armorpenalty
> dieroll
));
2179 /* automatic if prev two attacks succeed, or if
2180 * already grabbed in a previous attack
2184 if (mon
->data
== &mons
[PM_SHADE
])
2185 Your("hug passes harmlessly through %s.", mon_nam(mon
));
2186 else if (!sticks(mon
->data
) && !u
.uswallow
) {
2187 if (mon
== u
.ustuck
) {
2188 pline("%s is being %s.", Monnam(mon
),
2189 u
.umonnum
== PM_ROPE_GOLEM
? "choked" : "crushed");
2190 sum
[i
] = damageum(mon
, mattk
);
2191 } else if (i
>= 2 && sum
[i
- 1] && sum
[i
- 2]) {
2192 You("grab %s!", mon_nam(mon
));
2194 sum
[i
] = damageum(mon
, mattk
);
2199 case AT_EXPL
: /* automatic hit if next to */
2202 sum
[i
] = explum(mon
, mattk
);
2206 tmp
= find_roll_to_hit(mon
, mattk
->aatyp
, (struct obj
*) 0,
2207 &attknum
, &armorpenalty
);
2208 if ((dhit
= (tmp
> rnd(20 + i
)))) {
2210 if (mon
->data
== &mons
[PM_SHADE
])
2211 Your("attempt to surround %s is harmless.", mon_nam(mon
));
2213 sum
[i
] = gulpum(mon
, mattk
);
2214 if (sum
[i
] == 2 && (mon
->data
->mlet
== S_ZOMBIE
2215 || mon
->data
->mlet
== S_MUMMY
)
2216 && rn2(5) && !Sick_resistance
) {
2217 You_feel("%ssick.", (Sick
) ? "very " : "");
2218 mdamageu(mon
, rnd(8));
2222 missum(mon
, mattk
, FALSE
);
2227 /* No check for uwep; if wielding nothing we want to
2228 * do the normal 1-2 points bare hand damage...
2230 if ((youmonst
.data
->mlet
== S_KOBOLD
2231 || youmonst
.data
->mlet
== S_ORC
2232 || youmonst
.data
->mlet
== S_GNOME
) && !weapon_used
)
2238 /* Not break--avoid passive attacks from enemy */
2242 case AT_GAZE
: /* all done using #monster command */
2246 default: /* Strange... */
2247 impossible("strange attack of yours (%d)", mattk
->aatyp
);
2250 u
.mh
= -1; /* dead in the current form */
2254 return (boolean
) passive(mon
, 1, 0, mattk
->aatyp
, FALSE
);
2257 (void) passive(mon
, sum
[i
], 1, mattk
->aatyp
, FALSE
);
2261 break; /* No extra attacks if no longer a monster */
2263 break; /* If paralyzed while attacking, i.e. floating eye */
2265 return (boolean
) (nsum
!= 0);
2268 /* Special (passive) attacks on you by monsters done here.
2271 passive(mon
, mhit
, malive
, aatyp
, wep_was_destroyed
)
2272 register struct monst
*mon
;
2273 register boolean mhit
;
2274 register int malive
;
2276 boolean wep_was_destroyed
;
2278 register struct permonst
*ptr
= mon
->data
;
2279 register int i
, tmp
;
2283 return (malive
| mhit
); /* no passive attacks */
2284 if (ptr
->mattk
[i
].aatyp
== AT_NONE
)
2285 break; /* try this one */
2287 /* Note: tmp not always used */
2288 if (ptr
->mattk
[i
].damn
)
2289 tmp
= d((int) ptr
->mattk
[i
].damn
, (int) ptr
->mattk
[i
].damd
);
2290 else if (ptr
->mattk
[i
].damd
)
2291 tmp
= d((int) mon
->m_lev
+ 1, (int) ptr
->mattk
[i
].damd
);
2295 /* These affect you even if they just died.
2297 switch (ptr
->mattk
[i
].adtyp
) {
2299 if (mhit
&& !mon
->mcan
) {
2300 if (aatyp
== AT_KICK
) {
2301 if (uarmf
&& !rn2(6))
2302 (void) erode_obj(uarmf
, xname(uarmf
), ERODE_BURN
,
2303 EF_GREASE
| EF_VERBOSE
);
2304 } else if (aatyp
== AT_WEAP
|| aatyp
== AT_CLAW
2305 || aatyp
== AT_MAGC
|| aatyp
== AT_TUCH
)
2306 passive_obj(mon
, (struct obj
*) 0, &(ptr
->mattk
[i
]));
2310 if (mhit
&& rn2(2)) {
2311 if (Blind
|| !flags
.verbose
)
2312 You("are splashed!");
2314 You("are splashed by %s acid!", s_suffix(mon_nam(mon
)));
2316 if (!Acid_resistance
)
2319 erode_armor(&youmonst
, ERODE_CORRODE
);
2322 if (aatyp
== AT_KICK
) {
2323 if (uarmf
&& !rn2(6))
2324 (void) erode_obj(uarmf
, xname(uarmf
), ERODE_CORRODE
,
2325 EF_GREASE
| EF_VERBOSE
);
2326 } else if (aatyp
== AT_WEAP
|| aatyp
== AT_CLAW
2327 || aatyp
== AT_MAGC
|| aatyp
== AT_TUCH
)
2328 passive_obj(mon
, (struct obj
*) 0, &(ptr
->mattk
[i
]));
2330 exercise(A_STR
, FALSE
);
2333 if (mhit
) { /* successful attack */
2334 long protector
= attk_protection((int) aatyp
);
2336 /* hero using monsters' AT_MAGC attack is hitting hand to
2337 hand rather than casting a spell */
2338 if (aatyp
== AT_MAGC
)
2341 if (protector
== 0L /* no protection */
2342 || (protector
== W_ARMG
&& !uarmg
2343 && !uwep
&& !wep_was_destroyed
)
2344 || (protector
== W_ARMF
&& !uarmf
)
2345 || (protector
== W_ARMH
&& !uarmh
)
2346 || (protector
== (W_ARMC
| W_ARMG
) && (!uarmc
|| !uarmg
))) {
2347 if (!Stone_resistance
2348 && !(poly_when_stoned(youmonst
.data
)
2349 && polymon(PM_STONE_GOLEM
))) {
2350 done_in_by(mon
, STONING
); /* "You turn to stone..." */
2357 if (mhit
&& !mon
->mcan
) {
2358 if (aatyp
== AT_KICK
) {
2360 (void) erode_obj(uarmf
, xname(uarmf
), ERODE_RUST
,
2361 EF_GREASE
| EF_VERBOSE
);
2362 } else if (aatyp
== AT_WEAP
|| aatyp
== AT_CLAW
2363 || aatyp
== AT_MAGC
|| aatyp
== AT_TUCH
)
2364 passive_obj(mon
, (struct obj
*) 0, &(ptr
->mattk
[i
]));
2368 if (mhit
&& !mon
->mcan
) {
2369 if (aatyp
== AT_KICK
) {
2371 (void) erode_obj(uarmf
, xname(uarmf
), ERODE_CORRODE
,
2372 EF_GREASE
| EF_VERBOSE
);
2373 } else if (aatyp
== AT_WEAP
|| aatyp
== AT_CLAW
2374 || aatyp
== AT_MAGC
|| aatyp
== AT_TUCH
)
2375 passive_obj(mon
, (struct obj
*) 0, &(ptr
->mattk
[i
]));
2379 /* wrath of gods for attacking Oracle */
2381 shieldeff(u
.ux
, u
.uy
);
2382 pline("A hail of magic missiles narrowly misses you!");
2384 You("are hit by magic missiles appearing from thin air!");
2388 case AD_ENCH
: /* KMH -- remove enchantment (disenchanter) */
2390 struct obj
*obj
= (struct obj
*) 0;
2392 if (aatyp
== AT_KICK
) {
2396 } else if (aatyp
== AT_BITE
|| aatyp
== AT_BUTT
2397 || (aatyp
>= AT_STNG
&& aatyp
< AT_WEAP
)) {
2398 break; /* no object involved */
2400 passive_obj(mon
, obj
, &(ptr
->mattk
[i
]));
2407 /* These only affect you if they still live.
2409 if (malive
&& !mon
->mcan
&& rn2(3)) {
2410 switch (ptr
->mattk
[i
].adtyp
) {
2412 if (ptr
== &mons
[PM_FLOATING_EYE
]) {
2413 if (!canseemon(mon
)) {
2417 if (ureflects("%s gaze is reflected by your %s.",
2418 s_suffix(Monnam(mon
)))) {
2420 } else if (Free_action
) {
2421 You("momentarily stiffen under %s gaze!",
2422 s_suffix(mon_nam(mon
)));
2423 } else if (Hallucination
&& rn2(4)) {
2424 pline("%s looks %s%s.", Monnam(mon
),
2425 !rn2(2) ? "" : "rather ",
2426 !rn2(2) ? "numb" : "stupified");
2428 You("are frozen by %s gaze!", s_suffix(mon_nam(mon
)));
2429 nomul((ACURR(A_WIS
) > 12 || rn2(4)) ? -tmp
: -127);
2430 multi_reason
= "frozen by a monster's gaze";
2434 pline("%s cannot defend itself.",
2435 Adjmonnam(mon
, "blind"));
2439 } else if (Free_action
) {
2440 You("momentarily stiffen.");
2441 } else { /* gelatinous cube */
2442 You("are frozen by %s!", mon_nam(mon
));
2443 nomovemsg
= You_can_move_again
;
2445 multi_reason
= "frozen by a monster";
2446 exercise(A_DEX
, FALSE
);
2449 case AD_COLD
: /* brown mold or blue jelly */
2450 if (monnear(mon
, u
.ux
, u
.uy
)) {
2451 if (Cold_resistance
) {
2452 shieldeff(u
.ux
, u
.uy
);
2453 You_feel("a mild chill.");
2454 ugolemeffects(AD_COLD
, tmp
);
2457 You("are suddenly very cold!");
2459 /* monster gets stronger with your heat! */
2460 mon
->mhp
+= tmp
/ 2;
2461 if (mon
->mhpmax
< mon
->mhp
)
2462 mon
->mhpmax
= mon
->mhp
;
2463 /* at a certain point, the monster will reproduce! */
2464 if (mon
->mhpmax
> ((int) (mon
->m_lev
+ 1) * 8))
2465 (void) split_mon(mon
, &youmonst
);
2468 case AD_STUN
: /* specifically yellow mold */
2470 make_stunned((long) tmp
, TRUE
);
2473 if (monnear(mon
, u
.ux
, u
.uy
)) {
2474 if (Fire_resistance
) {
2475 shieldeff(u
.ux
, u
.uy
);
2476 You_feel("mildly warm.");
2477 ugolemeffects(AD_FIRE
, tmp
);
2480 You("are suddenly very hot!");
2481 mdamageu(mon
, tmp
); /* fire damage */
2485 if (Shock_resistance
) {
2486 shieldeff(u
.ux
, u
.uy
);
2487 You_feel("a mild tingle.");
2488 ugolemeffects(AD_ELEC
, tmp
);
2491 You("are jolted with electricity!");
2498 return (malive
| mhit
);
2502 * Special (passive) attacks on an attacking object by monsters done here.
2503 * Assumes the attack was successful.
2506 passive_obj(mon
, obj
, mattk
)
2507 register struct monst
*mon
;
2508 register struct obj
*obj
; /* null means pick uwep, uswapwep or uarmg */
2509 struct attack
*mattk
; /* null means we find one internally */
2511 struct permonst
*ptr
= mon
->data
;
2514 /* if caller hasn't specified an object, use uwep, uswapwep or uarmg */
2516 obj
= (u
.twoweap
&& uswapwep
&& !rn2(2)) ? uswapwep
: uwep
;
2517 if (!obj
&& mattk
->adtyp
== AD_ENCH
)
2518 obj
= uarmg
; /* no weapon? then must be gloves */
2520 return; /* no object to affect */
2523 /* if caller hasn't specified an attack, find one */
2527 return; /* no passive attacks */
2528 if (ptr
->mattk
[i
].aatyp
== AT_NONE
)
2529 break; /* try this one */
2531 mattk
= &(ptr
->mattk
[i
]);
2534 switch (mattk
->adtyp
) {
2536 if (!rn2(6) && !mon
->mcan
2537 /* steam vortex: fire resist applies, fire damage doesn't */
2538 && mon
->data
!= &mons
[PM_STEAM_VORTEX
]) {
2539 (void) erode_obj(obj
, NULL
, ERODE_BURN
, EF_NONE
);
2544 (void) erode_obj(obj
, NULL
, ERODE_CORRODE
, EF_NONE
);
2549 (void) erode_obj(obj
, NULL
, ERODE_RUST
, EF_NONE
);
2554 (void) erode_obj(obj
, NULL
, ERODE_CORRODE
, EF_NONE
);
2559 if (drain_item(obj
) && carried(obj
)
2560 && (obj
->known
|| obj
->oclass
== ARMOR_CLASS
)) {
2561 pline("%s less effective.", Yobjnam2(obj
, "seem"));
2573 /* Note: caller must ascertain mtmp is mimicking... */
2575 stumble_onto_mimic(mtmp
)
2578 const char *fmt
= "Wait! That's %s!", *generic
= "a monster", *what
= 0;
2580 if (!u
.ustuck
&& !mtmp
->mflee
&& dmgtype(mtmp
->data
, AD_STCK
))
2585 what
= generic
; /* with default fmt */
2586 else if (mtmp
->m_ap_type
== M_AP_MONSTER
)
2587 what
= a_monnam(mtmp
); /* differs from what was sensed */
2589 int glyph
= levl
[u
.ux
+ u
.dx
][u
.uy
+ u
.dy
].glyph
;
2591 if (glyph_is_cmap(glyph
) && (glyph_to_cmap(glyph
) == S_hcdoor
2592 || glyph_to_cmap(glyph
) == S_vcdoor
))
2593 fmt
= "The door actually was %s!";
2594 else if (glyph_is_object(glyph
) && glyph_to_obj(glyph
) == GOLD_PIECE
)
2595 fmt
= "That gold was %s!";
2597 /* cloned Wiz starts out mimicking some other monster and
2598 might make himself invisible before being revealed */
2599 if (mtmp
->minvis
&& !See_invisible
)
2602 what
= a_monnam(mtmp
);
2607 wakeup(mtmp
); /* clears mimicking */
2608 /* if hero is blind, wakeup() won't display the monster even though
2609 it's no longer concealed */
2610 if (!canspotmon(mtmp
)
2611 && !glyph_is_invisible(levl
[mtmp
->mx
][mtmp
->my
].glyph
))
2612 map_invisible(mtmp
->mx
, mtmp
->my
);
2619 char *hands
= makeplural(body_part(HAND
));
2621 if (!u
.umconf
|| mon
->mconf
)
2623 if (u
.umconf
== 1) {
2625 Your("%s stop tingling.", hands
);
2627 Your("%s stop glowing %s.", hands
, hcolor(NH_RED
));
2630 pline_The("tingling in your %s lessens.", hands
);
2632 Your("%s no longer glow so brightly %s.", hands
, hcolor(NH_RED
));
2638 flash_hits_mon(mtmp
, otmp
)
2640 struct obj
*otmp
; /* source of flash */
2642 int tmp
, amt
, res
= 0, useeit
= canseemon(mtmp
);
2644 if (mtmp
->msleeping
) {
2645 mtmp
->msleeping
= 0;
2647 pline_The("flash awakens %s.", mon_nam(mtmp
));
2650 } else if (mtmp
->data
->mlet
!= S_LIGHT
) {
2651 if (!resists_blnd(mtmp
)) {
2652 tmp
= dist2(otmp
->ox
, otmp
->oy
, mtmp
->mx
, mtmp
->my
);
2654 pline("%s is blinded by the flash!", Monnam(mtmp
));
2657 if (mtmp
->data
== &mons
[PM_GREMLIN
]) {
2658 /* Rule #1: Keep them out of the light. */
2659 amt
= otmp
->otyp
== WAN_LIGHT
? d(1 + otmp
->spe
, 4)
2660 : rn2(min(mtmp
->mhp
, 4));
2661 light_hits_gremlin(mtmp
, amt
);
2663 if (mtmp
->mhp
> 0) {
2664 if (!context
.mon_moving
)
2666 if (tmp
< 9 && !mtmp
->isshk
&& rn2(4))
2667 monflee(mtmp
, rn2(4) ? rnd(100) : 0, FALSE
, TRUE
);
2669 mtmp
->mblinded
= (tmp
< 3) ? 0 : rnd(1 + 50 / tmp
);
2677 light_hits_gremlin(mon
, dmg
)
2681 pline("%s %s!", Monnam(mon
),
2682 (dmg
> mon
->mhp
/ 2) ? "wails in agony" : "cries out in pain");
2683 if ((mon
->mhp
-= dmg
) <= 0) {
2684 if (context
.mon_moving
)
2685 monkilled(mon
, (char *) 0, AD_BLND
);
2688 } else if (cansee(mon
->mx
, mon
->my
) && !canspotmon(mon
)) {
2689 map_invisible(mon
->mx
, mon
->my
);