Source:NetHack 3.0.0/mhitm.c

From NetHackWiki
Revision as of 04:53, 4 March 2008 by Kernigh bot (talk | contribs) (NetHack 3.0.0/mhitm.c moved to Source:NetHack 3.0.0/mhitm.c: Robot: moved page)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

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

Warning! This is the source code from an old release. For the latest release, see Source code

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

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

1.    /*	SCCS Id: @(#)mhitm.c	3.0	88/11/10
2.    /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3.    /* NetHack may be freely redistributed.  See license for details. */
4.    
5.    #include	"hack.h"
6.    #ifdef NAMED_ITEMS
7.    #  include "artifact.h"
8.    #endif
9.    
10.   static boolean vis, far_noise;
11.   static long noisetime;
12.   static struct obj *otmp;
13.   
14.   static void mrustm P((struct monst *, struct monst *, struct obj *));
15.   static int hitmm P((struct monst *,struct monst *,struct attack *));
16.   static int gazemm P((struct monst *,struct monst *,struct attack *));
17.   static int gulpmm P((struct monst *,struct monst *,struct attack *));
18.   static int explmm P((struct monst *,struct attack *));
19.   static int mdamagem P((struct monst *,struct monst *,struct attack *));
20.   static void mswingsm P((struct monst *, struct monst *, struct obj *));
21.   
22.   static boolean
23.   m_incompat(magr, mdef)
24.   /* This must work like in mhitu.c.  Specifically, if it's a shopkeeper
25.    * polymorphed into a monster of a specific gender, the specific gender
26.    * overrides.  Thus, do not use is_female(), since then a female shopkeeper
27.    * polymorphed into an incubus, or any shopkeeper turned into something
28.    * genderless, would be treated improperly.
29.    * This nonsense could be avoided if every monster had a gender field...
30.    */
31.   register struct monst *magr, *mdef;
32.   {
33.   	return(gender(magr) != 1-gender(mdef));
34.   }
35.   
36.   static void
37.   noises(magr, mattk)
38.   	register struct monst *magr;
39.   	register struct	attack *mattk;
40.   {
41.   	boolean farq = (dist(magr->mx, magr->my) > 15);
42.   
43.   	if(flags.soundok && (farq != far_noise || moves-noisetime > 10)) {
44.   		far_noise = farq;
45.   		noisetime = moves;
46.   		You("hear %s%s.",
47.   			(mattk->aatyp == AT_EXPL) ? "an explosion" : "some noises",
48.   			farq ? " in the distance" : "");
49.   	}
50.   }
51.   
52.   static
53.   void
54.   missmm(magr, mdef, mattk)
55.   	register struct monst *magr, *mdef;
56.   	struct attack *mattk;
57.   {
58.   	char buf[BUFSZ];
59.   
60.   	if(vis) {
61.   		if(mdef->mimic) seemimic(mdef);
62.   		if(magr->mimic) seemimic(magr);
63.   		if (sp_melee(magr) && !magr->mcan &&
64.   			    (is_nymph(magr) || !m_incompat(magr,mdef))) {
65.   			Sprintf(buf, "%s pretends to be friendly to",
66.   								Monnam(magr));
67.   		} else
68.   			Sprintf(buf,"%s misses", Monnam(magr));
69.   		pline("%s %s.", buf, mon_nam(mdef));
70.   	} else  noises(magr, mattk);
71.   }
72.   
73.   int
74.   fightm(mtmp)		/* have monsters fight each other */
75.   	register struct monst *mtmp;
76.   {
77.   register struct monst *mon;
78.   /*	TODO:	this loop needs to be restructured, as we don't know if
79.    *		either "mon" or "mon->nmon" will exist after the attack.
80.    */
81.   	for(mon = fmon; mon; mon = mon->nmon)
82.   	    if(mon != mtmp) {
83.   		if(dist2(mon->mx,mon->my,mtmp->mx,mtmp->my) < 3)
84.   		    return(mattackm(mtmp,mon));
85.   	    }
86.   	return(-1);
87.   }
88.   
89.   /*
90.    * mattackm returns -1 (magr died), 0 (miss), 1 (mdef hit), or 2 (mdef killed)
91.    *
92.    * Each successive attack has a lower probability of hitting.  Some
93.    * rely on the success of previous attacks.
94.    *
95.    * In the case of exploding monsters, the monster dies as well.
96.    */
97.   int
98.   mattackm(magr, mdef)
99.   	register struct monst *magr,*mdef;
100.  {
101.  	int	i, tmp, nsum, sum[NATTK];
102.  	struct	attack	*mattk;
103.  	struct	permonst *pa, *pd;
104.  	schar	strike;
105.  
106.  	if(!magr || !mdef) return(0);		/* mike@genat */
107.  	pa = magr->data; pd = mdef->data;
108.  	if(magr->mfroz) return(0);		/* riv05!a3 */
109.  
110.  /*	Calculate the armour class differential.	*/
111.  
112.  	tmp = pd->ac + magr->m_lev;
113.  	if(mdef->mconf || mdef->mfroz || mdef->msleep){
114.  		tmp += 4;
115.  		if(mdef->msleep) mdef->msleep = 0;
116.  	}
117.  
118.  	if (is_elf(magr->data) && is_orc(mdef->data)) tmp++;
119.  
120.  /*	Set up visibility of action			*/
121.  	vis = (cansee(magr->mx,magr->my) && cansee(mdef->mx,mdef->my));
122.  
123.  /*	Set flag indicating monster has moved this turn.  Necessary since a
124.   *	monster might get an attack out of sequence (i.e. before its move) in
125.   *	some cases, in which case this still counts as its move for the round
126.   *	and it shouldn't move again.
127.   */
128.  	magr->mlstmv = moves;
129.  
130.  /*	Now perform all attacks for the monster.	*/
131.  
132.  	for(i=0; i<NATTK; i++) sum[i] = 0;
133.  	for(i = nsum = 0; i < NATTK; nsum |= sum[i++]) {
134.  	    mattk = &(pa->mattk[i]);
135.  	    otmp = (struct obj *)0;
136.  	    switch(mattk->aatyp) {
137.  
138.  		case AT_WEAP:		/* "hand to hand" attacks */
139.  			otmp = select_hwep(magr);
140.  			if(otmp) {
141.  				if (vis) mswingsm(magr, mdef, otmp);
142.  				tmp += hitval(otmp, pd);
143.  			}
144.  		case AT_CLAW:
145.  		case AT_KICK:
146.  		case AT_BITE:
147.  		case AT_STNG:
148.  		case AT_TUCH:
149.  		case AT_BUTT:
150.  			if((strike = (tmp > rnd(20+i)))) {
151.  				sum[i] = hitmm(magr, mdef, mattk);
152.  				if(sum[i] == -1) return(-1);
153.  			} else	missmm(magr, mdef, mattk);
154.  			break;
155.  
156.  		case AT_HUGS:	/* automatic if prev two attacks succeed */
157.  			strike = 1;
158.  			if(sum[i-1] && sum[i-2]) {
159.  			    sum[i] = hitmm(magr, mdef, mattk);
160.  			    if(sum[i] == -1) return(-1);
161.  			}
162.  			break;
163.  
164.  		case AT_GAZE:	/* will not wake up a sleeper */
165.  			strike = 0;
166.  			sum[i] = gazemm(magr, mdef, mattk);
167.  			break;
168.  
169.  		case AT_EXPL:	/* automatic hit if next to */
170.  			strike = -1;
171.  			sum[i] = explmm(magr, mattk);
172.  			break;
173.  
174.  		case AT_ENGL:
175.  			if((strike = (tmp > rnd(20+i))))
176.  				sum[i]= gulpmm(magr, mdef, mattk);
177.  			else	missmm(magr, mdef, mattk);
178.  			break;
179.  
180.  		default:		/* no attack */
181.  			strike = 0;
182.  			break;
183.  	    }
184.  	    if(sum[i] == 2) return(2);  	/* defender dead */
185.  	    if(strike)	    mdef->msleep = 0;
186.  	    if(strike == -1)   return(-1);		/* attacker dead */
187.  	    nsum |= sum[i];
188.  	}
189.  	return(nsum);
190.  }
191.  
192.  /* hitmm returns 0 (miss), 1 (hit), 2 (kill), or -1 (magr died) */
193.  static int
194.  hitmm(magr, mdef, mattk)
195.  	register struct monst *magr,*mdef;
196.  	struct	attack *mattk;
197.  {
198.  
199.  	if(vis){
200.  		char buf[BUFSZ];
201.  		if(mdef->mimic) seemimic(mdef);
202.  		if(magr->mimic) seemimic(magr);
203.  		if(sp_melee(magr) && !magr->mcan) {
204.  			if(!is_nymph(magr) && m_incompat(magr,mdef))
205.  				goto strike;
206.  			Sprintf(buf, "%s %s", Monnam(magr),
207.  				mdef->mblinded ? "talks to" : "smiles at");
208.  			pline("%s %s %s.", buf, mon_nam(mdef),
209.  				m_incompat(magr,mdef) ?
210.  					"engagingly" : "seductively");
211.  		} else {
212.  	strike:
213.  		    switch (mattk->aatyp) {
214.  			case AT_BITE:
215.  				Sprintf(buf,"%s bites", Monnam(magr));
216.  				break;
217.  			case AT_STNG:
218.  				Sprintf(buf,"%s stings", Monnam(magr));
219.  				break;
220.  			case AT_BUTT:
221.  				Sprintf(buf,"%s butts", Monnam(magr));
222.  				break;
223.  			case AT_TUCH:
224.  				Sprintf(buf,"%s touches", Monnam(magr));
225.  				break;
226.  			case AT_HUGS:
227.  				if (magr != u.ustuck) {
228.  				    Sprintf(buf,"%s squeezes", Monnam(magr));
229.  				    break;
230.  				}
231.  			default:
232.  				Sprintf(buf,"%s hits", Monnam(magr));
233.  		    }
234.  		}
235.  		pline("%s %s.", buf, mon_nam(mdef));
236.  	} else  noises(magr, mattk);
237.  	return(mdamagem(magr, mdef, mattk));
238.  }
239.  
240.  static int
241.  gazemm(magr, mdef, mattk)
242.  	register struct monst *magr, *mdef;
243.  	struct attack *mattk;
244.  {
245.  	char buf[BUFSZ];
246.  
247.  	if(vis) {
248.  		Sprintf(buf,"%s gazes at", Monnam(magr));
249.  		pline("%s %s.", buf, mon_nam(mdef));
250.  	}
251.  
252.  	if (mdef->mblinded || mdef->msleep) {
253.  
254.  	    if(vis) pline("but nothing happens.");
255.  	    return(0);
256.  	}
257.  
258.  	return(mdamagem(magr, mdef, mattk));
259.  }
260.  
261.  static int
262.  gulpmm(magr, mdef, mattk)
263.  	register struct monst *magr, *mdef;
264.  	register struct	attack *mattk;
265.  {
266.  	int	mx, my, tmp;
267.  	char buf[BUFSZ];
268.  
269.  	if(vis) {
270.  		Sprintf(buf,"%s swallows", Monnam(magr));
271.  		pline("%s %s.", buf, mon_nam(mdef));
272.  	}
273.  
274.  	mx = magr->mx;
275.  	my = magr->my;
276.  	 /* move over top of the defender */
277.  	if(cansee(mdef->mx, mdef->my))	unpmon(mdef);
278.  	if(cansee(magr->mx, magr->my))	unpmon(magr);
279.  	magr->mx = mdef->mx;
280.  	magr->my = mdef->my;
281.  	if(cansee(magr->mx, magr->my))	pmon(magr);
282.  	if((tmp = mdamagem(magr, mdef, mattk)) == 2) {
283.  		levl[mx][my].mmask = 0;
284.  		return(2);	/* defender died */
285.  	} else {		/* defender survived */
286.  		if(cansee(magr->mx, magr->my))	unpmon(magr);
287.  		magr->mx = mx;
288.  		magr->my = my;
289.  		/* move off of defender */
290.  		if(cansee(magr->mx, magr->my))	pmon(magr);
291.  		if(cansee(mdef->mx, mdef->my))	pmon(mdef);
292.  		return(tmp);
293.  	}
294.  }
295.  
296.  static int
297.  explmm(magr, mattk)
298.  	register struct monst *magr;
299.  	register struct	attack *mattk;
300.  {
301.  	register struct monst *mon;
302.  
303.  	if(cansee(magr->mx, magr->my))
304.  		pline("%s explodes!", Monnam(magr));
305.  	else	noises(magr, mattk);
306.  
307.  	for(mon = fmon; mon; mon = mon->nmon)
308.  	    if(mon != magr) {
309.  		if(dist2(mon->mx, mon->my, magr->mx, magr->my) < 3)
310.  		    (void) mdamagem(magr, mon, mattk);
311.  	    }
312.  
313.  	if(dist2(magr->mx, magr->my, u.ux, u.uy) < 3)
314.  		(void) mdamageu(magr, d((int)mattk->damn, (int)mattk->damd));
315.  
316.  	mondied(magr);
317.  	return(2);
318.  }
319.  
320.  static int
321.  mdamagem(magr, mdef, mattk)
322.  	register struct monst	*magr, *mdef;
323.  	register struct attack	*mattk;
324.  {
325.  	struct	permonst *ptr, *pd = mdef->data;
326.  	int	tmp = d((int)mattk->damn,(int)mattk->damd);
327.  	char buf[BUFSZ];
328.  
329.  	switch(mattk->adtyp) {
330.  	    case AD_DGST:
331.  		if(flags.verbose && flags.soundok) pline("\"Burrrrp!\"");
332.  		tmp = mdef->mhp;
333.  		break;
334.  	    case AD_STUN:
335.  		if (magr->mcan) break;
336.  		if(vis) pline("%s staggers for a moment.", Monnam(mdef));
337.  		mdef->mstun = 1;
338.  	    case AD_PHYS:
339.  		if (mattk->aatyp == AT_KICK && thick_skinned(mdef->data))
340.  			tmp = 0;
341.  		else if(mattk->aatyp == AT_WEAP) {
342.  		    if(otmp) {
343.  			tmp += dmgval(otmp, pd);
344.  #ifdef NAMED_ITEMS
345.  			if(spec_ability(otmp, SPFX_DRLI) &&
346.  			    !resists_drli(mdef->data)) {
347.  			    int dam = rnd(8);
348.  
349.  			    tmp += dam;
350.  			    if(vis)
351.  				pline("The %s blade drains the life from %s!",
352.  					Hallucination ? hcolor() : black,
353.  					mon_nam(mdef));
354.  			    mdef->mhpmax -= dam;
355.  			    if (mdef->m_lev == 0)
356.  				tmp = mdef->mhp;
357.  			    else mdef->m_lev--;
358.  			}
359.  #endif
360.  			mrustm(magr, mdef, otmp);
361.  		    }
362.  		}
363.  		break;
364.  	    case AD_FIRE:
365.  		if (magr->mcan) {
366.  		    tmp = 0;
367.  		    break;
368.  		}
369.  #ifdef GOLEMS
370.  		golemeffects(mdef, AD_FIRE, tmp);
371.  #endif /* GOLEMS */
372.  		if(resists_fire(pd)) {
373.  		    shieldeff(mdef->mx, mdef->my);
374.  		    tmp = 0;
375.  		} else {
376.  		    tmp += destroy_mitem(mdef, SCROLL_SYM, AD_FIRE);
377.  		    tmp += destroy_mitem(mdef, POTION_SYM, AD_FIRE);
378.  #ifdef SPELLS
379.  		    tmp += destroy_mitem(mdef, SPBOOK_SYM, AD_FIRE);
380.  #endif
381.  		}
382.  		break;
383.  	    case AD_COLD:
384.  		if (magr->mcan) {
385.  		    tmp = 0;
386.  		    break;
387.  		}
388.  #ifdef GOLEMS
389.  		golemeffects(mdef, AD_COLD, tmp);
390.  #endif /* GOLEMS */
391.  		if(resists_cold(pd)) {
392.  		    shieldeff(mdef->mx, mdef->my);
393.  		    tmp = 0;
394.  		} else tmp += destroy_mitem(mdef, POTION_SYM, AD_COLD);
395.  		break;
396.  	    case AD_ELEC:
397.  		if (magr->mcan) {
398.  		    tmp = 0;
399.  		    break;
400.  		}
401.  #ifdef GOLEMS
402.  		golemeffects(mdef, AD_ELEC, tmp);
403.  #endif /* GOLEMS */
404.  		if(resists_elec(pd)) {
405.  		    shieldeff(mdef->mx, mdef->my);
406.  		    tmp = 0;
407.  		}
408.  		break;
409.  	    case AD_ACID:
410.  		if (magr->mcan) {
411.  		    tmp = 0;
412.  		    break;
413.  		}
414.  		if(resists_acid(pd)) tmp = 0;
415.  		break;
416.  	    case AD_RUST:
417.  #ifdef GOLEMS
418.  		if (!magr->mcan && pd == &mons[PM_IRON_GOLEM]) {
419.  			if (vis) pline("%s falls to pieces!", Monnam(mdef));
420.  			else if(mdef->mtame)
421.  			     pline("May %s rust in peace.", mon_nam(mdef));
422.  			mondied(mdef);
423.  			magr->mhpmax += 1 + rn2((int)mdef->m_lev+1);
424.  			ptr = grow_up(magr);
425.  			if(!ptr) return(-1);
426.  			return(2);
427.  		}
428.  #endif /* GOLEMS */
429.  		tmp = 0;
430.  		break;
431.  	    case AD_DCAY:
432.  #ifdef GOLEMS
433.  		if (!magr->mcan && (pd == &mons[PM_WOOD_GOLEM] ||
434.  		    pd == &mons[PM_LEATHER_GOLEM])) {
435.  			if (vis) pline("%s falls to pieces!", Monnam(mdef));
436.  			else if(mdef->mtame)
437.  			     pline("May %s rot in peace.", mon_nam(mdef));
438.  			mondied(mdef);
439.  			magr->mhpmax += 1 + rn2((int)mdef->m_lev+1);
440.  			ptr = grow_up(magr);
441.  			if(!ptr) return(-1);
442.  			return(2);
443.  		}
444.  #endif /* GOLEMS */
445.  		tmp = 0;
446.  		break;
447.  	    case AD_STON:
448.  		if(!resists_ston(pd)) {
449.  			magr->mhpmax += 1 + rn2((int)mdef->m_lev+1);
450.  			if(vis) pline("%s turns to stone!", Monnam(mdef));
451.  			else if(mdef->mtame)
452.       You("have a peculiarly sad feeling for a moment, then it passes.");
453.  			monstone(mdef);
454.  			ptr = grow_up(magr);
455.  			if(!ptr) return(-1);
456.  			return(2);
457.  		}
458.  		tmp = 0;	/* no damage if this fails */
459.  		break;
460.  	    case AD_TLPT:
461.  		if(!magr->mcan && tmp >= mdef->mhp) {
462.  		    rloc(mdef);
463.  		    if(vis && !cansee(mdef->mx, mdef->my))
464.  			pline("%s suddenly disappears!", Monnam(mdef));
465.  		}
466.  		break;
467.  	    case AD_SLEE:
468.  		if(!resists_sleep(pd) && !magr->mcan && vis && !mdef->msleep) {
469.  		    pline("%s falls asleep.", Monnam(mdef));
470.  		    mdef->msleep = 1;
471.  		}
472.  		break;
473.  	    case AD_PLYS:
474.  		if(!magr->mcan && vis && !mdef->mfroz) {
475.  		    pline("%s stops moving.", Monnam(mdef));
476.  		    mdef->mfroz = 1;
477.  		}
478.  		break;
479.  	    case AD_SLOW:
480.  		if(!magr->mcan && vis && mdef->mspeed != MSLOW) {
481.  		    pline("%s slows down.", Monnam(mdef));
482.  		    if (mdef->mspeed == MFAST) mdef->mspeed = 0;
483.  		    else mdef->mspeed = MSLOW;
484.  		}
485.  		break;
486.  	    case AD_CONF:
487.  		/* Since confusing another monster doesn't have a real time
488.  		 * limit, setting spec_used would not really be right (though
489.  		 * we still should check for it).
490.  		 */
491.  		if(!magr->mcan && vis && !mdef->mconf && !magr->mspec_used) {
492.  		    pline("%s looks confused.", Monnam(mdef));
493.  		    mdef->mconf = 1;
494.  		}
495.  		break;
496.  	    case AD_BLND:
497.  		if(!magr->mcan && haseyes(pd)) {
498.  
499.  		    if(vis && !mdef->mblinded)
500.  			pline("%s is blinded.", Monnam(mdef));
501.  		    {
502.  			register unsigned rnd_tmp;
503.  			rnd_tmp = d((int)mattk->damn, (int)mattk->damd);
504.  			mdef->mcansee = 0;
505.  			if((mdef->mblinded + rnd_tmp) > 127)
506.  				mdef->mblinded = 127;
507.  			else mdef->mblinded += rnd_tmp;
508.  		    }
509.  		}
510.  		tmp = 0;
511.  		break;
512.  	    case AD_CURS:
513.  		if(!night() && (magr->data == &mons[PM_GREMLIN])) break;
514.  		if(!magr->mcan && !rn2(10)) {
515.  		    if (is_were(mdef->data) && mdef->data->mlet != S_HUMAN)
516.  			were_change(mdef);
517.  #ifdef GOLEMS
518.  		    if (mdef->data == &mons[PM_CLAY_GOLEM]) {
519.  			    if (vis) {
520.  				pline("Some writing vanishes from %s's head!",
521.  				    mon_nam(mdef));
522.  				pline("%s dies!", Monnam(mdef));
523.  			    }
524.  			    else if (mdef->mtame)
525.  	You("have a strangely sad feeling for a moment, then it passes.");
526.  			    mondied(mdef);
527.  			    magr->mhpmax += 1 + rn2((int)mdef->m_lev+1);
528.  			    ptr = grow_up(magr);
529.  			    if(!ptr) return(-1);
530.  			    return(2);
531.  		      }
532.  #endif /* GOLEMS */
533.  		    mdef->mcan = 1;
534.  		    if (flags.soundok) {
535.  			    if (!vis) You("hear laughter.");
536.  			    else pline("%s chuckles.", Monnam(magr));
537.  		    }
538.  		}
539.  		break;
540.  	    case AD_SGLD:
541.  		tmp = 0;
542.  		if (magr->mcan || !mdef->mgold) break;
543.  		/* technically incorrect; no check for stealing gold from
544.  		 * between mdef's feet...
545.  		 */
546.  		magr->mgold += mdef->mgold;
547.  		mdef->mgold = 0;
548.  		if (vis) {
549.  			Strcpy(buf, Monnam(magr));
550.  			pline("%s steals some gold from %s.", buf,
551.  								mon_nam(mdef));
552.  		}
553.  		break;
554.  	    case AD_DRLI:
555.  		if(rn2(2) && !resists_drli(mdef->data)) {
556.  			tmp = d(2,6);
557.  			if (vis)
558.  			    kludge("%s suddenly seems weaker!", Monnam(mdef));
559.  			mdef->mhpmax -= tmp;
560.  			if (mdef->m_lev == 0)
561.  				tmp = mdef->mhp;
562.  			else mdef->m_lev--;
563.  			/* Automatic kill if drained past level 0 */
564.  		}
565.  		break;
566.  #ifdef SEDUCE
567.  	    case AD_SSEX:
568.  #endif
569.  	    case AD_SITM:	/* for now these are the same */
570.  	    case AD_SEDU:
571.  		if (!magr->mcan && mdef->minvent) {
572.  		   	otmp = mdef->minvent;
573.  			mdef->minvent = otmp->nobj;
574.  			otmp->nobj = magr->minvent;
575.  			magr->minvent = otmp;
576.  			if (vis) {
577.  				Strcpy(buf, Monnam(magr));
578.  				pline("%s steals %s from %s!", buf,
579.  						doname(otmp), mon_nam(mdef));
580.  			}
581.  		}
582.  		tmp = 0;
583.  		break;
584.  	    case AD_DRST:
585.  	    case AD_DRDX:
586.  	    case AD_DRCO:
587.  		if (!magr->mcan && !rn2(8)) {
588.  		    if (vis)
589.  			pline("%s's %s was poisoned!", Monnam(magr),
590.  				mattk->aatyp==AT_BITE ? "bite" : "sting");
591.  		    if (resists_poison(mdef->data)) {
592.  			if (vis)
593.  			    pline("The poison doesn't seem to affect %s.",
594.  				mon_nam(mdef));
595.  		    } else {
596.  			if (rn2(10)) tmp += rn1(10,6);
597.  			else {
598.  			    if (vis) pline("The poison was deadly...");
599.  			    tmp = mdef->mhp;
600.  			}
601.  		    }
602.  		}
603.  		break;
604.  	    case AD_STCK:
605.  	    case AD_WRAP: /* monsters cannot grab one another, it's too hard */
606.  		break;
607.  	    default:	tmp = 0;
608.  			break;
609.  	}
610.  	if(!tmp) return(1);
611.  
612.  	if((mdef->mhp -= tmp) < 1) {
613.  	    magr->mhpmax += 1 + rn2((int)mdef->m_lev+1);
614.  	    if(vis) pline("%s is killed!", Monnam(mdef));
615.  	    else if(mdef->mtame)
616.  		You("have a sad feeling for a moment, then it passes.");
617.  	    mondied(mdef);
618.  	    ptr = grow_up(magr);
619.  	    if(!ptr) return(-1);
620.  	    return(2);
621.  	}
622.  	/* fixes a bug where max monster hp could overflow. */
623.  	if(magr->mhpmax <= 0 || magr->mhpmax > MHPMAX) magr->mhpmax = MHPMAX;
624.  
625.  	return(1);
626.  }
627.  
628.  int
629.  noattacks(ptr)			/* returns 1 if monster doesn't attack */
630.  	struct	permonst *ptr;
631.  {
632.  	int i;
633.  
634.  	for(i = 0; i < NATTK; i++)
635.  		if(ptr->mattk[i].aatyp) return(0);
636.  
637.  	return(1);
638.  }
639.  
640.  static void
641.  mrustm(magr, mdef, obj)
642.  register struct monst *magr, *mdef;
643.  register struct obj *obj;
644.  {
645.  	if (!magr || !mdef || !obj) return; /* just in case */
646.  	if (mdef->data == &mons[PM_RUST_MONSTER] &&
647.  				objects[obj->otyp].oc_material == METAL &&
648.  				!obj->rustfree && obj->spe > -2) {
649.  		if(obj->blessed && rn2(3)) {
650.  		    if (cansee(mdef->mx, mdef->my))
651.  			pline("%s's weapon is not affected.", Monnam(magr));
652.  		} else {
653.  		    if (cansee(mdef->mx, mdef->my))
654.  			pline("%s's %s!", Monnam(magr),
655.  						aobjnam(obj, "corrode"));
656.  		    obj->spe--;
657.  		}
658.  	}
659.  }
660.  
661.  static void
662.  mswingsm(magr, mdef, otemp)
663.  register struct monst *magr, *mdef;
664.  register struct obj *otemp;
665.  {
666.  	char buf[BUFSZ];
667.  	Strcpy(buf, mon_nam(mdef));
668.  	if (!flags.verbose || Blind || otemp->olet != WEAPON_SYM) return;
669.  	pline("%s %s %s %s at %s.", Monnam(magr),
670.  	      (otemp->otyp == SPEAR ||
671.  	       otemp->otyp == LANCE ||
672.  	       otemp->otyp == GLAIVE ||
673.  	       otemp->otyp == TRIDENT) ? "thrusts" : "swings",
674.  	      is_female(magr) ? "her" :
675.  	      is_human(magr->data) ? "his" : "its",
676.  	      xname(otemp), buf);
677.  }