Source:NetHack 1.3d/monmove.c

From NetHackWiki
Jump to: navigation, search

Below is the full text to monmove.c from the source code of NetHack 1.3d. To link to a particular line, write [[NetHack 1.3d/monmove.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.    /*	SCCS Id: @(#)monmove.c	1.3	87/07/14
2.    /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3.    /* monmove.c - version 1.0 */
4.    
5.    #include "hack.h"
6.    #include "mfndpos.h"
7.    #define	NULL	(char *) 0
8.    
9.    extern int warnlevel;	/* defined in mon.c */
10.   
11.   dochugw(mtmp) register struct monst *mtmp; {
12.   register x = mtmp->mx;
13.   register y = mtmp->my;
14.   register d = dochug(mtmp);
15.   register dd;
16.   	if(!d)		/* monster still alive */
17.   	if(Warning)
18.   	if(!mtmp->mpeaceful)
19.   	if(mtmp->data->mlevel > warnlevel)
20.   	if((dd = dist(mtmp->mx,mtmp->my)) < dist(x,y))
21.   	if(dd < 100)
22.   	if(!canseemon(mtmp))
23.   		warnlevel = mtmp->data->mlevel;
24.   	return(d);
25.   }
26.   
27.   /* returns 1 if monster died moving, 0 otherwise */
28.   dochug(mtmp)
29.   register struct monst *mtmp;
30.   {
31.   	register struct permonst *mdat;
32.   	register tmp, nearby, scared, onscary;
33.   
34.   	if(mtmp->cham && !rn2(6))
35.   		(void) newcham(mtmp, &mons[dlevel+14+rn2(CMNUM-14-dlevel)]);
36.   	mdat = mtmp->data;
37.   	if(mdat->mlevel < 0)
38.   		panic("bad monster %c (%d)",mdat->mlet,mdat->mlevel);
39.   
40.   	/* regenerate monsters */
41.   	if((!(moves%20) || index(MREGEN, mdat->mlet)) &&
42.   	    mtmp->mhp < mtmp->mhpmax)
43.   		mtmp->mhp++;
44.   
45.   	if(mtmp->mfroz) {
46.   		if (Hallucination) pmon(mtmp);
47.   		return(0);	/* frozen monsters don't do anything */
48.   	}
49.   
50.   	if(mtmp->msleep)	/* there is a chance we will wake it */
51.   		if(!disturb(mtmp)) return(0);
52.   
53.   	/* not frozen or sleeping: wipe out texts written in the dust */
54.   	wipe_engr_at(mtmp->mx, mtmp->my, 1);
55.   
56.   	/* confused monsters get unconfused with small probability */
57.   	if(mtmp->mconf && !rn2(50)) mtmp->mconf = 0;
58.   
59.   	/* some monsters teleport */
60.   	if(mtmp->mflee && index("tNL", mdat->mlet) && !rn2(40)){
61.   		rloc(mtmp);
62.   		return(0);
63.   	}
64.   	if(mdat->mmove < rnd(6)) return(0);
65.   
66.   	/* fleeing monsters might regain courage */
67.   	if(mtmp->mflee && !mtmp->mfleetim
68.   	    && mtmp->mhp == mtmp->mhpmax && !rn2(25))
69.   		mtmp->mflee = 0;
70.   
71.   	nearby = (dist(mtmp->mx, mtmp->my) < 3);
72.   	onscary = (sengr_at("Elbereth", u.ux, u.uy) ||
73.   			sobj_at(SCR_SCARE_MONSTER, u.ux, u.uy));
74.   	scared = (nearby && onscary && !mtmp->mtame && mtmp->mcansee);
75.   	if(scared && !mtmp->mflee) {
76.   		mtmp->mflee = 1;
77.   		mtmp->mfleetim = (rn2(7) ? rnd(10) : rnd(100));
78.   	}
79.   
80.   	if(!nearby ||
81.   		mtmp->mflee || scared ||
82.   		mtmp->mconf ||
83.   		(mtmp->minvis && !rn2(3)) ||
84.   #ifndef KOPS
85.   		(index("BIuy", mdat->mlet) && !rn2(4)) ||
86.   #else
87.   		(index("KBIuy", mdat->mlet) && !rn2(4)) ||
88.   #endif
89.   		(mdat->mlet == 'L' && !u.ugold && (mtmp->mgold || rn2(2))) ||
90.   		(!mtmp->mcansee && !rn2(4)) ||
91.   		mtmp->mpeaceful
92.   	   ) {
93.   		tmp = m_move(mtmp,0);	/* 2: monster died moving */
94.   		if(tmp == 2 || (tmp && mdat->mmove <= 12))
95.   			return(tmp == 2);
96.   
97.   		if(Hallucination && tmp==0) pmon(mtmp);
98.   /* If 0, this means the monster didn't move.  During hallucination, its
99.      appearance should still change. */
100.  
101.  #ifdef HARD
102.  		/* Without this line, fast monsters don't hit you when they've
103.  		 * caught up to you. -dgk
104.  		 */
105.  		nearby = (dist(mtmp->mx, mtmp->my) < 3);
106.  		scared = (nearby && onscary);
107.  		if(scared && !mtmp->mflee) {
108.  			mtmp->mflee = 1;
109.  			mtmp->mfleetim = (rn2(7) ? rnd(10) : rnd(100));
110.  		}
111.  #endif
112.  	}
113.  #ifdef HARD	/* Demonic Blackmail!!! */
114.  	if(mdat->mlet == '&' && mtmp->mpeaceful && !mtmp->mtame)
115.  		if(demon_talk(mtmp))
116.  			 return(1);	/* you paid it off */
117.  #endif
118.  	if(!index("Ea", mdat->mlet) && nearby &&
119.  	 !mtmp->mpeaceful && u.uhp > 0 && !scared) {
120.  		if(mhitu(mtmp))
121.  			return(1);	/* monster died (e.g. 'y' or 'F') */
122.  	}
123.  	/* extra movement for fast monsters */
124.  	if(mdat->mmove-12 > rnd(12)) tmp = m_move(mtmp,1);
125.  	return(tmp == 2);
126.  }
127.  
128.  m_move(mtmp,after)
129.  register struct monst *mtmp;
130.  {
131.  #ifndef REGBUG
132.  	register
133.  #endif
134.  		 struct monst *mtmp2;
135.  #ifndef REGBUG
136.  	register
137.  #endif
138.  		int nx,ny,omx,omy,appr,nearer,cnt,i,j;
139.  	xchar gx,gy,nix,niy,chcnt;
140.  	schar chi;
141.  	boolean likegold, likegems, likeobjs;
142.  #ifdef KAA
143.  	boolean likerock;
144.  #endif
145.  	char msym = mtmp->data->mlet;
146.  	schar mmoved = 0;	/* not strictly nec.: chi >= 0 will do */
147.  	coord poss[9];
148.  	long info[9];
149.  
150.  	if(mtmp->mfroz || mtmp->msleep)
151.  		return(0);
152.  	if(mtmp->mtrapped) {
153.  		i = mintrap(mtmp);
154.  		if(i == 2) return(2);	/* he died */
155.  		if(i == 1) return(0);	/* still in trap, so didnt move */
156.  	}
157.  	if(mtmp->mhide && o_at(mtmp->mx,mtmp->my) && rn2(10))
158.  		return(0);		/* do not leave hiding place */
159.  
160.  #ifndef NOWORM
161.  	if(mtmp->wormno)
162.  		goto not_special;
163.  #endif
164.  
165.  	/* my dog gets a special treatment */
166.  	if(mtmp->mtame) {
167.  		return( dog_move(mtmp, after) );
168.  	}
169.  
170.  	/* likewise for shopkeeper */
171.  	if(mtmp->isshk) {
172.  		mmoved = shk_move(mtmp);
173.  		if(mmoved >= 0)
174.  			goto postmov;
175.  		mmoved = 0;		/* follow player outside shop */
176.  	}
177.  
178.  	/* and for the guard */
179.  	if(mtmp->isgd) {
180.  		mmoved = gd_move();
181.  		goto postmov;
182.  	}
183.  
184.  /* teleport if that lies in our nature ('t') or when badly wounded ('1') */
185.  	if((msym == 't' && !rn2(5))
186.  	|| (msym == '1' && (mtmp->mhp < 7 || (!xdnstair && !rn2(5))
187.  		|| levl[u.ux][u.uy].typ == STAIRS))) {
188.  		if(mtmp->mhp < 7 || (msym == 't' && rn2(2)))
189.  			rloc(mtmp);
190.  		else
191.  			mnexto(mtmp);
192.  		mmoved = 1;
193.  		goto postmov;
194.  	}
195.  
196.  	/* spit fire ('D') or use a wand ('1') when appropriate */
197.  #ifdef DGKMOD
198.  	/* Add arrow and bolt throwing monsters */
199.  	if (index(
200.  # ifdef KAA
201.  #  ifdef KOPS
202.  		"D1OKC9",
203.  #  else
204.  		"D1KC9",
205.  #  endif
206.  # else
207.  #  ifdef KOPS
208.  		"D1OKC",
209.  #  else
210.  		"D1KC",
211.  #  endif
212.  # endif
213.  			  msym))	
214.  
215.  		if (!inrange(mtmp))	/* inrange returns 1 if OK for mon */
216.  			return(0);	/* to move after it zaps or throws */
217.  #else
218.  	if(index("D1", msym))
219.  		inrange(mtmp);
220.  #endif
221.  
222.  	if(msym == 'U' && !mtmp->mcan && canseemon(mtmp) &&
223.  	    mtmp->mcansee && rn2(5)) {
224.  		if(!Confusion)
225.  			pline("%s's gaze has confused you!", Monnam(mtmp));
226.  		else
227.  			pline("You are getting more and more confused.");
228.  		if(rn2(3)) mtmp->mcan = 1;
229.  		HConfusion += d(3,4);		/* timeout */
230.  	}
231.  not_special:
232.  	if(!mtmp->mflee && u.uswallow && u.ustuck != mtmp) return(1);
233.  	appr = 1;
234.  	if(mtmp->mflee) appr = -1;
235.  	if(mtmp->mconf || Invis ||  !mtmp->mcansee ||
236.  		(index("BIy", msym) && !rn2(3)))
237.  		appr = 0;
238.  	omx = mtmp->mx;
239.  	omy = mtmp->my;
240.  	gx = u.ux;
241.  	gy = u.uy;
242.  	if(msym == 'L' && appr == 1 && mtmp->mgold > u.ugold)
243.  		appr = -1;
244.  
245.  	/* random criterion for 'smell' or track finding ability
246.  	   should use mtmp->msmell or sth
247.  	 */
248.  	if(msym == '@' ||
249.  	  ('a' <= msym && msym <= 'z')) {
250.  	extern coord *gettrack();
251.  	register coord *cp;
252.  	schar mroom;
253.  		mroom = inroom(omx,omy);
254.  		if(mroom < 0 || mroom != inroom(u.ux,u.uy)){
255.  		    cp = gettrack(omx,omy);
256.  		    if(cp){
257.  			gx = cp->x;
258.  			gy = cp->y;
259.  		    }
260.  		}
261.  	}
262.  
263.  	/* look for gold or jewels nearby */
264.  #ifdef ROCKMOLE
265.  	likegold = (index("LODr", msym) != NULL);
266.  	likegems = (index("ODu", msym) != NULL);
267.  	likeobjs = (mtmp->mhide || msym == 'r');
268.  #else
269.  	likegold = (index("LOD", msym) != NULL);
270.  	likegems = (index("ODu", msym) != NULL);
271.  	likeobjs = mtmp->mhide;
272.  #endif
273.  #ifdef KAA
274.  	likerock = (msym == '9');
275.  #endif
276.  #define	SRCHRADIUS	25
277.  	{ xchar mind = SRCHRADIUS;		/* not too far away */
278.  	  register int dd;
279.  	  if(likegold){
280.  		register struct gold *gold;
281.  		for(gold = fgold; gold; gold = gold->ngold)
282.  		  if((dd = DIST(omx,omy,gold->gx,gold->gy)) < mind){
283.  		    mind = dd;
284.  		    gx = gold->gx;
285.  		    gy = gold->gy;
286.  		}
287.  	  }
288.  	  if(likegems || likeobjs
289.  #ifdef KAA
290.  				  || likerock
291.  #endif
292.  	    )  {
293.  		register struct obj *otmp;
294.  		for(otmp = fobj; otmp; otmp = otmp->nobj)
295.  		if(likeobjs
296.  		   || (likegems && otmp->olet == GEM_SYM)
297.  #ifdef KAA
298.  		   || (likerock && otmp->olet == ROCK_SYM)
299.  #endif
300.  			)  {
301.  			if(msym != 'u' || objects[otmp->otyp].g_val != 0)
302.  			    if((dd = DIST(omx,omy,otmp->ox,otmp->oy)) < mind){
303.  				mind = dd;
304.  				gx = otmp->ox;
305.  				gy = otmp->oy;
306.  			    }
307.  			}
308.  	    }
309.  	  if(mind < SRCHRADIUS && appr == -1) {
310.  		if(dist(omx,omy) < 10) {
311.  		    gx = u.ux;
312.  		    gy = u.uy;
313.  		} else
314.  		    appr = 1;
315.  	  }
316.  	}
317.  	nix = omx;
318.  	niy = omy;
319.  	cnt = mfndpos(mtmp,poss,info,
320.  		msym == 'u' ? NOTONL :
321.  #ifdef ROCKMOLE
322.  		msym == 'r' ? ALLOW_WALL :
323.  #endif
324.  		(msym == '@' || msym == '1') ? (ALLOW_SSM | ALLOW_TRAPS) :
325.  		index(UNDEAD, msym) ? NOGARLIC :
326.  #ifdef KAA
327.  		    (msym == '9') ? (ALLOW_ROCK | ALLOW_TRAPS) : ALLOW_TRAPS);
328.  #else
329.  		     ALLOW_TRAPS);
330.  #endif
331.  	chcnt = 0;
332.  	chi = -1;
333.  	for(i=0; i<cnt; i++) {
334.  		nx = poss[i].x;
335.  		ny = poss[i].y;
336.  		for(j=0; j<MTSZ && j<cnt-1; j++)
337.  			if(nx == mtmp->mtrack[j].x && ny == mtmp->mtrack[j].y)
338.  				if(rn2(4*(cnt-j))) goto nxti;
339.  #ifdef STUPID
340.  		/* some stupid compilers think that this is too complicated */
341.  		{ int d1 = DIST(nx,ny,gx,gy);
342.  		  int d2 = DIST(nix,niy,gx,gy);
343.  		  nearer = (d1 < d2);
344.  		}
345.  #else
346.  		nearer = (DIST(nx,ny,gx,gy) < DIST(nix,niy,gx,gy));
347.  #endif
348.  		if((appr == 1 && nearer) || (appr == -1 && !nearer) ||
349.  			!mmoved ||
350.  			(!appr && !rn2(++chcnt))){
351.  			nix = nx;
352.  			niy = ny;
353.  			chi = i;
354.  			mmoved = 1;
355.  		}
356.  	nxti:	;
357.  	}
358.  	if(mmoved){
359.  		if(info[chi] & ALLOW_M){
360.  			mtmp2 = m_at(nix,niy);
361.  			if(hitmm(mtmp,mtmp2) == 1 && rn2(4) &&
362.  			  hitmm(mtmp2,mtmp) == 2) return(2);
363.  			return(0);
364.  		}
365.  		if(info[chi] & ALLOW_U){
366.  		  (void) hitu(mtmp, d(mtmp->data->damn, mtmp->data->damd)+1);
367.  		  return(0);
368.  		}
369.  		mtmp->mx = nix;
370.  		mtmp->my = niy;
371.  		for(j=MTSZ-1; j>0; j--) mtmp->mtrack[j] = mtmp->mtrack[j-1];
372.  		mtmp->mtrack[0].x = omx;
373.  		mtmp->mtrack[0].y = omy;
374.  #ifndef NOWORM
375.  		if(mtmp->wormno) worm_move(mtmp);
376.  #endif
377.  	} else {
378.  		if(msym == 'u' && rn2(2)){
379.  			rloc(mtmp);
380.  			return(0);
381.  		}
382.  #ifndef NOWORM
383.  		if(mtmp->wormno) worm_nomove(mtmp);
384.  #endif
385.  	}
386.  postmov:
387.  	if(mmoved == 1) {
388.  		if(mintrap(mtmp) == 2)	/* he died */
389.  			return(2);
390.  #ifdef ROCKMOLE
391.  	       /* Maybe a rock mole just ate something? */
392.  	       if(msym == 'r' && IS_ROCK(levl[mtmp->mx][mtmp->my].typ) &&
393.  		  levl[mtmp->mx][mtmp->my].typ != POOL){
394.  		   register int pile = rnd(25);
395.  		   /* Just ate something. */
396.  		   if(levl[mtmp->mx][mtmp->my].typ == 0)
397.  		     levl[mtmp->mx][mtmp->my].typ = CORR;
398.  		   else if(IS_WALL(levl[mtmp->mx][mtmp->my].typ))
399.  		     levl[mtmp->mx][mtmp->my].typ = DOOR;
400.  		   mnewsym(mtmp->mx,mtmp->my);
401.  		   /* Left behind a pile? */
402.  		   if(pile < 5) {
403.  		       if(pile == 1)
404.  			mksobj_at(ENORMOUS_ROCK, mtmp->mx, mtmp->my);
405.  		      else
406.  			mksobj_at(ROCK, mtmp->mx, mtmp->my);
407.  		   }
408.  		  if(cansee(mtmp->mx, mtmp->my))
409.  		    atl(mtmp->mx,mtmp->my,fobj->olet);
410.  	       }
411.  	       /* Maybe a rock mole just ate some gold or armor? */
412.  	       if(msym == 'r') meatgold(mtmp);
413.  #endif /* ROCKMOLE /**/
414.  		if(likegold) mpickgold(mtmp);
415.  #ifdef KAA
416.  		if(likerock || likegems) mpickgems(mtmp);
417.  #else
418.  		if(likegems) mpickgems(mtmp);
419.  #endif
420.  		if(mtmp->mhide) mtmp->mundetected = 1;
421.  	}
422.  	pmon(mtmp);
423.  	return(mmoved);
424.  }
425.