2 * @brief fill_data_type構造体を使ってダンジョンを生成/構成する処理
7 #include "room/cave-filler.h"
8 #include "dungeon/dungeon-flag-types.h"
9 #include "dungeon/dungeon.h"
10 #include "floor//geometry.h"
11 #include "floor/cave.h"
12 #include "grid/feature.h"
13 #include "grid/grid.h"
14 #include "room/lake-types.h"
15 #include "system/floor-type-definition.h"
16 #include "system/grid-type-definition.h"
17 #include "system/player-type-definition.h"
18 #include "util/point-2d.h"
21 typedef struct fill_data_type {
32 /* features to fill with */
41 /* number of filled squares */
45 static fill_data_type fill_data;
48 * Store routine for the fractal floor generator
49 * this routine probably should be an inline function or a macro.
51 static void store_height(floor_type *floor_ptr, POSITION x, POSITION y, FEAT_IDX val)
53 if (((x == fill_data.xmin) || (y == fill_data.ymin) || (x == fill_data.xmax) || (y == fill_data.ymax)) && (val <= fill_data.c1))
54 val = fill_data.c1 + 1;
56 floor_ptr->grid_array[y][x].feat = val;
60 void generate_hmap(floor_type *floor_ptr, POSITION y0, POSITION x0, POSITION xsiz, POSITION ysiz, int grd, int roug, int cutoff)
62 POSITION xsize = xsiz;
63 POSITION ysize = ysiz;
77 POSITION xhsize = xsize / 2;
78 POSITION yhsize = ysize / 2;
82 fill_data.xmin = x0 - xhsize;
83 fill_data.ymin = y0 - yhsize;
84 fill_data.xmax = x0 + xhsize;
85 fill_data.ymax = y0 + yhsize;
86 fill_data.c1 = cutoff;
87 POSITION diagsize = 362;
88 POSITION maxsize = (xsize > ysize) ? xsize : ysize;
89 for (POSITION i = 0; i <= xsize; i++) {
90 for (POSITION j = 0; j <= ysize; j++) {
91 floor_ptr->grid_array[(int)(fill_data.ymin + j)][(int)(fill_data.xmin + i)].feat = -1;
92 floor_ptr->grid_array[(int)(fill_data.ymin + j)][(int)(fill_data.xmin + i)].info &= ~(CAVE_ICKY);
96 floor_ptr->grid_array[fill_data.ymin][fill_data.xmin].feat = (int16_t)maxsize;
97 floor_ptr->grid_array[fill_data.ymax][fill_data.xmin].feat = (int16_t)maxsize;
98 floor_ptr->grid_array[fill_data.ymin][fill_data.xmax].feat = (int16_t)maxsize;
99 floor_ptr->grid_array[fill_data.ymax][fill_data.xmax].feat = (int16_t)maxsize;
100 floor_ptr->grid_array[y0][x0].feat = 0;
101 POSITION xstep = xsize * 256;
102 POSITION xhstep = xsize * 256;
103 POSITION ystep = ysize * 256;
104 POSITION yhstep = ysize * 256;
105 POSITION xxsize = xsize * 256;
106 POSITION yysize = ysize * 256;
107 while ((xhstep > 256) || (yhstep > 256)) {
112 POSITION xstep2 = xstep / 256;
113 POSITION ystep2 = ystep / 256;
114 POSITION xhstep2 = xhstep / 256;
115 POSITION yhstep2 = yhstep / 256;
116 for (POSITION i = xhstep; i <= xxsize - xhstep; i += xstep) {
117 for (POSITION j = 0; j <= yysize; j += ystep) {
118 POSITION ii = i / 256 + fill_data.xmin;
119 POSITION jj = j / 256 + fill_data.ymin;
120 if (floor_ptr->grid_array[jj][ii].feat != -1)
124 store_height(floor_ptr, ii, jj, randint1(maxsize));
128 store_height(floor_ptr, ii, jj,
129 (floor_ptr->grid_array[jj][fill_data.xmin + (i - xhstep) / 256].feat + floor_ptr->grid_array[jj][fill_data.xmin + (i + xhstep) / 256].feat)
131 + (randint1(xstep2) - xhstep2) * roug / 16);
135 for (POSITION j = yhstep; j <= yysize - yhstep; j += ystep) {
136 for (POSITION i = 0; i <= xxsize; i += xstep) {
137 POSITION ii = i / 256 + fill_data.xmin;
138 POSITION jj = j / 256 + fill_data.ymin;
139 if (floor_ptr->grid_array[jj][ii].feat != -1)
143 store_height(floor_ptr, ii, jj, randint1(maxsize));
147 store_height(floor_ptr, ii, jj,
148 (floor_ptr->grid_array[fill_data.ymin + (j - yhstep) / 256][ii].feat + floor_ptr->grid_array[fill_data.ymin + (j + yhstep) / 256][ii].feat)
150 + (randint1(ystep2) - yhstep2) * roug / 16);
154 for (POSITION i = xhstep; i <= xxsize - xhstep; i += xstep) {
155 for (POSITION j = yhstep; j <= yysize - yhstep; j += ystep) {
156 POSITION ii = i / 256 + fill_data.xmin;
157 POSITION jj = j / 256 + fill_data.ymin;
158 if (floor_ptr->grid_array[jj][ii].feat != -1)
162 store_height(floor_ptr, ii, jj, randint1(maxsize));
166 POSITION xm = fill_data.xmin + (i - xhstep) / 256;
167 POSITION xp = fill_data.xmin + (i + xhstep) / 256;
168 POSITION ym = fill_data.ymin + (j - yhstep) / 256;
169 POSITION yp = fill_data.ymin + (j + yhstep) / 256;
170 store_height(floor_ptr, ii, jj,
171 (floor_ptr->grid_array[ym][xm].feat + floor_ptr->grid_array[yp][xm].feat + floor_ptr->grid_array[ym][xp].feat
172 + floor_ptr->grid_array[yp][xp].feat)
174 + (randint1(xstep2) - xhstep2) * (diagsize / 16) / 256 * roug);
180 static bool hack_isnt_wall(player_type *player_ptr, POSITION y, POSITION x, int c1, int c2, int c3, FEAT_IDX feat1, FEAT_IDX feat2, FEAT_IDX feat3,
181 BIT_FLAGS info1, BIT_FLAGS info2, BIT_FLAGS info3)
183 floor_type *floor_ptr = player_ptr->current_floor_ptr;
184 if (floor_ptr->grid_array[y][x].info & CAVE_ICKY)
187 floor_ptr->grid_array[y][x].info |= (CAVE_ICKY);
188 if (floor_ptr->grid_array[y][x].feat <= c1) {
189 if (randint1(100) < 75) {
190 floor_ptr->grid_array[y][x].feat = feat1;
191 floor_ptr->grid_array[y][x].info &= ~(CAVE_MASK);
192 floor_ptr->grid_array[y][x].info |= info1;
195 floor_ptr->grid_array[y][x].feat = feat2;
196 floor_ptr->grid_array[y][x].info &= ~(CAVE_MASK);
197 floor_ptr->grid_array[y][x].info |= info2;
202 if (floor_ptr->grid_array[y][x].feat <= c2) {
203 if (randint1(100) < 75) {
204 floor_ptr->grid_array[y][x].feat = feat2;
205 floor_ptr->grid_array[y][x].info &= ~(CAVE_MASK);
206 floor_ptr->grid_array[y][x].info |= info2;
209 floor_ptr->grid_array[y][x].feat = feat1;
210 floor_ptr->grid_array[y][x].info &= ~(CAVE_MASK);
211 floor_ptr->grid_array[y][x].info |= info1;
216 if (floor_ptr->grid_array[y][x].feat <= c3) {
217 floor_ptr->grid_array[y][x].feat = feat3;
218 floor_ptr->grid_array[y][x].info &= ~(CAVE_MASK);
219 floor_ptr->grid_array[y][x].info |= info3;
223 place_bold(player_ptr, y, x, GB_OUTER);
228 * Quick and nasty fill routine used to find the connected region
229 * of floor in the middle of the grids
231 static void cave_fill(player_type *player_ptr, const POSITION y, const POSITION x)
233 floor_type *floor_ptr = player_ptr->current_floor_ptr;
236 std::queue<Pos2D> que;
239 while (!que.empty()) {
240 const auto [y_cur, x_cur] = que.front();
243 for (int d = 0; d < 8; d++) {
244 int y_to = y_cur + ddy_ddd[d];
245 int x_to = x_cur + ddx_ddd[d];
246 if (!in_bounds(floor_ptr, y_to, x_to)) {
247 floor_ptr->grid_array[y_to][x_to].info |= CAVE_ICKY;
251 if ((x_to <= fill_data.xmin) || (x_to >= fill_data.xmax) || (y_to <= fill_data.ymin) || (y_to >= fill_data.ymax)) {
252 floor_ptr->grid_array[y_to][x_to].info |= CAVE_ICKY;
256 if (!hack_isnt_wall(player_ptr, y_to, x_to, fill_data.c1, fill_data.c2, fill_data.c3, fill_data.feat1, fill_data.feat2, fill_data.feat3,
257 fill_data.info1, fill_data.info2, fill_data.info3))
260 que.emplace(y_to, x_to);
262 (fill_data.amount)++;
267 bool generate_fracave(player_type *player_ptr, POSITION y0, POSITION x0, POSITION xsize, POSITION ysize, int cutoff, bool light, bool room)
269 POSITION xhsize = xsize / 2;
270 POSITION yhsize = ysize / 2;
271 fill_data.c1 = cutoff;
274 fill_data.feat1 = feat_ground_type[randint0(100)];
275 fill_data.feat2 = feat_ground_type[randint0(100)];
276 fill_data.feat3 = feat_ground_type[randint0(100)];
277 fill_data.info1 = CAVE_FLOOR;
278 fill_data.info2 = CAVE_FLOOR;
279 fill_data.info3 = CAVE_FLOOR;
280 fill_data.amount = 0;
281 floor_type *floor_ptr = player_ptr->current_floor_ptr;
282 cave_fill(player_ptr, (byte)y0, (byte)x0);
283 if (fill_data.amount < 10) {
284 for (POSITION x = 0; x <= xsize; ++x) {
285 for (POSITION y = 0; y <= ysize; ++y) {
286 place_bold(player_ptr, y0 + y - yhsize, x0 + x - xhsize, GB_EXTRA);
287 floor_ptr->grid_array[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY | CAVE_ROOM);
294 for (int i = 0; i <= xsize; ++i) {
295 auto *g_ptr1 = &floor_ptr->grid_array[y0 - yhsize][i + x0 - xhsize];
296 if (g_ptr1->is_icky() && (room)) {
297 place_bold(player_ptr, y0 - yhsize, x0 + i - xhsize, GB_OUTER);
299 floor_ptr->grid_array[y0 - yhsize][x0 + i - xhsize].info |= (CAVE_GLOW);
301 g_ptr1->info |= (CAVE_ROOM);
302 place_bold(player_ptr, y0 - yhsize, x0 + i - xhsize, GB_OUTER);
304 place_bold(player_ptr, y0 - yhsize, x0 + i - xhsize, GB_EXTRA);
307 auto *g_ptr2 = &floor_ptr->grid_array[ysize + y0 - yhsize][i + x0 - xhsize];
308 if (g_ptr2->is_icky() && (room)) {
309 place_bold(player_ptr, y0 + ysize - yhsize, x0 + i - xhsize, GB_OUTER);
311 g_ptr2->info |= (CAVE_GLOW);
313 g_ptr2->info |= (CAVE_ROOM);
314 place_bold(player_ptr, y0 + ysize - yhsize, x0 + i - xhsize, GB_OUTER);
316 place_bold(player_ptr, y0 + ysize - yhsize, x0 + i - xhsize, GB_EXTRA);
319 g_ptr1->info &= ~(CAVE_ICKY);
320 g_ptr2->info &= ~(CAVE_ICKY);
323 for (int i = 1; i < ysize; ++i) {
324 auto *g_ptr1 = &floor_ptr->grid_array[i + y0 - yhsize][x0 - xhsize];
325 if (g_ptr1->is_icky() && room) {
326 place_bold(player_ptr, y0 + i - yhsize, x0 - xhsize, GB_OUTER);
328 g_ptr1->info |= (CAVE_GLOW);
330 g_ptr1->info |= (CAVE_ROOM);
331 place_bold(player_ptr, y0 + i - yhsize, x0 - xhsize, GB_OUTER);
333 place_bold(player_ptr, y0 + i - yhsize, x0 - xhsize, GB_EXTRA);
336 auto *g_ptr2 = &floor_ptr->grid_array[i + y0 - yhsize][xsize + x0 - xhsize];
337 if (g_ptr2->is_icky() && room) {
338 place_bold(player_ptr, y0 + i - yhsize, x0 + xsize - xhsize, GB_OUTER);
340 g_ptr2->info |= (CAVE_GLOW);
342 g_ptr2->info |= (CAVE_ROOM);
343 place_bold(player_ptr, y0 + i - yhsize, x0 + xsize - xhsize, GB_OUTER);
345 place_bold(player_ptr, y0 + i - yhsize, x0 + xsize - xhsize, GB_EXTRA);
348 g_ptr1->info &= ~(CAVE_ICKY);
349 g_ptr2->info &= ~(CAVE_ICKY);
352 for (POSITION x = 1; x < xsize; ++x) {
353 for (POSITION y = 1; y < ysize; ++y) {
354 auto *g_ptr1 = &floor_ptr->grid_array[y0 + y - yhsize][x0 + x - xhsize];
355 if (g_ptr1->is_floor() && g_ptr1->is_icky()) {
356 g_ptr1->info &= ~CAVE_ICKY;
358 g_ptr1->info |= (CAVE_GLOW);
361 g_ptr1->info |= (CAVE_ROOM);
366 auto *g_ptr2 = &floor_ptr->grid_array[y0 + y - yhsize][x0 + x - xhsize];
367 if (g_ptr2->is_outer() && g_ptr2->is_icky()) {
368 g_ptr2->info &= ~(CAVE_ICKY);
370 g_ptr2->info |= (CAVE_GLOW);
373 g_ptr2->info |= (CAVE_ROOM);
375 place_bold(player_ptr, y0 + y - yhsize, x0 + x - xhsize, GB_EXTRA);
376 g_ptr2->info &= ~(CAVE_ROOM);
382 place_bold(player_ptr, y0 + y - yhsize, x0 + x - xhsize, GB_EXTRA);
383 g_ptr2->info &= ~(CAVE_ICKY | CAVE_ROOM);
390 bool generate_lake(player_type *player_ptr, POSITION y0, POSITION x0, POSITION xsize, POSITION ysize, int c1, int c2, int c3, int type)
392 FEAT_IDX feat1, feat2, feat3;
393 POSITION xhsize = xsize / 2;
394 POSITION yhsize = ysize / 2;
396 case LAKE_T_LAVA: /* Lava */
397 feat1 = feat_deep_lava;
398 feat2 = feat_shallow_lava;
399 feat3 = feat_ground_type[randint0(100)];
401 case LAKE_T_WATER: /* Water */
402 feat1 = feat_deep_water;
403 feat2 = feat_shallow_water;
404 feat3 = feat_ground_type[randint0(100)];
406 case LAKE_T_CAVE: /* Collapsed floor_ptr->grid_array */
407 feat1 = feat_ground_type[randint0(100)];
408 feat2 = feat_ground_type[randint0(100)];
411 case LAKE_T_EARTH_VAULT: /* Earth vault */
413 feat2 = feat_ground_type[randint0(100)];
416 case LAKE_T_AIR_VAULT: /* Air vault */
421 case LAKE_T_WATER_VAULT: /* Water vault */
422 feat1 = feat_shallow_water;
423 feat2 = feat_deep_water;
424 feat3 = feat_shallow_water;
426 case LAKE_T_FIRE_VAULT: /* Fire Vault */
427 feat1 = feat_shallow_lava;
428 feat2 = feat_deep_lava;
429 feat3 = feat_shallow_lava;
438 fill_data.feat1 = feat1;
439 fill_data.feat2 = feat2;
440 fill_data.feat3 = feat3;
444 fill_data.amount = 0;
446 floor_type *floor_ptr = player_ptr->current_floor_ptr;
447 cave_fill(player_ptr, (byte)y0, (byte)x0);
448 if (fill_data.amount < 10) {
449 for (POSITION x = 0; x <= xsize; ++x) {
450 for (POSITION y = 0; y <= ysize; ++y) {
451 place_bold(player_ptr, y0 + y - yhsize, x0 + x - xhsize, GB_FLOOR);
452 floor_ptr->grid_array[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY);
459 for (int i = 0; i <= xsize; ++i) {
460 place_bold(player_ptr, y0 + 0 - yhsize, x0 + i - xhsize, GB_EXTRA);
461 place_bold(player_ptr, y0 + ysize - yhsize, x0 + i - xhsize, GB_EXTRA);
462 floor_ptr->grid_array[y0 - yhsize][x0 + i - xhsize].info &= ~(CAVE_ICKY);
463 floor_ptr->grid_array[y0 + ysize - yhsize][x0 + i - xhsize].info &= ~(CAVE_ICKY);
466 for (int i = 1; i < ysize; ++i) {
467 place_bold(player_ptr, y0 + i - yhsize, x0 - xhsize, GB_EXTRA);
468 place_bold(player_ptr, y0 + i - yhsize, x0 + xsize - xhsize, GB_EXTRA);
469 floor_ptr->grid_array[y0 + i - yhsize][x0 - xhsize].info &= ~(CAVE_ICKY);
470 floor_ptr->grid_array[y0 + i - yhsize][x0 + xsize - xhsize].info &= ~(CAVE_ICKY);
473 for (POSITION x = 1; x < xsize; ++x) {
474 for (POSITION y = 1; y < ysize; ++y) {
475 auto *g_ptr = &floor_ptr->grid_array[y0 + y - yhsize][x0 + x - xhsize];
476 if (!g_ptr->is_icky() || g_ptr->is_outer())
477 place_bold(player_ptr, y0 + y - yhsize, x0 + x - xhsize, GB_EXTRA);
479 floor_ptr->grid_array[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY | CAVE_ROOM);
480 if (cave_has_flag_bold(floor_ptr, y0 + y - yhsize, x0 + x - xhsize, FF::LAVA)) {
481 if (d_info[floor_ptr->dungeon_idx].flags.has_not(DungeonFeatureType::DARKNESS))
482 floor_ptr->grid_array[y0 + y - yhsize][x0 + x - xhsize].info |= CAVE_GLOW;