Source:NetHack 1.4f/dogmove.c

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