1 #include "room/space-finder.h"
2 #include "dungeon/dungeon-flag-types.h"
3 #include "dungeon/dungeon.h"
4 #include "floor/cave.h"
6 #include "system/dungeon-data-definition.h"
7 #include "system/floor-type-definition.h"
8 #include "system/player-type-definition.h"
11 * @brief 指定のマスが床系地形であるかを返す / Function that sees if a square is a floor. (Includes range checking.)
12 * @param x チェックするマスのX座標
13 * @param y チェックするマスのY座標
16 static bool get_is_floor(floor_type *floor_ptr, POSITION x, POSITION y)
18 if (!in_bounds(floor_ptr, y, x)) {
22 if (is_floor_bold(floor_ptr, y, x))
29 * @brief 指定のマスを床地形に変える / Set a square to be floor. (Includes range checking.)
30 * @param player_ptr プレーヤーへの参照ポインタ
31 * @param x 地形を変えたいマスのX座標
32 * @param y 地形を変えたいマスのY座標
35 static void set_floor(player_type *player_ptr, POSITION x, POSITION y)
37 floor_type *floor_ptr = player_ptr->current_floor_ptr;
38 if (!in_bounds(floor_ptr, y, x))
41 if (floor_ptr->grid_array[y][x].info & CAVE_ROOM)
44 if (is_extra_bold(floor_ptr, y, x))
45 place_bold(player_ptr, y, x, GB_FLOOR);
50 * 指定範囲に通路が通っていることを確認した上で床で埋める
51 * This function tunnels around a room if it will cut off part of a grid system.
52 * @param player_ptr プレーヤーへの参照ポインタ
59 static void check_room_boundary(player_type *player_ptr, POSITION x1, POSITION y1, POSITION x2, POSITION y2)
65 floor_type *floor_ptr = player_ptr->current_floor_ptr;
66 old_is_floor = get_is_floor(floor_ptr, x1 - 1, y1);
68 for (POSITION x = x1; x <= x2; x++) {
69 new_is_floor = get_is_floor(floor_ptr, x, y1 - 1);
70 if (new_is_floor != old_is_floor)
73 old_is_floor = new_is_floor;
76 for (POSITION y = y1; y <= y2; y++) {
77 new_is_floor = get_is_floor(floor_ptr, x2 + 1, y);
78 if (new_is_floor != old_is_floor)
81 old_is_floor = new_is_floor;
84 for (POSITION x = x2; x >= x1; x--) {
85 new_is_floor = get_is_floor(floor_ptr, x, y2 + 1);
86 if (new_is_floor != old_is_floor)
89 old_is_floor = new_is_floor;
92 for (POSITION y = y2; y >= y1; y--) {
93 new_is_floor = get_is_floor(floor_ptr, x1 - 1, y);
94 if (new_is_floor != old_is_floor)
97 old_is_floor = new_is_floor;
103 for (POSITION y = y1; y <= y2; y++)
104 for (POSITION x = x1; x <= x2; x++)
105 set_floor(player_ptr, x, y);
110 * find_space()の予備処理として部屋の生成が可能かを判定する /
111 * Helper function for find_space(). Is this a good location?
112 * @param blocks_high 範囲の高さ
113 * @param blocks_wide 範囲の幅
114 * @param block_y 範囲の上端
115 * @param block_x 範囲の左端
118 static bool find_space_aux(dun_data_type *dd_ptr, POSITION blocks_high, POSITION blocks_wide, POSITION block_y, POSITION block_x)
120 if (blocks_wide < 3) {
121 if ((blocks_wide == 2) && (block_x % 3) == 2)
123 } else if ((blocks_wide % 3) == 0) {
124 if ((block_x % 3) != 0)
127 if (block_x + (blocks_wide / 2) <= dd_ptr->col_rooms / 2) {
128 if (((block_x % 3) == 2) && ((blocks_wide % 3) == 2))
130 if ((block_x % 3) == 1)
133 if (((block_x % 3) == 2) && ((blocks_wide % 3) == 2))
135 if ((block_x % 3) == 1)
140 POSITION by1 = block_y;
141 POSITION bx1 = block_x;
142 POSITION by2 = block_y + blocks_high;
143 POSITION bx2 = block_x + blocks_wide;
145 if ((by1 < 0) || (by2 > dd_ptr->row_rooms) || (bx1 < 0) || (bx2 > dd_ptr->col_rooms))
148 for (POSITION by = by1; by < by2; by++)
149 for (POSITION bx = bx1; bx < bx2; bx++)
150 if (dd_ptr->room_map[by][bx])
157 * @brief 部屋生成が可能なスペースを確保する / Find a good spot for the next room. -LM-
158 * @param player_ptr プレーヤーへの参照ポインタ
159 * @param y 部屋の生成が可能な中心Y座標を返す参照ポインタ
160 * @param x 部屋の生成が可能な中心X座標を返す参照ポインタ
161 * @param height 確保したい領域の高さ
162 * @param width 確保したい領域の幅
163 * @return 所定の範囲が確保できた場合TRUEを返す
165 * Find and allocate a free space in the dungeon large enough to hold\n
166 * the room calling this function.\n
168 * We allocate space in 11x11 blocks, but want to make sure that rooms\n
169 * alignment neatly on the standard screen. Therefore, we make them use\n
170 * blocks in few 11x33 rectangles as possible.\n
172 * Be careful to include the edges of the room in height and width!\n
174 * Return TRUE and values for the center of the room if all went well.\n
175 * Otherwise, return FALSE.\n
177 bool find_space(player_type *player_ptr, dun_data_type *dd_ptr, POSITION *y, POSITION *x, POSITION height, POSITION width)
180 POSITION block_y = 0;
181 POSITION block_x = 0;
182 POSITION blocks_high = 1 + ((height - 1) / BLOCK_HGT);
183 POSITION blocks_wide = 1 + ((width - 1) / BLOCK_WID);
184 if ((dd_ptr->row_rooms < blocks_high) || (dd_ptr->col_rooms < blocks_wide))
188 for (block_y = dd_ptr->row_rooms - blocks_high; block_y >= 0; block_y--) {
189 for (block_x = dd_ptr->col_rooms - blocks_wide; block_x >= 0; block_x--) {
190 if (find_space_aux(dd_ptr, blocks_high, blocks_wide, block_y, block_x)) {
191 /* Find a valid place */
200 if (!(d_info[player_ptr->current_floor_ptr->dungeon_idx].flags1 & DF1_NO_CAVE))
201 pick = randint1(candidates);
203 pick = candidates / 2 + 1;
205 for (block_y = dd_ptr->row_rooms - blocks_high; block_y >= 0; block_y--) {
206 for (block_x = dd_ptr->col_rooms - blocks_wide; block_x >= 0; block_x--) {
207 if (find_space_aux(dd_ptr, blocks_high, blocks_wide, block_y, block_x)) {
218 POSITION by1 = block_y;
219 POSITION bx1 = block_x;
220 POSITION by2 = block_y + blocks_high;
221 POSITION bx2 = block_x + blocks_wide;
222 *y = ((by1 + by2) * BLOCK_HGT) / 2;
223 *x = ((bx1 + bx2) * BLOCK_WID) / 2;
224 if (dd_ptr->cent_n < CENT_MAX) {
225 dd_ptr->cent[dd_ptr->cent_n].y = (byte)*y;
226 dd_ptr->cent[dd_ptr->cent_n].x = (byte)*x;
230 for (POSITION by = by1; by < by2; by++)
231 for (POSITION bx = bx1; bx < bx2; bx++)
232 dd_ptr->room_map[by][bx] = TRUE;
234 check_room_boundary(player_ptr, *x - width / 2 - 1, *y - height / 2 - 1, *x + (width - 1) / 2 + 1, *y + (height - 1) / 2 + 1);