1 /* SCCS Id: @(#)mhitu.c 3.4 2003/11/26 */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed. See license for details. */
8 STATIC_VAR NEARDATA struct obj *otmp;
10 STATIC_DCL void FDECL(urustm, (struct monst *, struct obj *));
12 STATIC_DCL boolean FDECL(u_slip_free, (struct monst *,struct attack *));
13 STATIC_DCL int FDECL(passiveum, (struct permonst *,struct monst *,struct attack *));
18 STATIC_DCL void FDECL(mayberem, (struct obj *, const char *));
22 STATIC_DCL boolean FDECL(diseasemu, (struct permonst *));
23 STATIC_DCL int FDECL(hitmu, (struct monst *,struct attack *));
24 STATIC_DCL int FDECL(gulpmu, (struct monst *,struct attack *));
25 STATIC_DCL int FDECL(explmu, (struct monst *,struct attack *,BOOLEAN_P));
26 STATIC_DCL void FDECL(missmu,(struct monst *,BOOLEAN_P,struct attack *));
27 STATIC_DCL void FDECL(mswings,(struct monst *,struct obj *));
28 STATIC_DCL void FDECL(wildmiss, (struct monst *,struct attack *));
30 STATIC_DCL void FDECL(hurtarmor,(int));
31 STATIC_DCL void FDECL(hitmsg,(struct monst *,struct attack *));
33 /* See comment in mhitm.c. If we use this a lot it probably should be */
34 /* changed to a parameter to mhitu. */
42 register struct monst *mtmp;
43 register struct attack *mattk;
47 /* Note: if opposite gender, "seductively" */
48 /* If same gender, "engagingly" for nymph, normal msg for others */
49 if((compat = could_seduce(mtmp, &youmonst, mattk))
50 && !mtmp->mcan && !mtmp->mspec_used) {
51 pline("%s %s you %s.", Monnam(mtmp),
52 Blind ? "talks to" : "smiles at",
53 compat == 2 ? "engagingly" : "seductively");
55 switch (mattk->aatyp) {
57 pline("%s bites!", Monnam(mtmp));
60 pline("%s kicks%c", Monnam(mtmp),
61 thick_skinned(youmonst.data) ? '.' : '!');
64 pline("%s stings!", Monnam(mtmp));
67 pline("%s butts!", Monnam(mtmp));
70 pline("%s touches you!", Monnam(mtmp));
73 pline("%s tentacles suck you!",
74 s_suffix(Monnam(mtmp)));
78 pline("%s explodes!", Monnam(mtmp));
81 pline("%s hits!", Monnam(mtmp));
86 missmu(mtmp, nearmiss, mattk) /* monster missed you */
87 register struct monst *mtmp;
88 register boolean nearmiss;
89 register struct attack *mattk;
91 if (!canspotmon(mtmp))
92 map_invisible(mtmp->mx, mtmp->my);
94 if(could_seduce(mtmp, &youmonst, mattk) && !mtmp->mcan)
95 pline("%s pretends to be friendly.", Monnam(mtmp));
97 if (!flags.verbose || !nearmiss)
98 pline("%s misses.", Monnam(mtmp));
100 pline("%s just misses!", Monnam(mtmp));
106 mswings(mtmp, otemp) /* monster swings obj */
107 register struct monst *mtmp;
108 register struct obj *otemp;
110 if (!flags.verbose || Blind || !mon_visible(mtmp))
112 pline("%s %s %s %s.", Monnam(mtmp),
113 (objects[otemp->otyp].oc_dir & PIERCE) ? "thrusts" : "swings",
114 mhis(mtmp), singular(otemp, xname));
117 /* return how a poison attack was delivered */
119 mpoisons_subj(mtmp, mattk)
121 struct attack *mattk;
123 if (mattk->aatyp == AT_WEAP) {
124 struct obj *mwep = (mtmp == &youmonst) ? uwep : MON_WEP(mtmp);
125 /* "Foo's attack was poisoned." is pretty lame, but at least
126 it's better than "sting" when not a stinging attack... */
127 return (!mwep || !mwep->opoisoned) ? "attack" : "weapon";
129 return (mattk->aatyp == AT_TUCH) ? "contact" :
130 (mattk->aatyp == AT_GAZE) ? "gaze" :
131 (mattk->aatyp == AT_BITE) ? "bite" : "sting";
135 /* called when your intrinsic speed is taken away */
142 else /* speed boots */
143 Your("quickness feels less natural.");
144 exercise(A_DEX, FALSE);
151 wildmiss(mtmp, mattk) /* monster attacked your displaced image */
152 register struct monst *mtmp;
153 register struct attack *mattk;
157 /* no map_invisible() -- no way to tell where _this_ is coming from */
159 if (!flags.verbose) return;
160 if (!cansee(mtmp->mx, mtmp->my)) return;
161 /* maybe it's attacking an image around the corner? */
163 compat = (mattk->adtyp == AD_SEDU || mattk->adtyp == AD_SSEX) &&
164 could_seduce(mtmp, &youmonst, (struct attack *)0);
166 if (!mtmp->mcansee || (Invis && !perceives(mtmp->data))) {
168 mattk->aatyp == AT_BITE ? "snaps" :
169 mattk->aatyp == AT_KICK ? "kicks" :
170 (mattk->aatyp == AT_STNG ||
171 mattk->aatyp == AT_BUTT ||
172 nolimbs(mtmp->data)) ? "lunges" : "swings";
175 pline("%s tries to touch you and misses!", Monnam(mtmp));
178 case 0: pline("%s %s wildly and misses!", Monnam(mtmp),
181 case 1: pline("%s attacks a spot beside you.", Monnam(mtmp));
183 case 2: pline("%s strikes at %s!", Monnam(mtmp),
184 levl[mtmp->mux][mtmp->muy].typ == WATER
185 ? "empty water" : "thin air");
187 default:pline("%s %s wildly!", Monnam(mtmp), swings);
191 } else if (Displaced) {
193 pline("%s smiles %s at your %sdisplaced image...",
195 compat == 2 ? "engagingly" : "seductively",
196 Invis ? "invisible " : "");
198 pline("%s strikes at your %sdisplaced image and misses you!",
199 /* Note: if you're both invisible and displaced,
200 * only monsters which see invisible will attack your
201 * displaced image, since the displaced image is also
205 Invis ? "invisible " : "");
207 } else if (Underwater) {
208 /* monsters may miss especially on water level where
209 bubbles shake the player here and there */
211 pline("%s reaches towards your distorted image.",Monnam(mtmp));
213 pline("%s is fooled by water reflections and misses!",Monnam(mtmp));
215 } else impossible("%s attacks you without knowing your location?",
220 expels(mtmp, mdat, message)
221 register struct monst *mtmp;
222 register struct permonst *mdat; /* if mtmp is polymorphed, mdat != mtmp->data */
227 You("get regurgitated!");
233 for(i = 0; i < NATTK; i++)
234 if(mdat->mattk[i].aatyp == AT_ENGL)
236 if (mdat->mattk[i].aatyp != AT_ENGL)
237 impossible("Swallower has no engulfing attack?");
239 if (is_whirly(mdat)) {
240 switch (mdat->mattk[i].adtyp) {
243 " in a shower of sparks");
247 " in a blast of frost");
251 Strcpy(blast, " with a squelch");
252 You("get expelled from %s%s!",
253 mon_nam(mtmp), blast);
257 unstuck(mtmp); /* ball&chain returned in unstuck() */
261 /* to cover for a case where mtmp is not in a next square */
262 if(um_dist(mtmp->mx,mtmp->my,1))
263 pline("Brrooaa... You land hard at some distance.");
269 /* select a monster's next attack, possibly substituting for its usual one */
271 getmattk(mptr, indx, prev_result, alt_attk_buf)
272 struct permonst *mptr;
273 int indx, prev_result[];
274 struct attack *alt_attk_buf;
276 struct attack *attk = &mptr->mattk[indx];
278 /* prevent a monster with two consecutive disease or hunger attacks
279 from hitting with both of them on the same turn; if the first has
280 already hit, switch to a stun attack for the second */
281 if (indx > 0 && prev_result[indx - 1] > 0 &&
282 (attk->adtyp == AD_DISE ||
283 attk->adtyp == AD_PEST ||
284 attk->adtyp == AD_FAMN) &&
285 attk->adtyp == mptr->mattk[indx - 1].adtyp) {
286 *alt_attk_buf = *attk;
288 attk->adtyp = AD_STUN;
294 * mattacku: monster attacks you
295 * returns 1 if monster dies (e.g. "yellow light"), 0 otherwise
296 * Note: if you're displaced or invisible the monster might attack the
298 * Assumption: it's attacking you or an empty square; if there's another
299 * monster which it attacks by mistake, the caller had better
304 register struct monst *mtmp;
306 struct attack *mattk, alt_attk;
307 int i, j, tmp, sum[NATTK];
308 struct permonst *mdat = mtmp->data;
309 boolean ranged = (distu(mtmp->mx, mtmp->my) > 3);
310 /* Is it near you? Affects your actions */
311 boolean range2 = !monnear(mtmp, mtmp->mux, mtmp->muy);
312 /* Does it think it's near you? Affects its actions */
313 boolean foundyou = (mtmp->mux==u.ux && mtmp->muy==u.uy);
314 /* Is it attacking you or your image? */
315 boolean youseeit = canseemon(mtmp);
316 /* Might be attacking your image around the corner, or
317 * invisible, or you might be blind....
320 if(!ranged) nomul(0);
321 if(mtmp->mhp <= 0 || (Underwater && !is_swimmer(mtmp->data)))
324 /* If swallowed, can only be affected by u.ustuck */
328 u.ustuck->mux = u.ux;
329 u.ustuck->muy = u.uy;
332 if(u.uinvulnerable) return (0); /* stomachs can't hurt you! */
337 if (mtmp == u.usteed)
338 /* Your steed won't attack you */
340 /* Orcs like to steal and eat horses and the like */
341 if (!rn2(is_orc(mtmp->data) ? 2 : 4) &&
342 distu(mtmp->mx, mtmp->my) <= 2) {
343 /* Attack your steed instead */
344 i = mattackm(mtmp, u.usteed);
345 if ((i & MM_AGR_DIED))
347 if (i & MM_DEF_DIED || u.umoved)
349 /* Let your steed retaliate */
350 return (!!(mattackm(u.usteed, mtmp) & MM_DEF_DIED));
355 if (u.uundetected && !range2 && foundyou && !u.uswallow) {
357 if (is_hider(youmonst.data)) {
358 coord cc; /* maybe we need a unexto() function? */
361 You("fall from the %s!", ceiling(u.ux,u.uy));
362 if (enexto(&cc, u.ux, u.uy, youmonst.data)) {
363 remove_monster(mtmp->mx, mtmp->my);
364 newsym(mtmp->mx,mtmp->my);
365 place_monster(mtmp, u.ux, u.uy);
366 if(mtmp->wormno) worm_move(mtmp);
367 teleds(cc.x, cc.y, TRUE);
371 pline("%s is killed by a falling %s (you)!",
372 Monnam(mtmp), youmonst.data->mname);
375 if (mtmp->mhp > 0) return 0;
378 if (youmonst.data->mlet != S_PIERCER)
379 return(0); /* trappers don't attack */
381 obj = which_armor(mtmp, WORN_HELMET);
382 if (obj && is_metallic(obj)) {
383 Your("blow glances off %s helmet.",
384 s_suffix(mon_nam(mtmp)));
386 if (3 + find_mac(mtmp) <= rnd(20)) {
387 pline("%s is hit by a falling piercer (you)!",
389 if ((mtmp->mhp -= d(3,6)) < 1)
392 pline("%s is almost hit by a falling piercer (you)!",
397 pline("It tries to move where you are hiding.");
399 /* Ugly kludge for eggs. The message is phrased so as
400 * to be directed at the monster, not the player,
401 * which makes "laid by you" wrong. For the
402 * parallelism to work, we can't rephrase it, so we
403 * zap the "laid by you" momentarily instead.
405 struct obj *obj = level.objects[u.ux][u.uy];
408 (youmonst.data->mlet == S_EEL && is_pool(u.ux, u.uy))) {
409 int save_spe = 0; /* suppress warning */
412 if (obj->otyp == EGG) obj->spe = 0;
414 if (youmonst.data->mlet == S_EEL)
415 pline("Wait, %s! There's a hidden %s named %s there!",
416 m_monnam(mtmp), youmonst.data->mname, plname);
418 pline("Wait, %s! There's a %s named %s hiding under %s!",
419 m_monnam(mtmp), youmonst.data->mname, plname,
420 doname(level.objects[u.ux][u.uy]));
421 if (obj) obj->spe = save_spe;
423 impossible("hiding under nothing?");
429 if (youmonst.data->mlet == S_MIMIC && youmonst.m_ap_type &&
430 !range2 && foundyou && !u.uswallow) {
431 if (!youseeit) pline("It gets stuck on you.");
432 else pline("Wait, %s! That's a %s named %s!",
433 m_monnam(mtmp), youmonst.data->mname, plname);
435 youmonst.m_ap_type = M_AP_NOTHING;
436 youmonst.mappearance = 0;
441 /* player might be mimicking an object */
442 if (youmonst.m_ap_type == M_AP_OBJECT && !range2 && foundyou && !u.uswallow) {
444 pline("%s %s!", Something,
445 (likes_gold(mtmp->data) && youmonst.mappearance == GOLD_PIECE) ?
446 "tries to pick you up" : "disturbs you");
447 else pline("Wait, %s! That %s is really %s named %s!",
449 mimic_obj_name(&youmonst),
450 an(mons[u.umonnum].mname),
452 if (multi < 0) { /* this should always be the case */
454 Sprintf(buf, "You appear to be %s again.",
455 Upolyd ? (const char *) an(youmonst.data->mname) :
456 (const char *) "yourself");
457 unmul(buf); /* immediately stop mimicking */
462 /* Work out the armor class differential */
463 tmp = AC_VALUE(u.uac) + 10; /* tmp ~= 0 - 20 */
465 if(multi < 0) tmp += 4;
466 if((Invis && !perceives(mdat)) || !mtmp->mcansee)
468 if(mtmp->mtrapped) tmp -= 2;
469 if(tmp <= 0) tmp = 1;
471 /* make eels visible the moment they hit/miss us */
472 if(mdat->mlet == S_EEL && mtmp->minvis && cansee(mtmp->mx,mtmp->my)) {
474 newsym(mtmp->mx,mtmp->my);
477 /* Special demon handling code */
478 if(!mtmp->cham && is_demon(mdat) && !range2
479 && mtmp->data != &mons[PM_BALROG]
480 && mtmp->data != &mons[PM_SUCCUBUS]
481 && mtmp->data != &mons[PM_INCUBUS])
482 if(!mtmp->mcan && !rn2(13)) msummon(mtmp);
484 /* Special lycanthrope handling code */
485 if(!mtmp->cham && is_were(mdat) && !range2) {
488 if(!rn2(5 - (night() * 2)) && !mtmp->mcan) new_were(mtmp);
489 } else if(!rn2(30) && !mtmp->mcan) new_were(mtmp);
492 if(!rn2(10) && !mtmp->mcan) {
493 int numseen, numhelp;
494 char buf[BUFSZ], genericwere[BUFSZ];
496 Strcpy(genericwere, "creature");
497 numhelp = were_summon(mdat, FALSE, &numseen, genericwere);
499 pline("%s summons help!", Monnam(mtmp));
502 You_feel("hemmed in.");
503 } else pline("But none comes.");
505 const char *from_nowhere;
508 pline("%s %s!", Something,
509 makeplural(growl_sound(mtmp)));
511 } else from_nowhere = " from nowhere";
513 if (numseen < 1) You_feel("hemmed in.");
516 Sprintf(buf, "%s appears",
519 Sprintf(buf, "%s appear",
520 makeplural(genericwere));
521 pline("%s%s!", upstart(buf), from_nowhere);
523 } /* else no help came; but you didn't know it tried */
528 if(u.uinvulnerable) {
529 /* monsters won't attack you */
531 pline("%s loosens its grip slightly.", Monnam(mtmp));
533 if (youseeit || sensemon(mtmp))
534 pline("%s starts to attack you, but pulls back.",
537 You_feel("%s move nearby.", something);
542 /* Unlike defensive stuff, don't let them use item _and_ attack. */
543 if(find_offensive(mtmp)) {
544 int foo = use_offensive(mtmp);
546 if (foo != 0) return(foo==1);
549 for(i = 0; i < NATTK; i++) {
552 mattk = getmattk(mdat, i, sum, &alt_attk);
553 if (u.uswallow && (mattk->aatyp != AT_ENGL))
555 switch(mattk->aatyp) {
556 case AT_CLAW: /* "hand to hand" attacks */
563 if(!range2 && (!MON_WEP(mtmp) || mtmp->mconf || Conflict ||
564 !touch_petrifies(youmonst.data))) {
566 if(tmp > (j = rnd(20+i))) {
567 if (mattk->aatyp != AT_KICK ||
568 !thick_skinned(youmonst.data))
569 sum[i] = hitmu(mtmp, mattk);
571 missmu(mtmp, (tmp == j), mattk);
573 wildmiss(mtmp, mattk);
577 case AT_HUGS: /* automatic if prev two attacks succeed */
578 /* Note: if displaced, prev attacks never succeeded */
579 if((!range2 && i>=2 && sum[i-1] && sum[i-2])
581 sum[i]= hitmu(mtmp, mattk);
584 case AT_GAZE: /* can affect you either ranged or not */
585 /* Medusa gaze already operated through m_respond in
586 * dochug(); don't gaze more than once per round.
588 if (mdat != &mons[PM_MEDUSA])
589 sum[i] = gazemu(mtmp, mattk);
592 case AT_EXPL: /* automatic hit if next to, and aimed at you */
593 if(!range2) sum[i] = explmu(mtmp, mattk, foundyou);
599 if(u.uswallow || tmp > (j = rnd(20+i))) {
600 /* Force swallowing monster to be
601 * displayed even when player is
604 sum[i] = gulpmu(mtmp, mattk);
606 missmu(mtmp, (tmp == j), mattk);
608 } else if (is_animal(mtmp->data)) {
609 pline("%s gulps some air!", Monnam(mtmp));
612 pline("%s lunges forward and recoils!",
615 You_hear("a %s nearby.",
616 is_whirly(mtmp->data) ?
617 "rushing noise" : "splat");
622 if(range2) sum[i] = breamu(mtmp, mattk);
623 /* Note: breamu takes care of displacement */
626 if(range2) sum[i] = spitmu(mtmp, mattk);
627 /* Note: spitmu takes care of displacement */
632 if (!Is_rogue_level(&u.uz))
638 /* Rare but not impossible. Normally the monster
639 * wields when 2 spaces away, but it can be
640 * teleported or whatever....
642 if (mtmp->weapon_check == NEED_WEAPON ||
644 mtmp->weapon_check = NEED_HTH_WEAPON;
645 /* mon_wield_item resets weapon_check as
647 if (mon_wield_item(mtmp) != 0) break;
650 otmp = MON_WEP(mtmp);
652 hittmp = hitval(otmp, &youmonst);
656 if(tmp > (j = dieroll = rnd(20+i)))
657 sum[i] = hitmu(mtmp, mattk);
659 missmu(mtmp, (tmp == j), mattk);
660 /* KMH -- Don't accumulate to-hit bonuses */
664 wildmiss(mtmp, mattk);
669 sum[i] = buzzmu(mtmp, mattk);
672 sum[i] = castmu(mtmp, mattk, TRUE, TRUE);
674 sum[i] = castmu(mtmp, mattk, TRUE, FALSE);
678 default: /* no attack */
681 if(flags.botl) bot();
682 /* give player a chance of waking up before dying -kaa */
683 if(sum[i] == 1) { /* successful attack */
684 if (u.usleep && u.usleep < monstermoves && !rn2(10)) {
686 nomovemsg = "The combat suddenly awakens you.";
689 if(sum[i] == 2) return 1; /* attacker dead */
690 if(sum[i] == 3) break; /* attacker teleported, no more attacks */
691 /* sum[i] == 0: unsuccessful attack */
700 * helper function for some compilers that have trouble with hitmu
710 /* 0 is burning, which we should never be called with */
711 case AD_RUST: hurt = 1; break;
712 case AD_CORR: hurt = 3; break;
713 default: hurt = 2; break;
716 /* What the following code does: it keeps looping until it
717 * finds a target for the rust monster.
718 * Head, feet, etc... not covered by metal, or covered by
719 * rusty metal, are not targets. However, your body always
720 * is, no matter what covers it.
725 if (!uarmh || !rust_dmg(uarmh, xname(uarmh), hurt, FALSE, &youmonst))
730 (void)rust_dmg(uarmc, xname(uarmc), hurt, TRUE, &youmonst);
733 /* Note the difference between break and continue;
734 * break means it was hit and didn't rust; continue
735 * means it wasn't a target and though it didn't rust
736 * something else did.
739 (void)rust_dmg(uarm, xname(uarm), hurt, TRUE, &youmonst);
742 (void)rust_dmg(uarmu, xname(uarmu), hurt, TRUE, &youmonst);
746 if (!uarms || !rust_dmg(uarms, xname(uarms), hurt, FALSE, &youmonst))
750 if (!uarmg || !rust_dmg(uarmg, xname(uarmg), hurt, FALSE, &youmonst))
754 if (!uarmf || !rust_dmg(uarmf, xname(uarmf), hurt, FALSE, &youmonst))
758 break; /* Out of while loop */
767 struct permonst *mdat;
769 if (Sick_resistance) {
770 You_feel("a slight illness.");
773 make_sick(Sick ? Sick/3L + 1L : (long)rn1(ACURR(A_CON), 20),
774 mdat->mname, TRUE, SICK_NONVOMITABLE);
779 /* check whether slippery clothing protects from hug or wrap attack */
781 u_slip_free(mtmp, mattk)
783 struct attack *mattk;
785 struct obj *obj = (uarmc ? uarmc : uarm);
788 if (!obj) obj = uarmu;
790 if (mattk->adtyp == AD_DRIN) obj = uarmh;
792 /* if your cloak/armor is greased, monster slips off; this
793 protection might fail (33% chance) when the armor is cursed */
794 if (obj && (obj->greased || obj->otyp == OILSKIN_CLOAK) &&
795 (!obj->cursed || rn2(3))) {
796 pline("%s %s your %s %s!",
798 (mattk->adtyp == AD_WRAP) ?
799 "slips off of" : "grabs you, but cannot hold onto",
800 obj->greased ? "greased" : "slippery",
801 /* avoid "slippery slippery cloak"
802 for undiscovered oilskin cloak */
803 (obj->greased || objects[obj->otyp].oc_name_known) ?
804 xname(obj) : cloak_simple_name(obj));
806 if (obj->greased && !rn2(2)) {
807 pline_The("grease wears off.");
816 /* armor that sufficiently covers the body might be able to block magic */
824 armor = (mon == &youmonst) ? uarm : which_armor(mon, W_ARM);
825 if (armor && armpro < objects[armor->otyp].a_can)
826 armpro = objects[armor->otyp].a_can;
827 armor = (mon == &youmonst) ? uarmc : which_armor(mon, W_ARMC);
828 if (armor && armpro < objects[armor->otyp].a_can)
829 armpro = objects[armor->otyp].a_can;
830 armor = (mon == &youmonst) ? uarmh : which_armor(mon, W_ARMH);
831 if (armor && armpro < objects[armor->otyp].a_can)
832 armpro = objects[armor->otyp].a_can;
834 /* armor types for shirt, gloves, shoes, and shield don't currently
835 provide any magic cancellation but we might as well be complete */
837 armor = (mon == &youmonst) ? uarmu : which_armor(mon, W_ARMU);
838 if (armor && armpro < objects[armor->otyp].a_can)
839 armpro = objects[armor->otyp].a_can;
841 armor = (mon == &youmonst) ? uarmg : which_armor(mon, W_ARMG);
842 if (armor && armpro < objects[armor->otyp].a_can)
843 armpro = objects[armor->otyp].a_can;
844 armor = (mon == &youmonst) ? uarmf : which_armor(mon, W_ARMF);
845 if (armor && armpro < objects[armor->otyp].a_can)
846 armpro = objects[armor->otyp].a_can;
847 armor = (mon == &youmonst) ? uarms : which_armor(mon, W_ARMS);
848 if (armor && armpro < objects[armor->otyp].a_can)
849 armpro = objects[armor->otyp].a_can;
852 /* this one is really a stretch... */
853 armor = (mon == &youmonst) ? 0 : which_armor(mon, W_SADDLE);
854 if (armor && armpro < objects[armor->otyp].a_can)
855 armpro = objects[armor->otyp].a_can;
862 * hitmu: monster hits you
863 * returns 2 if monster dies (e.g. "yellow light"), 1 otherwise
864 * 3 if the monster lives but teleported/paralyzed, so it can't keep
869 register struct monst *mtmp;
870 register struct attack *mattk;
872 register struct permonst *mdat = mtmp->data;
873 register int uncancelled, ptmp;
874 int dmg, armpro, permdmg;
876 struct permonst *olduasmon = youmonst.data;
879 if (!canspotmon(mtmp))
880 map_invisible(mtmp->mx, mtmp->my);
882 /* If the monster is undetected & hits you, you should know where
883 * the attack came from.
885 if(mtmp->mundetected && (hides_under(mdat) || mdat->mlet == S_EEL)) {
886 mtmp->mundetected = 0;
887 if (!(Blind ? Blind_telepat : Unblind_telepat)) {
891 if ((obj = level.objects[mtmp->mx][mtmp->my]) != 0) {
892 if (Blind && !obj->dknown)
894 else if (is_pool(mtmp->mx, mtmp->my) && !Underwater)
899 pline("%s was hidden under %s!", Amonnam(mtmp), what);
901 newsym(mtmp->mx, mtmp->my);
905 /* First determine the base damage done */
906 dmg = d((int)mattk->damn, (int)mattk->damd);
907 if(is_undead(mdat) && midnight())
908 dmg += d((int)mattk->damn, (int)mattk->damd); /* extra damage */
910 /* Next a cancellation factor */
911 /* Use uncancelled when the cancellation factor takes into account certain
912 * armor's special magic protection. Otherwise just use !mtmp->mcan.
914 armpro = magic_negation(&youmonst);
915 uncancelled = !mtmp->mcan && ((rn2(3) >= armpro) || !rn2(50));
918 /* Now, adjust damages via resistances or specific attacks */
919 switch(mattk->adtyp) {
921 if (mattk->aatyp == AT_HUGS && !sticks(youmonst.data)) {
922 if(!u.ustuck && rn2(2)) {
923 if (u_slip_free(mtmp, mattk)) {
927 pline("%s grabs you!", Monnam(mtmp));
929 } else if(u.ustuck == mtmp) {
930 exercise(A_STR, FALSE);
932 (mtmp->data == &mons[PM_ROPE_GOLEM])
933 ? "choked" : "crushed");
935 } else { /* hand to hand weapon */
936 if(mattk->aatyp == AT_WEAP && otmp) {
937 if (otmp->otyp == CORPSE
938 && touch_petrifies(&mons[otmp->corpsenm])) {
940 pline("%s hits you with the %s corpse.",
941 Monnam(mtmp), mons[otmp->corpsenm].mname);
945 dmg += dmgval(otmp, &youmonst);
946 if (dmg <= 0) dmg = 1;
947 if (!(otmp->oartifact &&
948 artifact_hit(mtmp, &youmonst, otmp, &dmg,dieroll)))
951 if (u.mh > 1 && u.mh > ((u.uac>0) ? dmg : dmg+u.uac) &&
952 objects[otmp->otyp].oc_material == IRON &&
953 (u.umonnum==PM_BLACK_PUDDING
954 || u.umonnum==PM_BROWN_PUDDING)) {
955 /* This redundancy necessary because you have to
956 * take the damage _before_ being cloned.
958 if (u.uac < 0) dmg += u.uac;
959 if (dmg < 1) dmg = 1;
960 if (dmg > 1) exercise(A_STR, FALSE);
965 You("divide as %s hits you!",mon_nam(mtmp));
968 } else if (mattk->aatyp != AT_TUCH || dmg != 0 ||
975 if (!diseasemu(mdat)) dmg = 0;
980 pline("You're %s!", on_fire(youmonst.data, mattk));
981 if (youmonst.data == &mons[PM_STRAW_GOLEM] ||
982 youmonst.data == &mons[PM_PAPER_GOLEM]) {
984 /* KMH -- this is okay with unchanging */
987 } else if (Fire_resistance) {
988 pline_The("fire doesn't feel hot!");
991 if((int) mtmp->m_lev > rn2(20))
992 destroy_item(SCROLL_CLASS, AD_FIRE);
993 if((int) mtmp->m_lev > rn2(20))
994 destroy_item(POTION_CLASS, AD_FIRE);
995 if((int) mtmp->m_lev > rn2(25))
996 destroy_item(SPBOOK_CLASS, AD_FIRE);
1001 hitmsg(mtmp, mattk);
1003 pline("You're covered in frost!");
1004 if (Cold_resistance) {
1005 pline_The("frost doesn't seem cold!");
1008 if((int) mtmp->m_lev > rn2(20))
1009 destroy_item(POTION_CLASS, AD_COLD);
1013 hitmsg(mtmp, mattk);
1016 if (Shock_resistance) {
1017 pline_The("zap doesn't shock you!");
1020 if((int) mtmp->m_lev > rn2(20))
1021 destroy_item(WAND_CLASS, AD_ELEC);
1022 if((int) mtmp->m_lev > rn2(20))
1023 destroy_item(RING_CLASS, AD_ELEC);
1027 hitmsg(mtmp, mattk);
1028 if (uncancelled && multi >= 0 && !rn2(5)) {
1029 if (Sleep_resistance) break;
1030 fall_asleep(-rnd(10), TRUE);
1031 if (Blind) You("are put to sleep!");
1032 else You("are put to sleep by %s!", mon_nam(mtmp));
1036 if (can_blnd(mtmp, &youmonst, mattk->aatyp, (struct obj*)0)) {
1037 if (!Blind) pline("%s blinds you!", Monnam(mtmp));
1038 make_blinded(Blinded+(long)dmg,FALSE);
1039 if (!Blind) Your(vision_clears);
1052 hitmsg(mtmp, mattk);
1053 if (uncancelled && !rn2(8)) {
1054 Sprintf(buf, "%s %s",
1055 s_suffix(Monnam(mtmp)), mpoisons_subj(mtmp, mattk));
1056 poisoned(buf, ptmp, mdat->mname, 30);
1060 hitmsg(mtmp, mattk);
1061 if (defends(AD_DRIN, uwep) || !has_head(youmonst.data)) {
1062 You("don't seem harmed.");
1063 /* Not clear what to do for green slimes */
1066 if (u_slip_free(mtmp,mattk)) break;
1068 if (uarmh && rn2(8)) {
1069 /* not body_part(HEAD) */
1070 Your("helmet blocks the attack to your head.");
1073 if (Half_physical_damage) dmg = (dmg+1) / 2;
1074 mdamageu(mtmp, dmg);
1076 if (!uarmh || uarmh->otyp != DUNCE_CAP) {
1077 Your("brain is eaten!");
1078 /* No such thing as mindless players... */
1079 if (ABASE(A_INT) <= ATTRMIN(A_INT)) {
1081 struct obj *wore_amulet = uamul;
1084 /* avoid looping on "die(y/n)?" */
1085 if (lifesaved && (discover || wizard)) {
1086 if (wore_amulet && !uamul) {
1087 /* used up AMULET_OF_LIFE_SAVING; still
1088 subject to dying from brainlessness */
1091 /* explicitly chose not to die;
1092 arbitrarily boost intelligence */
1093 ABASE(A_INT) = ATTRMIN(A_INT) + 2;
1094 You_feel("like a scarecrow.");
1100 pline("Unfortunately your brain is still gone.");
1102 Your("last thought fades away.");
1103 killer = "brainlessness";
1104 killer_format = KILLED_BY;
1110 /* adjattrib gives dunce cap message when appropriate */
1111 (void) adjattrib(A_INT, -rnd(2), FALSE);
1112 forget_levels(25); /* lose memory of 25% of levels */
1113 forget_objects(25); /* lose memory of 25% of objects */
1114 exercise(A_WIS, FALSE);
1117 hitmsg(mtmp, mattk);
1118 if (uncancelled && multi >= 0 && !rn2(3)) {
1120 You("momentarily stiffen.");
1122 if (Blind) You("are frozen!");
1123 else You("are frozen by %s!", mon_nam(mtmp));
1124 nomovemsg = 0; /* default: "you can move again" */
1126 exercise(A_DEX, FALSE);
1131 hitmsg(mtmp, mattk);
1132 if (uncancelled && !rn2(3) && !Drain_resistance) {
1133 losexp("life drainage");
1137 { register long side = rn2(2) ? RIGHT_SIDE : LEFT_SIDE;
1138 const char *sidestr = (side == RIGHT_SIDE) ? "right" : "left";
1140 /* This case is too obvious to ignore, but Nethack is not in
1141 * general very good at considering height--most short monsters
1142 * still _can_ attack you when you're flying or mounted.
1143 * [FIXME: why can't a flying attacker overcome this?]
1149 Levitation || Flying) {
1150 pline("%s tries to reach your %s %s!", Monnam(mtmp),
1151 sidestr, body_part(LEG));
1153 } else if (mtmp->mcan) {
1154 pline("%s nuzzles against your %s %s!", Monnam(mtmp),
1155 sidestr, body_part(LEG));
1159 if (rn2(2) && (uarmf->otyp == LOW_BOOTS ||
1160 uarmf->otyp == IRON_SHOES))
1161 pline("%s pricks the exposed part of your %s %s!",
1162 Monnam(mtmp), sidestr, body_part(LEG));
1164 pline("%s pricks through your %s boot!",
1165 Monnam(mtmp), sidestr);
1167 pline("%s scratches your %s boot!", Monnam(mtmp),
1172 } else pline("%s pricks your %s %s!", Monnam(mtmp),
1173 sidestr, body_part(LEG));
1174 set_wounded_legs(side, rnd(60-ACURR(A_DEX)));
1175 exercise(A_STR, FALSE);
1176 exercise(A_DEX, FALSE);
1180 case AD_STON: /* cockatrice */
1181 hitmsg(mtmp, mattk);
1185 You_hear("a cough from %s!", mon_nam(mtmp));
1188 You_hear("%s hissing!", s_suffix(mon_nam(mtmp)));
1190 (flags.moonphase == NEW_MOON && !have_lizard())) {
1192 if (!Stoned && !Stone_resistance
1193 && !(poly_when_stoned(youmonst.data) &&
1194 polymon(PM_STONE_GOLEM))) {
1196 delayed_killer = mtmp->data->mname;
1197 if (mtmp->data->geno & G_UNIQ) {
1198 if (!type_is_pname(mtmp->data)) {
1199 static char kbuf[BUFSZ];
1201 /* "the" buffer may be reallocated */
1202 Strcpy(kbuf, the(delayed_killer));
1203 delayed_killer = kbuf;
1205 killer_format = KILLED_BY;
1206 } else killer_format = KILLED_BY_AN;
1208 /* You("turn to stone..."); */
1209 /* done_in_by(mtmp); */
1216 hitmsg(mtmp, mattk);
1217 if (uncancelled && !u.ustuck && !sticks(youmonst.data))
1221 if ((!mtmp->mcan || u.ustuck == mtmp) && !sticks(youmonst.data)) {
1222 if (!u.ustuck && !rn2(10)) {
1223 if (u_slip_free(mtmp, mattk)) {
1226 pline("%s swings itself around you!",
1230 } else if(u.ustuck == mtmp) {
1231 if (is_pool(mtmp->mx,mtmp->my) && !Swimming
1234 (levl[mtmp->mx][mtmp->my].typ != POOL) &&
1235 (levl[mtmp->mx][mtmp->my].typ != WATER) &&
1236 !Is_medusa_level(&u.uz) &&
1237 !Is_waterlevel(&u.uz);
1239 pline("%s drowns you...", Monnam(mtmp));
1240 killer_format = KILLED_BY_AN;
1241 Sprintf(buf, "%s by %s",
1242 moat ? "moat" : "pool of water",
1243 an(mtmp->data->mname));
1246 } else if(mattk->aatyp == AT_HUGS)
1247 You("are being crushed.");
1251 pline("%s brushes against your %s.", Monnam(mtmp),
1257 hitmsg(mtmp, mattk);
1258 if (uncancelled && !rn2(4) && u.ulycn == NON_PM &&
1259 !Protection_from_shape_changers &&
1260 !defends(AD_WERE,uwep)) {
1261 You_feel("feverish.");
1262 exercise(A_CON, FALSE);
1263 u.ulycn = monsndx(mdat);
1267 hitmsg(mtmp, mattk);
1268 if (youmonst.data->mlet == mdat->mlet) break;
1269 if(!mtmp->mcan) stealgold(mtmp);
1272 case AD_SITM: /* for now these are the same */
1274 if (is_animal(mtmp->data)) {
1275 hitmsg(mtmp, mattk);
1276 if (mtmp->mcan) break;
1277 /* Continue below */
1278 } else if (dmgtype(youmonst.data, AD_SEDU)
1280 || dmgtype(youmonst.data, AD_SSEX)
1283 pline("%s %s.", Monnam(mtmp), mtmp->minvent ?
1284 "brags about the goods some dungeon explorer provided" :
1285 "makes some remarks about how difficult theft is lately");
1286 if (!tele_restrict(mtmp)) (void) rloc(mtmp, FALSE);
1288 } else if (mtmp->mcan) {
1290 pline("%s tries to %s you, but you seem %s.",
1291 Adjmonnam(mtmp, "plain"),
1292 flags.female ? "charm" : "seduce",
1293 flags.female ? "unaffected" : "uninterested");
1296 if (!tele_restrict(mtmp)) (void) rloc(mtmp, FALSE);
1302 switch (steal(mtmp, buf)) {
1308 if (!is_animal(mtmp->data) && !tele_restrict(mtmp))
1309 (void) rloc(mtmp, FALSE);
1310 if (is_animal(mtmp->data) && *buf) {
1311 if (canseemon(mtmp))
1312 pline("%s tries to %s away with %s.",
1314 locomotion(mtmp->data, "run"),
1317 monflee(mtmp, 0, FALSE, FALSE);
1323 if(could_seduce(mtmp, &youmonst, mattk) == 1
1330 hitmsg(mtmp, mattk);
1331 /* when the Wiz hits, 1/20 steals the amulet */
1332 if (u.uhave.amulet ||
1333 u.uhave.bell || u.uhave.book || u.uhave.menorah
1334 || u.uhave.questart) /* carrying the Quest Artifact */
1335 if (!rn2(20)) stealamulet(mtmp);
1339 hitmsg(mtmp, mattk);
1342 Your("position suddenly seems very uncertain!");
1347 hitmsg(mtmp, mattk);
1348 if (mtmp->mcan) break;
1349 if (u.umonnum == PM_IRON_GOLEM) {
1351 /* KMH -- this is okay with unchanging */
1358 hitmsg(mtmp, mattk);
1359 if (mtmp->mcan) break;
1363 hitmsg(mtmp, mattk);
1364 if (mtmp->mcan) break;
1365 if (u.umonnum == PM_WOOD_GOLEM ||
1366 u.umonnum == PM_LEATHER_GOLEM) {
1368 /* KMH -- this is okay with unchanging */
1375 /* a cancelled nurse is just an ordinary monster */
1377 hitmsg(mtmp, mattk);
1384 && !uarm && !uarmh && !uarms && !uarmg && !uarmc && !uarmf) {
1385 boolean goaway = FALSE;
1386 pline("%s hits! (I hope you don't mind.)", Monnam(mtmp));
1390 /* no upper limit necessary; effect is temporary */
1392 if (!rn2(13)) goaway = TRUE;
1394 if (u.mh > u.mhmax) u.mh = u.mhmax;
1398 /* hard upper limit via nurse care: 25 * ulevel */
1399 if (u.uhpmax < 5 * u.ulevel + d(2 * u.ulevel, 10))
1401 if (!rn2(13)) goaway = TRUE;
1403 if (u.uhp > u.uhpmax) u.uhp = u.uhpmax;
1405 if (!rn2(3)) exercise(A_STR, TRUE);
1406 if (!rn2(3)) exercise(A_CON, TRUE);
1407 if (Sick) make_sick(0L, (char *) 0, FALSE, SICK_ALL);
1412 } else if (!rn2(33)) {
1413 if (!tele_restrict(mtmp)) (void) rloc(mtmp, FALSE);
1414 monflee(mtmp, d(3, 6), TRUE, FALSE);
1419 if (Role_if(PM_HEALER)) {
1420 if (flags.soundok && !(moves % 5))
1421 verbalize("Doc, I can't help you unless you cooperate.");
1423 } else hitmsg(mtmp, mattk);
1427 hitmsg(mtmp, mattk);
1428 if(!night() && mdat == &mons[PM_GREMLIN]) break;
1429 if(!mtmp->mcan && !rn2(10)) {
1430 if (flags.soundok) {
1431 if (Blind) You_hear("laughter.");
1432 else pline("%s chuckles.", Monnam(mtmp));
1434 if (u.umonnum == PM_CLAY_GOLEM) {
1435 pline("Some writing vanishes from your head!");
1436 /* KMH -- this is okay with unchanging */
1444 hitmsg(mtmp, mattk);
1445 if(!mtmp->mcan && !rn2(4)) {
1446 make_stunned(HStun + dmg, TRUE);
1451 hitmsg(mtmp, mattk);
1452 if (!mtmp->mcan && !rn2(3))
1453 if (Acid_resistance) {
1454 pline("You're covered in acid, but it seems harmless.");
1457 pline("You're covered in acid! It burns!");
1458 exercise(A_STR, FALSE);
1463 hitmsg(mtmp, mattk);
1464 if (uncancelled && HFast &&
1465 !defends(AD_SLOW, uwep) && !rn2(4))
1469 hitmsg(mtmp, mattk);
1470 if (uncancelled && !rn2(4))
1475 hitmsg(mtmp, mattk);
1476 if(!mtmp->mcan && !rn2(4) && !mtmp->mspec_used) {
1477 mtmp->mspec_used = mtmp->mspec_used + (dmg + rn2(6));
1479 You("are getting even more confused.");
1480 else You("are getting confused.");
1481 make_confused(HConfusion + dmg, FALSE);
1486 pline("%s reaches out with its deadly touch.", Monnam(mtmp));
1487 if (is_undead(youmonst.data)) {
1488 /* Still does normal damage */
1489 pline("Was that the touch of death?");
1493 case 19: case 18: case 17:
1495 killer_format = KILLED_BY_AN;
1496 killer = "touch of death";
1500 } /* else FALLTHRU */
1501 default: /* case 16: ... case 5: */
1502 You_feel("your life force draining away...");
1503 permdmg = 1; /* actual damage done below */
1505 case 4: case 3: case 2: case 1: case 0:
1506 if (Antimagic) shieldeff(u.ux, u.uy);
1507 pline("Lucky for you, it didn't work!");
1513 pline("%s reaches out, and you feel fever and chills.",
1515 (void) diseasemu(mdat); /* plus the normal damage */
1518 pline("%s reaches out, and your body shrivels.",
1520 exercise(A_CON, FALSE);
1521 if (!is_fainted()) morehungry(rn1(40,40));
1522 /* plus the normal damage */
1525 hitmsg(mtmp, mattk);
1526 if (!uncancelled) break;
1527 if (flaming(youmonst.data)) {
1528 pline_The("slime burns away!");
1530 } else if (Unchanging ||
1531 youmonst.data == &mons[PM_GREEN_SLIME]) {
1532 You("are unaffected.");
1534 } else if (!Slimed) {
1535 You("don't feel very well.");
1538 killer_format = KILLED_BY_AN;
1539 delayed_killer = mtmp->data->mname;
1543 case AD_ENCH: /* KMH -- remove enchantment (disenchanter) */
1544 hitmsg(mtmp, mattk);
1545 /* uncancelled is sufficient enough; please
1546 don't make this attack less frequent */
1548 struct obj *obj = some_armor(&youmonst);
1550 if (drain_item(obj)) {
1551 Your("%s less effective.", aobjnam(obj, "seem"));
1558 if(u.uhp < 1) done_in_by(mtmp);
1560 /* Negative armor class reduces damage done instead of fully protecting
1563 if (dmg && u.uac < 0) {
1565 if (dmg < 1) dmg = 1;
1569 if (Half_physical_damage
1570 /* Mitre of Holiness */
1571 || (Role_if(PM_PRIEST) && uarmh && is_quest_artifact(uarmh) &&
1572 (is_undead(mtmp->data) || is_demon(mtmp->data))))
1575 if (permdmg) { /* Death's life force drain */
1576 int lowerlimit, *hpmax_p;
1578 * Apply some of the damage to permanent hit points:
1579 * polymorphed 100% against poly'd hpmax
1580 * hpmax > 25*lvl 100% against normal hpmax
1581 * hpmax > 10*lvl 50..100%
1582 * hpmax > 5*lvl 25..75%
1584 * Never reduces hpmax below 1 hit point per level.
1586 permdmg = rn2(dmg / 2 + 1);
1587 if (Upolyd || u.uhpmax > 25 * u.ulevel) permdmg = dmg;
1588 else if (u.uhpmax > 10 * u.ulevel) permdmg += dmg / 2;
1589 else if (u.uhpmax > 5 * u.ulevel) permdmg += dmg / 4;
1593 /* [can't use youmonst.m_lev] */
1594 lowerlimit = min((int)youmonst.data->mlevel, u.ulevel);
1596 hpmax_p = &u.uhpmax;
1597 lowerlimit = u.ulevel;
1599 if (*hpmax_p - permdmg > lowerlimit)
1600 *hpmax_p -= permdmg;
1601 else if (*hpmax_p > lowerlimit)
1602 *hpmax_p = lowerlimit;
1603 else /* unlikely... */
1604 ; /* already at or below minimum threshold; do nothing */
1608 mdamageu(mtmp, dmg);
1612 res = passiveum(olduasmon, mtmp, mattk);
1623 gulpmu(mtmp, mattk) /* monster swallows you, or damage if u.uswallow */
1624 register struct monst *mtmp;
1625 register struct attack *mattk;
1627 struct trap *t = t_at(u.ux, u.uy);
1628 int tmp = d((int)mattk->damn, (int)mattk->damd);
1630 register struct obj *otmp2;
1633 if (!u.uswallow) { /* swallows you */
1634 if (youmonst.data->msize >= MZ_HUGE) return(0);
1635 if ((t && ((t->ttyp == PIT) || (t->ttyp == SPIKED_PIT))) &&
1636 sobj_at(BOULDER, u.ux, u.uy))
1639 if (Punished) unplacebc(); /* ball&chain go away */
1640 remove_monster(mtmp->mx, mtmp->my);
1641 mtmp->mtrapped = 0; /* no longer on old trap */
1642 place_monster(mtmp, u.ux, u.uy);
1644 newsym(mtmp->mx,mtmp->my);
1646 if (is_animal(mtmp->data) && u.usteed) {
1648 /* Too many quirks presently if hero and steed
1649 * are swallowed. Pretend purple worms don't
1650 * like horses for now :-)
1652 Strcpy(buf, mon_nam(u.usteed));
1653 pline ("%s lunges forward and plucks you off %s!",
1655 dismount_steed(DISMOUNT_ENGULFED);
1658 pline("%s engulfs you!", Monnam(mtmp));
1660 reset_occupations(); /* behave as if you had moved */
1663 You("are released from the %s!",
1664 u.utraptype==TT_WEB ? "web" : "trap");
1668 i = number_leashed();
1670 const char *s = (i > 1) ? "leashes" : "leash";
1671 pline_The("%s %s loose.", s, vtense(s, "snap"));
1675 if (touch_petrifies(youmonst.data) && !resists_ston(mtmp)) {
1676 minstapetrify(mtmp, TRUE);
1677 if (mtmp->mhp > 0) return 0;
1681 display_nhwindow(WIN_MESSAGE, FALSE);
1682 vision_recalc(2); /* hero can't see anything */
1684 /* u.uswldtim always set > 1 */
1685 tim_tmp = 25 - (int)mtmp->m_lev;
1686 if (tim_tmp > 0) tim_tmp = rnd(tim_tmp) / 2;
1687 else if (tim_tmp < 0) tim_tmp = -(rnd(-tim_tmp) / 2);
1688 tim_tmp += -u.uac + 10;
1689 u.uswldtim = (unsigned)((tim_tmp < 2) ? 2 : tim_tmp);
1691 for (otmp2 = invent; otmp2; otmp2 = otmp2->nobj)
1692 (void) snuff_lit(otmp2);
1695 if (mtmp != u.ustuck) return(0);
1696 if (u.uswldtim > 0) u.uswldtim -= 1;
1698 switch(mattk->adtyp) {
1701 if (Slow_digestion) {
1702 /* Messages are handled below */
1705 } else if (u.uswldtim == 0) {
1706 pline("%s totally digests you!", Monnam(mtmp));
1708 if (Half_physical_damage) tmp *= 2; /* sorry */
1710 pline("%s%s digests you!", Monnam(mtmp),
1711 (u.uswldtim == 2) ? " thoroughly" :
1712 (u.uswldtim == 1) ? " utterly" : "");
1713 exercise(A_STR, FALSE);
1717 if (mtmp->data == &mons[PM_FOG_CLOUD]) {
1718 You("are laden with moisture and %s",
1719 flaming(youmonst.data) ? "are smoldering out!" :
1720 Breathless ? "find it mildly uncomfortable." :
1721 amphibious(youmonst.data) ? "feel comforted." :
1722 "can barely breathe!");
1723 /* NB: Amphibious includes Breathless */
1724 if (Amphibious && !flaming(youmonst.data)) tmp = 0;
1726 You("are pummeled with debris!");
1727 exercise(A_STR, FALSE);
1731 if (Acid_resistance) {
1732 You("are covered with a seemingly harmless goo.");
1735 if (Hallucination) pline("Ouch! You've been slimed!");
1736 else You("are covered in slime! It burns!");
1737 exercise(A_STR, FALSE);
1741 if (can_blnd(mtmp, &youmonst, mattk->aatyp, (struct obj*)0)) {
1743 You_cant("see in here!");
1744 make_blinded((long)tmp,FALSE);
1745 if (!Blind) Your(vision_clears);
1747 /* keep him blind until disgorged */
1748 make_blinded(Blinded+1,FALSE);
1753 if(!mtmp->mcan && rn2(2)) {
1754 pline_The("air around you crackles with electricity.");
1755 if (Shock_resistance) {
1756 shieldeff(u.ux, u.uy);
1757 You("seem unhurt.");
1758 ugolemeffects(AD_ELEC,tmp);
1764 if(!mtmp->mcan && rn2(2)) {
1765 if (Cold_resistance) {
1766 shieldeff(u.ux, u.uy);
1767 You_feel("mildly chilly.");
1768 ugolemeffects(AD_COLD,tmp);
1770 } else You("are freezing to death!");
1774 if(!mtmp->mcan && rn2(2)) {
1775 if (Fire_resistance) {
1776 shieldeff(u.ux, u.uy);
1777 You_feel("mildly hot.");
1778 ugolemeffects(AD_FIRE,tmp);
1780 } else You("are burning to a crisp!");
1785 if (!diseasemu(mtmp->data)) tmp = 0;
1792 if (Half_physical_damage) tmp = (tmp+1) / 2;
1794 mdamageu(mtmp, tmp);
1795 if (tmp) stop_occupation();
1797 if (touch_petrifies(youmonst.data) && !resists_ston(mtmp)) {
1798 pline("%s very hurriedly %s you!", Monnam(mtmp),
1799 is_animal(mtmp->data)? "regurgitates" : "expels");
1800 expels(mtmp, mtmp->data, FALSE);
1801 } else if (!u.uswldtim || youmonst.data->msize >= MZ_HUGE) {
1802 You("get %s!", is_animal(mtmp->data)? "regurgitated" : "expelled");
1803 if (flags.verbose && (is_animal(mtmp->data) ||
1804 (dmgtype(mtmp->data, AD_DGST) && Slow_digestion)))
1805 pline("Obviously %s doesn't like your taste.", mon_nam(mtmp));
1806 expels(mtmp, mtmp->data, FALSE);
1812 explmu(mtmp, mattk, ufound) /* monster explodes in your face */
1813 register struct monst *mtmp;
1814 register struct attack *mattk;
1817 if (mtmp->mcan) return(0);
1820 pline("%s explodes at a spot in %s!",
1821 canseemon(mtmp) ? Monnam(mtmp) : "It",
1822 levl[mtmp->mux][mtmp->muy].typ == WATER
1823 ? "empty water" : "thin air");
1825 register int tmp = d((int)mattk->damn, (int)mattk->damd);
1826 register boolean not_affected = defends((int)mattk->adtyp, uwep);
1828 hitmsg(mtmp, mattk);
1830 switch (mattk->adtyp) {
1832 not_affected |= Cold_resistance;
1835 not_affected |= Fire_resistance;
1838 not_affected |= Shock_resistance;
1841 if (!not_affected) {
1842 if (ACURR(A_DEX) > rnd(20)) {
1843 You("duck some of the blast.");
1846 if (flags.verbose) You("get blasted!");
1848 if (mattk->adtyp == AD_FIRE) burn_away_slime();
1849 if (Half_physical_damage) tmp = (tmp+1) / 2;
1850 mdamageu(mtmp, tmp);
1855 not_affected = resists_blnd(&youmonst);
1856 if (!not_affected) {
1857 /* sometimes you're affected even if it's invisible */
1858 if (mon_visible(mtmp) || (rnd(tmp /= 2) > u.ulevel)) {
1859 You("are blinded by a blast of light!");
1860 make_blinded((long)tmp, FALSE);
1861 if (!Blind) Your(vision_clears);
1862 } else if (flags.verbose)
1863 You("get the impression it was not terribly bright.");
1868 not_affected |= Blind ||
1869 (u.umonnum == PM_BLACK_LIGHT ||
1870 u.umonnum == PM_VIOLET_FUNGUS ||
1871 dmgtype(youmonst.data, AD_STUN));
1872 if (!not_affected) {
1875 You("are caught in a blast of kaleidoscopic light!");
1876 chg = make_hallucinated(HHallucination + (long)tmp,FALSE,0L);
1877 You("%s.", chg ? "are freaked out" : "seem unaffected");
1885 You("seem unaffected by it.");
1886 ugolemeffects((int)mattk->adtyp, tmp);
1890 wake_nearto(mtmp->mx, mtmp->my, 7*7);
1891 if (mtmp->mhp > 0) return(0);
1892 return(2); /* it dies */
1896 gazemu(mtmp, mattk) /* monster gazes at you */
1897 register struct monst *mtmp;
1898 register struct attack *mattk;
1900 switch(mattk->adtyp) {
1902 if (mtmp->mcan || !mtmp->mcansee) {
1903 if (!canseemon(mtmp)) break; /* silently */
1904 pline("%s %s.", Monnam(mtmp),
1905 (mtmp->data == &mons[PM_MEDUSA] && mtmp->mcan) ?
1906 "doesn't look all that ugly" :
1907 "gazes ineffectually");
1910 if (Reflecting && couldsee(mtmp->mx, mtmp->my) &&
1911 mtmp->data == &mons[PM_MEDUSA]) {
1912 /* hero has line of sight to Medusa and she's not blind */
1913 boolean useeit = canseemon(mtmp);
1916 (void) ureflects("%s gaze is reflected by your %s.",
1917 s_suffix(Monnam(mtmp)));
1918 if (mon_reflects(mtmp, !useeit ? (char *)0 :
1919 "The gaze is reflected away by %s %s!"))
1921 if (!m_canseeu(mtmp)) { /* probably you're invisible */
1924 "%s doesn't seem to notice that %s gaze was reflected.",
1925 Monnam(mtmp), mhis(mtmp));
1929 pline("%s is turned to stone!", Monnam(mtmp));
1933 if (mtmp->mhp > 0) break;
1936 if (canseemon(mtmp) && couldsee(mtmp->mx, mtmp->my) &&
1937 !Stone_resistance) {
1938 You("meet %s gaze.", s_suffix(mon_nam(mtmp)));
1940 if(poly_when_stoned(youmonst.data) && polymon(PM_STONE_GOLEM))
1942 You("turn to stone...");
1943 killer_format = KILLED_BY;
1944 killer = mtmp->data->mname;
1949 if(!mtmp->mcan && canseemon(mtmp) &&
1950 couldsee(mtmp->mx, mtmp->my) &&
1951 mtmp->mcansee && !mtmp->mspec_used && rn2(5)) {
1954 mtmp->mspec_used = mtmp->mspec_used + (conf + rn2(6));
1956 pline("%s gaze confuses you!",
1957 s_suffix(Monnam(mtmp)));
1959 You("are getting more and more confused.");
1960 make_confused(HConfusion + conf, FALSE);
1965 if(!mtmp->mcan && canseemon(mtmp) &&
1966 couldsee(mtmp->mx, mtmp->my) &&
1967 mtmp->mcansee && !mtmp->mspec_used && rn2(5)) {
1970 mtmp->mspec_used = mtmp->mspec_used + (stun + rn2(6));
1971 pline("%s stares piercingly at you!", Monnam(mtmp));
1972 make_stunned(HStun + stun, TRUE);
1977 if (!mtmp->mcan && canseemon(mtmp) && !resists_blnd(&youmonst)
1978 && distu(mtmp->mx,mtmp->my) <= BOLT_LIM*BOLT_LIM) {
1979 int blnd = d((int)mattk->damn, (int)mattk->damd);
1981 You("are blinded by %s radiance!",
1982 s_suffix(mon_nam(mtmp)));
1983 make_blinded((long)blnd,FALSE);
1985 /* not blind at this point implies you're wearing
1986 the Eyes of the Overworld; make them block this
1987 particular stun attack too */
1988 if (!Blind) Your(vision_clears);
1989 else make_stunned((long)d(1,3),TRUE);
1993 if (!mtmp->mcan && canseemon(mtmp) &&
1994 couldsee(mtmp->mx, mtmp->my) &&
1995 mtmp->mcansee && !mtmp->mspec_used && rn2(5)) {
1998 pline("%s attacks you with a fiery gaze!", Monnam(mtmp));
2000 if (Fire_resistance) {
2001 pline_The("fire doesn't feel hot!");
2005 if ((int) mtmp->m_lev > rn2(20))
2006 destroy_item(SCROLL_CLASS, AD_FIRE);
2007 if ((int) mtmp->m_lev > rn2(20))
2008 destroy_item(POTION_CLASS, AD_FIRE);
2009 if ((int) mtmp->m_lev > rn2(25))
2010 destroy_item(SPBOOK_CLASS, AD_FIRE);
2011 if (dmg) mdamageu(mtmp, dmg);
2014 #ifdef PM_BEHOLDER /* work in progress */
2016 if(!mtmp->mcan && canseemon(mtmp) &&
2017 couldsee(mtmp->mx, mtmp->my) && mtmp->mcansee &&
2018 multi >= 0 && !rn2(5) && !Sleep_resistance) {
2020 fall_asleep(-rnd(10), TRUE);
2021 pline("%s gaze makes you very sleepy...",
2022 s_suffix(Monnam(mtmp)));
2026 if(!mtmp->mcan && canseemon(mtmp) && mtmp->mcansee &&
2027 (HFast & (INTRINSIC|TIMEOUT)) &&
2028 !defends(AD_SLOW, uwep) && !rn2(4))
2034 default: impossible("Gaze attack %d?", mattk->adtyp);
2044 mdamageu(mtmp, n) /* mtmp hits you for n points damage */
2045 register struct monst *mtmp;
2051 if (u.mh < 1) rehumanize();
2054 if(u.uhp < 1) done_in_by(mtmp);
2063 register struct monst *mon;
2064 register struct obj *obj;
2069 if (!mon || !obj) return; /* just in case */
2070 if (dmgtype(youmonst.data, AD_CORR))
2072 else if (dmgtype(youmonst.data, AD_RUST))
2077 vis = cansee(mon->mx, mon->my);
2079 if ((is_acid ? is_corrodeable(obj) : is_rustprone(obj)) &&
2080 (is_acid ? obj->oeroded2 : obj->oeroded) < MAX_ERODE) {
2081 if (obj->greased || obj->oerodeproof || (obj->blessed && rn2(3))) {
2083 pline("Somehow, %s weapon is not affected.",
2084 s_suffix(mon_nam(mon)));
2085 if (obj->greased && !rn2(2)) obj->greased = 0;
2089 s_suffix(Monnam(mon)),
2090 aobjnam(obj, (is_acid ? "corrode" : "rust")),
2091 (is_acid ? obj->oeroded2 : obj->oeroded)
2093 if (is_acid) obj->oeroded2++;
2094 else obj->oeroded++;
2103 could_seduce(magr,mdef,mattk)
2104 struct monst *magr, *mdef;
2105 struct attack *mattk;
2106 /* returns 0 if seduction impossible,
2108 * 2 if wrong gender for nymph */
2110 register struct permonst *pagr;
2111 boolean agrinvis, defperc;
2112 xchar genagr, gendef;
2114 if (is_animal(magr->data)) return (0);
2115 if(magr == &youmonst) {
2116 pagr = youmonst.data;
2117 agrinvis = (Invis != 0);
2118 genagr = poly_gender();
2121 agrinvis = magr->minvis;
2122 genagr = gender(magr);
2124 if(mdef == &youmonst) {
2125 defperc = (See_invisible != 0);
2126 gendef = poly_gender();
2128 defperc = perceives(mdef->data);
2129 gendef = gender(mdef);
2132 if(agrinvis && !defperc
2134 && mattk && mattk->adtyp != AD_SSEX
2139 if(pagr->mlet != S_NYMPH
2140 && ((pagr != &mons[PM_INCUBUS] && pagr != &mons[PM_SUCCUBUS])
2142 || (mattk && mattk->adtyp != AD_SSEX)
2147 if(genagr == 1 - gendef)
2150 return (pagr->mlet == S_NYMPH) ? 2 : 0;
2157 /* Returns 1 if monster teleported */
2160 register struct monst *mon;
2162 register struct obj *ring, *nring;
2163 boolean fem = (mon->data == &mons[PM_SUCCUBUS]); /* otherwise incubus */
2166 if (mon->mcan || mon->mspec_used) {
2167 pline("%s acts as though %s has got a %sheadache.",
2168 Monnam(mon), mhe(mon),
2169 mon->mcan ? "severe " : "");
2173 if (unconscious()) {
2174 pline("%s seems dismayed at your lack of response.",
2179 if (Blind) pline("It caresses you...");
2180 else You_feel("very attracted to %s.", mon_nam(mon));
2182 for(ring = invent; ring; ring = nring) {
2184 if (ring->otyp != RIN_ADORNMENT) continue;
2186 if (rn2(20) < ACURR(A_CHA)) {
2187 Sprintf(qbuf, "\"That %s looks pretty. May I have it?\"",
2188 safe_qbuf("",sizeof("\"That looks pretty. May I have it?\""),
2189 xname(ring), simple_typename(ring->otyp), "ring"));
2190 makeknown(RIN_ADORNMENT);
2191 if (yn(qbuf) == 'n') continue;
2192 } else pline("%s decides she'd like your %s, and takes it.",
2193 Blind ? "She" : Monnam(mon), xname(ring));
2194 makeknown(RIN_ADORNMENT);
2195 if (ring==uleft || ring==uright) Ring_gone(ring);
2196 if (ring==uwep) setuwep((struct obj *)0);
2197 if (ring==uswapwep) setuswapwep((struct obj *)0);
2198 if (ring==uquiver) setuqwep((struct obj *)0);
2200 (void) mpickobj(mon,ring);
2204 if (uleft && uright && uleft->otyp == RIN_ADORNMENT
2205 && uright->otyp==RIN_ADORNMENT)
2207 if (ring==uleft || ring==uright) continue;
2208 if (rn2(20) < ACURR(A_CHA)) {
2209 Sprintf(qbuf,"\"That %s looks pretty. Would you wear it for me?\"",
2211 sizeof("\"That looks pretty. Would you wear it for me?\""),
2212 xname(ring), simple_typename(ring->otyp), "ring"));
2213 makeknown(RIN_ADORNMENT);
2214 if (yn(qbuf) == 'n') continue;
2216 pline("%s decides you'd look prettier wearing your %s,",
2217 Blind ? "He" : Monnam(mon), xname(ring));
2218 pline("and puts it on your finger.");
2220 makeknown(RIN_ADORNMENT);
2222 pline("%s puts %s on your right %s.",
2223 Blind ? "He" : Monnam(mon), the(xname(ring)), body_part(HAND));
2224 setworn(ring, RIGHT_RING);
2225 } else if (!uleft) {
2226 pline("%s puts %s on your left %s.",
2227 Blind ? "He" : Monnam(mon), the(xname(ring)), body_part(HAND));
2228 setworn(ring, LEFT_RING);
2229 } else if (uright && uright->otyp != RIN_ADORNMENT) {
2230 Strcpy(buf, xname(uright));
2231 pline("%s replaces your %s with your %s.",
2232 Blind ? "He" : Monnam(mon), buf, xname(ring));
2234 setworn(ring, RIGHT_RING);
2235 } else if (uleft && uleft->otyp != RIN_ADORNMENT) {
2236 Strcpy(buf, xname(uleft));
2237 pline("%s replaces your %s with your %s.",
2238 Blind ? "He" : Monnam(mon), buf, xname(ring));
2240 setworn(ring, LEFT_RING);
2241 } else impossible("ring replacement");
2243 prinv((char *)0, ring, 0L);
2247 if (!uarmc && !uarmf && !uarmg && !uarms && !uarmh
2252 pline("%s murmurs sweet nothings into your ear.",
2253 Blind ? (fem ? "She" : "He") : Monnam(mon));
2255 pline("%s murmurs in your ear, while helping you undress.",
2256 Blind ? (fem ? "She" : "He") : Monnam(mon));
2257 mayberem(uarmc, cloak_simple_name(uarmc));
2259 mayberem(uarm, "suit");
2260 mayberem(uarmf, "boots");
2261 if(!uwep || !welded(uwep))
2262 mayberem(uarmg, "gloves");
2263 mayberem(uarms, "shield");
2264 mayberem(uarmh, "helmet");
2267 mayberem(uarmu, "shirt");
2270 if (uarm || uarmc) {
2271 verbalize("You're such a %s; I wish...",
2272 flags.female ? "sweet lady" : "nice guy");
2273 if (!tele_restrict(mon)) (void) rloc(mon, FALSE);
2276 if (u.ualign.type == A_CHAOTIC)
2279 /* by this point you have discovered mon's identity, blind or not... */
2280 pline("Time stands still while you and %s lie in each other's arms...",
2282 if (rn2(35) > ACURR(A_CHA) + ACURR(A_INT)) {
2283 /* Don't bother with mspec_used here... it didn't get tired! */
2284 pline("%s seems to have enjoyed it more than you...",
2287 case 0: You_feel("drained of energy.");
2289 u.uenmax -= rnd(Half_physical_damage ? 5 : 10);
2290 exercise(A_CON, FALSE);
2291 if (u.uenmax < 0) u.uenmax = 0;
2293 case 1: You("are down in the dumps.");
2294 (void) adjattrib(A_CON, -1, TRUE);
2295 exercise(A_CON, FALSE);
2298 case 2: Your("senses are dulled.");
2299 (void) adjattrib(A_WIS, -1, TRUE);
2300 exercise(A_WIS, FALSE);
2304 if (!resists_drli(&youmonst)) {
2305 You_feel("out of shape.");
2306 losexp("overexertion");
2308 You("have a curious feeling...");
2313 You_feel("exhausted.");
2314 exercise(A_STR, FALSE);
2316 if(Half_physical_damage) tmp = (tmp+1) / 2;
2317 losehp(tmp, "exhaustion", KILLED_BY);
2322 mon->mspec_used = rnd(100); /* monster is worn out */
2323 You("seem to have enjoyed it more than %s...",
2326 case 0: You_feel("raised to your full potential.");
2327 exercise(A_CON, TRUE);
2328 u.uen = (u.uenmax += rnd(5));
2330 case 1: You_feel("good enough to do it again.");
2331 (void) adjattrib(A_CON, 1, TRUE);
2332 exercise(A_CON, TRUE);
2335 case 2: You("will always remember %s...", noit_mon_nam(mon));
2336 (void) adjattrib(A_WIS, 1, TRUE);
2337 exercise(A_WIS, TRUE);
2340 case 3: pline("That was a very educational experience.");
2342 exercise(A_WIS, TRUE);
2344 case 4: You_feel("restored to health!");
2346 if (Upolyd) u.mh = u.mhmax;
2347 exercise(A_STR, TRUE);
2353 if (mon->mtame) /* don't charge */ ;
2354 else if (rn2(20) < ACURR(A_CHA)) {
2355 pline("%s demands that you pay %s, but you refuse...",
2357 Blind ? (fem ? "her" : "him") : mhim(mon));
2358 } else if (u.umonnum == PM_LEPRECHAUN)
2359 pline("%s tries to take your money, but fails...",
2365 if (u.ugold > (long)LARGEST_INT - 10L)
2366 cost = (long) rnd(LARGEST_INT) + 500L;
2368 cost = (long) rnd((int)u.ugold + 10) + 500L;
2369 if (mon->mpeaceful) {
2371 if (!cost) cost = 1L;
2373 if (cost > u.ugold) cost = u.ugold;
2374 if (!cost) verbalize("It's on the house!");
2376 pline("%s takes %ld %s for services rendered!",
2377 noit_Monnam(mon), cost, currency(cost));
2384 long umoney = money_cnt(invent);
2386 if (umoney > (long)LARGEST_INT - 10L)
2387 cost = (long) rnd(LARGEST_INT) + 500L;
2389 cost = (long) rnd((int)umoney + 10) + 500L;
2390 if (mon->mpeaceful) {
2392 if (!cost) cost = 1L;
2394 if (cost > umoney) cost = umoney;
2395 if (!cost) verbalize("It's on the house!");
2397 pline("%s takes %ld %s for services rendered!",
2398 noit_Monnam(mon), cost, currency(cost));
2399 money2mon(mon, cost);
2404 if (!rn2(25)) mon->mcan = 1; /* monster is worn out */
2405 if (!tele_restrict(mon)) (void) rloc(mon, FALSE);
2411 register struct obj *obj;
2416 if (!obj || !obj->owornmask) return;
2418 if (rn2(20) < ACURR(A_CHA)) {
2419 Sprintf(qbuf,"\"Shall I remove your %s, %s?\"",
2421 (!rn2(2) ? "lover" : !rn2(2) ? "dear" : "sweetheart"));
2422 if (yn(qbuf) == 'n') return;
2424 char hairbuf[BUFSZ];
2426 Sprintf(hairbuf, "let me run my fingers through your %s",
2428 verbalize("Take off your %s; %s.", str,
2429 (obj == uarm) ? "let's get a little closer" :
2430 (obj == uarmc || obj == uarms) ? "it's in the way" :
2431 (obj == uarmf) ? "let me rub your feet" :
2432 (obj == uarmg) ? "they're too clumsy" :
2434 (obj == uarmu) ? "let me massage you" :
2439 remove_worn_item(obj, TRUE);
2448 passiveum(olduasmon,mtmp,mattk)
2449 struct permonst *olduasmon;
2450 register struct monst *mtmp;
2451 register struct attack *mattk;
2455 for (i = 0; ; i++) {
2456 if (i >= NATTK) return 1;
2457 if (olduasmon->mattk[i].aatyp == AT_NONE ||
2458 olduasmon->mattk[i].aatyp == AT_BOOM) break;
2460 if (olduasmon->mattk[i].damn)
2461 tmp = d((int)olduasmon->mattk[i].damn,
2462 (int)olduasmon->mattk[i].damd);
2463 else if(olduasmon->mattk[i].damd)
2464 tmp = d((int)olduasmon->mlevel+1, (int)olduasmon->mattk[i].damd);
2468 /* These affect the enemy even if you were "killed" (rehumanized) */
2469 switch(olduasmon->mattk[i].adtyp) {
2472 pline("%s is splashed by your acid!", Monnam(mtmp));
2473 if (resists_acid(mtmp)) {
2474 pline("%s is not affected.", Monnam(mtmp));
2478 if (!rn2(30)) erode_armor(mtmp, TRUE);
2479 if (!rn2(6)) erode_obj(MON_WEP(mtmp), TRUE, TRUE);
2481 case AD_STON: /* cockatrice */
2483 long protector = attk_protection((int)mattk->aatyp),
2484 wornitems = mtmp->misc_worn_check;
2486 /* wielded weapon gives same protection as gloves here */
2487 if (MON_WEP(mtmp) != 0) wornitems |= W_ARMG;
2489 if (!resists_ston(mtmp) && (protector == 0L ||
2490 (protector != ~0L &&
2491 (wornitems & protector) != protector))) {
2492 if (poly_when_stoned(mtmp->data)) {
2496 pline("%s turns to stone!", Monnam(mtmp));
2499 if (mtmp->mhp > 0) return 1;
2504 case AD_ENCH: /* KMH -- remove enchantment (disenchanter) */
2506 (void) drain_item(otmp);
2513 if (!Upolyd) return 1;
2515 /* These affect the enemy only if you are still a monster */
2516 if (rn2(3)) switch(youmonst.data->mattk[i].adtyp) {
2518 if (youmonst.data->mattk[i].aatyp == AT_BOOM) {
2520 /* KMH, balance patch -- this is okay with unchanging */
2525 case AD_PLYS: /* Floating eye */
2526 if (tmp > 127) tmp = 127;
2527 if (u.umonnum == PM_FLOATING_EYE) {
2528 if (!rn2(4)) tmp = 127;
2529 if (mtmp->mcansee && haseyes(mtmp->data) && rn2(3) &&
2530 (perceives(mtmp->data) || !Invis)) {
2532 pline("As a blind %s, you cannot defend yourself.",
2533 youmonst.data->mname);
2535 if (mon_reflects(mtmp,
2536 "Your gaze is reflected by %s %s."))
2538 pline("%s is frozen by your gaze!", Monnam(mtmp));
2540 mtmp->mfrozen = tmp;
2544 } else { /* gelatinous cube */
2545 pline("%s is frozen by you.", Monnam(mtmp));
2547 mtmp->mfrozen = tmp;
2551 case AD_COLD: /* Brown mold or blue jelly */
2552 if (resists_cold(mtmp)) {
2553 shieldeff(mtmp->mx, mtmp->my);
2554 pline("%s is mildly chilly.", Monnam(mtmp));
2555 golemeffects(mtmp, AD_COLD, tmp);
2559 pline("%s is suddenly very cold!", Monnam(mtmp));
2561 if (u.mhmax < u.mh) u.mhmax = u.mh;
2562 if (u.mhmax > ((youmonst.data->mlevel+1) * 8))
2563 (void)split_mon(&youmonst, mtmp);
2565 case AD_STUN: /* Yellow mold */
2568 pline("%s %s.", Monnam(mtmp),
2569 makeplural(stagger(mtmp->data, "stagger")));
2573 case AD_FIRE: /* Red mold */
2574 if (resists_fire(mtmp)) {
2575 shieldeff(mtmp->mx, mtmp->my);
2576 pline("%s is mildly warm.", Monnam(mtmp));
2577 golemeffects(mtmp, AD_FIRE, tmp);
2581 pline("%s is suddenly very hot!", Monnam(mtmp));
2584 if (resists_elec(mtmp)) {
2585 shieldeff(mtmp->mx, mtmp->my);
2586 pline("%s is slightly tingled.", Monnam(mtmp));
2587 golemeffects(mtmp, AD_ELEC, tmp);
2591 pline("%s is jolted with your electricity!", Monnam(mtmp));
2599 if((mtmp->mhp -= tmp) <= 0) {
2600 pline("%s dies!", Monnam(mtmp));
2602 if (mtmp->mhp > 0) return 1;
2615 register struct monst *mon;
2616 int mndx = monsndx(youmonst.data);
2618 if (u.mh <= 1) return(struct monst *)0;
2619 if (mvitals[mndx].mvflags & G_EXTINCT) return(struct monst *)0;
2620 mon = makemon(youmonst.data, u.ux, u.uy, NO_MINVENT|MM_EDOG);
2621 mon = christen_monst(mon, plname);
2623 mon->m_lev = youmonst.data->mlevel;
2624 mon->mhpmax = u.mhmax;
2625 mon->mhp = u.mh / 2;