Source:NetHack 3.6.0/src/dig.c

From NetHackWiki
(Redirected from Dig.c)
Jump to: navigation, search

Below is the full text to dig.c from the source code of NetHack 3.6.0. To link to a particular line, write [[Source:NetHack 3.6.0/src/dig.c#line123]], for example.

The NetHack General Public License applies to screenshots, source code and other content from NetHack.

This content was modified from the original NetHack source code distribution (by splitting up NetHack content between wiki pages, and possibly further editing). See the page history for a list of who changed it, and on what dates.

Top of file

  1.  /* NetHack 3.6	dig.c	$NHDT-Date: 1449269915 2015/12/04 22:58:35 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.103 $ */
  2.  /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3.  /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5.  #include "hack.h"
  6.  
  7.  static NEARDATA boolean did_dig_msg;
  8.  
  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));
  17.  
  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
  25.  

rm_waslit

  1.  STATIC_OVL boolean
  2.  rm_waslit()
  3.  {
  4.      register xchar x, y;
  5.  
  6.      if (levl[u.ux][u.uy].typ == ROOM && levl[u.ux][u.uy].waslit)
  7.          return TRUE;
  8.      for (x = u.ux - 2; x < u.ux + 3; x++)
  9.          for (y = u.uy - 1; y < u.uy + 2; y++)
  10.              if (isok(x, y) && levl[x][y].waslit)
  11.                  return TRUE;
  12.      return FALSE;
  13.  }
  14.  

mkcavepos

  1.  /* Change level topology.  Messes with vision tables and ignores things like
  2.   * boulders in the name of a nice effect.  Vision will get fixed up again
  3.   * immediately after the effect is complete.
  4.   */
  5.  STATIC_OVL void
  6.  mkcavepos(x, y, dist, waslit, rockit)
  7.  xchar x, y;
  8.  int dist;
  9.  boolean waslit, rockit;
  10.  {
  11.      register struct rm *lev;
  12.  
  13.      if (!isok(x, y))
  14.          return;
  15.      lev = &levl[x][y];
  16.  
  17.      if (rockit) {
  18.          register struct monst *mtmp;
  19.  
  20.          if (IS_ROCK(lev->typ))
  21.              return;
  22.          if (t_at(x, y))
  23.              return;                   /* don't cover the portal */
  24.          if ((mtmp = m_at(x, y)) != 0) /* make sure crucial monsters survive */
  25.              if (!passes_walls(mtmp->data))
  26.                  (void) rloc(mtmp, TRUE);
  27.      } else if (lev->typ == ROOM)
  28.          return;
  29.  
  30.      unblock_point(x, y); /* make sure vision knows this location is open */
  31.  
  32.      /* fake out saved state */
  33.      lev->seenv = 0;
  34.      lev->doormask = 0;
  35.      if (dist < 3)
  36.          lev->lit = (rockit ? FALSE : TRUE);
  37.      if (waslit)
  38.          lev->waslit = (rockit ? FALSE : TRUE);
  39.      lev->horizontal = FALSE;
  40.      /* short-circuit vision recalc */
  41.      viz_array[y][x] = (dist < 3) ? (IN_SIGHT | COULD_SEE) : COULD_SEE;
  42.      lev->typ = (rockit ? STONE : ROOM);
  43.      if (dist >= 3)
  44.          impossible("mkcavepos called with dist %d", dist);
  45.      feel_newsym(x, y);
  46.  }
  47.  

mkcavearea

  1.  STATIC_OVL void
  2.  mkcavearea(rockit)
  3.  register boolean rockit;
  4.  {
  5.      int dist;
  6.      xchar xmin = u.ux, xmax = u.ux;
  7.      xchar ymin = u.uy, ymax = u.uy;
  8.      register xchar i;
  9.      register boolean waslit = rm_waslit();
  10.  
  11.      if (rockit)
  12.          pline("Crash!  The ceiling collapses around you!");
  13.      else
  14.          pline("A mysterious force %s cave around you!",
  15.                (levl[u.ux][u.uy].typ == CORR) ? "creates a" : "extends the");
  16.      display_nhwindow(WIN_MESSAGE, TRUE);
  17.  
  18.      for (dist = 1; dist <= 2; dist++) {
  19.          xmin--;
  20.          xmax++;
  21.  
  22.          /* top and bottom */
  23.          if (dist < 2) { /* the area is wider that it is high */
  24.              ymin--;
  25.              ymax++;
  26.              for (i = xmin + 1; i < xmax; i++) {
  27.                  mkcavepos(i, ymin, dist, waslit, rockit);
  28.                  mkcavepos(i, ymax, dist, waslit, rockit);
  29.              }
  30.          }
  31.  
  32.          /* left and right */
  33.          for (i = ymin; i <= ymax; i++) {
  34.              mkcavepos(xmin, i, dist, waslit, rockit);
  35.              mkcavepos(xmax, i, dist, waslit, rockit);
  36.          }
  37.  
  38.          flush_screen(1); /* make sure the new glyphs shows up */
  39.          delay_output();
  40.      }
  41.  
  42.      if (!rockit && levl[u.ux][u.uy].typ == CORR) {
  43.          levl[u.ux][u.uy].typ = ROOM;
  44.          if (waslit)
  45.              levl[u.ux][u.uy].waslit = TRUE;
  46.          newsym(u.ux, u.uy); /* in case player is invisible */
  47.      }
  48.  
  49.      vision_full_recalc = 1; /* everything changed */
  50.  }
  51.  

dig_typ

  1.  /* When digging into location <x,y>, what are you actually digging into? */
  2.  int
  3.  dig_typ(otmp, x, y)
  4.  struct obj *otmp;
  5.  xchar x, y;
  6.  {
  7.      boolean ispick;
  8.  
  9.      if (!otmp)
  10.          return DIGTYP_UNDIGGABLE;
  11.      ispick = is_pick(otmp);
  12.      if (!ispick && !is_axe(otmp))
  13.          return DIGTYP_UNDIGGABLE;
  14.  
  15.      return ((ispick && sobj_at(STATUE, x, y))
  16.                 ? DIGTYP_STATUE
  17.                 : (ispick && sobj_at(BOULDER, x, y))
  18.                    ? DIGTYP_BOULDER
  19.                    : closed_door(x, y)
  20.                       ? DIGTYP_DOOR
  21.                       : IS_TREE(levl[x][y].typ)
  22.                          ? (ispick ? DIGTYP_UNDIGGABLE : DIGTYP_TREE)
  23.                          : (ispick && IS_ROCK(levl[x][y].typ)
  24.                             && (!level.flags.arboreal
  25.                                 || IS_WALL(levl[x][y].typ)))
  26.                             ? DIGTYP_ROCK
  27.                             : DIGTYP_UNDIGGABLE);
  28.  }
  29.  

is_digging

  1.  boolean
  2.  is_digging()
  3.  {
  4.      if (occupation == dig) {
  5.          return TRUE;
  6.      }
  7.      return FALSE;
  8.  }
  9.  

dig_check

  1.  #define BY_YOU (&youmonst)
  2.  #define BY_OBJECT ((struct monst *) 0)
  3.  
  4.  boolean
  5.  dig_check(madeby, verbose, x, y)
  6.  struct monst *madeby;
  7.  boolean verbose;
  8.  int x, y;
  9.  {
  10.      struct trap *ttmp = t_at(x, y);
  11.      const char *verb =
  12.          (madeby == BY_YOU && uwep && is_axe(uwep)) ? "chop" : "dig in";
  13.  
  14.      if (On_stairs(x, y)) {
  15.          if (x == xdnladder || x == xupladder) {
  16.              if (verbose)
  17.                  pline_The("ladder resists your effort.");
  18.          } else if (verbose)
  19.              pline_The("stairs are too hard to %s.", verb);
  20.          return FALSE;
  21.      } else if (IS_THRONE(levl[x][y].typ) && madeby != BY_OBJECT) {
  22.          if (verbose)
  23.              pline_The("throne is too hard to break apart.");
  24.          return FALSE;
  25.      } else if (IS_ALTAR(levl[x][y].typ)
  26.                 && (madeby != BY_OBJECT || Is_astralevel(&u.uz)
  27.                     || Is_sanctum(&u.uz))) {
  28.          if (verbose)
  29.              pline_The("altar is too hard to break apart.");
  30.          return FALSE;
  31.      } else if (Is_airlevel(&u.uz)) {
  32.          if (verbose)
  33.              You("cannot %s thin air.", verb);
  34.          return FALSE;
  35.      } else if (Is_waterlevel(&u.uz)) {
  36.          if (verbose)
  37.              pline_The("water splashes and subsides.");
  38.          return FALSE;
  39.      } else if ((IS_ROCK(levl[x][y].typ) && levl[x][y].typ != SDOOR
  40.                  && (levl[x][y].wall_info & W_NONDIGGABLE) != 0)
  41.                 || (ttmp
  42.                     && (ttmp->ttyp == MAGIC_PORTAL
  43.                         || ttmp->ttyp == VIBRATING_SQUARE
  44.                         || (!Can_dig_down(&u.uz) && !levl[x][y].candig)))) {
  45.          if (verbose)
  46.              pline_The("%s here is too hard to %s.", surface(x, y), verb);
  47.          return FALSE;
  48.      } else if (sobj_at(BOULDER, x, y)) {
  49.          if (verbose)
  50.              There("isn't enough room to %s here.", verb);
  51.          return FALSE;
  52.      } else if (madeby == BY_OBJECT
  53.                 /* the block against existing traps is mainly to
  54.                    prevent broken wands from turning holes into pits */
  55.                 && (ttmp || is_pool_or_lava(x, y))) {
  56.          /* digging by player handles pools separately */
  57.          return FALSE;
  58.      }
  59.      return TRUE;
  60.  }
  61.  

