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