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