OSDN Git Service

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