| abstract
| - Below is the full text to hack.c from the source code of NetHack 3.3.0. To link to a particular line, write [[NetHack 3.3.0/hack.c#line123]], for example. Warning! This is the source code from an old release. For the latest release, see Source code 1. /* SCCS Id: @(#)hack.c 3.3 1999/08/16 */ 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. STATIC_DCL int NDECL(moverock); 8. STATIC_DCL int FDECL(still_chewing,(XCHAR_P,XCHAR_P)); 9. #ifdef SINKS 10. STATIC_DCL void NDECL(dosinkfall); 11. #endif 12. STATIC_DCL boolean FDECL(monstinroom, (struct permonst *,int)); 13. 14. STATIC_DCL void FDECL(move_update, (BOOLEAN_P)); 15. 16. #define IS_SHOP(x) (rooms[x].rtype >= SHOPBASE) 17. 18. #ifdef OVL2 19. 20. boolean 21. revive_nasty(x, y, msg) 22. int x,y; 23. const char *msg; 24. { 25. register struct obj *otmp, *otmp2; 26. struct monst *mtmp; 27. coord cc; 28. boolean revived = FALSE; 29. 30. for(otmp = level.objects[x][y]; otmp; otmp = otmp2) { 31. otmp2 = otmp->nexthere; 32. if (otmp->otyp == CORPSE && 33. (is_rider(&mons[otmp->corpsenm]) || 34. otmp->corpsenm == PM_WIZARD_OF_YENDOR)) { 35. /* move any living monster already at that location */ 36. if((mtmp = m_at(x,y)) && enexto(&cc, x, y, mtmp->data)) 37. rloc_to(mtmp, cc.x, cc.y); 38. if(msg) Norep("%s", msg); 39. revived = revive_corpse(otmp); 40. } 41. } 42. 43. /* this location might not be safe, if not, move revived monster */ 44. if (revived) { 45. mtmp = m_at(x,y); 46. if (mtmp && !goodpos(x, y, mtmp) && 47. enexto(&cc, x, y, mtmp->data)) { 48. rloc_to(mtmp, cc.x, cc.y); 49. } 50. /* else impossible? */ 51. } 52. 53. return (revived); 54. } 55. 56. STATIC_OVL int 57. moverock() 58. { 59. register xchar rx, ry, sx, sy; 60. register struct obj *otmp; 61. register struct trap *ttmp; 62. register struct monst *mtmp; 63. 64. sx = u.ux + u.dx, sy = u.uy + u.dy; /* boulder starting position */ 65. while ((otmp = sobj_at(BOULDER, sx, sy)) != 0) { 66. /* make sure that this boulder is visible as the top object */ 67. if (otmp != level.objects[sx][sy]) movobj(otmp, sx, sy); 68. 69. rx = u.ux + 2 * u.dx; /* boulder destination position */ 70. ry = u.uy + 2 * u.dy; 71. nomul(0); 72. if (Levitation || Is_airlevel(&u.uz)) { 73. if (Blind) feel_location(sx, sy); 74. You("don't have enough leverage to push %s.", the(xname(otmp))); 75. /* Give them a chance to climb over it? */ 76. return -1; 77. } 78. if (verysmall(youmonst.data) 79. #ifdef STEED 80. && !u.usteed 81. #endif 82. ) { 83. if (Blind) feel_location(sx, sy); 84. pline("You're too small to push that %s.", xname(otmp)); 85. goto cannot_push; 86. } 87. if (isok(rx,ry) && !IS_ROCK(levl[rx][ry].typ) && 88. (!IS_DOOR(levl[rx][ry].typ) || !(u.dx && u.dy) || ( 89. #ifdef REINCARNATION 90. !Is_rogue_level(&u.uz) && 91. #endif 92. (levl[rx][ry].doormask & ~D_BROKEN) == D_NODOOR)) && 93. !sobj_at(BOULDER, rx, ry)) { 94. ttmp = t_at(rx, ry); 95. mtmp = m_at(rx, ry); 96. 97. /* KMH -- Sokoban doesn't let you push boulders diagonally */ 98. if (In_sokoban(&u.uz) && u.dx && u.dy) { 99. if (Blind) feel_location(sx,sy); 100. pline("%s won't roll diagonally on this %s.", 101. The(xname(otmp)), surface(sx, sy)); 102. goto cannot_push; 103. } 104. 105. if (revive_nasty(rx, ry, "You sense movement on the other side.")) 106. return (-1); 107. 108. if (mtmp && !noncorporeal(mtmp->data) && 109. (!mtmp->mtrapped || 110. !(ttmp && ((ttmp->ttyp == PIT) || 111. (ttmp->ttyp == SPIKED_PIT))))) { 112. if (canspotmon(mtmp)) 113. pline("There's %s on the other side.", mon_nam(mtmp)); 114. else { 115. if (Blind) feel_location(sx, sy); 116. You_hear("a monster behind %s.", the(xname(otmp))); 117. map_invisible(rx, ry); 118. } 119. if (flags.verbose) 120. pline("Perhaps that's why %s cannot move it.", 121. #ifdef STEED 122. u.usteed ? mon_nam(u.usteed) : 123. #endif 124. "you"); 125. goto cannot_push; 126. } 127. 128. if (ttmp) 129. switch(ttmp->ttyp) { 130. case LANDMINE: 131. if (rn2(10)) { 132. pline("KAABLAMM!!! %s triggers %s land mine.", 133. The(xname(otmp)), 134. ttmp->madeby_u ? "your" : "a"); 135. obj_extract_self(otmp); 136. place_object(otmp, rx, ry); 137. deltrap(ttmp); 138. del_engr_at(rx,ry); 139. scatter(rx,ry, 4, 140. MAY_DESTROY|MAY_HIT|MAY_FRACTURE|VIS_EFFECTS, 141. (struct obj *)0); 142. if (cansee(rx,ry)) newsym(rx,ry); 143. continue; 144. } 145. break; 146. case SPIKED_PIT: 147. case PIT: 148. obj_extract_self(otmp); 149. /* vision kludge to get messages right; 150. the pit will temporarily be seen even 151. if this is one among multiple boulders */ 152. if (!Blind) viz_array[ry][rx] |= IN_SIGHT; 153. if (!flooreffects(otmp, rx, ry, "fall")) { 154. place_object(otmp, rx, ry); 155. } 156. if (mtmp && !Blind) newsym(rx, ry); 157. continue; 158. case HOLE: 159. case TRAPDOOR: 160. pline("%s %s and plugs a %s in the %s!", 161. The(xname(otmp)), 162. (ttmp->ttyp == TRAPDOOR) ? "triggers" : "falls into", 163. (ttmp->ttyp == TRAPDOOR) ? "trap door" : "hole", 164. surface(rx, ry)); 165. deltrap(ttmp); 166. delobj(otmp); 167. bury_objs(rx, ry); 168. if (cansee(rx,ry)) newsym(rx,ry); 169. continue; 170. case LEVEL_TELEP: 171. case TELEP_TRAP: 172. #ifdef STEED 173. if (u.usteed) 174. pline("%s pushes %s and suddenly it disappears!", 175. Monnam(u.usteed), the(xname(otmp))); 176. else 177. #endif 178. You("push %s and suddenly it disappears!", 179. the(xname(otmp))); 180. if (ttmp->ttyp == TELEP_TRAP) 181. rloco(otmp); 182. else { 183. int newlev = random_teleport_level(); 184. d_level dest; 185. 186. if (newlev == depth(&u.uz) || In_endgame(&u.uz)) 187. continue; 188. obj_extract_self(otmp); 189. add_to_migration(otmp); 190. get_level(&dest, newlev); 191. otmp->ox = dest.dnum; 192. otmp->oy = dest.dlevel; 193. otmp->owornmask = (long)MIGR_RANDOM; 194. } 195. seetrap(ttmp); 196. continue; 197. } 198. if (closed_door(rx, ry)) 199. goto nopushmsg; 200. if (boulder_hits_pool(otmp, rx, ry, TRUE)) 201. continue; 202. /* 203. * Re-link at top of fobj chain so that pile order is preserved 204. * when level is restored. 205. */ 206. if (otmp != fobj) { 207. remove_object(otmp); 208. place_object(otmp, otmp->ox, otmp->oy); 209. } 210. 211. { 212. #ifdef LINT /* static long lastmovetime; */ 213. long lastmovetime; 214. lastmovetime = 0; 215. #else 216. static NEARDATA long lastmovetime; 217. #endif 218. /* note: this var contains garbage initially and 219. after a restore */ 220. #ifdef STEED 221. if (!u.usteed) { 222. #endif 223. if (moves > lastmovetime+2 || moves < lastmovetime) 224. pline("With %s effort you move %s.", 225. throws_rocks(youmonst.data) ? "little" : "great", 226. the(xname(otmp))); 227. exercise(A_STR, TRUE); 228. #ifdef STEED 229. } else 230. pline("%s moves %s.", Monnam(u.usteed), the(xname(otmp))); 231. #endif 232. lastmovetime = moves; 233. } 234. 235. /* Move the boulder *after* the message. */ 236. if (glyph_is_invisible(levl[rx][ry].glyph)) 237. unmap_object(rx, ry); 238. movobj(otmp, rx, ry); /* does newsym(rx,ry) */ 239. if (Blind) { 240. feel_location(rx,ry); 241. feel_location(sx, sy); 242. } else { 243. newsym(sx, sy); 244. } 245. } else { 246. nopushmsg: 247. #ifdef STEED 248. if (u.usteed) 249. pline("%s tries to move %s, but cannot.", 250. Monnam(u.usteed), the(xname(otmp))); 251. else 252. #endif 253. You("try to move %s, but in vain.", the(xname(otmp))); 254. if (Blind) feel_location(sx, sy); 255. cannot_push: 256. if (throws_rocks(youmonst.data)) { 257. #ifdef STEED 258. if (u.usteed && P_SKILL(P_RIDING) < P_BASIC) 259. You("aren't skilled enough to %s %s from %s.", 260. flags.pickup ? "pick up" : "push aside", 261. the(xname(otmp)), mon_nam(u.usteed)); 262. else 263. #endif 264. pline("However, you can easily %s.", 265. flags.pickup ? "pick it up" : "push it aside"); 266. break; 267. } 268. 269. if ( 270. #ifdef STEED 271. !u.usteed && 272. #endif 273. (((!invent || inv_weight() <= -850) && 274. (!u.dx || !u.dy || (IS_ROCK(levl[u.ux][sy].typ) 275. && IS_ROCK(levl[sx][u.uy].typ)))) 276. || verysmall(youmonst.data))) { 277. pline("However, you can squeeze yourself into a small opening."); 278. break; 279. } else 280. return (-1); 281. } 282. } 283. return (0); 284. } 285. 286. /* 287. * still_chewing() 288. * 289. * Chew on a wall, door, or boulder. Returns TRUE if still eating, FALSE 290. * when done. 291. */ 292. STATIC_OVL int 293. still_chewing(x,y) 294. xchar x, y; 295. { 296. struct rm *lev = &levl[x][y]; 297. struct obj *boulder = sobj_at(BOULDER,x,y); 298. const char *digtxt = (char *)0, *dmgtxt = (char *)0; 299. 300. if (digging.down) /* not continuing previous dig (w/ pick-axe) */ 301. (void) memset((genericptr_t)&digging, 0, sizeof digging); 302. 303. if (!boulder && IS_ROCK(lev->typ) && !may_dig(x,y)) { 304. You("hurt your teeth on the hard stone."); 305. nomul(0); 306. return 1; 307. } else if (digging.pos.x != x || digging.pos.y != y || 308. !on_level(&digging.level, &u.uz)) { 309. digging.down = FALSE; 310. digging.chew = TRUE; 311. digging.pos.x = x; 312. digging.pos.y = y; 313. assign_level(&digging.level, &u.uz); 314. /* solid rock takes more work & time to dig through */ 315. digging.effort = (IS_ROCK(lev->typ) ? 30 : 60) + u.udaminc; 316. You("start chewing %s %s.", 317. boulder ? "on a" : "a hole in the", 318. boulder ? "boulder" : IS_ROCK(lev->typ) ? "rock" : "door"); 319. return 1; 320. } else if ((digging.effort += (30 + u.udaminc)) <= 100) { 321. if (flags.verbose) 322. You("%s chewing on the %s.", 323. digging.chew ? "continue" : "begin", 324. boulder ? "boulder" : IS_ROCK(lev->typ) ? "rock" : "door"); 325. digging.chew = TRUE; 326. return 1; 327. } 328. 329. if (boulder) { 330. delobj(boulder); /* boulder goes bye-bye */ 331. You("eat the boulder."); /* yum */ 332. 333. /* 334. * The location could still block because of 335. * 1. More than one boulder 336. * 2. Boulder stuck in a wall/stone/door. 337. * 338. * [perhaps use does_block() below (from vision.c)] 339. */ 340. if (IS_ROCK(lev->typ) || closed_door(x,y) || sobj_at(BOULDER,x,y)) { 341. block_point(x,y); /* delobj will unblock the point */ 342. /* reset dig state */ 343. (void) memset((genericptr_t)&digging, 0, sizeof digging); 344. return 1; 345. } 346. 347. } else if (IS_WALL(lev->typ)) { 348. if (*in_rooms(x, y, SHOPBASE)) { 349. add_damage(x, y, 10L * ACURRSTR); 350. dmgtxt = "damage"; 351. } 352. digtxt = "chew a hole in the wall."; 353. if (level.flags.is_maze_lev) { 354. lev->typ = ROOM; 355. } else if (level.flags.is_cavernous_lev) { 356. lev->typ = CORR; 357. } else { 358. lev->typ = DOOR; 359. lev->doormask = D_NODOOR; 360. } 361. } else if (lev->typ == SDOOR) { 362. if (lev->doormask & D_TRAPPED) { 363. lev->doormask = D_NODOOR; 364. b_trapped("secret door", 0); 365. } else { 366. digtxt = "chew through the secret door."; 367. lev->doormask = D_BROKEN; 368. } 369. lev->typ = DOOR; 370. 371. } else if (IS_DOOR(lev->typ)) { 372. if (*in_rooms(x, y, SHOPBASE)) { 373. add_damage(x, y, 400L); 374. dmgtxt = "break"; 375. } 376. if (lev->doormask & D_TRAPPED) { 377. lev->doormask = D_NODOOR; 378. b_trapped("door", 0); 379. } else { 380. digtxt = "chew through the door."; 381. lev->doormask = D_BROKEN; 382. } 383. 384. } else { /* STONE or SCORR */ 385. digtxt = "chew a passage through the rock."; 386. lev->typ = CORR; 387. } 388. 389. unblock_point(x, y); /* vision */ 390. newsym(x, y); 391. if (digtxt) You(digtxt); /* after newsym */ 392. if (dmgtxt) pay_for_damage(dmgtxt); 393. (void) memset((genericptr_t)&digging, 0, sizeof digging); 394. return 0; 395. } 396. 397. #endif /* OVL2 */ 398. #ifdef OVLB 399. 400. void 401. movobj(obj, ox, oy) 402. register struct obj *obj; 403. register xchar ox, oy; 404. { 405. /* optimize by leaving on the fobj chain? */ 406. remove_object(obj); 407. newsym(obj->ox, obj->oy); 408. place_object(obj, ox, oy); 409. newsym(ox, oy); 410. } 411. 412. #ifdef SINKS 413. static NEARDATA const char fell_on_sink[] = "fell onto a sink"; 414. 415. STATIC_OVL void 416. dosinkfall() 417. { 418. register struct obj *obj; 419. 420. if (is_floater(youmonst.data) || (HLevitation & FROMOUTSIDE)) { 421. You("wobble unsteadily for a moment."); 422. } else { 423. You("crash to the floor!"); 424. losehp((rn1(10, 20 - (int)ACURR(A_CON))), 425. fell_on_sink, NO_KILLER_PREFIX); 426. exercise(A_DEX, FALSE); 427. for(obj = level.objects[u.ux][u.uy]; obj; obj = obj->nexthere) 428. if(obj->oclass == WEAPON_CLASS) { 429. You("fell on %s.",doname(obj)); 430. losehp(rnd(3), fell_on_sink, NO_KILLER_PREFIX); 431. exercise(A_CON, FALSE); 432. } 433. } 434. 435. ELevitation &= ~W_ARTI; 436. HLevitation &= ~(I_SPECIAL|TIMEOUT); 437. HLevitation++; 438. if(uleft && uleft->otyp == RIN_LEVITATION) { 439. obj = uleft; 440. Ring_off(obj); 441. off_msg(obj); 442. } 443. if(uright && uright->otyp == RIN_LEVITATION) { 444. obj = uright; 445. Ring_off(obj); 446. off_msg(obj); 447. } 448. if(uarmf && uarmf->otyp == LEVITATION_BOOTS) { 449. obj = uarmf; 450. (void)Boots_off(); 451. off_msg(obj); 452. } 453. HLevitation--; 454. } 455. #endif 456. 457. boolean 458. may_dig(x,y) 459. register xchar x,y; 460. /* intended to be called only on ROCKs */ 461. { 462. return (boolean)(!(IS_STWALL(levl[x][y].typ) && 463. (levl[x][y].wall_info & W_NONDIGGABLE))); 464. } 465. 466. boolean 467. may_passwall(x,y) 468. register xchar x,y; 469. { 470. return (boolean)(!(IS_STWALL(levl[x][y].typ) && 471. (levl[x][y].wall_info & W_NONPASSWALL))); 472. } 473. 474. #endif /* OVLB */ 475. #ifdef OVL1 476. 477. boolean 478. bad_rock(mdat,x,y) 479. struct permonst *mdat; 480. register xchar x,y; 481. { 482. return((boolean) ((In_sokoban(&u.uz) && sobj_at(BOULDER,x,y)) || 483. (IS_ROCK(levl[x][y].typ) 484. && (!tunnels(mdat) || needspick(mdat) || !may_dig(x,y)) 485. && !(passes_walls(mdat) && may_passwall(x,y))))); 486. } 487. 488. boolean 489. invocation_pos(x, y) 490. xchar x, y; 491. { 492. return((boolean)(Invocation_lev(&u.uz) && x == inv_pos.x && y == inv_pos.y)); 493. } 494. 495. #endif /* OVL1 */ 496. #ifdef OVL3 497. 498. void 499. domove() 500. { 501. register struct monst *mtmp; 502. register struct rm *tmpr,*ust; 503. register xchar x,y; 504. struct trap *trap; 505. int wtcap; 506. boolean on_ice; 507. xchar chainx, chainy, ballx, bally; /* ball&chain new positions */ 508. int bc_control; /* control for ball&chain */ 509. boolean cause_delay = FALSE; /* dragging ball will skip a move */ 510. 511. u_wipe_engr(rnd(5)); 512. 513. if(((wtcap = near_capacity()) >= OVERLOADED 514. || (wtcap > SLT_ENCUMBER && 515. (Upolyd ? (u.mh < 5 && u.mh != u.mhmax) 516. : (u.uhp < 10 && u.uhp != u.uhpmax)))) 517. && !Is_airlevel(&u.uz)) { 518. if(wtcap < OVERLOADED) { 519. You("don't have enough stamina to move."); 520. exercise(A_CON, FALSE); 521. } else 522. You("collapse under your load."); 523. nomul(0); 524. return; 525. } 526. if(u.uswallow) { 527. u.dx = u.dy = 0; 528. u.ux = x = u.ustuck->mx; 529. u.uy = y = u.ustuck->my; 530. mtmp = u.ustuck; 531. } else { 532. if (Is_airlevel(&u.uz) && rn2(4) && 533. !Levitation && !Flying) { 534. switch(rn2(3)) { 535. case 0: 536. You("tumble in place."); 537. exercise(A_DEX, FALSE); 538. break; 539. case 1: 540. You_cant("control your movements very well."); break; 541. case 2: 542. pline("It's hard to walk in thin air."); 543. exercise(A_DEX, TRUE); 544. break; 545. } 546. return; 547. } 548. 549. /* check slippery ice */ 550. on_ice = !Levitation && is_ice(u.ux, u.uy); 551. if (on_ice) { 552. static int skates = 0; 553. if (!skates) skates = find_skates(); 554. if ((uarmf && uarmf->otyp == skates) 555. || resists_cold(&youmonst) || Flying 556. || is_floater(youmonst.data) || is_clinger(youmonst.data) 557. || is_whirly(youmonst.data)) 558. on_ice = FALSE; 559. else if (!rn2(Cold_resistance ? 3 : 2)) { 560. HFumbling |= FROMOUTSIDE; 561. HFumbling &= ~TIMEOUT; 562. HFumbling += 1; /* slip on next move */ 563. } 564. } 565. if (!on_ice && (HFumbling & FROMOUTSIDE)) 566. HFumbling &= ~FROMOUTSIDE; 567. 568. x = u.ux + u.dx; 569. y = u.uy + u.dy; 570. if(Stunned || (Confusion && !rn2(5))) { 571. register int tries = 0; 572. 573. do { 574. if(tries++ > 50) { 575. nomul(0); 576. return; 577. } 578. confdir(); 579. x = u.ux + u.dx; 580. y = u.uy + u.dy; 581. } while(!isok(x, y) || bad_rock(youmonst.data, x, y)); 582. } 583. /* turbulence might alter your actual destination */ 584. if (u.uinwater) { 585. water_friction(); 586. if (!u.dx && !u.dy) { 587. nomul(0); 588. return; 589. } 590. x = u.ux + u.dx; 591. y = u.uy + u.dy; 592. } 593. if(!isok(x, y)) { 594. nomul(0); 595. return; 596. } 597. if((trap = t_at(x, y)) && trap->tseen) { 598. if(flags.run >= 2) { 599. nomul(0); 600. flags.move = 0; 601. return; 602. } else 603. nomul(0); 604. } 605. 606. if (u.ustuck && (x != u.ustuck->mx || y != u.ustuck->my)) { 607. if (distu(u.ustuck->mx, u.ustuck->my) > 2) { 608. /* perhaps it fled (or was teleported or ... ) */ 609. u.ustuck = 0; 610. } else if (sticks(youmonst.data)) { 611. /* When polymorphed into a sticking monster, 612. * u.ustuck means it's stuck to you, not you to it. 613. */ 614. You("release %s.", mon_nam(u.ustuck)); 615. u.ustuck = 0; 616. } else { 617. /* If holder is asleep or paralyzed: 618. * 37.5% chance of getting away, 619. * 12.5% chance of waking/releasing it; 620. * otherwise: 621. * 7.5% chance of getting away. 622. * [strength ought to be a factor] 623. */ 624. switch (rn2(!u.ustuck->mcanmove ? 8 : 40)) { 625. case 0: case 1: case 2: 626. You("pull free from %s.", mon_nam(u.ustuck)); 627. u.ustuck = 0; 628. break; 629. case 3: 630. if (!u.ustuck->mcanmove) { 631. /* it's free to move on next turn */ 632. u.ustuck->mfrozen = 1; 633. u.ustuck->msleeping = 0; 634. } 635. /*FALLTHRU*/ 636. default: 637. You("cannot escape from %s!", mon_nam(u.ustuck)); 638. nomul(0); 639. return; 640. } 641. } 642. } 643. 644. mtmp = m_at(x,y); 645. if (mtmp) { 646. /* Don't attack if you're running, and can see it */ 647. /* We should never get here if forcefight */ 648. if (flags.run && 649. ((!Blind && mon_visible(mtmp) && 650. ((mtmp->m_ap_type != M_AP_FURNITURE && 651. mtmp->m_ap_type != M_AP_OBJECT) || 652. Protection_from_shape_changers)) || 653. sensemon(mtmp))) { 654. nomul(0); 655. flags.move = 0; 656. return; 657. } 658. } 659. } 660. 661. u.ux0 = u.ux; 662. u.uy0 = u.uy; 663. bhitpos.x = x; 664. bhitpos.y = y; 665. tmpr = &levl[x][y]; 666. 667. /* attack monster */ 668. if(mtmp) { 669. nomul(0); 670. /* only attack if we know it's there */ 671. /* or if we used the 'F' command to fight blindly */ 672. /* or if it hides_under, in which case we call attack() to print 673. * the Wait! message. 674. * This is different from ceiling hiders, who aren't handled in 675. * attack(). 676. */ 677. 678. /* If they used a 'm' command, trying to move onto a monster 679. * prints the below message and wastes a turn. The exception is 680. * if the monster is unseen and the player doesn't remember an 681. * invisible monster--then, we fall through to attack() and 682. * attack_check(), which still wastes a turn, but prints a 683. * different message and makes the player remember the monster. */ 684. if(flags.nopick && 685. (canspotmon(mtmp) || glyph_is_invisible(levl[x][y].glyph))){ 686. if(mtmp->m_ap_type && !Protection_from_shape_changers 687. && !sensemon(mtmp)) 688. stumble_onto_mimic(mtmp); 689. else 690. You("move right into %s.", mon_nam(mtmp)); 691. return; 692. } 693. if(flags.forcefight || !mtmp->mundetected || sensemon(mtmp) || 694. ((hides_under(mtmp->data) || mtmp->data->mlet == S_EEL) && 695. !is_safepet(mtmp))){ 696. gethungry(); 697. if(wtcap >= HVY_ENCUMBER && moves%3) { 698. if (Upolyd && u.mh > 1) { 699. u.mh--; 700. } else if (!Upolyd && u.uhp > 1) { 701. u.uhp--; 702. } else { 703. You("pass out from exertion!"); 704. exercise(A_CON, FALSE); 705. fall_asleep(-10, FALSE); 706. } 707. } 708. if(multi < 0) return; /* we just fainted */ 709. 710. /* try to attack; note that it might evade */ 711. /* also, we don't attack tame when _safepet_ */ 712. if(attack(mtmp)) return; 713. } 714. } 715. 716. /* specifying 'F' with no monster wastes a turn */ 717. if (flags.forcefight || 718. /* remembered an 'I' && didn't use a move command */ 719. (glyph_is_invisible(levl[x][y].glyph) && !flags.nopick)) { 720. You("attack %s.", Underwater ? "empty water" : "thin air"); 721. unmap_object(x, y); /* known empty -- remove 'I' if present */ 722. newsym(x, y); 723. nomul(0); 724. return; 725. } 726. if (glyph_is_invisible(levl[x][y].glyph)) { 727. unmap_object(x, y); 728. newsym(x, y); 729. } 730. 731. /* not attacking an animal, so we try to move */ 732. #ifdef STEED 733. if (u.usteed && !u.usteed->mcanmove && (u.dx || u.dy)) { 734. pline("%s won't move!", Monnam(u.usteed)); 735. nomul(0); 736. return; 737. } else 738. #endif 739. if(!youmonst.data->mmove) { 740. You("are rooted %s.", 741. Levitation || Is_airlevel(&u.uz) || Is_waterlevel(&u.uz) ? 742. "in place" : "to the ground"); 743. nomul(0); 744. return; 745. } 746. if(u.utrap) { 747. if(u.utraptype == TT_PIT) { 748. if (!rn2(2) && sobj_at(BOULDER, u.ux, u.uy)) { 749. Your("%s gets stuck in a crevice.", body_part(LEG)); 750. display_nhwindow(WIN_MESSAGE, FALSE); 751. clear_nhwindow(WIN_MESSAGE); 752. You("free your %s.", body_part(LEG)); 753. } else if (!(--u.utrap)) { 754. You("crawl to the edge of the pit."); 755. fill_pit(u.ux, u.uy); 756. vision_full_recalc = 1; /* vision limits change */ 757. } else if (flags.verbose) 758. Norep( (Hallucination && !rn2(5)) ? 759. "You've fallen, and you can't get up." : 760. "You are still in a pit." ); 761. } else if (u.utraptype == TT_LAVA) { 762. if(flags.verbose) 763. Norep("You are stuck in the lava."); 764. if(!is_lava(x,y)) { 765. u.utrap--; 766. if((u.utrap & 0xff) == 0) { 767. You("pull yourself to the edge of the lava."); 768. u.utrap = 0; 769. } 770. } 771. u.umoved = TRUE; 772. } else if (u.utraptype == TT_WEB) { 773. if(uwep && uwep->oartifact == ART_STING) { 774. u.utrap = 0; 775. pline("Sting cuts through the web!"); 776. return; 777. } 778. if(--u.utrap) { 779. if(flags.verbose) 780. Norep("You are stuck to the web."); 781. } else You("disentangle yourself."); 782. } else if (u.utraptype == TT_INFLOOR) { 783. if(--u.utrap) { 784. if(flags.verbose) 785. Norep("You are stuck in the floor."); 786. } else You("finally wiggle free."); 787. } else { 788. if(flags.verbose) 789. Norep("You are caught in a bear trap."); 790. if((u.dx && u.dy) || !rn2(5)) u.utrap--; 791. } 792. return; 793. } 794. 795. 796. /* 797. * Check for physical obstacles. First, the place we are going. 798. */ 799. if (IS_ROCK(tmpr->typ) || tmpr->typ == IRONBARS) { 800. if (Blind) feel_location(x,y); 801. if (Passes_walls && may_passwall(x,y)) { 802. ; /* do nothing */ 803. } else if (tunnels(youmonst.data) && !needspick(youmonst.data)) { 804. /* Eat the rock. */ 805. if (still_chewing(x,y)) return; 806. } else { 807. if (Is_stronghold(&u.uz) && is_db_wall(x,y)) 808. pline_The("drawbridge is up!"); 809. flags.move = 0; 810. nomul(0); 811. return; 812. } 813. } else if (IS_DOOR(tmpr->typ)) { 814. if (closed_door(x,y)) { 815. if (Blind) feel_location(x,y); 816. if (Passes_walls) 817. ; /* do nothing */ 818. else if (can_ooze(&youmonst)) 819. You("ooze under the door."); 820. else if (tunnels(youmonst.data) && !needspick(youmonst.data)) { 821. /* Eat the door. */ 822. if (still_chewing(x,y)) return; 823. } else { 824. flags.move = 0; 825. if (amorphous(youmonst.data)) 826. You("try to ooze under the door, but can't squeeze your possessions through."); 827. else if (x == u.ux || y == u.uy) { 828. if (Blind || Stunned || ACURR(A_DEX) < 10 || Fumbling) { 829. pline("Ouch! You bump into a door."); 830. exercise(A_DEX, FALSE); 831. } else pline("That door is closed."); 832. } 833. nomul(0); 834. return; 835. } 836. } else if (u.dx && u.dy && !Passes_walls 837. && ((tmpr->doormask & ~D_BROKEN) 838. #ifdef REINCARNATION 839. || Is_rogue_level(&u.uz) 840. #endif 841. || block_door(x,y))) { 842. /* Diagonal moves into a door are not allowed. */ 843. if (Blind) feel_location(x,y); /* ?? */ 844. flags.move = 0; 845. nomul(0); 846. return; 847. } 848. } 849. if (u.dx && u.dy 850. && bad_rock(youmonst.data,u.ux,y) && bad_rock(youmonst.data,x,u.uy)) { 851. /* Move at a diagonal. */ 852. if (In_sokoban(&u.uz)) { 853. You("cannot pass that way."); 854. nomul(0); 855. return; 856. } 857. if (bigmonst(youmonst.data)) { 858. Your("body is too large to fit through."); 859. nomul(0); 860. return; 861. } 862. if (invent && (inv_weight() + weight_cap() > 600)) { 863. You("are carrying too much to get through."); 864. nomul(0); 865. return; 866. } 867. } 868. 869. ust = &levl[u.ux][u.uy]; 870. 871. /* Now see if other things block our way . . */ 872. if (u.dx && u.dy && !Passes_walls 873. && (IS_DOOR(ust->typ) && ((ust->doormask & ~D_BROKEN) 874. #ifdef REINCARNATION 875. || Is_rogue_level(&u.uz) 876. #endif 877. || block_entry(x, y)) 878. )) { 879. /* Can't move at a diagonal out of a doorway with door. */ 880. flags.move = 0; 881. nomul(0); 882. return; 883. } 884. 885. if (sobj_at(BOULDER,x,y) && (In_sokoban(&u.uz) || !Passes_walls)) { 886. if (!(Blind || Hallucination) && (flags.run >= 2)) { 887. nomul(0); 888. flags.move = 0; 889. return; 890. } 891. /* tunneling monsters will chew before pushing */ 892. if (tunnels(youmonst.data) && !needspick(youmonst.data)) { 893. if (still_chewing(x,y)) return; 894. } else 895. if (moverock() < 0) return; 896. } 897. 898. /* OK, it is a legal place to move. */ 899. 900. /* Move ball and chain. */ 901. if (Punished) 902. if (!drag_ball(x,y, &bc_control, &ballx, &bally, &chainx, &chainy, 903. &cause_delay)) 904. return; 905. 906. /* Check regions entering/leaving */ 907. if (!in_out_region(x,y)) 908. return; 909. 910. /* now move the hero */ 911. mtmp = m_at(x, y); 912. u.ux += u.dx; 913. u.uy += u.dy; 914. #ifdef STEED 915. /* Move your steed, too */ 916. if (u.usteed) { 917. u.usteed->mx = u.ux; 918. u.usteed->my = u.uy; 919. exercise_steed(); 920. } 921. #endif 922. 923. /* 924. * If safepet at destination then move the pet to the hero's 925. * previous location using the same conditions as in attack(). 926. * there are special extenuating circumstances: 927. * (1) if the pet dies then your god angers, 928. * (2) if the pet gets trapped then your god may disapprove, 929. * (3) if the pet was already trapped and you attempt to free it 930. * not only do you encounter the trap but you may frighten your 931. * pet causing it to go wild! moral: don't abuse this privilege. 932. * 933. * Ceiling-hiding pets are skipped by this section of code, to 934. * be caught by the normal falling-monster code. 935. */ 936. if (is_safepet(mtmp) && !(is_hider(mtmp->data) && mtmp->mundetected)) { 937. /* if trapped, there's a chance the pet goes wild */ 938. if (mtmp->mtrapped) { 939. if (!rn2(mtmp->mtame)) { 940. mtmp->mtame = mtmp->mpeaceful = mtmp->msleeping = 0; 941. growl(mtmp); 942. } else { 943. yelp(mtmp); 944. } 945. } 946. mtmp->mundetected = 0; 947. if (mtmp->m_ap_type) seemimic(mtmp); 948. else if (!mtmp->mtame) newsym(mtmp->mx, mtmp->my); 949. 950. if (mtmp->mtrapped && 951. (trap = t_at(mtmp->mx, mtmp->my)) != 0 && 952. (trap->ttyp == PIT || trap->ttyp == SPIKED_PIT) && 953. sobj_at(BOULDER, trap->tx, trap->ty)) { 954. /* can't swap places with pet pinned in a pit by a boulder */ 955. u.ux = u.ux0, u.uy = u.uy0; /* didn't move after all */ 956. } else { 957. mtmp->mtrapped = 0; 958. remove_monster(x, y); 959. place_monster(mtmp, u.ux0, u.uy0); 960. 961. /* check for displacing it into pools and traps */ 962. switch (minwater(mtmp) ? 2 : mintrap(mtmp)) { 963. case 0: 964. You("%s %s.", mtmp->mtame ? "displaced" : "frightened", 965. y_monnam(mtmp)); 966. break; 967. case 1: /* trapped */ 968. case 3: /* changed levels */ 969. /* there's already been a trap message, reinforce it */ 970. abuse_dog(mtmp); 971. adjalign(-3); 972. break; 973. case 2: 974. /* it may have drowned or died. that's no way to 975. * treat a pet! your god gets angry. 976. */ 977. if (rn2(4)) { 978. You_feel("guilty about losing your pet like this."); 979. u.ugangr++; 980. adjalign(-15); 981. } 982. break; 983. default: 984. pline("that's strange, unknown mintrap result!"); 985. break; 986. } 987. } 988. } 989. 990. reset_occupations(); 991. if (flags.run) { 992. if (IS_DOOR(tmpr->typ) || IS_ROCK(tmpr->typ) || 993. IS_FURNITURE(tmpr->typ)) 994. nomul(0); 995. } 996. 997. if (hides_under(youmonst.data)) 998. u.uundetected = OBJ_AT(u.ux, u.uy); 999. else if (youmonst.data->mlet == S_EEL) 1000. u.uundetected = is_pool(u.ux, u.uy) && !Is_waterlevel(&u.uz); 1001. else if (u.dx || u.dy) 1002. u.uundetected = 0; 1003. 1004. /* 1005. * Mimics (or whatever) become noticeable if they move and are 1006. * imitating something that doesn't move. We could extend this 1007. * to non-moving monsters... 1008. */ 1009. if ((u.dx || u.dy) && (youmonst.m_ap_type == M_AP_OBJECT 1010. || youmonst.m_ap_type == M_AP_FURNITURE)) 1011. youmonst.m_ap_type = M_AP_NOTHING; 1012. 1013. check_leash(u.ux0,u.uy0); 1014. 1015. if(u.ux0 != u.ux || u.uy0 != u.uy) { 1016. u.umoved = TRUE; 1017. /* Clean old position -- vision_recalc() will print our new one. */ 1018. newsym(u.ux0,u.uy0); 1019. /* Since the hero has moved, adjust what can be seen/unseen. */ 1020. vision_recalc(1); /* Do the work now in the recover time. */ 1021. invocation_message(); 1022. } 1023. 1024. if (Punished) /* put back ball and chain */ 1025. move_bc(0,bc_control,ballx,bally,chainx,chainy); 1026. 1027. spoteffects(); 1028. 1029. /* delay next move because of ball dragging */ 1030. /* must come after we finished picking up, in spoteffects() */ 1031. if (cause_delay) { 1032. nomul(-2); 1033. nomovemsg = ""; 1034. } 1035. } 1036. 1037. void 1038. invocation_message() 1039. { 1040. /* a special clue-msg when on the Invocation position */ 1041. if(invocation_pos(u.ux, u.uy) && !On_stairs(u.ux, u.uy)) { 1042. struct obj *otmp = carrying(CANDELABRUM_OF_INVOCATION); 1043. 1044. You_feel("a strange vibration under your %s.", 1045. makeplural(body_part(FOOT))); 1046. if (otmp && otmp->spe == 7 && otmp->lamplit) 1047. pline("%s %s!", The(xname(otmp)), 1048. Blind ? "throbs palpably" : "glows with a strange light"); 1049. } 1050. } 1051. 1052. #endif /* OVL3 */ 1053. #ifdef OVL2 1054. 1055. void 1056. spoteffects() 1057. { 1058. register struct trap *trap; 1059. register struct monst *mtmp; 1060. 1061. if(u.uinwater) { 1062. int was_underwater; 1063. 1064. if (!is_pool(u.ux,u.uy)) { 1065. if (Is_waterlevel(&u.uz)) 1066. You("pop into an air bubble."); 1067. else if (is_lava(u.ux, u.uy)) 1068. You("leave the water..."); /* oops! */ 1069. else 1070. You("are on solid %s again.", 1071. is_ice(u.ux, u.uy) ? "ice" : "land"); 1072. } 1073. else if (Is_waterlevel(&u.uz)) 1074. goto stillinwater; 1075. else if (Levitation) 1076. You("pop out of the water like a cork!"); 1077. else if (Flying) 1078. You("fly out of the water."); 1079. else if (Wwalking) 1080. You("slowly rise above the surface."); 1081. else 1082. goto stillinwater; 1083. was_underwater = Underwater && !Is_waterlevel(&u.uz); 1084. u.uinwater = 0; /* leave the water */ 1085. if (was_underwater) { /* restore vision */ 1086. docrt(); 1087. vision_full_recalc = 1; 1088. } 1089. } 1090. stillinwater:; 1091. if (!Levitation && !u.ustuck && !Flying) { 1092. /* limit recursive calls through teleds() */ 1093. if(is_lava(u.ux,u.uy) && lava_effects()) 1094. return; 1095. if(is_pool(u.ux,u.uy) && !Wwalking && drown()) 1096. return; 1097. } 1098. check_special_room(FALSE); 1099. #ifdef SINKS 1100. if(IS_SINK(levl[u.ux][u.uy].typ) && Levitation) 1101. dosinkfall(); 1102. #endif 1103. if (!in_steed_dismounting) 1104. pickup(1); 1105. if ((trap = t_at(u.ux,u.uy)) != 0) 1106. dotrap(trap); /* fall into pit, arrow trap, etc. */ 1107. if((mtmp = m_at(u.ux, u.uy)) && !u.uswallow) { 1108. mtmp->mundetected = mtmp->msleeping = 0; 1109. switch(mtmp->data->mlet) { 1110. case S_PIERCER: 1111. pline("%s suddenly drops from the %s!", 1112. Amonnam(mtmp), ceiling(u.ux,u.uy)); 1113. if(mtmp->mtame) /* jumps to greet you, not attack */ 1114. ; 1115. else if(uarmh) 1116. pline("Its blow glances off your helmet."); 1117. else if (u.uac + 3 <= rnd(20)) 1118. You("are almost hit by %s!", 1119. x_monnam(mtmp, 2, "falling", 1)); 1120. else { 1121. int dmg; 1122. You("are hit by %s!", 1123. x_monnam(mtmp, 2, "falling", 1)); 1124. dmg = d(4,6); 1125. if(Half_physical_damage) dmg = (dmg+1) / 2; 1126. mdamageu(mtmp, dmg); 1127. } 1128. break; 1129. default: /* monster surprises you. */ 1130. if(mtmp->mtame) 1131. pline("%s jumps near you from the %s.", 1132. Amonnam(mtmp), ceiling(u.ux,u.uy)); 1133. else if(mtmp->mpeaceful) { 1134. You("surprise %s!", 1135. Blind && !sensemon(mtmp) ? 1136. something : a_monnam(mtmp)); 1137. mtmp->mpeaceful = 0; 1138. } else 1139. pline("%s attacks you by surprise!", 1140. Amonnam(mtmp)); 1141. break; 1142. } 1143. mnexto(mtmp); /* have to move the monster */ 1144. } 1145. } 1146. 1147. STATIC_OVL boolean 1148. monstinroom(mdat,roomno) 1149. struct permonst *mdat; 1150. int roomno; 1151. { 1152. register struct monst *mtmp; 1153. 1154. for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) 1155. if(mtmp->data == mdat && 1156. index(in_rooms(mtmp->mx, mtmp->my, 0), roomno + ROOMOFFSET)) 1157. return(TRUE); 1158. return(FALSE); 1159. } 1160. 1161. char * 1162. in_rooms(x, y, typewanted) 1163. register xchar x, y; 1164. register int typewanted; 1165. { 1166. static char buf[5]; 1167. char rno, *ptr = &buf[4]; 1168. int typefound, min_x, min_y, max_x, max_y_offset, step; 1169. register struct rm *lev; 1170. 1171. #define goodtype(rno) (!typewanted || \ 1172. ((typefound = rooms[rno - ROOMOFFSET].rtype) == typewanted) || \ 1173. ((typewanted == SHOPBASE) && (typefound > SHOPBASE))) \ 1174. 1175. switch (rno = levl[x][y].roomno) { 1176. case NO_ROOM: 1177. return(ptr); 1178. case SHARED: 1179. step = 2; 1180. break; 1181. case SHARED_PLUS: 1182. step = 1; 1183. break; 1184. default: /* i.e. a regular room # */ 1185. if (goodtype(rno)) 1186. *(--ptr) = rno; 1187. return(ptr); 1188. } 1189. 1190. min_x = x - 1; 1191. max_x = x + 1; 1192. if (x < 1) 1193. min_x += step; 1194. else 1195. if (x >= COLNO) 1196. max_x -= step; 1197. 1198. min_y = y - 1; 1199. max_y_offset = 2; 1200. if (min_y < 0) { 1201. min_y += step; 1202. max_y_offset -= step; 1203. } else 1204. if ((min_y + max_y_offset) >= ROWNO) 1205. max_y_offset -= step; 1206. 1207. for (x = min_x; x <= max_x; x += step) { 1208. lev = &levl[x][min_y]; 1209. y = 0; 1210. if (((rno = lev[y].roomno) >= ROOMOFFSET) && 1211. !index(ptr, rno) && goodtype(rno)) 1212. *(--ptr) = rno; 1213. y += step; 1214. if (y > max_y_offset) 1215. continue; 1216. if (((rno = lev[y].roomno) >= ROOMOFFSET) && 1217. !index(ptr, rno) && goodtype(rno)) 1218. *(--ptr) = rno; 1219. y += step; 1220. if (y > max_y_offset) 1221. continue; 1222. if (((rno = lev[y].roomno) >= ROOMOFFSET) && 1223. !index(ptr, rno) && goodtype(rno)) 1224. *(--ptr) = rno; 1225. } 1226. return(ptr); 1227. } 1228. 1229. STATIC_OVL void 1230. move_update(newlev) 1231. register boolean newlev; 1232. { 1233. char *ptr1, *ptr2, *ptr3, *ptr4; 1234. 1235. Strcpy(u.urooms0, u.urooms); 1236. Strcpy(u.ushops0, u.ushops); 1237. if (newlev) { 1238. u.urooms[0] = '\0'; 1239. u.uentered[0] = '\0'; 1240. u.ushops[0] = '\0'; 1241. u.ushops_entered[0] = '\0'; 1242. Strcpy(u.ushops_left, u.ushops0); 1243. return; 1244. } 1245. Strcpy(u.urooms, in_rooms(u.ux, u.uy, 0)); 1246. 1247. for (ptr1 = &u.urooms[0], 1248. ptr2 = &u.uentered[0], 1249. ptr3 = &u.ushops[0], 1250. ptr4 = &u.ushops_entered[0]; 1251. *ptr1; ptr1++) { 1252. if (!index(u.urooms0, *ptr1)) 1253. *(ptr2++) = *ptr1; 1254. if (IS_SHOP(*ptr1 - ROOMOFFSET)) { 1255. *(ptr3++) = *ptr1; 1256. if (!index(u.ushops0, *ptr1)) 1257. *(ptr4++) = *ptr1; 1258. } 1259. } 1260. *ptr2 = '\0'; 1261. *ptr3 = '\0'; 1262. *ptr4 = '\0'; 1263. 1264. /* filter u.ushops0 -> u.ushops_left */ 1265. for (ptr1 = &u.ushops0[0], ptr2 = &u.ushops_left[0]; *ptr1; ptr1++) 1266. if (!index(u.ushops, *ptr1)) 1267. *(ptr2++) = *ptr1; 1268. *ptr2 = '\0'; 1269. } 1270. 1271. void 1272. check_special_room(newlev) 1273. register boolean newlev; 1274. { 1275. register struct monst *mtmp; 1276. char *ptr; 1277. 1278. move_update(newlev); 1279. 1280. if (*u.ushops0) 1281. u_left_shop(u.ushops_left, newlev); 1282. 1283. if (!*u.uentered && !*u.ushops_entered) /* implied by newlev */ 1284. return; /* no entrance messages necessary */ 1285. 1286. /* Did we just enter a shop? */ 1287. if (*u.ushops_entered) 1288. u_entered_shop(u.ushops_entered); 1289. 1290. for (ptr = &u.uentered[0]; *ptr; ptr++) { 1291. register int roomno = *ptr - ROOMOFFSET, rt = rooms[roomno].rtype; 1292. 1293. /* Did we just enter some other special room? */ 1294. /* vault.c insists that a vault remain a VAULT, 1295. * and temples should remain TEMPLEs, 1296. * but everything else gives a message only the first time */ 1297. switch (rt) { 1298. case ZOO: 1299. pline("Welcome to David's treasure zoo!"); 1300. break; 1301. case SWAMP: 1302. pline("It %s rather %s down here.", 1303. Blind ? "feels" : "looks", 1304. Blind ? "humid" : "muddy"); 1305. break; 1306. case COURT: 1307. You("enter an opulent throne room!"); 1308. break; 1309. case LEPREHALL: 1310. You("enter a leprechaun hall!"); 1311. break; 1312. case MORGUE: 1313. if(midnight()) { 1314. const char *run = locomotion(youmonst.data, "Run"); 1315. pline("%s away! %s away!", run, run); 1316. } else 1317. You("have an uncanny feeling..."); 1318. break; 1319. case BEEHIVE: 1320. You("enter a giant beehive!"); 1321. break; 1322. case COCKNEST: 1323. You("enter a disgusting nest!"); 1324. break; 1325. case ANTHOLE: 1326. You("enter an anthole!"); 1327. break; 1328. case BARRACKS: 1329. if(monstinroom(&mons[PM_SOLDIER], roomno) || 1330. monstinroom(&mons[PM_SERGEANT], roomno) || 1331. monstinroom(&mons[PM_LIEUTENANT], roomno) || 1332. monstinroom(&mons[PM_CAPTAIN], roomno)) 1333. You("enter a military barracks!"); 1334. else 1335. You("enter an abandoned barracks."); 1336. break; 1337. case DELPHI: 1338. if(monstinroom(&mons[PM_ORACLE], roomno)) 1339. verbalize("%s, %s, welcome to Delphi!", Hello(), plname); 1340. break; 1341. case TEMPLE: 1342. intemple(roomno + ROOMOFFSET); 1343. /* fall through */ 1344. default: 1345. rt = 0; 1346. } 1347. 1348. if (rt != 0) { 1349. rooms[roomno].rtype = OROOM; 1350. if (!search_special(rt)) { 1351. /* No more room of that type */ 1352. switch(rt) { 1353. case COURT: 1354. level.flags.has_court = 0; 1355. break; 1356. case SWAMP: 1357. level.flags.has_swamp = 0; 1358. break; 1359. case MORGUE: 1360. level.flags.has_morgue = 0; 1361. break; 1362. case ZOO: 1363. level.flags.has_zoo = 0; 1364. break; 1365. case BARRACKS: 1366. level.flags.has_barracks = 0; 1367. break; 1368. case TEMPLE: 1369. level.flags.has_temple = 0; 1370. break; 1371. case BEEHIVE: 1372. level.flags.has_beehive = 0; 1373. break; 1374. } 1375. } 1376. if (rt == COURT || rt == SWAMP || rt == MORGUE || rt == ZOO) 1377. for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) 1378. if (!Stealth && !rn2(3)) mtmp->msleeping = 0; 1379. } 1380. } 1381. 1382. return; 1383. } 1384. 1385. #endif /* OVL2 */ 1386. #ifdef OVLB 1387. 1388. int 1389. dopickup() 1390. { 1391. int count; 1392. /* awful kludge to work around parse()'s pre-decrement */ 1393. count = (multi || (save_cm && *save_cm == ',')) ? multi + 1 : 0; 1394. multi = 0; /* always reset */ 1395. /* uswallow case added by GAN 01/29/87 */ 1396. if(u.uswallow) { 1397. if (is_animal(u.ustuck->data)) { 1398. You("pick up %s tongue.", s_suffix(mon_nam(u.ustuck))); 1399. pline("But it's kind of slimy, so you drop it."); 1400. } else 1401. You("don't %s anything in here to pick up.", 1402. Blind ? "feel" : "see"); 1403. return(1); 1404. } 1405. if(is_pool(u.ux, u.uy)) { 1406. if (Wwalking || is_floater(youmonst.data) || is_clinger(youmonst.data) 1407. || (Flying && !Breathless)) { 1408. You("cannot dive into the water to pick things up."); 1409. return(1); 1410. } else if (!Underwater) { 1411. You_cant("even see the bottom, let alone pick up %s.", 1412. something); 1413. return(1); 1414. } 1415. } 1416. if(!OBJ_AT(u.ux, u.uy)) { 1417. pline("There is nothing here to pick up."); 1418. return(0); 1419. } 1420. if (!can_reach_floor()) { 1421. #ifdef STEED 1422. if (u.usteed && P_SKILL(P_RIDING) < P_BASIC) 1423. You("aren't skilled enough to reach from %s.", 1424. mon_nam(u.usteed)); 1425. else 1426. #endif 1427. You("cannot reach the %s.", surface(u.ux,u.uy)); 1428. return(1); 1429. } 1430. pickup(-count); 1431. return(1); 1432. } 1433. 1434. #endif /* OVLB */ 1435. #ifdef OVL2 1436. 1437. /* stop running if we see something interesting */ 1438. /* turn around a corner if that is the only way we can proceed */ 1439. /* do not turn left or right twice */ 1440. void 1441. lookaround() 1442. { 1443. register int x, y, i, x0 = 0, y0 = 0, m0 = 1, i0 = 9; 1444. register int corrct = 0, noturn = 0; 1445. register struct monst *mtmp; 1446. register struct trap *trap; 1447. 1448. /* Grid bugs stop if trying to move diagonal, even if blind. Maybe */ 1449. /* they polymorphed while in the middle of a long move. */ 1450. if (u.umonnum == PM_GRID_BUG && u.dx && u.dy) { 1451. nomul(0); 1452. return; 1453. } 1454. 1455. if(Blind || flags.run == 0) return; 1456. for(x = u.ux-1; x <= u.ux+1; x++) for(y = u.uy-1; y <= u.uy+1; y++) { 1457. if(!isok(x,y)) continue; 1458. 1459. if(u.umonnum == PM_GRID_BUG && x != u.ux && y != u.uy) continue; 1460. 1461. if(x == u.ux && y == u.uy) continue; 1462. 1463. if((mtmp = m_at(x,y)) && 1464. mtmp->m_ap_type != M_AP_FURNITURE && 1465. mtmp->m_ap_type != M_AP_OBJECT && 1466. (!mtmp->minvis || See_invisible) && !mtmp->mundetected) { 1467. if((flags.run != 1 && !mtmp->mtame) 1468. || (x == u.ux+u.dx && y == u.uy+u.dy)) 1469. goto stop; 1470. } 1471. 1472. if (levl[x][y].typ == STONE) continue; 1473. if (x == u.ux-u.dx && y == u.uy-u.dy) continue; 1474. 1475. if (IS_ROCK(levl[x][y].typ) || (levl[x][y].typ == ROOM) || 1476. IS_AIR(levl[x][y].typ)) 1477. continue; 1478. else if (closed_door(x,y)) { 1479. if(x != u.ux && y != u.uy) continue; 1480. if(flags.run != 1) goto stop; 1481. goto bcorr; 1482. } else if (levl[x][y].typ == CORR) { 1483. bcorr: 1484. if(levl[u.ux][u.uy].typ != ROOM) { 1485. if(flags.run == 1 || flags.run == 3) { 1486. i = dist2(x,y,u.ux+u.dx,u.uy+u.dy); 1487. if(i > 2) continue; 1488. if(corrct == 1 && dist2(x,y,x0,y0) != 1) 1489. noturn = 1; 1490. if(i < i0) { 1491. i0 = i; 1492. x0 = x; 1493. y0 = y; 1494. m0 = mtmp ? 1 : 0; 1495. } 1496. } 1497. corrct++; 1498. } 1499. continue; 1500. } else if ((trap = t_at(x,y)) && trap->tseen) { 1501. if(flags.run == 1) goto bcorr; /* if you must */ 1502. if(x == u.ux+u.dx && y == u.uy+u.dy) goto stop; 1503. continue; 1504. } else if (is_pool(x,y) || is_lava(x,y)) { 1505. /* water and lava only stop you if directly in front, and stop 1506. * you even if you are running 1507. */ 1508. if(!Levitation && !Flying && !is_clinger(youmonst.data) && 1509. x == u.ux+u.dx && y == u.uy+u.dy) 1510. /* No Wwalking check; otherwise they'd be able 1511. * to test boots by trying to SHIFT-direction 1512. * into a pool and seeing if the game allowed it 1513. */ 1514. goto stop; 1515. continue; 1516. } else { /* e.g. objects or trap or stairs */ 1517. if(flags.run == 1) goto bcorr; 1518. if(mtmp) continue; /* d */ 1519. if(((x == u.ux - u.dx) && (y != u.uy + u.dy)) || 1520. ((y == u.uy - u.dy) && (x != u.ux + u.dx))) 1521. continue; 1522. } 1523. stop: 1524. nomul(0); 1525. return; 1526. } /* end for loops */ 1527. 1528. if(corrct > 1 && flags.run == 2) goto stop; 1529. if((flags.run == 1 || flags.run == 3) && !noturn && !m0 && i0 && 1530. (corrct == 1 || (corrct == 2 && i0 == 1))) { 1531. /* make sure that we do not turn too far */ 1532. if(i0 == 2) { 1533. if(u.dx == y0-u.uy && u.dy == u.ux-x0) 1534. i = 2; /* straight turn right */ 1535. else 1536. i = -2; /* straight turn left */ 1537. } else if(u.dx && u.dy) { 1538. if((u.dx == u.dy && y0 == u.uy) || (u.dx != u.dy && y0 != u.uy)) 1539. i = -1; /* half turn left */ 1540. else 1541. i = 1; /* half turn right */ 1542. } else { 1543. if((x0-u.ux == y0-u.uy && !u.dy) || (x0-u.ux != y0-u.uy && u.dy)) 1544. i = 1; /* half turn right */ 1545. else 1546. i = -1; /* half turn left */ 1547. } 1548. 1549. i += u.last_str_turn; 1550. if(i <= 2 && i >= -2) { 1551. u.last_str_turn = i; 1552. u.dx = x0-u.ux; 1553. u.dy = y0-u.uy; 1554. } 1555. } 1556. } 1557. 1558. /* something like lookaround, but we are not running */ 1559. /* react only to monsters that might hit us */ 1560. int 1561. monster_nearby() 1562. { 1563. register int x,y; 1564. register struct monst *mtmp; 1565. 1566. /* Also see the similar check in dochugw() in monmove.c */ 1567. for(x = u.ux-1; x <= u.ux+1; x++) 1568. for(y = u.uy-1; y <= u.uy+1; y++) { 1569. if(!isok(x,y)) continue; 1570. if(x == u.ux && y == u.uy) continue; 1571. if((mtmp = m_at(x,y)) && 1572. mtmp->m_ap_type != M_AP_FURNITURE && 1573. mtmp->m_ap_type != M_AP_OBJECT && 1574. (!mtmp->mpeaceful || Hallucination) && 1575. (!is_hider(mtmp->data) || !mtmp->mundetected) && 1576. !noattacks(mtmp->data) && 1577. mtmp->mcanmove && !mtmp->msleeping && /* aplvax!jcn */ 1578. !onscary(u.ux, u.uy, mtmp) && 1579. canspotmon(mtmp)) 1580. return(1); 1581. } 1582. return(0); 1583. } 1584. 1585. void 1586. nomul(nval) 1587. register int nval; 1588. { 1589. if(multi < nval) return; /* This is a bug fix by ab@unido */ 1590. u.uinvulnerable = FALSE; /* Kludge to avoid ctrl-C bug -dlc */ 1591. u.usleep = 0; 1592. multi = nval; 1593. flags.mv = flags.run = 0; 1594. } 1595. 1596. /* called when a non-movement, multi-turn action has completed */ 1597. void unmul(msg_override) 1598. const char *msg_override; 1599. { 1600. multi = 0; /* caller will usually have done this already */ 1601. if (msg_override) nomovemsg = msg_override; 1602. else if (!nomovemsg) nomovemsg = You_can_move_again; 1603. if (*nomovemsg) pline(nomovemsg); 1604. nomovemsg = 0; 1605. u.usleep = 0; 1606. if (afternmv) (*afternmv)(); 1607. afternmv = 0; 1608. } 1609. 1610. #endif /* OVL2 */ 1611. #ifdef OVL1 1612. 1613. void 1614. losehp(n, knam, k_format) 1615. register int n; 1616. register const char *knam; 1617. boolean k_format; 1618. { 1619. if (Upolyd) { 1620. u.mh -= n; 1621. if (u.mhmax < u.mh) u.mhmax = u.mh; 1622. flags.botl = 1; 1623. if (u.mh < 1) rehumanize(); 1624. return; 1625. } 1626. 1627. u.uhp -= n; 1628. if(u.uhp > u.uhpmax) 1629. u.uhpmax = u.uhp; /* perhaps n was negative */ 1630. flags.botl = 1; 1631. if(u.uhp < 1) { 1632. killer_format = k_format; 1633. killer = knam; /* the thing that killed you */ 1634. You("die..."); 1635. done(DIED); 1636. } else if (u.uhp*10 < u.uhpmax && moves-wailmsg > 50 && n > 0) { 1637. wailmsg = moves; 1638. if (Role_if(PM_WIZARD) || Race_if(PM_ELF) || Role_if(PM_VALKYRIE)) { 1639. if (u.uhp == 1) 1640. pline("%s is about to die.", 1641. (Role_if(PM_WIZARD) || Role_if(PM_VALKYRIE)) ? 1642. urole.name.m : "Elf"); 1643. else if (4 <= (!!(HTeleportation & INTRINSIC)) + 1644. (!!(HSee_invisible & INTRINSIC)) + 1645. (!!(HPoison_resistance & INTRINSIC)) + 1646. (!!(HCold_resistance & INTRINSIC)) + 1647. (!!(HShock_resistance & INTRINSIC)) + 1648. (!!(HFire_resistance & INTRINSIC)) + 1649. (!!(HSleep_resistance & INTRINSIC)) + 1650. (!!(HDisint_resistance & INTRINSIC)) + 1651. (!!(HTeleport_control & INTRINSIC)) + 1652. (!!(HStealth & INTRINSIC)) + 1653. (!!(HFast & INTRINSIC)) + 1654. (!!(HInvis & INTRINSIC))) 1655. pline("%s, all your powers will be lost...", 1656. (Role_if(PM_WIZARD) || Role_if(PM_VALKYRIE)) ? 1657. urole.name.m : "Elf"); 1658. else 1659. pline("%s, your life force is running out.", 1660. (Role_if(PM_WIZARD) || Role_if(PM_VALKYRIE)) ? 1661. urole.name.m : "Elf"); 1662. } else { 1663. if(u.uhp == 1) 1664. You_hear("the wailing of the Banshee..."); 1665. else 1666. You_hear("the howling of the CwnAnnwn..."); 1667. } 1668. } 1669. } 1670. 1671. int 1672. weight_cap() 1673. { 1674. register long carrcap; 1675. 1676. carrcap = (((ACURRSTR + ACURR(A_CON))/2)+1)*50; 1677. if (Upolyd) { 1678. /* consistent with can_carry() in mon.c */ 1679. if (youmonst.data->mlet == S_NYMPH) 1680. carrcap = MAX_CARR_CAP; 1681. else if (!youmonst.data->cwt) 1682. carrcap = (carrcap * (long)youmonst.data->msize) / MZ_HUMAN; 1683. else if (!strongmonst(youmonst.data) 1684. || (strongmonst(youmonst.data) && (youmonst.data->cwt > WT_HUMAN))) 1685. carrcap = (carrcap * (long)youmonst.data->cwt / WT_HUMAN); 1686. } 1687. 1688. if (Levitation || Is_airlevel(&u.uz) /* pugh@cornell */ 1689. #ifdef STEED 1690. || (u.usteed && strongmonst(u.usteed->data)) 1691. #endif 1692. ) 1693. carrcap = MAX_CARR_CAP; 1694. else { 1695. if(carrcap > MAX_CARR_CAP) carrcap = MAX_CARR_CAP; 1696. if (!Flying) { 1697. if(EWounded_legs & LEFT_SIDE) carrcap -= 100; 1698. if(EWounded_legs & RIGHT_SIDE) carrcap -= 100; 1699. } 1700. if (carrcap < 0) carrcap = 0; 1701. } 1702. return((int) carrcap); 1703. } 1704. 1705. static int wc; /* current weight_cap(); valid after call to inv_weight() */ 1706. 1707. /* returns how far beyond the normal capacity the player is currently. */ 1708. /* inv_weight() is negative if the player is below normal capacity. */ 1709. int 1710. inv_weight() 1711. { 1712. register struct obj *otmp = invent; 1713. register int wt; 1714. 1715. /* when putting stuff into containers, gold is inserted at the head 1716. of invent for easier manipulation by askchain & co, but it's also 1717. retained in u.ugold in order to keep the status line accurate; we 1718. mustn't add its weight in twice under that circumstance */ 1719. wt = (otmp && otmp->oclass == GOLD_CLASS) ? 0 : 1720. (int)((u.ugold + 50L) / 100L); 1721. 1722. while (otmp) { 1723. if (otmp->otyp != BOULDER || !throws_rocks(youmonst.data)) 1724. wt += otmp->owt; 1725. otmp = otmp->nobj; 1726. } 1727. wc = weight_cap(); 1728. return (wt - wc); 1729. } 1730. 1731. /* 1732. * Returns 0 if below normal capacity, or the number of "capacity units" 1733. * over the normal capacity the player is loaded. Max is 5. 1734. */ 1735. int 1736. calc_capacity(xtra_wt) 1737. int xtra_wt; 1738. { 1739. int cap, wt = inv_weight() + xtra_wt; 1740. 1741. if (wt <= 0) return UNENCUMBERED; 1742. if (wc <= 1) return OVERLOADED; 1743. cap = (wt*2 / wc) + 1; 1744. return min(cap, OVERLOADED); 1745. } 1746. 1747. int 1748. near_capacity() 1749. { 1750. return calc_capacity(0); 1751. } 1752. 1753. int 1754. max_capacity() 1755. { 1756. int wt = inv_weight(); 1757. 1758. return (wt - (2 * wc)); 1759. } 1760. 1761. boolean 1762. check_capacity(str) 1763. const char *str; 1764. { 1765. if(near_capacity() >= EXT_ENCUMBER) { 1766. if(str) 1767. pline(str); 1768. else 1769. You_cant("do that while carrying so much stuff."); 1770. return 1; 1771. } 1772. return 0; 1773. } 1774. 1775. #endif /* OVL1 */ 1776. #ifdef OVLB 1777. 1778. int 1779. inv_cnt() 1780. { 1781. register struct obj *otmp = invent; 1782. register int ct = 0; 1783. 1784. while(otmp){ 1785. ct++; 1786. otmp = otmp->nobj; 1787. } 1788. return(ct); 1789. } 1790. 1791. #endif /* OVLB */ 1792. 1793. /*hack.c*/
|