Source:Hack 1.0/hack.mon.c

From NetHackWiki
Revision as of 22:28, 3 March 2008 by Kernigh bot (talk | contribs) (Hack 1.0/hack.mon.c moved to Source:Hack 1.0/hack.mon.c: Robot: moved page)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

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

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

Screenshots and source code from Hack are used under the CWI license.

1.    /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */
2.    
3.    #include "hack.h"
4.    #include "hack.mfndpos.h"
5.    #define	SIZE(x)	(int)(sizeof(x) / sizeof(x[0]))
6.    #define	NULL	(char *) 0
7.    extern struct monst *makemon();
8.    
9.    int warnlevel;		/* used by movemon and dochugw */
10.   long lastwarntime;
11.   int lastwarnlev;
12.   char *warnings[] = {
13.   	"white", "pink", "red", "ruby", "purple", "black"
14.   };
15.   
16.   movemon()
17.   {
18.   	register struct monst *mtmp;
19.   	register int fr;
20.   
21.   	warnlevel = 0;
22.   
23.   	while(1) {
24.   		/* find a monster that we haven't treated yet */
25.   		/* note that mtmp or mtmp->nmon might get killed
26.   		   while mtmp moves, so we cannot just walk down the
27.   		   chain (even new monsters might get created!) */
28.   		for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
29.   			if(mtmp->mlstmv < moves) goto next_mon;
30.   		/* treated all monsters */
31.   		break;
32.   
33.   	next_mon:
34.   		mtmp->mlstmv = moves;
35.   		if(mtmp->mblinded && !--mtmp->mblinded)
36.   			mtmp->mcansee = 1;
37.   		if(mtmp->mimic) continue;
38.   		if(mtmp->mspeed != MSLOW || !(moves%2)){
39.   			/* continue if the monster died fighting */
40.   			fr = -1;
41.   			if(Conflict && cansee(mtmp->mx,mtmp->my)
42.   				&& (fr = fightm(mtmp)) == 2)
43.   				continue;
44.   			if(fr<0 && dochugw(mtmp))
45.   				continue;
46.   		}
47.   		if(mtmp->mspeed == MFAST && dochugw(mtmp))
48.   			continue;
49.   	}
50.   
51.   	warnlevel -= u.ulevel;
52.   	if(warnlevel >= SIZE(warnings))
53.   		warnlevel = SIZE(warnings)-1;
54.   	if(warnlevel >= 0)
55.   	if(warnlevel > lastwarnlev || moves > lastwarntime + 5){
56.   	    register char *rr;
57.   	    switch(Warning & (LEFT_RING | RIGHT_RING)){
58.   	    case LEFT_RING:
59.   		rr = "Your left ring glows";
60.   		break;
61.   	    case RIGHT_RING:
62.   		rr = "Your right ring glows";
63.   		break;
64.   	    case LEFT_RING | RIGHT_RING:
65.   		rr = "Both your rings glow";
66.   		break;
67.   	    default:
68.   		rr = "Your fingertips glow";
69.   		break;
70.   	    }
71.   	    pline("%s %s!", rr, warnings[warnlevel]);
72.   	    lastwarntime = moves;
73.   	    lastwarnlev = warnlevel;
74.   	}
75.   
76.   	dmonsfree();	/* remove all dead monsters */
77.   }
78.   
79.   justswld(mtmp,name)
80.   register struct monst *mtmp;
81.   char *name;
82.   {
83.   
84.   	mtmp->mx = u.ux;
85.   	mtmp->my = u.uy;
86.   	u.ustuck = mtmp;
87.   	pmon(mtmp);
88.   	kludge("%s swallows you!",name);
89.   	more();
90.   	seeoff(1);
91.   	u.uswallow = 1;
92.   	swallowed();
93.   }
94.   
95.   youswld(mtmp,dam,die,name)
96.   register struct monst *mtmp;
97.   register dam,die;
98.   char *name;
99.   {
100.  	if(mtmp != u.ustuck) return;
101.  	kludge("%s digests you!",name);
102.  	u.uhp -= dam;
103.  	if(u.uswldtim++ == die){
104.  		pline("It totally digests you!");
105.  		u.uhp = -1;
106.  	}
107.   if(u.uhp < 1) done_in_by(mtmp);
108.  }
109.  
110.  dochugw(mtmp) register struct monst *mtmp; {
111.  register x = mtmp->mx;
112.  register y = mtmp->my;
113.  register d = dochug(mtmp);
114.  register dd;
115.  	if(!d)		/* monster still alive */
116.  	if(Warning)
117.  	if(!mtmp->mpeaceful)
118.  	if((dd = dist(mtmp->mx,mtmp->my)) < dist(x,y))
119.  	if(dd < 100)
120.  	if(!cansee(mtmp->mx, mtmp->my) || (mtmp->minvis && !See_invisible))
121.  	if(mtmp->data->mlevel > warnlevel)
122.  		warnlevel = mtmp->data->mlevel;
123.  	return(d);
124.  }
125.  
126.  /* returns 1 if monster died moving, 0 otherwise */
127.  dochug(mtmp)
128.  register struct monst *mtmp;
129.  {
130.  	register struct permonst *mdat;
131.  	register tmp;
132.  
133.  	if(mtmp->cham && !rn2(6))
134.  		(void) newcham(mtmp, &mons[dlevel+14+rn2(CMNUM-14-dlevel)]);
135.  	mdat = mtmp->data;
136.  	if(mdat->mlevel < 0)
137.  		panic("bad monster %c (%d)",mdat->mlet,mdat->mlevel);
138.  	if((!(moves%20) || index("ViT",mdat->mlet)) &&
139.  	    mtmp->mhp<mtmp->orig_hp)
140.  		mtmp->mhp++; /* regenerate monsters. */
141.  	if(mtmp->mfroz) return(0); /* frozen monsters don't do anything. */
142.  	if(mtmp->msleep) {/* wake up a monster, or get out of here. */
143.  		if(cansee(mtmp->mx,mtmp->my) && !Stealth &&
144.  			(!index("NL",mdat->mlet) || !rn2(50)) &&
145.  			(Aggravate_monster || (!rn2(7) && !mtmp->mimic)))
146.  			mtmp->msleep = 0;
147.  		else return(0);
148.  	}
149.  
150.  	/* not frozen or sleeping: wipe out texts written in the dust */
151.  	wipe_engr_at(mtmp->mx, mtmp->my, 1);
152.  
153.  	/* confused monsters get unconfused with small probability */
154.  	if(mtmp->mconf && !rn2(50)) mtmp->mconf = 0;
155.  
156.  	/* some monsters teleport */
157.  	if(mtmp->mflee && index("tNL", mdat->mlet) && !rn2(40)){
158.  		rloc(mtmp);
159.  		return(0);
160.  	}
161.  	if(mdat->mmove < rnd(6)) return(0);
162.  	if((mtmp->mflee ||
163.  		mtmp->mconf ||
164.  		(index("BIuy", mdat->mlet) && !rn2(4)) ||
165.  		(mdat->mlet == 'L' && !u.ugold && (mtmp->mgold || rn2(2))) ||
166.  		dist(mtmp->mx,mtmp->my) > 2 ||
167.  		(!mtmp->mcansee && !rn2(4)) ||
168.  		mtmp->mpeaceful
169.  	   ) && (tmp = m_move(mtmp,0)) && mdat->mmove <= 12)
170.  		return(tmp == 2);
171.  	if(tmp == 2) return(1);	/* monster died moving */
172.  
173.  	if(!index("Ea", mdat->mlet) && dist(mtmp->mx, mtmp->my) < 3 &&
174.  	 !mtmp->mpeaceful && u.uhp > 0 &&
175.  	 !sengr_at("Elbereth", u.ux, u.uy) &&
176.  	 !sobj_at(SCR_SCARE_MONSTER, u.ux, u.uy)) {
177.  		if(mhitu(mtmp))
178.  			return(1);	/* monster died (e.g. 'y' or 'F') */
179.  	}
180.  	/* extra movement for fast monsters */
181.  	if(mdat->mmove-12 > rnd(12)) tmp = m_move(mtmp,1);
182.  	return(tmp == 2);
183.  }
184.  
185.  inrange(mtmp)
186.  register struct monst *mtmp;
187.  {
188.  	register schar tx,ty;
189.  
190.  	/* spit fire only when both in a room or both in a corridor */
191.  	if(inroom(u.ux,u.uy) != inroom(mtmp->mx,mtmp->my)) return;
192.  	tx = u.ux - mtmp->mx;
193.  	ty = u.uy - mtmp->my;
194.  	if((!tx && abs(ty) < 8) || (!ty && abs(tx) < 8)
195.  	    || (abs(tx) == abs(ty) && abs(tx) < 8)){
196.  		/* spit fire in the direction of @ (not nec. hitting) */
197.  		buzz(-1,mtmp->mx,mtmp->my,sgn(tx),sgn(ty));
198.  		if(u.uhp < 1) done_in_by(mtmp);
199.  	}
200.  }
201.  
202.  m_move(mtmp,after)
203.  register struct monst *mtmp;
204.  {
205.  	register struct monst *mtmp2;
206.  	register nx,ny,omx,omy,appr,nearer,cnt,i,j;
207.  	xchar gx,gy,nix,niy,chcnt;
208.  	schar chi;
209.  	boolean likegold, likegems, likeobjs;
210.  	schar mmoved = 0;	/* not strictly nec.: chi >= 0 will do */
211.  	coord poss[9];
212.  	int info[9];
213.  
214.  	if(mtmp->mtrapped) {
215.  		i = mintrap(mtmp);
216.  		if(i == 2) return(2);	/* he died */
217.  		if(i == 1) return(0);	/* still in trap, so didnt move */
218.  	}
219.  	if(mtmp->mhide && o_at(mtmp->mx,mtmp->my) && rn2(10))
220.  		return(0);		/* do not leave hiding place */
221.  
222.  	/* my dog gets a special treatment */
223.  	if(mtmp->mtame) {
224.  		return( dog_move(mtmp, after) );
225.  	}
226.  
227.  	/* likewise for shopkeeper */
228.  	if(mtmp->isshk) {
229.  		mmoved = shk_move();
230.  		goto postmov;
231.  	}
232.  
233.  	/* and for the guard */
234.  	if(mtmp->isgd) {
235.  		mmoved = gd_move();
236.  		goto postmov;
237.  	}
238.  
239.  	if(mtmp->data->mlet == 't' && !rn2(5)) {
240.  		if(rn2(2))
241.  			mnexto(mtmp);
242.  		else
243.  			rloc(mtmp);
244.  		mmoved = 1;
245.  		goto postmov;
246.  	}
247.  	if(mtmp->data->mlet == 'D' && !mtmp->mcan)
248.  		inrange(mtmp);
249.  	if(!Blind && !Confusion && mtmp->data->mlet == 'U' && !mtmp->mcan
250.  		&& cansee(mtmp->mx,mtmp->my) && rn2(5)) {
251.  		pline("%s's gaze has confused you!", Monnam(mtmp));
252.  		if(rn2(5)) mtmp->mcan = 1;
253.  		Confusion = d(3,4);		/* timeout */
254.  	}
255.  	if(!mtmp->mflee && u.uswallow && u.ustuck != mtmp) return(1);
256.  	appr = 1;
257.  	if(mtmp->mflee) appr = -1;
258.  	if(mtmp->mconf || Invis ||  !mtmp->mcansee ||
259.  		(index("BIy",mtmp->data->mlet) && !rn2(3)))
260.  		appr = 0;
261.  	omx = mtmp->mx;
262.  	omy = mtmp->my;
263.  	gx = u.ux;
264.  	gy = u.uy;
265.  	if(mtmp->data->mlet == 'L' && appr == 1 && mtmp->mgold > u.ugold)
266.  		appr = -1;
267.  #ifdef TRACK
268.  	/* random criterion for 'smell'
269.  	   should use mtmp->msmell
270.  	 */
271.  	if('a' <= mtmp->data->mlet && mtmp->data->mlet <= 'z') {
272.  	extern coord *gettrack();
273.  	register coord *cp;
274.  	schar mroom;
275.  		mroom = inroom(omx,omy);
276.  		if(mroom < 0 || mroom != inroom(u.ux,u.uy)){
277.  		    cp = gettrack(omx,omy);
278.  		    if(cp){
279.  			gx = cp->x;
280.  			gy = cp->y;
281.  		    }
282.  		}
283.  	}
284.  #endif TRACK
285.  	/* look for gold or jewels nearby */
286.  	likegold = (index("LOD", mtmp->data->mlet) != NULL);
287.  	likegems = (index("ODu", mtmp->data->mlet) != NULL);
288.  	likeobjs = mtmp->mhide;
289.  #define	SRCHRADIUS	25
290.  	{ xchar mind = SRCHRADIUS;		/* not too far away */
291.  	  register int dd;
292.  	  if(likegold){
293.  		register struct gen *gold;
294.  		for(gold = fgold; gold; gold = gold->ngen)
295.  		  if((dd = DIST(omx,omy,gold->gx,gold->gy)) < mind){
296.  		    mind = dd;
297.  		    gx = gold->gx;
298.  		    gy = gold->gy;
299.  		}
300.  	  }
301.  	  if(likegems || likeobjs){
302.  		register struct obj *otmp;
303.  		for(otmp = fobj; otmp; otmp = otmp->nobj)
304.  		if(likeobjs || otmp->olet == GEM_SYM)
305.  		if(mtmp->data->mlet != 'u' ||
306.  			objects[otmp->otyp].g_val != 0)
307.  		if((dd = DIST(omx,omy,otmp->ox,otmp->oy)) < mind){
308.  		    mind = dd;
309.  		    gx = otmp->ox;
310.  		    gy = otmp->oy;
311.  		}
312.  	  }
313.  	  if(mind < SRCHRADIUS && appr == -1) {
314.  		if(dist(omx,omy) < 10) {
315.  		    gx = u.ux;
316.  		    gy = u.uy;
317.  		} else
318.     appr = 1;
319.  	  }
320.  	}
321.  	nix = omx;
322.  	niy = omy;
323.  	cnt = mfndpos(mtmp,poss,info,
324.  		mtmp->data->mlet == 'u' ? NOTONL :
325.  		index(" VWZ", mtmp->data->mlet) ? NOGARLIC : ALLOW_TRAPS);
326.  		/* ALLOW_ROCK for some monsters ? */
327.  	chcnt = 0;
328.  	chi = -1;
329.  	for(i=0; i<cnt; i++) {
330.  		nx = poss[i].x;
331.  		ny = poss[i].y;
332.  		for(j=0; j<MTSZ && j<cnt-1; j++)
333.  			if(nx == mtmp->mtrack[j].x && ny == mtmp->mtrack[j].y)
334.  				if(rn2(4*(cnt-j))) goto nxti;
335.  #ifdef STUPID
336.  		/* some stupid compilers think that this is too complicated */
337.  		{ int d1 = DIST(nx,ny,gx,gy);
338.  		  int d2 = DIST(nix,niy,gx,gy);
339.  		  nearer = (d1 < d2);
340.  		}
341.  #else
342.  		nearer = (DIST(nx,ny,gx,gy) < DIST(nix,niy,gx,gy));
343.  #endif STUPID
344.  		if((appr == 1 && nearer) || (appr == -1 && !nearer) ||
345.  			!mmoved ||
346.  			(!appr && !rn2(++chcnt))){
347.  			nix = nx;
348.  			niy = ny;
349.  			chi = i;
350.  			mmoved = 1;
351.  		}
352.   nxti:	;
353.  	}
354.  	if(mmoved){
355.  		if(info[chi] & ALLOW_M){
356.  			mtmp2 = m_at(nix,niy);
357.  			if(hitmm(mtmp,mtmp2) == 1 && rn2(4) &&
358.  			  hitmm(mtmp2,mtmp) == 2) return(2);
359.  			return(0);
360.  		}
361.  		if(info[chi] & ALLOW_U){
362.  		  (void) hitu(mtmp, d(mtmp->data->damn, mtmp->data->damd)+1);
363.  		  return(0);
364.  		}
365.  		mtmp->mx = nix;
366.  		mtmp->my = niy;
367.  		for(j=MTSZ-1; j>0; j--) mtmp->mtrack[j] = mtmp->mtrack[j-1];
368.  		mtmp->mtrack[0].x = omx;
369.  		mtmp->mtrack[0].y = omy;
370.  #ifndef NOWORM
371.  		if(mtmp->wormno) worm_move(mtmp);
372.  #endif NOWORM
373.  	} else {
374.  		if(mtmp->data->mlet == 'u' && rn2(2)){
375.  			rloc(mtmp);
376.  			return(0);
377.  		}
378.  #ifndef NOWORM
379.  		if(mtmp->wormno) worm_nomove(mtmp);
380.  #endif NOWORM
381.  	}
382.  postmov:
383.  	if(mmoved == 1) {
384.  		if(mintrap(mtmp) == 2)	/* he died */
385.  			return(2);
386.  		if(likegold) mpickgold(mtmp);
387.  		if(likegems) mpickgems(mtmp);
388.  		if(mtmp->mhide) mtmp->mundetected = 1;
389.  	}
390.  	pmon(mtmp);
391.  	return(mmoved);
392.  }
393.  
394.  mpickgold(mtmp) register struct monst *mtmp; {
395.  register struct gen *gold;
396.  	while(gold = g_at(mtmp->mx, mtmp->my, fgold)){
397.  		mtmp->mgold += gold->gflag;
398.  		freegold(gold);
399.  		if(levl[mtmp->mx][mtmp->my].scrsym == '$')
400.  			newsym(mtmp->mx, mtmp->my);
401.  	}
402.  }
403.  
404.  mpickgems(mtmp) register struct monst *mtmp; {
405.  register struct obj *otmp;
406.  	for(otmp = fobj; otmp; otmp = otmp->nobj)
407.  	if(otmp->olet == GEM_SYM)
408.  	if(otmp->ox == mtmp->mx && otmp->oy == mtmp->my)
409.  	if(mtmp->data->mlet != 'u' || objects[otmp->otyp].g_val != 0){
410.  		freeobj(otmp);
411.  		mpickobj(mtmp, otmp);
412.  		if(levl[mtmp->mx][mtmp->my].scrsym == GEM_SYM)
413.  			newsym(mtmp->mx, mtmp->my);	/* %% */
414.  		return;	/* pick only one object */
415.  	}
416.  }
417.  
418.  /* return number of acceptable neighbour positions */
419.  mfndpos(mon,poss,info,flag)
420.  register struct monst *mon; coord poss[9]; int info[9], flag; {
421.  register int x,y,nx,ny,cnt = 0,tmp;
422.  register struct monst *mtmp;
423.  	x = mon->mx;
424.  	y = mon->my;
425.  	if(mon->mconf) {
426.  		flag |= ALLOW_ALL;
427.  		flag &= ~NOTONL;
428.  	}
429.  	for(nx = x-1; nx <= x+1; nx++) for(ny = y-1; ny <= y+1; ny++)
430.  	if(nx != x || ny != y) if(isok(nx,ny))
431.  	if((tmp = levl[nx][ny].typ) >= DOOR)
432.  	if(!(nx != x && ny != y &&
433.  		(levl[x][y].typ == DOOR || tmp == DOOR))){
434.  		info[cnt] = 0;
435.  		if(nx == u.ux && ny == u.uy){
436.  			if(!(flag & ALLOW_U)) continue;
437.  			info[cnt] = ALLOW_U;
438.  		} else if(mtmp = m_at(nx,ny)){
439.  			if(!(flag & ALLOW_M)) continue;
440.  			info[cnt] = ALLOW_M;
441.  			if(mtmp->mtame){
442.  				if(!(flag & ALLOW_TM)) continue;
443.  				info[cnt] |= ALLOW_TM;
444.  			}
445.  		}
446.  		if(sobj_at(CLOVE_OF_GARLIC, nx, ny)) {
447.  			if(flag & NOGARLIC) continue;
448.  			info[cnt] |= NOGARLIC;
449.  		}
450.  		if(sobj_at(SCR_SCARE_MONSTER, nx, ny) ||
451.  		   (!mon->mpeaceful && sengr_at("Elbereth", nx, ny))) {
452.  			if(!(flag & ALLOW_SSM)) continue;
453.  			info[cnt] |= ALLOW_SSM;
454.  		}
455.  		if(sobj_at(ENORMOUS_ROCK, nx, ny)) {
456.  			if(!(flag & ALLOW_ROCK)) continue;
457.  			info[cnt] |= ALLOW_ROCK;
458.  		}
459.  		if(!Invis && online(nx,ny)){
460.  			if(flag & NOTONL) continue;
461.  			info[cnt] |= NOTONL;
462.  		}
463.  		/* we cannot avoid traps of an unknown kind */
464.  		{ register struct gen *gtmp = g_at(nx, ny, ftrap);
465.  		  register int tt;
466.  			if(gtmp) {
467.  				tt = 1 << (gtmp->gflag & ~SEEN);
468.  				if(mon->mtrapseen & tt){
469.  					if(!(flag & tt)) continue;
470.  					info[cnt] |= tt;
471.  				}
472.  			}
473.  		}
474.  		poss[cnt].x = nx;
475.  		poss[cnt].y = ny;
476.  		cnt++;
477.  	}
478.  	return(cnt);
479.  }
480.  
481.  dist(x,y) int x,y; {
482.  	return((x-u.ux)*(x-u.ux) + (y-u.uy)*(y-u.uy));
483.  }
484.  
485.  poisoned(string, pname)
486.  register char *string, *pname;
487.  {
488.  	if(Blind) pline("It was poisoned.");
489.  	else pline("The %s was poisoned!",string);
490.  	if(Poison_resistance) {
491.  		pline("The poison doesn't seem to affect you.");
492.  		return;
493.  	}
494.  	switch(rnd(6)) {
495.  	case 1:
496.  		u.uhp = -1;
497.  		break;
498.  	case 2:
499.  	case 3:
500.  	case 4:
501.  		losestr(rn1(3,3));
502.  		break;
503.  	case 5:
504.  	case 6:
505.  		losehp(rn1(10,6), pname);
506.  		return;
507.  	}
508.  	if(u.uhp < 1) killer = pname;
509.  }
510.  
511.  mondead(mtmp)
512.  register struct monst *mtmp;
513.  {
514.  	relobj(mtmp,1);
515.  	unpmon(mtmp);
516.  	relmon(mtmp);
517.  	if(u.ustuck == mtmp) {
518.  		u.ustuck = 0;
519.  		if(u.uswallow) {
520.  			u.uswallow = 0;
521.  			setsee();
522.  			docrt();
523.  		}
524.  	}
525.  	if(mtmp->isshk) shkdead();
526.  	if(mtmp->isgd) gddead();
527.  #ifndef NOWORM
528.  	if(mtmp->wormno) wormdead(mtmp);
529.  #endif NOWORM
530.  	monfree(mtmp);
531.  }
532.  
533.  /* called when monster is moved to larger structure */
534.  replmon(mtmp,mtmp2)
535.  register struct monst *mtmp, *mtmp2;
536.  {
537.  	relmon(mtmp);
538.  	monfree(mtmp);
539.  	mtmp2->nmon = fmon;
540.  	fmon = mtmp2;
541.  }
542.  
543.  relmon(mon)
544.  register struct monst *mon;
545.  {
546.  	register struct monst *mtmp;
547.  
548.  	if(mon == fmon) fmon = fmon->nmon;
549.  	else {
550.  		for(mtmp = fmon; mtmp->nmon != mon; mtmp = mtmp->nmon) ;
551.  		mtmp->nmon = mon->nmon;
552.  	}
553.  }
554.  
555.  /* we do not free monsters immediately, in order to have their name
556.     available shortly after their demise */
557.  struct monst *fdmon;	/* chain of dead monsters, need not to be saved */
558.  
559.  monfree(mtmp) register struct monst *mtmp; {
560.  	mtmp->nmon = fdmon;
561.  	fdmon = mtmp;
562.  }
563.  
564.  dmonsfree(){
565.  register struct monst *mtmp;
566.  	while(mtmp = fdmon){
567.  		fdmon = mtmp->nmon;
568.  		free((char *) mtmp);
569.  	}
570.  }
571.  
572.  killed(mtmp) struct monst *mtmp; {
573.  #ifdef lint
574.  #define	NEW_SCORING
575.  #endif lint
576.  register int tmp,tmp2,nk,x,y;
577.  register struct permonst *mdat = mtmp->data;
578.  	if(mtmp->cham) mdat = PM_CHAM;
579.  	if(Blind) pline("You destroy it!");
580.  	else {
581.  		pline("You destroy %s!",
582.  			mtmp->mtame ? amonnam(mtmp, "poor") : monnam(mtmp));
583.  	}
584.  	if(u.umconf) {
585.  		if(!Blind) pline("Your hands stop glowing blue.");
586.  		u.umconf = 0;
587.  	}
588.  
589.  	/* count killed monsters */
590.  #define	MAXMONNO	100
591.  	nk = 1;		      /* in case we cannot find it in mons */
592.  	tmp = mdat - mons;    /* index in mons array (if not 'd', '@', ...) */
593.  	if(tmp >= 0 && tmp < CMNUM+2) {
594.  	    extern char fut_geno[];
595.  	    u.nr_killed[tmp]++;
596.  	    if((nk = u.nr_killed[tmp]) > MAXMONNO &&
597.  		!index(fut_geno, mdat->mlet))
598.  		    charcat(fut_geno,  mdat->mlet);
599.  	}
600.  
601.  	/* punish bad behaviour */
602.  	if(mdat->mlet == '@') Telepat = 0, u.uluck -= 2;
603.  	if(mtmp->mpeaceful || mtmp->mtame) u.uluck--;
604.  	if(mdat->mlet == 'u') u.uluck -= 5;
605.  
606.  	/* give experience points */
607.  	tmp = 1 + mdat->mlevel * mdat->mlevel;
608.  	if(mdat->ac < 3) tmp += 2*(7 - mdat->ac);
609.  	if(index("AcsSDXaeRTVWU&In:P", mdat->mlet))
610.  		tmp += 2*mdat->mlevel;
611.  	if(index("DeV&P",mdat->mlet)) tmp += (7*mdat->mlevel);
612.  	if(mdat->mlevel > 6) tmp += 50;
613.  
614.  #ifdef NEW_SCORING
615.  	/* ------- recent addition: make nr of points decrease
616.  		   when this is not the first of this kind */
617.  	{ int ul = u.ulevel;
618.  	  int ml = mdat->mlevel;
619.  
620.  	if(ul < 14)    /* points are given based on present and future level */
621.  	    for(tmp2 = 0; !tmp2 || ul + tmp2 <= ml; tmp2++)
622.  		if(u.uexp + 1 + (tmp + ((tmp2 <= 0) ? 0 : 4<<(tmp2-1)))/nk
623.  		    >= 10*pow((unsigned)(ul-1)))
624.  			if(++ul == 14) break;
625.  
626.  	tmp2 = ml - ul -1;
627.  	tmp = (tmp + ((tmp2 < 0) ? 0 : 4<<tmp2))/nk;
628.  	if(!tmp) tmp = 1;
629.  	}
630.  	/* note: ul is not necessarily the future value of u.ulevel */
631.  	/* ------- end of recent valuation change ------- */
632.  #endif NEW_SCORING
633.  
634.  	u.uexp += tmp;
635.  	u.urexp += 4*tmp;
636.  	flags.botl = 1;
637.  	while(u.ulevel < 14 && u.uexp >= 10*pow(u.ulevel-1)){
638.  		pline("Welcome to level %d.", ++u.ulevel);
639.  		tmp = rnd(10);
640.  		if(tmp < 3) tmp = rnd(10);
641.  		u.uhpmax += tmp;
642.  		u.uhp += tmp;
643.  		flags.botl = 1;
644.  	}
645.  
646.  	/* dispose of monster and make cadaver */
647.  	x = mtmp->mx;	y = mtmp->my;
648.  	mondead(mtmp);
649.  	tmp = mdat->mlet;
650.  	if(tmp == 'm') { /* he killed a minotaur, give him a wand of digging */
651.  			/* note: the dead minotaur will be on top of it! */
652.  		mksobj_at(WAND_SYM, WAN_DIGGING, x, y);
653.  		/* if(cansee(x,y)) atl(x,y,fobj->olet); */
654.  		stackobj(fobj);
655.  	} else
656.  #ifndef NOWORM
657.  	if(tmp == 'w') {
658.  		mksobj_at(WEAPON_SYM, WORM_TOOTH, x, y);
659.  		stackobj(fobj);
660.  	} else
661.  #endif	NOWORM
662.  	if(!letter(tmp) || !rn2(3)) tmp = 0;
663.  
664.  	if(levl[x][y].typ >= DOOR)	/* might be mimic in wall */
665.  	    if(x != u.ux || y != u.uy) /* might be here after swallowed */
666.  		if(index("NTVm&",mdat->mlet) || rn2(5)) {
667.  		mkobj_at(tmp,x,y);
668.  		if(cansee(x,y)) atl(x,y,fobj->olet);
669.  		stackobj(fobj);
670.  	}
671.  }
672.  
673.  kludge(str,arg)
674.  register char *str,*arg;
675.  {
676.  	if(Blind) {
677.  		if(*str == '%') pline(str,"It");
678.  		else pline(str,"it");
679.  	} else pline(str,arg);
680.  }
681.  
682.  rescham()	/* force all chameleons to become normal */
683.  {
684.  	register struct monst *mtmp;
685.  
686.  	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
687.  		if(mtmp->cham) {
688.  			mtmp->cham = 0;
689.  			(void) newcham(mtmp,PM_CHAM);
690.  		}
691.  }
692.  
693.  newcham(mtmp,mdat)	/* make a chameleon look like a new monster */
694.  			/* returns 1 if the monster actually changed */
695.  register struct monst *mtmp;
696.  register struct permonst *mdat;
697.  {
698.  	register mhp, hpn, hpd;
699.  
700.  	if(mdat == mtmp->data) return(0);	/* still the same monster */
701.  #ifndef NOWORM
702.  	if(mtmp->wormno) wormdead(mtmp);	/* throw tail away */
703.  #endif NOWORM
704.  	hpn = mtmp->mhp;
705.  	hpd = (mtmp->data->mlevel)*8;
706.  	if(!hpd) hpd = 4;
707.  	mtmp->data = mdat;
708.  	mhp = (mdat->mlevel)*8;
709.  	/* new hp: same fraction of max as before */
710.  	mtmp->mhp = 2 + (hpn*mhp)/hpd;
711.  	hpn = mtmp->orig_hp;
712.  	mtmp->orig_hp = 2 + (hpn*mhp)/hpd;
713.  	mtmp->minvis = (mdat->mlet == 'I') ? 1 : 0;
714.  #ifndef NOWORM
715.  	if(mdat->mlet == 'w' && getwn(mtmp)) initworm(mtmp);
716.  #endif NOWORM
717.  	unpmon(mtmp);	/* necessary for 'I' and to force pmon */
718.  	pmon(mtmp);
719.  	return(1);
720.  }
721.  
722.  mnexto(mtmp)	/* Make monster mtmp next to you (if possible) */
723.  struct monst *mtmp;
724.  {
725.  	extern coord enexto();
726.  	coord mm;
727.  	mm = enexto(u.ux, u.uy);
728.  	mtmp->mx = mm.x;
729.  	mtmp->my = mm.y;
730.  	pmon(mtmp);
731.  }
732.  
733.  rloc(mtmp)
734.  struct monst *mtmp;
735.  {
736.  	register tx,ty;
737.  	register char ch = mtmp->data->mlet;
738.  
739.  #ifndef NOWORM
740.  	if(ch == 'w' && mtmp->mx) return;	/* do not relocate worms */
741.  #endif NOWORM
742.  	do {
743.  		tx = rn1(COLNO-3,2);
744.  		ty = rn2(ROWNO);
745.  	} while(!goodpos(tx,ty));
746.  	mtmp->mx = tx;
747.  	mtmp->my = ty;
748.  	if(u.ustuck == mtmp){
749.  		if(u.uswallow) {
750.  			u.ux = tx;
751.  			u.uy = ty;
752.  			docrt();
753.  		} else	u.ustuck = 0;
754.  	}
755.  	pmon(mtmp);
756.  }
757.  
758.  ishuman(mtmp) register struct monst *mtmp; {
759.  	return(mtmp->data->mlet == '@');
760.  }
761.  
762.  setmangry(mtmp) register struct monst *mtmp; {
763.  	if(!mtmp->mpeaceful) return;
764.  	if(mtmp->mtame) return;
765.  	mtmp->mpeaceful = 0;
766.  	if(ishuman(mtmp)) pline("%s gets angry!", Monnam(mtmp));
767.  }