Source:NetHack 3.4.0/dig.c

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