OSDN Git Service

lesser vaultやgreater vaultの生成失敗時のreturn FALSEする位置を変更.
[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;
2830         int dummy;
2831         int x, y;
2832         int xval, yval;
2833         int xoffset, yoffset;
2834         int transno;
2835
2836         /* Pick a lesser vault */
2837         for (dummy = 0; dummy < SAFE_MAX_ATTEMPTS; dummy++)
2838         {
2839                 /* Access a random vault record */
2840                 v_ptr = &v_info[randint0(max_v_idx)];
2841
2842                 /* Accept the first lesser vault */
2843                 if (v_ptr->typ == 7) break;
2844         }
2845
2846         /* No lesser vault found */
2847         if (dummy >= SAFE_MAX_ATTEMPTS)
2848         {
2849                 if (cheat_room)
2850                 {
2851 #ifdef JP
2852                         msg_print("·Ù¹ð¡ª¾®¤µ¤ÊÃϲ¼¼¼¤òÇÛÃ֤Ǥ­¤Þ¤»¤ó¡ª");
2853 #else
2854                         msg_print("Warning! Could not place lesser vault!");
2855 #endif
2856                 }
2857                 return FALSE;
2858         }
2859
2860         /* pick type of transformation (0-7) */
2861         transno = randint0(8);
2862
2863         /* calculate offsets */
2864         x = v_ptr->wid;
2865         y = v_ptr->hgt;
2866
2867         /* Some huge vault cannot be ratated to fit in the dungeon */
2868         if (x+2 > cur_hgt-2)
2869         {
2870                 /* Forbid 90 or 270 degree ratation */
2871                 transno &= ~1;
2872         }
2873
2874         coord_trans(&x, &y, 0, 0, transno);
2875
2876         if (x < 0)
2877         {
2878                 xoffset = -x - 1;
2879         }
2880         else
2881         {
2882                 xoffset = 0;
2883         }
2884
2885         if (y < 0)
2886         {
2887                 yoffset = -y - 1;
2888         }
2889         else
2890         {
2891                 yoffset = 0;
2892         }
2893
2894         /* Find and reserve some space in the dungeon.  Get center of room. */
2895         if (!find_space(&yval, &xval, abs(y), abs(x))) return FALSE;
2896
2897 #ifdef FORCE_V_IDX
2898         v_ptr = &v_info[2];
2899 #endif
2900
2901         /* Message */
2902 #ifdef JP
2903         if (cheat_room) msg_format("¾®¤µ¤ÊÃϲ¼¼¼(%s)", v_name + v_ptr->name);
2904 #else
2905         if (cheat_room) msg_format("Lesser vault (%s)", v_name + v_ptr->name);
2906 #endif
2907
2908         /* Boost the rating */
2909         rating += v_ptr->rat;
2910
2911         /* (Sometimes) Cause a special feeling */
2912         if ((dun_level <= 50) ||
2913                 (randint1((dun_level - 40) * (dun_level - 40) + 50) < 400))
2914         {
2915                 good_item_flag = TRUE;
2916         }
2917
2918         /* Hack -- Build the vault */
2919         build_vault(yval, xval, v_ptr->hgt, v_ptr->wid,
2920                     v_text + v_ptr->text, xoffset, yoffset, transno);
2921
2922         return TRUE;
2923 }
2924
2925
2926 /*
2927  * Type 8 -- greater vaults (see "v_info.txt")
2928  */
2929 static bool build_type8(void)
2930 {
2931         vault_type *v_ptr;
2932         int dummy;
2933         int xval, yval;
2934         int x, y;
2935         int transno;
2936         int xoffset, yoffset;
2937
2938         /* Pick a greater vault */
2939         for (dummy = 0; dummy < SAFE_MAX_ATTEMPTS; dummy++)
2940         {
2941                 /* Access a random vault record */
2942                 v_ptr = &v_info[randint0(max_v_idx)];
2943
2944                 /* Accept the first greater vault */
2945                 if (v_ptr->typ == 8) break;
2946         }
2947
2948         /* No greater vault found */
2949         if (dummy >= SAFE_MAX_ATTEMPTS)
2950         {
2951                 if (cheat_room)
2952                 {
2953 #ifdef JP
2954                         msg_print("·Ù¹ð¡ªµðÂç¤ÊÃϲ¼¼¼¤òÇÛÃ֤Ǥ­¤Þ¤»¤ó¡ª");
2955 #else
2956                         msg_print("Warning! Could not place greater vault!");
2957 #endif
2958                 }
2959                 return FALSE;
2960         }
2961
2962         /* pick type of transformation (0-7) */
2963         transno = randint0(8);
2964
2965         /* calculate offsets */
2966         x = v_ptr->wid;
2967         y = v_ptr->hgt;
2968
2969         /* Some huge vault cannot be ratated to fit in the dungeon */
2970         if (x+2 > cur_hgt-2)
2971         {
2972                 /* Forbid 90 or 270 degree ratation */
2973                 transno &= ~1;
2974         }
2975
2976         coord_trans(&x, &y, 0, 0, transno);
2977
2978         if (x < 0)
2979         {
2980                 xoffset = - x - 1;
2981         }
2982         else
2983         {
2984                 xoffset = 0;
2985         }
2986
2987         if (y < 0)
2988         {
2989                 yoffset = - y - 1;
2990         }
2991         else
2992         {
2993                 yoffset = 0;
2994         }
2995
2996         /*
2997          * Try to allocate space for room.  If fails, exit
2998          *
2999          * Hack -- Prepare a bit larger space (+2, +2) to 
3000          * prevent generation of vaults with no-entrance.
3001          */
3002         /* Find and reserve some space in the dungeon.  Get center of room. */
3003         if (!find_space(&yval, &xval, abs(y) + 2, abs(x) + 2)) return FALSE;
3004
3005 #ifdef FORCE_V_IDX
3006         v_ptr = &v_info[76 + randint1(3)];
3007 #endif
3008
3009         /* Message */
3010 #ifdef JP
3011         if (cheat_room) msg_format("µðÂç¤ÊÃϲ¼¼¼(%s)", v_name + v_ptr->name);
3012 #else
3013         if (cheat_room) msg_format("Greater vault (%s)", v_name + v_ptr->name);
3014 #endif
3015
3016         /* Boost the rating */
3017         rating += v_ptr->rat;
3018
3019         /* (Sometimes) Cause a special feeling */
3020         if ((dun_level <= 50) ||
3021             (randint1((dun_level - 40) * (dun_level - 40) + 50) < 400))
3022         {
3023                 good_item_flag = TRUE;
3024         }
3025
3026         /* Hack -- Build the vault */
3027         build_vault(yval, xval, v_ptr->hgt, v_ptr->wid,
3028                     v_text + v_ptr->text, xoffset, yoffset, transno);
3029
3030         return TRUE;
3031 }
3032
3033 /*
3034  * Structure to hold all "fill" data
3035  */
3036
3037 typedef struct fill_data_type fill_data_type;
3038
3039 struct fill_data_type
3040 {
3041         /* area size */
3042         int xmin;
3043         int ymin;
3044         int xmax;
3045         int ymax;
3046
3047         /* cutoffs */
3048         int c1;
3049         int c2;
3050         int c3;
3051
3052         /* features to fill with */
3053         int feat1;
3054         int feat2;
3055         int feat3;
3056
3057         int info1;
3058         int info2;
3059         int info3;
3060
3061         /* number of filled squares */
3062         int amount;
3063 };
3064
3065 static fill_data_type fill_data;
3066
3067
3068 /* Store routine for the fractal cave generator */
3069 /* this routine probably should be an inline function or a macro. */
3070 static void store_height(int x, int y, int val)
3071 {
3072         /* if on boundary set val > cutoff so walls are not as square */
3073         if (((x == fill_data.xmin) || (y == fill_data.ymin) ||
3074              (x == fill_data.xmax) || (y == fill_data.ymax)) &&
3075             (val <= fill_data.c1)) val = fill_data.c1 + 1;
3076
3077         /* store the value in height-map format */
3078         cave[y][x].feat = val;
3079
3080         return;
3081 }
3082
3083
3084 /*
3085 * Explanation of the plasma fractal algorithm:
3086 *
3087 * A grid of points is created with the properties of a 'height-map'
3088 * This is done by making the corners of the grid have a random value.
3089 * The grid is then subdivided into one with twice the resolution.
3090 * The new points midway between two 'known' points can be calculated
3091 * by taking the average value of the 'known' ones and randomly adding
3092 * or subtracting an amount proportional to the distance between those
3093 * points.  The final 'middle' points of the grid are then calculated
3094 * by averaging all four of the originally 'known' corner points.  An
3095 * random amount is added or subtracted from this to get a value of the
3096 * height at that point.  The scaling factor here is adjusted to the
3097 * slightly larger distance diagonally as compared to orthogonally.
3098 *
3099 * This is then repeated recursively to fill an entire 'height-map'
3100 * A rectangular map is done the same way, except there are different
3101 * scaling factors along the x and y directions.
3102 *
3103 * A hack to change the amount of correlation between points is done using
3104 * the grd variable.  If the current step size is greater than grd then
3105 * the point will be random, otherwise it will be calculated by the
3106 * above algorithm.  This makes a maximum distance at which two points on
3107 * the height map can affect each other.
3108 *
3109 * How fractal caves are made:
3110 *
3111 * When the map is complete, a cut-off value is used to create a cave.
3112 * Heights below this value are "floor", and heights above are "wall".
3113 * This also can be used to create lakes, by adding more height levels
3114 * representing shallow and deep water/ lava etc.
3115 *
3116 * The grd variable affects the width of passages.
3117 * The roug variable affects the roughness of those passages
3118 *
3119 * The tricky part is making sure the created cave is connected.  This
3120 * is done by 'filling' from the inside and only keeping the 'filled'
3121 * floor.  Walls bounding the 'filled' floor are also kept.  Everything
3122 * else is converted to the normal granite FEAT_WALL_EXTRA.
3123  */
3124
3125
3126 /*
3127  *  Note that this uses the cave.feat array in a very hackish way
3128  *  the values are first set to zero, and then each array location
3129  *  is used as a "heightmap"
3130  *  The heightmap then needs to be converted back into the "feat" format.
3131  *
3132  *  grd=level at which fractal turns on.  smaller gives more mazelike caves
3133  *  roug=roughness level.  16=normal.  higher values make things more convoluted
3134  *    small values are good for smooth walls.
3135  *  size=length of the side of the square cave system.
3136  */
3137 static void generate_hmap(int y0, int x0, int xsiz, int ysiz, int grd, int roug, int cutoff)
3138 {
3139         int xhsize, yhsize, xsize, ysize, maxsize;
3140
3141         /*
3142          * fixed point variables- these are stored as 256 x normal value
3143          * this gives 8 binary places of fractional part + 8 places of normal part
3144          */
3145
3146         u16b xstep, xhstep, ystep, yhstep;
3147         u16b xstep2, xhstep2, ystep2, yhstep2;
3148         u16b i, j, ii, jj, diagsize, xxsize, yysize;
3149         
3150         /* Cache for speed */
3151         u16b xm, xp, ym, yp;
3152
3153         /* redefine size so can change the value if out of range */
3154         xsize = xsiz;
3155         ysize = ysiz;
3156
3157         /* Paranoia about size of the system of caves */
3158         if (xsize > 254) xsize = 254;
3159         if (xsize < 4) xsize = 4;
3160         if (ysize > 254) ysize = 254;
3161         if (ysize < 4) ysize = 4;
3162
3163         /* get offsets to middle of array */
3164         xhsize = xsize / 2;
3165         yhsize = ysize / 2;
3166
3167         /* fix rounding problem */
3168         xsize = xhsize * 2;
3169         ysize = yhsize * 2;
3170
3171         /* get limits of region */
3172         fill_data.xmin = x0 - xhsize;
3173         fill_data.ymin = y0 - yhsize;
3174         fill_data.xmax = x0 + xhsize;
3175         fill_data.ymax = y0 + yhsize;
3176         
3177         /* Store cutoff in global for quick access */
3178         fill_data.c1 = cutoff;
3179         
3180         /*
3181         * Scale factor for middle points:
3182         * About sqrt(2) * 256 - correct for a square lattice
3183         * approximately correct for everything else.
3184          */
3185         diagsize = 362;
3186
3187         /* maximum of xsize and ysize */
3188         maxsize = (xsize > ysize) ? xsize : ysize;
3189
3190         /* Clear the section */
3191         for (i = 0; i <= xsize; i++)
3192         {
3193                 for (j = 0; j <= ysize; j++)
3194                 {
3195                         /* 255 is a flag for "not done yet" */
3196                         cave[(int)(fill_data.ymin + j)][(int)(fill_data.xmin + i)].feat = 255;
3197                         /* Clear icky flag because may be redoing the cave */
3198                         cave[(int)(fill_data.ymin + j)][(int)(fill_data.xmin + i)].info &= ~(CAVE_ICKY);
3199                 }
3200         }
3201
3202         /* Boundaries are walls */
3203         cave[fill_data.ymin][fill_data.xmin].feat = maxsize;
3204         cave[fill_data.ymax][fill_data.xmin].feat = maxsize;
3205         cave[fill_data.ymin][fill_data.xmax].feat = maxsize;
3206         cave[fill_data.ymax][fill_data.xmax].feat = maxsize;
3207
3208         /* Set the middle square to be an open area. */
3209         cave[y0][x0].feat = 0;
3210
3211         /* Initialize the step sizes */
3212         xstep = xhstep = xsize * 256;
3213         ystep = yhstep = ysize * 256;
3214         xxsize = xsize * 256;
3215         yysize = ysize * 256;
3216
3217         /*
3218          * Fill in the rectangle with fractal height data -
3219          * like the 'plasma fractal' in fractint.
3220          */
3221         while ((xhstep > 256) || (yhstep > 256))
3222         {
3223                 /* Halve the step sizes */
3224                 xstep = xhstep;
3225                 xhstep /= 2;
3226                 ystep = yhstep;
3227                 yhstep /= 2;
3228                 
3229                 /* cache well used values */
3230                 xstep2 = xstep / 256;
3231                 ystep2 = ystep / 256;
3232                 
3233                 xhstep2 = xhstep / 256;
3234                 yhstep2 = yhstep / 256;
3235
3236                 /* middle top to bottom. */
3237                 for (i = xhstep; i <= xxsize - xhstep; i += xstep)
3238                 {
3239                         for (j = 0; j <= yysize; j += ystep)
3240                         {
3241                                 /* cache often used values */
3242                                 ii = i / 256 + fill_data.xmin;
3243                                 jj = j / 256 + fill_data.ymin;
3244                                 
3245                                 /* Test square */
3246                                 if (cave[jj][ii].feat == 255)
3247                                 {                               
3248                                         if (xhstep2 > grd)
3249                                         {
3250                                                 /* If greater than 'grid' level then is random */
3251                                                 store_height(ii, jj, randint1(maxsize));
3252                                         }
3253                                         else
3254                                         {
3255                                                 /* Average of left and right points +random bit */
3256                                                 store_height(ii, jj,
3257                                                         (cave[jj][fill_data.xmin + (i - xhstep) / 256].feat
3258                                                          + cave[jj][fill_data.xmin + (i + xhstep) / 256].feat) / 2
3259                                                          + (randint1(xstep2) - xhstep2) * roug / 16);
3260                                         }
3261                                 }
3262                         }
3263                 }
3264
3265
3266                 /* middle left to right. */
3267                 for (j = yhstep; j <= yysize - yhstep; j += ystep)
3268                 {
3269                         for (i = 0; i <= xxsize; i += xstep)
3270                         {
3271                                 /* cache often used values */
3272                                 ii = i / 256 + fill_data.xmin;
3273                                 jj = j / 256 + fill_data.ymin;
3274                                 
3275                                 /* Test square */
3276                                 if (cave[jj][ii].feat == 255)
3277                                 {
3278                                         if (xhstep2 > grd)
3279                                         {
3280                                                 /* If greater than 'grid' level then is random */
3281                                                 store_height(ii, jj, randint1(maxsize));
3282                                         }
3283                                         else
3284                                         {
3285                                                 /* Average of up and down points +random bit */
3286                                                 store_height(ii, jj,
3287                                                         (cave[fill_data.ymin + (j - yhstep) / 256][ii].feat
3288                                                         + cave[fill_data.ymin + (j + yhstep) / 256][ii].feat) / 2
3289                                                         + (randint1(ystep2) - yhstep2) * roug / 16);
3290                                         }
3291                                 }
3292                         }
3293                 }
3294
3295                 /* center. */
3296                 for (i = xhstep; i <= xxsize - xhstep; i += xstep)
3297                 {
3298                         for (j = yhstep; j <= yysize - yhstep; j += ystep)
3299                         {
3300                                 /* cache often used values */
3301                                 ii = i / 256 + fill_data.xmin;
3302                                 jj = j / 256 + fill_data.ymin;
3303                                 
3304                                 /* Test square */
3305                                 if (cave[jj][ii].feat == 255)
3306                                 {                               
3307                                         if (xhstep2 > grd)
3308                                         {
3309                                                 /* If greater than 'grid' level then is random */
3310                                                 store_height(ii, jj, randint1(maxsize));
3311                                         }
3312                                         else
3313                                         {
3314                                                 /* Cache reused values. */
3315                                                 xm = fill_data.xmin + (i - xhstep) / 256;
3316                                                 xp = fill_data.xmin + (i + xhstep) / 256;
3317                                                 ym = fill_data.ymin + (j - yhstep) / 256;
3318                                                 yp = fill_data.ymin + (j + yhstep) / 256;                                       
3319                                         
3320                                                 /* 
3321                                                  * Average over all four corners + scale by diagsize to
3322                                                  * reduce the effect of the square grid on the shape of the fractal
3323                                                  */                             
3324                                                 store_height(ii, jj,
3325                                                         (cave[ym][xm].feat + cave[yp][xm].feat
3326                                                         + cave[ym][xp].feat + cave[yp][xp].feat) / 4
3327                                                         + (randint1(xstep2) - xhstep2) * (diagsize / 16) / 256 * roug);
3328                                         }
3329                                 }
3330                         }
3331                 }
3332         }
3333 }
3334
3335
3336 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)
3337 {
3338         /*
3339          * function used to convert from height-map back to the
3340          *  normal angband cave format
3341          */
3342         if (cave[y][x].info & CAVE_ICKY)
3343         {
3344                 /* already done */
3345                 return FALSE;
3346         }
3347         else
3348         {
3349                 /* Show that have looked at this square */
3350                 cave[y][x].info|= (CAVE_ICKY);
3351
3352                 /* Use cutoffs c1-c3 to allocate regions of floor /water/ lava etc. */
3353                 if (cave[y][x].feat <= c1)
3354                 {
3355                         /* 25% of the time use the other tile : it looks better this way */
3356                         if (randint1(100) < 75)
3357                         {
3358                                 cave[y][x].feat = feat1;
3359                                 cave[y][x].info &= ~(CAVE_MASK);
3360                                 cave[y][x].info |= info1;
3361                                 return TRUE;
3362                         }
3363                         else
3364                         {
3365                                 cave[y][x].feat = feat2;
3366                                 cave[y][x].info &= ~(CAVE_MASK);
3367                                 cave[y][x].info |= info2;
3368                                 return TRUE;
3369                         }
3370                 }
3371                 else if (cave[y][x].feat <= c2)
3372                 {
3373                         /* 25% of the time use the other tile : it looks better this way */
3374                         if (randint1(100) < 75)
3375                         {
3376                                 cave[y][x].feat = feat2;
3377                                 cave[y][x].info &= ~(CAVE_MASK);
3378                                 cave[y][x].info |= info2;
3379                                 return TRUE;
3380                         }
3381                         else
3382                         {
3383                                 cave[y][x].feat = feat1;
3384                                 cave[y][x].info &= ~(CAVE_MASK);
3385                                 cave[y][x].info |= info1;
3386                                 return TRUE;
3387                         }
3388                 }
3389                 else if (cave[y][x].feat <= c3)
3390                 {
3391                         cave[y][x].feat = feat3;
3392                         cave[y][x].info |= info3;
3393                         return TRUE;
3394                 }
3395                 /* if greater than cutoff then is a wall */
3396                 else
3397                 {
3398                         place_outer_bold(y, x);
3399                         return FALSE;
3400                 }
3401         }
3402 }
3403
3404
3405
3406
3407 /*
3408  * Quick and nasty fill routine used to find the connected region
3409  * of floor in the middle of the cave
3410  */
3411 static void cave_fill(byte y, byte x)
3412 {
3413         int i, j, d;
3414         int ty, tx;
3415
3416         int flow_tail = 1;
3417         int flow_head = 0;
3418
3419
3420         /*** Start Grid ***/
3421
3422         /* Enqueue that entry */
3423         temp_y[0] = y;
3424         temp_x[0] = x;
3425
3426
3427         /* Now process the queue */
3428         while (flow_head != flow_tail)
3429         {
3430                 /* Extract the next entry */
3431                 ty = temp_y[flow_head];
3432                 tx = temp_x[flow_head];
3433
3434                 /* Forget that entry */
3435                 if (++flow_head == TEMP_MAX) flow_head = 0;
3436
3437                 /* Add the "children" */
3438                 for (d = 0; d < 8; d++)
3439                 {
3440                         int old_head = flow_tail;
3441
3442                         /* Child location */
3443                         j = ty + ddy_ddd[d];
3444                         i = tx + ddx_ddd[d];
3445
3446                         /* Paranoia Don't leave the cave */
3447                         if (!in_bounds(j, i))
3448                         {
3449                                 /* affect boundary */
3450                                 cave[j][i].info |= CAVE_ICKY;
3451 /*                              return; */
3452                         }
3453
3454                         /* If within bounds */
3455                         else if ((i > fill_data.xmin) && (i < fill_data.xmax)
3456                                 && (j > fill_data.ymin) && (j < fill_data.ymax))
3457                         {
3458                                 /* If not a wall or floor done before */
3459                                 if (hack_isnt_wall(j, i,
3460                                         fill_data.c1, fill_data.c2, fill_data.c3,
3461                                         fill_data.feat1, fill_data.feat2, fill_data.feat3,
3462                                         fill_data.info1, fill_data.info2, fill_data.info3))
3463                                 {
3464                                         /* Enqueue that entry */
3465                                         temp_y[flow_tail] = j;
3466                                         temp_x[flow_tail] = i;
3467
3468                                         /* Advance the queue */
3469                                         if (++flow_tail == TEMP_MAX) flow_tail = 0;
3470
3471                                         /* Hack -- Overflow by forgetting new entry */
3472                                         if (flow_tail == flow_head)
3473                                         {
3474                                                 flow_tail = old_head;
3475                                         }
3476                                         else
3477                                         {
3478                                                 /* keep tally of size of cave system */
3479                                                 (fill_data.amount)++;
3480                                         }
3481                                 }
3482                         }
3483                         else
3484                         {
3485                                 /* affect boundary */
3486                                 cave[j][i].info |= CAVE_ICKY;
3487                         }
3488                 }
3489         }
3490 }
3491
3492
3493 static bool generate_fracave(int y0, int x0, int xsize, int ysize, int cutoff, bool light, bool room)
3494 {
3495         int x, y, i, xhsize, yhsize;
3496         
3497
3498         /* offsets to middle from corner */
3499         xhsize = xsize / 2;
3500         yhsize = ysize / 2;
3501
3502
3503         /*
3504          * select region connected to center of cave system
3505          * this gets rid of alot of isolated one-sqaures that
3506          * can make teleport traps instadeaths...
3507          */
3508
3509         /* cutoffs */
3510         fill_data.c1 = cutoff;
3511         fill_data.c2 = 0;
3512         fill_data.c3 = 0;
3513
3514         /* features to fill with */
3515         fill_data.feat1 = floor_type[randint0(100)];
3516         fill_data.feat2 = floor_type[randint0(100)];
3517         fill_data.feat3 = floor_type[randint0(100)];
3518
3519         fill_data.info1 = CAVE_FLOOR;
3520         fill_data.info2 = CAVE_FLOOR;
3521         fill_data.info3 = CAVE_FLOOR;
3522
3523         /* number of filled squares */
3524         fill_data.amount = 0;
3525
3526         cave_fill((byte)y0, (byte)x0);
3527
3528         /* if tally too small, try again */
3529         if (fill_data.amount < 10)
3530         {
3531                 /* too small - clear area and try again later */
3532                 for (x = 0; x <= xsize; ++x)
3533                 {
3534                         for (y = 0; y <= ysize; ++y)
3535                         {
3536                                 place_extra_bold(y0 + y - yhsize, x0 + x - xhsize);
3537                                 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY | CAVE_ROOM);
3538                         }
3539                 }
3540                 return FALSE;
3541         }
3542
3543         /*
3544          * Do boundarys-check to see if they are next to a filled region
3545          * If not then they are set to normal granite
3546          * If so then they are marked as room walls.
3547          */
3548         for (i = 0; i <= xsize; ++i)
3549         {
3550                 /* top boundary */
3551                 if ((cave[0 + y0 - yhsize][i + x0 - xhsize].info & CAVE_ICKY) && (room))
3552                 {
3553                         /* Next to a 'filled' region? - set to be room walls */
3554                         place_outer_bold(y0 + 0 - yhsize, x0 + i - xhsize);
3555                         if (light) cave[y0 + 0 - yhsize][x0 + i - xhsize].info |= (CAVE_GLOW);
3556                         cave[y0 + 0 - yhsize][x0 + i - xhsize].info |= (CAVE_ROOM);
3557                         place_outer_bold(y0 + 0 - yhsize, x0 + i - xhsize);
3558                 }
3559                 else
3560                 {
3561                         /* set to be normal granite */
3562                         place_extra_bold(y0 + 0 - yhsize, x0 + i - xhsize);
3563                 }
3564
3565                 /* bottom boundary */
3566                 if ((cave[ysize + y0 - yhsize][i + x0 - xhsize].info & CAVE_ICKY) && (room))
3567                 {
3568                         /* Next to a 'filled' region? - set to be room walls */
3569                         place_outer_bold(y0 + ysize - yhsize, x0 + i - xhsize);
3570                         if (light) cave[y0 + ysize - yhsize][x0 + i - xhsize].info|=(CAVE_GLOW);
3571                         cave[y0 + ysize - yhsize][x0 + i - xhsize].info|=(CAVE_ROOM);
3572                         place_outer_bold(y0 + ysize - yhsize, x0 + i - xhsize);
3573                 }
3574                 else
3575                 {
3576                         /* set to be normal granite */
3577                         place_extra_bold(y0 + ysize - yhsize, x0 + i - xhsize);
3578                 }
3579
3580                 /* clear the icky flag-don't need it any more */
3581                 cave[y0 + 0 - yhsize][x0 + i - xhsize].info &= ~(CAVE_ICKY);
3582                 cave[y0 + ysize - yhsize][x0 + i - xhsize].info &= ~(CAVE_ICKY);
3583         }
3584
3585         /* Do the left and right boundaries minus the corners (done above) */
3586         for (i = 1; i < ysize; ++i)
3587         {
3588                 /* left boundary */
3589                 if ((cave[i + y0 - yhsize][0 + x0 - xhsize].info & CAVE_ICKY) && room)
3590                 {
3591                         /* room boundary */
3592                         place_outer_bold(y0 + i - yhsize, x0 + 0 - xhsize);
3593                         if (light) cave[y0 + i - yhsize][x0 + 0 - xhsize].info |= (CAVE_GLOW);
3594                         cave[y0 + i - yhsize][x0 + 0 - xhsize].info |= (CAVE_ROOM);
3595                         place_outer_bold(y0 + i - yhsize, x0 + 0 - xhsize);
3596                 }
3597                 else
3598                 {
3599                         /* outside room */
3600                         place_extra_bold(y0 + i - yhsize, x0 + 0 - xhsize);
3601                 }
3602                 /* right boundary */
3603                 if ((cave[i + y0 - yhsize][xsize + x0 - xhsize].info & CAVE_ICKY) && room)
3604                 {
3605                         /* room boundary */
3606                         place_outer_bold(y0 + i - yhsize, x0 + xsize - xhsize);
3607                         if (light) cave[y0 + i - yhsize][x0 + xsize - xhsize].info |= (CAVE_GLOW);
3608                         cave[y0 + i - yhsize][x0 + xsize - xhsize].info |= (CAVE_ROOM);
3609                         place_outer_bold(y0 + i - yhsize, x0 + xsize - xhsize);
3610                 }
3611                 else
3612                 {
3613                         /* outside room */
3614                         place_extra_bold(y0 + i - yhsize, x0 + xsize - xhsize);
3615                 }
3616
3617                 /* clear icky flag -done with it */
3618                 cave[y0 + i - yhsize][x0 + 0 - xhsize].info &= ~(CAVE_ICKY);
3619                 cave[y0 + i - yhsize][x0 + xsize - xhsize].info &= ~(CAVE_ICKY);
3620         }
3621
3622
3623         /* Do the rest: convert back to the normal format */
3624         for (x = 1; x < xsize; ++x)
3625         {
3626                 for (y = 1; y < ysize; ++y)
3627                 {
3628                         if (is_floor_bold(y0 + y - yhsize, x0 + x - xhsize) &&
3629                             (cave[y0 + y - yhsize][x0 + x - xhsize].info & CAVE_ICKY))
3630                         {
3631                                 /* Clear the icky flag in the filled region */
3632                                 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~CAVE_ICKY;
3633
3634                                 /* Set appropriate flags */
3635                                 if (light) cave[y0 + y - yhsize][x0 + x - xhsize].info |= (CAVE_GLOW);
3636                                 if (room) cave[y0 + y - yhsize][x0 + x - xhsize].info |= (CAVE_ROOM);
3637                         }
3638                         else if (is_outer_bold(y0 + y - yhsize, x0 + x - xhsize) &&
3639                                  (cave[y0 + y - yhsize][x0 + x - xhsize].info & CAVE_ICKY))
3640                         {
3641                                 /* Walls */
3642                                 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY);
3643                                 if (light) cave[y0 + y - yhsize][x0 + x - xhsize].info |= (CAVE_GLOW);
3644                                 if (room)
3645                                 {
3646                                         cave[y0 + y - yhsize][x0 + x - xhsize].info |= (CAVE_ROOM);
3647                                 }
3648                                 else
3649                                 {
3650
3651                                         place_extra_bold(y0 + y - yhsize, x0 + x - xhsize);
3652                                         cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ROOM);
3653                                 }
3654                         }
3655                         else
3656                         {
3657                                 /* Clear the unconnected regions */
3658                                 place_extra_bold(y0 + y - yhsize, x0 + x - xhsize);
3659                                 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY | CAVE_ROOM);
3660                         }
3661                 }
3662         }
3663
3664         /*
3665          * XXX XXX XXX There is a slight problem when tunnels pierce the caves:
3666          * Extra doors appear inside the system.  (Its not very noticeable though.)
3667          * This can be removed by "filling" from the outside in.  This allows a separation
3668          * from FEAT_WALL_OUTER with FEAT_WALL_INNER.  (Internal walls are  F.W.OUTER instead.)
3669          * The extra effort for what seems to be only a minor thing (even non-existant if you
3670          * think of the caves not as normal rooms, but as holes in the dungeon), doesn't seem
3671          * worth it.
3672          */
3673
3674         return TRUE;
3675 }
3676
3677
3678 /*
3679  * Driver routine to create fractal cave system
3680  */
3681 static bool build_type9(void)
3682 {
3683         int grd, roug, cutoff, xsize, ysize, y0, x0;
3684
3685         bool done, light, room;
3686
3687         /* get size: note 'Evenness'*/
3688         xsize = randint1(22) * 2 + 6;
3689         ysize = randint1(15) * 2 + 6;
3690
3691         /* Find and reserve some space in the dungeon.  Get center of room. */
3692         if (!find_space(&y0, &x0, ysize + 1, xsize + 1)) return FALSE;
3693
3694         light = done = FALSE;
3695         room = TRUE;
3696
3697         if ((dun_level <= randint1(25)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS)) light = TRUE;
3698
3699         while (!done)
3700         {
3701                 /* Note: size must be even or there are rounding problems
3702                 * This causes the tunnels not to connect properly to the room */
3703
3704                 /* testing values for these parameters feel free to adjust */
3705                 grd = 1 << (randint0(4));
3706
3707                 /* want average of about 16 */
3708                 roug = randint1(8) * randint1(4);
3709
3710                 /* about size/2 */
3711                 cutoff = randint1(xsize / 4) + randint1(ysize / 4) +
3712                          randint1(xsize / 4) + randint1(ysize / 4);
3713
3714                 /* make it */
3715                 generate_hmap(y0, x0, xsize, ysize, grd, roug, cutoff);
3716
3717                 /* Convert to normal format + clean up */
3718                 done = generate_fracave(y0, x0, xsize, ysize, cutoff, light, room);
3719         }
3720
3721         return TRUE;
3722 }
3723
3724 #ifdef ALLOW_CAVERNS_AND_LAKES
3725 /*
3726  * Builds a cave system in the center of the dungeon.
3727  */
3728 void build_cavern(void)
3729 {
3730         int grd, roug, cutoff, xsize, ysize, x0, y0;
3731         bool done, light;
3732
3733         light = done = FALSE;
3734         if ((dun_level <= randint1(50)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS)) light = TRUE;
3735
3736         /* Make a cave the size of the dungeon */
3737         xsize = cur_wid - 1;
3738         ysize = cur_hgt - 1;
3739         x0 = xsize / 2;
3740         y0 = ysize / 2;
3741
3742         /* Paranoia: make size even */
3743         xsize = x0 * 2;
3744         ysize = y0 * 2;
3745
3746         while (!done)
3747         {
3748                 /* testing values for these parameters: feel free to adjust */
3749                 grd = randint1(4) + 4;
3750
3751                 /* want average of about 16 */
3752                 roug = randint1(8) * randint1(4);
3753
3754                 /* about size/2 */
3755                 cutoff = xsize / 2;
3756
3757                  /* make it */
3758                 generate_hmap(y0 + 1, x0 + 1, xsize, ysize, grd, roug, cutoff);
3759
3760                 /* Convert to normal format+ clean up */
3761                 done = generate_fracave(y0 + 1, x0 + 1, xsize, ysize, cutoff, light, FALSE);
3762         }
3763 }
3764
3765 static bool generate_lake(int y0, int x0, int xsize, int ysize, int c1, int c2, int c3, int type)
3766 {
3767         int x, y, i, xhsize, yhsize;
3768         int feat1, feat2, feat3;
3769
3770         /* offsets to middle from corner */
3771         xhsize = xsize / 2;
3772         yhsize = ysize / 2;
3773
3774         /* Get features based on type */
3775         switch (type)
3776         {
3777         case LAKE_T_LAVA: /* Lava */
3778                 feat1 = FEAT_DEEP_LAVA;
3779                 feat2 = FEAT_SHAL_LAVA;
3780                 feat3 = floor_type[randint0(100)];
3781                 break;
3782         case LAKE_T_WATER: /* Water */
3783                 feat1 = FEAT_DEEP_WATER;
3784                 feat2 = FEAT_SHAL_WATER;
3785                 feat3 = floor_type[randint0(100)];
3786                 break;
3787         case LAKE_T_CAVE: /* Collapsed cave */
3788                 feat1 = floor_type[randint0(100)];
3789                 feat2 = floor_type[randint0(100)];
3790                 feat3 = FEAT_RUBBLE;
3791                 break;
3792         case LAKE_T_EARTH_VAULT: /* Earth vault */
3793                 feat1 = FEAT_RUBBLE;
3794                 feat2 = floor_type[randint0(100)];
3795                 feat3 = FEAT_RUBBLE;
3796                 break;
3797         case LAKE_T_AIR_VAULT: /* Air vault */
3798                 feat1 = FEAT_GRASS;
3799                 feat2 = FEAT_TREES;
3800                 feat3 = FEAT_GRASS;
3801                 break;
3802         case LAKE_T_WATER_VAULT: /* Water vault */
3803                 feat1 = FEAT_SHAL_WATER;
3804                 feat2 = FEAT_DEEP_WATER;
3805                 feat3 = FEAT_SHAL_WATER;
3806                 break;
3807         case LAKE_T_FIRE_VAULT: /* Fire Vault */
3808                 feat1 = FEAT_SHAL_LAVA;
3809                 feat2 = FEAT_DEEP_LAVA;
3810                 feat3 = FEAT_SHAL_LAVA;
3811                 break;
3812
3813         /* Paranoia */
3814         default: return FALSE;
3815         }
3816
3817         /*
3818          * select region connected to center of cave system
3819          * this gets rid of alot of isolated one-sqaures that
3820          * can make teleport traps instadeaths...
3821          */
3822
3823         /* cutoffs */
3824         fill_data.c1 = c1;
3825         fill_data.c2 = c2;
3826         fill_data.c3 = c3;
3827
3828         /* features to fill with */
3829         fill_data.feat1 = feat1;
3830         fill_data.feat2 = feat2;
3831         fill_data.feat3 = feat3;
3832
3833         fill_data.info1 = 0;
3834         fill_data.info2 = 0;
3835         fill_data.info3 = 0;
3836
3837         /* number of filled squares */
3838         fill_data.amount = 0;
3839
3840         /* select region connected to center of cave system
3841         * this gets rid of alot of isolated one-sqaures that
3842         * can make teleport traps instadeaths... */
3843         cave_fill((byte)y0, (byte)x0);
3844
3845         /* if tally too small, try again */
3846         if (fill_data.amount < 10)
3847         {
3848                 /* too small -clear area and try again later */
3849                 for (x = 0; x <= xsize; ++x)
3850                 {
3851                         for (y = 0; y <= ysize; ++y)
3852                         {
3853                                 place_floor_bold(y0 + y - yhsize, x0 + x - xhsize);
3854                                 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY);
3855                         }
3856                 }
3857                 return FALSE;
3858         }
3859
3860         /* Do boundarys- set to normal granite */
3861         for (i = 0; i <= xsize; ++i)
3862         {
3863                 place_extra_bold(y0 + 0 - yhsize, x0 + i - xhsize);
3864                 place_extra_bold(y0 + ysize - yhsize, x0 + i - xhsize);
3865
3866                 /* clear the icky flag-don't need it any more */
3867                 cave[y0 + 0 - yhsize][x0 + i - xhsize].info &= ~(CAVE_ICKY);
3868                 cave[y0 + ysize - yhsize][x0 + i - xhsize].info &= ~(CAVE_ICKY);
3869         }
3870
3871         /* Do the left and right boundaries minus the corners (done above) */
3872
3873         for (i = 1; i < ysize; ++i)
3874         {
3875                 place_extra_bold(y0 + i - yhsize, x0 + 0 - xhsize);
3876                 place_extra_bold(y0 + i - yhsize, x0 + xsize - xhsize);
3877
3878                 /* clear icky flag -done with it */
3879                 cave[y0 + i - yhsize][x0 + 0 - xhsize].info &= ~(CAVE_ICKY);
3880                 cave[y0 + i - yhsize][x0 + xsize - xhsize].info &= ~(CAVE_ICKY);
3881         }
3882
3883
3884         /* Do the rest: convert back to the normal format */
3885         for (x = 1; x < xsize; ++x)
3886         {
3887                 for (y = 1; y < ysize; ++y)
3888                 {
3889                         /* Fill unconnected regions with granite */
3890                         if ((!(cave[y0 + y - yhsize][x0 + x - xhsize].info & CAVE_ICKY)) ||
3891                                 is_outer_bold(y0 + y - yhsize, x0 + x - xhsize))
3892                                 place_extra_bold(y0 + y - yhsize, x0 + x - xhsize);
3893
3894                         /* turn off icky flag (no longer needed.) */
3895                         cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY | CAVE_ROOM);
3896
3897                         /* Light lava and trees */
3898                         if ((cave[y0 + y - yhsize][x0 + x - xhsize].feat == FEAT_DEEP_LAVA) ||
3899                                 (cave[y0 + y - yhsize][x0 + x - xhsize].feat == FEAT_SHAL_LAVA))
3900                         {
3901                                 if (!(d_info[dungeon_type].flags1 & DF1_DARKNESS)) cave[y0 + y - yhsize][x0 + x - xhsize].info |= CAVE_GLOW;
3902                         }
3903                 }
3904         }
3905
3906         return TRUE;
3907 }
3908
3909
3910 /*
3911  * makes a lake/collapsed cave system in the center of the dungeon
3912  */
3913 void build_lake(int type)
3914 {
3915         int grd, roug, xsize, ysize, x0, y0;
3916         bool done = FALSE;
3917         int c1, c2, c3;
3918
3919         /* paranoia - exit if lake type out of range. */
3920         if ((type < LAKE_T_LAVA) || (type > LAKE_T_FIRE_VAULT))
3921         {
3922                 msg_format("Invalid lake type (%d)", type);
3923                 return;
3924         }
3925
3926         /* Make the size of the dungeon */
3927         xsize = cur_wid - 1;
3928         ysize = cur_hgt - 1;
3929         x0 = xsize / 2;
3930         y0 = ysize / 2;
3931
3932         /* Paranoia: make size even */
3933         xsize = x0 * 2;
3934         ysize = y0 * 2;
3935
3936         while (!done)
3937         {
3938                 /* testing values for these parameters: feel free to adjust */
3939                 grd = randint1(3) + 4;
3940
3941                 /* want average of about 16 */
3942                 roug = randint1(8) * randint1(4);
3943
3944                 /* Make up size of various componants */
3945                 /* Floor */
3946                 c3 = 3 * xsize / 4;
3947
3948                 /* Deep water/lava */
3949                 c1 = randint0(c3 / 2) + randint0(c3 / 2) - 5;
3950
3951                 /* Shallow boundary */
3952                 c2 = (c1 + c3) / 2;
3953
3954                 /* make it */
3955                 generate_hmap(y0 + 1, x0 + 1, xsize, ysize, grd, roug, c3);
3956
3957                 /* Convert to normal format+ clean up */
3958                 done = generate_lake(y0 + 1, x0 + 1, xsize, ysize, c1, c2, c3, type);
3959         }
3960 }
3961 #endif /* ALLOW_CAVERNS_AND_LAKES */
3962
3963
3964 /*
3965  * Routine used by the random vault creators to add a door to a location
3966  * Note that range checking has to be done in the calling routine.
3967  *
3968  * The doors must be INSIDE the allocated region.
3969  */
3970 static void add_door(int x, int y)
3971 {
3972         /* Need to have a wall in the center square */
3973         if (!is_outer_bold(y, x)) return;
3974
3975         /* look at:
3976          *  x#x
3977          *  .#.
3978          *  x#x
3979          *
3980          *  where x=don't care
3981          *  .=floor, #=wall
3982          */
3983
3984         if (is_floor_bold(y-1,x) && is_floor_bold(y+1,x) &&
3985             (is_outer_bold(y, x - 1) && is_outer_bold(y, x + 1)))
3986         {
3987                 /* secret door */
3988                 place_secret_door(y, x);
3989
3990                 /* set boundarys so don't get wide doors */
3991                 place_solid_bold(y, x - 1);
3992                 place_solid_bold(y, x + 1);
3993         }
3994
3995
3996         /* look at:
3997          *  x#x
3998          *  .#.
3999          *  x#x
4000          *
4001          *  where x = don't care
4002          *  .=floor, #=wall
4003          */
4004         if (is_outer_bold(y - 1, x) && is_outer_bold(y + 1, x) &&
4005             is_floor_bold(y,x-1) && is_floor_bold(y,x+1))
4006         {
4007                 /* secret door */
4008                 place_secret_door(y, x);
4009
4010                 /* set boundarys so don't get wide doors */
4011                 place_solid_bold(y - 1, x);
4012                 place_solid_bold(y + 1, x);
4013         }
4014 }
4015
4016
4017 /*
4018  * Routine that fills the empty areas of a room with treasure and monsters.
4019  */
4020 static void fill_treasure(int x1, int x2, int y1, int y2, int difficulty)
4021 {
4022         int x, y, cx, cy, size;
4023         s32b value;
4024
4025         /* center of room:*/
4026         cx = (x1 + x2) / 2;
4027         cy = (y1 + y2) / 2;
4028
4029         /* Rough measure of size of vault= sum of lengths of sides */
4030         size = abs(x2 - x1) + abs(y2 - y1);
4031
4032         for (x = x1; x <= x2; x++)
4033         {
4034                 for (y = y1; y <= y2; y++)
4035                 {
4036                         /* Thing added based on distance to center of vault
4037                          * Difficulty is 1-easy to 10-hard */
4038                         value = ((((s32b)(distance(cx, cy, x, y))) * 100) / size) + randint1(10) - difficulty;
4039
4040                         /* hack- empty square part of the time */
4041                         if ((randint1(100) - difficulty * 3) > 50) value = 20;
4042
4043                          /* if floor, shallow water and lava */
4044                         if (is_floor_bold(y, x) ||
4045                             (cave[y][x].feat == FEAT_SHAL_WATER) ||
4046                             (cave[y][x].feat == FEAT_SHAL_LAVA))
4047                         {
4048                                 /* The smaller 'value' is, the better the stuff */
4049                                 if (value < 0)
4050                                 {
4051                                         /* Meanest monster + treasure */
4052                                         monster_level = base_level + 40;
4053                                         place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
4054                                         monster_level = base_level;
4055                                         object_level = base_level + 20;
4056                                         place_object(y, x, AM_GOOD);
4057                                         object_level = base_level;
4058                                 }
4059                                 else if (value < 5)
4060                                 {
4061                                         /* Mean monster +treasure */
4062                                         monster_level = base_level + 20;
4063                                         place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
4064                                         monster_level = base_level;
4065                                         object_level = base_level + 10;
4066                                         place_object(y, x, AM_GOOD);
4067                                         object_level = base_level;
4068                                 }
4069                                 else if (value < 10)
4070                                 {
4071                                         /* Monster */
4072                                         monster_level = base_level + 9;
4073                                         place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
4074                                         monster_level = base_level;
4075                                 }
4076                                 else if (value < 17)
4077                                 {
4078                                         /* Intentional Blank space */
4079
4080                                         /*
4081                                          * (Want some of the vault to be empty
4082                                          * so have room for group monsters.
4083                                          * This is used in the hack above to lower
4084                                          * the density of stuff in the vault.)
4085                                          */
4086                                 }
4087                                 else if (value < 23)
4088                                 {
4089                                         /* Object or trap */
4090                                         if (randint0(100) < 25)
4091                                         {
4092                                                 place_object(y, x, 0L);
4093                                         }
4094                                         else
4095                                         {
4096                                                 place_trap(y, x);
4097                                         }
4098                                 }
4099                                 else if (value < 30)
4100                                 {
4101                                         /* Monster and trap */
4102                                         monster_level = base_level + 5;
4103                                         place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
4104                                         monster_level = base_level;
4105                                         place_trap(y, x);
4106                                 }
4107                                 else if (value < 40)
4108                                 {
4109                                         /* Monster or object */
4110                                         if (randint0(100) < 50)
4111                                         {
4112                                                 monster_level = base_level + 3;
4113                                                 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
4114                                                 monster_level = base_level;
4115                                         }
4116                                         if (randint0(100) < 50)
4117                                         {
4118                                                 object_level = base_level + 7;
4119                                                 place_object(y, x, 0L);
4120                                                 object_level = base_level;
4121                                         }
4122                                 }
4123                                 else if (value < 50)
4124                                 {
4125                                         /* Trap */
4126                                         place_trap(y, x);
4127                                 }
4128                                 else
4129                                 {
4130                                         /* Various Stuff */
4131
4132                                         /* 20% monster, 40% trap, 20% object, 20% blank space */
4133                                         if (randint0(100) < 20)
4134                                         {
4135                                                 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
4136                                         }
4137                                         else if (randint0(100) < 50)
4138                                         {
4139                                                 place_trap(y, x);
4140                                         }
4141                                         else if (randint0(100) < 50)
4142                                         {
4143                                                 place_object(y, x, 0L);
4144                                         }
4145                                 }
4146
4147                         }
4148                 }
4149         }
4150 }
4151
4152
4153 /*
4154  * This function creates a random vault that looks like a collection of bubbles.
4155  * It works by getting a set of coordinates that represent the center of each
4156  * bubble.  The entire room is made by seeing which bubble center is closest. If
4157  * two centers are equidistant then the square is a wall, otherwise it is a floor.
4158  * The only exception is for squares really near a center, these are always floor.
4159  * (It looks better than without this check.)
4160  *
4161  * Note: If two centers are on the same point then this algorithm will create a
4162  *       blank bubble filled with walls. - This is prevented from happening.
4163  */
4164 static void build_bubble_vault(int x0, int y0, int xsize, int ysize)
4165 {
4166         #define BUBBLENUM 10            /* number of bubbles */
4167
4168         /* array of center points of bubbles */
4169         coord center[BUBBLENUM];
4170
4171         int i, j, x, y;
4172         u16b min1, min2, temp;
4173         bool done;
4174
4175         /* Offset from center to top left hand corner */
4176         int xhsize = xsize / 2;
4177         int yhsize = ysize / 2;
4178
4179
4180         if (cheat_room) msg_print("Bubble Vault");
4181
4182         /* Allocate center of bubbles */
4183         center[0].x = randint1(xsize - 3) + 1;
4184         center[0].y = randint1(ysize - 3) + 1;
4185
4186         for (i = 1; i < BUBBLENUM; i++)
4187         {
4188                 done = FALSE;
4189
4190                 /* get center and check to see if it is unique */
4191                 while (!done)
4192                 {
4193                         done = TRUE;
4194
4195                         x = randint1(xsize - 3) + 1;
4196                         y = randint1(ysize - 3) + 1;
4197
4198                         for (j = 0; j < i; j++)
4199                         {
4200                                 /* rough test to see if there is an overlap */
4201                                 if ((x == center[j].x) && (y == center[j].y)) done = FALSE;
4202                         }
4203                 }
4204
4205                 center[i].x = x;
4206                 center[i].y = y;
4207         }
4208
4209
4210         /* Top and bottom boundaries */
4211         for (i = 0; i < xsize; i++)
4212         {
4213                 int x = x0 - xhsize + i;
4214
4215                 place_outer_noperm_bold(y0 - yhsize + 0, x);
4216                 cave[y0 - yhsize + 0][x].info |= (CAVE_ROOM | CAVE_ICKY);
4217                 place_outer_noperm_bold(y0 - yhsize + ysize - 1, x);
4218                 cave[y0 - yhsize + ysize - 1][x].info |= (CAVE_ROOM | CAVE_ICKY);
4219         }
4220
4221         /* Left and right boundaries */
4222         for (i = 1; i < ysize - 1; i++)
4223         {
4224                 int y = y0 - yhsize + i;
4225
4226                 place_outer_noperm_bold(y, x0 - xhsize + 0);
4227                 cave[y][x0 - xhsize + 0].info |= (CAVE_ROOM | CAVE_ICKY);
4228                 place_outer_noperm_bold(y, x0 - xhsize + xsize - 1);
4229                 cave[y][x0 - xhsize + xsize - 1].info |= (CAVE_ROOM | CAVE_ICKY);
4230         }
4231
4232         /* Fill in middle with bubbles */
4233         for (x = 1; x < xsize - 1; x++)
4234         {
4235                 for (y = 1; y < ysize - 1; y++)
4236                 {
4237                         /* Get distances to two closest centers */
4238
4239                         /* initialize */
4240                         min1 = distance(x, y, center[0].x, center[0].y);
4241                         min2 = distance(x, y, center[1].x, center[1].y);
4242
4243                         if (min1 > min2)
4244                         {
4245                                 /* swap if in wrong order */
4246                                 temp = min1;
4247                                 min1 = min2;
4248                                 min2 = temp;
4249                         }
4250
4251                         /* Scan the rest */
4252                         for (i = 2; i < BUBBLENUM; i++)
4253                         {
4254                                 temp = distance(x, y, center[i].x, center[i].y);
4255
4256                                 if (temp < min1)
4257                                 {
4258                                         /* smallest */
4259                                         min2 = min1;
4260                                         min1 = temp;
4261                                 }
4262                                 else if (temp < min2)
4263                                 {
4264                                         /* second smallest */
4265                                         min2 = temp;
4266                                 }
4267                         }
4268                         if (((min2 - min1) <= 2) && (!(min1 < 3)))
4269                         {
4270                                 /* Boundary at midpoint+ not at inner region of bubble */
4271                                 place_outer_noperm_bold(y0 - yhsize + y, x0 - xhsize + x);
4272                         }
4273                         else
4274                         {
4275                                 /* middle of a bubble */
4276                                 place_floor_bold(y0 - yhsize + y, x0 - xhsize + x);
4277                         }
4278
4279                         /* clean up rest of flags */
4280                         cave[y0 - yhsize + y][x0 - xhsize + x].info |= (CAVE_ROOM | CAVE_ICKY);
4281                 }
4282         }
4283
4284         /* Try to add some random doors */
4285         for (i = 0; i < 500; i++)
4286         {
4287                 x = randint1(xsize - 3) - xhsize + x0 + 1;
4288                 y = randint1(ysize - 3) - yhsize + y0 + 1;
4289                 add_door(x, y);
4290         }
4291
4292         /* Fill with monsters and treasure, low difficulty */
4293         fill_treasure(x0 - xhsize + 1, x0 - xhsize + xsize - 2, y0 - yhsize + 1, y0 - yhsize + ysize - 2, randint1(5));
4294 }
4295
4296
4297 /*
4298  * Overlay a rectangular room given its bounds
4299  * This routine is used by build_room_vault
4300  * The area inside the walls is not touched:
4301  * only granite is removed- normal walls stay
4302  */
4303 static void build_room(int x1, int x2, int y1, int y2)
4304 {
4305         int x, y, i, xsize, ysize, temp;
4306
4307         /* Check if rectangle has no width */
4308         if ((x1 == x2) || (y1 == y2)) return;
4309
4310         /* initialize */
4311         if (x1 > x2)
4312         {
4313                 /* Swap boundaries if in wrong order */
4314                 temp = x1;
4315                 x1 = x2;
4316                 x2 = temp;
4317         }
4318
4319         if (y1 > y2)
4320         {
4321                 /* Swap boundaries if in wrong order */
4322                 temp = y1;
4323                 y1 = y2;
4324                 y2 = temp;
4325         }
4326
4327         /* get total widths */
4328         xsize = x2 - x1;
4329         ysize = y2 - y1;
4330
4331
4332         /* Top and bottom boundaries */
4333         for (i = 0; i <= xsize; i++)
4334         {
4335                 place_outer_noperm_bold(y1, x1 + i);
4336                 cave[y1][x1 + i].info |= (CAVE_ROOM | CAVE_ICKY);
4337                 place_outer_noperm_bold(y2, x1 + i);
4338                 cave[y2][x1 + i].info |= (CAVE_ROOM | CAVE_ICKY);
4339         }
4340
4341         /* Left and right boundaries */
4342         for (i = 1; i < ysize; i++)
4343         {
4344                 place_outer_noperm_bold(y1 + i, x1);
4345                 cave[y1 + i][x1].info|=(CAVE_ROOM | CAVE_ICKY);
4346                 place_outer_noperm_bold(y1 + i, x2);
4347                 cave[y1 + i][x2].info|=(CAVE_ROOM | CAVE_ICKY);
4348         }
4349
4350         /* Middle */
4351         for (x = 1; x < xsize; x++)
4352         {
4353                 for (y = 1; y < ysize; y++)
4354                 {
4355                         if (is_extra_bold(y1+y, x1+x))
4356                         {
4357                                 /* clear the untouched region */
4358                                 place_floor_bold(y1 + y, x1 + x);
4359                                 cave[y1 + y][x1 + x].info |= (CAVE_ROOM | CAVE_ICKY);
4360                         }
4361                         else
4362                         {
4363                                 /* make it a room- but don't touch */
4364                                 cave[y1 + y][x1 + x].info |= (CAVE_ROOM | CAVE_ICKY);
4365                         }
4366                 }
4367         }
4368 }
4369
4370
4371 /* Create a random vault that looks like a collection of overlapping rooms */
4372
4373 static void build_room_vault(int x0, int y0, int xsize, int ysize)
4374 {
4375         int i, x1, x2, y1, y2, xhsize, yhsize;
4376
4377         /* get offset from center */
4378         xhsize = xsize / 2;
4379         yhsize = ysize / 2;
4380
4381         if (cheat_room) msg_print("Room Vault");
4382
4383         /* fill area so don't get problems with arena levels */
4384         for (x1 = 0; x1 < xsize; x1++)
4385         {
4386                 int x = x0 - xhsize + x1;
4387
4388                 for (y1 = 0; y1 < ysize; y1++)
4389                 {
4390                         int y = y0 - yhsize + y1;
4391
4392                         place_extra_bold(y, x);
4393                         cave[y][x].info &= (~CAVE_ICKY);
4394                 }
4395         }
4396
4397         /* add ten random rooms */
4398         for (i = 0; i < 10; i++)
4399         {
4400                 x1 = randint1(xhsize) * 2 + x0 - xhsize;
4401                 x2 = randint1(xhsize) * 2 + x0 - xhsize;
4402                 y1 = randint1(yhsize) * 2 + y0 - yhsize;
4403                 y2 = randint1(yhsize) * 2 + y0 - yhsize;
4404                 build_room(x1, x2, y1, y2);
4405         }
4406
4407         /* Add some random doors */
4408         for (i = 0; i < 500; i++)
4409         {
4410                 x1 = randint1(xsize - 3) - xhsize + x0 + 1;
4411                 y1 = randint1(ysize - 3) - yhsize + y0 + 1;
4412                 add_door(x1, y1);
4413         }
4414
4415         /* Fill with monsters and treasure, high difficulty */
4416         fill_treasure(x0 - xhsize + 1, x0 - xhsize + xsize - 2, y0 - yhsize + 1, y0 - yhsize + ysize - 2, randint1(5) + 5);
4417 }
4418
4419
4420 /* Create a random vault out of a fractal cave */
4421 static void build_cave_vault(int x0, int y0, int xsiz, int ysiz)
4422 {
4423         int grd, roug, cutoff, xhsize, yhsize, xsize, ysize, x, y;
4424         bool done, light, room;
4425
4426         /* round to make sizes even */
4427         xhsize = xsiz / 2;
4428         yhsize = ysiz / 2;
4429         xsize = xhsize * 2;
4430         ysize = yhsize * 2;
4431
4432         if (cheat_room) msg_print("Cave Vault");
4433
4434         light = done = FALSE;
4435         room = TRUE;
4436
4437         while (!done)
4438         {
4439                 /* testing values for these parameters feel free to adjust */
4440                 grd = 1 << randint0(4);
4441
4442                 /* want average of about 16 */
4443                 roug = randint1(8) * randint1(4);
4444
4445                 /* about size/2 */
4446                 cutoff = randint1(xsize / 4) + randint1(ysize / 4) +
4447                          randint1(xsize / 4) + randint1(ysize / 4);
4448
4449                 /* make it */
4450                 generate_hmap(y0, x0, xsize, ysize, grd, roug, cutoff);
4451
4452                 /* Convert to normal format+ clean up */
4453                 done = generate_fracave(y0, x0, xsize, ysize, cutoff, light, room);
4454         }
4455
4456         /* Set icky flag because is a vault */
4457         for (x = 0; x <= xsize; x++)
4458         {
4459                 for (y = 0; y <= ysize; y++)
4460                 {
4461                         cave[y0 - yhsize + y][x0 - xhsize + x].info |= CAVE_ICKY;
4462                 }
4463         }
4464
4465         /* Fill with monsters and treasure, low difficulty */
4466         fill_treasure(x0 - xhsize + 1, x0 - xhsize + xsize - 1, y0 - yhsize + 1, y0 - yhsize + ysize - 1, randint1(5));
4467 }
4468
4469 /*
4470  * maze vault -- rectangular labyrinthine rooms
4471  *
4472  * maze vault uses two routines:
4473  *    r_visit - a recursive routine that builds the labyrinth
4474  *    build_maze_vault - a driver routine that calls r_visit and adds
4475  *                   monsters, traps and treasure
4476  *
4477  * The labyrinth is built by creating a spanning tree of a graph.
4478  * The graph vertices are at
4479  *    (x, y) = (2j + x1, 2k + y1)   j = 0,...,m-1    k = 0,...,n-1
4480  * and the edges are the vertical and horizontal nearest neighbors.
4481  *
4482  * The spanning tree is created by performing a suitably randomized
4483  * depth-first traversal of the graph. The only adjustable parameter
4484  * is the randint0(3) below; it governs the relative density of
4485  * twists and turns in the labyrinth: smaller number, more twists.
4486  */
4487 static void r_visit(int y1, int x1, int y2, int x2,
4488                     int node, int dir, int *visited)
4489 {
4490         int i, j, m, n, temp, x, y, adj[4];
4491
4492         /* dimensions of vertex array */
4493         m = (x2 - x1) / 2 + 1;
4494         n = (y2 - y1) / 2 + 1;
4495
4496         /* mark node visited and set it to a floor */
4497         visited[node] = 1;
4498         x = 2 * (node % m) + x1;
4499         y = 2 * (node / m) + y1;
4500         place_floor_bold(y, x);
4501
4502         /* setup order of adjacent node visits */
4503         if (one_in_(3))
4504         {
4505                 /* pick a random ordering */
4506                 for (i = 0; i < 4; i++)
4507                         adj[i] = i;
4508                 for (i = 0; i < 4; i++)
4509                 {
4510                         j = randint0(4);
4511                         temp = adj[i];
4512                         adj[i] = adj[j];
4513                         adj[j] = temp;
4514                 }
4515                 dir = adj[0];
4516         }
4517         else
4518         {
4519                 /* pick a random ordering with dir first */
4520                 adj[0] = dir;
4521                 for (i = 1; i < 4; i++)
4522                         adj[i] = i;
4523                 for (i = 1; i < 4; i++)
4524                 {
4525                         j = 1 + randint0(3);
4526                         temp = adj[i];
4527                         adj[i] = adj[j];
4528                         adj[j] = temp;
4529                 }
4530         }
4531
4532         for (i = 0; i < 4; i++)
4533         {
4534                 switch (adj[i])
4535                 {
4536                         case 0:
4537                                 /* (0,+) - check for bottom boundary */
4538                                 if ((node / m < n - 1) && (visited[node + m] == 0))
4539                                 {
4540                                         place_floor_bold(y + 1, x);
4541                                         r_visit(y1, x1, y2, x2, node + m, dir, visited);
4542                                 }
4543                                 break;
4544                         case 1:
4545                                 /* (0,-) - check for top boundary */
4546                                 if ((node / m > 0) && (visited[node - m] == 0))
4547                                 {
4548                                         place_floor_bold(y - 1, x);
4549                                         r_visit(y1, x1, y2, x2, node - m, dir, visited);
4550                                 }
4551                                 break;
4552                         case 2:
4553                                 /* (+,0) - check for right boundary */
4554                                 if ((node % m < m - 1) && (visited[node + 1] == 0))
4555                                 {
4556                                         place_floor_bold(y, x + 1);
4557                                         r_visit(y1, x1, y2, x2, node + 1, dir, visited);
4558                                 }
4559                                 break;
4560                         case 3:
4561                                 /* (-,0) - check for left boundary */
4562                                 if ((node % m > 0) && (visited[node - 1] == 0))
4563                                 {
4564                                         place_floor_bold(y, x - 1);
4565                                         r_visit(y1, x1, y2, x2, node - 1, dir, visited);
4566                                 }
4567                 } /* end switch */
4568         }
4569 }
4570
4571
4572 void build_maze_vault(int x0, int y0, int xsize, int ysize, bool is_vault)
4573 {
4574         int y, x, dy, dx;
4575         int y1, x1, y2, x2;
4576         int m, n, num_vertices, *visited;
4577         bool light;
4578         cave_type *c_ptr;
4579
4580
4581         if (cheat_room && is_vault) msg_print("Maze Vault");
4582
4583         /* Choose lite or dark */
4584         light = ((dun_level <= randint1(25)) && is_vault && !(d_info[dungeon_type].flags1 & DF1_DARKNESS));
4585
4586         /* Pick a random room size - randomized by calling routine */
4587         dy = ysize / 2 - 1;
4588         dx = xsize / 2 - 1;
4589
4590         y1 = y0 - dy;
4591         x1 = x0 - dx;
4592         y2 = y0 + dy;
4593         x2 = x0 + dx;
4594
4595         /* generate the room */
4596         for (y = y1 - 1; y <= y2 + 1; y++)
4597         {
4598                 for (x = x1 - 1; x <= x2 + 1; x++)
4599                 {
4600                         c_ptr = &cave[y][x];
4601                         c_ptr->info |= CAVE_ROOM;
4602                         if (is_vault) c_ptr->info |= CAVE_ICKY;
4603                         if ((x == x1 - 1) || (x == x2 + 1) || (y == y1 - 1) || (y == y2 + 1))
4604                         {
4605                                 place_outer_grid(c_ptr);
4606                         }
4607                         else if (!is_vault)
4608                         {
4609                                 place_extra_grid(c_ptr);
4610                         }
4611                         else
4612                         {
4613                                 place_inner_grid(c_ptr);
4614                         }
4615                         if (light) c_ptr->info |= (CAVE_GLOW);
4616                 }
4617         }
4618
4619         /* dimensions of vertex array */
4620         m = dx + 1;
4621         n = dy + 1;
4622         num_vertices = m * n;
4623
4624         /* initialize array of visited vertices */
4625         C_MAKE(visited, num_vertices, int);
4626
4627         /* traverse the graph to create a spaning tree, pick a random root */
4628         r_visit(y1, x1, y2, x2, randint0(num_vertices), 0, visited);
4629
4630         /* Fill with monsters and treasure, low difficulty */
4631         if (is_vault) fill_treasure(x1, x2, y1, y2, randint1(5));
4632
4633         C_KILL(visited, num_vertices, int);
4634 }
4635
4636
4637 /* Build a "mini" checkerboard vault
4638  *
4639  * This is done by making a permanent wall maze and setting
4640  * the diagonal sqaures of the checker board to be granite.
4641  * The vault has two entrances on opposite sides to guarantee
4642  * a way to get in even if the vault abuts a side of the dungeon.
4643  */
4644 static void build_mini_c_vault(int x0, int y0, int xsize, int ysize)
4645 {
4646         int dy, dx;
4647         int y1, x1, y2, x2, y, x, total;
4648         int m, n, num_vertices;
4649         int *visited;
4650
4651         if (cheat_room) msg_print("Mini Checker Board Vault");
4652
4653         /* Pick a random room size */
4654         dy = ysize / 2 - 1;
4655         dx = xsize / 2 - 1;
4656
4657         y1 = y0 - dy;
4658         x1 = x0 - dx;
4659         y2 = y0 + dy;
4660         x2 = x0 + dx;
4661
4662
4663         /* generate the room */
4664         for (x = x1 - 2; x <= x2 + 2; x++)
4665         {
4666                 if (!in_bounds(y1-2,x)) break;
4667
4668                 cave[y1-2][x].info |= (CAVE_ROOM | CAVE_ICKY);
4669
4670                 place_outer_noperm_bold(y1-2, x);
4671         }
4672
4673         for (x = x1 - 2; x <= x2 + 2; x++)
4674         {
4675                 if (!in_bounds(y2+2,x)) break;
4676
4677                 cave[y2+2][x].info |= (CAVE_ROOM | CAVE_ICKY);
4678
4679                 place_outer_noperm_bold(y2+2, x);
4680         }
4681
4682         for (y = y1 - 2; y <= y2 + 2; y++)
4683         {
4684                 if (!in_bounds(y,x1-2)) break;
4685
4686                 cave[y][x1-2].info |= (CAVE_ROOM | CAVE_ICKY);
4687
4688                 place_outer_noperm_bold(y, x1-2);
4689         }
4690
4691         for (y = y1 - 2; y <= y2 + 2; y++)
4692         {
4693                 if (!in_bounds(y,x2+2)) break;
4694
4695                 cave[y][x2+2].info |= (CAVE_ROOM | CAVE_ICKY);
4696
4697                 place_outer_noperm_bold(y, x2+2);
4698         }
4699
4700         for (y = y1 - 1; y <= y2 + 1; y++)
4701         {
4702                 for (x = x1 - 1; x <= x2 + 1; x++)
4703                 {
4704                         cave_type *c_ptr = &cave[y][x];
4705
4706                         c_ptr->info |= (CAVE_ROOM | CAVE_ICKY);
4707
4708                         /* Permanent walls */
4709                         c_ptr->feat = FEAT_PERM_INNER;
4710                         c_ptr->info &= ~(CAVE_MASK);
4711                         c_ptr->info |= CAVE_INNER;
4712                 }
4713         }
4714
4715
4716         /* dimensions of vertex array */
4717         m = dx + 1;
4718         n = dy + 1;
4719         num_vertices = m * n;
4720
4721         /* initialize array of visited vertices */
4722         C_MAKE(visited, num_vertices, int);
4723
4724         /* traverse the graph to create a spannng tree, pick a random root */
4725         r_visit(y1, x1, y2, x2, randint0(num_vertices), 0, visited);
4726
4727         /* Make it look like a checker board vault */
4728         for (x = x1; x <= x2; x++)
4729         {
4730                 for (y = y1; y <= y2; y++)
4731                 {
4732                         total = x - x1 + y - y1;
4733                         /* If total is odd- and is a floor then make a wall */
4734                         if ((total % 2 == 1) && is_floor_bold(y, x))
4735                         {
4736                                 place_inner_bold(y, x);
4737                         }
4738                 }
4739         }
4740
4741         /* Make a couple of entrances */
4742         if (one_in_(2))
4743         {
4744                 /* left and right */
4745                 y = randint1(dy) + dy / 2;
4746                 place_inner_bold(y1 + y, x1 - 1);
4747                 place_inner_bold(y1 + y, x2 + 1);
4748         }
4749         else
4750         {
4751                 /* top and bottom */
4752                 x = randint1(dx) + dx / 2;
4753                 place_inner_bold(y1 - 1, x1 + x);
4754                 place_inner_bold(y2 + 1, x1 + x);
4755         }
4756
4757         /* Fill with monsters and treasure, highest difficulty */
4758         fill_treasure(x1, x2, y1, y2, 10);
4759
4760         C_KILL(visited, num_vertices, int);
4761 }
4762
4763
4764 /* Build a town/ castle by using a recursive algorithm.
4765  * Basically divide each region in a probalistic way to create
4766  * smaller regions.  When the regions get too small stop.
4767  *
4768  * The power variable is a measure of how well defended a region is.
4769  * This alters the possible choices.
4770  */
4771 static void build_recursive_room(int x1, int y1, int x2, int y2, int power)
4772 {
4773         int xsize, ysize;
4774         int x, y;
4775         int choice;
4776
4777         /* Temp variables */
4778         int t1, t2, t3, t4;
4779
4780         xsize = x2 - x1;
4781         ysize = y2 - y1;
4782
4783         if ((power < 3) && (xsize > 12) && (ysize > 12))
4784         {
4785                 /* Need outside wall +keep */
4786                 choice = 1;
4787         }
4788         else
4789         {
4790                 if (power < 10)
4791                 {
4792                         /* Make rooms + subdivide */
4793                         if ((randint1(10) > 2) && (xsize < 8) && (ysize < 8))
4794                         {
4795                                 choice = 4;
4796                         }
4797                         else
4798                         {
4799                                 choice = randint1(2) + 1;
4800                         }
4801                 }
4802                 else
4803                 {
4804                         /* Mostly subdivide */
4805                         choice = randint1(3) + 1;
4806                 }
4807         }
4808
4809         /* Based on the choice made above, do something */
4810
4811         switch (choice)
4812         {
4813                 case 1:
4814                 {
4815                         /* Outer walls */
4816
4817                         /* top and bottom */
4818                         for (x = x1; x <= x2; x++)
4819                         {
4820                                 place_outer_bold(y1, x);
4821                                 place_outer_bold(y2, x);
4822                         }
4823
4824                         /* left and right */
4825                         for (y = y1 + 1; y < y2; y++)
4826                         {
4827                                 place_outer_bold(y, x1);
4828                                 place_outer_bold(y, x2);
4829                         }
4830
4831                         /* Make a couple of entrances */
4832                         if (one_in_(2))
4833                         {
4834                                 /* left and right */
4835                                 y = randint1(ysize) + y1;
4836                                 place_floor_bold(y, x1);
4837                                 place_floor_bold(y, x2);
4838                         }
4839                         else
4840                         {
4841                                 /* top and bottom */
4842                                 x = randint1(xsize) + x1;
4843                                 place_floor_bold(y1, x);
4844                                 place_floor_bold(y2, x);
4845                         }
4846
4847                         /* Select size of keep */
4848                         t1 = randint1(ysize / 3) + y1;
4849                         t2 = y2 - randint1(ysize / 3);
4850                         t3 = randint1(xsize / 3) + x1;
4851                         t4 = x2 - randint1(xsize / 3);
4852
4853                         /* Do outside areas */
4854
4855                         /* Above and below keep */
4856                         build_recursive_room(x1 + 1, y1 + 1, x2 - 1, t1, power + 1);
4857                         build_recursive_room(x1 + 1, t2, x2 - 1, y2, power + 1);
4858
4859                         /* Left and right of keep */
4860                         build_recursive_room(x1 + 1, t1 + 1, t3, t2 - 1, power + 3);
4861                         build_recursive_room(t4, t1 + 1, x2 - 1, t2 - 1, power + 3);
4862
4863                         /* Make the keep itself: */
4864                         x1 = t3;
4865                         x2 = t4;
4866                         y1 = t1;
4867                         y2 = t2;
4868                         xsize = x2 - x1;
4869                         ysize = y2 - y1;
4870                         power += 2;
4871
4872                         /* Fall through */
4873                 }
4874                 case 4:
4875                 {
4876                         /* Try to build a room */
4877                         if ((xsize < 3) || (ysize < 3))
4878                         {
4879                                 for (y = y1; y < y2; y++)
4880                                 {
4881                                         for (x = x1; x < x2; x++)
4882                                         {
4883                                                 place_inner_bold(y, x);
4884                                         }
4885                                 }
4886
4887                                 /* Too small */
4888                                 return;
4889                         }
4890
4891                         /* Make outside walls */
4892                         /* top and bottom */
4893                         for (x = x1 + 1; x <= x2 - 1; x++)
4894                         {
4895                                 place_inner_bold(y1 + 1, x);
4896                                 place_inner_bold(y2 - 1, x);
4897                         }
4898
4899                         /* left and right */
4900                         for (y = y1 + 1; y <= y2 - 1; y++)
4901                         {
4902                                 place_inner_bold(y, x1 + 1);
4903                                 place_inner_bold(y, x2 - 1);
4904                         }
4905
4906                         /* Make a door */
4907                         y = randint1(ysize - 3) + y1 + 1;
4908
4909                         if (one_in_(2))
4910                         {
4911                                 /* left */
4912                                 place_floor_bold(y, x1 + 1);
4913                         }
4914                         else
4915                         {
4916                                 /* right */
4917                                 place_floor_bold(y, x2 - 1);
4918                         }
4919
4920                         /* Build the room */
4921                         build_recursive_room(x1 + 2, y1 + 2, x2 - 2, y2 - 2, power + 3);
4922                         break;
4923                 }
4924                 case 2:
4925                 {
4926                         /* Try and divide vertically */
4927                         if (xsize < 3)
4928                         {
4929                                 /* Too small */
4930                                 for (y = y1; y < y2; y++)
4931                                 {
4932                                         for (x = x1; x < x2; x++)
4933                                         {
4934                                                 place_inner_bold(y, x);
4935                                         }
4936                                 }
4937                                 return;
4938                         }
4939
4940                         t1 = randint1(xsize - 2) + x1 + 1;
4941                         build_recursive_room(x1, y1, t1, y2, power - 2);
4942                         build_recursive_room(t1 + 1, y1, x2, y2, power - 2);
4943                         break;
4944                 }
4945                 case 3:
4946                 {
4947                         /* Try and divide horizontally */
4948                         if (ysize < 3)
4949                         {
4950                                 /* Too small */
4951                                 for (y = y1; y < y2; y++)
4952                                 {
4953                                         for (x = x1; x < x2; x++)
4954                                         {
4955                                                 place_inner_bold(y, x);
4956                                         }
4957                                 }
4958                                 return;
4959                         }
4960
4961                         t1 = randint1(ysize - 2) + y1 + 1;
4962                         build_recursive_room(x1, y1, x2, t1, power - 2);
4963                         build_recursive_room(x1, t1 + 1, x2, y2, power - 2);
4964                         break;
4965                 }
4966         }
4967 }
4968
4969
4970 /* Build a castle */
4971
4972 /* Driver routine: clear the region and call the recursive
4973 * room routine.
4974 *
4975 *This makes a vault that looks like a castle/ city in the dungeon.
4976 */
4977 static void build_castle_vault(int x0, int y0, int xsize, int ysize)
4978 {
4979         int dy, dx;
4980         int y1, x1, y2, x2;
4981         int y, x;
4982
4983         /* Pick a random room size */
4984         dy = ysize / 2 - 1;
4985         dx = xsize / 2 - 1;
4986
4987         y1 = y0 - dy;
4988         x1 = x0 - dx;
4989         y2 = y0 + dy;
4990         x2 = x0 + dx;
4991
4992         if (cheat_room) msg_print("Castle Vault");
4993
4994         /* generate the room */
4995         for (y = y1 - 1; y <= y2 + 1; y++)
4996         {
4997                 for (x = x1 - 1; x <= x2 + 1; x++)
4998                 {
4999                         cave[y][x].info |= (CAVE_ROOM | CAVE_ICKY);
5000                         /* Make everything a floor */
5001                         place_floor_bold(y, x);
5002                 }
5003         }
5004
5005         /* Make the castle */
5006         build_recursive_room(x1, y1, x2, y2, randint1(5));
5007
5008         /* Fill with monsters and treasure, low difficulty */
5009         fill_treasure(x1, x2, y1, y2, randint1(3));
5010 }
5011
5012
5013 /*
5014  * Add outer wall to a floored region
5015  * Note: no range checking is done so must be inside dungeon
5016  * This routine also stomps on doors
5017  */
5018 static void add_outer_wall(int x, int y, int light,
5019                                                                         int x1, int y1, int x2, int y2)
5020 {
5021         int i, j;
5022
5023         if (!in_bounds(y, x)) return;
5024
5025         /* hack- check to see if square has been visited before
5026         * if so, then exit (use room flag to do this) */
5027         if (cave[y][x].info & CAVE_ROOM) return;
5028
5029         /* set room flag */
5030         cave[y][x].info |= CAVE_ROOM;
5031
5032         if (is_floor_bold(y, x))
5033         {
5034                 for (i = -1; i <= 1; i++)
5035                 {
5036                         for (j = -1; j <= 1; j++)
5037                         {
5038                                 if ((x + i >= x1) && (x + i <= x2) &&
5039                                          (y + j >= y1) && (y + j <= y2))
5040                                 {
5041                                         add_outer_wall(x + i, y + j, light, x1, y1, x2, y2);
5042                                         if (light) cave[y][x].info |= CAVE_GLOW;
5043                                 }
5044                         }
5045                 }
5046         }
5047         else if (is_extra_bold(y, x))
5048         {
5049                 /* Set bounding walls */
5050                 place_outer_bold(y, x);
5051                 if (light) cave[y][x].info |= CAVE_GLOW;
5052         }
5053         else if (cave[y][x].feat == FEAT_PERM_OUTER)
5054         {
5055                 /* Set bounding walls */
5056                 if (light) cave[y][x].info |= CAVE_GLOW;
5057         }
5058 }
5059
5060
5061 /*
5062  * Hacked distance formula - gives the 'wrong' answer.
5063  * Used to build crypts
5064  */
5065 static int dist2(int x1, int y1, int x2, int y2,
5066                  int h1, int h2, int h3, int h4)
5067 {
5068         int dx, dy;
5069         dx = abs(x2 - x1);
5070         dy = abs(y2 - y1);
5071
5072         /* Basically this works by taking the normal pythagorean formula
5073          * and using an expansion to express this in a way without the
5074          * square root.  This approximate formula is then perturbed to give
5075          * the distorted results.  (I found this by making a mistake when I was
5076          * trying to fix the circular rooms.)
5077          */
5078
5079         /* h1-h4 are constants that describe the metric */
5080         if (dx >= 2 * dy) return (dx + (dy * h1) / h2);
5081         if (dy >= 2 * dx) return (dy + (dx * h1) / h2);
5082         return (((dx + dy) * 128) / 181 +
5083                 (dx * dx / (dy * h3) + dy * dy / (dx * h3)) * h4);
5084         /* 128/181 is approx. 1/sqrt(2) */
5085 }
5086
5087
5088 /*
5089  * Build target vault.
5090  * This is made by two concentric "crypts" with perpendicular
5091  * walls creating the cross-hairs.
5092  */
5093 static void build_target_vault(int x0, int y0, int xsize, int ysize)
5094 {
5095         int rad, x, y;
5096
5097         /* Make a random metric */
5098         int h1, h2, h3, h4;
5099         h1 = randint1(32) - 16;
5100         h2 = randint1(16);
5101         h3 = randint1(32);
5102         h4 = randint1(32) - 16;
5103
5104         if (cheat_room) msg_print("Target Vault");
5105
5106         /* work out outer radius */
5107         if (xsize > ysize)
5108         {
5109                 rad = ysize / 2;
5110         }
5111         else
5112         {
5113                 rad = xsize / 2;
5114         }
5115
5116         /* Make floor */
5117         for (x = x0 - rad; x <= x0 + rad; x++)
5118         {
5119                 for (y = y0 - rad; y <= y0 + rad; y++)
5120                 {
5121                         /* clear room flag */
5122                         cave[y][x].info &= ~(CAVE_ROOM);
5123
5124                         /* Vault - so is "icky" */
5125                         cave[y][x].info |= CAVE_ICKY;
5126
5127                         if (dist2(y0, x0, y, x, h1, h2, h3, h4) <= rad - 1)
5128                         {
5129                                 /* inside- so is floor */
5130                                 place_floor_bold(y, x);
5131                         }
5132                         else
5133                         {
5134                                 /* make granite outside so arena works */
5135                                 place_extra_bold(y, x);
5136                         }
5137
5138                         /* proper boundary for arena */
5139                         if (((y + rad) == y0) || ((y - rad) == y0) ||
5140                             ((x + rad) == x0) || ((x - rad) == x0))
5141                         {
5142                                 place_extra_bold(y, x);
5143                         }
5144                 }
5145         }
5146
5147         /* Find visible outer walls and set to be FEAT_OUTER */
5148         add_outer_wall(x0, y0, FALSE, x0 - rad - 1, y0 - rad - 1,
5149                        x0 + rad + 1, y0 + rad + 1);
5150
5151         /* Add inner wall */
5152         for (x = x0 - rad / 2; x <= x0 + rad / 2; x++)
5153         {
5154                 for (y = y0 - rad / 2; y <= y0 + rad / 2; y++)
5155                 {
5156                         if (dist2(y0, x0, y, x, h1, h2, h3, h4) == rad / 2)
5157                         {
5158                                 /* Make an internal wall */
5159                                 place_inner_bold(y, x);
5160                         }
5161                 }
5162         }
5163
5164         /* Add perpendicular walls */
5165         for (x = x0 - rad; x <= x0 + rad; x++)
5166         {
5167                 place_inner_bold(y0, x);
5168         }
5169
5170         for (y = y0 - rad; y <= y0 + rad; y++)
5171         {
5172                 place_inner_bold(y, x0);
5173         }
5174
5175         /* Make inner vault */
5176         for (y = y0 - 1; y <= y0 + 1; y++)
5177         {
5178                 place_inner_bold(y, x0 - 1);
5179                 place_inner_bold(y, x0 + 1);
5180         }
5181         for (x = x0 - 1; x <= x0 + 1; x++)
5182         {
5183                 place_inner_bold(y0 - 1, x);
5184                 place_inner_bold(y0 + 1, x);
5185         }
5186
5187         place_floor_bold(y0, x0);
5188
5189
5190         /* Add doors to vault */
5191         /* get two distances so can place doors relative to centre */
5192         x = (rad - 2) / 4 + 1;
5193         y = rad / 2 + x;
5194
5195         add_door(x0 + x, y0);
5196         add_door(x0 + y, y0);
5197         add_door(x0 - x, y0);
5198         add_door(x0 - y, y0);
5199         add_door(x0, y0 + x);
5200         add_door(x0, y0 + y);
5201         add_door(x0, y0 - x);
5202         add_door(x0, y0 - y);
5203
5204         /* Fill with stuff - medium difficulty */
5205         fill_treasure(x0 - rad, x0 + rad, y0 - rad, y0 + rad, randint1(3) + 3);
5206 }
5207
5208
5209 #ifdef ALLOW_CAVERNS_AND_LAKES
5210 /*
5211  * This routine uses a modified version of the lake code to make a
5212  * distribution of some terrain type over the vault.  This type
5213  * depends on the dungeon depth.
5214  *
5215  * Miniture rooms are then scattered across the vault.
5216  */
5217 static void build_elemental_vault(int x0, int y0, int xsiz, int ysiz)
5218 {
5219         int grd, roug;
5220         int c1, c2, c3;
5221         bool done = FALSE;
5222         int xsize, ysize, xhsize, yhsize, x, y, i;
5223         int type;
5224
5225
5226         if (cheat_room) msg_print("Elemental Vault");
5227
5228         /* round to make sizes even */
5229         xhsize = xsiz / 2;
5230         yhsize = ysiz / 2;
5231         xsize = xhsize * 2;
5232         ysize = yhsize * 2;
5233
5234         if (dun_level < 25)
5235         {
5236                 /* Earth vault  (Rubble) */
5237                 type = LAKE_T_EARTH_VAULT;
5238         }
5239         else if (dun_level < 50)
5240         {
5241                 /* Air vault (Trees) */
5242                 type = LAKE_T_AIR_VAULT;
5243         }
5244         else if (dun_level < 75)
5245         {
5246                 /* Water vault (shallow water) */
5247                 type = LAKE_T_WATER_VAULT;
5248         }
5249         else
5250         {
5251                 /* Fire vault (shallow lava) */
5252                 type = LAKE_T_FIRE_VAULT;
5253         }
5254
5255         while (!done)
5256         {
5257                 /* testing values for these parameters: feel free to adjust */
5258                 grd = 1 << (randint0(3));
5259
5260                 /* want average of about 16 */
5261                 roug = randint1(8) * randint1(4);
5262
5263                 /* Make up size of various componants */
5264                 /* Floor */
5265                 c3 = 2 * xsize / 3;
5266
5267                 /* Deep water/lava */
5268                 c1 = randint0(c3 / 2) + randint0(c3 / 2) - 5;
5269
5270                 /* Shallow boundary */
5271                 c2 = (c1 + c3) / 2;
5272
5273                 /* make it */
5274                 generate_hmap(y0, x0, xsize, ysize, grd, roug, c3);
5275
5276                 /* Convert to normal format+ clean up */
5277                 done = generate_lake(y0, x0, xsize, ysize, c1, c2, c3, type);
5278         }
5279
5280         /* Set icky flag because is a vault */
5281         for (x = 0; x <= xsize; x++)
5282         {
5283                 for (y = 0; y <= ysize; y++)
5284                 {
5285                         cave[y0 - yhsize + y][x0 - xhsize + x].info |= CAVE_ICKY;
5286                 }
5287         }
5288
5289         /* make a few rooms in the vault */
5290         for (i = 1; i <= (xsize * ysize) / 50; i++)
5291         {
5292                 build_small_room(x0 + randint0(xsize - 4) - xsize / 2 + 2,
5293                                  y0 + randint0(ysize - 4) - ysize / 2 + 2);
5294         }
5295
5296         /* Fill with monsters and treasure, low difficulty */
5297         fill_treasure(x0 - xhsize + 1, x0 - xhsize + xsize - 1,
5298                       y0 - yhsize + 1, y0 - yhsize + ysize - 1, randint1(5));
5299 }
5300 #endif /* ALLOW_CAVERNS_AND_LAKES */
5301
5302
5303 /*
5304  * Random vaults
5305  */
5306 static bool build_type10(void)
5307 {
5308         int y0, x0, xsize, ysize, vtype;
5309
5310         /* Get size */
5311         /* big enough to look good, small enough to be fairly common. */
5312         xsize = randint1(22) + 22;
5313         ysize = randint1(11) + 11;
5314
5315         /* Find and reserve some space in the dungeon.  Get center of room. */
5316         if (!find_space(&y0, &x0, ysize + 1, xsize + 1)) return FALSE;
5317
5318         /* Boost the rating- higher than lesser vaults and lower than greater vaults */
5319         rating += 10;
5320
5321         /* (Sometimes) Cause a special feeling */
5322         if ((dun_level <= 50) ||
5323             (randint1((dun_level - 40) * (dun_level - 40) + 1) < 400))
5324         {
5325                 good_item_flag = TRUE;
5326         }
5327
5328         /* Select type of vault */
5329 #ifdef ALLOW_CAVERNS_AND_LAKES
5330         vtype = randint1(15);
5331 #else /* ALLOW_CAVERNS_AND_LAKES */
5332         vtype = randint1(7);
5333 #endif /* ALLOW_CAVERNS_AND_LAKES */
5334
5335         switch (vtype)
5336         {
5337                 /* Build an appropriate room */
5338                 case 1: case  9: build_bubble_vault(x0, y0, xsize, ysize); break;
5339                 case 2: case 10: build_room_vault(x0, y0, xsize, ysize); break;
5340                 case 3: case 11: build_cave_vault(x0, y0, xsize, ysize); break;
5341                 case 4: case 12: build_maze_vault(x0, y0, xsize, ysize, TRUE); break;
5342                 case 5: case 13: build_mini_c_vault(x0, y0, xsize, ysize); break;
5343                 case 6: case 14: build_castle_vault(x0, y0, xsize, ysize); break;
5344                 case 7: case 15: build_target_vault(x0, y0, xsize, ysize); break;
5345 #ifdef ALLOW_CAVERNS_AND_LAKES
5346                 case 8: build_elemental_vault(x0, y0, xsize, ysize); break;
5347 #endif /* ALLOW_CAVERNS_AND_LAKES */
5348                 /* I know how to add a few more... give me some time. */
5349
5350                 /* Paranoia */
5351                 default: return FALSE;
5352         }
5353
5354         return TRUE;
5355 }
5356
5357
5358 /*
5359  * Build an vertical oval room.
5360  * For every grid in the possible square, check the distance.
5361  * If it's less than the radius, make it a room square.
5362  *
5363  * When done fill from the inside to find the walls,
5364  */
5365 static bool build_type11(void)
5366 {
5367         int rad, x, y, x0, y0;
5368         int light = FALSE;
5369
5370         /* Occasional light */
5371         if ((randint1(dun_level) <= 15) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS)) light = TRUE;
5372
5373         rad = randint0(9);
5374
5375         /* Find and reserve some space in the dungeon.  Get center of room. */
5376         if (!find_space(&y0, &x0, rad * 2 + 1, rad * 2 + 1)) return FALSE;
5377
5378         /* Make circular floor */
5379         for (x = x0 - rad; x <= x0 + rad; x++)
5380         {
5381                 for (y = y0 - rad; y <= y0 + rad; y++)
5382                 {
5383                         if (distance(y0, x0, y, x) <= rad - 1)
5384                         {
5385                                 /* inside- so is floor */
5386                                 place_floor_bold(y, x);
5387                         }
5388                         else if (distance(y0, x0, y, x) <= rad + 1)
5389                         {
5390                                 /* make granite outside so arena works */
5391                                 place_extra_bold(y, x);
5392                         }
5393                 }
5394         }
5395
5396         /* Find visible outer walls and set to be FEAT_OUTER */
5397         add_outer_wall(x0, y0, light, x0 - rad, y0 - rad, x0 + rad, y0 + rad);
5398
5399         return TRUE;
5400 }
5401
5402
5403 /*
5404  * Build crypt room.
5405  * For every grid in the possible square, check the (fake) distance.
5406  * If it's less than the radius, make it a room square.
5407  *
5408  * When done fill from the inside to find the walls,
5409  */
5410 static bool build_type12(void)
5411 {
5412         int rad, x, y, x0, y0;
5413         int light = FALSE;
5414         bool emptyflag = TRUE;
5415
5416         /* Make a random metric */
5417         int h1, h2, h3, h4;
5418         h1 = randint1(32) - 16;
5419         h2 = randint1(16);
5420         h3 = randint1(32);
5421         h4 = randint1(32) - 16;
5422
5423         /* Occasional light */
5424         if ((randint1(dun_level) <= 5) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS)) light = TRUE;
5425
5426         rad = randint1(9);
5427
5428         /* Find and reserve some space in the dungeon.  Get center of room. */
5429         if (!find_space(&y0, &x0, rad * 2 + 3, rad * 2 + 3)) return FALSE;
5430
5431         /* Make floor */
5432         for (x = x0 - rad; x <= x0 + rad; x++)
5433         {
5434                 for (y = y0 - rad; y <= y0 + rad; y++)
5435                 {
5436                         /* clear room flag */
5437                         cave[y][x].info &= ~(CAVE_ROOM);
5438
5439                         if (dist2(y0, x0, y, x, h1, h2, h3, h4) <= rad - 1)
5440                         {
5441                                 /* inside - so is floor */
5442                                 place_floor_bold(y, x);
5443                         }
5444                         else if (distance(y0, x0, y, x) < 3)
5445                         {
5446                                 place_floor_bold(y, x);
5447                         }
5448                         else
5449                         {
5450                                 /* make granite outside so arena works */
5451                                 place_extra_bold(y, x);
5452                         }
5453
5454                         /* proper boundary for arena */
5455                         if (((y + rad) == y0) || ((y - rad) == y0) ||
5456                             ((x + rad) == x0) || ((x - rad) == x0))
5457                         {
5458                                 place_extra_bold(y, x);
5459                         }
5460                 }
5461         }
5462
5463         /* Find visible outer walls and set to be FEAT_OUTER */
5464         add_outer_wall(x0, y0, light, x0 - rad - 1, y0 - rad - 1,
5465                        x0 + rad + 1, y0 + rad + 1);
5466
5467         /* Check to see if there is room for an inner vault */
5468         for (x = x0 - 2; x <= x0 + 2; x++)
5469         {
5470                 for (y = y0 - 2; y <= y0 + 2; y++)
5471                 {
5472                         if (!is_floor_bold(y, x))
5473                         {
5474                                 /* Wall in the way */
5475                                 emptyflag = FALSE;
5476                         }
5477                 }
5478         }
5479
5480         if (emptyflag && one_in_(2))
5481         {
5482                 /* Build the vault */
5483                 build_small_room(x0, y0);
5484
5485                 /* Place a treasure in the vault */
5486                 place_object(y0, x0, 0L);
5487
5488                 /* Let's guard the treasure well */
5489                 vault_monsters(y0, x0, randint0(2) + 3);
5490
5491                 /* Traps naturally */
5492                 vault_traps(y0, x0, 4, 4, randint0(3) + 2);
5493         }
5494
5495         return TRUE;
5496 }
5497
5498
5499 /*
5500  * Helper function for "trapped monster pit"
5501  */
5502 static bool vault_aux_trapped_pit(int r_idx)
5503 {
5504         monster_race *r_ptr = &r_info[r_idx];
5505
5506         /* Validate the monster */
5507         if (!vault_monster_okay(r_idx)) return (FALSE);
5508
5509         /* No wall passing monster */
5510         if (r_ptr->flags2 & (RF2_PASS_WALL | RF2_KILL_WALL)) return (FALSE);
5511
5512         /* Okay */
5513         return (TRUE);
5514 }
5515
5516
5517 /*
5518  * Type 12 -- Trapped monster pits
5519  *
5520  * A trapped monster pit is a "big" room with a straight corridor in
5521  * which wall opening traps are placed, and with two "inner" rooms
5522  * containing a "collection" of monsters of a given type organized in
5523  * the room.
5524  *
5525  * The trapped monster pit appears as shown below, where the actual
5526  * monsters in each location depend on the type of the pit
5527  *
5528  *  #########################
5529  *  #                       #
5530  *  ####################### #
5531  *  #####001123454321100### #
5532  *  ###0012234567654322100# #
5533  *  ####################### #
5534  *  #           ^           #
5535  *  # #######################
5536  *  # #0012234567654322100###
5537  *  # ###001123454321100#####
5538  *  # #######################
5539  *  #                       #
5540  *  #########################
5541  *
5542  * Note that the monsters in the pit are now chosen by using "get_mon_num()"
5543  * to request 16 "appropriate" monsters, sorting them by level, and using
5544  * the "even" entries in this sorted list for the contents of the pit.
5545  *
5546  * Hack -- all of the "dragons" in a "dragon" pit must be the same "color",
5547  * which is handled by requiring a specific "breath" attack for all of the
5548  * dragons.  This may include "multi-hued" breath.  Note that "wyrms" may
5549  * be present in many of the dragon pits, if they have the proper breath.
5550  *
5551  * Note the use of the "get_mon_num_prep()" function, and the special
5552  * "get_mon_num_hook()" restriction function, to prepare the "monster
5553  * allocation table" in such a way as to optimize the selection of
5554  * "appropriate" non-unique monsters for the pit.
5555  *
5556  * Note that the "get_mon_num()" function may (rarely) fail, in which case
5557  * the pit will be empty, and will not effect the level rating.
5558  *
5559  * Note that "monster pits" will never contain "unique" monsters.
5560  */
5561 static bool build_type13(void)
5562 {
5563         static int placing[][3] = {
5564                 {-2, -9, 0}, {-2, -8, 0}, {-3, -7, 0}, {-3, -6, 0},
5565                 {+2, -9, 0}, {+2, -8, 0}, {+3, -7, 0}, {+3, -6, 0},
5566                 {-2, +9, 0}, {-2, +8, 0}, {-3, +7, 0}, {-3, +6, 0},
5567                 {+2, +9, 0}, {+2, +8, 0}, {+3, +7, 0}, {+3, +6, 0},
5568                 {-2, -7, 1}, {-3, -5, 1}, {-3, -4, 1}, 
5569                 {+2, -7, 1}, {+3, -5, 1}, {+3, -4, 1}, 
5570                 {-2, +7, 1}, {-3, +5, 1}, {-3, +4, 1}, 
5571                 {+2, +7, 1}, {+3, +5, 1}, {+3, +4, 1},
5572                 {-2, -6, 2}, {-2, -5, 2}, {-3, -3, 2},
5573                 {+2, -6, 2}, {+2, -5, 2}, {+3, -3, 2},
5574                 {-2, +6, 2}, {-2, +5, 2}, {-3, +3, 2},
5575                 {+2, +6, 2}, {+2, +5, 2}, {+3, +3, 2},
5576                 {-2, -4, 3}, {-3, -2, 3},
5577                 {+2, -4, 3}, {+3, -2, 3},
5578                 {-2, +4, 3}, {-3, +2, 3},
5579                 {+2, +4, 3}, {+3, +2, 3},
5580                 {-2, -3, 4}, {-3, -1, 4},
5581                 {+2, -3, 4}, {+3, -1, 4},
5582                 {-2, +3, 4}, {-3, +1, 4},
5583                 {+2, +3, 4}, {+3, +1, 4},
5584                 {-2, -2, 5}, {-3, 0, 5}, {-2, +2, 5},
5585                 {+2, -2, 5}, {+3, 0, 5}, {+2, +2, 5},
5586                 {-2, -1, 6}, {-2, +1, 6},
5587                 {+2, -1, 6}, {+2, +1, 6},
5588                 {-2, 0, 7}, {+2, 0, 7},
5589                 {0, 0, -1}
5590         };
5591
5592         int y, x, y1, x1, y2, x2, xval, yval;
5593         int i, j;
5594
5595         int what[16];
5596
5597         monster_type align;
5598
5599         cave_type *c_ptr;
5600
5601         int cur_pit_type = pick_vault_type(pit_types, d_info[dungeon_type].pit);
5602         vault_aux_type *n_ptr;
5603
5604         /* Only in Angband */
5605         if (dungeon_type != DUNGEON_ANGBAND) return FALSE;
5606
5607         /* No type available */
5608         if (cur_pit_type < 0) return FALSE;
5609
5610         n_ptr = &pit_types[cur_pit_type];
5611
5612         /* Process a preparation function if necessary */
5613         if (n_ptr->prep_func) (*(n_ptr->prep_func))();
5614
5615         /* Prepare allocation table */
5616         get_mon_num_prep(n_ptr->hook_func, vault_aux_trapped_pit);
5617
5618         align.sub_align = SUB_ALIGN_NEUTRAL;
5619
5620         /* Pick some monster types */
5621         for (i = 0; i < 16; i++)
5622         {
5623                 int r_idx = 0, attempts = 100;
5624                 monster_race *r_ptr = NULL;
5625
5626                 while (attempts--)
5627                 {
5628                         /* Get a (hard) monster type */
5629                         r_idx = get_mon_num(dun_level + 0);
5630                         r_ptr = &r_info[r_idx];
5631
5632                         /* Decline incorrect alignment */
5633                         if (monster_has_hostile_align(&align, 0, 0, r_ptr)) continue;
5634
5635                         /* Accept this monster */
5636                         break;
5637                 }
5638
5639                 /* Notice failure */
5640                 if (!r_idx || !attempts) return FALSE;
5641
5642                 /* Note the alignment */
5643                 if (r_ptr->flags3 & RF3_EVIL) align.sub_align |= SUB_ALIGN_EVIL;
5644                 if (r_ptr->flags3 & RF3_GOOD) align.sub_align |= SUB_ALIGN_GOOD;
5645
5646                 what[i] = r_idx;
5647         }
5648
5649         /* Find and reserve some space in the dungeon.  Get center of room. */
5650         if (!find_space(&yval, &xval, 13, 25)) return FALSE;
5651
5652         /* Large room */
5653         y1 = yval - 5;
5654         y2 = yval + 5;
5655         x1 = xval - 11;
5656         x2 = xval + 11;
5657
5658         /* Fill with inner walls */
5659         for (y = y1 - 1; y <= y2 + 1; y++)
5660         {
5661                 for (x = x1 - 1; x <= x2 + 1; x++)
5662                 {
5663                         c_ptr = &cave[y][x];
5664                         place_inner_grid(c_ptr);
5665                         c_ptr->info |= (CAVE_ROOM);
5666                 }
5667         }
5668
5669         /* Place the floor area 1 */
5670         for (x = x1 + 3; x <= x2 - 3; x++)
5671         {
5672                 c_ptr = &cave[yval-2][x];
5673                 place_floor_grid(c_ptr);
5674                 add_cave_info(yval-2, x, CAVE_ICKY);
5675
5676                 c_ptr = &cave[yval+2][x];
5677                 place_floor_grid(c_ptr);
5678                 add_cave_info(yval+2, x, CAVE_ICKY);
5679         }
5680
5681         /* Place the floor area 2 */
5682         for (x = x1 + 5; x <= x2 - 5; x++)
5683         {
5684                 c_ptr = &cave[yval-3][x];
5685                 place_floor_grid(c_ptr);
5686                 add_cave_info(yval-3, x, CAVE_ICKY);
5687
5688                 c_ptr = &cave[yval+3][x];
5689                 place_floor_grid(c_ptr);
5690                 add_cave_info(yval+3, x, CAVE_ICKY);
5691         }
5692
5693         /* Corridor */
5694         for (x = x1; x <= x2; x++)
5695         {
5696                 c_ptr = &cave[yval][x];
5697                 place_floor_grid(c_ptr);
5698                 c_ptr = &cave[y1][x];
5699                 place_floor_grid(c_ptr);
5700                 c_ptr = &cave[y2][x];
5701                 place_floor_grid(c_ptr);
5702         }
5703
5704         /* Place the outer walls */
5705         for (y = y1 - 1; y <= y2 + 1; y++)
5706         {
5707                 c_ptr = &cave[y][x1 - 1];
5708                 place_outer_grid(c_ptr);
5709                 c_ptr = &cave[y][x2 + 1];
5710                 place_outer_grid(c_ptr);
5711         }
5712         for (x = x1 - 1; x <= x2 + 1; x++)
5713         {
5714                 c_ptr = &cave[y1 - 1][x];
5715                 place_outer_grid(c_ptr);
5716                 c_ptr = &cave[y2 + 1][x];
5717                 place_outer_grid(c_ptr);
5718         }
5719
5720         /* Random corridor */
5721         if (one_in_(2))
5722         {
5723                 for (y = y1; y <= yval; y++)
5724                 {
5725                         place_floor_bold(y, x2);
5726                         place_solid_bold(y, x1-1);
5727                 }
5728                 for (y = yval; y <= y2 + 1; y++)
5729                 {
5730                         place_floor_bold(y, x1);
5731                         place_solid_bold(y, x2+1);
5732                 }
5733         }
5734         else
5735         {
5736                 for (y = yval; y <= y2 + 1; y++)
5737                 {
5738                         place_floor_bold(y, x1);
5739                         place_solid_bold(y, x2+1);
5740                 }
5741                 for (y = y1; y <= yval; y++)
5742                 {
5743                         place_floor_bold(y, x2);
5744                         place_solid_bold(y, x1-1);
5745                 }
5746         }
5747
5748         /* Place the wall open trap */
5749         cave[yval][xval].mimic = cave[yval][xval].feat;
5750         cave[yval][xval].feat = FEAT_TRAP_OPEN;
5751
5752         /* Sort the entries */
5753         for (i = 0; i < 16 - 1; i++)
5754         {
5755                 /* Sort the entries */
5756                 for (j = 0; j < 16 - 1; j++)
5757                 {
5758                         int i1 = j;
5759                         int i2 = j + 1;
5760
5761                         int p1 = r_info[what[i1]].level;
5762                         int p2 = r_info[what[i2]].level;
5763
5764                         /* Bubble */
5765                         if (p1 > p2)
5766                         {
5767                                 int tmp = what[i1];
5768                                 what[i1] = what[i2];
5769                                 what[i2] = tmp;
5770                         }
5771                 }
5772         }
5773
5774         /* Message */
5775         if (cheat_room)
5776         {
5777                 /* Room type */
5778 #ifdef JP
5779                 msg_format("%s%s¤Î櫥ԥåÈ", n_ptr->name, pit_subtype_string(cur_pit_type, FALSE));
5780 #else
5781                 msg_format("Trapped monster pit (%s%s)", n_ptr->name, pit_subtype_string(cur_pit_type, FALSE));
5782 #endif
5783         }
5784
5785         /* Select the entries */
5786         for (i = 0; i < 8; i++)
5787         {
5788                 /* Every other entry */
5789                 what[i] = what[i * 2];
5790
5791                 if (cheat_hear)
5792                 {
5793                         /* Message */
5794                         msg_print(r_name + r_info[what[i]].name);
5795                 }
5796         }
5797
5798         /* Increase the level rating */
5799         rating += 20;
5800
5801         /* (Sometimes) Cause a "special feeling" (for "Monster Pits") */
5802         if ((dun_level <= 40) && (randint1(dun_level * dun_level + 50) < 300))
5803         {
5804                 good_item_flag = TRUE;
5805         }
5806
5807         for (i = 0; placing[i][2] >= 0; i++)
5808         {
5809                 y = yval + placing[i][0];
5810                 x = xval + placing[i][1];
5811                 place_monster_aux(0, y, x, what[placing[i][2]], PM_NO_KAGE);
5812         }
5813
5814         return TRUE;
5815 }
5816
5817
5818 /*
5819  * Type 14 -- trapped rooms
5820  *
5821  * A special trap is placed at center of the room
5822  */
5823 static bool build_type14(void)
5824 {
5825         int y, x, y2, x2, yval, xval;
5826         int y1, x1, xsize, ysize;
5827
5828         bool light;
5829
5830         cave_type *c_ptr;
5831         byte trap;
5832
5833         /* Pick a room size */
5834         y1 = randint1(4);
5835         x1 = randint1(11);
5836         y2 = randint1(3);
5837         x2 = randint1(11);
5838
5839         xsize = x1 + x2 + 1;
5840         ysize = y1 + y2 + 1;
5841
5842         /* Find and reserve some space in the dungeon.  Get center of room. */
5843         if (!find_space(&yval, &xval, ysize + 2, xsize + 2)) return FALSE;
5844
5845         /* Choose lite or dark */
5846         light = ((dun_level <= randint1(25)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS));
5847
5848
5849         /* Get corner values */
5850         y1 = yval - ysize / 2;
5851         x1 = xval - xsize / 2;
5852         y2 = yval + (ysize - 1) / 2;
5853         x2 = xval + (xsize - 1) / 2;
5854
5855
5856         /* Place a full floor under the room */
5857         for (y = y1 - 1; y <= y2 + 1; y++)
5858         {
5859                 for (x = x1 - 1; x <= x2 + 1; x++)
5860                 {
5861                         c_ptr = &cave[y][x];
5862                         place_floor_grid(c_ptr);
5863                         c_ptr->info |= (CAVE_ROOM);
5864                         if (light) c_ptr->info |= (CAVE_GLOW);
5865                 }
5866         }
5867
5868         /* Walls around the room */
5869         for (y = y1 - 1; y <= y2 + 1; y++)
5870         {
5871                 c_ptr = &cave[y][x1 - 1];
5872                 place_outer_grid(c_ptr);
5873                 c_ptr = &cave[y][x2 + 1];
5874                 place_outer_grid(c_ptr);
5875         }
5876         for (x = x1 - 1; x <= x2 + 1; x++)
5877         {
5878                 c_ptr = &cave[y1 - 1][x];
5879                 place_outer_grid(c_ptr);
5880                 c_ptr = &cave[y2 + 1][x];
5881                 place_outer_grid(c_ptr);
5882         }
5883
5884         if (dun_level < 30 + randint1(30))
5885                 trap = FEAT_TRAP_PIRANHA;
5886         else
5887                 trap = FEAT_TRAP_ARMAGEDDON;
5888
5889         /* Place a special trap */
5890         c_ptr = &cave[rand_spread(yval, ysize/4)][rand_spread(xval, xsize/4)];
5891         c_ptr->mimic = c_ptr->feat;
5892         c_ptr->feat = trap;
5893
5894         /* Message */
5895         if (cheat_room)
5896         {
5897 #ifdef JP
5898                 msg_format("%s¤ÎÉô²°", f_name + f_info[trap].name);
5899 #else
5900                 msg_format("Room of %s", f_name + f_info[trap].name);
5901 #endif
5902         }
5903
5904         return TRUE;
5905 }
5906
5907
5908 /*
5909  * Attempt to build a room of the given type at the given block
5910  *
5911  * Note that we restrict the number of "crowded" rooms to reduce
5912  * the chance of overflowing the monster list during level creation.
5913  */
5914 bool room_build(int typ)
5915 {
5916         /* Build a room */
5917         switch (typ)
5918         {
5919         /* Build an appropriate room */
5920         case ROOM_T_NORMAL:        build_type1(); break;
5921         case ROOM_T_OVERLAP:       build_type2(); break;
5922         case ROOM_T_CROSS:         build_type3(); break;
5923         case ROOM_T_INNER_FEAT:    build_type4(); break;
5924         case ROOM_T_NEST:          build_type5(); break;
5925         case ROOM_T_PIT:           build_type6(); break;
5926         case ROOM_T_LESSER_VAULT:  build_type7(); break;
5927         case ROOM_T_GREATER_VAULT: build_type8(); break;
5928         case ROOM_T_FRACAVE:       build_type9(); break;
5929         case ROOM_T_RANDOM_VAULT:  build_type10(); break;
5930         case ROOM_T_OVAL:          build_type11(); break;
5931         case ROOM_T_CRYPT:         build_type12(); break;
5932         case ROOM_T_TRAP_PIT:      build_type13(); break;
5933         case ROOM_T_TRAP:          build_type14(); break;
5934
5935         /* Paranoia */
5936         default: return FALSE;
5937         }
5938
5939         return TRUE;
5940 }
5941
5942
5943 #define MOVE_PLIST(dst, src) (prob_list[dst] += prob_list[src], prob_list[src] = 0)
5944
5945 /*
5946  * [from SAngband (originally from OAngband)]
5947  * 
5948  * Generate rooms in dungeon.  Build bigger rooms at first.
5949  */
5950 void generate_rooms(void)
5951 {
5952         int i;
5953         bool remain;
5954         int crowded = 0;
5955         int total_prob;
5956         int prob_list[ROOM_T_MAX];
5957         int rooms_built = 0;
5958         int area_size = 100 * (cur_hgt*cur_wid) / (MAX_HGT*MAX_WID);
5959         int level_index = MIN(10, div_round(dun_level, 10));
5960
5961         /* Number of each type of room on this level */
5962         s16b room_num[ROOM_T_MAX];
5963
5964         /* Limit number of rooms */
5965         int dun_rooms = rand_range(DUN_ROOMS_MIN, DUN_ROOMS_MAX * area_size / 100);
5966
5967         /* Assume normal cave */
5968         room_info_type *room_info_ptr = room_info_normal;
5969
5970
5971         /*
5972          * Initialize probability list.
5973          */
5974         for (i = 0; i < ROOM_T_MAX; i++)
5975         {
5976                 /* No rooms allowed above their minimum depth. */
5977                 if (dun_level < room_info_ptr[i].min_level)
5978                 {
5979                         prob_list[i] = 0;
5980                 }
5981                 else
5982                 {
5983                         prob_list[i] = room_info_ptr[i].prob[level_index];
5984                 }
5985         }
5986
5987         /*
5988          * XXX -- Various dungeon types and options.
5989          */
5990
5991         /* Ironman sees only Greater Vaults */
5992         if (ironman_rooms && !((d_info[dungeon_type].flags1 & (DF1_BEGINNER | DF1_CHAMELEON))))
5993         {
5994                 for (i = 0; i < ROOM_T_MAX; i++)
5995                 {
5996                         if (i == ROOM_T_GREATER_VAULT) prob_list[i] = 1;
5997                         else prob_list[i] = 0;
5998                 }
5999         }
6000
6001         /* Forbidden vaults */
6002         else if (d_info[dungeon_type].flags1 & DF1_NO_VAULT)
6003         {
6004                 prob_list[ROOM_T_LESSER_VAULT] = 0;
6005                 prob_list[ROOM_T_GREATER_VAULT] = 0;
6006                 prob_list[ROOM_T_RANDOM_VAULT] = 0;
6007         }
6008
6009
6010         /* NO_CAVE dungeon (Castle)*/
6011         if (d_info[dungeon_type].flags1 & DF1_NO_CAVE)
6012         {
6013                 MOVE_PLIST(ROOM_T_NORMAL, ROOM_T_FRACAVE);
6014                 MOVE_PLIST(ROOM_T_INNER_FEAT, ROOM_T_CRYPT);
6015                 MOVE_PLIST(ROOM_T_INNER_FEAT, ROOM_T_OVAL);
6016         }
6017
6018         /* CAVE dungeon (Orc cave etc.) */
6019         else if (d_info[dungeon_type].flags1 & DF1_CAVE)
6020         {
6021                 MOVE_PLIST(ROOM_T_FRACAVE, ROOM_T_NORMAL);
6022         }
6023
6024         /* No caves when a (random) cavern exists: they look bad */
6025         else if (dun->cavern || dun->empty_level)
6026         {
6027                 prob_list[ROOM_T_FRACAVE] = 0;
6028         }
6029
6030
6031         /*
6032          * Initialize number of rooms,
6033          * And calcurate total probability.
6034          */
6035         for (total_prob = 0, i = 0; i < ROOM_T_MAX; i++)
6036         {
6037                 room_num[i] = 0;
6038                 total_prob += prob_list[i];
6039         }
6040
6041         /*
6042          * Prepare the number of rooms, of all types, we should build
6043          * on this level.
6044          */
6045         for (i = dun_rooms; i > 0; i--)
6046         {
6047                 int room_type;
6048                 int rand = randint0(total_prob);
6049
6050                 /* Get room_type randomly */
6051                 for (room_type = 0; room_type < ROOM_T_MAX; room_type++)
6052                 {
6053                         if (rand < prob_list[room_type]) break;
6054                         else rand -= prob_list[room_type];
6055                 }
6056
6057                 /* Paranoia */
6058                 if (room_type >= ROOM_T_MAX) room_type = ROOM_T_NORMAL;
6059
6060                 /* Increase the number of rooms of that type we should build. */
6061                 room_num[room_type]++;
6062
6063                 switch (room_type)
6064                 {
6065                 case ROOM_T_NEST:
6066                 case ROOM_T_PIT:
6067                 case ROOM_T_LESSER_VAULT:
6068                 case ROOM_T_TRAP_PIT:
6069
6070                         /* Large room */
6071                         i -= 2;
6072                         break;
6073
6074                 case ROOM_T_GREATER_VAULT:
6075                 case ROOM_T_RANDOM_VAULT:
6076
6077                         /* Largest room */
6078                         i -= 3;
6079                         break;
6080                 }
6081         }
6082
6083         /*
6084          * Build each type of room one by one until we cannot build any more.
6085          * [from SAngband (originally from OAngband)]
6086          */
6087         while (TRUE)
6088         {
6089                 /* Assume no remaining rooms */
6090                 remain = FALSE;
6091
6092                 for (i = 0; i < ROOM_T_MAX; i++)
6093                 {
6094                         /* What type of room are we building now? */
6095                         int room_type = room_build_order[i];
6096
6097                         /* Go next if none available */
6098                         if (!room_num[room_type]) continue;
6099
6100                         /* Use up one unit */
6101                         room_num[room_type]--;
6102
6103                         /* Build the room. */
6104                         if (room_build(room_type))
6105                         {
6106                                 /* Increase the room built count. */
6107                                 rooms_built++;
6108
6109                                 /* Mark as there was some remaining rooms */
6110                                 remain = TRUE;
6111
6112                                 switch (room_type)
6113                                 {
6114                                 case ROOM_T_PIT:
6115                                 case ROOM_T_NEST:
6116                                 case ROOM_T_TRAP_PIT:
6117
6118                                         /* Avoid too many monsters */
6119                                         if (++crowded >= 2)
6120                                         {
6121                                                 room_num[ROOM_T_PIT] = 0;
6122                                                 room_num[ROOM_T_NEST] = 0;
6123                                                 room_num[ROOM_T_TRAP_PIT] = 0;
6124                                         }
6125                                 }
6126                         }
6127
6128                         /* Stop building this type on failure. */
6129                         else
6130                         {
6131                                 room_num[room_type] = 0;
6132                         }
6133                 }
6134
6135                 /* End loop if no room remain */
6136                 if (!remain) break;
6137         }
6138
6139 }
6140
6141