OSDN Git Service

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