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"
10 * @brief 指定のマスが床系地形であるかを返す / Function that sees if a square is a floor. (Includes range checking.)
11 * @param x チェックするマスのX座標
12 * @param y チェックするマスのY座標
15 static bool get_is_floor(floor_type *floor_ptr, POSITION x, POSITION y)
17 if (!in_bounds(floor_ptr, y, x)) {
21 if (is_floor_bold(floor_ptr, y, x))
28 * @brief 指定のマスを床地形に変える / Set a square to be floor. (Includes range checking.)
29 * @param player_ptr プレーヤーへの参照ポインタ
30 * @param x 地形を変えたいマスのX座標
31 * @param y 地形を変えたいマスのY座標
34 static void set_floor(player_type *player_ptr, POSITION x, POSITION y)
36 floor_type *floor_ptr = player_ptr->current_floor_ptr;
37 if (!in_bounds(floor_ptr, y, x))
40 if (floor_ptr->grid_array[y][x].info & CAVE_ROOM)
43 if (is_extra_bold(floor_ptr, y, x))
44 place_bold(player_ptr, y, x, GB_FLOOR);
49 * 指定範囲に通路が通っていることを確認した上で床で埋める
50 * This function tunnels around a room if it will cut off part of a grid system.
51 * @param player_ptr プレーヤーへの参照ポインタ
58 static void check_room_boundary(player_type *player_ptr, POSITION x1, POSITION y1, POSITION x2, POSITION y2)
64 floor_type *floor_ptr = player_ptr->current_floor_ptr;
65 old_is_floor = get_is_floor(floor_ptr, x1 - 1, y1);
67 for (POSITION x = x1; x <= x2; x++) {
68 new_is_floor = get_is_floor(floor_ptr, x, y1 - 1);
69 if (new_is_floor != old_is_floor)
72 old_is_floor = new_is_floor;
75 for (POSITION y = y1; y <= y2; y++) {
76 new_is_floor = get_is_floor(floor_ptr, x2 + 1, y);
77 if (new_is_floor != old_is_floor)
80 old_is_floor = new_is_floor;
83 for (POSITION x = x2; x >= x1; x--) {
84 new_is_floor = get_is_floor(floor_ptr, x, y2 + 1);
85 if (new_is_floor != old_is_floor)
88 old_is_floor = new_is_floor;
91 for (POSITION y = y2; y >= y1; y--) {
92 new_is_floor = get_is_floor(floor_ptr, x1 - 1, y);
93 if (new_is_floor != old_is_floor)
96 old_is_floor = new_is_floor;
102 for (POSITION y = y1; y <= y2; y++)
103 for (POSITION x = x1; x <= x2; x++)
104 set_floor(player_ptr, x, y);
109 * find_space()の予備処理として部屋の生成が可能かを判定する /
110 * Helper function for find_space(). Is this a good location?
111 * @param blocks_high 範囲の高さ
112 * @param blocks_wide 範囲の幅
113 * @param block_y 範囲の上端
114 * @param block_x 範囲の左端
117 static bool find_space_aux(dun_data_type *dd_ptr, POSITION blocks_high, POSITION blocks_wide, POSITION block_y, POSITION block_x)
119 if (blocks_wide < 3) {
120 if ((blocks_wide == 2) && (block_x % 3) == 2)
122 } else if ((blocks_wide % 3) == 0) {
123 if ((block_x % 3) != 0)
126 if (block_x + (blocks_wide / 2) <= dd_ptr->col_rooms / 2) {
127 if (((block_x % 3) == 2) && ((blocks_wide % 3) == 2))
129 if ((block_x % 3) == 1)
132 if (((block_x % 3) == 2) && ((blocks_wide % 3) == 2))
134 if ((block_x % 3) == 1)
139 POSITION by1 = block_y;
140 POSITION bx1 = block_x;
141 POSITION by2 = block_y + blocks_high;
142 POSITION bx2 = block_x + blocks_wide;
144 if ((by1 < 0) || (by2 > dd_ptr->row_rooms) || (bx1 < 0) || (bx2 > dd_ptr->col_rooms))
147 for (POSITION by = by1; by < by2; by++)
148 for (POSITION bx = bx1; bx < bx2; bx++)
149 if (dd_ptr->room_map[by][bx])
156 * @brief 部屋生成が可能なスペースを確保する / Find a good spot for the next room. -LM-
157 * @param player_ptr プレーヤーへの参照ポインタ
158 * @param y 部屋の生成が可能な中心Y座標を返す参照ポインタ
159 * @param x 部屋の生成が可能な中心X座標を返す参照ポインタ
160 * @param height 確保したい領域の高さ
161 * @param width 確保したい領域の幅
162 * @return 所定の範囲が確保できた場合TRUEを返す
164 * Find and allocate a free space in the dungeon large enough to hold\n
165 * the room calling this function.\n
167 * We allocate space in 11x11 blocks, but want to make sure that rooms\n
168 * align neatly on the standard screen. Therefore, we make them use\n
169 * blocks in few 11x33 rectangles as possible.\n
171 * Be careful to include the edges of the room in height and width!\n
173 * Return TRUE and values for the center of the room if all went well.\n
174 * Otherwise, return FALSE.\n
176 bool find_space(player_type *player_ptr, dun_data_type *dd_ptr, POSITION *y, POSITION *x, POSITION height, POSITION width)
179 POSITION block_y = 0;
180 POSITION block_x = 0;
181 POSITION blocks_high = 1 + ((height - 1) / BLOCK_HGT);
182 POSITION blocks_wide = 1 + ((width - 1) / BLOCK_WID);
183 if ((dd_ptr->row_rooms < blocks_high) || (dd_ptr->col_rooms < blocks_wide))
187 for (block_y = dd_ptr->row_rooms - blocks_high; block_y >= 0; block_y--) {
188 for (block_x = dd_ptr->col_rooms - blocks_wide; block_x >= 0; block_x--) {
189 if (find_space_aux(dd_ptr, blocks_high, blocks_wide, block_y, block_x)) {
190 /* Find a valid place */
199 if (!(d_info[player_ptr->current_floor_ptr->dungeon_idx].flags1 & DF1_NO_CAVE))
200 pick = randint1(candidates);
202 pick = candidates / 2 + 1;
204 for (block_y = dd_ptr->row_rooms - blocks_high; block_y >= 0; block_y--) {
205 for (block_x = dd_ptr->col_rooms - blocks_wide; block_x >= 0; block_x--) {
206 if (find_space_aux(dd_ptr, blocks_high, blocks_wide, block_y, block_x)) {
217 POSITION by1 = block_y;
218 POSITION bx1 = block_x;
219 POSITION by2 = block_y + blocks_high;
220 POSITION bx2 = block_x + blocks_wide;
221 *y = ((by1 + by2) * BLOCK_HGT) / 2;
222 *x = ((bx1 + bx2) * BLOCK_WID) / 2;
223 if (dd_ptr->cent_n < CENT_MAX) {
224 dd_ptr->cent[dd_ptr->cent_n].y = (byte)*y;
225 dd_ptr->cent[dd_ptr->cent_n].x = (byte)*x;
229 for (POSITION by = by1; by < by2; by++)
230 for (POSITION bx = bx1; bx < bx2; bx++)
231 dd_ptr->room_map[by][bx] = TRUE;
233 check_room_boundary(player_ptr, *x - width / 2 - 1, *y - height / 2 - 1, *x + (width - 1) / 2 + 1, *y + (height - 1) / 2 + 1);