OSDN Git Service

927b0821cb01e42a3531654430828238ac0fafc7
[hengbandforosx/hengbandosx.git] / src / grid / feature-generator.cpp
1 #include "grid/feature-generator.h"
2 #include "dungeon/dungeon-flag-mask.h"
3 #include "dungeon/dungeon-flag-types.h"
4 #include "dungeon/dungeon.h"
5 #include "dungeon/quest.h"
6 #include "floor/cave.h"
7 #include "floor/dungeon-tunnel-util.h"
8 #include "floor/geometry.h"
9 #include "game-option/cheat-types.h"
10 #include "game-option/game-play-options.h"
11 #include "grid/door.h"
12 #include "grid/feature-flag-types.h"
13 #include "room/lake-types.h"
14 #include "room/rooms-builder.h"
15 #include "system/dungeon-data-definition.h"
16 #include "system/floor-type-definition.h"
17 #include "system/grid-type-definition.h"
18 #include "system/player-type-definition.h"
19 #include "wizard/wizard-messages.h"
20
21 /*!
22  * @brief フロアに洞窟や湖を配置する / Generate various caverns and lakes
23  * @details There were moved from cave_gen().
24  */
25 void gen_caverns_and_lakes(player_type *owner_ptr, dungeon_type *dungeon_ptr, dun_data_type *dd_ptr)
26 {
27     floor_type *floor_ptr = owner_ptr->current_floor_ptr;
28     if ((floor_ptr->dun_level > 30) && one_in_(DUN_DEST * 2) && small_levels && dungeon_ptr->flags.has(DF::DESTROY)) {
29         dd_ptr->destroyed = true;
30         build_lake(owner_ptr, one_in_(2) ? LAKE_T_CAVE : LAKE_T_EARTH_VAULT);
31     }
32
33     if (one_in_(LAKE_LEVEL) && !dd_ptr->empty_level && !dd_ptr->destroyed && dungeon_ptr->flags.has_any_of(DF_LAKE_MASK)) {
34         int count = 0;
35         if (dungeon_ptr->flags.has(DF::LAKE_WATER))
36             count += 3;
37
38         if (dungeon_ptr->flags.has(DF::LAKE_LAVA))
39             count += 3;
40
41         if (dungeon_ptr->flags.has(DF::LAKE_RUBBLE))
42             count += 3;
43
44         if (dungeon_ptr->flags.has(DF::LAKE_TREE))
45             count += 3;
46
47         if (dungeon_ptr->flags.has(DF::LAKE_LAVA)) {
48             if ((floor_ptr->dun_level > 80) && (randint0(count) < 2))
49                 dd_ptr->laketype = LAKE_T_LAVA;
50
51             count -= 2;
52             if (!dd_ptr->laketype && (floor_ptr->dun_level > 80) && one_in_(count))
53                 dd_ptr->laketype = LAKE_T_FIRE_VAULT;
54
55             count--;
56         }
57
58         if (dungeon_ptr->flags.has(DF::LAKE_WATER) && !dd_ptr->laketype) {
59             if ((floor_ptr->dun_level > 50) && randint0(count) < 2)
60                 dd_ptr->laketype = LAKE_T_WATER;
61
62             count -= 2;
63             if (!dd_ptr->laketype && (floor_ptr->dun_level > 50) && one_in_(count))
64                 dd_ptr->laketype = LAKE_T_WATER_VAULT;
65
66             count--;
67         }
68
69         if (dungeon_ptr->flags.has(DF::LAKE_RUBBLE) && !dd_ptr->laketype) {
70             if ((floor_ptr->dun_level > 35) && (randint0(count) < 2))
71                 dd_ptr->laketype = LAKE_T_CAVE;
72
73             count -= 2;
74             if (!dd_ptr->laketype && (floor_ptr->dun_level > 35) && one_in_(count))
75                 dd_ptr->laketype = LAKE_T_EARTH_VAULT;
76
77             count--;
78         }
79
80         if ((floor_ptr->dun_level > 5) && dungeon_ptr->flags.has(DF::LAKE_TREE) && !dd_ptr->laketype)
81             dd_ptr->laketype = LAKE_T_AIR_VAULT;
82
83         if (dd_ptr->laketype) {
84             msg_print_wizard(owner_ptr, CHEAT_DUNGEON, _("湖を生成します。", "Lake on the level."));
85             build_lake(owner_ptr, dd_ptr->laketype);
86         }
87     }
88
89     if ((floor_ptr->dun_level > DUN_CAVERN) && !dd_ptr->empty_level && dungeon_ptr->flags.has(DF::CAVERN) && !dd_ptr->laketype && !dd_ptr->destroyed
90         && (randint1(1000) < floor_ptr->dun_level)) {
91         dd_ptr->cavern = true;
92         msg_print_wizard(owner_ptr, CHEAT_DUNGEON, _("洞窟を生成。", "Cavern on level."));
93         build_cavern(owner_ptr);
94     }
95
96     if (quest_number(owner_ptr, floor_ptr->dun_level))
97         dd_ptr->destroyed = false;
98 }
99
100 bool has_river_flag(dungeon_type *dungeon_ptr)
101 {
102     return dungeon_ptr->flags.has_any_of(DF_RIVER_MASK);
103 }
104
105 /*!
106  * @brief 隣接4マスに存在する通路の数を返す / Count the number of "corridor" grids adjacent to the given grid.
107  * @param y1 基準となるマスのY座標
108  * @param x1 基準となるマスのX座標
109  * @return 通路の数
110  * @note Assumes "in_bounds(y1, x1)"
111  * @details
112  * XXX XXX This routine currently only counts actual "empty floor"\n
113  * grids which are not in rooms.  We might want to also count stairs,\n
114  * open doors, closed doors, etc.
115  */
116 static int next_to_corr(floor_type *floor_ptr, POSITION y1, POSITION x1)
117 {
118     int k = 0;
119     for (int i = 0; i < 4; i++) {
120         POSITION y = y1 + ddy_ddd[i];
121         POSITION x = x1 + ddx_ddd[i];
122         grid_type *g_ptr;
123         g_ptr = &floor_ptr->grid_array[y][x];
124         if (cave_has_flag_grid(g_ptr, FF_WALL) || !g_ptr->is_floor() || g_ptr->is_room())
125             continue;
126
127         k++;
128     }
129
130     return k;
131 }
132
133 /*!
134  * @brief ドアを設置可能な地形かを返す / Determine if the given location is "between" two walls, and "next to" two corridor spaces.
135  * @param y 判定を行いたいマスのY座標
136  * @param x 判定を行いたいマスのX座標
137  * @return ドアを設置可能ならばTRUEを返す
138  * @details まず垂直方向に、次に水平方向に調べる
139  */
140 static bool possible_doorway(floor_type *floor_ptr, POSITION y, POSITION x)
141 {
142     if (next_to_corr(floor_ptr, y, x) < 2)
143         return false;
144
145     if (cave_has_flag_bold(floor_ptr, y - 1, x, FF_WALL) && cave_has_flag_bold(floor_ptr, y + 1, x, FF_WALL))
146         return true;
147
148     if (cave_has_flag_bold(floor_ptr, y, x - 1, FF_WALL) && cave_has_flag_bold(floor_ptr, y, x + 1, FF_WALL))
149         return true;
150
151     return false;
152 }
153
154 /*!
155  * @brief ドアの設置を試みる / Places door at y, x position if at least 2 walls found
156  * @param player_ptr プレーヤーへの参照ポインタ
157  * @param y 設置を行いたいマスのY座標
158  * @param x 設置を行いたいマスのX座標
159  */
160 void try_door(player_type *player_ptr, dt_type *dt_ptr, POSITION y, POSITION x)
161 {
162     floor_type *floor_ptr = player_ptr->current_floor_ptr;
163     if (!in_bounds(floor_ptr, y, x) || cave_has_flag_bold(floor_ptr, y, x, FF_WALL) || floor_ptr->grid_array[y][x].is_room())
164         return;
165
166     bool can_place_door = randint0(100) < dt_ptr->dun_tun_jct;
167     can_place_door &= possible_doorway(floor_ptr, y, x);
168     can_place_door &= d_info[player_ptr->dungeon_idx].flags.has_not(DF::NO_DOORS);
169     if (can_place_door)
170         place_random_door(player_ptr, y, x, false);
171 }