OSDN Git Service

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