1 #include "floor/cave-generator.h"
2 #include "dungeon/dungeon-flag-types.h"
3 #include "dungeon/dungeon.h"
4 #include "dungeon/quest-monster-placer.h"
5 #include "floor/dungeon-tunnel-util.h"
6 #include "floor/floor-allocation-types.h"
7 #include "floor/floor-streams.h"
8 #include "floor/geometry.h"
9 #include "floor/object-allocator.h"
10 #include "floor/tunnel-generator.h"
11 #include "floor/wild.h"
12 #include "game-option/birth-options.h"
13 #include "game-option/cheat-types.h"
14 #include "game-option/game-play-options.h"
15 #include "grid/door.h"
16 #include "grid/feature-generator.h"
17 #include "grid/feature.h"
18 #include "grid/grid.h"
19 #include "monster-floor/monster-generator.h"
20 #include "monster-floor/monster-summon.h"
21 #include "monster-floor/place-monster-types.h"
22 #include "monster/monster-util.h"
23 #include "room/lake-types.h"
24 #include "room/room-generator.h"
25 #include "room/rooms-maze-vault.h"
26 #include "system/dungeon-data-definition.h"
27 #include "system/floor-type-definition.h"
28 #include "system/player-type-definition.h"
29 #include "util/bit-flags-calculator.h"
30 #include "wizard/wizard-messages.h"
32 static void reset_lite_area(floor_type *floor_ptr)
34 floor_ptr->lite_n = 0;
35 floor_ptr->mon_lite_n = 0;
36 floor_ptr->redraw_n = 0;
37 floor_ptr->view_n = 0;
40 static dun_data_type *initialize_dun_data_type(dun_data_type *dd_ptr, concptr *why)
42 dd_ptr->destroyed = FALSE;
43 dd_ptr->empty_level = FALSE;
44 dd_ptr->cavern = FALSE;
50 static void check_arena_floor(player_type *player_ptr, dun_data_type *dd_ptr)
52 floor_type *floor_ptr = player_ptr->current_floor_ptr;
53 if (!dd_ptr->empty_level) {
54 for (POSITION y = 0; y < floor_ptr->height; y++)
55 for (POSITION x = 0; x < floor_ptr->width; x++)
56 place_bold(player_ptr, y, x, GB_EXTRA);
61 for (POSITION y = 0; y < floor_ptr->height; y++)
62 for (POSITION x = 0; x < floor_ptr->width; x++)
63 place_bold(player_ptr, y, x, GB_FLOOR);
65 for (POSITION x = 0; x < floor_ptr->width; x++) {
66 place_bold(player_ptr, 0, x, GB_EXTRA);
67 place_bold(player_ptr, floor_ptr->height - 1, x, GB_EXTRA);
70 for (POSITION y = 1; y < (floor_ptr->height - 1); y++) {
71 place_bold(player_ptr, y, 0, GB_EXTRA);
72 place_bold(player_ptr, y, floor_ptr->width - 1, GB_EXTRA);
76 static void place_cave_contents(player_type *player_ptr, dun_data_type *dd_ptr, dungeon_type *d_ptr)
78 floor_type *floor_ptr = player_ptr->current_floor_ptr;
79 if (floor_ptr->dun_level == 1)
80 while (one_in_(DUN_MOS_DEN))
81 place_trees(player_ptr, randint1(floor_ptr->width - 2), randint1(floor_ptr->height - 2));
83 if (dd_ptr->destroyed)
84 destroy_level(player_ptr);
86 if (has_river_flag(d_ptr) && one_in_(3) && (randint1(floor_ptr->dun_level) > 5))
87 add_river(floor_ptr, dd_ptr);
89 for (int i = 0; i < dd_ptr->cent_n; i++) {
91 int pick = rand_range(0, i);
92 ty = dd_ptr->cent[i].y;
93 tx = dd_ptr->cent[i].x;
94 dd_ptr->cent[i].y = dd_ptr->cent[pick].y;
95 dd_ptr->cent[i].x = dd_ptr->cent[pick].x;
96 dd_ptr->cent[pick].y = ty;
97 dd_ptr->cent[pick].x = tx;
101 static bool decide_tunnel_planned_site(player_type *player_ptr, dun_data_type *dd_ptr, dungeon_type *d_ptr, dt_type *dt_ptr, int i)
105 if (randint1(player_ptr->current_floor_ptr->dun_level) > d_ptr->tunnel_percent)
106 (void)build_tunnel2(player_ptr, dd_ptr, dd_ptr->cent[i].x, dd_ptr->cent[i].y, dd_ptr->tunnel_x, dd_ptr->tunnel_y, 2, 2);
107 else if (!build_tunnel(player_ptr, dd_ptr, dt_ptr, dd_ptr->cent[i].y, dd_ptr->cent[i].x, dd_ptr->tunnel_y, dd_ptr->tunnel_x))
108 dd_ptr->tunnel_fail_count++;
110 if (dd_ptr->tunnel_fail_count >= 2) {
111 *dd_ptr->why = _("トンネル接続に失敗", "Failed to generate tunnels");
118 static void make_tunnels(player_type *player_ptr, dun_data_type *dd_ptr)
120 for (int j = 0; j < dd_ptr->tunn_n; j++) {
123 dd_ptr->tunnel_y = dd_ptr->tunn[j].y;
124 dd_ptr->tunnel_x = dd_ptr->tunn[j].x;
125 g_ptr = &player_ptr->current_floor_ptr->grid_array[dd_ptr->tunnel_y][dd_ptr->tunnel_x];
126 f_ptr = &f_info[g_ptr->feat];
127 if (!has_flag(f_ptr->flags, FF_MOVE) || (!has_flag(f_ptr->flags, FF_WATER) && !has_flag(f_ptr->flags, FF_LAVA))) {
129 place_grid(player_ptr, g_ptr, GB_FLOOR);
134 static void make_walls(player_type *player_ptr, dun_data_type *dd_ptr, dungeon_type *d_ptr, dt_type *dt_ptr)
136 for (int j = 0; j < dd_ptr->wall_n; j++) {
138 dd_ptr->tunnel_y = dd_ptr->wall[j].y;
139 dd_ptr->tunnel_x = dd_ptr->wall[j].x;
140 g_ptr = &player_ptr->current_floor_ptr->grid_array[dd_ptr->tunnel_y][dd_ptr->tunnel_x];
142 place_grid(player_ptr, g_ptr, GB_FLOOR);
143 if ((randint0(100) < dt_ptr->dun_tun_pen) && d_ptr->flags.has_not(DF::NO_DOORS))
144 place_random_door(player_ptr, dd_ptr->tunnel_y, dd_ptr->tunnel_x, TRUE);
148 static bool make_centers(player_type *player_ptr, dun_data_type *dd_ptr, dungeon_type *d_ptr, dt_type *dt_ptr)
150 dd_ptr->tunnel_fail_count = 0;
152 dd_ptr->tunnel_y = dd_ptr->cent[dd_ptr->cent_n - 1].y;
153 dd_ptr->tunnel_x = dd_ptr->cent[dd_ptr->cent_n - 1].x;
154 for (int i = 0; i < dd_ptr->cent_n; i++) {
155 if (!decide_tunnel_planned_site(player_ptr, dd_ptr, d_ptr, dt_ptr, i))
158 make_tunnels(player_ptr, dd_ptr);
159 make_walls(player_ptr, dd_ptr, d_ptr, dt_ptr);
160 dd_ptr->tunnel_y = dd_ptr->cent[i].y;
161 dd_ptr->tunnel_x = dd_ptr->cent[i].x;
167 static void make_doors(player_type *player_ptr, dun_data_type *dd_ptr, dt_type *dt_ptr)
169 for (int i = 0; i < dd_ptr->door_n; i++) {
170 dd_ptr->tunnel_y = dd_ptr->door[i].y;
171 dd_ptr->tunnel_x = dd_ptr->door[i].x;
172 try_door(player_ptr, dt_ptr, dd_ptr->tunnel_y, dd_ptr->tunnel_x - 1);
173 try_door(player_ptr, dt_ptr, dd_ptr->tunnel_y, dd_ptr->tunnel_x + 1);
174 try_door(player_ptr, dt_ptr, dd_ptr->tunnel_y - 1, dd_ptr->tunnel_x);
175 try_door(player_ptr, dt_ptr, dd_ptr->tunnel_y + 1, dd_ptr->tunnel_x);
179 static void make_only_tunnel_points(floor_type *floor_ptr, dun_data_type *dd_ptr)
181 int point_num = (floor_ptr->width * floor_ptr->height) / 200 + randint1(3);
182 dd_ptr->cent_n = point_num;
183 for (int i = 0; i < point_num; i++) {
184 dd_ptr->cent[i].y = randint0(floor_ptr->height);
185 dd_ptr->cent[i].x = randint0(floor_ptr->width);
189 static bool make_one_floor(player_type *player_ptr, dun_data_type *dd_ptr, dungeon_type *d_ptr)
191 floor_type *floor_ptr = player_ptr->current_floor_ptr;
193 if (d_info[floor_ptr->dungeon_idx].flags.has(DF::NO_ROOM)) {
194 make_only_tunnel_points(floor_ptr, dd_ptr);
196 if (!generate_rooms(player_ptr, dd_ptr)) {
197 *dd_ptr->why = _("部屋群の生成に失敗", "Failed to generate rooms");
202 place_cave_contents(player_ptr, dd_ptr, d_ptr);
204 dt_type *dt_ptr = initialize_dt_type(&tmp_dt);
205 if (!make_centers(player_ptr, dd_ptr, d_ptr, dt_ptr))
208 make_doors(player_ptr, dd_ptr, dt_ptr);
209 if (!alloc_stairs(player_ptr, feat_down_stair, rand_range(3, 4), 3)) {
210 *dd_ptr->why = _("下り階段生成に失敗", "Failed to generate down stairs.");
214 if (!alloc_stairs(player_ptr, feat_up_stair, rand_range(1, 2), 3)) {
215 *dd_ptr->why = _("上り階段生成に失敗", "Failed to generate up stairs.");
222 static bool switch_making_floor(player_type *player_ptr, dun_data_type *dd_ptr, dungeon_type *d_ptr)
224 if (d_ptr->flags.has(DF::MAZE)) {
225 floor_type *floor_ptr = player_ptr->current_floor_ptr;
226 build_maze_vault(player_ptr, floor_ptr->width / 2 - 1, floor_ptr->height / 2 - 1, floor_ptr->width - 4, floor_ptr->height - 4, FALSE);
227 if (!alloc_stairs(player_ptr, feat_down_stair, rand_range(2, 3), 3)) {
228 *dd_ptr->why = _("迷宮ダンジョンの下り階段生成に失敗", "Failed to alloc up stairs in maze dungeon.");
232 if (!alloc_stairs(player_ptr, feat_up_stair, 1, 3)) {
233 *dd_ptr->why = _("迷宮ダンジョンの上り階段生成に失敗", "Failed to alloc down stairs in maze dungeon.");
240 if (!make_one_floor(player_ptr, dd_ptr, d_ptr))
246 static void make_aqua_streams(player_type *player_ptr, dun_data_type *dd_ptr, dungeon_type *d_ptr)
248 if (dd_ptr->laketype != 0)
252 for (int i = 0; i < DUN_STR_QUA; i++)
253 build_streamer(player_ptr, d_ptr->stream2, DUN_STR_QC);
256 for (int i = 0; i < DUN_STR_MAG; i++)
257 build_streamer(player_ptr, d_ptr->stream1, DUN_STR_MC);
260 static void make_perm_walls(player_type *player_ptr)
262 floor_type *floor_ptr = player_ptr->current_floor_ptr;
263 for (POSITION x = 0; x < floor_ptr->width; x++) {
264 place_bound_perm_wall(player_ptr, &floor_ptr->grid_array[0][x]);
265 place_bound_perm_wall(player_ptr, &floor_ptr->grid_array[floor_ptr->height - 1][x]);
268 for (POSITION y = 1; y < (floor_ptr->height - 1); y++) {
269 place_bound_perm_wall(player_ptr, &floor_ptr->grid_array[y][0]);
270 place_bound_perm_wall(player_ptr, &floor_ptr->grid_array[y][floor_ptr->width - 1]);
274 static bool check_place_necessary_objects(player_type *player_ptr, dun_data_type *dd_ptr)
276 if (!new_player_spot(player_ptr)) {
277 *dd_ptr->why = _("プレイヤー配置に失敗", "Failed to place a player");
281 if (!place_quest_monsters(player_ptr)) {
282 *dd_ptr->why = _("クエストモンスター配置に失敗", "Failed to place a quest monster");
289 static void decide_dungeon_data_allocation(player_type *player_ptr, dun_data_type *dd_ptr, dungeon_type *d_ptr)
291 floor_type *floor_ptr = player_ptr->current_floor_ptr;
292 dd_ptr->alloc_object_num = floor_ptr->dun_level / 3;
293 if (dd_ptr->alloc_object_num > 10)
294 dd_ptr->alloc_object_num = 10;
296 if (dd_ptr->alloc_object_num < 2)
297 dd_ptr->alloc_object_num = 2;
299 dd_ptr->alloc_monster_num = d_ptr->min_m_alloc_level;
300 if (floor_ptr->height >= MAX_HGT && floor_ptr->width >= MAX_WID)
303 int small_tester = dd_ptr->alloc_monster_num;
304 dd_ptr->alloc_monster_num = (dd_ptr->alloc_monster_num * floor_ptr->height) / MAX_HGT;
305 dd_ptr->alloc_monster_num = (dd_ptr->alloc_monster_num * floor_ptr->width) / MAX_WID;
306 dd_ptr->alloc_monster_num += 1;
307 if (dd_ptr->alloc_monster_num > small_tester)
308 dd_ptr->alloc_monster_num = small_tester;
310 msg_format_wizard(player_ptr, CHEAT_DUNGEON, _("モンスター数基本値を %d から %d に減らします", "Reduced monsters base from %d to %d"), small_tester,
311 dd_ptr->alloc_monster_num);
314 static bool allocate_dungeon_data(player_type *player_ptr, dun_data_type *dd_ptr, dungeon_type *d_ptr)
316 dd_ptr->alloc_monster_num += randint1(8);
317 for (dd_ptr->alloc_monster_num = dd_ptr->alloc_monster_num + dd_ptr->alloc_object_num; dd_ptr->alloc_monster_num > 0; dd_ptr->alloc_monster_num--)
318 (void)alloc_monster(player_ptr, 0, PM_ALLOW_SLEEP, summon_specific);
320 alloc_object(player_ptr, ALLOC_SET_BOTH, ALLOC_TYP_TRAP, randint1(dd_ptr->alloc_object_num));
321 if (d_ptr->flags.has_not(DF::NO_CAVE))
322 alloc_object(player_ptr, ALLOC_SET_CORR, ALLOC_TYP_RUBBLE, randint1(dd_ptr->alloc_object_num));
324 floor_type *floor_ptr = player_ptr->current_floor_ptr;
325 if (player_ptr->enter_dungeon && floor_ptr->dun_level > 1)
326 floor_ptr->object_level = 1;
328 alloc_object(player_ptr, ALLOC_SET_ROOM, ALLOC_TYP_OBJECT, randnor(DUN_AMT_ROOM, 3));
329 alloc_object(player_ptr, ALLOC_SET_BOTH, ALLOC_TYP_OBJECT, randnor(DUN_AMT_ITEM, 3));
330 alloc_object(player_ptr, ALLOC_SET_BOTH, ALLOC_TYP_GOLD, randnor(DUN_AMT_GOLD, 3));
331 floor_ptr->object_level = floor_ptr->base_level;
332 if (alloc_guardian(player_ptr, TRUE))
335 *dd_ptr->why = _("ダンジョンの主配置に失敗", "Failed to place a dungeon guardian");
339 static void decide_grid_glowing(floor_type *floor_ptr, dun_data_type *dd_ptr, dungeon_type *d_ptr)
341 bool is_empty_or_dark = dd_ptr->empty_level;
342 is_empty_or_dark &= !one_in_(DARK_EMPTY) || (randint1(100) > floor_ptr->dun_level);
343 is_empty_or_dark &= d_ptr->flags.has_not(DF::DARKNESS);
344 if (!is_empty_or_dark)
347 for (POSITION y = 0; y < floor_ptr->height; y++)
348 for (POSITION x = 0; x < floor_ptr->width; x++)
349 floor_ptr->grid_array[y][x].info |= CAVE_GLOW;
353 * @brief ダンジョン生成のメインルーチン / Generate a new dungeon level
354 * @details Note that "dun_body" adds about 4000 bytes of memory to the stack.
355 * @param player_ptr プレーヤーへの参照ポインタ
356 * @param why エラー原因メッセージを返す
357 * @return ダンジョン生成が全て無事に成功したらTRUEを返す。
359 bool cave_gen(player_type *player_ptr, concptr *why)
361 floor_type *floor_ptr = player_ptr->current_floor_ptr;
362 reset_lite_area(floor_ptr);
363 set_floor_and_wall(floor_ptr->dungeon_idx);
364 get_mon_num_prep(player_ptr, get_monster_hook(player_ptr), NULL);
366 dun_data_type tmp_dd;
367 dun_data_type *dd_ptr = initialize_dun_data_type(&tmp_dd, why);
368 dd_ptr->row_rooms = floor_ptr->height / BLOCK_HGT;
369 dd_ptr->col_rooms = floor_ptr->width / BLOCK_WID;
370 for (POSITION y = 0; y < dd_ptr->row_rooms; y++)
371 for (POSITION x = 0; x < dd_ptr->col_rooms; x++)
372 dd_ptr->room_map[y][x] = FALSE;
375 dungeon_type *d_ptr = &d_info[floor_ptr->dungeon_idx];
376 if (ironman_empty_levels || (d_ptr->flags.has(DF::ARENA) && (empty_levels && one_in_(EMPTY_LEVEL)))) {
377 dd_ptr->empty_level = TRUE;
378 msg_print_wizard(player_ptr, CHEAT_DUNGEON, _("アリーナレベルを生成。", "Arena level."));
381 check_arena_floor(player_ptr, dd_ptr);
382 gen_caverns_and_lakes(player_ptr, d_ptr, dd_ptr);
383 if (!switch_making_floor(player_ptr, dd_ptr, d_ptr))
386 make_aqua_streams(player_ptr, dd_ptr, d_ptr);
387 make_perm_walls(player_ptr);
388 if (!check_place_necessary_objects(player_ptr, dd_ptr))
391 decide_dungeon_data_allocation(player_ptr, dd_ptr, d_ptr);
392 if (!allocate_dungeon_data(player_ptr, dd_ptr, d_ptr))
395 decide_grid_glowing(floor_ptr, dd_ptr, d_ptr);