OSDN Git Service

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