abstract
| - Below is the full text to monmove.c from the source code of NetHack 3.2.0. To link to a particular line, write [[NetHack 3.2.0/monmove.c#line123]], for example. Warning! This is the source code from an old release. For the latest release, see Source code 1. /* SCCS Id: @(#)monmove.c 3.2 96/02/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. #include "mfndpos.h" 7. #include "artifact.h" 8. 9. #ifdef OVL0 10. 11. static int FDECL(disturb,(struct monst *)); 12. static void FDECL(distfleeck,(struct monst *,int *,int *,int *)); 13. static int FDECL(m_arrival, (struct monst *)); 14. static void FDECL(watch_on_duty,(struct monst *)); 15. 16. #endif /* OVL0 */ 17. #ifdef OVLB 18. 19. boolean /* TRUE : mtmp died */ 20. mb_trapped(mtmp) 21. register struct monst *mtmp; 22. { 23. if (flags.verbose) { 24. if (cansee(mtmp->mx, mtmp->my)) 25. pline("KABOOM!! You see a door explode."); 26. else if (flags.soundok) 27. You_hear("a distant explosion."); 28. } 29. wake_nearto(mtmp->mx, mtmp->my, 7*7); 30. mtmp->mstun = 1; 31. mtmp->mhp -= rnd(15); 32. if(mtmp->mhp <= 0) { 33. mondied(mtmp); 34. if (mtmp->mhp > 0) /* lifesaved */ 35. return(FALSE); 36. else 37. return(TRUE); 38. } 39. return(FALSE); 40. } 41. 42. #endif /* OVLB */ 43. #ifdef OVL0 44. 45. static void 46. watch_on_duty(mtmp) 47. register struct monst *mtmp; 48. { 49. register s_level *slev = Is_special(&u.uz); 50. int x, y; 51. 52. if(slev && slev->flags.town && mtmp->mpeaceful && 53. mtmp->mcansee && m_canseeu(mtmp) && !rn2(3)) { 54. 55. if(picking_lock(&x, &y) && IS_DOOR(levl[x][y].typ) && 56. (levl[x][y].doormask & D_LOCKED)) { 57. 58. if(couldsee(mtmp->mx, mtmp->my)) { 59. 60. pline("%s yells:", Amonnam(mtmp)); 61. if(levl[x][y].looted & D_WARNED) { 62. verbalize("Halt, thief! You're under arrest!"); 63. (void) angry_guards(!(flags.soundok)); 64. } else { 65. verbalize("Hey, stop picking that lock!"); 66. levl[x][y].looted |= D_WARNED; 67. } 68. stop_occupation(); 69. } 70. } 71. } 72. } 73. 74. #endif /* OVL0 */ 75. #ifdef OVL1 76. 77. int 78. dochugw(mtmp) 79. register struct monst *mtmp; 80. { 81. register int x = mtmp->mx, y = mtmp->my; 82. boolean already_saw_mon = !occupation ? 0 : canspotmon(mtmp); 83. int rd = dochug(mtmp); 84. int dd; 85. 86. if(Warning && !rd && !mtmp->mpeaceful && 87. (dd = distu(mtmp->mx,mtmp->my)) < distu(x,y) && 88. dd < 100 && !canseemon(mtmp)) { 89. /* Note: this assumes we only want to warn against the monster to 90. * which the weapon does extra damage, as there is no "monster 91. * which the weapon warns against" field. 92. */ 93. if (spec_ability(uwep, SPFX_WARN) && spec_dbon(uwep, mtmp, 1)) 94. warnlevel = 100; 95. else if ((int) (mtmp->m_lev / 4) > warnlevel) 96. warnlevel = (mtmp->m_lev / 4); 97. } 98. 99. /* a similar check is in monster_nearby() in hack.c */ 100. /* check whether hero notices monster and stops current activity */ 101. if (occupation && !rd && !Confusion && 102. (!mtmp->mpeaceful || Hallucination) && 103. /* it's close enough to be a threat */ 104. distu(mtmp->mx,mtmp->my) <= (BOLT_LIM+1)*(BOLT_LIM+1) && 105. /* and either couldn't see it before, or it was too far away */ 106. (!already_saw_mon || !couldsee(x,y) || 107. distu(x,y) > (BOLT_LIM+1)*(BOLT_LIM+1)) && 108. /* can see it now, or sense it and would normally see it */ 109. (canseemon(mtmp) || 110. (sensemon(mtmp) && couldsee(mtmp->mx,mtmp->my))) && 111. !noattacks(mtmp->data) && !onscary(u.ux, u.uy, mtmp)) 112. stop_occupation(); 113. 114. return(rd); 115. } 116. 117. #endif /* OVL1 */ 118. #ifdef OVL2 119. 120. boolean 121. onscary(x, y, mtmp) 122. int x, y; 123. struct monst *mtmp; 124. { 125. if (mtmp->isshk || mtmp->isgd || mtmp->iswiz || !mtmp->mcansee || 126. mtmp->mpeaceful || mtmp->data->mlet == S_HUMAN || 127. is_lminion(mtmp->data) || is_rider(mtmp->data) || 128. mtmp->data == &mons[PM_MINOTAUR]) 129. return(FALSE); 130. 131. return (boolean)(sobj_at(SCR_SCARE_MONSTER, x, y) 132. #ifdef ELBERETH 133. || sengr_at("Elbereth", x, y) 134. #endif 135. || (mtmp->data->mlet == S_VAMPIRE 136. && IS_ALTAR(levl[x][y].typ))); 137. } 138. 139. #endif /* OVL2 */ 140. #ifdef OVL0 141. 142. /* regenerate lost hit points */ 143. void 144. mon_regen(mon, digest_meal) 145. struct monst *mon; 146. boolean digest_meal; 147. { 148. if (mon->mhp < mon->mhpmax && 149. (moves % 20 == 0 || regenerates(mon->data))) mon->mhp++; 150. if (mon->mspec_used) mon->mspec_used--; 151. if (digest_meal) { 152. if (mon->meating) mon->meating--; 153. } 154. } 155. 156. /* 157. * Possibly awaken the given monster. Return a 1 if the monster has been 158. * jolted awake. 159. */ 160. static int 161. disturb(mtmp) 162. register struct monst *mtmp; 163. { 164. /* 165. * + Ettins are hard to surprise. 166. * + Nymphs, jabberwocks, and leprechauns do not easily wake up. 167. * 168. * Wake up if: 169. * in direct LOS AND 170. * within 10 squares AND 171. * not stealthy or (mon is an ettin and 9/10) AND 172. * (mon is not a nymph, jabberwock, or leprechaun) or 1/50 AND 173. * Aggravate or mon is (dog or human) or 174. * (1/7 and mon is not mimicing furniture or object) 175. */ 176. if(couldsee(mtmp->mx,mtmp->my) && 177. distu(mtmp->mx,mtmp->my) <= 100 && 178. (!Stealth || (mtmp->data == &mons[PM_ETTIN] && rn2(10))) && 179. (!(mtmp->data->mlet == S_NYMPH 180. || mtmp->data == &mons[PM_JABBERWOCK] 181. || mtmp->data->mlet == S_LEPRECHAUN) || !rn2(50)) && 182. (Aggravate_monster 183. || (mtmp->data->mlet == S_DOG || 184. mtmp->data->mlet == S_HUMAN) 185. || (!rn2(7) && mtmp->m_ap_type != M_AP_FURNITURE && 186. mtmp->m_ap_type != M_AP_OBJECT) )) { 187. 188. mtmp->msleep = 0; 189. return(1); 190. } 191. return(0); 192. } 193. 194. static void 195. distfleeck(mtmp,inrange,nearby,scared) 196. register struct monst *mtmp; 197. int *inrange, *nearby, *scared; 198. { 199. int seescaryx, seescaryy; 200. 201. *inrange = (dist2(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy) <= 202. (BOLT_LIM * BOLT_LIM)); 203. *nearby = *inrange && monnear(mtmp, mtmp->mux, mtmp->muy); 204. 205. /* Note: if your image is displaced, the monster sees the Elbereth 206. * at your displaced position, thus never attacking your displaced 207. * position, but possibly attacking you by accident. If you are 208. * invisible, it sees the Elbereth at your real position, thus never 209. * running into you by accident but possibly attacking the spot 210. * where it guesses you are. 211. */ 212. if (!mtmp->mcansee || (Invis && !perceives(mtmp->data))) { 213. seescaryx = mtmp->mux; 214. seescaryy = mtmp->muy; 215. } else { 216. seescaryx = u.ux; 217. seescaryy = u.uy; 218. } 219. *scared = (*nearby && (onscary(seescaryx, seescaryy, mtmp) || 220. (!mtmp->mpeaceful && 221. in_your_sanctuary(mtmp->mx, mtmp->my)))); 222. 223. if(*scared && !mtmp->mflee) { 224. if (!sticks(uasmon)) 225. unstuck(mtmp); /* monster lets go when fleeing */ 226. mtmp->mflee = 1; 227. #ifdef STUPID 228. if (rn2(7)) 229. mtmp->mfleetim = rnd(10); 230. else 231. mtmp->mfleetim = rnd(100); 232. #else 233. mtmp->mfleetim = rnd(rn2(7) ? 10 : 100); 234. #endif 235. } 236. 237. } 238. 239. /* perform a special one-time action for a monster; returns -1 if nothing 240. special happened, 0 if monster uses up its turn, 1 if monster is killed */ 241. static int 242. m_arrival(mon) 243. struct monst *mon; 244. { 245. mon->mstrategy &= ~STRAT_ARRIVE; /* always reset */ 246. 247. return -1; 248. } 249. 250. /* returns 1 if monster died moving, 0 otherwise */ 251. /* The whole dochugw/m_move/distfleeck/mfndpos section is serious spaghetti 252. * code. --KAA 253. */ 254. int 255. dochug(mtmp) 256. register struct monst *mtmp; 257. { 258. register struct permonst *mdat; 259. register int tmp=0; 260. int inrange, nearby, scared; 261. 262. /* Pre-movement adjustments */ 263. 264. if(mtmp->cham && !rn2(6)) /* polymorph chameleons */ 265. (void) newcham(mtmp, (struct permonst *)0); 266. 267. /* regenerate monsters */ 268. mon_regen(mtmp, FALSE); 269. 270. /* polymorph lycanthropes */ 271. were_change(mtmp); 272. 273. mdat = mtmp->data; /* after newcham and were_change */ 274. 275. if (mtmp->mstrategy & STRAT_ARRIVE) { 276. int res = m_arrival(mtmp); 277. if (res >= 0) return res; 278. } 279. 280. /* check for waitmask status change */ 281. if ((mtmp->mstrategy & STRAT_WAITFORU) && 282. (m_canseeu(mtmp) || mtmp->mhp < mtmp->mhpmax)) 283. mtmp->mstrategy &= ~STRAT_WAITFORU; 284. 285. /* update quest status flags */ 286. quest_stat_check(mtmp); 287. 288. if (!mtmp->mcanmove || (mtmp->mstrategy & STRAT_WAITMASK)) { 289. if (Hallucination) newsym(mtmp->mx,mtmp->my); 290. if (mtmp->mcanmove && (mtmp->mstrategy & STRAT_CLOSE) && 291. !mtmp->msleep && monnear(mtmp, u.ux, u.uy)) 292. quest_talk(mtmp); /* give the leaders a chance to speak */ 293. return(0); /* other frozen monsters can't do anything */ 294. } 295. 296. /* there is a chance we will wake it */ 297. if(mtmp->msleep && !disturb(mtmp)) { 298. if (Hallucination) newsym(mtmp->mx,mtmp->my); 299. return(0); 300. } 301. 302. /* not frozen or sleeping: wipe out texts written in the dust */ 303. wipe_engr_at(mtmp->mx, mtmp->my, 1); 304. 305. /* confused monsters get unconfused with small probability */ 306. if (mtmp->mconf && !rn2(50)) mtmp->mconf = 0; 307. 308. /* stunned monsters get un-stunned with larger probability */ 309. if (mtmp->mstun && !rn2(10)) mtmp->mstun = 0; 310. 311. /* some monsters teleport */ 312. if (mtmp->mflee && !rn2(40) && can_teleport(mdat) && !mtmp->iswiz) { 313. rloc(mtmp); 314. return(0); 315. } 316. if (mdat->msound == MS_SHRIEK && !um_dist(mtmp->mx, mtmp->my, 1)) 317. m_respond(mtmp); 318. if (mdat == &mons[PM_MEDUSA] && cansee(mtmp->mx, mtmp->my)) 319. m_respond(mtmp); 320. if (mdat->mmove < rnd(6)) return(0); 321. 322. /* fleeing monsters might regain courage */ 323. if (mtmp->mflee && !mtmp->mfleetim 324. && mtmp->mhp == mtmp->mhpmax && !rn2(25)) mtmp->mflee = 0; 325. 326. set_apparxy(mtmp); 327. /* Must be done after you move and before the monster does. The 328. * set_apparxy() call in m_move() doesn't suffice since the variables 329. * inrange, etc. all depend on stuff set by set_apparxy(). 330. */ 331. 332. /* Monsters that want to acquire things */ 333. /* may teleport, so do it before inrange is set */ 334. if(is_covetous(mdat)) (void) tactics(mtmp); 335. 336. /* check distance and scariness of attacks */ 337. distfleeck(mtmp,&inrange,&nearby,&scared); 338. 339. if(find_defensive(mtmp)) { 340. if (use_defensive(mtmp) != 0) 341. return 1; 342. } else if(find_misc(mtmp)) { 343. if (use_misc(mtmp) != 0) 344. return 1; 345. } 346. 347. /* Demonic Blackmail! */ 348. if(nearby && mdat->msound == MS_BRIBE && 349. mtmp->mpeaceful && !mtmp->mtame && !u.uswallow) { 350. if (mtmp->mux != u.ux || mtmp->muy != u.uy) { 351. pline("%s whispers at thin air.", 352. cansee(mtmp->mux, mtmp->muy) ? Monnam(mtmp) : "It"); 353. 354. if (is_demon(uasmon)) rloc(mtmp); 355. /* "Good hunting, brother" */ 356. else { 357. mtmp->minvis = mtmp->perminvis = 0; 358. /* Why? For the same reason in real demon talk */ 359. pline("%s gets angry!", Amonnam(mtmp)); 360. mtmp->mpeaceful = 0; 361. /* since no way is an image going to pay it off */ 362. } 363. } else if(demon_talk(mtmp)) return(1); /* you paid it off */ 364. } 365. 366. /* the watch will look around and see if you are up to no good :-) */ 367. if (mdat == &mons[PM_WATCHMAN] || mdat == &mons[PM_WATCH_CAPTAIN]) 368. watch_on_duty(mtmp); 369. 370. else if (mdat == &mons[PM_MIND_FLAYER] && !rn2(20)) { 371. struct monst *m2, *nmon = (struct monst *)0; 372. 373. if (canseemon(mtmp)) 374. pline("%s concentrates.", Monnam(mtmp)); 375. if (distu(mtmp->mx, mtmp->my) > BOLT_LIM * BOLT_LIM) { 376. You("sense a faint wave of psychic energy."); 377. goto toofar; 378. } 379. pline("A wave of psychic energy pours over you!"); 380. if (mtmp->mpeaceful && 381. (!Conflict || resist(mtmp, RING_CLASS, 0, 0))) 382. pline("It feels quite soothing."); 383. else { 384. register boolean m_sen = sensemon(mtmp); 385. 386. if (m_sen || (Telepat && rn2(2)) || !rn2(10)) { 387. int dmg; 388. pline("It locks on to your %s!", 389. m_sen ? "telepathy" : 390. Telepat ? "latent telepathy" : "mind"); 391. dmg = rnd(15); 392. if (Half_spell_damage) dmg = (dmg+1) / 2; 393. losehp(dmg, "psychic blast", KILLED_BY_AN); 394. } 395. } 396. for(m2=fmon; m2; m2 = nmon) { 397. nmon = m2->nmon; 398. if (m2->mpeaceful != mtmp->mpeaceful) continue; 399. if (mindless(m2->data)) continue; 400. if (m2 == mtmp) continue; 401. if ((telepathic(m2->data) && 402. (rn2(2) || m2->mblinded)) || !rn2(10)) { 403. if (cansee(m2->mx, m2->my)) 404. pline("It locks on to %s.", mon_nam(m2)); 405. m2->mhp -= rnd(15); 406. if (m2->mhp <= 0) 407. monkilled(m2, "", AD_DRIN); 408. } 409. } 410. } 411. toofar: 412. /* If monster is nearby you, and has to wield a weapon, do so. This 413. * costs the monster a move, of course. 414. */ 415. if((!mtmp->mpeaceful || Conflict) && inrange && 416. dist2(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy) <= 8 417. && attacktype(mdat, AT_WEAP)) { 418. if (mtmp->weapon_check == NEED_WEAPON || !MON_WEP(mtmp)) { 419. mtmp->weapon_check = NEED_HTH_WEAPON; 420. if (mon_wield_item(mtmp) != 0) return(0); 421. } 422. } 423. 424. /* Now the actual movement phase */ 425. 426. if(!nearby || mtmp->mflee || scared || 427. mtmp->mconf || mtmp->mstun || (mtmp->minvis && !rn2(3)) || 428. (mdat->mlet == S_LEPRECHAUN && !u.ugold && (mtmp->mgold || rn2(2))) || 429. (is_wanderer(mdat) && !rn2(4)) || (Conflict && !mtmp->iswiz) || 430. (!mtmp->mcansee && !rn2(4)) || mtmp->mpeaceful) { 431. 432. tmp = m_move(mtmp, 0); 433. distfleeck(mtmp,&inrange,&nearby,&scared); /* recalc */ 434. 435. switch (tmp) { 436. case 0: /* no movement, but it can still attack you */ 437. case 3: /* absolutely no movement */ 438. /* for pets, case 0 and 3 are equivalent */ 439. /* During hallucination, monster appearance should 440. * still change - even if it doesn't move. 441. */ 442. if(Hallucination) newsym(mtmp->mx,mtmp->my); 443. break; 444. case 1: /* monster moved */ 445. /* Maybe it stepped on a trap and fell asleep... */ 446. if(mtmp->msleep || !mtmp->mcanmove) return(0); 447. if(!nearby && 448. (ranged_attk(mdat) || find_offensive(mtmp))) 449. break; 450. else if(mdat->mmove <= 12) { 451. /* a monster that's digesting you can move at the 452. * same time -dlc 453. */ 454. if(u.uswallow && mtmp == u.ustuck) 455. return(mattacku(mtmp)); 456. return(0); 457. } 458. break; 459. case 2: /* monster died */ 460. return(1); 461. } 462. } 463. 464. /* Now, attack the player if possible - one attack set per monst */ 465. 466. if (!mtmp->mpeaceful || 467. (Conflict && !resist(mtmp, RING_CLASS, 0, 0))) { 468. if(inrange && !noattacks(mdat) && u.uhp > 0 && !scared && tmp != 3) 469. if(mattacku(mtmp)) return(1); /* monster died (e.g. exploded) */ 470. 471. if(mtmp->wormno) wormhitu(mtmp); 472. } 473. /* special speeches for quest monsters */ 474. if(!mtmp->msleep && mtmp->mcanmove && nearby) 475. quest_talk(mtmp); 476. else 477. /* extra emotional attack for vile monsters */ 478. if(inrange && mtmp->data->msound == MS_CUSS && !mtmp->mpeaceful && 479. couldsee(mtmp->mx, mtmp->my) && !mtmp->minvis && !rn2(5)) 480. cuss(mtmp); 481. 482. /* extra movement for fast monsters */ 483. if(mdat->mmove-12 > rnd(12)) tmp = m_move(mtmp, 1); 484. return(tmp == 2); 485. } 486. 487. static NEARDATA const char practical[] = { WEAPON_CLASS, ARMOR_CLASS, GEM_CLASS, FOOD_CLASS, 0 }; 488. static NEARDATA const char magical[] = { 489. AMULET_CLASS, POTION_CLASS, SCROLL_CLASS, WAND_CLASS, RING_CLASS, 490. SPBOOK_CLASS, 0 }; 491. static NEARDATA const char indigestion[] = { BALL_CLASS, ROCK_CLASS, 0 }; 492. static NEARDATA const char boulder_class[] = { ROCK_CLASS, 0 }; 493. static NEARDATA const char gem_class[] = { GEM_CLASS, 0 }; 494. 495. boolean 496. itsstuck(mtmp) 497. register struct monst *mtmp; 498. { 499. if (sticks(uasmon) && mtmp==u.ustuck && !u.uswallow) { 500. pline("%s cannot escape from you!", Monnam(mtmp)); 501. return(TRUE); 502. } 503. return(FALSE); 504. } 505. 506. /* Return values: 507. * 0: did not move, but can still attack and do other stuff. 508. * 1: moved, possibly can attack. 509. * 2: monster died. 510. * 3: did not move, and can't do anything else either. 511. */ 512. int 513. m_move(mtmp, after) 514. register struct monst *mtmp; 515. register int after; 516. { 517. register int appr; 518. xchar gx,gy,nix,niy,chcnt; 519. int chi; /* could be schar except for stupid Sun-2 compiler */ 520. boolean likegold=0, likegems=0, likeobjs=0, likemagic=0, conceals=0; 521. boolean likerock=0, can_tunnel=0; 522. boolean can_open=0, can_unlock=0, doorbuster=0; 523. boolean uses_items=0; 524. struct permonst *ptr; 525. struct monst *mtoo; 526. schar mmoved = 0; /* not strictly nec.: chi >= 0 will do */ 527. long info[9]; 528. long flag; 529. int omx = mtmp->mx, omy = mtmp->my; 530. struct obj *mw_tmp; 531. 532. if(mtmp->mtrapped) { 533. int i = mintrap(mtmp); 534. if(i >= 2) { newsym(mtmp->mx,mtmp->my); return(2); }/* it died */ 535. if(i == 1) return(0); /* still in trap, so didn't move */ 536. } 537. ptr = mtmp->data; /* mintrap() can change mtmp->data -dlc */ 538. 539. if (mtmp->meating) { 540. mtmp->meating--; 541. return 3; /* still eating */ 542. } 543. if (hides_under(ptr) && OBJ_AT(mtmp->mx, mtmp->my) && rn2(10)) 544. return 0; /* do not leave hiding place */ 545. 546. set_apparxy(mtmp); 547. /* where does mtmp think you are? */ 548. /* Not necessary if m_move called from this file, but necessary in 549. * other calls of m_move (ex. leprechauns dodging) 550. */ 551. can_tunnel = tunnels(ptr) && 552. #ifdef REINCARNATION 553. !Is_rogue_level(&u.uz) && 554. #endif 555. (!needspick(ptr) || m_carrying(mtmp, PICK_AXE)); 556. can_open = !(nohands(ptr) || verysmall(ptr)); 557. can_unlock = ((can_open && m_carrying(mtmp, SKELETON_KEY)) || mtmp->iswiz); 558. doorbuster = is_giant(ptr); 559. if(mtmp->wormno) goto not_special; 560. /* my dog gets special treatment */ 561. if(mtmp->mtame) { 562. mmoved = dog_move(mtmp, after); 563. goto postmov; 564. } 565. 566. /* likewise for shopkeeper */ 567. if(mtmp->isshk) { 568. mmoved = shk_move(mtmp); 569. if(mmoved == -2) return(2); 570. if(mmoved >= 0) goto postmov; 571. mmoved = 0; /* follow player outside shop */ 572. } 573. 574. /* and for the guard */ 575. if(mtmp->isgd) { 576. mmoved = gd_move(mtmp); 577. if(mmoved == -2) return(2); 578. if(mmoved >= 0) goto postmov; 579. mmoved = 0; 580. } 581. 582. /* and the acquisitive monsters get special treatment */ 583. if(is_covetous(ptr)) { 584. xchar tx = STRAT_GOALX(mtmp->mstrategy), 585. ty = STRAT_GOALY(mtmp->mstrategy); 586. struct monst *intruder = m_at(tx, ty); 587. /* 588. * if there's a monster on the object or in possesion of it, 589. * attack it. 590. */ 591. if((dist2(mtmp->mx, mtmp->my, tx, ty) < 2) && 592. intruder && (intruder != mtmp)) { 593. 594. if(mattackm(mtmp, intruder) == 2) return(2); 595. mmoved = 1; 596. } else mmoved = 0; 597. goto postmov; 598. } 599. 600. /* and for the priest */ 601. if(mtmp->ispriest) { 602. mmoved = pri_move(mtmp); 603. if(mmoved == -2) return(2); 604. if(mmoved >= 0) goto postmov; 605. mmoved = 0; 606. } 607. 608. #ifdef MAIL 609. if(ptr == &mons[PM_MAIL_DAEMON]) { 610. if(flags.soundok && canseemon(mtmp)) 611. verbalize("I'm late!"); 612. mongone(mtmp); 613. return(2); 614. } 615. #endif 616. 617. /* teleport if that lies in our nature */ 618. if(ptr == &mons[PM_TENGU] && !rn2(5) && !mtmp->mcan) { 619. if(mtmp->mhp < 7 || mtmp->mpeaceful || rn2(2)) 620. rloc(mtmp); 621. else 622. mnexto(mtmp); 623. mmoved = 1; 624. goto postmov; 625. } 626. not_special: 627. if(u.uswallow && !mtmp->mflee && u.ustuck != mtmp) return(1); 628. omx = mtmp->mx; 629. omy = mtmp->my; 630. gx = mtmp->mux; 631. gy = mtmp->muy; 632. appr = mtmp->mflee ? -1 : 1; 633. if (mtmp->mconf || (u.uswallow && mtmp == u.ustuck)) 634. appr = 0; 635. else { 636. boolean should_see = (couldsee(omx, omy) && 637. (levl[gx][gy].lit || 638. !levl[omx][omy].lit) && 639. (dist2(omx, omy, gx, gy) <= 36)); 640. 641. if (!mtmp->mcansee || 642. (should_see && Invis && !perceives(ptr) && rn2(11)) || 643. (u.usym == S_MIMIC_DEF) || u.uundetected || 644. (u.usym == 0 && !likes_gold(ptr)) || /* 0 => gold */ 645. (mtmp->mpeaceful && !mtmp->isshk) || /* allow shks to follow */ 646. ((ptr->mlet == S_STALKER || ptr->mlet == S_BAT || 647. ptr->mlet == S_LIGHT) && !rn2(3))) 648. appr = 0; 649. 650. if(monsndx(ptr) == PM_LEPRECHAUN && (appr == 1) && 651. (mtmp->mgold > u.ugold)) 652. appr = -1; 653. 654. if (!should_see && can_track(ptr)) { 655. register coord *cp; 656. 657. cp = gettrack(omx,omy); 658. if (cp) { 659. gx = cp->x; 660. gy = cp->y; 661. } 662. } 663. } 664. 665. if ((!mtmp->mpeaceful || !rn2(10)) 666. #ifdef REINCARNATION 667. && (!Is_rogue_level(&u.uz)) 668. #endif 669. ) { 670. boolean in_line = lined_up(mtmp) && 671. (distmin(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy) <= 672. (throws_rocks(uasmon) ? 20 : ACURRSTR/2+1) 673. ); 674. 675. if (appr != 1 || !in_line) { 676. /* Monsters in combat won't pick stuff up, avoiding the 677. * situation where you toss arrows at it and it has nothing 678. * better to do than pick the arrows up. 679. */ 680. register int pctload = (curr_mon_load(mtmp) * 100) / 681. max_mon_load(mtmp); 682. 683. /* look for gold or jewels nearby */ 684. likegold = (likes_gold(ptr) && pctload < 95); 685. likegems = (likes_gems(ptr) && pctload < 85); 686. uses_items = (!mindless(ptr) && !is_animal(ptr) 687. && pctload < 75); 688. likeobjs = (likes_objs(ptr) && pctload < 75); 689. likemagic = (likes_magic(ptr) && pctload < 85); 690. likerock = (throws_rocks(ptr) && pctload < 50); 691. conceals = hides_under(ptr); 692. } 693. } 694. 695. #define SQSRCHRADIUS 5 696. 697. { register int minr = SQSRCHRADIUS; /* not too far away */ 698. register struct obj *otmp; 699. register int xx, yy; 700. int oomx, oomy, lmx, lmy; 701. 702. /* cut down the search radius if it thinks character is closer. */ 703. if(distmin(mtmp->mux, mtmp->muy, omx, omy) < SQSRCHRADIUS && 704. !mtmp->mpeaceful) minr--; 705. /* guards shouldn't get too distracted */ 706. if(!mtmp->mpeaceful && is_mercenary(ptr)) minr = 1; 707. 708. if((likegold || likegems || likeobjs || likemagic || likerock || conceals) 709. && (!*in_rooms(omx, omy, SHOPBASE) || (!rn2(25) && !mtmp->isshk))) { 710. look_for_obj: 711. oomx = min(COLNO-1, omx+minr); 712. oomy = min(ROWNO-1, omy+minr); 713. lmx = max(1, omx-minr); 714. lmy = max(0, omy-minr); 715. for(otmp = fobj; otmp; otmp = otmp->nobj) { 716. /* monsters may pick rocks up, but won't go out of their way 717. to grab them; this might hamper sling wielders, but it cuts 718. down on move overhead by filtering out most common item */ 719. if (otmp->otyp == ROCK) continue; 720. xx = otmp->ox; 721. yy = otmp->oy; 722. /* Nymphs take everything. Most other creatures should not 723. * pick up corpses except as a special case like in 724. * searches_for_item(). We need to do this check in 725. * mpickstuff() as well. 726. */ 727. if(xx >= lmx && xx <= oomx && yy >= lmy && yy <= oomy) { 728. /* don't get stuck circling around an object that's underneath 729. an immobile or hidden monster; paralysis victims excluded */ 730. if ((mtoo = m_at(xx,yy)) != 0 && 731. (mtoo->msleep || mtoo->mundetected || 732. (mtoo->mappearance && !mtoo->iswiz) || 733. !mtoo->data->mmove)) continue; 734. 735. if(((likegold && otmp->oclass == GOLD_CLASS) || 736. (likeobjs && index(practical, otmp->oclass) && 737. (otmp->otyp != CORPSE || (ptr->mlet == S_NYMPH 738. && !is_rider(&mons[otmp->corpsenm])))) || 739. (likemagic && index(magical, otmp->oclass)) || 740. (uses_items && searches_for_item(mtmp, otmp)) || 741. (likerock && otmp->otyp == BOULDER) || 742. (likegems && otmp->oclass == GEM_CLASS && 743. objects[otmp->otyp].oc_material != MINERAL) || 744. (conceals && !cansee(otmp->ox,otmp->oy)) || 745. (ptr == &mons[PM_GELATINOUS_CUBE] && 746. !index(indigestion, otmp->oclass) && 747. !(otmp->otyp == CORPSE && 748. otmp->corpsenm == PM_COCKATRICE)) 749. ) && touch_artifact(otmp,mtmp)) { 750. if(can_carry(mtmp,otmp) && 751. (throws_rocks(ptr) || 752. !sobj_at(BOULDER,xx,yy)) && 753. (ptr->mlet != S_UNICORN || 754. objects[otmp->otyp].oc_material == GEMSTONE) && 755. /* Don't get stuck circling an Elbereth */ 756. !(onscary(xx, yy, mtmp))) { 757. minr = distmin(omx,omy,xx,yy); 758. oomx = min(COLNO-1, omx+minr); 759. oomy = min(ROWNO-1, omy+minr); 760. lmx = max(1, omx-minr); 761. lmy = max(0, omy-minr); 762. gx = otmp->ox; 763. gy = otmp->oy; 764. if (gx == omx && gy == omy) { 765. mmoved = 3; /* actually unnecessary */ 766. goto postmov; 767. } 768. } 769. } 770. } 771. } 772. } else if(likegold) { 773. /* don't try to pick up anything else, but use the same loop */ 774. uses_items = 0; 775. likegems = likeobjs = likemagic = likerock = conceals = 0; 776. goto look_for_obj; 777. } 778. 779. if(minr < SQSRCHRADIUS && appr == -1) { 780. if(distmin(omx,omy,mtmp->mux,mtmp->muy) <= 3) { 781. gx = mtmp->mux; 782. gy = mtmp->muy; 783. } else 784. appr = 1; 785. } 786. } 787. 788. if (can_tunnel && needspick(ptr) && 789. (mw_tmp = MON_WEP(mtmp)) != 0 && mw_tmp->otyp != PICK_AXE) { 790. /* not wielding its pick-axe yet; if its current weapon 791. is cursed, then it can't switch; when approaching, 792. it won't switch if the desired destination can be reached 793. without digging [to inhibit repeated pick/weapon flip-flop] */ 794. if (mw_tmp->cursed || (appr > 0 && m_cansee(mtmp, gx, gy))) 795. can_tunnel = FALSE; 796. } 797. 798. nix = omx; 799. niy = omy; 800. flag = 0L; 801. if (mtmp->mpeaceful && (!Conflict || resist(mtmp, RING_CLASS, 0, 0))) 802. flag |= (ALLOW_SANCT | ALLOW_SSM); 803. else flag |= ALLOW_U; 804. if (ptr->mlet == S_UNICORN) flag |= NOTONL; 805. if (passes_walls(ptr)) flag |= (ALLOW_WALL | ALLOW_ROCK); 806. if (can_tunnel) flag |= ALLOW_DIG; 807. if (is_human(ptr) || ptr == &mons[PM_MINOTAUR]) flag |= ALLOW_SSM; 808. if (is_undead(ptr) && ptr->mlet != S_GHOST) flag |= NOGARLIC; 809. if (throws_rocks(ptr)) flag |= ALLOW_ROCK; 810. if (can_open) flag |= OPENDOOR; 811. if (can_unlock) flag |= UNLOCKDOOR; 812. if (doorbuster) flag |= BUSTDOOR; 813. { 814. register int i, j, nx, ny, nearer; 815. int jcnt, cnt; 816. int ndist, nidist; 817. register coord *mtrk; 818. coord poss[9]; 819. 820. cnt = mfndpos(mtmp, poss, info, flag); 821. chcnt = 0; 822. jcnt = min(MTSZ, cnt-1); 823. chi = -1; 824. nidist = dist2(nix,niy,gx,gy); 825. /* allow monsters be shortsighted on some levels for balance */ 826. if(!mtmp->mpeaceful && level.flags.shortsighted && 827. nidist > (couldsee(nix,niy) ? 144 : 36) && appr == 1) appr = 0; 828. 829. for(i=0; i < cnt; i++) { 830. nx = poss[i].x; 831. ny = poss[i].y; 832. 833. if (appr != 0) { 834. mtrk = &mtmp->mtrack[0]; 835. for(j=0; j < jcnt; mtrk++, j++) 836. if(nx == mtrk->x && ny == mtrk->y) 837. if(rn2(4*(cnt-j))) 838. goto nxti; 839. } 840. 841. nearer = ((ndist = dist2(nx,ny,gx,gy)) < nidist); 842. 843. if((appr == 1 && nearer) || (appr == -1 && !nearer) || 844. (!appr && !rn2(++chcnt)) || !mmoved) { 845. nix = nx; 846. niy = ny; 847. nidist = ndist; 848. chi = i; 849. mmoved = 1; 850. } 851. nxti: ; 852. } 853. } 854. 855. if(mmoved) { 856. register int j; 857. 858. if (mmoved==1 && (u.ux != nix || u.uy != niy) && itsstuck(mtmp)) 859. return(3); 860. 861. if (mmoved==1 && can_tunnel && needspick(ptr) && 862. (!(mw_tmp = MON_WEP(mtmp)) || mw_tmp->otyp != PICK_AXE)) { 863. mtmp->weapon_check = NEED_PICK_AXE; 864. (void)mon_wield_item(mtmp); 865. } 866. /* If ALLOW_U is set, either it's trying to attack you, or it 867. * thinks it is. In either case, attack this spot in preference to 868. * all others. 869. */ 870. /* Actually, this whole section of code doesn't work as you'd expect. 871. * Most attacks are handled in dochug(). It calls distfleeck(), which 872. * among other things sets nearby if the monster is near you--and if 873. * nearby is set, we never call m_move unless it is a special case 874. * (confused, stun, etc.) The effect is that this ALLOW_U (and 875. * mfndpos) has no effect for normal attacks, though it lets a confused 876. * monster attack you by accident. 877. */ 878. if(info[chi] & ALLOW_U) { 879. nix = mtmp->mux; 880. niy = mtmp->muy; 881. } 882. if (nix == u.ux && niy == u.uy) { 883. mtmp->mux = u.ux; 884. mtmp->muy = u.uy; 885. return(0); 886. } 887. /* The monster may attack another based on 1 of 2 conditions: 888. * 1 - It may be confused. 889. * 2 - It may mistake the monster for your (displaced) image. 890. * Pets get taken care of above and shouldn't reach this code. 891. * Conflict gets handled even farther away (movemon()). 892. */ 893. if((info[chi] & ALLOW_M) || 894. (nix == mtmp->mux && niy == mtmp->muy)) { 895. struct monst *mtmp2; 896. int mstatus; 897. mtmp2 = m_at(nix,niy); 898. 899. mstatus = mattackm(mtmp, mtmp2); 900. 901. if (mstatus & MM_AGR_DIED) /* aggressor died */ 902. return 2; 903. 904. if ((mstatus & MM_HIT) && !(mstatus & MM_DEF_DIED) && 905. rn2(4) && mtmp2->mlstmv != monstermoves) { 906. mstatus = mattackm(mtmp2, mtmp); /* return attack */ 907. if (mstatus & MM_DEF_DIED) 908. return 2; 909. } 910. return 3; 911. } 912. 913. remove_monster(omx, omy); 914. place_monster(mtmp, nix, niy); 915. for(j = MTSZ-1; j > 0; j--) 916. mtmp->mtrack[j] = mtmp->mtrack[j-1]; 917. mtmp->mtrack[0].x = omx; 918. mtmp->mtrack[0].y = omy; 919. /* Place a segment at the old position. */ 920. if (mtmp->wormno) worm_move(mtmp); 921. } else { 922. if(ptr->mlet == S_UNICORN && rn2(2)) { 923. rloc(mtmp); 924. return(1); 925. } 926. if(mtmp->wormno) worm_nomove(mtmp); 927. } 928. postmov: 929. if(mmoved == 1 || mmoved == 3) { 930. boolean canseeit = cansee(mtmp->mx, mtmp->my); 931. 932. if(mmoved == 1) { 933. newsym(omx,omy); /* update the old position */ 934. if (mintrap(mtmp) >= 2) { 935. if(mtmp->mx) newsym(mtmp->mx,mtmp->my); 936. return(2); /* it died */ 937. } 938. ptr = mtmp->data; 939. 940. /* open a door, or crash through it, if you can */ 941. if(IS_DOOR(levl[mtmp->mx][mtmp->my].typ) 942. && !passes_walls(ptr) /* doesn't need to open doors */ 943. && !can_tunnel /* taken care of below */ 944. ) { 945. struct rm *here = &levl[mtmp->mx][mtmp->my]; 946. boolean btrapped = (here->doormask & D_TRAPPED); 947. 948. if(here->doormask & (D_LOCKED|D_CLOSED) && amorphous(ptr)) { 949. if (flags.verbose && canseeit) 950. pline("%s %ss under the door.", Monnam(mtmp), 951. (ptr == &mons[PM_FOG_CLOUD] || 952. ptr == &mons[PM_YELLOW_LIGHT]) 953. ? "flow" : "ooze"); 954. } else if(here->doormask & D_LOCKED && can_unlock) { 955. if(btrapped) { 956. here->doormask = D_NODOOR; 957. newsym(mtmp->mx, mtmp->my); 958. unblock_point(mtmp->mx,mtmp->my); /* vision */ 959. if(mb_trapped(mtmp)) return(2); 960. } else { 961. if (flags.verbose) { 962. if (canseeit) 963. You("see a door unlock and open."); 964. else if (flags.soundok) 965. You_hear("a door unlock and open."); 966. } 967. here->doormask = D_ISOPEN; 968. /* newsym(mtmp->mx, mtmp->my); */ 969. unblock_point(mtmp->mx,mtmp->my); /* vision */ 970. } 971. } else if (here->doormask == D_CLOSED && can_open) { 972. if(btrapped) { 973. here->doormask = D_NODOOR; 974. newsym(mtmp->mx, mtmp->my); 975. unblock_point(mtmp->mx,mtmp->my); /* vision */ 976. if(mb_trapped(mtmp)) return(2); 977. } else { 978. if (flags.verbose) { 979. if (canseeit) 980. You("see a door open."); 981. else if (flags.soundok) 982. You_hear("a door open."); 983. } 984. here->doormask = D_ISOPEN; 985. /* newsym(mtmp->mx, mtmp->my); */ /* done below */ 986. unblock_point(mtmp->mx,mtmp->my); /* vision */ 987. } 988. } else if (here->doormask & (D_LOCKED|D_CLOSED)) { 989. /* mfndpos guarantees this must be a doorbuster */ 990. if(btrapped) { 991. here->doormask = D_NODOOR; 992. newsym(mtmp->mx, mtmp->my); 993. unblock_point(mtmp->mx,mtmp->my); /* vision */ 994. if(mb_trapped(mtmp)) return(2); 995. } else { 996. if (flags.verbose) { 997. if (canseeit) 998. You("see a door crash open."); 999. else if (flags.soundok) 1000. You_hear("a door crash open."); 1001. } 1002. if (here->doormask & D_LOCKED && !rn2(2)) 1003. here->doormask = D_NODOOR; 1004. else here->doormask = D_BROKEN; 1005. /* newsym(mtmp->mx, mtmp->my); */ /* done below */ 1006. unblock_point(mtmp->mx,mtmp->my); /* vision */ 1007. } 1008. } 1009. } 1010. 1011. /* possibly dig */ 1012. if (can_tunnel && mdig_tunnel(mtmp)) 1013. return(2); /* mon died (position already updated) */ 1014. 1015. /* set also in domove(), hack.c */ 1016. if (u.uswallow && mtmp == u.ustuck && 1017. (mtmp->mx != omx || mtmp->my != omy)) { 1018. /* If the monster moved, then update */ 1019. u.ux0 = u.ux; 1020. u.uy0 = u.uy; 1021. u.ux = mtmp->mx; 1022. u.uy = mtmp->my; 1023. swallowed(0); 1024. } else 1025. newsym(mtmp->mx,mtmp->my); 1026. } 1027. if(OBJ_AT(mtmp->mx, mtmp->my) && mtmp->mcanmove) { 1028. /* Maybe a rock mole just ate some metal object */ 1029. if (metallivorous(ptr)) { 1030. if (meatgold(mtmp) == 2) return 2; /* it died */ 1031. } 1032. 1033. if(g_at(mtmp->mx,mtmp->my) && likegold) mpickgold(mtmp); 1034. 1035. /* Maybe a cube ate just about anything */ 1036. if (ptr == &mons[PM_GELATINOUS_CUBE]) { 1037. if (meatobj(mtmp) == 2) return 2; /* it died */ 1038. } 1039. 1040. if(!*in_rooms(mtmp->mx, mtmp->my, SHOPBASE) || !rn2(25)) { 1041. boolean picked = FALSE; 1042. 1043. if(likeobjs) picked |= mpickstuff(mtmp, practical); 1044. if(likemagic) picked |= mpickstuff(mtmp, magical); 1045. if(likerock) picked |= mpickstuff(mtmp, boulder_class); 1046. if(likegems) picked |= mpickstuff(mtmp, gem_class); 1047. if(uses_items) picked |= mpickstuff(mtmp, (char *)0); 1048. if(picked) mmoved = 3; 1049. } 1050. 1051. if(mtmp->minvis) { 1052. newsym(mtmp->mx, mtmp->my); 1053. if (mtmp->wormno) see_wsegs(mtmp); 1054. } 1055. } 1056. 1057. if(hides_under(ptr) || ptr->mlet == S_EEL) { 1058. /* Always set--or reset--mundetected if it's already hidden 1059. (just in case the object it was hiding under went away); 1060. usually set mundetected unless monster can't move. */ 1061. if (mtmp->mundetected || 1062. (mtmp->mcanmove && !mtmp->msleep && rn2(5))) 1063. mtmp->mundetected = (ptr->mlet != S_EEL) ? 1064. OBJ_AT(mtmp->mx, mtmp->my) : 1065. (is_pool(mtmp->mx, mtmp->my) && !Is_waterlevel(&u.uz)); 1066. newsym(mtmp->mx, mtmp->my); 1067. } 1068. } 1069. return(mmoved); 1070. } 1071. 1072. #endif /* OVL0 */ 1073. #ifdef OVL2 1074. 1075. boolean 1076. closed_door(x, y) 1077. register int x, y; 1078. { 1079. return((boolean)(IS_DOOR(levl[x][y].typ) && 1080. (levl[x][y].doormask & (D_LOCKED | D_CLOSED)))); 1081. } 1082. 1083. boolean 1084. accessible(x, y) 1085. register int x, y; 1086. { 1087. return((boolean)(ACCESSIBLE(levl[x][y].typ) && !closed_door(x, y))); 1088. } 1089. 1090. #endif /* OVL2 */ 1091. #ifdef OVL0 1092. 1093. /* decide where the monster thinks you are standing */ 1094. void 1095. set_apparxy(mtmp) 1096. register struct monst *mtmp; 1097. { 1098. boolean notseen, gotu; 1099. register int disp, mx = mtmp->mux, my = mtmp->muy; 1100. 1101. /* 1102. * do cheapest and/or most likely tests first 1103. */ 1104. 1105. /* pet knows your smell; grabber still has hold of you */ 1106. if (mtmp->mtame || mtmp == u.ustuck) goto found_you; 1107. 1108. /* monsters which know where you are don't suddenly forget, 1109. if you haven't moved away */ 1110. if (mx == u.ux && my == u.uy) goto found_you; 1111. 1112. notseen = (!mtmp->mcansee || (Invis && !perceives(mtmp->data))); 1113. /* add cases as required. eg. Displacement ... */ 1114. disp = ((notseen || Underwater) ? 1 : 1115. Displaced ? (couldsee(mx, my) ? 2 : 1) : 0); 1116. if (!disp) goto found_you; 1117. 1118. /* without something like the following, invis. and displ. 1119. are too powerful */ 1120. gotu = notseen ? !rn2(3) : Displaced ? !rn2(4) : FALSE; 1121. 1122. #if 0 /* this never worked as intended & isn't needed anyway */ 1123. /* If invis but not displaced, staying around gets you 'discovered' */ 1124. gotu |= (!Displaced && u.dx == 0 && u.dy == 0); 1125. #endif 1126. 1127. if (!gotu) { 1128. register int try_cnt = 0; 1129. do { 1130. if (++try_cnt > 200) goto found_you; /* punt */ 1131. mx = u.ux - disp + rn2(2*disp+1); 1132. my = u.uy - disp + rn2(2*disp+1); 1133. } while (!isok(mx,my) 1134. || (disp != 2 && mx == mtmp->mx && my == mtmp->my) 1135. || ((mx != u.ux || my != u.uy) && 1136. !passes_walls(mtmp->data) && 1137. (!ACCESSIBLE(levl[mx][my].typ) || 1138. (closed_door(mx, my) && !amorphous(mtmp->data))))); 1139. } else { 1140. found_you: 1141. mx = u.ux; 1142. my = u.uy; 1143. } 1144. 1145. mtmp->mux = mx; 1146. mtmp->muy = my; 1147. } 1148. 1149. #endif /* OVL0 */ 1150. 1151. /*monmove.c*/
|