NHDT->ANH, nethack->anethack, nhdat->anhdat
[aNetHack.git] / src / dig.c
blobca800e279b62d0c40516d623adaf91fc0cc205d2
1 /* aNetHack 0.0.1 dig.c $ANH-Date: 1449269915 2015/12/04 22:58:35 $ $ANH-Branch: master $:$ANH-Revision: 1.103 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* aNetHack may be freely redistributed. See license for details. */
5 #include "hack.h"
7 static NEARDATA boolean did_dig_msg;
9 STATIC_DCL boolean NDECL(rm_waslit);
10 STATIC_DCL void FDECL(mkcavepos,
11 (XCHAR_P, XCHAR_P, int, BOOLEAN_P, BOOLEAN_P));
12 STATIC_DCL void FDECL(mkcavearea, (BOOLEAN_P));
13 STATIC_DCL int NDECL(dig);
14 STATIC_DCL void FDECL(dig_up_grave, (coord *));
15 STATIC_DCL int FDECL(adj_pit_checks, (coord *, char *));
16 STATIC_DCL void FDECL(pit_flow, (struct trap *, SCHAR_P));
18 /* Indices returned by dig_typ() */
19 #define DIGTYP_UNDIGGABLE 0
20 #define DIGTYP_ROCK 1
21 #define DIGTYP_STATUE 2
22 #define DIGTYP_BOULDER 3
23 #define DIGTYP_DOOR 4
24 #define DIGTYP_TREE 5
26 STATIC_OVL boolean
27 rm_waslit()
29 register xchar x, y;
31 if (levl[u.ux][u.uy].typ == ROOM && levl[u.ux][u.uy].waslit)
32 return TRUE;
33 for (x = u.ux - 2; x < u.ux + 3; x++)
34 for (y = u.uy - 1; y < u.uy + 2; y++)
35 if (isok(x, y) && levl[x][y].waslit)
36 return TRUE;
37 return FALSE;
40 /* Change level topology. Messes with vision tables and ignores things like
41 * boulders in the name of a nice effect. Vision will get fixed up again
42 * immediately after the effect is complete.
44 STATIC_OVL void
45 mkcavepos(x, y, dist, waslit, rockit)
46 xchar x, y;
47 int dist;
48 boolean waslit, rockit;
50 register struct rm *lev;
52 if (!isok(x, y))
53 return;
54 lev = &levl[x][y];
56 if (rockit) {
57 register struct monst *mtmp;
59 if (IS_ROCK(lev->typ))
60 return;
61 if (t_at(x, y))
62 return; /* don't cover the portal */
63 if ((mtmp = m_at(x, y)) != 0) /* make sure crucial monsters survive */
64 if (!passes_walls(mtmp->data))
65 (void) rloc(mtmp, TRUE);
66 } else if (lev->typ == ROOM)
67 return;
69 unblock_point(x, y); /* make sure vision knows this location is open */
71 /* fake out saved state */
72 lev->seenv = 0;
73 lev->doormask = 0;
74 if (dist < 3)
75 lev->lit = (rockit ? FALSE : TRUE);
76 if (waslit)
77 lev->waslit = (rockit ? FALSE : TRUE);
78 lev->horizontal = FALSE;
79 /* short-circuit vision recalc */
80 viz_array[y][x] = (dist < 3) ? (IN_SIGHT | COULD_SEE) : COULD_SEE;
81 lev->typ = (rockit ? STONE : ROOM);
82 if (dist >= 3)
83 impossible("mkcavepos called with dist %d", dist);
84 feel_newsym(x, y);
87 STATIC_OVL void
88 mkcavearea(rockit)
89 register boolean rockit;
91 int dist;
92 xchar xmin = u.ux, xmax = u.ux;
93 xchar ymin = u.uy, ymax = u.uy;
94 register xchar i;
95 register boolean waslit = rm_waslit();
97 if (rockit)
98 pline("Crash! The ceiling collapses around you!");
99 else
100 pline("A mysterious force %s cave around you!",
101 (levl[u.ux][u.uy].typ == CORR) ? "creates a" : "extends the");
102 display_nhwindow(WIN_MESSAGE, TRUE);
104 for (dist = 1; dist <= 2; dist++) {
105 xmin--;
106 xmax++;
108 /* top and bottom */
109 if (dist < 2) { /* the area is wider that it is high */
110 ymin--;
111 ymax++;
112 for (i = xmin + 1; i < xmax; i++) {
113 mkcavepos(i, ymin, dist, waslit, rockit);
114 mkcavepos(i, ymax, dist, waslit, rockit);
118 /* left and right */
119 for (i = ymin; i <= ymax; i++) {
120 mkcavepos(xmin, i, dist, waslit, rockit);
121 mkcavepos(xmax, i, dist, waslit, rockit);
124 flush_screen(1); /* make sure the new glyphs shows up */
125 delay_output();
128 if (!rockit && levl[u.ux][u.uy].typ == CORR) {
129 levl[u.ux][u.uy].typ = ROOM;
130 if (waslit)
131 levl[u.ux][u.uy].waslit = TRUE;
132 newsym(u.ux, u.uy); /* in case player is invisible */
135 vision_full_recalc = 1; /* everything changed */
138 /* When digging into location <x,y>, what are you actually digging into? */
140 dig_typ(otmp, x, y)
141 struct obj *otmp;
142 xchar x, y;
144 boolean ispick;
146 if (!otmp)
147 return DIGTYP_UNDIGGABLE;
148 ispick = is_pick(otmp);
149 if (!ispick && !is_axe(otmp))
150 return DIGTYP_UNDIGGABLE;
152 return ((ispick && sobj_at(STATUE, x, y))
153 ? DIGTYP_STATUE
154 : (ispick && sobj_at(BOULDER, x, y))
155 ? DIGTYP_BOULDER
156 : closed_door(x, y)
157 ? DIGTYP_DOOR
158 : IS_TREE(levl[x][y].typ)
159 ? (ispick ? DIGTYP_UNDIGGABLE : DIGTYP_TREE)
160 : (ispick && IS_ROCK(levl[x][y].typ)
161 && (!level.flags.arboreal
162 || IS_WALL(levl[x][y].typ)))
163 ? DIGTYP_ROCK
164 : DIGTYP_UNDIGGABLE);
167 boolean
168 is_digging()
170 if (occupation == dig) {
171 return TRUE;
173 return FALSE;
176 #define BY_YOU (&youmonst)
177 #define BY_OBJECT ((struct monst *) 0)
179 boolean
180 dig_check(madeby, verbose, x, y)
181 struct monst *madeby;
182 boolean verbose;
183 int x, y;
185 struct trap *ttmp = t_at(x, y);
186 const char *verb =
187 (madeby == BY_YOU && uwep && is_axe(uwep)) ? "chop" : "dig in";
189 if (On_stairs(x, y)) {
190 if (x == xdnladder || x == xupladder) {
191 if (verbose)
192 pline_The("ladder resists your effort.");
193 } else if (verbose)
194 pline_The("stairs are too hard to %s.", verb);
195 return FALSE;
196 } else if (IS_THRONE(levl[x][y].typ) && madeby != BY_OBJECT) {
197 if (verbose)
198 pline_The("throne is too hard to break apart.");
199 return FALSE;
200 } else if (IS_ALTAR(levl[x][y].typ)
201 && (madeby != BY_OBJECT || Is_astralevel(&u.uz)
202 || Is_sanctum(&u.uz))) {
203 if (verbose)
204 pline_The("altar is too hard to break apart.");
205 return FALSE;
206 } else if (Is_airlevel(&u.uz)) {
207 if (verbose)
208 You("cannot %s thin air.", verb);
209 return FALSE;
210 } else if (Is_waterlevel(&u.uz)) {
211 if (verbose)
212 pline_The("%s splashes and subsides.", hliquid("water"));
213 return FALSE;
214 } else if ((IS_ROCK(levl[x][y].typ) && levl[x][y].typ != SDOOR
215 && (levl[x][y].wall_info & W_NONDIGGABLE) != 0)
216 || (ttmp
217 && (ttmp->ttyp == MAGIC_PORTAL
218 || ttmp->ttyp == VIBRATING_SQUARE
219 || (!Can_dig_down(&u.uz) && !levl[x][y].candig)))) {
220 if (verbose)
221 pline_The("%s here is too hard to %s.", surface(x, y), verb);
222 return FALSE;
223 } else if (sobj_at(BOULDER, x, y)) {
224 if (verbose)
225 There("isn't enough room to %s here.", verb);
226 return FALSE;
227 } else if (madeby == BY_OBJECT
228 /* the block against existing traps is mainly to
229 prevent broken wands from turning holes into pits */
230 && (ttmp || is_pool_or_lava(x, y))) {
231 /* digging by player handles pools separately */
232 return FALSE;
234 return TRUE;
237 STATIC_OVL int
238 dig(VOID_ARGS)
240 register struct rm *lev;
241 register xchar dpx = context.digging.pos.x, dpy = context.digging.pos.y;
242 register boolean ispick = uwep && is_pick(uwep);
243 const char *verb = (!uwep || is_pick(uwep)) ? "dig into" : "chop through";
245 lev = &levl[dpx][dpy];
246 /* perhaps a nymph stole your pick-axe while you were busy digging */
247 /* or perhaps you teleported away */
248 if (u.uswallow || !uwep || (!ispick && !is_axe(uwep))
249 || !on_level(&context.digging.level, &u.uz)
250 || ((context.digging.down ? (dpx != u.ux || dpy != u.uy)
251 : (distu(dpx, dpy) > 2))))
252 return 0;
254 if (context.digging.down) {
255 if (!dig_check(BY_YOU, TRUE, u.ux, u.uy))
256 return 0;
257 } else { /* !context.digging.down */
258 if (IS_TREE(lev->typ) && !may_dig(dpx, dpy)
259 && dig_typ(uwep, dpx, dpy) == DIGTYP_TREE) {
260 pline("This tree seems to be petrified.");
261 return 0;
263 if (IS_ROCK(lev->typ) && !may_dig(dpx, dpy)
264 && dig_typ(uwep, dpx, dpy) == DIGTYP_ROCK) {
265 pline("This %s is too hard to %s.",
266 is_db_wall(dpx, dpy) ? "drawbridge" : "wall", verb);
267 return 0;
270 if (Fumbling && !rn2(3)) {
271 switch (rn2(3)) {
272 case 0:
273 if (!welded(uwep)) {
274 You("fumble and drop %s.", yname(uwep));
275 dropx(uwep);
276 } else {
277 if (u.usteed)
278 pline("%s and %s %s!", Yobjnam2(uwep, "bounce"),
279 otense(uwep, "hit"), mon_nam(u.usteed));
280 else
281 pline("Ouch! %s and %s you!", Yobjnam2(uwep, "bounce"),
282 otense(uwep, "hit"));
283 set_wounded_legs(RIGHT_SIDE, 5 + rnd(5));
285 break;
286 case 1:
287 pline("Bang! You hit with the broad side of %s!",
288 the(xname(uwep)));
289 break;
290 default:
291 Your("swing misses its mark.");
292 break;
294 return 0;
297 context.digging.effort +=
298 10 + rn2(5) + abon() + uwep->spe - greatest_erosion(uwep) + u.udaminc;
299 if (Race_if(PM_DWARF))
300 context.digging.effort *= 2;
301 if (context.digging.down) {
302 struct trap *ttmp = t_at(dpx, dpy);
304 if (context.digging.effort > 250 || (ttmp && ttmp->ttyp == HOLE)) {
305 (void) dighole(FALSE, FALSE, (coord *) 0);
306 (void) memset((genericptr_t) &context.digging, 0,
307 sizeof context.digging);
308 return 0; /* done with digging */
311 if (context.digging.effort <= 50
312 || (ttmp && (ttmp->ttyp == TRAPDOOR || ttmp->ttyp == PIT
313 || ttmp->ttyp == SPIKED_PIT))) {
314 return 1;
315 } else if (ttmp && (ttmp->ttyp == LANDMINE
316 || (ttmp->ttyp == BEAR_TRAP && !u.utrap))) {
317 /* digging onto a set object trap triggers it;
318 hero should have used #untrap first */
319 dotrap(ttmp, FORCETRAP);
320 /* restart completely from scratch if we resume digging */
321 (void) memset((genericptr_t) &context.digging, 0,
322 sizeof context.digging);
323 return 0;
324 } else if (ttmp && ttmp->ttyp == BEAR_TRAP && u.utrap) {
325 if (rnl(7) > (Fumbling ? 1 : 4)) {
326 char kbuf[BUFSZ];
327 int dmg = dmgval(uwep, &youmonst) + dbon();
329 if (dmg < 1)
330 dmg = 1;
331 else if (uarmf)
332 dmg = (dmg + 1) / 2;
333 You("hit yourself in the %s.", body_part(FOOT));
334 Sprintf(kbuf, "chopping off %s own %s", uhis(),
335 body_part(FOOT));
336 losehp(Maybe_Half_Phys(dmg), kbuf, KILLED_BY);
337 } else {
338 You("destroy the bear trap with %s.",
339 yobjnam(uwep, (const char *) 0));
340 u.utrap = 0; /* release from trap */
341 deltrap(ttmp);
343 /* we haven't made any progress toward a pit yet */
344 context.digging.effort = 0;
345 return 0;
348 if (IS_ALTAR(lev->typ)) {
349 altar_wrath(dpx, dpy);
350 angry_priest();
353 /* make pit at <u.ux,u.uy> */
354 if (dighole(TRUE, FALSE, (coord *) 0)) {
355 context.digging.level.dnum = 0;
356 context.digging.level.dlevel = -1;
358 return 0;
361 if (context.digging.effort > 100) {
362 register const char *digtxt, *dmgtxt = (const char *) 0;
363 register struct obj *obj;
364 register boolean shopedge = *in_rooms(dpx, dpy, SHOPBASE);
366 if ((obj = sobj_at(STATUE, dpx, dpy)) != 0) {
367 if (break_statue(obj))
368 digtxt = "The statue shatters.";
369 else
370 /* it was a statue trap; break_statue()
371 * printed a message and updated the screen
373 digtxt = (char *) 0;
374 } else if ((obj = sobj_at(BOULDER, dpx, dpy)) != 0) {
375 struct obj *bobj;
377 fracture_rock(obj);
378 if ((bobj = sobj_at(BOULDER, dpx, dpy)) != 0) {
379 /* another boulder here, restack it to the top */
380 obj_extract_self(bobj);
381 place_object(bobj, dpx, dpy);
383 digtxt = "The boulder falls apart.";
384 } else if (lev->typ == STONE || lev->typ == SCORR
385 || IS_TREE(lev->typ)) {
386 if (Is_earthlevel(&u.uz)) {
387 if (uwep->blessed && !rn2(3)) {
388 mkcavearea(FALSE);
389 goto cleanup;
390 } else if ((uwep->cursed && !rn2(4))
391 || (!uwep->blessed && !rn2(6))) {
392 mkcavearea(TRUE);
393 goto cleanup;
396 if (IS_TREE(lev->typ)) {
397 digtxt = "You cut down the tree.";
398 lev->typ = ROOM;
399 if (!rn2(5))
400 (void) rnd_treefruit_at(dpx, dpy);
401 } else {
402 digtxt = "You succeed in cutting away some rock.";
403 lev->typ = CORR;
405 } else if (IS_WALL(lev->typ)) {
406 if (shopedge) {
407 add_damage(dpx, dpy, 10L * ACURRSTR);
408 dmgtxt = "damage";
410 if (level.flags.is_maze_lev) {
411 lev->typ = ROOM;
412 } else if (level.flags.is_cavernous_lev && !in_town(dpx, dpy)) {
413 lev->typ = CORR;
414 } else {
415 lev->typ = DOOR;
416 lev->doormask = D_NODOOR;
418 digtxt = "You make an opening in the wall.";
419 } else if (lev->typ == SDOOR) {
420 cvt_sdoor_to_door(lev); /* ->typ = DOOR */
421 digtxt = "You break through a secret door!";
422 if (!(lev->doormask & D_TRAPPED))
423 lev->doormask = D_BROKEN;
424 } else if (closed_door(dpx, dpy)) {
425 digtxt = "You break through the door.";
426 if (shopedge) {
427 add_damage(dpx, dpy, 400L);
428 dmgtxt = "break";
430 if (!(lev->doormask & D_TRAPPED))
431 lev->doormask = D_BROKEN;
432 } else
433 return 0; /* statue or boulder got taken */
435 if (!does_block(dpx, dpy, &levl[dpx][dpy]))
436 unblock_point(dpx, dpy); /* vision: can see through */
437 feel_newsym(dpx, dpy);
438 if (digtxt && !context.digging.quiet)
439 pline1(digtxt); /* after newsym */
440 if (dmgtxt)
441 pay_for_damage(dmgtxt, FALSE);
443 if (Is_earthlevel(&u.uz) && !rn2(3)) {
444 register struct monst *mtmp;
446 switch (rn2(2)) {
447 case 0:
448 mtmp = makemon(&mons[PM_EARTH_ELEMENTAL], dpx, dpy,
449 NO_MM_FLAGS);
450 break;
451 default:
452 mtmp = makemon(&mons[PM_XORN], dpx, dpy, NO_MM_FLAGS);
453 break;
455 if (mtmp)
456 pline_The("debris from your digging comes to life!");
458 if (IS_DOOR(lev->typ) && (lev->doormask & D_TRAPPED)) {
459 lev->doormask = D_NODOOR;
460 b_trapped("door", 0);
461 newsym(dpx, dpy);
463 cleanup:
464 context.digging.lastdigtime = moves;
465 context.digging.quiet = FALSE;
466 context.digging.level.dnum = 0;
467 context.digging.level.dlevel = -1;
468 return 0;
469 } else { /* not enough effort has been spent yet */
470 static const char *const d_target[6] = { "", "rock", "statue",
471 "boulder", "door", "tree" };
472 int dig_target = dig_typ(uwep, dpx, dpy);
474 if (IS_WALL(lev->typ) || dig_target == DIGTYP_DOOR) {
475 if (*in_rooms(dpx, dpy, SHOPBASE)) {
476 pline("This %s seems too hard to %s.",
477 IS_DOOR(lev->typ) ? "door" : "wall", verb);
478 return 0;
480 } else if (dig_target == DIGTYP_UNDIGGABLE
481 || (dig_target == DIGTYP_ROCK && !IS_ROCK(lev->typ)))
482 return 0; /* statue or boulder got taken */
484 if (!did_dig_msg) {
485 You("hit the %s with all your might.", d_target[dig_target]);
486 did_dig_msg = TRUE;
489 return 1;
492 /* When will hole be finished? Very rough indication used by shopkeeper. */
494 holetime()
496 if (occupation != dig || !*u.ushops)
497 return -1;
498 return ((250 - context.digging.effort) / 20);
501 /* Return typ of liquid to fill a hole with, or ROOM, if no liquid nearby */
502 schar
503 fillholetyp(x, y, fill_if_any)
504 int x, y;
505 boolean fill_if_any; /* force filling if it exists at all */
507 register int x1, y1;
508 int lo_x = max(1, x - 1), hi_x = min(x + 1, COLNO - 1),
509 lo_y = max(0, y - 1), hi_y = min(y + 1, ROWNO - 1);
510 int pool_cnt = 0, moat_cnt = 0, lava_cnt = 0;
512 for (x1 = lo_x; x1 <= hi_x; x1++)
513 for (y1 = lo_y; y1 <= hi_y; y1++)
514 if (is_moat(x1, y1))
515 moat_cnt++;
516 else if (is_pool(x1, y1))
517 /* This must come after is_moat since moats are pools
518 * but not vice-versa. */
519 pool_cnt++;
520 else if (is_lava(x1, y1))
521 lava_cnt++;
523 if (!fill_if_any)
524 pool_cnt /= 3; /* not as much liquid as the others */
526 if ((lava_cnt > moat_cnt + pool_cnt && rn2(lava_cnt + 1))
527 || (lava_cnt && fill_if_any))
528 return LAVAPOOL;
529 else if ((moat_cnt > 0 && rn2(moat_cnt + 1)) || (moat_cnt && fill_if_any))
530 return MOAT;
531 else if ((pool_cnt > 0 && rn2(pool_cnt + 1)) || (pool_cnt && fill_if_any))
532 return POOL;
533 else
534 return ROOM;
537 void
538 digactualhole(x, y, madeby, ttyp)
539 register int x, y;
540 struct monst *madeby;
541 int ttyp;
543 struct obj *oldobjs, *newobjs;
544 register struct trap *ttmp;
545 char surface_type[BUFSZ];
546 struct rm *lev = &levl[x][y];
547 boolean shopdoor;
548 struct monst *mtmp = m_at(x, y); /* may be madeby */
549 boolean madeby_u = (madeby == BY_YOU);
550 boolean madeby_obj = (madeby == BY_OBJECT);
551 boolean at_u = (x == u.ux) && (y == u.uy);
552 boolean wont_fall = Levitation || Flying;
554 if (at_u && u.utrap) {
555 if (u.utraptype == TT_BURIEDBALL)
556 buried_ball_to_punishment();
557 else if (u.utraptype == TT_INFLOOR)
558 u.utrap = 0;
561 /* these furniture checks were in dighole(), but wand
562 breaking bypasses that routine and calls us directly */
563 if (IS_FOUNTAIN(lev->typ)) {
564 dogushforth(FALSE);
565 SET_FOUNTAIN_WARNED(x, y); /* force dryup */
566 dryup(x, y, madeby_u);
567 return;
568 } else if (IS_SINK(lev->typ)) {
569 breaksink(x, y);
570 return;
571 } else if (lev->typ == DRAWBRIDGE_DOWN
572 || (is_drawbridge_wall(x, y) >= 0)) {
573 int bx = x, by = y;
574 /* if under the portcullis, the bridge is adjacent */
575 (void) find_drawbridge(&bx, &by);
576 destroy_drawbridge(bx, by);
577 return;
580 if (ttyp != PIT && (!Can_dig_down(&u.uz) && !lev->candig)) {
581 impossible("digactualhole: can't dig %s on this level.",
582 defsyms[trap_to_defsym(ttyp)].explanation);
583 ttyp = PIT;
586 /* maketrap() might change it, also, in this situation,
587 surface() returns an inappropriate string for a grave */
588 if (IS_GRAVE(lev->typ))
589 Strcpy(surface_type, "grave");
590 else
591 Strcpy(surface_type, surface(x, y));
592 shopdoor = IS_DOOR(lev->typ) && *in_rooms(x, y, SHOPBASE);
593 oldobjs = level.objects[x][y];
594 ttmp = maketrap(x, y, ttyp);
595 if (!ttmp)
596 return;
597 newobjs = level.objects[x][y];
598 ttmp->madeby_u = madeby_u;
599 ttmp->tseen = 0;
600 if (cansee(x, y))
601 seetrap(ttmp);
602 else if (madeby_u)
603 feeltrap(ttmp);
605 if (ttyp == PIT) {
606 if (madeby_u) {
607 if (x != u.ux || y != u.uy)
608 You("dig an adjacent pit.");
609 else
610 You("dig a pit in the %s.", surface_type);
611 if (shopdoor)
612 pay_for_damage("ruin", FALSE);
613 } else if (!madeby_obj && canseemon(madeby))
614 pline("%s digs a pit in the %s.", Monnam(madeby), surface_type);
615 else if (cansee(x, y) && flags.verbose)
616 pline("A pit appears in the %s.", surface_type);
618 if (at_u) {
619 if (!wont_fall) {
620 u.utrap = rn1(4, 2);
621 u.utraptype = TT_PIT;
622 vision_full_recalc = 1; /* vision limits change */
623 } else
624 u.utrap = 0;
625 if (oldobjs != newobjs) /* something unearthed */
626 (void) pickup(1); /* detects pit */
627 } else if (mtmp) {
628 if (is_flyer(mtmp->data) || is_floater(mtmp->data)) {
629 if (canseemon(mtmp))
630 pline("%s %s over the pit.", Monnam(mtmp),
631 (is_flyer(mtmp->data)) ? "flies" : "floats");
632 } else if (mtmp != madeby)
633 (void) mintrap(mtmp);
635 } else { /* was TRAPDOOR now a HOLE*/
637 if (madeby_u)
638 You("dig a hole through the %s.", surface_type);
639 else if (!madeby_obj && canseemon(madeby))
640 pline("%s digs a hole through the %s.", Monnam(madeby),
641 surface_type);
642 else if (cansee(x, y) && flags.verbose)
643 pline("A hole appears in the %s.", surface_type);
645 if (at_u) {
646 if (!u.ustuck && !wont_fall && !next_to_u()) {
647 You("are jerked back by your pet!");
648 wont_fall = TRUE;
651 /* Floor objects get a chance of falling down. The case where
652 * the hero does NOT fall down is treated here. The case
653 * where the hero does fall down is treated in goto_level().
655 if (u.ustuck || wont_fall) {
656 if (newobjs)
657 impact_drop((struct obj *) 0, x, y, 0);
658 if (oldobjs != newobjs)
659 (void) pickup(1);
660 if (shopdoor && madeby_u)
661 pay_for_damage("ruin", FALSE);
663 } else {
664 d_level newlevel;
666 if (*u.ushops && madeby_u)
667 shopdig(1); /* shk might snatch pack */
668 /* handle earlier damage, eg breaking wand of digging */
669 else if (!madeby_u)
670 pay_for_damage("dig into", TRUE);
672 You("fall through...");
673 /* Earlier checks must ensure that the destination
674 * level exists and is in the present dungeon.
676 newlevel.dnum = u.uz.dnum;
677 newlevel.dlevel = u.uz.dlevel + 1;
678 goto_level(&newlevel, FALSE, TRUE, FALSE);
679 /* messages for arriving in special rooms */
680 spoteffects(FALSE);
682 } else {
683 if (shopdoor && madeby_u)
684 pay_for_damage("ruin", FALSE);
685 if (newobjs)
686 impact_drop((struct obj *) 0, x, y, 0);
687 if (mtmp) {
688 /*[don't we need special sokoban handling here?]*/
689 if (is_flyer(mtmp->data) || is_floater(mtmp->data)
690 || mtmp->data == &mons[PM_WUMPUS]
691 || (mtmp->wormno && count_wsegs(mtmp) > 5)
692 || mtmp->data->msize >= MZ_HUGE)
693 return;
694 if (mtmp == u.ustuck) /* probably a vortex */
695 return; /* temporary? kludge */
697 if (teleport_pet(mtmp, FALSE)) {
698 d_level tolevel;
700 if (Is_stronghold(&u.uz)) {
701 assign_level(&tolevel, &valley_level);
702 } else if (Is_botlevel(&u.uz)) {
703 if (canseemon(mtmp))
704 pline("%s avoids the trap.", Monnam(mtmp));
705 return;
706 } else {
707 get_level(&tolevel, depth(&u.uz) + 1);
709 if (mtmp->isshk)
710 make_angry_shk(mtmp, 0, 0);
711 migrate_to_level(mtmp, ledger_no(&tolevel), MIGR_RANDOM,
712 (coord *) 0);
720 * Called from dighole(), but also from do_break_wand()
721 * in apply.c.
723 void
724 liquid_flow(x, y, typ, ttmp, fillmsg)
725 xchar x, y;
726 schar typ;
727 struct trap *ttmp;
728 const char *fillmsg;
730 boolean u_spot = (x == u.ux && y == u.uy);
732 if (ttmp)
733 (void) delfloortrap(ttmp);
734 /* if any objects were frozen here, they're released now */
735 unearth_objs(x, y);
737 if (fillmsg)
738 pline(fillmsg, hliquid(typ == LAVAPOOL ? "lava" : "water"));
739 if (u_spot && !(Levitation || Flying)) {
740 if (typ == LAVAPOOL)
741 (void) lava_effects();
742 else if (!Wwalking)
743 (void) drown();
747 /* return TRUE if digging succeeded, FALSE otherwise */
748 boolean
749 dighole(pit_only, by_magic, cc)
750 boolean pit_only, by_magic;
751 coord *cc;
753 register struct trap *ttmp;
754 struct rm *lev;
755 struct obj *boulder_here;
756 schar typ;
757 xchar dig_x, dig_y;
758 boolean nohole;
760 if (!cc) {
761 dig_x = u.ux;
762 dig_y = u.uy;
763 } else {
764 dig_x = cc->x;
765 dig_y = cc->y;
766 if (!isok(dig_x, dig_y))
767 return FALSE;
770 ttmp = t_at(dig_x, dig_y);
771 lev = &levl[dig_x][dig_y];
772 nohole = (!Can_dig_down(&u.uz) && !lev->candig);
774 if ((ttmp && (ttmp->ttyp == MAGIC_PORTAL
775 || ttmp->ttyp == VIBRATING_SQUARE || nohole))
776 || (IS_ROCK(lev->typ) && lev->typ != SDOOR
777 && (lev->wall_info & W_NONDIGGABLE) != 0)) {
778 pline_The("%s %shere is too hard to dig in.", surface(dig_x, dig_y),
779 (dig_x != u.ux || dig_y != u.uy) ? "t" : "");
781 } else if (is_pool_or_lava(dig_x, dig_y)) {
782 pline_The("%s sloshes furiously for a moment, then subsides.",
783 hliquid(is_lava(dig_x, dig_y) ? "lava" : "water"));
784 wake_nearby(); /* splashing */
786 } else if (lev->typ == DRAWBRIDGE_DOWN
787 || (is_drawbridge_wall(dig_x, dig_y) >= 0)) {
788 /* drawbridge_down is the platform crossing the moat when the
789 bridge is extended; drawbridge_wall is the open "doorway" or
790 closed "door" where the portcullis/mechanism is located */
791 if (pit_only) {
792 pline_The("drawbridge seems too hard to dig through.");
793 return FALSE;
794 } else {
795 int x = dig_x, y = dig_y;
796 /* if under the portcullis, the bridge is adjacent */
797 (void) find_drawbridge(&x, &y);
798 destroy_drawbridge(x, y);
799 return TRUE;
802 } else if ((boulder_here = sobj_at(BOULDER, dig_x, dig_y)) != 0) {
803 if (ttmp && (ttmp->ttyp == PIT || ttmp->ttyp == SPIKED_PIT)
804 && rn2(2)) {
805 pline_The("boulder settles into the %spit.",
806 (dig_x != u.ux || dig_y != u.uy) ? "adjacent " : "");
807 ttmp->ttyp = PIT; /* crush spikes */
808 } else {
810 * digging makes a hole, but the boulder immediately
811 * fills it. Final outcome: no hole, no boulder.
813 pline("KADOOM! The boulder falls in!");
814 (void) delfloortrap(ttmp);
816 delobj(boulder_here);
817 return TRUE;
819 } else if (IS_GRAVE(lev->typ)) {
820 digactualhole(dig_x, dig_y, BY_YOU, PIT);
821 dig_up_grave(cc);
822 return TRUE;
823 } else if (lev->typ == DRAWBRIDGE_UP) {
824 /* must be floor or ice, other cases handled above */
825 /* dig "pit" and let fluid flow in (if possible) */
826 typ = fillholetyp(dig_x, dig_y, FALSE);
828 if (typ == ROOM) {
830 * We can't dig a hole here since that will destroy
831 * the drawbridge. The following is a cop-out. --dlc
833 pline_The("%s %shere is too hard to dig in.",
834 surface(dig_x, dig_y),
835 (dig_x != u.ux || dig_y != u.uy) ? "t" : "");
836 return FALSE;
839 lev->drawbridgemask &= ~DB_UNDER;
840 lev->drawbridgemask |= (typ == LAVAPOOL) ? DB_LAVA : DB_MOAT;
841 liquid_flow(dig_x, dig_y, typ, ttmp,
842 "As you dig, the hole fills with %s!");
843 return TRUE;
845 /* the following two are here for the wand of digging */
846 } else if (IS_THRONE(lev->typ)) {
847 pline_The("throne is too hard to break apart.");
849 } else if (IS_ALTAR(lev->typ)) {
850 pline_The("altar is too hard to break apart.");
852 } else {
853 typ = fillholetyp(dig_x, dig_y, FALSE);
855 if (typ != ROOM) {
856 lev->typ = typ;
857 liquid_flow(dig_x, dig_y, typ, ttmp,
858 "As you dig, the hole fills with %s!");
859 return TRUE;
862 /* magical digging disarms settable traps */
863 if (by_magic && ttmp
864 && (ttmp->ttyp == LANDMINE || ttmp->ttyp == BEAR_TRAP)) {
865 int otyp = (ttmp->ttyp == LANDMINE) ? LAND_MINE : BEARTRAP;
867 /* convert trap into buried object (deletes trap) */
868 cnv_trap_obj(otyp, 1, ttmp, TRUE);
871 /* finally we get to make a hole */
872 if (nohole || pit_only)
873 digactualhole(dig_x, dig_y, BY_YOU, PIT);
874 else
875 digactualhole(dig_x, dig_y, BY_YOU, HOLE);
877 return TRUE;
880 return FALSE;
883 STATIC_OVL void
884 dig_up_grave(cc)
885 coord *cc;
887 struct obj *otmp;
888 xchar dig_x, dig_y;
890 if (!cc) {
891 dig_x = u.ux;
892 dig_y = u.uy;
893 } else {
894 dig_x = cc->x;
895 dig_y = cc->y;
896 if (!isok(dig_x, dig_y))
897 return;
900 /* Grave-robbing is frowned upon... */
901 exercise(A_WIS, FALSE);
902 if (Role_if(PM_ARCHEOLOGIST)) {
903 adjalign(-sgn(u.ualign.type) * 3);
904 You_feel("like a despicable grave-robber!");
905 } else if (Role_if(PM_SAMURAI)) {
906 adjalign(-sgn(u.ualign.type));
907 You("disturb the honorable dead!");
908 } else if ((u.ualign.type == A_LAWFUL) && (u.ualign.record > -10)) {
909 adjalign(-sgn(u.ualign.type));
910 You("have violated the sanctity of this grave!");
913 switch (rn2(5)) {
914 case 0:
915 case 1:
916 You("unearth a corpse.");
917 if (!!(otmp = mk_tt_object(CORPSE, dig_x, dig_y)))
918 otmp->age -= 100; /* this is an *OLD* corpse */
920 break;
921 case 2:
922 if (!Blind)
923 pline(Hallucination ? "Dude! The living dead!"
924 : "The grave's owner is very upset!");
925 (void) makemon(mkclass(S_ZOMBIE, 0), dig_x, dig_y, NO_MM_FLAGS);
926 break;
927 case 3:
928 if (!Blind)
929 pline(Hallucination ? "I want my mummy!"
930 : "You've disturbed a tomb!");
931 (void) makemon(mkclass(S_MUMMY, 0), dig_x, dig_y, NO_MM_FLAGS);
932 break;
933 default:
934 /* No corpse */
935 pline_The("grave seems unused. Strange....");
936 break;
938 levl[dig_x][dig_y].typ = ROOM;
939 del_engr_at(dig_x, dig_y);
940 newsym(dig_x, dig_y);
941 return;
945 use_pick_axe(obj)
946 struct obj *obj;
948 const char *sdp, *verb;
949 char *dsp, dirsyms[12], qbuf[BUFSZ];
950 boolean ispick;
951 int rx, ry, downok, res = 0;
953 /* Check tool */
954 if (obj != uwep) {
955 if (!wield_tool(obj, "swing"))
956 return 0;
957 else
958 res = 1;
960 ispick = is_pick(obj);
961 verb = ispick ? "dig" : "chop";
963 if (u.utrap && u.utraptype == TT_WEB) {
964 pline("%s you can't %s while entangled in a web.",
965 /* res==0 => no prior message;
966 res==1 => just got "You now wield a pick-axe." message */
967 !res ? "Unfortunately," : "But", verb);
968 return res;
971 /* construct list of directions to show player for likely choices */
972 downok = !!can_reach_floor(FALSE);
973 dsp = dirsyms;
974 for (sdp = Cmd.dirchars; *sdp; ++sdp) {
975 /* filter out useless directions */
976 if (u.uswallow) {
977 ; /* all directions are viable when swallowed */
978 } else if (movecmd(*sdp)) {
979 /* normal direction, within plane of the level map;
980 movecmd() sets u.dx, u.dy, u.dz and returns !u.dz */
981 if (!dxdy_moveok())
982 continue; /* handle NODIAG */
983 rx = u.ux + u.dx;
984 ry = u.uy + u.dy;
985 if (!isok(rx, ry) || dig_typ(obj, rx, ry) == DIGTYP_UNDIGGABLE)
986 continue;
987 } else {
988 /* up or down; we used to always include down, so that
989 there would always be at least one choice shown, but
990 it shouldn't be a likely candidate when floating high
991 above the floor; include up instead in that situation
992 (as a silly candidate rather than a likely one...) */
993 if ((u.dz > 0) ^ downok)
994 continue;
996 /* include this direction */
997 *dsp++ = *sdp;
999 *dsp = 0;
1000 Sprintf(qbuf, "In what direction do you want to %s? [%s]", verb, dirsyms);
1001 if (!getdir(qbuf))
1002 return res;
1004 return use_pick_axe2(obj);
1007 /* MRKR: use_pick_axe() is split in two to allow autodig to bypass */
1008 /* the "In what direction do you want to dig?" query. */
1009 /* use_pick_axe2() uses the existing u.dx, u.dy and u.dz */
1011 use_pick_axe2(obj)
1012 struct obj *obj;
1014 register int rx, ry;
1015 register struct rm *lev;
1016 struct trap *trap, *trap_with_u;
1017 int dig_target;
1018 boolean ispick = is_pick(obj);
1019 const char *verbing = ispick ? "digging" : "chopping";
1021 if (u.uswallow && attack(u.ustuck)) {
1022 ; /* return 1 */
1023 } else if (Underwater) {
1024 pline("Turbulence torpedoes your %s attempts.", verbing);
1025 } else if (u.dz < 0) {
1026 if (Levitation)
1027 You("don't have enough leverage.");
1028 else
1029 You_cant("reach the %s.", ceiling(u.ux, u.uy));
1030 } else if (!u.dx && !u.dy && !u.dz) {
1031 char buf[BUFSZ];
1032 int dam;
1034 dam = rnd(2) + dbon() + obj->spe;
1035 if (dam <= 0)
1036 dam = 1;
1037 You("hit yourself with %s.", yname(uwep));
1038 Sprintf(buf, "%s own %s", uhis(), OBJ_NAME(objects[obj->otyp]));
1039 losehp(Maybe_Half_Phys(dam), buf, KILLED_BY);
1040 context.botl = 1;
1041 return 1;
1042 } else if (u.dz == 0) {
1043 if (Stunned || (Confusion && !rn2(5)))
1044 confdir();
1045 rx = u.ux + u.dx;
1046 ry = u.uy + u.dy;
1047 if (!isok(rx, ry)) {
1048 pline("Clash!");
1049 return 1;
1051 lev = &levl[rx][ry];
1052 if (MON_AT(rx, ry) && attack(m_at(rx, ry)))
1053 return 1;
1054 dig_target = dig_typ(obj, rx, ry);
1055 if (dig_target == DIGTYP_UNDIGGABLE) {
1056 /* ACCESSIBLE or POOL */
1057 trap = t_at(rx, ry);
1058 if (trap && trap->ttyp == WEB) {
1059 if (!trap->tseen) {
1060 seetrap(trap);
1061 There("is a spider web there!");
1063 pline("%s entangled in the web.", Yobjnam2(obj, "become"));
1064 /* you ought to be able to let go; tough luck */
1065 /* (maybe `move_into_trap()' would be better) */
1066 nomul(-d(2, 2));
1067 multi_reason = "stuck in a spider web";
1068 nomovemsg = "You pull free.";
1069 } else if (lev->typ == IRONBARS) {
1070 pline("Clang!");
1071 wake_nearby();
1072 } else if (IS_TREE(lev->typ))
1073 You("need an axe to cut down a tree.");
1074 else if (IS_ROCK(lev->typ))
1075 You("need a pick to dig rock.");
1076 else if (!ispick && (sobj_at(STATUE, rx, ry)
1077 || sobj_at(BOULDER, rx, ry))) {
1078 boolean vibrate = !rn2(3);
1079 pline("Sparks fly as you whack the %s.%s",
1080 sobj_at(STATUE, rx, ry) ? "statue" : "boulder",
1081 vibrate ? " The axe-handle vibrates violently!" : "");
1082 if (vibrate)
1083 losehp(Maybe_Half_Phys(2), "axing a hard object",
1084 KILLED_BY);
1085 } else if (u.utrap && u.utraptype == TT_PIT && trap
1086 && (trap_with_u = t_at(u.ux, u.uy))
1087 && (trap->ttyp == PIT || trap->ttyp == SPIKED_PIT)
1088 && !conjoined_pits(trap, trap_with_u, FALSE)) {
1089 int idx;
1090 for (idx = 0; idx < 8; idx++) {
1091 if (xdir[idx] == u.dx && ydir[idx] == u.dy)
1092 break;
1094 /* idx is valid if < 8 */
1095 if (idx < 8) {
1096 int adjidx = (idx + 4) % 8;
1097 trap_with_u->conjoined |= (1 << idx);
1098 trap->conjoined |= (1 << adjidx);
1099 pline("You clear some debris from between the pits.");
1101 } else if (u.utrap && u.utraptype == TT_PIT
1102 && (trap_with_u = t_at(u.ux, u.uy))) {
1103 You("swing %s, but the rubble has no place to go.",
1104 yobjnam(obj, (char *) 0));
1105 } else
1106 You("swing %s through thin air.", yobjnam(obj, (char *) 0));
1107 } else {
1108 static const char *const d_action[6] = { "swinging", "digging",
1109 "chipping the statue",
1110 "hitting the boulder",
1111 "chopping at the door",
1112 "cutting the tree" };
1113 did_dig_msg = FALSE;
1114 context.digging.quiet = FALSE;
1115 if (context.digging.pos.x != rx || context.digging.pos.y != ry
1116 || !on_level(&context.digging.level, &u.uz)
1117 || context.digging.down) {
1118 if (flags.autodig && dig_target == DIGTYP_ROCK
1119 && !context.digging.down && context.digging.pos.x == u.ux
1120 && context.digging.pos.y == u.uy
1121 && (moves <= context.digging.lastdigtime + 2
1122 && moves >= context.digging.lastdigtime)) {
1123 /* avoid messages if repeated autodigging */
1124 did_dig_msg = TRUE;
1125 context.digging.quiet = TRUE;
1127 context.digging.down = context.digging.chew = FALSE;
1128 context.digging.warned = FALSE;
1129 context.digging.pos.x = rx;
1130 context.digging.pos.y = ry;
1131 assign_level(&context.digging.level, &u.uz);
1132 context.digging.effort = 0;
1133 if (!context.digging.quiet)
1134 You("start %s.", d_action[dig_target]);
1135 } else {
1136 You("%s %s.", context.digging.chew ? "begin" : "continue",
1137 d_action[dig_target]);
1138 context.digging.chew = FALSE;
1140 set_occupation(dig, verbing, 0);
1142 } else if (Is_airlevel(&u.uz) || Is_waterlevel(&u.uz)) {
1143 /* it must be air -- water checked above */
1144 You("swing %s through thin air.", yobjnam(obj, (char *) 0));
1145 } else if (!can_reach_floor(FALSE)) {
1146 cant_reach_floor(u.ux, u.uy, FALSE, FALSE);
1147 } else if (is_pool_or_lava(u.ux, u.uy)) {
1148 /* Monsters which swim also happen not to be able to dig */
1149 You("cannot stay under%s long enough.",
1150 is_pool(u.ux, u.uy) ? "water" : " the lava");
1151 } else if ((trap = t_at(u.ux, u.uy)) != 0
1152 && uteetering_at_seen_pit(trap)) {
1153 dotrap(trap, FORCEBUNGLE);
1154 /* might escape trap and still be teetering at brink */
1155 if (!u.utrap)
1156 cant_reach_floor(u.ux, u.uy, FALSE, TRUE);
1157 } else if (!ispick
1158 /* can only dig down with an axe when doing so will
1159 trigger or disarm a trap here */
1160 && (!trap || (trap->ttyp != LANDMINE
1161 && trap->ttyp != BEAR_TRAP))) {
1162 pline("%s merely scratches the %s.", Yobjnam2(obj, (char *) 0),
1163 surface(u.ux, u.uy));
1164 u_wipe_engr(3);
1165 } else {
1166 if (context.digging.pos.x != u.ux || context.digging.pos.y != u.uy
1167 || !on_level(&context.digging.level, &u.uz)
1168 || !context.digging.down) {
1169 context.digging.chew = FALSE;
1170 context.digging.down = TRUE;
1171 context.digging.warned = FALSE;
1172 context.digging.pos.x = u.ux;
1173 context.digging.pos.y = u.uy;
1174 assign_level(&context.digging.level, &u.uz);
1175 context.digging.effort = 0;
1176 You("start %s downward.", verbing);
1177 if (*u.ushops)
1178 shopdig(0);
1179 } else
1180 You("continue %s downward.", verbing);
1181 did_dig_msg = FALSE;
1182 set_occupation(dig, verbing, 0);
1184 return 1;
1188 * Town Watchmen frown on damage to the town walls, trees or fountains.
1189 * It's OK to dig holes in the ground, however.
1190 * If mtmp is assumed to be a watchman, a watchman is found if mtmp == 0
1191 * zap == TRUE if wand/spell of digging, FALSE otherwise (chewing)
1193 void
1194 watch_dig(mtmp, x, y, zap)
1195 struct monst *mtmp;
1196 xchar x, y;
1197 boolean zap;
1199 struct rm *lev = &levl[x][y];
1201 if (in_town(x, y)
1202 && (closed_door(x, y) || lev->typ == SDOOR || IS_WALL(lev->typ)
1203 || IS_FOUNTAIN(lev->typ) || IS_TREE(lev->typ))) {
1204 if (!mtmp) {
1205 for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
1206 if (DEADMONSTER(mtmp))
1207 continue;
1208 if (is_watch(mtmp->data) && mtmp->mcansee && m_canseeu(mtmp)
1209 && couldsee(mtmp->mx, mtmp->my) && mtmp->mpeaceful)
1210 break;
1214 if (mtmp) {
1215 if (zap || context.digging.warned) {
1216 verbalize("Halt, vandal! You're under arrest!");
1217 (void) angry_guards(!!Deaf);
1218 } else {
1219 const char *str;
1221 if (IS_DOOR(lev->typ))
1222 str = "door";
1223 else if (IS_TREE(lev->typ))
1224 str = "tree";
1225 else if (IS_ROCK(lev->typ))
1226 str = "wall";
1227 else
1228 str = "fountain";
1229 verbalize("Hey, stop damaging that %s!", str);
1230 context.digging.warned = TRUE;
1232 if (is_digging())
1233 stop_occupation();
1238 /* Return TRUE if monster died, FALSE otherwise. Called from m_move(). */
1239 boolean
1240 mdig_tunnel(mtmp)
1241 register struct monst *mtmp;
1243 register struct rm *here;
1244 int pile = rnd(12);
1246 here = &levl[mtmp->mx][mtmp->my];
1247 if (here->typ == SDOOR)
1248 cvt_sdoor_to_door(here); /* ->typ = DOOR */
1250 /* Eats away door if present & closed or locked */
1251 if (closed_door(mtmp->mx, mtmp->my)) {
1252 if (*in_rooms(mtmp->mx, mtmp->my, SHOPBASE))
1253 add_damage(mtmp->mx, mtmp->my, 0L);
1254 unblock_point(mtmp->mx, mtmp->my); /* vision */
1255 if (here->doormask & D_TRAPPED) {
1256 here->doormask = D_NODOOR;
1257 if (mb_trapped(mtmp)) { /* mtmp is killed */
1258 newsym(mtmp->mx, mtmp->my);
1259 return TRUE;
1261 } else {
1262 if (!rn2(3) && flags.verbose) /* not too often.. */
1263 draft_message(TRUE); /* "You feel an unexpected draft." */
1264 here->doormask = D_BROKEN;
1266 newsym(mtmp->mx, mtmp->my);
1267 return FALSE;
1268 } else if (here->typ == SCORR) {
1269 here->typ = CORR;
1270 unblock_point(mtmp->mx, mtmp->my);
1271 newsym(mtmp->mx, mtmp->my);
1272 draft_message(FALSE); /* "You feel a draft." */
1273 return FALSE;
1274 } else if (!IS_ROCK(here->typ) && !IS_TREE(here->typ)) /* no dig */
1275 return FALSE;
1277 /* Only rock, trees, and walls fall through to this point. */
1278 if ((here->wall_info & W_NONDIGGABLE) != 0) {
1279 impossible("mdig_tunnel: %s at (%d,%d) is undiggable",
1280 (IS_WALL(here->typ) ? "wall"
1281 : IS_TREE(here->typ) ? "tree" : "stone"),
1282 (int) mtmp->mx, (int) mtmp->my);
1283 return FALSE; /* still alive */
1286 if (IS_WALL(here->typ)) {
1287 /* KMH -- Okay on arboreal levels (room walls are still stone) */
1288 if (flags.verbose && !rn2(5))
1289 You_hear("crashing rock.");
1290 if (*in_rooms(mtmp->mx, mtmp->my, SHOPBASE))
1291 add_damage(mtmp->mx, mtmp->my, 0L);
1292 if (level.flags.is_maze_lev) {
1293 here->typ = ROOM;
1294 } else if (level.flags.is_cavernous_lev
1295 && !in_town(mtmp->mx, mtmp->my)) {
1296 here->typ = CORR;
1297 } else {
1298 here->typ = DOOR;
1299 here->doormask = D_NODOOR;
1301 } else if (IS_TREE(here->typ)) {
1302 here->typ = ROOM;
1303 if (pile && pile < 5)
1304 (void) rnd_treefruit_at(mtmp->mx, mtmp->my);
1305 } else {
1306 here->typ = CORR;
1307 if (pile && pile < 5)
1308 (void) mksobj_at((pile == 1) ? BOULDER : ROCK, mtmp->mx, mtmp->my,
1309 TRUE, FALSE);
1311 newsym(mtmp->mx, mtmp->my);
1312 if (!sobj_at(BOULDER, mtmp->mx, mtmp->my))
1313 unblock_point(mtmp->mx, mtmp->my); /* vision */
1315 return FALSE;
1318 #define STRIDENT 4 /* from pray.c */
1320 /* draft refers to air currents, but can be a pun on "draft" as conscription
1321 for military service (probably not a good pun if it has to be explained) */
1322 void
1323 draft_message(unexpected)
1324 boolean unexpected;
1327 * [Bug or TODO? Have caller pass coordinates and use the travel
1328 * mechanism to determine whether there is a path between
1329 * destroyed door (or exposed secret corridor) and hero's location.
1330 * When there is no such path, no draft should be felt.]
1333 if (unexpected) {
1334 if (!Hallucination)
1335 You_feel("an unexpected draft.");
1336 else
1337 /* U.S. classification system uses 1-A for eligible to serve
1338 and 4-F for ineligible due to physical or mental defect;
1339 some intermediate values exist but are rarely seen */
1340 You_feel("like you are %s.",
1341 (ACURR(A_STR) < 6 || ACURR(A_DEX) < 6
1342 || ACURR(A_CON) < 6 || ACURR(A_CHA) < 6
1343 || ACURR(A_INT) < 6 || ACURR(A_WIS) < 6) ? "4-F"
1344 : "1-A");
1345 } else {
1346 if (!Hallucination) {
1347 You_feel("a draft.");
1348 } else {
1349 /* "marching" is deliberately ambiguous; it might mean drills
1350 after entering military service or mean engaging in protests */
1351 static const char *draft_reaction[] = {
1352 "enlisting", "marching", "protesting", "fleeing",
1354 int dridx;
1356 /* Lawful: 0..1, Neutral: 1..2, Chaotic: 2..3 */
1357 dridx = rn1(2, 1 - sgn(u.ualign.type));
1358 if (u.ualign.record < STRIDENT)
1359 /* L: +(0..2), N: +(-1..1), C: +(-2..0); all: 0..3 */
1360 dridx += rn1(3, sgn(u.ualign.type) - 1);
1361 You_feel("like %s.", draft_reaction[dridx]);
1366 /* digging via wand zap or spell cast */
1367 void
1368 zap_dig()
1370 struct rm *room;
1371 struct monst *mtmp;
1372 struct obj *otmp;
1373 struct trap *trap_with_u = (struct trap *) 0;
1374 int zx, zy, diridx = 8, digdepth, flow_x = -1, flow_y = -1;
1375 boolean shopdoor, shopwall, maze_dig, pitdig = FALSE, pitflow = FALSE;
1378 * Original effect (approximately):
1379 * from CORR: dig until we pierce a wall
1380 * from ROOM: pierce wall and dig until we reach
1381 * an ACCESSIBLE place.
1382 * Currently: dig for digdepth positions;
1383 * also down on request of Lennart Augustsson.
1384 * 3.6.0: from a PIT: dig one adjacent pit.
1387 if (u.uswallow) {
1388 mtmp = u.ustuck;
1390 if (!is_whirly(mtmp->data)) {
1391 if (is_animal(mtmp->data))
1392 You("pierce %s %s wall!", s_suffix(mon_nam(mtmp)),
1393 mbodypart(mtmp, STOMACH));
1394 mtmp->mhp = 1; /* almost dead */
1395 expels(mtmp, mtmp->data, !is_animal(mtmp->data));
1397 return;
1398 } /* swallowed */
1400 if (u.dz) {
1401 if (!Is_airlevel(&u.uz) && !Is_waterlevel(&u.uz) && !Underwater) {
1402 if (u.dz < 0 || On_stairs(u.ux, u.uy)) {
1403 int dmg;
1404 if (On_stairs(u.ux, u.uy))
1405 pline_The("beam bounces off the %s and hits the %s.",
1406 (u.ux == xdnladder || u.ux == xupladder)
1407 ? "ladder"
1408 : "stairs",
1409 ceiling(u.ux, u.uy));
1410 You("loosen a rock from the %s.", ceiling(u.ux, u.uy));
1411 pline("It falls on your %s!", body_part(HEAD));
1412 dmg = rnd((uarmh && is_metallic(uarmh)) ? 2 : 6);
1413 losehp(Maybe_Half_Phys(dmg), "falling rock", KILLED_BY_AN);
1414 otmp = mksobj_at(ROCK, u.ux, u.uy, FALSE, FALSE);
1415 if (otmp) {
1416 (void) xname(otmp); /* set dknown, maybe bknown */
1417 stackobj(otmp);
1419 newsym(u.ux, u.uy);
1420 } else {
1421 watch_dig((struct monst *) 0, u.ux, u.uy, TRUE);
1422 (void) dighole(FALSE, TRUE, (coord *) 0);
1425 return;
1426 } /* up or down */
1428 /* normal case: digging across the level */
1429 shopdoor = shopwall = FALSE;
1430 maze_dig = level.flags.is_maze_lev && !Is_earthlevel(&u.uz);
1431 zx = u.ux + u.dx;
1432 zy = u.uy + u.dy;
1433 if (u.utrap && u.utraptype == TT_PIT
1434 && (trap_with_u = t_at(u.ux, u.uy))) {
1435 pitdig = TRUE;
1436 for (diridx = 0; diridx < 8; diridx++) {
1437 if (xdir[diridx] == u.dx && ydir[diridx] == u.dy)
1438 break;
1439 /* diridx is valid if < 8 */
1442 digdepth = rn1(18, 8);
1443 tmp_at(DISP_BEAM, cmap_to_glyph(S_digbeam));
1444 while (--digdepth >= 0) {
1445 if (!isok(zx, zy))
1446 break;
1447 room = &levl[zx][zy];
1448 tmp_at(zx, zy);
1449 delay_output(); /* wait a little bit */
1451 if (pitdig) { /* we are already in a pit if this is true */
1452 coord cc;
1453 struct trap *adjpit = t_at(zx, zy);
1454 if ((diridx < 8) && !conjoined_pits(adjpit, trap_with_u, FALSE)) {
1455 digdepth = 0; /* limited to the adjacent location only */
1456 if (!(adjpit && (adjpit->ttyp == PIT
1457 || adjpit->ttyp == SPIKED_PIT))) {
1458 char buf[BUFSZ];
1459 cc.x = zx;
1460 cc.y = zy;
1461 if (!adj_pit_checks(&cc, buf)) {
1462 if (buf[0])
1463 pline1(buf);
1464 } else {
1465 /* this can also result in a pool at zx,zy */
1466 dighole(TRUE, TRUE, &cc);
1467 adjpit = t_at(zx, zy);
1470 if (adjpit
1471 && (adjpit->ttyp == PIT || adjpit->ttyp == SPIKED_PIT)) {
1472 int adjidx = (diridx + 4) % 8;
1473 trap_with_u->conjoined |= (1 << diridx);
1474 adjpit->conjoined |= (1 << adjidx);
1475 flow_x = zx;
1476 flow_y = zy;
1477 pitflow = TRUE;
1479 if (is_pool(zx, zy) || is_lava(zx, zy)) {
1480 flow_x = zx - u.dx;
1481 flow_y = zy - u.dy;
1482 pitflow = TRUE;
1484 break;
1486 } else if (closed_door(zx, zy) || room->typ == SDOOR) {
1487 if (*in_rooms(zx, zy, SHOPBASE)) {
1488 add_damage(zx, zy, 400L);
1489 shopdoor = TRUE;
1491 if (room->typ == SDOOR)
1492 room->typ = DOOR;
1493 else if (cansee(zx, zy))
1494 pline_The("door is razed!");
1495 watch_dig((struct monst *) 0, zx, zy, TRUE);
1496 room->doormask = D_NODOOR;
1497 unblock_point(zx, zy); /* vision */
1498 digdepth -= 2;
1499 if (maze_dig)
1500 break;
1501 } else if (maze_dig) {
1502 if (IS_WALL(room->typ)) {
1503 if (!(room->wall_info & W_NONDIGGABLE)) {
1504 if (*in_rooms(zx, zy, SHOPBASE)) {
1505 add_damage(zx, zy, 200L);
1506 shopwall = TRUE;
1508 room->typ = ROOM;
1509 unblock_point(zx, zy); /* vision */
1510 } else if (!Blind)
1511 pline_The("wall glows then fades.");
1512 break;
1513 } else if (IS_TREE(room->typ)) { /* check trees before stone */
1514 if (!(room->wall_info & W_NONDIGGABLE)) {
1515 room->typ = ROOM;
1516 unblock_point(zx, zy); /* vision */
1517 } else if (!Blind)
1518 pline_The("tree shudders but is unharmed.");
1519 break;
1520 } else if (room->typ == STONE || room->typ == SCORR) {
1521 if (!(room->wall_info & W_NONDIGGABLE)) {
1522 room->typ = CORR;
1523 unblock_point(zx, zy); /* vision */
1524 } else if (!Blind)
1525 pline_The("rock glows then fades.");
1526 break;
1528 } else if (IS_ROCK(room->typ)) {
1529 if (!may_dig(zx, zy))
1530 break;
1531 if (IS_WALL(room->typ) || room->typ == SDOOR) {
1532 if (*in_rooms(zx, zy, SHOPBASE)) {
1533 add_damage(zx, zy, 200L);
1534 shopwall = TRUE;
1536 watch_dig((struct monst *) 0, zx, zy, TRUE);
1537 if (level.flags.is_cavernous_lev && !in_town(zx, zy)) {
1538 room->typ = CORR;
1539 } else {
1540 room->typ = DOOR;
1541 room->doormask = D_NODOOR;
1543 digdepth -= 2;
1544 } else if (IS_TREE(room->typ)) {
1545 room->typ = ROOM;
1546 digdepth -= 2;
1547 } else { /* IS_ROCK but not IS_WALL or SDOOR */
1548 room->typ = CORR;
1549 digdepth--;
1551 unblock_point(zx, zy); /* vision */
1553 zx += u.dx;
1554 zy += u.dy;
1555 } /* while */
1556 tmp_at(DISP_END, 0); /* closing call */
1558 if (pitflow && isok(flow_x, flow_y)) {
1559 struct trap *ttmp = t_at(flow_x, flow_y);
1560 if (ttmp && (ttmp->ttyp == PIT || ttmp->ttyp == SPIKED_PIT)) {
1561 schar filltyp = fillholetyp(ttmp->tx, ttmp->ty, TRUE);
1562 if (filltyp != ROOM)
1563 pit_flow(ttmp, filltyp);
1567 if (shopdoor || shopwall)
1568 pay_for_damage(shopdoor ? "destroy" : "dig into", FALSE);
1569 return;
1573 * This checks what is on the surface above the
1574 * location where an adjacent pit might be created if
1575 * you're zapping a wand of digging laterally while
1576 * down in the pit.
1578 STATIC_OVL int
1579 adj_pit_checks(cc, msg)
1580 coord *cc;
1581 char *msg;
1583 int ltyp;
1584 struct rm *room;
1585 const char *foundation_msg =
1586 "The foundation is too hard to dig through from this angle.";
1588 if (!cc)
1589 return FALSE;
1590 if (!isok(cc->x, cc->y))
1591 return FALSE;
1592 *msg = '\0';
1593 room = &levl[cc->x][cc->y];
1594 ltyp = room->typ;
1596 if (is_pool(cc->x, cc->y) || is_lava(cc->x, cc->y)) {
1597 /* this is handled by the caller after we return FALSE */
1598 return FALSE;
1599 } else if (closed_door(cc->x, cc->y) || room->typ == SDOOR) {
1600 /* We reject this here because dighole() isn't
1601 prepared to deal with this case */
1602 Strcpy(msg, foundation_msg);
1603 return FALSE;
1604 } else if (IS_WALL(ltyp)) {
1605 /* if (room->wall_info & W_NONDIGGABLE) */
1606 Strcpy(msg, foundation_msg);
1607 return FALSE;
1608 } else if (IS_TREE(ltyp)) { /* check trees before stone */
1609 /* if (room->wall_info & W_NONDIGGABLE) */
1610 Strcpy(msg, "The tree's roots glow then fade.");
1611 return FALSE;
1612 } else if (ltyp == STONE || ltyp == SCORR) {
1613 if (room->wall_info & W_NONDIGGABLE) {
1614 Strcpy(msg, "The rock glows then fades.");
1615 return FALSE;
1617 } else if (ltyp == IRONBARS) {
1618 /* "set of iron bars" */
1619 Strcpy(msg, "The bars go much deeper than your pit.");
1620 #if 0
1621 } else if (is_lava(cc->x, cc->y)) {
1622 } else if (is_ice(cc->x, cc->y)) {
1623 } else if (is_pool(cc->x, cc->y)) {
1624 } else if (IS_GRAVE(ltyp)) {
1625 #endif
1626 } else if (IS_SINK(ltyp)) {
1627 Strcpy(msg, "A tangled mass of plumbing remains below the sink.");
1628 return FALSE;
1629 } else if ((cc->x == xupladder && cc->y == yupladder) /* ladder up */
1630 || (cc->x == xdnladder && cc->y == ydnladder)) { /* " down */
1631 Strcpy(msg, "The ladder is unaffected.");
1632 return FALSE;
1633 } else {
1634 const char *supporting = (const char *) 0;
1636 if (IS_FOUNTAIN(ltyp))
1637 supporting = "fountain";
1638 else if (IS_THRONE(ltyp))
1639 supporting = "throne";
1640 else if (IS_ALTAR(ltyp))
1641 supporting = "altar";
1642 else if ((cc->x == xupstair && cc->y == yupstair)
1643 || (cc->x == sstairs.sx && cc->y == sstairs.sy
1644 && sstairs.up))
1645 /* "staircase up" */
1646 supporting = "stairs";
1647 else if ((cc->x == xdnstair && cc->y == ydnstair)
1648 || (cc->x == sstairs.sx && cc->y == sstairs.sy
1649 && !sstairs.up))
1650 /* "staircase down" */
1651 supporting = "stairs";
1652 else if (ltyp == DRAWBRIDGE_DOWN /* "lowered drawbridge" */
1653 || ltyp == DBWALL) /* "raised drawbridge" */
1654 supporting = "drawbridge";
1656 if (supporting) {
1657 Sprintf(msg, "The %s%ssupporting structures remain intact.",
1658 supporting ? s_suffix(supporting) : "",
1659 supporting ? " " : "");
1660 return FALSE;
1663 return TRUE;
1667 * Ensure that all conjoined pits fill up.
1669 STATIC_OVL void
1670 pit_flow(trap, filltyp)
1671 struct trap *trap;
1672 schar filltyp;
1674 if (trap && (filltyp != ROOM)
1675 && (trap->ttyp == PIT || trap->ttyp == SPIKED_PIT)) {
1676 struct trap t;
1677 int idx;
1679 t = *trap;
1680 levl[trap->tx][trap->ty].typ = filltyp;
1681 liquid_flow(trap->tx, trap->ty, filltyp, trap,
1682 (trap->tx == u.ux && trap->ty == u.uy)
1683 ? "Suddenly %s flows in from the adjacent pit!"
1684 : (char *) 0);
1685 for (idx = 0; idx < 8; ++idx) {
1686 if (t.conjoined & (1 << idx)) {
1687 int x, y;
1688 struct trap *t2;
1690 x = t.tx + xdir[idx];
1691 y = t.ty + ydir[idx];
1692 t2 = t_at(x, y);
1693 #if 0
1694 /* cannot do this back-check; liquid_flow()
1695 * called deltrap() which cleaned up the
1696 * conjoined fields on both pits.
1698 if (t2 && (t2->conjoined & (1 << ((idx + 4) % 8))))
1699 #endif
1700 /* recursion */
1701 pit_flow(t2, filltyp);
1707 struct obj *
1708 buried_ball(cc)
1709 coord *cc;
1711 xchar check_x, check_y;
1712 struct obj *otmp, *otmp2;
1714 if (u.utraptype == TT_BURIEDBALL)
1715 for (otmp = level.buriedobjlist; otmp; otmp = otmp2) {
1716 otmp2 = otmp->nobj;
1717 if (otmp->otyp != HEAVY_IRON_BALL)
1718 continue;
1719 /* try the exact location first */
1720 if (otmp->ox == cc->x && otmp->oy == cc->y)
1721 return otmp;
1722 /* Now try the vicinity */
1724 * (x-2,y-2) (x+2,y-2)
1725 * (x,y)
1726 * (x-2,y+2) (x+2,y+2)
1728 for (check_x = cc->x - 2; check_x <= cc->x + 2; ++check_x)
1729 for (check_y = cc->y - 2; check_y <= cc->y + 2; ++check_y) {
1730 if (check_x == cc->x && check_y == cc->y)
1731 continue;
1732 if (isok(check_x, check_y)
1733 && (otmp->ox == check_x && otmp->oy == check_y)) {
1734 cc->x = check_x;
1735 cc->y = check_y;
1736 return otmp;
1740 return (struct obj *) 0;
1743 void
1744 buried_ball_to_punishment()
1746 coord cc;
1747 struct obj *ball;
1748 cc.x = u.ux;
1749 cc.y = u.uy;
1750 ball = buried_ball(&cc);
1751 if (ball) {
1752 obj_extract_self(ball);
1753 #if 0
1754 /* rusting buried metallic objects is not implemented yet */
1755 if (ball->timed)
1756 (void) stop_timer(RUST_METAL, obj_to_any(ball));
1757 #endif
1758 punish(ball); /* use ball as flag for unearthed buried ball */
1759 u.utrap = 0;
1760 u.utraptype = 0;
1761 del_engr_at(cc.x, cc.y);
1762 newsym(cc.x, cc.y);
1766 void
1767 buried_ball_to_freedom()
1769 coord cc;
1770 struct obj *ball;
1771 cc.x = u.ux;
1772 cc.y = u.uy;
1773 ball = buried_ball(&cc);
1774 if (ball) {
1775 obj_extract_self(ball);
1776 #if 0
1777 /* rusting buried metallic objects is not implemented yet */
1778 if (ball->timed)
1779 (void) stop_timer(RUST_METAL, obj_to_any(ball));
1780 #endif
1781 place_object(ball, cc.x, cc.y);
1782 stackobj(ball);
1783 u.utrap = 0;
1784 u.utraptype = 0;
1785 del_engr_at(cc.x, cc.y);
1786 newsym(cc.x, cc.y);
1790 /* move objects from fobj/nexthere lists to buriedobjlist, keeping position
1791 information */
1792 struct obj *
1793 bury_an_obj(otmp, dealloced)
1794 struct obj *otmp;
1795 boolean *dealloced;
1797 struct obj *otmp2;
1798 boolean under_ice;
1800 debugpline1("bury_an_obj: %s", xname(otmp));
1801 if (dealloced)
1802 *dealloced = FALSE;
1803 if (otmp == uball) {
1804 unpunish();
1805 u.utrap = rn1(50, 20);
1806 u.utraptype = TT_BURIEDBALL;
1807 pline_The("iron ball gets buried!");
1809 /* after unpunish(), or might get deallocated chain */
1810 otmp2 = otmp->nexthere;
1812 * obj_resists(,0,0) prevents Rider corpses from being buried.
1813 * It also prevents The Amulet and invocation tools from being
1814 * buried. Since they can't be confined to bags and statues,
1815 * it makes sense that they can't be buried either, even though
1816 * the real reason there (direct accessibility when carried) is
1817 * completely different.
1819 if (otmp == uchain || obj_resists(otmp, 0, 0))
1820 return otmp2;
1822 if (otmp->otyp == LEASH && otmp->leashmon != 0)
1823 o_unleash(otmp);
1825 if (otmp->lamplit && otmp->otyp != POT_OIL)
1826 end_burn(otmp, TRUE);
1828 obj_extract_self(otmp);
1830 under_ice = is_ice(otmp->ox, otmp->oy);
1831 if (otmp->otyp == ROCK && !under_ice) {
1832 /* merges into burying material */
1833 if (dealloced)
1834 *dealloced = TRUE;
1835 obfree(otmp, (struct obj *) 0);
1836 return otmp2;
1839 * Start a rot on organic material. Not corpses -- they
1840 * are already handled.
1842 if (otmp->otyp == CORPSE) {
1843 ; /* should cancel timer if under_ice */
1844 } else if ((under_ice ? otmp->oclass == POTION_CLASS : is_organic(otmp))
1845 && !obj_resists(otmp, 5, 95)) {
1846 (void) start_timer((under_ice ? 0L : 250L) + (long) rnd(250),
1847 TIMER_OBJECT, ROT_ORGANIC, obj_to_any(otmp));
1848 #if 0
1849 /* rusting of buried metal not yet implemented */
1850 } else if (is_rustprone(otmp)) {
1851 (void) start_timer((long) rnd((otmp->otyp == HEAVY_IRON_BALL)
1852 ? 1500
1853 : 250),
1854 TIMER_OBJECT, RUST_METAL, obj_to_any(otmp));
1855 #endif
1857 add_to_buried(otmp);
1858 return otmp2;
1861 void
1862 bury_objs(x, y)
1863 int x, y;
1865 struct obj *otmp, *otmp2;
1867 if (level.objects[x][y] != (struct obj *) 0) {
1868 debugpline2("bury_objs: at <%d,%d>", x, y);
1870 for (otmp = level.objects[x][y]; otmp; otmp = otmp2)
1871 otmp2 = bury_an_obj(otmp, (boolean *) 0);
1873 /* don't expect any engravings here, but just in case */
1874 del_engr_at(x, y);
1875 newsym(x, y);
1878 /* move objects from buriedobjlist to fobj/nexthere lists */
1879 void
1880 unearth_objs(x, y)
1881 int x, y;
1883 struct obj *otmp, *otmp2, *bball;
1884 coord cc;
1886 debugpline2("unearth_objs: at <%d,%d>", x, y);
1887 cc.x = x;
1888 cc.y = y;
1889 bball = buried_ball(&cc);
1890 for (otmp = level.buriedobjlist; otmp; otmp = otmp2) {
1891 otmp2 = otmp->nobj;
1892 if (otmp->ox == x && otmp->oy == y) {
1893 if (bball && otmp == bball && u.utraptype == TT_BURIEDBALL) {
1894 buried_ball_to_punishment();
1895 } else {
1896 obj_extract_self(otmp);
1897 if (otmp->timed)
1898 (void) stop_timer(ROT_ORGANIC, obj_to_any(otmp));
1899 place_object(otmp, x, y);
1900 stackobj(otmp);
1904 del_engr_at(x, y);
1905 newsym(x, y);
1909 * The organic material has rotted away while buried. As an expansion,
1910 * we could add add partial damage. A damage count is kept in the object
1911 * and every time we are called we increment the count and reschedule another
1912 * timeout. Eventually the object rots away.
1914 * This is used by buried objects other than corpses. When a container rots
1915 * away, any contents become newly buried objects.
1917 /* ARGSUSED */
1918 void
1919 rot_organic(arg, timeout)
1920 anything *arg;
1921 long timeout UNUSED;
1923 struct obj *obj = arg->a_obj;
1925 while (Has_contents(obj)) {
1926 /* We don't need to place contained object on the floor
1927 first, but we do need to update its map coordinates. */
1928 obj->cobj->ox = obj->ox, obj->cobj->oy = obj->oy;
1929 /* Everything which can be held in a container can also be
1930 buried, so bury_an_obj's use of obj_extract_self insures
1931 that Has_contents(obj) will eventually become false. */
1932 (void) bury_an_obj(obj->cobj, (boolean *) 0);
1934 obj_extract_self(obj);
1935 obfree(obj, (struct obj *) 0);
1939 * Called when a corpse has rotted completely away.
1941 void
1942 rot_corpse(arg, timeout)
1943 anything *arg;
1944 long timeout;
1946 xchar x = 0, y = 0;
1947 struct obj *obj = arg->a_obj;
1948 boolean on_floor = obj->where == OBJ_FLOOR,
1949 in_invent = obj->where == OBJ_INVENT;
1951 if (on_floor) {
1952 x = obj->ox;
1953 y = obj->oy;
1954 } else if (in_invent) {
1955 if (flags.verbose) {
1956 char *cname = corpse_xname(obj, (const char *) 0, CXN_NO_PFX);
1958 Your("%s%s %s away%c", obj == uwep ? "wielded " : "", cname,
1959 otense(obj, "rot"), obj == uwep ? '!' : '.');
1961 if (obj == uwep) {
1962 uwepgone(); /* now bare handed */
1963 stop_occupation();
1964 } else if (obj == uswapwep) {
1965 uswapwepgone();
1966 stop_occupation();
1967 } else if (obj == uquiver) {
1968 uqwepgone();
1969 stop_occupation();
1971 } else if (obj->where == OBJ_MINVENT && obj->owornmask) {
1972 if (obj == MON_WEP(obj->ocarry))
1973 setmnotwielded(obj->ocarry, obj);
1974 } else if (obj->where == OBJ_MIGRATING) {
1975 /* clear destination flag so that obfree()'s check for
1976 freeing a worn object doesn't get a false hit */
1977 obj->owornmask = 0L;
1979 rot_organic(arg, timeout);
1980 if (on_floor) {
1981 struct monst *mtmp = m_at(x, y);
1983 /* a hiding monster may be exposed */
1984 if (mtmp && !OBJ_AT(x, y) && mtmp->mundetected
1985 && hides_under(mtmp->data)) {
1986 mtmp->mundetected = 0;
1987 } else if (x == u.ux && y == u.uy && u.uundetected && hides_under(youmonst.data))
1988 (void) hideunder(&youmonst);
1989 newsym(x, y);
1990 } else if (in_invent)
1991 update_inventory();
1994 #if 0
1995 void
1996 bury_monst(mtmp)
1997 struct monst *mtmp;
1999 debugpline1("bury_monst: %s", mon_nam(mtmp));
2000 if (canseemon(mtmp)) {
2001 if (is_flyer(mtmp->data) || is_floater(mtmp->data)) {
2002 pline_The("%s opens up, but %s is not swallowed!",
2003 surface(mtmp->mx, mtmp->my), mon_nam(mtmp));
2004 return;
2005 } else
2006 pline_The("%s opens up and swallows %s!",
2007 surface(mtmp->mx, mtmp->my), mon_nam(mtmp));
2010 mtmp->mburied = TRUE;
2011 wakeup(mtmp, FALSE); /* at least give it a chance :-) */
2012 newsym(mtmp->mx, mtmp->my);
2015 void
2016 bury_you()
2018 debugpline0("bury_you");
2019 if (!Levitation && !Flying) {
2020 if (u.uswallow)
2021 You_feel("a sensation like falling into a trap!");
2022 else
2023 pline_The("%s opens beneath you and you fall in!",
2024 surface(u.ux, u.uy));
2026 u.uburied = TRUE;
2027 if (!Strangled && !Breathless)
2028 Strangled = 6;
2029 under_ground(1);
2033 void
2034 unearth_you()
2036 debugpline0("unearth_you");
2037 u.uburied = FALSE;
2038 under_ground(0);
2039 if (!uamul || uamul->otyp != AMULET_OF_STRANGULATION)
2040 Strangled = 0;
2041 vision_recalc(0);
2044 void
2045 escape_tomb()
2047 debugpline0("escape_tomb");
2048 if ((Teleportation || can_teleport(youmonst.data))
2049 && (Teleport_control || rn2(3) < Luck+2)) {
2050 You("attempt a teleport spell.");
2051 (void) dotele(); /* calls unearth_you() */
2052 } else if (u.uburied) { /* still buried after 'port attempt */
2053 boolean good;
2055 if (amorphous(youmonst.data) || Passes_walls
2056 || noncorporeal(youmonst.data)
2057 || (unsolid(youmonst.data)
2058 && youmonst.data != &mons[PM_WATER_ELEMENTAL])
2059 || (tunnels(youmonst.data) && !needspick(youmonst.data))) {
2060 You("%s up through the %s.",
2061 (tunnels(youmonst.data) && !needspick(youmonst.data))
2062 ? "try to tunnel"
2063 : (amorphous(youmonst.data))
2064 ? "ooze"
2065 : "phase",
2066 surface(u.ux, u.uy));
2068 good = (tunnels(youmonst.data) && !needspick(youmonst.data))
2069 ? dighole(TRUE, FALSE, (coord *)0) : TRUE;
2070 if (good)
2071 unearth_you();
2076 void
2077 bury_obj(otmp)
2078 struct obj *otmp;
2080 debugpline0("bury_obj");
2081 if (cansee(otmp->ox, otmp->oy))
2082 pline_The("objects on the %s tumble into a hole!",
2083 surface(otmp->ox, otmp->oy));
2085 bury_objs(otmp->ox, otmp->oy);
2087 #endif /*0*/
2089 #ifdef DEBUG
2090 /* bury everything at your loc and around */
2092 wiz_debug_cmd_bury()
2094 int x, y;
2096 for (x = u.ux - 1; x <= u.ux + 1; x++)
2097 for (y = u.uy - 1; y <= u.uy + 1; y++)
2098 if (isok(x, y))
2099 bury_objs(x, y);
2100 return 0;
2102 #endif /* DEBUG */
2104 /*dig.c*/