abstract
| - Below is the full text to dogmove.c from the source code of SLASH'EM 0.0.7E7F2. To link to a particular line, write [[SLASH'EM 0.0.7E7F2/dogmove.c#line123]], for example. The latest source code for vanilla NetHack is at Source code. 1. /* SCCS Id: @(#)dogmove.c 3.4 2002/09/10 */ 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. #include "emin.h" 10. #include "epri.h" 11. 12. /* #define DEBUG */ /* uncomment to enable debugging */ 13. 14. #ifdef DEBUG 15. # ifdef WIZARD 16. #define debugpline if (wizard) pline 17. # else 18. #define debugpline pline 19. # endif 20. #endif 21. 22. extern boolean notonhead; 23. 24. #ifdef OVL0 25. 26. STATIC_DCL boolean FDECL(dog_hunger,(struct monst *,struct edog *)); 27. STATIC_DCL int FDECL(dog_invent,(struct monst *,struct edog *,int)); 28. STATIC_DCL int FDECL(dog_goal,(struct monst *,struct edog *,int,int,int)); 29. 30. STATIC_DCL struct obj *FDECL(DROPPABLES, (struct monst *)); 31. STATIC_DCL boolean FDECL(can_reach_location,(struct monst *,XCHAR_P,XCHAR_P, 32. XCHAR_P,XCHAR_P)); 33. STATIC_DCL boolean FDECL(could_reach_item,(struct monst *, XCHAR_P,XCHAR_P)); 34. 35. STATIC_OVL struct obj * 36. DROPPABLES(mon) 37. register struct monst *mon; 38. { 39. register struct obj *obj; 40. struct obj *wep = MON_WEP(mon); 41. boolean item1 = FALSE, item2 = FALSE; 42. 43. if (is_animal(mon->data) || mindless(mon->data)) 44. item1 = item2 = TRUE; 45. if (!tunnels(mon->data) || !needspick(mon->data)) 46. item1 = TRUE; 47. for(obj = mon->minvent; obj; obj = obj->nobj) { 48. if (!item1 && is_pick(obj) && (obj->otyp != DWARVISH_MATTOCK 49. || !which_armor(mon, W_ARMS))) { 50. item1 = TRUE; 51. continue; 52. } 53. if (!item2 && obj->otyp == UNICORN_HORN && !obj->cursed) { 54. item2 = TRUE; 55. continue; 56. } 57. if (!obj->owornmask && obj != wep) return obj; 58. } 59. return (struct obj *)0; 60. } 61. 62. static NEARDATA const char nofetch[] = { BALL_CLASS, CHAIN_CLASS, ROCK_CLASS, 0 }; 63. 64. #endif /* OVL0 */ 65. 66. STATIC_OVL boolean FDECL(cursed_object_at, (struct monst *, int, int)); 67. 68. STATIC_VAR xchar gtyp, gx, gy; /* type and position of dog's current goal */ 69. 70. STATIC_PTR void FDECL(wantdoor, (int, int, genericptr_t)); 71. 72. #ifdef OVLB 73. STATIC_OVL boolean 74. cursed_object_at(mtmp, x, y) 75. register struct monst *mtmp; 76. int x, y; 77. { 78. struct obj *otmp; 79. 80. for(otmp = level.objects[x][y]; otmp; otmp = otmp->nexthere) 81. /* [Tom] demons & undead don't care, though */ 82. /* [ALI] demons & undead avoid blessed items instead */ 83. if ((is_demon(mtmp->data) || is_undead(mtmp->data)) ? 84. otmp->blessed : otmp->cursed) 85. { 86. #ifdef DEBUG 87. debugpline("%s thinks %s at (%d,%d) is `cursed'", 88. noit_Monnam(mtmp), doname(otmp), x, y); 89. #endif 90. return TRUE; 91. } 92. return FALSE; 93. } 94. 95. int 96. dog_nutrition(mtmp, obj) 97. struct monst *mtmp; 98. struct obj *obj; 99. { 100. int nutrit; 101. 102. /* 103. * It is arbitrary that the pet takes the same length of time to eat 104. * as a human, but gets more nutritional value. 105. */ 106. if (obj->oclass == FOOD_CLASS) { 107. if(obj->otyp == CORPSE) { 108. mtmp->meating = 3 + (mons[obj->corpsenm].cwt >> 6); 109. nutrit = mons[obj->corpsenm].cnutrit; 110. } else { 111. mtmp->meating = objects[obj->otyp].oc_delay; 112. nutrit = objects[obj->otyp].oc_nutrition; 113. } 114. switch(mtmp->data->msize) { 115. case MZ_TINY: nutrit *= 8; break; 116. case MZ_SMALL: nutrit *= 6; break; 117. default: 118. case MZ_MEDIUM: nutrit *= 5; break; 119. case MZ_LARGE: nutrit *= 4; break; 120. case MZ_HUGE: nutrit *= 3; break; 121. case MZ_GIGANTIC: nutrit *= 2; break; 122. } 123. if(obj->oeaten) { 124. mtmp->meating = eaten_stat(mtmp->meating, obj); 125. nutrit = eaten_stat(nutrit, obj); 126. } 127. } else if (obj->oclass == COIN_CLASS) { 128. mtmp->meating = (int)(obj->quan/2000) + 1; 129. if (mtmp->meating < 0) mtmp->meating = 1; 130. nutrit = (int)(obj->quan/20); 131. if (nutrit < 0) nutrit = 0; 132. } else { 133. /* Unusual pet such as gelatinous cube eating odd stuff. 134. * meating made consistent with wild monsters in mon.c. 135. * nutrit made consistent with polymorphed player nutrit in 136. * eat.c. (This also applies to pets eating gold.) 137. */ 138. mtmp->meating = obj->owt/20 + 1; 139. nutrit = 5*objects[obj->otyp].oc_nutrition; 140. } 141. return nutrit; 142. } 143. 144. /* returns 2 if pet dies, otherwise 1 */ 145. int 146. dog_eat(mtmp, obj, x, y, devour) 147. register struct monst *mtmp; 148. register struct obj * obj; 149. int x, y; 150. boolean devour; 151. { 152. register struct edog *edog = EDOG(mtmp); 153. boolean poly = FALSE, grow = FALSE, heal = FALSE; 154. int nutrit; 155. boolean vis = (cansee(x, y) || cansee(mtmp->mx, mtmp->my)); 156. boolean vampiric = is_vampire(mtmp->data); 157. 158. if(edog->hungrytime < monstermoves) 159. edog->hungrytime = monstermoves; 160. nutrit = dog_nutrition(mtmp, obj); 161. poly = polyfodder(obj); 162. grow = mlevelgain(obj); 163. heal = mhealup(obj); 164. if (devour) { 165. if (mtmp->meating > 1) mtmp->meating /= 2; 166. if (nutrit > 1) nutrit = (nutrit * 3) / 4; 167. } 168. 169. /* vampires only get 1/5 normal nutrition */ 170. if (vampiric) { 171. mtmp->meating = (mtmp->meating + 4) / 5; 172. nutrit = (nutrit + 4) / 5; 173. } 174. 175. edog->hungrytime += nutrit; 176. mtmp->mconf = 0; 177. if (edog->mhpmax_penalty) { 178. /* no longer starving */ 179. mtmp->mhpmax += edog->mhpmax_penalty; 180. edog->mhpmax_penalty = 0; 181. } 182. if (mtmp->mflee && mtmp->mfleetim > 1) mtmp->mfleetim /= 2; 183. if (mtmp->mtame < 20) mtmp->mtame++; 184. if (x != mtmp->mx || y != mtmp->my) { /* moved & ate on same turn */ 185. newsym(x, y); 186. newsym(mtmp->mx, mtmp->my); 187. } 188. if (is_pool(x, y) && !Underwater) { 189. /* Don't print obj */ 190. /* TODO: Reveal presence of sea monster (especially sharks) */ 191. } else 192. /* hack: observe the action if either new or old location is in view */ 193. /* However, invisible monsters should still be "it" even though out of 194. sight locations should not. */ 195. if (vis) 196. pline("%s %s %s.", mon_visible(mtmp) ? noit_Monnam(mtmp) : "It", 197. vampiric ? "drains" : devour ? "devours" : "eats", 198. (obj->oclass == FOOD_CLASS) ? 199. singular(obj, doname) : doname(obj)); 200. /* It's a reward if it's DOGFOOD and the player dropped/threw it. */ 201. /* We know the player had it if invlet is set -dlc */ 202. if(dogfood(mtmp,obj) == DOGFOOD && obj->invlet) 203. #ifdef LINT 204. edog->apport = 0; 205. #else 206. edog->apport += (int)(200L/ 207. ((long)edog->dropdist + monstermoves - edog->droptime)); 208. #endif 209. if (mtmp->data == &mons[PM_RUST_MONSTER] && obj->oerodeproof) { 210. /* The object's rustproofing is gone now */ 211. obj->oerodeproof = 0; 212. mtmp->mstun = 1; 213. if (canseemon(mtmp) && flags.verbose) { 214. pline("%s spits %s out in disgust!", 215. Monnam(mtmp), distant_name(obj,doname)); 216. } 217. } else if (vampiric) { 218. /* Split Object */ 219. if (obj->quan > 1L) { 220. if(!carried(obj)) { 221. (void) splitobj(obj, 1L); 222. } else { 223. /* Carried */ 224. obj = splitobj(obj, obj->quan - 1L); 225. 226. freeinv(obj); 227. if (inv_cnt() >= 52 && !merge_choice(invent, obj)) 228. dropy(obj); 229. else 230. obj = addinv(obj); /* unlikely but a merge is possible */ 231. } 232. #ifdef DEBUG 233. debugpline("split object,"); 234. #endif 235. } 236. 237. /* Take away blood nutrition */ 238. obj->oeaten = drainlevel(obj); 239. obj->odrained = 1; 240. } else if (obj == uball) { 241. unpunish(); 242. delobj(obj); 243. } else if (obj == uchain) 244. unpunish(); 245. else if (obj->quan > 1L && obj->oclass == FOOD_CLASS) { 246. obj->quan--; 247. obj->owt = weight(obj); 248. } else 249. delobj(obj); 250. 251. if (poly) { 252. (void) mon_spec_poly(mtmp, (struct permonst *)0, 0L, FALSE, 253. cansee(mtmp->mx, mtmp->my), FALSE, FALSE); 254. #if 0 255. (void) newcham(mtmp, (struct permonst *)0, FALSE, 256. cansee(mtmp->mx, mtmp->my)); 257. #endif 258. } 259. /* limit "instant" growth to prevent potential abuse */ 260. if (grow && (int) mtmp->m_lev < (int)mtmp->data->mlevel + 15) { 261. if (!grow_up(mtmp, (struct monst *)0)) return 2; 262. } 263. if (heal) mtmp->mhp = mtmp->mhpmax; 264. return 1; 265. } 266. 267. #endif /* OVLB */ 268. #ifdef OVL0 269. 270. /* hunger effects -- returns TRUE on starvation */ 271. STATIC_OVL boolean 272. dog_hunger(mtmp, edog) 273. register struct monst *mtmp; 274. register struct edog *edog; 275. { 276. if (monstermoves > edog->hungrytime + 500) { 277. if (!carnivorous(mtmp->data) && !herbivorous(mtmp->data)) { 278. edog->hungrytime = monstermoves + 500; 279. /* but not too high; it might polymorph */ 280. } else if (!edog->mhpmax_penalty) { 281. /* starving pets are limited in healing */ 282. int newmhpmax = mtmp->mhpmax / 3; 283. mtmp->mconf = 1; 284. edog->mhpmax_penalty = mtmp->mhpmax - newmhpmax; 285. mtmp->mhpmax = newmhpmax; 286. if (mtmp->mhp > mtmp->mhpmax) 287. mtmp->mhp = mtmp->mhpmax; 288. if (mtmp->mhp < 1) goto dog_died; 289. if (cansee(mtmp->mx, mtmp->my)) 290. pline("%s is confused from hunger.", Monnam(mtmp)); 291. else if (couldsee(mtmp->mx, mtmp->my)) 292. beg(mtmp); 293. else 294. You_feel("worried about %s.", y_monnam(mtmp)); 295. stop_occupation(); 296. } else if (monstermoves > edog->hungrytime + 750 || mtmp->mhp < 1) { 297. dog_died: 298. if (mtmp->mleashed 299. #ifdef STEED 300. && mtmp != u.usteed 301. #endif 302. ) 303. Your("leash goes slack."); 304. else if (cansee(mtmp->mx, mtmp->my)) 305. pline("%s starves.", Monnam(mtmp)); 306. else 307. You_feel("%s for a moment.", 308. Hallucination ? "bummed" : "sad"); 309. mondied(mtmp); 310. return(TRUE); 311. } 312. } 313. return(FALSE); 314. } 315. 316. /* do something with object (drop, pick up, eat) at current position 317. * returns 1 if object eaten (since that counts as dog's move), 2 if died 318. */ 319. STATIC_OVL int 320. dog_invent(mtmp, edog, udist) 321. register struct monst *mtmp; 322. register struct edog *edog; 323. int udist; 324. { 325. /* KMH, balance patch -- quantity picked up should depend on dog's level */ 326. int dogquan = 10 * mtmp->m_lev; 327. register int omx, omy; 328. struct obj *obj; 329. /* 330. struct obj *floor_obj; 331. int temp_quan; 332. */ 333. if (mtmp->msleeping || !mtmp->mcanmove) return(0); 334. 335. omx = mtmp->mx; 336. omy = mtmp->my; 337. 338. /* if we are carrying sth then we drop it (perhaps near @) */ 339. /* Note: if apport == 1 then our behaviour is independent of udist */ 340. /* Use udist+1 so steed won't cause divide by zero */ 341. #ifndef GOLDOBJ 342. if(DROPPABLES(mtmp) || mtmp->mgold) { 343. #else 344. if(DROPPABLES(mtmp)) { 345. #endif 346. if (!rn2(udist+1) || !rn2(edog->apport)) 347. if(rn2(10) < edog->apport){ 348. relobj(mtmp, (int)mtmp->minvis, TRUE); 349. if(edog->apport > 1) edog->apport--; 350. edog->dropdist = udist; /* hpscdi!jon */ 351. edog->droptime = moves; 352. } 353. } else { 354. if((obj=level.objects[omx][omy]) && !index(nofetch,obj->oclass) 355. #ifdef MAIL 356. && obj->otyp != SCR_MAIL 357. #endif 358. ){ 359. int edible = dogfood(mtmp, obj); 360. 361. if ((edible <= CADAVER || 362. /* starving pet is more aggressive about eating */ 363. (edog->mhpmax_penalty && edible == ACCFOOD)) && 364. could_reach_item(mtmp, obj->ox, obj->oy)) 365. return dog_eat(mtmp, obj, omx, omy, FALSE); 366. 367. /* [Tom] demonic & undead pets don't mind cursed items */ 368. if(can_carry(mtmp, obj) && 369. could_reach_item(mtmp, obj->ox, obj->oy) && 370. (!obj->cursed || is_demon(mtmp->data) || is_undead(mtmp->data)) && 371. (!obj->blessed || (!is_demon(mtmp->data) && !is_undead(mtmp->data)))) { 372. if(rn2(20) < edog->apport+3) { 373. if (rn2(udist) || !rn2(edog->apport)) { 374. if ((!nohands(mtmp->data)) || 375. /* KMH, balance patch -- 10*level */ 376. (obj->quan <= dogquan)) 377. { 378. if (cansee(omx, omy) && flags.verbose) 379. pline("%s picks up %s.", Monnam(mtmp), 380. distant_name(obj, doname)); 381. obj_extract_self(obj); 382. newsym(omx,omy); 383. (void) mpickobj(mtmp,obj); 384. } 385. else /* picking up a few objects from a pile... */ 386. /* KMH -- fix picking up zero quantity */ 387. if (dogquan > 0) { 388. if (obj->oclass == COIN_CLASS) { 389. /* KMH, balance patch -- 10*level */ 390. #ifndef GOLDOBJ 391. obj->quan -= dogquan; 392. if (cansee(omx, omy) && flags.verbose) 393. pline("%s picks up %d gold pieces.", 394. Monnam(mtmp), 395. dogquan); 396. mtmp->mgold += dogquan; 397. #else 398. if (obj->quan != dogquan) 399. obj = splitobj(obj, dogquan); 400. if (cansee(omx, omy) && flags.verbose) 401. pline("%s picks up %s.", 402. Monnam(mtmp), 403. doname(obj)); 404. obj_extract_self(obj); 405. newsym(omx,omy); 406. (void) mpickobj(mtmp,obj); 407. #endif 408. } else { 409. /* 410. struct obj *floor_obj; 411. int temp_quan; 412. 413. obj->quan -= dogquan; 414. temp_quan = obj->quan; 415. floor_obj = level.objects[omx][omy]; 416. mpickobj(mtmp,obj); 417. obj->quan = dogquan; 418. if (cansee(omx, omy) && flags.verbose) 419. pline("%s picks up %s.", Monnam(mtmp), 420. distant_name(obj, doname)); 421. floor_obj->quan = temp_quan;*/ 422. } 423. } 424. if (attacktype(mtmp->data, AT_WEAP) && 425. mtmp->weapon_check == NEED_WEAPON) { 426. mtmp->weapon_check = NEED_HTH_WEAPON; 427. (void) mon_wield_item(mtmp); 428. } 429. m_dowear(mtmp, FALSE); 430. } 431. } 432. } 433. } 434. } 435. return 0; 436. } 437. 438. /* set dog's goal -- gtyp, gx, gy 439. * returns -1/0/1 (dog's desire to approach player) or -2 (abort move) 440. */ 441. STATIC_OVL int 442. dog_goal(mtmp, edog, after, udist, whappr) 443. register struct monst *mtmp; 444. struct edog *edog; 445. int after, udist, whappr; 446. { 447. register int omx, omy; 448. boolean in_masters_sight, dog_has_minvent; 449. register struct obj *obj; 450. xchar otyp; 451. int appr; 452. 453. #ifdef STEED 454. /* Steeds don't move on their own will */ 455. if (mtmp == u.usteed) 456. return (-2); 457. #endif 458. 459. omx = mtmp->mx; 460. omy = mtmp->my; 461. 462. in_masters_sight = couldsee(omx, omy); 463. dog_has_minvent = (DROPPABLES(mtmp) != 0); 464. 465. if (!edog || mtmp->mleashed) { /* he's not going anywhere... */ 466. gtyp = APPORT; 467. gx = u.ux; 468. gy = u.uy; 469. } else { 470. #define DDIST(x,y) (dist2(x,y,omx,omy)) 471. #define SQSRCHRADIUS 5 472. int min_x, max_x, min_y, max_y; 473. register int nx, ny; 474. 475. gtyp = UNDEF; /* no goal as yet */ 476. gx = gy = 0; /* suppress 'used before set' message */ 477. 478. if ((min_x = omx - SQSRCHRADIUS) < 1) min_x = 1; 479. if ((max_x = omx + SQSRCHRADIUS) >= COLNO) max_x = COLNO - 1; 480. if ((min_y = omy - SQSRCHRADIUS) < 0) min_y = 0; 481. if ((max_y = omy + SQSRCHRADIUS) >= ROWNO) max_y = ROWNO - 1; 482. 483. /* nearby food is the first choice, then other objects */ 484. for (obj = fobj; obj; obj = obj->nobj) { 485. nx = obj->ox; 486. ny = obj->oy; 487. if (nx >= min_x && nx <= max_x && ny >= min_y && ny <= max_y) { 488. otyp = dogfood(mtmp, obj); 489. /* skip inferior goals */ 490. if (otyp > gtyp || otyp == UNDEF) 491. continue; 492. /* avoid cursed items unless starving */ 493. if (cursed_object_at(mtmp, nx, ny) && 494. !(edog->mhpmax_penalty && otyp < MANFOOD)) 495. continue; 496. /* skip completely unreacheable goals */ 497. if (!could_reach_item(mtmp, nx, ny) || 498. !can_reach_location(mtmp, mtmp->mx, mtmp->my, nx, ny)) 499. continue; 500. if (otyp < MANFOOD) { 501. if (otyp < gtyp || DDIST(nx,ny) < DDIST(gx,gy)) { 502. gx = nx; 503. gy = ny; 504. gtyp = otyp; 505. } 506. } else if(gtyp == UNDEF && in_masters_sight && 507. !dog_has_minvent && 508. (!levl[omx][omy].lit || levl[u.ux][u.uy].lit) && 509. (otyp == MANFOOD || m_cansee(mtmp, nx, ny)) && 510. edog->apport > rn2(8) && 511. can_carry(mtmp,obj)) { 512. gx = nx; 513. gy = ny; 514. gtyp = APPORT; 515. } 516. } 517. } 518. } 519. 520. /* follow player if appropriate */ 521. if (gtyp == UNDEF || 522. (gtyp != DOGFOOD && gtyp != APPORT && monstermoves < edog->hungrytime)) { 523. gx = u.ux; 524. gy = u.uy; 525. if (after && udist <= 4 && gx == u.ux && gy == u.uy) 526. return(-2); 527. appr = (udist >= 9) ? 1 : (mtmp->mflee) ? -1 : 0; 528. if (udist > 1) { 529. if (!IS_ROOM(levl[u.ux][u.uy].typ) || !rn2(4) || 530. whappr || 531. (dog_has_minvent && rn2(edog->apport))) 532. appr = 1; 533. } 534. /* if you have dog food it'll follow you more closely */ 535. if (appr == 0) { 536. obj = invent; 537. while (obj) { 538. if(dogfood(mtmp, obj) == DOGFOOD) { 539. appr = 1; 540. break; 541. } 542. obj = obj->nobj; 543. } 544. } 545. } else 546. appr = 1; /* gtyp != UNDEF */ 547. if(mtmp->mconf) 548. appr = 0; 549. 550. #define FARAWAY (COLNO + 2) /* position outside screen */ 551. if (gx == u.ux && gy == u.uy && !in_masters_sight) { 552. register coord *cp; 553. 554. cp = gettrack(omx,omy); 555. if (cp) { 556. gx = cp->x; 557. gy = cp->y; 558. if(edog) edog->ogoal.x = 0; 559. } else { 560. /* assume master hasn't moved far, and reuse previous goal */ 561. if(edog && edog->ogoal.x && 562. ((edog->ogoal.x != omx) || (edog->ogoal.y != omy))) { 563. gx = edog->ogoal.x; 564. gy = edog->ogoal.y; 565. edog->ogoal.x = 0; 566. } else { 567. int fardist = FARAWAY * FARAWAY; 568. gx = gy = FARAWAY; /* random */ 569. do_clear_area(omx, omy, 9, wantdoor, 570. (genericptr_t)&fardist); 571. 572. /* here gx == FARAWAY e.g. when dog is in a vault */ 573. if (gx == FARAWAY || (gx == omx && gy == omy)) { 574. gx = u.ux; 575. gy = u.uy; 576. } else if(edog) { 577. edog->ogoal.x = gx; 578. edog->ogoal.y = gy; 579. } 580. } 581. } 582. } else if(edog) { 583. edog->ogoal.x = 0; 584. } 585. return appr; 586. } 587. 588. #ifdef DEBUG 589. #define CHECK_ALLOW(flag,str) if ((allowflags & (flag)) == (flag)) { \ 590. allowflags ^= (flag); \ 591. if (bp != buf) { *bp++=','; *bp++=' '; } \ 592. Strcpy(bp, str); \ 593. bp += strlen(bp); \ 594. } else 595. 596. STATIC_OVL char * 597. allow_set(allowflags) 598. long allowflags; 599. { 600. static char buf[500]; 601. char *bp = buf; 602. if (allowflags == 0) 603. return "(none)"; 604. *bp = '\0'; 605. CHECK_ALLOW(ALLOW_TRAPS, "can enter traps"); 606. CHECK_ALLOW(ALLOW_U, "can attack you"); 607. CHECK_ALLOW(ALLOW_M, "can attack other monsters"); 608. CHECK_ALLOW(ALLOW_TM, "can attack tame monsters"); 609. CHECK_ALLOW(NOTONL, "avoids direct line to player"); 610. CHECK_ALLOW(OPENDOOR, "opens closed doors"); 611. CHECK_ALLOW(UNLOCKDOOR, "unlocks locked doors"); 612. CHECK_ALLOW(BUSTDOOR, "breaks any doors"); 613. CHECK_ALLOW(ALLOW_ROCK, "pushes rocks"); 614. CHECK_ALLOW(ALLOW_WALL, "walks thru walls"); 615. CHECK_ALLOW(ALLOW_DIG, "digs"); 616. CHECK_ALLOW(ALLOW_SANCT, "enters temples"); 617. CHECK_ALLOW(ALLOW_SSM, "ignores scare monster"); 618. CHECK_ALLOW(NOGARLIC, "hates garlic"); 619. if (allowflags) { 620. if (bp != buf) { *bp++=','; *bp++=' '; } 621. sprintf(bp, "0x%lX", allowflags); 622. } 623. return buf; 624. } 625. 626. #undef CHECK_ALLOW 627. #endif 628. 629. boolean 630. betrayed(mtmp) 631. register struct monst *mtmp; 632. { 633. boolean has_edog = !mtmp->isminion; 634. struct edog *edog = EDOG(mtmp); 635. int udist = distu(mtmp->mx, mtmp->my); 636. 637. if (udist < 4 && has_edog && !mtmp->isspell && !rn2(3) 638. && can_betray(mtmp->data) 639. && !mindless(mtmp->data) 640. && mtmp->mhp >= u.uhp /* Pet is buff enough */ 641. && rn2(22) > mtmp->mtame /* Roll against tameness */ 642. && rn2(edog->abuse + 2)) { 643. /* Treason */ 644. if (canseemon(mtmp)) 645. pline("%s turns on you!", Monnam(mtmp)); 646. else 647. pline("You feel uneasy about %s.", y_monnam(mtmp)); 648. mtmp->mpeaceful = 0; 649. mtmp->mtame = 0; 650. mtmp->mtraitor = TRUE; 651. 652. /* Do we need to call newsym() here? */ 653. newsym(mtmp->mx, mtmp->my); 654. return TRUE; 655. } 656. return FALSE; 657. } 658. 659. /* return 0 (no move), 1 (move) or 2 (dead) */ 660. int 661. dog_move(mtmp, after) 662. register struct monst *mtmp; 663. register int after; /* this is extra fast monster movement */ 664. { 665. int omx, omy; /* original mtmp position */ 666. int appr, whappr, udist; 667. int i, j, k; 668. register struct edog *edog = EDOG(mtmp); 669. struct obj *obj = (struct obj *) 0; 670. xchar otyp; 671. boolean has_edog, cursemsg[9], is_spell, do_eat = FALSE; 672. xchar nix, niy; /* position mtmp is (considering) moving to */ 673. register int nx, ny; /* temporary coordinates */ 674. xchar cnt, uncursedcnt, chcnt; 675. int chi = -1, nidist, ndist; 676. coord poss[9]; 677. long info[9], allowflags; 678. #define GDIST(x,y) (dist2(x,y,gx,gy)) 679. 680. /* 681. * Tame Angels have isminion set and an ispriest structure instead of 682. * an edog structure. Fortunately, guardian Angels need not worry 683. * about mundane things like eating and fetching objects, and can 684. * spend all their energy defending the player. (They are the only 685. * monsters with other structures that can be tame.) 686. */ 687. has_edog = !mtmp->isminion; 688. 689. /* 690. * Similar to Angels and Guardians are spell beings - temporary 691. * magical manifestations of the spellcaster's mind. 692. * They don't eat/pickup objects - only fight. 693. * But, they aren't dismissed by conflict. 694. */ 695. is_spell = mtmp->isspell; 696. 697. omx = mtmp->mx; 698. omy = mtmp->my; 699. if (has_edog && !is_spell && dog_hunger(mtmp, edog)) return(2); /* starved */ 700. 701. udist = distu(omx,omy); 702. #ifdef STEED 703. /* Let steeds eat and maybe throw rider during Conflict */ 704. if (mtmp == u.usteed) { 705. if (Conflict && !resist(mtmp, RING_CLASS, 0, 0)) { 706. dismount_steed(DISMOUNT_THROWN); 707. return (1); 708. } 709. udist = 1; 710. } else 711. #endif 712. /* maybe we tamed him while being swallowed --jgm */ 713. if (!udist) return(0); 714. 715. /* Intelligent pets may rebel (apart from minions, spell beings) */ 716. if (!rn2(850) && betrayed(mtmp)) return 1; 717. 718. nix = omx; /* set before newdogpos */ 719. niy = omy; 720. cursemsg[0] = FALSE; /* lint suppression */ 721. info[0] = 0; /* ditto */ 722. 723. if (has_edog && !is_spell) { 724. j = dog_invent(mtmp, edog, udist); 725. if (j == 2) return 2; /* died */ 726. else if (j == 1) goto newdogpos; /* eating something */ 727. 728. whappr = (monstermoves - edog->whistletime < 5); 729. } else 730. whappr = 0; 731. 732. appr = dog_goal(mtmp, (has_edog && !is_spell) ? edog : (struct edog *)0, 733. after, udist, whappr); 734. #ifdef DEBUG 735. { 736. char *goal; 737. switch(gtyp) 738. { 739. case DOGFOOD: goal = "dogfood"; break; 740. case CADAVER: goal = "cadaver"; break; 741. case ACCFOOD: goal = "accfood"; break; 742. case MANFOOD: goal = "manfood"; break; 743. case APPORT: goal = "apport"; break; 744. case POISON: goal = "poison"; break; 745. case UNDEF: goal = "undef"; break; 746. case TABU: goal = "tabu"; break; 747. default: goal = "???"; break; 748. } 749. debugpline("G(%s): %s @ (%d,%d), appr = %d", 750. mon_nam(mtmp), goal, gx, gy, appr); 751. } 752. #endif 753. if (appr == -2) return(0); 754. 755. allowflags = ALLOW_M | ALLOW_TRAPS | ALLOW_SSM | ALLOW_SANCT; 756. if (passes_walls(mtmp->data)) allowflags |= (ALLOW_ROCK | ALLOW_WALL); 757. if (passes_bars(mtmp->data) && !In_sokoban(&u.uz)) 758. allowflags |= ALLOW_BARS; 759. if (throws_rocks(mtmp->data)) allowflags |= ALLOW_ROCK; 760. if (Conflict && !resist(mtmp, RING_CLASS, 0, 0) && In_endgame(&u.uz)) { 761. allowflags |= ALLOW_U; 762. if (!has_edog && !is_spell) { 763. coord mm; 764. /* Guardian angel refuses to be conflicted; rather, 765. * it disappears, angrily, and sends in some nasties 766. */ 767. if (canspotmon(mtmp)) { 768. pline("%s rebukes you, saying:", Monnam(mtmp)); 769. verbalize("Since you desire conflict, have some more!"); 770. } 771. mongone(mtmp); 772. i = rnd(4); 773. while(i--) { 774. mm.x = u.ux; 775. mm.y = u.uy; 776. if(enexto(&mm, mm.x, mm.y, &mons[PM_ANGEL])) 777. (void) mk_roamer(&mons[PM_ANGEL], u.ualign.type, 778. mm.x, mm.y, FALSE); 779. } 780. return(2); 781. 782. } 783. } 784. 785. /* ALI -- Mindless pets shouldn't attack monsters when 786. * scared; they have no sense of allegiance to the hero, 787. * only self-preservation. This prevents weak pets blocking 788. * your exit from a shop by constantly missing shopkeeper. 789. */ 790. if (mindless(mtmp->data) && mtmp->mflee) 791. allowflags &= ~ALLOW_M; 792. 793. if (!Conflict && !mtmp->mconf && 794. mtmp == u.ustuck && !sticks(youmonst.data)) { 795. unstuck(mtmp); /* swallowed case handled above */ 796. You("get released!"); 797. } 798. if (!nohands(mtmp->data) && !verysmall(mtmp->data)) { 799. allowflags |= OPENDOOR; 800. if (m_carrying(mtmp, SKELETON_KEY)) allowflags |= BUSTDOOR; 801. } 802. if (is_giant(mtmp->data)) allowflags |= BUSTDOOR; 803. if (tunnels(mtmp->data)) allowflags |= ALLOW_DIG; 804. cnt = mfndpos(mtmp, poss, info, allowflags); 805. #ifdef DEBUG 806. debugpline("%d positions found with allow: %s", cnt, 807. allow_set(allowflags)); 808. for (i = 0; i < cnt; i++) { 809. debugpline("[%d] %s @ (%d, %d)", i, 810. allow_set(info[i]), poss[i].x, poss[i].y); 811. } 812. #endif 813. 814. /* Normally dogs don't step on cursed items, but if they have no 815. * other choice they will. This requires checking ahead of time 816. * to see how many uncursed item squares are around. 817. */ 818. 819. uncursedcnt = 0; 820. for (i = 0; i < cnt; i++) { 821. nx = poss[i].x; ny = poss[i].y; 822. if (MON_AT(nx,ny) && !(info[i] & ALLOW_M)) continue; 823. if (cursed_object_at(mtmp, nx, ny)) continue; 824. uncursedcnt++; 825. } 826. 827. chcnt = 0; 828. chi = -1; 829. nidist = GDIST(nix,niy); 830. 831. for (i = 0; i < cnt; i++) { 832. nx = poss[i].x; 833. ny = poss[i].y; 834. cursemsg[i] = FALSE; 835. 836. /* if leashed, we drag him along. */ 837. if (mtmp->mleashed && distu(nx, ny) > 4) continue; 838. 839. /* if a guardian, try to stay close by choice */ 840. if ((!has_edog || is_spell) && 841. (j = distu(nx, ny)) > 16 && j >= udist) continue; 842. 843. if ((info[i] & ALLOW_M) && MON_AT(nx, ny)) { 844. int mstatus; 845. register struct monst *mtmp2 = m_at(nx,ny); 846. aligntyp align1, align2; /* For priests, minions etc. */ 847. 848. if (mtmp->isminion) align1 = EMIN(mtmp)->min_align; 849. else if (is_unicorn(mtmp->data)) 850. align1 = sgn(mtmp->data->maligntyp); 851. else if (mtmp->ispriest) align1 = EPRI(mtmp)->shralign; 852. else align1 = A_NONE; 853. if (mtmp2->isminion) align2 = EMIN(mtmp2)->min_align; 854. else if (is_unicorn(mtmp2->data)) 855. align2 = sgn(mtmp2->data->maligntyp); 856. else if (mtmp2->ispriest) align2 = EPRI(mtmp2)->shralign; 857. else align2 = A_NONE; 858. 859. /* Mindless monsters and spelled monsters have no fear of 860. * attacking higher level monsters 861. */ 862. if (((int)mtmp2->m_lev >= (int)mtmp->m_lev+2 && !is_spell && 863. !mindless(mtmp->data)) || 864. (mtmp2->data == &mons[PM_FLOATING_EYE] && rn2(10) && 865. mtmp->mcansee && haseyes(mtmp->data) && mtmp2->mcansee 866. && (perceives(mtmp->data) || !mtmp2->minvis)) || 867. (mtmp2->data==&mons[PM_GELATINOUS_CUBE] && rn2(10)) || 868. (mtmp2->data==&mons[PM_GAS_SPORE] && rn2(16)) || 869. (!attacktype(mtmp->data, AT_EXPL) && 870. max_passive_dmg(mtmp2, mtmp) >= mtmp->mhp) || 871. /* Minions/Angels don't attack 872. * coaligned minions/priests/angels/unicorns. 873. */ 874. (align1 == align2 && align1 != A_NONE) || 875. ((mtmp->mhp*4 < mtmp->mhpmax 876. || mtmp2->data->msound == MS_GUARDIAN 877. || mtmp2->data->msound == MS_LEADER) && 878. mtmp2->mpeaceful && !Conflict) || 879. (touch_petrifies(mtmp2->data) && 880. !resists_ston(mtmp))) 881. continue; 882. 883. if (after) return(0); /* hit only once each move */ 884. 885. notonhead = 0; 886. mstatus = mattackm(mtmp, mtmp2); 887. 888. /* aggressor (pet) died */ 889. if (mstatus & MM_AGR_DIED) return 2; 890. 891. if ((mstatus & MM_HIT) && !(mstatus & MM_DEF_DIED) && 892. rn2(4) && mtmp2->mlstmv != monstermoves && 893. !onscary(mtmp->mx, mtmp->my, mtmp2) && 894. /* monnear check needed: long worms hit on tail */ 895. monnear(mtmp2, mtmp->mx, mtmp->my)) { 896. mstatus = mattackm(mtmp2, mtmp); /* return attack */ 897. if (mstatus & MM_DEF_DIED) return 2; 898. } 899. 900. return 0; 901. } 902. 903. { /* Dog avoids harmful traps, but perhaps it has to pass one 904. * in order to follow player. (Non-harmful traps do not 905. * have ALLOW_TRAPS in info[].) The dog only avoids the 906. * trap if you've seen it, unlike enemies who avoid traps 907. * if they've seen some trap of that type sometime in the 908. * past. (Neither behavior is really realistic.) 909. */ 910. struct trap *trap; 911. 912. if ((info[i] & ALLOW_TRAPS) && (trap = t_at(nx,ny))) { 913. if (mtmp->mleashed) { 914. if (flags.soundok) whimper(mtmp); 915. } else 916. /* 1/40 chance of stepping on it anyway, in case 917. * it has to pass one to follow the player... 918. */ 919. if (trap->tseen && rn2(40)) continue; 920. } 921. } 922. 923. /* dog eschews cursed objects, but likes dog food */ 924. /* [Tom] except demons & undead, who don't care */ 925. /* (minion isn't interested; `cursemsg' stays FALSE) */ 926. if (has_edog && !is_spell) { 927. for (obj = level.objects[nx][ny]; obj; obj = obj->nexthere) { 928. if ((obj->cursed) && has_edog && !is_demon(mtmp->data) 929. && !is_undead(mtmp->data)) cursemsg[i] = TRUE; 930. if (obj->blessed && has_edog && (is_demon(mtmp->data) 931. || is_undead(mtmp->data))) cursemsg[i] = TRUE; 932. else if ((otyp = dogfood(mtmp, obj)) < MANFOOD && 933. (otyp < ACCFOOD || edog->hungrytime <= monstermoves)) { 934. /* Note: our dog likes the food so much that he 935. * might eat it even when it conceals a cursed object */ 936. nix = nx; 937. niy = ny; 938. chi = i; 939. do_eat = TRUE; 940. cursemsg[i] = FALSE; /* not reluctant */ 941. goto newdogpos; 942. } 943. } 944. } 945. /* didn't find something to eat; if we saw a cursed item and 946. aren't being forced to walk on it, usually keep looking */ 947. if (cursemsg[i] && !mtmp->mleashed && uncursedcnt > 0 && 948. rn2(13 * uncursedcnt)) continue; 949. 950. /* lessen the chance of backtracking to previous position(s) */ 951. k = (has_edog && !is_spell) ? uncursedcnt : cnt; 952. for (j = 0; j < MTSZ && j < k - 1; j++) 953. if (nx == mtmp->mtrack[j].x && ny == mtmp->mtrack[j].y) 954. if (rn2(MTSZ * (k - j))) goto nxti; 955. 956. j = ((ndist = GDIST(nx,ny)) - nidist) * appr; 957. if ((j == 0 && !rn2(++chcnt)) || j < 0 || 958. (j > 0 && !whappr && 959. ((omx == nix && omy == niy && !rn2(3)) 960. || !rn2(12)) 961. )) { 962. nix = nx; 963. niy = ny; 964. nidist = ndist; 965. if(j < 0) chcnt = 0; 966. chi = i; 967. } 968. nxti: ; 969. } 970. newdogpos: 971. if (nix != omx || niy != omy) { 972. struct obj *mw_tmp; 973. 974. if (info[chi] & ALLOW_U) { 975. if (mtmp->mleashed) { /* play it safe */ 976. pline("%s breaks loose of %s leash!", 977. Monnam(mtmp), mhis(mtmp)); 978. m_unleash(mtmp, FALSE); 979. } 980. (void) mattacku(mtmp); 981. return(0); 982. } 983. if (!m_in_out_region(mtmp, nix, niy)) 984. return 1; 985. if (((IS_ROCK(levl[nix][niy].typ) && may_dig(nix,niy)) || 986. closed_door(nix, niy)) && 987. mtmp->weapon_check != NO_WEAPON_WANTED && 988. tunnels(mtmp->data) && needspick(mtmp->data)) { 989. if (closed_door(nix, niy)) { 990. if (!(mw_tmp = MON_WEP(mtmp)) || 991. !is_pick(mw_tmp) || !is_axe(mw_tmp)) 992. mtmp->weapon_check = NEED_PICK_OR_AXE; 993. } else if (IS_TREE(levl[nix][niy].typ)) { 994. if (!(mw_tmp = MON_WEP(mtmp)) || !is_axe(mw_tmp)) 995. mtmp->weapon_check = NEED_AXE; 996. } else if (!(mw_tmp = MON_WEP(mtmp)) || !is_pick(mw_tmp)) { 997. mtmp->weapon_check = NEED_PICK_AXE; 998. } 999. if (mtmp->weapon_check >= NEED_PICK_AXE && 1000. mon_wield_item(mtmp)) 1001. return 0; 1002. } 1003. /* insert a worm_move() if worms ever begin to eat things */ 1004. remove_monster(omx, omy); 1005. place_monster(mtmp, nix, niy); 1006. if (has_edog && !is_spell && cursemsg[chi] && (cansee(omx,omy) || cansee(nix,niy))) 1007. pline("%s moves only reluctantly.", Monnam(mtmp)); 1008. for (j=MTSZ-1; j>0; j--) mtmp->mtrack[j] = mtmp->mtrack[j-1]; 1009. mtmp->mtrack[0].x = omx; 1010. mtmp->mtrack[0].y = omy; 1011. /* We have to know if the pet's gonna do a combined eat and 1012. * move before moving it, but it can't eat until after being 1013. * moved. Thus the do_eat flag. 1014. */ 1015. if (do_eat) { 1016. if (dog_eat(mtmp, obj, omx, omy, FALSE) == 2) return 2; 1017. } 1018. } else if (mtmp->mleashed && distu(omx, omy) > 4) { 1019. /* an incredible kludge, but the only way to keep pooch near 1020. * after it spends time eating or in a trap, etc. 1021. */ 1022. coord cc; 1023. 1024. nx = sgn(omx - u.ux); 1025. ny = sgn(omy - u.uy); 1026. cc.x = u.ux + nx; 1027. cc.y = u.uy + ny; 1028. if (goodpos(cc.x, cc.y, mtmp, 0)) goto dognext; 1029. 1030. i = xytod(nx, ny); 1031. for (j = (i + 7)%8; j < (i + 1)%8; j++) { 1032. dtoxy(&cc, j); 1033. if (goodpos(cc.x, cc.y, mtmp, 0)) goto dognext; 1034. } 1035. for (j = (i + 6)%8; j < (i + 2)%8; j++) { 1036. dtoxy(&cc, j); 1037. if (goodpos(cc.x, cc.y, mtmp, 0)) goto dognext; 1038. } 1039. cc.x = mtmp->mx; 1040. cc.y = mtmp->my; 1041. dognext: 1042. if (!m_in_out_region(mtmp, nix, niy)) 1043. return 1; 1044. remove_monster(mtmp->mx, mtmp->my); 1045. place_monster(mtmp, cc.x, cc.y); 1046. newsym(cc.x,cc.y); 1047. set_apparxy(mtmp); 1048. } 1049. return(1); 1050. } 1051. 1052. /* check if a monster could pick up objects from a location */ 1053. STATIC_OVL boolean 1054. could_reach_item(mon, nx, ny) 1055. struct monst *mon; 1056. xchar nx, ny; 1057. { 1058. if ((!is_pool(nx,ny) || is_swimmer(mon->data)) && 1059. (!is_lava(nx,ny) || likes_lava(mon->data)) && 1060. (!sobj_at(BOULDER,nx,ny) || throws_rocks(mon->data))) 1061. return TRUE; 1062. return FALSE; 1063. } 1064. 1065. /* Hack to prevent a dog from being endlessly stuck near an object that 1066. * it can't reach, such as caught in a teleport scroll niche. It recursively 1067. * checks to see if the squares in between are good. The checking could be a 1068. * little smarter; a full check would probably be useful in m_move() too. 1069. * Since the maximum food distance is 5, this should never be more than 5 calls 1070. * deep. 1071. */ 1072. STATIC_OVL boolean 1073. can_reach_location(mon, mx, my, fx, fy) 1074. struct monst *mon; 1075. xchar mx, my, fx, fy; 1076. { 1077. int i, j; 1078. int dist; 1079. 1080. if (mx == fx && my == fy) return TRUE; 1081. if (!isok(mx, my)) return FALSE; /* should not happen */ 1082. 1083. dist = dist2(mx, my, fx, fy); 1084. for(i=mx-1; i<=mx+1; i++) { 1085. for(j=my-1; j<=my+1; j++) { 1086. if (!isok(i, j)) 1087. continue; 1088. if (dist2(i, j, fx, fy) >= dist) 1089. continue; 1090. if (IS_ROCK(levl[i][j].typ) && !passes_walls(mon->data) && 1091. (!may_dig(i,j) || !tunnels(mon->data))) 1092. continue; 1093. if (IS_DOOR(levl[i][j].typ) && 1094. (levl[i][j].doormask & (D_CLOSED | D_LOCKED))) 1095. continue; 1096. if (!could_reach_item(mon, i, j)) 1097. continue; 1098. if (can_reach_location(mon, i, j, fx, fy)) 1099. return TRUE; 1100. } 1101. } 1102. return FALSE; 1103. } 1104. 1105. #endif /* OVL0 */ 1106. #ifdef OVLB 1107. 1108. /*ARGSUSED*/ /* do_clear_area client */ 1109. STATIC_PTR void 1110. wantdoor(x, y, distance) 1111. int x, y; 1112. genericptr_t distance; 1113. { 1114. int ndist; 1115. 1116. if (*(int*)distance > (ndist = distu(x, y))) { 1117. gx = x; 1118. gy = y; 1119. *(int*)distance = ndist; 1120. } 1121. } 1122. 1123. #endif /* OVLB */ 1124. 1125. /*dogmove.c*/
|