OSDN Git Service

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