#include "rooms.h"
#include "streams.h"
-int dun_rooms;
-
int dun_tun_rnd;
int dun_tun_chg;
int dun_tun_con;
*/
dun_data *dun;
+
/*
* Places some staircases near walls
*/
/*
- * Generate a new dungeon level
+ * Generate various caverns and lakes
*
- * Note that "dun_body" adds about 4000 bytes of memory to the stack.
+ * There were moved from cave_gen().
*/
-static bool cave_gen(void)
+static void gen_caverns_and_lakes(void)
{
- int i, j, k, y, x, y1, x1;
+#ifdef ALLOW_CAVERNS_AND_LAKES
+ /* Possible "destroyed" level */
+ if ((dun_level > 30) && one_in_(DUN_DEST*2) && (small_levels) && (d_info[dungeon_type].flags1 & DF1_DESTROY))
+ {
+ dun->destroyed = TRUE;
- int max_vault_ok = 2;
+ /* extra rubble around the place looks cool */
+ build_lake(one_in_(2) ? LAKE_T_CAVE : LAKE_T_EARTH_VAULT);
+ }
- int feat1 = 0, feat2 = 0;
+ /* Make a lake some of the time */
+ if (one_in_(LAKE_LEVEL) && !dun->empty_level && !dun->destroyed &&
+ (d_info[dungeon_type].flags1 & DF1_LAKE_MASK))
+ {
+ int count = 0;
+ if (d_info[dungeon_type].flags1 & DF1_LAKE_WATER) count += 3;
+ if (d_info[dungeon_type].flags1 & DF1_LAKE_LAVA) count += 3;
+ if (d_info[dungeon_type].flags1 & DF1_LAKE_RUBBLE) count += 3;
+ if (d_info[dungeon_type].flags1 & DF1_LAKE_TREE) count += 3;
- cave_type *c_ptr;
+ if (d_info[dungeon_type].flags1 & DF1_LAKE_LAVA)
+ {
+ /* Lake of Lava */
+ if ((dun_level > 80) && (randint0(count) < 2)) dun->laketype = LAKE_T_LAVA;
+ count -= 2;
+
+ /* Lake of Lava2 */
+ if (!dun->laketype && (dun_level > 80) && one_in_(count)) dun->laketype = LAKE_T_FIRE_VAULT;
+ count--;
+ }
+
+ if ((d_info[dungeon_type].flags1 & DF1_LAKE_WATER) && !dun->laketype)
+ {
+ /* Lake of Water */
+ if ((dun_level > 50) && randint0(count) < 2) dun->laketype = LAKE_T_WATER;
+ count -= 2;
+
+ /* Lake of Water2 */
+ if (!dun->laketype && (dun_level > 50) && one_in_(count)) dun->laketype = LAKE_T_WATER_VAULT;
+ count--;
+ }
+
+ if ((d_info[dungeon_type].flags1 & DF1_LAKE_RUBBLE) && !dun->laketype)
+ {
+ /* Lake of rubble */
+ if ((dun_level > 35) && (randint0(count) < 2)) dun->laketype = LAKE_T_CAVE;
+ count -= 2;
+
+ /* Lake of rubble2 */
+ if (!dun->laketype && (dun_level > 35) && one_in_(count)) dun->laketype = LAKE_T_EARTH_VAULT;
+ count--;
+ }
+
+ /* Lake of tree */
+ if ((dun_level > 5) && (d_info[dungeon_type].flags1 & DF1_LAKE_TREE) && !dun->laketype) dun->laketype = LAKE_T_AIR_VAULT;
+
+ if (dun->laketype)
+ {
+ if (cheat_room)
+#ifdef JP
+ msg_print("¸Ð¤òÀ¸À®¡£");
+#else
+ msg_print("Lake on the level.");
+#endif
- bool destroyed = FALSE;
- bool empty_level = FALSE;
- bool cavern = FALSE;
- int laketype = 0;
+ build_lake(dun->laketype);
+ }
+ }
+
+ if ((dun_level > DUN_CAVERN) && !dun->empty_level &&
+ (d_info[dungeon_type].flags1 & DF1_CAVERN) &&
+ !dun->laketype && !dun->destroyed && (randint1(1000) < dun_level))
+ {
+ dun->cavern = TRUE;
+
+ /* make a large fractal cave in the middle of the dungeon */
+
+ if (cheat_room)
+#ifdef JP
+ msg_print("ƶ·¢¤òÀ¸À®¡£");
+#else
+ msg_print("Cavern on level.");
+#endif
+ build_cavern();
+ }
+#endif /* ALLOW_CAVERNS_AND_LAKES */
+
+ /* Hack -- No destroyed "quest" levels */
+ if (quest_number(dun_level)) dun->destroyed = FALSE;
+}
+
+
+
+/*
+ * 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;
dun_data dun_body;
+ /* Global data */
+ dun = &dun_body;
+
+ dun->destroyed = FALSE;
+ dun->empty_level = FALSE;
+ dun->cavern = FALSE;
+ dun->laketype = 0;
+
/* Fill the arrays of floors and walls in the good proportions */
set_floor_and_wall(dungeon_type);
feat_wall_inner = d_info[dungeon_type].inner_wall;
feat_wall_solid = d_info[dungeon_type].outer_wall;
- /* Global data */
- dun = &dun_body;
-
- if (cur_hgt <= SCREEN_HGT / 2 - 2) max_vault_ok--;
- if (cur_wid <= SCREEN_WID / 2 - 2) max_vault_ok--;
-
/* Randomize the dungeon creation values */
- dun_rooms = rand_range(DUN_ROOMS_MIN, DUN_ROOMS_MAX);
dun_tun_rnd = rand_range(DUN_TUN_RND_MIN, DUN_TUN_RND_MAX);
dun_tun_chg = rand_range(DUN_TUN_CHG_MIN, DUN_TUN_CHG_MAX);
dun_tun_con = rand_range(DUN_TUN_CON_MIN, DUN_TUN_CON_MAX);
}
}
- /* No "crowded" rooms yet */
- dun->crowded = 0;
-
/* No rooms yet */
dun->cent_n = 0;
/* Empty arena levels */
if (ironman_empty_levels || ((d_info[dungeon_type].flags1 & DF1_ARENA) && (empty_levels && one_in_(EMPTY_LEVEL))))
{
- empty_level = TRUE;
+ dun->empty_level = TRUE;
if (cheat_room)
#ifdef JP
#endif
}
- if (empty_level)
+ if (dun->empty_level)
{
/* Start with floors */
for (y = 0; y < cur_hgt; y++)
}
}
-#ifdef ALLOW_CAVERNS_AND_LAKES
- /* Possible "destroyed" level */
- if ((dun_level > 30) && one_in_(DUN_DEST*2) && (small_levels) && (d_info[dungeon_type].flags1 & DF1_DESTROY))
- {
- destroyed = TRUE;
- /* extra rubble around the place looks cool */
- build_lake(one_in_(2) ? GEN_LAKE_TYPE_CAVE : GEN_LAKE_TYPE_EARTH_VAULT);
- }
+ /* Generate various caverns and lakes */
+ gen_caverns_and_lakes();
- /* Make a lake some of the time */
- if (one_in_(LAKE_LEVEL) && !empty_level && !destroyed &&
- (d_info[dungeon_type].flags1 & DF1_LAKE_MASK))
- {
- int count = 0;
- if (d_info[dungeon_type].flags1 & DF1_LAKE_WATER) count += 3;
- if (d_info[dungeon_type].flags1 & DF1_LAKE_LAVA) count += 3;
- if (d_info[dungeon_type].flags1 & DF1_LAKE_RUBBLE) count += 3;
- if (d_info[dungeon_type].flags1 & DF1_LAKE_TREE) count += 3;
-
- if (d_info[dungeon_type].flags1 & DF1_LAKE_LAVA)
- {
- /* Lake of Lava */
- if ((dun_level > 80) && (randint0(count) < 2)) laketype = GEN_LAKE_TYPE_LAVA;
- count -= 2;
-
- /* Lake of Lava2 */
- if (!laketype && (dun_level > 80) && one_in_(count)) laketype = GEN_LAKE_TYPE_FIRE_VAULT;
- count--;
- }
-
- if ((d_info[dungeon_type].flags1 & DF1_LAKE_WATER) && !laketype)
- {
- /* Lake of Water */
- if ((dun_level > 50) && randint0(count) < 2) laketype = GEN_LAKE_TYPE_WATER;
- count -= 2;
-
- /* Lake of Water2 */
- if (!laketype && (dun_level > 50) && one_in_(count)) laketype = GEN_LAKE_TYPE_WATER_VAULT;
- count--;
- }
-
- if ((d_info[dungeon_type].flags1 & DF1_LAKE_RUBBLE) && !laketype)
- {
- /* Lake of rubble */
- if ((dun_level > 35) && (randint0(count) < 2)) laketype = GEN_LAKE_TYPE_CAVE;
- count -= 2;
-
- /* Lake of rubble2 */
- if (!laketype && (dun_level > 35) && one_in_(count)) laketype = GEN_LAKE_TYPE_EARTH_VAULT;
- count--;
- }
-
- /* Lake of tree */
- if ((dun_level > 5) && (d_info[dungeon_type].flags1 & DF1_LAKE_TREE) && !laketype) laketype = GEN_LAKE_TYPE_AIR_VAULT;
-
- if (laketype)
- {
- if (cheat_room)
-#ifdef JP
- msg_print("¸Ð¤òÀ¸À®¡£");
-#else
- msg_print("Lake on the level.");
-#endif
-
- build_lake(laketype);
- }
- }
-
- if ((dun_level > DUN_CAVERN) && !empty_level &&
- (d_info[dungeon_type].flags1 & DF1_CAVERN) &&
- !laketype && !destroyed && (randint1(1000) < dun_level))
- {
- cavern = TRUE;
-
- /* make a large fractal cave in the middle of the dungeon */
-
- if (cheat_room)
-#ifdef JP
- msg_print("ƶ·¢¤òÀ¸À®¡£");
-#else
- msg_print("Cavern on level.");
-#endif
-
- build_cavern();
- }
-#endif /* ALLOW_CAVERNS_AND_LAKES */
-
- /* Hack -- No destroyed "quest" levels */
- if (quest_number(dun_level)) destroyed = FALSE;
/* Build maze */
if (d_info[dungeon_type].flags1 & DF1_MAZE)
/* Build some rooms */
else
{
- for (i = 0; i < dun_rooms; i++)
- {
- bool force_rooms = (ironman_rooms && !((d_info[dungeon_type].flags1 & DF1_BEGINNER) || (d_info[dungeon_type].flags1 & DF1_CHAMELEON)));
-
- /* Pick a block for the room */
- y = randint0(dun->row_rooms);
- x = randint0(dun->col_rooms);
-
- /* Align dungeon rooms */
- if (d_info[dungeon_type].flags1 & DF1_NO_CAVE)
- {
- /* Slide some rooms right */
- if ((x % 3) == 0) x++;
-
- /* Slide some rooms left */
- if ((x % 3) == 2) x--;
- }
+ /*
+ * Build each type of room in turn until we cannot build any more.
+ */
+ generate_rooms();
- /* Attempt an "unusual" room */
- if (force_rooms || (randint0(DUN_UNUSUAL) < dun_level))
- {
- /* Roll for room type */
- while (1)
- {
- k = (force_rooms ? 0 : randint0(100));
- if (force_rooms) break;
- if ((d_info[dungeon_type].flags1 & DF1_NO_VAULT) && (k < 14)) continue;
- break;
- }
-
- /* Attempt a very unusual room */
- if (force_rooms || (randint0(DUN_UNUSUAL) < dun_level))
- {
-#ifdef FORCE_V_IDX
- if (room_build(y, x, ROOM_BUILD_TYPE_GREATER_VAULT)) continue;
-#else
- /* Type 8 -- Greater vault (4%) */
- if (k < 4)
- {
- if (max_vault_ok > 1)
- {
- if (room_build(y, x, ROOM_BUILD_TYPE_GREATER_VAULT)) continue;
- }
- else
- {
-#ifdef JP
- if (cheat_room) msg_print("µðÂç¤ÊÃϲ¼¼¼¤òµÑ²¼¤·¤Þ¤¹¡£");
-#else
- if (cheat_room) msg_print("Refusing a greater vault.");
-#endif
- }
- }
-
- /* Type 7 -- Lesser vault (6%) */
- if (k < 10)
- {
- if (max_vault_ok > 0)
- {
- if (room_build(y, x, ROOM_BUILD_TYPE_LESSER_VAULT)) continue;
- }
- else
- {
-#ifdef JP
- if (cheat_room) msg_print("¾®¤µ¤ÊÃϲ¼¼¼¤òµÑ²¼¤·¤Þ¤¹¡£");
-#else
- if (cheat_room) msg_print("Refusing a lesser vault.");
-#endif
- }
- }
-
-
- /* Type 10 -- Random vault (4%) */
- if ((k < 14) && room_build(y, x, ROOM_BUILD_TYPE_RANDOM_VAULT)) continue;
-
- /* Type 5 -- Monster nest (8%) */
- if ((k < 22) && room_build(y, x, ROOM_BUILD_TYPE_NEST)) continue;
-
- /* Type 6 -- Monster pit (10%) */
- if ((k < 32) && room_build(y, x, ROOM_BUILD_TYPE_PIT)) continue;
-
- /* Type 13 -- Trapped monster pit (5%) */
- if ((k < 37) && room_build(y, x, ROOM_BUILD_TYPE_TRAP_PIT)) continue;
-
- /* Type 14 -- Trapped room (5%) */
- if ((k < 42) && room_build(y, x, ROOM_BUILD_TYPE_TRAP)) continue;
-#endif
- }
-
- /* Type 2 -- Overlapping (25%) */
- if ((k < 25) && room_build(y, x, ROOM_BUILD_TYPE_OVERLAP)) continue;
-
- /* Type 3 -- Cross room (25%) */
- if ((k < 50) && room_build(y, x, ROOM_BUILD_TYPE_CROSS)) continue;
-
- if (d_info[dungeon_type].flags1 & DF1_NO_CAVE)
- {
- if (room_build(y, x, ROOM_BUILD_TYPE_INNER_FEAT)) continue;
- }
- else
- {
- /* Type 4 -- Large room (25%) */
- if ((k < 75) && room_build(y, x, ROOM_BUILD_TYPE_INNER_FEAT)) continue;
-
- /* Type 11 -- Circular (10%) */
- if ((k < 85) && room_build(y, x, ROOM_BUILD_TYPE_OVAL)) continue;
-
- /* Type 12 -- Crypt (15%) */
- if ((k < 100) && room_build(y, x, ROOM_BUILD_TYPE_CRYPT)) continue;
- }
- }
-
- /* The deeper you are, the more cavelike the rooms are */
- k = randint1(100);
-
- /* No caves when a cavern exists: they look bad */
- if (((k < dun_level) || (d_info[dungeon_type].flags1 & DF1_CAVE))
- && !cavern && !empty_level && !laketype
- && !(d_info[dungeon_type].flags1 & DF1_NO_CAVE))
- {
- /* Type 9 -- Fractal cave */
- if (room_build(y, x, ROOM_BUILD_TYPE_FRACAVE)) continue;
- }
- else
- {
- /* Attempt a "trivial" room */
- if (room_build(y, x, ROOM_BUILD_TYPE_NORMAL)) continue;
- }
-
- continue;
- }
/* Make a hole in the dungeon roof sometimes at level 1 */
if (dun_level == 1)
}
/* Destroy the level if necessary */
- if (destroyed) destroy_level();
+ if (dun->destroyed) destroy_level();
/* Hack -- Add some rivers */
if (one_in_(3) && (randint1(dun_level) > 5))
{
+ int feat1 = 0, feat2 = 0;
+
/* Choose water or lava */
if ((randint1(MAX_DEPTH * 2) - 1 > dun_level) && (d_info[dungeon_type].flags1 & DF1_WATER_RIVER))
{
/* Only add river if matches lake type or if have no lake at all */
- if ((((laketype == GEN_LAKE_TYPE_LAVA) && (feat1 == FEAT_DEEP_LAVA)) ||
- ((laketype == GEN_LAKE_TYPE_WATER) && (feat1 == FEAT_DEEP_WATER)) ||
- !laketype) && feat1)
+ if ((((dun->laketype == LAKE_T_LAVA) && (feat1 == FEAT_DEEP_LAVA)) ||
+ ((dun->laketype == LAKE_T_WATER) && (feat1 == FEAT_DEEP_WATER)) ||
+ !dun->laketype) && feat1)
{
add_river(feat1, feat2);
}
/* Hack -- Scramble the room order */
for (i = 0; i < dun->cent_n; i++)
{
- int pick1 = randint0(dun->cent_n);
- int pick2 = randint0(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;
+ int ty, tx;
+ int pick = rand_range(0, i);
+
+ ty = dun->cent[i].y;
+ tx = dun->cent[i].x;
+ dun->cent[i].y = dun->cent[pick].y;
+ dun->cent[i].x = dun->cent[pick].x;
+ dun->cent[pick].y = ty;
+ dun->cent[pick].x = tx;
}
/* Start with no tunnel doors */
/* Connect all the rooms together */
for (i = 0; i < dun->cent_n; i++)
{
+ int j;
+
/* Reset the arrays */
dun->tunn_n = 0;
dun->wall_n = 0;
/* Turn the tunnel into corridor */
for (j = 0; j < dun->tunn_n; j++)
{
+ cave_type *c_ptr;
+
/* Access the grid */
y = dun->tunn[j].y;
x = dun->tunn[j].x;
/* Apply the piercings that we found */
for (j = 0; j < dun->wall_n; j++)
{
+ cave_type *c_ptr;
+
/* Access the grid */
y = dun->wall[j].y;
x = dun->wall[j].x;
if (!alloc_stairs(FEAT_LESS, rand_range(1, 2), 3)) return FALSE;
}
- if (!laketype)
+ if (!dun->laketype)
{
if (d_info[dungeon_type].stream2)
{
/* Put the Guardian */
(void)alloc_guardian();
- if (empty_level && (!one_in_(DARK_EMPTY) || (randint1(100) > dun_level)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS))
+ if (dun->empty_level && (!one_in_(DARK_EMPTY) || (randint1(100) > dun_level)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS))
{
/* Lite the cave */
for (y = 0; y < cur_hgt; y++)
/*
- * Array of minimum room depths
+ * [from SAngband (originally from OAngband)]
+ *
+ * Table of values that control how many times each type of room will
+ * appear. Each type of room has its own row, and each column
+ * corresponds to dungeon levels 0, 10, 20, and so on. The final
+ * value is the minimum depth the room can appear at. -LM-
+ *
+ * Level 101 and below use the values for level 100.
+ *
+ * Rooms with lots of monsters or loot may not be generated if the
+ * object or monster lists are already nearly full. Rooms will not
+ * appear above their minimum depth. Tiny levels will not have space
+ * for all the rooms you ask for.
*/
-static s16b roomdep[] =
+static room_info_type room_info_normal[ROOM_T_MAX] =
{
- 0, /* 0 = Nothing */
- 1, /* 1 = Simple (33x11) */
- 1, /* 2 = Overlapping (33x11) */
- 3, /* 3 = Crossed (33x11) */
- 3, /* 4 = Large (33x11) */
- 10, /* 5 = Monster nest (33x11) */
- 10, /* 6 = Monster pit (33x11) */
- 10, /* 7 = Lesser vault (33x22) */
- 20, /* 8 = Greater vault (66x44) */
- 5, /* 9 = Fractal cave (42x24) */
- 10, /* 10 = Random vault (44x22) */
- 3, /* 11 = Circular rooms (22x22) */
- 10, /* 12 = Crypts (22x22) */
- 20, /* 13 = Trapped monster pit */
- 20, /* 14 = Piranha/Armageddon trap room */
+ /* Depth */
+ /* 0 10 20 30 40 50 60 70 80 90 100 min limit */
+
+ {{999,900,800,700,600,500,400,300,200,100, 0}, 0}, /*NORMAL */
+ {{ 1, 10, 20, 30, 40, 50, 60, 70, 80, 90,100}, 1}, /*OVERLAP */
+ {{ 1, 10, 20, 30, 40, 50, 60, 70, 80, 90,100}, 3}, /*CROSS */
+ {{ 1, 10, 20, 30, 40, 50, 60, 70, 80, 90,100}, 3}, /*INNER_F */
+ {{ 0, 1, 1, 1, 2, 3, 5, 6, 8, 10, 13}, 10}, /*NEST */
+ {{ 0, 1, 1, 2, 3, 4, 6, 8, 10, 13, 16}, 10}, /*PIT */
+ {{ 0, 1, 1, 1, 2, 2, 3, 5, 6, 8, 10}, 10}, /*LESSER_V */
+ {{ 0, 0, 1, 1, 1, 2, 2, 3, 4, 5, 6}, 20}, /*GREATER_V*/
+ {{ 0,100,200,300,400,500,600,700,800,900,999}, 10}, /*FRACAVE */
+ {{ 0, 1, 1, 1, 1, 2, 2, 3, 4, 5, 6}, 10}, /*RANDOM_V */
+ {{ 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40}, 3}, /*OVAL */
+ {{ 1, 6, 12, 18, 24, 30, 36, 42, 48, 54, 60}, 10}, /*CRYPT */
+ {{ 0, 0, 1, 1, 1, 2, 3, 4, 5, 6, 8}, 20}, /*TRAP_PIT */
+ {{ 0, 0, 1, 1, 1, 2, 3, 4, 5, 6, 8}, 20}, /*TRAP */
+};
+
+
+/* Build rooms in descending order of difficulty. */
+static byte room_build_order[ROOM_T_MAX] = {
+ ROOM_T_GREATER_VAULT,
+ ROOM_T_RANDOM_VAULT,
+ ROOM_T_LESSER_VAULT,
+ ROOM_T_TRAP_PIT,
+ ROOM_T_PIT,
+ ROOM_T_NEST,
+ ROOM_T_TRAP,
+ ROOM_T_INNER_FEAT,
+ ROOM_T_OVAL,
+ ROOM_T_CRYPT,
+ ROOM_T_OVERLAP,
+ ROOM_T_CROSS,
+ ROOM_T_FRACAVE,
+ ROOM_T_NORMAL,
};
/*
- * This function is used to allocate the space needed by a room in the room_map
- * array.
- * x, y 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.
- * xx, yy are the returned center of the allocated room in coordinates for
- * cave.feat and cave.info etc.
+ * Find a good spot for the next room. -LM-
+ *
+ * Find and allocate a free space in the dungeon large enough to hold
+ * the room calling this function.
+ *
+ * We allocate space in 11x11 blocks, but want to make sure that rooms
+ * align neatly on the standard screen. Therefore, we make them use
+ * blocks in few 11x33 rectangles as possible.
+ *
+ * Be careful to include the edges of the room in height and width!
+ *
+ * Return TRUE and values for the center of the room if all went well.
+ * Otherwise, return FALSE.
*/
-static bool room_alloc(int x, int y, bool crowded, int by0, int bx0, int *xx, int *yy)
+static bool find_space(int *y, int *x, int height, int width)
{
- int temp, bx1, bx2, by1, by2, by, bx;
+ int i;
+ int by, bx, by1, bx1, by2, bx2;
+ int block_y, block_x;
- /* Calculate number of room_map squares to allocate */
+ bool filled;
- /* temp is total number along width */
- temp = ((x - 1) / BLOCK_WID) + 1;
- /* bx2 = ending block */
- bx2 = temp / 2 + bx0;
+ /* Find out how many blocks we need. */
+ int blocks_high = 1 + ((height - 1) / BLOCK_HGT);
+ int blocks_wide = 1 + ((width - 1) / BLOCK_WID);
- /* bx1 = starting block (Note: rounding taken care of here.) */
- bx1 = bx2 + 1 - temp;
+ /* There are no way to allocate such huge space */
+ if (dun->row_rooms < blocks_high) return FALSE;
+ if (dun->col_rooms < blocks_wide) return FALSE;
- /* temp is total number along height */
- temp = ((y - 1) / BLOCK_HGT) + 1;
+ /* Sometimes, little rooms like to have more space. */
+ if (blocks_wide == 2)
+ {
+ if (one_in_(3)) blocks_wide = 3;
+ }
+ else if (blocks_wide == 1)
+ {
+ if (one_in_(2)) blocks_wide = rand_range(2, 3);
+ }
- /* by2 = ending block */
- by2 = temp / 2 + by0;
- /* by1 = starting block */
- by1 = by2 + 1 - temp;
+ /* We'll allow twenty-five guesses. */
+ for (i = 0; i < 25; i++)
+ {
+ filled = FALSE;
+ /* Pick a top left block at random */
+ block_y = randint0(dun->row_rooms - blocks_high);
+ block_x = randint0(dun->col_rooms - blocks_wide);
- /* Never run off the screen */
- if ((by1 < 0) || (by2 >= dun->row_rooms)) return (FALSE);
- if ((bx1 < 0) || (bx2 >= dun->col_rooms)) return (FALSE);
- /* Verify open space */
- for (by = by1; by <= by2; by++)
- {
- for (bx = bx1; bx <= bx2; bx++)
+ /* Itty-bitty rooms can shift about within their rectangle */
+ if (blocks_wide < 3)
{
- if (dun->room_map[by][bx]) return (FALSE);
+ /* Rooms that straddle a border must shift. */
+ if ((blocks_wide == 2) && ((block_x % 3) == 2))
+ {
+ if (one_in_(2)) block_x--;
+ else block_x++;
+ }
}
- }
- /* It is *extremely* important that the following calculation */
- /* be *exactly* correct to prevent memory errors XXX XXX XXX */
+ /* Rooms with width divisible by 3 get fitted to a rectangle. */
+ else if ((blocks_wide % 3) == 0)
+ {
+ /* Align to the left edge of a 11x33 rectangle. */
+ if ((block_x % 3) == 2) block_x++;
+ if ((block_x % 3) == 1) block_x--;
+ }
+
+ /*
+ * Big rooms that do not have a width divisible by 3 get
+ * aligned towards the edge of the dungeon closest to them.
+ */
+ else
+ {
+ /* Shift towards left edge of dungeon. */
+ if (block_x + (blocks_wide / 2) <= dun->col_rooms / 2)
+ {
+ if (((block_x % 3) == 2) && ((blocks_wide % 3) == 2))
+ block_x--;
+ if ((block_x % 3) == 1) block_x--;
+ }
+
+ /* Shift toward right edge of dungeon. */
+ else
+ {
+ if (((block_x % 3) == 2) && ((blocks_wide % 3) == 2))
+ block_x++;
+ if ((block_x % 3) == 1) block_x++;
+ }
+ }
- /* Acquire the location of the room */
- *yy = ((by1 + by2 + 1) * BLOCK_HGT) / 2;
- *xx = ((bx1 + bx2 + 1) * BLOCK_WID) / 2;
+ /* Extract blocks */
+ by1 = block_y + 0;
+ bx1 = block_x + 0;
+ by2 = block_y + blocks_high;
+ bx2 = block_x + blocks_wide;
+ /* Never run off the screen */
+ if ((by1 < 0) || (by2 > dun->row_rooms)) continue;
+ if ((bx1 < 0) || (bx2 > dun->col_rooms)) continue;
- /* Save the room location */
- if (dun->cent_n < CENT_MAX)
- {
- dun->cent[dun->cent_n].y = *yy;
- dun->cent[dun->cent_n].x = *xx;
- dun->cent_n++;
- }
+ /* Verify available space */
+ for (by = by1; by < by2; by++)
+ {
+ for (bx = bx1; bx < bx2; bx++)
+ {
+ if (dun->room_map[by][bx])
+ {
+ filled = TRUE;
+ }
+ }
+ }
- /* Reserve some blocks */
- for (by = by1; by <= by2; by++)
- {
- for (bx = bx1; bx <= bx2; bx++)
+ /* If space filled, try again. */
+ if (filled) continue;
+
+
+ /* It is *extremely* important that the following calculation */
+ /* be *exactly* correct to prevent memory errors XXX XXX XXX */
+
+ /* Acquire the location of the room */
+ (*y) = ((by1 + by2) * BLOCK_HGT) / 2;
+ (*x) = ((bx1 + bx2) * BLOCK_WID) / 2;
+
+ /* Save the room location */
+ if (dun->cent_n < CENT_MAX)
{
- dun->room_map[by][bx] = TRUE;
+ dun->cent[dun->cent_n].y = *y;
+ dun->cent[dun->cent_n].x = *x;
+ dun->cent_n++;
}
- }
- /* Count "crowded" rooms */
- if (crowded) dun->crowded++;
+ /* Reserve some blocks. */
+ for (by = by1; by < by2; by++)
+ {
+ for (bx = bx1; bx < bx2; bx++)
+ {
+ dun->room_map[by][bx] = TRUE;
+ }
+ }
- /*
- * Hack- See if room will cut off a cavern.
- * If so, fix by tunneling outside the room in such a way as to connect the caves.
- */
- check_room_boundary(*xx - x / 2 - 1, *yy - y / 2 - 1,
- *xx + (x - 1) / 2 + 1, *yy + (y - 1) / 2 + 1);
- /* Success */
- return (TRUE);
+ /*
+ * Hack- See if room will cut off a cavern.
+ *
+ * If so, fix by tunneling outside the room in such a
+ * way as to connect the caves.
+ */
+ check_room_boundary(*x - width / 2 - 1, *y - height / 2 - 1, *x + (width - 1) / 2 + 1, *y + (height - 1) / 2 + 1);
+
+
+ /* Success. */
+ return (TRUE);
+ }
+
+ /* Failure. */
+ return (FALSE);
}
+
+
+
/*
* Room building routines.
*
/*
* Type 1 -- normal rectangular rooms
*/
-static void build_type1(int by0, int bx0)
+static bool build_type1(void)
{
int y, x, y2, x2, yval, xval;
int y1, x1, xsize, ysize;
xsize = x1 + x2 + 1;
ysize = y1 + y2 + 1;
- /* Try to allocate space for room. If fails, exit */
- if (!room_alloc(xsize + 2, ysize + 2, FALSE, by0, bx0, &xval, &yval)) return;
+ /* Find and reserve some space in the dungeon. Get center of room. */
+ if (!find_space(&yval, &xval, ysize + 2, xsize + 2)) return FALSE;
/* Choose lite or dark */
light = ((dun_level <= randint1(25)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS));
place_random_door(yval, xval, TRUE);
}
+
+ return TRUE;
}
/*
* Type 2 -- Overlapping rectangular rooms
*/
-static void build_type2(int by0, int bx0)
+static bool build_type2(void)
{
int y, x, xval, yval;
int y1a, x1a, y2a, x2a;
bool light;
cave_type *c_ptr;
-
- /* Try to allocate space for room. If fails, exit */
- if (!room_alloc(25, 11, FALSE, by0, bx0, &xval, &yval)) return;
+ /* Find and reserve some space in the dungeon. Get center of room. */
+ if (!find_space(&yval, &xval, 11, 25)) return FALSE;
/* Choose lite or dark */
light = ((dun_level <= randint1(25)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS));
place_floor_grid(c_ptr);
}
}
+
+ return TRUE;
}
* 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)
+static bool build_type3(void)
{
int y, x, dy, dx, wy, wx;
int y1a, x1a, y2a, x2a;
cave_type *c_ptr;
- /* Try to allocate space for room. */
- if (!room_alloc(25, 11, FALSE, by0, bx0, &xval, &yval)) return;
+ /* Find and reserve some space in the dungeon. Get center of room. */
+ if (!find_space(&yval, &xval, 11, 25)) return FALSE;
+
/* Choose lite or dark */
light = ((dun_level <= randint1(25)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS));
break;
}
}
+
+ return TRUE;
}
* 4 - Inner room has a maze
* 5 - A set of four inner rooms
*/
-static void build_type4(int by0, int bx0)
+static bool build_type4(void)
{
int y, x, y1, x1;
int y2, x2, tmp, yval, xval;
cave_type *c_ptr;
- /* Try to allocate space for room. */
- if (!room_alloc(25, 11, FALSE, by0, bx0, &xval, &yval)) return;
+ /* Find and reserve some space in the dungeon. Get center of room. */
+ if (!find_space(&yval, &xval, 11, 25)) return FALSE;
/* Choose lite or dark */
light = ((dun_level <= randint1(25)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS));
break;
}
}
+
+ return TRUE;
}
return n_ptr->name ? count : -1;
}
-static void build_type6(int by0, int bx0, bool nest);
-static void build_type5(int by0, int bx0, bool nest);
-
static vault_aux_type nest_types[] =
{
#ifdef JP
*
* Note that "monster nests" will never contain "unique" monsters.
*/
-static void build_type5(int by0, int bx0, bool pit)
+static bool build_type5(void)
{
int y, x, y1, x1, y2, x2, xval, yval;
int i;
int cur_nest_type = pick_vault_type(nest_types, d_info[dungeon_type].nest);
vault_aux_type *n_ptr;
- /* Try to allocate space for room. */
- if (!room_alloc(25, 11, TRUE, by0, bx0, &xval, &yval)) return;
+ /* Find and reserve some space in the dungeon. Get center of room. */
+ if (!find_space(&yval, &xval, 11, 25)) return FALSE;
/* No type available */
if (cur_nest_type < 0)
{
- if (pit) return;
- else
- {
- build_type6(by0, bx0, TRUE);
- return;
- }
+ return FALSE;
}
n_ptr = &nest_types[cur_nest_type];
}
/* Notice failure */
- if (!r_idx || !attempts) return;
+ if (!r_idx || !attempts) return FALSE;
/* Note the alignment */
if (r_ptr->flags3 & RF3_EVIL) align.sub_align |= SUB_ALIGN_EVIL;
msg_print(r_name + r_info[nest_mon_info[i].r_idx].name);
}
}
+
+ return TRUE;
}
*
* Note that "monster pits" will never contain "unique" monsters.
*/
-static void build_type6(int by0, int bx0, bool nest)
+static bool build_type6(void)
{
int y, x, y1, x1, y2, x2, xval, yval;
int i, j;
int cur_pit_type = pick_vault_type(pit_types, d_info[dungeon_type].pit);
vault_aux_type *n_ptr;
- /* Try to allocate space for room. */
- if (!room_alloc(25, 11, TRUE, by0, bx0, &xval, &yval)) return;
+ /* Find and reserve some space in the dungeon. Get center of room. */
+ if (!find_space(&yval, &xval, 11, 25)) return FALSE;
/* No type available */
if (cur_pit_type < 0)
{
- if (nest) return;
- else
- {
- build_type5(by0, bx0, TRUE);
- return;
- }
+ return FALSE;
}
n_ptr = &pit_types[cur_pit_type];
}
/* Notice failure */
- if (!r_idx || !attempts) return;
+ if (!r_idx || !attempts) return FALSE;
/* Note the alignment */
if (r_ptr->flags3 & RF3_EVIL) align.sub_align |= SUB_ALIGN_EVIL;
/* Center monster */
place_monster_aux(0, yval, xval, what[7], PM_NO_KAGE);
+
+ return TRUE;
}
* be expressed simply in terms of swapping and inverting the
* x and y coordinates.
*/
- for (i = 0; i <= transno % 4; i++)
+ for (i = 0; i < transno % 4; i++)
{
/* rotate by 90 degrees */
temp = *x;
coord_trans(&i, &j, xoffset, yoffset, transno);
/* Extract the location */
- if (transno%2)
+ if (transno % 2 == 0)
{
/* no swap of x/y */
x = xval - (xmax / 2) + i;
coord_trans(&i, &j, xoffset, yoffset, transno);
/* Extract the location */
- if (transno % 2)
+ if (transno % 2 == 0)
{
/* no swap of x/y */
x = xval - (xmax / 2) + i;
/*
* Type 7 -- simple vaults (see "v_info.txt")
*/
-static void build_type7(int by0, int bx0)
+static bool build_type7(void)
{
vault_type *v_ptr = NULL;
int dummy = 0;
}
/* No lesser vault found */
- if (!v_ptr) return;
+ if (!v_ptr) return FALSE;
/* pick type of transformation (0-7) */
transno = randint0(8);
x = v_ptr->wid;
y = v_ptr->hgt;
+ /* Some huge vault cannot be ratated to fit in the dungeon */
+ if (x+2 > cur_hgt-2)
+ {
+ /* Forbid 90 or 270 degree ratation */
+ transno &= ~1;
+ }
+
coord_trans(&x, &y, 0, 0, transno);
if (x < 0)
yoffset = 0;
}
- /* Try to allocate space for room. */
- if (!room_alloc(abs(x), abs(y), FALSE, by0, bx0, &xval, &yval)) return;
+
+ /* Find and reserve some space in the dungeon. Get center of room. */
+ if (!find_space(&yval, &xval, abs(y), abs(x))) return FALSE;
+
if (dummy >= SAFE_MAX_ATTEMPTS)
{
#endif
}
- return;
+ return FALSE;
}
/* Hack -- Build the vault */
build_vault(yval, xval, v_ptr->hgt, v_ptr->wid,
v_text + v_ptr->text, xoffset, yoffset, transno);
+
+ return TRUE;
}
/*
* Type 8 -- greater vaults (see "v_info.txt")
*/
-static void build_type8(int by0, int bx0)
+static bool build_type8(void)
{
vault_type *v_ptr = NULL;
int dummy = 0;
}
/* No greater vault found */
- if (!v_ptr) return;
+ if (!v_ptr) return FALSE;
/* pick type of transformation (0-7) */
transno = randint0(8);
x = v_ptr->wid;
y = v_ptr->hgt;
+ /* Some huge vault cannot be ratated to fit in the dungeon */
+ if (x+2 > cur_hgt-2)
+ {
+ /* Forbid 90 or 270 degree ratation */
+ transno &= ~1;
+ }
+
coord_trans(&x, &y, 0, 0, transno);
if (x < 0)
* Hack -- Prepare a bit larger space (+2, +2) to
* prevent generation of vaults with no-entrance.
*/
- if (!room_alloc(abs(x) + 2, abs(y) + 2, FALSE, by0, bx0, &xval, &yval)) return;
+ /* Find and reserve some space in the dungeon. Get center of room. */
+ if (!find_space(&yval, &xval, abs(y) + 2, abs(x) + 2)) return FALSE;
+
if (dummy >= SAFE_MAX_ATTEMPTS)
{
#endif
}
- return;
+ return FALSE;
}
/* Hack -- Build the vault */
build_vault(yval, xval, v_ptr->hgt, v_ptr->wid,
v_text + v_ptr->text, xoffset, yoffset, transno);
+
+ return TRUE;
}
/*
/*
* Driver routine to create fractal cave system
*/
-static void build_type9(int by0, int bx0)
+static bool build_type9(void)
{
int grd, roug, cutoff, xsize, ysize, y0, x0;
xsize = randint1(22) * 2 + 6;
ysize = randint1(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;
+ /* Find and reserve some space in the dungeon. Get center of room. */
+ if (!find_space(&y0, &x0, ysize + 1, xsize + 1)) return FALSE;
light = done = FALSE;
room = TRUE;
/* Convert to normal format + clean up */
done = generate_fracave(y0, x0, xsize, ysize, cutoff, light, room);
}
+
+ return TRUE;
}
#ifdef ALLOW_CAVERNS_AND_LAKES
/* Get features based on type */
switch (type)
{
- case GEN_LAKE_TYPE_LAVA: /* Lava */
+ case LAKE_T_LAVA: /* Lava */
feat1 = FEAT_DEEP_LAVA;
feat2 = FEAT_SHAL_LAVA;
feat3 = floor_type[randint0(100)];
break;
- case GEN_LAKE_TYPE_WATER: /* Water */
+ case LAKE_T_WATER: /* Water */
feat1 = FEAT_DEEP_WATER;
feat2 = FEAT_SHAL_WATER;
feat3 = floor_type[randint0(100)];
break;
- case GEN_LAKE_TYPE_CAVE: /* Collapsed cave */
+ case LAKE_T_CAVE: /* Collapsed cave */
feat1 = floor_type[randint0(100)];
feat2 = floor_type[randint0(100)];
feat3 = FEAT_RUBBLE;
break;
- case GEN_LAKE_TYPE_EARTH_VAULT: /* Earth vault */
+ case LAKE_T_EARTH_VAULT: /* Earth vault */
feat1 = FEAT_RUBBLE;
feat2 = floor_type[randint0(100)];
feat3 = FEAT_RUBBLE;
break;
- case GEN_LAKE_TYPE_AIR_VAULT: /* Air vault */
+ case LAKE_T_AIR_VAULT: /* Air vault */
feat1 = FEAT_GRASS;
feat2 = FEAT_TREES;
feat3 = FEAT_GRASS;
break;
- case GEN_LAKE_TYPE_WATER_VAULT: /* Water vault */
+ case LAKE_T_WATER_VAULT: /* Water vault */
feat1 = FEAT_SHAL_WATER;
feat2 = FEAT_DEEP_WATER;
feat3 = FEAT_SHAL_WATER;
break;
- case GEN_LAKE_TYPE_FIRE_VAULT: /* Fire Vault */
+ case LAKE_T_FIRE_VAULT: /* Fire Vault */
feat1 = FEAT_SHAL_LAVA;
feat2 = FEAT_DEEP_LAVA;
feat3 = FEAT_SHAL_LAVA;
int c1, c2, c3;
/* paranoia - exit if lake type out of range. */
- if ((type < GEN_LAKE_TYPE_LAVA) || (type > GEN_LAKE_TYPE_FIRE_VAULT))
+ if ((type < LAKE_T_LAVA) || (type > LAKE_T_FIRE_VAULT))
{
msg_format("Invalid lake type (%d)", type);
return;
* 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 m, n, num_vertices;
cave[y1-2][x].info |= (CAVE_ROOM | CAVE_ICKY);
- place_extra_noperm_bold(y1-2, x);
+ place_outer_noperm_bold(y1-2, x);
}
for (x = x1 - 2; x <= x2 + 2; x++)
cave[y2+2][x].info |= (CAVE_ROOM | CAVE_ICKY);
- place_extra_noperm_bold(y2+2, x);
+ place_outer_noperm_bold(y2+2, x);
}
for (y = y1 - 2; y <= y2 + 2; y++)
cave[y][x1-2].info |= (CAVE_ROOM | CAVE_ICKY);
- place_extra_noperm_bold(y, x1-2);
+ place_outer_noperm_bold(y, x1-2);
}
for (y = y1 - 2; y <= y2 + 2; y++)
cave[y][x2+2].info |= (CAVE_ROOM | CAVE_ICKY);
- place_extra_noperm_bold(y, x2+2);
+ place_outer_noperm_bold(y, x2+2);
}
for (y = y1 - 1; y <= y2 + 1; y++)
{
for (x = x1 - 1; x <= x2 + 1; x++)
{
- cave[y][x].info |= (CAVE_ROOM | CAVE_ICKY);
+ cave_type *c_ptr = &cave[y][x];
+
+ c_ptr->info |= (CAVE_ROOM | CAVE_ICKY);
/* Permanent walls */
- cave[y][x].feat = FEAT_PERM_INNER;
+ c_ptr->feat = FEAT_PERM_INNER;
+ c_ptr->info &= ~(CAVE_MASK);
+ c_ptr->info |= CAVE_INNER;
}
}
{
/* left and right */
y = randint1(dy) + dy / 2;
- place_outer_noperm_bold(y1 + y, x1 - 1);
- place_outer_noperm_bold(y1 + y, x2 + 1);
+ place_inner_bold(y1 + y, x1 - 1);
+ place_inner_bold(y1 + y, x2 + 1);
}
else
{
/* top and bottom */
x = randint1(dx) + dx / 2;
- place_outer_noperm_bold(y1 - 1, x1 + x);
- place_outer_noperm_bold(y2 + 1, x1 + x);
+ place_inner_bold(y1 - 1, x1 + x);
+ place_inner_bold(y2 + 1, x1 + x);
}
/* Fill with monsters and treasure, highest difficulty */
if (dun_level < 25)
{
/* Earth vault (Rubble) */
- type = GEN_LAKE_TYPE_EARTH_VAULT;
+ type = LAKE_T_EARTH_VAULT;
}
else if (dun_level < 50)
{
/* Air vault (Trees) */
- type = GEN_LAKE_TYPE_AIR_VAULT;
+ type = LAKE_T_AIR_VAULT;
}
else if (dun_level < 75)
{
/* Water vault (shallow water) */
- type = GEN_LAKE_TYPE_WATER_VAULT;
+ type = LAKE_T_WATER_VAULT;
}
else
{
/* Fire vault (shallow lava) */
- type = GEN_LAKE_TYPE_FIRE_VAULT;
+ type = LAKE_T_FIRE_VAULT;
}
while (!done)
/*
* Random vaults
*/
-static void build_type10(int by0, int bx0)
+static bool build_type10(void)
{
int y0, x0, xsize, ysize, vtype;
xsize = randint1(22) + 22;
ysize = randint1(11) + 11;
- /* Allocate in room_map. If will not fit, exit */
- if (!room_alloc(xsize + 1, ysize + 1, FALSE, by0, bx0, &x0, &y0)) return;
+ /* Find and reserve some space in the dungeon. Get center of room. */
+ if (!find_space(&y0, &x0, ysize + 1, xsize + 1)) return FALSE;
/* Boost the rating- higher than lesser vaults and lower than greater vaults */
rating += 10;
/* I know how to add a few more... give me some time. */
/* Paranoia */
- default: return;
+ default: return FALSE;
}
+
+ return TRUE;
}
*
* When done fill from the inside to find the walls,
*/
-static void build_type11(int by0, int bx0)
+static bool build_type11(void)
{
int rad, x, y, x0, y0;
int light = FALSE;
rad = randint0(9);
- /* Allocate in room_map. If will not fit, exit */
- if (!room_alloc(rad * 2 + 1, rad * 2 + 1, FALSE, by0, bx0, &x0, &y0)) return;
+ /* Find and reserve some space in the dungeon. Get center of room. */
+ if (!find_space(&y0, &x0, rad * 2 + 1, rad * 2 + 1)) return FALSE;
/* Make circular floor */
for (x = x0 - rad; x <= x0 + rad; x++)
/* Find visible outer walls and set to be FEAT_OUTER */
add_outer_wall(x0, y0, light, x0 - rad, y0 - rad, x0 + rad, y0 + rad);
+
+ return TRUE;
}
*
* When done fill from the inside to find the walls,
*/
-static void build_type12(int by0, int bx0)
- {
+static bool build_type12(void)
+{
int rad, x, y, x0, y0;
int light = FALSE;
bool emptyflag = TRUE;
rad = randint1(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;
+ /* Find and reserve some space in the dungeon. Get center of room. */
+ if (!find_space(&y0, &x0, rad * 2 + 3, rad * 2 + 3)) return FALSE;
/* Make floor */
for (x = x0 - rad; x <= x0 + rad; x++)
/* Traps naturally */
vault_traps(y0, x0, 4, 4, randint0(3) + 2);
}
+
+ return TRUE;
}
*
* Note that "monster pits" will never contain "unique" monsters.
*/
-static void build_type13(int by0, int bx0)
+static bool build_type13(void)
{
static int placing[][3] = {
{-2, -9, 0}, {-2, -8, 0}, {-3, -7, 0}, {-3, -6, 0},
vault_aux_type *n_ptr;
/* Only in Angband */
- if (dungeon_type != 1) return;
+ if (dungeon_type != 1) return FALSE;
- /* Try to allocate space for room. */
- if (!room_alloc(25, 13, TRUE, by0, bx0, &xval, &yval)) return;
+ /* Find and reserve some space in the dungeon. Get center of room. */
+ if (!find_space(&yval, &xval, 13, 25)) return FALSE;
/* No type available */
- if (cur_pit_type < 0) return;
+ if (cur_pit_type < 0) return FALSE;
n_ptr = &pit_types[cur_pit_type];
}
/* Notice failure */
- if (!r_idx || !attempts) return;
+ if (!r_idx || !attempts) return FALSE;
/* Note the alignment */
if (r_ptr->flags3 & RF3_EVIL) align.sub_align |= SUB_ALIGN_EVIL;
x = xval + placing[i][1];
place_monster_aux(0, y, x, what[placing[i][2]], PM_NO_KAGE);
}
+
+ return TRUE;
}
*
* A special trap is placed at center of the room
*/
-static void build_type14(int by0, int bx0)
+static bool build_type14(void)
{
int y, x, y2, x2, yval, xval;
int y1, x1, xsize, ysize;
xsize = x1 + x2 + 1;
ysize = y1 + y2 + 1;
- /* Try to allocate space for room. If fails, exit */
- if (!room_alloc(xsize + 2, ysize + 2, FALSE, by0, bx0, &xval, &yval)) return;
+ /* Find and reserve some space in the dungeon. Get center of room. */
+ if (!find_space(&yval, &xval, ysize + 2, xsize + 2)) return FALSE;
/* Choose lite or dark */
light = ((dun_level <= randint1(25)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS));
msg_format("Room of %s", f_name + f_info[trap].name);
#endif
}
+
+ return TRUE;
}
* Note that we restrict the number of "crowded" rooms to reduce
* the chance of overflowing the monster list during level creation.
*/
-bool room_build(int by0, int bx0, int typ)
+bool room_build(int typ)
{
- /* Restrict level */
- if ((dun_level < roomdep[typ]) && !ironman_rooms) return FALSE;
-
- /* Restrict "crowded" rooms */
- if ((dun->crowded >= 2) && ((typ == ROOM_BUILD_TYPE_NEST) ||
- (typ == ROOM_BUILD_TYPE_PIT) || (typ == ROOM_BUILD_TYPE_TRAP_PIT))) return FALSE;
-
/* Build a room */
switch (typ)
{
/* Build an appropriate room */
- case ROOM_BUILD_TYPE_NORMAL: build_type1(by0, bx0); break;
- case ROOM_BUILD_TYPE_OVERLAP: build_type2(by0, bx0); break;
- case ROOM_BUILD_TYPE_CROSS: build_type3(by0, bx0); break;
- case ROOM_BUILD_TYPE_INNER_FEAT: build_type4(by0, bx0); break;
- case ROOM_BUILD_TYPE_NEST: build_type5(by0, bx0, FALSE); break;
- case ROOM_BUILD_TYPE_PIT: build_type6(by0, bx0, FALSE); break;
- case ROOM_BUILD_TYPE_LESSER_VAULT: build_type7(by0, bx0); break;
- case ROOM_BUILD_TYPE_GREATER_VAULT: build_type8(by0, bx0); break;
- case ROOM_BUILD_TYPE_FRACAVE: build_type9(by0, bx0); break;
- case ROOM_BUILD_TYPE_RANDOM_VAULT: build_type10(by0, bx0); break;
- case ROOM_BUILD_TYPE_OVAL: build_type11(by0, bx0); break;
- case ROOM_BUILD_TYPE_CRYPT: build_type12(by0, bx0); break;
- case ROOM_BUILD_TYPE_TRAP_PIT: build_type13(by0, bx0); break;
- case ROOM_BUILD_TYPE_TRAP: build_type14(by0, bx0); break;
+ case ROOM_T_NORMAL: build_type1(); break;
+ case ROOM_T_OVERLAP: build_type2(); break;
+ case ROOM_T_CROSS: build_type3(); break;
+ case ROOM_T_INNER_FEAT: build_type4(); break;
+ case ROOM_T_NEST: build_type5(); break;
+ case ROOM_T_PIT: build_type6(); break;
+ case ROOM_T_LESSER_VAULT: build_type7(); break;
+ case ROOM_T_GREATER_VAULT: build_type8(); break;
+ case ROOM_T_FRACAVE: build_type9(); break;
+ case ROOM_T_RANDOM_VAULT: build_type10(); break;
+ case ROOM_T_OVAL: build_type11(); break;
+ case ROOM_T_CRYPT: build_type12(); break;
+ case ROOM_T_TRAP_PIT: build_type13(); break;
+ case ROOM_T_TRAP: build_type14(); break;
/* Paranoia */
default: return FALSE;
return TRUE;
}
+
+
+#define MOVE_PLIST(dst, src) (prob_list[dst] += prob_list[src], prob_list[src] = 0)
+
+/*
+ * [from SAngband (originally from OAngband)]
+ *
+ * Generate rooms in dungeon. Build bigger rooms at first.
+ */
+void generate_rooms(void)
+{
+ int i;
+ bool remain;
+ int crowded = 0;
+ int total_prob;
+ int prob_list[ROOM_T_MAX];
+ int rooms_built = 0;
+ int area_size = 100 * (cur_hgt*cur_wid) / (MAX_HGT*MAX_WID);
+ int level_index = MIN(10, div_round(dun_level, 10));
+
+ /* Number of each type of room on this level */
+ s16b room_num[ROOM_T_MAX];
+
+ /* Limit number of rooms */
+ int dun_rooms = rand_range(DUN_ROOMS_MIN, DUN_ROOMS_MAX * area_size / 100);
+
+ /* Assume normal cave */
+ room_info_type *room_info_ptr = room_info_normal;
+
+
+ /*
+ * Initialize probability list.
+ */
+ for (i = 0; i < ROOM_T_MAX; i++)
+ {
+ /* No rooms allowed above their minimum depth. */
+ if (dun_level < room_info_ptr[i].min_level)
+ {
+ prob_list[i] = 0;
+ }
+ else
+ {
+ prob_list[i] = room_info_ptr[i].prob[level_index];
+ }
+ }
+
+ /*
+ * XXX -- Various dungeon types and options.
+ */
+
+ /* Ironman sees only Greater Vaults */
+ if (ironman_rooms && !((d_info[dungeon_type].flags1 & (DF1_BEGINNER | DF1_CHAMELEON))))
+ {
+ for (i = 0; i < ROOM_T_MAX; i++)
+ {
+ if (i == ROOM_T_GREATER_VAULT) prob_list[i] = 1;
+ else prob_list[i] = 0;
+ }
+ }
+
+ /* Forbidden vaults */
+ else if (d_info[dungeon_type].flags1 & DF1_NO_VAULT)
+ {
+ prob_list[ROOM_T_LESSER_VAULT] = 0;
+ prob_list[ROOM_T_GREATER_VAULT] = 0;
+ prob_list[ROOM_T_RANDOM_VAULT] = 0;
+ }
+
+
+ /* NO_CAVE dungeon (Castle)*/
+ if (d_info[dungeon_type].flags1 & DF1_NO_CAVE)
+ {
+ MOVE_PLIST(ROOM_T_NORMAL, ROOM_T_FRACAVE);
+ MOVE_PLIST(ROOM_T_INNER_FEAT, ROOM_T_CRYPT);
+ MOVE_PLIST(ROOM_T_INNER_FEAT, ROOM_T_OVAL);
+ }
+
+ /* CAVE dungeon (Orc cave etc.) */
+ else if (d_info[dungeon_type].flags1 & DF1_CAVE)
+ {
+ MOVE_PLIST(ROOM_T_FRACAVE, ROOM_T_NORMAL);
+ }
+
+ /* No caves when a (random) cavern exists: they look bad */
+ else if (dun->cavern || dun->empty_level)
+ {
+ prob_list[ROOM_T_FRACAVE] = 0;
+ }
+
+
+ /*
+ * Initialize number of rooms,
+ * And calcurate total probability.
+ */
+ for (total_prob = 0, i = 0; i < ROOM_T_MAX; i++)
+ {
+ room_num[i] = 0;
+ total_prob += prob_list[i];
+ }
+
+ /*
+ * Prepare the number of rooms, of all types, we should build
+ * on this level.
+ */
+ for (i = 0; i < dun_rooms; i++)
+ {
+ int room_type;
+ int rand = randint0(total_prob);
+
+ /* Get room_type randomly */
+ for (room_type = 0; room_type < ROOM_T_MAX; room_type++)
+ {
+ if (rand < prob_list[room_type]) break;
+ else rand -= prob_list[room_type];
+ }
+
+ /* Paranoia */
+ if (room_type >= ROOM_T_MAX) room_type = ROOM_T_NORMAL;
+
+ /* Increase the number of rooms of that type we should build. */
+ room_num[room_type]++;
+ }
+
+
+ /*
+ * Build each type of room one by one until we cannot build any more.
+ * [from SAngband (originally from OAngband)]
+ */
+ while (TRUE)
+ {
+ /* Assume no remaining rooms */
+ remain = FALSE;
+
+ for (i = 0; i < ROOM_T_MAX; i++)
+ {
+ /* What type of room are we building now? */
+ int room_type = room_build_order[i];
+
+ /* Stop building rooms when we hit the maximum. */
+ if (rooms_built >= dun_rooms)
+ {
+ remain = FALSE;
+ break;
+ }
+
+ /* Go next if none available */
+ if (!room_num[room_type]) continue;
+
+ /* Use up one unit */
+ room_num[room_type]--;
+
+ /* Build the room. */
+ if (room_build(room_type))
+ {
+ /* Increase the room built count. */
+ rooms_built++;
+
+ /* Mark as there was some remaining rooms */
+ remain = TRUE;
+
+ switch (room_type)
+ {
+ case ROOM_T_PIT:
+ case ROOM_T_NEST:
+ case ROOM_T_TRAP_PIT:
+
+ /* Avoid too many monsters */
+ if (++crowded >= 2)
+ {
+ room_num[ROOM_T_PIT] = 0;
+ room_num[ROOM_T_NEST] = 0;
+ room_num[ROOM_T_TRAP_PIT] = 0;
+ }
+ }
+ }
+
+ /* Stop building this type on failure. */
+ else
+ {
+ room_num[room_type] = 0;
+ }
+ }
+
+ /* End loop if no room remain */
+ if (!remain) break;
+ }
+
+}
+
+