OSDN Git Service

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