OSDN Git Service

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