dig

  1.  STATIC_OVL int
  2.  dig(VOID_ARGS)
  3.  {
  4.      register struct rm *lev;
  5.      register xchar dpx = context.digging.pos.x, dpy = context.digging.pos.y;
  6.      register boolean ispick = uwep && is_pick(uwep);
  7.      const char *verb = (!uwep || is_pick(uwep)) ? "dig into" : "chop through";
  8.  
  9.      lev = &levl[dpx][dpy];
  10.      /* perhaps a nymph stole your pick-axe while you were busy digging */
  11.      /* or perhaps you teleported away */
  12.      if (u.uswallow || !uwep || (!ispick && !is_axe(uwep))
  13.          || !on_level(&context.digging.level, &u.uz)
  14.          || ((context.digging.down ? (dpx != u.ux || dpy != u.uy)
  15.                                    : (distu(dpx, dpy) > 2))))
  16.          return 0;
  17.  
  18.      if (context.digging.down) {
  19.          if (!dig_check(BY_YOU, TRUE, u.ux, u.uy))
  20.              return 0;
  21.      } else { /* !context.digging.down */
  22.          if (IS_TREE(lev->typ) && !may_dig(dpx, dpy)
  23.              && dig_typ(uwep, dpx, dpy) == DIGTYP_TREE) {
  24.              pline("This tree seems to be petrified.");
  25.              return 0;
  26.          }
  27.          if (IS_ROCK(lev->typ) && !may_dig(dpx, dpy)
  28.              && dig_typ(uwep, dpx, dpy) == DIGTYP_ROCK) {
  29.              pline("This %s is too hard to %s.",
  30.                    is_db_wall(dpx, dpy) ? "drawbridge" : "wall", verb);
  31.              return 0;
  32.          }
  33.      }
  34.      if (Fumbling && !rn2(3)) {
  35.          switch (rn2(3)) {
  36.          case 0:
  37.              if (!welded(uwep)) {
  38.                  You("fumble and drop %s.", yname(uwep));
  39.                  dropx(uwep);
  40.              } else {
  41.                  if (u.usteed)
  42.                      pline("%s and %s %s!", Yobjnam2(uwep, "bounce"),
  43.                            otense(uwep, "hit"), mon_nam(u.usteed));
  44.                  else
  45.                      pline("Ouch!  %s and %s you!", Yobjnam2(uwep, "bounce"),
  46.                            otense(uwep, "hit"));
  47.                  set_wounded_legs(RIGHT_SIDE, 5 + rnd(5));
  48.              }
  49.              break;
  50.          case 1:
  51.              pline("Bang!  You hit with the broad side of %s!",
  52.                    the(xname(uwep)));
  53.              break;
  54.          default:
  55.              Your("swing misses its mark.");
  56.              break;
  57.          }
  58.          return 0;
  59.      }
  60.  
  61.      context.digging.effort +=
  62.          10 + rn2(5) + abon() + uwep->spe - greatest_erosion(uwep) + u.udaminc;
  63.      if (Race_if(PM_DWARF))
  64.          context.digging.effort *= 2;
  65.      if (context.digging.down) {
  66.          struct trap *ttmp = t_at(dpx, dpy);
  67.  
  68.          if (context.digging.effort > 250 || (ttmp && ttmp->ttyp == HOLE)) {
  69.              (void) dighole(FALSE, FALSE, (coord *) 0);
  70.              (void) memset((genericptr_t) &context.digging, 0,
  71.                            sizeof context.digging);
  72.              return 0; /* done with digging */
  73.          }
  74.  
  75.          if (context.digging.effort <= 50
  76.              || (ttmp && (ttmp->ttyp == TRAPDOOR || ttmp->ttyp == PIT
  77.                           || ttmp->ttyp == SPIKED_PIT))) {
  78.              return 1;
  79.          } else if (ttmp && (ttmp->ttyp == LANDMINE
  80.                              || (ttmp->ttyp == BEAR_TRAP && !u.utrap))) {
  81.              /* digging onto a set object trap triggers it;
  82.                 hero should have used #untrap first */
  83.              dotrap(ttmp, FORCETRAP);
  84.              /* restart completely from scratch if we resume digging */
  85.              (void) memset((genericptr_t) &context.digging, 0,
  86.                            sizeof context.digging);
  87.              return 0;
  88.          } else if (ttmp && ttmp->ttyp == BEAR_TRAP && u.utrap) {
  89.              if (rnl(7) > (Fumbling ? 1 : 4)) {
  90.                  char kbuf[BUFSZ];
  91.                  int dmg = dmgval(uwep, &youmonst) + dbon();
  92.  
  93.                  if (dmg < 1)
  94.                      dmg = 1;
  95.                  else if (uarmf)
  96.                      dmg = (dmg + 1) / 2;
  97.                  You("hit yourself in the %s.", body_part(FOOT));
  98.                  Sprintf(kbuf, "chopping off %s own %s", uhis(),
  99.                          body_part(FOOT));
  100.                  losehp(Maybe_Half_Phys(dmg), kbuf, KILLED_BY);
  101.              } else {
  102.                  You("destroy the bear trap with %s.",
  103.                      yobjnam(uwep, (const char *) 0));
  104.                  u.utrap = 0; /* release from trap */
  105.                  deltrap(ttmp);
  106.              }
  107.              /* we haven't made any progress toward a pit yet */
  108.              context.digging.effort = 0;
  109.              return 0;
  110.          }
  111.  
  112.          if (IS_ALTAR(lev->typ)) {
  113.              altar_wrath(dpx, dpy);
  114.              angry_priest();
  115.          }
  116.  
  117.          /* make pit at <u.ux,u.uy> */
  118.          if (dighole(TRUE, FALSE, (coord *) 0)) {
  119.              context.digging.level.dnum = 0;
  120.              context.digging.level.dlevel = -1;
  121.          }
  122.          return 0;
  123.      }
  124.  
  125.      if (context.digging.effort > 100) {
  126.          register const char *digtxt, *dmgtxt = (const char *) 0;
  127.          register struct obj *obj;
  128.          register boolean shopedge = *in_rooms(dpx, dpy, SHOPBASE);
  129.  
  130.          if ((obj = sobj_at(STATUE, dpx, dpy)) != 0) {
  131.              if (break_statue(obj))
  132.                  digtxt = "The statue shatters.";
  133.              else
  134.                  /* it was a statue trap; break_statue()
  135.                   * printed a message and updated the screen
  136.                   */
  137.                  digtxt = (char *) 0;
  138.          } else if ((obj = sobj_at(BOULDER, dpx, dpy)) != 0) {
  139.              struct obj *bobj;
  140.  
  141.              fracture_rock(obj);
  142.              if ((bobj = sobj_at(BOULDER, dpx, dpy)) != 0) {
  143.                  /* another boulder here, restack it to the top */
  144.                  obj_extract_self(bobj);
  145.                  place_object(bobj, dpx, dpy);
  146.              }
  147.              digtxt = "The boulder falls apart.";
  148.          } else if (lev->typ == STONE || lev->typ == SCORR
  149.                     || IS_TREE(lev->typ)) {
  150.              if (Is_earthlevel(&u.uz)) {
  151.                  if (uwep->blessed && !rn2(3)) {
  152.                      mkcavearea(FALSE);
  153.                      goto cleanup;
  154.                  } else if ((uwep->cursed && !rn2(4))
  155.                             || (!uwep->blessed && !rn2(6))) {
  156.                      mkcavearea(TRUE);
  157.                      goto cleanup;
  158.                  }
  159.              }
  160.              if (IS_TREE(lev->typ)) {
  161.                  digtxt = "You cut down the tree.";
  162.                  lev->typ = ROOM;
  163.                  if (!rn2(5))
  164.                      (void) rnd_treefruit_at(dpx, dpy);
  165.              } else {
  166.                  digtxt = "You succeed in cutting away some rock.";
  167.                  lev->typ = CORR;
  168.              }
  169.          } else if (IS_WALL(lev->typ)) {
  170.              if (shopedge) {
  171.                  add_damage(dpx, dpy, 10L * ACURRSTR);
  172.                  dmgtxt = "damage";
  173.              }
  174.              if (level.flags.is_maze_lev) {
  175.                  lev->typ = ROOM;
  176.              } else if (level.flags.is_cavernous_lev && !in_town(dpx, dpy)) {
  177.                  lev->typ = CORR;
  178.              } else {
  179.                  lev->typ = DOOR;
  180.                  lev->doormask = D_NODOOR;
  181.              }
  182.              digtxt = "You make an opening in the wall.";
  183.          } else if (lev->typ == SDOOR) {
  184.              cvt_sdoor_to_door(lev); /* ->typ = DOOR */
  185.              digtxt = "You break through a secret door!";
  186.              if (!(lev->doormask & D_TRAPPED))
  187.                  lev->doormask = D_BROKEN;
  188.          } else if (closed_door(dpx, dpy)) {
  189.              digtxt = "You break through the door.";
  190.              if (shopedge) {
  191.                  add_damage(dpx, dpy, 400L);
  192.                  dmgtxt = "break";
  193.              }
  194.              if (!(lev->doormask & D_TRAPPED))
  195.                  lev->doormask = D_BROKEN;
  196.          } else
  197.              return 0; /* statue or boulder got taken */
  198.  
  199.          if (!does_block(dpx, dpy, &levl[dpx][dpy]))
  200.              unblock_point(dpx, dpy); /* vision:  can see through */
  201.          feel_newsym(dpx, dpy);
  202.          if (digtxt && !context.digging.quiet)
  203.              pline1(digtxt); /* after newsym */
  204.          if (dmgtxt)
  205.              pay_for_damage(dmgtxt, FALSE);
  206.  
  207.          if (Is_earthlevel(&u.uz) && !rn2(3)) {
  208.              register struct monst *mtmp;
  209.  
  210.              switch (rn2(2)) {
  211.              case 0:
  212.                  mtmp = makemon(&mons[PM_EARTH_ELEMENTAL], dpx, dpy,
  213.                                 NO_MM_FLAGS);
  214.                  break;
  215.              default:
  216.                  mtmp = makemon(&mons[PM_XORN], dpx, dpy, NO_MM_FLAGS);
  217.                  break;
  218.              }
  219.              if (mtmp)
  220.                  pline_The("debris from your digging comes to life!");
  221.          }
  222.          if (IS_DOOR(lev->typ) && (lev->doormask & D_TRAPPED)) {
  223.              lev->doormask = D_NODOOR;
  224.              b_trapped("door", 0);
  225.              newsym(dpx, dpy);
  226.          }
  227.      cleanup:
  228.          context.digging.lastdigtime = moves;
  229.          context.digging.quiet = FALSE;
  230.          context.digging.level.dnum = 0;
  231.          context.digging.level.dlevel = -1;
  232.          return 0;
  233.      } else { /* not enough effort has been spent yet */
  234.          static const char *const d_target[6] = { "",        "rock", "statue",
  235.                                                   "boulder", "door", "tree" };
  236.          int dig_target = dig_typ(uwep, dpx, dpy);
  237.  
  238.          if (IS_WALL(lev->typ) || dig_target == DIGTYP_DOOR) {
  239.              if (*in_rooms(dpx, dpy, SHOPBASE)) {
  240.                  pline("This %s seems too hard to %s.",
  241.                        IS_DOOR(lev->typ) ? "door" : "wall", verb);
  242.                  return 0;
  243.              }
  244.          } else if (dig_target == DIGTYP_UNDIGGABLE
  245.                     || (dig_target == DIGTYP_ROCK && !IS_ROCK(lev->typ)))
  246.              return 0; /* statue or boulder got taken */
  247.  
  248.          if (!did_dig_msg) {
  249.              You("hit the %s with all your might.", d_target[dig_target]);
  250.              did_dig_msg = TRUE;
  251.          }
  252.      }
  253.      return 1;
  254.  }
  255.  

holetime

  1.  /* When will hole be finished? Very rough indication used by shopkeeper. */
  2.  int
  3.  holetime()
  4.  {
  5.      if (occupation != dig || !*u.ushops)
  6.          return -1;
  7.      return ((250 - context.digging.effort) / 20);
  8.  }
  9.  

fillholetyp

  1.  /* Return typ of liquid to fill a hole with, or ROOM, if no liquid nearby */
  2.  schar
  3.  fillholetyp(x, y, fill_if_any)
  4.  int x, y;
  5.  boolean fill_if_any; /* force filling if it exists at all */
  6.  {
  7.      register int x1, y1;
  8.      int lo_x = max(1, x - 1), hi_x = min(x + 1, COLNO - 1),
  9.          lo_y = max(0, y - 1), hi_y = min(y + 1, ROWNO - 1);
  10.      int pool_cnt = 0, moat_cnt = 0, lava_cnt = 0;
  11.  
  12.      for (x1 = lo_x; x1 <= hi_x; x1++)
  13.          for (y1 = lo_y; y1 <= hi_y; y1++)
  14.              if (is_moat(x1, y1))
  15.                  moat_cnt++;
  16.              else if (is_pool(x1, y1))
  17.                  /* This must come after is_moat since moats are pools
  18.                   * but not vice-versa. */
  19.                  pool_cnt++;
  20.              else if (is_lava(x1, y1))
  21.                  lava_cnt++;
  22.  
  23.      if (!fill_if_any)
  24.          pool_cnt /= 3; /* not as much liquid as the others */
  25.  
  26.      if ((lava_cnt > moat_cnt + pool_cnt && rn2(lava_cnt + 1))
  27.          || (lava_cnt && fill_if_any))
  28.          return LAVAPOOL;
  29.      else if ((moat_cnt > 0 && rn2(moat_cnt + 1)) || (moat_cnt && fill_if_any))
  30.          return MOAT;
  31.      else if ((pool_cnt > 0 && rn2(pool_cnt + 1)) || (pool_cnt && fill_if_any))
  32.          return POOL;
  33.      else
  34.          return ROOM;
  35.  }
  36.  

