3 * Purpose: make rooms. Used by generate.c when creating dungeons.
7 * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke
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.
21 * [from SAngband (originally from OAngband)]
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-
28 * Level 101 and below use the values for level 100.
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.
35 static room_info_type room_info_normal[ROOM_T_MAX] =
38 /* 0 10 20 30 40 50 60 70 80 90 100 min limit */
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 */
59 /* Build rooms in descending order of difficulty. */
60 static byte room_build_order[ROOM_T_MAX] = {
80 static void place_locked_door(int y, int x)
82 if (d_info[dungeon_type].flags1 & DF1_NO_DOORS)
84 place_floor_bold(y, x);
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);
94 static void place_secret_door(int y, int x, int type)
96 if (d_info[dungeon_type].flags1 & DF1_NO_DOORS)
98 place_floor_bold(y, x);
102 cave_type *c_ptr = &cave[y][x];
104 if (type == DOOR_DEFAULT)
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);
111 /* Create secret door */
112 place_closed_door(y, x, type);
114 if (type != DOOR_CURTAIN)
116 /* Hide by inner wall because this is used in rooms only */
117 c_ptr->mimic = feat_wall_inner;
119 /* Floor type terrain cannot hide a door */
120 if (feat_supports_los(c_ptr->mimic) && !feat_supports_los(c_ptr->feat))
122 if (have_flag(f_info[c_ptr->mimic].flags, FF_MOVE) || have_flag(f_info[c_ptr->mimic].flags, FF_CAN_FLY))
124 c_ptr->feat = one_in_(2) ? c_ptr->mimic : floor_type[randint0(100)];
130 c_ptr->info &= ~(CAVE_FLOOR);
131 delete_monster(y, x);
136 * This funtion makes a very small room centred at (x0, y0)
137 * This is used in crypts, and random elemental vaults.
139 * Note - this should be used only on allocated regions
140 * within another room.
142 static void build_small_room(int x0, int y0)
146 for (y = y0 - 1; y <= y0 + 1; y++)
148 place_inner_bold(y, x0 - 1);
149 place_inner_bold(y, x0 + 1);
152 for (x = x0 - 1; x <= x0 + 1; x++)
154 place_inner_bold(y0 - 1, x);
155 place_inner_bold(y0 + 1, x);
158 /* Place a secret door on one side */
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;
167 /* Clear mimic type */
168 cave[y0][x0].mimic = 0;
170 /* Add inner open space */
171 place_floor_bold(y0, x0);
176 * This function tunnels around a room if
177 * it will cut off part of a cave system.
179 static void check_room_boundary(int x1, int y1, int x2, int y2)
182 bool old_is_floor, new_is_floor;
188 old_is_floor = get_is_floor(x1 - 1, y1);
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.
196 /* Above the top boundary */
197 for (x = x1; x <= x2; x++)
199 new_is_floor = get_is_floor(x, y1 - 1);
201 /* Increment counter if they are different */
202 if (new_is_floor != old_is_floor) count++;
204 old_is_floor = new_is_floor;
208 for (y = y1; y <= y2; y++)
210 new_is_floor = get_is_floor(x2 + 1, y);
212 /* increment counter if they are different */
213 if (new_is_floor != old_is_floor) count++;
215 old_is_floor = new_is_floor;
218 /* Bottom boundary */
219 for (x = x2; x >= x1; x--)
221 new_is_floor = get_is_floor(x, y2 + 1);
223 /* increment counter if they are different */
224 if (new_is_floor != old_is_floor) count++;
226 old_is_floor = new_is_floor;
230 for (y = y2; y >= y1; y--)
232 new_is_floor = get_is_floor(x1 - 1, y);
234 /* increment counter if they are different */
235 if (new_is_floor != old_is_floor) count++;
237 old_is_floor = new_is_floor;
240 /* If all the same, or only one connection exit. */
241 if (count <= 2) return;
244 /* Tunnel around the room so to prevent problems with caves */
245 for (y = y1; y <= y2; y++)
247 for (x = x1; x <= x2; x++)
256 * Helper function for find_space().
258 * Is this a good location?
260 static bool find_space_aux(int blocks_high, int blocks_wide, int block_y, int block_x)
262 int by1, bx1, by2, bx2, by, bx;
264 /* Itty-bitty rooms must shift about within their rectangle */
267 if ((blocks_wide == 2) && (block_x % 3) == 2)
271 /* Rooms with width divisible by 3 must be fitted to a rectangle. */
272 else if ((blocks_wide % 3) == 0)
274 /* Must be aligned to the left edge of a 11x33 rectangle. */
275 if ((block_x % 3) != 0)
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.
285 /* Shift towards left edge of dungeon. */
286 if (block_x + (blocks_wide / 2) <= dun->col_rooms / 2)
288 if (((block_x % 3) == 2) && ((blocks_wide % 3) == 2))
290 if ((block_x % 3) == 1)
294 /* Shift toward right edge of dungeon. */
297 if (((block_x % 3) == 2) && ((blocks_wide % 3) == 2))
299 if ((block_x % 3) == 1)
307 by2 = block_y + blocks_high;
308 bx2 = block_x + blocks_wide;
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;
314 /* Verify available space */
315 for (by = by1; by < by2; by++)
317 for (bx = bx1; bx < bx2; bx++)
319 if (dun->room_map[by][bx])
326 /* This location is okay */
332 * Find a good spot for the next room. -LM-
334 * Find and allocate a free space in the dungeon large enough to hold
335 * the room calling this function.
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.
341 * Be careful to include the edges of the room in height and width!
343 * Return TRUE and values for the center of the room if all went well.
344 * Otherwise, return FALSE.
346 static bool find_space(int *y, int *x, int height, int width)
348 int candidates, pick;
349 int by, bx, by1, bx1, by2, bx2;
350 int block_y = 0, block_x = 0;
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);
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;
364 /* Count the number of valid places */
365 for (block_y = dun->row_rooms - blocks_high; block_y >= 0; block_y--)
367 for (block_x = dun->col_rooms - blocks_wide; block_x >= 0; block_x--)
369 if (find_space_aux(blocks_high, blocks_wide, block_y, block_x))
371 /* Find a valid place */
384 if (!(d_info[dungeon_type].flags1 & DF1_NO_CAVE))
386 /* Choose a random one */
387 pick = randint1(candidates);
390 /* NO_CAVE dungeon (Castle) */
393 /* Always choose the center one */
394 pick = candidates/2 + 1;
397 /* Pick up the choosen location */
398 for (block_y = dun->row_rooms - blocks_high; block_y >= 0; block_y--)
400 for (block_x = dun->col_rooms - blocks_wide; block_x >= 0; block_x--)
402 if (find_space_aux(blocks_high, blocks_wide, block_y, block_x))
406 /* This one is picked? */
417 by2 = block_y + blocks_high;
418 bx2 = block_x + blocks_wide;
421 * It is *extremely* important that the following calculation
422 * be *exactly* correct to prevent memory errors
425 /* Acquire the location of the room */
426 (*y) = ((by1 + by2) * BLOCK_HGT) / 2;
427 (*x) = ((bx1 + bx2) * BLOCK_WID) / 2;
429 /* Save the room location */
430 if (dun->cent_n < CENT_MAX)
432 dun->cent[dun->cent_n].y = *y;
433 dun->cent[dun->cent_n].x = *x;
437 /* Reserve some blocks. */
438 for (by = by1; by < by2; by++)
440 for (bx = bx1; bx < bx2; bx++)
442 dun->room_map[by][bx] = TRUE;
448 * Hack- See if room will cut off a cavern.
450 * If so, fix by tunneling outside the room in such a
451 * way as to connect the caves.
453 check_room_boundary(*x - width / 2 - 1, *y - height / 2 - 1, *x + (width - 1) / 2 + 1, *y + (height - 1) / 2 + 1);
463 * Room building routines.
469 * 4 -- large room with features
473 * 8 -- greater vaults
475 * 10 -- random vaults
476 * 11 -- circular rooms
478 * 13 -- trapped monster pits
481 * 16 -- underground arcade
486 * Type 1 -- normal rectangular rooms
488 static bool build_type1(void)
490 int y, x, y2, x2, yval, xval;
491 int y1, x1, xsize, ysize;
497 bool curtain = (d_info[dungeon_type].flags1 & DF1_CURTAIN) &&
498 one_in_((d_info[dungeon_type].flags1 & DF1_NO_CAVE) ? 48 : 512);
500 /* Pick a room size */
509 /* Find and reserve some space in the dungeon. Get center of room. */
510 if (!find_space(&yval, &xval, ysize + 2, xsize + 2))
512 /* Limit to the minimum room size, and retry */
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;
525 /* Choose lite or dark */
526 light = ((dun_level <= randint1(25)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS));
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;
536 /* Place a full floor under the room */
537 for (y = y1 - 1; y <= y2 + 1; y++)
539 for (x = x1 - 1; x <= x2 + 1; x++)
542 place_floor_grid(c_ptr);
543 c_ptr->info |= (CAVE_ROOM);
544 if (light) c_ptr->info |= (CAVE_GLOW);
548 /* Walls around the room */
549 for (y = y1 - 1; y <= y2 + 1; y++)
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);
556 for (x = x1 - 1; x <= x2 + 1; x++)
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);
565 /* Hack -- Occasional curtained room */
566 if (curtain && (y2 - y1 > 2) && (x2 - x1 > 2))
568 for (y = y1; y <= y2; y++)
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);
577 for (x = x1; x <= x2; x++)
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);
589 /* Hack -- Occasional pillar room */
592 for (y = y1; y <= y2; y += 2)
594 for (x = x1; x <= x2; x += 2)
597 place_inner_grid(c_ptr);
602 /* Hack -- Occasional room with four pillars */
603 else if (one_in_(20))
605 if ((y1 + 4 < y2) && (x1 + 4 < x2))
607 c_ptr = &cave[y1 + 1][x1 + 1];
608 place_inner_grid(c_ptr);
610 c_ptr = &cave[y1 + 1][x2 - 1];
611 place_inner_grid(c_ptr);
613 c_ptr = &cave[y2 - 1][x1 + 1];
614 place_inner_grid(c_ptr);
616 c_ptr = &cave[y2 - 1][x2 - 1];
617 place_inner_grid(c_ptr);
621 /* Hack -- Occasional ragged-edge room */
622 else if (one_in_(50))
624 for (y = y1 + 2; y <= y2 - 2; y += 2)
626 c_ptr = &cave[y][x1];
627 place_inner_grid(c_ptr);
628 c_ptr = &cave[y][x2];
629 place_inner_grid(c_ptr);
631 for (x = x1 + 2; x <= x2 - 2; x += 2)
633 c_ptr = &cave[y1][x];
634 place_inner_grid(c_ptr);
635 c_ptr = &cave[y2][x];
636 place_inner_grid(c_ptr);
639 /* Hack -- Occasional divided room */
640 else if (one_in_(50))
642 bool curtain2 = (d_info[dungeon_type].flags1 & DF1_CURTAIN) &&
643 one_in_((d_info[dungeon_type].flags1 & DF1_NO_CAVE) ? 2 : 128);
645 if (randint1(100) < 50)
647 /* Horizontal wall */
648 for (x = x1; x <= x2; x++)
650 place_inner_bold(yval, x);
651 if (curtain2) cave[yval][x].feat = feat_door[DOOR_CURTAIN].closed;
654 /* Prevent edge of wall from being tunneled */
655 place_solid_bold(yval, x1 - 1);
656 place_solid_bold(yval, x2 + 1);
661 for (y = y1; y <= y2; y++)
663 place_inner_bold(y, xval);
664 if (curtain2) cave[y][xval].feat = feat_door[DOOR_CURTAIN].closed;
667 /* Prevent edge of wall from being tunneled */
668 place_solid_bold(y1 - 1, xval);
669 place_solid_bold(y2 + 1, xval);
672 place_random_door(yval, xval, TRUE);
673 if (curtain2) cave[yval][xval].feat = feat_door[DOOR_CURTAIN].closed;
681 * Type 2 -- Overlapping rectangular rooms
683 static bool build_type2(void)
685 int y, x, xval, yval;
686 int y1a, x1a, y2a, x2a;
687 int y1b, x1b, y2b, x2b;
691 /* Find and reserve some space in the dungeon. Get center of room. */
692 if (!find_space(&yval, &xval, 11, 25)) return FALSE;
694 /* Choose lite or dark */
695 light = ((dun_level <= randint1(25)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS));
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);
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);
710 /* Place a full floor for room "a" */
711 for (y = y1a - 1; y <= y2a + 1; y++)
713 for (x = x1a - 1; x <= x2a + 1; x++)
716 place_floor_grid(c_ptr);
717 c_ptr->info |= (CAVE_ROOM);
718 if (light) c_ptr->info |= (CAVE_GLOW);
722 /* Place a full floor for room "b" */
723 for (y = y1b - 1; y <= y2b + 1; y++)
725 for (x = x1b - 1; x <= x2b + 1; x++)
728 place_floor_grid(c_ptr);
729 c_ptr->info |= (CAVE_ROOM);
730 if (light) c_ptr->info |= (CAVE_GLOW);
735 /* Place the walls around room "a" */
736 for (y = y1a - 1; y <= y2a + 1; y++)
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);
743 for (x = x1a - 1; x <= x2a + 1; x++)
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);
751 /* Place the walls around room "b" */
752 for (y = y1b - 1; y <= y2b + 1; y++)
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);
759 for (x = x1b - 1; x <= x2b + 1; x++)
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);
769 /* Replace the floor for room "a" */
770 for (y = y1a; y <= y2a; y++)
772 for (x = x1a; x <= x2a; x++)
775 place_floor_grid(c_ptr);
779 /* Replace the floor for room "b" */
780 for (y = y1b; y <= y2b; y++)
782 for (x = x1b; x <= x2b; x++)
785 place_floor_grid(c_ptr);
795 * Type 3 -- Cross shaped rooms
797 * Builds a room at a row, column coordinate
799 * Room "a" runs north/south, and Room "b" runs east/east
800 * So the "central pillar" runs from x1a, y1b to x2a, y2b.
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.
806 static bool build_type3(void)
808 int y, x, dy, dx, wy, wx;
809 int y1a, x1a, y2a, x2a;
810 int y1b, x1b, y2b, x2b;
816 /* Find and reserve some space in the dungeon. Get center of room. */
817 if (!find_space(&yval, &xval, 11, 25)) return FALSE;
820 /* Choose lite or dark */
821 light = ((dun_level <= randint1(25)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS));
823 /* For now, always 3x3 */
826 /* Pick max vertical size (at most 4) */
827 dy = rand_range(3, 4);
829 /* Pick max horizontal size (at most 15) */
830 dx = rand_range(3, 11);
833 /* Determine extents of the north/south room */
839 /* Determine extents of the east/west room */
846 /* Place a full floor for room "a" */
847 for (y = y1a - 1; y <= y2a + 1; y++)
849 for (x = x1a - 1; x <= x2a + 1; x++)
852 place_floor_grid(c_ptr);
853 c_ptr->info |= (CAVE_ROOM);
854 if (light) c_ptr->info |= (CAVE_GLOW);
858 /* Place a full floor for room "b" */
859 for (y = y1b - 1; y <= y2b + 1; y++)
861 for (x = x1b - 1; x <= x2b + 1; x++)
864 place_floor_grid(c_ptr);
865 c_ptr->info |= (CAVE_ROOM);
866 if (light) c_ptr->info |= (CAVE_GLOW);
871 /* Place the walls around room "a" */
872 for (y = y1a - 1; y <= y2a + 1; y++)
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);
879 for (x = x1a - 1; x <= x2a + 1; x++)
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);
887 /* Place the walls around room "b" */
888 for (y = y1b - 1; y <= y2b + 1; y++)
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);
895 for (x = x1b - 1; x <= x2b + 1; x++)
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);
904 /* Replace the floor for room "a" */
905 for (y = y1a; y <= y2a; y++)
907 for (x = x1a; x <= x2a; x++)
910 place_floor_grid(c_ptr);
914 /* Replace the floor for room "b" */
915 for (y = y1b; y <= y2b; y++)
917 for (x = x1b; x <= x2b; x++)
920 place_floor_grid(c_ptr);
926 /* Special features (3/4) */
929 /* Large solid middle pillar */
932 for (y = y1b; y <= y2b; y++)
934 for (x = x1a; x <= x2a; x++)
937 place_inner_grid(c_ptr);
943 /* Inner treasure vault */
946 /* Build the vault */
947 for (y = y1b; y <= y2b; y++)
949 c_ptr = &cave[y][x1a];
950 place_inner_grid(c_ptr);
951 c_ptr = &cave[y][x2a];
952 place_inner_grid(c_ptr);
954 for (x = x1a; x <= x2a; x++)
956 c_ptr = &cave[y1b][x];
957 place_inner_grid(c_ptr);
958 c_ptr = &cave[y2b][x];
959 place_inner_grid(c_ptr);
962 /* Place a secret door on the inner room */
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;
971 /* Place a treasure in the vault */
972 place_object(yval, xval, 0L);
974 /* Let's guard the treasure well */
975 vault_monsters(yval, xval, randint0(2) + 3);
977 /* Traps naturally */
978 vault_traps(yval, xval, 4, 4, randint0(3) + 2);
986 /* Occasionally pinch the center shut */
989 /* Pinch the east/west sides */
990 for (y = y1b; y <= y2b; y++)
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);
999 /* Pinch the north/south sides */
1000 for (x = x1a; x <= x2a; x++)
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);
1009 /* Sometimes shut using secret doors */
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);
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);
1023 /* Occasionally put a "plus" in the center */
1024 else if (one_in_(3))
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);
1038 /* Occasionally put a pillar in the center */
1039 else if (one_in_(3))
1041 c_ptr = &cave[yval][xval];
1042 place_inner_grid(c_ptr);
1054 * Type 4 -- Large room with inner features
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
1063 static bool build_type4(void)
1066 int y2, x2, tmp, yval, xval;
1071 /* Find and reserve some space in the dungeon. Get center of room. */
1072 if (!find_space(&yval, &xval, 11, 25)) return FALSE;
1074 /* Choose lite or dark */
1075 light = ((dun_level <= randint1(25)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS));
1083 /* Place a full floor under the room */
1084 for (y = y1 - 1; y <= y2 + 1; y++)
1086 for (x = x1 - 1; x <= x2 + 1; x++)
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);
1096 for (y = y1 - 1; y <= y2 + 1; y++)
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);
1103 for (x = x1 - 1; x <= x2 + 1; x++)
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);
1112 /* The inner room */
1118 /* The inner walls */
1119 for (y = y1 - 1; y <= y2 + 1; y++)
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);
1126 for (x = x1 - 1; x <= x2 + 1; x++)
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);
1135 /* Inner room variations */
1136 switch (randint1(5))
1138 /* Just an inner room with a monster */
1141 /* Place a secret door */
1142 switch (randint1(4))
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;
1150 /* Place a monster in the room */
1151 vault_monsters(yval, xval, 1);
1156 /* Treasure Vault (with a door) */
1159 /* Place a secret door */
1160 switch (randint1(4))
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;
1168 /* Place another inner room */
1169 for (y = yval - 1; y <= yval + 1; y++)
1171 for (x = xval - 1; x <= xval + 1; x++)
1173 if ((x == xval) && (y == yval)) continue;
1174 c_ptr = &cave[y][x];
1175 place_inner_grid(c_ptr);
1179 /* Place a locked door on the inner room */
1180 switch (randint1(4))
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;
1188 /* Monsters to guard the "treasure" */
1189 vault_monsters(yval, xval, randint1(3) + 2);
1192 if (randint0(100) < 80)
1194 place_object(yval, xval, 0L);
1200 place_random_stairs(yval, xval);
1203 /* Traps to protect the treasure */
1204 vault_traps(yval, xval, 4, 10, 2 + randint1(3));
1209 /* Inner pillar(s). */
1212 /* Place a secret door */
1213 switch (randint1(4))
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;
1221 /* Large Inner Pillar */
1222 for (y = yval - 1; y <= yval + 1; y++)
1224 for (x = xval - 1; x <= xval + 1; x++)
1226 c_ptr = &cave[y][x];
1227 place_inner_grid(c_ptr);
1231 /* Occasionally, two more Large Inner Pillars */
1235 for (y = yval - 1; y <= yval + 1; y++)
1237 for (x = xval - 5 - tmp; x <= xval - 3 - tmp; x++)
1239 c_ptr = &cave[y][x];
1240 place_inner_grid(c_ptr);
1242 for (x = xval + 3 + tmp; x <= xval + 5 + tmp; x++)
1244 c_ptr = &cave[y][x];
1245 place_inner_grid(c_ptr);
1250 /* Occasionally, some Inner rooms */
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);
1257 /* Long horizontal walls */
1258 for (x = xval - 5; x <= xval + 5; x++)
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);
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);
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);
1277 vault_monsters(yval, xval - 2, randint1(2));
1278 vault_monsters(yval, xval + 2, randint1(2));
1281 if (one_in_(3)) place_object(yval, xval - 2, 0L);
1282 if (one_in_(3)) place_object(yval, xval + 2, 0L);
1291 /* Place a secret door */
1292 switch (randint1(4))
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;
1300 /* Maze (really a checkerboard) */
1301 for (y = y1; y <= y2; y++)
1303 for (x = x1; x <= x2; x++)
1307 c_ptr = &cave[y][x];
1308 place_inner_grid(c_ptr);
1313 /* Monsters just love mazes. */
1314 vault_monsters(yval, xval - 5, randint1(3));
1315 vault_monsters(yval, xval + 5, randint1(3));
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));
1321 /* Mazes should have some treasure too. */
1322 vault_objects(yval, xval, 3);
1327 /* Four small rooms. */
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);
1335 for (y = y1; y <= y2; y++)
1337 c_ptr = &cave[y][xval];
1338 place_inner_grid(c_ptr);
1340 for (x = x1; x <= x2; x++)
1342 c_ptr = &cave[yval][x];
1343 place_inner_grid(c_ptr);
1346 /* Doors into the rooms */
1347 if (randint0(100) < 50)
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);
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);
1364 /* Treasure, centered at the center of the cross */
1365 vault_objects(yval, xval, 2 + randint1(2));
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));
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
1386 * None of the pits/nests are allowed to include "unique" monsters.
1391 * Monster validation macro
1393 * Line 1 -- forbid town monsters
1394 * Line 2 -- forbid uniques
1395 * Line 3 -- forbid aquatic monsters
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))
1405 /* Race index for "monster pit (clone)" */
1406 static int vault_aux_race;
1408 /* Race index for "monster pit (symbol clone)" */
1409 static char vault_aux_char;
1411 /* Breath mask for "monster pit (dragon)" */
1412 static u32b vault_aux_dragon_mask4;
1416 * Helper monster selection function
1418 static bool vault_aux_simple(int r_idx)
1421 return (vault_monster_okay(r_idx));
1426 * Helper function for "monster nest (jelly)"
1428 static bool vault_aux_jelly(int r_idx)
1430 monster_race *r_ptr = &r_info[r_idx];
1432 /* Validate the monster */
1433 if (!vault_monster_okay(r_idx)) return (FALSE);
1435 if ((r_ptr->flags2 & RF2_KILL_BODY) && !(r_ptr->flags1 & RF1_NEVER_BLOW)) return (FALSE);
1437 /* Also decline evil jellies (like death molds and shoggoths) */
1438 if (r_ptr->flags3 & (RF3_EVIL)) return (FALSE);
1440 /* Require icky thing, jelly, mold, or mushroom */
1441 if (!my_strchr("ijm,", r_ptr->d_char)) return (FALSE);
1449 * Helper function for "monster nest (animal)"
1451 static bool vault_aux_animal(int r_idx)
1453 monster_race *r_ptr = &r_info[r_idx];
1455 /* Validate the monster */
1456 if (!vault_monster_okay(r_idx)) return (FALSE);
1458 /* Require "animal" flag */
1459 if (!(r_ptr->flags3 & (RF3_ANIMAL))) return (FALSE);
1467 * Helper function for "monster nest (undead)"
1469 static bool vault_aux_undead(int r_idx)
1471 monster_race *r_ptr = &r_info[r_idx];
1473 /* Validate the monster */
1474 if (!vault_monster_okay(r_idx)) return (FALSE);
1476 /* Require Undead */
1477 if (!(r_ptr->flags3 & (RF3_UNDEAD))) return (FALSE);
1485 * Helper function for "monster nest (chapel)"
1487 static bool vault_aux_chapel_g(int r_idx)
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,
1497 monster_race *r_ptr = &r_info[r_idx];
1499 /* Validate the monster */
1500 if (!vault_monster_okay(r_idx)) return (FALSE);
1502 if (r_ptr->flags3 & (RF3_EVIL)) return (FALSE);
1503 if ((r_idx == MON_A_GOLD) || (r_idx == MON_A_SILVER)) return (FALSE);
1505 /* Require "priest" or Angel */
1507 if (r_ptr->d_char == 'A') return TRUE;
1509 for (i = 0; chapel_list[i]; i++)
1510 if (r_idx == chapel_list[i]) return TRUE;
1517 * Helper function for "monster nest (kennel)"
1519 static bool vault_aux_kennel(int r_idx)
1521 monster_race *r_ptr = &r_info[r_idx];
1523 /* Validate the monster */
1524 if (!vault_monster_okay(r_idx)) return (FALSE);
1526 /* Require a Zephyr Hound or a dog */
1527 if (!my_strchr("CZ", r_ptr->d_char)) return (FALSE);
1535 * Helper function for "monster nest (mimic)"
1537 static bool vault_aux_mimic(int r_idx)
1539 monster_race *r_ptr = &r_info[r_idx];
1541 /* Validate the monster */
1542 if (!vault_monster_okay(r_idx)) return (FALSE);
1545 if (!my_strchr("!$&(/=?[\\|", r_ptr->d_char)) return (FALSE);
1552 * Helper function for "monster nest (clone)"
1554 static bool vault_aux_clone(int r_idx)
1556 /* Validate the monster */
1557 if (!vault_monster_okay(r_idx)) return (FALSE);
1559 return (r_idx == vault_aux_race);
1564 * Helper function for "monster nest (symbol clone)"
1566 static bool vault_aux_symbol_e(int r_idx)
1568 monster_race *r_ptr = &r_info[r_idx];
1570 /* Validate the monster */
1571 if (!vault_monster_okay(r_idx)) return (FALSE);
1573 if ((r_ptr->flags2 & RF2_KILL_BODY) && !(r_ptr->flags1 & RF1_NEVER_BLOW)) return (FALSE);
1575 if (r_ptr->flags3 & (RF3_GOOD)) return (FALSE);
1577 /* Decline incorrect symbol */
1578 if (r_ptr->d_char != vault_aux_char) return (FALSE);
1586 * Helper function for "monster nest (symbol clone)"
1588 static bool vault_aux_symbol_g(int r_idx)
1590 monster_race *r_ptr = &r_info[r_idx];
1592 /* Validate the monster */
1593 if (!vault_monster_okay(r_idx)) return (FALSE);
1595 if ((r_ptr->flags2 & RF2_KILL_BODY) && !(r_ptr->flags1 & RF1_NEVER_BLOW)) return (FALSE);
1597 if (r_ptr->flags3 & (RF3_EVIL)) return (FALSE);
1599 /* Decline incorrect symbol */
1600 if (r_ptr->d_char != vault_aux_char) return (FALSE);
1608 * Helper function for "monster pit (orc)"
1610 static bool vault_aux_orc(int r_idx)
1612 monster_race *r_ptr = &r_info[r_idx];
1614 /* Validate the monster */
1615 if (!vault_monster_okay(r_idx)) return (FALSE);
1618 if (!(r_ptr->flags3 & RF3_ORC)) return (FALSE);
1620 /* Decline undead */
1621 if (r_ptr->flags3 & RF3_UNDEAD) return (FALSE);
1629 * Helper function for "monster pit (troll)"
1631 static bool vault_aux_troll(int r_idx)
1633 monster_race *r_ptr = &r_info[r_idx];
1635 /* Validate the monster */
1636 if (!vault_monster_okay(r_idx)) return (FALSE);
1639 if (!(r_ptr->flags3 & RF3_TROLL)) return (FALSE);
1641 /* Decline undead */
1642 if (r_ptr->flags3 & RF3_UNDEAD) return (FALSE);
1650 * Helper function for "monster pit (giant)"
1652 static bool vault_aux_giant(int r_idx)
1654 monster_race *r_ptr = &r_info[r_idx];
1656 /* Validate the monster */
1657 if (!vault_monster_okay(r_idx)) return (FALSE);
1660 if (!(r_ptr->flags3 & RF3_GIANT)) return (FALSE);
1662 if (r_ptr->flags3 & RF3_GOOD) return (FALSE);
1664 /* Decline undead */
1665 if (r_ptr->flags3 & RF3_UNDEAD) return (FALSE);
1673 * Helper function for "monster pit (dragon)"
1675 static bool vault_aux_dragon(int r_idx)
1677 monster_race *r_ptr = &r_info[r_idx];
1679 /* Validate the monster */
1680 if (!vault_monster_okay(r_idx)) return (FALSE);
1682 /* Require dragon */
1683 if (!(r_ptr->flags3 & RF3_DRAGON)) return (FALSE);
1685 /* Hack -- Require correct "breath attack" */
1686 if (r_ptr->flags4 != vault_aux_dragon_mask4) return (FALSE);
1688 /* Decline undead */
1689 if (r_ptr->flags3 & RF3_UNDEAD) return (FALSE);
1697 * Helper function for "monster pit (demon)"
1699 static bool vault_aux_demon(int r_idx)
1701 monster_race *r_ptr = &r_info[r_idx];
1703 /* Validate the monster */
1704 if (!vault_monster_okay(r_idx)) return (FALSE);
1706 if ((r_ptr->flags2 & RF2_KILL_BODY) && !(r_ptr->flags1 & RF1_NEVER_BLOW)) return (FALSE);
1709 if (!(r_ptr->flags3 & RF3_DEMON)) return (FALSE);
1717 * Helper function for "monster pit (lovecraftian)"
1719 static bool vault_aux_cthulhu(int r_idx)
1721 monster_race *r_ptr = &r_info[r_idx];
1723 /* Validate the monster */
1724 if (!vault_monster_okay(r_idx)) return (FALSE);
1726 if ((r_ptr->flags2 & RF2_KILL_BODY) && !(r_ptr->flags1 & RF1_NEVER_BLOW)) return (FALSE);
1728 /* Require eldritch horror */
1729 if (!(r_ptr->flags2 & (RF2_ELDRITCH_HORROR))) return (FALSE);
1737 * Helper function for "monster pit (clone)"
1739 static void vault_prep_clone(void)
1741 /* Apply the monster restriction */
1742 get_mon_num_prep(vault_aux_simple, NULL);
1744 /* Pick a race to clone */
1745 vault_aux_race = get_mon_num(dun_level + 10);
1747 /* Remove the monster restriction */
1748 get_mon_num_prep(NULL, NULL);
1753 * Helper function for "monster pit (symbol clone)"
1755 static void vault_prep_symbol(void)
1759 /* Apply the monster restriction */
1760 get_mon_num_prep(vault_aux_simple, NULL);
1762 /* Pick a race to clone */
1763 r_idx = get_mon_num(dun_level + 10);
1765 /* Remove the monster restriction */
1766 get_mon_num_prep(NULL, NULL);
1768 /* Extract the symbol */
1769 vault_aux_char = r_info[r_idx].d_char;
1774 * Helper function for "monster pit (dragon)"
1776 static void vault_prep_dragon(void)
1778 /* Pick dragon type */
1779 switch (randint0(6))
1784 /* Restrict dragon breath type */
1785 vault_aux_dragon_mask4 = RF4_BR_ACID;
1794 /* Restrict dragon breath type */
1795 vault_aux_dragon_mask4 = RF4_BR_ELEC;
1804 /* Restrict dragon breath type */
1805 vault_aux_dragon_mask4 = RF4_BR_FIRE;
1814 /* Restrict dragon breath type */
1815 vault_aux_dragon_mask4 = RF4_BR_COLD;
1824 /* Restrict dragon breath type */
1825 vault_aux_dragon_mask4 = RF4_BR_POIS;
1834 /* Restrict dragon breath type */
1835 vault_aux_dragon_mask4 = (RF4_BR_ACID | RF4_BR_ELEC |
1836 RF4_BR_FIRE | RF4_BR_COLD |
1847 * Helper function for "monster pit (dark elf)"
1849 static bool vault_aux_dark_elf(int r_idx)
1852 static int dark_elf_list[] =
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,
1859 /* Validate the monster */
1860 if (!vault_monster_okay(r_idx)) return FALSE;
1862 /* Require dark elves */
1863 for (i = 0; dark_elf_list[i]; i++)
1864 if (r_idx == dark_elf_list[i]) return TRUE;
1871 typedef struct vault_aux_type vault_aux_type;
1874 struct vault_aux_type
1877 bool (*hook_func)(int r_idx);
1878 void (*prep_func)(void);
1884 static int pick_vault_type(vault_aux_type *l_ptr, s16b allow_flag_mask)
1886 int tmp, total, count;
1888 vault_aux_type *n_ptr;
1890 /* Calculate the total possibilities */
1891 for (n_ptr = l_ptr, total = 0, count = 0; TRUE; n_ptr++, count++)
1894 if (!n_ptr->name) break;
1896 /* Ignore excessive depth */
1897 if (n_ptr->level > dun_level) continue;
1899 /* Not matched with pit/nest flag */
1900 if (!(allow_flag_mask & (1L << count))) continue;
1902 /* Count this possibility */
1903 total += n_ptr->chance * MAX_DEPTH / (MIN(dun_level, MAX_DEPTH - 1) - n_ptr->level + 5);
1906 /* Pick a random type */
1907 tmp = randint0(total);
1909 /* Find this type */
1910 for (n_ptr = l_ptr, total = 0, count = 0; TRUE; n_ptr++, count++)
1913 if (!n_ptr->name) break;
1915 /* Ignore excessive depth */
1916 if (n_ptr->level > dun_level) continue;
1918 /* Not matched with pit/nest flag */
1919 if (!(allow_flag_mask & (1L << count))) continue;
1921 /* Count this possibility */
1922 total += n_ptr->chance * MAX_DEPTH / (MIN(dun_level, MAX_DEPTH - 1) - n_ptr->level + 5);
1924 /* Found the type */
1925 if (tmp < total) break;
1928 return n_ptr->name ? count : -1;
1931 static vault_aux_type nest_types[] =
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},
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},
1960 static vault_aux_type pit_types[] =
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},
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},
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
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
2016 * Hack -- Get the string describing subtype of pit/nest
2017 * Determined in prepare function (some pit/nest only)
2019 static cptr pit_subtype_string(int type, bool nest)
2021 static char inner_buf[256] = "";
2023 inner_buf[0] = '\0'; /* Init string */
2025 if (nest) /* Nests */
2029 case NEST_TYPE_CLONE:
2030 sprintf(inner_buf, "(%s)", r_name + r_info[vault_aux_race].name);
2032 case NEST_TYPE_SYMBOL_GOOD:
2033 case NEST_TYPE_SYMBOL_EVIL:
2034 sprintf(inner_buf, "(%c)", vault_aux_char);
2042 case PIT_TYPE_SYMBOL_GOOD:
2043 case PIT_TYPE_SYMBOL_EVIL:
2044 sprintf(inner_buf, "(%c)", vault_aux_char);
2046 case PIT_TYPE_DRAGON:
2047 switch (vault_aux_dragon_mask4)
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;
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;
2077 /* A struct for nest monster information with cheat_hear */
2087 * Comp function for sorting nest monster information
2089 static bool ang_sort_comp_nest_mon_info(vptr u, vptr v, int a, int b)
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];
2101 /* Extract used info */
2102 z1 = nest_mon_info[a].used;
2103 z2 = nest_mon_info[b].used;
2105 /* Compare used status */
2106 if (z1 < z2) return FALSE;
2107 if (z1 > z2) return TRUE;
2109 /* Compare levels */
2110 if (r1_ptr->level < r2_ptr->level) return TRUE;
2111 if (r1_ptr->level > r2_ptr->level) return FALSE;
2113 /* Compare experience */
2114 if (r1_ptr->mexp < r2_ptr->mexp) return TRUE;
2115 if (r1_ptr->mexp > r2_ptr->mexp) return FALSE;
2117 /* Compare indexes */
2123 * Swap function for sorting nest monster information
2125 static void ang_sort_swap_nest_mon_info(vptr u, vptr v, int a, int b)
2127 nest_mon_info_type *nest_mon_info = (nest_mon_info_type *)u;
2128 nest_mon_info_type holder;
2134 holder = nest_mon_info[a];
2135 nest_mon_info[a] = nest_mon_info[b];
2136 nest_mon_info[b] = holder;
2140 #define NUM_NEST_MON_TYPE 64
2143 * Type 5 -- Monster nests
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.
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".
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.
2156 * Note that the "get_mon_num()" function may (rarely) fail, in which
2157 * case the nest will be empty.
2159 * Note that "monster nests" will never contain "unique" monsters.
2161 static bool build_type5(void)
2163 int y, x, y1, x1, y2, x2, xval, yval;
2165 nest_mon_info_type nest_mon_info[NUM_NEST_MON_TYPE];
2171 int cur_nest_type = pick_vault_type(nest_types, d_info[dungeon_type].nest);
2172 vault_aux_type *n_ptr;
2174 /* No type available */
2175 if (cur_nest_type < 0) return FALSE;
2177 n_ptr = &nest_types[cur_nest_type];
2179 /* Process a preparation function if necessary */
2180 if (n_ptr->prep_func) (*(n_ptr->prep_func))();
2182 /* Prepare allocation table */
2183 get_mon_num_prep(n_ptr->hook_func, NULL);
2185 align.sub_align = SUB_ALIGN_NEUTRAL;
2187 /* Pick some monster types */
2188 for (i = 0; i < NUM_NEST_MON_TYPE; i++)
2190 int r_idx = 0, attempts = 100;
2191 monster_race *r_ptr = NULL;
2195 /* Get a (hard) monster type */
2196 r_idx = get_mon_num(dun_level + 11);
2197 r_ptr = &r_info[r_idx];
2199 /* Decline incorrect alignment */
2200 if (monster_has_hostile_align(&align, 0, 0, r_ptr)) continue;
2202 /* Accept this monster */
2206 /* Notice failure */
2207 if (!r_idx || !attempts) return FALSE;
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;
2213 nest_mon_info[i].r_idx = r_idx;
2214 nest_mon_info[i].used = FALSE;
2217 /* Find and reserve some space in the dungeon. Get center of room. */
2218 if (!find_space(&yval, &xval, 11, 25)) return FALSE;
2226 /* Place the floor area */
2227 for (y = y1 - 1; y <= y2 + 1; y++)
2229 for (x = x1 - 1; x <= x2 + 1; x++)
2231 c_ptr = &cave[y][x];
2232 place_floor_grid(c_ptr);
2233 c_ptr->info |= (CAVE_ROOM);
2237 /* Place the outer walls */
2238 for (y = y1 - 1; y <= y2 + 1; y++)
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);
2245 for (x = x1 - 1; x <= x2 + 1; x++)
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);
2254 /* Advance to the center room */
2260 /* The inner walls */
2261 for (y = y1 - 1; y <= y2 + 1; y++)
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);
2269 for (x = x1 - 1; x <= x2 + 1; x++)
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);
2276 for (y = y1; y <= y2; y++)
2278 for (x = x1; x <= x2; x++)
2280 add_cave_info(y, x, CAVE_ICKY);
2284 /* Place a secret door */
2285 switch (randint1(4))
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;
2298 msg_format("¥â¥ó¥¹¥¿¡¼Éô²°(nest)(%s%s)", n_ptr->name, pit_subtype_string(cur_nest_type, TRUE));
2300 msg_format("Monster nest (%s%s)", n_ptr->name, pit_subtype_string(cur_nest_type, TRUE));
2304 /* Place some monsters */
2305 for (y = yval - 2; y <= yval + 2; y++)
2307 for (x = xval - 9; x <= xval + 9; x++)
2311 i = randint0(NUM_NEST_MON_TYPE);
2312 r_idx = nest_mon_info[i].r_idx;
2314 /* Place that "random" monster (no groups) */
2315 (void)place_monster_aux(0, y, x, r_idx, 0L);
2317 nest_mon_info[i].used = TRUE;
2321 if (cheat_room && cheat_hear)
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);
2327 /* Dump the entries (prevent multi-printing) */
2328 for (i = 0; i < NUM_NEST_MON_TYPE; i++)
2330 if (!nest_mon_info[i].used) break;
2331 for (; i < NUM_NEST_MON_TYPE - 1; i++)
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;
2336 msg_print(r_name + r_info[nest_mon_info[i].r_idx].name);
2345 * Type 6 -- Monster pits
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.
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
2353 * #####################
2354 * #0000000000000000000#
2355 * #0112233455543322110#
2356 * #0112233467643322110#
2357 * #0112233455543322110#
2358 * #0000000000000000000#
2359 * #####################
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.
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.
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.
2375 * Note that the "get_mon_num()" function may (rarely) fail, in which case
2376 * the pit will be empty.
2378 * Note that "monster pits" will never contain "unique" monsters.
2380 static bool build_type6(void)
2382 int y, x, y1, x1, y2, x2, xval, yval;
2391 int cur_pit_type = pick_vault_type(pit_types, d_info[dungeon_type].pit);
2392 vault_aux_type *n_ptr;
2394 /* No type available */
2395 if (cur_pit_type < 0) return FALSE;
2397 n_ptr = &pit_types[cur_pit_type];
2399 /* Process a preparation function if necessary */
2400 if (n_ptr->prep_func) (*(n_ptr->prep_func))();
2402 /* Prepare allocation table */
2403 get_mon_num_prep(n_ptr->hook_func, NULL);
2405 align.sub_align = SUB_ALIGN_NEUTRAL;
2407 /* Pick some monster types */
2408 for (i = 0; i < 16; i++)
2410 int r_idx = 0, attempts = 100;
2411 monster_race *r_ptr = NULL;
2415 /* Get a (hard) monster type */
2416 r_idx = get_mon_num(dun_level + 11);
2417 r_ptr = &r_info[r_idx];
2419 /* Decline incorrect alignment */
2420 if (monster_has_hostile_align(&align, 0, 0, r_ptr)) continue;
2422 /* Accept this monster */
2426 /* Notice failure */
2427 if (!r_idx || !attempts) return FALSE;
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;
2436 /* Find and reserve some space in the dungeon. Get center of room. */
2437 if (!find_space(&yval, &xval, 11, 25)) return FALSE;
2445 /* Place the floor area */
2446 for (y = y1 - 1; y <= y2 + 1; y++)
2448 for (x = x1 - 1; x <= x2 + 1; x++)
2450 c_ptr = &cave[y][x];
2451 place_floor_grid(c_ptr);
2452 c_ptr->info |= (CAVE_ROOM);
2456 /* Place the outer walls */
2457 for (y = y1 - 1; y <= y2 + 1; y++)
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);
2464 for (x = x1 - 1; x <= x2 + 1; x++)
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);
2472 /* Advance to the center room */
2478 /* The inner walls */
2479 for (y = y1 - 1; y <= y2 + 1; y++)
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);
2486 for (x = x1 - 1; x <= x2 + 1; x++)
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);
2493 for (y = y1; y <= y2; y++)
2495 for (x = x1; x <= x2; x++)
2497 add_cave_info(y, x, CAVE_ICKY);
2501 /* Place a secret door */
2502 switch (randint1(4))
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;
2510 /* Sort the entries */
2511 for (i = 0; i < 16 - 1; i++)
2513 /* Sort the entries */
2514 for (j = 0; j < 16 - 1; j++)
2519 int p1 = r_info[what[i1]].level;
2520 int p2 = r_info[what[i2]].level;
2526 what[i1] = what[i2];
2537 msg_format("¥â¥ó¥¹¥¿¡¼Éô²°(pit)(%s%s)", n_ptr->name, pit_subtype_string(cur_pit_type, FALSE));
2539 msg_format("Monster pit (%s%s)", n_ptr->name, pit_subtype_string(cur_pit_type, FALSE));
2543 /* Select the entries */
2544 for (i = 0; i < 8; i++)
2546 /* Every other entry */
2547 what[i] = what[i * 2];
2552 msg_print(r_name + r_info[what[i]].name);
2556 /* Top and bottom rows */
2557 for (x = xval - 9; x <= xval + 9; x++)
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);
2563 /* Middle columns */
2564 for (y = yval - 1; y <= yval + 1; y++)
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);
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);
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);
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);
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);
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);
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);
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);
2591 /* Above/Below the center monster */
2592 for (x = xval - 1; x <= xval + 1; x++)
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);
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);
2602 /* Center monster */
2603 place_monster_aux(0, yval, xval, what[7], PM_NO_KAGE);
2609 /* coordinate translation code */
2610 static void coord_trans(int *x, int *y, int xoffset, int yoffset, int transno)
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.
2624 for (i = 0; i < transno % 4; i++)
2626 /* rotate by 90 degrees */
2634 /* Reflect depending on status of 3rd bit. */
2638 /* Add offsets so vault stays in the first quadrant */
2645 * Hack -- fill in "vault" rooms
2647 static void build_vault(int yval, int xval, int ymax, int xmax, cptr data,
2648 int xoffset, int yoffset, int transno)
2650 int dx, dy, x, y, i, j;
2657 /* Place dungeon features and objects */
2658 for (t = data, dy = 0; dy < ymax; dy++)
2660 for (dx = 0; dx < xmax; dx++, t++)
2662 /* prevent loop counter from being overwritten */
2667 coord_trans(&i, &j, xoffset, yoffset, transno);
2669 /* Extract the location */
2670 if (transno % 2 == 0)
2672 /* no swap of x/y */
2673 x = xval - (xmax / 2) + i;
2674 y = yval - (ymax / 2) + j;
2679 x = xval - (ymax / 2) + i;
2680 y = yval - (xmax / 2) + j;
2683 /* Hack -- skip "non-grids" */
2684 if (*t == ' ') continue;
2686 /* Access the grid */
2687 c_ptr = &cave[y][x];
2689 /* Lay down a floor */
2690 place_floor_grid(c_ptr);
2692 /* Remove any mimic */
2695 /* Part of a vault */
2696 c_ptr->info |= (CAVE_ROOM | CAVE_ICKY);
2698 /* Analyze the grid */
2701 /* Granite wall (outer) */
2703 place_outer_noperm_grid(c_ptr);
2706 /* Granite wall (inner) */
2708 place_inner_grid(c_ptr);
2711 /* Glass wall (inner) */
2713 place_inner_grid(c_ptr);
2714 c_ptr->feat = feat_glass_wall;
2717 /* Permanent wall (inner) */
2719 place_inner_perm_grid(c_ptr);
2722 /* Permanent glass wall (inner) */
2724 place_inner_perm_grid(c_ptr);
2725 c_ptr->feat = feat_permanent_glass_wall;
2730 if (randint0(100) < 75)
2732 place_object(y, x, 0L);
2742 place_secret_door(y, x, DOOR_DEFAULT);
2745 /* Secret glass doors */
2747 place_secret_door(y, x, DOOR_GLASS_DOOR);
2748 if (is_closed_door(c_ptr->feat)) c_ptr->mimic = feat_glass_wall;
2753 place_secret_door(y, x, DOOR_CURTAIN);
2761 /* Black market in a dungeon */
2763 set_cave_feat(y, x, feat_black_market);
2764 store_init(NO_TOWN, STORE_BLACK);
2769 set_cave_feat(y, x, feat_pattern_start);
2773 set_cave_feat(y, x, feat_pattern_1);
2777 set_cave_feat(y, x, feat_pattern_2);
2781 set_cave_feat(y, x, feat_pattern_3);
2785 set_cave_feat(y, x, feat_pattern_4);
2789 set_cave_feat(y, x, feat_pattern_end);
2793 set_cave_feat(y, x, feat_pattern_exit);
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;
2807 /* Place dungeon monsters and objects */
2808 for (t = data, dy = 0; dy < ymax; dy++)
2810 for (dx = 0; dx < xmax; dx++, t++)
2812 /* prevent loop counter from being overwritten */
2817 coord_trans(&i, &j, xoffset, yoffset, transno);
2819 /* Extract the location */
2820 if (transno % 2 == 0)
2822 /* no swap of x/y */
2823 x = xval - (xmax / 2) + i;
2824 y = yval - (ymax / 2) + j;
2829 x = xval - (ymax / 2) + i;
2830 y = yval - (xmax / 2) + j;
2833 /* Hack -- skip "non-grids" */
2834 if (*t == ' ') continue;
2836 /* Analyze the symbol */
2842 monster_level = base_level + 5;
2843 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
2844 monster_level = base_level;
2848 /* Meaner monster */
2851 monster_level = base_level + 11;
2852 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
2853 monster_level = base_level;
2857 /* Meaner monster, plus treasure */
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;
2869 /* Nasty monster and treasure */
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;
2881 /* Monster and/or object */
2884 if (randint0(100) < 50)
2886 monster_level = base_level + 3;
2887 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
2888 monster_level = base_level;
2890 if (randint0(100) < 50)
2892 object_level = base_level + 7;
2893 place_object(y, x, 0L);
2894 object_level = base_level;
2906 * Type 7 -- simple vaults (see "v_info.txt")
2908 static bool build_type7(void)
2914 int xoffset, yoffset;
2917 /* Pick a lesser vault */
2918 for (dummy = 0; dummy < SAFE_MAX_ATTEMPTS; dummy++)
2920 /* Access a random vault record */
2921 v_ptr = &v_info[randint0(max_v_idx)];
2923 /* Accept the first lesser vault */
2924 if (v_ptr->typ == 7) break;
2927 /* No lesser vault found */
2928 if (dummy >= SAFE_MAX_ATTEMPTS)
2933 msg_print("·Ù¹ð¡ª¾®¤µ¤ÊÃϲ¼¼¼¤òÇÛÃ֤Ǥ¤Þ¤»¤ó¡ª");
2935 msg_print("Warning! Could not place lesser vault!");
2941 /* pick type of transformation (0-7) */
2942 transno = randint0(8);
2944 /* calculate offsets */
2948 /* Some huge vault cannot be ratated to fit in the dungeon */
2949 if (x+2 > cur_hgt-2)
2951 /* Forbid 90 or 270 degree ratation */
2955 coord_trans(&x, &y, 0, 0, transno);
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;
2984 if (cheat_room) msg_format("¾®¤µ¤ÊÃϲ¼¼¼(%s)", v_name + v_ptr->name);
2986 if (cheat_room) msg_format("Lesser vault (%s)", v_name + v_ptr->name);
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);
2998 * Type 8 -- greater vaults (see "v_info.txt")
3000 static bool build_type8(void)
3007 int xoffset, yoffset;
3009 /* Pick a greater vault */
3010 for (dummy = 0; dummy < SAFE_MAX_ATTEMPTS; dummy++)
3012 /* Access a random vault record */
3013 v_ptr = &v_info[randint0(max_v_idx)];
3015 /* Accept the first greater vault */
3016 if (v_ptr->typ == 8) break;
3019 /* No greater vault found */
3020 if (dummy >= SAFE_MAX_ATTEMPTS)
3025 msg_print("·Ù¹ð¡ªµðÂç¤ÊÃϲ¼¼¼¤òÇÛÃ֤Ǥ¤Þ¤»¤ó¡ª");
3027 msg_print("Warning! Could not place greater vault!");
3033 /* pick type of transformation (0-7) */
3034 transno = randint0(8);
3036 /* calculate offsets */
3040 /* Some huge vault cannot be ratated to fit in the dungeon */
3041 if (x+2 > cur_hgt-2)
3043 /* Forbid 90 or 270 degree ratation */
3047 coord_trans(&x, &y, 0, 0, transno);
3068 * Try to allocate space for room. If fails, exit
3070 * Hack -- Prepare a bit larger space (+2, +2) to
3071 * prevent generation of vaults with no-entrance.
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;
3077 v_ptr = &v_info[76 + randint1(3)];
3082 if (cheat_room) msg_format("µðÂç¤ÊÃϲ¼¼¼(%s)", v_name + v_ptr->name);
3084 if (cheat_room) msg_format("Greater vault (%s)", v_name + v_ptr->name);
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);
3095 * Structure to hold all "fill" data
3098 typedef struct fill_data_type fill_data_type;
3100 struct fill_data_type
3113 /* features to fill with */
3122 /* number of filled squares */
3126 static fill_data_type fill_data;
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)
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;
3138 /* store the value in height-map format */
3139 cave[y][x].feat = val;
3146 * Explanation of the plasma fractal algorithm:
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.
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.
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.
3170 * How fractal caves are made:
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.
3177 * The grd variable affects the width of passages.
3178 * The roug variable affects the roughness of those passages
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_.
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.
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.
3198 static void generate_hmap(int y0, int x0, int xsiz, int ysiz, int grd, int roug, int cutoff)
3200 int xhsize, yhsize, xsize, ysize, maxsize;
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
3207 u16b xstep, xhstep, ystep, yhstep;
3208 u16b xstep2, xhstep2, ystep2, yhstep2;
3209 u16b i, j, ii, jj, diagsize, xxsize, yysize;
3211 /* Cache for speed */
3212 u16b xm, xp, ym, yp;
3214 /* redefine size so can change the value if out of range */
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;
3224 /* get offsets to middle of array */
3228 /* fix rounding problem */
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;
3238 /* Store cutoff in global for quick access */
3239 fill_data.c1 = cutoff;
3242 * Scale factor for middle points:
3243 * About sqrt(2) * 256 - correct for a square lattice
3244 * approximately correct for everything else.
3248 /* maximum of xsize and ysize */
3249 maxsize = (xsize > ysize) ? xsize : ysize;
3251 /* Clear the section */
3252 for (i = 0; i <= xsize; i++)
3254 for (j = 0; j <= ysize; j++)
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);
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;
3269 /* Set the middle square to be an open area. */
3270 cave[y0][x0].feat = 0;
3272 /* Initialize the step sizes */
3273 xstep = xhstep = xsize * 256;
3274 ystep = yhstep = ysize * 256;
3275 xxsize = xsize * 256;
3276 yysize = ysize * 256;
3279 * Fill in the rectangle with fractal height data -
3280 * like the 'plasma fractal' in fractint.
3282 while ((xhstep > 256) || (yhstep > 256))
3284 /* Halve the step sizes */
3290 /* cache well used values */
3291 xstep2 = xstep / 256;
3292 ystep2 = ystep / 256;
3294 xhstep2 = xhstep / 256;
3295 yhstep2 = yhstep / 256;
3297 /* middle top to bottom. */
3298 for (i = xhstep; i <= xxsize - xhstep; i += xstep)
3300 for (j = 0; j <= yysize; j += ystep)
3302 /* cache often used values */
3303 ii = i / 256 + fill_data.xmin;
3304 jj = j / 256 + fill_data.ymin;
3307 if (cave[jj][ii].feat == -1)
3311 /* If greater than 'grid' level then is random */
3312 store_height(ii, jj, randint1(maxsize));
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);
3327 /* middle left to right. */
3328 for (j = yhstep; j <= yysize - yhstep; j += ystep)
3330 for (i = 0; i <= xxsize; i += xstep)
3332 /* cache often used values */
3333 ii = i / 256 + fill_data.xmin;
3334 jj = j / 256 + fill_data.ymin;
3337 if (cave[jj][ii].feat == -1)
3341 /* If greater than 'grid' level then is random */
3342 store_height(ii, jj, randint1(maxsize));
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);
3357 for (i = xhstep; i <= xxsize - xhstep; i += xstep)
3359 for (j = yhstep; j <= yysize - yhstep; j += ystep)
3361 /* cache often used values */
3362 ii = i / 256 + fill_data.xmin;
3363 jj = j / 256 + fill_data.ymin;
3366 if (cave[jj][ii].feat == -1)
3370 /* If greater than 'grid' level then is random */
3371 store_height(ii, jj, randint1(maxsize));
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;
3382 * Average over all four corners + scale by diagsize to
3383 * reduce the effect of the square grid on the shape of the fractal
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);
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)
3400 * function used to convert from height-map back to the
3401 * normal angband cave format
3403 if (cave[y][x].info & CAVE_ICKY)
3410 /* Show that have looked at this square */
3411 cave[y][x].info|= (CAVE_ICKY);
3413 /* Use cutoffs c1-c3 to allocate regions of floor /water/ lava etc. */
3414 if (cave[y][x].feat <= c1)
3416 /* 25% of the time use the other tile : it looks better this way */
3417 if (randint1(100) < 75)
3419 cave[y][x].feat = feat1;
3420 cave[y][x].info &= ~(CAVE_MASK);
3421 cave[y][x].info |= info1;
3426 cave[y][x].feat = feat2;
3427 cave[y][x].info &= ~(CAVE_MASK);
3428 cave[y][x].info |= info2;
3432 else if (cave[y][x].feat <= c2)
3434 /* 25% of the time use the other tile : it looks better this way */
3435 if (randint1(100) < 75)
3437 cave[y][x].feat = feat2;
3438 cave[y][x].info &= ~(CAVE_MASK);
3439 cave[y][x].info |= info2;
3444 cave[y][x].feat = feat1;
3445 cave[y][x].info &= ~(CAVE_MASK);
3446 cave[y][x].info |= info1;
3450 else if (cave[y][x].feat <= c3)
3452 cave[y][x].feat = feat3;
3453 cave[y][x].info &= ~(CAVE_MASK);
3454 cave[y][x].info |= info3;
3457 /* if greater than cutoff then is a wall */
3460 place_outer_bold(y, x);
3470 * Quick and nasty fill routine used to find the connected region
3471 * of floor in the middle of the cave
3473 static void cave_fill(byte y, byte x)
3482 /*** Start Grid ***/
3484 /* Enqueue that entry */
3489 /* Now process the queue */
3490 while (flow_head != flow_tail)
3492 /* Extract the next entry */
3493 ty = temp_y[flow_head];
3494 tx = temp_x[flow_head];
3496 /* Forget that entry */
3497 if (++flow_head == TEMP_MAX) flow_head = 0;
3499 /* Add the "children" */
3500 for (d = 0; d < 8; d++)
3502 int old_head = flow_tail;
3504 /* Child location */
3505 j = ty + ddy_ddd[d];
3506 i = tx + ddx_ddd[d];
3508 /* Paranoia Don't leave the cave */
3509 if (!in_bounds(j, i))
3511 /* affect boundary */
3512 cave[j][i].info |= CAVE_ICKY;
3516 /* If within bounds */
3517 else if ((i > fill_data.xmin) && (i < fill_data.xmax)
3518 && (j > fill_data.ymin) && (j < fill_data.ymax))
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))
3526 /* Enqueue that entry */
3527 temp_y[flow_tail] = j;
3528 temp_x[flow_tail] = i;
3530 /* Advance the queue */
3531 if (++flow_tail == TEMP_MAX) flow_tail = 0;
3533 /* Hack -- Overflow by forgetting new entry */
3534 if (flow_tail == flow_head)
3536 flow_tail = old_head;
3540 /* keep tally of size of cave system */
3541 (fill_data.amount)++;
3547 /* affect boundary */
3548 cave[j][i].info |= CAVE_ICKY;
3555 static bool generate_fracave(int y0, int x0, int xsize, int ysize, int cutoff, bool light, bool room)
3557 int x, y, i, xhsize, yhsize;
3559 /* offsets to middle from corner */
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...
3571 fill_data.c1 = cutoff;
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)];
3580 fill_data.info1 = CAVE_FLOOR;
3581 fill_data.info2 = CAVE_FLOOR;
3582 fill_data.info3 = CAVE_FLOOR;
3584 /* number of filled squares */
3585 fill_data.amount = 0;
3587 cave_fill((byte)y0, (byte)x0);
3589 /* if tally too small, try again */
3590 if (fill_data.amount < 10)
3592 /* too small - clear area and try again later */
3593 for (x = 0; x <= xsize; ++x)
3595 for (y = 0; y <= ysize; ++y)
3597 place_extra_bold(y0 + y - yhsize, x0 + x - xhsize);
3598 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY | CAVE_ROOM);
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.
3609 for (i = 0; i <= xsize; ++i)
3612 if ((cave[0 + y0 - yhsize][i + x0 - xhsize].info & CAVE_ICKY) && (room))
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);
3622 /* set to be normal granite */
3623 place_extra_bold(y0 + 0 - yhsize, x0 + i - xhsize);
3626 /* bottom boundary */
3627 if ((cave[ysize + y0 - yhsize][i + x0 - xhsize].info & CAVE_ICKY) && (room))
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);
3637 /* set to be normal granite */
3638 place_extra_bold(y0 + ysize - yhsize, x0 + i - xhsize);
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);
3646 /* Do the left and right boundaries minus the corners (done above) */
3647 for (i = 1; i < ysize; ++i)
3650 if ((cave[i + y0 - yhsize][0 + x0 - xhsize].info & CAVE_ICKY) && room)
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);
3661 place_extra_bold(y0 + i - yhsize, x0 + 0 - xhsize);
3663 /* right boundary */
3664 if ((cave[i + y0 - yhsize][xsize + x0 - xhsize].info & CAVE_ICKY) && room)
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);
3675 place_extra_bold(y0 + i - yhsize, x0 + xsize - xhsize);
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);
3684 /* Do the rest: convert back to the normal format */
3685 for (x = 1; x < xsize; ++x)
3687 for (y = 1; y < ysize; ++y)
3689 if (is_floor_bold(y0 + y - yhsize, x0 + x - xhsize) &&
3690 (cave[y0 + y - yhsize][x0 + x - xhsize].info & CAVE_ICKY))
3692 /* Clear the icky flag in the filled region */
3693 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~CAVE_ICKY;
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);
3699 else if (is_outer_bold(y0 + y - yhsize, x0 + x - xhsize) &&
3700 (cave[y0 + y - yhsize][x0 + x - xhsize].info & CAVE_ICKY))
3703 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY);
3704 if (light) cave[y0 + y - yhsize][x0 + x - xhsize].info |= (CAVE_GLOW);
3707 cave[y0 + y - yhsize][x0 + x - xhsize].info |= (CAVE_ROOM);
3712 place_extra_bold(y0 + y - yhsize, x0 + x - xhsize);
3713 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ROOM);
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);
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
3740 * Driver routine to create fractal cave system
3742 static bool build_type9(void)
3744 int grd, roug, cutoff, xsize, ysize, y0, x0;
3746 bool done, light, room;
3748 /* get size: note 'Evenness'*/
3749 xsize = randint1(22) * 2 + 6;
3750 ysize = randint1(15) * 2 + 6;
3752 /* Find and reserve some space in the dungeon. Get center of room. */
3753 if (!find_space(&y0, &x0, ysize + 1, xsize + 1))
3755 /* Limit to the minimum room size, and retry */
3759 /* Find and reserve some space in the dungeon. Get center of room. */
3760 if (!find_space(&y0, &x0, ysize + 1, xsize + 1))
3766 return build_type1();
3770 light = done = FALSE;
3773 if ((dun_level <= randint1(25)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS)) light = TRUE;
3777 /* Note: size must be even or there are rounding problems
3778 * This causes the tunnels not to connect properly to the room */
3780 /* testing values for these parameters feel free to adjust */
3781 grd = 1 << (randint0(4));
3783 /* want average of about 16 */
3784 roug = randint1(8) * randint1(4);
3787 cutoff = randint1(xsize / 4) + randint1(ysize / 4) +
3788 randint1(xsize / 4) + randint1(ysize / 4);
3791 generate_hmap(y0, x0, xsize, ysize, grd, roug, cutoff);
3793 /* Convert to normal format + clean up */
3794 done = generate_fracave(y0, x0, xsize, ysize, cutoff, light, room);
3800 #ifdef ALLOW_CAVERNS_AND_LAKES
3802 * Builds a cave system in the center of the dungeon.
3804 void build_cavern(void)
3806 int grd, roug, cutoff, xsize, ysize, x0, y0;
3809 light = done = FALSE;
3810 if ((dun_level <= randint1(50)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS)) light = TRUE;
3812 /* Make a cave the size of the dungeon */
3813 xsize = cur_wid - 1;
3814 ysize = cur_hgt - 1;
3818 /* Paranoia: make size even */
3824 /* testing values for these parameters: feel free to adjust */
3825 grd = randint1(4) + 4;
3827 /* want average of about 16 */
3828 roug = randint1(8) * randint1(4);
3834 generate_hmap(y0 + 1, x0 + 1, xsize, ysize, grd, roug, cutoff);
3836 /* Convert to normal format+ clean up */
3837 done = generate_fracave(y0 + 1, x0 + 1, xsize, ysize, cutoff, light, FALSE);
3841 static bool generate_lake(int y0, int x0, int xsize, int ysize, int c1, int c2, int c3, int type)
3843 int x, y, i, xhsize, yhsize;
3844 int feat1, feat2, feat3;
3846 /* offsets to middle from corner */
3850 /* Get features based on type */
3853 case LAKE_T_LAVA: /* Lava */
3854 feat1 = feat_deep_lava;
3855 feat2 = feat_shallow_lava;
3856 feat3 = floor_type[randint0(100)];
3858 case LAKE_T_WATER: /* Water */
3859 feat1 = feat_deep_water;
3860 feat2 = feat_shallow_water;
3861 feat3 = floor_type[randint0(100)];
3863 case LAKE_T_CAVE: /* Collapsed cave */
3864 feat1 = floor_type[randint0(100)];
3865 feat2 = floor_type[randint0(100)];
3866 feat3 = feat_rubble;
3868 case LAKE_T_EARTH_VAULT: /* Earth vault */
3869 feat1 = feat_rubble;
3870 feat2 = floor_type[randint0(100)];
3871 feat3 = feat_rubble;
3873 case LAKE_T_AIR_VAULT: /* Air vault */
3878 case LAKE_T_WATER_VAULT: /* Water vault */
3879 feat1 = feat_shallow_water;
3880 feat2 = feat_deep_water;
3881 feat3 = feat_shallow_water;
3883 case LAKE_T_FIRE_VAULT: /* Fire Vault */
3884 feat1 = feat_shallow_lava;
3885 feat2 = feat_deep_lava;
3886 feat3 = feat_shallow_lava;
3890 default: return FALSE;
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...
3904 /* features to fill with */
3905 fill_data.feat1 = feat1;
3906 fill_data.feat2 = feat2;
3907 fill_data.feat3 = feat3;
3909 fill_data.info1 = 0;
3910 fill_data.info2 = 0;
3911 fill_data.info3 = 0;
3913 /* number of filled squares */
3914 fill_data.amount = 0;
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);
3921 /* if tally too small, try again */
3922 if (fill_data.amount < 10)
3924 /* too small -clear area and try again later */
3925 for (x = 0; x <= xsize; ++x)
3927 for (y = 0; y <= ysize; ++y)
3929 place_floor_bold(y0 + y - yhsize, x0 + x - xhsize);
3930 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY);
3936 /* Do boundarys- set to normal granite */
3937 for (i = 0; i <= xsize; ++i)
3939 place_extra_bold(y0 + 0 - yhsize, x0 + i - xhsize);
3940 place_extra_bold(y0 + ysize - yhsize, x0 + i - xhsize);
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);
3947 /* Do the left and right boundaries minus the corners (done above) */
3949 for (i = 1; i < ysize; ++i)
3951 place_extra_bold(y0 + i - yhsize, x0 + 0 - xhsize);
3952 place_extra_bold(y0 + i - yhsize, x0 + xsize - xhsize);
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);
3960 /* Do the rest: convert back to the normal format */
3961 for (x = 1; x < xsize; ++x)
3963 for (y = 1; y < ysize; ++y)
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);
3970 /* turn off icky flag (no longer needed.) */
3971 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY | CAVE_ROOM);
3974 if (cave_have_flag_bold(y0 + y - yhsize, x0 + x - xhsize, FF_LAVA))
3976 if (!(d_info[dungeon_type].flags1 & DF1_DARKNESS)) cave[y0 + y - yhsize][x0 + x - xhsize].info |= CAVE_GLOW;
3986 * makes a lake/collapsed cave system in the center of the dungeon
3988 void build_lake(int type)
3990 int grd, roug, xsize, ysize, x0, y0;
3994 /* paranoia - exit if lake type out of range. */
3995 if ((type < LAKE_T_LAVA) || (type > LAKE_T_FIRE_VAULT))
3997 msg_format("Invalid lake type (%d)", type);
4001 /* Make the size of the dungeon */
4002 xsize = cur_wid - 1;
4003 ysize = cur_hgt - 1;
4007 /* Paranoia: make size even */
4013 /* testing values for these parameters: feel free to adjust */
4014 grd = randint1(3) + 4;
4016 /* want average of about 16 */
4017 roug = randint1(8) * randint1(4);
4019 /* Make up size of various componants */
4023 /* Deep water/lava */
4024 c1 = randint0(c3 / 2) + randint0(c3 / 2) - 5;
4026 /* Shallow boundary */
4030 generate_hmap(y0 + 1, x0 + 1, xsize, ysize, grd, roug, c3);
4032 /* Convert to normal format+ clean up */
4033 done = generate_lake(y0 + 1, x0 + 1, xsize, ysize, c1, c2, c3, type);
4036 #endif /* ALLOW_CAVERNS_AND_LAKES */
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.
4043 * The doors must be INSIDE the allocated region.
4045 static void add_door(int x, int y)
4047 /* Need to have a wall in the center square */
4048 if (!is_outer_bold(y, x)) return;
4055 * where x=don't care
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)))
4063 place_secret_door(y, x, DOOR_DEFAULT);
4065 /* set boundarys so don't get wide doors */
4066 place_solid_bold(y, x - 1);
4067 place_solid_bold(y, x + 1);
4076 * where x = don't care
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))
4083 place_secret_door(y, x, DOOR_DEFAULT);
4085 /* set boundarys so don't get wide doors */
4086 place_solid_bold(y - 1, x);
4087 place_solid_bold(y + 1, x);
4093 * Routine that fills the empty areas of a room with treasure and monsters.
4095 static void fill_treasure(int x1, int x2, int y1, int y2, int difficulty)
4097 int x, y, cx, cy, size;
4100 /* center of room:*/
4104 /* Rough measure of size of vault= sum of lengths of sides */
4105 size = abs(x2 - x1) + abs(y2 - y1);
4107 for (x = x1; x <= x2; x++)
4109 for (y = y1; y <= y2; y++)
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;
4115 /* hack- empty square part of the time */
4116 if ((randint1(100) - difficulty * 3) > 50) value = 20;
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)))
4122 /* The smaller 'value' is, the better the stuff */
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;
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;
4143 else if (value < 10)
4146 monster_level = base_level + 9;
4147 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
4148 monster_level = base_level;
4150 else if (value < 17)
4152 /* Intentional Blank space */
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.)
4161 else if (value < 23)
4163 /* Object or trap */
4164 if (randint0(100) < 25)
4166 place_object(y, x, 0L);
4173 else if (value < 30)
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;
4181 else if (value < 40)
4183 /* Monster or object */
4184 if (randint0(100) < 50)
4186 monster_level = base_level + 3;
4187 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
4188 monster_level = base_level;
4190 if (randint0(100) < 50)
4192 object_level = base_level + 7;
4193 place_object(y, x, 0L);
4194 object_level = base_level;
4197 else if (value < 50)
4206 /* 20% monster, 40% trap, 20% object, 20% blank space */
4207 if (randint0(100) < 20)
4209 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
4211 else if (randint0(100) < 50)
4215 else if (randint0(100) < 50)
4217 place_object(y, x, 0L);
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.)
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.
4238 static void build_bubble_vault(int x0, int y0, int xsize, int ysize)
4240 #define BUBBLENUM 10 /* number of bubbles */
4242 /* array of center points of bubbles */
4243 coord center[BUBBLENUM];
4246 u16b min1, min2, temp;
4249 /* Offset from center to top left hand corner */
4250 int xhsize = xsize / 2;
4251 int yhsize = ysize / 2;
4254 if (cheat_room) msg_print("Bubble Vault");
4256 /* Allocate center of bubbles */
4257 center[0].x = (byte)randint1(xsize - 3) + 1;
4258 center[0].y = (byte)randint1(ysize - 3) + 1;
4260 for (i = 1; i < BUBBLENUM; i++)
4264 /* get center and check to see if it is unique */
4269 x = randint1(xsize - 3) + 1;
4270 y = randint1(ysize - 3) + 1;
4272 for (j = 0; j < i; j++)
4274 /* rough test to see if there is an overlap */
4275 if ((x == center[j].x) && (y == center[j].y)) done = FALSE;
4284 /* Top and bottom boundaries */
4285 for (i = 0; i < xsize; i++)
4287 int x = x0 - xhsize + i;
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);
4295 /* Left and right boundaries */
4296 for (i = 1; i < ysize - 1; i++)
4298 int y = y0 - yhsize + i;
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);
4306 /* Fill in middle with bubbles */
4307 for (x = 1; x < xsize - 1; x++)
4309 for (y = 1; y < ysize - 1; y++)
4311 /* Get distances to two closest centers */
4314 min1 = distance(x, y, center[0].x, center[0].y);
4315 min2 = distance(x, y, center[1].x, center[1].y);
4319 /* swap if in wrong order */
4326 for (i = 2; i < BUBBLENUM; i++)
4328 temp = distance(x, y, center[i].x, center[i].y);
4336 else if (temp < min2)
4338 /* second smallest */
4342 if (((min2 - min1) <= 2) && (!(min1 < 3)))
4344 /* Boundary at midpoint+ not at inner region of bubble */
4345 place_outer_noperm_bold(y0 - yhsize + y, x0 - xhsize + x);
4349 /* middle of a bubble */
4350 place_floor_bold(y0 - yhsize + y, x0 - xhsize + x);
4353 /* clean up rest of flags */
4354 cave[y0 - yhsize + y][x0 - xhsize + x].info |= (CAVE_ROOM | CAVE_ICKY);
4358 /* Try to add some random doors */
4359 for (i = 0; i < 500; i++)
4361 x = randint1(xsize - 3) - xhsize + x0 + 1;
4362 y = randint1(ysize - 3) - yhsize + y0 + 1;
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));
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
4377 static void build_room(int x1, int x2, int y1, int y2)
4379 int x, y, i, xsize, ysize, temp;
4381 /* Check if rectangle has no width */
4382 if ((x1 == x2) || (y1 == y2)) return;
4387 /* Swap boundaries if in wrong order */
4395 /* Swap boundaries if in wrong order */
4401 /* get total widths */
4406 /* Top and bottom boundaries */
4407 for (i = 0; i <= xsize; i++)
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);
4415 /* Left and right boundaries */
4416 for (i = 1; i < ysize; i++)
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);
4425 for (x = 1; x < xsize; x++)
4427 for (y = 1; y < ysize; y++)
4429 if (is_extra_bold(y1+y, x1+x))
4431 /* clear the untouched region */
4432 place_floor_bold(y1 + y, x1 + x);
4433 cave[y1 + y][x1 + x].info |= (CAVE_ROOM | CAVE_ICKY);
4437 /* make it a room- but don't touch */
4438 cave[y1 + y][x1 + x].info |= (CAVE_ROOM | CAVE_ICKY);
4445 /* Create a random vault that looks like a collection of overlapping rooms */
4447 static void build_room_vault(int x0, int y0, int xsize, int ysize)
4449 int i, x1, x2, y1, y2, xhsize, yhsize;
4451 /* get offset from center */
4455 if (cheat_room) msg_print("Room Vault");
4457 /* fill area so don't get problems with arena levels */
4458 for (x1 = 0; x1 < xsize; x1++)
4460 int x = x0 - xhsize + x1;
4462 for (y1 = 0; y1 < ysize; y1++)
4464 int y = y0 - yhsize + y1;
4466 place_extra_bold(y, x);
4467 cave[y][x].info &= (~CAVE_ICKY);
4471 /* add ten random rooms */
4472 for (i = 0; i < 10; i++)
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);
4481 /* Add some random doors */
4482 for (i = 0; i < 500; i++)
4484 x1 = randint1(xsize - 3) - xhsize + x0 + 1;
4485 y1 = randint1(ysize - 3) - yhsize + y0 + 1;
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);
4494 /* Create a random vault out of a fractal cave */
4495 static void build_cave_vault(int x0, int y0, int xsiz, int ysiz)
4497 int grd, roug, cutoff, xhsize, yhsize, xsize, ysize, x, y;
4498 bool done, light, room;
4500 /* round to make sizes even */
4506 if (cheat_room) msg_print("Cave Vault");
4508 light = done = FALSE;
4513 /* testing values for these parameters feel free to adjust */
4514 grd = 1 << randint0(4);
4516 /* want average of about 16 */
4517 roug = randint1(8) * randint1(4);
4520 cutoff = randint1(xsize / 4) + randint1(ysize / 4) +
4521 randint1(xsize / 4) + randint1(ysize / 4);
4524 generate_hmap(y0, x0, xsize, ysize, grd, roug, cutoff);
4526 /* Convert to normal format+ clean up */
4527 done = generate_fracave(y0, x0, xsize, ysize, cutoff, light, room);
4530 /* Set icky flag because is a vault */
4531 for (x = 0; x <= xsize; x++)
4533 for (y = 0; y <= ysize; y++)
4535 cave[y0 - yhsize + y][x0 - xhsize + x].info |= CAVE_ICKY;
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));
4544 * maze vault -- rectangular labyrinthine rooms
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
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.
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.
4561 static void r_visit(int y1, int x1, int y2, int x2,
4562 int node, int dir, int *visited)
4564 int i, j, m, n, temp, x, y, adj[4];
4566 /* dimensions of vertex array */
4567 m = (x2 - x1) / 2 + 1;
4568 n = (y2 - y1) / 2 + 1;
4570 /* mark node visited and set it to a floor */
4572 x = 2 * (node % m) + x1;
4573 y = 2 * (node / m) + y1;
4574 place_floor_bold(y, x);
4576 /* setup order of adjacent node visits */
4579 /* pick a random ordering */
4580 for (i = 0; i < 4; i++)
4582 for (i = 0; i < 4; i++)
4593 /* pick a random ordering with dir first */
4595 for (i = 1; i < 4; i++)
4597 for (i = 1; i < 4; i++)
4599 j = 1 + randint0(3);
4606 for (i = 0; i < 4; i++)
4611 /* (0,+) - check for bottom boundary */
4612 if ((node / m < n - 1) && (visited[node + m] == 0))
4614 place_floor_bold(y + 1, x);
4615 r_visit(y1, x1, y2, x2, node + m, dir, visited);
4619 /* (0,-) - check for top boundary */
4620 if ((node / m > 0) && (visited[node - m] == 0))
4622 place_floor_bold(y - 1, x);
4623 r_visit(y1, x1, y2, x2, node - m, dir, visited);
4627 /* (+,0) - check for right boundary */
4628 if ((node % m < m - 1) && (visited[node + 1] == 0))
4630 place_floor_bold(y, x + 1);
4631 r_visit(y1, x1, y2, x2, node + 1, dir, visited);
4635 /* (-,0) - check for left boundary */
4636 if ((node % m > 0) && (visited[node - 1] == 0))
4638 place_floor_bold(y, x - 1);
4639 r_visit(y1, x1, y2, x2, node - 1, dir, visited);
4646 void build_maze_vault(int x0, int y0, int xsize, int ysize, bool is_vault)
4650 int m, n, num_vertices, *visited;
4655 if (cheat_room && is_vault) msg_print("Maze Vault");
4657 /* Choose lite or dark */
4658 light = ((dun_level <= randint1(25)) && is_vault && !(d_info[dungeon_type].flags1 & DF1_DARKNESS));
4660 /* Pick a random room size - randomized by calling routine */
4669 /* generate the room */
4670 for (y = y1 - 1; y <= y2 + 1; y++)
4672 for (x = x1 - 1; x <= x2 + 1; x++)
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))
4679 place_outer_grid(c_ptr);
4683 place_extra_grid(c_ptr);
4687 place_inner_grid(c_ptr);
4689 if (light) c_ptr->info |= (CAVE_GLOW);
4693 /* dimensions of vertex array */
4696 num_vertices = m * n;
4698 /* initialize array of visited vertices */
4699 C_MAKE(visited, num_vertices, int);
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);
4704 /* Fill with monsters and treasure, low difficulty */
4705 if (is_vault) fill_treasure(x1, x2, y1, y2, randint1(5));
4707 C_KILL(visited, num_vertices, int);
4711 /* Build a "mini" checkerboard vault
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.
4718 static void build_mini_c_vault(int x0, int y0, int xsize, int ysize)
4721 int y1, x1, y2, x2, y, x, total;
4722 int m, n, num_vertices;
4725 if (cheat_room) msg_print("Mini Checker Board Vault");
4727 /* Pick a random room size */
4737 /* generate the room */
4738 for (x = x1 - 2; x <= x2 + 2; x++)
4740 if (!in_bounds(y1-2,x)) break;
4742 cave[y1-2][x].info |= (CAVE_ROOM | CAVE_ICKY);
4744 place_outer_noperm_bold(y1-2, x);
4747 for (x = x1 - 2; x <= x2 + 2; x++)
4749 if (!in_bounds(y2+2,x)) break;
4751 cave[y2+2][x].info |= (CAVE_ROOM | CAVE_ICKY);
4753 place_outer_noperm_bold(y2+2, x);
4756 for (y = y1 - 2; y <= y2 + 2; y++)
4758 if (!in_bounds(y,x1-2)) break;
4760 cave[y][x1-2].info |= (CAVE_ROOM | CAVE_ICKY);
4762 place_outer_noperm_bold(y, x1-2);
4765 for (y = y1 - 2; y <= y2 + 2; y++)
4767 if (!in_bounds(y,x2+2)) break;
4769 cave[y][x2+2].info |= (CAVE_ROOM | CAVE_ICKY);
4771 place_outer_noperm_bold(y, x2+2);
4774 for (y = y1 - 1; y <= y2 + 1; y++)
4776 for (x = x1 - 1; x <= x2 + 1; x++)
4778 cave_type *c_ptr = &cave[y][x];
4780 c_ptr->info |= (CAVE_ROOM | CAVE_ICKY);
4782 /* Permanent walls */
4783 place_inner_perm_grid(c_ptr);
4788 /* dimensions of vertex array */
4791 num_vertices = m * n;
4793 /* initialize array of visited vertices */
4794 C_MAKE(visited, num_vertices, int);
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);
4799 /* Make it look like a checker board vault */
4800 for (x = x1; x <= x2; x++)
4802 for (y = y1; y <= y2; y++)
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))
4808 place_inner_bold(y, x);
4813 /* Make a couple of entrances */
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);
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);
4829 /* Fill with monsters and treasure, highest difficulty */
4830 fill_treasure(x1, x2, y1, y2, 10);
4832 C_KILL(visited, num_vertices, int);
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.
4840 * The power variable is a measure of how well defended a region is.
4841 * This alters the possible choices.
4843 static void build_recursive_room(int x1, int y1, int x2, int y2, int power)
4849 /* Temp variables */
4855 if ((power < 3) && (xsize > 12) && (ysize > 12))
4857 /* Need outside wall +keep */
4864 /* Make rooms + subdivide */
4865 if ((randint1(10) > 2) && (xsize < 8) && (ysize < 8))
4871 choice = randint1(2) + 1;
4876 /* Mostly subdivide */
4877 choice = randint1(3) + 1;
4881 /* Based on the choice made above, do something */
4889 /* top and bottom */
4890 for (x = x1; x <= x2; x++)
4892 place_outer_bold(y1, x);
4893 place_outer_bold(y2, x);
4896 /* left and right */
4897 for (y = y1 + 1; y < y2; y++)
4899 place_outer_bold(y, x1);
4900 place_outer_bold(y, x2);
4903 /* Make a couple of entrances */
4906 /* left and right */
4907 y = randint1(ysize) + y1;
4908 place_floor_bold(y, x1);
4909 place_floor_bold(y, x2);
4913 /* top and bottom */
4914 x = randint1(xsize) + x1;
4915 place_floor_bold(y1, x);
4916 place_floor_bold(y2, x);
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);
4925 /* Do outside areas */
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);
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);
4935 /* Make the keep itself: */
4948 /* Try to build a room */
4949 if ((xsize < 3) || (ysize < 3))
4951 for (y = y1; y < y2; y++)
4953 for (x = x1; x < x2; x++)
4955 place_inner_bold(y, x);
4963 /* Make outside walls */
4964 /* top and bottom */
4965 for (x = x1 + 1; x <= x2 - 1; x++)
4967 place_inner_bold(y1 + 1, x);
4968 place_inner_bold(y2 - 1, x);
4971 /* left and right */
4972 for (y = y1 + 1; y <= y2 - 1; y++)
4974 place_inner_bold(y, x1 + 1);
4975 place_inner_bold(y, x2 - 1);
4979 y = randint1(ysize - 3) + y1 + 1;
4984 place_floor_bold(y, x1 + 1);
4989 place_floor_bold(y, x2 - 1);
4992 /* Build the room */
4993 build_recursive_room(x1 + 2, y1 + 2, x2 - 2, y2 - 2, power + 3);
4998 /* Try and divide vertically */
5002 for (y = y1; y < y2; y++)
5004 for (x = x1; x < x2; x++)
5006 place_inner_bold(y, x);
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);
5019 /* Try and divide horizontally */
5023 for (y = y1; y < y2; y++)
5025 for (x = x1; x < x2; x++)
5027 place_inner_bold(y, x);
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);
5042 /* Build a castle */
5044 /* Driver routine: clear the region and call the recursive
5047 *This makes a vault that looks like a castle/ city in the dungeon.
5049 static void build_castle_vault(int x0, int y0, int xsize, int ysize)
5055 /* Pick a random room size */
5064 if (cheat_room) msg_print("Castle Vault");
5066 /* generate the room */
5067 for (y = y1 - 1; y <= y2 + 1; y++)
5069 for (x = x1 - 1; x <= x2 + 1; x++)
5071 cave[y][x].info |= (CAVE_ROOM | CAVE_ICKY);
5072 /* Make everything a floor */
5073 place_floor_bold(y, x);
5077 /* Make the castle */
5078 build_recursive_room(x1, y1, x2, y2, randint1(5));
5080 /* Fill with monsters and treasure, low difficulty */
5081 fill_treasure(x1, x2, y1, y2, randint1(3));
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
5090 static void add_outer_wall(int x, int y, int light, int x1, int y1, int x2, int y2)
5093 feature_type *f_ptr;
5096 if (!in_bounds(y, x)) return;
5098 c_ptr = &cave[y][x];
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;
5105 c_ptr->info |= CAVE_ROOM;
5107 f_ptr = &f_info[c_ptr->feat];
5109 if (is_floor_bold(y, x))
5111 for (i = -1; i <= 1; i++)
5113 for (j = -1; j <= 1; j++)
5115 if ((x + i >= x1) && (x + i <= x2) &&
5116 (y + j >= y1) && (y + j <= y2))
5118 add_outer_wall(x + i, y + j, light, x1, y1, x2, y2);
5119 if (light) c_ptr->info |= CAVE_GLOW;
5124 else if (is_extra_bold(y, x))
5126 /* Set bounding walls */
5127 place_outer_bold(y, x);
5128 if (light) c_ptr->info |= CAVE_GLOW;
5130 else if (permanent_wall(f_ptr))
5132 /* Set bounding walls */
5133 if (light) c_ptr->info |= CAVE_GLOW;
5139 * Hacked distance formula - gives the 'wrong' answer.
5140 * Used to build crypts
5142 static int dist2(int x1, int y1, int x2, int y2,
5143 int h1, int h2, int h3, int h4)
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.)
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) */
5166 * Build target vault.
5167 * This is made by two concentric "crypts" with perpendicular
5168 * walls creating the cross-hairs.
5170 static void build_target_vault(int x0, int y0, int xsize, int ysize)
5174 /* Make a random metric */
5176 h1 = randint1(32) - 16;
5179 h4 = randint1(32) - 16;
5181 if (cheat_room) msg_print("Target Vault");
5183 /* work out outer radius */
5194 for (x = x0 - rad; x <= x0 + rad; x++)
5196 for (y = y0 - rad; y <= y0 + rad; y++)
5198 /* clear room flag */
5199 cave[y][x].info &= ~(CAVE_ROOM);
5201 /* Vault - so is "icky" */
5202 cave[y][x].info |= CAVE_ICKY;
5204 if (dist2(y0, x0, y, x, h1, h2, h3, h4) <= rad - 1)
5206 /* inside- so is floor */
5207 place_floor_bold(y, x);
5211 /* make granite outside so arena works */
5212 place_extra_bold(y, x);
5215 /* proper boundary for arena */
5216 if (((y + rad) == y0) || ((y - rad) == y0) ||
5217 ((x + rad) == x0) || ((x - rad) == x0))
5219 place_extra_bold(y, x);
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);
5228 /* Add inner wall */
5229 for (x = x0 - rad / 2; x <= x0 + rad / 2; x++)
5231 for (y = y0 - rad / 2; y <= y0 + rad / 2; y++)
5233 if (dist2(y0, x0, y, x, h1, h2, h3, h4) == rad / 2)
5235 /* Make an internal wall */
5236 place_inner_bold(y, x);
5241 /* Add perpendicular walls */
5242 for (x = x0 - rad; x <= x0 + rad; x++)
5244 place_inner_bold(y0, x);
5247 for (y = y0 - rad; y <= y0 + rad; y++)
5249 place_inner_bold(y, x0);
5252 /* Make inner vault */
5253 for (y = y0 - 1; y <= y0 + 1; y++)
5255 place_inner_bold(y, x0 - 1);
5256 place_inner_bold(y, x0 + 1);
5258 for (x = x0 - 1; x <= x0 + 1; x++)
5260 place_inner_bold(y0 - 1, x);
5261 place_inner_bold(y0 + 1, x);
5264 place_floor_bold(y0, x0);
5267 /* Add doors to vault */
5268 /* get two distances so can place doors relative to centre */
5269 x = (rad - 2) / 4 + 1;
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);
5281 /* Fill with stuff - medium difficulty */
5282 fill_treasure(x0 - rad, x0 + rad, y0 - rad, y0 + rad, randint1(3) + 3);
5286 #ifdef ALLOW_CAVERNS_AND_LAKES
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.
5292 * Miniture rooms are then scattered across the vault.
5294 static void build_elemental_vault(int x0, int y0, int xsiz, int ysiz)
5299 int xsize, ysize, xhsize, yhsize, x, y, i;
5303 if (cheat_room) msg_print("Elemental Vault");
5305 /* round to make sizes even */
5313 /* Earth vault (Rubble) */
5314 type = LAKE_T_EARTH_VAULT;
5316 else if (dun_level < 50)
5318 /* Air vault (Trees) */
5319 type = LAKE_T_AIR_VAULT;
5321 else if (dun_level < 75)
5323 /* Water vault (shallow water) */
5324 type = LAKE_T_WATER_VAULT;
5328 /* Fire vault (shallow lava) */
5329 type = LAKE_T_FIRE_VAULT;
5334 /* testing values for these parameters: feel free to adjust */
5335 grd = 1 << (randint0(3));
5337 /* want average of about 16 */
5338 roug = randint1(8) * randint1(4);
5340 /* Make up size of various componants */
5344 /* Deep water/lava */
5345 c1 = randint0(c3 / 2) + randint0(c3 / 2) - 5;
5347 /* Shallow boundary */
5351 generate_hmap(y0, x0, xsize, ysize, grd, roug, c3);
5353 /* Convert to normal format+ clean up */
5354 done = generate_lake(y0, x0, xsize, ysize, c1, c2, c3, type);
5357 /* Set icky flag because is a vault */
5358 for (x = 0; x <= xsize; x++)
5360 for (y = 0; y <= ysize; y++)
5362 cave[y0 - yhsize + y][x0 - xhsize + x].info |= CAVE_ICKY;
5366 /* make a few rooms in the vault */
5367 for (i = 1; i <= (xsize * ysize) / 50; i++)
5369 build_small_room(x0 + randint0(xsize - 4) - xsize / 2 + 2,
5370 y0 + randint0(ysize - 4) - ysize / 2 + 2);
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));
5377 #endif /* ALLOW_CAVERNS_AND_LAKES */
5383 static bool build_type10(void)
5385 int y0, x0, xsize, ysize, vtype;
5388 /* big enough to look good, small enough to be fairly common. */
5389 xsize = randint1(22) + 22;
5390 ysize = randint1(11) + 11;
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;
5395 /* Select type of vault */
5396 #ifdef ALLOW_CAVERNS_AND_LAKES
5399 vtype = randint1(15);
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 */
5406 vtype = randint1(7);
5408 while ((d_info[dungeon_type].flags1 & DF1_NO_CAVE) &&
5409 ((vtype == 1) || (vtype == 3)));
5410 #endif /* ALLOW_CAVERNS_AND_LAKES */
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. */
5428 default: return FALSE;
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.
5440 * When done fill from the inside to find the walls,
5442 static bool build_type11(void)
5444 int rad, x, y, x0, y0;
5447 /* Occasional light */
5448 if ((randint1(dun_level) <= 15) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS)) light = TRUE;
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;
5455 /* Make circular floor */
5456 for (x = x0 - rad; x <= x0 + rad; x++)
5458 for (y = y0 - rad; y <= y0 + rad; y++)
5460 if (distance(y0, x0, y, x) <= rad - 1)
5462 /* inside- so is floor */
5463 place_floor_bold(y, x);
5465 else if (distance(y0, x0, y, x) <= rad + 1)
5467 /* make granite outside so arena works */
5468 place_extra_bold(y, x);
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);
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.
5485 * When done fill from the inside to find the walls,
5487 static bool build_type12(void)
5489 int rad, x, y, x0, y0;
5491 bool emptyflag = TRUE;
5493 /* Make a random metric */
5495 h1 = randint1(32) - 16;
5498 h4 = randint1(32) - 16;
5500 /* Occasional light */
5501 if ((randint1(dun_level) <= 5) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS)) light = TRUE;
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;
5509 for (x = x0 - rad; x <= x0 + rad; x++)
5511 for (y = y0 - rad; y <= y0 + rad; y++)
5513 /* clear room flag */
5514 cave[y][x].info &= ~(CAVE_ROOM);
5516 if (dist2(y0, x0, y, x, h1, h2, h3, h4) <= rad - 1)
5518 /* inside - so is floor */
5519 place_floor_bold(y, x);
5521 else if (distance(y0, x0, y, x) < 3)
5523 place_floor_bold(y, x);
5527 /* make granite outside so arena works */
5528 place_extra_bold(y, x);
5531 /* proper boundary for arena */
5532 if (((y + rad) == y0) || ((y - rad) == y0) ||
5533 ((x + rad) == x0) || ((x - rad) == x0))
5535 place_extra_bold(y, x);
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);
5544 /* Check to see if there is room for an inner vault */
5545 for (x = x0 - 2; x <= x0 + 2; x++)
5547 for (y = y0 - 2; y <= y0 + 2; y++)
5549 if (!is_floor_bold(y, x))
5551 /* Wall in the way */
5557 if (emptyflag && one_in_(2))
5559 /* Build the vault */
5560 build_small_room(x0, y0);
5562 /* Place a treasure in the vault */
5563 place_object(y0, x0, 0L);
5565 /* Let's guard the treasure well */
5566 vault_monsters(y0, x0, randint0(2) + 3);
5568 /* Traps naturally */
5569 vault_traps(y0, x0, 4, 4, randint0(3) + 2);
5577 * Helper function for "trapped monster pit"
5579 static bool vault_aux_trapped_pit(int r_idx)
5581 monster_race *r_ptr = &r_info[r_idx];
5583 /* Validate the monster */
5584 if (!vault_monster_okay(r_idx)) return (FALSE);
5586 /* No wall passing monster */
5587 if (r_ptr->flags2 & (RF2_PASS_WALL | RF2_KILL_WALL)) return (FALSE);
5595 * Type 13 -- Trapped monster pits
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
5602 * The trapped monster pit appears as shown below, where the actual
5603 * monsters in each location depend on the type of the pit
5605 * #########################
5607 * ####################### #
5608 * #####001123454321100### #
5609 * ###0012234567654322100# #
5610 * ####################### #
5612 * # #######################
5613 * # #0012234567654322100###
5614 * # ###001123454321100#####
5615 * # #######################
5617 * #########################
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.
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.
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.
5633 * Note that the "get_mon_num()" function may (rarely) fail, in which case
5634 * the pit will be empty.
5636 * Note that "monster pits" will never contain "unique" monsters.
5638 static bool build_type13(void)
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},
5669 int y, x, y1, x1, y2, x2, xval, yval;
5678 int cur_pit_type = pick_vault_type(pit_types, d_info[dungeon_type].pit);
5679 vault_aux_type *n_ptr;
5681 /* Only in Angband */
5682 if (dungeon_type != DUNGEON_ANGBAND) return FALSE;
5684 /* No type available */
5685 if (cur_pit_type < 0) return FALSE;
5687 n_ptr = &pit_types[cur_pit_type];
5689 /* Process a preparation function if necessary */
5690 if (n_ptr->prep_func) (*(n_ptr->prep_func))();
5692 /* Prepare allocation table */
5693 get_mon_num_prep(n_ptr->hook_func, vault_aux_trapped_pit);
5695 align.sub_align = SUB_ALIGN_NEUTRAL;
5697 /* Pick some monster types */
5698 for (i = 0; i < 16; i++)
5700 int r_idx = 0, attempts = 100;
5701 monster_race *r_ptr = NULL;
5705 /* Get a (hard) monster type */
5706 r_idx = get_mon_num(dun_level + 0);
5707 r_ptr = &r_info[r_idx];
5709 /* Decline incorrect alignment */
5710 if (monster_has_hostile_align(&align, 0, 0, r_ptr)) continue;
5712 /* Accept this monster */
5716 /* Notice failure */
5717 if (!r_idx || !attempts) return FALSE;
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;
5726 /* Find and reserve some space in the dungeon. Get center of room. */
5727 if (!find_space(&yval, &xval, 13, 25)) return FALSE;
5735 /* Fill with inner walls */
5736 for (y = y1 - 1; y <= y2 + 1; y++)
5738 for (x = x1 - 1; x <= x2 + 1; x++)
5740 c_ptr = &cave[y][x];
5741 place_inner_grid(c_ptr);
5742 c_ptr->info |= (CAVE_ROOM);
5746 /* Place the floor area 1 */
5747 for (x = x1 + 3; x <= x2 - 3; x++)
5749 c_ptr = &cave[yval-2][x];
5750 place_floor_grid(c_ptr);
5751 add_cave_info(yval-2, x, CAVE_ICKY);
5753 c_ptr = &cave[yval+2][x];
5754 place_floor_grid(c_ptr);
5755 add_cave_info(yval+2, x, CAVE_ICKY);
5758 /* Place the floor area 2 */
5759 for (x = x1 + 5; x <= x2 - 5; x++)
5761 c_ptr = &cave[yval-3][x];
5762 place_floor_grid(c_ptr);
5763 add_cave_info(yval-3, x, CAVE_ICKY);
5765 c_ptr = &cave[yval+3][x];
5766 place_floor_grid(c_ptr);
5767 add_cave_info(yval+3, x, CAVE_ICKY);
5771 for (x = x1; x <= x2; x++)
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);
5781 /* Place the outer walls */
5782 for (y = y1 - 1; y <= y2 + 1; y++)
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);
5789 for (x = x1 - 1; x <= x2 + 1; x++)
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);
5797 /* Random corridor */
5800 for (y = y1; y <= yval; y++)
5802 place_floor_bold(y, x2);
5803 place_solid_bold(y, x1-1);
5805 for (y = yval; y <= y2 + 1; y++)
5807 place_floor_bold(y, x1);
5808 place_solid_bold(y, x2+1);
5813 for (y = yval; y <= y2 + 1; y++)
5815 place_floor_bold(y, x1);
5816 place_solid_bold(y, x2+1);
5818 for (y = y1; y <= yval; y++)
5820 place_floor_bold(y, x2);
5821 place_solid_bold(y, x1-1);
5825 /* Place the wall open trap */
5826 cave[yval][xval].mimic = cave[yval][xval].feat;
5827 cave[yval][xval].feat = feat_trap_open;
5829 /* Sort the entries */
5830 for (i = 0; i < 16 - 1; i++)
5832 /* Sort the entries */
5833 for (j = 0; j < 16 - 1; j++)
5838 int p1 = r_info[what[i1]].level;
5839 int p2 = r_info[what[i2]].level;
5845 what[i1] = what[i2];
5856 msg_format("%s%s¤Î櫥ԥåÈ", n_ptr->name, pit_subtype_string(cur_pit_type, FALSE));
5858 msg_format("Trapped monster pit (%s%s)", n_ptr->name, pit_subtype_string(cur_pit_type, FALSE));
5862 /* Select the entries */
5863 for (i = 0; i < 8; i++)
5865 /* Every other entry */
5866 what[i] = what[i * 2];
5871 msg_print(r_name + r_info[what[i]].name);
5875 for (i = 0; placing[i][2] >= 0; i++)
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);
5887 * Type 14 -- trapped rooms
5889 * A special trap is placed at center of the room
5891 static bool build_type14(void)
5893 int y, x, y2, x2, yval, xval;
5894 int y1, x1, xsize, ysize;
5901 /* Pick a room size */
5907 xsize = x1 + x2 + 1;
5908 ysize = y1 + y2 + 1;
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;
5913 /* Choose lite or dark */
5914 light = ((dun_level <= randint1(25)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS));
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;
5924 /* Place a full floor under the room */
5925 for (y = y1 - 1; y <= y2 + 1; y++)
5927 for (x = x1 - 1; x <= x2 + 1; x++)
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);
5936 /* Walls around the room */
5937 for (y = y1 - 1; y <= y2 + 1; y++)
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);
5944 for (x = x1 - 1; x <= x2 + 1; x++)
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);
5952 if (dun_level < 30 + randint1(30))
5953 trap = feat_trap_piranha;
5955 trap = feat_trap_armageddon;
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;
5966 msg_format("%s¤ÎÉô²°", f_name + f_info[trap].name);
5968 msg_format("Room of %s", f_name + f_info[trap].name);
5977 * Helper function for "glass room"
5979 static bool vault_aux_lite(int r_idx)
5981 monster_race *r_ptr = &r_info[r_idx];
5983 /* Validate the monster */
5984 if (!vault_monster_okay(r_idx)) return FALSE;
5986 /* Require lite attack */
5987 if (!(r_ptr->flags4 & RF4_BR_LITE) && !(r_ptr->flags5 & RF5_BA_LITE)) return FALSE;
5989 /* No wall passing monsters */
5990 if (r_ptr->flags2 & (RF2_PASS_WALL | RF2_KILL_WALL)) return FALSE;
5992 /* No disintegrating monsters */
5993 if (r_ptr->flags4 & RF4_BR_DISI) return FALSE;
5999 * Helper function for "glass room"
6001 static bool vault_aux_shards(int r_idx)
6003 monster_race *r_ptr = &r_info[r_idx];
6005 /* Validate the monster */
6006 if (!vault_monster_okay(r_idx)) return FALSE;
6008 /* Require shards breath attack */
6009 if (!(r_ptr->flags4 & RF4_BR_SHAR)) return FALSE;
6015 * Hack -- determine if a template is potion
6017 static bool kind_is_potion(int k_idx)
6019 return k_info[k_idx].tval == TV_POTION;
6023 * Type 15 -- glass rooms
6025 static bool build_type15(void)
6027 int y, x, y2, x2, yval, xval;
6028 int y1, x1, xsize, ysize;
6033 /* Pick a room size */
6034 xsize = rand_range(9, 13);
6035 ysize = rand_range(9, 13);
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;
6040 /* Choose lite or dark */
6041 light = ((dun_level <= randint1(25)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS));
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;
6049 /* Place a full floor under the room */
6050 for (y = y1 - 1; y <= y2 + 1; y++)
6052 for (x = x1 - 1; x <= x2 + 1; x++)
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);
6062 /* Walls around the room */
6063 for (y = y1 - 1; y <= y2 + 1; y++)
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;
6072 for (x = x1 - 1; x <= x2 + 1; x++)
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;
6082 switch (randint1(3))
6084 case 1: /* 4 lite breathers + potion */
6088 /* Prepare allocation table */
6089 get_mon_num_prep(vault_aux_lite, NULL);
6091 /* Place fixed lite berathers */
6092 for (dir1 = 4; dir1 < 8; dir1++)
6094 int r_idx = get_mon_num(dun_level);
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);
6100 /* Walls around the breather */
6101 for (dir2 = 0; dir2 < 8; dir2++)
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;
6109 /* Walls around the potion */
6110 for (dir1 = 0; dir1 < 4; dir1++)
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);
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;
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);
6135 case 2: /* 1 lite breather + random object */
6140 c_ptr = &cave[y1 + 1][x1 + 1];
6141 place_inner_grid(c_ptr);
6142 c_ptr->feat = feat_glass_wall;
6144 c_ptr = &cave[y1 + 1][x2 - 1];
6145 place_inner_grid(c_ptr);
6146 c_ptr->feat = feat_glass_wall;
6148 c_ptr = &cave[y2 - 1][x1 + 1];
6149 place_inner_grid(c_ptr);
6150 c_ptr->feat = feat_glass_wall;
6152 c_ptr = &cave[y2 - 1][x2 - 1];
6153 place_inner_grid(c_ptr);
6154 c_ptr->feat = feat_glass_wall;
6156 /* Prepare allocation table */
6157 get_mon_num_prep(vault_aux_lite, NULL);
6159 r_idx = get_mon_num(dun_level);
6160 if (r_idx) place_monster_aux(0, yval, xval, r_idx, 0L);
6162 /* Walls around the breather */
6163 for (dir1 = 0; dir1 < 8; dir1++)
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;
6170 /* Curtains around the breather */
6171 for (y = yval - 1; y <= yval + 1; y++)
6173 place_closed_door(y, xval - 2, DOOR_CURTAIN);
6174 place_closed_door(y, xval + 2, DOOR_CURTAIN);
6176 for (x = xval - 1; x <= xval + 1; x++)
6178 place_closed_door(yval - 2, x, DOOR_CURTAIN);
6179 place_closed_door(yval + 2, x, DOOR_CURTAIN);
6182 /* Place an object */
6183 place_object(yval, xval, AM_NO_FIXED_ART);
6184 cave[yval][xval].info |= (CAVE_ICKY);
6188 case 3: /* 4 shards breathers + 2 potions */
6192 /* Walls around the potion */
6193 for (y = yval - 2; y <= yval + 2; y++)
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;
6202 for (x = xval - 2; x <= xval + 2; x++)
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;
6211 for (dir1 = 4; dir1 < 8; dir1++)
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;
6218 /* Prepare allocation table */
6219 get_mon_num_prep(vault_aux_shards, NULL);
6221 /* Place shard berathers */
6222 for (dir1 = 4; dir1 < 8; dir1++)
6224 int r_idx = get_mon_num(dun_level);
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);
6231 /* Place two potions */
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);
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);
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);
6259 msg_print("¥¬¥é¥¹¤ÎÉô²°");
6261 msg_print("Glass room");
6269 /* Create a new floor room with optional light */
6270 void generate_room_floor(int y1, int x1, int y2, int x2, int light)
6276 for (y = y1; y <= y2; y++)
6278 for (x = x1; x <= x2; x++)
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);
6289 void generate_fill_perm_bold(int y1, int x1, int y2, int x2)
6293 for (y = y1; y <= y2; y++)
6295 for (x = x1; x <= x2; x++)
6298 place_extra_perm_bold(y, x);
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)
6309 /* Struct for build underground buildings */
6312 int y0, x0; /* North-west corner (relative) */
6313 int y1, x1; /* South-east corner (relative) */
6317 ugbldg_type *ugbldg;
6320 * Precalculate buildings' location of underground arcade
6322 static bool precalc_ugarcade(int town_hgt, int town_wid, int n)
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;
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;
6335 /* Calculate building locations */
6336 for (i = 0; i < n; i++)
6338 cur_ugbldg = &ugbldg[i];
6339 (void)WIPE(cur_ugbldg, ugbldg_type);
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);
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);
6357 /* Scan this building's area */
6358 for (abort = FALSE, y = cur_ugbldg->y0; (y <= cur_ugbldg->y1) && !abort; y++)
6360 for (x = cur_ugbldg->x0; x <= cur_ugbldg->x1; x++)
6362 if (ugarcade_used[y][x])
6372 while (abort && attempt); /* Accept this building if no overlapping */
6374 /* Failed to generate underground arcade */
6375 if (!attempt) break;
6378 * Mark to ugarcade_used[][] as "used"
6379 * Note: Building-adjacent grids are included for preventing
6380 * connected bulidings.
6382 for (y = cur_ugbldg->y0 - 1; y <= cur_ugbldg->y1 + 1; y++)
6384 for (x = cur_ugbldg->x0 - 1; x <= cur_ugbldg->x1 + 1; x++)
6386 ugarcade_used[y][x] = TRUE;
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 *);
6395 /* If i < n, generation is not allowed */
6400 * Actually create buildings
6401 * Note: ltcy and ltcx indicate "left top corner".
6403 static void build_stores(int ltcy, int ltcx, int stores[], int n)
6406 ugbldg_type *cur_ugbldg;
6408 for (i = 0; i < n; i++)
6410 cur_ugbldg = &ugbldg[i];
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,
6419 for (i = 0; i < n; i++)
6421 cur_ugbldg = &ugbldg[i];
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);
6428 /* Pick a door direction (S,N,E,W) */
6429 switch (randint0(4))
6434 x = rand_range(cur_ugbldg->x0, cur_ugbldg->x1);
6440 x = rand_range(cur_ugbldg->x0, cur_ugbldg->x1);
6445 y = rand_range(cur_ugbldg->y0, cur_ugbldg->y1);
6451 y = rand_range(cur_ugbldg->y0, cur_ugbldg->y1);
6456 for (j = 0; j < max_f_idx; j++)
6458 if (have_flag(f_info[j].flags, FF_STORE))
6460 if (f_info[j].subtype == stores[i]) break;
6464 /* Clear previous contents, add a store door */
6467 cave_set_feat(ltcy + y, ltcx + x, j);
6470 store_init(NO_TOWN, stores[i]);
6477 * Type 16 -- Underground Arcade
6479 * Town logic flow for generation of new town
6480 * Originally from Vanilla 3.0.3
6482 * We start with a fully wiped cave of normal floors.
6484 * Note that town_gen_hack() plays games with the R.N.G.
6486 * This function does NOT do anything about the owners of the stores,
6487 * nor the contents thereof. It only handles the physical layout.
6489 static bool build_type16(void)
6493 STORE_GENERAL, STORE_ARMOURY, STORE_WEAPON, STORE_TEMPLE,
6494 STORE_ALCHEMIST, STORE_MAGIC, STORE_BLACK, STORE_BOOK,
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;
6502 /* Hack -- If already exist black market, prevent building */
6503 for (y = 0; (y < cur_hgt) && !prevent_bm; y++)
6505 for (x = 0; x < cur_wid; x++)
6507 if (cave[y][x].feat == FF_STORE)
6509 prevent_bm = (f_info[cave[y][x].feat].subtype == STORE_BLACK);
6514 for (i = 0; i < n; i++)
6516 if ((stores[i] == STORE_BLACK) && prevent_bm) stores[i] = stores[--n];
6518 if (!n) return FALSE;
6520 /* Allocate buildings array */
6521 C_MAKE(ugbldg, n, ugbldg_type);
6523 /* If cannot build stores, abort */
6524 if (!precalc_ugarcade(town_hgt, town_wid, n))
6526 /* Free buildings array */
6527 C_KILL(ugbldg, n, ugbldg_type);
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))
6534 /* Free buildings array */
6535 C_KILL(ugbldg, n, ugbldg_type);
6539 /* Get top left corner */
6540 y1 = yval - (town_hgt / 2);
6541 x1 = xval - (town_wid / 2);
6543 /* Generate new room */
6544 generate_room_floor(
6545 y1 + town_hgt / 3, x1 + town_wid / 3,
6546 y1 + town_hgt * 2 / 3, x < x1 + town_wid * 2 / 3, FALSE);
6549 build_stores(y1, x1, stores, n);
6552 if (cheat_room) msg_print("Ãϲ¼³¹");
6554 if (cheat_room) msg_print("Underground Arcade");
6557 /* Free buildings array */
6558 C_KILL(ugbldg, n, ugbldg_type);
6565 * Attempt to build a room of the given type at the given block
6567 * Note that we restrict the number of "crowded" rooms to reduce
6568 * the chance of overflowing the monster list during level creation.
6570 static bool room_build(int typ)
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();
6599 #define MOVE_PLIST(dst, src) (prob_list[dst] += prob_list[src], prob_list[src] = 0)
6602 * [from SAngband (originally from OAngband)]
6604 * Generate rooms in dungeon. Build bigger rooms at first.
6606 bool generate_rooms(void)
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));
6617 /* Number of each type of room on this level */
6618 s16b room_num[ROOM_T_MAX];
6620 /* Limit number of rooms */
6621 int dun_rooms = DUN_ROOMS_MAX * area_size / 100;
6623 /* Assume normal cave */
6624 room_info_type *room_info_ptr = room_info_normal;
6627 * Initialize probability list.
6629 for (i = 0; i < ROOM_T_MAX; i++)
6631 /* No rooms allowed above their minimum depth. */
6632 if (dun_level < room_info_ptr[i].min_level)
6638 prob_list[i] = room_info_ptr[i].prob[level_index];
6643 * XXX -- Various dungeon types and options.
6646 /* Ironman sees only Greater Vaults */
6647 if (ironman_rooms && !((d_info[dungeon_type].flags1 & (DF1_BEGINNER | DF1_CHAMELEON | DF1_SMALLEST))))
6649 for (i = 0; i < ROOM_T_MAX; i++)
6651 if (i == ROOM_T_GREATER_VAULT) prob_list[i] = 1;
6652 else prob_list[i] = 0;
6656 /* Forbidden vaults */
6657 else if (d_info[dungeon_type].flags1 & DF1_NO_VAULT)
6659 prob_list[ROOM_T_LESSER_VAULT] = 0;
6660 prob_list[ROOM_T_GREATER_VAULT] = 0;
6661 prob_list[ROOM_T_RANDOM_VAULT] = 0;
6665 /* NO_CAVE dungeon (Castle)*/
6666 if (d_info[dungeon_type].flags1 & DF1_NO_CAVE)
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);
6673 /* CAVE dungeon (Orc cave etc.) */
6674 else if (d_info[dungeon_type].flags1 & DF1_CAVE)
6676 MOVE_PLIST(ROOM_T_FRACAVE, ROOM_T_NORMAL);
6679 /* No caves when a (random) cavern exists: they look bad */
6680 else if (dun->cavern || dun->empty_level)
6682 prob_list[ROOM_T_FRACAVE] = 0;
6685 /* Forbidden glass rooms */
6686 if (!(d_info[dungeon_type].flags1 & DF1_GLASS_ROOM))
6688 prob_list[ROOM_T_GLASS] = 0;
6691 if (!(d_info[dungeon_type].flags1 & DF1_ARCADE))
6693 prob_list[ROOM_T_ARCADE] = 0;
6697 * Initialize number of rooms,
6698 * And calcurate total probability.
6700 for (total_prob = 0, i = 0; i < ROOM_T_MAX; i++)
6703 total_prob += prob_list[i];
6707 * Prepare the number of rooms, of all types, we should build
6710 for (i = dun_rooms; i > 0; i--)
6713 int rand = randint0(total_prob);
6715 /* Get room_type randomly */
6716 for (room_type = 0; room_type < ROOM_T_MAX; room_type++)
6718 if (rand < prob_list[room_type]) break;
6719 else rand -= prob_list[room_type];
6723 if (room_type >= ROOM_T_MAX) room_type = ROOM_T_NORMAL;
6725 /* Increase the number of rooms of that type we should build. */
6726 room_num[room_type]++;
6732 case ROOM_T_LESSER_VAULT:
6733 case ROOM_T_TRAP_PIT:
6741 case ROOM_T_GREATER_VAULT:
6742 case ROOM_T_RANDOM_VAULT:
6751 * Build each type of room one by one until we cannot build any more.
6752 * [from SAngband (originally from OAngband)]
6756 /* Assume no remaining rooms */
6759 for (i = 0; i < ROOM_T_MAX; i++)
6761 /* What type of room are we building now? */
6762 int room_type = room_build_order[i];
6764 /* Go next if none available */
6765 if (!room_num[room_type]) continue;
6767 /* Use up one unit */
6768 room_num[room_type]--;
6770 /* Build the room. */
6771 if (room_build(room_type))
6773 /* Increase the room built count. */
6776 /* Mark as there was some remaining rooms */
6783 case ROOM_T_TRAP_PIT:
6785 /* Avoid too many monsters */
6788 room_num[ROOM_T_PIT] = 0;
6789 room_num[ROOM_T_NEST] = 0;
6790 room_num[ROOM_T_TRAP_PIT] = 0;
6796 /* Avoid double-town */
6797 room_num[ROOM_T_ARCADE] = 0;
6803 /* End loop if no room remain */
6807 if (rooms_built < 1) return FALSE;
6812 msg_format("Éô²°¿ô: %d", rooms_built);
6814 msg_format("Number of Rooms: %d", rooms_built);