abstract
| - Below is the full text to dig.c from the source code of NetHack 3.2.0. To link to a particular line, write [[NetHack 3.2.0/dig.c#line123]], for example. Warning! This is the source code from an old release. For the latest release, see Source code 1. /* SCCS Id: @(#)dig.c 3.2 96/03/15 */ 2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3. /* NetHack may be freely redistributed. See license for details. */ 4. 5. #include "hack.h" 6. #include "edog.h" 7. /* #define DEBUG /* turn on for diagnostics */ 8. 9. #ifdef OVLB 10. 11. static NEARDATA boolean did_dig_msg; 12. 13. static boolean NDECL(rm_waslit); 14. static void FDECL(mkcavepos, (XCHAR_P,XCHAR_P,int,BOOLEAN_P,BOOLEAN_P)); 15. static void FDECL(mkcavearea, (BOOLEAN_P)); 16. static int FDECL(dig_typ, (XCHAR_P,XCHAR_P)); 17. STATIC_DCL int NDECL(dig); 18. STATIC_DCL schar FDECL(fillholetyp, (int, int)); 19. 20. static boolean 21. rm_waslit() 22. { 23. register xchar x, y; 24. 25. if(levl[u.ux][u.uy].typ == ROOM && levl[u.ux][u.uy].waslit) 26. return(TRUE); 27. for(x = u.ux-2; x < u.ux+3; x++) 28. for(y = u.uy-1; y < u.uy+2; y++) 29. if(isok(x,y) && levl[x][y].waslit) return(TRUE); 30. return(FALSE); 31. } 32. 33. /* Change level topology. Messes with vision tables and ignores things like 34. * boulders in the name of a nice effect. Vision will get fixed up again 35. * immediately after the effect is complete. 36. */ 37. static void 38. mkcavepos(x, y, dist, waslit, rockit) 39. xchar x,y; 40. int dist; 41. boolean waslit, rockit; 42. { 43. register struct rm *lev; 44. 45. if(!isok(x,y)) return; 46. lev = &levl[x][y]; 47. 48. if(rockit) { 49. register struct monst *mtmp; 50. 51. if(IS_ROCK(lev->typ)) return; 52. if(t_at(x, y)) return; /* don't cover the portal */ 53. if ((mtmp = m_at(x, y)) != 0) /* make sure crucial monsters survive */ 54. if(!passes_walls(mtmp->data)) rloc(mtmp); 55. } else if(lev->typ == ROOM) return; 56. 57. unblock_point(x,y); /* make sure vision knows this location is open */ 58. 59. /* fake out saved state */ 60. lev->seenv = 0; 61. lev->doormask = 0; 62. if(dist < 3) lev->lit = (rockit ? FALSE : TRUE); 63. if(waslit) lev->waslit = (rockit ? FALSE : TRUE); 64. lev->horizontal = FALSE; 65. viz_array[y][x] = (dist < 3 ) ? 66. (IN_SIGHT|COULD_SEE) : /* short-circuit vision recalc */ 67. COULD_SEE; 68. lev->typ = (rockit ? STONE : ROOM); 69. if(dist >= 3) 70. impossible("mkcavepos called with dist %d", dist); 71. if(Blind) 72. feel_location(x, y); 73. else newsym(x,y); 74. } 75. 76. static void 77. mkcavearea(rockit) 78. register boolean rockit; 79. { 80. int dist; 81. xchar xmin = u.ux, xmax = u.ux; 82. xchar ymin = u.uy, ymax = u.uy; 83. register xchar i; 84. register boolean waslit = rm_waslit(); 85. 86. if(rockit) pline("Crash! The ceiling collapses around you!"); 87. else pline("A mysterious force %s cave around you!", 88. (levl[u.ux][u.uy].typ == CORR) ? "creates a" : "extends the"); 89. display_nhwindow(WIN_MESSAGE, TRUE); 90. 91. for(dist = 1; dist <= 2; dist++) { 92. xmin--; xmax++; 93. 94. /* top and bottom */ 95. if(dist < 2) { /* the area is wider that it is high */ 96. ymin--; ymax++; 97. for(i = xmin+1; i < xmax; i++) { 98. mkcavepos(i, ymin, dist, waslit, rockit); 99. mkcavepos(i, ymax, dist, waslit, rockit); 100. } 101. } 102. 103. /* left and right */ 104. for(i = ymin; i <= ymax; i++) { 105. mkcavepos(xmin, i, dist, waslit, rockit); 106. mkcavepos(xmax, i, dist, waslit, rockit); 107. } 108. 109. flush_screen(1); /* make sure the new glyphs shows up */ 110. delay_output(); 111. } 112. 113. if(!rockit && levl[u.ux][u.uy].typ == CORR) { 114. levl[u.ux][u.uy].typ = ROOM; 115. if(waslit) levl[u.ux][u.uy].waslit = TRUE; 116. newsym(u.ux, u.uy); /* in case player is invisible */ 117. } 118. 119. vision_full_recalc = 1; /* everything changed */ 120. } 121. 122. /* When digging into location , what are you actually digging into? */ 123. /* result: 1=>statue, 2=>boulder, 3=>door, 0=>other; used as array index */ 124. static int 125. dig_typ(x, y) 126. xchar x, y; 127. { 128. return (sobj_at(STATUE, x, y) ? 1 : 129. sobj_at(BOULDER, x, y) ? 2 : 130. closed_door(x, y) ? 3 : 0); 131. } 132. 133. #define BY_YOU (&youmonst) 134. #define BY_OBJECT ((struct monst *)0) 135. 136. boolean 137. dig_check(madeby, verbose, x, y) 138. struct monst *madeby; 139. boolean verbose; 140. int x, y; 141. { 142. struct trap *ttmp; 143. 144. if (On_stairs(x, y)) { 145. if (x == xdnladder || x == xupladder) { 146. if(verbose) pline_The("ladder resists your effort."); 147. } else if(verbose) pline_The("stairs are too hard to dig in."); 148. return(FALSE); 149. } else if (IS_THRONE(levl[x][y].typ) && madeby != BY_OBJECT) { 150. if(verbose) pline_The("throne is too hard to break apart."); 151. return(FALSE); 152. } else if (IS_ALTAR(levl[x][y].typ) && (madeby != BY_OBJECT || 153. Is_astralevel(&u.uz) || Is_sanctum(&u.uz))) { 154. if(verbose) pline_The("altar is too hard to break apart."); 155. return(FALSE); 156. } else if (Is_airlevel(&u.uz)) { 157. if(verbose) You("cannot dig in thin air."); 158. return(FALSE); 159. } else if (Is_waterlevel(&u.uz)) { 160. if(verbose) pline_The("water splashes and subsides."); 161. return(FALSE); 162. } else if ((IS_WALL(levl[x][y].typ) 163. && (levl[x][y].wall_info & W_NONDIGGABLE) != 0) 164. || ((ttmp = t_at(x, y)) != 0 && 165. (ttmp->ttyp == MAGIC_PORTAL || !Can_dig_down(&u.uz)))) { 166. if(verbose) pline_The("%s here is too hard to dig in.", 167. surface(x,y)); 168. return(FALSE); 169. } else if (sobj_at(BOULDER, x, y)) { 170. if(verbose) pline("There isn't enough room to dig here."); 171. return(FALSE); 172. } else if (madeby == BY_OBJECT && (is_pool(x,y) || is_lava(x,y))) { 173. /* digging by player handles pools separately */ 174. return FALSE; 175. } 176. return(TRUE); 177. } 178. 179. STATIC_OVL int 180. dig() 181. { 182. register struct rm *lev; 183. register xchar dpx = digging.pos.x, dpy = digging.pos.y; 184. 185. lev = &levl[dpx][dpy]; 186. /* perhaps a nymph stole your pick-axe while you were busy digging */ 187. /* or perhaps you teleported away */ 188. if (u.uswallow || !uwep || uwep->otyp != PICK_AXE || 189. !on_level(&digging.level, &u.uz) || 190. ((digging.down ? (dpx != u.ux || dpy != u.uy) 191. : (distu(dpx,dpy) > 2)))) 192. return(0); 193. 194. if (digging.down) { 195. if(!dig_check(BY_YOU, TRUE, u.ux, u.uy)) return(0); 196. } else { /* !digging.down */ 197. if (IS_ROCK(lev->typ) && !may_dig(dpx,dpy) && !dig_typ(dpx, dpy)) { 198. pline("This wall is too hard to dig into."); 199. return(0); 200. } 201. } 202. if(Fumbling && !rn2(3)) { 203. switch(rn2(3)) { 204. case 0: if(!welded(uwep)) { 205. You("fumble and drop your %s.", xname(uwep)); 206. dropx(uwep); 207. setuwep((struct obj *)0); 208. } else { 209. pline("Ouch! Your %s bounces and hits you!", 210. xname(uwep)); 211. set_wounded_legs(RIGHT_SIDE, 5 + rnd(5)); 212. } 213. break; 214. case 1: pline("Bang! You hit with the broad side of %s!", 215. the(xname(uwep))); 216. break; 217. default: Your("swing misses its mark."); 218. break; 219. } 220. return(0); 221. } 222. 223. digging.effort += 10 + rn2(5) + abon() + 224. uwep->spe - uwep->oeroded + u.udaminc; 225. if (digging.down) { 226. register struct trap *ttmp; 227. 228. if (digging.effort > 250) { 229. (void) dighole(FALSE); 230. (void) memset((genericptr_t)&digging, 0, sizeof digging); 231. return(0); /* done with digging */ 232. } 233. 234. if (digging.effort <= 50 || 235. ((ttmp = t_at(dpx,dpy)) != 0 && 236. (ttmp->ttyp == PIT || ttmp->ttyp == SPIKED_PIT || 237. ttmp->ttyp == TRAPDOOR || ttmp->ttyp == HOLE))) 238. return(1); 239. 240. if (IS_ALTAR(lev->typ)) { 241. altar_wrath(dpx, dpy); 242. angry_priest(); 243. } 244. 245. if (dighole(TRUE)) { /* make pit at */ 246. digging.level.dnum = 0; 247. digging.level.dlevel = -1; 248. } 249. return(0); 250. } 251. 252. if (digging.effort > 100) { 253. register const char *digtxt, *dmgtxt = (const char*) 0; 254. register struct obj *obj; 255. register boolean shopedge = *in_rooms(dpx, dpy, SHOPBASE); 256. 257. if ((obj = sobj_at(STATUE, dpx, dpy)) != 0) { 258. if (break_statue(obj)) 259. digtxt = "The statue shatters."; 260. else 261. /* it was a statue trap; break_statue() 262. * printed a message and updated the screen 263. */ 264. digtxt = (char *)0; 265. } else if ((obj = sobj_at(BOULDER, dpx, dpy)) != 0) { 266. fracture_rock(obj); 267. digtxt = "The boulder falls apart."; 268. } else if (lev->typ == STONE || lev->typ == SCORR) { 269. if(Is_earthlevel(&u.uz)) { 270. if(uwep->blessed && !rn2(3)) { 271. mkcavearea(FALSE); 272. goto cleanup; 273. } else if((uwep->cursed && !rn2(4)) || 274. (!uwep->blessed && !rn2(6))) { 275. mkcavearea(TRUE); 276. goto cleanup; 277. } 278. } 279. lev->typ = CORR; 280. digtxt = "You succeed in cutting away some rock."; 281. } else if(IS_WALL(lev->typ)) { 282. if(shopedge) { 283. add_damage(dpx, dpy, 10L * ACURRSTR); 284. dmgtxt = "damage"; 285. } 286. if (level.flags.is_maze_lev) { 287. lev->typ = ROOM; 288. } else if (level.flags.is_cavernous_lev) { 289. lev->typ = CORR; 290. } else { 291. lev->typ = DOOR; 292. lev->doormask = D_NODOOR; 293. } 294. digtxt = "You make an opening in the wall."; 295. } else if(lev->typ == SDOOR) { 296. lev->typ = DOOR; 297. lev->doormask = exposed_sdoor_mask(lev); 298. digtxt = "You break through a secret door!"; 299. if(!(lev->doormask & D_TRAPPED)) 300. lev->doormask = D_BROKEN; 301. } else if(closed_door(dpx, dpy)) { 302. digtxt = "You break through the door."; 303. if(shopedge) { 304. add_damage(dpx, dpy, 400L); 305. dmgtxt = "break"; 306. } 307. if(!(lev->doormask & D_TRAPPED)) 308. lev->doormask = D_BROKEN; 309. } else return(0); /* statue or boulder got taken */ 310. 311. unblock_point(dpx,dpy); /* vision: can see through */ 312. if(Blind) 313. feel_location(dpx, dpy); 314. else 315. newsym(dpx, dpy); 316. if(digtxt) pline(digtxt); /* after newsym */ 317. if(dmgtxt) 318. pay_for_damage(dmgtxt); 319. 320. if(Is_earthlevel(&u.uz) && !rn2(3)) { 321. register struct monst *mtmp; 322. 323. switch(rn2(2)) { 324. case 0: 325. mtmp = makemon(&mons[PM_EARTH_ELEMENTAL], dpx, dpy); 326. break; 327. default: 328. mtmp = makemon(&mons[PM_XORN], dpx, dpy); 329. break; 330. } 331. if(mtmp) pline_The("debris from your digging comes to life!"); 332. } 333. if(IS_DOOR(lev->typ) && (lev->doormask & D_TRAPPED)) { 334. lev->doormask = D_NODOOR; 335. b_trapped("door", 0); 336. newsym(dpx, dpy); 337. } 338. cleanup: 339. digging.level.dnum = 0; 340. digging.level.dlevel = -1; 341. return(0); 342. } else { /* not enough effort has been spent yet */ 343. static const char *d_target[4] = { 344. "rock", "statue", "boulder", "door" 345. }; 346. int dig_target = dig_typ(dpx, dpy); 347. 348. if (IS_WALL(lev->typ) || dig_target == 3) { 349. if(*in_rooms(dpx, dpy, SHOPBASE)) { 350. pline("This %s seems too hard to dig into.", 351. IS_DOOR(lev->typ) ? "door" : "wall"); 352. return(0); 353. } 354. } else if (!IS_ROCK(lev->typ) && !dig_target) 355. return(0); /* statue or boulder got taken */ 356. if(!did_dig_msg) { 357. You("hit the %s with all your might.", 358. d_target[dig_target]); 359. did_dig_msg = TRUE; 360. } 361. } 362. return(1); 363. } 364. 365. /* When will hole be finished? Very rough indication used by shopkeeper. */ 366. int 367. holetime() 368. { 369. if(occupation != dig || !*u.ushops) return(-1); 370. return ((250 - digging.effort) / 20); 371. } 372. 373. /* Return typ of liquid to fill a hole with, or ROOM, if no liquid nearby */ 374. STATIC_OVL 375. schar 376. fillholetyp(x,y) 377. int x, y; 378. { 379. register int x1, y1; 380. int lo_x = max(1,x-1), hi_x = min(x+1,COLNO-1), 381. lo_y = max(0,y-1), hi_y = min(y+1,ROWNO-1); 382. int pool_cnt = 0, moat_cnt = 0, lava_cnt = 0; 383. 384. for (x1 = lo_x; x1 <= hi_x; x1++) 385. for (y1 = lo_y; y1 <= hi_y; y1++) 386. if (levl[x1][y1].typ == POOL) 387. pool_cnt++; 388. else if (levl[x1][y1].typ == MOAT || 389. (levl[x1][y1].typ == DRAWBRIDGE_UP && 390. (levl[x1][y1].drawbridgemask & DB_UNDER) == DB_MOAT)) 391. moat_cnt++; 392. else if (levl[x1][y1].typ == LAVAPOOL || 393. (levl[x1][y1].typ == DRAWBRIDGE_UP && 394. (levl[x1][y1].drawbridgemask & DB_UNDER) == DB_LAVA)) 395. lava_cnt++; 396. pool_cnt /= 3; /* not as much liquid as the others */ 397. 398. if (lava_cnt > moat_cnt + pool_cnt && rn2(lava_cnt + 1)) 399. return LAVAPOOL; 400. else if (moat_cnt > 0 && rn2(moat_cnt + 1)) 401. return MOAT; 402. else if (pool_cnt > 0 && rn2(pool_cnt + 1)) 403. return POOL; 404. else 405. return ROOM; 406. } 407. 408. void 409. digactualhole(x, y, madeby, ttyp) 410. register int x, y; 411. struct monst *madeby; 412. int ttyp; 413. { 414. struct obj *oldobjs, *newobjs; 415. register struct trap *ttmp; 416. char surface_type[BUFSZ]; 417. struct rm *lev = &levl[x][y]; 418. boolean shopdoor; 419. struct monst *mtmp = m_at(x, y); /* may be madeby */ 420. boolean madeby_u = (madeby == BY_YOU); 421. boolean madeby_obj = (madeby == BY_OBJECT); 422. boolean at_u = (x == u.ux) && (y == u.uy); 423. boolean wont_fall = Levitation || is_flyer(uasmon); 424. 425. /* these furniture checks were in dighole(), but wand 426. breaking bypasses that routine and calls us directly */ 427. if (IS_FOUNTAIN(lev->typ)) { 428. dogushforth(FALSE); 429. lev->looted |= F_WARNED; /* force dryup */ 430. dryup(x, y); 431. return; 432. #ifdef SINKS 433. } else if (IS_SINK(lev->typ)) { 434. breaksink(x, y); 435. return; 436. #endif 437. } 438. 439. Strcpy(surface_type, surface(x,y)); /* maketrap() might change it */ 440. shopdoor = IS_DOOR(lev->typ) && *in_rooms(x, y, SHOPBASE); 441. oldobjs = level.objects[x][y]; 442. ttmp = maketrap(x, y, ttyp); 443. if (!ttmp) return; 444. newobjs = level.objects[x][y]; 445. ttmp->tseen = (madeby_u || cansee(x,y)); 446. ttmp->madeby_u = madeby_u; 447. newsym(ttmp->tx,ttmp->ty); 448. 449. if (ttyp == PIT) { 450. 451. if(madeby_u) { 452. You("dig a pit in the %s.", surface_type); 453. if (shopdoor) pay_for_damage("ruin"); 454. } else if (!madeby_obj && canseemon(madeby)) 455. pline("%s digs a pit in the %s.", Monnam(madeby), surface_type); 456. else if (cansee(x, y) && flags.verbose) 457. pline("A pit appears in the %s.", surface_type); 458. 459. if(at_u) { 460. if (!wont_fall) { 461. u.utrap = rn1(4,2); 462. u.utraptype = TT_PIT; 463. vision_full_recalc = 1; /* vision limits change */ 464. } else 465. u.utrap = 0; 466. if (oldobjs != newobjs) /* something unearthed */ 467. pickup(1); /* detects pit */ 468. } else if(mtmp) { 469. if(is_flyer(mtmp->data) || is_floater(mtmp->data)) { 470. if(canseemon(mtmp)) 471. pline("%s %s over the pit.", Monnam(mtmp), 472. (is_flyer(mtmp->data)) ? 473. "flies" : "floats"); 474. } else if(mtmp != madeby) 475. (void) mintrap(mtmp); 476. } 477. } else { /* was TRAPDOOR now a HOLE*/ 478. if (!Can_fall_thru(&u.uz)) 479. panic("Holes & trapdoors cannot exist on this level."); 480. 481. if(madeby_u) 482. You("dig a hole through the %s.", surface_type); 483. else if(!madeby_obj && canseemon(madeby)) 484. pline("%s digs a hole through the %s.", 485. Monnam(madeby), surface_type); 486. else if(cansee(x, y) && flags.verbose) 487. pline("A hole appears in the %s.", surface_type); 488. 489. if (at_u) { 490. if (!u.ustuck && !wont_fall && !next_to_u()) { 491. You("are jerked back by your pet!"); 492. wont_fall = TRUE; 493. } 494. 495. /* Floor objects get a chance of falling down. The case where 496. * the hero does NOT fall down is treated here. The case 497. * where the hero does fall down is treated in goto_level(). 498. */ 499. if (u.ustuck || wont_fall) { 500. if (newobjs) 501. impact_drop((struct obj *)0, x, y, 0); 502. if (oldobjs != newobjs) 503. pickup(1); 504. if (shopdoor && madeby_u) pay_for_damage("ruin"); 505. 506. } else { 507. d_level newlevel; 508. 509. if (*u.ushops && madeby_u) 510. shopdig(1); /* shk might snatch pack */ 511. 512. You("fall through..."); 513. /* Earlier checks must ensure that the destination 514. * level exists and is in the present dungeon. 515. */ 516. newlevel.dnum = u.uz.dnum; 517. newlevel.dlevel = u.uz.dlevel + 1; 518. goto_level(&newlevel, FALSE, TRUE, FALSE); 519. } 520. } else { 521. if (shopdoor && madeby_u) pay_for_damage("ruin"); 522. if (newobjs) 523. impact_drop((struct obj *)0, x, y, 0); 524. if (mtmp) { 525. 526. if (is_flyer(mtmp->data) || is_floater(mtmp->data) || 527. mtmp->data == &mons[PM_WUMPUS] || 528. (mtmp->wormno && count_wsegs(mtmp) > 5) || 529. mtmp->data->msize >= MZ_HUGE) return; 530. if (mtmp == u.ustuck) /* probably a vortex */ 531. return; /* temporary? kludge */ 532. 533. if (teleport_pet(mtmp)) { 534. d_level tolevel; 535. 536. if (Is_stronghold(&u.uz)) { 537. assign_level(&tolevel, &valley_level); 538. } else if (Is_botlevel(&u.uz)) { 539. if (canseemon(mtmp)) 540. pline("%s avoids the trap.", Monnam(mtmp)); 541. return; 542. } else { 543. get_level(&tolevel, depth(&u.uz) + 1); 544. } 545. migrate_to_level(mtmp, ledger_no(&tolevel), 546. MIGR_RANDOM, (coord *)0); 547. } 548. } 549. } 550. } 551. } 552. 553. /* return TRUE if digging succeeded, FALSE otherwise */ 554. boolean 555. dighole(pit_only) 556. boolean pit_only; 557. { 558. register struct trap *ttmp = t_at(u.ux, u.uy); 559. struct rm *lev = &levl[u.ux][u.uy]; 560. struct obj *boulder_here; 561. schar typ; 562. boolean nohole = !Can_dig_down(&u.uz); 563. 564. if ((ttmp && (ttmp->ttyp == MAGIC_PORTAL || nohole)) || 565. (IS_WALL(lev->typ) && (lev->wall_info & W_NONDIGGABLE) != 0)) { 566. pline_The("%s here is too hard to dig in.", surface(u.ux,u.uy)); 567. 568. } else if (is_pool(u.ux, u.uy) || is_lava(u.ux, u.uy)) { 569. pline_The("%s sloshes furiously for a moment, then subsides.", 570. is_lava(u.ux, u.uy) ? "lava" : "water"); 571. wake_nearby(); /* splashing */ 572. 573. } else if (lev->typ == DRAWBRIDGE_DOWN || 574. (is_drawbridge_wall(u.ux, u.uy) >= 0)) { 575. /* drawbridge_down is the platform crossing the moat when the 576. bridge is extended; drawbridge_wall is the open "doorway" or 577. closed "door" where the portcullis/mechanism is located */ 578. if (pit_only) { 579. pline_The("drawbridge seems too hard to dig through."); 580. return FALSE; 581. } else { 582. int x = u.ux, y = u.uy; 583. /* if under the portcullis, the bridge is adjacent */ 584. (void) find_drawbridge(&x, &y); 585. destroy_drawbridge(x, y); 586. return TRUE; 587. } 588. 589. } else if ((boulder_here = sobj_at(BOULDER, u.ux, u.uy)) != 0) { 590. if (ttmp && (ttmp->ttyp == PIT || ttmp->ttyp == SPIKED_PIT) && 591. rn2(2)) { 592. pline_The("boulder settles into the pit."); 593. ttmp->ttyp = PIT; /* crush spikes */ 594. } else { 595. /* 596. * digging makes a hole, but the boulder immediately 597. * fills it. Final outcome: no hole, no boulder. 598. */ 599. pline("KADOOM! The boulder falls in!"); 600. (void) delfloortrap(ttmp); 601. } 602. delobj(boulder_here); 603. return TRUE; 604. 605. } else if (lev->typ == DRAWBRIDGE_UP) { 606. /* must be floor or ice, other cases handled above */ 607. /* dig "pit" and let fluid flow in (if possible) */ 608. typ = fillholetyp(u.ux,u.uy); 609. 610. if (typ == ROOM) { 611. /* 612. * We can't dig a hole here since that will destroy 613. * the drawbridge. The following is a cop-out. --dlc 614. */ 615. pline_The("%s here is too hard to dig in.", 616. surface(u.ux, u.uy)); 617. return FALSE; 618. } 619. 620. lev->drawbridgemask &= ~DB_UNDER; 621. lev->drawbridgemask |= (typ == LAVAPOOL) ? DB_LAVA : DB_MOAT; 622. 623. liquid_flow: 624. if (ttmp) (void) delfloortrap(ttmp); 625. /* if any objects were frozen here, they're released now */ 626. unearth_objs(u.ux, u.uy); 627. 628. pline("As you dig, the hole fills with %s!", 629. typ == LAVAPOOL ? "lava" : "water"); 630. if (!Levitation && !is_flyer(uasmon)) { 631. if (typ == LAVAPOOL) 632. (void) lava_effects(); 633. else if (!Wwalking) 634. (void) drown(); 635. } 636. return TRUE; 637. 638. /* the following two are here for the wand of digging */ 639. } else if (IS_THRONE(lev->typ)) { 640. pline_The("throne is too hard to break apart."); 641. 642. } else if (IS_ALTAR(lev->typ)) { 643. pline_The("altar is too hard to break apart."); 644. 645. } else { 646. typ = fillholetyp(u.ux,u.uy); 647. 648. if (typ != ROOM) { 649. lev->typ = typ; 650. goto liquid_flow; 651. } 652. 653. /* finally we get to make a hole */ 654. if (nohole || pit_only) 655. digactualhole(u.ux, u.uy, BY_YOU, PIT); 656. else 657. digactualhole(u.ux, u.uy, BY_YOU, HOLE); 658. 659. return TRUE; 660. } 661. 662. return FALSE; 663. } 664. 665. int 666. use_pick_axe(obj) 667. struct obj *obj; 668. { 669. char dirsyms[12]; 670. char qbuf[QBUFSZ]; 671. register char *dsp = dirsyms; 672. register struct rm *lev; 673. register int rx, ry; 674. int dig_target, res = 0; 675. register const char *sdp; 676. if(flags.num_pad) sdp = ndir; else sdp = sdir; /* DICE workaround */ 677. 678. if (obj != uwep) { 679. if (!wield_tool(obj)) return(0); 680. else res = 1; 681. } 682. if (u.utrap && u.utraptype == TT_WEB) { 683. pline("%s you can't dig while entangled in a web.", 684. /* res==0 => no prior message; 685. res==1 => just got "You now wield a pick-axe." message */ 686. !res ? "Unfortunately," : "But"); 687. return res; 688. } 689. 690. while(*sdp) { 691. (void) movecmd(*sdp); /* sets u.dx and u.dy and u.dz */ 692. rx = u.ux + u.dx; 693. ry = u.uy + u.dy; 694. if(u.dz > 0 || (u.dz == 0 && isok(rx, ry) && 695. (IS_ROCK(levl[rx][ry].typ) || dig_typ(rx, ry)))) 696. *dsp++ = *sdp; 697. sdp++; 698. } 699. *dsp = 0; 700. Sprintf(qbuf, "In what direction do you want to dig? [%s]", dirsyms); 701. if(!getdir(qbuf)) 702. return(res); 703. if (u.uswallow && attack(u.ustuck)) { 704. ; /* return(1) */ 705. } else if (Underwater) { 706. pline("Turbulence torpedoes your digging attempts."); 707. } else if(u.dz < 0) { 708. if(Levitation) 709. You("don't have enough leverage."); 710. else 711. You_cant("reach the %s.",ceiling(u.ux,u.uy)); 712. } else if(!u.dx && !u.dy && !u.dz) { 713. char buf[BUFSZ]; 714. int dam; 715. 716. dam = rnd(2) + dbon() + obj->spe; 717. if (dam <= 0) dam = 1; 718. You("hit yourself with your pick-axe."); 719. /* self_pronoun() won't work twice in a sentence */ 720. Strcpy(buf, self_pronoun("killed %sself with %%s pick-axe", 721. "him")); 722. losehp(dam, self_pronoun(buf, "his"), NO_KILLER_PREFIX); 723. flags.botl=1; 724. return(1); 725. } else if(u.dz == 0) { 726. if(Stunned || (Confusion && !rn2(5))) confdir(); 727. rx = u.ux + u.dx; 728. ry = u.uy + u.dy; 729. if(!isok(rx, ry)) { 730. pline("Clash!"); 731. return(1); 732. } 733. lev = &levl[rx][ry]; 734. if(MON_AT(rx, ry) && attack(m_at(rx, ry))) 735. return(1); 736. dig_target = dig_typ(rx, ry); 737. if (!IS_ROCK(lev->typ) && !dig_target) { 738. /* ACCESSIBLE or POOL */ 739. struct trap *trap = t_at(rx, ry); 740. 741. if (trap && trap->ttyp == WEB) { 742. if (!trap->tseen) { 743. seetrap(trap); 744. pline("There is a spider web there!"); 745. } 746. Your("%s becomes entangled in the web.", 747. aobjnam(obj, (char *)0)); 748. /* you ought to be able to let go; tough luck */ 749. /* (maybe `move_into_trap()' would be better) */ 750. nomul(-d(2,2)); 751. nomovemsg = "You pull free."; 752. } else 753. You("swing your %s through thin air.", 754. aobjnam(obj, (char *)0)); 755. } else { 756. static const char *d_action[4] = { 757. "digging", 758. "chipping the statue", 759. "hitting the boulder", 760. "chopping at the door" 761. }; 762. if (digging.pos.x != rx || digging.pos.y != ry || 763. !on_level(&digging.level, &u.uz) || digging.down) { 764. digging.down = digging.chew = FALSE; 765. digging.pos.x = rx; 766. digging.pos.y = ry; 767. assign_level(&digging.level, &u.uz); 768. digging.effort = 0; 769. You("start %s.", d_action[dig_target]); 770. } else { 771. You("%s %s.", digging.chew ? "begin" : "continue", 772. d_action[dig_target]); 773. digging.chew = FALSE; 774. } 775. did_dig_msg = FALSE; 776. set_occupation(dig, "digging", 0); 777. } 778. } else if (Is_airlevel(&u.uz) || Is_waterlevel(&u.uz)) { 779. /* it must be air -- water checked above */ 780. You("swing your %s through thin air.", aobjnam(obj, (char *)0)); 781. } else if (!can_reach_floor()) { 782. You_cant("reach the %s.", surface(u.ux,u.uy)); 783. } else if (is_pool(u.ux, u.uy)) { 784. /* Monsters which swim also happen not to be able to dig */ 785. You("cannot stay underwater long enough."); 786. } else { 787. if (digging.pos.x != u.ux || digging.pos.y != u.uy || 788. !on_level(&digging.level, &u.uz) || !digging.down) { 789. digging.chew = FALSE; 790. digging.down = TRUE; 791. digging.pos.x = u.ux; 792. digging.pos.y = u.uy; 793. assign_level(&digging.level, &u.uz); 794. digging.effort = 0; 795. You("start digging downward."); 796. if (*u.ushops) shopdig(0); 797. } else 798. You("continue digging downward."); 799. did_dig_msg = FALSE; 800. set_occupation(dig, "digging", 0); 801. } 802. return(1); 803. } 804. 805. #endif /* OVLB */ 806. #ifdef OVL0 807. 808. /* Return TRUE if monster died, FALSE otherwise. Called from m_move(). */ 809. boolean 810. mdig_tunnel(mtmp) 811. register struct monst *mtmp; 812. { 813. register struct rm *here; 814. int pile; 815. 816. here = &levl[mtmp->mx][mtmp->my]; 817. if (here->typ == SDOOR) { 818. here->typ = DOOR; 819. here->doormask = exposed_sdoor_mask(here); 820. } 821. 822. /* Eats away door if present & closed or locked */ 823. if (closed_door(mtmp->mx, mtmp->my)) { 824. if (*in_rooms(mtmp->mx, mtmp->my, SHOPBASE)) 825. add_damage(mtmp->mx, mtmp->my, 0L); 826. unblock_point(mtmp->mx, mtmp->my); /* vision */ 827. if (here->doormask & D_TRAPPED) { 828. here->doormask = D_NODOOR; 829. if (mb_trapped(mtmp)) { /* mtmp is killed */ 830. newsym(mtmp->mx, mtmp->my); 831. return TRUE; 832. } 833. } else { 834. if (!rn2(3) && flags.verbose) /* not too often.. */ 835. You_feel("an unexpected draft."); 836. here->doormask = D_BROKEN; 837. } 838. newsym(mtmp->mx, mtmp->my); 839. return FALSE; 840. } else 841. if (!IS_ROCK(here->typ)) /* no dig */ 842. return FALSE; 843. 844. /* Only rock and walls fall through to this point. */ 845. if ((here->wall_info & W_NONDIGGABLE) != 0) { 846. impossible("mdig_tunnel: %s at (%d,%d) is undiggable", 847. (IS_WALL(here->typ) ? "wall" : "stone"), 848. (int) mtmp->mx, (int) mtmp->my); 849. return FALSE; /* still alive */ 850. } 851. 852. if (IS_WALL(here->typ)) { 853. if (flags.soundok && flags.verbose && !rn2(5)) 854. You_hear("crashing rock."); 855. if (*in_rooms(mtmp->mx, mtmp->my, SHOPBASE)) 856. add_damage(mtmp->mx, mtmp->my, 0L); 857. if (level.flags.is_maze_lev) { 858. here->typ = ROOM; 859. } else if (level.flags.is_cavernous_lev) { 860. here->typ = CORR; 861. } else { 862. here->typ = DOOR; 863. here->doormask = D_NODOOR; 864. } 865. } else 866. here->typ = CORR; 867. 868. pile = rnd(12); 869. if (pile < 5) /* leave behind some rocks? */ 870. (void) mksobj_at((pile == 1) ? BOULDER : ROCK, 871. mtmp->mx, mtmp->my, TRUE); 872. newsym(mtmp->mx, mtmp->my); 873. if (!sobj_at(BOULDER, mtmp->mx, mtmp->my)) 874. unblock_point(mtmp->mx, mtmp->my); /* vision */ 875. 876. return FALSE; 877. } 878. 879. #endif /* OVL0 */ 880. #ifdef OVL3 881. 882. /* digging via wand zap or spell cast */ 883. void 884. zap_dig() 885. { 886. struct rm *room; 887. struct monst *mtmp; 888. struct obj *otmp; 889. int zx, zy, digdepth; 890. boolean shopdoor, shopwall, maze_dig; 891. /* 892. * Original effect (approximately): 893. * from CORR: dig until we pierce a wall 894. * from ROOM: pierce wall and dig until we reach 895. * an ACCESSIBLE place. 896. * Currently: dig for digdepth positions; 897. * also down on request of Lennart Augustsson. 898. */ 899. 900. if (u.uswallow) { 901. mtmp = u.ustuck; 902. 903. if (!is_whirly(mtmp->data)) { 904. if (is_animal(mtmp->data)) 905. You("pierce %s stomach wall!", s_suffix(mon_nam(mtmp))); 906. mtmp->mhp = 1; /* almost dead */ 907. expels(mtmp, mtmp->data, !is_animal(mtmp->data)); 908. } 909. return; 910. } /* swallowed */ 911. 912. if (u.dz) { 913. if (!Is_airlevel(&u.uz) && !Is_waterlevel(&u.uz)) { 914. if (u.dz < 0 || On_stairs(u.ux, u.uy)) { 915. if (On_stairs(u.ux, u.uy)) 916. pline_The("beam bounces off the %s and hits the %s.", 917. (u.ux == xdnladder || u.ux == xupladder) ? 918. "ladder" : "stairs", ceiling(u.ux, u.uy)); 919. You("loosen a rock from the %s.", ceiling(u.ux, u.uy)); 920. pline("It falls on your %s!", body_part(HEAD)); 921. losehp(1, "falling rock", KILLED_BY_AN); 922. if ((otmp = mksobj_at(ROCK, u.ux, u.uy, FALSE)) != 0) { 923. (void)xname(otmp); /* set dknown, maybe bknown */ 924. stackobj(otmp); 925. } 926. if (Invisible) newsym(u.ux, u.uy); 927. } else { 928. (void) dighole(FALSE); 929. } 930. } 931. return; 932. } /* up or down */ 933. 934. /* normal case: digging across the level */ 935. shopdoor = shopwall = FALSE; 936. maze_dig = level.flags.is_maze_lev && !Is_earthlevel(&u.uz); 937. zx = u.ux + u.dx; 938. zy = u.uy + u.dy; 939. digdepth = rn1(18, 8); 940. tmp_at(DISP_BEAM, cmap_to_glyph(S_digbeam)); 941. while (--digdepth >= 0) { 942. if (!isok(zx,zy)) break; 943. room = &levl[zx][zy]; 944. tmp_at(zx,zy); 945. delay_output(); /* wait a little bit */ 946. if (closed_door(zx, zy) || room->typ == SDOOR) { 947. if (*in_rooms(zx,zy,SHOPBASE)) { 948. add_damage(zx, zy, 400L); 949. shopdoor = TRUE; 950. } 951. if (room->typ == SDOOR) 952. room->typ = DOOR; 953. else if (cansee(zx, zy)) 954. pline_The("door is razed!"); 955. room->doormask = D_NODOOR; 956. unblock_point(zx,zy); /* vision */ 957. digdepth -= 2; 958. if (maze_dig) break; 959. } else if (maze_dig) { 960. if (IS_WALL(room->typ)) { 961. if (!(room->wall_info & W_NONDIGGABLE)) { 962. if (*in_rooms(zx,zy,SHOPBASE)) { 963. add_damage(zx, zy, 200L); 964. shopwall = TRUE; 965. } 966. room->typ = ROOM; 967. unblock_point(zx,zy); /* vision */ 968. } else if (!Blind) 969. pline_The("wall glows then fades."); 970. break; 971. } else if (room->typ == STONE || room->typ == SCORR) { 972. if (!(room->wall_info & W_NONDIGGABLE)) { 973. room->typ = CORR; 974. unblock_point(zx,zy); /* vision */ 975. } else if (!Blind) 976. pline_The("rock glows then fades."); 977. break; 978. } 979. } else if (IS_ROCK(room->typ)) { 980. if (!may_dig(zx,zy)) break; 981. if (IS_WALL(room->typ) || room->typ == SDOOR) { 982. if (*in_rooms(zx,zy,SHOPBASE)) { 983. add_damage(zx, zy, 200L); 984. shopwall = TRUE; 985. } 986. if (level.flags.is_cavernous_lev) { 987. room->typ = CORR; 988. } else { 989. room->typ = DOOR; 990. room->doormask = D_NODOOR; 991. } 992. digdepth -= 2; 993. } else { /* IS_ROCK but not IS_WALL or SDOOR */ 994. room->typ = CORR; 995. digdepth--; 996. } 997. unblock_point(zx,zy); /* vision */ 998. } 999. zx += u.dx; 1000. zy += u.dy; 1001. } /* while */ 1002. tmp_at(DISP_END,0); /* closing call */ 1003. if (shopdoor || shopwall) 1004. pay_for_damage(shopdoor ? "destroy" : "dig into"); 1005. return; 1006. } 1007. 1008. /* move objects from fobj/nexthere lists to buriedobjlist, keeping position */ 1009. /* information */ 1010. struct obj * 1011. bury_an_obj(otmp) 1012. struct obj *otmp; 1013. { 1014. struct obj *otmp2; 1015. boolean under_ice; 1016. 1017. #ifdef DEBUG 1018. pline("bury_an_obj: %s", xname(otmp)); 1019. #endif 1020. if (otmp == uball) 1021. unpunish(); 1022. /* after unpunish(), or might get deallocated chain */ 1023. otmp2 = otmp->nexthere; 1024. /* 1025. * obj_resists(,0,0) prevents Rider corpses from being buried. 1026. * It also prevents The Amulet and invocation tools from being 1027. * buried. Since they can't be confined to bags and statues, 1028. * it makes sense that they can't be buried either, even though 1029. * the real reason there (direct accessibility when carried) is 1030. * completely different. 1031. */ 1032. if (otmp == uchain || obj_resists(otmp, 0, 0)) 1033. return(otmp2); 1034. 1035. if (otmp->otyp == LEASH && otmp->leashmon != 0) 1036. o_unleash(otmp); 1037. 1038. if (otmp->lamplit && otmp->otyp != POT_OIL) 1039. end_burn(otmp, TRUE); 1040. 1041. obj_extract_self(otmp); 1042. 1043. under_ice = is_ice(otmp->ox, otmp->oy); 1044. if (otmp->otyp == ROCK && !under_ice) { 1045. /* merges into burying material */ 1046. obfree(otmp, (struct obj *)0); 1047. return(otmp2); 1048. } 1049. /* 1050. * Start a rot on organic material. Not corpses -- they 1051. * are already handled. 1052. */ 1053. if (otmp->otyp == CORPSE) { 1054. ; /* should cancel timer if under_ice */ 1055. } else if ((under_ice ? otmp->oclass == POTION_CLASS : is_organic(otmp)) 1056. && !obj_resists(otmp, 5, 95)) { 1057. (void) start_timer((under_ice ? 0L : 250L) + (long)rnd(250), 1058. TIMER_OBJECT, ROT_ORGANIC, (genericptr_t)otmp); 1059. } 1060. add_to_buried(otmp); 1061. return(otmp2); 1062. } 1063. 1064. void 1065. bury_objs(x, y) 1066. int x, y; 1067. { 1068. struct obj *otmp, *otmp2; 1069. 1070. #ifdef DEBUG 1071. if(level.objects[x][y] != (struct obj *)0) 1072. pline("bury_objs: at %d, %d", x, y); 1073. #endif 1074. for (otmp = level.objects[x][y]; otmp; otmp = otmp2) 1075. otmp2 = bury_an_obj(otmp); 1076. 1077. /* don't expect any engravings here, but just in case */ 1078. del_engr_at(x, y); 1079. newsym(x, y); 1080. } 1081. 1082. /* move objects from buriedobjlist to fobj/nexthere lists */ 1083. void 1084. unearth_objs(x, y) 1085. int x, y; 1086. { 1087. struct obj *otmp, *otmp2; 1088. 1089. #ifdef DEBUG 1090. pline("unearth_objs: at %d, %d", x, y); 1091. #endif 1092. for (otmp = level.buriedobjlist; otmp; otmp = otmp2) { 1093. otmp2 = otmp->nobj; 1094. if (otmp->ox == x && otmp->oy == y) { 1095. obj_extract_self(otmp); 1096. if (otmp->timed) 1097. (void) stop_timer(ROT_ORGANIC, (genericptr_t)otmp); 1098. place_object(otmp, x, y); 1099. stackobj(otmp); 1100. } 1101. } 1102. del_engr_at(x, y); 1103. newsym(x, y); 1104. } 1105. 1106. /* 1107. * The organic material has rotted away while buried. As an expansion, 1108. * we could add add partial damage. A damage count is kept in the object 1109. * and every time we are called we increment the count and reschedule another 1110. * timeout. Eventually the object rots away. 1111. * 1112. * This is used by buried objects. This has a different entry in the 1113. * table than rot_corpse() because the rot stops when unearthed. 1114. */ 1115. /* ARGSUSED */ 1116. void 1117. rot_organic(arg, timeout) 1118. genericptr_t arg; 1119. long timeout; /* unused */ 1120. { 1121. struct obj *obj = (struct obj *) arg; 1122. 1123. obj_extract_self(obj); 1124. obfree(obj, (struct obj *) 0); 1125. } 1126. 1127. /* 1128. * See rot_organic above. This needs to be different from rot_organic, 1129. * even though they act the same. 1130. */ 1131. void 1132. rot_corpse(arg, timeout) 1133. genericptr_t arg; 1134. long timeout; /* unused */ 1135. { 1136. xchar x = 0, y = 0; 1137. struct obj *obj = (struct obj *) arg; 1138. boolean on_floor = obj->where == OBJ_FLOOR, 1139. in_invent = obj->where == OBJ_INVENT; 1140. 1141. if (on_floor) { 1142. x = obj->ox; 1143. y = obj->oy; 1144. } else if (in_invent) { 1145. if (flags.verbose) 1146. Your("%s%s rot%s away%c", 1147. obj == uwep ? "wielded " : "", corpse_xname(obj, FALSE), 1148. obj->quan == 1L ? "s" : "", obj == uwep ? '!' : '.'); 1149. if (obj == uwep) { 1150. uwepgone(); /* now bare handed */ 1151. stop_occupation(); 1152. } 1153. } 1154. rot_organic(arg, timeout); 1155. if (on_floor) newsym(x, y); 1156. else if (in_invent) update_inventory(); 1157. } 1158. 1159. #if 0 1160. void 1161. bury_monst(mtmp) 1162. struct monst *mtmp; 1163. { 1164. #ifdef DEBUG 1165. pline("bury_monst: %s", mon_nam(mtmp)); 1166. #endif 1167. if(canseemon(mtmp)) { 1168. if(is_flyer(mtmp->data) || is_floater(mtmp->data)) { 1169. pline_The("%s opens up, but %s is not swallowed!", 1170. surface(mtmp->mx, mtmp->my), mon_nam(mtmp)); 1171. return; 1172. } else 1173. pline_The("%s opens up and swallows %s!", 1174. surface(mtmp->mx, mtmp->my), mon_nam(mtmp)); 1175. } 1176. 1177. mtmp->mburied = TRUE; 1178. wakeup(mtmp); /* at least give it a chance :-) */ 1179. newsym(mtmp->mx, mtmp->my); 1180. } 1181. 1182. void 1183. bury_you() 1184. { 1185. #ifdef DEBUG 1186. pline("bury_you"); 1187. #endif 1188. if (!Levitation && !is_flyer(uasmon)) { 1189. if(u.uswallow) 1190. You_feel("a sensation like falling into a trap!"); 1191. else 1192. pline_The("%s opens beneath you and you fall in!", 1193. surface(u.ux, u.uy)); 1194. 1195. u.uburied = TRUE; 1196. if(!Strangled && !Breathless) Strangled = 6; 1197. under_ground(1); 1198. } 1199. } 1200. 1201. void 1202. unearth_you() 1203. { 1204. #ifdef DEBUG 1205. pline("unearth_you"); 1206. #endif 1207. u.uburied = FALSE; 1208. under_ground(0); 1209. if(!uamul || uamul->otyp != AMULET_OF_STRANGULATION) 1210. Strangled = 0; 1211. vision_recalc(0); 1212. } 1213. 1214. void 1215. escape_tomb() 1216. { 1217. #ifdef DEBUG 1218. pline("escape_tomb"); 1219. #endif 1220. if ((Teleportation || can_teleport(uasmon)) && 1221. (Teleport_control || rn2(3) < Luck+2)) { 1222. You("attempt a teleport spell."); 1223. (void) dotele(); /* calls unearth_you() */ 1224. } else if(u.uburied) { /* still buried after 'port attempt */ 1225. boolean good; 1226. 1227. if(amorphous(uasmon) || passes_walls(uasmon) || 1228. noncorporeal(uasmon) || unsolid(uasmon) || 1229. (tunnels(uasmon) && !needspick(uasmon))) { 1230. 1231. You("%s up through the floor.", 1232. (tunnels(uasmon) && !needspick(uasmon)) ? 1233. "try to tunnel" : (amorphous(uasmon)) ? 1234. "ooze" : "phase"); 1235. 1236. if(tunnels(uasmon) && !needspick(uasmon)) 1237. good = dighole(TRUE); 1238. else good = TRUE; 1239. if(good) unearth_you(); 1240. } 1241. } 1242. } 1243. 1244. void 1245. bury_obj(otmp) 1246. struct obj *otmp; 1247. { 1248. 1249. #ifdef DEBUG 1250. pline("bury_obj"); 1251. #endif 1252. if(cansee(otmp->ox, otmp->oy)) 1253. pline_The("objects on the %s tumble into a hole!", 1254. surface(otmp->ox, otmp->oy)); 1255. 1256. bury_objs(otmp->ox, otmp->oy); 1257. } 1258. #endif 1259. 1260. #ifdef DEBUG 1261. void 1262. wiz_debug_cmd() /* in this case, bury everything at your loc and around */ 1263. { 1264. int x, y; 1265. 1266. for (x = u.ux - 1; x <= u.ux + 1; x++) 1267. for (y = u.uy - 1; y <= u.uy + 1; y++) 1268. if (isok(x,y)) bury_objs(x,y); 1269. } 1270. 1271. #endif /* DEBUG */ 1272. #endif /* OVL3 */ 1273. 1274. /*dig.c*/
|