digactualhole

  1.  void
  2.  digactualhole(x, y, madeby, ttyp)
  3.  register int x, y;
  4.  struct monst *madeby;
  5.  int ttyp;
  6.  {
  7.      struct obj *oldobjs, *newobjs;
  8.      register struct trap *ttmp;
  9.      char surface_type[BUFSZ];
  10.      struct rm *lev = &levl[x][y];
  11.      boolean shopdoor;
  12.      struct monst *mtmp = m_at(x, y); /* may be madeby */
  13.      boolean madeby_u = (madeby == BY_YOU);
  14.      boolean madeby_obj = (madeby == BY_OBJECT);
  15.      boolean at_u = (x == u.ux) && (y == u.uy);
  16.      boolean wont_fall = Levitation || Flying;
  17.  
  18.      if (at_u && u.utrap) {
  19.          if (u.utraptype == TT_BURIEDBALL)
  20.              buried_ball_to_punishment();
  21.          else if (u.utraptype == TT_INFLOOR)
  22.              u.utrap = 0;
  23.      }
  24.  
  25.      /* these furniture checks were in dighole(), but wand
  26.         breaking bypasses that routine and calls us directly */
  27.      if (IS_FOUNTAIN(lev->typ)) {
  28.          dogushforth(FALSE);
  29.          SET_FOUNTAIN_WARNED(x, y); /* force dryup */
  30.          dryup(x, y, madeby_u);
  31.          return;
  32.      } else if (IS_SINK(lev->typ)) {
  33.          breaksink(x, y);
  34.          return;
  35.      } else if (lev->typ == DRAWBRIDGE_DOWN
  36.                 || (is_drawbridge_wall(x, y) >= 0)) {
  37.          int bx = x, by = y;
  38.          /* if under the portcullis, the bridge is adjacent */
  39.          (void) find_drawbridge(&bx, &by);
  40.          destroy_drawbridge(bx, by);
  41.          return;
  42.      }
  43.  
  44.      if (ttyp != PIT && (!Can_dig_down(&u.uz) && !lev->candig)) {
  45.          impossible("digactualhole: can't dig %s on this level.",
  46.                     defsyms[trap_to_defsym(ttyp)].explanation);
  47.          ttyp = PIT;
  48.      }
  49.  
  50.      /* maketrap() might change it, also, in this situation,
  51.         surface() returns an inappropriate string for a grave */
  52.      if (IS_GRAVE(lev->typ))
  53.          Strcpy(surface_type, "grave");
  54.      else
  55.          Strcpy(surface_type, surface(x, y));
  56.      shopdoor = IS_DOOR(lev->typ) && *in_rooms(x, y, SHOPBASE);
  57.      oldobjs = level.objects[x][y];
  58.      ttmp = maketrap(x, y, ttyp);
  59.      if (!ttmp)
  60.          return;
  61.      newobjs = level.objects[x][y];
  62.      ttmp->madeby_u = madeby_u;
  63.      ttmp->tseen = 0;
  64.      if (cansee(x, y))
  65.          seetrap(ttmp);
  66.      else if (madeby_u)
  67.          feeltrap(ttmp);
  68.  
  69.      if (ttyp == PIT) {
  70.          if (madeby_u) {
  71.              if (x != u.ux || y != u.uy)
  72.                  You("dig an adjacent pit.");
  73.              else
  74.                  You("dig a pit in the %s.", surface_type);
  75.              if (shopdoor)
  76.                  pay_for_damage("ruin", FALSE);
  77.          } else if (!madeby_obj && canseemon(madeby))
  78.              pline("%s digs a pit in the %s.", Monnam(madeby), surface_type);
  79.          else if (cansee(x, y) && flags.verbose)
  80.              pline("A pit appears in the %s.", surface_type);
  81.  
  82.          if (at_u) {
  83.              if (!wont_fall) {
  84.                  u.utrap = rn1(4, 2);
  85.                  u.utraptype = TT_PIT;
  86.                  vision_full_recalc = 1; /* vision limits change */
  87.              } else
  88.                  u.utrap = 0;
  89.              if (oldobjs != newobjs) /* something unearthed */
  90.                  (void) pickup(1);   /* detects pit */
  91.          } else if (mtmp) {
  92.              if (is_flyer(mtmp->data) || is_floater(mtmp->data)) {
  93.                  if (canseemon(mtmp))
  94.                      pline("%s %s over the pit.", Monnam(mtmp),
  95.                            (is_flyer(mtmp->data)) ? "flies" : "floats");
  96.              } else if (mtmp != madeby)
  97.                  (void) mintrap(mtmp);
  98.          }
  99.      } else { /* was TRAPDOOR now a HOLE*/
  100.  
  101.          if (madeby_u)
  102.              You("dig a hole through the %s.", surface_type);
  103.          else if (!madeby_obj && canseemon(madeby))
  104.              pline("%s digs a hole through the %s.", Monnam(madeby),
  105.                    surface_type);
  106.          else if (cansee(x, y) && flags.verbose)
  107.              pline("A hole appears in the %s.", surface_type);
  108.  
  109.          if (at_u) {
  110.              if (!u.ustuck && !wont_fall && !next_to_u()) {
  111.                  You("are jerked back by your pet!");
  112.                  wont_fall = TRUE;
  113.              }
  114.  
  115.              /* Floor objects get a chance of falling down.  The case where
  116.               * the hero does NOT fall down is treated here.  The case
  117.               * where the hero does fall down is treated in goto_level().
  118.               */
  119.              if (u.ustuck || wont_fall) {
  120.                  if (newobjs)
  121.                      impact_drop((struct obj *) 0, x, y, 0);
  122.                  if (oldobjs != newobjs)
  123.                      (void) pickup(1);
  124.                  if (shopdoor && madeby_u)
  125.                      pay_for_damage("ruin", FALSE);
  126.  
  127.              } else {
  128.                  d_level newlevel;
  129.  
  130.                  if (*u.ushops && madeby_u)
  131.                      shopdig(1); /* shk might snatch pack */
  132.                  /* handle earlier damage, eg breaking wand of digging */
  133.                  else if (!madeby_u)
  134.                      pay_for_damage("dig into", TRUE);
  135.  
  136.                  You("fall through...");
  137.                  /* Earlier checks must ensure that the destination
  138.                   * level exists and is in the present dungeon.
  139.                   */
  140.                  newlevel.dnum = u.uz.dnum;
  141.                  newlevel.dlevel = u.uz.dlevel + 1;
  142.                  goto_level(&newlevel, FALSE, TRUE, FALSE);
  143.                  /* messages for arriving in special rooms */
  144.                  spoteffects(FALSE);
  145.              }
  146.          } else {
  147.              if (shopdoor && madeby_u)
  148.                  pay_for_damage("ruin", FALSE);
  149.              if (newobjs)
  150.                  impact_drop((struct obj *) 0, x, y, 0);
  151.              if (mtmp) {
  152.                  /*[don't we need special sokoban handling here?]*/
  153.                  if (is_flyer(mtmp->data) || is_floater(mtmp->data)
  154.                      || mtmp->data == &mons[PM_WUMPUS]
  155.                      || (mtmp->wormno && count_wsegs(mtmp) > 5)
  156.                      || mtmp->data->msize >= MZ_HUGE)
  157.                      return;
  158.                  if (mtmp == u.ustuck) /* probably a vortex */
  159.                      return;           /* temporary? kludge */
  160.  
  161.                  if (teleport_pet(mtmp, FALSE)) {
  162.                      d_level tolevel;
  163.  
  164.                      if (Is_stronghold(&u.uz)) {
  165.                          assign_level(&tolevel, &valley_level);
  166.                      } else if (Is_botlevel(&u.uz)) {
  167.                          if (canseemon(mtmp))
  168.                              pline("%s avoids the trap.", Monnam(mtmp));
  169.                          return;
  170.                      } else {
  171.                          get_level(&tolevel, depth(&u.uz) + 1);
  172.                      }
  173.                      if (mtmp->isshk)
  174.                          make_angry_shk(mtmp, 0, 0);
  175.                      migrate_to_level(mtmp, ledger_no(&tolevel), MIGR_RANDOM,
  176.                                       (coord *) 0);
  177.                  }
  178.              }
  179.          }
  180.      }
  181.  }
  182.  

liquid_flow

  1.  /*
  2.   * Called from dighole(), but also from do_break_wand()
  3.   * in apply.c.
  4.   */
  5.  void
  6.  liquid_flow(x, y, typ, ttmp, fillmsg)
  7.  xchar x, y;
  8.  schar typ;
  9.  struct trap *ttmp;
  10.  const char *fillmsg;
  11.  {
  12.      boolean u_spot = (x == u.ux && y == u.uy);
  13.  
  14.      if (ttmp)
  15.          (void) delfloortrap(ttmp);
  16.      /* if any objects were frozen here, they're released now */
  17.      unearth_objs(x, y);
  18.  
  19.      if (fillmsg)
  20.          pline(fillmsg, typ == LAVAPOOL ? "lava" : "water");
  21.      if (u_spot && !(Levitation || Flying)) {
  22.          if (typ == LAVAPOOL)
  23.              (void) lava_effects();
  24.          else if (!Wwalking)
  25.              (void) drown();
  26.      }
  27.  }
  28.  

