Wikia

Wikihack

Source:Mhitm.c

2,032pages on
this wiki
Talk0

Below is the full text to src/mhitm.c from NetHack 3.4.3. To link to a particular line, write [[mhitm.c#line123]], for example.

Top of file Edit

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.    
The NetHack General Public License applies to screenshots, source code and other content from NetHack.
5.    #include "hack.h"
6.    #include "artifact.h"
7.    #include "edog.h"
8.    
9.    extern boolean notonhead;
10.   
11.   #ifdef OVLB
12.   
13.   static NEARDATA boolean vis, far_noise;
14.   static NEARDATA long noisetime;
15.   static NEARDATA struct obj *otmp;
16.   
17.   static const char brief_feeling[] =
18.   	"have a %s feeling for a moment, then it passes.";
19.   
20.   STATIC_DCL char *FDECL(mon_nam_too, (char *,struct monst *,struct monst *));
21.   STATIC_DCL void FDECL(mrustm, (struct monst *, struct monst *, struct obj *));
22.   STATIC_DCL int FDECL(hitmm, (struct monst *,struct monst *,struct attack *));
23.   STATIC_DCL int FDECL(gazemm, (struct monst *,struct monst *,struct attack *));
24.   STATIC_DCL int FDECL(gulpmm, (struct monst *,struct monst *,struct attack *));
25.   STATIC_DCL int FDECL(explmm, (struct monst *,struct monst *,struct attack *));
26.   STATIC_DCL int FDECL(mdamagem, (struct monst *,struct monst *,struct attack *));
27.   STATIC_DCL void FDECL(mswingsm, (struct monst *, struct monst *, struct obj *));
28.   STATIC_DCL void FDECL(noises,(struct monst *,struct attack *));
29.   STATIC_DCL void FDECL(missmm,(struct monst *,struct monst *,struct attack *));
30.   STATIC_DCL int FDECL(passivemm, (struct monst *, struct monst *, BOOLEAN_P, int));
31.   
32.   /* Needed for the special case of monsters wielding vorpal blades (rare).
33.    * If we use this a lot it should probably be a parameter to mdamagem()
34.    * instead of a global variable.
35.    */
36.   static int dieroll;
37.   

mon_name_too Edit

38.   /* returns mon_nam(mon) relative to other_mon; normal name unless they're
39.      the same, in which case the reference is to {him|her|it} self */
40.   STATIC_OVL char *
41.   mon_nam_too(outbuf, mon, other_mon)
42.   char *outbuf;
43.   struct monst *mon, *other_mon;
44.   {
45.   	Strcpy(outbuf, mon_nam(mon));
46.   	if (mon == other_mon)
47.   	    switch (pronoun_gender(mon)) {
48.   	    case 0:	Strcpy(outbuf, "himself");  break;
49.   	    case 1:	Strcpy(outbuf, "herself");  break;
50.   	    default:	Strcpy(outbuf, "itself"); break;
51.   	    }
52.   	return outbuf;
53.   }
54.   

noises Edit

55.   STATIC_OVL void
56.   noises(magr, mattk)
57.   	register struct monst *magr;
58.   	register struct	attack *mattk;
59.   {
60.   	boolean farq = (distu(magr->mx, magr->my) > 15);
61.   
62.   	if(flags.soundok && (farq != far_noise || moves-noisetime > 10)) {
63.   		far_noise = farq;
64.   		noisetime = moves;
65.   		You_hear("%s%s.",
66.   			(mattk->aatyp == AT_EXPL) ? "an explosion" : "some noises",
67.   			farq ? " in the distance" : "");
68.   	}
69.   }
70.   

missmm Edit

71.   STATIC_OVL
72.   void
73.   missmm(magr, mdef, mattk)
74.   	register struct monst *magr, *mdef;
75.   	struct attack *mattk;
76.   {
77.   	const char *fmt;
78.   	char buf[BUFSZ], mdef_name[BUFSZ];
79.   
80.   	if (vis) {
81.   		if (!canspotmon(magr))
82.   		    map_invisible(magr->mx, magr->my);
83.   		if (!canspotmon(mdef))
84.   		    map_invisible(mdef->mx, mdef->my);
85.   		if (mdef->m_ap_type) seemimic(mdef);
86.   		if (magr->m_ap_type) seemimic(magr);
87.   		fmt = (could_seduce(magr,mdef,mattk) && !magr->mcan) ?
88.   			"%s pretends to be friendly to" : "%s misses";
89.   		Sprintf(buf, fmt, Monnam(magr));
90.   		pline("%s %s.", buf, mon_nam_too(mdef_name, mdef, magr));
91.   	} else  noises(magr, mattk);
92.   }
93.   

fightm Edit

94.   /*
95.    *  fightm()  -- fight some other monster
96.    *
97.    *  Returns:
98.    *	0 - Monster did nothing.
99.    *	1 - If the monster made an attack.  The monster might have died.
100.   *
101.   *  There is an exception to the above.  If mtmp has the hero swallowed,
102.   *  then we report that the monster did nothing so it will continue to
103.   *  digest the hero.
104.   */
105.  int
106.  fightm(mtmp)		/* have monsters fight each other */
107.  	register struct monst *mtmp;
108.  {
109.  	register struct monst *mon, *nmon;
110.  	int result, has_u_swallowed;
111.  #ifdef LINT
112.  	nmon = 0;
113.  #endif
114.  	/* perhaps the monster will resist Conflict */
115.  	if(resist(mtmp, RING_CLASS, 0, 0))
116.  	    return(0);
117.  
118.  	if(u.ustuck == mtmp) {
119.  	    /* perhaps we're holding it... */
120.  	    if(itsstuck(mtmp))
121.  		return(0);
122.  	}
123.  	has_u_swallowed = (u.uswallow && (mtmp == u.ustuck));
124.  
125.  	for(mon = fmon; mon; mon = nmon) {
126.  	    nmon = mon->nmon;
127.  	    if(nmon == mtmp) nmon = mtmp->nmon;
128.  	    /* Be careful to ignore monsters that are already dead, since we
129.  	     * might be calling this before we've cleaned them up.  This can
130.  	     * happen if the monster attacked a cockatrice bare-handedly, for
131.  	     * instance.
132.  	     */
133.  	    if(mon != mtmp && !DEADMONSTER(mon)) {
134.  		if(monnear(mtmp,mon->mx,mon->my)) {
135.  		    if(!u.uswallow && (mtmp == u.ustuck)) {
136.  			if(!rn2(4)) {
137.  			    pline("%s releases you!", Monnam(mtmp));
138.  			    u.ustuck = 0;
139.  			} else
140.  			    break;
141.  		    }
142.  
143.  		    /* mtmp can be killed */
144.  		    bhitpos.x = mon->mx;
145.  		    bhitpos.y = mon->my;
146.  		    notonhead = 0;
147.  		    result = mattackm(mtmp,mon);
148.  
149.  		    if (result & MM_AGR_DIED) return 1;	/* mtmp died */
150.  		    /*
151.  		     *  If mtmp has the hero swallowed, lie and say there
152.  		     *  was no attack (this allows mtmp to digest the hero).
153.  		     */
154.  		    if (has_u_swallowed) return 0;
155.  
156.  		    /* Allow attacked monsters a chance to hit back. Primarily
157.  		     * to allow monsters that resist conflict to respond.
158.  		     */
159.  		    if ((result & MM_HIT) && !(result & MM_DEF_DIED) &&
160.  			rn2(4) && mon->movement >= NORMAL_SPEED) {
161.  			mon->movement -= NORMAL_SPEED;
162.  			notonhead = 0;
163.  			(void) mattackm(mon, mtmp);	/* return attack */
164.  		    }
165.  
166.  		    return ((result & MM_HIT) ? 1 : 0);
167.  		}
168.  	    }
169.  	}
170.  	return 0;
171.  }
172.  

mattackm Edit

173.  /*
174.   * mattackm() -- a monster attacks another monster.
175.   *
176.   * This function returns a result bitfield:
177.   *
178.   *	    --------- aggressor died
179.   *	   /  ------- defender died
180.   *	  /  /  ----- defender was hit
181.   *	 /  /  /
182.   *	x  x  x
183.   *
184.   *	0x4	MM_AGR_DIED
185.   *	0x2	MM_DEF_DIED
186.   *	0x1	MM_HIT
187.   *	0x0	MM_MISS
188.   *
189.   * Each successive attack has a lower probability of hitting.  Some rely on the
190.   * success of previous attacks.  ** this doen't seem to be implemented -dl **
191.   *
192.   * In the case of exploding monsters, the monster dies as well.
193.   */
194.  int
195.  mattackm(magr, mdef)
196.      register struct monst *magr,*mdef;
197.  {
198.      int		    i,		/* loop counter */
199.  		    tmp,	/* amour class difference */
200.  		    strike,	/* hit this attack */
201.  		    attk,	/* attack attempted this time */
202.  		    struck = 0,	/* hit at least once */
203.  		    res[NATTK];	/* results of all attacks */
204.      struct attack   *mattk, alt_attk;
205.      struct permonst *pa, *pd;
206.  
207.      if (!magr || !mdef) return(MM_MISS);		/* mike@genat */
208.      if (!magr->mcanmove || magr->msleeping) return(MM_MISS);
209.      pa = magr->data;  pd = mdef->data;
210.  
211.      /* Grid bugs cannot attack at an angle. */
212.      if (pa == &mons[PM_GRID_BUG] && magr->mx != mdef->mx
213.  						&& magr->my != mdef->my)
214.  	return(MM_MISS);
215.  
216.      /* Calculate the armour class differential. */
217.      tmp = find_mac(mdef) + magr->m_lev;
218.      if (mdef->mconf || !mdef->mcanmove || mdef->msleeping) {
219.  	tmp += 4;
220.  	mdef->msleeping = 0;
221.      }
222.  
223.      /* undetect monsters become un-hidden if they are attacked */
224.      if (mdef->mundetected) {
225.  	mdef->mundetected = 0;
226.  	newsym(mdef->mx, mdef->my);
227.  	if(canseemon(mdef) && !sensemon(mdef)) {
228.  	    if (u.usleep) You("dream of %s.",
229.  				(mdef->data->geno & G_UNIQ) ?
230.  				a_monnam(mdef) : makeplural(m_monnam(mdef)));
231.  	    else pline("Suddenly, you notice %s.", a_monnam(mdef));
232.  	}
233.      }
234.  
235.      /* Elves hate orcs. */
236.      if (is_elf(pa) && is_orc(pd)) tmp++;
237.  
238.  
239.      /* Set up the visibility of action */
240.      vis = (cansee(magr->mx,magr->my) && cansee(mdef->mx,mdef->my) && (canspotmon(magr) || canspotmon(mdef)));
241.  
242.      /*	Set flag indicating monster has moved this turn.  Necessary since a
243.       *	monster might get an attack out of sequence (i.e. before its move) in
244.       *	some cases, in which case this still counts as its move for the round
245.       *	and it shouldn't move again.
246.       */
247.      magr->mlstmv = monstermoves;
248.  
249.      /* Now perform all attacks for the monster. */
250.      for (i = 0; i < NATTK; i++) {
251.  	res[i] = MM_MISS;
252.  	mattk = getmattk(pa, i, res, &alt_attk);
253.  	otmp = (struct obj *)0;
254.  	attk = 1;
255.  	switch (mattk->aatyp) {
256.  	    case AT_WEAP:		/* "hand to hand" attacks */
257.  		if (magr->weapon_check == NEED_WEAPON || !MON_WEP(magr)) {
258.  		    magr->weapon_check = NEED_HTH_WEAPON;
259.  		    if (mon_wield_item(magr) != 0) return 0;
260.  		}
261.  		possibly_unwield(magr, FALSE);
262.  		otmp = MON_WEP(magr);
263.  
264.  		if (otmp) {
265.  		    if (vis) mswingsm(magr, mdef, otmp);
266.  		    tmp += hitval(otmp, mdef);
267.  		}
268.  		/* fall through */
269.  	    case AT_CLAW:
270.  	    case AT_KICK:
271.  	    case AT_BITE:
272.  	    case AT_STNG:
273.  	    case AT_TUCH:
274.  	    case AT_BUTT:
275.  	    case AT_TENT:
276.  		/* Nymph that teleported away on first attack? */
277.  		if (distmin(magr->mx,magr->my,mdef->mx,mdef->my) > 1)
278.  		    return MM_MISS;
279.  		/* Monsters won't attack cockatrices physically if they
280.  		 * have a weapon instead.  This instinct doesn't work for
281.  		 * players, or under conflict or confusion. 
282.  		 */
283.  		if (!magr->mconf && !Conflict && otmp &&
284.  		    mattk->aatyp != AT_WEAP && touch_petrifies(mdef->data)) {
285.  		    strike = 0;
286.  		    break;
287.  		}
288.  		dieroll = rnd(20 + i);
289.  		strike = (tmp > dieroll);
290.  		/* KMH -- don't accumulate to-hit bonuses */
291.  		if (otmp)
292.  		    tmp -= hitval(otmp, mdef);
293.  		if (strike) {
294.  		    res[i] = hitmm(magr, mdef, mattk);
295.  		    if((mdef->data == &mons[PM_BLACK_PUDDING] || mdef->data == &mons[PM_BROWN_PUDDING])
296.  		       && otmp && objects[otmp->otyp].oc_material == IRON
297.  		       && mdef->mhp > 1 && !mdef->mcan)
298.  		    {
299.  			if (clone_mon(mdef, 0, 0)) {
300.  			    if (vis) {
301.  				char buf[BUFSZ];
302.  
303.  				Strcpy(buf, Monnam(mdef));
304.  				pline("%s divides as %s hits it!", buf, mon_nam(magr));
305.  			    }
306.  			}
307.  		    }
308.  		} else
309.  		    missmm(magr, mdef, mattk);
310.  		break;
311.  
312.  	    case AT_HUGS:	/* automatic if prev two attacks succeed */
313.  		strike = (i >= 2 && res[i-1] == MM_HIT && res[i-2] == MM_HIT);
314.  		if (strike)
315.  		    res[i] = hitmm(magr, mdef, mattk);
316.  
317.  		break;
318.  
319.  	    case AT_GAZE:
320.  		strike = 0;	/* will not wake up a sleeper */
321.  		res[i] = gazemm(magr, mdef, mattk);
322.  		break;
323.  
324.  	    case AT_EXPL:
325.  		res[i] = explmm(magr, mdef, mattk);
326.  		if (res[i] == MM_MISS) { /* cancelled--no attack */
327.  		    strike = 0;
328.  		    attk = 0;
329.  		} else
330.  		    strike = 1;	/* automatic hit */
331.  		break;
332.  
333.  	    case AT_ENGL:
334.  #ifdef STEED
335.  		if (u.usteed && (mdef == u.usteed)) {
336.  		    strike = 0;
337.  		    break;
338.  		} 
339.  #endif
340.  		/* Engulfing attacks are directed at the hero if
341.  		 * possible. -dlc
342.  		 */
343.  		if (u.uswallow && magr == u.ustuck)
344.  		    strike = 0;
345.  		else {
346.  		    if ((strike = (tmp > rnd(20+i))))
347.  			res[i] = gulpmm(magr, mdef, mattk);
348.  		    else
349.  			missmm(magr, mdef, mattk);
350.  		}
351.  		break;
352.  
353.  	    default:		/* no attack */
354.  		strike = 0;
355.  		attk = 0;
356.  		break;
357.  	}
358.  
359.  	if (attk && !(res[i] & MM_AGR_DIED))
360.  	    res[i] = passivemm(magr, mdef, strike, res[i] & MM_DEF_DIED);
361.  
362.  	if (res[i] & MM_DEF_DIED) return res[i];
363.  
364.  	/*
365.  	 *  Wake up the defender.  NOTE:  this must follow the check
366.  	 *  to see if the defender died.  We don't want to modify
367.  	 *  unallocated monsters!
368.  	 */
369.  	if (strike) mdef->msleeping = 0;
370.  
371.  	if (res[i] & MM_AGR_DIED)  return res[i];
372.  	/* return if aggressor can no longer attack */
373.  	if (!magr->mcanmove || magr->msleeping) return res[i];
374.  	if (res[i] & MM_HIT) struck = 1;	/* at least one hit */
375.      }
376.  
377.      return(struck ? MM_HIT : MM_MISS);
378.  }
379.  

hitmm Edit

380.  /* Returns the result of mdamagem(). */
381.  STATIC_OVL int
382.  hitmm(magr, mdef, mattk)
383.  	register struct monst *magr,*mdef;
384.  	struct	attack *mattk;
385.  {
386.  	if(vis){
387.  		int compat;
388.  		char buf[BUFSZ], mdef_name[BUFSZ];
389.  
390.  		if (!canspotmon(magr))
391.  		    map_invisible(magr->mx, magr->my);
392.  		if (!canspotmon(mdef))
393.  		    map_invisible(mdef->mx, mdef->my);
394.  		if(mdef->m_ap_type) seemimic(mdef);
395.  		if(magr->m_ap_type) seemimic(magr);
396.  		if((compat = could_seduce(magr,mdef,mattk)) && !magr->mcan) {
397.  			Sprintf(buf, "%s %s", Monnam(magr),
398.  				mdef->mcansee ? "smiles at" : "talks to");
399.  			pline("%s %s %s.", buf, mon_nam(mdef),
400.  				compat == 2 ?
401.  					"engagingly" : "seductively");
402.  		} else {
403.  		    char magr_name[BUFSZ];
404.  
405.  		    Strcpy(magr_name, Monnam(magr));
406.  		    switch (mattk->aatyp) {
407.  			case AT_BITE:
408.  				Sprintf(buf,"%s bites", magr_name);
409.  				break;
410.  			case AT_STNG:
411.  				Sprintf(buf,"%s stings", magr_name);
412.  				break;
413.  			case AT_BUTT:
414.  				Sprintf(buf,"%s butts", magr_name);
415.  				break;
416.  			case AT_TUCH:
417.  				Sprintf(buf,"%s touches", magr_name);
418.  				break;
419.  			case AT_TENT:
420.  				Sprintf(buf, "%s tentacles suck",
421.  					s_suffix(magr_name));
422.  				break;
423.  			case AT_HUGS:
424.  				if (magr != u.ustuck) {
425.  				    Sprintf(buf,"%s squeezes", magr_name);
426.  				    break;
427.  				}
428.  			default:
429.  				Sprintf(buf,"%s hits", magr_name);
430.  		    }
431.  		    pline("%s %s.", buf, mon_nam_too(mdef_name, mdef, magr));
432.  		}
433.  	} else  noises(magr, mattk);
434.  	return(mdamagem(magr, mdef, mattk));
435.  }
436.  

gazemm Edit

437.  /* Returns the same values as mdamagem(). */
438.  STATIC_OVL int
439.  gazemm(magr, mdef, mattk)
440.  	register struct monst *magr, *mdef;
441.  	struct attack *mattk;
442.  {
443.  	char buf[BUFSZ];
444.  
445.  	if(vis) {
446.  		Sprintf(buf,"%s gazes at", Monnam(magr));
447.  		pline("%s %s...", buf, mon_nam(mdef));
448.  	}
449.  
450.  	if (magr->mcan || !magr->mcansee ||
451.  	    (magr->minvis && !perceives(mdef->data)) ||
452.  	    !mdef->mcansee || mdef->msleeping) {
453.  	    if(vis) pline("but nothing happens.");
454.  	    return(MM_MISS);
455.  	}
456.  	/* call mon_reflects 2x, first test, then, if visible, print message */
457.  	if (magr->data == &mons[PM_MEDUSA] && mon_reflects(mdef, (char *)0)) {
458.  	    if (canseemon(mdef))
459.  		(void) mon_reflects(mdef,
460.  				    "The gaze is reflected away by %s %s.");
461.  	    if (mdef->mcansee) {
462.  		if (mon_reflects(magr, (char *)0)) {
463.  		    if (canseemon(magr))
464.  			(void) mon_reflects(magr,
465.  					"The gaze is reflected away by %s %s.");
466.  		    return (MM_MISS);
467.  		}
468.  		if (mdef->minvis && !perceives(magr->data)) {
469.  		    if (canseemon(magr)) {
470.  			pline("%s doesn't seem to notice that %s gaze was reflected.",
471.  			      Monnam(magr), mhis(magr));
472.  		    }
473.  		    return (MM_MISS);
474.  		}
475.  		if (canseemon(magr))
476.  		    pline("%s is turned to stone!", Monnam(magr));
477.  		monstone(magr);
478.  		if (magr->mhp > 0) return (MM_MISS);
479.  		return (MM_AGR_DIED);
480.  	    }
481.  	}
482.  
483.  	return(mdamagem(magr, mdef, mattk));
484.  }
485.  

gulpmm Edit

486.  /* Returns the same values as mattackm(). */
487.  STATIC_OVL int
488.  gulpmm(magr, mdef, mattk)
489.  	register struct monst *magr, *mdef;
490.  	register struct	attack *mattk;
491.  {
492.  	xchar	ax, ay, dx, dy;
493.  	int	status;
494.  	char buf[BUFSZ];
495.  	struct obj *obj;
496.  
497.  	if (mdef->data->msize >= MZ_HUGE) return MM_MISS;
498.  
499.  	if (vis) {
500.  		Sprintf(buf,"%s swallows", Monnam(magr));
501.  		pline("%s %s.", buf, mon_nam(mdef));
502.  	}
503.  	for (obj = mdef->minvent; obj; obj = obj->nobj)
504.  	    (void) snuff_lit(obj);
505.  
506.  	/*
507.  	 *  All of this maniuplation is needed to keep the display correct.
508.  	 *  There is a flush at the next pline().
509.  	 */
510.  	ax = magr->mx;
511.  	ay = magr->my;
512.  	dx = mdef->mx;
513.  	dy = mdef->my;
514.  	/*
515.  	 *  Leave the defender in the monster chain at it's current position,
516.  	 *  but don't leave it on the screen.  Move the agressor to the def-
517.  	 *  ender's position.
518.  	 */
519.  	remove_monster(ax, ay);
520.  	place_monster(magr, dx, dy);
521.  	newsym(ax,ay);			/* erase old position */
522.  	newsym(dx,dy);			/* update new position */
523.  
524.  	status = mdamagem(magr, mdef, mattk);
525.  
526.  	if ((status & MM_AGR_DIED) && (status & MM_DEF_DIED)) {
527.  	    ;					/* both died -- do nothing  */
528.  	}
529.  	else if (status & MM_DEF_DIED) {	/* defender died */
530.  	    /*
531.  	     *  Note:  remove_monster() was called in relmon(), wiping out
532.  	     *  magr from level.monsters[mdef->mx][mdef->my].  We need to
533.  	     *  put it back and display it.	-kd
534.  	     */
535.  	    place_monster(magr, dx, dy);
536.  	    newsym(dx, dy);
537.  	}
538.  	else if (status & MM_AGR_DIED) {	/* agressor died */
539.  	    place_monster(mdef, dx, dy);
540.  	    newsym(dx, dy);
541.  	}
542.  	else {					/* both alive, put them back */
543.  	    if (cansee(dx, dy))
544.  		pline("%s is regurgitated!", Monnam(mdef));
545.  
546.  	    place_monster(magr, ax, ay);
547.  	    place_monster(mdef, dx, dy);
548.  	    newsym(ax, ay);
549.  	    newsym(dx, dy);
550.  	}
551.  
552.  	return status;
553.  }
554.  

explmm Edit

555.  STATIC_OVL int
556.  explmm(magr, mdef, mattk)
557.  	register struct monst *magr, *mdef;
558.  	register struct	attack *mattk;
559.  {
560.  	int result;
561.  
562.  	if (magr->mcan)
563.  	    return MM_MISS;
564.  
565.  	if(cansee(magr->mx, magr->my))
566.  		pline("%s explodes!", Monnam(magr));
567.  	else	noises(magr, mattk);
568.  
569.  	result = mdamagem(magr, mdef, mattk);
570.  
571.  	/* Kill off agressor if it didn't die. */
572.  	if (!(result & MM_AGR_DIED)) {
573.  	    mondead(magr);
574.  	    if (magr->mhp > 0) return result;	/* life saved */
575.  	    result |= MM_AGR_DIED;
576.  	}
577.  	if (magr->mtame)	/* give this one even if it was visible */
578.  	    You(brief_feeling, "melancholy");
579.  
580.  	return result;
581.  }
582.  

mdamagem Edit

583.  /*
584.   *  See comment at top of mattackm(), for return values.
585.   */
586.  STATIC_OVL int
587.  mdamagem(magr, mdef, mattk)
588.  	register struct monst	*magr, *mdef;
589.  	register struct attack	*mattk;
590.  {
591.  	struct obj *obj;
592.  	char buf[BUFSZ];
593.  	struct permonst *pa = magr->data, *pd = mdef->data;
594.  	int armpro, num, tmp = d((int)mattk->damn, (int)mattk->damd);
595.  	boolean cancelled;
596.  
597.  	if (touch_petrifies(pd) && !resists_ston(magr)) {
598.  	    long protector = attk_protection((int)mattk->aatyp),
599.  		 wornitems = magr->misc_worn_check;
600.  
601.  	    /* wielded weapon gives same protection as gloves here */
602.  	    if (otmp != 0) wornitems |= W_ARMG;
603.  
604.  	    if (protector == 0L ||
605.  		  (protector != ~0L && (wornitems & protector) != protector)) {
606.  		if (poly_when_stoned(pa)) {
607.  		    mon_to_stone(magr);
608.  		    return MM_HIT; /* no damage during the polymorph */
609.  		}
610.  		if (vis) pline("%s turns to stone!", Monnam(magr));
611.  		monstone(magr);
612.  		if (magr->mhp > 0) return 0;
613.  		else if (magr->mtame && !vis)
614.  		    You(brief_feeling, "peculiarly sad");
615.  		return MM_AGR_DIED;
616.  	    }
617.  	}
618.  
619.  	/* cancellation factor is the same as when attacking the hero */
620.  	armpro = magic_negation(mdef);
621.  	cancelled = magr->mcan || !((rn2(3) >= armpro) || !rn2(50));
622.  
623.  	switch(mattk->adtyp) {
624.  	    case AD_DGST:
625.  		/* eating a Rider or its corpse is fatal */
626.  		if (is_rider(mdef->data)) {
627.  		    if (vis)
628.  			pline("%s %s!", Monnam(magr),
629.  			      mdef->data == &mons[PM_FAMINE] ?
630.  				"belches feebly, shrivels up and dies" :
631.  			      mdef->data == &mons[PM_PESTILENCE] ?
632.  				"coughs spasmodically and collapses" :
633.  				"vomits violently and drops dead");
634.  		    mondied(magr);
635.  		    if (magr->mhp > 0) return 0;	/* lifesaved */
636.  		    else if (magr->mtame && !vis)
637.  			You(brief_feeling, "queasy");
638.  		    return MM_AGR_DIED;
639.  		}
640.  		if(flags.verbose && flags.soundok) verbalize("Burrrrp!");
641.  		tmp = mdef->mhp;
642.  		/* Use up amulet of life saving */
643.  		if (!!(obj = mlifesaver(mdef))) m_useup(mdef, obj);
644.  
645.  		/* Is a corpse for nutrition possible?  It may kill magr */
646.  		if (!corpse_chance(mdef, magr, TRUE) || magr->mhp < 1)
647.  		    break;
648.  
649.  		/* Pets get nutrition from swallowing monster whole.
650.  		 * No nutrition from G_NOCORPSE monster, eg, undead.
651.  		 * DGST monsters don't die from undead corpses
652.  		 */
653.  		num = monsndx(mdef->data);
654.  		if (magr->mtame && !magr->isminion &&
655.  		    !(mvitals[num].mvflags & G_NOCORPSE)) {
656.  		    struct obj *virtualcorpse = mksobj(CORPSE, FALSE, FALSE);
657.  		    int nutrit;
658.  
659.  		    virtualcorpse->corpsenm = num;
660.  		    virtualcorpse->owt = weight(virtualcorpse);
661.  		    nutrit = dog_nutrition(magr, virtualcorpse);
662.  		    dealloc_obj(virtualcorpse);
663.  
664.  		    /* only 50% nutrition, 25% of normal eating time */
665.  		    if (magr->meating > 1) magr->meating = (magr->meating+3)/4;
666.  		    if (nutrit > 1) nutrit /= 2;
667.  		    EDOG(magr)->hungrytime += nutrit;
668.  		}
669.  		break;
670.  	    case AD_STUN:
671.  		if (magr->mcan) break;
672.  		if (canseemon(mdef))
673.  		    pline("%s %s for a moment.", Monnam(mdef),
674.  			  makeplural(stagger(mdef->data, "stagger")));
675.  		mdef->mstun = 1;
676.  		goto physical;
677.  	    case AD_LEGS:
678.  		if (magr->mcan) {
679.  		    tmp = 0;
680.  		    break;
681.  		}
682.  		goto physical;
683.  	    case AD_WERE:
684.  	    case AD_HEAL:
685.  	    case AD_PHYS:
686.   physical:
687.  		if (mattk->aatyp == AT_KICK && thick_skinned(pd)) {
688.  		    tmp = 0;
689.  		} else if(mattk->aatyp == AT_WEAP) {
690.  		    if(otmp) {
691.  			if (otmp->otyp == CORPSE &&
692.  				touch_petrifies(&mons[otmp->corpsenm]))
693.  			    goto do_stone;
694.  			tmp += dmgval(otmp, mdef);
695.  			if (otmp->oartifact) {
696.  			    (void)artifact_hit(magr,mdef, otmp, &tmp, dieroll);
697.  			    if (mdef->mhp <= 0)
698.  				return (MM_DEF_DIED |
699.  					(grow_up(magr,mdef) ? 0 : MM_AGR_DIED));
700.  			}
701.  			if (tmp)
702.  				mrustm(magr, mdef, otmp);
703.  		    }
704.  		} else if (magr->data == &mons[PM_PURPLE_WORM] &&
705.  			    mdef->data == &mons[PM_SHRIEKER]) {
706.  		    /* hack to enhance mm_aggression(); we don't want purple
707.  		       worm's bite attack to kill a shrieker because then it
708.  		       won't swallow the corpse; but if the target survives,
709.  		       the subsequent engulf attack should accomplish that */
710.  		    if (tmp >= mdef->mhp) tmp = mdef->mhp - 1;
711.  		}
712.  		break;
713.  	    case AD_FIRE:
714.  		if (cancelled) {
715.  		    tmp = 0;
716.  		    break;
717.  		}
718.  		if (vis)
719.  		    pline("%s is %s!", Monnam(mdef),
720.  			  on_fire(mdef->data, mattk));
721.  		if (pd == &mons[PM_STRAW_GOLEM] ||
722.  		    pd == &mons[PM_PAPER_GOLEM]) {
723.  			if (vis) pline("%s burns completely!", Monnam(mdef));
724.  			mondied(mdef);
725.  			if (mdef->mhp > 0) return 0;
726.  			else if (mdef->mtame && !vis)
727.  			    pline("May %s roast in peace.", mon_nam(mdef));
728.  			return (MM_DEF_DIED | (grow_up(magr,mdef) ?
729.  							0 : MM_AGR_DIED));
730.  		}
731.  		tmp += destroy_mitem(mdef, SCROLL_CLASS, AD_FIRE);
732.  		tmp += destroy_mitem(mdef, SPBOOK_CLASS, AD_FIRE);
733.  		if (resists_fire(mdef)) {
734.  		    if (vis)
735.  			pline_The("fire doesn't seem to burn %s!",
736.  								mon_nam(mdef));
737.  		    shieldeff(mdef->mx, mdef->my);
738.  		    golemeffects(mdef, AD_FIRE, tmp);
739.  		    tmp = 0;
740.  		}
741.  		/* only potions damage resistant players in destroy_item */
742.  		tmp += destroy_mitem(mdef, POTION_CLASS, AD_FIRE);
743.  		break;
744.  	    case AD_COLD:
745.  		if (cancelled) {
746.  		    tmp = 0;
747.  		    break;
748.  		}
749.  		if (vis) pline("%s is covered in frost!", Monnam(mdef));
750.  		if (resists_cold(mdef)) {
751.  		    if (vis)
752.  			pline_The("frost doesn't seem to chill %s!",
753.  								mon_nam(mdef));
754.  		    shieldeff(mdef->mx, mdef->my);
755.  		    golemeffects(mdef, AD_COLD, tmp);
756.  		    tmp = 0;
757.  		}
758.  		tmp += destroy_mitem(mdef, POTION_CLASS, AD_COLD);
759.  		break;
760.  	    case AD_ELEC:
761.  		if (cancelled) {
762.  		    tmp = 0;
763.  		    break;
764.  		}
765.  		if (vis) pline("%s gets zapped!", Monnam(mdef));
766.  		tmp += destroy_mitem(mdef, WAND_CLASS, AD_ELEC);
767.  		if (resists_elec(mdef)) {
768.  		    if (vis) pline_The("zap doesn't shock %s!", mon_nam(mdef));
769.  		    shieldeff(mdef->mx, mdef->my);
770.  		    golemeffects(mdef, AD_ELEC, tmp);
771.  		    tmp = 0;
772.  		}
773.  		/* only rings damage resistant players in destroy_item */
774.  		tmp += destroy_mitem(mdef, RING_CLASS, AD_ELEC);
775.  		break;
776.  	    case AD_ACID:
777.  		if (magr->mcan) {
778.  		    tmp = 0;
779.  		    break;
780.  		}
781.  		if (resists_acid(mdef)) {
782.  		    if (vis)
783.  			pline("%s is covered in acid, but it seems harmless.",
784.  			      Monnam(mdef));
785.  		    tmp = 0;
786.  		} else if (vis) {
787.  		    pline("%s is covered in acid!", Monnam(mdef));
788.  		    pline("It burns %s!", mon_nam(mdef));
789.  		}
790.  		if (!rn2(30)) erode_armor(mdef, TRUE);
791.  		if (!rn2(6)) erode_obj(MON_WEP(mdef), TRUE, TRUE);
792.  		break;
793.  	    case AD_RUST:
794.  		if (magr->mcan) break;
795.  		if (pd == &mons[PM_IRON_GOLEM]) {
796.  			if (vis) pline("%s falls to pieces!", Monnam(mdef));
797.  			mondied(mdef);
798.  			if (mdef->mhp > 0) return 0;
799.  			else if (mdef->mtame && !vis)
800.  			    pline("May %s rust in peace.", mon_nam(mdef));
801.  			return (MM_DEF_DIED | (grow_up(magr,mdef) ?
802.  							0 : MM_AGR_DIED));
803.  		}
804.  		hurtmarmor(mdef, AD_RUST);
805.  		mdef->mstrategy &= ~STRAT_WAITFORU;
806.  		tmp = 0;
807.  		break;
808.  	    case AD_CORR:
809.  		if (magr->mcan) break;
810.  		hurtmarmor(mdef, AD_CORR);
811.  		mdef->mstrategy &= ~STRAT_WAITFORU;
812.  		tmp = 0;
813.  		break;
814.  	    case AD_DCAY:
815.  		if (magr->mcan) break;
816.  		if (pd == &mons[PM_WOOD_GOLEM] ||
817.  		    pd == &mons[PM_LEATHER_GOLEM]) {
818.  			if (vis) pline("%s falls to pieces!", Monnam(mdef));
819.  			mondied(mdef);
820.  			if (mdef->mhp > 0) return 0;
821.  			else if (mdef->mtame && !vis)
822.  			    pline("May %s rot in peace.", mon_nam(mdef));
823.  			return (MM_DEF_DIED | (grow_up(magr,mdef) ?
824.  							0 : MM_AGR_DIED));
825.  		}
826.  		hurtmarmor(mdef, AD_DCAY);
827.  		mdef->mstrategy &= ~STRAT_WAITFORU;
828.  		tmp = 0;
829.  		break;
830.  	    case AD_STON:
831.  		if (magr->mcan) break;
832.   do_stone:
833.  		/* may die from the acid if it eats a stone-curing corpse */
834.  		if (munstone(mdef, FALSE)) goto post_stone;
835.  		if (poly_when_stoned(pd)) {
836.  			mon_to_stone(mdef);
837.  			tmp = 0;
838.  			break;
839.  		}
840.  		if (!resists_ston(mdef)) {
841.  			if (vis) pline("%s turns to stone!", Monnam(mdef));
842.  			monstone(mdef);
843.   post_stone:		if (mdef->mhp > 0) return 0;
844.  			else if (mdef->mtame && !vis)
845.  			    You(brief_feeling, "peculiarly sad");
846.  			return (MM_DEF_DIED | (grow_up(magr,mdef) ?
847.  							0 : MM_AGR_DIED));
848.  		}
849.  		tmp = (mattk->adtyp == AD_STON ? 0 : 1);
850.  		break;
851.  	    case AD_TLPT:
852.  		if (!cancelled && tmp < mdef->mhp && !tele_restrict(mdef)) {
853.  		    char mdef_Monnam[BUFSZ];
854.  		    /* save the name before monster teleports, otherwise
855.  		       we'll get "it" in the suddenly disappears message */
856.  		    if (vis) Strcpy(mdef_Monnam, Monnam(mdef));
857.  		    mdef->mstrategy &= ~STRAT_WAITFORU;
858.  		    (void) rloc(mdef, FALSE);
859.  		    if (vis && !canspotmon(mdef)
860.  #ifdef STEED
861.  		    	&& mdef != u.usteed
862.  #endif
863.  		    	)
864.  			pline("%s suddenly disappears!", mdef_Monnam);
865.  		}
866.  		break;
867.  	    case AD_SLEE:
868.  		if (!cancelled && !mdef->msleeping &&
869.  			sleep_monst(mdef, rnd(10), -1)) {
870.  		    if (vis) {
871.  			Strcpy(buf, Monnam(mdef));
872.  			pline("%s is put to sleep by %s.", buf, mon_nam(magr));
873.  		    }
874.  		    mdef->mstrategy &= ~STRAT_WAITFORU;
875.  		    slept_monst(mdef);
876.  		}
877.  		break;
878.  	    case AD_PLYS:
879.  		if(!cancelled && mdef->mcanmove) {
880.  		    if (vis) {
881.  			Strcpy(buf, Monnam(mdef));
882.  			pline("%s is frozen by %s.", buf, mon_nam(magr));
883.  		    }
884.  		    mdef->mcanmove = 0;
885.  		    mdef->mfrozen = rnd(10);
886.  		    mdef->mstrategy &= ~STRAT_WAITFORU;
887.  		}
888.  		break;
889.  	    case AD_SLOW:
890.  		if (!cancelled && mdef->mspeed != MSLOW) {
891.  		    unsigned int oldspeed = mdef->mspeed;
892.  
893.  		    mon_adjust_speed(mdef, -1, (struct obj *)0);
894.  		    mdef->mstrategy &= ~STRAT_WAITFORU;
895.  		    if (mdef->mspeed != oldspeed && vis)
896.  			pline("%s slows down.", Monnam(mdef));
897.  		}
898.  		break;
899.  	    case AD_CONF:
900.  		/* Since confusing another monster doesn't have a real time
901.  		 * limit, setting spec_used would not really be right (though
902.  		 * we still should check for it).
903.  		 */
904.  		if (!magr->mcan && !mdef->mconf && !magr->mspec_used) {
905.  		    if (vis) pline("%s looks confused.", Monnam(mdef));
906.  		    mdef->mconf = 1;
907.  		    mdef->mstrategy &= ~STRAT_WAITFORU;
908.  		}
909.  		break;
910.  	    case AD_BLND:
911.  		if (can_blnd(magr, mdef, mattk->aatyp, (struct obj*)0)) {
912.  		    register unsigned rnd_tmp;
913.  
914.  		    if (vis && mdef->mcansee)
915.  			pline("%s is blinded.", Monnam(mdef));
916.  		    rnd_tmp = d((int)mattk->damn, (int)mattk->damd);
917.  		    if ((rnd_tmp += mdef->mblinded) > 127) rnd_tmp = 127;
918.  		    mdef->mblinded = rnd_tmp;
919.  		    mdef->mcansee = 0;
920.  		    mdef->mstrategy &= ~STRAT_WAITFORU;
921.  		}
922.  		tmp = 0;
923.  		break;
924.  	    case AD_HALU:
925.  		if (!magr->mcan && haseyes(pd) && mdef->mcansee) {
926.  		    if (vis) pline("%s looks %sconfused.",
927.  				    Monnam(mdef), mdef->mconf ? "more " : "");
928.  		    mdef->mconf = 1;
929.  		    mdef->mstrategy &= ~STRAT_WAITFORU;
930.  		}
931.  		tmp = 0;
932.  		break;
933.  	    case AD_CURS:
934.  		if (!night() && (pa == &mons[PM_GREMLIN])) break;
935.  		if (!magr->mcan && !rn2(10)) {
936.  		    mdef->mcan = 1;	/* cancelled regardless of lifesave */
937.  		    mdef->mstrategy &= ~STRAT_WAITFORU;
938.  		    if (is_were(pd) && pd->mlet != S_HUMAN)
939.  			were_change(mdef);
940.  		    if (pd == &mons[PM_CLAY_GOLEM]) {
941.  			    if (vis) {
942.  				pline("Some writing vanishes from %s head!",
943.  				    s_suffix(mon_nam(mdef)));
944.  				pline("%s is destroyed!", Monnam(mdef));
945.  			    }
946.  			    mondied(mdef);
947.  			    if (mdef->mhp > 0) return 0;
948.  			    else if (mdef->mtame && !vis)
949.  				You(brief_feeling, "strangely sad");
950.  			    return (MM_DEF_DIED | (grow_up(magr,mdef) ?
951.  							0 : MM_AGR_DIED));
952.  		    }
953.  		    if (flags.soundok) {
954.  			    if (!vis) You_hear("laughter.");
955.  			    else pline("%s chuckles.", Monnam(magr));
956.  		    }
957.  		}
958.  		break;
959.  	    case AD_SGLD:
960.  		tmp = 0;
961.  #ifndef GOLDOBJ
962.  		if (magr->mcan || !mdef->mgold) break;
963.  		/* technically incorrect; no check for stealing gold from
964.  		 * between mdef's feet...
965.  		 */
966.  		magr->mgold += mdef->mgold;
967.  		mdef->mgold = 0;
968.  #else
969.                  if (magr->mcan) break;
970.  		/* technically incorrect; no check for stealing gold from
971.  		 * between mdef's feet...
972.  		 */
973.                  {
974.  		    struct obj *gold = findgold(mdef->minvent);
975.  		    if (!gold) break;
976.                      obj_extract_self(gold);
977.  		    add_to_minv(magr, gold);
978.                  }
979.  #endif
980.  		mdef->mstrategy &= ~STRAT_WAITFORU;
981.  		if (vis) {
982.  		    Strcpy(buf, Monnam(magr));
983.  		    pline("%s steals some gold from %s.", buf, mon_nam(mdef));
984.  		}
985.  		if (!tele_restrict(magr)) {
986.  		    (void) rloc(magr, FALSE);
987.  		    if (vis && !canspotmon(magr))
988.  			pline("%s suddenly disappears!", buf);
989.  		}
990.  		break;
991.  	    case AD_DRLI:
992.  		if (!cancelled && !rn2(3) && !resists_drli(mdef)) {
993.  			tmp = d(2,6);
994.  			if (vis)
995.  			    pline("%s suddenly seems weaker!", Monnam(mdef));
996.  			mdef->mhpmax -= tmp;
997.  			if (mdef->m_lev == 0)
998.  				tmp = mdef->mhp;
999.  			else mdef->m_lev--;
1000. 			/* Automatic kill if drained past level 0 */
1001. 		}
1002. 		break;
1003. #ifdef SEDUCE
1004. 	    case AD_SSEX:
1005. #endif
1006. 	    case AD_SITM:	/* for now these are the same */
1007. 	    case AD_SEDU:
1008. 		if (magr->mcan) break;
1009. 		/* find an object to steal, non-cursed if magr is tame */
1010. 		for (obj = mdef->minvent; obj; obj = obj->nobj)
1011. 		    if (!magr->mtame || !obj->cursed)
1012. 			break;
1013. 
1014. 		if (obj) {
1015. 			char onambuf[BUFSZ], mdefnambuf[BUFSZ];
1016. 
1017. 			/* make a special x_monnam() call that never omits
1018. 			   the saddle, and save it for later messages */
1019. 			Strcpy(mdefnambuf, x_monnam(mdef, ARTICLE_THE, (char *)0, 0, FALSE));
1020. 
1021. 			otmp = obj;
1022. #ifdef STEED
1023. 			if (u.usteed == mdef &&
1024. 					otmp == which_armor(mdef, W_SADDLE))
1025. 				/* "You can no longer ride <steed>." */
1026. 				dismount_steed(DISMOUNT_POLY);
1027. #endif
1028. 			obj_extract_self(otmp);
1029. 			if (otmp->owornmask) {
1030. 				mdef->misc_worn_check &= ~otmp->owornmask;
1031. 				if (otmp->owornmask & W_WEP)
1032. 				    setmnotwielded(mdef,otmp);
1033. 				otmp->owornmask = 0L;
1034. 				update_mon_intrinsics(mdef, otmp, FALSE, FALSE);
1035. 			}
1036. 			/* add_to_minv() might free otmp [if it merges] */
1037. 			if (vis)
1038. 				Strcpy(onambuf, doname(otmp));
1039. 			(void) add_to_minv(magr, otmp);
1040. 			if (vis) {
1041. 				Strcpy(buf, Monnam(magr));
1042. 				pline("%s steals %s from %s!", buf,
1043. 				    onambuf, mdefnambuf);
1044. 			}
1045. 			possibly_unwield(mdef, FALSE);
1046. 			mdef->mstrategy &= ~STRAT_WAITFORU;
1047. 			mselftouch(mdef, (const char *)0, FALSE);
1048. 			if (mdef->mhp <= 0)
1049. 				return (MM_DEF_DIED | (grow_up(magr,mdef) ?
1050. 							0 : MM_AGR_DIED));
1051. 			if (magr->data->mlet == S_NYMPH &&
1052. 			    !tele_restrict(magr)) {
1053. 			    (void) rloc(magr, FALSE);
1054. 			    if (vis && !canspotmon(magr))
1055. 				pline("%s suddenly disappears!", buf);
1056. 			}
1057. 		}
1058. 		tmp = 0;
1059. 		break;
1060. 	    case AD_DRST:
1061. 	    case AD_DRDX:
1062. 	    case AD_DRCO:
1063. 		if (!cancelled && !rn2(8)) {
1064. 		    if (vis)
1065. 			pline("%s %s was poisoned!", s_suffix(Monnam(magr)),
1066. 			      mpoisons_subj(magr, mattk));
1067. 		    if (resists_poison(mdef)) {
1068. 			if (vis)
1069. 			    pline_The("poison doesn't seem to affect %s.",
1070. 				mon_nam(mdef));
1071. 		    } else {
1072. 			if (rn2(10)) tmp += rn1(10,6);
1073. 			else {
1074. 			    if (vis) pline_The("poison was deadly...");
1075. 			    tmp = mdef->mhp;
1076. 			}
1077. 		    }
1078. 		}
1079. 		break;
1080. 	    case AD_DRIN:
1081. 		if (notonhead || !has_head(pd)) {
1082. 		    if (vis) pline("%s doesn't seem harmed.", Monnam(mdef));
1083. 		    /* Not clear what to do for green slimes */
1084. 		    tmp = 0;
1085. 		    break;
1086. 		}
1087. 		if ((mdef->misc_worn_check & W_ARMH) && rn2(8)) {
1088. 		    if (vis) {
1089. 			Strcpy(buf, s_suffix(Monnam(mdef)));
1090. 			pline("%s helmet blocks %s attack to %s head.",
1091. 				buf, s_suffix(mon_nam(magr)),
1092. 				mhis(mdef));
1093. 		    }
1094. 		    break;
1095. 		}
1096. 		if (vis) pline("%s brain is eaten!", s_suffix(Monnam(mdef)));
1097. 		if (mindless(pd)) {
1098. 		    if (vis) pline("%s doesn't notice.", Monnam(mdef));
1099. 		    break;
1100. 		}
1101. 		tmp += rnd(10); /* fakery, since monsters lack INT scores */
1102. 		if (magr->mtame && !magr->isminion) {
1103. 		    EDOG(magr)->hungrytime += rnd(60);
1104. 		    magr->mconf = 0;
1105. 		}
1106. 		if (tmp >= mdef->mhp && vis)
1107. 		    pline("%s last thought fades away...",
1108. 			          s_suffix(Monnam(mdef)));
1109. 		break;
1110. 	    case AD_SLIM:
1111. 		if (cancelled) break;	/* physical damage only */
1112. 		if (!rn2(4) && !flaming(mdef->data) &&
1113. 				mdef->data != &mons[PM_GREEN_SLIME]) {
1114. 		    (void) newcham(mdef, &mons[PM_GREEN_SLIME], FALSE, vis);
1115. 		    mdef->mstrategy &= ~STRAT_WAITFORU;
1116. 		    tmp = 0;
1117. 		}
1118. 		break;
1119. 	    case AD_STCK:
1120. 		if (cancelled) tmp = 0;
1121. 		break;
1122. 	    case AD_WRAP: /* monsters cannot grab one another, it's too hard */
1123. 		if (magr->mcan) tmp = 0;
1124. 		break;
1125. 	    case AD_ENCH:
1126. 		/* there's no msomearmor() function, so just do damage */
1127. 	     /* if (cancelled) break; */
1128. 		break;
1129. 	    default:	tmp = 0;
1130. 			break;
1131. 	}
1132. 	if(!tmp) return(MM_MISS);
1133. 
1134. 	if((mdef->mhp -= tmp) < 1) {
1135. 	    if (m_at(mdef->mx, mdef->my) == magr) {  /* see gulpmm() */
1136. 		remove_monster(mdef->mx, mdef->my);
1137. 		mdef->mhp = 1;	/* otherwise place_monster will complain */
1138. 		place_monster(mdef, mdef->mx, mdef->my);
1139. 		mdef->mhp = 0;
1140. 	    }
1141. 	    monkilled(mdef, "", (int)mattk->adtyp);
1142. 	    if (mdef->mhp > 0) return 0; /* mdef lifesaved */
1143. 
1144. 	    if (mattk->adtyp == AD_DGST) {
1145. 		/* various checks similar to dog_eat and meatobj.
1146. 		 * after monkilled() to provide better message ordering */
1147. 		if (mdef->cham != CHAM_ORDINARY) {
1148. 		    (void) newcham(magr, (struct permonst *)0, FALSE, TRUE);
1149. 		} else if (mdef->data == &mons[PM_GREEN_SLIME]) {
1150. 		    (void) newcham(magr, &mons[PM_GREEN_SLIME], FALSE, TRUE);
1151. 		} else if (mdef->data == &mons[PM_WRAITH]) {
1152. 		    (void) grow_up(magr, (struct monst *)0);
1153. 		    /* don't grow up twice */
1154. 		    return (MM_DEF_DIED | (magr->mhp > 0 ? 0 : MM_AGR_DIED));
1155. 		} else if (mdef->data == &mons[PM_NURSE]) {
1156. 		    magr->mhp = magr->mhpmax;
1157. 		}
1158. 	    }
1159. 
1160. 	    return (MM_DEF_DIED | (grow_up(magr,mdef) ? 0 : MM_AGR_DIED));
1161. 	}
1162. 	return(MM_HIT);
1163. }
1164. 
1165. #endif /* OVLB */
1166. 
1167. 

noattacks Edit

1168. #ifdef OVL0
1169. 
1170. int
1171. noattacks(ptr)			/* returns 1 if monster doesn't attack */
1172. 	struct	permonst *ptr;
1173. {
1174. 	int i;
1175. 
1176. 	for(i = 0; i < NATTK; i++)
1177. 		if(ptr->mattk[i].aatyp) return(0);
1178. 
1179. 	return(1);
1180. }
1181. 

sleep_monst Edit

1182. /* `mon' is hit by a sleep attack; return 1 if it's affected, 0 otherwise */
1183. int
1184. sleep_monst(mon, amt, how)
1185. struct monst *mon;
1186. int amt, how;
1187. {
1188. 	if (resists_sleep(mon) ||
1189. 		(how >= 0 && resist(mon, (char)how, 0, NOTELL))) {
1190. 	    shieldeff(mon->mx, mon->my);
1191. 	} else if (mon->mcanmove) {
1192. 	    amt += (int) mon->mfrozen;
1193. 	    if (amt > 0) {	/* sleep for N turns */
1194. 		mon->mcanmove = 0;
1195. 		mon->mfrozen = min(amt, 127);
1196. 	    } else {		/* sleep until awakened */
1197. 		mon->msleeping = 1;
1198. 	    }
1199. 	    return 1;
1200. 	}
1201. 	return 0;
1202. }
1203. 

slept_monst Edit

1204. /* sleeping grabber releases, engulfer doesn't; don't use for paralysis! */
1205. void
1206. slept_monst(mon)
1207. struct monst *mon;
1208. {
1209. 	if ((mon->msleeping || !mon->mcanmove) && mon == u.ustuck &&
1210. 		!sticks(youmonst.data) && !u.uswallow) {
1211. 	    pline("%s grip relaxes.", s_suffix(Monnam(mon)));
1212. 	    unstuck(mon);
1213. 	}
1214. }
1215. 
1216. #endif /* OVL0 */

mrustm Edit

1217. #ifdef OVLB
1218. 
1219. STATIC_OVL void
1220. mrustm(magr, mdef, obj)
1221. register struct monst *magr, *mdef;
1222. register struct obj *obj;
1223. {
1224. 	boolean is_acid;
1225. 
1226. 	if (!magr || !mdef || !obj) return; /* just in case */
1227. 
1228. 	if (dmgtype(mdef->data, AD_CORR))
1229. 	    is_acid = TRUE;
1230. 	else if (dmgtype(mdef->data, AD_RUST))
1231. 	    is_acid = FALSE;
1232. 	else
1233. 	    return;
1234. 
1235. 	if (!mdef->mcan &&
1236. 	    (is_acid ? is_corrodeable(obj) : is_rustprone(obj)) &&
1237. 	    (is_acid ? obj->oeroded2 : obj->oeroded) < MAX_ERODE) {
1238. 		if (obj->greased || obj->oerodeproof || (obj->blessed && rn2(3))) {
1239. 		    if (cansee(mdef->mx, mdef->my) && flags.verbose)
1240. 			pline("%s weapon is not affected.",
1241. 			                 s_suffix(Monnam(magr)));
1242. 		    if (obj->greased && !rn2(2)) obj->greased = 0;
1243. 		} else {
1244. 		    if (cansee(mdef->mx, mdef->my)) {
1245. 			pline("%s %s%s!", s_suffix(Monnam(magr)),
1246. 			    aobjnam(obj, (is_acid ? "corrode" : "rust")),
1247. 			    (is_acid ? obj->oeroded2 : obj->oeroded)
1248. 				? " further" : "");
1249. 		    }
1250. 		    if (is_acid) obj->oeroded2++;
1251. 		    else obj->oeroded++;
1252. 		}
1253. 	}
1254. }
1255. 

mswingsm Edit

1256. STATIC_OVL void
1257. mswingsm(magr, mdef, otemp)
1258. register struct monst *magr, *mdef;
1259. register struct obj *otemp;
1260. {
1261. 	char buf[BUFSZ];
1262. 	if (!flags.verbose || Blind || !mon_visible(magr)) return;
1263. 	Strcpy(buf, mon_nam(mdef));
1264. 	pline("%s %s %s %s at %s.", Monnam(magr),
1265. 	      (objects[otemp->otyp].oc_dir & PIERCE) ? "thrusts" : "swings",
1266. 	      mhis(magr), singular(otemp, xname), buf);
1267. }
1268. 

passivemm Edit

1269. /*
1270.  * Passive responses by defenders.  Does not replicate responses already
1271.  * handled above.  Returns same values as mattackm.
1272.  */
1273. STATIC_OVL int
1274. passivemm(magr,mdef,mhit,mdead)
1275. register struct monst *magr, *mdef;
1276. boolean mhit;
1277. int mdead;
1278. {
1279. 	register struct permonst *mddat = mdef->data;
1280. 	register struct permonst *madat = magr->data;
1281. 	char buf[BUFSZ];
1282. 	int i, tmp;
1283. 
1284. 	for(i = 0; ; i++) {
1285. 	    if(i >= NATTK) return (mdead | mhit); /* no passive attacks */
1286. 	    if(mddat->mattk[i].aatyp == AT_NONE) break;
1287. 	}
1288. 	if (mddat->mattk[i].damn)
1289. 	    tmp = d((int)mddat->mattk[i].damn,
1290. 				    (int)mddat->mattk[i].damd);
1291. 	else if(mddat->mattk[i].damd)
1292. 	    tmp = d((int)mddat->mlevel+1, (int)mddat->mattk[i].damd);
1293. 	else
1294. 	    tmp = 0;
1295. 
1296. 	/* These affect the enemy even if defender killed */
1297. 	switch(mddat->mattk[i].adtyp) {
1298. 	    case AD_ACID:
1299. 		if (mhit && !rn2(2)) {
1300. 		    Strcpy(buf, Monnam(magr));
1301. 		    if(canseemon(magr))
1302. 			pline("%s is splashed by %s acid!",
1303. 			      buf, s_suffix(mon_nam(mdef)));
1304. 		    if (resists_acid(magr)) {
1305. 			if(canseemon(magr))
1306. 			    pline("%s is not affected.", Monnam(magr));
1307. 			tmp = 0;
1308. 		    }
1309. 		} else tmp = 0;
1310. 		goto assess_dmg;
1311. 	    case AD_ENCH:	/* KMH -- remove enchantment (disenchanter) */
1312. 		if (mhit && !mdef->mcan && otmp) {
1313. 		    (void) drain_item(otmp);
1314. 		    /* No message */
1315. 		}
1316. 		break;
1317. 	    default:
1318. 		break;
1319. 	}
1320. 	if (mdead || mdef->mcan) return (mdead|mhit);
1321. 
1322. 	/* These affect the enemy only if defender is still alive */
1323. 	if (rn2(3)) switch(mddat->mattk[i].adtyp) {
1324. 	    case AD_PLYS: /* Floating eye */
1325. 		if (tmp > 127) tmp = 127;
1326. 		if (mddat == &mons[PM_FLOATING_EYE]) {
1327. 		    if (!rn2(4)) tmp = 127;
1328. 		    if (magr->mcansee && haseyes(madat) && mdef->mcansee &&
1329. 			(perceives(madat) || !mdef->minvis)) {
1330. 			Sprintf(buf, "%s gaze is reflected by %%s %%s.",
1331. 				s_suffix(mon_nam(mdef)));
1332. 			if (mon_reflects(magr,
1333. 					 canseemon(magr) ? buf : (char *)0))
1334. 				return(mdead|mhit);
1335. 			Strcpy(buf, Monnam(magr));
1336. 			if(canseemon(magr))
1337. 			    pline("%s is frozen by %s gaze!",
1338. 				  buf, s_suffix(mon_nam(mdef)));
1339. 			magr->mcanmove = 0;
1340. 			magr->mfrozen = tmp;
1341. 			return (mdead|mhit);
1342. 		    }
1343. 		} else { /* gelatinous cube */
1344. 		    Strcpy(buf, Monnam(magr));
1345. 		    if(canseemon(magr))
1346. 			pline("%s is frozen by %s.", buf, mon_nam(mdef));
1347. 		    magr->mcanmove = 0;
1348. 		    magr->mfrozen = tmp;
1349. 		    return (mdead|mhit);
1350. 		}
1351. 		return 1;
1352. 	    case AD_COLD:
1353. 		if (resists_cold(magr)) {
1354. 		    if (canseemon(magr)) {
1355. 			pline("%s is mildly chilly.", Monnam(magr));
1356. 			golemeffects(magr, AD_COLD, tmp);
1357. 		    }
1358. 		    tmp = 0;
1359. 		    break;
1360. 		}
1361. 		if(canseemon(magr))
1362. 		    pline("%s is suddenly very cold!", Monnam(magr));
1363. 		mdef->mhp += tmp / 2;
1364. 		if (mdef->mhpmax < mdef->mhp) mdef->mhpmax = mdef->mhp;
1365. 		if (mdef->mhpmax > ((int) (mdef->m_lev+1) * 8))
1366. 		    (void)split_mon(mdef, magr);
1367. 		break;
1368. 	    case AD_STUN:
1369. 		if (!magr->mstun) {
1370. 		    magr->mstun = 1;
1371. 		    if (canseemon(magr))
1372. 			pline("%s %s...", Monnam(magr),
1373. 			      makeplural(stagger(magr->data, "stagger")));
1374. 		}
1375. 		tmp = 0;
1376. 		break;
1377. 	    case AD_FIRE:
1378. 		if (resists_fire(magr)) {
1379. 		    if (canseemon(magr)) {
1380. 			pline("%s is mildly warmed.", Monnam(magr));
1381. 			golemeffects(magr, AD_FIRE, tmp);
1382. 		    }
1383. 		    tmp = 0;
1384. 		    break;
1385. 		}
1386. 		if(canseemon(magr))
1387. 		    pline("%s is suddenly very hot!", Monnam(magr));
1388. 		break;
1389. 	    case AD_ELEC:
1390. 		if (resists_elec(magr)) {
1391. 		    if (canseemon(magr)) {
1392. 			pline("%s is mildly tingled.", Monnam(magr));
1393. 			golemeffects(magr, AD_ELEC, tmp);
1394. 		    }
1395. 		    tmp = 0;
1396. 		    break;
1397. 		}
1398. 		if(canseemon(magr))
1399. 		    pline("%s is jolted with electricity!", Monnam(magr));
1400. 		break;
1401. 	    default: tmp = 0;
1402. 		break;
1403. 	}
1404. 	else tmp = 0;
1405. 
1406.     assess_dmg:
1407. 	if((magr->mhp -= tmp) <= 0) {
1408. 		monkilled(magr, "", (int)mddat->mattk[i].adtyp);
1409. 		return (mdead | mhit | MM_AGR_DIED);
1410. 	}
1411. 	return (mdead | mhit);
1412. }
1413. 

attk_protection Edit

1414. /* "aggressive defense"; what type of armor prevents specified attack
1415.    from touching its target? */
1416. long
1417. attk_protection(aatyp)
1418. int aatyp;
1419. {
1420.     long w_mask = 0L;
1421. 
1422.     switch (aatyp) {
1423.     case AT_NONE:
1424.     case AT_SPIT:
1425.     case AT_EXPL:
1426.     case AT_BOOM:
1427.     case AT_GAZE:
1428.     case AT_BREA:
1429.     case AT_MAGC:
1430. 	w_mask = ~0L;		/* special case; no defense needed */
1431. 	break;
1432.     case AT_CLAW:
1433.     case AT_TUCH:
1434.     case AT_WEAP:
1435. 	w_mask = W_ARMG;	/* caller needs to check for weapon */
1436. 	break;
1437.     case AT_KICK:
1438. 	w_mask = W_ARMF;
1439. 	break;
1440.     case AT_BUTT:
1441. 	w_mask = W_ARMH;
1442. 	break;
1443.     case AT_HUGS:
1444. 	w_mask = (W_ARMC|W_ARMG); /* attacker needs both to be protected */
1445. 	break;
1446.     case AT_BITE:
1447.     case AT_STNG:
1448.     case AT_ENGL:
1449.     case AT_TENT:
1450.     default:
1451. 	w_mask = 0L;		/* no defense available */
1452. 	break;
1453.     }
1454.     return w_mask;
1455. }
1456. 
1457. #endif /* OVLB */
1458. 
1459. /*mhitm.c*/
1460. 

Around Wikia's network

Random Wiki