Source:NetHack 2.3e/monmove.c

From NetHackWiki
Jump to navigation Jump to search

Below is the full text to monmove.c from the source code of NetHack 2.3e.

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

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

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