dighole

  1.  /* return TRUE if digging succeeded, FALSE otherwise */
  2.  boolean
  3.  dighole(pit_only, by_magic, cc)
  4.  boolean pit_only, by_magic;
  5.  coord *cc;
  6.  {
  7.      register struct trap *ttmp;
  8.      struct rm *lev;
  9.      struct obj *boulder_here;
  10.      schar typ;
  11.      xchar dig_x, dig_y;
  12.      boolean nohole;
  13.  
  14.      if (!cc) {
  15.          dig_x = u.ux;
  16.          dig_y = u.uy;
  17.      } else {
  18.          dig_x = cc->x;
  19.          dig_y = cc->y;
  20.          if (!isok(dig_x, dig_y))
  21.              return FALSE;
  22.      }
  23.  
  24.      ttmp = t_at(dig_x, dig_y);
  25.      lev = &levl[dig_x][dig_y];
  26.      nohole = (!Can_dig_down(&u.uz) && !lev->candig);
  27.  
  28.      if ((ttmp && (ttmp->ttyp == MAGIC_PORTAL
  29.                    || ttmp->ttyp == VIBRATING_SQUARE || nohole))
  30.          || (IS_ROCK(lev->typ) && lev->typ != SDOOR
  31.              && (lev->wall_info & W_NONDIGGABLE) != 0)) {
  32.          pline_The("%s %shere is too hard to dig in.", surface(dig_x, dig_y),
  33.                    (dig_x != u.ux || dig_y != u.uy) ? "t" : "");
  34.  
  35.      } else if (is_pool_or_lava(dig_x, dig_y)) {
  36.          pline_The("%s sloshes furiously for a moment, then subsides.",
  37.                    is_lava(dig_x, dig_y) ? "lava" : "water");
  38.          wake_nearby(); /* splashing */
  39.  
  40.      } else if (lev->typ == DRAWBRIDGE_DOWN
  41.                 || (is_drawbridge_wall(dig_x, dig_y) >= 0)) {
  42.          /* drawbridge_down is the platform crossing the moat when the
  43.             bridge is extended; drawbridge_wall is the open "doorway" or
  44.             closed "door" where the portcullis/mechanism is located */
  45.          if (pit_only) {
  46.              pline_The("drawbridge seems too hard to dig through.");
  47.              return FALSE;
  48.          } else {
  49.              int x = dig_x, y = dig_y;
  50.              /* if under the portcullis, the bridge is adjacent */
  51.              (void) find_drawbridge(&x, &y);
  52.              destroy_drawbridge(x, y);
  53.              return TRUE;
  54.          }
  55.  
  56.      } else if ((boulder_here = sobj_at(BOULDER, dig_x, dig_y)) != 0) {
  57.          if (ttmp && (ttmp->ttyp == PIT || ttmp->ttyp == SPIKED_PIT)
  58.              && rn2(2)) {
  59.              pline_The("boulder settles into the %spit.",
  60.                        (dig_x != u.ux || dig_y != u.uy) ? "adjacent " : "");
  61.              ttmp->ttyp = PIT; /* crush spikes */
  62.          } else {
  63.              /*
  64.               * digging makes a hole, but the boulder immediately
  65.               * fills it.  Final outcome:  no hole, no boulder.
  66.               */
  67.              pline("KADOOM! The boulder falls in!");
  68.              (void) delfloortrap(ttmp);
  69.          }
  70.          delobj(boulder_here);
  71.          return TRUE;
  72.  
  73.      } else if (IS_GRAVE(lev->typ)) {
  74.          digactualhole(dig_x, dig_y, BY_YOU, PIT);
  75.          dig_up_grave(cc);
  76.          return TRUE;
  77.      } else if (lev->typ == DRAWBRIDGE_UP) {
  78.          /* must be floor or ice, other cases handled above */
  79.          /* dig "pit" and let fluid flow in (if possible) */
  80.          typ = fillholetyp(dig_x, dig_y, FALSE);
  81.  
  82.          if (typ == ROOM) {
  83.              /*
  84.               * We can't dig a hole here since that will destroy
  85.               * the drawbridge.  The following is a cop-out. --dlc
  86.               */
  87.              pline_The("%s %shere is too hard to dig in.",
  88.                        surface(dig_x, dig_y),
  89.                        (dig_x != u.ux || dig_y != u.uy) ? "t" : "");
  90.              return FALSE;
  91.          }
  92.  
  93.          lev->drawbridgemask &= ~DB_UNDER;
  94.          lev->drawbridgemask |= (typ == LAVAPOOL) ? DB_LAVA : DB_MOAT;
  95.          liquid_flow(dig_x, dig_y, typ, ttmp,
  96.                      "As you dig, the hole fills with %s!");
  97.          return TRUE;
  98.  
  99.          /* the following two are here for the wand of digging */
  100.      } else if (IS_THRONE(lev->typ)) {
  101.          pline_The("throne is too hard to break apart.");
  102.  
  103.      } else if (IS_ALTAR(lev->typ)) {
  104.          pline_The("altar is too hard to break apart.");
  105.  
  106.      } else {
  107.          typ = fillholetyp(dig_x, dig_y, FALSE);
  108.  
  109.          if (typ != ROOM) {
  110.              lev->typ = typ;
  111.              liquid_flow(dig_x, dig_y, typ, ttmp,
  112.                          "As you dig, the hole fills with %s!");
  113.              return TRUE;
  114.          }
  115.  
  116.          /* magical digging disarms settable traps */
  117.          if (by_magic && ttmp
  118.              && (ttmp->ttyp == LANDMINE || ttmp->ttyp == BEAR_TRAP)) {
  119.              int otyp = (ttmp->ttyp == LANDMINE) ? LAND_MINE : BEARTRAP;
  120.  
  121.              /* convert trap into buried object (deletes trap) */
  122.              cnv_trap_obj(otyp, 1, ttmp, TRUE);
  123.          }
  124.  
  125.          /* finally we get to make a hole */
  126.          if (nohole || pit_only)
  127.              digactualhole(dig_x, dig_y, BY_YOU, PIT);
  128.          else
  129.              digactualhole(dig_x, dig_y, BY_YOU, HOLE);
  130.  
  131.          return TRUE;
  132.      }
  133.  
  134.      return FALSE;
  135.  }
  136.  

dig_up_grave

  1.  STATIC_OVL void
  2.  dig_up_grave(cc)
  3.  coord *cc;
  4.  {
  5.      struct obj *otmp;
  6.      xchar dig_x, dig_y;
  7.  
  8.      if (!cc) {
  9.          dig_x = u.ux;
  10.          dig_y = u.uy;
  11.      } else {
  12.          dig_x = cc->x;
  13.          dig_y = cc->y;
  14.          if (!isok(dig_x, dig_y))
  15.              return;
  16.      }
  17.  
  18.      /* Grave-robbing is frowned upon... */
  19.      exercise(A_WIS, FALSE);
  20.      if (Role_if(PM_ARCHEOLOGIST)) {
  21.          adjalign(-sgn(u.ualign.type) * 3);
  22.          You_feel("like a despicable grave-robber!");
  23.      } else if (Role_if(PM_SAMURAI)) {
  24.          adjalign(-sgn(u.ualign.type));
  25.          You("disturb the honorable dead!");
  26.      } else if ((u.ualign.type == A_LAWFUL) && (u.ualign.record > -10)) {
  27.          adjalign(-sgn(u.ualign.type));
  28.          You("have violated the sanctity of this grave!");
  29.      }
  30.  
  31.      switch (rn2(5)) {
  32.      case 0:
  33.      case 1:
  34.          You("unearth a corpse.");
  35.          if (!!(otmp = mk_tt_object(CORPSE, dig_x, dig_y)))
  36.              otmp->age -= 100; /* this is an *OLD* corpse */
  37.          ;
  38.          break;
  39.      case 2:
  40.          if (!Blind)
  41.              pline(Hallucination ? "Dude!  The living dead!"
  42.                                  : "The grave's owner is very upset!");
  43.          (void) makemon(mkclass(S_ZOMBIE, 0), dig_x, dig_y, NO_MM_FLAGS);
  44.          break;
  45.      case 3:
  46.          if (!Blind)
  47.              pline(Hallucination ? "I want my mummy!"
  48.                                  : "You've disturbed a tomb!");
  49.          (void) makemon(mkclass(S_MUMMY, 0), dig_x, dig_y, NO_MM_FLAGS);
  50.          break;
  51.      default:
  52.          /* No corpse */
  53.          pline_The("grave seems unused.  Strange....");
  54.          break;
  55.      }
  56.      levl[dig_x][dig_y].typ = ROOM;
  57.      del_engr_at(dig_x, dig_y);
  58.      newsym(dig_x, dig_y);
  59.      return;
  60.  }
  61.  

use_pick_axe

  1.  int
  2.  use_pick_axe(obj)
  3.  struct obj *obj;
  4.  {
  5.      const char *sdp, *verb;
  6.      char *dsp, dirsyms[12], qbuf[BUFSZ];
  7.      boolean ispick;
  8.      int rx, ry, downok, res = 0;
  9.  
  10.      /* Check tool */
  11.      if (obj != uwep) {
  12.          if (!wield_tool(obj, "swing"))
  13.              return 0;
  14.          else
  15.              res = 1;
  16.      }
  17.      ispick = is_pick(obj);
  18.      verb = ispick ? "dig" : "chop";
  19.  
  20.      if (u.utrap && u.utraptype == TT_WEB) {
  21.          pline("%s you can't %s while entangled in a web.",
  22.                /* res==0 => no prior message;
  23.                   res==1 => just got "You now wield a pick-axe." message */
  24.                !res ? "Unfortunately," : "But", verb);
  25.          return res;
  26.      }
  27.  
  28.      /* construct list of directions to show player for likely choices */
  29.      downok = !!can_reach_floor(FALSE);
  30.      dsp = dirsyms;
  31.      for (sdp = Cmd.dirchars; *sdp; ++sdp) {
  32.          /* filter out useless directions */
  33.          if (u.uswallow) {
  34.              ; /* all directions are viable when swallowed */
  35.          } else if (movecmd(*sdp)) {
  36.              /* normal direction, within plane of the level map;
  37.                 movecmd() sets u.dx, u.dy, u.dz and returns !u.dz */
  38.              if (!dxdy_moveok())
  39.                  continue; /* handle NODIAG */
  40.              rx = u.ux + u.dx;
  41.              ry = u.uy + u.dy;
  42.              if (!isok(rx, ry) || dig_typ(obj, rx, ry) == DIGTYP_UNDIGGABLE)
  43.                  continue;
  44.          } else {
  45.              /* up or down; we used to always include down, so that
  46.                 there would always be at least one choice shown, but
  47.                 it shouldn't be a likely candidate when floating high
  48.                 above the floor; include up instead in that situation
  49.                 (as a silly candidate rather than a likely one...) */
  50.              if ((u.dz > 0) ^ downok)
  51.                  continue;
  52.          }
  53.          /* include this direction */
  54.          *dsp++ = *sdp;
  55.      }
  56.      *dsp = 0;
  57.      Sprintf(qbuf, "In what direction do you want to %s? [%s]", verb, dirsyms);
  58.      if (!getdir(qbuf))
  59.          return res;
  60.  
  61.      return use_pick_axe2(obj);
  62.  }
  63.  

