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)
2833 int xoffset, yoffset;
2836 /* Pick a lesser vault */
2837 for (dummy = 0; dummy < SAFE_MAX_ATTEMPTS; dummy++)
2839 /* Access a random vault record */
2840 v_ptr = &v_info[randint0(max_v_idx)];
2842 /* Accept the first lesser vault */
2843 if (v_ptr->typ == 7) break;
2846 /* No lesser vault found */
2847 if (dummy >= SAFE_MAX_ATTEMPTS)
2852 msg_print("·Ù¹ð¡ª¾®¤µ¤ÊÃϲ¼¼¼¤òÇÛÃ֤Ǥ¤Þ¤»¤ó¡ª");
2854 msg_print("Warning! Could not place lesser vault!");
2860 /* pick type of transformation (0-7) */
2861 transno = randint0(8);
2863 /* calculate offsets */
2867 /* Some huge vault cannot be ratated to fit in the dungeon */
2868 if (x+2 > cur_hgt-2)
2870 /* Forbid 90 or 270 degree ratation */
2874 coord_trans(&x, &y, 0, 0, transno);
2894 /* Find and reserve some space in the dungeon. Get center of room. */
2895 if (!find_space(&yval, &xval, abs(y), abs(x))) return FALSE;
2903 if (cheat_room) msg_format("¾®¤µ¤ÊÃϲ¼¼¼(%s)", v_name + v_ptr->name);
2905 if (cheat_room) msg_format("Lesser vault (%s)", v_name + v_ptr->name);
2908 /* Boost the rating */
2909 rating += v_ptr->rat;
2911 /* (Sometimes) Cause a special feeling */
2912 if ((dun_level <= 50) ||
2913 (randint1((dun_level - 40) * (dun_level - 40) + 50) < 400))
2915 good_item_flag = TRUE;
2918 /* Hack -- Build the vault */
2919 build_vault(yval, xval, v_ptr->hgt, v_ptr->wid,
2920 v_text + v_ptr->text, xoffset, yoffset, transno);
2927 * Type 8 -- greater vaults (see "v_info.txt")
2929 static bool build_type8(void)
2936 int xoffset, yoffset;
2938 /* Pick a greater vault */
2939 for (dummy = 0; dummy < SAFE_MAX_ATTEMPTS; dummy++)
2941 /* Access a random vault record */
2942 v_ptr = &v_info[randint0(max_v_idx)];
2944 /* Accept the first greater vault */
2945 if (v_ptr->typ == 8) break;
2948 /* No greater vault found */
2949 if (dummy >= SAFE_MAX_ATTEMPTS)
2954 msg_print("·Ù¹ð¡ªµðÂç¤ÊÃϲ¼¼¼¤òÇÛÃ֤Ǥ¤Þ¤»¤ó¡ª");
2956 msg_print("Warning! Could not place greater vault!");
2962 /* pick type of transformation (0-7) */
2963 transno = randint0(8);
2965 /* calculate offsets */
2969 /* Some huge vault cannot be ratated to fit in the dungeon */
2970 if (x+2 > cur_hgt-2)
2972 /* Forbid 90 or 270 degree ratation */
2976 coord_trans(&x, &y, 0, 0, transno);
2997 * Try to allocate space for room. If fails, exit
2999 * Hack -- Prepare a bit larger space (+2, +2) to
3000 * prevent generation of vaults with no-entrance.
3002 /* Find and reserve some space in the dungeon. Get center of room. */
3003 if (!find_space(&yval, &xval, abs(y) + 2, abs(x) + 2)) return FALSE;
3006 v_ptr = &v_info[76 + randint1(3)];
3011 if (cheat_room) msg_format("µðÂç¤ÊÃϲ¼¼¼(%s)", v_name + v_ptr->name);
3013 if (cheat_room) msg_format("Greater vault (%s)", v_name + v_ptr->name);
3016 /* Boost the rating */
3017 rating += v_ptr->rat;
3019 /* (Sometimes) Cause a special feeling */
3020 if ((dun_level <= 50) ||
3021 (randint1((dun_level - 40) * (dun_level - 40) + 50) < 400))
3023 good_item_flag = TRUE;
3026 /* Hack -- Build the vault */
3027 build_vault(yval, xval, v_ptr->hgt, v_ptr->wid,
3028 v_text + v_ptr->text, xoffset, yoffset, transno);
3034 * Structure to hold all "fill" data
3037 typedef struct fill_data_type fill_data_type;
3039 struct fill_data_type
3052 /* features to fill with */
3061 /* number of filled squares */
3065 static fill_data_type fill_data;
3068 /* Store routine for the fractal cave generator */
3069 /* this routine probably should be an inline function or a macro. */
3070 static void store_height(int x, int y, int val)
3072 /* if on boundary set val > cutoff so walls are not as square */
3073 if (((x == fill_data.xmin) || (y == fill_data.ymin) ||
3074 (x == fill_data.xmax) || (y == fill_data.ymax)) &&
3075 (val <= fill_data.c1)) val = fill_data.c1 + 1;
3077 /* store the value in height-map format */
3078 cave[y][x].feat = val;
3085 * Explanation of the plasma fractal algorithm:
3087 * A grid of points is created with the properties of a 'height-map'
3088 * This is done by making the corners of the grid have a random value.
3089 * The grid is then subdivided into one with twice the resolution.
3090 * The new points midway between two 'known' points can be calculated
3091 * by taking the average value of the 'known' ones and randomly adding
3092 * or subtracting an amount proportional to the distance between those
3093 * points. The final 'middle' points of the grid are then calculated
3094 * by averaging all four of the originally 'known' corner points. An
3095 * random amount is added or subtracted from this to get a value of the
3096 * height at that point. The scaling factor here is adjusted to the
3097 * slightly larger distance diagonally as compared to orthogonally.
3099 * This is then repeated recursively to fill an entire 'height-map'
3100 * A rectangular map is done the same way, except there are different
3101 * scaling factors along the x and y directions.
3103 * A hack to change the amount of correlation between points is done using
3104 * the grd variable. If the current step size is greater than grd then
3105 * the point will be random, otherwise it will be calculated by the
3106 * above algorithm. This makes a maximum distance at which two points on
3107 * the height map can affect each other.
3109 * How fractal caves are made:
3111 * When the map is complete, a cut-off value is used to create a cave.
3112 * Heights below this value are "floor", and heights above are "wall".
3113 * This also can be used to create lakes, by adding more height levels
3114 * representing shallow and deep water/ lava etc.
3116 * The grd variable affects the width of passages.
3117 * The roug variable affects the roughness of those passages
3119 * The tricky part is making sure the created cave is connected. This
3120 * is done by 'filling' from the inside and only keeping the 'filled'
3121 * floor. Walls bounding the 'filled' floor are also kept. Everything
3122 * else is converted to the normal granite FEAT_WALL_EXTRA.
3127 * Note that this uses the cave.feat array in a very hackish way
3128 * the values are first set to zero, and then each array location
3129 * is used as a "heightmap"
3130 * The heightmap then needs to be converted back into the "feat" format.
3132 * grd=level at which fractal turns on. smaller gives more mazelike caves
3133 * roug=roughness level. 16=normal. higher values make things more convoluted
3134 * small values are good for smooth walls.
3135 * size=length of the side of the square cave system.
3137 static void generate_hmap(int y0, int x0, int xsiz, int ysiz, int grd, int roug, int cutoff)
3139 int xhsize, yhsize, xsize, ysize, maxsize;
3142 * fixed point variables- these are stored as 256 x normal value
3143 * this gives 8 binary places of fractional part + 8 places of normal part
3146 u16b xstep, xhstep, ystep, yhstep;
3147 u16b xstep2, xhstep2, ystep2, yhstep2;
3148 u16b i, j, ii, jj, diagsize, xxsize, yysize;
3150 /* Cache for speed */
3151 u16b xm, xp, ym, yp;
3153 /* redefine size so can change the value if out of range */
3157 /* Paranoia about size of the system of caves */
3158 if (xsize > 254) xsize = 254;
3159 if (xsize < 4) xsize = 4;
3160 if (ysize > 254) ysize = 254;
3161 if (ysize < 4) ysize = 4;
3163 /* get offsets to middle of array */
3167 /* fix rounding problem */
3171 /* get limits of region */
3172 fill_data.xmin = x0 - xhsize;
3173 fill_data.ymin = y0 - yhsize;
3174 fill_data.xmax = x0 + xhsize;
3175 fill_data.ymax = y0 + yhsize;
3177 /* Store cutoff in global for quick access */
3178 fill_data.c1 = cutoff;
3181 * Scale factor for middle points:
3182 * About sqrt(2) * 256 - correct for a square lattice
3183 * approximately correct for everything else.
3187 /* maximum of xsize and ysize */
3188 maxsize = (xsize > ysize) ? xsize : ysize;
3190 /* Clear the section */
3191 for (i = 0; i <= xsize; i++)
3193 for (j = 0; j <= ysize; j++)
3195 /* 255 is a flag for "not done yet" */
3196 cave[(int)(fill_data.ymin + j)][(int)(fill_data.xmin + i)].feat = 255;
3197 /* Clear icky flag because may be redoing the cave */
3198 cave[(int)(fill_data.ymin + j)][(int)(fill_data.xmin + i)].info &= ~(CAVE_ICKY);
3202 /* Boundaries are walls */
3203 cave[fill_data.ymin][fill_data.xmin].feat = maxsize;
3204 cave[fill_data.ymax][fill_data.xmin].feat = maxsize;
3205 cave[fill_data.ymin][fill_data.xmax].feat = maxsize;
3206 cave[fill_data.ymax][fill_data.xmax].feat = maxsize;
3208 /* Set the middle square to be an open area. */
3209 cave[y0][x0].feat = 0;
3211 /* Initialize the step sizes */
3212 xstep = xhstep = xsize * 256;
3213 ystep = yhstep = ysize * 256;
3214 xxsize = xsize * 256;
3215 yysize = ysize * 256;
3218 * Fill in the rectangle with fractal height data -
3219 * like the 'plasma fractal' in fractint.
3221 while ((xhstep > 256) || (yhstep > 256))
3223 /* Halve the step sizes */
3229 /* cache well used values */
3230 xstep2 = xstep / 256;
3231 ystep2 = ystep / 256;
3233 xhstep2 = xhstep / 256;
3234 yhstep2 = yhstep / 256;
3236 /* middle top to bottom. */
3237 for (i = xhstep; i <= xxsize - xhstep; i += xstep)
3239 for (j = 0; j <= yysize; j += ystep)
3241 /* cache often used values */
3242 ii = i / 256 + fill_data.xmin;
3243 jj = j / 256 + fill_data.ymin;
3246 if (cave[jj][ii].feat == 255)
3250 /* If greater than 'grid' level then is random */
3251 store_height(ii, jj, randint1(maxsize));
3255 /* Average of left and right points +random bit */
3256 store_height(ii, jj,
3257 (cave[jj][fill_data.xmin + (i - xhstep) / 256].feat
3258 + cave[jj][fill_data.xmin + (i + xhstep) / 256].feat) / 2
3259 + (randint1(xstep2) - xhstep2) * roug / 16);
3266 /* middle left to right. */
3267 for (j = yhstep; j <= yysize - yhstep; j += ystep)
3269 for (i = 0; i <= xxsize; i += xstep)
3271 /* cache often used values */
3272 ii = i / 256 + fill_data.xmin;
3273 jj = j / 256 + fill_data.ymin;
3276 if (cave[jj][ii].feat == 255)
3280 /* If greater than 'grid' level then is random */
3281 store_height(ii, jj, randint1(maxsize));
3285 /* Average of up and down points +random bit */
3286 store_height(ii, jj,
3287 (cave[fill_data.ymin + (j - yhstep) / 256][ii].feat
3288 + cave[fill_data.ymin + (j + yhstep) / 256][ii].feat) / 2
3289 + (randint1(ystep2) - yhstep2) * roug / 16);
3296 for (i = xhstep; i <= xxsize - xhstep; i += xstep)
3298 for (j = yhstep; j <= yysize - yhstep; j += ystep)
3300 /* cache often used values */
3301 ii = i / 256 + fill_data.xmin;
3302 jj = j / 256 + fill_data.ymin;
3305 if (cave[jj][ii].feat == 255)
3309 /* If greater than 'grid' level then is random */
3310 store_height(ii, jj, randint1(maxsize));
3314 /* Cache reused values. */
3315 xm = fill_data.xmin + (i - xhstep) / 256;
3316 xp = fill_data.xmin + (i + xhstep) / 256;
3317 ym = fill_data.ymin + (j - yhstep) / 256;
3318 yp = fill_data.ymin + (j + yhstep) / 256;
3321 * Average over all four corners + scale by diagsize to
3322 * reduce the effect of the square grid on the shape of the fractal
3324 store_height(ii, jj,
3325 (cave[ym][xm].feat + cave[yp][xm].feat
3326 + cave[ym][xp].feat + cave[yp][xp].feat) / 4
3327 + (randint1(xstep2) - xhstep2) * (diagsize / 16) / 256 * roug);
3336 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)
3339 * function used to convert from height-map back to the
3340 * normal angband cave format
3342 if (cave[y][x].info & CAVE_ICKY)
3349 /* Show that have looked at this square */
3350 cave[y][x].info|= (CAVE_ICKY);
3352 /* Use cutoffs c1-c3 to allocate regions of floor /water/ lava etc. */
3353 if (cave[y][x].feat <= c1)
3355 /* 25% of the time use the other tile : it looks better this way */
3356 if (randint1(100) < 75)
3358 cave[y][x].feat = feat1;
3359 cave[y][x].info &= ~(CAVE_MASK);
3360 cave[y][x].info |= info1;
3365 cave[y][x].feat = feat2;
3366 cave[y][x].info &= ~(CAVE_MASK);
3367 cave[y][x].info |= info2;
3371 else if (cave[y][x].feat <= c2)
3373 /* 25% of the time use the other tile : it looks better this way */
3374 if (randint1(100) < 75)
3376 cave[y][x].feat = feat2;
3377 cave[y][x].info &= ~(CAVE_MASK);
3378 cave[y][x].info |= info2;
3383 cave[y][x].feat = feat1;
3384 cave[y][x].info &= ~(CAVE_MASK);
3385 cave[y][x].info |= info1;
3389 else if (cave[y][x].feat <= c3)
3391 cave[y][x].feat = feat3;
3392 cave[y][x].info |= info3;
3395 /* if greater than cutoff then is a wall */
3398 place_outer_bold(y, x);
3408 * Quick and nasty fill routine used to find the connected region
3409 * of floor in the middle of the cave
3411 static void cave_fill(byte y, byte x)
3420 /*** Start Grid ***/
3422 /* Enqueue that entry */
3427 /* Now process the queue */
3428 while (flow_head != flow_tail)
3430 /* Extract the next entry */
3431 ty = temp_y[flow_head];
3432 tx = temp_x[flow_head];
3434 /* Forget that entry */
3435 if (++flow_head == TEMP_MAX) flow_head = 0;
3437 /* Add the "children" */
3438 for (d = 0; d < 8; d++)
3440 int old_head = flow_tail;
3442 /* Child location */
3443 j = ty + ddy_ddd[d];
3444 i = tx + ddx_ddd[d];
3446 /* Paranoia Don't leave the cave */
3447 if (!in_bounds(j, i))
3449 /* affect boundary */
3450 cave[j][i].info |= CAVE_ICKY;
3454 /* If within bounds */
3455 else if ((i > fill_data.xmin) && (i < fill_data.xmax)
3456 && (j > fill_data.ymin) && (j < fill_data.ymax))
3458 /* If not a wall or floor done before */
3459 if (hack_isnt_wall(j, i,
3460 fill_data.c1, fill_data.c2, fill_data.c3,
3461 fill_data.feat1, fill_data.feat2, fill_data.feat3,
3462 fill_data.info1, fill_data.info2, fill_data.info3))
3464 /* Enqueue that entry */
3465 temp_y[flow_tail] = j;
3466 temp_x[flow_tail] = i;
3468 /* Advance the queue */
3469 if (++flow_tail == TEMP_MAX) flow_tail = 0;
3471 /* Hack -- Overflow by forgetting new entry */
3472 if (flow_tail == flow_head)
3474 flow_tail = old_head;
3478 /* keep tally of size of cave system */
3479 (fill_data.amount)++;
3485 /* affect boundary */
3486 cave[j][i].info |= CAVE_ICKY;
3493 static bool generate_fracave(int y0, int x0, int xsize, int ysize, int cutoff, bool light, bool room)
3495 int x, y, i, xhsize, yhsize;
3498 /* offsets to middle from corner */
3504 * select region connected to center of cave system
3505 * this gets rid of alot of isolated one-sqaures that
3506 * can make teleport traps instadeaths...
3510 fill_data.c1 = cutoff;
3514 /* features to fill with */
3515 fill_data.feat1 = floor_type[randint0(100)];
3516 fill_data.feat2 = floor_type[randint0(100)];
3517 fill_data.feat3 = floor_type[randint0(100)];
3519 fill_data.info1 = CAVE_FLOOR;
3520 fill_data.info2 = CAVE_FLOOR;
3521 fill_data.info3 = CAVE_FLOOR;
3523 /* number of filled squares */
3524 fill_data.amount = 0;
3526 cave_fill((byte)y0, (byte)x0);
3528 /* if tally too small, try again */
3529 if (fill_data.amount < 10)
3531 /* too small - clear area and try again later */
3532 for (x = 0; x <= xsize; ++x)
3534 for (y = 0; y <= ysize; ++y)
3536 place_extra_bold(y0 + y - yhsize, x0 + x - xhsize);
3537 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY | CAVE_ROOM);
3544 * Do boundarys-check to see if they are next to a filled region
3545 * If not then they are set to normal granite
3546 * If so then they are marked as room walls.
3548 for (i = 0; i <= xsize; ++i)
3551 if ((cave[0 + y0 - yhsize][i + x0 - xhsize].info & CAVE_ICKY) && (room))
3553 /* Next to a 'filled' region? - set to be room walls */
3554 place_outer_bold(y0 + 0 - yhsize, x0 + i - xhsize);
3555 if (light) cave[y0 + 0 - yhsize][x0 + i - xhsize].info |= (CAVE_GLOW);
3556 cave[y0 + 0 - yhsize][x0 + i - xhsize].info |= (CAVE_ROOM);
3557 place_outer_bold(y0 + 0 - yhsize, x0 + i - xhsize);
3561 /* set to be normal granite */
3562 place_extra_bold(y0 + 0 - yhsize, x0 + i - xhsize);
3565 /* bottom boundary */
3566 if ((cave[ysize + y0 - yhsize][i + x0 - xhsize].info & CAVE_ICKY) && (room))
3568 /* Next to a 'filled' region? - set to be room walls */
3569 place_outer_bold(y0 + ysize - yhsize, x0 + i - xhsize);
3570 if (light) cave[y0 + ysize - yhsize][x0 + i - xhsize].info|=(CAVE_GLOW);
3571 cave[y0 + ysize - yhsize][x0 + i - xhsize].info|=(CAVE_ROOM);
3572 place_outer_bold(y0 + ysize - yhsize, x0 + i - xhsize);
3576 /* set to be normal granite */
3577 place_extra_bold(y0 + ysize - yhsize, x0 + i - xhsize);
3580 /* clear the icky flag-don't need it any more */
3581 cave[y0 + 0 - yhsize][x0 + i - xhsize].info &= ~(CAVE_ICKY);
3582 cave[y0 + ysize - yhsize][x0 + i - xhsize].info &= ~(CAVE_ICKY);
3585 /* Do the left and right boundaries minus the corners (done above) */
3586 for (i = 1; i < ysize; ++i)
3589 if ((cave[i + y0 - yhsize][0 + x0 - xhsize].info & CAVE_ICKY) && room)
3592 place_outer_bold(y0 + i - yhsize, x0 + 0 - xhsize);
3593 if (light) cave[y0 + i - yhsize][x0 + 0 - xhsize].info |= (CAVE_GLOW);
3594 cave[y0 + i - yhsize][x0 + 0 - xhsize].info |= (CAVE_ROOM);
3595 place_outer_bold(y0 + i - yhsize, x0 + 0 - xhsize);
3600 place_extra_bold(y0 + i - yhsize, x0 + 0 - xhsize);
3602 /* right boundary */
3603 if ((cave[i + y0 - yhsize][xsize + x0 - xhsize].info & CAVE_ICKY) && room)
3606 place_outer_bold(y0 + i - yhsize, x0 + xsize - xhsize);
3607 if (light) cave[y0 + i - yhsize][x0 + xsize - xhsize].info |= (CAVE_GLOW);
3608 cave[y0 + i - yhsize][x0 + xsize - xhsize].info |= (CAVE_ROOM);
3609 place_outer_bold(y0 + i - yhsize, x0 + xsize - xhsize);
3614 place_extra_bold(y0 + i - yhsize, x0 + xsize - xhsize);
3617 /* clear icky flag -done with it */
3618 cave[y0 + i - yhsize][x0 + 0 - xhsize].info &= ~(CAVE_ICKY);
3619 cave[y0 + i - yhsize][x0 + xsize - xhsize].info &= ~(CAVE_ICKY);
3623 /* Do the rest: convert back to the normal format */
3624 for (x = 1; x < xsize; ++x)
3626 for (y = 1; y < ysize; ++y)
3628 if (is_floor_bold(y0 + y - yhsize, x0 + x - xhsize) &&
3629 (cave[y0 + y - yhsize][x0 + x - xhsize].info & CAVE_ICKY))
3631 /* Clear the icky flag in the filled region */
3632 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~CAVE_ICKY;
3634 /* Set appropriate flags */
3635 if (light) cave[y0 + y - yhsize][x0 + x - xhsize].info |= (CAVE_GLOW);
3636 if (room) cave[y0 + y - yhsize][x0 + x - xhsize].info |= (CAVE_ROOM);
3638 else if (is_outer_bold(y0 + y - yhsize, x0 + x - xhsize) &&
3639 (cave[y0 + y - yhsize][x0 + x - xhsize].info & CAVE_ICKY))
3642 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY);
3643 if (light) cave[y0 + y - yhsize][x0 + x - xhsize].info |= (CAVE_GLOW);
3646 cave[y0 + y - yhsize][x0 + x - xhsize].info |= (CAVE_ROOM);
3651 place_extra_bold(y0 + y - yhsize, x0 + x - xhsize);
3652 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ROOM);
3657 /* Clear the unconnected regions */
3658 place_extra_bold(y0 + y - yhsize, x0 + x - xhsize);
3659 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY | CAVE_ROOM);
3665 * XXX XXX XXX There is a slight problem when tunnels pierce the caves:
3666 * Extra doors appear inside the system. (Its not very noticeable though.)
3667 * This can be removed by "filling" from the outside in. This allows a separation
3668 * from FEAT_WALL_OUTER with FEAT_WALL_INNER. (Internal walls are F.W.OUTER instead.)
3669 * The extra effort for what seems to be only a minor thing (even non-existant if you
3670 * think of the caves not as normal rooms, but as holes in the dungeon), doesn't seem
3679 * Driver routine to create fractal cave system
3681 static bool build_type9(void)
3683 int grd, roug, cutoff, xsize, ysize, y0, x0;
3685 bool done, light, room;
3687 /* get size: note 'Evenness'*/
3688 xsize = randint1(22) * 2 + 6;
3689 ysize = randint1(15) * 2 + 6;
3691 /* Find and reserve some space in the dungeon. Get center of room. */
3692 if (!find_space(&y0, &x0, ysize + 1, xsize + 1)) return FALSE;
3694 light = done = FALSE;
3697 if ((dun_level <= randint1(25)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS)) light = TRUE;
3701 /* Note: size must be even or there are rounding problems
3702 * This causes the tunnels not to connect properly to the room */
3704 /* testing values for these parameters feel free to adjust */
3705 grd = 1 << (randint0(4));
3707 /* want average of about 16 */
3708 roug = randint1(8) * randint1(4);
3711 cutoff = randint1(xsize / 4) + randint1(ysize / 4) +
3712 randint1(xsize / 4) + randint1(ysize / 4);
3715 generate_hmap(y0, x0, xsize, ysize, grd, roug, cutoff);
3717 /* Convert to normal format + clean up */
3718 done = generate_fracave(y0, x0, xsize, ysize, cutoff, light, room);
3724 #ifdef ALLOW_CAVERNS_AND_LAKES
3726 * Builds a cave system in the center of the dungeon.
3728 void build_cavern(void)
3730 int grd, roug, cutoff, xsize, ysize, x0, y0;
3733 light = done = FALSE;
3734 if ((dun_level <= randint1(50)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS)) light = TRUE;
3736 /* Make a cave the size of the dungeon */
3737 xsize = cur_wid - 1;
3738 ysize = cur_hgt - 1;
3742 /* Paranoia: make size even */
3748 /* testing values for these parameters: feel free to adjust */
3749 grd = randint1(4) + 4;
3751 /* want average of about 16 */
3752 roug = randint1(8) * randint1(4);
3758 generate_hmap(y0 + 1, x0 + 1, xsize, ysize, grd, roug, cutoff);
3760 /* Convert to normal format+ clean up */
3761 done = generate_fracave(y0 + 1, x0 + 1, xsize, ysize, cutoff, light, FALSE);
3765 static bool generate_lake(int y0, int x0, int xsize, int ysize, int c1, int c2, int c3, int type)
3767 int x, y, i, xhsize, yhsize;
3768 int feat1, feat2, feat3;
3770 /* offsets to middle from corner */
3774 /* Get features based on type */
3777 case LAKE_T_LAVA: /* Lava */
3778 feat1 = FEAT_DEEP_LAVA;
3779 feat2 = FEAT_SHAL_LAVA;
3780 feat3 = floor_type[randint0(100)];
3782 case LAKE_T_WATER: /* Water */
3783 feat1 = FEAT_DEEP_WATER;
3784 feat2 = FEAT_SHAL_WATER;
3785 feat3 = floor_type[randint0(100)];
3787 case LAKE_T_CAVE: /* Collapsed cave */
3788 feat1 = floor_type[randint0(100)];
3789 feat2 = floor_type[randint0(100)];
3790 feat3 = FEAT_RUBBLE;
3792 case LAKE_T_EARTH_VAULT: /* Earth vault */
3793 feat1 = FEAT_RUBBLE;
3794 feat2 = floor_type[randint0(100)];
3795 feat3 = FEAT_RUBBLE;
3797 case LAKE_T_AIR_VAULT: /* Air vault */
3802 case LAKE_T_WATER_VAULT: /* Water vault */
3803 feat1 = FEAT_SHAL_WATER;
3804 feat2 = FEAT_DEEP_WATER;
3805 feat3 = FEAT_SHAL_WATER;
3807 case LAKE_T_FIRE_VAULT: /* Fire Vault */
3808 feat1 = FEAT_SHAL_LAVA;
3809 feat2 = FEAT_DEEP_LAVA;
3810 feat3 = FEAT_SHAL_LAVA;
3814 default: return FALSE;
3818 * select region connected to center of cave system
3819 * this gets rid of alot of isolated one-sqaures that
3820 * can make teleport traps instadeaths...
3828 /* features to fill with */
3829 fill_data.feat1 = feat1;
3830 fill_data.feat2 = feat2;
3831 fill_data.feat3 = feat3;
3833 fill_data.info1 = 0;
3834 fill_data.info2 = 0;
3835 fill_data.info3 = 0;
3837 /* number of filled squares */
3838 fill_data.amount = 0;
3840 /* select region connected to center of cave system
3841 * this gets rid of alot of isolated one-sqaures that
3842 * can make teleport traps instadeaths... */
3843 cave_fill((byte)y0, (byte)x0);
3845 /* if tally too small, try again */
3846 if (fill_data.amount < 10)
3848 /* too small -clear area and try again later */
3849 for (x = 0; x <= xsize; ++x)
3851 for (y = 0; y <= ysize; ++y)
3853 place_floor_bold(y0 + y - yhsize, x0 + x - xhsize);
3854 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY);
3860 /* Do boundarys- set to normal granite */
3861 for (i = 0; i <= xsize; ++i)
3863 place_extra_bold(y0 + 0 - yhsize, x0 + i - xhsize);
3864 place_extra_bold(y0 + ysize - yhsize, x0 + i - xhsize);
3866 /* clear the icky flag-don't need it any more */
3867 cave[y0 + 0 - yhsize][x0 + i - xhsize].info &= ~(CAVE_ICKY);
3868 cave[y0 + ysize - yhsize][x0 + i - xhsize].info &= ~(CAVE_ICKY);
3871 /* Do the left and right boundaries minus the corners (done above) */
3873 for (i = 1; i < ysize; ++i)
3875 place_extra_bold(y0 + i - yhsize, x0 + 0 - xhsize);
3876 place_extra_bold(y0 + i - yhsize, x0 + xsize - xhsize);
3878 /* clear icky flag -done with it */
3879 cave[y0 + i - yhsize][x0 + 0 - xhsize].info &= ~(CAVE_ICKY);
3880 cave[y0 + i - yhsize][x0 + xsize - xhsize].info &= ~(CAVE_ICKY);
3884 /* Do the rest: convert back to the normal format */
3885 for (x = 1; x < xsize; ++x)
3887 for (y = 1; y < ysize; ++y)
3889 /* Fill unconnected regions with granite */
3890 if ((!(cave[y0 + y - yhsize][x0 + x - xhsize].info & CAVE_ICKY)) ||
3891 is_outer_bold(y0 + y - yhsize, x0 + x - xhsize))
3892 place_extra_bold(y0 + y - yhsize, x0 + x - xhsize);
3894 /* turn off icky flag (no longer needed.) */
3895 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY | CAVE_ROOM);
3897 /* Light lava and trees */
3898 if ((cave[y0 + y - yhsize][x0 + x - xhsize].feat == FEAT_DEEP_LAVA) ||
3899 (cave[y0 + y - yhsize][x0 + x - xhsize].feat == FEAT_SHAL_LAVA))
3901 if (!(d_info[dungeon_type].flags1 & DF1_DARKNESS)) cave[y0 + y - yhsize][x0 + x - xhsize].info |= CAVE_GLOW;
3911 * makes a lake/collapsed cave system in the center of the dungeon
3913 void build_lake(int type)
3915 int grd, roug, xsize, ysize, x0, y0;
3919 /* paranoia - exit if lake type out of range. */
3920 if ((type < LAKE_T_LAVA) || (type > LAKE_T_FIRE_VAULT))
3922 msg_format("Invalid lake type (%d)", type);
3926 /* Make the size of the dungeon */
3927 xsize = cur_wid - 1;
3928 ysize = cur_hgt - 1;
3932 /* Paranoia: make size even */
3938 /* testing values for these parameters: feel free to adjust */
3939 grd = randint1(3) + 4;
3941 /* want average of about 16 */
3942 roug = randint1(8) * randint1(4);
3944 /* Make up size of various componants */
3948 /* Deep water/lava */
3949 c1 = randint0(c3 / 2) + randint0(c3 / 2) - 5;
3951 /* Shallow boundary */
3955 generate_hmap(y0 + 1, x0 + 1, xsize, ysize, grd, roug, c3);
3957 /* Convert to normal format+ clean up */
3958 done = generate_lake(y0 + 1, x0 + 1, xsize, ysize, c1, c2, c3, type);
3961 #endif /* ALLOW_CAVERNS_AND_LAKES */
3965 * Routine used by the random vault creators to add a door to a location
3966 * Note that range checking has to be done in the calling routine.
3968 * The doors must be INSIDE the allocated region.
3970 static void add_door(int x, int y)
3972 /* Need to have a wall in the center square */
3973 if (!is_outer_bold(y, x)) return;
3980 * where x=don't care
3984 if (is_floor_bold(y-1,x) && is_floor_bold(y+1,x) &&
3985 (is_outer_bold(y, x - 1) && is_outer_bold(y, x + 1)))
3988 place_secret_door(y, x);
3990 /* set boundarys so don't get wide doors */
3991 place_solid_bold(y, x - 1);
3992 place_solid_bold(y, x + 1);
4001 * where x = don't care
4004 if (is_outer_bold(y - 1, x) && is_outer_bold(y + 1, x) &&
4005 is_floor_bold(y,x-1) && is_floor_bold(y,x+1))
4008 place_secret_door(y, x);
4010 /* set boundarys so don't get wide doors */
4011 place_solid_bold(y - 1, x);
4012 place_solid_bold(y + 1, x);
4018 * Routine that fills the empty areas of a room with treasure and monsters.
4020 static void fill_treasure(int x1, int x2, int y1, int y2, int difficulty)
4022 int x, y, cx, cy, size;
4025 /* center of room:*/
4029 /* Rough measure of size of vault= sum of lengths of sides */
4030 size = abs(x2 - x1) + abs(y2 - y1);
4032 for (x = x1; x <= x2; x++)
4034 for (y = y1; y <= y2; y++)
4036 /* Thing added based on distance to center of vault
4037 * Difficulty is 1-easy to 10-hard */
4038 value = ((((s32b)(distance(cx, cy, x, y))) * 100) / size) + randint1(10) - difficulty;
4040 /* hack- empty square part of the time */
4041 if ((randint1(100) - difficulty * 3) > 50) value = 20;
4043 /* if floor, shallow water and lava */
4044 if (is_floor_bold(y, x) ||
4045 (cave[y][x].feat == FEAT_SHAL_WATER) ||
4046 (cave[y][x].feat == FEAT_SHAL_LAVA))
4048 /* The smaller 'value' is, the better the stuff */
4051 /* Meanest monster + treasure */
4052 monster_level = base_level + 40;
4053 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
4054 monster_level = base_level;
4055 object_level = base_level + 20;
4056 place_object(y, x, AM_GOOD);
4057 object_level = base_level;
4061 /* Mean monster +treasure */
4062 monster_level = base_level + 20;
4063 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
4064 monster_level = base_level;
4065 object_level = base_level + 10;
4066 place_object(y, x, AM_GOOD);
4067 object_level = base_level;
4069 else if (value < 10)
4072 monster_level = base_level + 9;
4073 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
4074 monster_level = base_level;
4076 else if (value < 17)
4078 /* Intentional Blank space */
4081 * (Want some of the vault to be empty
4082 * so have room for group monsters.
4083 * This is used in the hack above to lower
4084 * the density of stuff in the vault.)
4087 else if (value < 23)
4089 /* Object or trap */
4090 if (randint0(100) < 25)
4092 place_object(y, x, 0L);
4099 else if (value < 30)
4101 /* Monster and trap */
4102 monster_level = base_level + 5;
4103 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
4104 monster_level = base_level;
4107 else if (value < 40)
4109 /* Monster or object */
4110 if (randint0(100) < 50)
4112 monster_level = base_level + 3;
4113 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
4114 monster_level = base_level;
4116 if (randint0(100) < 50)
4118 object_level = base_level + 7;
4119 place_object(y, x, 0L);
4120 object_level = base_level;
4123 else if (value < 50)
4132 /* 20% monster, 40% trap, 20% object, 20% blank space */
4133 if (randint0(100) < 20)
4135 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
4137 else if (randint0(100) < 50)
4141 else if (randint0(100) < 50)
4143 place_object(y, x, 0L);
4154 * This function creates a random vault that looks like a collection of bubbles.
4155 * It works by getting a set of coordinates that represent the center of each
4156 * bubble. The entire room is made by seeing which bubble center is closest. If
4157 * two centers are equidistant then the square is a wall, otherwise it is a floor.
4158 * The only exception is for squares really near a center, these are always floor.
4159 * (It looks better than without this check.)
4161 * Note: If two centers are on the same point then this algorithm will create a
4162 * blank bubble filled with walls. - This is prevented from happening.
4164 static void build_bubble_vault(int x0, int y0, int xsize, int ysize)
4166 #define BUBBLENUM 10 /* number of bubbles */
4168 /* array of center points of bubbles */
4169 coord center[BUBBLENUM];
4172 u16b min1, min2, temp;
4175 /* Offset from center to top left hand corner */
4176 int xhsize = xsize / 2;
4177 int yhsize = ysize / 2;
4180 if (cheat_room) msg_print("Bubble Vault");
4182 /* Allocate center of bubbles */
4183 center[0].x = randint1(xsize - 3) + 1;
4184 center[0].y = randint1(ysize - 3) + 1;
4186 for (i = 1; i < BUBBLENUM; i++)
4190 /* get center and check to see if it is unique */
4195 x = randint1(xsize - 3) + 1;
4196 y = randint1(ysize - 3) + 1;
4198 for (j = 0; j < i; j++)
4200 /* rough test to see if there is an overlap */
4201 if ((x == center[j].x) && (y == center[j].y)) done = FALSE;
4210 /* Top and bottom boundaries */
4211 for (i = 0; i < xsize; i++)
4213 int x = x0 - xhsize + i;
4215 place_outer_noperm_bold(y0 - yhsize + 0, x);
4216 cave[y0 - yhsize + 0][x].info |= (CAVE_ROOM | CAVE_ICKY);
4217 place_outer_noperm_bold(y0 - yhsize + ysize - 1, x);
4218 cave[y0 - yhsize + ysize - 1][x].info |= (CAVE_ROOM | CAVE_ICKY);
4221 /* Left and right boundaries */
4222 for (i = 1; i < ysize - 1; i++)
4224 int y = y0 - yhsize + i;
4226 place_outer_noperm_bold(y, x0 - xhsize + 0);
4227 cave[y][x0 - xhsize + 0].info |= (CAVE_ROOM | CAVE_ICKY);
4228 place_outer_noperm_bold(y, x0 - xhsize + xsize - 1);
4229 cave[y][x0 - xhsize + xsize - 1].info |= (CAVE_ROOM | CAVE_ICKY);
4232 /* Fill in middle with bubbles */
4233 for (x = 1; x < xsize - 1; x++)
4235 for (y = 1; y < ysize - 1; y++)
4237 /* Get distances to two closest centers */
4240 min1 = distance(x, y, center[0].x, center[0].y);
4241 min2 = distance(x, y, center[1].x, center[1].y);
4245 /* swap if in wrong order */
4252 for (i = 2; i < BUBBLENUM; i++)
4254 temp = distance(x, y, center[i].x, center[i].y);
4262 else if (temp < min2)
4264 /* second smallest */
4268 if (((min2 - min1) <= 2) && (!(min1 < 3)))
4270 /* Boundary at midpoint+ not at inner region of bubble */
4271 place_outer_noperm_bold(y0 - yhsize + y, x0 - xhsize + x);
4275 /* middle of a bubble */
4276 place_floor_bold(y0 - yhsize + y, x0 - xhsize + x);
4279 /* clean up rest of flags */
4280 cave[y0 - yhsize + y][x0 - xhsize + x].info |= (CAVE_ROOM | CAVE_ICKY);
4284 /* Try to add some random doors */
4285 for (i = 0; i < 500; i++)
4287 x = randint1(xsize - 3) - xhsize + x0 + 1;
4288 y = randint1(ysize - 3) - yhsize + y0 + 1;
4292 /* Fill with monsters and treasure, low difficulty */
4293 fill_treasure(x0 - xhsize + 1, x0 - xhsize + xsize - 2, y0 - yhsize + 1, y0 - yhsize + ysize - 2, randint1(5));
4298 * Overlay a rectangular room given its bounds
4299 * This routine is used by build_room_vault
4300 * The area inside the walls is not touched:
4301 * only granite is removed- normal walls stay
4303 static void build_room(int x1, int x2, int y1, int y2)
4305 int x, y, i, xsize, ysize, temp;
4307 /* Check if rectangle has no width */
4308 if ((x1 == x2) || (y1 == y2)) return;
4313 /* Swap boundaries if in wrong order */
4321 /* Swap boundaries if in wrong order */
4327 /* get total widths */
4332 /* Top and bottom boundaries */
4333 for (i = 0; i <= xsize; i++)
4335 place_outer_noperm_bold(y1, x1 + i);
4336 cave[y1][x1 + i].info |= (CAVE_ROOM | CAVE_ICKY);
4337 place_outer_noperm_bold(y2, x1 + i);
4338 cave[y2][x1 + i].info |= (CAVE_ROOM | CAVE_ICKY);
4341 /* Left and right boundaries */
4342 for (i = 1; i < ysize; i++)
4344 place_outer_noperm_bold(y1 + i, x1);
4345 cave[y1 + i][x1].info|=(CAVE_ROOM | CAVE_ICKY);
4346 place_outer_noperm_bold(y1 + i, x2);
4347 cave[y1 + i][x2].info|=(CAVE_ROOM | CAVE_ICKY);
4351 for (x = 1; x < xsize; x++)
4353 for (y = 1; y < ysize; y++)
4355 if (is_extra_bold(y1+y, x1+x))
4357 /* clear the untouched region */
4358 place_floor_bold(y1 + y, x1 + x);
4359 cave[y1 + y][x1 + x].info |= (CAVE_ROOM | CAVE_ICKY);
4363 /* make it a room- but don't touch */
4364 cave[y1 + y][x1 + x].info |= (CAVE_ROOM | CAVE_ICKY);
4371 /* Create a random vault that looks like a collection of overlapping rooms */
4373 static void build_room_vault(int x0, int y0, int xsize, int ysize)
4375 int i, x1, x2, y1, y2, xhsize, yhsize;
4377 /* get offset from center */
4381 if (cheat_room) msg_print("Room Vault");
4383 /* fill area so don't get problems with arena levels */
4384 for (x1 = 0; x1 < xsize; x1++)
4386 int x = x0 - xhsize + x1;
4388 for (y1 = 0; y1 < ysize; y1++)
4390 int y = y0 - yhsize + y1;
4392 place_extra_bold(y, x);
4393 cave[y][x].info &= (~CAVE_ICKY);
4397 /* add ten random rooms */
4398 for (i = 0; i < 10; i++)
4400 x1 = randint1(xhsize) * 2 + x0 - xhsize;
4401 x2 = randint1(xhsize) * 2 + x0 - xhsize;
4402 y1 = randint1(yhsize) * 2 + y0 - yhsize;
4403 y2 = randint1(yhsize) * 2 + y0 - yhsize;
4404 build_room(x1, x2, y1, y2);
4407 /* Add some random doors */
4408 for (i = 0; i < 500; i++)
4410 x1 = randint1(xsize - 3) - xhsize + x0 + 1;
4411 y1 = randint1(ysize - 3) - yhsize + y0 + 1;
4415 /* Fill with monsters and treasure, high difficulty */
4416 fill_treasure(x0 - xhsize + 1, x0 - xhsize + xsize - 2, y0 - yhsize + 1, y0 - yhsize + ysize - 2, randint1(5) + 5);
4420 /* Create a random vault out of a fractal cave */
4421 static void build_cave_vault(int x0, int y0, int xsiz, int ysiz)
4423 int grd, roug, cutoff, xhsize, yhsize, xsize, ysize, x, y;
4424 bool done, light, room;
4426 /* round to make sizes even */
4432 if (cheat_room) msg_print("Cave Vault");
4434 light = done = FALSE;
4439 /* testing values for these parameters feel free to adjust */
4440 grd = 1 << randint0(4);
4442 /* want average of about 16 */
4443 roug = randint1(8) * randint1(4);
4446 cutoff = randint1(xsize / 4) + randint1(ysize / 4) +
4447 randint1(xsize / 4) + randint1(ysize / 4);
4450 generate_hmap(y0, x0, xsize, ysize, grd, roug, cutoff);
4452 /* Convert to normal format+ clean up */
4453 done = generate_fracave(y0, x0, xsize, ysize, cutoff, light, room);
4456 /* Set icky flag because is a vault */
4457 for (x = 0; x <= xsize; x++)
4459 for (y = 0; y <= ysize; y++)
4461 cave[y0 - yhsize + y][x0 - xhsize + x].info |= CAVE_ICKY;
4465 /* Fill with monsters and treasure, low difficulty */
4466 fill_treasure(x0 - xhsize + 1, x0 - xhsize + xsize - 1, y0 - yhsize + 1, y0 - yhsize + ysize - 1, randint1(5));
4470 * maze vault -- rectangular labyrinthine rooms
4472 * maze vault uses two routines:
4473 * r_visit - a recursive routine that builds the labyrinth
4474 * build_maze_vault - a driver routine that calls r_visit and adds
4475 * monsters, traps and treasure
4477 * The labyrinth is built by creating a spanning tree of a graph.
4478 * The graph vertices are at
4479 * (x, y) = (2j + x1, 2k + y1) j = 0,...,m-1 k = 0,...,n-1
4480 * and the edges are the vertical and horizontal nearest neighbors.
4482 * The spanning tree is created by performing a suitably randomized
4483 * depth-first traversal of the graph. The only adjustable parameter
4484 * is the randint0(3) below; it governs the relative density of
4485 * twists and turns in the labyrinth: smaller number, more twists.
4487 static void r_visit(int y1, int x1, int y2, int x2,
4488 int node, int dir, int *visited)
4490 int i, j, m, n, temp, x, y, adj[4];
4492 /* dimensions of vertex array */
4493 m = (x2 - x1) / 2 + 1;
4494 n = (y2 - y1) / 2 + 1;
4496 /* mark node visited and set it to a floor */
4498 x = 2 * (node % m) + x1;
4499 y = 2 * (node / m) + y1;
4500 place_floor_bold(y, x);
4502 /* setup order of adjacent node visits */
4505 /* pick a random ordering */
4506 for (i = 0; i < 4; i++)
4508 for (i = 0; i < 4; i++)
4519 /* pick a random ordering with dir first */
4521 for (i = 1; i < 4; i++)
4523 for (i = 1; i < 4; i++)
4525 j = 1 + randint0(3);
4532 for (i = 0; i < 4; i++)
4537 /* (0,+) - check for bottom boundary */
4538 if ((node / m < n - 1) && (visited[node + m] == 0))
4540 place_floor_bold(y + 1, x);
4541 r_visit(y1, x1, y2, x2, node + m, dir, visited);
4545 /* (0,-) - check for top boundary */
4546 if ((node / m > 0) && (visited[node - m] == 0))
4548 place_floor_bold(y - 1, x);
4549 r_visit(y1, x1, y2, x2, node - m, dir, visited);
4553 /* (+,0) - check for right boundary */
4554 if ((node % m < m - 1) && (visited[node + 1] == 0))
4556 place_floor_bold(y, x + 1);
4557 r_visit(y1, x1, y2, x2, node + 1, dir, visited);
4561 /* (-,0) - check for left boundary */
4562 if ((node % m > 0) && (visited[node - 1] == 0))
4564 place_floor_bold(y, x - 1);
4565 r_visit(y1, x1, y2, x2, node - 1, dir, visited);
4572 void build_maze_vault(int x0, int y0, int xsize, int ysize, bool is_vault)
4576 int m, n, num_vertices, *visited;
4581 if (cheat_room && is_vault) msg_print("Maze Vault");
4583 /* Choose lite or dark */
4584 light = ((dun_level <= randint1(25)) && is_vault && !(d_info[dungeon_type].flags1 & DF1_DARKNESS));
4586 /* Pick a random room size - randomized by calling routine */
4595 /* generate the room */
4596 for (y = y1 - 1; y <= y2 + 1; y++)
4598 for (x = x1 - 1; x <= x2 + 1; x++)
4600 c_ptr = &cave[y][x];
4601 c_ptr->info |= CAVE_ROOM;
4602 if (is_vault) c_ptr->info |= CAVE_ICKY;
4603 if ((x == x1 - 1) || (x == x2 + 1) || (y == y1 - 1) || (y == y2 + 1))
4605 place_outer_grid(c_ptr);
4609 place_extra_grid(c_ptr);
4613 place_inner_grid(c_ptr);
4615 if (light) c_ptr->info |= (CAVE_GLOW);
4619 /* dimensions of vertex array */
4622 num_vertices = m * n;
4624 /* initialize array of visited vertices */
4625 C_MAKE(visited, num_vertices, int);
4627 /* traverse the graph to create a spaning tree, pick a random root */
4628 r_visit(y1, x1, y2, x2, randint0(num_vertices), 0, visited);
4630 /* Fill with monsters and treasure, low difficulty */
4631 if (is_vault) fill_treasure(x1, x2, y1, y2, randint1(5));
4633 C_KILL(visited, num_vertices, int);
4637 /* Build a "mini" checkerboard vault
4639 * This is done by making a permanent wall maze and setting
4640 * the diagonal sqaures of the checker board to be granite.
4641 * The vault has two entrances on opposite sides to guarantee
4642 * a way to get in even if the vault abuts a side of the dungeon.
4644 static void build_mini_c_vault(int x0, int y0, int xsize, int ysize)
4647 int y1, x1, y2, x2, y, x, total;
4648 int m, n, num_vertices;
4651 if (cheat_room) msg_print("Mini Checker Board Vault");
4653 /* Pick a random room size */
4663 /* generate the room */
4664 for (x = x1 - 2; x <= x2 + 2; x++)
4666 if (!in_bounds(y1-2,x)) break;
4668 cave[y1-2][x].info |= (CAVE_ROOM | CAVE_ICKY);
4670 place_outer_noperm_bold(y1-2, x);
4673 for (x = x1 - 2; x <= x2 + 2; x++)
4675 if (!in_bounds(y2+2,x)) break;
4677 cave[y2+2][x].info |= (CAVE_ROOM | CAVE_ICKY);
4679 place_outer_noperm_bold(y2+2, x);
4682 for (y = y1 - 2; y <= y2 + 2; y++)
4684 if (!in_bounds(y,x1-2)) break;
4686 cave[y][x1-2].info |= (CAVE_ROOM | CAVE_ICKY);
4688 place_outer_noperm_bold(y, x1-2);
4691 for (y = y1 - 2; y <= y2 + 2; y++)
4693 if (!in_bounds(y,x2+2)) break;
4695 cave[y][x2+2].info |= (CAVE_ROOM | CAVE_ICKY);
4697 place_outer_noperm_bold(y, x2+2);
4700 for (y = y1 - 1; y <= y2 + 1; y++)
4702 for (x = x1 - 1; x <= x2 + 1; x++)
4704 cave_type *c_ptr = &cave[y][x];
4706 c_ptr->info |= (CAVE_ROOM | CAVE_ICKY);
4708 /* Permanent walls */
4709 c_ptr->feat = FEAT_PERM_INNER;
4710 c_ptr->info &= ~(CAVE_MASK);
4711 c_ptr->info |= CAVE_INNER;
4716 /* dimensions of vertex array */
4719 num_vertices = m * n;
4721 /* initialize array of visited vertices */
4722 C_MAKE(visited, num_vertices, int);
4724 /* traverse the graph to create a spannng tree, pick a random root */
4725 r_visit(y1, x1, y2, x2, randint0(num_vertices), 0, visited);
4727 /* Make it look like a checker board vault */
4728 for (x = x1; x <= x2; x++)
4730 for (y = y1; y <= y2; y++)
4732 total = x - x1 + y - y1;
4733 /* If total is odd- and is a floor then make a wall */
4734 if ((total % 2 == 1) && is_floor_bold(y, x))
4736 place_inner_bold(y, x);
4741 /* Make a couple of entrances */
4744 /* left and right */
4745 y = randint1(dy) + dy / 2;
4746 place_inner_bold(y1 + y, x1 - 1);
4747 place_inner_bold(y1 + y, x2 + 1);
4751 /* top and bottom */
4752 x = randint1(dx) + dx / 2;
4753 place_inner_bold(y1 - 1, x1 + x);
4754 place_inner_bold(y2 + 1, x1 + x);
4757 /* Fill with monsters and treasure, highest difficulty */
4758 fill_treasure(x1, x2, y1, y2, 10);
4760 C_KILL(visited, num_vertices, int);
4764 /* Build a town/ castle by using a recursive algorithm.
4765 * Basically divide each region in a probalistic way to create
4766 * smaller regions. When the regions get too small stop.
4768 * The power variable is a measure of how well defended a region is.
4769 * This alters the possible choices.
4771 static void build_recursive_room(int x1, int y1, int x2, int y2, int power)
4777 /* Temp variables */
4783 if ((power < 3) && (xsize > 12) && (ysize > 12))
4785 /* Need outside wall +keep */
4792 /* Make rooms + subdivide */
4793 if ((randint1(10) > 2) && (xsize < 8) && (ysize < 8))
4799 choice = randint1(2) + 1;
4804 /* Mostly subdivide */
4805 choice = randint1(3) + 1;
4809 /* Based on the choice made above, do something */
4817 /* top and bottom */
4818 for (x = x1; x <= x2; x++)
4820 place_outer_bold(y1, x);
4821 place_outer_bold(y2, x);
4824 /* left and right */
4825 for (y = y1 + 1; y < y2; y++)
4827 place_outer_bold(y, x1);
4828 place_outer_bold(y, x2);
4831 /* Make a couple of entrances */
4834 /* left and right */
4835 y = randint1(ysize) + y1;
4836 place_floor_bold(y, x1);
4837 place_floor_bold(y, x2);
4841 /* top and bottom */
4842 x = randint1(xsize) + x1;
4843 place_floor_bold(y1, x);
4844 place_floor_bold(y2, x);
4847 /* Select size of keep */
4848 t1 = randint1(ysize / 3) + y1;
4849 t2 = y2 - randint1(ysize / 3);
4850 t3 = randint1(xsize / 3) + x1;
4851 t4 = x2 - randint1(xsize / 3);
4853 /* Do outside areas */
4855 /* Above and below keep */
4856 build_recursive_room(x1 + 1, y1 + 1, x2 - 1, t1, power + 1);
4857 build_recursive_room(x1 + 1, t2, x2 - 1, y2, power + 1);
4859 /* Left and right of keep */
4860 build_recursive_room(x1 + 1, t1 + 1, t3, t2 - 1, power + 3);
4861 build_recursive_room(t4, t1 + 1, x2 - 1, t2 - 1, power + 3);
4863 /* Make the keep itself: */
4876 /* Try to build a room */
4877 if ((xsize < 3) || (ysize < 3))
4879 for (y = y1; y < y2; y++)
4881 for (x = x1; x < x2; x++)
4883 place_inner_bold(y, x);
4891 /* Make outside walls */
4892 /* top and bottom */
4893 for (x = x1 + 1; x <= x2 - 1; x++)
4895 place_inner_bold(y1 + 1, x);
4896 place_inner_bold(y2 - 1, x);
4899 /* left and right */
4900 for (y = y1 + 1; y <= y2 - 1; y++)
4902 place_inner_bold(y, x1 + 1);
4903 place_inner_bold(y, x2 - 1);
4907 y = randint1(ysize - 3) + y1 + 1;
4912 place_floor_bold(y, x1 + 1);
4917 place_floor_bold(y, x2 - 1);
4920 /* Build the room */
4921 build_recursive_room(x1 + 2, y1 + 2, x2 - 2, y2 - 2, power + 3);
4926 /* Try and divide vertically */
4930 for (y = y1; y < y2; y++)
4932 for (x = x1; x < x2; x++)
4934 place_inner_bold(y, x);
4940 t1 = randint1(xsize - 2) + x1 + 1;
4941 build_recursive_room(x1, y1, t1, y2, power - 2);
4942 build_recursive_room(t1 + 1, y1, x2, y2, power - 2);
4947 /* Try and divide horizontally */
4951 for (y = y1; y < y2; y++)
4953 for (x = x1; x < x2; x++)
4955 place_inner_bold(y, x);
4961 t1 = randint1(ysize - 2) + y1 + 1;
4962 build_recursive_room(x1, y1, x2, t1, power - 2);
4963 build_recursive_room(x1, t1 + 1, x2, y2, power - 2);
4970 /* Build a castle */
4972 /* Driver routine: clear the region and call the recursive
4975 *This makes a vault that looks like a castle/ city in the dungeon.
4977 static void build_castle_vault(int x0, int y0, int xsize, int ysize)
4983 /* Pick a random room size */
4992 if (cheat_room) msg_print("Castle Vault");
4994 /* generate the room */
4995 for (y = y1 - 1; y <= y2 + 1; y++)
4997 for (x = x1 - 1; x <= x2 + 1; x++)
4999 cave[y][x].info |= (CAVE_ROOM | CAVE_ICKY);
5000 /* Make everything a floor */
5001 place_floor_bold(y, x);
5005 /* Make the castle */
5006 build_recursive_room(x1, y1, x2, y2, randint1(5));
5008 /* Fill with monsters and treasure, low difficulty */
5009 fill_treasure(x1, x2, y1, y2, randint1(3));
5014 * Add outer wall to a floored region
5015 * Note: no range checking is done so must be inside dungeon
5016 * This routine also stomps on doors
5018 static void add_outer_wall(int x, int y, int light,
5019 int x1, int y1, int x2, int y2)
5023 if (!in_bounds(y, x)) return;
5025 /* hack- check to see if square has been visited before
5026 * if so, then exit (use room flag to do this) */
5027 if (cave[y][x].info & CAVE_ROOM) return;
5030 cave[y][x].info |= CAVE_ROOM;
5032 if (is_floor_bold(y, x))
5034 for (i = -1; i <= 1; i++)
5036 for (j = -1; j <= 1; j++)
5038 if ((x + i >= x1) && (x + i <= x2) &&
5039 (y + j >= y1) && (y + j <= y2))
5041 add_outer_wall(x + i, y + j, light, x1, y1, x2, y2);
5042 if (light) cave[y][x].info |= CAVE_GLOW;
5047 else if (is_extra_bold(y, x))
5049 /* Set bounding walls */
5050 place_outer_bold(y, x);
5051 if (light) cave[y][x].info |= CAVE_GLOW;
5053 else if (cave[y][x].feat == FEAT_PERM_OUTER)
5055 /* Set bounding walls */
5056 if (light) cave[y][x].info |= CAVE_GLOW;
5062 * Hacked distance formula - gives the 'wrong' answer.
5063 * Used to build crypts
5065 static int dist2(int x1, int y1, int x2, int y2,
5066 int h1, int h2, int h3, int h4)
5072 /* Basically this works by taking the normal pythagorean formula
5073 * and using an expansion to express this in a way without the
5074 * square root. This approximate formula is then perturbed to give
5075 * the distorted results. (I found this by making a mistake when I was
5076 * trying to fix the circular rooms.)
5079 /* h1-h4 are constants that describe the metric */
5080 if (dx >= 2 * dy) return (dx + (dy * h1) / h2);
5081 if (dy >= 2 * dx) return (dy + (dx * h1) / h2);
5082 return (((dx + dy) * 128) / 181 +
5083 (dx * dx / (dy * h3) + dy * dy / (dx * h3)) * h4);
5084 /* 128/181 is approx. 1/sqrt(2) */
5089 * Build target vault.
5090 * This is made by two concentric "crypts" with perpendicular
5091 * walls creating the cross-hairs.
5093 static void build_target_vault(int x0, int y0, int xsize, int ysize)
5097 /* Make a random metric */
5099 h1 = randint1(32) - 16;
5102 h4 = randint1(32) - 16;
5104 if (cheat_room) msg_print("Target Vault");
5106 /* work out outer radius */
5117 for (x = x0 - rad; x <= x0 + rad; x++)
5119 for (y = y0 - rad; y <= y0 + rad; y++)
5121 /* clear room flag */
5122 cave[y][x].info &= ~(CAVE_ROOM);
5124 /* Vault - so is "icky" */
5125 cave[y][x].info |= CAVE_ICKY;
5127 if (dist2(y0, x0, y, x, h1, h2, h3, h4) <= rad - 1)
5129 /* inside- so is floor */
5130 place_floor_bold(y, x);
5134 /* make granite outside so arena works */
5135 place_extra_bold(y, x);
5138 /* proper boundary for arena */
5139 if (((y + rad) == y0) || ((y - rad) == y0) ||
5140 ((x + rad) == x0) || ((x - rad) == x0))
5142 place_extra_bold(y, x);
5147 /* Find visible outer walls and set to be FEAT_OUTER */
5148 add_outer_wall(x0, y0, FALSE, x0 - rad - 1, y0 - rad - 1,
5149 x0 + rad + 1, y0 + rad + 1);
5151 /* Add inner wall */
5152 for (x = x0 - rad / 2; x <= x0 + rad / 2; x++)
5154 for (y = y0 - rad / 2; y <= y0 + rad / 2; y++)
5156 if (dist2(y0, x0, y, x, h1, h2, h3, h4) == rad / 2)
5158 /* Make an internal wall */
5159 place_inner_bold(y, x);
5164 /* Add perpendicular walls */
5165 for (x = x0 - rad; x <= x0 + rad; x++)
5167 place_inner_bold(y0, x);
5170 for (y = y0 - rad; y <= y0 + rad; y++)
5172 place_inner_bold(y, x0);
5175 /* Make inner vault */
5176 for (y = y0 - 1; y <= y0 + 1; y++)
5178 place_inner_bold(y, x0 - 1);
5179 place_inner_bold(y, x0 + 1);
5181 for (x = x0 - 1; x <= x0 + 1; x++)
5183 place_inner_bold(y0 - 1, x);
5184 place_inner_bold(y0 + 1, x);
5187 place_floor_bold(y0, x0);
5190 /* Add doors to vault */
5191 /* get two distances so can place doors relative to centre */
5192 x = (rad - 2) / 4 + 1;
5195 add_door(x0 + x, y0);
5196 add_door(x0 + y, y0);
5197 add_door(x0 - x, y0);
5198 add_door(x0 - y, y0);
5199 add_door(x0, y0 + x);
5200 add_door(x0, y0 + y);
5201 add_door(x0, y0 - x);
5202 add_door(x0, y0 - y);
5204 /* Fill with stuff - medium difficulty */
5205 fill_treasure(x0 - rad, x0 + rad, y0 - rad, y0 + rad, randint1(3) + 3);
5209 #ifdef ALLOW_CAVERNS_AND_LAKES
5211 * This routine uses a modified version of the lake code to make a
5212 * distribution of some terrain type over the vault. This type
5213 * depends on the dungeon depth.
5215 * Miniture rooms are then scattered across the vault.
5217 static void build_elemental_vault(int x0, int y0, int xsiz, int ysiz)
5222 int xsize, ysize, xhsize, yhsize, x, y, i;
5226 if (cheat_room) msg_print("Elemental Vault");
5228 /* round to make sizes even */
5236 /* Earth vault (Rubble) */
5237 type = LAKE_T_EARTH_VAULT;
5239 else if (dun_level < 50)
5241 /* Air vault (Trees) */
5242 type = LAKE_T_AIR_VAULT;
5244 else if (dun_level < 75)
5246 /* Water vault (shallow water) */
5247 type = LAKE_T_WATER_VAULT;
5251 /* Fire vault (shallow lava) */
5252 type = LAKE_T_FIRE_VAULT;
5257 /* testing values for these parameters: feel free to adjust */
5258 grd = 1 << (randint0(3));
5260 /* want average of about 16 */
5261 roug = randint1(8) * randint1(4);
5263 /* Make up size of various componants */
5267 /* Deep water/lava */
5268 c1 = randint0(c3 / 2) + randint0(c3 / 2) - 5;
5270 /* Shallow boundary */
5274 generate_hmap(y0, x0, xsize, ysize, grd, roug, c3);
5276 /* Convert to normal format+ clean up */
5277 done = generate_lake(y0, x0, xsize, ysize, c1, c2, c3, type);
5280 /* Set icky flag because is a vault */
5281 for (x = 0; x <= xsize; x++)
5283 for (y = 0; y <= ysize; y++)
5285 cave[y0 - yhsize + y][x0 - xhsize + x].info |= CAVE_ICKY;
5289 /* make a few rooms in the vault */
5290 for (i = 1; i <= (xsize * ysize) / 50; i++)
5292 build_small_room(x0 + randint0(xsize - 4) - xsize / 2 + 2,
5293 y0 + randint0(ysize - 4) - ysize / 2 + 2);
5296 /* Fill with monsters and treasure, low difficulty */
5297 fill_treasure(x0 - xhsize + 1, x0 - xhsize + xsize - 1,
5298 y0 - yhsize + 1, y0 - yhsize + ysize - 1, randint1(5));
5300 #endif /* ALLOW_CAVERNS_AND_LAKES */
5306 static bool build_type10(void)
5308 int y0, x0, xsize, ysize, vtype;
5311 /* big enough to look good, small enough to be fairly common. */
5312 xsize = randint1(22) + 22;
5313 ysize = randint1(11) + 11;
5315 /* Find and reserve some space in the dungeon. Get center of room. */
5316 if (!find_space(&y0, &x0, ysize + 1, xsize + 1)) return FALSE;
5318 /* Boost the rating- higher than lesser vaults and lower than greater vaults */
5321 /* (Sometimes) Cause a special feeling */
5322 if ((dun_level <= 50) ||
5323 (randint1((dun_level - 40) * (dun_level - 40) + 1) < 400))
5325 good_item_flag = TRUE;
5328 /* Select type of vault */
5329 #ifdef ALLOW_CAVERNS_AND_LAKES
5330 vtype = randint1(15);
5331 #else /* ALLOW_CAVERNS_AND_LAKES */
5332 vtype = randint1(7);
5333 #endif /* ALLOW_CAVERNS_AND_LAKES */
5337 /* Build an appropriate room */
5338 case 1: case 9: build_bubble_vault(x0, y0, xsize, ysize); break;
5339 case 2: case 10: build_room_vault(x0, y0, xsize, ysize); break;
5340 case 3: case 11: build_cave_vault(x0, y0, xsize, ysize); break;
5341 case 4: case 12: build_maze_vault(x0, y0, xsize, ysize, TRUE); break;
5342 case 5: case 13: build_mini_c_vault(x0, y0, xsize, ysize); break;
5343 case 6: case 14: build_castle_vault(x0, y0, xsize, ysize); break;
5344 case 7: case 15: build_target_vault(x0, y0, xsize, ysize); break;
5345 #ifdef ALLOW_CAVERNS_AND_LAKES
5346 case 8: build_elemental_vault(x0, y0, xsize, ysize); break;
5347 #endif /* ALLOW_CAVERNS_AND_LAKES */
5348 /* I know how to add a few more... give me some time. */
5351 default: return FALSE;
5359 * Build an vertical oval room.
5360 * For every grid in the possible square, check the distance.
5361 * If it's less than the radius, make it a room square.
5363 * When done fill from the inside to find the walls,
5365 static bool build_type11(void)
5367 int rad, x, y, x0, y0;
5370 /* Occasional light */
5371 if ((randint1(dun_level) <= 15) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS)) light = TRUE;
5375 /* Find and reserve some space in the dungeon. Get center of room. */
5376 if (!find_space(&y0, &x0, rad * 2 + 1, rad * 2 + 1)) return FALSE;
5378 /* Make circular floor */
5379 for (x = x0 - rad; x <= x0 + rad; x++)
5381 for (y = y0 - rad; y <= y0 + rad; y++)
5383 if (distance(y0, x0, y, x) <= rad - 1)
5385 /* inside- so is floor */
5386 place_floor_bold(y, x);
5388 else if (distance(y0, x0, y, x) <= rad + 1)
5390 /* make granite outside so arena works */
5391 place_extra_bold(y, x);
5396 /* Find visible outer walls and set to be FEAT_OUTER */
5397 add_outer_wall(x0, y0, light, x0 - rad, y0 - rad, x0 + rad, y0 + rad);
5405 * For every grid in the possible square, check the (fake) distance.
5406 * If it's less than the radius, make it a room square.
5408 * When done fill from the inside to find the walls,
5410 static bool build_type12(void)
5412 int rad, x, y, x0, y0;
5414 bool emptyflag = TRUE;
5416 /* Make a random metric */
5418 h1 = randint1(32) - 16;
5421 h4 = randint1(32) - 16;
5423 /* Occasional light */
5424 if ((randint1(dun_level) <= 5) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS)) light = TRUE;
5428 /* Find and reserve some space in the dungeon. Get center of room. */
5429 if (!find_space(&y0, &x0, rad * 2 + 3, rad * 2 + 3)) return FALSE;
5432 for (x = x0 - rad; x <= x0 + rad; x++)
5434 for (y = y0 - rad; y <= y0 + rad; y++)
5436 /* clear room flag */
5437 cave[y][x].info &= ~(CAVE_ROOM);
5439 if (dist2(y0, x0, y, x, h1, h2, h3, h4) <= rad - 1)
5441 /* inside - so is floor */
5442 place_floor_bold(y, x);
5444 else if (distance(y0, x0, y, x) < 3)
5446 place_floor_bold(y, x);
5450 /* make granite outside so arena works */
5451 place_extra_bold(y, x);
5454 /* proper boundary for arena */
5455 if (((y + rad) == y0) || ((y - rad) == y0) ||
5456 ((x + rad) == x0) || ((x - rad) == x0))
5458 place_extra_bold(y, x);
5463 /* Find visible outer walls and set to be FEAT_OUTER */
5464 add_outer_wall(x0, y0, light, x0 - rad - 1, y0 - rad - 1,
5465 x0 + rad + 1, y0 + rad + 1);
5467 /* Check to see if there is room for an inner vault */
5468 for (x = x0 - 2; x <= x0 + 2; x++)
5470 for (y = y0 - 2; y <= y0 + 2; y++)
5472 if (!is_floor_bold(y, x))
5474 /* Wall in the way */
5480 if (emptyflag && one_in_(2))
5482 /* Build the vault */
5483 build_small_room(x0, y0);
5485 /* Place a treasure in the vault */
5486 place_object(y0, x0, 0L);
5488 /* Let's guard the treasure well */
5489 vault_monsters(y0, x0, randint0(2) + 3);
5491 /* Traps naturally */
5492 vault_traps(y0, x0, 4, 4, randint0(3) + 2);
5500 * Helper function for "trapped monster pit"
5502 static bool vault_aux_trapped_pit(int r_idx)
5504 monster_race *r_ptr = &r_info[r_idx];
5506 /* Validate the monster */
5507 if (!vault_monster_okay(r_idx)) return (FALSE);
5509 /* No wall passing monster */
5510 if (r_ptr->flags2 & (RF2_PASS_WALL | RF2_KILL_WALL)) return (FALSE);
5518 * Type 12 -- Trapped monster pits
5520 * A trapped monster pit is a "big" room with a straight corridor in
5521 * which wall opening traps are placed, and with two "inner" rooms
5522 * containing a "collection" of monsters of a given type organized in
5525 * The trapped monster pit appears as shown below, where the actual
5526 * monsters in each location depend on the type of the pit
5528 * #########################
5530 * ####################### #
5531 * #####001123454321100### #
5532 * ###0012234567654322100# #
5533 * ####################### #
5535 * # #######################
5536 * # #0012234567654322100###
5537 * # ###001123454321100#####
5538 * # #######################
5540 * #########################
5542 * Note that the monsters in the pit are now chosen by using "get_mon_num()"
5543 * to request 16 "appropriate" monsters, sorting them by level, and using
5544 * the "even" entries in this sorted list for the contents of the pit.
5546 * Hack -- all of the "dragons" in a "dragon" pit must be the same "color",
5547 * which is handled by requiring a specific "breath" attack for all of the
5548 * dragons. This may include "multi-hued" breath. Note that "wyrms" may
5549 * be present in many of the dragon pits, if they have the proper breath.
5551 * Note the use of the "get_mon_num_prep()" function, and the special
5552 * "get_mon_num_hook()" restriction function, to prepare the "monster
5553 * allocation table" in such a way as to optimize the selection of
5554 * "appropriate" non-unique monsters for the pit.
5556 * Note that the "get_mon_num()" function may (rarely) fail, in which case
5557 * the pit will be empty, and will not effect the level rating.
5559 * Note that "monster pits" will never contain "unique" monsters.
5561 static bool build_type13(void)
5563 static int placing[][3] = {
5564 {-2, -9, 0}, {-2, -8, 0}, {-3, -7, 0}, {-3, -6, 0},
5565 {+2, -9, 0}, {+2, -8, 0}, {+3, -7, 0}, {+3, -6, 0},
5566 {-2, +9, 0}, {-2, +8, 0}, {-3, +7, 0}, {-3, +6, 0},
5567 {+2, +9, 0}, {+2, +8, 0}, {+3, +7, 0}, {+3, +6, 0},
5568 {-2, -7, 1}, {-3, -5, 1}, {-3, -4, 1},
5569 {+2, -7, 1}, {+3, -5, 1}, {+3, -4, 1},
5570 {-2, +7, 1}, {-3, +5, 1}, {-3, +4, 1},
5571 {+2, +7, 1}, {+3, +5, 1}, {+3, +4, 1},
5572 {-2, -6, 2}, {-2, -5, 2}, {-3, -3, 2},
5573 {+2, -6, 2}, {+2, -5, 2}, {+3, -3, 2},
5574 {-2, +6, 2}, {-2, +5, 2}, {-3, +3, 2},
5575 {+2, +6, 2}, {+2, +5, 2}, {+3, +3, 2},
5576 {-2, -4, 3}, {-3, -2, 3},
5577 {+2, -4, 3}, {+3, -2, 3},
5578 {-2, +4, 3}, {-3, +2, 3},
5579 {+2, +4, 3}, {+3, +2, 3},
5580 {-2, -3, 4}, {-3, -1, 4},
5581 {+2, -3, 4}, {+3, -1, 4},
5582 {-2, +3, 4}, {-3, +1, 4},
5583 {+2, +3, 4}, {+3, +1, 4},
5584 {-2, -2, 5}, {-3, 0, 5}, {-2, +2, 5},
5585 {+2, -2, 5}, {+3, 0, 5}, {+2, +2, 5},
5586 {-2, -1, 6}, {-2, +1, 6},
5587 {+2, -1, 6}, {+2, +1, 6},
5588 {-2, 0, 7}, {+2, 0, 7},
5592 int y, x, y1, x1, y2, x2, xval, yval;
5601 int cur_pit_type = pick_vault_type(pit_types, d_info[dungeon_type].pit);
5602 vault_aux_type *n_ptr;
5604 /* Only in Angband */
5605 if (dungeon_type != DUNGEON_ANGBAND) return FALSE;
5607 /* No type available */
5608 if (cur_pit_type < 0) return FALSE;
5610 n_ptr = &pit_types[cur_pit_type];
5612 /* Process a preparation function if necessary */
5613 if (n_ptr->prep_func) (*(n_ptr->prep_func))();
5615 /* Prepare allocation table */
5616 get_mon_num_prep(n_ptr->hook_func, vault_aux_trapped_pit);
5618 align.sub_align = SUB_ALIGN_NEUTRAL;
5620 /* Pick some monster types */
5621 for (i = 0; i < 16; i++)
5623 int r_idx = 0, attempts = 100;
5624 monster_race *r_ptr = NULL;
5628 /* Get a (hard) monster type */
5629 r_idx = get_mon_num(dun_level + 0);
5630 r_ptr = &r_info[r_idx];
5632 /* Decline incorrect alignment */
5633 if (monster_has_hostile_align(&align, 0, 0, r_ptr)) continue;
5635 /* Accept this monster */
5639 /* Notice failure */
5640 if (!r_idx || !attempts) return FALSE;
5642 /* Note the alignment */
5643 if (r_ptr->flags3 & RF3_EVIL) align.sub_align |= SUB_ALIGN_EVIL;
5644 if (r_ptr->flags3 & RF3_GOOD) align.sub_align |= SUB_ALIGN_GOOD;
5649 /* Find and reserve some space in the dungeon. Get center of room. */
5650 if (!find_space(&yval, &xval, 13, 25)) return FALSE;
5658 /* Fill with inner walls */
5659 for (y = y1 - 1; y <= y2 + 1; y++)
5661 for (x = x1 - 1; x <= x2 + 1; x++)
5663 c_ptr = &cave[y][x];
5664 place_inner_grid(c_ptr);
5665 c_ptr->info |= (CAVE_ROOM);
5669 /* Place the floor area 1 */
5670 for (x = x1 + 3; x <= x2 - 3; x++)
5672 c_ptr = &cave[yval-2][x];
5673 place_floor_grid(c_ptr);
5674 add_cave_info(yval-2, x, CAVE_ICKY);
5676 c_ptr = &cave[yval+2][x];
5677 place_floor_grid(c_ptr);
5678 add_cave_info(yval+2, x, CAVE_ICKY);
5681 /* Place the floor area 2 */
5682 for (x = x1 + 5; x <= x2 - 5; x++)
5684 c_ptr = &cave[yval-3][x];
5685 place_floor_grid(c_ptr);
5686 add_cave_info(yval-3, x, CAVE_ICKY);
5688 c_ptr = &cave[yval+3][x];
5689 place_floor_grid(c_ptr);
5690 add_cave_info(yval+3, x, CAVE_ICKY);
5694 for (x = x1; x <= x2; x++)
5696 c_ptr = &cave[yval][x];
5697 place_floor_grid(c_ptr);
5698 c_ptr = &cave[y1][x];
5699 place_floor_grid(c_ptr);
5700 c_ptr = &cave[y2][x];
5701 place_floor_grid(c_ptr);
5704 /* Place the outer walls */
5705 for (y = y1 - 1; y <= y2 + 1; y++)
5707 c_ptr = &cave[y][x1 - 1];
5708 place_outer_grid(c_ptr);
5709 c_ptr = &cave[y][x2 + 1];
5710 place_outer_grid(c_ptr);
5712 for (x = x1 - 1; x <= x2 + 1; x++)
5714 c_ptr = &cave[y1 - 1][x];
5715 place_outer_grid(c_ptr);
5716 c_ptr = &cave[y2 + 1][x];
5717 place_outer_grid(c_ptr);
5720 /* Random corridor */
5723 for (y = y1; y <= yval; y++)
5725 place_floor_bold(y, x2);
5726 place_solid_bold(y, x1-1);
5728 for (y = yval; y <= y2 + 1; y++)
5730 place_floor_bold(y, x1);
5731 place_solid_bold(y, x2+1);
5736 for (y = yval; y <= y2 + 1; y++)
5738 place_floor_bold(y, x1);
5739 place_solid_bold(y, x2+1);
5741 for (y = y1; y <= yval; y++)
5743 place_floor_bold(y, x2);
5744 place_solid_bold(y, x1-1);
5748 /* Place the wall open trap */
5749 cave[yval][xval].mimic = cave[yval][xval].feat;
5750 cave[yval][xval].feat = FEAT_TRAP_OPEN;
5752 /* Sort the entries */
5753 for (i = 0; i < 16 - 1; i++)
5755 /* Sort the entries */
5756 for (j = 0; j < 16 - 1; j++)
5761 int p1 = r_info[what[i1]].level;
5762 int p2 = r_info[what[i2]].level;
5768 what[i1] = what[i2];
5779 msg_format("%s%s¤Î櫥ԥåÈ", n_ptr->name, pit_subtype_string(cur_pit_type, FALSE));
5781 msg_format("Trapped monster pit (%s%s)", n_ptr->name, pit_subtype_string(cur_pit_type, FALSE));
5785 /* Select the entries */
5786 for (i = 0; i < 8; i++)
5788 /* Every other entry */
5789 what[i] = what[i * 2];
5794 msg_print(r_name + r_info[what[i]].name);
5798 /* Increase the level rating */
5801 /* (Sometimes) Cause a "special feeling" (for "Monster Pits") */
5802 if ((dun_level <= 40) && (randint1(dun_level * dun_level + 50) < 300))
5804 good_item_flag = TRUE;
5807 for (i = 0; placing[i][2] >= 0; i++)
5809 y = yval + placing[i][0];
5810 x = xval + placing[i][1];
5811 place_monster_aux(0, y, x, what[placing[i][2]], PM_NO_KAGE);
5819 * Type 14 -- trapped rooms
5821 * A special trap is placed at center of the room
5823 static bool build_type14(void)
5825 int y, x, y2, x2, yval, xval;
5826 int y1, x1, xsize, ysize;
5833 /* Pick a room size */
5839 xsize = x1 + x2 + 1;
5840 ysize = y1 + y2 + 1;
5842 /* Find and reserve some space in the dungeon. Get center of room. */
5843 if (!find_space(&yval, &xval, ysize + 2, xsize + 2)) return FALSE;
5845 /* Choose lite or dark */
5846 light = ((dun_level <= randint1(25)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS));
5849 /* Get corner values */
5850 y1 = yval - ysize / 2;
5851 x1 = xval - xsize / 2;
5852 y2 = yval + (ysize - 1) / 2;
5853 x2 = xval + (xsize - 1) / 2;
5856 /* Place a full floor under the room */
5857 for (y = y1 - 1; y <= y2 + 1; y++)
5859 for (x = x1 - 1; x <= x2 + 1; x++)
5861 c_ptr = &cave[y][x];
5862 place_floor_grid(c_ptr);
5863 c_ptr->info |= (CAVE_ROOM);
5864 if (light) c_ptr->info |= (CAVE_GLOW);
5868 /* Walls around the room */
5869 for (y = y1 - 1; y <= y2 + 1; y++)
5871 c_ptr = &cave[y][x1 - 1];
5872 place_outer_grid(c_ptr);
5873 c_ptr = &cave[y][x2 + 1];
5874 place_outer_grid(c_ptr);
5876 for (x = x1 - 1; x <= x2 + 1; x++)
5878 c_ptr = &cave[y1 - 1][x];
5879 place_outer_grid(c_ptr);
5880 c_ptr = &cave[y2 + 1][x];
5881 place_outer_grid(c_ptr);
5884 if (dun_level < 30 + randint1(30))
5885 trap = FEAT_TRAP_PIRANHA;
5887 trap = FEAT_TRAP_ARMAGEDDON;
5889 /* Place a special trap */
5890 c_ptr = &cave[rand_spread(yval, ysize/4)][rand_spread(xval, xsize/4)];
5891 c_ptr->mimic = c_ptr->feat;
5898 msg_format("%s¤ÎÉô²°", f_name + f_info[trap].name);
5900 msg_format("Room of %s", f_name + f_info[trap].name);
5909 * Attempt to build a room of the given type at the given block
5911 * Note that we restrict the number of "crowded" rooms to reduce
5912 * the chance of overflowing the monster list during level creation.
5914 bool room_build(int typ)
5919 /* Build an appropriate room */
5920 case ROOM_T_NORMAL: build_type1(); break;
5921 case ROOM_T_OVERLAP: build_type2(); break;
5922 case ROOM_T_CROSS: build_type3(); break;
5923 case ROOM_T_INNER_FEAT: build_type4(); break;
5924 case ROOM_T_NEST: build_type5(); break;
5925 case ROOM_T_PIT: build_type6(); break;
5926 case ROOM_T_LESSER_VAULT: build_type7(); break;
5927 case ROOM_T_GREATER_VAULT: build_type8(); break;
5928 case ROOM_T_FRACAVE: build_type9(); break;
5929 case ROOM_T_RANDOM_VAULT: build_type10(); break;
5930 case ROOM_T_OVAL: build_type11(); break;
5931 case ROOM_T_CRYPT: build_type12(); break;
5932 case ROOM_T_TRAP_PIT: build_type13(); break;
5933 case ROOM_T_TRAP: build_type14(); break;
5936 default: return FALSE;
5943 #define MOVE_PLIST(dst, src) (prob_list[dst] += prob_list[src], prob_list[src] = 0)
5946 * [from SAngband (originally from OAngband)]
5948 * Generate rooms in dungeon. Build bigger rooms at first.
5950 void generate_rooms(void)
5956 int prob_list[ROOM_T_MAX];
5957 int rooms_built = 0;
5958 int area_size = 100 * (cur_hgt*cur_wid) / (MAX_HGT*MAX_WID);
5959 int level_index = MIN(10, div_round(dun_level, 10));
5961 /* Number of each type of room on this level */
5962 s16b room_num[ROOM_T_MAX];
5964 /* Limit number of rooms */
5965 int dun_rooms = rand_range(DUN_ROOMS_MIN, DUN_ROOMS_MAX * area_size / 100);
5967 /* Assume normal cave */
5968 room_info_type *room_info_ptr = room_info_normal;
5972 * Initialize probability list.
5974 for (i = 0; i < ROOM_T_MAX; i++)
5976 /* No rooms allowed above their minimum depth. */
5977 if (dun_level < room_info_ptr[i].min_level)
5983 prob_list[i] = room_info_ptr[i].prob[level_index];
5988 * XXX -- Various dungeon types and options.
5991 /* Ironman sees only Greater Vaults */
5992 if (ironman_rooms && !((d_info[dungeon_type].flags1 & (DF1_BEGINNER | DF1_CHAMELEON))))
5994 for (i = 0; i < ROOM_T_MAX; i++)
5996 if (i == ROOM_T_GREATER_VAULT) prob_list[i] = 1;
5997 else prob_list[i] = 0;
6001 /* Forbidden vaults */
6002 else if (d_info[dungeon_type].flags1 & DF1_NO_VAULT)
6004 prob_list[ROOM_T_LESSER_VAULT] = 0;
6005 prob_list[ROOM_T_GREATER_VAULT] = 0;
6006 prob_list[ROOM_T_RANDOM_VAULT] = 0;
6010 /* NO_CAVE dungeon (Castle)*/
6011 if (d_info[dungeon_type].flags1 & DF1_NO_CAVE)
6013 MOVE_PLIST(ROOM_T_NORMAL, ROOM_T_FRACAVE);
6014 MOVE_PLIST(ROOM_T_INNER_FEAT, ROOM_T_CRYPT);
6015 MOVE_PLIST(ROOM_T_INNER_FEAT, ROOM_T_OVAL);
6018 /* CAVE dungeon (Orc cave etc.) */
6019 else if (d_info[dungeon_type].flags1 & DF1_CAVE)
6021 MOVE_PLIST(ROOM_T_FRACAVE, ROOM_T_NORMAL);
6024 /* No caves when a (random) cavern exists: they look bad */
6025 else if (dun->cavern || dun->empty_level)
6027 prob_list[ROOM_T_FRACAVE] = 0;
6032 * Initialize number of rooms,
6033 * And calcurate total probability.
6035 for (total_prob = 0, i = 0; i < ROOM_T_MAX; i++)
6038 total_prob += prob_list[i];
6042 * Prepare the number of rooms, of all types, we should build
6045 for (i = dun_rooms; i > 0; i--)
6048 int rand = randint0(total_prob);
6050 /* Get room_type randomly */
6051 for (room_type = 0; room_type < ROOM_T_MAX; room_type++)
6053 if (rand < prob_list[room_type]) break;
6054 else rand -= prob_list[room_type];
6058 if (room_type >= ROOM_T_MAX) room_type = ROOM_T_NORMAL;
6060 /* Increase the number of rooms of that type we should build. */
6061 room_num[room_type]++;
6067 case ROOM_T_LESSER_VAULT:
6068 case ROOM_T_TRAP_PIT:
6074 case ROOM_T_GREATER_VAULT:
6075 case ROOM_T_RANDOM_VAULT:
6084 * Build each type of room one by one until we cannot build any more.
6085 * [from SAngband (originally from OAngband)]
6089 /* Assume no remaining rooms */
6092 for (i = 0; i < ROOM_T_MAX; i++)
6094 /* What type of room are we building now? */
6095 int room_type = room_build_order[i];
6097 /* Go next if none available */
6098 if (!room_num[room_type]) continue;
6100 /* Use up one unit */
6101 room_num[room_type]--;
6103 /* Build the room. */
6104 if (room_build(room_type))
6106 /* Increase the room built count. */
6109 /* Mark as there was some remaining rooms */
6116 case ROOM_T_TRAP_PIT:
6118 /* Avoid too many monsters */
6121 room_num[ROOM_T_PIT] = 0;
6122 room_num[ROOM_T_NEST] = 0;
6123 room_num[ROOM_T_TRAP_PIT] = 0;
6128 /* Stop building this type on failure. */
6131 room_num[room_type] = 0;
6135 /* End loop if no room remain */