2 * @brief fill_data_type構造体を使ってダンジョンを生成/構成する処理
7 #include "room/cave-filler.h"
8 #include "dungeon/dungeon-flag-types.h"
9 #include "floor//geometry.h"
10 #include "floor/cave.h"
11 #include "grid/feature.h"
12 #include "grid/grid.h"
13 #include "room/lake-types.h"
14 #include "system/dungeon-info.h"
15 #include "system/floor-type-definition.h"
16 #include "system/grid-type-definition.h"
17 #include "system/player-type-definition.h"
18 #include "system/terrain-type-definition.h"
19 #include "util/point-2d.h"
22 struct fill_data_type {
33 /* features to fill with */
42 /* number of filled squares */
46 static fill_data_type fill_data;
49 * Store routine for the fractal floor generator
50 * this routine probably should be an inline function or a macro.
52 static void store_height(FloorType *floor_ptr, POSITION x, POSITION y, FEAT_IDX val)
54 if (((x == fill_data.xmin) || (y == fill_data.ymin) || (x == fill_data.xmax) || (y == fill_data.ymax)) && (val <= fill_data.c1)) {
55 val = fill_data.c1 + 1;
58 floor_ptr->grid_array[y][x].feat = val;
62 void generate_hmap(FloorType *floor_ptr, POSITION y0, POSITION x0, POSITION xsiz, POSITION ysiz, int grd, int roug, int cutoff)
64 POSITION xsize = xsiz;
65 POSITION ysize = ysiz;
83 POSITION xhsize = xsize / 2;
84 POSITION yhsize = ysize / 2;
88 fill_data.xmin = x0 - xhsize;
89 fill_data.ymin = y0 - yhsize;
90 fill_data.xmax = x0 + xhsize;
91 fill_data.ymax = y0 + yhsize;
92 fill_data.c1 = cutoff;
93 POSITION diagsize = 362;
94 POSITION maxsize = (xsize > ysize) ? xsize : ysize;
95 for (POSITION i = 0; i <= xsize; i++) {
96 for (POSITION j = 0; j <= ysize; j++) {
97 floor_ptr->grid_array[(int)(fill_data.ymin + j)][(int)(fill_data.xmin + i)].feat = -1;
98 floor_ptr->grid_array[(int)(fill_data.ymin + j)][(int)(fill_data.xmin + i)].info &= ~(CAVE_ICKY);
102 floor_ptr->grid_array[fill_data.ymin][fill_data.xmin].feat = (int16_t)maxsize;
103 floor_ptr->grid_array[fill_data.ymax][fill_data.xmin].feat = (int16_t)maxsize;
104 floor_ptr->grid_array[fill_data.ymin][fill_data.xmax].feat = (int16_t)maxsize;
105 floor_ptr->grid_array[fill_data.ymax][fill_data.xmax].feat = (int16_t)maxsize;
106 floor_ptr->grid_array[y0][x0].feat = 0;
107 POSITION xstep = xsize * 256;
108 POSITION xhstep = xsize * 256;
109 POSITION ystep = ysize * 256;
110 POSITION yhstep = ysize * 256;
111 POSITION xxsize = xsize * 256;
112 POSITION yysize = ysize * 256;
113 while ((xhstep > 256) || (yhstep > 256)) {
118 POSITION xstep2 = xstep / 256;
119 POSITION ystep2 = ystep / 256;
120 POSITION xhstep2 = xhstep / 256;
121 POSITION yhstep2 = yhstep / 256;
122 for (POSITION i = xhstep; i <= xxsize - xhstep; i += xstep) {
123 for (POSITION j = 0; j <= yysize; j += ystep) {
124 POSITION ii = i / 256 + fill_data.xmin;
125 POSITION jj = j / 256 + fill_data.ymin;
126 if (floor_ptr->grid_array[jj][ii].feat != -1) {
131 store_height(floor_ptr, ii, jj, randint1(maxsize));
135 store_height(floor_ptr, ii, jj,
136 (floor_ptr->grid_array[jj][fill_data.xmin + (i - xhstep) / 256].feat + floor_ptr->grid_array[jj][fill_data.xmin + (i + xhstep) / 256].feat) / 2 + (randint1(xstep2) - xhstep2) * roug / 16);
140 for (POSITION j = yhstep; j <= yysize - yhstep; j += ystep) {
141 for (POSITION i = 0; i <= xxsize; i += xstep) {
142 POSITION ii = i / 256 + fill_data.xmin;
143 POSITION jj = j / 256 + fill_data.ymin;
144 if (floor_ptr->grid_array[jj][ii].feat != -1) {
149 store_height(floor_ptr, ii, jj, randint1(maxsize));
153 store_height(floor_ptr, ii, jj,
154 (floor_ptr->grid_array[fill_data.ymin + (j - yhstep) / 256][ii].feat + floor_ptr->grid_array[fill_data.ymin + (j + yhstep) / 256][ii].feat) / 2 + (randint1(ystep2) - yhstep2) * roug / 16);
158 for (POSITION i = xhstep; i <= xxsize - xhstep; i += xstep) {
159 for (POSITION j = yhstep; j <= yysize - yhstep; j += ystep) {
160 POSITION ii = i / 256 + fill_data.xmin;
161 POSITION jj = j / 256 + fill_data.ymin;
162 if (floor_ptr->grid_array[jj][ii].feat != -1) {
167 store_height(floor_ptr, ii, jj, randint1(maxsize));
171 POSITION xm = fill_data.xmin + (i - xhstep) / 256;
172 POSITION xp = fill_data.xmin + (i + xhstep) / 256;
173 POSITION ym = fill_data.ymin + (j - yhstep) / 256;
174 POSITION yp = fill_data.ymin + (j + yhstep) / 256;
175 store_height(floor_ptr, ii, jj,
176 (floor_ptr->grid_array[ym][xm].feat + floor_ptr->grid_array[yp][xm].feat + floor_ptr->grid_array[ym][xp].feat + floor_ptr->grid_array[yp][xp].feat) / 4 + (randint1(xstep2) - xhstep2) * (diagsize / 16) / 256 * roug);
182 static bool hack_isnt_wall(PlayerType *player_ptr, POSITION y, POSITION x, int c1, int c2, int c3, FEAT_IDX feat1, FEAT_IDX feat2, FEAT_IDX feat3,
183 BIT_FLAGS info1, BIT_FLAGS info2, BIT_FLAGS info3)
185 auto *floor_ptr = player_ptr->current_floor_ptr;
186 if (floor_ptr->grid_array[y][x].info & CAVE_ICKY) {
190 floor_ptr->grid_array[y][x].info |= (CAVE_ICKY);
191 if (floor_ptr->grid_array[y][x].feat <= c1) {
192 if (randint1(100) < 75) {
193 floor_ptr->grid_array[y][x].feat = feat1;
194 floor_ptr->grid_array[y][x].info &= ~(CAVE_MASK);
195 floor_ptr->grid_array[y][x].info |= info1;
198 floor_ptr->grid_array[y][x].feat = feat2;
199 floor_ptr->grid_array[y][x].info &= ~(CAVE_MASK);
200 floor_ptr->grid_array[y][x].info |= info2;
205 if (floor_ptr->grid_array[y][x].feat <= c2) {
206 if (randint1(100) < 75) {
207 floor_ptr->grid_array[y][x].feat = feat2;
208 floor_ptr->grid_array[y][x].info &= ~(CAVE_MASK);
209 floor_ptr->grid_array[y][x].info |= info2;
212 floor_ptr->grid_array[y][x].feat = feat1;
213 floor_ptr->grid_array[y][x].info &= ~(CAVE_MASK);
214 floor_ptr->grid_array[y][x].info |= info1;
219 if (floor_ptr->grid_array[y][x].feat <= c3) {
220 floor_ptr->grid_array[y][x].feat = feat3;
221 floor_ptr->grid_array[y][x].info &= ~(CAVE_MASK);
222 floor_ptr->grid_array[y][x].info |= info3;
226 place_bold(player_ptr, y, x, GB_OUTER);
231 * Quick and nasty fill routine used to find the connected region
232 * of floor in the middle of the grids
234 static void cave_fill(PlayerType *player_ptr, const POSITION y, const POSITION x)
236 auto *floor_ptr = player_ptr->current_floor_ptr;
239 std::queue<Pos2D> que;
242 while (!que.empty()) {
243 const auto [y_cur, x_cur] = que.front();
246 for (int d = 0; d < 8; d++) {
247 int y_to = y_cur + ddy_ddd[d];
248 int x_to = x_cur + ddx_ddd[d];
249 if (!in_bounds(floor_ptr, y_to, x_to)) {
250 floor_ptr->grid_array[y_to][x_to].info |= CAVE_ICKY;
254 if ((x_to <= fill_data.xmin) || (x_to >= fill_data.xmax) || (y_to <= fill_data.ymin) || (y_to >= fill_data.ymax)) {
255 floor_ptr->grid_array[y_to][x_to].info |= CAVE_ICKY;
259 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,
260 fill_data.info1, fill_data.info2, fill_data.info3)) {
264 que.emplace(y_to, x_to);
266 (fill_data.amount)++;
271 bool generate_fracave(PlayerType *player_ptr, POSITION y0, POSITION x0, POSITION xsize, POSITION ysize, int cutoff, bool light, bool room)
273 POSITION xhsize = xsize / 2;
274 POSITION yhsize = ysize / 2;
275 fill_data.c1 = cutoff;
278 fill_data.feat1 = rand_choice(feat_ground_type);
279 fill_data.feat2 = rand_choice(feat_ground_type);
280 fill_data.feat3 = rand_choice(feat_ground_type);
281 fill_data.info1 = CAVE_FLOOR;
282 fill_data.info2 = CAVE_FLOOR;
283 fill_data.info3 = CAVE_FLOOR;
284 fill_data.amount = 0;
285 auto *floor_ptr = player_ptr->current_floor_ptr;
286 cave_fill(player_ptr, (byte)y0, (byte)x0);
287 if (fill_data.amount < 10) {
288 for (POSITION x = 0; x <= xsize; ++x) {
289 for (POSITION y = 0; y <= ysize; ++y) {
290 place_bold(player_ptr, y0 + y - yhsize, x0 + x - xhsize, GB_EXTRA);
291 floor_ptr->grid_array[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY | CAVE_ROOM);
298 for (int i = 0; i <= xsize; ++i) {
299 auto *g_ptr1 = &floor_ptr->grid_array[y0 - yhsize][i + x0 - xhsize];
300 if (g_ptr1->is_icky() && (room)) {
301 place_bold(player_ptr, y0 - yhsize, x0 + i - xhsize, GB_OUTER);
303 floor_ptr->grid_array[y0 - yhsize][x0 + i - xhsize].info |= (CAVE_GLOW);
306 g_ptr1->info |= (CAVE_ROOM);
307 place_bold(player_ptr, y0 - yhsize, x0 + i - xhsize, GB_OUTER);
309 place_bold(player_ptr, y0 - yhsize, x0 + i - xhsize, GB_EXTRA);
312 auto *g_ptr2 = &floor_ptr->grid_array[ysize + y0 - yhsize][i + x0 - xhsize];
313 if (g_ptr2->is_icky() && (room)) {
314 place_bold(player_ptr, y0 + ysize - yhsize, x0 + i - xhsize, GB_OUTER);
316 g_ptr2->info |= (CAVE_GLOW);
319 g_ptr2->info |= (CAVE_ROOM);
320 place_bold(player_ptr, y0 + ysize - yhsize, x0 + i - xhsize, GB_OUTER);
322 place_bold(player_ptr, y0 + ysize - yhsize, x0 + i - xhsize, GB_EXTRA);
325 g_ptr1->info &= ~(CAVE_ICKY);
326 g_ptr2->info &= ~(CAVE_ICKY);
329 for (int i = 1; i < ysize; ++i) {
330 auto *g_ptr1 = &floor_ptr->grid_array[i + y0 - yhsize][x0 - xhsize];
331 if (g_ptr1->is_icky() && room) {
332 place_bold(player_ptr, y0 + i - yhsize, x0 - xhsize, GB_OUTER);
334 g_ptr1->info |= (CAVE_GLOW);
337 g_ptr1->info |= (CAVE_ROOM);
338 place_bold(player_ptr, y0 + i - yhsize, x0 - xhsize, GB_OUTER);
340 place_bold(player_ptr, y0 + i - yhsize, x0 - xhsize, GB_EXTRA);
343 auto *g_ptr2 = &floor_ptr->grid_array[i + y0 - yhsize][xsize + x0 - xhsize];
344 if (g_ptr2->is_icky() && room) {
345 place_bold(player_ptr, y0 + i - yhsize, x0 + xsize - xhsize, GB_OUTER);
347 g_ptr2->info |= (CAVE_GLOW);
350 g_ptr2->info |= (CAVE_ROOM);
351 place_bold(player_ptr, y0 + i - yhsize, x0 + xsize - xhsize, GB_OUTER);
353 place_bold(player_ptr, y0 + i - yhsize, x0 + xsize - xhsize, GB_EXTRA);
356 g_ptr1->info &= ~(CAVE_ICKY);
357 g_ptr2->info &= ~(CAVE_ICKY);
360 for (POSITION x = 1; x < xsize; ++x) {
361 for (POSITION y = 1; y < ysize; ++y) {
362 auto *g_ptr1 = &floor_ptr->grid_array[y0 + y - yhsize][x0 + x - xhsize];
363 if (g_ptr1->is_floor() && g_ptr1->is_icky()) {
364 g_ptr1->info &= ~CAVE_ICKY;
366 g_ptr1->info |= (CAVE_GLOW);
370 g_ptr1->info |= (CAVE_ROOM);
376 auto *g_ptr2 = &floor_ptr->grid_array[y0 + y - yhsize][x0 + x - xhsize];
377 if (g_ptr2->is_outer() && g_ptr2->is_icky()) {
378 g_ptr2->info &= ~(CAVE_ICKY);
380 g_ptr2->info |= (CAVE_GLOW);
384 g_ptr2->info |= (CAVE_ROOM);
386 place_bold(player_ptr, y0 + y - yhsize, x0 + x - xhsize, GB_EXTRA);
387 g_ptr2->info &= ~(CAVE_ROOM);
393 place_bold(player_ptr, y0 + y - yhsize, x0 + x - xhsize, GB_EXTRA);
394 g_ptr2->info &= ~(CAVE_ICKY | CAVE_ROOM);
401 bool generate_lake(PlayerType *player_ptr, POSITION y0, POSITION x0, POSITION xsize, POSITION ysize, int c1, int c2, int c3, int type)
403 FEAT_IDX feat1, feat2, feat3;
404 POSITION xhsize = xsize / 2;
405 POSITION yhsize = ysize / 2;
407 case LAKE_T_LAVA: /* Lava */
408 feat1 = feat_deep_lava;
409 feat2 = feat_shallow_lava;
410 feat3 = rand_choice(feat_ground_type);
412 case LAKE_T_WATER: /* Water */
413 feat1 = feat_deep_water;
414 feat2 = feat_shallow_water;
415 feat3 = rand_choice(feat_ground_type);
417 case LAKE_T_CAVE: /* Collapsed floor_ptr->grid_array */
418 feat1 = rand_choice(feat_ground_type);
419 feat2 = rand_choice(feat_ground_type);
422 case LAKE_T_EARTH_VAULT: /* Earth vault */
424 feat2 = rand_choice(feat_ground_type);
427 case LAKE_T_AIR_VAULT: /* Air vault */
432 case LAKE_T_WATER_VAULT: /* Water vault */
433 feat1 = feat_shallow_water;
434 feat2 = feat_deep_water;
435 feat3 = feat_shallow_water;
437 case LAKE_T_FIRE_VAULT: /* Fire Vault */
438 feat1 = feat_shallow_lava;
439 feat2 = feat_deep_lava;
440 feat3 = feat_shallow_lava;
449 fill_data.feat1 = feat1;
450 fill_data.feat2 = feat2;
451 fill_data.feat3 = feat3;
455 fill_data.amount = 0;
457 auto *floor_ptr = player_ptr->current_floor_ptr;
458 cave_fill(player_ptr, (byte)y0, (byte)x0);
459 if (fill_data.amount < 10) {
460 for (POSITION x = 0; x <= xsize; ++x) {
461 for (POSITION y = 0; y <= ysize; ++y) {
462 place_bold(player_ptr, y0 + y - yhsize, x0 + x - xhsize, GB_FLOOR);
463 floor_ptr->grid_array[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY);
470 for (int i = 0; i <= xsize; ++i) {
471 place_bold(player_ptr, y0 + 0 - yhsize, x0 + i - xhsize, GB_EXTRA);
472 place_bold(player_ptr, y0 + ysize - yhsize, x0 + i - xhsize, GB_EXTRA);
473 floor_ptr->grid_array[y0 - yhsize][x0 + i - xhsize].info &= ~(CAVE_ICKY);
474 floor_ptr->grid_array[y0 + ysize - yhsize][x0 + i - xhsize].info &= ~(CAVE_ICKY);
477 for (int i = 1; i < ysize; ++i) {
478 place_bold(player_ptr, y0 + i - yhsize, x0 - xhsize, GB_EXTRA);
479 place_bold(player_ptr, y0 + i - yhsize, x0 + xsize - xhsize, GB_EXTRA);
480 floor_ptr->grid_array[y0 + i - yhsize][x0 - xhsize].info &= ~(CAVE_ICKY);
481 floor_ptr->grid_array[y0 + i - yhsize][x0 + xsize - xhsize].info &= ~(CAVE_ICKY);
484 for (POSITION x = 1; x < xsize; ++x) {
485 for (POSITION y = 1; y < ysize; ++y) {
486 auto *g_ptr = &floor_ptr->grid_array[y0 + y - yhsize][x0 + x - xhsize];
487 if (!g_ptr->is_icky() || g_ptr->is_outer()) {
488 place_bold(player_ptr, y0 + y - yhsize, x0 + x - xhsize, GB_EXTRA);
491 floor_ptr->grid_array[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY | CAVE_ROOM);
492 if (cave_has_flag_bold(floor_ptr, y0 + y - yhsize, x0 + x - xhsize, TerrainCharacteristics::LAVA)) {
493 if (floor_ptr->get_dungeon_definition().flags.has_not(DungeonFeatureType::DARKNESS)) {
494 floor_ptr->grid_array[y0 + y - yhsize][x0 + x - xhsize].info |= CAVE_GLOW;