OSDN Git Service

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