Source:NetHack 3.6.1/src/mklev.c

From NetHackWiki
(Redirected from Source:Ref/join)
Jump to: navigation, search

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

Top of file

  1.  /* NetHack 3.6	mklev.c	$NHDT-Date: 1511681724 2017/11/26 07:35:24 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.47 $ */
  2.  /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3.  /*-Copyright (c) Alex Smith, 2017. */
  4.  /* NetHack may be freely redistributed.  See license for details. */

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.

  1.  
  2.  #include "hack.h"
  3.  
  4.  /* for UNIX, Rand #def'd to (long)lrand48() or (long)random() */
  5.  /* croom->lx etc are schar (width <= int), so % arith ensures that */
  6.  /* conversion of result to int is reasonable */
  7.  
  8.  STATIC_DCL void FDECL(mkfount, (int, struct mkroom *));
  9.  STATIC_DCL void FDECL(mksink, (struct mkroom *));
  10.  STATIC_DCL void FDECL(mkaltar, (struct mkroom *));
  11.  STATIC_DCL void FDECL(mkgrave, (struct mkroom *));
  12.  STATIC_DCL void NDECL(makevtele);
  13.  STATIC_DCL void NDECL(clear_level_structures);
  14.  STATIC_DCL void NDECL(makelevel);
  15.  STATIC_DCL boolean FDECL(bydoor, (XCHAR_P, XCHAR_P));
  16.  STATIC_DCL struct mkroom *FDECL(find_branch_room, (coord *));
  17.  STATIC_DCL struct mkroom *FDECL(pos_to_room, (XCHAR_P, XCHAR_P));
  18.  STATIC_DCL boolean FDECL(place_niche, (struct mkroom *, int *, int *, int *));
  19.  STATIC_DCL void FDECL(makeniche, (int));
  20.  STATIC_DCL void NDECL(make_niches);
  21.  STATIC_PTR int FDECL(CFDECLSPEC do_comp, (const genericptr,
  22.                                            const genericptr));
  23.  STATIC_DCL void FDECL(dosdoor, (XCHAR_P, XCHAR_P, struct mkroom *, int));
  24.  STATIC_DCL void FDECL(join, (int, int, BOOLEAN_P));
  25.  STATIC_DCL void FDECL(do_room_or_subroom, (struct mkroom *, int, int,
  26.                                             int, int, BOOLEAN_P,
  27.                                             SCHAR_P, BOOLEAN_P, BOOLEAN_P));
  28.  STATIC_DCL void NDECL(makerooms);
  29.  STATIC_DCL void FDECL(finddpos, (coord *, XCHAR_P, XCHAR_P,
  30.                                   XCHAR_P, XCHAR_P));
  31.  STATIC_DCL void FDECL(mkinvpos, (XCHAR_P, XCHAR_P, int));
  32.  STATIC_DCL void FDECL(mk_knox_portal, (XCHAR_P, XCHAR_P));
  33.  
  34.  #define create_vault() create_room(-1, -1, 2, 2, -1, -1, VAULT, TRUE)
  35.  #define init_vault() vault_x = -1
  36.  #define do_vault() (vault_x != -1)
  37.  static xchar vault_x, vault_y;
  38.  static boolean made_branch; /* used only during level creation */
  39.  
  40.  /* Args must be (const genericptr) so that qsort will always be happy. */
  41.  

do_comp

  1.  STATIC_PTR int CFDECLSPEC
  2.  do_comp(vx, vy)
  3.  const genericptr vx;
  4.  const genericptr vy;
  5.  {
  6.  #ifdef LINT
  7.      /* lint complains about possible pointer alignment problems, but we know
  8.         that vx and vy are always properly aligned. Hence, the following
  9.         bogus definition:
  10.      */
  11.      return (vx == vy) ? 0 : -1;
  12.  #else
  13.      register const struct mkroom *x, *y;
  14.  
  15.      x = (const struct mkroom *) vx;
  16.      y = (const struct mkroom *) vy;
  17.      if (x->lx < y->lx)
  18.          return -1;
  19.      return (x->lx > y->lx);
  20.  #endif /* LINT */
  21.  }
  22.  

finddpos

  1.  STATIC_OVL void
  2.  finddpos(cc, xl, yl, xh, yh)
  3.  coord *cc;
  4.  xchar xl, yl, xh, yh;
  5.  {
  6.      register xchar x, y;
  7.  
  8.      x = rn1(xh - xl + 1, xl);
  9.      y = rn1(yh - yl + 1, yl);
  10.      if (okdoor(x, y))
  11.          goto gotit;
  12.  
  13.      for (x = xl; x <= xh; x++)
  14.          for (y = yl; y <= yh; y++)
  15.              if (okdoor(x, y))
  16.                  goto gotit;
  17.  
  18.      for (x = xl; x <= xh; x++)
  19.          for (y = yl; y <= yh; y++)
  20.              if (IS_DOOR(levl[x][y].typ) || levl[x][y].typ == SDOOR)
  21.                  goto gotit;
  22.      /* cannot find something reasonable -- strange */
  23.      x = xl;
  24.      y = yh;
  25.  gotit:
  26.      cc->x = x;
  27.      cc->y = y;
  28.      return;
  29.  }
  30.  

sort_rooms

  1.  void
  2.  sort_rooms()
  3.  {
  4.  #if defined(SYSV) || defined(DGUX)
  5.      qsort((genericptr_t) rooms, (unsigned) nroom, sizeof(struct mkroom),
  6.            do_comp);
  7.  #else
  8.      qsort((genericptr_t) rooms, nroom, sizeof(struct mkroom), do_comp);
  9.  #endif
  10.  }
  11.  

do_room_or_subroom

  1.  STATIC_OVL void
  2.  do_room_or_subroom(croom, lowx, lowy, hix, hiy, lit, rtype, special, is_room)
  3.  register struct mkroom *croom;
  4.  int lowx, lowy;
  5.  register int hix, hiy;
  6.  boolean lit;
  7.  schar rtype;
  8.  boolean special;
  9.  boolean is_room;
  10.  {
  11.      register int x, y;
  12.      struct rm *lev;
  13.  
  14.      /* locations might bump level edges in wall-less rooms */
  15.      /* add/subtract 1 to allow for edge locations */
  16.      if (!lowx)
  17.          lowx++;
  18.      if (!lowy)
  19.          lowy++;
  20.      if (hix >= COLNO - 1)
  21.          hix = COLNO - 2;
  22.      if (hiy >= ROWNO - 1)
  23.          hiy = ROWNO - 2;
  24.  
  25.      if (lit) {
  26.          for (x = lowx - 1; x <= hix + 1; x++) {
  27.              lev = &levl[x][max(lowy - 1, 0)];
  28.              for (y = lowy - 1; y <= hiy + 1; y++)
  29.                  lev++->lit = 1;
  30.          }
  31.          croom->rlit = 1;
  32.      } else
  33.          croom->rlit = 0;
  34.  
  35.      croom->lx = lowx;
  36.      croom->hx = hix;
  37.      croom->ly = lowy;
  38.      croom->hy = hiy;
  39.      croom->rtype = rtype;
  40.      croom->doorct = 0;
  41.      /* if we're not making a vault, doorindex will still be 0
  42.       * if we are, we'll have problems adding niches to the previous room
  43.       * unless fdoor is at least doorindex
  44.       */
  45.      croom->fdoor = doorindex;
  46.      croom->irregular = FALSE;
  47.  
  48.      croom->nsubrooms = 0;
  49.      croom->sbrooms[0] = (struct mkroom *) 0;
  50.      if (!special) {
  51.          for (x = lowx - 1; x <= hix + 1; x++)
  52.              for (y = lowy - 1; y <= hiy + 1; y += (hiy - lowy + 2)) {
  53.                  levl[x][y].typ = HWALL;
  54.                  levl[x][y].horizontal = 1; /* For open/secret doors. */
  55.              }
  56.          for (x = lowx - 1; x <= hix + 1; x += (hix - lowx + 2))
  57.              for (y = lowy; y <= hiy; y++) {
  58.                  levl[x][y].typ = VWALL;
  59.                  levl[x][y].horizontal = 0; /* For open/secret doors. */
  60.              }
  61.          for (x = lowx; x <= hix; x++) {
  62.              lev = &levl[x][lowy];
  63.              for (y = lowy; y <= hiy; y++)
  64.                  lev++->typ = ROOM;
  65.          }
  66.          if (is_room) {
  67.              levl[lowx - 1][lowy - 1].typ = TLCORNER;
  68.              levl[hix + 1][lowy - 1].typ = TRCORNER;
  69.              levl[lowx - 1][hiy + 1].typ = BLCORNER;
  70.              levl[hix + 1][hiy + 1].typ = BRCORNER;
  71.          } else { /* a subroom */
  72.              wallification(lowx - 1, lowy - 1, hix + 1, hiy + 1);
  73.          }
  74.      }
  75.  }
  76.  

add_room

  1.  void
  2.  add_room(lowx, lowy, hix, hiy, lit, rtype, special)
  3.  int lowx, lowy, hix, hiy;
  4.  boolean lit;
  5.  schar rtype;
  6.  boolean special;
  7.  {
  8.      register struct mkroom *croom;
  9.  
  10.      croom = &rooms[nroom];
  11.      do_room_or_subroom(croom, lowx, lowy, hix, hiy, lit, rtype, special,
  12.                         (boolean) TRUE);
  13.      croom++;
  14.      croom->hx = -1;
  15.      nroom++;
  16.  }
  17.  

