OSDN Git Service

cheat_room時に, いくつかのpitやnestについて詳細を表示するように変更.
[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 by inner wall because this is used in rooms only */
70                 c_ptr->mimic = feat_wall_inner;
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, TRUE);
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 typedef struct vault_aux_type vault_aux_type;
1607
1608
1609 struct vault_aux_type
1610 {
1611         cptr name;
1612         bool (*hook_func)(int r_idx);
1613         void (*prep_func)(void);
1614         int level;
1615         int chance;
1616 };
1617
1618
1619 static int pick_vault_type(vault_aux_type *l_ptr, s16b allow_flag_mask)
1620 {
1621         int tmp, total, count;
1622
1623         vault_aux_type *n_ptr;
1624
1625         /* Calculate the total possibilities */
1626         for (n_ptr = l_ptr, total = 0, count = 0; TRUE; n_ptr++, count++)
1627         {
1628                 /* Note end */
1629                 if (!n_ptr->name) break;
1630
1631                 /* Ignore excessive depth */
1632                 if (n_ptr->level > dun_level) continue;
1633
1634                 /* Not matched with pit/nest flag */
1635                 if (!(allow_flag_mask & (1L << count))) continue;
1636
1637                 /* Count this possibility */
1638                 total += n_ptr->chance * MAX_DEPTH / (MIN(dun_level, MAX_DEPTH - 1) - n_ptr->level + 5);
1639         }
1640
1641         /* Pick a random type */
1642         tmp = randint0(total);
1643
1644         /* Find this type */
1645         for (n_ptr = l_ptr, total = 0, count = 0; TRUE; n_ptr++, count++)
1646         {
1647                 /* Note end */
1648                 if (!n_ptr->name) break;
1649
1650                 /* Ignore excessive depth */
1651                 if (n_ptr->level > dun_level) continue;
1652
1653                 /* Not matched with pit/nest flag */
1654                 if (!(allow_flag_mask & (1L << count))) continue;
1655
1656                 /* Count this possibility */
1657                 total += n_ptr->chance * MAX_DEPTH / (MIN(dun_level, MAX_DEPTH - 1) - n_ptr->level + 5);
1658
1659                 /* Found the type */
1660                 if (tmp < total) break;
1661         }
1662
1663         return n_ptr->name ? count : -1;
1664 }
1665
1666 static void build_type6(int by0, int bx0, bool nest);
1667 static void build_type5(int by0, int bx0, bool nest);
1668
1669 static vault_aux_type nest_types[] =
1670 {
1671 #ifdef JP
1672         {"¥¯¥í¡¼¥ó",    vault_aux_clone,        vault_prep_clone,       5,      3},
1673         {"¥¼¥ê¡¼",      vault_aux_jelly,        NULL,                   5,      6},
1674         {"¥·¥ó¥Ü¥ë(Á±)",vault_aux_symbol_g,     vault_prep_symbol,      25,     2},
1675         {"¥·¥ó¥Ü¥ë(°­)",vault_aux_symbol_e,     vault_prep_symbol,      25,     2},
1676         {"¥ß¥ß¥Ã¥¯",    vault_aux_mimic,        NULL,                   30,     4},
1677         {"¶¸µ¤",        vault_aux_cthulhu,      NULL,                   70,     2},
1678         {"¸¤¾®²°",      vault_aux_kennel,       NULL,                   45,     4},
1679         {"ưʪ±à",      vault_aux_animal,       NULL,                   35,     5},
1680         {"¶µ²ñ",        vault_aux_chapel_g,     NULL,                   75,     4},
1681         {"¥¢¥ó¥Ç¥Ã¥É",  vault_aux_undead,       NULL,                   75,     5},
1682         {NULL,          NULL,                   NULL,                   0,      0},
1683 #else
1684         {"clone",       vault_aux_clone,        vault_prep_clone,       5,      3},
1685         {"jelly",       vault_aux_jelly,        NULL,                   5,      6},
1686         {"symbol good",vault_aux_symbol_g,      vault_prep_symbol,      25,     2},
1687         {"symbol evil",vault_aux_symbol_e,      vault_prep_symbol,      25,     2},
1688         {"mimic",       vault_aux_mimic,        NULL,                   30,     4},
1689         {"lovecraftian",vault_aux_cthulhu,      NULL,                   70,     2},
1690         {"kennel",      vault_aux_kennel,       NULL,                   45,     4},
1691         {"animal",      vault_aux_animal,       NULL,                   35,     5},
1692         {"chapel",      vault_aux_chapel_g,     NULL,                   75,     4},
1693         {"undead",      vault_aux_undead,       NULL,                   75,     5},
1694         {NULL,          NULL,                   NULL,                   0,      0},
1695 #endif
1696 };
1697
1698 static vault_aux_type pit_types[] =
1699 {
1700 #ifdef JP
1701         {"¥ª¡¼¥¯",      vault_aux_orc,          NULL,                   5,      6},
1702         {"¥È¥í¥ë",      vault_aux_troll,        NULL,                   20,     6},
1703         {"¥¸¥ã¥¤¥¢¥ó¥È",vault_aux_giant,        NULL,                   50,     6},
1704         {"¶¸µ¤",        vault_aux_cthulhu,      NULL,                   80,     2},
1705         {"¥·¥ó¥Ü¥ë(Á±)",vault_aux_symbol_g,     vault_prep_symbol,      70,     1},
1706         {"¥·¥ó¥Ü¥ë(°­)",vault_aux_symbol_e,     vault_prep_symbol,      70,     1},
1707         {"¶µ²ñ",        vault_aux_chapel_g,     NULL,                   65,     2},
1708         {"¥É¥é¥´¥ó",    vault_aux_dragon,       vault_prep_dragon,      70,     6},
1709         {"¥Ç¡¼¥â¥ó",    vault_aux_demon,        NULL,                   80,     6},
1710         {NULL,          NULL,                   NULL,                   0,      0},
1711 #else
1712         {"orc",         vault_aux_orc,          NULL,                   5,      6},
1713         {"troll",       vault_aux_troll,        NULL,                   20,     6},
1714         {"giant",       vault_aux_giant,        NULL,                   50,     6},
1715         {"lovecraftian",vault_aux_cthulhu,      NULL,                   80,     2},
1716         {"symbol good",vault_aux_symbol_g,      vault_prep_symbol,      70,     1},
1717         {"symbol evil",vault_aux_symbol_e,      vault_prep_symbol,      70,     1},
1718         {"chapel",      vault_aux_chapel_g,     NULL,                   65,     2},
1719         {"dragon",      vault_aux_dragon,       vault_prep_dragon,      70,     6},
1720         {"demon",       vault_aux_demon,        NULL,                   80,     6},
1721         {NULL,          NULL,                   NULL,                   0,      0},
1722 #endif
1723 };
1724
1725
1726 /* Nest types code */
1727 #define NEST_TYPE_CLONE        0
1728 #define NEST_TYPE_JELLY        1
1729 #define NEST_TYPE_SYMBOL_GOOD  2
1730 #define NEST_TYPE_SYMBOL_EVIL  3
1731 #define NEST_TYPE_MIMIC        4
1732 #define NEST_TYPE_LOVECRAFTIAN 5
1733 #define NEST_TYPE_KENNEL       6
1734 #define NEST_TYPE_ANIMAL       7
1735 #define NEST_TYPE_CHAPEL       8
1736 #define NEST_TYPE_UNDEAD       9
1737
1738 /* Pit types code */
1739 #define PIT_TYPE_ORC           0
1740 #define PIT_TYPE_TROLL         1
1741 #define PIT_TYPE_GIANT         2
1742 #define PIT_TYPE_LOVECRAFTIAN  3
1743 #define PIT_TYPE_SYMBOL_GOOD   4
1744 #define PIT_TYPE_SYMBOL_EVIL   5
1745 #define PIT_TYPE_CHAPEL        6
1746 #define PIT_TYPE_DRAGON        7
1747 #define PIT_TYPE_DEMON         8
1748
1749
1750 /*
1751  * Hack -- Get the string describing subtype of pit/nest
1752  * Determined in prepare function (some pit/nest only)
1753  */
1754 static cptr pit_subtype_string(int type, bool nest)
1755 {
1756         static char inner_buf[256] = "";
1757
1758         inner_buf[0] = '\0'; /* Init string */
1759
1760         if (nest) /* Nests */
1761         {
1762                 switch (type)
1763                 {
1764                 case NEST_TYPE_CLONE:
1765                         sprintf(inner_buf, "(%s)", r_name + r_info[vault_aux_race].name);
1766                         break;
1767                 case NEST_TYPE_SYMBOL_GOOD:
1768                 case NEST_TYPE_SYMBOL_EVIL:
1769                         sprintf(inner_buf, "(%c)", vault_aux_char);
1770                         break;
1771                 }
1772         }
1773         else /* Pits */
1774         {
1775                 switch (type)
1776                 {
1777                 case PIT_TYPE_SYMBOL_GOOD:
1778                 case PIT_TYPE_SYMBOL_EVIL:
1779                         sprintf(inner_buf, "(%c)", vault_aux_char);
1780                         break;
1781                 case PIT_TYPE_DRAGON:
1782                         switch (vault_aux_dragon_mask4)
1783                         {
1784 #ifdef JP
1785                         case RF4_BR_ACID: strcpy(inner_buf, "(»À)");   break;
1786                         case RF4_BR_ELEC: strcpy(inner_buf, "(°ðºÊ)"); break;
1787                         case RF4_BR_FIRE: strcpy(inner_buf, "(²Ð±ê)"); break;
1788                         case RF4_BR_COLD: strcpy(inner_buf, "(Î䵤)"); break;
1789                         case RF4_BR_POIS: strcpy(inner_buf, "(ÆÇ)");   break;
1790                         case (RF4_BR_ACID | RF4_BR_ELEC | RF4_BR_FIRE | RF4_BR_COLD | RF4_BR_POIS):
1791                                 strcpy(inner_buf, "(Ëü¿§)"); break;
1792                         default: strcpy(inner_buf, "(̤ÄêµÁ)"); break;
1793 #else
1794                         case RF4_BR_ACID: strcpy(inner_buf, "(acid)");      break;
1795                         case RF4_BR_ELEC: strcpy(inner_buf, "(lightning)"); break;
1796                         case RF4_BR_FIRE: strcpy(inner_buf, "(fire)");      break;
1797                         case RF4_BR_COLD: strcpy(inner_buf, "(frost)");     break;
1798                         case RF4_BR_POIS: strcpy(inner_buf, "(poison)");    break;
1799                         case (RF4_BR_ACID | RF4_BR_ELEC | RF4_BR_FIRE | RF4_BR_COLD | RF4_BR_POIS):
1800                                 strcpy(inner_buf, "(multi-hued)"); break;
1801                         default: strcpy(inner_buf, "(undefined)"); break;
1802 #endif
1803                         }
1804                         break;
1805                 }
1806         }
1807
1808         return inner_buf;
1809 }
1810
1811
1812 /*
1813  * Type 5 -- Monster nests
1814  *
1815  * A monster nest is a "big" room, with an "inner" room, containing
1816  * a "collection" of monsters of a given type strewn about the room.
1817  *
1818  * The monsters are chosen from a set of 64 randomly selected monster
1819  * races, to allow the nest creation to fail instead of having "holes".
1820  *
1821  * Note the use of the "get_mon_num_prep()" function, and the special
1822  * "get_mon_num_hook()" restriction function, to prepare the "monster
1823  * allocation table" in such a way as to optimize the selection of
1824  * "appropriate" non-unique monsters for the nest.
1825  *
1826  * Note that the "get_mon_num()" function may (rarely) fail, in which
1827  * case the nest will be empty, and will not affect the level rating.
1828  *
1829  * Note that "monster nests" will never contain "unique" monsters.
1830  */
1831 static void build_type5(int by0, int bx0, bool pit)
1832 {
1833         int y, x, y1, x1, y2, x2, xval, yval;
1834         int i;
1835         int what[64];
1836
1837         int align = 0;
1838
1839         cave_type *c_ptr;
1840
1841         int cur_nest_type = pick_vault_type(nest_types, d_info[dungeon_type].nest);
1842         vault_aux_type *n_ptr;
1843
1844         /* Try to allocate space for room. */
1845         if (!room_alloc(25, 11, TRUE, by0, bx0, &xval, &yval)) return;
1846
1847         /* No type available */
1848         if (cur_nest_type < 0)
1849         {
1850                 if (pit) return;
1851                 else
1852                 {
1853                         build_type6(by0, bx0, TRUE);
1854                         return;
1855                 }
1856         }
1857
1858         n_ptr = &nest_types[cur_nest_type];
1859
1860         /* Process a preparation function if necessary */
1861         if (n_ptr->prep_func) (*(n_ptr->prep_func))();
1862
1863         /* Large room */
1864         y1 = yval - 4;
1865         y2 = yval + 4;
1866         x1 = xval - 11;
1867         x2 = xval + 11;
1868
1869         /* Place the floor area */
1870         for (y = y1 - 1; y <= y2 + 1; y++)
1871         {
1872                 for (x = x1 - 1; x <= x2 + 1; x++)
1873                 {
1874                         c_ptr = &cave[y][x];
1875                         place_floor_grid(c_ptr);
1876                         c_ptr->info |= (CAVE_ROOM);
1877                 }
1878         }
1879
1880         /* Place the outer walls */
1881         for (y = y1 - 1; y <= y2 + 1; y++)
1882         {
1883                 c_ptr = &cave[y][x1 - 1];
1884                 place_outer_grid(c_ptr);
1885                 c_ptr = &cave[y][x2 + 1];
1886                 place_outer_grid(c_ptr);
1887         }
1888         for (x = x1 - 1; x <= x2 + 1; x++)
1889         {
1890                 c_ptr = &cave[y1 - 1][x];
1891                 place_outer_grid(c_ptr);
1892                 c_ptr = &cave[y2 + 1][x];
1893                 place_outer_grid(c_ptr);
1894         }
1895
1896
1897         /* Advance to the center room */
1898         y1 = y1 + 2;
1899         y2 = y2 - 2;
1900         x1 = x1 + 2;
1901         x2 = x2 - 2;
1902
1903         /* The inner walls */
1904         for (y = y1 - 1; y <= y2 + 1; y++)
1905         {
1906                 c_ptr = &cave[y][x1 - 1];
1907                 place_inner_grid(c_ptr);
1908                 c_ptr = &cave[y][x2 + 1];
1909                 place_inner_grid(c_ptr);
1910         }
1911
1912         for (x = x1 - 1; x <= x2 + 1; x++)
1913         {
1914                 c_ptr = &cave[y1 - 1][x];
1915                 place_inner_grid(c_ptr);
1916                 c_ptr = &cave[y2 + 1][x];
1917                 place_inner_grid(c_ptr);
1918         }
1919         for (y = y1; y <= y2; y++)
1920         {
1921                 for (x = x1; x <= x2; x++)
1922                 {
1923                         add_cave_info(y, x, CAVE_ICKY);
1924                 }
1925         }
1926
1927
1928         /* Place a secret door */
1929         switch (randint1(4))
1930         {
1931                 case 1: place_secret_door(y1 - 1, xval); break;
1932                 case 2: place_secret_door(y2 + 1, xval); break;
1933                 case 3: place_secret_door(yval, x1 - 1); break;
1934                 case 4: place_secret_door(yval, x2 + 1); break;
1935         }
1936
1937
1938         /* Prepare allocation table */
1939         get_mon_num_prep(n_ptr->hook_func, NULL);
1940
1941         /* Pick some monster types */
1942         for (i = 0; i < 64; i++)
1943         {
1944                 int r_idx = 0, attempts = 100;
1945
1946                 while (attempts--)
1947                 {
1948                         /* Get a (hard) monster type */
1949                         r_idx = get_mon_num(dun_level + 10);
1950
1951                         /* Decline incorrect alignment */
1952                         if (((align < 0) && (r_info[r_idx].flags3 & RF3_GOOD)) ||
1953                                  ((align > 0) && (r_info[r_idx].flags3 & RF3_EVIL)))
1954                         {
1955                                 continue;
1956                         }
1957
1958                         /* Accept this monster */
1959                         break;
1960                 }
1961
1962                 /* Notice failure */
1963                 if (!r_idx || !attempts) return;
1964
1965                 /* Note the alignment */
1966                 if (r_info[r_idx].flags3 & RF3_GOOD) align++;
1967                 else if (r_info[r_idx].flags3 & RF3_EVIL) align--;
1968
1969                 what[i] = r_idx;
1970         }
1971
1972         /* Describe */
1973         if (cheat_room)
1974         {
1975                 /* Room type */
1976 #ifdef JP
1977                 msg_format("¥â¥ó¥¹¥¿¡¼Éô²°(nest)(%s%s)", n_ptr->name, pit_subtype_string(cur_nest_type, TRUE));
1978 #else
1979                 msg_format("Monster nest (%s%s)", n_ptr->name, pit_subtype_string(cur_nest_type, TRUE));
1980 #endif
1981         }
1982
1983         /* Increase the level rating */
1984         rating += 10;
1985
1986         /* (Sometimes) Cause a "special feeling" (for "Monster Nests") */
1987         if ((dun_level <= 40) && (randint1(dun_level * dun_level + 50) < 300))
1988         {
1989                 good_item_flag = TRUE;
1990         }
1991
1992         /* Place some monsters */
1993         for (y = yval - 2; y <= yval + 2; y++)
1994         {
1995                 for (x = xval - 9; x <= xval + 9; x++)
1996                 {
1997                         int r_idx = what[randint0(64)];
1998
1999                         /* Place that "random" monster (no groups) */
2000                         (void)place_monster_aux(0, y, x, r_idx, 0L);
2001                 }
2002         }
2003 }
2004
2005
2006 /*
2007  * Type 6 -- Monster pits
2008  *
2009  * A monster pit is a "big" room, with an "inner" room, containing
2010  * a "collection" of monsters of a given type organized in the room.
2011  *
2012  * The inside room in a monster pit appears as shown below, where the
2013  * actual monsters in each location depend on the type of the pit
2014  *
2015  *   #####################
2016  *   #0000000000000000000#
2017  *   #0112233455543322110#
2018  *   #0112233467643322110#
2019  *   #0112233455543322110#
2020  *   #0000000000000000000#
2021  *   #####################
2022  *
2023  * Note that the monsters in the pit are now chosen by using "get_mon_num()"
2024  * to request 16 "appropriate" monsters, sorting them by level, and using
2025  * the "even" entries in this sorted list for the contents of the pit.
2026  *
2027  * Hack -- all of the "dragons" in a "dragon" pit must be the same "color",
2028  * which is handled by requiring a specific "breath" attack for all of the
2029  * dragons.  This may include "multi-hued" breath.  Note that "wyrms" may
2030  * be present in many of the dragon pits, if they have the proper breath.
2031  *
2032  * Note the use of the "get_mon_num_prep()" function, and the special
2033  * "get_mon_num_hook()" restriction function, to prepare the "monster
2034  * allocation table" in such a way as to optimize the selection of
2035  * "appropriate" non-unique monsters for the pit.
2036  *
2037  * Note that the "get_mon_num()" function may (rarely) fail, in which case
2038  * the pit will be empty, and will not effect the level rating.
2039  *
2040  * Note that "monster pits" will never contain "unique" monsters.
2041  */
2042 static void build_type6(int by0, int bx0, bool nest)
2043 {
2044         int y, x, y1, x1, y2, x2, xval, yval;
2045         int i, j;
2046
2047         int what[16];
2048
2049         int align = 0;
2050
2051         cave_type *c_ptr;
2052
2053         int cur_pit_type = pick_vault_type(pit_types, d_info[dungeon_type].pit);
2054         vault_aux_type *n_ptr;
2055
2056         /* Try to allocate space for room. */
2057         if (!room_alloc(25, 11, TRUE, by0, bx0, &xval, &yval)) return;
2058
2059         /* No type available */
2060         if (cur_pit_type < 0)
2061         {
2062                 if (nest) return;
2063                 else
2064                 {
2065                         build_type5(by0, bx0, TRUE);
2066                         return;
2067                 }
2068         }
2069
2070         n_ptr = &pit_types[cur_pit_type];
2071
2072         /* Process a preparation function if necessary */
2073         if (n_ptr->prep_func) (*(n_ptr->prep_func))();
2074
2075         /* Large room */
2076         y1 = yval - 4;
2077         y2 = yval + 4;
2078         x1 = xval - 11;
2079         x2 = xval + 11;
2080
2081         /* Place the floor area */
2082         for (y = y1 - 1; y <= y2 + 1; y++)
2083         {
2084                 for (x = x1 - 1; x <= x2 + 1; x++)
2085                 {
2086                         c_ptr = &cave[y][x];
2087                         place_floor_grid(c_ptr);
2088                         c_ptr->info |= (CAVE_ROOM);
2089                 }
2090         }
2091
2092         /* Place the outer walls */
2093         for (y = y1 - 1; y <= y2 + 1; y++)
2094         {
2095                 c_ptr = &cave[y][x1 - 1];
2096                 place_outer_grid(c_ptr);
2097                 c_ptr = &cave[y][x2 + 1];
2098                 place_outer_grid(c_ptr);
2099         }
2100         for (x = x1 - 1; x <= x2 + 1; x++)
2101         {
2102                 c_ptr = &cave[y1 - 1][x];
2103                 place_outer_grid(c_ptr);
2104                 c_ptr = &cave[y2 + 1][x];
2105                 place_outer_grid(c_ptr);
2106         }
2107
2108         /* Advance to the center room */
2109         y1 = y1 + 2;
2110         y2 = y2 - 2;
2111         x1 = x1 + 2;
2112         x2 = x2 - 2;
2113
2114         /* The inner walls */
2115         for (y = y1 - 1; y <= y2 + 1; y++)
2116         {
2117                 c_ptr = &cave[y][x1 - 1];
2118                 place_inner_grid(c_ptr);
2119                 c_ptr = &cave[y][x2 + 1];
2120                 place_inner_grid(c_ptr);
2121         }
2122         for (x = x1 - 1; x <= x2 + 1; x++)
2123         {
2124                 c_ptr = &cave[y1 - 1][x];
2125                 place_inner_grid(c_ptr);
2126                 c_ptr = &cave[y2 + 1][x];
2127                 place_inner_grid(c_ptr);
2128         }
2129         for (y = y1; y <= y2; y++)
2130         {
2131                 for (x = x1; x <= x2; x++)
2132                 {
2133                         add_cave_info(y, x, CAVE_ICKY);
2134                 }
2135         }
2136
2137         /* Place a secret door */
2138         switch (randint1(4))
2139         {
2140                 case 1: place_secret_door(y1 - 1, xval); break;
2141                 case 2: place_secret_door(y2 + 1, xval); break;
2142                 case 3: place_secret_door(yval, x1 - 1); break;
2143                 case 4: place_secret_door(yval, x2 + 1); break;
2144         }
2145
2146
2147         /* Prepare allocation table */
2148         get_mon_num_prep(n_ptr->hook_func, NULL);
2149
2150         /* Pick some monster types */
2151         for (i = 0; i < 16; i++)
2152         {
2153                 int r_idx = 0, attempts = 100;
2154
2155                 while (attempts--)
2156                 {
2157                         /* Get a (hard) monster type */
2158                         r_idx = get_mon_num(dun_level + 10);
2159
2160                         /* Decline incorrect alignment */
2161                         if (((align < 0) && (r_info[r_idx].flags3 & RF3_GOOD)) ||
2162                                  ((align > 0) && (r_info[r_idx].flags3 & RF3_EVIL)))
2163                         {
2164                                 continue;
2165                         }
2166
2167                         /* Accept this monster */
2168                         break;
2169                 }
2170
2171                 /* Notice failure */
2172                 if (!r_idx || !attempts) return;
2173
2174                 /* Note the alignment */
2175                 if (r_info[r_idx].flags3 & RF3_GOOD) align++;
2176                 else if (r_info[r_idx].flags3 & RF3_EVIL) align--;
2177
2178                 what[i] = r_idx;
2179         }
2180
2181         /* Sort the entries */
2182         for (i = 0; i < 16 - 1; i++)
2183         {
2184                 /* Sort the entries */
2185                 for (j = 0; j < 16 - 1; j++)
2186                 {
2187                         int i1 = j;
2188                         int i2 = j + 1;
2189
2190                         int p1 = r_info[what[i1]].level;
2191                         int p2 = r_info[what[i2]].level;
2192
2193                         /* Bubble */
2194                         if (p1 > p2)
2195                         {
2196                                 int tmp = what[i1];
2197                                 what[i1] = what[i2];
2198                                 what[i2] = tmp;
2199                         }
2200                 }
2201         }
2202
2203         /* Message */
2204         if (cheat_room)
2205         {
2206                 /* Room type */
2207 #ifdef JP
2208                 msg_format("¥â¥ó¥¹¥¿¡¼Éô²°(pit)(%s%s)", n_ptr->name, pit_subtype_string(cur_pit_type, FALSE));
2209 #else
2210                 msg_format("Monster pit (%s%s)", n_ptr->name, pit_subtype_string(cur_pit_type, FALSE));
2211 #endif
2212         }
2213
2214         /* Select the entries */
2215         for (i = 0; i < 8; i++)
2216         {
2217                 /* Every other entry */
2218                 what[i] = what[i * 2];
2219
2220                 if (cheat_hear)
2221                 {
2222                         /* Message */
2223                         msg_print(r_name + r_info[what[i]].name);
2224                 }
2225         }
2226
2227         /* Increase the level rating */
2228         rating += 10;
2229
2230         /* (Sometimes) Cause a "special feeling" (for "Monster Pits") */
2231         if ((dun_level <= 40) && (randint1(dun_level * dun_level + 50) < 300))
2232         {
2233                 good_item_flag = TRUE;
2234         }
2235
2236         /* Top and bottom rows */
2237         for (x = xval - 9; x <= xval + 9; x++)
2238         {
2239                 place_monster_aux(0, yval - 2, x, what[0], PM_NO_KAGE);
2240                 place_monster_aux(0, yval + 2, x, what[0], PM_NO_KAGE);
2241         }
2242
2243         /* Middle columns */
2244         for (y = yval - 1; y <= yval + 1; y++)
2245         {
2246                 place_monster_aux(0, y, xval - 9, what[0], PM_NO_KAGE);
2247                 place_monster_aux(0, y, xval + 9, what[0], PM_NO_KAGE);
2248
2249                 place_monster_aux(0, y, xval - 8, what[1], PM_NO_KAGE);
2250                 place_monster_aux(0, y, xval + 8, what[1], PM_NO_KAGE);
2251
2252                 place_monster_aux(0, y, xval - 7, what[1], PM_NO_KAGE);
2253                 place_monster_aux(0, y, xval + 7, what[1], PM_NO_KAGE);
2254
2255                 place_monster_aux(0, y, xval - 6, what[2], PM_NO_KAGE);
2256                 place_monster_aux(0, y, xval + 6, what[2], PM_NO_KAGE);
2257
2258                 place_monster_aux(0, y, xval - 5, what[2], PM_NO_KAGE);
2259                 place_monster_aux(0, y, xval + 5, what[2], PM_NO_KAGE);
2260
2261                 place_monster_aux(0, y, xval - 4, what[3], PM_NO_KAGE);
2262                 place_monster_aux(0, y, xval + 4, what[3], PM_NO_KAGE);
2263
2264                 place_monster_aux(0, y, xval - 3, what[3], PM_NO_KAGE);
2265                 place_monster_aux(0, y, xval + 3, what[3], PM_NO_KAGE);
2266
2267                 place_monster_aux(0, y, xval - 2, what[4], PM_NO_KAGE);
2268                 place_monster_aux(0, y, xval + 2, what[4], PM_NO_KAGE);
2269         }
2270
2271         /* Above/Below the center monster */
2272         for (x = xval - 1; x <= xval + 1; x++)
2273         {
2274                 place_monster_aux(0, yval + 1, x, what[5], PM_NO_KAGE);
2275                 place_monster_aux(0, yval - 1, x, what[5], PM_NO_KAGE);
2276         }
2277
2278         /* Next to the center monster */
2279         place_monster_aux(0, yval, xval + 1, what[6], PM_NO_KAGE);
2280         place_monster_aux(0, yval, xval - 1, what[6], PM_NO_KAGE);
2281
2282         /* Center monster */
2283         place_monster_aux(0, yval, xval, what[7], PM_NO_KAGE);
2284 }
2285
2286
2287 /* coordinate translation code */
2288 static void coord_trans(int *x, int *y, int xoffset, int yoffset, int transno)
2289 {
2290         int i;
2291         int temp;
2292
2293         /*
2294          * transno specifies what transformation is required. (0-7)
2295          * The lower two bits indicate by how much the vault is rotated,
2296          * and the upper bit indicates a reflection.
2297          * This is done by using rotation matrices... however since
2298          * these are mostly zeros for rotations by 90 degrees this can
2299          * be expressed simply in terms of swapping and inverting the
2300          * x and y coordinates.
2301          */
2302         for (i = 0; i <= transno % 4; i++)
2303         {
2304                 /* rotate by 90 degrees */
2305                 temp = *x;
2306                 *x = -(*y);
2307                 *y = temp;
2308         }
2309
2310         if (transno / 4)
2311         {
2312                 /* Reflect depending on status of 3rd bit. */
2313                 *x = -(*x);
2314         }
2315
2316         /* Add offsets so vault stays in the first quadrant */
2317         *x += xoffset;
2318         *y += yoffset;
2319 }
2320
2321
2322 /*
2323  * Hack -- fill in "vault" rooms
2324  */
2325 static void build_vault(int yval, int xval, int ymax, int xmax, cptr data,
2326                 int xoffset, int yoffset, int transno)
2327 {
2328         int dx, dy, x, y, i, j;
2329
2330         cptr t;
2331
2332         cave_type *c_ptr;
2333
2334
2335         /* Place dungeon features and objects */
2336         for (t = data, dy = 0; dy < ymax; dy++)
2337         {
2338                 for (dx = 0; dx < xmax; dx++, t++)
2339                 {
2340                         /* prevent loop counter from being overwritten */
2341                         i = dx;
2342                         j = dy;
2343
2344                         /* Flip / rotate */
2345                         coord_trans(&i, &j, xoffset, yoffset, transno);
2346
2347                         /* Extract the location */
2348                         if (transno%2)
2349                         {
2350                                 /* no swap of x/y */
2351                                 x = xval - (xmax / 2) + i;
2352                                 y = yval - (ymax / 2) + j;
2353                         }
2354                         else
2355                         {
2356                                 /* swap of x/y */
2357                                 x = xval - (ymax / 2) + i;
2358                                 y = yval - (xmax / 2) + j;
2359                         }
2360
2361                         /* Hack -- skip "non-grids" */
2362                         if (*t == ' ') continue;
2363
2364                         /* Access the grid */
2365                         c_ptr = &cave[y][x];
2366
2367                         /* Lay down a floor */
2368                         place_floor_grid(c_ptr);
2369
2370                         /* Remove any mimic */
2371                         c_ptr->mimic = 0;
2372
2373                         /* Part of a vault */
2374                         c_ptr->info |= (CAVE_ROOM | CAVE_ICKY);
2375
2376                         /* Analyze the grid */
2377                         switch (*t)
2378                         {
2379                                 /* Granite wall (outer) */
2380                         case '%':
2381                                 place_outer_noperm_grid(c_ptr);
2382                                 break;
2383
2384                                 /* Granite wall (inner) */
2385                         case '#':
2386                                 place_inner_grid(c_ptr);
2387                                 break;
2388
2389                                 /* Permanent wall (inner) */
2390                         case 'X':
2391                                 c_ptr->feat = FEAT_PERM_INNER;
2392                                 c_ptr->info &= ~(CAVE_MASK);
2393                                 c_ptr->info |= CAVE_INNER;
2394                                 break;
2395
2396                                 /* Treasure/trap */
2397                         case '*':
2398                                 if (randint0(100) < 75)
2399                                 {
2400                                         place_object(y, x, FALSE, FALSE);
2401                                 }
2402                                 else
2403                                 {
2404                                         place_trap(y, x);
2405                                 }
2406                                 break;
2407
2408                                 /* Secret doors */
2409                         case '+':
2410                                 place_secret_door(y, x);
2411                                 break;
2412
2413                                 /* Trap */
2414                         case '^':
2415                                 place_trap(y, x);
2416                                 break;
2417
2418                                 /* Black market in a dungeon */
2419                         case 'S':
2420                                 set_cave_feat(y, x, FEAT_SHOP_HEAD + STORE_BLACK);
2421                                 store_init(NO_TOWN, STORE_BLACK);
2422                                 break;
2423                                 
2424                                 /* The Pattern */
2425                         case 'p':
2426                                 set_cave_feat(y, x, FEAT_PATTERN_START);
2427                                 break;
2428                                 
2429                         case 'a':
2430                                 set_cave_feat(y, x, FEAT_PATTERN_1);
2431                                 break;
2432                                 
2433                         case 'b':
2434                                 set_cave_feat(y, x, FEAT_PATTERN_2);
2435                                 break;
2436                                 
2437                         case 'c':
2438                                 set_cave_feat(y, x, FEAT_PATTERN_3);
2439                                 break;
2440                                 
2441                         case 'd':
2442                                 set_cave_feat(y, x, FEAT_PATTERN_4);
2443                                 break;
2444                                 
2445                         case 'P':
2446                                 set_cave_feat(y, x, FEAT_PATTERN_END);
2447                                 break;
2448                                 
2449                         case 'B':
2450                                 set_cave_feat(y, x, FEAT_PATTERN_XTRA1);
2451                                 break;
2452
2453                         case 'A':
2454                                 /* Reward for Pattern walk */
2455                                 object_level = base_level + 12;
2456                                 place_object(y, x, TRUE, FALSE);
2457                                 object_level = base_level;
2458                                 break;
2459                         }
2460                 }
2461         }
2462
2463
2464         /* Place dungeon monsters and objects */
2465         for (t = data, dy = 0; dy < ymax; dy++)
2466         {
2467                 for (dx = 0; dx < xmax; dx++, t++)
2468                 {
2469                         /* prevent loop counter from being overwritten */
2470                         i = dx;
2471                         j = dy;
2472
2473                         /* Flip / rotate */
2474                         coord_trans(&i, &j, xoffset, yoffset, transno);
2475
2476                         /* Extract the location */
2477                         if (transno % 2)
2478                         {
2479                                 /* no swap of x/y */
2480                                 x = xval - (xmax / 2) + i;
2481                                 y = yval - (ymax / 2) + j;
2482                         }
2483                         else
2484                         {
2485                                 /* swap of x/y */
2486                                 x = xval - (ymax / 2) + i;
2487                                 y = yval - (xmax / 2) + j;
2488                         }
2489
2490                         /* Hack -- skip "non-grids" */
2491                         if (*t == ' ') continue;
2492
2493                         /* Analyze the symbol */
2494                         switch (*t)
2495                         {
2496                                 /* Monster */
2497                                 case '&':
2498                                 {
2499                                         monster_level = base_level + 5;
2500                                         place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
2501                                         monster_level = base_level;
2502                                         break;
2503                                 }
2504
2505                                 /* Meaner monster */
2506                                 case '@':
2507                                 {
2508                                         monster_level = base_level + 11;
2509                                         place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
2510                                         monster_level = base_level;
2511                                         break;
2512                                 }
2513
2514                                 /* Meaner monster, plus treasure */
2515                                 case '9':
2516                                 {
2517                                         monster_level = base_level + 9;
2518                                         place_monster(y, x, PM_ALLOW_SLEEP);
2519                                         monster_level = base_level;
2520                                         object_level = base_level + 7;
2521                                         place_object(y, x, TRUE, FALSE);
2522                                         object_level = base_level;
2523                                         break;
2524                                 }
2525
2526                                 /* Nasty monster and treasure */
2527                                 case '8':
2528                                 {
2529                                         monster_level = base_level + 40;
2530                                         place_monster(y, x, PM_ALLOW_SLEEP);
2531                                         monster_level = base_level;
2532                                         object_level = base_level + 20;
2533                                         place_object(y, x, TRUE, TRUE);
2534                                         object_level = base_level;
2535                                         break;
2536                                 }
2537
2538                                 /* Monster and/or object */
2539                                 case ',':
2540                                 {
2541                                         if (randint0(100) < 50)
2542                                         {
2543                                                 monster_level = base_level + 3;
2544                                                 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
2545                                                 monster_level = base_level;
2546                                         }
2547                                         if (randint0(100) < 50)
2548                                         {
2549                                                 object_level = base_level + 7;
2550                                                 place_object(y, x, FALSE, FALSE);
2551                                                 object_level = base_level;
2552                                         }
2553                                         break;
2554                                 }
2555
2556                         }
2557                 }
2558         }
2559 }
2560
2561
2562 /*
2563  * Type 7 -- simple vaults (see "v_info.txt")
2564  */
2565 static void build_type7(int by0, int bx0)
2566 {
2567         vault_type *v_ptr = NULL;
2568         int dummy = 0;
2569         int x, y;
2570         int xval, yval;
2571         int xoffset, yoffset;
2572         int transno;
2573
2574         /* Pick a lesser vault */
2575         while (dummy < SAFE_MAX_ATTEMPTS)
2576         {
2577                 dummy++;
2578
2579                 /* Access a random vault record */
2580                 v_ptr = &v_info[randint0(max_v_idx)];
2581
2582                 /* Accept the first lesser vault */
2583                 if (v_ptr->typ == 7) break;
2584         }
2585
2586         /* No lesser vault found */
2587         if (!v_ptr) return;
2588
2589         /* pick type of transformation (0-7) */
2590         transno = randint0(8);
2591
2592         /* calculate offsets */
2593         x = v_ptr->wid;
2594         y = v_ptr->hgt;
2595
2596         coord_trans(&x, &y, 0, 0, transno);
2597
2598         if (x < 0)
2599         {
2600                 xoffset = -x - 1;
2601         }
2602         else
2603         {
2604                 xoffset = 0;
2605         }
2606
2607         if (y < 0)
2608         {
2609                 yoffset = -y - 1;
2610         }
2611         else
2612         {
2613                 yoffset = 0;
2614         }
2615
2616         /* Try to allocate space for room. */
2617         if (!room_alloc(abs(x), abs(y), FALSE, by0, bx0, &xval, &yval)) return;
2618
2619         if (dummy >= SAFE_MAX_ATTEMPTS)
2620         {
2621                 if (cheat_room)
2622                 {
2623 #ifdef JP
2624 msg_print("·Ù¹ð¡ª¾®¤µ¤ÊÃϲ¼¼¼¤òÇÛÃ֤Ǥ­¤Þ¤»¤ó¡ª");
2625 #else
2626                         msg_print("Warning! Could not place lesser vault!");
2627 #endif
2628
2629                 }
2630                 return;
2631         }
2632
2633
2634 #ifdef FORCE_V_IDX
2635         v_ptr = &v_info[2];
2636 #endif
2637
2638         /* Message */
2639         if (cheat_room) msg_format("%s", v_name + v_ptr->name);
2640
2641         /* Boost the rating */
2642         rating += v_ptr->rat;
2643
2644         /* (Sometimes) Cause a special feeling */
2645         if ((dun_level <= 50) ||
2646                 (randint1((dun_level - 40) * (dun_level - 40) + 50) < 400))
2647         {
2648                 good_item_flag = TRUE;
2649         }
2650
2651         /* Hack -- Build the vault */
2652         build_vault(yval, xval, v_ptr->hgt, v_ptr->wid,
2653                     v_text + v_ptr->text, xoffset, yoffset, transno);
2654 }
2655
2656
2657 /*
2658  * Type 8 -- greater vaults (see "v_info.txt")
2659  */
2660 static void build_type8(int by0, int bx0)
2661 {
2662         vault_type *v_ptr = NULL;
2663         int dummy = 0;
2664         int xval, yval;
2665         int x, y;
2666         int transno;
2667         int xoffset, yoffset;
2668
2669         /* Pick a greater vault */
2670         while (dummy < SAFE_MAX_ATTEMPTS)
2671         {
2672                 dummy++;
2673
2674                 /* Access a random vault record */
2675                 v_ptr = &v_info[randint0(max_v_idx)];
2676
2677                 /* Accept the first greater vault */
2678                 if (v_ptr->typ == 8) break;
2679         }
2680
2681         /* No greater vault found */
2682         if (!v_ptr) return;
2683
2684         /* pick type of transformation (0-7) */
2685         transno = randint0(8);
2686
2687         /* calculate offsets */
2688         x = v_ptr->wid;
2689         y = v_ptr->hgt;
2690
2691         coord_trans(&x, &y, 0, 0, transno);
2692
2693         if (x < 0)
2694         {
2695                 xoffset = - x - 1;
2696         }
2697         else
2698         {
2699                 xoffset = 0;
2700         }
2701
2702         if (y < 0)
2703         {
2704                 yoffset = - y - 1;
2705         }
2706         else
2707         {
2708                 yoffset = 0;
2709         }
2710
2711         /*
2712          * Try to allocate space for room.  If fails, exit
2713          *
2714          * Hack -- Prepare a bit larger space (+2, +2) to 
2715          * prevent generation of vaults with no-entrance.
2716          */
2717         if (!room_alloc(abs(x) + 2, abs(y) + 2, FALSE, by0, bx0, &xval, &yval)) return;
2718
2719         if (dummy >= SAFE_MAX_ATTEMPTS)
2720         {
2721                 if (cheat_room)
2722                 {
2723 #ifdef JP
2724 msg_print("·Ù¹ð¡ªµðÂç¤ÊÃϲ¼¼¼¤òÇÛÃ֤Ǥ­¤Þ¤»¤ó¡ª");
2725 #else
2726                         msg_print("Warning! Could not place greater vault!");
2727 #endif
2728
2729                 }
2730                 return;
2731         }
2732
2733
2734 #ifdef FORCE_V_IDX
2735         v_ptr = &v_info[76 + randint1(3)];
2736 #endif
2737
2738         /* Message */
2739         if (cheat_room) msg_format("%s", v_name + v_ptr->name);
2740
2741         /* Boost the rating */
2742         rating += v_ptr->rat;
2743
2744         /* (Sometimes) Cause a special feeling */
2745         if ((dun_level <= 50) ||
2746             (randint1((dun_level - 40) * (dun_level - 40) + 50) < 400))
2747         {
2748                 good_item_flag = TRUE;
2749         }
2750
2751         /* Hack -- Build the vault */
2752         build_vault(yval, xval, v_ptr->hgt, v_ptr->wid,
2753                     v_text + v_ptr->text, xoffset, yoffset, transno);
2754 }
2755
2756 /*
2757  * Structure to hold all "fill" data
2758  */
2759
2760 typedef struct fill_data_type fill_data_type;
2761
2762 struct fill_data_type
2763 {
2764         /* area size */
2765         int xmin;
2766         int ymin;
2767         int xmax;
2768         int ymax;
2769
2770         /* cutoffs */
2771         int c1;
2772         int c2;
2773         int c3;
2774
2775         /* features to fill with */
2776         int feat1;
2777         int feat2;
2778         int feat3;
2779
2780         int info1;
2781         int info2;
2782         int info3;
2783
2784         /* number of filled squares */
2785         int amount;
2786 };
2787
2788 static fill_data_type fill_data;
2789
2790
2791 /* Store routine for the fractal cave generator */
2792 /* this routine probably should be an inline function or a macro. */
2793 static void store_height(int x, int y, int val)
2794 {
2795         /* if on boundary set val > cutoff so walls are not as square */
2796         if (((x == fill_data.xmin) || (y == fill_data.ymin) ||
2797              (x == fill_data.xmax) || (y == fill_data.ymax)) &&
2798             (val <= fill_data.c1)) val = fill_data.c1 + 1;
2799
2800         /* store the value in height-map format */
2801         cave[y][x].feat = val;
2802
2803         return;
2804 }
2805
2806
2807 /*
2808 * Explanation of the plasma fractal algorithm:
2809 *
2810 * A grid of points is created with the properties of a 'height-map'
2811 * This is done by making the corners of the grid have a random value.
2812 * The grid is then subdivided into one with twice the resolution.
2813 * The new points midway between two 'known' points can be calculated
2814 * by taking the average value of the 'known' ones and randomly adding
2815 * or subtracting an amount proportional to the distance between those
2816 * points.  The final 'middle' points of the grid are then calculated
2817 * by averaging all four of the originally 'known' corner points.  An
2818 * random amount is added or subtracted from this to get a value of the
2819 * height at that point.  The scaling factor here is adjusted to the
2820 * slightly larger distance diagonally as compared to orthogonally.
2821 *
2822 * This is then repeated recursively to fill an entire 'height-map'
2823 * A rectangular map is done the same way, except there are different
2824 * scaling factors along the x and y directions.
2825 *
2826 * A hack to change the amount of correlation between points is done using
2827 * the grd variable.  If the current step size is greater than grd then
2828 * the point will be random, otherwise it will be calculated by the
2829 * above algorithm.  This makes a maximum distance at which two points on
2830 * the height map can affect each other.
2831 *
2832 * How fractal caves are made:
2833 *
2834 * When the map is complete, a cut-off value is used to create a cave.
2835 * Heights below this value are "floor", and heights above are "wall".
2836 * This also can be used to create lakes, by adding more height levels
2837 * representing shallow and deep water/ lava etc.
2838 *
2839 * The grd variable affects the width of passages.
2840 * The roug variable affects the roughness of those passages
2841 *
2842 * The tricky part is making sure the created cave is connected.  This
2843 * is done by 'filling' from the inside and only keeping the 'filled'
2844 * floor.  Walls bounding the 'filled' floor are also kept.  Everything
2845 * else is converted to the normal granite FEAT_WALL_EXTRA.
2846  */
2847
2848
2849 /*
2850  *  Note that this uses the cave.feat array in a very hackish way
2851  *  the values are first set to zero, and then each array location
2852  *  is used as a "heightmap"
2853  *  The heightmap then needs to be converted back into the "feat" format.
2854  *
2855  *  grd=level at which fractal turns on.  smaller gives more mazelike caves
2856  *  roug=roughness level.  16=normal.  higher values make things more convoluted
2857  *    small values are good for smooth walls.
2858  *  size=length of the side of the square cave system.
2859  */
2860 static void generate_hmap(int y0, int x0, int xsiz, int ysiz, int grd, int roug, int cutoff)
2861 {
2862         int xhsize, yhsize, xsize, ysize, maxsize;
2863
2864         /*
2865          * fixed point variables- these are stored as 256 x normal value
2866          * this gives 8 binary places of fractional part + 8 places of normal part
2867          */
2868
2869         u16b xstep, xhstep, ystep, yhstep;
2870         u16b xstep2, xhstep2, ystep2, yhstep2;
2871         u16b i, j, ii, jj, diagsize, xxsize, yysize;
2872         
2873         /* Cache for speed */
2874         u16b xm, xp, ym, yp;
2875
2876         /* redefine size so can change the value if out of range */
2877         xsize = xsiz;
2878         ysize = ysiz;
2879
2880         /* Paranoia about size of the system of caves */
2881         if (xsize > 254) xsize = 254;
2882         if (xsize < 4) xsize = 4;
2883         if (ysize > 254) ysize = 254;
2884         if (ysize < 4) ysize = 4;
2885
2886         /* get offsets to middle of array */
2887         xhsize = xsize / 2;
2888         yhsize = ysize / 2;
2889
2890         /* fix rounding problem */
2891         xsize = xhsize * 2;
2892         ysize = yhsize * 2;
2893
2894         /* get limits of region */
2895         fill_data.xmin = x0 - xhsize;
2896         fill_data.ymin = y0 - yhsize;
2897         fill_data.xmax = x0 + xhsize;
2898         fill_data.ymax = y0 + yhsize;
2899         
2900         /* Store cutoff in global for quick access */
2901         fill_data.c1 = cutoff;
2902         
2903         /*
2904         * Scale factor for middle points:
2905         * About sqrt(2) * 256 - correct for a square lattice
2906         * approximately correct for everything else.
2907          */
2908         diagsize = 362;
2909
2910         /* maximum of xsize and ysize */
2911         maxsize = (xsize > ysize) ? xsize : ysize;
2912
2913         /* Clear the section */
2914         for (i = 0; i <= xsize; i++)
2915         {
2916                 for (j = 0; j <= ysize; j++)
2917                 {
2918                         /* 255 is a flag for "not done yet" */
2919                         cave[(int)(fill_data.ymin + j)][(int)(fill_data.xmin + i)].feat = 255;
2920                         /* Clear icky flag because may be redoing the cave */
2921                         cave[(int)(fill_data.ymin + j)][(int)(fill_data.xmin + i)].info &= ~(CAVE_ICKY);
2922                 }
2923         }
2924
2925         /* Boundaries are walls */
2926         cave[fill_data.ymin][fill_data.xmin].feat = maxsize;
2927         cave[fill_data.ymax][fill_data.xmin].feat = maxsize;
2928         cave[fill_data.ymin][fill_data.xmax].feat = maxsize;
2929         cave[fill_data.ymax][fill_data.xmax].feat = maxsize;
2930
2931         /* Set the middle square to be an open area. */
2932         cave[y0][x0].feat = 0;
2933
2934         /* Initialize the step sizes */
2935         xstep = xhstep = xsize * 256;
2936         ystep = yhstep = ysize * 256;
2937         xxsize = xsize * 256;
2938         yysize = ysize * 256;
2939
2940         /*
2941          * Fill in the rectangle with fractal height data -
2942          * like the 'plasma fractal' in fractint.
2943          */
2944         while ((xhstep > 256) || (yhstep > 256))
2945         {
2946                 /* Halve the step sizes */
2947                 xstep = xhstep;
2948                 xhstep /= 2;
2949                 ystep = yhstep;
2950                 yhstep /= 2;
2951                 
2952                 /* cache well used values */
2953                 xstep2 = xstep / 256;
2954                 ystep2 = ystep / 256;
2955                 
2956                 xhstep2 = xhstep / 256;
2957                 yhstep2 = yhstep / 256;
2958
2959                 /* middle top to bottom. */
2960                 for (i = xhstep; i <= xxsize - xhstep; i += xstep)
2961                 {
2962                         for (j = 0; j <= yysize; j += ystep)
2963                         {
2964                                 /* cache often used values */
2965                                 ii = i / 256 + fill_data.xmin;
2966                                 jj = j / 256 + fill_data.ymin;
2967                                 
2968                                 /* Test square */
2969                                 if (cave[jj][ii].feat == 255)
2970                                 {                               
2971                                         if (xhstep2 > grd)
2972                                         {
2973                                                 /* If greater than 'grid' level then is random */
2974                                                 store_height(ii, jj, randint1(maxsize));
2975                                         }
2976                                         else
2977                                         {
2978                                                 /* Average of left and right points +random bit */
2979                                                 store_height(ii, jj,
2980                                                         (cave[jj][fill_data.xmin + (i - xhstep) / 256].feat
2981                                                          + cave[jj][fill_data.xmin + (i + xhstep) / 256].feat) / 2
2982                                                          + (randint1(xstep2) - xhstep2) * roug / 16);
2983                                         }
2984                                 }
2985                         }
2986                 }
2987
2988
2989                 /* middle left to right. */
2990                 for (j = yhstep; j <= yysize - yhstep; j += ystep)
2991                 {
2992                         for (i = 0; i <= xxsize; i += xstep)
2993                         {
2994                                 /* cache often used values */
2995                                 ii = i / 256 + fill_data.xmin;
2996                                 jj = j / 256 + fill_data.ymin;
2997                                 
2998                                 /* Test square */
2999                                 if (cave[jj][ii].feat == 255)
3000                                 {
3001                                         if (xhstep2 > grd)
3002                                         {
3003                                                 /* If greater than 'grid' level then is random */
3004                                                 store_height(ii, jj, randint1(maxsize));
3005                                         }
3006                                         else
3007                                         {
3008                                                 /* Average of up and down points +random bit */
3009                                                 store_height(ii, jj,
3010                                                         (cave[fill_data.ymin + (j - yhstep) / 256][ii].feat
3011                                                         + cave[fill_data.ymin + (j + yhstep) / 256][ii].feat) / 2
3012                                                         + (randint1(ystep2) - yhstep2) * roug / 16);
3013                                         }
3014                                 }
3015                         }
3016                 }
3017
3018                 /* center. */
3019                 for (i = xhstep; i <= xxsize - xhstep; i += xstep)
3020                 {
3021                         for (j = yhstep; j <= yysize - yhstep; j += ystep)
3022                         {
3023                                 /* cache often used values */
3024                                 ii = i / 256 + fill_data.xmin;
3025                                 jj = j / 256 + fill_data.ymin;
3026                                 
3027                                 /* Test square */
3028                                 if (cave[jj][ii].feat == 255)
3029                                 {                               
3030                                         if (xhstep2 > grd)
3031                                         {
3032                                                 /* If greater than 'grid' level then is random */
3033                                                 store_height(ii, jj, randint1(maxsize));
3034                                         }
3035                                         else
3036                                         {
3037                                                 /* Cache reused values. */
3038                                                 xm = fill_data.xmin + (i - xhstep) / 256;
3039                                                 xp = fill_data.xmin + (i + xhstep) / 256;
3040                                                 ym = fill_data.ymin + (j - yhstep) / 256;
3041                                                 yp = fill_data.ymin + (j + yhstep) / 256;                                       
3042                                         
3043                                                 /* 
3044                                                  * Average over all four corners + scale by diagsize to
3045                                                  * reduce the effect of the square grid on the shape of the fractal
3046                                                  */                             
3047                                                 store_height(ii, jj,
3048                                                         (cave[ym][xm].feat + cave[yp][xm].feat
3049                                                         + cave[ym][xp].feat + cave[yp][xp].feat) / 4
3050                                                         + (randint1(xstep2) - xhstep2) * (diagsize / 16) / 256 * roug);
3051                                         }
3052                                 }
3053                         }
3054                 }
3055         }
3056 }
3057
3058
3059 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)
3060 {
3061         /*
3062          * function used to convert from height-map back to the
3063          *  normal angband cave format
3064          */
3065         if (cave[y][x].info & CAVE_ICKY)
3066         {
3067                 /* already done */
3068                 return FALSE;
3069         }
3070         else
3071         {
3072                 /* Show that have looked at this square */
3073                 cave[y][x].info|= (CAVE_ICKY);
3074
3075                 /* Use cutoffs c1-c3 to allocate regions of floor /water/ lava etc. */
3076                 if (cave[y][x].feat <= c1)
3077                 {
3078                         /* 25% of the time use the other tile : it looks better this way */
3079                         if (randint1(100) < 75)
3080                         {
3081                                 cave[y][x].feat = feat1;
3082                                 cave[y][x].info &= ~(CAVE_MASK);
3083                                 cave[y][x].info |= info1;
3084                                 return TRUE;
3085                         }
3086                         else
3087                         {
3088                                 cave[y][x].feat = feat2;
3089                                 cave[y][x].info &= ~(CAVE_MASK);
3090                                 cave[y][x].info |= info2;
3091                                 return TRUE;
3092                         }
3093                 }
3094                 else if (cave[y][x].feat <= c2)
3095                 {
3096                         /* 25% of the time use the other tile : it looks better this way */
3097                         if (randint1(100) < 75)
3098                         {
3099                                 cave[y][x].feat = feat2;
3100                                 cave[y][x].info &= ~(CAVE_MASK);
3101                                 cave[y][x].info |= info2;
3102                                 return TRUE;
3103                         }
3104                         else
3105                         {
3106                                 cave[y][x].feat = feat1;
3107                                 cave[y][x].info &= ~(CAVE_MASK);
3108                                 cave[y][x].info |= info1;
3109                                 return TRUE;
3110                         }
3111                 }
3112                 else if (cave[y][x].feat <= c3)
3113                 {
3114                         cave[y][x].feat = feat3;
3115                         cave[y][x].info |= info3;
3116                         return TRUE;
3117                 }
3118                 /* if greater than cutoff then is a wall */
3119                 else
3120                 {
3121                         place_outer_bold(y, x);
3122                         return FALSE;
3123                 }
3124         }
3125 }
3126
3127
3128
3129
3130 /*
3131  * Quick and nasty fill routine used to find the connected region
3132  * of floor in the middle of the cave
3133  */
3134 static void cave_fill(byte y, byte x)
3135 {
3136         int i, j, d;
3137         int ty, tx;
3138
3139         int flow_tail = 1;
3140         int flow_head = 0;
3141
3142
3143         /*** Start Grid ***/
3144
3145         /* Enqueue that entry */
3146         temp_y[0] = y;
3147         temp_x[0] = x;
3148
3149
3150         /* Now process the queue */
3151         while (flow_head != flow_tail)
3152         {
3153                 /* Extract the next entry */
3154                 ty = temp_y[flow_head];
3155                 tx = temp_x[flow_head];
3156
3157                 /* Forget that entry */
3158                 if (++flow_head == TEMP_MAX) flow_head = 0;
3159
3160                 /* Add the "children" */
3161                 for (d = 0; d < 8; d++)
3162                 {
3163                         int old_head = flow_tail;
3164
3165                         /* Child location */
3166                         j = ty + ddy_ddd[d];
3167                         i = tx + ddx_ddd[d];
3168
3169                         /* Paranoia Don't leave the cave */
3170                         if (!in_bounds(j, i))
3171                         {
3172                                 /* affect boundary */
3173                                 cave[j][i].info |= CAVE_ICKY;
3174 /*                              return; */
3175                         }
3176
3177                         /* If within bounds */
3178                         else if ((i > fill_data.xmin) && (i < fill_data.xmax)
3179                                 && (j > fill_data.ymin) && (j < fill_data.ymax))
3180                         {
3181                                 /* If not a wall or floor done before */
3182                                 if (hack_isnt_wall(j, i,
3183                                         fill_data.c1, fill_data.c2, fill_data.c3,
3184                                         fill_data.feat1, fill_data.feat2, fill_data.feat3,
3185                                         fill_data.info1, fill_data.info2, fill_data.info3))
3186                                 {
3187                                         /* Enqueue that entry */
3188                                         temp_y[flow_tail] = j;
3189                                         temp_x[flow_tail] = i;
3190
3191                                         /* Advance the queue */
3192                                         if (++flow_tail == TEMP_MAX) flow_tail = 0;
3193
3194                                         /* Hack -- Overflow by forgetting new entry */
3195                                         if (flow_tail == flow_head)
3196                                         {
3197                                                 flow_tail = old_head;
3198                                         }
3199                                         else
3200                                         {
3201                                                 /* keep tally of size of cave system */
3202                                                 (fill_data.amount)++;
3203                                         }
3204                                 }
3205                         }
3206                         else
3207                         {
3208                                 /* affect boundary */
3209                                 cave[j][i].info |= CAVE_ICKY;
3210                         }
3211                 }
3212         }
3213 }
3214
3215
3216 static bool generate_fracave(int y0, int x0, int xsize, int ysize, int cutoff, bool light, bool room)
3217 {
3218         int x, y, i, xhsize, yhsize;
3219         
3220
3221         /* offsets to middle from corner */
3222         xhsize = xsize / 2;
3223         yhsize = ysize / 2;
3224
3225
3226         /*
3227          * select region connected to center of cave system
3228          * this gets rid of alot of isolated one-sqaures that
3229          * can make teleport traps instadeaths...
3230          */
3231
3232         /* cutoffs */
3233         fill_data.c1 = cutoff;
3234         fill_data.c2 = 0;
3235         fill_data.c3 = 0;
3236
3237         /* features to fill with */
3238         fill_data.feat1 = floor_type[randint0(100)];
3239         fill_data.feat2 = floor_type[randint0(100)];
3240         fill_data.feat3 = floor_type[randint0(100)];
3241
3242         fill_data.info1 = CAVE_FLOOR;
3243         fill_data.info2 = CAVE_FLOOR;
3244         fill_data.info3 = CAVE_FLOOR;
3245
3246         /* number of filled squares */
3247         fill_data.amount = 0;
3248
3249         cave_fill((byte)y0, (byte)x0);
3250
3251         /* if tally too small, try again */
3252         if (fill_data.amount < 10)
3253         {
3254                 /* too small - clear area and try again later */
3255                 for (x = 0; x <= xsize; ++x)
3256                 {
3257                         for (y = 0; y <= ysize; ++y)
3258                         {
3259                                 place_extra_bold(y0 + y - yhsize, x0 + x - xhsize);
3260                                 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY | CAVE_ROOM);
3261                         }
3262                 }
3263                 return FALSE;
3264         }
3265
3266         /*
3267          * Do boundarys-check to see if they are next to a filled region
3268          * If not then they are set to normal granite
3269          * If so then they are marked as room walls.
3270          */
3271         for (i = 0; i <= xsize; ++i)
3272         {
3273                 /* top boundary */
3274                 if ((cave[0 + y0 - yhsize][i + x0 - xhsize].info & CAVE_ICKY) && (room))
3275                 {
3276                         /* Next to a 'filled' region? - set to be room walls */
3277                         place_outer_bold(y0 + 0 - yhsize, x0 + i - xhsize);
3278                         if (light) cave[y0 + 0 - yhsize][x0 + i - xhsize].info |= (CAVE_GLOW);
3279                         cave[y0 + 0 - yhsize][x0 + i - xhsize].info |= (CAVE_ROOM);
3280                         place_outer_bold(y0 + 0 - yhsize, x0 + i - xhsize);
3281                 }
3282                 else
3283                 {
3284                         /* set to be normal granite */
3285                         place_extra_bold(y0 + 0 - yhsize, x0 + i - xhsize);
3286                 }
3287
3288                 /* bottom boundary */
3289                 if ((cave[ysize + y0 - yhsize][i + x0 - xhsize].info & CAVE_ICKY) && (room))
3290                 {
3291                         /* Next to a 'filled' region? - set to be room walls */
3292                         place_outer_bold(y0 + ysize - yhsize, x0 + i - xhsize);
3293                         if (light) cave[y0 + ysize - yhsize][x0 + i - xhsize].info|=(CAVE_GLOW);
3294                         cave[y0 + ysize - yhsize][x0 + i - xhsize].info|=(CAVE_ROOM);
3295                         place_outer_bold(y0 + ysize - yhsize, x0 + i - xhsize);
3296                 }
3297                 else
3298                 {
3299                         /* set to be normal granite */
3300                         place_extra_bold(y0 + ysize - yhsize, x0 + i - xhsize);
3301                 }
3302
3303                 /* clear the icky flag-don't need it any more */
3304                 cave[y0 + 0 - yhsize][x0 + i - xhsize].info &= ~(CAVE_ICKY);
3305                 cave[y0 + ysize - yhsize][x0 + i - xhsize].info &= ~(CAVE_ICKY);
3306         }
3307
3308         /* Do the left and right boundaries minus the corners (done above) */
3309         for (i = 1; i < ysize; ++i)
3310         {
3311                 /* left boundary */
3312                 if ((cave[i + y0 - yhsize][0 + x0 - xhsize].info & CAVE_ICKY) && room)
3313                 {
3314                         /* room boundary */
3315                         place_outer_bold(y0 + i - yhsize, x0 + 0 - xhsize);
3316                         if (light) cave[y0 + i - yhsize][x0 + 0 - xhsize].info |= (CAVE_GLOW);
3317                         cave[y0 + i - yhsize][x0 + 0 - xhsize].info |= (CAVE_ROOM);
3318                         place_outer_bold(y0 + i - yhsize, x0 + 0 - xhsize);
3319                 }
3320                 else
3321                 {
3322                         /* outside room */
3323                         place_extra_bold(y0 + i - yhsize, x0 + 0 - xhsize);
3324                 }
3325                 /* right boundary */
3326                 if ((cave[i + y0 - yhsize][xsize + x0 - xhsize].info & CAVE_ICKY) && room)
3327                 {
3328                         /* room boundary */
3329                         place_outer_bold(y0 + i - yhsize, x0 + xsize - xhsize);
3330                         if (light) cave[y0 + i - yhsize][x0 + xsize - xhsize].info |= (CAVE_GLOW);
3331                         cave[y0 + i - yhsize][x0 + xsize - xhsize].info |= (CAVE_ROOM);
3332                         place_outer_bold(y0 + i - yhsize, x0 + xsize - xhsize);
3333                 }
3334                 else
3335                 {
3336                         /* outside room */
3337                         place_extra_bold(y0 + i - yhsize, x0 + xsize - xhsize);
3338                 }
3339
3340                 /* clear icky flag -done with it */
3341                 cave[y0 + i - yhsize][x0 + 0 - xhsize].info &= ~(CAVE_ICKY);
3342                 cave[y0 + i - yhsize][x0 + xsize - xhsize].info &= ~(CAVE_ICKY);
3343         }
3344
3345
3346         /* Do the rest: convert back to the normal format */
3347         for (x = 1; x < xsize; ++x)
3348         {
3349                 for (y = 1; y < ysize; ++y)
3350                 {
3351                         if (is_floor_bold(y0 + y - yhsize, x0 + x - xhsize) &&
3352                             (cave[y0 + y - yhsize][x0 + x - xhsize].info & CAVE_ICKY))
3353                         {
3354                                 /* Clear the icky flag in the filled region */
3355                                 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~CAVE_ICKY;
3356
3357                                 /* Set appropriate flags */
3358                                 if (light) cave[y0 + y - yhsize][x0 + x - xhsize].info |= (CAVE_GLOW);
3359                                 if (room) cave[y0 + y - yhsize][x0 + x - xhsize].info |= (CAVE_ROOM);
3360                         }
3361                         else if (is_outer_bold(y0 + y - yhsize, x0 + x - xhsize) &&
3362                                  (cave[y0 + y - yhsize][x0 + x - xhsize].info & CAVE_ICKY))
3363                         {
3364                                 /* Walls */
3365                                 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY);
3366                                 if (light) cave[y0 + y - yhsize][x0 + x - xhsize].info |= (CAVE_GLOW);
3367                                 if (room)
3368                                 {
3369                                         cave[y0 + y - yhsize][x0 + x - xhsize].info |= (CAVE_ROOM);
3370                                 }
3371                                 else
3372                                 {
3373
3374                                         place_extra_bold(y0 + y - yhsize, x0 + x - xhsize);
3375                                         cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ROOM);
3376                                 }
3377                         }
3378                         else
3379                         {
3380                                 /* Clear the unconnected regions */
3381                                 place_extra_bold(y0 + y - yhsize, x0 + x - xhsize);
3382                                 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY | CAVE_ROOM);
3383                         }
3384                 }
3385         }
3386
3387         /*
3388          * XXX XXX XXX There is a slight problem when tunnels pierce the caves:
3389          * Extra doors appear inside the system.  (Its not very noticeable though.)
3390          * This can be removed by "filling" from the outside in.  This allows a separation
3391          * from FEAT_WALL_OUTER with FEAT_WALL_INNER.  (Internal walls are  F.W.OUTER instead.)
3392          * The extra effort for what seems to be only a minor thing (even non-existant if you
3393          * think of the caves not as normal rooms, but as holes in the dungeon), doesn't seem
3394          * worth it.
3395          */
3396
3397         return TRUE;
3398 }
3399
3400
3401 /*
3402  * Driver routine to create fractal cave system
3403  */
3404 static void build_type9(int by0, int bx0)
3405 {
3406         int grd, roug, cutoff, xsize, ysize, y0, x0;
3407
3408         bool done, light, room;
3409
3410         /* get size: note 'Evenness'*/
3411         xsize = randint1(22) * 2 + 6;
3412         ysize = randint1(15) * 2 + 6;
3413
3414         /* Try to allocate space for room.  If fails, exit */
3415         if (!room_alloc(xsize + 1, ysize + 1, FALSE, by0, bx0, &x0, &y0)) return;
3416
3417         light = done = FALSE;
3418         room = TRUE;
3419
3420         if ((dun_level <= randint1(25)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS)) light = TRUE;
3421
3422         while (!done)
3423         {
3424                 /* Note: size must be even or there are rounding problems
3425                 * This causes the tunnels not to connect properly to the room */
3426
3427                 /* testing values for these parameters feel free to adjust */
3428                 grd = 1 << (randint0(4));
3429
3430                 /* want average of about 16 */
3431                 roug = randint1(8) * randint1(4);
3432
3433                 /* about size/2 */
3434                 cutoff = randint1(xsize / 4) + randint1(ysize / 4) +
3435                          randint1(xsize / 4) + randint1(ysize / 4);
3436
3437                 /* make it */
3438                 generate_hmap(y0, x0, xsize, ysize, grd, roug, cutoff);
3439
3440                 /* Convert to normal format + clean up */
3441                 done = generate_fracave(y0, x0, xsize, ysize, cutoff, light, room);
3442         }
3443 }
3444
3445 #ifdef ALLOW_CAVERNS_AND_LAKES
3446 /*
3447  * Builds a cave system in the center of the dungeon.
3448  */
3449 void build_cavern(void)
3450 {
3451         int grd, roug, cutoff, xsize, ysize, x0, y0;
3452         bool done, light;
3453
3454         light = done = FALSE;
3455         if ((dun_level <= randint1(50)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS)) light = TRUE;
3456
3457         /* Make a cave the size of the dungeon */
3458         xsize = cur_wid - 1;
3459         ysize = cur_hgt - 1;
3460         x0 = xsize / 2;
3461         y0 = ysize / 2;
3462
3463         /* Paranoia: make size even */
3464         xsize = x0 * 2;
3465         ysize = y0 * 2;
3466
3467         while (!done)
3468         {
3469                 /* testing values for these parameters: feel free to adjust */
3470                 grd = randint1(4) + 4;
3471
3472                 /* want average of about 16 */
3473                 roug = randint1(8) * randint1(4);
3474
3475                 /* about size/2 */
3476                 cutoff = xsize / 2;
3477
3478                  /* make it */
3479                 generate_hmap(y0 + 1, x0 + 1, xsize, ysize, grd, roug, cutoff);
3480
3481                 /* Convert to normal format+ clean up */
3482                 done = generate_fracave(y0 + 1, x0 + 1, xsize, ysize, cutoff, light, FALSE);
3483         }
3484 }
3485
3486 static bool generate_lake(int y0, int x0, int xsize, int ysize, int c1, int c2, int c3, int type)
3487 {
3488         int x, y, i, xhsize, yhsize;
3489         int feat1, feat2, feat3;
3490
3491         /* offsets to middle from corner */
3492         xhsize = xsize / 2;
3493         yhsize = ysize / 2;
3494
3495         /* Get features based on type */
3496         switch (type)
3497         {
3498         case GEN_LAKE_TYPE_LAVA: /* Lava */
3499                 feat1 = FEAT_DEEP_LAVA;
3500                 feat2 = FEAT_SHAL_LAVA;
3501                 feat3 = floor_type[randint0(100)];
3502                 break;
3503         case GEN_LAKE_TYPE_WATER: /* Water */
3504                 feat1 = FEAT_DEEP_WATER;
3505                 feat2 = FEAT_SHAL_WATER;
3506                 feat3 = floor_type[randint0(100)];
3507                 break;
3508         case GEN_LAKE_TYPE_CAVE: /* Collapsed cave */
3509                 feat1 = floor_type[randint0(100)];
3510                 feat2 = floor_type[randint0(100)];
3511                 feat3 = FEAT_RUBBLE;
3512                 break;
3513         case GEN_LAKE_TYPE_EARTH_VAULT: /* Earth vault */
3514                 feat1 = FEAT_RUBBLE;
3515                 feat2 = floor_type[randint0(100)];
3516                 feat3 = FEAT_RUBBLE;
3517                 break;
3518         case GEN_LAKE_TYPE_AIR_VAULT: /* Air vault */
3519                 feat1 = FEAT_GRASS;
3520                 feat2 = FEAT_TREES;
3521                 feat3 = FEAT_GRASS;
3522                 break;
3523         case GEN_LAKE_TYPE_WATER_VAULT: /* Water vault */
3524                 feat1 = FEAT_SHAL_WATER;
3525                 feat2 = FEAT_DEEP_WATER;
3526                 feat3 = FEAT_SHAL_WATER;
3527                 break;
3528         case GEN_LAKE_TYPE_FIRE_VAULT: /* Fire Vault */
3529                 feat1 = FEAT_SHAL_LAVA;
3530                 feat2 = FEAT_DEEP_LAVA;
3531                 feat3 = FEAT_SHAL_LAVA;
3532                 break;
3533
3534         /* Paranoia */
3535         default: return FALSE;
3536         }
3537
3538         /*
3539          * select region connected to center of cave system
3540          * this gets rid of alot of isolated one-sqaures that
3541          * can make teleport traps instadeaths...
3542          */
3543
3544         /* cutoffs */
3545         fill_data.c1 = c1;
3546         fill_data.c2 = c2;
3547         fill_data.c3 = c3;
3548
3549         /* features to fill with */
3550         fill_data.feat1 = feat1;
3551         fill_data.feat2 = feat2;
3552         fill_data.feat3 = feat3;
3553
3554         fill_data.info1 = 0;
3555         fill_data.info2 = 0;
3556         fill_data.info3 = 0;
3557
3558         /* number of filled squares */
3559         fill_data.amount = 0;
3560
3561         /* select region connected to center of cave system
3562         * this gets rid of alot of isolated one-sqaures that
3563         * can make teleport traps instadeaths... */
3564         cave_fill((byte)y0, (byte)x0);
3565
3566         /* if tally too small, try again */
3567         if (fill_data.amount < 10)
3568         {
3569                 /* too small -clear area and try again later */
3570                 for (x = 0; x <= xsize; ++x)
3571                 {
3572                         for (y = 0; y <= ysize; ++y)
3573                         {
3574                                 place_floor_bold(y0 + y - yhsize, x0 + x - xhsize);
3575                                 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY);
3576                         }
3577                 }
3578                 return FALSE;
3579         }
3580
3581         /* Do boundarys- set to normal granite */
3582         for (i = 0; i <= xsize; ++i)
3583         {
3584                 place_extra_bold(y0 + 0 - yhsize, x0 + i - xhsize);
3585                 place_extra_bold(y0 + ysize - yhsize, x0 + i - xhsize);
3586
3587                 /* clear the icky flag-don't need it any more */
3588                 cave[y0 + 0 - yhsize][x0 + i - xhsize].info &= ~(CAVE_ICKY);
3589                 cave[y0 + ysize - yhsize][x0 + i - xhsize].info &= ~(CAVE_ICKY);
3590         }
3591
3592         /* Do the left and right boundaries minus the corners (done above) */
3593
3594         for (i = 1; i < ysize; ++i)
3595         {
3596                 place_extra_bold(y0 + i - yhsize, x0 + 0 - xhsize);
3597                 place_extra_bold(y0 + i - yhsize, x0 + xsize - xhsize);
3598
3599                 /* clear icky flag -done with it */
3600                 cave[y0 + i - yhsize][x0 + 0 - xhsize].info &= ~(CAVE_ICKY);
3601                 cave[y0 + i - yhsize][x0 + xsize - xhsize].info &= ~(CAVE_ICKY);
3602         }
3603
3604
3605         /* Do the rest: convert back to the normal format */
3606         for (x = 1; x < xsize; ++x)
3607         {
3608                 for (y = 1; y < ysize; ++y)
3609                 {
3610                         /* Fill unconnected regions with granite */
3611                         if ((!(cave[y0 + y - yhsize][x0 + x - xhsize].info & CAVE_ICKY)) ||
3612                                 is_outer_bold(y0 + y - yhsize, x0 + x - xhsize))
3613                                 place_extra_bold(y0 + y - yhsize, x0 + x - xhsize);
3614
3615                         /* turn off icky flag (no longer needed.) */
3616                         cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY | CAVE_ROOM);
3617
3618                         /* Light lava and trees */
3619                         if ((cave[y0 + y - yhsize][x0 + x - xhsize].feat == FEAT_DEEP_LAVA) ||
3620                                 (cave[y0 + y - yhsize][x0 + x - xhsize].feat == FEAT_SHAL_LAVA))
3621                         {
3622                                 if (!(d_info[dungeon_type].flags1 & DF1_DARKNESS)) cave[y0 + y - yhsize][x0 + x - xhsize].info |= CAVE_GLOW;
3623                         }
3624                 }
3625         }
3626
3627         return TRUE;
3628 }
3629
3630
3631 /*
3632  * makes a lake/collapsed cave system in the center of the dungeon
3633  */
3634 void build_lake(int type)
3635 {
3636         int grd, roug, xsize, ysize, x0, y0;
3637         bool done = FALSE;
3638         int c1, c2, c3;
3639
3640         /* paranoia - exit if lake type out of range. */
3641         if ((type < GEN_LAKE_TYPE_LAVA) || (type > GEN_LAKE_TYPE_FIRE_VAULT))
3642         {
3643                 msg_format("Invalid lake type (%d)", type);
3644                 return;
3645         }
3646
3647         /* Make the size of the dungeon */
3648         xsize = cur_wid - 1;
3649         ysize = cur_hgt - 1;
3650         x0 = xsize / 2;
3651         y0 = ysize / 2;
3652
3653         /* Paranoia: make size even */
3654         xsize = x0 * 2;
3655         ysize = y0 * 2;
3656
3657         while (!done)
3658         {
3659                 /* testing values for these parameters: feel free to adjust */
3660                 grd = randint1(3) + 4;
3661
3662                 /* want average of about 16 */
3663                 roug = randint1(8) * randint1(4);
3664
3665                 /* Make up size of various componants */
3666                 /* Floor */
3667                 c3 = 3 * xsize / 4;
3668
3669                 /* Deep water/lava */
3670                 c1 = randint0(c3 / 2) + randint0(c3 / 2) - 5;
3671
3672                 /* Shallow boundary */
3673                 c2 = (c1 + c3) / 2;
3674
3675                 /* make it */
3676                 generate_hmap(y0 + 1, x0 + 1, xsize, ysize, grd, roug, c3);
3677
3678                 /* Convert to normal format+ clean up */
3679                 done = generate_lake(y0 + 1, x0 + 1, xsize, ysize, c1, c2, c3, type);
3680         }
3681 }
3682 #endif /* ALLOW_CAVERNS_AND_LAKES */
3683
3684
3685 /*
3686  * Routine used by the random vault creators to add a door to a location
3687  * Note that range checking has to be done in the calling routine.
3688  *
3689  * The doors must be INSIDE the allocated region.
3690  */
3691 static void add_door(int x, int y)
3692 {
3693         /* Need to have a wall in the center square */
3694         if (!is_outer_bold(y, x)) return;
3695
3696         /* look at:
3697          *  x#x
3698          *  .#.
3699          *  x#x
3700          *
3701          *  where x=don't care
3702          *  .=floor, #=wall
3703          */
3704
3705         if (is_floor_bold(y-1,x) && is_floor_bold(y+1,x) &&
3706             (is_outer_bold(y, x - 1) && is_outer_bold(y, x + 1)))
3707         {
3708                 /* secret door */
3709                 place_secret_door(y, x);
3710
3711                 /* set boundarys so don't get wide doors */
3712                 place_solid_bold(y, x - 1);
3713                 place_solid_bold(y, x + 1);
3714         }
3715
3716
3717         /* look at:
3718          *  x#x
3719          *  .#.
3720          *  x#x
3721          *
3722          *  where x = don't care
3723          *  .=floor, #=wall
3724          */
3725         if (is_outer_bold(y - 1, x) && is_outer_bold(y + 1, x) &&
3726             is_floor_bold(y,x-1) && is_floor_bold(y,x+1))
3727         {
3728                 /* secret door */
3729                 place_secret_door(y, x);
3730
3731                 /* set boundarys so don't get wide doors */
3732                 place_solid_bold(y - 1, x);
3733                 place_solid_bold(y + 1, x);
3734         }
3735 }
3736
3737
3738 /*
3739  * Routine that fills the empty areas of a room with treasure and monsters.
3740  */
3741 static void fill_treasure(int x1, int x2, int y1, int y2, int difficulty)
3742 {
3743         int x, y, cx, cy, size;
3744         s32b value;
3745
3746         /* center of room:*/
3747         cx = (x1 + x2) / 2;
3748         cy = (y1 + y2) / 2;
3749
3750         /* Rough measure of size of vault= sum of lengths of sides */
3751         size = abs(x2 - x1) + abs(y2 - y1);
3752
3753         for (x = x1; x <= x2; x++)
3754         {
3755                 for (y = y1; y <= y2; y++)
3756                 {
3757                         /* Thing added based on distance to center of vault
3758                          * Difficulty is 1-easy to 10-hard */
3759                         value = ((((s32b)(distance(cx, cy, x, y))) * 100) / size) + randint1(10) - difficulty;
3760
3761                         /* hack- empty square part of the time */
3762                         if ((randint1(100) - difficulty * 3) > 50) value = 20;
3763
3764                          /* if floor, shallow water and lava */
3765                         if (is_floor_bold(y, x) ||
3766                             (cave[y][x].feat == FEAT_SHAL_WATER) ||
3767                             (cave[y][x].feat == FEAT_SHAL_LAVA))
3768                         {
3769                                 /* The smaller 'value' is, the better the stuff */
3770                                 if (value < 0)
3771                                 {
3772                                         /* Meanest monster + treasure */
3773                                         monster_level = base_level + 40;
3774                                         place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
3775                                         monster_level = base_level;
3776                                         object_level = base_level + 20;
3777                                         place_object(y, x, TRUE, FALSE);
3778                                         object_level = base_level;
3779                                 }
3780                                 else if (value < 5)
3781                                 {
3782                                         /* Mean monster +treasure */
3783                                         monster_level = base_level + 20;
3784                                         place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
3785                                         monster_level = base_level;
3786                                         object_level = base_level + 10;
3787                                         place_object(y, x, TRUE, FALSE);
3788                                         object_level = base_level;
3789                                 }
3790                                 else if (value < 10)
3791                                 {
3792                                         /* Monster */
3793                                         monster_level = base_level + 9;
3794                                         place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
3795                                         monster_level = base_level;
3796                                 }
3797                                 else if (value < 17)
3798                                 {
3799                                         /* Intentional Blank space */
3800
3801                                         /*
3802                                          * (Want some of the vault to be empty
3803                                          * so have room for group monsters.
3804                                          * This is used in the hack above to lower
3805                                          * the density of stuff in the vault.)
3806                                          */
3807                                 }
3808                                 else if (value < 23)
3809                                 {
3810                                         /* Object or trap */
3811                                         if (randint0(100) < 25)
3812                                         {
3813                                                 place_object(y, x, FALSE, FALSE);
3814                                         }
3815                                         else
3816                                         {
3817                                                 place_trap(y, x);
3818                                         }
3819                                 }
3820                                 else if (value < 30)
3821                                 {
3822                                         /* Monster and trap */
3823                                         monster_level = base_level + 5;
3824                                         place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
3825                                         monster_level = base_level;
3826                                         place_trap(y, x);
3827                                 }
3828                                 else if (value < 40)
3829                                 {
3830                                         /* Monster or object */
3831                                         if (randint0(100) < 50)
3832                                         {
3833                                                 monster_level = base_level + 3;
3834                                                 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
3835                                                 monster_level = base_level;
3836                                         }
3837                                         if (randint0(100) < 50)
3838                                         {
3839                                                 object_level = base_level + 7;
3840                                                 place_object(y, x, FALSE, FALSE);
3841                                                 object_level = base_level;
3842                                         }
3843                                 }
3844                                 else if (value < 50)
3845                                 {
3846                                         /* Trap */
3847                                         place_trap(y, x);
3848                                 }
3849                                 else
3850                                 {
3851                                         /* Various Stuff */
3852
3853                                         /* 20% monster, 40% trap, 20% object, 20% blank space */
3854                                         if (randint0(100) < 20)
3855                                         {
3856                                                 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
3857                                         }
3858                                         else if (randint0(100) < 50)
3859                                         {
3860                                                 place_trap(y, x);
3861                                         }
3862                                         else if (randint0(100) < 50)
3863                                         {
3864                                                 place_object(y, x, FALSE, FALSE);
3865                                         }
3866                                 }
3867
3868                         }
3869                 }
3870         }
3871 }
3872
3873
3874 /*
3875  * This function creates a random vault that looks like a collection of bubbles.
3876  * It works by getting a set of coordinates that represent the center of each
3877  * bubble.  The entire room is made by seeing which bubble center is closest. If
3878  * two centers are equidistant then the square is a wall, otherwise it is a floor.
3879  * The only exception is for squares really near a center, these are always floor.
3880  * (It looks better than without this check.)
3881  *
3882  * Note: If two centers are on the same point then this algorithm will create a
3883  *       blank bubble filled with walls. - This is prevented from happening.
3884  */
3885 static void build_bubble_vault(int x0, int y0, int xsize, int ysize)
3886 {
3887         #define BUBBLENUM 10            /* number of bubbles */
3888
3889         /* array of center points of bubbles */
3890         coord center[BUBBLENUM];
3891
3892         int i, j, x, y;
3893         u16b min1, min2, temp;
3894         bool done;
3895
3896         /* Offset from center to top left hand corner */
3897         int xhsize = xsize / 2;
3898         int yhsize = ysize / 2;
3899
3900
3901         if (cheat_room) msg_print("Bubble Vault");
3902
3903         /* Allocate center of bubbles */
3904         center[0].x = randint1(xsize - 3) + 1;
3905         center[0].y = randint1(ysize - 3) + 1;
3906
3907         for (i = 1; i < BUBBLENUM; i++)
3908         {
3909                 done = FALSE;
3910
3911                 /* get center and check to see if it is unique */
3912                 while (!done)
3913                 {
3914                         done = TRUE;
3915
3916                         x = randint1(xsize - 3) + 1;
3917                         y = randint1(ysize - 3) + 1;
3918
3919                         for (j = 0; j < i; j++)
3920                         {
3921                                 /* rough test to see if there is an overlap */
3922                                 if ((x == center[j].x) && (y == center[j].y)) done = FALSE;
3923                         }
3924                 }
3925
3926                 center[i].x = x;
3927                 center[i].y = y;
3928         }
3929
3930
3931         /* Top and bottom boundaries */
3932         for (i = 0; i < xsize; i++)
3933         {
3934                 int x = x0 - xhsize + i;
3935
3936                 place_outer_noperm_bold(y0 - yhsize + 0, x);
3937                 cave[y0 - yhsize + 0][x].info |= (CAVE_ROOM | CAVE_ICKY);
3938                 place_outer_noperm_bold(y0 - yhsize + ysize - 1, x);
3939                 cave[y0 - yhsize + ysize - 1][x].info |= (CAVE_ROOM | CAVE_ICKY);
3940         }
3941
3942         /* Left and right boundaries */
3943         for (i = 1; i < ysize - 1; i++)
3944         {
3945                 int y = y0 - yhsize + i;
3946
3947                 place_outer_noperm_bold(y, x0 - xhsize + 0);
3948                 cave[y][x0 - xhsize + 0].info |= (CAVE_ROOM | CAVE_ICKY);
3949                 place_outer_noperm_bold(y, x0 - xhsize + xsize - 1);
3950                 cave[y][x0 - xhsize + xsize - 1].info |= (CAVE_ROOM | CAVE_ICKY);
3951         }
3952
3953         /* Fill in middle with bubbles */
3954         for (x = 1; x < xsize - 1; x++)
3955         {
3956                 for (y = 1; y < ysize - 1; y++)
3957                 {
3958                         /* Get distances to two closest centers */
3959
3960                         /* initialize */
3961                         min1 = distance(x, y, center[0].x, center[0].y);
3962                         min2 = distance(x, y, center[1].x, center[1].y);
3963
3964                         if (min1 > min2)
3965                         {
3966                                 /* swap if in wrong order */
3967                                 temp = min1;
3968                                 min1 = min2;
3969                                 min2 = temp;
3970                         }
3971
3972                         /* Scan the rest */
3973                         for (i = 2; i < BUBBLENUM; i++)
3974                         {
3975                                 temp = distance(x, y, center[i].x, center[i].y);
3976
3977                                 if (temp < min1)
3978                                 {
3979                                         /* smallest */
3980                                         min2 = min1;
3981                                         min1 = temp;
3982                                 }
3983                                 else if (temp < min2)
3984                                 {
3985                                         /* second smallest */
3986                                         min2 = temp;
3987                                 }
3988                         }
3989                         if (((min2 - min1) <= 2) && (!(min1 < 3)))
3990                         {
3991                                 /* Boundary at midpoint+ not at inner region of bubble */
3992                                 place_outer_noperm_bold(y0 - yhsize + y, x0 - xhsize + x);
3993                         }
3994                         else
3995                         {
3996                                 /* middle of a bubble */
3997                                 place_floor_bold(y0 - yhsize + y, x0 - xhsize + x);
3998                         }
3999
4000                         /* clean up rest of flags */
4001                         cave[y0 - yhsize + y][x0 - xhsize + x].info |= (CAVE_ROOM | CAVE_ICKY);
4002                 }
4003         }
4004
4005         /* Try to add some random doors */
4006         for (i = 0; i < 500; i++)
4007         {
4008                 x = randint1(xsize - 3) - xhsize + x0 + 1;
4009                 y = randint1(ysize - 3) - yhsize + y0 + 1;
4010                 add_door(x, y);
4011         }
4012
4013         /* Fill with monsters and treasure, low difficulty */
4014         fill_treasure(x0 - xhsize + 1, x0 - xhsize + xsize - 2, y0 - yhsize + 1, y0 - yhsize + ysize - 2, randint1(5));
4015 }
4016
4017
4018 /*
4019  * Overlay a rectangular room given its bounds
4020  * This routine is used by build_room_vault
4021  * The area inside the walls is not touched:
4022  * only granite is removed- normal walls stay
4023  */
4024 static void build_room(int x1, int x2, int y1, int y2)
4025 {
4026         int x, y, i, xsize, ysize, temp;
4027
4028         /* Check if rectangle has no width */
4029         if ((x1 == x2) || (y1 == y2)) return;
4030
4031         /* initialize */
4032         if (x1 > x2)
4033         {
4034                 /* Swap boundaries if in wrong order */
4035                 temp = x1;
4036                 x1 = x2;
4037                 x2 = temp;
4038         }
4039
4040         if (y1 > y2)
4041         {
4042                 /* Swap boundaries if in wrong order */
4043                 temp = y1;
4044                 y1 = y2;
4045                 y2 = temp;
4046         }
4047
4048         /* get total widths */
4049         xsize = x2 - x1;
4050         ysize = y2 - y1;
4051
4052
4053         /* Top and bottom boundaries */
4054         for (i = 0; i <= xsize; i++)
4055         {
4056                 place_outer_noperm_bold(y1, x1 + i);
4057                 cave[y1][x1 + i].info |= (CAVE_ROOM | CAVE_ICKY);
4058                 place_outer_noperm_bold(y2, x1 + i);
4059                 cave[y2][x1 + i].info |= (CAVE_ROOM | CAVE_ICKY);
4060         }
4061
4062         /* Left and right boundaries */
4063         for (i = 1; i < ysize; i++)
4064         {
4065                 place_outer_noperm_bold(y1 + i, x1);
4066                 cave[y1 + i][x1].info|=(CAVE_ROOM | CAVE_ICKY);
4067                 place_outer_noperm_bold(y1 + i, x2);
4068                 cave[y1 + i][x2].info|=(CAVE_ROOM | CAVE_ICKY);
4069         }
4070
4071         /* Middle */
4072         for (x = 1; x < xsize; x++)
4073         {
4074                 for (y = 1; y < ysize; y++)
4075                 {
4076                         if (is_extra_bold(y1+y, x1+x))
4077                         {
4078                                 /* clear the untouched region */
4079                                 place_floor_bold(y1 + y, x1 + x);
4080                                 cave[y1 + y][x1 + x].info |= (CAVE_ROOM | CAVE_ICKY);
4081                         }
4082                         else
4083                         {
4084                                 /* make it a room- but don't touch */
4085                                 cave[y1 + y][x1 + x].info |= (CAVE_ROOM | CAVE_ICKY);
4086                         }
4087                 }
4088         }
4089 }
4090
4091
4092 /* Create a random vault that looks like a collection of overlapping rooms */
4093
4094 static void build_room_vault(int x0, int y0, int xsize, int ysize)
4095 {
4096         int i, x1, x2, y1, y2, xhsize, yhsize;
4097
4098         /* get offset from center */
4099         xhsize = xsize / 2;
4100         yhsize = ysize / 2;
4101
4102         if (cheat_room) msg_print("Room Vault");
4103
4104         /* fill area so don't get problems with arena levels */
4105         for (x1 = 0; x1 < xsize; x1++)
4106         {
4107                 int x = x0 - xhsize + x1;
4108
4109                 for (y1 = 0; y1 < ysize; y1++)
4110                 {
4111                         int y = y0 - yhsize + y1;
4112
4113                         place_extra_bold(y, x);
4114                         cave[y][x].info &= (~CAVE_ICKY);
4115                 }
4116         }
4117
4118         /* add ten random rooms */
4119         for (i = 0; i < 10; i++)
4120         {
4121                 x1 = randint1(xhsize) * 2 + x0 - xhsize;
4122                 x2 = randint1(xhsize) * 2 + x0 - xhsize;
4123                 y1 = randint1(yhsize) * 2 + y0 - yhsize;
4124                 y2 = randint1(yhsize) * 2 + y0 - yhsize;
4125                 build_room(x1, x2, y1, y2);
4126         }
4127
4128         /* Add some random doors */
4129         for (i = 0; i < 500; i++)
4130         {
4131                 x1 = randint1(xsize - 3) - xhsize + x0 + 1;
4132                 y1 = randint1(ysize - 3) - yhsize + y0 + 1;
4133                 add_door(x1, y1);
4134         }
4135
4136         /* Fill with monsters and treasure, high difficulty */
4137         fill_treasure(x0 - xhsize + 1, x0 - xhsize + xsize - 2, y0 - yhsize + 1, y0 - yhsize + ysize - 2, randint1(5) + 5);
4138 }
4139
4140
4141 /* Create a random vault out of a fractal cave */
4142 static void build_cave_vault(int x0, int y0, int xsiz, int ysiz)
4143 {
4144         int grd, roug, cutoff, xhsize, yhsize, xsize, ysize, x, y;
4145         bool done, light, room;
4146
4147         /* round to make sizes even */
4148         xhsize = xsiz / 2;
4149         yhsize = ysiz / 2;
4150         xsize = xhsize * 2;
4151         ysize = yhsize * 2;
4152
4153         if (cheat_room) msg_print("Cave Vault");
4154
4155         light = done = FALSE;
4156         room = TRUE;
4157
4158         while (!done)
4159         {
4160                 /* testing values for these parameters feel free to adjust */
4161                 grd = 1 << randint0(4);
4162
4163                 /* want average of about 16 */
4164                 roug = randint1(8) * randint1(4);
4165
4166                 /* about size/2 */
4167                 cutoff = randint1(xsize / 4) + randint1(ysize / 4) +
4168                          randint1(xsize / 4) + randint1(ysize / 4);
4169
4170                 /* make it */
4171                 generate_hmap(y0, x0, xsize, ysize, grd, roug, cutoff);
4172
4173                 /* Convert to normal format+ clean up */
4174                 done = generate_fracave(y0, x0, xsize, ysize, cutoff, light, room);
4175         }
4176
4177         /* Set icky flag because is a vault */
4178         for (x = 0; x <= xsize; x++)
4179         {
4180                 for (y = 0; y <= ysize; y++)
4181                 {
4182                         cave[y0 - yhsize + y][x0 - xhsize + x].info |= CAVE_ICKY;
4183                 }
4184         }
4185
4186         /* Fill with monsters and treasure, low difficulty */
4187         fill_treasure(x0 - xhsize + 1, x0 - xhsize + xsize - 1, y0 - yhsize + 1, y0 - yhsize + ysize - 1, randint1(5));
4188 }
4189
4190 /*
4191  * maze vault -- rectangular labyrinthine rooms
4192  *
4193  * maze vault uses two routines:
4194  *    r_visit - a recursive routine that builds the labyrinth
4195  *    build_maze_vault - a driver routine that calls r_visit and adds
4196  *                   monsters, traps and treasure
4197  *
4198  * The labyrinth is built by creating a spanning tree of a graph.
4199  * The graph vertices are at
4200  *    (x, y) = (2j + x1, 2k + y1)   j = 0,...,m-1    k = 0,...,n-1
4201  * and the edges are the vertical and horizontal nearest neighbors.
4202  *
4203  * The spanning tree is created by performing a suitably randomized
4204  * depth-first traversal of the graph. The only adjustable parameter
4205  * is the randint0(3) below; it governs the relative density of
4206  * twists and turns in the labyrinth: smaller number, more twists.
4207  */
4208 static void r_visit(int y1, int x1, int y2, int x2,
4209                     int node, int dir, int *visited)
4210 {
4211         int i, j, m, n, temp, x, y, adj[4];
4212
4213         /* dimensions of vertex array */
4214         m = (x2 - x1) / 2 + 1;
4215         n = (y2 - y1) / 2 + 1;
4216
4217         /* mark node visited and set it to a floor */
4218         visited[node] = 1;
4219         x = 2 * (node % m) + x1;
4220         y = 2 * (node / m) + y1;
4221         place_floor_bold(y, x);
4222
4223         /* setup order of adjacent node visits */
4224         if (one_in_(3))
4225         {
4226                 /* pick a random ordering */
4227                 for (i = 0; i < 4; i++)
4228                         adj[i] = i;
4229                 for (i = 0; i < 4; i++)
4230                 {
4231                         j = randint0(4);
4232                         temp = adj[i];
4233                         adj[i] = adj[j];
4234                         adj[j] = temp;
4235                 }
4236                 dir = adj[0];
4237         }
4238         else
4239         {
4240                 /* pick a random ordering with dir first */
4241                 adj[0] = dir;
4242                 for (i = 1; i < 4; i++)
4243                         adj[i] = i;
4244                 for (i = 1; i < 4; i++)
4245                 {
4246                         j = 1 + randint0(3);
4247                         temp = adj[i];
4248                         adj[i] = adj[j];
4249                         adj[j] = temp;
4250                 }
4251         }
4252
4253         for (i = 0; i < 4; i++)
4254         {
4255                 switch (adj[i])
4256                 {
4257                         case 0:
4258                                 /* (0,+) - check for bottom boundary */
4259                                 if ((node / m < n - 1) && (visited[node + m] == 0))
4260                                 {
4261                                         place_floor_bold(y + 1, x);
4262                                         r_visit(y1, x1, y2, x2, node + m, dir, visited);
4263                                 }
4264                                 break;
4265                         case 1:
4266                                 /* (0,-) - check for top boundary */
4267                                 if ((node / m > 0) && (visited[node - m] == 0))
4268                                 {
4269                                         place_floor_bold(y - 1, x);
4270                                         r_visit(y1, x1, y2, x2, node - m, dir, visited);
4271                                 }
4272                                 break;
4273                         case 2:
4274                                 /* (+,0) - check for right boundary */
4275                                 if ((node % m < m - 1) && (visited[node + 1] == 0))
4276                                 {
4277                                         place_floor_bold(y, x + 1);
4278                                         r_visit(y1, x1, y2, x2, node + 1, dir, visited);
4279                                 }
4280                                 break;
4281                         case 3:
4282                                 /* (-,0) - check for left boundary */
4283                                 if ((node % m > 0) && (visited[node - 1] == 0))
4284                                 {
4285                                         place_floor_bold(y, x - 1);
4286                                         r_visit(y1, x1, y2, x2, node - 1, dir, visited);
4287                                 }
4288                 } /* end switch */
4289         }
4290 }
4291
4292
4293 void build_maze_vault(int x0, int y0, int xsize, int ysize, bool is_vault)
4294 {
4295         int y, x, dy, dx;
4296         int y1, x1, y2, x2;
4297         int m, n, num_vertices, *visited;
4298         bool light;
4299         cave_type *c_ptr;
4300
4301
4302         if (cheat_room && is_vault) msg_print("Maze Vault");
4303
4304         /* Choose lite or dark */
4305         light = ((dun_level <= randint1(25)) && is_vault && !(d_info[dungeon_type].flags1 & DF1_DARKNESS));
4306
4307         /* Pick a random room size - randomized by calling routine */
4308         dy = ysize / 2 - 1;
4309         dx = xsize / 2 - 1;
4310
4311         y1 = y0 - dy;
4312         x1 = x0 - dx;
4313         y2 = y0 + dy;
4314         x2 = x0 + dx;
4315
4316         /* generate the room */
4317         for (y = y1 - 1; y <= y2 + 1; y++)
4318         {
4319                 for (x = x1 - 1; x <= x2 + 1; x++)
4320                 {
4321                         c_ptr = &cave[y][x];
4322                         c_ptr->info |= CAVE_ROOM;
4323                         if (is_vault) c_ptr->info |= CAVE_ICKY;
4324                         if ((x == x1 - 1) || (x == x2 + 1) || (y == y1 - 1) || (y == y2 + 1))
4325                         {
4326                                 place_outer_grid(c_ptr);
4327                         }
4328                         else if (!is_vault)
4329                         {
4330                                 place_extra_grid(c_ptr);
4331                         }
4332                         else
4333                         {
4334                                 place_inner_grid(c_ptr);
4335                         }
4336                         if (light) c_ptr->info |= (CAVE_GLOW);
4337                 }
4338         }
4339
4340         /* dimensions of vertex array */
4341         m = dx + 1;
4342         n = dy + 1;
4343         num_vertices = m * n;
4344
4345         /* initialize array of visited vertices */
4346         C_MAKE(visited, num_vertices, int);
4347
4348         /* traverse the graph to create a spaning tree, pick a random root */
4349         r_visit(y1, x1, y2, x2, randint0(num_vertices), 0, visited);
4350
4351         /* Fill with monsters and treasure, low difficulty */
4352         if (is_vault) fill_treasure(x1, x2, y1, y2, randint1(5));
4353
4354         C_KILL(visited, num_vertices, int);
4355 }
4356
4357
4358 /* Build a "mini" checkerboard vault
4359  *
4360  * This is done by making a permanent wall maze and setting
4361  * the diagonal sqaures of the checker board to be granite.
4362  * The vault has two entrances on opposite sides to guarantee
4363  * a way to get in even if the vault abuts a side of the dungeon.
4364  */
4365 static void build_mini_c_vault(int x0, int y0, int xsize, int ysize)
4366  {
4367         int dy, dx;
4368         int y1, x1, y2, x2, y, x, total;
4369         int m, n, num_vertices;
4370         int *visited;
4371
4372         if (cheat_room) msg_print("Mini Checker Board Vault");
4373
4374         /* Pick a random room size */
4375         dy = ysize / 2 - 1;
4376         dx = xsize / 2 - 1;
4377
4378         y1 = y0 - dy;
4379         x1 = x0 - dx;
4380         y2 = y0 + dy;
4381         x2 = x0 + dx;
4382
4383
4384         /* generate the room */
4385         for (x = x1 - 2; x <= x2 + 2; x++)
4386         {
4387                 if (!in_bounds(y1-2,x)) break;
4388
4389                 cave[y1-2][x].info |= (CAVE_ROOM | CAVE_ICKY);
4390
4391                 place_extra_noperm_bold(y1-2, x);
4392         }
4393
4394         for (x = x1 - 2; x <= x2 + 2; x++)
4395         {
4396                 if (!in_bounds(y2+2,x)) break;
4397
4398                 cave[y2+2][x].info |= (CAVE_ROOM | CAVE_ICKY);
4399
4400                 place_extra_noperm_bold(y2+2, x);
4401         }
4402
4403         for (y = y1 - 2; y <= y2 + 2; y++)
4404         {
4405                 if (!in_bounds(y,x1-2)) break;
4406
4407                 cave[y][x1-2].info |= (CAVE_ROOM | CAVE_ICKY);
4408
4409                 place_extra_noperm_bold(y, x1-2);
4410         }
4411
4412         for (y = y1 - 2; y <= y2 + 2; y++)
4413         {
4414                 if (!in_bounds(y,x2+2)) break;
4415
4416                 cave[y][x2+2].info |= (CAVE_ROOM | CAVE_ICKY);
4417
4418                 place_extra_noperm_bold(y, x2+2);
4419         }
4420
4421         for (y = y1 - 1; y <= y2 + 1; y++)
4422         {
4423                 for (x = x1 - 1; x <= x2 + 1; x++)
4424                 {
4425                         cave[y][x].info |= (CAVE_ROOM | CAVE_ICKY);
4426
4427                         /* Permanent walls */
4428                         cave[y][x].feat = FEAT_PERM_INNER;
4429                 }
4430         }
4431
4432
4433         /* dimensions of vertex array */
4434         m = dx + 1;
4435         n = dy + 1;
4436         num_vertices = m * n;
4437
4438         /* initialize array of visited vertices */
4439         C_MAKE(visited, num_vertices, int);
4440
4441         /* traverse the graph to create a spannng tree, pick a random root */
4442         r_visit(y1, x1, y2, x2, randint0(num_vertices), 0, visited);
4443
4444         /* Make it look like a checker board vault */
4445         for (x = x1; x <= x2; x++)
4446         {
4447                 for (y = y1; y <= y2; y++)
4448                 {
4449                         total = x - x1 + y - y1;
4450                         /* If total is odd- and is a floor then make a wall */
4451                         if ((total % 2 == 1) && is_floor_bold(y, x))
4452                         {
4453                                 place_inner_bold(y, x);
4454                         }
4455                 }
4456         }
4457
4458         /* Make a couple of entrances */
4459         if (one_in_(2))
4460         {
4461                 /* left and right */
4462                 y = randint1(dy) + dy / 2;
4463                 place_outer_noperm_bold(y1 + y, x1 - 1);
4464                 place_outer_noperm_bold(y1 + y, x2 + 1);
4465         }
4466         else
4467         {
4468                 /* top and bottom */
4469                 x = randint1(dx) + dx / 2;
4470                 place_outer_noperm_bold(y1 - 1, x1 + x);
4471                 place_outer_noperm_bold(y2 + 1, x1 + x);
4472         }
4473
4474         /* Fill with monsters and treasure, highest difficulty */
4475         fill_treasure(x1, x2, y1, y2, 10);
4476
4477         C_KILL(visited, num_vertices, int);
4478 }
4479
4480
4481 /* Build a town/ castle by using a recursive algorithm.
4482  * Basically divide each region in a probalistic way to create
4483  * smaller regions.  When the regions get too small stop.
4484  *
4485  * The power variable is a measure of how well defended a region is.
4486  * This alters the possible choices.
4487  */
4488 static void build_recursive_room(int x1, int y1, int x2, int y2, int power)
4489 {
4490         int xsize, ysize;
4491         int x, y;
4492         int choice;
4493
4494         /* Temp variables */
4495         int t1, t2, t3, t4;
4496
4497         xsize = x2 - x1;
4498         ysize = y2 - y1;
4499
4500         if ((power < 3) && (xsize > 12) && (ysize > 12))
4501         {
4502                 /* Need outside wall +keep */
4503                 choice = 1;
4504         }
4505         else
4506         {
4507                 if (power < 10)
4508                 {
4509                         /* Make rooms + subdivide */
4510                         if ((randint1(10) > 2) && (xsize < 8) && (ysize < 8))
4511                         {
4512                                 choice = 4;
4513                         }
4514                         else
4515                         {
4516                                 choice = randint1(2) + 1;
4517                         }
4518                 }
4519                 else
4520                 {
4521                         /* Mostly subdivide */
4522                         choice = randint1(3) + 1;
4523                 }
4524         }
4525
4526         /* Based on the choice made above, do something */
4527
4528         switch (choice)
4529         {
4530                 case 1:
4531                 {
4532                         /* Outer walls */
4533
4534                         /* top and bottom */
4535                         for (x = x1; x <= x2; x++)
4536                         {
4537                                 place_outer_bold(y1, x);
4538                                 place_outer_bold(y2, x);
4539                         }
4540
4541                         /* left and right */
4542                         for (y = y1 + 1; y < y2; y++)
4543                         {
4544                                 place_outer_bold(y, x1);
4545                                 place_outer_bold(y, x2);
4546                         }
4547
4548                         /* Make a couple of entrances */
4549                         if (one_in_(2))
4550                         {
4551                                 /* left and right */
4552                                 y = randint1(ysize) + y1;
4553                                 place_floor_bold(y, x1);
4554                                 place_floor_bold(y, x2);
4555                         }
4556                         else
4557                         {
4558                                 /* top and bottom */
4559                                 x = randint1(xsize) + x1;
4560                                 place_floor_bold(y1, x);
4561                                 place_floor_bold(y2, x);
4562                         }
4563
4564                         /* Select size of keep */
4565                         t1 = randint1(ysize / 3) + y1;
4566                         t2 = y2 - randint1(ysize / 3);
4567                         t3 = randint1(xsize / 3) + x1;
4568                         t4 = x2 - randint1(xsize / 3);
4569
4570                         /* Do outside areas */
4571
4572                         /* Above and below keep */
4573                         build_recursive_room(x1 + 1, y1 + 1, x2 - 1, t1, power + 1);
4574                         build_recursive_room(x1 + 1, t2, x2 - 1, y2, power + 1);
4575
4576                         /* Left and right of keep */
4577                         build_recursive_room(x1 + 1, t1 + 1, t3, t2 - 1, power + 3);
4578                         build_recursive_room(t4, t1 + 1, x2 - 1, t2 - 1, power + 3);
4579
4580                         /* Make the keep itself: */
4581                         x1 = t3;
4582                         x2 = t4;
4583                         y1 = t1;
4584                         y2 = t2;
4585                         xsize = x2 - x1;
4586                         ysize = y2 - y1;
4587                         power += 2;
4588
4589                         /* Fall through */
4590                 }
4591                 case 4:
4592                 {
4593                         /* Try to build a room */
4594                         if ((xsize < 3) || (ysize < 3))
4595                         {
4596                                 for (y = y1; y < y2; y++)
4597                                 {
4598                                         for (x = x1; x < x2; x++)
4599                                         {
4600                                                 place_inner_bold(y, x);
4601                                         }
4602                                 }
4603
4604                                 /* Too small */
4605                                 return;
4606                         }
4607
4608                         /* Make outside walls */
4609                         /* top and bottom */
4610                         for (x = x1 + 1; x <= x2 - 1; x++)
4611                         {
4612                                 place_inner_bold(y1 + 1, x);
4613                                 place_inner_bold(y2 - 1, x);
4614                         }
4615
4616                         /* left and right */
4617                         for (y = y1 + 1; y <= y2 - 1; y++)
4618                         {
4619                                 place_inner_bold(y, x1 + 1);
4620                                 place_inner_bold(y, x2 - 1);
4621                         }
4622
4623                         /* Make a door */
4624                         y = randint1(ysize - 3) + y1 + 1;
4625
4626                         if (one_in_(2))
4627                         {
4628                                 /* left */
4629                                 place_floor_bold(y, x1 + 1);
4630                         }
4631                         else
4632                         {
4633                                 /* right */
4634                                 place_floor_bold(y, x2 - 1);
4635                         }
4636
4637                         /* Build the room */
4638                         build_recursive_room(x1 + 2, y1 + 2, x2 - 2, y2 - 2, power + 3);
4639                         break;
4640                 }
4641                 case 2:
4642                 {
4643                         /* Try and divide vertically */
4644                         if (xsize < 3)
4645                         {
4646                                 /* Too small */
4647                                 for (y = y1; y < y2; y++)
4648                                 {
4649                                         for (x = x1; x < x2; x++)
4650                                         {
4651                                                 place_inner_bold(y, x);
4652                                         }
4653                                 }
4654                                 return;
4655                         }
4656
4657                         t1 = randint1(xsize - 2) + x1 + 1;
4658                         build_recursive_room(x1, y1, t1, y2, power - 2);
4659                         build_recursive_room(t1 + 1, y1, x2, y2, power - 2);
4660                         break;
4661                 }
4662                 case 3:
4663                 {
4664                         /* Try and divide horizontally */
4665                         if (ysize < 3)
4666                         {
4667                                 /* Too small */
4668                                 for (y = y1; y < y2; y++)
4669                                 {
4670                                         for (x = x1; x < x2; x++)
4671                                         {
4672                                                 place_inner_bold(y, x);
4673                                         }
4674                                 }
4675                                 return;
4676                         }
4677
4678                         t1 = randint1(ysize - 2) + y1 + 1;
4679                         build_recursive_room(x1, y1, x2, t1, power - 2);
4680                         build_recursive_room(x1, t1 + 1, x2, y2, power - 2);
4681                         break;
4682                 }
4683         }
4684 }
4685
4686
4687 /* Build a castle */
4688
4689 /* Driver routine: clear the region and call the recursive
4690 * room routine.
4691 *
4692 *This makes a vault that looks like a castle/ city in the dungeon.
4693 */
4694 static void build_castle_vault(int x0, int y0, int xsize, int ysize)
4695 {
4696         int dy, dx;
4697         int y1, x1, y2, x2;
4698         int y, x;
4699
4700         /* Pick a random room size */
4701         dy = ysize / 2 - 1;
4702         dx = xsize / 2 - 1;
4703
4704         y1 = y0 - dy;
4705         x1 = x0 - dx;
4706         y2 = y0 + dy;
4707         x2 = x0 + dx;
4708
4709         if (cheat_room) msg_print("Castle Vault");
4710
4711         /* generate the room */
4712         for (y = y1 - 1; y <= y2 + 1; y++)
4713         {
4714                 for (x = x1 - 1; x <= x2 + 1; x++)
4715                 {
4716                         cave[y][x].info |= (CAVE_ROOM | CAVE_ICKY);
4717                         /* Make everything a floor */
4718                         place_floor_bold(y, x);
4719                 }
4720         }
4721
4722         /* Make the castle */
4723         build_recursive_room(x1, y1, x2, y2, randint1(5));
4724
4725         /* Fill with monsters and treasure, low difficulty */
4726         fill_treasure(x1, x2, y1, y2, randint1(3));
4727 }
4728
4729
4730 /*
4731  * Add outer wall to a floored region
4732  * Note: no range checking is done so must be inside dungeon
4733  * This routine also stomps on doors
4734  */
4735 static void add_outer_wall(int x, int y, int light,
4736                                                                         int x1, int y1, int x2, int y2)
4737 {
4738         int i, j;
4739
4740         if (!in_bounds(y, x)) return;
4741
4742         /* hack- check to see if square has been visited before
4743         * if so, then exit (use room flag to do this) */
4744         if (cave[y][x].info & CAVE_ROOM) return;
4745
4746         /* set room flag */
4747         cave[y][x].info |= CAVE_ROOM;
4748
4749         if (is_floor_bold(y, x))
4750         {
4751                 for (i = -1; i <= 1; i++)
4752                 {
4753                         for (j = -1; j <= 1; j++)
4754                         {
4755                                 if ((x + i >= x1) && (x + i <= x2) &&
4756                                          (y + j >= y1) && (y + j <= y2))
4757                                 {
4758                                         add_outer_wall(x + i, y + j, light, x1, y1, x2, y2);
4759                                         if (light) cave[y][x].info |= CAVE_GLOW;
4760                                 }
4761                         }
4762                 }
4763         }
4764         else if (is_extra_bold(y, x))
4765         {
4766                 /* Set bounding walls */
4767                 place_outer_bold(y, x);
4768                 if (light) cave[y][x].info |= CAVE_GLOW;
4769         }
4770         else if (cave[y][x].feat == FEAT_PERM_OUTER)
4771         {
4772                 /* Set bounding walls */
4773                 if (light) cave[y][x].info |= CAVE_GLOW;
4774         }
4775 }
4776
4777
4778 /*
4779  * Hacked distance formula - gives the 'wrong' answer.
4780  * Used to build crypts
4781  */
4782 static int dist2(int x1, int y1, int x2, int y2,
4783                  int h1, int h2, int h3, int h4)
4784 {
4785         int dx, dy;
4786         dx = abs(x2 - x1);
4787         dy = abs(y2 - y1);
4788
4789         /* Basically this works by taking the normal pythagorean formula
4790          * and using an expansion to express this in a way without the
4791          * square root.  This approximate formula is then perturbed to give
4792          * the distorted results.  (I found this by making a mistake when I was
4793          * trying to fix the circular rooms.)
4794          */
4795
4796         /* h1-h4 are constants that describe the metric */
4797         if (dx >= 2 * dy) return (dx + (dy * h1) / h2);
4798         if (dy >= 2 * dx) return (dy + (dx * h1) / h2);
4799         return (((dx + dy) * 128) / 181 +
4800                 (dx * dx / (dy * h3) + dy * dy / (dx * h3)) * h4);
4801         /* 128/181 is approx. 1/sqrt(2) */
4802 }
4803
4804
4805 /*
4806  * Build target vault.
4807  * This is made by two concentric "crypts" with perpendicular
4808  * walls creating the cross-hairs.
4809  */
4810 static void build_target_vault(int x0, int y0, int xsize, int ysize)
4811 {
4812         int rad, x, y;
4813
4814         /* Make a random metric */
4815         int h1, h2, h3, h4;
4816         h1 = randint1(32) - 16;
4817         h2 = randint1(16);
4818         h3 = randint1(32);
4819         h4 = randint1(32) - 16;
4820
4821         if (cheat_room) msg_print("Target Vault");
4822
4823         /* work out outer radius */
4824         if (xsize > ysize)
4825         {
4826                 rad = ysize / 2;
4827         }
4828         else
4829         {
4830                 rad = xsize / 2;
4831         }
4832
4833         /* Make floor */
4834         for (x = x0 - rad; x <= x0 + rad; x++)
4835         {
4836                 for (y = y0 - rad; y <= y0 + rad; y++)
4837                 {
4838                         /* clear room flag */
4839                         cave[y][x].info &= ~(CAVE_ROOM);
4840
4841                         /* Vault - so is "icky" */
4842                         cave[y][x].info |= CAVE_ICKY;
4843
4844                         if (dist2(y0, x0, y, x, h1, h2, h3, h4) <= rad - 1)
4845                         {
4846                                 /* inside- so is floor */
4847                                 place_floor_bold(y, x);
4848                         }
4849                         else
4850                         {
4851                                 /* make granite outside so arena works */
4852                                 place_extra_bold(y, x);
4853                         }
4854
4855                         /* proper boundary for arena */
4856                         if (((y + rad) == y0) || ((y - rad) == y0) ||
4857                             ((x + rad) == x0) || ((x - rad) == x0))
4858                         {
4859                                 place_extra_bold(y, x);
4860                         }
4861                 }
4862         }
4863
4864         /* Find visible outer walls and set to be FEAT_OUTER */
4865         add_outer_wall(x0, y0, FALSE, x0 - rad - 1, y0 - rad - 1,
4866                        x0 + rad + 1, y0 + rad + 1);
4867
4868         /* Add inner wall */
4869         for (x = x0 - rad / 2; x <= x0 + rad / 2; x++)
4870         {
4871                 for (y = y0 - rad / 2; y <= y0 + rad / 2; y++)
4872                 {
4873                         if (dist2(y0, x0, y, x, h1, h2, h3, h4) == rad / 2)
4874                         {
4875                                 /* Make an internal wall */
4876                                 place_inner_bold(y, x);
4877                         }
4878                 }
4879         }
4880
4881         /* Add perpendicular walls */
4882         for (x = x0 - rad; x <= x0 + rad; x++)
4883         {
4884                 place_inner_bold(y0, x);
4885         }
4886
4887         for (y = y0 - rad; y <= y0 + rad; y++)
4888         {
4889                 place_inner_bold(y, x0);
4890         }
4891
4892         /* Make inner vault */
4893         for (y = y0 - 1; y <= y0 + 1; y++)
4894         {
4895                 place_inner_bold(y, x0 - 1);
4896                 place_inner_bold(y, x0 + 1);
4897         }
4898         for (x = x0 - 1; x <= x0 + 1; x++)
4899         {
4900                 place_inner_bold(y0 - 1, x);
4901                 place_inner_bold(y0 + 1, x);
4902         }
4903
4904         place_floor_bold(y0, x0);
4905
4906
4907         /* Add doors to vault */
4908         /* get two distances so can place doors relative to centre */
4909         x = (rad - 2) / 4 + 1;
4910         y = rad / 2 + x;
4911
4912         add_door(x0 + x, y0);
4913         add_door(x0 + y, y0);
4914         add_door(x0 - x, y0);
4915         add_door(x0 - y, y0);
4916         add_door(x0, y0 + x);
4917         add_door(x0, y0 + y);
4918         add_door(x0, y0 - x);
4919         add_door(x0, y0 - y);
4920
4921         /* Fill with stuff - medium difficulty */
4922         fill_treasure(x0 - rad, x0 + rad, y0 - rad, y0 + rad, randint1(3) + 3);
4923 }
4924
4925
4926 #ifdef ALLOW_CAVERNS_AND_LAKES
4927 /*
4928  * This routine uses a modified version of the lake code to make a
4929  * distribution of some terrain type over the vault.  This type
4930  * depends on the dungeon depth.
4931  *
4932  * Miniture rooms are then scattered across the vault.
4933  */
4934 static void build_elemental_vault(int x0, int y0, int xsiz, int ysiz)
4935 {
4936         int grd, roug;
4937         int c1, c2, c3;
4938         bool done = FALSE;
4939         int xsize, ysize, xhsize, yhsize, x, y, i;
4940         int type;
4941
4942
4943         if (cheat_room) msg_print("Elemental Vault");
4944
4945         /* round to make sizes even */
4946         xhsize = xsiz / 2;
4947         yhsize = ysiz / 2;
4948         xsize = xhsize * 2;
4949         ysize = yhsize * 2;
4950
4951         if (dun_level < 25)
4952         {
4953                 /* Earth vault  (Rubble) */
4954                 type = GEN_LAKE_TYPE_EARTH_VAULT;
4955         }
4956         else if (dun_level < 50)
4957         {
4958                 /* Air vault (Trees) */
4959                 type = GEN_LAKE_TYPE_AIR_VAULT;
4960         }
4961         else if (dun_level < 75)
4962         {
4963                 /* Water vault (shallow water) */
4964                 type = GEN_LAKE_TYPE_WATER_VAULT;
4965         }
4966         else
4967         {
4968                 /* Fire vault (shallow lava) */
4969                 type = GEN_LAKE_TYPE_FIRE_VAULT;
4970         }
4971
4972         while (!done)
4973         {
4974                 /* testing values for these parameters: feel free to adjust */
4975                 grd = 1 << (randint0(3));
4976
4977                 /* want average of about 16 */
4978                 roug = randint1(8) * randint1(4);
4979
4980                 /* Make up size of various componants */
4981                 /* Floor */
4982                 c3 = 2 * xsize / 3;
4983
4984                 /* Deep water/lava */
4985                 c1 = randint0(c3 / 2) + randint0(c3 / 2) - 5;
4986
4987                 /* Shallow boundary */
4988                 c2 = (c1 + c3) / 2;
4989
4990                 /* make it */
4991                 generate_hmap(y0, x0, xsize, ysize, grd, roug, c3);
4992
4993                 /* Convert to normal format+ clean up */
4994                 done = generate_lake(y0, x0, xsize, ysize, c1, c2, c3, type);
4995         }
4996
4997         /* Set icky flag because is a vault */
4998         for (x = 0; x <= xsize; x++)
4999         {
5000                 for (y = 0; y <= ysize; y++)
5001                 {
5002                         cave[y0 - yhsize + y][x0 - xhsize + x].info |= CAVE_ICKY;
5003                 }
5004         }
5005
5006         /* make a few rooms in the vault */
5007         for (i = 1; i <= (xsize * ysize) / 50; i++)
5008         {
5009                 build_small_room(x0 + randint0(xsize - 4) - xsize / 2 + 2,
5010                                  y0 + randint0(ysize - 4) - ysize / 2 + 2);
5011         }
5012
5013         /* Fill with monsters and treasure, low difficulty */
5014         fill_treasure(x0 - xhsize + 1, x0 - xhsize + xsize - 1,
5015                       y0 - yhsize + 1, y0 - yhsize + ysize - 1, randint1(5));
5016 }
5017 #endif /* ALLOW_CAVERNS_AND_LAKES */
5018
5019
5020 /*
5021  * Random vaults
5022  */
5023 static void build_type10(int by0, int bx0)
5024 {
5025         int y0, x0, xsize, ysize, vtype;
5026
5027         /* Get size */
5028         /* big enough to look good, small enough to be fairly common. */
5029         xsize = randint1(22) + 22;
5030         ysize = randint1(11) + 11;
5031
5032         /* Allocate in room_map.  If will not fit, exit */
5033         if (!room_alloc(xsize + 1, ysize + 1, FALSE, by0, bx0, &x0, &y0)) return;
5034
5035         /* Boost the rating- higher than lesser vaults and lower than greater vaults */
5036         rating += 10;
5037
5038         /* (Sometimes) Cause a special feeling */
5039         if ((dun_level <= 50) ||
5040             (randint1((dun_level - 40) * (dun_level - 40) + 1) < 400))
5041         {
5042                 good_item_flag = TRUE;
5043         }
5044
5045         /* Select type of vault */
5046 #ifdef ALLOW_CAVERNS_AND_LAKES
5047         vtype = randint1(15);
5048 #else /* ALLOW_CAVERNS_AND_LAKES */
5049         vtype = randint1(7);
5050 #endif /* ALLOW_CAVERNS_AND_LAKES */
5051
5052         switch (vtype)
5053         {
5054                 /* Build an appropriate room */
5055                 case 1: case  9: build_bubble_vault(x0, y0, xsize, ysize); break;
5056                 case 2: case 10: build_room_vault(x0, y0, xsize, ysize); break;
5057                 case 3: case 11: build_cave_vault(x0, y0, xsize, ysize); break;
5058                 case 4: case 12: build_maze_vault(x0, y0, xsize, ysize, TRUE); break;
5059                 case 5: case 13: build_mini_c_vault(x0, y0, xsize, ysize); break;
5060                 case 6: case 14: build_castle_vault(x0, y0, xsize, ysize); break;
5061                 case 7: case 15: build_target_vault(x0, y0, xsize, ysize); break;
5062 #ifdef ALLOW_CAVERNS_AND_LAKES
5063                 case 8: build_elemental_vault(x0, y0, xsize, ysize); break;
5064 #endif /* ALLOW_CAVERNS_AND_LAKES */
5065                 /* I know how to add a few more... give me some time. */
5066
5067                 /* Paranoia */
5068                 default: return;
5069         }
5070 }
5071
5072
5073 /*
5074  * Build an vertical oval room.
5075  * For every grid in the possible square, check the distance.
5076  * If it's less than the radius, make it a room square.
5077  *
5078  * When done fill from the inside to find the walls,
5079  */
5080 static void build_type11(int by0, int bx0)
5081 {
5082         int rad, x, y, x0, y0;
5083         int light = FALSE;
5084
5085         /* Occasional light */
5086         if ((randint1(dun_level) <= 15) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS)) light = TRUE;
5087
5088         rad = randint0(9);
5089
5090         /* Allocate in room_map.  If will not fit, exit */
5091         if (!room_alloc(rad * 2 + 1, rad * 2 + 1, FALSE, by0, bx0, &x0, &y0)) return;
5092
5093         /* Make circular floor */
5094         for (x = x0 - rad; x <= x0 + rad; x++)
5095         {
5096                 for (y = y0 - rad; y <= y0 + rad; y++)
5097                 {
5098                         if (distance(y0, x0, y, x) <= rad - 1)
5099                         {
5100                                 /* inside- so is floor */
5101                                 place_floor_bold(y, x);
5102                         }
5103                         else if (distance(y0, x0, y, x) <= rad + 1)
5104                         {
5105                                 /* make granite outside so arena works */
5106                                 place_extra_bold(y, x);
5107                         }
5108                 }
5109         }
5110
5111         /* Find visible outer walls and set to be FEAT_OUTER */
5112         add_outer_wall(x0, y0, light, x0 - rad, y0 - rad, x0 + rad, y0 + rad);
5113 }
5114
5115
5116 /*
5117  * Build crypt room.
5118  * For every grid in the possible square, check the (fake) distance.
5119  * If it's less than the radius, make it a room square.
5120  *
5121  * When done fill from the inside to find the walls,
5122  */
5123 static void build_type12(int by0, int bx0)
5124         {
5125         int rad, x, y, x0, y0;
5126         int light = FALSE;
5127         bool emptyflag = TRUE;
5128
5129         /* Make a random metric */
5130         int h1, h2, h3, h4;
5131         h1 = randint1(32) - 16;
5132         h2 = randint1(16);
5133         h3 = randint1(32);
5134         h4 = randint1(32) - 16;
5135
5136         /* Occasional light */
5137         if ((randint1(dun_level) <= 5) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS)) light = TRUE;
5138
5139         rad = randint1(9);
5140
5141         /* Allocate in room_map.  If will not fit, exit */
5142         if (!room_alloc(rad * 2 + 3, rad * 2 + 3, FALSE, by0, bx0, &x0, &y0)) return;
5143
5144         /* Make floor */
5145         for (x = x0 - rad; x <= x0 + rad; x++)
5146         {
5147                 for (y = y0 - rad; y <= y0 + rad; y++)
5148                 {
5149                         /* clear room flag */
5150                         cave[y][x].info &= ~(CAVE_ROOM);
5151
5152                         if (dist2(y0, x0, y, x, h1, h2, h3, h4) <= rad - 1)
5153                         {
5154                                 /* inside - so is floor */
5155                                 place_floor_bold(y, x);
5156                         }
5157                         else if (distance(y0, x0, y, x) < 3)
5158                         {
5159                                 place_floor_bold(y, x);
5160                         }
5161                         else
5162                         {
5163                                 /* make granite outside so arena works */
5164                                 place_extra_bold(y, x);
5165                         }
5166
5167                         /* proper boundary for arena */
5168                         if (((y + rad) == y0) || ((y - rad) == y0) ||
5169                             ((x + rad) == x0) || ((x - rad) == x0))
5170                         {
5171                                 place_extra_bold(y, x);
5172                         }
5173                 }
5174         }
5175
5176         /* Find visible outer walls and set to be FEAT_OUTER */
5177         add_outer_wall(x0, y0, light, x0 - rad - 1, y0 - rad - 1,
5178                        x0 + rad + 1, y0 + rad + 1);
5179
5180         /* Check to see if there is room for an inner vault */
5181         for (x = x0 - 2; x <= x0 + 2; x++)
5182         {
5183                 for (y = y0 - 2; y <= y0 + 2; y++)
5184                 {
5185                         if (!is_floor_bold(y, x))
5186                         {
5187                                 /* Wall in the way */
5188                                 emptyflag = FALSE;
5189                         }
5190                 }
5191         }
5192
5193         if (emptyflag && one_in_(2))
5194         {
5195                 /* Build the vault */
5196                 build_small_room(x0, y0);
5197
5198                 /* Place a treasure in the vault */
5199                 place_object(y0, x0, FALSE, FALSE);
5200
5201                 /* Let's guard the treasure well */
5202                 vault_monsters(y0, x0, randint0(2) + 3);
5203
5204                 /* Traps naturally */
5205                 vault_traps(y0, x0, 4, 4, randint0(3) + 2);
5206         }
5207 }
5208
5209
5210 /*
5211  * Helper function for "trapped monster pit"
5212  */
5213 static bool vault_aux_trapped_pit(int r_idx)
5214 {
5215         monster_race *r_ptr = &r_info[r_idx];
5216
5217         /* Validate the monster */
5218         if (!vault_monster_okay(r_idx)) return (FALSE);
5219
5220         /* No wall passing monster */
5221         if (r_ptr->flags2 & (RF2_PASS_WALL | RF2_KILL_WALL)) return (FALSE);
5222
5223         /* Okay */
5224         return (TRUE);
5225 }
5226
5227
5228 /*
5229  * Type 12 -- Trapped monster pits
5230  *
5231  * A trapped monster pit is a "big" room with a straight corridor in
5232  * which wall opening traps are placed, and with two "inner" rooms
5233  * containing a "collection" of monsters of a given type organized in
5234  * the room.
5235  *
5236  * The trapped monster pit appears as shown below, where the actual
5237  * monsters in each location depend on the type of the pit
5238  *
5239  *  #########################
5240  *  #                       #
5241  *  ####################### #
5242  *  #####001123454321100### #
5243  *  ###0012234567654322100# #
5244  *  ####################### #
5245  *  #           ^           #
5246  *  # #######################
5247  *  # #0012234567654322100###
5248  *  # ###001123454321100#####
5249  *  # #######################
5250  *  #                       #
5251  *  #########################
5252  *
5253  * Note that the monsters in the pit are now chosen by using "get_mon_num()"
5254  * to request 16 "appropriate" monsters, sorting them by level, and using
5255  * the "even" entries in this sorted list for the contents of the pit.
5256  *
5257  * Hack -- all of the "dragons" in a "dragon" pit must be the same "color",
5258  * which is handled by requiring a specific "breath" attack for all of the
5259  * dragons.  This may include "multi-hued" breath.  Note that "wyrms" may
5260  * be present in many of the dragon pits, if they have the proper breath.
5261  *
5262  * Note the use of the "get_mon_num_prep()" function, and the special
5263  * "get_mon_num_hook()" restriction function, to prepare the "monster
5264  * allocation table" in such a way as to optimize the selection of
5265  * "appropriate" non-unique monsters for the pit.
5266  *
5267  * Note that the "get_mon_num()" function may (rarely) fail, in which case
5268  * the pit will be empty, and will not effect the level rating.
5269  *
5270  * Note that "monster pits" will never contain "unique" monsters.
5271  */
5272 static void build_type13(int by0, int bx0)
5273 {
5274         static int placing[][3] = {
5275                 {-2, -9, 0}, {-2, -8, 0}, {-3, -7, 0}, {-3, -6, 0},
5276                 {+2, -9, 0}, {+2, -8, 0}, {+3, -7, 0}, {+3, -6, 0},
5277                 {-2, +9, 0}, {-2, +8, 0}, {-3, +7, 0}, {-3, +6, 0},
5278                 {+2, +9, 0}, {+2, +8, 0}, {+3, +7, 0}, {+3, +6, 0},
5279                 {-2, -7, 1}, {-3, -5, 1}, {-3, -4, 1}, 
5280                 {+2, -7, 1}, {+3, -5, 1}, {+3, -4, 1}, 
5281                 {-2, +7, 1}, {-3, +5, 1}, {-3, +4, 1}, 
5282                 {+2, +7, 1}, {+3, +5, 1}, {+3, +4, 1},
5283                 {-2, -6, 2}, {-2, -5, 2}, {-3, -3, 2},
5284                 {+2, -6, 2}, {+2, -5, 2}, {+3, -3, 2},
5285                 {-2, +6, 2}, {-2, +5, 2}, {-3, +3, 2},
5286                 {+2, +6, 2}, {+2, +5, 2}, {+3, +3, 2},
5287                 {-2, -4, 3}, {-3, -2, 3},
5288                 {+2, -4, 3}, {+3, -2, 3},
5289                 {-2, +4, 3}, {-3, +2, 3},
5290                 {+2, +4, 3}, {+3, +2, 3},
5291                 {-2, -3, 4}, {-3, -1, 4},
5292                 {+2, -3, 4}, {+3, -1, 4},
5293                 {-2, +3, 4}, {-3, +1, 4},
5294                 {+2, +3, 4}, {+3, +1, 4},
5295                 {-2, -2, 5}, {-3, 0, 5}, {-2, +2, 5},
5296                 {+2, -2, 5}, {+3, 0, 5}, {+2, +2, 5},
5297                 {-2, -1, 6}, {-2, +1, 6},
5298                 {+2, -1, 6}, {+2, +1, 6},
5299                 {-2, 0, 7}, {+2, 0, 7},
5300                 {0, 0, -1}
5301         };
5302
5303         int y, x, y1, x1, y2, x2, xval, yval;
5304         int i, j;
5305
5306         int what[16];
5307
5308         int align = 0;
5309
5310         cave_type *c_ptr;
5311
5312         int cur_pit_type = pick_vault_type(pit_types, d_info[dungeon_type].pit);
5313         vault_aux_type *n_ptr;
5314
5315         /* Only in Angband */
5316         if (dungeon_type != 1) return;
5317
5318         /* Try to allocate space for room. */
5319         if (!room_alloc(25, 13, TRUE, by0, bx0, &xval, &yval)) return;
5320
5321         /* No type available */
5322         if (cur_pit_type < 0) return;
5323
5324         n_ptr = &pit_types[cur_pit_type];
5325
5326         /* Process a preparation function if necessary */
5327         if (n_ptr->prep_func) (*(n_ptr->prep_func))();
5328
5329         /* Large room */
5330         y1 = yval - 5;
5331         y2 = yval + 5;
5332         x1 = xval - 11;
5333         x2 = xval + 11;
5334
5335         /* Fill with inner walls */
5336         for (y = y1 - 1; y <= y2 + 1; y++)
5337         {
5338                 for (x = x1 - 1; x <= x2 + 1; x++)
5339                 {
5340                         c_ptr = &cave[y][x];
5341                         place_inner_grid(c_ptr);
5342                         c_ptr->info |= (CAVE_ROOM);
5343                 }
5344         }
5345
5346         /* Place the floor area 1 */
5347         for (x = x1 + 3; x <= x2 - 3; x++)
5348         {
5349                 c_ptr = &cave[yval-2][x];
5350                 place_floor_grid(c_ptr);
5351                 add_cave_info(yval-2, x, CAVE_ICKY);
5352
5353                 c_ptr = &cave[yval+2][x];
5354                 place_floor_grid(c_ptr);
5355                 add_cave_info(yval+2, x, CAVE_ICKY);
5356         }
5357
5358         /* Place the floor area 2 */
5359         for (x = x1 + 5; x <= x2 - 5; x++)
5360         {
5361                 c_ptr = &cave[yval-3][x];
5362                 place_floor_grid(c_ptr);
5363                 add_cave_info(yval-3, x, CAVE_ICKY);
5364
5365                 c_ptr = &cave[yval+3][x];
5366                 place_floor_grid(c_ptr);
5367                 add_cave_info(yval+3, x, CAVE_ICKY);
5368         }
5369
5370         /* Corridor */
5371         for (x = x1; x <= x2; x++)
5372         {
5373                 c_ptr = &cave[yval][x];
5374                 place_floor_grid(c_ptr);
5375                 c_ptr = &cave[y1][x];
5376                 place_floor_grid(c_ptr);
5377                 c_ptr = &cave[y2][x];
5378                 place_floor_grid(c_ptr);
5379         }
5380
5381         /* Place the outer walls */
5382         for (y = y1 - 1; y <= y2 + 1; y++)
5383         {
5384                 c_ptr = &cave[y][x1 - 1];
5385                 place_outer_grid(c_ptr);
5386                 c_ptr = &cave[y][x2 + 1];
5387                 place_outer_grid(c_ptr);
5388         }
5389         for (x = x1 - 1; x <= x2 + 1; x++)
5390         {
5391                 c_ptr = &cave[y1 - 1][x];
5392                 place_outer_grid(c_ptr);
5393                 c_ptr = &cave[y2 + 1][x];
5394                 place_outer_grid(c_ptr);
5395         }
5396
5397         /* Random corridor */
5398         if (one_in_(2))
5399         {
5400                 for (y = y1; y <= yval; y++)
5401                 {
5402                         place_floor_bold(y, x2);
5403                         place_solid_bold(y, x1-1);
5404                 }
5405                 for (y = yval; y <= y2 + 1; y++)
5406                 {
5407                         place_floor_bold(y, x1);
5408                         place_solid_bold(y, x2+1);
5409                 }
5410         }
5411         else
5412         {
5413                 for (y = yval; y <= y2 + 1; y++)
5414                 {
5415                         place_floor_bold(y, x1);
5416                         place_solid_bold(y, x2+1);
5417                 }
5418                 for (y = y1; y <= yval; y++)
5419                 {
5420                         place_floor_bold(y, x2);
5421                         place_solid_bold(y, x1-1);
5422                 }
5423         }
5424
5425         /* Place the wall open trap */
5426         cave[yval][xval].mimic = cave[yval][xval].feat;
5427         cave[yval][xval].feat = FEAT_TRAP_OPEN;
5428
5429         /* Prepare allocation table */
5430         get_mon_num_prep(n_ptr->hook_func, vault_aux_trapped_pit);
5431
5432         /* Pick some monster types */
5433         for (i = 0; i < 16; i++)
5434         {
5435                 int r_idx = 0, attempts = 100;
5436
5437                 while (attempts--)
5438                 {
5439                         /* Get a (hard) monster type */
5440                         r_idx = get_mon_num(dun_level + 0);
5441
5442                         /* Decline incorrect alignment */
5443                         if (((align < 0) && (r_info[r_idx].flags3 & RF3_GOOD)) ||
5444                                  ((align > 0) && (r_info[r_idx].flags3 & RF3_EVIL)))
5445                         {
5446                                 continue;
5447                         }
5448
5449                         /* Accept this monster */
5450                         break;
5451                 }
5452
5453                 /* Notice failure */
5454                 if (!r_idx || !attempts) return;
5455
5456                 /* Note the alignment */
5457                 if (r_info[r_idx].flags3 & RF3_GOOD) align++;
5458                 else if (r_info[r_idx].flags3 & RF3_EVIL) align--;
5459
5460                 what[i] = r_idx;
5461         }
5462
5463         /* Sort the entries */
5464         for (i = 0; i < 16 - 1; i++)
5465         {
5466                 /* Sort the entries */
5467                 for (j = 0; j < 16 - 1; j++)
5468                 {
5469                         int i1 = j;
5470                         int i2 = j + 1;
5471
5472                         int p1 = r_info[what[i1]].level;
5473                         int p2 = r_info[what[i2]].level;
5474
5475                         /* Bubble */
5476                         if (p1 > p2)
5477                         {
5478                                 int tmp = what[i1];
5479                                 what[i1] = what[i2];
5480                                 what[i2] = tmp;
5481                         }
5482                 }
5483         }
5484
5485         /* Message */
5486         if (cheat_room)
5487         {
5488                 /* Room type */
5489 #ifdef JP
5490                 msg_format("%s%s¤Î櫥ԥåÈ", n_ptr->name, pit_subtype_string(cur_pit_type, FALSE));
5491 #else
5492                 msg_format("Trapped monster pit (%s%s)", n_ptr->name, pit_subtype_string(cur_pit_type, FALSE));
5493 #endif
5494         }
5495
5496         /* Select the entries */
5497         for (i = 0; i < 8; i++)
5498         {
5499                 /* Every other entry */
5500                 what[i] = what[i * 2];
5501
5502                 if (cheat_hear)
5503                 {
5504                         /* Message */
5505                         msg_print(r_name + r_info[what[i]].name);
5506                 }
5507         }
5508
5509         /* Increase the level rating */
5510         rating += 20;
5511
5512         /* (Sometimes) Cause a "special feeling" (for "Monster Pits") */
5513         if ((dun_level <= 40) && (randint1(dun_level * dun_level + 50) < 300))
5514         {
5515                 good_item_flag = TRUE;
5516         }
5517
5518
5519         for (i = 0; placing[i][2] >= 0; i++)
5520         {
5521                 y = yval + placing[i][0];
5522                 x = xval + placing[i][1];
5523                 place_monster_aux(0, y, x, what[placing[i][2]], PM_NO_KAGE);
5524         }
5525 }
5526
5527
5528 /*
5529  * Type 14 -- trapped rooms
5530  *
5531  * A special trap is placed at center of the room
5532  */
5533 static void build_type14(int by0, int bx0)
5534 {
5535         int y, x, y2, x2, yval, xval;
5536         int y1, x1, xsize, ysize;
5537
5538         bool light;
5539
5540         cave_type *c_ptr;
5541         byte trap;
5542
5543         /* Pick a room size */
5544         y1 = randint1(4);
5545         x1 = randint1(11);
5546         y2 = randint1(3);
5547         x2 = randint1(11);
5548
5549         xsize = x1 + x2 + 1;
5550         ysize = y1 + y2 + 1;
5551
5552         /* Try to allocate space for room.  If fails, exit */
5553         if (!room_alloc(xsize + 2, ysize + 2, FALSE, by0, bx0, &xval, &yval)) return;
5554
5555         /* Choose lite or dark */
5556         light = ((dun_level <= randint1(25)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS));
5557
5558
5559         /* Get corner values */
5560         y1 = yval - ysize / 2;
5561         x1 = xval - xsize / 2;
5562         y2 = yval + (ysize - 1) / 2;
5563         x2 = xval + (xsize - 1) / 2;
5564
5565
5566         /* Place a full floor under the room */
5567         for (y = y1 - 1; y <= y2 + 1; y++)
5568         {
5569                 for (x = x1 - 1; x <= x2 + 1; x++)
5570                 {
5571                         c_ptr = &cave[y][x];
5572                         place_floor_grid(c_ptr);
5573                         c_ptr->info |= (CAVE_ROOM);
5574                         if (light) c_ptr->info |= (CAVE_GLOW);
5575                 }
5576         }
5577
5578         /* Walls around the room */
5579         for (y = y1 - 1; y <= y2 + 1; y++)
5580         {
5581                 c_ptr = &cave[y][x1 - 1];
5582                 place_outer_grid(c_ptr);
5583                 c_ptr = &cave[y][x2 + 1];
5584                 place_outer_grid(c_ptr);
5585         }
5586         for (x = x1 - 1; x <= x2 + 1; x++)
5587         {
5588                 c_ptr = &cave[y1 - 1][x];
5589                 place_outer_grid(c_ptr);
5590                 c_ptr = &cave[y2 + 1][x];
5591                 place_outer_grid(c_ptr);
5592         }
5593
5594         if (dun_level < 30 + randint1(30))
5595                 trap = FEAT_TRAP_PIRANHA;
5596         else
5597                 trap = FEAT_TRAP_ARMAGEDDON;
5598
5599         /* Place a special trap */
5600         c_ptr = &cave[rand_spread(yval, ysize/4)][rand_spread(xval, xsize/4)];
5601         c_ptr->mimic = c_ptr->feat;
5602         c_ptr->feat = trap;
5603
5604         /* Message */
5605         if (cheat_room)
5606         {
5607 #ifdef JP
5608                 msg_format("%s¤ÎÉô²°", f_name + f_info[trap].name);
5609 #else
5610                 msg_format("Room of %s", f_name + f_info[trap].name);
5611 #endif
5612         }
5613 }
5614
5615
5616 /*
5617  * Attempt to build a room of the given type at the given block
5618  *
5619  * Note that we restrict the number of "crowded" rooms to reduce
5620  * the chance of overflowing the monster list during level creation.
5621  */
5622 bool room_build(int by0, int bx0, int typ)
5623 {
5624         /* Restrict level */
5625         if ((dun_level < roomdep[typ]) && !ironman_rooms) return FALSE;
5626
5627         /* Restrict "crowded" rooms */
5628         if ((dun->crowded >= 2) && ((typ == ROOM_BUILD_TYPE_NEST) ||
5629                 (typ == ROOM_BUILD_TYPE_PIT) || (typ == ROOM_BUILD_TYPE_TRAP_PIT))) return FALSE;
5630
5631         /* Build a room */
5632         switch (typ)
5633         {
5634         /* Build an appropriate room */
5635         case ROOM_BUILD_TYPE_NORMAL:        build_type1(by0, bx0); break;
5636         case ROOM_BUILD_TYPE_OVERLAP:       build_type2(by0, bx0); break;
5637         case ROOM_BUILD_TYPE_CROSS:         build_type3(by0, bx0); break;
5638         case ROOM_BUILD_TYPE_INNER_FEAT:    build_type4(by0, bx0); break;
5639         case ROOM_BUILD_TYPE_NEST:          build_type5(by0, bx0, FALSE); break;
5640         case ROOM_BUILD_TYPE_PIT:           build_type6(by0, bx0, FALSE); break;
5641         case ROOM_BUILD_TYPE_LESSER_VAULT:  build_type7(by0, bx0); break;
5642         case ROOM_BUILD_TYPE_GREATER_VAULT: build_type8(by0, bx0); break;
5643         case ROOM_BUILD_TYPE_FRACAVE:       build_type9(by0, bx0); break;
5644         case ROOM_BUILD_TYPE_RANDOM_VAULT:  build_type10(by0, bx0); break;
5645         case ROOM_BUILD_TYPE_OVAL:          build_type11(by0, bx0); break;
5646         case ROOM_BUILD_TYPE_CRYPT:         build_type12(by0, bx0); break;
5647         case ROOM_BUILD_TYPE_TRAP_PIT:      build_type13(by0, bx0); break;
5648         case ROOM_BUILD_TYPE_TRAP:          build_type14(by0, bx0); break;
5649
5650         /* Paranoia */
5651         default: return FALSE;
5652         }
5653
5654         return TRUE;
5655 }