Source:NetHack 3.0.0/mhitu.c

From NetHackWiki
Jump to navigation Jump to search

Below is the full text to mhitu.c from the source code of NetHack 3.0.0. To link to a particular line, write [[NetHack 3.0.0/mhitu.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: \@(#)mhitu.c	3.0	88/10/28
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 struct obj *otmp;
11.   #ifdef POLYSELF
12.   static void urustm P((struct monst *, struct obj *));
13.   static int passiveum P((struct permonst *, struct monst *));
14.   #endif
15.   #ifdef SEDUCE
16.   static void mayberem P((struct obj *, char *));
17.   #endif
18.   static int hitmu P((struct monst *,struct attack *));
19.   static int gulpmu P((struct monst *,struct attack *));
20.   static int explmu P((struct monst *,struct attack *));
21.   static int gazemu P((struct monst *,struct attack *));
22.   
23.   #ifdef POLYSELF
24.   boolean
25.   /* also needed in uhitm.c */
26.   #else
27.   static boolean
28.   #endif
29.   incompatible(mon)
30.   register struct monst *mon;
31.   {
32.   	return(poly_gender() != 1-gender(mon));
33.   }
34.   
35.   boolean
36.   is_nymph(mon)
37.   register struct monst *mon;
38.   {
39.   	return( mon->data->mlet == S_NYMPH );
40.   }
41.   
42.   boolean
43.   sp_melee(mon)
44.   register struct monst *mon;
45.   {
46.   	return(
47.   #ifdef SEDUCE
48.   		(mon->data == &mons[PM_SUCCUBUS] && !mon->minvis) ||
49.   		(mon->data == &mons[PM_INCUBUS] && !mon->minvis) ||
50.   #endif
51.   		is_nymph(mon));
52.   }
53.   
54.   static void
55.   hitmsg(mtmp, attyp)
56.   register struct monst *mtmp;
57.   register uchar attyp;
58.   {
59.   	/* Note: if opposite gender, "seductively" */
60.   	/* If same gender, "engagingly" for nymph, normal msg for others */
61.   	if(sp_melee(mtmp) && !mtmp->mcan) {
62.   		if(!is_nymph(mtmp) && incompatible(mtmp)) goto strike;
63.   	    	kludge("%s %s you %s.", Monnam(mtmp),
64.   			Blind ? "talks to" : "smiles at",
65.   			incompatible(mtmp) ? "engagingly" : "seductively");
66.   	} else
67.   strike:
68.   	    switch (attyp) {
69.   		case AT_BITE:
70.   			kludge("%s bites!", Monnam(mtmp));
71.   			break;
72.   		case AT_KICK:
73.   #ifdef POLYSELF
74.   			kludge("%s kicks%c", Monnam(mtmp), thick_skinned(uasmon) ? '.' : '!');
75.   #else
76.   			kludge("%s kicks!", Monnam(mtmp));
77.   #endif
78.   			break;
79.   		case AT_STNG:
80.   			kludge("%s stings!", Monnam(mtmp));
81.   			break;
82.   		case AT_BUTT:
83.   			kludge("%s butts!", Monnam(mtmp));
84.   			break;
85.   		case AT_TUCH:
86.   			kludge("%s touches you!", Monnam(mtmp));
87.   			break;
88.   		default:
89.   			kludge("%s hits!", Monnam(mtmp));
90.   	    }
91.   }
92.   
93.   static void
94.   missmu(mtmp, nearmiss)		/* monster missed you */
95.   register struct monst *mtmp;
96.   register boolean nearmiss;
97.   {
98.   	if(sp_melee(mtmp) && !mtmp->mcan) {
99.   	    if(!is_nymph(mtmp) && incompatible(mtmp)) goto strike;
100.  	    kludge("%s pretends to be friendly.", Monnam(mtmp));
101.  	} else {
102.  strike:
103.  	    if (!flags.verbose || !nearmiss)
104.  		kludge("%s misses.", Monnam(mtmp));
105.  	    else
106.  		kludge("%s just misses!", Monnam(mtmp));
107.  	}
108.  }
109.  
110.  static void
111.  mswings(mtmp, otemp)		/* monster swings obj */
112.  register struct monst *mtmp;
113.  register struct obj *otemp;
114.  {
115.  	if (!flags.verbose || Blind || otemp->olet != WEAPON_SYM) return;
116.  	pline("%s %s %s %s.", Monnam(mtmp),
117.  	      (otemp->otyp == SPEAR ||
118.  	       otemp->otyp == LANCE ||
119.  	       otemp->otyp == GLAIVE ||
120.  	       otemp->otyp == TRIDENT) ? "thrusts" : "swings",
121.  	      is_female(mtmp) ? "her" :
122.  	      is_human(mtmp->data) ? "his" : "its",
123.  	      xname(otemp));
124.  }
125.  
126.  static void
127.  wildmiss(mtmp)		/* monster attacked your displaced image */
128.  	register struct monst *mtmp;
129.  {
130.  	if (!flags.verbose) return;
131.  	if (!cansee(mtmp->mx, mtmp->my)) return;
132.  		/* maybe it's attacking an image around the corner? */
133.  	if(Invis && !perceives(mtmp->data)) {
134.  	    if(sp_melee(mtmp) && !mtmp->mcan) {
135.  		if(!is_nymph(mtmp) && incompatible(mtmp)) goto strike;
136.  		kludge("%s tries to touch you and misses!", Monnam(mtmp));
137.  	    } else
138.  strike:
139.  		switch(rn2(3)) {
140.  		case 0: kludge("%s swings wildly and misses!", Monnam(mtmp));
141.  		    break;
142.  		case 1: kludge("%s attacks a spot beside you.", Monnam(mtmp));
143.  		    break;
144.  		case 2: kludge("%s strikes at thin air!", Monnam(mtmp));
145.  		    break;
146.  		default:kludge("%s swings wildly!", Monnam(mtmp));
147.  		    break;
148.  		}
149.  	}
150.  	else if(Displaced) {
151.  	    if(sp_melee(mtmp) && !mtmp->mcan) {
152.  		if(!is_nymph(mtmp) && incompatible(mtmp)) goto strikem;
153.  		kludge("%s smiles %s at your %sdisplaced image...",
154.  			Monnam(mtmp),
155.  			incompatible(mtmp) ? "engagingly" : "seductively",
156.  			Invis ? "invisible " : "");
157.  	   } else
158.  strikem:
159.  		kludge("%s strikes at your %sdisplaced image and misses you!",
160.  			/* Note: if you're both invisible and displaced,
161.  			 * only monsters which see invisible will attack your
162.  			 * displaced image, since the displaced image is also
163.  			 * invisible.
164.  			 */
165.  			Monnam(mtmp),
166.  			Invis ? "invisible " : "");
167.  	}
168.  	else impossible("%s attacks you without knowing your location?",
169.  		Monnam(mtmp));
170.  }
171.  
172.  static void
173.  regurgitates(mtmp)
174.  register struct monst *mtmp;
175.  {
176.  	u.ux = mtmp->mx;
177.  	u.uy = mtmp->my;
178.  	u.uswallow = 0;
179.  	u.ustuck = 0;
180.  	mnexto(mtmp);
181.  	setsee();
182.  	docrt();
183.  	spoteffects();
184.  	/* to cover for a case where mtmp is not in a next square */
185.  	if(um_dist(mtmp->mx,mtmp->my,1))
186.  		pline("Brrooaa...  You land hard at some distance.");
187.  }
188.  
189.  /*
190.   * mattacku: monster attacks you
191.   *	returns 1 if monster dies (e.g. "yellow light"), 0 otherwise
192.   *	Note: if you're displaced or invisible the monster might attack the
193.   *		wrong position...
194.   *	Assumption: it's attacking you or an empty square; if there's another
195.   *		monster which it attacks by mistake, the caller had better
196.   *		take care of it...
197.   */
198.  int
199.  mattacku(mtmp)
200.  	register struct monst *mtmp;
201.  {
202.  	struct	attack	*mattk;
203.  	int	i, j, tmp, sum[NATTK];
204.  	struct	permonst *mdat = mtmp->data;
205.  	boolean ranged = (dist(mtmp->mx, mtmp->my) > 3);
206.  		/* Is it near you?  Affects your actions */
207.  	boolean range2 = (dist2(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy) > 3);
208.  		/* Does it think it's near you?  Affects its actions */
209.  	boolean foundyou = (mtmp->mux==u.ux && mtmp->muy==u.uy);
210.  		/* Is it attacking you or your image? */
211.  	boolean youseeit = (cansee(mtmp->mx, mtmp->my));
212.  		/* Necessary since if it's attacking your image around a
213.  		 * corner, you might not see it
214.  		 */
215.  
216.  	if(!ranged) nomul(0);
217.  	if(mtmp->mhp <= 0) return(0);
218.  
219.  	/* If swallowed, can only be affected by u.ustuck */
220.  	if(u.uswallow) {
221.  	    if(mtmp != u.ustuck)
222.  		return(0);
223.  	    u.ustuck->mux = u.ux;
224.  	    u.ustuck->muy = u.uy;
225.  	    range2 = 0;
226.  	    foundyou = 1;
227.  	    /* This is not impossible! */
228.  	    /* If the swallowing monster changes into a monster
229.  	     * that is not capable of swallowing you, you get
230.  	     * regurgitated - dgk
231.  	     */
232.  	    for(i = 0; i < NATTK; i++)
233.  		if(mdat->mattk[i].aatyp == AT_ENGL) goto doattack;
234.  
235.  	    You("get regurgitated!");
236.  	    regurgitates(mtmp);
237.  	    return(0);
238.  	}
239.  doattack:
240.  #ifdef POLYSELF
241.  	if (u.uundetected && !range2 && foundyou) {
242.  		u.uundetected = 0;
243.  		if (u.usym == S_PIERCER) {
244.  		    coord cc; /* maybe we need a unexto() function? */
245.  
246.  		    unpmon(mtmp);
247.  		    levl[mtmp->mx][mtmp->my].mmask = 0;
248.  		    mtmp->mx = u.ux; mtmp->my = u.uy;
249.  		    levl[mtmp->mx][mtmp->my].mmask = 1;
250.  		    pmon(mtmp);
251.  		    enexto(&cc, u.ux, u.uy);
252.  		    /* Luckily piercers cannot walk through walls, so this
253.  		     * will work.  If they can (i.e., if someone adds a potion
254.  		     * of phasing), we gotta change this...
255.  		     */
256.  		    teleds(cc.x, cc.y);
257.  		    You("fall from the ceiling!");
258.  		    if (is_mercenary(mtmp->data) && m_carrying(mtmp,HELMET)) {
259.  			kludge("Your blow glances off %s's helmet.",
260.  								mon_nam(mtmp));
261.  		    } else {
262.  			if (3 + mtmp->data->ac <= rnd(20)) {
263.  			    kludge("%s is hit by a falling piercer (you)!",
264.  								Monnam(mtmp));
265.  			    if ((mtmp->mhp -= d(3,6)) < 1)
266.  				killed(mtmp);
267.  			} else
268.  			  kludge("%s is almost hit by a falling piercer (you)!",
269.  			    					Monnam(mtmp));
270.  		    }
271.  		} else {
272.  		    if (Blind) pline("It tries to move where you are hiding.");
273.  		    else
274.  		     pline("Wait, %s!  There's a %s named %s hiding under %s!",
275.  			mtmp->mnamelth ? NAME(mtmp) : mtmp->data->mname,
276.  			uasmon->mname, plname,
277.  			levl[u.ux][u.uy].omask ? doname(o_at(u.ux,u.uy)) :
278.  			"some gold");
279.  		    prme();
280.  		}
281.  		return(0);
282.  	}
283.  	if (u.usym == S_MIMIC_DEF && !range2 && foundyou) {
284.  		if (Blind) pline("It gets stuck on you.");
285.  		    else pline("Wait, %s!  That's a %s named %s!",
286.  			mtmp->mnamelth ? NAME(mtmp) : mtmp->data->mname,
287.  			uasmon->mname, plname);
288.  		u.ustuck = mtmp;
289.  		u.usym = S_MIMIC;
290.  		prme();
291.  		return(0);
292.  	}
293.  #endif
294.  /*	Work out the armor class differential	*/
295.  	tmp = u.uac + 10;		/* tmp ~= 0 - 20 */
296.  /*	give people with Ac < -9 at least some vulnerability */
297.  /*	negative AC gives an actual AC of somewhere from -1 to the AC */
298.  	if (tmp < 10) tmp = 10 - rnd(10-tmp);
299.  	tmp += mtmp->m_lev;
300.  	if(multi < 0) tmp += 4;
301.  	if((Invis && !perceives(mdat)) || !mtmp->mcansee)
302.  		tmp -= 2;
303.  	if(mtmp->mtrapped) tmp -= 2;
304.  	if(tmp <= 0) tmp = 1;
305.  
306.  	/* make eels visible the moment they hit/miss us */
307.  	if(mdat->mlet == S_EEL && mtmp->minvis && cansee(mtmp->mx,mtmp->my)) {
308.  		mtmp->minvis = 0;
309.  		pmon(mtmp);
310.  	}
311.  
312.  /*	Special demon handling code */
313.  	if(!mtmp->cham && is_demon(mdat) && !range2
314.  #ifdef HARD
315.  	   && mtmp->data != &mons[PM_BALROG]
316.  	   && mtmp->data != &mons[PM_SUCCUBUS]
317.  	   && mtmp->data != &mons[PM_INCUBUS]
318.  #endif
319.  	   )
320.  	    if(!mtmp->mcan && !rn2(13))	dsummon(mdat);
321.  
322.  /*	Special lycanthrope handling code */
323.  	if(!mtmp->cham && is_were(mdat) && !range2) {
324.  
325.  	    if(is_human(mdat)) {
326.  		if(!rn2(5 - (night() * 2)) && !mtmp->mcan) new_were(mtmp);
327.  	    } else if(!rn2(30) && !mtmp->mcan) new_were(mtmp);
328.  
329.  	    if(!rn2(10) && !mtmp->mcan) {
330.  		if(!Blind) {
331.  			pline("%s summons help!",youseeit ?
332.  				Monnam(mtmp) : "It");
333.  		} else
334.  			You("feel hemmed in.");
335.  		/* Technically wrong; we really should check if you can see the
336.  		 * help, but close enough...
337.  		 */
338.  		if (!were_summon(mdat,FALSE) && !Blind)
339.  		    pline("But none comes.");
340.  	    }
341.  	}
342.  
343.  	for(i = 0; i < NATTK; i++) {
344.  
345.  	    mattk = &(mdat->mattk[i]);
346.  	    switch(mattk->aatyp) {
347.  		case AT_CLAW:	/* "hand to hand" attacks */
348.  		case AT_KICK:
349.  		case AT_BITE:
350.  		case AT_STNG:
351.  		case AT_TUCH:
352.  		case AT_BUTT:
353.  			if(!range2) {
354.  			    if (!foundyou) {
355.  				wildmiss(mtmp);
356.  				sum[i] = 0;
357.  			    } else if(tmp > (j = rnd(20+i)))
358.  #ifdef POLYSELF
359.  				if (mattk->aatyp == AT_KICK &&
360.  					thick_skinned(uasmon)) sum[i] = 0;
361.  			        else
362.  #endif
363.  					sum[i] = hitmu(mtmp, mattk);
364.  			    else {
365.  				missmu(mtmp, (tmp == j));
366.  				sum[i] = 0;
367.  			    }
368.  			} else	sum[i] = 0;
369.  			break;
370.  
371.  		case AT_HUGS:	/* automatic if prev two attacks succeed */
372.  			/* Note: if displaced, prev attacks never succeeded */
373.  			if(!range2) {
374.  			    if(sum[i-1] && sum[i-2])
375.  				sum[i]= hitmu(mtmp, mattk);
376.  			    else sum[i] = 0;
377.  			} else	 sum[i] = 0;
378.  			break;
379.  
380.  		case AT_GAZE:	/* can affect you either ranged or not */
381.  			if (!youseeit) sum[i] = 0;
382.  			    /* Displaced and around a corner so not visible */
383.  			else sum[i] = gazemu(mtmp, mattk);
384.  			break;
385.  
386.  		case AT_EXPL:	/* automatic hit if next to, and aimed at you */
387.  			if(!range2) {
388.  			    if (!foundyou) {
389.  				if (!mtmp->mcan) {
390.  				    pline("%s explodes at a spot in thin air!",
391.  					youseeit ? Monnam(mtmp) : "It");
392.  				    mondead(mtmp);
393.  				    sum[i] = 2;
394.  				} else sum[i] = 0;
395.  			    } else    sum[i] = explmu(mtmp, mattk);
396.  			} else sum[i] = 0;
397.  			break;
398.  
399.  		case AT_ENGL:
400.  			if (!range2) {
401.  			    if(foundyou) {
402.  				if(u.uswallow || tmp > (j = rnd(20+i))) {
403.  				    /* Force swallowing monster to be
404.  				     * displayed even when player is
405.  				     * moving away */
406.  				    nscr();
407.  				    sum[i] = gulpmu(mtmp, mattk);
408.  				} else {
409.  				    missmu(mtmp, (tmp == j));
410.  				    sum[i] = 0;
411.  				}
412.  			    } else pline("%s gulps some air!", youseeit ?
413.  				Monnam(mtmp) : "It");
414.  			} else	sum[i] = 0;
415.  			break;
416.  		case AT_BREA:
417.  			if(range2) sum[i] = breamu(mtmp, mattk);
418.  			/* Note: breamu takes care of displacement */
419.  			else	   sum[i] = 0;
420.  			break;
421.  		case AT_SPIT:
422.  			if(range2) sum[i] = spitmu(mtmp);
423.  			/* Note: spitmu takes care of displacement */
424.  			else	   sum[i] = 0;
425.  			break;
426.  		case AT_WEAP:
427.  			if(range2) {
428.  #ifdef REINCARNATION
429.  				if (dlevel != rogue_level)
430.  #endif
431.  					sum[i] = thrwmu(mtmp);
432.  			} else {
433.  			    if (!foundyou) {
434.  				wildmiss(mtmp);
435.  				sum[i] = 0;
436.  			    } else {
437.  				set_uasmon();
438.  				otmp = select_hwep(mtmp);
439.  				if(otmp) {
440.  				    tmp += hitval(otmp, uasmon);
441.  				    mswings(mtmp, otmp);
442.  				}
443.  				if(tmp > (j = rnd(20+i)))
444.  				    sum[i] = hitmu(mtmp, mattk);
445.  				else {
446.  				    missmu(mtmp, (tmp == j));
447.  				    sum[i] = 0;
448.  				}
449.  			    }
450.  			}
451.  			break;
452.  		case AT_MAGC:
453.  			if(!range2) {
454.  			    if (!foundyou) {
455.  				pline("%s casts a spell at thin air!",
456.  					youseeit ? Monnam(mtmp) : "It");
457.  				sum[i] = 0;
458.  				/* Not totally right since castmu allows other
459.  				 * spells, such as the monster healing itself,
460.  				 * that should work even when not next to you--
461.  				 * but the previous code was just as wrong.
462.  				 * --KAA
463.  				 */
464.  			    } else sum[i] = castmu(mtmp, mattk);
465.  			} else	sum[i] = buzzmu(mtmp, mattk);
466.  			break;
467.  
468.  		default:		/* no attack */
469.  			sum[i] = 0;
470.  			break;
471.  	    }
472.  	    if(flags.botl) bot();
473.  	    if(sum[i] == 2)  return(1);  	/* attacker dead */
474.  	}
475.  	return(0);
476.  }
477.  
478.  /*
479.   * hitmu: monster hits you
480.   *	  returns 2 if monster dies (e.g. "yellow light"), 0 otherwise
481.   */
482.  static
483.  int
484.  hitmu(mtmp, mattk)
485.  	register struct monst *mtmp;
486.  	register struct attack  *mattk;
487.  {
488.  	register struct permonst *mdat = mtmp->data;
489.  	register int dmg, ctmp, ptmp;
490.  	register boolean getbronze;
491.  	char	 buf[BUFSZ];
492.  #ifdef POLYSELF
493.  	struct permonst *olduasmon = uasmon;
494.  	int res;
495.  #endif
496.  
497.  /*	If the monster is undetected & hits you.  You should know where
498.   *	the attack came from.
499.   */
500.  	if(mtmp->mhide && mtmp->mundetected) {
501.  	    mtmp->mundetected = 0;
502.  	    if(!(Blind ? Telepat : (HTelepat & WORN_HELMET))) {
503.  		register struct obj *obj;
504.  
505.  		if(levl[mtmp->mx][mtmp->my].omask == 1) {
506.  		    if(obj = o_at(mtmp->mx,mtmp->my))
507.  			pline("%s was hidden under %s!",
508.  				  Xmonnam(mtmp), doname(obj));
509.  		} else if (levl[mtmp->mx][mtmp->my].gmask == 1)
510.  			pline("%s was hidden under some gold!",
511.  				  Xmonnam(mtmp));
512.  	    }
513.  	}
514.  
515.  /*	First determine the base damage done */
516.  	dmg = d((int)mattk->damn, (int)mattk->damd);
517.  	if(is_undead(mdat) && midnight())
518.  		dmg += d((int)mattk->damn, (int)mattk->damd); /* extra damage */
519.  
520.  /*	Next a cancellation factor	*/
521.  /*	Use ctmp when the cancellation factor takes into account certain
522.   *	armor's special magic protection.  Otherwise just use !mtmp->mcan.
523.   */
524.  	ctmp = !mtmp->mcan &&
525.  		(!uarm || (rn2(3) >= objects[uarm->otyp].a_can) || !rn2(50))
526.  	     && (!uarmc || (rn2(3) >= objects[uarmc->otyp].a_can) || !rn2(50));
527.  
528.  /*	Now, adjust damages via resistances or specific attacks */
529.  	switch(mattk->adtyp) {
530.  	    case AD_PHYS:
531.  		if(mattk->aatyp == AT_HUGS
532.  #ifdef POLYSELF
533.  					   && !sticks(uasmon)
534.  #endif
535.  								) {
536.  		    if(!u.ustuck && rn2(2)) {
537.  			u.ustuck = mtmp;
538.  			kludge("%s grabs you!", Monnam(mtmp));
539.  		    } else if(u.ustuck == mtmp)
540.  			You("are being %s.",
541.  #ifdef GOLEMS
542.  			      (mtmp->data == &mons[PM_ROPE_GOLEM])
543.  			      ? "choked" :
544.  #endif /* GOLEMS */
545.  			      "crushed");
546.  
547.  		} else {			  /* hand to hand weapon */
548.  		    hitmsg(mtmp,mattk->aatyp);
549.  		    if(mattk->aatyp == AT_WEAP && otmp) {
550.  			dmg += dmgval(otmp, uasmon);
551.  			if (dmg <= 0) dmg = 1;
552.  #ifdef NAMED_ITEMS
553.  			if (spec_ability(otmp, SPFX_DRLI)
554.  #  ifdef POLYSELF
555.  						&& !resists_drli(uasmon)
556.  #  endif
557.  									) {
558.  				pline("The %s blade drains your life!",
559.  					Hallucination ? hcolor() : black);
560.  				losexp();
561.  			}
562.  #endif
563.  #ifdef POLYSELF
564.  			if (u.mh > 1 && u.mh > ((u.uac>0) ? dmg : dmg+u.uac) &&
565.  					(u.umonnum==PM_BLACK_PUDDING
566.  					|| u.umonnum==PM_BROWN_PUDDING)) {
567.  			    /* This redundancy necessary because you have to
568.  			     * take the damage _before_ being cloned.
569.  			     */
570.  			    if (u.uac < 0) dmg += u.uac;
571.  			    if (dmg < 1) dmg = 1;
572.  			    u.mh -= dmg;
573.  			    flags.botl = 1;
574.  			    dmg = 0;
575.  			    if(cloneu())
576.  			    kludge("You divide as %s hits you!",mon_nam(mtmp));
577.  			}
578.  			urustm(mtmp, otmp);
579.  #endif
580.  		    }
581.  		}
582.  		break;
583.  	    case AD_DISE:
584.  		hitmsg(mtmp, mattk->aatyp);
585.  		You("feel very sick.");
586.  		make_sick((long)rn1(25-ACURR(A_CON),15),FALSE);
587.  		u.usick_cause = mdat->mname;
588.  		break;
589.  	    case AD_FIRE:
590.  		hitmsg(mtmp,mattk->aatyp);
591.  		if(ctmp && rn2(2)) {
592.  		    pline("You're on fire!");
593.  		    if (Fire_resistance) {
594.  			pline("The fire doesn't feel hot!");
595.  			dmg = 0;
596.  		    }
597.  		    if(mtmp->m_lev > rn2(20))
598.  			destroy_item(SCROLL_SYM, AD_FIRE);
599.  		    if(mtmp->m_lev > rn2(20))
600.  			destroy_item(POTION_SYM, AD_FIRE);
601.  #ifdef SPELLS
602.  		    if(mtmp->m_lev > rn2(25))
603.  			destroy_item(SPBOOK_SYM, AD_FIRE);
604.  #endif
605.  		}
606.  		break;
607.  	    case AD_COLD:
608.  		hitmsg(mtmp,mattk->aatyp);
609.  		if(ctmp && rn2(2)) {
610.  		    pline("You're covered in frost!");
611.  		    if (Cold_resistance) {
612.  			pline("The frost doesn't seem cold!");
613.  			dmg = 0;
614.  		    }
615.  		    if(mtmp->m_lev > rn2(20))
616.  			destroy_item(POTION_SYM, AD_COLD);
617.  		}
618.  		break;
619.  	    case AD_ELEC:
620.  		hitmsg(mtmp,mattk->aatyp);
621.  		if(ctmp && rn2(2)) {
622.  		    You("get zapped!");
623.  		    if (Shock_resistance) {
624.  			pline("The zap doesn't shock you!");
625.  			dmg = 0;
626.  		    }
627.  		    if(mtmp->m_lev > rn2(20))
628.  			destroy_item(WAND_SYM, AD_ELEC);
629.  		    if(mtmp->m_lev > rn2(20))
630.  			destroy_item(RING_SYM, AD_ELEC);
631.  		}
632.  		break;
633.  	    case AD_SLEE:
634.  		hitmsg(mtmp,mattk->aatyp);
635.  		if(ctmp && multi >= 0 && !rn2(5)) {
636.  		    if (Sleep_resistance) break;
637.  		    nomul(-rnd(10));
638.  		    if (Blind)	You("are put to sleep!");
639.  		    else	You("are put to sleep by %s!",mon_nam(mtmp));
640.  		}
641.  		break;
642.  	    case AD_DRST:
643.  		ptmp = A_STR;
644.  		goto dopois;
645.  	    case AD_DRDX:
646.  		ptmp = A_DEX;
647.  		goto dopois;
648.  	    case AD_DRCO:
649.  		ptmp = A_CON;
650.  dopois:
651.  		hitmsg(mtmp,mattk->aatyp);
652.  		if(ctmp && !rn2(8)) {
653.  			Sprintf(buf, "%s's %s",
654.  				Hallucination ? rndmonnam() : mdat->mname,
655.  				(mattk->aatyp == AT_BITE) ? "bite" : "sting");
656.  			poisoned(buf, ptmp, mdat->mname);
657.  		}
658.  		break;
659.  	    case AD_PLYS:
660.  		hitmsg(mtmp, mattk->aatyp);
661.  		if(ctmp && multi >= 0 && !rn2(3)) {
662.  		    if (Blind)	You("are frozen!");
663.  		    else	You("are frozen by %s!", mon_nam(mtmp));
664.  		    nomul(-rnd(10));
665.  		}
666.  		break;
667.  	    case AD_DRLI:
668.  		hitmsg(mtmp, mattk->aatyp);
669.  		if (ctmp && !rn2(3)
670.  #ifdef POLYSELF
671.  		    && !resists_drli(uasmon)
672.  #endif
673.  #ifdef NAMED_ITEMS
674.  		    && !defends(AD_DRLI, uwep)
675.  #endif
676.  		    ) losexp();
677.  		break;
678.  	    case AD_LEGS:
679.  		{ register long side = rn2(2) ? RIGHT_SIDE : LEFT_SIDE;
680.  		  if (mtmp->mcan) {
681.  		    pline("%s nuzzles against your %s %s!", Monnam(mtmp),
682.  			  (side == RIGHT_SIDE) ? "right" : "left",
683.  			  body_part(LEG));
684.  		  } else {
685.  		    if (uarmf) {
686.  			pline("%s scratches your %s boot!", Monnam(mtmp),
687.  				(side == RIGHT_SIDE) ? "right" : "left");
688.  			break;
689.  		    }
690.  		    pline("%s pricks your %s %s!", Monnam(mtmp),
691.  			  (side == RIGHT_SIDE) ? "right" : "left",
692.  			  body_part(LEG));
693.  		    set_wounded_legs(side, rnd(60-ACURR(A_DEX)));
694.  		  }
695.  		  break;
696.  		}
697.  	    case AD_STON:	/* at present only a cockatrice */
698.  		hitmsg(mtmp,mattk->aatyp);
699.  		if(!rn2(3) && !Stoned) {
700.  		    if (mtmp->mcan) {
701.  			if (flags.soundok)
702.  			    You("hear a cough from %s!", mon_nam(mtmp));
703.  		    } else {
704.  			if (flags.soundok)
705.  			    You("hear %s's hissing!", mon_nam(mtmp));
706.  			if((!rn2(10) ||
707.  			    (flags.moonphase == NEW_MOON &&
708.  			     !carrying(DEAD_LIZARD)))
709.  #ifdef POLYSELF
710.  			    && !resists_ston(uasmon)
711.  #endif
712.  			    ) {
713.  				Stoned = 5;
714.  				return(1);
715.  				/* You("turn to stone..."); */
716.  				/* done_in_by(mtmp); */
717.  			}
718.  		    }
719.  		}
720.  		break;
721.  	    case AD_STCK:
722.  		hitmsg(mtmp,mattk->aatyp);
723.  		if(ctmp && !u.ustuck
724.  #ifdef POLYSELF
725.  				     && !sticks(uasmon)
726.  #endif
727.  							) u.ustuck = mtmp;
728.  		break;
729.  	    case AD_WRAP:
730.  		if(ctmp
731.  #ifdef POLYSELF
732.  			&& !sticks(uasmon)
733.  #endif
734.  					  ) {
735.  		    if(!u.ustuck && !rn2(10)) {
736.  			pline("%s swings itself around you!",
737.  				Monnam(mtmp));
738.  			u.ustuck = mtmp;
739.  		    } else if(u.ustuck == mtmp) {
740.  			if (is_pool(mtmp->mx,mtmp->my)
741.  #ifdef POLYSELF
742.  			    && !is_swimmer(uasmon)
743.  #endif
744.  			   ) {
745.  			    pline("%s drowns you...", Monnam(mtmp));
746.  			    done("drowned");
747.  			} else if(mattk->aatyp == AT_HUGS)
748.  			    You("are being crushed.");
749.  		    } else dmg = 0;
750.  		} else dmg = 0;
751.  		break;
752.  	    case AD_WERE:
753.  		hitmsg(mtmp,mattk->aatyp);
754.  #ifdef POLYSELF
755.  		if (ctmp && !rn2(4) && u.ulycn == -1
756.  # ifdef NAMED_ITEMS
757.  		    && !defends(AD_WERE,uwep)
758.  # endif
759.  		    ) {
760.  		    You("feel feverish.");
761.  		    u.ulycn = monsndx(mdat);
762.  		}
763.  #endif
764.  		break;
765.  	    case AD_SGLD:
766.  		hitmsg(mtmp,mattk->aatyp);
767.  #ifdef POLYSELF
768.  		if (u.usym == mdat->mlet) break;
769.  #endif
770.  		if(!mtmp->mcan) stealgold(mtmp);
771.  		break;
772.  
773.  	    case AD_SITM:	/* for now these are the same */
774.  	    case AD_SEDU:
775.  #ifdef POLYSELF
776.  		if (dmgtype(uasmon, AD_SEDU)
777.  #  ifdef SEDUCE
778.  			|| dmgtype(uasmon, AD_SSEX)
779.  #  endif
780.  						) {
781.  			if (mtmp->minvent)
782.  	pline("%s brags about the goods some dungeon explorer provided.",
783.  	Monnam(mtmp));
784.  			else
785.  	pline("%s makes some remarks about how difficult theft is lately.",
786.  	Monnam(mtmp));
787.  			rloc(mtmp);
788.  		} else
789.  #endif
790.  		if(mtmp->mcan) {
791.  		    if (!Blind) {
792.  			pline("%s tries to %s you, but you seem %s.",
793.  			    Amonnam(mtmp, "plain"),
794.  			    flags.female ? "charm" : "seduce",
795.  			    flags.female ? "unaffected" : "uninterested");
796.  		    }
797.  		    if(rn2(3)) rloc(mtmp);
798.  		} else if(steal(mtmp)) {
799.  			rloc(mtmp);
800.  			mtmp->mflee = 1;
801.  		}
802.  		break;
803.  #ifdef SEDUCE
804.  	    case AD_SSEX:
805.  		if(!mtmp->mcan && !mtmp->minvis) doseduce(mtmp);
806.  		break;
807.  #endif
808.  	    case AD_SAMU:
809.  		hitmsg(mtmp,mattk->aatyp);
810.  		/* when the Wiz hits, 1/20 steals the amulet */
811.  		if (!carrying(AMULET_OF_YENDOR)) break;
812.  		if (!rn2(20)) stealamulet(mtmp);
813.  		break;
814.  
815.  	    case AD_TLPT:
816.  		hitmsg(mtmp,mattk->aatyp);
817.  		if(ctmp) {
818.  		    if(flags.verbose)
819.  			Your("position suddenly seems very uncertain!");
820.  		    tele();
821.  		}
822.  		break;
823.  	    case AD_RUST:
824.  		hitmsg(mtmp,mattk->aatyp);
825.  		if (mtmp->mcan) break;
826.  #ifdef POLYSELF
827.  #ifdef GOLEMS
828.  		if (u.umonnum == PM_IRON_GOLEM) {
829.  			You("rust!");
830.  			rehumanize();
831.  			break;
832.  		}
833.  #endif /* GOLEMS */
834.  #endif
835.  		/* What the following code does: it keeps looping until it
836.  		 * finds a target for the rust monster.
837.  		 * Head, feet, etc... not covered by metal, or covered by
838.  		 * rusty metal, are not targets.  However, your body always
839.  		 * is, no matter what covers it.
840.  		 */
841.  		getbronze = (mdat == &mons[PM_BLACK_PUDDING] &&
842.  			     uarm->otyp == BRONZE_PLATE_MAIL);
843.  		while (1) {
844.  		    switch(rn2(5)) {
845.  		    case 0:
846.  			if (!rust_dmg(uarmh, "helmet", 1, FALSE)) continue;
847.  			break;
848.  		    case 1:
849.  			if (uarmc) break;
850.  			/* Note the difference between break and continue;
851.  			 * break means it was hit and didn't rust; continue
852.  			 * means it wasn't a target and though it didn't rust
853.  			 * something else did.
854.  			 */
855.  			if (getbronze)
856.  			    (void)rust_dmg(uarm, "bronze armor", 3, TRUE);
857.  			else
858.  			    (void)rust_dmg(uarm, "armor", 1, TRUE);
859.  			break;
860.  		    case 2:
861.  			if (!rust_dmg(uarms, "shield", 1, FALSE)) continue;
862.  			break;
863.  		    case 3:
864.  			if (!rust_dmg(uarmg, "metal gauntlets", 1, FALSE))
865.  			    continue;
866.  			break;
867.  		    case 4:
868.  			if (!rust_dmg(uarmf, "metal boots", 1, FALSE)) continue;
869.  			break;
870.  		    }
871.  		    break; /* Out of while loop */
872.  		}
873.  		break;
874.  	    case AD_DCAY:
875.  		hitmsg(mtmp,mattk->aatyp);
876.  		if (mtmp->mcan) break;
877.  #ifdef POLYSELF
878.  #ifdef GOLEMS
879.  		if (u.umonnum == PM_WOOD_GOLEM ||
880.  		    u.umonnum == PM_LEATHER_GOLEM) {
881.  			You("rot!");
882.  			rehumanize();
883.  			break;
884.  		}
885.  #endif /* GOLEMS */
886.  #endif
887.  		while (1) {
888.  		    switch(rn2(5)) {
889.  		    case 0:
890.  			if (!rust_dmg(uarmh, "leather helmet", 2, FALSE))
891.  				continue;
892.  			break;
893.  		    case 1:
894.  			if (uarmc) break;
895.  			(void)rust_dmg(uarm, "leather armor", 2, TRUE);
896.  			break;
897.  		    case 2:
898.  			if (!rust_dmg(uarms, "wooden shield", 2, FALSE))
899.  				continue;
900.  			break;
901.  		    case 3:
902.  			if (!rust_dmg(uarmg, "gloves", 2, FALSE)) continue;
903.  			break;
904.  		    case 4:
905.  			if (!rust_dmg(uarmf, "boots", 2, FALSE)) continue;
906.  			break;
907.  		    }
908.  		    break; /* Out of while loop */
909.  		}
910.  		break;
911.  	    case AD_HEAL:
912.  		if(!uwep
913.  #ifdef SHIRT
914.  		   && !uarmu
915.  #endif
916.  		   && !uarm && !uarmh && !uarms && !uarmg && !uarmc && !uarmf) {
917.  		    kludge("%s hits! (I hope you don't mind.)", Monnam(mtmp));
918.  #ifdef POLYSELF
919.  			if (u.mtimedone) {
920.  				u.mh += rnd(7);
921.  				if(!rn2(7)) u.mhmax++;
922.  				if(u.mh > u.mhmax) u.mh = u.mhmax;
923.  				if(u.mh == u.mhmax && !rn2(50)) mongone(mtmp);
924.  			} else {
925.  #endif
926.  				u.uhp += rnd(7);
927.  				if(!rn2(7)) u.uhpmax++;
928.  				if(u.uhp > u.uhpmax) u.uhp = u.uhpmax;
929.  				if(u.uhp == u.uhpmax && !rn2(50)) mongone(mtmp);
930.  #ifdef POLYSELF
931.  			}
932.  #endif
933.  			flags.botl = 1;
934.  			if(!rn2(50)) rloc(mtmp);
935.  			dmg = 0;
936.  		} else
937.  		    if(pl_character[0] == 'H') {
938.  			    if (flags.soundok && !(moves % 5))
939.  				pline("'Doc, I can't help you unless you cooperate.'");
940.  			    dmg = 0;
941.  		    } else hitmsg(mtmp,mattk->aatyp);
942.  		break;
943.  	    case AD_CURS:
944.  		hitmsg(mtmp,mattk->aatyp);
945.  		if(!night() && mdat == &mons[PM_GREMLIN]) break;
946.  		if(!mtmp->mcan && !rn2(10)) {
947.  		    if (flags.soundok)
948.  			if (Blind) You("hear laughter.");
949.  			else       pline("%s chuckles.", Monnam(mtmp));
950.  #ifdef POLYSELF
951.  #ifdef GOLEMS
952.  		    if (u.umonnum == PM_CLAY_GOLEM) {
953.  			pline("Some writing vanishes from your head!");
954.  			rehumanize();
955.  			break;
956.  		    }
957.  #endif /* GOLEMS */
958.  #endif
959.  		    attrcurse();
960.  		}
961.  		break;
962.  	    case AD_STUN:
963.  		hitmsg(mtmp,mattk->aatyp);
964.  		if(!mtmp->mcan && !rn2(4)) {
965.  		    make_stunned(HStun + dmg, TRUE);
966.  		    dmg /= 2;
967.  		}
968.  		break;
969.  	    case AD_ACID:
970.  		hitmsg(mtmp,mattk->aatyp);
971.  		if(!mtmp->mcan && !rn2(3))
972.  #ifdef POLYSELF
973.  		    if (resists_acid(uasmon)) {
974.  			pline("You're covered in acid, but it seems harmless.");
975.  			dmg = 0;
976.  		    } else
977.  #endif
978.  			pline("You're covered in acid!	It burns!");
979.  		else		dmg = 0;
980.  		break;
981.  	    case AD_SLOW:
982.  		hitmsg(mtmp,mattk->aatyp);
983.  		if(!ctmp && (Fast & (INTRINSIC|TIMEOUT)) && !rn2(4)) {
984.  		    Fast &= ~(INTRINSIC|TIMEOUT);
985.  		    You("feel yourself slowing down.");
986.  		}
987.  		break;
988.  	    case AD_DREN:
989.  		hitmsg(mtmp,mattk->aatyp);
990.  #ifdef SPELLS
991.  		if(!ctmp && !rn2(4)) drain_en(dmg);
992.  #endif
993.  		dmg = 0;
994.  		break;
995.  	    case AD_CUSS:
996.  		if(flags.soundok && !rn2(3)) cuss(mtmp);
997.  		dmg = 0;
998.  		break;
999.  #ifdef HARD /* a non-gaze AD_CONF exists only for one of the demons */
1000. 	    case AD_CONF:
1001. 		hitmsg(mtmp,mattk->aatyp);
1002. 		if(!mtmp->mcan && !rn2(4) && !mtmp->mspec_used) {
1003. 		    mtmp->mspec_used += (dmg + rn2(6));
1004. 		    if(Confusion)
1005. 			 You("are getting even more confused.");
1006. 		    else You("are getting confused.");
1007. 		    make_confused(HConfusion + dmg, FALSE);
1008. 		}
1009. #endif
1010. 		/* fall through to next case */
1011. 	    default:	dmg = 0;
1012. 			break;
1013. 	}
1014. 	if(u.uhp < 1) done_in_by(mtmp);
1015. 
1016. /*	Negative armor class reduces damage done instead of fully protecting
1017.  *	against hits.
1018.  */
1019. 	if (dmg && u.uac < 0) {
1020. 		dmg -= rnd(-u.uac);
1021. 		if (dmg < 1) dmg = 1;
1022. 	}
1023. 
1024. 	if(dmg) mdamageu(mtmp, dmg);
1025. 
1026. #ifdef POLYSELF
1027. 	res = passiveum(olduasmon, mtmp);
1028. 	stop_occupation();
1029. 	return res;
1030. #else
1031. 	stop_occupation();
1032. 	return 1;
1033. #endif
1034. }
1035. 
1036. static
1037. int
1038. gulpmu(mtmp, mattk)	/* monster swallows you, or damage if u.uswallow */
1039. 	register struct monst *mtmp;
1040. 	register struct attack  *mattk;
1041. {
1042. 	int	tmp = d((int)mattk->damn, (int)mattk->damd);
1043. 	int	tim_tmp;
1044. #ifdef WALKIES
1045. 	int	i;
1046. #endif
1047. 
1048. 	if(!u.uswallow) {	/* swallow him */
1049. 		levl[mtmp->mx][mtmp->my].mmask = 0;
1050. 		mtmp->mx = u.ux;
1051. 		mtmp->my = u.uy;
1052. 		levl[mtmp->mx][mtmp->my].mmask = 1;
1053. 		u.ustuck = mtmp;
1054. 		pmon(mtmp);
1055. 		kludge("%s engulfs you!", Monnam(mtmp));
1056. #ifdef WALKIES
1057. 		if((i = number_leashed()) > 0) {
1058. 			pline("The leash%s snap%s loose...",
1059. 					(i > 1) ? "es" : "",
1060. 					(i > 1) ? "" : "s");
1061. 			unleash_all();
1062. 		}
1063. #endif
1064. #ifdef POLYSELF
1065. 		if (u.umonnum==PM_COCKATRICE) {
1066. 			kludge("%s turns to stone!", Monnam(mtmp));
1067. 			stoned = 1;
1068. 			xkilled(mtmp, 0);
1069. 			return 2;
1070. 		}
1071. #endif
1072. 		more();
1073. 		seeoff(1);
1074. 		u.uswallow = 1;
1075. 		/*assume that u.uswldtim always set >=0*/
1076. 		u.uswldtim = (tim_tmp =
1077. 			(-u.uac + 10 + rnd(25 - (int)mtmp->m_lev)) >> 1) > 0 ?
1078. 			    tim_tmp : 0;
1079. 		swallowed(1);
1080. 	} else {
1081. 
1082. 	    if(mtmp != u.ustuck) return(0);
1083. 	    switch(mattk->adtyp) {
1084. 
1085. 		case AD_DGST:
1086. 		    if(!u.uswldtim) {	/* a3 *//*no cf unsigned <=0*/
1087. 			kludge("%s totally digests you!", Monnam(mtmp));
1088. 			tmp = u.uhp;
1089. 		    } else {
1090. 			kludge("%s digests you!", Monnam(mtmp));
1091. 		    }
1092. 		    break;
1093. 		case AD_PHYS:
1094. 		    You("are pummeled with debris!");
1095. 		    break;
1096. 		case AD_ACID:
1097. #ifdef POLYSELF
1098. 		    if (resists_acid(uasmon)) {
1099. 			You("are covered with a seemingly harmless goo.");
1100. 			tmp = 0;
1101. 		    } else
1102. #endif
1103. 		    if (Hallucination) pline("Ouch!  You've been slimed!");
1104. 		    else You("are covered in slime!  It burns!!!");
1105. 		    break;
1106. 		case AD_BLND:
1107. 		    if(!Blind) {
1108. 			You("can't see in here!");
1109. 			make_blinded((long)tmp,FALSE);
1110. 		    } else make_blinded(Blinded+1,FALSE);	/* keep him blind until disgorged */
1111. 		    tmp = 0;
1112. 		    break;
1113. 		case AD_ELEC:
1114. 		    if(!mtmp->mcan && rn2(2)) {
1115. 			pline("The air around you crackles with electricity.");
1116. 			if (Shock_resistance) {
1117. 				shieldeff(u.ux, u.uy);
1118. 				You("seem unhurt.");
1119. #if defined(POLYSELF) && defined(GOLEMS)
1120. 				ugolemeffects(AD_ELEC,tmp);
1121. #endif
1122. 				tmp = 0;
1123. 			}
1124. 		    } else tmp = 0;
1125. 		    break;
1126. 		case AD_COLD:
1127. 		    if(!mtmp->mcan && rn2(2)) {
1128. 			if (Cold_resistance) {
1129. 				shieldeff(u.ux, u.uy);
1130. 				You("feel mildly chilly.");
1131. #if defined(POLYSELF) && defined(GOLEMS)
1132. 				ugolemeffects(AD_COLD,tmp);
1133. #endif
1134. 				tmp = 0;
1135. 			} else You("are freezing to death!");
1136. 		    } else tmp = 0;
1137. 		    break;
1138. 		case AD_FIRE:
1139. 		    if(!mtmp->mcan && rn2(2)) {
1140. 			if (Fire_resistance) {
1141. 				shieldeff(u.ux, u.uy);
1142. 				You("feel mildly hot.");
1143. #if defined(POLYSELF) && defined(GOLEMS)
1144. 				ugolemeffects(AD_FIRE,tmp);
1145. #endif
1146. 				tmp = 0;
1147. 			} else You("are burning to a crisp!");
1148. 		    } else tmp = 0;
1149. 		    break;
1150. #ifdef HARD
1151. 		case AD_DISE:
1152. 		    if (!Sick) You("feel very sick.");
1153. 		    make_sick(Sick + (long)rn1(25-ACURR(A_CON),15),FALSE);
1154. 		    u.usick_cause = mtmp->data->mname;
1155. 		    break;
1156. #endif
1157. 		default:	tmp = 0;
1158. 				break;
1159. 	    }
1160. 	}
1161. 
1162. 	mdamageu(mtmp, tmp);
1163. 	if(u.uswldtim) --u.uswldtim;
1164. 	if(!u.uswldtim
1165. #ifdef POLYSELF
1166. 	    || u.umonnum==PM_COCKATRICE
1167. #endif
1168. 	    ) {
1169. #ifdef POLYSELF
1170. 	    if (u.umonnum == PM_COCKATRICE) {
1171. 		kludge("%s very hurriedly regurgitates you!",
1172. 		       Monnam(mtmp));
1173. 		u.uswldtim = 0;
1174. 	    } else {
1175. #endif
1176. 		You("get regurgitated!");
1177. 		if(flags.verbose)
1178. 		    kludge("Obviously %s doesn't like your taste.",
1179. 							mon_nam(mtmp));
1180. #ifdef POLYSELF
1181. 	    }
1182. #endif
1183. 	    regurgitates(mtmp);
1184. 	}
1185. 	return(1);
1186. }
1187. 
1188. static
1189. int
1190. explmu(mtmp, mattk)	/* monster explodes in your face */
1191. 	register struct monst *mtmp;
1192. 	register struct attack  *mattk;
1193. {
1194. 	register int tmp = d((int)mattk->damn, (int)mattk->damd);
1195. 
1196. 	if(mtmp->mcan) return(0);
1197. 	if(!Blind)	kludge("%s explodes!", Monnam(mtmp));
1198. 	else		pline("It explodes!");
1199. 
1200. 	switch(mattk->adtyp) {
1201. 	    case AD_COLD:
1202. 		if(Cold_resistance) {
1203. 			You("seem unaffected by it.");
1204. #if defined(POLYSELF) && defined(GOLEMS)
1205. 			ugolemeffects(AD_COLD,tmp);
1206. #endif
1207. 			tmp = 0;
1208. 		} else {
1209. 			if(ACURR(A_DEX) > rnd(20)) {
1210. 				if (!flags.verbose)
1211. 				    You("are caught in the blast!");
1212. 			} else {
1213. 				You("duck the blast...");
1214. 				tmp /= 2;
1215. 			}
1216. 		}
1217. 		break;
1218. 	    case AD_BLND:
1219. 		if(!Blind
1220. #ifdef POLYSELF
1221. 			&& u.usym != S_YLIGHT
1222. #endif
1223. 			) {
1224. 			You("are blinded by a blast of light!");
1225. 			make_blinded((long)tmp,FALSE);
1226. 		}
1227. 		tmp = 0;
1228. 		break;
1229. 	    default: break;
1230. 	}
1231. 	mdamageu(mtmp, tmp);
1232. 	mondead(mtmp);
1233. 	return(2);	/* it dies */
1234. }
1235. 
1236. static
1237. int
1238. gazemu(mtmp, mattk)	/* monster gazes at you */
1239. 	register struct monst *mtmp;
1240. 	register struct attack  *mattk;
1241. {
1242. 	switch(mattk->adtyp) {
1243. 	    case AD_STON:
1244. 		if (mtmp->mcan) {
1245. 		    You("notice that %s isn't all that ugly.",mon_nam(mtmp));
1246. 		   break;
1247. 		}
1248. 		if (canseemon(mtmp)) {
1249. 			You("look upon %s.", mon_nam(mtmp));
1250. #ifdef POLYSELF
1251. 			if (resists_ston(uasmon)) {
1252. 				pline("So what?");
1253. 				break;
1254. 			}
1255. #endif
1256. 			You("turn to stone...");
1257. 			killer = mons[PM_MEDUSA].mname;
1258. 			done("stoned");
1259. 	    	}
1260. 		break;
1261. 	    case AD_CONF:
1262. 		if(!mtmp->mcan && canseemon(mtmp) && mtmp->mcansee && 
1263. 					!mtmp->mspec_used && rn2(5)) {
1264. 		    int conf = d(3,4);
1265. 
1266. 		    mtmp->mspec_used += (conf + rn2(6));
1267. 		    if(!Confusion)
1268. 			pline("%s's gaze confuses you!", Monnam(mtmp));
1269. 		    else
1270. 			You("are getting more and more confused.");
1271. 		    make_confused(HConfusion + conf, FALSE);
1272. 		}
1273. 		break;
1274. 	    default: impossible("Gaze attack %d?", mattk->adtyp);
1275. 		break;
1276. 	}
1277. 	return(1);
1278. }
1279. 
1280. void
1281. mdamageu(mtmp, n)	/* mtmp hits you for n points damage */
1282. 	register struct monst *mtmp;
1283. 	register int n;
1284. {
1285. #ifdef POLYSELF
1286. 	if (u.mtimedone) {
1287. 		u.mh -= n;
1288. 		flags.botl = 1;
1289. 		if (u.mh < 1) rehumanize();
1290. 		return;
1291. 	}
1292. #endif
1293. 	u.uhp -= n;
1294. 	flags.botl = 1;
1295. 	if(u.uhp < 1)
1296. 		done_in_by(mtmp);
1297. }
1298. 
1299. #ifdef POLYSELF
1300. static void
1301. urustm(mon, obj)
1302. register struct monst *mon;
1303. register struct obj *obj;
1304. {
1305. 	boolean vis = cansee(mon->mx, mon->my);
1306. 
1307. 	if (!mon || !obj) return; /* just in case */
1308. 	if (u.umonnum == PM_RUST_MONSTER &&
1309. 				objects[obj->otyp].oc_material == METAL &&
1310. 				obj->spe > -2) {
1311. 		if(obj->rustfree) {
1312. 		    if (vis)
1313. 			pline("The rust vanishes from %s's weapon!",
1314. 								mon_nam(mon));
1315. 		} else if(obj->blessed && rn2(3)) {
1316. 		    if (vis)
1317. 			pline("Somehow, %s's weapon is not affected!",
1318. 								mon_nam(mon));
1319. 		} else {
1320. 		    if (vis)
1321. 			pline("%s's %s!", Monnam(mon), aobjnam(obj,"corrode"));
1322. 		    obj->spe--;
1323. 		}
1324. 	}
1325. }
1326. #endif
1327. 
1328. #ifdef SEDUCE
1329. void
1330. doseduce(mon)
1331. register struct monst *mon;
1332. {
1333. 	register struct obj *ring;
1334. 	boolean fem = (mon->data == &mons[PM_SUCCUBUS]); /* otherwise incubus */
1335. 
1336. 	if (fem == poly_gender() || poly_gender()==2) return;
1337. 
1338. 	if (mon->mcan || mon->mspec_used) {
1339.   		pline("%s acts as though %s has got a %sheadache.",
1340.   			Blind ? "It" : Monnam(mon), Blind ? "it" :
1341.   			fem ? "she" : "he",
1342. 			mon->mcan ? "severe " : "");
1343. 		return;
1344. 	}
1345. 
1346. 	if (unconscious()) {
1347. 		kludge("%s seems dismayed at your lack of response.",
1348. 			Monnam(mon));
1349. 		return;
1350. 	}
1351. 
1352. 	if (Blind) pline("It caresses you...");
1353. 	else You("feel very attracted to %s.", mon_nam(mon));
1354. 
1355. 	for(ring = invent; ring; ring = ring->nobj) {
1356. 	    if (ring->otyp != RIN_ADORNMENT) continue;
1357. 	    if (fem) {
1358. 		if (rn2(20) < ACURR(A_CHA)) {
1359. 		    pline("\"That %s looks pretty.  May I have it?\" ",
1360. 			xname(ring));
1361. 		    makeknown(RIN_ADORNMENT);
1362. 		    if (yn() == 'n') continue;
1363. 		} else pline("%s decides she'd like your %s, and takes it.",
1364. 			Blind ? "She" : Monnam(mon), xname(ring));
1365. 		if (ring->known) makeknown(RIN_ADORNMENT);
1366. 		if (ring==uleft || ring==uright) Ring_gone(ring);
1367. 		if (ring==uwep) setuwep((struct obj *)0);
1368. 		freeinv(ring);
1369. 		mpickobj(mon,ring);
1370. 	    } else {
1371. 		char buf[BUFSZ];
1372. 
1373. 		if (uleft && uright && uleft->otyp == RIN_ADORNMENT
1374. 				&& uright->otyp==RIN_ADORNMENT)
1375. 			break;
1376. 		if (ring==uleft || ring==uright) continue;
1377. 		if (rn2(20) < ACURR(A_CHA)) {
1378. 		    pline("\"That %s looks pretty.  Would you wear it for me?\" ",
1379. 			xname(ring));
1380. 		    makeknown(RIN_ADORNMENT);
1381. 		    if (yn() == 'n') continue;
1382. 		} else {
1383. 		    pline("%s decides you'd look prettier wearing your %s,",
1384. 			Blind ? "He" : Monnam(mon), xname(ring));
1385. 		    pline("and puts it on your finger.");
1386. 		}
1387. 		makeknown(RIN_ADORNMENT);
1388. 		if (!uright) {
1389. 		    pline("%s puts the %s on your right hand.",
1390. 			Blind ? "He" : Monnam(mon), xname(ring));
1391. 		    setworn(ring, RIGHT_RING);
1392. 		} else if (!uleft) {
1393. 		    pline("%s puts the %s on your left hand.",
1394. 			Blind ? "He" : Monnam(mon), xname(ring));
1395. 		    setworn(ring, LEFT_RING);
1396. 		} else if (uright && uright->otyp != RIN_ADORNMENT) {
1397. 		    Strcpy(buf, xname(uright));
1398. 		    pline("%s replaces your %s with your %s.",
1399. 			Blind ? "He" : Monnam(mon), buf, xname(ring));
1400. 		    Ring_gone(uright);
1401. 		    setworn(ring, RIGHT_RING);
1402. 		} else if (uleft && uleft->otyp != RIN_ADORNMENT) {
1403. 		    Strcpy(buf, xname(uleft));
1404. 		    pline("%s replaces your %s with your %s.",
1405. 			Blind ? "He" : Monnam(mon), buf, xname(ring));
1406. 		    Ring_gone(uleft);
1407. 		    setworn(ring, LEFT_RING);
1408. 		} else impossible("ring replacement");
1409. 		Ring_on(ring);
1410. 	    	prinv(ring);
1411. 	    }
1412. 	}
1413. 
1414. 	pline("%s murmurs in your ear, while helping you undress.",
1415. 		Blind ? (fem ? "She" : "He") : Monnam(mon));
1416. 	mayberem(uarmc, "cloak");
1417. 	if(!uarmc)
1418. 		mayberem(uarm, "suit");
1419. 	mayberem(uarmf, "boots");
1420. 	mayberem(uarmg, "gloves");
1421. 	mayberem(uarms, "shield");
1422. #ifdef SHIRT
1423. 	if(!uarmc && !uarm)
1424. 		mayberem(uarmu, "shirt");
1425. #endif
1426. 
1427. 	if (uarm || uarmc) {
1428. 		pline("\"You're such a %s; I wish...\"",
1429. 				flags.female ? "sweet lady" : "nice guy");
1430. 		rloc(mon);
1431. 		return;
1432. 	}
1433. #define ALIGNLIM 	(5L + (moves/200L)) /* from pray.c */
1434. 	if (u.ualigntyp == U_CHAOTIC && u.ualign < ALIGNLIM) u.ualign++;
1435. 
1436. 	/* by this point you have discovered mon's identity, blind or not... */
1437. 	pline("Time stands still while you and %s lie in each other's arms...",
1438. 		mon_nam(mon));
1439. 	if (rn2(35) > ACURR(A_CHA) + ACURR(A_INT)) {
1440. 		/* Don't bother with mspec_used here... it didn't get tired! */
1441. 		pline("%s seems to have enjoyed it more than you...",
1442. 			Monnam(mon));
1443. #ifdef SPELLS
1444. 		switch (rn2(5)) {
1445. 			case 0: You("feel drained of energy.");
1446. 				u.uen = 0;
1447. 				u.uenmax -= rnd(10);
1448. 				if (u.uenmax < 0) u.uenmax = 0;
1449. 				break;
1450. #else
1451. 		switch (rnd(4)) {
1452. #endif
1453. 			case 1: You("are down in the dumps.");
1454. 				adjattrib(A_CON, -1, TRUE);
1455. 				flags.botl = 1;
1456. 				break;
1457. 			case 2: Your("senses are dulled.");
1458. 				adjattrib(A_WIS, -1, TRUE);
1459. 				flags.botl = 1;
1460. 				break;
1461. 			case 3:
1462. #ifdef POLYSELF
1463. 				if (resists_drli(uasmon))
1464. 				    You("have a curious feeling...");
1465. 				else {
1466. #endif
1467. 				    You("feel out of shape.");
1468. 				    losexp();
1469. #ifdef POLYSELF
1470. 				}
1471. #endif
1472. 				break;
1473. 			case 4: You("feel exhausted.");
1474. 				losehp(5+rnd(10), "bout of exhaustion");
1475. 				break;
1476. 		}
1477. 	} else {
1478. 		mon->mspec_used = rnd(100); /* monster is worn out */
1479. 		You("seem to have enjoyed it more than %s...", mon_nam(mon));
1480. #ifdef SPELLS
1481. 		switch (rn2(5)) {
1482. 			case 0: You("feel raised to your full potential.");
1483. 				u.uen = (u.uenmax += rnd(5));
1484. 				break;
1485. #else
1486. 		switch (rnd(4)) {
1487. #endif
1488. 			case 1: You("feel good enough to do it again.");
1489. 				adjattrib(A_CON, 1, TRUE);
1490. 				flags.botl = 1;
1491. 				break;
1492. 			case 2: You("will always remember %s...", mon_nam(mon));
1493. 				adjattrib(A_WIS, 1, TRUE);
1494. 				flags.botl = 1;
1495. 				break;
1496. 			case 3: pline("That was a very educational experience.");
1497. 				pluslvl();
1498. 				break;
1499. 			case 4: You("feel restored to health!");
1500. 				u.uhp = u.uhpmax;
1501. #ifdef POLYSELF
1502. 				if (u.mtimedone) u.mh = u.mhmax;
1503. #endif
1504. 				flags.botl = 1;
1505. 				break;
1506. 		}
1507. 	}
1508. 
1509. 	if (mon->mtame) /* don't charge */ ;
1510. 	else if (rn2(20) < ACURR(A_CHA)) {
1511. 		pline("%s demands that you pay %s, but you refuse...",
1512. 			Monnam(mon), (fem ? "her" : "him"));
1513. 	}
1514. #ifdef POLYSELF
1515. 	else if (u.umonnum == PM_LEPRECHAUN)
1516. 		pline("%s tries to take your money, but fails...",
1517. 				Monnam(mon));
1518. #endif
1519. 	else {
1520. 		long cost = (long)rnd(
1521. 			(int)(u.ugold > 32767L ? 32767 : u.ugold) +10) + 500;
1522. 
1523. 		if (mon->mpeaceful) {
1524. 			cost /= 5;
1525. 			if (!cost) cost=1;
1526. 		}
1527. 		if (cost > u.ugold) cost = u.ugold;
1528. 		if (!cost) pline("%s says: \"It's on the house!\"", Monnam(mon));
1529. 		else {
1530. 		    pline("%s takes %ld Zorkmid%s for services rendered!",
1531. 			    Monnam(mon), cost, (cost==1) ? "" : "s");
1532. 		    u.ugold -= cost;
1533. 		    mon->mgold += cost;
1534. 		    flags.botl = 1;
1535. 		}
1536. 	}
1537. 	if (!rn2(25)) mon->mcan = 1; /* monster is worn out */
1538. 	rloc(mon);
1539. }
1540. 
1541. static void
1542. mayberem(obj, str)
1543. register struct obj *obj;
1544. char *str;
1545. {
1546. 	if (!obj || !obj->owornmask) return;
1547. 
1548. 	if (rn2(20) < ACURR(A_CHA)) {
1549. 		pline("\"Shall I remove your %s, %s?\" ",
1550. 			str,
1551. 			(!rn2(2) ? "lover" : !rn2(2) ? "dear" : "sweetheart"));
1552. 		if (yn() == 'n') return;
1553. 	} else pline("\"Take off your %s; %s.\"", str,
1554. 			(obj == uarm)  ? "let's get a little closer" :
1555. 			(obj == uarmc) ? "it's in the way" :
1556. 			(obj == uarmf) ? "let me rub your feet" :
1557. 			(obj == uarmg) ? "they're too clumsy" :
1558. #ifdef SHIRT
1559. 			(obj == uarmu) ? "let me massage you" :
1560. #endif
1561. 			/* obj == uarmh */
1562. 			"so I can run my fingers through your hair");
1563. 
1564. 	if (obj == uarm)  (void) Armor_off();
1565. 	else if (obj == uarmc) (void) Cloak_off();
1566. 	else if (obj == uarmf) (void) Boots_off();
1567. 	else if (obj == uarmg) (void) Gloves_off();
1568. 	else if (obj == uarmh) (void) Helmet_off();
1569. 	else setworn((struct obj *)0, obj->owornmask & W_ARMOR);
1570. }
1571. #endif  /* SEDUCE */
1572. 
1573. #ifdef POLYSELF
1574. static int
1575. passiveum(olduasmon,mtmp)
1576. struct permonst *olduasmon;
1577. register struct monst *mtmp;
1578. {
1579. 	register struct permonst *mdat = mtmp->data;
1580. 	int dam = 0;
1581. 
1582. 	if (olduasmon->mattk[0].aatyp != AT_NONE) return 1;
1583. 
1584. 	/* These affect the enemy even if you were "killed" (rehumanized) */
1585. 	switch(olduasmon->mattk[0].adtyp) {
1586. 	    case AD_ACID:
1587. 		if (!rn2(2)) {
1588. 		    kludge("%s is splashed by your acid!", Monnam(mtmp));
1589. 		    if(!resists_acid(mdat))
1590. 			dam = d((int)olduasmon->mlevel+1,
1591. 					(int)olduasmon->mattk[0].damd);
1592. 		    else pline("%s is not affected.", Monnam(mtmp));
1593. 		}
1594. 		break;
1595. 	    default:
1596. 		break;
1597. 	}
1598. 	if (!u.mtimedone) return 1;
1599. 
1600. 	/* These affect the enemy only if you are still a monster */
1601. 	if (rn2(3)) switch(uasmon->mattk[0].adtyp) {
1602. 	    case AD_PLYS: /* Floating eye */
1603. 		if (!mtmp->mblinded && rn2(3)) {
1604. 		    if (Blind)
1605. 			pline("As a blind %s, you cannot defend yourself.",
1606. 							uasmon->mname);
1607. 		    else {
1608. 			pline("%s is frozen by your gaze!", Monnam(mtmp));
1609. 			mtmp->mfroz = 1;
1610. 		    }
1611. 		}
1612. 		break;
1613. 	    case AD_COLD: /* Brown mold or blue jelly */
1614. 		dam = d((int)uasmon->mlevel+1, (int)uasmon->mattk[0].damd);
1615. 		if(resists_cold(mdat)) {
1616.   		    shieldeff(mtmp->mx, mtmp->my);
1617. 		    kludge("%s is mildly chilly.", Monnam(mtmp));
1618. #ifdef GOLEMS
1619. 		    golemeffects(mtmp, AD_COLD, dam);
1620. #endif /* GOLEMS */
1621. 		    dam = 0;
1622. 		    break;
1623. 		}
1624. 		kludge("%s is suddenly very cold!", Monnam(mtmp));
1625. 		u.mh += dam / 2;
1626. 		if (u.mhmax < u.mh) u.mhmax = u.mh;
1627. 		if (u.mhmax > ((uasmon->mlevel+1) * 8)) {
1628. 			register struct monst *mon;
1629. 
1630. 			if (mon = cloneu()) {
1631. 			    mon->mhpmax = u.mhmax /= 2;
1632. 			    if (Blind)
1633. 				You("multiply from its heat!");
1634. 			    else
1635. 				You("multiply from %s's heat!", mon_nam(mtmp));
1636. 			}
1637. 		}
1638. 		break;
1639. 	    case AD_STUN: /* Yellow mold */
1640. 		if (!mtmp->mstun) {
1641. 		    mtmp->mstun = 1;
1642. 		    kludge("%s staggers...", Monnam(mtmp));
1643. 		}
1644. 		break;
1645. 	    case AD_FIRE: /* Red mold */
1646. 		dam = d((int)uasmon->mlevel+1, (int)uasmon->mattk[0].damd);
1647. 		if(resists_fire(mdat)) {
1648.   		    shieldeff(mtmp->mx, mtmp->my);
1649. 		    kludge("%s is mildly warm.", Monnam(mtmp));
1650. #ifdef GOLEMS
1651. 		    golemeffects(mtmp, AD_FIRE, dam);
1652. #endif /* GOLEMS */
1653. 		    dam = 0;
1654. 		    break;
1655. 		}
1656. 		kludge("%s is suddenly very hot!", Monnam(mtmp));
1657. 	}
1658. 
1659. 	if((mtmp->mhp -= dam) <= 0) {
1660. 		kludge("%s dies!", Monnam(mtmp));
1661. 		xkilled(mtmp,0);
1662. 		return(2);
1663. 	}
1664. 	return 1;
1665. }
1666. 
1667. #include "edog.h"
1668. struct monst *
1669. cloneu()
1670. {
1671. 	register struct monst *mon;
1672. 	register int nmlth = strlen(plname) + 1;
1673. 
1674. 	if (u.mh <= 1) return(struct monst *)0;
1675. 	uasmon->pxlth += sizeof(struct edog) + nmlth;
1676. 	mon = makemon(uasmon, u.ux, u.uy);
1677. 	uasmon->pxlth -= sizeof(struct edog) + nmlth;
1678. 	mon->mxlth = sizeof(struct edog);
1679. 	Strcpy(NAME(mon), plname);
1680. 	mon->mnamelth = nmlth;
1681. 	initedog(mon);
1682. 	mon->m_lev = uasmon->mlevel;
1683. 	mon->mhp = u.mh /= 2;
1684. 	mon->mhpmax = u.mhmax;
1685. 	return(mon);
1686. }
1687. #endif /* POLYSELF */