OSDN Git Service

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