-+-+-+-+-+-+-+-+ START OF PART 20 -+-+-+-+-+-+-+-+
X   This software may be copied and distributed for educational, research, an
Vd
X   not for profit purposes provided that this copyright and statement are
X   included in all such copies. */
X
X#include "config.h"
X#include "constant.h"
X#include "types.h"
X#include "externs.h"
X
X#if defined(USG) && !defined(VMS) && !defined(MAC)
X#if !defined(ATARIST_MWC) && !defined(AMIGA)
X#if !defined(__TURBOC__)
X#include <memory.h>
X#else
X#ifndef ATARIST_TC
X#include <mem.h>
X#endif
X#endif
X#endif
X#endif
X
X#if defined(MAC)
X#include <string.h>
X#endif
X
X#ifdef ATARIST_TC
X#include <string.h>
X#endif
X
Xtypedef struct coords `7B
X  int x, y;
X`7D coords;
X
X#if defined(LINT_ARGS)
Xstatic void correct_dir(int *, int * , int, int, int, int);
Xstatic void rand_dir(int *,int *);
Xstatic void blank_cave(void);
Xstatic void fill_cave(int);
Xstatic void place_boundary(void);
Xstatic void place_streamer(int, int);
Xstatic void place_open_door(int, int);
Xstatic void place_broken_door(int, int);
Xstatic void place_closed_door(int, int);
Xstatic void place_locked_door(int, int);
Xstatic void place_stuck_door(int, int);
Xstatic void place_secret_door(int, int);
Xstatic void place_door(int, int);
Xstatic void place_up_stairs(int, int);
Xstatic void place_down_stairs(int, int);
Xstatic void place_stairs(int, int, int);
Xstatic void vault_trap(int, int, int, int, int);
Xstatic void vault_monster(int, int, int);
Xstatic void build_room(int, int);
Xstatic void build_type1(int, int);
Xstatic void build_type2(int, int);
Xstatic void build_type3(int, int);
Xstatic void build_tunnel(int, int, int, int);
Xstatic int next_to(int, int);
Xstatic void try_door(int, int);
Xstatic void new_spot(int16 *, int16 *);
Xstatic void cave_gen(void);
Xstatic void build_store(int, int, int);
Xstatic void tlink(void);
Xstatic void mlink(void);
Xstatic void town_gen(void);
X#endif
X
Xstatic coords doorstk`5B100`5D;
Xstatic int doorindex;
X
X
X/* Always picks a correct direction`09`09*/
Xstatic void correct_dir(rdir, cdir, y1, x1, y2, x2)
Xint *rdir, *cdir;
Xregister int y1, x1, y2, x2;
X`7B
X  if (y1 < y2)
X    *rdir =  1;
X  else if (y1 == y2)
X    *rdir =  0;
X  else
X    *rdir = -1;
X  if (x1 < x2)
X    *cdir =  1;
X  else if (x1 == x2)
X    *cdir =  0;
X  else
X    *cdir = -1;
X  if ((*rdir != 0) && (*cdir != 0))
X    `7B
X      if (randint (2) == 1)
X`09*rdir = 0;
X      else
X`09*cdir = 0;
X    `7D
X`7D
X
X
X/* Chance of wandering direction`09`09`09*/
Xstatic void rand_dir(rdir, cdir)
Xint *rdir, *cdir;
X`7B
X  register int tmp;
X
X  tmp = randint(4);
X  if (tmp < 3)
X    `7B
X      *cdir = 0;
X      *rdir = -3 + (tmp << 1); /* tmp=1 -> *rdir=-1; tmp=2 -> *rdir=1 */
X    `7D
X  else
X    `7B
X      *rdir = 0;
X      *cdir = -7 + (tmp << 1); /* tmp=3 -> *cdir=-1; tmp=4 -> *cdir=1 */
X    `7D
X`7D
X
X
X/* Blanks out entire cave`09`09`09`09-RAK-`09*/
Xstatic void blank_cave()
X`7B
X#ifndef USG
X  bzero ((char *)&cave`5B0`5D`5B0`5D, sizeof (cave));
X#else
X#ifdef MAC
X  /* On the mac, cave is a pointer, so sizeof(cave) = 4! */
X  (void)memset((char *)&cave`5B0`5D`5B0`5D, 0,
X`09       (long) sizeof(cave_type) * MAX_HEIGHT * MAX_WIDTH);
X#else
X  (void)memset((char *)&cave`5B0`5D`5B0`5D, 0, sizeof (cave));
X#endif
X#endif
X`7D
X
X
X/* Fills in empty spots with desired rock`09`09-RAK-`09*/
X/* Note: 9 is a temporary value.`09`09`09`09*/
Xstatic void fill_cave(fval)
Xregister int fval;
X`7B
X  register int i, j;
X  register cave_type *c_ptr;
X
X  /* no need to check the border of the cave */
X
X  for (i = cur_height - 2; i > 0; i--)
X    `7B
X      c_ptr = &cave`5Bi`5D`5B1`5D;
X      for (j = cur_width - 2; j > 0; j--)
X`09`7B
X`09  if ((c_ptr->fval == NULL_WALL) `7C`7C (c_ptr->fval == TMP1_WALL) `7C`7C
X`09      (c_ptr->fval == TMP2_WALL))
X`09    c_ptr->fval = fval;
X`09  c_ptr++;
X`09`7D
X    `7D
X`7D
X
X#ifdef DEBUG
X#include <assert.h>
X#endif
X
X/* Places indestructible rock around edges of dungeon`09-RAK-`09*/
Xstatic void place_boundary()
X`7B
X  register int i;
X  register cave_type *top_ptr, *bottom_ptr;
X  cave_type (*left_ptr)`5BMAX_WIDTH`5D;
X  cave_type (*right_ptr)`5BMAX_WIDTH`5D;
X
X  /* put permanent wall on leftmost row and rightmost row */
X  left_ptr = (cave_type (*)`5BMAX_WIDTH`5D) &cave`5B0`5D`5B0`5D;
X  right_ptr = (cave_type (*)`5BMAX_WIDTH`5D) &cave`5B0`5D`5Bcur_width - 1`5D
V;
X
X  for (i = 0; i < cur_height; i++)
X    `7B
X#ifdef DEBUG
X      assert ((cave_type *)left_ptr == &cave`5Bi`5D`5B0`5D);
X      assert ((cave_type *)right_ptr == &cave`5Bi`5D`5Bcur_width-1`5D);
X#endif
X
X      ((cave_type *)left_ptr)->fval`09= BOUNDARY_WALL;
X      left_ptr++;
X      ((cave_type *)right_ptr)->fval`09= BOUNDARY_WALL;
X      right_ptr++;
X    `7D
X
X  /* put permanent wall on top row and bottom row */
X  top_ptr = &cave`5B0`5D`5B0`5D;
X  bottom_ptr = &cave`5Bcur_height - 1`5D`5B0`5D;
X
X  for (i = 0; i < cur_width; i++)
X    `7B
X#ifdef DEBUG
X      assert (top_ptr == &cave`5B0`5D`5Bi`5D);
X      assert (bottom_ptr == &cave`5Bcur_height - 1`5D`5Bi`5D);
X#endif
X
X      top_ptr->fval`09= BOUNDARY_WALL;
X      top_ptr++;
X      bottom_ptr->fval`09= BOUNDARY_WALL;
X      bottom_ptr++;
X    `7D
X`7D
X
X
X/* Places "streamers" of rock through dungeon`09`09-RAK-`09*/
Xstatic void place_streamer(fval, treas_chance)
Xint fval;
Xint treas_chance;
X`7B
X  register int i, tx, ty;
X  int y, x, t1, t2, dir;
X  register cave_type *c_ptr;
X
X  /* Choose starting point and direction`09`09*/
X  y = (cur_height / 2) + 11 - randint(23);
X  x = (cur_width / 2)  + 16 - randint(33);
X
X  dir = randint(8);`09/* Number 1-4, 6-9`09*/
X  if (dir > 4)
X    dir = dir + 1;
X
X  /* Place streamer into dungeon`09`09`09*/
X  t1 = 2*DUN_STR_RNG + 1;`09/* Constants`09*/
X  t2 =`09 DUN_STR_RNG + 1;
X  do
X    `7B
X      for (i = 0; i < DUN_STR_DEN; i++)
X`09`7B
X`09  ty = y + randint(t1) - t2;
X`09  tx = x + randint(t1) - t2;
X`09  if (in_bounds(ty, tx))
X`09    `7B
X`09      c_ptr = &cave`5Bty`5D`5Btx`5D;
X`09      if (c_ptr->fval == GRANITE_WALL)
X`09`09`7B
X`09`09  c_ptr->fval = fval;
X`09`09  if (randint(treas_chance) == 1)
X`09`09    place_gold(ty, tx);
X`09`09`7D
X`09    `7D
X`09`7D
X    `7D
X  while (mmove(dir, &y, &x));
X`7D
X
X
Xstatic void place_open_door(y, x)
Xint y, x;
X`7B
X  register int cur_pos;
X  register cave_type *cave_ptr;
X
X  cur_pos = popt();
X  cave_ptr = &cave`5By`5D`5Bx`5D;
X  cave_ptr->tptr = cur_pos;
X  invcopy(&t_list`5Bcur_pos`5D, OBJ_OPEN_DOOR);
X  cave_ptr->fval  = CORR_FLOOR;
X`7D
X
X
Xstatic void place_broken_door(y, x)
Xint y, x;
X`7B
X  register int cur_pos;
X  register cave_type *cave_ptr;
X
X  cur_pos = popt();
X  cave_ptr = &cave`5By`5D`5Bx`5D;
X  cave_ptr->tptr = cur_pos;
X  invcopy(&t_list`5Bcur_pos`5D, OBJ_OPEN_DOOR);
X  cave_ptr->fval  = CORR_FLOOR;
X  t_list`5Bcur_pos`5D.p1 = 1;
X`7D
X
X
Xstatic void place_closed_door(y, x)
Xint y, x;
X`7B
X  register int cur_pos;
X  register cave_type *cave_ptr;
X
X  cur_pos = popt();
X  cave_ptr = &cave`5By`5D`5Bx`5D;
X  cave_ptr->tptr = cur_pos;
X  invcopy(&t_list`5Bcur_pos`5D, OBJ_CLOSED_DOOR);
X  cave_ptr->fval  = BLOCKED_FLOOR;
X`7D
X
X
Xstatic void place_locked_door(y, x)
Xint y, x;
X`7B
X  register int cur_pos;
X  register cave_type *cave_ptr;
X
X  cur_pos = popt();
X  cave_ptr = &cave`5By`5D`5Bx`5D;
X  cave_ptr->tptr = cur_pos;
X  invcopy(&t_list`5Bcur_pos`5D, OBJ_CLOSED_DOOR);
X  cave_ptr->fval  = BLOCKED_FLOOR;
X  t_list`5Bcur_pos`5D.p1 = randint(10) + 10;
X`7D
X
X
Xstatic void place_stuck_door(y, x)
Xint y, x;
X`7B
X  register int cur_pos;
X  register cave_type *cave_ptr;
X
X  cur_pos = popt();
X  cave_ptr = &cave`5By`5D`5Bx`5D;
X  cave_ptr->tptr = cur_pos;
X  invcopy(&t_list`5Bcur_pos`5D, OBJ_CLOSED_DOOR);
X  cave_ptr->fval  = BLOCKED_FLOOR;
X  t_list`5Bcur_pos`5D.p1 = -randint(10) - 10;
X`7D
X
X
Xstatic void place_secret_door(y, x)
Xint y, x;
X`7B
X  register int cur_pos;
X  register cave_type *cave_ptr;
X
X  cur_pos = popt();
X  cave_ptr = &cave`5By`5D`5Bx`5D;
X  cave_ptr->tptr = cur_pos;
X  invcopy(&t_list`5Bcur_pos`5D, OBJ_SECRET_DOOR);
X  cave_ptr->fval  = BLOCKED_FLOOR;
X`7D
X
X
Xstatic void place_door(y, x)
Xint y, x;
X`7B
X  register int tmp;
X
X  tmp = randint(3);
X  if (tmp == 1)
X    `7B
X      if (randint(4) == 1)
X`09place_broken_door(y, x);
X      else
X`09place_open_door(y, x);
X    `7D
X  else if (tmp == 2)
X    `7B
X      tmp = randint(12);
X      if (tmp > 3)
X`09place_closed_door(y, x);
X      else if (tmp == 3)
X`09place_stuck_door(y, x);
X      else
X`09place_locked_door(y, x);
X    `7D
X  else
X    place_secret_door(y, x);
X`7D
X
X
X/* Place an up staircase at given y, x`09`09`09-RAK-`09*/
Xstatic void place_up_stairs(y, x)
Xint y, x;
X`7B
X  register int cur_pos;
X  register cave_type *cave_ptr;
X
X  cave_ptr = &cave`5By`5D`5Bx`5D;
X  if (cave_ptr->tptr != 0)
X    (void) delete_object(y, x);
X  cur_pos = popt();
X  cave_ptr->tptr = cur_pos;
X  invcopy(&t_list`5Bcur_pos`5D, OBJ_UP_STAIR);
X`7D
X
X
X/* Place a down staircase at given y, x`09`09`09-RAK-`09*/
Xstatic void place_down_stairs(y, x)
Xint y, x;
X`7B
X  register int cur_pos;
X  register cave_type *cave_ptr;
X
X  cave_ptr = &cave`5By`5D`5Bx`5D;
X  if (cave_ptr->tptr != 0)
X    (void) delete_object(y, x);
X  cur_pos = popt();
X  cave_ptr->tptr = cur_pos;
X  invcopy(&t_list`5Bcur_pos`5D, OBJ_DOWN_STAIR);
X`7D
X
X
X/* Places a staircase 1=up, 2=down`09`09`09-RAK-`09*/
Xstatic void place_stairs(typ, num, walls)
Xint typ, num, walls;
X`7B
X  register cave_type *cave_ptr;
X  int i, j, flag;
X  register int y1, x1, y2, x2;
X
X  for (i = 0; i < num; i++)
X    `7B
X      flag = FALSE;
X      do
X`09`7B
X`09  j = 0;
X`09  do
X`09    `7B
X`09      /* Note: don't let y1/x1 be zero, and don't let y2/x2 be equal
X`09`09 to cur_height-1/cur_width-1, these values are always
X`09`09 BOUNDARY_ROCK. */
X`09      y1 = randint(cur_height - 14);
X`09      x1 = randint(cur_width  - 14);
X`09      y2 = y1 + 12;
X`09      x2 = x1 + 12;
X`09      do
X`09`09`7B
X`09`09  do
X`09`09    `7B
X`09`09      cave_ptr = &cave`5By1`5D`5Bx1`5D;
X`09`09      if (cave_ptr->fval <= MAX_OPEN_SPACE
X`09`09`09  && (cave_ptr->tptr == 0)
X`09`09`09  && (next_to_walls(y1, x1) >= walls))
X`09`09`09`7B
X`09`09`09  flag = TRUE;
X`09`09`09  if (typ == 1)
X`09`09`09    place_up_stairs(y1, x1);
X`09`09`09  else
X`09`09`09    place_down_stairs(y1, x1);
X`09`09`09`7D
X`09`09      x1++;
X`09`09    `7D
X`09`09  while ((x1 != x2) && (!flag));
X`09`09  x1 = x2 - 12;
X`09`09  y1++;
X`09`09`7D
X`09      while ((y1 != y2) && (!flag));
X`09      j++;
X`09    `7D
X`09  while ((!flag) && (j <= 30));
X`09  walls--;
X`09`7D
X      while (!flag);
X    `7D
X`7D
X
X
X/* Place a trap with a given displacement of point`09-RAK-`09*/
Xstatic void vault_trap(y, x, yd, xd, num)
Xint y, x, yd, xd, num;
X`7B
X  register int count, y1, x1;
X  int i, flag;
X  register cave_type *c_ptr;
X
X  for (i = 0; i < num; i++)
X    `7B
X      flag = FALSE;
X      count = 0;
X      do
X`09`7B
X`09  y1 = y - yd - 1 + randint(2*yd+1);
X`09  x1 = x - xd - 1 + randint(2*xd+1);
X`09  c_ptr = &cave`5By1`5D`5Bx1`5D;
X`09  if ((c_ptr->fval != NULL_WALL) && (c_ptr->fval <= MAX_CAVE_FLOOR)
X`09      && (c_ptr->tptr == 0))
X`09    `7B
X`09      place_trap(y1, x1, randint(MAX_TRAP)-1);
X`09      flag = TRUE;
X`09    `7D
X`09  count++;
X`09`7D
X      while ((!flag) && (count <= 5));
X    `7D
X`7D
X
X
X/* Place a trap with a given displacement of point`09-RAK-`09*/
Xstatic void vault_monster(y, x, num)
Xint y, x, num;
X`7B
X  register int i;
X  int y1, x1;
X
X  for (i = 0; i < num; i++)
X    `7B
X      y1 = y;
X      x1 = x;
X      (void) summon_monster(&y1, &x1, TRUE);
X    `7D
X`7D
X
X
X/* Builds a room at a row, column coordinate`09`09-RAK-`09*/
Xstatic void build_room(yval, xval)
Xint yval, xval;
X`7B
X  register int i, j, y_depth, x_right;
X  int y_height, x_left;
X  int8u floor;
X  register cave_type *c_ptr, *d_ptr;
X
X  if (dun_level <= randint(25))
X    floor = LIGHT_FLOOR;`09/* Floor with light`09*/
X  else
X    floor = DARK_FLOOR;`09`09/* Dark floor`09`09*/
X
X  y_height = yval - randint(4);
X  y_depth  = yval + randint(3);
X  x_left   = xval - randint(11);
X  x_right  = xval + randint(11);
X
X  /* the x dim of rooms tends to be much larger than the y dim, so don't
X     bother rewriting the y loop */
X
X  for (i = y_height; i <= y_depth; i++)
X    `7B
X      c_ptr = &cave`5Bi`5D`5Bx_left`5D;
X      for (j = x_left; j <= x_right; j++)
X`09`7B
X`09  c_ptr->fval  = floor;
X`09  c_ptr->lr = TRUE;
X`09  c_ptr++;
X`09`7D
X    `7D
X
X  for (i = (y_height - 1); i <= (y_depth + 1); i++)
X    `7B
X      c_ptr = &cave`5Bi`5D`5Bx_left-1`5D;
X      c_ptr->fval   = GRANITE_WALL;
X      c_ptr->lr = TRUE;
X      c_ptr = &cave`5Bi`5D`5Bx_right+1`5D;
X      c_ptr->fval  = GRANITE_WALL;
X      c_ptr->lr = TRUE;
X    `7D
X
X  c_ptr = &cave`5By_height - 1`5D`5Bx_left`5D;
X  d_ptr = &cave`5By_depth + 1`5D`5Bx_left`5D;
X  for (i = x_left; i <= x_right; i++)
X    `7B
X      c_ptr->fval  = GRANITE_WALL;
X      c_ptr->lr = TRUE;
X      c_ptr++;
X      d_ptr->fval   = GRANITE_WALL;
X      d_ptr->lr = TRUE;
X      d_ptr++;
X    `7D
X`7D
X
X
X/* Builds a room at a row, column coordinate`09`09-RAK-`09*/
X/* Type 1 unusual rooms are several overlapping rectangular ones`09*/
Xstatic void build_type1(yval, xval)
Xint yval, xval;
X`7B
X  int y_height, y_depth;
X  int x_left, x_right, limit;
X  register int i0, i, j;
X  int8u floor;
X  register cave_type *c_ptr, *d_ptr;
X
X  if (dun_level <= randint(25))
X    floor = LIGHT_FLOOR;`09/* Floor with light`09*/
X  else
X    floor = DARK_FLOOR;`09`09/* Dark floor`09`09*/
X  limit = 1 + randint(2);
X  for (i0 = 0; i0 < limit; i0++)
X    `7B
X      y_height = yval - randint(4);
X      y_depth  = yval + randint(3);
X      x_left   = xval - randint(11);
X      x_right  = xval + randint(11);
X
X      /* the x dim of rooms tends to be much larger than the y dim, so don't
X`09 bother rewriting the y loop */
X
X      for (i = y_height; i <= y_depth; i++)
X`09`7B
X`09  c_ptr = &cave`5Bi`5D`5Bx_left`5D;
+-+-+-+-+-+-+-+-  END  OF PART 20 +-+-+-+-+-+-+-+-
