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
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
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
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 *
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 *
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*/