OSDN Git Service

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