OSDN Git Service

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