OSDN Git Service

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