OSDN Git Service

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