Fandom

Wikihack

Source:SLASH'EM 0.0.7E7F2/mhitm.c

2,035pages on
this wiki
Add New Page
Talk0

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.
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. 

Ad blocker interference detected!


Wikia is a free-to-use site that makes money from advertising. We have a modified experience for viewers using ad blockers

Wikia is not accessible if you’ve made further modifications. Remove the custom ad blocker rule(s) and the page will load as expected.