2 * @brief ダンジョンフロアの部屋生成処理 / make rooms. Used by generate.c when creating dungeons.
5 * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke\n
6 * This software may be copied and distributed for educational, research,\n
7 * and not for profit purposes provided that this copyright and statement\n
8 * are included in all such copies. Other copyrights may also apply.\n
9 * 2014 Deskull rearranged comment for Doxygen. \n
11 * Room building routines.\n
17 * 4 -- large room with features\n
18 * 5 -- monster nests\n
20 * 7 -- simple vaults\n
21 * 8 -- greater vaults\n
22 * 9 -- fractal caves\n
23 * 10 -- random vaults\n
24 * 11 -- circular rooms\n
26 * 13 -- trapped monster pits\n
27 * 14 -- trapped room\n
29 * 16 -- underground arcade\n
31 * Some functions are used to determine if the given monster\n
32 * is appropriate for inclusion in a monster nest or monster pit or\n
35 * None of the pits/nests are allowed to include "unique" monsters.\n
38 #include "room/rooms-builder.h"
39 #include "dungeon/dungeon-flag-types.h"
40 #include "dungeon/dungeon.h"
41 #include "floor/cave.h"
42 #include "grid/door.h"
43 #include "grid/feature.h"
44 #include "grid/grid.h"
45 #include "room/cave-filler.h"
46 #include "room/lake-types.h"
47 #include "system/floor-type-definition.h"
48 #include "system/player-type-definition.h"
49 #include "view/display-messages.h"
52 * @brief 1マスだけの部屋を作成し、上下左右いずれか一つに隠しドアを配置する。
53 * @param player_ptr プレーヤーへの参照ポインタ
54 * @param y0 配置したい中心のY座標
55 * @param x0 配置したい中心のX座標
57 * This funtion makes a very small room centred at (x0, y0)
58 * This is used in crypts, and random elemental vaults.
60 * Note - this should be used only on allocated regions
61 * within another room.
63 void build_small_room(player_type *player_ptr, POSITION x0, POSITION y0)
65 for (POSITION y = y0 - 1; y <= y0 + 1; y++) {
66 place_bold(player_ptr, y, x0 - 1, GB_INNER);
67 place_bold(player_ptr, y, x0 + 1, GB_INNER);
70 for (POSITION x = x0 - 1; x <= x0 + 1; x++) {
71 place_bold(player_ptr, y0 - 1, x, GB_INNER);
72 place_bold(player_ptr, y0 + 1, x, GB_INNER);
75 switch (randint0(4)) {
77 place_secret_door(player_ptr, y0, x0 - 1, DOOR_DEFAULT);
80 place_secret_door(player_ptr, y0, x0 + 1, DOOR_DEFAULT);
83 place_secret_door(player_ptr, y0 - 1, x0, DOOR_DEFAULT);
86 place_secret_door(player_ptr, y0 + 1, x0, DOOR_DEFAULT);
90 player_ptr->current_floor_ptr->grid_array[y0][x0].mimic = 0;
91 place_bold(player_ptr, y0, x0, GB_FLOOR);
95 * Builds a cave system in the center of the dungeon.
97 void build_cavern(player_type *player_ptr)
101 floor_type *floor_ptr = player_ptr->current_floor_ptr;
102 if ((floor_ptr->dun_level <= randint1(50)) && d_info[floor_ptr->dungeon_idx].flags.has_not(DF::DARKNESS))
105 POSITION xsize = floor_ptr->width - 1;
106 POSITION ysize = floor_ptr->height - 1;
107 POSITION x0 = xsize / 2;
108 POSITION y0 = ysize / 2;
113 int grd = randint1(4) + 4;
114 int roug = randint1(8) * randint1(4);
115 int cutoff = xsize / 2;
116 generate_hmap(floor_ptr, y0 + 1, x0 + 1, xsize, ysize, grd, roug, cutoff);
117 done = generate_fracave(player_ptr, y0 + 1, x0 + 1, xsize, ysize, cutoff, light, false);
122 * makes a lake/collapsed floor in the center of the dungeon
124 void build_lake(player_type *player_ptr, int type)
126 if ((type < LAKE_T_LAVA) || (type > LAKE_T_FIRE_VAULT)) {
127 msg_format("Invalid lake type (%d)", type);
131 floor_type *floor_ptr = player_ptr->current_floor_ptr;
132 int xsize = floor_ptr->width - 1;
133 int ysize = floor_ptr->height - 1;
140 int grd = randint1(3) + 4;
141 int roug = randint1(8) * randint1(4);
142 int c3 = 3 * xsize / 4;
143 int c1 = randint0(c3 / 2) + randint0(c3 / 2) - 5;
144 int c2 = (c1 + c3) / 2;
145 generate_hmap(floor_ptr, y0 + 1, x0 + 1, xsize, ysize, grd, roug, c3);
146 done = generate_lake(player_ptr, y0 + 1, x0 + 1, xsize, ysize, c1, c2, c3, type);
151 * Overlay a rectangular room given its bounds
152 * This routine is used by build_room_vault
153 * The area inside the walls is not touched:
154 * only granite is removed- normal walls stay
156 void build_room(player_type *player_ptr, POSITION x1, POSITION x2, POSITION y1, POSITION y2)
159 if ((x1 == x2) || (y1 == y2))
174 POSITION xsize = x2 - x1;
175 POSITION ysize = y2 - y1;
176 floor_type *floor_ptr = player_ptr->current_floor_ptr;
177 for (int i = 0; i <= xsize; i++) {
178 place_bold(player_ptr, y1, x1 + i, GB_OUTER_NOPERM);
179 floor_ptr->grid_array[y1][x1 + i].info |= (CAVE_ROOM | CAVE_ICKY);
180 place_bold(player_ptr, y2, x1 + i, GB_OUTER_NOPERM);
181 floor_ptr->grid_array[y2][x1 + i].info |= (CAVE_ROOM | CAVE_ICKY);
184 for (int i = 1; i < ysize; i++) {
185 place_bold(player_ptr, y1 + i, x1, GB_OUTER_NOPERM);
186 floor_ptr->grid_array[y1 + i][x1].info |= (CAVE_ROOM | CAVE_ICKY);
187 place_bold(player_ptr, y1 + i, x2, GB_OUTER_NOPERM);
188 floor_ptr->grid_array[y1 + i][x2].info |= (CAVE_ROOM | CAVE_ICKY);
191 for (POSITION x = 1; x < xsize; x++) {
192 for (POSITION y = 1; y < ysize; y++) {
193 if (is_extra_bold(floor_ptr, y1 + y, x1 + x)) {
194 place_bold(player_ptr, y1 + y, x1 + x, GB_FLOOR);
195 floor_ptr->grid_array[y1 + y][x1 + x].info |= (CAVE_ROOM | CAVE_ICKY);
197 floor_ptr->grid_array[y1 + y][x1 + x].info |= (CAVE_ROOM | CAVE_ICKY);
204 * Build a town/ castle by using a recursive algorithm.
205 * Basically divide each region in a probalistic way to create
206 * smaller regions. When the regions get too small stop.
208 * The power variable is a measure of how well defended a region is.
209 * This alters the possible choices.
211 void build_recursive_room(player_type *player_ptr, POSITION x1, POSITION y1, POSITION x2, POSITION y2, int power)
213 POSITION xsize = x2 - x1;
214 POSITION ysize = y2 - y1;
217 if ((power < 3) && (xsize > 12) && (ysize > 12)) {
221 if ((randint1(10) > 2) && (xsize < 8) && (ysize < 8)) {
224 choice = randint1(2) + 1;
227 choice = randint1(3) + 1;
236 for (x = x1; x <= x2; x++) {
237 place_bold(player_ptr, y1, x, GB_OUTER);
238 place_bold(player_ptr, y2, x, GB_OUTER);
241 for (y = y1 + 1; y < y2; y++) {
242 place_bold(player_ptr, y, x1, GB_OUTER);
243 place_bold(player_ptr, y, x2, GB_OUTER);
247 y = randint1(ysize) + y1;
248 place_bold(player_ptr, y, x1, GB_FLOOR);
249 place_bold(player_ptr, y, x2, GB_FLOOR);
251 x = randint1(xsize) + x1;
252 place_bold(player_ptr, y1, x, GB_FLOOR);
253 place_bold(player_ptr, y2, x, GB_FLOOR);
256 int t1 = randint1(ysize / 3) + y1;
257 int t2 = y2 - randint1(ysize / 3);
258 int t3 = randint1(xsize / 3) + x1;
259 int t4 = x2 - randint1(xsize / 3);
261 /* Do outside areas */
262 build_recursive_room(player_ptr, x1 + 1, y1 + 1, x2 - 1, t1, power + 1);
263 build_recursive_room(player_ptr, x1 + 1, t2, x2 - 1, y2, power + 1);
264 build_recursive_room(player_ptr, x1 + 1, t1 + 1, t3, t2 - 1, power + 3);
265 build_recursive_room(player_ptr, t4, t1 + 1, x2 - 1, t2 - 1, power + 3);
277 /* Try to build a room */
278 if ((xsize < 3) || (ysize < 3)) {
279 for (int y = y1; y < y2; y++) {
280 for (int x = x1; x < x2; x++) {
281 place_bold(player_ptr, y, x, GB_INNER);
288 for (int x = x1 + 1; x <= x2 - 1; x++) {
289 place_bold(player_ptr, y1 + 1, x, GB_INNER);
290 place_bold(player_ptr, y2 - 1, x, GB_INNER);
293 for (int y = y1 + 1; y <= y2 - 1; y++) {
294 place_bold(player_ptr, y, x1 + 1, GB_INNER);
295 place_bold(player_ptr, y, x2 - 1, GB_INNER);
298 int y = randint1(ysize - 3) + y1 + 1;
301 place_bold(player_ptr, y, x1 + 1, GB_FLOOR);
304 place_bold(player_ptr, y, x2 - 1, GB_FLOOR);
307 build_recursive_room(player_ptr, x1 + 2, y1 + 2, x2 - 2, y2 - 2, power + 3);
311 /* Try and divide vertically */
313 for (int y = y1; y < y2; y++) {
314 for (int x = x1; x < x2; x++) {
315 place_bold(player_ptr, y, x, GB_INNER);
321 int t1 = randint1(xsize - 2) + x1 + 1;
322 build_recursive_room(player_ptr, x1, y1, t1, y2, power - 2);
323 build_recursive_room(player_ptr, t1 + 1, y1, x2, y2, power - 2);
327 /* Try and divide horizontally */
329 for (int y = y1; y < y2; y++)
330 for (int x = x1; x < x2; x++)
331 place_bold(player_ptr, y, x, GB_INNER);
336 int t1 = randint1(ysize - 2) + y1 + 1;
337 build_recursive_room(player_ptr, x1, y1, x2, t1, power - 2);
338 build_recursive_room(player_ptr, x1, t1 + 1, x2, y2, power - 2);
345 * Add outer wall to a floored region
346 * Note: no range checking is done so must be inside dungeon
347 * This routine also stomps on doors
349 void add_outer_wall(player_type *player_ptr, POSITION x, POSITION y, int light, POSITION x1, POSITION y1, POSITION x2, POSITION y2)
351 floor_type *floor_ptr = player_ptr->current_floor_ptr;
352 if (!in_bounds(floor_ptr, y, x))
356 g_ptr = &floor_ptr->grid_array[y][x];
357 if (g_ptr->info & CAVE_ROOM)
360 g_ptr->info |= CAVE_ROOM;
362 f_ptr = &f_info[g_ptr->feat];
363 if (is_floor_bold(floor_ptr, y, x)) {
364 for (int i = -1; i <= 1; i++) {
365 for (int j = -1; j <= 1; j++) {
366 if ((x + i >= x1) && (x + i <= x2) && (y + j >= y1) && (y + j <= y2)) {
367 add_outer_wall(player_ptr, x + i, y + j, light, x1, y1, x2, y2);
369 g_ptr->info |= CAVE_GLOW;
377 if (is_extra_bold(floor_ptr, y, x)) {
378 place_bold(player_ptr, y, x, GB_OUTER);
380 g_ptr->info |= CAVE_GLOW;
385 if (permanent_wall(f_ptr)) {
387 g_ptr->info |= CAVE_GLOW;
392 * Hacked distance formula - gives the 'wrong' answer.
393 * Used to build crypts
395 POSITION dist2(POSITION x1, POSITION y1, POSITION x2, POSITION y2, POSITION h1, POSITION h2, POSITION h3, POSITION h4)
397 POSITION dx = abs(x2 - x1);
398 POSITION dy = abs(y2 - y1);
400 return (dx + (dy * h1) / h2);
403 return (dy + (dx * h1) / h2);
405 return (((dx + dy) * 128) / 181 + (dx * dx / (dy * h3) + dy * dy / (dx * h3)) * h4);