Source:NetHack 3.0.0/mon.c

From NetHackWiki
Jump to navigation Jump to search

Below is the full text to mon.c from the source code of NetHack 3.0.0. To link to a particular line, write [[NetHack 3.0.0/mon.c#line123]], for example.

Warning! This is the source code from an old release. For the latest release, see Source code

The NetHack General Public License applies to screenshots, source code and other content from NetHack.

This content was modified from the original NetHack source code distribution (by splitting up NetHack content between wiki pages, and possibly further editing). See the page history for a list of who changed it, and on what dates.

1.    /*	SCCS Id: @(#)mon.c	3.0	88/10/31
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 "mfndpos.h"
7.    #ifdef NAMED_ITEMS
8.    #  include "artifact.h"
9.    #endif
10.   
11.   #ifdef HARD
12.   static boolean restrap();
13.   #endif
14.   
15.   long lastwarntime;
16.   int lastwarnlev;
17.   static const char *warnings[] = {
18.   	"white", "pink", "red", "ruby", "purple", "black" };
19.   struct monst *fdmon;	/* chain of dead monsters, need not to be saved */
20.   
21.   /* Creates a monster corpse, a "special" corpse, or nothing if it doesn't
22.    * leave corpses.  Monsters which leave "special" corpses should have
23.    * G_NOCORPSE set in order to prevent wishing for one, finding tins of one,
24.    * etc....
25.    */
26.   static struct obj *
27.   make_corpse(mtmp)
28.   register struct monst *mtmp;
29.   {
30.   	register struct permonst *mdat = mtmp->data;
31.   #ifdef GOLEMS
32.   	int pieces;
33.   #endif
34.   	struct obj *obj = 0;
35.   	int x = mtmp->mx, y = mtmp->my;
36.   
37.   	switch(monsndx(mdat)) {
38.   	    case PM_KOBOLD_MUMMY:
39.   		obj = mksobj_at(MUMMY_WRAPPING, x, y); /* and fall through */
40.   	    case PM_KOBOLD_ZOMBIE:
41.   		obj = mksobj_at(CORPSE, x, y);
42.   		obj->corpsenm = PM_KOBOLD;
43.   		break;
44.   	    case PM_GNOME_MUMMY:
45.   		obj = mksobj_at(MUMMY_WRAPPING, x, y); /* and fall through */
46.   	    case PM_GNOME_ZOMBIE:
47.   		obj = mksobj_at(CORPSE, x, y);
48.   		obj->corpsenm = PM_GNOME;
49.   		break;
50.   	    case PM_ORC_MUMMY:
51.   		obj = mksobj_at(MUMMY_WRAPPING, x, y); /* and fall through */
52.   	    case PM_ORC_ZOMBIE:
53.   		obj = mksobj_at(CORPSE, x, y);
54.   		obj->corpsenm = PM_ORC;
55.   		break;
56.   	    case PM_ELF_MUMMY:
57.   		obj = mksobj_at(MUMMY_WRAPPING, x, y); /* and fall through */
58.   	    case PM_ELF_ZOMBIE:
59.   		obj = mksobj_at(CORPSE, x, y);
60.   		obj->corpsenm = PM_ELF;
61.   		break;
62.   	    case PM_HUMAN_MUMMY:
63.   		obj = mksobj_at(MUMMY_WRAPPING, x, y); /* and fall through */
64.   	    case PM_HUMAN_ZOMBIE:
65.   		obj = mksobj_at(CORPSE, x, y);
66.   		obj->corpsenm = PM_HUMAN;
67.   		break;
68.   	    case PM_GIANT_MUMMY:
69.   		obj = mksobj_at(MUMMY_WRAPPING, x, y); /* and fall through */
70.   	    case PM_GIANT_ZOMBIE:
71.   		obj = mksobj_at(CORPSE, x, y);
72.   		obj->corpsenm = PM_GIANT;
73.   		break;
74.   	    case PM_ETTIN_MUMMY:
75.   		obj = mksobj_at(MUMMY_WRAPPING, x, y); /* and fall through */
76.   	    case PM_ETTIN_ZOMBIE:
77.   		obj = mksobj_at(CORPSE, x, y);
78.   		obj->corpsenm = PM_ETTIN;
79.   		break;
80.   #ifdef GOLEMS
81.   	    case PM_IRON_GOLEM:
82.   		pieces = d(2,6);
83.   		while (pieces--)
84.   			obj = mksobj_at(IRON_CHAIN, x, y);
85.   		break;
86.   	    case PM_CLAY_GOLEM:
87.   		obj = mksobj_at(ROCK, x, y);
88.   		obj->quan = rn2(20) + 100;
89.   		obj->owt = weight(obj);
90.   		break;
91.   	    case PM_STONE_GOLEM:
92.   		obj = mkstatue(mdat, x, y);
93.   		break;
94.   	    case PM_WOOD_GOLEM:
95.   		pieces = d(2,4);
96.   		while(pieces--)
97.   			obj = mksobj_at(QUARTERSTAFF, x, y);
98.   		break;
99.   	    case PM_LEATHER_GOLEM:
100.  		pieces = d(2,4);
101.  		while(pieces--)
102.  			obj = mksobj_at(LEATHER_ARMOR, x, y);
103.  		break;
104.  #endif
105.  	    default:
106.  		if (mdat->geno & G_NOCORPSE)
107.  			return (struct obj *)0;
108.  		else obj = mkcorpse_at(mdat, x, y);
109.  		break;
110.  	}
111.  	/* All special cases should precede the G_NOCORPSE check */
112.  
113.  	/* Note: oname() cannot be used generically for non-inventory objects
114.  	 * unless you fix the link from the previous object in the chain.
115.  	 * (Here we know it's the first one, so there was no link.)
116.  	 */
117.  	if (mtmp->mnamelth) {
118.  		obj = oname(obj, NAME(mtmp), 0);
119.  		fobj = obj;
120.  	}
121.  	stackobj(fobj);
122.  	newsym(x, y);
123.  	return obj;
124.  }
125.  
126.  
127.  static void
128.  dmonsfree(){
129.  register struct monst *mtmp;
130.  	while(mtmp = fdmon){
131.  		fdmon = mtmp->nmon;
132.  		free((genericptr_t) mtmp);
133.  	}
134.  }
135.  
136.  void
137.  movemon()
138.  {
139.  	register struct monst *mtmp;
140.  	register int fr;
141.  
142.  	warnlevel = 0;
143.  
144.  	while(1) {
145.  		/*  Find a monster that we have not treated yet.
146.  		 *  Note that mtmp or mtmp->nmon might get killed
147.  		 *  while mtmp moves, so we cannot just walk down the
148.  		 *  chain (even new monsters might get created!)
149.  		 */
150.  		/* Do tame monsters first.  Necessary so that when the tame
151.  		 * monster attacks something, the something gets a chance to
152.  		 * attack the tame monster back (which it's permitted to do
153.  		 * only if it hasn't made its move yet).
154.  		 */
155.  		for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
156.  			if(mtmp->mlstmv < moves && mtmp->mtame) goto next_mon;
157.  		for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
158.  			if(mtmp->mlstmv < moves && !mtmp->mtame) goto next_mon;
159.  		/* treated all monsters */
160.  		break;
161.  
162.  	next_mon:
163.  		mtmp->mlstmv = moves;
164.  
165.  		/* most monsters drown in pools */
166.  		{ boolean inpool,infountain,iseel,isgremlin;
167.  
168.  		  inpool = is_pool(mtmp->mx,mtmp->my);
169.  		  iseel = mtmp->data->mlet == S_EEL;
170.  		  isgremlin = mtmp->data->mlet == S_GREMLIN;
171.  		  infountain = IS_FOUNTAIN(levl[mtmp->mx][mtmp->my].typ);
172.  		/* Gremlin multiplying won't go on forever since the hit points
173.  		 * keep going down, and when it gets to 1 hit point the clone
174.  		 * function will fail.
175.  		 */
176.  		  if((inpool || infountain) && isgremlin && rn2(3)) {
177.  			struct monst *mtmp2 = clone_mon(mtmp);
178.  
179.  			if (mtmp2) {
180.  			    mtmp2->mhpmax = (mtmp->mhpmax /= 2);
181.  			    if(cansee(mtmp->mx,mtmp->my))
182.  				pline("%s multiplies.", Monnam(mtmp));
183.  			}
184.  #ifdef FOUNTAINS
185.  			if (infountain) dryup();
186.  #endif
187.  		  } else
188.  		  if(inpool && !is_flyer(mtmp->data) && !is_swimmer(mtmp->data)) {
189.  			if(cansee(mtmp->mx,mtmp->my))
190.  			    pline("%s drowns.", Monnam(mtmp));
191.  			mondead(mtmp);
192.  			continue;
193.  		  } else
194.  		/* but eels have a difficult time outside */
195.  		  if(iseel && !inpool) {
196.  			if(mtmp->mhp > 1) mtmp->mhp--;
197.  			mtmp->mflee = 1;
198.  			mtmp->mfleetim += 2;
199.  		  }
200.  		}
201.  		if(mtmp->mblinded && !--mtmp->mblinded)
202.  			mtmp->mcansee = 1;
203.  		if(mtmp->mfleetim && !--mtmp->mfleetim)
204.  			mtmp->mflee = 0;
205.  #ifdef HARD
206.  		/* unwatched mimics and piercers may hide again  [MRS] */
207.  		if(is_hider(mtmp->data) && restrap(mtmp))   continue;
208.  #endif
209.  		if(mtmp->mimic) continue;
210.  		if(mtmp->mspeed != MSLOW || !(moves%2)){
211.  			/* continue if the monster died fighting */
212.  			fr = -1;
213.  /* TODO:	Handle the case of the agressor dying? */
214.  			if(Conflict && cansee(mtmp->mx,mtmp->my)
215.  				&& !mtmp->iswiz
216.  				&& (fr = fightm(mtmp)) == 2)
217.  				continue;
218.    			if(fr<0 && dochugw(mtmp))
219.  				continue;
220.  		}
221.  		if(mtmp->mspeed == MFAST && dochugw(mtmp))
222.  			continue;
223.  	}
224.  #ifdef NAMED_ITEMS
225.  	if (warnlevel == 100) {
226.  		Your("%s %s!", aobjnam(uwep, "glow"),
227.  			Hallucination ? hcolor() : light_blue);
228.  		warnlevel = 0;
229.  	}
230.  #endif
231.  	warnlevel -= u.ulevel;
232.  	if(warnlevel >= SIZE(warnings))
233.  		warnlevel = SIZE(warnings)-1;
234.  	if(!Blind && warnlevel >= 0)
235.  	if(warnlevel > lastwarnlev || moves > lastwarntime + 5){
236.  	    register char *rr;
237.  	
238.  	    switch((int) (Warning & (LEFT_RING | RIGHT_RING))){
239.  	    case LEFT_RING:
240.  		rr = "Your left ring glows";
241.  		break;
242.  	    case RIGHT_RING:
243.  		rr = "Your right ring glows";
244.  		break;
245.  	    case LEFT_RING | RIGHT_RING:
246.  		rr = "Both your rings glow";
247.  		break;
248.  	    default:
249.  		{ char buf[33];
250.  		Sprintf(buf, "Your %s glow", makeplural(body_part(FINGERTIP)));
251.  		rr = buf;
252.  		}
253.  		break;
254.  	    }
255.  	    pline("%s %s!", rr, Hallucination ? hcolor() : warnings[warnlevel]);
256.  	    lastwarntime = moves;
257.  	    lastwarnlev = warnlevel;
258.  	}
259.  
260.  	dmonsfree();	/* remove all dead monsters */
261.  }
262.  
263.  void
264.  meatgold(mtmp)
265.  	register struct monst *mtmp;
266.  {
267.  	register struct gold *gold;
268.  	register struct obj *otmp;
269.  
270.  	/* Eats gold if it is there */
271.  	while(gold = g_at(mtmp->mx, mtmp->my)){
272.  		if (cansee(mtmp->mx, mtmp->my) && flags.verbose)
273.  			pline("%s eats some gold!", Monnam(mtmp));
274.  		mtmp->meating = (int)((gold->amount + 500L)/1000L);
275.  		freegold(gold);
276.  		/* Left behind a pile? */
277.  		if(rnd(25) < 3) (void) mksobj_at(ROCK, mtmp->mx, mtmp->my);
278.  		newsym(mtmp->mx, mtmp->my);
279.  	}
280.  	/* Eats topmost metal object if it is there */
281.  	for (otmp = fobj; otmp; otmp = otmp->nobj)
282.  	    if (otmp->ox == mtmp->mx && otmp->oy == mtmp->my &&
283.  		objects[otmp->otyp].oc_material == METAL) {
284.  		    if (cansee(mtmp->mx,mtmp->my) && flags.verbose)
285.  			pline("%s eats %s!", Monnam(mtmp),
286.  				distant_name(otmp,doname));
287.  		    else if (flags.soundok && flags.verbose)
288.  			You("hear a crunching sound.");
289.  		    mtmp->meating = otmp->owt/2 - 1;
290.  		    /* Heal up to the object's weight in hp */
291.  		    if (mtmp->mhp < mtmp->mhpmax) {
292.  			mtmp->mhp += objects[otmp->otyp].oc_weight;
293.  			if (mtmp->mhp > mtmp->mhpmax) mtmp->mhp = mtmp->mhpmax;
294.  		    }
295.  		    freeobj(otmp);
296.  		    /* Left behind a pile? */
297.  		    if(rnd(25) < 3) (void) mksobj_at(ROCK, mtmp->mx, mtmp->my);
298.  		    newsym(mtmp->mx, mtmp->my);
299.  		    break;
300.  	    }
301.  	set_omask(mtmp->mx, mtmp->my);
302.  }
303.  
304.  void
305.  meatobj(mtmp)		/* for gelatinous cubes */
306.  	register struct monst *mtmp;
307.  {
308.  	register struct obj *otmp, *otmp2;
309.  
310.  	/* Eats organic, glass, or wood objects if there */
311.  	/* Engulfs anything else, metal and rock */
312.  	for (otmp = fobj; otmp; otmp = otmp2) {
313.  	    otmp2 = otmp->nobj;
314.  	    if (otmp->ox == mtmp->mx && otmp->oy == mtmp->my) {
315.  		if(!objects[otmp->otyp].oc_material <= WOOD) {
316.  		    if (cansee(mtmp->mx,mtmp->my) && flags.verbose)
317.  			pline("%s eats %s!", Monnam(mtmp),
318.  				distant_name(otmp, doname));
319.  		    else if (flags.soundok && flags.verbose)
320.  			You("hear a slurping sound.");
321.                      /* Heal up to the object's weight in hp */
322.  		    if (mtmp->mhp < mtmp->mhpmax) {
323.  			mtmp->mhp += objects[otmp->otyp].oc_weight;
324.  			if (mtmp->mhp > mtmp->mhpmax) mtmp->mhp = mtmp->mhpmax;
325.  		    }
326.  		    delobj(otmp);		/* munch */
327.  		} else if (otmp->olet != ROCK_SYM && otmp->olet != BALL_SYM) {
328.  		    if (cansee(mtmp->mx, mtmp->my) && flags.verbose)
329.  			pline("%s engulfs %s.", Monnam(mtmp),
330.  				distant_name(otmp,doname));
331.  		    freeobj(otmp);
332.  		    mpickobj(mtmp, otmp);	/* slurp */
333.  		}
334.  	    }
335.  	    /* Engulf & devour is instant, so don't set meating */
336.  	    newsym(mtmp->mx, mtmp->my);
337.  	}
338.  	set_omask(mtmp->mx, mtmp->my);
339.  }
340.  
341.  void
342.  mpickgold(mtmp)
343.  	register struct monst *mtmp;
344.  {
345.  	register struct gold *gold;
346.  
347.  	while(gold = g_at(mtmp->mx, mtmp->my)){
348.  		mtmp->mgold += gold->amount;
349.  		if (cansee(mtmp->mx, mtmp->my) && flags.verbose)
350.  			pline("%s picks up some gold.", Monnam(mtmp));
351.  		freegold(gold);
352.  		if(levl[mtmp->mx][mtmp->my].scrsym == GOLD_SYM)
353.  			newsym(mtmp->mx, mtmp->my);
354.  	}
355.  	set_omask(mtmp->mx, mtmp->my);
356.  }
357.  
358.  /* Now includes giants which pick up enormous rocks.  KAA */
359.  void
360.  mpickgems(mtmp)
361.  	register struct monst *mtmp;
362.  {
363.  	register struct obj *otmp;
364.  
365.  	for(otmp = fobj; otmp; otmp = otmp->nobj)
366.  	  if(throws_rocks(mtmp->data) ? otmp->otyp == BOULDER :
367.  			(otmp->olet == GEM_SYM && otmp->otyp < LAST_GEM+5))
368.  	    if(otmp->ox == mtmp->mx && otmp->oy == mtmp->my)
369.  	      if(mtmp->data->mlet != S_UNICORN
370.  		 || objects[otmp->otyp].g_val != 0){
371.  		if (cansee(mtmp->mx,mtmp->my) && flags.verbose)
372.  			pline("%s picks up %s.", Monnam(mtmp),
373.  				distant_name(otmp, doname));
374.  		freeobj(otmp);
375.  		mpickobj(mtmp, otmp);
376.  		newsym(mtmp->mx, mtmp->my);
377.  		return;	/* pick only one object */
378.  	      }
379.  	set_omask(mtmp->mx, mtmp->my);
380.  }
381.  
382.  int
383.  curr_mon_load(mtmp)
384.  register struct monst *mtmp;
385.  {
386.  	register int curload = 0;
387.  	register struct obj *obj;
388.  
389.  	for(obj = mtmp->minvent; obj; obj = obj->nobj) {
390.  		if(obj->otyp != BOULDER || !throws_rocks(mtmp->data))
391.  			curload += weight(obj);
392.  	}
393.  
394.  	return curload;
395.  }
396.  
397.  int
398.  max_mon_load(mtmp)
399.  register struct monst *mtmp;
400.  {
401.  	register int maxload;
402.  
403.  	/* Base monster carrying capacity is equal to human maximum
404.  	 * carrying capacity, or half human maximum if not strong.
405.  	 * (for a polymorphed player, the value used would be the
406.  	 * non-polymorphed carrying capacity instead of max/half max).
407.  	 * This is then modified by the ratio between the monster weights
408.  	 * and human weights (weight of a human=45).  Limits for corpseless
409.  	 * monsters are arbitrary.
410.  	 */
411.  	maxload = (mtmp->data->cwt ? mtmp->data->cwt : mtmp->data->mlevel*6)
412.  		* MAX_CARR_CAP / 45;
413.  	if (!strongmonst(mtmp->data)) maxload /= 2;
414.  
415.  	return maxload;
416.  }
417.  
418.  /* for restricting monsters' object-pickup */
419.  boolean
420.  can_carry(mtmp,otmp)
421.  struct monst *mtmp;
422.  struct obj *otmp;
423.  {
424.  	register int newload = weight(otmp);
425.  
426.  	if (mtmp->isshk) return(TRUE); /* no limit */
427.  	if (mtmp->mpeaceful && !mtmp->mtame) return(FALSE);
428.  	/* otherwise players might find themselves obligated to violate
429.  	 * their alignment if the monster takes something they need
430.  	 */
431.  	
432.  	/* special--boulder throwers carry unlimited amounts of boulders */
433.  	if (throws_rocks(mtmp->data) && otmp->otyp == BOULDER)
434.  		return(TRUE);
435.  	
436.  	/* nymphs deal in stolen merchandise, but not boulders or statues */
437.  	if (mtmp->data->mlet == S_NYMPH)
438.  		return !(otmp->olet == ROCK_SYM);
439.  
440.  	if(curr_mon_load(mtmp) + newload > max_mon_load(mtmp)) return(FALSE);
441.  
442.  	return(TRUE);
443.  }
444.  
445.  void
446.  mpickstuff(mtmp, str)
447.  	register struct monst *mtmp;
448.  	register char *str;
449.  {
450.  	register struct obj *otmp;
451.  
452.  /*	prevent shopkeepers from leaving the door of their shop */
453.  	if(mtmp->isshk && inhishop(mtmp)) return;
454.  
455.  	for(otmp = fobj; otmp; otmp = otmp->nobj)
456.  	  if(index(str, otmp->olet))
457.  	    if(otmp->ox == mtmp->mx && otmp->oy == mtmp->my) {
458.  		if(!can_carry(mtmp,otmp)) return;
459.  		if (cansee(mtmp->mx,mtmp->my) && flags.verbose)
460.  			pline("%s picks up %s.", Monnam(mtmp), doname(otmp));
461.  		freeobj(otmp);
462.  		mpickobj(mtmp, otmp);
463.  		if(index(str, (char) levl[mtmp->mx][mtmp->my].scrsym))
464.  			newsym(mtmp->mx, mtmp->my);
465.  		set_omask(mtmp->mx, mtmp->my);
466.  		return;			/* pick only one object */
467.  	    }
468.  }
469.  
470.  /* return number of acceptable neighbour positions */
471.  int
472.  mfndpos(mon, poss, info, flag)
473.  	register struct monst *mon;
474.  	coord *poss;	/* coord poss[9] */
475.  	long *info;	/* long info[9] */
476.  	long flag;
477.  {
478.  	register int x,y,nx,ny,cnt = 0,ntyp;
479.  	int nowtyp;
480.  	boolean wantpool,poolok;
481.  
482.  	x = mon->mx;
483.  	y = mon->my;
484.  	nowtyp = levl[x][y].typ;
485.  
486.  	wantpool = mon->data->mlet == S_EEL;
487.  	poolok = is_flyer(mon->data) || (is_swimmer(mon->data) && !wantpool);
488.  nexttry:	/* eels prefer the water, but if there is no water nearby,
489.  		   they will crawl over land */
490.  	if(mon->mconf) {
491.  		flag |= ALLOW_ALL;
492.  		flag &= ~NOTONL;
493.  	}
494.  	if(!mon->mcansee)
495.  		flag |= ALLOW_SSM;
496.  	for(nx = x-1; nx <= x+1; nx++) for(ny = y-1; ny <= y+1; ny++) {
497.  	    if((nx == x && ny == y) || !isok(nx,ny)) continue;
498.  	    if(IS_ROCK(ntyp = levl[nx][ny].typ) && !(flag & ALLOW_WALL) &&
499.  		!((flag & ALLOW_DIG) && may_dig(nx,ny))) continue;
500.  	    if(IS_DOOR(ntyp) && !amorphous(mon->data) &&
501.  	       ((levl[nx][ny].doormask & D_LOCKED &&
502.  		   !is_giant(mon->data) && !mon->isshk) ||
503.  		(levl[nx][ny].doormask & D_CLOSED &&
504.  		   (verysmall(mon->data) ||
505.  		    (!is_giant(mon->data) && nohands(mon->data))))
506.  	       ) && !(flag & (ALLOW_WALL|ALLOW_DIG))) continue;
507.  	    if(nx != x && ny != y && (IS_DOOR(nowtyp) || IS_DOOR(ntyp)))
508.  		continue;
509.  	    if(is_pool(nx,ny) == wantpool || poolok) {
510.  		/* Displacement also displaces the Elbereth/scare monster,
511.  		 * as long as you are visible.
512.  		 */
513.  		int dispx = (Displaced && (!Invis || perceives(mon->data)) &&
514.  			(mon->mux==nx)) ? u.ux : nx;
515.  		int dispy = (Displaced && (!Invis || perceives(mon->data)) &&
516.  			(mon->muy==ny)) ? u.uy : ny;
517.  
518.  		info[cnt] = 0;
519.  		if(sobj_at(SCR_SCARE_MONSTER, dispx, dispy)
520.  #ifdef ELBERETH
521.  		   || sengr_at("Elbereth", dispx, dispy)
522.  #endif
523.  		  ) {
524.  			if(!(flag & ALLOW_SSM)) continue;
525.  			info[cnt] |= ALLOW_SSM;
526.  		}
527.  		if((nx == u.ux && ny == u.uy) ||
528.  		   (nx == mon->mux && ny == mon->muy)) {
529.  			if(!(flag & ALLOW_U)) continue;
530.  			info[cnt] |= ALLOW_U;
531.  		} else {
532.  			if(levl[nx][ny].mmask) {
533.  				if(!(flag & ALLOW_M)) continue;
534.  				info[cnt] |= ALLOW_M;
535.  				if((m_at(nx,ny))->mtame) {
536.  					if(!(flag & ALLOW_TM)) continue;
537.  					info[cnt] |= ALLOW_TM;
538.  				}
539.  			}
540.  #if defined(ALTARS) && defined(THEOLOGY)
541.  			/* Note: ALLOW_SANCT only prevents movement, not */
542.  			/* attack, into a temple. */
543.  			if(!in_temple(x, y) && in_temple(nx, ny) &&
544.  					u_in_sanctuary(in_temple(nx, ny))) {
545.  				if(!(flag & ALLOW_SANCT)) continue;
546.  				info[cnt] |= ALLOW_SANCT;
547.  			}
548.  #endif
549.  		}
550.  		if(sobj_at(CLOVE_OF_GARLIC, nx, ny)) {
551.  			if(flag & NOGARLIC) continue;
552.  			info[cnt] |= NOGARLIC;
553.  		}
554.  		if(sobj_at(BOULDER, nx, ny)) {
555.  			if(!(flag & ALLOW_ROCK)) continue;
556.  			info[cnt] |= ALLOW_ROCK;
557.  		}
558.  		if((!Invis || perceives(mon->data)) && online(nx,ny)){
559.  			if(flag & NOTONL) continue;
560.  			info[cnt] |= NOTONL;
561.  		}
562.  		/* we cannot avoid traps of an unknown kind */
563.  		{ register struct trap *ttmp = t_at(nx, ny);
564.  		  register long tt;
565.  			if(ttmp) {
566.  /*				tt = 1L << ttmp->ttyp;*/
567.  /* why don't we just have code look like what it's supposed to do? then it
568.  /* might start working for every case. try this instead: -sac */
569.  				tt = (ttmp->ttyp < TRAPNUM && ttmp->ttyp);
570.  				/* below if added by GAN 02/06/87 to avoid
571.  				 * traps out of range
572.  				 */
573.  				if(!(tt & ALLOW_TRAPS))  {
574.  impossible("A monster looked at a very strange trap of type %d.", ttmp->ttyp);
575.  					continue;
576.  				}
577.  				if(mon->mtrapseen & tt) {
578.  
579.  					if(!(flag & tt)) continue;
580.  					info[cnt] |= tt;
581.  				}
582.  			}
583.  		}
584.  		poss[cnt].x = nx;
585.  		poss[cnt].y = ny;
586.  		cnt++;
587.  	    }
588.  	}
589.  	if(!cnt && wantpool && !is_pool(x,y)) {
590.  		wantpool = FALSE;
591.  		goto nexttry;
592.  	}
593.  	return(cnt);
594.  }
595.  
596.  int
597.  dist(x, y)
598.  register int x,y;
599.  {
600.  	register int dx = x - u.ux, dy = y - u.uy;
601.  	return dx*dx + dy*dy;
602.  }
603.  
604.  static const char *poiseff[] = {
605.  
606.  	" feel very weak", "r brain is on fire",
607.  	" can't think straight", "r muscles won't obey you",
608.  	" feel very sick", " break out in hives"
609.  };
610.  
611.  void
612.  poisontell(typ)
613.  
614.  	int	typ;
615.  {
616.  	pline("You%s.", poiseff[typ]);
617.  }
618.  
619.  void
620.  poisoned(string, typ, pname)
621.  register char *string, *pname;
622.  register int  typ;
623.  {
624.  	register int i, plural;
625.  	boolean thrown_weapon = !strncmp(string, "poison", 6);
626.  		/* admittedly a kludge... */
627.  
628.  	if(strcmp(string, "blast") && !thrown_weapon) {
629.  	    /* 'blast' has already given a 'poison gas' message */
630.  	    /* so have "poison arrow", "poison dart", etc... */
631.  	    plural = (string[strlen(string) - 1] == 's')? 1 : 0;
632.  	    if(Blind)
633.  		pline("%s poisoned.", (plural) ? "They were" : "It was");
634.  	    else
635.  		pline("The %s %s poisoned!", string, (plural) ? "were" : "was");
636.  	}
637.  
638.  	if(Poison_resistance) {
639.  		if(!strcmp(string, "blast")) shieldeff(u.ux, u.uy);
640.  		pline("The poison doesn't seem to affect you.");
641.  		return;
642.  	}
643.  	i = rn2(10 + 20*thrown_weapon);
644.  	if(i == 0 && typ != A_CHA) {
645.  		u.uhp = -1;
646.  		pline("The poison was deadly...");
647.  	} else if(i <= 5) {
648.  		pline("You%s!", poiseff[typ]);
649.  		adjattrib(typ, thrown_weapon ? -1 : -rn1(3,3), TRUE);
650.  	} else {
651.  		losehp(thrown_weapon ? rnd(6) : rn1(10,6), pname);
652.  	}
653.  	if(u.uhp < 1) {
654.  		killer = pname;
655.  		done("died");
656.  	}
657.  }
658.  
659.  static void
660.  m_detach(mtmp)
661.  register struct monst *mtmp;
662.  {
663.  #ifdef WALKIES
664.  	if(mtmp->mleashed) m_unleash(mtmp);
665.  #endif
666.  	relobj(mtmp,1);
667.  	unpmon(mtmp);
668.  	relmon(mtmp);
669.  	unstuck(mtmp);
670.  }
671.  
672.  void
673.  mondead(mtmp)
674.  register struct monst *mtmp;
675.  {
676.  	m_detach(mtmp);	
677.  #ifdef KOPS
678.  	if(mtmp->data->mlet == S_KOP && allow_kops) {
679.  	    /* Dead Kops may come back. */
680.  	    switch(rnd(5)) {
681.  		case 1:	     /* returns near the stairs */
682.  			(void) mkmon_at(mtmp->data->mname,xdnstair,ydnstair);
683.  			break;
684.  		case 2:	     /* randomly */
685.  			(void) mkmon_at(mtmp->data->mname,0,0);
686.  			break;
687.  		default:
688.  			break;
689.  	    }
690.  	}
691.  #endif
692.  	if(mtmp->isshk) shkdead(mtmp);
693.  	if(mtmp->isgd) gddead();
694.  #ifdef WORM
695.  	if(mtmp->wormno) wormdead(mtmp);
696.  #endif
697.  #ifdef HARD
698.  	if(mtmp->iswiz) wizdead(mtmp);
699.  #endif
700.  #ifdef MEDUSA
701.  	if(mtmp->data == &mons[PM_MEDUSA]) u.ukilled_medusa = TRUE;
702.  #endif
703.  	monfree(mtmp);
704.  }
705.  
706.  /* called when monster is moved to larger structure */
707.  void
708.  replmon(mtmp, mtmp2)
709.  register struct monst *mtmp, *mtmp2;
710.  {
711.  	relmon(mtmp);
712.  	monfree(mtmp);
713.  	levl[mtmp2->mx][mtmp2->my].mmask = 1;
714.  	mtmp2->nmon = fmon;
715.  	fmon = mtmp2;
716.  	if(u.ustuck == mtmp) u.ustuck = mtmp2;
717.  	if(mtmp2->isshk) replshk(mtmp,mtmp2);
718.  	if(mtmp2->isgd) replgd(mtmp,mtmp2);
719.  }
720.  
721.  void
722.  relmon(mon)
723.  register struct monst *mon;
724.  {
725.  	register struct monst *mtmp;
726.  
727.  	if (fmon == 0)  panic ("relmon: no fmon available.");
728.  
729.  	levl[mon->mx][mon->my].mmask = 0;
730.  
731.  	if(mon == fmon) fmon = fmon->nmon;
732.  	else {
733.  		for(mtmp = fmon; mtmp && mtmp->nmon != mon; mtmp = mtmp->nmon) ;
734.  		if(mtmp)    mtmp->nmon = mon->nmon;
735.  		else	    panic("relmon: mon not in list.");
736.  	}
737.  }
738.  
739.  /* we do not free monsters immediately, in order to have their name
740.     available shortly after their demise */
741.  void
742.  monfree(mtmp) register struct monst *mtmp; {
743.  	mtmp->nmon = fdmon;
744.  	fdmon = mtmp;
745.  	levl[mtmp->mx][mtmp->my].mmask = 0;
746.  }
747.  
748.  void
749.  unstuck(mtmp)
750.  register struct monst *mtmp;
751.  {
752.  	if(u.ustuck == mtmp) {
753.  		if(u.uswallow){
754.  			u.ux = mtmp->mx;
755.  			u.uy = mtmp->my;
756.  			u.uswallow = 0;
757.  			setsee();
758.  			docrt();
759.  		}
760.  		u.ustuck = 0;
761.  	}
762.  }
763.  
764.  void
765.  killed(mtmp)
766.  register struct monst *mtmp;
767.  {
768.  	xkilled(mtmp, 1);
769.  }
770.  
771.  void
772.  xkilled(mtmp, dest)
773.  	register struct monst *mtmp;
774.  /*
775.   * Dest=1, normal; dest=0, don't print message; dest=2, don't drop corpse
776.   * either; dest=3, message but no corpse
777.   */
778.  	int	dest;
779.  {
780.  	register int tmp, nk, x, y;
781.  	register struct permonst *mdat = mtmp->data;
782.  	register struct obj *otmp;
783.  	boolean chance;
784.  
785.  	if (dest & 1) {
786.  	    if(!cansee(mtmp->mx,mtmp->my)) You("destroy it!");
787.  	    else {
788.  		You("destroy %s!",
789.  			mtmp->mtame ? a_monnam(mtmp, "poor") : mon_nam(mtmp));
790.  	    }
791.  	}
792.  
793.  	/* restore chameleon, lycanthropes to true form at death */
794.  	/* cannot do this in make_corpse() since genociding monsters after
795.  	 * MAXMONNO were killed does the wrong type
796.  	 */
797.  	if(mtmp->cham) mtmp->data = mdat = &mons[PM_CHAMELEON];
798.  	if(mdat == &mons[PM_JACKALWERE])
799.  		mtmp->data = mdat = &mons[PM_WEREJACKAL];
800.  	if(mdat == &mons[PM_WOLFWERE])
801.  		mtmp->data = mdat = &mons[PM_WEREWOLF];
802.  	if(mdat == &mons[PM_RATWERE])
803.  		mtmp->data = mdat = &mons[PM_WERERAT];
804.  
805.  	if(u.umconf) {
806.  	    if(!Blind) {
807.  		Your("%s stop glowing %s.",
808.  		makeplural(body_part(HAND)),
809.  		Hallucination ? hcolor() : red);
810.  	    }
811.  	    u.umconf = 0;
812.  	}
813.  
814.  	/* if we have killed MAXMONNO monsters of a given type, and it
815.  	 * can be done, genocide that monster.
816.  	 */
817.  	tmp = monsndx(mdat);
818.  	u.nr_killed[tmp]++;
819.  	nk = u.nr_killed[tmp];
820.  #ifdef TOLKIEN
821.  	if(nk > (tmp==PM_NAZGUL ? 9 : MAXMONNO) &&
822.  				!(mons[tmp].geno & (G_NOGEN | G_GENOD))) {
823.  #else
824.  	if(nk > MAXMONNO && !(mons[tmp].geno & (G_NOGEN | G_GENOD))) {
825.  #endif
826.  #ifdef DEBUG
827.  		pline("Automatically genocided %s.", makeplural(mons[tmp].mname));
828.  #endif
829.  		mons[tmp].geno |= G_GENOD;
830.  	}
831.  #ifdef MAIL
832.  	/* If you kill the mail daemon, no more mail delivery.  -3. */
833.  	else if(tmp==PM_MAIL_DAEMON) mons[tmp].geno |= G_GENOD;
834.  #endif	
835.  
836.  	/* punish bad behaviour */
837.  	if(is_human(mdat) && !always_hostile(mdat) &&
838.  	   (monsndx(mdat) < PM_ARCHEOLOGIST || monsndx(mdat) > PM_WIZARD) &&
839.  	   u.ualigntyp != U_CHAOTIC) {
840.  		HTelepat &= ~INTRINSIC;
841.  		change_luck(-2);
842.  	}
843.  	if((mtmp->mpeaceful && !rn2(2)) || mtmp->mtame)	change_luck(-1);
844.  	if ((mdat==&mons[PM_BLACK_UNICORN] && u.ualigntyp == U_CHAOTIC) ||
845.  	    (mdat==&mons[PM_GREY_UNICORN] && u.ualigntyp == U_NEUTRAL) ||
846.  	    (mdat==&mons[PM_WHITE_UNICORN] && u.ualigntyp == U_LAWFUL))
847.  		change_luck(-5);
848.  
849.  	/* give experience points */
850.  	tmp = experience(mtmp, nk);
851.  	more_experienced(tmp, 0);
852.  	newexplevel();		/* will decide if you go up */
853.  
854.  	/* adjust alignment points */
855.  	if(mtmp->mtame)
856.  		adjalign(-15);	/* bad!! */
857.  #if defined(ALTARS) && defined(THEOLOGY)
858.  	else if (mtmp->ispriest && !p_coaligned(mtmp))
859.  		adjalign(2);
860.  #endif
861.  	else if (mtmp->mpeaceful)
862.  		adjalign(-5);
863.  	/* malign was already adjusted for ualigntyp and randomization */
864.  	adjalign(mtmp->malign);
865.  
866.  	/* dispose of monster and make cadaver */
867.  	if(stoned) {
868.  		monstone(mtmp);
869.  		return;
870.  	}
871.  
872.  	x = mtmp->mx;   y = mtmp->my;
873.  
874.  	mondead(mtmp);
875.  
876.  	if((dest & 2)
877.  #ifdef REINCARNATION
878.  		 || dlevel == rogue_level
879.  #endif
880.  					) return;
881.  
882.  #ifdef WORM
883.  	if(mdat == &mons[PM_LONG_WORM]) {
884.  		(void) mksobj_at(WORM_TOOTH, x, y);
885.  		stackobj(fobj);
886.  		newsym(x,y);
887.  	}
888.  #endif
889.  #ifdef MAIL
890.  	if(mdat == &mons[PM_MAIL_DAEMON]) {
891.  		(void) mksobj_at(SCR_MAIL, x, y);
892.  		stackobj(fobj);
893.  		newsym(x,y);
894.  	}
895.  #endif
896.  	if(!ACCESSIBLE(levl[x][y].typ) ||
897.  	   (IS_DOOR(levl[x][y].typ) &&
898.  	    levl[x][y].doormask & (D_CLOSED | D_LOCKED))) {
899.  	    /* might be mimic in wall or dead eel*/
900.   	    newsym(x,y);
901.  	} else if(x != u.ux || y != u.uy) {
902.  		/* might be here after swallowed */
903.  		if (!rn2(6) && !(mdat->geno & G_NOCORPSE)
904.  #ifdef KOPS
905.  					&& mdat->mlet != S_KOP
906.  #endif
907.  							) {
908.  			int typ;
909.  
910.  			otmp = mkobj_at(RANDOM_SYM, x, y);
911.  			/* Don't create large objects from small monsters */
912.  			typ = otmp->otyp;
913.  			if (!bigmonst(mdat) && typ != FOOD_RATION
914.  #ifdef WALKIES
915.  			    && typ != LEASH
916.  #endif
917.  			    && typ != FIGURINE
918.  			    && (otmp->owt > 3 ||
919.  				(typ >= SPEAR && typ <= LANCE) ||
920.  				(typ >= SCIMITAR && typ <= KATANA) ||
921.  				(typ == MORNING_STAR || typ == QUARTERSTAFF) ||
922.  				(typ >= BARDICHE && typ <= VOULGE) ||
923.  				(typ>=PLATE_MAIL && typ<=DRAGON_SCALE_MAIL) ||
924.  				(typ == LARGE_SHIELD))) {
925.  			    delobj(otmp);
926.  			} else newsym(x,y);
927.  		}
928.  		/* Whether or not it always makes a corpse is, in theory,
929.  		 * different from whether or not the corpse is "special";
930.  		 * if we want both, we have to specify it explicitly.
931.  		 */
932.  		if (bigmonst(mdat)
933.  #ifdef GOLEMS
934.  				   || is_golem(mdat)
935.  #endif
936.  		   ) chance = 1;
937.  		else chance = !rn2((int)
938.  			(2 + ((mdat->geno & G_FREQ)<2) + verysmall(mdat)));
939.  		if (chance)
940.  			(void) make_corpse(mtmp);
941.  	}
942.  }
943.  
944.  /*VARARGS2*/
945.  void
946.  kludge(str, arg, arg2, arg3)
947.  	register char *str,*arg,*arg2,*arg3;
948.  {
949.  	if(Blind || !flags.verbose) {
950.  		if(*str == '%') pline(str,"It",arg2,arg3);
951.  		else pline(str,"it",arg2,arg3);
952.  	} else pline(str,arg,arg2,arg3);
953.  }
954.  
955.  void
956.  rescham() {	/* force all chameleons to become normal */
957.  
958.  	register struct monst *mtmp;
959.  
960.  	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
961.  		if(mtmp->cham) {
962.  			mtmp->cham = 0;
963.  			(void) newcham(mtmp, &mons[PM_CHAMELEON]);
964.  		}
965.  		if(is_were(mtmp->data) && mtmp->data->mlet != S_HUMAN)
966.  			(void) new_were(mtmp);
967.  	}
968.  }
969.  
970.  /* Let the chameleons change again -dgk */
971.  void
972.  restartcham() {
973.  
974.  	register struct monst *mtmp;
975.  
976.  	for (mtmp = fmon; mtmp; mtmp = mtmp->nmon)
977.  		if (mtmp->data->mlet == S_CHAMELEON)
978.  			mtmp->cham = 1;
979.  }
980.  
981.  int
982.  newcham(mtmp, mdat)	/* make a chameleon look like a new monster */
983.  			/* returns 1 if the monster actually changed */
984.  	register struct monst *mtmp;
985.  	register struct permonst *mdat;
986.  {
987.  	register int mhp, hpn, hpd;
988.  	int tryct;
989.  
990.  	/* mdat = 0 -> caller wants a random monster shape */
991.  	tryct = 0;
992.  	if(mdat == 0) {
993.  		while (++tryct < 100) {
994.  			static int num;
995.  			mdat = &mons[num=rn2(NUMMONS)];
996.  			if ((!is_human(mdat) || num == PM_NURSE)
997.  				&& !type_is_pname(mdat)
998.  				&& !is_were(mdat)
999.  #ifdef MEDUSA
1000. 				&& num != PM_MEDUSA
1001. #endif
1002. #ifdef MAIL
1003. 				&& num != PM_MAIL_DAEMON
1004. #endif
1005. 				)
1006. 				break;
1007. 		}
1008. 		if (tryct >= 100) return(0); /* Should never happen */
1009. 	}
1010.   	if(mdat == mtmp->data) return(0);	/* still the same monster */
1011. 
1012. #ifdef WORM
1013. 	if(mtmp->wormno) wormdead(mtmp);	/* throw tail away */
1014. #endif
1015. 	mtmp->m_lev = adj_lev(mdat);		/* new monster level */
1016. 
1017. 	hpn = mtmp->mhp;
1018.  	hpd = (mtmp->m_lev < 50) ? (mtmp->m_lev)*8 : mdat->mlevel;
1019.  	if(!hpd) hpd = 4;
1020.  	mhp = (mtmp->m_lev < 50) ? (mtmp->m_lev)*8 : mdat->mlevel;
1021.  	if(!mhp) mhp = 4;
1022. 
1023. 	/* new hp: same fraction of max as before */
1024. #ifndef LINT
1025.  	mtmp->mhp = (int)(((long)hpn*(long)mhp)/(long)hpd);
1026. #endif
1027.  	if(mtmp->mhp < 0) mtmp->mhp = hpn;	/* overflow */
1028. /* Unlikely but not impossible; a 1HD creature with 1HP that changes into a
1029.    0HD creature will require this statement */
1030.  	if (!mtmp->mhp) mtmp->mhp = 1;
1031. 
1032. /* and the same for maximum hit points */
1033. 	hpn = mtmp->mhpmax;
1034. #ifndef LINT
1035.  	mtmp->mhpmax = (int)(((long)hpn*(long)mhp)/(long)hpd);
1036. #endif
1037.  	if(mtmp->mhpmax < 0) mtmp->mhpmax = hpn;	/* overflow */
1038.  	if (!mtmp->mhpmax) mtmp->mhpmax = 1;
1039. 
1040.  	mtmp->data = mdat;
1041. 	mtmp->minvis = !!(mdat->mlet == S_STALKER);
1042. 	mtmp->mhide = !!hides_under(mdat);
1043. 	if (!mtmp->mhide) mtmp->mundetected = 0;
1044. 	if (u.ustuck == mtmp
1045. #ifdef POLYSELF
1046. 			&& !sticks(uasmon)
1047. #endif
1048. 			&& !sticks(mdat))
1049. 		u.ustuck = 0;
1050. #ifdef WORM
1051. 	if(mdat == &mons[PM_LONG_WORM] && getwn(mtmp)) initworm(mtmp);
1052. 			/* perhaps we should clear mtmp->mtame here? */
1053. #endif
1054. 	unpmon(mtmp);	/* necessary for 'I' and to force pmon */
1055. 	pmon(mtmp);
1056. 	return(1);
1057. }
1058. 
1059. void
1060. mnexto(mtmp)	/* Make monster mtmp next to you (if possible) */
1061. 	struct monst *mtmp;
1062. {
1063. 	coord mm;
1064. 	enexto(&mm, u.ux, u.uy);
1065. 	levl[mtmp->mx][mtmp->my].mmask = 0;
1066. 	levl[mm.x][mm.y].mmask = 1;
1067. 	mtmp->mx = mm.x;
1068. 	mtmp->my = mm.y;
1069. 	pmon(mtmp);
1070. 	set_apparxy(mtmp);
1071. }
1072. 
1073. void
1074. mnearto(mtmp,x,y,gz)	/* Make monster near (or at) location if possible */
1075. 	register struct monst *mtmp;
1076. 	xchar x, y;
1077. 	boolean gz;     
1078. {
1079. 	coord mm;
1080. 	if(!gz || !goodpos(x,y)) {
1081. 		enexto(&mm, x, y);
1082. 		x = mm.x; y = mm.y;
1083. 	}
1084. 	if(x == mtmp->mx && y == mtmp->my) /* that was easy */
1085. 		return;
1086. 	levl[mtmp->mx][mtmp->my].mmask = 0;
1087. 	levl[x][y].mmask = 1;
1088. 	mtmp->mx = x;
1089. 	mtmp->my = y;
1090. 	pmon(mtmp);
1091. 	set_apparxy(mtmp);
1092. }
1093. 
1094. void
1095. setmangry(mtmp)
1096. 	register struct monst *mtmp;
1097. {
1098. 	if(!mtmp->mpeaceful) return;
1099. 	if(mtmp->mtame) return;
1100. 	mtmp->mpeaceful = 0;
1101. #if defined(ALTARS) && defined(THEOLOGY)
1102. 	if(mtmp->ispriest) {
1103. 		if(p_coaligned(mtmp)) adjalign(-5); /* very bad */
1104. 		else adjalign(2);
1105. 	} else
1106. #endif
1107. 	adjalign(-1);		/* attacking peaceful monsters is bad */
1108. 	if(humanoid(mtmp->data) || mtmp->isshk || mtmp->isgd)
1109. 		pline("%s gets angry!", Monnam(mtmp));
1110. #ifdef SOUNDS
1111. 	else if (flags.verbose && flags.soundok) growl(mtmp);
1112. #endif
1113. }
1114. 
1115. int
1116. disturb(mtmp)		/* awaken monsters while in the same room.
1117. 			 * return a 1 if they have been woken.
1118. 			 */
1119. 	register struct monst *mtmp;
1120. {
1121. 	/* wake up, or get out of here. */
1122. 	/* ettins are hard to surprise */
1123. 	/* Nymphs and Leprechauns do not easily wake up */
1124. 	if(cansee(mtmp->mx,mtmp->my) &&
1125. 		(!Stealth || (mtmp->data == &mons[PM_ETTIN] && rn2(10))) &&
1126. 		(!(mtmp->data->mlet == S_NYMPH
1127. 		   || mtmp->data->mlet == S_LEPRECHAUN) || !rn2(50)) &&
1128. 		(Aggravate_monster ||
1129. 		 (mtmp->data->mlet == S_DOG || mtmp->data->mlet == S_HUMAN) ||
1130. 		(!rn2(7) && !mtmp->mimic))) {
1131. 		mtmp->msleep = 0;
1132. 		return(1);
1133. 	}
1134. 	if(Hallucination) pmon(mtmp);
1135. 	return(0);
1136. }
1137. 
1138. #ifdef HARD
1139. static boolean
1140. restrap(mtmp)
1141. /* unwatched hiders may hide again,
1142.  * if so, a 1 is returned.
1143.  */
1144. register struct monst *mtmp;
1145. {
1146. 	if(mtmp->cham || mtmp->mcan || mtmp->mimic ||
1147. 	   cansee(mtmp->mx, mtmp->my) || rn2(3))
1148. 		return(FALSE);
1149. 
1150. 	if(mtmp->data->mlet == S_MIMIC) {
1151. 		set_mimic_sym(mtmp);
1152. 		return(TRUE);
1153. 	} else
1154. 	    if(levl[mtmp->mx][mtmp->my].typ == ROOM)  {
1155. 		(void) maketrap(mtmp->mx, mtmp->my, MONST_TRAP);
1156. 		/* override type selection */
1157. 		ftrap->pm = monsndx(mtmp->data);
1158. 		mondead(mtmp);
1159. 		return(TRUE);
1160. 	    }
1161. 
1162. 	return(FALSE);
1163. }
1164. #endif
1165. 
1166. /* drop (perhaps) a cadaver and remove monster */
1167. void
1168. mondied(mdef)
1169. register struct monst *mdef;
1170. {
1171. 	mondead(mdef);
1172. 	if(rn2(3)
1173. #ifdef REINCARNATION
1174. 	   && dlevel != rogue_level
1175. #endif
1176. 					)
1177. 		(void) make_corpse(mdef);
1178. }
1179. 
1180. /* monster disappears, not dies */
1181. void
1182. mongone(mdef)
1183. register struct monst *mdef;
1184. {
1185. 	register struct obj *otmp, *otmp2;
1186. 
1187. 	/* release monster's inventory */
1188. 	for (otmp = mdef->minvent; otmp; otmp = otmp2) {
1189. 		otmp2 = otmp->nobj;
1190. 		obfree(otmp, (struct obj *)0);
1191. 	}
1192. 	mdef->minvent = 0;
1193. 	mdef->mgold = 0;
1194. 	m_detach(mdef);
1195. 	monfree(mdef);
1196. }
1197. 
1198. /* drop a statue or rock and remove monster */
1199. void
1200. monstone(mdef)
1201. register struct monst *mdef;
1202. {
1203. 	struct obj *otmp;
1204. 
1205. 	if(!verysmall(mdef->data) ||
1206. 	   !rn2(2 + ((mdef->data->geno & G_FREQ) > 2))) {
1207. 		otmp = mk_named_object(STATUE, mdef->data, mdef->mx, mdef->my,
1208. 			NAME(mdef), (int)mdef->mnamelth);
1209. 		otmp->spe = 0; /* no book inside */
1210. 	} else
1211. 		(void) mksobj_at(ROCK, mdef->mx, mdef->my);
1212. 
1213. 	stackobj(fobj);
1214. 
1215. 	if(cansee(mdef->mx, mdef->my)){
1216. 		unpmon(mdef);
1217. 		atl(mdef->mx,mdef->my,Hallucination ? rndobjsym() : fobj->olet);
1218. 	}
1219. 	mondead(mdef);
1220. }
1221. 
1222. #ifdef GOLEMS
1223. void
1224. golemeffects(mon, damtype, dam)
1225. register struct monst *mon;
1226. int damtype, dam;
1227. {
1228. 	int heal=0, slow=0;
1229. 
1230. 	if (mon->data != &mons[PM_FLESH_GOLEM]
1231. 					&& mon->data != &mons[PM_IRON_GOLEM])
1232. 		return;
1233. 
1234. 	if (mon->data == &mons[PM_FLESH_GOLEM]) {
1235. 		if (damtype == AD_ELEC) heal = dam / 6;
1236. 		else if (damtype == AD_FIRE || damtype == AD_COLD) slow = 1;
1237. 	} else {
1238. 		if (damtype == AD_ELEC) slow = 1;
1239. 		else if (damtype == AD_FIRE) heal = dam;
1240. 	}
1241. 	if (slow) {
1242. 		if (mon->mspeed != MSLOW) {
1243. 			if (mon->mspeed == MFAST) mon->mspeed = 0;
1244. 			else mon->mspeed = MSLOW;
1245. 			if (cansee(mon->mx, mon->my))
1246. 				pline("%s seems to be moving slower.",
1247. 					Monnam(mon));
1248. 		}
1249. 	}
1250. 	if (heal) {
1251. 		if (mon->mhp < mon->mhpmax) {
1252. 			mon->mhp += dam;
1253. 			if (mon->mhp > mon->mhpmax) mon->mhp = mon->mhpmax;
1254. 			if (cansee(mon->mx, mon->my))
1255. 				pline("%s seems healthier.", Monnam(mon));
1256. 		}
1257. 	}
1258. }
1259. #endif /* GOLEMS */