1    | /*	SCCS Id: @(#)mon.c	3.3	2000/07/24	*/
2    | /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3    | /* NetHack may be freely redistributed.  See license for details. */
4    | 
5    | /* If you're using precompiled headers, you don't want this either */
6    | #ifdef MICROPORT_BUG
7    | #define MKROOM_H
8    | #endif
9    | 
10   | #include "hack.h"
11   | #include "mfndpos.h"
12   | #include "edog.h"
13   | #include <ctype.h>
14   | 
15   | STATIC_DCL boolean FDECL(corpse_chance,(struct monst *));
16   | STATIC_DCL boolean FDECL(restrap,(struct monst *));
17   | STATIC_DCL long FDECL(mm_aggression, (struct monst *,struct monst *));
18   | #ifdef OVL2
19   | STATIC_DCL int NDECL(pick_animal);
20   | STATIC_DCL int FDECL(select_newcham_form, (struct monst *));
21   | STATIC_DCL void FDECL(kill_eggs, (struct obj *));
22   | #endif
23   | 
24   | #if 0
25   | /* part of the original warning code which was replaced in 3.3.1 */
26   | #ifdef OVL1
27   | #define warnDelay 10
28   | long lastwarntime;
29   | int lastwarnlev;
30   | 
31   | const char *warnings[] = {
32   | 	"white", "pink", "red", "ruby", "purple", "black"
33   | };
34   | 
35   | STATIC_DCL void NDECL(warn_effects);
36   | #endif /* OVL1 */
37   | #endif /* 0 */
38   | 
39   | #ifndef OVLB
40   | STATIC_VAR short cham_to_pm[];
41   | #else
42   | STATIC_DCL struct obj *FDECL(make_corpse,(struct monst *));
43   | STATIC_DCL void FDECL(m_detach, (struct monst *, struct permonst *));
44   | STATIC_DCL void FDECL(lifesaved_monster, (struct monst *));
45   | 
46   | /* convert the monster index of an undead to its living counterpart */
47   | int
48   | undead_to_corpse(mndx)
49   | int mndx;
50   | {
51   | 	switch (mndx) {
52   | 	case PM_KOBOLD_ZOMBIE:
53   | 	case PM_KOBOLD_MUMMY:	mndx = PM_KOBOLD;  break;
54   | 	case PM_DWARF_ZOMBIE:
55   | 	case PM_DWARF_MUMMY:	mndx = PM_DWARF;  break;
56   | 	case PM_GNOME_ZOMBIE:
57   | 	case PM_GNOME_MUMMY:	mndx = PM_GNOME;  break;
58   | 	case PM_ORC_ZOMBIE:
59   | 	case PM_ORC_MUMMY:	mndx = PM_ORC;  break;
60   | 	case PM_ELF_ZOMBIE:
61   | 	case PM_ELF_MUMMY:	mndx = PM_ELF;  break;
62   | 	case PM_VAMPIRE:
63   | 	case PM_VAMPIRE_LORD:
64   | #if 0	/* DEFERRED */
65   | 	case PM_VAMPIRE_MAGE:
66   | #endif
67   | 	case PM_HUMAN_ZOMBIE:
68   | 	case PM_HUMAN_MUMMY:	mndx = PM_HUMAN;  break;
69   | 	case PM_GIANT_ZOMBIE:
70   | 	case PM_GIANT_MUMMY:	mndx = PM_GIANT;  break;
71   | 	case PM_ETTIN_ZOMBIE:
72   | 	case PM_ETTIN_MUMMY:	mndx = PM_ETTIN;  break;
73   | 	default:  break;
74   | 	}
75   | 	return mndx;
76   | }
77   | 
78   | /* convert monster index to chameleon index */
79   | int
80   | pm_to_cham(mndx)
81   | int mndx;
82   | {
83   | 	int mcham;
84   | 
85   | 	switch (mndx) {
86   | 	case PM_CHAMELEON:	mcham = CHAM_CHAMELEON; break;
87   | 	case PM_DOPPELGANGER:	mcham = CHAM_DOPPELGANGER; break;
88   | 	case PM_SANDESTIN:	mcham = CHAM_SANDESTIN; break;
89   | 	default: mcham = CHAM_ORDINARY; break;
90   | 	}
91   | 	return mcham;
92   | }
93   | 
94   | /* convert chameleon index to monster index */
95   | STATIC_VAR short cham_to_pm[] = {
96   | 		NON_PM,		/* placeholder for CHAM_ORDINARY */
97   | 		PM_CHAMELEON,
98   | 		PM_DOPPELGANGER,
99   | 		PM_SANDESTIN,
100  | };
101  | 
102  | /* return TRUE if the monster tends to revive */
103  | #define REVIVER(ptr)	(is_rider(ptr) || ptr->mlet == S_TROLL)
104  | 
105  | #define KEEPTRAITS(mon)	(mon->isshk || mon->mtame || \
106  | 			 (mon->data->geno & G_UNIQ) || REVIVER(mon->data))
107  | 
108  | /* Creates a monster corpse, a "special" corpse, or nothing if it doesn't
109  |  * leave corpses.  Monsters which leave "special" corpses should have
110  |  * G_NOCORPSE set in order to prevent wishing for one, finding tins of one,
111  |  * etc....
112  |  */
113  | STATIC_OVL struct obj *
114  | make_corpse(mtmp)
115  | register struct monst *mtmp;
116  | {
117  | 	register struct permonst *mdat = mtmp->data;
118  | 	int num;
119  | 	struct obj *obj = (struct obj *)0;
120  | 	int x = mtmp->mx, y = mtmp->my;
121  | 	int mndx = monsndx(mdat);
122  | 
123  | 	switch(mndx) {
124  | 	    case PM_GRAY_DRAGON:
125  | 	    case PM_SILVER_DRAGON:
126  | #if 0	/* DEFERRED */
127  | 	    case PM_SHIMMERING_DRAGON:
128  | #endif
129  | 	    case PM_RED_DRAGON:
130  | 	    case PM_ORANGE_DRAGON:
131  | 	    case PM_WHITE_DRAGON:
132  | 	    case PM_BLACK_DRAGON:
133  | 	    case PM_BLUE_DRAGON:
134  | 	    case PM_GREEN_DRAGON:
135  | 	    case PM_YELLOW_DRAGON:
136  | 		/* Make dragon scales.  This assumes that the order of the */
137  | 		/* dragons is the same as the order of the scales.	   */
138  | 		if (!rn2(mtmp->mrevived ? 20 : 3)) {
139  | 		    obj = mksobj_at(GRAY_DRAGON_SCALES +
140  | 				    monsndx(mdat)-PM_GRAY_DRAGON, x, y, FALSE);
141  | 		    obj->spe = 0;
142  | 		    obj->cursed = obj->blessed = FALSE;
143  | 		}
144  | 		goto default_1;
145  | 
146  | 	    case PM_WHITE_UNICORN:
147  | 	    case PM_GRAY_UNICORN:
148  | 	    case PM_BLACK_UNICORN:
149  | 		(void) mksobj_at(UNICORN_HORN, x, y, TRUE);
150  | 		goto default_1;
151  | 	    case PM_LONG_WORM:
152  | 		(void) mksobj_at(WORM_TOOTH, x, y, TRUE);
153  | 		goto default_1;
154  | 	    case PM_VAMPIRE:
155  | 	    case PM_VAMPIRE_LORD:
156  | 		/* include mtmp in the mkcorpstat() call */
157  | 		num = undead_to_corpse(mndx);
158  | 		obj = mkcorpstat(CORPSE, mtmp, &mons[num], x, y, TRUE);
159  | 		obj->age -= 100;		/* this is an *OLD* corpse */
160  | 		break;
161  | 	    case PM_KOBOLD_MUMMY:
162  | 	    case PM_DWARF_MUMMY:
163  | 	    case PM_GNOME_MUMMY:
164  | 	    case PM_ORC_MUMMY:
165  | 	    case PM_ELF_MUMMY:
166  | 	    case PM_HUMAN_MUMMY:
167  | 	    case PM_GIANT_MUMMY:
168  | 	    case PM_ETTIN_MUMMY:
169  | 	    case PM_KOBOLD_ZOMBIE:
170  | 	    case PM_DWARF_ZOMBIE:
171  | 	    case PM_GNOME_ZOMBIE:
172  | 	    case PM_ORC_ZOMBIE:
173  | 	    case PM_ELF_ZOMBIE:
174  | 	    case PM_HUMAN_ZOMBIE:
175  | 	    case PM_GIANT_ZOMBIE:
176  | 	    case PM_ETTIN_ZOMBIE:
177  | 		num = undead_to_corpse(mndx);
178  | 		obj = mkcorpstat(CORPSE, mtmp, &mons[num], x, y, TRUE);
179  | 		obj->age -= 100;		/* this is an *OLD* corpse */
180  | 		break;
181  | 	    case PM_IRON_GOLEM:
182  | 		num = d(2,6);
183  | 		while (num--)
184  | 			obj = mksobj_at(IRON_CHAIN, x, y, TRUE);
185  | 		mtmp->mnamelth = 0;
186  | 		break;
187  | 	    case PM_GLASS_GOLEM:
188  | 		num = d(2,4);   /* very low chance of creating all glass gems */
189  | 		while (num--)
190  | 			obj = mksobj_at((LAST_GEM + rnd(9)), x, y, TRUE);
191  | 		mtmp->mnamelth = 0;
192  | 		break;
193  | 	    case PM_CLAY_GOLEM:
194  | 		obj = mksobj_at(ROCK, x, y, FALSE);
195  | 		obj->quan = (long)(rn2(20) + 50);
196  | 		obj->owt = weight(obj);
197  | 		mtmp->mnamelth = 0;
198  | 		break;
199  | 	    case PM_STONE_GOLEM:
200  | 		obj = mkcorpstat(STATUE, (struct monst *)0,
201  | 			mdat, x, y, FALSE);
202  | 		break;
203  | 	    case PM_WOOD_GOLEM:
204  | 		num = d(2,4);
205  | 		while(num--) {
206  | 			obj = mksobj_at(QUARTERSTAFF, x, y, TRUE);
207  | 			if (obj && obj->oartifact) {	/* don't allow this */
208  | 				artifact_exists(obj, ONAME(obj), FALSE);
209  | 				Strcpy(ONAME(obj), "");  obj->onamelth = 0;
210  | 			}
211  | 		}
212  | 		mtmp->mnamelth = 0;
213  | 		break;
214  | 	    case PM_LEATHER_GOLEM:
215  | 		num = d(2,4);
216  | 		while(num--)
217  | 			obj = mksobj_at(LEATHER_ARMOR, x, y, TRUE);
218  | 		mtmp->mnamelth = 0;
219  | 		break;
220  | 	    case PM_GOLD_GOLEM:
221  | 		/* Good luck gives more coins */
222  | 		obj = mkgold((long)(200 - rnl(101)), x, y);
223  | 		mtmp->mnamelth = 0;
224  | 		break;
225  | 	    case PM_PAPER_GOLEM:
226  | 		num = d(2,3);
227  | 		while (num--)
228  | 			obj = mksobj_at(SCR_BLANK_PAPER, x, y, TRUE);
229  | 		mtmp->mnamelth = 0;
230  | 		break;
231  | 	    default_1:
232  | 	    default:
233  | 		if (mvitals[mndx].mvflags & G_NOCORPSE)
234  | 		    return (struct obj *)0;
235  | 		else	/* preserve the unique traits of some creatures */
236  | 		    obj = mkcorpstat(CORPSE, KEEPTRAITS(mtmp) ? mtmp : 0,
237  | 				     mdat, x, y, TRUE);
238  | 		break;
239  | 	}
240  | 	/* All special cases should precede the G_NOCORPSE check */
241  | 
242  | 	if (mtmp->mnamelth)
243  | 	    obj = oname(obj, NAME(mtmp));
244  | 
245  | #ifdef INVISIBLE_OBJECTS
246  | 	/* Invisible monster ==> invisible corpse */
247  | 	obj->oinvis = mtmp->minvis;
248  | #endif
249  | 
250  | 	stackobj(obj);
251  | 	newsym(x, y);
252  | 	return obj;
253  | }
254  | 
255  | #endif /* OVLB */
256  | #ifdef OVL1
257  | 
258  | #if 0
259  | /* part of the original warning code which was replaced in 3.3.1 */
260  | STATIC_OVL void
261  | warn_effects()
262  | {
263  |     if (warnlevel == 100) {
264  | 	if(!Blind && uwep &&
265  | 	    (warnlevel > lastwarnlev || moves > lastwarntime + warnDelay)) {
266  | 	    Your("%s %s!", aobjnam(uwep, "glow"),
267  | 		hcolor(light_blue));
268  | 	    lastwarnlev = warnlevel;
269  | 	    lastwarntime = moves;
270  | 	}
271  | 	warnlevel = 0;
272  | 	return;
273  |     }
274  | 
275  |     if (warnlevel >= SIZE(warnings))
276  | 	warnlevel = SIZE(warnings)-1;
277  |     if (!Blind &&
278  | 	    (warnlevel > lastwarnlev || moves > lastwarntime + warnDelay)) {
279  | 	const char *which, *what, *how;
280  | 	long rings = (EWarning & (LEFT_RING|RIGHT_RING));
281  | 
282  | 	if (rings) {
283  | 	    what = Hallucination ? "mood ring" : "ring";
284  | 	    how = "glows";	/* singular verb */
285  | 	    if (rings == LEFT_RING) {
286  | 		which = "left ";
287  | 	    } else if (rings == RIGHT_RING) {
288  | 		which = "right ";
289  | 	    } else {		/* both */
290  | 		which = "";
291  | 		what = (const char *) makeplural(what);
292  | 		how = "glow";	/* plural verb */
293  | 	    }
294  | 	    Your("%s%s %s %s!", which, what, how, hcolor(warnings[warnlevel]));
295  | 	} else {
296  | 	    if (Hallucination)
297  | 		Your("spider-sense is tingling...");
298  | 	    else
299  | 		You_feel("apprehensive as you sense a %s flash.",
300  | 		    warnings[warnlevel]);
301  | 	}
302  | 
303  | 	lastwarntime = moves;
304  | 	lastwarnlev = warnlevel;
305  |     }
306  | }
307  | #endif /* 0 */
308  | 
309  | /* check mtmp and water for compatibility, 0 (survived), 1 (drowned) */
310  | int
311  | minwater(mtmp)
312  | register struct monst *mtmp;
313  | {
314  |     boolean inpool, infountain;
315  | 
316  |     inpool = is_pool(mtmp->mx,mtmp->my) &&
317  | 	     !is_flyer(mtmp->data) && !is_floater(mtmp->data);
318  |     infountain = IS_FOUNTAIN(levl[mtmp->mx][mtmp->my].typ);
319  | 
320  | #ifdef STEED
321  | 	/* Flying and levitation keeps our steed out of the water */
322  | 	/* (but not water-walking or swimming) */
323  | 	if (mtmp == u.usteed && (Flying || Levitation))
324  | 		return (0);
325  | #endif
326  | 
327  |     /* Gremlin multiplying won't go on forever since the hit points
328  |      * keep going down, and when it gets to 1 hit point the clone
329  |      * function will fail.
330  |      */
331  |     if (mtmp->data == &mons[PM_GREMLIN] && (inpool || infountain) && rn2(3)) {
332  | 	if (split_mon(mtmp, (struct monst *)0))
333  | 	    dryup(mtmp->mx, mtmp->my, FALSE);
334  | 	if (inpool) water_damage(mtmp->minvent, FALSE, FALSE);
335  | 	return (0);
336  |     } else if (mtmp->data == &mons[PM_IRON_GOLEM] && inpool && !rn2(5)) {
337  | 	int dam = d(2,6);
338  | 	if (cansee(mtmp->mx,mtmp->my))
339  | 	    pline("%s rusts.", Monnam(mtmp));
340  | 	mtmp->mhp -= dam;
341  | 	if (mtmp->mhpmax > dam) mtmp->mhpmax -= dam;
342  | 	if (mtmp->mhp < 1) {
343  | 	    mondead(mtmp);
344  | 	    if (mtmp->mhp < 1) return (1);
345  | 	}
346  | 	water_damage(mtmp->minvent, FALSE, FALSE);
347  | 	return (0);
348  |     }
349  | 
350  |     if (inpool) {
351  | 	/* Most monsters drown in pools.  flooreffects() will take care of
352  | 	 * water damage to dead monsters' inventory, but survivors need to
353  | 	 * be handled here.  Swimmers are able to protect their stuff...
354  | 	 */
355  | 	if (!is_clinger(mtmp->data)
356  | 	    && !is_swimmer(mtmp->data) && !amphibious(mtmp->data)) {
357  | 	    if (cansee(mtmp->mx,mtmp->my)) {
358  | 		    pline("%s drowns.", Monnam(mtmp));
359  | 	    }
360  | 	    mondead(mtmp);
361  | 	    if (mtmp->mhp > 0) {
362  | 		rloc(mtmp);
363  | 		water_damage(mtmp->minvent, FALSE, FALSE);
364  | 		return 0;
365  | 	    }
366  | 	    return (1);
367  | 	}
368  |     } else {
369  | 	/* but eels have a difficult time outside */
370  | 	if (mtmp->data->mlet == S_EEL && !Is_waterlevel(&u.uz)) {
371  | 	    if(mtmp->mhp > 1) mtmp->mhp--;
372  | 	    mtmp->mflee = 1;
373  | 	    mtmp->mfleetim += 2;
374  | 	}
375  |     }
376  |     return (0);
377  | }
378  | 
379  | 
380  | int
381  | mcalcmove(mon)
382  | struct monst *mon;
383  | {
384  |     int mmove = mon->data->mmove;
385  | 
386  |     /* Note: MSLOW's `+ 1' prevents slowed speed 1 getting reduced to 0;
387  |      *	     MFAST's `+ 2' prevents hasted speed 1 from becoming a no-op;
388  |      *	     both adjustments have negligible effect on higher speeds.
389  |      */
390  |     if (mon->mspeed == MSLOW)
391  | 	mmove = (2 * mmove + 1) / 3;
392  |     else if (mon->mspeed == MFAST)
393  | 	mmove = (4 * mmove + 2) / 3;
394  | 
395  | #ifdef STEED
396  |     if (mon == u.usteed) {
397  | 	if (u.ugallop && flags.mv) {
398  | 	    /* average movement is 1.50 times normal */
399  | 	    mmove = ((rn2(2) ? 4 : 5) * mmove) / 3;
400  | 	}
401  |     }
402  | #endif
403  | 
404  |     return mmove;
405  | }
406  | 
407  | /* actions that happen once per ``turn'', regardless of each
408  |    individual monster's metabolism; some of these might need to
409  |    be reclassified to occur more in proportion with movement rate */
410  | void
411  | mcalcdistress()
412  | {
413  |     struct monst *mtmp;
414  | 
415  |     for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
416  | 	if (DEADMONSTER(mtmp)) continue;
417  | 
418  | 	/* regenerate hit points */
419  | 	mon_regen(mtmp, FALSE);
420  | 
421  | 	/* possibly polymorph shapechangers and lycanthropes */
422  | 	if (mtmp->cham && !rn2(6))
423  | 	    (void) newcham(mtmp, (struct permonst *)0);
424  | 	were_change(mtmp);
425  | 
426  | 	/* gradually time out temporary problems */
427  | 	if (mtmp->mblinded && !--mtmp->mblinded)
428  | 	    mtmp->mcansee = 1;
429  | 	if (mtmp->mfrozen && !--mtmp->mfrozen)
430  | 	    mtmp->mcanmove = 1;
431  | 	if (mtmp->mfleetim && !--mtmp->mfleetim)
432  | 	    mtmp->mflee = 0;
433  | 
434  | 	/* FIXME: mtmp->mlstmv ought to be updated here */
435  |     }
436  | }
437  | 
438  | int
439  | movemon()
440  | {
441  |     register struct monst *mtmp, *nmtmp;
442  |     register boolean somebody_can_move = FALSE;
443  | #if 0
444  |     /* part of the original warning code which was replaced in 3.3.1 */
445  |     warnlevel = 0;
446  | #endif
447  | 
448  |     /*
449  |     Some of you may remember the former assertion here that
450  |     because of deaths and other actions, a simple one-pass
451  |     algorithm wasn't possible for movemon.  Deaths are no longer
452  |     removed to the separate list fdmon; they are simply left in
453  |     the chain with hit points <= 0, to be cleaned up at the end
454  |     of the pass.
455  | 
456  |     The only other actions which cause monsters to be removed from
457  |     the chain are level migrations and losedogs().  I believe losedogs()
458  |     is a cleanup routine not associated with monster movements, and
459  |     monsters can only affect level migrations on themselves, not others
460  |     (hence the fetching of nmon before moving the monster).  Currently,
461  |     monsters can jump into traps, read cursed scrolls of teleportation,
462  |     and drink cursed potions of raise level to change levels.  These are
463  |     all reflexive at this point.  Should one monster be able to level
464  |     teleport another, this scheme would have problems.
465  |     */
466  | 
467  |     for(mtmp = fmon; mtmp; mtmp = nmtmp) {
468  | 	nmtmp = mtmp->nmon;
469  | 
470  | 	/* Find a monster that we have not treated yet.	 */
471  | 	if(DEADMONSTER(mtmp))
472  | 	    continue;
473  | 	if(mtmp->movement < NORMAL_SPEED)
474  | 	    continue;
475  | 
476  | 	mtmp->movement -= NORMAL_SPEED;
477  | 	if (mtmp->movement >= NORMAL_SPEED)
478  | 	    somebody_can_move = TRUE;
479  | 
480  | 	if (minwater(mtmp)) continue;
481  | 
482  | 	if (is_hider(mtmp->data)) {
483  | 	    /* unwatched mimics and piercers may hide again  [MRS] */
484  | 	    if(restrap(mtmp))   continue;
485  | 	    if(mtmp->m_ap_type == M_AP_FURNITURE ||
486  | 				mtmp->m_ap_type == M_AP_OBJECT)
487  | 		    continue;
488  | 	    if(mtmp->mundetected) continue;
489  | 	}
490  | 
491  | 	/* continue if the monster died fighting */
492  | 	if (Conflict && !mtmp->iswiz && mtmp->mcansee) {
493  | 	    /* Note:
494  | 	     *  Conflict does not take effect in the first round.
495  | 	     *  Therefore, A monster when stepping into the area will
496  | 	     *  get to swing at you.
497  | 	     *
498  | 	     *  The call to fightm() must be _last_.  The monster might
499  | 	     *  have died if it returns 1.
500  | 	     */
501  | 	    if (couldsee(mtmp->mx,mtmp->my) &&
502  | 		(distu(mtmp->mx,mtmp->my) <= BOLT_LIM*BOLT_LIM) &&
503  | 							fightm(mtmp))
504  | 		continue;	/* mon might have died */
505  | 	}
506  | 	if(dochugw(mtmp))		/* otherwise just move the monster */
507  | 	    continue;
508  |     }
509  | #if 0
510  |     /* part of the original warning code which was replaced in 3.3.1 */
511  |     if(warnlevel > 0)
512  | 	warn_effects();
513  | #endif
514  | 
515  |     if (any_light_source())
516  | 	vision_full_recalc = 1;	/* in case a mon moved with a light source */
517  |     dmonsfree();	/* remove all dead monsters */
518  | 
519  |     /* a monster may have levteleported player -dlc */
520  |     if (u.utotype) {
521  | 	deferred_goto();
522  | 	/* changed levels, so these monsters are dormant */
523  | 	somebody_can_move = FALSE;
524  |     }
525  | 
526  |     return somebody_can_move;
527  | }
528  | 
529  | #endif /* OVL1 */
530  | #ifdef OVLB
531  | 
532  | #define mstoning(obj)	(ofood(obj) && \
533  | 					(touch_petrifies(&mons[(obj)->corpsenm]) || \
534  | 					(obj)->corpsenm == PM_MEDUSA))
535  | 
536  | /*
537  |  * Maybe eat a metallic object (not just gold).
538  |  * Return value: 0 => nothing happened, 1 => monster ate something,
539  |  * 2 => monster died (it must have grown into a genocided form, but
540  |  * that can't happen at present because nothing which eats objects
541  |  * has young and old forms).
542  |  */
543  | int
544  | meatgold(mtmp)
545  | 	register struct monst *mtmp;
546  | {
547  | 	register struct obj *otmp;
548  | 	struct permonst *ptr;
549  | 	int poly, grow, heal, mstone;
550  | 
551  | 	/* If a pet, eating is handled separately, in dog.c */
552  | 	if (mtmp->mtame) return 0;
553  | 
554  | 	/* Eats topmost metal object if it is there */
555  | 	for (otmp = level.objects[mtmp->mx][mtmp->my];
556  | 						    otmp; otmp = otmp->nexthere)
557  | 	    if (is_metallic(otmp) && !obj_resists(otmp, 5, 95) &&
558  | 		touch_artifact(otmp,mtmp)) {
559  | 		if (mtmp->data == &mons[PM_RUST_MONSTER] && otmp->oerodeproof) {
560  | 		    if (canseemon(mtmp) && flags.verbose) {
561  | 			pline("%s eats %s!",
562  | 				Monnam(mtmp),
563  | 				distant_name(otmp,doname));
564  | 		    }
565  | 		    /* The object's rustproofing is gone now */
566  | 		    otmp->oerodeproof = 0;
567  | 		    mtmp->mstun = 1;
568  | 		    if (canseemon(mtmp) && flags.verbose) {
569  | 			pline("%s spits %s out in disgust!",
570  | 			      Monnam(mtmp), distant_name(otmp,doname));
571  | 		    }
572  | 		/* KMH -- Don't eat undigestable/choking objects */
573  | 		} else if (otmp->otyp != AMULET_OF_STRANGULATION &&
574  | 				otmp->otyp != RIN_SLOW_DIGESTION) {
575  | 		    if (cansee(mtmp->mx,mtmp->my) && flags.verbose)
576  | 			pline("%s eats %s!", Monnam(mtmp),
577  | 				distant_name(otmp,doname));
578  | 		    else if (flags.soundok && flags.verbose)
579  | 			You_hear("a crunching sound.");
580  | 		    mtmp->meating = otmp->owt/2 + 1;
581  | 		    /* Heal up to the object's weight in hp */
582  | 		    if (mtmp->mhp < mtmp->mhpmax) {
583  | 			mtmp->mhp += objects[otmp->otyp].oc_weight;
584  | 			if (mtmp->mhp > mtmp->mhpmax) mtmp->mhp = mtmp->mhpmax;
585  | 		    }
586  | 		    if(otmp == uball) {
587  | 			unpunish();
588  | 			delobj(otmp);
589  | 		    } else if (otmp == uchain) {
590  | 			unpunish();	/* frees uchain */
591  | 		    } else {
592  | 			poly = polyfodder(otmp);
593  | 			grow = mlevelgain(otmp);
594  | 			heal = mhealup(otmp);
595  | 			mstone = mstoning(otmp);
596  | 			delobj(otmp);
597  | 			ptr = mtmp->data;
598  | 			if (poly) {
599  | 			    if (newcham(mtmp, (struct permonst *)0))
600  | 				ptr = mtmp->data;
601  | 			} else if (grow) {
602  | 			    ptr = grow_up(mtmp, (struct monst *)0);
603  | 			} else if (mstone) {
604  | 			    if (poly_when_stoned(ptr)) {
605  | 				mon_to_stone(mtmp);
606  | 				ptr = mtmp->data;
607  | 			    } else if (!resists_ston(mtmp)) {
608  | 				if (canseemon(mtmp))
609  | 				    pline("%s turns to stone!", Monnam(mtmp));
610  | 				monstone(mtmp);
611  | 				ptr = (struct permonst *)0;
612  | 			    }
613  | 			} else if (heal) {
614  | 			    mtmp->mhp = mtmp->mhpmax;
615  | 			}
616  | 			if (!ptr) return 2;		 /* it died */
617  | 		    }
618  | 		    /* Left behind a pile? */
619  | 		    if(rnd(25) < 3) (void) mksobj_at(ROCK, mtmp->mx, mtmp->my, TRUE);
620  | 		    newsym(mtmp->mx, mtmp->my);
621  | 		    return 1;
622  | 		}
623  | 	    }
624  | 	return 0;
625  | }
626  | 
627  | int
628  | meatobj(mtmp)		/* for gelatinous cubes */
629  | 	register struct monst *mtmp;
630  | {
631  | 	register struct obj *otmp, *otmp2;
632  | 	struct permonst *ptr;
633  | 	int poly, grow, heal, count = 0, ecount = 0;
634  | 	char buf[BUFSZ];
635  | 
636  | 	buf[0] = '\0';
637  | 	/* If a pet, eating is handled separately, in dog.c */
638  | 	if (mtmp->mtame) return 0;
639  | 
640  | 	/* Eats organic objects, including cloth and wood, if there */
641  | 	/* Engulfs others, except huge rocks and metal attached to player */
642  | 	for (otmp = level.objects[mtmp->mx][mtmp->my]; otmp; otmp = otmp2) {
643  | 	    otmp2 = otmp->nexthere;
644  | 	    if (is_organic(otmp) && !obj_resists(otmp, 5, 95) &&
645  | 		    touch_artifact(otmp,mtmp)) {
646  | 		if (otmp->otyp == CORPSE && touch_petrifies(&mons[otmp->corpsenm]) &&
647  | 			!resists_ston(mtmp))
648  | 		    continue;
649  | 		if (otmp->otyp == AMULET_OF_STRANGULATION ||
650  | 				otmp->otyp == RIN_SLOW_DIGESTION)
651  | 		    continue;
652  | 		++count;
653  | 		if (cansee(mtmp->mx,mtmp->my) && flags.verbose)
654  | 		    pline("%s eats %s!", Monnam(mtmp),
655  | 			    distant_name(otmp, doname));
656  | 		else if (flags.soundok && flags.verbose)
657  | 		    You_hear("a slurping sound.");
658  | 		/* Heal up to the object's weight in hp */
659  | 		if (mtmp->mhp < mtmp->mhpmax) {
660  | 		    mtmp->mhp += objects[otmp->otyp].oc_weight;
661  | 		    if (mtmp->mhp > mtmp->mhpmax) mtmp->mhp = mtmp->mhpmax;
662  | 		}
663  | 		if (Has_contents(otmp)) {
664  | 		    register struct obj *otmp3;
665  | 		    /* contents of eaten containers become engulfed; this
666  | 		       is arbitrary, but otherwise g.cubes are too powerful */
667  | 		    while ((otmp3 = otmp->cobj) != 0) {
668  | 			obj_extract_self(otmp3);
669  | 			if (otmp->otyp == ICE_BOX && otmp3->otyp == CORPSE) {
670  | 			    otmp3->age = monstermoves - otmp3->age;
671  | 			    start_corpse_timeout(otmp3);
672  | 			}
673  | 			(void) mpickobj(mtmp, otmp3);
674  | 		    }
675  | 		}
676  | 		poly = polyfodder(otmp);
677  | 		grow = mlevelgain(otmp);
678  | 		heal = mhealup(otmp);
679  | 		delobj(otmp);		/* munch */
680  | 		ptr = mtmp->data;
681  | 		if (poly) {
682  | 		    if (newcham(mtmp, (struct permonst *)0)) ptr = mtmp->data;
683  | 		} else if (grow) {
684  | 		    ptr = grow_up(mtmp, (struct monst *)0);
685  | 		} else if (heal) {
686  | 		    mtmp->mhp = mtmp->mhpmax;
687  | 		}
688  | 		/* in case it polymorphed or died */
689  | 		if (ptr != &mons[PM_GELATINOUS_CUBE])
690  | 		    return !ptr ? 2 : 1;
691  | 	    } else if (otmp->oclass != ROCK_CLASS &&
692  | 				    otmp != uball && otmp != uchain) {
693  | 		++ecount;
694  | 		if (ecount == 1) {
695  | 			Sprintf(buf, "%s engulfs %s.", Monnam(mtmp),
696  | 			    distant_name(otmp,doname));
697  | 		} else if (ecount == 2)
698  | 			Sprintf(buf, "%s engulfs several objects.", Monnam(mtmp));
699  | 		obj_extract_self(otmp);
700  | 		(void) mpickobj(mtmp, otmp);	/* slurp */
701  | 	    }
702  | 	    /* Engulf & devour is instant, so don't set meating */
703  | 	    if (mtmp->minvis) newsym(mtmp->mx, mtmp->my);
704  | 	}
705  | 	if (ecount > 0) {
706  | 	    if (cansee(mtmp->mx, mtmp->my) && flags.verbose && buf[0])
707  | 		pline("%s", buf);
708  | 	    else if (flags.soundok && flags.verbose)
709  | 	    	You_hear("%s slurping sound%s.",
710  | 			ecount == 1 ? "a" : "several",
711  | 			ecount == 1 ? "" : "s");
712  | 	}
713  | 	return ((count > 0) || (ecount > 0)) ? 1 : 0;
714  | }
715  | 
716  | void
717  | mpickgold(mtmp)
718  | 	register struct monst *mtmp;
719  | {
720  |     register struct obj *gold;
721  | 
722  |     if ((gold = g_at(mtmp->mx, mtmp->my)) != 0) {
723  | 	mtmp->mgold += gold->quan;
724  | 	delobj(gold);
725  | 	if (cansee(mtmp->mx, mtmp->my) ) {
726  | 	    if (flags.verbose && !mtmp->isgd)
727  | 		pline("%s picks up some gold.", Monnam(mtmp));
728  | 	    newsym(mtmp->mx, mtmp->my);
729  | 	}
730  |     }
731  | }
732  | #endif /* OVLB */
733  | #ifdef OVL2
734  | 
735  | boolean
736  | mpickstuff(mtmp, str)
737  | 	register struct monst *mtmp;
738  | 	register const char *str;
739  | {
740  | 	register struct obj *otmp, *otmp2;
741  | 
742  | /*	prevent shopkeepers from leaving the door of their shop */
743  | 	if(mtmp->isshk && inhishop(mtmp)) return FALSE;
744  | 
745  | 	for(otmp = level.objects[mtmp->mx][mtmp->my]; otmp; otmp = otmp2) {
746  | 	    otmp2 = otmp->nexthere;
747  | /*	Nymphs take everything.  Most monsters don't pick up corpses. */
748  | 	    if (!str ? searches_for_item(mtmp,otmp) :
749  | 		  !!(index(str, otmp->oclass))) {
750  | 		if (otmp->otyp == CORPSE && (
751  | 		    is_rider(&mons[otmp->corpsenm]) ||
752  | 		    (touch_petrifies(&mons[otmp->corpsenm])
753  | 			&& !(mtmp->misc_worn_check & W_ARMG)) ||
754  | 		    (mtmp->data->mlet != S_NYMPH
755  | 			&& !touch_petrifies(&mons[otmp->corpsenm])
756  | 			&& otmp->corpsenm != PM_LIZARD
757  | 			&& !acidic(&mons[otmp->corpsenm]))
758  | 		   ))
759  | 			continue;
760  | 		if (!touch_artifact(otmp,mtmp)) continue;
761  | 		if (!can_carry(mtmp,otmp)) continue;
762  | 		if (is_pool(mtmp->mx,mtmp->my)) continue;
763  | #ifdef INVISIBLE_OBJECTS
764  | 		if (otmp->oinvis && !perceives(mtmp->data)) continue;
765  | #endif
766  | 		if (cansee(mtmp->mx,mtmp->my) && flags.verbose)
767  | 			pline("%s picks up %s.", Monnam(mtmp),
768  | 			      (distu(mtmp->my, mtmp->my) <= 5) ?
769  | 				doname(otmp) : distant_name(otmp, doname));
770  | 		obj_extract_self(otmp);
771  | 		/* unblock point after extract, before pickup */
772  | 		if (otmp->otyp == BOULDER)
773  | 		    unblock_point(otmp->ox,otmp->oy);	/* vision */
774  | 		(void) mpickobj(mtmp, otmp);	/* may merge and free otmp */
775  | 		m_dowear(mtmp, FALSE);
776  | 		newsym(mtmp->mx, mtmp->my);
777  | 		return TRUE;			/* pick only one object */
778  | 	    }
779  | 	}
780  | 	return FALSE;
781  | }
782  | 
783  | #endif /* OVL2 */
784  | #ifdef OVL0
785  | 
786  | int
787  | curr_mon_load(mtmp)
788  | register struct monst *mtmp;
789  | {
790  | 	register int curload = 0;
791  | 	register struct obj *obj;
792  | 
793  | 	for(obj = mtmp->minvent; obj; obj = obj->nobj) {
794  | 		if(obj->otyp != BOULDER || !throws_rocks(mtmp->data))
795  | 			curload += obj->owt;
796  | 	}
797  | 
798  | 	return curload;
799  | }
800  | 
801  | int
802  | max_mon_load(mtmp)
803  | register struct monst *mtmp;
804  | {
805  | 	register long maxload;
806  | 
807  | 	/* Base monster carrying capacity is equal to human maximum
808  | 	 * carrying capacity, or half human maximum if not strong.
809  | 	 * (for a polymorphed player, the value used would be the
810  | 	 * non-polymorphed carrying capacity instead of max/half max).
811  | 	 * This is then modified by the ratio between the monster weights
812  | 	 * and human weights.  Corpseless monsters are given a capacity
813  | 	 * proportional to their size instead of weight.
814  | 	 */
815  | 	if (!mtmp->data->cwt)
816  | 		maxload = (MAX_CARR_CAP * (long)mtmp->data->msize) / MZ_HUMAN;
817  | 	else if (!strongmonst(mtmp->data)
818  | 		|| (strongmonst(mtmp->data) && (mtmp->data->cwt > WT_HUMAN)))
819  | 		maxload = (MAX_CARR_CAP * (long)mtmp->data->cwt) / WT_HUMAN;
820  | 	else	maxload = MAX_CARR_CAP; /*strong monsters w/cwt <= WT_HUMAN*/
821  | 
822  | 	if (!strongmonst(mtmp->data)) maxload /= 2;
823  | 
824  | 	if (maxload < 1) maxload = 1;
825  | 
826  | 	return (int) maxload;
827  | }
828  | 
829  | /* for restricting monsters' object-pickup */
830  | boolean
831  | can_carry(mtmp,otmp)
832  | struct monst *mtmp;
833  | struct obj *otmp;
834  | {
835  | 	int otyp = otmp->otyp, newload = otmp->owt;
836  | 	struct permonst *mdat = mtmp->data;
837  | 
838  | 	if (notake(mdat)) return FALSE;		/* can't carry anything */
839  | 
840  | 	if (otyp == CORPSE && touch_petrifies(&mons[otmp->corpsenm]) &&
841  | 		!(mtmp->misc_worn_check & W_ARMG) && !resists_ston(mtmp))
842  | 	    return FALSE;
843  | 	if (objects[otyp].oc_material == SILVER && hates_silver(mdat) &&
844  | 		(otyp != BELL_OF_OPENING || !is_covetous(mdat)))
845  | 	    return FALSE;
846  | 
847  | #ifdef STEED
848  | 	/* Steeds don't pick up stuff (to avoid shop abuse) */
849  | 	if (mtmp == u.usteed) return (FALSE);
850  | #endif
851  | 	if (mtmp->isshk) return(TRUE); /* no limit */
852  | 	if (mtmp->mpeaceful && !mtmp->mtame) return(FALSE);
853  | 	/* otherwise players might find themselves obligated to violate
854  | 	 * their alignment if the monster takes something they need
855  | 	 */
856  | 
857  | 	/* special--boulder throwers carry unlimited amounts of boulders */
858  | 	if (throws_rocks(mdat) && otyp == BOULDER)
859  | 		return(TRUE);
860  | 
861  | 	/* nymphs deal in stolen merchandise, but not boulders or statues */
862  | 	if (mdat->mlet == S_NYMPH)
863  | 		return (boolean)(otmp->oclass != ROCK_CLASS);
864  | 
865  | 	if (curr_mon_load(mtmp) + newload > max_mon_load(mtmp)) return FALSE;
866  | 
867  | 	return(TRUE);
868  | }
869  | 
870  | /* return number of acceptable neighbour positions */
871  | int
872  | mfndpos(mon, poss, info, flag)
873  | 	register struct monst *mon;
874  | 	coord *poss;	/* coord poss[9] */
875  | 	long *info;	/* long info[9] */
876  | 	long flag;
877  | {
878  | 	struct permonst *mdat = mon->data;
879  | 	register xchar x,y,nx,ny;
880  | 	register int cnt = 0;
881  | 	register uchar ntyp;
882  | 	uchar nowtyp;
883  | 	boolean wantpool,poolok,lavaok,nodiag;
884  | 	int maxx, maxy;
885  | 
886  | 	x = mon->mx;
887  | 	y = mon->my;
888  | 	nowtyp = levl[x][y].typ;
889  | 
890  | 	nodiag = (mdat == &mons[PM_GRID_BUG]);
891  | 	wantpool = mdat->mlet == S_EEL;
892  | 	poolok = is_flyer(mdat) || is_clinger(mdat) ||
893  | 		 (is_swimmer(mdat) && !wantpool);
894  | 	lavaok = is_flyer(mdat) || is_clinger(mdat) || likes_lava(mdat);
895  | 
896  | nexttry:	/* eels prefer the water, but if there is no water nearby,
897  | 		   they will crawl over land */
898  | 	if(mon->mconf) {
899  | 		flag |= ALLOW_ALL;
900  | 		flag &= ~NOTONL;
901  | 	}
902  | 	if(!mon->mcansee)
903  | 		flag |= ALLOW_SSM;
904  | 	maxx = min(x+1,COLNO-1);
905  | 	maxy = min(y+1,ROWNO-1);
906  | 	for(nx = max(1,x-1); nx <= maxx; nx++)
907  | 	  for(ny = max(0,y-1); ny <= maxy; ny++) {
908  | 	    if(nx == x && ny == y) continue;
909  | 	    if(IS_ROCK(ntyp = levl[nx][ny].typ) &&
910  | 	       !((flag & ALLOW_WALL) && may_passwall(nx,ny)) &&
911  | 	       !((flag & ALLOW_DIG) && may_dig(nx,ny))) continue;
912  | 	    /* KMH -- Added iron bars */
913  | 	    if (ntyp == IRONBARS &&
914  | 	    	!((flag & ALLOW_WALL) && may_passwall(nx,ny))) continue;
915  | 	    if(IS_DOOR(ntyp) && !amorphous(mdat) &&
916  | 	       ((levl[nx][ny].doormask & D_CLOSED && !(flag & OPENDOOR)) ||
917  | 		(levl[nx][ny].doormask & D_LOCKED && !(flag & UNLOCKDOOR))
918  | 	       ) && !(flag & (ALLOW_WALL|ALLOW_DIG|BUSTDOOR))) continue;
919  | 	    if(nx != x && ny != y && (nodiag ||
920  | #ifdef REINCARNATION
921  | 	       ((IS_DOOR(nowtyp) &&
922  | 		 ((levl[x][y].doormask & ~D_BROKEN) || Is_rogue_level(&u.uz))) ||
923  | 		(IS_DOOR(ntyp) &&
924  | 		 ((levl[nx][ny].doormask & ~D_BROKEN) || Is_rogue_level(&u.uz))))
925  | #else
926  | 	       ((IS_DOOR(nowtyp) && (levl[x][y].doormask & ~D_BROKEN)) ||
927  | 		(IS_DOOR(ntyp) && (levl[nx][ny].doormask & ~D_BROKEN)))
928  | #endif
929  | 	       ))
930  | 		continue;
931  | 	    if((is_pool(nx,ny) == wantpool || poolok) &&
932  | 	       (lavaok || !is_lava(nx,ny))) {
933  | 		int dispx, dispy;
934  | 		boolean monseeu = (mon->mcansee && (!Invis || perceives(mdat)));
935  | 		boolean checkobj = OBJ_AT(nx,ny);
936  | 
937  | 		/* Displacement also displaces the Elbereth/scare monster,
938  | 		 * as long as you are visible.
939  | 		 */
940  | 		if(Displaced && monseeu && (mon->mux==nx) && (mon->muy==ny)) {
941  | 		    dispx = u.ux;
942  | 		    dispy = u.uy;
943  | 		} else {
944  | 		    dispx = nx;
945  | 		    dispy = ny;
946  | 		}
947  | 
948  | 		info[cnt] = 0;
949  | 		if ((checkobj || Displaced) && onscary(dispx, dispy, mon)) {
950  | 		    if(!(flag & ALLOW_SSM)) continue;
951  | 		    info[cnt] |= ALLOW_SSM;
952  | 		}
953  | 		if((nx == u.ux && ny == u.uy) ||
954  | 		   (nx == mon->mux && ny == mon->muy)) {
955  | 			if (nx == u.ux && ny == u.uy) {
956  | 				/* If it's right next to you, it found you,
957  | 				 * displaced or no.  We must set mux and muy
958  | 				 * right now, so when we return we can tell
959  | 				 * that the ALLOW_U means to attack _you_ and
960  | 				 * not the image.
961  | 				 */
962  | 				mon->mux = u.ux;
963  | 				mon->muy = u.uy;
964  | 			}
965  | 			if(!(flag & ALLOW_U)) continue;
966  | 			info[cnt] |= ALLOW_U;
967  | 		} else {
968  | 			if(MON_AT(nx, ny)) {
969  | 				struct monst *mtmp2 = m_at(nx, ny);
970  | 				long mmflag = flag | mm_aggression(mon, mtmp2);
971  | 
972  | 				if (!(mmflag & ALLOW_M)) continue;
973  | 				info[cnt] |= ALLOW_M;
974  | 				if (mtmp2->mtame) {
975  | 					if (!(mmflag & ALLOW_TM)) continue;
976  | 					info[cnt] |= ALLOW_TM;
977  | 				}
978  | 			}
979  | 			/* Note: ALLOW_SANCT only prevents movement, not */
980  | 			/* attack, into a temple. */
981  | 			if(level.flags.has_temple &&
982  | 			   *in_rooms(nx, ny, TEMPLE) &&
983  | 			   !*in_rooms(x, y, TEMPLE) &&
984  | 			   in_your_sanctuary((struct monst *)0, nx, ny)) {
985  | 				if(!(flag & ALLOW_SANCT)) continue;
986  | 				info[cnt] |= ALLOW_SANCT;
987  | 			}
988  | 		}
989  | 		if(checkobj && sobj_at(CLOVE_OF_GARLIC, nx, ny)) {
990  | 			if(flag & NOGARLIC) continue;
991  | 			info[cnt] |= NOGARLIC;
992  | 		}
993  | 		if(checkobj && sobj_at(BOULDER, nx, ny)) {
994  | 			if(!(flag & ALLOW_ROCK)) continue;
995  | 			info[cnt] |= ALLOW_ROCK;
996  | 		}
997  | 		if (monseeu && onlineu(nx,ny)) {
998  | 			if(flag & NOTONL) continue;
999  | 			info[cnt] |= NOTONL;
1000 | 		}
1001 | 		if (nx != x && ny != y && bad_rock(mdat, x, ny)
1002 | 			    && bad_rock(mdat, nx, y)
1003 | 			    && (bigmonst(mdat) || (curr_mon_load(mon) > 600)))
1004 | 			continue;
1005 | 		/* The monster avoids a particular type of trap if it's familiar
1006 | 		 * with the trap type.  Pets get ALLOW_TRAPS and checking is
1007 | 		 * done in dogmove.c.  In either case, "harmless" traps are
1008 | 		 * neither avoided nor marked in info[].
1009 | 		 */
1010 | 		{ register struct trap *ttmp = t_at(nx, ny);
1011 | 		    if(ttmp) {
1012 | 			if(ttmp->ttyp >= TRAPNUM || ttmp->ttyp == 0)  {
1013 | impossible("A monster looked at a very strange trap of type %d.", ttmp->ttyp);
1014 | 			    continue;
1015 | 			}
1016 | 			if ((ttmp->ttyp != RUST_TRAP
1017 | 					|| mdat == &mons[PM_IRON_GOLEM])
1018 | 				&& ttmp->ttyp != STATUE_TRAP
1019 | 				&& ((ttmp->ttyp != PIT
1020 | 				    && ttmp->ttyp != SPIKED_PIT
1021 | 				    && ttmp->ttyp != TRAPDOOR
1022 | 				    && ttmp->ttyp != HOLE)
1023 | 				      || (!is_flyer(mdat)
1024 | 				    && !is_floater(mdat)
1025 | 				    && !is_clinger(mdat))
1026 | 				      || In_sokoban(&u.uz))
1027 | 				&& (ttmp->ttyp != SLP_GAS_TRAP ||
1028 | 				    !resists_sleep(mon))
1029 | 				&& (ttmp->ttyp != BEAR_TRAP ||
1030 | 				    (mdat->msize > MZ_SMALL &&
1031 | 				     !amorphous(mdat) && !is_flyer(mdat)))
1032 | 				&& (ttmp->ttyp != FIRE_TRAP ||
1033 | 				    !resists_fire(mon))
1034 | 				&& (ttmp->ttyp != SQKY_BOARD || !is_flyer(mdat))
1035 | 				&& (ttmp->ttyp != WEB || (!amorphous(mdat) &&
1036 | 				    !webmaker(mdat)))
1037 | 			) {
1038 | 			    if (!(flag & ALLOW_TRAPS)) {
1039 | 				if (mon->mtrapseen & (1L << (ttmp->ttyp - 1)))
1040 | 				    continue;
1041 | 			    }
1042 | 			    info[cnt] |= ALLOW_TRAPS;
1043 | 			}
1044 | 		    }
1045 | 		}
1046 | 		poss[cnt].x = nx;
1047 | 		poss[cnt].y = ny;
1048 | 		cnt++;
1049 | 	    }
1050 | 	}
1051 | 	if(!cnt && wantpool && !is_pool(x,y)) {
1052 | 		wantpool = FALSE;
1053 | 		goto nexttry;
1054 | 	}
1055 | 	return(cnt);
1056 | }
1057 | 
1058 | #endif /* OVL0 */
1059 | #ifdef OVL1
1060 | 
1061 | /* Monster against monster special attacks; for the specified monster
1062 |    combinations, this allows one monster to attack another adjacent one
1063 |    in the absence of Conflict.  There is no provision for targetting
1064 |    other monsters; just hand to hand fighting when they happen to be
1065 |    next to each other. */
1066 | STATIC_OVL long
1067 | mm_aggression(magr, mdef)
1068 | struct monst *magr,	/* monster that is currently deciding where to move */
1069 | 	     *mdef;	/* another monster which is next to it */
1070 | {
1071 | 	/* supposedly purple worms are attracted to shrieking because they
1072 | 	   like to eat shriekers, so attack the latter when feasible */
1073 | 	if (magr->data == &mons[PM_PURPLE_WORM] &&
1074 | 		mdef->data == &mons[PM_SHRIEKER])
1075 | 	    return ALLOW_M|ALLOW_TM;
1076 | 	/* Various other combinations such as dog vs cat, cat vs rat, and
1077 | 	   elf vs orc have been suggested.  For the time being we don't
1078 | 	   support those. */
1079 | 	return 0L;
1080 | }
1081 | 
1082 | boolean
1083 | monnear(mon, x, y)
1084 | register struct monst *mon;
1085 | register int x,y;
1086 | /* Is the square close enough for the monster to move or attack into? */
1087 | {
1088 | 	register int distance = dist2(mon->mx, mon->my, x, y);
1089 | 	if (distance==2 && mon->data==&mons[PM_GRID_BUG]) return 0;
1090 | 	return((boolean)(distance < 3));
1091 | }
1092 | 
1093 | /* really free dead monsters */
1094 | void
1095 | dmonsfree()
1096 | {
1097 |     struct monst **mtmp;
1098 |     int count = 0;
1099 | 
1100 |     for (mtmp = &fmon; *mtmp;) {
1101 | 	if ((*mtmp)->mhp <= 0) {
1102 | 	    struct monst *freetmp = *mtmp;
1103 | 	    *mtmp = (*mtmp)->nmon;
1104 | 	    dealloc_monst(freetmp);
1105 | 	    count++;
1106 | 	} else
1107 | 	    mtmp = &(*mtmp)->nmon;
1108 |     }
1109 | 
1110 |     if (count != iflags.purge_monsters)
1111 | 	impossible("dmonsfree: %d removed doesn't match %d pending",
1112 | 		   count, iflags.purge_monsters);
1113 |     iflags.purge_monsters = 0;
1114 | }
1115 | 
1116 | #endif /* OVL1 */
1117 | #ifdef OVLB
1118 | 
1119 | /* called when monster is moved to larger structure */
1120 | void
1121 | replmon(mtmp, mtmp2)
1122 | register struct monst *mtmp, *mtmp2;
1123 | {
1124 |     struct obj *otmp;
1125 | 
1126 |     /* transfer the monster's inventory */
1127 |     for (otmp = mtmp2->minvent; otmp; otmp = otmp->nobj) {
1128 | #ifdef DEBUG
1129 | 	if (otmp->where != OBJ_MINVENT || otmp->ocarry != mtmp)
1130 | 	    panic("replmon: minvent inconsistency");
1131 | #endif
1132 | 	otmp->ocarry = mtmp2;
1133 |     }
1134 |     mtmp->minvent = 0;
1135 | 
1136 |     /* remove the old monster from the map and from `fmon' list */
1137 |     relmon(mtmp);
1138 | 
1139 |     /* finish adding its replacement */
1140 | #ifdef STEED
1141 |     if (mtmp == u.usteed) ; else	/* don't place steed onto the map */
1142 | #endif
1143 |     place_monster(mtmp2, mtmp2->mx, mtmp2->my);
1144 |     if (mtmp2->wormno)	    /* update level.monsters[wseg->wx][wseg->wy] */
1145 | 	place_wsegs(mtmp2); /* locations to mtmp2 not mtmp. */
1146 |     if (emits_light(mtmp2->data)) {
1147 | 	/* since this is so rare, we don't have any `mon_move_light_source' */
1148 | 	new_light_source(mtmp2->mx, mtmp2->my,
1149 | 			 emits_light(mtmp2->data),
1150 | 			 LS_MONSTER, (genericptr_t)mtmp2);
1151 | 	/* here we rely on the fact that `mtmp' hasn't actually been deleted */
1152 | 	del_light_source(LS_MONSTER, (genericptr_t)mtmp);
1153 |     }
1154 |     mtmp2->nmon = fmon;
1155 |     fmon = mtmp2;
1156 |     if (u.ustuck == mtmp) u.ustuck = mtmp2;
1157 | #ifdef STEED
1158 |     if (u.usteed == mtmp) u.usteed = mtmp2;
1159 | #endif
1160 |     if (mtmp2->isshk) replshk(mtmp,mtmp2);
1161 | 
1162 |     /* discard the old monster */
1163 |     dealloc_monst(mtmp);
1164 | }
1165 | 
1166 | /* release mon from display and monster list */
1167 | void
1168 | relmon(mon)
1169 | register struct monst *mon;
1170 | {
1171 | 	register struct monst *mtmp;
1172 | 
1173 | 	if (fmon == (struct monst *)0)  panic ("relmon: no fmon available.");
1174 | 
1175 | 	remove_monster(mon->mx, mon->my);
1176 | 
1177 | 	if(mon == fmon) fmon = fmon->nmon;
1178 | 	else {
1179 | 		for(mtmp = fmon; mtmp && mtmp->nmon != mon; mtmp = mtmp->nmon) ;
1180 | 		if(mtmp)    mtmp->nmon = mon->nmon;
1181 | 		else	    panic("relmon: mon not in list.");
1182 | 	}
1183 | }
1184 | 
1185 | /* remove effects of mtmp from other data structures */
1186 | STATIC_OVL void
1187 | m_detach(mtmp, mptr)
1188 | struct monst *mtmp;
1189 | struct permonst *mptr;	/* reflects mtmp->data _prior_ to mtmp's death */
1190 | {
1191 | 	if(mtmp->mleashed) m_unleash(mtmp);
1192 | 	    /* to prevent an infinite relobj-flooreffects-hmon-killed loop */
1193 | 	mtmp->mtrapped = 0;
1194 | 	mtmp->mhp = 0; /* simplify some tests: force mhp to 0 */
1195 | 	relobj(mtmp, 0, FALSE);
1196 | 	remove_monster(mtmp->mx, mtmp->my);
1197 | 	if (emits_light(mptr))
1198 | 	    del_light_source(LS_MONSTER, (genericptr_t)mtmp);
1199 | 	newsym(mtmp->mx,mtmp->my);
1200 | 	unstuck(mtmp);
1201 | 	fill_pit(mtmp->mx, mtmp->my);
1202 | 
1203 | 	if(mtmp->isshk) shkgone(mtmp);
1204 | 	if(mtmp->wormno) wormgone(mtmp);
1205 | 	iflags.purge_monsters++;
1206 | }
1207 | 
1208 | /* find the worn amulet of life saving which will save a monster */
1209 | struct obj *
1210 | mlifesaver(mon)
1211 | struct monst *mon;
1212 | {
1213 | 	if (!nonliving(mon->data)) {
1214 | 	    struct obj *otmp = which_armor(mon, W_AMUL);
1215 | 
1216 | 	    if (otmp && otmp->otyp == AMULET_OF_LIFE_SAVING)
1217 | 		return otmp;
1218 | 	}
1219 | 	return (struct obj *)0;
1220 | }
1221 | 
1222 | STATIC_OVL void
1223 | lifesaved_monster(mtmp)
1224 | struct monst *mtmp;
1225 | {
1226 | 	struct obj *lifesave = mlifesaver(mtmp);
1227 | 
1228 | 	if (lifesave) {
1229 | 		/* not canseemon; amulets are on the head, so you don't want */
1230 | 		/* to show this for a long worm with only a tail visible. */
1231 | 		/* Nor do you check invisibility, because glowing and disinte- */
1232 | 		/* grating amulets are always visible. */
1233 | 		if (cansee(mtmp->mx, mtmp->my)) {
1234 | 			pline("But wait...");
1235 | 			pline("%s medallion begins to glow!",
1236 | 				s_suffix(Monnam(mtmp)));
1237 | 			makeknown(AMULET_OF_LIFE_SAVING);
1238 | 			pline("%s looks much better!", Monnam(mtmp));
1239 | 			pline_The("medallion crumbles to dust!");
1240 | 		}
1241 | 		m_useup(mtmp, lifesave);
1242 | 		mtmp->mcanmove = 1;
1243 | 		mtmp->mfrozen = 0;
1244 | 		if (mtmp->mtame && !mtmp->isminion) {
1245 | 			struct edog *edog = EDOG(mtmp);
1246 | 			if (edog->hungrytime < moves+500)
1247 | 				edog->hungrytime = moves+500;
1248 | 			if (edog->mhpmax_penalty) {
1249 | 				/* was starving */
1250 | 				mtmp->mhpmax += edog->mhpmax_penalty;
1251 | 				edog->mhpmax_penalty = 0;
1252 | 			}
1253 | 			wary_dog(mtmp, FALSE);
1254 | 		}
1255 | 		if (mtmp->mhpmax <= 0) mtmp->mhpmax = 10;
1256 | 		mtmp->mhp = mtmp->mhpmax;
1257 | 		if (mvitals[monsndx(mtmp->data)].mvflags & G_GENOD) {
1258 | 			if (cansee(mtmp->mx, mtmp->my))
1259 | 			    pline("Unfortunately %s is still genocided...",
1260 | 				mon_nam(mtmp));
1261 | 		} else
1262 | 			return;
1263 | 	}
1264 | 	mtmp->mhp = 0;
1265 | }
1266 | 
1267 | void
1268 | mondead(mtmp)
1269 | register struct monst *mtmp;
1270 | {
1271 | 	struct permonst *mptr;
1272 | 	int tmp;
1273 | 
1274 | 	if(mtmp->isgd) {
1275 | 		/* if we're going to abort the death, it *must* be before
1276 | 		 * the m_detach or there will be relmon problems later */
1277 | 		if(!grddead(mtmp)) return;
1278 | 	}
1279 | 	lifesaved_monster(mtmp);
1280 | 	if (mtmp->mhp > 0) return;
1281 | 
1282 | #ifdef STEED
1283 | 	/* Player is thrown from his steed when it dies */
1284 | 	if (mtmp == u.usteed)
1285 | 		dismount_steed(DISMOUNT_GENERIC);
1286 | #endif
1287 | 
1288 | 	mptr = mtmp->data;		/* save this for m_detach() */
1289 | 	/* restore chameleon, lycanthropes to true form at death */
1290 | 	if (mtmp->cham)
1291 | 	    set_mon_data(mtmp, &mons[cham_to_pm[mtmp->cham]], -1);
1292 | 	else if (mtmp->data == &mons[PM_WEREJACKAL])
1293 | 	    set_mon_data(mtmp, &mons[PM_HUMAN_WEREJACKAL], -1);
1294 | 	else if (mtmp->data == &mons[PM_WEREWOLF])
1295 | 	    set_mon_data(mtmp, &mons[PM_HUMAN_WEREWOLF], -1);
1296 | 	else if (mtmp->data == &mons[PM_WERERAT])
1297 | 	    set_mon_data(mtmp, &mons[PM_HUMAN_WERERAT], -1);
1298 | 
1299 | 	/* if MAXMONNO monsters of a given type have died, and it
1300 | 	 * can be done, extinguish that monster.
1301 | 	 *
1302 | 	 * mvitals[].died does double duty as total number of dead monsters
1303 | 	 * and as experience factor for the player killing more monsters.
1304 | 	 * this means that a dragon dying by other means reduces the
1305 | 	 * experience the player gets for killing a dragon directly; this
1306 | 	 * is probably not too bad, since the player likely finagled the
1307 | 	 * first dead dragon via ring of conflict or pets, and extinguishing
1308 | 	 * based on only player kills probably opens more avenues of abuse
1309 | 	 * for rings of conflict and such.
1310 | 	 */
1311 | 	tmp = monsndx(mtmp->data);
1312 | 	if (mvitals[tmp].died < 255) mvitals[tmp].died++;
1313 | #ifdef MAIL
1314 | 	/* if the mail daemon dies, no more mail delivery.  -3. */
1315 | 	if (tmp == PM_MAIL_DAEMON) mvitals[tmp].mvflags |= G_GENOD;
1316 | #endif
1317 | 
1318 | #ifdef KOPS
1319 | 	if (mtmp->data->mlet == S_KOP) {
1320 | 	    /* Dead Kops may come back. */
1321 | 	    switch(rnd(5)) {
1322 | 		case 1:	     /* returns near the stairs */
1323 | 			(void) makemon(mtmp->data,xdnstair,ydnstair,NO_MM_FLAGS);
1324 | 			break;
1325 | 		case 2:	     /* randomly */
1326 | 			(void) makemon(mtmp->data,0,0,NO_MM_FLAGS);
1327 | 			break;
1328 | 		default:
1329 | 			break;
1330 | 	    }
1331 | 	}
1332 | #endif
1333 | 	if(mtmp->iswiz) wizdead();
1334 | 	if(mtmp->data->msound == MS_NEMESIS) nemdead();
1335 | 	if(glyph_is_invisible(levl[mtmp->mx][mtmp->my].glyph))
1336 | 	    unmap_object(mtmp->mx, mtmp->my);
1337 | 	m_detach(mtmp, mptr);
1338 | }
1339 | 
1340 | STATIC_OVL boolean
1341 | corpse_chance(mon)
1342 | struct monst *mon;
1343 | {
1344 | 	struct permonst *mdat = mon->data;
1345 | 	int i, tmp;
1346 | 
1347 | 
1348 | 	if (mdat == &mons[PM_VLAD_THE_IMPALER] || mdat->mlet == S_LICH) {
1349 | 		if (cansee(mon->mx, mon->my))
1350 | 			pline("%s body crumbles into dust.",
1351 | 				s_suffix(Monnam(mon)));
1352 | 		return FALSE;
1353 | 	}
1354 | 
1355 | 	/* Gas spores always explode upon death */
1356 | 	for(i = 0; i < NATTK; i++) {
1357 | 	    if (mdat->mattk[i].aatyp == AT_BOOM) {
1358 | 	    	if (mdat->mattk[i].damn)
1359 | 	    	    tmp = d((int)mdat->mattk[i].damn,
1360 | 	    	    		(int)mdat->mattk[i].damd);
1361 | 	    	else if(mdat->mattk[i].damd)
1362 | 	    	    tmp = d((int)mdat->mlevel+1, (int)mdat->mattk[i].damd);
1363 | 	    	else tmp = 0;
1364 | 	    	Sprintf(killer_buf, "%s explosion", s_suffix(mdat->mname));
1365 | 	    	killer = killer_buf;
1366 | 	    	killer_format = KILLED_BY_AN;
1367 | 	    	explode(mon->mx, mon->my, -1, tmp, MON_EXPLODE); 
1368 | 	    	return (FALSE);
1369 | 	    }
1370 |   	}
1371 | 
1372 | 	/* must duplicate this below check in xkilled() since it results in
1373 | 	 * creating no objects as well as no corpse
1374 | 	 */
1375 | 	if (
1376 | #ifdef REINCARNATION
1377 | 		 Is_rogue_level(&u.uz) ||
1378 | #endif
1379 | 	   (level.flags.graveyard && is_undead(mdat) && rn2(3)))
1380 | 		return FALSE;
1381 | 
1382 | 	if (bigmonst(mdat) || mdat == &mons[PM_LIZARD]
1383 | 		   || is_golem(mdat)
1384 | 		   || is_mplayer(mdat)
1385 | 		   || is_rider(mdat))
1386 | 		return TRUE;
1387 | 	return (boolean) (!rn2((int)
1388 | 		(2 + ((int)(mdat->geno & G_FREQ)<2) + verysmall(mdat))));
1389 | }
1390 | 
1391 | /* drop (perhaps) a cadaver and remove monster */
1392 | void
1393 | mondied(mdef)
1394 | register struct monst *mdef;
1395 | {
1396 | 	mondead(mdef);
1397 | 	if (mdef->mhp > 0) return;	/* lifesaved */
1398 | 
1399 | 	if (corpse_chance(mdef))
1400 | 		(void) make_corpse(mdef);
1401 | }
1402 | 
1403 | /* monster disappears, not dies */
1404 | void
1405 | mongone(mdef)
1406 | register struct monst *mdef;
1407 | {
1408 | #ifdef STEED
1409 | 	/* Player is thrown from his steed when it disappears */
1410 | 	if (mdef == u.usteed)
1411 | 		dismount_steed(DISMOUNT_GENERIC);
1412 | #endif
1413 | 
1414 | 	discard_minvent(mdef);	/* release monster's inventory */
1415 | 	mdef->mgold = 0L;
1416 | 	m_detach(mdef, mdef->data);
1417 | }
1418 | 
1419 | /* drop a statue or rock and remove monster */
1420 | void
1421 | monstone(mdef)
1422 | register struct monst *mdef;
1423 | {
1424 | 	struct obj *otmp, *obj;
1425 | 	xchar x = mdef->mx, y = mdef->my;
1426 | 
1427 | 	/* we have to make the statue before calling mondead, to be able to
1428 | 	 * put inventory in it, and we have to check for lifesaving before
1429 | 	 * making the statue....
1430 | 	 */
1431 | 	lifesaved_monster(mdef);
1432 | 	if (mdef->mhp > 0) return;
1433 | 
1434 | 	mdef->mtrapped = 0;	/* (see m_detach) */
1435 | 
1436 | 	if ((int)mdef->data->msize > MZ_TINY ||
1437 | 		    !rn2(2 + ((int) (mdef->data->geno & G_FREQ) > 2))) {
1438 | 		otmp = mkcorpstat(STATUE, KEEPTRAITS(mdef) ? mdef : 0,
1439 | 				  mdef->data, x, y, FALSE);
1440 | 		if (mdef->mnamelth) otmp = oname(otmp, NAME(mdef));
1441 | 		/* some objects may end up outside the statue */
1442 | 		while ((obj = mdef->minvent) != 0) {
1443 | 		    obj_extract_self(obj);
1444 | 		    obj->owornmask = 0L;
1445 | 		    if (obj->otyp == BOULDER ||
1446 | #if 0				/* monsters don't carry statues */
1447 |      (obj->otyp == STATUE && mons[obj->corpsenm].msize >= mdef->data->msize) ||
1448 | #endif
1449 | 				obj_resists(obj, 0, 0)) {
1450 | 			if (flooreffects(obj, x, y, "fall")) continue;
1451 | 			place_object(obj, x, y);
1452 | 		    } else {
1453 | 			if (obj->lamplit) end_burn(obj, TRUE);
1454 | 			add_to_container(otmp, obj);
1455 | 		    }
1456 | 		}
1457 | 		if (mdef->mgold) {
1458 | 			struct obj *au;
1459 | 			au = mksobj(GOLD_PIECE, FALSE, FALSE);
1460 | 			au->quan = mdef->mgold;
1461 | 			au->owt = weight(au);
1462 | 			add_to_container(otmp, au);
1463 | 			mdef->mgold = 0;
1464 | 		}
1465 | 		/* Archeologists should not break unique statues */
1466 | 		if (mdef->data->geno & G_UNIQ)
1467 | 			otmp->spe = 1;
1468 | 		otmp->owt = weight(otmp);
1469 | 	} else
1470 | 		otmp = mksobj_at(ROCK, x, y, TRUE);
1471 | 
1472 | 	stackobj(otmp);
1473 | 	/* mondead() already does this, but we must do it before the newsym */
1474 | 	if(glyph_is_invisible(levl[x][y].glyph))
1475 | 	    unmap_object(x, y);
1476 | 	if (cansee(x, y)) newsym(x,y);
1477 | 	mondead(mdef);
1478 | }
1479 | 
1480 | /* another monster has killed the monster mdef */
1481 | void
1482 | monkilled(mdef, fltxt, how)
1483 | register struct monst *mdef;
1484 | const char *fltxt;
1485 | int how;
1486 | {
1487 | 	boolean be_sad = FALSE;		/* true if unseen pet is killed */
1488 | 
1489 | 	if ((mdef->wormno ? worm_known(mdef) : cansee(mdef->mx, mdef->my))
1490 | 		&& fltxt)
1491 | 	    pline("%s is %s%s%s!", Monnam(mdef),
1492 | 			nonliving(mdef->data) ? "destroyed" : "killed",
1493 | 		    *fltxt ? " by the " : "",
1494 | 		    fltxt
1495 | 		 );
1496 | 	else
1497 | 	    be_sad = (mdef->mtame != 0);
1498 | 
1499 | 	/* no corpses if digested or disintegrated */
1500 | 	if(how == AD_DGST || how == -AD_RBRE)
1501 | 	    mondead(mdef);
1502 | 	else
1503 | 	    mondied(mdef);
1504 | 
1505 | 	if (be_sad && mdef->mhp <= 0)
1506 | 	    You("have a sad feeling for a moment, then it passes.");
1507 | }
1508 | 
1509 | void
1510 | unstuck(mtmp)
1511 | register struct monst *mtmp;
1512 | {
1513 | 	if(u.ustuck == mtmp) {
1514 | 		if(u.uswallow){
1515 | 			u.ux = mtmp->mx;
1516 | 			u.uy = mtmp->my;
1517 | 			u.uswallow = 0;
1518 | 			u.uswldtim = 0;
1519 | 			if (Punished) placebc();
1520 | 			vision_full_recalc = 1;
1521 | 			docrt();
1522 | 		}
1523 | 		u.ustuck = 0;
1524 | 	}
1525 | }
1526 | 
1527 | void
1528 | killed(mtmp)
1529 | register struct monst *mtmp;
1530 | {
1531 | 	xkilled(mtmp, 1);
1532 | }
1533 | 
1534 | /* the player has killed the monster mtmp */
1535 | void
1536 | xkilled(mtmp, dest)
1537 | 	register struct monst *mtmp;
1538 | /*
1539 |  * Dest=1, normal; dest=0, don't print message; dest=2, don't drop corpse
1540 |  * either; dest=3, message but no corpse
1541 |  */
1542 | 	int	dest;
1543 | {
1544 | 	register int tmp, x = mtmp->mx, y = mtmp->my;
1545 | 	register struct permonst *mdat;
1546 | 	int mndx;
1547 | 	register struct obj *otmp;
1548 | 	register struct trap *t;
1549 | 	boolean redisp = FALSE;
1550 | 	boolean wasinside = u.uswallow && (u.ustuck == mtmp);
1551 | 
1552 | 
1553 | 	/* KMH, conduct */
1554 | 	u.uconduct.killer++;
1555 | 
1556 | 	if (dest & 1) {
1557 | 	    if(!wasinside && !canspotmon(mtmp))
1558 | 		You("destroy it!");
1559 | 	    else {
1560 | 		You("destroy %s!",
1561 | 			mtmp->mtame
1562 | 			    ? x_monnam(mtmp, ARTICLE_THE, "poor",
1563 | 				mtmp->mnamelth ? SUPPRESS_SADDLE : 0, FALSE)
1564 | 			    : mon_nam(mtmp));
1565 | 	    }
1566 | 	}
1567 | 
1568 | 	if (mtmp->mtrapped &&
1569 | 	    ((t = t_at(x, y)) && (t->ttyp == PIT || t->ttyp == SPIKED_PIT)) &&
1570 | 	    sobj_at(BOULDER, x, y))
1571 | 		dest ^= 2; /*
1572 | 			    * Prevent corpses/treasure being created "on top"
1573 | 			    * of the boulder that is about to fall in. This is
1574 | 			    * out of order, but cannot be helped unless this
1575 | 			    * whole routine is rearranged.
1576 | 			    */
1577 | 
1578 | 	/* your pet knows who just killed it...watch out */
1579 | 	if (mtmp->mtame && !mtmp->isminion) EDOG(mtmp)->killed_by_u = 1;
1580 | 
1581 | 	/* dispose of monster and make cadaver */
1582 | 	if(stoned) monstone(mtmp);
1583 | 	else mondead(mtmp);
1584 | 
1585 | 	if (mtmp->mhp > 0) { /* monster lifesaved */
1586 | 		/* Cannot put the non-visible lifesaving message in
1587 | 		 * lifesaved_monster() since the message appears only when you
1588 | 		 * kill it (as opposed to visible lifesaving which always
1589 | 		 * appears).
1590 | 		 */
1591 | 		stoned = FALSE;
1592 | 		if (!cansee(x,y)) pline("Maybe not...");
1593 | 		return;
1594 | 	}
1595 | 
1596 | 	mdat = mtmp->data; /* note: mondead can change mtmp->data */
1597 | 	mndx = monsndx(mdat);
1598 | 
1599 | 	if (stoned) {
1600 | 		stoned = FALSE;
1601 | 		goto cleanup;
1602 | 	}
1603 | 
1604 | 	if((dest & 2)
1605 | #ifdef REINCARNATION
1606 | 		 || Is_rogue_level(&u.uz)
1607 | #endif
1608 | 	   || (level.flags.graveyard && is_undead(mdat) && rn2(3)))
1609 | 		goto cleanup;
1610 | 
1611 | #ifdef MAIL
1612 | 	if(mdat == &mons[PM_MAIL_DAEMON]) {
1613 | 		stackobj(mksobj_at(SCR_MAIL, x, y, FALSE));
1614 | 		redisp = TRUE;
1615 | 	}
1616 | #endif
1617 | 	if(!accessible(x, y) && !is_pool(x, y)) {
1618 | 	    /* might be mimic in wall or corpse in lava */
1619 | 	    redisp = TRUE;
1620 | 	    if(wasinside) spoteffects(TRUE);
1621 | 	} else if(x != u.ux || y != u.uy) {
1622 | 		/* might be here after swallowed */
1623 | 		if (!rn2(6) && !(mvitals[mndx].mvflags & G_NOCORPSE)
1624 | #ifdef KOPS
1625 | 					&& mdat->mlet != S_KOP
1626 | #endif
1627 | 							) {
1628 | 			int typ;
1629 | 
1630 | 			otmp = mkobj_at(RANDOM_CLASS, x, y, TRUE);
1631 | 			/* Don't create large objects from small monsters */
1632 | 			typ = otmp->otyp;
1633 | 			if (mdat->msize < MZ_HUMAN && typ != FOOD_RATION
1634 | 			    && typ != LEASH
1635 | 			    && typ != FIGURINE
1636 | 			    && (otmp->owt > 3 ||
1637 | 				objects[typ].oc_big /*oc_bimanual/oc_bulky*/ ||
1638 | 				is_spear(otmp) || is_pole(otmp) ||
1639 | 				typ == MORNING_STAR)) {
1640 | 			    delobj(otmp);
1641 | 			} else redisp = TRUE;
1642 | 		}
1643 | 		/* Whether or not it always makes a corpse is, in theory,
1644 | 		 * different from whether or not the corpse is "special";
1645 | 		 * if we want both, we have to specify it explicitly.
1646 | 		 */
1647 | 		if (corpse_chance(mtmp))
1648 | 			(void) make_corpse(mtmp);
1649 | 	}
1650 | 	if(redisp) newsym(x,y);
1651 | cleanup:
1652 | 	/* punish bad behaviour */
1653 | 	if(is_human(mdat) && (!always_hostile(mdat) && mtmp->malign <= 0) &&
1654 | 	   (mndx < PM_ARCHEOLOGIST || mndx > PM_WIZARD) &&
1655 | 	   u.ualign.type != A_CHAOTIC) {
1656 | 		HTelepat &= ~INTRINSIC;
1657 | 		change_luck(-2);
1658 | 		You("murderer!");
1659 | 		if (Blind && !Blind_telepat)
1660 | 		    see_monsters(); /* Can't sense monsters any more. */
1661 | 	}
1662 | 	if((mtmp->mpeaceful && !rn2(2)) || mtmp->mtame)	change_luck(-1);
1663 | 	if (is_unicorn(mdat) &&
1664 | 				sgn(u.ualign.type) == sgn(mdat->maligntyp)) {
1665 | 		change_luck(-5);
1666 | 		You_feel("guilty...");
1667 | 	}
1668 | 
1669 | 	/* give experience points */
1670 | 	tmp = experience(mtmp, (int)mvitals[mndx].died + 1);
1671 | 	more_experienced(tmp, 0);
1672 | 	newexplevel();		/* will decide if you go up */
1673 | 
1674 | 	/* adjust alignment points */
1675 | 	if (mdat->msound == MS_LEADER) {		/* REAL BAD! */
1676 | 	    adjalign(-(u.ualign.record+(int)ALIGNLIM/2));
1677 | 	    pline("That was %sa bad idea...",
1678 | 	    		u.uevent.qcompleted ? "probably " : "");
1679 | 	} else if (mdat->msound == MS_NEMESIS)	/* Real good! */
1680 | 	    adjalign((int)(ALIGNLIM/4));
1681 | 	else if (mdat->msound == MS_GUARDIAN) {	/* Bad */
1682 | 	    adjalign(-(int)(ALIGNLIM/8));
1683 | 	    if (!Hallucination) pline("That was probably a bad idea...");
1684 | 	    else pline("Whoopsie-daisy!");
1685 | 	}else if (mtmp->ispriest) {
1686 | 		adjalign((p_coaligned(mtmp)) ? -2 : 2);
1687 | 		/* cancel divine protection for killing your priest */
1688 | 		if (p_coaligned(mtmp)) u.ublessed = 0;
1689 | 		if (mdat->maligntyp == A_NONE)
1690 | 			adjalign((int)(ALIGNLIM / 4));		/* BIG bonus */
1691 | 	} else if (mtmp->mtame) {
1692 | 		adjalign(-15);	/* bad!! */
1693 | 		/* your god is mighty displeased... */
1694 | 		if (!Hallucination) You_hear("the rumble of distant thunder...");
1695 | 		else You_hear("the studio audience applaud!");
1696 | 	} else if (mtmp->mpeaceful)
1697 | 		adjalign(-5);
1698 | 
1699 | 	/* malign was already adjusted for u.ualign.type and randomization */
1700 | 	adjalign(mtmp->malign);
1701 | }
1702 | 
1703 | /* changes the monster into a stone monster of the same type */
1704 | /* this should only be called when poly_when_stoned() is true */
1705 | void
1706 | mon_to_stone(mtmp)
1707 |     register struct monst *mtmp;
1708 | {
1709 |     if(mtmp->data->mlet == S_GOLEM) {
1710 | 	/* it's a golem, and not a stone golem */
1711 | 	if(canseemon(mtmp))
1712 | 	    pline("%s solidifies...", Monnam(mtmp));
1713 | 	if (newcham(mtmp, &mons[PM_STONE_GOLEM])) {
1714 | 	    if(canseemon(mtmp))
1715 | 		pline("Now it's %s.", an(mtmp->data->mname));
1716 | 	} else {
1717 | 	    if(canseemon(mtmp))
1718 | 		pline("... and returns to normal.");
1719 | 	}
1720 |     } else
1721 | 	impossible("Can't polystone %s!", a_monnam(mtmp));
1722 | }
1723 | 
1724 | void
1725 | mnexto(mtmp)	/* Make monster mtmp next to you (if possible) */
1726 | 	struct monst *mtmp;
1727 | {
1728 | 	coord mm;
1729 | 
1730 | #ifdef STEED
1731 | 	if (mtmp == u.usteed) {
1732 | 		/* Keep your steed in sync with you instead */
1733 | 		mtmp->mx = u.ux;
1734 | 		mtmp->my = u.uy;
1735 | 		return;
1736 | 	}
1737 | #endif
1738 | 
1739 | 	if(!enexto(&mm, u.ux, u.uy, mtmp->data)) return;
1740 | 	rloc_to(mtmp, mm.x, mm.y);
1741 | 	return;
1742 | }
1743 | 
1744 | /* mnearto()
1745 |  * Put monster near (or at) location if possible.
1746 |  * Returns:
1747 |  *	1 - if a monster was moved from x, y to put mtmp at x, y.
1748 |  *	0 - in most cases.
1749 |  */
1750 | boolean
1751 | mnearto(mtmp,x,y,move_other)
1752 | register struct monst *mtmp;
1753 | xchar x, y;
1754 | boolean move_other;	/* make sure mtmp gets to x, y! so move m_at(x, y) */
1755 | {
1756 | 	struct monst *othermon = (struct monst *)0;
1757 | 	xchar newx, newy;
1758 | 	coord mm;
1759 | 
1760 | 	if ((mtmp->mx == x) && (mtmp->my == y)) return(FALSE);
1761 | 
1762 | 	if (move_other && (othermon = m_at(x, y))) {
1763 | 		if (othermon->wormno)
1764 | 			remove_worm(othermon);
1765 | 		else
1766 | 			remove_monster(x, y);
1767 | 	}
1768 | 
1769 | 	newx = x;
1770 | 	newy = y;
1771 | 
1772 | 	if (!goodpos(newx, newy, mtmp)) {
1773 | 		/* actually we have real problems if enexto ever fails.
1774 | 		 * migrating_mons that need to be placed will cause
1775 | 		 * no end of trouble.
1776 | 		 */
1777 | 		if (!enexto(&mm, newx, newy, mtmp->data)) return(FALSE);
1778 | 		newx = mm.x; newy = mm.y;
1779 | 	}
1780 | 
1781 | 	rloc_to(mtmp, newx, newy);
1782 | 
1783 | 	if (move_other && othermon) {
1784 | 	    othermon->mx = othermon->my = 0;
1785 | 	    (void) mnearto(othermon, x, y, FALSE);
1786 | 	    if ((othermon->mx != x) || (othermon->my != y))
1787 | 		return(TRUE);
1788 | 	}
1789 | 
1790 | 	return(FALSE);
1791 | }
1792 | 
1793 | 
1794 | static const char *poiseff[] = {
1795 | 
1796 | 	" feel weaker", "r brain is on fire",
1797 | 	"r judgement is impaired", "r muscles won't obey you",
1798 | 	" feel very sick", " break out in hives"
1799 | };
1800 | 
1801 | void
1802 | poisontell(typ)
1803 | 
1804 | 	int	typ;
1805 | {
1806 | 	pline("You%s.", poiseff[typ]);
1807 | }
1808 | 
1809 | void
1810 | poisoned(string, typ, pname, fatal)
1811 | register const char *string, *pname;
1812 | register int  typ, fatal;
1813 | {
1814 | 	register int i, plural;
1815 | 	boolean thrown_weapon = !strncmp(string, "poison", 6);
1816 | 		/* admittedly a kludge... */
1817 | 
1818 | 	if(strcmp(string, "blast") && !thrown_weapon) {
1819 | 	    /* 'blast' has already given a 'poison gas' message */
1820 | 	    /* so have "poison arrow", "poison dart", etc... */
1821 | 	    plural = (string[strlen(string) - 1] == 's')? 1 : 0;
1822 | 	    /* avoid "The" Orcus's sting was poisoned... */
1823 | 	    pline("%s%s %s poisoned!", isupper(*string) ? "" : "The ",
1824 | 			string, plural ? "were" : "was");
1825 | 	}
1826 | 
1827 | 	if(Poison_resistance) {
1828 | 		if(!strcmp(string, "blast")) shieldeff(u.ux, u.uy);
1829 | 		pline_The("poison doesn't seem to affect you.");
1830 | 		return;
1831 | 	}
1832 | 	i = rn2(fatal + 20*thrown_weapon);
1833 | 	if(i == 0 && typ != A_CHA) {
1834 | 		u.uhp = -1;
1835 | 		pline_The("poison was deadly...");
1836 | 	} else if(i <= 5) {
1837 | 		/* Check that a stat change was made */
1838 | 		if (adjattrib(typ, thrown_weapon ? -1 : -rn1(3,3), 1))
1839 |   		    pline("You%s!", poiseff[typ]);
1840 | 	} else {
1841 | 		i = thrown_weapon ? rnd(6) : rn1(10,6);
1842 | 		if(Half_physical_damage) i = (i+1) / 2;
1843 | 		losehp(i, pname, KILLED_BY_AN);
1844 | 	}
1845 | 	if(u.uhp < 1) {
1846 | 		killer_format = KILLED_BY_AN;
1847 | 		killer = pname;
1848 | 		/* "Poisoned by a poisoned ___" is redundant */
1849 | 		done(thrown_weapon ? DIED : POISONING);
1850 | 	}
1851 | 	(void) encumber_msg();
1852 | }
1853 | 
1854 | /* monster responds to player action; not the same as a passive attack */
1855 | /* assumes reason for response has been tested, and response _must_ be made */
1856 | void
1857 | m_respond(mtmp)
1858 | register struct monst *mtmp;
1859 | {
1860 |     if(mtmp->data->msound == MS_SHRIEK) {
1861 | 	if(flags.soundok) {
1862 | 	    pline("%s shrieks.", Monnam(mtmp));
1863 | 	    stop_occupation();
1864 | 	}
1865 | 	if (!rn2(10)) {
1866 | 	    if (!rn2(13))
1867 | 		(void) makemon(&mons[PM_PURPLE_WORM], 0, 0, NO_MM_FLAGS);
1868 | 	    else
1869 | 		(void) makemon((struct permonst *)0, 0, 0, NO_MM_FLAGS);
1870 | 
1871 | 	}
1872 | 	aggravate();
1873 |     }
1874 |     if(mtmp->data == &mons[PM_MEDUSA] && !mtmp->mcan) {
1875 | 	register int i;
1876 | 	for(i = 0; i < NATTK; i++)
1877 | 	     if(mtmp->data->mattk[i].aatyp == AT_GAZE) {
1878 | 		 (void) gazemu(mtmp, &mtmp->data->mattk[i]);
1879 | 		 break;
1880 | 	     }
1881 |     }
1882 | }
1883 | 
1884 | #endif /* OVLB */
1885 | #ifdef OVL2
1886 | 
1887 | void
1888 | setmangry(mtmp)
1889 | register struct monst *mtmp;
1890 | {
1891 | 	mtmp->mstrategy &= ~STRAT_WAITMASK;
1892 | 	if(!mtmp->mpeaceful) return;
1893 | 	if(mtmp->mtame) return;
1894 | 	mtmp->mpeaceful = 0;
1895 | 	if(mtmp->ispriest) {
1896 | 		if(p_coaligned(mtmp)) adjalign(-5); /* very bad */
1897 | 		else adjalign(2);
1898 | 	} else
1899 | 		adjalign(-1);		/* attacking peaceful monsters is bad */
1900 | 	if (couldsee(mtmp->mx, mtmp->my)) {
1901 | 		if (humanoid(mtmp->data) || mtmp->isshk || mtmp->isgd)
1902 | 		    pline("%s gets angry!", Monnam(mtmp));
1903 | 		else if (flags.verbose && flags.soundok) growl(mtmp);
1904 | 	}
1905 | 
1906 | 	/* attacking your own quest leader will anger his or her guardians */
1907 | 	if (!flags.mon_moving &&	/* should always be the case here */
1908 | 		mtmp->data == &mons[quest_info(MS_LEADER)]) {
1909 | 	    struct monst *mon;
1910 | 	    struct permonst *q_guardian = &mons[quest_info(MS_GUARDIAN)];
1911 | 	    int got_mad = 0;
1912 | 
1913 | 	    /* guardians will sense this attack even if they can't see it */
1914 | 	    for (mon = fmon; mon; mon = mon->nmon)
1915 | 		if (!DEADMONSTER(mon) && mon->data == q_guardian && mon->mpeaceful) {
1916 | 		    mon->mpeaceful = 0;
1917 | 		    if (canseemon(mon)) ++got_mad;
1918 | 		}
1919 | 	    if (got_mad && !Hallucination)
1920 | 		pline_The("%s appear%s to be angry too...",
1921 | 		      got_mad == 1 ? q_guardian->mname :
1922 | 				    makeplural(q_guardian->mname),
1923 | 		      got_mad == 1 ? "s" : "");
1924 | 	}
1925 | }
1926 | 
1927 | void
1928 | wakeup(mtmp)
1929 | register struct monst *mtmp;
1930 | {
1931 | 	mtmp->msleeping = 0;
1932 | 	mtmp->meating = 0;	/* assume there's no salvagable food left */
1933 | 	setmangry(mtmp);
1934 | 	if(mtmp->m_ap_type) seemimic(mtmp);
1935 | }
1936 | 
1937 | /* Wake up nearby monsters. */
1938 | void
1939 | wake_nearby()
1940 | {
1941 | 	register struct monst *mtmp;
1942 | 
1943 | 	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
1944 | 	    if (!DEADMONSTER(mtmp) && distu(mtmp->mx,mtmp->my) < u.ulevel*20) {
1945 | 		mtmp->msleeping = 0;
1946 | 		if (mtmp->mtame && !mtmp->isminion)
1947 | 		    EDOG(mtmp)->whistletime = moves;
1948 | 	    }
1949 | 	}
1950 | }
1951 | 
1952 | /* Wake up monsters near some particular location. */
1953 | void
1954 | wake_nearto(x, y, distance)
1955 | register int x, y, distance;
1956 | {
1957 | 	register struct monst *mtmp;
1958 | 
1959 | 	for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
1960 | 	    if (!DEADMONSTER(mtmp) && mtmp->msleeping && (distance == 0 ||
1961 | 				 dist2(mtmp->mx, mtmp->my, x, y) < distance))
1962 | 		mtmp->msleeping = 0;
1963 | 	}
1964 | }
1965 | 
1966 | /* NOTE: we must check for mimicry before calling this routine */
1967 | void
1968 | seemimic(mtmp)
1969 | register struct monst *mtmp;
1970 | {
1971 | 	/*
1972 | 	 *  Discovered mimics don't block light.
1973 | 	 */
1974 | 	if ((mtmp->m_ap_type == M_AP_FURNITURE &&
1975 | 		(mtmp->mappearance==S_hcdoor || mtmp->mappearance==S_vcdoor))||
1976 | 	    (mtmp->m_ap_type == M_AP_OBJECT && mtmp->mappearance == BOULDER))
1977 | 	    unblock_point(mtmp->mx,mtmp->my);
1978 | 
1979 | 	mtmp->m_ap_type = M_AP_NOTHING;
1980 | 	mtmp->mappearance = 0;
1981 | 	newsym(mtmp->mx,mtmp->my);
1982 | }
1983 | 
1984 | /* force all chameleons to become normal */
1985 | void
1986 | rescham()
1987 | {
1988 | 	register struct monst *mtmp;
1989 | 	int mcham;
1990 | 
1991 | 	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
1992 | 		if (DEADMONSTER(mtmp)) continue;
1993 | 		mcham = (int) mtmp->cham;
1994 | 		if (mcham) {
1995 | 			mtmp->cham = CHAM_ORDINARY;
1996 | 			(void) newcham(mtmp, &mons[cham_to_pm[mcham]]);
1997 | 		}
1998 | 		if(is_were(mtmp->data) && mtmp->data->mlet != S_HUMAN)
1999 | 			new_were(mtmp);
2000 | 		if(mtmp->m_ap_type && cansee(mtmp->mx, mtmp->my)) {
2001 | 			seemimic(mtmp);
2002 | 			/* we pretend that the mimic doesn't */
2003 | 			/* know that it has been unmasked.   */
2004 | 			mtmp->msleeping = 1;
2005 | 		}
2006 | 	}
2007 | }
2008 | 
2009 | /* Let the chameleons change again -dgk */
2010 | void
2011 | restartcham()
2012 | {
2013 | 	register struct monst *mtmp;
2014 | 
2015 | 	for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
2016 | 		if (DEADMONSTER(mtmp)) continue;
2017 | 		mtmp->cham = pm_to_cham(monsndx(mtmp->data));
2018 | 		if (mtmp->data->mlet == S_MIMIC && mtmp->msleeping &&
2019 | 				cansee(mtmp->mx, mtmp->my)) {
2020 | 			set_mimic_sym(mtmp);
2021 | 			newsym(mtmp->mx,mtmp->my);
2022 | 		}
2023 | 	}
2024 | }
2025 | 
2026 | /* called when restoring a monster from a saved level; protection
2027 |    against shape-changing might be different now than it was at the
2028 |    time the level was saved. */
2029 | void
2030 | restore_cham(mon)
2031 | struct monst *mon;
2032 | {
2033 | 	int mcham;
2034 | 
2035 | 	if (Protection_from_shape_changers) {
2036 | 	    mcham = (int) mon->cham;
2037 | 	    if (mcham) {
2038 | 		mon->cham = CHAM_ORDINARY;
2039 | 		(void) newcham(mon, &mons[cham_to_pm[mcham]]);
2040 | 	    } else if (is_were(mon->data) && !is_human(mon->data)) {
2041 | 		new_were(mon);
2042 | 	    }
2043 | 	} else {
2044 | 	    mon->cham = pm_to_cham(monsndx(mon->data));
2045 | 	}
2046 | }
2047 | 
2048 | /* unwatched hiders may hide again; if so, a 1 is returned.  */
2049 | STATIC_OVL boolean
2050 | restrap(mtmp)
2051 | register struct monst *mtmp;
2052 | {
2053 | 	if(mtmp->cham || mtmp->mcan || mtmp->m_ap_type ||
2054 | 	   cansee(mtmp->mx, mtmp->my) || rn2(3) || (mtmp == u.ustuck))
2055 | 		return(FALSE);
2056 | 
2057 | 	if(mtmp->data->mlet == S_MIMIC) {
2058 | 		set_mimic_sym(mtmp);
2059 | 		return(TRUE);
2060 | 	} else
2061 | 	    if(levl[mtmp->mx][mtmp->my].typ == ROOM)  {
2062 | 		mtmp->mundetected = 1;
2063 | 		return(TRUE);
2064 | 	    }
2065 | 
2066 | 	return(FALSE);
2067 | }
2068 | 
2069 | short *animal_list = 0;		/* list of PM values for animal monsters */
2070 | int animal_list_count;
2071 | 
2072 | void
2073 | mon_animal_list(construct)
2074 | boolean construct;
2075 | {
2076 | 	if (construct) {
2077 | 	    short animal_temp[SPECIAL_PM];
2078 | 	    int i, n;
2079 | 
2080 | 	 /* if (animal_list) impossible("animal_list already exists"); */
2081 | 
2082 | 	    for (n = 0, i = LOW_PM; i < SPECIAL_PM; i++)
2083 | 		if (is_animal(&mons[i])) animal_temp[n++] = i;
2084 | 	 /* if (n == 0) animal_temp[n++] = NON_PM; */
2085 | 
2086 | 	    animal_list = (short *)alloc(n * sizeof *animal_list);
2087 | 	    (void) memcpy((genericptr_t)animal_list,
2088 | 			  (genericptr_t)animal_temp,
2089 | 			  n * sizeof *animal_list);
2090 | 	    animal_list_count = n;
2091 | 	} else {	/* release */
2092 | 	    if (animal_list) free((genericptr_t)animal_list), animal_list = 0;
2093 | 	    animal_list_count = 0;
2094 | 	}
2095 | }
2096 | 
2097 | STATIC_OVL int
2098 | pick_animal()
2099 | {
2100 | 	if (!animal_list) mon_animal_list(TRUE);
2101 | 
2102 | 	return animal_list[rn2(animal_list_count)];
2103 | }
2104 | 
2105 | STATIC_OVL int
2106 | select_newcham_form(mon)
2107 | struct monst *mon;
2108 | {
2109 | 	int mndx = NON_PM;
2110 | 
2111 | 	switch (mon->cham) {
2112 | 	    case CHAM_SANDESTIN:
2113 | 		if (rn2(7)) mndx = pick_nasty();
2114 | 		break;
2115 | 	    case CHAM_DOPPELGANGER:
2116 | 		if (!rn2(7)) mndx = pick_nasty();
2117 | 		else if (rn2(3)) mndx = rn1(PM_WIZARD - PM_ARCHEOLOGIST + 1,
2118 | 					    PM_ARCHEOLOGIST);
2119 | 		break;
2120 | 	    case CHAM_CHAMELEON:
2121 | 		if (!rn2(3)) mndx = pick_animal();
2122 | 		break;
2123 | 	    case CHAM_ORDINARY:
2124 | 		break;
2125 | 	}
2126 | 	if (mndx == NON_PM) mndx = rn1(SPECIAL_PM - LOW_PM, LOW_PM);
2127 | 	return mndx;
2128 | }
2129 | 
2130 | /* make a chameleon look like a new monster; returns 1 if it actually changed */
2131 | int
2132 | newcham(mtmp, mdat)
2133 | struct monst *mtmp;
2134 | struct permonst *mdat;
2135 | {
2136 | 	int mhp, hpn, hpd;
2137 | 	int mndx, tryct;
2138 | 	struct permonst *olddata = mtmp->data;
2139 | 
2140 | 	/* mdat = 0 -> caller wants a random monster shape */
2141 | 	tryct = 0;
2142 | 	if (mdat == 0) {
2143 | 	    while (++tryct <= 100) {
2144 | 		mndx = select_newcham_form(mtmp);
2145 | 		mdat = &mons[mndx];
2146 | 		if ((mvitals[mndx].mvflags & G_GENOD) != 0 ||
2147 | 			is_placeholder(mdat)) continue;
2148 | 		/* polyok rules out all M2_PNAME and M2_WERE's;
2149 | 		   select_newcham_form might deliberately pick a player
2150 | 		   character type, so we can't arbitrarily rule out all
2151 | 		   human forms any more */
2152 | 		if (is_mplayer(mdat) || (!is_human(mdat) && polyok(mdat)))
2153 | 		    break;
2154 | 	    }
2155 | 	    if (tryct > 100) return 0;	/* Should never happen */
2156 | 	} else if (mvitals[monsndx(mdat)].mvflags & G_GENOD)
2157 | 	    return(0);	/* passed in mdat is genocided */
2158 | 
2159 | 	if(is_male(mdat)) {
2160 | 		if(mtmp->female) mtmp->female = FALSE;
2161 | 	} else if (is_female(mdat)) {
2162 | 		if(!mtmp->female) mtmp->female = TRUE;
2163 | 	} else if (!is_neuter(mdat)) {
2164 | 		if(!rn2(10)) mtmp->female = !mtmp->female;
2165 | 	}
2166 | 
2167 | 	if (In_endgame(&u.uz) && is_mplayer(olddata)) {
2168 | 		/* mplayers start out as "Foo the Bar", but some of the
2169 | 		 * titles are inappropriate when polymorphed, particularly
2170 | 		 * into the opposite sex.  players don't use ranks when
2171 | 		 * polymorphed, so dropping the rank for mplayers seems
2172 | 		 * reasonable.
2173 | 		 */
2174 | 		char *p = index(NAME(mtmp), ' ');
2175 | 		if (p) {
2176 | 			*p = '\0';
2177 | 			mtmp->mnamelth = p - NAME(mtmp) + 1;
2178 | 		}
2179 | 	}
2180 | 
2181 | 	if(mdat == mtmp->data) return(0);	/* still the same monster */
2182 | 
2183 | 	if(mtmp->wormno) {			/* throw tail away */
2184 | 		wormgone(mtmp);
2185 | 		place_monster(mtmp, mtmp->mx, mtmp->my);
2186 | 	}
2187 | 
2188 | 	hpn = mtmp->mhp;
2189 | 	hpd = (mtmp->m_lev < 50) ? ((int)mtmp->m_lev)*8 : mdat->mlevel;
2190 | 	if(!hpd) hpd = 4;
2191 | 
2192 | 	mtmp->m_lev = adj_lev(mdat);		/* new monster level */
2193 | 
2194 | 	mhp = (mtmp->m_lev < 50) ? ((int)mtmp->m_lev)*8 : mdat->mlevel;
2195 | 	if(!mhp) mhp = 4;
2196 | 
2197 | 	/* new hp: same fraction of max as before */
2198 | #ifndef LINT
2199 | 	mtmp->mhp = (int)(((long)hpn*(long)mhp)/(long)hpd);
2200 | #endif
2201 | 	if(mtmp->mhp < 0) mtmp->mhp = hpn;	/* overflow */
2202 | /* Unlikely but not impossible; a 1HD creature with 1HP that changes into a
2203 |    0HD creature will require this statement */
2204 | 	if (!mtmp->mhp) mtmp->mhp = 1;
2205 | 
2206 | /* and the same for maximum hit points */
2207 | 	hpn = mtmp->mhpmax;
2208 | #ifndef LINT
2209 | 	mtmp->mhpmax = (int)(((long)hpn*(long)mhp)/(long)hpd);
2210 | #endif
2211 | 	if(mtmp->mhpmax < 0) mtmp->mhpmax = hpn;	/* overflow */
2212 | 	if (!mtmp->mhpmax) mtmp->mhpmax = 1;
2213 | 
2214 | 	/* take on the new form... */
2215 | 	set_mon_data(mtmp, mdat, 0);
2216 | 
2217 | 	if (emits_light(olddata) != emits_light(mtmp->data)) {
2218 | 	    /* used to give light, now doesn't, or vice versa,
2219 | 	       or light's range has changed */
2220 | 	    if (emits_light(olddata))
2221 | 		del_light_source(LS_MONSTER, (genericptr_t)mtmp);
2222 | 	    if (emits_light(mtmp->data))
2223 | 		new_light_source(mtmp->mx, mtmp->my, emits_light(mtmp->data),
2224 | 				 LS_MONSTER, (genericptr_t)mtmp);
2225 | 	}
2226 | 	mtmp->perminvis = pm_invisible(mdat);
2227 | 	mtmp->minvis = mtmp->invis_blkd ? 0 : mtmp->perminvis;
2228 | 	if (!(hides_under(mdat) && OBJ_AT(mtmp->mx, mtmp->my)) &&
2229 | 			!(mdat->mlet == S_EEL && is_pool(mtmp->mx, mtmp->my)))
2230 | 		mtmp->mundetected = 0;
2231 | 	if (u.ustuck == mtmp) {
2232 | 		if(u.uswallow) {
2233 | 			if(!attacktype(mdat,AT_ENGL)) {
2234 | 				/* Does mdat care? */
2235 | 				if (!noncorporeal(mdat) && !amorphous(mdat) &&
2236 | 				    !is_whirly(mdat) &&
2237 | 				    (mdat != &mons[PM_YELLOW_LIGHT])) {
2238 | 					You("break out of %s%s!", mon_nam(mtmp),
2239 | 					    (is_animal(mdat)?
2240 | 					    "'s stomach" : ""));
2241 | 					mtmp->mhp = 1;  /* almost dead */
2242 | 				}
2243 | 				expels(mtmp, olddata, FALSE);
2244 | 			}
2245 | 		} else if (!sticks(mdat) && !sticks(youmonst.data))
2246 | 			unstuck(mtmp);
2247 | 	}
2248 | 
2249 | #ifndef DCC30_BUG
2250 | 	if (mdat == &mons[PM_LONG_WORM] && (mtmp->wormno = get_wormno()) != 0) {
2251 | #else
2252 | 	/* DICE 3.0 doesn't like assigning and comparing mtmp->wormno in the
2253 | 	 * same expression.
2254 | 	 */
2255 | 	if (mdat == &mons[PM_LONG_WORM] &&
2256 | 		(mtmp->wormno = get_wormno(), mtmp->wormno != 0)) {
2257 | #endif
2258 | 	    /* we can now create worms with tails - 11/91 */
2259 | 	    initworm(mtmp, rn2(5));
2260 | 	    if (count_wsegs(mtmp))
2261 | 		place_worm_tail_randomly(mtmp, mtmp->mx, mtmp->my);
2262 | 	}
2263 | 
2264 | 	newsym(mtmp->mx,mtmp->my);
2265 | 
2266 | 	mon_break_armor(mtmp);
2267 | 	if (!(mtmp->misc_worn_check & W_ARMG))
2268 | 	    mselftouch(mtmp, "No longer petrify-resistant, ",
2269 | 			!flags.mon_moving);
2270 | 	possibly_unwield(mtmp);
2271 | 	m_dowear(mtmp, FALSE);
2272 | 
2273 | 	/* This ought to re-test can_carry() on each item in the inventory
2274 | 	 * rather than just checking ex-giants & boulders, but that'd be
2275 | 	 * pretty expensive to perform.  If implemented, then perhaps
2276 | 	 * minvent should be sorted in order to drop heaviest items first.
2277 | 	 */
2278 | 	/* former giants can't continue carrying boulders */
2279 | 	if (mtmp->minvent && !throws_rocks(mdat)) {
2280 | 	    register struct obj *otmp, *otmp2;
2281 | 
2282 | 	    for (otmp = mtmp->minvent; otmp; otmp = otmp2) {
2283 | 		otmp2 = otmp->nobj;
2284 | 		if (otmp->otyp == BOULDER) {
2285 | 		    obj_extract_self(otmp);
2286 | 		    /* probably ought to give some "drop" message here */
2287 | 		    if (flooreffects(otmp, mtmp->mx, mtmp->my, "")) continue;
2288 | 		    place_object(otmp, mtmp->mx, mtmp->my);
2289 | 		}
2290 | 	    }
2291 | 	}
2292 | 
2293 | 	return(1);
2294 | }
2295 | 
2296 | /* sometimes an egg will be special */
2297 | #define BREEDER_EGG (!rn2(77))
2298 | 
2299 | /*
2300 |  * Determine if the given monster number can be hatched from an egg.
2301 |  * Return the monster number to use as the egg's corpsenm.  Return
2302 |  * NON_PM if the given monster can't be hatched.
2303 |  */
2304 | int
2305 | can_be_hatched(mnum)
2306 | int mnum;
2307 | {
2308 |     mnum = little_to_big(mnum);
2309 |     /*
2310 |      * Queen bees lay killer bee eggs (usually), but killer bees don't
2311 |      * grow into queen bees.  Ditto for [winged-]gargoyles.
2312 |      */
2313 |     if (mnum == PM_KILLER_BEE || mnum == PM_GARGOYLE ||
2314 | 	    (lays_eggs(&mons[mnum]) && (BREEDER_EGG ||
2315 | 		(mnum != PM_QUEEN_BEE && mnum != PM_WINGED_GARGOYLE))))
2316 | 	return mnum;
2317 |     return NON_PM;
2318 | }
2319 | 
2320 | /* type of egg laid by #sit; usually matches parent */
2321 | int
2322 | egg_type_from_parent(mnum, force_ordinary)
2323 | int mnum;	/* parent monster; caller must handle lays_eggs() check */
2324 | boolean force_ordinary;
2325 | {
2326 |     if (force_ordinary || !BREEDER_EGG) {
2327 | 	if (mnum == PM_QUEEN_BEE) mnum = PM_KILLER_BEE;
2328 | 	else if (mnum == PM_WINGED_GARGOYLE) mnum = PM_GARGOYLE;
2329 |     }
2330 |     return mnum;
2331 | }
2332 | 
2333 | /* decide whether an egg of the indicated monster type is viable; */
2334 | /* also used to determine whether an egg or tin can be created... */
2335 | boolean
2336 | dead_species(m_idx, egg)
2337 | int m_idx;
2338 | boolean egg;
2339 | {
2340 | 	/*
2341 | 	 * For monsters with both baby and adult forms, genociding either
2342 | 	 * form kills all eggs of that monster.  Monsters with more than
2343 | 	 * two forms (small->large->giant mimics) are more or less ignored;
2344 | 	 * fortunately, none of them have eggs.  Species extinction due to
2345 | 	 * overpopulation does not kill eggs.
2346 | 	 */
2347 | 	return (boolean)
2348 | 		(m_idx >= LOW_PM &&
2349 | 		 ((mvitals[m_idx].mvflags & G_GENOD) != 0 ||
2350 | 		  (egg &&
2351 | 		   (mvitals[big_to_little(m_idx)].mvflags & G_GENOD) != 0)));
2352 | }
2353 | 
2354 | /* kill off any eggs of genocided monsters */
2355 | STATIC_OVL void
2356 | kill_eggs(obj_list)
2357 | struct obj *obj_list;
2358 | {
2359 | 	struct obj *otmp;
2360 | 
2361 | 	for (otmp = obj_list; otmp; otmp = otmp->nobj)
2362 | 	    if (otmp->otyp == EGG) {
2363 | 		if (dead_species(otmp->corpsenm, TRUE)) {
2364 | 		    /*
2365 | 		     * It seems we could also just catch this when
2366 | 		     * it attempted to hatch, so we wouldn't have to
2367 | 		     * search all of the objlists.. or stop all
2368 | 		     * hatch timers based on a corpsenm.
2369 | 		     */
2370 | 		    kill_egg(otmp);
2371 | 		}
2372 | #if 0	/* not used */
2373 | 	    } else if (otmp->otyp == TIN) {
2374 | 		if (dead_species(otmp->corpsenm, FALSE))
2375 | 		    otmp->corpsenm = NON_PM;	/* empty tin */
2376 | 	    } else if (otmp->otyp == CORPSE) {
2377 | 		if (dead_species(otmp->corpsenm, FALSE))
2378 | 		    ;		/* not yet implemented... */
2379 | #endif
2380 | 	    } else if (Has_contents(otmp)) {
2381 | 		kill_eggs(otmp->cobj);
2382 | 	    }
2383 | }
2384 | 
2385 | /* kill all members of genocided species */
2386 | void
2387 | kill_genocided_monsters()
2388 | {
2389 | 	struct monst *mtmp, *mtmp2;
2390 | 	boolean kill_cham[CHAM_MAX_INDX+1];
2391 | 	int mndx;
2392 | 
2393 | 	kill_cham[CHAM_ORDINARY] = FALSE;	/* (this is mndx==0) */
2394 | 	for (mndx = 1; mndx <= CHAM_MAX_INDX; mndx++)
2395 | 	  kill_cham[mndx] = (mvitals[cham_to_pm[mndx]].mvflags & G_GENOD) != 0;
2396 | 	/*
2397 | 	 * Called during genocide, and again upon level change.  The latter
2398 | 	 * catches up with any migrating monsters as they finally arrive at
2399 | 	 * their intended destinations, so possessions get deposited there.
2400 | 	 *
2401 | 	 * Chameleon handling:
2402 | 	 *	1) if chameleons have been genocided, destroy them
2403 | 	 *	   regardless of current form;
2404 | 	 *	2) otherwise, force every chameleon which is imitating
2405 | 	 *	   any genocided species to take on a new form.
2406 | 	 */
2407 | 	for (mtmp = fmon; mtmp; mtmp = mtmp2) {
2408 | 	    mtmp2 = mtmp->nmon;
2409 | 	    if (DEADMONSTER(mtmp)) continue;
2410 | 	    mndx = monsndx(mtmp->data);
2411 | 	    if ((mvitals[mndx].mvflags & G_GENOD) || kill_cham[mtmp->cham]) {
2412 | 		if (mtmp->cham && !kill_cham[mtmp->cham])
2413 | 		    (void) newcham(mtmp, (struct permonst *)0);
2414 | 		else
2415 | 		    mondead(mtmp);
2416 | 	    }
2417 | 	    if (mtmp->minvent) kill_eggs(mtmp->minvent);
2418 | 	}
2419 | 
2420 | 	kill_eggs(invent);
2421 | 	kill_eggs(fobj);
2422 | 	kill_eggs(level.buriedobjlist);
2423 | }
2424 | 
2425 | #endif /* OVL2 */
2426 | #ifdef OVLB
2427 | 
2428 | void
2429 | golemeffects(mon, damtype, dam)
2430 | register struct monst *mon;
2431 | int damtype, dam;
2432 | {
2433 |     int heal = 0, slow = 0;
2434 | 
2435 |     if (mon->data == &mons[PM_FLESH_GOLEM]) {
2436 | 	if (damtype == AD_ELEC) heal = dam / 6;
2437 | 	else if (damtype == AD_FIRE || damtype == AD_COLD) slow = 1;
2438 |     } else if (mon->data == &mons[PM_IRON_GOLEM]) {
2439 | 	if (damtype == AD_ELEC) slow = 1;
2440 | 	else if (damtype == AD_FIRE) heal = dam;
2441 |     } else {
2442 | 	return;
2443 |     }
2444 |     if (slow) {
2445 | 	if (mon->mspeed != MSLOW) {
2446 | 	    unsigned int oldspeed = mon->mspeed;
2447 | 
2448 | 	    mon_adjust_speed(mon, -1);
2449 | 	    if (mon->mspeed != oldspeed && cansee(mon->mx, mon->my))
2450 | 		pline("%s seems to be moving slower.", Monnam(mon));
2451 | 	}
2452 |     }
2453 |     if (heal) {
2454 | 	if (mon->mhp < mon->mhpmax) {
2455 | 	    mon->mhp += dam;
2456 | 	    if (mon->mhp > mon->mhpmax) mon->mhp = mon->mhpmax;
2457 | 	    if (cansee(mon->mx, mon->my))
2458 | 		pline("%s seems healthier.", Monnam(mon));
2459 | 	}
2460 |     }
2461 | }
2462 | 
2463 | boolean
2464 | angry_guards(silent)
2465 | register boolean silent;
2466 | {
2467 | 	register struct monst *mtmp;
2468 | 	register int ct = 0, nct = 0, sct = 0, slct = 0;
2469 | 
2470 | 	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
2471 | 		if (DEADMONSTER(mtmp)) continue;
2472 | 		if((mtmp->data == &mons[PM_WATCHMAN] ||
2473 | 			       mtmp->data == &mons[PM_WATCH_CAPTAIN])
2474 | 					&& mtmp->mpeaceful) {
2475 | 			ct++;
2476 | 			if(cansee(mtmp->mx, mtmp->my) && mtmp->mcanmove) {
2477 | 				if (distu(mtmp->mx, mtmp->my) == 2) nct++;
2478 | 				else sct++;
2479 | 			}
2480 | 			if (mtmp->msleeping || mtmp->mfrozen) {
2481 | 				slct++;
2482 | 				mtmp->msleeping = mtmp->mfrozen = 0;
2483 | 			}
2484 | 			mtmp->mpeaceful = 0;
2485 | 		}
2486 | 	}
2487 | 	if(ct) {
2488 | 	    if(!silent) { /* do we want pline msgs? */
2489 | 		if(slct) pline_The("guard%s wake%s up!",
2490 | 				 slct > 1 ? "s" : "", slct == 1 ? "s" : "");
2491 | 		if(nct || sct) {
2492 | 			if(nct) pline_The("guard%s get%s angry!",
2493 | 				nct == 1 ? "" : "s", nct == 1 ? "s" : "");
2494 | 			else if(!Blind)
2495 | 				You("see %sangry guard%s approaching!",
2496 | 				  sct == 1 ? "an " : "", sct > 1 ? "s" : "");
2497 | 		} else if(flags.soundok)
2498 | 			You_hear("the shrill sound of a guard's whistle.");
2499 | 	    }
2500 | 	    return(TRUE);
2501 | 	}
2502 | 	return(FALSE);
2503 | }
2504 | 
2505 | void
2506 | pacify_guards()
2507 | {
2508 | 	register struct monst *mtmp;
2509 | 
2510 | 	for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
2511 | 	    if (DEADMONSTER(mtmp)) continue;
2512 | 	    if (mtmp->data == &mons[PM_WATCHMAN] ||
2513 | 		mtmp->data == &mons[PM_WATCH_CAPTAIN])
2514 | 	    mtmp->mpeaceful = 1;
2515 | 	}
2516 | }
2517 | #endif /* OVLB */
2518 | 
2519 | /*mon.c*/