Source:SLASH'EM 0.0.7E7F2/mhitm.c

From NetHackWiki
Jump to navigation Jump to search

Below is the full text to mhitm.c from the source code of SLASH'EM 0.0.7E7F2. To link to a particular line, write [[SLASH'EM 0.0.7E7F2/mhitm.c#line123]], for example.

The latest source code for vanilla NetHack is at Source code.


The NetHack General Public License applies to screenshots, source code and other content from NetHack.

This content was modified from the original NetHack source code distribution (by splitting up NetHack content between wiki pages, and possibly further editing). See the page history for a list of who changed it, and on what dates.

1.    /*	SCCS Id: @(#)mhitm.c	3.4	2003/01/02	*/
2.    /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3.    /* NetHack may be freely redistributed.  See license for details. */
4.    
5.    #include "hack.h"
6.    #include "artifact.h"
7.    #include "edog.h"
8.    
9.    extern boolean notonhead;
10.   extern const char *breathwep[];		/* from mthrowu.c */
11.   
12.   #define POLE_LIM 5	/* How far monsters can use pole-weapons */
13.   
14.   #ifdef OVLB
15.   
16.   static NEARDATA boolean vis, far_noise;
17.   static NEARDATA long noisetime;
18.   static NEARDATA struct obj *otmp;
19.   
20.   static const char brief_feeling[] =
21.   	"have a %s feeling for a moment, then it passes.";
22.   
23.   STATIC_DCL char *FDECL(mon_nam_too, (char *,struct monst *,struct monst *));
24.   STATIC_DCL void FDECL(mrustm, (struct monst *, struct monst *, struct obj *));
25.   STATIC_DCL int FDECL(breamm, (struct monst *, struct monst *, struct attack *));
26.   STATIC_DCL int FDECL(spitmm, (struct monst *, struct monst *, struct attack *));
27.   STATIC_DCL int FDECL(thrwmm, (struct monst *, struct monst *));
28.   STATIC_DCL int FDECL(hitmm, (struct monst *,struct monst *,struct attack *));
29.   STATIC_DCL int FDECL(gazemm, (struct monst *,struct monst *,struct attack *));
30.   STATIC_DCL int FDECL(gulpmm, (struct monst *,struct monst *,struct attack *));
31.   STATIC_DCL int FDECL(explmm, (struct monst *,struct monst *,struct attack *));
32.   STATIC_DCL int FDECL(mdamagem, (struct monst *,struct monst *,struct attack *));
33.   STATIC_DCL void FDECL(mswingsm, (struct monst *, struct monst *, struct obj *));
34.   STATIC_DCL void FDECL(noises,(struct monst *,struct attack *));
35.   STATIC_DCL void FDECL(missmm,(struct monst *,struct monst *, int, int, struct attack *));
36.   STATIC_DCL int FDECL(passivemm, (struct monst *, struct monst *, BOOLEAN_P, int));
37.   
38.   /* Needed for the special case of monsters wielding vorpal blades (rare).
39.    * If we use this a lot it should probably be a parameter to mdamagem()
40.    * instead of a global variable.
41.    */
42.   static int dieroll;
43.   
44.   /* returns mon_nam(mon) relative to other_mon; normal name unless they're
45.      the same, in which case the reference is to {him|her|it} self */
46.   STATIC_OVL char *
47.   mon_nam_too(outbuf, mon, other_mon)
48.   char *outbuf;
49.   struct monst *mon, *other_mon;
50.   {
51.   	Strcpy(outbuf, mon_nam(mon));
52.   	if (mon == other_mon)
53.   	    switch (pronoun_gender(mon)) {
54.   	    case 0:	Strcpy(outbuf, "himself");  break;
55.   	    case 1:	Strcpy(outbuf, "herself");  break;
56.   	    default:	Strcpy(outbuf, "itself"); break;
57.   	    }
58.   	return outbuf;
59.   }
60.   
61.   STATIC_OVL void
62.   noises(magr, mattk)
63.   	register struct monst *magr;
64.   	register struct	attack *mattk;
65.   {
66.   	boolean farq = (distu(magr->mx, magr->my) > 15);
67.   
68.   	if(flags.soundok && (farq != far_noise || moves-noisetime > 10)) {
69.   		far_noise = farq;
70.   		noisetime = moves;
71.   		You_hear("%s%s.",
72.   			(mattk->aatyp == AT_EXPL) ? "an explosion" : "some noises",
73.   			farq ? " in the distance" : "");
74.   	}
75.   }
76.   
77.   STATIC_OVL
78.   void
79.   missmm(magr, mdef, target, roll, mattk)
80.   	register struct monst *magr, *mdef;
81.   	struct attack *mattk;
82.   	int target, roll;
83.   {
84.   	boolean nearmiss = (target == roll);
85.   	const char *fmt;
86.           char buf[BUFSZ], mon_name[BUFSZ];
87.   
88.   	register struct obj *blocker = (struct obj *)0;
89.   	long mwflags = mdef->misc_worn_check;
90.   
91.   		/* 3 values for blocker
92.   		 *	No blocker:  (struct obj *) 0  
93.   		 * 	Piece of armour:  object
94.   		 */
95.   
96.   	/* This is a hack,  since there is no fast equivalent for uarm, uarms, etc.  
97.   	 * Technically, we really should check from the inside out...
98.   	 */
99.   	if (target < roll) {
100.  	    for (blocker = mdef->minvent; blocker; blocker = blocker->nobj) {
101.  		if (blocker->owornmask & mwflags) {
102.  			target += ARM_BONUS(blocker);
103.  			if (target > roll) break;
104.  		}
105.  	    }
106.  	}
107.  
108.  	if (vis) {
109.  		if (!canspotmon(magr))
110.  		    map_invisible(magr->mx, magr->my);
111.  		if (!canspotmon(mdef))
112.  		    map_invisible(mdef->mx, mdef->my);
113.  		if (mdef->m_ap_type) seemimic(mdef);
114.  		if (magr->m_ap_type) seemimic(magr);
115.  		if (flags.verbose && !nearmiss && blocker) {
116.  			fmt = "%s %s blocks";
117.  			Sprintf(buf,fmt, s_suffix(Monnam(mdef)), 
118.  				aobjnam(blocker, (char *)0));
119.  	                pline("%s %s.", buf, mon_nam_too(mon_name, magr, mdef));
120.  		} else {
121.  		fmt = (could_seduce(magr,mdef,mattk) && !magr->mcan) ?
122.  				"%s pretends to be friendly to" : 
123.  				((flags.verbose && nearmiss) ? "%s just misses" : 
124.  				  "%s misses");
125.  		Sprintf(buf, fmt, Monnam(magr));
126.  	                pline("%s %s.", buf, mon_nam_too(mon_name, mdef, magr));
127.  		}
128.  	} else  noises(magr, mattk);
129.  }
130.  
131.  /*
132.   *  fightm()  -- fight some other monster
133.   *
134.   *  Returns:
135.   *	0 - Monster did nothing.
136.   *	1 - If the monster made an attack.  The monster might have died.
137.   *
138.   *  There is an exception to the above.  If mtmp has the hero swallowed,
139.   *  then we report that the monster did nothing so it will continue to
140.   *  digest the hero.
141.   */
142.  int
143.  fightm(mtmp)		/* have monsters fight each other */
144.  	register struct monst *mtmp;
145.  {
146.  	register struct monst *mon, *nmon;
147.  	int result, has_u_swallowed;
148.  #ifdef LINT
149.  	nmon = 0;
150.  #endif
151.  	/* perhaps the monster will resist Conflict */
152.  	if(resist(mtmp, RING_CLASS, 0, 0))
153.  	    return(0);
154.  
155.  	if(u.ustuck == mtmp) {
156.  	    /* perhaps we're holding it... */
157.  	    if(itsstuck(mtmp))
158.  		return(0);
159.  	}
160.  	has_u_swallowed = (u.uswallow && (mtmp == u.ustuck));
161.  
162.  	for(mon = fmon; mon; mon = nmon) {
163.  	    nmon = mon->nmon;
164.  	    if(nmon == mtmp) nmon = mtmp->nmon;
165.  	    /* Be careful to ignore monsters that are already dead, since we
166.  	     * might be calling this before we've cleaned them up.  This can
167.  	     * happen if the monster attacked a cockatrice bare-handedly, for
168.  	     * instance.
169.  	     */
170.  	    if(mon != mtmp && !DEADMONSTER(mon)) {
171.  		if(monnear(mtmp,mon->mx,mon->my)) {
172.  		    if(!u.uswallow && (mtmp == u.ustuck)) {
173.  			if(!rn2(4)) {
174.  			    pline("%s releases you!", Monnam(mtmp));
175.  			    setustuck(0);
176.  			} else
177.  			    break;
178.  		    }
179.  
180.  		    /* mtmp can be killed */
181.  		    bhitpos.x = mon->mx;
182.  		    bhitpos.y = mon->my;
183.  		    notonhead = 0;
184.  		    result = mattackm(mtmp,mon);
185.  
186.  		    if (result & MM_AGR_DIED) return 1;	/* mtmp died */
187.  		    /*
188.  		     *  If mtmp has the hero swallowed, lie and say there
189.  		     *  was no attack (this allows mtmp to digest the hero).
190.  		     */
191.  		    if (has_u_swallowed) return 0;
192.  
193.  		    /* Allow attacked monsters a chance to hit back. Primarily
194.  		     * to allow monsters that resist conflict to respond.
195.  		     */
196.  		    if ((result & MM_HIT) && !(result & MM_DEF_DIED) &&
197.  			rn2(4) && mon->movement >= NORMAL_SPEED) {
198.  			mon->movement -= NORMAL_SPEED;
199.  			notonhead = 0;
200.  			(void) mattackm(mon, mtmp);	/* return attack */
201.  		    }
202.  
203.  		    return ((result & MM_HIT) ? 1 : 0);
204.  		}
205.  	    }
206.  	}
207.  	return 0;
208.  }
209.  
210.  /*
211.   * mattackm() -- a monster attacks another monster.
212.   *
213.   * This function returns a result bitfield:
214.   *
215.   *	    --------- aggressor died
216.   *	   /  ------- defender died
217.   *	  /  /  ----- defender was hit
218.   *	 /  /  /
219.   *	x  x  x
220.   *
221.   *	0x4	MM_AGR_DIED
222.   *	0x2	MM_DEF_DIED
223.   *	0x1	MM_HIT
224.   *	0x0	MM_MISS
225.   *
226.   * Each successive attack has a lower probability of hitting.  Some rely on the
227.   * success of previous attacks.  ** this doen't seem to be implemented -dl **
228.   *
229.   * In the case of exploding monsters, the monster dies as well.
230.   */
231.  int
232.  mattackm(magr, mdef)
233.      register struct monst *magr,*mdef;
234.  {
235.      int		    i,		/* loop counter */
236.  		    tmp,	/* amour class difference */
237.  		    strike,	/* hit this attack */
238.  		    attk,	/* attack attempted this time */
239.  		    struck = 0,	/* hit at least once */
240.  		    res[NATTK];	/* results of all attacks */
241.      struct attack   *mattk, alt_attk;
242.      struct permonst *pa, *pd;
243.      /*
244.       * Pets don't use "ranged" attacks for fear of hitting their master
245.       */
246.      boolean range;
247.  
248.      if (!magr || !mdef) return(MM_MISS);		/* mike@genat */
249.      if (!magr->mcanmove || magr->msleeping) return(MM_MISS);
250.      pa = magr->data;  pd = mdef->data;
251.  
252.      /* Grid bugs cannot attack at an angle. */
253.      if (pa == &mons[PM_GRID_BUG] && magr->mx != mdef->mx
254.  						&& magr->my != mdef->my)
255.  	return(MM_MISS);
256.  
257.      range = !magr->mtame && !monnear(magr, mdef->mx, mdef->my);
258.  
259.      /* Calculate the armour class differential. */
260.      tmp = find_mac(mdef) + magr->m_lev;
261.      if (mdef->mconf || !mdef->mcanmove || mdef->msleeping) {
262.  	tmp += 4;
263.  	mdef->msleeping = 0;
264.      }
265.  
266.      /* undetect monsters become un-hidden if they are attacked */
267.      if (mdef->mundetected) {
268.  	mdef->mundetected = 0;
269.  	newsym(mdef->mx, mdef->my);
270.  	if(canseemon(mdef) && !sensemon(mdef)) {
271.  	    if (u.usleep) You("dream of %s.",
272.  				(mdef->data->geno & G_UNIQ) ?
273.  				a_monnam(mdef) : makeplural(m_monnam(mdef)));
274.  	    else pline("Suddenly, you notice %s.", a_monnam(mdef));
275.  	}
276.      }
277.  
278.      /* Elves hate orcs. */
279.      if (is_elf(pa) && is_orc(pd)) tmp++;
280.  
281.  
282.      /* Set up the visibility of action */
283.      vis = (cansee(magr->mx,magr->my) && cansee(mdef->mx,mdef->my) && (canspotmon(magr) || canspotmon(mdef)));
284.  
285.      /*	Set flag indicating monster has moved this turn.  Necessary since a
286.       *	monster might get an attack out of sequence (i.e. before its move) in
287.       *	some cases, in which case this still counts as its move for the round
288.       *	and it shouldn't move again.
289.       */
290.      magr->mlstmv = monstermoves;
291.  
292.      /* Now perform all attacks for the monster. */
293.      for (i = 0; i < NATTK; i++) {
294.  	res[i] = MM_MISS;
295.  	mattk = getmattk(pa, i, res, &alt_attk);
296.  	otmp = (struct obj *)0;
297.  	attk = 1;
298.  	switch (mattk->aatyp) {
299.  	    case AT_BREA:
300.  	    case AT_SPIT:
301.  		if (range) {
302.  		    if (mattk->aatyp == AT_BREA)
303.  			res[i] = breamm(magr, mdef, mattk);
304.  		    else
305.  			res[i] = spitmm(magr, mdef, mattk);
306.  		    /* We can't distinguish no action from failed attack
307.  		     * so assume defender doesn't waken unless actually hit.
308.  		     */
309.  		    strike = res[i] & MM_HIT;
310.  		} else
311.  		    strike = 0;
312.  		attk = 0;
313.  		break;
314.  
315.  	    case AT_MAGC:
316.  		/* [ALI] Monster-on-monster spell casting always fails. This
317.  		 * is partly for balance reasons and partly because the
318.  		 * amount of code required to implement it is prohibitive.
319.  		 */
320.  		strike = 0;
321.  		attk = 0;
322.  		if (canseemon(magr) && couldsee(magr->mx, magr->my)) {
323.  		    char buf[BUFSZ];
324.  		    Strcpy(buf, Monnam(magr));
325.  		    if (vis)
326.  			pline("%s points at %s, then curses.", buf,
327.  				mon_nam(mdef));
328.  		    else
329.  			pline("%s points and curses at something.", buf);
330.  		} else if (flags.soundok)
331.  		    Norep("You hear a mumbled curse.");
332.  		break;
333.  
334.  	    case AT_WEAP:
335.  		/* "ranged" attacks */
336.  #ifdef REINCARNATION
337.  		if (!Is_rogue_level(&u.uz) && range) {
338.  #else
339.  		if (range) {
340.  #endif
341.  		    res[i] = thrwmm(magr, mdef);
342.  		    attk = 0;
343.  		    strike = res[i] & MM_HIT;
344.  		    break;
345.  		}
346.  		/* "hand to hand" attacks */
347.  		if (magr->weapon_check == NEED_WEAPON || !MON_WEP(magr)) {
348.  		    magr->weapon_check = NEED_HTH_WEAPON;
349.  		    if (mon_wield_item(magr) != 0) return 0;
350.  		}
351.  		possibly_unwield(magr, FALSE);
352.  		otmp = MON_WEP(magr);
353.  
354.  		if (otmp) {
355.  		    if (vis) mswingsm(magr, mdef, otmp);
356.  		    tmp += hitval(otmp, mdef);
357.  		}
358.  		/* fall through */
359.  	    case AT_CLAW:
360.  	    case AT_KICK:
361.  	    case AT_BITE:
362.  	    case AT_STNG:
363.  	    case AT_TUCH:
364.  	    case AT_BUTT:
365.  	    case AT_TENT:
366.  		/* Nymph that teleported away on first attack? */
367.  		if (distmin(magr->mx,magr->my,mdef->mx,mdef->my) > 1)
368.  		    return MM_MISS;
369.  		/* Monsters won't attack cockatrices physically if they
370.  		 * have a weapon instead.  This instinct doesn't work for
371.  		 * players, or under conflict or confusion. 
372.  		 */
373.  		if (!magr->mconf && !Conflict && otmp &&
374.  		    mattk->aatyp != AT_WEAP && touch_petrifies(mdef->data)) {
375.  		    strike = 0;
376.  		    break;
377.  		}
378.  		dieroll = rnd(20 + i);
379.  		strike = (tmp > dieroll);
380.  		if (strike) {
381.  		    res[i] = hitmm(magr, mdef, mattk);
382.  		    if((mdef->data == &mons[PM_BLACK_PUDDING] || mdef->data == &mons[PM_BROWN_PUDDING])
383.  		       && otmp && objects[otmp->otyp].oc_material == IRON
384.  		       && mdef->mhp > 1 && !mdef->mcan)
385.  		    {
386.  			if (clone_mon(mdef, 0, 0)) {
387.  			    if (vis) {
388.  				char buf[BUFSZ];
389.  
390.  				Strcpy(buf, Monnam(mdef));
391.  				pline("%s divides as %s hits it!", buf, mon_nam(magr));
392.  			    }
393.  			}
394.  		    }
395.  		} else
396.  		    missmm(magr, mdef, tmp, dieroll, mattk);
397.  		/* KMH -- don't accumulate to-hit bonuses */
398.  		if (otmp)
399.  		    tmp -= hitval(otmp, mdef);
400.  		break;
401.  
402.  	    case AT_HUGS:	/* automatic if prev two attacks succeed */
403.  		strike = (i >= 2 && res[i-1] == MM_HIT && res[i-2] == MM_HIT);
404.  		if (strike)
405.  		    res[i] = hitmm(magr, mdef, mattk);
406.  
407.  		break;
408.  
409.  	    case AT_GAZE:
410.  		strike = 0;	/* will not wake up a sleeper */
411.  		res[i] = gazemm(magr, mdef, mattk);
412.  		break;
413.  
414.  	    case AT_EXPL:
415.  		res[i] = explmm(magr, mdef, mattk);
416.  		if (res[i] == MM_MISS) { /* cancelled--no attack */
417.  		    strike = 0;
418.  		    attk = 0;
419.  		} else
420.  		    strike = 1;	/* automatic hit */
421.  		break;
422.  
423.  	    case AT_ENGL:
424.  #ifdef STEED
425.  		if (u.usteed && (mdef == u.usteed)) {
426.  		    strike = 0;
427.  		    break;
428.  		} 
429.  #endif
430.  		/* Engulfing attacks are directed at the hero if
431.  		 * possible. -dlc
432.  		 */
433.  		if (u.uswallow && magr == u.ustuck)
434.  		    strike = 0;
435.  		else {
436.  		    if ((strike = (tmp > (dieroll = rnd(20+i)))))
437.  			res[i] = gulpmm(magr, mdef, mattk);
438.  		    else
439.  			missmm(magr, mdef, tmp, dieroll, mattk);
440.  		}
441.  		break;
442.  
443.  	    default:		/* no attack */
444.  		strike = 0;
445.  		attk = 0;
446.  		break;
447.  	}
448.  
449.  	if (attk && !(res[i] & MM_AGR_DIED))
450.  	    res[i] = passivemm(magr, mdef, strike, res[i] & MM_DEF_DIED);
451.  
452.  	if (res[i] & MM_DEF_DIED) return res[i];
453.  
454.  	/*
455.  	 *  Wake up the defender.  NOTE:  this must follow the check
456.  	 *  to see if the defender died.  We don't want to modify
457.  	 *  unallocated monsters!
458.  	 */
459.  	if (strike) mdef->msleeping = 0;
460.  
461.  	if (res[i] & MM_AGR_DIED)  return res[i];
462.  	/* return if aggressor can no longer attack */
463.  	if (!magr->mcanmove || magr->msleeping) return res[i];
464.  	if (res[i] & MM_HIT) struck = 1;	/* at least one hit */
465.      }
466.  
467.      return(struck ? MM_HIT : MM_MISS);
468.  }
469.  
470.  /* monster attempts breath attack against another monster */
471.  STATIC_OVL int
472.  breamm(magr, mdef, mattk)
473.  struct monst *magr, *mdef;
474.  struct attack *mattk;
475.  {
476.      /* if new breath types are added, change AD_ACID to max type */
477.      int typ = mattk->adtyp == AD_RBRE ? rnd(AD_ACID) : mattk->adtyp;
478.      int mhp;
479.  
480.      if (linedup(mdef->mx, mdef->my, magr->mx, magr->my)) {
481.  	if (magr->mcan) {
482.  	    if (flags.soundok) {
483.  		if (canseemon(magr))
484.  		    pline("%s coughs.", Monnam(magr));
485.  		else
486.  		    You_hear("a cough.");
487.  	    }
488.  	} else if (!magr->mspec_used && rn2(3)) {
489.  	    if (typ >= AD_MAGM && typ <= AD_ACID) {
490.  		if (canseemon(magr))
491.  		    pline("%s breathes %s!", Monnam(magr), breathwep[typ-1]);
492.  		mhp = mdef->mhp;
493.  		buzz((int)(-20 - (typ-1)), (int)mattk->damn,
494.  			magr->mx, magr->my, sgn(tbx), sgn(tby));
495.  		nomul(0);
496.  		/* breath runs out sometimes. */
497.  		if (!rn2(3))
498.  		    magr->mspec_used = 10+rn2(20);
499.  		return (mdef->mhp < 1 ? MM_DEF_DIED : 0) |
500.  		       (mdef->mhp < mhp ? MM_HIT : 0) |
501.  		       (magr->mhp < 1 ? MM_AGR_DIED : 0);
502.  	    } else impossible("Breath weapon %d used", typ-1);
503.  	}
504.      }
505.      return MM_MISS;
506.  }
507.  
508.  /* monster attempts spit attack against another monster */
509.  STATIC_OVL int
510.  spitmm(magr, mdef, mattk)
511.  struct monst *magr, *mdef;
512.  struct attack *mattk;
513.  {
514.      register struct obj *obj;
515.      int mhp;
516.  
517.      if (magr->mcan) {
518.  	if (flags.soundok) {
519.  	    if (canseemon(magr))
520.  		pline("A dry rattle comes from %s throat.",
521.  			s_suffix(mon_nam(magr)));
522.  	    else
523.  		You_hear("a dry rattle.");
524.  	}
525.  	return MM_MISS;
526.      }
527.  
528.      if (linedup(mdef->mx, mdef->my, magr->mx, magr->my)) {
529.  	switch (mattk->adtyp) {
530.  	    case AD_BLND:
531.  	    case AD_DRST:
532.  		obj = mksobj(BLINDING_VENOM, TRUE, FALSE);
533.  		break;
534.  	    default:
535.  		impossible("bad attack type in spitmm");
536.  	    /* fall through */
537.  	    case AD_ACID:
538.  		obj = mksobj(ACID_VENOM, TRUE, FALSE);
539.  		break;
540.  	}
541.  	if (!rn2(BOLT_LIM - distmin(magr->mx, magr->my, mdef->mx, mdef->my))) {
542.  	    if (canseemon(magr))
543.  		pline("%s spits venom!", Monnam(magr));
544.  	    mhp = mdef->mhp;
545.  	    m_throw(magr, magr->mx, magr->my, sgn(tbx), sgn(tby),
546.  		    distmin(magr->mx, magr->my, mdef->mx, mdef->my), obj);
547.  	    nomul(0);
548.  	    return (mdef->mhp < 1 ? MM_DEF_DIED : 0) |
549.  		   (mdef->mhp < mhp ? MM_HIT : 0) |
550.  		   (magr->mhp < 1 ? MM_AGR_DIED : 0);
551.  	}
552.      }
553.      return MM_MISS;
554.  }
555.  
556.  /* monster attempts ranged weapon attack against another monster */
557.  STATIC_OVL int
558.  thrwmm(magr, mdef)
559.  struct monst *magr, *mdef;
560.  {
561.      struct obj *obj, *mwep;
562.      schar skill;
563.      int multishot, mhp;
564.      const char *onm;
565.  
566.      /* Rearranged beginning so monsters can use polearms not in a line */
567.      if (magr->weapon_check == NEED_WEAPON || !MON_WEP(magr)) {
568.  	magr->weapon_check = NEED_RANGED_WEAPON;
569.  	/* mon_wield_item resets weapon_check as appropriate */
570.  	if(mon_wield_item(magr) != 0) return MM_MISS;
571.      }
572.  
573.      /* Pick a weapon */
574.      obj = select_rwep(magr);
575.      if (!obj) return MM_MISS;
576.  
577.      if (is_pole(obj)) {
578.  	int dam, hitv, vis = canseemon(magr);
579.  
580.  	if (dist2(magr->mx, magr->my, mdef->mx, mdef->my) > POLE_LIM ||
581.  		!m_cansee(magr, mdef->mx, mdef->my))
582.  	    return MM_MISS;	/* Out of range, or intervening wall */
583.  
584.  	if (vis) {
585.  	    onm = xname(obj);
586.  	    pline("%s thrusts %s.", Monnam(magr),
587.  		  obj_is_pname(obj) ? the(onm) : an(onm));
588.  	}
589.  
590.  	dam = dmgval(obj, mdef);
591.  	hitv = 3 - distmin(mdef->mx, mdef->my, magr->mx, magr->my);
592.  	if (hitv < -4) hitv = -4;
593.  	if (bigmonst(mdef->data)) hitv++;
594.  	hitv += 8 + obj->spe;
595.  	if (dam < 1) dam = 1;
596.  
597.  	if (find_mac(mdef) + hitv <= rnd(20)) {
598.  	    if (flags.verbose && canseemon(mdef))
599.  		pline("It misses %s.", mon_nam(mdef));
600.  	    else if (vis)
601.  		pline("It misses.");
602.  	    return MM_MISS;
603.  	} else {
604.  	    if (flags.verbose && canseemon(mdef))
605.  		pline("It hits %s%s", a_monnam(mdef), exclam(dam));
606.  	    else if (vis)
607.  		pline("It hits.");
608.  	    if (objects[obj->otyp].oc_material == SILVER &&
609.  		    hates_silver(mdef->data) && canseemon(mdef)) {
610.  		if (vis)
611.  		    pline_The("silver sears %s flesh!",
612.  			    s_suffix(mon_nam(mdef)));
613.  		else
614.  		    pline("%s flesh is seared!", s_suffix(Monnam(mdef)));
615.  	    }
616.  	    mdef->mhp -= dam;
617.  	    if (mdef->mhp < 1) {
618.  		if (canseemon(mdef))
619.  		    pline("%s is %s!", Monnam(mdef),
620.  			    (nonliving(mdef->data) || !canspotmon(mdef))
621.  			    ? "destroyed" : "killed");
622.  		mondied(mdef);
623.  		return MM_DEF_DIED | MM_HIT;
624.  	    }
625.  	    else
626.  		return MM_HIT;
627.  	}
628.      }
629.  
630.      if (!linedup(mdef->mx, mdef->my, magr->mx, magr->my))
631.  	return MM_MISS;
632.  
633.      skill = objects[obj->otyp].oc_skill;
634.      mwep = MON_WEP(magr);		/* wielded weapon */
635.  
636.      if (ammo_and_launcher(obj, mwep) && objects[mwep->otyp].oc_range &&
637.  	    dist2(magr->mx, magr->my, mdef->mx, mdef->my) >
638.  	    objects[mwep->otyp].oc_range * objects[mwep->otyp].oc_range)
639.  	return MM_MISS; /* Out of range */
640.  
641.      /* Multishot calculations */
642.      multishot = 1;
643.      if ((ammo_and_launcher(obj, mwep) || skill == P_DAGGER ||
644.  	    skill == -P_DART || skill == -P_SHURIKEN) && !magr->mconf) {
645.  	/* Assumes lords are skilled, princes are expert */
646.  	if (is_prince(magr->data)) multishot += 2;
647.  	else if (is_lord(magr->data)) multishot++;
648.  
649.  	/*  Elven Craftsmanship makes for light,  quick bows */
650.  	if (obj->otyp == ELVEN_ARROW && !obj->cursed)
651.  	    multishot++;
652.  	if (mwep && mwep->otyp == ELVEN_BOW && !mwep->cursed) multishot++;
653.  	/* 1/3 of object enchantment */
654.  	if (mwep && mwep->spe > 1)
655.  	    multishot += rounddiv(mwep->spe, 3);
656.  	/* Some randomness */
657.  	if (multishot > 1)
658.  	    multishot = rnd(multishot);
659.  #ifdef FIREARMS
660.  	if (mwep && objects[mwep->otyp].oc_rof && is_launcher(mwep))
661.  	    multishot += objects[mwep->otyp].oc_rof;
662.  #endif
663.  
664.  	switch (monsndx(magr->data)) {
665.  	case PM_RANGER:
666.  		multishot++;
667.  		break;
668.  	case PM_ROGUE:
669.  		if (skill == P_DAGGER) multishot++;
670.  		break;
671.  	case PM_NINJA:
672.  	case PM_SAMURAI:
673.  		if (obj->otyp == YA && mwep &&
674.  		    mwep->otyp == YUMI) multishot++;
675.  		break;
676.  	default:
677.  	    break;
678.  	}
679.  	/* racial bonus */
680.  	if ((is_elf(magr->data) &&
681.  		obj->otyp == ELVEN_ARROW &&
682.  		mwep && mwep->otyp == ELVEN_BOW) ||
683.  	    (is_orc(magr->data) &&
684.  		obj->otyp == ORCISH_ARROW &&
685.  		mwep && mwep->otyp == ORCISH_BOW))
686.  	    multishot++;
687.  
688.  	if ((long)multishot > obj->quan) multishot = (int)obj->quan;
689.  	if (multishot < 1) multishot = 1;
690.  	/* else multishot = rnd(multishot); */
691.      }
692.  
693.      if (canseemon(magr)) {
694.  	char onmbuf[BUFSZ];
695.  
696.  	if (multishot > 1) {
697.  	    /* "N arrows"; multishot > 1 implies obj->quan > 1, so
698.  	       xname()'s result will already be pluralized */
699.  	    Sprintf(onmbuf, "%d %s", multishot, xname(obj));
700.  	    onm = onmbuf;
701.  	} else {
702.  	    /* "an arrow" */
703.  	    onm = singular(obj, xname);
704.  	    onm = obj_is_pname(obj) ? the(onm) : an(onm);
705.  	}
706.  	m_shot.s = ammo_and_launcher(obj,mwep) ? TRUE : FALSE;
707.  	pline("%s %s %s!", Monnam(magr),
708.  #ifdef FIREARMS
709.  	      m_shot.s ? is_bullet(obj) ? "fires" : "shoots" : "throws",
710.  	      onm);
711.  #else
712.  	      m_shot.s ? "shoots" : "throws", onm);
713.  #endif
714.  	m_shot.o = obj->otyp;
715.      } else {
716.  	m_shot.o = STRANGE_OBJECT;	/* don't give multishot feedback */
717.      }
718.  
719.      mhp = mdef->mhp;
720.      m_shot.n = multishot;
721.      for (m_shot.i = 1; m_shot.i <= m_shot.n; m_shot.i++)
722.  	m_throw(magr, magr->mx, magr->my, sgn(tbx), sgn(tby),
723.  		distmin(magr->mx, magr->my, mdef->mx, mdef->my), obj);
724.      m_shot.n = m_shot.i = 0;
725.      m_shot.o = STRANGE_OBJECT;
726.      m_shot.s = FALSE;
727.  
728.      nomul(0);
729.  
730.      return (mdef->mhp < 1 ? MM_DEF_DIED : 0) | (mdef->mhp < mhp ? MM_HIT : 0) |
731.  	   (magr->mhp < 1 ? MM_AGR_DIED : 0);
732.  }
733.  
734.  /* Returns the result of mdamagem(). */
735.  STATIC_OVL int
736.  hitmm(magr, mdef, mattk)
737.  	register struct monst *magr,*mdef;
738.  	struct	attack *mattk;
739.  {
740.  	if(vis){
741.  		int compat;
742.  		char buf[BUFSZ], mdef_name[BUFSZ];
743.  
744.  		if (!canspotmon(magr))
745.  		    map_invisible(magr->mx, magr->my);
746.  		if (!canspotmon(mdef))
747.  		    map_invisible(mdef->mx, mdef->my);
748.  		if(mdef->m_ap_type) seemimic(mdef);
749.  		if(magr->m_ap_type) seemimic(magr);
750.  		if((compat = could_seduce(magr,mdef,mattk)) && !magr->mcan) {
751.  			Sprintf(buf, "%s %s", Monnam(magr),
752.  				mdef->mcansee ? "smiles at" : "talks to");
753.  			pline("%s %s %s.", buf, mon_nam(mdef),
754.  				compat == 2 ?
755.  					"engagingly" : "seductively");
756.  		} else {
757.  		    char magr_name[BUFSZ];
758.  
759.  		    Strcpy(magr_name, Monnam(magr));
760.  		    switch (mattk->aatyp) {
761.  			case AT_BITE:
762.  				Sprintf(buf,"%s bites", magr_name);
763.  				break;
764.  			case AT_STNG:
765.  				Sprintf(buf,"%s stings", magr_name);
766.  				break;
767.  			case AT_BUTT:
768.  				Sprintf(buf,"%s butts", magr_name);
769.  				break;
770.  			case AT_TUCH:
771.  				Sprintf(buf,"%s touches", magr_name);
772.  				break;
773.  			case AT_TENT:
774.  				Sprintf(buf, "%s tentacles suck",
775.  					s_suffix(magr_name));
776.  				break;
777.  			case AT_HUGS:
778.  				if (magr != u.ustuck) {
779.  				    Sprintf(buf,"%s squeezes", magr_name);
780.  				    break;
781.  				}
782.  			case AT_MULTIPLY:
783.  				/* No message. */
784.  				break;
785.  			default:
786.  				Sprintf(buf,"%s hits", magr_name);
787.  		    }
788.  		    pline("%s %s.", buf, mon_nam_too(mdef_name, mdef, magr));
789.  		}
790.  	} else  noises(magr, mattk);
791.  	return(mdamagem(magr, mdef, mattk));
792.  }
793.  
794.  /* Returns the same values as mdamagem(). */
795.  STATIC_OVL int
796.  gazemm(magr, mdef, mattk)
797.  	register struct monst *magr, *mdef;
798.  	struct attack *mattk;
799.  {
800.  	char buf[BUFSZ];
801.  
802.  	if(vis) {
803.  		Sprintf(buf,"%s gazes at", Monnam(magr));
804.  		pline("%s %s...", buf, mon_nam(mdef));
805.  	}
806.  
807.  	if (magr->mcan || !magr->mcansee ||
808.  	    (magr->minvis && !perceives(mdef->data)) ||
809.  	    !mdef->mcansee || mdef->msleeping) {
810.  	    if(vis) pline("but nothing happens.");
811.  	    return(MM_MISS);
812.  	}
813.  	/* call mon_reflects 2x, first test, then, if visible, print message */
814.  	if (magr->data == &mons[PM_MEDUSA] && mon_reflects(mdef, (char *)0)) {
815.  	    if (canseemon(mdef))
816.  		(void) mon_reflects(mdef,
817.  				    "The gaze is reflected away by %s %s.");
818.  	    if (mdef->mcansee) {
819.  		if (mon_reflects(magr, (char *)0)) {
820.  		    if (canseemon(magr))
821.  			(void) mon_reflects(magr,
822.  					"The gaze is reflected away by %s %s.");
823.  		    return (MM_MISS);
824.  		}
825.  		if (mdef->minvis && !perceives(magr->data)) {
826.  		    if (canseemon(magr)) {
827.  			pline("%s doesn't seem to notice that %s gaze was reflected.",
828.  			      Monnam(magr), mhis(magr));
829.  		    }
830.  		    return (MM_MISS);
831.  		}
832.  		if (canseemon(magr))
833.  		    pline("%s is turned to stone!", Monnam(magr));
834.  		monstone(magr);
835.  		if (magr->mhp > 0) return (MM_MISS);
836.  		return (MM_AGR_DIED);
837.  	    }
838.  	}
839.  
840.  	return(mdamagem(magr, mdef, mattk));
841.  }
842.  
843.  /* Returns the same values as mattackm(). */
844.  STATIC_OVL int
845.  gulpmm(magr, mdef, mattk)
846.  	register struct monst *magr, *mdef;
847.  	register struct	attack *mattk;
848.  {
849.  	xchar	ax, ay, dx, dy;
850.  	int	status;
851.  	char buf[BUFSZ];
852.  	struct obj *obj;
853.  
854.  	if (mdef->data->msize >= MZ_HUGE) return MM_MISS;
855.  
856.  	if (vis) {
857.  		Sprintf(buf,"%s swallows", Monnam(magr));
858.  		pline("%s %s.", buf, mon_nam(mdef));
859.  	}
860.  	for (obj = mdef->minvent; obj; obj = obj->nobj)
861.  	    (void) snuff_lit(obj);
862.  
863.  	/*
864.  	 *  All of this maniuplation is needed to keep the display correct.
865.  	 *  There is a flush at the next pline().
866.  	 */
867.  	ax = magr->mx;
868.  	ay = magr->my;
869.  	dx = mdef->mx;
870.  	dy = mdef->my;
871.  	/*
872.  	 *  Leave the defender in the monster chain at it's current position,
873.  	 *  but don't leave it on the screen.  Move the agressor to the def-
874.  	 *  ender's position.
875.  	 */
876.  	remove_monster(ax, ay);
877.  	place_monster(magr, dx, dy);
878.  	newsym(ax,ay);			/* erase old position */
879.  	newsym(dx,dy);			/* update new position */
880.  
881.  	status = mdamagem(magr, mdef, mattk);
882.  
883.  	if ((status & MM_AGR_DIED) && (status & MM_DEF_DIED)) {
884.  	    ;					/* both died -- do nothing  */
885.  	}
886.  	else if (status & MM_DEF_DIED) {	/* defender died */
887.  	    /*
888.  	     *  Note:  remove_monster() was called in relmon(), wiping out
889.  	     *  magr from level.monsters[mdef->mx][mdef->my].  We need to
890.  	     *  put it back and display it.	-kd
891.  	     */
892.  	    place_monster(magr, dx, dy);
893.  	    newsym(dx, dy);
894.  	}
895.  	else if (status & MM_AGR_DIED) {	/* agressor died */
896.  	    place_monster(mdef, dx, dy);
897.  	    newsym(dx, dy);
898.  	}
899.  	else {					/* both alive, put them back */
900.  	    if (cansee(dx, dy))
901.  		pline("%s is regurgitated!", Monnam(mdef));
902.  
903.  	    place_monster(magr, ax, ay);
904.  	    place_monster(mdef, dx, dy);
905.  	    newsym(ax, ay);
906.  	    newsym(dx, dy);
907.  	}
908.  
909.  	return status;
910.  }
911.  
912.  STATIC_OVL int
913.  explmm(magr, mdef, mattk)
914.  	register struct monst *magr, *mdef;
915.  	register struct	attack *mattk;
916.  {
917.  	int result;
918.  
919.  	if (magr->mcan)
920.  	    return MM_MISS;
921.  
922.  	if(cansee(magr->mx, magr->my))
923.  		pline("%s explodes!", Monnam(magr));
924.  	else	noises(magr, mattk);
925.  
926.  	remove_monster(magr->mx, magr->my);     /* MAR */
927.  	result = mdamagem(magr, mdef, mattk);
928.  	place_monster(magr,magr->mx, magr->my); /* MAR */
929.  
930.  	/* Kill off agressor if it didn't die. */
931.  	if (!(result & MM_AGR_DIED)) {
932.  	    mondead(magr);
933.  	    if (magr->mhp > 0) return result;	/* life saved */
934.  	    result |= MM_AGR_DIED;
935.  	}
936.  	/* KMH -- Player gets blame for flame/freezing sphere */
937.  	if (magr->isspell && !(result & MM_DEF_DIED))
938.  		setmangry(mdef);
939.  	/* give this one even if it was visible, except for spell creatures */
940.  	if (magr->mtame && !magr->isspell)
941.  	    You(brief_feeling, "melancholy");
942.  
943.  	return result;
944.  }
945.  
946.  /*
947.   *  See comment at top of mattackm(), for return values.
948.   */
949.  STATIC_OVL int
950.  mdamagem(magr, mdef, mattk)
951.  	register struct monst	*magr, *mdef;
952.  	register struct attack	*mattk;
953.  {
954.  	struct obj *obj;
955.  	char buf[BUFSZ];
956.  	struct permonst *pa = magr->data, *pd = mdef->data;
957.  	int armpro, num, tmp = d((int)mattk->damn, (int)mattk->damd);
958.  	boolean cancelled;
959.  	int canhitmon, objenchant;        
960.          boolean nohit = FALSE;
961.  
962.  	if (touch_petrifies(pd) && !resists_ston(magr)) {
963.  	    long protector = attk_protection((int)mattk->aatyp),
964.  		 wornitems = magr->misc_worn_check;
965.  
966.  	    /* wielded weapon gives same protection as gloves here */
967.  	    if (otmp != 0) wornitems |= W_ARMG;
968.  
969.  	    if (protector == 0L ||
970.  		  (protector != ~0L && (wornitems & protector) != protector)) {
971.  		if (poly_when_stoned(pa)) {
972.  		    mon_to_stone(magr);
973.  		    return MM_HIT; /* no damage during the polymorph */
974.  		}
975.  		if (vis) pline("%s turns to stone!", Monnam(magr));
976.  		monstone(magr);
977.  		if (magr->mhp > 0) return 0;
978.  		else if (magr->mtame && !vis)
979.  		    You(brief_feeling, "peculiarly sad");
980.  		return MM_AGR_DIED;
981.  	    }
982.  	}
983.  
984.  	canhitmon = 0;
985.  	if (need_one(mdef))    canhitmon = 1;
986.  	if (need_two(mdef))    canhitmon = 2;
987.  	if (need_three(mdef))  canhitmon = 3;
988.  	if (need_four(mdef))   canhitmon = 4;
989.  
990.  	if (mattk->aatyp == AT_WEAP && otmp) {
991.  	    objenchant = otmp->spe;
992.  	    if (objenchant < 0) objenchant = 0;
993.  	    if (otmp->oartifact) {
994.  		if (otmp->spe < 2) objenchant += 1;
995.  		else objenchant = 2;
996.  	    }
997.  #ifdef LIGHTSABERS
998.  	    if (is_lightsaber(otmp)) objenchant = 4;
999.  #endif
1000. 	} else objenchant = 0;
1001. 
1002. 	/* a monster that needs a +1 weapon to hit it hits as a +1 weapon... */
1003. 	if (need_one(magr))    objenchant = 1;
1004. 	if (need_two(magr))    objenchant = 2;
1005. 	if (need_three(magr))  objenchant = 3;
1006. 	if (need_four(magr))   objenchant = 4;
1007. 	/* overridden by specific flags */
1008. 	if (hit_as_one(magr))    objenchant = 1;
1009. 	if (hit_as_two(magr))    objenchant = 2;
1010. 	if (hit_as_three(magr))  objenchant = 3;
1011. 	if (hit_as_four(magr))   objenchant = 4;
1012. 
1013. 	if (objenchant < canhitmon) nohit = TRUE;
1014. 
1015. 	/* cancellation factor is the same as when attacking the hero */
1016. 	armpro = magic_negation(mdef);
1017. 	cancelled = magr->mcan || !((rn2(3) >= armpro) || !rn2(50));
1018. 
1019. 	switch(mattk->adtyp) {
1020. 	    case AD_DGST:
1021. 		if (nohit) nohit = FALSE;                
1022. 		/* eating a Rider or its corpse is fatal */
1023. 		if (is_rider(mdef->data)) {
1024. 		    if (vis)
1025. 			pline("%s %s!", Monnam(magr),
1026. 			      mdef->data == &mons[PM_FAMINE] ?
1027. 				"belches feebly, shrivels up and dies" :
1028. 			      mdef->data == &mons[PM_PESTILENCE] ?
1029. 				"coughs spasmodically and collapses" :
1030. 				"vomits violently and drops dead");
1031. 		    mondied(magr);
1032. 		    if (magr->mhp > 0) return 0;	/* lifesaved */
1033. 		    else if (magr->mtame && !vis)
1034. 			You(brief_feeling, "queasy");
1035. 		    return MM_AGR_DIED;
1036. 		}
1037. 		if(flags.verbose && flags.soundok) verbalize("Burrrrp!");
1038. 		tmp = mdef->mhp;
1039. 		/* Use up amulet of life saving */
1040. 		if (!!(obj = mlifesaver(mdef))) m_useup(mdef, obj);
1041. 
1042. 		/* Is a corpse for nutrition possible?  It may kill magr */
1043. 		if (!corpse_chance(mdef, magr, TRUE) || magr->mhp < 1)
1044. 		    break;
1045. 
1046. 		/* Pets get nutrition from swallowing monster whole.
1047. 		 * No nutrition from G_NOCORPSE monster, eg, undead.
1048. 		 * DGST monsters don't die from undead corpses
1049. 		 */
1050. 		num = monsndx(mdef->data);
1051. 		if (magr->mtame && !magr->isminion &&
1052. 		    !(mvitals[num].mvflags & G_NOCORPSE)) {
1053. 		    struct obj *virtualcorpse = mksobj(CORPSE, FALSE, FALSE);
1054. 		    int nutrit;
1055. 
1056. 		    virtualcorpse->corpsenm = num;
1057. 		    virtualcorpse->owt = weight(virtualcorpse);
1058. 		    nutrit = dog_nutrition(magr, virtualcorpse);
1059. 		    dealloc_obj(virtualcorpse);
1060. 
1061. 		    /* only 50% nutrition, 25% of normal eating time */
1062. 		    if (magr->meating > 1) magr->meating = (magr->meating+3)/4;
1063. 		    if (nutrit > 1) nutrit /= 2;
1064. 		    EDOG(magr)->hungrytime += nutrit;
1065. 		}
1066. 		break;
1067. 	    case AD_STUN:
1068. 		if (magr->mcan) break;
1069. 		if (canseemon(mdef))
1070. 		    pline("%s %s for a moment.", Monnam(mdef),
1071. 			  makeplural(stagger(mdef->data, "stagger")));
1072. 		mdef->mstun = 1;
1073. 		goto physical;
1074. 	    case AD_LEGS:
1075. 		if (magr->mcan) {
1076. 		    tmp = 0;
1077. 		    break;
1078. 		}
1079. 		goto physical;
1080. 	    case AD_WERE:
1081. 	    case AD_HEAL:
1082. 	    case AD_PHYS:
1083. physical:
1084. 		if (mattk->aatyp == AT_WEAP && otmp) {
1085. 		    if (otmp->otyp == CORPSE &&
1086. 			    touch_petrifies(&mons[otmp->corpsenm]) && nohit)
1087. 			nohit = FALSE;
1088. 		} else if(nohit) break;                
1089. 		if (mattk->aatyp == AT_KICK && thick_skinned(pd)) {
1090. 		    tmp = 0;
1091. 		} else if(mattk->aatyp == AT_WEAP) {
1092. 		    if(otmp) {
1093. 			if (otmp->otyp == CORPSE &&
1094. 				touch_petrifies(&mons[otmp->corpsenm]))
1095. 			    goto do_stone;
1096. 
1097. 			/* WAC -- Real weapon?
1098. 			 * Could be stuck with a cursed bow/polearm it wielded
1099. 			 */
1100. 			if (/* if you strike with a bow... */
1101. 			    is_launcher(otmp) ||
1102. 			    /* or strike with a missile in your hand... */
1103. 			    (is_missile(otmp) || is_ammo(otmp)) ||
1104. #ifdef LIGHTSABERS
1105. 			    /* lightsaber that isn't lit ;) */
1106. 			    (is_lightsaber(otmp) && !otmp->lamplit) ||
1107. #endif
1108. 			    /* WAC -- or using a pole at short range... */
1109. 			    (is_pole(otmp))) {
1110. 			    /* then do only 1-2 points of damage */
1111. 			    if (pd == &mons[PM_SHADE] && otmp->otyp != SILVER_ARROW)
1112. 				tmp = 0;
1113. 			    else
1114. 				tmp = rnd(2);
1115. 
1116. #if 0 /* Monsters don't wield boomerangs */
1117. 		    	    if(otmp->otyp == BOOMERANG /* && !rnl(3) */) {
1118. 				pline("As %s hits you, %s breaks into splinters.",
1119. 				      mon_nam(mtmp), the(xname(otmp)));
1120. 				useup(otmp);
1121. 				otmp = (struct obj *) 0;
1122. 				possibly_unwield(mtmp);
1123. 				if (pd != &mons[PM_SHADE])
1124. 				    tmp++;
1125. 		    	    }
1126. #endif			
1127. 			} else tmp += dmgval(otmp, mdef);
1128. 
1129. 			/* MRKR: Handling damage when hitting with */
1130. 			/*       a burning torch */
1131. 
1132. 			if(otmp->otyp == TORCH && otmp->lamplit
1133. 			   && !resists_fire(mdef)) {
1134. 
1135. 			  if (!Blind) {
1136. 			    static char outbuf[BUFSZ];
1137. 			    char *s = Shk_Your(outbuf, otmp);
1138. 
1139. 			    boolean water = (mdef->data ==
1140. 					     &mons[PM_WATER_ELEMENTAL]);
1141. 
1142. 			    pline("%s %s %s%s %s%s.", s, xname(otmp),
1143. 				  (water ? "vaporize" : "burn"),
1144. 				  (otmp->quan > 1L ? "" : "s"),
1145. 				  (water ? "part of " : ""), mon_nam(mdef));
1146. 			  }
1147. 
1148. 			  burn_faster(otmp, 1);
1149. 
1150. 			  tmp++;
1151. 			  if (resists_cold(mdef)) tmp += rnd(3);
1152. 
1153. 			  if (!rn2(2) && burnarmor(mdef)) {
1154. 			    if (!rn2(3))
1155. 			      (void)destroy_mitem(mdef, POTION_CLASS, AD_FIRE);
1156. 			    if (!rn2(3))
1157. 			      (void)destroy_mitem(mdef, SCROLL_CLASS, AD_FIRE);
1158. 			    if (!rn2(5))
1159. 			      (void)destroy_mitem(mdef, SPBOOK_CLASS, AD_FIRE);
1160. 			  }
1161. 			}
1162. 
1163.                         /* WAC Weres get seared */
1164.                         if(otmp && objects[otmp->otyp].oc_material == SILVER &&
1165.                           (hates_silver(pd))) {
1166.                                 tmp += 8;
1167.                                 if (vis) pline("The silver sears %s!", mon_nam(mdef));
1168.                         }
1169.                         /* Stakes do extra dmg agains vamps */
1170.                         if (otmp && otmp->otyp == WOODEN_STAKE && is_vampire(pd)) {
1171.                                 if(otmp->oartifact == ART_STAKE_OF_VAN_HELSING) {
1172.                                         if (!rn2(10)) {
1173.                                                 if (vis) {
1174.                                                         Strcpy(buf, Monnam(magr));
1175.                                                         pline("%s plunges the stake into the heart of %s.",
1176.                                                                 buf, mon_nam(mdef));
1177.                                                         pline("%s's body vaporizes!", Monnam(mdef));
1178.                                                 }
1179.                                                 mondead(mdef); /* no corpse */
1180.                                                 if (mdef->mhp < 0) return (MM_DEF_DIED |
1181.                                                         (grow_up(magr,mdef) ? 0 : MM_AGR_DIED));                                                
1182.                                         } else {
1183.                                                 if (vis) {
1184.                                                         Strcpy(buf, Monnam(magr));
1185.                                                         pline("%s drives the stake into %s.",
1186.                                                                 buf, mon_nam(mdef));
1187.                                                 }
1188.                                                 tmp += rnd(6) + 2;
1189.                                         }
1190.                                 } else {
1191.                                         if (vis) {
1192.                                                 Strcpy(buf, Monnam(magr));
1193.                                                 pline("%s drives the stake into %s.",
1194.                                                         buf, mon_nam(mdef));
1195.                                         }
1196.                                         tmp += rnd(6);
1197.                                 }
1198.                         }
1199. 
1200.                         if (otmp && otmp->oartifact) {
1201. 			    (void)artifact_hit(magr,mdef, otmp, &tmp, dieroll);
1202. 			    if (mdef->mhp <= 0)
1203. 				return (MM_DEF_DIED |
1204. 					(grow_up(magr,mdef) ? 0 : MM_AGR_DIED));
1205. 			}
1206. 			if (otmp && tmp)
1207. 				mrustm(magr, mdef, otmp);
1208. 		    }
1209. 		} else if (magr->data == &mons[PM_PURPLE_WORM] &&
1210. 			    mdef->data == &mons[PM_SHRIEKER]) {
1211. 		    /* hack to enhance mm_aggression(); we don't want purple
1212. 		       worm's bite attack to kill a shrieker because then it
1213. 		       won't swallow the corpse; but if the target survives,
1214. 		       the subsequent engulf attack should accomplish that */
1215. 		    if (tmp >= mdef->mhp) tmp = mdef->mhp - 1;
1216. 		}
1217. 		break;
1218. 	    case AD_FIRE:
1219. 		if (nohit) break;
1220. 		
1221. 		if (cancelled) {
1222. 		    tmp = 0;
1223. 		    break;
1224. 		}
1225. 		if (vis)
1226. 		    pline("%s is %s!", Monnam(mdef),
1227. 			  on_fire(mdef->data, mattk));
1228. 		if (pd == &mons[PM_STRAW_GOLEM] ||
1229. 		    pd == &mons[PM_WAX_GOLEM] ||
1230. 		    pd == &mons[PM_PAPER_GOLEM]) {
1231. 			if (vis) pline("%s burns completely!", Monnam(mdef));
1232. 			mondied(mdef);
1233. 			if (mdef->mhp > 0) return 0;
1234. 			else if (mdef->mtame && !vis)
1235. 			    pline("May %s roast in peace.", mon_nam(mdef));
1236. 			return (MM_DEF_DIED | (grow_up(magr,mdef) ?
1237. 							0 : MM_AGR_DIED));
1238. 		}
1239. 		tmp += destroy_mitem(mdef, SCROLL_CLASS, AD_FIRE);
1240. 		tmp += destroy_mitem(mdef, SPBOOK_CLASS, AD_FIRE);
1241. 		if (resists_fire(mdef)) {
1242. 		    if (vis)
1243. 			pline_The("fire doesn't seem to burn %s!",
1244. 								mon_nam(mdef));
1245. 		    shieldeff(mdef->mx, mdef->my);
1246. 		    golemeffects(mdef, AD_FIRE, tmp);
1247. 		    tmp = 0;
1248. 		}
1249. 		/* only potions damage resistant players in destroy_item */
1250. 		tmp += destroy_mitem(mdef, POTION_CLASS, AD_FIRE);
1251. 		break;
1252. 	    case AD_COLD:
1253. 		if (nohit) break;
1254. 		
1255. 		if (cancelled) {
1256. 		    tmp = 0;
1257. 		    break;
1258. 		}
1259. 		if (vis) pline("%s is covered in frost!", Monnam(mdef));
1260. 		if (resists_cold(mdef)) {
1261. 		    if (vis)
1262. 			pline_The("frost doesn't seem to chill %s!",
1263. 								mon_nam(mdef));
1264. 		    shieldeff(mdef->mx, mdef->my);
1265. 		    golemeffects(mdef, AD_COLD, tmp);
1266. 		    tmp = 0;
1267. 		}
1268. 		tmp += destroy_mitem(mdef, POTION_CLASS, AD_COLD);
1269. 		break;
1270. 	    case AD_ELEC:
1271. 		if (nohit) break;
1272. 		
1273. 		if (cancelled) {
1274. 		    tmp = 0;
1275. 		    break;
1276. 		}
1277. 		if (vis) pline("%s gets zapped!", Monnam(mdef));
1278. 		tmp += destroy_mitem(mdef, WAND_CLASS, AD_ELEC);
1279. 		if (resists_elec(mdef)) {
1280. 		    if (vis) pline_The("zap doesn't shock %s!", mon_nam(mdef));
1281. 		    shieldeff(mdef->mx, mdef->my);
1282. 		    golemeffects(mdef, AD_ELEC, tmp);
1283. 		    tmp = 0;
1284. 		}
1285. 		/* only rings damage resistant players in destroy_item */
1286. 		tmp += destroy_mitem(mdef, RING_CLASS, AD_ELEC);
1287. 		break;
1288. 	    case AD_ACID:
1289. 		if (nohit) break;
1290. 		
1291. 		if (magr->mcan) {
1292. 		    tmp = 0;
1293. 		    break;
1294. 		}
1295. 		if (resists_acid(mdef)) {
1296. 		    if (vis)
1297. 			pline("%s is covered in acid, but it seems harmless.",
1298. 			      Monnam(mdef));
1299. 		    tmp = 0;
1300. 		} else if (vis) {
1301. 		    pline("%s is covered in acid!", Monnam(mdef));
1302. 		    pline("It burns %s!", mon_nam(mdef));
1303. 		}
1304. 		if (!rn2(30)) erode_armor(mdef, TRUE);
1305. 		if (!rn2(6)) erode_obj(MON_WEP(mdef), TRUE, TRUE);
1306. 		break;
1307. 	    case AD_RUST:
1308. 		if (magr->mcan) break;
1309. 		if (pd == &mons[PM_IRON_GOLEM]) {
1310. 			if (vis) pline("%s falls to pieces!", Monnam(mdef));
1311. 			mondied(mdef);
1312. 			if (mdef->mhp > 0) return 0;
1313. 			else if (mdef->mtame && !vis)
1314. 			    pline("May %s rust in peace.", mon_nam(mdef));
1315. 			return (MM_DEF_DIED | (grow_up(magr,mdef) ?
1316. 							0 : MM_AGR_DIED));
1317. 		}
1318. 		hurtmarmor(mdef, AD_RUST);
1319. 		mdef->mstrategy &= ~STRAT_WAITFORU;
1320. 		tmp = 0;
1321. 		break;
1322. 	    case AD_CORR:
1323. 		if (magr->mcan) break;
1324. 		hurtmarmor(mdef, AD_CORR);
1325. 		mdef->mstrategy &= ~STRAT_WAITFORU;
1326. 		tmp = 0;
1327. 		break;
1328. 	    case AD_DCAY:
1329. 		if (magr->mcan) break;
1330. 		if (pd == &mons[PM_WOOD_GOLEM] ||
1331. 		    pd == &mons[PM_LEATHER_GOLEM]) {
1332. 			if (vis) pline("%s falls to pieces!", Monnam(mdef));
1333. 			mondied(mdef);
1334. 			if (mdef->mhp > 0) return 0;
1335. 			else if (mdef->mtame && !vis)
1336. 			    pline("May %s rot in peace.", mon_nam(mdef));
1337. 			return (MM_DEF_DIED | (grow_up(magr,mdef) ?
1338. 							0 : MM_AGR_DIED));
1339. 		}
1340. 		hurtmarmor(mdef, AD_DCAY);
1341. 		tmp = 0;
1342. 		break;
1343. 	    case AD_STON:
1344. 		if (magr->mcan) break;
1345. 		if (mattk->aatyp == AT_GAZE && mon_reflects(mdef, (char *)0)) {
1346. 		    tmp = 0;
1347. 		    (void) mon_reflects(mdef, "But it reflects from %s %s!");
1348. 		    if (poly_when_stoned(pa)) {
1349. 			mon_to_stone(magr);
1350. 			break;
1351. 		    }
1352. 		    if (!resists_ston(magr)) {
1353. 			if (vis) pline("%s turns to stone!", Monnam(magr));
1354. 			monstone(magr);
1355. 			if (magr->mhp > 0) return 0;
1356. 			else if (magr->mtame && !vis)
1357. 			    You(brief_feeling, "peculiarly sad");
1358. 			return MM_AGR_DIED;
1359. 		    }
1360. 		}
1361.  do_stone:
1362. 		/* may die from the acid if it eats a stone-curing corpse */
1363. 		if (munstone(mdef, FALSE)) goto post_stone;
1364. 		if (poly_when_stoned(pd)) {
1365. 			mon_to_stone(mdef);
1366. 			tmp = 0;
1367. 			break;
1368. 		}
1369. 		if (!resists_ston(mdef)) {
1370. 			if (vis) pline("%s turns to stone!", Monnam(mdef));
1371. 			monstone(mdef);
1372.  post_stone:		if (mdef->mhp > 0) return 0;
1373. 			else if (mdef->mtame && !vis)
1374. 			    You(brief_feeling, "peculiarly sad");
1375. 			return (MM_DEF_DIED | (grow_up(magr,mdef) ?
1376. 							0 : MM_AGR_DIED));
1377. 		}
1378. 		tmp = (mattk->adtyp == AD_STON ? 0 : 1);
1379. 		break;
1380. 	    case AD_TLPT:
1381. 		if (!cancelled && tmp < mdef->mhp && !tele_restrict(mdef)) {
1382. 		    char mdef_Monnam[BUFSZ];
1383. 		    /* save the name before monster teleports, otherwise
1384. 		       we'll get "it" in the suddenly disappears message */
1385. 		    if (vis) Strcpy(mdef_Monnam, Monnam(mdef));
1386. 		    mdef->mstrategy &= ~STRAT_WAITFORU;
1387. 		    (void) rloc(mdef, FALSE);
1388. 		    if (vis && !canspotmon(mdef)
1389. #ifdef STEED
1390. 		    	&& mdef != u.usteed
1391. #endif
1392. 		    	)
1393. 			pline("%s suddenly disappears!", mdef_Monnam);
1394. 		}
1395. 		break;
1396. 	    case AD_SLEE:
1397. 		if (nohit) break;                
1398. 		
1399. 		if (cancelled) break;
1400. 		if (mattk->aatyp == AT_GAZE && mon_reflects(mdef, (char *)0)) {
1401. 		    tmp = 0;
1402. 		    (void) mon_reflects(mdef, "But it reflects from %s %s!");
1403. 		    if (sleep_monst(magr, rnd(10), -1))
1404. 			if (vis) pline("%s is put to sleep!", Monnam(magr));
1405. 		    break;
1406. 		}
1407. 
1408. 		if (!cancelled && !mdef->msleeping &&
1409. 			sleep_monst(mdef, rnd(10), -1)) {
1410. 		    if (vis) {
1411. 			Strcpy(buf, Monnam(mdef));
1412. 			pline("%s is put to sleep by %s.", buf, mon_nam(magr));
1413. 		    }
1414. 		    mdef->mstrategy &= ~STRAT_WAITFORU;
1415. 		    slept_monst(mdef);
1416. 		}
1417. 		break;
1418. 	    /* WAC DEATH (gaze) */
1419. 	    case AD_DETH:
1420. 		if (rn2(16)) {
1421. 		    /* No death, but still cause damage */
1422. 		    break;
1423. 		} 
1424. 		if (vis && mattk->aatyp == AT_GAZE) 
1425. 		    pline("%s gazes intently!", Monnam(magr));
1426. 		if (mattk->aatyp == AT_GAZE && mon_reflects(mdef, (char *)0)) {
1427. 		    /* WAC reflected gaze 
1428. 		     * Oooh boy...that was a bad move :B 
1429. 		     */
1430. 		    tmp = 0;
1431. 		    if (vis) {
1432. 			shieldeff(mdef->mx, mdef->my);
1433. 			(void) mon_reflects(mdef, "But it reflects from %s %s!");
1434. 		    }
1435. 		    if (resists_magm(magr)) {
1436. 			if (vis) pline("%s shudders momentarily...", Monnam(magr));
1437. 			break;
1438. 		    }
1439. 		    if (vis) pline("%s dies!", Monnam(magr));
1440. 		    mondied(magr);
1441. 		    if (magr->mhp > 0) return 0;  /* lifesaved */
1442. 		    else if (magr->mtame && !vis)
1443. 			You(brief_feeling, "peculiarly sad");
1444. 		    return MM_AGR_DIED;
1445. 		} else if (is_undead(mdef->data)) {
1446. 		    /* Still does normal damage */
1447. 		    if (vis) pline("Something didn't work...");
1448. 		    break;
1449. 		} else if (resists_magm(mdef)) {
1450. 		    if (vis) pline("%s shudders momentarily...", Monnam(mdef));
1451. 		} else {
1452. 		    tmp = mdef->mhp;
1453. 		}
1454. 		break;
1455. 	    case AD_PLYS:
1456. 		if (nohit) break;                
1457. 		if(!cancelled && mdef->mcanmove) {
1458. 		    if (vis) {
1459. 			Strcpy(buf, Monnam(mdef));
1460. 			pline("%s is frozen by %s.", buf, mon_nam(magr));
1461. 		    }
1462. 		    mdef->mcanmove = 0;
1463. 		    mdef->mfrozen = rnd(10);
1464. 		    mdef->mstrategy &= ~STRAT_WAITFORU;
1465. 		}
1466. 		break;
1467. 	    case AD_TCKL:
1468. 		if(!cancelled && mdef->mcanmove) {
1469. 		    if (vis) {
1470. 			Strcpy(buf, Monnam(magr));
1471. 			pline("%s mercilessly tickles %s.", buf, mon_nam(mdef));
1472. 		    }
1473. 		    mdef->mcanmove = 0;
1474. 		    mdef->mfrozen = rnd(10);
1475. 		    mdef->mstrategy &= ~STRAT_WAITFORU;
1476.   		}
1477. 		break;
1478. 	    case AD_SLOW:
1479. 		if (nohit) break;
1480. 		if(!cancelled && vis && mdef->mspeed != MSLOW) {
1481. 		    unsigned int oldspeed = mdef->mspeed;
1482. 
1483. 		    mon_adjust_speed(mdef, -1, (struct obj *)0);
1484. 		    mdef->mstrategy &= ~STRAT_WAITFORU;
1485. 		    if (mdef->mspeed != oldspeed && vis)
1486. 			pline("%s slows down.", Monnam(mdef));
1487. 		}
1488. 		break;
1489. 	    case AD_CONF:
1490. 		if (nohit) break;
1491. 		/* Since confusing another monster doesn't have a real time
1492. 		 * limit, setting spec_used would not really be right (though
1493. 		 * we still should check for it).
1494. 		 */
1495. 		if (!magr->mcan && !mdef->mconf && !magr->mspec_used) {
1496. 		    if (vis) pline("%s looks confused.", Monnam(mdef));
1497. 		    mdef->mconf = 1;
1498. 		    mdef->mstrategy &= ~STRAT_WAITFORU;
1499. 		}
1500. 		break;
1501. 	    case AD_DREN:
1502. 		if (nohit) break;
1503. 	    	if (resists_magm(mdef)) {
1504. 		    if (vis) {
1505. 			shieldeff(mdef->mx,mdef->my);
1506. 			pline("%s is unaffected.", Monnam(mdef));
1507. 		    }
1508. 	    	} else {
1509. 	    	    mon_drain_en(mdef, 
1510. 				((mdef->m_lev > 0) ? (rnd(mdef->m_lev)) : 0) + 1);
1511. 	    	}	    
1512. 	    case AD_BLND:
1513. 		if (nohit) break;                
1514. 	       
1515. 		if (can_blnd(magr, mdef, mattk->aatyp, (struct obj*)0)) {
1516. 		    register unsigned rnd_tmp;
1517. 
1518. 		    if (vis && mdef->mcansee)
1519. 			pline("%s is blinded.", Monnam(mdef));
1520. 		    rnd_tmp = d((int)mattk->damn, (int)mattk->damd);
1521. 		    if ((rnd_tmp += mdef->mblinded) > 127) rnd_tmp = 127;
1522. 		    mdef->mblinded = rnd_tmp;
1523. 		    mdef->mcansee = 0;
1524. 		    mdef->mstrategy &= ~STRAT_WAITFORU;
1525. 		}
1526. 		tmp = 0;
1527. 		break;
1528. 	    case AD_HALU:
1529. 		if (!magr->mcan && haseyes(pd) && mdef->mcansee) {
1530. 		    if (vis) pline("%s looks %sconfused.",
1531. 				    Monnam(mdef), mdef->mconf ? "more " : "");
1532. 		    mdef->mconf = 1;
1533. 		    mdef->mstrategy &= ~STRAT_WAITFORU;
1534. 		}
1535. 		tmp = 0;
1536. 		break;
1537. 	    case AD_CURS:
1538. 		if (nohit) break;
1539. 		
1540. 		if (!night() && (pa == &mons[PM_GREMLIN])) break;
1541. 		if (!magr->mcan && !rn2(10)) {
1542. 		    mdef->mcan = 1;	/* cancelled regardless of lifesave */
1543. 		    mdef->mstrategy &= ~STRAT_WAITFORU;
1544. 		    if (is_were(pd) && pd->mlet != S_HUMAN)
1545. 			were_change(mdef);
1546. 		    if (pd == &mons[PM_CLAY_GOLEM]) {
1547. 			    if (vis) {
1548. 				pline("Some writing vanishes from %s head!",
1549. 				    s_suffix(mon_nam(mdef)));
1550. 				pline("%s is destroyed!", Monnam(mdef));
1551. 			    }
1552. 			    mondied(mdef);
1553. 			    if (mdef->mhp > 0) return 0;
1554. 			    else if (mdef->mtame && !vis)
1555. 				You(brief_feeling, "strangely sad");
1556. 			    return (MM_DEF_DIED | (grow_up(magr,mdef) ?
1557. 							0 : MM_AGR_DIED));
1558. 		    }
1559. 		    if (flags.soundok) {
1560. 			    if (!vis) You_hear("laughter.");
1561. 			    else pline("%s chuckles.", Monnam(magr));
1562. 		    }
1563. 		}
1564. 		break;
1565. 	    case AD_SGLD:
1566. 		tmp = 0;
1567. #ifndef GOLDOBJ
1568. 		if (magr->mcan || !mdef->mgold) break;
1569. 		/* technically incorrect; no check for stealing gold from
1570. 		 * between mdef's feet...
1571. 		 */
1572. 		magr->mgold += mdef->mgold;
1573. 		mdef->mgold = 0;
1574. #else
1575.                 if (magr->mcan) break;
1576. 		/* technically incorrect; no check for stealing gold from
1577. 		 * between mdef's feet...
1578. 		 */
1579.                 {
1580. 		    struct obj *gold = findgold(mdef->minvent);
1581. 		    if (!gold) break;
1582.                     obj_extract_self(gold);
1583. 		    add_to_minv(magr, gold);
1584.                 }
1585. #endif
1586. 		mdef->mstrategy &= ~STRAT_WAITFORU;
1587. 		if (vis) {
1588. 		    Strcpy(buf, Monnam(magr));
1589. 		    pline("%s steals some gold from %s.", buf, mon_nam(mdef));
1590. 		}
1591. 		if (!tele_restrict(magr)) {
1592. 		    (void) rloc(magr, FALSE);
1593. 		    if (vis && !canspotmon(magr))
1594. 			pline("%s suddenly disappears!", buf);
1595. 		}
1596. 		break;
1597. 	    case AD_DRLI:
1598. 		if (nohit) break;                
1599. 
1600. 		if (!cancelled && magr->mtame && !magr->isminion &&
1601. 			is_vampire(pa) && mattk->aatyp == AT_BITE &&
1602. 			has_blood(pd))
1603. 		    EDOG(magr)->hungrytime += ((int)((mdef->data)->cnutrit / 20) + 1);
1604. 		
1605. 		if (!cancelled && rn2(2) && !resists_drli(mdef)) {
1606. 			tmp = d(2,6);
1607. 			if (vis)
1608. 			    pline("%s suddenly seems weaker!", Monnam(mdef));
1609. 			mdef->mhpmax -= tmp;
1610. 			if (mdef->m_lev == 0)
1611. 				tmp = mdef->mhp;
1612. 			else mdef->m_lev--;
1613. 			/* Automatic kill if drained past level 0 */
1614. 		}
1615. 		break;
1616. #ifdef SEDUCE
1617. 	    case AD_SSEX:
1618. #endif
1619. 	    case AD_SITM:	/* for now these are the same */
1620. 	    case AD_SEDU:
1621. 		if (magr->mcan) break;
1622. 		/* find an object to steal, non-cursed if magr is tame */
1623. 		for (obj = mdef->minvent; obj; obj = obj->nobj)
1624. 		    if (!magr->mtame || !obj->cursed)
1625. 			break;
1626. 
1627. 		if (obj) {
1628. 			char onambuf[BUFSZ], mdefnambuf[BUFSZ];
1629. 
1630. 			/* make a special x_monnam() call that never omits
1631. 			   the saddle, and save it for later messages */
1632. 			Strcpy(mdefnambuf, x_monnam(mdef, ARTICLE_THE, (char *)0, 0, FALSE));
1633. 
1634. 			otmp = obj;
1635. #ifdef STEED
1636. 			if (u.usteed == mdef &&
1637. 					otmp == which_armor(mdef, W_SADDLE))
1638. 				/* "You can no longer ride <steed>." */
1639. 				dismount_steed(DISMOUNT_POLY);
1640. #endif
1641. 			obj_extract_self(otmp);
1642. 			if (otmp->owornmask) {
1643. 				mdef->misc_worn_check &= ~otmp->owornmask;
1644. 				if (otmp->owornmask & W_WEP)
1645. 				    setmnotwielded(mdef,otmp);
1646. 				otmp->owornmask = 0L;
1647. 				update_mon_intrinsics(mdef, otmp, FALSE, FALSE);
1648. 			}
1649. 			/* add_to_minv() might free otmp [if it merges] */
1650. 			if (vis)
1651. 				Strcpy(onambuf, doname(otmp));
1652. 			(void) add_to_minv(magr, otmp);
1653. 			if (vis) {
1654. 				Strcpy(buf, Monnam(magr));
1655. 				pline("%s steals %s from %s!", buf,
1656. 				    onambuf, mdefnambuf);
1657. 			}
1658. 			possibly_unwield(mdef, FALSE);
1659. 			mdef->mstrategy &= ~STRAT_WAITFORU;
1660. 			mselftouch(mdef, (const char *)0, FALSE);
1661. 			if (mdef->mhp <= 0)
1662. 				return (MM_DEF_DIED | (grow_up(magr,mdef) ?
1663. 							0 : MM_AGR_DIED));
1664. 			if (magr->data->mlet == S_NYMPH &&
1665. 			    !tele_restrict(magr)) {
1666. 			    (void) rloc(magr, FALSE);
1667. 			    if (vis && !canspotmon(magr))
1668. 				pline("%s suddenly disappears!", buf);
1669. 			}
1670. 		}
1671. 		tmp = 0;
1672. 		break;
1673. 	    case AD_DRST:
1674. 	    case AD_DRDX:
1675. 	    case AD_DRCO:
1676. 		if (nohit) break;
1677. 		
1678. 		if (!cancelled && !rn2(8)) {
1679. 		    if (vis)
1680. 			pline("%s %s was poisoned!", s_suffix(Monnam(magr)),
1681. 			      mpoisons_subj(magr, mattk));
1682. 		    if (resists_poison(mdef)) {
1683. 			if (vis)
1684. 			    pline_The("poison doesn't seem to affect %s.",
1685. 				mon_nam(mdef));
1686. 		    } else {
1687. 			if (rn2(10)) tmp += rn1(10,6);
1688. 			else {
1689. 			    if (vis) pline_The("poison was deadly...");
1690. 			    tmp = mdef->mhp;
1691. 			}
1692. 		    }
1693. 		}
1694. 		break;
1695. 	    case AD_DRIN:
1696. 		if (notonhead || !has_head(pd)) {
1697. 		    if (vis) pline("%s doesn't seem harmed.", Monnam(mdef));
1698. 		    /* Not clear what to do for green slimes */
1699. 		    tmp = 0;
1700. 		    break;
1701. 		}
1702. 		if ((mdef->misc_worn_check & W_ARMH) && rn2(8)) {
1703. 		    if (vis) {
1704. 			Strcpy(buf, s_suffix(Monnam(mdef)));
1705. 			pline("%s helmet blocks %s attack to %s head.",
1706. 				buf, s_suffix(mon_nam(magr)),
1707. 				mhis(mdef));
1708. 		    }
1709. 		    break;
1710. 		}
1711. 		if (vis) pline("%s brain is eaten!", s_suffix(Monnam(mdef)));
1712. 		if (mindless(pd)) {
1713. 		    if (vis) pline("%s doesn't notice.", Monnam(mdef));
1714. 		    break;
1715. 		}
1716. 		tmp += rnd(10); /* fakery, since monsters lack INT scores */
1717. 		if (magr->mtame && !magr->isminion) {
1718. 		    EDOG(magr)->hungrytime += rnd(60);
1719. 		    magr->mconf = 0;
1720. 		}
1721. 		if (tmp >= mdef->mhp && vis)
1722. 		    pline("%s last thought fades away...",
1723. 			          s_suffix(Monnam(mdef)));
1724. 		break;
1725. 	    case AD_SLIM:
1726. 		if (cancelled) break;   /* physical damage only */
1727. 		if (!rn2(4) && !flaming(mdef->data) &&
1728. 				mdef->data != &mons[PM_GREEN_SLIME]) {
1729. 		    if (newcham(mdef, &mons[PM_GREEN_SLIME], FALSE, vis)) {
1730. 			mdef->oldmonnm = PM_GREEN_SLIME;
1731. 			(void) stop_timer(UNPOLY_MON, (genericptr_t) mdef);
1732. 		    }
1733. 		    mdef->mstrategy &= ~STRAT_WAITFORU;
1734. 		    tmp = 0;
1735. 		}
1736. 		break;
1737. 	    case AD_STCK:
1738. 		if (cancelled) tmp = 0;
1739. 		break;
1740. 	    case AD_WRAP: /* monsters cannot grab one another, it's too hard */
1741. 		if (magr->mcan) tmp = 0;
1742. 		break;
1743. 	    case AD_ENCH:
1744. 		/* There's no msomearmor() function, so just do damage */
1745. 	     /* if (cancelled) break; */
1746. 		break;
1747. 	    case AD_POLY:
1748. 		if (!magr->mcan && tmp < mdef->mhp) {
1749. 		    if (resists_magm(mdef)) {
1750. 			/* magic resistance protects from polymorph traps, so
1751. 			 * make it guard against involuntary polymorph attacks
1752. 			 * too... */
1753. 			if (vis) shieldeff(mdef->mx, mdef->my);
1754. 			break;
1755. 		    }
1756. #if 0
1757. 		    if (!rn2(25) || !mon_poly(mdef)) {
1758. 			if (vis)
1759. 			    pline("%s shudders!", Monnam(mdef));
1760. 			/* no corpse after system shock */
1761. 			tmp = rnd(30);
1762. 		    } else 
1763. #endif
1764. 		    (void) mon_poly(mdef, FALSE,
1765. 			    "%s undergoes a freakish metamorphosis!");
1766. 		}
1767. 		break;
1768. 	    case AD_CALM:	/* KMH -- koala attack */
1769. 		/* Certain monsters aren't even made peaceful. */
1770. 		if (!mdef->iswiz && mdef->data != &mons[PM_MEDUSA] &&
1771. 			!(mdef->data->mflags3 & M3_COVETOUS) &&
1772. 			!(mdef->data->geno & G_UNIQ) &&
1773. 			(magr->mtame || mdef->mtame)) {
1774. 		    if (vis) pline("%s looks calmer.", Monnam(mdef));
1775. 		    mdef->mpeaceful = 1;
1776. 		    mdef->mtame = 0;
1777. 		    tmp = 0;
1778. 		}
1779. 		break;
1780. 	    default:	tmp = 0;
1781. 			break;
1782. 	}
1783. 	if(!tmp) return(MM_MISS);
1784. 
1785. 	/* STEPHEN WHITE'S NEW CODE */
1786. 	if (objenchant < canhitmon && vis) {
1787. 			Strcpy(buf, Monnam(magr));
1788. 			pline("%s doesn't seem to harm %s.", buf,
1789. 								mon_nam(mdef));
1790. 		return(MM_HIT);
1791. 	}
1792. 	/* WAC -- Caveman Primal Roar ability */
1793. 	if (magr->mtame != 0 && tech_inuse(T_PRIMAL_ROAR)) {
1794. 		tmp *= 2; /* Double Damage! */
1795. 	}
1796. 	if((mdef->mhp -= tmp) < 1) {
1797. 	    if (m_at(mdef->mx, mdef->my) == magr) {  /* see gulpmm() */
1798. 		remove_monster(mdef->mx, mdef->my);
1799. 		mdef->mhp = 1;	/* otherwise place_monster will complain */
1800. 		place_monster(mdef, mdef->mx, mdef->my);
1801. 		mdef->mhp = 0;
1802. 	    }
1803. 	    /* get experience from spell creatures */
1804. 	    if (magr->uexp) mon_xkilled(mdef, "", (int)mattk->adtyp);
1805. 	    else monkilled(mdef, "", (int)mattk->adtyp);
1806. 
1807. 	    if (mdef->mhp > 0) return 0; /* mdef lifesaved */
1808. 
1809. 	    if (mattk->adtyp == AD_DGST) { 
1810. 		/* various checks similar to dog_eat and meatobj.
1811. 		 * after monkilled() to provide better message ordering */
1812. 		if (mdef->cham != CHAM_ORDINARY) {
1813. 		    (void) newcham(magr, (struct permonst *)0, FALSE, TRUE);
1814. 		} else if (mdef->data == &mons[PM_GREEN_SLIME]) {
1815. 		    (void) newcham(magr, &mons[PM_GREEN_SLIME], FALSE, TRUE);
1816. 		} else if (mdef->data == &mons[PM_WRAITH]) {
1817. 		    (void) grow_up(magr, (struct monst *)0);
1818. 		    /* don't grow up twice */
1819. 		    return (MM_DEF_DIED | (magr->mhp > 0 ? 0 : MM_AGR_DIED));
1820. 		} else if (mdef->data == &mons[PM_NURSE]) {
1821. 		    magr->mhp = magr->mhpmax;
1822. 		}
1823. 	    }
1824. 
1825. 	    return (MM_DEF_DIED |
1826. 		    ((magr->mhp > 0 && grow_up(magr,mdef)) ? 0 : MM_AGR_DIED));
1827. 	}
1828. 	return(MM_HIT);
1829. }
1830. 
1831. #endif /* OVLB */
1832. 
1833. 
1834. #ifdef OVL0
1835. 
1836. int
1837. noattacks(ptr)			/* returns 1 if monster doesn't attack */
1838. 	struct	permonst *ptr;
1839. {
1840. 	int i;
1841. 
1842. 	for(i = 0; i < NATTK; i++)
1843. 		if(ptr->mattk[i].aatyp) return(0);
1844. 
1845. 	return(1);
1846. }
1847. 
1848. /* `mon' is hit by a sleep attack; return 1 if it's affected, 0 otherwise */
1849. int
1850. sleep_monst(mon, amt, how)
1851. struct monst *mon;
1852. int amt, how;
1853. {
1854. 	if (resists_sleep(mon) ||
1855. 		(how >= 0 && resist(mon, (char)how, 0, NOTELL))) {
1856. 	    shieldeff(mon->mx, mon->my);
1857. 	} else if (mon->mcanmove) {
1858. 	    amt += (int) mon->mfrozen;
1859. 	    if (amt > 0) {	/* sleep for N turns */
1860. 		mon->mcanmove = 0;
1861. 		mon->mfrozen = min(amt, 127);
1862. 	    } else {		/* sleep until awakened */
1863. 		mon->msleeping = 1;
1864. 	    }
1865. 	    return 1;
1866. 	}
1867. 	return 0;
1868. }
1869. 
1870. /* sleeping grabber releases, engulfer doesn't; don't use for paralysis! */
1871. void
1872. slept_monst(mon)
1873. struct monst *mon;
1874. {
1875. 	if ((mon->msleeping || !mon->mcanmove) && mon == u.ustuck &&
1876. 		!sticks(youmonst.data) && !u.uswallow) {
1877. 	    pline("%s grip relaxes.", s_suffix(Monnam(mon)));
1878. 	    unstuck(mon);
1879. 	}
1880. }
1881. 
1882. #endif /* OVL0 */
1883. #ifdef OVLB
1884. 
1885. STATIC_OVL void
1886. mrustm(magr, mdef, obj)
1887. register struct monst *magr, *mdef;
1888. register struct obj *obj;
1889. {
1890. 	boolean is_acid;
1891. 
1892. 	if (!magr || !mdef || !obj) return; /* just in case */
1893. 
1894. 	if (dmgtype(mdef->data, AD_CORR))
1895. 	    is_acid = TRUE;
1896. 	else if (dmgtype(mdef->data, AD_RUST))
1897. 	    is_acid = FALSE;
1898. 	else
1899. 	    return;
1900. 
1901. 	if (!mdef->mcan &&
1902. 	    (is_acid ? is_corrodeable(obj) : is_rustprone(obj)) &&
1903. 	    (is_acid ? obj->oeroded2 : obj->oeroded) < MAX_ERODE) {
1904. 		if (obj->greased || obj->oerodeproof || (obj->blessed && rn2(3))) {
1905. 		    if (cansee(mdef->mx, mdef->my) && flags.verbose)
1906. 			pline("%s weapon is not affected.",
1907. 			                 s_suffix(Monnam(magr)));
1908. 		    if (obj->greased && !rn2(2)) obj->greased = 0;
1909. 		} else {
1910. 		    if (cansee(mdef->mx, mdef->my)) {
1911. 			pline("%s %s%s!", s_suffix(Monnam(magr)),
1912. 			    aobjnam(obj, (is_acid ? "corrode" : "rust")),
1913. 			    (is_acid ? obj->oeroded2 : obj->oeroded)
1914. 				? " further" : "");
1915. 		    }
1916. 		    if (is_acid) obj->oeroded2++;
1917. 		    else obj->oeroded++;
1918. 		}
1919. 	}
1920. }
1921. 
1922. STATIC_OVL void
1923. mswingsm(magr, mdef, otemp)
1924. register struct monst *magr, *mdef;
1925. register struct obj *otemp;
1926. {
1927. 	char buf[BUFSZ];
1928. 	if (!flags.verbose || Blind || !mon_visible(magr)) return;
1929. 	Strcpy(buf, mon_nam(mdef));
1930. 	pline("%s %s %s %s at %s.", Monnam(magr),
1931. 	      (objects[otemp->otyp].oc_dir & PIERCE) ? "thrusts" : "swings",
1932. 	      mhis(magr), singular(otemp, xname), buf);
1933. }
1934. 
1935. /*
1936.  * Passive responses by defenders.  Does not replicate responses already
1937.  * handled above.  Returns same values as mattackm.
1938.  */
1939. STATIC_OVL int
1940. passivemm(magr,mdef,mhit,mdead)
1941. register struct monst *magr, *mdef;
1942. boolean mhit;
1943. int mdead;
1944. {
1945. 	register struct permonst *mddat = mdef->data;
1946. 	register struct permonst *madat = magr->data;
1947. 	char buf[BUFSZ];
1948. 	int i, tmp;
1949. 
1950. 	for(i = 0; ; i++) {
1951. 	    if(i >= NATTK) return (mdead | mhit); /* no passive attacks */
1952. 	    if(mddat->mattk[i].aatyp == AT_NONE /*||
1953. 	       mddat->mattk[i].aatyp == AT_BOOM*/) break;
1954. 	}
1955. 	if (mddat->mattk[i].damn)
1956. 	    tmp = d((int)mddat->mattk[i].damn,
1957. 				    (int)mddat->mattk[i].damd);
1958. 	else if(mddat->mattk[i].damd)
1959. 	    tmp = d((int)mddat->mlevel+1, (int)mddat->mattk[i].damd);
1960. 	else
1961. 	    tmp = 0;
1962. 
1963. 	/* These affect the enemy even if defender killed */
1964. 	switch(mddat->mattk[i].adtyp) {
1965. 	    case AD_ACID:
1966. 		if (mhit && !rn2(2)) {
1967. 		    Strcpy(buf, Monnam(magr));
1968. 		    if(canseemon(magr))
1969. 			pline("%s is splashed by %s acid!",
1970. 			      buf, s_suffix(mon_nam(mdef)));
1971. 		    if (resists_acid(magr)) {
1972. 			if(canseemon(magr))
1973. 			    pline("%s is not affected.", Monnam(magr));
1974. 			tmp = 0;
1975. 		    }
1976. 		} else tmp = 0;
1977. 		goto assess_dmg;
1978. 		case AD_MAGM:
1979. 	    /* wrath of gods for attacking Oracle */
1980. 	    if(resists_magm(magr)) {
1981. 		if(canseemon(magr)) {
1982. 		shieldeff(magr->mx, magr->my);
1983. 		pline("A hail of magic missiles narrowly misses %s!",mon_nam(magr));
1984. 		}
1985. 	    } else {
1986. 		if(canseemon(magr))
1987. 			pline(magr->data == &mons[PM_WOODCHUCK] ? "ZOT!" : 
1988. 			"%s is hit by magic missiles appearing from thin air!",Monnam(magr));
1989. 		goto assess_dmg;
1990. 	    }
1991. 	    break;
1992. 	    case AD_ENCH:	/* KMH -- remove enchantment (disenchanter) */
1993. 		if (mhit && !mdef->mcan && otmp) {
1994. 				drain_item(otmp);
1995. 		    /* No message */
1996. 		}
1997. 		break;
1998. 	    default:
1999. 		break;
2000. 	}
2001. 	if (mdead || mdef->mcan) return (mdead|mhit);
2002. 
2003. 	/* These affect the enemy only if defender is still alive */
2004. 	if (rn2(3)) switch(mddat->mattk[i].adtyp) {
2005. 	    case AD_PLYS: /* Floating eye */
2006. 		if (tmp > 127) tmp = 127;
2007. 		if (mddat == &mons[PM_FLOATING_EYE]) {
2008. 		    if (!rn2(4)) tmp = 127;
2009. 		    if (magr->mcansee && haseyes(madat) && mdef->mcansee &&
2010. 			(perceives(madat) || !mdef->minvis)) {
2011. 			Sprintf(buf, "%s gaze is reflected by %%s %%s.",
2012. 				s_suffix(mon_nam(mdef)));
2013. 			if (mon_reflects(magr,
2014. 					 canseemon(magr) ? buf : (char *)0))
2015. 				return(mdead|mhit);
2016. 			Strcpy(buf, Monnam(magr));
2017. 			if(canseemon(magr))
2018. 			    pline("%s is frozen by %s gaze!",
2019. 				  buf, s_suffix(mon_nam(mdef)));
2020. 			magr->mcanmove = 0;
2021. 			magr->mfrozen = tmp;
2022. 			return (mdead|mhit);
2023. 		    }
2024. 		} else { /* gelatinous cube */
2025. 		    Strcpy(buf, Monnam(magr));
2026. 		    if(canseemon(magr))
2027. 			pline("%s is frozen by %s.", buf, mon_nam(mdef));
2028. 		    magr->mcanmove = 0;
2029. 		    magr->mfrozen = tmp;
2030. 		    return (mdead|mhit);
2031. 		}
2032. 		return 1;
2033. 	    case AD_COLD:
2034. 		if (resists_cold(magr)) {
2035. 		    if (canseemon(magr)) {
2036. 			pline("%s is mildly chilly.", Monnam(magr));
2037. 			golemeffects(magr, AD_COLD, tmp);
2038. 		    }
2039. 		    tmp = 0;
2040. 		    break;
2041. 		}
2042. 		if(canseemon(magr))
2043. 		    pline("%s is suddenly very cold!", Monnam(magr));
2044. 		mdef->mhp += tmp / 2;
2045. 		if (mdef->mhpmax < mdef->mhp) mdef->mhpmax = mdef->mhp;
2046. 		if (mdef->mhpmax > ((int) (mdef->m_lev+1) * 8))
2047. 		    (void)split_mon(mdef, magr);
2048. 		break;
2049. 	    case AD_STUN:
2050. 		if (!magr->mstun) {
2051. 		    magr->mstun = 1;
2052. 		    if (canseemon(magr))
2053. 			pline("%s %s...", Monnam(magr),
2054. 			      makeplural(stagger(magr->data, "stagger")));
2055. 		}
2056. 		tmp = 0;
2057. 		break;
2058. 	    case AD_FIRE:
2059. 		if (resists_fire(magr)) {
2060. 		    if (canseemon(magr)) {
2061. 			pline("%s is mildly warmed.", Monnam(magr));
2062. 			golemeffects(magr, AD_FIRE, tmp);
2063. 		    }
2064. 		    tmp = 0;
2065. 		    break;
2066. 		}
2067. 		if(canseemon(magr))
2068. 		    pline("%s is suddenly very hot!", Monnam(magr));
2069. 		break;
2070. 	    case AD_ELEC:
2071. 		if (resists_elec(magr)) {
2072. 		    if (canseemon(magr)) {
2073. 			pline("%s is mildly tingled.", Monnam(magr));
2074. 			golemeffects(magr, AD_ELEC, tmp);
2075. 		    }
2076. 		    tmp = 0;
2077. 		    break;
2078. 		}
2079. 		if(canseemon(magr))
2080. 		    pline("%s is jolted with electricity!", Monnam(magr));
2081. 		break;
2082. 	    default: tmp = 0;
2083. 		break;
2084. 	}
2085. 	else tmp = 0;
2086. 
2087.     assess_dmg:
2088. 	if((magr->mhp -= tmp) <= 0) {
2089. 		/* get experience from spell creatures */
2090. 		if (mdef->uexp) mon_xkilled(magr, "", (int)mddat->mattk[i].adtyp);
2091. 		else monkilled(magr, "", (int)mddat->mattk[i].adtyp);
2092. 
2093. 		return (mdead | mhit | MM_AGR_DIED);
2094. 	}
2095. 	return (mdead | mhit);
2096. }
2097. 
2098. /* "aggressive defense"; what type of armor prevents specified attack
2099.    from touching its target? */
2100. long
2101. attk_protection(aatyp)
2102. int aatyp;
2103. {
2104.     long w_mask = 0L;
2105. 
2106.     switch (aatyp) {
2107.     case AT_NONE:
2108.     case AT_SPIT:
2109.     case AT_EXPL:
2110.     case AT_BOOM:
2111.     case AT_GAZE:
2112.     case AT_BREA:
2113.     case AT_MAGC:
2114. 	w_mask = ~0L;		/* special case; no defense needed */
2115. 	break;
2116.     case AT_CLAW:
2117.     case AT_TUCH:
2118.     case AT_WEAP:
2119. 	w_mask = W_ARMG;	/* caller needs to check for weapon */
2120. 	break;
2121.     case AT_KICK:
2122. 	w_mask = W_ARMF;
2123. 	break;
2124.     case AT_BUTT:
2125. 	w_mask = W_ARMH;
2126. 	break;
2127.     case AT_HUGS:
2128. 	w_mask = (W_ARMC|W_ARMG); /* attacker needs both to be protected */
2129. 	break;
2130.     case AT_BITE:
2131.     case AT_STNG:
2132.     case AT_ENGL:
2133.     case AT_TENT:
2134.     default:
2135. 	w_mask = 0L;		/* no defense available */
2136. 	break;
2137.     }
2138.     return w_mask;
2139. }
2140. 
2141. #endif /* OVLB */
2142. 
2143. /*mhitm.c*/
2144.