use_pick_axe2

  1.  /* MRKR: use_pick_axe() is split in two to allow autodig to bypass */
  2.  /*       the "In what direction do you want to dig?" query.        */
  3.  /*       use_pick_axe2() uses the existing u.dx, u.dy and u.dz    */
  4.  int
  5.  use_pick_axe2(obj)
  6.  struct obj *obj;
  7.  {
  8.      register int rx, ry;
  9.      register struct rm *lev;
  10.      struct trap *trap, *trap_with_u;
  11.      int dig_target;
  12.      boolean ispick = is_pick(obj);
  13.      const char *verbing = ispick ? "digging" : "chopping";
  14.  
  15.      if (u.uswallow && attack(u.ustuck)) {
  16.          ; /* return 1 */
  17.      } else if (Underwater) {
  18.          pline("Turbulence torpedoes your %s attempts.", verbing);
  19.      } else if (u.dz < 0) {
  20.          if (Levitation)
  21.              You("don't have enough leverage.");
  22.          else
  23.              You_cant("reach the %s.", ceiling(u.ux, u.uy));
  24.      } else if (!u.dx && !u.dy && !u.dz) {
  25.          char buf[BUFSZ];
  26.          int dam;
  27.  
  28.          dam = rnd(2) + dbon() + obj->spe;
  29.          if (dam <= 0)
  30.              dam = 1;
  31.          You("hit yourself with %s.", yname(uwep));
  32.          Sprintf(buf, "%s own %s", uhis(), OBJ_NAME(objects[obj->otyp]));
  33.          losehp(Maybe_Half_Phys(dam), buf, KILLED_BY);
  34.          context.botl = 1;
  35.          return 1;
  36.      } else if (u.dz == 0) {
  37.          if (Stunned || (Confusion && !rn2(5)))
  38.              confdir();
  39.          rx = u.ux + u.dx;
  40.          ry = u.uy + u.dy;
  41.          if (!isok(rx, ry)) {
  42.              pline("Clash!");
  43.              return 1;
  44.          }
  45.          lev = &levl[rx][ry];
  46.          if (MON_AT(rx, ry) && attack(m_at(rx, ry)))
  47.              return 1;
  48.          dig_target = dig_typ(obj, rx, ry);
  49.          if (dig_target == DIGTYP_UNDIGGABLE) {
  50.              /* ACCESSIBLE or POOL */
  51.              trap = t_at(rx, ry);
  52.              if (trap && trap->ttyp == WEB) {
  53.                  if (!trap->tseen) {
  54.                      seetrap(trap);
  55.                      There("is a spider web there!");
  56.                  }
  57.                  pline("%s entangled in the web.", Yobjnam2(obj, "become"));
  58.                  /* you ought to be able to let go; tough luck */
  59.                  /* (maybe `move_into_trap()' would be better) */
  60.                  nomul(-d(2, 2));
  61.                  multi_reason = "stuck in a spider web";
  62.                  nomovemsg = "You pull free.";
  63.              } else if (lev->typ == IRONBARS) {
  64.                  pline("Clang!");
  65.                  wake_nearby();
  66.              } else if (IS_TREE(lev->typ))
  67.                  You("need an axe to cut down a tree.");
  68.              else if (IS_ROCK(lev->typ))
  69.                  You("need a pick to dig rock.");
  70.              else if (!ispick && (sobj_at(STATUE, rx, ry)
  71.                                   || sobj_at(BOULDER, rx, ry))) {
  72.                  boolean vibrate = !rn2(3);
  73.                  pline("Sparks fly as you whack the %s.%s",
  74.                        sobj_at(STATUE, rx, ry) ? "statue" : "boulder",
  75.                        vibrate ? " The axe-handle vibrates violently!" : "");
  76.                  if (vibrate)
  77.                      losehp(Maybe_Half_Phys(2), "axing a hard object",
  78.                             KILLED_BY);
  79.              } else if (u.utrap && u.utraptype == TT_PIT && trap
  80.                         && (trap_with_u = t_at(u.ux, u.uy))
  81.                         && (trap->ttyp == PIT || trap->ttyp == SPIKED_PIT)
  82.                         && !conjoined_pits(trap, trap_with_u, FALSE)) {
  83.                  int idx;
  84.                  for (idx = 0; idx < 8; idx++) {
  85.                      if (xdir[idx] == u.dx && ydir[idx] == u.dy)
  86.                          break;
  87.                  }
  88.                  /* idx is valid if < 8 */
  89.                  if (idx < 8) {
  90.                      int adjidx = (idx + 4) % 8;
  91.                      trap_with_u->conjoined |= (1 << idx);
  92.                      trap->conjoined |= (1 << adjidx);
  93.                      pline("You clear some debris from between the pits.");
  94.                  }
  95.              } else if (u.utrap && u.utraptype == TT_PIT
  96.                         && (trap_with_u = t_at(u.ux, u.uy))) {
  97.                  You("swing %s, but the rubble has no place to go.",
  98.                      yobjnam(obj, (char *) 0));
  99.              } else
  100.                  You("swing %s through thin air.", yobjnam(obj, (char *) 0));
  101.          } else {
  102.              static const char *const d_action[6] = { "swinging", "digging",
  103.                                                       "chipping the statue",
  104.                                                       "hitting the boulder",
  105.                                                       "chopping at the door",
  106.                                                       "cutting the tree" };
  107.              did_dig_msg = FALSE;
  108.              context.digging.quiet = FALSE;
  109.              if (context.digging.pos.x != rx || context.digging.pos.y != ry
  110.                  || !on_level(&context.digging.level, &u.uz)
  111.                  || context.digging.down) {
  112.                  if (flags.autodig && dig_target == DIGTYP_ROCK
  113.                      && !context.digging.down && context.digging.pos.x == u.ux
  114.                      && context.digging.pos.y == u.uy
  115.                      && (moves <= context.digging.lastdigtime + 2
  116.                          && moves >= context.digging.lastdigtime)) {
  117.                      /* avoid messages if repeated autodigging */
  118.                      did_dig_msg = TRUE;
  119.                      context.digging.quiet = TRUE;
  120.                  }
  121.                  context.digging.down = context.digging.chew = FALSE;
  122.                  context.digging.warned = FALSE;
  123.                  context.digging.pos.x = rx;
  124.                  context.digging.pos.y = ry;
  125.                  assign_level(&context.digging.level, &u.uz);
  126.                  context.digging.effort = 0;
  127.                  if (!context.digging.quiet)
  128.                      You("start %s.", d_action[dig_target]);
  129.              } else {
  130.                  You("%s %s.", context.digging.chew ? "begin" : "continue",
  131.                      d_action[dig_target]);
  132.                  context.digging.chew = FALSE;
  133.              }
  134.              set_occupation(dig, verbing, 0);
  135.          }
  136.      } else if (Is_airlevel(&u.uz) || Is_waterlevel(&u.uz)) {
  137.          /* it must be air -- water checked above */
  138.          You("swing %s through thin air.", yobjnam(obj, (char *) 0));
  139.      } else if (!can_reach_floor(FALSE)) {
  140.          cant_reach_floor(u.ux, u.uy, FALSE, FALSE);
  141.      } else if (is_pool_or_lava(u.ux, u.uy)) {
  142.          /* Monsters which swim also happen not to be able to dig */
  143.          You("cannot stay under%s long enough.",
  144.              is_pool(u.ux, u.uy) ? "water" : " the lava");
  145.      } else if ((trap = t_at(u.ux, u.uy)) != 0
  146.                 && uteetering_at_seen_pit(trap)) {
  147.          dotrap(trap, FORCEBUNGLE);
  148.          /* might escape trap and still be teetering at brink */
  149.          if (!u.utrap)
  150.              cant_reach_floor(u.ux, u.uy, FALSE, TRUE);
  151.      } else if (!ispick
  152.                 /* can only dig down with an axe when doing so will
  153.                    trigger or disarm a trap here */
  154.                 && (!trap || (trap->ttyp != LANDMINE
  155.                               && trap->ttyp != BEAR_TRAP))) {
  156.          pline("%s merely scratches the %s.", Yobjnam2(obj, (char *) 0),
  157.                surface(u.ux, u.uy));
  158.          u_wipe_engr(3);
  159.      } else {
  160.          if (context.digging.pos.x != u.ux || context.digging.pos.y != u.uy
  161.              || !on_level(&context.digging.level, &u.uz)
  162.              || !context.digging.down) {
  163.              context.digging.chew = FALSE;
  164.              context.digging.down = TRUE;
  165.              context.digging.warned = FALSE;
  166.              context.digging.pos.x = u.ux;
  167.              context.digging.pos.y = u.uy;
  168.              assign_level(&context.digging.level, &u.uz);
  169.              context.digging.effort = 0;
  170.              You("start %s downward.", verbing);
  171.              if (*u.ushops)
  172.                  shopdig(0);
  173.          } else
  174.              You("continue %s downward.", verbing);
  175.          did_dig_msg = FALSE;
  176.          set_occupation(dig, verbing, 0);
  177.      }
  178.      return 1;
  179.  }
  180.  

watch_dig

  1.  /*
  2.   * Town Watchmen frown on damage to the town walls, trees or fountains.
  3.   * It's OK to dig holes in the ground, however.
  4.   * If mtmp is assumed to be a watchman, a watchman is found if mtmp == 0
  5.   * zap == TRUE if wand/spell of digging, FALSE otherwise (chewing)
  6.   */
  7.  void
  8.  watch_dig(mtmp, x, y, zap)
  9.  struct monst *mtmp;
  10.  xchar x, y;
  11.  boolean zap;
  12.  {
  13.      struct rm *lev = &levl[x][y];
  14.  
  15.      if (in_town(x, y)
  16.          && (closed_door(x, y) || lev->typ == SDOOR || IS_WALL(lev->typ)
  17.              || IS_FOUNTAIN(lev->typ) || IS_TREE(lev->typ))) {
  18.          if (!mtmp) {
  19.              for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
  20.                  if (DEADMONSTER(mtmp))
  21.                      continue;
  22.                  if (is_watch(mtmp->data) && mtmp->mcansee && m_canseeu(mtmp)
  23.                      && couldsee(mtmp->mx, mtmp->my) && mtmp->mpeaceful)
  24.                      break;
  25.              }
  26.          }
  27.  
  28.          if (mtmp) {
  29.              if (zap || context.digging.warned) {
  30.                  verbalize("Halt, vandal!  You're under arrest!");
  31.                  (void) angry_guards(!!Deaf);
  32.              } else {
  33.                  const char *str;
  34.  
  35.                  if (IS_DOOR(lev->typ))
  36.                      str = "door";
  37.                  else if (IS_TREE(lev->typ))
  38.                      str = "tree";
  39.                  else if (IS_ROCK(lev->typ))
  40.                      str = "wall";
  41.                  else
  42.                      str = "fountain";
  43.                  verbalize("Hey, stop damaging that %s!", str);
  44.                  context.digging.warned = TRUE;
  45.              }
  46.              if (is_digging())
  47.                  stop_occupation();
  48.          }
  49.      }
  50.  }
  51.  

mdig_tunnel

  1.  /* Return TRUE if monster died, FALSE otherwise.  Called from m_move(). */
  2.  boolean
  3.  mdig_tunnel(mtmp)
  4.  register struct monst *mtmp;
  5.  {
  6.      register struct rm *here;
  7.      int pile = rnd(12);
  8.  
  9.      here = &levl[mtmp->mx][mtmp->my];
  10.      if (here->typ == SDOOR)
  11.          cvt_sdoor_to_door(here); /* ->typ = DOOR */
  12.  
  13.      /* Eats away door if present & closed or locked */
  14.      if (closed_door(mtmp->mx, mtmp->my)) {
  15.          if (*in_rooms(mtmp->mx, mtmp->my, SHOPBASE))
  16.              add_damage(mtmp->mx, mtmp->my, 0L);
  17.          unblock_point(mtmp->mx, mtmp->my); /* vision */
  18.          if (here->doormask & D_TRAPPED) {
  19.              here->doormask = D_NODOOR;
  20.              if (mb_trapped(mtmp)) { /* mtmp is killed */
  21.                  newsym(mtmp->mx, mtmp->my);
  22.                  return TRUE;
  23.              }
  24.          } else {
  25.              if (!rn2(3) && flags.verbose) /* not too often.. */
  26.                  draft_message(TRUE); /* "You feel an unexpected draft." */
  27.              here->doormask = D_BROKEN;
  28.          }
  29.          newsym(mtmp->mx, mtmp->my);
  30.          return FALSE;
  31.      } else if (here->typ == SCORR) {
  32.          here->typ = CORR;
  33.          unblock_point(mtmp->mx, mtmp->my);
  34.          newsym(mtmp->mx, mtmp->my);
  35.          draft_message(FALSE); /* "You feel a draft." */
  36.          return FALSE;
  37.      } else if (!IS_ROCK(here->typ) && !IS_TREE(here->typ)) /* no dig */
  38.          return FALSE;
  39.  
  40.      /* Only rock, trees, and walls fall through to this point. */
  41.      if ((here->wall_info & W_NONDIGGABLE) != 0) {
  42.          impossible("mdig_tunnel:  %s at (%d,%d) is undiggable",
  43.                     (IS_WALL(here->typ) ? "wall"
  44.                      : IS_TREE(here->typ) ? "tree" : "stone"),
  45.                     (int) mtmp->mx, (int) mtmp->my);
  46.          return FALSE; /* still alive */
  47.      }
  48.  
  49.      if (IS_WALL(here->typ)) {
  50.          /* KMH -- Okay on arboreal levels (room walls are still stone) */
  51.          if (flags.verbose && !rn2(5))
  52.              You_hear("crashing rock.");
  53.          if (*in_rooms(mtmp->mx, mtmp->my, SHOPBASE))
  54.              add_damage(mtmp->mx, mtmp->my, 0L);
  55.          if (level.flags.is_maze_lev) {
  56.              here->typ = ROOM;
  57.          } else if (level.flags.is_cavernous_lev
  58.                     && !in_town(mtmp->mx, mtmp->my)) {
  59.              here->typ = CORR;
  60.          } else {
  61.              here->typ = DOOR;
  62.              here->doormask = D_NODOOR;
  63.          }
  64.      } else if (IS_TREE(here->typ)) {
  65.          here->typ = ROOM;
  66.          if (pile && pile < 5)
  67.              (void) rnd_treefruit_at(mtmp->mx, mtmp->my);
  68.      } else {
  69.          here->typ = CORR;
  70.          if (pile && pile < 5)
  71.              (void) mksobj_at((pile == 1) ? BOULDER : ROCK, mtmp->mx, mtmp->my,
  72.                               TRUE, FALSE);
  73.      }
  74.      newsym(mtmp->mx, mtmp->my);
  75.      if (!sobj_at(BOULDER, mtmp->mx, mtmp->my))
  76.          unblock_point(mtmp->mx, mtmp->my); /* vision */
  77.  
  78.      return FALSE;
  79.  }
  80.  

