OSDN Git Service

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