OSDN Git Service

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