draft_message

  1.  #define STRIDENT 4 /* from pray.c */
  2.  
  3.  /* draft refers to air currents, but can be a pun on "draft" as conscription
  4.     for military service (probably not a good pun if it has to be explained) */
  5.  void
  6.  draft_message(unexpected)
  7.  boolean unexpected;
  8.  {
  9.      /*
  10.       * [Bug or TODO?  Have caller pass coordinates and use the travel
  11.       * mechanism to determine whether there is a path between
  12.       * destroyed door (or exposed secret corridor) and hero's location.
  13.       * When there is no such path, no draft should be felt.]
  14.       */
  15.  
  16.      if (unexpected) {
  17.          if (!Hallucination)
  18.              You_feel("an unexpected draft.");
  19.          else
  20.              /* U.S. classification system uses 1-A for eligible to serve
  21.                 and 4-F for ineligible due to physical or mental defect;
  22.                 some intermediate values exist but are rarely seen */
  23.              You_feel("like you are %s.",
  24.                       (ACURR(A_STR) < 6 || ACURR(A_DEX) < 6
  25.                        || ACURR(A_CON) < 6 || ACURR(A_CHA) < 6
  26.                        || ACURR(A_INT) < 6 || ACURR(A_WIS) < 6) ? "4-F"
  27.                                                                 : "1-A");
  28.      } else {
  29.          if (!Hallucination) {
  30.              You_feel("a draft.");
  31.          } else {
  32.              /* "marching" is deliberately ambiguous; it might mean drills
  33.                  after entering military service or mean engaging in protests */
  34.              static const char *draft_reaction[] = {
  35.                  "enlisting", "marching", "protesting", "fleeing",
  36.              };
  37.              int dridx;
  38.  
  39.              /* Lawful: 0..1, Neutral: 1..2, Chaotic: 2..3 */
  40.              dridx = rn1(2, 1 - sgn(u.ualign.type));
  41.              if (u.ualign.record < STRIDENT)
  42.                  /* L: +(0..2), N: +(-1..1), C: +(-2..0); all: 0..3 */
  43.                  dridx += rn1(3, sgn(u.ualign.type) - 1);
  44.              You_feel("like %s.", draft_reaction[dridx]);
  45.          }
  46.      }
  47.  }
  48.  

zap_dig

  1.  /* digging via wand zap or spell cast */
  2.  void
  3.  zap_dig()
  4.  {
  5.      struct rm *room;
  6.      struct monst *mtmp;
  7.      struct obj *otmp;
  8.      struct trap *trap_with_u = (struct trap *) 0;
  9.      int zx, zy, diridx = 8, digdepth, flow_x = -1, flow_y = -1;
  10.      boolean shopdoor, shopwall, maze_dig, pitdig = FALSE, pitflow = FALSE;
  11.  
  12.      /*
  13.       * Original effect (approximately):
  14.       * from CORR: dig until we pierce a wall
  15.       * from ROOM: pierce wall and dig until we reach
  16.       * an ACCESSIBLE place.
  17.       * Currently: dig for digdepth positions;
  18.       * also down on request of Lennart Augustsson.
  19.       * 3.6.0: from a PIT: dig one adjacent pit.
  20.       */
  21.  
  22.      if (u.uswallow) {
  23.          mtmp = u.ustuck;
  24.  
  25.          if (!is_whirly(mtmp->data)) {
  26.              if (is_animal(mtmp->data))
  27.                  You("pierce %s %s wall!", s_suffix(mon_nam(mtmp)),
  28.                      mbodypart(mtmp, STOMACH));
  29.              mtmp->mhp = 1; /* almost dead */
  30.              expels(mtmp, mtmp->data, !is_animal(mtmp->data));
  31.          }
  32.          return;
  33.      } /* swallowed */
  34.  
  35.      if (u.dz) {
  36.          if (!Is_airlevel(&u.uz) && !Is_waterlevel(&u.uz) && !Underwater) {
  37.              if (u.dz < 0 || On_stairs(u.ux, u.uy)) {
  38.                  int dmg;
  39.                  if (On_stairs(u.ux, u.uy))
  40.                      pline_The("beam bounces off the %s and hits the %s.",
  41.                                (u.ux == xdnladder || u.ux == xupladder)
  42.                                    ? "ladder"
  43.                                    : "stairs",
  44.                                ceiling(u.ux, u.uy));
  45.                  You("loosen a rock from the %s.", ceiling(u.ux, u.uy));
  46.                  pline("It falls on your %s!", body_part(HEAD));
  47.                  dmg = rnd((uarmh && is_metallic(uarmh)) ? 2 : 6);
  48.                  losehp(Maybe_Half_Phys(dmg), "falling rock", KILLED_BY_AN);
  49.                  otmp = mksobj_at(ROCK, u.ux, u.uy, FALSE, FALSE);
  50.                  if (otmp) {
  51.                      (void) xname(otmp); /* set dknown, maybe bknown */
  52.                      stackobj(otmp);
  53.                  }
  54.                  newsym(u.ux, u.uy);
  55.              } else {
  56.                  watch_dig((struct monst *) 0, u.ux, u.uy, TRUE);
  57.                  (void) dighole(FALSE, TRUE, (coord *) 0);
  58.              }
  59.          }
  60.          return;
  61.      } /* up or down */
  62.  
  63.      /* normal case: digging across the level */
  64.      shopdoor = shopwall = FALSE;
  65.      maze_dig = level.flags.is_maze_lev && !Is_earthlevel(&u.uz);
  66.      zx = u.ux + u.dx;
  67.      zy = u.uy + u.dy;
  68.      if (u.utrap && u.utraptype == TT_PIT
  69.          && (trap_with_u = t_at(u.ux, u.uy))) {
  70.          pitdig = TRUE;
  71.          for (diridx = 0; diridx < 8; diridx++) {
  72.              if (xdir[diridx] == u.dx && ydir[diridx] == u.dy)
  73.                  break;
  74.              /* diridx is valid if < 8 */
  75.          }
  76.      }
  77.      digdepth = rn1(18, 8);
  78.      tmp_at(DISP_BEAM, cmap_to_glyph(S_digbeam));
  79.      while (--digdepth >= 0) {
  80.          if (!isok(zx, zy))
  81.              break;
  82.          room = &levl[zx][zy];
  83.          tmp_at(zx, zy);
  84.          delay_output(); /* wait a little bit */
  85.  
  86.          if (pitdig) { /* we are already in a pit if this is true */
  87.              coord cc;
  88.              struct trap *adjpit = t_at(zx, zy);
  89.              if ((diridx < 8) && !conjoined_pits(adjpit, trap_with_u, FALSE)) {
  90.                  digdepth = 0; /* limited to the adjacent location only */
  91.                  if (!(adjpit && (adjpit->ttyp == PIT
  92.                                   || adjpit->ttyp == SPIKED_PIT))) {
  93.                      char buf[BUFSZ];
  94.                      cc.x = zx;
  95.                      cc.y = zy;
  96.                      if (!adj_pit_checks(&cc, buf)) {
  97.                          if (buf[0])
  98.                              pline1(buf);
  99.                      } else {
  100.                          /* this can also result in a pool at zx,zy */
  101.                          dighole(TRUE, TRUE, &cc);
  102.                          adjpit = t_at(zx, zy);
  103.                      }
  104.                  }
  105.                  if (adjpit
  106.                      && (adjpit->ttyp == PIT || adjpit->ttyp == SPIKED_PIT)) {
  107.                      int adjidx = (diridx + 4) % 8;
  108.                      trap_with_u->conjoined |= (1 << diridx);
  109.                      adjpit->conjoined |= (1 << adjidx);
  110.                      flow_x = zx;
  111.                      flow_y = zy;
  112.                      pitflow = TRUE;
  113.                  }
  114.                  if (is_pool(zx, zy) || is_lava(zx, zy)) {
  115.                      flow_x = zx - u.dx;
  116.                      flow_y = zy - u.dy;
  117.                      pitflow = TRUE;
  118.                  }
  119.                  break;
  120.              }
  121.          } else if (closed_door(zx, zy) || room->typ == SDOOR) {
  122.              if (*in_rooms(zx, zy, SHOPBASE)) {
  123.                  add_damage(zx, zy, 400L);
  124.                  shopdoor = TRUE;
  125.              }
  126.              if (room->typ == SDOOR)
  127.                  room->typ = DOOR;
  128.              else if (cansee(zx, zy))
  129.                  pline_The("door is razed!");
  130.              watch_dig((struct monst *) 0, zx, zy, TRUE);
  131.              room->doormask = D_NODOOR;
  132.              unblock_point(zx, zy); /* vision */
  133.              digdepth -= 2;
  134.              if (maze_dig)
  135.                  break;
  136.          } else if (maze_dig) {
  137.              if (IS_WALL(room->typ)) {
  138.                  if (!(room->wall_info & W_NONDIGGABLE)) {
  139.                      if (*in_rooms(zx, zy, SHOPBASE)) {
  140.                          add_damage(zx, zy, 200L);
  141.                          shopwall = TRUE;
  142.                      }
  143.                      room->typ = ROOM;
  144.                      unblock_point(zx, zy); /* vision */
  145.                  } else if (!Blind)
  146.                      pline_The("wall glows then fades.");
  147.                  break;
  148.              } else if (IS_TREE(room->typ)) { /* check trees before stone */
  149.                  if (!(room->wall_info & W_NONDIGGABLE)) {
  150.                      room->typ = ROOM;
  151.                      unblock_point(zx, zy); /* vision */
  152.                  } else if (!Blind)
  153.                      pline_The("tree shudders but is unharmed.");
  154.                  break;
  155.              } else if (room->typ == STONE || room->typ == SCORR) {
  156.                  if (!(room->wall_info & W_NONDIGGABLE)) {
  157.                      room->typ = CORR;
  158.                      unblock_point(zx, zy); /* vision */
  159.                  } else if (!Blind)
  160.                      pline_The("rock glows then fades.");
  161.                  break;
  162.              }
  163.          } else if (IS_ROCK(room->typ)) {
  164.              if (!may_dig(zx, zy))
  165.                  break;
  166.              if (IS_WALL(room->typ) || room->typ == SDOOR) {
  167.                  if (*in_rooms(zx, zy, SHOPBASE)) {
  168.                      add_damage(zx, zy, 200L);
  169.                      shopwall = TRUE;
  170.                  }
  171.                  watch_dig((struct monst *) 0, zx, zy, TRUE);
  172.                  if (level.flags.is_cavernous_lev && !in_town(zx, zy)) {
  173.                      room->typ = CORR;
  174.                  } else {
  175.                      room->typ = DOOR;
  176.                      room->doormask = D_NODOOR;
  177.                  }
  178.                  digdepth -= 2;
  179.              } else if (IS_TREE(room->typ)) {
  180.                  room->typ = ROOM;
  181.                  digdepth -= 2;
  182.              } else { /* IS_ROCK but not IS_WALL or SDOOR */
  183.                  room->typ = CORR;
  184.                  digdepth--;
  185.              }
  186.              unblock_point(zx, zy); /* vision */
  187.          }
  188.          zx += u.dx;
  189.          zy += u.dy;
  190.      }                    /* while */
  191.      tmp_at(DISP_END, 0); /* closing call */
  192.  
  193.      if (pitflow && isok(flow_x, flow_y)) {
  194.          struct trap *ttmp = t_at(flow_x, flow_y);
  195.          if (ttmp && (ttmp->ttyp == PIT || ttmp->ttyp == SPIKED_PIT)) {
  196.              schar filltyp = fillholetyp(ttmp->tx, ttmp->ty, TRUE);
  197.              if (filltyp != ROOM)
  198.                  pit_flow(ttmp, filltyp);
  199.          }
  200.      }
  201.  
  202.      if (shopdoor || shopwall)
  203.          pay_for_damage(shopdoor ? "destroy" : "dig into", FALSE);
  204.      return;
  205.  }
  206.  

