Source:NetHack 1.3d/dogmove.c

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

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 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; jmtrack[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. }