Source:NetHack 3.1.0/dogmove.c

Below is the full text to dogmove.c from the source code of NetHack 3.1.0. To link to a particular line, write [[NetHack 3.1.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.1	92/11/26	*/ 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.  #ifdef OVL0 11.   12.   static boolean FDECL(dog_hunger,(struct monst *,struct edog *)); 13.  static boolean FDECL(dog_invent,(struct monst *,struct edog *,int)); 14.  static int FDECL(dog_goal,(struct monst *,struct edog *,int,int,int)); 15.   16.   #ifndef MUSE 17.  #define DROPPABLES(mtmp) mtmp->minvent 18.  #else 19.  static struct obj *FDECL(DROPPABLES, (struct monst *)); 20.   21.   static struct obj * 22.  DROPPABLES(mon) 23.  register struct monst *mon; 24.  {  25.   	register struct obj *obj; 26.  	struct obj *wep = MON_WEP(mon); 27.   28.   	for(obj = mon->minvent; obj; obj = obj->nobj) 29.  		if (!obj->owornmask && obj != wep) return obj; 30.  	return (struct obj *)0; 31.  }  32.   #endif 33.   34.   static const char NEARDATA nofetch[] = { BALL_CLASS, CHAIN_CLASS, ROCK_CLASS, 0 }; 35.   36.   #endif /* OVL0 */ 37.   38.   STATIC_VAR xchar gtyp, gx, gy;	/* type and position of dog's current goal */ 39.   40.   STATIC_DCL void FDECL(dog_eat, (struct monst *, struct obj *, int, int)); 41.  STATIC_PTR void FDECL(wantdoor, (int, int, genericptr_t)); 42.   43.   #ifdef OVLB 44.   45.   STATIC_OVL void 46.  dog_eat(mtmp, obj, x, y)  47. register struct monst *mtmp; 48.  register struct obj * obj; 49.  int x, y;  50. { 51.   	register struct edog *edog = EDOG(mtmp); 52.  	int nutrit; 53.   54.   	if(edog->hungrytime < moves) 55.  	    edog->hungrytime = moves; 56.  	/*  57.   	 * It is arbitrary that the pet takes the same length of time to eat 58.  	 * as a human, but gets more nutritional value. 59.  	 */  60.   	if (obj->oclass == FOOD_CLASS) { 61.  	    if(obj->otyp == CORPSE) { 62.  		mtmp->meating = 3 + (mons[obj->corpsenm].cwt >> 6); 63.  		nutrit = mons[obj->corpsenm].cnutrit; 64.  	    } else { 65.  		mtmp->meating = objects[obj->otyp].oc_delay; 66.  		nutrit = objects[obj->otyp].oc_nutrition; 67.  	    }  68.   	    switch(mtmp->data->msize) { 69.  		case MZ_TINY: nutrit *= 8; break; 70.  		case MZ_SMALL: nutrit *= 6; break; 71.  		default: 72.  		case MZ_MEDIUM: nutrit *= 5; break; 73.  		case MZ_LARGE: nutrit *= 4; break; 74.  		case MZ_HUGE: nutrit *= 3; break; 75.  		case MZ_GIGANTIC: nutrit *= 2; break; 76.  	    }  77.   	    if(obj->oeaten) { 78.  		mtmp->meating = eaten_stat(mtmp->meating, obj); 79.  		nutrit = eaten_stat(nutrit, obj); 80.  	    }  81.   	} else if (obj->oclass == GOLD_CLASS) { 82.  	    mtmp->meating = ((int)obj->quan/2000) + 1; 83.  	    nutrit = ((int)obj->quan/20); 84.  	} else { 85.  	    /* Unusual pet such as gelatinous cube eating odd stuff. 86.  	     * meating made consistent with wild monsters in mon.c.  87. * nutrit made consistent with polymorphed player nutrit in 88. * eat.c. (This also applies to pets eating gold.) 89.  	     */  90.   	    mtmp->meating = obj->owt/20 + 1; 91.  	    nutrit = 5*objects[obj->otyp].oc_nutrition; 92.  	}  93.   	edog->hungrytime += nutrit; 94.  	mtmp->mconf = 0; 95.  	if (mtmp->mtame < 20) mtmp->mtame++; 96.  	if(cansee(x,y)) 97.  	    pline("%s eats %s.", Monnam(mtmp), (obj->oclass==FOOD_CLASS)  98.   		? singular(obj, doname) : doname(obj)); 99.  	/* It's a reward if it's DOGFOOD and the player dropped/threw it. */ 100.  	/* We know the player had it if invlet is set -dlc */ 101. 	if(dogfood(mtmp,obj) == DOGFOOD && obj->invlet) 102. #ifdef LINT 103. 	    edog->apport = 0; 104. #else 105. 	    edog->apport += (unsigned)(200L/  106.  		((long)edog->dropdist+moves-edog->droptime)); 107. #endif 108. 	if (obj == uball) { 109. 	    unpunish; 110. 	    delobj(obj); 111. 	} else if (obj == uchain) 112. 	    unpunish; 113. 	else if (obj->quan > 1L && obj->oclass == FOOD_CLASS) 114. 	    obj->quan--; 115. 	else 116. 	    delobj(obj); 117. }  118.   119.  #endif /* OVLB */ 120. #ifdef OVL0 121.  122.  /* hunger effects -- returns TRUE on starvation */ 123. static boolean 124. dog_hunger(mtmp, edog) 125. register struct monst *mtmp; 126. register struct edog *edog; 127. {  128.  	if(moves > edog->hungrytime + 500) { 129. 	    if(!carnivorous(mtmp->data) && !herbivorous(mtmp->data)) { 130. 		edog->hungrytime = moves + 500; 131. 		/* but not too high; it might polymorph */ 132. 	    } else if (!mtmp->mconf) { 133. 		mtmp->mconf = 1; 134. 		mtmp->mhpmax /= 3; 135. 		if(mtmp->mhp > mtmp->mhpmax) 136. 		    mtmp->mhp = mtmp->mhpmax; 137. 		if(mtmp->mhp < 1) goto dog_died; 138. 		if(cansee(mtmp->mx, mtmp->my)) 139. 		    pline("%s is confused from hunger.", Monnam(mtmp)); 140. 		else { 141. 		    char buf[BUFSZ]; 142.  143.  		    Strcpy(buf, "the "); 144. 		    You("feel worried about %s.", mtmp->mnamelth ?  145.  			NAME(mtmp) : strcat(buf, Hallucination 146. 			? rndmonnam : mtmp->data->mname)); 147. 		}  148.  	    } else if(moves > edog->hungrytime + 750 || mtmp->mhp < 1) { 149. 	    dog_died: 150. #ifdef WALKIES 151. 		if(mtmp->mleashed) 152. 		    Your("leash goes slack."); 153. #endif 154. 		if(cansee(mtmp->mx, mtmp->my)) 155. 		    pline("%s dies%s.", Monnam(mtmp),  156.  			    (mtmp->mhp >= 1) ? "" : " from hunger"); 157. 		else 158. 		    You("have a sad feeling for a moment, then it passes."); 159. 		mondied(mtmp); 160. 		return(TRUE); 161. 	    }  162.  	}  163.  	return(FALSE); 164. }  165.   166.  /* do something with object (drop, pick up, eat) at current position 167.  * returns TRUE if object eaten (since that counts as dog's move) 168.  */  169.  static boolean 170. dog_invent(mtmp, edog, udist) 171. register struct monst *mtmp; 172. register struct edog *edog; 173. int udist; 174. {  175.  	register int omx, omy; 176. 	struct obj *obj; 177.  178.  	omx = mtmp->mx; 179. 	omy = mtmp->my; 180.  181.  	/* if we are carrying sth then we drop it (perhaps near @) */ 182. 	/* Note: if apport == 1 then our behaviour is independent of udist */ 183. 	if(DROPPABLES(mtmp) || mtmp->mgold) { 184. 	    if(!rn2(udist) || !rn2((int) edog->apport)) 185. 		if(rn2(10) < edog->apport){ 186. 		    relobj(mtmp, (int)mtmp->minvis, TRUE); 187. 		    if(edog->apport > 1) edog->apport--; 188. 		    edog->dropdist = udist;		/* hpscdi!jon */ 189. 		    edog->droptime = moves; 190. 		}  191.  	} else { 192. 	    if((obj=level.objects[omx][omy]) && !index(nofetch,obj->oclass)  193.  #ifdef MAIL  194.  			&& obj->otyp != SCR_MAIL  195.  #endif  196.  									){ 197. 		if (dogfood(mtmp, obj) <= CADAVER) { 198. 		    dog_eat(mtmp, obj, omx, omy); 199. 		    return TRUE; 200. 		}  201.  		if(can_carry(mtmp, obj) && !obj->cursed) 202. 		    if(rn2(20) < edog->apport+3) 203. 			if(rn2(udist) || !rn2((int) edog->apport)) { 204. 			    if (cansee(omx, omy) && flags.verbose) 205. 				pline("%s picks up %s.", Monnam(mtmp),  206.  				    distant_name(obj, doname)); 207. 			    freeobj(obj); 208. 			    newsym(omx,omy); 209. 			    mpickobj(mtmp,obj); 210. 			}  211.  	    }  212.  	}  213.  	return FALSE; 214. }  215.   216.  /* set dog's goal -- gtyp, gx, gy  217. * returns -1/0/1 (dog's desire to approach player) or -2 (abort move) 218.  */  219.  static int 220. dog_goal(mtmp, edog, after, udist, whappr) 221. register struct monst *mtmp; 222. struct edog *edog; 223. int after, udist, whappr; 224. {  225.  	register int omx, omy; 226. 	boolean in_masters_sight; 227. 	register struct obj *obj; 228. 	xchar otyp; 229. 	int appr; 230.  231.  	omx = mtmp->mx; 232. 	omy = mtmp->my; 233.  234.  	in_masters_sight = couldsee(omx, omy); 235.  236.  	if (!edog  237.  #ifdef WALKIES  238.  		    || mtmp->mleashed	/* he's not going anywhere... */  239.  #endif  240.  					) { 241. 	    gtyp = APPORT; 242. 	    gx = u.ux; 243. 	    gy = u.uy; 244. 	} else { 245. #define DDIST(x,y) (dist2(x,y,omx,omy)) 246. #define SQSRCHRADIUS 5 247. 	    int min_x, max_x, min_y, max_y; 248. 	    register int nx, ny; 249.  250.  	    gtyp = UNDEF;	/* no goal as yet */ 251. 	    gx = gy = 0;	/* suppress 'used before set' message */ 252.  253.  	    if ((min_x = omx - SQSRCHRADIUS) < 0) min_x = 0; 254. 	    if ((max_x = omx + SQSRCHRADIUS) >= COLNO) max_x = COLNO - 1; 255. 	    if ((min_y = omy - SQSRCHRADIUS) < 0) min_y = 0; 256. 	    if ((max_y = omy + SQSRCHRADIUS) >= ROWNO) max_y = ROWNO - 1; 257.  258.  	    /* nearby food is the first choice, then other objects */ 259. 	    for (obj = fobj; obj; obj = obj->nobj) { 260. 		nx = obj->ox; 261. 		ny = obj->oy; 262. 		if (nx >= min_x && nx <= max_x && ny >= min_y && ny <= max_y) { 263. 		    otyp = dogfood(mtmp, obj); 264. 		    if (otyp > gtyp || otyp == UNDEF) 265. 			continue; 266. 		    if (otyp < MANFOOD) { 267. 			if (otyp < gtyp || DDIST(nx,ny) < DDIST(gx,gy)) { 268. 			    gx = nx; 269. 			    gy = ny; 270. 			    gtyp = otyp; 271. 			}  272.  		    } else if(gtyp == UNDEF && in_masters_sight &&  273.  			      !mtmp->minvent &&  274.  			      (!levl[omx][omy].lit || levl[u.ux][u.uy].lit) &&  275.  			      (otyp == MANFOOD || m_cansee(mtmp, nx, ny)) &&  276.  			      edog->apport > rn2(8) &&  277.  			      can_carry(mtmp,obj)) { 278. 			gx = nx; 279. 			gy = ny; 280. 			gtyp = APPORT; 281. 		    }  282.  		}  283.  	    }  284.  	}  285.   286.  	/* follow player if appropriate */ 287. 	if (gtyp == UNDEF ||  288.  	    (gtyp != DOGFOOD && gtyp != APPORT && moves < edog->hungrytime)) { 289. 		gx = u.ux; 290. 		gy = u.uy; 291. 		if (after && udist <= 4 && gx == u.ux && gy == u.uy) 292. 			return(-2); 293. 		appr = (udist >= 9) ? 1 : (mtmp->mflee) ? -1 : 0; 294.  		if (udist > 1) { 295. 			if (!IS_ROOM(levl[u.ux][u.uy].typ) || !rn2(4) ||  296.  			   whappr ||  297.  			   (mtmp->minvent && rn2((int) edog->apport))) 298. 				appr = 1; 299. 		}  300.  		/* if you have dog food it'll follow you more closely */ 301. 		if (appr == 0) { 302. 			obj = invent; 303. 			while (obj) { 304. 				if(dogfood(mtmp, obj) == DOGFOOD) { 305. 					appr = 1; 306. 					break; 307. 				}  308.  				obj = obj->nobj; 309. 			}  310.  		}  311.  	} else 312. 	    appr = 1;	/* gtyp != UNDEF */ 313. 	if(mtmp->mconf) 314. 	    appr = 0; 315.  316.  #define FARAWAY (COLNO + 2)		/* position outside screen */ 317. 	if (gx == u.ux && gy == u.uy && !in_masters_sight) { 318. 	    register coord *cp; 319.  320.  	    cp = gettrack(omx,omy); 321. 	    if (cp) { 322. 		gx = cp->x; 323. 		gy = cp->y; 324. 		if(edog) edog->ogoal.x = 0; 325. 	    } else { 326. 		/* assume master hasn't moved far, and reuse previous goal */ 327. 		if(edog && edog->ogoal.x &&  328.  		   ((edog->ogoal.x != omx) || (edog->ogoal.y != omy))) { 329. 		    gx = edog->ogoal.x;  330. gy = edog->ogoal.y; 331. edog->ogoal.x = 0; 332. 		} else { 333. 		    int fardist = FARAWAY * FARAWAY; 334. 		    gx = gy = FARAWAY; /* random */ 335. 		    do_clear_area(omx, omy, 9, wantdoor,  336.  				  (genericptr_t)&fardist); 337.  338.  		    /* here gx == FARAWAY e.g. when dog is in a vault */ 339. 		    if (gx == FARAWAY || (gx == omx && gy == omy)) { 340. 			gx = u.ux; 341. 			gy = u.uy; 342. 		    } else if(edog) { 343. 			edog->ogoal.x = gx; 344. 			edog->ogoal.y = gy; 345. 		    }  346.  		}  347.  	    }  348.  	} else if(edog) { 349. 	    edog->ogoal.x = 0; 350. 	}  351.  	return appr; 352. }  353.   354.  /* return 0 (no move), 1 (move) or 2 (dead) */ 355. int 356. dog_move(mtmp, after) 357. register struct monst *mtmp; 358. register int after;	/* this is extra fast monster movement */ 359. {  360.  	int omx, omy;		/* original mtmp position */ 361. 	int appr, whappr, udist; 362. 	int i, j;  363. register struct edog *edog = EDOG(mtmp); 364. 	struct obj *obj = (struct obj *) 0; 365. 	xchar otyp; 366. 	boolean has_edog, cursemsg = FALSE, do_eat = FALSE; 367. 	xchar nix, niy;		/* position mtmp is (considering) moving to */ 368. 	register int nx, ny;	/* temporary coordinates */ 369. 	xchar cnt, uncursedcnt, chcnt; 370. 	int chi = -1, nidist, ndist; 371. 	coord poss[9]; 372. 	long info[9], allowflags; 373. #define GDIST(x,y) (dist2(x,y,gx,gy)) 374.  375.  	/*  376.  	 * Tame Angels have isminion set and an ispriest structure instead of  377. * an edog structure. Fortunately, guardian Angels need not worry 378. 	 * about mundane things like eating and fetching objects, and can 379. 	 * spend all their energy defending the player. (They are the only 380.  	 * monsters with other structures that can be tame.) 381. 	 */  382.  	has_edog = !mtmp->isminion; 383.  384.  	omx = mtmp->mx; 385. 	omy = mtmp->my; 386. 	if (has_edog && dog_hunger(mtmp, edog)) return(2);	/* starved */ 387.  388.  	udist = distu(omx,omy); 389. 	/* maybe we tamed him while being swallowed --jgm */ 390. 	if (!udist) return(0); 391.  392.  	nix = omx;	/* set before newdogpos */ 393. 	niy = omy; 394.  395.  	if (has_edog && dog_invent(mtmp, edog, udist))	/* eating something */ 396. 		goto newdogpos; 397.  398.  	if (has_edog) 399. 	    whappr = (moves - edog->whistletime < 5); 400. 	else 401. 	    whappr = 0; 402.  403.  	appr = dog_goal(mtmp, has_edog ? edog : (struct edog *)0,  404.  							after, udist, whappr); 405. 	if (appr == -2) return(0); 406.  407.  	allowflags = ALLOW_M | ALLOW_TRAPS | ALLOW_SSM | ALLOW_SANCT; 408. 	if (passes_walls(mtmp->data)) allowflags |= (ALLOW_ROCK|ALLOW_WALL); 409. 	if (throws_rocks(mtmp->data)) allowflags |= ALLOW_ROCK; 410. 	if (Conflict && !resist(mtmp, RING_CLASS, 0, 0)) { 411. 	    allowflags |= ALLOW_U; 412. 	    if (!has_edog) { 413. 		coord mm; 414. 		/* Guardian angel refuses to be conflicted; rather, 415. 		 * it disappears, angrily, and sends in some nasties 416. 		 */  417.  		if (canseemon(mtmp) || sensemon(mtmp)) { 418. 		    pline("%s rebukes you, saying:", Monnam(mtmp)); 419. 		    verbalize("Since you desire conflict, have some more!"); 420. 		}  421.  		mongone(mtmp); 422. 		i = rnd(4); 423. 		while(i--) { 424. 		    mm.x = u.ux; 425. 		    mm.y = u.uy; 426. 		    if(enexto(&mm, mm.x, mm.y, &mons[PM_ANGEL])) 427. 			(void) mk_roamer(&mons[PM_ANGEL], u.ualign.type,  428.  					 mm.x, mm.y, FALSE); 429. 		}  430.  		return(2); 431.  432.  	    }  433.  	}  434.  	if (!nohands(mtmp->data) && !verysmall(mtmp->data)) { 435. 		allowflags |= OPENDOOR; 436. 		if (m_carrying(mtmp, SKELETON_KEY)) allowflags |= BUSTDOOR; 437. 	}  438.  	if (is_giant(mtmp->data)) allowflags |= BUSTDOOR; 439. 	if (tunnels(mtmp->data) && !needspick(mtmp->data)) 440. 		allowflags |= ALLOW_DIG; 441. 	cnt = mfndpos(mtmp, poss, info, allowflags); 442.  443.  	/* Normally dogs don't step on cursed items, but if they have no  444. * other choice they will. This requires checking ahead of time 445. 	 * to see how many cursed item squares are around. 446. 	 */  447.  	uncursedcnt = 0; 448. 	for (i = 0; i < cnt; i++) { 449. 		nx = poss[i].x; ny = poss[i].y;  450. if (MON_AT(nx,ny)) continue; 451. 		for (obj = level.objects[nx][ny]; obj; obj = obj->nexthere) 452. 			if (obj->cursed) goto skipu; 453. 		uncursedcnt++; 454. skipu:; 455. 	}  456.   457.  	chcnt = 0; 458. 	chi = -1; 459. 	nidist = GDIST(nix,niy); 460.  461.  	for (i = 0; i < cnt; i++) { 462. 		nx = poss[i].x;  463. ny = poss[i].y; 464. #ifdef WALKIES 465. 		/* if leashed, we drag him along. */ 466.  		if (mtmp->mleashed && distu(nx, ny) > 4) continue; 467. #endif 468. 		/* if a guardian, try to stay close by choice */ 469. 		if (!has_edog &&  470.  		    (j = distu(nx, ny)) > 16 && j >= udist) continue; 471.  472.  		if ((info[i] & ALLOW_M) && MON_AT(nx, ny)) { 473. 		    int stat; 474. 		    register struct monst *mtmp2 = m_at(nx,ny); 475.  476.  		    if ((int)mtmp2->m_lev >= (int)mtmp->m_lev+2 ||  477.  			(mtmp2->data == &mons[PM_FLOATING_EYE] && rn2(10) && 478. 			 mtmp->mcansee && haseyes(mtmp->data) && mtmp2->mcansee 479. 			 && (perceives(mtmp->data) || !mtmp2->minvis)) ||  480.  			(mtmp2->data==&mons[PM_GELATINOUS_CUBE] && rn2(10)) ||  481.  			(max_passive_dmg(mtmp2, mtmp) >= mtmp->mhp) ||  482.  			(mtmp->mhp*4 < mtmp->mhpmax && 483. 			 mtmp2->mpeaceful && !Conflict) ||  484.  			   (mtmp2->data->mlet == S_COCKATRICE && 485. 				!resists_ston(mtmp->data))) 486. 			continue; 487.  488.  		    if (after) return(0); /* hit only once each move */ 489.  490.  		    stat = mattackm(mtmp, mtmp2); 491.  492.  		    /* aggressor (pet) died */ 493. 		    if (stat & MM_AGR_DIED) return 2; 494.  495.  		    if ((stat & MM_HIT) && !(stat & MM_DEF_DIED) &&  496.  			rn2(4) && mtmp2->mlstmv != monstermoves) { 497. 			stat = mattackm(mtmp2, mtmp);	/* return attack */ 498. 			if (stat & MM_DEF_DIED) return 2; 499. 		    }  500.   501.  		    return 0; 502. 		}  503.   504.  		{   /* dog avoids traps, but perhaps it has to pass a trap 505. 		     * in order to follow player 506. 		     */  507.  		    struct trap *trap; 508.  509.  		    if ((info[i] & ALLOW_TRAPS) && (trap = t_at(nx,ny))) { 510. 			if ((trap->ttyp == RUST_TRAP 511. 					&& mtmp->data != &mons[PM_IRON_GOLEM])  512.  				|| trap->ttyp == STATUE_TRAP  513.  				|| ((trap->ttyp == PIT  514.  				    || trap->ttyp == SPIKED_PIT  515.  				    || (trap->ttyp == TRAPDOOR && 516. 					!Can_fall_thru(&u.uz))) 517. 				    && (is_flyer(mtmp->data) ||  518.  					is_clinger(mtmp->data)))  519.  				|| (trap->ttyp == SLP_GAS_TRAP && 520. 				    resists_sleep(mtmp->data))) 521. 			    if(!trap->tseen || rn2(3)) continue; 522. #ifdef WALKIES 523. 			if (!mtmp->mleashed) { 524. #endif 525. 			    if (!trap->tseen && rn2(40)) continue; 526. 			    if (rn2(10)) continue; 527. #ifdef WALKIES 528. 			}  529.  # ifdef SOUNDS 530. 			else if (flags.soundok) 531. 				whimper(mtmp); 532. # endif 533. #endif 534. 		    }  535.  		}  536.   537.  		/* dog eschews cursed objects, but likes dog food */ 538. 		for (obj = level.objects[nx][ny]; obj; obj = obj->nexthere) { 539. 		    if (obj->cursed && !mtmp->mleashed && uncursedcnt) 540. 			goto nxti; 541. 		    if (obj->cursed) cursemsg = TRUE; 542. 		    if (has_edog && (otyp = dogfood(mtmp, obj)) < MANFOOD &&  543.  				(otyp < ACCFOOD || edog->hungrytime <= moves)){ 544. 			/* Note: our dog likes the food so much that he  545. * might eat it even when it conceals a cursed object */ 546. 			nix = nx; 547. 			niy = ny; 548. 			chi = i;  549. do_eat = TRUE; 550. 			goto newdogpos; 551. 		    }  552.  		}  553.   554.  		for (j = 0; j < MTSZ && j < cnt-1; j++) 555. 			if (nx == mtmp->mtrack[j].x && ny == mtmp->mtrack[j].y)  556. if (rn2(4*(cnt-j))) goto nxti; 557.  558.  		j = ((ndist = GDIST(nx,ny)) - nidist) * appr; 559. 		if ((j == 0 && !rn2(++chcnt)) || j < 0 ||  560.  			(j > 0 && !whappr && 561. 				((omx == nix && omy == niy && !rn2(3))  562.  					|| !rn2(12)) 563. 			)) {  564.  			nix = nx; 565. 			niy = ny; 566. 			nidist = ndist; 567. 			if(j < 0) chcnt = 0; 568. 			chi = i;  569. } 570.  	nxti:	; 571. 	}  572.  newdogpos: 573. 	if (nix != omx || niy != omy) { 574. 		if (info[chi] & ALLOW_U) { 575. #ifdef WALKIES 576. 			if (mtmp->mleashed) { /* play it safe */ 577. 				pline("%s breaks loose of %s leash!",  578.  					Monnam(mtmp),  579.  					humanoid(mtmp->data)  580.  					    ? (mtmp->female ? "her" : "his") 581.  					    : "its"); 582. 				m_unleash(mtmp); 583. 			}  584.  #endif 585. 			(void) mattacku(mtmp); 586. 			return(0); 587. 		}  588.  		/* insert a worm_move if worms ever begin to eat things */ 589. 		remove_monster(omx, omy); 590. 		place_monster(mtmp, nix, niy); 591. 		if (cursemsg && (cansee(omx,omy) || cansee(nix,niy))) 592. 			pline("%s moves only reluctantly.", Monnam(mtmp)); 593. 		for (j=MTSZ-1; j>0; j--) mtmp->mtrack[j] = mtmp->mtrack[j-1]; 594. 		mtmp->mtrack[0].x = omx; 595. 		mtmp->mtrack[0].y = omy; 596. 		/* We have to know if the pet's gonna do a combined eat and 597. 		 * move before moving it, but it can't eat until after being 598. 		 * moved. Thus the do_eat flag. 599. 		 */  600.  		if (do_eat) 601. 			dog_eat(mtmp, obj, nix, niy); 602. 	}  603.  #ifdef WALKIES 604. 	  /* an incredible kludge, but the only way to keep pooch near 605. 	   * after it spends time eating or in a trap, etc. 606. 	   */  607.  	  else if (mtmp->mleashed && distu(omx, omy) > 4) { 608. 		coord cc; 609.  610.  		nx = sgn(omx - u.ux); 611. 		ny = sgn(omy - u.uy); 612. 		cc.x = u.ux + nx; 613. 		cc.y = u.uy + ny; 614. 		if (goodpos(cc.x, cc.y, mtmp, mtmp->data)) goto dognext; 615.  616.  	 	i  = xytod(nx, ny); 617. 		for (j = (i + 7)%8; j < (i + 1)%8; j++) { 618. 			dtoxy(&cc, j); 619. 			if (goodpos(cc.x, cc.y, mtmp, mtmp->data)) goto dognext; 620. 		}  621.  		for (j = (i + 6)%8; j < (i + 2)%8; j++) { 622. 			dtoxy(&cc, j); 623. 			if (goodpos(cc.x, cc.y, mtmp, mtmp->data)) goto dognext; 624. 		}  625.  		cc.x = mtmp->mx; 626. 		cc.y = mtmp->my; 627. dognext: 628. 		remove_monster(mtmp->mx, mtmp->my); 629. 		place_monster(mtmp, cc.x, cc.y); 630. 		newsym(cc.x,cc.y); 631. 		set_apparxy(mtmp); 632. 	}  633.  #endif 634. 	return(1); 635. }  636.   637.  #endif /* OVL0 */ 638. #ifdef OVLB 639.  640.  /*ARGSUSED*/	/* do_clear_area client */ 641. STATIC_PTR void 642. wantdoor(x, y, distance) 643. int x, y;  644. genericptr_t distance; 645. {  646.      register ndist; 647.  648.      if (*(int*)distance > (ndist = distu(x, y))) { 649. 	gx = x;  650. gy = y; 651. *(int*)distance = ndist; 652.     }  653.  }  654.   655.  #endif /* OVLB */ 656.  657.  /*dogmove.c*/