add_subroom

  1.  void
  2.  add_subroom(proom, lowx, lowy, hix, hiy, lit, rtype, special)
  3.  struct mkroom *proom;
  4.  int lowx, lowy, hix, hiy;
  5.  boolean lit;
  6.  schar rtype;
  7.  boolean special;
  8.  {
  9.      register struct mkroom *croom;
  10.  
  11.      croom = &subrooms[nsubroom];
  12.      do_room_or_subroom(croom, lowx, lowy, hix, hiy, lit, rtype, special,
  13.                         (boolean) FALSE);
  14.      proom->sbrooms[proom->nsubrooms++] = croom;
  15.      croom++;
  16.      croom->hx = -1;
  17.      nsubroom++;
  18.  }
  19.  

makerooms

  1.  STATIC_OVL void
  2.  makerooms()
  3.  {
  4.      boolean tried_vault = FALSE;
  5.  
  6.      /* make rooms until satisfied */
  7.      /* rnd_rect() will returns 0 if no more rects are available... */
  8.      while (nroom < MAXNROFROOMS && rnd_rect()) {
  9.          if (nroom >= (MAXNROFROOMS / 6) && rn2(2) && !tried_vault) {
  10.              tried_vault = TRUE;
  11.              if (create_vault()) {
  12.                  vault_x = rooms[nroom].lx;
  13.                  vault_y = rooms[nroom].ly;
  14.                  rooms[nroom].hx = -1;
  15.              }
  16.          } else if (!create_room(-1, -1, -1, -1, -1, -1, OROOM, -1))
  17.              return;
  18.      }
  19.      return;
  20.  }
  21.  

join

  1.  STATIC_OVL void
  2.  join(a, b, nxcor)
  3.  register int a, b;
  4.  boolean nxcor;
  5.  {
  6.      coord cc, tt, org, dest;
  7.      register xchar tx, ty, xx, yy;
  8.      register struct mkroom *croom, *troom;
  9.      register int dx, dy;
  10.  
  11.      croom = &rooms[a];
  12.      troom = &rooms[b];
  13.  
  14.      /* find positions cc and tt for doors in croom and troom
  15.         and direction for a corridor between them */
  16.  
  17.      if (troom->hx < 0 || croom->hx < 0 || doorindex >= DOORMAX)
  18.          return;
  19.      if (troom->lx > croom->hx) {
  20.          dx = 1;
  21.          dy = 0;
  22.          xx = croom->hx + 1;
  23.          tx = troom->lx - 1;
  24.          finddpos(&cc, xx, croom->ly, xx, croom->hy);
  25.          finddpos(&tt, tx, troom->ly, tx, troom->hy);
  26.      } else if (troom->hy < croom->ly) {
  27.          dy = -1;
  28.          dx = 0;
  29.          yy = croom->ly - 1;
  30.          finddpos(&cc, croom->lx, yy, croom->hx, yy);
  31.          ty = troom->hy + 1;
  32.          finddpos(&tt, troom->lx, ty, troom->hx, ty);
  33.      } else if (troom->hx < croom->lx) {
  34.          dx = -1;
  35.          dy = 0;
  36.          xx = croom->lx - 1;
  37.          tx = troom->hx + 1;
  38.          finddpos(&cc, xx, croom->ly, xx, croom->hy);
  39.          finddpos(&tt, tx, troom->ly, tx, troom->hy);
  40.      } else {
  41.          dy = 1;
  42.          dx = 0;
  43.          yy = croom->hy + 1;
  44.          ty = troom->ly - 1;
  45.          finddpos(&cc, croom->lx, yy, croom->hx, yy);
  46.          finddpos(&tt, troom->lx, ty, troom->hx, ty);
  47.      }
  48.      xx = cc.x;
  49.      yy = cc.y;
  50.      tx = tt.x - dx;
  51.      ty = tt.y - dy;
  52.      if (nxcor && levl[xx + dx][yy + dy].typ)
  53.          return;
  54.      if (okdoor(xx, yy) || !nxcor)
  55.          dodoor(xx, yy, croom);
  56.  
  57.      org.x = xx + dx;
  58.      org.y = yy + dy;
  59.      dest.x = tx;
  60.      dest.y = ty;
  61.  
  62.      if (!dig_corridor(&org, &dest, nxcor, level.flags.arboreal ? ROOM : CORR,
  63.                        STONE))
  64.          return;
  65.  
  66.      /* we succeeded in digging the corridor */
  67.      if (okdoor(tt.x, tt.y) || !nxcor)
  68.          dodoor(tt.x, tt.y, troom);
  69.  
  70.      if (smeq[a] < smeq[b])
  71.          smeq[b] = smeq[a];
  72.      else
  73.          smeq[a] = smeq[b];
  74.  }
  75.  

makecorridors

  1.  void
  2.  makecorridors()
  3.  {
  4.      int a, b, i;
  5.      boolean any = TRUE;
  6.  
  7.      for (a = 0; a < nroom - 1; a++) {
  8.          join(a, a + 1, FALSE);
  9.          if (!rn2(50))
  10.              break; /* allow some randomness */
  11.      }
  12.      for (a = 0; a < nroom - 2; a++)
  13.          if (smeq[a] != smeq[a + 2])
  14.              join(a, a + 2, FALSE);
  15.      for (a = 0; any && a < nroom; a++) {
  16.          any = FALSE;
  17.          for (b = 0; b < nroom; b++)
  18.              if (smeq[a] != smeq[b]) {
  19.                  join(a, b, FALSE);
  20.                  any = TRUE;
  21.              }
  22.      }
  23.      if (nroom > 2)
  24.          for (i = rn2(nroom) + 4; i; i--) {
  25.              a = rn2(nroom);
  26.              b = rn2(nroom - 2);
  27.              if (b >= a)
  28.                  b += 2;
  29.              join(a, b, TRUE);
  30.          }
  31.  }
  32.  

add_door

  1.  void
  2.  add_door(x, y, aroom)
  3.  register int x, y;
  4.  register struct mkroom *aroom;
  5.  {
  6.      register struct mkroom *broom;
  7.      register int tmp;
  8.      int i;
  9.  
  10.      if (aroom->doorct == 0)
  11.          aroom->fdoor = doorindex;
  12.  
  13.      aroom->doorct++;
  14.  
  15.      for (tmp = doorindex; tmp > aroom->fdoor; tmp--)
  16.          doors[tmp] = doors[tmp - 1];
  17.  
  18.      for (i = 0; i < nroom; i++) {
  19.          broom = &rooms[i];
  20.          if (broom != aroom && broom->doorct && broom->fdoor >= aroom->fdoor)
  21.              broom->fdoor++;
  22.      }
  23.      for (i = 0; i < nsubroom; i++) {
  24.          broom = &subrooms[i];
  25.          if (broom != aroom && broom->doorct && broom->fdoor >= aroom->fdoor)
  26.              broom->fdoor++;
  27.      }
  28.  
  29.      doorindex++;
  30.      doors[aroom->fdoor].x = x;
  31.      doors[aroom->fdoor].y = y;
  32.  }
  33.  

dosdoor

  1.  STATIC_OVL void
  2.  dosdoor(x, y, aroom, type)
  3.  register xchar x, y;
  4.  struct mkroom *aroom;
  5.  int type;
  6.  {
  7.      boolean shdoor = *in_rooms(x, y, SHOPBASE) ? TRUE : FALSE;
  8.  
  9.      if (!IS_WALL(levl[x][y].typ)) /* avoid SDOORs on already made doors */
  10.          type = DOOR;
  11.      levl[x][y].typ = type;
  12.      if (type == DOOR) {
  13.          if (!rn2(3)) { /* is it a locked door, closed, or a doorway? */
  14.              if (!rn2(5))
  15.                  levl[x][y].doormask = D_ISOPEN;
  16.              else if (!rn2(6))
  17.                  levl[x][y].doormask = D_LOCKED;
  18.              else
  19.                  levl[x][y].doormask = D_CLOSED;
  20.  
  21.              if (levl[x][y].doormask != D_ISOPEN && !shdoor
  22.                  && level_difficulty() >= 5 && !rn2(25))
  23.                  levl[x][y].doormask |= D_TRAPPED;
  24.          } else {
  25.  #ifdef STUPID
  26.              if (shdoor)
  27.                  levl[x][y].doormask = D_ISOPEN;
  28.              else
  29.                  levl[x][y].doormask = D_NODOOR;
  30.  #else
  31.              levl[x][y].doormask = (shdoor ? D_ISOPEN : D_NODOOR);
  32.  #endif
  33.          }
  34.  
  35.          /* also done in roguecorr(); doing it here first prevents
  36.             making mimics in place of trapped doors on rogue level */
  37.          if (Is_rogue_level(&u.uz))
  38.              levl[x][y].doormask = D_NODOOR;
  39.  
  40.          if (levl[x][y].doormask & D_TRAPPED) {
  41.              struct monst *mtmp;
  42.  
  43.              if (level_difficulty() >= 9 && !rn2(5)
  44.                  && !((mvitals[PM_SMALL_MIMIC].mvflags & G_GONE)
  45.                       && (mvitals[PM_LARGE_MIMIC].mvflags & G_GONE)
  46.                       && (mvitals[PM_GIANT_MIMIC].mvflags & G_GONE))) {
  47.                  /* make a mimic instead */
  48.                  levl[x][y].doormask = D_NODOOR;
  49.                  mtmp = makemon(mkclass(S_MIMIC, 0), x, y, NO_MM_FLAGS);
  50.                  if (mtmp)
  51.                      set_mimic_sym(mtmp);
  52.              }
  53.          }
  54.          /* newsym(x,y); */
  55.      } else { /* SDOOR */
  56.          if (shdoor || !rn2(5))
  57.              levl[x][y].doormask = D_LOCKED;
  58.          else
  59.              levl[x][y].doormask = D_CLOSED;
  60.  
  61.          if (!shdoor && level_difficulty() >= 4 && !rn2(20))
  62.              levl[x][y].doormask |= D_TRAPPED;
  63.      }
  64.  
  65.      add_door(x, y, aroom);
  66.  }
  67.  

