Source:NetHack 3.0.0/dogmove.c

From NetHackWiki
Revision as of 04:30, 4 March 2008 by Kernigh bot (talk | contribs) (NetHack 3.0.0/dogmove.c moved to Source:NetHack 3.0.0/dogmove.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 dogmove.c from the source code of NetHack 3.0.0. To link to a particular line, write [[NetHack 3.0.0/dogmove.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: @(#)dogmove.c	3.0	88/04/15
2.    /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3.    /* NetHack may be freely redistributed.  See license for details. */
4.    
5.    #include "hack.h"
6.    
7.    #include "mfndpos.h"
8.    #include "edog.h"
9.    
10.   static const char nofetch[] = { BALL_SYM, CHAIN_SYM, ROCK_SYM, 0 };
11.   
12.   /* return 0 (no move), 1 (move) or 2 (dead) */
13.   int
14.   dog_move(mtmp, after)
15.   register struct monst *mtmp;
16.   register int after;
17.   {
18.   register int nx,ny,omx,omy,appr,nearer,j;
19.   int udist,chi,i,whappr;
20.   /* XLINT register struct permonst *mdat = mtmp->data; */
21.   register struct edog *edog = EDOG(mtmp);
22.   struct obj *obj;
23.   struct trap *trap;
24.   xchar cnt,chcnt,nix,niy;
25.   schar dogroom,uroom;
26.   xchar gx,gy,gtyp,otyp;	/* current goal */
27.   coord poss[9];
28.   long info[9];
29.   long allowflags;
30.   #define GDIST(x,y) (dist2(x,y,gx,gy))
31.   #define DDIST(x,y) (dist2(x,y,omx,omy))
32.   
33.   	omx = mtmp->mx;
34.   	omy = mtmp->my;
35.   	whappr = (moves - EDOG(mtmp)->whistletime < 5);
36.   	if(moves > EDOG(mtmp)->hungrytime + 500) {
37.   		if(!carnivorous(mtmp->data) && !herbivorous(mtmp->data)) {
38.   			EDOG(mtmp)->hungrytime = moves + 500;
39.   			/* but not too high; it might polymorph */
40.   		} else if (!mtmp->mconf) {
41.   			mtmp->mconf = 1;
42.   			mtmp->mhpmax /= 3;
43.   			if(mtmp->mhp > mtmp->mhpmax)
44.   				mtmp->mhp = mtmp->mhpmax;
45.   			if(cansee(omx,omy))
46.   			    pline("%s is confused from hunger.", Monnam(mtmp));
47.   			else You("feel worried about %s.", mon_nam(mtmp));
48.   		} else if(moves > EDOG(mtmp)->hungrytime + 750 ||
49.   							mtmp->mhp < 1) {
50.   #ifdef WALKIES
51.   			if(mtmp->mleashed)
52.   				Your("leash goes slack.");
53.   #endif
54.   			if(cansee(omx,omy))
55.   				pline("%s dies%s.", Monnam(mtmp),
56.   				      (mtmp->mhp >= 1) ? "" : " from hunger");
57.   			else
58.   		You("have a sad feeling for a moment, then it passes.");
59.   			mondied(mtmp);
60.   			return(2);
61.   		}
62.   	}
63.   	dogroom = inroom(omx,omy);
64.   	uroom = inroom(u.ux,u.uy);
65.   	udist = dist(omx,omy);
66.   
67.   	/* maybe we tamed him while being swallowed --jgm */
68.   	if(!udist) return(0);
69.   
70.   	/* if we are carrying sth then we drop it (perhaps near @) */
71.   	/* Note: if apport == 1 then our behaviour is independent of udist */
72.   	if(mtmp->minvent){
73.   		if(!rn2(udist) || !rn2((int) edog->apport))
74.   		if(rn2(10) < edog->apport){
75.   			if (cansee(omx,omy) && flags.verbose)
76.   			    pline("%s drops %s.", Monnam(mtmp),
77.   					distant_name(mtmp->minvent, doname));
78.   			relobj(mtmp, (int) mtmp->minvis);
79.   			if(edog->apport > 1) edog->apport--;
80.   			edog->dropdist = udist;		/* hpscdi!jon */
81.   			edog->droptime = moves;
82.   		}
83.   	} else {
84.   		if(obj = o_at(omx,omy)) if(!index(nofetch, obj->olet)){
85.   		    if((otyp = dogfood(mtmp, obj)) <= CADAVER){
86.   			nix = omx;
87.   			niy = omy;
88.   			goto eatobj;
89.   		    }
90.   		    if(can_carry(mtmp, obj))
91.   		    if(rn2(20) < edog->apport+3)
92.   		    if(rn2(udist) || !rn2((int) edog->apport)){
93.   			if (cansee(omx, omy) && flags.verbose)
94.   			    pline("%s picks up %s.", Monnam(mtmp),
95.   				distant_name(obj, doname));
96.   			freeobj(obj);
97.   			unpobj(obj);
98.   			/* if(levl[omx][omy].scrsym == obj->olet)
99.   				newsym(omx,omy); */
100.  			mpickobj(mtmp,obj);
101.  		    }
102.  		}
103.  	}
104.  
105.  	gtyp = UNDEF;	/* no goal as yet */
106.  	gx = gy = 0;	/* suppress 'used before set' message */
107.  #ifdef WALKIES
108.  	/* If he's on a leash, he's not going anywhere. */
109.  	if(mtmp->mleashed) {
110.  
111.  		gtyp = APPORT;
112.  		gx = u.ux;
113.  		gy = u.uy;
114.  	} else
115.  #endif
116.  	/* first we look for food, then objects */
117.  	    for(obj = fobj; obj; obj = obj->nobj) {
118.  		otyp = dogfood(mtmp, obj);
119.  		if(otyp > gtyp || otyp == UNDEF) continue;
120.  		if(inroom(obj->ox,obj->oy) != dogroom) continue;
121.  		if(otyp < MANFOOD &&
122.  		 (dogroom >= 0 || DDIST(obj->ox,obj->oy) < 10)) {
123.  			if(otyp < gtyp || (otyp == gtyp &&
124.  				DDIST(obj->ox,obj->oy) < DDIST(gx,gy))){
125.  				gx = obj->ox;
126.  				gy = obj->oy;
127.  				gtyp = otyp;
128.  			}
129.  		} else if(gtyp == UNDEF && dogroom >= 0 &&
130.  		   uroom == dogroom &&
131.  		   !mtmp->minvent && edog->apport > rn2(8) &&
132.  		   can_carry(mtmp,obj)){
133.  			gx = obj->ox;
134.  			gy = obj->oy;
135.  			gtyp = APPORT;
136.  		}
137.  	    }
138.  
139.  	if(gtyp == UNDEF ||
140.  	  (gtyp != DOGFOOD && gtyp != APPORT && moves < EDOG(mtmp)->hungrytime)){
141.  		if(dogroom < 0 || dogroom == uroom){
142.  			gx = u.ux;
143.  			gy = u.uy;
144.  		} else {
145.  			int tmp = rooms[dogroom].fdoor;
146.  			    cnt = rooms[dogroom].doorct;
147.  
148.  			gx = gy = FAR;	/* random, far away */
149.  			while(cnt--){
150.  			    if(dist(gx,gy) >
151.  				dist(doors[tmp].x, doors[tmp].y)){
152.  					gx = doors[tmp].x;
153.  					gy = doors[tmp].y;
154.  				}
155.  				tmp++;
156.  			}
157.  			/* here gx == FAR e.g. when dog is in a vault */
158.  			if(gx == FAR || (gx == omx && gy == omy)){
159.  				gx = u.ux;
160.  				gy = u.uy;
161.  			}
162.  		}
163.  		appr = (udist >= 9) ? 1 : (mtmp->mflee) ? -1 : 0;
164.  		if(after && udist <= 4 && gx == u.ux && gy == u.uy)
165.  			return(0);
166.  		if(udist > 1){
167.  			if(!IS_ROOM(levl[u.ux][u.uy].typ) || !rn2(4) ||
168.  			   whappr ||
169.  			   (mtmp->minvent && rn2((int) edog->apport)))
170.  				appr = 1;
171.  		}
172.  		/* if you have dog food it'll follow you more closely */
173.  		if(appr == 0){
174.  			obj = invent;
175.  			while(obj){
176.  				if(obj->otyp == TRIPE_RATION){
177.  					appr = 1;
178.  					break;
179.  				}
180.  				obj = obj->nobj;
181.  			}
182.  		}
183.  	} else	appr = 1;	/* gtyp != UNDEF */
184.  	if(mtmp->mconf) appr = 0;
185.  
186.  	if(gx == u.ux && gy == u.uy && (dogroom != uroom || dogroom < 0)) {
187.  	register coord *cp;
188.  		cp = gettrack(omx,omy);
189.  		if(cp){
190.  			gx = cp->x;
191.  			gy = cp->y;
192.  		}
193.  	}
194.  
195.  	nix = omx;
196.  	niy = omy;
197.  	
198.  	allowflags = ALLOW_M | ALLOW_TRAPS | ALLOW_SSM | ALLOW_SANCT;
199.  	if (passes_walls(mtmp->data)) allowflags |= (ALLOW_ROCK|ALLOW_WALL);
200.  	if (tunnels(mtmp->data) && !needspick(mtmp->data))
201.  		allowflags |= ALLOW_DIG;
202.  	cnt = mfndpos(mtmp, poss, info, allowflags);
203.  	if (allowflags & ALLOW_DIG) if(!mdig_tunnel(mtmp)) return(2);
204.  	chcnt = 0;
205.  	chi = -1;
206.  	for(i=0; i<cnt; i++){
207.  		nx = poss[i].x;
208.  		ny = poss[i].y;
209.  #ifdef WALKIES
210.  		/* if leashed, we drag him along. */
211.  		if(dist(nx, ny) > 4 && mtmp->mleashed) continue;
212.  #endif
213.  		if(info[i] & ALLOW_M) {
214.  			if(levl[nx][ny].mmask) {
215.  			    register struct monst *mtmp2 = m_at(nx,ny);
216.  
217.  			    if(mtmp2->m_lev >= mtmp->m_lev+2 ||
218.  			       (mtmp2->data->mlet == S_COCKATRICE &&
219.  				!(mtmp->data->mflags1 & M1_STON_RES)))
220.  				continue;
221.  			    if(after) return(0); /* hit only once each move */
222.  
223.  			    if(mattackm(mtmp, mtmp2) == 1 && rn2(4) &&
224.  			      mtmp2->mlstmv != moves &&
225.  			      mattackm(mtmp2, mtmp) == 2) return(2);
226.  			    return(0);
227.  			}
228.  		}
229.  
230.  		/* dog avoids traps */
231.  		/* but perhaps we have to pass a trap in order to follow @ */
232.  		if((info[i] & ALLOW_TRAPS) && (trap = t_at(nx,ny))){
233.  #ifdef WALKIES
234.  			if(!mtmp->mleashed) {
235.  #endif
236.  			    if(!trap->tseen && rn2(40)) continue;
237.  			    if(rn2(10)) continue;
238.  #ifdef WALKIES
239.  			}
240.  # ifdef SOUNDS
241.  			else if(flags.soundok)
242.  				whimper(mtmp);
243.  # endif
244.  #endif
245.  		}
246.  
247.  		/* dog eschews cursed objects */
248.  		/* but likes dog food */
249.  		obj = fobj;
250.  		if(levl[nx][ny].omask) 
251.  		  while(obj){
252.  		    if(obj->ox != nx || obj->oy != ny)
253.  			goto nextobj;
254.  		    if(obj->cursed && !mtmp->mleashed) goto nxti;
255.  		    if(obj->olet == FOOD_SYM &&
256.  			(otyp = dogfood(mtmp, obj)) < MANFOOD &&
257.  			(otyp < ACCFOOD || EDOG(mtmp)->hungrytime <= moves)){
258.  			/* Note: our dog likes the food so much that he
259.  			might eat it even when it conceals a cursed object */
260.  			nix = nx;
261.  			niy = ny;
262.  			chi = i;
263.  		     eatobj:
264.  			mtmp->meating =
265.  			    obj->quan * objects[obj->otyp].oc_delay;
266.  			if(EDOG(mtmp)->hungrytime < moves)
267.  			    EDOG(mtmp)->hungrytime = moves;
268.  			EDOG(mtmp)->hungrytime +=
269.  			    5*obj->quan * objects[obj->otyp].nutrition;
270.  			mtmp->mconf = 0;
271.  			if (mtmp->mtame < 20) mtmp->mtame++;
272.  			if(cansee(nix,niy))
273.  			    pline("%s eats %s.", Monnam(mtmp), doname(obj));
274.  			/* perhaps this was a reward */
275.  			if(otyp != CADAVER)
276.  #ifdef LINT	/* edog->apport += (unsigned) (200L/((long) edog->dropdist...*/
277.  			edog->apport = 0;
278.  #else
279.  			edog->apport += (unsigned)(200L/
280.  				((long)edog->dropdist+moves-edog->droptime));
281.  #endif
282.  			delobj(obj);
283.  			goto newdogpos;
284.  		    }
285.  		nextobj:
286.  		    obj = obj->nobj;
287.  		}
288.  
289.  		for(j=0; j<MTSZ && j<cnt-1; j++)
290.  			if(nx == mtmp->mtrack[j].x && ny == mtmp->mtrack[j].y)
291.  				if(rn2(4*(cnt-j))) goto nxti;
292.  
293.  		nearer = (GDIST(nx,ny) - GDIST(nix,niy)) * appr;
294.  		if((nearer == 0 && !rn2(++chcnt)) || nearer<0 ||
295.  			(nearer > 0 && !whappr &&
296.  				((omx == nix && omy == niy && !rn2(3))
297.  				|| !rn2(12))
298.  			)){
299.  			nix = nx;
300.  			niy = ny;
301.  			if(nearer < 0) chcnt = 0;
302.  			chi = i;
303.  		}
304.  	nxti:	;
305.  	}
306.  newdogpos:
307.  	if(nix != omx || niy != omy) {
308.  		if(info[chi] & ALLOW_U) {
309.  #ifdef WALKIES
310.  			if(mtmp->mleashed) { /* play it safe */
311.  				pline("%s breaks loose of %s leash!", 
312.  					is_female(mtmp) ? "her" :
313.  					is_human(mtmp->data) ? "his" : "its",
314.  					Monnam(mtmp));
315.  				m_unleash(mtmp);
316.  			}
317.  #endif
318.  			(void) mattacku(mtmp);
319.  			return(0);
320.  		}
321.  		levl[omx][omy].mmask = 0;
322.  		levl[nix][niy].mmask = 1;
323.  		mtmp->mx = nix;
324.  		mtmp->my = niy;
325.  		for(j=MTSZ-1; j>0; j--) mtmp->mtrack[j] = mtmp->mtrack[j-1];
326.  		mtmp->mtrack[0].x = omx;
327.  		mtmp->mtrack[0].y = omy;
328.  	}
329.  #ifdef WALKIES
330.  	  /* an incredible kluge, but the only way to keep pooch near
331.  	   * after he spends time eating or in a trap, etc...
332.  	   */
333.  	  else  if(mtmp->mleashed && dist(omx, omy) > 4) {
334.  		coord cc;	
335.  
336.  		nx = sgn(omx - u.ux);
337.  		ny = sgn(omy - u.uy);
338.  		if(goodpos((cc.x = u.ux+nx), (cc.y = u.uy+ny))) goto dognext;
339.  
340.  	 	i  = xytod(nx, ny);
341.  		for(j = (i + 7)%8; j < (i + 1)%8; j++) {
342.  
343.  		   dtoxy(&cc, j);
344.  		   if(goodpos(cc.x, cc.y)) goto dognext;
345.  		}
346.  		for(j = (i + 6)%8; j < (i + 2)%8; j++) {
347.  
348.  		   dtoxy(&cc, j);
349.  		   if(goodpos(cc.x, cc.y)) goto dognext;
350.  		}
351.  		cc.x = mtmp->mx;
352.  		cc.y = mtmp->my;
353.  dognext:
354.  		levl[mtmp->mx][mtmp->my].mmask = 0;
355.  		levl[cc.x][cc.y].mmask = 1;
356.  		mtmp->mx = cc.x;
357.  		mtmp->my = cc.y;
358.  		pmon(mtmp);
359.  		set_apparxy(mtmp);
360.  	}
361.  #endif
362.  
363.  	if(mintrap(mtmp) == 2)		/* he died */
364.  		return(2);
365.  	pmon(mtmp);
366.  	return(1);
367.  }