OSDN Git Service

[Refactor] #40570 Renamed rooms.c/h to rooms-builder.c/h
[hengband/hengband.git] / src / room / rooms-vault.c
1 /*!
2  * @brief Vaultの生成処理
3  * @date 2018/09/11
4  * @author deskull
5  */
6
7 #include "room/rooms-vault.h"
8 #include "dungeon/dungeon-flag-types.h"
9 #include "dungeon/dungeon.h"
10 #include "floor/cave.h"
11 #include "floor/floor-generate.h"
12 #include "floor/floor.h"
13 #include "floor/wild.h"
14 #include "game-option/cheat-types.h"
15 #include "grid/feature.h"
16 #include "grid/grid.h"
17 #include "grid/trap.h"
18 #include "monster-floor/monster-generator.h"
19 #include "monster-floor/place-monster-types.h"
20 #include "object-enchant/item-apply-magic.h"
21 #include "room/cave-filler.h"
22 #include "room/lake-types.h"
23 #include "room/rooms-builder.h"
24 #include "room/rooms-maze-vault.h"
25 #include "room/space-finder.h"
26 #include "room/treasure-deployment.h"
27 #include "store/store-util.h"
28 #include "store/store.h"
29 #include "system/dungeon-data-definition.h"
30 #include "system/floor-type-definition.h"
31 #include "wizard/wizard-messages.h"
32
33 /*
34  * The vault generation arrays
35  */
36 vault_type *v_info;
37 char *v_name;
38 char *v_text;
39
40 /*
41  * Maximum number of vaults in v_info.txt
42  */
43 VAULT_IDX max_v_idx;
44
45 /*
46  * This function creates a random vault that looks like a collection of bubbles.
47  * It works by getting a set of coordinates that represent the center of each
48  * bubble.  The entire room is made by seeing which bubble center is closest. If
49  * two centers are equidistant then the square is a wall, otherwise it is a floor.
50  * The only exception is for squares really near a center, these are always floor.
51  * (It looks better than without this check.)
52  *
53  * Note: If two centers are on the same point then this algorithm will create a
54  *       blank bubble filled with walls. - This is prevented from happening.
55  */
56 static void build_bubble_vault(player_type *player_ptr, POSITION x0, POSITION y0, POSITION xsize, POSITION ysize)
57 {
58 #define BUBBLENUM 10 /* number of bubbles */
59
60     /* array of center points of bubbles */
61     coord center[BUBBLENUM];
62
63     int i, j;
64     POSITION x = 0, y = 0;
65     u16b min1, min2, temp;
66     bool done;
67
68     /* Offset from center to top left hand corner */
69     POSITION xhsize = xsize / 2;
70     POSITION yhsize = ysize / 2;
71
72     msg_print_wizard(player_ptr, CHEAT_DUNGEON, _("泡型ランダムVaultを生成しました。", "Room Vault."));
73
74     /* Allocate center of bubbles */
75     center[0].x = (byte)randint1(xsize - 3) + 1;
76     center[0].y = (byte)randint1(ysize - 3) + 1;
77
78     for (i = 1; i < BUBBLENUM; i++) {
79         done = FALSE;
80
81         /* get center and check to see if it is unique */
82         while (!done) {
83             done = TRUE;
84
85             x = randint1(xsize - 3) + 1;
86             y = randint1(ysize - 3) + 1;
87
88             for (j = 0; j < i; j++) {
89                 /* rough test to see if there is an overlap */
90                 if ((x == center[j].x) && (y == center[j].y))
91                     done = FALSE;
92             }
93         }
94
95         center[i].x = x;
96         center[i].y = y;
97     }
98
99     /* Top and bottom boundaries */
100     floor_type *floor_ptr = player_ptr->current_floor_ptr;
101     for (i = 0; i < xsize; i++) {
102         int side_x = x0 - xhsize + i;
103
104         place_bold(player_ptr, y0 - yhsize + 0, side_x, GB_OUTER_NOPERM);
105         floor_ptr->grid_array[y0 - yhsize + 0][side_x].info |= (CAVE_ROOM | CAVE_ICKY);
106         place_bold(player_ptr, y0 - yhsize + ysize - 1, side_x, GB_OUTER_NOPERM);
107         floor_ptr->grid_array[y0 - yhsize + ysize - 1][side_x].info |= (CAVE_ROOM | CAVE_ICKY);
108     }
109
110     /* Left and right boundaries */
111     for (i = 1; i < ysize - 1; i++) {
112         int side_y = y0 - yhsize + i;
113
114         place_bold(player_ptr, side_y, x0 - xhsize + 0, GB_OUTER_NOPERM);
115         floor_ptr->grid_array[side_y][x0 - xhsize + 0].info |= (CAVE_ROOM | CAVE_ICKY);
116         place_bold(player_ptr, side_y, x0 - xhsize + xsize - 1, GB_OUTER_NOPERM);
117         floor_ptr->grid_array[side_y][x0 - xhsize + xsize - 1].info |= (CAVE_ROOM | CAVE_ICKY);
118     }
119
120     /* Fill in middle with bubbles */
121     for (x = 1; x < xsize - 1; x++) {
122         for (y = 1; y < ysize - 1; y++) {
123             /* Get distances to two closest centers */
124
125             min1 = (u16b)distance(x, y, center[0].x, center[0].y);
126             min2 = (u16b)distance(x, y, center[1].x, center[1].y);
127
128             if (min1 > min2) {
129                 /* swap if in wrong order */
130                 temp = min1;
131                 min1 = min2;
132                 min2 = temp;
133             }
134
135             /* Scan the rest */
136             for (i = 2; i < BUBBLENUM; i++) {
137                 temp = (u16b)distance(x, y, center[i].x, center[i].y);
138
139                 if (temp < min1) {
140                     /* smallest */
141                     min2 = min1;
142                     min1 = temp;
143                 } else if (temp < min2) {
144                     /* second smallest */
145                     min2 = temp;
146                 }
147             }
148             if (((min2 - min1) <= 2) && (!(min1 < 3))) {
149                 /* Boundary at midpoint+ not at inner region of bubble */
150                 place_bold(player_ptr, y0 - yhsize + y, x0 - xhsize + x, GB_OUTER_NOPERM);
151             } else {
152                 /* middle of a bubble */
153                 place_bold(player_ptr, y0 - yhsize + y, x0 - xhsize + x, GB_FLOOR);
154             }
155
156             /* clean up rest of flags */
157             floor_ptr->grid_array[y0 - yhsize + y][x0 - xhsize + x].info |= (CAVE_ROOM | CAVE_ICKY);
158         }
159     }
160
161     /* Try to add some random doors */
162     for (i = 0; i < 500; i++) {
163         x = randint1(xsize - 3) - xhsize + x0 + 1;
164         y = randint1(ysize - 3) - yhsize + y0 + 1;
165         add_door(player_ptr, x, y);
166     }
167
168     /* Fill with monsters and treasure, low difficulty */
169     fill_treasure(player_ptr, x0 - xhsize + 1, x0 - xhsize + xsize - 2, y0 - yhsize + 1, y0 - yhsize + ysize - 2, randint1(5));
170 }
171
172 /* Create a random vault that looks like a collection of overlapping rooms */
173 static void build_room_vault(player_type *player_ptr, POSITION x0, POSITION y0, POSITION xsize, POSITION ysize)
174 {
175     POSITION x1, x2, y1, y2, xhsize, yhsize;
176     int i;
177
178     /* get offset from center */
179     xhsize = xsize / 2;
180     yhsize = ysize / 2;
181
182     msg_print_wizard(player_ptr, CHEAT_DUNGEON, _("部屋型ランダムVaultを生成しました。", "Room Vault."));
183
184     /* fill area so don't get problems with arena levels */
185     floor_type *floor_ptr = player_ptr->current_floor_ptr;
186     for (x1 = 0; x1 < xsize; x1++) {
187         POSITION x = x0 - xhsize + x1;
188
189         for (y1 = 0; y1 < ysize; y1++) {
190             POSITION y = y0 - yhsize + y1;
191
192             place_bold(player_ptr, y, x, GB_EXTRA);
193             floor_ptr->grid_array[y][x].info &= (~CAVE_ICKY);
194         }
195     }
196
197     /* add ten random rooms */
198     for (i = 0; i < 10; i++) {
199         x1 = randint1(xhsize) * 2 + x0 - xhsize;
200         x2 = randint1(xhsize) * 2 + x0 - xhsize;
201         y1 = randint1(yhsize) * 2 + y0 - yhsize;
202         y2 = randint1(yhsize) * 2 + y0 - yhsize;
203         build_room(player_ptr, x1, x2, y1, y2);
204     }
205
206     /* Add some random doors */
207     for (i = 0; i < 500; i++) {
208         x1 = randint1(xsize - 3) - xhsize + x0 + 1;
209         y1 = randint1(ysize - 3) - yhsize + y0 + 1;
210         add_door(player_ptr, x1, y1);
211     }
212
213     /* Fill with monsters and treasure, high difficulty */
214     fill_treasure(player_ptr, x0 - xhsize + 1, x0 - xhsize + xsize - 2, y0 - yhsize + 1, y0 - yhsize + ysize - 2, randint1(5) + 5);
215 }
216
217 /* Create a random vault out of a fractal grid */
218 static void build_cave_vault(player_type *player_ptr, POSITION x0, POSITION y0, POSITION xsiz, POSITION ysiz)
219 {
220     int grd, roug, cutoff;
221     bool done, light, room;
222     POSITION xhsize, yhsize, xsize, ysize, x, y;
223
224     /* round to make sizes even */
225     xhsize = xsiz / 2;
226     yhsize = ysiz / 2;
227     xsize = xhsize * 2;
228     ysize = yhsize * 2;
229
230     msg_print_wizard(player_ptr, CHEAT_DUNGEON, _("洞穴ランダムVaultを生成しました。", "Cave Vault."));
231
232     light = done = FALSE;
233     room = TRUE;
234
235     floor_type *floor_ptr = player_ptr->current_floor_ptr;
236     while (!done) {
237         /* testing values for these parameters feel free to adjust */
238         grd = 1 << randint0(4);
239
240         /* want average of about 16 */
241         roug = randint1(8) * randint1(4);
242
243         /* about size/2 */
244         cutoff = randint1(xsize / 4) + randint1(ysize / 4) + randint1(xsize / 4) + randint1(ysize / 4);
245
246         /* make it */
247         generate_hmap(floor_ptr, y0, x0, xsize, ysize, grd, roug, cutoff);
248
249         /* Convert to normal format+ clean up */
250         done = generate_fracave(player_ptr, y0, x0, xsize, ysize, cutoff, light, room);
251     }
252
253     /* Set icky flag because is a vault */
254     for (x = 0; x <= xsize; x++) {
255         for (y = 0; y <= ysize; y++) {
256             floor_ptr->grid_array[y0 - yhsize + y][x0 - xhsize + x].info |= CAVE_ICKY;
257         }
258     }
259
260     /* Fill with monsters and treasure, low difficulty */
261     fill_treasure(player_ptr, x0 - xhsize + 1, x0 - xhsize + xsize - 1, y0 - yhsize + 1, y0 - yhsize + ysize - 1, randint1(5));
262 }
263
264 /*!
265  * @brief Vault地形を回転、上下左右反転するための座標変換を返す / coordinate translation code
266  * @param x 変換したい点のX座標参照ポインタ
267  * @param y 変換したい点のY座標参照ポインタ
268  * @param xoffset Vault生成時の基準X座標
269  * @param yoffset Vault生成時の基準Y座標
270  * @param transno 処理ID
271  * @return なし
272  */
273 static void coord_trans(POSITION *x, POSITION *y, POSITION xoffset, POSITION yoffset, int transno)
274 {
275     int i;
276     int temp;
277
278     /*
279      * transno specifies what transformation is required. (0-7)
280      * The lower two bits indicate by how much the vault is rotated,
281      * and the upper bit indicates a reflection.
282      * This is done by using rotation matrices... however since
283      * these are mostly zeros for rotations by 90 degrees this can
284      * be expressed simply in terms of swapping and inverting the
285      * x and y coordinates.
286      */
287     for (i = 0; i < transno % 4; i++) {
288         /* rotate by 90 degrees */
289         temp = *x;
290         *x = -(*y);
291         *y = temp;
292     }
293
294     if (transno / 4) {
295         /* Reflect depending on status of 3rd bit. */
296         *x = -(*x);
297     }
298
299     /* Add offsets so vault stays in the first quadrant */
300     *x += xoffset;
301     *y += yoffset;
302 }
303
304 /*!
305  * @brief Vaultをフロアに配置する / Hack -- fill in "vault" rooms
306  * @param player_ptr プレーヤーへの参照ポインタ
307  * @param yval 生成基準Y座標
308  * @param xval 生成基準X座標
309  * @param ymax VaultのYサイズ
310  * @param xmax VaultのXサイズ
311  * @param data Vaultのデータ文字列
312  * @param xoffset 変換基準X座標
313  * @param yoffset 変換基準Y座標
314  * @param transno 変換ID
315  * @return なし
316  */
317 static void build_vault(
318     player_type *player_ptr, POSITION yval, POSITION xval, POSITION ymax, POSITION xmax, concptr data, POSITION xoffset, POSITION yoffset, int transno)
319 {
320     POSITION dx, dy, x, y, i, j;
321     concptr t;
322     grid_type *g_ptr;
323
324     /* Place dungeon features and objects */
325     floor_type *floor_ptr = player_ptr->current_floor_ptr;
326     for (t = data, dy = 0; dy < ymax; dy++) {
327         for (dx = 0; dx < xmax; dx++, t++) {
328             /* prevent loop counter from being overwritten */
329             i = dx;
330             j = dy;
331
332             /* Flip / rotate */
333             coord_trans(&i, &j, xoffset, yoffset, transno);
334
335             if (transno % 2 == 0) {
336                 /* no swap of x/y */
337                 x = xval - (xmax / 2) + i;
338                 y = yval - (ymax / 2) + j;
339             } else {
340                 /* swap of x/y */
341                 x = xval - (ymax / 2) + i;
342                 y = yval - (xmax / 2) + j;
343             }
344
345             /* Hack -- skip "non-grids" */
346             if (*t == ' ')
347                 continue;
348             g_ptr = &floor_ptr->grid_array[y][x];
349
350             /* Lay down a floor */
351             place_grid(player_ptr, g_ptr, GB_FLOOR);
352
353             /* Remove any mimic */
354             g_ptr->mimic = 0;
355
356             /* Part of a vault */
357             g_ptr->info |= (CAVE_ROOM | CAVE_ICKY);
358
359             /* Analyze the grid */
360             switch (*t) {
361                 /* Granite wall (outer) */
362             case '%':
363                 place_grid(player_ptr, g_ptr, GB_OUTER_NOPERM);
364                 break;
365
366                 /* Granite wall (inner) */
367             case '#':
368                 place_grid(player_ptr, g_ptr, GB_INNER);
369                 break;
370
371                 /* Glass wall (inner) */
372             case '$':
373                 place_grid(player_ptr, g_ptr, GB_INNER);
374                 g_ptr->feat = feat_glass_wall;
375                 break;
376
377                 /* Permanent wall (inner) */
378             case 'X':
379                 place_grid(player_ptr, g_ptr, GB_INNER_PERM);
380                 break;
381
382                 /* Permanent glass wall (inner) */
383             case 'Y':
384                 place_grid(player_ptr, g_ptr, GB_INNER_PERM);
385                 g_ptr->feat = feat_permanent_glass_wall;
386                 break;
387
388                 /* Treasure/trap */
389             case '*':
390                 if (randint0(100) < 75) {
391                     place_object(player_ptr, y, x, 0L);
392                 } else {
393                     place_trap(player_ptr, y, x);
394                 }
395                 break;
396
397                 /* Treasure */
398             case '[':
399                 place_object(player_ptr, y, x, 0L);
400                 break;
401
402                 /* Tree */
403             case ':':
404                 g_ptr->feat = feat_tree;
405                 break;
406
407                 /* Secret doors */
408             case '+':
409                 place_secret_door(player_ptr, y, x, DOOR_DEFAULT);
410                 break;
411
412                 /* Secret glass doors */
413             case '-':
414                 place_secret_door(player_ptr, y, x, DOOR_GLASS_DOOR);
415                 if (is_closed_door(player_ptr, g_ptr->feat))
416                     g_ptr->mimic = feat_glass_wall;
417                 break;
418
419                 /* Curtains */
420             case '\'':
421                 place_secret_door(player_ptr, y, x, DOOR_CURTAIN);
422                 break;
423
424                 /* Trap */
425             case '^':
426                 place_trap(player_ptr, y, x);
427                 break;
428
429                 /* Black market in a dungeon */
430             case 'S':
431                 set_cave_feat(floor_ptr, y, x, feat_black_market);
432                 store_init(NO_TOWN, STORE_BLACK);
433                 break;
434
435                 /* The Pattern */
436             case 'p':
437                 set_cave_feat(floor_ptr, y, x, feat_pattern_start);
438                 break;
439
440             case 'a':
441                 set_cave_feat(floor_ptr, y, x, feat_pattern_1);
442                 break;
443
444             case 'b':
445                 set_cave_feat(floor_ptr, y, x, feat_pattern_2);
446                 break;
447
448             case 'c':
449                 set_cave_feat(floor_ptr, y, x, feat_pattern_3);
450                 break;
451
452             case 'd':
453                 set_cave_feat(floor_ptr, y, x, feat_pattern_4);
454                 break;
455
456             case 'P':
457                 set_cave_feat(floor_ptr, y, x, feat_pattern_end);
458                 break;
459
460             case 'B':
461                 set_cave_feat(floor_ptr, y, x, feat_pattern_exit);
462                 break;
463
464             case 'A':
465                 /* Reward for Pattern walk */
466                 floor_ptr->object_level = floor_ptr->base_level + 12;
467                 place_object(player_ptr, y, x, AM_GOOD | AM_GREAT);
468                 floor_ptr->object_level = floor_ptr->base_level;
469                 break;
470
471             case '~':
472                 set_cave_feat(floor_ptr, y, x, feat_shallow_water);
473                 break;
474
475             case '=':
476                 set_cave_feat(floor_ptr, y, x, feat_deep_water);
477                 break;
478
479             case 'v':
480                 set_cave_feat(floor_ptr, y, x, feat_shallow_lava);
481                 break;
482
483             case 'w':
484                 set_cave_feat(floor_ptr, y, x, feat_deep_lava);
485                 break;
486
487             case 'f':
488                 set_cave_feat(floor_ptr, y, x, feat_shallow_acid_puddle);
489                 break;
490
491             case 'F':
492                 set_cave_feat(floor_ptr, y, x, feat_deep_acid_puddle);
493                 break;
494
495             case 'g':
496                 set_cave_feat(floor_ptr, y, x, feat_shallow_poisonous_puddle);
497                 break;
498
499             case 'G':
500                 set_cave_feat(floor_ptr, y, x, feat_deep_poisonous_puddle);
501                 break;
502
503             case 'h':
504                 set_cave_feat(floor_ptr, y, x, feat_cold_zone);
505                 break;
506
507             case 'H':
508                 set_cave_feat(floor_ptr, y, x, feat_heavy_cold_zone);
509                 break;
510
511             case 'i':
512                 set_cave_feat(floor_ptr, y, x, feat_electrical_zone);
513                 break;
514
515             case 'I':
516                 set_cave_feat(floor_ptr, y, x, feat_heavy_electrical_zone);
517                 break;
518             }
519         }
520     }
521
522     /* Place dungeon monsters and objects */
523     for (t = data, dy = 0; dy < ymax; dy++) {
524         for (dx = 0; dx < xmax; dx++, t++) {
525             /* prevent loop counter from being overwritten */
526             i = dx;
527             j = dy;
528
529             /* Flip / rotate */
530             coord_trans(&i, &j, xoffset, yoffset, transno);
531
532             if (transno % 2 == 0) {
533                 /* no swap of x/y */
534                 x = xval - (xmax / 2) + i;
535                 y = yval - (ymax / 2) + j;
536             } else {
537                 /* swap of x/y */
538                 x = xval - (ymax / 2) + i;
539                 y = yval - (xmax / 2) + j;
540             }
541
542             /* Hack -- skip "non-grids" */
543             if (*t == ' ')
544                 continue;
545
546             /* Analyze the symbol */
547             switch (*t) {
548             case '&': {
549                 floor_ptr->monster_level = floor_ptr->base_level + 5;
550                 place_monster(player_ptr, y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
551                 floor_ptr->monster_level = floor_ptr->base_level;
552                 break;
553             }
554
555             /* Meaner monster */
556             case '@': {
557                 floor_ptr->monster_level = floor_ptr->base_level + 11;
558                 place_monster(player_ptr, y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
559                 floor_ptr->monster_level = floor_ptr->base_level;
560                 break;
561             }
562
563             /* Meaner monster, plus treasure */
564             case '9': {
565                 floor_ptr->monster_level = floor_ptr->base_level + 9;
566                 place_monster(player_ptr, y, x, PM_ALLOW_SLEEP);
567                 floor_ptr->monster_level = floor_ptr->base_level;
568                 floor_ptr->object_level = floor_ptr->base_level + 7;
569                 place_object(player_ptr, y, x, AM_GOOD);
570                 floor_ptr->object_level = floor_ptr->base_level;
571                 break;
572             }
573
574             /* Nasty monster and treasure */
575             case '8': {
576                 floor_ptr->monster_level = floor_ptr->base_level + 40;
577                 place_monster(player_ptr, y, x, PM_ALLOW_SLEEP);
578                 floor_ptr->monster_level = floor_ptr->base_level;
579                 floor_ptr->object_level = floor_ptr->base_level + 20;
580                 place_object(player_ptr, y, x, AM_GOOD | AM_GREAT);
581                 floor_ptr->object_level = floor_ptr->base_level;
582                 break;
583             }
584
585             /* Monster and/or object */
586             case ',': {
587                 if (randint0(100) < 50) {
588                     floor_ptr->monster_level = floor_ptr->base_level + 3;
589                     place_monster(player_ptr, y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
590                     floor_ptr->monster_level = floor_ptr->base_level;
591                 }
592                 if (randint0(100) < 50) {
593                     floor_ptr->object_level = floor_ptr->base_level + 7;
594                     place_object(player_ptr, y, x, 0L);
595                     floor_ptr->object_level = floor_ptr->base_level;
596                 }
597                 break;
598             }
599             }
600         }
601     }
602 }
603
604 /*!
605  * @brief タイプ7の部屋…v_info.txtより小型vaultを生成する / Type 7 -- simple vaults (see "v_info.txt")
606  * @return なし
607  */
608 bool build_type7(player_type *player_ptr)
609 {
610     vault_type *v_ptr = NULL;
611     int dummy;
612     POSITION x, y;
613     POSITION xval, yval;
614     POSITION xoffset, yoffset;
615     int transno;
616
617     /* Pick a lesser vault */
618     for (dummy = 0; dummy < SAFE_MAX_ATTEMPTS; dummy++) {
619         /* Access a random vault record */
620         v_ptr = &v_info[randint0(max_v_idx)];
621
622         /* Accept the first lesser vault */
623         if (v_ptr->typ == 7)
624             break;
625     }
626
627     /* No lesser vault found */
628     if (dummy >= SAFE_MAX_ATTEMPTS) {
629         msg_print_wizard(player_ptr, CHEAT_DUNGEON, _("小型固定Vaultを配置できませんでした。", "Could not place lesser vault."));
630         return FALSE;
631     }
632
633     /* pick type of transformation (0-7) */
634     transno = randint0(8);
635
636     /* calculate offsets */
637     x = v_ptr->wid;
638     y = v_ptr->hgt;
639
640     /* Some huge vault cannot be ratated to fit in the dungeon */
641     floor_type *floor_ptr = player_ptr->current_floor_ptr;
642     if (x + 2 > floor_ptr->height - 2) {
643         /* Forbid 90 or 270 degree ratation */
644         transno &= ~1;
645     }
646
647     coord_trans(&x, &y, 0, 0, transno);
648
649     if (x < 0) {
650         xoffset = -x - 1;
651     } else {
652         xoffset = 0;
653     }
654
655     if (y < 0) {
656         yoffset = -y - 1;
657     } else {
658         yoffset = 0;
659     }
660
661     /* Find and reserve some space in the dungeon.  Get center of room. */
662     if (!find_space(player_ptr, &yval, &xval, abs(y), abs(x)))
663         return FALSE;
664
665     msg_format_wizard(player_ptr, CHEAT_DUNGEON, _("小型Vault(%s)を生成しました。", "Lesser vault (%s)."), v_name + v_ptr->name);
666
667     /* Hack -- Build the vault */
668     build_vault(player_ptr, yval, xval, v_ptr->hgt, v_ptr->wid, v_text + v_ptr->text, xoffset, yoffset, transno);
669
670     return TRUE;
671 }
672
673 /*!
674  * @brief タイプ8の部屋…v_info.txtより大型vaultを生成する / Type 8 -- greater vaults (see "v_info.txt")
675  * @return なし
676  */
677 bool build_type8(player_type *player_ptr)
678 {
679     vault_type *v_ptr;
680     int dummy;
681     POSITION xval, yval;
682     POSITION x, y;
683     int transno;
684     POSITION xoffset, yoffset;
685
686     /* Pick a greater vault */
687     for (dummy = 0; dummy < SAFE_MAX_ATTEMPTS; dummy++) {
688         /* Access a random vault record */
689         v_ptr = &v_info[randint0(max_v_idx)];
690
691         /* Accept the first greater vault */
692         if (v_ptr->typ == 8)
693             break;
694     }
695
696     /* No greater vault found */
697     if (dummy >= SAFE_MAX_ATTEMPTS) {
698         msg_print_wizard(player_ptr, CHEAT_DUNGEON, _("大型固定Vaultを配置できませんでした。", "Could not place greater vault."));
699         return FALSE;
700     }
701
702     /* pick type of transformation (0-7) */
703     transno = randint0(8);
704
705     /* calculate offsets */
706     x = v_ptr->wid;
707     y = v_ptr->hgt;
708
709     /* Some huge vault cannot be ratated to fit in the dungeon */
710     floor_type *floor_ptr = player_ptr->current_floor_ptr;
711     if (x + 2 > floor_ptr->height - 2) {
712         /* Forbid 90 or 270 degree ratation */
713         transno &= ~1;
714     }
715
716     coord_trans(&x, &y, 0, 0, transno);
717
718     if (x < 0) {
719         xoffset = -x - 1;
720     } else {
721         xoffset = 0;
722     }
723
724     if (y < 0) {
725         yoffset = -y - 1;
726     } else {
727         yoffset = 0;
728     }
729
730     /*
731      * Try to allocate space for room.  If fails, exit
732      *
733      * Hack -- Prepare a bit larger space (+2, +2) to
734      * prevent generation of vaults with no-entrance.
735      */
736     /* Find and reserve some space in the dungeon.  Get center of room. */
737     if (!find_space(player_ptr, &yval, &xval, (POSITION)(abs(y) + 2), (POSITION)(abs(x) + 2)))
738         return FALSE;
739
740     msg_format_wizard(player_ptr, CHEAT_DUNGEON, _("大型固定Vault(%s)を生成しました。", "Greater vault (%s)."), v_name + v_ptr->name);
741
742     /* Hack -- Build the vault */
743     build_vault(player_ptr, yval, xval, v_ptr->hgt, v_ptr->wid, v_text + v_ptr->text, xoffset, yoffset, transno);
744
745     return TRUE;
746 }
747
748 /*
749  * Build target vault.
750  * This is made by two concentric "crypts" with perpendicular
751  * walls creating the cross-hairs.
752  */
753 static void build_target_vault(player_type *player_ptr, POSITION x0, POSITION y0, POSITION xsize, POSITION ysize)
754 {
755     POSITION rad, x, y;
756
757     /* Make a random metric */
758     POSITION h1, h2, h3, h4;
759     h1 = randint1(32) - 16;
760     h2 = randint1(16);
761     h3 = randint1(32);
762     h4 = randint1(32) - 16;
763
764     msg_print_wizard(player_ptr, CHEAT_DUNGEON, _("対称形ランダムVaultを生成しました。", "Elemental Vault"));
765
766     /* work out outer radius */
767     if (xsize > ysize) {
768         rad = ysize / 2;
769     } else {
770         rad = xsize / 2;
771     }
772
773     /* Make floor */
774     floor_type *floor_ptr = player_ptr->current_floor_ptr;
775     for (x = x0 - rad; x <= x0 + rad; x++) {
776         for (y = y0 - rad; y <= y0 + rad; y++) {
777             /* clear room flag */
778             floor_ptr->grid_array[y][x].info &= ~(CAVE_ROOM);
779
780             /* Vault - so is "icky" */
781             floor_ptr->grid_array[y][x].info |= CAVE_ICKY;
782
783             if (dist2(y0, x0, y, x, h1, h2, h3, h4) <= rad - 1) {
784                 /* inside- so is floor */
785                 place_bold(player_ptr, y, x, GB_FLOOR);
786             } else {
787                 /* make granite outside so arena works */
788                 place_bold(player_ptr, y, x, GB_EXTRA);
789             }
790
791             /* proper boundary for arena */
792             if (((y + rad) == y0) || ((y - rad) == y0) || ((x + rad) == x0) || ((x - rad) == x0)) {
793                 place_bold(player_ptr, y, x, GB_EXTRA);
794             }
795         }
796     }
797
798     /* Find visible outer walls and set to be FEAT_OUTER */
799     add_outer_wall(player_ptr, x0, y0, FALSE, x0 - rad - 1, y0 - rad - 1, x0 + rad + 1, y0 + rad + 1);
800
801     /* Add inner wall */
802     for (x = x0 - rad / 2; x <= x0 + rad / 2; x++) {
803         for (y = y0 - rad / 2; y <= y0 + rad / 2; y++) {
804             if (dist2(y0, x0, y, x, h1, h2, h3, h4) == rad / 2) {
805                 /* Make an internal wall */
806                 place_bold(player_ptr, y, x, GB_INNER);
807             }
808         }
809     }
810
811     /* Add perpendicular walls */
812     for (x = x0 - rad; x <= x0 + rad; x++) {
813         place_bold(player_ptr, y0, x, GB_INNER);
814     }
815
816     for (y = y0 - rad; y <= y0 + rad; y++) {
817         place_bold(player_ptr, y, x0, GB_INNER);
818     }
819
820     /* Make inner vault */
821     for (y = y0 - 1; y <= y0 + 1; y++) {
822         place_bold(player_ptr, y, x0 - 1, GB_INNER);
823         place_bold(player_ptr, y, x0 + 1, GB_INNER);
824     }
825     for (x = x0 - 1; x <= x0 + 1; x++) {
826         place_bold(player_ptr, y0 - 1, x, GB_INNER);
827         place_bold(player_ptr, y0 + 1, x, GB_INNER);
828     }
829
830     place_bold(player_ptr, y0, x0, GB_FLOOR);
831
832     /* Add doors to vault */
833     /* get two distances so can place doors relative to centre */
834     x = (rad - 2) / 4 + 1;
835     y = rad / 2 + x;
836
837     add_door(player_ptr, x0 + x, y0);
838     add_door(player_ptr, x0 + y, y0);
839     add_door(player_ptr, x0 - x, y0);
840     add_door(player_ptr, x0 - y, y0);
841     add_door(player_ptr, x0, y0 + x);
842     add_door(player_ptr, x0, y0 + y);
843     add_door(player_ptr, x0, y0 - x);
844     add_door(player_ptr, x0, y0 - y);
845
846     /* Fill with stuff - medium difficulty */
847     fill_treasure(player_ptr, x0 - rad, x0 + rad, y0 - rad, y0 + rad, randint1(3) + 3);
848 }
849
850 /*
851  * This routine uses a modified version of the lake code to make a
852  * distribution of some terrain type over the vault.  This type
853  * depends on the dungeon depth.
854  *
855  * Miniture rooms are then scattered across the vault.
856  */
857 static void build_elemental_vault(player_type *player_ptr, POSITION x0, POSITION y0, POSITION xsiz, POSITION ysiz)
858 {
859     int grd, roug;
860     int c1, c2, c3;
861     bool done = FALSE;
862     POSITION xsize, ysize, xhsize, yhsize, x, y;
863     int i;
864     int type;
865
866     msg_print_wizard(player_ptr, CHEAT_DUNGEON, _("精霊界ランダムVaultを生成しました。", "Elemental Vault"));
867
868     /* round to make sizes even */
869     xhsize = xsiz / 2;
870     yhsize = ysiz / 2;
871     xsize = xhsize * 2;
872     ysize = yhsize * 2;
873
874     floor_type *floor_ptr = player_ptr->current_floor_ptr;
875     if (floor_ptr->dun_level < 25) {
876         /* Earth vault  (Rubble) */
877         type = LAKE_T_EARTH_VAULT;
878     } else if (floor_ptr->dun_level < 50) {
879         /* Air vault (Trees) */
880         type = LAKE_T_AIR_VAULT;
881     } else if (floor_ptr->dun_level < 75) {
882         /* Water vault (shallow water) */
883         type = LAKE_T_WATER_VAULT;
884     } else {
885         /* Fire vault (shallow lava) */
886         type = LAKE_T_FIRE_VAULT;
887     }
888
889     while (!done) {
890         /* testing values for these parameters: feel free to adjust */
891         grd = 1 << (randint0(3));
892
893         /* want average of about 16 */
894         roug = randint1(8) * randint1(4);
895
896         /* Make up size of various componants */
897         /* Floor */
898         c3 = 2 * xsize / 3;
899
900         /* Deep water/lava */
901         c1 = randint0(c3 / 2) + randint0(c3 / 2) - 5;
902
903         /* Shallow boundary */
904         c2 = (c1 + c3) / 2;
905
906         /* make it */
907         generate_hmap(floor_ptr, y0, x0, xsize, ysize, grd, roug, c3);
908
909         /* Convert to normal format+ clean up */
910         done = generate_lake(player_ptr, y0, x0, xsize, ysize, c1, c2, c3, type);
911     }
912
913     /* Set icky flag because is a vault */
914     for (x = 0; x <= xsize; x++) {
915         for (y = 0; y <= ysize; y++) {
916             floor_ptr->grid_array[y0 - yhsize + y][x0 - xhsize + x].info |= CAVE_ICKY;
917         }
918     }
919
920     /* make a few rooms in the vault */
921     for (i = 1; i <= (xsize * ysize) / 50; i++) {
922         build_small_room(player_ptr, x0 + randint0(xsize - 4) - xsize / 2 + 2, y0 + randint0(ysize - 4) - ysize / 2 + 2);
923     }
924
925     /* Fill with monsters and treasure, low difficulty */
926     fill_treasure(player_ptr, x0 - xhsize + 1, x0 - xhsize + xsize - 1, y0 - yhsize + 1, y0 - yhsize + ysize - 1, randint1(5));
927 }
928
929 /* Build a "mini" checkerboard vault
930  *
931  * This is done by making a permanent wall maze and setting
932  * the diagonal sqaures of the checker board to be granite.
933  * The vault has two entrances on opposite sides to guarantee
934  * a way to get in even if the vault abuts a side of the dungeon.
935  */
936 static void build_mini_c_vault(player_type *player_ptr, POSITION x0, POSITION y0, POSITION xsize, POSITION ysize)
937 {
938     POSITION dy, dx;
939     POSITION y1, x1, y2, x2, y, x, total;
940     int m, n, num_vertices;
941     int *visited;
942
943     msg_print_wizard(player_ptr, CHEAT_DUNGEON, _("小型チェッカーランダムVaultを生成しました。", "Mini Checker Board Vault."));
944
945     /* Pick a random room size */
946     dy = ysize / 2 - 1;
947     dx = xsize / 2 - 1;
948
949     y1 = y0 - dy;
950     x1 = x0 - dx;
951     y2 = y0 + dy;
952     x2 = x0 + dx;
953
954     /* generate the room */
955     floor_type *floor_ptr = player_ptr->current_floor_ptr;
956     for (x = x1 - 2; x <= x2 + 2; x++) {
957         if (!in_bounds(floor_ptr, y1 - 2, x))
958             break;
959
960         floor_ptr->grid_array[y1 - 2][x].info |= (CAVE_ROOM | CAVE_ICKY);
961
962         place_bold(player_ptr, y1 - 2, x, GB_OUTER_NOPERM);
963     }
964
965     for (x = x1 - 2; x <= x2 + 2; x++) {
966         if (!in_bounds(floor_ptr, y2 + 2, x))
967             break;
968
969         floor_ptr->grid_array[y2 + 2][x].info |= (CAVE_ROOM | CAVE_ICKY);
970
971         place_bold(player_ptr, y2 + 2, x, GB_OUTER_NOPERM);
972     }
973
974     for (y = y1 - 2; y <= y2 + 2; y++) {
975         if (!in_bounds(floor_ptr, y, x1 - 2))
976             break;
977
978         floor_ptr->grid_array[y][x1 - 2].info |= (CAVE_ROOM | CAVE_ICKY);
979
980         place_bold(player_ptr, y, x1 - 2, GB_OUTER_NOPERM);
981     }
982
983     for (y = y1 - 2; y <= y2 + 2; y++) {
984         if (!in_bounds(floor_ptr, y, x2 + 2))
985             break;
986
987         floor_ptr->grid_array[y][x2 + 2].info |= (CAVE_ROOM | CAVE_ICKY);
988
989         place_bold(player_ptr, y, x2 + 2, GB_OUTER_NOPERM);
990     }
991
992     for (y = y1 - 1; y <= y2 + 1; y++) {
993         for (x = x1 - 1; x <= x2 + 1; x++) {
994             grid_type *g_ptr = &floor_ptr->grid_array[y][x];
995
996             g_ptr->info |= (CAVE_ROOM | CAVE_ICKY);
997
998             /* Permanent walls */
999             place_grid(player_ptr, g_ptr, GB_INNER_PERM);
1000         }
1001     }
1002
1003     /* dimensions of vertex array */
1004     m = dx + 1;
1005     n = dy + 1;
1006     num_vertices = m * n;
1007
1008     /* initialize array of visited vertices */
1009     C_MAKE(visited, num_vertices, int);
1010
1011     /* traverse the graph to create a spannng tree, pick a random root */
1012     r_visit(player_ptr, y1, x1, y2, x2, randint0(num_vertices), 0, visited);
1013
1014     /* Make it look like a checker board vault */
1015     for (x = x1; x <= x2; x++) {
1016         for (y = y1; y <= y2; y++) {
1017             total = x - x1 + y - y1;
1018             /* If total is odd- and is a floor then make a wall */
1019             if ((total % 2 == 1) && is_floor_bold(floor_ptr, y, x)) {
1020                 place_bold(player_ptr, y, x, GB_INNER);
1021             }
1022         }
1023     }
1024
1025     /* Make a couple of entrances */
1026     if (one_in_(2)) {
1027         /* left and right */
1028         y = randint1(dy) + dy / 2;
1029         place_bold(player_ptr, y1 + y, x1 - 1, GB_INNER);
1030         place_bold(player_ptr, y1 + y, x2 + 1, GB_INNER);
1031     } else {
1032         /* top and bottom */
1033         x = randint1(dx) + dx / 2;
1034         place_bold(player_ptr, y1 - 1, x1 + x, GB_INNER);
1035         place_bold(player_ptr, y2 + 1, x1 + x, GB_INNER);
1036     }
1037
1038     /* Fill with monsters and treasure, highest difficulty */
1039     fill_treasure(player_ptr, x1, x2, y1, y2, 10);
1040
1041     C_KILL(visited, num_vertices, int);
1042 }
1043
1044 /* Build a castle */
1045 /* Driver routine: clear the region and call the recursive
1046  * room routine.
1047  *
1048  *This makes a vault that looks like a castle/ city in the dungeon.
1049  */
1050 static void build_castle_vault(player_type *player_ptr, POSITION x0, POSITION y0, POSITION xsize, POSITION ysize)
1051 {
1052     POSITION dy, dx;
1053     POSITION y1, x1, y2, x2;
1054     POSITION y, x;
1055
1056     /* Pick a random room size */
1057     dy = ysize / 2 - 1;
1058     dx = xsize / 2 - 1;
1059
1060     y1 = y0 - dy;
1061     x1 = x0 - dx;
1062     y2 = y0 + dy;
1063     x2 = x0 + dx;
1064
1065     msg_print_wizard(player_ptr, CHEAT_DUNGEON, _("城型ランダムVaultを生成しました。", "Castle Vault"));
1066
1067     /* generate the room */
1068     floor_type *floor_ptr = player_ptr->current_floor_ptr;
1069     for (y = y1 - 1; y <= y2 + 1; y++) {
1070         for (x = x1 - 1; x <= x2 + 1; x++) {
1071             floor_ptr->grid_array[y][x].info |= (CAVE_ROOM | CAVE_ICKY);
1072             /* Make everything a floor */
1073             place_bold(player_ptr, y, x, GB_FLOOR);
1074         }
1075     }
1076
1077     /* Make the castle */
1078     build_recursive_room(player_ptr, x1, y1, x2, y2, randint1(5));
1079
1080     /* Fill with monsters and treasure, low difficulty */
1081     fill_treasure(player_ptr, x1, x2, y1, y2, randint1(3));
1082 }
1083
1084 /*!
1085  * @brief タイプ10の部屋…ランダム生成vault / Type 10 -- Random vaults
1086  * @param player_ptr プレーヤーへの参照ポインタ
1087  * @return なし
1088  */
1089 bool build_type10(player_type *player_ptr)
1090 {
1091     POSITION y0, x0, xsize, ysize, vtype;
1092
1093     /* big enough to look good, small enough to be fairly common. */
1094     xsize = randint1(22) + 22;
1095     ysize = randint1(11) + 11;
1096
1097     /* Find and reserve some space in the dungeon.  Get center of room. */
1098     floor_type *floor_ptr = player_ptr->current_floor_ptr;
1099     if (!find_space(player_ptr, &y0, &x0, ysize + 1, xsize + 1))
1100         return FALSE;
1101
1102     /* Select type of vault */
1103     do {
1104         vtype = randint1(15);
1105     } while ((d_info[floor_ptr->dungeon_idx].flags1 & DF1_NO_CAVE) && ((vtype == 1) || (vtype == 3) || (vtype == 8) || (vtype == 9) || (vtype == 11)));
1106
1107     switch (vtype) {
1108         /* Build an appropriate room */
1109     case 1:
1110     case 9:
1111         build_bubble_vault(player_ptr, x0, y0, xsize, ysize);
1112         break;
1113     case 2:
1114     case 10:
1115         build_room_vault(player_ptr, x0, y0, xsize, ysize);
1116         break;
1117     case 3:
1118     case 11:
1119         build_cave_vault(player_ptr, x0, y0, xsize, ysize);
1120         break;
1121     case 4:
1122     case 12:
1123         build_maze_vault(player_ptr, x0, y0, xsize, ysize, TRUE);
1124         break;
1125     case 5:
1126     case 13:
1127         build_mini_c_vault(player_ptr, x0, y0, xsize, ysize);
1128         break;
1129     case 6:
1130     case 14:
1131         build_castle_vault(player_ptr, x0, y0, xsize, ysize);
1132         break;
1133     case 7:
1134     case 15:
1135         build_target_vault(player_ptr, x0, y0, xsize, ysize);
1136         break;
1137     case 8:
1138         build_elemental_vault(player_ptr, x0, y0, xsize, ysize);
1139         break;
1140         /* I know how to add a few more... give me some time. */
1141     default:
1142         return FALSE;
1143     }
1144
1145     return TRUE;
1146 }
1147
1148 /*!
1149  * @brief タイプ17の部屋…v_info.txtより固定特殊部屋を生成する / Type 17 -- fixed special room (see "v_info.txt")
1150  * @return なし
1151  */
1152 bool build_type17(player_type *player_ptr)
1153 {
1154     vault_type *v_ptr = NULL;
1155     int dummy;
1156     POSITION x, y;
1157     POSITION xval, yval;
1158     POSITION xoffset, yoffset;
1159     int transno;
1160
1161     /* Pick a lesser vault */
1162     for (dummy = 0; dummy < SAFE_MAX_ATTEMPTS; dummy++) {
1163         /* Access a random vault record */
1164         v_ptr = &v_info[randint0(max_v_idx)];
1165
1166         /* Accept the special fix room. */
1167         if (v_ptr->typ == 17)
1168             break;
1169     }
1170
1171     /* No lesser vault found */
1172     if (dummy >= SAFE_MAX_ATTEMPTS) {
1173         msg_print_wizard(player_ptr, CHEAT_DUNGEON, _("固定特殊部屋を配置できませんでした。", "Could not place fixed special room."));
1174         return FALSE;
1175     }
1176
1177     /* pick type of transformation (0-7) */
1178     transno = randint0(8);
1179
1180     /* calculate offsets */
1181     x = v_ptr->wid;
1182     y = v_ptr->hgt;
1183
1184     /* Some huge vault cannot be ratated to fit in the dungeon */
1185     floor_type *floor_ptr = player_ptr->current_floor_ptr;
1186     if (x + 2 > floor_ptr->height - 2) {
1187         /* Forbid 90 or 270 degree ratation */
1188         transno &= ~1;
1189     }
1190
1191     coord_trans(&x, &y, 0, 0, transno);
1192
1193     if (x < 0) {
1194         xoffset = -x - 1;
1195     } else {
1196         xoffset = 0;
1197     }
1198
1199     if (y < 0) {
1200         yoffset = -y - 1;
1201     } else {
1202         yoffset = 0;
1203     }
1204
1205     /* Find and reserve some space in the dungeon.  Get center of room. */
1206     if (!find_space(player_ptr, &yval, &xval, abs(y), abs(x)))
1207         return FALSE;
1208
1209     msg_format_wizard(player_ptr, CHEAT_DUNGEON, _("特殊固定部屋(%s)を生成しました。", "Special Fix room (%s)."), v_name + v_ptr->name);
1210
1211     /* Hack -- Build the vault */
1212     build_vault(player_ptr, yval, xval, v_ptr->hgt, v_ptr->wid, v_text + v_ptr->text, xoffset, yoffset, transno);
1213
1214     return TRUE;
1215 }