Source:NetHack 1.3d/dogmove.c

From NetHackWiki
Jump to: navigation, search

Below is the full text to dogmove.c from the source code of NetHack 1.3d. To link to a particular line, write [[NetHack 1.3d/dogmove.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: @(#)dogmove.c	1.3	87/07/14
2.    /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3.    /* dogmove.c - version 1.0 */
4.    
5.    #include	"hack.h"
6.    #include "mfndpos.h"
7.    #include "mkroom.h"
8.    #include "edog.h"
9.    
10.   /* return 0 (no move), 1 (move) or 2 (dead) */
11.   dog_move(mtmp, after) register struct monst *mtmp; {
12.   #ifndef REGBUG
13.   register
14.   #endif
15.   	 int nx,ny,omx,omy,appr,nearer,j;
16.   int udist,chi,i,whappr;
17.   register struct monst *mtmp2;
18.   register struct permonst *mdat = mtmp->data;
19.   register struct edog *edog = EDOG(mtmp);
20.   struct obj *obj;
21.   struct trap *trap;
22.   xchar cnt,chcnt,nix,niy;
23.   schar dogroom,uroom;
24.   xchar gx,gy,gtyp,otyp;	/* current goal */
25.   coord poss[9];
26.   long info[9];
27.   #define GDIST(x,y) ((x-gx)*(x-gx) + (y-gy)*(y-gy))
28.   #define DDIST(x,y) ((x-omx)*(x-omx) + (y-omy)*(y-omy))
29.   
30.   	if(moves <= edog->eattime) return(0);	/* dog is still eating */
31.   	omx = mtmp->mx;
32.   	omy = mtmp->my;
33.   	whappr = (moves - EDOG(mtmp)->whistletime < 5);
34.   	if(moves > edog->hungrytime + 500 && !mtmp->mconf){
35.   		mtmp->mconf = 1;
36.   		mtmp->mhpmax /= 3;
37.   		if(mtmp->mhp > mtmp->mhpmax)
38.   			mtmp->mhp = mtmp->mhpmax;
39.   		if(cansee(omx,omy))
40.   			pline("%s is confused from hunger.", Monnam(mtmp));
41.   		else	pline("You feel worried about %s.", monnam(mtmp));
42.   	} else
43.   	if(moves > edog->hungrytime + 750 || mtmp->mhp < 1){
44.   		if(cansee(omx,omy))
45.   			pline("%s dies from hunger.", Monnam(mtmp));
46.   		else
47.   #ifdef WALKIES
48.   		mtmp->mleashed = 0;
49.   		pline("Your leash goes slack...");
50.   #endif
51.   		pline("You have a sad feeling for a moment, then it passes.");
52.   		mondied(mtmp);
53.   		return(2);
54.   	}
55.   	dogroom = inroom(omx,omy);
56.   	uroom = inroom(u.ux,u.uy);
57.   	udist = dist(omx,omy);
58.   
59.   	/* maybe we tamed him while being swallowed --jgm */
60.   	if(!udist) return(0);
61.   
62.   	/* if we are carrying sth then we drop it (perhaps near @) */
63.   	/* Note: if apport == 1 then our behaviour is independent of udist */
64.   	if(mtmp->minvent){
65.   		if(!rn2(udist) || !rn2((int) edog->apport))
66.   		if(rn2(10) < edog->apport){
67.   			relobj(mtmp, (int) mtmp->minvis);
68.   			if(edog->apport > 1) edog->apport--;
69.   			edog->dropdist = udist;		/* hpscdi!jon */
70.   			edog->droptime = moves;
71.   		}
72.   	} else {
73.   		if(obj = o_at(omx,omy)) if(!index("0_", obj->olet)){
74.   		    if((otyp = dogfood(obj)) <= CADAVER){
75.   			nix = omx;
76.   			niy = omy;
77.   			goto eatobj;
78.   		    }
79.   		    if(obj->owt < 10*mtmp->data->mlevel)
80.   		    if(rn2(20) < edog->apport+3)
81.   		    if(rn2(udist) || !rn2((int) edog->apport)){
82.   			freeobj(obj);
83.   			unpobj(obj);
84.   			/* if(levl[omx][omy].scrsym == obj->olet)
85.   				newsym(omx,omy); */
86.   			mpickobj(mtmp,obj);
87.   		    }
88.   		}
89.   	}
90.   
91.   	gtyp = UNDEF;	/* no goal as yet */
92.   	gx = gy = 0;	/* suppress 'used before set' message */
93.   #ifdef WALKIES
94.   	/* If he's on a leash, he's not going anywhere. */
95.   	if(mtmp->mleashed) {
96.   
97.   		gtyp = APPORT;
98.   		gx = u.ux;
99.   		gy = u.uy;
100.  	} else
101.  #endif
102.  	/* first we look for food */
103.  	    for(obj = fobj; obj; obj = obj->nobj) {
104.  		otyp = dogfood(obj);
105.  		if(otyp > gtyp || otyp == UNDEF) continue;
106.  		if(inroom(obj->ox,obj->oy) != dogroom) continue;
107.  		if(otyp < MANFOOD &&
108.  		 (dogroom >= 0 || DDIST(obj->ox,obj->oy) < 10)) {
109.  			if(otyp < gtyp || (otyp == gtyp &&
110.  				DDIST(obj->ox,obj->oy) < DDIST(gx,gy))){
111.  				gx = obj->ox;
112.  				gy = obj->oy;
113.  				gtyp = otyp;
114.  			}
115.  		} else
116.  		if(gtyp == UNDEF && dogroom >= 0 &&
117.  		   uroom == dogroom &&
118.  		   !mtmp->minvent && edog->apport > rn2(8)){
119.  			gx = obj->ox;
120.  			gy = obj->oy;
121.  			gtyp = APPORT;
122.  		}
123.  	    }
124.  
125.  	if(gtyp == UNDEF ||
126.  	  (gtyp != DOGFOOD && gtyp != APPORT && moves < edog->hungrytime)){
127.  		if(dogroom < 0 || dogroom == uroom){
128.  			gx = u.ux;
129.  			gy = u.uy;
130.  #ifndef QUEST
131.  		} else {
132.  			int tmp = rooms[dogroom].fdoor;
133.  			    cnt = rooms[dogroom].doorct;
134.  
135.  			gx = gy = FAR;	/* random, far away */
136.  			while(cnt--){
137.  			    if(dist(gx,gy) >
138.  				dist(doors[tmp].x, doors[tmp].y)){
139.  					gx = doors[tmp].x;
140.  					gy = doors[tmp].y;
141.  				}
142.  				tmp++;
143.  			}
144.  			/* here gx == FAR e.g. when dog is in a vault */
145.  			if(gx == FAR || (gx == omx && gy == omy)){
146.  				gx = u.ux;
147.  				gy = u.uy;
148.  			}
149.  #endif
150.  		}
151.  		appr = (udist >= 9) ? 1 : (mtmp->mflee) ? -1 : 0;
152.  		if(after && udist <= 4 && gx == u.ux && gy == u.uy)
153.  			return(0);
154.  		if(udist > 1){
155.  			if(!IS_ROOM(levl[u.ux][u.uy].typ) || !rn2(4) ||
156.  			   whappr ||
157.  			   (mtmp->minvent && rn2((int) edog->apport)))
158.  				appr = 1;
159.  		}
160.  		/* if you have dog food he'll follow you more closely */
161.  		if(appr == 0){
162.  			obj = invent;
163.  			while(obj){
164.  				if(obj->otyp == TRIPE_RATION){
165.  					appr = 1;
166.  					break;
167.  				}
168.  				obj = obj->nobj;
169.  			}
170.  		}
171.  	} else	appr = 1;	/* gtyp != UNDEF */
172.  	if(mtmp->mconf) appr = 0;
173.  
174.  	if(gx == u.ux && gy == u.uy && (dogroom != uroom || dogroom < 0)) {
175.  	extern coord *gettrack();
176.  	register coord *cp;
177.  		cp = gettrack(omx,omy);
178.  		if(cp){
179.  			gx = cp->x;
180.  			gy = cp->y;
181.  		}
182.  	}
183.  
184.  	nix = omx;
185.  	niy = omy;
186.  	cnt = mfndpos(mtmp,poss,info,ALLOW_M | ALLOW_TRAPS);
187.  	chcnt = 0;
188.  	chi = -1;
189.  	for(i=0; i<cnt; i++){
190.  		nx = poss[i].x;
191.  		ny = poss[i].y;
192.  #ifdef WALKIES
193.  		/* if leashed, we drag him along. */
194.  		if(dist(nx, ny) > 4 && mtmp->mleashed) continue;
195.  #endif
196.  		if(info[i] & ALLOW_M) {
197.  			mtmp2 = m_at(nx,ny);
198.  			if(mtmp2->data->mlevel >= mdat->mlevel+2 ||
199.  			   mtmp2->data->mlet == 'c')
200.  				continue;
201.  			if(after) return(0); /* hit only once each move */
202.  
203.  			if(hitmm(mtmp, mtmp2) == 1 && rn2(4) &&
204.  			  mtmp2->mlstmv != moves &&
205.  			  hitmm(mtmp2,mtmp) == 2) return(2);
206.  			return(0);
207.  		}
208.  
209.  		/* dog avoids traps */
210.  		/* but perhaps we have to pass a trap in order to follow @ */
211.  		if((info[i] & ALLOW_TRAPS) && (trap = t_at(nx,ny))){
212.  			if(!trap->tseen && rn2(40)) continue;
213.  			if(rn2(10)) continue;
214.  		}
215.  
216.  		/* dog eschewes cursed objects */
217.  		/* but likes dog food */
218.  		obj = fobj;
219.  		while(obj){
220.  		    if(obj->ox != nx || obj->oy != ny)
221.  			goto nextobj;
222.  		    if(obj->cursed) goto nxti;
223.  		    if(obj->olet == FOOD_SYM &&
224.  			(otyp = dogfood(obj)) < MANFOOD &&
225.  			(otyp < ACCFOOD || edog->hungrytime <= moves)){
226.  			/* Note: our dog likes the food so much that he
227.  			might eat it even when it conceals a cursed object */
228.  			nix = nx;
229.  			niy = ny;
230.  			chi = i;
231.  		     eatobj:
232.  			edog->eattime =
233.  			    moves + obj->quan * objects[obj->otyp].oc_delay;
234.  			if(edog->hungrytime < moves)
235.  			    edog->hungrytime = moves;
236.  			edog->hungrytime +=
237.  			    5*obj->quan * objects[obj->otyp].nutrition;
238.  			mtmp->mconf = 0;
239.  			if(cansee(nix,niy))
240.  			    pline("%s ate %s.", Monnam(mtmp), doname(obj));
241.  			/* perhaps this was a reward */
242.  			if(otyp != CADAVER)
243.  			edog->apport += 200/(edog->dropdist+moves-edog->droptime);
244.  			delobj(obj);
245.  			goto newdogpos;
246.  		    }
247.  		nextobj:
248.  		    obj = obj->nobj;
249.  		}
250.  
251.  		for(j=0; j<MTSZ && j<cnt-1; j++)
252.  			if(nx == mtmp->mtrack[j].x && ny == mtmp->mtrack[j].y)
253.  				if(rn2(4*(cnt-j))) goto nxti;
254.  
255.  /* Some stupid C compilers cannot compute the whole expression at once. */
256.  		nearer = GDIST(nx,ny);
257.  		nearer -= GDIST(nix,niy);
258.  		nearer *= appr;
259.  		if((nearer == 0 && !rn2(++chcnt)) || nearer<0 ||
260.  			(nearer > 0 && !whappr &&
261.  				((omx == nix && omy == niy && !rn2(3))
262.  				|| !rn2(12))
263.  			)){
264.  			nix = nx;
265.  			niy = ny;
266.  			if(nearer < 0) chcnt = 0;
267.  			chi = i;
268.  		}
269.  	nxti:	;
270.  	}
271.  newdogpos:
272.  	if(nix != omx || niy != omy){
273.  		if(info[chi] & ALLOW_U){
274.  			(void) hitu(mtmp, d(mdat->damn, mdat->damd)+1);
275.  			return(0);
276.  		}
277.  		mtmp->mx = nix;
278.  		mtmp->my = niy;
279.  		for(j=MTSZ-1; j>0; j--) mtmp->mtrack[j] = mtmp->mtrack[j-1];
280.  		mtmp->mtrack[0].x = omx;
281.  		mtmp->mtrack[0].y = omy;
282.  	}
283.  #ifdef WALKIES
284.  	  /* an incredible kluge, but the only way to keep pooch near
285.  	   * after he spends time eating or in a trap, etc...
286.  	   */
287.  	  else  if(mtmp->mleashed && dist(omx, omy) > 4) mnexto(mtmp);
288.  #endif
289.  
290.  	if(mintrap(mtmp) == 2)	{		/* he died */
291.  #ifdef WALKIES
292.  		mtmp->mleashed = 0;
293.  #endif
294.  		return(2);
295.  	}
296.  	pmon(mtmp);
297.  	return(1);
298.  }