OSDN Git Service

Merge pull request #3532 from sikabane-works/release/3.0.0.87-alpha
[hengbandforosx/hengbandosx.git] / src / room / rooms-normal.cpp
1 #include "room/rooms-normal.h"
2 #include "dungeon/dungeon-flag-types.h"
3 #include "floor/geometry.h"
4 #include "grid/door.h"
5 #include "grid/grid.h"
6 #include "grid/object-placer.h"
7 #include "grid/stair.h"
8 #include "grid/trap.h"
9 #include "room/door-definition.h"
10 #include "room/rooms-builder.h"
11 #include "room/space-finder.h"
12 #include "room/vault-builder.h"
13 #include "system/dungeon-info.h"
14 #include "system/floor-type-definition.h"
15 #include "system/grid-type-definition.h"
16 #include "system/player-type-definition.h"
17
18 /*!
19  * @brief タイプ1の部屋…通常可変長方形の部屋を生成する / Type 1 -- normal rectangular rooms
20  * @param player_ptr プレイヤーへの参照ポインタ
21  */
22 bool build_type1(PlayerType *player_ptr, dun_data_type *dd_ptr)
23 {
24     POSITION y, x, y2, x2, yval, xval;
25     POSITION y1, x1, xsize, ysize;
26
27     bool light;
28
29     grid_type *g_ptr;
30
31     auto *floor_ptr = player_ptr->current_floor_ptr;
32     const auto &dungeon = floor_ptr->get_dungeon_definition();
33     bool curtain = (dungeon.flags.has(DungeonFeatureType::CURTAIN)) && one_in_(dungeon.flags.has(DungeonFeatureType::NO_CAVE) ? 48 : 512);
34
35     /* Pick a room size */
36     y1 = randint1(4);
37     x1 = randint1(11);
38     y2 = randint1(3);
39     x2 = randint1(11);
40
41     xsize = x1 + x2 + 1;
42     ysize = y1 + y2 + 1;
43
44     /* Find and reserve some space in the dungeon.  Get center of room. */
45     if (!find_space(player_ptr, dd_ptr, &yval, &xval, ysize + 2, xsize + 2)) {
46         /* Limit to the minimum room size, and retry */
47         y1 = 1;
48         x1 = 1;
49         y2 = 1;
50         x2 = 1;
51
52         xsize = x1 + x2 + 1;
53         ysize = y1 + y2 + 1;
54
55         /* Find and reserve some space in the dungeon.  Get center of room. */
56         if (!find_space(player_ptr, dd_ptr, &yval, &xval, ysize + 2, xsize + 2)) {
57             return false;
58         }
59     }
60
61     /* Choose lite or dark */
62     light = ((floor_ptr->dun_level <= randint1(25)) && dungeon.flags.has_not(DungeonFeatureType::DARKNESS));
63
64     /* Get corner values */
65     y1 = yval - ysize / 2;
66     x1 = xval - xsize / 2;
67     y2 = yval + (ysize - 1) / 2;
68     x2 = xval + (xsize - 1) / 2;
69
70     /* Place a full floor under the room */
71     for (y = y1 - 1; y <= y2 + 1; y++) {
72         for (x = x1 - 1; x <= x2 + 1; x++) {
73             g_ptr = &floor_ptr->grid_array[y][x];
74             place_grid(player_ptr, g_ptr, GB_FLOOR);
75             g_ptr->info |= (CAVE_ROOM);
76             if (light) {
77                 g_ptr->info |= (CAVE_GLOW);
78             }
79         }
80     }
81
82     /* Walls around the room */
83     for (y = y1 - 1; y <= y2 + 1; y++) {
84         g_ptr = &floor_ptr->grid_array[y][x1 - 1];
85         place_grid(player_ptr, g_ptr, GB_OUTER);
86         g_ptr = &floor_ptr->grid_array[y][x2 + 1];
87         place_grid(player_ptr, g_ptr, GB_OUTER);
88     }
89     for (x = x1 - 1; x <= x2 + 1; x++) {
90         g_ptr = &floor_ptr->grid_array[y1 - 1][x];
91         place_grid(player_ptr, g_ptr, GB_OUTER);
92         g_ptr = &floor_ptr->grid_array[y2 + 1][x];
93         place_grid(player_ptr, g_ptr, GB_OUTER);
94     }
95
96     /* Hack -- Occasional curtained room */
97     if (curtain && (y2 - y1 > 2) && (x2 - x1 > 2)) {
98         for (y = y1; y <= y2; y++) {
99             g_ptr = &floor_ptr->grid_array[y][x1];
100             g_ptr->feat = feat_door[DOOR_CURTAIN].closed;
101             g_ptr->info &= ~(CAVE_MASK);
102             g_ptr = &floor_ptr->grid_array[y][x2];
103             g_ptr->feat = feat_door[DOOR_CURTAIN].closed;
104             g_ptr->info &= ~(CAVE_MASK);
105         }
106         for (x = x1; x <= x2; x++) {
107             g_ptr = &floor_ptr->grid_array[y1][x];
108             g_ptr->feat = feat_door[DOOR_CURTAIN].closed;
109             g_ptr->info &= ~(CAVE_MASK);
110             g_ptr = &floor_ptr->grid_array[y2][x];
111             g_ptr->feat = feat_door[DOOR_CURTAIN].closed;
112             g_ptr->info &= ~(CAVE_MASK);
113         }
114     }
115
116     /* Hack -- Occasional pillar room */
117     if (one_in_(20)) {
118         for (y = y1; y <= y2; y += 2) {
119             for (x = x1; x <= x2; x += 2) {
120                 g_ptr = &floor_ptr->grid_array[y][x];
121                 place_grid(player_ptr, g_ptr, GB_INNER);
122             }
123         }
124     }
125
126     /* Hack -- Occasional room with four pillars */
127     else if (one_in_(20)) {
128         if ((y1 + 4 < y2) && (x1 + 4 < x2)) {
129             g_ptr = &floor_ptr->grid_array[y1 + 1][x1 + 1];
130             place_grid(player_ptr, g_ptr, GB_INNER);
131
132             g_ptr = &floor_ptr->grid_array[y1 + 1][x2 - 1];
133             place_grid(player_ptr, g_ptr, GB_INNER);
134
135             g_ptr = &floor_ptr->grid_array[y2 - 1][x1 + 1];
136             place_grid(player_ptr, g_ptr, GB_INNER);
137
138             g_ptr = &floor_ptr->grid_array[y2 - 1][x2 - 1];
139             place_grid(player_ptr, g_ptr, GB_INNER);
140         }
141     }
142
143     /* Hack -- Occasional ragged-edge room */
144     else if (one_in_(50)) {
145         for (y = y1 + 2; y <= y2 - 2; y += 2) {
146             g_ptr = &floor_ptr->grid_array[y][x1];
147             place_grid(player_ptr, g_ptr, GB_INNER);
148             g_ptr = &floor_ptr->grid_array[y][x2];
149             place_grid(player_ptr, g_ptr, GB_INNER);
150         }
151         for (x = x1 + 2; x <= x2 - 2; x += 2) {
152             g_ptr = &floor_ptr->grid_array[y1][x];
153             place_grid(player_ptr, g_ptr, GB_INNER);
154             g_ptr = &floor_ptr->grid_array[y2][x];
155             place_grid(player_ptr, g_ptr, GB_INNER);
156         }
157     }
158     /* Hack -- Occasional divided room */
159     else if (one_in_(50)) {
160         bool curtain2 = (dungeon.flags.has(DungeonFeatureType::CURTAIN)) && one_in_(dungeon.flags.has(DungeonFeatureType::NO_CAVE) ? 2 : 128);
161
162         if (randint1(100) < 50) {
163             /* Horizontal wall */
164             for (x = x1; x <= x2; x++) {
165                 place_bold(player_ptr, yval, x, GB_INNER);
166                 if (curtain2) {
167                     floor_ptr->grid_array[yval][x].feat = feat_door[DOOR_CURTAIN].closed;
168                 }
169             }
170
171             /* Prevent edge of wall from being tunneled */
172             place_bold(player_ptr, yval, x1 - 1, GB_SOLID);
173             place_bold(player_ptr, yval, x2 + 1, GB_SOLID);
174         } else {
175             /* Vertical wall */
176             for (y = y1; y <= y2; y++) {
177                 place_bold(player_ptr, y, xval, GB_INNER);
178                 if (curtain2) {
179                     floor_ptr->grid_array[y][xval].feat = feat_door[DOOR_CURTAIN].closed;
180                 }
181             }
182
183             /* Prevent edge of wall from being tunneled */
184             place_bold(player_ptr, y1 - 1, xval, GB_SOLID);
185             place_bold(player_ptr, y2 + 1, xval, GB_SOLID);
186         }
187
188         place_random_door(player_ptr, yval, xval, true);
189         if (curtain2) {
190             floor_ptr->grid_array[yval][xval].feat = feat_door[DOOR_CURTAIN].closed;
191         }
192     }
193
194     return true;
195 }
196
197 /*!
198  * @brief タイプ2の部屋…二重長方形の部屋を生成する / Type 2 -- Overlapping rectangular rooms
199  * @param player_ptr プレイヤーへの参照ポインタ
200  */
201 bool build_type2(PlayerType *player_ptr, dun_data_type *dd_ptr)
202 {
203     POSITION y, x, xval, yval;
204     POSITION y1a, x1a, y2a, x2a;
205     POSITION y1b, x1b, y2b, x2b;
206     bool light;
207     grid_type *g_ptr;
208
209     /* Find and reserve some space in the dungeon.  Get center of room. */
210     auto *floor_ptr = player_ptr->current_floor_ptr;
211     if (!find_space(player_ptr, dd_ptr, &yval, &xval, 11, 25)) {
212         return false;
213     }
214
215     /* Choose lite or dark */
216     light = ((floor_ptr->dun_level <= randint1(25)) && floor_ptr->get_dungeon_definition().flags.has_not(DungeonFeatureType::DARKNESS));
217
218     /* Determine extents of the first room */
219     y1a = yval - randint1(4);
220     y2a = yval + randint1(3);
221     x1a = xval - randint1(11);
222     x2a = xval + randint1(10);
223
224     /* Determine extents of the second room */
225     y1b = yval - randint1(3);
226     y2b = yval + randint1(4);
227     x1b = xval - randint1(10);
228     x2b = xval + randint1(11);
229
230     /* Place a full floor for room "a" */
231     for (y = y1a - 1; y <= y2a + 1; y++) {
232         for (x = x1a - 1; x <= x2a + 1; x++) {
233             g_ptr = &floor_ptr->grid_array[y][x];
234             place_grid(player_ptr, g_ptr, GB_FLOOR);
235             g_ptr->info |= (CAVE_ROOM);
236             if (light) {
237                 g_ptr->info |= (CAVE_GLOW);
238             }
239         }
240     }
241
242     /* Place a full floor for room "b" */
243     for (y = y1b - 1; y <= y2b + 1; y++) {
244         for (x = x1b - 1; x <= x2b + 1; x++) {
245             g_ptr = &floor_ptr->grid_array[y][x];
246             place_grid(player_ptr, g_ptr, GB_FLOOR);
247             g_ptr->info |= (CAVE_ROOM);
248             if (light) {
249                 g_ptr->info |= (CAVE_GLOW);
250             }
251         }
252     }
253
254     /* Place the walls around room "a" */
255     for (y = y1a - 1; y <= y2a + 1; y++) {
256         g_ptr = &floor_ptr->grid_array[y][x1a - 1];
257         place_grid(player_ptr, g_ptr, GB_OUTER);
258         g_ptr = &floor_ptr->grid_array[y][x2a + 1];
259         place_grid(player_ptr, g_ptr, GB_OUTER);
260     }
261     for (x = x1a - 1; x <= x2a + 1; x++) {
262         g_ptr = &floor_ptr->grid_array[y1a - 1][x];
263         place_grid(player_ptr, g_ptr, GB_OUTER);
264         g_ptr = &floor_ptr->grid_array[y2a + 1][x];
265         place_grid(player_ptr, g_ptr, GB_OUTER);
266     }
267
268     /* Place the walls around room "b" */
269     for (y = y1b - 1; y <= y2b + 1; y++) {
270         g_ptr = &floor_ptr->grid_array[y][x1b - 1];
271         place_grid(player_ptr, g_ptr, GB_OUTER);
272         g_ptr = &floor_ptr->grid_array[y][x2b + 1];
273         place_grid(player_ptr, g_ptr, GB_OUTER);
274     }
275     for (x = x1b - 1; x <= x2b + 1; x++) {
276         g_ptr = &floor_ptr->grid_array[y1b - 1][x];
277         place_grid(player_ptr, g_ptr, GB_OUTER);
278         g_ptr = &floor_ptr->grid_array[y2b + 1][x];
279         place_grid(player_ptr, g_ptr, GB_OUTER);
280     }
281
282     /* Replace the floor for room "a" */
283     for (y = y1a; y <= y2a; y++) {
284         for (x = x1a; x <= x2a; x++) {
285             g_ptr = &floor_ptr->grid_array[y][x];
286             place_grid(player_ptr, g_ptr, GB_FLOOR);
287         }
288     }
289
290     /* Replace the floor for room "b" */
291     for (y = y1b; y <= y2b; y++) {
292         for (x = x1b; x <= x2b; x++) {
293             g_ptr = &floor_ptr->grid_array[y][x];
294             place_grid(player_ptr, g_ptr, GB_FLOOR);
295         }
296     }
297
298     return true;
299 }
300
301 /*!
302  * @brief タイプ3の部屋…十字型の部屋を生成する / Type 3 -- Cross shaped rooms
303  * @param player_ptr プレイヤーへの参照ポインタ
304  * @details
305  * Builds a room at a row, column coordinate\n
306  *\n
307  * Room "a" runs north/south, and Room "b" runs east/east\n
308  * So the "central pillar" runs from x1a, y1b to x2a, y2b.\n
309  *\n
310  * Note that currently, the "center" is always 3x3, but I think that\n
311  * the code below will work (with "bounds checking") for 5x5, or even\n
312  * for unsymetric values like 4x3 or 5x3 or 3x4 or 3x5, or even larger.\n
313  */
314 bool build_type3(PlayerType *player_ptr, dun_data_type *dd_ptr)
315 {
316     POSITION y, x, dy, dx, wy, wx;
317     POSITION y1a, x1a, y2a, x2a;
318     POSITION y1b, x1b, y2b, x2b;
319     POSITION yval, xval;
320     bool light;
321     grid_type *g_ptr;
322
323     /* Find and reserve some space in the dungeon.  Get center of room. */
324     auto *floor_ptr = player_ptr->current_floor_ptr;
325     if (!find_space(player_ptr, dd_ptr, &yval, &xval, 11, 25)) {
326         return false;
327     }
328
329     /* Choose lite or dark */
330     const auto &dungeon = floor_ptr->get_dungeon_definition();
331     light = ((floor_ptr->dun_level <= randint1(25)) && dungeon.flags.has_not(DungeonFeatureType::DARKNESS));
332
333     /* For now, always 3x3 */
334     wx = wy = 1;
335
336     /* Pick max vertical size (at most 4) */
337     dy = rand_range(3, 4);
338
339     /* Pick max horizontal size (at most 15) */
340     dx = rand_range(3, 11);
341
342     /* Determine extents of the north/south room */
343     y1a = yval - dy;
344     y2a = yval + dy;
345     x1a = xval - wx;
346     x2a = xval + wx;
347
348     /* Determine extents of the east/west room */
349     y1b = yval - wy;
350     y2b = yval + wy;
351     x1b = xval - dx;
352     x2b = xval + dx;
353
354     /* Place a full floor for room "a" */
355     for (y = y1a - 1; y <= y2a + 1; y++) {
356         for (x = x1a - 1; x <= x2a + 1; x++) {
357             g_ptr = &floor_ptr->grid_array[y][x];
358             place_grid(player_ptr, g_ptr, GB_FLOOR);
359             g_ptr->info |= (CAVE_ROOM);
360             if (light) {
361                 g_ptr->info |= (CAVE_GLOW);
362             }
363         }
364     }
365
366     /* Place a full floor for room "b" */
367     for (y = y1b - 1; y <= y2b + 1; y++) {
368         for (x = x1b - 1; x <= x2b + 1; x++) {
369             g_ptr = &floor_ptr->grid_array[y][x];
370             place_grid(player_ptr, g_ptr, GB_FLOOR);
371             g_ptr->info |= (CAVE_ROOM);
372             if (light) {
373                 g_ptr->info |= (CAVE_GLOW);
374             }
375         }
376     }
377
378     /* Place the walls around room "a" */
379     for (y = y1a - 1; y <= y2a + 1; y++) {
380         g_ptr = &floor_ptr->grid_array[y][x1a - 1];
381         place_grid(player_ptr, g_ptr, GB_OUTER);
382         g_ptr = &floor_ptr->grid_array[y][x2a + 1];
383         place_grid(player_ptr, g_ptr, GB_OUTER);
384     }
385     for (x = x1a - 1; x <= x2a + 1; x++) {
386         g_ptr = &floor_ptr->grid_array[y1a - 1][x];
387         place_grid(player_ptr, g_ptr, GB_OUTER);
388         g_ptr = &floor_ptr->grid_array[y2a + 1][x];
389         place_grid(player_ptr, g_ptr, GB_OUTER);
390     }
391
392     /* Place the walls around room "b" */
393     for (y = y1b - 1; y <= y2b + 1; y++) {
394         g_ptr = &floor_ptr->grid_array[y][x1b - 1];
395         place_grid(player_ptr, g_ptr, GB_OUTER);
396         g_ptr = &floor_ptr->grid_array[y][x2b + 1];
397         place_grid(player_ptr, g_ptr, GB_OUTER);
398     }
399     for (x = x1b - 1; x <= x2b + 1; x++) {
400         g_ptr = &floor_ptr->grid_array[y1b - 1][x];
401         place_grid(player_ptr, g_ptr, GB_OUTER);
402         g_ptr = &floor_ptr->grid_array[y2b + 1][x];
403         place_grid(player_ptr, g_ptr, GB_OUTER);
404     }
405
406     /* Replace the floor for room "a" */
407     for (y = y1a; y <= y2a; y++) {
408         for (x = x1a; x <= x2a; x++) {
409             g_ptr = &floor_ptr->grid_array[y][x];
410             place_grid(player_ptr, g_ptr, GB_FLOOR);
411         }
412     }
413
414     /* Replace the floor for room "b" */
415     for (y = y1b; y <= y2b; y++) {
416         for (x = x1b; x <= x2b; x++) {
417             g_ptr = &floor_ptr->grid_array[y][x];
418             place_grid(player_ptr, g_ptr, GB_FLOOR);
419         }
420     }
421
422     /* Special features (3/4) */
423     switch (randint0(4)) {
424         /* Large solid middle pillar */
425     case 1: {
426         for (y = y1b; y <= y2b; y++) {
427             for (x = x1a; x <= x2a; x++) {
428                 g_ptr = &floor_ptr->grid_array[y][x];
429                 place_grid(player_ptr, g_ptr, GB_INNER);
430             }
431         }
432         break;
433     }
434
435     /* Inner treasure vault */
436     case 2: {
437         /* Build the vault */
438         for (y = y1b; y <= y2b; y++) {
439             g_ptr = &floor_ptr->grid_array[y][x1a];
440             place_grid(player_ptr, g_ptr, GB_INNER);
441             g_ptr = &floor_ptr->grid_array[y][x2a];
442             place_grid(player_ptr, g_ptr, GB_INNER);
443         }
444         for (x = x1a; x <= x2a; x++) {
445             g_ptr = &floor_ptr->grid_array[y1b][x];
446             place_grid(player_ptr, g_ptr, GB_INNER);
447             g_ptr = &floor_ptr->grid_array[y2b][x];
448             place_grid(player_ptr, g_ptr, GB_INNER);
449         }
450
451         /* Place a secret door on the inner room */
452         switch (randint0(4)) {
453         case 0:
454             place_secret_door(player_ptr, y1b, xval, DOOR_DEFAULT);
455             break;
456         case 1:
457             place_secret_door(player_ptr, y2b, xval, DOOR_DEFAULT);
458             break;
459         case 2:
460             place_secret_door(player_ptr, yval, x1a, DOOR_DEFAULT);
461             break;
462         case 3:
463             place_secret_door(player_ptr, yval, x2a, DOOR_DEFAULT);
464             break;
465         }
466
467         /* Place a treasure in the vault */
468         place_object(player_ptr, yval, xval, 0L);
469
470         /* Let's guard the treasure well */
471         vault_monsters(player_ptr, yval, xval, randint0(2) + 3);
472
473         /* Traps naturally */
474         vault_traps(player_ptr, yval, xval, 4, 4, randint0(3) + 2);
475
476         break;
477     }
478
479     /* Something else */
480     case 3: {
481         /* Occasionally pinch the center shut */
482         if (one_in_(3)) {
483             /* Pinch the east/west sides */
484             for (y = y1b; y <= y2b; y++) {
485                 if (y == yval) {
486                     continue;
487                 }
488                 g_ptr = &floor_ptr->grid_array[y][x1a - 1];
489                 place_grid(player_ptr, g_ptr, GB_INNER);
490                 g_ptr = &floor_ptr->grid_array[y][x2a + 1];
491                 place_grid(player_ptr, g_ptr, GB_INNER);
492             }
493
494             /* Pinch the north/south sides */
495             for (x = x1a; x <= x2a; x++) {
496                 if (x == xval) {
497                     continue;
498                 }
499                 g_ptr = &floor_ptr->grid_array[y1b - 1][x];
500                 place_grid(player_ptr, g_ptr, GB_INNER);
501                 g_ptr = &floor_ptr->grid_array[y2b + 1][x];
502                 place_grid(player_ptr, g_ptr, GB_INNER);
503             }
504
505             /* Sometimes shut using secret doors */
506             if (one_in_(3)) {
507                 int door_type = (dungeon.flags.has(DungeonFeatureType::CURTAIN) && one_in_(dungeon.flags.has(DungeonFeatureType::NO_CAVE) ? 16 : 256))
508                                     ? DOOR_CURTAIN
509                                     : (dungeon.flags.has(DungeonFeatureType::GLASS_DOOR) ? DOOR_GLASS_DOOR : DOOR_DOOR);
510
511                 place_secret_door(player_ptr, yval, x1a - 1, door_type);
512                 place_secret_door(player_ptr, yval, x2a + 1, door_type);
513                 place_secret_door(player_ptr, y1b - 1, xval, door_type);
514                 place_secret_door(player_ptr, y2b + 1, xval, door_type);
515             }
516         }
517
518         /* Occasionally put a "plus" in the center */
519         else if (one_in_(3)) {
520             g_ptr = &floor_ptr->grid_array[yval][xval];
521             place_grid(player_ptr, g_ptr, GB_INNER);
522             g_ptr = &floor_ptr->grid_array[y1b][xval];
523             place_grid(player_ptr, g_ptr, GB_INNER);
524             g_ptr = &floor_ptr->grid_array[y2b][xval];
525             place_grid(player_ptr, g_ptr, GB_INNER);
526             g_ptr = &floor_ptr->grid_array[yval][x1a];
527             place_grid(player_ptr, g_ptr, GB_INNER);
528             g_ptr = &floor_ptr->grid_array[yval][x2a];
529             place_grid(player_ptr, g_ptr, GB_INNER);
530         }
531
532         /* Occasionally put a pillar in the center */
533         else if (one_in_(3)) {
534             g_ptr = &floor_ptr->grid_array[yval][xval];
535             place_grid(player_ptr, g_ptr, GB_INNER);
536         }
537
538         break;
539     }
540     }
541
542     return true;
543 }
544
545 /*!
546  * @brief タイプ4の部屋…固定サイズの二重構造部屋を生成する / Type 4 -- Large room with inner features
547  * @param player_ptr プレイヤーへの参照ポインタ
548  * @details
549  * Possible sub-types:\n
550  *      1 - Just an inner room with one door\n
551  *      2 - An inner room within an inner room\n
552  *      3 - An inner room with pillar(s)\n
553  *      4 - Inner room has a maze\n
554  *      5 - A set of four inner rooms\n
555  */
556 bool build_type4(PlayerType *player_ptr, dun_data_type *dd_ptr)
557 {
558     POSITION y, x, y1, x1;
559     POSITION y2, x2, tmp, yval, xval;
560     bool light;
561     grid_type *g_ptr;
562
563     /* Find and reserve some space in the dungeon.  Get center of room. */
564     auto *floor_ptr = player_ptr->current_floor_ptr;
565     const auto &dungeon = floor_ptr->get_dungeon_definition();
566     if (!find_space(player_ptr, dd_ptr, &yval, &xval, 11, 25)) {
567         return false;
568     }
569
570     /* Choose lite or dark */
571     light = ((floor_ptr->dun_level <= randint1(25)) && dungeon.flags.has_not(DungeonFeatureType::DARKNESS));
572
573     /* Large room */
574     y1 = yval - 4;
575     y2 = yval + 4;
576     x1 = xval - 11;
577     x2 = xval + 11;
578
579     /* Place a full floor under the room */
580     for (y = y1 - 1; y <= y2 + 1; y++) {
581         for (x = x1 - 1; x <= x2 + 1; x++) {
582             g_ptr = &floor_ptr->grid_array[y][x];
583             place_grid(player_ptr, g_ptr, GB_FLOOR);
584             g_ptr->info |= (CAVE_ROOM);
585             if (light) {
586                 g_ptr->info |= (CAVE_GLOW);
587             }
588         }
589     }
590
591     /* Outer Walls */
592     for (y = y1 - 1; y <= y2 + 1; y++) {
593         g_ptr = &floor_ptr->grid_array[y][x1 - 1];
594         place_grid(player_ptr, g_ptr, GB_OUTER);
595         g_ptr = &floor_ptr->grid_array[y][x2 + 1];
596         place_grid(player_ptr, g_ptr, GB_OUTER);
597     }
598     for (x = x1 - 1; x <= x2 + 1; x++) {
599         g_ptr = &floor_ptr->grid_array[y1 - 1][x];
600         place_grid(player_ptr, g_ptr, GB_OUTER);
601         g_ptr = &floor_ptr->grid_array[y2 + 1][x];
602         place_grid(player_ptr, g_ptr, GB_OUTER);
603     }
604
605     /* The inner room */
606     y1 = y1 + 2;
607     y2 = y2 - 2;
608     x1 = x1 + 2;
609     x2 = x2 - 2;
610
611     /* The inner walls */
612     for (y = y1 - 1; y <= y2 + 1; y++) {
613         g_ptr = &floor_ptr->grid_array[y][x1 - 1];
614         place_grid(player_ptr, g_ptr, GB_INNER);
615         g_ptr = &floor_ptr->grid_array[y][x2 + 1];
616         place_grid(player_ptr, g_ptr, GB_INNER);
617     }
618     for (x = x1 - 1; x <= x2 + 1; x++) {
619         g_ptr = &floor_ptr->grid_array[y1 - 1][x];
620         place_grid(player_ptr, g_ptr, GB_INNER);
621         g_ptr = &floor_ptr->grid_array[y2 + 1][x];
622         place_grid(player_ptr, g_ptr, GB_INNER);
623     }
624
625     /* Inner room variations */
626     switch (randint1(5)) {
627         /* Just an inner room with a monster */
628     case 1: {
629         /* Place a secret door */
630         switch (randint1(4)) {
631         case 1:
632             place_secret_door(player_ptr, y1 - 1, xval, DOOR_DEFAULT);
633             break;
634         case 2:
635             place_secret_door(player_ptr, y2 + 1, xval, DOOR_DEFAULT);
636             break;
637         case 3:
638             place_secret_door(player_ptr, yval, x1 - 1, DOOR_DEFAULT);
639             break;
640         case 4:
641             place_secret_door(player_ptr, yval, x2 + 1, DOOR_DEFAULT);
642             break;
643         }
644
645         /* Place a monster in the room */
646         vault_monsters(player_ptr, yval, xval, 1);
647
648         break;
649     }
650
651     /* Treasure Vault (with a door) */
652     case 2: {
653         /* Place a secret door */
654         switch (randint1(4)) {
655         case 1:
656             place_secret_door(player_ptr, y1 - 1, xval, DOOR_DEFAULT);
657             break;
658         case 2:
659             place_secret_door(player_ptr, y2 + 1, xval, DOOR_DEFAULT);
660             break;
661         case 3:
662             place_secret_door(player_ptr, yval, x1 - 1, DOOR_DEFAULT);
663             break;
664         case 4:
665             place_secret_door(player_ptr, yval, x2 + 1, DOOR_DEFAULT);
666             break;
667         }
668
669         /* Place another inner room */
670         for (y = yval - 1; y <= yval + 1; y++) {
671             for (x = xval - 1; x <= xval + 1; x++) {
672                 if ((x == xval) && (y == yval)) {
673                     continue;
674                 }
675                 g_ptr = &floor_ptr->grid_array[y][x];
676                 place_grid(player_ptr, g_ptr, GB_INNER);
677             }
678         }
679
680         /* Place a locked door on the inner room */
681         switch (randint1(4)) {
682         case 1:
683             place_locked_door(player_ptr, yval - 1, xval);
684             break;
685         case 2:
686             place_locked_door(player_ptr, yval + 1, xval);
687             break;
688         case 3:
689             place_locked_door(player_ptr, yval, xval - 1);
690             break;
691         case 4:
692             place_locked_door(player_ptr, yval, xval + 1);
693             break;
694         }
695
696         /* Monsters to guard the "treasure" */
697         vault_monsters(player_ptr, yval, xval, randint1(3) + 2);
698
699         /* Object (80%) */
700         if (randint0(100) < 80) {
701             place_object(player_ptr, yval, xval, 0L);
702         }
703
704         /* Stairs (20%) */
705         else {
706             place_random_stairs(player_ptr, yval, xval);
707         }
708
709         /* Traps to protect the treasure */
710         vault_traps(player_ptr, yval, xval, 4, 10, 2 + randint1(3));
711
712         break;
713     }
714
715     /* Inner pillar(s). */
716     case 3: {
717         /* Place a secret door */
718         switch (randint1(4)) {
719         case 1:
720             place_secret_door(player_ptr, y1 - 1, xval, DOOR_DEFAULT);
721             break;
722         case 2:
723             place_secret_door(player_ptr, y2 + 1, xval, DOOR_DEFAULT);
724             break;
725         case 3:
726             place_secret_door(player_ptr, yval, x1 - 1, DOOR_DEFAULT);
727             break;
728         case 4:
729             place_secret_door(player_ptr, yval, x2 + 1, DOOR_DEFAULT);
730             break;
731         }
732
733         /* Large Inner Pillar */
734         for (y = yval - 1; y <= yval + 1; y++) {
735             for (x = xval - 1; x <= xval + 1; x++) {
736                 g_ptr = &floor_ptr->grid_array[y][x];
737                 place_grid(player_ptr, g_ptr, GB_INNER);
738             }
739         }
740
741         /* Occasionally, two more Large Inner Pillars */
742         if (one_in_(2)) {
743             tmp = randint1(2);
744             for (y = yval - 1; y <= yval + 1; y++) {
745                 for (x = xval - 5 - tmp; x <= xval - 3 - tmp; x++) {
746                     g_ptr = &floor_ptr->grid_array[y][x];
747                     place_grid(player_ptr, g_ptr, GB_INNER);
748                 }
749                 for (x = xval + 3 + tmp; x <= xval + 5 + tmp; x++) {
750                     g_ptr = &floor_ptr->grid_array[y][x];
751                     place_grid(player_ptr, g_ptr, GB_INNER);
752                 }
753             }
754         }
755
756         /* Occasionally, some Inner rooms */
757         if (one_in_(3)) {
758             int door_type = (dungeon.flags.has(DungeonFeatureType::CURTAIN) && one_in_(dungeon.flags.has(DungeonFeatureType::NO_CAVE) ? 16 : 256))
759                                 ? DOOR_CURTAIN
760                                 : (dungeon.flags.has(DungeonFeatureType::GLASS_DOOR) ? DOOR_GLASS_DOOR : DOOR_DOOR);
761
762             /* Long horizontal walls */
763             for (x = xval - 5; x <= xval + 5; x++) {
764                 g_ptr = &floor_ptr->grid_array[yval - 1][x];
765                 place_grid(player_ptr, g_ptr, GB_INNER);
766                 g_ptr = &floor_ptr->grid_array[yval + 1][x];
767                 place_grid(player_ptr, g_ptr, GB_INNER);
768             }
769
770             /* Close off the left/right edges */
771             g_ptr = &floor_ptr->grid_array[yval][xval - 5];
772             place_grid(player_ptr, g_ptr, GB_INNER);
773             g_ptr = &floor_ptr->grid_array[yval][xval + 5];
774             place_grid(player_ptr, g_ptr, GB_INNER);
775
776             /* Secret doors (random top/bottom) */
777             place_secret_door(player_ptr, yval - 3 + (randint1(2) * 2), xval - 3, door_type);
778             place_secret_door(player_ptr, yval - 3 + (randint1(2) * 2), xval + 3, door_type);
779
780             /* Monsters */
781             vault_monsters(player_ptr, yval, xval - 2, randint1(2));
782             vault_monsters(player_ptr, yval, xval + 2, randint1(2));
783
784             /* Objects */
785             if (one_in_(3)) {
786                 place_object(player_ptr, yval, xval - 2, 0L);
787             }
788             if (one_in_(3)) {
789                 place_object(player_ptr, yval, xval + 2, 0L);
790             }
791         }
792
793         break;
794     }
795
796     /* Maze inside. */
797     case 4: {
798         /* Place a secret door */
799         switch (randint1(4)) {
800         case 1:
801             place_secret_door(player_ptr, y1 - 1, xval, DOOR_DEFAULT);
802             break;
803         case 2:
804             place_secret_door(player_ptr, y2 + 1, xval, DOOR_DEFAULT);
805             break;
806         case 3:
807             place_secret_door(player_ptr, yval, x1 - 1, DOOR_DEFAULT);
808             break;
809         case 4:
810             place_secret_door(player_ptr, yval, x2 + 1, DOOR_DEFAULT);
811             break;
812         }
813
814         /* Maze (really a checkerboard) */
815         for (y = y1; y <= y2; y++) {
816             for (x = x1; x <= x2; x++) {
817                 if (0x1 & (x + y)) {
818                     g_ptr = &floor_ptr->grid_array[y][x];
819                     place_grid(player_ptr, g_ptr, GB_INNER);
820                 }
821             }
822         }
823
824         /* Monsters just love mazes. */
825         vault_monsters(player_ptr, yval, xval - 5, randint1(3));
826         vault_monsters(player_ptr, yval, xval + 5, randint1(3));
827
828         /* Traps make them entertaining. */
829         vault_traps(player_ptr, yval, xval - 3, 2, 8, randint1(3));
830         vault_traps(player_ptr, yval, xval + 3, 2, 8, randint1(3));
831
832         /* Mazes should have some treasure too. */
833         vault_objects(player_ptr, yval, xval, 3);
834
835         break;
836     }
837
838     /* Four small rooms. */
839     case 5: {
840         int door_type = (dungeon.flags.has(DungeonFeatureType::CURTAIN) && one_in_(dungeon.flags.has(DungeonFeatureType::NO_CAVE) ? 16 : 256))
841                             ? DOOR_CURTAIN
842                             : (dungeon.flags.has(DungeonFeatureType::GLASS_DOOR) ? DOOR_GLASS_DOOR : DOOR_DOOR);
843
844         /* Inner "cross" */
845         for (y = y1; y <= y2; y++) {
846             g_ptr = &floor_ptr->grid_array[y][xval];
847             place_grid(player_ptr, g_ptr, GB_INNER);
848         }
849         for (x = x1; x <= x2; x++) {
850             g_ptr = &floor_ptr->grid_array[yval][x];
851             place_grid(player_ptr, g_ptr, GB_INNER);
852         }
853
854         /* Doors into the rooms */
855         if (randint0(100) < 50) {
856             int i = randint1(10);
857             place_secret_door(player_ptr, y1 - 1, xval - i, door_type);
858             place_secret_door(player_ptr, y1 - 1, xval + i, door_type);
859             place_secret_door(player_ptr, y2 + 1, xval - i, door_type);
860             place_secret_door(player_ptr, y2 + 1, xval + i, door_type);
861         } else {
862             int i = randint1(3);
863             place_secret_door(player_ptr, yval + i, x1 - 1, door_type);
864             place_secret_door(player_ptr, yval - i, x1 - 1, door_type);
865             place_secret_door(player_ptr, yval + i, x2 + 1, door_type);
866             place_secret_door(player_ptr, yval - i, x2 + 1, door_type);
867         }
868
869         /* Treasure, centered at the center of the cross */
870         vault_objects(player_ptr, yval, xval, 2 + randint1(2));
871
872         /* Gotta have some monsters. */
873         vault_monsters(player_ptr, yval + 1, xval - 4, randint1(4));
874         vault_monsters(player_ptr, yval + 1, xval + 4, randint1(4));
875         vault_monsters(player_ptr, yval - 1, xval - 4, randint1(4));
876         vault_monsters(player_ptr, yval - 1, xval + 4, randint1(4));
877
878         break;
879     }
880     }
881
882     return true;
883 }
884
885 /*!
886  * @brief タイプ11の部屋…円形部屋の生成 / Type 11 -- Build an vertical oval room.
887  * @param player_ptr プレイヤーへの参照ポインタ
888  * @details
889  * For every grid in the possible square, check the distance.\n
890  * If it's less than the radius, make it a room square.\n
891  *\n
892  * When done fill from the inside to find the walls,\n
893  */
894 bool build_type11(PlayerType *player_ptr, dun_data_type *dd_ptr)
895 {
896     POSITION rad, x, y, x0, y0;
897     int light = false;
898
899     /* Occasional light */
900     auto *floor_ptr = player_ptr->current_floor_ptr;
901     if ((randint1(floor_ptr->dun_level) <= 15) && floor_ptr->get_dungeon_definition().flags.has_not(DungeonFeatureType::DARKNESS)) {
902         light = true;
903     }
904
905     rad = randint0(9);
906
907     /* Find and reserve some space in the dungeon.  Get center of room. */
908     if (!find_space(player_ptr, dd_ptr, &y0, &x0, rad * 2 + 1, rad * 2 + 1)) {
909         return false;
910     }
911
912     /* Make circular floor */
913     for (x = x0 - rad; x <= x0 + rad; x++) {
914         for (y = y0 - rad; y <= y0 + rad; y++) {
915             if (distance(y0, x0, y, x) <= rad - 1) {
916                 /* inside- so is floor */
917                 place_bold(player_ptr, y, x, GB_FLOOR);
918             } else if (distance(y0, x0, y, x) <= rad + 1) {
919                 /* make granite outside so on_defeat_arena_monster works */
920                 place_bold(player_ptr, y, x, GB_EXTRA);
921             }
922         }
923     }
924
925     /* Find visible outer walls and set to be FEAT_OUTER */
926     add_outer_wall(player_ptr, x0, y0, light, x0 - rad, y0 - rad, x0 + rad, y0 + rad);
927
928     return true;
929 }
930
931 /*!
932  * @brief タイプ12の部屋…ドーム型部屋の生成 / Type 12 -- Build crypt room.
933  * @param player_ptr プレイヤーへの参照ポインタ
934  * @details
935  * For every grid in the possible square, check the (fake) distance.\n
936  * If it's less than the radius, make it a room square.\n
937  *\n
938  * When done fill from the inside to find the walls,\n
939  */
940 bool build_type12(PlayerType *player_ptr, dun_data_type *dd_ptr)
941 {
942     POSITION rad, x, y, x0, y0;
943     int light = false;
944     bool emptyflag = true;
945
946     /* Make a random metric */
947     POSITION h1, h2, h3, h4;
948     h1 = randint1(32) - 16;
949     h2 = randint1(16);
950     h3 = randint1(32);
951     h4 = randint1(32) - 16;
952
953     /* Occasional light */
954     auto *floor_ptr = player_ptr->current_floor_ptr;
955     if ((randint1(floor_ptr->dun_level) <= 5) && floor_ptr->get_dungeon_definition().flags.has_not(DungeonFeatureType::DARKNESS)) {
956         light = true;
957     }
958
959     rad = randint1(9);
960
961     /* Find and reserve some space in the dungeon.  Get center of room. */
962     if (!find_space(player_ptr, dd_ptr, &y0, &x0, rad * 2 + 3, rad * 2 + 3)) {
963         return false;
964     }
965
966     /* Make floor */
967     for (x = x0 - rad; x <= x0 + rad; x++) {
968         for (y = y0 - rad; y <= y0 + rad; y++) {
969             /* clear room flag */
970             floor_ptr->grid_array[y][x].info &= ~(CAVE_ROOM);
971
972             if (dist2(y0, x0, y, x, h1, h2, h3, h4) <= rad - 1) {
973                 /* inside - so is floor */
974                 place_bold(player_ptr, y, x, GB_FLOOR);
975             } else if (distance(y0, x0, y, x) < 3) {
976                 place_bold(player_ptr, y, x, GB_FLOOR);
977             } else {
978                 /* make granite outside so on_defeat_arena_monster works */
979                 place_bold(player_ptr, y, x, GB_EXTRA);
980             }
981
982             /* proper boundary for on_defeat_arena_monster */
983             if (((y + rad) == y0) || ((y - rad) == y0) || ((x + rad) == x0) || ((x - rad) == x0)) {
984                 place_bold(player_ptr, y, x, GB_EXTRA);
985             }
986         }
987     }
988
989     /* Find visible outer walls and set to be FEAT_OUTER */
990     add_outer_wall(player_ptr, x0, y0, light, x0 - rad - 1, y0 - rad - 1, x0 + rad + 1, y0 + rad + 1);
991
992     /* Check to see if there is room for an inner vault */
993     for (x = x0 - 2; x <= x0 + 2; x++) {
994         for (y = y0 - 2; y <= y0 + 2; y++) {
995             if (!floor_ptr->grid_array[y][x].is_floor()) {
996                 /* Wall in the way */
997                 emptyflag = false;
998             }
999         }
1000     }
1001
1002     if (emptyflag && one_in_(2)) {
1003         /* Build the vault */
1004         build_small_room(player_ptr, x0, y0);
1005
1006         /* Place a treasure in the vault */
1007         place_object(player_ptr, y0, x0, 0L);
1008
1009         /* Let's guard the treasure well */
1010         vault_monsters(player_ptr, y0, x0, randint0(2) + 3);
1011
1012         /* Traps naturally */
1013         vault_traps(player_ptr, y0, x0, 4, 4, randint0(3) + 2);
1014     }
1015
1016     return true;
1017 }