OSDN Git Service

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