About: Source:NetHack 3.4.0/dogmove.c   Sponge Permalink

An Entity of Type : owl:Thing, within Data Space : 134.155.108.49:8890 associated with source dataset(s)

Below is the full text to dogmove.c from the source code of NetHack 3.4.0. To link to a particular line, write [[NetHack 3.4.0/dogmove.c#line123]], for example. Warning! This is the source code from an old release. For the latest release, see Source code

AttributesValues
rdfs:label
  • Source:NetHack 3.4.0/dogmove.c
rdfs:comment
  • Below is the full text to dogmove.c from the source code of NetHack 3.4.0. To link to a particular line, write [[NetHack 3.4.0/dogmove.c#line123]], for example. Warning! This is the source code from an old release. For the latest release, see Source code
dcterms:subject
dbkwik:nethack/pro...iPageUsesTemplate
abstract
  • Below is the full text to dogmove.c from the source code of NetHack 3.4.0. To link to a particular line, write [[NetHack 3.4.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.4 2002/03/09 */ 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. extern boolean notonhead; 11. 12. #ifdef OVL0 13. 14. STATIC_DCL boolean FDECL(dog_hunger,(struct monst *,struct edog *)); 15. STATIC_DCL int FDECL(dog_invent,(struct monst *,struct edog *,int)); 16. STATIC_DCL int FDECL(dog_goal,(struct monst *,struct edog *,int,int,int)); 17. 18. STATIC_DCL struct obj *FDECL(DROPPABLES, (struct monst *)); 19. STATIC_DCL boolean FDECL(can_reach_food,(struct monst *,XCHAR_P,XCHAR_P,XCHAR_P, 20. XCHAR_P)); 21. 22. STATIC_OVL struct obj * 23. DROPPABLES(mon) 24. register struct monst *mon; 25. { 26. register struct obj *obj; 27. struct obj *wep = MON_WEP(mon); 28. boolean item1 = FALSE, item2 = FALSE; 29. 30. if (is_animal(mon->data) || mindless(mon->data)) 31. item1 = item2 = TRUE; 32. if (!tunnels(mon->data) || !needspick(mon->data)) 33. item1 = TRUE; 34. for(obj = mon->minvent; obj; obj = obj->nobj) { 35. if (!item1 && is_pick(obj) && (obj->otyp != DWARVISH_MATTOCK 36. || !which_armor(mon, W_ARMS))) { 37. item1 = TRUE; 38. continue; 39. } 40. if (!item2 && obj->otyp == UNICORN_HORN && !obj->cursed) { 41. item2 = TRUE; 42. continue; 43. } 44. if (!obj->owornmask && obj != wep) return obj; 45. } 46. return (struct obj *)0; 47. } 48. 49. static NEARDATA const char nofetch[] = { BALL_CLASS, CHAIN_CLASS, ROCK_CLASS, 0 }; 50. 51. #endif /* OVL0 */ 52. 53. STATIC_OVL boolean FDECL(cursed_object_at, (int, int)); 54. 55. STATIC_VAR xchar gtyp, gx, gy; /* type and position of dog's current goal */ 56. 57. STATIC_PTR void FDECL(wantdoor, (int, int, genericptr_t)); 58. 59. #ifdef OVLB 60. STATIC_OVL boolean 61. cursed_object_at(x, y) 62. int x, y; 63. { 64. struct obj *otmp; 65. 66. for(otmp = level.objects[x][y]; otmp; otmp = otmp->nexthere) 67. if (otmp->cursed) return TRUE; 68. return FALSE; 69. } 70. 71. int 72. dog_nutrition(mtmp, obj) 73. struct monst *mtmp; 74. struct obj *obj; 75. { 76. int nutrit; 77. 78. /* 79. * It is arbitrary that the pet takes the same length of time to eat 80. * as a human, but gets more nutritional value. 81. */ 82. if (obj->oclass == FOOD_CLASS) { 83. if(obj->otyp == CORPSE) { 84. mtmp->meating = 3 + (mons[obj->corpsenm].cwt >> 6); 85. nutrit = mons[obj->corpsenm].cnutrit; 86. } else { 87. mtmp->meating = objects[obj->otyp].oc_delay; 88. nutrit = objects[obj->otyp].oc_nutrition; 89. } 90. switch(mtmp->data->msize) { 91. case MZ_TINY: nutrit *= 8; break; 92. case MZ_SMALL: nutrit *= 6; break; 93. default: 94. case MZ_MEDIUM: nutrit *= 5; break; 95. case MZ_LARGE: nutrit *= 4; break; 96. case MZ_HUGE: nutrit *= 3; break; 97. case MZ_GIGANTIC: nutrit *= 2; break; 98. } 99. if(obj->oeaten) { 100. mtmp->meating = eaten_stat(mtmp->meating, obj); 101. nutrit = eaten_stat(nutrit, obj); 102. } 103. } else if (obj->oclass == GOLD_CLASS) { 104. mtmp->meating = (int)(obj->quan/2000) + 1; 105. if (mtmp->meating < 0) mtmp->meating = 1; 106. nutrit = (int)(obj->quan/20); 107. if (nutrit < 0) nutrit = 0; 108. } else { 109. /* Unusual pet such as gelatinous cube eating odd stuff. 110. * meating made consistent with wild monsters in mon.c. 111. * nutrit made consistent with polymorphed player nutrit in 112. * eat.c. (This also applies to pets eating gold.) 113. */ 114. mtmp->meating = obj->owt/20 + 1; 115. nutrit = 5*objects[obj->otyp].oc_nutrition; 116. } 117. return nutrit; 118. } 119. 120. /* returns 2 if pet dies, otherwise 1 */ 121. int 122. dog_eat(mtmp, obj, x, y, devour) 123. register struct monst *mtmp; 124. register struct obj * obj; 125. int x, y; 126. boolean devour; 127. { 128. register struct edog *edog = EDOG(mtmp); 129. boolean poly = FALSE, grow = FALSE, heal = FALSE; 130. int nutrit; 131. 132. if(edog->hungrytime < monstermoves) 133. edog->hungrytime = monstermoves; 134. nutrit = dog_nutrition(mtmp, obj); 135. poly = polyfodder(obj); 136. grow = mlevelgain(obj); 137. heal = mhealup(obj); 138. if (devour) { 139. if (mtmp->meating > 1) mtmp->meating /= 2; 140. if (nutrit > 1) nutrit = (nutrit * 3) / 4; 141. } 142. edog->hungrytime += nutrit; 143. mtmp->mconf = 0; 144. if (edog->mhpmax_penalty) { 145. /* no longer starving */ 146. mtmp->mhpmax += edog->mhpmax_penalty; 147. edog->mhpmax_penalty = 0; 148. } 149. if (mtmp->mflee && mtmp->mfleetim > 1) mtmp->mfleetim /= 2; 150. if (mtmp->mtame < 20) mtmp->mtame++; 151. if (x != mtmp->mx || y != mtmp->my) { /* moved & ate on same turn */ 152. newsym(x, y); 153. newsym(mtmp->mx, mtmp->my); 154. } 155. if (is_pool(x, y) && !Underwater) { 156. /* Don't print obj */ 157. /* TODO: Reveal presence of sea monster (especially sharks) */ 158. } else 159. /* hack: observe the action if either new or old location is in view */ 160. if (cansee(x, y) || cansee(mtmp->mx, mtmp->my)) 161. pline("%s %s %s.", noit_Monnam(mtmp), 162. devour ? "devours" : "eats", 163. (obj->oclass == FOOD_CLASS) ? 164. singular(obj, doname) : doname(obj)); 165. /* It's a reward if it's DOGFOOD and the player dropped/threw it. */ 166. /* We know the player had it if invlet is set -dlc */ 167. if(dogfood(mtmp,obj) == DOGFOOD && obj->invlet) 168. #ifdef LINT 169. edog->apport = 0; 170. #else 171. edog->apport += (int)(200L/ 172. ((long)edog->dropdist + monstermoves - edog->droptime)); 173. #endif 174. if (mtmp->data == &mons[PM_RUST_MONSTER] && obj->oerodeproof) { 175. /* The object's rustproofing is gone now */ 176. obj->oerodeproof = 0; 177. mtmp->mstun = 1; 178. if (canseemon(mtmp) && flags.verbose) { 179. pline("%s spits %s out in disgust!", 180. Monnam(mtmp), distant_name(obj,doname)); 181. } 182. } else if (obj == uball) { 183. unpunish(); 184. delobj(obj); 185. } else if (obj == uchain) 186. unpunish(); 187. else if (obj->quan > 1L && obj->oclass == FOOD_CLASS) { 188. obj->quan--; 189. obj->owt = weight(obj); 190. } else 191. delobj(obj); 192. 193. if (poly) { 194. char oldpet[BUFSZ]; 195. #ifdef STEED 196. long mw = mtmp->misc_worn_check; 197. 198. mtmp->misc_worn_check &= ~W_SADDLE; 199. #endif 200. Strcpy(oldpet, Monnam(mtmp)); 201. #ifdef STEED 202. mtmp->misc_worn_check = mw; 203. #endif 204. if (newcham(mtmp, (struct permonst *)0, FALSE) && 205. cansee(mtmp->mx, mtmp->my)) { 206. uchar save_mnamelth = mtmp->mnamelth; 207. mtmp->mnamelth = 0; 208. pline("%s turns into %s!", oldpet, a_monnam(mtmp)); 209. mtmp->mnamelth = save_mnamelth; 210. } 211. } 212. /* limit "instant" growth to prevent potential abuse */ 213. if (grow && (int) mtmp->m_lev < (int)mtmp->data->mlevel + 15) { 214. if (!grow_up(mtmp, (struct monst *)0)) return 2; 215. } 216. if (heal) mtmp->mhp = mtmp->mhpmax; 217. return 1; 218. } 219. 220. #endif /* OVLB */ 221. #ifdef OVL0 222. 223. /* hunger effects -- returns TRUE on starvation */ 224. STATIC_OVL boolean 225. dog_hunger(mtmp, edog) 226. register struct monst *mtmp; 227. register struct edog *edog; 228. { 229. if (monstermoves > edog->hungrytime + 500) { 230. if (!carnivorous(mtmp->data) && !herbivorous(mtmp->data)) { 231. edog->hungrytime = monstermoves + 500; 232. /* but not too high; it might polymorph */ 233. } else if (!edog->mhpmax_penalty) { 234. /* starving pets are limited in healing */ 235. int newmhpmax = mtmp->mhpmax / 3; 236. mtmp->mconf = 1; 237. edog->mhpmax_penalty = mtmp->mhpmax - newmhpmax; 238. mtmp->mhpmax = newmhpmax; 239. if (mtmp->mhp > mtmp->mhpmax) 240. mtmp->mhp = mtmp->mhpmax; 241. if (mtmp->mhp < 1) goto dog_died; 242. if (cansee(mtmp->mx, mtmp->my)) 243. pline("%s is confused from hunger.", Monnam(mtmp)); 244. else if (couldsee(mtmp->mx, mtmp->my)) 245. beg(mtmp); 246. else 247. You_feel("worried about %s.", y_monnam(mtmp)); 248. stop_occupation(); 249. } else if (monstermoves > edog->hungrytime + 750 || mtmp->mhp < 1) { 250. dog_died: 251. if (mtmp->mleashed) 252. Your("leash goes slack."); 253. else if (cansee(mtmp->mx, mtmp->my)) 254. pline("%s dies%s.", Monnam(mtmp), 255. (mtmp->mhp >= 1) ? "" : " from hunger"); 256. else 257. You_feel("%s for a moment.", 258. Hallucination ? "bummed" : "sad"); 259. mondied(mtmp); 260. return(TRUE); 261. } 262. } 263. return(FALSE); 264. } 265. 266. /* do something with object (drop, pick up, eat) at current position 267. * returns 1 if object eaten (since that counts as dog's move), 2 if died 268. */ 269. STATIC_OVL int 270. dog_invent(mtmp, edog, udist) 271. register struct monst *mtmp; 272. register struct edog *edog; 273. int udist; 274. { 275. register int omx, omy; 276. struct obj *obj; 277. 278. if (mtmp->msleeping || !mtmp->mcanmove) return(0); 279. 280. omx = mtmp->mx; 281. omy = mtmp->my; 282. 283. /* if we are carrying sth then we drop it (perhaps near @) */ 284. /* Note: if apport == 1 then our behaviour is independent of udist */ 285. /* Use udist+1 so steed won't cause divide by zero */ 286. #ifndef GOLDOBJ 287. if(DROPPABLES(mtmp) || mtmp->mgold) { 288. #else 289. if(DROPPABLES(mtmp)) { 290. #endif 291. if (!rn2(udist+1) || !rn2(edog->apport)) 292. if(rn2(10) < edog->apport){ 293. relobj(mtmp, (int)mtmp->minvis, TRUE); 294. if(edog->apport > 1) edog->apport--; 295. edog->dropdist = udist; /* hpscdi!jon */ 296. edog->droptime = monstermoves; 297. } 298. } else { 299. if((obj=level.objects[omx][omy]) && !index(nofetch,obj->oclass) 300. #ifdef MAIL 301. && obj->otyp != SCR_MAIL 302. #endif 303. ){ 304. if (dogfood(mtmp, obj) <= CADAVER) 305. return dog_eat(mtmp, obj, omx, omy, FALSE); 306. 307. if(can_carry(mtmp, obj) && !obj->cursed && 308. !is_pool(mtmp->mx,mtmp->my)) { 309. if(rn2(20) < edog->apport+3) { 310. if (rn2(udist) || !rn2(edog->apport)) { 311. if (cansee(omx, omy) && flags.verbose) 312. pline("%s picks up %s.", Monnam(mtmp), 313. distant_name(obj, doname)); 314. obj_extract_self(obj); 315. newsym(omx,omy); 316. (void) mpickobj(mtmp,obj); 317. if (attacktype(mtmp->data, AT_WEAP) && 318. mtmp->weapon_check == NEED_WEAPON) { 319. mtmp->weapon_check = NEED_HTH_WEAPON; 320. (void) mon_wield_item(mtmp); 321. } 322. m_dowear(mtmp, FALSE); 323. } 324. } 325. } 326. } 327. } 328. return 0; 329. } 330. 331. /* set dog's goal -- gtyp, gx, gy 332. * returns -1/0/1 (dog's desire to approach player) or -2 (abort move) 333. */ 334. STATIC_OVL int 335. dog_goal(mtmp, edog, after, udist, whappr) 336. register struct monst *mtmp; 337. struct edog *edog; 338. int after, udist, whappr; 339. { 340. register int omx, omy; 341. boolean in_masters_sight; 342. register struct obj *obj; 343. xchar otyp; 344. int appr; 345. 346. 347. #ifdef STEED 348. /* Steeds don't move on their own will */ 349. if (mtmp == u.usteed) 350. return (-2); 351. #endif 352. 353. omx = mtmp->mx; 354. omy = mtmp->my; 355. 356. in_masters_sight = couldsee(omx, omy); 357. 358. if (!edog || mtmp->mleashed) { /* he's not going anywhere... */ 359. gtyp = APPORT; 360. gx = u.ux; 361. gy = u.uy; 362. } else { 363. #define DDIST(x,y) (dist2(x,y,omx,omy)) 364. #define SQSRCHRADIUS 5 365. int min_x, max_x, min_y, max_y; 366. register int nx, ny; 367. 368. gtyp = UNDEF; /* no goal as yet */ 369. gx = gy = 0; /* suppress 'used before set' message */ 370. 371. if ((min_x = omx - SQSRCHRADIUS) < 0) min_x = 0; 372. if ((max_x = omx + SQSRCHRADIUS) >= COLNO) max_x = COLNO - 1; 373. if ((min_y = omy - SQSRCHRADIUS) < 0) min_y = 0; 374. if ((max_y = omy + SQSRCHRADIUS) >= ROWNO) max_y = ROWNO - 1; 375. 376. /* nearby food is the first choice, then other objects */ 377. for (obj = fobj; obj; obj = obj->nobj) { 378. nx = obj->ox; 379. ny = obj->oy; 380. if (nx >= min_x && nx <= max_x && ny >= min_y && ny <= max_y) { 381. otyp = dogfood(mtmp, obj); 382. if (otyp > gtyp || otyp == UNDEF) 383. continue; 384. if (cursed_object_at(nx, ny)) 385. continue; 386. if (otyp < MANFOOD && 387. can_reach_food(mtmp, mtmp->mx, mtmp->my, nx, ny)) { 388. if (otyp < gtyp || DDIST(nx,ny) < DDIST(gx,gy)) { 389. gx = nx; 390. gy = ny; 391. gtyp = otyp; 392. } 393. } else if(gtyp == UNDEF && in_masters_sight && 394. !mtmp->minvent && 395. (!levl[omx][omy].lit || levl[u.ux][u.uy].lit) && 396. (otyp == MANFOOD || m_cansee(mtmp, nx, ny)) && 397. edog->apport > rn2(8) && 398. can_carry(mtmp,obj)) { 399. gx = nx; 400. gy = ny; 401. gtyp = APPORT; 402. } 403. } 404. } 405. } 406. 407. /* follow player if appropriate */ 408. if (gtyp == UNDEF || 409. (gtyp != DOGFOOD && gtyp != APPORT && monstermoves < edog->hungrytime)) { 410. gx = u.ux; 411. gy = u.uy; 412. if (after && udist <= 4 && gx == u.ux && gy == u.uy) 413. return(-2); 414. appr = (udist >= 9) ? 1 : (mtmp->mflee) ? -1 : 0; 415. if (udist > 1) { 416. if (!IS_ROOM(levl[u.ux][u.uy].typ) || !rn2(4) || 417. whappr || 418. (mtmp->minvent && rn2(edog->apport))) 419. appr = 1; 420. } 421. /* if you have dog food it'll follow you more closely */ 422. if (appr == 0) { 423. obj = invent; 424. while (obj) { 425. if(dogfood(mtmp, obj) == DOGFOOD) { 426. appr = 1; 427. break; 428. } 429. obj = obj->nobj; 430. } 431. } 432. } else 433. appr = 1; /* gtyp != UNDEF */ 434. if(mtmp->mconf) 435. appr = 0; 436. 437. #define FARAWAY (COLNO + 2) /* position outside screen */ 438. if (gx == u.ux && gy == u.uy && !in_masters_sight) { 439. register coord *cp; 440. 441. cp = gettrack(omx,omy); 442. if (cp) { 443. gx = cp->x; 444. gy = cp->y; 445. if(edog) edog->ogoal.x = 0; 446. } else { 447. /* assume master hasn't moved far, and reuse previous goal */ 448. if(edog && edog->ogoal.x && 449. ((edog->ogoal.x != omx) || (edog->ogoal.y != omy))) { 450. gx = edog->ogoal.x; 451. gy = edog->ogoal.y; 452. edog->ogoal.x = 0; 453. } else { 454. int fardist = FARAWAY * FARAWAY; 455. gx = gy = FARAWAY; /* random */ 456. do_clear_area(omx, omy, 9, wantdoor, 457. (genericptr_t)&fardist); 458. 459. /* here gx == FARAWAY e.g. when dog is in a vault */ 460. if (gx == FARAWAY || (gx == omx && gy == omy)) { 461. gx = u.ux; 462. gy = u.uy; 463. } else if(edog) { 464. edog->ogoal.x = gx; 465. edog->ogoal.y = gy; 466. } 467. } 468. } 469. } else if(edog) { 470. edog->ogoal.x = 0; 471. } 472. return appr; 473. } 474. 475. /* return 0 (no move), 1 (move) or 2 (dead) */ 476. int 477. dog_move(mtmp, after) 478. register struct monst *mtmp; 479. register int after; /* this is extra fast monster movement */ 480. { 481. int omx, omy; /* original mtmp position */ 482. int appr, whappr, udist; 483. int i, j, k; 484. register struct edog *edog = EDOG(mtmp); 485. struct obj *obj = (struct obj *) 0; 486. xchar otyp; 487. boolean has_edog, cursemsg[9], do_eat = FALSE; 488. xchar nix, niy; /* position mtmp is (considering) moving to */ 489. register int nx, ny; /* temporary coordinates */ 490. xchar cnt, uncursedcnt, chcnt; 491. int chi = -1, nidist, ndist; 492. coord poss[9]; 493. long info[9], allowflags; 494. #define GDIST(x,y) (dist2(x,y,gx,gy)) 495. 496. /* 497. * Tame Angels have isminion set and an ispriest structure instead of 498. * an edog structure. Fortunately, guardian Angels need not worry 499. * about mundane things like eating and fetching objects, and can 500. * spend all their energy defending the player. (They are the only 501. * monsters with other structures that can be tame.) 502. */ 503. has_edog = !mtmp->isminion; 504. 505. omx = mtmp->mx; 506. omy = mtmp->my; 507. if (has_edog && dog_hunger(mtmp, edog)) return(2); /* starved */ 508. 509. udist = distu(omx,omy); 510. #ifdef STEED 511. /* Let steeds eat and maybe throw rider during Conflict */ 512. if (mtmp == u.usteed) { 513. if (Conflict && !resist(mtmp, RING_CLASS, 0, 0)) { 514. dismount_steed(DISMOUNT_THROWN); 515. return (1); 516. } 517. udist = 1; 518. } else 519. #endif 520. /* maybe we tamed him while being swallowed --jgm */ 521. if (!udist) return(0); 522. 523. nix = omx; /* set before newdogpos */ 524. niy = omy; 525. cursemsg[0] = FALSE; /* lint suppression */ 526. info[0] = 0; /* ditto */ 527. 528. if (has_edog) { 529. j = dog_invent(mtmp, edog, udist); 530. if (j == 2) return 2; /* died */ 531. else if (j == 1) goto newdogpos; /* eating something */ 532. 533. whappr = (monstermoves - edog->whistletime < 5); 534. } else 535. whappr = 0; 536. 537. appr = dog_goal(mtmp, has_edog ? edog : (struct edog *)0, 538. after, udist, whappr); 539. if (appr == -2) return(0); 540. 541. allowflags = ALLOW_M | ALLOW_TRAPS | ALLOW_SSM | ALLOW_SANCT; 542. if (passes_walls(mtmp->data)) allowflags |= (ALLOW_ROCK|ALLOW_WALL); 543. if (throws_rocks(mtmp->data)) allowflags |= ALLOW_ROCK; 544. if (Conflict && !resist(mtmp, RING_CLASS, 0, 0)) { 545. allowflags |= ALLOW_U; 546. if (!has_edog) { 547. coord mm; 548. /* Guardian angel refuses to be conflicted; rather, 549. * it disappears, angrily, and sends in some nasties 550. */ 551. if (canspotmon(mtmp)) { 552. pline("%s rebukes you, saying:", Monnam(mtmp)); 553. verbalize("Since you desire conflict, have some more!"); 554. } 555. mongone(mtmp); 556. i = rnd(4); 557. while(i--) { 558. mm.x = u.ux; 559. mm.y = u.uy; 560. if(enexto(&mm, mm.x, mm.y, &mons[PM_ANGEL])) 561. (void) mk_roamer(&mons[PM_ANGEL], u.ualign.type, 562. mm.x, mm.y, FALSE); 563. } 564. return(2); 565. 566. } 567. } 568. if (!Conflict && !mtmp->mconf && 569. mtmp == u.ustuck && !sticks(youmonst.data)) { 570. unstuck(mtmp); /* swallowed case handled above */ 571. You("get released!"); 572. } 573. if (!nohands(mtmp->data) && !verysmall(mtmp->data)) { 574. allowflags |= OPENDOOR; 575. if (m_carrying(mtmp, SKELETON_KEY)) allowflags |= BUSTDOOR; 576. } 577. if (is_giant(mtmp->data)) allowflags |= BUSTDOOR; 578. if (tunnels(mtmp->data) && (!needspick(mtmp->data) || 579. m_carrying(mtmp, PICK_AXE) || 580. m_carrying(mtmp, DWARVISH_MATTOCK))) 581. allowflags |= ALLOW_DIG; 582. cnt = mfndpos(mtmp, poss, info, allowflags); 583. 584. /* Normally dogs don't step on cursed items, but if they have no 585. * other choice they will. This requires checking ahead of time 586. * to see how many uncursed item squares are around. 587. */ 588. uncursedcnt = 0; 589. for (i = 0; i < cnt; i++) { 590. nx = poss[i].x; ny = poss[i].y; 591. if (MON_AT(nx,ny) && !(info[i] & ALLOW_M)) continue; 592. if (cursed_object_at(nx, ny)) continue; 593. uncursedcnt++; 594. } 595. 596. chcnt = 0; 597. chi = -1; 598. nidist = GDIST(nix,niy); 599. 600. for (i = 0; i < cnt; i++) { 601. nx = poss[i].x; 602. ny = poss[i].y; 603. cursemsg[i] = FALSE; 604. 605. /* if leashed, we drag him along. */ 606. if (mtmp->mleashed && distu(nx, ny) > 4) continue; 607. 608. /* if a guardian, try to stay close by choice */ 609. if (!has_edog && 610. (j = distu(nx, ny)) > 16 && j >= udist) continue; 611. 612. if ((info[i] & ALLOW_M) && MON_AT(nx, ny)) { 613. int mstatus; 614. register struct monst *mtmp2 = m_at(nx,ny); 615. 616. if ((int)mtmp2->m_lev >= (int)mtmp->m_lev+2 || 617. (mtmp2->data == &mons[PM_FLOATING_EYE] && rn2(10) && 618. mtmp->mcansee && haseyes(mtmp->data) && mtmp2->mcansee 619. && (perceives(mtmp->data) || !mtmp2->minvis)) || 620. (mtmp2->data==&mons[PM_GELATINOUS_CUBE] && rn2(10)) || 621. (max_passive_dmg(mtmp2, mtmp) >= mtmp->mhp) || 622. ((mtmp->mhp*4 < mtmp->mhpmax 623. || mtmp2->data->msound == MS_GUARDIAN 624. || mtmp2->data->msound == MS_LEADER) && 625. mtmp2->mpeaceful && !Conflict) || 626. (touch_petrifies(mtmp2->data) && 627. !resists_ston(mtmp))) 628. continue; 629. 630. if (after) return(0); /* hit only once each move */ 631. 632. notonhead = 0; 633. mstatus = mattackm(mtmp, mtmp2); 634. 635. /* aggressor (pet) died */ 636. if (mstatus & MM_AGR_DIED) return 2; 637. 638. if ((mstatus & MM_HIT) && !(mstatus & MM_DEF_DIED) && 639. rn2(4) && mtmp2->mlstmv != monstermoves && 640. !onscary(mtmp->mx, mtmp->my, mtmp2) && 641. /* monnear check needed: long worms hit on tail */ 642. monnear(mtmp2, mtmp->mx, mtmp->my)) { 643. mstatus = mattackm(mtmp2, mtmp); /* return attack */ 644. if (mstatus & MM_DEF_DIED) return 2; 645. } 646. 647. return 0; 648. } 649. 650. { /* Dog avoids harmful traps, but perhaps it has to pass one 651. * in order to follow player. (Non-harmful traps do not 652. * have ALLOW_TRAPS in info[].) The dog only avoids the 653. * trap if you've seen it, unlike enemies who avoid traps 654. * if they've seen some trap of that type sometime in the 655. * past. (Neither behavior is really realistic.) 656. */ 657. struct trap *trap; 658. 659. if ((info[i] & ALLOW_TRAPS) && (trap = t_at(nx,ny))) { 660. if (mtmp->mleashed) { 661. if (flags.soundok) whimper(mtmp); 662. } else 663. /* 1/40 chance of stepping on it anyway, in case 664. * it has to pass one to follow the player... 665. */ 666. if (trap->tseen && rn2(40)) continue; 667. } 668. } 669. 670. /* dog eschews cursed objects, but likes dog food */ 671. /* (minion isn't interested; `cursemsg' stays FALSE) */ 672. if (has_edog) 673. for (obj = level.objects[nx][ny]; obj; obj = obj->nexthere) { 674. if (obj->cursed) cursemsg[i] = TRUE; 675. else if ((otyp = dogfood(mtmp, obj)) < MANFOOD && 676. (otyp < ACCFOOD || edog->hungrytime <= monstermoves)) { 677. /* Note: our dog likes the food so much that he 678. * might eat it even when it conceals a cursed object */ 679. nix = nx; 680. niy = ny; 681. chi = i; 682. do_eat = TRUE; 683. cursemsg[i] = FALSE; /* not reluctant */ 684. goto newdogpos; 685. } 686. } 687. /* didn't find something to eat; if we saw a cursed item and 688. aren't being forced to walk on it, usually keep looking */ 689. if (cursemsg[i] && !mtmp->mleashed && uncursedcnt > 0 && 690. rn2(13 * uncursedcnt)) continue; 691. 692. /* lessen the chance of backtracking to previous position(s) */ 693. k = has_edog ? uncursedcnt : cnt; 694. for (j = 0; j < MTSZ && j < k - 1; j++) 695. if (nx == mtmp->mtrack[j].x && ny == mtmp->mtrack[j].y) 696. if (rn2(MTSZ * (k - j))) goto nxti; 697. 698. j = ((ndist = GDIST(nx,ny)) - nidist) * appr; 699. if ((j == 0 && !rn2(++chcnt)) || j < 0 || 700. (j > 0 && !whappr && 701. ((omx == nix && omy == niy && !rn2(3)) 702. || !rn2(12)) 703. )) { 704. nix = nx; 705. niy = ny; 706. nidist = ndist; 707. if(j < 0) chcnt = 0; 708. chi = i; 709. } 710. nxti: ; 711. } 712. newdogpos: 713. if (nix != omx || niy != omy) { 714. struct obj *mw_tmp; 715. 716. if (info[chi] & ALLOW_U) { 717. if (mtmp->mleashed) { /* play it safe */ 718. pline("%s breaks loose of %s leash!", 719. Monnam(mtmp), mhis(mtmp)); 720. m_unleash(mtmp, FALSE); 721. } 722. (void) mattacku(mtmp); 723. return(0); 724. } 725. if (!m_in_out_region(mtmp, nix, niy)) 726. return 1; 727. if(IS_ROCK(levl[nix][niy].typ) && may_dig(nix,niy) && 728. mtmp->weapon_check != NO_WEAPON_WANTED && 729. tunnels(mtmp->data) && needspick(mtmp->data) && 730. (!(mw_tmp = MON_WEP(mtmp)) || !is_pick(mw_tmp))) { 731. mtmp->weapon_check = NEED_PICK_AXE; 732. if (mon_wield_item(mtmp)) 733. return 0; 734. } 735. /* insert a worm_move() if worms ever begin to eat things */ 736. remove_monster(omx, omy); 737. place_monster(mtmp, nix, niy); 738. if (cursemsg[chi] && (cansee(omx,omy) || cansee(nix,niy))) 739. pline("%s moves only reluctantly.", Monnam(mtmp)); 740. for (j=MTSZ-1; j>0; j--) mtmp->mtrack[j] = mtmp->mtrack[j-1]; 741. mtmp->mtrack[0].x = omx; 742. mtmp->mtrack[0].y = omy; 743. /* We have to know if the pet's gonna do a combined eat and 744. * move before moving it, but it can't eat until after being 745. * moved. Thus the do_eat flag. 746. */ 747. if (do_eat) { 748. if (dog_eat(mtmp, obj, omx, omy, FALSE) == 2) return 2; 749. } 750. } else if (mtmp->mleashed && distu(omx, omy) > 4) { 751. /* an incredible kludge, but the only way to keep pooch near 752. * after it spends time eating or in a trap, etc. 753. */ 754. coord cc; 755. 756. nx = sgn(omx - u.ux); 757. ny = sgn(omy - u.uy); 758. cc.x = u.ux + nx; 759. cc.y = u.uy + ny; 760. if (goodpos(cc.x, cc.y, mtmp)) goto dognext; 761. 762. i = xytod(nx, ny); 763. for (j = (i + 7)%8; j < (i + 1)%8; j++) { 764. dtoxy(&cc, j); 765. if (goodpos(cc.x, cc.y, mtmp)) goto dognext; 766. } 767. for (j = (i + 6)%8; j < (i + 2)%8; j++) { 768. dtoxy(&cc, j); 769. if (goodpos(cc.x, cc.y, mtmp)) goto dognext; 770. } 771. cc.x = mtmp->mx; 772. cc.y = mtmp->my; 773. dognext: 774. if (!m_in_out_region(mtmp, nix, niy)) 775. return 1; 776. remove_monster(mtmp->mx, mtmp->my); 777. place_monster(mtmp, cc.x, cc.y); 778. newsym(cc.x,cc.y); 779. set_apparxy(mtmp); 780. } 781. return(1); 782. } 783. 784. /* Hack to prevent a dog from being endlessly stuck near a piece of food that 785. * it can't reach, such as caught in a teleport scroll niche. It recursively 786. * checks to see if the squares inbetween are good. The checking could be a 787. * little smarter; a full check would probably be useful in m_move() too. 788. * Since the maximum food distance is 5, this should never be more than 5 calls 789. * deep. 790. */ 791. STATIC_OVL boolean 792. can_reach_food(mon, mx, my, fx, fy) 793. struct monst *mon; 794. xchar mx, my, fx, fy; 795. { 796. int i, j; 797. int dist; 798. 799. if (mx == fx && my == fy) return TRUE; 800. if (!isok(mx, my)) return FALSE; /* should not happen */ 801. 802. dist = dist2(mx, my, fx, fy); 803. for(i=mx-1; i<=mx+1; i++) { 804. for(j=my-1; j<=my+1; j++) { 805. if (!isok(i, j)) 806. continue; 807. if (dist2(i, j, fx, fy) >= dist) 808. continue; 809. if (IS_ROCK(levl[i][j].typ) && !passes_walls(mon->data) && 810. (!may_dig(i,j) || !tunnels(mon->data))) 811. continue; 812. if (IS_DOOR(levl[i][j].typ) && 813. (levl[i][j].doormask & (D_CLOSED | D_LOCKED))) 814. continue; 815. if (is_pool(i, j) && !is_swimmer(mon->data)) 816. continue; 817. if (is_lava(i, j) && !likes_lava(mon->data)) 818. continue; 819. if (sobj_at(BOULDER,i,j) && !throws_rocks(mon->data)) 820. continue; 821. if (can_reach_food(mon, i, j, fx, fy)) 822. return TRUE; 823. } 824. } 825. return FALSE; 826. } 827. 828. #endif /* OVL0 */ 829. #ifdef OVLB 830. 831. /*ARGSUSED*/ /* do_clear_area client */ 832. STATIC_PTR void 833. wantdoor(x, y, distance) 834. int x, y; 835. genericptr_t distance; 836. { 837. int ndist; 838. 839. if (*(int*)distance > (ndist = distu(x, y))) { 840. gx = x; 841. gy = y; 842. *(int*)distance = ndist; 843. } 844. } 845. 846. #endif /* OVLB */ 847. 848. /*dogmove.c*/
Alternative Linked Data Views: ODE     Raw Data in: CXML | CSV | RDF ( N-Triples N3/Turtle JSON XML ) | OData ( Atom JSON ) | Microdata ( JSON HTML) | JSON-LD    About   
This material is Open Knowledge   W3C Semantic Web Technology [RDF Data] Valid XHTML + RDFa
OpenLink Virtuoso version 07.20.3217, on Linux (x86_64-pc-linux-gnu), Standard Edition
Data on this page belongs to its respective rights holders.
Virtuoso Faceted Browser Copyright © 2009-2012 OpenLink Software