OSDN Git Service

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