place_niche

  1.  STATIC_OVL boolean
  2.  place_niche(aroom, dy, xx, yy)
  3.  register struct mkroom *aroom;
  4.  int *dy, *xx, *yy;
  5.  {
  6.      coord dd;
  7.  
  8.      if (rn2(2)) {
  9.          *dy = 1;
  10.          finddpos(&dd, aroom->lx, aroom->hy + 1, aroom->hx, aroom->hy + 1);
  11.      } else {
  12.          *dy = -1;
  13.          finddpos(&dd, aroom->lx, aroom->ly - 1, aroom->hx, aroom->ly - 1);
  14.      }
  15.      *xx = dd.x;
  16.      *yy = dd.y;
  17.      return (boolean) ((isok(*xx, *yy + *dy)
  18.                         && levl[*xx][*yy + *dy].typ == STONE)
  19.                        && (isok(*xx, *yy - *dy)
  20.                            && !IS_POOL(levl[*xx][*yy - *dy].typ)
  21.                            && !IS_FURNITURE(levl[*xx][*yy - *dy].typ)));
  22.  }
  23.  
  24.  /* there should be one of these per trap, in the same order as trap.h */
  25.  static NEARDATA const char *trap_engravings[TRAPNUM] = {
  26.      (char *) 0,      (char *) 0,    (char *) 0,    (char *) 0, (char *) 0,
  27.      (char *) 0,      (char *) 0,    (char *) 0,    (char *) 0, (char *) 0,
  28.      (char *) 0,      (char *) 0,    (char *) 0,    (char *) 0,
  29.      /* 14..16: trap door, teleport, level-teleport */
  30.      "Vlad was here", "ad aerarium", "ad aerarium", (char *) 0, (char *) 0,
  31.      (char *) 0,      (char *) 0,    (char *) 0,    (char *) 0, (char *) 0,
  32.  };
  33.  

makeniche

  1.  STATIC_OVL void
  2.  makeniche(trap_type)
  3.  int trap_type;
  4.  {
  5.      register struct mkroom *aroom;
  6.      struct rm *rm;
  7.      int vct = 8;
  8.      int dy, xx, yy;
  9.      struct trap *ttmp;
  10.  
  11.      if (doorindex < DOORMAX) {
  12.          while (vct--) {
  13.              aroom = &rooms[rn2(nroom)];
  14.              if (aroom->rtype != OROOM)
  15.                  continue; /* not an ordinary room */
  16.              if (aroom->doorct == 1 && rn2(5))
  17.                  continue;
  18.              if (!place_niche(aroom, &dy, &xx, &yy))
  19.                  continue;
  20.  
  21.              rm = &levl[xx][yy + dy];
  22.              if (trap_type || !rn2(4)) {
  23.                  rm->typ = SCORR;
  24.                  if (trap_type) {
  25.                      if ((trap_type == HOLE || trap_type == TRAPDOOR)
  26.                          && !Can_fall_thru(&u.uz))
  27.                          trap_type = ROCKTRAP;
  28.                      ttmp = maketrap(xx, yy + dy, trap_type);
  29.                      if (ttmp) {
  30.                          if (trap_type != ROCKTRAP)
  31.                              ttmp->once = 1;
  32.                          if (trap_engravings[trap_type]) {
  33.                              make_engr_at(xx, yy - dy,
  34.                                           trap_engravings[trap_type], 0L,
  35.                                           DUST);
  36.                              wipe_engr_at(xx, yy - dy, 5,
  37.                                           FALSE); /* age it a little */
  38.                          }
  39.                      }
  40.                  }
  41.                  dosdoor(xx, yy, aroom, SDOOR);
  42.              } else {
  43.                  rm->typ = CORR;
  44.                  if (rn2(7))
  45.                      dosdoor(xx, yy, aroom, rn2(5) ? SDOOR : DOOR);
  46.                  else {
  47.                      /* inaccessible niches occasionally have iron bars */
  48.                      if (!rn2(5) && IS_WALL(levl[xx][yy].typ)) {
  49.                          levl[xx][yy].typ = IRONBARS;
  50.                          if (rn2(3))
  51.                              (void) mkcorpstat(CORPSE, (struct monst *) 0,
  52.                                                mkclass(S_HUMAN, 0), xx,
  53.                                                yy + dy, TRUE);
  54.                      }
  55.                      if (!level.flags.noteleport)
  56.                          (void) mksobj_at(SCR_TELEPORTATION, xx, yy + dy, TRUE,
  57.                                           FALSE);
  58.                      if (!rn2(3))
  59.                          (void) mkobj_at(0, xx, yy + dy, TRUE);
  60.                  }
  61.              }
  62.              return;
  63.          }
  64.      }
  65.  }
  66.  

make_niches

  1.  STATIC_OVL void
  2.  make_niches()
  3.  {
  4.      int ct = rnd((nroom >> 1) + 1), dep = depth(&u.uz);
  5.      boolean ltptr = (!level.flags.noteleport && dep > 15),
  6.              vamp = (dep > 5 && dep < 25);
  7.  
  8.      while (ct--) {
  9.          if (ltptr && !rn2(6)) {
  10.              ltptr = FALSE;
  11.              makeniche(LEVEL_TELEP);
  12.          } else if (vamp && !rn2(6)) {
  13.              vamp = FALSE;
  14.              makeniche(TRAPDOOR);
  15.          } else
  16.              makeniche(NO_TRAP);
  17.      }
  18.  }
  19.  

makevtele

  1.  STATIC_OVL void
  2.  makevtele()
  3.  {
  4.      makeniche(TELEP_TRAP);
  5.  }
  6.  

clear_level_structures

  1.  /* clear out various globals that keep information on the current level.
  2.   * some of this is only necessary for some types of levels (maze, normal,
  3.   * special) but it's easier to put it all in one place than make sure
  4.   * each type initializes what it needs to separately.
  5.   */
  6.  STATIC_OVL void
  7.  clear_level_structures()
  8.  {
  9.      static struct rm zerorm = { cmap_to_glyph(S_stone),
  10.                                  0, 0, 0, 0, 0, 0, 0, 0, 0 };
  11.      register int x, y;
  12.      register struct rm *lev;
  13.  
  14.      for (x = 0; x < COLNO; x++) {
  15.          lev = &levl[x][0];
  16.          for (y = 0; y < ROWNO; y++) {
  17.              *lev++ = zerorm;
  18.              /*
  19.               * These used to be '#if MICROPORT_BUG',
  20.               * with use of memset(0) for '#if !MICROPORT_BUG' below,
  21.               * but memset is not appropriate for initializing pointers,
  22.               * so do these level.objects[][] and level.monsters[][]
  23.               * initializations unconditionally.
  24.               */
  25.              level.objects[x][y] = (struct obj *) 0;
  26.              level.monsters[x][y] = (struct monst *) 0;
  27.          }
  28.      }
  29.      level.objlist = (struct obj *) 0;
  30.      level.buriedobjlist = (struct obj *) 0;
  31.      level.monlist = (struct monst *) 0;
  32.      level.damagelist = (struct damage *) 0;
  33.      level.bonesinfo = (struct cemetery *) 0;
  34.  
  35.      level.flags.nfountains = 0;
  36.      level.flags.nsinks = 0;
  37.      level.flags.has_shop = 0;
  38.      level.flags.has_vault = 0;
  39.      level.flags.has_zoo = 0;
  40.      level.flags.has_court = 0;
  41.      level.flags.has_morgue = level.flags.graveyard = 0;
  42.      level.flags.has_beehive = 0;
  43.      level.flags.has_barracks = 0;
  44.      level.flags.has_temple = 0;
  45.      level.flags.has_swamp = 0;
  46.      level.flags.noteleport = 0;
  47.      level.flags.hardfloor = 0;
  48.      level.flags.nommap = 0;
  49.      level.flags.hero_memory = 1;
  50.      level.flags.shortsighted = 0;
  51.      level.flags.sokoban_rules = 0;
  52.      level.flags.is_maze_lev = 0;
  53.      level.flags.is_cavernous_lev = 0;
  54.      level.flags.arboreal = 0;
  55.      level.flags.wizard_bones = 0;
  56.      level.flags.corrmaze = 0;
  57.  
  58.      nroom = 0;
  59.      rooms[0].hx = -1;
  60.      nsubroom = 0;
  61.      subrooms[0].hx = -1;
  62.      doorindex = 0;
  63.      init_rect();
  64.      init_vault();
  65.      xdnstair = ydnstair = xupstair = yupstair = 0;
  66.      sstairs.sx = sstairs.sy = 0;
  67.      xdnladder = ydnladder = xupladder = yupladder = 0;
  68.      made_branch = FALSE;
  69.      clear_regions();
  70.  }
  71.  