adj_pit_checks

  1.  /*
  2.   * This checks what is on the surface above the
  3.   * location where an adjacent pit might be created if
  4.   * you're zapping a wand of digging laterally while
  5.   * down in the pit.
  6.   */
  7.  STATIC_OVL int
  8.  adj_pit_checks(cc, msg)
  9.  coord *cc;
  10.  char *msg;
  11.  {
  12.      int ltyp;
  13.      struct rm *room;
  14.      const char *foundation_msg =
  15.          "The foundation is too hard to dig through from this angle.";
  16.  
  17.      if (!cc)
  18.          return FALSE;
  19.      if (!isok(cc->x, cc->y))
  20.          return FALSE;
  21.      *msg = '\0';
  22.      room = &levl[cc->x][cc->y];
  23.      ltyp = room->typ;
  24.  
  25.      if (is_pool(cc->x, cc->y) || is_lava(cc->x, cc->y)) {
  26.          /* this is handled by the caller after we return FALSE */
  27.          return FALSE;
  28.      } else if (closed_door(cc->x, cc->y) || room->typ == SDOOR) {
  29.          /* We reject this here because dighole() isn't
  30.             prepared to deal with this case */
  31.          Strcpy(msg, foundation_msg);
  32.          return FALSE;
  33.      } else if (IS_WALL(ltyp)) {
  34.          /* if (room->wall_info & W_NONDIGGABLE) */
  35.          Strcpy(msg, foundation_msg);
  36.          return FALSE;
  37.      } else if (IS_TREE(ltyp)) { /* check trees before stone */
  38.          /* if (room->wall_info & W_NONDIGGABLE) */
  39.          Strcpy(msg, "The tree's roots glow then fade.");
  40.          return FALSE;
  41.      } else if (ltyp == STONE || ltyp == SCORR) {
  42.          if (room->wall_info & W_NONDIGGABLE) {
  43.              Strcpy(msg, "The rock glows then fades.");
  44.              return FALSE;
  45.          }
  46.      } else if (ltyp == IRONBARS) {
  47.          /* "set of iron bars" */
  48.          Strcpy(msg, "The bars go much deeper than your pit.");
  49.  #if 0
  50.      } else if (is_lava(cc->x, cc->y)) {
  51.      } else if (is_ice(cc->x, cc->y)) {
  52.      } else if (is_pool(cc->x, cc->y)) {
  53.      } else if (IS_GRAVE(ltyp)) {
  54.  #endif
  55.      } else if (IS_SINK(ltyp)) {
  56.          Strcpy(msg, "A tangled mass of plumbing remains below the sink.");
  57.          return FALSE;
  58.      } else if ((cc->x == xupladder && cc->y == yupladder) /* ladder up */
  59.                 || (cc->x == xdnladder && cc->y == ydnladder)) { /* " down */
  60.          Strcpy(msg, "The ladder is unaffected.");
  61.          return FALSE;
  62.      } else {
  63.          const char *supporting = (const char *) 0;
  64.  
  65.          if (IS_FOUNTAIN(ltyp))
  66.              supporting = "fountain";
  67.          else if (IS_THRONE(ltyp))
  68.              supporting = "throne";
  69.          else if (IS_ALTAR(ltyp))
  70.              supporting = "altar";
  71.          else if ((cc->x == xupstair && cc->y == yupstair)
  72.                   || (cc->x == sstairs.sx && cc->y == sstairs.sy
  73.                       && sstairs.up))
  74.              /* "staircase up" */
  75.              supporting = "stairs";
  76.          else if ((cc->x == xdnstair && cc->y == ydnstair)
  77.                   || (cc->x == sstairs.sx && cc->y == sstairs.sy
  78.                       && !sstairs.up))
  79.              /* "staircase down" */
  80.              supporting = "stairs";
  81.          else if (ltyp == DRAWBRIDGE_DOWN   /* "lowered drawbridge" */
  82.                   || ltyp == DBWALL)        /* "raised drawbridge" */
  83.              supporting = "drawbridge";
  84.  
  85.          if (supporting) {
  86.              Sprintf(msg, "The %s%ssupporting structures remain intact.",
  87.                      supporting ? s_suffix(supporting) : "",
  88.                      supporting ? " " : "");
  89.              return FALSE;
  90.          }
  91.      }
  92.      return TRUE;
  93.  }
  94.  

pit_flow

  1.  /*
  2.   * Ensure that all conjoined pits fill up.
  3.   */
  4.  STATIC_OVL void
  5.  pit_flow(trap, filltyp)
  6.  struct trap *trap;
  7.  schar filltyp;
  8.  {
  9.      if (trap && (filltyp != ROOM)
  10.          && (trap->ttyp == PIT || trap->ttyp == SPIKED_PIT)) {
  11.          struct trap t;
  12.          int idx;
  13.  
  14.          t = *trap;
  15.          levl[trap->tx][trap->ty].typ = filltyp;
  16.          liquid_flow(trap->tx, trap->ty, filltyp, trap,
  17.                      (trap->tx == u.ux && trap->ty == u.uy)
  18.                          ? "Suddenly %s flows in from the adjacent pit!"
  19.                          : (char *) 0);
  20.          for (idx = 0; idx < 8; ++idx) {
  21.              if (t.conjoined & (1 << idx)) {
  22.                  int x, y;
  23.                  struct trap *t2;
  24.  
  25.                  x = t.tx + xdir[idx];
  26.                  y = t.ty + ydir[idx];
  27.                  t2 = t_at(x, y);
  28.  #if 0
  29.                  /* cannot do this back-check; liquid_flow()
  30.                   * called deltrap() which cleaned up the
  31.                   * conjoined fields on both pits.
  32.                   */
  33.                  if (t2 && (t2->conjoined & (1 << ((idx + 4) % 8))))
  34.  #endif
  35.                  /* recursion */
  36.                  pit_flow(t2, filltyp);
  37.              }
  38.          }
  39.      }
  40.  }
  41.  

buried_ball

  1.  struct obj *
  2.  buried_ball(cc)
  3.  coord *cc;
  4.  {
  5.      xchar check_x, check_y;
  6.      struct obj *otmp, *otmp2;
  7.  
  8.      if (u.utraptype == TT_BURIEDBALL)
  9.          for (otmp = level.buriedobjlist; otmp; otmp = otmp2) {
  10.              otmp2 = otmp->nobj;
  11.              if (otmp->otyp != HEAVY_IRON_BALL)
  12.                  continue;
  13.              /* try the exact location first */
  14.              if (otmp->ox == cc->x && otmp->oy == cc->y)
  15.                  return otmp;
  16.              /* Now try the vicinity */
  17.              /*
  18.               * (x-2,y-2)       (x+2,y-2)
  19.               *           (x,y)
  20.               * (x-2,y+2)       (x+2,y+2)
  21.               */
  22.              for (check_x = cc->x - 2; check_x <= cc->x + 2; ++check_x)
  23.                  for (check_y = cc->y - 2; check_y <= cc->y + 2; ++check_y) {
  24.                      if (check_x == cc->x && check_y == cc->y)
  25.                          continue;
  26.                      if (isok(check_x, check_y)
  27.                          && (otmp->ox == check_x && otmp->oy == check_y)) {
  28.                          cc->x = check_x;
  29.                          cc->y = check_y;
  30.                          return otmp;
  31.                      }
  32.                  }
  33.          }
  34.      return (struct obj *) 0;
  35.  }
  36.  

buried_ball_to_punishment

  1.  void
  2.  buried_ball_to_punishment()
  3.  {
  4.      coord cc;
  5.      struct obj *ball;
  6.      cc.x = u.ux;
  7.      cc.y = u.uy;
  8.      ball = buried_ball(&cc);
  9.      if (ball) {
  10.          obj_extract_self(ball);
  11.  #if 0
  12.          /* rusting buried metallic objects is not implemented yet */
  13.          if (ball->timed)
  14.              (void) stop_timer(RUST_METAL, obj_to_any(ball));
  15.  #endif
  16.          punish(ball); /* use ball as flag for unearthed buried ball */
  17.          u.utrap = 0;
  18.          u.utraptype = 0;
  19.          del_engr_at(cc.x, cc.y);
  20.          newsym(cc.x, cc.y);
  21.      }
  22.  }
  23.  

buried_ball_to_freedom

  1.  void
  2.  buried_ball_to_freedom()
  3.  {
  4.      coord cc;
  5.      struct obj *ball;
  6.      cc.x = u.ux;
  7.      cc.y = u.uy;
  8.      ball = buried_ball(&cc);
  9.      if (ball) {
  10.          obj_extract_self(ball);
  11.  #if 0
  12.          /* rusting buried metallic objects is not implemented yet */
  13.          if (ball->timed)
  14.              (void) stop_timer(RUST_METAL, obj_to_any(ball));
  15.  #endif
  16.          place_object(ball, cc.x, cc.y);
  17.          stackobj(ball);
  18.          u.utrap = 0;
  19.          u.utraptype = 0;
  20.          del_engr_at(cc.x, cc.y);
  21.          newsym(cc.x, cc.y);
  22.      }
  23.  }
  24.  

