Source:NetHack 3.0.0/dogmove.c

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

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