makelevel

  1.  STATIC_OVL void
  2.  makelevel()
  3.  {
  4.      register struct mkroom *croom, *troom;
  5.      register int tryct;
  6.      register int x, y;
  7.      struct monst *tmonst; /* always put a web with a spider */
  8.      branch *branchp;
  9.      int room_threshold;
  10.  
  11.      if (wiz1_level.dlevel == 0)
  12.          init_dungeons();
  13.      oinit(); /* assign level dependent obj probabilities */
  14.      clear_level_structures();
  15.  
  16.      {
  17.          register s_level *slev = Is_special(&u.uz);
  18.  
  19.          /* check for special levels */
  20.          if (slev && !Is_rogue_level(&u.uz)) {
  21.              makemaz(slev->proto);
  22.              return;
  23.          } else if (dungeons[u.uz.dnum].proto[0]) {
  24.              makemaz("");
  25.              return;
  26.          } else if (In_mines(&u.uz)) {
  27.              makemaz("minefill");
  28.              return;
  29.          } else if (In_quest(&u.uz)) {
  30.              char fillname[9];
  31.              s_level *loc_lev;
  32.  
  33.              Sprintf(fillname, "%s-loca", urole.filecode);
  34.              loc_lev = find_level(fillname);
  35.  
  36.              Sprintf(fillname, "%s-fil", urole.filecode);
  37.              Strcat(fillname,
  38.                     (u.uz.dlevel < loc_lev->dlevel.dlevel) ? "a" : "b");
  39.              makemaz(fillname);
  40.              return;
  41.          } else if (In_hell(&u.uz)
  42.                     || (rn2(5) && u.uz.dnum == medusa_level.dnum
  43.                         && depth(&u.uz) > depth(&medusa_level))) {
  44.              makemaz("");
  45.              return;
  46.          }
  47.      }
  48.  
  49.      /* otherwise, fall through - it's a "regular" level. */
  50.  
  51.      if (Is_rogue_level(&u.uz)) {
  52.          makeroguerooms();
  53.          makerogueghost();
  54.      } else
  55.          makerooms();
  56.      sort_rooms();
  57.  
  58.      /* construct stairs (up and down in different rooms if possible) */
  59.      croom = &rooms[rn2(nroom)];
  60.      if (!Is_botlevel(&u.uz))
  61.          mkstairs(somex(croom), somey(croom), 0, croom); /* down */
  62.      if (nroom > 1) {
  63.          troom = croom;
  64.          croom = &rooms[rn2(nroom - 1)];
  65.          if (croom == troom)
  66.              croom++;
  67.      }
  68.  
  69.      if (u.uz.dlevel != 1) {
  70.          xchar sx, sy;
  71.          do {
  72.              sx = somex(croom);
  73.              sy = somey(croom);
  74.          } while (occupied(sx, sy));
  75.          mkstairs(sx, sy, 1, croom); /* up */
  76.      }
  77.  
  78.      branchp = Is_branchlev(&u.uz);    /* possible dungeon branch */
  79.      room_threshold = branchp ? 4 : 3; /* minimum number of rooms needed
  80.                                           to allow a random special room */
  81.      if (Is_rogue_level(&u.uz))
  82.          goto skip0;
  83.      makecorridors();
  84.      make_niches();
  85.  
  86.      /* make a secret treasure vault, not connected to the rest */
  87.      if (do_vault()) {
  88.          xchar w, h;
  89.          debugpline0("trying to make a vault...");
  90.          w = 1;
  91.          h = 1;
  92.          if (check_room(&vault_x, &w, &vault_y, &h, TRUE)) {
  93.          fill_vault:
  94.              add_room(vault_x, vault_y, vault_x + w, vault_y + h, TRUE, VAULT,
  95.                       FALSE);
  96.              level.flags.has_vault = 1;
  97.              ++room_threshold;
  98.              fill_room(&rooms[nroom - 1], FALSE);
  99.              mk_knox_portal(vault_x + w, vault_y + h);
  100.              if (!level.flags.noteleport && !rn2(3))
  101.                  makevtele();
  102.          } else if (rnd_rect() && create_vault()) {
  103.              vault_x = rooms[nroom].lx;
  104.              vault_y = rooms[nroom].ly;
  105.              if (check_room(&vault_x, &w, &vault_y, &h, TRUE))
  106.                  goto fill_vault;
  107.              else
  108.                  rooms[nroom].hx = -1;
  109.          }
  110.      }
  111.  
  112.      {
  113.          register int u_depth = depth(&u.uz);
  114.  
  115.          if (wizard && nh_getenv("SHOPTYPE"))
  116.              mkroom(SHOPBASE);
  117.          else if (u_depth > 1 && u_depth < depth(&medusa_level)
  118.                   && nroom >= room_threshold && rn2(u_depth) < 3)
  119.              mkroom(SHOPBASE);
  120.          else if (u_depth > 4 && !rn2(6))
  121.              mkroom(COURT);
  122.          else if (u_depth > 5 && !rn2(8)
  123.                   && !(mvitals[PM_LEPRECHAUN].mvflags & G_GONE))
  124.              mkroom(LEPREHALL);
  125.          else if (u_depth > 6 && !rn2(7))
  126.              mkroom(ZOO);
  127.          else if (u_depth > 8 && !rn2(5))
  128.              mkroom(TEMPLE);
  129.          else if (u_depth > 9 && !rn2(5)
  130.                   && !(mvitals[PM_KILLER_BEE].mvflags & G_GONE))
  131.              mkroom(BEEHIVE);
  132.          else if (u_depth > 11 && !rn2(6))
  133.              mkroom(MORGUE);
  134.          else if (u_depth > 12 && !rn2(8) && antholemon())
  135.              mkroom(ANTHOLE);
  136.          else if (u_depth > 14 && !rn2(4)
  137.                   && !(mvitals[PM_SOLDIER].mvflags & G_GONE))
  138.              mkroom(BARRACKS);
  139.          else if (u_depth > 15 && !rn2(6))
  140.              mkroom(SWAMP);
  141.          else if (u_depth > 16 && !rn2(8)
  142.                   && !(mvitals[PM_COCKATRICE].mvflags & G_GONE))
  143.              mkroom(COCKNEST);
  144.      }
  145.  
  146.  skip0:
  147.      /* Place multi-dungeon branch. */
  148.      place_branch(branchp, 0, 0);
  149.  
  150.      /* for each room: put things inside */
  151.      for (croom = rooms; croom->hx > 0; croom++) {
  152.          if (croom->rtype != OROOM)
  153.              continue;
  154.  
  155.          /* put a sleeping monster inside */
  156.          /* Note: monster may be on the stairs. This cannot be
  157.             avoided: maybe the player fell through a trap door
  158.             while a monster was on the stairs. Conclusion:
  159.             we have to check for monsters on the stairs anyway. */
  160.  
  161.          if (u.uhave.amulet || !rn2(3)) {
  162.              x = somex(croom);
  163.              y = somey(croom);
  164.              tmonst = makemon((struct permonst *) 0, x, y, NO_MM_FLAGS);
  165.              if (tmonst && tmonst->data == &mons[PM_GIANT_SPIDER]
  166.                  && !occupied(x, y))
  167.                  (void) maketrap(x, y, WEB);
  168.          }
  169.          /* put traps and mimics inside */
  170.          x = 8 - (level_difficulty() / 6);
  171.          if (x <= 1)
  172.              x = 2;
  173.          while (!rn2(x))
  174.              mktrap(0, 0, croom, (coord *) 0);
  175.          if (!rn2(3))
  176.              (void) mkgold(0L, somex(croom), somey(croom));
  177.          if (Is_rogue_level(&u.uz))
  178.              goto skip_nonrogue;
  179.          if (!rn2(10))
  180.              mkfount(0, croom);
  181.          if (!rn2(60))
  182.              mksink(croom);
  183.          if (!rn2(60))
  184.              mkaltar(croom);
  185.          x = 80 - (depth(&u.uz) * 2);
  186.          if (x < 2)
  187.              x = 2;
  188.          if (!rn2(x))
  189.              mkgrave(croom);
  190.  
  191.          /* put statues inside */
  192.          if (!rn2(20))
  193.              (void) mkcorpstat(STATUE, (struct monst *) 0,
  194.                                (struct permonst *) 0, somex(croom),
  195.                                somey(croom), CORPSTAT_INIT);
  196.          /* put box/chest inside;
  197.           *  40% chance for at least 1 box, regardless of number
  198.           *  of rooms; about 5 - 7.5% for 2 boxes, least likely
  199.           *  when few rooms; chance for 3 or more is negligible.
  200.           */
  201.          if (!rn2(nroom * 5 / 2))
  202.              (void) mksobj_at((rn2(3)) ? LARGE_BOX : CHEST, somex(croom),
  203.                               somey(croom), TRUE, FALSE);
  204.  
  205.          /* maybe make some graffiti */
  206.          if (!rn2(27 + 3 * abs(depth(&u.uz)))) {
  207.              char buf[BUFSZ];
  208.              const char *mesg = random_engraving(buf);
  209.              if (mesg) {
  210.                  do {
  211.                      x = somex(croom);
  212.                      y = somey(croom);
  213.                  } while (levl[x][y].typ != ROOM && !rn2(40));
  214.                  if (!(IS_POOL(levl[x][y].typ)
  215.                        || IS_FURNITURE(levl[x][y].typ)))
  216.                      make_engr_at(x, y, mesg, 0L, MARK);
  217.              }
  218.          }
  219.  
  220.      skip_nonrogue:
  221.          if (!rn2(3)) {
  222.              (void) mkobj_at(0, somex(croom), somey(croom), TRUE);
  223.              tryct = 0;
  224.              while (!rn2(5)) {
  225.                  if (++tryct > 100) {
  226.                      impossible("tryct overflow4");
  227.                      break;
  228.                  }
  229.                  (void) mkobj_at(0, somex(croom), somey(croom), TRUE);
  230.              }
  231.          }
  232.      }
  233.  }
  234.  

