OSDN Git Service

94daf214f7c039fc75ed85f4e768df1ecbb3df5c
[hengbandforosx/hengbandosx.git] / src / room / cave-filler.cpp
1 /*!
2  * @brief fill_data_type構造体を使ってダンジョンを生成/構成する処理
3  * @date 2020/07/24
4  * @author Hourier
5  */
6
7 #include "room/cave-filler.h"
8 #include "dungeon/dungeon-flag-types.h"
9 #include "dungeon/dungeon.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/floor-type-definition.h"
15
16 typedef struct fill_data_type {
17     POSITION xmin;
18     POSITION ymin;
19     POSITION xmax;
20     POSITION ymax;
21
22     /* cutoffs */
23     int c1;
24     int c2;
25     int c3;
26
27     /* features to fill with */
28     FEAT_IDX feat1;
29     FEAT_IDX feat2;
30     FEAT_IDX feat3;
31
32     int info1;
33     int info2;
34     int info3;
35
36     /* number of filled squares */
37     int amount;
38 } fill_data_type;
39
40 static fill_data_type fill_data;
41
42 /*!
43  * Store routine for the fractal floor generator
44  * this routine probably should be an inline function or a macro.
45  */
46 static void store_height(floor_type *floor_ptr, POSITION x, POSITION y, FEAT_IDX val)
47 {
48     if (((x == fill_data.xmin) || (y == fill_data.ymin) || (x == fill_data.xmax) || (y == fill_data.ymax)) && (val <= fill_data.c1))
49         val = fill_data.c1 + 1;
50
51     floor_ptr->grid_array[y][x].feat = val;
52     return;
53 }
54
55 void generate_hmap(floor_type *floor_ptr, POSITION y0, POSITION x0, POSITION xsiz, POSITION ysiz, int grd, int roug, int cutoff)
56 {
57     POSITION xsize = xsiz;
58     POSITION ysize = ysiz;
59
60     if (xsize > 254)
61         xsize = 254;
62
63     if (xsize < 4)
64         xsize = 4;
65
66     if (ysize > 254)
67         ysize = 254;
68
69     if (ysize < 4)
70         ysize = 4;
71
72     POSITION xhsize = xsize / 2;
73     POSITION yhsize = ysize / 2;
74     xsize = xhsize * 2;
75     ysize = yhsize * 2;
76
77     fill_data.xmin = x0 - xhsize;
78     fill_data.ymin = y0 - yhsize;
79     fill_data.xmax = x0 + xhsize;
80     fill_data.ymax = y0 + yhsize;
81     fill_data.c1 = cutoff;
82     POSITION diagsize = 362;
83     POSITION maxsize = (xsize > ysize) ? xsize : ysize;
84     for (POSITION i = 0; i <= xsize; i++) {
85         for (POSITION j = 0; j <= ysize; j++) {
86             floor_ptr->grid_array[(int)(fill_data.ymin + j)][(int)(fill_data.xmin + i)].feat = -1;
87             floor_ptr->grid_array[(int)(fill_data.ymin + j)][(int)(fill_data.xmin + i)].info &= ~(CAVE_ICKY);
88         }
89     }
90
91     floor_ptr->grid_array[fill_data.ymin][fill_data.xmin].feat = (s16b)maxsize;
92     floor_ptr->grid_array[fill_data.ymax][fill_data.xmin].feat = (s16b)maxsize;
93     floor_ptr->grid_array[fill_data.ymin][fill_data.xmax].feat = (s16b)maxsize;
94     floor_ptr->grid_array[fill_data.ymax][fill_data.xmax].feat = (s16b)maxsize;
95     floor_ptr->grid_array[y0][x0].feat = 0;
96     POSITION xstep = xsize * 256;
97     POSITION xhstep = xsize * 256;
98     POSITION ystep = ysize * 256;
99     POSITION yhstep = ysize * 256;
100     POSITION xxsize = xsize * 256;
101     POSITION yysize = ysize * 256;
102     while ((xhstep > 256) || (yhstep > 256)) {
103         xstep = xhstep;
104         xhstep /= 2;
105         ystep = yhstep;
106         yhstep /= 2;
107         POSITION xstep2 = xstep / 256;
108         POSITION ystep2 = ystep / 256;
109         POSITION xhstep2 = xhstep / 256;
110         POSITION yhstep2 = yhstep / 256;
111         for (POSITION i = xhstep; i <= xxsize - xhstep; i += xstep) {
112             for (POSITION j = 0; j <= yysize; j += ystep) {
113                 POSITION ii = i / 256 + fill_data.xmin;
114                 POSITION jj = j / 256 + fill_data.ymin;
115                 if (floor_ptr->grid_array[jj][ii].feat != -1)
116                     continue;
117
118                 if (xhstep2 > grd) {
119                     store_height(floor_ptr, ii, jj, randint1(maxsize));
120                     continue;
121                 }
122
123                 store_height(floor_ptr, ii, jj,
124                     (floor_ptr->grid_array[jj][fill_data.xmin + (i - xhstep) / 256].feat + floor_ptr->grid_array[jj][fill_data.xmin + (i + xhstep) / 256].feat)
125                             / 2
126                         + (randint1(xstep2) - xhstep2) * roug / 16);
127             }
128         }
129
130         for (POSITION j = yhstep; j <= yysize - yhstep; j += ystep) {
131             for (POSITION i = 0; i <= xxsize; i += xstep) {
132                 POSITION ii = i / 256 + fill_data.xmin;
133                 POSITION jj = j / 256 + fill_data.ymin;
134                 if (floor_ptr->grid_array[jj][ii].feat != -1)
135                     continue;
136
137                 if (xhstep2 > grd) {
138                     store_height(floor_ptr, ii, jj, randint1(maxsize));
139                     continue;
140                 }
141
142                 store_height(floor_ptr, ii, jj,
143                     (floor_ptr->grid_array[fill_data.ymin + (j - yhstep) / 256][ii].feat + floor_ptr->grid_array[fill_data.ymin + (j + yhstep) / 256][ii].feat)
144                             / 2
145                         + (randint1(ystep2) - yhstep2) * roug / 16);
146             }
147         }
148
149         for (POSITION i = xhstep; i <= xxsize - xhstep; i += xstep) {
150             for (POSITION j = yhstep; j <= yysize - yhstep; j += ystep) {
151                 POSITION ii = i / 256 + fill_data.xmin;
152                 POSITION jj = j / 256 + fill_data.ymin;
153                 if (floor_ptr->grid_array[jj][ii].feat != -1)
154                     continue;
155
156                 if (xhstep2 > grd) {
157                     store_height(floor_ptr, ii, jj, randint1(maxsize));
158                     continue;
159                 }
160
161                 POSITION xm = fill_data.xmin + (i - xhstep) / 256;
162                 POSITION xp = fill_data.xmin + (i + xhstep) / 256;
163                 POSITION ym = fill_data.ymin + (j - yhstep) / 256;
164                 POSITION yp = fill_data.ymin + (j + yhstep) / 256;
165                 store_height(floor_ptr, ii, jj,
166                     (floor_ptr->grid_array[ym][xm].feat + floor_ptr->grid_array[yp][xm].feat + floor_ptr->grid_array[ym][xp].feat
167                         + floor_ptr->grid_array[yp][xp].feat)
168                             / 4
169                         + (randint1(xstep2) - xhstep2) * (diagsize / 16) / 256 * roug);
170             }
171         }
172     }
173 }
174
175 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,
176     BIT_FLAGS info1, BIT_FLAGS info2, BIT_FLAGS info3)
177 {
178     floor_type *floor_ptr = player_ptr->current_floor_ptr;
179     if (floor_ptr->grid_array[y][x].info & CAVE_ICKY)
180         return FALSE;
181
182     floor_ptr->grid_array[y][x].info |= (CAVE_ICKY);
183     if (floor_ptr->grid_array[y][x].feat <= c1) {
184         if (randint1(100) < 75) {
185             floor_ptr->grid_array[y][x].feat = feat1;
186             floor_ptr->grid_array[y][x].info &= ~(CAVE_MASK);
187             floor_ptr->grid_array[y][x].info |= info1;
188             return TRUE;
189         } else {
190             floor_ptr->grid_array[y][x].feat = feat2;
191             floor_ptr->grid_array[y][x].info &= ~(CAVE_MASK);
192             floor_ptr->grid_array[y][x].info |= info2;
193             return TRUE;
194         }
195     }
196
197     if (floor_ptr->grid_array[y][x].feat <= c2) {
198         if (randint1(100) < 75) {
199             floor_ptr->grid_array[y][x].feat = feat2;
200             floor_ptr->grid_array[y][x].info &= ~(CAVE_MASK);
201             floor_ptr->grid_array[y][x].info |= info2;
202             return TRUE;
203         } else {
204             floor_ptr->grid_array[y][x].feat = feat1;
205             floor_ptr->grid_array[y][x].info &= ~(CAVE_MASK);
206             floor_ptr->grid_array[y][x].info |= info1;
207             return TRUE;
208         }
209     }
210
211     if (floor_ptr->grid_array[y][x].feat <= c3) {
212         floor_ptr->grid_array[y][x].feat = feat3;
213         floor_ptr->grid_array[y][x].info &= ~(CAVE_MASK);
214         floor_ptr->grid_array[y][x].info |= info3;
215         return TRUE;
216     }
217
218     place_bold(player_ptr, y, x, GB_OUTER);
219     return FALSE;
220 }
221
222 /*
223  * Quick and nasty fill routine used to find the connected region
224  * of floor in the middle of the grids
225  */
226 static void cave_fill(player_type *player_ptr, POSITION y, POSITION x)
227 {
228     int flow_tail_room = 1;
229     int flow_head_room = 0;
230     tmp_pos.y[0] = y;
231     tmp_pos.x[0] = x;
232     floor_type *floor_ptr = player_ptr->current_floor_ptr;
233     while (flow_head_room != flow_tail_room) {
234         POSITION ty = tmp_pos.y[flow_head_room];
235         POSITION tx = tmp_pos.x[flow_head_room];
236         if (++flow_head_room == TEMP_MAX)
237             flow_head_room = 0;
238
239         for (int d = 0; d < 8; d++) {
240             int old_head = flow_tail_room;
241             int j = ty + ddy_ddd[d];
242             int i = tx + ddx_ddd[d];
243             if (!in_bounds(floor_ptr, j, i)) {
244                 floor_ptr->grid_array[j][i].info |= CAVE_ICKY;
245                 continue;
246             }
247
248             if ((i <= fill_data.xmin) || (i >= fill_data.xmax) || (j <= fill_data.ymin) || (j >= fill_data.ymax)) {
249                 floor_ptr->grid_array[j][i].info |= CAVE_ICKY;
250                 continue;
251             }
252
253             if (!hack_isnt_wall(player_ptr, j, i, fill_data.c1, fill_data.c2, fill_data.c3, fill_data.feat1, fill_data.feat2, fill_data.feat3, fill_data.info1,
254                     fill_data.info2, fill_data.info3))
255                 continue;
256
257             tmp_pos.y[flow_tail_room] = (byte)j;
258             tmp_pos.x[flow_tail_room] = (byte)i;
259             if (++flow_tail_room == TEMP_MAX)
260                 flow_tail_room = 0;
261
262             if (flow_tail_room == flow_head_room) {
263                 flow_tail_room = old_head;
264                 continue;
265             }
266
267             (fill_data.amount)++;
268         }
269     }
270 }
271
272 bool generate_fracave(player_type *player_ptr, POSITION y0, POSITION x0, POSITION xsize, POSITION ysize, int cutoff, bool light, bool room)
273 {
274     POSITION xhsize = xsize / 2;
275     POSITION yhsize = ysize / 2;
276     fill_data.c1 = cutoff;
277     fill_data.c2 = 0;
278     fill_data.c3 = 0;
279     fill_data.feat1 = feat_ground_type[randint0(100)];
280     fill_data.feat2 = feat_ground_type[randint0(100)];
281     fill_data.feat3 = feat_ground_type[randint0(100)];
282     fill_data.info1 = CAVE_FLOOR;
283     fill_data.info2 = CAVE_FLOOR;
284     fill_data.info3 = CAVE_FLOOR;
285     fill_data.amount = 0;
286     floor_type *floor_ptr = player_ptr->current_floor_ptr;
287     cave_fill(player_ptr, (byte)y0, (byte)x0);
288     if (fill_data.amount < 10) {
289         for (POSITION x = 0; x <= xsize; ++x) {
290             for (POSITION y = 0; y <= ysize; ++y) {
291                 place_bold(player_ptr, y0 + y - yhsize, x0 + x - xhsize, GB_EXTRA);
292                 floor_ptr->grid_array[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY | CAVE_ROOM);
293             }
294         }
295
296         return FALSE;
297     }
298
299     for (int i = 0; i <= xsize; ++i) {
300         if ((floor_ptr->grid_array[0 + y0 - yhsize][i + x0 - xhsize].info & CAVE_ICKY) && (room)) {
301             place_bold(player_ptr, y0 + 0 - yhsize, x0 + i - xhsize, GB_OUTER);
302             if (light)
303                 floor_ptr->grid_array[y0 + 0 - yhsize][x0 + i - xhsize].info |= (CAVE_GLOW);
304
305             floor_ptr->grid_array[y0 + 0 - yhsize][x0 + i - xhsize].info |= (CAVE_ROOM);
306             place_bold(player_ptr, y0 + 0 - yhsize, x0 + i - xhsize, GB_OUTER);
307         } else {
308             place_bold(player_ptr, y0 + 0 - yhsize, x0 + i - xhsize, GB_EXTRA);
309         }
310
311         if ((floor_ptr->grid_array[ysize + y0 - yhsize][i + x0 - xhsize].info & CAVE_ICKY) && (room)) {
312             place_bold(player_ptr, y0 + ysize - yhsize, x0 + i - xhsize, GB_OUTER);
313             if (light)
314                 floor_ptr->grid_array[y0 + ysize - yhsize][x0 + i - xhsize].info |= (CAVE_GLOW);
315
316             floor_ptr->grid_array[y0 + ysize - yhsize][x0 + i - xhsize].info |= (CAVE_ROOM);
317             place_bold(player_ptr, y0 + ysize - yhsize, x0 + i - xhsize, GB_OUTER);
318         } else {
319             place_bold(player_ptr, y0 + ysize - yhsize, x0 + i - xhsize, GB_EXTRA);
320         }
321
322         floor_ptr->grid_array[y0 + 0 - yhsize][x0 + i - xhsize].info &= ~(CAVE_ICKY);
323         floor_ptr->grid_array[y0 + ysize - yhsize][x0 + i - xhsize].info &= ~(CAVE_ICKY);
324     }
325
326     for (int i = 1; i < ysize; ++i) {
327         if ((floor_ptr->grid_array[i + y0 - yhsize][0 + x0 - xhsize].info & CAVE_ICKY) && room) {
328             place_bold(player_ptr, y0 + i - yhsize, x0 + 0 - xhsize, GB_OUTER);
329             if (light)
330                 floor_ptr->grid_array[y0 + i - yhsize][x0 + 0 - xhsize].info |= (CAVE_GLOW);
331
332             floor_ptr->grid_array[y0 + i - yhsize][x0 + 0 - xhsize].info |= (CAVE_ROOM);
333             place_bold(player_ptr, y0 + i - yhsize, x0 + 0 - xhsize, GB_OUTER);
334         } else {
335             place_bold(player_ptr, y0 + i - yhsize, x0 + 0 - xhsize, GB_EXTRA);
336         }
337
338         if ((floor_ptr->grid_array[i + y0 - yhsize][xsize + x0 - xhsize].info & CAVE_ICKY) && room) {
339             place_bold(player_ptr, y0 + i - yhsize, x0 + xsize - xhsize, GB_OUTER);
340             if (light)
341                 floor_ptr->grid_array[y0 + i - yhsize][x0 + xsize - xhsize].info |= (CAVE_GLOW);
342
343             floor_ptr->grid_array[y0 + i - yhsize][x0 + xsize - xhsize].info |= (CAVE_ROOM);
344             place_bold(player_ptr, y0 + i - yhsize, x0 + xsize - xhsize, GB_OUTER);
345         } else {
346             place_bold(player_ptr, y0 + i - yhsize, x0 + xsize - xhsize, GB_EXTRA);
347         }
348
349         floor_ptr->grid_array[y0 + i - yhsize][x0 + 0 - xhsize].info &= ~(CAVE_ICKY);
350         floor_ptr->grid_array[y0 + i - yhsize][x0 + xsize - xhsize].info &= ~(CAVE_ICKY);
351     }
352
353     for (POSITION x = 1; x < xsize; ++x) {
354         for (POSITION y = 1; y < ysize; ++y) {
355             if (is_floor_bold(floor_ptr, y0 + y - yhsize, x0 + x - xhsize) && (floor_ptr->grid_array[y0 + y - yhsize][x0 + x - xhsize].info & CAVE_ICKY)) {
356                 floor_ptr->grid_array[y0 + y - yhsize][x0 + x - xhsize].info &= ~CAVE_ICKY;
357                 if (light)
358                     floor_ptr->grid_array[y0 + y - yhsize][x0 + x - xhsize].info |= (CAVE_GLOW);
359
360                 if (room)
361                     floor_ptr->grid_array[y0 + y - yhsize][x0 + x - xhsize].info |= (CAVE_ROOM);
362
363                 continue;
364             }
365
366             if (is_outer_bold(floor_ptr, y0 + y - yhsize, x0 + x - xhsize) && (floor_ptr->grid_array[y0 + y - yhsize][x0 + x - xhsize].info & CAVE_ICKY)) {
367                 floor_ptr->grid_array[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY);
368                 if (light)
369                     floor_ptr->grid_array[y0 + y - yhsize][x0 + x - xhsize].info |= (CAVE_GLOW);
370
371                 if (room) {
372                     floor_ptr->grid_array[y0 + y - yhsize][x0 + x - xhsize].info |= (CAVE_ROOM);
373                 } else {
374                     place_bold(player_ptr, y0 + y - yhsize, x0 + x - xhsize, GB_EXTRA);
375                     floor_ptr->grid_array[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ROOM);
376                 }
377
378                 continue;
379             }
380
381             place_bold(player_ptr, y0 + y - yhsize, x0 + x - xhsize, GB_EXTRA);
382             floor_ptr->grid_array[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY | CAVE_ROOM);
383         }
384     }
385
386     return TRUE;
387 }
388
389 bool generate_lake(player_type *player_ptr, POSITION y0, POSITION x0, POSITION xsize, POSITION ysize, int c1, int c2, int c3, int type)
390 {
391     FEAT_IDX feat1, feat2, feat3;
392     POSITION xhsize = xsize / 2;
393     POSITION yhsize = ysize / 2;
394     switch (type) {
395     case LAKE_T_LAVA: /* Lava */
396         feat1 = feat_deep_lava;
397         feat2 = feat_shallow_lava;
398         feat3 = feat_ground_type[randint0(100)];
399         break;
400     case LAKE_T_WATER: /* Water */
401         feat1 = feat_deep_water;
402         feat2 = feat_shallow_water;
403         feat3 = feat_ground_type[randint0(100)];
404         break;
405     case LAKE_T_CAVE: /* Collapsed floor_ptr->grid_array */
406         feat1 = feat_ground_type[randint0(100)];
407         feat2 = feat_ground_type[randint0(100)];
408         feat3 = feat_rubble;
409         break;
410     case LAKE_T_EARTH_VAULT: /* Earth vault */
411         feat1 = feat_rubble;
412         feat2 = feat_ground_type[randint0(100)];
413         feat3 = feat_rubble;
414         break;
415     case LAKE_T_AIR_VAULT: /* Air vault */
416         feat1 = feat_grass;
417         feat2 = feat_tree;
418         feat3 = feat_grass;
419         break;
420     case LAKE_T_WATER_VAULT: /* Water vault */
421         feat1 = feat_shallow_water;
422         feat2 = feat_deep_water;
423         feat3 = feat_shallow_water;
424         break;
425     case LAKE_T_FIRE_VAULT: /* Fire Vault */
426         feat1 = feat_shallow_lava;
427         feat2 = feat_deep_lava;
428         feat3 = feat_shallow_lava;
429         break;
430     default:
431         return FALSE;
432     }
433
434     fill_data.c1 = c1;
435     fill_data.c2 = c2;
436     fill_data.c3 = c3;
437     fill_data.feat1 = feat1;
438     fill_data.feat2 = feat2;
439     fill_data.feat3 = feat3;
440     fill_data.info1 = 0;
441     fill_data.info2 = 0;
442     fill_data.info3 = 0;
443     fill_data.amount = 0;
444
445     floor_type *floor_ptr = player_ptr->current_floor_ptr;
446     cave_fill(player_ptr, (byte)y0, (byte)x0);
447     if (fill_data.amount < 10) {
448         for (POSITION x = 0; x <= xsize; ++x) {
449             for (POSITION y = 0; y <= ysize; ++y) {
450                 place_bold(player_ptr, y0 + y - yhsize, x0 + x - xhsize, GB_FLOOR);
451                 floor_ptr->grid_array[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY);
452             }
453         }
454
455         return FALSE;
456     }
457
458     for (int i = 0; i <= xsize; ++i) {
459         place_bold(player_ptr, y0 + 0 - yhsize, x0 + i - xhsize, GB_EXTRA);
460         place_bold(player_ptr, y0 + ysize - yhsize, x0 + i - xhsize, GB_EXTRA);
461         floor_ptr->grid_array[y0 + 0 - yhsize][x0 + i - xhsize].info &= ~(CAVE_ICKY);
462         floor_ptr->grid_array[y0 + ysize - yhsize][x0 + i - xhsize].info &= ~(CAVE_ICKY);
463     }
464
465     for (int i = 1; i < ysize; ++i) {
466         place_bold(player_ptr, y0 + i - yhsize, x0 + 0 - xhsize, GB_EXTRA);
467         place_bold(player_ptr, y0 + i - yhsize, x0 + xsize - xhsize, GB_EXTRA);
468         floor_ptr->grid_array[y0 + i - yhsize][x0 + 0 - xhsize].info &= ~(CAVE_ICKY);
469         floor_ptr->grid_array[y0 + i - yhsize][x0 + xsize - xhsize].info &= ~(CAVE_ICKY);
470     }
471
472     for (POSITION x = 1; x < xsize; ++x) {
473         for (POSITION y = 1; y < ysize; ++y) {
474             if ((!(floor_ptr->grid_array[y0 + y - yhsize][x0 + x - xhsize].info & CAVE_ICKY)) || is_outer_bold(floor_ptr, y0 + y - yhsize, x0 + x - xhsize))
475                 place_bold(player_ptr, y0 + y - yhsize, x0 + x - xhsize, GB_EXTRA);
476
477             floor_ptr->grid_array[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY | CAVE_ROOM);
478             if (cave_has_flag_bold(floor_ptr, y0 + y - yhsize, x0 + x - xhsize, FF_LAVA)) {
479                 if (!(d_info[floor_ptr->dungeon_idx].flags1 & DF1_DARKNESS))
480                     floor_ptr->grid_array[y0 + y - yhsize][x0 + x - xhsize].info |= CAVE_GLOW;
481             }
482         }
483     }
484
485     return TRUE;
486 }