OSDN Git Service

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