OSDN Git Service

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