OSDN Git Service

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