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