OSDN Git Service

[Refactor] #40581 Separated summon_self() from on_dead_dawn() and on_dead_totem_moai()
[hengbandforosx/hengbandosx.git] / src / floor / cave-generator.c
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/grid.h"
18 #include "monster-floor/monster-generator.h"
19 #include "monster-floor/monster-summon.h"
20 #include "monster-floor/place-monster-types.h"
21 #include "monster/monster-util.h"
22 #include "room/lake-types.h"
23 #include "room/room-generator.h"
24 #include "room/rooms-maze-vault.h"
25 #include "system/dungeon-data-definition.h"
26 #include "system/floor-type-definition.h"
27 #include "util/bit-flags-calculator.h"
28 #include "wizard/wizard-messages.h"
29
30 static void reset_lite_area(floor_type *floor_ptr)
31 {
32     floor_ptr->lite_n = 0;
33     floor_ptr->mon_lite_n = 0;
34     floor_ptr->redraw_n = 0;
35     floor_ptr->view_n = 0;
36 }
37
38 static dun_data_type *initialize_dun_data_type(dun_data_type *dd_ptr, concptr *why)
39 {
40     dd_ptr->destroyed = FALSE;
41     dd_ptr->empty_level = FALSE;
42     dd_ptr->cavern = FALSE;
43     dd_ptr->laketype = 0;
44     dd_ptr->why = why;
45     return dd_ptr;
46 }
47
48 static void check_arena_floor(player_type *player_ptr, dun_data_type *dd_ptr)
49 {
50     floor_type *floor_ptr = player_ptr->current_floor_ptr;
51     if (!dd_ptr->empty_level) {
52         for (POSITION y = 0; y < floor_ptr->height; y++)
53             for (POSITION x = 0; x < floor_ptr->width; x++)
54                 place_bold(player_ptr, y, x, GB_EXTRA);
55
56         return;
57     }
58
59     for (POSITION y = 0; y < floor_ptr->height; y++)
60         for (POSITION x = 0; x < floor_ptr->width; x++)
61             place_bold(player_ptr, y, x, GB_FLOOR);
62
63     for (POSITION x = 0; x < floor_ptr->width; x++) {
64         place_bold(player_ptr, 0, x, GB_EXTRA);
65         place_bold(player_ptr, floor_ptr->height - 1, x, GB_EXTRA);
66     }
67
68     for (POSITION y = 1; y < (floor_ptr->height - 1); y++) {
69         place_bold(player_ptr, y, 0, GB_EXTRA);
70         place_bold(player_ptr, y, floor_ptr->width - 1, GB_EXTRA);
71     }
72 }
73
74 static void place_cave_contents(player_type *player_ptr, dun_data_type *dd_ptr, dungeon_type *d_ptr)
75 {
76     floor_type *floor_ptr = player_ptr->current_floor_ptr;
77     if (floor_ptr->dun_level == 1)
78         while (one_in_(DUN_MOS_DEN))
79             place_trees(player_ptr, randint1(floor_ptr->width - 2), randint1(floor_ptr->height - 2));
80
81     if (dd_ptr->destroyed)
82         destroy_level(player_ptr);
83
84     if (has_river_flag(d_ptr) && one_in_(3) && (randint1(floor_ptr->dun_level) > 5))
85         add_river(floor_ptr, dd_ptr);
86
87     for (int i = 0; i < dd_ptr->cent_n; i++) {
88         POSITION ty, tx;
89         int pick = rand_range(0, i);
90         ty = dd_ptr->cent[i].y;
91         tx = dd_ptr->cent[i].x;
92         dd_ptr->cent[i].y = dd_ptr->cent[pick].y;
93         dd_ptr->cent[i].x = dd_ptr->cent[pick].x;
94         dd_ptr->cent[pick].y = ty;
95         dd_ptr->cent[pick].x = tx;
96     }
97 }
98
99 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)
100 {
101     dd_ptr->tunn_n = 0;
102     dd_ptr->wall_n = 0;
103     if (randint1(player_ptr->current_floor_ptr->dun_level) > d_ptr->tunnel_percent)
104         (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);
105     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))
106         dd_ptr->tunnel_fail_count++;
107
108     if (dd_ptr->tunnel_fail_count >= 2) {
109         *dd_ptr->why = _("トンネル接続に失敗", "Failed to generate tunnels");
110         return FALSE;
111     }
112
113     return TRUE;
114 }
115
116 static void make_tunnels(player_type *player_ptr, dun_data_type *dd_ptr)
117 {
118     for (int j = 0; j < dd_ptr->tunn_n; j++) {
119         grid_type *g_ptr;
120         feature_type *f_ptr;
121         dd_ptr->tunnel_y = dd_ptr->tunn[j].y;
122         dd_ptr->tunnel_x = dd_ptr->tunn[j].x;
123         g_ptr = &player_ptr->current_floor_ptr->grid_array[dd_ptr->tunnel_y][dd_ptr->tunnel_x];
124         f_ptr = &f_info[g_ptr->feat];
125         if (!have_flag(f_ptr->flags, FF_MOVE) || (!have_flag(f_ptr->flags, FF_WATER) && !have_flag(f_ptr->flags, FF_LAVA))) {
126             g_ptr->mimic = 0;
127             place_grid(player_ptr, g_ptr, GB_FLOOR);
128         }
129     }
130 }
131
132 static void make_walls(player_type *player_ptr, dun_data_type *dd_ptr, dungeon_type *d_ptr, dt_type *dt_ptr)
133 {
134     for (int j = 0; j < dd_ptr->wall_n; j++) {
135         grid_type *g_ptr;
136         dd_ptr->tunnel_y = dd_ptr->wall[j].y;
137         dd_ptr->tunnel_x = dd_ptr->wall[j].x;
138         g_ptr = &player_ptr->current_floor_ptr->grid_array[dd_ptr->tunnel_y][dd_ptr->tunnel_x];
139         g_ptr->mimic = 0;
140         place_grid(player_ptr, g_ptr, GB_FLOOR);
141         if ((randint0(100) < dt_ptr->dun_tun_pen) && !(d_ptr->flags1 & DF1_NO_DOORS))
142             place_random_door(player_ptr, dd_ptr->tunnel_y, dd_ptr->tunnel_x, TRUE);
143     }
144 }
145
146 static bool make_centers(player_type *player_ptr, dun_data_type *dd_ptr, dungeon_type *d_ptr, dt_type *dt_ptr)
147 {
148     dd_ptr->tunnel_fail_count = 0;
149     dd_ptr->door_n = 0;
150     dd_ptr->tunnel_y = dd_ptr->cent[dd_ptr->cent_n - 1].y;
151     dd_ptr->tunnel_x = dd_ptr->cent[dd_ptr->cent_n - 1].x;
152     for (int i = 0; i < dd_ptr->cent_n; i++) {
153         if (!decide_tunnel_planned_site(player_ptr, dd_ptr, d_ptr, dt_ptr, i))
154             return FALSE;
155
156         make_tunnels(player_ptr, dd_ptr);
157         make_walls(player_ptr, dd_ptr, d_ptr, dt_ptr);
158         dd_ptr->tunnel_y = dd_ptr->cent[i].y;
159         dd_ptr->tunnel_x = dd_ptr->cent[i].x;
160     }
161
162     return TRUE;
163 }
164
165 static void make_doors(player_type *player_ptr, dun_data_type *dd_ptr, dt_type *dt_ptr)
166 {
167     for (int i = 0; i < dd_ptr->door_n; i++) {
168         dd_ptr->tunnel_y = dd_ptr->door[i].y;
169         dd_ptr->tunnel_x = dd_ptr->door[i].x;
170         try_door(player_ptr, dt_ptr, dd_ptr->tunnel_y, dd_ptr->tunnel_x - 1);
171         try_door(player_ptr, dt_ptr, dd_ptr->tunnel_y, dd_ptr->tunnel_x + 1);
172         try_door(player_ptr, dt_ptr, dd_ptr->tunnel_y - 1, dd_ptr->tunnel_x);
173         try_door(player_ptr, dt_ptr, dd_ptr->tunnel_y + 1, dd_ptr->tunnel_x);
174     }
175 }
176
177 static bool make_one_floor(player_type *player_ptr, dun_data_type *dd_ptr, dungeon_type *d_ptr)
178 {
179     if (!generate_rooms(player_ptr, dd_ptr)) {
180         *dd_ptr->why = _("部屋群の生成に失敗", "Failed to generate rooms");
181         return FALSE;
182     }
183
184     place_cave_contents(player_ptr, dd_ptr, d_ptr);
185     dt_type tmp_dt;
186     dt_type *dt_ptr = initialize_dt_type(&tmp_dt);
187     if (!make_centers(player_ptr, dd_ptr, d_ptr, dt_ptr))
188         return FALSE;
189
190     make_doors(player_ptr, dd_ptr, dt_ptr);
191     if (!alloc_stairs(player_ptr, feat_down_stair, rand_range(3, 4), 3)) {
192         *dd_ptr->why = _("下り階段生成に失敗", "Failed to generate down stairs.");
193         return FALSE;
194     }
195
196     if (!alloc_stairs(player_ptr, feat_up_stair, rand_range(1, 2), 3)) {
197         *dd_ptr->why = _("上り階段生成に失敗", "Failed to generate up stairs.");
198         return FALSE;
199     }
200
201     return TRUE;
202 }
203
204 static bool switch_making_floor(player_type *player_ptr, dun_data_type *dd_ptr, dungeon_type *d_ptr)
205 {
206     if (d_ptr->flags1 & DF1_MAZE) {
207         floor_type *floor_ptr = player_ptr->current_floor_ptr;
208         build_maze_vault(player_ptr, floor_ptr->width / 2 - 1, floor_ptr->height / 2 - 1, floor_ptr->width - 4, floor_ptr->height - 4, FALSE);
209         if (!alloc_stairs(player_ptr, feat_down_stair, rand_range(2, 3), 3)) {
210             *dd_ptr->why = _("迷宮ダンジョンの下り階段生成に失敗", "Failed to alloc up stairs in maze dungeon.");
211             return FALSE;
212         }
213
214         if (!alloc_stairs(player_ptr, feat_up_stair, 1, 3)) {
215             *dd_ptr->why = _("迷宮ダンジョンの上り階段生成に失敗", "Failed to alloc down stairs in maze dungeon.");
216             return FALSE;
217         }
218
219         return TRUE;
220     }
221     
222     if (!make_one_floor(player_ptr, dd_ptr, d_ptr))
223         return FALSE;
224
225     return TRUE;
226 }
227
228 static void make_aqua_streams(player_type *player_ptr, dun_data_type *dd_ptr, dungeon_type *d_ptr)
229 {
230     if (dd_ptr->laketype != 0)
231         return;
232
233     if (d_ptr->stream2)
234         for (int i = 0; i < DUN_STR_QUA; i++)
235             build_streamer(player_ptr, d_ptr->stream2, DUN_STR_QC);
236
237     if (d_ptr->stream1)
238         for (int i = 0; i < DUN_STR_MAG; i++)
239             build_streamer(player_ptr, d_ptr->stream1, DUN_STR_MC);
240 }
241
242 static void make_perm_walls(player_type *player_ptr)
243 {
244     floor_type *floor_ptr = player_ptr->current_floor_ptr;
245     for (POSITION x = 0; x < floor_ptr->width; x++) {
246         place_bound_perm_wall(player_ptr, &floor_ptr->grid_array[0][x]);
247         place_bound_perm_wall(player_ptr, &floor_ptr->grid_array[floor_ptr->height - 1][x]);
248     }
249
250     for (POSITION y = 1; y < (floor_ptr->height - 1); y++) {
251         place_bound_perm_wall(player_ptr, &floor_ptr->grid_array[y][0]);
252         place_bound_perm_wall(player_ptr, &floor_ptr->grid_array[y][floor_ptr->width - 1]);
253     }
254 }
255
256 static bool check_place_necessary_objects(player_type *player_ptr, dun_data_type *dd_ptr)
257 {
258     if (!new_player_spot(player_ptr)) {
259         *dd_ptr->why = _("プレイヤー配置に失敗", "Failed to place a player");
260         return FALSE;
261     }
262
263     if (!place_quest_monsters(player_ptr)) {
264         *dd_ptr->why = _("クエストモンスター配置に失敗", "Failed to place a quest monster");
265         return FALSE;
266     }
267
268     return TRUE;
269 }
270
271 static void decide_dungeon_data_allocation(player_type *player_ptr, dun_data_type *dd_ptr, dungeon_type *d_ptr)
272 {
273     floor_type *floor_ptr = player_ptr->current_floor_ptr;
274     dd_ptr->alloc_object_num = floor_ptr->dun_level / 3;
275     if (dd_ptr->alloc_object_num > 10)
276         dd_ptr->alloc_object_num = 10;
277
278     if (dd_ptr->alloc_object_num < 2)
279         dd_ptr->alloc_object_num = 2;
280
281     dd_ptr->alloc_monster_num = d_ptr->min_m_alloc_level;
282     if (floor_ptr->height >= MAX_HGT && floor_ptr->width >= MAX_WID)
283         return;
284
285     int small_tester = dd_ptr->alloc_monster_num;
286     dd_ptr->alloc_monster_num = (dd_ptr->alloc_monster_num * floor_ptr->height) / MAX_HGT;
287     dd_ptr->alloc_monster_num = (dd_ptr->alloc_monster_num * floor_ptr->width) / MAX_WID;
288     dd_ptr->alloc_monster_num += 1;
289     if (dd_ptr->alloc_monster_num > small_tester)
290         dd_ptr->alloc_monster_num = small_tester;
291     else
292         msg_format_wizard(player_ptr, CHEAT_DUNGEON, _("モンスター数基本値を %d から %d に減らします", "Reduced monsters base from %d to %d"), small_tester,
293             dd_ptr->alloc_monster_num);
294 }
295
296 static bool allocate_dungeon_data(player_type *player_ptr, dun_data_type *dd_ptr, dungeon_type *d_ptr)
297 {
298     dd_ptr->alloc_monster_num += randint1(8);
299     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--)
300         (void)alloc_monster(player_ptr, 0, PM_ALLOW_SLEEP, summon_specific);
301
302     alloc_object(player_ptr, ALLOC_SET_BOTH, ALLOC_TYP_TRAP, randint1(dd_ptr->alloc_object_num));
303     if (!(d_ptr->flags1 & DF1_NO_CAVE))
304         alloc_object(player_ptr, ALLOC_SET_CORR, ALLOC_TYP_RUBBLE, randint1(dd_ptr->alloc_object_num));
305
306     floor_type *floor_ptr = player_ptr->current_floor_ptr;
307     if (player_ptr->enter_dungeon && floor_ptr->dun_level > 1)
308         floor_ptr->object_level = 1;
309
310     alloc_object(player_ptr, ALLOC_SET_ROOM, ALLOC_TYP_OBJECT, randnor(DUN_AMT_ROOM, 3));
311     alloc_object(player_ptr, ALLOC_SET_BOTH, ALLOC_TYP_OBJECT, randnor(DUN_AMT_ITEM, 3));
312     alloc_object(player_ptr, ALLOC_SET_BOTH, ALLOC_TYP_GOLD, randnor(DUN_AMT_GOLD, 3));
313     floor_ptr->object_level = floor_ptr->base_level;
314     if (alloc_guardian(player_ptr, TRUE))
315         return TRUE;
316
317     *dd_ptr->why = _("ダンジョンの主配置に失敗", "Failed to place a dungeon guardian");
318     return FALSE;
319 }
320
321 static void decide_grid_glowing(floor_type *floor_ptr, dun_data_type *dd_ptr, dungeon_type *d_ptr)
322 {
323     bool is_empty_or_dark = dd_ptr->empty_level;
324     is_empty_or_dark &= !one_in_(DARK_EMPTY) || (randint1(100) > floor_ptr->dun_level);
325     is_empty_or_dark &= (d_ptr->flags1 & DF1_DARKNESS) == 0;
326     if (!is_empty_or_dark)
327         return;
328
329     for (POSITION y = 0; y < floor_ptr->height; y++)
330         for (POSITION x = 0; x < floor_ptr->width; x++)
331             floor_ptr->grid_array[y][x].info |= CAVE_GLOW;
332 }
333
334 /*!
335  * @brief ダンジョン生成のメインルーチン / Generate a new dungeon level
336  * @details Note that "dun_body" adds about 4000 bytes of memory to the stack.
337  * @param player_ptr プレーヤーへの参照ポインタ
338  * @param why エラー原因メッセージを返す
339  * @return ダンジョン生成が全て無事に成功したらTRUEを返す。
340  */
341 bool cave_gen(player_type *player_ptr, concptr *why)
342 {
343     floor_type *floor_ptr = player_ptr->current_floor_ptr;
344     reset_lite_area(floor_ptr);
345     set_floor_and_wall(floor_ptr->dungeon_idx);
346     get_mon_num_prep(player_ptr, get_monster_hook(player_ptr), NULL);
347
348     dun_data_type tmp_dd;
349     dun_data_type *dd_ptr = initialize_dun_data_type(&tmp_dd, why);
350     dd_ptr->row_rooms = floor_ptr->height / BLOCK_HGT;
351     dd_ptr->col_rooms = floor_ptr->width / BLOCK_WID;
352     for (POSITION y = 0; y < dd_ptr->row_rooms; y++)
353         for (POSITION x = 0; x < dd_ptr->col_rooms; x++)
354             dd_ptr->room_map[y][x] = FALSE;
355
356     dd_ptr->cent_n = 0;
357     dungeon_type *d_ptr = &d_info[floor_ptr->dungeon_idx];
358     if (ironman_empty_levels || ((d_ptr->flags1 & DF1_ARENA) && (empty_levels && one_in_(EMPTY_LEVEL)))) {
359         dd_ptr->empty_level = TRUE;
360         msg_print_wizard(player_ptr, CHEAT_DUNGEON, _("アリーナレベルを生成。", "Arena level."));
361     }
362
363     check_arena_floor(player_ptr, dd_ptr);
364     gen_caverns_and_lakes(player_ptr, d_ptr, dd_ptr);
365     if (!switch_making_floor(player_ptr, dd_ptr, d_ptr))
366         return FALSE;
367
368     make_aqua_streams(player_ptr, dd_ptr, d_ptr);
369     make_perm_walls(player_ptr);
370     if (!check_place_necessary_objects(player_ptr, dd_ptr))
371         return FALSE;
372
373     decide_dungeon_data_allocation(player_ptr, dd_ptr, d_ptr);
374     if (!allocate_dungeon_data(player_ptr, dd_ptr, d_ptr))
375         return FALSE;
376
377     decide_grid_glowing(floor_ptr, dd_ptr, d_ptr);
378     return TRUE;
379 }