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