bury_an_obj

  1.  /* move objects from fobj/nexthere lists to buriedobjlist, keeping position
  2.     information */
  3.  struct obj *
  4.  bury_an_obj(otmp, dealloced)
  5.  struct obj *otmp;
  6.  boolean *dealloced;
  7.  {
  8.      struct obj *otmp2;
  9.      boolean under_ice;
  10.  
  11.      debugpline1("bury_an_obj: %s", xname(otmp));
  12.      if (dealloced)
  13.          *dealloced = FALSE;
  14.      if (otmp == uball) {
  15.          unpunish();
  16.          u.utrap = rn1(50, 20);
  17.          u.utraptype = TT_BURIEDBALL;
  18.          pline_The("iron ball gets buried!");
  19.      }
  20.      /* after unpunish(), or might get deallocated chain */
  21.      otmp2 = otmp->nexthere;
  22.      /*
  23.       * obj_resists(,0,0) prevents Rider corpses from being buried.
  24.       * It also prevents The Amulet and invocation tools from being
  25.       * buried.  Since they can't be confined to bags and statues,
  26.       * it makes sense that they can't be buried either, even though
  27.       * the real reason there (direct accessibility when carried) is
  28.       * completely different.
  29.       */
  30.      if (otmp == uchain || obj_resists(otmp, 0, 0))
  31.          return otmp2;
  32.  
  33.      if (otmp->otyp == LEASH && otmp->leashmon != 0)
  34.          o_unleash(otmp);
  35.  
  36.      if (otmp->lamplit && otmp->otyp != POT_OIL)
  37.          end_burn(otmp, TRUE);
  38.  
  39.      obj_extract_self(otmp);
  40.  
  41.      under_ice = is_ice(otmp->ox, otmp->oy);
  42.      if (otmp->otyp == ROCK && !under_ice) {
  43.          /* merges into burying material */
  44.          if (dealloced)
  45.              *dealloced = TRUE;
  46.          obfree(otmp, (struct obj *) 0);
  47.          return otmp2;
  48.      }
  49.      /*
  50.       * Start a rot on organic material.  Not corpses -- they
  51.       * are already handled.
  52.       */
  53.      if (otmp->otyp == CORPSE) {
  54.          ; /* should cancel timer if under_ice */
  55.      } else if ((under_ice ? otmp->oclass == POTION_CLASS : is_organic(otmp))
  56.                 && !obj_resists(otmp, 5, 95)) {
  57.          (void) start_timer((under_ice ? 0L : 250L) + (long) rnd(250),
  58.                             TIMER_OBJECT, ROT_ORGANIC, obj_to_any(otmp));
  59.  #if 0
  60.      /* rusting of buried metal not yet implemented */
  61.      } else if (is_rustprone(otmp)) {
  62.          (void) start_timer((long) rnd((otmp->otyp == HEAVY_IRON_BALL)
  63.                                           ? 1500
  64.                                           : 250),
  65.                             TIMER_OBJECT, RUST_METAL, obj_to_any(otmp));
  66.  #endif
  67.      }
  68.      add_to_buried(otmp);
  69.      return  otmp2;
  70.  }
  71.  

bury_objs

  1.  void
  2.  bury_objs(x, y)
  3.  int x, y;
  4.  {
  5.      struct obj *otmp, *otmp2;
  6.  
  7.      if (level.objects[x][y] != (struct obj *) 0) {
  8.          debugpline2("bury_objs: at <%d,%d>", x, y);
  9.      }
  10.      for (otmp = level.objects[x][y]; otmp; otmp = otmp2)
  11.          otmp2 = bury_an_obj(otmp, (boolean *) 0);
  12.  
  13.      /* don't expect any engravings here, but just in case */
  14.      del_engr_at(x, y);
  15.      newsym(x, y);
  16.  }
  17.  

unearth_objs

  1.  /* move objects from buriedobjlist to fobj/nexthere lists */
  2.  void
  3.  unearth_objs(x, y)
  4.  int x, y;
  5.  {
  6.      struct obj *otmp, *otmp2, *bball;
  7.      coord cc;
  8.  
  9.      debugpline2("unearth_objs: at <%d,%d>", x, y);
  10.      cc.x = x;
  11.      cc.y = y;
  12.      bball = buried_ball(&cc);
  13.      for (otmp = level.buriedobjlist; otmp; otmp = otmp2) {
  14.          otmp2 = otmp->nobj;
  15.          if (otmp->ox == x && otmp->oy == y) {
  16.              if (bball && otmp == bball && u.utraptype == TT_BURIEDBALL) {
  17.                  buried_ball_to_punishment();
  18.              } else {
  19.                  obj_extract_self(otmp);
  20.                  if (otmp->timed)
  21.                      (void) stop_timer(ROT_ORGANIC, obj_to_any(otmp));
  22.                  place_object(otmp, x, y);
  23.                  stackobj(otmp);
  24.              }
  25.          }
  26.      }
  27.      del_engr_at(x, y);
  28.      newsym(x, y);
  29.  }
  30.  

rot_organic

  1.  /*
  2.   * The organic material has rotted away while buried.  As an expansion,
  3.   * we could add add partial damage.  A damage count is kept in the object
  4.   * and every time we are called we increment the count and reschedule another
  5.   * timeout.  Eventually the object rots away.
  6.   *
  7.   * This is used by buried objects other than corpses.  When a container rots
  8.   * away, any contents become newly buried objects.
  9.   */
  10.  /* ARGSUSED */
  11.  void
  12.  rot_organic(arg, timeout)
  13.  anything *arg;
  14.  long timeout UNUSED;
  15.  {
  16.      struct obj *obj = arg->a_obj;
  17.  
  18.      while (Has_contents(obj)) {
  19.          /* We don't need to place contained object on the floor
  20.             first, but we do need to update its map coordinates. */
  21.          obj->cobj->ox = obj->ox, obj->cobj->oy = obj->oy;
  22.          /* Everything which can be held in a container can also be
  23.             buried, so bury_an_obj's use of obj_extract_self insures
  24.             that Has_contents(obj) will eventually become false. */
  25.          (void) bury_an_obj(obj->cobj, (boolean *) 0);
  26.      }
  27.      obj_extract_self(obj);
  28.      obfree(obj, (struct obj *) 0);
  29.  }
  30.  

rot_corpse

  1.  /*
  2.   * Called when a corpse has rotted completely away.
  3.   */
  4.  void
  5.  rot_corpse(arg, timeout)
  6.  anything *arg;
  7.  long timeout;
  8.  {
  9.      xchar x = 0, y = 0;
  10.      struct obj *obj = arg->a_obj;
  11.      boolean on_floor = obj->where == OBJ_FLOOR,
  12.              in_invent = obj->where == OBJ_INVENT;
  13.  
  14.      if (on_floor) {
  15.          x = obj->ox;
  16.          y = obj->oy;
  17.      } else if (in_invent) {
  18.          if (flags.verbose) {
  19.              char *cname = corpse_xname(obj, (const char *) 0, CXN_NO_PFX);
  20.  
  21.              Your("%s%s %s away%c", obj == uwep ? "wielded " : "", cname,
  22.                   otense(obj, "rot"), obj == uwep ? '!' : '.');
  23.          }
  24.          if (obj == uwep) {
  25.              uwepgone(); /* now bare handed */
  26.              stop_occupation();
  27.          } else if (obj == uswapwep) {
  28.              uswapwepgone();
  29.              stop_occupation();
  30.          } else if (obj == uquiver) {
  31.              uqwepgone();
  32.              stop_occupation();
  33.          }
  34.      } else if (obj->where == OBJ_MINVENT && obj->owornmask) {
  35.          if (obj == MON_WEP(obj->ocarry))
  36.              setmnotwielded(obj->ocarry, obj);
  37.      } else if (obj->where == OBJ_MIGRATING) {
  38.          /* clear destination flag so that obfree()'s check for
  39.             freeing a worn object doesn't get a false hit */
  40.          obj->owornmask = 0L;
  41.      }
  42.      rot_organic(arg, timeout);
  43.      if (on_floor) {
  44.          struct monst *mtmp = m_at(x, y);
  45.  
  46.          /* a hiding monster may be exposed */
  47.          if (mtmp && !OBJ_AT(x, y) && mtmp->mundetected
  48.              && hides_under(mtmp->data)) {
  49.              mtmp->mundetected = 0;
  50.          } else if (x == u.ux && y == u.uy && u.uundetected && hides_under(youmonst.data))
  51.              (void) hideunder(&youmonst);
  52.          newsym(x, y);
  53.      } else if (in_invent)
  54.          update_inventory();
  55.  }
  56.  

bury_monst

None of the following five functions are compiled.

  1.  #if 0
  2.  void
  3.  bury_monst(mtmp)
  4.  struct monst *mtmp;
  5.  {
  6.      debugpline1("bury_monst: %s", mon_nam(mtmp));
  7.      if (canseemon(mtmp)) {
  8.          if (is_flyer(mtmp->data) || is_floater(mtmp->data)) {
  9.              pline_The("%s opens up, but %s is not swallowed!",
  10.                        surface(mtmp->mx, mtmp->my), mon_nam(mtmp));
  11.              return;
  12.          } else
  13.              pline_The("%s opens up and swallows %s!",
  14.                        surface(mtmp->mx, mtmp->my), mon_nam(mtmp));
  15.      }
  16.  
  17.      mtmp->mburied = TRUE;
  18.      wakeup(mtmp);       /* at least give it a chance :-) */
  19.      newsym(mtmp->mx, mtmp->my);
  20.  }
  21.  

bury_you

  1.  void
  2.  bury_you()
  3.  {
  4.      debugpline0("bury_you");
  5.      if (!Levitation && !Flying) {
  6.          if (u.uswallow)
  7.              You_feel("a sensation like falling into a trap!");
  8.          else
  9.              pline_The("%s opens beneath you and you fall in!",
  10.                        surface(u.ux, u.uy));
  11.  
  12.          u.uburied = TRUE;
  13.          if (!Strangled && !Breathless)
  14.              Strangled = 6;
  15.          under_ground(1);
  16.      }
  17.  }
  18.  

unearth_you

  1.  void
  2.  unearth_you()
  3.  {
  4.      debugpline0("unearth_you");
  5.      u.uburied = FALSE;
  6.      under_ground(0);
  7.      if (!uamul || uamul->otyp != AMULET_OF_STRANGULATION)
  8.          Strangled = 0;
  9.      vision_recalc(0);
  10.  }
  11.  

escape_tomb

  1.  void
  2.  escape_tomb()
  3.  {
  4.      debugpline0("escape_tomb");
  5.      if ((Teleportation || can_teleport(youmonst.data))
  6.          && (Teleport_control || rn2(3) < Luck+2)) {
  7.          You("attempt a teleport spell.");
  8.          (void) dotele();        /* calls unearth_you() */
  9.      } else if (u.uburied) { /* still buried after 'port attempt */
  10.          boolean good;
  11.  
  12.          if (amorphous(youmonst.data) || Passes_walls
  13.              || noncorporeal(youmonst.data)
  14.              || (unsolid(youmonst.data)
  15.                  && youmonst.data != &mons[PM_WATER_ELEMENTAL])
  16.              || (tunnels(youmonst.data) && !needspick(youmonst.data))) {
  17.              You("%s up through the %s.",
  18.                  (tunnels(youmonst.data) && !needspick(youmonst.data))
  19.                     ? "try to tunnel"
  20.                     : (amorphous(youmonst.data))
  21.                        ? "ooze"
  22.                        : "phase",
  23.                  surface(u.ux, u.uy));
  24.  
  25.              good = (tunnels(youmonst.data) && !needspick(youmonst.data))
  26.                        ? dighole(TRUE, FALSE, (coord *)0) : TRUE;
  27.              if (good)
  28.                  unearth_you();
  29.          }
  30.      }
  31.  }
  32.  

bury_obj

  1.  void
  2.  bury_obj(otmp)
  3.  struct obj *otmp;
  4.  {
  5.      debugpline0("bury_obj");
  6.      if (cansee(otmp->ox, otmp->oy))
  7.          pline_The("objects on the %s tumble into a hole!",
  8.                    surface(otmp->ox, otmp->oy));
  9.  
  10.      bury_objs(otmp->ox, otmp->oy);
  11.  }
  12.  #endif /*0*/

wiz_debug_cmd_bury

  1.  
  2.  #ifdef DEBUG
  3.  /* bury everything at your loc and around */
  4.  int
  5.  wiz_debug_cmd_bury()
  6.  {
  7.      int x, y;
  8.  
  9.      for (x = u.ux - 1; x <= u.ux + 1; x++)
  10.          for (y = u.uy - 1; y <= u.uy + 1; y++)
  11.              if (isok(x, y))
  12.                  bury_objs(x, y);
  13.      return 0;
  14.  }
  15.  #endif /* DEBUG */
  16.  
  17.  /*dig.c*/