OSDN Git Service

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