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, 3, 4, 5, 6}, 20}, /*GREATER_V*/
48 {{ 0,100,200,300,400,500,600,700,800,900,999}, 10}, /*FRACAVE */
49 {{ 0, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3}, 10}, /*RANDOM_V */
50 {{ 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40}, 3}, /*OVAL */
51 {{ 1, 6, 12, 18, 24, 30, 36, 42, 48, 54, 60}, 10}, /*CRYPT */
52 {{ 0, 0, 1, 1, 1, 2, 3, 4, 5, 6, 8}, 20}, /*TRAP_PIT */
53 {{ 0, 0, 1, 1, 1, 2, 3, 4, 5, 6, 8}, 20}, /*TRAP */
57 /* Build rooms in descending order of difficulty. */
58 static byte room_build_order[ROOM_T_MAX] = {
76 static void place_locked_door(int y, int x)
78 if (d_info[dungeon_type].flags1 & DF1_NO_DOORS)
80 place_floor_bold(y, x);
84 set_cave_feat(y, x, FEAT_DOOR_HEAD+randint1(7));
85 cave[y][x].info &= ~(CAVE_FLOOR);
89 static void place_secret_door(int y, int x)
91 if (d_info[dungeon_type].flags1 & DF1_NO_DOORS)
93 place_floor_bold(y, x);
97 cave_type *c_ptr = &cave[y][x];
99 /* Create secret door */
100 place_closed_door(y, x);
102 /* Hide by inner wall because this is used in rooms only */
103 c_ptr->mimic = feat_wall_inner;
105 /* Floor type terrain cannot hide a door */
106 if (feat_floor(c_ptr->mimic))
108 c_ptr->feat = c_ptr->mimic;
112 c_ptr->info &= ~(CAVE_FLOOR);
117 * This funtion makes a very small room centred at (x0, y0)
118 * This is used in crypts, and random elemental vaults.
120 * Note - this should be used only on allocated regions
121 * within another room.
123 static void build_small_room(int x0, int y0)
127 for (y = y0 - 1; y <= y0 + 1; y++)
129 place_inner_bold(y, x0 - 1);
130 place_inner_bold(y, x0 + 1);
133 for (x = x0 - 1; x <= x0 + 1; x++)
135 place_inner_bold(y0 - 1, x);
136 place_inner_bold(y0 + 1, x);
139 /* Place a secret door on one side */
142 case 0: place_secret_door(y0, x0 - 1); break;
143 case 1: place_secret_door(y0, x0 + 1); break;
144 case 2: place_secret_door(y0 - 1, x0); break;
145 case 3: place_secret_door(y0 + 1, x0); break;
148 /* Clear mimic type */
149 cave[y0][x0].mimic = 0;
151 /* Add inner open space */
152 place_floor_bold(y0, x0);
157 * This function tunnels around a room if
158 * it will cut off part of a cave system.
160 static void check_room_boundary(int x1, int y1, int x2, int y2)
163 bool old_is_floor, new_is_floor;
169 old_is_floor = get_is_floor(x1 - 1, y1);
172 * Count the number of floor-wall boundaries around the room
173 * Note: diagonal squares are ignored since the player can move diagonally
174 * to bypass these if needed.
177 /* Above the top boundary */
178 for (x = x1; x <= x2; x++)
180 new_is_floor = get_is_floor(x, y1 - 1);
182 /* Increment counter if they are different */
183 if (new_is_floor != old_is_floor) count++;
185 old_is_floor = new_is_floor;
189 for (y = y1; y <= y2; y++)
191 new_is_floor = get_is_floor(x2 + 1, y);
193 /* increment counter if they are different */
194 if (new_is_floor != old_is_floor) count++;
196 old_is_floor = new_is_floor;
199 /* Bottom boundary */
200 for (x = x2; x >= x1; x--)
202 new_is_floor = get_is_floor(x, y2 + 1);
204 /* increment counter if they are different */
205 if (new_is_floor != old_is_floor) count++;
207 old_is_floor = new_is_floor;
211 for (y = y2; y >= y1; y--)
213 new_is_floor = get_is_floor(x1 - 1, y);
215 /* increment counter if they are different */
216 if (new_is_floor != old_is_floor) count++;
218 old_is_floor = new_is_floor;
221 /* If all the same, or only one connection exit. */
222 if (count <= 2) return;
225 /* Tunnel around the room so to prevent problems with caves */
226 for (y = y1; y <= y2; y++)
228 for (x = x1; x <= x2; x++)
237 * Helper function for find_space().
239 * Is this a good location?
241 static bool find_space_aux(int blocks_high, int blocks_wide, int block_y, int block_x)
243 int by1, bx1, by2, bx2, by, bx;
245 /* Itty-bitty rooms must shift about within their rectangle */
248 if ((blocks_wide == 2) && (block_x % 3) == 2)
252 /* Rooms with width divisible by 3 must be fitted to a rectangle. */
253 else if ((blocks_wide % 3) == 0)
255 /* Must be aligned to the left edge of a 11x33 rectangle. */
256 if ((block_x % 3) != 0)
261 * Big rooms that do not have a width divisible by 3 must be
262 * aligned towards the edge of the dungeon closest to them.
266 /* Shift towards left edge of dungeon. */
267 if (block_x + (blocks_wide / 2) <= dun->col_rooms / 2)
269 if (((block_x % 3) == 2) && ((blocks_wide % 3) == 2))
271 if ((block_x % 3) == 1)
275 /* Shift toward right edge of dungeon. */
278 if (((block_x % 3) == 2) && ((blocks_wide % 3) == 2))
280 if ((block_x % 3) == 1)
288 by2 = block_y + blocks_high;
289 bx2 = block_x + blocks_wide;
291 /* Never run off the screen */
292 if ((by1 < 0) || (by2 > dun->row_rooms)) return FALSE;
293 if ((bx1 < 0) || (bx2 > dun->col_rooms)) return FALSE;
295 /* Verify available space */
296 for (by = by1; by < by2; by++)
298 for (bx = bx1; bx < bx2; bx++)
300 if (dun->room_map[by][bx])
307 /* This location is okay */
313 * Find a good spot for the next room. -LM-
315 * Find and allocate a free space in the dungeon large enough to hold
316 * the room calling this function.
318 * We allocate space in 11x11 blocks, but want to make sure that rooms
319 * align neatly on the standard screen. Therefore, we make them use
320 * blocks in few 11x33 rectangles as possible.
322 * Be careful to include the edges of the room in height and width!
324 * Return TRUE and values for the center of the room if all went well.
325 * Otherwise, return FALSE.
327 static bool find_space(int *y, int *x, int height, int width)
329 int candidates, pick;
330 int by, bx, by1, bx1, by2, bx2;
331 int block_y = 0, block_x = 0;
334 /* Find out how many blocks we need. */
335 int blocks_high = 1 + ((height - 1) / BLOCK_HGT);
336 int blocks_wide = 1 + ((width - 1) / BLOCK_WID);
338 /* There are no way to allocate such huge space */
339 if (dun->row_rooms < blocks_high) return FALSE;
340 if (dun->col_rooms < blocks_wide) return FALSE;
343 /* Sometimes, little rooms like to have more space. */
344 if (blocks_wide == 2)
346 if (one_in_(3)) blocks_wide = 3;
348 else if (blocks_wide == 1)
350 if (one_in_(2)) blocks_wide = rand_range(2, 3);
357 /* Count the number of varid places */
358 for (block_y = dun->row_rooms - blocks_high; block_y >= 0; block_y--)
360 for (block_x = dun->col_rooms - blocks_wide; block_x >= 0; block_x--)
362 if (find_space_aux(blocks_high, blocks_wide, block_y, block_x))
364 /* Find a varid place */
376 /* Choose a random one */
377 pick = randint1(candidates);
379 /* Pick up the choosen location */
380 for (block_y = dun->row_rooms - blocks_high; block_y >= 0; block_y--)
382 for (block_x = dun->col_rooms - blocks_wide; block_x >= 0; block_x--)
384 if (find_space_aux(blocks_high, blocks_wide, block_y, block_x))
388 /* This one is picked? */
399 by2 = block_y + blocks_high;
400 bx2 = block_x + blocks_wide;
403 * It is *extremely* important that the following calculation
404 * be *exactly* correct to prevent memory errors
407 /* Acquire the location of the room */
408 (*y) = ((by1 + by2) * BLOCK_HGT) / 2;
409 (*x) = ((bx1 + bx2) * BLOCK_WID) / 2;
411 /* Save the room location */
412 if (dun->cent_n < CENT_MAX)
414 dun->cent[dun->cent_n].y = *y;
415 dun->cent[dun->cent_n].x = *x;
419 /* Reserve some blocks. */
420 for (by = by1; by < by2; by++)
422 for (bx = bx1; bx < bx2; bx++)
424 dun->room_map[by][bx] = TRUE;
430 * Hack- See if room will cut off a cavern.
432 * If so, fix by tunneling outside the room in such a
433 * way as to connect the caves.
435 check_room_boundary(*x - width / 2 - 1, *y - height / 2 - 1, *x + (width - 1) / 2 + 1, *y + (height - 1) / 2 + 1);
445 * Room building routines.
451 * 4 -- large room with features
455 * 8 -- greater vaults
457 * 10 -- random vaults
458 * 11 -- circular rooms
460 * 13 -- trapped monster pits
466 * Type 1 -- normal rectangular rooms
468 static bool build_type1(void)
470 int y, x, y2, x2, yval, xval;
471 int y1, x1, xsize, ysize;
477 /* Pick a room size */
486 /* Find and reserve some space in the dungeon. Get center of room. */
487 if (!find_space(&yval, &xval, ysize + 2, xsize + 2)) return FALSE;
489 /* Choose lite or dark */
490 light = ((dun_level <= randint1(25)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS));
493 /* Get corner values */
494 y1 = yval - ysize / 2;
495 x1 = xval - xsize / 2;
496 y2 = yval + (ysize - 1) / 2;
497 x2 = xval + (xsize - 1) / 2;
500 /* Place a full floor under the room */
501 for (y = y1 - 1; y <= y2 + 1; y++)
503 for (x = x1 - 1; x <= x2 + 1; x++)
506 place_floor_grid(c_ptr);
507 c_ptr->info |= (CAVE_ROOM);
508 if (light) c_ptr->info |= (CAVE_GLOW);
512 /* Walls around the room */
513 for (y = y1 - 1; y <= y2 + 1; y++)
515 c_ptr = &cave[y][x1 - 1];
516 place_outer_grid(c_ptr);
517 c_ptr = &cave[y][x2 + 1];
518 place_outer_grid(c_ptr);
520 for (x = x1 - 1; x <= x2 + 1; x++)
522 c_ptr = &cave[y1 - 1][x];
523 place_outer_grid(c_ptr);
524 c_ptr = &cave[y2 + 1][x];
525 place_outer_grid(c_ptr);
529 /* Hack -- Occasional pillar room */
532 for (y = y1; y <= y2; y += 2)
534 for (x = x1; x <= x2; x += 2)
537 place_inner_grid(c_ptr);
542 /* Hack -- Occasional room with four pillars */
543 else if (one_in_(20))
545 if ((y1 + 4 < y2) && (x1 + 4 < x2))
547 c_ptr = &cave[y1 + 1][x1 + 1];
548 place_inner_grid(c_ptr);
550 c_ptr = &cave[y1 + 1][x2 - 1];
551 place_inner_grid(c_ptr);
553 c_ptr = &cave[y2 - 1][x1 + 1];
554 place_inner_grid(c_ptr);
556 c_ptr = &cave[y2 - 1][x2 - 1];
557 place_inner_grid(c_ptr);
561 /* Hack -- Occasional ragged-edge room */
562 else if (one_in_(50))
564 for (y = y1 + 2; y <= y2 - 2; y += 2)
566 c_ptr = &cave[y][x1];
567 place_inner_grid(c_ptr);
568 c_ptr = &cave[y][x2];
569 place_inner_grid(c_ptr);
571 for (x = x1 + 2; x <= x2 - 2; x += 2)
573 c_ptr = &cave[y1][x];
574 place_inner_grid(c_ptr);
575 c_ptr = &cave[y2][x];
576 place_inner_grid(c_ptr);
579 /* Hack -- Occasional divided room */
580 else if (one_in_(50))
582 if (randint1(100) < 50)
584 /* Horizontal wall */
585 for (x = x1; x <= x2; x++)
587 place_inner_bold(yval, x);
590 /* Prevent edge of wall from being tunneled */
591 place_solid_bold(yval, x1 - 1);
592 place_solid_bold(yval, x2 + 1);
597 for (y = y1; y <= y2; y++)
599 place_inner_bold(y, xval);
602 /* Prevent edge of wall from being tunneled */
603 place_solid_bold(y1 - 1, xval);
604 place_solid_bold(y2 + 1, xval);
607 place_random_door(yval, xval, TRUE);
615 * Type 2 -- Overlapping rectangular rooms
617 static bool build_type2(void)
619 int y, x, xval, yval;
620 int y1a, x1a, y2a, x2a;
621 int y1b, x1b, y2b, x2b;
625 /* Find and reserve some space in the dungeon. Get center of room. */
626 if (!find_space(&yval, &xval, 11, 25)) return FALSE;
628 /* Choose lite or dark */
629 light = ((dun_level <= randint1(25)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS));
631 /* Determine extents of the first room */
632 y1a = yval - randint1(4);
633 y2a = yval + randint1(3);
634 x1a = xval - randint1(11);
635 x2a = xval + randint1(10);
637 /* Determine extents of the second room */
638 y1b = yval - randint1(3);
639 y2b = yval + randint1(4);
640 x1b = xval - randint1(10);
641 x2b = xval + randint1(11);
644 /* Place a full floor for room "a" */
645 for (y = y1a - 1; y <= y2a + 1; y++)
647 for (x = x1a - 1; x <= x2a + 1; x++)
650 place_floor_grid(c_ptr);
651 c_ptr->info |= (CAVE_ROOM);
652 if (light) c_ptr->info |= (CAVE_GLOW);
656 /* Place a full floor for room "b" */
657 for (y = y1b - 1; y <= y2b + 1; y++)
659 for (x = x1b - 1; x <= x2b + 1; x++)
662 place_floor_grid(c_ptr);
663 c_ptr->info |= (CAVE_ROOM);
664 if (light) c_ptr->info |= (CAVE_GLOW);
669 /* Place the walls around room "a" */
670 for (y = y1a - 1; y <= y2a + 1; y++)
672 c_ptr = &cave[y][x1a - 1];
673 place_outer_grid(c_ptr);
674 c_ptr = &cave[y][x2a + 1];
675 place_outer_grid(c_ptr);
677 for (x = x1a - 1; x <= x2a + 1; x++)
679 c_ptr = &cave[y1a - 1][x];
680 place_outer_grid(c_ptr);
681 c_ptr = &cave[y2a + 1][x];
682 place_outer_grid(c_ptr);
685 /* Place the walls around room "b" */
686 for (y = y1b - 1; y <= y2b + 1; y++)
688 c_ptr = &cave[y][x1b - 1];
689 place_outer_grid(c_ptr);
690 c_ptr = &cave[y][x2b + 1];
691 place_outer_grid(c_ptr);
693 for (x = x1b - 1; x <= x2b + 1; x++)
695 c_ptr = &cave[y1b - 1][x];
696 place_outer_grid(c_ptr);
697 c_ptr = &cave[y2b + 1][x];
698 place_outer_grid(c_ptr);
703 /* Replace the floor for room "a" */
704 for (y = y1a; y <= y2a; y++)
706 for (x = x1a; x <= x2a; x++)
709 place_floor_grid(c_ptr);
713 /* Replace the floor for room "b" */
714 for (y = y1b; y <= y2b; y++)
716 for (x = x1b; x <= x2b; x++)
719 place_floor_grid(c_ptr);
729 * Type 3 -- Cross shaped rooms
731 * Builds a room at a row, column coordinate
733 * Room "a" runs north/south, and Room "b" runs east/east
734 * So the "central pillar" runs from x1a, y1b to x2a, y2b.
736 * Note that currently, the "center" is always 3x3, but I think that
737 * the code below will work (with "bounds checking") for 5x5, or even
738 * for unsymetric values like 4x3 or 5x3 or 3x4 or 3x5, or even larger.
740 static bool build_type3(void)
742 int y, x, dy, dx, wy, wx;
743 int y1a, x1a, y2a, x2a;
744 int y1b, x1b, y2b, x2b;
750 /* Find and reserve some space in the dungeon. Get center of room. */
751 if (!find_space(&yval, &xval, 11, 25)) return FALSE;
754 /* Choose lite or dark */
755 light = ((dun_level <= randint1(25)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS));
757 /* For now, always 3x3 */
760 /* Pick max vertical size (at most 4) */
761 dy = rand_range(3, 4);
763 /* Pick max horizontal size (at most 15) */
764 dx = rand_range(3, 11);
767 /* Determine extents of the north/south room */
773 /* Determine extents of the east/west room */
780 /* Place a full floor for room "a" */
781 for (y = y1a - 1; y <= y2a + 1; y++)
783 for (x = x1a - 1; x <= x2a + 1; x++)
786 place_floor_grid(c_ptr);
787 c_ptr->info |= (CAVE_ROOM);
788 if (light) c_ptr->info |= (CAVE_GLOW);
792 /* Place a full floor for room "b" */
793 for (y = y1b - 1; y <= y2b + 1; y++)
795 for (x = x1b - 1; x <= x2b + 1; x++)
798 place_floor_grid(c_ptr);
799 c_ptr->info |= (CAVE_ROOM);
800 if (light) c_ptr->info |= (CAVE_GLOW);
805 /* Place the walls around room "a" */
806 for (y = y1a - 1; y <= y2a + 1; y++)
808 c_ptr = &cave[y][x1a - 1];
809 place_outer_grid(c_ptr);
810 c_ptr = &cave[y][x2a + 1];
811 place_outer_grid(c_ptr);
813 for (x = x1a - 1; x <= x2a + 1; x++)
815 c_ptr = &cave[y1a - 1][x];
816 place_outer_grid(c_ptr);
817 c_ptr = &cave[y2a + 1][x];
818 place_outer_grid(c_ptr);
821 /* Place the walls around room "b" */
822 for (y = y1b - 1; y <= y2b + 1; y++)
824 c_ptr = &cave[y][x1b - 1];
825 place_outer_grid(c_ptr);
826 c_ptr = &cave[y][x2b + 1];
827 place_outer_grid(c_ptr);
829 for (x = x1b - 1; x <= x2b + 1; x++)
831 c_ptr = &cave[y1b - 1][x];
832 place_outer_grid(c_ptr);
833 c_ptr = &cave[y2b + 1][x];
834 place_outer_grid(c_ptr);
838 /* Replace the floor for room "a" */
839 for (y = y1a; y <= y2a; y++)
841 for (x = x1a; x <= x2a; x++)
844 place_floor_grid(c_ptr);
848 /* Replace the floor for room "b" */
849 for (y = y1b; y <= y2b; y++)
851 for (x = x1b; x <= x2b; x++)
854 place_floor_grid(c_ptr);
860 /* Special features (3/4) */
863 /* Large solid middle pillar */
866 for (y = y1b; y <= y2b; y++)
868 for (x = x1a; x <= x2a; x++)
871 place_inner_grid(c_ptr);
877 /* Inner treasure vault */
880 /* Build the vault */
881 for (y = y1b; y <= y2b; y++)
883 c_ptr = &cave[y][x1a];
884 place_inner_grid(c_ptr);
885 c_ptr = &cave[y][x2a];
886 place_inner_grid(c_ptr);
888 for (x = x1a; x <= x2a; x++)
890 c_ptr = &cave[y1b][x];
891 place_inner_grid(c_ptr);
892 c_ptr = &cave[y2b][x];
893 place_inner_grid(c_ptr);
896 /* Place a secret door on the inner room */
899 case 0: place_secret_door(y1b, xval); break;
900 case 1: place_secret_door(y2b, xval); break;
901 case 2: place_secret_door(yval, x1a); break;
902 case 3: place_secret_door(yval, x2a); break;
905 /* Place a treasure in the vault */
906 place_object(yval, xval, 0L);
908 /* Let's guard the treasure well */
909 vault_monsters(yval, xval, randint0(2) + 3);
911 /* Traps naturally */
912 vault_traps(yval, xval, 4, 4, randint0(3) + 2);
920 /* Occasionally pinch the center shut */
923 /* Pinch the east/west sides */
924 for (y = y1b; y <= y2b; y++)
926 if (y == yval) continue;
927 c_ptr = &cave[y][x1a - 1];
928 place_inner_grid(c_ptr);
929 c_ptr = &cave[y][x2a + 1];
930 place_inner_grid(c_ptr);
933 /* Pinch the north/south sides */
934 for (x = x1a; x <= x2a; x++)
936 if (x == xval) continue;
937 c_ptr = &cave[y1b - 1][x];
938 place_inner_grid(c_ptr);
939 c_ptr = &cave[y2b + 1][x];
940 place_inner_grid(c_ptr);
943 /* Sometimes shut using secret doors */
946 place_secret_door(yval, x1a - 1);
947 place_secret_door(yval, x2a + 1);
948 place_secret_door(y1b - 1, xval);
949 place_secret_door(y2b + 1, xval);
953 /* Occasionally put a "plus" in the center */
956 c_ptr = &cave[yval][xval];
957 place_inner_grid(c_ptr);
958 c_ptr = &cave[y1b][xval];
959 place_inner_grid(c_ptr);
960 c_ptr = &cave[y2b][xval];
961 place_inner_grid(c_ptr);
962 c_ptr = &cave[yval][x1a];
963 place_inner_grid(c_ptr);
964 c_ptr = &cave[yval][x2a];
965 place_inner_grid(c_ptr);
968 /* Occasionally put a pillar in the center */
971 c_ptr = &cave[yval][xval];
972 place_inner_grid(c_ptr);
984 * Type 4 -- Large room with inner features
986 * Possible sub-types:
987 * 1 - Just an inner room with one door
988 * 2 - An inner room within an inner room
989 * 3 - An inner room with pillar(s)
990 * 4 - Inner room has a maze
991 * 5 - A set of four inner rooms
993 static bool build_type4(void)
996 int y2, x2, tmp, yval, xval;
1001 /* Find and reserve some space in the dungeon. Get center of room. */
1002 if (!find_space(&yval, &xval, 11, 25)) return FALSE;
1004 /* Choose lite or dark */
1005 light = ((dun_level <= randint1(25)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS));
1013 /* Place a full floor under the room */
1014 for (y = y1 - 1; y <= y2 + 1; y++)
1016 for (x = x1 - 1; x <= x2 + 1; x++)
1018 c_ptr = &cave[y][x];
1019 place_floor_grid(c_ptr);
1020 c_ptr->info |= (CAVE_ROOM);
1021 if (light) c_ptr->info |= (CAVE_GLOW);
1026 for (y = y1 - 1; y <= y2 + 1; y++)
1028 c_ptr = &cave[y][x1 - 1];
1029 place_outer_grid(c_ptr);
1030 c_ptr = &cave[y][x2 + 1];
1031 place_outer_grid(c_ptr);
1033 for (x = x1 - 1; x <= x2 + 1; x++)
1035 c_ptr = &cave[y1 - 1][x];
1036 place_outer_grid(c_ptr);
1037 c_ptr = &cave[y2 + 1][x];
1038 place_outer_grid(c_ptr);
1042 /* The inner room */
1048 /* The inner walls */
1049 for (y = y1 - 1; y <= y2 + 1; y++)
1051 c_ptr = &cave[y][x1 - 1];
1052 place_inner_grid(c_ptr);
1053 c_ptr = &cave[y][x2 + 1];
1054 place_inner_grid(c_ptr);
1056 for (x = x1 - 1; x <= x2 + 1; x++)
1058 c_ptr = &cave[y1 - 1][x];
1059 place_inner_grid(c_ptr);
1060 c_ptr = &cave[y2 + 1][x];
1061 place_inner_grid(c_ptr);
1065 /* Inner room variations */
1066 switch (randint1(5))
1068 /* Just an inner room with a monster */
1071 /* Place a secret door */
1072 switch (randint1(4))
1074 case 1: place_secret_door(y1 - 1, xval); break;
1075 case 2: place_secret_door(y2 + 1, xval); break;
1076 case 3: place_secret_door(yval, x1 - 1); break;
1077 case 4: place_secret_door(yval, x2 + 1); break;
1080 /* Place a monster in the room */
1081 vault_monsters(yval, xval, 1);
1086 /* Treasure Vault (with a door) */
1089 /* Place a secret door */
1090 switch (randint1(4))
1092 case 1: place_secret_door(y1 - 1, xval); break;
1093 case 2: place_secret_door(y2 + 1, xval); break;
1094 case 3: place_secret_door(yval, x1 - 1); break;
1095 case 4: place_secret_door(yval, x2 + 1); break;
1098 /* Place another inner room */
1099 for (y = yval - 1; y <= yval + 1; y++)
1101 for (x = xval - 1; x <= xval + 1; x++)
1103 if ((x == xval) && (y == yval)) continue;
1104 c_ptr = &cave[y][x];
1105 place_inner_grid(c_ptr);
1109 /* Place a locked door on the inner room */
1110 switch (randint1(4))
1112 case 1: place_locked_door(yval - 1, xval); break;
1113 case 2: place_locked_door(yval + 1, xval); break;
1114 case 3: place_locked_door(yval, xval - 1); break;
1115 case 4: place_locked_door(yval, xval + 1); break;
1118 /* Monsters to guard the "treasure" */
1119 vault_monsters(yval, xval, randint1(3) + 2);
1122 if (randint0(100) < 80)
1124 place_object(yval, xval, 0L);
1130 place_random_stairs(yval, xval);
1133 /* Traps to protect the treasure */
1134 vault_traps(yval, xval, 4, 10, 2 + randint1(3));
1139 /* Inner pillar(s). */
1142 /* Place a secret door */
1143 switch (randint1(4))
1145 case 1: place_secret_door(y1 - 1, xval); break;
1146 case 2: place_secret_door(y2 + 1, xval); break;
1147 case 3: place_secret_door(yval, x1 - 1); break;
1148 case 4: place_secret_door(yval, x2 + 1); break;
1151 /* Large Inner Pillar */
1152 for (y = yval - 1; y <= yval + 1; y++)
1154 for (x = xval - 1; x <= xval + 1; x++)
1156 c_ptr = &cave[y][x];
1157 place_inner_grid(c_ptr);
1161 /* Occasionally, two more Large Inner Pillars */
1165 for (y = yval - 1; y <= yval + 1; y++)
1167 for (x = xval - 5 - tmp; x <= xval - 3 - tmp; x++)
1169 c_ptr = &cave[y][x];
1170 place_inner_grid(c_ptr);
1172 for (x = xval + 3 + tmp; x <= xval + 5 + tmp; x++)
1174 c_ptr = &cave[y][x];
1175 place_inner_grid(c_ptr);
1180 /* Occasionally, some Inner rooms */
1183 /* Long horizontal walls */
1184 for (x = xval - 5; x <= xval + 5; x++)
1186 c_ptr = &cave[yval - 1][x];
1187 place_inner_grid(c_ptr);
1188 c_ptr = &cave[yval + 1][x];
1189 place_inner_grid(c_ptr);
1192 /* Close off the left/right edges */
1193 c_ptr = &cave[yval][xval - 5];
1194 place_inner_grid(c_ptr);
1195 c_ptr = &cave[yval][xval + 5];
1196 place_inner_grid(c_ptr);
1198 /* Secret doors (random top/bottom) */
1199 place_secret_door(yval - 3 + (randint1(2) * 2), xval - 3);
1200 place_secret_door(yval - 3 + (randint1(2) * 2), xval + 3);
1203 vault_monsters(yval, xval - 2, randint1(2));
1204 vault_monsters(yval, xval + 2, randint1(2));
1207 if (one_in_(3)) place_object(yval, xval - 2, 0L);
1208 if (one_in_(3)) place_object(yval, xval + 2, 0L);
1217 /* Place a secret door */
1218 switch (randint1(4))
1220 case 1: place_secret_door(y1 - 1, xval); break;
1221 case 2: place_secret_door(y2 + 1, xval); break;
1222 case 3: place_secret_door(yval, x1 - 1); break;
1223 case 4: place_secret_door(yval, x2 + 1); break;
1226 /* Maze (really a checkerboard) */
1227 for (y = y1; y <= y2; y++)
1229 for (x = x1; x <= x2; x++)
1233 c_ptr = &cave[y][x];
1234 place_inner_grid(c_ptr);
1239 /* Monsters just love mazes. */
1240 vault_monsters(yval, xval - 5, randint1(3));
1241 vault_monsters(yval, xval + 5, randint1(3));
1243 /* Traps make them entertaining. */
1244 vault_traps(yval, xval - 3, 2, 8, randint1(3));
1245 vault_traps(yval, xval + 3, 2, 8, randint1(3));
1247 /* Mazes should have some treasure too. */
1248 vault_objects(yval, xval, 3);
1253 /* Four small rooms. */
1257 for (y = y1; y <= y2; y++)
1259 c_ptr = &cave[y][xval];
1260 place_inner_grid(c_ptr);
1262 for (x = x1; x <= x2; x++)
1264 c_ptr = &cave[yval][x];
1265 place_inner_grid(c_ptr);
1268 /* Doors into the rooms */
1269 if (randint0(100) < 50)
1271 int i = randint1(10);
1272 place_secret_door(y1 - 1, xval - i);
1273 place_secret_door(y1 - 1, xval + i);
1274 place_secret_door(y2 + 1, xval - i);
1275 place_secret_door(y2 + 1, xval + i);
1279 int i = randint1(3);
1280 place_secret_door(yval + i, x1 - 1);
1281 place_secret_door(yval - i, x1 - 1);
1282 place_secret_door(yval + i, x2 + 1);
1283 place_secret_door(yval - i, x2 + 1);
1286 /* Treasure, centered at the center of the cross */
1287 vault_objects(yval, xval, 2 + randint1(2));
1289 /* Gotta have some monsters. */
1290 vault_monsters(yval + 1, xval - 4, randint1(4));
1291 vault_monsters(yval + 1, xval + 4, randint1(4));
1292 vault_monsters(yval - 1, xval - 4, randint1(4));
1293 vault_monsters(yval - 1, xval + 4, randint1(4));
1304 * The following functions are used to determine if the given monster
1305 * is appropriate for inclusion in a monster nest or monster pit or
1308 * None of the pits/nests are allowed to include "unique" monsters.
1313 * Monster validation macro
1315 * Line 1 -- forbid town monsters
1316 * Line 2 -- forbid uniques
1317 * Line 3 -- forbid aquatic monsters
1319 #define vault_monster_okay(I) \
1320 (mon_hook_dungeon(I) && \
1321 !(r_info[I].flags1 & RF1_UNIQUE) && \
1322 !(r_info[I].flags7 & RF7_UNIQUE2) && \
1323 !(r_info[I].flagsr & RFR_RES_ALL) && \
1324 !(r_info[I].flags7 & RF7_AQUATIC))
1327 /* Race index for "monster pit (clone)" */
1328 static int vault_aux_race;
1330 /* Race index for "monster pit (symbol clone)" */
1331 static char vault_aux_char;
1333 /* Breath mask for "monster pit (dragon)" */
1334 static u32b vault_aux_dragon_mask4;
1338 * Helper monster selection function
1340 static bool vault_aux_simple(int r_idx)
1343 return (vault_monster_okay(r_idx));
1348 * Helper function for "monster nest (jelly)"
1350 static bool vault_aux_jelly(int r_idx)
1352 monster_race *r_ptr = &r_info[r_idx];
1354 /* Validate the monster */
1355 if (!vault_monster_okay(r_idx)) return (FALSE);
1357 if ((r_ptr->flags2 & RF2_KILL_BODY) && !(r_ptr->flags1 & RF1_NEVER_BLOW)) return (FALSE);
1359 /* Also decline evil jellies (like death molds and shoggoths) */
1360 if (r_ptr->flags3 & (RF3_EVIL)) return (FALSE);
1362 /* Require icky thing, jelly, mold, or mushroom */
1363 if (!strchr("ijm,", r_ptr->d_char)) return (FALSE);
1371 * Helper function for "monster nest (animal)"
1373 static bool vault_aux_animal(int r_idx)
1375 monster_race *r_ptr = &r_info[r_idx];
1377 /* Validate the monster */
1378 if (!vault_monster_okay(r_idx)) return (FALSE);
1380 /* Require "animal" flag */
1381 if (!(r_ptr->flags3 & (RF3_ANIMAL))) return (FALSE);
1389 * Helper function for "monster nest (undead)"
1391 static bool vault_aux_undead(int r_idx)
1393 monster_race *r_ptr = &r_info[r_idx];
1395 /* Validate the monster */
1396 if (!vault_monster_okay(r_idx)) return (FALSE);
1398 /* Require Undead */
1399 if (!(r_ptr->flags3 & (RF3_UNDEAD))) return (FALSE);
1407 * Helper function for "monster nest (chapel)"
1409 static bool vault_aux_chapel_g(int r_idx)
1411 static int chapel_list[] = {
1412 MON_NOV_PRIEST, MON_NOV_PALADIN, MON_NOV_PRIEST_G, MON_NOV_PALADIN_G,
1413 MON_PRIEST, MON_JADE_MONK, MON_IVORY_MONK, MON_ULTRA_PALADIN,
1414 MON_EBONY_MONK, MON_W_KNIGHT, MON_KNI_TEMPLAR, MON_PALADIN,
1419 monster_race *r_ptr = &r_info[r_idx];
1421 /* Validate the monster */
1422 if (!vault_monster_okay(r_idx)) return (FALSE);
1424 if (r_ptr->flags3 & (RF3_EVIL)) return (FALSE);
1425 if ((r_idx == MON_A_GOLD) || (r_idx == MON_A_SILVER)) return (FALSE);
1427 /* Require "priest" or Angel */
1429 if (r_ptr->d_char == 'A') return TRUE;
1431 for (i = 0; chapel_list[i]; i++)
1432 if (r_idx == chapel_list[i]) return TRUE;
1439 * Helper function for "monster nest (kennel)"
1441 static bool vault_aux_kennel(int r_idx)
1443 monster_race *r_ptr = &r_info[r_idx];
1445 /* Validate the monster */
1446 if (!vault_monster_okay(r_idx)) return (FALSE);
1448 /* Require a Zephyr Hound or a dog */
1449 if (!strchr("CZ", r_ptr->d_char)) return (FALSE);
1457 * Helper function for "monster nest (mimic)"
1459 static bool vault_aux_mimic(int r_idx)
1461 monster_race *r_ptr = &r_info[r_idx];
1463 /* Validate the monster */
1464 if (!vault_monster_okay(r_idx)) return (FALSE);
1467 if (!strchr("!|$?=", r_ptr->d_char)) return (FALSE);
1474 * Helper function for "monster nest (clone)"
1476 static bool vault_aux_clone(int r_idx)
1478 /* Validate the monster */
1479 if (!vault_monster_okay(r_idx)) return (FALSE);
1481 return (r_idx == vault_aux_race);
1486 * Helper function for "monster nest (symbol clone)"
1488 static bool vault_aux_symbol_e(int r_idx)
1490 monster_race *r_ptr = &r_info[r_idx];
1492 /* Validate the monster */
1493 if (!vault_monster_okay(r_idx)) return (FALSE);
1495 if ((r_ptr->flags2 & RF2_KILL_BODY) && !(r_ptr->flags1 & RF1_NEVER_BLOW)) return (FALSE);
1497 if (r_ptr->flags3 & (RF3_GOOD)) return (FALSE);
1499 /* Decline incorrect symbol */
1500 if (r_ptr->d_char != vault_aux_char) return (FALSE);
1508 * Helper function for "monster nest (symbol clone)"
1510 static bool vault_aux_symbol_g(int r_idx)
1512 monster_race *r_ptr = &r_info[r_idx];
1514 /* Validate the monster */
1515 if (!vault_monster_okay(r_idx)) return (FALSE);
1517 if ((r_ptr->flags2 & RF2_KILL_BODY) && !(r_ptr->flags1 & RF1_NEVER_BLOW)) return (FALSE);
1519 if (r_ptr->flags3 & (RF3_EVIL)) return (FALSE);
1521 /* Decline incorrect symbol */
1522 if (r_ptr->d_char != vault_aux_char) return (FALSE);
1530 * Helper function for "monster pit (orc)"
1532 static bool vault_aux_orc(int r_idx)
1534 monster_race *r_ptr = &r_info[r_idx];
1536 /* Validate the monster */
1537 if (!vault_monster_okay(r_idx)) return (FALSE);
1540 if (!(r_ptr->flags3 & RF3_ORC)) return (FALSE);
1542 /* Decline undead */
1543 if (r_ptr->flags3 & RF3_UNDEAD) return (FALSE);
1551 * Helper function for "monster pit (troll)"
1553 static bool vault_aux_troll(int r_idx)
1555 monster_race *r_ptr = &r_info[r_idx];
1557 /* Validate the monster */
1558 if (!vault_monster_okay(r_idx)) return (FALSE);
1561 if (!(r_ptr->flags3 & RF3_TROLL)) return (FALSE);
1563 /* Decline undead */
1564 if (r_ptr->flags3 & RF3_UNDEAD) return (FALSE);
1572 * Helper function for "monster pit (giant)"
1574 static bool vault_aux_giant(int r_idx)
1576 monster_race *r_ptr = &r_info[r_idx];
1578 /* Validate the monster */
1579 if (!vault_monster_okay(r_idx)) return (FALSE);
1582 if (!(r_ptr->flags3 & RF3_GIANT)) return (FALSE);
1584 if (r_ptr->flags3 & RF3_GOOD) return (FALSE);
1586 /* Decline undead */
1587 if (r_ptr->flags3 & RF3_UNDEAD) return (FALSE);
1595 * Helper function for "monster pit (dragon)"
1597 static bool vault_aux_dragon(int r_idx)
1599 monster_race *r_ptr = &r_info[r_idx];
1601 /* Validate the monster */
1602 if (!vault_monster_okay(r_idx)) return (FALSE);
1604 /* Require dragon */
1605 if (!(r_ptr->flags3 & RF3_DRAGON)) return (FALSE);
1607 /* Hack -- Require correct "breath attack" */
1608 if (r_ptr->flags4 != vault_aux_dragon_mask4) return (FALSE);
1610 /* Decline undead */
1611 if (r_ptr->flags3 & RF3_UNDEAD) return (FALSE);
1619 * Helper function for "monster pit (demon)"
1621 static bool vault_aux_demon(int r_idx)
1623 monster_race *r_ptr = &r_info[r_idx];
1625 /* Validate the monster */
1626 if (!vault_monster_okay(r_idx)) return (FALSE);
1628 if ((r_ptr->flags2 & RF2_KILL_BODY) && !(r_ptr->flags1 & RF1_NEVER_BLOW)) return (FALSE);
1631 if (!(r_ptr->flags3 & RF3_DEMON)) return (FALSE);
1639 * Helper function for "monster pit (lovecraftian)"
1641 static bool vault_aux_cthulhu(int r_idx)
1643 monster_race *r_ptr = &r_info[r_idx];
1645 /* Validate the monster */
1646 if (!vault_monster_okay(r_idx)) return (FALSE);
1648 if ((r_ptr->flags2 & RF2_KILL_BODY) && !(r_ptr->flags1 & RF1_NEVER_BLOW)) return (FALSE);
1650 /* Require eldritch horror */
1651 if (!(r_ptr->flags2 & (RF2_ELDRITCH_HORROR))) return (FALSE);
1659 * Helper function for "monster pit (clone)"
1661 static void vault_prep_clone(void)
1663 /* Apply the monster restriction */
1664 get_mon_num_prep(vault_aux_simple, NULL);
1666 /* Pick a race to clone */
1667 vault_aux_race = get_mon_num(dun_level + 10);
1669 /* Remove the monster restriction */
1670 get_mon_num_prep(NULL, NULL);
1675 * Helper function for "monster pit (symbol clone)"
1677 static void vault_prep_symbol(void)
1681 /* Apply the monster restriction */
1682 get_mon_num_prep(vault_aux_simple, NULL);
1684 /* Pick a race to clone */
1685 r_idx = get_mon_num(dun_level + 10);
1687 /* Remove the monster restriction */
1688 get_mon_num_prep(NULL, NULL);
1690 /* Extract the symbol */
1691 vault_aux_char = r_info[r_idx].d_char;
1696 * Helper function for "monster pit (dragon)"
1698 static void vault_prep_dragon(void)
1700 /* Pick dragon type */
1701 switch (randint0(6))
1706 /* Restrict dragon breath type */
1707 vault_aux_dragon_mask4 = RF4_BR_ACID;
1716 /* Restrict dragon breath type */
1717 vault_aux_dragon_mask4 = RF4_BR_ELEC;
1726 /* Restrict dragon breath type */
1727 vault_aux_dragon_mask4 = RF4_BR_FIRE;
1736 /* Restrict dragon breath type */
1737 vault_aux_dragon_mask4 = RF4_BR_COLD;
1746 /* Restrict dragon breath type */
1747 vault_aux_dragon_mask4 = RF4_BR_POIS;
1756 /* Restrict dragon breath type */
1757 vault_aux_dragon_mask4 = (RF4_BR_ACID | RF4_BR_ELEC |
1758 RF4_BR_FIRE | RF4_BR_COLD |
1769 * Helper function for "monster pit (dark elf)"
1771 static bool vault_aux_dark_elf(int r_idx)
1774 static int dark_elf_list[] =
1776 MON_D_ELF, MON_D_ELF_MAGE, MON_D_ELF_WARRIOR, MON_D_ELF_PRIEST,
1777 MON_D_ELF_LORD, MON_D_ELF_WARLOCK, MON_D_ELF_DRUID, MON_NIGHTBLADE,
1778 MON_D_ELF_SORC, MON_D_ELF_SHADE, 0,
1781 /* Validate the monster */
1782 if (!vault_monster_okay(r_idx)) return FALSE;
1784 /* Require dark elves */
1785 for (i = 0; dark_elf_list[i]; i++)
1786 if (r_idx == dark_elf_list[i]) return TRUE;
1793 typedef struct vault_aux_type vault_aux_type;
1796 struct vault_aux_type
1799 bool (*hook_func)(int r_idx);
1800 void (*prep_func)(void);
1806 static int pick_vault_type(vault_aux_type *l_ptr, s16b allow_flag_mask)
1808 int tmp, total, count;
1810 vault_aux_type *n_ptr;
1812 /* Calculate the total possibilities */
1813 for (n_ptr = l_ptr, total = 0, count = 0; TRUE; n_ptr++, count++)
1816 if (!n_ptr->name) break;
1818 /* Ignore excessive depth */
1819 if (n_ptr->level > dun_level) continue;
1821 /* Not matched with pit/nest flag */
1822 if (!(allow_flag_mask & (1L << count))) continue;
1824 /* Count this possibility */
1825 total += n_ptr->chance * MAX_DEPTH / (MIN(dun_level, MAX_DEPTH - 1) - n_ptr->level + 5);
1828 /* Pick a random type */
1829 tmp = randint0(total);
1831 /* Find this type */
1832 for (n_ptr = l_ptr, total = 0, count = 0; TRUE; n_ptr++, count++)
1835 if (!n_ptr->name) break;
1837 /* Ignore excessive depth */
1838 if (n_ptr->level > dun_level) continue;
1840 /* Not matched with pit/nest flag */
1841 if (!(allow_flag_mask & (1L << count))) continue;
1843 /* Count this possibility */
1844 total += n_ptr->chance * MAX_DEPTH / (MIN(dun_level, MAX_DEPTH - 1) - n_ptr->level + 5);
1846 /* Found the type */
1847 if (tmp < total) break;
1850 return n_ptr->name ? count : -1;
1853 static vault_aux_type nest_types[] =
1856 {"¥¯¥í¡¼¥ó", vault_aux_clone, vault_prep_clone, 5, 3},
1857 {"¥¼¥ê¡¼", vault_aux_jelly, NULL, 5, 6},
1858 {"¥·¥ó¥Ü¥ë(Á±)", vault_aux_symbol_g, vault_prep_symbol, 25, 2},
1859 {"¥·¥ó¥Ü¥ë(°)", vault_aux_symbol_e, vault_prep_symbol, 25, 2},
1860 {"¥ß¥ß¥Ã¥¯", vault_aux_mimic, NULL, 30, 4},
1861 {"¶¸µ¤", vault_aux_cthulhu, NULL, 70, 2},
1862 {"¸¤¾®²°", vault_aux_kennel, NULL, 45, 4},
1863 {"ưʪ±à", vault_aux_animal, NULL, 35, 5},
1864 {"¶µ²ñ", vault_aux_chapel_g, NULL, 75, 4},
1865 {"¥¢¥ó¥Ç¥Ã¥É", vault_aux_undead, NULL, 75, 5},
1866 {NULL, NULL, NULL, 0, 0},
1868 {"clone", vault_aux_clone, vault_prep_clone, 5, 3},
1869 {"jelly", vault_aux_jelly, NULL, 5, 6},
1870 {"symbol good", vault_aux_symbol_g, vault_prep_symbol, 25, 2},
1871 {"symbol evil", vault_aux_symbol_e, vault_prep_symbol, 25, 2},
1872 {"mimic", vault_aux_mimic, NULL, 30, 4},
1873 {"lovecraftian", vault_aux_cthulhu, NULL, 70, 2},
1874 {"kennel", vault_aux_kennel, NULL, 45, 4},
1875 {"animal", vault_aux_animal, NULL, 35, 5},
1876 {"chapel", vault_aux_chapel_g, NULL, 75, 4},
1877 {"undead", vault_aux_undead, NULL, 75, 5},
1878 {NULL, NULL, NULL, 0, 0},
1882 static vault_aux_type pit_types[] =
1885 {"¥ª¡¼¥¯", vault_aux_orc, NULL, 5, 6},
1886 {"¥È¥í¥ë", vault_aux_troll, NULL, 20, 6},
1887 {"¥¸¥ã¥¤¥¢¥ó¥È", vault_aux_giant, NULL, 50, 6},
1888 {"¶¸µ¤", vault_aux_cthulhu, NULL, 80, 2},
1889 {"¥·¥ó¥Ü¥ë(Á±)", vault_aux_symbol_g, vault_prep_symbol, 70, 1},
1890 {"¥·¥ó¥Ü¥ë(°)", vault_aux_symbol_e, vault_prep_symbol, 70, 1},
1891 {"¶µ²ñ", vault_aux_chapel_g, NULL, 65, 2},
1892 {"¥É¥é¥´¥ó", vault_aux_dragon, vault_prep_dragon, 70, 6},
1893 {"¥Ç¡¼¥â¥ó", vault_aux_demon, NULL, 80, 6},
1894 {"¥À¡¼¥¯¥¨¥ë¥Õ", vault_aux_dark_elf, NULL, 45, 4},
1895 {NULL, NULL, NULL, 0, 0},
1897 {"orc", vault_aux_orc, NULL, 5, 6},
1898 {"troll", vault_aux_troll, NULL, 20, 6},
1899 {"giant", vault_aux_giant, NULL, 50, 6},
1900 {"lovecraftian", vault_aux_cthulhu, NULL, 80, 2},
1901 {"symbol good", vault_aux_symbol_g, vault_prep_symbol, 70, 1},
1902 {"symbol evil", vault_aux_symbol_e, vault_prep_symbol, 70, 1},
1903 {"chapel", vault_aux_chapel_g, NULL, 65, 2},
1904 {"dragon", vault_aux_dragon, vault_prep_dragon, 70, 6},
1905 {"demon", vault_aux_demon, NULL, 80, 6},
1906 {"dark elf", vault_aux_dark_elf, NULL, 45, 4},
1907 {NULL, NULL, NULL, 0, 0},
1912 /* Nest types code */
1913 #define NEST_TYPE_CLONE 0
1914 #define NEST_TYPE_JELLY 1
1915 #define NEST_TYPE_SYMBOL_GOOD 2
1916 #define NEST_TYPE_SYMBOL_EVIL 3
1917 #define NEST_TYPE_MIMIC 4
1918 #define NEST_TYPE_LOVECRAFTIAN 5
1919 #define NEST_TYPE_KENNEL 6
1920 #define NEST_TYPE_ANIMAL 7
1921 #define NEST_TYPE_CHAPEL 8
1922 #define NEST_TYPE_UNDEAD 9
1924 /* Pit types code */
1925 #define PIT_TYPE_ORC 0
1926 #define PIT_TYPE_TROLL 1
1927 #define PIT_TYPE_GIANT 2
1928 #define PIT_TYPE_LOVECRAFTIAN 3
1929 #define PIT_TYPE_SYMBOL_GOOD 4
1930 #define PIT_TYPE_SYMBOL_EVIL 5
1931 #define PIT_TYPE_CHAPEL 6
1932 #define PIT_TYPE_DRAGON 7
1933 #define PIT_TYPE_DEMON 8
1934 #define PIT_TYPE_DARK_ELF 9
1938 * Hack -- Get the string describing subtype of pit/nest
1939 * Determined in prepare function (some pit/nest only)
1941 static cptr pit_subtype_string(int type, bool nest)
1943 static char inner_buf[256] = "";
1945 inner_buf[0] = '\0'; /* Init string */
1947 if (nest) /* Nests */
1951 case NEST_TYPE_CLONE:
1952 sprintf(inner_buf, "(%s)", r_name + r_info[vault_aux_race].name);
1954 case NEST_TYPE_SYMBOL_GOOD:
1955 case NEST_TYPE_SYMBOL_EVIL:
1956 sprintf(inner_buf, "(%c)", vault_aux_char);
1964 case PIT_TYPE_SYMBOL_GOOD:
1965 case PIT_TYPE_SYMBOL_EVIL:
1966 sprintf(inner_buf, "(%c)", vault_aux_char);
1968 case PIT_TYPE_DRAGON:
1969 switch (vault_aux_dragon_mask4)
1972 case RF4_BR_ACID: strcpy(inner_buf, "(»À)"); break;
1973 case RF4_BR_ELEC: strcpy(inner_buf, "(°ðºÊ)"); break;
1974 case RF4_BR_FIRE: strcpy(inner_buf, "(²Ð±ê)"); break;
1975 case RF4_BR_COLD: strcpy(inner_buf, "(Î䵤)"); break;
1976 case RF4_BR_POIS: strcpy(inner_buf, "(ÆÇ)"); break;
1977 case (RF4_BR_ACID | RF4_BR_ELEC | RF4_BR_FIRE | RF4_BR_COLD | RF4_BR_POIS):
1978 strcpy(inner_buf, "(Ëü¿§)"); break;
1979 default: strcpy(inner_buf, "(̤ÄêµÁ)"); break;
1981 case RF4_BR_ACID: strcpy(inner_buf, "(acid)"); break;
1982 case RF4_BR_ELEC: strcpy(inner_buf, "(lightning)"); break;
1983 case RF4_BR_FIRE: strcpy(inner_buf, "(fire)"); break;
1984 case RF4_BR_COLD: strcpy(inner_buf, "(frost)"); break;
1985 case RF4_BR_POIS: strcpy(inner_buf, "(poison)"); break;
1986 case (RF4_BR_ACID | RF4_BR_ELEC | RF4_BR_FIRE | RF4_BR_COLD | RF4_BR_POIS):
1987 strcpy(inner_buf, "(multi-hued)"); break;
1988 default: strcpy(inner_buf, "(undefined)"); break;
1999 /* A struct for nest monster information with cheat_hear */
2009 * Comp function for sorting nest monster information
2011 static bool ang_sort_comp_nest_mon_info(vptr u, vptr v, int a, int b)
2013 nest_mon_info_type *nest_mon_info = (nest_mon_info_type *)u;
2014 int w1 = nest_mon_info[a].r_idx;
2015 int w2 = nest_mon_info[b].r_idx;
2016 monster_race *r1_ptr = &r_info[w1];
2017 monster_race *r2_ptr = &r_info[w2];
2023 /* Extract used info */
2024 z1 = nest_mon_info[a].used;
2025 z2 = nest_mon_info[b].used;
2027 /* Compare used status */
2028 if (z1 < z2) return FALSE;
2029 if (z1 > z2) return TRUE;
2031 /* Compare levels */
2032 if (r1_ptr->level < r2_ptr->level) return TRUE;
2033 if (r1_ptr->level > r2_ptr->level) return FALSE;
2035 /* Compare experience */
2036 if (r1_ptr->mexp < r2_ptr->mexp) return TRUE;
2037 if (r1_ptr->mexp > r2_ptr->mexp) return FALSE;
2039 /* Compare indexes */
2045 * Swap function for sorting nest monster information
2047 static void ang_sort_swap_nest_mon_info(vptr u, vptr v, int a, int b)
2049 nest_mon_info_type *nest_mon_info = (nest_mon_info_type *)u;
2050 nest_mon_info_type holder;
2056 holder = nest_mon_info[a];
2057 nest_mon_info[a] = nest_mon_info[b];
2058 nest_mon_info[b] = holder;
2062 #define NUM_NEST_MON_TYPE 64
2065 * Type 5 -- Monster nests
2067 * A monster nest is a "big" room, with an "inner" room, containing
2068 * a "collection" of monsters of a given type strewn about the room.
2070 * The monsters are chosen from a set of 64 randomly selected monster
2071 * races, to allow the nest creation to fail instead of having "holes".
2073 * Note the use of the "get_mon_num_prep()" function, and the special
2074 * "get_mon_num_hook()" restriction function, to prepare the "monster
2075 * allocation table" in such a way as to optimize the selection of
2076 * "appropriate" non-unique monsters for the nest.
2078 * Note that the "get_mon_num()" function may (rarely) fail, in which
2079 * case the nest will be empty, and will not affect the level rating.
2081 * Note that "monster nests" will never contain "unique" monsters.
2083 static bool build_type5(void)
2085 int y, x, y1, x1, y2, x2, xval, yval;
2087 nest_mon_info_type nest_mon_info[NUM_NEST_MON_TYPE];
2093 int cur_nest_type = pick_vault_type(nest_types, d_info[dungeon_type].nest);
2094 vault_aux_type *n_ptr;
2096 /* No type available */
2097 if (cur_nest_type < 0) return FALSE;
2099 n_ptr = &nest_types[cur_nest_type];
2101 /* Process a preparation function if necessary */
2102 if (n_ptr->prep_func) (*(n_ptr->prep_func))();
2104 /* Prepare allocation table */
2105 get_mon_num_prep(n_ptr->hook_func, NULL);
2107 align.sub_align = SUB_ALIGN_NEUTRAL;
2109 /* Pick some monster types */
2110 for (i = 0; i < NUM_NEST_MON_TYPE; i++)
2112 int r_idx = 0, attempts = 100;
2113 monster_race *r_ptr = NULL;
2117 /* Get a (hard) monster type */
2118 r_idx = get_mon_num(dun_level + 10);
2119 r_ptr = &r_info[r_idx];
2121 /* Decline incorrect alignment */
2122 if (monster_has_hostile_align(&align, 0, 0, r_ptr)) continue;
2124 /* Accept this monster */
2128 /* Notice failure */
2129 if (!r_idx || !attempts) return FALSE;
2131 /* Note the alignment */
2132 if (r_ptr->flags3 & RF3_EVIL) align.sub_align |= SUB_ALIGN_EVIL;
2133 if (r_ptr->flags3 & RF3_GOOD) align.sub_align |= SUB_ALIGN_GOOD;
2135 nest_mon_info[i].r_idx = r_idx;
2136 nest_mon_info[i].used = FALSE;
2139 /* Find and reserve some space in the dungeon. Get center of room. */
2140 if (!find_space(&yval, &xval, 11, 25)) return FALSE;
2148 /* Place the floor area */
2149 for (y = y1 - 1; y <= y2 + 1; y++)
2151 for (x = x1 - 1; x <= x2 + 1; x++)
2153 c_ptr = &cave[y][x];
2154 place_floor_grid(c_ptr);
2155 c_ptr->info |= (CAVE_ROOM);
2159 /* Place the outer walls */
2160 for (y = y1 - 1; y <= y2 + 1; y++)
2162 c_ptr = &cave[y][x1 - 1];
2163 place_outer_grid(c_ptr);
2164 c_ptr = &cave[y][x2 + 1];
2165 place_outer_grid(c_ptr);
2167 for (x = x1 - 1; x <= x2 + 1; x++)
2169 c_ptr = &cave[y1 - 1][x];
2170 place_outer_grid(c_ptr);
2171 c_ptr = &cave[y2 + 1][x];
2172 place_outer_grid(c_ptr);
2176 /* Advance to the center room */
2182 /* The inner walls */
2183 for (y = y1 - 1; y <= y2 + 1; y++)
2185 c_ptr = &cave[y][x1 - 1];
2186 place_inner_grid(c_ptr);
2187 c_ptr = &cave[y][x2 + 1];
2188 place_inner_grid(c_ptr);
2191 for (x = x1 - 1; x <= x2 + 1; x++)
2193 c_ptr = &cave[y1 - 1][x];
2194 place_inner_grid(c_ptr);
2195 c_ptr = &cave[y2 + 1][x];
2196 place_inner_grid(c_ptr);
2198 for (y = y1; y <= y2; y++)
2200 for (x = x1; x <= x2; x++)
2202 add_cave_info(y, x, CAVE_ICKY);
2206 /* Place a secret door */
2207 switch (randint1(4))
2209 case 1: place_secret_door(y1 - 1, xval); break;
2210 case 2: place_secret_door(y2 + 1, xval); break;
2211 case 3: place_secret_door(yval, x1 - 1); break;
2212 case 4: place_secret_door(yval, x2 + 1); break;
2220 msg_format("¥â¥ó¥¹¥¿¡¼Éô²°(nest)(%s%s)", n_ptr->name, pit_subtype_string(cur_nest_type, TRUE));
2222 msg_format("Monster nest (%s%s)", n_ptr->name, pit_subtype_string(cur_nest_type, TRUE));
2226 /* Increase the level rating */
2229 /* (Sometimes) Cause a "special feeling" (for "Monster Nests") */
2230 if ((dun_level <= 40) && (randint1(dun_level * dun_level + 50) < 300))
2232 good_item_flag = TRUE;
2235 /* Place some monsters */
2236 for (y = yval - 2; y <= yval + 2; y++)
2238 for (x = xval - 9; x <= xval + 9; x++)
2242 i = randint0(NUM_NEST_MON_TYPE);
2243 r_idx = nest_mon_info[i].r_idx;
2245 /* Place that "random" monster (no groups) */
2246 (void)place_monster_aux(0, y, x, r_idx, 0L);
2248 nest_mon_info[i].used = TRUE;
2252 if (cheat_room && cheat_hear)
2254 ang_sort_comp = ang_sort_comp_nest_mon_info;
2255 ang_sort_swap = ang_sort_swap_nest_mon_info;
2256 ang_sort(nest_mon_info, NULL, NUM_NEST_MON_TYPE);
2258 /* Dump the entries (prevent multi-printing) */
2259 for (i = 0; i < NUM_NEST_MON_TYPE; i++)
2261 if (!nest_mon_info[i].used) break;
2262 for (; i < NUM_NEST_MON_TYPE - 1; i++)
2264 if (nest_mon_info[i].r_idx != nest_mon_info[i + 1].r_idx) break;
2265 if (!nest_mon_info[i + 1].used) break;
2267 msg_print(r_name + r_info[nest_mon_info[i].r_idx].name);
2276 * Type 6 -- Monster pits
2278 * A monster pit is a "big" room, with an "inner" room, containing
2279 * a "collection" of monsters of a given type organized in the room.
2281 * The inside room in a monster pit appears as shown below, where the
2282 * actual monsters in each location depend on the type of the pit
2284 * #####################
2285 * #0000000000000000000#
2286 * #0112233455543322110#
2287 * #0112233467643322110#
2288 * #0112233455543322110#
2289 * #0000000000000000000#
2290 * #####################
2292 * Note that the monsters in the pit are now chosen by using "get_mon_num()"
2293 * to request 16 "appropriate" monsters, sorting them by level, and using
2294 * the "even" entries in this sorted list for the contents of the pit.
2296 * Hack -- all of the "dragons" in a "dragon" pit must be the same "color",
2297 * which is handled by requiring a specific "breath" attack for all of the
2298 * dragons. This may include "multi-hued" breath. Note that "wyrms" may
2299 * be present in many of the dragon pits, if they have the proper breath.
2301 * Note the use of the "get_mon_num_prep()" function, and the special
2302 * "get_mon_num_hook()" restriction function, to prepare the "monster
2303 * allocation table" in such a way as to optimize the selection of
2304 * "appropriate" non-unique monsters for the pit.
2306 * Note that the "get_mon_num()" function may (rarely) fail, in which case
2307 * the pit will be empty, and will not effect the level rating.
2309 * Note that "monster pits" will never contain "unique" monsters.
2311 static bool build_type6(void)
2313 int y, x, y1, x1, y2, x2, xval, yval;
2322 int cur_pit_type = pick_vault_type(pit_types, d_info[dungeon_type].pit);
2323 vault_aux_type *n_ptr;
2325 /* No type available */
2326 if (cur_pit_type < 0) return FALSE;
2328 n_ptr = &pit_types[cur_pit_type];
2330 /* Process a preparation function if necessary */
2331 if (n_ptr->prep_func) (*(n_ptr->prep_func))();
2333 /* Prepare allocation table */
2334 get_mon_num_prep(n_ptr->hook_func, NULL);
2336 align.sub_align = SUB_ALIGN_NEUTRAL;
2338 /* Pick some monster types */
2339 for (i = 0; i < 16; i++)
2341 int r_idx = 0, attempts = 100;
2342 monster_race *r_ptr = NULL;
2346 /* Get a (hard) monster type */
2347 r_idx = get_mon_num(dun_level + 10);
2348 r_ptr = &r_info[r_idx];
2350 /* Decline incorrect alignment */
2351 if (monster_has_hostile_align(&align, 0, 0, r_ptr)) continue;
2353 /* Accept this monster */
2357 /* Notice failure */
2358 if (!r_idx || !attempts) return FALSE;
2360 /* Note the alignment */
2361 if (r_ptr->flags3 & RF3_EVIL) align.sub_align |= SUB_ALIGN_EVIL;
2362 if (r_ptr->flags3 & RF3_GOOD) align.sub_align |= SUB_ALIGN_GOOD;
2367 /* Find and reserve some space in the dungeon. Get center of room. */
2368 if (!find_space(&yval, &xval, 11, 25)) return FALSE;
2376 /* Place the floor area */
2377 for (y = y1 - 1; y <= y2 + 1; y++)
2379 for (x = x1 - 1; x <= x2 + 1; x++)
2381 c_ptr = &cave[y][x];
2382 place_floor_grid(c_ptr);
2383 c_ptr->info |= (CAVE_ROOM);
2387 /* Place the outer walls */
2388 for (y = y1 - 1; y <= y2 + 1; y++)
2390 c_ptr = &cave[y][x1 - 1];
2391 place_outer_grid(c_ptr);
2392 c_ptr = &cave[y][x2 + 1];
2393 place_outer_grid(c_ptr);
2395 for (x = x1 - 1; x <= x2 + 1; x++)
2397 c_ptr = &cave[y1 - 1][x];
2398 place_outer_grid(c_ptr);
2399 c_ptr = &cave[y2 + 1][x];
2400 place_outer_grid(c_ptr);
2403 /* Advance to the center room */
2409 /* The inner walls */
2410 for (y = y1 - 1; y <= y2 + 1; y++)
2412 c_ptr = &cave[y][x1 - 1];
2413 place_inner_grid(c_ptr);
2414 c_ptr = &cave[y][x2 + 1];
2415 place_inner_grid(c_ptr);
2417 for (x = x1 - 1; x <= x2 + 1; x++)
2419 c_ptr = &cave[y1 - 1][x];
2420 place_inner_grid(c_ptr);
2421 c_ptr = &cave[y2 + 1][x];
2422 place_inner_grid(c_ptr);
2424 for (y = y1; y <= y2; y++)
2426 for (x = x1; x <= x2; x++)
2428 add_cave_info(y, x, CAVE_ICKY);
2432 /* Place a secret door */
2433 switch (randint1(4))
2435 case 1: place_secret_door(y1 - 1, xval); break;
2436 case 2: place_secret_door(y2 + 1, xval); break;
2437 case 3: place_secret_door(yval, x1 - 1); break;
2438 case 4: place_secret_door(yval, x2 + 1); break;
2441 /* Sort the entries */
2442 for (i = 0; i < 16 - 1; i++)
2444 /* Sort the entries */
2445 for (j = 0; j < 16 - 1; j++)
2450 int p1 = r_info[what[i1]].level;
2451 int p2 = r_info[what[i2]].level;
2457 what[i1] = what[i2];
2468 msg_format("¥â¥ó¥¹¥¿¡¼Éô²°(pit)(%s%s)", n_ptr->name, pit_subtype_string(cur_pit_type, FALSE));
2470 msg_format("Monster pit (%s%s)", n_ptr->name, pit_subtype_string(cur_pit_type, FALSE));
2474 /* Select the entries */
2475 for (i = 0; i < 8; i++)
2477 /* Every other entry */
2478 what[i] = what[i * 2];
2483 msg_print(r_name + r_info[what[i]].name);
2487 /* Increase the level rating */
2490 /* (Sometimes) Cause a "special feeling" (for "Monster Pits") */
2491 if ((dun_level <= 40) && (randint1(dun_level * dun_level + 50) < 300))
2493 good_item_flag = TRUE;
2496 /* Top and bottom rows */
2497 for (x = xval - 9; x <= xval + 9; x++)
2499 place_monster_aux(0, yval - 2, x, what[0], PM_NO_KAGE);
2500 place_monster_aux(0, yval + 2, x, what[0], PM_NO_KAGE);
2503 /* Middle columns */
2504 for (y = yval - 1; y <= yval + 1; y++)
2506 place_monster_aux(0, y, xval - 9, what[0], PM_NO_KAGE);
2507 place_monster_aux(0, y, xval + 9, what[0], PM_NO_KAGE);
2509 place_monster_aux(0, y, xval - 8, what[1], PM_NO_KAGE);
2510 place_monster_aux(0, y, xval + 8, what[1], PM_NO_KAGE);
2512 place_monster_aux(0, y, xval - 7, what[1], PM_NO_KAGE);
2513 place_monster_aux(0, y, xval + 7, what[1], PM_NO_KAGE);
2515 place_monster_aux(0, y, xval - 6, what[2], PM_NO_KAGE);
2516 place_monster_aux(0, y, xval + 6, what[2], PM_NO_KAGE);
2518 place_monster_aux(0, y, xval - 5, what[2], PM_NO_KAGE);
2519 place_monster_aux(0, y, xval + 5, what[2], PM_NO_KAGE);
2521 place_monster_aux(0, y, xval - 4, what[3], PM_NO_KAGE);
2522 place_monster_aux(0, y, xval + 4, what[3], PM_NO_KAGE);
2524 place_monster_aux(0, y, xval - 3, what[3], PM_NO_KAGE);
2525 place_monster_aux(0, y, xval + 3, what[3], PM_NO_KAGE);
2527 place_monster_aux(0, y, xval - 2, what[4], PM_NO_KAGE);
2528 place_monster_aux(0, y, xval + 2, what[4], PM_NO_KAGE);
2531 /* Above/Below the center monster */
2532 for (x = xval - 1; x <= xval + 1; x++)
2534 place_monster_aux(0, yval + 1, x, what[5], PM_NO_KAGE);
2535 place_monster_aux(0, yval - 1, x, what[5], PM_NO_KAGE);
2538 /* Next to the center monster */
2539 place_monster_aux(0, yval, xval + 1, what[6], PM_NO_KAGE);
2540 place_monster_aux(0, yval, xval - 1, what[6], PM_NO_KAGE);
2542 /* Center monster */
2543 place_monster_aux(0, yval, xval, what[7], PM_NO_KAGE);
2549 /* coordinate translation code */
2550 static void coord_trans(int *x, int *y, int xoffset, int yoffset, int transno)
2556 * transno specifies what transformation is required. (0-7)
2557 * The lower two bits indicate by how much the vault is rotated,
2558 * and the upper bit indicates a reflection.
2559 * This is done by using rotation matrices... however since
2560 * these are mostly zeros for rotations by 90 degrees this can
2561 * be expressed simply in terms of swapping and inverting the
2562 * x and y coordinates.
2564 for (i = 0; i < transno % 4; i++)
2566 /* rotate by 90 degrees */
2574 /* Reflect depending on status of 3rd bit. */
2578 /* Add offsets so vault stays in the first quadrant */
2585 * Hack -- fill in "vault" rooms
2587 static void build_vault(int yval, int xval, int ymax, int xmax, cptr data,
2588 int xoffset, int yoffset, int transno)
2590 int dx, dy, x, y, i, j;
2597 /* Place dungeon features and objects */
2598 for (t = data, dy = 0; dy < ymax; dy++)
2600 for (dx = 0; dx < xmax; dx++, t++)
2602 /* prevent loop counter from being overwritten */
2607 coord_trans(&i, &j, xoffset, yoffset, transno);
2609 /* Extract the location */
2610 if (transno % 2 == 0)
2612 /* no swap of x/y */
2613 x = xval - (xmax / 2) + i;
2614 y = yval - (ymax / 2) + j;
2619 x = xval - (ymax / 2) + i;
2620 y = yval - (xmax / 2) + j;
2623 /* Hack -- skip "non-grids" */
2624 if (*t == ' ') continue;
2626 /* Access the grid */
2627 c_ptr = &cave[y][x];
2629 /* Lay down a floor */
2630 place_floor_grid(c_ptr);
2632 /* Remove any mimic */
2635 /* Part of a vault */
2636 c_ptr->info |= (CAVE_ROOM | CAVE_ICKY);
2638 /* Analyze the grid */
2641 /* Granite wall (outer) */
2643 place_outer_noperm_grid(c_ptr);
2646 /* Granite wall (inner) */
2648 place_inner_grid(c_ptr);
2651 /* Permanent wall (inner) */
2653 c_ptr->feat = FEAT_PERM_INNER;
2654 c_ptr->info &= ~(CAVE_MASK);
2655 c_ptr->info |= CAVE_INNER;
2660 if (randint0(100) < 75)
2662 place_object(y, x, 0L);
2672 place_secret_door(y, x);
2680 /* Black market in a dungeon */
2682 set_cave_feat(y, x, FEAT_SHOP_HEAD + STORE_BLACK);
2683 store_init(NO_TOWN, STORE_BLACK);
2688 set_cave_feat(y, x, FEAT_PATTERN_START);
2692 set_cave_feat(y, x, FEAT_PATTERN_1);
2696 set_cave_feat(y, x, FEAT_PATTERN_2);
2700 set_cave_feat(y, x, FEAT_PATTERN_3);
2704 set_cave_feat(y, x, FEAT_PATTERN_4);
2708 set_cave_feat(y, x, FEAT_PATTERN_END);
2712 set_cave_feat(y, x, FEAT_PATTERN_XTRA1);
2716 /* Reward for Pattern walk */
2717 object_level = base_level + 12;
2718 place_object(y, x, AM_GOOD | AM_GREAT);
2719 object_level = base_level;
2726 /* Place dungeon monsters and objects */
2727 for (t = data, dy = 0; dy < ymax; dy++)
2729 for (dx = 0; dx < xmax; dx++, t++)
2731 /* prevent loop counter from being overwritten */
2736 coord_trans(&i, &j, xoffset, yoffset, transno);
2738 /* Extract the location */
2739 if (transno % 2 == 0)
2741 /* no swap of x/y */
2742 x = xval - (xmax / 2) + i;
2743 y = yval - (ymax / 2) + j;
2748 x = xval - (ymax / 2) + i;
2749 y = yval - (xmax / 2) + j;
2752 /* Hack -- skip "non-grids" */
2753 if (*t == ' ') continue;
2755 /* Analyze the symbol */
2761 monster_level = base_level + 5;
2762 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
2763 monster_level = base_level;
2767 /* Meaner monster */
2770 monster_level = base_level + 11;
2771 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
2772 monster_level = base_level;
2776 /* Meaner monster, plus treasure */
2779 monster_level = base_level + 9;
2780 place_monster(y, x, PM_ALLOW_SLEEP);
2781 monster_level = base_level;
2782 object_level = base_level + 7;
2783 place_object(y, x, AM_GOOD);
2784 object_level = base_level;
2788 /* Nasty monster and treasure */
2791 monster_level = base_level + 40;
2792 place_monster(y, x, PM_ALLOW_SLEEP);
2793 monster_level = base_level;
2794 object_level = base_level + 20;
2795 place_object(y, x, AM_GOOD | AM_GREAT);
2796 object_level = base_level;
2800 /* Monster and/or object */
2803 if (randint0(100) < 50)
2805 monster_level = base_level + 3;
2806 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
2807 monster_level = base_level;
2809 if (randint0(100) < 50)
2811 object_level = base_level + 7;
2812 place_object(y, x, 0L);
2813 object_level = base_level;
2825 * Type 7 -- simple vaults (see "v_info.txt")
2827 static bool build_type7(void)
2829 vault_type *v_ptr = NULL;
2833 int xoffset, yoffset;
2836 /* Pick a lesser vault */
2837 while (dummy < SAFE_MAX_ATTEMPTS)
2841 /* Access a random vault record */
2842 v_ptr = &v_info[randint0(max_v_idx)];
2844 /* Accept the first lesser vault */
2845 if (v_ptr->typ == 7) break;
2848 /* No lesser vault found */
2849 if (!v_ptr) return FALSE;
2851 /* pick type of transformation (0-7) */
2852 transno = randint0(8);
2854 /* calculate offsets */
2858 /* Some huge vault cannot be ratated to fit in the dungeon */
2859 if (x+2 > cur_hgt-2)
2861 /* Forbid 90 or 270 degree ratation */
2865 coord_trans(&x, &y, 0, 0, transno);
2886 /* Find and reserve some space in the dungeon. Get center of room. */
2887 if (!find_space(&yval, &xval, abs(y), abs(x))) return FALSE;
2890 if (dummy >= SAFE_MAX_ATTEMPTS)
2895 msg_print("·Ù¹ð¡ª¾®¤µ¤ÊÃϲ¼¼¼¤òÇÛÃ֤Ǥ¤Þ¤»¤ó¡ª");
2897 msg_print("Warning! Could not place lesser vault!");
2910 if (cheat_room) msg_format("%s", v_name + v_ptr->name);
2912 /* Boost the rating */
2913 rating += v_ptr->rat;
2915 /* (Sometimes) Cause a special feeling */
2916 if ((dun_level <= 50) ||
2917 (randint1((dun_level - 40) * (dun_level - 40) + 50) < 400))
2919 good_item_flag = TRUE;
2922 /* Hack -- Build the vault */
2923 build_vault(yval, xval, v_ptr->hgt, v_ptr->wid,
2924 v_text + v_ptr->text, xoffset, yoffset, transno);
2931 * Type 8 -- greater vaults (see "v_info.txt")
2933 static bool build_type8(void)
2935 vault_type *v_ptr = NULL;
2940 int xoffset, yoffset;
2942 /* Pick a greater vault */
2943 while (dummy < SAFE_MAX_ATTEMPTS)
2947 /* Access a random vault record */
2948 v_ptr = &v_info[randint0(max_v_idx)];
2950 /* Accept the first greater vault */
2951 if (v_ptr->typ == 8) break;
2954 /* No greater vault found */
2955 if (!v_ptr) return FALSE;
2957 /* pick type of transformation (0-7) */
2958 transno = randint0(8);
2960 /* calculate offsets */
2964 /* Some huge vault cannot be ratated to fit in the dungeon */
2965 if (x+2 > cur_hgt-2)
2967 /* Forbid 90 or 270 degree ratation */
2971 coord_trans(&x, &y, 0, 0, transno);
2992 * Try to allocate space for room. If fails, exit
2994 * Hack -- Prepare a bit larger space (+2, +2) to
2995 * prevent generation of vaults with no-entrance.
2997 /* Find and reserve some space in the dungeon. Get center of room. */
2998 if (!find_space(&yval, &xval, abs(y) + 2, abs(x) + 2)) return FALSE;
3001 if (dummy >= SAFE_MAX_ATTEMPTS)
3006 msg_print("·Ù¹ð¡ªµðÂç¤ÊÃϲ¼¼¼¤òÇÛÃ֤Ǥ¤Þ¤»¤ó¡ª");
3008 msg_print("Warning! Could not place greater vault!");
3017 v_ptr = &v_info[76 + randint1(3)];
3021 if (cheat_room) msg_format("%s", v_name + v_ptr->name);
3023 /* Boost the rating */
3024 rating += v_ptr->rat;
3026 /* (Sometimes) Cause a special feeling */
3027 if ((dun_level <= 50) ||
3028 (randint1((dun_level - 40) * (dun_level - 40) + 50) < 400))
3030 good_item_flag = TRUE;
3033 /* Hack -- Build the vault */
3034 build_vault(yval, xval, v_ptr->hgt, v_ptr->wid,
3035 v_text + v_ptr->text, xoffset, yoffset, transno);
3041 * Structure to hold all "fill" data
3044 typedef struct fill_data_type fill_data_type;
3046 struct fill_data_type
3059 /* features to fill with */
3068 /* number of filled squares */
3072 static fill_data_type fill_data;
3075 /* Store routine for the fractal cave generator */
3076 /* this routine probably should be an inline function or a macro. */
3077 static void store_height(int x, int y, int val)
3079 /* if on boundary set val > cutoff so walls are not as square */
3080 if (((x == fill_data.xmin) || (y == fill_data.ymin) ||
3081 (x == fill_data.xmax) || (y == fill_data.ymax)) &&
3082 (val <= fill_data.c1)) val = fill_data.c1 + 1;
3084 /* store the value in height-map format */
3085 cave[y][x].feat = val;
3092 * Explanation of the plasma fractal algorithm:
3094 * A grid of points is created with the properties of a 'height-map'
3095 * This is done by making the corners of the grid have a random value.
3096 * The grid is then subdivided into one with twice the resolution.
3097 * The new points midway between two 'known' points can be calculated
3098 * by taking the average value of the 'known' ones and randomly adding
3099 * or subtracting an amount proportional to the distance between those
3100 * points. The final 'middle' points of the grid are then calculated
3101 * by averaging all four of the originally 'known' corner points. An
3102 * random amount is added or subtracted from this to get a value of the
3103 * height at that point. The scaling factor here is adjusted to the
3104 * slightly larger distance diagonally as compared to orthogonally.
3106 * This is then repeated recursively to fill an entire 'height-map'
3107 * A rectangular map is done the same way, except there are different
3108 * scaling factors along the x and y directions.
3110 * A hack to change the amount of correlation between points is done using
3111 * the grd variable. If the current step size is greater than grd then
3112 * the point will be random, otherwise it will be calculated by the
3113 * above algorithm. This makes a maximum distance at which two points on
3114 * the height map can affect each other.
3116 * How fractal caves are made:
3118 * When the map is complete, a cut-off value is used to create a cave.
3119 * Heights below this value are "floor", and heights above are "wall".
3120 * This also can be used to create lakes, by adding more height levels
3121 * representing shallow and deep water/ lava etc.
3123 * The grd variable affects the width of passages.
3124 * The roug variable affects the roughness of those passages
3126 * The tricky part is making sure the created cave is connected. This
3127 * is done by 'filling' from the inside and only keeping the 'filled'
3128 * floor. Walls bounding the 'filled' floor are also kept. Everything
3129 * else is converted to the normal granite FEAT_WALL_EXTRA.
3134 * Note that this uses the cave.feat array in a very hackish way
3135 * the values are first set to zero, and then each array location
3136 * is used as a "heightmap"
3137 * The heightmap then needs to be converted back into the "feat" format.
3139 * grd=level at which fractal turns on. smaller gives more mazelike caves
3140 * roug=roughness level. 16=normal. higher values make things more convoluted
3141 * small values are good for smooth walls.
3142 * size=length of the side of the square cave system.
3144 static void generate_hmap(int y0, int x0, int xsiz, int ysiz, int grd, int roug, int cutoff)
3146 int xhsize, yhsize, xsize, ysize, maxsize;
3149 * fixed point variables- these are stored as 256 x normal value
3150 * this gives 8 binary places of fractional part + 8 places of normal part
3153 u16b xstep, xhstep, ystep, yhstep;
3154 u16b xstep2, xhstep2, ystep2, yhstep2;
3155 u16b i, j, ii, jj, diagsize, xxsize, yysize;
3157 /* Cache for speed */
3158 u16b xm, xp, ym, yp;
3160 /* redefine size so can change the value if out of range */
3164 /* Paranoia about size of the system of caves */
3165 if (xsize > 254) xsize = 254;
3166 if (xsize < 4) xsize = 4;
3167 if (ysize > 254) ysize = 254;
3168 if (ysize < 4) ysize = 4;
3170 /* get offsets to middle of array */
3174 /* fix rounding problem */
3178 /* get limits of region */
3179 fill_data.xmin = x0 - xhsize;
3180 fill_data.ymin = y0 - yhsize;
3181 fill_data.xmax = x0 + xhsize;
3182 fill_data.ymax = y0 + yhsize;
3184 /* Store cutoff in global for quick access */
3185 fill_data.c1 = cutoff;
3188 * Scale factor for middle points:
3189 * About sqrt(2) * 256 - correct for a square lattice
3190 * approximately correct for everything else.
3194 /* maximum of xsize and ysize */
3195 maxsize = (xsize > ysize) ? xsize : ysize;
3197 /* Clear the section */
3198 for (i = 0; i <= xsize; i++)
3200 for (j = 0; j <= ysize; j++)
3202 /* 255 is a flag for "not done yet" */
3203 cave[(int)(fill_data.ymin + j)][(int)(fill_data.xmin + i)].feat = 255;
3204 /* Clear icky flag because may be redoing the cave */
3205 cave[(int)(fill_data.ymin + j)][(int)(fill_data.xmin + i)].info &= ~(CAVE_ICKY);
3209 /* Boundaries are walls */
3210 cave[fill_data.ymin][fill_data.xmin].feat = maxsize;
3211 cave[fill_data.ymax][fill_data.xmin].feat = maxsize;
3212 cave[fill_data.ymin][fill_data.xmax].feat = maxsize;
3213 cave[fill_data.ymax][fill_data.xmax].feat = maxsize;
3215 /* Set the middle square to be an open area. */
3216 cave[y0][x0].feat = 0;
3218 /* Initialize the step sizes */
3219 xstep = xhstep = xsize * 256;
3220 ystep = yhstep = ysize * 256;
3221 xxsize = xsize * 256;
3222 yysize = ysize * 256;
3225 * Fill in the rectangle with fractal height data -
3226 * like the 'plasma fractal' in fractint.
3228 while ((xhstep > 256) || (yhstep > 256))
3230 /* Halve the step sizes */
3236 /* cache well used values */
3237 xstep2 = xstep / 256;
3238 ystep2 = ystep / 256;
3240 xhstep2 = xhstep / 256;
3241 yhstep2 = yhstep / 256;
3243 /* middle top to bottom. */
3244 for (i = xhstep; i <= xxsize - xhstep; i += xstep)
3246 for (j = 0; j <= yysize; j += ystep)
3248 /* cache often used values */
3249 ii = i / 256 + fill_data.xmin;
3250 jj = j / 256 + fill_data.ymin;
3253 if (cave[jj][ii].feat == 255)
3257 /* If greater than 'grid' level then is random */
3258 store_height(ii, jj, randint1(maxsize));
3262 /* Average of left and right points +random bit */
3263 store_height(ii, jj,
3264 (cave[jj][fill_data.xmin + (i - xhstep) / 256].feat
3265 + cave[jj][fill_data.xmin + (i + xhstep) / 256].feat) / 2
3266 + (randint1(xstep2) - xhstep2) * roug / 16);
3273 /* middle left to right. */
3274 for (j = yhstep; j <= yysize - yhstep; j += ystep)
3276 for (i = 0; i <= xxsize; i += xstep)
3278 /* cache often used values */
3279 ii = i / 256 + fill_data.xmin;
3280 jj = j / 256 + fill_data.ymin;
3283 if (cave[jj][ii].feat == 255)
3287 /* If greater than 'grid' level then is random */
3288 store_height(ii, jj, randint1(maxsize));
3292 /* Average of up and down points +random bit */
3293 store_height(ii, jj,
3294 (cave[fill_data.ymin + (j - yhstep) / 256][ii].feat
3295 + cave[fill_data.ymin + (j + yhstep) / 256][ii].feat) / 2
3296 + (randint1(ystep2) - yhstep2) * roug / 16);
3303 for (i = xhstep; i <= xxsize - xhstep; i += xstep)
3305 for (j = yhstep; j <= yysize - yhstep; j += ystep)
3307 /* cache often used values */
3308 ii = i / 256 + fill_data.xmin;
3309 jj = j / 256 + fill_data.ymin;
3312 if (cave[jj][ii].feat == 255)
3316 /* If greater than 'grid' level then is random */
3317 store_height(ii, jj, randint1(maxsize));
3321 /* Cache reused values. */
3322 xm = fill_data.xmin + (i - xhstep) / 256;
3323 xp = fill_data.xmin + (i + xhstep) / 256;
3324 ym = fill_data.ymin + (j - yhstep) / 256;
3325 yp = fill_data.ymin + (j + yhstep) / 256;
3328 * Average over all four corners + scale by diagsize to
3329 * reduce the effect of the square grid on the shape of the fractal
3331 store_height(ii, jj,
3332 (cave[ym][xm].feat + cave[yp][xm].feat
3333 + cave[ym][xp].feat + cave[yp][xp].feat) / 4
3334 + (randint1(xstep2) - xhstep2) * (diagsize / 16) / 256 * roug);
3343 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)
3346 * function used to convert from height-map back to the
3347 * normal angband cave format
3349 if (cave[y][x].info & CAVE_ICKY)
3356 /* Show that have looked at this square */
3357 cave[y][x].info|= (CAVE_ICKY);
3359 /* Use cutoffs c1-c3 to allocate regions of floor /water/ lava etc. */
3360 if (cave[y][x].feat <= c1)
3362 /* 25% of the time use the other tile : it looks better this way */
3363 if (randint1(100) < 75)
3365 cave[y][x].feat = feat1;
3366 cave[y][x].info &= ~(CAVE_MASK);
3367 cave[y][x].info |= info1;
3372 cave[y][x].feat = feat2;
3373 cave[y][x].info &= ~(CAVE_MASK);
3374 cave[y][x].info |= info2;
3378 else if (cave[y][x].feat <= c2)
3380 /* 25% of the time use the other tile : it looks better this way */
3381 if (randint1(100) < 75)
3383 cave[y][x].feat = feat2;
3384 cave[y][x].info &= ~(CAVE_MASK);
3385 cave[y][x].info |= info2;
3390 cave[y][x].feat = feat1;
3391 cave[y][x].info &= ~(CAVE_MASK);
3392 cave[y][x].info |= info1;
3396 else if (cave[y][x].feat <= c3)
3398 cave[y][x].feat = feat3;
3399 cave[y][x].info |= info3;
3402 /* if greater than cutoff then is a wall */
3405 place_outer_bold(y, x);
3415 * Quick and nasty fill routine used to find the connected region
3416 * of floor in the middle of the cave
3418 static void cave_fill(byte y, byte x)
3427 /*** Start Grid ***/
3429 /* Enqueue that entry */
3434 /* Now process the queue */
3435 while (flow_head != flow_tail)
3437 /* Extract the next entry */
3438 ty = temp_y[flow_head];
3439 tx = temp_x[flow_head];
3441 /* Forget that entry */
3442 if (++flow_head == TEMP_MAX) flow_head = 0;
3444 /* Add the "children" */
3445 for (d = 0; d < 8; d++)
3447 int old_head = flow_tail;
3449 /* Child location */
3450 j = ty + ddy_ddd[d];
3451 i = tx + ddx_ddd[d];
3453 /* Paranoia Don't leave the cave */
3454 if (!in_bounds(j, i))
3456 /* affect boundary */
3457 cave[j][i].info |= CAVE_ICKY;
3461 /* If within bounds */
3462 else if ((i > fill_data.xmin) && (i < fill_data.xmax)
3463 && (j > fill_data.ymin) && (j < fill_data.ymax))
3465 /* If not a wall or floor done before */
3466 if (hack_isnt_wall(j, i,
3467 fill_data.c1, fill_data.c2, fill_data.c3,
3468 fill_data.feat1, fill_data.feat2, fill_data.feat3,
3469 fill_data.info1, fill_data.info2, fill_data.info3))
3471 /* Enqueue that entry */
3472 temp_y[flow_tail] = j;
3473 temp_x[flow_tail] = i;
3475 /* Advance the queue */
3476 if (++flow_tail == TEMP_MAX) flow_tail = 0;
3478 /* Hack -- Overflow by forgetting new entry */
3479 if (flow_tail == flow_head)
3481 flow_tail = old_head;
3485 /* keep tally of size of cave system */
3486 (fill_data.amount)++;
3492 /* affect boundary */
3493 cave[j][i].info |= CAVE_ICKY;
3500 static bool generate_fracave(int y0, int x0, int xsize, int ysize, int cutoff, bool light, bool room)
3502 int x, y, i, xhsize, yhsize;
3505 /* offsets to middle from corner */
3511 * select region connected to center of cave system
3512 * this gets rid of alot of isolated one-sqaures that
3513 * can make teleport traps instadeaths...
3517 fill_data.c1 = cutoff;
3521 /* features to fill with */
3522 fill_data.feat1 = floor_type[randint0(100)];
3523 fill_data.feat2 = floor_type[randint0(100)];
3524 fill_data.feat3 = floor_type[randint0(100)];
3526 fill_data.info1 = CAVE_FLOOR;
3527 fill_data.info2 = CAVE_FLOOR;
3528 fill_data.info3 = CAVE_FLOOR;
3530 /* number of filled squares */
3531 fill_data.amount = 0;
3533 cave_fill((byte)y0, (byte)x0);
3535 /* if tally too small, try again */
3536 if (fill_data.amount < 10)
3538 /* too small - clear area and try again later */
3539 for (x = 0; x <= xsize; ++x)
3541 for (y = 0; y <= ysize; ++y)
3543 place_extra_bold(y0 + y - yhsize, x0 + x - xhsize);
3544 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY | CAVE_ROOM);
3551 * Do boundarys-check to see if they are next to a filled region
3552 * If not then they are set to normal granite
3553 * If so then they are marked as room walls.
3555 for (i = 0; i <= xsize; ++i)
3558 if ((cave[0 + y0 - yhsize][i + x0 - xhsize].info & CAVE_ICKY) && (room))
3560 /* Next to a 'filled' region? - set to be room walls */
3561 place_outer_bold(y0 + 0 - yhsize, x0 + i - xhsize);
3562 if (light) cave[y0 + 0 - yhsize][x0 + i - xhsize].info |= (CAVE_GLOW);
3563 cave[y0 + 0 - yhsize][x0 + i - xhsize].info |= (CAVE_ROOM);
3564 place_outer_bold(y0 + 0 - yhsize, x0 + i - xhsize);
3568 /* set to be normal granite */
3569 place_extra_bold(y0 + 0 - yhsize, x0 + i - xhsize);
3572 /* bottom boundary */
3573 if ((cave[ysize + y0 - yhsize][i + x0 - xhsize].info & CAVE_ICKY) && (room))
3575 /* Next to a 'filled' region? - set to be room walls */
3576 place_outer_bold(y0 + ysize - yhsize, x0 + i - xhsize);
3577 if (light) cave[y0 + ysize - yhsize][x0 + i - xhsize].info|=(CAVE_GLOW);
3578 cave[y0 + ysize - yhsize][x0 + i - xhsize].info|=(CAVE_ROOM);
3579 place_outer_bold(y0 + ysize - yhsize, x0 + i - xhsize);
3583 /* set to be normal granite */
3584 place_extra_bold(y0 + ysize - yhsize, x0 + i - xhsize);
3587 /* clear the icky flag-don't need it any more */
3588 cave[y0 + 0 - yhsize][x0 + i - xhsize].info &= ~(CAVE_ICKY);
3589 cave[y0 + ysize - yhsize][x0 + i - xhsize].info &= ~(CAVE_ICKY);
3592 /* Do the left and right boundaries minus the corners (done above) */
3593 for (i = 1; i < ysize; ++i)
3596 if ((cave[i + y0 - yhsize][0 + x0 - xhsize].info & CAVE_ICKY) && room)
3599 place_outer_bold(y0 + i - yhsize, x0 + 0 - xhsize);
3600 if (light) cave[y0 + i - yhsize][x0 + 0 - xhsize].info |= (CAVE_GLOW);
3601 cave[y0 + i - yhsize][x0 + 0 - xhsize].info |= (CAVE_ROOM);
3602 place_outer_bold(y0 + i - yhsize, x0 + 0 - xhsize);
3607 place_extra_bold(y0 + i - yhsize, x0 + 0 - xhsize);
3609 /* right boundary */
3610 if ((cave[i + y0 - yhsize][xsize + x0 - xhsize].info & CAVE_ICKY) && room)
3613 place_outer_bold(y0 + i - yhsize, x0 + xsize - xhsize);
3614 if (light) cave[y0 + i - yhsize][x0 + xsize - xhsize].info |= (CAVE_GLOW);
3615 cave[y0 + i - yhsize][x0 + xsize - xhsize].info |= (CAVE_ROOM);
3616 place_outer_bold(y0 + i - yhsize, x0 + xsize - xhsize);
3621 place_extra_bold(y0 + i - yhsize, x0 + xsize - xhsize);
3624 /* clear icky flag -done with it */
3625 cave[y0 + i - yhsize][x0 + 0 - xhsize].info &= ~(CAVE_ICKY);
3626 cave[y0 + i - yhsize][x0 + xsize - xhsize].info &= ~(CAVE_ICKY);
3630 /* Do the rest: convert back to the normal format */
3631 for (x = 1; x < xsize; ++x)
3633 for (y = 1; y < ysize; ++y)
3635 if (is_floor_bold(y0 + y - yhsize, x0 + x - xhsize) &&
3636 (cave[y0 + y - yhsize][x0 + x - xhsize].info & CAVE_ICKY))
3638 /* Clear the icky flag in the filled region */
3639 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~CAVE_ICKY;
3641 /* Set appropriate flags */
3642 if (light) cave[y0 + y - yhsize][x0 + x - xhsize].info |= (CAVE_GLOW);
3643 if (room) cave[y0 + y - yhsize][x0 + x - xhsize].info |= (CAVE_ROOM);
3645 else if (is_outer_bold(y0 + y - yhsize, x0 + x - xhsize) &&
3646 (cave[y0 + y - yhsize][x0 + x - xhsize].info & CAVE_ICKY))
3649 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY);
3650 if (light) cave[y0 + y - yhsize][x0 + x - xhsize].info |= (CAVE_GLOW);
3653 cave[y0 + y - yhsize][x0 + x - xhsize].info |= (CAVE_ROOM);
3658 place_extra_bold(y0 + y - yhsize, x0 + x - xhsize);
3659 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ROOM);
3664 /* Clear the unconnected regions */
3665 place_extra_bold(y0 + y - yhsize, x0 + x - xhsize);
3666 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY | CAVE_ROOM);
3672 * XXX XXX XXX There is a slight problem when tunnels pierce the caves:
3673 * Extra doors appear inside the system. (Its not very noticeable though.)
3674 * This can be removed by "filling" from the outside in. This allows a separation
3675 * from FEAT_WALL_OUTER with FEAT_WALL_INNER. (Internal walls are F.W.OUTER instead.)
3676 * The extra effort for what seems to be only a minor thing (even non-existant if you
3677 * think of the caves not as normal rooms, but as holes in the dungeon), doesn't seem
3686 * Driver routine to create fractal cave system
3688 static bool build_type9(void)
3690 int grd, roug, cutoff, xsize, ysize, y0, x0;
3692 bool done, light, room;
3694 /* get size: note 'Evenness'*/
3695 xsize = randint1(22) * 2 + 6;
3696 ysize = randint1(15) * 2 + 6;
3698 /* Find and reserve some space in the dungeon. Get center of room. */
3699 if (!find_space(&y0, &x0, ysize + 1, xsize + 1)) return FALSE;
3701 light = done = FALSE;
3704 if ((dun_level <= randint1(25)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS)) light = TRUE;
3708 /* Note: size must be even or there are rounding problems
3709 * This causes the tunnels not to connect properly to the room */
3711 /* testing values for these parameters feel free to adjust */
3712 grd = 1 << (randint0(4));
3714 /* want average of about 16 */
3715 roug = randint1(8) * randint1(4);
3718 cutoff = randint1(xsize / 4) + randint1(ysize / 4) +
3719 randint1(xsize / 4) + randint1(ysize / 4);
3722 generate_hmap(y0, x0, xsize, ysize, grd, roug, cutoff);
3724 /* Convert to normal format + clean up */
3725 done = generate_fracave(y0, x0, xsize, ysize, cutoff, light, room);
3731 #ifdef ALLOW_CAVERNS_AND_LAKES
3733 * Builds a cave system in the center of the dungeon.
3735 void build_cavern(void)
3737 int grd, roug, cutoff, xsize, ysize, x0, y0;
3740 light = done = FALSE;
3741 if ((dun_level <= randint1(50)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS)) light = TRUE;
3743 /* Make a cave the size of the dungeon */
3744 xsize = cur_wid - 1;
3745 ysize = cur_hgt - 1;
3749 /* Paranoia: make size even */
3755 /* testing values for these parameters: feel free to adjust */
3756 grd = randint1(4) + 4;
3758 /* want average of about 16 */
3759 roug = randint1(8) * randint1(4);
3765 generate_hmap(y0 + 1, x0 + 1, xsize, ysize, grd, roug, cutoff);
3767 /* Convert to normal format+ clean up */
3768 done = generate_fracave(y0 + 1, x0 + 1, xsize, ysize, cutoff, light, FALSE);
3772 static bool generate_lake(int y0, int x0, int xsize, int ysize, int c1, int c2, int c3, int type)
3774 int x, y, i, xhsize, yhsize;
3775 int feat1, feat2, feat3;
3777 /* offsets to middle from corner */
3781 /* Get features based on type */
3784 case LAKE_T_LAVA: /* Lava */
3785 feat1 = FEAT_DEEP_LAVA;
3786 feat2 = FEAT_SHAL_LAVA;
3787 feat3 = floor_type[randint0(100)];
3789 case LAKE_T_WATER: /* Water */
3790 feat1 = FEAT_DEEP_WATER;
3791 feat2 = FEAT_SHAL_WATER;
3792 feat3 = floor_type[randint0(100)];
3794 case LAKE_T_CAVE: /* Collapsed cave */
3795 feat1 = floor_type[randint0(100)];
3796 feat2 = floor_type[randint0(100)];
3797 feat3 = FEAT_RUBBLE;
3799 case LAKE_T_EARTH_VAULT: /* Earth vault */
3800 feat1 = FEAT_RUBBLE;
3801 feat2 = floor_type[randint0(100)];
3802 feat3 = FEAT_RUBBLE;
3804 case LAKE_T_AIR_VAULT: /* Air vault */
3809 case LAKE_T_WATER_VAULT: /* Water vault */
3810 feat1 = FEAT_SHAL_WATER;
3811 feat2 = FEAT_DEEP_WATER;
3812 feat3 = FEAT_SHAL_WATER;
3814 case LAKE_T_FIRE_VAULT: /* Fire Vault */
3815 feat1 = FEAT_SHAL_LAVA;
3816 feat2 = FEAT_DEEP_LAVA;
3817 feat3 = FEAT_SHAL_LAVA;
3821 default: return FALSE;
3825 * select region connected to center of cave system
3826 * this gets rid of alot of isolated one-sqaures that
3827 * can make teleport traps instadeaths...
3835 /* features to fill with */
3836 fill_data.feat1 = feat1;
3837 fill_data.feat2 = feat2;
3838 fill_data.feat3 = feat3;
3840 fill_data.info1 = 0;
3841 fill_data.info2 = 0;
3842 fill_data.info3 = 0;
3844 /* number of filled squares */
3845 fill_data.amount = 0;
3847 /* select region connected to center of cave system
3848 * this gets rid of alot of isolated one-sqaures that
3849 * can make teleport traps instadeaths... */
3850 cave_fill((byte)y0, (byte)x0);
3852 /* if tally too small, try again */
3853 if (fill_data.amount < 10)
3855 /* too small -clear area and try again later */
3856 for (x = 0; x <= xsize; ++x)
3858 for (y = 0; y <= ysize; ++y)
3860 place_floor_bold(y0 + y - yhsize, x0 + x - xhsize);
3861 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY);
3867 /* Do boundarys- set to normal granite */
3868 for (i = 0; i <= xsize; ++i)
3870 place_extra_bold(y0 + 0 - yhsize, x0 + i - xhsize);
3871 place_extra_bold(y0 + ysize - yhsize, x0 + i - xhsize);
3873 /* clear the icky flag-don't need it any more */
3874 cave[y0 + 0 - yhsize][x0 + i - xhsize].info &= ~(CAVE_ICKY);
3875 cave[y0 + ysize - yhsize][x0 + i - xhsize].info &= ~(CAVE_ICKY);
3878 /* Do the left and right boundaries minus the corners (done above) */
3880 for (i = 1; i < ysize; ++i)
3882 place_extra_bold(y0 + i - yhsize, x0 + 0 - xhsize);
3883 place_extra_bold(y0 + i - yhsize, x0 + xsize - xhsize);
3885 /* clear icky flag -done with it */
3886 cave[y0 + i - yhsize][x0 + 0 - xhsize].info &= ~(CAVE_ICKY);
3887 cave[y0 + i - yhsize][x0 + xsize - xhsize].info &= ~(CAVE_ICKY);
3891 /* Do the rest: convert back to the normal format */
3892 for (x = 1; x < xsize; ++x)
3894 for (y = 1; y < ysize; ++y)
3896 /* Fill unconnected regions with granite */
3897 if ((!(cave[y0 + y - yhsize][x0 + x - xhsize].info & CAVE_ICKY)) ||
3898 is_outer_bold(y0 + y - yhsize, x0 + x - xhsize))
3899 place_extra_bold(y0 + y - yhsize, x0 + x - xhsize);
3901 /* turn off icky flag (no longer needed.) */
3902 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY | CAVE_ROOM);
3904 /* Light lava and trees */
3905 if ((cave[y0 + y - yhsize][x0 + x - xhsize].feat == FEAT_DEEP_LAVA) ||
3906 (cave[y0 + y - yhsize][x0 + x - xhsize].feat == FEAT_SHAL_LAVA))
3908 if (!(d_info[dungeon_type].flags1 & DF1_DARKNESS)) cave[y0 + y - yhsize][x0 + x - xhsize].info |= CAVE_GLOW;
3918 * makes a lake/collapsed cave system in the center of the dungeon
3920 void build_lake(int type)
3922 int grd, roug, xsize, ysize, x0, y0;
3926 /* paranoia - exit if lake type out of range. */
3927 if ((type < LAKE_T_LAVA) || (type > LAKE_T_FIRE_VAULT))
3929 msg_format("Invalid lake type (%d)", type);
3933 /* Make the size of the dungeon */
3934 xsize = cur_wid - 1;
3935 ysize = cur_hgt - 1;
3939 /* Paranoia: make size even */
3945 /* testing values for these parameters: feel free to adjust */
3946 grd = randint1(3) + 4;
3948 /* want average of about 16 */
3949 roug = randint1(8) * randint1(4);
3951 /* Make up size of various componants */
3955 /* Deep water/lava */
3956 c1 = randint0(c3 / 2) + randint0(c3 / 2) - 5;
3958 /* Shallow boundary */
3962 generate_hmap(y0 + 1, x0 + 1, xsize, ysize, grd, roug, c3);
3964 /* Convert to normal format+ clean up */
3965 done = generate_lake(y0 + 1, x0 + 1, xsize, ysize, c1, c2, c3, type);
3968 #endif /* ALLOW_CAVERNS_AND_LAKES */
3972 * Routine used by the random vault creators to add a door to a location
3973 * Note that range checking has to be done in the calling routine.
3975 * The doors must be INSIDE the allocated region.
3977 static void add_door(int x, int y)
3979 /* Need to have a wall in the center square */
3980 if (!is_outer_bold(y, x)) return;
3987 * where x=don't care
3991 if (is_floor_bold(y-1,x) && is_floor_bold(y+1,x) &&
3992 (is_outer_bold(y, x - 1) && is_outer_bold(y, x + 1)))
3995 place_secret_door(y, x);
3997 /* set boundarys so don't get wide doors */
3998 place_solid_bold(y, x - 1);
3999 place_solid_bold(y, x + 1);
4008 * where x = don't care
4011 if (is_outer_bold(y - 1, x) && is_outer_bold(y + 1, x) &&
4012 is_floor_bold(y,x-1) && is_floor_bold(y,x+1))
4015 place_secret_door(y, x);
4017 /* set boundarys so don't get wide doors */
4018 place_solid_bold(y - 1, x);
4019 place_solid_bold(y + 1, x);
4025 * Routine that fills the empty areas of a room with treasure and monsters.
4027 static void fill_treasure(int x1, int x2, int y1, int y2, int difficulty)
4029 int x, y, cx, cy, size;
4032 /* center of room:*/
4036 /* Rough measure of size of vault= sum of lengths of sides */
4037 size = abs(x2 - x1) + abs(y2 - y1);
4039 for (x = x1; x <= x2; x++)
4041 for (y = y1; y <= y2; y++)
4043 /* Thing added based on distance to center of vault
4044 * Difficulty is 1-easy to 10-hard */
4045 value = ((((s32b)(distance(cx, cy, x, y))) * 100) / size) + randint1(10) - difficulty;
4047 /* hack- empty square part of the time */
4048 if ((randint1(100) - difficulty * 3) > 50) value = 20;
4050 /* if floor, shallow water and lava */
4051 if (is_floor_bold(y, x) ||
4052 (cave[y][x].feat == FEAT_SHAL_WATER) ||
4053 (cave[y][x].feat == FEAT_SHAL_LAVA))
4055 /* The smaller 'value' is, the better the stuff */
4058 /* Meanest monster + treasure */
4059 monster_level = base_level + 40;
4060 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
4061 monster_level = base_level;
4062 object_level = base_level + 20;
4063 place_object(y, x, AM_GOOD);
4064 object_level = base_level;
4068 /* Mean monster +treasure */
4069 monster_level = base_level + 20;
4070 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
4071 monster_level = base_level;
4072 object_level = base_level + 10;
4073 place_object(y, x, AM_GOOD);
4074 object_level = base_level;
4076 else if (value < 10)
4079 monster_level = base_level + 9;
4080 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
4081 monster_level = base_level;
4083 else if (value < 17)
4085 /* Intentional Blank space */
4088 * (Want some of the vault to be empty
4089 * so have room for group monsters.
4090 * This is used in the hack above to lower
4091 * the density of stuff in the vault.)
4094 else if (value < 23)
4096 /* Object or trap */
4097 if (randint0(100) < 25)
4099 place_object(y, x, 0L);
4106 else if (value < 30)
4108 /* Monster and trap */
4109 monster_level = base_level + 5;
4110 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
4111 monster_level = base_level;
4114 else if (value < 40)
4116 /* Monster or object */
4117 if (randint0(100) < 50)
4119 monster_level = base_level + 3;
4120 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
4121 monster_level = base_level;
4123 if (randint0(100) < 50)
4125 object_level = base_level + 7;
4126 place_object(y, x, 0L);
4127 object_level = base_level;
4130 else if (value < 50)
4139 /* 20% monster, 40% trap, 20% object, 20% blank space */
4140 if (randint0(100) < 20)
4142 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
4144 else if (randint0(100) < 50)
4148 else if (randint0(100) < 50)
4150 place_object(y, x, 0L);
4161 * This function creates a random vault that looks like a collection of bubbles.
4162 * It works by getting a set of coordinates that represent the center of each
4163 * bubble. The entire room is made by seeing which bubble center is closest. If
4164 * two centers are equidistant then the square is a wall, otherwise it is a floor.
4165 * The only exception is for squares really near a center, these are always floor.
4166 * (It looks better than without this check.)
4168 * Note: If two centers are on the same point then this algorithm will create a
4169 * blank bubble filled with walls. - This is prevented from happening.
4171 static void build_bubble_vault(int x0, int y0, int xsize, int ysize)
4173 #define BUBBLENUM 10 /* number of bubbles */
4175 /* array of center points of bubbles */
4176 coord center[BUBBLENUM];
4179 u16b min1, min2, temp;
4182 /* Offset from center to top left hand corner */
4183 int xhsize = xsize / 2;
4184 int yhsize = ysize / 2;
4187 if (cheat_room) msg_print("Bubble Vault");
4189 /* Allocate center of bubbles */
4190 center[0].x = randint1(xsize - 3) + 1;
4191 center[0].y = randint1(ysize - 3) + 1;
4193 for (i = 1; i < BUBBLENUM; i++)
4197 /* get center and check to see if it is unique */
4202 x = randint1(xsize - 3) + 1;
4203 y = randint1(ysize - 3) + 1;
4205 for (j = 0; j < i; j++)
4207 /* rough test to see if there is an overlap */
4208 if ((x == center[j].x) && (y == center[j].y)) done = FALSE;
4217 /* Top and bottom boundaries */
4218 for (i = 0; i < xsize; i++)
4220 int x = x0 - xhsize + i;
4222 place_outer_noperm_bold(y0 - yhsize + 0, x);
4223 cave[y0 - yhsize + 0][x].info |= (CAVE_ROOM | CAVE_ICKY);
4224 place_outer_noperm_bold(y0 - yhsize + ysize - 1, x);
4225 cave[y0 - yhsize + ysize - 1][x].info |= (CAVE_ROOM | CAVE_ICKY);
4228 /* Left and right boundaries */
4229 for (i = 1; i < ysize - 1; i++)
4231 int y = y0 - yhsize + i;
4233 place_outer_noperm_bold(y, x0 - xhsize + 0);
4234 cave[y][x0 - xhsize + 0].info |= (CAVE_ROOM | CAVE_ICKY);
4235 place_outer_noperm_bold(y, x0 - xhsize + xsize - 1);
4236 cave[y][x0 - xhsize + xsize - 1].info |= (CAVE_ROOM | CAVE_ICKY);
4239 /* Fill in middle with bubbles */
4240 for (x = 1; x < xsize - 1; x++)
4242 for (y = 1; y < ysize - 1; y++)
4244 /* Get distances to two closest centers */
4247 min1 = distance(x, y, center[0].x, center[0].y);
4248 min2 = distance(x, y, center[1].x, center[1].y);
4252 /* swap if in wrong order */
4259 for (i = 2; i < BUBBLENUM; i++)
4261 temp = distance(x, y, center[i].x, center[i].y);
4269 else if (temp < min2)
4271 /* second smallest */
4275 if (((min2 - min1) <= 2) && (!(min1 < 3)))
4277 /* Boundary at midpoint+ not at inner region of bubble */
4278 place_outer_noperm_bold(y0 - yhsize + y, x0 - xhsize + x);
4282 /* middle of a bubble */
4283 place_floor_bold(y0 - yhsize + y, x0 - xhsize + x);
4286 /* clean up rest of flags */
4287 cave[y0 - yhsize + y][x0 - xhsize + x].info |= (CAVE_ROOM | CAVE_ICKY);
4291 /* Try to add some random doors */
4292 for (i = 0; i < 500; i++)
4294 x = randint1(xsize - 3) - xhsize + x0 + 1;
4295 y = randint1(ysize - 3) - yhsize + y0 + 1;
4299 /* Fill with monsters and treasure, low difficulty */
4300 fill_treasure(x0 - xhsize + 1, x0 - xhsize + xsize - 2, y0 - yhsize + 1, y0 - yhsize + ysize - 2, randint1(5));
4305 * Overlay a rectangular room given its bounds
4306 * This routine is used by build_room_vault
4307 * The area inside the walls is not touched:
4308 * only granite is removed- normal walls stay
4310 static void build_room(int x1, int x2, int y1, int y2)
4312 int x, y, i, xsize, ysize, temp;
4314 /* Check if rectangle has no width */
4315 if ((x1 == x2) || (y1 == y2)) return;
4320 /* Swap boundaries if in wrong order */
4328 /* Swap boundaries if in wrong order */
4334 /* get total widths */
4339 /* Top and bottom boundaries */
4340 for (i = 0; i <= xsize; i++)
4342 place_outer_noperm_bold(y1, x1 + i);
4343 cave[y1][x1 + i].info |= (CAVE_ROOM | CAVE_ICKY);
4344 place_outer_noperm_bold(y2, x1 + i);
4345 cave[y2][x1 + i].info |= (CAVE_ROOM | CAVE_ICKY);
4348 /* Left and right boundaries */
4349 for (i = 1; i < ysize; i++)
4351 place_outer_noperm_bold(y1 + i, x1);
4352 cave[y1 + i][x1].info|=(CAVE_ROOM | CAVE_ICKY);
4353 place_outer_noperm_bold(y1 + i, x2);
4354 cave[y1 + i][x2].info|=(CAVE_ROOM | CAVE_ICKY);
4358 for (x = 1; x < xsize; x++)
4360 for (y = 1; y < ysize; y++)
4362 if (is_extra_bold(y1+y, x1+x))
4364 /* clear the untouched region */
4365 place_floor_bold(y1 + y, x1 + x);
4366 cave[y1 + y][x1 + x].info |= (CAVE_ROOM | CAVE_ICKY);
4370 /* make it a room- but don't touch */
4371 cave[y1 + y][x1 + x].info |= (CAVE_ROOM | CAVE_ICKY);
4378 /* Create a random vault that looks like a collection of overlapping rooms */
4380 static void build_room_vault(int x0, int y0, int xsize, int ysize)
4382 int i, x1, x2, y1, y2, xhsize, yhsize;
4384 /* get offset from center */
4388 if (cheat_room) msg_print("Room Vault");
4390 /* fill area so don't get problems with arena levels */
4391 for (x1 = 0; x1 < xsize; x1++)
4393 int x = x0 - xhsize + x1;
4395 for (y1 = 0; y1 < ysize; y1++)
4397 int y = y0 - yhsize + y1;
4399 place_extra_bold(y, x);
4400 cave[y][x].info &= (~CAVE_ICKY);
4404 /* add ten random rooms */
4405 for (i = 0; i < 10; i++)
4407 x1 = randint1(xhsize) * 2 + x0 - xhsize;
4408 x2 = randint1(xhsize) * 2 + x0 - xhsize;
4409 y1 = randint1(yhsize) * 2 + y0 - yhsize;
4410 y2 = randint1(yhsize) * 2 + y0 - yhsize;
4411 build_room(x1, x2, y1, y2);
4414 /* Add some random doors */
4415 for (i = 0; i < 500; i++)
4417 x1 = randint1(xsize - 3) - xhsize + x0 + 1;
4418 y1 = randint1(ysize - 3) - yhsize + y0 + 1;
4422 /* Fill with monsters and treasure, high difficulty */
4423 fill_treasure(x0 - xhsize + 1, x0 - xhsize + xsize - 2, y0 - yhsize + 1, y0 - yhsize + ysize - 2, randint1(5) + 5);
4427 /* Create a random vault out of a fractal cave */
4428 static void build_cave_vault(int x0, int y0, int xsiz, int ysiz)
4430 int grd, roug, cutoff, xhsize, yhsize, xsize, ysize, x, y;
4431 bool done, light, room;
4433 /* round to make sizes even */
4439 if (cheat_room) msg_print("Cave Vault");
4441 light = done = FALSE;
4446 /* testing values for these parameters feel free to adjust */
4447 grd = 1 << randint0(4);
4449 /* want average of about 16 */
4450 roug = randint1(8) * randint1(4);
4453 cutoff = randint1(xsize / 4) + randint1(ysize / 4) +
4454 randint1(xsize / 4) + randint1(ysize / 4);
4457 generate_hmap(y0, x0, xsize, ysize, grd, roug, cutoff);
4459 /* Convert to normal format+ clean up */
4460 done = generate_fracave(y0, x0, xsize, ysize, cutoff, light, room);
4463 /* Set icky flag because is a vault */
4464 for (x = 0; x <= xsize; x++)
4466 for (y = 0; y <= ysize; y++)
4468 cave[y0 - yhsize + y][x0 - xhsize + x].info |= CAVE_ICKY;
4472 /* Fill with monsters and treasure, low difficulty */
4473 fill_treasure(x0 - xhsize + 1, x0 - xhsize + xsize - 1, y0 - yhsize + 1, y0 - yhsize + ysize - 1, randint1(5));
4477 * maze vault -- rectangular labyrinthine rooms
4479 * maze vault uses two routines:
4480 * r_visit - a recursive routine that builds the labyrinth
4481 * build_maze_vault - a driver routine that calls r_visit and adds
4482 * monsters, traps and treasure
4484 * The labyrinth is built by creating a spanning tree of a graph.
4485 * The graph vertices are at
4486 * (x, y) = (2j + x1, 2k + y1) j = 0,...,m-1 k = 0,...,n-1
4487 * and the edges are the vertical and horizontal nearest neighbors.
4489 * The spanning tree is created by performing a suitably randomized
4490 * depth-first traversal of the graph. The only adjustable parameter
4491 * is the randint0(3) below; it governs the relative density of
4492 * twists and turns in the labyrinth: smaller number, more twists.
4494 static void r_visit(int y1, int x1, int y2, int x2,
4495 int node, int dir, int *visited)
4497 int i, j, m, n, temp, x, y, adj[4];
4499 /* dimensions of vertex array */
4500 m = (x2 - x1) / 2 + 1;
4501 n = (y2 - y1) / 2 + 1;
4503 /* mark node visited and set it to a floor */
4505 x = 2 * (node % m) + x1;
4506 y = 2 * (node / m) + y1;
4507 place_floor_bold(y, x);
4509 /* setup order of adjacent node visits */
4512 /* pick a random ordering */
4513 for (i = 0; i < 4; i++)
4515 for (i = 0; i < 4; i++)
4526 /* pick a random ordering with dir first */
4528 for (i = 1; i < 4; i++)
4530 for (i = 1; i < 4; i++)
4532 j = 1 + randint0(3);
4539 for (i = 0; i < 4; i++)
4544 /* (0,+) - check for bottom boundary */
4545 if ((node / m < n - 1) && (visited[node + m] == 0))
4547 place_floor_bold(y + 1, x);
4548 r_visit(y1, x1, y2, x2, node + m, dir, visited);
4552 /* (0,-) - check for top boundary */
4553 if ((node / m > 0) && (visited[node - m] == 0))
4555 place_floor_bold(y - 1, x);
4556 r_visit(y1, x1, y2, x2, node - m, dir, visited);
4560 /* (+,0) - check for right boundary */
4561 if ((node % m < m - 1) && (visited[node + 1] == 0))
4563 place_floor_bold(y, x + 1);
4564 r_visit(y1, x1, y2, x2, node + 1, dir, visited);
4568 /* (-,0) - check for left boundary */
4569 if ((node % m > 0) && (visited[node - 1] == 0))
4571 place_floor_bold(y, x - 1);
4572 r_visit(y1, x1, y2, x2, node - 1, dir, visited);
4579 void build_maze_vault(int x0, int y0, int xsize, int ysize, bool is_vault)
4583 int m, n, num_vertices, *visited;
4588 if (cheat_room && is_vault) msg_print("Maze Vault");
4590 /* Choose lite or dark */
4591 light = ((dun_level <= randint1(25)) && is_vault && !(d_info[dungeon_type].flags1 & DF1_DARKNESS));
4593 /* Pick a random room size - randomized by calling routine */
4602 /* generate the room */
4603 for (y = y1 - 1; y <= y2 + 1; y++)
4605 for (x = x1 - 1; x <= x2 + 1; x++)
4607 c_ptr = &cave[y][x];
4608 c_ptr->info |= CAVE_ROOM;
4609 if (is_vault) c_ptr->info |= CAVE_ICKY;
4610 if ((x == x1 - 1) || (x == x2 + 1) || (y == y1 - 1) || (y == y2 + 1))
4612 place_outer_grid(c_ptr);
4616 place_extra_grid(c_ptr);
4620 place_inner_grid(c_ptr);
4622 if (light) c_ptr->info |= (CAVE_GLOW);
4626 /* dimensions of vertex array */
4629 num_vertices = m * n;
4631 /* initialize array of visited vertices */
4632 C_MAKE(visited, num_vertices, int);
4634 /* traverse the graph to create a spaning tree, pick a random root */
4635 r_visit(y1, x1, y2, x2, randint0(num_vertices), 0, visited);
4637 /* Fill with monsters and treasure, low difficulty */
4638 if (is_vault) fill_treasure(x1, x2, y1, y2, randint1(5));
4640 C_KILL(visited, num_vertices, int);
4644 /* Build a "mini" checkerboard vault
4646 * This is done by making a permanent wall maze and setting
4647 * the diagonal sqaures of the checker board to be granite.
4648 * The vault has two entrances on opposite sides to guarantee
4649 * a way to get in even if the vault abuts a side of the dungeon.
4651 static void build_mini_c_vault(int x0, int y0, int xsize, int ysize)
4654 int y1, x1, y2, x2, y, x, total;
4655 int m, n, num_vertices;
4658 if (cheat_room) msg_print("Mini Checker Board Vault");
4660 /* Pick a random room size */
4670 /* generate the room */
4671 for (x = x1 - 2; x <= x2 + 2; x++)
4673 if (!in_bounds(y1-2,x)) break;
4675 cave[y1-2][x].info |= (CAVE_ROOM | CAVE_ICKY);
4677 place_outer_noperm_bold(y1-2, x);
4680 for (x = x1 - 2; x <= x2 + 2; x++)
4682 if (!in_bounds(y2+2,x)) break;
4684 cave[y2+2][x].info |= (CAVE_ROOM | CAVE_ICKY);
4686 place_outer_noperm_bold(y2+2, x);
4689 for (y = y1 - 2; y <= y2 + 2; y++)
4691 if (!in_bounds(y,x1-2)) break;
4693 cave[y][x1-2].info |= (CAVE_ROOM | CAVE_ICKY);
4695 place_outer_noperm_bold(y, x1-2);
4698 for (y = y1 - 2; y <= y2 + 2; y++)
4700 if (!in_bounds(y,x2+2)) break;
4702 cave[y][x2+2].info |= (CAVE_ROOM | CAVE_ICKY);
4704 place_outer_noperm_bold(y, x2+2);
4707 for (y = y1 - 1; y <= y2 + 1; y++)
4709 for (x = x1 - 1; x <= x2 + 1; x++)
4711 cave_type *c_ptr = &cave[y][x];
4713 c_ptr->info |= (CAVE_ROOM | CAVE_ICKY);
4715 /* Permanent walls */
4716 c_ptr->feat = FEAT_PERM_INNER;
4717 c_ptr->info &= ~(CAVE_MASK);
4718 c_ptr->info |= CAVE_INNER;
4723 /* dimensions of vertex array */
4726 num_vertices = m * n;
4728 /* initialize array of visited vertices */
4729 C_MAKE(visited, num_vertices, int);
4731 /* traverse the graph to create a spannng tree, pick a random root */
4732 r_visit(y1, x1, y2, x2, randint0(num_vertices), 0, visited);
4734 /* Make it look like a checker board vault */
4735 for (x = x1; x <= x2; x++)
4737 for (y = y1; y <= y2; y++)
4739 total = x - x1 + y - y1;
4740 /* If total is odd- and is a floor then make a wall */
4741 if ((total % 2 == 1) && is_floor_bold(y, x))
4743 place_inner_bold(y, x);
4748 /* Make a couple of entrances */
4751 /* left and right */
4752 y = randint1(dy) + dy / 2;
4753 place_inner_bold(y1 + y, x1 - 1);
4754 place_inner_bold(y1 + y, x2 + 1);
4758 /* top and bottom */
4759 x = randint1(dx) + dx / 2;
4760 place_inner_bold(y1 - 1, x1 + x);
4761 place_inner_bold(y2 + 1, x1 + x);
4764 /* Fill with monsters and treasure, highest difficulty */
4765 fill_treasure(x1, x2, y1, y2, 10);
4767 C_KILL(visited, num_vertices, int);
4771 /* Build a town/ castle by using a recursive algorithm.
4772 * Basically divide each region in a probalistic way to create
4773 * smaller regions. When the regions get too small stop.
4775 * The power variable is a measure of how well defended a region is.
4776 * This alters the possible choices.
4778 static void build_recursive_room(int x1, int y1, int x2, int y2, int power)
4784 /* Temp variables */
4790 if ((power < 3) && (xsize > 12) && (ysize > 12))
4792 /* Need outside wall +keep */
4799 /* Make rooms + subdivide */
4800 if ((randint1(10) > 2) && (xsize < 8) && (ysize < 8))
4806 choice = randint1(2) + 1;
4811 /* Mostly subdivide */
4812 choice = randint1(3) + 1;
4816 /* Based on the choice made above, do something */
4824 /* top and bottom */
4825 for (x = x1; x <= x2; x++)
4827 place_outer_bold(y1, x);
4828 place_outer_bold(y2, x);
4831 /* left and right */
4832 for (y = y1 + 1; y < y2; y++)
4834 place_outer_bold(y, x1);
4835 place_outer_bold(y, x2);
4838 /* Make a couple of entrances */
4841 /* left and right */
4842 y = randint1(ysize) + y1;
4843 place_floor_bold(y, x1);
4844 place_floor_bold(y, x2);
4848 /* top and bottom */
4849 x = randint1(xsize) + x1;
4850 place_floor_bold(y1, x);
4851 place_floor_bold(y2, x);
4854 /* Select size of keep */
4855 t1 = randint1(ysize / 3) + y1;
4856 t2 = y2 - randint1(ysize / 3);
4857 t3 = randint1(xsize / 3) + x1;
4858 t4 = x2 - randint1(xsize / 3);
4860 /* Do outside areas */
4862 /* Above and below keep */
4863 build_recursive_room(x1 + 1, y1 + 1, x2 - 1, t1, power + 1);
4864 build_recursive_room(x1 + 1, t2, x2 - 1, y2, power + 1);
4866 /* Left and right of keep */
4867 build_recursive_room(x1 + 1, t1 + 1, t3, t2 - 1, power + 3);
4868 build_recursive_room(t4, t1 + 1, x2 - 1, t2 - 1, power + 3);
4870 /* Make the keep itself: */
4883 /* Try to build a room */
4884 if ((xsize < 3) || (ysize < 3))
4886 for (y = y1; y < y2; y++)
4888 for (x = x1; x < x2; x++)
4890 place_inner_bold(y, x);
4898 /* Make outside walls */
4899 /* top and bottom */
4900 for (x = x1 + 1; x <= x2 - 1; x++)
4902 place_inner_bold(y1 + 1, x);
4903 place_inner_bold(y2 - 1, x);
4906 /* left and right */
4907 for (y = y1 + 1; y <= y2 - 1; y++)
4909 place_inner_bold(y, x1 + 1);
4910 place_inner_bold(y, x2 - 1);
4914 y = randint1(ysize - 3) + y1 + 1;
4919 place_floor_bold(y, x1 + 1);
4924 place_floor_bold(y, x2 - 1);
4927 /* Build the room */
4928 build_recursive_room(x1 + 2, y1 + 2, x2 - 2, y2 - 2, power + 3);
4933 /* Try and divide vertically */
4937 for (y = y1; y < y2; y++)
4939 for (x = x1; x < x2; x++)
4941 place_inner_bold(y, x);
4947 t1 = randint1(xsize - 2) + x1 + 1;
4948 build_recursive_room(x1, y1, t1, y2, power - 2);
4949 build_recursive_room(t1 + 1, y1, x2, y2, power - 2);
4954 /* Try and divide horizontally */
4958 for (y = y1; y < y2; y++)
4960 for (x = x1; x < x2; x++)
4962 place_inner_bold(y, x);
4968 t1 = randint1(ysize - 2) + y1 + 1;
4969 build_recursive_room(x1, y1, x2, t1, power - 2);
4970 build_recursive_room(x1, t1 + 1, x2, y2, power - 2);
4977 /* Build a castle */
4979 /* Driver routine: clear the region and call the recursive
4982 *This makes a vault that looks like a castle/ city in the dungeon.
4984 static void build_castle_vault(int x0, int y0, int xsize, int ysize)
4990 /* Pick a random room size */
4999 if (cheat_room) msg_print("Castle Vault");
5001 /* generate the room */
5002 for (y = y1 - 1; y <= y2 + 1; y++)
5004 for (x = x1 - 1; x <= x2 + 1; x++)
5006 cave[y][x].info |= (CAVE_ROOM | CAVE_ICKY);
5007 /* Make everything a floor */
5008 place_floor_bold(y, x);
5012 /* Make the castle */
5013 build_recursive_room(x1, y1, x2, y2, randint1(5));
5015 /* Fill with monsters and treasure, low difficulty */
5016 fill_treasure(x1, x2, y1, y2, randint1(3));
5021 * Add outer wall to a floored region
5022 * Note: no range checking is done so must be inside dungeon
5023 * This routine also stomps on doors
5025 static void add_outer_wall(int x, int y, int light,
5026 int x1, int y1, int x2, int y2)
5030 if (!in_bounds(y, x)) return;
5032 /* hack- check to see if square has been visited before
5033 * if so, then exit (use room flag to do this) */
5034 if (cave[y][x].info & CAVE_ROOM) return;
5037 cave[y][x].info |= CAVE_ROOM;
5039 if (is_floor_bold(y, x))
5041 for (i = -1; i <= 1; i++)
5043 for (j = -1; j <= 1; j++)
5045 if ((x + i >= x1) && (x + i <= x2) &&
5046 (y + j >= y1) && (y + j <= y2))
5048 add_outer_wall(x + i, y + j, light, x1, y1, x2, y2);
5049 if (light) cave[y][x].info |= CAVE_GLOW;
5054 else if (is_extra_bold(y, x))
5056 /* Set bounding walls */
5057 place_outer_bold(y, x);
5058 if (light) cave[y][x].info |= CAVE_GLOW;
5060 else if (cave[y][x].feat == FEAT_PERM_OUTER)
5062 /* Set bounding walls */
5063 if (light) cave[y][x].info |= CAVE_GLOW;
5069 * Hacked distance formula - gives the 'wrong' answer.
5070 * Used to build crypts
5072 static int dist2(int x1, int y1, int x2, int y2,
5073 int h1, int h2, int h3, int h4)
5079 /* Basically this works by taking the normal pythagorean formula
5080 * and using an expansion to express this in a way without the
5081 * square root. This approximate formula is then perturbed to give
5082 * the distorted results. (I found this by making a mistake when I was
5083 * trying to fix the circular rooms.)
5086 /* h1-h4 are constants that describe the metric */
5087 if (dx >= 2 * dy) return (dx + (dy * h1) / h2);
5088 if (dy >= 2 * dx) return (dy + (dx * h1) / h2);
5089 return (((dx + dy) * 128) / 181 +
5090 (dx * dx / (dy * h3) + dy * dy / (dx * h3)) * h4);
5091 /* 128/181 is approx. 1/sqrt(2) */
5096 * Build target vault.
5097 * This is made by two concentric "crypts" with perpendicular
5098 * walls creating the cross-hairs.
5100 static void build_target_vault(int x0, int y0, int xsize, int ysize)
5104 /* Make a random metric */
5106 h1 = randint1(32) - 16;
5109 h4 = randint1(32) - 16;
5111 if (cheat_room) msg_print("Target Vault");
5113 /* work out outer radius */
5124 for (x = x0 - rad; x <= x0 + rad; x++)
5126 for (y = y0 - rad; y <= y0 + rad; y++)
5128 /* clear room flag */
5129 cave[y][x].info &= ~(CAVE_ROOM);
5131 /* Vault - so is "icky" */
5132 cave[y][x].info |= CAVE_ICKY;
5134 if (dist2(y0, x0, y, x, h1, h2, h3, h4) <= rad - 1)
5136 /* inside- so is floor */
5137 place_floor_bold(y, x);
5141 /* make granite outside so arena works */
5142 place_extra_bold(y, x);
5145 /* proper boundary for arena */
5146 if (((y + rad) == y0) || ((y - rad) == y0) ||
5147 ((x + rad) == x0) || ((x - rad) == x0))
5149 place_extra_bold(y, x);
5154 /* Find visible outer walls and set to be FEAT_OUTER */
5155 add_outer_wall(x0, y0, FALSE, x0 - rad - 1, y0 - rad - 1,
5156 x0 + rad + 1, y0 + rad + 1);
5158 /* Add inner wall */
5159 for (x = x0 - rad / 2; x <= x0 + rad / 2; x++)
5161 for (y = y0 - rad / 2; y <= y0 + rad / 2; y++)
5163 if (dist2(y0, x0, y, x, h1, h2, h3, h4) == rad / 2)
5165 /* Make an internal wall */
5166 place_inner_bold(y, x);
5171 /* Add perpendicular walls */
5172 for (x = x0 - rad; x <= x0 + rad; x++)
5174 place_inner_bold(y0, x);
5177 for (y = y0 - rad; y <= y0 + rad; y++)
5179 place_inner_bold(y, x0);
5182 /* Make inner vault */
5183 for (y = y0 - 1; y <= y0 + 1; y++)
5185 place_inner_bold(y, x0 - 1);
5186 place_inner_bold(y, x0 + 1);
5188 for (x = x0 - 1; x <= x0 + 1; x++)
5190 place_inner_bold(y0 - 1, x);
5191 place_inner_bold(y0 + 1, x);
5194 place_floor_bold(y0, x0);
5197 /* Add doors to vault */
5198 /* get two distances so can place doors relative to centre */
5199 x = (rad - 2) / 4 + 1;
5202 add_door(x0 + x, y0);
5203 add_door(x0 + y, y0);
5204 add_door(x0 - x, y0);
5205 add_door(x0 - y, y0);
5206 add_door(x0, y0 + x);
5207 add_door(x0, y0 + y);
5208 add_door(x0, y0 - x);
5209 add_door(x0, y0 - y);
5211 /* Fill with stuff - medium difficulty */
5212 fill_treasure(x0 - rad, x0 + rad, y0 - rad, y0 + rad, randint1(3) + 3);
5216 #ifdef ALLOW_CAVERNS_AND_LAKES
5218 * This routine uses a modified version of the lake code to make a
5219 * distribution of some terrain type over the vault. This type
5220 * depends on the dungeon depth.
5222 * Miniture rooms are then scattered across the vault.
5224 static void build_elemental_vault(int x0, int y0, int xsiz, int ysiz)
5229 int xsize, ysize, xhsize, yhsize, x, y, i;
5233 if (cheat_room) msg_print("Elemental Vault");
5235 /* round to make sizes even */
5243 /* Earth vault (Rubble) */
5244 type = LAKE_T_EARTH_VAULT;
5246 else if (dun_level < 50)
5248 /* Air vault (Trees) */
5249 type = LAKE_T_AIR_VAULT;
5251 else if (dun_level < 75)
5253 /* Water vault (shallow water) */
5254 type = LAKE_T_WATER_VAULT;
5258 /* Fire vault (shallow lava) */
5259 type = LAKE_T_FIRE_VAULT;
5264 /* testing values for these parameters: feel free to adjust */
5265 grd = 1 << (randint0(3));
5267 /* want average of about 16 */
5268 roug = randint1(8) * randint1(4);
5270 /* Make up size of various componants */
5274 /* Deep water/lava */
5275 c1 = randint0(c3 / 2) + randint0(c3 / 2) - 5;
5277 /* Shallow boundary */
5281 generate_hmap(y0, x0, xsize, ysize, grd, roug, c3);
5283 /* Convert to normal format+ clean up */
5284 done = generate_lake(y0, x0, xsize, ysize, c1, c2, c3, type);
5287 /* Set icky flag because is a vault */
5288 for (x = 0; x <= xsize; x++)
5290 for (y = 0; y <= ysize; y++)
5292 cave[y0 - yhsize + y][x0 - xhsize + x].info |= CAVE_ICKY;
5296 /* make a few rooms in the vault */
5297 for (i = 1; i <= (xsize * ysize) / 50; i++)
5299 build_small_room(x0 + randint0(xsize - 4) - xsize / 2 + 2,
5300 y0 + randint0(ysize - 4) - ysize / 2 + 2);
5303 /* Fill with monsters and treasure, low difficulty */
5304 fill_treasure(x0 - xhsize + 1, x0 - xhsize + xsize - 1,
5305 y0 - yhsize + 1, y0 - yhsize + ysize - 1, randint1(5));
5307 #endif /* ALLOW_CAVERNS_AND_LAKES */
5313 static bool build_type10(void)
5315 int y0, x0, xsize, ysize, vtype;
5318 /* big enough to look good, small enough to be fairly common. */
5319 xsize = randint1(22) + 22;
5320 ysize = randint1(11) + 11;
5322 /* Find and reserve some space in the dungeon. Get center of room. */
5323 if (!find_space(&y0, &x0, ysize + 1, xsize + 1)) return FALSE;
5325 /* Boost the rating- higher than lesser vaults and lower than greater vaults */
5328 /* (Sometimes) Cause a special feeling */
5329 if ((dun_level <= 50) ||
5330 (randint1((dun_level - 40) * (dun_level - 40) + 1) < 400))
5332 good_item_flag = TRUE;
5335 /* Select type of vault */
5336 #ifdef ALLOW_CAVERNS_AND_LAKES
5337 vtype = randint1(15);
5338 #else /* ALLOW_CAVERNS_AND_LAKES */
5339 vtype = randint1(7);
5340 #endif /* ALLOW_CAVERNS_AND_LAKES */
5344 /* Build an appropriate room */
5345 case 1: case 9: build_bubble_vault(x0, y0, xsize, ysize); break;
5346 case 2: case 10: build_room_vault(x0, y0, xsize, ysize); break;
5347 case 3: case 11: build_cave_vault(x0, y0, xsize, ysize); break;
5348 case 4: case 12: build_maze_vault(x0, y0, xsize, ysize, TRUE); break;
5349 case 5: case 13: build_mini_c_vault(x0, y0, xsize, ysize); break;
5350 case 6: case 14: build_castle_vault(x0, y0, xsize, ysize); break;
5351 case 7: case 15: build_target_vault(x0, y0, xsize, ysize); break;
5352 #ifdef ALLOW_CAVERNS_AND_LAKES
5353 case 8: build_elemental_vault(x0, y0, xsize, ysize); break;
5354 #endif /* ALLOW_CAVERNS_AND_LAKES */
5355 /* I know how to add a few more... give me some time. */
5358 default: return FALSE;
5366 * Build an vertical oval room.
5367 * For every grid in the possible square, check the distance.
5368 * If it's less than the radius, make it a room square.
5370 * When done fill from the inside to find the walls,
5372 static bool build_type11(void)
5374 int rad, x, y, x0, y0;
5377 /* Occasional light */
5378 if ((randint1(dun_level) <= 15) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS)) light = TRUE;
5382 /* Find and reserve some space in the dungeon. Get center of room. */
5383 if (!find_space(&y0, &x0, rad * 2 + 1, rad * 2 + 1)) return FALSE;
5385 /* Make circular floor */
5386 for (x = x0 - rad; x <= x0 + rad; x++)
5388 for (y = y0 - rad; y <= y0 + rad; y++)
5390 if (distance(y0, x0, y, x) <= rad - 1)
5392 /* inside- so is floor */
5393 place_floor_bold(y, x);
5395 else if (distance(y0, x0, y, x) <= rad + 1)
5397 /* make granite outside so arena works */
5398 place_extra_bold(y, x);
5403 /* Find visible outer walls and set to be FEAT_OUTER */
5404 add_outer_wall(x0, y0, light, x0 - rad, y0 - rad, x0 + rad, y0 + rad);
5412 * For every grid in the possible square, check the (fake) distance.
5413 * If it's less than the radius, make it a room square.
5415 * When done fill from the inside to find the walls,
5417 static bool build_type12(void)
5419 int rad, x, y, x0, y0;
5421 bool emptyflag = TRUE;
5423 /* Make a random metric */
5425 h1 = randint1(32) - 16;
5428 h4 = randint1(32) - 16;
5430 /* Occasional light */
5431 if ((randint1(dun_level) <= 5) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS)) light = TRUE;
5435 /* Find and reserve some space in the dungeon. Get center of room. */
5436 if (!find_space(&y0, &x0, rad * 2 + 3, rad * 2 + 3)) return FALSE;
5439 for (x = x0 - rad; x <= x0 + rad; x++)
5441 for (y = y0 - rad; y <= y0 + rad; y++)
5443 /* clear room flag */
5444 cave[y][x].info &= ~(CAVE_ROOM);
5446 if (dist2(y0, x0, y, x, h1, h2, h3, h4) <= rad - 1)
5448 /* inside - so is floor */
5449 place_floor_bold(y, x);
5451 else if (distance(y0, x0, y, x) < 3)
5453 place_floor_bold(y, x);
5457 /* make granite outside so arena works */
5458 place_extra_bold(y, x);
5461 /* proper boundary for arena */
5462 if (((y + rad) == y0) || ((y - rad) == y0) ||
5463 ((x + rad) == x0) || ((x - rad) == x0))
5465 place_extra_bold(y, x);
5470 /* Find visible outer walls and set to be FEAT_OUTER */
5471 add_outer_wall(x0, y0, light, x0 - rad - 1, y0 - rad - 1,
5472 x0 + rad + 1, y0 + rad + 1);
5474 /* Check to see if there is room for an inner vault */
5475 for (x = x0 - 2; x <= x0 + 2; x++)
5477 for (y = y0 - 2; y <= y0 + 2; y++)
5479 if (!is_floor_bold(y, x))
5481 /* Wall in the way */
5487 if (emptyflag && one_in_(2))
5489 /* Build the vault */
5490 build_small_room(x0, y0);
5492 /* Place a treasure in the vault */
5493 place_object(y0, x0, 0L);
5495 /* Let's guard the treasure well */
5496 vault_monsters(y0, x0, randint0(2) + 3);
5498 /* Traps naturally */
5499 vault_traps(y0, x0, 4, 4, randint0(3) + 2);
5507 * Helper function for "trapped monster pit"
5509 static bool vault_aux_trapped_pit(int r_idx)
5511 monster_race *r_ptr = &r_info[r_idx];
5513 /* Validate the monster */
5514 if (!vault_monster_okay(r_idx)) return (FALSE);
5516 /* No wall passing monster */
5517 if (r_ptr->flags2 & (RF2_PASS_WALL | RF2_KILL_WALL)) return (FALSE);
5525 * Type 12 -- Trapped monster pits
5527 * A trapped monster pit is a "big" room with a straight corridor in
5528 * which wall opening traps are placed, and with two "inner" rooms
5529 * containing a "collection" of monsters of a given type organized in
5532 * The trapped monster pit appears as shown below, where the actual
5533 * monsters in each location depend on the type of the pit
5535 * #########################
5537 * ####################### #
5538 * #####001123454321100### #
5539 * ###0012234567654322100# #
5540 * ####################### #
5542 * # #######################
5543 * # #0012234567654322100###
5544 * # ###001123454321100#####
5545 * # #######################
5547 * #########################
5549 * Note that the monsters in the pit are now chosen by using "get_mon_num()"
5550 * to request 16 "appropriate" monsters, sorting them by level, and using
5551 * the "even" entries in this sorted list for the contents of the pit.
5553 * Hack -- all of the "dragons" in a "dragon" pit must be the same "color",
5554 * which is handled by requiring a specific "breath" attack for all of the
5555 * dragons. This may include "multi-hued" breath. Note that "wyrms" may
5556 * be present in many of the dragon pits, if they have the proper breath.
5558 * Note the use of the "get_mon_num_prep()" function, and the special
5559 * "get_mon_num_hook()" restriction function, to prepare the "monster
5560 * allocation table" in such a way as to optimize the selection of
5561 * "appropriate" non-unique monsters for the pit.
5563 * Note that the "get_mon_num()" function may (rarely) fail, in which case
5564 * the pit will be empty, and will not effect the level rating.
5566 * Note that "monster pits" will never contain "unique" monsters.
5568 static bool build_type13(void)
5570 static int placing[][3] = {
5571 {-2, -9, 0}, {-2, -8, 0}, {-3, -7, 0}, {-3, -6, 0},
5572 {+2, -9, 0}, {+2, -8, 0}, {+3, -7, 0}, {+3, -6, 0},
5573 {-2, +9, 0}, {-2, +8, 0}, {-3, +7, 0}, {-3, +6, 0},
5574 {+2, +9, 0}, {+2, +8, 0}, {+3, +7, 0}, {+3, +6, 0},
5575 {-2, -7, 1}, {-3, -5, 1}, {-3, -4, 1},
5576 {+2, -7, 1}, {+3, -5, 1}, {+3, -4, 1},
5577 {-2, +7, 1}, {-3, +5, 1}, {-3, +4, 1},
5578 {+2, +7, 1}, {+3, +5, 1}, {+3, +4, 1},
5579 {-2, -6, 2}, {-2, -5, 2}, {-3, -3, 2},
5580 {+2, -6, 2}, {+2, -5, 2}, {+3, -3, 2},
5581 {-2, +6, 2}, {-2, +5, 2}, {-3, +3, 2},
5582 {+2, +6, 2}, {+2, +5, 2}, {+3, +3, 2},
5583 {-2, -4, 3}, {-3, -2, 3},
5584 {+2, -4, 3}, {+3, -2, 3},
5585 {-2, +4, 3}, {-3, +2, 3},
5586 {+2, +4, 3}, {+3, +2, 3},
5587 {-2, -3, 4}, {-3, -1, 4},
5588 {+2, -3, 4}, {+3, -1, 4},
5589 {-2, +3, 4}, {-3, +1, 4},
5590 {+2, +3, 4}, {+3, +1, 4},
5591 {-2, -2, 5}, {-3, 0, 5}, {-2, +2, 5},
5592 {+2, -2, 5}, {+3, 0, 5}, {+2, +2, 5},
5593 {-2, -1, 6}, {-2, +1, 6},
5594 {+2, -1, 6}, {+2, +1, 6},
5595 {-2, 0, 7}, {+2, 0, 7},
5599 int y, x, y1, x1, y2, x2, xval, yval;
5608 int cur_pit_type = pick_vault_type(pit_types, d_info[dungeon_type].pit);
5609 vault_aux_type *n_ptr;
5611 /* Only in Angband */
5612 if (dungeon_type != DUNGEON_ANGBAND) return FALSE;
5614 /* No type available */
5615 if (cur_pit_type < 0) return FALSE;
5617 n_ptr = &pit_types[cur_pit_type];
5619 /* Process a preparation function if necessary */
5620 if (n_ptr->prep_func) (*(n_ptr->prep_func))();
5622 /* Prepare allocation table */
5623 get_mon_num_prep(n_ptr->hook_func, vault_aux_trapped_pit);
5625 align.sub_align = SUB_ALIGN_NEUTRAL;
5627 /* Pick some monster types */
5628 for (i = 0; i < 16; i++)
5630 int r_idx = 0, attempts = 100;
5631 monster_race *r_ptr = NULL;
5635 /* Get a (hard) monster type */
5636 r_idx = get_mon_num(dun_level + 0);
5637 r_ptr = &r_info[r_idx];
5639 /* Decline incorrect alignment */
5640 if (monster_has_hostile_align(&align, 0, 0, r_ptr)) continue;
5642 /* Accept this monster */
5646 /* Notice failure */
5647 if (!r_idx || !attempts) return FALSE;
5649 /* Note the alignment */
5650 if (r_ptr->flags3 & RF3_EVIL) align.sub_align |= SUB_ALIGN_EVIL;
5651 if (r_ptr->flags3 & RF3_GOOD) align.sub_align |= SUB_ALIGN_GOOD;
5656 /* Find and reserve some space in the dungeon. Get center of room. */
5657 if (!find_space(&yval, &xval, 13, 25)) return FALSE;
5665 /* Fill with inner walls */
5666 for (y = y1 - 1; y <= y2 + 1; y++)
5668 for (x = x1 - 1; x <= x2 + 1; x++)
5670 c_ptr = &cave[y][x];
5671 place_inner_grid(c_ptr);
5672 c_ptr->info |= (CAVE_ROOM);
5676 /* Place the floor area 1 */
5677 for (x = x1 + 3; x <= x2 - 3; x++)
5679 c_ptr = &cave[yval-2][x];
5680 place_floor_grid(c_ptr);
5681 add_cave_info(yval-2, x, CAVE_ICKY);
5683 c_ptr = &cave[yval+2][x];
5684 place_floor_grid(c_ptr);
5685 add_cave_info(yval+2, x, CAVE_ICKY);
5688 /* Place the floor area 2 */
5689 for (x = x1 + 5; x <= x2 - 5; x++)
5691 c_ptr = &cave[yval-3][x];
5692 place_floor_grid(c_ptr);
5693 add_cave_info(yval-3, x, CAVE_ICKY);
5695 c_ptr = &cave[yval+3][x];
5696 place_floor_grid(c_ptr);
5697 add_cave_info(yval+3, x, CAVE_ICKY);
5701 for (x = x1; x <= x2; x++)
5703 c_ptr = &cave[yval][x];
5704 place_floor_grid(c_ptr);
5705 c_ptr = &cave[y1][x];
5706 place_floor_grid(c_ptr);
5707 c_ptr = &cave[y2][x];
5708 place_floor_grid(c_ptr);
5711 /* Place the outer walls */
5712 for (y = y1 - 1; y <= y2 + 1; y++)
5714 c_ptr = &cave[y][x1 - 1];
5715 place_outer_grid(c_ptr);
5716 c_ptr = &cave[y][x2 + 1];
5717 place_outer_grid(c_ptr);
5719 for (x = x1 - 1; x <= x2 + 1; x++)
5721 c_ptr = &cave[y1 - 1][x];
5722 place_outer_grid(c_ptr);
5723 c_ptr = &cave[y2 + 1][x];
5724 place_outer_grid(c_ptr);
5727 /* Random corridor */
5730 for (y = y1; y <= yval; y++)
5732 place_floor_bold(y, x2);
5733 place_solid_bold(y, x1-1);
5735 for (y = yval; y <= y2 + 1; y++)
5737 place_floor_bold(y, x1);
5738 place_solid_bold(y, x2+1);
5743 for (y = yval; y <= y2 + 1; y++)
5745 place_floor_bold(y, x1);
5746 place_solid_bold(y, x2+1);
5748 for (y = y1; y <= yval; y++)
5750 place_floor_bold(y, x2);
5751 place_solid_bold(y, x1-1);
5755 /* Place the wall open trap */
5756 cave[yval][xval].mimic = cave[yval][xval].feat;
5757 cave[yval][xval].feat = FEAT_TRAP_OPEN;
5759 /* Sort the entries */
5760 for (i = 0; i < 16 - 1; i++)
5762 /* Sort the entries */
5763 for (j = 0; j < 16 - 1; j++)
5768 int p1 = r_info[what[i1]].level;
5769 int p2 = r_info[what[i2]].level;
5775 what[i1] = what[i2];
5786 msg_format("%s%s¤Î櫥ԥåÈ", n_ptr->name, pit_subtype_string(cur_pit_type, FALSE));
5788 msg_format("Trapped monster pit (%s%s)", n_ptr->name, pit_subtype_string(cur_pit_type, FALSE));
5792 /* Select the entries */
5793 for (i = 0; i < 8; i++)
5795 /* Every other entry */
5796 what[i] = what[i * 2];
5801 msg_print(r_name + r_info[what[i]].name);
5805 /* Increase the level rating */
5808 /* (Sometimes) Cause a "special feeling" (for "Monster Pits") */
5809 if ((dun_level <= 40) && (randint1(dun_level * dun_level + 50) < 300))
5811 good_item_flag = TRUE;
5814 for (i = 0; placing[i][2] >= 0; i++)
5816 y = yval + placing[i][0];
5817 x = xval + placing[i][1];
5818 place_monster_aux(0, y, x, what[placing[i][2]], PM_NO_KAGE);
5826 * Type 14 -- trapped rooms
5828 * A special trap is placed at center of the room
5830 static bool build_type14(void)
5832 int y, x, y2, x2, yval, xval;
5833 int y1, x1, xsize, ysize;
5840 /* Pick a room size */
5846 xsize = x1 + x2 + 1;
5847 ysize = y1 + y2 + 1;
5849 /* Find and reserve some space in the dungeon. Get center of room. */
5850 if (!find_space(&yval, &xval, ysize + 2, xsize + 2)) return FALSE;
5852 /* Choose lite or dark */
5853 light = ((dun_level <= randint1(25)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS));
5856 /* Get corner values */
5857 y1 = yval - ysize / 2;
5858 x1 = xval - xsize / 2;
5859 y2 = yval + (ysize - 1) / 2;
5860 x2 = xval + (xsize - 1) / 2;
5863 /* Place a full floor under the room */
5864 for (y = y1 - 1; y <= y2 + 1; y++)
5866 for (x = x1 - 1; x <= x2 + 1; x++)
5868 c_ptr = &cave[y][x];
5869 place_floor_grid(c_ptr);
5870 c_ptr->info |= (CAVE_ROOM);
5871 if (light) c_ptr->info |= (CAVE_GLOW);
5875 /* Walls around the room */
5876 for (y = y1 - 1; y <= y2 + 1; y++)
5878 c_ptr = &cave[y][x1 - 1];
5879 place_outer_grid(c_ptr);
5880 c_ptr = &cave[y][x2 + 1];
5881 place_outer_grid(c_ptr);
5883 for (x = x1 - 1; x <= x2 + 1; x++)
5885 c_ptr = &cave[y1 - 1][x];
5886 place_outer_grid(c_ptr);
5887 c_ptr = &cave[y2 + 1][x];
5888 place_outer_grid(c_ptr);
5891 if (dun_level < 30 + randint1(30))
5892 trap = FEAT_TRAP_PIRANHA;
5894 trap = FEAT_TRAP_ARMAGEDDON;
5896 /* Place a special trap */
5897 c_ptr = &cave[rand_spread(yval, ysize/4)][rand_spread(xval, xsize/4)];
5898 c_ptr->mimic = c_ptr->feat;
5905 msg_format("%s¤ÎÉô²°", f_name + f_info[trap].name);
5907 msg_format("Room of %s", f_name + f_info[trap].name);
5916 * Attempt to build a room of the given type at the given block
5918 * Note that we restrict the number of "crowded" rooms to reduce
5919 * the chance of overflowing the monster list during level creation.
5921 bool room_build(int typ)
5926 /* Build an appropriate room */
5927 case ROOM_T_NORMAL: build_type1(); break;
5928 case ROOM_T_OVERLAP: build_type2(); break;
5929 case ROOM_T_CROSS: build_type3(); break;
5930 case ROOM_T_INNER_FEAT: build_type4(); break;
5931 case ROOM_T_NEST: build_type5(); break;
5932 case ROOM_T_PIT: build_type6(); break;
5933 case ROOM_T_LESSER_VAULT: build_type7(); break;
5934 case ROOM_T_GREATER_VAULT: build_type8(); break;
5935 case ROOM_T_FRACAVE: build_type9(); break;
5936 case ROOM_T_RANDOM_VAULT: build_type10(); break;
5937 case ROOM_T_OVAL: build_type11(); break;
5938 case ROOM_T_CRYPT: build_type12(); break;
5939 case ROOM_T_TRAP_PIT: build_type13(); break;
5940 case ROOM_T_TRAP: build_type14(); break;
5943 default: return FALSE;
5950 #define MOVE_PLIST(dst, src) (prob_list[dst] += prob_list[src], prob_list[src] = 0)
5953 * [from SAngband (originally from OAngband)]
5955 * Generate rooms in dungeon. Build bigger rooms at first.
5957 void generate_rooms(void)
5963 int prob_list[ROOM_T_MAX];
5964 int rooms_built = 0;
5965 int area_size = 100 * (cur_hgt*cur_wid) / (MAX_HGT*MAX_WID);
5966 int level_index = MIN(10, div_round(dun_level, 10));
5968 /* Number of each type of room on this level */
5969 s16b room_num[ROOM_T_MAX];
5971 /* Limit number of rooms */
5972 int dun_rooms = rand_range(DUN_ROOMS_MIN, DUN_ROOMS_MAX * area_size / 100);
5974 /* Assume normal cave */
5975 room_info_type *room_info_ptr = room_info_normal;
5979 * Initialize probability list.
5981 for (i = 0; i < ROOM_T_MAX; i++)
5983 /* No rooms allowed above their minimum depth. */
5984 if (dun_level < room_info_ptr[i].min_level)
5990 prob_list[i] = room_info_ptr[i].prob[level_index];
5995 * XXX -- Various dungeon types and options.
5998 /* Ironman sees only Greater Vaults */
5999 if (ironman_rooms && !((d_info[dungeon_type].flags1 & (DF1_BEGINNER | DF1_CHAMELEON))))
6001 for (i = 0; i < ROOM_T_MAX; i++)
6003 if (i == ROOM_T_GREATER_VAULT) prob_list[i] = 1;
6004 else prob_list[i] = 0;
6008 /* Forbidden vaults */
6009 else if (d_info[dungeon_type].flags1 & DF1_NO_VAULT)
6011 prob_list[ROOM_T_LESSER_VAULT] = 0;
6012 prob_list[ROOM_T_GREATER_VAULT] = 0;
6013 prob_list[ROOM_T_RANDOM_VAULT] = 0;
6017 /* NO_CAVE dungeon (Castle)*/
6018 if (d_info[dungeon_type].flags1 & DF1_NO_CAVE)
6020 MOVE_PLIST(ROOM_T_NORMAL, ROOM_T_FRACAVE);
6021 MOVE_PLIST(ROOM_T_INNER_FEAT, ROOM_T_CRYPT);
6022 MOVE_PLIST(ROOM_T_INNER_FEAT, ROOM_T_OVAL);
6025 /* CAVE dungeon (Orc cave etc.) */
6026 else if (d_info[dungeon_type].flags1 & DF1_CAVE)
6028 MOVE_PLIST(ROOM_T_FRACAVE, ROOM_T_NORMAL);
6031 /* No caves when a (random) cavern exists: they look bad */
6032 else if (dun->cavern || dun->empty_level)
6034 prob_list[ROOM_T_FRACAVE] = 0;
6039 * Initialize number of rooms,
6040 * And calcurate total probability.
6042 for (total_prob = 0, i = 0; i < ROOM_T_MAX; i++)
6045 total_prob += prob_list[i];
6049 * Prepare the number of rooms, of all types, we should build
6052 for (i = dun_rooms; i > 0; i--)
6055 int rand = randint0(total_prob);
6057 /* Get room_type randomly */
6058 for (room_type = 0; room_type < ROOM_T_MAX; room_type++)
6060 if (rand < prob_list[room_type]) break;
6061 else rand -= prob_list[room_type];
6065 if (room_type >= ROOM_T_MAX) room_type = ROOM_T_NORMAL;
6067 /* Increase the number of rooms of that type we should build. */
6068 room_num[room_type]++;
6074 case ROOM_T_LESSER_VAULT:
6075 case ROOM_T_TRAP_PIT:
6081 case ROOM_T_GREATER_VAULT:
6082 case ROOM_T_RANDOM_VAULT:
6091 * Build each type of room one by one until we cannot build any more.
6092 * [from SAngband (originally from OAngband)]
6096 /* Assume no remaining rooms */
6099 for (i = 0; i < ROOM_T_MAX; i++)
6101 /* What type of room are we building now? */
6102 int room_type = room_build_order[i];
6104 /* Go next if none available */
6105 if (!room_num[room_type]) continue;
6107 /* Use up one unit */
6108 room_num[room_type]--;
6110 /* Build the room. */
6111 if (room_build(room_type))
6113 /* Increase the room built count. */
6116 /* Mark as there was some remaining rooms */
6123 case ROOM_T_TRAP_PIT:
6125 /* Avoid too many monsters */
6128 room_num[ROOM_T_PIT] = 0;
6129 room_num[ROOM_T_NEST] = 0;
6130 room_num[ROOM_T_TRAP_PIT] = 0;
6135 /* Stop building this type on failure. */
6138 room_num[room_type] = 0;
6142 /* End loop if no room remain */