abstract
| - Below is the full text to hack.c from the source code of SLASH'EM 0.0.7E7F2. To link to a particular line, write [[SLASH'EM 0.0.7E7F2/hack.c#line123]], for example. The latest source code for vanilla NetHack is at Source code. 1. /* SCCS Id: @(#)hack.c 3.4 2003/04/30 */ 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. #ifdef OVL1 8. STATIC_DCL void NDECL(maybe_wail); 9. #endif /*OVL1*/ 10. STATIC_DCL int NDECL(moverock); 11. STATIC_DCL int FDECL(still_chewing,(XCHAR_P,XCHAR_P)); 12. #ifdef SINKS 13. STATIC_DCL void NDECL(dosinkfall); 14. #endif 15. STATIC_DCL boolean FDECL(findtravelpath, (BOOLEAN_P)); 16. STATIC_DCL boolean FDECL(monstinroom, (struct permonst *,int)); 17. 18. STATIC_DCL void FDECL(move_update, (BOOLEAN_P)); 19. 20. #define IS_SHOP(x) (rooms[x].rtype >= SHOPBASE) 21. 22. #ifdef OVL2 23. 24. #ifdef DUNGEON_GROWTH 25. void 26. rndmappos(x,y) /* guaranteed to return a valid coord */ 27. xchar *x; 28. xchar *y; 29. { 30. if (*x >= COLNO) *x = COLNO; 31. else if (*x == -1) *x = rn2(COLNO-1)+1; 32. else if (*x < 1) *x = 1; 33. 34. if (*y >= ROWNO) *y = ROWNO; 35. else if (*y == -1) *y = rn2(ROWNO); 36. else if (*y < 0) *y = 0; 37. } 38. 39. #define HERB_GROWTH_LIMIT 3 /* to limit excessive farming */ 40. 41. static const struct herb_info { 42. int herb; 43. boolean in_water; 44. } herb_info[] = { 45. { SPRIG_OF_WOLFSBANE, FALSE }, 46. { CLOVE_OF_GARLIC, FALSE }, 47. { CARROT, FALSE }, 48. { KELP_FROND, TRUE } 49. }; 50. 51. long 52. count_herbs_at(x,y, watery) 53. xchar x,y; 54. boolean watery; 55. { 56. register int dd; 57. register long count = 0; 58. 59. if (isok(x,y)) { 60. for (dd = 0; dd < SIZE(herb_info); dd++) { 61. if (watery == herb_info[dd].in_water) { 62. register struct obj *otmp = sobj_at(herb_info[dd].herb, x,y); 63. if (otmp) 64. count += otmp->quan; 65. } 66. } 67. } 68. return count; 69. } 70. 71. /* returns TRUE if a herb can grow at (x,y) */ 72. boolean 73. herb_can_grow_at(x,y, watery) 74. xchar x,y; 75. boolean watery; 76. { 77. register struct rm *lev = &levl[x][y]; 78. if (inside_shop(x,y)) return FALSE; 79. if (watery) 80. return (IS_POOL(lev->typ) && 81. ((count_herbs_at(x,y, watery)) < HERB_GROWTH_LIMIT)); 82. return (lev->lit && (lev->typ == ROOM || lev->typ == CORR || 83. (IS_DOOR(lev->typ) && 84. ((lev->doormask == D_NODOOR) || 85. (lev->doormask == D_ISOPEN) || 86. (lev->doormask == D_BROKEN)))) && 87. (count_herbs_at(x,y, watery) < HERB_GROWTH_LIMIT)); 88. } 89. 90. /* grow herbs in water. return true if did something. */ 91. boolean 92. grow_water_herbs(herb, x,y) 93. int herb; 94. xchar x,y; 95. { 96. struct obj *otmp; 97. 98. rndmappos(&x, &y); 99. otmp = sobj_at(herb, x, y); 100. if (otmp && herb_can_grow_at(x,y, TRUE)) { 101. otmp->quan++; 102. otmp->owt = weight(otmp); 103. return TRUE; 104. /* There's no need to start growing these on the neighboring 105. * mapgrids, as they move around (see water_current()) 106. */ 107. } 108. return FALSE; 109. } 110. 111. /* grow herb on ground at (x,y), or maybe spread out. 112. return true if did something. */ 113. boolean 114. grow_herbs(herb, x,y, showmsg, update) 115. int herb; 116. xchar x,y; 117. boolean showmsg, update; 118. { 119. struct obj *otmp; 120. struct rm *lev; 121. 122. rndmappos(&x, &y); 123. lev = &levl[x][y]; 124. otmp = sobj_at(herb, x, y); 125. if (otmp && herb_can_grow_at(x,y, FALSE)) { 126. if (otmp->quan <= rn2(HERB_GROWTH_LIMIT)) { 127. otmp->quan++; 128. otmp->owt = weight(otmp); 129. return TRUE; 130. } else { 131. int dd, dofs = rn2(8); 132. /* check surroundings, maybe grow there? */ 133. for (dd = 0; dd < 8; dd++) { 134. coord pos; 135. 136. dtoxy(&pos, (dd+dofs) % 8); 137. pos.x += x; 138. pos.y += y; 139. if (isok(pos.x,pos.y) && herb_can_grow_at(pos.x,pos.y, FALSE)) { 140. lev = &levl[pos.x][pos.y]; 141. otmp = sobj_at(herb, pos.x, pos.y); 142. if (otmp) { 143. if (otmp->quan <= rn2(HERB_GROWTH_LIMIT)) { 144. otmp->quan++; 145. otmp->owt = weight(otmp); 146. return TRUE; 147. } 148. } else { 149. otmp = mksobj(herb, TRUE, FALSE); 150. otmp->quan = 1; 151. otmp->owt = weight(otmp); 152. place_object(otmp, pos.x, pos.y); 153. if (update) newsym(pos.x,pos.y); 154. if (cansee(pos.x,pos.y)) { 155. if (showmsg && flags.verbose) { 156. const char *what; 157. if (herb == CLOVE_OF_GARLIC) 158. what = "some garlic"; 159. else 160. what = an(xname(otmp)); 161. Norep("Suddenly you notice %s growing on the %s.", 162. what, surface(pos.x,pos.y)); 163. } 164. } 165. return TRUE; 166. } 167. } 168. } 169. } 170. } 171. return FALSE; 172. } 173. 174. /* moves topmost object in water at (x,y) to dir. 175. return true if did something. */ 176. boolean 177. water_current(x,y,dir,waterforce, showmsg, update) 178. xchar x,y; 179. int dir; 180. unsigned waterforce; /* strength of the water current */ 181. boolean showmsg, update; 182. { 183. struct obj *otmp; 184. coord pos; 185. 186. rndmappos(&x,&y); 187. dtoxy(&pos, dir); 188. pos.x += x; 189. pos.y += y; 190. if (isok(pos.x,pos.y) && IS_POOL(levl[x][y].typ) && 191. IS_POOL(levl[pos.x][pos.y].typ)) { 192. otmp = level.objects[x][y]; 193. if (otmp && otmp->where == OBJ_FLOOR) { 194. if (otmp->quan > 1) 195. otmp = splitobj(otmp, otmp->quan - 1); 196. if (otmp->owt <= waterforce) { 197. if (showmsg && Underwater && 198. (cansee(pos.x,pos.y) || cansee(x,y))) { 199. Norep("%s floats%s in%s the murky water.", 200. An(xname(otmp)), 201. (cansee(x,y) && cansee(pos.x,pos.y)) ? "" : 202. (cansee(x,y) ? " away from you" : " towards you"), 203. flags.verbose ? " the currents of" : ""); 204. } 205. obj_extract_self(otmp); 206. place_object(otmp, pos.x,pos.y); 207. stackobj(otmp); 208. if (update) { 209. newsym(x,y); 210. newsym(pos.x,pos.y); 211. } 212. return TRUE; 213. } else /* the object didn't move, put it back */ 214. stackobj(otmp); 215. } 216. } 217. return FALSE; 218. } 219. 220. /* a tree at (x,y) spontaneously drops a ripe fruit */ 221. boolean 222. drop_ripe_treefruit(x,y,showmsg, update) 223. xchar x,y; 224. boolean showmsg, update; 225. { 226. register struct rm *lev; 227. 228. rndmappos(&x,&y); 229. lev = &levl[x][y]; 230. if (IS_TREE(lev->typ) && !(lev->looted & TREE_LOOTED) && may_dig(x,y)) { 231. coord pos; 232. int dir, dofs = rn2(8); 233. for (dir = 0; dir < 8; dir++) { 234. dtoxy(&pos, (dir + dofs) % 8); 235. pos.x += x; 236. pos.y += y; 237. if (!isok(pos.x, pos.y)) return FALSE; 238. lev = &levl[pos.x][pos.y]; 239. if (SPACE_POS(lev->typ) || IS_POOL(lev->typ)) { 240. struct obj *otmp; 241. otmp = rnd_treefruit_at(pos.x,pos.y); 242. if (otmp) { 243. otmp->quan = 1; 244. otmp->owt = weight(otmp); 245. obj_extract_self(otmp); 246. if (showmsg) { 247. if ((cansee(pos.x,pos.y) || cansee(x,y))) { 248. Norep("%s falls from %s%s.", 249. cansee(pos.x,pos.y) ? An(xname(otmp)) : Something, 250. cansee(x,y) ? "the tree" : "somewhere", 251. (cansee(x,y) && IS_POOL(lev->typ)) ? 252. " into the water" : ""); 253. } else if (distu(pos.x,pos.y) < 9 && 254. otmp->otyp != EUCALYPTUS_LEAF) { 255. /* a leaf is too light to cause any sound */ 256. You_hear("a %s!", 257. (IS_POOL(lev->typ) || IS_FOUNTAIN(lev->typ)) ? 258. "plop" : "splut"); /* rainforesty sounds */ 259. } 260. } 261. place_object(otmp, pos.x,pos.y); 262. stackobj(otmp); 263. if (rn2(6)) levl[x][y].looted |= TREE_LOOTED; 264. if (update) newsym(pos.x,pos.y); 265. return TRUE; 266. } 267. } 268. } 269. } 270. return FALSE; 271. } 272. 273. /* Tree at (x,y) seeds. returns TRUE if a new tree was created. 274. * Creates a kind of forest, with (hopefully) most places available. 275. */ 276. boolean 277. seed_tree(x,y) 278. xchar x,y; 279. { 280. coord pos, pos2; 281. struct rm *lev; 282. 283. rndmappos(&x,&y); 284. if (IS_TREE(levl[x][y].typ) && may_dig(x,y)) { 285. int dir = rn2(8); 286. dtoxy(&pos, dir); 287. pos.x += x; 288. pos.y += y; 289. if (!rn2(3)) { 290. dtoxy(&pos2, (dir+rn2(2)) % 8); 291. pos.x += pos2.x; 292. pos.y += pos2.y; 293. } 294. if (!isok(pos.x,pos.y)) return FALSE; 295. lev = &levl[pos.x][pos.y]; 296. if (lev->lit && !cansee(pos.x,pos.y) && !inside_shop(pos.x,pos.y) && 297. (lev->typ == ROOM || lev->typ == CORR) && 298. !(u.ux == pos.x && u.uy == pos.y) && !m_at(pos.x,pos.y) && 299. !t_at(pos.x,pos.y) && !OBJ_AT(pos.x,pos.y)) { 300. int nogrow = 0; 301. int dx,dy; 302. for (dx = pos.x-1; dx <= pos.x+1; dx++) { 303. for (dy = pos.y-1; dy <= pos.y+1; dy++) { 304. if (!isok(dx,dy) || 305. (isok(dx,dy) && !SPACE_POS(levl[dx][dy].typ))) 306. nogrow++; 307. } 308. } 309. if (nogrow < 3) { 310. lev->typ = TREE; 311. lev->looted &= ~TREE_LOOTED; 312. block_point(pos.x,pos.y); 313. return TRUE; 314. } 315. } 316. } 317. return FALSE; 318. } 319. 320. void 321. dgn_growths(showmsg, update) 322. boolean showmsg; /* show messages */ 323. boolean update; /* do newsym() */ 324. { 325. int herbnum = rn2(SIZE(herb_info)); 326. (void) seed_tree(-1,-1); 327. if (herb_info[herbnum].in_water) 328. (void) grow_water_herbs(herb_info[herbnum].herb, -1,-1); 329. else 330. (void) grow_herbs(herb_info[herbnum].herb, -1,-1, showmsg, update); 331. if (!rn2(30)) 332. (void) drop_ripe_treefruit(-1,-1, showmsg, update); 333. (void) water_current(-1,-1, rn2(8), 334. Is_waterlevel(&u.uz) ? 200 : 25, showmsg, update); 335. } 336. 337. /* catch up with growths when returning to a previously visited level */ 338. void 339. catchup_dgn_growths(mvs) 340. int mvs; 341. { 342. if (mvs < 0) mvs = 0; 343. else if (mvs > LARGEST_INT) mvs = LARGEST_INT; 344. while (mvs-- > 0) 345. dgn_growths(FALSE, FALSE); 346. } 347. #endif /* DUNGEON_GROWTH */ 348. 349. boolean 350. revive_nasty(x, y, msg) 351. int x,y; 352. const char *msg; 353. { 354. register struct obj *otmp, *otmp2; 355. struct monst *mtmp; 356. coord cc; 357. boolean revived = FALSE; 358. 359. for(otmp = level.objects[x][y]; otmp; otmp = otmp2) { 360. otmp2 = otmp->nexthere; 361. if (otmp->otyp == CORPSE && 362. (is_rider(&mons[otmp->corpsenm]) || 363. otmp->corpsenm == PM_WIZARD_OF_YENDOR)) { 364. /* move any living monster already at that location */ 365. if((mtmp = m_at(x,y)) && enexto(&cc, x, y, mtmp->data)) 366. rloc_to(mtmp, cc.x, cc.y); 367. if(msg) Norep("%s", msg); 368. revived = revive_corpse(otmp, FALSE); 369. } 370. } 371. 372. /* this location might not be safe, if not, move revived monster */ 373. if (revived) { 374. mtmp = m_at(x,y); 375. if (mtmp && !goodpos(x, y, mtmp, 0) && 376. enexto(&cc, x, y, mtmp->data)) { 377. rloc_to(mtmp, cc.x, cc.y); 378. } 379. /* else impossible? */ 380. } 381. 382. return (revived); 383. } 384. 385. STATIC_OVL int 386. moverock() 387. { 388. register xchar rx, ry, sx, sy; 389. register struct obj *otmp; 390. register struct trap *ttmp; 391. register struct monst *mtmp; 392. 393. sx = u.ux + u.dx, sy = u.uy + u.dy; /* boulder starting position */ 394. while ((otmp = sobj_at(BOULDER, sx, sy)) != 0) { 395. /* make sure that this boulder is visible as the top object */ 396. if (otmp != level.objects[sx][sy]) movobj(otmp, sx, sy); 397. 398. rx = u.ux + 2 * u.dx; /* boulder destination position */ 399. ry = u.uy + 2 * u.dy; 400. nomul(0); 401. if (Levitation || Is_airlevel(&u.uz)) { 402. if (Blind) feel_location(sx,sy); 403. You("don't have enough leverage to push %s.", the(xname(otmp))); 404. /* Give them a chance to climb over it? */ 405. return -1; 406. } 407. if (verysmall(youmonst.data) 408. #ifdef STEED 409. && !u.usteed 410. #endif 411. ) { 412. if (Blind) feel_location(sx,sy); 413. pline("You're too small to push that %s.", xname(otmp)); 414. goto cannot_push; 415. } 416. if (isok(rx,ry) && !IS_ROCK(levl[rx][ry].typ) && 417. levl[rx][ry].typ != IRONBARS && 418. (!IS_DOOR(levl[rx][ry].typ) || !(u.dx && u.dy) || ( 419. #ifdef REINCARNATION 420. !Is_rogue_level(&u.uz) && 421. #endif 422. (levl[rx][ry].doormask & ~D_BROKEN) == D_NODOOR)) && 423. !sobj_at(BOULDER, rx, ry)) { 424. ttmp = t_at(rx, ry); 425. mtmp = m_at(rx, ry); 426. 427. /* KMH -- Sokoban doesn't let you push boulders diagonally */ 428. if (In_sokoban(&u.uz) && u.dx && u.dy) { 429. if (Blind) feel_location(sx,sy); 430. pline("%s won't roll diagonally on this %s.", 431. The(xname(otmp)), surface(sx, sy)); 432. goto cannot_push; 433. } 434. 435. if (revive_nasty(rx, ry, "You sense movement on the other side.")) 436. return (-1); 437. 438. if (mtmp && !noncorporeal(mtmp->data) && 439. (!mtmp->mtrapped || 440. !(ttmp && ((ttmp->ttyp == PIT) || 441. (ttmp->ttyp == SPIKED_PIT))))) { 442. 443. if (Blind) feel_location(sx,sy); 444. if (canspotmon(mtmp)) { 445. boolean by_name = (mtmp->data->geno & G_UNIQ || 446. mtmp->isshk || mtmp->mnamelth); 447. if (by_name && !Hallucination) 448. pline("%s is on the other side.", Monnam(mtmp)); 449. else 450. pline("There's %s on the other side.", a_monnam(mtmp)); 451. } else { 452. You_hear("a monster behind %s.", the(xname(otmp))); 453. map_invisible(rx, ry); 454. } 455. if (flags.verbose) 456. pline("Perhaps that's why %s cannot move it.", 457. #ifdef STEED 458. u.usteed ? y_monnam(u.usteed) : 459. #endif 460. "you"); 461. goto cannot_push; 462. } 463. 464. if (ttmp) 465. switch(ttmp->ttyp) { 466. case LANDMINE: 467. if (rn2(10)) { 468. obj_extract_self(otmp); 469. place_object(otmp, rx, ry); 470. unblock_point(sx, sy); 471. newsym(sx, sy); 472. pline("KAABLAMM!!! %s %s land mine.", 473. Tobjnam(otmp, "trigger"), 474. ttmp->madeby_u ? "your" : "a"); 475. blow_up_landmine(ttmp); 476. /* if the boulder remains, it should fill the pit */ 477. fill_pit(u.ux, u.uy); 478. if (cansee(rx,ry)) newsym(rx,ry); 479. continue; 480. } 481. break; 482. case SPIKED_PIT: 483. case PIT: 484. obj_extract_self(otmp); 485. /* vision kludge to get messages right; 486. the pit will temporarily be seen even 487. if this is one among multiple boulders */ 488. if (!Blind) viz_array[ry][rx] |= IN_SIGHT; 489. if (!flooreffects(otmp, rx, ry, "fall")) { 490. place_object(otmp, rx, ry); 491. } 492. if (mtmp && !Blind) newsym(rx, ry); 493. continue; 494. case HOLE: 495. case TRAPDOOR: 496. if (Blind) 497. pline("Kerplunk! You no longer feel %s.", 498. the(xname(otmp))); 499. else 500. pline("%s%s and %s a %s in the %s!", 501. Tobjnam(otmp, 502. (ttmp->ttyp == TRAPDOOR) ? "trigger" : "fall"), 503. (ttmp->ttyp == TRAPDOOR) ? nul : " into", 504. otense(otmp, "plug"), 505. (ttmp->ttyp == TRAPDOOR) ? "trap door" : "hole", 506. surface(rx, ry)); 507. deltrap(ttmp); 508. delobj(otmp); 509. bury_objs(rx, ry); 510. if (cansee(rx,ry)) newsym(rx,ry); 511. continue; 512. case LEVEL_TELEP: 513. case TELEP_TRAP: 514. #ifdef STEED 515. if (u.usteed) 516. pline("%s pushes %s and suddenly it disappears!", 517. upstart(y_monnam(u.usteed)), the(xname(otmp))); 518. else 519. #endif 520. You("push %s and suddenly it disappears!", 521. the(xname(otmp))); 522. if (ttmp->ttyp == TELEP_TRAP) 523. rloco(otmp); 524. else { 525. int newlev = random_teleport_level(); 526. d_level dest; 527. 528. if (newlev == depth(&u.uz) || In_endgame(&u.uz)) 529. continue; 530. obj_extract_self(otmp); 531. add_to_migration(otmp); 532. get_level(&dest, newlev); 533. otmp->ox = dest.dnum; 534. otmp->oy = dest.dlevel; 535. otmp->owornmask = (long)MIGR_RANDOM; 536. } 537. seetrap(ttmp); 538. continue; 539. } 540. if (closed_door(rx, ry)) 541. goto nopushmsg; 542. if (boulder_hits_pool(otmp, rx, ry, TRUE)) 543. continue; 544. /* 545. * Re-link at top of fobj chain so that pile order is preserved 546. * when level is restored. 547. */ 548. if (otmp != fobj) { 549. remove_object(otmp); 550. place_object(otmp, otmp->ox, otmp->oy); 551. } 552. 553. { 554. #ifdef LINT /* static long lastmovetime; */ 555. long lastmovetime; 556. lastmovetime = 0; 557. #else 558. /* note: reset to zero after save/restore cycle */ 559. static NEARDATA long lastmovetime; 560. #endif 561. #ifdef STEED 562. if (!u.usteed) { 563. #endif 564. if (moves > lastmovetime+2 || moves < lastmovetime) 565. pline("With %s effort you move %s.", 566. throws_rocks(youmonst.data) ? "little" : "great", 567. the(xname(otmp))); 568. exercise(A_STR, TRUE); 569. #ifdef STEED 570. } else 571. pline("%s moves %s.", 572. upstart(y_monnam(u.usteed)), the(xname(otmp))); 573. #endif 574. lastmovetime = moves; 575. } 576. 577. /* Move the boulder *after* the message. */ 578. if (memory_is_invisible(rx, ry)) 579. unmap_object(rx, ry); 580. movobj(otmp, rx, ry); /* does newsym(rx,ry) */ 581. if (Blind) { 582. feel_location(rx,ry); 583. feel_location(sx,sy); 584. } else { 585. newsym(sx,sy); 586. } 587. } else { 588. nopushmsg: 589. #ifdef STEED 590. if (u.usteed) 591. pline("%s tries to move %s, but cannot.", 592. upstart(y_monnam(u.usteed)), the(xname(otmp))); 593. else 594. #endif 595. You("try to move %s, but in vain.", the(xname(otmp))); 596. if (Blind) feel_location(sx,sy); 597. cannot_push: 598. if (throws_rocks(youmonst.data)) { 599. #ifdef STEED 600. if (u.usteed && P_SKILL(P_RIDING) < P_BASIC) { 601. You("aren't skilled enough to %s %s from %s.", 602. (flags.pickup && !In_sokoban(&u.uz)) 603. ? "pick up" : "push aside", 604. the(xname(otmp)), y_monnam(u.usteed)); 605. } else 606. #endif 607. { 608. pline("However, you can easily %s.", 609. (flags.pickup && !In_sokoban(&u.uz)) 610. ? "pick it up" : "push it aside"); 611. if (In_sokoban(&u.uz)) 612. change_luck(-1); /* Sokoban guilt */ 613. break; 614. } 615. break; 616. } 617. 618. if ( 619. #ifdef STEED 620. !u.usteed && 621. #endif 622. (((!invent || inv_weight() <= -850) && 623. (!u.dx || !u.dy || (IS_ROCK(levl[u.ux][sy].typ) 624. && IS_ROCK(levl[sx][u.uy].typ)))) 625. || verysmall(youmonst.data))) { 626. pline("However, you can squeeze yourself into a small opening."); 627. if (In_sokoban(&u.uz)) 628. change_luck(-1); /* Sokoban guilt */ 629. break; 630. } else 631. return (-1); 632. } 633. } 634. return (0); 635. } 636. 637. /* 638. * still_chewing() 639. * 640. * Chew on a wall, door, or boulder. Returns TRUE if still eating, FALSE 641. * when done. 642. */ 643. STATIC_OVL int 644. still_chewing(x,y) 645. xchar x, y; 646. { 647. struct rm *lev = &levl[x][y]; 648. struct obj *boulder = sobj_at(BOULDER,x,y); 649. const char *digtxt = (char *)0, *dmgtxt = (char *)0; 650. 651. if (digging.down) /* not continuing previous dig (w/ pick-axe) */ 652. (void) memset((genericptr_t)&digging, 0, sizeof digging); 653. 654. if (!boulder && IS_ROCK(lev->typ) && !may_dig(x,y)) { 655. You("hurt your teeth on the %s.", 656. IS_TREE(lev->typ) ? "tree" : "hard stone"); 657. nomul(0); 658. return 1; 659. } else if (digging.pos.x != x || digging.pos.y != y || 660. !on_level(&digging.level, &u.uz)) { 661. digging.down = FALSE; 662. digging.chew = TRUE; 663. digging.warned = FALSE; 664. digging.pos.x = x; 665. digging.pos.y = y; 666. assign_level(&digging.level, &u.uz); 667. /* solid rock takes more work & time to dig through */ 668. digging.effort = 669. (IS_ROCK(lev->typ) && !IS_TREE(lev->typ) ? 30 : 60) + u.udaminc; 670. You("start chewing %s %s.", 671. (boulder || IS_TREE(lev->typ)) ? "on a" : "a hole in the", 672. boulder ? "boulder" : 673. IS_TREE(lev->typ) ? "tree" : IS_ROCK(lev->typ) ? "rock" : "door"); 674. watch_dig((struct monst *)0, x, y, FALSE); 675. return 1; 676. } else if ((digging.effort += (30 + u.udaminc)) <= 100) { 677. if (flags.verbose) 678. You("%s chewing on the %s.", 679. digging.chew ? "continue" : "begin", 680. boulder ? "boulder" : 681. IS_TREE(lev->typ) ? "tree" : 682. IS_ROCK(lev->typ) ? "rock" : "door"); 683. digging.chew = TRUE; 684. watch_dig((struct monst *)0, x, y, FALSE); 685. return 1; 686. } 687. 688. /* Okay, you've chewed through something */ 689. u.uconduct.food++; 690. u.uhunger += rnd(20); 691. 692. if (boulder) { 693. delobj(boulder); /* boulder goes bye-bye */ 694. You("eat the boulder."); /* yum */ 695. 696. /* 697. * The location could still block because of 698. * 1. More than one boulder 699. * 2. Boulder stuck in a wall/stone/door. 700. * 701. * [perhaps use does_block() below (from vision.c)] 702. */ 703. if (IS_ROCK(lev->typ) || closed_door(x,y) || sobj_at(BOULDER,x,y)) { 704. block_point(x,y); /* delobj will unblock the point */ 705. /* reset dig state */ 706. (void) memset((genericptr_t)&digging, 0, sizeof digging); 707. return 1; 708. } 709. 710. } else if (IS_WALL(lev->typ)) { 711. if (*in_rooms(x, y, SHOPBASE)) { 712. add_damage(x, y, 10L * ACURRSTR); 713. dmgtxt = "damage"; 714. } 715. digtxt = "chew a hole in the wall."; 716. if (level.flags.is_maze_lev) { 717. lev->typ = ROOM; 718. } else if (level.flags.is_cavernous_lev && !in_town(x, y)) { 719. lev->typ = CORR; 720. } else { 721. lev->typ = DOOR; 722. lev->doormask = D_NODOOR; 723. } 724. } else if (IS_TREE(lev->typ)) { 725. digtxt = "chew through the tree."; 726. lev->typ = ROOM; 727. } else if (lev->typ == SDOOR) { 728. if (lev->doormask & D_TRAPPED) { 729. lev->doormask = D_NODOOR; 730. b_trapped("secret door", 0); 731. } else { 732. digtxt = "chew through the secret door."; 733. lev->doormask = D_BROKEN; 734. } 735. lev->typ = DOOR; 736. 737. } else if (IS_DOOR(lev->typ)) { 738. if (*in_rooms(x, y, SHOPBASE)) { 739. add_damage(x, y, 400L); 740. dmgtxt = "break"; 741. } 742. if (lev->doormask & D_TRAPPED) { 743. lev->doormask = D_NODOOR; 744. b_trapped("door", 0); 745. } else { 746. digtxt = "chew through the door."; 747. lev->doormask = D_BROKEN; 748. } 749. 750. } else { /* STONE or SCORR */ 751. digtxt = "chew a passage through the rock."; 752. lev->typ = CORR; 753. } 754. 755. unblock_point(x, y); /* vision */ 756. newsym(x, y); 757. if (digtxt) You(digtxt); /* after newsym */ 758. if (dmgtxt) pay_for_damage(dmgtxt, FALSE); 759. (void) memset((genericptr_t)&digging, 0, sizeof digging); 760. return 0; 761. } 762. 763. #endif /* OVL2 */ 764. #ifdef OVLB 765. 766. void 767. movobj(obj, ox, oy) 768. register struct obj *obj; 769. register xchar ox, oy; 770. { 771. /* optimize by leaving on the fobj chain? */ 772. remove_object(obj); 773. newsym(obj->ox, obj->oy); 774. place_object(obj, ox, oy); 775. newsym(ox, oy); 776. } 777. 778. #ifdef SINKS 779. static NEARDATA const char fell_on_sink[] = "fell onto a sink"; 780. 781. STATIC_OVL void 782. dosinkfall() 783. { 784. register struct obj *obj; 785. 786. if (is_floater(youmonst.data) || (HLevitation & FROMOUTSIDE)) { 787. You("wobble unsteadily for a moment."); 788. } else { 789. long save_ELev = ELevitation, save_HLev = HLevitation; 790. 791. /* fake removal of levitation in advance so that final 792. disclosure will be right in case this turns out to 793. be fatal; fortunately the fact that rings and boots 794. are really still worn has no effect on bones data */ 795. ELevitation = HLevitation = 0L; 796. You("crash to the floor!"); 797. losehp(rn1(8, 25 - (int)ACURR(A_CON)), 798. fell_on_sink, NO_KILLER_PREFIX); 799. exercise(A_DEX, FALSE); 800. selftouch("Falling, you"); 801. for (obj = level.objects[u.ux][u.uy]; obj; obj = obj->nexthere) 802. if (obj->oclass == WEAPON_CLASS || is_weptool(obj)) { 803. You("fell on %s.", doname(obj)); 804. losehp(rnd(3), fell_on_sink, NO_KILLER_PREFIX); 805. exercise(A_CON, FALSE); 806. } 807. ELevitation = save_ELev; 808. HLevitation = save_HLev; 809. } 810. 811. ELevitation &= ~W_ARTI; 812. HLevitation &= ~(I_SPECIAL|TIMEOUT); 813. HLevitation++; 814. if(uleft && uleft->otyp == RIN_LEVITATION) { 815. obj = uleft; 816. Ring_off(obj); 817. off_msg(obj); 818. } 819. if(uright && uright->otyp == RIN_LEVITATION) { 820. obj = uright; 821. Ring_off(obj); 822. off_msg(obj); 823. } 824. if(uarmf && uarmf->otyp == LEVITATION_BOOTS) { 825. obj = uarmf; 826. (void)Boots_off(); 827. off_msg(obj); 828. } 829. HLevitation--; 830. } 831. #endif 832. 833. boolean 834. may_dig(x,y) 835. register xchar x,y; 836. /* intended to be called only on ROCKs */ 837. { 838. return (boolean)(!(IS_STWALL(levl[x][y].typ) && 839. (levl[x][y].wall_info & W_NONDIGGABLE))); 840. } 841. 842. boolean 843. may_passwall(x,y) 844. register xchar x,y; 845. { 846. return (boolean)(!(IS_STWALL(levl[x][y].typ) && 847. (levl[x][y].wall_info & W_NONPASSWALL))); 848. } 849. 850. #endif /* OVLB */ 851. #ifdef OVL1 852. 853. /* [ALI] Changed to take monst * as argument to support passwall property */ 854. boolean 855. bad_rock(mon,x,y) 856. struct monst *mon; 857. register xchar x,y; 858. { 859. struct permonst *mdat = mon->data; 860. boolean passwall = mon == &youmonst ? Passes_walls : passes_walls(mdat); 861. return((boolean) ((In_sokoban(&u.uz) && sobj_at(BOULDER,x,y)) || 862. (IS_ROCK(levl[x][y].typ) 863. && (!tunnels(mdat) || needspick(mdat) || !may_dig(x,y)) 864. && !(passwall && may_passwall(x,y))))); 865. } 866. 867. boolean 868. invocation_pos(x, y) 869. xchar x, y; 870. { 871. return((boolean)(Invocation_lev(&u.uz) && x == inv_pos.x && y == inv_pos.y)); 872. } 873. 874. #endif /* OVL1 */ 875. #ifdef OVL3 876. /* For my clever ending messages... */ 877. int Instant_Death = 0; 878. int Quick_Death = 0; 879. int Nibble_Death = 0; 880. int last_hit = 0; 881. int second_last_hit = 0; 882. int third_last_hit = 0; 883. 884. /* For those tough guys who get carried away... */ 885. int repeat_hit = 0; 886. 887. /* return TRUE if (dx,dy) is an OK place to move 888. * mode is one of DO_MOVE, TEST_MOVE or TEST_TRAV 889. */ 890. boolean 891. test_move(ux, uy, dx, dy, mode) 892. int ux, uy, dx, dy; 893. int mode; 894. { 895. int x = ux+dx; 896. int y = uy+dy; 897. register struct rm *tmpr = &levl[x][y]; 898. register struct rm *ust; 899. 900. /* 901. * Check for physical obstacles. First, the place we are going. 902. */ 903. if (IS_ROCK(tmpr->typ) || tmpr->typ == IRONBARS) { 904. if (Blind && mode == DO_MOVE) feel_location(x,y); 905. if (tmpr->typ == IRONBARS) { 906. if (!(Passes_walls || passes_bars(youmonst.data))) 907. return FALSE; 908. else if (In_sokoban(&u.uz)) { 909. if (mode == DO_MOVE) 910. pline_The("Sokoban bars resist your ability."); 911. return FALSE; 912. } 913. } else if (Passes_walls && may_passwall(x,y)) { 914. ; /* do nothing */ 915. } else if (tunnels(youmonst.data) && !needspick(youmonst.data)) { 916. /* Eat the rock. */ 917. if (mode == DO_MOVE && still_chewing(x,y)) return FALSE; 918. } else if (flags.autodig && !flags.run && !flags.nopick && 919. uwep && is_pick(uwep)) { 920. /* MRKR: Automatic digging when wielding the appropriate tool */ 921. if (mode == DO_MOVE) 922. (void) use_pick_axe2(uwep); 923. return FALSE; 924. } else { 925. if (mode == DO_MOVE) { 926. if (Is_stronghold(&u.uz) && is_db_wall(x,y)) 927. pline_The("drawbridge is up!"); 928. if (Passes_walls && !may_passwall(x,y) && In_sokoban(&u.uz)) 929. pline_The("Sokoban walls resist your ability."); 930. } 931. return FALSE; 932. } 933. } else if (IS_DOOR(tmpr->typ)) { 934. if (closed_door(x,y)) { 935. if (Blind && mode == DO_MOVE) feel_location(x,y); 936. /* ALI - artifact doors */ 937. if (artifact_door(x, y)) { 938. if (mode == DO_MOVE) { 939. if (amorphous(youmonst.data)) 940. You("try to ooze under the door, but the gap is too small."); 941. else if (tunnels(youmonst.data) && !needspick(youmonst.data)) 942. You("hurt your teeth on the re-enforced door."); 943. else if (x == u.ux || y == u.uy) { 944. if (Blind || Stunned || ACURR(A_DEX) < 10 || Fumbling) { pline("Ouch! You bump into a heavy door."); 945. exercise(A_DEX, FALSE); 946. } else pline("That door is closed."); 947. } 948. } 949. return FALSE; 950. } else 951. if (Passes_walls) 952. ; /* do nothing */ 953. else if (can_ooze(&youmonst)) { 954. if (mode == DO_MOVE) You("ooze under the door."); 955. } else if (tunnels(youmonst.data) && !needspick(youmonst.data)) { 956. /* Eat the door. */ 957. if (mode == DO_MOVE && still_chewing(x,y)) return FALSE; 958. } else { 959. if (mode == DO_MOVE) { 960. if (amorphous(youmonst.data)) 961. You("try to ooze under the door, but can't squeeze your possessions through."); 962. else if (x == ux || y == uy) { 963. if (Blind || Stunned || ACURR(A_DEX) < 10 || Fumbling) { 964. #ifdef STEED 965. if (u.usteed) { 966. You_cant("lead %s through that closed door.", 967. y_monnam(u.usteed)); 968. } else 969. #endif 970. { 971. pline("Ouch! You bump into a door."); 972. exercise(A_DEX, FALSE); 973. } 974. } else pline("That door is closed."); 975. } 976. } else if (mode == TEST_TRAV) goto testdiag; 977. return FALSE; 978. } 979. } else { 980. testdiag: 981. if (dx && dy && !Passes_walls 982. && ((tmpr->doormask & ~D_BROKEN) 983. #ifdef REINCARNATION 984. || Is_rogue_level(&u.uz) 985. #endif 986. || block_door(x,y))) { 987. /* Diagonal moves into a door are not allowed. */ 988. if (Blind && mode == DO_MOVE) 989. feel_location(x,y); 990. return FALSE; 991. } 992. } 993. } 994. if (dx && dy 995. && bad_rock(&youmonst,ux,y) && bad_rock(&youmonst,x,uy)) { 996. /* Move at a diagonal. */ 997. if (In_sokoban(&u.uz)) { 998. if (mode == DO_MOVE) 999. You("cannot pass that way."); 1000. return FALSE; 1001. } 1002. if (bigmonst(youmonst.data)) { 1003. if (mode == DO_MOVE) 1004. Your("body is too large to fit through."); 1005. return FALSE; 1006. } 1007. if (invent && (inv_weight() + weight_cap() > 600)) { 1008. if (mode == DO_MOVE) 1009. You("are carrying too much to get through."); 1010. return FALSE; 1011. } 1012. } 1013. /* Pick travel path that does not require crossing a trap. 1014. * Avoid water and lava using the usual running rules. 1015. * (but not u.ux/u.uy because findtravelpath walks toward u.ux/u.uy) */ 1016. if (flags.run == 8 && mode != DO_MOVE && (x != u.ux || y != u.uy)) { 1017. struct trap* t = t_at(x, y); 1018. 1019. if ((t && t->tseen) || 1020. (!Levitation && !Flying && 1021. !is_clinger(youmonst.data) && 1022. (is_pool(x, y) || is_lava(x, y)) && levl[x][y].seenv)) 1023. return FALSE; 1024. } 1025. 1026. ust = &levl[ux][uy]; 1027. 1028. /* Now see if other things block our way . . */ 1029. if (dx && dy && !Passes_walls 1030. && (IS_DOOR(ust->typ) && ((ust->doormask & ~D_BROKEN) 1031. #ifdef REINCARNATION 1032. || Is_rogue_level(&u.uz) 1033. #endif 1034. || block_entry(x, y)) 1035. )) { 1036. /* Can't move at a diagonal out of a doorway with door. */ 1037. return FALSE; 1038. } 1039. 1040. if (sobj_at(BOULDER,x,y) && (In_sokoban(&u.uz) || !Passes_walls)) { 1041. if (!(Blind || Hallucination) && (flags.run >= 2) && mode != TEST_TRAV) 1042. return FALSE; 1043. if (mode == DO_MOVE) { 1044. /* tunneling monsters will chew before pushing */ 1045. if (tunnels(youmonst.data) && !needspick(youmonst.data) && 1046. !In_sokoban(&u.uz)) { 1047. if (still_chewing(x,y)) return FALSE; 1048. } else 1049. if (moverock() < 0) return FALSE; 1050. } else if (mode == TEST_TRAV) { 1051. struct obj* obj; 1052. 1053. /* don't pick two boulders in a row, unless there's a way thru */ 1054. if (sobj_at(BOULDER,ux,uy) && !In_sokoban(&u.uz)) { 1055. if (!Passes_walls && 1056. !(tunnels(youmonst.data) && !needspick(youmonst.data)) && 1057. !carrying(PICK_AXE) && !carrying(DWARVISH_MATTOCK) && 1058. !((obj = carrying(WAN_DIGGING)) && 1059. !objects[obj->otyp].oc_name_known)) 1060. return FALSE; 1061. } 1062. } 1063. /* assume you'll be able to push it when you get there... */ 1064. } 1065. 1066. /* OK, it is a legal place to move. */ 1067. return TRUE; 1068. } 1069. 1070. /* 1071. * Find a path from the destination (u.tx,u.ty) back to (u.ux,u.uy). 1072. * A shortest path is returned. If guess is TRUE, consider various 1073. * inaccessible locations as valid intermediate path points. 1074. * Returns TRUE if a path was found. 1075. */ 1076. static boolean 1077. findtravelpath(guess) 1078. boolean guess; 1079. { 1080. /* if travel to adjacent, reachable location, use normal movement rules */ 1081. if (!guess && iflags.travel1 && distmin(u.ux, u.uy, u.tx, u.ty) == 1) { 1082. flags.run = 0; 1083. if (test_move(u.ux, u.uy, u.tx-u.ux, u.ty-u.uy, TEST_MOVE)) { 1084. u.dx = u.tx-u.ux; 1085. u.dy = u.ty-u.uy; 1086. nomul(0); 1087. iflags.travelcc.x = iflags.travelcc.y = -1; 1088. return TRUE; 1089. } 1090. flags.run = 8; 1091. } 1092. if (u.tx != u.ux || u.ty != u.uy) { 1093. xchar travel[COLNO][ROWNO]; 1094. xchar travelstepx[2][COLNO*ROWNO]; 1095. xchar travelstepy[2][COLNO*ROWNO]; 1096. xchar tx, ty, ux, uy; 1097. int n = 1; /* max offset in travelsteps */ 1098. int set = 0; /* two sets current and previous */ 1099. int radius = 1; /* search radius */ 1100. int i; 1101. 1102. /* If guessing, first find an "obvious" goal location. The obvious 1103. * goal is the position the player knows of, or might figure out 1104. * (couldsee) that is closest to the target on a straight path. 1105. */ 1106. if (guess) { 1107. tx = u.ux; ty = u.uy; ux = u.tx; uy = u.ty; 1108. } else { 1109. tx = u.tx; ty = u.ty; ux = u.ux; uy = u.uy; 1110. } 1111. 1112. noguess: 1113. (void) memset((genericptr_t)travel, 0, sizeof(travel)); 1114. travelstepx[0][0] = tx; 1115. travelstepy[0][0] = ty; 1116. 1117. while (n != 0) { 1118. int nn = 0; 1119. 1120. for (i = 0; i < n; i++) { 1121. int dir; 1122. int x = travelstepx[set][i]; 1123. int y = travelstepy[set][i]; 1124. static int ordered[] = { 0, 2, 4, 6, 1, 3, 5, 7 }; 1125. /* no diagonal movement for grid bugs */ 1126. int dirmax = u.umonnum == PM_GRID_BUG ? 4 : 8; 1127. 1128. for (dir = 0; dir < dirmax; ++dir) { 1129. int nx = x+xdir[ordered[dir]]; 1130. int ny = y+ydir[ordered[dir]]; 1131. 1132. if (!isok(nx, ny)) continue; 1133. if ((!Passes_walls && !can_ooze(&youmonst) && 1134. closed_door(x, y)) || sobj_at(BOULDER, x, y)) { 1135. /* closed doors and boulders usually 1136. * cause a delay, so prefer another path */ 1137. if (travel[x][y] > radius-3) { 1138. travelstepx[1-set][nn] = x; 1139. travelstepy[1-set][nn] = y; 1140. /* don't change travel matrix! */ 1141. nn++; 1142. continue; 1143. } 1144. } 1145. if (test_move(x, y, nx-x, ny-y, TEST_TRAV) && 1146. (levl[nx][ny].seenv || (!Blind && couldsee(nx, ny)))) { 1147. if (nx == ux && ny == uy) { 1148. if (!guess) { 1149. u.dx = x-ux; 1150. u.dy = y-uy; 1151. if (x == u.tx && y == u.ty) { 1152. nomul(0); 1153. /* reset run so domove run checks work */ 1154. flags.run = 8; 1155. iflags.travelcc.x = iflags.travelcc.y = -1; 1156. } 1157. return TRUE; 1158. } 1159. } else if (!travel[nx][ny]) { 1160. travelstepx[1-set][nn] = nx; 1161. travelstepy[1-set][nn] = ny; 1162. travel[nx][ny] = radius; 1163. nn++; 1164. } 1165. } 1166. } 1167. } 1168. 1169. n = nn; 1170. set = 1-set; 1171. radius++; 1172. } 1173. 1174. /* if guessing, find best location in travel matrix and go there */ 1175. if (guess) { 1176. int px = tx, py = ty; /* pick location */ 1177. int dist, nxtdist, d2, nd2; 1178. 1179. dist = distmin(ux, uy, tx, ty); 1180. d2 = dist2(ux, uy, tx, ty); 1181. for (tx = 1; tx < COLNO; ++tx) 1182. for (ty = 0; ty < ROWNO; ++ty) 1183. if (travel[tx][ty]) { 1184. nxtdist = distmin(ux, uy, tx, ty); 1185. if (nxtdist == dist && couldsee(tx, ty)) { 1186. nd2 = dist2(ux, uy, tx, ty); 1187. if (nd2 < d2) { 1188. /* prefer non-zigzag path */ 1189. px = tx; py = ty; 1190. d2 = nd2; 1191. } 1192. } else if (nxtdist < dist && couldsee(tx, ty)) { 1193. px = tx; py = ty; 1194. dist = nxtdist; 1195. d2 = dist2(ux, uy, tx, ty); 1196. } 1197. } 1198. 1199. if (px == u.ux && py == u.uy) { 1200. /* no guesses, just go in the general direction */ 1201. u.dx = sgn(u.tx - u.ux); 1202. u.dy = sgn(u.ty - u.uy); 1203. if (test_move(u.ux, u.uy, u.dx, u.dy, TEST_MOVE)) 1204. return TRUE; 1205. goto found; 1206. } 1207. tx = px; 1208. ty = py; 1209. ux = u.ux; 1210. uy = u.uy; 1211. set = 0; 1212. n = radius = 1; 1213. guess = FALSE; 1214. goto noguess; 1215. } 1216. return FALSE; 1217. } 1218. 1219. found: 1220. u.dx = 0; 1221. u.dy = 0; 1222. nomul(0); 1223. return FALSE; 1224. } 1225. 1226. void 1227. domove() 1228. { 1229. register struct monst *mtmp; 1230. register struct rm *tmpr; 1231. register xchar x,y; 1232. struct trap *trap; 1233. int wtcap; 1234. boolean on_ice; 1235. xchar chainx, chainy, ballx, bally; /* ball&chain new positions */ 1236. int bc_control; /* control for ball&chain */ 1237. boolean cause_delay = FALSE; /* dragging ball will skip a move */ 1238. const char *predicament; 1239. boolean displacer = FALSE; /* defender attempts to displace you */ 1240. 1241. u_wipe_engr(rnd(5)); 1242. 1243. if (flags.travel) { 1244. if (!findtravelpath(FALSE)) 1245. (void) findtravelpath(TRUE); 1246. iflags.travel1 = 0; 1247. } 1248. 1249. if(((wtcap = near_capacity()) >= OVERLOADED 1250. || (wtcap > SLT_ENCUMBER && 1251. (Upolyd ? (u.mh < 5 && u.mh != u.mhmax) 1252. : (u.uhp < 10 && u.uhp != u.uhpmax)))) 1253. && !Is_airlevel(&u.uz)) { 1254. if(wtcap < OVERLOADED) { 1255. You("don't have enough stamina to move."); 1256. exercise(A_CON, FALSE); 1257. } else 1258. You("collapse under your load."); 1259. nomul(0); 1260. return; 1261. } 1262. if(u.uswallow) { 1263. u.dx = u.dy = 0; 1264. u.ux = x = u.ustuck->mx; 1265. u.uy = y = u.ustuck->my; 1266. mtmp = u.ustuck; 1267. } else { 1268. if (Is_airlevel(&u.uz) && rn2(4) && 1269. !Levitation && !Flying) { 1270. switch(rn2(3)) { 1271. case 0: 1272. You("tumble in place."); 1273. exercise(A_DEX, FALSE); 1274. break; 1275. case 1: 1276. You_cant("control your movements very well."); break; 1277. case 2: 1278. pline("It's hard to walk in thin air."); 1279. exercise(A_DEX, TRUE); 1280. break; 1281. } 1282. return; 1283. } 1284. 1285. /* check slippery ice */ 1286. on_ice = !Levitation && is_ice(u.ux, u.uy); 1287. if (on_ice) { 1288. static int skates = 0; 1289. if (!skates) skates = find_skates(); 1290. if ((uarmf && uarmf->otyp == skates) 1291. || resists_cold(&youmonst) || Flying 1292. || is_floater(youmonst.data) || is_clinger(youmonst.data) 1293. || is_whirly(youmonst.data)) 1294. on_ice = FALSE; 1295. else if (!rn2(Cold_resistance ? 3 : 2)) { 1296. HFumbling |= FROMOUTSIDE; 1297. HFumbling &= ~TIMEOUT; 1298. HFumbling += 1; /* slip on next move */ 1299. } 1300. } 1301. if (!on_ice && (HFumbling & FROMOUTSIDE)) 1302. HFumbling &= ~FROMOUTSIDE; 1303. 1304. x = u.ux + u.dx; 1305. y = u.uy + u.dy; 1306. #ifdef STEED 1307. /* Check if your steed can move */ 1308. if (u.usteed && (!u.usteed->mcanmove || u.usteed->msleeping)) { 1309. Your("steed doesn't respond!"); 1310. nomul(0); 1311. return; 1312. } 1313. #endif 1314. if(Stunned || (Confusion && !rn2(5)) 1315. #ifdef STEED 1316. || (u.usteed && u.usteed->mconf) 1317. #endif 1318. ) { 1319. register int tries = 0; 1320. 1321. do { 1322. if(tries++ > 50) { 1323. nomul(0); 1324. return; 1325. } 1326. confdir(); 1327. x = u.ux + u.dx; 1328. y = u.uy + u.dy; 1329. } while(!isok(x, y) || bad_rock(&youmonst, x, y)); 1330. } 1331. /* turbulence might alter your actual destination */ 1332. if (u.uinwater) { 1333. water_friction(); 1334. if (!u.dx && !u.dy) { 1335. nomul(0); 1336. return; 1337. } 1338. x = u.ux + u.dx; 1339. y = u.uy + u.dy; 1340. } 1341. if(!isok(x, y)) { 1342. nomul(0); 1343. return; 1344. } 1345. if (((trap = t_at(x, y)) && trap->tseen) || 1346. (Blind && !Levitation && !Flying && 1347. !is_clinger(youmonst.data) && 1348. (is_pool(x, y) || is_lava(x, y)) && levl[x][y].seenv)) { 1349. if(flags.run >= 2) { 1350. nomul(0); 1351. flags.move = 0; 1352. return; 1353. } else 1354. nomul(0); 1355. } 1356. 1357. if (u.ustuck && (x != u.ustuck->mx || y != u.ustuck->my)) { 1358. if (distu(u.ustuck->mx, u.ustuck->my) > 2) { 1359. /* perhaps it fled (or was teleported or ... ) */ 1360. setustuck(0); 1361. } else if (sticks(youmonst.data)) { 1362. /* When polymorphed into a sticking monster, 1363. * u.ustuck means it's stuck to you, not you to it. 1364. */ 1365. You("release %s.", mon_nam(u.ustuck)); 1366. setustuck(0); 1367. } else { 1368. /* If holder is asleep or paralyzed: 1369. * 37.5% chance of getting away, 1370. * 12.5% chance of waking/releasing it; 1371. * otherwise: 1372. * 7.5% chance of getting away. 1373. * [strength ought to be a factor] 1374. * If holder is tame and there is no conflict, 1375. * guaranteed escape. 1376. */ 1377. switch (rn2(!u.ustuck->mcanmove ? 8 : 40)) { 1378. case 0: case 1: case 2: 1379. pull_free: 1380. You("pull free from %s.", mon_nam(u.ustuck)); 1381. setustuck(0); 1382. break; 1383. case 3: 1384. if (!u.ustuck->mcanmove) { 1385. /* it's free to move on next turn */ 1386. u.ustuck->mfrozen = 1; 1387. u.ustuck->msleeping = 0; 1388. } 1389. /*FALLTHRU*/ 1390. default: 1391. if (u.ustuck->mtame && 1392. !Conflict && !u.ustuck->mconf) 1393. goto pull_free; 1394. You("cannot escape from %s!", mon_nam(u.ustuck)); 1395. nomul(0); 1396. return; 1397. } 1398. } 1399. } 1400. 1401. mtmp = m_at(x,y); 1402. if (mtmp) { 1403. /* Don't attack if you're running, and can see it */ 1404. /* We should never get here if forcefight */ 1405. if (flags.run && 1406. ((!Blind && mon_visible(mtmp) && 1407. ((mtmp->m_ap_type != M_AP_FURNITURE && 1408. mtmp->m_ap_type != M_AP_OBJECT) || 1409. Protection_from_shape_changers)) || 1410. sensemon(mtmp))) { 1411. nomul(0); 1412. flags.move = 0; 1413. return; 1414. } 1415. } 1416. } 1417. u.ux0 = u.ux; 1418. u.uy0 = u.uy; 1419. bhitpos.x = x; 1420. bhitpos.y = y; 1421. tmpr = &levl[x][y]; 1422. /* attack monster */ 1423. if(mtmp) { 1424. nomul(0); 1425. /* only attack if we know it's there */ 1426. /* or if we used the 'F' command to fight blindly */ 1427. /* or if it hides_under, in which case we call attack() to print 1428. * the Wait! message. 1429. * This is different from ceiling hiders, who aren't handled in 1430. * attack(). 1431. */ 1432. 1433. /* If they used a 'm' command, trying to move onto a monster 1434. * prints the below message and wastes a turn. The exception is 1435. * if the monster is unseen and the player doesn't remember an 1436. * invisible monster--then, we fall through to attack() and 1437. * attack_check(), which still wastes a turn, but prints a 1438. * different message and makes the player remember the monster. */ 1439. if(flags.nopick && 1440. (canspotmon(mtmp) || memory_is_invisible(x, y))){ 1441. if(mtmp->m_ap_type && !Protection_from_shape_changers 1442. && !sensemon(mtmp)) 1443. stumble_onto_mimic(mtmp); 1444. else if (mtmp->mpeaceful && !Hallucination) 1445. pline("Pardon me, %s.", m_monnam(mtmp)); 1446. else 1447. You("move right into %s.", mon_nam(mtmp)); 1448. return; 1449. } 1450. if(flags.forcefight || !mtmp->mundetected || sensemon(mtmp) || 1451. ((hides_under(mtmp->data) || mtmp->data->mlet == S_EEL) && 1452. !is_safepet(mtmp))){ 1453. gethungry(); 1454. if(wtcap >= HVY_ENCUMBER && moves%3) { 1455. if (Upolyd && u.mh > 1) { 1456. u.mh--; 1457. } else if (!Upolyd && u.uhp > 1) { 1458. u.uhp--; 1459. } else { 1460. You("pass out from exertion!"); 1461. exercise(A_CON, FALSE); 1462. fall_asleep(-10, FALSE); 1463. } 1464. } 1465. if(multi < 0) return; /* we just fainted */ 1466. /* new displacer beast thingie -- by [Tom] */ 1467. /* sometimes, instead of attacking, you displace it. */ 1468. /* Good joke, huh? */ 1469. if (mtmp->data == &mons[PM_DISPLACER_BEAST] && !rn2(2)) 1470. displacer = TRUE; 1471. else 1472. /* try to attack; note that it might evade */ 1473. /* also, we don't attack tame when _safepet_ */ 1474. if(attack(mtmp)) return; 1475. } 1476. } 1477. /* specifying 'F' with no monster wastes a turn */ 1478. if (flags.forcefight || 1479. /* remembered an 'I' && didn't use a move command */ 1480. (memory_is_invisible(x, y) && !flags.nopick)) { 1481. boolean expl = (Upolyd && attacktype(youmonst.data, AT_EXPL)); 1482. char buf[BUFSZ]; 1483. Sprintf(buf,"a vacant spot on the %s", surface(x,y)); 1484. You("%s %s.", 1485. expl ? "explode at" : "attack", 1486. !Underwater ? "thin air" : 1487. is_pool(x,y) ? "empty water" : buf); 1488. unmap_object(x, y); /* known empty -- remove 'I' if present */ 1489. newsym(x, y); 1490. nomul(0); 1491. if (expl) { 1492. u.mh = -1; /* dead in the current form */ 1493. rehumanize(); 1494. } 1495. return; 1496. } 1497. if (memory_is_invisible(x, y)) { 1498. unmap_object(x, y); 1499. newsym(x, y); 1500. } 1501. /* not attacking an animal, so we try to move */ 1502. if (!displacer) { 1503. 1504. #ifdef STEED 1505. if (u.usteed && !u.usteed->mcanmove && (u.dx || u.dy)) { 1506. pline("%s won't move!", upstart(y_monnam(u.usteed))); 1507. nomul(0); 1508. return; 1509. } else 1510. #endif 1511. if(!youmonst.data->mmove) { 1512. You("are rooted %s.", 1513. Levitation || Is_airlevel(&u.uz) || Is_waterlevel(&u.uz) ? 1514. "in place" : "to the ground"); 1515. nomul(0); 1516. return; 1517. } 1518. if(u.utrap) { 1519. if(u.utraptype == TT_PIT) { 1520. if (!rn2(2) && sobj_at(BOULDER, u.ux, u.uy)) { 1521. Your("%s gets stuck in a crevice.", body_part(LEG)); 1522. display_nhwindow(WIN_MESSAGE, FALSE); 1523. clear_nhwindow(WIN_MESSAGE); 1524. You("free your %s.", body_part(LEG)); 1525. } else if (Flying && !In_sokoban(&u.uz)) { 1526. /* eg fell in pit, poly'd to a flying monster */ 1527. You("fly from the pit."); 1528. u.utrap = 0; 1529. fill_pit(u.ux, u.uy); 1530. vision_full_recalc = 1; /* vision limits change */ 1531. } else if (!(--u.utrap)) { 1532. You("%s to the edge of the pit.", 1533. (In_sokoban(&u.uz) && Levitation) ? 1534. "struggle against the air currents and float" : 1535. #ifdef STEED 1536. u.usteed ? "ride" : 1537. #endif 1538. "crawl"); 1539. fill_pit(u.ux, u.uy); 1540. vision_full_recalc = 1; /* vision limits change */ 1541. } else if (flags.verbose) { 1542. #ifdef STEED 1543. if (u.usteed) 1544. Norep("%s is still in a pit.", 1545. upstart(y_monnam(u.usteed))); 1546. else 1547. #endif 1548. Norep( (Hallucination && !rn2(5)) ? 1549. "You've fallen, and you can't get up." : 1550. "You are still in a pit." ); 1551. } 1552. } else if (u.utraptype == TT_LAVA) { 1553. if(flags.verbose) { 1554. predicament = "stuck in the lava"; 1555. #ifdef STEED 1556. if (u.usteed) 1557. Norep("%s is %s.", upstart(y_monnam(u.usteed)), 1558. predicament); 1559. else 1560. #endif 1561. Norep("You are %s.", predicament); 1562. } 1563. if(!is_lava(x,y)) { 1564. u.utrap--; 1565. if((u.utrap & 0xff) == 0) { 1566. #ifdef STEED 1567. if (u.usteed) 1568. You("lead %s to the edge of the lava.", 1569. y_monnam(u.usteed)); 1570. else 1571. #endif 1572. You("pull yourself to the edge of the lava."); 1573. u.utrap = 0; 1574. } 1575. } 1576. u.umoved = TRUE; 1577. } else if (u.utraptype == TT_WEB) { 1578. if(uwep && uwep->oartifact == ART_STING) { 1579. u.utrap = 0; 1580. pline("Sting cuts through the web!"); 1581. return; 1582. } 1583. if(--u.utrap) { 1584. if(flags.verbose) { 1585. predicament = "stuck to the web"; 1586. #ifdef STEED 1587. if (u.usteed) 1588. Norep("%s is %s.", upstart(y_monnam(u.usteed)), 1589. predicament); 1590. else 1591. #endif 1592. Norep("You are %s.", predicament); 1593. } 1594. } else { 1595. #ifdef STEED 1596. if (u.usteed) 1597. pline("%s breaks out of the web.", 1598. upstart(y_monnam(u.usteed))); 1599. else 1600. #endif 1601. You("disentangle yourself."); 1602. } 1603. } else if (u.utraptype == TT_INFLOOR) { 1604. if(--u.utrap) { 1605. if(flags.verbose) { 1606. predicament = "stuck in the"; 1607. #ifdef STEED 1608. if (u.usteed) 1609. Norep("%s is %s %s.", 1610. upstart(y_monnam(u.usteed)), 1611. predicament, surface(u.ux, u.uy)); 1612. else 1613. #endif 1614. Norep("You are %s %s.", predicament, 1615. surface(u.ux, u.uy)); 1616. } 1617. } else { 1618. #ifdef STEED 1619. if (u.usteed) 1620. pline("%s finally wiggles free.", 1621. upstart(y_monnam(u.usteed))); 1622. else 1623. #endif 1624. You("finally wiggle free."); 1625. } 1626. } else { 1627. if(flags.verbose) { 1628. predicament = "caught in a bear trap"; 1629. #ifdef STEED 1630. if (u.usteed) 1631. Norep("%s is %s.", upstart(y_monnam(u.usteed)), 1632. predicament); 1633. else 1634. #endif 1635. Norep("You are %s.", predicament); 1636. } 1637. if((u.dx && u.dy) || !rn2(5)) u.utrap--; 1638. } 1639. return; 1640. } 1641. 1642. if (!test_move(u.ux, u.uy, x-u.ux, y-u.uy, DO_MOVE)) { 1643. flags.move = 0; 1644. nomul(0); 1645. return; 1646. } 1647. 1648. } else if (!test_move(u.ux, u.uy, x-u.ux, y-u.uy, TEST_MOVE)) { 1649. /* 1650. * If a monster attempted to displace us but failed 1651. * then we are entitled to our normal attack. 1652. */ 1653. if (!attack(mtmp)) { 1654. flags.move = 0; 1655. nomul(0); 1656. } 1657. return; 1658. } 1659. 1660. /* Move ball and chain. */ 1661. if (Punished) 1662. if (!drag_ball(x,y, &bc_control, &ballx, &bally, &chainx, &chainy, 1663. &cause_delay, TRUE)) 1664. return; 1665. 1666. /* Check regions entering/leaving */ 1667. if (!in_out_region(x,y)) { 1668. #if 0 1669. /* [ALI] This can't happen at present, but if it did we would 1670. * also need to worry about the call to drag_ball above. 1671. */ 1672. if (displacer) (void)attack(mtmp); 1673. #endif 1674. return; 1675. } 1676. 1677. /* now move the hero */ 1678. mtmp = m_at(x, y); 1679. u.ux += u.dx; 1680. u.uy += u.dy; 1681. #ifdef STEED 1682. /* Move your steed, too */ 1683. if (u.usteed) { 1684. u.usteed->mx = u.ux; 1685. u.usteed->my = u.uy; 1686. exercise_steed(); 1687. } 1688. #endif 1689. 1690. if (displacer) { 1691. char pnambuf[BUFSZ]; 1692. 1693. u.utrap = 0; /* A lucky escape */ 1694. /* save its current description in case of polymorph */ 1695. Strcpy(pnambuf, mon_nam(mtmp)); 1696. remove_monster(x, y); 1697. place_monster(mtmp, u.ux0, u.uy0); 1698. /* check for displacing it into pools and traps */ 1699. switch (minliquid(mtmp) ? 2 : mintrap(mtmp)) { 1700. case 0: 1701. You("displaced %s.", pnambuf); 1702. break; 1703. case 1: 1704. case 3: 1705. break; 1706. case 2: 1707. u.uconduct.killer++; 1708. break; 1709. } 1710. } 1711. 1712. /* 1713. * if safepet at destination then move the pet to the hero's 1714. * previous location using the same conditions as in attack(). 1715. * there are special extenuating circumstances: 1716. * (1) if the pet dies then your god angers, 1717. * (2) if the pet gets trapped then your god may disapprove, 1718. * (3) if the pet was already trapped and you attempt to free it 1719. * not only do you encounter the trap but you may frighten your 1720. * pet causing it to go wild! moral: don't abuse this privilege. 1721. * 1722. * Ceiling-hiding pets are skipped by this section of code, to 1723. * be caught by the normal falling-monster code. 1724. */ 1725. if (is_safepet(mtmp) && !(is_hider(mtmp->data) && mtmp->mundetected)) { 1726. /* if trapped, there's a chance the pet goes wild */ 1727. if (mtmp->mtrapped) { 1728. if (!rn2(mtmp->mtame)) { 1729. mtmp->mtame = mtmp->mpeaceful = mtmp->msleeping = 0; 1730. if (mtmp->mleashed) m_unleash(mtmp, TRUE); 1731. growl(mtmp); 1732. } else { 1733. yelp(mtmp); 1734. } 1735. } 1736. mtmp->mundetected = 0; 1737. if (mtmp->m_ap_type) seemimic(mtmp); 1738. else if (!mtmp->mtame) newsym(mtmp->mx, mtmp->my); 1739. 1740. if (mtmp->mtrapped && 1741. (trap = t_at(mtmp->mx, mtmp->my)) != 0 && 1742. (trap->ttyp == PIT || trap->ttyp == SPIKED_PIT) && 1743. sobj_at(BOULDER, trap->tx, trap->ty)) { 1744. /* can't swap places with pet pinned in a pit by a boulder */ 1745. u.ux = u.ux0, u.uy = u.uy0; /* didn't move after all */ 1746. } else if (u.ux0 != x && u.uy0 != y && 1747. bad_rock(mtmp, x, u.uy0) && 1748. bad_rock(mtmp, u.ux0, y) && 1749. (bigmonst(mtmp->data) || (curr_mon_load(mtmp) > 600))) { 1750. /* can't swap places when pet won't fit thru the opening */ 1751. u.ux = u.ux0, u.uy = u.uy0; /* didn't move after all */ 1752. You("stop. %s won't fit through.", upstart(y_monnam(mtmp))); 1753. } else { 1754. char pnambuf[BUFSZ]; 1755. 1756. /* save its current description in case of polymorph */ 1757. Strcpy(pnambuf, y_monnam(mtmp)); 1758. mtmp->mtrapped = 0; 1759. remove_monster(x, y); 1760. place_monster(mtmp, u.ux0, u.uy0); 1761. 1762. /* check for displacing it into pools and traps */ 1763. switch (minliquid(mtmp) ? 2 : mintrap(mtmp)) { 1764. case 0: 1765. You("%s %s.", mtmp->mtame ? "displaced" : "frightened", 1766. pnambuf); 1767. break; 1768. case 1: /* trapped */ 1769. case 3: /* changed levels */ 1770. /* there's already been a trap message, reinforce it */ 1771. abuse_dog(mtmp); 1772. adjalign(-3); 1773. break; 1774. case 2: 1775. /* it may have drowned or died. that's no way to 1776. * treat a pet! your god gets angry. 1777. */ 1778. if (rn2(4)) { 1779. You_feel("guilty about losing your pet like this."); 1780. u.ugangr++; 1781. adjalign(-15); 1782. } 1783. 1784. /* you killed your pet by direct action. 1785. * minliquid and mintrap don't know to do this 1786. */ 1787. u.uconduct.killer++; 1788. break; 1789. default: 1790. pline("that's strange, unknown mintrap result!"); 1791. break; 1792. } 1793. } 1794. } 1795. 1796. reset_occupations(); 1797. if (flags.run) { 1798. if ( flags.run < 8 ) 1799. if (IS_DOOR(tmpr->typ) || IS_ROCK(tmpr->typ) || 1800. IS_FURNITURE(tmpr->typ)) 1801. nomul(0); 1802. } 1803. 1804. if (hides_under(youmonst.data)) 1805. u.uundetected = OBJ_AT(u.ux, u.uy); 1806. else if (youmonst.data->mlet == S_EEL) 1807. u.uundetected = is_pool(u.ux, u.uy) && !Is_waterlevel(&u.uz); 1808. else if (u.dx || u.dy) 1809. u.uundetected = 0; 1810. 1811. /* 1812. * Mimics (or whatever) become noticeable if they move and are 1813. * imitating something that doesn't move. We could extend this 1814. * to non-moving monsters... 1815. */ 1816. if ((u.dx || u.dy) && (youmonst.m_ap_type == M_AP_OBJECT 1817. || youmonst.m_ap_type == M_AP_FURNITURE)) 1818. youmonst.m_ap_type = M_AP_NOTHING; 1819. 1820. check_leash(u.ux0,u.uy0); 1821. 1822. if(u.ux0 != u.ux || u.uy0 != u.uy) { 1823. u.umoved = TRUE; 1824. /* Clean old position -- vision_recalc() will print our new one. */ 1825. newsym(u.ux0,u.uy0); 1826. /* Since the hero has moved, adjust what can be seen/unseen. */ 1827. vision_recalc(1); /* Do the work now in the recover time. */ 1828. invocation_message(); 1829. } 1830. 1831. if (Punished) /* put back ball and chain */ 1832. move_bc(0,bc_control,ballx,bally,chainx,chainy); 1833. 1834. spoteffects(TRUE); 1835. 1836. /* delay next move because of ball dragging */ 1837. /* must come after we finished picking up, in spoteffects() */ 1838. if (cause_delay) { 1839. nomul(-2); 1840. nomovemsg = ""; 1841. } 1842. 1843. if (flags.run && iflags.runmode != RUN_TPORT) { 1844. /* display every step or every 7th step depending upon mode */ 1845. if (iflags.runmode != RUN_LEAP || !(moves % 7L)) { 1846. if (flags.time) flags.botl = 1; 1847. curs_on_u(); 1848. delay_output(); 1849. if (iflags.runmode == RUN_CRAWL) { 1850. delay_output(); 1851. delay_output(); 1852. delay_output(); 1853. delay_output(); 1854. } 1855. } 1856. } 1857. } 1858. 1859. void 1860. invocation_message() 1861. { 1862. /* a special clue-msg when on the Invocation position */ 1863. if(invocation_pos(u.ux, u.uy) && !On_stairs(u.ux, u.uy)) { 1864. char buf[BUFSZ]; 1865. struct obj *otmp = carrying(CANDELABRUM_OF_INVOCATION); 1866. 1867. nomul(0); /* stop running or travelling */ 1868. if (Hallucination) 1869. pline("You're picking up good vibrations!"); 1870. else { 1871. #ifdef STEED 1872. if (u.usteed) Sprintf(buf, "beneath %s", y_monnam(u.usteed)); 1873. else 1874. #endif 1875. if (Levitation || Flying) Strcpy(buf, "beneath you"); 1876. else Sprintf(buf, "under your %s", makeplural(body_part(FOOT))); 1877. 1878. You_feel("a strange vibration %s.", buf); 1879. } 1880. if (otmp && otmp->spe == 7 && otmp->lamplit) 1881. pline("%s %s!", The(xname(otmp)), 1882. Blind ? "throbs palpably" : "glows with a strange light"); 1883. } 1884. } 1885. 1886. #endif /* OVL3 */ 1887. #ifdef OVL2 1888. 1889. void 1890. spoteffects(pick) 1891. boolean pick; 1892. { 1893. register struct monst *mtmp; 1894. 1895. if(u.uinwater) { 1896. int was_underwater; 1897. 1898. if (!is_pool(u.ux,u.uy)) { 1899. if (Is_waterlevel(&u.uz)) 1900. You("pop into an air bubble."); 1901. else if (is_lava(u.ux, u.uy)) 1902. You("leave the water..."); /* oops! */ 1903. else 1904. You("are on solid %s again.", 1905. is_ice(u.ux, u.uy) ? "ice" : "land"); 1906. } 1907. else if (Is_waterlevel(&u.uz)) 1908. goto stillinwater; 1909. else if (Levitation) 1910. You("pop out of the water like a cork!"); 1911. /* KMH, balance patch -- new intrinsic */ 1912. else if (Flying) 1913. You("fly out of the water."); 1914. else if (Wwalking) 1915. You("slowly rise above the surface."); 1916. /* else if (Swimming) 1917. You("paddle up to the surface.");*/ 1918. else 1919. goto stillinwater; 1920. was_underwater = Underwater && !Is_waterlevel(&u.uz); 1921. u.uinwater = 0; /* leave the water */ 1922. if (was_underwater) { /* restore vision */ 1923. docrt(); 1924. vision_full_recalc = 1; 1925. } 1926. } 1927. stillinwater:; 1928. if (!Levitation && !u.ustuck && !Flying) { 1929. /* limit recursive calls through teleds() */ 1930. if (is_pool(u.ux, u.uy) || is_lava(u.ux, u.uy)) { 1931. #ifdef STEED 1932. if (u.usteed && !is_flyer(u.usteed->data) && 1933. !is_floater(u.usteed->data) && 1934. !is_clinger(u.usteed->data)) { 1935. dismount_steed(Underwater ? 1936. DISMOUNT_FELL : DISMOUNT_GENERIC); 1937. /* dismount_steed() -> float_down() -> pickup() */ 1938. if (!Is_airlevel(&u.uz) && !Is_waterlevel(&u.uz)) 1939. pick = FALSE; 1940. } else 1941. #endif 1942. if (is_lava(u.ux, u.uy)) { 1943. if (lava_effects()) return; 1944. } else if (!Wwalking && drown()) 1945. return; 1946. } 1947. } 1948. check_special_room(FALSE); 1949. #ifdef SINKS 1950. if(IS_SINK(levl[u.ux][u.uy].typ) && Levitation) 1951. dosinkfall(); 1952. #endif 1953. if (!in_steed_dismounting) { /* if dismounting, we'll check again later */ 1954. struct trap *trap = t_at(u.ux, u.uy); 1955. boolean pit; 1956. pit = (trap && (trap->ttyp == PIT || trap->ttyp == SPIKED_PIT)); 1957. if (trap && pit) 1958. dotrap(trap, 0); /* fall into pit */ 1959. if (pick) (void) pickup(1); 1960. if (trap && !pit) 1961. dotrap(trap, 0); /* fall into arrow trap, etc. */ 1962. } 1963. if((mtmp = m_at(u.ux, u.uy)) && !u.uswallow) { 1964. mtmp->mundetected = mtmp->msleeping = 0; 1965. switch(mtmp->data->mlet) { 1966. case S_PIERCER: 1967. pline("%s suddenly drops from the %s!", 1968. Amonnam(mtmp), ceiling(u.ux,u.uy)); 1969. if(mtmp->mtame) /* jumps to greet you, not attack */ 1970. ; 1971. else if(uarmh && is_metallic(uarmh)) 1972. pline("Its blow glances off your helmet."); 1973. else if (u.uac + 3 <= rnd(20)) 1974. You("are almost hit by %s!", 1975. x_monnam(mtmp, ARTICLE_A, "falling", 0, TRUE)); 1976. else { 1977. int dmg; 1978. You("are hit by %s!", 1979. x_monnam(mtmp, ARTICLE_A, "falling", 0, TRUE)); 1980. dmg = d(4,6); 1981. if(Half_physical_damage) dmg = (dmg+1) / 2; 1982. mdamageu(mtmp, dmg); 1983. } 1984. break; 1985. default: /* monster surprises you. */ 1986. if(mtmp->mtame) 1987. pline("%s jumps near you from the %s.", 1988. Amonnam(mtmp), ceiling(u.ux,u.uy)); 1989. else if(mtmp->mpeaceful) { 1990. You("surprise %s!", 1991. Blind && !sensemon(mtmp) ? 1992. something : a_monnam(mtmp)); 1993. mtmp->mpeaceful = 0; 1994. } else 1995. pline("%s attacks you by surprise!", 1996. Amonnam(mtmp)); 1997. break; 1998. } 1999. mnexto(mtmp); /* have to move the monster */ 2000. } 2001. } 2002. 2003. STATIC_OVL boolean 2004. monstinroom(mdat,roomno) 2005. struct permonst *mdat; 2006. int roomno; 2007. { 2008. register struct monst *mtmp; 2009. 2010. for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) 2011. if(!DEADMONSTER(mtmp) && mtmp->data == mdat && 2012. index(in_rooms(mtmp->mx, mtmp->my, 0), roomno + ROOMOFFSET)) 2013. return(TRUE); 2014. return(FALSE); 2015. } 2016. 2017. char * 2018. in_rooms(x, y, typewanted) 2019. register xchar x, y; 2020. register int typewanted; 2021. { 2022. static char buf[5]; 2023. char rno, *ptr = &buf[4]; 2024. int typefound, min_x, min_y, max_x, max_y_offset, step; 2025. register struct rm *lev; 2026. 2027. #define goodtype(rno) (!typewanted || \ 2028. ((typefound = rooms[rno - ROOMOFFSET].rtype) == typewanted) || \ 2029. ((typewanted == SHOPBASE) && (typefound > SHOPBASE))) \ 2030. 2031. switch (rno = levl[x][y].roomno) { 2032. case NO_ROOM: 2033. return(ptr); 2034. case SHARED: 2035. step = 2; 2036. break; 2037. case SHARED_PLUS: 2038. step = 1; 2039. break; 2040. default: /* i.e. a regular room # */ 2041. if (goodtype(rno)) 2042. *(--ptr) = rno; 2043. return(ptr); 2044. } 2045. 2046. min_x = x - 1; 2047. max_x = x + 1; 2048. if (x < 1) 2049. min_x += step; 2050. else 2051. if (x >= COLNO) 2052. max_x -= step; 2053. 2054. min_y = y - 1; 2055. max_y_offset = 2; 2056. if (min_y < 0) { 2057. min_y += step; 2058. max_y_offset -= step; 2059. } else 2060. if ((min_y + max_y_offset) >= ROWNO) 2061. max_y_offset -= step; 2062. 2063. for (x = min_x; x <= max_x; x += step) { 2064. lev = &levl[x][min_y]; 2065. y = 0; 2066. if (((rno = lev[y].roomno) >= ROOMOFFSET) && 2067. !index(ptr, rno) && goodtype(rno)) 2068. *(--ptr) = rno; 2069. y += step; 2070. if (y > max_y_offset) 2071. continue; 2072. if (((rno = lev[y].roomno) >= ROOMOFFSET) && 2073. !index(ptr, rno) && goodtype(rno)) 2074. *(--ptr) = rno; 2075. y += step; 2076. if (y > max_y_offset) 2077. continue; 2078. if (((rno = lev[y].roomno) >= ROOMOFFSET) && 2079. !index(ptr, rno) && goodtype(rno)) 2080. *(--ptr) = rno; 2081. } 2082. return(ptr); 2083. } 2084. 2085. /* is (x,y) in a town? */ 2086. boolean 2087. in_town(x, y) 2088. register int x, y; 2089. { 2090. s_level *slev = Is_special(&u.uz); 2091. register struct mkroom *sroom; 2092. boolean has_subrooms = FALSE; 2093. 2094. if (!slev || !slev->flags.town) return FALSE; 2095. 2096. /* 2097. * See if (x,y) is in a room with subrooms, if so, assume it's the 2098. * town. If there are no subrooms, the whole level is in town. 2099. */ 2100. for (sroom = &rooms[0]; sroom->hx > 0; sroom++) { 2101. if (sroom->nsubrooms > 0) { 2102. has_subrooms = TRUE; 2103. if (inside_room(sroom, x, y)) return TRUE; 2104. } 2105. } 2106. 2107. return !has_subrooms; 2108. } 2109. 2110. STATIC_OVL void 2111. move_update(newlev) 2112. register boolean newlev; 2113. { 2114. char *ptr1, *ptr2, *ptr3, *ptr4; 2115. 2116. Strcpy(u.urooms0, u.urooms); 2117. Strcpy(u.ushops0, u.ushops); 2118. if (newlev) { 2119. u.urooms[0] = '\0'; 2120. u.uentered[0] = '\0'; 2121. u.ushops[0] = '\0'; 2122. u.ushops_entered[0] = '\0'; 2123. Strcpy(u.ushops_left, u.ushops0); 2124. return; 2125. } 2126. Strcpy(u.urooms, in_rooms(u.ux, u.uy, 0)); 2127. 2128. for (ptr1 = &u.urooms[0], 2129. ptr2 = &u.uentered[0], 2130. ptr3 = &u.ushops[0], 2131. ptr4 = &u.ushops_entered[0]; 2132. *ptr1; ptr1++) { 2133. if (!index(u.urooms0, *ptr1)) 2134. *(ptr2++) = *ptr1; 2135. if (IS_SHOP(*ptr1 - ROOMOFFSET)) { 2136. *(ptr3++) = *ptr1; 2137. if (!index(u.ushops0, *ptr1)) 2138. *(ptr4++) = *ptr1; 2139. } 2140. } 2141. *ptr2 = '\0'; 2142. *ptr3 = '\0'; 2143. *ptr4 = '\0'; 2144. 2145. /* filter u.ushops0 -> u.ushops_left */ 2146. for (ptr1 = &u.ushops0[0], ptr2 = &u.ushops_left[0]; *ptr1; ptr1++) 2147. if (!index(u.ushops, *ptr1)) 2148. *(ptr2++) = *ptr1; 2149. *ptr2 = '\0'; 2150. } 2151. 2152. void 2153. check_special_room(newlev) 2154. register boolean newlev; 2155. { 2156. register struct monst *mtmp; 2157. char *ptr; 2158. 2159. move_update(newlev); 2160. 2161. if (*u.ushops0) 2162. u_left_shop(u.ushops_left, newlev); 2163. 2164. if (!*u.uentered && !*u.ushops_entered) /* implied by newlev */ 2165. return; /* no entrance messages necessary */ 2166. 2167. /* Did we just enter a shop? */ 2168. if (*u.ushops_entered) 2169. u_entered_shop(u.ushops_entered); 2170. 2171. for (ptr = &u.uentered[0]; *ptr; ptr++) { 2172. register int roomno = *ptr - ROOMOFFSET, rt = rooms[roomno].rtype; 2173. 2174. /* Did we just enter some other special room? */ 2175. /* vault.c insists that a vault remain a VAULT, 2176. * and temples should remain TEMPLEs, 2177. * but everything else gives a message only the first time */ 2178. switch (rt) { 2179. case ZOO: 2180. pline("Welcome to David's treasure zoo!"); 2181. break; 2182. case SWAMP: 2183. pline("It %s rather %s down here.", 2184. Blind ? "feels" : "looks", 2185. Blind ? "humid" : "muddy"); 2186. break; 2187. case COURT: 2188. You("enter an opulent throne room!"); 2189. break; 2190. case REALZOO: 2191. You("enter a smelly zoo!"); 2192. break; 2193. case GIANTCOURT: 2194. You("enter a giant throne room!"); 2195. break; 2196. case DRAGONLAIR: 2197. You("enter a dragon lair..."); 2198. break; 2199. case BADFOODSHOP: 2200. You("enter an abandoned store..."); 2201. break; 2202. case LEPREHALL: 2203. You("enter a leprechaun hall!"); 2204. break; 2205. case MORGUE: 2206. if(midnight()) { 2207. const char *run = locomotion(youmonst.data, "Run"); 2208. pline("%s away! %s away!", run, run); 2209. } else 2210. You("have an uncanny feeling..."); 2211. break; 2212. case BEEHIVE: 2213. You("enter a giant beehive!"); 2214. break; 2215. case LEMUREPIT: 2216. You("enter a pit of screaming lemures!"); 2217. break; 2218. case MIGOHIVE: 2219. You("enter a strange hive!"); 2220. break; 2221. case FUNGUSFARM: 2222. You("enter a room full of fungi!"); 2223. break; 2224. case COCKNEST: 2225. You("enter a disgusting nest!"); 2226. break; 2227. case ANTHOLE: 2228. You("enter an anthole!"); 2229. break; 2230. case BARRACKS: 2231. if(monstinroom(&mons[PM_SOLDIER], roomno) || 2232. monstinroom(&mons[PM_SERGEANT], roomno) || 2233. monstinroom(&mons[PM_LIEUTENANT], roomno) || 2234. monstinroom(&mons[PM_CAPTAIN], roomno)) 2235. You("enter a military barracks!"); 2236. else 2237. You("enter an abandoned barracks."); 2238. break; 2239. case DELPHI: 2240. if(monstinroom(&mons[PM_ORACLE], roomno)) 2241. verbalize("%s, %s, welcome to Delphi!", 2242. Hello((struct monst *) 0), plname); 2243. break; 2244. case TEMPLE: 2245. intemple(roomno + ROOMOFFSET); 2246. /* fall through */ 2247. default: 2248. rt = 0; 2249. } 2250. 2251. if (rt != 0) { 2252. rooms[roomno].rtype = OROOM; 2253. if (!search_special(rt)) { 2254. /* No more room of that type */ 2255. switch(rt) { 2256. case COURT: 2257. case GIANTCOURT: 2258. level.flags.has_court = 0; 2259. break; 2260. case SWAMP: 2261. level.flags.has_swamp = 0; 2262. break; 2263. case MORGUE: 2264. level.flags.has_morgue = 0; 2265. break; 2266. case ZOO: 2267. case REALZOO: 2268. level.flags.has_zoo = 0; 2269. break; 2270. case BARRACKS: 2271. level.flags.has_barracks = 0; 2272. break; 2273. case TEMPLE: 2274. level.flags.has_temple = 0; 2275. break; 2276. case BEEHIVE: 2277. level.flags.has_beehive = 0; 2278. break; 2279. case LEMUREPIT: 2280. level.flags.has_lemurepit = 0; 2281. break; 2282. case MIGOHIVE: 2283. level.flags.has_migohive = 0; 2284. break; 2285. case FUNGUSFARM: 2286. level.flags.has_fungusfarm = 0; 2287. break; 2288. } 2289. } 2290. if(rt==COURT || rt==SWAMP || rt==MORGUE || rt==ZOO) 2291. for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) 2292. if (!DEADMONSTER(mtmp) && !Stealth && !rn2(3)) mtmp->msleeping = 0; 2293. } 2294. } 2295. 2296. return; 2297. } 2298. 2299. #endif /* OVL2 */ 2300. #ifdef OVLB 2301. 2302. int 2303. dopickup() 2304. { 2305. int count; 2306. struct trap *traphere = t_at(u.ux, u.uy); 2307. /* awful kludge to work around parse()'s pre-decrement */ 2308. count = (multi || (save_cm && *save_cm == ',')) ? multi + 1 : 0; 2309. multi = 0; /* always reset */ 2310. /* uswallow case added by GAN 01/29/87 */ 2311. if(u.uswallow) { 2312. if (!u.ustuck->minvent) { 2313. if (is_animal(u.ustuck->data)) { 2314. You("pick up %s tongue.", 2315. s_suffix(mon_nam(u.ustuck))); 2316. pline("But it's kind of slimy, so you drop it."); 2317. } else 2318. You("don't %s anything in here to pick up.", 2319. Blind ? "feel" : "see"); 2320. return(1); 2321. } else { 2322. int tmpcount = -count; 2323. return loot_mon(u.ustuck, &tmpcount, (boolean *)0); 2324. } 2325. } 2326. if(is_pool(u.ux, u.uy)) { 2327. if (Wwalking || is_floater(youmonst.data) || is_clinger(youmonst.data) 2328. || (Flying && !Breathless)) { 2329. You("cannot dive into the water to pick things up."); 2330. return(0); 2331. } else if (!Underwater) { 2332. You_cant("even see the bottom, let alone pick up %s.", 2333. something); 2334. return(0); 2335. } 2336. } 2337. if (is_lava(u.ux, u.uy)) { 2338. if (Wwalking || is_floater(youmonst.data) || is_clinger(youmonst.data) 2339. || (Flying && !Breathless)) { 2340. You_cant("reach the bottom to pick things up."); 2341. return(0); 2342. } else if (!likes_lava(youmonst.data)) { 2343. You("would burn to a crisp trying to pick things up."); 2344. return(0); 2345. } 2346. } 2347. if(!OBJ_AT(u.ux, u.uy)) { 2348. There("is nothing here to pick up."); 2349. return(0); 2350. } 2351. if (!can_reach_floor()) { 2352. #ifdef STEED 2353. if (u.usteed && P_SKILL(P_RIDING) < P_BASIC) 2354. You("aren't skilled enough to reach from %s.", 2355. y_monnam(u.usteed)); 2356. else 2357. #endif 2358. You("cannot reach the %s.", surface(u.ux,u.uy)); 2359. return(0); 2360. } 2361. 2362. if (traphere && traphere->tseen) { 2363. /* Allow pickup from holes and trap doors that you escaped from 2364. * because that stuff is teetering on the edge just like you, but 2365. * not pits, because there is an elevation discrepancy with stuff 2366. * in pits. 2367. */ 2368. if ((traphere->ttyp == PIT || traphere->ttyp == SPIKED_PIT) && 2369. (!u.utrap || (u.utrap && u.utraptype != TT_PIT))) { 2370. You("cannot reach the bottom of the pit."); 2371. return(0); 2372. } 2373. } 2374. 2375. return (pickup(-count)); 2376. } 2377. 2378. #endif /* OVLB */ 2379. #ifdef OVL2 2380. 2381. /* stop running if we see something interesting */ 2382. /* turn around a corner if that is the only way we can proceed */ 2383. /* do not turn left or right twice */ 2384. void 2385. lookaround() 2386. { 2387. register int x, y, i, x0 = 0, y0 = 0, m0 = 1, i0 = 9; 2388. register int corrct = 0, noturn = 0; 2389. register struct monst *mtmp; 2390. register struct trap *trap; 2391. 2392. /* Grid bugs stop if trying to move diagonal, even if blind. Maybe */ 2393. /* they polymorphed while in the middle of a long move. */ 2394. if (u.umonnum == PM_GRID_BUG && u.dx && u.dy) { 2395. nomul(0); 2396. return; 2397. } 2398. 2399. if(Blind || flags.run == 0) return; 2400. for(x = u.ux-1; x <= u.ux+1; x++) for(y = u.uy-1; y <= u.uy+1; y++) { 2401. if(!isok(x,y)) continue; 2402. 2403. if(u.umonnum == PM_GRID_BUG && x != u.ux && y != u.uy) continue; 2404. 2405. if(x == u.ux && y == u.uy) continue; 2406. 2407. if((mtmp = m_at(x,y)) && 2408. mtmp->m_ap_type != M_AP_FURNITURE && 2409. mtmp->m_ap_type != M_AP_OBJECT && 2410. (!mtmp->minvis || See_invisible) && !mtmp->mundetected) { 2411. if((flags.run != 1 && !mtmp->mtame) 2412. || (x == u.ux+u.dx && y == u.uy+u.dy)) 2413. goto stop; 2414. } 2415. 2416. if (levl[x][y].typ == STONE) continue; 2417. if (x == u.ux-u.dx && y == u.uy-u.dy) continue; 2418. 2419. if (IS_ROCK(levl[x][y].typ) || (levl[x][y].typ == ROOM) || 2420. IS_AIR(levl[x][y].typ)) 2421. continue; 2422. else if (closed_door(x,y) || 2423. (mtmp && mtmp->m_ap_type == M_AP_FURNITURE && 2424. (mtmp->mappearance == S_hcdoor || 2425. mtmp->mappearance == S_vcdoor))) { 2426. if(x != u.ux && y != u.uy) continue; 2427. if(flags.run != 1) goto stop; 2428. goto bcorr; 2429. } else if (levl[x][y].typ == CORR) { 2430. bcorr: 2431. if(levl[u.ux][u.uy].typ != ROOM) { 2432. if(flags.run == 1 || flags.run == 3 || flags.run == 8) { 2433. i = dist2(x,y,u.ux+u.dx,u.uy+u.dy); 2434. if(i > 2) continue; 2435. if(corrct == 1 && dist2(x,y,x0,y0) != 1) 2436. noturn = 1; 2437. if(i < i0) { 2438. i0 = i; 2439. x0 = x; 2440. y0 = y; 2441. m0 = mtmp ? 1 : 0; 2442. } 2443. } 2444. corrct++; 2445. } 2446. continue; 2447. } else if ((trap = t_at(x,y)) && trap->tseen) { 2448. if(flags.run == 1) goto bcorr; /* if you must */ 2449. if(x == u.ux+u.dx && y == u.uy+u.dy) goto stop; 2450. continue; 2451. } else if (is_pool(x,y) || is_lava(x,y)) { 2452. /* water and lava only stop you if directly in front, and stop 2453. * you even if you are running 2454. */ 2455. /* KMH, balance patch -- new intrinsic */ 2456. if(!Levitation && !Flying && !is_clinger(youmonst.data) && 2457. x == u.ux+u.dx && y == u.uy+u.dy) 2458. /* No Wwalking check; otherwise they'd be able 2459. * to test boots by trying to SHIFT-direction 2460. * into a pool and seeing if the game allowed it 2461. */ 2462. goto stop; 2463. continue; 2464. } else { /* e.g. objects or trap or stairs */ 2465. if(flags.run == 1) goto bcorr; 2466. if(flags.run == 8) continue; 2467. if(mtmp) continue; /* d */ 2468. if(((x == u.ux - u.dx) && (y != u.uy + u.dy)) || 2469. ((y == u.uy - u.dy) && (x != u.ux + u.dx))) 2470. continue; 2471. } 2472. stop: 2473. nomul(0); 2474. return; 2475. } /* end for loops */ 2476. 2477. if(corrct > 1 && flags.run == 2) goto stop; 2478. if((flags.run == 1 || flags.run == 3 || flags.run == 8) && 2479. !noturn && !m0 && i0 && (corrct == 1 || (corrct == 2 && i0 == 1))) 2480. { 2481. /* make sure that we do not turn too far */ 2482. if(i0 == 2) { 2483. if(u.dx == y0-u.uy && u.dy == u.ux-x0) 2484. i = 2; /* straight turn right */ 2485. else 2486. i = -2; /* straight turn left */ 2487. } else if(u.dx && u.dy) { 2488. if((u.dx == u.dy && y0 == u.uy) || (u.dx != u.dy && y0 != u.uy)) 2489. i = -1; /* half turn left */ 2490. else 2491. i = 1; /* half turn right */ 2492. } else { 2493. if((x0-u.ux == y0-u.uy && !u.dy) || (x0-u.ux != y0-u.uy && u.dy)) 2494. i = 1; /* half turn right */ 2495. else 2496. i = -1; /* half turn left */ 2497. } 2498. 2499. i += u.last_str_turn; 2500. if(i <= 2 && i >= -2) { 2501. u.last_str_turn = i; 2502. u.dx = x0-u.ux; 2503. u.dy = y0-u.uy; 2504. } 2505. } 2506. } 2507. 2508. /* something like lookaround, but we are not running */ 2509. /* react only to monsters that might hit us */ 2510. int 2511. monster_nearby() 2512. { 2513. register int x,y; 2514. register struct monst *mtmp; 2515. 2516. /* Also see the similar check in dochugw() in monmove.c */ 2517. for(x = u.ux-1; x <= u.ux+1; x++) 2518. for(y = u.uy-1; y <= u.uy+1; y++) { 2519. if(!isok(x,y)) continue; 2520. if(x == u.ux && y == u.uy) continue; 2521. if((mtmp = m_at(x,y)) && 2522. mtmp->m_ap_type != M_AP_FURNITURE && 2523. mtmp->m_ap_type != M_AP_OBJECT && 2524. (!mtmp->mpeaceful || Hallucination) && 2525. (!is_hider(mtmp->data) || !mtmp->mundetected) && 2526. !noattacks(mtmp->data) && 2527. mtmp->mcanmove && !mtmp->msleeping && /* aplvax!jcn */ 2528. !onscary(u.ux, u.uy, mtmp) && 2529. canspotmon(mtmp)) 2530. return(1); 2531. } 2532. return(0); 2533. } 2534. 2535. STATIC_OVL void 2536. maybe_wail() 2537. { 2538. static short powers[] = { TELEPORT, SEE_INVIS, POISON_RES, COLD_RES, 2539. SHOCK_RES, FIRE_RES, SLEEP_RES, DISINT_RES, 2540. TELEPORT_CONTROL, STEALTH, FAST, INVIS }; 2541. 2542. if (moves <= wailmsg + 50) return; 2543. 2544. wailmsg = moves; 2545. if (Role_if(PM_WIZARD) || Race_if(PM_ELF) || Role_if(PM_VALKYRIE)) { 2546. const char *who; 2547. int i, powercnt; 2548. 2549. who = (Role_if(PM_WIZARD) || Role_if(PM_VALKYRIE)) ? 2550. urole.name.m : "Elf"; 2551. if (u.uhp == 1) { 2552. pline("%s is about to die.", who); 2553. } else { 2554. for (i = 0, powercnt = 0; i < SIZE(powers); ++i) 2555. if (u.uprops[powers[i]].intrinsic & INTRINSIC) ++powercnt; 2556. 2557. pline(powercnt >= 4 ? "%s, all your powers will be lost..." 2558. : "%s, your life force is running out.", who); 2559. } 2560. } else { 2561. You_hear(u.uhp == 1 ? "the wailing of the Banshee..." 2562. : "the howling of the CwnAnnwn..."); 2563. } 2564. } 2565. 2566. void 2567. nomul(nval) 2568. register int nval; 2569. { 2570. if(multi < nval) return; /* This is a bug fix by ab@unido */ 2571. u.uinvulnerable = FALSE; /* Kludge to avoid ctrl-C bug -dlc */ 2572. u.usleep = 0; 2573. multi = nval; 2574. flags.travel = iflags.travel1 = flags.mv = flags.run = 0; 2575. } 2576. 2577. /* called when a non-movement, multi-turn action has completed */ 2578. void 2579. unmul(msg_override) 2580. const char *msg_override; 2581. { 2582. multi = 0; /* caller will usually have done this already */ 2583. if (msg_override) nomovemsg = msg_override; 2584. else if (!nomovemsg) nomovemsg = You_can_move_again; 2585. if (*nomovemsg) pline(nomovemsg); 2586. nomovemsg = 0; 2587. u.usleep = 0; 2588. if (afternmv) (*afternmv)(); 2589. afternmv = 0; 2590. } 2591. 2592. #endif /* OVL2 */ 2593. #ifdef OVL1 2594. 2595. 2596. #ifdef SHOW_DMG 2597. /* Print the amount of damage inflicted */ 2598. /* KMH -- Centralized to one function */ 2599. void 2600. showdmg(n) 2601. register int n; 2602. { 2603. int lev; 2604. 2605. 2606. if (flags.showdmg && n > 1) { 2607. switch (Role_switch) { 2608. case PM_BARBARIAN: case PM_MONK: lev = 10; break; 2609. case PM_CAVEMAN: case PM_VALKYRIE: lev = 12; break; 2610. case PM_SAMURAI: case PM_KNIGHT: lev = 14; break; 2611. default: lev = 17; break; 2612. } 2613. switch (Race_switch) { 2614. case PM_GNOME: if (lev > 14) lev = 14; break; 2615. } 2616. #ifdef WIZARD 2617. if (wizard) lev = 1; 2618. #endif 2619. if(u.ulevel >= lev) 2620. pline("(%d pts.)", n); 2621. } 2622. return; 2623. } 2624. #endif 2625. 2626. 2627. void 2628. losehp(n, knam, k_format) 2629. register int n; 2630. register const char *knam; 2631. int k_format; /* WAC k_format is an int */ 2632. { 2633. /* [max] Invulnerable no dmg */ 2634. if (Invulnerable) { 2635. n = 0; 2636. pline("You are unharmed!"); 2637. /* NOTE: DO NOT RETURN - losehp is also called to check for death 2638. * via u.uhp < 1 2639. */ 2640. } 2641. #ifdef SHOW_DMG 2642. else if (flags.showdmg && n > 0) pline("[%d pts.]", n); /* WAC see damage */ 2643. #endif 2644. 2645. if (Upolyd) { 2646. u.mh -= n; 2647. if (u.mhmax < u.mh) u.mhmax = u.mh; 2648. if (u.mh < 1) 2649. rehumanize(); 2650. else if (n > 0 && u.mh*10 < u.mhmax && Unchanging) 2651. maybe_wail(); 2652. return; 2653. } else { 2654. u.uhp -= n; 2655. if(u.uhp > u.uhpmax) 2656. u.uhpmax = u.uhp; /* perhaps n was negative */ 2657. } 2658. 2659. flags.botl = 1; /* Update status bar */ 2660. 2661. if(u.uhp < 1) { 2662. killer_format = k_format; 2663. killer = knam; /* the thing that killed you */ 2664. You("die..."); 2665. done(DIED); 2666. } else if (n > 0 && u.uhp*10 < u.uhpmax) { 2667. maybe_wail(); 2668. } 2669. } 2670. 2671. int 2672. weight_cap() 2673. { 2674. register long carrcap; 2675. 2676. carrcap = 25*(ACURRSTR + ACURR(A_CON)) + 50; 2677. if (Upolyd) { 2678. /* consistent with can_carry() in mon.c */ 2679. if (youmonst.data->mlet == S_NYMPH) 2680. carrcap = MAX_CARR_CAP; 2681. else if (!youmonst.data->cwt) 2682. carrcap = (carrcap * (long)youmonst.data->msize) / MZ_HUMAN; 2683. else if (!strongmonst(youmonst.data) 2684. || (strongmonst(youmonst.data) && (youmonst.data->cwt > WT_HUMAN))) 2685. carrcap = (carrcap * (long)youmonst.data->cwt / WT_HUMAN); 2686. } 2687. 2688. if (Levitation || Is_airlevel(&u.uz) /* pugh@cornell */ 2689. #ifdef STEED 2690. || (u.usteed && strongmonst(u.usteed->data)) 2691. #endif 2692. ) 2693. carrcap = MAX_CARR_CAP; 2694. else { 2695. if(carrcap > MAX_CARR_CAP) carrcap = MAX_CARR_CAP; 2696. if (!Flying) { 2697. if(EWounded_legs & LEFT_SIDE) carrcap -= 100; 2698. if(EWounded_legs & RIGHT_SIDE) carrcap -= 100; 2699. } 2700. if (carrcap < 0) carrcap = 0; 2701. } 2702. return((int) carrcap); 2703. } 2704. 2705. static int wc; /* current weight_cap(); valid after call to inv_weight() */ 2706. 2707. /* returns how far beyond the normal capacity the player is currently. */ 2708. /* inv_weight() is negative if the player is below normal capacity. */ 2709. int 2710. inv_weight() 2711. { 2712. register struct obj *otmp = invent; 2713. register int wt = 0; 2714. 2715. #ifndef GOLDOBJ 2716. /* when putting stuff into containers, gold is inserted at the head 2717. of invent for easier manipulation by askchain & co, but it's also 2718. retained in u.ugold in order to keep the status line accurate; we 2719. mustn't add its weight in twice under that circumstance */ 2720. wt = (otmp && otmp->oclass == COIN_CLASS) ? 0 : 2721. (int)((u.ugold + 50L) / 100L); 2722. #endif 2723. while (otmp) { 2724. #ifndef GOLDOBJ 2725. if (otmp->otyp != BOULDER || !throws_rocks(youmonst.data)) 2726. #else 2727. if (otmp->oclass == COIN_CLASS) 2728. wt += (int)(((long)otmp->quan + 50L) / 100L); 2729. else if (otmp->otyp != BOULDER || !throws_rocks(youmonst.data)) 2730. #endif 2731. wt += otmp->owt; 2732. otmp = otmp->nobj; 2733. } 2734. wc = weight_cap(); 2735. return (wt - wc); 2736. } 2737. 2738. /* 2739. * Returns 0 if below normal capacity, or the number of "capacity units" 2740. * over the normal capacity the player is loaded. Max is 5. 2741. */ 2742. int 2743. calc_capacity(xtra_wt) 2744. int xtra_wt; 2745. { 2746. int cap, wt = inv_weight() + xtra_wt; 2747. 2748. if (wt <= 0) return UNENCUMBERED; 2749. if (wc <= 1) return OVERLOADED; 2750. cap = (wt*2 / wc) + 1; 2751. return min(cap, OVERLOADED); 2752. } 2753. 2754. int 2755. near_capacity() 2756. { 2757. return calc_capacity(0); 2758. } 2759. 2760. int 2761. max_capacity() 2762. { 2763. int wt = inv_weight(); 2764. 2765. return (wt - (2 * wc)); 2766. } 2767. 2768. boolean 2769. check_capacity(str) 2770. const char *str; 2771. { 2772. if(near_capacity() >= EXT_ENCUMBER) { 2773. if(str) 2774. pline(str); 2775. else 2776. You_cant("do that while carrying so much stuff."); 2777. return 1; 2778. } 2779. return 0; 2780. } 2781. 2782. #endif /* OVL1 */ 2783. #ifdef OVLB 2784. 2785. int 2786. inv_cnt() 2787. { 2788. register struct obj *otmp = invent; 2789. register int ct = 0; 2790. 2791. while(otmp){ 2792. ct++; 2793. otmp = otmp->nobj; 2794. } 2795. return(ct); 2796. } 2797. 2798. #ifdef GOLDOBJ 2799. /* Counts the money in an object chain. */ 2800. /* Intended use is for your or some monsters inventory, */ 2801. /* now that u.gold/m.gold is gone.*/ 2802. /* Counting money in a container might be possible too. */ 2803. long 2804. money_cnt(otmp) 2805. struct obj *otmp; 2806. { 2807. while(otmp) { 2808. /* Must change when silver & copper is implemented: */ 2809. if (otmp->oclass == COIN_CLASS) return otmp->quan; 2810. otmp = otmp->nobj; 2811. } 2812. return 0; 2813. } 2814. #endif 2815. #endif /* OVLB */ 2816. 2817. /*hack.c*/
|