mineralize

  1.  /*
  2.   *      Place deposits of minerals (gold and misc gems) in the stone
  3.   *      surrounding the rooms on the map.
  4.   *      Also place kelp in water.
  5.   *      mineralize(-1, -1, -1, -1, FALSE); => "default" behaviour
  6.   */
  7.  void
  8.  mineralize(kelp_pool, kelp_moat, goldprob, gemprob, skip_lvl_checks)
  9.  int kelp_pool, kelp_moat, goldprob, gemprob;
  10.  boolean skip_lvl_checks;
  11.  {
  12.      s_level *sp;
  13.      struct obj *otmp;
  14.      int x, y, cnt;
  15.  
  16.      if (kelp_pool < 0)
  17.          kelp_pool = 10;
  18.      if (kelp_moat < 0)
  19.          kelp_moat = 30;
  20.  
  21.      /* Place kelp, except on the plane of water */
  22.      if (!skip_lvl_checks && In_endgame(&u.uz))
  23.          return;
  24.      for (x = 2; x < (COLNO - 2); x++)
  25.          for (y = 1; y < (ROWNO - 1); y++)
  26.              if ((kelp_pool && levl[x][y].typ == POOL && !rn2(kelp_pool))
  27.                  || (kelp_moat && levl[x][y].typ == MOAT && !rn2(kelp_moat)))
  28.                  (void) mksobj_at(KELP_FROND, x, y, TRUE, FALSE);
  29.  
  30.      /* determine if it is even allowed;
  31.         almost all special levels are excluded */
  32.      if (!skip_lvl_checks
  33.          && (In_hell(&u.uz) || In_V_tower(&u.uz) || Is_rogue_level(&u.uz)
  34.              || level.flags.arboreal
  35.              || ((sp = Is_special(&u.uz)) != 0 && !Is_oracle_level(&u.uz)
  36.                  && (!In_mines(&u.uz) || sp->flags.town))))
  37.          return;
  38.  
  39.      /* basic level-related probabilities */
  40.      if (goldprob < 0)
  41.          goldprob = 20 + depth(&u.uz) / 3;
  42.      if (gemprob < 0)
  43.          gemprob = goldprob / 4;
  44.  
  45.      /* mines have ***MORE*** goodies - otherwise why mine? */
  46.      if (!skip_lvl_checks) {
  47.          if (In_mines(&u.uz)) {
  48.              goldprob *= 2;
  49.              gemprob *= 3;
  50.          } else if (In_quest(&u.uz)) {
  51.              goldprob /= 4;
  52.              gemprob /= 6;
  53.          }
  54.      }
  55.  
  56.      /*
  57.       * Seed rock areas with gold and/or gems.
  58.       * We use fairly low level object handling to avoid unnecessary
  59.       * overhead from placing things in the floor chain prior to burial.
  60.       */
  61.      for (x = 2; x < (COLNO - 2); x++)
  62.          for (y = 1; y < (ROWNO - 1); y++)
  63.              if (levl[x][y + 1].typ != STONE) { /* <x,y> spot not eligible */
  64.                  y += 2; /* next two spots aren't eligible either */
  65.              } else if (levl[x][y].typ != STONE) { /* this spot not eligible */
  66.                  y += 1; /* next spot isn't eligible either */
  67.              } else if (!(levl[x][y].wall_info & W_NONDIGGABLE)
  68.                         && levl[x][y - 1].typ == STONE
  69.                         && levl[x + 1][y - 1].typ == STONE
  70.                         && levl[x - 1][y - 1].typ == STONE
  71.                         && levl[x + 1][y].typ == STONE
  72.                         && levl[x - 1][y].typ == STONE
  73.                         && levl[x + 1][y + 1].typ == STONE
  74.                         && levl[x - 1][y + 1].typ == STONE) {
  75.                  if (rn2(1000) < goldprob) {
  76.                      if ((otmp = mksobj(GOLD_PIECE, FALSE, FALSE)) != 0) {
  77.                          otmp->ox = x, otmp->oy = y;
  78.                          otmp->quan = 1L + rnd(goldprob * 3);
  79.                          otmp->owt = weight(otmp);
  80.                          if (!rn2(3))
  81.                              add_to_buried(otmp);
  82.                          else
  83.                              place_object(otmp, x, y);
  84.                      }
  85.                  }
  86.                  if (rn2(1000) < gemprob) {
  87.                      for (cnt = rnd(2 + dunlev(&u.uz) / 3); cnt > 0; cnt--)
  88.                          if ((otmp = mkobj(GEM_CLASS, FALSE)) != 0) {
  89.                              if (otmp->otyp == ROCK) {
  90.                                  dealloc_obj(otmp); /* discard it */
  91.                              } else {
  92.                                  otmp->ox = x, otmp->oy = y;
  93.                                  if (!rn2(3))
  94.                                      add_to_buried(otmp);
  95.                                  else
  96.                                      place_object(otmp, x, y);
  97.                              }
  98.                          }
  99.                  }
  100.              }
  101.  }
  102.  

mklev

  1.  void
  2.  mklev()
  3.  {
  4.      struct mkroom *croom;
  5.      int ridx;
  6.  
  7.      init_mapseen(&u.uz);
  8.      if (getbones())
  9.          return;
  10.  
  11.      in_mklev = TRUE;
  12.      makelevel();
  13.      bound_digging();
  14.      mineralize(-1, -1, -1, -1, FALSE);
  15.      in_mklev = FALSE;
  16.      /* has_morgue gets cleared once morgue is entered; graveyard stays
  17.         set (graveyard might already be set even when has_morgue is clear
  18.         [see fixup_special()], so don't update it unconditionally) */
  19.      if (level.flags.has_morgue)
  20.          level.flags.graveyard = 1;
  21.      if (!level.flags.is_maze_lev) {
  22.          for (croom = &rooms[0]; croom != &rooms[nroom]; croom++)
  23.  #ifdef SPECIALIZATION
  24.              topologize(croom, FALSE);
  25.  #else
  26.              topologize(croom);
  27.  #endif
  28.      }
  29.      set_wall_state();
  30.      /* for many room types, rooms[].rtype is zeroed once the room has been
  31.         entered; rooms[].orig_rtype always retains original rtype value */
  32.      for (ridx = 0; ridx < SIZE(rooms); ridx++)
  33.          rooms[ridx].orig_rtype = rooms[ridx].rtype;
  34.  }
  35.  

topologize

  1.  void
  2.  #ifdef SPECIALIZATION
  3.  topologize(croom, do_ordinary)
  4.  struct mkroom *croom;
  5.  boolean do_ordinary;
  6.  #else
  7.  topologize(croom)
  8.  struct mkroom *croom;
  9.  #endif
  10.  {
  11.      register int x, y, roomno = (int) ((croom - rooms) + ROOMOFFSET);
  12.      int lowx = croom->lx, lowy = croom->ly;
  13.      int hix = croom->hx, hiy = croom->hy;
  14.  #ifdef SPECIALIZATION
  15.      schar rtype = croom->rtype;
  16.  #endif
  17.      int subindex, nsubrooms = croom->nsubrooms;
  18.  
  19.      /* skip the room if already done; i.e. a shop handled out of order */
  20.      /* also skip if this is non-rectangular (it _must_ be done already) */
  21.      if ((int) levl[lowx][lowy].roomno == roomno || croom->irregular)
  22.          return;
  23.  #ifdef SPECIALIZATION
  24.      if (Is_rogue_level(&u.uz))
  25.          do_ordinary = TRUE; /* vision routine helper */
  26.      if ((rtype != OROOM) || do_ordinary)
  27.  #endif
  28.          {
  29.          /* do innards first */
  30.          for (x = lowx; x <= hix; x++)
  31.              for (y = lowy; y <= hiy; y++)
  32.  #ifdef SPECIALIZATION
  33.                  if (rtype == OROOM)
  34.                      levl[x][y].roomno = NO_ROOM;
  35.                  else
  36.  #endif
  37.                      levl[x][y].roomno = roomno;
  38.          /* top and bottom edges */
  39.          for (x = lowx - 1; x <= hix + 1; x++)
  40.              for (y = lowy - 1; y <= hiy + 1; y += (hiy - lowy + 2)) {
  41.                  levl[x][y].edge = 1;
  42.                  if (levl[x][y].roomno)
  43.                      levl[x][y].roomno = SHARED;
  44.                  else
  45.                      levl[x][y].roomno = roomno;
  46.              }
  47.          /* sides */
  48.          for (x = lowx - 1; x <= hix + 1; x += (hix - lowx + 2))
  49.              for (y = lowy; y <= hiy; y++) {
  50.                  levl[x][y].edge = 1;
  51.                  if (levl[x][y].roomno)
  52.                      levl[x][y].roomno = SHARED;
  53.                  else
  54.                      levl[x][y].roomno = roomno;
  55.              }
  56.      }
  57.      /* subrooms */
  58.      for (subindex = 0; subindex < nsubrooms; subindex++)
  59.  #ifdef SPECIALIZATION
  60.          topologize(croom->sbrooms[subindex], (boolean) (rtype != OROOM));
  61.  #else
  62.          topologize(croom->sbrooms[subindex]);
  63.  #endif
  64.  }
  65.  

