OSDN Git Service

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