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