OSDN Git Service

[Refactor] #39076 "grid_array" の 置換処理で誤ったコメントを修正/削除. / Fix and delete wrong replaced...
[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(floor_ptr, 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(floor_ptr, 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(floor_ptr, 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(floor_ptr, 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(floor_ptr, y0 - yhsize + y, x0 - xhsize + x);
147                         }
148                         else
149                         {
150                                 /* middle of a bubble */
151                                 place_floor_bold(floor_ptr, 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(floor_ptr, 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(floor_ptr, 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(floor_ptr, 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 grid */
221 static void build_cave_vault(floor_type *floor_ptr, 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(floor_ptr, y0, x0, xsize, ysize, grd, roug, cutoff);
252
253                 /* Convert to normal format+ clean up */
254                 done = generate_fracave(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                         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(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(floor_ptr, 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(floor_ptr, 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(floor_ptr, y, x);
847                         }
848                         else
849                         {
850                                 /* make granite outside so arena works */
851                                 place_extra_bold(floor_ptr, 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(floor_ptr, y, x);
859                         }
860                 }
861         }
862
863         /* Find visible outer walls and set to be FEAT_OUTER */
864         add_outer_wall(floor_ptr, x0, y0, FALSE, x0 - rad - 1, y0 - rad - 1, x0 + rad + 1, y0 + rad + 1);
865
866         /* Add inner wall */
867         for (x = x0 - rad / 2; x <= x0 + rad / 2; x++)
868         {
869                 for (y = y0 - rad / 2; y <= y0 + rad / 2; y++)
870                 {
871                         if (dist2(y0, x0, y, x, h1, h2, h3, h4) == rad / 2)
872                         {
873                                 /* Make an internal wall */
874                                 place_inner_bold(floor_ptr, y, x);
875                         }
876                 }
877         }
878
879         /* Add perpendicular walls */
880         for (x = x0 - rad; x <= x0 + rad; x++)
881         {
882                 place_inner_bold(floor_ptr, y0, x);
883         }
884
885         for (y = y0 - rad; y <= y0 + rad; y++)
886         {
887                 place_inner_bold(floor_ptr, y, x0);
888         }
889
890         /* Make inner vault */
891         for (y = y0 - 1; y <= y0 + 1; y++)
892         {
893                 place_inner_bold(floor_ptr, y, x0 - 1);
894                 place_inner_bold(floor_ptr, y, x0 + 1);
895         }
896         for (x = x0 - 1; x <= x0 + 1; x++)
897         {
898                 place_inner_bold(floor_ptr, y0 - 1, x);
899                 place_inner_bold(floor_ptr, y0 + 1, x);
900         }
901
902         place_floor_bold(floor_ptr, y0, x0);
903
904
905         /* Add doors to vault */
906         /* get two distances so can place doors relative to centre */
907         x = (rad - 2) / 4 + 1;
908         y = rad / 2 + x;
909
910         add_door(floor_ptr, x0 + x, y0);
911         add_door(floor_ptr, x0 + y, y0);
912         add_door(floor_ptr, x0 - x, y0);
913         add_door(floor_ptr, x0 - y, y0);
914         add_door(floor_ptr, x0, y0 + x);
915         add_door(floor_ptr, x0, y0 + y);
916         add_door(floor_ptr, x0, y0 - x);
917         add_door(floor_ptr, x0, y0 - y);
918
919         /* Fill with stuff - medium difficulty */
920         fill_treasure(floor_ptr, x0 - rad, x0 + rad, y0 - rad, y0 + rad, randint1(3) + 3);
921 }
922
923
924 #ifdef ALLOW_CAVERNS_AND_LAKES
925 /*
926 * This routine uses a modified version of the lake code to make a
927 * distribution of some terrain type over the vault.  This type
928 * depends on the dungeon depth.
929 *
930 * Miniture rooms are then scattered across the vault.
931 */
932 static void build_elemental_vault(floor_type *floor_ptr, POSITION x0, POSITION y0, POSITION xsiz, POSITION ysiz)
933 {
934         int grd, roug;
935         int c1, c2, c3;
936         bool done = FALSE;
937         POSITION xsize, ysize, xhsize, yhsize, x, y;
938         int i;
939         int type;
940
941         msg_print_wizard(CHEAT_DUNGEON, _("精霊界ランダムVaultを生成しました。", "Elemental Vault"));
942
943         /* round to make sizes even */
944         xhsize = xsiz / 2;
945         yhsize = ysiz / 2;
946         xsize = xhsize * 2;
947         ysize = yhsize * 2;
948
949         if (floor_ptr->dun_level < 25)
950         {
951                 /* Earth vault  (Rubble) */
952                 type = LAKE_T_EARTH_VAULT;
953         }
954         else if (floor_ptr->dun_level < 50)
955         {
956                 /* Air vault (Trees) */
957                 type = LAKE_T_AIR_VAULT;
958         }
959         else if (floor_ptr->dun_level < 75)
960         {
961                 /* Water vault (shallow water) */
962                 type = LAKE_T_WATER_VAULT;
963         }
964         else
965         {
966                 /* Fire vault (shallow lava) */
967                 type = LAKE_T_FIRE_VAULT;
968         }
969
970         while (!done)
971         {
972                 /* testing values for these parameters: feel free to adjust */
973                 grd = 1 << (randint0(3));
974
975                 /* want average of about 16 */
976                 roug = randint1(8) * randint1(4);
977
978                 /* Make up size of various componants */
979                 /* Floor */
980                 c3 = 2 * xsize / 3;
981
982                 /* Deep water/lava */
983                 c1 = randint0(c3 / 2) + randint0(c3 / 2) - 5;
984
985                 /* Shallow boundary */
986                 c2 = (c1 + c3) / 2;
987
988                 /* make it */
989                 generate_hmap(floor_ptr, y0, x0, xsize, ysize, grd, roug, c3);
990
991                 /* Convert to normal format+ clean up */
992                 done = generate_lake(floor_ptr, y0, x0, xsize, ysize, c1, c2, c3, type);
993         }
994
995         /* Set icky flag because is a vault */
996         for (x = 0; x <= xsize; x++)
997         {
998                 for (y = 0; y <= ysize; y++)
999                 {
1000                         floor_ptr->grid_array[y0 - yhsize + y][x0 - xhsize + x].info |= CAVE_ICKY;
1001                 }
1002         }
1003
1004         /* make a few rooms in the vault */
1005         for (i = 1; i <= (xsize * ysize) / 50; i++)
1006         {
1007                 build_small_room(floor_ptr, x0 + randint0(xsize - 4) - xsize / 2 + 2,
1008                         y0 + randint0(ysize - 4) - ysize / 2 + 2);
1009         }
1010
1011         /* Fill with monsters and treasure, low difficulty */
1012         fill_treasure(floor_ptr, x0 - xhsize + 1, x0 - xhsize + xsize - 1,
1013                 y0 - yhsize + 1, y0 - yhsize + ysize - 1, randint1(5));
1014 }
1015 #endif /* ALLOW_CAVERNS_AND_LAKES */
1016
1017
1018 /* Build a "mini" checkerboard vault
1019 *
1020 * This is done by making a permanent wall maze and setting
1021 * the diagonal sqaures of the checker board to be granite.
1022 * The vault has two entrances on opposite sides to guarantee
1023 * a way to get in even if the vault abuts a side of the dungeon.
1024 */
1025 static void build_mini_c_vault(floor_type *floor_ptr, POSITION x0, POSITION y0, POSITION xsize, POSITION ysize)
1026 {
1027         POSITION dy, dx;
1028         POSITION y1, x1, y2, x2, y, x, total;
1029         int m, n, num_vertices;
1030         int *visited;
1031
1032         msg_print_wizard(CHEAT_DUNGEON, _("小型チェッカーランダムVaultを生成しました。", "Mini Checker Board Vault."));
1033
1034         /* Pick a random room size */
1035         dy = ysize / 2 - 1;
1036         dx = xsize / 2 - 1;
1037
1038         y1 = y0 - dy;
1039         x1 = x0 - dx;
1040         y2 = y0 + dy;
1041         x2 = x0 + dx;
1042
1043
1044         /* generate the room */
1045         for (x = x1 - 2; x <= x2 + 2; x++)
1046         {
1047                 if (!in_bounds(floor_ptr, y1 - 2, x)) break;
1048
1049                 floor_ptr->grid_array[y1 - 2][x].info |= (CAVE_ROOM | CAVE_ICKY);
1050
1051                 place_outer_noperm_bold(floor_ptr, y1 - 2, x);
1052         }
1053
1054         for (x = x1 - 2; x <= x2 + 2; x++)
1055         {
1056                 if (!in_bounds(floor_ptr, y2 + 2, x)) break;
1057
1058                 floor_ptr->grid_array[y2 + 2][x].info |= (CAVE_ROOM | CAVE_ICKY);
1059
1060                 place_outer_noperm_bold(floor_ptr, y2 + 2, x);
1061         }
1062
1063         for (y = y1 - 2; y <= y2 + 2; y++)
1064         {
1065                 if (!in_bounds(floor_ptr, y, x1 - 2)) break;
1066
1067                 floor_ptr->grid_array[y][x1 - 2].info |= (CAVE_ROOM | CAVE_ICKY);
1068
1069                 place_outer_noperm_bold(floor_ptr, y, x1 - 2);
1070         }
1071
1072         for (y = y1 - 2; y <= y2 + 2; y++)
1073         {
1074                 if (!in_bounds(floor_ptr, y, x2 + 2)) break;
1075
1076                 floor_ptr->grid_array[y][x2 + 2].info |= (CAVE_ROOM | CAVE_ICKY);
1077
1078                 place_outer_noperm_bold(floor_ptr, y, x2 + 2);
1079         }
1080
1081         for (y = y1 - 1; y <= y2 + 1; y++)
1082         {
1083                 for (x = x1 - 1; x <= x2 + 1; x++)
1084                 {
1085                         grid_type *g_ptr = &floor_ptr->grid_array[y][x];
1086
1087                         g_ptr->info |= (CAVE_ROOM | CAVE_ICKY);
1088
1089                         /* Permanent walls */
1090                         place_inner_perm_grid(g_ptr);
1091                 }
1092         }
1093
1094
1095         /* dimensions of vertex array */
1096         m = dx + 1;
1097         n = dy + 1;
1098         num_vertices = m * n;
1099
1100         /* initialize array of visited vertices */
1101         C_MAKE(visited, num_vertices, int);
1102
1103         /* traverse the graph to create a spannng tree, pick a random root */
1104         r_visit(floor_ptr, y1, x1, y2, x2, randint0(num_vertices), 0, visited);
1105
1106         /* Make it look like a checker board vault */
1107         for (x = x1; x <= x2; x++)
1108         {
1109                 for (y = y1; y <= y2; y++)
1110                 {
1111                         total = x - x1 + y - y1;
1112                         /* If total is odd- and is a floor then make a wall */
1113                         if ((total % 2 == 1) && is_floor_bold(floor_ptr, y, x))
1114                         {
1115                                 place_inner_bold(floor_ptr, y, x);
1116                         }
1117                 }
1118         }
1119
1120         /* Make a couple of entrances */
1121         if (one_in_(2))
1122         {
1123                 /* left and right */
1124                 y = randint1(dy) + dy / 2;
1125                 place_inner_bold(floor_ptr, y1 + y, x1 - 1);
1126                 place_inner_bold(floor_ptr, y1 + y, x2 + 1);
1127         }
1128         else
1129         {
1130                 /* top and bottom */
1131                 x = randint1(dx) + dx / 2;
1132                 place_inner_bold(floor_ptr, y1 - 1, x1 + x);
1133                 place_inner_bold(floor_ptr, y2 + 1, x1 + x);
1134         }
1135
1136         /* Fill with monsters and treasure, highest difficulty */
1137         fill_treasure(floor_ptr, x1, x2, y1, y2, 10);
1138
1139         C_KILL(visited, num_vertices, int);
1140 }
1141
1142 /* Build a castle */
1143 /* Driver routine: clear the region and call the recursive
1144 * room routine.
1145 *
1146 *This makes a vault that looks like a castle/ city in the dungeon.
1147 */
1148 static void build_castle_vault(floor_type *floor_ptr, POSITION x0, POSITION y0, POSITION xsize, POSITION ysize)
1149 {
1150         POSITION dy, dx;
1151         POSITION y1, x1, y2, x2;
1152         POSITION y, x;
1153
1154         /* Pick a random room size */
1155         dy = ysize / 2 - 1;
1156         dx = xsize / 2 - 1;
1157
1158         y1 = y0 - dy;
1159         x1 = x0 - dx;
1160         y2 = y0 + dy;
1161         x2 = x0 + dx;
1162
1163         msg_print_wizard(CHEAT_DUNGEON, _("城型ランダムVaultを生成しました。", "Castle Vault"));
1164
1165         /* generate the room */
1166         for (y = y1 - 1; y <= y2 + 1; y++)
1167         {
1168                 for (x = x1 - 1; x <= x2 + 1; x++)
1169                 {
1170                         floor_ptr->grid_array[y][x].info |= (CAVE_ROOM | CAVE_ICKY);
1171                         /* Make everything a floor */
1172                         place_floor_bold(floor_ptr, y, x);
1173                 }
1174         }
1175
1176         /* Make the castle */
1177         build_recursive_room(floor_ptr, x1, y1, x2, y2, randint1(5));
1178
1179         /* Fill with monsters and treasure, low difficulty */
1180         fill_treasure(floor_ptr, x1, x2, y1, y2, randint1(3));
1181 }
1182
1183
1184
1185 /*!
1186 * @brief タイプ10の部屋…ランダム生成vault / Type 10 -- Random vaults
1187 * @return なし
1188 */
1189 bool build_type10(floor_type *floor_ptr)
1190 {
1191         POSITION y0, x0, xsize, ysize, vtype;
1192
1193         /* big enough to look good, small enough to be fairly common. */
1194         xsize = randint1(22) + 22;
1195         ysize = randint1(11) + 11;
1196
1197         /* Find and reserve some space in the dungeon.  Get center of room. */
1198         if (!find_space(&y0, &x0, ysize + 1, xsize + 1)) return FALSE;
1199
1200         /* Select type of vault */
1201 #ifdef ALLOW_CAVERNS_AND_LAKES
1202         do
1203         {
1204                 vtype = randint1(15);
1205         } while ((d_info[floor_ptr->dungeon_idx].flags1 & DF1_NO_CAVE) &&
1206                 ((vtype == 1) || (vtype == 3) || (vtype == 8) || (vtype == 9) || (vtype == 11)));
1207 #else /* ALLOW_CAVERNS_AND_LAKES */
1208         do
1209         {
1210                 vtype = randint1(7);
1211         } while ((d_info[floor_ptr->dungeon_idx].flags1 & DF1_NO_CAVE) &&
1212                 ((vtype == 1) || (vtype == 3)));
1213 #endif /* ALLOW_CAVERNS_AND_LAKES */
1214
1215         switch (vtype)
1216         {
1217                 /* Build an appropriate room */
1218         case 1: case  9: build_bubble_vault(floor_ptr, x0, y0, xsize, ysize); break;
1219         case 2: case 10: build_room_vault(floor_ptr, x0, y0, xsize, ysize); break;
1220         case 3: case 11: build_cave_vault(floor_ptr, x0, y0, xsize, ysize); break;
1221         case 4: case 12: build_maze_vault(floor_ptr, x0, y0, xsize, ysize, TRUE); break;
1222         case 5: case 13: build_mini_c_vault(floor_ptr, x0, y0, xsize, ysize); break;
1223         case 6: case 14: build_castle_vault(floor_ptr, x0, y0, xsize, ysize); break;
1224         case 7: case 15: build_target_vault(floor_ptr, x0, y0, xsize, ysize); break;
1225 #ifdef ALLOW_CAVERNS_AND_LAKES
1226         case 8: build_elemental_vault(floor_ptr, x0, y0, xsize, ysize); break;
1227 #endif /* ALLOW_CAVERNS_AND_LAKES */
1228                 /* I know how to add a few more... give me some time. */
1229         default: return FALSE;
1230         }
1231
1232         return TRUE;
1233 }
1234
1235
1236 /*!
1237 * @brief タイプ17の部屋…v_info.txtより固定特殊部屋を生成する / Type 17 -- fixed special room (see "v_info.txt")
1238 * @return なし
1239 */
1240 bool build_type17(floor_type *floor_ptr)
1241 {
1242         vault_type *v_ptr = NULL;
1243         int dummy;
1244         POSITION x, y;
1245         POSITION xval, yval;
1246         POSITION xoffset, yoffset;
1247         int transno;
1248
1249         /* Pick a lesser vault */
1250         for (dummy = 0; dummy < SAFE_MAX_ATTEMPTS; dummy++)
1251         {
1252                 /* Access a random vault record */
1253                 v_ptr = &v_info[randint0(max_v_idx)];
1254
1255                 /* Accept the special fix room. */
1256                 if (v_ptr->typ == 17) break;
1257         }
1258
1259         /* No lesser vault found */
1260         if (dummy >= SAFE_MAX_ATTEMPTS)
1261         {
1262                 msg_print_wizard(CHEAT_DUNGEON, _("固定特殊部屋を配置できませんでした。", "Could not place fixed special room."));
1263                 return FALSE;
1264         }
1265
1266         /* pick type of transformation (0-7) */
1267         transno = randint0(8);
1268
1269         /* calculate offsets */
1270         x = v_ptr->wid;
1271         y = v_ptr->hgt;
1272
1273         /* Some huge vault cannot be ratated to fit in the dungeon */
1274         if (x + 2 > floor_ptr->height - 2)
1275         {
1276                 /* Forbid 90 or 270 degree ratation */
1277                 transno &= ~1;
1278         }
1279
1280         coord_trans(&x, &y, 0, 0, transno);
1281
1282         if (x < 0)
1283         {
1284                 xoffset = -x - 1;
1285         }
1286         else
1287         {
1288                 xoffset = 0;
1289         }
1290
1291         if (y < 0)
1292         {
1293                 yoffset = -y - 1;
1294         }
1295         else
1296         {
1297                 yoffset = 0;
1298         }
1299
1300         /* Find and reserve some space in the dungeon.  Get center of room. */
1301         if (!find_space(&yval, &xval, abs(y), abs(x))) return FALSE;
1302
1303 #ifdef FORCE_V_IDX
1304         v_ptr = &v_info[2];
1305 #endif
1306
1307         msg_format_wizard(CHEAT_DUNGEON, _("特殊固定部屋(%s)を生成しました。", "Special Fix room (%s)."), v_name + v_ptr->name);
1308
1309         /* Hack -- Build the vault */
1310         build_vault(floor_ptr, yval, xval, v_ptr->hgt, v_ptr->wid,
1311                 v_text + v_ptr->text, xoffset, yoffset, transno);
1312
1313         return TRUE;
1314 }
1315