OSDN Git Service

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