find_branch_room

  1.  /* Find an unused room for a branch location. */
  2.  STATIC_OVL struct mkroom *
  3.  find_branch_room(mp)
  4.  coord *mp;
  5.  {
  6.      struct mkroom *croom = 0;
  7.  
  8.      if (nroom == 0) {
  9.          mazexy(mp); /* already verifies location */
  10.      } else {
  11.          /* not perfect - there may be only one stairway */
  12.          if (nroom > 2) {
  13.              int tryct = 0;
  14.  
  15.              do
  16.                  croom = &rooms[rn2(nroom)];
  17.              while ((croom == dnstairs_room || croom == upstairs_room
  18.                      || croom->rtype != OROOM) && (++tryct < 100));
  19.          } else
  20.              croom = &rooms[rn2(nroom)];
  21.  
  22.          do {
  23.              if (!somexy(croom, mp))
  24.                  impossible("Can't place branch!");
  25.          } while (occupied(mp->x, mp->y)
  26.                   || (levl[mp->x][mp->y].typ != CORR
  27.                       && levl[mp->x][mp->y].typ != ROOM));
  28.      }
  29.      return croom;
  30.  }
  31.  

pos_to_room

  1.  /* Find the room for (x,y).  Return null if not in a room. */
  2.  STATIC_OVL struct mkroom *
  3.  pos_to_room(x, y)
  4.  xchar x, y;
  5.  {
  6.      int i;
  7.      struct mkroom *curr;
  8.  
  9.      for (curr = rooms, i = 0; i < nroom; curr++, i++)
  10.          if (inside_room(curr, x, y))
  11.              return curr;
  12.      ;
  13.      return (struct mkroom *) 0;
  14.  }
  15.  

place_branch

  1.  /* If given a branch, randomly place a special stair or portal. */
  2.  void
  3.  place_branch(br, x, y)
  4.  branch *br; /* branch to place */
  5.  xchar x, y; /* location */
  6.  {
  7.      coord m;
  8.      d_level *dest;
  9.      boolean make_stairs;
  10.      struct mkroom *br_room;
  11.  
  12.      /*
  13.       * Return immediately if there is no branch to make or we have
  14.       * already made one.  This routine can be called twice when
  15.       * a special level is loaded that specifies an SSTAIR location
  16.       * as a favored spot for a branch.
  17.       */
  18.      if (!br || made_branch)
  19.          return;
  20.  
  21.      if (!x) { /* find random coordinates for branch */
  22.          br_room = find_branch_room(&m);
  23.          x = m.x;
  24.          y = m.y;
  25.      } else {
  26.          br_room = pos_to_room(x, y);
  27.      }
  28.  
  29.      if (on_level(&br->end1, &u.uz)) {
  30.          /* we're on end1 */
  31.          make_stairs = br->type != BR_NO_END1;
  32.          dest = &br->end2;
  33.      } else {
  34.          /* we're on end2 */
  35.          make_stairs = br->type != BR_NO_END2;
  36.          dest = &br->end1;
  37.      }
  38.  
  39.      if (br->type == BR_PORTAL) {
  40.          mkportal(x, y, dest->dnum, dest->dlevel);
  41.      } else if (make_stairs) {
  42.          sstairs.sx = x;
  43.          sstairs.sy = y;
  44.          sstairs.up =
  45.              (char) on_level(&br->end1, &u.uz) ? br->end1_up : !br->end1_up;
  46.          assign_level(&sstairs.tolev, dest);
  47.          sstairs_room = br_room;
  48.  
  49.          levl[x][y].ladder = sstairs.up ? LA_UP : LA_DOWN;
  50.          levl[x][y].typ = STAIRS;
  51.      }
  52.      /*
  53.       * Set made_branch to TRUE even if we didn't make a stairwell (i.e.
  54.       * make_stairs is false) since there is currently only one branch
  55.       * per level, if we failed once, we're going to fail again on the
  56.       * next call.
  57.       */
  58.      made_branch = TRUE;
  59.  }
  60.  

bydoor

  1.  STATIC_OVL boolean
  2.  bydoor(x, y)
  3.  register xchar x, y;
  4.  {
  5.      register int typ;
  6.  
  7.      if (isok(x + 1, y)) {
  8.          typ = levl[x + 1][y].typ;
  9.          if (IS_DOOR(typ) || typ == SDOOR)
  10.              return TRUE;
  11.      }
  12.      if (isok(x - 1, y)) {
  13.          typ = levl[x - 1][y].typ;
  14.          if (IS_DOOR(typ) || typ == SDOOR)
  15.              return TRUE;
  16.      }
  17.      if (isok(x, y + 1)) {
  18.          typ = levl[x][y + 1].typ;
  19.          if (IS_DOOR(typ) || typ == SDOOR)
  20.              return TRUE;
  21.      }
  22.      if (isok(x, y - 1)) {
  23.          typ = levl[x][y - 1].typ;
  24.          if (IS_DOOR(typ) || typ == SDOOR)
  25.              return TRUE;
  26.      }
  27.      return FALSE;
  28.  }
  29.  

okdoor

  1.  /* see whether it is allowable to create a door at [x,y] */
  2.  int
  3.  okdoor(x, y)
  4.  xchar x, y;
  5.  {
  6.      boolean near_door = bydoor(x, y);
  7.  
  8.      return ((levl[x][y].typ == HWALL || levl[x][y].typ == VWALL)
  9.              && doorindex < DOORMAX && !near_door);
  10.  }
  11.  

dodoor

  1.  void
  2.  dodoor(x, y, aroom)
  3.  int x, y;
  4.  struct mkroom *aroom;
  5.  {
  6.      if (doorindex >= DOORMAX) {
  7.          impossible("DOORMAX exceeded?");
  8.          return;
  9.      }
  10.  
  11.      dosdoor(x, y, aroom, rn2(8) ? DOOR : SDOOR);
  12.  }
  13.  

occupied

  1.  boolean
  2.  occupied(x, y)
  3.  register xchar x, y;
  4.  {
  5.      return (boolean) (t_at(x, y) || IS_FURNITURE(levl[x][y].typ)
  6.                        || is_lava(x, y) || is_pool(x, y)
  7.                        || invocation_pos(x, y));
  8.  }
  9.  

