1/*	SCCS Id: @(#)mhitu.c	3.4	2003/11/26	*/
2/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3/* NetHack may be freely redistributed.  See license for details. */
4
5#include "hack.h"
6#include "artifact.h"
7
8STATIC_VAR NEARDATA struct obj *otmp;
9
10STATIC_DCL void FDECL(urustm, (struct monst *, struct obj *));
11# ifdef OVL1
12STATIC_DCL boolean FDECL(u_slip_free, (struct monst *,struct attack *));
13STATIC_DCL int FDECL(passiveum, (struct permonst *,struct monst *,struct attack *));
14# endif /* OVL1 */
15
16#ifdef OVLB
17# ifdef SEDUCE
18STATIC_DCL void FDECL(mayberem, (struct obj *, const char *));
19# endif
20#endif /* OVLB */
21
22STATIC_DCL boolean FDECL(diseasemu, (struct permonst *));
23STATIC_DCL int FDECL(hitmu, (struct monst *,struct attack *));
24STATIC_DCL int FDECL(gulpmu, (struct monst *,struct attack *));
25STATIC_DCL int FDECL(explmu, (struct monst *,struct attack *,BOOLEAN_P));
26STATIC_DCL void FDECL(missmu,(struct monst *,BOOLEAN_P,struct attack *));
27STATIC_DCL void FDECL(mswings,(struct monst *,struct obj *));
28STATIC_DCL void FDECL(wildmiss, (struct monst *,struct attack *));
29
30STATIC_DCL void FDECL(hurtarmor,(int));
31STATIC_DCL void FDECL(hitmsg,(struct monst *,struct attack *));
32
33/* See comment in mhitm.c.  If we use this a lot it probably should be */
34/* changed to a parameter to mhitu. */
35static int dieroll;
36
37#ifdef OVL1
38
39
40STATIC_OVL void
41hitmsg(mtmp, mattk)
42register struct monst *mtmp;
43register struct attack *mattk;
44{
45	int compat;
46
47	/* Note: if opposite gender, "seductively" */
48	/* If same gender, "engagingly" for nymph, normal msg for others */
49	if((compat = could_seduce(mtmp, &youmonst, mattk))
50			&& !mtmp->mcan && !mtmp->mspec_used) {
51		pline("%s %s you %s.", Monnam(mtmp),
52			Blind ? "talks to" : "smiles at",
53			compat == 2 ? "engagingly" : "seductively");
54	} else
55	    switch (mattk->aatyp) {
56		case AT_BITE:
57			pline("%s bites!", Monnam(mtmp));
58			break;
59		case AT_KICK:
60			pline("%s kicks%c", Monnam(mtmp),
61				    thick_skinned(youmonst.data) ? '.' : '!');
62			break;
63		case AT_STNG:
64			pline("%s stings!", Monnam(mtmp));
65			break;
66		case AT_BUTT:
67			pline("%s butts!", Monnam(mtmp));
68			break;
69		case AT_TUCH:
70			pline("%s touches you!", Monnam(mtmp));
71			break;
72		case AT_TENT:
73			pline("%s tentacles suck you!",
74				        s_suffix(Monnam(mtmp)));
75			break;
76		case AT_EXPL:
77		case AT_BOOM:
78			pline("%s explodes!", Monnam(mtmp));
79			break;
80		default:
81			pline("%s hits!", Monnam(mtmp));
82	    }
83}
84
85STATIC_OVL void
86missmu(mtmp, nearmiss, mattk)		/* monster missed you */
87register struct monst *mtmp;
88register boolean nearmiss;
89register struct attack *mattk;
90{
91	if (!canspotmon(mtmp))
92	    map_invisible(mtmp->mx, mtmp->my);
93
94	if(could_seduce(mtmp, &youmonst, mattk) && !mtmp->mcan)
95	    pline("%s pretends to be friendly.", Monnam(mtmp));
96	else {
97	    if (!flags.verbose || !nearmiss)
98		pline("%s misses.", Monnam(mtmp));
99	    else
100		pline("%s just misses!", Monnam(mtmp));
101	}
102	stop_occupation();
103}
104
105STATIC_OVL void
106mswings(mtmp, otemp)		/* monster swings obj */
107register struct monst *mtmp;
108register struct obj *otemp;
109{
110	if (!flags.verbose || Blind || !mon_visible(mtmp))
111		return;
112	pline("%s %s %s %s.", Monnam(mtmp),
113	      (objects[otemp->otyp].oc_dir & PIERCE) ? "thrusts" : "swings",
114	      mhis(mtmp), singular(otemp, xname));
115}
116
117/* return how a poison attack was delivered */
118const char *
119mpoisons_subj(mtmp, mattk)
120struct monst *mtmp;
121struct attack *mattk;
122{
123	if (mattk->aatyp == AT_WEAP) {
124	    struct obj *mwep = (mtmp == &youmonst) ? uwep : MON_WEP(mtmp);
125	    /* "Foo's attack was poisoned." is pretty lame, but at least
126	       it's better than "sting" when not a stinging attack... */
127	    return (!mwep || !mwep->opoisoned) ? "attack" : "weapon";
128	} else {
129	    return (mattk->aatyp == AT_TUCH) ? "contact" :
130		   (mattk->aatyp == AT_GAZE) ? "gaze" :
131		   (mattk->aatyp == AT_BITE) ? "bite" : "sting";
132	}
133}
134
135/* called when your intrinsic speed is taken away */
136void
137u_slow_down()
138{
139	HFast = 0L;
140	if (!Fast)
141	    You("slow down.");
142	else	/* speed boots */
143	    Your("quickness feels less natural.");
144	exercise(A_DEX, FALSE);
145}
146
147#endif /* OVL1 */
148#ifdef OVLB
149
150STATIC_OVL void
151wildmiss(mtmp, mattk)		/* monster attacked your displaced image */
152	register struct monst *mtmp;
153	register struct attack *mattk;
154{
155	int compat;
156
157	/* no map_invisible() -- no way to tell where _this_ is coming from */
158
159	if (!flags.verbose) return;
160	if (!cansee(mtmp->mx, mtmp->my)) return;
161		/* maybe it's attacking an image around the corner? */
162
163	compat = (mattk->adtyp == AD_SEDU || mattk->adtyp == AD_SSEX) &&
164		 could_seduce(mtmp, &youmonst, (struct attack *)0);
165
166	if (!mtmp->mcansee || (Invis && !perceives(mtmp->data))) {
167	    const char *swings =
168		mattk->aatyp == AT_BITE ? "snaps" :
169		mattk->aatyp == AT_KICK ? "kicks" :
170		(mattk->aatyp == AT_STNG ||
171		 mattk->aatyp == AT_BUTT ||
172		 nolimbs(mtmp->data)) ? "lunges" : "swings";
173
174	    if (compat)
175		pline("%s tries to touch you and misses!", Monnam(mtmp));
176	    else
177		switch(rn2(3)) {
178		case 0: pline("%s %s wildly and misses!", Monnam(mtmp),
179			      swings);
180		    break;
181		case 1: pline("%s attacks a spot beside you.", Monnam(mtmp));
182		    break;
183		case 2: pline("%s strikes at %s!", Monnam(mtmp),
184				levl[mtmp->mux][mtmp->muy].typ == WATER
185				    ? "empty water" : "thin air");
186		    break;
187		default:pline("%s %s wildly!", Monnam(mtmp), swings);
188		    break;
189		}
190
191	} else if (Displaced) {
192	    if (compat)
193		pline("%s smiles %s at your %sdisplaced image...",
194			Monnam(mtmp),
195			compat == 2 ? "engagingly" : "seductively",
196			Invis ? "invisible " : "");
197	    else
198		pline("%s strikes at your %sdisplaced image and misses you!",
199			/* Note: if you're both invisible and displaced,
200			 * only monsters which see invisible will attack your
201			 * displaced image, since the displaced image is also
202			 * invisible.
203			 */
204			Monnam(mtmp),
205			Invis ? "invisible " : "");
206
207	} else if (Underwater) {
208	    /* monsters may miss especially on water level where
209	       bubbles shake the player here and there */
210	    if (compat)
211		pline("%s reaches towards your distorted image.",Monnam(mtmp));
212	    else
213		pline("%s is fooled by water reflections and misses!",Monnam(mtmp));
214
215	} else impossible("%s attacks you without knowing your location?",
216		Monnam(mtmp));
217}
218
219void
220expels(mtmp, mdat, message)
221register struct monst *mtmp;
222register struct permonst *mdat; /* if mtmp is polymorphed, mdat != mtmp->data */
223boolean message;
224{
225	if (message) {
226		if (is_animal(mdat))
227			You("get regurgitated!");
228		else {
229			char blast[40];
230			register int i;
231
232			blast[0] = '\0';
233			for(i = 0; i < NATTK; i++)
234				if(mdat->mattk[i].aatyp == AT_ENGL)
235					break;
236			if (mdat->mattk[i].aatyp != AT_ENGL)
237			      impossible("Swallower has no engulfing attack?");
238			else {
239				if (is_whirly(mdat)) {
240					switch (mdat->mattk[i].adtyp) {
241						case AD_ELEC:
242							Strcpy(blast,
243						      " in a shower of sparks");
244							break;
245						case AD_COLD:
246							Strcpy(blast,
247							" in a blast of frost");
248							break;
249					}
250				} else
251					Strcpy(blast, " with a squelch");
252				You("get expelled from %s%s!",
253				    mon_nam(mtmp), blast);
254			}
255		}
256	}
257	unstuck(mtmp);	/* ball&chain returned in unstuck() */
258	mnexto(mtmp);
259	newsym(u.ux,u.uy);
260	spoteffects(TRUE);
261	/* to cover for a case where mtmp is not in a next square */
262	if(um_dist(mtmp->mx,mtmp->my,1))
263		pline("Brrooaa...  You land hard at some distance.");
264}
265
266#endif /* OVLB */
267#ifdef OVL0
268
269/* select a monster's next attack, possibly substituting for its usual one */
270struct attack *
271getmattk(mptr, indx, prev_result, alt_attk_buf)
272struct permonst *mptr;
273int indx, prev_result[];
274struct attack *alt_attk_buf;
275{
276    struct attack *attk = &mptr->mattk[indx];
277
278    /* prevent a monster with two consecutive disease or hunger attacks
279       from hitting with both of them on the same turn; if the first has
280       already hit, switch to a stun attack for the second */
281    if (indx > 0 && prev_result[indx - 1] > 0 &&
282	    (attk->adtyp == AD_DISE ||
283		attk->adtyp == AD_PEST ||
284		attk->adtyp == AD_FAMN) &&
285	    attk->adtyp == mptr->mattk[indx - 1].adtyp) {
286	*alt_attk_buf = *attk;
287	attk = alt_attk_buf;
288	attk->adtyp = AD_STUN;
289    }
290    return attk;
291}
292
293/*
294 * mattacku: monster attacks you
295 *	returns 1 if monster dies (e.g. "yellow light"), 0 otherwise
296 *	Note: if you're displaced or invisible the monster might attack the
297 *		wrong position...
298 *	Assumption: it's attacking you or an empty square; if there's another
299 *		monster which it attacks by mistake, the caller had better
300 *		take care of it...
301 */
302int
303mattacku(mtmp)
304	register struct monst *mtmp;
305{
306	struct	attack	*mattk, alt_attk;
307	int	i, j, tmp, sum[NATTK];
308	struct	permonst *mdat = mtmp->data;
309	boolean ranged = (distu(mtmp->mx, mtmp->my) > 3);
310		/* Is it near you?  Affects your actions */
311	boolean range2 = !monnear(mtmp, mtmp->mux, mtmp->muy);
312		/* Does it think it's near you?  Affects its actions */
313	boolean foundyou = (mtmp->mux==u.ux && mtmp->muy==u.uy);
314		/* Is it attacking you or your image? */
315	boolean youseeit = canseemon(mtmp);
316		/* Might be attacking your image around the corner, or
317		 * invisible, or you might be blind....
318		 */
319
320	if(!ranged) nomul(0);
321	if(mtmp->mhp <= 0 || (Underwater && !is_swimmer(mtmp->data)))
322	    return(0);
323
324	/* If swallowed, can only be affected by u.ustuck */
325	if(u.uswallow) {
326	    if(mtmp != u.ustuck)
327		return(0);
328	    u.ustuck->mux = u.ux;
329	    u.ustuck->muy = u.uy;
330	    range2 = 0;
331	    foundyou = 1;
332	    if(u.uinvulnerable) return (0); /* stomachs can't hurt you! */
333	}
334
335#ifdef STEED
336	else if (u.usteed) {
337		if (mtmp == u.usteed)
338			/* Your steed won't attack you */
339			return (0);
340		/* Orcs like to steal and eat horses and the like */
341		if (!rn2(is_orc(mtmp->data) ? 2 : 4) &&
342				distu(mtmp->mx, mtmp->my) <= 2) {
343			/* Attack your steed instead */
344			i = mattackm(mtmp, u.usteed);
345			if ((i & MM_AGR_DIED))
346				return (1);
347			if (i & MM_DEF_DIED || u.umoved)
348				return (0);
349			/* Let your steed retaliate */
350			return (!!(mattackm(u.usteed, mtmp) & MM_DEF_DIED));
351		}
352	}
353#endif
354
355	if (u.uundetected && !range2 && foundyou && !u.uswallow) {
356		u.uundetected = 0;
357		if (is_hider(youmonst.data)) {
358		    coord cc; /* maybe we need a unexto() function? */
359		    struct obj *obj;
360
361		    You("fall from the %s!", ceiling(u.ux,u.uy));
362		    if (enexto(&cc, u.ux, u.uy, youmonst.data)) {
363			remove_monster(mtmp->mx, mtmp->my);
364			newsym(mtmp->mx,mtmp->my);
365			place_monster(mtmp, u.ux, u.uy);
366			if(mtmp->wormno) worm_move(mtmp);
367			teleds(cc.x, cc.y, TRUE);
368			set_apparxy(mtmp);
369			newsym(u.ux,u.uy);
370		    } else {
371			pline("%s is killed by a falling %s (you)!",
372					Monnam(mtmp), youmonst.data->mname);
373			killed(mtmp);
374			newsym(u.ux,u.uy);
375			if (mtmp->mhp > 0) return 0;
376			else return 1;
377		    }
378		    if (youmonst.data->mlet != S_PIERCER)
379			return(0);	/* trappers don't attack */
380
381		    obj = which_armor(mtmp, WORN_HELMET);
382		    if (obj && is_metallic(obj)) {
383			Your("blow glances off %s helmet.",
384			               s_suffix(mon_nam(mtmp)));
385		    } else {
386			if (3 + find_mac(mtmp) <= rnd(20)) {
387			    pline("%s is hit by a falling piercer (you)!",
388								Monnam(mtmp));
389			    if ((mtmp->mhp -= d(3,6)) < 1)
390				killed(mtmp);
391			} else
392			  pline("%s is almost hit by a falling piercer (you)!",
393								Monnam(mtmp));
394		    }
395		} else {
396		    if (!youseeit)
397			pline("It tries to move where you are hiding.");
398		    else {
399			/* Ugly kludge for eggs.  The message is phrased so as
400			 * to be directed at the monster, not the player,
401			 * which makes "laid by you" wrong.  For the
402			 * parallelism to work, we can't rephrase it, so we
403			 * zap the "laid by you" momentarily instead.
404			 */
405			struct obj *obj = level.objects[u.ux][u.uy];
406
407			if (obj ||
408			      (youmonst.data->mlet == S_EEL && is_pool(u.ux, u.uy))) {
409			    int save_spe = 0; /* suppress warning */
410			    if (obj) {
411				save_spe = obj->spe;
412				if (obj->otyp == EGG) obj->spe = 0;
413			    }
414			    if (youmonst.data->mlet == S_EEL)
415		pline("Wait, %s!  There's a hidden %s named %s there!",
416				m_monnam(mtmp), youmonst.data->mname, plname);
417			    else
418	     pline("Wait, %s!  There's a %s named %s hiding under %s!",
419				m_monnam(mtmp), youmonst.data->mname, plname,
420				doname(level.objects[u.ux][u.uy]));
421			    if (obj) obj->spe = save_spe;
422			} else
423			    impossible("hiding under nothing?");
424		    }
425		    newsym(u.ux,u.uy);
426		}
427		return(0);
428	}
429	if (youmonst.data->mlet == S_MIMIC && youmonst.m_ap_type &&
430		    !range2 && foundyou && !u.uswallow) {
431		if (!youseeit) pline("It gets stuck on you.");
432		else pline("Wait, %s!  That's a %s named %s!",
433			   m_monnam(mtmp), youmonst.data->mname, plname);
434		u.ustuck = mtmp;
435		youmonst.m_ap_type = M_AP_NOTHING;
436		youmonst.mappearance = 0;
437		newsym(u.ux,u.uy);
438		return(0);
439	}
440
441	/* player might be mimicking an object */
442	if (youmonst.m_ap_type == M_AP_OBJECT && !range2 && foundyou && !u.uswallow) {
443	    if (!youseeit)
444		 pline("%s %s!", Something,
445			(likes_gold(mtmp->data) && youmonst.mappearance == GOLD_PIECE) ?
446			"tries to pick you up" : "disturbs you");
447	    else pline("Wait, %s!  That %s is really %s named %s!",
448			m_monnam(mtmp),
449			mimic_obj_name(&youmonst),
450			an(mons[u.umonnum].mname),
451			plname);
452	    if (multi < 0) {	/* this should always be the case */
453		char buf[BUFSZ];
454		Sprintf(buf, "You appear to be %s again.",
455			Upolyd ? (const char *) an(youmonst.data->mname) :
456			    (const char *) "yourself");
457		unmul(buf);	/* immediately stop mimicking */
458	    }
459	    return 0;
460	}
461
462/*	Work out the armor class differential	*/
463	tmp = AC_VALUE(u.uac) + 10;		/* tmp ~= 0 - 20 */
464	tmp += mtmp->m_lev;
465	if(multi < 0) tmp += 4;
466	if((Invis && !perceives(mdat)) || !mtmp->mcansee)
467		tmp -= 2;
468	if(mtmp->mtrapped) tmp -= 2;
469	if(tmp <= 0) tmp = 1;
470
471	/* make eels visible the moment they hit/miss us */
472	if(mdat->mlet == S_EEL && mtmp->minvis && cansee(mtmp->mx,mtmp->my)) {
473		mtmp->minvis = 0;
474		newsym(mtmp->mx,mtmp->my);
475	}
476
477/*	Special demon handling code */
478	if(!mtmp->cham && is_demon(mdat) && !range2
479	   && mtmp->data != &mons[PM_BALROG]
480	   && mtmp->data != &mons[PM_SUCCUBUS]
481	   && mtmp->data != &mons[PM_INCUBUS])
482	    if(!mtmp->mcan && !rn2(13))	msummon(mtmp);
483
484/*	Special lycanthrope handling code */
485	if(!mtmp->cham && is_were(mdat) && !range2) {
486
487	    if(is_human(mdat)) {
488		if(!rn2(5 - (night() * 2)) && !mtmp->mcan) new_were(mtmp);
489	    } else if(!rn2(30) && !mtmp->mcan) new_were(mtmp);
490	    mdat = mtmp->data;
491
492	    if(!rn2(10) && !mtmp->mcan) {
493	    	int numseen, numhelp;
494		char buf[BUFSZ], genericwere[BUFSZ];
495
496		Strcpy(genericwere, "creature");
497		numhelp = were_summon(mdat, FALSE, &numseen, genericwere);
498		if (youseeit) {
499			pline("%s summons help!", Monnam(mtmp));
500			if (numhelp > 0) {
501			    if (numseen == 0)
502				You_feel("hemmed in.");
503			} else pline("But none comes.");
504		} else {
505			const char *from_nowhere;
506
507			if (flags.soundok) {
508				pline("%s %s!", Something,
509					makeplural(growl_sound(mtmp)));
510				from_nowhere = "";
511			} else from_nowhere = " from nowhere";
512			if (numhelp > 0) {
513			    if (numseen < 1) You_feel("hemmed in.");
514			    else {
515				if (numseen == 1)
516			    		Sprintf(buf, "%s appears",
517							an(genericwere));
518			    	else
519			    		Sprintf(buf, "%s appear",
520							makeplural(genericwere));
521				pline("%s%s!", upstart(buf), from_nowhere);
522			    }
523			} /* else no help came; but you didn't know it tried */
524		}
525	    }
526	}
527
528	if(u.uinvulnerable) {
529	    /* monsters won't attack you */
530	    if(mtmp == u.ustuck)
531		pline("%s loosens its grip slightly.", Monnam(mtmp));
532	    else if(!range2) {
533		if (youseeit || sensemon(mtmp))
534		    pline("%s starts to attack you, but pulls back.",
535			  Monnam(mtmp));
536		else
537		    You_feel("%s move nearby.", something);
538	    }
539	    return (0);
540	}
541
542	/* Unlike defensive stuff, don't let them use item _and_ attack. */
543	if(find_offensive(mtmp)) {
544		int foo = use_offensive(mtmp);
545
546		if (foo != 0) return(foo==1);
547	}
548
549	for(i = 0; i < NATTK; i++) {
550
551	    sum[i] = 0;
552	    mattk = getmattk(mdat, i, sum, &alt_attk);
553	    if (u.uswallow && (mattk->aatyp != AT_ENGL))
554		continue;
555	    switch(mattk->aatyp) {
556		case AT_CLAW:	/* "hand to hand" attacks */
557		case AT_KICK:
558		case AT_BITE:
559		case AT_STNG:
560		case AT_TUCH:
561		case AT_BUTT:
562		case AT_TENT:
563			if(!range2 && (!MON_WEP(mtmp) || mtmp->mconf || Conflict ||
564					!touch_petrifies(youmonst.data))) {
565			    if (foundyou) {
566				if(tmp > (j = rnd(20+i))) {
567				    if (mattk->aatyp != AT_KICK ||
568					    !thick_skinned(youmonst.data))
569					sum[i] = hitmu(mtmp, mattk);
570				} else
571				    missmu(mtmp, (tmp == j), mattk);
572			    } else
573				wildmiss(mtmp, mattk);
574			}
575			break;
576
577		case AT_HUGS:	/* automatic if prev two attacks succeed */
578			/* Note: if displaced, prev attacks never succeeded */
579			if((!range2 && i>=2 && sum[i-1] && sum[i-2])
580							|| mtmp == u.ustuck)
581				sum[i]= hitmu(mtmp, mattk);
582			break;
583
584		case AT_GAZE:	/* can affect you either ranged or not */
585			/* Medusa gaze already operated through m_respond in
586			 * dochug(); don't gaze more than once per round.
587			 */
588			if (mdat != &mons[PM_MEDUSA])
589				sum[i] = gazemu(mtmp, mattk);
590			break;
591
592		case AT_EXPL:	/* automatic hit if next to, and aimed at you */
593			if(!range2) sum[i] = explmu(mtmp, mattk, foundyou);
594			break;
595
596		case AT_ENGL:
597			if (!range2) {
598			    if(foundyou) {
599				if(u.uswallow || tmp > (j = rnd(20+i))) {
600				    /* Force swallowing monster to be
601				     * displayed even when player is
602				     * moving away */
603				    flush_screen(1);
604				    sum[i] = gulpmu(mtmp, mattk);
605				} else {
606				    missmu(mtmp, (tmp == j), mattk);
607				}
608			    } else if (is_animal(mtmp->data)) {
609				pline("%s gulps some air!", Monnam(mtmp));
610			    } else {
611				if (youseeit)
612				    pline("%s lunges forward and recoils!",
613					  Monnam(mtmp));
614				else
615				    You_hear("a %s nearby.",
616					     is_whirly(mtmp->data) ?
617						"rushing noise" : "splat");
618			   }
619			}
620			break;
621		case AT_BREA:
622			if(range2) sum[i] = breamu(mtmp, mattk);
623			/* Note: breamu takes care of displacement */
624			break;
625		case AT_SPIT:
626			if(range2) sum[i] = spitmu(mtmp, mattk);
627			/* Note: spitmu takes care of displacement */
628			break;
629		case AT_WEAP:
630			if(range2) {
631#ifdef REINCARNATION
632				if (!Is_rogue_level(&u.uz))
633#endif
634					thrwmu(mtmp);
635			} else {
636			    int hittmp = 0;
637
638			    /* Rare but not impossible.  Normally the monster
639			     * wields when 2 spaces away, but it can be
640			     * teleported or whatever....
641			     */
642			    if (mtmp->weapon_check == NEED_WEAPON ||
643							!MON_WEP(mtmp)) {
644				mtmp->weapon_check = NEED_HTH_WEAPON;
645				/* mon_wield_item resets weapon_check as
646				 * appropriate */
647				if (mon_wield_item(mtmp) != 0) break;
648			    }
649			    if (foundyou) {
650				otmp = MON_WEP(mtmp);
651				if(otmp) {
652				    hittmp = hitval(otmp, &youmonst);
653				    tmp += hittmp;
654				    mswings(mtmp, otmp);
655				}
656				if(tmp > (j = dieroll = rnd(20+i)))
657				    sum[i] = hitmu(mtmp, mattk);
658				else
659				    missmu(mtmp, (tmp == j), mattk);
660				/* KMH -- Don't accumulate to-hit bonuses */
661				if (otmp)
662					tmp -= hittmp;
663			    } else
664				wildmiss(mtmp, mattk);
665			}
666			break;
667		case AT_MAGC:
668			if (range2)
669			    sum[i] = buzzmu(mtmp, mattk);
670			else {
671			    if (foundyou)
672				sum[i] = castmu(mtmp, mattk, TRUE, TRUE);
673			    else
674				sum[i] = castmu(mtmp, mattk, TRUE, FALSE);
675			}
676			break;
677
678		default:		/* no attack */
679			break;
680	    }
681	    if(flags.botl) bot();
682	/* give player a chance of waking up before dying -kaa */
683	    if(sum[i] == 1) {	    /* successful attack */
684		if (u.usleep && u.usleep < monstermoves && !rn2(10)) {
685		    multi = -1;
686		    nomovemsg = "The combat suddenly awakens you.";
687		}
688	    }
689	    if(sum[i] == 2) return 1;		/* attacker dead */
690	    if(sum[i] == 3) break;  /* attacker teleported, no more attacks */
691	    /* sum[i] == 0: unsuccessful attack */
692	}
693	return(0);
694}
695
696#endif /* OVL0 */
697#ifdef OVLB
698
699/*
700 * helper function for some compilers that have trouble with hitmu
701 */
702
703STATIC_OVL void
704hurtarmor(attk)
705int attk;
706{
707	int	hurt;
708
709	switch(attk) {
710	    /* 0 is burning, which we should never be called with */
711	    case AD_RUST: hurt = 1; break;
712	    case AD_CORR: hurt = 3; break;
713	    default: hurt = 2; break;
714	}
715
716	/* What the following code does: it keeps looping until it
717	 * finds a target for the rust monster.
718	 * Head, feet, etc... not covered by metal, or covered by
719	 * rusty metal, are not targets.  However, your body always
720	 * is, no matter what covers it.
721	 */
722	while (1) {
723	    switch(rn2(5)) {
724	    case 0:
725		if (!uarmh || !rust_dmg(uarmh, xname(uarmh), hurt, FALSE, &youmonst))
726			continue;
727		break;
728	    case 1:
729		if (uarmc) {
730		    (void)rust_dmg(uarmc, xname(uarmc), hurt, TRUE, &youmonst);
731		    break;
732		}
733		/* Note the difference between break and continue;
734		 * break means it was hit and didn't rust; continue
735		 * means it wasn't a target and though it didn't rust
736		 * something else did.
737		 */
738		if (uarm)
739		    (void)rust_dmg(uarm, xname(uarm), hurt, TRUE, &youmonst);
740#ifdef TOURIST
741		else if (uarmu)
742		    (void)rust_dmg(uarmu, xname(uarmu), hurt, TRUE, &youmonst);
743#endif
744		break;
745	    case 2:
746		if (!uarms || !rust_dmg(uarms, xname(uarms), hurt, FALSE, &youmonst))
747		    continue;
748		break;
749	    case 3:
750		if (!uarmg || !rust_dmg(uarmg, xname(uarmg), hurt, FALSE, &youmonst))
751		    continue;
752		break;
753	    case 4:
754		if (!uarmf || !rust_dmg(uarmf, xname(uarmf), hurt, FALSE, &youmonst))
755		    continue;
756		break;
757	    }
758	    break; /* Out of while loop */
759	}
760}
761
762#endif /* OVLB */
763#ifdef OVL1
764
765STATIC_OVL boolean
766diseasemu(mdat)
767struct permonst *mdat;
768{
769	if (Sick_resistance) {
770		You_feel("a slight illness.");
771		return FALSE;
772	} else {
773		make_sick(Sick ? Sick/3L + 1L : (long)rn1(ACURR(A_CON), 20),
774			mdat->mname, TRUE, SICK_NONVOMITABLE);
775		return TRUE;
776	}
777}
778
779/* check whether slippery clothing protects from hug or wrap attack */
780STATIC_OVL boolean
781u_slip_free(mtmp, mattk)
782struct monst *mtmp;
783struct attack *mattk;
784{
785	struct obj *obj = (uarmc ? uarmc : uarm);
786
787#ifdef TOURIST
788	if (!obj) obj = uarmu;
789#endif
790	if (mattk->adtyp == AD_DRIN) obj = uarmh;
791
792	/* if your cloak/armor is greased, monster slips off; this
793	   protection might fail (33% chance) when the armor is cursed */
794	if (obj && (obj->greased || obj->otyp == OILSKIN_CLOAK) &&
795		(!obj->cursed || rn2(3))) {
796	    pline("%s %s your %s %s!",
797		  Monnam(mtmp),
798		  (mattk->adtyp == AD_WRAP) ?
799			"slips off of" : "grabs you, but cannot hold onto",
800		  obj->greased ? "greased" : "slippery",
801		  /* avoid "slippery slippery cloak"
802		     for undiscovered oilskin cloak */
803		  (obj->greased || objects[obj->otyp].oc_name_known) ?
804			xname(obj) : cloak_simple_name(obj));
805
806	    if (obj->greased && !rn2(2)) {
807		pline_The("grease wears off.");
808		obj->greased = 0;
809		update_inventory();
810	    }
811	    return TRUE;
812	}
813	return FALSE;
814}
815
816/* armor that sufficiently covers the body might be able to block magic */
817int
818magic_negation(mon)
819struct monst *mon;
820{
821	struct obj *armor;
822	int armpro = 0;
823
824	armor = (mon == &youmonst) ? uarm : which_armor(mon, W_ARM);
825	if (armor && armpro < objects[armor->otyp].a_can)
826	    armpro = objects[armor->otyp].a_can;
827	armor = (mon == &youmonst) ? uarmc : which_armor(mon, W_ARMC);
828	if (armor && armpro < objects[armor->otyp].a_can)
829	    armpro = objects[armor->otyp].a_can;
830	armor = (mon == &youmonst) ? uarmh : which_armor(mon, W_ARMH);
831	if (armor && armpro < objects[armor->otyp].a_can)
832	    armpro = objects[armor->otyp].a_can;
833
834	/* armor types for shirt, gloves, shoes, and shield don't currently
835	   provide any magic cancellation but we might as well be complete */
836#ifdef TOURIST
837	armor = (mon == &youmonst) ? uarmu : which_armor(mon, W_ARMU);
838	if (armor && armpro < objects[armor->otyp].a_can)
839	    armpro = objects[armor->otyp].a_can;
840#endif
841	armor = (mon == &youmonst) ? uarmg : which_armor(mon, W_ARMG);
842	if (armor && armpro < objects[armor->otyp].a_can)
843	    armpro = objects[armor->otyp].a_can;
844	armor = (mon == &youmonst) ? uarmf : which_armor(mon, W_ARMF);
845	if (armor && armpro < objects[armor->otyp].a_can)
846	    armpro = objects[armor->otyp].a_can;
847	armor = (mon == &youmonst) ? uarms : which_armor(mon, W_ARMS);
848	if (armor && armpro < objects[armor->otyp].a_can)
849	    armpro = objects[armor->otyp].a_can;
850
851#ifdef STEED
852	/* this one is really a stretch... */
853	armor = (mon == &youmonst) ? 0 : which_armor(mon, W_SADDLE);
854	if (armor && armpro < objects[armor->otyp].a_can)
855	    armpro = objects[armor->otyp].a_can;
856#endif
857
858	return armpro;
859}
860
861/*
862 * hitmu: monster hits you
863 *	  returns 2 if monster dies (e.g. "yellow light"), 1 otherwise
864 *	  3 if the monster lives but teleported/paralyzed, so it can't keep
865 *	       attacking you
866 */
867STATIC_OVL int
868hitmu(mtmp, mattk)
869	register struct monst *mtmp;
870	register struct attack  *mattk;
871{
872	register struct permonst *mdat = mtmp->data;
873	register int uncancelled, ptmp;
874	int dmg, armpro, permdmg;
875	char	 buf[BUFSZ];
876	struct permonst *olduasmon = youmonst.data;
877	int res;
878
879	if (!canspotmon(mtmp))
880	    map_invisible(mtmp->mx, mtmp->my);
881
882/*	If the monster is undetected & hits you, you should know where
883 *	the attack came from.
884 */
885	if(mtmp->mundetected && (hides_under(mdat) || mdat->mlet == S_EEL)) {
886	    mtmp->mundetected = 0;
887	    if (!(Blind ? Blind_telepat : Unblind_telepat)) {
888		struct obj *obj;
889		const char *what;
890
891		if ((obj = level.objects[mtmp->mx][mtmp->my]) != 0) {
892		    if (Blind && !obj->dknown)
893			what = something;
894		    else if (is_pool(mtmp->mx, mtmp->my) && !Underwater)
895			what = "the water";
896		    else
897			what = doname(obj);
898
899		    pline("%s was hidden under %s!", Amonnam(mtmp), what);
900		}
901		newsym(mtmp->mx, mtmp->my);
902	    }
903	}
904
905/*	First determine the base damage done */
906	dmg = d((int)mattk->damn, (int)mattk->damd);
907	if(is_undead(mdat) && midnight())
908		dmg += d((int)mattk->damn, (int)mattk->damd); /* extra damage */
909
910/*	Next a cancellation factor	*/
911/*	Use uncancelled when the cancellation factor takes into account certain
912 *	armor's special magic protection.  Otherwise just use !mtmp->mcan.
913 */
914	armpro = magic_negation(&youmonst);
915	uncancelled = !mtmp->mcan && ((rn2(3) >= armpro) || !rn2(50));
916
917	permdmg = 0;
918/*	Now, adjust damages via resistances or specific attacks */
919	switch(mattk->adtyp) {
920	    case AD_PHYS:
921		if (mattk->aatyp == AT_HUGS && !sticks(youmonst.data)) {
922		    if(!u.ustuck && rn2(2)) {
923			if (u_slip_free(mtmp, mattk)) {
924			    dmg = 0;
925			} else {
926			    u.ustuck = mtmp;
927			    pline("%s grabs you!", Monnam(mtmp));
928			}
929		    } else if(u.ustuck == mtmp) {
930			exercise(A_STR, FALSE);
931			You("are being %s.",
932			      (mtmp->data == &mons[PM_ROPE_GOLEM])
933			      ? "choked" : "crushed");
934		    }
935		} else {			  /* hand to hand weapon */
936		    if(mattk->aatyp == AT_WEAP && otmp) {
937			if (otmp->otyp == CORPSE
938				&& touch_petrifies(&mons[otmp->corpsenm])) {
939			    dmg = 1;
940			    pline("%s hits you with the %s corpse.",
941				Monnam(mtmp), mons[otmp->corpsenm].mname);
942			    if (!Stoned)
943				goto do_stone;
944			}
945			dmg += dmgval(otmp, &youmonst);
946			if (dmg <= 0) dmg = 1;
947			if (!(otmp->oartifact &&
948				artifact_hit(mtmp, &youmonst, otmp, &dmg,dieroll)))
949			     hitmsg(mtmp, mattk);
950			if (!dmg) break;
951			if (u.mh > 1 && u.mh > ((u.uac>0) ? dmg : dmg+u.uac) &&
952				   objects[otmp->otyp].oc_material == IRON &&
953					(u.umonnum==PM_BLACK_PUDDING
954					|| u.umonnum==PM_BROWN_PUDDING)) {
955			    /* This redundancy necessary because you have to
956			     * take the damage _before_ being cloned.
957			     */
958			    if (u.uac < 0) dmg += u.uac;
959			    if (dmg < 1) dmg = 1;
960			    if (dmg > 1) exercise(A_STR, FALSE);
961			    u.mh -= dmg;
962			    flags.botl = 1;
963			    dmg = 0;
964			    if(cloneu())
965			    You("divide as %s hits you!",mon_nam(mtmp));
966			}
967			urustm(mtmp, otmp);
968		    } else if (mattk->aatyp != AT_TUCH || dmg != 0 ||
969				mtmp != u.ustuck)
970			hitmsg(mtmp, mattk);
971		}
972		break;
973	    case AD_DISE:
974		hitmsg(mtmp, mattk);
975		if (!diseasemu(mdat)) dmg = 0;
976		break;
977	    case AD_FIRE:
978		hitmsg(mtmp, mattk);
979		if (uncancelled) {
980		    pline("You're %s!", on_fire(youmonst.data, mattk));
981		    if (youmonst.data == &mons[PM_STRAW_GOLEM] ||
982		        youmonst.data == &mons[PM_PAPER_GOLEM]) {
983			    You("roast!");
984			    /* KMH -- this is okay with unchanging */
985			    rehumanize();
986			    break;
987		    } else if (Fire_resistance) {
988			pline_The("fire doesn't feel hot!");
989			dmg = 0;
990		    }
991		    if((int) mtmp->m_lev > rn2(20))
992			destroy_item(SCROLL_CLASS, AD_FIRE);
993		    if((int) mtmp->m_lev > rn2(20))
994			destroy_item(POTION_CLASS, AD_FIRE);
995		    if((int) mtmp->m_lev > rn2(25))
996			destroy_item(SPBOOK_CLASS, AD_FIRE);
997		    burn_away_slime();
998		} else dmg = 0;
999		break;
1000	    case AD_COLD:
1001		hitmsg(mtmp, mattk);
1002		if (uncancelled) {
1003		    pline("You're covered in frost!");
1004		    if (Cold_resistance) {
1005			pline_The("frost doesn't seem cold!");
1006			dmg = 0;
1007		    }
1008		    if((int) mtmp->m_lev > rn2(20))
1009			destroy_item(POTION_CLASS, AD_COLD);
1010		} else dmg = 0;
1011		break;
1012	    case AD_ELEC:
1013		hitmsg(mtmp, mattk);
1014		if (uncancelled) {
1015		    You("get zapped!");
1016		    if (Shock_resistance) {
1017			pline_The("zap doesn't shock you!");
1018			dmg = 0;
1019		    }
1020		    if((int) mtmp->m_lev > rn2(20))
1021			destroy_item(WAND_CLASS, AD_ELEC);
1022		    if((int) mtmp->m_lev > rn2(20))
1023			destroy_item(RING_CLASS, AD_ELEC);
1024		} else dmg = 0;
1025		break;
1026	    case AD_SLEE:
1027		hitmsg(mtmp, mattk);
1028		if (uncancelled && multi >= 0 && !rn2(5)) {
1029		    if (Sleep_resistance) break;
1030		    fall_asleep(-rnd(10), TRUE);
1031		    if (Blind) You("are put to sleep!");
1032		    else You("are put to sleep by %s!", mon_nam(mtmp));
1033		}
1034		break;
1035	    case AD_BLND:
1036		if (can_blnd(mtmp, &youmonst, mattk->aatyp, (struct obj*)0)) {
1037		    if (!Blind) pline("%s blinds you!", Monnam(mtmp));
1038		    make_blinded(Blinded+(long)dmg,FALSE);
1039		    if (!Blind) Your(vision_clears);
1040		}
1041		dmg = 0;
1042		break;
1043	    case AD_DRST:
1044		ptmp = A_STR;
1045		goto dopois;
1046	    case AD_DRDX:
1047		ptmp = A_DEX;
1048		goto dopois;
1049	    case AD_DRCO:
1050		ptmp = A_CON;
1051dopois:
1052		hitmsg(mtmp, mattk);
1053		if (uncancelled && !rn2(8)) {
1054		    Sprintf(buf, "%s %s",
1055			    s_suffix(Monnam(mtmp)), mpoisons_subj(mtmp, mattk));
1056		    poisoned(buf, ptmp, mdat->mname, 30);
1057		}
1058		break;
1059	    case AD_DRIN:
1060		hitmsg(mtmp, mattk);
1061		if (defends(AD_DRIN, uwep) || !has_head(youmonst.data)) {
1062		    You("don't seem harmed.");
1063		    /* Not clear what to do for green slimes */
1064		    break;
1065		}
1066		if (u_slip_free(mtmp,mattk)) break;
1067
1068		if (uarmh && rn2(8)) {
1069		    /* not body_part(HEAD) */
1070		    Your("helmet blocks the attack to your head.");
1071		    break;
1072		}
1073		if (Half_physical_damage) dmg = (dmg+1) / 2;
1074		mdamageu(mtmp, dmg);
1075
1076		if (!uarmh || uarmh->otyp != DUNCE_CAP) {
1077		    Your("brain is eaten!");
1078		    /* No such thing as mindless players... */
1079		    if (ABASE(A_INT) <= ATTRMIN(A_INT)) {
1080			int lifesaved = 0;
1081			struct obj *wore_amulet = uamul;
1082
1083			while(1) {
1084			    /* avoid looping on "die(y/n)?" */
1085			    if (lifesaved && (discover || wizard)) {
1086				if (wore_amulet && !uamul) {
1087				    /* used up AMULET_OF_LIFE_SAVING; still
1088				       subject to dying from brainlessness */
1089				    wore_amulet = 0;
1090				} else {
1091				    /* explicitly chose not to die;
1092				       arbitrarily boost intelligence */
1093				    ABASE(A_INT) = ATTRMIN(A_INT) + 2;
1094				    You_feel("like a scarecrow.");
1095				    break;
1096				}
1097			    }
1098
1099			    if (lifesaved)
1100				pline("Unfortunately your brain is still gone.");
1101			    else
1102				Your("last thought fades away.");
1103			    killer = "brainlessness";
1104			    killer_format = KILLED_BY;
1105			    done(DIED);
1106			    lifesaved++;
1107			}
1108		    }
1109		}
1110		/* adjattrib gives dunce cap message when appropriate */
1111		(void) adjattrib(A_INT, -rnd(2), FALSE);
1112		forget_levels(25);	/* lose memory of 25% of levels */
1113		forget_objects(25);	/* lose memory of 25% of objects */
1114		exercise(A_WIS, FALSE);
1115		break;
1116	    case AD_PLYS:
1117		hitmsg(mtmp, mattk);
1118		if (uncancelled && multi >= 0 && !rn2(3)) {
1119		    if (Free_action) {
1120			You("momentarily stiffen.");
1121		    } else {
1122			if (Blind) You("are frozen!");
1123			else You("are frozen by %s!", mon_nam(mtmp));
1124			nomovemsg = 0;	/* default: "you can move again" */
1125			nomul(-rnd(10));
1126			exercise(A_DEX, FALSE);
1127		    }
1128		}
1129		break;
1130	    case AD_DRLI:
1131		hitmsg(mtmp, mattk);
1132		if (uncancelled && !rn2(3) && !Drain_resistance) {
1133		    losexp("life drainage");
1134		}
1135		break;
1136	    case AD_LEGS:
1137		{ register long side = rn2(2) ? RIGHT_SIDE : LEFT_SIDE;
1138		  const char *sidestr = (side == RIGHT_SIDE) ? "right" : "left";
1139
1140		/* This case is too obvious to ignore, but Nethack is not in
1141		 * general very good at considering height--most short monsters
1142		 * still _can_ attack you when you're flying or mounted.
1143		 * [FIXME: why can't a flying attacker overcome this?]
1144		 */
1145		  if (
1146#ifdef STEED
1147			u.usteed ||
1148#endif
1149				    Levitation || Flying) {
1150		    pline("%s tries to reach your %s %s!", Monnam(mtmp),
1151			  sidestr, body_part(LEG));
1152		    dmg = 0;
1153		  } else if (mtmp->mcan) {
1154		    pline("%s nuzzles against your %s %s!", Monnam(mtmp),
1155			  sidestr, body_part(LEG));
1156		    dmg = 0;
1157		  } else {
1158		    if (uarmf) {
1159			if (rn2(2) && (uarmf->otyp == LOW_BOOTS ||
1160					     uarmf->otyp == IRON_SHOES))
1161			    pline("%s pricks the exposed part of your %s %s!",
1162				Monnam(mtmp), sidestr, body_part(LEG));
1163			else if (!rn2(5))
1164			    pline("%s pricks through your %s boot!",
1165				Monnam(mtmp), sidestr);
1166			else {
1167			    pline("%s scratches your %s boot!", Monnam(mtmp),
1168				sidestr);
1169			    dmg = 0;
1170			    break;
1171			}
1172		    } else pline("%s pricks your %s %s!", Monnam(mtmp),
1173			  sidestr, body_part(LEG));
1174		    set_wounded_legs(side, rnd(60-ACURR(A_DEX)));
1175		    exercise(A_STR, FALSE);
1176		    exercise(A_DEX, FALSE);
1177		  }
1178		  break;
1179		}
1180	    case AD_STON:	/* cockatrice */
1181		hitmsg(mtmp, mattk);
1182		if(!rn2(3)) {
1183		    if (mtmp->mcan) {
1184			if (flags.soundok)
1185			    You_hear("a cough from %s!", mon_nam(mtmp));
1186		    } else {
1187			if (flags.soundok)
1188			    You_hear("%s hissing!", s_suffix(mon_nam(mtmp)));
1189			if(!rn2(10) ||
1190			    (flags.moonphase == NEW_MOON && !have_lizard())) {
1191 do_stone:
1192			    if (!Stoned && !Stone_resistance
1193				    && !(poly_when_stoned(youmonst.data) &&
1194					polymon(PM_STONE_GOLEM))) {
1195				Stoned = 5;
1196				delayed_killer = mtmp->data->mname;
1197				if (mtmp->data->geno & G_UNIQ) {
1198				    if (!type_is_pname(mtmp->data)) {
1199					static char kbuf[BUFSZ];
1200
1201					/* "the" buffer may be reallocated */
1202					Strcpy(kbuf, the(delayed_killer));
1203					delayed_killer = kbuf;
1204				    }
1205				    killer_format = KILLED_BY;
1206				} else killer_format = KILLED_BY_AN;
1207				return(1);
1208				/* You("turn to stone..."); */
1209				/* done_in_by(mtmp); */
1210			    }
1211			}
1212		    }
1213		}
1214		break;
1215	    case AD_STCK:
1216		hitmsg(mtmp, mattk);
1217		if (uncancelled && !u.ustuck && !sticks(youmonst.data))
1218			u.ustuck = mtmp;
1219		break;
1220	    case AD_WRAP:
1221		if ((!mtmp->mcan || u.ustuck == mtmp) && !sticks(youmonst.data)) {
1222		    if (!u.ustuck && !rn2(10)) {
1223			if (u_slip_free(mtmp, mattk)) {
1224			    dmg = 0;
1225			} else {
1226			    pline("%s swings itself around you!",
1227				  Monnam(mtmp));
1228			    u.ustuck = mtmp;
1229			}
1230		    } else if(u.ustuck == mtmp) {
1231			if (is_pool(mtmp->mx,mtmp->my) && !Swimming
1232			    && !Amphibious) {
1233			    boolean moat =
1234				(levl[mtmp->mx][mtmp->my].typ != POOL) &&
1235				(levl[mtmp->mx][mtmp->my].typ != WATER) &&
1236				!Is_medusa_level(&u.uz) &&
1237				!Is_waterlevel(&u.uz);
1238
1239			    pline("%s drowns you...", Monnam(mtmp));
1240			    killer_format = KILLED_BY_AN;
1241			    Sprintf(buf, "%s by %s",
1242				    moat ? "moat" : "pool of water",
1243				    an(mtmp->data->mname));
1244			    killer = buf;
1245			    done(DROWNING);
1246			} else if(mattk->aatyp == AT_HUGS)
1247			    You("are being crushed.");
1248		    } else {
1249			dmg = 0;
1250			if(flags.verbose)
1251			    pline("%s brushes against your %s.", Monnam(mtmp),
1252				   body_part(LEG));
1253		    }
1254		} else dmg = 0;
1255		break;
1256	    case AD_WERE:
1257		hitmsg(mtmp, mattk);
1258		if (uncancelled && !rn2(4) && u.ulycn == NON_PM &&
1259			!Protection_from_shape_changers &&
1260			!defends(AD_WERE,uwep)) {
1261		    You_feel("feverish.");
1262		    exercise(A_CON, FALSE);
1263		    u.ulycn = monsndx(mdat);
1264		}
1265		break;
1266	    case AD_SGLD:
1267		hitmsg(mtmp, mattk);
1268		if (youmonst.data->mlet == mdat->mlet) break;
1269		if(!mtmp->mcan) stealgold(mtmp);
1270		break;
1271
1272	    case AD_SITM:	/* for now these are the same */
1273	    case AD_SEDU:
1274		if (is_animal(mtmp->data)) {
1275			hitmsg(mtmp, mattk);
1276			if (mtmp->mcan) break;
1277			/* Continue below */
1278		} else if (dmgtype(youmonst.data, AD_SEDU)
1279#ifdef SEDUCE
1280			|| dmgtype(youmonst.data, AD_SSEX)
1281#endif
1282						) {
1283			pline("%s %s.", Monnam(mtmp), mtmp->minvent ?
1284		    "brags about the goods some dungeon explorer provided" :
1285		    "makes some remarks about how difficult theft is lately");
1286			if (!tele_restrict(mtmp)) (void) rloc(mtmp, FALSE);
1287			return 3;
1288		} else if (mtmp->mcan) {
1289		    if (!Blind) {
1290			pline("%s tries to %s you, but you seem %s.",
1291			    Adjmonnam(mtmp, "plain"),
1292			    flags.female ? "charm" : "seduce",
1293			    flags.female ? "unaffected" : "uninterested");
1294		    }
1295		    if(rn2(3)) {
1296			if (!tele_restrict(mtmp)) (void) rloc(mtmp, FALSE);
1297			return 3;
1298		    }
1299		    break;
1300		}
1301		buf[0] = '\0';
1302		switch (steal(mtmp, buf)) {
1303		  case -1:
1304			return 2;
1305		  case 0:
1306			break;
1307		  default:
1308			if (!is_animal(mtmp->data) && !tele_restrict(mtmp))
1309			    (void) rloc(mtmp, FALSE);
1310			if (is_animal(mtmp->data) && *buf) {
1311			    if (canseemon(mtmp))
1312				pline("%s tries to %s away with %s.",
1313				      Monnam(mtmp),
1314				      locomotion(mtmp->data, "run"),
1315				      buf);
1316			}
1317			monflee(mtmp, 0, FALSE, FALSE);
1318			return 3;
1319		}
1320		break;
1321#ifdef SEDUCE
1322	    case AD_SSEX:
1323		if(could_seduce(mtmp, &youmonst, mattk) == 1
1324			&& !mtmp->mcan)
1325		    if (doseduce(mtmp))
1326			return 3;
1327		break;
1328#endif
1329	    case AD_SAMU:
1330		hitmsg(mtmp, mattk);
1331		/* when the Wiz hits, 1/20 steals the amulet */
1332		if (u.uhave.amulet ||
1333		     u.uhave.bell || u.uhave.book || u.uhave.menorah
1334		     || u.uhave.questart) /* carrying the Quest Artifact */
1335		    if (!rn2(20)) stealamulet(mtmp);
1336		break;
1337
1338	    case AD_TLPT:
1339		hitmsg(mtmp, mattk);
1340		if (uncancelled) {
1341		    if(flags.verbose)
1342			Your("position suddenly seems very uncertain!");
1343		    tele();
1344		}
1345		break;
1346	    case AD_RUST:
1347		hitmsg(mtmp, mattk);
1348		if (mtmp->mcan) break;
1349		if (u.umonnum == PM_IRON_GOLEM) {
1350			You("rust!");
1351			/* KMH -- this is okay with unchanging */
1352			rehumanize();
1353			break;
1354		}
1355		hurtarmor(AD_RUST);
1356		break;
1357	    case AD_CORR:
1358		hitmsg(mtmp, mattk);
1359		if (mtmp->mcan) break;
1360		hurtarmor(AD_CORR);
1361		break;
1362	    case AD_DCAY:
1363		hitmsg(mtmp, mattk);
1364		if (mtmp->mcan) break;
1365		if (u.umonnum == PM_WOOD_GOLEM ||
1366		    u.umonnum == PM_LEATHER_GOLEM) {
1367			You("rot!");
1368			/* KMH -- this is okay with unchanging */
1369			rehumanize();
1370			break;
1371		}
1372		hurtarmor(AD_DCAY);
1373		break;
1374	    case AD_HEAL:
1375		/* a cancelled nurse is just an ordinary monster */
1376		if (mtmp->mcan) {
1377		    hitmsg(mtmp, mattk);
1378		    break;
1379		}
1380		if(!uwep
1381#ifdef TOURIST
1382		   && !uarmu
1383#endif
1384		   && !uarm && !uarmh && !uarms && !uarmg && !uarmc && !uarmf) {
1385		    boolean goaway = FALSE;
1386		    pline("%s hits!  (I hope you don't mind.)", Monnam(mtmp));
1387		    if (Upolyd) {
1388			u.mh += rnd(7);
1389			if (!rn2(7)) {
1390			    /* no upper limit necessary; effect is temporary */
1391			    u.mhmax++;
1392			    if (!rn2(13)) goaway = TRUE;
1393			}
1394			if (u.mh > u.mhmax) u.mh = u.mhmax;
1395		    } else {
1396			u.uhp += rnd(7);
1397			if (!rn2(7)) {
1398			    /* hard upper limit via nurse care: 25 * ulevel */
1399			    if (u.uhpmax < 5 * u.ulevel + d(2 * u.ulevel, 10))
1400				u.uhpmax++;
1401			    if (!rn2(13)) goaway = TRUE;
1402			}
1403			if (u.uhp > u.uhpmax) u.uhp = u.uhpmax;
1404		    }
1405		    if (!rn2(3)) exercise(A_STR, TRUE);
1406		    if (!rn2(3)) exercise(A_CON, TRUE);
1407		    if (Sick) make_sick(0L, (char *) 0, FALSE, SICK_ALL);
1408		    flags.botl = 1;
1409		    if (goaway) {
1410			mongone(mtmp);
1411			return 2;
1412		    } else if (!rn2(33)) {
1413			if (!tele_restrict(mtmp)) (void) rloc(mtmp, FALSE);
1414			monflee(mtmp, d(3, 6), TRUE, FALSE);
1415			return 3;
1416		    }
1417		    dmg = 0;
1418		} else {
1419		    if (Role_if(PM_HEALER)) {
1420			if (flags.soundok && !(moves % 5))
1421		      verbalize("Doc, I can't help you unless you cooperate.");
1422			dmg = 0;
1423		    } else hitmsg(mtmp, mattk);
1424		}
1425		break;
1426	    case AD_CURS:
1427		hitmsg(mtmp, mattk);
1428		if(!night() && mdat == &mons[PM_GREMLIN]) break;
1429		if(!mtmp->mcan && !rn2(10)) {
1430		    if (flags.soundok) {
1431			if (Blind) You_hear("laughter.");
1432			else       pline("%s chuckles.", Monnam(mtmp));
1433		    }
1434		    if (u.umonnum == PM_CLAY_GOLEM) {
1435			pline("Some writing vanishes from your head!");
1436			/* KMH -- this is okay with unchanging */
1437			rehumanize();
1438			break;
1439		    }
1440		    attrcurse();
1441		}
1442		break;
1443	    case AD_STUN:
1444		hitmsg(mtmp, mattk);
1445		if(!mtmp->mcan && !rn2(4)) {
1446		    make_stunned(HStun + dmg, TRUE);
1447		    dmg /= 2;
1448		}
1449		break;
1450	    case AD_ACID:
1451		hitmsg(mtmp, mattk);
1452		if (!mtmp->mcan && !rn2(3))
1453		    if (Acid_resistance) {
1454			pline("You're covered in acid, but it seems harmless.");
1455			dmg = 0;
1456		    } else {
1457			pline("You're covered in acid!	It burns!");
1458			exercise(A_STR, FALSE);
1459		    }
1460		else		dmg = 0;
1461		break;
1462	    case AD_SLOW:
1463		hitmsg(mtmp, mattk);
1464		if (uncancelled && HFast &&
1465					!defends(AD_SLOW, uwep) && !rn2(4))
1466		    u_slow_down();
1467		break;
1468	    case AD_DREN:
1469		hitmsg(mtmp, mattk);
1470		if (uncancelled && !rn2(4))
1471		    drain_en(dmg);
1472		dmg = 0;
1473		break;
1474	    case AD_CONF:
1475		hitmsg(mtmp, mattk);
1476		if(!mtmp->mcan && !rn2(4) && !mtmp->mspec_used) {
1477		    mtmp->mspec_used = mtmp->mspec_used + (dmg + rn2(6));
1478		    if(Confusion)
1479			 You("are getting even more confused.");
1480		    else You("are getting confused.");
1481		    make_confused(HConfusion + dmg, FALSE);
1482		}
1483		dmg = 0;
1484		break;
1485	    case AD_DETH:
1486		pline("%s reaches out with its deadly touch.", Monnam(mtmp));
1487		if (is_undead(youmonst.data)) {
1488		    /* Still does normal damage */
1489		    pline("Was that the touch of death?");
1490		    break;
1491		}
1492		switch (rn2(20)) {
1493		case 19: case 18: case 17:
1494		    if (!Antimagic) {
1495			killer_format = KILLED_BY_AN;
1496			killer = "touch of death";
1497			done(DIED);
1498			dmg = 0;
1499			break;
1500		    } /* else FALLTHRU */
1501		default: /* case 16: ... case 5: */
1502		    You_feel("your life force draining away...");
1503		    permdmg = 1;	/* actual damage done below */
1504		    break;
1505		case 4: case 3: case 2: case 1: case 0:
1506		    if (Antimagic) shieldeff(u.ux, u.uy);
1507		    pline("Lucky for you, it didn't work!");
1508		    dmg = 0;
1509		    break;
1510		}
1511		break;
1512	    case AD_PEST:
1513		pline("%s reaches out, and you feel fever and chills.",
1514			Monnam(mtmp));
1515		(void) diseasemu(mdat); /* plus the normal damage */
1516		break;
1517	    case AD_FAMN:
1518		pline("%s reaches out, and your body shrivels.",
1519			Monnam(mtmp));
1520		exercise(A_CON, FALSE);
1521		if (!is_fainted()) morehungry(rn1(40,40));
1522		/* plus the normal damage */
1523		break;
1524	    case AD_SLIM:
1525		hitmsg(mtmp, mattk);
1526		if (!uncancelled) break;
1527		if (flaming(youmonst.data)) {
1528		    pline_The("slime burns away!");
1529		    dmg = 0;
1530		} else if (Unchanging ||
1531				youmonst.data == &mons[PM_GREEN_SLIME]) {
1532		    You("are unaffected.");
1533		    dmg = 0;
1534		} else if (!Slimed) {
1535		    You("don't feel very well.");
1536		    Slimed = 10L;
1537		    flags.botl = 1;
1538		    killer_format = KILLED_BY_AN;
1539		    delayed_killer = mtmp->data->mname;
1540		} else
1541		    pline("Yuck!");
1542		break;
1543	    case AD_ENCH:	/* KMH -- remove enchantment (disenchanter) */
1544		hitmsg(mtmp, mattk);
1545		/* uncancelled is sufficient enough; please
1546		   don't make this attack less frequent */
1547		if (uncancelled) {
1548		    struct obj *obj = some_armor(&youmonst);
1549
1550		    if (drain_item(obj)) {
1551			Your("%s less effective.", aobjnam(obj, "seem"));
1552		    }
1553		}
1554		break;
1555	    default:	dmg = 0;
1556			break;
1557	}
1558	if(u.uhp < 1) done_in_by(mtmp);
1559
1560/*	Negative armor class reduces damage done instead of fully protecting
1561 *	against hits.
1562 */
1563	if (dmg && u.uac < 0) {
1564		dmg -= rnd(-u.uac);
1565		if (dmg < 1) dmg = 1;
1566	}
1567
1568	if(dmg) {
1569	    if (Half_physical_damage
1570					/* Mitre of Holiness */
1571		|| (Role_if(PM_PRIEST) && uarmh && is_quest_artifact(uarmh) &&
1572		    (is_undead(mtmp->data) || is_demon(mtmp->data))))
1573		dmg = (dmg+1) / 2;
1574
1575	    if (permdmg) {	/* Death's life force drain */
1576		int lowerlimit, *hpmax_p;
1577		/*
1578		 * Apply some of the damage to permanent hit points:
1579		 *	polymorphed	    100% against poly'd hpmax
1580		 *	hpmax > 25*lvl	    100% against normal hpmax
1581		 *	hpmax > 10*lvl	50..100%
1582		 *	hpmax >  5*lvl	25..75%
1583		 *	otherwise	 0..50%
1584		 * Never reduces hpmax below 1 hit point per level.
1585		 */
1586		permdmg = rn2(dmg / 2 + 1);
1587		if (Upolyd || u.uhpmax > 25 * u.ulevel) permdmg = dmg;
1588		else if (u.uhpmax > 10 * u.ulevel) permdmg += dmg / 2;
1589		else if (u.uhpmax > 5 * u.ulevel) permdmg += dmg / 4;
1590
1591		if (Upolyd) {
1592		    hpmax_p = &u.mhmax;
1593		    /* [can't use youmonst.m_lev] */
1594		    lowerlimit = min((int)youmonst.data->mlevel, u.ulevel);
1595		} else {
1596		    hpmax_p = &u.uhpmax;
1597		    lowerlimit = u.ulevel;
1598		}
1599		if (*hpmax_p - permdmg > lowerlimit)
1600		    *hpmax_p -= permdmg;
1601		else if (*hpmax_p > lowerlimit)
1602		    *hpmax_p = lowerlimit;
1603		else	/* unlikely... */
1604		    ;	/* already at or below minimum threshold; do nothing */
1605		flags.botl = 1;
1606	    }
1607
1608	    mdamageu(mtmp, dmg);
1609	}
1610
1611	if (dmg)
1612	    res = passiveum(olduasmon, mtmp, mattk);
1613	else
1614	    res = 1;
1615	stop_occupation();
1616	return res;
1617}
1618
1619#endif /* OVL1 */
1620#ifdef OVLB
1621
1622STATIC_OVL int
1623gulpmu(mtmp, mattk)	/* monster swallows you, or damage if u.uswallow */
1624	register struct monst *mtmp;
1625	register struct attack  *mattk;
1626{
1627	struct trap *t = t_at(u.ux, u.uy);
1628	int	tmp = d((int)mattk->damn, (int)mattk->damd);
1629	int	tim_tmp;
1630	register struct obj *otmp2;
1631	int	i;
1632
1633	if (!u.uswallow) {	/* swallows you */
1634		if (youmonst.data->msize >= MZ_HUGE) return(0);
1635		if ((t && ((t->ttyp == PIT) || (t->ttyp == SPIKED_PIT))) &&
1636		    sobj_at(BOULDER, u.ux, u.uy))
1637			return(0);
1638
1639		if (Punished) unplacebc();	/* ball&chain go away */
1640		remove_monster(mtmp->mx, mtmp->my);
1641		mtmp->mtrapped = 0;		/* no longer on old trap */
1642		place_monster(mtmp, u.ux, u.uy);
1643		u.ustuck = mtmp;
1644		newsym(mtmp->mx,mtmp->my);
1645#ifdef STEED
1646		if (is_animal(mtmp->data) && u.usteed) {
1647			char buf[BUFSZ];
1648			/* Too many quirks presently if hero and steed
1649			 * are swallowed. Pretend purple worms don't
1650			 * like horses for now :-)
1651			 */
1652			Strcpy(buf, mon_nam(u.usteed));
1653			pline ("%s lunges forward and plucks you off %s!",
1654				Monnam(mtmp), buf);
1655			dismount_steed(DISMOUNT_ENGULFED);
1656		} else
1657#endif
1658		pline("%s engulfs you!", Monnam(mtmp));
1659		stop_occupation();
1660		reset_occupations();	/* behave as if you had moved */
1661
1662		if (u.utrap) {
1663			You("are released from the %s!",
1664				u.utraptype==TT_WEB ? "web" : "trap");
1665			u.utrap = 0;
1666		}
1667
1668		i = number_leashed();
1669		if (i > 0) {
1670		    const char *s = (i > 1) ? "leashes" : "leash";
1671		    pline_The("%s %s loose.", s, vtense(s, "snap"));
1672		    unleash_all();
1673		}
1674
1675		if (touch_petrifies(youmonst.data) && !resists_ston(mtmp)) {
1676			minstapetrify(mtmp, TRUE);
1677			if (mtmp->mhp > 0) return 0;
1678			else return 2;
1679		}
1680
1681		display_nhwindow(WIN_MESSAGE, FALSE);
1682		vision_recalc(2);	/* hero can't see anything */
1683		u.uswallow = 1;
1684		/* u.uswldtim always set > 1 */
1685		tim_tmp = 25 - (int)mtmp->m_lev;
1686		if (tim_tmp > 0) tim_tmp = rnd(tim_tmp) / 2;
1687		else if (tim_tmp < 0) tim_tmp = -(rnd(-tim_tmp) / 2);
1688		tim_tmp += -u.uac + 10;
1689		u.uswldtim = (unsigned)((tim_tmp < 2) ? 2 : tim_tmp);
1690		swallowed(1);
1691		for (otmp2 = invent; otmp2; otmp2 = otmp2->nobj)
1692		    (void) snuff_lit(otmp2);
1693	}
1694
1695	if (mtmp != u.ustuck) return(0);
1696	if (u.uswldtim > 0) u.uswldtim -= 1;
1697
1698	switch(mattk->adtyp) {
1699
1700		case AD_DGST:
1701		    if (Slow_digestion) {
1702			/* Messages are handled below */
1703			u.uswldtim = 0;
1704			tmp = 0;
1705		    } else if (u.uswldtim == 0) {
1706			pline("%s totally digests you!", Monnam(mtmp));
1707			tmp = u.uhp;
1708			if (Half_physical_damage) tmp *= 2; /* sorry */
1709		    } else {
1710			pline("%s%s digests you!", Monnam(mtmp),
1711			      (u.uswldtim == 2) ? " thoroughly" :
1712			      (u.uswldtim == 1) ? " utterly" : "");
1713			exercise(A_STR, FALSE);
1714		    }
1715		    break;
1716		case AD_PHYS:
1717		    if (mtmp->data == &mons[PM_FOG_CLOUD]) {
1718			You("are laden with moisture and %s",
1719			    flaming(youmonst.data) ? "are smoldering out!" :
1720			    Breathless ? "find it mildly uncomfortable." :
1721			    amphibious(youmonst.data) ? "feel comforted." :
1722			    "can barely breathe!");
1723			/* NB: Amphibious includes Breathless */
1724			if (Amphibious && !flaming(youmonst.data)) tmp = 0;
1725		    } else {
1726			You("are pummeled with debris!");
1727			exercise(A_STR, FALSE);
1728		    }
1729		    break;
1730		case AD_ACID:
1731		    if (Acid_resistance) {
1732			You("are covered with a seemingly harmless goo.");
1733			tmp = 0;
1734		    } else {
1735		      if (Hallucination) pline("Ouch!  You've been slimed!");
1736		      else You("are covered in slime!  It burns!");
1737		      exercise(A_STR, FALSE);
1738		    }
1739		    break;
1740		case AD_BLND:
1741		    if (can_blnd(mtmp, &youmonst, mattk->aatyp, (struct obj*)0)) {
1742			if(!Blind) {
1743			    You_cant("see in here!");
1744			    make_blinded((long)tmp,FALSE);
1745			    if (!Blind) Your(vision_clears);
1746			} else
1747			    /* keep him blind until disgorged */
1748			    make_blinded(Blinded+1,FALSE);
1749		    }
1750		    tmp = 0;
1751		    break;
1752		case AD_ELEC:
1753		    if(!mtmp->mcan && rn2(2)) {
1754			pline_The("air around you crackles with electricity.");
1755			if (Shock_resistance) {
1756				shieldeff(u.ux, u.uy);
1757				You("seem unhurt.");
1758				ugolemeffects(AD_ELEC,tmp);
1759				tmp = 0;
1760			}
1761		    } else tmp = 0;
1762		    break;
1763		case AD_COLD:
1764		    if(!mtmp->mcan && rn2(2)) {
1765			if (Cold_resistance) {
1766				shieldeff(u.ux, u.uy);
1767				You_feel("mildly chilly.");
1768				ugolemeffects(AD_COLD,tmp);
1769				tmp = 0;
1770			} else You("are freezing to death!");
1771		    } else tmp = 0;
1772		    break;
1773		case AD_FIRE:
1774		    if(!mtmp->mcan && rn2(2)) {
1775			if (Fire_resistance) {
1776				shieldeff(u.ux, u.uy);
1777				You_feel("mildly hot.");
1778				ugolemeffects(AD_FIRE,tmp);
1779				tmp = 0;
1780			} else You("are burning to a crisp!");
1781			burn_away_slime();
1782		    } else tmp = 0;
1783		    break;
1784		case AD_DISE:
1785		    if (!diseasemu(mtmp->data)) tmp = 0;
1786		    break;
1787		default:
1788		    tmp = 0;
1789		    break;
1790	}
1791
1792	if (Half_physical_damage) tmp = (tmp+1) / 2;
1793
1794	mdamageu(mtmp, tmp);
1795	if (tmp) stop_occupation();
1796
1797	if (touch_petrifies(youmonst.data) && !resists_ston(mtmp)) {
1798	    pline("%s very hurriedly %s you!", Monnam(mtmp),
1799		  is_animal(mtmp->data)? "regurgitates" : "expels");
1800	    expels(mtmp, mtmp->data, FALSE);
1801	} else if (!u.uswldtim || youmonst.data->msize >= MZ_HUGE) {
1802	    You("get %s!", is_animal(mtmp->data)? "regurgitated" : "expelled");
1803	    if (flags.verbose && (is_animal(mtmp->data) ||
1804		    (dmgtype(mtmp->data, AD_DGST) && Slow_digestion)))
1805		pline("Obviously %s doesn't like your taste.", mon_nam(mtmp));
1806	    expels(mtmp, mtmp->data, FALSE);
1807	}
1808	return(1);
1809}
1810
1811STATIC_OVL int
1812explmu(mtmp, mattk, ufound)	/* monster explodes in your face */
1813register struct monst *mtmp;
1814register struct attack  *mattk;
1815boolean ufound;
1816{
1817    if (mtmp->mcan) return(0);
1818
1819    if (!ufound)
1820	pline("%s explodes at a spot in %s!",
1821	    canseemon(mtmp) ? Monnam(mtmp) : "It",
1822	    levl[mtmp->mux][mtmp->muy].typ == WATER
1823		? "empty water" : "thin air");
1824    else {
1825	register int tmp = d((int)mattk->damn, (int)mattk->damd);
1826	register boolean not_affected = defends((int)mattk->adtyp, uwep);
1827
1828	hitmsg(mtmp, mattk);
1829
1830	switch (mattk->adtyp) {
1831	    case AD_COLD:
1832		not_affected |= Cold_resistance;
1833		goto common;
1834	    case AD_FIRE:
1835		not_affected |= Fire_resistance;
1836		goto common;
1837	    case AD_ELEC:
1838		not_affected |= Shock_resistance;
1839common:
1840
1841		if (!not_affected) {
1842		    if (ACURR(A_DEX) > rnd(20)) {
1843			You("duck some of the blast.");
1844			tmp = (tmp+1) / 2;
1845		    } else {
1846		        if (flags.verbose) You("get blasted!");
1847		    }
1848		    if (mattk->adtyp == AD_FIRE) burn_away_slime();
1849		    if (Half_physical_damage) tmp = (tmp+1) / 2;
1850		    mdamageu(mtmp, tmp);
1851		}
1852		break;
1853
1854	    case AD_BLND:
1855		not_affected = resists_blnd(&youmonst);
1856		if (!not_affected) {
1857		    /* sometimes you're affected even if it's invisible */
1858		    if (mon_visible(mtmp) || (rnd(tmp /= 2) > u.ulevel)) {
1859			You("are blinded by a blast of light!");
1860			make_blinded((long)tmp, FALSE);
1861			if (!Blind) Your(vision_clears);
1862		    } else if (flags.verbose)
1863			You("get the impression it was not terribly bright.");
1864		}
1865		break;
1866
1867	    case AD_HALU:
1868		not_affected |= Blind ||
1869			(u.umonnum == PM_BLACK_LIGHT ||
1870			 u.umonnum == PM_VIOLET_FUNGUS ||
1871			 dmgtype(youmonst.data, AD_STUN));
1872		if (!not_affected) {
1873		    boolean chg;
1874		    if (!Hallucination)
1875			You("are caught in a blast of kaleidoscopic light!");
1876		    chg = make_hallucinated(HHallucination + (long)tmp,FALSE,0L);
1877		    You("%s.", chg ? "are freaked out" : "seem unaffected");
1878		}
1879		break;
1880
1881	    default:
1882		break;
1883	}
1884	if (not_affected) {
1885	    You("seem unaffected by it.");
1886	    ugolemeffects((int)mattk->adtyp, tmp);
1887	}
1888    }
1889    mondead(mtmp);
1890    wake_nearto(mtmp->mx, mtmp->my, 7*7);
1891    if (mtmp->mhp > 0) return(0);
1892    return(2);	/* it dies */
1893}
1894
1895int
1896gazemu(mtmp, mattk)	/* monster gazes at you */
1897	register struct monst *mtmp;
1898	register struct attack  *mattk;
1899{
1900	switch(mattk->adtyp) {
1901	    case AD_STON:
1902		if (mtmp->mcan || !mtmp->mcansee) {
1903		    if (!canseemon(mtmp)) break;	/* silently */
1904		    pline("%s %s.", Monnam(mtmp),
1905			  (mtmp->data == &mons[PM_MEDUSA] && mtmp->mcan) ?
1906				"doesn't look all that ugly" :
1907				"gazes ineffectually");
1908		    break;
1909		}
1910		if (Reflecting && couldsee(mtmp->mx, mtmp->my) &&
1911			mtmp->data == &mons[PM_MEDUSA]) {
1912		    /* hero has line of sight to Medusa and she's not blind */
1913		    boolean useeit = canseemon(mtmp);
1914
1915		    if (useeit)
1916			(void) ureflects("%s gaze is reflected by your %s.",
1917					 s_suffix(Monnam(mtmp)));
1918		    if (mon_reflects(mtmp, !useeit ? (char *)0 :
1919				     "The gaze is reflected away by %s %s!"))
1920			break;
1921		    if (!m_canseeu(mtmp)) { /* probably you're invisible */
1922			if (useeit)
1923			    pline(
1924		      "%s doesn't seem to notice that %s gaze was reflected.",
1925				  Monnam(mtmp), mhis(mtmp));
1926			break;
1927		    }
1928		    if (useeit)
1929			pline("%s is turned to stone!", Monnam(mtmp));
1930		    stoned = TRUE;
1931		    killed(mtmp);
1932
1933		    if (mtmp->mhp > 0) break;
1934		    return 2;
1935		}
1936		if (canseemon(mtmp) && couldsee(mtmp->mx, mtmp->my) &&
1937		    !Stone_resistance) {
1938		    You("meet %s gaze.", s_suffix(mon_nam(mtmp)));
1939		    stop_occupation();
1940		    if(poly_when_stoned(youmonst.data) && polymon(PM_STONE_GOLEM))
1941			break;
1942		    You("turn to stone...");
1943		    killer_format = KILLED_BY;
1944		    killer = mtmp->data->mname;
1945		    done(STONING);
1946		}
1947		break;
1948	    case AD_CONF:
1949		if(!mtmp->mcan && canseemon(mtmp) &&
1950		   couldsee(mtmp->mx, mtmp->my) &&
1951		   mtmp->mcansee && !mtmp->mspec_used && rn2(5)) {
1952		    int conf = d(3,4);
1953
1954		    mtmp->mspec_used = mtmp->mspec_used + (conf + rn2(6));
1955		    if(!Confusion)
1956			pline("%s gaze confuses you!",
1957			                  s_suffix(Monnam(mtmp)));
1958		    else
1959			You("are getting more and more confused.");
1960		    make_confused(HConfusion + conf, FALSE);
1961		    stop_occupation();
1962		}
1963		break;
1964	    case AD_STUN:
1965		if(!mtmp->mcan && canseemon(mtmp) &&
1966		   couldsee(mtmp->mx, mtmp->my) &&
1967		   mtmp->mcansee && !mtmp->mspec_used && rn2(5)) {
1968		    int stun = d(2,6);
1969
1970		    mtmp->mspec_used = mtmp->mspec_used + (stun + rn2(6));
1971		    pline("%s stares piercingly at you!", Monnam(mtmp));
1972		    make_stunned(HStun + stun, TRUE);
1973		    stop_occupation();
1974		}
1975		break;
1976	    case AD_BLND:
1977		if (!mtmp->mcan && canseemon(mtmp) && !resists_blnd(&youmonst)
1978			&& distu(mtmp->mx,mtmp->my) <= BOLT_LIM*BOLT_LIM) {
1979		    int blnd = d((int)mattk->damn, (int)mattk->damd);
1980
1981		    You("are blinded by %s radiance!",
1982			              s_suffix(mon_nam(mtmp)));
1983		    make_blinded((long)blnd,FALSE);
1984		    stop_occupation();
1985		    /* not blind at this point implies you're wearing
1986		       the Eyes of the Overworld; make them block this
1987		       particular stun attack too */
1988		    if (!Blind) Your(vision_clears);
1989		    else make_stunned((long)d(1,3),TRUE);
1990		}
1991		break;
1992	    case AD_FIRE:
1993		if (!mtmp->mcan && canseemon(mtmp) &&
1994			couldsee(mtmp->mx, mtmp->my) &&
1995			mtmp->mcansee && !mtmp->mspec_used && rn2(5)) {
1996		    int dmg = d(2,6);
1997
1998		    pline("%s attacks you with a fiery gaze!", Monnam(mtmp));
1999		    stop_occupation();
2000		    if (Fire_resistance) {
2001			pline_The("fire doesn't feel hot!");
2002			dmg = 0;
2003		    }
2004		    burn_away_slime();
2005		    if ((int) mtmp->m_lev > rn2(20))
2006			destroy_item(SCROLL_CLASS, AD_FIRE);
2007		    if ((int) mtmp->m_lev > rn2(20))
2008			destroy_item(POTION_CLASS, AD_FIRE);
2009		    if ((int) mtmp->m_lev > rn2(25))
2010			destroy_item(SPBOOK_CLASS, AD_FIRE);
2011		    if (dmg) mdamageu(mtmp, dmg);
2012		}
2013		break;
2014#ifdef PM_BEHOLDER /* work in progress */
2015	    case AD_SLEE:
2016		if(!mtmp->mcan && canseemon(mtmp) &&
2017		   couldsee(mtmp->mx, mtmp->my) && mtmp->mcansee &&
2018		   multi >= 0 && !rn2(5) && !Sleep_resistance) {
2019
2020		    fall_asleep(-rnd(10), TRUE);
2021		    pline("%s gaze makes you very sleepy...",
2022			  s_suffix(Monnam(mtmp)));
2023		}
2024		break;
2025	    case AD_SLOW:
2026		if(!mtmp->mcan && canseemon(mtmp) && mtmp->mcansee &&
2027		   (HFast & (INTRINSIC|TIMEOUT)) &&
2028		   !defends(AD_SLOW, uwep) && !rn2(4))
2029
2030		    u_slow_down();
2031		    stop_occupation();
2032		break;
2033#endif
2034	    default: impossible("Gaze attack %d?", mattk->adtyp);
2035		break;
2036	}
2037	return(0);
2038}
2039
2040#endif /* OVLB */
2041#ifdef OVL1
2042
2043void
2044mdamageu(mtmp, n)	/* mtmp hits you for n points damage */
2045register struct monst *mtmp;
2046register int n;
2047{
2048	flags.botl = 1;
2049	if (Upolyd) {
2050		u.mh -= n;
2051		if (u.mh < 1) rehumanize();
2052	} else {
2053		u.uhp -= n;
2054		if(u.uhp < 1) done_in_by(mtmp);
2055	}
2056}
2057
2058#endif /* OVL1 */
2059#ifdef OVLB
2060
2061STATIC_OVL void
2062urustm(mon, obj)
2063register struct monst *mon;
2064register struct obj *obj;
2065{
2066	boolean vis;
2067	boolean is_acid;
2068
2069	if (!mon || !obj) return; /* just in case */
2070	if (dmgtype(youmonst.data, AD_CORR))
2071	    is_acid = TRUE;
2072	else if (dmgtype(youmonst.data, AD_RUST))
2073	    is_acid = FALSE;
2074	else
2075	    return;
2076
2077	vis = cansee(mon->mx, mon->my);
2078
2079	if ((is_acid ? is_corrodeable(obj) : is_rustprone(obj)) &&
2080	    (is_acid ? obj->oeroded2 : obj->oeroded) < MAX_ERODE) {
2081		if (obj->greased || obj->oerodeproof || (obj->blessed && rn2(3))) {
2082		    if (vis)
2083			pline("Somehow, %s weapon is not affected.",
2084						s_suffix(mon_nam(mon)));
2085		    if (obj->greased && !rn2(2)) obj->greased = 0;
2086		} else {
2087		    if (vis)
2088			pline("%s %s%s!",
2089			        s_suffix(Monnam(mon)),
2090				aobjnam(obj, (is_acid ? "corrode" : "rust")),
2091			        (is_acid ? obj->oeroded2 : obj->oeroded)
2092				    ? " further" : "");
2093		    if (is_acid) obj->oeroded2++;
2094		    else obj->oeroded++;
2095		}
2096	}
2097}
2098
2099#endif /* OVLB */
2100#ifdef OVL1
2101
2102int
2103could_seduce(magr,mdef,mattk)
2104struct monst *magr, *mdef;
2105struct attack *mattk;
2106/* returns 0 if seduction impossible,
2107 *	   1 if fine,
2108 *	   2 if wrong gender for nymph */
2109{
2110	register struct permonst *pagr;
2111	boolean agrinvis, defperc;
2112	xchar genagr, gendef;
2113
2114	if (is_animal(magr->data)) return (0);
2115	if(magr == &youmonst) {
2116		pagr = youmonst.data;
2117		agrinvis = (Invis != 0);
2118		genagr = poly_gender();
2119	} else {
2120		pagr = magr->data;
2121		agrinvis = magr->minvis;
2122		genagr = gender(magr);
2123	}
2124	if(mdef == &youmonst) {
2125		defperc = (See_invisible != 0);
2126		gendef = poly_gender();
2127	} else {
2128		defperc = perceives(mdef->data);
2129		gendef = gender(mdef);
2130	}
2131
2132	if(agrinvis && !defperc
2133#ifdef SEDUCE
2134		&& mattk && mattk->adtyp != AD_SSEX
2135#endif
2136		)
2137		return 0;
2138
2139	if(pagr->mlet != S_NYMPH
2140		&& ((pagr != &mons[PM_INCUBUS] && pagr != &mons[PM_SUCCUBUS])
2141#ifdef SEDUCE
2142		    || (mattk && mattk->adtyp != AD_SSEX)
2143#endif
2144		   ))
2145		return 0;
2146
2147	if(genagr == 1 - gendef)
2148		return 1;
2149	else
2150		return (pagr->mlet == S_NYMPH) ? 2 : 0;
2151}
2152
2153#endif /* OVL1 */
2154#ifdef OVLB
2155
2156#ifdef SEDUCE
2157/* Returns 1 if monster teleported */
2158int
2159doseduce(mon)
2160register struct monst *mon;
2161{
2162	register struct obj *ring, *nring;
2163	boolean fem = (mon->data == &mons[PM_SUCCUBUS]); /* otherwise incubus */
2164	char qbuf[QBUFSZ];
2165
2166	if (mon->mcan || mon->mspec_used) {
2167		pline("%s acts as though %s has got a %sheadache.",
2168		      Monnam(mon), mhe(mon),
2169		      mon->mcan ? "severe " : "");
2170		return 0;
2171	}
2172
2173	if (unconscious()) {
2174		pline("%s seems dismayed at your lack of response.",
2175		      Monnam(mon));
2176		return 0;
2177	}
2178
2179	if (Blind) pline("It caresses you...");
2180	else You_feel("very attracted to %s.", mon_nam(mon));
2181
2182	for(ring = invent; ring; ring = nring) {
2183	    nring = ring->nobj;
2184	    if (ring->otyp != RIN_ADORNMENT) continue;
2185	    if (fem) {
2186		if (rn2(20) < ACURR(A_CHA)) {
2187		    Sprintf(qbuf, "\"That %s looks pretty.  May I have it?\"",
2188			safe_qbuf("",sizeof("\"That  looks pretty.  May I have it?\""),
2189			xname(ring), simple_typename(ring->otyp), "ring"));
2190		    makeknown(RIN_ADORNMENT);
2191		    if (yn(qbuf) == 'n') continue;
2192		} else pline("%s decides she'd like your %s, and takes it.",
2193			Blind ? "She" : Monnam(mon), xname(ring));
2194		makeknown(RIN_ADORNMENT);
2195		if (ring==uleft || ring==uright) Ring_gone(ring);
2196		if (ring==uwep) setuwep((struct obj *)0);
2197		if (ring==uswapwep) setuswapwep((struct obj *)0);
2198		if (ring==uquiver) setuqwep((struct obj *)0);
2199		freeinv(ring);
2200		(void) mpickobj(mon,ring);
2201	    } else {
2202		char buf[BUFSZ];
2203
2204		if (uleft && uright && uleft->otyp == RIN_ADORNMENT
2205				&& uright->otyp==RIN_ADORNMENT)
2206			break;
2207		if (ring==uleft || ring==uright) continue;
2208		if (rn2(20) < ACURR(A_CHA)) {
2209		    Sprintf(qbuf,"\"That %s looks pretty.  Would you wear it for me?\"",
2210			safe_qbuf("",
2211			    sizeof("\"That  looks pretty.  Would you wear it for me?\""),
2212			    xname(ring), simple_typename(ring->otyp), "ring"));
2213		    makeknown(RIN_ADORNMENT);
2214		    if (yn(qbuf) == 'n') continue;
2215		} else {
2216		    pline("%s decides you'd look prettier wearing your %s,",
2217			Blind ? "He" : Monnam(mon), xname(ring));
2218		    pline("and puts it on your finger.");
2219		}
2220		makeknown(RIN_ADORNMENT);
2221		if (!uright) {
2222		    pline("%s puts %s on your right %s.",
2223			Blind ? "He" : Monnam(mon), the(xname(ring)), body_part(HAND));
2224		    setworn(ring, RIGHT_RING);
2225		} else if (!uleft) {
2226		    pline("%s puts %s on your left %s.",
2227			Blind ? "He" : Monnam(mon), the(xname(ring)), body_part(HAND));
2228		    setworn(ring, LEFT_RING);
2229		} else if (uright && uright->otyp != RIN_ADORNMENT) {
2230		    Strcpy(buf, xname(uright));
2231		    pline("%s replaces your %s with your %s.",
2232			Blind ? "He" : Monnam(mon), buf, xname(ring));
2233		    Ring_gone(uright);
2234		    setworn(ring, RIGHT_RING);
2235		} else if (uleft && uleft->otyp != RIN_ADORNMENT) {
2236		    Strcpy(buf, xname(uleft));
2237		    pline("%s replaces your %s with your %s.",
2238			Blind ? "He" : Monnam(mon), buf, xname(ring));
2239		    Ring_gone(uleft);
2240		    setworn(ring, LEFT_RING);
2241		} else impossible("ring replacement");
2242		Ring_on(ring);
2243		prinv((char *)0, ring, 0L);
2244	    }
2245	}
2246
2247	if (!uarmc && !uarmf && !uarmg && !uarms && !uarmh
2248#ifdef TOURIST
2249								&& !uarmu
2250#endif
2251									)
2252		pline("%s murmurs sweet nothings into your ear.",
2253			Blind ? (fem ? "She" : "He") : Monnam(mon));
2254	else
2255		pline("%s murmurs in your ear, while helping you undress.",
2256			Blind ? (fem ? "She" : "He") : Monnam(mon));
2257	mayberem(uarmc, cloak_simple_name(uarmc));
2258	if(!uarmc)
2259		mayberem(uarm, "suit");
2260	mayberem(uarmf, "boots");
2261	if(!uwep || !welded(uwep))
2262		mayberem(uarmg, "gloves");
2263	mayberem(uarms, "shield");
2264	mayberem(uarmh, "helmet");
2265#ifdef TOURIST
2266	if(!uarmc && !uarm)
2267		mayberem(uarmu, "shirt");
2268#endif
2269
2270	if (uarm || uarmc) {
2271		verbalize("You're such a %s; I wish...",
2272				flags.female ? "sweet lady" : "nice guy");
2273		if (!tele_restrict(mon)) (void) rloc(mon, FALSE);
2274		return 1;
2275	}
2276	if (u.ualign.type == A_CHAOTIC)
2277		adjalign(1);
2278
2279	/* by this point you have discovered mon's identity, blind or not... */
2280	pline("Time stands still while you and %s lie in each other's arms...",
2281		noit_mon_nam(mon));
2282	if (rn2(35) > ACURR(A_CHA) + ACURR(A_INT)) {
2283		/* Don't bother with mspec_used here... it didn't get tired! */
2284		pline("%s seems to have enjoyed it more than you...",
2285			noit_Monnam(mon));
2286		switch (rn2(5)) {
2287			case 0: You_feel("drained of energy.");
2288				u.uen = 0;
2289				u.uenmax -= rnd(Half_physical_damage ? 5 : 10);
2290			        exercise(A_CON, FALSE);
2291				if (u.uenmax < 0) u.uenmax = 0;
2292				break;
2293			case 1: You("are down in the dumps.");
2294				(void) adjattrib(A_CON, -1, TRUE);
2295			        exercise(A_CON, FALSE);
2296				flags.botl = 1;
2297				break;
2298			case 2: Your("senses are dulled.");
2299				(void) adjattrib(A_WIS, -1, TRUE);
2300			        exercise(A_WIS, FALSE);
2301				flags.botl = 1;
2302				break;
2303			case 3:
2304				if (!resists_drli(&youmonst)) {
2305				    You_feel("out of shape.");
2306				    losexp("overexertion");
2307				} else {
2308				    You("have a curious feeling...");
2309				}
2310				break;
2311			case 4: {
2312				int tmp;
2313				You_feel("exhausted.");
2314			        exercise(A_STR, FALSE);
2315				tmp = rn1(10, 6);
2316				if(Half_physical_damage) tmp = (tmp+1) / 2;
2317				losehp(tmp, "exhaustion", KILLED_BY);
2318				break;
2319			}
2320		}
2321	} else {
2322		mon->mspec_used = rnd(100); /* monster is worn out */
2323		You("seem to have enjoyed it more than %s...",
2324		    noit_mon_nam(mon));
2325		switch (rn2(5)) {
2326		case 0: You_feel("raised to your full potential.");
2327			exercise(A_CON, TRUE);
2328			u.uen = (u.uenmax += rnd(5));
2329			break;
2330		case 1: You_feel("good enough to do it again.");
2331			(void) adjattrib(A_CON, 1, TRUE);
2332			exercise(A_CON, TRUE);
2333			flags.botl = 1;
2334			break;
2335		case 2: You("will always remember %s...", noit_mon_nam(mon));
2336			(void) adjattrib(A_WIS, 1, TRUE);
2337			exercise(A_WIS, TRUE);
2338			flags.botl = 1;
2339			break;
2340		case 3: pline("That was a very educational experience.");
2341			pluslvl(FALSE);
2342			exercise(A_WIS, TRUE);
2343			break;
2344		case 4: You_feel("restored to health!");
2345			u.uhp = u.uhpmax;
2346			if (Upolyd) u.mh = u.mhmax;
2347			exercise(A_STR, TRUE);
2348			flags.botl = 1;
2349			break;
2350		}
2351	}
2352
2353	if (mon->mtame) /* don't charge */ ;
2354	else if (rn2(20) < ACURR(A_CHA)) {
2355		pline("%s demands that you pay %s, but you refuse...",
2356			noit_Monnam(mon),
2357			Blind ? (fem ? "her" : "him") : mhim(mon));
2358	} else if (u.umonnum == PM_LEPRECHAUN)
2359		pline("%s tries to take your money, but fails...",
2360				noit_Monnam(mon));
2361	else {
2362#ifndef GOLDOBJ
2363		long cost;
2364
2365		if (u.ugold > (long)LARGEST_INT - 10L)
2366			cost = (long) rnd(LARGEST_INT) + 500L;
2367		else
2368			cost = (long) rnd((int)u.ugold + 10) + 500L;
2369		if (mon->mpeaceful) {
2370			cost /= 5L;
2371			if (!cost) cost = 1L;
2372		}
2373		if (cost > u.ugold) cost = u.ugold;
2374		if (!cost) verbalize("It's on the house!");
2375		else {
2376		    pline("%s takes %ld %s for services rendered!",
2377			    noit_Monnam(mon), cost, currency(cost));
2378		    u.ugold -= cost;
2379		    mon->mgold += cost;
2380		    flags.botl = 1;
2381		}
2382#else
2383		long cost;
2384                long umoney = money_cnt(invent);
2385
2386		if (umoney > (long)LARGEST_INT - 10L)
2387			cost = (long) rnd(LARGEST_INT) + 500L;
2388		else
2389			cost = (long) rnd((int)umoney + 10) + 500L;
2390		if (mon->mpeaceful) {
2391			cost /= 5L;
2392			if (!cost) cost = 1L;
2393		}
2394		if (cost > umoney) cost = umoney;
2395		if (!cost) verbalize("It's on the house!");
2396		else {
2397		    pline("%s takes %ld %s for services rendered!",
2398			    noit_Monnam(mon), cost, currency(cost));
2399                    money2mon(mon, cost);
2400		    flags.botl = 1;
2401		}
2402#endif
2403	}
2404	if (!rn2(25)) mon->mcan = 1; /* monster is worn out */
2405	if (!tele_restrict(mon)) (void) rloc(mon, FALSE);
2406	return 1;
2407}
2408
2409STATIC_OVL void
2410mayberem(obj, str)
2411register struct obj *obj;
2412const char *str;
2413{
2414	char qbuf[QBUFSZ];
2415
2416	if (!obj || !obj->owornmask) return;
2417
2418	if (rn2(20) < ACURR(A_CHA)) {
2419		Sprintf(qbuf,"\"Shall I remove your %s, %s?\"",
2420			str,
2421			(!rn2(2) ? "lover" : !rn2(2) ? "dear" : "sweetheart"));
2422		if (yn(qbuf) == 'n') return;
2423	} else {
2424		char hairbuf[BUFSZ];
2425
2426		Sprintf(hairbuf, "let me run my fingers through your %s",
2427			body_part(HAIR));
2428		verbalize("Take off your %s; %s.", str,
2429			(obj == uarm)  ? "let's get a little closer" :
2430			(obj == uarmc || obj == uarms) ? "it's in the way" :
2431			(obj == uarmf) ? "let me rub your feet" :
2432			(obj == uarmg) ? "they're too clumsy" :
2433#ifdef TOURIST
2434			(obj == uarmu) ? "let me massage you" :
2435#endif
2436			/* obj == uarmh */
2437			hairbuf);
2438	}
2439	remove_worn_item(obj, TRUE);
2440}
2441#endif  /* SEDUCE */
2442
2443#endif /* OVLB */
2444
2445#ifdef OVL1
2446
2447STATIC_OVL int
2448passiveum(olduasmon,mtmp,mattk)
2449struct permonst *olduasmon;
2450register struct monst *mtmp;
2451register struct attack *mattk;
2452{
2453	int i, tmp;
2454
2455	for (i = 0; ; i++) {
2456	    if (i >= NATTK) return 1;
2457	    if (olduasmon->mattk[i].aatyp == AT_NONE ||
2458	    		olduasmon->mattk[i].aatyp == AT_BOOM) break;
2459	}
2460	if (olduasmon->mattk[i].damn)
2461	    tmp = d((int)olduasmon->mattk[i].damn,
2462				    (int)olduasmon->mattk[i].damd);
2463	else if(olduasmon->mattk[i].damd)
2464	    tmp = d((int)olduasmon->mlevel+1, (int)olduasmon->mattk[i].damd);
2465	else
2466	    tmp = 0;
2467
2468	/* These affect the enemy even if you were "killed" (rehumanized) */
2469	switch(olduasmon->mattk[i].adtyp) {
2470	    case AD_ACID:
2471		if (!rn2(2)) {
2472		    pline("%s is splashed by your acid!", Monnam(mtmp));
2473		    if (resists_acid(mtmp)) {
2474			pline("%s is not affected.", Monnam(mtmp));
2475			tmp = 0;
2476		    }
2477		} else tmp = 0;
2478		if (!rn2(30)) erode_armor(mtmp, TRUE);
2479		if (!rn2(6)) erode_obj(MON_WEP(mtmp), TRUE, TRUE);
2480		goto assess_dmg;
2481	    case AD_STON: /* cockatrice */
2482	    {
2483		long protector = attk_protection((int)mattk->aatyp),
2484		     wornitems = mtmp->misc_worn_check;
2485
2486		/* wielded weapon gives same protection as gloves here */
2487		if (MON_WEP(mtmp) != 0) wornitems |= W_ARMG;
2488
2489		if (!resists_ston(mtmp) && (protector == 0L ||
2490			(protector != ~0L &&
2491			    (wornitems & protector) != protector))) {
2492		    if (poly_when_stoned(mtmp->data)) {
2493			mon_to_stone(mtmp);
2494			return (1);
2495		    }
2496		    pline("%s turns to stone!", Monnam(mtmp));
2497		    stoned = 1;
2498		    xkilled(mtmp, 0);
2499		    if (mtmp->mhp > 0) return 1;
2500		    return 2;
2501		}
2502		return 1;
2503	    }
2504	    case AD_ENCH:	/* KMH -- remove enchantment (disenchanter) */
2505	    	if (otmp) {
2506	    	    (void) drain_item(otmp);
2507	    	    /* No message */
2508	    	}
2509	    	return (1);
2510	    default:
2511		break;
2512	}
2513	if (!Upolyd) return 1;
2514
2515	/* These affect the enemy only if you are still a monster */
2516	if (rn2(3)) switch(youmonst.data->mattk[i].adtyp) {
2517	    case AD_PHYS:
2518	    	if (youmonst.data->mattk[i].aatyp == AT_BOOM) {
2519	    	    You("explode!");
2520	    	    /* KMH, balance patch -- this is okay with unchanging */
2521	    	    rehumanize();
2522	    	    goto assess_dmg;
2523	    	}
2524	    	break;
2525	    case AD_PLYS: /* Floating eye */
2526		if (tmp > 127) tmp = 127;
2527		if (u.umonnum == PM_FLOATING_EYE) {
2528		    if (!rn2(4)) tmp = 127;
2529		    if (mtmp->mcansee && haseyes(mtmp->data) && rn2(3) &&
2530				(perceives(mtmp->data) || !Invis)) {
2531			if (Blind)
2532			    pline("As a blind %s, you cannot defend yourself.",
2533							youmonst.data->mname);
2534		        else {
2535			    if (mon_reflects(mtmp,
2536					    "Your gaze is reflected by %s %s."))
2537				return 1;
2538			    pline("%s is frozen by your gaze!", Monnam(mtmp));
2539			    mtmp->mcanmove = 0;
2540			    mtmp->mfrozen = tmp;
2541			    return 3;
2542			}
2543		    }
2544		} else { /* gelatinous cube */
2545		    pline("%s is frozen by you.", Monnam(mtmp));
2546		    mtmp->mcanmove = 0;
2547		    mtmp->mfrozen = tmp;
2548		    return 3;
2549		}
2550		return 1;
2551	    case AD_COLD: /* Brown mold or blue jelly */
2552		if (resists_cold(mtmp)) {
2553		    shieldeff(mtmp->mx, mtmp->my);
2554		    pline("%s is mildly chilly.", Monnam(mtmp));
2555		    golemeffects(mtmp, AD_COLD, tmp);
2556		    tmp = 0;
2557		    break;
2558		}
2559		pline("%s is suddenly very cold!", Monnam(mtmp));
2560		u.mh += tmp / 2;
2561		if (u.mhmax < u.mh) u.mhmax = u.mh;
2562		if (u.mhmax > ((youmonst.data->mlevel+1) * 8))
2563		    (void)split_mon(&youmonst, mtmp);
2564		break;
2565	    case AD_STUN: /* Yellow mold */
2566		if (!mtmp->mstun) {
2567		    mtmp->mstun = 1;
2568		    pline("%s %s.", Monnam(mtmp),
2569			  makeplural(stagger(mtmp->data, "stagger")));
2570		}
2571		tmp = 0;
2572		break;
2573	    case AD_FIRE: /* Red mold */
2574		if (resists_fire(mtmp)) {
2575		    shieldeff(mtmp->mx, mtmp->my);
2576		    pline("%s is mildly warm.", Monnam(mtmp));
2577		    golemeffects(mtmp, AD_FIRE, tmp);
2578		    tmp = 0;
2579		    break;
2580		}
2581		pline("%s is suddenly very hot!", Monnam(mtmp));
2582		break;
2583	    case AD_ELEC:
2584		if (resists_elec(mtmp)) {
2585		    shieldeff(mtmp->mx, mtmp->my);
2586		    pline("%s is slightly tingled.", Monnam(mtmp));
2587		    golemeffects(mtmp, AD_ELEC, tmp);
2588		    tmp = 0;
2589		    break;
2590		}
2591		pline("%s is jolted with your electricity!", Monnam(mtmp));
2592		break;
2593	    default: tmp = 0;
2594		break;
2595	}
2596	else tmp = 0;
2597
2598    assess_dmg:
2599	if((mtmp->mhp -= tmp) <= 0) {
2600		pline("%s dies!", Monnam(mtmp));
2601		xkilled(mtmp,0);
2602		if (mtmp->mhp > 0) return 1;
2603		return 2;
2604	}
2605	return 1;
2606}
2607
2608#endif /* OVL1 */
2609#ifdef OVLB
2610
2611#include "edog.h"
2612struct monst *
2613cloneu()
2614{
2615	register struct monst *mon;
2616	int mndx = monsndx(youmonst.data);
2617
2618	if (u.mh <= 1) return(struct monst *)0;
2619	if (mvitals[mndx].mvflags & G_EXTINCT) return(struct monst *)0;
2620	mon = makemon(youmonst.data, u.ux, u.uy, NO_MINVENT|MM_EDOG);
2621	mon = christen_monst(mon, plname);
2622	initedog(mon);
2623	mon->m_lev = youmonst.data->mlevel;
2624	mon->mhpmax = u.mhmax;
2625	mon->mhp = u.mh / 2;
2626	u.mh -= mon->mhp;
2627	flags.botl = 1;
2628	return(mon);
2629}
2630
2631#endif /* OVLB */
2632
2633/*mhitu.c*/
2634