OSDN Git Service

[Refactor] fire_ball() から fire_breath() へのリファクタリング漏れ修正。 / Refactor non-renamed fire_b...
[hengband/hengband.git] / src / rooms.c
1 /*!
2  * @file rooms.c
3  * @brief ダンジョンフロアの部屋生成処理 / make rooms. Used by generate.c when creating dungeons.
4  * @date 2014/01/06
5  * @author
6  * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke\n
7  * This software may be copied and distributed for educational, research,\n
8  * and not for profit purposes provided that this copyright and statement\n
9  * are included in all such copies.  Other copyrights may also apply.\n
10  * 2014 Deskull rearranged comment for Doxygen. \n
11  * @details
12  * Room building routines.\n
13  *\n
14  * Room types:\n
15  *   1 -- normal\n
16  *   2 -- overlapping\n
17  *   3 -- cross shaped\n
18  *   4 -- large room with features\n
19  *   5 -- monster nests\n
20  *   6 -- monster pits\n
21  *   7 -- simple vaults\n
22  *   8 -- greater vaults\n
23  *   9 -- fractal caves\n
24  *  10 -- random vaults\n
25  *  11 -- circular rooms\n
26  *  12 -- crypts\n
27  *  13 -- trapped monster pits\n
28  *  14 -- trapped room\n
29  *  15 -- glass room\n
30  *  16 -- underground arcade\n
31  *\n
32  * Some functions are used to determine if the given monster\n
33  * is appropriate for inclusion in a monster nest or monster pit or\n
34  * the given type.\n
35  *\n
36  * None of the pits/nests are allowed to include "unique" monsters.\n
37  */
38
39 #include "angband.h"
40 #include "generate.h"
41 #include "grid.h"
42 #include "rooms.h"
43
44 #include "rooms_normal.h"
45
46
47 /*!
48  * 各部屋タイプの生成比定義
49  *[from SAngband (originally from OAngband)]\n
50  *\n
51  * Table of values that control how many times each type of room will\n
52  * appear.  Each type of room has its own row, and each column\n
53  * corresponds to dungeon levels 0, 10, 20, and so on.  The final\n
54  * value is the minimum depth the room can appear at.  -LM-\n
55  *\n
56  * Level 101 and below use the values for level 100.\n
57  *\n
58  * Rooms with lots of monsters or loot may not be generated if the\n
59  * object or monster lists are already nearly full.  Rooms will not\n
60  * appear above their minimum depth.  Tiny levels will not have space\n
61  * for all the rooms you ask for.\n
62  */
63 static room_info_type room_info_normal[ROOM_T_MAX] =
64 {
65         /* Depth */
66         /*  0  10  20  30  40  50  60  70  80  90 100  min limit */
67
68         {{999,900,800,700,600,500,400,300,200,100,  0},  0}, /*NORMAL   */
69         {{  1, 10, 20, 30, 40, 50, 60, 70, 80, 90,100},  1}, /*OVERLAP  */
70         {{  1, 10, 20, 30, 40, 50, 60, 70, 80, 90,100},  3}, /*CROSS    */
71         {{  1, 10, 20, 30, 40, 50, 60, 70, 80, 90,100},  3}, /*INNER_F  */
72         {{  0,  1,  1,  1,  2,  3,  5,  6,  8, 10, 13}, 10}, /*NEST     */
73         {{  0,  1,  1,  2,  3,  4,  6,  8, 10, 13, 16}, 10}, /*PIT      */
74         {{  0,  1,  1,  1,  2,  2,  3,  5,  6,  8, 10}, 10}, /*LESSER_V */
75         {{  0,  0,  1,  1,  1,  2,  2,  2,  3,  3,  4}, 20}, /*GREATER_V*/
76         {{  0,100,200,300,400,500,600,700,800,900,999}, 10}, /*FRACAVE  */
77         {{  0,  1,  1,  1,  1,  1,  1,  1,  1,  2,  2}, 10}, /*RANDOM_V */
78         {{  0,  4,  8, 12, 16, 20, 24, 28, 32, 36, 40},  3}, /*OVAL     */
79         {{  1,  6, 12, 18, 24, 30, 36, 42, 48, 54, 60}, 10}, /*CRYPT    */
80         {{  0,  0,  1,  1,  1,  2,  3,  4,  5,  6,  8}, 20}, /*TRAP_PIT */
81         {{  0,  0,  1,  1,  1,  2,  3,  4,  5,  6,  8}, 20}, /*TRAP     */
82         {{  0,  0,  0,  0,  1,  1,  1,  2,  2,  2,  2}, 40}, /*GLASS    */
83         {{  1,  1,  1,  1,  1,  1,  1,  2,  2,  3,  3},  1}, /*ARCADE   */
84 };
85
86
87 /*! 部屋の生成処理順 / Build rooms in descending order of difficulty. */
88 static byte room_build_order[ROOM_T_MAX] = {
89         ROOM_T_GREATER_VAULT,
90         ROOM_T_ARCADE,
91         ROOM_T_RANDOM_VAULT,
92         ROOM_T_LESSER_VAULT,
93         ROOM_T_TRAP_PIT,
94         ROOM_T_PIT,
95         ROOM_T_NEST,
96         ROOM_T_TRAP,
97         ROOM_T_GLASS,
98         ROOM_T_INNER_FEAT,
99         ROOM_T_OVAL,
100         ROOM_T_CRYPT,
101         ROOM_T_OVERLAP,
102         ROOM_T_CROSS,
103         ROOM_T_FRACAVE,
104         ROOM_T_NORMAL,
105 };
106
107 /*!
108  * @brief 鍵のかかったドアを配置する
109  * @param y 配置したいフロアのY座標
110  * @param x 配置したいフロアのX座標
111  * @return なし
112  */
113 void place_locked_door(int y, int x)
114 {
115         if (d_info[dungeon_type].flags1 & DF1_NO_DOORS)
116         {
117                 place_floor_bold(y, x);
118         }
119         else
120         {
121                 set_cave_feat(y, x, feat_locked_door_random((d_info[dungeon_type].flags1 & DF1_GLASS_DOOR) ? DOOR_GLASS_DOOR : DOOR_DOOR));
122                 cave[y][x].info &= ~(CAVE_FLOOR);
123                 delete_monster(y, x);
124         }
125 }
126
127 /*!
128  * @brief 隠しドアを配置する
129  * @param y 配置したいフロアのY座標
130  * @param x 配置したいフロアのX座標
131  * @param type DOOR_DEFAULT / DOOR_DOOR / DOOR_GLASS_DOOR / DOOR_CURTAIN のいずれか
132  * @return なし
133  */
134 void place_secret_door(int y, int x, int type)
135 {
136         if (d_info[dungeon_type].flags1 & DF1_NO_DOORS)
137         {
138                 place_floor_bold(y, x);
139         }
140         else
141         {
142                 cave_type *c_ptr = &cave[y][x];
143
144                 if (type == DOOR_DEFAULT)
145                 {
146                         type = ((d_info[dungeon_type].flags1 & DF1_CURTAIN) &&
147                                 one_in_((d_info[dungeon_type].flags1 & DF1_NO_CAVE) ? 16 : 256)) ? DOOR_CURTAIN :
148                                 ((d_info[dungeon_type].flags1 & DF1_GLASS_DOOR) ? DOOR_GLASS_DOOR : DOOR_DOOR);
149                 }
150
151                 /* Create secret door */
152                 place_closed_door(y, x, type);
153
154                 if (type != DOOR_CURTAIN)
155                 {
156                         /* Hide by inner wall because this is used in rooms only */
157                         c_ptr->mimic = feat_wall_inner;
158
159                         /* Floor type terrain cannot hide a door */
160                         if (feat_supports_los(c_ptr->mimic) && !feat_supports_los(c_ptr->feat))
161                         {
162                                 if (have_flag(f_info[c_ptr->mimic].flags, FF_MOVE) || have_flag(f_info[c_ptr->mimic].flags, FF_CAN_FLY))
163                                 {
164                                         c_ptr->feat = one_in_(2) ? c_ptr->mimic : floor_type[randint0(100)];
165                                 }
166                                 c_ptr->mimic = 0;
167                         }
168                 }
169
170                 c_ptr->info &= ~(CAVE_FLOOR);
171                 delete_monster(y, x);
172         }
173 }
174
175 /*!
176  * @brief 1マスだけの部屋を作成し、上下左右いずれか一つに隠しドアを配置する。
177  * @param y0 配置したい中心のY座標
178  * @param x0 配置したい中心のX座標
179  * @details
180  * This funtion makes a very small room centred at (x0, y0)
181  * This is used in crypts, and random elemental vaults.
182  *
183  * Note - this should be used only on allocated regions
184  * within another room.
185  */
186 static void build_small_room(int x0, int y0)
187 {
188         int x, y;
189
190         for (y = y0 - 1; y <= y0 + 1; y++)
191         {
192                 place_inner_bold(y, x0 - 1);
193                 place_inner_bold(y, x0 + 1);
194         }
195
196         for (x = x0 - 1; x <= x0 + 1; x++)
197         {
198                 place_inner_bold(y0 - 1, x);
199                 place_inner_bold(y0 + 1, x);
200         }
201
202         /* Place a secret door on one side */
203         switch (randint0(4))
204         {
205                 case 0: place_secret_door(y0, x0 - 1, DOOR_DEFAULT); break;
206                 case 1: place_secret_door(y0, x0 + 1, DOOR_DEFAULT); break;
207                 case 2: place_secret_door(y0 - 1, x0, DOOR_DEFAULT); break;
208                 case 3: place_secret_door(y0 + 1, x0, DOOR_DEFAULT); break;
209         }
210
211         /* Clear mimic type */
212         cave[y0][x0].mimic = 0;
213
214         /* Add inner open space */
215         place_floor_bold(y0, x0);
216 }
217
218 /*!
219  * @brief
220  * 指定範囲に通路が通っていることを確認した上で床で埋める
221  * This function tunnels around a room if it will cut off part of a cave system.
222  * @param x1 範囲の左端
223  * @param y1 範囲の上端
224  * @param x2 範囲の右端
225  * @param y2 範囲の下端
226  * @return なし
227  */
228 static void check_room_boundary(int x1, int y1, int x2, int y2)
229 {
230         int count, x, y;
231         bool old_is_floor, new_is_floor;
232
233
234         /* Initialize */
235         count = 0;
236
237         old_is_floor = get_is_floor(x1 - 1, y1);
238
239         /*
240          * Count the number of floor-wall boundaries around the room
241          * Note: diagonal squares are ignored since the player can move diagonally
242          * to bypass these if needed.
243          */
244
245         /* Above the top boundary */
246         for (x = x1; x <= x2; x++)
247         {
248                 new_is_floor = get_is_floor(x, y1 - 1);
249
250                 /* Increment counter if they are different */
251                 if (new_is_floor != old_is_floor) count++;
252
253                 old_is_floor = new_is_floor;
254         }
255
256         /* Right boundary */
257         for (y = y1; y <= y2; y++)
258         {
259                 new_is_floor = get_is_floor(x2 + 1, y);
260
261                 /* increment counter if they are different */
262                 if (new_is_floor != old_is_floor) count++;
263
264                 old_is_floor = new_is_floor;
265         }
266
267         /* Bottom boundary */
268         for (x = x2; x >= x1; x--)
269         {
270                 new_is_floor = get_is_floor(x, y2 + 1);
271
272                 /* increment counter if they are different */
273                 if (new_is_floor != old_is_floor) count++;
274
275                 old_is_floor = new_is_floor;
276         }
277
278         /* Left boundary */
279         for (y = y2; y >= y1; y--)
280         {
281                 new_is_floor = get_is_floor(x1 - 1, y);
282
283                 /* increment counter if they are different */
284                 if (new_is_floor != old_is_floor) count++;
285
286                 old_is_floor = new_is_floor;
287         }
288
289         /* If all the same, or only one connection exit. */
290         if (count <= 2) return;
291
292
293         /* Tunnel around the room so to prevent problems with caves */
294         for (y = y1; y <= y2; y++)
295         {
296                 for (x = x1; x <= x2; x++)
297                 {
298                         set_floor(x, y);
299                 }
300         }
301 }
302
303
304 /*!
305  * @brief
306  * find_space()の予備処理として部屋の生成が可能かを判定する /
307  * Helper function for find_space(). Is this a good location?
308  * @param blocks_high 範囲の高さ
309  * @param blocks_wide 範囲の幅
310  * @param block_y 範囲の上端
311  * @param block_x 範囲の左端
312  * @return なし
313  */
314 static bool find_space_aux(int blocks_high, int blocks_wide, int block_y, int block_x)
315 {
316         int by1, bx1, by2, bx2, by, bx;
317
318         /* Itty-bitty rooms must shift about within their rectangle */
319         if (blocks_wide < 3)
320         {
321                 if ((blocks_wide == 2) && (block_x % 3) == 2)
322                         return FALSE;
323         }
324
325         /* Rooms with width divisible by 3 must be fitted to a rectangle. */
326         else if ((blocks_wide % 3) == 0)
327         {
328                 /* Must be aligned to the left edge of a 11x33 rectangle. */
329                 if ((block_x % 3) != 0)
330                         return FALSE;
331         }
332
333         /*
334          * Big rooms that do not have a width divisible by 3 must be
335          * aligned towards the edge of the dungeon closest to them.
336          */
337         else
338         {
339                 /* Shift towards left edge of dungeon. */
340                 if (block_x + (blocks_wide / 2) <= dun->col_rooms / 2)
341                 {
342                         if (((block_x % 3) == 2) && ((blocks_wide % 3) == 2))
343                                 return FALSE;
344                         if ((block_x % 3) == 1)
345                                 return FALSE;
346                 }
347
348                 /* Shift toward right edge of dungeon. */
349                 else
350                 {
351                         if (((block_x % 3) == 2) && ((blocks_wide % 3) == 2))
352                                 return FALSE;
353                         if ((block_x % 3) == 1)
354                                 return FALSE;
355                 }
356         }
357
358         /* Extract blocks */
359         by1 = block_y + 0;
360         bx1 = block_x + 0;
361         by2 = block_y + blocks_high;
362         bx2 = block_x + blocks_wide;
363
364         /* Never run off the screen */
365         if ((by1 < 0) || (by2 > dun->row_rooms)) return FALSE;
366         if ((bx1 < 0) || (bx2 > dun->col_rooms)) return FALSE;
367         
368         /* Verify available space */
369         for (by = by1; by < by2; by++)
370         {
371                 for (bx = bx1; bx < bx2; bx++)
372                 {
373                         if (dun->room_map[by][bx])
374                         {
375                                 return FALSE;
376                         }
377                 }
378         }
379
380         /* This location is okay */
381         return TRUE;
382 }
383
384
385 /*!
386  * @brief 部屋生成が可能なスペースを確保する / Find a good spot for the next room.  -LM-
387  * @param y 部屋の生成が可能な中心Y座標を返す参照ポインタ
388  * @param x 部屋の生成が可能な中心X座標を返す参照ポインタ
389  * @param height 確保したい領域の高さ
390  * @param width 確保したい領域の幅
391  * @return 所定の範囲が確保できた場合TRUEを返す
392  * @details
393  * Find and allocate a free space in the dungeon large enough to hold\n
394  * the room calling this function.\n
395  *\n
396  * We allocate space in 11x11 blocks, but want to make sure that rooms\n
397  * align neatly on the standard screen.  Therefore, we make them use\n
398  * blocks in few 11x33 rectangles as possible.\n
399  *\n
400  * Be careful to include the edges of the room in height and width!\n
401  *\n
402  * Return TRUE and values for the center of the room if all went well.\n
403  * Otherwise, return FALSE.\n
404  */
405 bool find_space(POSITION *y, POSITION *x, POSITION height, POSITION width)
406 {
407         int candidates, pick;
408         int by, bx, by1, bx1, by2, bx2;
409         int block_y = 0, block_x = 0;
410
411
412         /* Find out how many blocks we need. */
413         int blocks_high = 1 + ((height - 1) / BLOCK_HGT);
414         int blocks_wide = 1 + ((width - 1) / BLOCK_WID);
415
416         /* There are no way to allocate such huge space */
417         if (dun->row_rooms < blocks_high) return FALSE;
418         if (dun->col_rooms < blocks_wide) return FALSE;
419
420         /* Initiallize */
421         candidates = 0;
422
423         /* Count the number of valid places */
424         for (block_y = dun->row_rooms - blocks_high; block_y >= 0; block_y--)
425         {
426                 for (block_x = dun->col_rooms - blocks_wide; block_x >= 0; block_x--)
427                 {
428                         if (find_space_aux(blocks_high, blocks_wide, block_y, block_x))
429                         {
430                                 /* Find a valid place */
431                                 candidates++;
432                         }
433                 }
434         }
435
436         /* No place! */
437         if (!candidates)
438         {
439                 return FALSE;
440         }
441
442         /* Normal dungeon */
443         if (!(d_info[dungeon_type].flags1 & DF1_NO_CAVE))
444         {
445                 /* Choose a random one */
446                 pick = randint1(candidates);
447         }
448
449         /* NO_CAVE dungeon (Castle) */
450         else
451         {
452                 /* Always choose the center one */
453                 pick = candidates/2 + 1;
454         }
455
456         /* Pick up the choosen location */
457         for (block_y = dun->row_rooms - blocks_high; block_y >= 0; block_y--)
458         {
459                 for (block_x = dun->col_rooms - blocks_wide; block_x >= 0; block_x--)
460                 {
461                         if (find_space_aux(blocks_high, blocks_wide, block_y, block_x))
462                         {
463                                 pick--;
464
465                                 /* This one is picked? */
466                                 if (!pick) break;
467                         }
468                 }
469
470                 if (!pick) break;
471         }
472
473         /* Extract blocks */
474         by1 = block_y + 0;
475         bx1 = block_x + 0;
476         by2 = block_y + blocks_high;
477         bx2 = block_x + blocks_wide;
478
479         /*
480          * It is *extremely* important that the following calculation
481          * be *exactly* correct to prevent memory errors
482          */
483
484         /* Acquire the location of the room */
485         (*y) = ((by1 + by2) * BLOCK_HGT) / 2;
486         (*x) = ((bx1 + bx2) * BLOCK_WID) / 2;
487
488         /* Save the room location */
489         if (dun->cent_n < CENT_MAX)
490         {
491                 dun->cent[dun->cent_n].y = (byte_hack)*y;
492                 dun->cent[dun->cent_n].x = (byte_hack)*x;
493                 dun->cent_n++;
494         }
495
496         /* Reserve some blocks. */
497         for (by = by1; by < by2; by++)
498         {
499                 for (bx = bx1; bx < bx2; bx++)
500                 {
501                         dun->room_map[by][bx] = TRUE;
502                 }
503         }
504
505
506         /*
507          * Hack- See if room will cut off a cavern.
508          *
509          * If so, fix by tunneling outside the room in such a
510          * way as to connect the caves.
511          */
512         check_room_boundary(*x - width / 2 - 1, *y - height / 2 - 1, *x + (width - 1) / 2 + 1, *y + (height - 1) / 2 + 1);
513
514
515         /* Success. */
516         return TRUE;
517 }
518
519
520
521
522
523
524 /*!
525  * vaultに配置可能なモンスターの条件を指定するマクロ / Monster validation macro
526  *
527  * Line 1 -- forbid town monsters
528  * Line 2 -- forbid uniques
529  * Line 3 -- forbid aquatic monsters
530  */
531 #define vault_monster_okay(I) \
532         (mon_hook_dungeon(I) && \
533          !(r_info[I].flags1 & RF1_UNIQUE) && \
534          !(r_info[I].flags7 & RF7_UNIQUE2) && \
535          !(r_info[I].flagsr & RFR_RES_ALL) && \
536          !(r_info[I].flags7 & RF7_AQUATIC))
537
538
539 /*! 通常pit生成時のモンスターの構成条件ID / Race index for "monster pit (clone)" */
540 static int vault_aux_race;
541
542 /*! 単一シンボルpit生成時の指定シンボル / Race index for "monster pit (symbol clone)" */
543 static char vault_aux_char;
544
545 /*! ブレス属性に基づくドラゴンpit生成時条件マスク / Breath mask for "monster pit (dragon)" */
546 static u32b vault_aux_dragon_mask4;
547
548
549 /*!
550  * @brief モンスターがVault生成の最低必要条件を満たしているかを返す /
551  * Helper monster selection function
552  * @param r_idx 確認したいモンスター種族ID
553  * @return Vault生成の最低必要条件を満たしているならTRUEを返す。
554  */
555 static bool vault_aux_simple(MONRACE_IDX r_idx)
556 {
557         /* Okay */
558         return (vault_monster_okay(r_idx));
559 }
560
561
562 /*!
563  * @brief モンスターがゼリーnestの生成必要条件を満たしているかを返す /
564  * Helper function for "monster nest (jelly)"
565  * @param r_idx 確認したいモンスター種族ID
566  * @return 生成必要条件を満たしているならTRUEを返す。
567  */
568 static bool vault_aux_jelly(MONRACE_IDX r_idx)
569 {
570         monster_race *r_ptr = &r_info[r_idx];
571
572         /* Validate the monster */
573         if (!vault_monster_okay(r_idx)) return (FALSE);
574
575         if ((r_ptr->flags2 & RF2_KILL_BODY) && !(r_ptr->flags1 & RF1_NEVER_BLOW)) return (FALSE);
576
577         /* Also decline evil jellies (like death molds and shoggoths) */
578         if (r_ptr->flags3 & (RF3_EVIL)) return (FALSE);
579
580         /* Require icky thing, jelly, mold, or mushroom */
581         if (!my_strchr("ijm,", r_ptr->d_char)) return (FALSE);
582
583         /* Okay */
584         return (TRUE);
585 }
586
587 /*!
588  * @brief モンスターが動物nestの生成必要条件を満たしているかを返す /
589  * Helper function for "monster nest (animal)"
590  * @param r_idx 確認したいモンスター種族ID
591  * @return 生成必要条件を満たしているならTRUEを返す。
592  */
593 static bool vault_aux_animal(MONRACE_IDX r_idx)
594 {
595         monster_race *r_ptr = &r_info[r_idx];
596
597         /* Validate the monster */
598         if (!vault_monster_okay(r_idx)) return (FALSE);
599
600         /* Require "animal" flag */
601         if (!(r_ptr->flags3 & (RF3_ANIMAL))) return (FALSE);
602
603         /* Okay */
604         return (TRUE);
605 }
606
607
608 /*!
609  * @brief モンスターがアンデッドnestの生成必要条件を満たしているかを返す /
610  * Helper function for "monster nest (undead)"
611  * @param r_idx 確認したいモンスター種族ID
612  * @return 生成必要条件を満たしているならTRUEを返す。
613  */
614 static bool vault_aux_undead(MONRACE_IDX r_idx)
615 {
616         monster_race *r_ptr = &r_info[r_idx];
617
618         /* Validate the monster */
619         if (!vault_monster_okay(r_idx)) return (FALSE);
620
621         /* Require Undead */
622         if (!(r_ptr->flags3 & (RF3_UNDEAD))) return (FALSE);
623
624         /* Okay */
625         return (TRUE);
626 }
627
628 /*!
629  * @brief モンスターが聖堂nestの生成必要条件を満たしているかを返す /
630  * Helper function for "monster nest (chapel)"
631  * @param r_idx 確認したいモンスター種族ID
632  * @return 生成必要条件を満たしているならTRUEを返す。
633  */
634 static bool vault_aux_chapel_g(MONRACE_IDX r_idx)
635 {
636         static int chapel_list[] = {
637                 MON_NOV_PRIEST, MON_NOV_PALADIN, MON_NOV_PRIEST_G, MON_NOV_PALADIN_G, 
638                 MON_PRIEST, MON_JADE_MONK, MON_IVORY_MONK, MON_ULTRA_PALADIN, 
639                 MON_EBONY_MONK, MON_W_KNIGHT, MON_KNI_TEMPLAR, MON_PALADIN,
640                 MON_TOPAZ_MONK, 0};
641
642         int i;
643
644         monster_race *r_ptr = &r_info[r_idx];
645
646         /* Validate the monster */
647         if (!vault_monster_okay(r_idx)) return (FALSE);
648
649         if (r_ptr->flags3 & (RF3_EVIL)) return (FALSE);
650         if ((r_idx == MON_A_GOLD) || (r_idx == MON_A_SILVER)) return (FALSE);
651
652         /* Require "priest" or Angel */
653
654         if (r_ptr->d_char == 'A') return TRUE;
655
656         for (i = 0; chapel_list[i]; i++)
657                 if (r_idx == chapel_list[i]) return TRUE;
658
659         return FALSE;
660 }
661
662 /*!
663  * @brief モンスターが犬小屋nestの生成必要条件を満たしているかを返す /
664  * Helper function for "monster nest (kennel)"
665  * @param r_idx 確認したいモンスター種族ID
666  * @return 生成必要条件を満たしているならTRUEを返す。
667  */
668 static bool vault_aux_kennel(MONRACE_IDX r_idx)
669 {
670         monster_race *r_ptr = &r_info[r_idx];
671
672         /* Validate the monster */
673         if (!vault_monster_okay(r_idx)) return (FALSE);
674
675         /* Require a Zephyr Hound or a dog */
676         if (!my_strchr("CZ", r_ptr->d_char)) return (FALSE);
677   
678         /* Okay */
679         return (TRUE);
680 }
681
682 /*!
683  * @brief モンスターがミミックnestの生成必要条件を満たしているかを返す /
684  * Helper function for "monster nest (mimic)"
685  * @param r_idx 確認したいモンスター種族ID
686  * @return 生成必要条件を満たしているならTRUEを返す。
687  */
688 static bool vault_aux_mimic(MONRACE_IDX r_idx)
689 {
690         monster_race *r_ptr = &r_info[r_idx];
691
692         /* Validate the monster */
693         if (!vault_monster_okay(r_idx)) return (FALSE);
694
695         /* Require mimic */
696         if (!my_strchr("!$&(/=?[\\|", r_ptr->d_char)) return (FALSE);
697
698         /* Okay */
699         return (TRUE);
700 }
701
702 /*!
703  * @brief モンスターが単一クローンnestの生成必要条件を満たしているかを返す /
704  * Helper function for "monster nest (clone)"
705  * @param r_idx 確認したいモンスター種族ID
706  * @return 生成必要条件を満たしているならTRUEを返す。
707  */
708 static bool vault_aux_clone(MONRACE_IDX r_idx)
709 {
710         /* Validate the monster */
711         if (!vault_monster_okay(r_idx)) return (FALSE);
712
713         return (r_idx == vault_aux_race);
714 }
715
716
717 /*!
718  * @brief モンスターが邪悪属性シンボルクローンnestの生成必要条件を満たしているかを返す /
719  * Helper function for "monster nest (symbol clone)"
720  * @param r_idx 確認したいモンスター種族ID
721  * @return 生成必要条件を満たしているならTRUEを返す。
722  */
723 static bool vault_aux_symbol_e(MONRACE_IDX r_idx)
724 {
725         monster_race *r_ptr = &r_info[r_idx];
726
727         /* Validate the monster */
728         if (!vault_monster_okay(r_idx)) return (FALSE);
729
730         if ((r_ptr->flags2 & RF2_KILL_BODY) && !(r_ptr->flags1 & RF1_NEVER_BLOW)) return (FALSE);
731
732         if (r_ptr->flags3 & (RF3_GOOD)) return (FALSE);
733
734         /* Decline incorrect symbol */
735         if (r_ptr->d_char != vault_aux_char) return (FALSE);
736
737         /* Okay */
738         return (TRUE);
739 }
740
741
742 /*!
743  * @brief モンスターが善良属性シンボルクローンnestの生成必要条件を満たしているかを返す /
744  * Helper function for "monster nest (symbol clone)"
745  * @param r_idx 確認したいモンスター種族ID
746  * @return 生成必要条件を満たしているならTRUEを返す。
747  */
748 static bool vault_aux_symbol_g(MONRACE_IDX r_idx)
749 {
750         monster_race *r_ptr = &r_info[r_idx];
751
752         /* Validate the monster */
753         if (!vault_monster_okay(r_idx)) return (FALSE);
754
755         if ((r_ptr->flags2 & RF2_KILL_BODY) && !(r_ptr->flags1 & RF1_NEVER_BLOW)) return (FALSE);
756
757         if (r_ptr->flags3 & (RF3_EVIL)) return (FALSE);
758
759         /* Decline incorrect symbol */
760         if (r_ptr->d_char != vault_aux_char) return (FALSE);
761
762         /* Okay */
763         return (TRUE);
764 }
765
766
767 /*!
768  * @brief モンスターがオークpitの生成必要条件を満たしているかを返す /
769  * Helper function for "monster pit (orc)"
770  * @param r_idx 確認したいモンスター種族ID
771  * @return 生成必要条件を満たしているならTRUEを返す。
772  */
773 static bool vault_aux_orc(MONRACE_IDX r_idx)
774 {
775         monster_race *r_ptr = &r_info[r_idx];
776
777         /* Validate the monster */
778         if (!vault_monster_okay(r_idx)) return (FALSE);
779
780         /* Require orc */
781         if (!(r_ptr->flags3 & RF3_ORC)) return (FALSE);
782
783         /* Decline undead */
784         if (r_ptr->flags3 & RF3_UNDEAD) return (FALSE);
785
786         /* Okay */
787         return (TRUE);
788 }
789
790
791 /*!
792  * @brief モンスターがトロルpitの生成必要条件を満たしているかを返す /
793  * Helper function for "monster pit (troll)"
794  * @param r_idx 確認したいモンスター種族ID
795  * @return 生成必要条件を満たしているならTRUEを返す。
796  */
797 static bool vault_aux_troll(MONRACE_IDX r_idx)
798 {
799         monster_race *r_ptr = &r_info[r_idx];
800
801         /* Validate the monster */
802         if (!vault_monster_okay(r_idx)) return (FALSE);
803
804         /* Require troll */
805         if (!(r_ptr->flags3 & RF3_TROLL)) return (FALSE);
806
807         /* Decline undead */
808         if (r_ptr->flags3 & RF3_UNDEAD) return (FALSE);
809
810         /* Okay */
811         return (TRUE);
812 }
813
814
815 /*!
816  * @brief モンスターが巨人pitの生成必要条件を満たしているかを返す /
817  * Helper function for "monster pit (giant)"
818  * @param r_idx 確認したいモンスター種族ID
819  * @return 生成必要条件を満たしているならTRUEを返す。
820  */
821 static bool vault_aux_giant(MONRACE_IDX r_idx)
822 {
823         monster_race *r_ptr = &r_info[r_idx];
824
825         /* Validate the monster */
826         if (!vault_monster_okay(r_idx)) return (FALSE);
827
828         /* Require giant */
829         if (!(r_ptr->flags3 & RF3_GIANT)) return (FALSE);
830
831         if (r_ptr->flags3 & RF3_GOOD) return (FALSE);
832
833         /* Decline undead */
834         if (r_ptr->flags3 & RF3_UNDEAD) return (FALSE);
835
836         /* Okay */
837         return (TRUE);
838 }
839
840
841 /*!
842  * @brief モンスターがドラゴンpitの生成必要条件を満たしているかを返す /
843  * Helper function for "monster pit (dragon)"
844  * @param r_idx 確認したいモンスター種族ID
845  * @return 生成必要条件を満たしているならTRUEを返す。
846  */
847 static bool vault_aux_dragon(MONRACE_IDX r_idx)
848 {
849         monster_race *r_ptr = &r_info[r_idx];
850
851         /* Validate the monster */
852         if (!vault_monster_okay(r_idx)) return (FALSE);
853
854         /* Require dragon */
855         if (!(r_ptr->flags3 & RF3_DRAGON)) return (FALSE);
856
857         /* Hack -- Require correct "breath attack" */
858         if (r_ptr->flags4 != vault_aux_dragon_mask4) return (FALSE);
859
860         /* Decline undead */
861         if (r_ptr->flags3 & RF3_UNDEAD) return (FALSE);
862
863         /* Okay */
864         return (TRUE);
865 }
866
867
868 /*!
869  * @brief モンスターが悪魔pitの生成必要条件を満たしているかを返す /
870  * Helper function for "monster pit (demon)"
871  * @param r_idx 確認したいモンスター種族ID
872  * @return 生成必要条件を満たしているならTRUEを返す。
873  */
874 static bool vault_aux_demon(MONRACE_IDX r_idx)
875 {
876         monster_race *r_ptr = &r_info[r_idx];
877
878         /* Validate the monster */
879         if (!vault_monster_okay(r_idx)) return (FALSE);
880
881         if ((r_ptr->flags2 & RF2_KILL_BODY) && !(r_ptr->flags1 & RF1_NEVER_BLOW)) return (FALSE);
882
883         /* Require demon */
884         if (!(r_ptr->flags3 & RF3_DEMON)) return (FALSE);
885
886         /* Okay */
887         return (TRUE);
888 }
889
890
891 /*!
892  * @brief モンスターが狂気pitの生成必要条件を満たしているかを返す /
893  * Helper function for "monster pit (lovecraftian)"
894  * @param r_idx 確認したいモンスター種族ID
895  * @return 生成必要条件を満たしているならTRUEを返す。
896  */
897 static bool vault_aux_cthulhu(MONRACE_IDX r_idx)
898 {
899         monster_race *r_ptr = &r_info[r_idx];
900
901         /* Validate the monster */
902         if (!vault_monster_okay(r_idx)) return (FALSE);
903
904         if ((r_ptr->flags2 & RF2_KILL_BODY) && !(r_ptr->flags1 & RF1_NEVER_BLOW)) return (FALSE);
905
906         /* Require eldritch horror */
907         if (!(r_ptr->flags2 & (RF2_ELDRITCH_HORROR))) return (FALSE);
908
909         /* Okay */
910         return (TRUE);
911 }
912
913
914 /*!
915  * @brief pit/nestの基準となる単種モンスターを決める /
916  * @return なし
917  */
918 static void vault_prep_clone(void)
919 {
920         /* Apply the monster restriction */
921         get_mon_num_prep(vault_aux_simple, NULL);
922
923         /* Pick a race to clone */
924         vault_aux_race = get_mon_num(dun_level + 10);
925
926         /* Remove the monster restriction */
927         get_mon_num_prep(NULL, NULL);
928 }
929
930
931 /*!
932  * @brief pit/nestの基準となるモンスターシンボルを決める /
933  * @return なし
934  */
935 static void vault_prep_symbol(void)
936 {
937         MONRACE_IDX r_idx;
938
939         /* Apply the monster restriction */
940         get_mon_num_prep(vault_aux_simple, NULL);
941
942         /* Pick a race to clone */
943         r_idx = get_mon_num(dun_level + 10);
944
945         /* Remove the monster restriction */
946         get_mon_num_prep(NULL, NULL);
947
948         /* Extract the symbol */
949         vault_aux_char = r_info[r_idx].d_char;
950 }
951
952 /*!
953  * @brief pit/nestの基準となるドラゴンの種類を決める /
954  * @return なし
955  */
956 static void vault_prep_dragon(void)
957 {
958         /* Pick dragon type */
959         switch (randint0(6))
960         {
961                 /* Black */
962                 case 0:
963                 {
964                         /* Restrict dragon breath type */
965                         vault_aux_dragon_mask4 = RF4_BR_ACID;
966
967                         /* Done */
968                         break;
969                 }
970
971                 /* Blue */
972                 case 1:
973                 {
974                         /* Restrict dragon breath type */
975                         vault_aux_dragon_mask4 = RF4_BR_ELEC;
976
977                         /* Done */
978                         break;
979                 }
980
981                 /* Red */
982                 case 2:
983                 {
984                         /* Restrict dragon breath type */
985                         vault_aux_dragon_mask4 = RF4_BR_FIRE;
986
987                         /* Done */
988                         break;
989                 }
990
991                 /* White */
992                 case 3:
993                 {
994                         /* Restrict dragon breath type */
995                         vault_aux_dragon_mask4 = RF4_BR_COLD;
996
997                         /* Done */
998                         break;
999                 }
1000
1001                 /* Green */
1002                 case 4:
1003                 {
1004                         /* Restrict dragon breath type */
1005                         vault_aux_dragon_mask4 = RF4_BR_POIS;
1006
1007                         /* Done */
1008                         break;
1009                 }
1010
1011                 /* Multi-hued */
1012                 default:
1013                 {
1014                         /* Restrict dragon breath type */
1015                         vault_aux_dragon_mask4 = (RF4_BR_ACID | RF4_BR_ELEC |
1016                                                                                           RF4_BR_FIRE | RF4_BR_COLD |
1017                                                                                           RF4_BR_POIS);
1018
1019                         /* Done */
1020                         break;
1021                 }
1022         }
1023 }
1024
1025
1026 /*!
1027  * @brief モンスターがダークエルフpitの生成必要条件を満たしているかを返す /
1028  * Helper function for "monster pit (dark elf)"
1029  * @param r_idx 確認したいモンスター種族ID
1030  * @return 生成必要条件を満たしているならTRUEを返す。
1031  */
1032 static bool vault_aux_dark_elf(MONRACE_IDX r_idx)
1033 {
1034         int i;
1035         static int dark_elf_list[] =
1036         {
1037                 MON_D_ELF, MON_D_ELF_MAGE, MON_D_ELF_WARRIOR, MON_D_ELF_PRIEST,
1038                 MON_D_ELF_LORD, MON_D_ELF_WARLOCK, MON_D_ELF_DRUID, MON_NIGHTBLADE,
1039                 MON_D_ELF_SORC, MON_D_ELF_SHADE, 0,
1040         };
1041
1042         /* Validate the monster */
1043         if (!vault_monster_okay(r_idx)) return FALSE;
1044
1045         /* Require dark elves */
1046         for (i = 0; dark_elf_list[i]; i++)
1047                 if (r_idx == dark_elf_list[i]) return TRUE;
1048
1049         /* Assume not */
1050         return FALSE;
1051 }
1052
1053 /*! pit/nest型情報のtypedef */
1054 typedef struct vault_aux_type vault_aux_type;
1055
1056 /*! pit/nest型情報の構造体定義 */
1057 struct vault_aux_type
1058 {
1059         cptr name;
1060         bool (*hook_func)(MONRACE_IDX r_idx);
1061         void (*prep_func)(void);
1062         int level;
1063         int chance;
1064 };
1065
1066 /*!
1067  * @brief ダンジョン毎に指定されたピット配列を基準にランダムなpit/nestタイプを決める
1068  * @param l_ptr 選択されたpit/nest情報を返す参照ポインタ
1069  * @param allow_flag_mask 生成が許されるpit/nestのビット配列
1070  * @return 選択されたpit/nestのID、選択失敗した場合-1を返す。
1071  */
1072 static int pick_vault_type(vault_aux_type *l_ptr, s16b allow_flag_mask)
1073 {
1074         int tmp, total, count;
1075
1076         vault_aux_type *n_ptr;
1077
1078         /* Calculate the total possibilities */
1079         for (n_ptr = l_ptr, total = 0, count = 0; TRUE; n_ptr++, count++)
1080         {
1081                 /* Note end */
1082                 if (!n_ptr->name) break;
1083
1084                 /* Ignore excessive depth */
1085                 if (n_ptr->level > dun_level) continue;
1086
1087                 /* Not matched with pit/nest flag */
1088                 if (!(allow_flag_mask & (1L << count))) continue;
1089
1090                 /* Count this possibility */
1091                 total += n_ptr->chance * MAX_DEPTH / (MIN(dun_level, MAX_DEPTH - 1) - n_ptr->level + 5);
1092         }
1093
1094         /* Pick a random type */
1095         tmp = randint0(total);
1096
1097         /* Find this type */
1098         for (n_ptr = l_ptr, total = 0, count = 0; TRUE; n_ptr++, count++)
1099         {
1100                 /* Note end */
1101                 if (!n_ptr->name) break;
1102
1103                 /* Ignore excessive depth */
1104                 if (n_ptr->level > dun_level) continue;
1105
1106                 /* Not matched with pit/nest flag */
1107                 if (!(allow_flag_mask & (1L << count))) continue;
1108
1109                 /* Count this possibility */
1110                 total += n_ptr->chance * MAX_DEPTH / (MIN(dun_level, MAX_DEPTH - 1) - n_ptr->level + 5);
1111
1112                 /* Found the type */
1113                 if (tmp < total) break;
1114         }
1115
1116         return n_ptr->name ? count : -1;
1117 }
1118
1119 /*!nest情報テーブル*/
1120 static vault_aux_type nest_types[] =
1121 {
1122 #ifdef JP
1123         {"クローン",     vault_aux_clone,    vault_prep_clone,   5, 3},
1124         {"ゼリー",       vault_aux_jelly,    NULL,               5, 6},
1125         {"シンボル(善)", vault_aux_symbol_g, vault_prep_symbol, 25, 2},
1126         {"シンボル(悪)", vault_aux_symbol_e, vault_prep_symbol, 25, 2},
1127         {"ミミック",     vault_aux_mimic,    NULL,              30, 4},
1128         {"狂気",         vault_aux_cthulhu,  NULL,              70, 2},
1129         {"犬小屋",       vault_aux_kennel,   NULL,              45, 4},
1130         {"動物園",       vault_aux_animal,   NULL,              35, 5},
1131         {"教会",         vault_aux_chapel_g, NULL,              75, 4},
1132         {"アンデッド",   vault_aux_undead,   NULL,              75, 5},
1133         {NULL,           NULL,               NULL,               0, 0},
1134 #else
1135         {"clone",        vault_aux_clone,    vault_prep_clone,   5, 3},
1136         {"jelly",        vault_aux_jelly,    NULL,               5, 6},
1137         {"symbol good",  vault_aux_symbol_g, vault_prep_symbol, 25, 2},
1138         {"symbol evil",  vault_aux_symbol_e, vault_prep_symbol, 25, 2},
1139         {"mimic",        vault_aux_mimic,    NULL,              30, 4},
1140         {"lovecraftian", vault_aux_cthulhu,  NULL,              70, 2},
1141         {"kennel",       vault_aux_kennel,   NULL,              45, 4},
1142         {"animal",       vault_aux_animal,   NULL,              35, 5},
1143         {"chapel",       vault_aux_chapel_g, NULL,              75, 4},
1144         {"undead",       vault_aux_undead,   NULL,              75, 5},
1145         {NULL,           NULL,               NULL,               0, 0},
1146 #endif
1147 };
1148
1149 /*!pit情報テーブル*/
1150 static vault_aux_type pit_types[] =
1151 {
1152 #ifdef JP
1153         {"オーク",       vault_aux_orc,      NULL,               5, 6},
1154         {"トロル",       vault_aux_troll,    NULL,              20, 6},
1155         {"ジャイアント", vault_aux_giant,    NULL,              50, 6},
1156         {"狂気",         vault_aux_cthulhu,  NULL,              80, 2},
1157         {"シンボル(善)", vault_aux_symbol_g, vault_prep_symbol, 70, 1},
1158         {"シンボル(悪)", vault_aux_symbol_e, vault_prep_symbol, 70, 1},
1159         {"教会",         vault_aux_chapel_g, NULL,              65, 2},
1160         {"ドラゴン",     vault_aux_dragon,   vault_prep_dragon, 70, 6},
1161         {"デーモン",     vault_aux_demon,    NULL,              80, 6},
1162         {"ダークエルフ", vault_aux_dark_elf, NULL,              45, 4},
1163         {NULL,           NULL,               NULL,               0, 0},
1164 #else
1165         {"orc",          vault_aux_orc,      NULL,               5, 6},
1166         {"troll",        vault_aux_troll,    NULL,              20, 6},
1167         {"giant",        vault_aux_giant,    NULL,              50, 6},
1168         {"lovecraftian", vault_aux_cthulhu,  NULL,              80, 2},
1169         {"symbol good",  vault_aux_symbol_g, vault_prep_symbol, 70, 1},
1170         {"symbol evil",  vault_aux_symbol_e, vault_prep_symbol, 70, 1},
1171         {"chapel",       vault_aux_chapel_g, NULL,              65, 2},
1172         {"dragon",       vault_aux_dragon,   vault_prep_dragon, 70, 6},
1173         {"demon",        vault_aux_demon,    NULL,              80, 6},
1174         {"dark elf",     vault_aux_dark_elf, NULL,              45, 4},
1175         {NULL,           NULL,               NULL,               0, 0},
1176 #endif
1177 };
1178
1179
1180 /*! nestのID定義 /  Nest types code */
1181 #define NEST_TYPE_CLONE        0
1182 #define NEST_TYPE_JELLY        1
1183 #define NEST_TYPE_SYMBOL_GOOD  2
1184 #define NEST_TYPE_SYMBOL_EVIL  3
1185 #define NEST_TYPE_MIMIC        4
1186 #define NEST_TYPE_LOVECRAFTIAN 5
1187 #define NEST_TYPE_KENNEL       6
1188 #define NEST_TYPE_ANIMAL       7
1189 #define NEST_TYPE_CHAPEL       8
1190 #define NEST_TYPE_UNDEAD       9
1191
1192 /*! pitのID定義 / Pit types code */
1193 #define PIT_TYPE_ORC           0
1194 #define PIT_TYPE_TROLL         1
1195 #define PIT_TYPE_GIANT         2
1196 #define PIT_TYPE_LOVECRAFTIAN  3
1197 #define PIT_TYPE_SYMBOL_GOOD   4
1198 #define PIT_TYPE_SYMBOL_EVIL   5
1199 #define PIT_TYPE_CHAPEL        6
1200 #define PIT_TYPE_DRAGON        7
1201 #define PIT_TYPE_DEMON         8
1202 #define PIT_TYPE_DARK_ELF      9
1203
1204
1205 /*!
1206  * @brief デバッグ時に生成されたpit/nestの型を出力する処理
1207  * @param type pit/nestの型ID
1208  * @param nest TRUEならばnest、FALSEならばpit
1209  * @return デバッグ表示文字列の参照ポインタ
1210  * @details
1211  * Hack -- Get the string describing subtype of pit/nest
1212  * Determined in prepare function (some pit/nest only)
1213  */
1214 static cptr pit_subtype_string(int type, bool nest)
1215 {
1216         static char inner_buf[256] = "";
1217
1218         inner_buf[0] = '\0'; /* Init string */
1219
1220         if (nest) /* Nests */
1221         {
1222                 switch (type)
1223                 {
1224                 case NEST_TYPE_CLONE:
1225                         sprintf(inner_buf, "(%s)", r_name + r_info[vault_aux_race].name);
1226                         break;
1227                 case NEST_TYPE_SYMBOL_GOOD:
1228                 case NEST_TYPE_SYMBOL_EVIL:
1229                         sprintf(inner_buf, "(%c)", vault_aux_char);
1230                         break;
1231                 }
1232         }
1233         else /* Pits */
1234         {
1235                 switch (type)
1236                 {
1237                 case PIT_TYPE_SYMBOL_GOOD:
1238                 case PIT_TYPE_SYMBOL_EVIL:
1239                         sprintf(inner_buf, "(%c)", vault_aux_char);
1240                         break;
1241                 case PIT_TYPE_DRAGON:
1242                         switch (vault_aux_dragon_mask4)
1243                         {
1244 #ifdef JP
1245                         case RF4_BR_ACID: strcpy(inner_buf, "(酸)");   break;
1246                         case RF4_BR_ELEC: strcpy(inner_buf, "(稲妻)"); break;
1247                         case RF4_BR_FIRE: strcpy(inner_buf, "(火炎)"); break;
1248                         case RF4_BR_COLD: strcpy(inner_buf, "(冷気)"); break;
1249                         case RF4_BR_POIS: strcpy(inner_buf, "(毒)");   break;
1250                         case (RF4_BR_ACID | RF4_BR_ELEC | RF4_BR_FIRE | RF4_BR_COLD | RF4_BR_POIS):
1251                                 strcpy(inner_buf, "(万色)"); break;
1252                         default: strcpy(inner_buf, "(未定義)"); break;
1253 #else
1254                         case RF4_BR_ACID: strcpy(inner_buf, "(acid)");      break;
1255                         case RF4_BR_ELEC: strcpy(inner_buf, "(lightning)"); break;
1256                         case RF4_BR_FIRE: strcpy(inner_buf, "(fire)");      break;
1257                         case RF4_BR_COLD: strcpy(inner_buf, "(frost)");     break;
1258                         case RF4_BR_POIS: strcpy(inner_buf, "(poison)");    break;
1259                         case (RF4_BR_ACID | RF4_BR_ELEC | RF4_BR_FIRE | RF4_BR_COLD | RF4_BR_POIS):
1260                                 strcpy(inner_buf, "(multi-hued)"); break;
1261                         default: strcpy(inner_buf, "(undefined)"); break;
1262 #endif
1263                         }
1264                         break;
1265                 }
1266         }
1267
1268         return inner_buf;
1269 }
1270
1271
1272 /*! デバッグ時にnestのモンスター情報を確認するための構造体 / A struct for nest monster information with cheat_hear */
1273 typedef struct
1274 {
1275         s16b r_idx;
1276         bool used;
1277 }
1278 nest_mon_info_type;
1279
1280
1281 /*
1282  *! @brief nestのモンスターリストをソートするための関数 /
1283  *  Comp function for sorting nest monster information
1284  *  @param u ソート処理対象配列ポインタ
1285  *  @param v 未使用
1286  *  @param a 比較対象参照ID1
1287  *  @param b 比較対象参照ID2
1288  */
1289 static bool ang_sort_comp_nest_mon_info(vptr u, vptr v, int a, int b)
1290 {
1291         nest_mon_info_type *nest_mon_info = (nest_mon_info_type *)u;
1292         int w1 = nest_mon_info[a].r_idx;
1293         int w2 = nest_mon_info[b].r_idx;
1294         monster_race *r1_ptr = &r_info[w1];
1295         monster_race *r2_ptr = &r_info[w2];
1296         int z1, z2;
1297
1298         /* Unused */
1299         (void)v;
1300
1301         /* Extract used info */
1302         z1 = nest_mon_info[a].used;
1303         z2 = nest_mon_info[b].used;
1304
1305         /* Compare used status */
1306         if (z1 < z2) return FALSE;
1307         if (z1 > z2) return TRUE;
1308
1309         /* Compare levels */
1310         if (r1_ptr->level < r2_ptr->level) return TRUE;
1311         if (r1_ptr->level > r2_ptr->level) return FALSE;
1312
1313         /* Compare experience */
1314         if (r1_ptr->mexp < r2_ptr->mexp) return TRUE;
1315         if (r1_ptr->mexp > r2_ptr->mexp) return FALSE;
1316
1317         /* Compare indexes */
1318         return w1 <= w2;
1319 }
1320
1321 /*!
1322  * @brief nestのモンスターリストをスワップするための関数 /
1323  * Swap function for sorting nest monster information
1324  * @param u スワップ処理対象配列ポインタ
1325  * @param v 未使用
1326  * @param a スワップ対象参照ID1
1327  * @param b スワップ対象参照ID2
1328  */
1329 static void ang_sort_swap_nest_mon_info(vptr u, vptr v, int a, int b)
1330 {
1331         nest_mon_info_type *nest_mon_info = (nest_mon_info_type *)u;
1332         nest_mon_info_type holder;
1333
1334         /* Unused */
1335         (void)v;
1336
1337         /* Swap */
1338         holder = nest_mon_info[a];
1339         nest_mon_info[a] = nest_mon_info[b];
1340         nest_mon_info[b] = holder;
1341 }
1342
1343
1344 #define NUM_NEST_MON_TYPE 64 /*!<nestの種別数 */
1345
1346
1347 /*!
1348  * @brief タイプ5の部屋…nestを生成する / Type 5 -- Monster nests
1349  * @return なし
1350  * @details
1351  * A monster nest is a "big" room, with an "inner" room, containing\n
1352  * a "collection" of monsters of a given type strewn about the room.\n
1353  *\n
1354  * The monsters are chosen from a set of 64 randomly selected monster\n
1355  * races, to allow the nest creation to fail instead of having "holes".\n
1356  *\n
1357  * Note the use of the "get_mon_num_prep()" function, and the special\n
1358  * "get_mon_num_hook()" restriction function, to prepare the "monster\n
1359  * allocation table" in such a way as to optimize the selection of\n
1360  * "appropriate" non-unique monsters for the nest.\n
1361  *\n
1362  * Note that the "get_mon_num()" function may (rarely) fail, in which\n
1363  * case the nest will be empty.\n
1364  *\n
1365  * Note that "monster nests" will never contain "unique" monsters.\n
1366  */
1367 static bool build_type5(void)
1368 {
1369         POSITION y, x, y1, x1, y2, x2, xval, yval;
1370         int i;
1371         nest_mon_info_type nest_mon_info[NUM_NEST_MON_TYPE];
1372
1373         monster_type align;
1374
1375         cave_type *c_ptr;
1376
1377         int cur_nest_type = pick_vault_type(nest_types, d_info[dungeon_type].nest);
1378         vault_aux_type *n_ptr;
1379
1380         /* No type available */
1381         if (cur_nest_type < 0) return FALSE;
1382
1383         n_ptr = &nest_types[cur_nest_type];
1384
1385         /* Process a preparation function if necessary */
1386         if (n_ptr->prep_func) (*(n_ptr->prep_func))();
1387
1388         /* Prepare allocation table */
1389         get_mon_num_prep(n_ptr->hook_func, NULL);
1390
1391         align.sub_align = SUB_ALIGN_NEUTRAL;
1392
1393         /* Pick some monster types */
1394         for (i = 0; i < NUM_NEST_MON_TYPE; i++)
1395         {
1396                 MONRACE_IDX r_idx = 0;
1397                 int attempts = 100;
1398                 monster_race *r_ptr = NULL;
1399
1400                 while (attempts--)
1401                 {
1402                         /* Get a (hard) monster type */
1403                         r_idx = get_mon_num(dun_level + 11);
1404                         r_ptr = &r_info[r_idx];
1405
1406                         /* Decline incorrect alignment */
1407                         if (monster_has_hostile_align(&align, 0, 0, r_ptr)) continue;
1408
1409                         /* Accept this monster */
1410                         break;
1411                 }
1412
1413                 /* Notice failure */
1414                 if (!r_idx || !attempts) return FALSE;
1415
1416                 /* Note the alignment */
1417                 if (r_ptr->flags3 & RF3_EVIL) align.sub_align |= SUB_ALIGN_EVIL;
1418                 if (r_ptr->flags3 & RF3_GOOD) align.sub_align |= SUB_ALIGN_GOOD;
1419
1420                 nest_mon_info[i].r_idx = (s16b)r_idx;
1421                 nest_mon_info[i].used = FALSE;
1422         }
1423
1424         /* Find and reserve some space in the dungeon.  Get center of room. */
1425         if (!find_space(&yval, &xval, 11, 25)) return FALSE;
1426
1427         /* Large room */
1428         y1 = yval - 4;
1429         y2 = yval + 4;
1430         x1 = xval - 11;
1431         x2 = xval + 11;
1432
1433         /* Place the floor area */
1434         for (y = y1 - 1; y <= y2 + 1; y++)
1435         {
1436                 for (x = x1 - 1; x <= x2 + 1; x++)
1437                 {
1438                         c_ptr = &cave[y][x];
1439                         place_floor_grid(c_ptr);
1440                         c_ptr->info |= (CAVE_ROOM);
1441                 }
1442         }
1443
1444         /* Place the outer walls */
1445         for (y = y1 - 1; y <= y2 + 1; y++)
1446         {
1447                 c_ptr = &cave[y][x1 - 1];
1448                 place_outer_grid(c_ptr);
1449                 c_ptr = &cave[y][x2 + 1];
1450                 place_outer_grid(c_ptr);
1451         }
1452         for (x = x1 - 1; x <= x2 + 1; x++)
1453         {
1454                 c_ptr = &cave[y1 - 1][x];
1455                 place_outer_grid(c_ptr);
1456                 c_ptr = &cave[y2 + 1][x];
1457                 place_outer_grid(c_ptr);
1458         }
1459
1460
1461         /* Advance to the center room */
1462         y1 = y1 + 2;
1463         y2 = y2 - 2;
1464         x1 = x1 + 2;
1465         x2 = x2 - 2;
1466
1467         /* The inner walls */
1468         for (y = y1 - 1; y <= y2 + 1; y++)
1469         {
1470                 c_ptr = &cave[y][x1 - 1];
1471                 place_inner_grid(c_ptr);
1472                 c_ptr = &cave[y][x2 + 1];
1473                 place_inner_grid(c_ptr);
1474         }
1475
1476         for (x = x1 - 1; x <= x2 + 1; x++)
1477         {
1478                 c_ptr = &cave[y1 - 1][x];
1479                 place_inner_grid(c_ptr);
1480                 c_ptr = &cave[y2 + 1][x];
1481                 place_inner_grid(c_ptr);
1482         }
1483         for (y = y1; y <= y2; y++)
1484         {
1485                 for (x = x1; x <= x2; x++)
1486                 {
1487                         add_cave_info(y, x, CAVE_ICKY);
1488                 }
1489         }
1490
1491         /* Place a secret door */
1492         switch (randint1(4))
1493         {
1494                 case 1: place_secret_door(y1 - 1, xval, DOOR_DEFAULT); break;
1495                 case 2: place_secret_door(y2 + 1, xval, DOOR_DEFAULT); break;
1496                 case 3: place_secret_door(yval, x1 - 1, DOOR_DEFAULT); break;
1497                 case 4: place_secret_door(yval, x2 + 1, DOOR_DEFAULT); break;
1498         }
1499
1500         msg_format_wizard(CHEAT_DUNGEON, _("モンスター部屋(nest)(%s%s)を生成します。", "Monster nest (%s%s)"), n_ptr->name, pit_subtype_string(cur_nest_type, TRUE));
1501
1502         /* Place some monsters */
1503         for (y = yval - 2; y <= yval + 2; y++)
1504         {
1505                 for (x = xval - 9; x <= xval + 9; x++)
1506                 {
1507                         MONRACE_IDX r_idx;
1508
1509                         i = randint0(NUM_NEST_MON_TYPE);
1510                         r_idx = nest_mon_info[i].r_idx;
1511
1512                         /* Place that "random" monster (no groups) */
1513                         (void)place_monster_aux(0, y, x, r_idx, 0L);
1514
1515                         nest_mon_info[i].used = TRUE;
1516                 }
1517         }
1518
1519         if (cheat_room)
1520         {
1521                 ang_sort_comp = ang_sort_comp_nest_mon_info;
1522                 ang_sort_swap = ang_sort_swap_nest_mon_info;
1523                 ang_sort(nest_mon_info, NULL, NUM_NEST_MON_TYPE);
1524
1525                 /* Dump the entries (prevent multi-printing) */
1526                 for (i = 0; i < NUM_NEST_MON_TYPE; i++)
1527                 {
1528                         if (!nest_mon_info[i].used) break;
1529                         for (; i < NUM_NEST_MON_TYPE - 1; i++)
1530                         {
1531                                 if (nest_mon_info[i].r_idx != nest_mon_info[i + 1].r_idx) break;
1532                                 if (!nest_mon_info[i + 1].used) break;
1533                         }
1534                         msg_format_wizard(CHEAT_DUNGEON, "Nest構成モンスターNo.%d:%s", i, r_name + r_info[nest_mon_info[i].r_idx].name);
1535                 }
1536         }
1537
1538         return TRUE;
1539 }
1540
1541
1542 /*!
1543  * @brief タイプ6の部屋…pitを生成する / Type 6 -- Monster pits
1544  * @return なし
1545  * @details
1546  * A monster pit is a "big" room, with an "inner" room, containing\n
1547  * a "collection" of monsters of a given type organized in the room.\n
1548  *\n
1549  * The inside room in a monster pit appears as shown below, where the\n
1550  * actual monsters in each location depend on the type of the pit\n
1551  *\n
1552  *   XXXXXXXXXXXXXXXXXXXXX\n
1553  *   X0000000000000000000X\n
1554  *   X0112233455543322110X\n
1555  *   X0112233467643322110X\n
1556  *   X0112233455543322110X\n
1557  *   X0000000000000000000X\n
1558  *   XXXXXXXXXXXXXXXXXXXXX\n
1559  *\n
1560  * Note that the monsters in the pit are now chosen by using "get_mon_num()"\n
1561  * to request 16 "appropriate" monsters, sorting them by level, and using\n
1562  * the "even" entries in this sorted list for the contents of the pit.\n
1563  *\n
1564  * Hack -- all of the "dragons" in a "dragon" pit must be the same "color",\n
1565  * which is handled by requiring a specific "breath" attack for all of the\n
1566  * dragons.  This may include "multi-hued" breath.  Note that "wyrms" may\n
1567  * be present in many of the dragon pits, if they have the proper breath.\n
1568  *\n
1569  * Note the use of the "get_mon_num_prep()" function, and the special\n
1570  * "get_mon_num_hook()" restriction function, to prepare the "monster\n
1571  * allocation table" in such a way as to optimize the selection of\n
1572  * "appropriate" non-unique monsters for the pit.\n
1573  *\n
1574  * Note that the "get_mon_num()" function may (rarely) fail, in which case\n
1575  * the pit will be empty.\n
1576  *\n
1577  * Note that "monster pits" will never contain "unique" monsters.\n
1578  */
1579 static bool build_type6(void)
1580 {
1581         POSITION y, x, y1, x1, y2, x2, xval, yval;
1582         int i, j;
1583
1584         MONRACE_IDX what[16];
1585
1586         monster_type align;
1587
1588         cave_type *c_ptr;
1589
1590         int cur_pit_type = pick_vault_type(pit_types, d_info[dungeon_type].pit);
1591         vault_aux_type *n_ptr;
1592
1593         /* No type available */
1594         if (cur_pit_type < 0) return FALSE;
1595
1596         n_ptr = &pit_types[cur_pit_type];
1597
1598         /* Process a preparation function if necessary */
1599         if (n_ptr->prep_func) (*(n_ptr->prep_func))();
1600
1601         /* Prepare allocation table */
1602         get_mon_num_prep(n_ptr->hook_func, NULL);
1603
1604         align.sub_align = SUB_ALIGN_NEUTRAL;
1605
1606         /* Pick some monster types */
1607         for (i = 0; i < 16; i++)
1608         {
1609                 MONRACE_IDX r_idx = 0;
1610                 int attempts = 100;
1611                 monster_race *r_ptr = NULL;
1612
1613                 while (attempts--)
1614                 {
1615                         /* Get a (hard) monster type */
1616                         r_idx = get_mon_num(dun_level + 11);
1617                         r_ptr = &r_info[r_idx];
1618
1619                         /* Decline incorrect alignment */
1620                         if (monster_has_hostile_align(&align, 0, 0, r_ptr)) continue;
1621
1622                         /* Accept this monster */
1623                         break;
1624                 }
1625
1626                 /* Notice failure */
1627                 if (!r_idx || !attempts) return FALSE;
1628
1629                 /* Note the alignment */
1630                 if (r_ptr->flags3 & RF3_EVIL) align.sub_align |= SUB_ALIGN_EVIL;
1631                 if (r_ptr->flags3 & RF3_GOOD) align.sub_align |= SUB_ALIGN_GOOD;
1632
1633                 what[i] = r_idx;
1634         }
1635
1636         /* Find and reserve some space in the dungeon.  Get center of room. */
1637         if (!find_space(&yval, &xval, 11, 25)) return FALSE;
1638
1639         /* Large room */
1640         y1 = yval - 4;
1641         y2 = yval + 4;
1642         x1 = xval - 11;
1643         x2 = xval + 11;
1644
1645         /* Place the floor area */
1646         for (y = y1 - 1; y <= y2 + 1; y++)
1647         {
1648                 for (x = x1 - 1; x <= x2 + 1; x++)
1649                 {
1650                         c_ptr = &cave[y][x];
1651                         place_floor_grid(c_ptr);
1652                         c_ptr->info |= (CAVE_ROOM);
1653                 }
1654         }
1655
1656         /* Place the outer walls */
1657         for (y = y1 - 1; y <= y2 + 1; y++)
1658         {
1659                 c_ptr = &cave[y][x1 - 1];
1660                 place_outer_grid(c_ptr);
1661                 c_ptr = &cave[y][x2 + 1];
1662                 place_outer_grid(c_ptr);
1663         }
1664         for (x = x1 - 1; x <= x2 + 1; x++)
1665         {
1666                 c_ptr = &cave[y1 - 1][x];
1667                 place_outer_grid(c_ptr);
1668                 c_ptr = &cave[y2 + 1][x];
1669                 place_outer_grid(c_ptr);
1670         }
1671
1672         /* Advance to the center room */
1673         y1 = y1 + 2;
1674         y2 = y2 - 2;
1675         x1 = x1 + 2;
1676         x2 = x2 - 2;
1677
1678         /* The inner walls */
1679         for (y = y1 - 1; y <= y2 + 1; y++)
1680         {
1681                 c_ptr = &cave[y][x1 - 1];
1682                 place_inner_grid(c_ptr);
1683                 c_ptr = &cave[y][x2 + 1];
1684                 place_inner_grid(c_ptr);
1685         }
1686         for (x = x1 - 1; x <= x2 + 1; x++)
1687         {
1688                 c_ptr = &cave[y1 - 1][x];
1689                 place_inner_grid(c_ptr);
1690                 c_ptr = &cave[y2 + 1][x];
1691                 place_inner_grid(c_ptr);
1692         }
1693         for (y = y1; y <= y2; y++)
1694         {
1695                 for (x = x1; x <= x2; x++)
1696                 {
1697                         add_cave_info(y, x, CAVE_ICKY);
1698                 }
1699         }
1700
1701         /* Place a secret door */
1702         switch (randint1(4))
1703         {
1704                 case 1: place_secret_door(y1 - 1, xval, DOOR_DEFAULT); break;
1705                 case 2: place_secret_door(y2 + 1, xval, DOOR_DEFAULT); break;
1706                 case 3: place_secret_door(yval, x1 - 1, DOOR_DEFAULT); break;
1707                 case 4: place_secret_door(yval, x2 + 1, DOOR_DEFAULT); break;
1708         }
1709
1710         /* Sort the entries */
1711         for (i = 0; i < 16 - 1; i++)
1712         {
1713                 /* Sort the entries */
1714                 for (j = 0; j < 16 - 1; j++)
1715                 {
1716                         int i1 = j;
1717                         int i2 = j + 1;
1718
1719                         int p1 = r_info[what[i1]].level;
1720                         int p2 = r_info[what[i2]].level;
1721
1722                         /* Bubble */
1723                         if (p1 > p2)
1724                         {
1725                                 MONRACE_IDX tmp = what[i1];
1726                                 what[i1] = what[i2];
1727                                 what[i2] = tmp;
1728                         }
1729                 }
1730         }
1731
1732         msg_format_wizard(CHEAT_DUNGEON, _("モンスター部屋(pit)(%s%s)を生成します。", "Monster pit (%s%s)"), n_ptr->name, pit_subtype_string(cur_pit_type, FALSE));
1733
1734         /* Select the entries */
1735         for (i = 0; i < 8; i++)
1736         {
1737                 /* Every other entry */
1738                 what[i] = what[i * 2];
1739                 msg_format_wizard(CHEAT_DUNGEON, _("Nest構成モンスター選択No.%d:%s", "Nest Monster Select No.%d:%s"), i, r_name + r_info[what[i]].name);
1740         }
1741
1742         /* Top and bottom rows */
1743         for (x = xval - 9; x <= xval + 9; x++)
1744         {
1745                 place_monster_aux(0, yval - 2, x, what[0], PM_NO_KAGE);
1746                 place_monster_aux(0, yval + 2, x, what[0], PM_NO_KAGE);
1747         }
1748
1749         /* Middle columns */
1750         for (y = yval - 1; y <= yval + 1; y++)
1751         {
1752                 place_monster_aux(0, y, xval - 9, what[0], PM_NO_KAGE);
1753                 place_monster_aux(0, y, xval + 9, what[0], PM_NO_KAGE);
1754
1755                 place_monster_aux(0, y, xval - 8, what[1], PM_NO_KAGE);
1756                 place_monster_aux(0, y, xval + 8, what[1], PM_NO_KAGE);
1757
1758                 place_monster_aux(0, y, xval - 7, what[1], PM_NO_KAGE);
1759                 place_monster_aux(0, y, xval + 7, what[1], PM_NO_KAGE);
1760
1761                 place_monster_aux(0, y, xval - 6, what[2], PM_NO_KAGE);
1762                 place_monster_aux(0, y, xval + 6, what[2], PM_NO_KAGE);
1763
1764                 place_monster_aux(0, y, xval - 5, what[2], PM_NO_KAGE);
1765                 place_monster_aux(0, y, xval + 5, what[2], PM_NO_KAGE);
1766
1767                 place_monster_aux(0, y, xval - 4, what[3], PM_NO_KAGE);
1768                 place_monster_aux(0, y, xval + 4, what[3], PM_NO_KAGE);
1769
1770                 place_monster_aux(0, y, xval - 3, what[3], PM_NO_KAGE);
1771                 place_monster_aux(0, y, xval + 3, what[3], PM_NO_KAGE);
1772
1773                 place_monster_aux(0, y, xval - 2, what[4], PM_NO_KAGE);
1774                 place_monster_aux(0, y, xval + 2, what[4], PM_NO_KAGE);
1775         }
1776
1777         /* Above/Below the center monster */
1778         for (x = xval - 1; x <= xval + 1; x++)
1779         {
1780                 place_monster_aux(0, yval + 1, x, what[5], PM_NO_KAGE);
1781                 place_monster_aux(0, yval - 1, x, what[5], PM_NO_KAGE);
1782         }
1783
1784         /* Next to the center monster */
1785         place_monster_aux(0, yval, xval + 1, what[6], PM_NO_KAGE);
1786         place_monster_aux(0, yval, xval - 1, what[6], PM_NO_KAGE);
1787
1788         /* Center monster */
1789         place_monster_aux(0, yval, xval, what[7], PM_NO_KAGE);
1790
1791         return TRUE;
1792 }
1793
1794
1795 /*!
1796  * @brief Vault地形を回転、上下左右反転するための座標変換を返す / coordinate translation code
1797  * @param x 変換したい点のX座標参照ポインタ
1798  * @param y 変換したい点のY座標参照ポインタ
1799  * @param xoffset Vault生成時の基準X座標
1800  * @param yoffset Vault生成時の基準Y座標
1801  * @param transno 処理ID
1802  * @return なし
1803  */
1804 static void coord_trans(POSITION *x, POSITION *y, POSITION xoffset, POSITION yoffset, int transno)
1805 {
1806         int i;
1807         int temp;
1808
1809         /*
1810          * transno specifies what transformation is required. (0-7)
1811          * The lower two bits indicate by how much the vault is rotated,
1812          * and the upper bit indicates a reflection.
1813          * This is done by using rotation matrices... however since
1814          * these are mostly zeros for rotations by 90 degrees this can
1815          * be expressed simply in terms of swapping and inverting the
1816          * x and y coordinates.
1817          */
1818         for (i = 0; i < transno % 4; i++)
1819         {
1820                 /* rotate by 90 degrees */
1821                 temp = *x;
1822                 *x = -(*y);
1823                 *y = temp;
1824         }
1825
1826         if (transno / 4)
1827         {
1828                 /* Reflect depending on status of 3rd bit. */
1829                 *x = -(*x);
1830         }
1831
1832         /* Add offsets so vault stays in the first quadrant */
1833         *x += xoffset;
1834         *y += yoffset;
1835 }
1836
1837 /*!
1838  * @brief Vaultをフロアに配置する / Hack -- fill in "vault" rooms
1839  * @param yval 生成基準Y座標
1840  * @param xval 生成基準X座標
1841  * @param ymax VaultのYサイズ
1842  * @param xmax VaultのXサイズ
1843  * @param data Vaultのデータ文字列
1844  * @param xoffset 変換基準X座標
1845  * @param yoffset 変換基準Y座標
1846  * @param transno 変換ID
1847  * @return なし
1848  */
1849 static void build_vault(POSITION yval, POSITION xval, POSITION ymax, POSITION xmax, cptr data,
1850                 POSITION xoffset, POSITION yoffset, int transno)
1851 {
1852         POSITION dx, dy, x, y, i, j;
1853         cptr t;
1854         cave_type *c_ptr;
1855
1856         /* Place dungeon features and objects */
1857         for (t = data, dy = 0; dy < ymax; dy++)
1858         {
1859                 for (dx = 0; dx < xmax; dx++, t++)
1860                 {
1861                         /* prevent loop counter from being overwritten */
1862                         i = dx;
1863                         j = dy;
1864
1865                         /* Flip / rotate */
1866                         coord_trans(&i, &j, xoffset, yoffset, transno);
1867
1868                         /* Extract the location */
1869                         if (transno % 2 == 0)
1870                         {
1871                                 /* no swap of x/y */
1872                                 x = xval - (xmax / 2) + i;
1873                                 y = yval - (ymax / 2) + j;
1874                         }
1875                         else
1876                         {
1877                                 /* swap of x/y */
1878                                 x = xval - (ymax / 2) + i;
1879                                 y = yval - (xmax / 2) + j;
1880                         }
1881
1882                         /* Hack -- skip "non-grids" */
1883                         if (*t == ' ') continue;
1884
1885                         /* Access the grid */
1886                         c_ptr = &cave[y][x];
1887
1888                         /* Lay down a floor */
1889                         place_floor_grid(c_ptr);
1890
1891                         /* Remove any mimic */
1892                         c_ptr->mimic = 0;
1893
1894                         /* Part of a vault */
1895                         c_ptr->info |= (CAVE_ROOM | CAVE_ICKY);
1896
1897                         /* Analyze the grid */
1898                         switch (*t)
1899                         {
1900                                 /* Granite wall (outer) */
1901                         case '%':
1902                                 place_outer_noperm_grid(c_ptr);
1903                                 break;
1904
1905                                 /* Granite wall (inner) */
1906                         case '#':
1907                                 place_inner_grid(c_ptr);
1908                                 break;
1909
1910                                 /* Glass wall (inner) */
1911                         case '$':
1912                                 place_inner_grid(c_ptr);
1913                                 c_ptr->feat = feat_glass_wall;
1914                                 break;
1915
1916                                 /* Permanent wall (inner) */
1917                         case 'X':
1918                                 place_inner_perm_grid(c_ptr);
1919                                 break;
1920
1921                                 /* Permanent glass wall (inner) */
1922                         case 'Y':
1923                                 place_inner_perm_grid(c_ptr);
1924                                 c_ptr->feat = feat_permanent_glass_wall;
1925                                 break;
1926
1927                                 /* Treasure/trap */
1928                         case '*':
1929                                 if (randint0(100) < 75)
1930                                 {
1931                                         place_object(y, x, 0L);
1932                                 }
1933                                 else
1934                                 {
1935                                         place_trap(y, x);
1936                                 }
1937                                 break;
1938
1939                                 /* Secret doors */
1940                         case '+':
1941                                 place_secret_door(y, x, DOOR_DEFAULT);
1942                                 break;
1943
1944                                 /* Secret glass doors */
1945                         case '-':
1946                                 place_secret_door(y, x, DOOR_GLASS_DOOR);
1947                                 if (is_closed_door(c_ptr->feat)) c_ptr->mimic = feat_glass_wall;
1948                                 break;
1949
1950                                 /* Curtains */
1951                         case '\'':
1952                                 place_secret_door(y, x, DOOR_CURTAIN);
1953                                 break;
1954
1955                                 /* Trap */
1956                         case '^':
1957                                 place_trap(y, x);
1958                                 break;
1959
1960                                 /* Black market in a dungeon */
1961                         case 'S':
1962                                 set_cave_feat(y, x, feat_black_market);
1963                                 store_init(NO_TOWN, STORE_BLACK);
1964                                 break;
1965
1966                                 /* The Pattern */
1967                         case 'p':
1968                                 set_cave_feat(y, x, feat_pattern_start);
1969                                 break;
1970
1971                         case 'a':
1972                                 set_cave_feat(y, x, feat_pattern_1);
1973                                 break;
1974
1975                         case 'b':
1976                                 set_cave_feat(y, x, feat_pattern_2);
1977                                 break;
1978
1979                         case 'c':
1980                                 set_cave_feat(y, x, feat_pattern_3);
1981                                 break;
1982
1983                         case 'd':
1984                                 set_cave_feat(y, x, feat_pattern_4);
1985                                 break;
1986
1987                         case 'P':
1988                                 set_cave_feat(y, x, feat_pattern_end);
1989                                 break;
1990
1991                         case 'B':
1992                                 set_cave_feat(y, x, feat_pattern_exit);
1993                                 break;
1994
1995                         case 'A':
1996                                 /* Reward for Pattern walk */
1997                                 object_level = base_level + 12;
1998                                 place_object(y, x, AM_GOOD | AM_GREAT);
1999                                 object_level = base_level;
2000                                 break;
2001                         }
2002                 }
2003         }
2004
2005
2006         /* Place dungeon monsters and objects */
2007         for (t = data, dy = 0; dy < ymax; dy++)
2008         {
2009                 for (dx = 0; dx < xmax; dx++, t++)
2010                 {
2011                         /* prevent loop counter from being overwritten */
2012                         i = dx;
2013                         j = dy;
2014
2015                         /* Flip / rotate */
2016                         coord_trans(&i, &j, xoffset, yoffset, transno);
2017
2018                         /* Extract the location */
2019                         if (transno % 2 == 0)
2020                         {
2021                                 /* no swap of x/y */
2022                                 x = xval - (xmax / 2) + i;
2023                                 y = yval - (ymax / 2) + j;
2024                         }
2025                         else
2026                         {
2027                                 /* swap of x/y */
2028                                 x = xval - (ymax / 2) + i;
2029                                 y = yval - (xmax / 2) + j;
2030                         }
2031
2032                         /* Hack -- skip "non-grids" */
2033                         if (*t == ' ') continue;
2034
2035                         /* Analyze the symbol */
2036                         switch (*t)
2037                         {
2038                                 /* Monster */
2039                                 case '&':
2040                                 {
2041                                         monster_level = base_level + 5;
2042                                         place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
2043                                         monster_level = base_level;
2044                                         break;
2045                                 }
2046
2047                                 /* Meaner monster */
2048                                 case '@':
2049                                 {
2050                                         monster_level = base_level + 11;
2051                                         place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
2052                                         monster_level = base_level;
2053                                         break;
2054                                 }
2055
2056                                 /* Meaner monster, plus treasure */
2057                                 case '9':
2058                                 {
2059                                         monster_level = base_level + 9;
2060                                         place_monster(y, x, PM_ALLOW_SLEEP);
2061                                         monster_level = base_level;
2062                                         object_level = base_level + 7;
2063                                         place_object(y, x, AM_GOOD);
2064                                         object_level = base_level;
2065                                         break;
2066                                 }
2067
2068                                 /* Nasty monster and treasure */
2069                                 case '8':
2070                                 {
2071                                         monster_level = base_level + 40;
2072                                         place_monster(y, x, PM_ALLOW_SLEEP);
2073                                         monster_level = base_level;
2074                                         object_level = base_level + 20;
2075                                         place_object(y, x, AM_GOOD | AM_GREAT);
2076                                         object_level = base_level;
2077                                         break;
2078                                 }
2079
2080                                 /* Monster and/or object */
2081                                 case ',':
2082                                 {
2083                                         if (randint0(100) < 50)
2084                                         {
2085                                                 monster_level = base_level + 3;
2086                                                 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
2087                                                 monster_level = base_level;
2088                                         }
2089                                         if (randint0(100) < 50)
2090                                         {
2091                                                 object_level = base_level + 7;
2092                                                 place_object(y, x, 0L);
2093                                                 object_level = base_level;
2094                                         }
2095                                         break;
2096                                 }
2097
2098                         }
2099                 }
2100         }
2101 }
2102
2103
2104 /*!
2105  * @brief タイプ7の部屋…v_info.txtより小型vaultを生成する / Type 7 -- simple vaults (see "v_info.txt")
2106  * @return なし
2107  */
2108 static bool build_type7(void)
2109 {
2110         vault_type *v_ptr = NULL;
2111         int dummy;
2112         POSITION x, y;
2113         POSITION xval, yval;
2114         POSITION xoffset, yoffset;
2115         int transno;
2116
2117         /* Pick a lesser vault */
2118         for (dummy = 0; dummy < SAFE_MAX_ATTEMPTS; dummy++)
2119         {
2120                 /* Access a random vault record */
2121                 v_ptr = &v_info[randint0(max_v_idx)];
2122
2123                 /* Accept the first lesser vault */
2124                 if (v_ptr->typ == 7) break;
2125         }
2126
2127         /* No lesser vault found */
2128         if (dummy >= SAFE_MAX_ATTEMPTS)
2129         {
2130                 msg_print_wizard(CHEAT_DUNGEON, _("小型固定Vaultを配置できませんでした。", "Could not place lesser vault."));
2131                 return FALSE;
2132         }
2133
2134         /* pick type of transformation (0-7) */
2135         transno = randint0(8);
2136
2137         /* calculate offsets */
2138         x = v_ptr->wid;
2139         y = v_ptr->hgt;
2140
2141         /* Some huge vault cannot be ratated to fit in the dungeon */
2142         if (x+2 > cur_hgt-2)
2143         {
2144                 /* Forbid 90 or 270 degree ratation */
2145                 transno &= ~1;
2146         }
2147
2148         coord_trans(&x, &y, 0, 0, transno);
2149
2150         if (x < 0)
2151         {
2152                 xoffset = -x - 1;
2153         }
2154         else
2155         {
2156                 xoffset = 0;
2157         }
2158
2159         if (y < 0)
2160         {
2161                 yoffset = -y - 1;
2162         }
2163         else
2164         {
2165                 yoffset = 0;
2166         }
2167
2168         /* Find and reserve some space in the dungeon.  Get center of room. */
2169         if (!find_space(&yval, &xval, abs(y), abs(x))) return FALSE;
2170
2171 #ifdef FORCE_V_IDX
2172         v_ptr = &v_info[2];
2173 #endif
2174
2175         /* Message */
2176         msg_format_wizard(CHEAT_DUNGEON, _("小型Vault(%s)を生成しました。", "Lesser vault (%s)."), v_name + v_ptr->name);
2177
2178         /* Hack -- Build the vault */
2179         build_vault(yval, xval, v_ptr->hgt, v_ptr->wid,
2180                     v_text + v_ptr->text, xoffset, yoffset, transno);
2181
2182         return TRUE;
2183 }
2184
2185 /*!
2186  * @brief タイプ8の部屋…v_info.txtより大型vaultを生成する / Type 8 -- greater vaults (see "v_info.txt")
2187  * @return なし
2188  */
2189 static bool build_type8(void)
2190 {
2191         vault_type *v_ptr;
2192         int dummy;
2193         POSITION xval, yval;
2194         POSITION x, y;
2195         int transno;
2196         int xoffset, yoffset;
2197
2198         /* Pick a greater vault */
2199         for (dummy = 0; dummy < SAFE_MAX_ATTEMPTS; dummy++)
2200         {
2201                 /* Access a random vault record */
2202                 v_ptr = &v_info[randint0(max_v_idx)];
2203
2204                 /* Accept the first greater vault */
2205                 if (v_ptr->typ == 8) break;
2206         }
2207
2208         /* No greater vault found */
2209         if (dummy >= SAFE_MAX_ATTEMPTS)
2210         {
2211                 msg_print_wizard(CHEAT_DUNGEON, _("大型固定Vaultを配置できませんでした。", "Could not place greater vault."));
2212                 return FALSE;
2213         }
2214
2215         /* pick type of transformation (0-7) */
2216         transno = randint0(8);
2217
2218         /* calculate offsets */
2219         x = v_ptr->wid;
2220         y = v_ptr->hgt;
2221
2222         /* Some huge vault cannot be ratated to fit in the dungeon */
2223         if (x+2 > cur_hgt-2)
2224         {
2225                 /* Forbid 90 or 270 degree ratation */
2226                 transno &= ~1;
2227         }
2228
2229         coord_trans(&x, &y, 0, 0, transno);
2230
2231         if (x < 0)
2232         {
2233                 xoffset = - x - 1;
2234         }
2235         else
2236         {
2237                 xoffset = 0;
2238         }
2239
2240         if (y < 0)
2241         {
2242                 yoffset = - y - 1;
2243         }
2244         else
2245         {
2246                 yoffset = 0;
2247         }
2248
2249         /*
2250          * Try to allocate space for room.  If fails, exit
2251          *
2252          * Hack -- Prepare a bit larger space (+2, +2) to 
2253          * prevent generation of vaults with no-entrance.
2254          */
2255         /* Find and reserve some space in the dungeon.  Get center of room. */
2256         if (!find_space(&yval, &xval, (POSITION)(abs(y) + 2), (POSITION)(abs(x) + 2))) return FALSE;
2257
2258 #ifdef FORCE_V_IDX
2259         v_ptr = &v_info[76 + randint1(3)];
2260 #endif
2261
2262         msg_format_wizard(CHEAT_DUNGEON, _("大型固定Vault(%s)を生成しました。", "Greater vault (%s)."), v_name + v_ptr->name);
2263
2264         /* Hack -- Build the vault */
2265         build_vault(yval, xval, v_ptr->hgt, v_ptr->wid,
2266                     v_text + v_ptr->text, xoffset, yoffset, transno);
2267
2268         return TRUE;
2269 }
2270
2271 /*
2272  * Structure to hold all "fill" data
2273  */
2274
2275 typedef struct fill_data_type fill_data_type;
2276
2277 struct fill_data_type
2278 {
2279         /* area size */
2280         int xmin;
2281         int ymin;
2282         int xmax;
2283         int ymax;
2284
2285         /* cutoffs */
2286         int c1;
2287         int c2;
2288         int c3;
2289
2290         /* features to fill with */
2291         int feat1;
2292         int feat2;
2293         int feat3;
2294
2295         int info1;
2296         int info2;
2297         int info3;
2298
2299         /* number of filled squares */
2300         int amount;
2301 };
2302
2303 static fill_data_type fill_data;
2304
2305
2306 /* Store routine for the fractal cave generator */
2307 /* this routine probably should be an inline function or a macro. */
2308 static void store_height(int x, int y, int val)
2309 {
2310         /* if on boundary set val > cutoff so walls are not as square */
2311         if (((x == fill_data.xmin) || (y == fill_data.ymin) ||
2312              (x == fill_data.xmax) || (y == fill_data.ymax)) &&
2313             (val <= fill_data.c1)) val = fill_data.c1 + 1;
2314
2315         /* store the value in height-map format */
2316         cave[y][x].feat = (s16b)val;
2317
2318         return;
2319 }
2320
2321
2322 /*
2323 * Explanation of the plasma fractal algorithm:
2324 *
2325 * A grid of points is created with the properties of a 'height-map'
2326 * This is done by making the corners of the grid have a random value.
2327 * The grid is then subdivided into one with twice the resolution.
2328 * The new points midway between two 'known' points can be calculated
2329 * by taking the average value of the 'known' ones and randomly adding
2330 * or subtracting an amount proportional to the distance between those
2331 * points.  The final 'middle' points of the grid are then calculated
2332 * by averaging all four of the originally 'known' corner points.  An
2333 * random amount is added or subtracted from this to get a value of the
2334 * height at that point.  The scaling factor here is adjusted to the
2335 * slightly larger distance diagonally as compared to orthogonally.
2336 *
2337 * This is then repeated recursively to fill an entire 'height-map'
2338 * A rectangular map is done the same way, except there are different
2339 * scaling factors along the x and y directions.
2340 *
2341 * A hack to change the amount of correlation between points is done using
2342 * the grd variable.  If the current step size is greater than grd then
2343 * the point will be random, otherwise it will be calculated by the
2344 * above algorithm.  This makes a maximum distance at which two points on
2345 * the height map can affect each other.
2346 *
2347 * How fractal caves are made:
2348 *
2349 * When the map is complete, a cut-off value is used to create a cave.
2350 * Heights below this value are "floor", and heights above are "wall".
2351 * This also can be used to create lakes, by adding more height levels
2352 * representing shallow and deep water/ lava etc.
2353 *
2354 * The grd variable affects the width of passages.
2355 * The roug variable affects the roughness of those passages
2356 *
2357 * The tricky part is making sure the created cave is connected.  This
2358 * is done by 'filling' from the inside and only keeping the 'filled'
2359 * floor.  Walls bounding the 'filled' floor are also kept.  Everything
2360 * else is converted to the normal _extra_.
2361  */
2362
2363
2364 /*
2365  *  Note that this uses the cave.feat array in a very hackish way
2366  *  the values are first set to zero, and then each array location
2367  *  is used as a "heightmap"
2368  *  The heightmap then needs to be converted back into the "feat" format.
2369  *
2370  *  grd=level at which fractal turns on.  smaller gives more mazelike caves
2371  *  roug=roughness level.  16=normal.  higher values make things more convoluted
2372  *    small values are good for smooth walls.
2373  *  size=length of the side of the square cave system.
2374  */
2375 static void generate_hmap(int y0, int x0, int xsiz, int ysiz, int grd, int roug, int cutoff)
2376 {
2377         int xhsize, yhsize, xsize, ysize, maxsize;
2378
2379         /*
2380          * fixed point variables- these are stored as 256 x normal value
2381          * this gives 8 binary places of fractional part + 8 places of normal part
2382          */
2383
2384         u16b xstep, xhstep, ystep, yhstep;
2385         u16b xstep2, xhstep2, ystep2, yhstep2;
2386         u16b i, j, ii, jj, diagsize, xxsize, yysize;
2387         
2388         /* Cache for speed */
2389         u16b xm, xp, ym, yp;
2390
2391         /* redefine size so can change the value if out of range */
2392         xsize = xsiz;
2393         ysize = ysiz;
2394
2395         /* Paranoia about size of the system of caves */
2396         if (xsize > 254) xsize = 254;
2397         if (xsize < 4) xsize = 4;
2398         if (ysize > 254) ysize = 254;
2399         if (ysize < 4) ysize = 4;
2400
2401         /* get offsets to middle of array */
2402         xhsize = xsize / 2;
2403         yhsize = ysize / 2;
2404
2405         /* fix rounding problem */
2406         xsize = xhsize * 2;
2407         ysize = yhsize * 2;
2408
2409         /* get limits of region */
2410         fill_data.xmin = x0 - xhsize;
2411         fill_data.ymin = y0 - yhsize;
2412         fill_data.xmax = x0 + xhsize;
2413         fill_data.ymax = y0 + yhsize;
2414
2415         /* Store cutoff in global for quick access */
2416         fill_data.c1 = cutoff;
2417
2418         /*
2419         * Scale factor for middle points:
2420         * About sqrt(2) * 256 - correct for a square lattice
2421         * approximately correct for everything else.
2422          */
2423         diagsize = 362;
2424
2425         /* maximum of xsize and ysize */
2426         maxsize = (xsize > ysize) ? xsize : ysize;
2427
2428         /* Clear the section */
2429         for (i = 0; i <= xsize; i++)
2430         {
2431                 for (j = 0; j <= ysize; j++)
2432                 {
2433                         /* -1 is a flag for "not done yet" */
2434                         cave[(int)(fill_data.ymin + j)][(int)(fill_data.xmin + i)].feat = -1;
2435                         /* Clear icky flag because may be redoing the cave */
2436                         cave[(int)(fill_data.ymin + j)][(int)(fill_data.xmin + i)].info &= ~(CAVE_ICKY);
2437                 }
2438         }
2439
2440         /* Boundaries are walls */
2441         cave[fill_data.ymin][fill_data.xmin].feat = (s16b)maxsize;
2442         cave[fill_data.ymax][fill_data.xmin].feat = (s16b)maxsize;
2443         cave[fill_data.ymin][fill_data.xmax].feat = (s16b)maxsize;
2444         cave[fill_data.ymax][fill_data.xmax].feat = (s16b)maxsize;
2445
2446         /* Set the middle square to be an open area. */
2447         cave[y0][x0].feat = 0;
2448
2449         /* Initialize the step sizes */
2450         xstep = xhstep = xsize * 256;
2451         ystep = yhstep = ysize * 256;
2452         xxsize = xsize * 256;
2453         yysize = ysize * 256;
2454
2455         /*
2456          * Fill in the rectangle with fractal height data -
2457          * like the 'plasma fractal' in fractint.
2458          */
2459         while ((xhstep > 256) || (yhstep > 256))
2460         {
2461                 /* Halve the step sizes */
2462                 xstep = xhstep;
2463                 xhstep /= 2;
2464                 ystep = yhstep;
2465                 yhstep /= 2;
2466
2467                 /* cache well used values */
2468                 xstep2 = xstep / 256;
2469                 ystep2 = ystep / 256;
2470
2471                 xhstep2 = xhstep / 256;
2472                 yhstep2 = yhstep / 256;
2473
2474                 /* middle top to bottom. */
2475                 for (i = xhstep; i <= xxsize - xhstep; i += xstep)
2476                 {
2477                         for (j = 0; j <= yysize; j += ystep)
2478                         {
2479                                 /* cache often used values */
2480                                 ii = i / 256 + fill_data.xmin;
2481                                 jj = j / 256 + fill_data.ymin;
2482
2483                                 /* Test square */
2484                                 if (cave[jj][ii].feat == -1)
2485                                 {
2486                                         if (xhstep2 > grd)
2487                                         {
2488                                                 /* If greater than 'grid' level then is random */
2489                                                 store_height(ii, jj, randint1(maxsize));
2490                                         }
2491                                         else
2492                                         {
2493                                                 /* Average of left and right points +random bit */
2494                                                 store_height(ii, jj,
2495                                                         (cave[jj][fill_data.xmin + (i - xhstep) / 256].feat
2496                                                          + cave[jj][fill_data.xmin + (i + xhstep) / 256].feat) / 2
2497                                                          + (randint1(xstep2) - xhstep2) * roug / 16);
2498                                         }
2499                                 }
2500                         }
2501                 }
2502
2503
2504                 /* middle left to right. */
2505                 for (j = yhstep; j <= yysize - yhstep; j += ystep)
2506                 {
2507                         for (i = 0; i <= xxsize; i += xstep)
2508                         {
2509                                 /* cache often used values */
2510                                 ii = i / 256 + fill_data.xmin;
2511                                 jj = j / 256 + fill_data.ymin;
2512
2513                                 /* Test square */
2514                                 if (cave[jj][ii].feat == -1)
2515                                 {
2516                                         if (xhstep2 > grd)
2517                                         {
2518                                                 /* If greater than 'grid' level then is random */
2519                                                 store_height(ii, jj, randint1(maxsize));
2520                                         }
2521                                         else
2522                                         {
2523                                                 /* Average of up and down points +random bit */
2524                                                 store_height(ii, jj,
2525                                                         (cave[fill_data.ymin + (j - yhstep) / 256][ii].feat
2526                                                         + cave[fill_data.ymin + (j + yhstep) / 256][ii].feat) / 2
2527                                                         + (randint1(ystep2) - yhstep2) * roug / 16);
2528                                         }
2529                                 }
2530                         }
2531                 }
2532
2533                 /* center. */
2534                 for (i = xhstep; i <= xxsize - xhstep; i += xstep)
2535                 {
2536                         for (j = yhstep; j <= yysize - yhstep; j += ystep)
2537                         {
2538                                 /* cache often used values */
2539                                 ii = i / 256 + fill_data.xmin;
2540                                 jj = j / 256 + fill_data.ymin;
2541
2542                                 /* Test square */
2543                                 if (cave[jj][ii].feat == -1)
2544                                 {
2545                                         if (xhstep2 > grd)
2546                                         {
2547                                                 /* If greater than 'grid' level then is random */
2548                                                 store_height(ii, jj, randint1(maxsize));
2549                                         }
2550                                         else
2551                                         {
2552                                                 /* Cache reused values. */
2553                                                 xm = fill_data.xmin + (i - xhstep) / 256;
2554                                                 xp = fill_data.xmin + (i + xhstep) / 256;
2555                                                 ym = fill_data.ymin + (j - yhstep) / 256;
2556                                                 yp = fill_data.ymin + (j + yhstep) / 256;
2557
2558                                                 /* 
2559                                                  * Average over all four corners + scale by diagsize to
2560                                                  * reduce the effect of the square grid on the shape of the fractal
2561                                                  */
2562                                                 store_height(ii, jj,
2563                                                         (cave[ym][xm].feat + cave[yp][xm].feat
2564                                                         + cave[ym][xp].feat + cave[yp][xp].feat) / 4
2565                                                         + (randint1(xstep2) - xhstep2) * (diagsize / 16) / 256 * roug);
2566                                         }
2567                                 }
2568                         }
2569                 }
2570         }
2571 }
2572
2573
2574 static bool hack_isnt_wall(int y, int x, int c1, int c2, int c3, int feat1, int feat2, int feat3, int info1, int info2, int info3)
2575 {
2576         /*
2577          * function used to convert from height-map back to the
2578          *  normal angband cave format
2579          */
2580         if (cave[y][x].info & CAVE_ICKY)
2581         {
2582                 /* already done */
2583                 return FALSE;
2584         }
2585         else
2586         {
2587                 /* Show that have looked at this square */
2588                 cave[y][x].info|= (CAVE_ICKY);
2589
2590                 /* Use cutoffs c1-c3 to allocate regions of floor /water/ lava etc. */
2591                 if (cave[y][x].feat <= c1)
2592                 {
2593                         /* 25% of the time use the other tile : it looks better this way */
2594                         if (randint1(100) < 75)
2595                         {
2596                                 cave[y][x].feat = (s16b)feat1;
2597                                 cave[y][x].info &= ~(CAVE_MASK);
2598                                 cave[y][x].info |= info1;
2599                                 return TRUE;
2600                         }
2601                         else
2602                         {
2603                                 cave[y][x].feat = (s16b)feat2;
2604                                 cave[y][x].info &= ~(CAVE_MASK);
2605                                 cave[y][x].info |= info2;
2606                                 return TRUE;
2607                         }
2608                 }
2609                 else if (cave[y][x].feat <= c2)
2610                 {
2611                         /* 25% of the time use the other tile : it looks better this way */
2612                         if (randint1(100) < 75)
2613                         {
2614                                 cave[y][x].feat = (s16b)feat2;
2615                                 cave[y][x].info &= ~(CAVE_MASK);
2616                                 cave[y][x].info |= info2;
2617                                 return TRUE;
2618                         }
2619                         else
2620                         {
2621                                 cave[y][x].feat = (s16b)feat1;
2622                                 cave[y][x].info &= ~(CAVE_MASK);
2623                                 cave[y][x].info |= info1;
2624                                 return TRUE;
2625                         }
2626                 }
2627                 else if (cave[y][x].feat <= c3)
2628                 {
2629                         cave[y][x].feat = (s16b)feat3;
2630                         cave[y][x].info &= ~(CAVE_MASK);
2631                         cave[y][x].info |= info3;
2632                         return TRUE;
2633                 }
2634                 /* if greater than cutoff then is a wall */
2635                 else
2636                 {
2637                         place_outer_bold(y, x);
2638                         return FALSE;
2639                 }
2640         }
2641 }
2642
2643
2644
2645
2646 /*
2647  * Quick and nasty fill routine used to find the connected region
2648  * of floor in the middle of the cave
2649  */
2650 static void cave_fill(POSITION y, POSITION x)
2651 {
2652         int i, j, d;
2653         int ty, tx;
2654
2655         int flow_tail = 1;
2656         int flow_head = 0;
2657
2658
2659         /*** Start Grid ***/
2660
2661         /* Enqueue that entry */
2662         temp_y[0] = y;
2663         temp_x[0] = x;
2664
2665
2666         /* Now process the queue */
2667         while (flow_head != flow_tail)
2668         {
2669                 /* Extract the next entry */
2670                 ty = temp_y[flow_head];
2671                 tx = temp_x[flow_head];
2672
2673                 /* Forget that entry */
2674                 if (++flow_head == TEMP_MAX) flow_head = 0;
2675
2676                 /* Add the "children" */
2677                 for (d = 0; d < 8; d++)
2678                 {
2679                         int old_head = flow_tail;
2680
2681                         /* Child location */
2682                         j = ty + ddy_ddd[d];
2683                         i = tx + ddx_ddd[d];
2684
2685                         /* Paranoia Don't leave the cave */
2686                         if (!in_bounds(j, i))
2687                         {
2688                                 /* affect boundary */
2689                                 cave[j][i].info |= CAVE_ICKY;
2690 /*                              return; */
2691                         }
2692
2693                         /* If within bounds */
2694                         else if ((i > fill_data.xmin) && (i < fill_data.xmax)
2695                                 && (j > fill_data.ymin) && (j < fill_data.ymax))
2696                         {
2697                                 /* If not a wall or floor done before */
2698                                 if (hack_isnt_wall(j, i,
2699                                         fill_data.c1, fill_data.c2, fill_data.c3,
2700                                         fill_data.feat1, fill_data.feat2, fill_data.feat3,
2701                                         fill_data.info1, fill_data.info2, fill_data.info3))
2702                                 {
2703                                         /* Enqueue that entry */
2704                                         temp_y[flow_tail] = (byte_hack)j;
2705                                         temp_x[flow_tail] = (byte_hack)i;
2706
2707                                         /* Advance the queue */
2708                                         if (++flow_tail == TEMP_MAX) flow_tail = 0;
2709
2710                                         /* Hack -- Overflow by forgetting new entry */
2711                                         if (flow_tail == flow_head)
2712                                         {
2713                                                 flow_tail = old_head;
2714                                         }
2715                                         else
2716                                         {
2717                                                 /* keep tally of size of cave system */
2718                                                 (fill_data.amount)++;
2719                                         }
2720                                 }
2721                         }
2722                         else
2723                         {
2724                                 /* affect boundary */
2725                                 cave[j][i].info |= CAVE_ICKY;
2726                         }
2727                 }
2728         }
2729 }
2730
2731
2732 static bool generate_fracave(int y0, int x0, int xsize, int ysize, int cutoff, bool light, bool room)
2733 {
2734         int x, y, i, xhsize, yhsize;
2735
2736         /* offsets to middle from corner */
2737         xhsize = xsize / 2;
2738         yhsize = ysize / 2;
2739
2740
2741         /*
2742          * select region connected to center of cave system
2743          * this gets rid of alot of isolated one-sqaures that
2744          * can make teleport traps instadeaths...
2745          */
2746
2747         /* cutoffs */
2748         fill_data.c1 = cutoff;
2749         fill_data.c2 = 0;
2750         fill_data.c3 = 0;
2751
2752         /* features to fill with */
2753         fill_data.feat1 = floor_type[randint0(100)];
2754         fill_data.feat2 = floor_type[randint0(100)];
2755         fill_data.feat3 = floor_type[randint0(100)];
2756
2757         fill_data.info1 = CAVE_FLOOR;
2758         fill_data.info2 = CAVE_FLOOR;
2759         fill_data.info3 = CAVE_FLOOR;
2760
2761         /* number of filled squares */
2762         fill_data.amount = 0;
2763
2764         cave_fill((byte)y0, (byte)x0);
2765
2766         /* if tally too small, try again */
2767         if (fill_data.amount < 10)
2768         {
2769                 /* too small - clear area and try again later */
2770                 for (x = 0; x <= xsize; ++x)
2771                 {
2772                         for (y = 0; y <= ysize; ++y)
2773                         {
2774                                 place_extra_bold(y0 + y - yhsize, x0 + x - xhsize);
2775                                 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY | CAVE_ROOM);
2776                         }
2777                 }
2778                 return FALSE;
2779         }
2780
2781         /*
2782          * Do boundarys-check to see if they are next to a filled region
2783          * If not then they are set to normal granite
2784          * If so then they are marked as room walls.
2785          */
2786         for (i = 0; i <= xsize; ++i)
2787         {
2788                 /* top boundary */
2789                 if ((cave[0 + y0 - yhsize][i + x0 - xhsize].info & CAVE_ICKY) && (room))
2790                 {
2791                         /* Next to a 'filled' region? - set to be room walls */
2792                         place_outer_bold(y0 + 0 - yhsize, x0 + i - xhsize);
2793                         if (light) cave[y0 + 0 - yhsize][x0 + i - xhsize].info |= (CAVE_GLOW);
2794                         cave[y0 + 0 - yhsize][x0 + i - xhsize].info |= (CAVE_ROOM);
2795                         place_outer_bold(y0 + 0 - yhsize, x0 + i - xhsize);
2796                 }
2797                 else
2798                 {
2799                         /* set to be normal granite */
2800                         place_extra_bold(y0 + 0 - yhsize, x0 + i - xhsize);
2801                 }
2802
2803                 /* bottom boundary */
2804                 if ((cave[ysize + y0 - yhsize][i + x0 - xhsize].info & CAVE_ICKY) && (room))
2805                 {
2806                         /* Next to a 'filled' region? - set to be room walls */
2807                         place_outer_bold(y0 + ysize - yhsize, x0 + i - xhsize);
2808                         if (light) cave[y0 + ysize - yhsize][x0 + i - xhsize].info|=(CAVE_GLOW);
2809                         cave[y0 + ysize - yhsize][x0 + i - xhsize].info|=(CAVE_ROOM);
2810                         place_outer_bold(y0 + ysize - yhsize, x0 + i - xhsize);
2811                 }
2812                 else
2813                 {
2814                         /* set to be normal granite */
2815                         place_extra_bold(y0 + ysize - yhsize, x0 + i - xhsize);
2816                 }
2817
2818                 /* clear the icky flag-don't need it any more */
2819                 cave[y0 + 0 - yhsize][x0 + i - xhsize].info &= ~(CAVE_ICKY);
2820                 cave[y0 + ysize - yhsize][x0 + i - xhsize].info &= ~(CAVE_ICKY);
2821         }
2822
2823         /* Do the left and right boundaries minus the corners (done above) */
2824         for (i = 1; i < ysize; ++i)
2825         {
2826                 /* left boundary */
2827                 if ((cave[i + y0 - yhsize][0 + x0 - xhsize].info & CAVE_ICKY) && room)
2828                 {
2829                         /* room boundary */
2830                         place_outer_bold(y0 + i - yhsize, x0 + 0 - xhsize);
2831                         if (light) cave[y0 + i - yhsize][x0 + 0 - xhsize].info |= (CAVE_GLOW);
2832                         cave[y0 + i - yhsize][x0 + 0 - xhsize].info |= (CAVE_ROOM);
2833                         place_outer_bold(y0 + i - yhsize, x0 + 0 - xhsize);
2834                 }
2835                 else
2836                 {
2837                         /* outside room */
2838                         place_extra_bold(y0 + i - yhsize, x0 + 0 - xhsize);
2839                 }
2840                 /* right boundary */
2841                 if ((cave[i + y0 - yhsize][xsize + x0 - xhsize].info & CAVE_ICKY) && room)
2842                 {
2843                         /* room boundary */
2844                         place_outer_bold(y0 + i - yhsize, x0 + xsize - xhsize);
2845                         if (light) cave[y0 + i - yhsize][x0 + xsize - xhsize].info |= (CAVE_GLOW);
2846                         cave[y0 + i - yhsize][x0 + xsize - xhsize].info |= (CAVE_ROOM);
2847                         place_outer_bold(y0 + i - yhsize, x0 + xsize - xhsize);
2848                 }
2849                 else
2850                 {
2851                         /* outside room */
2852                         place_extra_bold(y0 + i - yhsize, x0 + xsize - xhsize);
2853                 }
2854
2855                 /* clear icky flag -done with it */
2856                 cave[y0 + i - yhsize][x0 + 0 - xhsize].info &= ~(CAVE_ICKY);
2857                 cave[y0 + i - yhsize][x0 + xsize - xhsize].info &= ~(CAVE_ICKY);
2858         }
2859
2860
2861         /* Do the rest: convert back to the normal format */
2862         for (x = 1; x < xsize; ++x)
2863         {
2864                 for (y = 1; y < ysize; ++y)
2865                 {
2866                         if (is_floor_bold(y0 + y - yhsize, x0 + x - xhsize) &&
2867                             (cave[y0 + y - yhsize][x0 + x - xhsize].info & CAVE_ICKY))
2868                         {
2869                                 /* Clear the icky flag in the filled region */
2870                                 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~CAVE_ICKY;
2871
2872                                 /* Set appropriate flags */
2873                                 if (light) cave[y0 + y - yhsize][x0 + x - xhsize].info |= (CAVE_GLOW);
2874                                 if (room) cave[y0 + y - yhsize][x0 + x - xhsize].info |= (CAVE_ROOM);
2875                         }
2876                         else if (is_outer_bold(y0 + y - yhsize, x0 + x - xhsize) &&
2877                                  (cave[y0 + y - yhsize][x0 + x - xhsize].info & CAVE_ICKY))
2878                         {
2879                                 /* Walls */
2880                                 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY);
2881                                 if (light) cave[y0 + y - yhsize][x0 + x - xhsize].info |= (CAVE_GLOW);
2882                                 if (room)
2883                                 {
2884                                         cave[y0 + y - yhsize][x0 + x - xhsize].info |= (CAVE_ROOM);
2885                                 }
2886                                 else
2887                                 {
2888
2889                                         place_extra_bold(y0 + y - yhsize, x0 + x - xhsize);
2890                                         cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ROOM);
2891                                 }
2892                         }
2893                         else
2894                         {
2895                                 /* Clear the unconnected regions */
2896                                 place_extra_bold(y0 + y - yhsize, x0 + x - xhsize);
2897                                 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY | CAVE_ROOM);
2898                         }
2899                 }
2900         }
2901
2902         /*
2903          * XXX XXX XXX There is a slight problem when tunnels pierce the caves:
2904          * Extra doors appear inside the system.  (Its not very noticeable though.)
2905          * This can be removed by "filling" from the outside in.  This allows a separation
2906          * from _outer_ with _inner_.  (Internal walls are  _outer_ instead.)
2907          * The extra effort for what seems to be only a minor thing (even non-existant if you
2908          * think of the caves not as normal rooms, but as holes in the dungeon), doesn't seem
2909          * worth it.
2910          */
2911
2912         return TRUE;
2913 }
2914
2915
2916 /*!
2917  * @brief タイプ9の部屋…フラクタルカーブによる洞窟生成 / Type 9 -- Driver routine to create fractal cave system
2918  * @return なし
2919  */
2920 static bool build_type9(void)
2921 {
2922         int grd, roug, cutoff;
2923         POSITION xsize, ysize, y0, x0;
2924
2925         bool done, light, room;
2926
2927         /* get size: note 'Evenness'*/
2928         xsize = randint1(22) * 2 + 6;
2929         ysize = randint1(15) * 2 + 6;
2930
2931         /* Find and reserve some space in the dungeon.  Get center of room. */
2932         if (!find_space(&y0, &x0, ysize + 1, xsize + 1))
2933         {
2934                 /* Limit to the minimum room size, and retry */
2935                 xsize = 8;
2936                 ysize = 8;
2937
2938                 /* Find and reserve some space in the dungeon.  Get center of room. */
2939                 if (!find_space(&y0, &x0, ysize + 1, xsize + 1))
2940                 {
2941                         /*
2942                          * Still no space?!
2943                          * Try normal room
2944                          */
2945                         return build_type1();
2946                 }
2947         }
2948
2949         light = done = FALSE;
2950         room = TRUE;
2951
2952         if ((dun_level <= randint1(25)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS)) light = TRUE;
2953
2954         while (!done)
2955         {
2956                 /* Note: size must be even or there are rounding problems
2957                 * This causes the tunnels not to connect properly to the room */
2958
2959                 /* testing values for these parameters feel free to adjust */
2960                 grd = 1 << (randint0(4));
2961
2962                 /* want average of about 16 */
2963                 roug = randint1(8) * randint1(4);
2964
2965                 /* about size/2 */
2966                 cutoff = randint1(xsize / 4) + randint1(ysize / 4) +
2967                          randint1(xsize / 4) + randint1(ysize / 4);
2968
2969                 /* make it */
2970                 generate_hmap(y0, x0, xsize, ysize, grd, roug, cutoff);
2971
2972                 /* Convert to normal format + clean up */
2973                 done = generate_fracave(y0, x0, xsize, ysize, cutoff, light, room);
2974         }
2975
2976         return TRUE;
2977 }
2978
2979 #ifdef ALLOW_CAVERNS_AND_LAKES
2980 /*
2981  * Builds a cave system in the center of the dungeon.
2982  */
2983 void build_cavern(void)
2984 {
2985         int grd, roug, cutoff, xsize, ysize, x0, y0;
2986         bool done, light;
2987
2988         light = done = FALSE;
2989         if ((dun_level <= randint1(50)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS)) light = TRUE;
2990
2991         /* Make a cave the size of the dungeon */
2992         xsize = cur_wid - 1;
2993         ysize = cur_hgt - 1;
2994         x0 = xsize / 2;
2995         y0 = ysize / 2;
2996
2997         /* Paranoia: make size even */
2998         xsize = x0 * 2;
2999         ysize = y0 * 2;
3000
3001         while (!done)
3002         {
3003                 /* testing values for these parameters: feel free to adjust */
3004                 grd = randint1(4) + 4;
3005
3006                 /* want average of about 16 */
3007                 roug = randint1(8) * randint1(4);
3008
3009                 /* about size/2 */
3010                 cutoff = xsize / 2;
3011
3012                  /* make it */
3013                 generate_hmap(y0 + 1, x0 + 1, xsize, ysize, grd, roug, cutoff);
3014
3015                 /* Convert to normal format+ clean up */
3016                 done = generate_fracave(y0 + 1, x0 + 1, xsize, ysize, cutoff, light, FALSE);
3017         }
3018 }
3019
3020 static bool generate_lake(int y0, int x0, int xsize, int ysize, int c1, int c2, int c3, int type)
3021 {
3022         int x, y, i, xhsize, yhsize;
3023         int feat1, feat2, feat3;
3024
3025         /* offsets to middle from corner */
3026         xhsize = xsize / 2;
3027         yhsize = ysize / 2;
3028
3029         /* Get features based on type */
3030         switch (type)
3031         {
3032         case LAKE_T_LAVA: /* Lava */
3033                 feat1 = feat_deep_lava;
3034                 feat2 = feat_shallow_lava;
3035                 feat3 = floor_type[randint0(100)];
3036                 break;
3037         case LAKE_T_WATER: /* Water */
3038                 feat1 = feat_deep_water;
3039                 feat2 = feat_shallow_water;
3040                 feat3 = floor_type[randint0(100)];
3041                 break;
3042         case LAKE_T_CAVE: /* Collapsed cave */
3043                 feat1 = floor_type[randint0(100)];
3044                 feat2 = floor_type[randint0(100)];
3045                 feat3 = feat_rubble;
3046                 break;
3047         case LAKE_T_EARTH_VAULT: /* Earth vault */
3048                 feat1 = feat_rubble;
3049                 feat2 = floor_type[randint0(100)];
3050                 feat3 = feat_rubble;
3051                 break;
3052         case LAKE_T_AIR_VAULT: /* Air vault */
3053                 feat1 = feat_grass;
3054                 feat2 = feat_tree;
3055                 feat3 = feat_grass;
3056                 break;
3057         case LAKE_T_WATER_VAULT: /* Water vault */
3058                 feat1 = feat_shallow_water;
3059                 feat2 = feat_deep_water;
3060                 feat3 = feat_shallow_water;
3061                 break;
3062         case LAKE_T_FIRE_VAULT: /* Fire Vault */
3063                 feat1 = feat_shallow_lava;
3064                 feat2 = feat_deep_lava;
3065                 feat3 = feat_shallow_lava;
3066                 break;
3067
3068         /* Paranoia */
3069         default: return FALSE;
3070         }
3071
3072         /*
3073          * select region connected to center of cave system
3074          * this gets rid of alot of isolated one-sqaures that
3075          * can make teleport traps instadeaths...
3076          */
3077
3078         /* cutoffs */
3079         fill_data.c1 = c1;
3080         fill_data.c2 = c2;
3081         fill_data.c3 = c3;
3082
3083         /* features to fill with */
3084         fill_data.feat1 = feat1;
3085         fill_data.feat2 = feat2;
3086         fill_data.feat3 = feat3;
3087
3088         fill_data.info1 = 0;
3089         fill_data.info2 = 0;
3090         fill_data.info3 = 0;
3091
3092         /* number of filled squares */
3093         fill_data.amount = 0;
3094
3095         /* select region connected to center of cave system
3096         * this gets rid of alot of isolated one-sqaures that
3097         * can make teleport traps instadeaths... */
3098         cave_fill((byte)y0, (byte)x0);
3099
3100         /* if tally too small, try again */
3101         if (fill_data.amount < 10)
3102         {
3103                 /* too small -clear area and try again later */
3104                 for (x = 0; x <= xsize; ++x)
3105                 {
3106                         for (y = 0; y <= ysize; ++y)
3107                         {
3108                                 place_floor_bold(y0 + y - yhsize, x0 + x - xhsize);
3109                                 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY);
3110                         }
3111                 }
3112                 return FALSE;
3113         }
3114
3115         /* Do boundarys- set to normal granite */
3116         for (i = 0; i <= xsize; ++i)
3117         {
3118                 place_extra_bold(y0 + 0 - yhsize, x0 + i - xhsize);
3119                 place_extra_bold(y0 + ysize - yhsize, x0 + i - xhsize);
3120
3121                 /* clear the icky flag-don't need it any more */
3122                 cave[y0 + 0 - yhsize][x0 + i - xhsize].info &= ~(CAVE_ICKY);
3123                 cave[y0 + ysize - yhsize][x0 + i - xhsize].info &= ~(CAVE_ICKY);
3124         }
3125
3126         /* Do the left and right boundaries minus the corners (done above) */
3127
3128         for (i = 1; i < ysize; ++i)
3129         {
3130                 place_extra_bold(y0 + i - yhsize, x0 + 0 - xhsize);
3131                 place_extra_bold(y0 + i - yhsize, x0 + xsize - xhsize);
3132
3133                 /* clear icky flag -done with it */
3134                 cave[y0 + i - yhsize][x0 + 0 - xhsize].info &= ~(CAVE_ICKY);
3135                 cave[y0 + i - yhsize][x0 + xsize - xhsize].info &= ~(CAVE_ICKY);
3136         }
3137
3138
3139         /* Do the rest: convert back to the normal format */
3140         for (x = 1; x < xsize; ++x)
3141         {
3142                 for (y = 1; y < ysize; ++y)
3143                 {
3144                         /* Fill unconnected regions with granite */
3145                         if ((!(cave[y0 + y - yhsize][x0 + x - xhsize].info & CAVE_ICKY)) ||
3146                                 is_outer_bold(y0 + y - yhsize, x0 + x - xhsize))
3147                                 place_extra_bold(y0 + y - yhsize, x0 + x - xhsize);
3148
3149                         /* turn off icky flag (no longer needed.) */
3150                         cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY | CAVE_ROOM);
3151
3152                         /* Light lava */
3153                         if (cave_have_flag_bold(y0 + y - yhsize, x0 + x - xhsize, FF_LAVA))
3154                         {
3155                                 if (!(d_info[dungeon_type].flags1 & DF1_DARKNESS)) cave[y0 + y - yhsize][x0 + x - xhsize].info |= CAVE_GLOW;
3156                         }
3157                 }
3158         }
3159
3160         return TRUE;
3161 }
3162
3163
3164 /*
3165  * makes a lake/collapsed cave system in the center of the dungeon
3166  */
3167 void build_lake(int type)
3168 {
3169         int grd, roug, xsize, ysize, x0, y0;
3170         bool done = FALSE;
3171         int c1, c2, c3;
3172
3173         /* paranoia - exit if lake type out of range. */
3174         if ((type < LAKE_T_LAVA) || (type > LAKE_T_FIRE_VAULT))
3175         {
3176                 msg_format("Invalid lake type (%d)", type);
3177                 return;
3178         }
3179
3180         /* Make the size of the dungeon */
3181         xsize = cur_wid - 1;
3182         ysize = cur_hgt - 1;
3183         x0 = xsize / 2;
3184         y0 = ysize / 2;
3185
3186         /* Paranoia: make size even */
3187         xsize = x0 * 2;
3188         ysize = y0 * 2;
3189
3190         while (!done)
3191         {
3192                 /* testing values for these parameters: feel free to adjust */
3193                 grd = randint1(3) + 4;
3194
3195                 /* want average of about 16 */
3196                 roug = randint1(8) * randint1(4);
3197
3198                 /* Make up size of various componants */
3199                 /* Floor */
3200                 c3 = 3 * xsize / 4;
3201
3202                 /* Deep water/lava */
3203                 c1 = randint0(c3 / 2) + randint0(c3 / 2) - 5;
3204
3205                 /* Shallow boundary */
3206                 c2 = (c1 + c3) / 2;
3207
3208                 /* make it */
3209                 generate_hmap(y0 + 1, x0 + 1, xsize, ysize, grd, roug, c3);
3210
3211                 /* Convert to normal format+ clean up */
3212                 done = generate_lake(y0 + 1, x0 + 1, xsize, ysize, c1, c2, c3, type);
3213         }
3214 }
3215 #endif /* ALLOW_CAVERNS_AND_LAKES */
3216
3217
3218 /*
3219  * Routine used by the random vault creators to add a door to a location
3220  * Note that range checking has to be done in the calling routine.
3221  *
3222  * The doors must be INSIDE the allocated region.
3223  */
3224 static void add_door(int x, int y)
3225 {
3226         /* Need to have a wall in the center square */
3227         if (!is_outer_bold(y, x)) return;
3228
3229         /* look at:
3230          *  x#x
3231          *  .#.
3232          *  x#x
3233          *
3234          *  where x=don't care
3235          *  .=floor, #=wall
3236          */
3237
3238         if (is_floor_bold(y-1,x) && is_floor_bold(y+1,x) &&
3239             (is_outer_bold(y, x - 1) && is_outer_bold(y, x + 1)))
3240         {
3241                 /* secret door */
3242                 place_secret_door(y, x, DOOR_DEFAULT);
3243
3244                 /* set boundarys so don't get wide doors */
3245                 place_solid_bold(y, x - 1);
3246                 place_solid_bold(y, x + 1);
3247         }
3248
3249
3250         /* look at:
3251          *  x#x
3252          *  .#.
3253          *  x#x
3254          *
3255          *  where x = don't care
3256          *  .=floor, #=wall
3257          */
3258         if (is_outer_bold(y - 1, x) && is_outer_bold(y + 1, x) &&
3259             is_floor_bold(y,x-1) && is_floor_bold(y,x+1))
3260         {
3261                 /* secret door */
3262                 place_secret_door(y, x, DOOR_DEFAULT);
3263
3264                 /* set boundarys so don't get wide doors */
3265                 place_solid_bold(y - 1, x);
3266                 place_solid_bold(y + 1, x);
3267         }
3268 }
3269
3270
3271 /*
3272  * Routine that fills the empty areas of a room with treasure and monsters.
3273  */
3274 static void fill_treasure(int x1, int x2, int y1, int y2, int difficulty)
3275 {
3276         int x, y, cx, cy, size;
3277         s32b value;
3278
3279         /* center of room:*/
3280         cx = (x1 + x2) / 2;
3281         cy = (y1 + y2) / 2;
3282
3283         /* Rough measure of size of vault= sum of lengths of sides */
3284         size = abs(x2 - x1) + abs(y2 - y1);
3285
3286         for (x = x1; x <= x2; x++)
3287         {
3288                 for (y = y1; y <= y2; y++)
3289                 {
3290                         /* Thing added based on distance to center of vault
3291                          * Difficulty is 1-easy to 10-hard */
3292                         value = ((((s32b)(distance(cx, cy, x, y))) * 100) / size) + randint1(10) - difficulty;
3293
3294                         /* hack- empty square part of the time */
3295                         if ((randint1(100) - difficulty * 3) > 50) value = 20;
3296
3297                          /* if floor, shallow water and lava */
3298                         if (is_floor_bold(y, x) ||
3299                             (cave_have_flag_bold(y, x, FF_PLACE) && cave_have_flag_bold(y, x, FF_DROP)))
3300                         {
3301                                 /* The smaller 'value' is, the better the stuff */
3302                                 if (value < 0)
3303                                 {
3304                                         /* Meanest monster + treasure */
3305                                         monster_level = base_level + 40;
3306                                         place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
3307                                         monster_level = base_level;
3308                                         object_level = base_level + 20;
3309                                         place_object(y, x, AM_GOOD);
3310                                         object_level = base_level;
3311                                 }
3312                                 else if (value < 5)
3313                                 {
3314                                         /* Mean monster +treasure */
3315                                         monster_level = base_level + 20;
3316                                         place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
3317                                         monster_level = base_level;
3318                                         object_level = base_level + 10;
3319                                         place_object(y, x, AM_GOOD);
3320                                         object_level = base_level;
3321                                 }
3322                                 else if (value < 10)
3323                                 {
3324                                         /* Monster */
3325                                         monster_level = base_level + 9;
3326                                         place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
3327                                         monster_level = base_level;
3328                                 }
3329                                 else if (value < 17)
3330                                 {
3331                                         /* Intentional Blank space */
3332
3333                                         /*
3334                                          * (Want some of the vault to be empty
3335                                          * so have room for group monsters.
3336                                          * This is used in the hack above to lower
3337                                          * the density of stuff in the vault.)
3338                                          */
3339                                 }
3340                                 else if (value < 23)
3341                                 {
3342                                         /* Object or trap */
3343                                         if (randint0(100) < 25)
3344                                         {
3345                                                 place_object(y, x, 0L);
3346                                         }
3347                                         else
3348                                         {
3349                                                 place_trap(y, x);
3350                                         }
3351                                 }
3352                                 else if (value < 30)
3353                                 {
3354                                         /* Monster and trap */
3355                                         monster_level = base_level + 5;
3356                                         place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
3357                                         monster_level = base_level;
3358                                         place_trap(y, x);
3359                                 }
3360                                 else if (value < 40)
3361                                 {
3362                                         /* Monster or object */
3363                                         if (randint0(100) < 50)
3364                                         {
3365                                                 monster_level = base_level + 3;
3366                                                 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
3367                                                 monster_level = base_level;
3368                                         }
3369                                         if (randint0(100) < 50)
3370                                         {
3371                                                 object_level = base_level + 7;
3372                                                 place_object(y, x, 0L);
3373                                                 object_level = base_level;
3374                                         }
3375                                 }
3376                                 else if (value < 50)
3377                                 {
3378                                         /* Trap */
3379                                         place_trap(y, x);
3380                                 }
3381                                 else
3382                                 {
3383                                         /* Various Stuff */
3384
3385                                         /* 20% monster, 40% trap, 20% object, 20% blank space */
3386                                         if (randint0(100) < 20)
3387                                         {
3388                                                 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
3389                                         }
3390                                         else if (randint0(100) < 50)
3391                                         {
3392                                                 place_trap(y, x);
3393                                         }
3394                                         else if (randint0(100) < 50)
3395                                         {
3396                                                 place_object(y, x, 0L);
3397                                         }
3398                                 }
3399
3400                         }
3401                 }
3402         }
3403 }
3404
3405
3406 /*
3407  * This function creates a random vault that looks like a collection of bubbles.
3408  * It works by getting a set of coordinates that represent the center of each
3409  * bubble.  The entire room is made by seeing which bubble center is closest. If
3410  * two centers are equidistant then the square is a wall, otherwise it is a floor.
3411  * The only exception is for squares really near a center, these are always floor.
3412  * (It looks better than without this check.)
3413  *
3414  * Note: If two centers are on the same point then this algorithm will create a
3415  *       blank bubble filled with walls. - This is prevented from happening.
3416  */
3417 static void build_bubble_vault(int x0, int y0, int xsize, int ysize)
3418 {
3419         #define BUBBLENUM 10            /* number of bubbles */
3420
3421         /* array of center points of bubbles */
3422         coord center[BUBBLENUM];
3423
3424         int i, j, x, y;
3425         u16b min1, min2, temp;
3426         bool done;
3427
3428         /* Offset from center to top left hand corner */
3429         int xhsize = xsize / 2;
3430         int yhsize = ysize / 2;
3431
3432         msg_print_wizard(CHEAT_DUNGEON, _("泡型ランダムVaultを生成しました。", "Room Vault."));
3433
3434         /* Allocate center of bubbles */
3435         center[0].x = (byte)randint1(xsize - 3) + 1;
3436         center[0].y = (byte)randint1(ysize - 3) + 1;
3437
3438         for (i = 1; i < BUBBLENUM; i++)
3439         {
3440                 done = FALSE;
3441
3442                 /* get center and check to see if it is unique */
3443                 while (!done)
3444                 {
3445                         done = TRUE;
3446
3447                         x = randint1(xsize - 3) + 1;
3448                         y = randint1(ysize - 3) + 1;
3449
3450                         for (j = 0; j < i; j++)
3451                         {
3452                                 /* rough test to see if there is an overlap */
3453                                 if ((x == center[j].x) && (y == center[j].y)) done = FALSE;
3454                         }
3455                 }
3456
3457                 center[i].x = (byte_hack)x;
3458                 center[i].y = (byte_hack)y;
3459         }
3460
3461
3462         /* Top and bottom boundaries */
3463         for (i = 0; i < xsize; i++)
3464         {
3465                 int side_x = x0 - xhsize + i;
3466
3467                 place_outer_noperm_bold(y0 - yhsize + 0, side_x);
3468                 cave[y0 - yhsize + 0][side_x].info |= (CAVE_ROOM | CAVE_ICKY);
3469                 place_outer_noperm_bold(y0 - yhsize + ysize - 1, side_x);
3470                 cave[y0 - yhsize + ysize - 1][side_x].info |= (CAVE_ROOM | CAVE_ICKY);
3471         }
3472
3473         /* Left and right boundaries */
3474         for (i = 1; i < ysize - 1; i++)
3475         {
3476                 int side_y = y0 - yhsize + i;
3477
3478                 place_outer_noperm_bold(side_y, x0 - xhsize + 0);
3479                 cave[side_y][x0 - xhsize + 0].info |= (CAVE_ROOM | CAVE_ICKY);
3480                 place_outer_noperm_bold(side_y, x0 - xhsize + xsize - 1);
3481                 cave[side_y][x0 - xhsize + xsize - 1].info |= (CAVE_ROOM | CAVE_ICKY);
3482         }
3483
3484         /* Fill in middle with bubbles */
3485         for (x = 1; x < xsize - 1; x++)
3486         {
3487                 for (y = 1; y < ysize - 1; y++)
3488                 {
3489                         /* Get distances to two closest centers */
3490
3491                         /* initialize */
3492                         min1 = (u16b)distance(x, y, center[0].x, center[0].y);
3493                         min2 = (u16b)distance(x, y, center[1].x, center[1].y);
3494
3495                         if (min1 > min2)
3496                         {
3497                                 /* swap if in wrong order */
3498                                 temp = min1;
3499                                 min1 = min2;
3500                                 min2 = temp;
3501                         }
3502
3503                         /* Scan the rest */
3504                         for (i = 2; i < BUBBLENUM; i++)
3505                         {
3506                                 temp = (u16b)distance(x, y, center[i].x, center[i].y);
3507
3508                                 if (temp < min1)
3509                                 {
3510                                         /* smallest */
3511                                         min2 = min1;
3512                                         min1 = temp;
3513                                 }
3514                                 else if (temp < min2)
3515                                 {
3516                                         /* second smallest */
3517                                         min2 = temp;
3518                                 }
3519                         }
3520                         if (((min2 - min1) <= 2) && (!(min1 < 3)))
3521                         {
3522                                 /* Boundary at midpoint+ not at inner region of bubble */
3523                                 place_outer_noperm_bold(y0 - yhsize + y, x0 - xhsize + x);
3524                         }
3525                         else
3526                         {
3527                                 /* middle of a bubble */
3528                                 place_floor_bold(y0 - yhsize + y, x0 - xhsize + x);
3529                         }
3530
3531                         /* clean up rest of flags */
3532                         cave[y0 - yhsize + y][x0 - xhsize + x].info |= (CAVE_ROOM | CAVE_ICKY);
3533                 }
3534         }
3535
3536         /* Try to add some random doors */
3537         for (i = 0; i < 500; i++)
3538         {
3539                 x = randint1(xsize - 3) - xhsize + x0 + 1;
3540                 y = randint1(ysize - 3) - yhsize + y0 + 1;
3541                 add_door(x, y);
3542         }
3543
3544         /* Fill with monsters and treasure, low difficulty */
3545         fill_treasure(x0 - xhsize + 1, x0 - xhsize + xsize - 2, y0 - yhsize + 1, y0 - yhsize + ysize - 2, randint1(5));
3546 }
3547
3548
3549 /*
3550  * Overlay a rectangular room given its bounds
3551  * This routine is used by build_room_vault
3552  * The area inside the walls is not touched:
3553  * only granite is removed- normal walls stay
3554  */
3555 static void build_room(int x1, int x2, int y1, int y2)
3556 {
3557         int x, y, i, xsize, ysize, temp;
3558
3559         /* Check if rectangle has no width */
3560         if ((x1 == x2) || (y1 == y2)) return;
3561
3562         /* initialize */
3563         if (x1 > x2)
3564         {
3565                 /* Swap boundaries if in wrong order */
3566                 temp = x1;
3567                 x1 = x2;
3568                 x2 = temp;
3569         }
3570
3571         if (y1 > y2)
3572         {
3573                 /* Swap boundaries if in wrong order */
3574                 temp = y1;
3575                 y1 = y2;
3576                 y2 = temp;
3577         }
3578
3579         /* get total widths */
3580         xsize = x2 - x1;
3581         ysize = y2 - y1;
3582
3583
3584         /* Top and bottom boundaries */
3585         for (i = 0; i <= xsize; i++)
3586         {
3587                 place_outer_noperm_bold(y1, x1 + i);
3588                 cave[y1][x1 + i].info |= (CAVE_ROOM | CAVE_ICKY);
3589                 place_outer_noperm_bold(y2, x1 + i);
3590                 cave[y2][x1 + i].info |= (CAVE_ROOM | CAVE_ICKY);
3591         }
3592
3593         /* Left and right boundaries */
3594         for (i = 1; i < ysize; i++)
3595         {
3596                 place_outer_noperm_bold(y1 + i, x1);
3597                 cave[y1 + i][x1].info|=(CAVE_ROOM | CAVE_ICKY);
3598                 place_outer_noperm_bold(y1 + i, x2);
3599                 cave[y1 + i][x2].info|=(CAVE_ROOM | CAVE_ICKY);
3600         }
3601
3602         /* Middle */
3603         for (x = 1; x < xsize; x++)
3604         {
3605                 for (y = 1; y < ysize; y++)
3606                 {
3607                         if (is_extra_bold(y1+y, x1+x))
3608                         {
3609                                 /* clear the untouched region */
3610                                 place_floor_bold(y1 + y, x1 + x);
3611                                 cave[y1 + y][x1 + x].info |= (CAVE_ROOM | CAVE_ICKY);
3612                         }
3613                         else
3614                         {
3615                                 /* make it a room- but don't touch */
3616                                 cave[y1 + y][x1 + x].info |= (CAVE_ROOM | CAVE_ICKY);
3617                         }
3618                 }
3619         }
3620 }
3621
3622
3623 /* Create a random vault that looks like a collection of overlapping rooms */
3624
3625 static void build_room_vault(int x0, int y0, int xsize, int ysize)
3626 {
3627         int i, x1, x2, y1, y2, xhsize, yhsize;
3628
3629         /* get offset from center */
3630         xhsize = xsize / 2;
3631         yhsize = ysize / 2;
3632
3633         msg_print_wizard(CHEAT_DUNGEON, _("部屋型ランダムVaultを生成しました。", "Room Vault."));
3634
3635         /* fill area so don't get problems with arena levels */
3636         for (x1 = 0; x1 < xsize; x1++)
3637         {
3638                 int x = x0 - xhsize + x1;
3639
3640                 for (y1 = 0; y1 < ysize; y1++)
3641                 {
3642                         int y = y0 - yhsize + y1;
3643
3644                         place_extra_bold(y, x);
3645                         cave[y][x].info &= (~CAVE_ICKY);
3646                 }
3647         }
3648
3649         /* add ten random rooms */
3650         for (i = 0; i < 10; i++)
3651         {
3652                 x1 = randint1(xhsize) * 2 + x0 - xhsize;
3653                 x2 = randint1(xhsize) * 2 + x0 - xhsize;
3654                 y1 = randint1(yhsize) * 2 + y0 - yhsize;
3655                 y2 = randint1(yhsize) * 2 + y0 - yhsize;
3656                 build_room(x1, x2, y1, y2);
3657         }
3658
3659         /* Add some random doors */
3660         for (i = 0; i < 500; i++)
3661         {
3662                 x1 = randint1(xsize - 3) - xhsize + x0 + 1;
3663                 y1 = randint1(ysize - 3) - yhsize + y0 + 1;
3664                 add_door(x1, y1);
3665         }
3666
3667         /* Fill with monsters and treasure, high difficulty */
3668         fill_treasure(x0 - xhsize + 1, x0 - xhsize + xsize - 2, y0 - yhsize + 1, y0 - yhsize + ysize - 2, randint1(5) + 5);
3669 }
3670
3671
3672 /* Create a random vault out of a fractal cave */
3673 static void build_cave_vault(int x0, int y0, int xsiz, int ysiz)
3674 {
3675         int grd, roug, cutoff, xhsize, yhsize, xsize, ysize, x, y;
3676         bool done, light, room;
3677
3678         /* round to make sizes even */
3679         xhsize = xsiz / 2;
3680         yhsize = ysiz / 2;
3681         xsize = xhsize * 2;
3682         ysize = yhsize * 2;
3683
3684         msg_print_wizard(CHEAT_DUNGEON, _("洞穴ランダムVaultを生成しました。", "Cave Vault."));
3685
3686         light = done = FALSE;
3687         room = TRUE;
3688
3689         while (!done)
3690         {
3691                 /* testing values for these parameters feel free to adjust */
3692                 grd = 1 << randint0(4);
3693
3694                 /* want average of about 16 */
3695                 roug = randint1(8) * randint1(4);
3696
3697                 /* about size/2 */
3698                 cutoff = randint1(xsize / 4) + randint1(ysize / 4) +
3699                          randint1(xsize / 4) + randint1(ysize / 4);
3700
3701                 /* make it */
3702                 generate_hmap(y0, x0, xsize, ysize, grd, roug, cutoff);
3703
3704                 /* Convert to normal format+ clean up */
3705                 done = generate_fracave(y0, x0, xsize, ysize, cutoff, light, room);
3706         }
3707
3708         /* Set icky flag because is a vault */
3709         for (x = 0; x <= xsize; x++)
3710         {
3711                 for (y = 0; y <= ysize; y++)
3712                 {
3713                         cave[y0 - yhsize + y][x0 - xhsize + x].info |= CAVE_ICKY;
3714                 }
3715         }
3716
3717         /* Fill with monsters and treasure, low difficulty */
3718         fill_treasure(x0 - xhsize + 1, x0 - xhsize + xsize - 1, y0 - yhsize + 1, y0 - yhsize + ysize - 1, randint1(5));
3719 }
3720
3721 /*
3722  * maze vault -- rectangular labyrinthine rooms
3723  *
3724  * maze vault uses two routines:
3725  *    r_visit - a recursive routine that builds the labyrinth
3726  *    build_maze_vault - a driver routine that calls r_visit and adds
3727  *                   monsters, traps and treasure
3728  *
3729  * The labyrinth is built by creating a spanning tree of a graph.
3730  * The graph vertices are at
3731  *    (x, y) = (2j + x1, 2k + y1)   j = 0,...,m-1    k = 0,...,n-1
3732  * and the edges are the vertical and horizontal nearest neighbors.
3733  *
3734  * The spanning tree is created by performing a suitably randomized
3735  * depth-first traversal of the graph. The only adjustable parameter
3736  * is the randint0(3) below; it governs the relative density of
3737  * twists and turns in the labyrinth: smaller number, more twists.
3738  */
3739 static void r_visit(int y1, int x1, int y2, int x2,
3740                     int node, int dir, int *visited)
3741 {
3742         int i, j, m, n, temp, x, y, adj[4];
3743
3744         /* dimensions of vertex array */
3745         m = (x2 - x1) / 2 + 1;
3746         n = (y2 - y1) / 2 + 1;
3747
3748         /* mark node visited and set it to a floor */
3749         visited[node] = 1;
3750         x = 2 * (node % m) + x1;
3751         y = 2 * (node / m) + y1;
3752         place_floor_bold(y, x);
3753
3754         /* setup order of adjacent node visits */
3755         if (one_in_(3))
3756         {
3757                 /* pick a random ordering */
3758                 for (i = 0; i < 4; i++)
3759                         adj[i] = i;
3760                 for (i = 0; i < 4; i++)
3761                 {
3762                         j = randint0(4);
3763                         temp = adj[i];
3764                         adj[i] = adj[j];
3765                         adj[j] = temp;
3766                 }
3767                 dir = adj[0];
3768         }
3769         else
3770         {
3771                 /* pick a random ordering with dir first */
3772                 adj[0] = dir;
3773                 for (i = 1; i < 4; i++)
3774                         adj[i] = i;
3775                 for (i = 1; i < 4; i++)
3776                 {
3777                         j = 1 + randint0(3);
3778                         temp = adj[i];
3779                         adj[i] = adj[j];
3780                         adj[j] = temp;
3781                 }
3782         }
3783
3784         for (i = 0; i < 4; i++)
3785         {
3786                 switch (adj[i])
3787                 {
3788                         case 0:
3789                                 /* (0,+) - check for bottom boundary */
3790                                 if ((node / m < n - 1) && (visited[node + m] == 0))
3791                                 {
3792                                         place_floor_bold(y + 1, x);
3793                                         r_visit(y1, x1, y2, x2, node + m, dir, visited);
3794                                 }
3795                                 break;
3796                         case 1:
3797                                 /* (0,-) - check for top boundary */
3798                                 if ((node / m > 0) && (visited[node - m] == 0))
3799                                 {
3800                                         place_floor_bold(y - 1, x);
3801                                         r_visit(y1, x1, y2, x2, node - m, dir, visited);
3802                                 }
3803                                 break;
3804                         case 2:
3805                                 /* (+,0) - check for right boundary */
3806                                 if ((node % m < m - 1) && (visited[node + 1] == 0))
3807                                 {
3808                                         place_floor_bold(y, x + 1);
3809                                         r_visit(y1, x1, y2, x2, node + 1, dir, visited);
3810                                 }
3811                                 break;
3812                         case 3:
3813                                 /* (-,0) - check for left boundary */
3814                                 if ((node % m > 0) && (visited[node - 1] == 0))
3815                                 {
3816                                         place_floor_bold(y, x - 1);
3817                                         r_visit(y1, x1, y2, x2, node - 1, dir, visited);
3818                                 }
3819                 } /* end switch */
3820         }
3821 }
3822
3823
3824 void build_maze_vault(int x0, int y0, int xsize, int ysize, bool is_vault)
3825 {
3826         int y, x, dy, dx;
3827         int y1, x1, y2, x2;
3828         int m, n, num_vertices, *visited;
3829         bool light;
3830         cave_type *c_ptr;
3831
3832         msg_print_wizard(CHEAT_DUNGEON, _("迷路ランダムVaultを生成しました。", "Maze Vault."));
3833
3834         /* Choose lite or dark */
3835         light = ((dun_level <= randint1(25)) && is_vault && !(d_info[dungeon_type].flags1 & DF1_DARKNESS));
3836
3837         /* Pick a random room size - randomized by calling routine */
3838         dy = ysize / 2 - 1;
3839         dx = xsize / 2 - 1;
3840
3841         y1 = y0 - dy;
3842         x1 = x0 - dx;
3843         y2 = y0 + dy;
3844         x2 = x0 + dx;
3845
3846         /* generate the room */
3847         for (y = y1 - 1; y <= y2 + 1; y++)
3848         {
3849                 for (x = x1 - 1; x <= x2 + 1; x++)
3850                 {
3851                         c_ptr = &cave[y][x];
3852                         c_ptr->info |= CAVE_ROOM;
3853                         if (is_vault) c_ptr->info |= CAVE_ICKY;
3854                         if ((x == x1 - 1) || (x == x2 + 1) || (y == y1 - 1) || (y == y2 + 1))
3855                         {
3856                                 place_outer_grid(c_ptr);
3857                         }
3858                         else if (!is_vault)
3859                         {
3860                                 place_extra_grid(c_ptr);
3861                         }
3862                         else
3863                         {
3864                                 place_inner_grid(c_ptr);
3865                         }
3866                         if (light) c_ptr->info |= (CAVE_GLOW);
3867                 }
3868         }
3869
3870         /* dimensions of vertex array */
3871         m = dx + 1;
3872         n = dy + 1;
3873         num_vertices = m * n;
3874
3875         /* initialize array of visited vertices */
3876         C_MAKE(visited, num_vertices, int);
3877
3878         /* traverse the graph to create a spaning tree, pick a random root */
3879         r_visit(y1, x1, y2, x2, randint0(num_vertices), 0, visited);
3880
3881         /* Fill with monsters and treasure, low difficulty */
3882         if (is_vault) fill_treasure(x1, x2, y1, y2, randint1(5));
3883
3884         C_KILL(visited, num_vertices, int);
3885 }
3886
3887
3888 /* Build a "mini" checkerboard vault
3889  *
3890  * This is done by making a permanent wall maze and setting
3891  * the diagonal sqaures of the checker board to be granite.
3892  * The vault has two entrances on opposite sides to guarantee
3893  * a way to get in even if the vault abuts a side of the dungeon.
3894  */
3895 static void build_mini_c_vault(int x0, int y0, int xsize, int ysize)
3896 {
3897         int dy, dx;
3898         int y1, x1, y2, x2, y, x, total;
3899         int m, n, num_vertices;
3900         int *visited;
3901
3902         msg_print_wizard(CHEAT_DUNGEON, _("小型チェッカーランダムVaultを生成しました。", "Mini Checker Board Vault."));
3903
3904         /* Pick a random room size */
3905         dy = ysize / 2 - 1;
3906         dx = xsize / 2 - 1;
3907
3908         y1 = y0 - dy;
3909         x1 = x0 - dx;
3910         y2 = y0 + dy;
3911         x2 = x0 + dx;
3912
3913
3914         /* generate the room */
3915         for (x = x1 - 2; x <= x2 + 2; x++)
3916         {
3917                 if (!in_bounds(y1-2,x)) break;
3918
3919                 cave[y1-2][x].info |= (CAVE_ROOM | CAVE_ICKY);
3920
3921                 place_outer_noperm_bold(y1-2, x);
3922         }
3923
3924         for (x = x1 - 2; x <= x2 + 2; x++)
3925         {
3926                 if (!in_bounds(y2+2,x)) break;
3927
3928                 cave[y2+2][x].info |= (CAVE_ROOM | CAVE_ICKY);
3929
3930                 place_outer_noperm_bold(y2+2, x);
3931         }
3932
3933         for (y = y1 - 2; y <= y2 + 2; y++)
3934         {
3935                 if (!in_bounds(y,x1-2)) break;
3936
3937                 cave[y][x1-2].info |= (CAVE_ROOM | CAVE_ICKY);
3938
3939                 place_outer_noperm_bold(y, x1-2);
3940         }
3941
3942         for (y = y1 - 2; y <= y2 + 2; y++)
3943         {
3944                 if (!in_bounds(y,x2+2)) break;
3945
3946                 cave[y][x2+2].info |= (CAVE_ROOM | CAVE_ICKY);
3947
3948                 place_outer_noperm_bold(y, x2+2);
3949         }
3950
3951         for (y = y1 - 1; y <= y2 + 1; y++)
3952         {
3953                 for (x = x1 - 1; x <= x2 + 1; x++)
3954                 {
3955                         cave_type *c_ptr = &cave[y][x];
3956
3957                         c_ptr->info |= (CAVE_ROOM | CAVE_ICKY);
3958
3959                         /* Permanent walls */
3960                         place_inner_perm_grid(c_ptr);
3961                 }
3962         }
3963
3964
3965         /* dimensions of vertex array */
3966         m = dx + 1;
3967         n = dy + 1;
3968         num_vertices = m * n;
3969
3970         /* initialize array of visited vertices */
3971         C_MAKE(visited, num_vertices, int);
3972
3973         /* traverse the graph to create a spannng tree, pick a random root */
3974         r_visit(y1, x1, y2, x2, randint0(num_vertices), 0, visited);
3975
3976         /* Make it look like a checker board vault */
3977         for (x = x1; x <= x2; x++)
3978         {
3979                 for (y = y1; y <= y2; y++)
3980                 {
3981                         total = x - x1 + y - y1;
3982                         /* If total is odd- and is a floor then make a wall */
3983                         if ((total % 2 == 1) && is_floor_bold(y, x))
3984                         {
3985                                 place_inner_bold(y, x);
3986                         }
3987                 }
3988         }
3989
3990         /* Make a couple of entrances */
3991         if (one_in_(2))
3992         {
3993                 /* left and right */
3994                 y = randint1(dy) + dy / 2;
3995                 place_inner_bold(y1 + y, x1 - 1);
3996                 place_inner_bold(y1 + y, x2 + 1);
3997         }
3998         else
3999         {
4000                 /* top and bottom */
4001                 x = randint1(dx) + dx / 2;
4002                 place_inner_bold(y1 - 1, x1 + x);
4003                 place_inner_bold(y2 + 1, x1 + x);
4004         }
4005
4006         /* Fill with monsters and treasure, highest difficulty */
4007         fill_treasure(x1, x2, y1, y2, 10);
4008
4009         C_KILL(visited, num_vertices, int);
4010 }
4011
4012
4013 /* Build a town/ castle by using a recursive algorithm.
4014  * Basically divide each region in a probalistic way to create
4015  * smaller regions.  When the regions get too small stop.
4016  *
4017  * The power variable is a measure of how well defended a region is.
4018  * This alters the possible choices.
4019  */
4020 static void build_recursive_room(int x1, int y1, int x2, int y2, int power)
4021 {
4022         int xsize, ysize;
4023         int x, y;
4024         int choice;
4025
4026         /* Temp variables */
4027         int t1, t2, t3, t4;
4028
4029         xsize = x2 - x1;
4030         ysize = y2 - y1;
4031
4032         if ((power < 3) && (xsize > 12) && (ysize > 12))
4033         {
4034                 /* Need outside wall +keep */
4035                 choice = 1;
4036         }
4037         else
4038         {
4039                 if (power < 10)
4040                 {
4041                         /* Make rooms + subdivide */
4042                         if ((randint1(10) > 2) && (xsize < 8) && (ysize < 8))
4043                         {
4044                                 choice = 4;
4045                         }
4046                         else
4047                         {
4048                                 choice = randint1(2) + 1;
4049                         }
4050                 }
4051                 else
4052                 {
4053                         /* Mostly subdivide */
4054                         choice = randint1(3) + 1;
4055                 }
4056         }
4057
4058         /* Based on the choice made above, do something */
4059
4060         switch (choice)
4061         {
4062                 case 1:
4063                 {
4064                         /* Outer walls */
4065
4066                         /* top and bottom */
4067                         for (x = x1; x <= x2; x++)
4068                         {
4069                                 place_outer_bold(y1, x);
4070                                 place_outer_bold(y2, x);
4071                         }
4072
4073                         /* left and right */
4074                         for (y = y1 + 1; y < y2; y++)
4075                         {
4076                                 place_outer_bold(y, x1);
4077                                 place_outer_bold(y, x2);
4078                         }
4079
4080                         /* Make a couple of entrances */
4081                         if (one_in_(2))
4082                         {
4083                                 /* left and right */
4084                                 y = randint1(ysize) + y1;
4085                                 place_floor_bold(y, x1);
4086                                 place_floor_bold(y, x2);
4087                         }
4088                         else
4089                         {
4090                                 /* top and bottom */
4091                                 x = randint1(xsize) + x1;
4092                                 place_floor_bold(y1, x);
4093                                 place_floor_bold(y2, x);
4094                         }
4095
4096                         /* Select size of keep */
4097                         t1 = randint1(ysize / 3) + y1;
4098                         t2 = y2 - randint1(ysize / 3);
4099                         t3 = randint1(xsize / 3) + x1;
4100                         t4 = x2 - randint1(xsize / 3);
4101
4102                         /* Do outside areas */
4103
4104                         /* Above and below keep */
4105                         build_recursive_room(x1 + 1, y1 + 1, x2 - 1, t1, power + 1);
4106                         build_recursive_room(x1 + 1, t2, x2 - 1, y2, power + 1);
4107
4108                         /* Left and right of keep */
4109                         build_recursive_room(x1 + 1, t1 + 1, t3, t2 - 1, power + 3);
4110                         build_recursive_room(t4, t1 + 1, x2 - 1, t2 - 1, power + 3);
4111
4112                         /* Make the keep itself: */
4113                         x1 = t3;
4114                         x2 = t4;
4115                         y1 = t1;
4116                         y2 = t2;
4117                         xsize = x2 - x1;
4118                         ysize = y2 - y1;
4119                         power += 2;
4120
4121                         /* Fall through */
4122                 }
4123                 case 4:
4124                 {
4125                         /* Try to build a room */
4126                         if ((xsize < 3) || (ysize < 3))
4127                         {
4128                                 for (y = y1; y < y2; y++)
4129                                 {
4130                                         for (x = x1; x < x2; x++)
4131                                         {
4132                                                 place_inner_bold(y, x);
4133                                         }
4134                                 }
4135
4136                                 /* Too small */
4137                                 return;
4138                         }
4139
4140                         /* Make outside walls */
4141                         /* top and bottom */
4142                         for (x = x1 + 1; x <= x2 - 1; x++)
4143                         {
4144                                 place_inner_bold(y1 + 1, x);
4145                                 place_inner_bold(y2 - 1, x);
4146                         }
4147
4148                         /* left and right */
4149                         for (y = y1 + 1; y <= y2 - 1; y++)
4150                         {
4151                                 place_inner_bold(y, x1 + 1);
4152                                 place_inner_bold(y, x2 - 1);
4153                         }
4154
4155                         /* Make a door */
4156                         y = randint1(ysize - 3) + y1 + 1;
4157
4158                         if (one_in_(2))
4159                         {
4160                                 /* left */
4161                                 place_floor_bold(y, x1 + 1);
4162                         }
4163                         else
4164                         {
4165                                 /* right */
4166                                 place_floor_bold(y, x2 - 1);
4167                         }
4168
4169                         /* Build the room */
4170                         build_recursive_room(x1 + 2, y1 + 2, x2 - 2, y2 - 2, power + 3);
4171                         break;
4172                 }
4173                 case 2:
4174                 {
4175                         /* Try and divide vertically */
4176                         if (xsize < 3)
4177                         {
4178                                 /* Too small */
4179                                 for (y = y1; y < y2; y++)
4180                                 {
4181                                         for (x = x1; x < x2; x++)
4182                                         {
4183                                                 place_inner_bold(y, x);
4184                                         }
4185                                 }
4186                                 return;
4187                         }
4188
4189                         t1 = randint1(xsize - 2) + x1 + 1;
4190                         build_recursive_room(x1, y1, t1, y2, power - 2);
4191                         build_recursive_room(t1 + 1, y1, x2, y2, power - 2);
4192                         break;
4193                 }
4194                 case 3:
4195                 {
4196                         /* Try and divide horizontally */
4197                         if (ysize < 3)
4198                         {
4199                                 /* Too small */
4200                                 for (y = y1; y < y2; y++)
4201                                 {
4202                                         for (x = x1; x < x2; x++)
4203                                         {
4204                                                 place_inner_bold(y, x);
4205                                         }
4206                                 }
4207                                 return;
4208                         }
4209
4210                         t1 = randint1(ysize - 2) + y1 + 1;
4211                         build_recursive_room(x1, y1, x2, t1, power - 2);
4212                         build_recursive_room(x1, t1 + 1, x2, y2, power - 2);
4213                         break;
4214                 }
4215         }
4216 }
4217
4218
4219 /* Build a castle */
4220
4221 /* Driver routine: clear the region and call the recursive
4222 * room routine.
4223 *
4224 *This makes a vault that looks like a castle/ city in the dungeon.
4225 */
4226 static void build_castle_vault(int x0, int y0, int xsize, int ysize)
4227 {
4228         int dy, dx;
4229         int y1, x1, y2, x2;
4230         int y, x;
4231
4232         /* Pick a random room size */
4233         dy = ysize / 2 - 1;
4234         dx = xsize / 2 - 1;
4235
4236         y1 = y0 - dy;
4237         x1 = x0 - dx;
4238         y2 = y0 + dy;
4239         x2 = x0 + dx;
4240
4241         msg_print_wizard(CHEAT_DUNGEON, _("城型ランダムVaultを生成しました。", "Castle Vault"));
4242
4243         /* generate the room */
4244         for (y = y1 - 1; y <= y2 + 1; y++)
4245         {
4246                 for (x = x1 - 1; x <= x2 + 1; x++)
4247                 {
4248                         cave[y][x].info |= (CAVE_ROOM | CAVE_ICKY);
4249                         /* Make everything a floor */
4250                         place_floor_bold(y, x);
4251                 }
4252         }
4253
4254         /* Make the castle */
4255         build_recursive_room(x1, y1, x2, y2, randint1(5));
4256
4257         /* Fill with monsters and treasure, low difficulty */
4258         fill_treasure(x1, x2, y1, y2, randint1(3));
4259 }
4260
4261
4262 /*
4263  * Add outer wall to a floored region
4264  * Note: no range checking is done so must be inside dungeon
4265  * This routine also stomps on doors
4266  */
4267 static void add_outer_wall(int x, int y, int light, int x1, int y1, int x2, int y2)
4268 {
4269         cave_type *c_ptr;
4270         feature_type *f_ptr;
4271         int i, j;
4272
4273         if (!in_bounds(y, x)) return;
4274
4275         c_ptr = &cave[y][x];
4276
4277         /* hack- check to see if square has been visited before
4278         * if so, then exit (use room flag to do this) */
4279         if (c_ptr->info & CAVE_ROOM) return;
4280
4281         /* set room flag */
4282         c_ptr->info |= CAVE_ROOM;
4283
4284         f_ptr = &f_info[c_ptr->feat];
4285
4286         if (is_floor_bold(y, x))
4287         {
4288                 for (i = -1; i <= 1; i++)
4289                 {
4290                         for (j = -1; j <= 1; j++)
4291                         {
4292                                 if ((x + i >= x1) && (x + i <= x2) &&
4293                                          (y + j >= y1) && (y + j <= y2))
4294                                 {
4295                                         add_outer_wall(x + i, y + j, light, x1, y1, x2, y2);
4296                                         if (light) c_ptr->info |= CAVE_GLOW;
4297                                 }
4298                         }
4299                 }
4300         }
4301         else if (is_extra_bold(y, x))
4302         {
4303                 /* Set bounding walls */
4304                 place_outer_bold(y, x);
4305                 if (light) c_ptr->info |= CAVE_GLOW;
4306         }
4307         else if (permanent_wall(f_ptr))
4308         {
4309                 /* Set bounding walls */
4310                 if (light) c_ptr->info |= CAVE_GLOW;
4311         }
4312 }
4313
4314
4315 /*
4316  * Hacked distance formula - gives the 'wrong' answer.
4317  * Used to build crypts
4318  */
4319 static int dist2(int x1, int y1, int x2, int y2,
4320                  int h1, int h2, int h3, int h4)
4321 {
4322         int dx, dy;
4323         dx = abs(x2 - x1);
4324         dy = abs(y2 - y1);
4325
4326         /* Basically this works by taking the normal pythagorean formula
4327          * and using an expansion to express this in a way without the
4328          * square root.  This approximate formula is then perturbed to give
4329          * the distorted results.  (I found this by making a mistake when I was
4330          * trying to fix the circular rooms.)
4331          */
4332
4333         /* h1-h4 are constants that describe the metric */
4334         if (dx >= 2 * dy) return (dx + (dy * h1) / h2);
4335         if (dy >= 2 * dx) return (dy + (dx * h1) / h2);
4336         return (((dx + dy) * 128) / 181 +
4337                 (dx * dx / (dy * h3) + dy * dy / (dx * h3)) * h4);
4338         /* 128/181 is approx. 1/sqrt(2) */
4339 }
4340
4341
4342 /*
4343  * Build target vault.
4344  * This is made by two concentric "crypts" with perpendicular
4345  * walls creating the cross-hairs.
4346  */
4347 static void build_target_vault(int x0, int y0, int xsize, int ysize)
4348 {
4349         int rad, x, y;
4350
4351         /* Make a random metric */
4352         int h1, h2, h3, h4;
4353         h1 = randint1(32) - 16;
4354         h2 = randint1(16);
4355         h3 = randint1(32);
4356         h4 = randint1(32) - 16;
4357
4358         msg_print_wizard(CHEAT_DUNGEON, _("対称形ランダムVaultを生成しました。", "Elemental Vault"));
4359
4360         /* work out outer radius */
4361         if (xsize > ysize)
4362         {
4363                 rad = ysize / 2;
4364         }
4365         else
4366         {
4367                 rad = xsize / 2;
4368         }
4369
4370         /* Make floor */
4371         for (x = x0 - rad; x <= x0 + rad; x++)
4372         {
4373                 for (y = y0 - rad; y <= y0 + rad; y++)
4374                 {
4375                         /* clear room flag */
4376                         cave[y][x].info &= ~(CAVE_ROOM);
4377
4378                         /* Vault - so is "icky" */
4379                         cave[y][x].info |= CAVE_ICKY;
4380
4381                         if (dist2(y0, x0, y, x, h1, h2, h3, h4) <= rad - 1)
4382                         {
4383                                 /* inside- so is floor */
4384                                 place_floor_bold(y, x);
4385                         }
4386                         else
4387                         {
4388                                 /* make granite outside so arena works */
4389                                 place_extra_bold(y, x);
4390                         }
4391
4392                         /* proper boundary for arena */
4393                         if (((y + rad) == y0) || ((y - rad) == y0) ||
4394                             ((x + rad) == x0) || ((x - rad) == x0))
4395                         {
4396                                 place_extra_bold(y, x);
4397                         }
4398                 }
4399         }
4400
4401         /* Find visible outer walls and set to be FEAT_OUTER */
4402         add_outer_wall(x0, y0, FALSE, x0 - rad - 1, y0 - rad - 1,
4403                        x0 + rad + 1, y0 + rad + 1);
4404
4405         /* Add inner wall */
4406         for (x = x0 - rad / 2; x <= x0 + rad / 2; x++)
4407         {
4408                 for (y = y0 - rad / 2; y <= y0 + rad / 2; y++)
4409                 {
4410                         if (dist2(y0, x0, y, x, h1, h2, h3, h4) == rad / 2)
4411                         {
4412                                 /* Make an internal wall */
4413                                 place_inner_bold(y, x);
4414                         }
4415                 }
4416         }
4417
4418         /* Add perpendicular walls */
4419         for (x = x0 - rad; x <= x0 + rad; x++)
4420         {
4421                 place_inner_bold(y0, x);
4422         }
4423
4424         for (y = y0 - rad; y <= y0 + rad; y++)
4425         {
4426                 place_inner_bold(y, x0);
4427         }
4428
4429         /* Make inner vault */
4430         for (y = y0 - 1; y <= y0 + 1; y++)
4431         {
4432                 place_inner_bold(y, x0 - 1);
4433                 place_inner_bold(y, x0 + 1);
4434         }
4435         for (x = x0 - 1; x <= x0 + 1; x++)
4436         {
4437                 place_inner_bold(y0 - 1, x);
4438                 place_inner_bold(y0 + 1, x);
4439         }
4440
4441         place_floor_bold(y0, x0);
4442
4443
4444         /* Add doors to vault */
4445         /* get two distances so can place doors relative to centre */
4446         x = (rad - 2) / 4 + 1;
4447         y = rad / 2 + x;
4448
4449         add_door(x0 + x, y0);
4450         add_door(x0 + y, y0);
4451         add_door(x0 - x, y0);
4452         add_door(x0 - y, y0);
4453         add_door(x0, y0 + x);
4454         add_door(x0, y0 + y);
4455         add_door(x0, y0 - x);
4456         add_door(x0, y0 - y);
4457
4458         /* Fill with stuff - medium difficulty */
4459         fill_treasure(x0 - rad, x0 + rad, y0 - rad, y0 + rad, randint1(3) + 3);
4460 }
4461
4462
4463 #ifdef ALLOW_CAVERNS_AND_LAKES
4464 /*
4465  * This routine uses a modified version of the lake code to make a
4466  * distribution of some terrain type over the vault.  This type
4467  * depends on the dungeon depth.
4468  *
4469  * Miniture rooms are then scattered across the vault.
4470  */
4471 static void build_elemental_vault(int x0, int y0, int xsiz, int ysiz)
4472 {
4473         int grd, roug;
4474         int c1, c2, c3;
4475         bool done = FALSE;
4476         int xsize, ysize, xhsize, yhsize, x, y, i;
4477         int type;
4478
4479         msg_print_wizard(CHEAT_DUNGEON, _("精霊界ランダムVaultを生成しました。", "Elemental Vault"));
4480
4481         /* round to make sizes even */
4482         xhsize = xsiz / 2;
4483         yhsize = ysiz / 2;
4484         xsize = xhsize * 2;
4485         ysize = yhsize * 2;
4486
4487         if (dun_level < 25)
4488         {
4489                 /* Earth vault  (Rubble) */
4490                 type = LAKE_T_EARTH_VAULT;
4491         }
4492         else if (dun_level < 50)
4493         {
4494                 /* Air vault (Trees) */
4495                 type = LAKE_T_AIR_VAULT;
4496         }
4497         else if (dun_level < 75)
4498         {
4499                 /* Water vault (shallow water) */
4500                 type = LAKE_T_WATER_VAULT;
4501         }
4502         else
4503         {
4504                 /* Fire vault (shallow lava) */
4505                 type = LAKE_T_FIRE_VAULT;
4506         }
4507
4508         while (!done)
4509         {
4510                 /* testing values for these parameters: feel free to adjust */
4511                 grd = 1 << (randint0(3));
4512
4513                 /* want average of about 16 */
4514                 roug = randint1(8) * randint1(4);
4515
4516                 /* Make up size of various componants */
4517                 /* Floor */
4518                 c3 = 2 * xsize / 3;
4519
4520                 /* Deep water/lava */
4521                 c1 = randint0(c3 / 2) + randint0(c3 / 2) - 5;
4522
4523                 /* Shallow boundary */
4524                 c2 = (c1 + c3) / 2;
4525
4526                 /* make it */
4527                 generate_hmap(y0, x0, xsize, ysize, grd, roug, c3);
4528
4529                 /* Convert to normal format+ clean up */
4530                 done = generate_lake(y0, x0, xsize, ysize, c1, c2, c3, type);
4531         }
4532
4533         /* Set icky flag because is a vault */
4534         for (x = 0; x <= xsize; x++)
4535         {
4536                 for (y = 0; y <= ysize; y++)
4537                 {
4538                         cave[y0 - yhsize + y][x0 - xhsize + x].info |= CAVE_ICKY;
4539                 }
4540         }
4541
4542         /* make a few rooms in the vault */
4543         for (i = 1; i <= (xsize * ysize) / 50; i++)
4544         {
4545                 build_small_room(x0 + randint0(xsize - 4) - xsize / 2 + 2,
4546                                  y0 + randint0(ysize - 4) - ysize / 2 + 2);
4547         }
4548
4549         /* Fill with monsters and treasure, low difficulty */
4550         fill_treasure(x0 - xhsize + 1, x0 - xhsize + xsize - 1,
4551                       y0 - yhsize + 1, y0 - yhsize + ysize - 1, randint1(5));
4552 }
4553 #endif /* ALLOW_CAVERNS_AND_LAKES */
4554
4555
4556 /*!
4557  * @brief タイプ10の部屋…ランダム生成vault / Type 10 -- Random vaults
4558  * @return なし
4559  */
4560 static bool build_type10(void)
4561 {
4562         POSITION y0, x0, xsize, ysize, vtype;
4563
4564         /* Get size */
4565         /* big enough to look good, small enough to be fairly common. */
4566         xsize = randint1(22) + 22;
4567         ysize = randint1(11) + 11;
4568
4569         /* Find and reserve some space in the dungeon.  Get center of room. */
4570         if (!find_space(&y0, &x0, ysize + 1, xsize + 1)) return FALSE;
4571
4572         /* Select type of vault */
4573 #ifdef ALLOW_CAVERNS_AND_LAKES
4574         do
4575         {
4576                 vtype = randint1(15);
4577         }
4578         while ((d_info[dungeon_type].flags1 & DF1_NO_CAVE) &&
4579                 ((vtype == 1) || (vtype == 3) || (vtype == 8) || (vtype == 9) || (vtype == 11)));
4580 #else /* ALLOW_CAVERNS_AND_LAKES */
4581         do
4582         {
4583                 vtype = randint1(7);
4584         }
4585         while ((d_info[dungeon_type].flags1 & DF1_NO_CAVE) &&
4586                 ((vtype == 1) || (vtype == 3)));
4587 #endif /* ALLOW_CAVERNS_AND_LAKES */
4588
4589         switch (vtype)
4590         {
4591                 /* Build an appropriate room */
4592                 case 1: case  9: build_bubble_vault(x0, y0, xsize, ysize); break;
4593                 case 2: case 10: build_room_vault(x0, y0, xsize, ysize); break;
4594                 case 3: case 11: build_cave_vault(x0, y0, xsize, ysize); break;
4595                 case 4: case 12: build_maze_vault(x0, y0, xsize, ysize, TRUE); break;
4596                 case 5: case 13: build_mini_c_vault(x0, y0, xsize, ysize); break;
4597                 case 6: case 14: build_castle_vault(x0, y0, xsize, ysize); break;
4598                 case 7: case 15: build_target_vault(x0, y0, xsize, ysize); break;
4599 #ifdef ALLOW_CAVERNS_AND_LAKES
4600                 case 8: build_elemental_vault(x0, y0, xsize, ysize); break;
4601 #endif /* ALLOW_CAVERNS_AND_LAKES */
4602                 /* I know how to add a few more... give me some time. */
4603
4604                 /* Paranoia */
4605                 default: return FALSE;
4606         }
4607
4608         return TRUE;
4609 }
4610
4611
4612 /*!
4613  * @brief タイプ11の部屋…円形部屋の生成 / Type 11 -- Build an vertical oval room.
4614  * @return なし
4615  * @details
4616  * For every grid in the possible square, check the distance.\n
4617  * If it's less than the radius, make it a room square.\n
4618  *\n
4619  * When done fill from the inside to find the walls,\n
4620  */
4621 static bool build_type11(void)
4622 {
4623         POSITION rad, x, y, x0, y0;
4624         int light = FALSE;
4625
4626         /* Occasional light */
4627         if ((randint1(dun_level) <= 15) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS)) light = TRUE;
4628
4629         rad = randint0(9);
4630
4631         /* Find and reserve some space in the dungeon.  Get center of room. */
4632         if (!find_space(&y0, &x0, rad * 2 + 1, rad * 2 + 1)) return FALSE;
4633
4634         /* Make circular floor */
4635         for (x = x0 - rad; x <= x0 + rad; x++)
4636         {
4637                 for (y = y0 - rad; y <= y0 + rad; y++)
4638                 {
4639                         if (distance(y0, x0, y, x) <= rad - 1)
4640                         {
4641                                 /* inside- so is floor */
4642                                 place_floor_bold(y, x);
4643                         }
4644                         else if (distance(y0, x0, y, x) <= rad + 1)
4645                         {
4646                                 /* make granite outside so arena works */
4647                                 place_extra_bold(y, x);
4648                         }
4649                 }
4650         }
4651
4652         /* Find visible outer walls and set to be FEAT_OUTER */
4653         add_outer_wall(x0, y0, light, x0 - rad, y0 - rad, x0 + rad, y0 + rad);
4654
4655         return TRUE;
4656 }
4657
4658
4659 /*!
4660  * @brief タイプ12の部屋…ドーム型部屋の生成 / Type 12 -- Build crypt room.
4661  * @return なし
4662  * @details
4663  * For every grid in the possible square, check the (fake) distance.\n
4664  * If it's less than the radius, make it a room square.\n
4665  *\n
4666  * When done fill from the inside to find the walls,\n
4667  */
4668 static bool build_type12(void)
4669 {
4670         POSITION rad, x, y, x0, y0;
4671         int light = FALSE;
4672         bool emptyflag = TRUE;
4673
4674         /* Make a random metric */
4675         int h1, h2, h3, h4;
4676         h1 = randint1(32) - 16;
4677         h2 = randint1(16);
4678         h3 = randint1(32);
4679         h4 = randint1(32) - 16;
4680
4681         /* Occasional light */
4682         if ((randint1(dun_level) <= 5) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS)) light = TRUE;
4683
4684         rad = randint1(9);
4685
4686         /* Find and reserve some space in the dungeon.  Get center of room. */
4687         if (!find_space(&y0, &x0, rad * 2 + 3, rad * 2 + 3)) return FALSE;
4688
4689         /* Make floor */
4690         for (x = x0 - rad; x <= x0 + rad; x++)
4691         {
4692                 for (y = y0 - rad; y <= y0 + rad; y++)
4693                 {
4694                         /* clear room flag */
4695                         cave[y][x].info &= ~(CAVE_ROOM);
4696
4697                         if (dist2(y0, x0, y, x, h1, h2, h3, h4) <= rad - 1)
4698                         {
4699                                 /* inside - so is floor */
4700                                 place_floor_bold(y, x);
4701                         }
4702                         else if (distance(y0, x0, y, x) < 3)
4703                         {
4704                                 place_floor_bold(y, x);
4705                         }
4706                         else
4707                         {
4708                                 /* make granite outside so arena works */
4709                                 place_extra_bold(y, x);
4710                         }
4711
4712                         /* proper boundary for arena */
4713                         if (((y + rad) == y0) || ((y - rad) == y0) ||
4714                             ((x + rad) == x0) || ((x - rad) == x0))
4715                         {
4716                                 place_extra_bold(y, x);
4717                         }
4718                 }
4719         }
4720
4721         /* Find visible outer walls and set to be FEAT_OUTER */
4722         add_outer_wall(x0, y0, light, x0 - rad - 1, y0 - rad - 1,
4723                        x0 + rad + 1, y0 + rad + 1);
4724
4725         /* Check to see if there is room for an inner vault */
4726         for (x = x0 - 2; x <= x0 + 2; x++)
4727         {
4728                 for (y = y0 - 2; y <= y0 + 2; y++)
4729                 {
4730                         if (!is_floor_bold(y, x))
4731                         {
4732                                 /* Wall in the way */
4733                                 emptyflag = FALSE;
4734                         }
4735                 }
4736         }
4737
4738         if (emptyflag && one_in_(2))
4739         {
4740                 /* Build the vault */
4741                 build_small_room(x0, y0);
4742
4743                 /* Place a treasure in the vault */
4744                 place_object(y0, x0, 0L);
4745
4746                 /* Let's guard the treasure well */
4747                 vault_monsters(y0, x0, randint0(2) + 3);
4748
4749                 /* Traps naturally */
4750                 vault_traps(y0, x0, 4, 4, randint0(3) + 2);
4751         }
4752
4753         return TRUE;
4754 }
4755
4756
4757 /*
4758  * Helper function for "trapped monster pit"
4759  */
4760 static bool vault_aux_trapped_pit(MONRACE_IDX r_idx)
4761 {
4762         monster_race *r_ptr = &r_info[r_idx];
4763
4764         /* Validate the monster */
4765         if (!vault_monster_okay(r_idx)) return (FALSE);
4766
4767         /* No wall passing monster */
4768         if (r_ptr->flags2 & (RF2_PASS_WALL | RF2_KILL_WALL)) return (FALSE);
4769
4770         /* Okay */
4771         return (TRUE);
4772 }
4773
4774
4775 /*!
4776  * @brief タイプ13の部屋…トラップpitの生成 / Type 13 -- Trapped monster pits
4777  * @return なし
4778  * @details
4779  * A trapped monster pit is a "big" room with a straight corridor in\n
4780  * which wall opening traps are placed, and with two "inner" rooms\n
4781  * containing a "collection" of monsters of a given type organized in\n
4782  * the room.\n
4783  *\n
4784  * The trapped monster pit appears as shown below, where the actual\n
4785  * monsters in each location depend on the type of the pit\n
4786  *\n
4787  *  XXXXXXXXXXXXXXXXXXXXXXXXX\n
4788  *  X                       X\n
4789  *  XXXXXXXXXXXXXXXXXXXXXXX X\n
4790  *  XXXXX001123454321100XXX X\n
4791  *  XXX0012234567654322100X X\n
4792  *  XXXXXXXXXXXXXXXXXXXXXXX X\n
4793  *  X           ^           X\n
4794  *  X XXXXXXXXXXXXXXXXXXXXXXX\n
4795  *  X X0012234567654322100XXX\n
4796  *  X XXX001123454321100XXXXX\n
4797  *  X XXXXXXXXXXXXXXXXXXXXXXX\n
4798  *  X                       X\n
4799  *  XXXXXXXXXXXXXXXXXXXXXXXXX\n
4800  *\n
4801  * Note that the monsters in the pit are now chosen by using "get_mon_num()"\n
4802  * to request 16 "appropriate" monsters, sorting them by level, and using\n
4803  * the "even" entries in this sorted list for the contents of the pit.\n
4804  *\n
4805  * Hack -- all of the "dragons" in a "dragon" pit must be the same "color",\n
4806  * which is handled by requiring a specific "breath" attack for all of the\n
4807  * dragons.  This may include "multi-hued" breath.  Note that "wyrms" may\n
4808  * be present in many of the dragon pits, if they have the proper breath.\n
4809  *\n
4810  * Note the use of the "get_mon_num_prep()" function, and the special\n
4811  * "get_mon_num_hook()" restriction function, to prepare the "monster\n
4812  * allocation table" in such a way as to optimize the selection of\n
4813  * "appropriate" non-unique monsters for the pit.\n
4814  *\n
4815  * Note that the "get_mon_num()" function may (rarely) fail, in which case\n
4816  * the pit will be empty.\n
4817  *\n
4818  * Note that "monster pits" will never contain "unique" monsters.\n
4819  */
4820 static bool build_type13(void)
4821 {
4822         static int placing[][3] = {
4823                 {-2, -9, 0}, {-2, -8, 0}, {-3, -7, 0}, {-3, -6, 0},
4824                 {+2, -9, 0}, {+2, -8, 0}, {+3, -7, 0}, {+3, -6, 0},
4825                 {-2, +9, 0}, {-2, +8, 0}, {-3, +7, 0}, {-3, +6, 0},
4826                 {+2, +9, 0}, {+2, +8, 0}, {+3, +7, 0}, {+3, +6, 0},
4827                 {-2, -7, 1}, {-3, -5, 1}, {-3, -4, 1}, 
4828                 {+2, -7, 1}, {+3, -5, 1}, {+3, -4, 1}, 
4829                 {-2, +7, 1}, {-3, +5, 1}, {-3, +4, 1}, 
4830                 {+2, +7, 1}, {+3, +5, 1}, {+3, +4, 1},
4831                 {-2, -6, 2}, {-2, -5, 2}, {-3, -3, 2},
4832                 {+2, -6, 2}, {+2, -5, 2}, {+3, -3, 2},
4833                 {-2, +6, 2}, {-2, +5, 2}, {-3, +3, 2},
4834                 {+2, +6, 2}, {+2, +5, 2}, {+3, +3, 2},
4835                 {-2, -4, 3}, {-3, -2, 3},
4836                 {+2, -4, 3}, {+3, -2, 3},
4837                 {-2, +4, 3}, {-3, +2, 3},
4838                 {+2, +4, 3}, {+3, +2, 3},
4839                 {-2, -3, 4}, {-3, -1, 4},
4840                 {+2, -3, 4}, {+3, -1, 4},
4841                 {-2, +3, 4}, {-3, +1, 4},
4842                 {+2, +3, 4}, {+3, +1, 4},
4843                 {-2, -2, 5}, {-3, 0, 5}, {-2, +2, 5},
4844                 {+2, -2, 5}, {+3, 0, 5}, {+2, +2, 5},
4845                 {-2, -1, 6}, {-2, +1, 6},
4846                 {+2, -1, 6}, {+2, +1, 6},
4847                 {-2, 0, 7}, {+2, 0, 7},
4848                 {0, 0, -1}
4849         };
4850
4851         POSITION y, x, y1, x1, y2, x2, xval, yval;
4852         int i, j;
4853
4854         MONRACE_IDX what[16];
4855
4856         monster_type align;
4857
4858         cave_type *c_ptr;
4859
4860         int cur_pit_type = pick_vault_type(pit_types, d_info[dungeon_type].pit);
4861         vault_aux_type *n_ptr;
4862
4863         /* Only in Angband */
4864         if (dungeon_type != DUNGEON_ANGBAND) return FALSE;
4865
4866         /* No type available */
4867         if (cur_pit_type < 0) return FALSE;
4868
4869         n_ptr = &pit_types[cur_pit_type];
4870
4871         /* Process a preparation function if necessary */
4872         if (n_ptr->prep_func) (*(n_ptr->prep_func))();
4873
4874         /* Prepare allocation table */
4875         get_mon_num_prep(n_ptr->hook_func, vault_aux_trapped_pit);
4876
4877         align.sub_align = SUB_ALIGN_NEUTRAL;
4878
4879         /* Pick some monster types */
4880         for (i = 0; i < 16; i++)
4881         {
4882                 MONRACE_IDX r_idx = 0;
4883                 int attempts = 100;
4884                 monster_race *r_ptr = NULL;
4885
4886                 while (attempts--)
4887                 {
4888                         /* Get a (hard) monster type */
4889                         r_idx = get_mon_num(dun_level + 0);
4890                         r_ptr = &r_info[r_idx];
4891
4892                         /* Decline incorrect alignment */
4893                         if (monster_has_hostile_align(&align, 0, 0, r_ptr)) continue;
4894
4895                         /* Accept this monster */
4896                         break;
4897                 }
4898
4899                 /* Notice failure */
4900                 if (!r_idx || !attempts) return FALSE;
4901
4902                 /* Note the alignment */
4903                 if (r_ptr->flags3 & RF3_EVIL) align.sub_align |= SUB_ALIGN_EVIL;
4904                 if (r_ptr->flags3 & RF3_GOOD) align.sub_align |= SUB_ALIGN_GOOD;
4905
4906                 what[i] = r_idx;
4907         }
4908
4909         /* Find and reserve some space in the dungeon.  Get center of room. */
4910         if (!find_space(&yval, &xval, 13, 25)) return FALSE;
4911
4912         /* Large room */
4913         y1 = yval - 5;
4914         y2 = yval + 5;
4915         x1 = xval - 11;
4916         x2 = xval + 11;
4917
4918         /* Fill with inner walls */
4919         for (y = y1 - 1; y <= y2 + 1; y++)
4920         {
4921                 for (x = x1 - 1; x <= x2 + 1; x++)
4922                 {
4923                         c_ptr = &cave[y][x];
4924                         place_inner_grid(c_ptr);
4925                         c_ptr->info |= (CAVE_ROOM);
4926                 }
4927         }
4928
4929         /* Place the floor area 1 */
4930         for (x = x1 + 3; x <= x2 - 3; x++)
4931         {
4932                 c_ptr = &cave[yval-2][x];
4933                 place_floor_grid(c_ptr);
4934                 add_cave_info(yval-2, x, CAVE_ICKY);
4935
4936                 c_ptr = &cave[yval+2][x];
4937                 place_floor_grid(c_ptr);
4938                 add_cave_info(yval+2, x, CAVE_ICKY);
4939         }
4940
4941         /* Place the floor area 2 */
4942         for (x = x1 + 5; x <= x2 - 5; x++)
4943         {
4944                 c_ptr = &cave[yval-3][x];
4945                 place_floor_grid(c_ptr);
4946                 add_cave_info(yval-3, x, CAVE_ICKY);
4947
4948                 c_ptr = &cave[yval+3][x];
4949                 place_floor_grid(c_ptr);
4950                 add_cave_info(yval+3, x, CAVE_ICKY);
4951         }
4952
4953         /* Corridor */
4954         for (x = x1; x <= x2; x++)
4955         {
4956                 c_ptr = &cave[yval][x];
4957                 place_floor_grid(c_ptr);
4958                 c_ptr = &cave[y1][x];
4959                 place_floor_grid(c_ptr);
4960                 c_ptr = &cave[y2][x];
4961                 place_floor_grid(c_ptr);
4962         }
4963
4964         /* Place the outer walls */
4965         for (y = y1 - 1; y <= y2 + 1; y++)
4966         {
4967                 c_ptr = &cave[y][x1 - 1];
4968                 place_outer_grid(c_ptr);
4969                 c_ptr = &cave[y][x2 + 1];
4970                 place_outer_grid(c_ptr);
4971         }
4972         for (x = x1 - 1; x <= x2 + 1; x++)
4973         {
4974                 c_ptr = &cave[y1 - 1][x];
4975                 place_outer_grid(c_ptr);
4976                 c_ptr = &cave[y2 + 1][x];
4977                 place_outer_grid(c_ptr);
4978         }
4979
4980         /* Random corridor */
4981         if (one_in_(2))
4982         {
4983                 for (y = y1; y <= yval; y++)
4984                 {
4985                         place_floor_bold(y, x2);
4986                         place_solid_bold(y, x1-1);
4987                 }
4988                 for (y = yval; y <= y2 + 1; y++)
4989                 {
4990                         place_floor_bold(y, x1);
4991                         place_solid_bold(y, x2+1);
4992                 }
4993         }
4994         else
4995         {
4996                 for (y = yval; y <= y2 + 1; y++)
4997                 {
4998                         place_floor_bold(y, x1);
4999                         place_solid_bold(y, x2+1);
5000                 }
5001                 for (y = y1; y <= yval; y++)
5002                 {
5003                         place_floor_bold(y, x2);
5004                         place_solid_bold(y, x1-1);
5005                 }
5006         }
5007
5008         /* Place the wall open trap */
5009         cave[yval][xval].mimic = cave[yval][xval].feat;
5010         cave[yval][xval].feat = feat_trap_open;
5011
5012         /* Sort the entries */
5013         for (i = 0; i < 16 - 1; i++)
5014         {
5015                 /* Sort the entries */
5016                 for (j = 0; j < 16 - 1; j++)
5017                 {
5018                         int i1 = j;
5019                         int i2 = j + 1;
5020
5021                         int p1 = r_info[what[i1]].level;
5022                         int p2 = r_info[what[i2]].level;
5023
5024                         /* Bubble */
5025                         if (p1 > p2)
5026                         {
5027                                 MONRACE_IDX tmp = what[i1];
5028                                 what[i1] = what[i2];
5029                                 what[i2] = tmp;
5030                         }
5031                 }
5032         }
5033
5034         msg_format_wizard(CHEAT_DUNGEON, _("%s%sの罠ピットが生成されました。", "Trapped monster pit (%s%s)"),
5035                 n_ptr->name, pit_subtype_string(cur_pit_type, FALSE));
5036
5037         /* Select the entries */
5038         for (i = 0; i < 8; i++)
5039         {
5040                 /* Every other entry */
5041                 what[i] = what[i * 2];
5042
5043                 if (cheat_hear)
5044                 {
5045                         /* Message */
5046                         msg_print(r_name + r_info[what[i]].name);
5047                 }
5048         }
5049
5050         for (i = 0; placing[i][2] >= 0; i++)
5051         {
5052                 y = yval + placing[i][0];
5053                 x = xval + placing[i][1];
5054                 place_monster_aux(0, y, x, what[placing[i][2]], PM_NO_KAGE);
5055         }
5056
5057         return TRUE;
5058 }
5059
5060
5061 /*!
5062  * @brief タイプ14の部屋…特殊トラップ部屋の生成 / Type 14 -- trapped rooms
5063  * @return なし
5064  * @details
5065  * A special trap is placed at center of the room
5066  */
5067 static bool build_type14(void)
5068 {
5069         POSITION y, x, y2, x2, yval, xval;
5070         POSITION y1, x1, xsize, ysize;
5071
5072         bool light;
5073
5074         cave_type *c_ptr;
5075         s16b trap;
5076
5077         /* Pick a room size */
5078         y1 = randint1(4);
5079         x1 = randint1(11);
5080         y2 = randint1(3);
5081         x2 = randint1(11);
5082
5083         xsize = x1 + x2 + 1;
5084         ysize = y1 + y2 + 1;
5085
5086         /* Find and reserve some space in the dungeon.  Get center of room. */
5087         if (!find_space(&yval, &xval, ysize + 2, xsize + 2)) return FALSE;
5088
5089         /* Choose lite or dark */
5090         light = ((dun_level <= randint1(25)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS));
5091
5092
5093         /* Get corner values */
5094         y1 = yval - ysize / 2;
5095         x1 = xval - xsize / 2;
5096         y2 = yval + (ysize - 1) / 2;
5097         x2 = xval + (xsize - 1) / 2;
5098
5099
5100         /* Place a full floor under the room */
5101         for (y = y1 - 1; y <= y2 + 1; y++)
5102         {
5103                 for (x = x1 - 1; x <= x2 + 1; x++)
5104                 {
5105                         c_ptr = &cave[y][x];
5106                         place_floor_grid(c_ptr);
5107                         c_ptr->info |= (CAVE_ROOM);
5108                         if (light) c_ptr->info |= (CAVE_GLOW);
5109                 }
5110         }
5111
5112         /* Walls around the room */
5113         for (y = y1 - 1; y <= y2 + 1; y++)
5114         {
5115                 c_ptr = &cave[y][x1 - 1];
5116                 place_outer_grid(c_ptr);
5117                 c_ptr = &cave[y][x2 + 1];
5118                 place_outer_grid(c_ptr);
5119         }
5120         for (x = x1 - 1; x <= x2 + 1; x++)
5121         {
5122                 c_ptr = &cave[y1 - 1][x];
5123                 place_outer_grid(c_ptr);
5124                 c_ptr = &cave[y2 + 1][x];
5125                 place_outer_grid(c_ptr);
5126         }
5127
5128         if (dun_level < 30 + randint1(30))
5129                 trap = feat_trap_piranha;
5130         else
5131                 trap = feat_trap_armageddon;
5132
5133         /* Place a special trap */
5134         c_ptr = &cave[rand_spread(yval, ysize/4)][rand_spread(xval, xsize/4)];
5135         c_ptr->mimic = c_ptr->feat;
5136         c_ptr->feat = trap;
5137
5138         msg_format_wizard(CHEAT_DUNGEON, _("%sの部屋が生成されました。", "Room of %s was generated."), f_name + f_info[trap].name);
5139
5140         return TRUE;
5141 }
5142
5143
5144 /*
5145  * Helper function for "glass room"
5146  */
5147 static bool vault_aux_lite(MONRACE_IDX r_idx)
5148 {
5149         monster_race *r_ptr = &r_info[r_idx];
5150
5151         /* Validate the monster */
5152         if (!vault_monster_okay(r_idx)) return FALSE;
5153
5154         /* Require lite attack */
5155         if (!(r_ptr->flags4 & RF4_BR_LITE) && !(r_ptr->a_ability_flags1 & RF5_BA_LITE)) return FALSE;
5156
5157         /* No wall passing monsters */
5158         if (r_ptr->flags2 & (RF2_PASS_WALL | RF2_KILL_WALL)) return FALSE;
5159
5160         /* No disintegrating monsters */
5161         if (r_ptr->flags4 & RF4_BR_DISI) return FALSE;
5162
5163         return TRUE;
5164 }
5165
5166 /*
5167  * Helper function for "glass room"
5168  */
5169 static bool vault_aux_shards(MONRACE_IDX r_idx)
5170 {
5171         monster_race *r_ptr = &r_info[r_idx];
5172
5173         /* Validate the monster */
5174         if (!vault_monster_okay(r_idx)) return FALSE;
5175
5176         /* Require shards breath attack */
5177         if (!(r_ptr->flags4 & RF4_BR_SHAR)) return FALSE;
5178
5179         return TRUE;
5180 }
5181
5182 /*
5183  * Hack -- determine if a template is potion
5184  */
5185 static bool kind_is_potion(KIND_OBJECT_IDX k_idx)
5186 {
5187         return k_info[k_idx].tval == TV_POTION;
5188 }
5189
5190 /*!
5191  * @brief タイプ15の部屋…ガラス部屋の生成 / Type 15 -- glass rooms
5192  * @return なし
5193  */
5194 static bool build_type15(void)
5195 {
5196         POSITION y, x, y2, x2, yval, xval;
5197         POSITION y1, x1, xsize, ysize;
5198         bool light;
5199
5200         cave_type *c_ptr;
5201
5202         /* Pick a room size */
5203         xsize = rand_range(9, 13);
5204         ysize = rand_range(9, 13);
5205
5206         /* Find and reserve some space in the dungeon.  Get center of room. */
5207         if (!find_space(&yval, &xval, ysize + 2, xsize + 2)) return FALSE;
5208
5209         /* Choose lite or dark */
5210         light = ((dun_level <= randint1(25)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS));
5211
5212         /* Get corner values */
5213         y1 = yval - ysize / 2;
5214         x1 = xval - xsize / 2;
5215         y2 = yval + (ysize - 1) / 2;
5216         x2 = xval + (xsize - 1) / 2;
5217
5218         /* Place a full floor under the room */
5219         for (y = y1 - 1; y <= y2 + 1; y++)
5220         {
5221                 for (x = x1 - 1; x <= x2 + 1; x++)
5222                 {
5223                         c_ptr = &cave[y][x];
5224                         place_floor_grid(c_ptr);
5225                         c_ptr->feat = feat_glass_floor;
5226                         c_ptr->info |= (CAVE_ROOM);
5227                         if (light) c_ptr->info |= (CAVE_GLOW);
5228                 }
5229         }
5230
5231         /* Walls around the room */
5232         for (y = y1 - 1; y <= y2 + 1; y++)
5233         {
5234                 c_ptr = &cave[y][x1 - 1];
5235                 place_outer_grid(c_ptr);
5236                 c_ptr->feat = feat_glass_wall;
5237                 c_ptr = &cave[y][x2 + 1];
5238                 place_outer_grid(c_ptr);
5239                 c_ptr->feat = feat_glass_wall;
5240         }
5241         for (x = x1 - 1; x <= x2 + 1; x++)
5242         {
5243                 c_ptr = &cave[y1 - 1][x];
5244                 place_outer_grid(c_ptr);
5245                 c_ptr->feat = feat_glass_wall;
5246                 c_ptr = &cave[y2 + 1][x];
5247                 place_outer_grid(c_ptr);
5248                 c_ptr->feat = feat_glass_wall;
5249         }
5250
5251         switch (randint1(3))
5252         {
5253         case 1: /* 4 lite breathers + potion */
5254                 {
5255                         int dir1, dir2;
5256
5257                         /* Prepare allocation table */
5258                         get_mon_num_prep(vault_aux_lite, NULL);
5259
5260                         /* Place fixed lite berathers */
5261                         for (dir1 = 4; dir1 < 8; dir1++)
5262                         {
5263                                 MONRACE_IDX r_idx = get_mon_num(dun_level);
5264
5265                                 y = yval + 2 * ddy_ddd[dir1];
5266                                 x = xval + 2 * ddx_ddd[dir1];
5267                                 if (r_idx) place_monster_aux(0, y, x, r_idx, PM_ALLOW_SLEEP);
5268
5269                                 /* Walls around the breather */
5270                                 for (dir2 = 0; dir2 < 8; dir2++)
5271                                 {
5272                                         c_ptr = &cave[y + ddy_ddd[dir2]][x + ddx_ddd[dir2]];
5273                                         place_inner_grid(c_ptr);
5274                                         c_ptr->feat = feat_glass_wall;
5275                                 }
5276                         }
5277
5278                         /* Walls around the potion */
5279                         for (dir1 = 0; dir1 < 4; dir1++)
5280                         {
5281                                 y = yval + 2 * ddy_ddd[dir1];
5282                                 x = xval + 2 * ddx_ddd[dir1];
5283                                 c_ptr = &cave[y][x];
5284                                 place_inner_perm_grid(c_ptr);
5285                                 c_ptr->feat = feat_permanent_glass_wall;
5286                                 cave[yval + ddy_ddd[dir1]][xval + ddx_ddd[dir1]].info |= (CAVE_ICKY);
5287                         }
5288
5289                         /* Glass door */
5290                         dir1 = randint0(4);
5291                         y = yval + 2 * ddy_ddd[dir1];
5292                         x = xval + 2 * ddx_ddd[dir1];
5293                         place_secret_door(y, x, DOOR_GLASS_DOOR);
5294                         c_ptr = &cave[y][x];
5295                         if (is_closed_door(c_ptr->feat)) c_ptr->mimic = feat_glass_wall;
5296
5297                         /* Place a potion */
5298                         get_obj_num_hook = kind_is_potion;
5299                         place_object(yval, xval, AM_NO_FIXED_ART);
5300                         cave[yval][xval].info |= (CAVE_ICKY);
5301                 }
5302                 break;
5303
5304         case 2: /* 1 lite breather + random object */
5305                 {
5306                         MONRACE_IDX r_idx;
5307                         DIRECTION dir1;
5308
5309                         /* Pillars */
5310                         c_ptr = &cave[y1 + 1][x1 + 1];
5311                         place_inner_grid(c_ptr);
5312                         c_ptr->feat = feat_glass_wall;
5313
5314                         c_ptr = &cave[y1 + 1][x2 - 1];
5315                         place_inner_grid(c_ptr);
5316                         c_ptr->feat = feat_glass_wall;
5317
5318                         c_ptr = &cave[y2 - 1][x1 + 1];
5319                         place_inner_grid(c_ptr);
5320                         c_ptr->feat = feat_glass_wall;
5321
5322                         c_ptr = &cave[y2 - 1][x2 - 1];
5323                         place_inner_grid(c_ptr);
5324                         c_ptr->feat = feat_glass_wall;
5325
5326                         /* Prepare allocation table */
5327                         get_mon_num_prep(vault_aux_lite, NULL);
5328
5329                         r_idx = get_mon_num(dun_level);
5330                         if (r_idx) place_monster_aux(0, yval, xval, r_idx, 0L);
5331
5332                         /* Walls around the breather */
5333                         for (dir1 = 0; dir1 < 8; dir1++)
5334                         {
5335                                 c_ptr = &cave[yval + ddy_ddd[dir1]][xval + ddx_ddd[dir1]];
5336                                 place_inner_grid(c_ptr);
5337                                 c_ptr->feat = feat_glass_wall;
5338                         }
5339
5340                         /* Curtains around the breather */
5341                         for (y = yval - 1; y <= yval + 1; y++)
5342                         {
5343                                 place_closed_door(y, xval - 2, DOOR_CURTAIN);
5344                                 place_closed_door(y, xval + 2, DOOR_CURTAIN);
5345                         }
5346                         for (x = xval - 1; x <= xval + 1; x++)
5347                         {
5348                                 place_closed_door(yval - 2, x, DOOR_CURTAIN);
5349                                 place_closed_door(yval + 2, x, DOOR_CURTAIN);
5350                         }
5351
5352                         /* Place an object */
5353                         place_object(yval, xval, AM_NO_FIXED_ART);
5354                         cave[yval][xval].info |= (CAVE_ICKY);
5355                 }
5356                 break;
5357
5358         case 3: /* 4 shards breathers + 2 potions */
5359                 {
5360                         int dir1;
5361
5362                         /* Walls around the potion */
5363                         for (y = yval - 2; y <= yval + 2; y++)
5364                         {
5365                                 c_ptr = &cave[y][xval - 3];
5366                                 place_inner_grid(c_ptr);
5367                                 c_ptr->feat = feat_glass_wall;
5368                                 c_ptr = &cave[y][xval + 3];
5369                                 place_inner_grid(c_ptr);
5370                                 c_ptr->feat = feat_glass_wall;
5371                         }
5372                         for (x = xval - 2; x <= xval + 2; x++)
5373                         {
5374                                 c_ptr = &cave[yval - 3][x];
5375                                 place_inner_grid(c_ptr);
5376                                 c_ptr->feat = feat_glass_wall;
5377                                 c_ptr = &cave[yval + 3][x];
5378                                 place_inner_grid(c_ptr);
5379                                 c_ptr->feat = feat_glass_wall;
5380                         }
5381                         for (dir1 = 4; dir1 < 8; dir1++)
5382                         {
5383                                 c_ptr = &cave[yval + 2 * ddy_ddd[dir1]][xval + 2 * ddx_ddd[dir1]];
5384                                 place_inner_grid(c_ptr);
5385                                 c_ptr->feat = feat_glass_wall;
5386                         }
5387
5388                         /* Prepare allocation table */
5389                         get_mon_num_prep(vault_aux_shards, NULL);
5390
5391                         /* Place shard berathers */
5392                         for (dir1 = 4; dir1 < 8; dir1++)
5393                         {
5394                                 MONRACE_IDX r_idx = get_mon_num(dun_level);
5395
5396                                 y = yval + ddy_ddd[dir1];
5397                                 x = xval + ddx_ddd[dir1];
5398                                 if (r_idx) place_monster_aux(0, y, x, r_idx, 0L);
5399                         }
5400
5401                         /* Place two potions */
5402                         if (one_in_(2))
5403                         {
5404                                 get_obj_num_hook = kind_is_potion;
5405                                 place_object(yval, xval - 1, AM_NO_FIXED_ART);
5406                                 get_obj_num_hook = kind_is_potion;
5407                                 place_object(yval, xval + 1, AM_NO_FIXED_ART);
5408                         }
5409                         else
5410                         {
5411                                 get_obj_num_hook = kind_is_potion;
5412                                 place_object(yval - 1, xval, AM_NO_FIXED_ART);
5413                                 get_obj_num_hook = kind_is_potion;
5414                                 place_object(yval + 1, xval, AM_NO_FIXED_ART);
5415                         }
5416
5417                         for (y = yval - 2; y <= yval + 2; y++)
5418                                 for (x = xval - 2; x <= xval + 2; x++)
5419                                         cave[y][x].info |= (CAVE_ICKY);
5420
5421                 }
5422                 break;
5423         }
5424
5425         msg_print_wizard(CHEAT_DUNGEON, _("ガラスの部屋が生成されました。", "Glass room was generated."));
5426
5427         return TRUE;
5428 }
5429
5430
5431 /* Create a new floor room with optional light */
5432 void generate_room_floor(int y1, int x1, int y2, int x2, int light)
5433 {
5434         int y, x;
5435         
5436         cave_type *c_ptr;
5437
5438         for (y = y1; y <= y2; y++)
5439         {
5440                 for (x = x1; x <= x2; x++)
5441                 {
5442                         /* Point to grid */
5443                         c_ptr = &cave[y][x];
5444                         place_floor_grid(c_ptr);
5445                         c_ptr->info |= (CAVE_ROOM);
5446                         if (light) c_ptr->info |= (CAVE_GLOW);
5447                 }
5448         }
5449 }
5450
5451 void generate_fill_perm_bold(int y1, int x1, int y2, int x2)
5452 {
5453         int y, x;
5454
5455         for (y = y1; y <= y2; y++)
5456         {
5457                 for (x = x1; x <= x2; x++)
5458                 {
5459                         /* Point to grid */
5460                         place_inner_perm_bold(y, x);
5461                 }
5462         }
5463 }
5464
5465 /* Minimum & maximum town size */
5466 #define MIN_TOWN_WID ((MAX_WID / 3) / 2)
5467 #define MIN_TOWN_HGT ((MAX_HGT / 3) / 2)
5468 #define MAX_TOWN_WID ((MAX_WID / 3) * 2 / 3)
5469 #define MAX_TOWN_HGT ((MAX_HGT / 3) * 2 / 3)
5470
5471 /* Struct for build underground buildings */
5472 typedef struct
5473 {
5474         int y0, x0; /* North-west corner (relative) */
5475         int y1, x1; /* South-east corner (relative) */
5476 }
5477 ugbldg_type;
5478
5479 ugbldg_type *ugbldg;
5480
5481 /*
5482  * Precalculate buildings' location of underground arcade
5483  */
5484 static bool precalc_ugarcade(int town_hgt, int town_wid, int n)
5485 {
5486         int i, y, x, center_y, center_x, tmp, attempt = 10000;
5487         int max_bldg_hgt = 3 * town_hgt / MAX_TOWN_HGT;
5488         int max_bldg_wid = 5 * town_wid / MAX_TOWN_WID;
5489         ugbldg_type *cur_ugbldg;
5490         bool **ugarcade_used, abort;
5491
5492         /* Allocate "ugarcade_used" array (2-dimension) */
5493         C_MAKE(ugarcade_used, town_hgt, bool *);
5494         C_MAKE(*ugarcade_used, town_hgt * town_wid, bool);
5495         for (y = 1; y < town_hgt; y++) ugarcade_used[y] = *ugarcade_used + y * town_wid;
5496
5497         /* Calculate building locations */
5498         for (i = 0; i < n; i++)
5499         {
5500                 cur_ugbldg = &ugbldg[i];
5501                 (void)WIPE(cur_ugbldg, ugbldg_type);
5502
5503                 do
5504                 {
5505                         /* Find the "center" of the store */
5506                         center_y = rand_range(2, town_hgt - 3);
5507                         center_x = rand_range(2, town_wid - 3);
5508
5509                         /* Determine the store boundaries */
5510                         tmp = center_y - randint1(max_bldg_hgt);
5511                         cur_ugbldg->y0 = MAX(tmp, 1);
5512                         tmp = center_x - randint1(max_bldg_wid);
5513                         cur_ugbldg->x0 = MAX(tmp, 1);
5514                         tmp = center_y + randint1(max_bldg_hgt);
5515                         cur_ugbldg->y1 = MIN(tmp, town_hgt - 2);
5516                         tmp = center_x + randint1(max_bldg_wid);
5517                         cur_ugbldg->x1 = MIN(tmp, town_wid - 2);
5518
5519                         /* Scan this building's area */
5520                         for (abort = FALSE, y = cur_ugbldg->y0; (y <= cur_ugbldg->y1) && !abort; y++)
5521                         {
5522                                 for (x = cur_ugbldg->x0; x <= cur_ugbldg->x1; x++)
5523                                 {
5524                                         if (ugarcade_used[y][x])
5525                                         {
5526                                                 abort = TRUE;
5527                                                 break;
5528                                         }
5529                                 }
5530                         }
5531
5532                         attempt--;
5533                 }
5534                 while (abort && attempt); /* Accept this building if no overlapping */
5535
5536                 /* Failed to generate underground arcade */
5537                 if (!attempt) break;
5538
5539                 /*
5540                  * Mark to ugarcade_used[][] as "used"
5541                  * Note: Building-adjacent grids are included for preventing
5542                  * connected bulidings.
5543                  */
5544                 for (y = cur_ugbldg->y0 - 1; y <= cur_ugbldg->y1 + 1; y++)
5545                 {
5546                         for (x = cur_ugbldg->x0 - 1; x <= cur_ugbldg->x1 + 1; x++)
5547                         {
5548                                 ugarcade_used[y][x] = TRUE;
5549                         }
5550                 }
5551         }
5552
5553         /* Free "ugarcade_used" array (2-dimension) */
5554         C_KILL(*ugarcade_used, town_hgt * town_wid, bool);
5555         C_KILL(ugarcade_used, town_hgt, bool *);
5556
5557         /* If i < n, generation is not allowed */
5558         return i == n;
5559 }
5560
5561 /*!
5562  * @brief タイプ16の部屋…地下都市生成のサブルーチン / Actually create buildings
5563  * @return なし
5564  * @param ltcy 生成基準Y座標
5565  * @param ltcx 生成基準X座標
5566  * @param stotes[] 生成する店舗のリスト
5567  * @param n 生成する店舗の数
5568  * @note
5569  * Note: ltcy and ltcx indicate "left top corner".
5570  */
5571 static void build_stores(int ltcy, int ltcx, int stores[], int n)
5572 {
5573         int i, y, x;
5574         IDX j;
5575         ugbldg_type *cur_ugbldg;
5576
5577         for (i = 0; i < n; i++)
5578         {
5579                 cur_ugbldg = &ugbldg[i];
5580
5581                 /* Generate new room */
5582                 generate_room_floor(
5583                         ltcy + cur_ugbldg->y0 - 2, ltcx + cur_ugbldg->x0 - 2,
5584                         ltcy + cur_ugbldg->y1 + 2, ltcx + cur_ugbldg->x1 + 2,
5585                         FALSE);
5586         }
5587
5588         for (i = 0; i < n; i++)
5589         {
5590                 cur_ugbldg = &ugbldg[i];
5591
5592                 /* Build an invulnerable rectangular building */
5593                 generate_fill_perm_bold(
5594                         ltcy + cur_ugbldg->y0, ltcx + cur_ugbldg->x0,
5595                         ltcy + cur_ugbldg->y1, ltcx + cur_ugbldg->x1);
5596
5597                 /* Pick a door direction (S,N,E,W) */
5598                 switch (randint0(4))
5599                 {
5600                 /* Bottom side */
5601                 case 0:
5602                         y = cur_ugbldg->y1;
5603                         x = rand_range(cur_ugbldg->x0, cur_ugbldg->x1);
5604                         break;
5605
5606                 /* Top side */
5607                 case 1:
5608                         y = cur_ugbldg->y0;
5609                         x = rand_range(cur_ugbldg->x0, cur_ugbldg->x1);
5610                         break;
5611
5612                 /* Right side */
5613                 case 2:
5614                         y = rand_range(cur_ugbldg->y0, cur_ugbldg->y1);
5615                         x = cur_ugbldg->x1;
5616                         break;
5617
5618                 /* Left side */
5619                 default:
5620                         y = rand_range(cur_ugbldg->y0, cur_ugbldg->y1);
5621                         x = cur_ugbldg->x0;
5622                         break;
5623                 }
5624
5625                 for (j = 0; j < max_f_idx; j++)
5626                 {
5627                         if (have_flag(f_info[j].flags, FF_STORE))
5628                         {
5629                                 if (f_info[j].subtype == stores[i]) break;
5630                         }
5631                 }
5632
5633                 /* Clear previous contents, add a store door */
5634                 if (j < max_f_idx)
5635                 {
5636                         cave_set_feat(ltcy + y, ltcx + x, j);
5637
5638                         /* Init store */
5639                         store_init(NO_TOWN, stores[i]);
5640                 }
5641         }
5642 }
5643
5644
5645 /*!
5646  * @brief タイプ16の部屋…地下都市の生成 / Type 16 -- Underground Arcade
5647  * @return なし
5648  * @details
5649  * Town logic flow for generation of new town\n
5650  * Originally from Vanilla 3.0.3\n
5651  *\n
5652  * We start with a fully wiped cave of normal floors.\n
5653  *\n
5654  * Note that town_gen_hack() plays games with the R.N.G.\n
5655  *\n
5656  * This function does NOT do anything about the owners of the stores,\n
5657  * nor the contents thereof.  It only handles the physical layout.\n
5658  */
5659 static bool build_type16(void)
5660 {
5661         int stores[] =
5662         {
5663                 STORE_GENERAL, STORE_ARMOURY, STORE_WEAPON, STORE_TEMPLE,
5664                 STORE_ALCHEMIST, STORE_MAGIC, STORE_BLACK, STORE_BOOK,
5665         };
5666         int n = sizeof stores / sizeof (int);
5667         POSITION i, y, x, y1, x1, yval, xval;
5668         int town_hgt = rand_range(MIN_TOWN_HGT, MAX_TOWN_HGT);
5669         int town_wid = rand_range(MIN_TOWN_WID, MAX_TOWN_WID);
5670         bool prevent_bm = FALSE;
5671
5672         /* Hack -- If already exist black market, prevent building */
5673         for (y = 0; (y < cur_hgt) && !prevent_bm; y++)
5674         {
5675                 for (x = 0; x < cur_wid; x++)
5676                 {
5677                         if (cave[y][x].feat == FF_STORE)
5678                         {
5679                                 prevent_bm = (f_info[cave[y][x].feat].subtype == STORE_BLACK);
5680                                 break;
5681                         }
5682                 }
5683         }
5684         for (i = 0; i < n; i++)
5685         {
5686                 if ((stores[i] == STORE_BLACK) && prevent_bm) stores[i] = stores[--n];
5687         }
5688         if (!n) return FALSE;
5689
5690         /* Allocate buildings array */
5691         C_MAKE(ugbldg, n, ugbldg_type);
5692
5693         /* If cannot build stores, abort */
5694         if (!precalc_ugarcade(town_hgt, town_wid, n))
5695         {
5696                 /* Free buildings array */
5697                 C_KILL(ugbldg, n, ugbldg_type);
5698                 return FALSE;
5699         }
5700
5701         /* Find and reserve some space in the dungeon.  Get center of room. */
5702         if (!find_space(&yval, &xval, town_hgt + 4, town_wid + 4))
5703         {
5704                 /* Free buildings array */
5705                 C_KILL(ugbldg, n, ugbldg_type);
5706                 return FALSE;
5707         }
5708
5709         /* Get top left corner */
5710         y1 = yval - (town_hgt / 2);
5711         x1 = xval - (town_wid / 2);
5712
5713         /* Generate new room */
5714         generate_room_floor(
5715                 y1 + town_hgt / 3, x1 + town_wid / 3,
5716                 y1 + town_hgt * 2 / 3, x1 + town_wid * 2 / 3, FALSE);
5717
5718         /* Build stores */
5719         build_stores(y1, x1, stores, n);
5720
5721         msg_print_wizard(CHEAT_DUNGEON, _("地下街を生成しました", "Underground arcade was generated."));
5722
5723         /* Free buildings array */
5724         C_KILL(ugbldg, n, ugbldg_type);
5725
5726         return TRUE;
5727 }
5728
5729
5730 /*!
5731  * @brief 与えられた部屋型IDに応じて部屋の生成処理分岐を行い結果を返す / Attempt to build a room of the given type at the given block
5732  * @param type 部屋型ID
5733  * @note that we restrict the number of "crowded" rooms to reduce the chance of overflowing the monster list during level creation.
5734  * @return 部屋の精製に成功した場合 TRUE を返す。
5735  */
5736 static bool room_build(int typ)
5737 {
5738         /* Build a room */
5739         switch (typ)
5740         {
5741         /* Build an appropriate room */
5742         case ROOM_T_NORMAL:        return build_type1();
5743         case ROOM_T_OVERLAP:       return build_type2();
5744         case ROOM_T_CROSS:         return build_type3();
5745         case ROOM_T_INNER_FEAT:    return build_type4();
5746         case ROOM_T_NEST:          return build_type5();
5747         case ROOM_T_PIT:           return build_type6();
5748         case ROOM_T_LESSER_VAULT:  return build_type7();
5749         case ROOM_T_GREATER_VAULT: return build_type8();
5750         case ROOM_T_FRACAVE:       return build_type9();
5751         case ROOM_T_RANDOM_VAULT:  return build_type10();
5752         case ROOM_T_OVAL:          return build_type11();
5753         case ROOM_T_CRYPT:         return build_type12();
5754         case ROOM_T_TRAP_PIT:      return build_type13();
5755         case ROOM_T_TRAP:          return build_type14();
5756         case ROOM_T_GLASS:         return build_type15();
5757         case ROOM_T_ARCADE:        return build_type16();
5758         }
5759
5760         /* Paranoia */
5761         return FALSE;
5762 }
5763
5764 /*!
5765  * @brief 指定した部屋の生成確率を別の部屋に加算し、指定した部屋の生成率を0にする
5766  * @param dst 確率を移す先の部屋種ID
5767  * @param src 確率を与える元の部屋種ID
5768  */
5769 #define MOVE_PLIST(dst, src) (prob_list[dst] += prob_list[src], prob_list[src] = 0) 
5770
5771 /*!
5772  * @brief 部屋生成処理のメインルーチン(Sangbandを経由してOangbandからの実装を引用) / Generate rooms in dungeon.  Build bigger rooms at first. [from SAngband (originally from OAngband)]
5773  * @return 部屋生成に成功した場合 TRUE を返す。
5774  */
5775 bool generate_rooms(void)
5776 {
5777         int i;
5778         bool remain;
5779         int crowded = 0;
5780         int total_prob;
5781         int prob_list[ROOM_T_MAX];
5782         int rooms_built = 0;
5783         int area_size = 100 * (cur_hgt*cur_wid) / (MAX_HGT*MAX_WID);
5784         int level_index = MIN(10, div_round(dun_level, 10));
5785
5786         /* Number of each type of room on this level */
5787         s16b room_num[ROOM_T_MAX];
5788
5789         /* Limit number of rooms */
5790         int dun_rooms = DUN_ROOMS_MAX * area_size / 100;
5791
5792         /* Assume normal cave */
5793         room_info_type *room_info_ptr = room_info_normal;
5794
5795         /*
5796          * Initialize probability list.
5797          */
5798         for (i = 0; i < ROOM_T_MAX; i++)
5799         {
5800                 /* No rooms allowed above their minimum depth. */
5801                 if (dun_level < room_info_ptr[i].min_level)
5802                 {
5803                         prob_list[i] = 0;
5804                 }
5805                 else
5806                 {
5807                         prob_list[i] = room_info_ptr[i].prob[level_index];
5808                 }
5809         }
5810
5811         /*
5812          * XXX -- Various dungeon types and options.
5813          */
5814
5815         /*! @details ダンジョンにBEGINNER、CHAMELEON、SMALLESTいずれのフラグもなく、かつ「常に通常でない部屋を生成する」フラグがONならば、GRATER_VAULTのみを生成対象とする。 / Ironman sees only Greater Vaults */
5816         if (ironman_rooms && !((d_info[dungeon_type].flags1 & (DF1_BEGINNER | DF1_CHAMELEON | DF1_SMALLEST))))
5817         {
5818                 for (i = 0; i < ROOM_T_MAX; i++)
5819                 {
5820                         if (i == ROOM_T_GREATER_VAULT) prob_list[i] = 1;
5821                         else prob_list[i] = 0;
5822                 }
5823         }
5824
5825         /*! @details ダンジョンにNO_VAULTフラグがあるならば、LESSER_VAULT / GREATER_VAULT/ RANDOM_VAULTを除外 / Forbidden vaults */
5826         else if (d_info[dungeon_type].flags1 & DF1_NO_VAULT)
5827         {
5828                 prob_list[ROOM_T_LESSER_VAULT] = 0;
5829                 prob_list[ROOM_T_GREATER_VAULT] = 0;
5830                 prob_list[ROOM_T_RANDOM_VAULT] = 0;
5831         }
5832
5833         /*! @details ダンジョンにNO_CAVEフラグがある場合、FRACAVEの生成枠がNORMALに与えられる。CRIPT、OVALの生成枠がINNER_Fに与えられる。/ NO_CAVE dungeon (Castle)*/
5834         if (d_info[dungeon_type].flags1 & DF1_NO_CAVE)
5835         {
5836                 MOVE_PLIST(ROOM_T_NORMAL, ROOM_T_FRACAVE);
5837                 MOVE_PLIST(ROOM_T_INNER_FEAT, ROOM_T_CRYPT);
5838                 MOVE_PLIST(ROOM_T_INNER_FEAT, ROOM_T_OVAL);
5839         }
5840
5841         /*! @details ダンジョンにCAVEフラグがある場合、NORMALの生成枠がFRACAVEに与えられる。/ CAVE dungeon (Orc cave etc.) */
5842         else if (d_info[dungeon_type].flags1 & DF1_CAVE)
5843         {
5844                 MOVE_PLIST(ROOM_T_FRACAVE, ROOM_T_NORMAL);
5845         }
5846
5847         /*! @details ダンジョンの基本地形が最初から渓谷かアリーナ型の場合 FRACAVE は生成から除外。 /  No caves when a (random) cavern exists: they look bad */
5848         else if (dun->cavern || dun->empty_level)
5849         {
5850                 prob_list[ROOM_T_FRACAVE] = 0;
5851         }
5852
5853         /*! @details ダンジョンに最初からGLASS_ROOMフラグがある場合、GLASS を生成から除外。/ Forbidden glass rooms */
5854         if (!(d_info[dungeon_type].flags1 & DF1_GLASS_ROOM))
5855         {
5856                 prob_list[ROOM_T_GLASS] = 0;
5857         }
5858
5859         /*! @details ARCADEは同フラグがダンジョンにないと生成されない。 / Forbidden glass rooms */
5860         if (!(d_info[dungeon_type].flags1 & DF1_ARCADE))
5861         {
5862                 prob_list[ROOM_T_ARCADE] = 0;
5863         }
5864
5865         /*
5866          * Initialize number of rooms,
5867          * And calcurate total probability.
5868          */
5869         for (total_prob = 0, i = 0; i < ROOM_T_MAX; i++)
5870         {
5871                 room_num[i] = 0;
5872                 total_prob += prob_list[i];
5873         }
5874
5875         /*
5876          * Prepare the number of rooms, of all types, we should build
5877          * on this level.
5878          */
5879         for (i = dun_rooms; i > 0; i--)
5880         {
5881                 int room_type;
5882                 int rand = randint0(total_prob);
5883
5884                 /* Get room_type randomly */
5885                 for (room_type = 0; room_type < ROOM_T_MAX; room_type++)
5886                 {
5887                         if (rand < prob_list[room_type]) break;
5888                         else rand -= prob_list[room_type];
5889                 }
5890
5891                 /* Paranoia */
5892                 if (room_type >= ROOM_T_MAX) room_type = ROOM_T_NORMAL;
5893
5894                 /* Increase the number of rooms of that type we should build. */
5895                 room_num[room_type]++;
5896
5897                 switch (room_type)
5898                 {
5899                 case ROOM_T_NEST:
5900                 case ROOM_T_PIT:
5901                 case ROOM_T_LESSER_VAULT:
5902                 case ROOM_T_TRAP_PIT:
5903                 case ROOM_T_GLASS:
5904                 case ROOM_T_ARCADE:
5905
5906                         /* Large room */
5907                         i -= 2;
5908                         break;
5909
5910                 case ROOM_T_GREATER_VAULT:
5911                 case ROOM_T_RANDOM_VAULT:
5912
5913                         /* Largest room */
5914                         i -= 3;
5915                         break;
5916                 }
5917         }
5918
5919         /*
5920          * Build each type of room one by one until we cannot build any more.
5921          * [from SAngband (originally from OAngband)]
5922          */
5923         while (TRUE)
5924         {
5925                 /* Assume no remaining rooms */
5926                 remain = FALSE;
5927
5928                 for (i = 0; i < ROOM_T_MAX; i++)
5929                 {
5930                         /* What type of room are we building now? */
5931                         int room_type = room_build_order[i];
5932
5933                         /* Go next if none available */
5934                         if (!room_num[room_type]) continue;
5935
5936                         /* Use up one unit */
5937                         room_num[room_type]--;
5938
5939                         /* Build the room. */
5940                         if (room_build(room_type))
5941                         {
5942                                 /* Increase the room built count. */
5943                                 rooms_built++;
5944
5945                                 /* Mark as there was some remaining rooms */
5946                                 remain = TRUE;
5947
5948                                 switch (room_type)
5949                                 {
5950                                 case ROOM_T_PIT:
5951                                 case ROOM_T_NEST:
5952                                 case ROOM_T_TRAP_PIT:
5953
5954                                         /* Avoid too many monsters */
5955                                         if (++crowded >= 2)
5956                                         {
5957                                                 room_num[ROOM_T_PIT] = 0;
5958                                                 room_num[ROOM_T_NEST] = 0;
5959                                                 room_num[ROOM_T_TRAP_PIT] = 0;
5960                                         }
5961                                         break;
5962
5963                                 case ROOM_T_ARCADE:
5964
5965                                         /* Avoid double-town */
5966                                         room_num[ROOM_T_ARCADE] = 0;
5967                                         break;
5968                                 }
5969                         }
5970                 }
5971
5972                 /* End loop if no room remain */
5973                 if (!remain) break;
5974         }
5975
5976         /*! @details 部屋生成数が2未満の場合生成失敗を返す */
5977         if (rooms_built < 2)
5978         {
5979                 msg_format_wizard(CHEAT_DUNGEON, _("部屋数が2未満でした。生成を再試行します。", "Number of rooms was under 2. Retry."), rooms_built);
5980                 return FALSE;
5981         }
5982
5983         msg_format_wizard(CHEAT_DUNGEON, _("このダンジョンの部屋数は %d です。", "Number of Rooms: %d"), rooms_built);
5984
5985         return TRUE;
5986 }