mktrap

  1.  /* make a trap somewhere (in croom if mazeflag = 0 && !tm) */
  2.  /* if tm != null, make trap at that location */
  3.  void
  4.  mktrap(num, mazeflag, croom, tm)
  5.  int num, mazeflag;
  6.  struct mkroom *croom;
  7.  coord *tm;
  8.  {
  9.      register int kind;
  10.      unsigned lvl = level_difficulty();
  11.      coord m;
  12.  
  13.      /* no traps in pools */
  14.      if (tm && is_pool(tm->x, tm->y))
  15.          return;
  16.  
  17.      if (num > 0 && num < TRAPNUM) {
  18.          kind = num;
  19.      } else if (Is_rogue_level(&u.uz)) {
  20.          switch (rn2(7)) {
  21.          default:
  22.              kind = BEAR_TRAP;
  23.              break; /* 0 */
  24.          case 1:
  25.              kind = ARROW_TRAP;
  26.              break;
  27.          case 2:
  28.              kind = DART_TRAP;
  29.              break;
  30.          case 3:
  31.              kind = TRAPDOOR;
  32.              break;
  33.          case 4:
  34.              kind = PIT;
  35.              break;
  36.          case 5:
  37.              kind = SLP_GAS_TRAP;
  38.              break;
  39.          case 6:
  40.              kind = RUST_TRAP;
  41.              break;
  42.          }
  43.      } else if (Inhell && !rn2(5)) {
  44.          /* bias the frequency of fire traps in Gehennom */
  45.          kind = FIRE_TRAP;
  46.      } else {
  47.          do {
  48.              kind = rnd(TRAPNUM - 1);
  49.              /* reject "too hard" traps */
  50.              switch (kind) {
  51.              case MAGIC_PORTAL:
  52.              case VIBRATING_SQUARE:
  53.                  kind = NO_TRAP;
  54.                  break;
  55.              case ROLLING_BOULDER_TRAP:
  56.              case SLP_GAS_TRAP:
  57.                  if (lvl < 2)
  58.                      kind = NO_TRAP;
  59.                  break;
  60.              case LEVEL_TELEP:
  61.                  if (lvl < 5 || level.flags.noteleport)
  62.                      kind = NO_TRAP;
  63.                  break;
  64.              case SPIKED_PIT:
  65.                  if (lvl < 5)
  66.                      kind = NO_TRAP;
  67.                  break;
  68.              case LANDMINE:
  69.                  if (lvl < 6)
  70.                      kind = NO_TRAP;
  71.                  break;
  72.              case WEB:
  73.                  if (lvl < 7)
  74.                      kind = NO_TRAP;
  75.                  break;
  76.              case STATUE_TRAP:
  77.              case POLY_TRAP:
  78.                  if (lvl < 8)
  79.                      kind = NO_TRAP;
  80.                  break;
  81.              case FIRE_TRAP:
  82.                  if (!Inhell)
  83.                      kind = NO_TRAP;
  84.                  break;
  85.              case TELEP_TRAP:
  86.                  if (level.flags.noteleport)
  87.                      kind = NO_TRAP;
  88.                  break;
  89.              case HOLE:
  90.                  /* make these much less often than other traps */
  91.                  if (rn2(7))
  92.                      kind = NO_TRAP;
  93.                  break;
  94.              }
  95.          } while (kind == NO_TRAP);
  96.      }
  97.  
  98.      if ((kind == TRAPDOOR || kind == HOLE) && !Can_fall_thru(&u.uz))
  99.          kind = ROCKTRAP;
  100.  
  101.      if (tm) {
  102.          m = *tm;
  103.      } else {
  104.          register int tryct = 0;
  105.          boolean avoid_boulder = (kind == PIT || kind == SPIKED_PIT
  106.                                   || kind == TRAPDOOR || kind == HOLE);
  107.  
  108.          do {
  109.              if (++tryct > 200)
  110.                  return;
  111.              if (mazeflag)
  112.                  mazexy(&m);
  113.              else if (!somexy(croom, &m))
  114.                  return;
  115.          } while (occupied(m.x, m.y)
  116.                   || (avoid_boulder && sobj_at(BOULDER, m.x, m.y)));
  117.      }
  118.  
  119.      (void) maketrap(m.x, m.y, kind);
  120.      if (kind == WEB)
  121.          (void) makemon(&mons[PM_GIANT_SPIDER], m.x, m.y, NO_MM_FLAGS);
  122.  
  123.      /* The hero isn't the only person who's entered the dungeon in
  124.         search of treasure. On the very shallowest levels, there's a
  125.         chance that a created trap will have killed something already
  126.         (and this is guaranteed on the first level).
  127.  
  128.         This isn't meant to give any meaningful treasure (in fact, any
  129.         items we drop here are typically cursed, other than ammo fired
  130.         by the trap). Rather, it's mostly just for flavour and to give
  131.         players on very early levels a sufficient chance to avoid traps
  132.         that may end up killing them before they have a fair chance to
  133.         build max HP. Including cursed items gives the same fair chance
  134.         to the starting pet, and fits the rule that possessions of the
  135.         dead are normally cursed.
  136.  
  137.         Some types of traps are excluded because they're entirely
  138.         nonlethal, even indirectly. We also exclude all of the
  139.         later/fancier traps because they tend to have special
  140.         considerations (e.g. webs, portals), often are indirectly
  141.         lethal, and tend not to generate on shallower levels anyway.
  142.         Finally, pits are excluded because it's weird to see an item
  143.         in a pit and yet not be able to identify that the pit is there. */
  144.      if (lvl <= (unsigned) rnd(4)
  145.          && kind != SQKY_BOARD && kind != RUST_TRAP
  146.          && kind != PIT && kind != SPIKED_PIT && kind < HOLE) {
  147.          /* Object generated by the trap; initially NULL, stays NULL if
  148.             we fail to generate an object or if the trap doesn't
  149.             generate objects. */
  150.          struct obj *otmp = NULL;
  151.          int victim_mnum; /* race of the victim */
  152.  
  153.          /* Not all trap types have special handling here; only the ones
  154.             that kill in a specific way that's obvious after the fact. */
  155.          switch (kind) {
  156.          case ARROW_TRAP:
  157.              otmp = mksobj(ARROW, TRUE, FALSE);
  158.              otmp->opoisoned = 0;
  159.              /* don't adjust the quantity; maybe the trap shot multiple
  160.                 times, there was an untrapping attempt, etc... */
  161.              break;
  162.          case DART_TRAP:
  163.              otmp = mksobj(DART, TRUE, FALSE);
  164.              break;
  165.          case ROCKTRAP:
  166.              otmp = mksobj(ROCK, TRUE, FALSE);
  167.              break;
  168.          default:
  169.              /* no item dropped by the trap */
  170.              break;
  171.          }
  172.          if (otmp) {
  173.              place_object(otmp, m.x, m.y);
  174.          }
  175.  
  176.          /* now otmp is reused for other items we're placing */
  177.  
  178.          /* Place a random possession. This could be a weapon, tool,
  179.             food, or gem, i.e. the item classes that are typically
  180.             nonmagical and not worthless. */
  181.          do {
  182.              int poss_class = RANDOM_CLASS; /* init => lint suppression */
  183.  
  184.              switch (rn2(4)) {
  185.              case 0:
  186.                  poss_class = WEAPON_CLASS;
  187.                  break;
  188.              case 1:
  189.                  poss_class = TOOL_CLASS;
  190.                  break;
  191.              case 2:
  192.                  poss_class = FOOD_CLASS;
  193.                  break;
  194.              case 3:
  195.                  poss_class = GEM_CLASS;
  196.                  break;
  197.              }
  198.  
  199.              otmp = mkobj(poss_class, FALSE);
  200.              /* these items are always cursed, both for flavour (owned
  201.                 by a dead adventurer, bones-pile-style) and for balance
  202.                 (less useful to use, and encourage pets to avoid the trap) */
  203.              if (otmp) {
  204.                  otmp->blessed = 0;
  205.                  otmp->cursed = 1;
  206.                  otmp->owt = weight(otmp);
  207.                  place_object(otmp, m.x, m.y);
  208.              }
  209.  
  210.              /* 20% chance of placing an additional item, recursively */
  211.          } while (!rn2(5));
  212.  
  213.          /* Place a corpse. */
  214.          switch (rn2(15)) {
  215.          case 0:
  216.              /* elf corpses are the rarest as they're the most useful */
  217.              victim_mnum = PM_ELF;
  218.              /* elven adventurers get sleep resistance early; so don't
  219.                 generate elf corpses on sleeping gas traps unless a)
  220.                 we're on dlvl 2 (1 is impossible) and b) we pass a coin
  221.                 flip */
  222.              if (kind == SLP_GAS_TRAP && !(lvl <= 2 && rn2(2)))
  223.                  victim_mnum = PM_HUMAN;
  224.              break;
  225.          case 1: case 2:
  226.              victim_mnum = PM_DWARF;
  227.              break;
  228.          case 3: case 4: case 5:
  229.              victim_mnum = PM_ORC;
  230.              break;
  231.          case 6: case 7: case 8: case 9:
  232.              /* more common as they could have come from the Mines */
  233.              victim_mnum = PM_GNOME;
  234.              /* 10% chance of a candle too */
  235.              if (!rn2(10)) {
  236.                  otmp = mksobj(rn2(4) ? TALLOW_CANDLE : WAX_CANDLE,
  237.                                TRUE, FALSE);
  238.                  otmp->quan = 1;
  239.                  otmp->blessed = 0;
  240.                  otmp->cursed = 1;
  241.                  otmp->owt = weight(otmp);
  242.                  place_object(otmp, m.x, m.y);
  243.              }
  244.              break;
  245.          default:
  246.              /* the most common race */
  247.              victim_mnum = PM_HUMAN;
  248.              break;
  249.          }
  250.          otmp = mkcorpstat(CORPSE, NULL, &mons[victim_mnum], m.x, m.y,
  251.                            CORPSTAT_INIT);
  252.          if (otmp)
  253.              otmp->age -= 51; /* died too long ago to eat */
  254.      }
  255.  }
  256.  

mkstairs

  1.  void
  2.  mkstairs(x, y, up, croom)
  3.  xchar x, y;
  4.  char up;
  5.  struct mkroom *croom;
  6.  {
  7.      if (!x) {
  8.          impossible("mkstairs:  bogus stair attempt at <%d,%d>", x, y);
  9.          return;
  10.      }
  11.  
  12.      /*
  13.       * We can't make a regular stair off an end of the dungeon.  This
  14.       * attempt can happen when a special level is placed at an end and
  15.       * has an up or down stair specified in its description file.
  16.       */
  17.      if ((dunlev(&u.uz) == 1 && up)
  18.          || (dunlev(&u.uz) == dunlevs_in_dungeon(&u.uz) && !up))
  19.          return;
  20.  
  21.      if (up) {
  22.          xupstair = x;
  23.          yupstair = y;
  24.          upstairs_room = croom;
  25.      } else {
  26.          xdnstair = x;
  27.          ydnstair = y;
  28.          dnstairs_room = croom;
  29.      }
  30.  
  31.      levl[x][y].typ = STAIRS;
  32.      levl[x][y].ladder = up ? LA_UP : LA_DOWN;
  33.  }
  34.  

mkfount

  1.  STATIC_OVL void
  2.  mkfount(mazeflag, croom)
  3.  int mazeflag;
  4.  struct mkroom *croom;
  5.  {
  6.      coord m;
  7.      register int tryct = 0;
  8.  
  9.      do {
  10.          if (++tryct > 200)
  11.              return;
  12.          if (mazeflag)
  13.              mazexy(&m);
  14.          else if (!somexy(croom, &m))
  15.              return;
  16.      } while (occupied(m.x, m.y) || bydoor(m.x, m.y));
  17.  
  18.      /* Put a fountain at m.x, m.y */
  19.      levl[m.x][m.y].typ = FOUNTAIN;
  20.      /* Is it a "blessed" fountain? (affects drinking from fountain) */
  21.      if (!rn2(7))
  22.          levl[m.x][m.y].blessedftn = 1;
  23.  
  24.      level.flags.nfountains++;
  25.  }
  26.  

mksink

  1.  STATIC_OVL void
  2.  mksink(croom)
  3.  struct mkroom *croom;
  4.  {
  5.      coord m;
  6.      register int tryct = 0;
  7.  
  8.      do {
  9.          if (++tryct > 200)
  10.              return;
  11.          if (!somexy(croom, &m))
  12.              return;
  13.      } while (occupied(m.x, m.y) || bydoor(m.x, m.y));
  14.  
  15.      /* Put a sink at m.x, m.y */
  16.      levl[m.x][m.y].typ = SINK;
  17.  
  18.      level.flags.nsinks++;
  19.  }
  20.  

mkaltar

  1.  STATIC_OVL void
  2.  mkaltar(croom)
  3.  struct mkroom *croom;
  4.  {
  5.      coord m;
  6.      register int tryct = 0;
  7.      aligntyp al;
  8.  
  9.      if (croom->rtype != OROOM)
  10.          return;
  11.  
  12.      do {
  13.          if (++tryct > 200)
  14.              return;
  15.          if (!somexy(croom, &m))
  16.              return;
  17.      } while (occupied(m.x, m.y) || bydoor(m.x, m.y));
  18.  
  19.      /* Put an altar at m.x, m.y */
  20.      levl[m.x][m.y].typ = ALTAR;
  21.  
  22.      /* -1 - A_CHAOTIC, 0 - A_NEUTRAL, 1 - A_LAWFUL */
  23.      al = rn2((int) A_LAWFUL + 2) - 1;
  24.      levl[m.x][m.y].altarmask = Align2amask(al);
  25.  }
  26.  

