summaryrefslogtreecommitdiff
path: root/src/generate.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/generate.c')
-rw-r--r--src/generate.c8890
1 files changed, 0 insertions, 8890 deletions
diff --git a/src/generate.c b/src/generate.c
deleted file mode 100644
index 6d83c321..00000000
--- a/src/generate.c
+++ /dev/null
@@ -1,8890 +0,0 @@
-/* File: generate.c */
-
-/* Purpose: Dungeon generation */
-
-/*
- * Copyright (c) 1989 James E. Wilson, Robert A. Koeneke
- *
- * This software may be copied and distributed for educational, research, and
- * not for profit purposes provided that this copyright and statement are
- * included in all such copies.
- */
-
-#include "angband.h"
-#define SAFE_MAX_ATTEMPTS 5000
-
-/*
- * Note that Level generation is *not* an important bottleneck,
- * though it can be annoyingly slow on older machines... Thus
- * we emphasize "simplicity" and "correctness" over "speed".
- *
- * This entire file is only needed for generating levels.
- * This may allow smart compilers to only load it when needed.
- *
- * Consider the "v_info.txt" file for vault generation.
- *
- * In this file, we use the "special" granite and perma-wall sub-types,
- * where "basic" is normal, "inner" is inside a room, "outer" is the
- * outer wall of a room, and "solid" is the outer wall of the dungeon
- * or any walls that may not be pierced by corridors. Thus the only
- * wall type that may be pierced by a corridor is the "outer granite"
- * type. The "basic granite" type yields the "actual" corridors.
- *
- * Note that we use the special "solid" granite wall type to prevent
- * multiple corridors from piercing a wall in two adjacent locations,
- * which would be messy, and we use the special "outer" granite wall
- * to indicate which walls "surround" rooms, and may thus be "pierced"
- * by corridors entering or leaving the room.
- *
- * Note that a tunnel which attempts to leave a room near the "edge"
- * of the dungeon in a direction toward that edge will cause "silly"
- * wall piercings, but will have no permanently incorrect effects,
- * as long as the tunnel can *eventually* exit from another side.
- * And note that the wall may not come back into the room by the
- * hole it left through, so it must bend to the left or right and
- * then optionally re-enter the room (at least 2 grids away). This
- * is not a problem since every room that is large enough to block
- * the passage of tunnels is also large enough to allow the tunnel
- * to pierce the room itself several times.
- *
- * Note that no two corridors may enter a room through adjacent grids,
- * they must either share an entryway or else use entryways at least
- * two grids apart. This prevents "large" (or "silly") doorways.
- *
- * To create rooms in the dungeon, we first divide the dungeon up
- * into "blocks" of 11x11 grids each, and require that all rooms
- * occupy a rectangular group of blocks. As long as each room type
- * reserves a sufficient number of blocks, the room building routines
- * will not need to check bounds. Note that most of the normal rooms
- * actually only use 23x11 grids, and so reserve 33x11 grids.
- *
- * Note that the use of 11x11 blocks (instead of the old 33x11 blocks)
- * allows more variability in the horizontal placement of rooms, and
- * at the same time has the disadvantage that some rooms (two thirds
- * of the normal rooms) may be "split" by panel boundaries. This can
- * induce a situation where a player is in a room and part of the room
- * is off the screen. It may be annoying enough to go back to 33x11
- * blocks to prevent this visual situation.
- *
- * Note that the dungeon generation routines are much different (2.7.5)
- * and perhaps "DUN_ROOMS" should be less than 50.
- *
- * XXX XXX XXX Note that it is possible to create a room which is only
- * connected to itself, because the "tunnel generation" code allows a
- * tunnel to leave a room, wander around, and then re-enter the room.
- *
- * XXX XXX XXX Note that it is possible to create a set of rooms which
- * are only connected to other rooms in that set, since there is nothing
- * explicit in the code to prevent this from happening. But this is less
- * likely than the "isolated room" problem, because each room attempts to
- * connect to another room, in a giant cycle, thus requiring at least two
- * bizarre occurances to create an isolated section of the dungeon.
- *
- * Note that (2.7.9) monster pits have been split into monster "nests"
- * and monster "pits". The "nests" have a collection of monsters of a
- * given type strewn randomly around the room (jelly, animal, or undead),
- * while the "pits" have a collection of monsters of a given type placed
- * around the room in an organized manner (orc, troll, giant, dragon, or
- * demon). Note that both "nests" and "pits" are now "level dependant",
- * and both make 16 "expensive" calls to the "get_mon_num()" function.
- *
- * Note that the cave grid flags changed in a rather drastic manner
- * for Angband 2.8.0 (and 2.7.9+), in particular, dungeon terrain
- * features, such as doors and stairs and traps and rubble and walls,
- * are all handled as a set of 64 possible "terrain features", and
- * not as "fake" objects (440-479) as in pre-2.8.0 versions.
- *
- * The 64 new "dungeon features" will also be used for "visual display"
- * but we must be careful not to allow, for example, the user to display
- * hidden traps in a different way from floors, or secret doors in a way
- * different from granite walls, or even permanent granite in a different
- * way from granite. XXX XXX XXX
- */
-
-
-/*
- * Dungeon generation values
- */
-#define DUN_ROOMS 50 /* Number of rooms to attempt */
-#define DUN_UNUSUAL 194 /* Level/chance of unusual room (was 200) */
-#define DUN_DEST 18 /* 1/chance of having a destroyed level */
-#define SMALL_LEVEL 6 /* 1/chance of smaller size (3->6) */
-#define EMPTY_LEVEL 15 /* 1/chance of being 'empty' (15)*/
-#define DARK_EMPTY 5 /* 1/chance of arena level NOT being lit (2)*/
-#define XTRA_MAGIC 10 /* 1/chance of having a level with more magic (10)*/
-#define DUN_WILD_VAULT 50 /* Chance of finding a wilderness vault. */
-#define DUN_WAT_RNG 2 /* Width of rivers */
-#define DUN_WAT_CHG 50 /* 1 in 50 chance of junction in river */
-#define DUN_CAVERN 30 /* 1/chance of having a cavern level */
-
-/*
- * Dungeon tunnel generation values
- */
-#define DUN_TUN_RND 10 /* Chance of random direction */
-#define DUN_TUN_CHG 30 /* Chance of changing direction */
-#define DUN_TUN_CON 15 /* Chance of extra tunneling */
-#define DUN_TUN_PEN 25 /* Chance of doors at room entrances */
-#define DUN_TUN_JCT 90 /* Chance of doors at tunnel junctions */
-
-/*
- * Dungeon streamer generation values
- */
-#define DUN_STR_DEN 5 /* Density of streamers */
-#define DUN_STR_RNG 2 /* Width of streamers */
-#define DUN_STR_MAG 3 /* Number of magma streamers */
-#define DUN_STR_MC 90 /* 1/chance of treasure per magma */
-#define DUN_STR_QUA 2 /* Number of quartz streamers */
-#define DUN_STR_QC 40 /* 1/chance of treasure per quartz */
-#define DUN_STR_SAN 1 /* Number of sand streamers */
-#define DUN_STR_SC 10 /* 1/chance of treasure per sandwall */
-#define DUN_STR_WLW 1 /* Width of lava & water streamers -KMW- */
-#define DUN_STR_DWLW 8 /* Density of water & lava streams -KMW- */
-
-
-/*
- * Dungeon treausre allocation values
- */
-#define DUN_AMT_ROOM 9 /* Amount of objects for rooms */
-#define DUN_AMT_ITEM 3 /* Amount of objects for rooms/corridors */
-#define DUN_AMT_GOLD 3 /* Amount of treasure for rooms/corridors */
-#define DUN_AMT_ALTAR 1 /* Amount of altars */
-#define DUN_AMT_BETWEEN 2 /* Amount of between gates */
-#define DUN_AMT_FOUNTAIN 1 /* Amount of fountains */
-
-/*
- * Hack -- Dungeon allocation "places"
- */
-#define ALLOC_SET_CORR 1 /* Hallway */
-#define ALLOC_SET_ROOM 2 /* Room */
-#define ALLOC_SET_BOTH 3 /* Anywhere */
-
-/*
- * Hack -- Dungeon allocation "types"
- */
-#define ALLOC_TYP_RUBBLE 1 /* Rubble */
-#define ALLOC_TYP_TRAP 3 /* Trap */
-#define ALLOC_TYP_GOLD 4 /* Gold */
-#define ALLOC_TYP_OBJECT 5 /* Object */
-#define ALLOC_TYP_ALTAR 6 /* Altar */
-#define ALLOC_TYP_BETWEEN 7 /* Between */
-#define ALLOC_TYP_FOUNTAIN 8 /* Fountain */
-
-
-/*
- * The "size" of a "generation block" in grids
- */
-#define BLOCK_HGT 11
-#define BLOCK_WID 11
-
-/*
- * Maximum numbers of rooms along each axis (currently 6x6)
- */
-#define MAX_ROOMS_ROW (MAX_HGT / BLOCK_HGT)
-#define MAX_ROOMS_COL (MAX_WID / BLOCK_WID)
-
-
-/*
- * Bounds on some arrays used in the "dun_data" structure.
- * These bounds are checked, though usually this is a formality.
- */
-#define CENT_MAX 100
-#define DOOR_MAX 200
-#define WALL_MAX 500
-#define TUNN_MAX 900
-
-
-/*
- * Maximal number of room types
- */
-#define ROOM_MAX 12
-
-
-
-/*
- * Simple structure to hold a map location
- */
-
-
-typedef struct coord coord;
-
-struct coord
-{
- byte y;
- byte x;
-};
-
-
-/*
- * Room type information
- */
-
-typedef struct room_data room_data;
-
-struct room_data
-{
- /* Required size in blocks */
- s16b dy1, dy2, dx1, dx2;
-
- /* Hack -- minimum level */
- s16b level;
-};
-
-
-/*
- * Structure to hold all "dungeon generation" data
- */
-
-typedef struct dun_data dun_data;
-
-struct dun_data
-{
- /* Array of centers of rooms */
- int cent_n;
- coord cent[CENT_MAX];
-
- /* Array of possible door locations */
- int door_n;
- coord door[DOOR_MAX];
-
- /* Array of wall piercing locations */
- int wall_n;
- coord wall[WALL_MAX];
-
- /* Array of tunnel grids */
- int tunn_n;
- coord tunn[TUNN_MAX];
-
- /* Number of blocks along each axis */
- int row_rooms;
- int col_rooms;
-
- /* Array of which blocks are used */
- bool_ room_map[MAX_ROOMS_ROW][MAX_ROOMS_COL];
-
- /* Hack -- there is a pit/nest on this level */
- bool_ crowded;
-};
-
-/*
- * Level generator type
- */
-
-typedef struct level_generator_type level_generator_type;
-struct level_generator_type
-{
- cptr name;
- bool_ (*generator)(cptr);
-
- bool_ default_stairs;
- bool_ default_monsters;
- bool_ default_objects;
- bool_ default_miscs;
-
- struct level_generator_type *next;
-};
-
-static level_generator_type *level_generators = NULL;
-
-/*
- * Add a new generator
- */
-void add_level_generator(cptr name, bool_ (*generator)(), bool_ stairs, bool_ monsters, bool_ objects, bool_ miscs)
-{
- level_generator_type *g;
-
- MAKE(g, level_generator_type);
- g->name = string_make(name);
- g->generator = generator;
-
- g->default_stairs = stairs;
- g->default_monsters = monsters;
- g->default_objects = objects;
- g->default_miscs = miscs;
-
- g->next = level_generators;
- level_generators = g;
-}
-
-
-/*
- * Dungeon generation data -- see "cave_gen()"
- */
-static dun_data *dun;
-
-/*
- * ???
- */
-static int template_race;
-
-
-
-/*
- * Array of room types depths
- */
-static s16b roomdep[] =
-{
- 0, /* 0 = Nothing */
- 1, /* 1 = Simple (33x11) */
- 1, /* 2 = Overlapping (33x11) */
- 3, /* 3 = Crossed (33x11) */
- 3, /* 4 = Large (33x11) */
- 5, /* 5 = Monster nest (33x11) */
- 5, /* 6 = Monster pit (33x11) */
- 5, /* 7 = Lesser vault (33x22) */
- 10, /* 8 = Greater vault (66x44) */
- 1, /* 9 = Circular rooms (22x22) */
- 3, /* 10 = Fractal cave (42x24) */
- 10, /* 11 = Random vault (44x22) */
- 10, /* 12 = Crypts (22x22) */
-};
-
-
-/*
- * Always picks a correct direction
- */
-static void correct_dir(int *rdir, int *cdir, int y1, int x1, int y2, int x2)
-{
- /* Extract vertical and horizontal directions */
- *rdir = (y1 == y2) ? 0 : (y1 < y2) ? 1 : -1;
- *cdir = (x1 == x2) ? 0 : (x1 < x2) ? 1 : -1;
-
- /* Never move diagonally */
- if (*rdir && *cdir)
- {
- if (rand_int(100) < 50)
- {
- *rdir = 0;
- }
- else
- {
- *cdir = 0;
- }
- }
-}
-
-
-/*
- * Pick a random direction
- */
-static void rand_dir(int *rdir, int *cdir)
-{
- /* Pick a random direction */
- int i = rand_int(4);
-
- /* Extract the dy/dx components */
- *rdir = ddy_ddd[i];
- *cdir = ddx_ddd[i];
-}
-
-
-/*
- * Convert existing terrain type to "up stairs"
- */
-static void place_up_stairs(int y, int x)
-{
- cave_type *c_ptr = &cave[y][x];
-
- /* Create up stairs */
- if ((rand_int(3) != 0) || (dungeon_flags2 & DF2_NO_SHAFT))
- {
- cave_set_feat(y, x, FEAT_LESS);
- }
- else
- {
- cave_set_feat(y, x, FEAT_SHAFT_UP);
- }
-
- c_ptr->special = 0;
-}
-
-
-/*
- * Convert existing terrain type to "down stairs" with dungeon changing.
- */
-static void place_magical_stairs(int y, int x, byte next)
-{
- cave_type *c_ptr = &cave[y][x];
-
- /* Create up stairs */
- cave_set_feat(y, x, FEAT_MORE);
- c_ptr->special = next;
-}
-
-
-/*
- * Convert existing terrain type to "down stairs"
- */
-static void place_down_stairs(int y, int x)
-{
- cave_type *c_ptr = &cave[y][x];
-
- /*
- * Create down stairs
- * All thoses tests are necesary because a shaft can jump up to 4 levels
- */
- if ((dun_level + 4 > d_info[dungeon_type].maxdepth) ||
- (rand_int(3) != 0) || (dungeon_flags2 & DF2_NO_SHAFT))
- {
- cave_set_feat(y, x, FEAT_MORE);
- }
- else
- {
- cave_set_feat(y, x, FEAT_SHAFT_DOWN);
- }
-
- c_ptr->special = 0;
-}
-
-
-/*
- * Helper function for place_new_way. Determine if y, x is one of
- * floor features of the current dungeon
- */
-static bool_ is_safe_floor(int y, int x)
-{
- dungeon_info_type *d_ptr = &d_info[dungeon_type];
- byte feat = cave[y][x].feat;
-
- /* One of the legal floor types */
- if (feat == d_ptr->floor1) return (TRUE);
- if (feat == d_ptr->floor2) return (TRUE);
- if (feat == d_ptr->floor3) return (TRUE);
-
- /* Assume non-floor */
- return (FALSE);
-}
-
-
-/*
- * Place a way to next / previoous level on flat places
- */
-void place_new_way(int *y, int *x)
-{
- int xx, yy;
- int x0, x1, x2;
- int y0, y1, y2;
- cave_type *c_ptr;
- bool_ ok;
- int i, way_n;
- byte way_x[MAX_WID], way_y[MAX_WID];
-
-
- /* Find valid location XXX XXX XXX */
- while (TRUE)
- {
- /* A way on vertical edge */
- if (rand_int(cur_hgt + cur_wid) < cur_hgt)
- {
- /* Pick a random grid */
- yy = *y = rand_int(cur_hgt - 2) + 1;
- xx = *x = 1 + (rand_int(2) * (cur_wid - 3));
-
- /* Pick a direction */
- if (xx == 1)
- {
- /* Left */
- x0 = + 1;
- y0 = 0;
-
- /* Sides */
- x1 = 0;
- y1 = -1;
- x2 = 0;
- y2 = + 1;
- }
- else
- {
- /* Right */
- x0 = -1;
- y0 = 0;
-
- /* Sides */
- x1 = 0;
- y1 = -1;
- x2 = 0;
- y2 = + 1;
- }
- }
-
- /* A way on horizontal edge */
- else
- {
- /* Pick a random grid */
- xx = *x = rand_int(cur_wid - 2) + 1;
- yy = *y = 1 + (rand_int(2) * (cur_hgt - 3));
-
- /* Pick a direction */
- if (yy == 1)
- {
- /* Down */
- x0 = 0;
- y0 = + 1;
-
- /* Sides */
- x1 = -1;
- y1 = 0;
- x2 = + 1;
- y2 = 0;
- }
- else
- {
- /* Up */
- x0 = 0;
- y0 = -1;
-
- /* Sides */
- x1 = -1;
- y1 = 0;
- x2 = + 1;
- y2 = 0;
- }
- }
-
-
- /* Look at the starting location */
- c_ptr = &cave[yy][xx];
-
- /* Reject locations inside vaults */
- if (c_ptr->info & (CAVE_ICKY)) continue;
-
- /* Reject permanent features */
- if ((f_info[c_ptr->feat].flags1 & (FF1_PERMANENT)) &&
- (f_info[c_ptr->feat].flags1 & (FF1_FLOOR))) continue;
-
- /* Reject room walls */
- if ((c_ptr->info & (CAVE_ROOM)) &&
- (c_ptr->feat == feat_wall_outer)) continue;
-
- /* Look at a neighbouring edge */
- c_ptr = &cave[yy + y1][xx + x1];
-
- /* Reject two adjacent ways */
- if ((c_ptr->feat == FEAT_WAY_MORE) ||
- (c_ptr->feat == FEAT_WAY_LESS)) continue;
-
- /* Look at the other neighbouring edge */
- c_ptr = &cave[yy + y2][xx + x2];
-
- /* Reject two adjacent ways */
- if ((c_ptr->feat == FEAT_WAY_MORE) ||
- (c_ptr->feat == FEAT_WAY_LESS)) continue;
-
- /* Look ahead */
- c_ptr = &cave[yy + y0][xx + x0];
-
- /* Reject two adjacent ways -- relatively rare, but this can happen */
- if ((c_ptr->feat == FEAT_WAY_MORE) ||
- (c_ptr->feat == FEAT_WAY_LESS)) continue;
-
-
- /* Reset counter */
- way_n = 0;
-
- /* Assume bad location */
- ok = FALSE;
-
- /* Check if it connects to current dungeon */
- while (in_bounds(yy, xx))
- {
-#if 1
-
- /* Check grids ahead */
- if (is_safe_floor(yy + y0, xx + x0)) ok = TRUE;
-
- /* Check side grids */
- if (is_safe_floor(yy + y1, xx + x1)) ok = TRUE;
- if (is_safe_floor(yy + y2, xx + x2)) ok = TRUE;
-
-#else
-
- /*
- * This can create unconnected sections if it bumps into a
- * non-penetrating streamer
- */
- /* Check grids ahead */
- if (cave_floor_bold(yy + y0, xx + x0)) ok = TRUE;
-
- /* Check side grids */
- if (cave_floor_bold(yy + y1, xx + x1)) ok = TRUE;
- if (cave_floor_bold(yy + y2, xx + x2)) ok = TRUE;
-
-#endif
-
- /* Connected */
- if (ok) break;
-
- /* Access grid (ahead) */
- c_ptr = &cave[yy + y0][xx + x0];
-
- /* Avoid opening vaults */
- if (c_ptr->feat == FEAT_PERM_OUTER)
- {
- /* Comment this out if you find any problems... */
- ok = TRUE;
-
- break;
- }
-
- /* Paranoia */
- if (c_ptr->feat == FEAT_PERM_SOLID) break;
-
- /*
- * Hack -- Avoid digging room corner
- *
- * CAVEAT: Can't handle situations like this:
- *
- * .....########
- * .....########
- * ######.....>#
- * #############
- * .....#
- * .....#
- */
- if (c_ptr->info & (CAVE_ROOM))
- {
- cave_type *c1_ptr = &cave[yy + y0 + y1][xx + x0 + x1];
- cave_type *c2_ptr = &cave[yy + y0 + y2][xx + x0 + x2];
-
- /* Bend the way */
- if ((c1_ptr->info & (CAVE_ROOM)) &&
- !(c2_ptr->info & (CAVE_ROOM)))
- {
- way_x[way_n] = xx + x1;
- way_y[way_n] = yy + y1;
- way_n++;
- way_x[way_n] = xx + x1 + x0;
- way_y[way_n] = yy + y1 + y0;
- way_n++;
- }
-
- /* Bend the way -- the other direction */
- else if ((c2_ptr->info & (CAVE_ROOM)) &&
- !(c1_ptr->info & (CAVE_ROOM)))
- {
- way_x[way_n] = xx + x2;
- way_y[way_n] = yy + y2;
- way_n++;
- way_x[way_n] = xx + x2 + x0;
- way_y[way_n] = yy + y2 + y0;
- way_n++;
- }
-
- else
- {
- way_x[way_n] = xx + x0;
- way_y[way_n] = yy + y0;
- way_n++;
- }
-
- ok = TRUE;
- break;
- }
-
- /* Remember the location */
- way_x[way_n] = xx + x0;
- way_y[way_n] = yy + y0;
- way_n++;
-
- /* Advance */
- xx += x0;
- yy += y0;
- }
-
- /* Accept connected corridor */
- if (ok) break;
-
- /* Try again, until valid location is found */
- }
-
-
- /* Actually dig a corridor connecting the way to dungeon */
- for (i = 0; i < way_n; i++)
- {
- /* Dig */
- place_floor(way_y[i], way_x[i]);
- }
-}
-
-
-/*
- * Returns random co-ordinates for player/monster/object
- */
-bool_ new_player_spot(int branch)
-{
- int y, x;
- int max_attempts = 5000;
-
- /* Place the player */
- if (dungeon_flags1 & DF1_FLAT)
- {
- place_new_way(&y, &x);
- }
- else
- {
- while (max_attempts--)
- {
- /* Pick a legal spot */
- y = rand_range(1, cur_hgt - 2);
- x = rand_range(1, cur_wid - 2);
-
- /* Must be a "naked" floor grid */
- if (!cave_naked_bold(y, x)) continue;
-
- /* Refuse to start on anti-teleport grids */
- if (cave[y][x].info & (CAVE_ICKY)) continue;
-
- /* Done */
- break;
-
- }
- }
-
- /* Should be -1, actually if we failed... */
- if (max_attempts < 1) return (FALSE);
-
-
- /* Save the new player grid */
- p_ptr->py = y;
- p_ptr->px = x;
-
- /* XXX XXX XXX */
- if (dungeon_stair && !(dungeon_flags2 & DF2_NO_STAIR) && dun_level &&
- (!is_quest(dun_level) || (old_dun_level < dun_level)) && !branch)
- {
- if (old_dun_level < dun_level)
- {
- place_up_stairs(p_ptr->py , p_ptr->px);
- if (dungeon_flags1 & DF1_FLAT)
- {
- cave_set_feat(p_ptr->py, p_ptr->px, FEAT_WAY_LESS);
- }
- }
- else
- {
- place_down_stairs(p_ptr->py , p_ptr->px);
- if (dungeon_flags1 & DF1_FLAT)
- {
- cave_set_feat(p_ptr->py, p_ptr->px, FEAT_WAY_MORE);
- }
- }
- }
-
- return (TRUE);
-}
-
-
-
-/*
- * Count the number of walls adjacent to the given grid.
- *
- * Note -- Assumes "in_bounds(y, x)"
- *
- * We count only granite walls and permanent walls.
- */
-static int next_to_walls(int y, int x)
-{
- int k = 0;
-
- if (f_info[cave[y + 1][x].feat].flags1 & FF1_WALL) k++;
- if (f_info[cave[y - 1][x].feat].flags1 & FF1_WALL) k++;
- if (f_info[cave[y][x + 1].feat].flags1 & FF1_WALL) k++;
- if (f_info[cave[y][x - 1].feat].flags1 & FF1_WALL) k++;
-
- return (k);
-}
-
-
-
-/*
- * Convert existing terrain type to rubble
- */
-static void place_rubble(int y, int x)
-{
- /* Create rubble */
- cave_set_feat(y, x, FEAT_RUBBLE);
-}
-
-
-/*
- * Place an altar at the given location
- */
-static void place_altar(int y, int x)
-{
- if (magik(10))
- cave_set_feat(y, x, 164);
-}
-
-
-/*
- * Place a fountain at the given location
- */
-static void place_fountain(int y, int x)
-{
- cave_type *c_ptr = &cave[y][x];
- int svals[SV_POTION_LAST + SV_POTION2_LAST + 1], maxsval = 0, k;
-
- /* List of usable svals */
- for (k = 1; k < max_k_idx; k++)
- {
- object_kind *k_ptr = &k_info[k];
-
- if (((k_ptr->tval == TV_POTION) || (k_ptr->tval == TV_POTION2)) &&
- (k_ptr->level <= dun_level) && (k_ptr->flags4 & TR4_FOUNTAIN))
- {
- if (k_ptr->tval == TV_POTION2) svals[maxsval] = k_ptr->sval + SV_POTION_LAST;
- else svals[maxsval] = k_ptr->sval;
- maxsval++;
- }
- }
-
- if (maxsval == 0) return;
-
- /* Place the fountain */
- if (randint(100) < 30)
- {
- cave_set_feat(y, x, FEAT_EMPTY_FOUNTAIN);
- c_ptr->special2 = 0;
- }
- else
- {
- cave_set_feat(y, x, FEAT_FOUNTAIN);
- c_ptr->special2 = damroll(3, 4);
- }
-
- c_ptr->special = svals[rand_int(maxsval)];
-}
-
-
-/*
- * Place a between gate at the given location
- */
-static void place_between(int y, int x)
-{
- cave_type *c_ptr = &cave[y][x], *c1_ptr;
- int gx, gy;
-
- while (TRUE)
- {
- /* Location */
- gy = rand_int(cur_hgt);
- gx = rand_int(cur_wid);
-
- /* Require "naked" floor grid */
- if (cave_naked_bold(gy, gx)) break;
- }
-
- /* Access the target grid */
- c1_ptr = &cave[gy][gx];
-
- /* Place a pair of between gates */
- cave_set_feat(y, x, FEAT_BETWEEN);
- c_ptr->special = gx + (gy << 8);
- cave_set_feat(gy, gx, FEAT_BETWEEN);
- c1_ptr->special = x + (y << 8);
-}
-
-
-/*
- * Place an up/down staircase at given location
- */
-static void place_random_stairs(int y, int x)
-{
- /* Paranoia */
- if (!cave_clean_bold(y, x)) return;
-
- /* Choose a staircase */
- if (!dun_level)
- {
- place_down_stairs(y, x);
- }
- else if (is_quest(dun_level) && (dun_level > 1))
- {
- place_up_stairs(y, x);
- }
- else if (dun_level >= d_info[dungeon_type].maxdepth)
- {
- if (d_info[dungeon_type].next)
- {
- place_magical_stairs(y, x, d_info[dungeon_type].next);
- }
- else
- {
- place_up_stairs(y, x);
- }
- }
- else if (rand_int(100) < 50)
- {
- place_down_stairs(y, x);
- }
- else
- {
- place_up_stairs(y, x);
- }
-}
-
-
-/*
- * Place a locked door at the given location
- */
-static void place_locked_door(int y, int x)
-{
- /* Create locked door */
- cave_set_feat(y, x, FEAT_DOOR_HEAD + randint(7));
-}
-
-
-/*
- * Place a secret door at the given location
- */
-static void place_secret_door(int y, int x)
-{
- cave_type *c_ptr = &cave[y][x];
-
- /* Vaults */
- if (c_ptr->info & CAVE_ICKY)
- {
- c_ptr->mimic = FEAT_WALL_INNER;
- }
-
- /* Ordinary room -- use current outer or inner wall */
- else if (c_ptr->info & CAVE_ROOM)
- {
- /* Determine if it's inner or outer XXX XXX XXX */
- if ((cave[y - 1][x].info & CAVE_ROOM) &&
- (cave[y + 1][x].info & CAVE_ROOM) &&
- (cave[y][x - 1].info & CAVE_ROOM) &&
- (cave[y][x + 1].info & CAVE_ROOM))
- {
- c_ptr->mimic = feat_wall_inner;
- }
- else
- {
- c_ptr->mimic = feat_wall_outer;
- }
- }
- else
- {
- c_ptr->mimic = fill_type[rand_int(100)];
- }
-
- /* Create secret door */
- cave_set_feat(y, x, FEAT_SECRET);
-}
-
-
-/*
- * Place a random type of door at the given location
- */
-static void place_random_door(int y, int x)
-{
- int tmp;
-
- /* Choose an object */
- tmp = rand_int(1000);
-
- /* Open doors (300/1000) */
- if (tmp < 300)
- {
- /* Create open door */
- cave_set_feat(y, x, FEAT_OPEN);
- }
-
- /* Broken doors (100/1000) */
- else if (tmp < 400)
- {
- /* Create broken door */
- cave_set_feat(y, x, FEAT_BROKEN);
- }
-
- /* Secret doors (200/1000) */
- else if (tmp < 600)
- {
- /* Create secret door */
- place_secret_door(y, x);
- }
-
- /* Closed doors (300/1000) */
- else if (tmp < 900)
- {
- /* Create closed door */
- cave_set_feat(y, x, FEAT_DOOR_HEAD + 0x00);
- }
-
- /* Locked doors (99/1000) */
- else if (tmp < 999)
- {
- /* Create locked door */
- cave_set_feat(y, x, FEAT_DOOR_HEAD + randint(7));
- }
-
- /* Stuck doors (1/1000) */
- else
- {
- /* Create jammed door */
- cave_set_feat(y, x, FEAT_DOOR_HEAD + 0x08 + (byte)rand_int(8));
- }
-}
-
-
-
-/*
- * Places some staircases near walls
- */
-static void alloc_stairs(int feat, int num, int walls, int branch)
-{
- int y, x, i, j, cnt;
-
- /* Place "num" stairs */
- for (cnt = 0, i = 0; i < num || (cnt < 1 && num > 1); i++)
- {
- /* Try several times, then decrease "walls" */
- for (j = 0; j <= SAFE_MAX_ATTEMPTS; j++)
- {
- if (dungeon_flags1 & DF1_FLAT)
- {
- place_new_way(&y, &x);
- }
- else
- {
- /* Pick a random grid */
- y = rand_int(cur_hgt);
- x = rand_int(cur_wid);
-
- /* Require "naked" floor grid */
- if (!cave_naked_bold(y, x)) continue;
-
- /* Require a certain number of adjacent walls */
- if (next_to_walls(y, x) < walls) continue;
- }
-
- /* Town -- must go down */
- if (!dun_level)
- {
- /* Clear previous contents, add down stairs */
- if (dungeon_flags1 & DF1_FLAT)
- {
- cave_set_feat(y, x, FEAT_WAY_MORE);
- }
- else if ((rand_int(3) == 0) && (!(dungeon_flags2 & DF2_NO_SHAFT)))
- {
- cave_set_feat(y, x, FEAT_SHAFT_DOWN);
- }
- else
- {
- cave_set_feat(y, x, FEAT_MORE);
- }
- }
-
- /* Quest -- must go up */
- else if ((is_quest(dun_level) && (dun_level >= 1)) ||
- ((dun_level >= d_info[dungeon_type].maxdepth) &&
- (!(dungeon_flags1 & DF1_FORCE_DOWN))))
- {
- /* Clear previous contents, add up stairs */
- if (dungeon_flags1 & DF1_FLAT)
- {
- cave_set_feat(y, x, FEAT_WAY_LESS);
- }
- else if ((rand_int(3) == 0) && (!(dungeon_flags2 & DF2_NO_SHAFT)))
- {
- cave_set_feat(y, x, FEAT_SHAFT_UP);
- }
- else
- {
- cave_set_feat(y, x, FEAT_LESS);
- }
- }
-
- /* Requested type */
- else
- {
- /* Clear previous contents, add stairs */
- cave_set_feat(y, x, feat);
- }
-
- cave[y][x].special = branch;
-
- /* Count the number of stairs we've actually managed to place. */
- cnt++;
-
- /* All done */
- break;
- }
-
- /* Require fewer walls */
- if (walls) walls--;
- }
-}
-
-
-
-
-/*
- * Allocates some objects (using "place" and "type")
- */
-static void alloc_object(int set, int typ, int num)
-{
- int y = 1, x = 1, k;
- int dummy = 0;
-
- /* Place some objects */
- for (k = 0; k < num; k++)
- {
- /* Pick a "legal" spot */
- while (dummy < SAFE_MAX_ATTEMPTS)
- {
- bool_ room;
-
- dummy++;
-
- /* Location */
- y = rand_int(cur_hgt);
- x = rand_int(cur_wid);
-
- /* Require "naked" floor grid */
- if (!cave_naked_bold(y, x)) continue;
-
- /* Check for "room" */
- room = (cave[y][x].info & (CAVE_ROOM)) ? TRUE : FALSE;
-
- /* Require corridor? */
- if ((set == ALLOC_SET_CORR) && room) continue;
-
- /* Require room? */
- if ((set == ALLOC_SET_ROOM) && !room) continue;
-
- /* Accept it */
- break;
- }
-
- if (dummy >= SAFE_MAX_ATTEMPTS)
- {
- if (cheat_room)
- {
- msg_format("Warning! Could not place object, type : %d!", typ);
- }
-
- return;
- }
-
-
- /* Place something */
- switch (typ)
- {
- case ALLOC_TYP_RUBBLE:
- {
- place_rubble(y, x);
- break;
- }
-
- case ALLOC_TYP_TRAP:
- {
- place_trap(y, x);
- break;
- }
-
- case ALLOC_TYP_GOLD:
- {
- place_gold(y, x);
- break;
- }
-
- case ALLOC_TYP_OBJECT:
- {
- place_object(y, x, FALSE, FALSE, OBJ_FOUND_FLOOR);
- break;
- }
-
- case ALLOC_TYP_ALTAR:
- {
- place_altar(y, x);
- break;
- }
-
- case ALLOC_TYP_BETWEEN:
- {
- place_between(y, x);
- break;
- }
-
- case ALLOC_TYP_FOUNTAIN:
- {
- place_fountain(y, x);
- break;
- }
- }
- }
-}
-
-
-/*
- * The following functions create a rectangle (e.g. outer wall of rooms)
- */
-void build_rectangle(int y1, int x1, int y2, int x2, int feat, int info)
-{
- int y, x;
-
- /* Top and bottom boundaries */
- for (x = x1; x <= x2; x++)
- {
- cave_set_feat(y1, x, feat);
- cave[y1][x].info |= (info);
-
- cave_set_feat(y2, x, feat);
- cave[y2][x].info |= (info);
- }
-
- /* Top and bottom boundaries */
- for (y = y1; y <= y2; y++)
- {
- cave_set_feat(y, x1, feat);
- cave[y][x1].info |= (info);
-
- cave_set_feat(y, x2, feat);
- cave[y][x2].info |= (info);
- }
-}
-
-
-/*
- * Place water through the dungeon using recursive fractal algorithm
- *
- * Why do those good at math and/or algorithms tend *not* to
- * place any spaces around binary operators? I've been always
- * wondering. This seems almost a unversal phenomenon...
- * Tried to make those conform to the rule, but there may still
- * some left untouched...
- */
-static void recursive_river(int x1, int y1, int x2, int y2,
- int feat1, int feat2, int width)
-{
- int dx, dy, length, l, x, y;
- int changex, changey;
- int ty, tx;
-
-
- length = distance(x1, y1, x2, y2);
-
- if (length > 4)
- {
- /*
- * Divide path in half and call routine twice.
- * There is a small chance of splitting the river
- */
- dx = (x2 - x1) / 2;
- dy = (y2 - y1) / 2;
-
- if (dy != 0)
- {
- /* perturbation perpendicular to path */
- changex = randint(abs(dy)) * 2 - abs(dy);
- }
- else
- {
- changex = 0;
- }
-
- if (dx != 0)
- {
- /* perturbation perpendicular to path */
- changey = randint(abs(dx)) * 2 - abs(dx);
- }
- else
- {
- changey = 0;
- }
-
-
-
- /* construct river out of two smaller ones */
- recursive_river(x1, y1, x1 + dx + changex, y1 + dy + changey,
- feat1, feat2, width);
- recursive_river(x1 + dx + changex, y1 + dy + changey, x2, y2,
- feat1, feat2, width);
-
- /* Split the river some of the time -junctions look cool */
- if ((width > 0) && (rand_int(DUN_WAT_CHG) == 0))
- {
- recursive_river(x1 + dx + changex, y1 + dy + changey,
- x1 + 8 * (dx + changex), y1 + 8 * (dy + changey),
- feat1, feat2, width - 1);
- }
- }
-
- /* Actually build the river */
- else
- {
- for (l = 0; l < length; l++)
- {
- x = x1 + l * (x2 - x1) / length;
- y = y1 + l * (y2 - y1) / length;
-
- for (ty = y - width - 1; ty <= y + width + 1; ty++)
- {
- for (tx = x - width - 1; tx <= x + width + 1; tx++)
- {
- if (!in_bounds(ty, tx)) continue;
-
- if (cave[ty][tx].feat == feat1) continue;
- if (cave[ty][tx].feat == feat2) continue;
-
- if (distance(ty, tx, y, x) > rand_spread(width, 1)) continue;
-
- /* Do not convert permanent features */
- if (cave_perma_bold(ty, tx)) continue;
-
- /*
- * Clear previous contents, add feature
- * The border mainly gets feat2, while the center
- * gets feat1
- */
- if (distance(ty, tx, y, x) > width)
- {
- cave_set_feat(ty, tx, feat2);
- }
- else
- {
- cave_set_feat(ty, tx, feat1);
- }
-
- /* Lava terrain glows */
- if ((feat1 == FEAT_DEEP_LAVA) ||
- (feat1 == FEAT_SHAL_LAVA))
- {
- cave[ty][tx].info |= CAVE_GLOW;
- }
-
- /* Hack -- don't teleport here */
- cave[ty][tx].info |= CAVE_ICKY;
- }
- }
- }
- }
-}
-
-
-/*
- * Places water through dungeon.
- */
-static void add_river(int feat1, int feat2)
-{
- int y2, x2;
- int y1 = 0, x1 = 0, wid;
-
-
- /* Hack -- Choose starting point */
- y2 = randint(cur_hgt / 2 - 2) + cur_hgt / 2;
- x2 = randint(cur_wid / 2 - 2) + cur_wid / 2;
-
- /* Hack -- Choose ending point somewhere on boundary */
- switch (randint(4))
- {
- case 1:
- {
- /* top boundary */
- x1 = randint(cur_wid - 2) + 1;
- y1 = 1;
- break;
- }
- case 2:
- {
- /* left boundary */
- x1 = 1;
- y1 = randint(cur_hgt - 2) + 1;
- break;
- }
- case 3:
- {
- /* right boundary */
- x1 = cur_wid - 1;
- y1 = randint(cur_hgt - 2) + 1;
- break;
- }
- case 4:
- {
- /* bottom boundary */
- x1 = randint(cur_wid - 2) + 1;
- y1 = cur_hgt - 1;
- break;
- }
- }
- wid = randint(DUN_WAT_RNG);
- recursive_river(x1, y1, x2, y2, feat1, feat2, wid);
-}
-
-
-/*
- * Places "streamers" of rock through dungeon
- *
- * Note that their are actually six different terrain features used
- * to represent streamers. Three each of magma and quartz, one for
- * basic vein, one with hidden gold, and one with known gold. The
- * hidden gold types are currently unused.
- */
-static void build_streamer(int feat, int chance)
-{
- int i, tx, ty;
- int y, x, dir;
- int dummy = 0;
- cave_type *c_ptr;
-
-
- /* Hack -- Choose starting point */
- y = rand_spread(cur_hgt / 2, 10);
- x = rand_spread(cur_wid / 2, 15);
-
- /* Choose a random compass direction */
- dir = ddd[rand_int(8)];
-
- /* Place streamer into dungeon */
- while (dummy < SAFE_MAX_ATTEMPTS)
- {
- dummy++;
-
- /* One grid per density */
- for (i = 0; i < DUN_STR_DEN; i++)
- {
- int d = DUN_STR_RNG;
-
- /* Pick a nearby grid */
- while (1)
- {
- ty = rand_spread(y, d);
- tx = rand_spread(x, d);
- if (!in_bounds2(ty, tx)) continue;
- break;
- }
-
- /* Access the grid */
- c_ptr = &cave[ty][tx];
-
- /* Only convert "granite" walls */
- if ((c_ptr->feat != feat_wall_inner) &&
- (c_ptr->feat != feat_wall_outer) &&
- (c_ptr->feat != d_info[dungeon_type].fill_type1) &&
- (c_ptr->feat != d_info[dungeon_type].fill_type2) &&
- (c_ptr->feat != d_info[dungeon_type].fill_type3)) continue;
-
- /* Clear mimic feature to avoid nasty consequences */
- c_ptr->mimic = 0;
-
- /* Clear previous contents, add proper vein type */
- cave_set_feat(ty, tx, feat);
-
- /* Hack -- Add some (known) treasure */
- if (rand_int(chance) == 0)
- {
- cave_set_feat(ty, tx, c_ptr->feat + 0x04);
- }
- }
-
- if (dummy >= SAFE_MAX_ATTEMPTS)
- {
- if (cheat_room)
- {
- msg_print("Warning! Could not place streamer!");
- }
- return;
- }
-
-
- /* Advance the streamer */
- y += ddy[dir];
- x += ddx[dir];
-
- /* Quit before leaving the dungeon */
- if (!in_bounds(y, x)) break;
- }
-}
-
-
-
-/*
- * Place streams of water, lava, & trees -KMW-
- * This routine varies the placement based on dungeon level
- * otherwise is similar to build_streamer
- */
-static void build_streamer2(int feat, int killwall)
-{
- int i, j, mid, tx, ty;
- int y, x, dir;
- int poolchance;
- int poolsize;
- cave_type *c_ptr;
-
- poolchance = randint(10);
-
- /* Hack -- Choose starting point */
- y = rand_spread(cur_hgt / 2, 10);
- x = rand_spread(cur_wid / 2, 15);
-
- /* Choose a random compass direction */
- dir = ddd[rand_int(8)];
-
- /* Place streamer into dungeon */
- if (poolchance > 2)
- {
- while (TRUE)
- {
- /* One grid per density */
- for (i = 0; i < (DUN_STR_DWLW + 1); i++)
- {
- int d = DUN_STR_WLW;
-
- /* Pick a nearby grid */
- while (1)
- {
- ty = rand_spread(y, d);
- tx = rand_spread(x, d);
- if (in_bounds(ty, tx)) break;
- }
-
- /* Access grid */
- c_ptr = &cave[ty][tx];
-
- /* Never convert vaults */
- if (c_ptr->info & (CAVE_ICKY)) continue;
-
- /* Reject permanent features */
- if ((f_info[c_ptr->feat].flags1 & (FF1_PERMANENT)) &&
- (f_info[c_ptr->feat].flags1 & (FF1_FLOOR))) continue;
-
- /* Avoid converting walls when told so */
- if (killwall == 0)
- {
- if (f_info[c_ptr->feat].flags1 & FF1_WALL) continue;
- }
-
- /* Clear mimic feature to avoid nasty consequences */
- c_ptr->mimic = 0;
-
- /* Clear previous contents, add proper vein type */
- cave_set_feat(ty, tx, feat);
- }
-
- /* Advance the streamer */
- y += ddy[dir];
- x += ddx[dir];
-
- /* Change direction */
- if (rand_int(20) == 0) dir = ddd[rand_int(8)];
-
- /* Stop at dungeon edge */
- if (!in_bounds(y, x)) break;
- }
- }
-
- /* Create pool */
- else if ((feat == FEAT_DEEP_WATER) || (feat == FEAT_DEEP_LAVA))
- {
- poolsize = 5 + randint(10);
- mid = poolsize / 2;
-
- /* One grid per density */
- for (i = 0; i < poolsize; i++)
- {
- for (j = 0; j < poolsize; j++)
- {
- tx = x + j;
- ty = y + i;
-
- if (!in_bounds(ty, tx)) continue;
-
- if (i < mid)
- {
- if (j < mid)
- {
- if ((i + j + 1) < mid)
- continue;
- }
- else if (j > (mid + i))
- continue;
- }
- else if (j < mid)
- {
- if (i > (mid + j))
- continue;
- }
- else if ((i + j) > ((mid * 3)-1))
- continue;
-
- /* Only convert non-permanent features */
- if (f_info[cave[ty][tx].feat].flags1 & FF1_PERMANENT) continue;
-
- /* Clear mimic feature to avoid nasty consequences */
- cave[ty][tx].mimic = 0;
-
- /* Clear previous contents, add proper vein type */
- cave_set_feat(ty, tx, feat);
- }
- }
- }
-}
-
-
-
-/*
- * Build a destroyed level
- */
-static void destroy_level(void)
-{
- int y1, x1, y, x, k, t, n;
-
- cave_type *c_ptr;
-
- /* Note destroyed levels */
- if ((cheat_room) || (p_ptr->precognition)) msg_print("Destroyed Level");
-
- /* Drop a few epi-centers (usually about two) */
- for (n = 0; n < randint(5); n++)
- {
- /* Pick an epi-center */
- x1 = rand_range(5, cur_wid - 1 - 5);
- y1 = rand_range(5, cur_hgt - 1 - 5);
-
- /* Big area of affect */
- for (y = (y1 - 15); y <= (y1 + 15); y++)
- {
- for (x = (x1 - 15); x <= (x1 + 15); x++)
- {
- /* Skip illegal grids */
- if (!in_bounds(y, x)) continue;
-
- /* Extract the distance */
- k = distance(y1, x1, y, x);
-
- /* Stay in the circle of death */
- if (k >= 16) continue;
-
- /* Delete the monster (if any) */
- delete_monster(y, x);
-
- /* Destroy valid grids */
- if (cave_valid_bold(y, x))
- {
- /* Delete objects */
- delete_object(y, x);
-
- /* Access the grid */
- c_ptr = &cave[y][x];
-
- /* Wall (or floor) type */
- t = rand_int(200);
-
- /* Granite */
- if (t < 20)
- {
- /* Create granite wall */
- cave_set_feat(y, x, FEAT_WALL_EXTRA);
- }
-
- /* Quartz */
- else if (t < 60)
- {
- /* Create quartz vein */
- cave_set_feat(y, x, FEAT_QUARTZ);
- }
-
- /* Magma */
- else if (t < 90)
- {
- /* Create magma vein */
- cave_set_feat(y, x, FEAT_MAGMA);
- }
-
- /* Sand */
- else if (t < 110)
- {
- /* Create sand vein */
- cave_set_feat(y, x, FEAT_SANDWALL);
- }
-
- /* Floor */
- else
- {
- /* Create floor */
- place_floor(y, x);
- }
-
- /* No longer part of a room or vault */
- c_ptr->info &= ~(CAVE_ROOM | CAVE_ICKY);
-
- /* No longer illuminated or known */
- c_ptr->info &= ~(CAVE_MARK | CAVE_GLOW);
- }
- }
- }
- }
-}
-
-
-/*
- * Function that sees if a square is a floor (Includes range checking)
- */
-static bool_ get_is_floor(int x, int y)
-{
- /* Out of bounds */
- if (!in_bounds(y, x)) return (FALSE);
-
- /* Do the real check: */
- if (f_info[cave[y][x].feat].flags1 & FF1_FLOOR) return (TRUE);
-
- return (FALSE);
-}
-
-
-/*
- * Tunnel around a room if it will cut off part of a cave system
- */
-static void check_room_boundary(int x1, int y1, int x2, int y2)
-{
- int count, x, y;
- bool_ old_is_floor, new_is_floor;
-
- /* Avoid doing this in irrelevant places -- pelpel */
- if (!(dungeon_flags1 & DF1_CAVERN)) return;
-
- /* Initialize */
- count = 0;
-
- old_is_floor = get_is_floor(x1 - 1, y1);
-
- /*
- * Count the number of floor-wall boundaries around the room
- * Note: diagonal squares are ignored since the player can move diagonally
- * to bypass these if needed.
- */
-
- /* Above the top boundary */
- for (x = x1; x <= x2; x++)
- {
- new_is_floor = get_is_floor(x, y1 - 1);
-
- /* increment counter if they are different */
- if (new_is_floor != old_is_floor) count++;
-
- old_is_floor = new_is_floor;
- }
-
- /* Right boundary */
- for (y = y1; y <= y2; y++)
- {
- new_is_floor = get_is_floor(x2 + 1, y);
-
- /* increment counter if they are different */
- if (new_is_floor != old_is_floor) count++;
-
- old_is_floor = new_is_floor;
- }
-
- /* Bottom boundary*/
- for (x = x2; x >= x1; x--)
- {
- new_is_floor = get_is_floor(x, y2 + 1);
-
- /* Increment counter if they are different */
- if (new_is_floor != old_is_floor) count++;
-
- old_is_floor = new_is_floor;
- }
-
- /* Left boundary */
- for (y = y2; y >= y1; y--)
- {
- new_is_floor = get_is_floor(x1 - 1, y);
-
- /* Increment counter if they are different */
- if (new_is_floor != old_is_floor) count++;
-
- old_is_floor = new_is_floor;
- }
-
-
- /* If all the same, or only one connection exit */
- if ((count == 0) || (count == 2)) return;
-
-
- /* Tunnel around the room so to prevent problems with caves */
- for (y = y1; y <= y2; y++)
- {
- for (x = x1; x <= x2; x++)
- {
- if (in_bounds(y, x)) place_floor(y, x);
- }
- }
-}
-
-
-/*
- * Create up to "num" objects near the given coordinates
- * Only really called by some of the "vault" routines.
- */
-static void vault_objects(int y, int x, int num)
-{
- int dummy = 0;
- int i = 0, j = y, k = x;
-
-
- /* Attempt to place 'num' objects */
- for (; num > 0; --num)
- {
- /* Try up to 11 spots looking for empty space */
- for (i = 0; i < 11; ++i)
- {
- /* Pick a random location */
- while (dummy < SAFE_MAX_ATTEMPTS)
- {
- j = rand_spread(y, 2);
- k = rand_spread(x, 3);
- dummy++;
- if (in_bounds(j, k)) break;
- }
-
-
- if (dummy >= SAFE_MAX_ATTEMPTS)
- {
- if (cheat_room)
- {
- msg_print("Warning! Could not place vault object!");
- }
- }
-
-
- /* Require "clean" floor space */
- if (!cave_clean_bold(j, k)) continue;
-
- /* Place an item */
- if (rand_int(100) < 75)
- {
- place_object(j, k, FALSE, FALSE, OBJ_FOUND_FLOOR);
- }
-
- /* Place gold */
- else
- {
- place_gold(j, k);
- }
-
- /* Placement accomplished */
- break;
- }
- }
-}
-
-
-/*
- * Place a trap with a given displacement of point
- */
-static void vault_trap_aux(int y, int x, int yd, int xd)
-{
- int count = 0, y1 = y, x1 = x;
- int dummy = 0;
-
- /* Place traps */
- for (count = 0; count <= 5; count++)
- {
- /* Get a location */
- while (dummy < SAFE_MAX_ATTEMPTS)
- {
- y1 = rand_spread(y, yd);
- x1 = rand_spread(x, xd);
- dummy++;
- if (in_bounds(y1, x1)) break;
- }
-
- if (dummy >= SAFE_MAX_ATTEMPTS)
- {
- if (cheat_room)
- {
- msg_print("Warning! Could not place vault trap!");
- }
- }
-
-
- /* Require "naked" floor grids */
- if (!cave_naked_bold(y1, x1)) continue;
-
- /* Place the trap */
- place_trap(y1, x1);
-
- /* Done */
- break;
- }
-}
-
-
-/*
- * Place some traps with a given displacement of given location
- */
-static void vault_traps(int y, int x, int yd, int xd, int num)
-{
- int i;
-
- for (i = 0; i < num; i++)
- {
- vault_trap_aux(y, x, yd, xd);
- }
-}
-
-
-/*
- * Hack -- Place some sleeping monsters near the given location
- */
-static void vault_monsters(int y1, int x1, int num)
-{
- int k, i, y, x;
-
- /* Try to summon "num" monsters "near" the given location */
- for (k = 0; k < num; k++)
- {
- /* Try nine locations */
- for (i = 0; i < 9; i++)
- {
- int d = 1;
-
- /* Pick a nearby location */
- scatter(&y, &x, y1, x1, d);
-
- /* Require "empty" floor grids */
- if (!cave_empty_bold(y, x)) continue;
-
- /* Place the monster (allow groups) */
- monster_level = dun_level + 2;
- (void)place_monster(y, x, TRUE, TRUE);
- monster_level = dun_level;
- }
- }
-}
-
-/*
- * Allocate the space needed by a room in the room_map array.
- *
- * width, height represent the size of the room (0...x-1) by (0...y-1).
- * crowded is used to denote a monset nest.
- * by0, bx0 are the positions in the room_map array given to the build_type'x'
- * function.
- * cx, cy are the returned center of the allocated room in coordinates for
- * cave.feat and cave.info etc.
- */
-bool_ room_alloc(int width, int height, bool_ crowded, int by0, int bx0, int *cx, int *cy)
-{
- int temp, eby, ebx, by, bx;
-
- /* Calculate number of room_map squares to allocate */
-
- /* Total number along width */
- temp = ((width - 1) / BLOCK_WID) + 1;
-
- for (ebx = bx0 + temp; bx0 > 0 && ebx > dun->col_rooms; bx0--, ebx--);
-
- if (ebx > dun->col_rooms) return (FALSE);
-
- /* Total number along height */
- temp = ((height - 1) / BLOCK_HGT) + 1;
-
- for (eby = by0 + temp; by0 > 0 && eby > dun->row_rooms; by0--, eby--);
-
- /* Never run off the screen */
- if (eby > dun->row_rooms) return (FALSE);
-
- /* Verify open space */
- for (by = by0; by < eby; by++)
- {
- for (bx = bx0; bx < ebx; bx++)
- {
- if (dun->room_map[by][bx]) return (FALSE);
- }
- }
-
- /*
- * It is *extremely* important that the following calculation
- * be *exactly* correct to prevent memory errors XXX XXX XXX
- */
-
- /* Acquire the location of the room */
- *cy = ((by0 + eby) * BLOCK_HGT) / 2;
- *cx = ((bx0 + ebx) * BLOCK_WID) / 2;
-
- /* Save the room location */
- if (dun->cent_n < CENT_MAX)
- {
- dun->cent[dun->cent_n].y = *cy;
- dun->cent[dun->cent_n].x = *cx;
- dun->cent_n++;
- }
-
- /* Reserve some blocks */
- for (by = by0; by < eby; by++)
- {
- for (bx = bx0; bx < ebx; bx++)
- {
- dun->room_map[by][bx] = TRUE;
- }
- }
-
- /* Count "crowded" rooms */
- if (crowded) dun->crowded = TRUE;
-
- /*
- * Hack -- See if room will cut off a cavern.
- * If so, fix by tunneling outside the room in such a way as
- * to conect the caves.
- */
- check_room_boundary(*cx - width / 2 - 1, *cy - height / 2 - 1,
- *cx + width / 2 + 1, *cy + height / 2 + 1);
-
- /* Success */
- return (TRUE);
-}
-
-/*
- * Room building routines.
- *
- * Room types:
- * 1 -- normal
- * 2 -- overlapping
- * 3 -- cross shaped
- * 4 -- large room with features
- * 5 -- monster nests
- * 6 -- monster pits
- * 7 -- simple vaults
- * 8 -- greater vaults
- * 9 -- circular rooms
- */
-
-/*
- * Type 1 -- normal rectangular rooms
- */
-static void build_type1(int by0, int bx0)
-{
- u16b info;
- int y, x = 1, y2, x2, yval, xval;
- int y1, x1, xsize, ysize;
-
- /* Pick a room size */
- y1 = rand_range(1, 4);
- x1 = rand_range(1, 10);
- y2 = rand_range(1, 3);
- x2 = rand_range(1, 9);
-
- xsize = x1 + x2;
- ysize = y1 + y2;
-
- /* Try to allocate space for room. If fails, exit */
- if (!room_alloc(xsize + 2, ysize + 2, FALSE, by0, bx0, &xval, &yval)) return;
-
- /* Get corner values */
- y1 = yval - ysize / 2;
- x1 = xval - xsize / 2;
- y2 = y1 + ysize - 1;
- x2 = x1 + xsize - 1;
-
- info = (dun_level <= randint(25)) ? (CAVE_ROOM|CAVE_GLOW) : CAVE_ROOM;
-
- /* Place a full floor under the room */
- for (y = y1; y <= y2; y++)
- {
- for (x = x1; x <= x2; x++)
- {
- place_floor(y, x);
- cave[y][x].info |= info;
- }
- }
-
- /* Walls around the room */
- build_rectangle(y1 - 1, x1 - 1, y2 + 1, x2 + 1, feat_wall_outer, info);
-
- /* Hack -- Occasional pillar room */
- if (ysize > 2 && xsize > 2)
- {
- if (rand_int(20) == 0)
- {
- for (y = y1; y <= y2; y += 2)
- {
- for (x = x1; x <= x2; x += 2)
- {
- cave_set_feat(y, x, feat_wall_inner);
- }
- }
- }
-
- /* Hack -- Occasional ragged-edge room */
- else if (rand_int(50) == 0)
- {
- for (y = y1 + 2; y <= y2 - 2; y += 2)
- {
- cave_set_feat(y, x1, feat_wall_inner);
- cave_set_feat(y, x2, feat_wall_inner);
- }
- for (x = x1 + 2; x <= x2 - 2; x += 2)
- {
- cave_set_feat(y1, x, feat_wall_inner);
- cave_set_feat(y2, x, feat_wall_inner);
- }
- }
- }
-}
-
-/*
- * Type 2 -- Overlapping rectangular rooms
- */
-static void build_type2(int by0, int bx0)
-{
- u16b info;
- int y, x, yval, xval;
- int y1a, x1a, y2a, x2a;
- int y1b, x1b, y2b, x2b;
-
- /* Try to allocate space for room. If fails, exit */
- if (!room_alloc(25, 11, FALSE, by0, bx0, &xval, &yval)) return;
-
- /* Determine extents of the first room */
- y1a = yval - randint(4);
- y2a = yval + randint(3);
- x1a = xval - randint(14);
- x2a = xval + randint(6);
-
- /* Determine extents of the second room */
- y1b = yval - randint(3);
- y2b = yval + randint(4);
- x1b = xval - randint(6);
- x2b = xval + randint(14);
-
- info = (dun_level <= randint(25)) ? (CAVE_ROOM|CAVE_GLOW) : CAVE_ROOM;
-
- /* Place the walls around room "a" */
- build_rectangle(y1a - 1, x1a - 1, y2a + 1, x2a + 1, feat_wall_outer, info);
-
- /* Place the walls around room "a" */
- build_rectangle(y1b - 1, x1b - 1, y2b + 1, x2b + 1, feat_wall_outer, info);
-
- /* Replace the floor for room "a" */
- for (y = y1a; y <= y2a; y++)
- {
- for (x = x1a; x <= x2a; x++)
- {
- place_floor(y, x);
- cave[y][x].info |= info;
- }
- }
-
- /* Replace the floor for room "b" */
- for (y = y1b; y <= y2b; y++)
- {
- for (x = x1b; x <= x2b; x++)
- {
- place_floor(y, x);
- cave[y][x].info |= info;
- }
- }
-}
-
-/*
- * Type 3 -- Cross shaped rooms
- *
- * Builds a room at a row, column coordinate
- *
- * Room "a" runs north/south, and Room "b" runs east/east
- * So the "central pillar" runs from x1a,y1b to x2a,y2b.
- *
- * Note that currently, the "center" is always 3x3, but I think that
- * the code below will work (with "bounds checking") for 5x5, or even
- * for unsymetric values like 4x3 or 5x3 or 3x4 or 3x5, or even larger.
- */
-static void build_type3(int by0, int bx0)
-{
- u16b info;
- int y, x, dy, dx, wy, wx;
- int y1a, x1a, y2a, x2a;
- int y1b, x1b, y2b, x2b;
- int yval, xval;
-
- /* Try to allocate space for room. If fails, exit */
- if (!room_alloc(25, 11, FALSE, by0, bx0, &xval, &yval)) return;
-
- /* For now, always 3x3 */
- wx = wy = 1;
-
- /* Pick max vertical size (at most 4) */
- dy = rand_range(3, 4);
-
- /* Pick max horizontal size (at most 11) */
- dx = rand_range(3, 11);
-
- /* Determine extents of the north/south room */
- y1a = yval - dy;
- y2a = yval + dy;
- x1a = xval - wx;
- x2a = xval + wx;
-
- /* Determine extents of the east/west room */
- y1b = yval - wy;
- y2b = yval + wy;
- x1b = xval - dx;
- x2b = xval + dx;
-
- info = (dun_level <= randint(25)) ? (CAVE_ROOM|CAVE_GLOW) : CAVE_ROOM;
-
- /* Place the walls around room "a" */
- build_rectangle(y1a - 1, x1a - 1, y2a + 1, x2a + 1, feat_wall_outer, info);
-
- /* Place the walls around room "a" */
- build_rectangle(y1b - 1, x1b - 1, y2b + 1, x2b + 1, feat_wall_outer, info);
-
- /* Replace the floor for room "a" */
- for (y = y1a; y <= y2a; y++)
- {
- for (x = x1a; x <= x2a; x++)
- {
- place_floor(y, x);
- cave[y][x].info |= info;
- }
- }
-
- /* Replace the floor for room "b" */
- for (y = y1b; y <= y2b; y++)
- {
- for (x = x1b; x <= x2b; x++)
- {
- place_floor(y, x);
- cave[y][x].info |= info;
- }
- }
-
- /* Special features (3/4) */
- switch (rand_int(4))
- {
- /* Large solid middle pillar */
- case 1:
- {
- for (y = y1b; y <= y2b; y++)
- {
- for (x = x1a; x <= x2a; x++)
- {
- cave_set_feat(y, x, feat_wall_inner);
- }
- }
- break;
- }
-
- /* Inner treasure vault */
- case 2:
- {
- /* Build the vault */
- build_rectangle(y1b, x1a, y2b, x2a, feat_wall_inner, info);
-
- /* Place a secret door on the inner room */
- switch (rand_int(4))
- {
- case 0:
- place_secret_door(y1b, xval);
- break;
- case 1:
- place_secret_door(y2b, xval);
- break;
- case 2:
- place_secret_door(yval, x1a);
- break;
- case 3:
- place_secret_door(yval, x2a);
- break;
- }
-
- /* Place a treasure in the vault */
- place_object(yval, xval, FALSE, FALSE, OBJ_FOUND_FLOOR);
-
- /* Let's guard the treasure well */
- vault_monsters(yval, xval, rand_int(2) + 3);
-
- /* Traps naturally */
- vault_traps(yval, xval, 4, 4, rand_int(3) + 2);
-
- break;
- }
-
- /* Something else */
- case 3:
- {
- /* Occasionally pinch the center shut */
- if (rand_int(3) == 0)
- {
- /* Pinch the east/west sides */
- for (y = y1b; y <= y2b; y++)
- {
- if (y == yval) continue;
- cave_set_feat(y, x1a - 1, feat_wall_inner);
- cave_set_feat(y, x2a + 1, feat_wall_inner);
- }
-
- /* Pinch the north/south sides */
- for (x = x1a; x <= x2a; x++)
- {
- if (x == xval) continue;
- cave_set_feat(y1b - 1, x, feat_wall_inner);
- cave_set_feat(y2b + 1, x, feat_wall_inner);
- }
-
- /* Sometimes shut using secret doors */
- if (rand_int(3) == 0)
- {
- place_secret_door(yval, x1a - 1);
- place_secret_door(yval, x2a + 1);
- place_secret_door(y1b - 1, xval);
- place_secret_door(y2b + 1, xval);
- }
- }
-
- /* Occasionally put a "plus" in the center */
- else if (rand_int(3) == 0)
- {
- cave_set_feat(yval, xval, feat_wall_inner);
- cave_set_feat(y1b, xval, feat_wall_inner);
- cave_set_feat(y2b, xval, feat_wall_inner);
- cave_set_feat(yval, x1a, feat_wall_inner);
- cave_set_feat(yval, x2a, feat_wall_inner);
- }
-
- /* Occasionally put a pillar in the center */
- else if (rand_int(3) == 0)
- {
- cave_set_feat(yval, xval, feat_wall_inner);
- }
-
- break;
- }
- }
-}
-
-/*
- * Type 4 -- Large room with inner features
- *
- * Possible sub-types:
- * 1 - Just an inner room with one door
- * 2 - An inner room within an inner room
- * 3 - An inner room with pillar(s)
- * 4 - Inner room has a maze
- * 5 - A set of four inner rooms
- */
-static void build_type4(int by0, int bx0)
-{
- u16b info;
- int y, x, y1, x1;
- int y2, x2, tmp, yval, xval;
-
- /* Try to allocate space for room. If fails, exit */
- if (!room_alloc(25, 11, FALSE, by0, bx0, &xval, &yval)) return;
-
- /* Large room */
- y1 = yval - 4;
- y2 = yval + 4;
- x1 = xval - 11;
- x2 = xval + 11;
-
- info = (dun_level <= randint(25)) ? (CAVE_ROOM|CAVE_GLOW) : CAVE_ROOM;
-
- /* Place a full floor under the room */
- for (y = y1 - 1; y <= y2 + 1; y++)
- {
- for (x = x1 - 1; x <= x2 + 1; x++)
- {
- place_floor(y, x);
- cave[y][x].info |= info;
- }
- }
-
- /* Outer Walls */
- build_rectangle(y1 - 1, x1 - 1, y2 + 1, x2 + 1, feat_wall_outer, info);
-
- /* The inner room */
- y1 = y1 + 2;
- y2 = y2 - 2;
- x1 = x1 + 2;
- x2 = x2 - 2;
-
- /* The inner walls */
- build_rectangle(y1 - 1, x1 - 1, y2 + 1, x2 + 1, feat_wall_inner, info);
-
- /* Inner room variations */
- switch (randint(5))
- {
- /* Just an inner room with a monster */
- case 1:
- {
- /* Place a secret door */
- switch (randint(4))
- {
- case 1:
- place_secret_door(y1 - 1, xval);
- break;
- case 2:
- place_secret_door(y2 + 1, xval);
- break;
- case 3:
- place_secret_door(yval, x1 - 1);
- break;
- case 4:
- place_secret_door(yval, x2 + 1);
- break;
- }
-
- /* Place a monster in the room */
- vault_monsters(yval, xval, 1);
-
- break;
- }
-
- /* Treasure Vault (with a door) */
- case 2:
- {
- /* Place a secret door */
- switch (randint(4))
- {
- case 1:
- place_secret_door(y1 - 1, xval);
- break;
- case 2:
- place_secret_door(y2 + 1, xval);
- break;
- case 3:
- place_secret_door(yval, x1 - 1);
- break;
- case 4:
- place_secret_door(yval, x2 + 1);
- break;
- }
-
- /* Place another inner room */
- build_rectangle(yval - 1, xval - 1, yval + 1, xval + 1,
- feat_wall_inner, info);
-
- /* Place a locked door on the inner room */
- switch (randint(4))
- {
- case 1:
- place_locked_door(yval - 1, xval);
- break;
- case 2:
- place_locked_door(yval + 1, xval);
- break;
- case 3:
- place_locked_door(yval, xval - 1);
- break;
- case 4:
- place_locked_door(yval, xval + 1);
- break;
- }
-
- /* Monsters to guard the "treasure" */
- vault_monsters(yval, xval, randint(3) + 2);
-
- /* Object (80%) */
- if (rand_int(100) < 80)
- {
- place_object(yval, xval, FALSE, FALSE, OBJ_FOUND_FLOOR);
- }
-
- /* Stairs (20%) */
- else
- {
- place_random_stairs(yval, xval);
- }
-
- /* Traps to protect the treasure */
- vault_traps(yval, xval, 4, 10, 2 + randint(3));
-
- break;
- }
-
- /* Inner pillar(s). */
- case 3:
- {
- /* Place a secret door */
- switch (randint(4))
- {
- case 1:
- place_secret_door(y1 - 1, xval);
- break;
- case 2:
- place_secret_door(y2 + 1, xval);
- break;
- case 3:
- place_secret_door(yval, x1 - 1);
- break;
- case 4:
- place_secret_door(yval, x2 + 1);
- break;
- }
-
- /* Large Inner Pillar */
- for (y = yval - 1; y <= yval + 1; y++)
- {
- for (x = xval - 1; x <= xval + 1; x++)
- {
- cave_set_feat(y, x, feat_wall_inner);
- }
- }
-
- /* Occasionally, two more Large Inner Pillars */
- if (rand_int(2) == 0)
- {
- tmp = randint(2);
- for (y = yval - 1; y <= yval + 1; y++)
- {
- for (x = xval - 5 - tmp; x <= xval - 3 - tmp; x++)
- {
- cave_set_feat(y, x, feat_wall_inner);
- }
- for (x = xval + 3 + tmp; x <= xval + 5 + tmp; x++)
- {
- cave_set_feat(y, x, feat_wall_inner);
- }
- }
- }
-
- /* Occasionally, some Inner rooms */
- if (rand_int(3) == 0)
- {
- /* Long horizontal walls */
- for (x = xval - 5; x <= xval + 5; x++)
- {
- cave_set_feat(yval - 1, x, feat_wall_inner);
- cave_set_feat(yval + 1, x, feat_wall_inner);
- }
-
- /* Close off the left/right edges */
- cave_set_feat(yval, xval - 5, feat_wall_inner);
- cave_set_feat(yval, xval + 5, feat_wall_inner);
-
- /* Secret doors (random top/bottom) */
- place_secret_door(yval - 3 + (randint(2) * 2), xval - 3);
- place_secret_door(yval - 3 + (randint(2) * 2), xval + 3);
-
- /* Monsters */
- vault_monsters(yval, xval - 2, randint(2));
- vault_monsters(yval, xval + 2, randint(2));
-
- /* Objects */
- if (rand_int(3) == 0) place_object(yval, xval - 2, FALSE, FALSE, OBJ_FOUND_FLOOR);
- if (rand_int(3) == 0) place_object(yval, xval + 2, FALSE, FALSE, OBJ_FOUND_FLOOR);
- }
-
- break;
- }
-
- /* Maze inside. */
- case 4:
- {
- /* Place a secret door */
- switch (randint(4))
- {
- case 1:
- place_secret_door(y1 - 1, xval);
- break;
- case 2:
- place_secret_door(y2 + 1, xval);
- break;
- case 3:
- place_secret_door(yval, x1 - 1);
- break;
- case 4:
- place_secret_door(yval, x2 + 1);
- break;
- }
-
- /* Maze (really a checkerboard) */
- for (y = y1; y <= y2; y++)
- {
- for (x = x1; x <= x2; x++)
- {
- if (0x1 & (x + y))
- {
- cave_set_feat(y, x, feat_wall_inner);
- }
- }
- }
-
- /* Monsters just love mazes. */
- vault_monsters(yval, xval - 5, randint(3));
- vault_monsters(yval, xval + 5, randint(3));
-
- /* Traps make them entertaining. */
- vault_traps(yval, xval - 3, 2, 8, randint(3));
- vault_traps(yval, xval + 3, 2, 8, randint(3));
-
- /* Mazes should have some treasure too. */
- vault_objects(yval, xval, 3);
-
- break;
- }
-
- /* Four small rooms. */
- case 5:
- {
- /* Inner "cross" */
- for (y = y1; y <= y2; y++)
- {
- cave_set_feat(y, xval, feat_wall_inner);
- }
-
- for (x = x1; x <= x2; x++)
- {
- cave_set_feat(yval, x, feat_wall_inner);
- }
-
- /* Doors into the rooms */
- if (rand_int(100) < 50)
- {
- int i = randint(10);
- place_secret_door(y1 - 1, xval - i);
- place_secret_door(y1 - 1, xval + i);
- place_secret_door(y2 + 1, xval - i);
- place_secret_door(y2 + 1, xval + i);
- }
- else
- {
- int i = randint(3);
- place_secret_door(yval + i, x1 - 1);
- place_secret_door(yval - i, x1 - 1);
- place_secret_door(yval + i, x2 + 1);
- place_secret_door(yval - i, x2 + 1);
- }
-
- /* Treasure, centered at the center of the cross */
- vault_objects(yval, xval, 2 + randint(2));
-
- /* Gotta have some monsters. */
- vault_monsters(yval + 1, xval - 4, randint(4));
- vault_monsters(yval + 1, xval + 4, randint(4));
- vault_monsters(yval - 1, xval - 4, randint(4));
- vault_monsters(yval - 1, xval + 4, randint(4));
-
- break;
- }
- }
-}
-
-
-/*
- * Determine if the given monster is appropriate for inclusion in
- * a monster nest or monster pit or the given type.
- *
- * None of the pits/nests are allowed to include "unique" monsters,
- * or monsters which can "multiply".
- *
- * Some of the pits/nests are asked to avoid monsters which can blink
- * away or which are invisible. This is probably a hack.
- *
- * The old method made direct use of monster "names", which is bad.
- *
- * Note the use of Angband 2.7.9 monster race pictures in various places.
- */
-
-
-/*
- * Helper function for "monster nest (jelly)"
- */
-static bool_ vault_aux_jelly(int r_idx)
-{
- monster_race *r_ptr = &r_info[r_idx];
-
- /* Decline unique monsters */
- if (r_ptr->flags1 & (RF1_UNIQUE)) return (FALSE);
-
- /* Also decline evil jellies (like death molds and shoggoths) */
- if (r_ptr->flags3 & (RF3_EVIL)) return (FALSE);
-
- /* Require icky thing, jelly, mold, or mushroom */
- if (!strchr("ijm,", r_ptr->d_char)) return (FALSE);
-
- /* Okay */
- return (TRUE);
-}
-
-
-/*
- * Helper function for "monster nest (animal)"
- */
-static bool_ vault_aux_animal(int r_idx)
-{
- monster_race *r_ptr = &r_info[r_idx];
-
- /* Decline unique monsters */
- if (r_ptr->flags1 & (RF1_UNIQUE)) return (FALSE);
-
- /* Require "animal" flag */
- if (!(r_ptr->flags3 & (RF3_ANIMAL))) return (FALSE);
-
- /* Okay */
- return (TRUE);
-}
-
-
-/*
- * Helper function for "monster nest (undead)"
- */
-static bool_ vault_aux_undead(int r_idx)
-{
- monster_race *r_ptr = &r_info[r_idx];
-
- /* Decline unique monsters */
- if (r_ptr->flags1 & (RF1_UNIQUE)) return (FALSE);
-
- /* Require Undead */
- if (!(r_ptr->flags3 & (RF3_UNDEAD))) return (FALSE);
-
- /* Okay */
- return (TRUE);
-}
-
-
-/*
- * Helper function for "monster nest (chapel)"
- */
-static bool_ vault_aux_chapel(int r_idx)
-{
- monster_race *r_ptr = &r_info[r_idx];
-
- /* Decline unique monsters */
- if (r_ptr->flags1 & (RF1_UNIQUE)) return (FALSE);
-
- /* Require "priest" or Angel */
- if (!((r_ptr->d_char == 'A') ||
- strstr((r_name + r_ptr->name), "riest")))
- {
- return (FALSE);
- }
-
- /* Okay */
- return (TRUE);
-}
-
-
-/*
- * Helper function for "monster nest (kennel)"
- */
-static bool_ vault_aux_kennel(int r_idx)
-{
- monster_race *r_ptr = &r_info[r_idx];
-
- /* Decline unique monsters */
- if (r_ptr->flags1 & (RF1_UNIQUE)) return (FALSE);
-
- /* Require a Zephyr Hound or a dog */
- return ((r_ptr->d_char == 'Z') || (r_ptr->d_char == 'C'));
-
-}
-
-
-/*
- * Helper function for "monster nest (treasure)"
- */
-static bool_ vault_aux_treasure(int r_idx)
-{
- monster_race *r_ptr = &r_info[r_idx];
-
- /* Decline unique monsters */
- if (r_ptr->flags1 & (RF1_UNIQUE)) return (FALSE);
-
- /* Require "priest" or Angel */
- if (!((r_ptr->d_char == '!') || (r_ptr->d_char == '|') ||
- (r_ptr->d_char == '$') || (r_ptr->d_char == '?') ||
- (r_ptr->d_char == '=')))
- {
- return (FALSE);
- }
-
- /* Okay */
- return (TRUE);
-}
-
-
-/*
- * Helper function for "monster nest (clone)"
- */
-static bool_ vault_aux_clone(int r_idx)
-{
- return (r_idx == template_race);
-}
-
-
-/*
- * Helper function for "monster nest (symbol clone)"
- */
-static bool_ vault_aux_symbol(int r_idx)
-{
- return ((r_info[r_idx].d_char == (r_info[template_race].d_char))
- && !(r_info[r_idx].flags1 & RF1_UNIQUE));
-}
-
-
-/*
- * Helper function for "monster pit (orc)"
- */
-static bool_ vault_aux_orc(int r_idx)
-{
- monster_race *r_ptr = &r_info[r_idx];
-
- /* Decline unique monsters */
- if (r_ptr->flags1 & (RF1_UNIQUE)) return (FALSE);
-
- /* Hack -- Require "o" monsters */
- if (!strchr("o", r_ptr->d_char)) return (FALSE);
-
- /* Okay */
- return (TRUE);
-}
-
-
-
-/*
- * Helper function for "monster pit (troll)"
- */
-static bool_ vault_aux_troll(int r_idx)
-{
- monster_race *r_ptr = &r_info[r_idx];
-
- /* Decline unique monsters */
- if (r_ptr->flags1 & (RF1_UNIQUE)) return (FALSE);
-
- /* Hack -- Require "T" monsters */
- if (!strchr("T", r_ptr->d_char)) return (FALSE);
-
- /* Okay */
- return (TRUE);
-}
-
-
-/*
- * Helper function for "monster pit (giant)"
- */
-static bool_ vault_aux_giant(int r_idx)
-{
- monster_race *r_ptr = &r_info[r_idx];
-
- /* Decline unique monsters */
- if (r_ptr->flags1 & (RF1_UNIQUE)) return (FALSE);
-
- /* Hack -- Require "P" monsters */
- if (!strchr("P", r_ptr->d_char)) return (FALSE);
-
- /* Okay */
- return (TRUE);
-}
-
-
-/*
- * Hack -- breath type for "vault_aux_dragon()"
- */
-static u32b vault_aux_dragon_mask4;
-
-
-/*
- * Helper function for "monster pit (dragon)"
- */
-static bool_ vault_aux_dragon(int r_idx)
-{
- monster_race *r_ptr = &r_info[r_idx];
-
- /* Decline unique monsters */
- if (r_ptr->flags1 & (RF1_UNIQUE)) return (FALSE);
-
- /* Hack -- Require "d" or "D" monsters */
- if (!strchr("Dd", r_ptr->d_char)) return (FALSE);
-
- /* Hack -- Require correct "breath attack" */
- if (r_ptr->flags4 != vault_aux_dragon_mask4) return (FALSE);
-
- /* Okay */
- return (TRUE);
-}
-
-
-/*
- * Helper function for "monster pit (demon)"
- */
-static bool_ vault_aux_demon(int r_idx)
-{
- monster_race *r_ptr = &r_info[r_idx];
-
- /* Decline unique monsters */
- if (r_ptr->flags1 & (RF1_UNIQUE)) return (FALSE);
-
- /* Hack -- Require "U" monsters */
- if (!strchr("U", r_ptr->d_char)) return (FALSE);
-
- /* Okay */
- return (TRUE);
-}
-
-
-/*
- * Type 5 -- Monster nests
- *
- * A monster nest is a "big" room, with an "inner" room, containing
- * a "collection" of monsters of a given type strewn about the room.
- *
- * The monsters are chosen from a set of 64 randomly selected monster
- * races, to allow the nest creation to fail instead of having "holes".
- *
- * Note the use of the "get_mon_num_prep()" function, and the special
- * "get_mon_num_hook()" restriction function, to prepare the "monster
- * allocation table" in such a way as to optimize the selection of
- * "appropriate" non-unique monsters for the nest.
- *
- * Currently, a monster nest is one of
- * a nest of "jelly" monsters (Dungeon level 5 and deeper)
- * a nest of "animal" monsters (Dungeon level 30 and deeper)
- * a nest of "undead" monsters (Dungeon level 50 and deeper)
- *
- * Note that the "get_mon_num()" function may (rarely) fail, in which
- * case the nest will be empty, and will not affect the level rating.
- *
- * Note that "monster nests" will never contain "unique" monsters.
- */
-static void build_type5(int by0, int bx0)
-{
- int y, x, y1, x1, y2, x2, xval, yval;
- int tmp, i;
- cptr name;
- bool_ empty = FALSE;
- bool_ (*old_get_mon_num_hook)(int r_idx);
- s16b what[64];
-
- /* Try to allocate space for room. If fails, exit */
- if (!room_alloc(25, 11, TRUE, by0, bx0, &xval, &yval)) return;
-
- /* Large room */
- y1 = yval - 4;
- y2 = yval + 4;
- x1 = xval - 11;
- x2 = xval + 11;
-
- /* Place the floor area */
- for (y = y1; y <= y2; y++)
- {
- for (x = x1; x <= x2; x++)
- {
- place_floor(y, x);
- cave[y][x].info |= (CAVE_ROOM);
- }
- }
-
- /* Place the outer walls */
- build_rectangle(y1 - 1, x1 - 1, y2 + 1, x2 + 1, feat_wall_outer, CAVE_ROOM);
-
- /* Advance to the center room */
- y1 = y1 + 2;
- y2 = y2 - 2;
- x1 = x1 + 2;
- x2 = x2 - 2;
-
- /* The inner walls */
- build_rectangle(y1 - 1, x1 - 1, y2 + 1, x2 + 1, feat_wall_inner, CAVE_ROOM);
-
- /* Place a secret door */
- switch (randint(4))
- {
- case 1:
- place_secret_door(y1 - 1, xval);
- break;
- case 2:
- place_secret_door(y2 + 1, xval);
- break;
- case 3:
- place_secret_door(yval, x1 - 1);
- break;
- case 4:
- place_secret_door(yval, x2 + 1);
- break;
- }
-
- /* Hack -- Choose a nest type */
- tmp = randint(dun_level);
-
- old_get_mon_num_hook = get_mon_num_hook;
-
- if ((tmp < 25) && (rand_int(2) != 0))
- {
- while (1)
- {
- template_race = randint(max_r_idx - 2);
-
- /* Reject uniques */
- if (r_info[template_race].flags1 & RF1_UNIQUE) continue;
-
- /* Reject OoD monsters in a loose fashion */
- if (((r_info[template_race].level) + randint(5)) >
- (dun_level + randint(5))) continue;
-
- /* Don't like 'break's like this, but this cannot be made better */
- break;
- }
-
- if ((dun_level >= (25 + randint(15))) && (rand_int(2) != 0))
- {
- name = "symbol clone";
- get_mon_num_hook = vault_aux_symbol;
- }
- else
- {
- name = "clone";
- get_mon_num_hook = vault_aux_clone;
- }
- }
- else if (tmp < 25)
- /* Monster nest (jelly) */
- {
- /* Describe */
- name = "jelly";
-
- /* Restrict to jelly */
- get_mon_num_hook = vault_aux_jelly;
- }
-
- else if (tmp < 50)
- {
- name = "treasure";
- get_mon_num_hook = vault_aux_treasure;
- }
-
- /* Monster nest (animal) */
- else if (tmp < 65)
- {
- if (rand_int(3) == 0)
- {
- name = "kennel";
- get_mon_num_hook = vault_aux_kennel;
- }
- else
- {
- /* Describe */
- name = "animal";
-
- /* Restrict to animal */
- get_mon_num_hook = vault_aux_animal;
- }
- }
-
- /* Monster nest (undead) */
- else
- {
- if (rand_int(3) == 0)
- {
- name = "chapel";
- get_mon_num_hook = vault_aux_chapel;
- }
- else
- {
- /* Describe */
- name = "undead";
-
- /* Restrict to undead */
- get_mon_num_hook = vault_aux_undead;
- }
- }
-
- /* Prepare allocation table */
- get_mon_num_prep();
-
- /* Pick some monster types */
- for (i = 0; i < 64; i++)
- {
- /* Get a (hard) monster type */
- what[i] = get_mon_num(dun_level + 10);
-
- /* Notice failure */
- if (!what[i]) empty = TRUE;
- }
-
- /* Remove restriction */
- get_mon_num_hook = old_get_mon_num_hook;
-
- /* Prepare allocation table */
- get_mon_num_prep();
-
- /* Oops */
- if (empty) return;
-
- /* Describe */
- if (cheat_room || p_ptr->precognition)
- {
- /* Room type */
- msg_format("Monster nest (%s)", name);
- }
-
- /* Increase the level rating */
- rating += 10;
-
- /* (Sometimes) Cause a "special feeling" (for "Monster Nests") */
- if ((dun_level <= 40) && (randint(dun_level * dun_level + 50) < 300))
- {
- good_item_flag = TRUE;
- }
-
- /* Place some monsters */
- for (y = yval - 2; y <= yval + 2; y++)
- {
- for (x = xval - 9; x <= xval + 9; x++)
- {
- int r_idx = what[rand_int(64)];
-
- /* Place that "random" monster (no groups) */
- (void)place_monster_aux(y, x, r_idx, FALSE, FALSE, MSTATUS_ENEMY);
- }
- }
-}
-
-
-
-/*
- * Type 6 -- Monster pits
- *
- * A monster pit is a "big" room, with an "inner" room, containing
- * a "collection" of monsters of a given type organized in the room.
- *
- * Monster types in the pit (list out of date...)
- * orc pit (Dungeon Level 5 and deeper)
- * troll pit (Dungeon Level 20 and deeper)
- * giant pit (Dungeon Level 40 and deeper)
- * dragon pit (Dungeon Level 60 and deeper)
- * demon pit (Dungeon Level 80 and deeper)
- *
- * The inside room in a monster pit appears as shown below, where the
- * actual monsters in each location depend on the type of the pit
- *
- * #####################
- * #0000000000000000000#
- * #0112233455543322110#
- * #0112233467643322110#
- * #0112233455543322110#
- * #0000000000000000000#
- * #####################
- *
- * Note that the monsters in the pit are now chosen by using "get_mon_num()"
- * to request 16 "appropriate" monsters, sorting them by level, and using
- * the "even" entries in this sorted list for the contents of the pit.
- *
- * Hack -- all of the "dragons" in a "dragon" pit must be the same "color",
- * which is handled by requiring a specific "breath" attack for all of the
- * dragons. This may include "multi-hued" breath. Note that "wyrms" may
- * be present in many of the dragon pits, if they have the proper breath.
- *
- * Note the use of the "get_mon_num_prep()" function, and the special
- * "get_mon_num_hook()" restriction function, to prepare the "monster
- * allocation table" in such a way as to optimize the selection of
- * "appropriate" non-unique monsters for the pit.
- *
- * Note that the "get_mon_num()" function may (rarely) fail, in which case
- * the pit will be empty, and will not effect the level rating.
- *
- * Note that "monster pits" will never contain "unique" monsters.
- */
-static void build_type6(int by0, int bx0)
-{
- int tmp, what[16];
- int i, j, y, x, y1, x1, y2, x2, xval, yval;
- bool_ empty = FALSE;
- cptr name;
- bool_ (*old_get_mon_num_hook)(int r_idx);
-
- /* Try to allocate space for room. If fails, exit */
- if (!room_alloc(25, 11, TRUE, by0, bx0, &xval, &yval)) return;
-
- /* Large room */
- y1 = yval - 4;
- y2 = yval + 4;
- x1 = xval - 11;
- x2 = xval + 11;
-
- /* Place the floor area */
- for (y = y1 - 1; y <= y2 + 1; y++)
- {
- for (x = x1 - 1; x <= x2 + 1; x++)
- {
- place_floor(y, x);
- cave[y][x].info |= (CAVE_ROOM);
- }
- }
-
- /* Place the outer walls */
- build_rectangle(y1 - 1, x1 - 1, y2 + 1, x2 + 1, feat_wall_outer, CAVE_ROOM);
-
- /* Advance to the center room */
- y1 = y1 + 2;
- y2 = y2 - 2;
- x1 = x1 + 2;
- x2 = x2 - 2;
-
- /* The inner walls */
- build_rectangle(y1 - 1, x1 - 1, y2 + 1, x2 + 1, feat_wall_outer, CAVE_ROOM);
-
- /* Place a secret door */
- switch (randint(4))
- {
- case 1:
- place_secret_door(y1 - 1, xval);
- break;
- case 2:
- place_secret_door(y2 + 1, xval);
- break;
- case 3:
- place_secret_door(yval, x1 - 1);
- break;
- case 4:
- place_secret_door(yval, x2 + 1);
- break;
- }
-
- /* Choose a pit type */
- tmp = randint(dun_level);
-
- old_get_mon_num_hook = get_mon_num_hook;
-
- /* Orc pit */
- if (tmp < 20)
- {
- /* Message */
- name = "orc";
-
- /* Restrict monster selection */
- get_mon_num_hook = vault_aux_orc;
- }
-
- /* Troll pit */
- else if (tmp < 40)
- {
- /* Message */
- name = "troll";
-
- /* Restrict monster selection */
- get_mon_num_hook = vault_aux_troll;
- }
-
- /* Giant pit */
- else if (tmp < 55)
- {
- /* Message */
- name = "giant";
-
- /* Restrict monster selection */
- get_mon_num_hook = vault_aux_giant;
- }
-
- else if (tmp < 70)
- {
- if (randint(4) != 1)
- {
- /* Message */
- name = "ordered clones";
-
- do
- {
- template_race = randint(max_r_idx - 2);
- }
- while ((r_info[template_race].flags1 & RF1_UNIQUE)
- || (((r_info[template_race].level) + randint(5)) >
- (dun_level + randint(5))));
-
- /* Restrict selection */
- get_mon_num_hook = vault_aux_symbol;
- }
- else
- {
- name = "ordered chapel";
- get_mon_num_hook = vault_aux_chapel;
- }
-
- }
-
- /* Dragon pit */
- else if (tmp < 80)
- {
- /* Pick dragon type */
- switch (rand_int(6))
- {
- /* Black */
- case 0:
- {
- /* Message */
- name = "acid dragon";
-
- /* Restrict dragon breath type */
- vault_aux_dragon_mask4 = RF4_BR_ACID;
-
- /* Done */
- break;
- }
-
- /* Blue */
- case 1:
- {
- /* Message */
- name = "electric dragon";
-
- /* Restrict dragon breath type */
- vault_aux_dragon_mask4 = RF4_BR_ELEC;
-
- /* Done */
- break;
- }
-
- /* Red */
- case 2:
- {
- /* Message */
- name = "fire dragon";
-
- /* Restrict dragon breath type */
- vault_aux_dragon_mask4 = RF4_BR_FIRE;
-
- /* Done */
- break;
- }
-
- /* White */
- case 3:
- {
- /* Message */
- name = "cold dragon";
-
- /* Restrict dragon breath type */
- vault_aux_dragon_mask4 = RF4_BR_COLD;
-
- /* Done */
- break;
- }
-
- /* Green */
- case 4:
- {
- /* Message */
- name = "poison dragon";
-
- /* Restrict dragon breath type */
- vault_aux_dragon_mask4 = RF4_BR_POIS;
-
- /* Done */
- break;
- }
-
- /* Multi-hued */
- default:
- {
- /* Message */
- name = "multi-hued dragon";
-
- /* Restrict dragon breath type */
- vault_aux_dragon_mask4 = (RF4_BR_ACID | RF4_BR_ELEC |
- RF4_BR_FIRE | RF4_BR_COLD |
- RF4_BR_POIS);
-
- /* Done */
- break;
- }
-
- }
-
- /* Restrict monster selection */
- get_mon_num_hook = vault_aux_dragon;
- }
-
- /* Demon pit */
- else
- {
- /* Message */
- name = "demon";
-
- /* Restrict monster selection */
- get_mon_num_hook = vault_aux_demon;
- }
-
- /* Prepare allocation table */
- get_mon_num_prep();
-
- /* Pick some monster types */
- for (i = 0; i < 16; i++)
- {
- /* Get a (hard) monster type */
- what[i] = get_mon_num(dun_level + 10);
-
- /* Notice failure */
- if (!what[i]) empty = TRUE;
- }
-
- /* Remove restriction */
- get_mon_num_hook = old_get_mon_num_hook;
-
- /* Prepare allocation table */
- get_mon_num_prep();
-
- /* Oops */
- if (empty) return;
-
- /* XXX XXX XXX */
- /* Sort the entries */
- for (i = 0; i < 16 - 1; i++)
- {
- /* Sort the entries */
- for (j = 0; j < 16 - 1; j++)
- {
- int i1 = j;
- int i2 = j + 1;
-
- int p1 = r_info[what[i1]].level;
- int p2 = r_info[what[i2]].level;
-
- /* Bubble */
- if (p1 > p2)
- {
- int tmp = what[i1];
- what[i1] = what[i2];
- what[i2] = tmp;
- }
- }
- }
-
- /* Select the entries */
- for (i = 0; i < 8; i++)
- {
- /* Every other entry */
- what[i] = what[i * 2];
- }
-
- /* Message */
- if (cheat_room || p_ptr->precognition)
- {
- /* Room type */
- msg_format("Monster pit (%s)", name);
-
- if (cheat_hear || p_ptr->precognition)
- {
- /* Contents */
- for (i = 0; i < 8; i++)
- {
- /* Message */
- msg_print(r_name + r_info[what[i]].name);
- }
- }
- }
-
- /* Increase the level rating */
- rating += 10;
-
- /* (Sometimes) Cause a "special feeling" (for "Monster Pits") */
- if ((dun_level <= 40) && (randint(dun_level * dun_level + 50) < 300))
- {
- good_item_flag = TRUE;
- }
-
- /* Top and bottom rows */
- for (x = xval - 9; x <= xval + 9; x++)
- {
- place_monster_aux(yval - 2, x, what[0], FALSE, FALSE, MSTATUS_ENEMY);
- place_monster_aux(yval + 2, x, what[0], FALSE, FALSE, MSTATUS_ENEMY);
- }
-
- /* Middle columns */
- for (y = yval - 1; y <= yval + 1; y++)
- {
- place_monster_aux(y, xval - 9, what[0], FALSE, FALSE, MSTATUS_ENEMY);
- place_monster_aux(y, xval + 9, what[0], FALSE, FALSE, MSTATUS_ENEMY);
-
- place_monster_aux(y, xval - 8, what[1], FALSE, FALSE, MSTATUS_ENEMY);
- place_monster_aux(y, xval + 8, what[1], FALSE, FALSE, MSTATUS_ENEMY);
-
- place_monster_aux(y, xval - 7, what[1], FALSE, FALSE, MSTATUS_ENEMY);
- place_monster_aux(y, xval + 7, what[1], FALSE, FALSE, MSTATUS_ENEMY);
-
- place_monster_aux(y, xval - 6, what[2], FALSE, FALSE, MSTATUS_ENEMY);
- place_monster_aux(y, xval + 6, what[2], FALSE, FALSE, MSTATUS_ENEMY);
-
- place_monster_aux(y, xval - 5, what[2], FALSE, FALSE, MSTATUS_ENEMY);
- place_monster_aux(y, xval + 5, what[2], FALSE, FALSE, MSTATUS_ENEMY);
-
- place_monster_aux(y, xval - 4, what[3], FALSE, FALSE, MSTATUS_ENEMY);
- place_monster_aux(y, xval + 4, what[3], FALSE, FALSE, MSTATUS_ENEMY);
-
- place_monster_aux(y, xval - 3, what[3], FALSE, FALSE, MSTATUS_ENEMY);
- place_monster_aux(y, xval + 3, what[3], FALSE, FALSE, MSTATUS_ENEMY);
-
- place_monster_aux(y, xval - 2, what[4], FALSE, FALSE, MSTATUS_ENEMY);
- place_monster_aux(y, xval + 2, what[4], FALSE, FALSE, MSTATUS_ENEMY);
- }
-
- /* Above/Below the center monster */
- for (x = xval - 1; x <= xval + 1; x++)
- {
- place_monster_aux(yval + 1, x, what[5], FALSE, FALSE, MSTATUS_ENEMY);
- place_monster_aux(yval - 1, x, what[5], FALSE, FALSE, MSTATUS_ENEMY);
- }
-
- /* Next to the center monster */
- place_monster_aux(yval, xval + 1, what[6], FALSE, FALSE, MSTATUS_ENEMY);
- place_monster_aux(yval, xval - 1, what[6], FALSE, FALSE, MSTATUS_ENEMY);
-
- /* Center monster */
- place_monster_aux(yval, xval, what[7], FALSE, FALSE, MSTATUS_ENEMY);
-}
-
-/*
- * Hack -- fill in "vault" rooms
- */
-static void build_vault(int yval, int xval, int ymax, int xmax, cptr data)
-{
- int dx, dy, x, y, bwy[8], bwx[8], i;
-
- cptr t;
-
- cave_type *c_ptr;
-
- /* Clean the between gates arrays */
- for (i = 0; i < 8; i++)
- {
- bwy[i] = bwx[i] = 9999;
- }
-
- /* Place dungeon features and objects */
- for (t = data, dy = 0; dy < ymax; dy++)
- {
- for (dx = 0; dx < xmax; dx++, t++)
- {
- /* Extract the location */
- x = xval - (xmax / 2) + dx;
- y = yval - (ymax / 2) + dy;
-
- /* Hack -- skip "non-grids" */
- if (*t == ' ') continue;
-
- /* Access the grid */
- c_ptr = &cave[y][x];
-
- /* Lay down a floor */
- place_floor(y, x);
-
- /* Part of a vault */
- c_ptr->info |= (CAVE_ROOM | CAVE_ICKY);
-
- /* Analyze the grid */
- switch (*t)
- {
- /* Granite wall (outer) */
- case '%':
- {
- cave_set_feat(y, x, FEAT_WALL_OUTER);
- break;
- }
-
- /* Granite wall (inner) */
- case '#':
- {
- cave_set_feat(y, x, FEAT_WALL_INNER);
- break;
- }
-
- /* Permanent wall (inner) */
- case 'X':
- {
- cave_set_feat(y, x, FEAT_PERM_INNER);
- break;
- }
-
- /* Treasure/trap */
- case '*':
- {
- if (rand_int(100) < 75)
- {
- place_object(y, x, FALSE, FALSE, OBJ_FOUND_VAULT);
- }
- else
- {
- place_trap(y, x);
- }
- break;
- }
-
- /* Secret doors */
- case '+':
- {
- place_secret_door(y, x);
- break;
- }
-
- /* Trap */
- case '^':
- {
- place_trap(y, x);
- break;
- }
-
- /* Glass wall */
- case 'G':
- {
- cave_set_feat(y, x, FEAT_GLASS_WALL);
- break;
- }
-
- /* Illusion wall */
- case 'I':
- {
- cave_set_feat(y, x, FEAT_ILLUS_WALL);
- break;
- }
- }
- }
- }
-
- /* Place dungeon monsters and objects */
- for (t = data, dy = 0; dy < ymax; dy++)
- {
- for (dx = 0; dx < xmax; dx++, t++)
- {
- /* Extract the grid */
- x = xval - (xmax / 2) + dx;
- y = yval - (ymax / 2) + dy;
-
- /* Hack -- skip "non-grids" */
- if (*t == ' ') continue;
-
- /* Access the grid */
- c_ptr = &cave[y][x];
-
- /* Analyze the symbol */
- switch (*t)
- {
- /* Monster */
- case '&':
- {
- monster_level = dun_level + 5;
- place_monster(y, x, TRUE, TRUE);
- monster_level = dun_level;
- break;
- }
-
- /* Meaner monster */
- case '@':
- {
- monster_level = dun_level + 11;
- place_monster(y, x, TRUE, TRUE);
- monster_level = dun_level;
- break;
- }
-
- /* Meaner monster, plus treasure */
- case '9':
- {
- monster_level = dun_level + 9;
- place_monster(y, x, TRUE, TRUE);
- monster_level = dun_level;
- object_level = dun_level + 7;
- place_object(y, x, TRUE, FALSE, OBJ_FOUND_VAULT);
- object_level = dun_level;
- break;
- }
-
- /* Nasty monster and treasure */
- case '8':
- {
- monster_level = dun_level + 40;
- place_monster(y, x, TRUE, TRUE);
- monster_level = dun_level;
- object_level = dun_level + 20;
- place_object(y, x, TRUE, TRUE, OBJ_FOUND_VAULT);
- object_level = dun_level;
- break;
- }
-
- /* Monster and/or object */
- case ',':
- {
- if (rand_int(100) < 50)
- {
- monster_level = dun_level + 3;
- place_monster(y, x, TRUE, TRUE);
- monster_level = dun_level;
- }
- if (rand_int(100) < 50)
- {
- object_level = dun_level + 7;
- place_object(y, x, FALSE, FALSE, OBJ_FOUND_VAULT);
- object_level = dun_level;
- }
- break;
- }
-
- case 'p':
- {
- cave_set_feat(y, x, FEAT_PATTERN_START);
- break;
- }
-
- case 'a':
- {
- cave_set_feat(y, x, FEAT_PATTERN_1);
- break;
- }
-
- case 'b':
- {
- cave_set_feat(y, x, FEAT_PATTERN_2);
- break;
- }
-
- case 'c':
- {
- cave_set_feat(y, x, FEAT_PATTERN_3);
- break;
- }
-
- case 'd':
- {
- cave_set_feat(y, x, FEAT_PATTERN_4);
- break;
- }
-
- case 'P':
- {
- cave_set_feat(y, x, FEAT_PATTERN_END);
- break;
- }
-
- case 'B':
- {
- cave_set_feat(y, x, FEAT_PATTERN_XTRA1);
- break;
- }
-
- case 'A':
- {
- object_level = dun_level + 12;
- place_object(y, x, TRUE, FALSE, OBJ_FOUND_VAULT);
- object_level = dun_level;
- break;
- }
-
-
- /* Between gates */
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- {
- /* Not found before */
- if (bwy[*t - '0'] == 9999)
- {
- cave_set_feat(y, x, FEAT_BETWEEN);
- bwy[*t - '0'] = y;
- bwx[*t - '0'] = x;
- }
- /* The second time */
- else
- {
- cave_set_feat(y, x, FEAT_BETWEEN);
- c_ptr->special = bwx[*t - '0'] + (bwy[*t - '0'] << 8);
- cave[bwy[*t - '0']][bwx[*t - '0']].special = x + (y << 8);
- }
- break;
- }
- }
- }
- }
-}
-
-/*
- * Type 7 -- simple vaults (see "v_info.txt")
- */
-static void build_type7(int by0, int bx0)
-{
- vault_type *v_ptr = NULL;
- int dummy = 0, xval, yval;
-
- /* Pick a lesser vault */
- while (dummy < SAFE_MAX_ATTEMPTS)
- {
- dummy++;
-
- /* Access a random vault record */
- v_ptr = &v_info[rand_int(max_v_idx)];
-
- /* Accept the first lesser vault */
- if (v_ptr->typ == 7) break;
- }
-
- /* Try to allocate space for room. If fails, exit */
- if (!room_alloc(v_ptr->wid, v_ptr->hgt, FALSE, by0, bx0, &xval, &yval))
- {
- if (cheat_room) msg_print("Could not allocate this vault here");
- return;
- }
-
- if (dummy >= SAFE_MAX_ATTEMPTS)
- {
- if (cheat_room)
- {
- msg_print("Warning! Could not place lesser vault!");
- }
- return;
- }
-
-
-#ifdef FORCE_V_IDX
- v_ptr = &v_info[FORCE_V_IDX];
-#endif
-
- /* Message */
- if (cheat_room || p_ptr->precognition) msg_print("Lesser Vault");
-
- /* Boost the rating */
- rating += v_ptr->rat;
-
- /* (Sometimes) Cause a special feeling */
- if ((dun_level <= 50) ||
- (randint((dun_level - 40) * (dun_level - 40) + 50) < 400))
- {
- good_item_flag = TRUE;
- }
-
- /* Hack -- Build the vault */
- build_vault(yval, xval, v_ptr->hgt, v_ptr->wid, v_text + v_ptr->text);
-}
-
-
-
-/*
- * Type 8 -- greater vaults (see "v_info.txt")
- */
-static void build_type8(int by0, int bx0)
-{
- vault_type *v_ptr = NULL;
- int dummy = 0, xval, yval;
-
- /* Pick a lesser vault */
- while (dummy < SAFE_MAX_ATTEMPTS)
- {
- dummy++;
-
- /* Access a random vault record */
- v_ptr = &v_info[rand_int(max_v_idx)];
-
- /* Accept the first greater vault */
- if (v_ptr->typ == 8) break;
- }
-
- /* Try to allocate space for room. If fails, exit */
- if (!room_alloc(v_ptr->wid, v_ptr->hgt, FALSE, by0, bx0, &xval, &yval))
- {
- if (cheat_room) msg_print("Could not allocate this vault here");
- return;
- }
-
- if (dummy >= SAFE_MAX_ATTEMPTS)
- {
- if (cheat_room)
- {
- msg_print("Warning! Could not place greater vault!");
- }
- return;
- }
-
-
-#ifdef FORCE_V_IDX
- v_ptr = &v_info[FORCE_V_IDX];
-#endif
-
- /* Message */
- if (cheat_room || p_ptr->precognition) msg_print("Greater Vault");
-
- /* Boost the rating */
- rating += v_ptr->rat;
-
- /* (Sometimes) Cause a special feeling */
- if ((dun_level <= 50) ||
- (randint((dun_level - 40) * (dun_level - 40) + 50) < 400))
- {
- good_item_flag = TRUE;
- }
-
- /* Hack -- Build the vault */
- build_vault(yval, xval, v_ptr->hgt, v_ptr->wid, v_text + v_ptr->text);
-}
-
-/*
- * DAG:
- * Build an vertical oval room.
- * For every grid in the possible square, check the distance.
- * If it's less than or == than the radius, make it a room square.
- * If its less, make it a normal grid. If it's == make it an outer
- * wall.
- */
-static void build_type9(int by0, int bx0)
-{
- u16b info;
- int rad, x, y, x0, y0;
-
- rad = 2 + rand_int(8);
-
- /* Try to allocate space for room. If fails, exit */
- if (!room_alloc(rad*2 + 1, rad*2 + 1, FALSE, by0, bx0, &x0, &y0)) return;
-
- info = (randint(dun_level) <= 5) ? (CAVE_ROOM|CAVE_GLOW) : CAVE_ROOM;
-
- for (x = x0 - rad; x <= x0 + rad; x++)
- {
- for (y = y0 - rad; y <= y0 + rad; y++)
- {
- if (distance(y0, x0, y, x) == rad)
- {
- cave[y][x].info |= info;
- cave_set_feat(y, x, feat_wall_outer);
- }
-
- if (distance(y0, x0, y, x) < rad)
- {
- cave[y][x].info |= info;
- place_floor(y, x);
- }
- }
- }
-}
-
-
-/*
- * Store routine for the fractal cave generator
- * this routine probably should be an inline function or a macro
- */
-static void store_height(int x, int y, int x0, int y0, byte val,
- int xhsize, int yhsize, int cutoff)
-{
- /* Only write to points that are "blank" */
- if (cave[y + y0 - yhsize][x + x0 - xhsize].feat != 255) return;
-
- /* If on boundary set val > cutoff so walls are not as square */
- if (((x == 0) || (y == 0) || (x == xhsize * 2) || (y == yhsize * 2)) &&
- (val <= cutoff)) val = cutoff + 1;
-
- /* Store the value in height-map format */
- /* Meant to be temporary, hence no cave_set_feat */
- cave[y + y0 - yhsize][x + x0 - xhsize].feat = val;
-
- return;
-}
-
-
-
-/*
- * Explanation of the plasma fractal algorithm:
- *
- * A grid of points is created with the properties of a 'height-map'
- * This is done by making the corners of the grid have a random value.
- * The grid is then subdivided into one with twice the resolution.
- * The new points midway between two 'known' points can be calculated
- * by taking the average value of the 'known' ones and randomly adding
- * or subtracting an amount proportional to the distance between those
- * points. The final 'middle' points of the grid are then calculated
- * by averaging all four of the originally 'known' corner points. An
- * random amount is added or subtracted from this to get a value of the
- * height at that point. The scaling factor here is adjusted to the
- * slightly larger distance diagonally as compared to orthogonally.
- *
- * This is then repeated recursively to fill an entire 'height-map'
- * A rectangular map is done the same way, except there are different
- * scaling factors along the x and y directions.
- *
- * A hack to change the amount of correlation between points is done using
- * the grd variable. If the current step size is greater than grd then
- * the point will be random, otherwise it will be calculated by the
- * above algorithm. This makes a maximum distance at which two points on
- * the height map can affect each other.
- *
- * How fractal caves are made:
- *
- * When the map is complete, a cut-off value is used to create a cave.
- * Heights below this value are "floor", and heights above are "wall".
- * This also can be used to create lakes, by adding more height levels
- * representing shallow and deep water/ lava etc.
- *
- * The grd variable affects the width of passages.
- * The roug variable affects the roughness of those passages
- *
- * The tricky part is making sure the created cave is connected. This
- * is done by 'filling' from the inside and only keeping the 'filled'
- * floor. Walls bounding the 'filled' floor are also kept. Everything
- * else is converted to the normal granite FEAT_WALL_EXTRA.
- */
-
-
-/*
- * Note that this uses the cave.feat array in a very hackish way
- * the values are first set to zero, and then each array location
- * is used as a "heightmap"
- * The heightmap then needs to be converted back into the "feat" format.
- *
- * grd=level at which fractal turns on. smaller gives more mazelike caves
- * roug=roughness level. 16=normal. higher values make things more
- * convoluted small values are good for smooth walls.
- * size=length of the side of the square cave system.
- */
-
-void generate_hmap(int y0, int x0, int xsiz, int ysiz, int grd,
- int roug, int cutoff)
-{
- int xhsize, yhsize, xsize, ysize, maxsize;
-
- /*
- * fixed point variables- these are stored as 256 x normal value
- * this gives 8 binary places of fractional part + 8 places of normal part
- */
- u16b xstep, xhstep, ystep, yhstep, i, j, diagsize, xxsize, yysize;
-
-
- /* Redefine size so can change the value if out of range */
- xsize = xsiz;
- ysize = ysiz;
-
- /* Paranoia about size of the system of caves*/
- if (xsize > 254) xsize = 254;
- if (xsize < 4) xsize = 4;
- if (ysize > 254) ysize = 254;
- if (ysize < 4) ysize = 4;
-
- /* Get offsets to middle of array */
- xhsize = xsize / 2;
- yhsize = ysize / 2;
-
- /* Fix rounding problem */
- xsize = xhsize * 2;
- ysize = yhsize * 2;
-
- /*
- * Scale factor for middle points:
- * About sqrt(2)*256 - correct for a square lattice
- * approximately correct for everything else.
- */
- diagsize = 362;
-
- /* Maximum of xsize and ysize */
- maxsize = (xsize > ysize) ? xsize : ysize;
-
- /* Clear the section */
- for (i = 0; i <= xsize; i++)
- {
- for (j = 0; j <= ysize; j++)
- {
- cave_type *c_ptr;
-
- /* Access the grid */
- c_ptr = &cave[j + y0 - yhsize][i + x0 - xhsize];
-
- /* 255 is a flag for "not done yet" */
- c_ptr->feat = 255;
-
- /* Clear icky flag because may be redoing the cave */
- c_ptr->info &= ~(CAVE_ICKY);
- }
- }
-
- /* Set the corner values just in case grd>size. */
- store_height(0, 0, x0, y0, maxsize, xhsize, yhsize, cutoff);
- store_height(0, ysize, x0, y0, maxsize, xhsize, yhsize, cutoff);
- store_height(xsize, 0, x0, y0, maxsize, xhsize, yhsize, cutoff);
- store_height(xsize, ysize, x0, y0, maxsize, xhsize, yhsize, cutoff);
-
- /* Set the middle square to be an open area. */
- store_height(xhsize, yhsize, x0, y0, 0, xhsize, yhsize, cutoff);
-
-
- /* Initialise the step sizes */
- xstep = xhstep = xsize * 256;
- ystep = yhstep = ysize * 256;
- xxsize = xsize * 256;
- yysize = ysize * 256;
-
- /*
- * Fill in the rectangle with fractal height data - like the
- * 'plasma fractal' in fractint
- */
- while ((xstep / 256 > 1) || (ystep / 256 > 1))
- {
- /* Halve the step sizes */
- xstep = xhstep;
- xhstep /= 2;
- ystep = yhstep;
- yhstep /= 2;
-
- /* Middle top to bottom */
- for (i = xhstep; i <= xxsize - xhstep; i += xstep)
- {
- for (j = 0; j <= yysize; j += ystep)
- {
- /* If greater than 'grid' level then is random */
- if (xhstep / 256 > grd)
- {
- store_height(i / 256, j / 256, x0, y0, randint(maxsize),
- xhsize, yhsize, cutoff);
- }
- else
- {
- cave_type *l, *r;
- byte val;
-
- /* Left point */
- l = &cave[j / 256 + y0 - yhsize][(i - xhstep) / 256 + x0 - xhsize];
-
- /* Right point */
- r = &cave[j / 256 + y0 - yhsize][(i + xhstep) / 256 + x0 - xhsize];
-
- /* Average of left and right points + random bit */
- val = (l->feat + r->feat) / 2 +
- (randint(xstep / 256) - xhstep / 256) * roug / 16;
-
- store_height(i / 256, j / 256, x0, y0, val,
- xhsize, yhsize, cutoff);
- }
- }
- }
-
-
- /* Middle left to right */
- for (j = yhstep; j <= yysize - yhstep; j += ystep)
- {
- for (i = 0; i <= xxsize; i += xstep)
- {
- /* If greater than 'grid' level then is random */
- if (xhstep / 256 > grd)
- {
- store_height(i / 256, j / 256, x0, y0, randint(maxsize),
- xhsize, yhsize, cutoff);
- }
- else
- {
- cave_type *u, *d;
- byte val;
-
- /* Up point */
- u = &cave[(j - yhstep) / 256 + y0 - yhsize][i / 256 + x0 - xhsize];
-
- /* Down point */
- d = &cave[(j + yhstep) / 256 + y0 - yhsize][i / 256 + x0 - xhsize];
-
- /* Average of up and down points + random bit */
- val = (u->feat + d->feat) / 2 +
- (randint(ystep / 256) - yhstep / 256) * roug / 16;
-
- store_height(i / 256, j / 256, x0, y0, val,
- xhsize, yhsize, cutoff);
- }
- }
- }
-
- /* Center */
- for (i = xhstep; i <= xxsize - xhstep; i += xstep)
- {
- for (j = yhstep; j <= yysize - yhstep; j += ystep)
- {
- /* If greater than 'grid' level then is random */
- if (xhstep / 256 > grd)
- {
- store_height(i / 256, j / 256, x0, y0, randint(maxsize),
- xhsize, yhsize, cutoff);
- }
- else
- {
- cave_type *ul, *dl, *ur, *dr;
- byte val;
-
- /* Up-left point */
- ul = &cave[(j - yhstep) / 256 + y0 - yhsize][(i - xhstep) / 256 + x0 - xhsize];
-
- /* Down-left point */
- dl = &cave[(j + yhstep) / 256 + y0 - yhsize][(i - xhstep) / 256 + x0 - xhsize];
-
- /* Up-right point */
- ur = &cave[(j - yhstep) / 256 + y0 - yhsize][(i + xhstep) / 256 + x0 - xhsize];
-
- /* Down-right point */
- dr = &cave[(j + yhstep) / 256 + y0 - yhsize][(i + xhstep) / 256 + x0 - xhsize];
-
- /*
- * average over all four corners + scale by diagsize to
- * reduce the effect of the square grid on the shape
- * of the fractal
- */
- val = (ul->feat + dl->feat + ur->feat + dr->feat) / 4 +
- (randint(xstep / 256) - xhstep / 256) *
- (diagsize / 16) / 256 * roug;
-
- store_height(i / 256, j / 256, x0, y0, val,
- xhsize, yhsize , cutoff);
- }
- }
- }
- }
-}
-
-
-/*
- * Convert from height-map back to the normal Angband cave format
- */
-static bool_ hack_isnt_wall(int y, int x, int cutoff)
-{
- /* Already done */
- if (cave[y][x].info & CAVE_ICKY)
- {
- return (FALSE);
- }
-
- else
- {
- /* Show that have looked at this square */
- cave[y][x].info |= (CAVE_ICKY);
-
- /* If less than cutoff then is a floor */
- if (cave[y][x].feat <= cutoff)
- {
- place_floor(y, x);
- return (TRUE);
- }
-
- /* If greater than cutoff then is a wall */
- else
- {
- cave_set_feat(y, x, feat_wall_outer);
- return (FALSE);
- }
- }
-}
-
-
-/*
- * Quick and nasty fill routine used to find the connected region
- * of floor in the middle of the cave
- */
-static void fill_hack(int y0, int x0, int y, int x, int xsize, int ysize,
- int cutoff, int *amount)
-{
- int i, j;
-
- /* check 8 neighbours +self (self is caught in the isnt_wall function) */
- for (i = -1; i <= 1; i++)
- {
- for (j = -1; j <= 1; j++)
- {
- /* If within bounds */
- if ((x + i > 0) && (x + i < xsize) &&
- (y + j > 0) && (y + j < ysize))
- {
- /* If not a wall or floor done before */
- if (hack_isnt_wall(y + j + y0 - ysize / 2,
- x + i + x0 - xsize / 2, cutoff))
- {
- /* then fill from the new point*/
- fill_hack(y0, x0, y + j, x + i, xsize, ysize,
- cutoff, amount);
-
- /* keep tally of size of cave system */
- (*amount)++;
- }
- }
-
- /* Affect boundary */
- else
- {
- cave[y0 + y + j - ysize / 2][x0 + x + i - xsize / 2].info |= (CAVE_ICKY);
- }
- }
- }
-}
-
-
-bool_ generate_fracave(int y0, int x0, int xsize, int ysize,
- int cutoff, bool_ light, bool_ room)
-{
- int x, y, i, amount, xhsize, yhsize;
- cave_type *c_ptr;
-
- /* Offsets to middle from corner */
- xhsize = xsize / 2;
- yhsize = ysize / 2;
-
- /* Reset tally */
- amount = 0;
-
- /*
- * Select region connected to center of cave system
- * this gets rid of alot of isolated one-sqaures that
- * can make teleport traps instadeaths...
- */
- fill_hack(y0, x0, yhsize, xhsize, xsize, ysize, cutoff, &amount);
-
- /* If tally too small, try again */
- if (amount < 10)
- {
- /* Too small -- clear area and try again later */
- for (x = 0; x <= xsize; ++x)
- {
- for (y = 0; y < ysize; ++y)
- {
- place_filler(y0 + y - yhsize, x0 + x - xhsize);
- cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY | CAVE_ROOM);
- }
- }
- return FALSE;
- }
-
-
- /*
- * Do boundaries -- check to see if they are next to a filled region
- * If not then they are set to normal granite
- * If so then they are marked as room walls
- */
- for (i = 0; i <= xsize; ++i)
- {
- /* Access top boundary grid */
- c_ptr = &cave[0 + y0 - yhsize][i + x0 - xhsize];
-
- /* Next to a 'filled' region? -- set to be room walls */
- if (c_ptr->info & CAVE_ICKY)
- {
- cave_set_feat(0 + y0 - yhsize, i + x0 - xhsize, feat_wall_outer);
-
- if (light) c_ptr->info |= (CAVE_GLOW);
- if (room)
- {
- c_ptr->info |= (CAVE_ROOM);
- }
- else
- {
- place_filler(0 + y0 - yhsize, i + x0 - xhsize);
- }
- }
-
- /* Outside of the room -- set to be normal granite */
- else
- {
- place_filler(0 + y0 - yhsize, i + x0 - xhsize);
- }
-
- /* Clear the icky flag -- don't need it any more */
- c_ptr->info &= ~(CAVE_ICKY);
-
-
- /* Access bottom boundary grid */
- c_ptr = &cave[ysize + y0 - yhsize][i + x0 - xhsize];
-
- /* Next to a 'filled' region? -- set to be room walls */
- if (c_ptr->info & CAVE_ICKY)
- {
- cave_set_feat(ysize + y0 - yhsize, i + x0 - xhsize, feat_wall_outer);
- if (light) c_ptr->info |= (CAVE_GLOW);
- if (room)
- {
- c_ptr->info |= (CAVE_ROOM);
- }
- else
- {
- place_filler(ysize + y0 - yhsize, i + x0 - xhsize);
- }
- }
-
- /* Outside of the room -- set to be normal granite */
- else
- {
- place_filler(ysize + y0 - yhsize, i + x0 - xhsize);
- }
-
- /* Clear the icky flag -- don't need it any more */
- c_ptr->info &= ~(CAVE_ICKY);
- }
-
-
- /* Do the left and right boundaries minus the corners (done above) */
- for (i = 1; i < ysize; ++i)
- {
- /* Access left boundary grid */
- c_ptr = &cave[i + y0 - yhsize][0 + x0 - xhsize];
-
- /* Next to a 'filled' region? -- set to be room walls */
- if (c_ptr->info & CAVE_ICKY)
- {
- cave_set_feat(i + y0 - yhsize, 0 + x0 - xhsize, feat_wall_outer);
- if (light) c_ptr->info |= (CAVE_GLOW);
- if (room)
- {
- c_ptr->info |= (CAVE_ROOM);
- }
- else
- {
- place_filler(i + y0 - yhsize, 0 + x0 - xhsize);
- }
- }
-
- /* Outside of the room -- set to be normal granite */
- else
- {
- place_filler(i + y0 - yhsize, 0 + x0 - xhsize);
- }
-
- /* Clear the icky flag -- don't need it any more */
- c_ptr->info &= ~(CAVE_ICKY);
-
-
- /* Access left boundary grid */
- c_ptr = &cave[i + y0 - yhsize][xsize + x0 - xhsize];
-
- /* Next to a 'filled' region? -- set to be room walls */
- if (c_ptr->info & CAVE_ICKY)
- {
- cave_set_feat(i + y0 - yhsize, xsize + x0 - xhsize, feat_wall_outer);
- if (light) c_ptr->info |= (CAVE_GLOW);
- if (room)
- {
- c_ptr->info |= (CAVE_ROOM);
- }
- else
- {
- place_filler(i + y0 - yhsize, xsize + x0 - xhsize);
- }
- }
-
- /* Outside of the room -- set to be normal granite */
- else
- {
- place_filler(i + y0 - yhsize, xsize + x0 - xhsize);
- }
-
- /* Clear the icky flag -- don't need it any more */
- c_ptr->info &= ~(CAVE_ICKY);
- }
-
-
- /*
- * Do the rest: convert back to the normal format
- * In other variants, may want to check to see if cave.feat< some value
- * if so, set to be water:- this will make interesting pools etc.
- * (I don't do this for standard Angband.)
- */
- for (x = 1; x < xsize; ++x)
- {
- for (y = 1; y < ysize; ++y)
- {
- /* Access the grid */
- c_ptr = &cave[y + y0 - yhsize][x + x0 - xhsize];
-
- /* A floor grid to be converted */
- if ((f_info[c_ptr->feat].flags1 & FF1_FLOOR) &&
- (c_ptr->info & CAVE_ICKY))
-
- {
- /* Clear the icky flag in the filled region */
- c_ptr->info &= ~(CAVE_ICKY);
-
- /* Set appropriate flags */
- if (light) c_ptr->info |= (CAVE_GLOW);
- if (room) c_ptr->info |= (CAVE_ROOM);
- }
-
- /* A wall grid to be convereted */
- else if ((c_ptr->feat == feat_wall_outer) &&
- (c_ptr->info & CAVE_ICKY))
- {
- /* Clear the icky flag in the filled region */
- c_ptr->info &= ~(CAVE_ICKY);
-
- /* Set appropriate flags */
- if (light) c_ptr->info |= (CAVE_GLOW);
- if (room)
- {
- c_ptr->info |= (CAVE_ROOM);
- }
- else
- {
- place_filler(y + y0 - yhsize, x + x0 - xhsize);
- }
- }
-
- /* None of the above -- clear the unconnected regions */
- else
- {
- place_filler(y + y0 - yhsize, x + x0 - xhsize);
- c_ptr->info &= ~(CAVE_ICKY | CAVE_ROOM);
- }
- }
- }
-
- /*
- * XXX XXX XXX There is a slight problem when tunnels pierce the caves:
- * Extra doors appear inside the system. (Its not very noticeable though.)
- * This can be removed by "filling" from the outside in. This allows
- * a separation from FEAT_WALL_OUTER with FEAT_WALL_INNER. (Internal
- * walls are F.W.OUTER instead.)
- * The extra effort for what seems to be only a minor thing (even
- * non-existant if you think of the caves not as normal rooms, but as
- * holes in the dungeon), doesn't seem worth it.
- */
-
- return (TRUE);
-}
-
-
-/*
- * Makes a cave system in the center of the dungeon
- */
-static void build_cavern(void)
-{
- int grd, roug, cutoff, xsize, ysize, x0, y0;
- bool_ done, light, room;
-
- light = done = room = FALSE;
- if (dun_level <= randint(25)) light = TRUE;
-
- /* Make a cave the size of the dungeon */
- xsize = cur_wid - 1;
- ysize = cur_hgt - 1;
- x0 = xsize / 2;
- y0 = ysize / 2;
-
- /* Paranoia: make size even */
- xsize = x0 * 2;
- ysize = y0 * 2;
-
- while (!done)
- {
- /* Testing values for these parameters: feel free to adjust */
- grd = 1 << (randint(4) + 4);
-
- /* Want average of about 16 */
- roug = randint(8) * randint(4);
-
- /* About size/2 */
- cutoff = xsize / 2;
-
- /* Make it */
- generate_hmap(y0, x0, xsize, ysize, grd, roug, cutoff);
-
- /* Convert to normal format+ clean up*/
- done = generate_fracave(y0, x0, xsize, ysize, cutoff, light, room);
- }
-}
-
-/*
- * Driver routine to create fractal cave system
- */
-static void build_type10(int by0, int bx0)
-{
- int grd, roug, cutoff, xsize, ysize, y0, x0;
-
- bool_ done, light, room;
-
- /* Get size: note 'Evenness'*/
- xsize = randint(22) * 2 + 6;
- ysize = randint(15) * 2 + 6;
-
- /* Try to allocate space for room. If fails, exit */
- if (!room_alloc(xsize + 1, ysize + 1, FALSE, by0, bx0, &x0, &y0)) return;
-
- light = done = FALSE;
- room = TRUE;
-
- if (dun_level <= randint(25)) light = TRUE;
-
- while (!done)
- {
- /*
- * Note: size must be even or there are rounding problems
- * This causes the tunnels not to connect properly to the room
- */
-
- /* Testing values for these parameters feel free to adjust */
- grd = 1 << (randint(4));
-
- /* Want average of about 16 */
- roug = randint(8) * randint(4);
-
- /* About size/2 */
- cutoff = randint(xsize / 4) + randint(ysize / 4) +
- randint(xsize / 4) + randint(ysize / 4);
-
- /* Make it */
- generate_hmap(y0, x0, xsize, ysize, grd, roug, cutoff);
-
- /* Convert to normal format + clean up*/
- done = generate_fracave(y0, x0, xsize, ysize, cutoff, light, room);
- }
-}
-
-
-/*
- * Random vault generation from Z 2.5.1
- */
-
-/*
- * Make a very small room centred at (x0, y0)
- *
- * This is used in crypts, and random elemental vaults.
- *
- * Note - this should be used only on allocated regions
- * within another room.
- */
-static void build_small_room(int x0, int y0)
-{
- build_rectangle(y0 - 1, x0 - 1, y0 + 1, x0 + 1, feat_wall_inner, CAVE_ROOM);
-
- /* Place a secret door on one side */
- switch (rand_int(4))
- {
- case 0:
- {
- place_secret_door(y0, x0 - 1);
- break;
- }
-
- case 1:
- {
- place_secret_door(y0, x0 + 1);
- break;
- }
-
- case 2:
- {
- place_secret_door(y0 - 1, x0);
- break;
- }
-
- case 3:
- {
- place_secret_door(y0 + 1, x0);
- break;
- }
- }
-
- /* Add inner open space */
- place_floor(y0, x0);
-}
-
-
-/*
- * Add a door to a location in a random vault
- *
- * Note that range checking has to be done in the calling routine.
- *
- * The doors must be INSIDE the allocated region.
- */
-static void add_door(int x, int y)
-{
- /* Need to have a wall in the center square */
- if (cave[y][x].feat != feat_wall_outer) return;
-
- /*
- * Look at:
- * x#x
- * .#.
- * x#x
- *
- * where x=don't care
- * .=floor, #=wall
- */
-
- if (get_is_floor(x, y - 1) && get_is_floor(x, y + 1) &&
- (cave[y][x - 1].feat == feat_wall_outer) &&
- (cave[y][x + 1].feat == feat_wall_outer))
- {
- /* secret door */
- place_secret_door(y, x);
-
- /* set boundarys so don't get wide doors */
- place_filler(y, x - 1);
- place_filler(y, x + 1);
- }
-
-
- /*
- * Look at:
- * x#x
- * .#.
- * x#x
- *
- * where x = don't care
- * .=floor, #=wall
- */
- if ((cave[y - 1][x].feat == feat_wall_outer) &&
- (cave[y + 1][x].feat == feat_wall_outer) &&
- get_is_floor(x - 1, y) && get_is_floor(x + 1, y))
- {
- /* secret door */
- place_secret_door(y, x);
-
- /* set boundarys so don't get wide doors */
- place_filler(y - 1, x);
- place_filler(y + 1, x);
- }
-}
-
-
-/*
- * Fill the empty areas of a room with treasure and monsters.
- */
-static void fill_treasure(int x1, int x2, int y1, int y2, int difficulty)
-{
- int x, y, cx, cy, size;
- s32b value;
-
- /* center of room:*/
- cx = (x1 + x2) / 2;
- cy = (y1 + y2) / 2;
-
- /* Rough measure of size of vault= sum of lengths of sides */
- size = abs(x2 - x1) + abs(y2 - y1);
-
- for (x = x1; x <= x2; x++)
- {
- for (y = y1; y <= y2; y++)
- {
- /*
- * Thing added based on distance to center of vault
- * Difficulty is 1-easy to 10-hard
- */
- value = (((s32b)distance(cx, cy, x, y) * 100) / size) +
- randint(10) - difficulty;
-
- /* Hack -- Empty square part of the time */
- if ((randint(100) - difficulty * 3) > 50) value = 20;
-
- /* If floor, shallow water or lava */
- if (get_is_floor(x, y) ||
- (cave[y][x].feat == FEAT_SHAL_WATER) ||
- (cave[y][x].feat == FEAT_SHAL_LAVA))
- {
- /* The smaller 'value' is, the better the stuff */
- if (value < 0)
- {
- /* Meanest monster + treasure */
- monster_level = dun_level + 40;
- place_monster(y, x, TRUE, TRUE);
- monster_level = dun_level;
- object_level = dun_level + 20;
- place_object(y, x, TRUE, FALSE, OBJ_FOUND_FLOOR);
- object_level = dun_level;
- }
- else if (value < 5)
- {
- /* Mean monster +treasure */
- monster_level = dun_level + 20;
- place_monster(y, x, TRUE, TRUE);
- monster_level = dun_level;
- object_level = dun_level + 10;
- place_object(y, x, TRUE, FALSE, OBJ_FOUND_FLOOR);
- object_level = dun_level;
- }
- else if (value < 10)
- {
- /* Monster */
- monster_level = dun_level + 9;
- place_monster(y, x, TRUE, TRUE);
- monster_level = dun_level;
- }
- else if (value < 17)
- {
- /* Intentional Blank space */
-
- /*
- * (Want some of the vault to be empty
- * so have room for group monsters.
- * This is used in the hack above to lower
- * the density of stuff in the vault.)
- */
- }
- else if (value < 23)
- {
- /* Object or trap */
- if (rand_int(100) < 25)
- {
- place_object(y, x, FALSE, FALSE, OBJ_FOUND_FLOOR);
- }
- else
- {
- place_trap(y, x);
- }
- }
- else if (value < 30)
- {
- /* Monster and trap */
- monster_level = dun_level + 5;
- place_monster(y, x, TRUE, TRUE);
- monster_level = dun_level;
- place_trap(y, x);
- }
- else if (value < 40)
- {
- /* Monster or object */
- if (rand_int(100) < 50)
- {
- monster_level = dun_level + 3;
- place_monster(y, x, TRUE, TRUE);
- monster_level = dun_level;
- }
- if (rand_int(100) < 50)
- {
- object_level = dun_level + 7;
- place_object(y, x, FALSE, FALSE, OBJ_FOUND_FLOOR);
- object_level = dun_level;
- }
- }
- else if (value < 50)
- {
- /* Trap */
- place_trap(y, x);
- }
- else
- {
- /* Various Stuff */
-
- /* 20% monster, 40% trap, 20% object, 20% blank space */
- if (rand_int(100) < 20)
- {
- place_monster(y, x, TRUE, TRUE);
- }
- else if (rand_int(100) < 50)
- {
- place_trap(y, x);
- }
- else if (rand_int(100) < 50)
- {
- place_object(y, x, FALSE, FALSE, OBJ_FOUND_FLOOR);
- }
- }
-
- }
- }
- }
-}
-
-
-/*
- * Creates a random vault that looks like a collection of bubbles
- *
- * It works by getting a set of coordinates that represent the center of
- * each bubble. The entire room is made by seeing which bubble center is
- * closest. If two centers are equidistant then the square is a wall,
- * otherwise it is a floor. The only exception is for squares really
- * near a center, these are always floor.
- * (It looks better than without this check.)
- *
- * Note: If two centers are on the same point then this algorithm will create a
- * blank bubble filled with walls. - This is prevented from happening.
- */
-
-#define BUBBLENUM 10 /* number of bubbles */
-
-static void build_bubble_vault(int x0, int y0, int xsize, int ysize)
-{
- /* array of center points of bubbles */
- coord center[BUBBLENUM];
-
- int i, j, k, x = 0, y = 0;
- u16b min1, min2, temp;
- bool_ done;
-
- /* Offset from center to top left hand corner */
- int xhsize = xsize / 2;
- int yhsize = ysize / 2;
-
- if (cheat_room) msg_print("Bubble Vault");
-
- /* Allocate center of bubbles */
- center[0].x = randint(xsize - 3) + 1;
- center[0].y = randint(ysize - 3) + 1;
-
- for (i = 1; i < BUBBLENUM; i++)
- {
- done = FALSE;
-
- /* Get center and check to see if it is unique */
- for (k = 0; !done && (k < 2000); k++)
- {
- done = TRUE;
-
- x = randint(xsize - 3) + 1;
- y = randint(ysize - 3) + 1;
-
- for (j = 0; j < i; j++)
- {
- /* Rough test to see if there is an overlap */
- if ((x == center[j].x) || (y == center[j].y)) done = FALSE;
- }
- }
-
- /* Too many failures */
- if (k >= 2000) return;
-
- center[i].x = x;
- center[i].y = y;
- }
-
- build_rectangle(y0 - yhsize, x0 - xhsize,
- y0 - yhsize + ysize - 1, x0 - xhsize + xsize - 1,
- feat_wall_outer, CAVE_ROOM | CAVE_ICKY);
-
- /* Fill in middle with bubbles */
- for (x = 1; x < xsize - 1; x++)
- {
- for (y = 1; y < ysize - 1; y++)
- {
- cave_type *c_ptr;
-
- /* Get distances to two closest centers */
-
- /* Initialise */
- min1 = distance(x, y, center[0].x, center[0].y);
- min2 = distance(x, y, center[1].x, center[1].y);
-
- if (min1 > min2)
- {
- /* Swap if in wrong order */
- temp = min1;
- min1 = min2;
- min2 = temp;
- }
-
- /* Scan the rest */
- for (i = 2; i < BUBBLENUM; i++)
- {
- temp = distance(x, y, center[i].x, center[i].y);
-
- if (temp < min1)
- {
- /* Smallest */
- min2 = min1;
- min1 = temp;
- }
- else if (temp < min2)
- {
- /* Second smallest */
- min2 = temp;
- }
- }
-
- /* Access the grid */
- c_ptr = &cave[y + y0 - yhsize][x + x0 - xhsize];
-
- /*
- * Boundary at midpoint+ not at inner region of bubble
- *
- * SCSCSC: was feat_wall_outer
- */
- if (((min2 - min1) <= 2) && (!(min1 < 3)))
- {
- place_filler(y + y0 - yhsize, x + x0 - xhsize);
- }
-
- /* Middle of a bubble */
- else
- {
- place_floor(y + y0 - yhsize, x + x0 - xhsize);
- }
-
- /* Clean up rest of flags */
- c_ptr->info |= (CAVE_ROOM | CAVE_ICKY);
- }
- }
-
- /* Try to add some random doors */
- for (i = 0; i < 500; i++)
- {
- x = randint(xsize - 3) - xhsize + x0 + 1;
- y = randint(ysize - 3) - yhsize + y0 + 1;
- add_door(x, y);
- }
-
- /* Fill with monsters and treasure, low difficulty */
- fill_treasure(x0 - xhsize + 1, x0 - xhsize + xsize - 2,
- y0 - yhsize + 1, y0 - yhsize + ysize - 2, randint(5));
-}
-
-
-/*
- * Convert FEAT_WALL_EXTRA (used by random vaults) to normal dungeon wall
- */
-static void convert_extra(int y1, int x1, int y2, int x2)
-{
- int x, y;
-
- for (x = x1; x <= x2; x++)
- {
- for (y = y1; y <= y2; y++)
- {
- if (cave[y][x].feat == FEAT_WALL_OUTER)
- {
- place_filler(y, x);
- }
- }
- }
-}
-
-
-/*
- * Overlay a rectangular room given its bounds
- *
- * This routine is used by build_room_vault (hence FEAT_WALL_OUTER)
- * The area inside the walls is not touched: only granite is removed
- * and normal walls stay
- */
-static void build_room(int x1, int x2, int y1, int y2)
-{
- int x, y, xsize, ysize, temp;
-
- /* Check if rectangle has no width */
- if ((x1 == x2) || (y1 == y2)) return;
-
- /* initialize */
- if (x1 > x2)
- {
- /* Swap boundaries if in wrong order */
- temp = x1;
- x1 = x2;
- x2 = temp;
- }
-
- if (y1 > y2)
- {
- /* Swap boundaries if in wrong order */
- temp = y1;
- y1 = y2;
- y2 = temp;
- }
-
- /* Get total widths */
- xsize = x2 - x1;
- ysize = y2 - y1;
-
- build_rectangle(y1, x1, y2, x2, feat_wall_outer, CAVE_ROOM | CAVE_ICKY);
-
- /* Middle */
- for (x = 1; x < xsize; x++)
- {
- for (y = 1; y < ysize; y++)
- {
- if (cave[y1 + y][x1 + x].feat == FEAT_WALL_OUTER)
- {
- /* Clear the untouched region */
- place_floor(y1 + y, x1 + x);
- cave[y1 + y][x1 + x].info |= (CAVE_ROOM | CAVE_ICKY);
- }
- else
- {
- /* Make it a room -- but don't touch */
- cave[y1 + y][x1 + x].info |= (CAVE_ROOM | CAVE_ICKY);
- }
- }
- }
-}
-
-
-/*
- * Create a random vault that looks like a collection of overlapping rooms
- */
-static void build_room_vault(int x0, int y0, int xsize, int ysize)
-{
- int i, x1, x2, y1, y2, xhsize, yhsize;
-
- /* Get offset from center */
- xhsize = xsize / 2;
- yhsize = ysize / 2;
-
- if (cheat_room) msg_print("Room Vault");
-
- /* Fill area so don't get problems with arena levels */
- for (x1 = 0; x1 <= xsize; x1++)
- {
- int x = x0 - xhsize + x1;
-
- for (y1 = 0; y1 <= ysize; y1++)
- {
- int y = y0 - yhsize + y1;
-
- cave_set_feat(y, x, FEAT_WALL_OUTER);
- cave[y][x].info &= ~(CAVE_ICKY);
- }
- }
-
- /* Add ten random rooms */
- for (i = 0; i < 10; i++)
- {
- x1 = randint(xhsize) * 2 + x0 - xhsize;
- x2 = randint(xhsize) * 2 + x0 - xhsize;
- y1 = randint(yhsize) * 2 + y0 - yhsize;
- y2 = randint(yhsize) * 2 + y0 - yhsize;
-
- build_room(x1, x2, y1, y2);
- }
-
- convert_extra(y0 - yhsize, x0 - xhsize, y0 - yhsize + ysize,
- x0 - xhsize + xsize);
-
- /* Add some random doors */
- for (i = 0; i < 500; i++)
- {
- x1 = randint(xsize - 2) - xhsize + x0 + 1;
- y1 = randint(ysize - 2) - yhsize + y0 + 1;
- add_door(x1, y1);
- }
-
- /* Fill with monsters and treasure, high difficulty */
- fill_treasure(x0 - xhsize + 1, x0 - xhsize + xsize - 1,
- y0 - yhsize + 1, y0 - yhsize + ysize - 1, randint(5) + 5);
-}
-
-
-/*
- * Create a random vault out of a fractal cave
- */
-static void build_cave_vault(int x0, int y0, int xsiz, int ysiz)
-{
- int grd, roug, cutoff, xhsize, yhsize, xsize, ysize, x, y;
- bool_ done, light, room;
-
- /* Round to make sizes even */
- xhsize = xsiz / 2;
- yhsize = ysiz / 2;
- xsize = xhsize * 2;
- ysize = yhsize * 2;
-
- if (cheat_room) msg_print("Cave Vault");
-
- light = done = FALSE;
- room = TRUE;
-
- while (!done)
- {
- /* Testing values for these parameters feel free to adjust */
- grd = 1 << rand_int(4);
-
- /* Want average of about 16 */
- roug = randint(8) * randint(4);
-
- /* About size/2 */
- cutoff = randint(xsize / 4) + randint(ysize / 4) +
- randint(xsize / 4) + randint(ysize / 4);
-
- /* Make it */
- generate_hmap(y0, x0, xsize, ysize, grd, roug, cutoff);
-
- /* Convert to normal format + clean up */
- done = generate_fracave(y0, x0, xsize, ysize, cutoff, light, room);
- }
-
- /* Set icky flag because is a vault */
- for (x = 0; x <= xsize; x++)
- {
- for (y = 0; y <= ysize; y++)
- {
- cave[y0 - yhsize + y][x0 - xhsize + x].info |= CAVE_ICKY;
- }
- }
-
- /* Fill with monsters and treasure, low difficulty */
- fill_treasure(x0 - xhsize + 1, x0 - xhsize + xsize - 1,
- y0 - yhsize + 1, y0 - yhsize + ysize - 1, randint(5));
-}
-
-
-/*
- * Maze vault -- rectangular labyrinthine rooms
- *
- * maze vault uses two routines:
- * r_visit - a recursive routine that builds the labyrinth
- * build_maze_vault - a driver routine that calls r_visit and adds
- * monsters, traps and treasure
- *
- * The labyrinth is built by creating a spanning tree of a graph.
- * The graph vertices are at
- * (x, y) = (2j + x1, 2k + y1) j = 0,...,m-1 k = 0,...,n-1
- * and the edges are the vertical and horizontal nearest neighbors.
- *
- * The spanning tree is created by performing a suitably randomized
- * depth-first traversal of the graph. The only adjustable parameter
- * is the rand_int(3) below; it governs the relative density of
- * twists and turns in the labyrinth: smaller number, more twists.
- */
-static void r_visit(int y1, int x1, int y2, int x2,
- int node, int dir, int *visited)
-{
- int i, j, m, n, temp, x, y, adj[4];
-
- /* Dimensions of vertex array */
- m = (x2 - x1) / 2 + 1;
- n = (y2 - y1) / 2 + 1;
-
- /* Mark node visited and set it to a floor */
- visited[node] = 1;
- x = 2 * (node % m) + x1;
- y = 2 * (node / m) + y1;
- place_floor(y, x);
-
- /* Setup order of adjacent node visits */
- if (rand_int(3) == 0)
- {
- /* Pick a random ordering */
- for (i = 0; i < 4; i++)
- {
- adj[i] = i;
- }
- for (i = 0; i < 4; i++)
- {
- j = rand_int(4);
- temp = adj[i];
- adj[i] = adj[j];
- adj[j] = temp;
- }
- dir = adj[0];
- }
- else
- {
- /* Pick a random ordering with dir first */
- adj[0] = dir;
- for (i = 1; i < 4; i++)
- {
- adj[i] = i;
- }
- for (i = 1; i < 4; i++)
- {
- j = 1 + rand_int(3);
- temp = adj[i];
- adj[i] = adj[j];
- adj[j] = temp;
- }
- }
-
- for (i = 0; i < 4; i++)
- {
- switch (adj[i])
- {
- /* (0,+) - check for bottom boundary */
- case 0:
- {
- if ((node / m < n - 1) && (visited[node + m] == 0))
- {
- place_floor(y + 1, x);
- r_visit(y1, x1, y2, x2, node + m, dir, visited);
- }
- break;
- }
-
- /* (0,-) - check for top boundary */
- case 1:
- {
- if ((node / m > 0) && (visited[node - m] == 0))
- {
- place_floor(y - 1, x);
- r_visit(y1, x1, y2, x2, node - m, dir, visited);
- }
- break;
- }
-
- /* (+,0) - check for right boundary */
- case 2:
- {
- if ((node % m < m - 1) && (visited[node + 1] == 0))
- {
- place_floor(y, x + 1);
- r_visit(y1, x1, y2, x2, node + 1, dir, visited);
- }
- break;
- }
-
- /* (-,0) - check for left boundary */
- case 3:
- {
- if ((node % m > 0) && (visited[node - 1] == 0))
- {
- place_floor(y, x - 1);
- r_visit(y1, x1, y2, x2, node - 1, dir, visited);
- }
- break;
- }
- }
- }
-}
-
-
-static void build_maze_vault(int x0, int y0, int xsize, int ysize)
-{
- int y, x, dy, dx;
- int y1, x1, y2, x2;
- int i, m, n, num_vertices, *visited;
- bool_ light;
- cave_type *c_ptr;
-
-
- if (cheat_room) msg_print("Maze Vault");
-
- /* Choose lite or dark */
- light = (dun_level <= randint(25));
-
- /* Pick a random room size - randomized by calling routine */
- dy = ysize / 2 - 1;
- dx = xsize / 2 - 1;
-
- y1 = y0 - dy;
- x1 = x0 - dx;
- y2 = y0 + dy;
- x2 = x0 + dx;
-
- /* Generate the room */
- for (y = y1 - 1; y <= y2 + 1; y++)
- {
- for (x = x1 - 1; x <= x2 + 1; x++)
- {
- c_ptr = &cave[y][x];
-
- c_ptr->info |= (CAVE_ROOM | CAVE_ICKY);
-
- if ((x == x1 - 1) || (x == x2 + 1) ||
- (y == y1 - 1) || (y == y2 + 1))
- {
- cave_set_feat(y, x, feat_wall_outer);
- }
- else
- {
- cave_set_feat(y, x, feat_wall_inner);
- }
- if (light) c_ptr->info |= (CAVE_GLOW);
- }
- }
-
- /* Dimensions of vertex array */
- m = dx + 1;
- n = dy + 1;
- num_vertices = m * n;
-
- /* Allocate an array for visited vertices */
- C_MAKE(visited, num_vertices, int);
-
- /* Initialise array of visited vertices */
- for (i = 0; i < num_vertices; i++)
- {
- visited[i] = 0;
- }
-
- /* Traverse the graph to create a spaning tree, pick a random root */
- r_visit(y1, x1, y2, x2, rand_int(num_vertices), 0, visited);
-
- /* Fill with monsters and treasure, low difficulty */
- fill_treasure(x1, x2, y1, y2, randint(5));
-
- /* Free the array for visited vertices */
- C_FREE(visited, num_vertices, int);
-}
-
-
-/*
- * Build a "mini" checkerboard vault
- *
- * This is done by making a permanent wall maze and setting
- * the diagonal sqaures of the checker board to be granite.
- * The vault has two entrances on opposite sides to guarantee
- * a way to get in even if the vault abuts a side of the dungeon.
- */
-static void build_mini_c_vault(int x0, int y0, int xsize, int ysize)
-{
- int dy, dx;
- int y1, x1, y2, x2, y, x, total;
- int i, m, n, num_vertices;
- int *visited;
-
- if (cheat_room) msg_print("Mini Checker Board Vault");
-
- /* Pick a random room size */
- dy = ysize / 2 - 1;
- dx = xsize / 2 - 1;
-
- y1 = y0 - dy;
- x1 = x0 - dx;
- y2 = y0 + dy;
- x2 = x0 + dx;
-
-
- /* Generate the room */
- for (y = y1 - 1; y <= y2 + 1; y++)
- {
- for (x = x1 - 1; x <= x2 + 1; x++)
- {
- cave[y][x].info |= (CAVE_ROOM | CAVE_ICKY);
-
- /* Permanent walls */
- cave_set_feat(y, x, FEAT_PERM_INNER);
- }
- }
-
-
- /* Dimensions of vertex array */
- m = dx + 1;
- n = dy + 1;
- num_vertices = m * n;
-
- /* Allocate an array for visited vertices */
- C_MAKE(visited, num_vertices, int);
-
- /* Initialise array of visited vertices */
- for (i = 0; i < num_vertices; i++)
- {
- visited[i] = 0;
- }
-
- /* Traverse the graph to create a spannng tree, pick a random root */
- r_visit(y1, x1, y2, x2, rand_int(num_vertices), 0, visited);
-
- /* Make it look like a checker board vault */
- for (x = x1; x <= x2; x++)
- {
- for (y = y1; y <= y2; y++)
- {
- total = x - x1 + y - y1;
-
- /* If total is odd and is a floor, then make a wall */
- if ((total % 2 == 1) && get_is_floor(x, y))
- {
- cave_set_feat(y, x, feat_wall_inner);
- }
- }
- }
-
- /* Make a couple of entrances */
- if (rand_int(2) == 0)
- {
- /* Left and right */
- y = randint(dy) + dy / 2;
- cave_set_feat(y1 + y, x1 - 1, feat_wall_outer);
- cave_set_feat(y1 + y, x2 + 1, feat_wall_outer);
- }
- else
- {
- /* Top and bottom */
- x = randint(dx) + dx / 2;
- cave_set_feat(y1 - 1, x1 + x, feat_wall_outer);
- cave_set_feat(y2 + 1, x1 + x, feat_wall_outer);
- }
-
- /* Fill with monsters and treasure, highest difficulty */
- fill_treasure(x1, x2, y1, y2, 10);
-
- /* Free the array for visited vertices */
- C_FREE(visited, num_vertices, int);
-}
-
-
-/*
- * Build a town/ castle by using a recursive algorithm.
- * Basically divide each region in a probalistic way to create
- * smaller regions. When the regions get too small stop.
- *
- * The power variable is a measure of how well defended a region is.
- * This alters the possible choices.
- */
-static void build_recursive_room(int x1, int y1, int x2, int y2, int power)
-{
- int xsize, ysize;
- int x, y;
- int choice;
-
- /* Temp variables */
- int t1, t2, t3, t4;
-
- xsize = x2 - x1;
- ysize = y2 - y1;
-
- if ((power < 3) && (xsize > 12) && (ysize > 12))
- {
- /* Need outside wall +keep */
- choice = 1;
- }
- else
- {
- if (power < 10)
- {
- /* Make rooms + subdivide */
- if ((randint(10) > 2) && (xsize < 8) && (ysize < 8))
- {
- choice = 4;
- }
- else
- {
- choice = randint(2) + 1;
- }
- }
- else
- {
- /* Mostly subdivide */
- choice = randint(3) + 1;
- }
- }
-
- /* Based on the choice made above, do something */
- switch (choice)
- {
- /* Outer walls */
- case 1:
- {
- /* Top and bottom */
- for (x = x1; x <= x2; x++)
- {
- cave_set_feat(y1, x, feat_wall_outer);
- cave_set_feat(y2, x, feat_wall_outer);
- }
-
- /* Left and right */
- for (y = y1 + 1; y < y2; y++)
- {
- cave_set_feat(y, x1, feat_wall_outer);
- cave_set_feat(y, x2, feat_wall_outer);
- }
-
- /* Make a couple of entrances */
- if (rand_int(2) == 0)
- {
- /* Left and right */
- y = randint(ysize) + y1;
- place_floor(y, x1);
- place_floor(y, x2);
- }
- else
- {
- /* Top and bottom */
- x = randint(xsize) + x1;
- place_floor(y1, x);
- place_floor(y2, x);
- }
-
- /* Select size of keep */
- t1 = randint(ysize / 3) + y1;
- t2 = y2 - randint(ysize / 3);
- t3 = randint(xsize / 3) + x1;
- t4 = x2 - randint(xsize / 3);
-
- /* Do outside areas */
-
- /* Above and below keep */
- build_recursive_room(x1 + 1, y1 + 1, x2 - 1, t1, power + 1);
- build_recursive_room(x1 + 1, t2, x2 - 1, y2, power + 1);
-
- /* Left and right of keep */
- build_recursive_room(x1 + 1, t1 + 1, t3, t2 - 1, power + 3);
- build_recursive_room(t4, t1 + 1, x2 - 1, t2 - 1, power + 3);
-
- /* Make the keep itself: */
- x1 = t3;
- x2 = t4;
- y1 = t1;
- y2 = t2;
- xsize = x2 - x1;
- ysize = y2 - y1;
- power += 2;
-
- /* Fall through */
- }
-
- /* Try to build a room */
- case 4:
- {
- if ((xsize < 3) || (ysize < 3))
- {
- for (y = y1; y < y2; y++)
- {
- for (x = x1; x < x2; x++)
- {
- cave_set_feat(y, x, feat_wall_inner);
- }
- }
-
- /* Too small */
- return;
- }
-
- /* Make outside walls */
-
- /* Top and bottom */
- for (x = x1 + 1; x <= x2 - 1; x++)
- {
- cave_set_feat(y1 + 1, x, feat_wall_inner);
- cave_set_feat(y2 - 1, x, feat_wall_inner);
- }
-
- /* Left and right */
- for (y = y1 + 1; y <= y2 - 1; y++)
- {
- cave_set_feat(y, x1 + 1, feat_wall_inner);
- cave_set_feat(y, x2 - 1, feat_wall_inner);
- }
-
- /* Make a door */
- y = randint(ysize - 3) + y1 + 1;
-
- if (rand_int(2) == 0)
- {
- /* Left */
- place_floor(y, x1 + 1);
- }
- else
- {
- /* Right */
- place_floor(y, x2 - 1);
- }
-
- /* Build the room */
- build_recursive_room(x1 + 2, y1 + 2, x2 - 2, y2 - 2, power + 3);
-
- break;
- }
-
- /* Try and divide vertically */
- case 2:
- {
- if (xsize < 3)
- {
- /* Too small */
- for (y = y1; y < y2; y++)
- {
- for (x = x1; x < x2; x++)
- {
- cave_set_feat(y, x, feat_wall_inner);
- }
- }
- return;
- }
-
- t1 = randint(xsize - 2) + x1 + 1;
- build_recursive_room(x1, y1, t1, y2, power - 2);
- build_recursive_room(t1 + 1, y1, x2, y2, power - 2);
-
- break;
- }
-
- /* Try and divide horizontally */
- case 3:
- {
- if (ysize < 3)
- {
- /* Too small */
- for (y = y1; y < y2; y++)
- {
- for (x = x1; x < x2; x++)
- {
- cave_set_feat(y, x, feat_wall_inner);
- }
- }
- return;
- }
-
- t1 = randint(ysize - 2) + y1 + 1;
- build_recursive_room(x1, y1, x2, t1, power - 2);
- build_recursive_room(x1, t1 + 1, x2, y2, power - 2);
-
- break;
- }
- }
-}
-
-
-/*
- * Build a castle
- *
- * Clear the region and call the recursive room routine.
- *
- * This makes a vault that looks like a castle or city in the dungeon.
- */
-static void build_castle_vault(int x0, int y0, int xsize, int ysize)
-{
- int dy, dx;
- int y1, x1, y2, x2;
- int y, x;
-
- /* Pick a random room size */
- dy = ysize / 2 - 1;
- dx = xsize / 2 - 1;
-
- y1 = y0 - dy;
- x1 = x0 - dx;
- y2 = y0 + dy;
- x2 = x0 + dx;
-
- if (cheat_room) msg_print("Castle Vault");
-
- /* Generate the room */
- for (y = y1 - 1; y <= y2 + 1; y++)
- {
- for (x = x1 - 1; x <= x2 + 1; x++)
- {
- cave[y][x].info |= (CAVE_ROOM | CAVE_ICKY);
-
- /* Make everything a floor */
- place_floor(y, x);
- }
- }
-
- /* Make the castle */
- build_recursive_room(x1, y1, x2, y2, randint(5));
-
- /* Fill with monsters and treasure, low difficulty */
- fill_treasure(x1, x2, y1, y2, randint(3));
-}
-
-
-/*
- * Add outer wall to a floored region
- *
- * Note: no range checking is done so must be inside dungeon
- * This routine also stomps on doors
- */
-static void add_outer_wall(int x, int y, int light, int x1, int y1,
- int x2, int y2)
-{
- int i, j;
-
- if (!in_bounds(y, x)) return;
-
- /*
- * Hack -- Check to see if square has been visited before
- * if so, then exit (use room flag to do this)
- */
- if (cave[y][x].info & CAVE_ROOM) return;
-
- /* Set room flag */
- cave[y][x].info |= (CAVE_ROOM);
-
- if (get_is_floor(x, y))
- {
- for (i = -1; i <= 1; i++)
- {
- for (j = -1; j <= 1; j++)
- {
- if ((x + i >= x1) && (x + i <= x2) &&
- (y + j >= y1) && (y + j <= y2))
- {
- add_outer_wall(x + i, y + j, light, x1, y1, x2, y2);
- if (light) cave[y][x].info |= CAVE_GLOW;
- }
- }
- }
- }
-
- /* Set bounding walls */
- else if (cave[y][x].feat == FEAT_WALL_EXTRA)
- {
- cave[y][x].feat = feat_wall_outer;
- if (light == TRUE) cave[y][x].info |= CAVE_GLOW;
- }
-
- /* Set bounding walls */
- else if (cave[y][x].feat == FEAT_PERM_OUTER)
- {
- if (light == TRUE) cave[y][x].info |= CAVE_GLOW;
- }
-}
-
-
-/*
- * Hacked distance formula - gives the 'wrong' answer
- *
- * Used to build crypts
- */
-static int dist2(int x1, int y1, int x2, int y2,
- int h1, int h2, int h3, int h4)
-{
- int dx, dy;
- dx = abs(x2 - x1);
- dy = abs(y2 - y1);
-
- /*
- * Basically this works by taking the normal pythagorean formula
- * and using an expansion to express this in a way without the
- * square root. This approximate formula is then perturbed to give
- * the distorted results. (I found this by making a mistake when I was
- * trying to fix the circular rooms.)
- */
-
- /* h1-h4 are constants that describe the metric */
- if (dx >= 2 * dy) return (dx + (dy * h1) / h2);
- if (dy >= 2 * dx) return (dy + (dx * h1) / h2);
-
- /* 128/181 is approx. 1/sqrt(2) */
- return (((dx + dy) * 128) / 181 +
- (dx * dx / (dy * h3) + dy * dy / (dx * h3)) * h4);
-}
-
-
-/*
- * Build target vault
- *
- * This is made by two concentric "crypts" with perpendicular
- * walls creating the cross-hairs.
- */
-static void build_target_vault(int x0, int y0, int xsize, int ysize)
-{
- int rad, x, y;
-
- int h1, h2, h3, h4;
-
-
- /* Make a random metric */
- h1 = randint(32) - 16;
- h2 = randint(16);
- h3 = randint(32);
- h4 = randint(32) - 16;
-
- if (cheat_room) msg_print("Target Vault");
-
- /* Work out outer radius */
- if (xsize > ysize)
- {
- rad = ysize / 2;
- }
- else
- {
- rad = xsize / 2;
- }
-
- /* Make floor */
- for (x = x0 - rad; x <= x0 + rad; x++)
- {
- for (y = y0 - rad; y <= y0 + rad; y++)
- {
- cave_type *c_ptr;
-
- /* Access the grid */
- c_ptr = &cave[y][x];
-
- /* Clear room flag */
- c_ptr->info &= ~(CAVE_ROOM);
-
- /* Grids in vaults are required to be "icky" */
- c_ptr->info |= (CAVE_ICKY);
-
- /* Inside -- floor */
- if (dist2(y0, x0, y, x, h1, h2, h3, h4) <= rad - 1)
- {
- place_floor(y, x);
- }
-
- /* Outside -- make it granite so that arena works */
- else
- {
- c_ptr->feat = FEAT_WALL_EXTRA;
- }
-
- /* Proper boundary for arena */
- if (((y + rad) == y0) || ((y - rad) == y0) ||
- ((x + rad) == x0) || ((x - rad) == x0))
- {
- cave_set_feat(y, x, feat_wall_outer);
- }
- }
- }
-
- /* Find visible outer walls and set to be FEAT_OUTER */
- add_outer_wall(x0, y0, FALSE, x0 - rad - 1, y0 - rad - 1,
- x0 + rad + 1, y0 + rad + 1);
-
- /* Add inner wall */
- for (x = x0 - rad / 2; x <= x0 + rad / 2; x++)
- {
- for (y = y0 - rad / 2; y <= y0 + rad / 2; y++)
- {
- if (dist2(y0, x0, y, x, h1, h2, h3, h4) == rad / 2)
- {
- /* Make an internal wall */
- cave_set_feat(y, x, feat_wall_inner);
- }
- }
- }
-
- /* Add perpendicular walls */
- for (x = x0 - rad; x <= x0 + rad; x++)
- {
- cave_set_feat(y0, x, feat_wall_inner);
- }
-
- for (y = y0 - rad; y <= y0 + rad; y++)
- {
- cave_set_feat(y, x0, feat_wall_inner);
- }
-
- /* Make inner vault */
- for (y = y0 - 1; y <= y0 + 1; y++)
- {
- cave_set_feat(y, x0 - 1, feat_wall_inner);
- cave_set_feat(y, x0 + 1, feat_wall_inner);
- }
- for (x = x0 - 1; x <= x0 + 1; x++)
- {
- cave_set_feat(y0 - 1, x, feat_wall_inner);
- cave_set_feat(y0 + 1, x, feat_wall_inner);
- }
-
- place_floor(y0, x0);
-
-
- /*
- * Add doors to vault
- *
- * Get two distances so can place doors relative to centre
- */
- x = (rad - 2) / 4 + 1;
- y = rad / 2 + x;
-
- add_door(x0 + x, y0);
- add_door(x0 + y, y0);
- add_door(x0 - x, y0);
- add_door(x0 - y, y0);
- add_door(x0, y0 + x);
- add_door(x0, y0 + y);
- add_door(x0, y0 - x);
- add_door(x0, y0 - y);
-
- /* Fill with stuff - medium difficulty */
- fill_treasure(x0 - rad, x0 + rad, y0 - rad, y0 + rad, randint(3) + 3);
-}
-
-
-/*
- * Random vaults
- */
-static void build_type11(int by0, int bx0)
-{
- int y0, x0, xsize, ysize, vtype;
-
- /* Get size -- gig enough to look good, small enough to be fairly common */
- xsize = randint(22) + 22;
- ysize = randint(11) + 11;
-
- /* Allocate in room_map. If will not fit, exit */
- if (!room_alloc(xsize + 2, ysize + 2, FALSE, by0, bx0, &x0, &y0)) return;
-
- /*
- * Boost the rating -- Higher than lesser vaults and lower than
- * greater vaults
- */
- rating += 10;
-
- /* (Sometimes) Cause a special feeling */
- if ((dun_level <= 50) ||
- (randint((dun_level - 40) * (dun_level - 40) + 1) < 400))
- {
- good_item_flag = TRUE;
- }
-
- /* Select type of vault */
- vtype = randint(8);
-
- switch (vtype)
- {
- /* Build an appropriate room */
- case 1:
- {
- build_bubble_vault(x0, y0, xsize, ysize);
- break;
- }
-
- case 2:
- {
- build_room_vault(x0, y0, xsize, ysize);
- break;
- }
-
- case 3:
- {
- build_cave_vault(x0, y0, xsize, ysize);
- break;
- }
-
- case 4:
- {
- build_maze_vault(x0, y0, xsize, ysize);
- break;
- }
-
- case 5:
- {
- build_mini_c_vault(x0, y0, xsize, ysize);
- break;
- }
-
- case 6:
- {
- build_castle_vault(x0, y0, xsize, ysize);
- break;
- }
-
- case 7:
- {
- build_target_vault(x0, y0, xsize, ysize);
- break;
- }
-
- /* I know how to add a few more... give me some time. */
-
- /* Paranoia */
- default:
- {
- return;
- }
- }
-}
-
-/*
- * Crypt room generation from Z 2.5.1
- */
-
-/*
- * Build crypt room.
- * For every grid in the possible square, check the (fake) distance.
- * If it's less than the radius, make it a room square.
- *
- * When done fill from the inside to find the walls,
- */
-static void build_type12(int by0, int bx0)
-{
- int light, rad, x, y, x0, y0;
- bool_ emptyflag = TRUE;
- int h1, h2, h3, h4;
-
- /* Make a random metric */
- h1 = randint(32) - 16;
- h2 = randint(16);
- h3 = randint(32);
- h4 = randint(32) - 16;
-
- /* Occasional light */
- light = (randint(dun_level) <= 5) ? TRUE : FALSE;
-
- rad = randint(9);
-
- /* Allocate in room_map. If will not fit, exit */
- if (!room_alloc(rad * 2 + 3, rad * 2 + 3, FALSE, by0, bx0, &x0, &y0)) return;
-
- /* Make floor */
- for (x = x0 - rad; x <= x0 + rad; x++)
- {
- for (y = y0 - rad; y <= y0 + rad; y++)
- {
- /* Clear room flag */
- cave[y][x].info &= ~(CAVE_ROOM);
-
- /* Inside -- floor */
- if (dist2(y0, x0, y, x, h1, h2, h3, h4) <= rad - 1)
- {
- place_floor(y, x);
- }
- else if (distance(y0, x0, y, x) < 3)
- {
- place_floor(y, x);
- }
-
- /* Outside -- make it granite so that arena works */
- else
- {
- cave_set_feat(y, x, feat_wall_outer);
- }
-
- /* Proper boundary for arena */
- if (((y + rad) == y0) || ((y - rad) == y0) ||
- ((x + rad) == x0) || ((x - rad) == x0))
- {
- cave_set_feat(y, x, feat_wall_outer);
- }
- }
- }
-
- /* Find visible outer walls and set to be FEAT_OUTER */
- add_outer_wall(x0, y0, light, x0 - rad - 1, y0 - rad - 1,
- x0 + rad + 1, y0 + rad + 1);
-
- /* Check to see if there is room for an inner vault */
- for (x = x0 - 2; x <= x0 + 2; x++)
- {
- for (y = y0 - 2; y <= y0 + 2; y++)
- {
- if (!get_is_floor(x, y))
- {
- /* Wall in the way */
- emptyflag = FALSE;
- }
- }
- }
-
- if (emptyflag && (rand_int(2) == 0))
- {
- /* Build the vault */
- build_small_room(x0, y0);
-
- /* Place a treasure in the vault */
- place_object(y0, x0, FALSE, FALSE, OBJ_FOUND_FLOOR);
-
- /* Let's guard the treasure well */
- vault_monsters(y0, x0, rand_int(2) + 3);
-
- /* Traps naturally */
- vault_traps(y0, x0, 4, 4, rand_int(3) + 2);
- }
-}
-
-
-/*
- * Constructs a tunnel between two points
- *
- * This function must be called BEFORE any streamers are created,
- * since we use the special "granite wall" sub-types to keep track
- * of legal places for corridors to pierce rooms.
- *
- * We use "door_flag" to prevent excessive construction of doors
- * along overlapping corridors.
- *
- * We queue the tunnel grids to prevent door creation along a corridor
- * which intersects itself.
- *
- * We queue the wall piercing grids to prevent a corridor from leaving
- * a room and then coming back in through the same entrance.
- *
- * We "pierce" grids which are "outer" walls of rooms, and when we
- * do so, we change all adjacent "outer" walls of rooms into "solid"
- * walls so that no two corridors may use adjacent grids for exits.
- *
- * The "solid" wall check prevents corridors from "chopping" the
- * corners of rooms off, as well as "silly" door placement, and
- * "excessively wide" room entrances.
- *
- * Useful "feat" values:
- * FEAT_WALL_EXTRA -- granite walls
- * FEAT_WALL_INNER -- inner room walls
- * FEAT_WALL_OUTER -- outer room walls
- * FEAT_WALL_SOLID -- solid room walls
- * FEAT_PERM_EXTRA -- shop walls (perma)
- * FEAT_PERM_INNER -- inner room walls (perma)
- * FEAT_PERM_OUTER -- outer room walls (perma)
- * FEAT_PERM_SOLID -- dungeon border (perma)
- */
-static void build_tunnel(int row1, int col1, int row2, int col2, bool_ water)
-{
- int i, y, x;
- int tmp_row, tmp_col;
- int row_dir, col_dir;
- int start_row, start_col;
- int main_loop_count = 0;
-
- bool_ door_flag = FALSE;
-
- cave_type *c_ptr;
-
-
- /* Reset the arrays */
- dun->tunn_n = 0;
- dun->wall_n = 0;
-
- /* Save the starting location */
- start_row = row1;
- start_col = col1;
-
- /* Start out in the correct direction */
- correct_dir(&row_dir, &col_dir, row1, col1, row2, col2);
-
- /* Keep going until done (or bored) */
- while ((row1 != row2) || (col1 != col2))
- {
- /* Mega-Hack -- Paranoia -- prevent infinite loops */
- if (main_loop_count++ > 2000) break;
-
- /* Allow bends in the tunnel */
- if (rand_int(100) < DUN_TUN_CHG)
- {
- /* Acquire the correct direction */
- correct_dir(&row_dir, &col_dir, row1, col1, row2, col2);
-
- /* Random direction */
- if (rand_int(100) < DUN_TUN_RND)
- {
- rand_dir(&row_dir, &col_dir);
- }
- }
-
- /* Get the next location */
- tmp_row = row1 + row_dir;
- tmp_col = col1 + col_dir;
-
-
- /* Extremely Important -- do not leave the dungeon */
- while (!in_bounds(tmp_row, tmp_col))
- {
- /* Acquire the correct direction */
- correct_dir(&row_dir, &col_dir, row1, col1, row2, col2);
-
- /* Random direction */
- if (rand_int(100) < DUN_TUN_RND)
- {
- rand_dir(&row_dir, &col_dir);
- }
-
- /* Get the next location */
- tmp_row = row1 + row_dir;
- tmp_col = col1 + col_dir;
- }
-
-
- /* Access the location */
- c_ptr = &cave[tmp_row][tmp_col];
-
-
- /* Avoid the edge of the dungeon */
- if (c_ptr->feat == FEAT_PERM_SOLID) continue;
-
- /* Avoid the edge of vaults */
- if (c_ptr->feat == FEAT_PERM_OUTER) continue;
-
- /* Avoid "solid" granite walls */
- if (c_ptr->feat == FEAT_WALL_SOLID) continue;
-
- /*
- * Pierce "outer" walls of rooms
- * Cannot trust feat code any longer...
- */
- if ((c_ptr->feat == feat_wall_outer) &&
- (c_ptr->info & CAVE_ROOM))
- {
- /* Acquire the "next" location */
- y = tmp_row + row_dir;
- x = tmp_col + col_dir;
-
- /* Hack -- Avoid outer/solid permanent walls */
- if (cave[y][x].feat == FEAT_PERM_SOLID) continue;
- if (cave[y][x].feat == FEAT_PERM_OUTER) continue;
-
- /* Hack -- Avoid outer/solid granite walls */
- if ((cave[y][x].feat == feat_wall_outer) &&
- (cave[y][x].info & CAVE_ROOM)) continue;
- if (cave[y][x].feat == FEAT_WALL_SOLID) continue;
-
- /* Accept this location */
- row1 = tmp_row;
- col1 = tmp_col;
-
- /* Save the wall location */
- if (dun->wall_n < WALL_MAX)
- {
- dun->wall[dun->wall_n].y = row1;
- dun->wall[dun->wall_n].x = col1;
- dun->wall_n++;
- }
-
- /* Forbid re-entry near this piercing */
- for (y = row1 - 1; y <= row1 + 1; y++)
- {
- for (x = col1 - 1; x <= col1 + 1; x++)
- {
- /* Convert adjacent "outer" walls as "solid" walls */
- if ((cave[y][x].feat == feat_wall_outer) &&
- (cave[y][x].info & CAVE_ROOM))
- {
- /* Change the wall to a "solid" wall */
- /* Mega-Hack -- to be brought back later... */
- cave_set_feat(y, x, FEAT_WALL_SOLID);
- }
- }
- }
- }
-
- /* Travel quickly through rooms */
- else if (c_ptr->info & (CAVE_ROOM))
- {
- /* Accept the location */
- row1 = tmp_row;
- col1 = tmp_col;
- }
-
- /* Tunnel through all other walls */
- else if ((c_ptr->feat == d_info[dungeon_type].fill_type1) ||
- (c_ptr->feat == d_info[dungeon_type].fill_type2) ||
- (c_ptr->feat == d_info[dungeon_type].fill_type3))
- {
- /* Accept this location */
- row1 = tmp_row;
- col1 = tmp_col;
-
- /* Save the tunnel location */
- if (dun->tunn_n < TUNN_MAX)
- {
- dun->tunn[dun->tunn_n].y = row1;
- dun->tunn[dun->tunn_n].x = col1;
- dun->tunn_n++;
- }
-
- /* Allow door in next grid */
- door_flag = FALSE;
- }
-
- /* Handle corridor intersections or overlaps */
- else
- {
- /* Accept the location */
- row1 = tmp_row;
- col1 = tmp_col;
-
- /* Collect legal door locations */
- if (!door_flag)
- {
- /* Save the door location */
- if (dun->door_n < DOOR_MAX)
- {
- dun->door[dun->door_n].y = row1;
- dun->door[dun->door_n].x = col1;
- dun->door_n++;
- }
-
- /* No door in next grid */
- door_flag = TRUE;
- }
-
- /* Hack -- allow pre-emptive tunnel termination */
- if (rand_int(100) >= DUN_TUN_CON)
- {
- /* Distance between row1 and start_row */
- tmp_row = row1 - start_row;
- if (tmp_row < 0) tmp_row = ( -tmp_row);
-
- /* Distance between col1 and start_col */
- tmp_col = col1 - start_col;
- if (tmp_col < 0) tmp_col = ( -tmp_col);
-
- /* Terminate the tunnel */
- if ((tmp_row > 10) || (tmp_col > 10)) break;
- }
- }
- }
-
-
- /* Turn the tunnel into corridor */
- for (i = 0; i < dun->tunn_n; i++)
- {
- /* Access the grid */
- y = dun->tunn[i].y;
- x = dun->tunn[i].x;
-
- /* Access the grid */
- c_ptr = &cave[y][x];
-
- /* Clear previous contents, add a floor */
- if (!water)
- {
- place_floor(y, x);
- }
- else
- {
- cave_set_feat(y, x, FEAT_SHAL_WATER);
- }
- }
-
-
- /* Apply the piercings that we found */
- for (i = 0; i < dun->wall_n; i++)
- {
- /* Access the grid */
- y = dun->wall[i].y;
- x = dun->wall[i].x;
-
- /* Access the grid */
- c_ptr = &cave[y][x];
-
- /* Clear previous contents, add up floor */
- place_floor(y, x);
-
- /* Occasional doorway */
- if (!(dungeon_flags1 & DF1_NO_DOORS) &&
- (rand_int(100) < DUN_TUN_PEN))
- {
- /* Place a random door */
- place_random_door(y, x);
- }
- }
-}
-
-
-
-
-/*
- * Count the number of "corridor" grids adjacent to the given grid.
- *
- * Note -- Assumes "in_bounds(y1, x1)"
- *
- * XXX XXX This routine currently only counts actual "empty floor"
- * grids which are not in rooms. We might want to also count stairs,
- * open doors, closed doors, etc.
- */
-static int next_to_corr(int y1, int x1)
-{
- int i, y, x, k = 0;
-
- cave_type *c_ptr;
-
- /* Scan adjacent grids */
- for (i = 0; i < 4; i++)
- {
- /* Extract the location */
- y = y1 + ddy_ddd[i];
- x = x1 + ddx_ddd[i];
-
- /* Skip non floors */
- if (!cave_floor_bold(y, x)) continue;
-
- /* Access the grid */
- c_ptr = &cave[y][x];
-
- /* Skip non "empty floor" grids */
- if ((c_ptr->feat != d_info[dungeon_type].floor1) &&
- (c_ptr->feat != d_info[dungeon_type].floor2) &&
- (c_ptr->feat != d_info[dungeon_type].floor3))
- {
- continue;
- }
-
- /* Skip grids inside rooms */
- if (c_ptr->info & (CAVE_ROOM)) continue;
-
- /* Count these grids */
- k++;
- }
-
- /* Return the number of corridors */
- return (k);
-}
-
-
-/*
- * Determine if the given location is "between" two walls,
- * and "next to" two corridor spaces. XXX XXX XXX
- *
- * Assumes "in_bounds(y,x)"
- */
-static bool_ possible_doorway(int y, int x)
-{
- /* Count the adjacent corridors */
- if (next_to_corr(y, x) >= 2)
- {
- /* Check Vertical */
- if ((f_info[cave[y - 1][x].feat].flags1 & FF1_WALL) &&
- (f_info[cave[y + 1][x].feat].flags1 & FF1_WALL))
- {
- return (TRUE);
- }
-
- /* Check Horizontal */
- if ((f_info[cave[y][x - 1].feat].flags1 & FF1_WALL) &&
- (f_info[cave[y][x + 1].feat].flags1 & FF1_WALL))
- {
- return (TRUE);
- }
- }
-
- /* No doorway */
- return (FALSE);
-}
-
-
-/*
- * Places doors around y, x position
- */
-static void try_doors(int y, int x)
-{
- bool_ dir_ok[4];
- int i, k, n;
- int yy, xx;
-
- /* Paranoia */
- /* if (!in_bounds(y, x)) return; */
-
- /* Some dungeons don't have doors at all */
- if (dungeon_flags1 & (DF1_NO_DOORS)) return;
-
- /* Reset tally */
- n = 0;
-
- /* Look four cardinal directions */
- for (i = 0; i < 4; i++)
- {
- /* Assume NG */
- dir_ok[i] = FALSE;
-
- /* Access location */
- yy = y + ddy_ddd[i];
- xx = x + ddx_ddd[i];
-
- /* Out of level boundary */
- if (!in_bounds(yy, xx)) continue;
-
- /* Ignore walls */
- if (f_info[cave[yy][xx].feat].flags1 & (FF1_WALL)) continue;
-
- /* Ignore room grids */
- if (cave[yy][xx].info & (CAVE_ROOM)) continue;
-
- /* Not a doorway */
- if (!possible_doorway(yy, xx)) continue;
-
- /* Accept the direction */
- dir_ok[i] = TRUE;
-
- /* Count good spots */
- n++;
- }
-
- /* Use the traditional method 75% of time */
- if (rand_int(100) < 75)
- {
- for (i = 0; i < 4; i++)
- {
- /* Bad locations */
- if (!dir_ok[i]) continue;
-
- /* Place one of various kinds of doors */
- if (rand_int(100) < DUN_TUN_JCT)
- {
- /* Access location */
- yy = y + ddy_ddd[i];
- xx = x + ddx_ddd[i];
-
- /* Place a door */
- place_random_door(yy, xx);
- }
- }
- }
-
- /* Use alternative method */
- else
- {
- /* A crossroad */
- if (n == 4)
- {
- /* Clear OK flags XXX */
- for (i = 0; i < 4; i++) dir_ok[i] = FALSE;
-
- /* Put one or two secret doors */
- dir_ok[rand_int(4)] = TRUE;
- dir_ok[rand_int(4)] = TRUE;
- }
-
- /* A T-shaped intersection or two possible doorways */
- else if ((n == 3) || (n == 2))
- {
- /* Pick one random location from the list */
- k = rand_int(n);
-
- for (i = 0; i < 4; i++)
- {
- /* Reject all but k'th OK direction */
- if (dir_ok[i] && (k-- != 0)) dir_ok[i] = FALSE;
- }
- }
-
- /* Place secret door(s) */
- for (i = 0; i < 4; i++)
- {
- /* Bad location */
- if (!dir_ok[i]) continue;
-
- /* Access location */
- yy = y + ddy_ddd[i];
- xx = x + ddx_ddd[i];
-
- /* Place a secret door */
- place_secret_door(yy, xx);
- }
- }
-}
-
-
-/*
- * Attempt to build a room of the given type at the given block
- *
- * Note that we restrict the number of "crowded" rooms to reduce
- * the chance of overflowing the monster list during level creation.
- */
-static bool_ room_build(int y, int x, int typ)
-{
- /* Restrict level */
- if ((dun_level < roomdep[typ]) && !ironman_rooms) return (FALSE);
-
- /* Restrict "crowded" rooms */
- if (dun->crowded && ((typ == 5) || (typ == 6))) return (FALSE);
-
- /* Build a room */
- switch (typ)
- {
- /* Build an appropriate room */
- case 12:
- build_type12(y, x);
- break;
- case 11:
- build_type11(y, x);
- break;
- case 10:
- build_type10(y, x);
- break;
- case 9:
- build_type9 (y, x);
- break;
- case 8:
- build_type8 (y, x);
- break;
- case 7:
- build_type7 (y, x);
- break;
- case 6:
- build_type6 (y, x);
- break;
- case 5:
- build_type5 (y, x);
- break;
- case 4:
- build_type4 (y, x);
- break;
- case 3:
- build_type3 (y, x);
- break;
- case 2:
- build_type2 (y, x);
- break;
- case 1:
- build_type1 (y, x);
- break;
-
- /* Paranoia */
- default:
- return (FALSE);
- }
-
- /* Success */
- return (TRUE);
-}
-
-/*
- * Set level boundaries
- */
-void set_bounders(bool_ empty_level)
-{
- int y, x;
-
- /* Special boundary walls -- Top */
- for (x = 0; x < cur_wid; x++)
- {
- /* XXX XXX */
- if (empty_level) cave[0][x].mimic = fill_type[rand_int(100)];
- else cave[0][x].mimic = cave[0][x].feat;
-
- /* Clear previous contents, add "solid" perma-wall */
- cave_set_feat(0, x, FEAT_PERM_SOLID);
- }
-
- /* Special boundary walls -- Bottom */
- for (x = 0; x < cur_wid; x++)
- {
- /* XXX XXX */
- if (empty_level) cave[cur_hgt - 1][x].mimic = fill_type[rand_int(100)];
- else cave[cur_hgt - 1][x].mimic = cave[cur_hgt - 1][x].feat;
-
- /* Clear previous contents, add "solid" perma-wall */
- cave_set_feat(cur_hgt - 1, x, FEAT_PERM_SOLID);
- }
-
- /* Special boundary walls -- Left */
- for (y = 1; y < cur_hgt - 1; y++)
- {
- /* XXX XXX */
- if (empty_level) cave[y][0].mimic = fill_type[rand_int(100)];
- else cave[y][0].mimic = cave[y][0].feat;
-
- /* Clear previous contents, add "solid" perma-wall */
- cave_set_feat(y, 0, FEAT_PERM_SOLID);
- }
-
- /* Special boundary walls -- Right */
- for (y = 1; y < cur_hgt - 1; y++)
- {
- /* XXX XXX */
- if (empty_level) cave[y][cur_wid - 1].mimic = fill_type[rand_int(100)];
- else cave[y][cur_wid - 1].mimic = cave[y][cur_wid - 1].feat;
-
- /* Clear previous contents, add "solid" perma-wall */
- cave_set_feat(y, cur_wid - 1, FEAT_PERM_SOLID);
- }
-}
-
-/* Needed to refill empty levels */
-static void fill_level(bool_ use_floor, byte smooth);
-
-/*
- * Generate a normal dungeon level
- */
-bool_ level_generate_dungeon()
-{
- int i, k, y, x, y1, x1, branch = get_branch();
- dungeon_info_type *d_ptr = &d_info[dungeon_type];
-
- int max_vault_ok = 2;
-
- bool_ destroyed = FALSE;
- bool_ empty_level = FALSE;
- bool_ cavern = FALSE;
- s16b town_level = 0;
-
- /* Is it a town level ? */
- for (i = 0; i < TOWN_DUNGEON; i++)
- {
- if (d_ptr->t_level[i] == dun_level) town_level = d_ptr->t_idx[i];
- }
-
- /* Check for arena level */
- if ((dungeon_flags1 & (DF1_EMPTY)) ||
- (empty_levels && (rand_int(EMPTY_LEVEL) == 0)))
- {
- empty_level = TRUE;
-
- if (cheat_room || p_ptr->precognition)
- {
- msg_print("Arena level.");
- }
-
- /* Refill the level with floor tiles */
- fill_level(empty_level, d_ptr->fill_method);
- }
-
- /* Possible cavern */
- if ((dungeon_flags1 & DF1_CAVERN) && (rand_int(dun_level / 2) > DUN_CAVERN))
- {
- cavern = TRUE;
-
- /* Make a large fractal cave in the middle of the dungeon */
- if (cheat_room)
- {
- msg_print("Cavern on level.");
- }
-
- build_cavern();
- }
-
- /* Possible "destroyed" level */
- if ((dun_level > 10) && (rand_int(DUN_DEST) == 0))
- {
- destroyed = TRUE;
- }
-
- /* Hack -- No destroyed "quest" levels */
- if (is_quest(dun_level)) destroyed = FALSE;
-
- /* Hack -- No destroyed "small" levels */
- if ((cur_wid != MAX_WID) || (cur_hgt != MAX_HGT)) destroyed = FALSE;
-
- /* Hack -- No destroyed levels */
- if (dungeon_flags1 & DF1_NO_DESTROY) destroyed = FALSE;
-
- /* Actual maximum number of rooms on this level */
- dun->row_rooms = cur_hgt / BLOCK_HGT;
- dun->col_rooms = cur_wid / BLOCK_WID;
-
-
- /* Initialize the room table */
- for (y = 0; y < dun->row_rooms; y++)
- {
- for (x = 0; x < dun->col_rooms; x++)
- {
- dun->room_map[y][x] = FALSE;
- }
- }
-
- /* No "crowded" rooms yet */
- dun->crowded = FALSE;
-
- /* No rooms yet */
- dun->cent_n = 0;
-
- /* Pick a block for the room */
- y = rand_int(dun->row_rooms);
- x = rand_int(dun->col_rooms);
-
- /* Align dungeon rooms */
- if (dungeon_align)
- {
- /* Slide some rooms right */
- if ((x % 3) == 0) x++;
-
- /* Slide some rooms left */
- if ((x % 3) == 2) x--;
- }
-
- /* Ugly */
- process_hooks(HOOK_BUILD_ROOM1, "(d,d)", y, x);
-
- /* Build some rooms */
- for (i = 0; i < DUN_ROOMS; i++)
- {
- /* Pick a block for the room */
- y = rand_int(dun->row_rooms);
- x = rand_int(dun->col_rooms);
-
- /* Align dungeon rooms */
- if (dungeon_align)
- {
- /* Slide some rooms right */
- if ((x % 3) == 0) x++;
-
- /* Slide some rooms left */
- if ((x % 3) == 2) x--;
- }
-
- /* Destroyed levels are boring */
- if (destroyed)
- {
- /* The deeper you are, the more cavelike the rooms are */
-
- /* no caves when cavern exists: they look bad */
- k = randint(100);
-
- if (!cavern && (k < dun_level))
- {
- /* Type 10 -- Fractal cave */
- if (room_build(y, x, 10)) continue;
- }
- else
- {
- /* Attempt a "trivial" room */
- if ((dungeon_flags1 & DF1_CIRCULAR_ROOMS) &&
- room_build(y, x, 9))
- {
- continue;
- }
- else if (room_build(y, x, 1)) continue;
- }
-
- /* Never mind */
- continue;
- }
-
- /* Attempt an "unusual" room -- no vaults on town levels */
- if (!town_level &&
- (ironman_rooms || (rand_int(DUN_UNUSUAL) < dun_level)))
- {
- /* Roll for room type */
- k = (ironman_rooms ? 0 : rand_int(100));
-
- /* Attempt a very unusual room */ /* test hack */
- if (ironman_rooms || (rand_int(DUN_UNUSUAL) < dun_level))
- {
-#ifdef FORCE_V_IDX
- if (room_build(y, x, 8)) continue;
-#else
-/* Type 8 -- Greater vault (10%) */
- if (k < 10)
- {
- if (max_vault_ok > 1)
- {
- if (room_build(y, x, 8)) continue;
- }
- else
- {
- if (cheat_room) msg_print("Refusing a greater vault.");
- }
- }
-
- /* Type 7 -- Lesser vault (15%) */
- if (k < 25)
- {
- if (max_vault_ok > 0)
- {
- if (room_build(y, x, 7)) continue;
- }
- else
- {
- if (cheat_room) msg_print("Refusing a lesser vault.");
- }
- }
-
-
- /* Type 5 -- Monster nest (15%) */
- if ((k < 40) && room_build(y, x, 5)) continue;
-
- /* Type 6 -- Monster pit (15%) */
- if ((k < 55) && room_build(y, x, 6)) continue;
-
- /* Type 11 -- Random vault (5%) */
- if ((k < 60) && room_build(y, x, 11)) continue;
-#endif
- }
-
- /* Type 4 -- Large room (25%) */
- if ((k < 25) && room_build(y, x, 4)) continue;
-
- /* Type 3 -- Cross room (20%) */
- if ((k < 45) && room_build(y, x, 3)) continue;
-
- /* Type 2 -- Overlapping (20%) */
- if ((k < 65) && room_build(y, x, 2)) continue;
-
- /* Type 10 -- Fractal cave (15%) */
- if ((k < 80) && room_build(y, x, 10)) continue;
-
- /* Type 9 -- Circular (10%) */
- /* Hack - build standard rectangular rooms if needed */
- if (k < 90)
- {
- if ((dungeon_flags1 & DF1_CIRCULAR_ROOMS) && room_build(y, x, 1)) continue;
- else if (room_build(y, x, 9)) continue;
- }
-
- /* Type 12 -- Crypt (10%) */
- if ((k < 100) && room_build(y, x, 12)) continue;
- }
-
- /* Attempt a trivial room */
- if (dungeon_flags1 & DF1_CAVE)
- {
- if (room_build(y, x, 10)) continue;
- }
- else
- {
- if ((dungeon_flags1 & DF1_CIRCULAR_ROOMS) && room_build(y, x, 9)) continue;
- else if (room_build(y, x, 1)) continue;
- }
- }
-
- /* If no rooms are allocated... */
- while (dun->cent_n == 0)
- {
- /* ...force the creation of a small rectangular room */
- (void)room_build(0, 0, 1);
- }
-
- /* Hack -- Scramble the room order */
- for (i = 0; i < dun->cent_n; i++)
- {
- int pick1 = rand_int(dun->cent_n);
- int pick2 = rand_int(dun->cent_n);
- y1 = dun->cent[pick1].y;
- x1 = dun->cent[pick1].x;
- dun->cent[pick1].y = dun->cent[pick2].y;
- dun->cent[pick1].x = dun->cent[pick2].x;
- dun->cent[pick2].y = y1;
- dun->cent[pick2].x = x1;
- }
-
- /* Start with no tunnel doors */
- dun->door_n = 0;
-
- /* Hack -- connect the first room to the last room */
- y = dun->cent[dun->cent_n - 1].y;
- x = dun->cent[dun->cent_n - 1].x;
-
- /* Connect all the rooms together */
- for (i = 0; i < dun->cent_n; i++)
- {
- /* Connect the room to the previous room */
- build_tunnel(dun->cent[i].y, dun->cent[i].x, y, x, FALSE);
-
- /* Remember the "previous" room */
- y = dun->cent[i].y;
- x = dun->cent[i].x;
- }
-
- /* Mega-Hack -- Convert FEAT_WALL_SOLID back into outer walls */
- for (y = 0; y < cur_hgt; y++)
- {
- for (x = 0; x < cur_wid; x++)
- {
- if (cave[y][x].feat == FEAT_WALL_SOLID)
- {
- cave_set_feat(y, x, feat_wall_outer);
- }
- }
- }
-
- /* Place intersection doors */
- for (i = 0; i < dun->door_n; i++)
- {
- /* Extract junction location */
- y = dun->door[i].y;
- x = dun->door[i].x;
-
- /* Try placing doors */
- try_doors(y, x);
- }
-
- if (strcmp(game_module, "ToME") == 0)
- {
- /* Hack -- Add some magma streamers */
- if ((dungeon_type == DUNGEON_MORDOR) || (dungeon_type == DUNGEON_ANGBAND))
- for (i = 0; i < DUN_STR_MAG; i++)
- {
- build_streamer(FEAT_MAGMA, DUN_STR_MC);
- }
-
- /* Hack -- Add some quartz streamers */
- if ((dungeon_type == DUNGEON_MORDOR) || (dungeon_type == DUNGEON_ANGBAND))
- for (i = 0; i < DUN_STR_QUA; i++)
- {
- build_streamer(FEAT_QUARTZ, DUN_STR_QC);
- }
- }
-
- /* Add some sand streamers */
- if ((dungeon_flags1 & DF1_SAND_VEIN) && !rand_int(4))
- {
- if ((cheat_room) || (p_ptr->precognition)) msg_print("Sand vein.");
- build_streamer(FEAT_SANDWALL, DUN_STR_SC);
- }
-
- /* Destroy the level if necessary */
- if (destroyed) destroy_level();
-
- /* Create the town if needed */
- if (town_level)
- {
- town_gen(town_level);
- }
-
- /* Hack -- Add some rivers if requested */
- if ((dungeon_flags1 & DF1_WATER_RIVER) && !rand_int(4))
- {
- if (cheat_room || p_ptr->precognition) msg_print("River of water.");
- add_river(FEAT_DEEP_WATER, FEAT_SHAL_WATER);
- }
- if ((dungeon_flags1 & DF1_LAVA_RIVER) && !rand_int(4))
- {
- if ((cheat_room) || (p_ptr->precognition)) msg_print("River of lava.");
- add_river(FEAT_DEEP_LAVA, FEAT_SHAL_LAVA);
- }
-
- if (dungeon_flags1 & DF1_WATER_RIVERS)
- {
- int max = 3 + rand_int(2);
- bool_ said = FALSE;
-
- for (i = 0; i < max; i++)
- {
- if (rand_int(3) == 0)
- {
- add_river(FEAT_DEEP_WATER, FEAT_SHAL_WATER);
- if (!said && ((cheat_room) || (p_ptr->precognition))) msg_print("Rivers of water.");
- said = TRUE;
- }
- }
- }
-
- if (dungeon_flags1 & DF1_LAVA_RIVERS)
- {
- int max = 2 + rand_int(2);
- bool_ said = FALSE;
-
- for (i = 0; i < max; i++)
- {
- if (rand_int(3) == 0)
- {
- add_river(FEAT_DEEP_LAVA, FEAT_SHAL_LAVA);
- if (!said && ((cheat_room) || (p_ptr->precognition))) msg_print("Rivers of lava.");
- said = TRUE;
- }
- }
- }
-
- /* Add streamers of trees, water, or lava -KMW- */
- if (!(dungeon_flags1 & DF1_NO_STREAMERS))
- {
- int num;
-
- /*
- * Flat levels (was: levels 1--2)
- *
- * Small trees (penetrate walls)
- */
- if ((dungeon_flags1 & DF1_FLAT) && (randint(20) > 15))
- {
- num = randint(DUN_STR_QUA);
-
- for (i = 0; i < num; i++)
- {
- build_streamer2(FEAT_SMALL_TREES, 1);
- }
- }
-
- /*
- * Levels 1 -- 33 (was: 1 -- 19)
- *
- * Shallow water (preserve walls)
- * Deep water (penetrate walls)
- */
- if (!(dun_level <= 33) && (randint(20) > 15))
- {
- num = randint(DUN_STR_QUA - 1);
-
- for (i = 0; i < num; i++)
- {
- build_streamer2(FEAT_SHAL_WATER, 0);
- }
-
- if (randint(20) > 15)
- {
- num = randint(DUN_STR_QUA);
-
- for (i = 0; i < num; i++)
- {
- build_streamer2(FEAT_DEEP_WATER, 1);
- }
- }
- }
-
- /*
- * Levels 34 -- (was: 20 --)
- */
- else if (dun_level > 33)
- {
- /*
- * Shallow lava (preserve walls)
- * Deep lava (penetrate walls)
- */
- if (randint(20) > 15)
- {
- num = randint(DUN_STR_QUA);
-
- for (i = 0; i < num; i++)
- {
- build_streamer2(FEAT_SHAL_LAVA, 0);
- }
-
- if (randint(20) > 15)
- {
- num = randint(DUN_STR_QUA - 1);
-
- for (i = 0; i < num; i++)
- {
- build_streamer2(FEAT_DEEP_LAVA, 1);
- }
- }
- }
-
- /*
- * Shallow water (preserve walls)
- * Deep water (penetrate walls)
- */
- else if (randint(20) > 15)
- {
- num = randint(DUN_STR_QUA - 1);
-
- for (i = 0; i < num; i++)
- {
- build_streamer2(FEAT_SHAL_WATER, 0);
- }
-
- if (randint(20) > 15)
- {
- num = randint(DUN_STR_QUA);
-
- for (i = 0; i < num; i++)
- {
- build_streamer2(FEAT_DEEP_WATER, 1);
- }
- }
- }
- }
- }
-
- /* Hack, seems like once a room overrode the level boundaries, this is BAD */
- set_bounders(empty_level);
-
- /* Determine the character location */
- if (!new_player_spot(branch))
- return FALSE;
-
- return TRUE;
-}
-
-/*
- * Bring the imprinted pets from the old level
- */
-void replace_all_friends()
-{
- int i;
-
- if (p_ptr->wild_mode) return;
-
- /* Scan every saved pet */
- for (i = 0; i < max_m_idx; i++)
- {
- if ((km_list[i].r_idx) && (km_list[i].status == MSTATUS_COMPANION))
- {
- int y = p_ptr->py, x = p_ptr->px;
- cave_type *c_ptr;
- monster_type *m_ptr;
-
- /* Find a suitable location */
- get_pos_player(5, &y, &x);
- c_ptr = &cave[y][x];
-
- /* Get a m_idx to use */
- c_ptr->m_idx = m_pop();
- m_ptr = &m_list[c_ptr->m_idx];
-
- /* Actualy place the monster */
- m_list[c_ptr->m_idx] = km_list[i];
- m_ptr->fy = y;
- m_ptr->fx = x;
- m_ptr->hold_o_idx = 0;
- }
- }
-}
-
-/*
- * Save the imprinted pets from the old level
- */
-void save_all_friends()
-{
- if (p_ptr->old_wild_mode) return;
-
- C_COPY(km_list, m_list, max_m_idx, monster_type);
-}
-
-
-
-/*
- * Return the dungeon type of the current level(it can only return the
- * principal dungeons)
- */
-byte calc_dungeon_type()
-{
- int i;
-
- for (i = 0; i < max_d_idx; i++)
- {
- if ((dun_level >= d_info[i].mindepth) &&
- (dun_level <= d_info[i].maxdepth) &&
- (d_info[i].flags1 & DF1_PRINCIPAL))
- return (i);
- }
- return (0);
-}
-
-
-/*
- * Build probability tables for walls and floors and set feat_wall_outer
- * and feat_wall_inner according to the current information in d_info.txt
- *
- * *hint* *hint* with this made extern, and we no longer have to
- * store fill_type and floor_type in the savefile...
- */
-static void init_feat_info(void)
-{
- dungeon_info_type *d_ptr = &d_info[dungeon_type];
- int i;
- int cur_depth, max_depth;
- int p1, p2;
- int floor_lim1, floor_lim2;
- int fill_lim1, fill_lim2;
-
-
- /* Retrieve dungeon depth info (base 1, to avoid zero divide errors) */
- cur_depth = (dun_level - d_ptr->mindepth) + 1;
- max_depth = (d_ptr->maxdepth - d_ptr->mindepth) + 1;
-
-
- /* Set room wall types */
- feat_wall_outer = d_ptr->outer_wall;
- feat_wall_inner = d_ptr->inner_wall;
-
-
- /* Setup probability info -- Floors */
- p1 = d_ptr->floor_percent1[0];
- p2 = d_ptr->floor_percent1[1];
- floor_lim1 = p1 + (p2 - p1) * cur_depth / max_depth;
-
- p1 = d_ptr->floor_percent2[0];
- p2 = d_ptr->floor_percent2[1];
- floor_lim2 = floor_lim1 + p1 + (p2 - p1) * cur_depth / max_depth;
-
- /* Setup probability info -- Fillers */
- p1 = d_ptr->fill_percent1[0];
- p2 = d_ptr->fill_percent1[1];
- fill_lim1 = p1 + (p2 - p1) * cur_depth / max_depth;
-
- p1 = d_ptr->fill_percent2[0];
- p2 = d_ptr->fill_percent2[1];
- fill_lim2 = fill_lim1 + p1 + (p2 - p1) * cur_depth / max_depth;
-
-
- /* Fill the arrays of floors and walls in the good proportions */
- for (i = 0; i < 100; i++)
- {
- if (i < floor_lim1)
- {
- floor_type[i] = d_ptr->floor1;
- }
- else if (i < floor_lim2)
- {
- floor_type[i] = d_ptr->floor2;
- }
- else
- {
- floor_type[i] = d_ptr->floor3;
- }
-
- if (i < fill_lim1)
- {
- fill_type[i] = d_ptr->fill_type1;
- }
- else if (i < fill_lim2)
- {
- fill_type[i] = d_ptr->fill_type2;
- }
- else
- {
- fill_type[i] = d_ptr->fill_type3;
- }
- }
-}
-
-
-/*
- * Fill a level with wall type specified in A: or L: line of d_info.txt
- *
- * 'use_floor', when it is TRUE, tells the function to use floor type
- * terrains (L:) instead of walls (A:).
- *
- * Filling behaviour can be controlled by the second parameter 'smooth',
- * with the following options available:
- *
- * smooth behaviour
- * ------ ------------------------------------------------------------
- * 0 Fill the entire level with fill_type1 / floor1
- * 1 All the grids are randomly selected (== --P5.1.2)
- * 2 Slightly smoothed -- look like scattered patches
- * 3 More smoothed -- tend to look like caverns / small scale map
- * 4-- Max smoothing -- tend to look like landscape/island/
- * continent etc.
- *
- * I put it here, because there's another filler generator in
- * wild.c, but it works better there, in fact...
- *
- * CAVEAT: smoothness of 3 or greater doesn't work well with the
- * current secret door implementation. Outer walls also need some
- * rethinking.
- *
- * -- pelpel
- */
-
-/*
- * Thou shalt not invoke the name of thy RNG in vain.
- * The Angband RNG generates 28 bit pseudo-random number, hence
- * 28 / 2 = 14
- */
-#define MAX_SHIFTS 14
-
-static void fill_level(bool_ use_floor, byte smooth)
-{
- int y, x;
- int step;
- int shift;
-
-
- /* Convert smoothness to initial step */
- if (smooth == 0) step = 0;
- else if (smooth == 1) step = 1;
- else if (smooth == 2) step = 2;
- else if (smooth == 3) step = 4;
- else step = 8;
-
- /*
- * Paranoia -- step must be less than or equal to a half of
- * width or height, whichever shorter
- */
- if ((cur_hgt < 16) && (step > 4)) step = 4;
- if ((cur_wid < 16) && (step > 4)) step = 4;
-
-
- /* Special case -- simple fill */
- if (step == 0)
- {
- byte filler;
-
- /* Pick a filler XXX XXX XXX */
- if (use_floor) filler = d_info[dungeon_type].floor1;
- else filler = d_info[dungeon_type].fill_type1;
-
- /* Fill the level with the filler without calling RNG */
- for (y = 0; y < cur_hgt; y++)
- {
- for (x = 0; x < cur_wid; x++)
- {
- cave_set_feat(y, x, filler);
- }
- }
-
- /* Done */
- return;
- }
-
-
- /*
- * Fill starting positions -- every 'step' grids horizontally and
- * vertically
- */
- for (y = 0; y < cur_hgt; y += step)
- {
- for (x = 0; x < cur_wid; x += step)
- {
- /*
- * Place randomly selected terrain feature using the prebuilt
- * probability table
- *
- * By slightly modifying this, you can build streamers as
- * well as normal fillers all at once, but this calls for
- * modifications to the other part of the dungeon generator.
- */
- if (use_floor) place_floor(y, x);
- else place_filler(y, x);
- }
- }
-
-
- /*
- * Fill spaces between, randomly picking one of their neighbours
- *
- * This simple yet powerful algorithm was described by Mike Anderson:
- *
- * A B A | B A a B
- * -> --+-- -> d e b
- * D C D | C D c C
- *
- * a can be either A or B, b B or C, c C or D and d D or A.
- * e is chosen from A, B, C and D.
- * Subdivide and repeat the process as many times as you like.
- *
- * All the nasty tricks that obscure this simplicity are mine (^ ^;)
- */
-
- /* Initialise bit shift counter */
- shift = MAX_SHIFTS;
-
- /* Repeat subdivision until all the grids are filled in */
- while ((step = step >> 1) > 0)
- {
- bool_ y_even, x_even;
- s16b y_wrap, x_wrap;
- s16b y_sel, x_sel;
- u32b selector = 0;
-
- /* Hacklette -- Calculate wrap-around locations */
- y_wrap = ((cur_hgt - 1) / (step * 2)) * (step * 2);
- x_wrap = ((cur_wid - 1) / (step * 2)) * (step * 2);
-
- /* Initialise vertical phase */
- y_even = 0;
-
- for (y = 0; y < cur_hgt; y += step)
- {
- /* Flip vertical phase */
- y_even = !y_even;
-
- /* Initialise horizontal phase */
- x_even = 0;
-
- for (x = 0; x < cur_wid; x += step)
- {
- /* Flip horizontal phase */
- x_even = !x_even;
-
- /* Already filled in by previous iterations */
- if (y_even && x_even) continue;
-
- /*
- * Retrieve next two bits from pseudo-random bit sequence
- *
- * You can do well not caring so much about their randomness.
- *
- * This is not really necessary, but I don't like to invoke
- * relatively expensive RNG when we can do with much smaller
- * number of calls.
- */
- if (shift >= MAX_SHIFTS)
- {
- selector = rand_int(0x10000000L);
- shift = 0;
- }
- else
- {
- selector >>= 2;
- shift++;
- }
-
- /* Vertically in sync */
- if (y_even) y_sel = y;
-
- /* Bit 1 selects neighbouring y */
- else y_sel = (selector & 2) ? y + step : y - step;
-
- /* Horizontally in sync */
- if (x_even) x_sel = x;
-
- /* Bit 0 selects neighbouring x */
- else x_sel = (selector & 1) ? x + step : x - step;
-
- /* Hacklette -- Fix out of range indices by wrapping around */
- if (y_sel >= cur_hgt) y_sel = 0;
- else if (y_sel < 0) y_sel = y_wrap;
- if (x_sel >= cur_wid) x_sel = 0;
- else if (x_sel < 0) x_sel = x_wrap;
-
- /*
- * Fill the grid with terrain feature of the randomly
- * picked up neighbour
- */
- cave_set_feat(y, x, cave[y_sel][x_sel].feat);
- }
- }
- }
-}
-
-
-/*
- * Generate a new dungeon level
- *
- * Note that "dun_body" adds about 4000 bytes of memory to the stack.
- */
-static bool_ cave_gen(void)
-{
- int i, k, y, x, y1, x1, branch;
- dungeon_info_type *d_ptr = &d_info[dungeon_type];
-
- int max_vault_ok = 2;
-
- bool_ empty_level = FALSE;
-
- level_generator_type *generator;
-
- dun_data dun_body;
-
- char generator_name[100];
-
- if (!get_dungeon_generator(generator_name))
- strnfmt(generator_name, 99, "%s", d_ptr->generator);
-
- /*
- * We generate a double dungeon. First we should halve the desired
- * width/height, generate the dungeon normally, then double it
- * in both directions
- */
- if (dungeon_flags1 & DF1_DOUBLE)
- {
- cur_wid /= 2;
- cur_hgt /= 2;
- }
-
- /* Fill the arrays of floors and walls in the good proportions */
- init_feat_info();
-
- /* Set the correct monster hook */
- set_mon_num_hook();
-
- /* Prepare allocation table */
- get_mon_num_prep();
-
- /* Global data */
- dun = &dun_body;
-
- if (!(max_panel_rows)) max_vault_ok--;
- if (!(max_panel_cols)) max_vault_ok--;
-
- /*
- * Hack -- Start with fill_type's
- *
- * Need a way to know appropriate smoothing factor for the current
- * dungeon. Maybe we need another d_info flag/value.
- */
- fill_level(empty_level, d_ptr->fill_method);
-
- set_bounders(empty_level);
-
- /*
- * Call the good level generator
- */
- generator = level_generators;
- while (generator)
- {
- if (!strcmp(generator->name, generator_name))
- {
- if (!generator->generator(generator->name))
- return FALSE;
- break;
- }
-
- generator = generator->next;
- }
-
- /* Only if requested */
- if (generator->default_stairs)
- {
- /* Is there a dungeon branch ? */
- if ((branch = get_branch()))
- {
- /* Place 5 down stair some walls */
- alloc_stairs(FEAT_MORE, 5, 3, branch);
- }
-
- /* Is there a father dungeon branch ? */
- if ((branch = get_fbranch()))
- {
- /* Place 1 down stair some walls */
- alloc_stairs(FEAT_LESS, 5, 3, branch);
- }
-
- if ((dun_level < d_ptr->maxdepth) || ((dun_level == d_ptr->maxdepth) && (dungeon_flags1 & DF1_FORCE_DOWN)))
- {
- /* Place 3 or 4 down stairs near some walls */
- alloc_stairs((dungeon_flags1 & DF1_FLAT) ? FEAT_WAY_MORE : FEAT_MORE, rand_range(3, 4), 3, 0);
-
- /* Place 0 or 1 down shafts near some walls */
- if (!(dungeon_flags2 & DF2_NO_SHAFT)) alloc_stairs((dungeon_flags1 & DF1_FLAT) ? FEAT_WAY_MORE : FEAT_SHAFT_DOWN, rand_range(0, 1), 3, 0);
- }
-
- if ((dun_level > d_ptr->mindepth) || ((dun_level == d_ptr->mindepth) && (!(dungeon_flags1 & DF1_NO_UP))))
- {
- /* Place 1 or 2 up stairs near some walls */
- alloc_stairs((dungeon_flags1 & DF1_FLAT) ? FEAT_WAY_LESS : FEAT_LESS, rand_range(1, 2), 3, 0);
-
- /* Place 0 or 1 up shafts near some walls */
- if (!(dungeon_flags2 & DF2_NO_SHAFT)) alloc_stairs((dungeon_flags1 & DF1_FLAT) ? FEAT_WAY_LESS : FEAT_SHAFT_UP, rand_range(0, 1), 3, 0);
- }
- }
-
- process_hooks(HOOK_GEN_LEVEL, "(d)", is_quest(dun_level));
-
- /* Basic "amount" */
- k = (dun_level / 3);
- if (k > 10) k = 10;
- if (k < 2) k = 2;
-
- /* Only if requested */
- if (generator->default_monsters)
- {
-
- /*
- * Pick a base number of monsters
- */
- i = d_ptr->min_m_alloc_level;
-
- /* To make small levels a bit more playable */
- if ((cur_hgt < MAX_HGT) || (cur_wid < MAX_WID))
- {
- int small_tester = i;
-
- i = (i * cur_hgt) / MAX_HGT;
- i = (i * cur_wid) / MAX_WID;
- i += 1;
-
- if (i > small_tester) i = small_tester;
- else if (cheat_hear)
- {
- msg_format("Reduced monsters base from %d to %d", small_tester, i);
- }
- }
-
- i += randint(8);
-
- /* Put some monsters in the dungeon */
- for (i = i + k; i > 0; i--)
- {
- (void)alloc_monster(0, TRUE);
- }
- }
-
- /* Check fates */
- for (i = 0; i < MAX_FATES; i++)
- {
- /* Ignore empty slots */
- if (fates[i].fate == FATE_NONE) continue;
-
- /* Check dungeon depth */
- if (fates[i].level != dun_level) continue;
-
- /* Non-serious fates don't always fire */
- if ((!fates[i].serious) && (randint(2) != 1)) continue;
-
- /* Player meets his/her fate now... */
- fate_flag = TRUE;
-
- switch (fates[i].fate)
- {
- case FATE_FIND_O:
- {
- int oy = p_ptr->py + 1;
- int ox = p_ptr->px;
- object_type *q_ptr, forge;
-
- /* Get local object */
- q_ptr = &forge;
-
- /* Mega-Hack */
- object_prep(q_ptr, fates[i].o_idx);
-
- /* Mega-Hack */
- apply_magic(q_ptr, dun_level, TRUE, TRUE, fates[i].serious);
-
- get_pos_player(10, &oy, &ox);
-
- /* Drop it from the heaven */
- drop_near(q_ptr, -1, oy, ox);
-
- /* Make it icky */
- fates[i].icky = TRUE;
- break;
- }
- case FATE_FIND_R:
- {
- int oy = p_ptr->py + 1;
- int ox = p_ptr->px;
-
- get_pos_player(10, &oy, &ox);
-
- place_monster_one(oy, ox, fates[i].r_idx, 0, fates[i].serious, MSTATUS_ENEMY);
-
- fates[i].icky = TRUE;
- break;
- }
- case FATE_FIND_A:
- {
- int oy = p_ptr->py + 1;
- int ox = p_ptr->px;
- object_type *q_ptr = NULL, forge;
-
- get_pos_player(10, &oy, &ox);
-
- /* XXX XXX XXX Grant a randart */
- if (fates[i].a_idx == 0)
- {
- int obj_lev;
- s16b k_idx;
-
- /* Apply restriction */
- get_obj_num_hook = kind_is_artifactable;
-
- /* Object level a la find object fates */
- obj_lev = max_dlv[dungeon_type] + randint(10);
-
- /* Rebuild allocation table */
- get_obj_num_prep();
-
- /* Roll for an object */
- k_idx = get_obj_num(obj_lev);
-
- /* Reset restriction */
- get_obj_num_hook = kind_is_legal;
-
- /* Invalidate the allocation table */
- alloc_kind_table_valid = FALSE;
-
- /* Get a local object */
- q_ptr = &forge;
-
- /* Wipe it */
- object_wipe(q_ptr);
-
- /* Create the object */
- object_prep(q_ptr, k_idx);
-
- /* SoAC it */
- create_artifact(q_ptr, FALSE, TRUE);
-
- /* Drop the artifact from heaven */
- drop_near(q_ptr, -1, oy, ox);
- }
-
- /* Grant a normal artefact */
- else if (a_info[fates[i].a_idx].cur_num == 0)
- {
- artifact_type *a_ptr = &a_info[fates[i].a_idx];
- s16b I_kind;
-
- /* Get local object */
- q_ptr = &forge;
-
- /* Wipe the object */
- object_wipe(q_ptr);
-
- /* Acquire the "kind" index */
- I_kind = lookup_kind(a_ptr->tval, a_ptr->sval);
-
- /* Create the artifact */
- object_prep(q_ptr, I_kind);
-
- /* Save the name */
- q_ptr->name1 = fates[i].a_idx;
-
- apply_magic(q_ptr, -1, TRUE, TRUE, TRUE);
-
- /* Drop the artifact from heaven */
- drop_near(q_ptr, -1, oy, ox);
- }
-
- fates[i].icky = TRUE;
- break;
- }
- }
- }
-
- /* Re scan the list to eliminate the inutile fate */
- for (i = 0; i < MAX_FATES; i++)
- {
- switch (fates[i].fate)
- {
- case FATE_FIND_A:
- {
- if (a_info[fates[i].a_idx].cur_num == 1) fates[i].icky = TRUE;
- break;
- }
- case FATE_FIND_R:
- {
- if ((r_info[fates[i].r_idx].cur_num == 1) && (r_info[fates[i].r_idx].flags1 & RF1_UNIQUE)) fates[i].icky = TRUE;
- break;
- }
- }
- }
-
- /* Only if requested */
- if (generator->default_miscs)
- {
- /* Place some traps in the dungeon */
- alloc_object(ALLOC_SET_BOTH, ALLOC_TYP_TRAP, randint(k * 2));
-
- /* Put some rubble in corridors */
- alloc_object(ALLOC_SET_CORR, ALLOC_TYP_RUBBLE, randint(k));
- }
-
- /* Only if requested */
- if (generator->default_objects)
- {
- /* Put some objects in rooms */
- if (dungeon_type != DUNGEON_DEATH) alloc_object(ALLOC_SET_ROOM, ALLOC_TYP_OBJECT, randnor(DUN_AMT_ROOM, 3));
-
- /* Put some objects/gold in the dungeon */
- if (dungeon_type != DUNGEON_DEATH) alloc_object(ALLOC_SET_BOTH, ALLOC_TYP_OBJECT, randnor(DUN_AMT_ITEM, 3));
- if (dungeon_type != DUNGEON_DEATH) alloc_object(ALLOC_SET_BOTH, ALLOC_TYP_GOLD, randnor(DUN_AMT_GOLD, 3));
- }
-
- /* Only if requested */
- if (generator->default_miscs)
- {
- /* Put some altars */
- alloc_object(ALLOC_SET_ROOM, ALLOC_TYP_ALTAR, randnor(DUN_AMT_ALTAR, 3));
-
- /* Put some between gates */
- alloc_object(ALLOC_SET_ROOM, ALLOC_TYP_BETWEEN, randnor(DUN_AMT_BETWEEN, 3));
-
- /* Put some fountains */
- alloc_object(ALLOC_SET_ROOM, ALLOC_TYP_FOUNTAIN, randnor(DUN_AMT_FOUNTAIN, 3));
- }
-
- /* Put an Artifact and Artifact Guardian is requested */
- if (d_ptr->final_guardian && (d_ptr->maxdepth == dun_level))
- {
- int oy;
- int ox;
- int m_idx, tries = 10000;
-
- /* Find a good position */
- while (tries)
- {
- /* Get a random spot */
- oy = randint(cur_hgt - 4) + 2;
- ox = randint(cur_wid - 4) + 2;
-
- /* Is it a good spot ? */
- if (cave_empty_bold(oy, ox)) break;
-
- /* One less try */
- tries--;
- }
-
- /* Place the guardian */
- m_allow_special[d_ptr->final_guardian] = TRUE;
- place_monster_one(oy, ox, d_ptr->final_guardian, 0, FALSE, MSTATUS_ENEMY);
- m_allow_special[d_ptr->final_guardian] = FALSE;
-
-
- m_idx = cave[oy][ox].m_idx;
-
- if (!m_idx && wizard) cmsg_print(TERM_L_RED, "WARNING: Could not place guardian.");
-
- /*
- * If guardian is successfully created and his/her/its
- * treasure hasn't been found, let him/her/it own that
- */
- if (m_idx && d_ptr->final_artifact &&
- (a_info[d_ptr->final_artifact].cur_num == 0))
- {
- artifact_type *a_ptr = &a_info[d_ptr->final_artifact];
- object_type *q_ptr, forge, *o_ptr;
- int I_kind, o_idx;
-
- /* Get new object */
- o_idx = o_pop();
-
- /* Proceed only if there's an object slot available */
- if (o_idx)
- {
- a_allow_special[d_ptr->final_artifact] = TRUE;
-
- /* Get local object */
- q_ptr = &forge;
-
- /* Wipe the object */
- object_wipe(q_ptr);
-
- /* Acquire the "kind" index */
- I_kind = lookup_kind(a_ptr->tval, a_ptr->sval);
-
- /* Create the artifact */
- object_prep(q_ptr, I_kind);
-
- /* Save the name */
- q_ptr->name1 = d_ptr->final_artifact;
-
- /* Actually create it */
- apply_magic(q_ptr, -1, TRUE, TRUE, TRUE);
-
- /* Where it is found ? */
- q_ptr->found = OBJ_FOUND_MONSTER;
- q_ptr->found_aux1 = d_ptr->final_guardian;
- q_ptr->found_aux2 = 0;
- q_ptr->found_aux3 = dungeon_type;
- q_ptr->found_aux4 = level_or_feat(dungeon_type, dun_level);
-
- a_allow_special[d_ptr->final_artifact] = FALSE;
-
- /* Get the item */
- o_ptr = &o_list[o_idx];
-
- /* Structure copy */
- object_copy(o_ptr, q_ptr);
-
- /* Build a stack */
- o_ptr->next_o_idx = m_list[m_idx].hold_o_idx;
-
- o_ptr->held_m_idx = m_idx;
- o_ptr->ix = 0;
- o_ptr->iy = 0;
-
- m_list[m_idx].hold_o_idx = o_idx;
- }
- }
-
- if (m_idx && d_ptr->final_object &&
- (k_info[d_ptr->final_object].artifact == FALSE))
- {
- object_type *q_ptr, forge, *o_ptr;
- int o_idx;
-
- /* Get new object */
- o_idx = o_pop();
-
- /* Proceed only if there's an object slot available */
- if (o_idx)
- {
- /* Get local object */
- q_ptr = &forge;
-
- k_allow_special[d_ptr->final_object] = TRUE;
-
- /* Wipe the object */
- object_wipe(q_ptr);
-
- /* Create the final object */
- object_prep(q_ptr, d_ptr->final_object);
- apply_magic(q_ptr, 1, FALSE, FALSE, FALSE);
-
- /* Where it is found ? */
- q_ptr->found = OBJ_FOUND_MONSTER;
- q_ptr->found_aux1 = d_ptr->final_guardian;
- q_ptr->found_aux2 = 0;
- q_ptr->found_aux3 = dungeon_type;
- q_ptr->found_aux4 = level_or_feat(dungeon_type, dun_level);
-
- k_allow_special[d_ptr->final_object] = FALSE;
-
- k_info[d_ptr->final_object].artifact = TRUE;
-
- /* Get the item */
- o_ptr = &o_list[o_idx];
-
- /* Structure copy */
- object_copy(o_ptr, q_ptr);
-
- /* Build a stack */
- o_ptr->next_o_idx = m_list[m_idx].hold_o_idx;
-
- o_ptr->held_m_idx = m_idx;
- o_ptr->ix = 0;
- o_ptr->iy = 0;
-
- m_list[m_idx].hold_o_idx = o_idx;
- }
- }
- }
-
- if ((empty_level) && (randint(DARK_EMPTY) != 1 || (randint(100) > dun_level)))
- wiz_lite();
-
- /* Now double the generated dungeon */
- if (dungeon_flags1 & DF1_DOUBLE)
- {
- /* We begin at the bottom-right corner and from there move
- * up/left (this way we don't need another array for the
- * dungeon data) */
- /* Note: we double the border permanent walls, too. It is
- * easier this way and I think it isn't too ugly */
- for (y = cur_hgt - 1, y1 = y * 2; y >= 0; y--, y1 -= 2)
- for (x = cur_wid - 1, x1 = x * 2; x >= 0; x--, x1 -= 2)
- {
- int disp[4][2] = {{0, 0}, {0, + 1}, { + 1, 0}, { + 1, + 1}};
-
- cave_type *c_ptr[4], *cc_ptr = &cave[y][x];
- object_type *o_ptr = &o_list[cc_ptr->o_idx];
- monster_type *m_ptr = &m_list[cc_ptr->m_idx];
-
- /*
- * Now we copy the generated data to the
- * appropriate grids
- */
- for (i = 0; i < 4; i++)
- {
- c_ptr[i] = &cave[y1 + disp[i][0]][x1 + disp[i][1]];
- *c_ptr[i] = *cc_ptr;
- c_ptr[i]->o_idx = 0;
- c_ptr[i]->m_idx = 0;
-
- if (cc_ptr->feat == FEAT_BETWEEN)
- {
- int xxx = cc_ptr->special & 0xFF;
- int yyy = cc_ptr->special >> 8;
-
- xxx *= 2;
- yyy *= 2;
- xxx += disp[i][1];
- yyy += disp[i][0];
- c_ptr[i]->special = xxx + (yyy << 8);
- }
- }
-
- /* Objects should be put only in 1 of the
- * new grids (otherwise we would segfault
- * a lot) ... */
- if (cc_ptr->o_idx != 0)
- {
- i = rand_int(4);
- c_ptr[i]->o_idx = cc_ptr->o_idx;
- o_ptr->iy = y1 + disp[i][0];
- o_ptr->ix = x1 + disp[i][1];
- }
-
- /* ..just like monsters */
- if (cc_ptr->m_idx != 0)
- {
- i = rand_int(4);
- c_ptr[i]->m_idx = cc_ptr->m_idx;
- m_ptr->fy = y1 + disp[i][0];
- m_ptr->fx = x1 + disp[i][1];
- }
- }
-
- /* Set the width/height ... */
- cur_wid *= 2;
- cur_hgt *= 2;
-
- /* ... and player position to the right place */
- p_ptr->py *= 2;
- p_ptr->px *= 2;
- }
-
- return TRUE;
-}
-
-
-/*
- * Builds the arena after it is entered -KMW-
- */
-static void build_arena(void)
-{
- int yval, y_height, y_depth, xval, x_left, x_right;
- register int i, j;
-
- yval = SCREEN_HGT / 2;
- xval = SCREEN_WID / 2;
- y_height = yval - 10 + SCREEN_HGT;
- y_depth = yval + 10 + SCREEN_HGT;
- x_left = xval - 32 + SCREEN_WID;
- x_right = xval + 32 + SCREEN_WID;
-
- for (i = y_height; i <= y_height + 5; i++)
- {
- for (j = x_left; j <= x_right; j++)
- {
- cave_set_feat(i, j, FEAT_PERM_EXTRA);
- cave[i][j].info |= (CAVE_GLOW | CAVE_MARK);
- }
- }
- for (i = y_depth; i >= y_depth - 5; i--)
- {
- for (j = x_left; j <= x_right; j++)
- {
- cave_set_feat(i, j, FEAT_PERM_EXTRA);
- cave[i][j].info |= (CAVE_GLOW | CAVE_MARK);
- }
- }
- for (j = x_left; j <= x_left + 17; j++)
- {
- for (i = y_height; i <= y_depth; i++)
- {
- cave_set_feat(i, j, FEAT_PERM_EXTRA);
- cave[i][j].info |= (CAVE_GLOW | CAVE_MARK);
- }
- }
- for (j = x_right; j >= x_right - 17; j--)
- {
- for (i = y_height; i <= y_depth; i++)
- {
- cave_set_feat(i, j, FEAT_PERM_EXTRA);
- cave[i][j].info |= (CAVE_GLOW | CAVE_MARK);
- }
- }
-
- cave_set_feat(y_height + 6, x_left + 18, FEAT_PERM_EXTRA);
- cave[y_height + 6][x_left + 18].info |= (CAVE_GLOW | CAVE_MARK);
- cave_set_feat(y_depth - 6, x_left + 18, FEAT_PERM_EXTRA);
- cave[y_depth - 6][x_left + 18].info |= (CAVE_GLOW | CAVE_MARK);
- cave_set_feat(y_height + 6, x_right - 18, FEAT_PERM_EXTRA);
- cave[y_height + 6][x_right - 18].info |= (CAVE_GLOW | CAVE_MARK);
- cave_set_feat(y_depth - 6, x_right - 18, FEAT_PERM_EXTRA);
- cave[y_depth - 6][x_right - 18].info |= (CAVE_GLOW | CAVE_MARK);
-
- i = y_height + 5;
- j = xval + SCREEN_WID;
- cave_set_feat(i, j, FEAT_SHOP);
- cave[i][j].info |= (CAVE_GLOW | CAVE_MARK);
- player_place(i + 1, j);
-}
-
-
-/*
- * Town logic flow for generation of arena -KMW-
- */
-static void arena_gen(void)
-{
- int y, x;
- int qy = SCREEN_HGT;
- int qx = SCREEN_WID;
- bool_ daytime;
-
- /* Day time */
- if ((turn % (10L * DAY)) < ((10L * DAY) / 2))
- daytime = TRUE;
-
- /* Night time */
- else
- daytime = FALSE;
-
- /* Start with solid walls */
- for (y = 0; y < MAX_HGT; y++)
- {
- for (x = 0; x < MAX_WID; x++)
- {
- /* Create "solid" perma-wall */
- cave_set_feat(y, x, FEAT_PERM_SOLID);
-
- /* Illuminate and memorize the walls */
- cave[y][x].info |= (CAVE_GLOW | CAVE_MARK);
- }
- }
-
- /* Then place some floors */
- for (y = qy + 1; y < qy + SCREEN_HGT - 1; y++)
- {
- for (x = qx + 1; x < qx + SCREEN_WID - 1; x++)
- {
- /* Create empty floor */
- cave_set_feat(y, x, FEAT_FLOOR);
-
- /* Darken and forget the floors */
- cave[y][x].info &= ~(CAVE_GLOW | CAVE_MARK);
-
- /* Day time */
- if (daytime)
- {
- /* Perma-Lite */
- cave[y][x].info |= (CAVE_GLOW);
-
- /* Memorize */
- if (view_perma_grids) cave[y][x].info |= (CAVE_MARK);
- }
- }
- }
-
- build_arena();
-
- place_monster_aux(p_ptr->py + 5, p_ptr->px, arena_monsters[p_ptr->arena_number],
- FALSE, FALSE, MSTATUS_ENEMY);
-}
-
-
-/*
- * Generate a quest level
- */
-static void quest_gen(void)
-{
- process_hooks(HOOK_GEN_QUEST, "(d)", is_quest(dun_level));
-}
-
-/*
- * Creates a special level
- */
-
-/* Mega-Hack */
-#define REGEN_HACK 0x02
-
-bool_ build_special_level(void)
-{
- char buf[80];
- int y, x, ystart = 2, xstart = 2;
- s16b level;
-
- /* No special levels on the surface */
- if (!dun_level) return FALSE;
-
- level = dun_level - d_info[dungeon_type].mindepth;
- if ((!get_dungeon_save(buf)) && (special_lvl[level][dungeon_type])) return FALSE;
- if (!get_dungeon_special(buf)) return FALSE;
-
- /* Big town */
- cur_hgt = MAX_HGT;
- cur_wid = MAX_WID;
-
- /* Determine number of panels */
- max_panel_rows = (cur_hgt / SCREEN_HGT) * 2 - 2;
- max_panel_cols = (cur_wid / SCREEN_WID) * 2 - 2;
-
- /* Assume illegal panel */
- panel_row_min = max_panel_rows * (SCREEN_HGT / 2);
- panel_col_min = max_panel_cols * (SCREEN_WID / 2);
-
- /* Start with perm walls */
- for (y = 0; y < cur_hgt; y++)
- {
- for (x = 0; x < cur_wid; x++)
- {
- cave_set_feat(y, x, FEAT_PERM_SOLID);
- }
- }
- /* Set the correct monster hook */
- set_mon_num_hook();
-
- /* Prepare allocation table */
- get_mon_num_prep();
-
- init_flags = INIT_CREATE_DUNGEON | INIT_POSITION;
- process_dungeon_file(buf, &ystart, &xstart, cur_hgt, cur_wid, TRUE, TRUE);
-
- special_lvl[level][dungeon_type] = REGEN_HACK;
- generate_special_feeling = TRUE;
-
- /* Special feeling because it's special */
- good_item_flag = TRUE;
-
- /*
- * Hack -- It's better/more dangerous than a greater vault.
- * Better to have a rating field in special level description.
- */
- rating += 40;
-
- return TRUE;
-}
-
-/*
- * Prepare regeneration of a special level, which should not happen,
- * but just in case...
- */
-static void wipe_special_level(void)
-{
- s16b level;
- char buf[80];
-
- /* No special levels on the surface */
- if (!dun_level) return;
-
- process_hooks(HOOK_LEVEL_REGEN, "()");
-
- /* Calculate relative depth */
- level = dun_level - d_info[dungeon_type].mindepth;
-
- /* No special level at this depth */
- if ((!get_dungeon_save(buf)) &&
- special_lvl[level][dungeon_type]) return;
- if (!get_dungeon_special(buf)) return;
-
- /* Clear the Mega-Hack flag */
- if (special_lvl[level][dungeon_type] == REGEN_HACK)
- special_lvl[level][dungeon_type] = FALSE;
-}
-
-/*
- * Finalise generation of a special level
- */
-static void finalise_special_level(void)
-{
- s16b level;
- char buf[80];
-
- /* No special levels on the surface */
- if (!dun_level) return;
-
- process_hooks(HOOK_LEVEL_END_GEN, "()");
-
- /* Calculate relative depth */
- level = dun_level - d_info[dungeon_type].mindepth;
-
- /* No special level at this depth */
- if ((!get_dungeon_save(buf)) &&
- special_lvl[level][dungeon_type]) return;
- if (!get_dungeon_special(buf)) return;
-
- /* Set the "generated" flag */
- if (special_lvl[level][dungeon_type] == REGEN_HACK)
- special_lvl[level][dungeon_type] = TRUE;
-}
-
-/*
- * Give some magical energy to the each grid of the level
- */
-void generate_grid_mana()
-{
- int y, x, mana, mult;
- bool_ xtra_magic = FALSE;
-
- if (randint(XTRA_MAGIC) == 1)
- {
- xtra_magic = TRUE;
-
- if (cheat_room || p_ptr->precognition)
- {
- msg_print("Magical level");
- }
- }
-
- mult = ((xtra_magic) ? 3 : 2);
-
- for (y = 0; y < cur_hgt; y++)
- {
- for (x = 0; x < cur_wid; x++)
- {
- cave_type *c_ptr = &cave[y][x];
-
- /* Calculate the amount of mana in each grid */
- mana = mult * m_bonus(255, dun_level) / 2;
- if (xtra_magic) mana += 10 + rand_int(10);
-
- /* Never more than 255 or less than 0(paranoia) */
- if (mana < 0) mana = 0;
- if (mana > 255) mana = 255;
-
- c_ptr->mana = mana;
- }
- }
-}
-
-
-/*
- * Generates a random dungeon level -RAK-
- *
- * Hack -- regenerate any "overflow" levels
- *
- * Hack -- allow auto-scumming via a gameplay option.
- */
-void generate_cave(void)
-{
- dungeon_info_type *d_ptr = &d_info[dungeon_type];
- int tester_1, tester_2;
- int y, x, num, i;
- bool_ loaded = FALSE;
- char buf[80];
- s16b town_level = 0;
-
- /* The dungeon is not ready */
- character_dungeon = FALSE;
- generate_special_feeling = FALSE;
-
- /* Initialize the flags with the basic dungeon flags */
- if (!dun_level)
- {
- dungeon_flags1 = d_info[DUNGEON_WILDERNESS].flags1;
- dungeon_flags2 = d_info[DUNGEON_WILDERNESS].flags2;
- }
- else
- {
- dungeon_flags1 = d_ptr->flags1;
- dungeon_flags2 = d_ptr->flags2;
- }
-
- /* Is it a town level ? */
- for (i = 0; i < TOWN_DUNGEON; i++)
- {
- if (d_ptr->t_level[i] == dun_level) town_level = d_ptr->t_idx[i];
- }
-
- /* Save the imprinted monsters */
- save_all_friends();
- wipe_m_list();
-
- /* Seed the RNG if appropriate */
- if (town_level)
- {
- Rand_quick = TRUE;
- Rand_value = town_info[town_level].seed;
- }
-
- process_hooks(HOOK_GEN_LEVEL_BEGIN, "");
-
- /* Try to load a saved level */
- if (get_dungeon_save(buf))
- {
- /* No effects */
- for (i = 0; i < MAX_EFFECTS; i++)
- {
- effects[i].time = 0;
- }
-
- /* Start with a blank cave */
- for (y = 0; y < MAX_HGT; y++)
- {
- for (x = 0; x < MAX_WID; x++)
- {
- /* No flags */
- cave[y][x].info = 0;
-
- /* No features */
- cave_set_feat(y, x, FEAT_PERM_INNER);
-
- /* No objects */
- cave[y][x].o_idx = 0;
-
- /* No monsters */
- cave[y][x].m_idx = 0;
-
- /* No traps */
- cave[y][x].t_idx = 0;
-
- /* No mimic */
- cave[y][x].mimic = 0;
-
- /* No effects */
- cave[y][x].effect = 0;
-
- /* No inscription */
- cave[y][x].inscription = 0;
-
- /* No flow */
- cave[y][x].cost = 0;
- cave[y][x].when = 0;
- }
- }
-
- loaded = load_dungeon(buf);
- }
-
- /* No saved level -- generate new one */
- if (!loaded)
- {
- if (!get_dungeon_special(buf) ||
- !special_lvl[dun_level - d_info[dungeon_type].mindepth][dungeon_type])
- {
- get_level_flags();
- }
-
- /* Generate */
- for (num = 0; TRUE; num++)
- {
- bool_ okay = TRUE;
-
- cptr why = NULL;
-
- /* No effects */
- for (i = 0; i < MAX_EFFECTS; i++)
- {
- effects[i].time = 0;
- }
-
- /* Start with a blank cave */
- for (y = 0; y < MAX_HGT; y++)
- {
- for (x = 0; x < MAX_WID; x++)
- {
- /* No flags */
- cave[y][x].info = 0;
-
- /* No features */
- cave_set_feat(y, x, FEAT_PERM_INNER);
-
- /* No objects */
- cave[y][x].o_idx = 0;
-
- /* No monsters */
- cave[y][x].m_idx = 0;
-
- /* No traps */
- cave[y][x].t_idx = 0;
-
- /* No mimic */
- cave[y][x].mimic = 0;
-
- /* No effect */
- cave[y][x].effect = 0;
-
- /* No inscription */
- cave[y][x].inscription = 0;
-
- /* No flow */
- cave[y][x].cost = 0;
- cave[y][x].when = 0;
- }
- }
-
-
- /* XXX XXX XXX XXX */
- o_max = 1;
-
-
- /* Mega-Hack -- no player yet */
- p_ptr->px = p_ptr->py = 0;
-
-
- /* Mega-Hack -- no panel yet */
- panel_row_min = 0;
- panel_row_max = 0;
- panel_col_min = 0;
- panel_col_max = 0;
-
-
- /* Reset the monster generation level */
- if (dungeon_type != DUNGEON_DEATH) monster_level = dun_level;
- else monster_level = (p_ptr->lev * 2) + 10 + rand_int(40);
-
- /* Reset the object generation level */
- object_level = dun_level;
-
- /* Nothing special here yet */
- good_item_flag = FALSE;
-
- /* Nothing good here yet */
- rating = 0;
-
- /* No ambush here yet */
- ambush_flag = FALSE;
-
- /* No fated level here yet */
- fate_flag = FALSE;
-
- /* Build the arena -KMW- */
- if (p_ptr->inside_arena)
- {
- /* Small arena */
- arena_gen();
- }
-
- /* Quest levels -KMW- */
- else if (p_ptr->inside_quest)
- {
- quest_gen();
- }
-
- /* Special levels */
- else if (build_special_level())
- {
- /* nothing */
- }
-
- /* Build the town */
- else if (!dun_level)
- {
- /* Big town */
- cur_hgt = MAX_HGT;
- cur_wid = MAX_WID;
-
- /* Determine number of panels */
- max_panel_rows = (cur_hgt / SCREEN_HGT) * 2 - 2;
- max_panel_cols = (cur_wid / SCREEN_WID) * 2 - 2;
-
- /* Assume illegal panel */
- panel_row_min = max_panel_rows * (SCREEN_HGT / 2);
- panel_col_min = max_panel_cols * (SCREEN_WID / 2);
-
- /* Big wilderness mode */
- if (!p_ptr->wild_mode)
- {
- /* Make the wilderness */
- wilderness_gen(0);
- }
-
- /* Small wilderness mode */
- else
- {
- /* Make the wilderness */
- wilderness_gen_small();
- }
-
-
- okay = TRUE;
- }
-
- /* Build a dungeon level */
- else
- {
- /* Requested size level */
- if (d_ptr->size_x != -1)
- {
- if (cheat_room || p_ptr->precognition)
- {
- msg_print ("A 'size' dungeon level.");
- }
-
- cur_hgt = d_ptr->size_y * SCREEN_HGT;
- cur_wid = d_ptr->size_x * SCREEN_WID;
-
- /* Determine number of panels */
- max_panel_rows = (cur_hgt / SCREEN_HGT) * 2 - 2;
- max_panel_cols = (cur_wid / SCREEN_WID) * 2 - 2;
-
- /* Assume illegal panel */
- panel_row_min = max_panel_rows * (SCREEN_HGT / 2);
- panel_col_min = max_panel_cols * (SCREEN_WID / 2);
-
- if (cheat_room)
- {
- msg_format("X:%d, Y:%d.", max_panel_cols, max_panel_rows);
- }
- }
- /* Very small (1 x 1 panel) level */
- else if (!(dungeon_flags1 & DF1_BIG) &&
- (dungeon_flags1 & DF1_SMALLEST))
- {
- if (cheat_room || p_ptr->precognition)
- {
- msg_print ("A 'small' dungeon level.");
- }
-
- cur_hgt = SCREEN_HGT;
- cur_wid = SCREEN_WID;
-
- /* Determine number of panels */
- max_panel_rows = 1;
- max_panel_cols = 1;
-
- /* Assume illegal panel */
- panel_row_min = max_panel_rows * (SCREEN_HGT / 2);
- panel_col_min = max_panel_cols * (SCREEN_WID / 2);
-
- if (cheat_room)
- {
- msg_format("X:1, Y:1.");
- }
- }
-
- /* Small level */
- else if (!(dungeon_flags1 & DF1_BIG) &&
- (always_small_level ||
- (dungeon_flags1 & DF1_SMALL) ||
- (small_levels && rand_int(SMALL_LEVEL) == 0)))
- {
- if (cheat_room || p_ptr->precognition)
- {
- msg_print ("A 'small' dungeon level.");
- }
-
- tester_1 = rand_range(1, (MAX_HGT / SCREEN_HGT));
- tester_2 = rand_range(1, (MAX_WID / SCREEN_WID) - 1);
-
- cur_hgt = tester_1 * SCREEN_HGT;
- cur_wid = tester_2 * SCREEN_WID;
-
- /* Determine number of panels */
- max_panel_rows = (cur_hgt / SCREEN_HGT) * 2 - 2;
- max_panel_cols = (cur_wid / SCREEN_WID) * 2 - 2;
-
- /* Assume illegal panel */
- panel_row_min = max_panel_rows * (SCREEN_HGT / 2);
- panel_col_min = max_panel_cols * (SCREEN_WID / 2);
-
- if (cheat_room)
- {
- msg_format("X:%d, Y:%d.", max_panel_cols, max_panel_rows);
- }
- }
-
- /* Normal level */
- else
- {
- /* Use full panels */
- cur_hgt = MAX_HGT;
- cur_wid = MAX_WID;
-
- /* Determine number of panels */
- max_panel_rows = (cur_hgt / SCREEN_HGT) * 2 - 2;
- max_panel_cols = (cur_wid / SCREEN_WID) * 2 - 2;
-
- /* Assume illegal panel */
- panel_row_min = max_panel_rows * (SCREEN_HGT / 2);
- panel_col_min = max_panel_cols * (SCREEN_WID / 2);
- }
-
- /* Generate a level */
- if (!cave_gen())
- {
- why = "could not place player";
- okay = FALSE;
- }
- }
-
- /* Extract the feeling */
- if (rating > 100) feeling = 2;
- else if (rating > 80) feeling = 3;
- else if (rating > 60) feeling = 4;
- else if (rating > 40) feeling = 5;
- else if (rating > 30) feeling = 6;
- else if (rating > 20) feeling = 7;
- else if (rating > 10) feeling = 8;
- else if (rating > 0) feeling = 9;
- else feeling = 10;
-
- /* Hack -- Have a special feeling sometimes */
- if (good_item_flag && !p_ptr->preserve) feeling = 1;
-
- /* It takes 1000 game turns for "feelings" to recharge */
- if ((turn - old_turn) < 1000) feeling = 0;
-
- /* Hack -- no feeling in the town */
- if (!dun_level) feeling = 0;
-
-
- /* Prevent object over-flow */
- if (o_max >= max_o_idx)
- {
- /* Message */
- why = "too many objects";
-
- /* Message */
- okay = FALSE;
- }
-
- /* Prevent monster over-flow */
- if (m_max >= max_m_idx)
- {
- /* Message */
- why = "too many monsters";
-
- /* Message */
- okay = FALSE;
- }
-
- /* Mega-Hack -- "auto-scum" */
- if (auto_scum && (num < 100) && !p_ptr->inside_quest && dun_level)
- {
- /* Require "goodness" */
- if ((feeling > 9) ||
- ((dun_level >= 5) && (feeling > 8)) ||
- ((dun_level >= 10) && (feeling > 7)) ||
- ((dun_level >= 20) && (feeling > 6)) ||
- ((dun_level >= 40) && (feeling > 5)))
- {
- /* Give message to cheaters */
- if (cheat_room || cheat_hear ||
- cheat_peek || cheat_xtra || p_ptr->precognition)
- {
- /* Message */
- why = "boring level";
- }
-
- /* Try again */
- okay = FALSE;
- }
- }
-
- /* Accept */
- if (okay || town_level) break;
-
- /* Message */
- if (why) msg_format("Generation restarted (%s)", why);
-
- /* Wipe the objects */
- wipe_o_list();
-
- /* Wipe the monsters */
- wipe_m_list();
-
- /* Clear the fate icky flags */
- for (i = 0; i < MAX_FATES; i++) fates[i].icky = FALSE;
-
- /*
- * Mega-Hack -- Reset special level flag if necessary
- * XXX XXX XXX
- */
- wipe_special_level();
- }
-
- /* Give some mana to each grid -- DG */
- generate_grid_mana();
- }
-
- /* Put the kept monsters -- DG */
- if (!p_ptr->wild_mode) replace_all_friends();
-
- /* Hack -- Clear used up fates */
- for (i = 0; i < MAX_FATES; i++)
- {
- if (fates[i].icky)
- {
- /* Mark the artefact as generated */
- if ((fates[i].fate == FATE_FIND_A) && fates[i].a_idx)
- {
- a_info[fates[i].a_idx].cur_num = 1;
- }
- fates[i].fate = FATE_NONE;
- fates[i].icky = FALSE;
- }
- }
-
- /* Set special level generated flag if applicable */
- finalise_special_level();
-
- /* No teleporatations yet */
- last_teleportation_y = -1;
- last_teleportation_x = -1;
-
- /* Mark the dungeon town as found */
- if (town_level)
- {
- /* Set the known flag */
- town_info[town_level].flags |= (TOWN_KNOWN);
- }
-
- /* The dungeon is ready */
- character_dungeon = TRUE;
-
- /* Remember when this level was "created" */
- old_turn = turn;
-
- /* Provide astral chars with the full map */
- if (p_ptr->astral && dun_level)
- {
- wiz_lite_extra();
- }
-
- /* Player should get the first move upon entering the dungeon */
- p_ptr->energy = 100;
-}