abstract
| - Below is the full text to dogmove.c from the source code of NetHack 3.2.0. To link to a particular line, write [[NetHack 3.2.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.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*/
|