mkgrave

  1.  static void
  2.  mkgrave(croom)
  3.  struct mkroom *croom;
  4.  {
  5.      coord m;
  6.      register int tryct = 0;
  7.      register struct obj *otmp;
  8.      boolean dobell = !rn2(10);
  9.  
  10.      if (croom->rtype != OROOM)
  11.          return;
  12.  
  13.      do {
  14.          if (++tryct > 200)
  15.              return;
  16.          if (!somexy(croom, &m))
  17.              return;
  18.      } while (occupied(m.x, m.y) || bydoor(m.x, m.y));
  19.  
  20.      /* Put a grave at m.x, m.y */
  21.      make_grave(m.x, m.y, dobell ? "Saved by the bell!" : (char *) 0);
  22.  
  23.      /* Possibly fill it with objects */
  24.      if (!rn2(3))
  25.          (void) mkgold(0L, m.x, m.y);
  26.      for (tryct = rn2(5); tryct; tryct--) {
  27.          otmp = mkobj(RANDOM_CLASS, TRUE);
  28.          if (!otmp)
  29.              return;
  30.          curse(otmp);
  31.          otmp->ox = m.x;
  32.          otmp->oy = m.y;
  33.          add_to_buried(otmp);
  34.      }
  35.  
  36.      /* Leave a bell, in case we accidentally buried someone alive */
  37.      if (dobell)
  38.          (void) mksobj_at(BELL, m.x, m.y, TRUE, FALSE);
  39.      return;
  40.  }
  41.  
  42.  /* maze levels have slightly different constraints from normal levels */
  43.  #define x_maze_min 2
  44.  #define y_maze_min 2
  45.  

mkinvokearea

  1.  /*
  2.   * Major level transmutation: add a set of stairs (to the Sanctum) after
  3.   * an earthquake that leaves behind a a new topology, centered at inv_pos.
  4.   * Assumes there are no rooms within the invocation area and that inv_pos
  5.   * is not too close to the edge of the map.  Also assume the hero can see,
  6.   * which is guaranteed for normal play due to the fact that sight is needed
  7.   * to read the Book of the Dead.
  8.   */
  9.  void
  10.  mkinvokearea()
  11.  {
  12.      int dist;
  13.      xchar xmin = inv_pos.x, xmax = inv_pos.x;
  14.      xchar ymin = inv_pos.y, ymax = inv_pos.y;
  15.      register xchar i;
  16.  
  17.      pline_The("floor shakes violently under you!");
  18.      pline_The("walls around you begin to bend and crumble!");
  19.      display_nhwindow(WIN_MESSAGE, TRUE);
  20.  
  21.      /* any trap hero is stuck in will be going away now */
  22.      if (u.utrap) {
  23.          u.utrap = 0;
  24.          if (u.utraptype == TT_BURIEDBALL)
  25.              buried_ball_to_punishment();
  26.      }
  27.      mkinvpos(xmin, ymin, 0); /* middle, before placing stairs */
  28.  
  29.      for (dist = 1; dist < 7; dist++) {
  30.          xmin--;
  31.          xmax++;
  32.  
  33.          /* top and bottom */
  34.          if (dist != 3) { /* the area is wider that it is high */
  35.              ymin--;
  36.              ymax++;
  37.              for (i = xmin + 1; i < xmax; i++) {
  38.                  mkinvpos(i, ymin, dist);
  39.                  mkinvpos(i, ymax, dist);
  40.              }
  41.          }
  42.  
  43.          /* left and right */
  44.          for (i = ymin; i <= ymax; i++) {
  45.              mkinvpos(xmin, i, dist);
  46.              mkinvpos(xmax, i, dist);
  47.          }
  48.  
  49.          flush_screen(1); /* make sure the new glyphs shows up */
  50.          delay_output();
  51.      }
  52.  
  53.      You("are standing at the top of a stairwell leading down!");
  54.      mkstairs(u.ux, u.uy, 0, (struct mkroom *) 0); /* down */
  55.      newsym(u.ux, u.uy);
  56.      vision_full_recalc = 1; /* everything changed */
  57.  }
  58.  

mkinvpos

  1.  /* Change level topology.  Boulders in the vicinity are eliminated.
  2.   * Temporarily overrides vision in the name of a nice effect.
  3.   */
  4.  STATIC_OVL void
  5.  mkinvpos(x, y, dist)
  6.  xchar x, y;
  7.  int dist;
  8.  {
  9.      struct trap *ttmp;
  10.      struct obj *otmp;
  11.      boolean make_rocks;
  12.      register struct rm *lev = &levl[x][y];
  13.  
  14.      /* clip at existing map borders if necessary */
  15.      if (!within_bounded_area(x, y, x_maze_min + 1, y_maze_min + 1,
  16.                               x_maze_max - 1, y_maze_max - 1)) {
  17.          /* only outermost 2 columns and/or rows may be truncated due to edge
  18.           */
  19.          if (dist < (7 - 2))
  20.              panic("mkinvpos: <%d,%d> (%d) off map edge!", x, y, dist);
  21.          return;
  22.      }
  23.  
  24.      /* clear traps */
  25.      if ((ttmp = t_at(x, y)) != 0)
  26.          deltrap(ttmp);
  27.  
  28.      /* clear boulders; leave some rocks for non-{moat|trap} locations */
  29.      make_rocks = (dist != 1 && dist != 4 && dist != 5) ? TRUE : FALSE;
  30.      while ((otmp = sobj_at(BOULDER, x, y)) != 0) {
  31.          if (make_rocks) {
  32.              fracture_rock(otmp);
  33.              make_rocks = FALSE; /* don't bother with more rocks */
  34.          } else {
  35.              obj_extract_self(otmp);
  36.              obfree(otmp, (struct obj *) 0);
  37.          }
  38.      }
  39.      unblock_point(x, y); /* make sure vision knows this location is open */
  40.  
  41.      /* fake out saved state */
  42.      lev->seenv = 0;
  43.      lev->doormask = 0;
  44.      if (dist < 6)
  45.          lev->lit = TRUE;
  46.      lev->waslit = TRUE;
  47.      lev->horizontal = FALSE;
  48.      /* short-circuit vision recalc */
  49.      viz_array[y][x] = (dist < 6) ? (IN_SIGHT | COULD_SEE) : COULD_SEE;
  50.  
  51.      switch (dist) {
  52.      case 1: /* fire traps */
  53.          if (is_pool(x, y))
  54.              break;
  55.          lev->typ = ROOM;
  56.          ttmp = maketrap(x, y, FIRE_TRAP);
  57.          if (ttmp)
  58.              ttmp->tseen = TRUE;
  59.          break;
  60.      case 0: /* lit room locations */
  61.      case 2:
  62.      case 3:
  63.      case 6: /* unlit room locations */
  64.          lev->typ = ROOM;
  65.          break;
  66.      case 4: /* pools (aka a wide moat) */
  67.      case 5:
  68.          lev->typ = MOAT;
  69.          /* No kelp! */
  70.          break;
  71.      default:
  72.          impossible("mkinvpos called with dist %d", dist);
  73.          break;
  74.      }
  75.  
  76.      /* display new value of position; could have a monster/object on it */
  77.      newsym(x, y);
  78.  }
  79.  

mk_knox_portal

  1.  /*
  2.   * The portal to Ludios is special.  The entrance can only occur within a
  3.   * vault in the main dungeon at a depth greater than 10.  The Ludios branch
  4.   * structure reflects this by having a bogus "source" dungeon:  the value
  5.   * of n_dgns (thus, Is_branchlev() will never find it).
  6.   *
  7.   * Ludios will remain isolated until the branch is corrected by this function.
  8.   */
  9.  STATIC_OVL void
  10.  mk_knox_portal(x, y)
  11.  xchar x, y;
  12.  {
  13.      extern int n_dgns; /* from dungeon.c */
  14.      d_level *source;
  15.      branch *br;
  16.      schar u_depth;
  17.  
  18.      br = dungeon_branch("Fort Ludios");
  19.      if (on_level(&knox_level, &br->end1)) {
  20.          source = &br->end2;
  21.      } else {
  22.          /* disallow Knox branch on a level with one branch already */
  23.          if (Is_branchlev(&u.uz))
  24.              return;
  25.          source = &br->end1;
  26.      }
  27.  
  28.      /* Already set or 2/3 chance of deferring until a later level. */
  29.      if (source->dnum < n_dgns || (rn2(3) && !wizard))
  30.          return;
  31.  
  32.      if (!(u.uz.dnum == oracle_level.dnum      /* in main dungeon */
  33.            && !at_dgn_entrance("The Quest")    /* but not Quest's entry */
  34.            && (u_depth = depth(&u.uz)) > 10    /* beneath 10 */
  35.            && u_depth < depth(&medusa_level))) /* and above Medusa */
  36.          return;
  37.  
  38.      /* Adjust source to be current level and re-insert branch. */
  39.      *source = u.uz;
  40.      insert_branch(br, TRUE);
  41.  
  42.      debugpline0("Made knox portal.");
  43.      place_branch(br, x, y);
  44.  }
  45.  
  46.  /*mklev.c*/