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