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 * Array of minimum room depths
23 static s16b roomdep[] =
26 1, /* 1 = Simple (33x11) */
27 1, /* 2 = Overlapping (33x11) */
28 3, /* 3 = Crossed (33x11) */
29 3, /* 4 = Large (33x11) */
30 10, /* 5 = Monster nest (33x11) */
31 10, /* 6 = Monster pit (33x11) */
32 10, /* 7 = Lesser vault (33x22) */
33 20, /* 8 = Greater vault (66x44) */
34 5, /* 9 = Fractal cave (42x24) */
35 10, /* 10 = Random vault (44x22) */
36 3, /* 11 = Circular rooms (22x22) */
37 10, /* 12 = Crypts (22x22) */
38 20, /* 13 = Trapped monster pit */
39 20, /* 14 = Piranha/Armageddon trap room */
43 static void place_locked_door(int y, int x)
45 if (d_info[dungeon_type].flags1 & DF1_NO_DOORS)
47 place_floor_bold(y, x);
51 set_cave_feat(y, x, FEAT_DOOR_HEAD+randint1(7));
52 cave[y][x].info &= ~(CAVE_FLOOR);
57 static void place_secret_door(int y, int x)
59 if (d_info[dungeon_type].flags1 & DF1_NO_DOORS)
61 place_floor_bold(y, x);
65 cave_type *c_ptr = &cave[y][x];
67 /* Create secret door */
68 place_closed_door(y, x);
70 /* Hide by inner wall because this is used in rooms only */
71 c_ptr->mimic = feat_wall_inner;
73 /* Floor type terrain cannot hide a door */
74 if (feat_floor(c_ptr->mimic))
76 c_ptr->feat = c_ptr->mimic;
80 c_ptr->info &= ~(CAVE_FLOOR);
86 * This funtion makes a very small room centred at (x0, y0)
87 * This is used in crypts, and random elemental vaults.
89 * Note - this should be used only on allocated regions
90 * within another room.
92 static void build_small_room(int x0, int y0)
96 for (y = y0 - 1; y <= y0 + 1; y++)
98 place_inner_bold(y, x0 - 1);
99 place_inner_bold(y, x0 + 1);
102 for (x = x0 - 1; x <= x0 + 1; x++)
104 place_inner_bold(y0 - 1, x);
105 place_inner_bold(y0 + 1, x);
108 /* Place a secret door on one side */
111 case 0: place_secret_door(y0, x0 - 1); break;
112 case 1: place_secret_door(y0, x0 + 1); break;
113 case 2: place_secret_door(y0 - 1, x0); break;
114 case 3: place_secret_door(y0 + 1, x0); break;
117 /* Clear mimic type */
118 cave[y0][x0].mimic = 0;
120 /* Add inner open space */
121 place_floor_bold(y0, x0);
126 * This function tunnels around a room if
127 * it will cut off part of a cave system.
129 static void check_room_boundary(int x1, int y1, int x2, int y2)
132 bool old_is_floor, new_is_floor;
138 old_is_floor = get_is_floor(x1 - 1, y1);
141 * Count the number of floor-wall boundaries around the room
142 * Note: diagonal squares are ignored since the player can move diagonally
143 * to bypass these if needed.
146 /* Above the top boundary */
147 for (x = x1; x <= x2; x++)
149 new_is_floor = get_is_floor(x, y1 - 1);
151 /* Increment counter if they are different */
152 if (new_is_floor != old_is_floor) count++;
154 old_is_floor = new_is_floor;
158 for (y = y1; y <= y2; y++)
160 new_is_floor = get_is_floor(x2 + 1, y);
162 /* increment counter if they are different */
163 if (new_is_floor != old_is_floor) count++;
165 old_is_floor = new_is_floor;
168 /* Bottom boundary */
169 for (x = x2; x >= x1; x--)
171 new_is_floor = get_is_floor(x, y2 + 1);
173 /* increment counter if they are different */
174 if (new_is_floor != old_is_floor) count++;
176 old_is_floor = new_is_floor;
180 for (y = y2; y >= y1; y--)
182 new_is_floor = get_is_floor(x1 - 1, y);
184 /* increment counter if they are different */
185 if (new_is_floor != old_is_floor) count++;
187 old_is_floor = new_is_floor;
190 /* If all the same, or only one connection exit. */
191 if (count <= 2) return;
194 /* Tunnel around the room so to prevent problems with caves */
195 for (y = y1; y <= y2; y++)
197 for (x = x1; x <= x2; x++)
206 * This function is used to allocate the space needed by a room in the room_map
208 * x, y represent the size of the room (0...x-1) by (0...y-1).
209 * crowded is used to denote a monset nest.
210 * by0, bx0 are the positions in the room_map array given to the build_type'x'
212 * xx, yy are the returned center of the allocated room in coordinates for
213 * cave.feat and cave.info etc.
215 static bool room_alloc(int x, int y, bool crowded, int by0, int bx0, int *xx, int *yy)
217 int temp, bx1, bx2, by1, by2, by, bx;
219 /* Calculate number of room_map squares to allocate */
221 /* temp is total number along width */
222 temp = ((x - 1) / BLOCK_WID) + 1;
224 /* bx2 = ending block */
225 bx2 = temp / 2 + bx0;
227 /* bx1 = starting block (Note: rounding taken care of here.) */
228 bx1 = bx2 + 1 - temp;
230 /* temp is total number along height */
231 temp = ((y - 1) / BLOCK_HGT) + 1;
233 /* by2 = ending block */
234 by2 = temp / 2 + by0;
236 /* by1 = starting block */
237 by1 = by2 + 1 - temp;
240 /* Never run off the screen */
241 if ((by1 < 0) || (by2 >= dun->row_rooms)) return (FALSE);
242 if ((bx1 < 0) || (bx2 >= dun->col_rooms)) return (FALSE);
244 /* Verify open space */
245 for (by = by1; by <= by2; by++)
247 for (bx = bx1; bx <= bx2; bx++)
249 if (dun->room_map[by][bx]) return (FALSE);
253 /* It is *extremely* important that the following calculation */
254 /* be *exactly* correct to prevent memory errors XXX XXX XXX */
256 /* Acquire the location of the room */
257 *yy = ((by1 + by2 + 1) * BLOCK_HGT) / 2;
258 *xx = ((bx1 + bx2 + 1) * BLOCK_WID) / 2;
261 /* Save the room location */
262 if (dun->cent_n < CENT_MAX)
264 dun->cent[dun->cent_n].y = *yy;
265 dun->cent[dun->cent_n].x = *xx;
269 /* Reserve some blocks */
270 for (by = by1; by <= by2; by++)
272 for (bx = bx1; bx <= bx2; bx++)
274 dun->room_map[by][bx] = TRUE;
278 /* Count "crowded" rooms */
279 if (crowded) dun->crowded++;
282 * Hack- See if room will cut off a cavern.
283 * If so, fix by tunneling outside the room in such a way as to connect the caves.
285 check_room_boundary(*xx - x / 2 - 1, *yy - y / 2 - 1,
286 *xx + (x - 1) / 2 + 1, *yy + (y - 1) / 2 + 1);
293 * Room building routines.
299 * 4 -- large room with features
303 * 8 -- greater vaults
305 * 10 -- random vaults
306 * 11 -- circular rooms
308 * 13 -- trapped monster pits
314 * Type 1 -- normal rectangular rooms
316 static void build_type1(int by0, int bx0)
318 int y, x, y2, x2, yval, xval;
319 int y1, x1, xsize, ysize;
325 /* Pick a room size */
334 /* Try to allocate space for room. If fails, exit */
335 if (!room_alloc(xsize + 2, ysize + 2, FALSE, by0, bx0, &xval, &yval)) return;
337 /* Choose lite or dark */
338 light = ((dun_level <= randint1(25)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS));
341 /* Get corner values */
342 y1 = yval - ysize / 2;
343 x1 = xval - xsize / 2;
344 y2 = yval + (ysize - 1) / 2;
345 x2 = xval + (xsize - 1) / 2;
348 /* Place a full floor under the room */
349 for (y = y1 - 1; y <= y2 + 1; y++)
351 for (x = x1 - 1; x <= x2 + 1; x++)
354 place_floor_grid(c_ptr);
355 c_ptr->info |= (CAVE_ROOM);
356 if (light) c_ptr->info |= (CAVE_GLOW);
360 /* Walls around the room */
361 for (y = y1 - 1; y <= y2 + 1; y++)
363 c_ptr = &cave[y][x1 - 1];
364 place_outer_grid(c_ptr);
365 c_ptr = &cave[y][x2 + 1];
366 place_outer_grid(c_ptr);
368 for (x = x1 - 1; x <= x2 + 1; x++)
370 c_ptr = &cave[y1 - 1][x];
371 place_outer_grid(c_ptr);
372 c_ptr = &cave[y2 + 1][x];
373 place_outer_grid(c_ptr);
377 /* Hack -- Occasional pillar room */
380 for (y = y1; y <= y2; y += 2)
382 for (x = x1; x <= x2; x += 2)
385 place_inner_grid(c_ptr);
390 /* Hack -- Occasional room with four pillars */
391 else if (one_in_(20))
393 if ((y1 + 4 < y2) && (x1 + 4 < x2))
395 c_ptr = &cave[y1 + 1][x1 + 1];
396 place_inner_grid(c_ptr);
398 c_ptr = &cave[y1 + 1][x2 - 1];
399 place_inner_grid(c_ptr);
401 c_ptr = &cave[y2 - 1][x1 + 1];
402 place_inner_grid(c_ptr);
404 c_ptr = &cave[y2 - 1][x2 - 1];
405 place_inner_grid(c_ptr);
409 /* Hack -- Occasional ragged-edge room */
410 else if (one_in_(50))
412 for (y = y1 + 2; y <= y2 - 2; y += 2)
414 c_ptr = &cave[y][x1];
415 place_inner_grid(c_ptr);
416 c_ptr = &cave[y][x2];
417 place_inner_grid(c_ptr);
419 for (x = x1 + 2; x <= x2 - 2; x += 2)
421 c_ptr = &cave[y1][x];
422 place_inner_grid(c_ptr);
423 c_ptr = &cave[y2][x];
424 place_inner_grid(c_ptr);
427 /* Hack -- Occasional divided room */
428 else if (one_in_(50))
430 if (randint1(100) < 50)
432 /* Horizontal wall */
433 for (x = x1; x <= x2; x++)
435 place_inner_bold(yval, x);
438 /* Prevent edge of wall from being tunneled */
439 place_solid_bold(yval, x1 - 1);
440 place_solid_bold(yval, x2 + 1);
445 for (y = y1; y <= y2; y++)
447 place_inner_bold(y, xval);
450 /* Prevent edge of wall from being tunneled */
451 place_solid_bold(y1 - 1, xval);
452 place_solid_bold(y2 + 1, xval);
455 place_random_door(yval, xval, TRUE);
461 * Type 2 -- Overlapping rectangular rooms
463 static void build_type2(int by0, int bx0)
465 int y, x, xval, yval;
466 int y1a, x1a, y2a, x2a;
467 int y1b, x1b, y2b, x2b;
472 /* Try to allocate space for room. If fails, exit */
473 if (!room_alloc(25, 11, FALSE, by0, bx0, &xval, &yval)) return;
475 /* Choose lite or dark */
476 light = ((dun_level <= randint1(25)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS));
478 /* Determine extents of the first room */
479 y1a = yval - randint1(4);
480 y2a = yval + randint1(3);
481 x1a = xval - randint1(11);
482 x2a = xval + randint1(10);
484 /* Determine extents of the second room */
485 y1b = yval - randint1(3);
486 y2b = yval + randint1(4);
487 x1b = xval - randint1(10);
488 x2b = xval + randint1(11);
491 /* Place a full floor for room "a" */
492 for (y = y1a - 1; y <= y2a + 1; y++)
494 for (x = x1a - 1; x <= x2a + 1; x++)
497 place_floor_grid(c_ptr);
498 c_ptr->info |= (CAVE_ROOM);
499 if (light) c_ptr->info |= (CAVE_GLOW);
503 /* Place a full floor for room "b" */
504 for (y = y1b - 1; y <= y2b + 1; y++)
506 for (x = x1b - 1; x <= x2b + 1; x++)
509 place_floor_grid(c_ptr);
510 c_ptr->info |= (CAVE_ROOM);
511 if (light) c_ptr->info |= (CAVE_GLOW);
516 /* Place the walls around room "a" */
517 for (y = y1a - 1; y <= y2a + 1; y++)
519 c_ptr = &cave[y][x1a - 1];
520 place_outer_grid(c_ptr);
521 c_ptr = &cave[y][x2a + 1];
522 place_outer_grid(c_ptr);
524 for (x = x1a - 1; x <= x2a + 1; x++)
526 c_ptr = &cave[y1a - 1][x];
527 place_outer_grid(c_ptr);
528 c_ptr = &cave[y2a + 1][x];
529 place_outer_grid(c_ptr);
532 /* Place the walls around room "b" */
533 for (y = y1b - 1; y <= y2b + 1; y++)
535 c_ptr = &cave[y][x1b - 1];
536 place_outer_grid(c_ptr);
537 c_ptr = &cave[y][x2b + 1];
538 place_outer_grid(c_ptr);
540 for (x = x1b - 1; x <= x2b + 1; x++)
542 c_ptr = &cave[y1b - 1][x];
543 place_outer_grid(c_ptr);
544 c_ptr = &cave[y2b + 1][x];
545 place_outer_grid(c_ptr);
550 /* Replace the floor for room "a" */
551 for (y = y1a; y <= y2a; y++)
553 for (x = x1a; x <= x2a; x++)
556 place_floor_grid(c_ptr);
560 /* Replace the floor for room "b" */
561 for (y = y1b; y <= y2b; y++)
563 for (x = x1b; x <= x2b; x++)
566 place_floor_grid(c_ptr);
574 * Type 3 -- Cross shaped rooms
576 * Builds a room at a row, column coordinate
578 * Room "a" runs north/south, and Room "b" runs east/east
579 * So the "central pillar" runs from x1a, y1b to x2a, y2b.
581 * Note that currently, the "center" is always 3x3, but I think that
582 * the code below will work (with "bounds checking") for 5x5, or even
583 * for unsymetric values like 4x3 or 5x3 or 3x4 or 3x5, or even larger.
585 static void build_type3(int by0, int bx0)
587 int y, x, dy, dx, wy, wx;
588 int y1a, x1a, y2a, x2a;
589 int y1b, x1b, y2b, x2b;
595 /* Try to allocate space for room. */
596 if (!room_alloc(25, 11, FALSE, by0, bx0, &xval, &yval)) return;
598 /* Choose lite or dark */
599 light = ((dun_level <= randint1(25)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS));
601 /* For now, always 3x3 */
604 /* Pick max vertical size (at most 4) */
605 dy = rand_range(3, 4);
607 /* Pick max horizontal size (at most 15) */
608 dx = rand_range(3, 11);
611 /* Determine extents of the north/south room */
617 /* Determine extents of the east/west room */
624 /* Place a full floor for room "a" */
625 for (y = y1a - 1; y <= y2a + 1; y++)
627 for (x = x1a - 1; x <= x2a + 1; x++)
630 place_floor_grid(c_ptr);
631 c_ptr->info |= (CAVE_ROOM);
632 if (light) c_ptr->info |= (CAVE_GLOW);
636 /* Place a full floor for room "b" */
637 for (y = y1b - 1; y <= y2b + 1; y++)
639 for (x = x1b - 1; x <= x2b + 1; x++)
642 place_floor_grid(c_ptr);
643 c_ptr->info |= (CAVE_ROOM);
644 if (light) c_ptr->info |= (CAVE_GLOW);
649 /* Place the walls around room "a" */
650 for (y = y1a - 1; y <= y2a + 1; y++)
652 c_ptr = &cave[y][x1a - 1];
653 place_outer_grid(c_ptr);
654 c_ptr = &cave[y][x2a + 1];
655 place_outer_grid(c_ptr);
657 for (x = x1a - 1; x <= x2a + 1; x++)
659 c_ptr = &cave[y1a - 1][x];
660 place_outer_grid(c_ptr);
661 c_ptr = &cave[y2a + 1][x];
662 place_outer_grid(c_ptr);
665 /* Place the walls around room "b" */
666 for (y = y1b - 1; y <= y2b + 1; y++)
668 c_ptr = &cave[y][x1b - 1];
669 place_outer_grid(c_ptr);
670 c_ptr = &cave[y][x2b + 1];
671 place_outer_grid(c_ptr);
673 for (x = x1b - 1; x <= x2b + 1; x++)
675 c_ptr = &cave[y1b - 1][x];
676 place_outer_grid(c_ptr);
677 c_ptr = &cave[y2b + 1][x];
678 place_outer_grid(c_ptr);
682 /* Replace the floor for room "a" */
683 for (y = y1a; y <= y2a; y++)
685 for (x = x1a; x <= x2a; x++)
688 place_floor_grid(c_ptr);
692 /* Replace the floor for room "b" */
693 for (y = y1b; y <= y2b; y++)
695 for (x = x1b; x <= x2b; x++)
698 place_floor_grid(c_ptr);
704 /* Special features (3/4) */
707 /* Large solid middle pillar */
710 for (y = y1b; y <= y2b; y++)
712 for (x = x1a; x <= x2a; x++)
715 place_inner_grid(c_ptr);
721 /* Inner treasure vault */
724 /* Build the vault */
725 for (y = y1b; y <= y2b; y++)
727 c_ptr = &cave[y][x1a];
728 place_inner_grid(c_ptr);
729 c_ptr = &cave[y][x2a];
730 place_inner_grid(c_ptr);
732 for (x = x1a; x <= x2a; x++)
734 c_ptr = &cave[y1b][x];
735 place_inner_grid(c_ptr);
736 c_ptr = &cave[y2b][x];
737 place_inner_grid(c_ptr);
740 /* Place a secret door on the inner room */
743 case 0: place_secret_door(y1b, xval); break;
744 case 1: place_secret_door(y2b, xval); break;
745 case 2: place_secret_door(yval, x1a); break;
746 case 3: place_secret_door(yval, x2a); break;
749 /* Place a treasure in the vault */
750 place_object(yval, xval, 0L);
752 /* Let's guard the treasure well */
753 vault_monsters(yval, xval, randint0(2) + 3);
755 /* Traps naturally */
756 vault_traps(yval, xval, 4, 4, randint0(3) + 2);
764 /* Occasionally pinch the center shut */
767 /* Pinch the east/west sides */
768 for (y = y1b; y <= y2b; y++)
770 if (y == yval) continue;
771 c_ptr = &cave[y][x1a - 1];
772 place_inner_grid(c_ptr);
773 c_ptr = &cave[y][x2a + 1];
774 place_inner_grid(c_ptr);
777 /* Pinch the north/south sides */
778 for (x = x1a; x <= x2a; x++)
780 if (x == xval) continue;
781 c_ptr = &cave[y1b - 1][x];
782 place_inner_grid(c_ptr);
783 c_ptr = &cave[y2b + 1][x];
784 place_inner_grid(c_ptr);
787 /* Sometimes shut using secret doors */
790 place_secret_door(yval, x1a - 1);
791 place_secret_door(yval, x2a + 1);
792 place_secret_door(y1b - 1, xval);
793 place_secret_door(y2b + 1, xval);
797 /* Occasionally put a "plus" in the center */
800 c_ptr = &cave[yval][xval];
801 place_inner_grid(c_ptr);
802 c_ptr = &cave[y1b][xval];
803 place_inner_grid(c_ptr);
804 c_ptr = &cave[y2b][xval];
805 place_inner_grid(c_ptr);
806 c_ptr = &cave[yval][x1a];
807 place_inner_grid(c_ptr);
808 c_ptr = &cave[yval][x2a];
809 place_inner_grid(c_ptr);
812 /* Occasionally put a pillar in the center */
815 c_ptr = &cave[yval][xval];
816 place_inner_grid(c_ptr);
826 * Type 4 -- Large room with inner features
828 * Possible sub-types:
829 * 1 - Just an inner room with one door
830 * 2 - An inner room within an inner room
831 * 3 - An inner room with pillar(s)
832 * 4 - Inner room has a maze
833 * 5 - A set of four inner rooms
835 static void build_type4(int by0, int bx0)
838 int y2, x2, tmp, yval, xval;
843 /* Try to allocate space for room. */
844 if (!room_alloc(25, 11, FALSE, by0, bx0, &xval, &yval)) return;
846 /* Choose lite or dark */
847 light = ((dun_level <= randint1(25)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS));
855 /* Place a full floor under the room */
856 for (y = y1 - 1; y <= y2 + 1; y++)
858 for (x = x1 - 1; x <= x2 + 1; x++)
861 place_floor_grid(c_ptr);
862 c_ptr->info |= (CAVE_ROOM);
863 if (light) c_ptr->info |= (CAVE_GLOW);
868 for (y = y1 - 1; y <= y2 + 1; y++)
870 c_ptr = &cave[y][x1 - 1];
871 place_outer_grid(c_ptr);
872 c_ptr = &cave[y][x2 + 1];
873 place_outer_grid(c_ptr);
875 for (x = x1 - 1; x <= x2 + 1; x++)
877 c_ptr = &cave[y1 - 1][x];
878 place_outer_grid(c_ptr);
879 c_ptr = &cave[y2 + 1][x];
880 place_outer_grid(c_ptr);
890 /* The inner walls */
891 for (y = y1 - 1; y <= y2 + 1; y++)
893 c_ptr = &cave[y][x1 - 1];
894 place_inner_grid(c_ptr);
895 c_ptr = &cave[y][x2 + 1];
896 place_inner_grid(c_ptr);
898 for (x = x1 - 1; x <= x2 + 1; x++)
900 c_ptr = &cave[y1 - 1][x];
901 place_inner_grid(c_ptr);
902 c_ptr = &cave[y2 + 1][x];
903 place_inner_grid(c_ptr);
907 /* Inner room variations */
910 /* Just an inner room with a monster */
913 /* Place a secret door */
916 case 1: place_secret_door(y1 - 1, xval); break;
917 case 2: place_secret_door(y2 + 1, xval); break;
918 case 3: place_secret_door(yval, x1 - 1); break;
919 case 4: place_secret_door(yval, x2 + 1); break;
922 /* Place a monster in the room */
923 vault_monsters(yval, xval, 1);
928 /* Treasure Vault (with a door) */
931 /* Place a secret door */
934 case 1: place_secret_door(y1 - 1, xval); break;
935 case 2: place_secret_door(y2 + 1, xval); break;
936 case 3: place_secret_door(yval, x1 - 1); break;
937 case 4: place_secret_door(yval, x2 + 1); break;
940 /* Place another inner room */
941 for (y = yval - 1; y <= yval + 1; y++)
943 for (x = xval - 1; x <= xval + 1; x++)
945 if ((x == xval) && (y == yval)) continue;
947 place_inner_grid(c_ptr);
951 /* Place a locked door on the inner room */
954 case 1: place_locked_door(yval - 1, xval); break;
955 case 2: place_locked_door(yval + 1, xval); break;
956 case 3: place_locked_door(yval, xval - 1); break;
957 case 4: place_locked_door(yval, xval + 1); break;
960 /* Monsters to guard the "treasure" */
961 vault_monsters(yval, xval, randint1(3) + 2);
964 if (randint0(100) < 80)
966 place_object(yval, xval, 0L);
972 place_random_stairs(yval, xval);
975 /* Traps to protect the treasure */
976 vault_traps(yval, xval, 4, 10, 2 + randint1(3));
981 /* Inner pillar(s). */
984 /* Place a secret door */
987 case 1: place_secret_door(y1 - 1, xval); break;
988 case 2: place_secret_door(y2 + 1, xval); break;
989 case 3: place_secret_door(yval, x1 - 1); break;
990 case 4: place_secret_door(yval, x2 + 1); break;
993 /* Large Inner Pillar */
994 for (y = yval - 1; y <= yval + 1; y++)
996 for (x = xval - 1; x <= xval + 1; x++)
999 place_inner_grid(c_ptr);
1003 /* Occasionally, two more Large Inner Pillars */
1007 for (y = yval - 1; y <= yval + 1; y++)
1009 for (x = xval - 5 - tmp; x <= xval - 3 - tmp; x++)
1011 c_ptr = &cave[y][x];
1012 place_inner_grid(c_ptr);
1014 for (x = xval + 3 + tmp; x <= xval + 5 + tmp; x++)
1016 c_ptr = &cave[y][x];
1017 place_inner_grid(c_ptr);
1022 /* Occasionally, some Inner rooms */
1025 /* Long horizontal walls */
1026 for (x = xval - 5; x <= xval + 5; x++)
1028 c_ptr = &cave[yval - 1][x];
1029 place_inner_grid(c_ptr);
1030 c_ptr = &cave[yval + 1][x];
1031 place_inner_grid(c_ptr);
1034 /* Close off the left/right edges */
1035 c_ptr = &cave[yval][xval - 5];
1036 place_inner_grid(c_ptr);
1037 c_ptr = &cave[yval][xval + 5];
1038 place_inner_grid(c_ptr);
1040 /* Secret doors (random top/bottom) */
1041 place_secret_door(yval - 3 + (randint1(2) * 2), xval - 3);
1042 place_secret_door(yval - 3 + (randint1(2) * 2), xval + 3);
1045 vault_monsters(yval, xval - 2, randint1(2));
1046 vault_monsters(yval, xval + 2, randint1(2));
1049 if (one_in_(3)) place_object(yval, xval - 2, 0L);
1050 if (one_in_(3)) place_object(yval, xval + 2, 0L);
1059 /* Place a secret door */
1060 switch (randint1(4))
1062 case 1: place_secret_door(y1 - 1, xval); break;
1063 case 2: place_secret_door(y2 + 1, xval); break;
1064 case 3: place_secret_door(yval, x1 - 1); break;
1065 case 4: place_secret_door(yval, x2 + 1); break;
1068 /* Maze (really a checkerboard) */
1069 for (y = y1; y <= y2; y++)
1071 for (x = x1; x <= x2; x++)
1075 c_ptr = &cave[y][x];
1076 place_inner_grid(c_ptr);
1081 /* Monsters just love mazes. */
1082 vault_monsters(yval, xval - 5, randint1(3));
1083 vault_monsters(yval, xval + 5, randint1(3));
1085 /* Traps make them entertaining. */
1086 vault_traps(yval, xval - 3, 2, 8, randint1(3));
1087 vault_traps(yval, xval + 3, 2, 8, randint1(3));
1089 /* Mazes should have some treasure too. */
1090 vault_objects(yval, xval, 3);
1095 /* Four small rooms. */
1099 for (y = y1; y <= y2; y++)
1101 c_ptr = &cave[y][xval];
1102 place_inner_grid(c_ptr);
1104 for (x = x1; x <= x2; x++)
1106 c_ptr = &cave[yval][x];
1107 place_inner_grid(c_ptr);
1110 /* Doors into the rooms */
1111 if (randint0(100) < 50)
1113 int i = randint1(10);
1114 place_secret_door(y1 - 1, xval - i);
1115 place_secret_door(y1 - 1, xval + i);
1116 place_secret_door(y2 + 1, xval - i);
1117 place_secret_door(y2 + 1, xval + i);
1121 int i = randint1(3);
1122 place_secret_door(yval + i, x1 - 1);
1123 place_secret_door(yval - i, x1 - 1);
1124 place_secret_door(yval + i, x2 + 1);
1125 place_secret_door(yval - i, x2 + 1);
1128 /* Treasure, centered at the center of the cross */
1129 vault_objects(yval, xval, 2 + randint1(2));
1131 /* Gotta have some monsters. */
1132 vault_monsters(yval + 1, xval - 4, randint1(4));
1133 vault_monsters(yval + 1, xval + 4, randint1(4));
1134 vault_monsters(yval - 1, xval - 4, randint1(4));
1135 vault_monsters(yval - 1, xval + 4, randint1(4));
1144 * The following functions are used to determine if the given monster
1145 * is appropriate for inclusion in a monster nest or monster pit or
1148 * None of the pits/nests are allowed to include "unique" monsters.
1153 * Monster validation macro
1155 * Line 1 -- forbid town monsters
1156 * Line 2 -- forbid uniques
1157 * Line 3 -- forbid aquatic monsters
1159 #define vault_monster_okay(I) \
1160 (mon_hook_dungeon(I) && \
1161 !(r_info[I].flags1 & RF1_UNIQUE) && \
1162 !(r_info[I].flags7 & RF7_UNIQUE2) && \
1163 !(r_info[I].flagsr & RFR_RES_ALL) && \
1164 !(r_info[I].flags7 & RF7_AQUATIC))
1167 /* Race index for "monster pit (clone)" */
1168 static int vault_aux_race;
1170 /* Race index for "monster pit (symbol clone)" */
1171 static char vault_aux_char;
1173 /* Breath mask for "monster pit (dragon)" */
1174 static u32b vault_aux_dragon_mask4;
1178 * Helper monster selection function
1180 static bool vault_aux_simple(int r_idx)
1183 return (vault_monster_okay(r_idx));
1188 * Helper function for "monster nest (jelly)"
1190 static bool vault_aux_jelly(int r_idx)
1192 monster_race *r_ptr = &r_info[r_idx];
1194 /* Validate the monster */
1195 if (!vault_monster_okay(r_idx)) return (FALSE);
1197 if ((r_ptr->flags2 & RF2_KILL_BODY) && !(r_ptr->flags1 & RF1_NEVER_BLOW)) return (FALSE);
1199 /* Also decline evil jellies (like death molds and shoggoths) */
1200 if (r_ptr->flags3 & (RF3_EVIL)) return (FALSE);
1202 /* Require icky thing, jelly, mold, or mushroom */
1203 if (!strchr("ijm,", r_ptr->d_char)) return (FALSE);
1211 * Helper function for "monster nest (animal)"
1213 static bool vault_aux_animal(int r_idx)
1215 monster_race *r_ptr = &r_info[r_idx];
1217 /* Validate the monster */
1218 if (!vault_monster_okay(r_idx)) return (FALSE);
1220 /* Require "animal" flag */
1221 if (!(r_ptr->flags3 & (RF3_ANIMAL))) return (FALSE);
1229 * Helper function for "monster nest (undead)"
1231 static bool vault_aux_undead(int r_idx)
1233 monster_race *r_ptr = &r_info[r_idx];
1235 /* Validate the monster */
1236 if (!vault_monster_okay(r_idx)) return (FALSE);
1238 /* Require Undead */
1239 if (!(r_ptr->flags3 & (RF3_UNDEAD))) return (FALSE);
1247 * Helper function for "monster nest (chapel)"
1249 static bool vault_aux_chapel_g(int r_idx)
1251 static int chapel_list[] = {
1252 MON_NOV_PRIEST, MON_NOV_PALADIN, MON_NOV_PRIEST_G, MON_NOV_PALADIN_G,
1253 MON_PRIEST, MON_JADE_MONK, MON_IVORY_MONK, MON_ULTRA_PALADIN,
1254 MON_EBONY_MONK, MON_W_KNIGHT, MON_KNI_TEMPLAR, MON_PALADIN,
1259 monster_race *r_ptr = &r_info[r_idx];
1261 /* Validate the monster */
1262 if (!vault_monster_okay(r_idx)) return (FALSE);
1264 if (r_ptr->flags3 & (RF3_EVIL)) return (FALSE);
1265 if ((r_idx == MON_A_GOLD) || (r_idx == MON_A_SILVER)) return (FALSE);
1267 /* Require "priest" or Angel */
1269 if (r_ptr->d_char == 'A') return TRUE;
1271 for (i = 0; chapel_list[i]; i++)
1272 if (r_idx == chapel_list[i]) return TRUE;
1279 * Helper function for "monster nest (kennel)"
1281 static bool vault_aux_kennel(int r_idx)
1283 monster_race *r_ptr = &r_info[r_idx];
1285 /* Validate the monster */
1286 if (!vault_monster_okay(r_idx)) return (FALSE);
1288 /* Require a Zephyr Hound or a dog */
1289 if (!strchr("CZ", r_ptr->d_char)) return (FALSE);
1297 * Helper function for "monster nest (mimic)"
1299 static bool vault_aux_mimic(int r_idx)
1301 monster_race *r_ptr = &r_info[r_idx];
1303 /* Validate the monster */
1304 if (!vault_monster_okay(r_idx)) return (FALSE);
1307 if (!strchr("!|$?=", r_ptr->d_char)) return (FALSE);
1314 * Helper function for "monster nest (clone)"
1316 static bool vault_aux_clone(int r_idx)
1318 /* Validate the monster */
1319 if (!vault_monster_okay(r_idx)) return (FALSE);
1321 return (r_idx == vault_aux_race);
1326 * Helper function for "monster nest (symbol clone)"
1328 static bool vault_aux_symbol_e(int r_idx)
1330 monster_race *r_ptr = &r_info[r_idx];
1332 /* Validate the monster */
1333 if (!vault_monster_okay(r_idx)) return (FALSE);
1335 if ((r_ptr->flags2 & RF2_KILL_BODY) && !(r_ptr->flags1 & RF1_NEVER_BLOW)) return (FALSE);
1337 if (r_ptr->flags3 & (RF3_GOOD)) return (FALSE);
1339 /* Decline incorrect symbol */
1340 if (r_ptr->d_char != vault_aux_char) return (FALSE);
1348 * Helper function for "monster nest (symbol clone)"
1350 static bool vault_aux_symbol_g(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 if (r_ptr->flags3 & (RF3_EVIL)) return (FALSE);
1361 /* Decline incorrect symbol */
1362 if (r_ptr->d_char != vault_aux_char) return (FALSE);
1370 * Helper function for "monster pit (orc)"
1372 static bool vault_aux_orc(int r_idx)
1374 monster_race *r_ptr = &r_info[r_idx];
1376 /* Validate the monster */
1377 if (!vault_monster_okay(r_idx)) return (FALSE);
1380 if (!(r_ptr->flags3 & RF3_ORC)) return (FALSE);
1382 /* Decline undead */
1383 if (r_ptr->flags3 & RF3_UNDEAD) return (FALSE);
1391 * Helper function for "monster pit (troll)"
1393 static bool vault_aux_troll(int r_idx)
1395 monster_race *r_ptr = &r_info[r_idx];
1397 /* Validate the monster */
1398 if (!vault_monster_okay(r_idx)) return (FALSE);
1401 if (!(r_ptr->flags3 & RF3_TROLL)) return (FALSE);
1403 /* Decline undead */
1404 if (r_ptr->flags3 & RF3_UNDEAD) return (FALSE);
1412 * Helper function for "monster pit (giant)"
1414 static bool vault_aux_giant(int r_idx)
1416 monster_race *r_ptr = &r_info[r_idx];
1418 /* Validate the monster */
1419 if (!vault_monster_okay(r_idx)) return (FALSE);
1422 if (!(r_ptr->flags3 & RF3_GIANT)) return (FALSE);
1424 if (r_ptr->flags3 & RF3_GOOD) return (FALSE);
1426 /* Decline undead */
1427 if (r_ptr->flags3 & RF3_UNDEAD) return (FALSE);
1435 * Helper function for "monster pit (dragon)"
1437 static bool vault_aux_dragon(int r_idx)
1439 monster_race *r_ptr = &r_info[r_idx];
1441 /* Validate the monster */
1442 if (!vault_monster_okay(r_idx)) return (FALSE);
1444 /* Require dragon */
1445 if (!(r_ptr->flags3 & RF3_DRAGON)) return (FALSE);
1447 /* Hack -- Require correct "breath attack" */
1448 if (r_ptr->flags4 != vault_aux_dragon_mask4) return (FALSE);
1450 /* Decline undead */
1451 if (r_ptr->flags3 & RF3_UNDEAD) return (FALSE);
1459 * Helper function for "monster pit (demon)"
1461 static bool vault_aux_demon(int r_idx)
1463 monster_race *r_ptr = &r_info[r_idx];
1465 /* Validate the monster */
1466 if (!vault_monster_okay(r_idx)) return (FALSE);
1468 if ((r_ptr->flags2 & RF2_KILL_BODY) && !(r_ptr->flags1 & RF1_NEVER_BLOW)) return (FALSE);
1471 if (!(r_ptr->flags3 & RF3_DEMON)) return (FALSE);
1479 * Helper function for "monster pit (lovecraftian)"
1481 static bool vault_aux_cthulhu(int r_idx)
1483 monster_race *r_ptr = &r_info[r_idx];
1485 /* Validate the monster */
1486 if (!vault_monster_okay(r_idx)) return (FALSE);
1488 if ((r_ptr->flags2 & RF2_KILL_BODY) && !(r_ptr->flags1 & RF1_NEVER_BLOW)) return (FALSE);
1490 /* Require eldritch horror */
1491 if (!(r_ptr->flags2 & (RF2_ELDRITCH_HORROR))) return (FALSE);
1499 * Helper function for "monster pit (clone)"
1501 static void vault_prep_clone(void)
1503 /* Apply the monster restriction */
1504 get_mon_num_prep(vault_aux_simple, NULL);
1506 /* Pick a race to clone */
1507 vault_aux_race = get_mon_num(dun_level + 10);
1509 /* Remove the monster restriction */
1510 get_mon_num_prep(NULL, NULL);
1515 * Helper function for "monster pit (symbol clone)"
1517 static void vault_prep_symbol(void)
1521 /* Apply the monster restriction */
1522 get_mon_num_prep(vault_aux_simple, NULL);
1524 /* Pick a race to clone */
1525 r_idx = get_mon_num(dun_level + 10);
1527 /* Remove the monster restriction */
1528 get_mon_num_prep(NULL, NULL);
1530 /* Extract the symbol */
1531 vault_aux_char = r_info[r_idx].d_char;
1536 * Helper function for "monster pit (dragon)"
1538 static void vault_prep_dragon(void)
1540 /* Pick dragon type */
1541 switch (randint0(6))
1546 /* Restrict dragon breath type */
1547 vault_aux_dragon_mask4 = RF4_BR_ACID;
1556 /* Restrict dragon breath type */
1557 vault_aux_dragon_mask4 = RF4_BR_ELEC;
1566 /* Restrict dragon breath type */
1567 vault_aux_dragon_mask4 = RF4_BR_FIRE;
1576 /* Restrict dragon breath type */
1577 vault_aux_dragon_mask4 = RF4_BR_COLD;
1586 /* Restrict dragon breath type */
1587 vault_aux_dragon_mask4 = RF4_BR_POIS;
1596 /* Restrict dragon breath type */
1597 vault_aux_dragon_mask4 = (RF4_BR_ACID | RF4_BR_ELEC |
1598 RF4_BR_FIRE | RF4_BR_COLD |
1609 * Helper function for "monster pit (dark elf)"
1611 static bool vault_aux_dark_elf(int r_idx)
1614 static int dark_elf_list[] =
1616 MON_D_ELF, MON_D_ELF_MAGE, MON_D_ELF_WARRIOR, MON_D_ELF_PRIEST,
1617 MON_D_ELF_LORD, MON_D_ELF_WARLOCK, MON_D_ELF_DRUID, MON_NIGHTBLADE,
1618 MON_D_ELF_SORC, MON_D_ELF_SHADE, 0,
1621 /* Validate the monster */
1622 if (!vault_monster_okay(r_idx)) return FALSE;
1624 /* Require dark elves */
1625 for (i = 0; dark_elf_list[i]; i++)
1626 if (r_idx == dark_elf_list[i]) return TRUE;
1633 typedef struct vault_aux_type vault_aux_type;
1636 struct vault_aux_type
1639 bool (*hook_func)(int r_idx);
1640 void (*prep_func)(void);
1646 static int pick_vault_type(vault_aux_type *l_ptr, s16b allow_flag_mask)
1648 int tmp, total, count;
1650 vault_aux_type *n_ptr;
1652 /* Calculate the total possibilities */
1653 for (n_ptr = l_ptr, total = 0, count = 0; TRUE; n_ptr++, count++)
1656 if (!n_ptr->name) break;
1658 /* Ignore excessive depth */
1659 if (n_ptr->level > dun_level) continue;
1661 /* Not matched with pit/nest flag */
1662 if (!(allow_flag_mask & (1L << count))) continue;
1664 /* Count this possibility */
1665 total += n_ptr->chance * MAX_DEPTH / (MIN(dun_level, MAX_DEPTH - 1) - n_ptr->level + 5);
1668 /* Pick a random type */
1669 tmp = randint0(total);
1671 /* Find this type */
1672 for (n_ptr = l_ptr, total = 0, count = 0; TRUE; n_ptr++, count++)
1675 if (!n_ptr->name) break;
1677 /* Ignore excessive depth */
1678 if (n_ptr->level > dun_level) continue;
1680 /* Not matched with pit/nest flag */
1681 if (!(allow_flag_mask & (1L << count))) continue;
1683 /* Count this possibility */
1684 total += n_ptr->chance * MAX_DEPTH / (MIN(dun_level, MAX_DEPTH - 1) - n_ptr->level + 5);
1686 /* Found the type */
1687 if (tmp < total) break;
1690 return n_ptr->name ? count : -1;
1693 static void build_type6(int by0, int bx0, bool nest);
1694 static void build_type5(int by0, int bx0, bool nest);
1696 static vault_aux_type nest_types[] =
1699 {"¥¯¥í¡¼¥ó", vault_aux_clone, vault_prep_clone, 5, 3},
1700 {"¥¼¥ê¡¼", vault_aux_jelly, NULL, 5, 6},
1701 {"¥·¥ó¥Ü¥ë(Á±)", vault_aux_symbol_g, vault_prep_symbol, 25, 2},
1702 {"¥·¥ó¥Ü¥ë(°)", vault_aux_symbol_e, vault_prep_symbol, 25, 2},
1703 {"¥ß¥ß¥Ã¥¯", vault_aux_mimic, NULL, 30, 4},
1704 {"¶¸µ¤", vault_aux_cthulhu, NULL, 70, 2},
1705 {"¸¤¾®²°", vault_aux_kennel, NULL, 45, 4},
1706 {"ưʪ±à", vault_aux_animal, NULL, 35, 5},
1707 {"¶µ²ñ", vault_aux_chapel_g, NULL, 75, 4},
1708 {"¥¢¥ó¥Ç¥Ã¥É", vault_aux_undead, NULL, 75, 5},
1709 {NULL, NULL, NULL, 0, 0},
1711 {"clone", vault_aux_clone, vault_prep_clone, 5, 3},
1712 {"jelly", vault_aux_jelly, NULL, 5, 6},
1713 {"symbol good", vault_aux_symbol_g, vault_prep_symbol, 25, 2},
1714 {"symbol evil", vault_aux_symbol_e, vault_prep_symbol, 25, 2},
1715 {"mimic", vault_aux_mimic, NULL, 30, 4},
1716 {"lovecraftian", vault_aux_cthulhu, NULL, 70, 2},
1717 {"kennel", vault_aux_kennel, NULL, 45, 4},
1718 {"animal", vault_aux_animal, NULL, 35, 5},
1719 {"chapel", vault_aux_chapel_g, NULL, 75, 4},
1720 {"undead", vault_aux_undead, NULL, 75, 5},
1721 {NULL, NULL, NULL, 0, 0},
1725 static vault_aux_type pit_types[] =
1728 {"¥ª¡¼¥¯", vault_aux_orc, NULL, 5, 6},
1729 {"¥È¥í¥ë", vault_aux_troll, NULL, 20, 6},
1730 {"¥¸¥ã¥¤¥¢¥ó¥È", vault_aux_giant, NULL, 50, 6},
1731 {"¶¸µ¤", vault_aux_cthulhu, NULL, 80, 2},
1732 {"¥·¥ó¥Ü¥ë(Á±)", vault_aux_symbol_g, vault_prep_symbol, 70, 1},
1733 {"¥·¥ó¥Ü¥ë(°)", vault_aux_symbol_e, vault_prep_symbol, 70, 1},
1734 {"¶µ²ñ", vault_aux_chapel_g, NULL, 65, 2},
1735 {"¥É¥é¥´¥ó", vault_aux_dragon, vault_prep_dragon, 70, 6},
1736 {"¥Ç¡¼¥â¥ó", vault_aux_demon, NULL, 80, 6},
1737 {"¥À¡¼¥¯¥¨¥ë¥Õ", vault_aux_dark_elf, NULL, 45, 4},
1738 {NULL, NULL, NULL, 0, 0},
1740 {"orc", vault_aux_orc, NULL, 5, 6},
1741 {"troll", vault_aux_troll, NULL, 20, 6},
1742 {"giant", vault_aux_giant, NULL, 50, 6},
1743 {"lovecraftian", vault_aux_cthulhu, NULL, 80, 2},
1744 {"symbol good", vault_aux_symbol_g, vault_prep_symbol, 70, 1},
1745 {"symbol evil", vault_aux_symbol_e, vault_prep_symbol, 70, 1},
1746 {"chapel", vault_aux_chapel_g, NULL, 65, 2},
1747 {"dragon", vault_aux_dragon, vault_prep_dragon, 70, 6},
1748 {"demon", vault_aux_demon, NULL, 80, 6},
1749 {"dark elf", vault_aux_dark_elf, NULL, 45, 4},
1750 {NULL, NULL, NULL, 0, 0},
1755 /* Nest types code */
1756 #define NEST_TYPE_CLONE 0
1757 #define NEST_TYPE_JELLY 1
1758 #define NEST_TYPE_SYMBOL_GOOD 2
1759 #define NEST_TYPE_SYMBOL_EVIL 3
1760 #define NEST_TYPE_MIMIC 4
1761 #define NEST_TYPE_LOVECRAFTIAN 5
1762 #define NEST_TYPE_KENNEL 6
1763 #define NEST_TYPE_ANIMAL 7
1764 #define NEST_TYPE_CHAPEL 8
1765 #define NEST_TYPE_UNDEAD 9
1767 /* Pit types code */
1768 #define PIT_TYPE_ORC 0
1769 #define PIT_TYPE_TROLL 1
1770 #define PIT_TYPE_GIANT 2
1771 #define PIT_TYPE_LOVECRAFTIAN 3
1772 #define PIT_TYPE_SYMBOL_GOOD 4
1773 #define PIT_TYPE_SYMBOL_EVIL 5
1774 #define PIT_TYPE_CHAPEL 6
1775 #define PIT_TYPE_DRAGON 7
1776 #define PIT_TYPE_DEMON 8
1777 #define PIT_TYPE_DARK_ELF 9
1781 * Hack -- Get the string describing subtype of pit/nest
1782 * Determined in prepare function (some pit/nest only)
1784 static cptr pit_subtype_string(int type, bool nest)
1786 static char inner_buf[256] = "";
1788 inner_buf[0] = '\0'; /* Init string */
1790 if (nest) /* Nests */
1794 case NEST_TYPE_CLONE:
1795 sprintf(inner_buf, "(%s)", r_name + r_info[vault_aux_race].name);
1797 case NEST_TYPE_SYMBOL_GOOD:
1798 case NEST_TYPE_SYMBOL_EVIL:
1799 sprintf(inner_buf, "(%c)", vault_aux_char);
1807 case PIT_TYPE_SYMBOL_GOOD:
1808 case PIT_TYPE_SYMBOL_EVIL:
1809 sprintf(inner_buf, "(%c)", vault_aux_char);
1811 case PIT_TYPE_DRAGON:
1812 switch (vault_aux_dragon_mask4)
1815 case RF4_BR_ACID: strcpy(inner_buf, "(»À)"); break;
1816 case RF4_BR_ELEC: strcpy(inner_buf, "(°ðºÊ)"); break;
1817 case RF4_BR_FIRE: strcpy(inner_buf, "(²Ð±ê)"); break;
1818 case RF4_BR_COLD: strcpy(inner_buf, "(Î䵤)"); break;
1819 case RF4_BR_POIS: strcpy(inner_buf, "(ÆÇ)"); break;
1820 case (RF4_BR_ACID | RF4_BR_ELEC | RF4_BR_FIRE | RF4_BR_COLD | RF4_BR_POIS):
1821 strcpy(inner_buf, "(Ëü¿§)"); break;
1822 default: strcpy(inner_buf, "(̤ÄêµÁ)"); break;
1824 case RF4_BR_ACID: strcpy(inner_buf, "(acid)"); break;
1825 case RF4_BR_ELEC: strcpy(inner_buf, "(lightning)"); break;
1826 case RF4_BR_FIRE: strcpy(inner_buf, "(fire)"); break;
1827 case RF4_BR_COLD: strcpy(inner_buf, "(frost)"); break;
1828 case RF4_BR_POIS: strcpy(inner_buf, "(poison)"); break;
1829 case (RF4_BR_ACID | RF4_BR_ELEC | RF4_BR_FIRE | RF4_BR_COLD | RF4_BR_POIS):
1830 strcpy(inner_buf, "(multi-hued)"); break;
1831 default: strcpy(inner_buf, "(undefined)"); break;
1842 /* A struct for nest monster information with cheat_hear */
1852 * Comp function for sorting nest monster information
1854 static bool ang_sort_comp_nest_mon_info(vptr u, vptr v, int a, int b)
1856 nest_mon_info_type *nest_mon_info = (nest_mon_info_type *)u;
1857 int w1 = nest_mon_info[a].r_idx;
1858 int w2 = nest_mon_info[b].r_idx;
1859 monster_race *r1_ptr = &r_info[w1];
1860 monster_race *r2_ptr = &r_info[w2];
1866 /* Extract used info */
1867 z1 = nest_mon_info[a].used;
1868 z2 = nest_mon_info[b].used;
1870 /* Compare used status */
1871 if (z1 < z2) return FALSE;
1872 if (z1 > z2) return TRUE;
1874 /* Compare levels */
1875 if (r1_ptr->level < r2_ptr->level) return TRUE;
1876 if (r1_ptr->level > r2_ptr->level) return FALSE;
1878 /* Compare experience */
1879 if (r1_ptr->mexp < r2_ptr->mexp) return TRUE;
1880 if (r1_ptr->mexp > r2_ptr->mexp) return FALSE;
1882 /* Compare indexes */
1888 * Swap function for sorting nest monster information
1890 static void ang_sort_swap_nest_mon_info(vptr u, vptr v, int a, int b)
1892 nest_mon_info_type *nest_mon_info = (nest_mon_info_type *)u;
1893 nest_mon_info_type holder;
1899 holder = nest_mon_info[a];
1900 nest_mon_info[a] = nest_mon_info[b];
1901 nest_mon_info[b] = holder;
1905 #define NUM_NEST_MON_TYPE 64
1908 * Type 5 -- Monster nests
1910 * A monster nest is a "big" room, with an "inner" room, containing
1911 * a "collection" of monsters of a given type strewn about the room.
1913 * The monsters are chosen from a set of 64 randomly selected monster
1914 * races, to allow the nest creation to fail instead of having "holes".
1916 * Note the use of the "get_mon_num_prep()" function, and the special
1917 * "get_mon_num_hook()" restriction function, to prepare the "monster
1918 * allocation table" in such a way as to optimize the selection of
1919 * "appropriate" non-unique monsters for the nest.
1921 * Note that the "get_mon_num()" function may (rarely) fail, in which
1922 * case the nest will be empty, and will not affect the level rating.
1924 * Note that "monster nests" will never contain "unique" monsters.
1926 static void build_type5(int by0, int bx0, bool pit)
1928 int y, x, y1, x1, y2, x2, xval, yval;
1930 nest_mon_info_type nest_mon_info[NUM_NEST_MON_TYPE];
1936 int cur_nest_type = pick_vault_type(nest_types, d_info[dungeon_type].nest);
1937 vault_aux_type *n_ptr;
1939 /* Try to allocate space for room. */
1940 if (!room_alloc(25, 11, TRUE, by0, bx0, &xval, &yval)) return;
1942 /* No type available */
1943 if (cur_nest_type < 0)
1948 build_type6(by0, bx0, TRUE);
1953 n_ptr = &nest_types[cur_nest_type];
1955 /* Process a preparation function if necessary */
1956 if (n_ptr->prep_func) (*(n_ptr->prep_func))();
1964 /* Place the floor area */
1965 for (y = y1 - 1; y <= y2 + 1; y++)
1967 for (x = x1 - 1; x <= x2 + 1; x++)
1969 c_ptr = &cave[y][x];
1970 place_floor_grid(c_ptr);
1971 c_ptr->info |= (CAVE_ROOM);
1975 /* Place the outer walls */
1976 for (y = y1 - 1; y <= y2 + 1; y++)
1978 c_ptr = &cave[y][x1 - 1];
1979 place_outer_grid(c_ptr);
1980 c_ptr = &cave[y][x2 + 1];
1981 place_outer_grid(c_ptr);
1983 for (x = x1 - 1; x <= x2 + 1; x++)
1985 c_ptr = &cave[y1 - 1][x];
1986 place_outer_grid(c_ptr);
1987 c_ptr = &cave[y2 + 1][x];
1988 place_outer_grid(c_ptr);
1992 /* Advance to the center room */
1998 /* The inner walls */
1999 for (y = y1 - 1; y <= y2 + 1; y++)
2001 c_ptr = &cave[y][x1 - 1];
2002 place_inner_grid(c_ptr);
2003 c_ptr = &cave[y][x2 + 1];
2004 place_inner_grid(c_ptr);
2007 for (x = x1 - 1; x <= x2 + 1; x++)
2009 c_ptr = &cave[y1 - 1][x];
2010 place_inner_grid(c_ptr);
2011 c_ptr = &cave[y2 + 1][x];
2012 place_inner_grid(c_ptr);
2014 for (y = y1; y <= y2; y++)
2016 for (x = x1; x <= x2; x++)
2018 add_cave_info(y, x, CAVE_ICKY);
2023 /* Place a secret door */
2024 switch (randint1(4))
2026 case 1: place_secret_door(y1 - 1, xval); break;
2027 case 2: place_secret_door(y2 + 1, xval); break;
2028 case 3: place_secret_door(yval, x1 - 1); break;
2029 case 4: place_secret_door(yval, x2 + 1); break;
2033 /* Prepare allocation table */
2034 get_mon_num_prep(n_ptr->hook_func, NULL);
2036 align.sub_align = SUB_ALIGN_NEUTRAL;
2038 /* Pick some monster types */
2039 for (i = 0; i < NUM_NEST_MON_TYPE; i++)
2041 int r_idx = 0, attempts = 100;
2042 monster_race *r_ptr = NULL;
2046 /* Get a (hard) monster type */
2047 r_idx = get_mon_num(dun_level + 10);
2048 r_ptr = &r_info[r_idx];
2050 /* Decline incorrect alignment */
2051 if (monster_has_hostile_align(&align, 0, 0, r_ptr)) continue;
2053 /* Accept this monster */
2057 /* Notice failure */
2058 if (!r_idx || !attempts) return;
2060 /* Note the alignment */
2061 if (r_ptr->flags3 & RF3_EVIL) align.sub_align |= SUB_ALIGN_EVIL;
2062 if (r_ptr->flags3 & RF3_GOOD) align.sub_align |= SUB_ALIGN_GOOD;
2064 nest_mon_info[i].r_idx = r_idx;
2065 nest_mon_info[i].used = FALSE;
2073 msg_format("¥â¥ó¥¹¥¿¡¼Éô²°(nest)(%s%s)", n_ptr->name, pit_subtype_string(cur_nest_type, TRUE));
2075 msg_format("Monster nest (%s%s)", n_ptr->name, pit_subtype_string(cur_nest_type, TRUE));
2079 /* Increase the level rating */
2082 /* (Sometimes) Cause a "special feeling" (for "Monster Nests") */
2083 if ((dun_level <= 40) && (randint1(dun_level * dun_level + 50) < 300))
2085 good_item_flag = TRUE;
2088 /* Place some monsters */
2089 for (y = yval - 2; y <= yval + 2; y++)
2091 for (x = xval - 9; x <= xval + 9; x++)
2095 i = randint0(NUM_NEST_MON_TYPE);
2096 r_idx = nest_mon_info[i].r_idx;
2098 /* Place that "random" monster (no groups) */
2099 (void)place_monster_aux(0, y, x, r_idx, 0L);
2101 nest_mon_info[i].used = TRUE;
2105 if (cheat_room && cheat_hear)
2107 ang_sort_comp = ang_sort_comp_nest_mon_info;
2108 ang_sort_swap = ang_sort_swap_nest_mon_info;
2109 ang_sort(nest_mon_info, NULL, NUM_NEST_MON_TYPE);
2111 /* Dump the entries (prevent multi-printing) */
2112 for (i = 0; i < NUM_NEST_MON_TYPE; i++)
2114 if (!nest_mon_info[i].used) break;
2115 for (; i < NUM_NEST_MON_TYPE - 1; i++)
2117 if (nest_mon_info[i].r_idx != nest_mon_info[i + 1].r_idx) break;
2118 if (!nest_mon_info[i + 1].used) break;
2120 msg_print(r_name + r_info[nest_mon_info[i].r_idx].name);
2127 * Type 6 -- Monster pits
2129 * A monster pit is a "big" room, with an "inner" room, containing
2130 * a "collection" of monsters of a given type organized in the room.
2132 * The inside room in a monster pit appears as shown below, where the
2133 * actual monsters in each location depend on the type of the pit
2135 * #####################
2136 * #0000000000000000000#
2137 * #0112233455543322110#
2138 * #0112233467643322110#
2139 * #0112233455543322110#
2140 * #0000000000000000000#
2141 * #####################
2143 * Note that the monsters in the pit are now chosen by using "get_mon_num()"
2144 * to request 16 "appropriate" monsters, sorting them by level, and using
2145 * the "even" entries in this sorted list for the contents of the pit.
2147 * Hack -- all of the "dragons" in a "dragon" pit must be the same "color",
2148 * which is handled by requiring a specific "breath" attack for all of the
2149 * dragons. This may include "multi-hued" breath. Note that "wyrms" may
2150 * be present in many of the dragon pits, if they have the proper breath.
2152 * Note the use of the "get_mon_num_prep()" function, and the special
2153 * "get_mon_num_hook()" restriction function, to prepare the "monster
2154 * allocation table" in such a way as to optimize the selection of
2155 * "appropriate" non-unique monsters for the pit.
2157 * Note that the "get_mon_num()" function may (rarely) fail, in which case
2158 * the pit will be empty, and will not effect the level rating.
2160 * Note that "monster pits" will never contain "unique" monsters.
2162 static void build_type6(int by0, int bx0, bool nest)
2164 int y, x, y1, x1, y2, x2, xval, yval;
2173 int cur_pit_type = pick_vault_type(pit_types, d_info[dungeon_type].pit);
2174 vault_aux_type *n_ptr;
2176 /* Try to allocate space for room. */
2177 if (!room_alloc(25, 11, TRUE, by0, bx0, &xval, &yval)) return;
2179 /* No type available */
2180 if (cur_pit_type < 0)
2185 build_type5(by0, bx0, TRUE);
2190 n_ptr = &pit_types[cur_pit_type];
2192 /* Process a preparation function if necessary */
2193 if (n_ptr->prep_func) (*(n_ptr->prep_func))();
2201 /* Place the floor area */
2202 for (y = y1 - 1; y <= y2 + 1; y++)
2204 for (x = x1 - 1; x <= x2 + 1; x++)
2206 c_ptr = &cave[y][x];
2207 place_floor_grid(c_ptr);
2208 c_ptr->info |= (CAVE_ROOM);
2212 /* Place the outer walls */
2213 for (y = y1 - 1; y <= y2 + 1; y++)
2215 c_ptr = &cave[y][x1 - 1];
2216 place_outer_grid(c_ptr);
2217 c_ptr = &cave[y][x2 + 1];
2218 place_outer_grid(c_ptr);
2220 for (x = x1 - 1; x <= x2 + 1; x++)
2222 c_ptr = &cave[y1 - 1][x];
2223 place_outer_grid(c_ptr);
2224 c_ptr = &cave[y2 + 1][x];
2225 place_outer_grid(c_ptr);
2228 /* Advance to the center room */
2234 /* The inner walls */
2235 for (y = y1 - 1; y <= y2 + 1; y++)
2237 c_ptr = &cave[y][x1 - 1];
2238 place_inner_grid(c_ptr);
2239 c_ptr = &cave[y][x2 + 1];
2240 place_inner_grid(c_ptr);
2242 for (x = x1 - 1; x <= x2 + 1; x++)
2244 c_ptr = &cave[y1 - 1][x];
2245 place_inner_grid(c_ptr);
2246 c_ptr = &cave[y2 + 1][x];
2247 place_inner_grid(c_ptr);
2249 for (y = y1; y <= y2; y++)
2251 for (x = x1; x <= x2; x++)
2253 add_cave_info(y, x, CAVE_ICKY);
2257 /* Place a secret door */
2258 switch (randint1(4))
2260 case 1: place_secret_door(y1 - 1, xval); break;
2261 case 2: place_secret_door(y2 + 1, xval); break;
2262 case 3: place_secret_door(yval, x1 - 1); break;
2263 case 4: place_secret_door(yval, x2 + 1); break;
2267 /* Prepare allocation table */
2268 get_mon_num_prep(n_ptr->hook_func, NULL);
2270 align.sub_align = SUB_ALIGN_NEUTRAL;
2272 /* Pick some monster types */
2273 for (i = 0; i < 16; i++)
2275 int r_idx = 0, attempts = 100;
2276 monster_race *r_ptr = NULL;
2280 /* Get a (hard) monster type */
2281 r_idx = get_mon_num(dun_level + 10);
2282 r_ptr = &r_info[r_idx];
2284 /* Decline incorrect alignment */
2285 if (monster_has_hostile_align(&align, 0, 0, r_ptr)) continue;
2287 /* Accept this monster */
2291 /* Notice failure */
2292 if (!r_idx || !attempts) return;
2294 /* Note the alignment */
2295 if (r_ptr->flags3 & RF3_EVIL) align.sub_align |= SUB_ALIGN_EVIL;
2296 if (r_ptr->flags3 & RF3_GOOD) align.sub_align |= SUB_ALIGN_GOOD;
2301 /* Sort the entries */
2302 for (i = 0; i < 16 - 1; i++)
2304 /* Sort the entries */
2305 for (j = 0; j < 16 - 1; j++)
2310 int p1 = r_info[what[i1]].level;
2311 int p2 = r_info[what[i2]].level;
2317 what[i1] = what[i2];
2328 msg_format("¥â¥ó¥¹¥¿¡¼Éô²°(pit)(%s%s)", n_ptr->name, pit_subtype_string(cur_pit_type, FALSE));
2330 msg_format("Monster pit (%s%s)", n_ptr->name, pit_subtype_string(cur_pit_type, FALSE));
2334 /* Select the entries */
2335 for (i = 0; i < 8; i++)
2337 /* Every other entry */
2338 what[i] = what[i * 2];
2343 msg_print(r_name + r_info[what[i]].name);
2347 /* Increase the level rating */
2350 /* (Sometimes) Cause a "special feeling" (for "Monster Pits") */
2351 if ((dun_level <= 40) && (randint1(dun_level * dun_level + 50) < 300))
2353 good_item_flag = TRUE;
2356 /* Top and bottom rows */
2357 for (x = xval - 9; x <= xval + 9; x++)
2359 place_monster_aux(0, yval - 2, x, what[0], PM_NO_KAGE);
2360 place_monster_aux(0, yval + 2, x, what[0], PM_NO_KAGE);
2363 /* Middle columns */
2364 for (y = yval - 1; y <= yval + 1; y++)
2366 place_monster_aux(0, y, xval - 9, what[0], PM_NO_KAGE);
2367 place_monster_aux(0, y, xval + 9, what[0], PM_NO_KAGE);
2369 place_monster_aux(0, y, xval - 8, what[1], PM_NO_KAGE);
2370 place_monster_aux(0, y, xval + 8, what[1], PM_NO_KAGE);
2372 place_monster_aux(0, y, xval - 7, what[1], PM_NO_KAGE);
2373 place_monster_aux(0, y, xval + 7, what[1], PM_NO_KAGE);
2375 place_monster_aux(0, y, xval - 6, what[2], PM_NO_KAGE);
2376 place_monster_aux(0, y, xval + 6, what[2], PM_NO_KAGE);
2378 place_monster_aux(0, y, xval - 5, what[2], PM_NO_KAGE);
2379 place_monster_aux(0, y, xval + 5, what[2], PM_NO_KAGE);
2381 place_monster_aux(0, y, xval - 4, what[3], PM_NO_KAGE);
2382 place_monster_aux(0, y, xval + 4, what[3], PM_NO_KAGE);
2384 place_monster_aux(0, y, xval - 3, what[3], PM_NO_KAGE);
2385 place_monster_aux(0, y, xval + 3, what[3], PM_NO_KAGE);
2387 place_monster_aux(0, y, xval - 2, what[4], PM_NO_KAGE);
2388 place_monster_aux(0, y, xval + 2, what[4], PM_NO_KAGE);
2391 /* Above/Below the center monster */
2392 for (x = xval - 1; x <= xval + 1; x++)
2394 place_monster_aux(0, yval + 1, x, what[5], PM_NO_KAGE);
2395 place_monster_aux(0, yval - 1, x, what[5], PM_NO_KAGE);
2398 /* Next to the center monster */
2399 place_monster_aux(0, yval, xval + 1, what[6], PM_NO_KAGE);
2400 place_monster_aux(0, yval, xval - 1, what[6], PM_NO_KAGE);
2402 /* Center monster */
2403 place_monster_aux(0, yval, xval, what[7], PM_NO_KAGE);
2407 /* coordinate translation code */
2408 static void coord_trans(int *x, int *y, int xoffset, int yoffset, int transno)
2414 * transno specifies what transformation is required. (0-7)
2415 * The lower two bits indicate by how much the vault is rotated,
2416 * and the upper bit indicates a reflection.
2417 * This is done by using rotation matrices... however since
2418 * these are mostly zeros for rotations by 90 degrees this can
2419 * be expressed simply in terms of swapping and inverting the
2420 * x and y coordinates.
2422 for (i = 0; i <= transno % 4; i++)
2424 /* rotate by 90 degrees */
2432 /* Reflect depending on status of 3rd bit. */
2436 /* Add offsets so vault stays in the first quadrant */
2443 * Hack -- fill in "vault" rooms
2445 static void build_vault(int yval, int xval, int ymax, int xmax, cptr data,
2446 int xoffset, int yoffset, int transno)
2448 int dx, dy, x, y, i, j;
2455 /* Place dungeon features and objects */
2456 for (t = data, dy = 0; dy < ymax; dy++)
2458 for (dx = 0; dx < xmax; dx++, t++)
2460 /* prevent loop counter from being overwritten */
2465 coord_trans(&i, &j, xoffset, yoffset, transno);
2467 /* Extract the location */
2470 /* no swap of x/y */
2471 x = xval - (xmax / 2) + i;
2472 y = yval - (ymax / 2) + j;
2477 x = xval - (ymax / 2) + i;
2478 y = yval - (xmax / 2) + j;
2481 /* Hack -- skip "non-grids" */
2482 if (*t == ' ') continue;
2484 /* Access the grid */
2485 c_ptr = &cave[y][x];
2487 /* Lay down a floor */
2488 place_floor_grid(c_ptr);
2490 /* Remove any mimic */
2493 /* Part of a vault */
2494 c_ptr->info |= (CAVE_ROOM | CAVE_ICKY);
2496 /* Analyze the grid */
2499 /* Granite wall (outer) */
2501 place_outer_noperm_grid(c_ptr);
2504 /* Granite wall (inner) */
2506 place_inner_grid(c_ptr);
2509 /* Permanent wall (inner) */
2511 c_ptr->feat = FEAT_PERM_INNER;
2512 c_ptr->info &= ~(CAVE_MASK);
2513 c_ptr->info |= CAVE_INNER;
2518 if (randint0(100) < 75)
2520 place_object(y, x, 0L);
2530 place_secret_door(y, x);
2538 /* Black market in a dungeon */
2540 set_cave_feat(y, x, FEAT_SHOP_HEAD + STORE_BLACK);
2541 store_init(NO_TOWN, STORE_BLACK);
2546 set_cave_feat(y, x, FEAT_PATTERN_START);
2550 set_cave_feat(y, x, FEAT_PATTERN_1);
2554 set_cave_feat(y, x, FEAT_PATTERN_2);
2558 set_cave_feat(y, x, FEAT_PATTERN_3);
2562 set_cave_feat(y, x, FEAT_PATTERN_4);
2566 set_cave_feat(y, x, FEAT_PATTERN_END);
2570 set_cave_feat(y, x, FEAT_PATTERN_XTRA1);
2574 /* Reward for Pattern walk */
2575 object_level = base_level + 12;
2576 place_object(y, x, AM_GOOD | AM_GREAT);
2577 object_level = base_level;
2584 /* Place dungeon monsters and objects */
2585 for (t = data, dy = 0; dy < ymax; dy++)
2587 for (dx = 0; dx < xmax; dx++, t++)
2589 /* prevent loop counter from being overwritten */
2594 coord_trans(&i, &j, xoffset, yoffset, transno);
2596 /* Extract the location */
2599 /* no swap of x/y */
2600 x = xval - (xmax / 2) + i;
2601 y = yval - (ymax / 2) + j;
2606 x = xval - (ymax / 2) + i;
2607 y = yval - (xmax / 2) + j;
2610 /* Hack -- skip "non-grids" */
2611 if (*t == ' ') continue;
2613 /* Analyze the symbol */
2619 monster_level = base_level + 5;
2620 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
2621 monster_level = base_level;
2625 /* Meaner monster */
2628 monster_level = base_level + 11;
2629 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
2630 monster_level = base_level;
2634 /* Meaner monster, plus treasure */
2637 monster_level = base_level + 9;
2638 place_monster(y, x, PM_ALLOW_SLEEP);
2639 monster_level = base_level;
2640 object_level = base_level + 7;
2641 place_object(y, x, AM_GOOD);
2642 object_level = base_level;
2646 /* Nasty monster and treasure */
2649 monster_level = base_level + 40;
2650 place_monster(y, x, PM_ALLOW_SLEEP);
2651 monster_level = base_level;
2652 object_level = base_level + 20;
2653 place_object(y, x, AM_GOOD | AM_GREAT);
2654 object_level = base_level;
2658 /* Monster and/or object */
2661 if (randint0(100) < 50)
2663 monster_level = base_level + 3;
2664 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
2665 monster_level = base_level;
2667 if (randint0(100) < 50)
2669 object_level = base_level + 7;
2670 place_object(y, x, 0L);
2671 object_level = base_level;
2683 * Type 7 -- simple vaults (see "v_info.txt")
2685 static void build_type7(int by0, int bx0)
2687 vault_type *v_ptr = NULL;
2691 int xoffset, yoffset;
2694 /* Pick a lesser vault */
2695 while (dummy < SAFE_MAX_ATTEMPTS)
2699 /* Access a random vault record */
2700 v_ptr = &v_info[randint0(max_v_idx)];
2702 /* Accept the first lesser vault */
2703 if (v_ptr->typ == 7) break;
2706 /* No lesser vault found */
2709 /* pick type of transformation (0-7) */
2710 transno = randint0(8);
2712 /* calculate offsets */
2716 coord_trans(&x, &y, 0, 0, transno);
2736 /* Try to allocate space for room. */
2737 if (!room_alloc(abs(x), abs(y), FALSE, by0, bx0, &xval, &yval)) return;
2739 if (dummy >= SAFE_MAX_ATTEMPTS)
2744 msg_print("·Ù¹ð¡ª¾®¤µ¤ÊÃϲ¼¼¼¤òÇÛÃ֤Ǥ¤Þ¤»¤ó¡ª");
2746 msg_print("Warning! Could not place lesser vault!");
2759 if (cheat_room) msg_format("%s", v_name + v_ptr->name);
2761 /* Boost the rating */
2762 rating += v_ptr->rat;
2764 /* (Sometimes) Cause a special feeling */
2765 if ((dun_level <= 50) ||
2766 (randint1((dun_level - 40) * (dun_level - 40) + 50) < 400))
2768 good_item_flag = TRUE;
2771 /* Hack -- Build the vault */
2772 build_vault(yval, xval, v_ptr->hgt, v_ptr->wid,
2773 v_text + v_ptr->text, xoffset, yoffset, transno);
2778 * Type 8 -- greater vaults (see "v_info.txt")
2780 static void build_type8(int by0, int bx0)
2782 vault_type *v_ptr = NULL;
2787 int xoffset, yoffset;
2789 /* Pick a greater vault */
2790 while (dummy < SAFE_MAX_ATTEMPTS)
2794 /* Access a random vault record */
2795 v_ptr = &v_info[randint0(max_v_idx)];
2797 /* Accept the first greater vault */
2798 if (v_ptr->typ == 8) break;
2801 /* No greater vault found */
2804 /* pick type of transformation (0-7) */
2805 transno = randint0(8);
2807 /* calculate offsets */
2811 coord_trans(&x, &y, 0, 0, transno);
2832 * Try to allocate space for room. If fails, exit
2834 * Hack -- Prepare a bit larger space (+2, +2) to
2835 * prevent generation of vaults with no-entrance.
2837 if (!room_alloc(abs(x) + 2, abs(y) + 2, FALSE, by0, bx0, &xval, &yval)) return;
2839 if (dummy >= SAFE_MAX_ATTEMPTS)
2844 msg_print("·Ù¹ð¡ªµðÂç¤ÊÃϲ¼¼¼¤òÇÛÃ֤Ǥ¤Þ¤»¤ó¡ª");
2846 msg_print("Warning! Could not place greater vault!");
2855 v_ptr = &v_info[76 + randint1(3)];
2859 if (cheat_room) msg_format("%s", v_name + v_ptr->name);
2861 /* Boost the rating */
2862 rating += v_ptr->rat;
2864 /* (Sometimes) Cause a special feeling */
2865 if ((dun_level <= 50) ||
2866 (randint1((dun_level - 40) * (dun_level - 40) + 50) < 400))
2868 good_item_flag = TRUE;
2871 /* Hack -- Build the vault */
2872 build_vault(yval, xval, v_ptr->hgt, v_ptr->wid,
2873 v_text + v_ptr->text, xoffset, yoffset, transno);
2877 * Structure to hold all "fill" data
2880 typedef struct fill_data_type fill_data_type;
2882 struct fill_data_type
2895 /* features to fill with */
2904 /* number of filled squares */
2908 static fill_data_type fill_data;
2911 /* Store routine for the fractal cave generator */
2912 /* this routine probably should be an inline function or a macro. */
2913 static void store_height(int x, int y, int val)
2915 /* if on boundary set val > cutoff so walls are not as square */
2916 if (((x == fill_data.xmin) || (y == fill_data.ymin) ||
2917 (x == fill_data.xmax) || (y == fill_data.ymax)) &&
2918 (val <= fill_data.c1)) val = fill_data.c1 + 1;
2920 /* store the value in height-map format */
2921 cave[y][x].feat = val;
2928 * Explanation of the plasma fractal algorithm:
2930 * A grid of points is created with the properties of a 'height-map'
2931 * This is done by making the corners of the grid have a random value.
2932 * The grid is then subdivided into one with twice the resolution.
2933 * The new points midway between two 'known' points can be calculated
2934 * by taking the average value of the 'known' ones and randomly adding
2935 * or subtracting an amount proportional to the distance between those
2936 * points. The final 'middle' points of the grid are then calculated
2937 * by averaging all four of the originally 'known' corner points. An
2938 * random amount is added or subtracted from this to get a value of the
2939 * height at that point. The scaling factor here is adjusted to the
2940 * slightly larger distance diagonally as compared to orthogonally.
2942 * This is then repeated recursively to fill an entire 'height-map'
2943 * A rectangular map is done the same way, except there are different
2944 * scaling factors along the x and y directions.
2946 * A hack to change the amount of correlation between points is done using
2947 * the grd variable. If the current step size is greater than grd then
2948 * the point will be random, otherwise it will be calculated by the
2949 * above algorithm. This makes a maximum distance at which two points on
2950 * the height map can affect each other.
2952 * How fractal caves are made:
2954 * When the map is complete, a cut-off value is used to create a cave.
2955 * Heights below this value are "floor", and heights above are "wall".
2956 * This also can be used to create lakes, by adding more height levels
2957 * representing shallow and deep water/ lava etc.
2959 * The grd variable affects the width of passages.
2960 * The roug variable affects the roughness of those passages
2962 * The tricky part is making sure the created cave is connected. This
2963 * is done by 'filling' from the inside and only keeping the 'filled'
2964 * floor. Walls bounding the 'filled' floor are also kept. Everything
2965 * else is converted to the normal granite FEAT_WALL_EXTRA.
2970 * Note that this uses the cave.feat array in a very hackish way
2971 * the values are first set to zero, and then each array location
2972 * is used as a "heightmap"
2973 * The heightmap then needs to be converted back into the "feat" format.
2975 * grd=level at which fractal turns on. smaller gives more mazelike caves
2976 * roug=roughness level. 16=normal. higher values make things more convoluted
2977 * small values are good for smooth walls.
2978 * size=length of the side of the square cave system.
2980 static void generate_hmap(int y0, int x0, int xsiz, int ysiz, int grd, int roug, int cutoff)
2982 int xhsize, yhsize, xsize, ysize, maxsize;
2985 * fixed point variables- these are stored as 256 x normal value
2986 * this gives 8 binary places of fractional part + 8 places of normal part
2989 u16b xstep, xhstep, ystep, yhstep;
2990 u16b xstep2, xhstep2, ystep2, yhstep2;
2991 u16b i, j, ii, jj, diagsize, xxsize, yysize;
2993 /* Cache for speed */
2994 u16b xm, xp, ym, yp;
2996 /* redefine size so can change the value if out of range */
3000 /* Paranoia about size of the system of caves */
3001 if (xsize > 254) xsize = 254;
3002 if (xsize < 4) xsize = 4;
3003 if (ysize > 254) ysize = 254;
3004 if (ysize < 4) ysize = 4;
3006 /* get offsets to middle of array */
3010 /* fix rounding problem */
3014 /* get limits of region */
3015 fill_data.xmin = x0 - xhsize;
3016 fill_data.ymin = y0 - yhsize;
3017 fill_data.xmax = x0 + xhsize;
3018 fill_data.ymax = y0 + yhsize;
3020 /* Store cutoff in global for quick access */
3021 fill_data.c1 = cutoff;
3024 * Scale factor for middle points:
3025 * About sqrt(2) * 256 - correct for a square lattice
3026 * approximately correct for everything else.
3030 /* maximum of xsize and ysize */
3031 maxsize = (xsize > ysize) ? xsize : ysize;
3033 /* Clear the section */
3034 for (i = 0; i <= xsize; i++)
3036 for (j = 0; j <= ysize; j++)
3038 /* 255 is a flag for "not done yet" */
3039 cave[(int)(fill_data.ymin + j)][(int)(fill_data.xmin + i)].feat = 255;
3040 /* Clear icky flag because may be redoing the cave */
3041 cave[(int)(fill_data.ymin + j)][(int)(fill_data.xmin + i)].info &= ~(CAVE_ICKY);
3045 /* Boundaries are walls */
3046 cave[fill_data.ymin][fill_data.xmin].feat = maxsize;
3047 cave[fill_data.ymax][fill_data.xmin].feat = maxsize;
3048 cave[fill_data.ymin][fill_data.xmax].feat = maxsize;
3049 cave[fill_data.ymax][fill_data.xmax].feat = maxsize;
3051 /* Set the middle square to be an open area. */
3052 cave[y0][x0].feat = 0;
3054 /* Initialize the step sizes */
3055 xstep = xhstep = xsize * 256;
3056 ystep = yhstep = ysize * 256;
3057 xxsize = xsize * 256;
3058 yysize = ysize * 256;
3061 * Fill in the rectangle with fractal height data -
3062 * like the 'plasma fractal' in fractint.
3064 while ((xhstep > 256) || (yhstep > 256))
3066 /* Halve the step sizes */
3072 /* cache well used values */
3073 xstep2 = xstep / 256;
3074 ystep2 = ystep / 256;
3076 xhstep2 = xhstep / 256;
3077 yhstep2 = yhstep / 256;
3079 /* middle top to bottom. */
3080 for (i = xhstep; i <= xxsize - xhstep; i += xstep)
3082 for (j = 0; j <= yysize; j += ystep)
3084 /* cache often used values */
3085 ii = i / 256 + fill_data.xmin;
3086 jj = j / 256 + fill_data.ymin;
3089 if (cave[jj][ii].feat == 255)
3093 /* If greater than 'grid' level then is random */
3094 store_height(ii, jj, randint1(maxsize));
3098 /* Average of left and right points +random bit */
3099 store_height(ii, jj,
3100 (cave[jj][fill_data.xmin + (i - xhstep) / 256].feat
3101 + cave[jj][fill_data.xmin + (i + xhstep) / 256].feat) / 2
3102 + (randint1(xstep2) - xhstep2) * roug / 16);
3109 /* middle left to right. */
3110 for (j = yhstep; j <= yysize - yhstep; j += ystep)
3112 for (i = 0; i <= xxsize; i += xstep)
3114 /* cache often used values */
3115 ii = i / 256 + fill_data.xmin;
3116 jj = j / 256 + fill_data.ymin;
3119 if (cave[jj][ii].feat == 255)
3123 /* If greater than 'grid' level then is random */
3124 store_height(ii, jj, randint1(maxsize));
3128 /* Average of up and down points +random bit */
3129 store_height(ii, jj,
3130 (cave[fill_data.ymin + (j - yhstep) / 256][ii].feat
3131 + cave[fill_data.ymin + (j + yhstep) / 256][ii].feat) / 2
3132 + (randint1(ystep2) - yhstep2) * roug / 16);
3139 for (i = xhstep; i <= xxsize - xhstep; i += xstep)
3141 for (j = yhstep; j <= yysize - yhstep; j += ystep)
3143 /* cache often used values */
3144 ii = i / 256 + fill_data.xmin;
3145 jj = j / 256 + fill_data.ymin;
3148 if (cave[jj][ii].feat == 255)
3152 /* If greater than 'grid' level then is random */
3153 store_height(ii, jj, randint1(maxsize));
3157 /* Cache reused values. */
3158 xm = fill_data.xmin + (i - xhstep) / 256;
3159 xp = fill_data.xmin + (i + xhstep) / 256;
3160 ym = fill_data.ymin + (j - yhstep) / 256;
3161 yp = fill_data.ymin + (j + yhstep) / 256;
3164 * Average over all four corners + scale by diagsize to
3165 * reduce the effect of the square grid on the shape of the fractal
3167 store_height(ii, jj,
3168 (cave[ym][xm].feat + cave[yp][xm].feat
3169 + cave[ym][xp].feat + cave[yp][xp].feat) / 4
3170 + (randint1(xstep2) - xhstep2) * (diagsize / 16) / 256 * roug);
3179 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)
3182 * function used to convert from height-map back to the
3183 * normal angband cave format
3185 if (cave[y][x].info & CAVE_ICKY)
3192 /* Show that have looked at this square */
3193 cave[y][x].info|= (CAVE_ICKY);
3195 /* Use cutoffs c1-c3 to allocate regions of floor /water/ lava etc. */
3196 if (cave[y][x].feat <= c1)
3198 /* 25% of the time use the other tile : it looks better this way */
3199 if (randint1(100) < 75)
3201 cave[y][x].feat = feat1;
3202 cave[y][x].info &= ~(CAVE_MASK);
3203 cave[y][x].info |= info1;
3208 cave[y][x].feat = feat2;
3209 cave[y][x].info &= ~(CAVE_MASK);
3210 cave[y][x].info |= info2;
3214 else if (cave[y][x].feat <= c2)
3216 /* 25% of the time use the other tile : it looks better this way */
3217 if (randint1(100) < 75)
3219 cave[y][x].feat = feat2;
3220 cave[y][x].info &= ~(CAVE_MASK);
3221 cave[y][x].info |= info2;
3226 cave[y][x].feat = feat1;
3227 cave[y][x].info &= ~(CAVE_MASK);
3228 cave[y][x].info |= info1;
3232 else if (cave[y][x].feat <= c3)
3234 cave[y][x].feat = feat3;
3235 cave[y][x].info |= info3;
3238 /* if greater than cutoff then is a wall */
3241 place_outer_bold(y, x);
3251 * Quick and nasty fill routine used to find the connected region
3252 * of floor in the middle of the cave
3254 static void cave_fill(byte y, byte x)
3263 /*** Start Grid ***/
3265 /* Enqueue that entry */
3270 /* Now process the queue */
3271 while (flow_head != flow_tail)
3273 /* Extract the next entry */
3274 ty = temp_y[flow_head];
3275 tx = temp_x[flow_head];
3277 /* Forget that entry */
3278 if (++flow_head == TEMP_MAX) flow_head = 0;
3280 /* Add the "children" */
3281 for (d = 0; d < 8; d++)
3283 int old_head = flow_tail;
3285 /* Child location */
3286 j = ty + ddy_ddd[d];
3287 i = tx + ddx_ddd[d];
3289 /* Paranoia Don't leave the cave */
3290 if (!in_bounds(j, i))
3292 /* affect boundary */
3293 cave[j][i].info |= CAVE_ICKY;
3297 /* If within bounds */
3298 else if ((i > fill_data.xmin) && (i < fill_data.xmax)
3299 && (j > fill_data.ymin) && (j < fill_data.ymax))
3301 /* If not a wall or floor done before */
3302 if (hack_isnt_wall(j, i,
3303 fill_data.c1, fill_data.c2, fill_data.c3,
3304 fill_data.feat1, fill_data.feat2, fill_data.feat3,
3305 fill_data.info1, fill_data.info2, fill_data.info3))
3307 /* Enqueue that entry */
3308 temp_y[flow_tail] = j;
3309 temp_x[flow_tail] = i;
3311 /* Advance the queue */
3312 if (++flow_tail == TEMP_MAX) flow_tail = 0;
3314 /* Hack -- Overflow by forgetting new entry */
3315 if (flow_tail == flow_head)
3317 flow_tail = old_head;
3321 /* keep tally of size of cave system */
3322 (fill_data.amount)++;
3328 /* affect boundary */
3329 cave[j][i].info |= CAVE_ICKY;
3336 static bool generate_fracave(int y0, int x0, int xsize, int ysize, int cutoff, bool light, bool room)
3338 int x, y, i, xhsize, yhsize;
3341 /* offsets to middle from corner */
3347 * select region connected to center of cave system
3348 * this gets rid of alot of isolated one-sqaures that
3349 * can make teleport traps instadeaths...
3353 fill_data.c1 = cutoff;
3357 /* features to fill with */
3358 fill_data.feat1 = floor_type[randint0(100)];
3359 fill_data.feat2 = floor_type[randint0(100)];
3360 fill_data.feat3 = floor_type[randint0(100)];
3362 fill_data.info1 = CAVE_FLOOR;
3363 fill_data.info2 = CAVE_FLOOR;
3364 fill_data.info3 = CAVE_FLOOR;
3366 /* number of filled squares */
3367 fill_data.amount = 0;
3369 cave_fill((byte)y0, (byte)x0);
3371 /* if tally too small, try again */
3372 if (fill_data.amount < 10)
3374 /* too small - clear area and try again later */
3375 for (x = 0; x <= xsize; ++x)
3377 for (y = 0; y <= ysize; ++y)
3379 place_extra_bold(y0 + y - yhsize, x0 + x - xhsize);
3380 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY | CAVE_ROOM);
3387 * Do boundarys-check to see if they are next to a filled region
3388 * If not then they are set to normal granite
3389 * If so then they are marked as room walls.
3391 for (i = 0; i <= xsize; ++i)
3394 if ((cave[0 + y0 - yhsize][i + x0 - xhsize].info & CAVE_ICKY) && (room))
3396 /* Next to a 'filled' region? - set to be room walls */
3397 place_outer_bold(y0 + 0 - yhsize, x0 + i - xhsize);
3398 if (light) cave[y0 + 0 - yhsize][x0 + i - xhsize].info |= (CAVE_GLOW);
3399 cave[y0 + 0 - yhsize][x0 + i - xhsize].info |= (CAVE_ROOM);
3400 place_outer_bold(y0 + 0 - yhsize, x0 + i - xhsize);
3404 /* set to be normal granite */
3405 place_extra_bold(y0 + 0 - yhsize, x0 + i - xhsize);
3408 /* bottom boundary */
3409 if ((cave[ysize + y0 - yhsize][i + x0 - xhsize].info & CAVE_ICKY) && (room))
3411 /* Next to a 'filled' region? - set to be room walls */
3412 place_outer_bold(y0 + ysize - yhsize, x0 + i - xhsize);
3413 if (light) cave[y0 + ysize - yhsize][x0 + i - xhsize].info|=(CAVE_GLOW);
3414 cave[y0 + ysize - yhsize][x0 + i - xhsize].info|=(CAVE_ROOM);
3415 place_outer_bold(y0 + ysize - yhsize, x0 + i - xhsize);
3419 /* set to be normal granite */
3420 place_extra_bold(y0 + ysize - yhsize, x0 + i - xhsize);
3423 /* clear the icky flag-don't need it any more */
3424 cave[y0 + 0 - yhsize][x0 + i - xhsize].info &= ~(CAVE_ICKY);
3425 cave[y0 + ysize - yhsize][x0 + i - xhsize].info &= ~(CAVE_ICKY);
3428 /* Do the left and right boundaries minus the corners (done above) */
3429 for (i = 1; i < ysize; ++i)
3432 if ((cave[i + y0 - yhsize][0 + x0 - xhsize].info & CAVE_ICKY) && room)
3435 place_outer_bold(y0 + i - yhsize, x0 + 0 - xhsize);
3436 if (light) cave[y0 + i - yhsize][x0 + 0 - xhsize].info |= (CAVE_GLOW);
3437 cave[y0 + i - yhsize][x0 + 0 - xhsize].info |= (CAVE_ROOM);
3438 place_outer_bold(y0 + i - yhsize, x0 + 0 - xhsize);
3443 place_extra_bold(y0 + i - yhsize, x0 + 0 - xhsize);
3445 /* right boundary */
3446 if ((cave[i + y0 - yhsize][xsize + x0 - xhsize].info & CAVE_ICKY) && room)
3449 place_outer_bold(y0 + i - yhsize, x0 + xsize - xhsize);
3450 if (light) cave[y0 + i - yhsize][x0 + xsize - xhsize].info |= (CAVE_GLOW);
3451 cave[y0 + i - yhsize][x0 + xsize - xhsize].info |= (CAVE_ROOM);
3452 place_outer_bold(y0 + i - yhsize, x0 + xsize - xhsize);
3457 place_extra_bold(y0 + i - yhsize, x0 + xsize - xhsize);
3460 /* clear icky flag -done with it */
3461 cave[y0 + i - yhsize][x0 + 0 - xhsize].info &= ~(CAVE_ICKY);
3462 cave[y0 + i - yhsize][x0 + xsize - xhsize].info &= ~(CAVE_ICKY);
3466 /* Do the rest: convert back to the normal format */
3467 for (x = 1; x < xsize; ++x)
3469 for (y = 1; y < ysize; ++y)
3471 if (is_floor_bold(y0 + y - yhsize, x0 + x - xhsize) &&
3472 (cave[y0 + y - yhsize][x0 + x - xhsize].info & CAVE_ICKY))
3474 /* Clear the icky flag in the filled region */
3475 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~CAVE_ICKY;
3477 /* Set appropriate flags */
3478 if (light) cave[y0 + y - yhsize][x0 + x - xhsize].info |= (CAVE_GLOW);
3479 if (room) cave[y0 + y - yhsize][x0 + x - xhsize].info |= (CAVE_ROOM);
3481 else if (is_outer_bold(y0 + y - yhsize, x0 + x - xhsize) &&
3482 (cave[y0 + y - yhsize][x0 + x - xhsize].info & CAVE_ICKY))
3485 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY);
3486 if (light) cave[y0 + y - yhsize][x0 + x - xhsize].info |= (CAVE_GLOW);
3489 cave[y0 + y - yhsize][x0 + x - xhsize].info |= (CAVE_ROOM);
3494 place_extra_bold(y0 + y - yhsize, x0 + x - xhsize);
3495 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ROOM);
3500 /* Clear the unconnected regions */
3501 place_extra_bold(y0 + y - yhsize, x0 + x - xhsize);
3502 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY | CAVE_ROOM);
3508 * XXX XXX XXX There is a slight problem when tunnels pierce the caves:
3509 * Extra doors appear inside the system. (Its not very noticeable though.)
3510 * This can be removed by "filling" from the outside in. This allows a separation
3511 * from FEAT_WALL_OUTER with FEAT_WALL_INNER. (Internal walls are F.W.OUTER instead.)
3512 * The extra effort for what seems to be only a minor thing (even non-existant if you
3513 * think of the caves not as normal rooms, but as holes in the dungeon), doesn't seem
3522 * Driver routine to create fractal cave system
3524 static void build_type9(int by0, int bx0)
3526 int grd, roug, cutoff, xsize, ysize, y0, x0;
3528 bool done, light, room;
3530 /* get size: note 'Evenness'*/
3531 xsize = randint1(22) * 2 + 6;
3532 ysize = randint1(15) * 2 + 6;
3534 /* Try to allocate space for room. If fails, exit */
3535 if (!room_alloc(xsize + 1, ysize + 1, FALSE, by0, bx0, &x0, &y0)) return;
3537 light = done = FALSE;
3540 if ((dun_level <= randint1(25)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS)) light = TRUE;
3544 /* Note: size must be even or there are rounding problems
3545 * This causes the tunnels not to connect properly to the room */
3547 /* testing values for these parameters feel free to adjust */
3548 grd = 1 << (randint0(4));
3550 /* want average of about 16 */
3551 roug = randint1(8) * randint1(4);
3554 cutoff = randint1(xsize / 4) + randint1(ysize / 4) +
3555 randint1(xsize / 4) + randint1(ysize / 4);
3558 generate_hmap(y0, x0, xsize, ysize, grd, roug, cutoff);
3560 /* Convert to normal format + clean up */
3561 done = generate_fracave(y0, x0, xsize, ysize, cutoff, light, room);
3565 #ifdef ALLOW_CAVERNS_AND_LAKES
3567 * Builds a cave system in the center of the dungeon.
3569 void build_cavern(void)
3571 int grd, roug, cutoff, xsize, ysize, x0, y0;
3574 light = done = FALSE;
3575 if ((dun_level <= randint1(50)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS)) light = TRUE;
3577 /* Make a cave the size of the dungeon */
3578 xsize = cur_wid - 1;
3579 ysize = cur_hgt - 1;
3583 /* Paranoia: make size even */
3589 /* testing values for these parameters: feel free to adjust */
3590 grd = randint1(4) + 4;
3592 /* want average of about 16 */
3593 roug = randint1(8) * randint1(4);
3599 generate_hmap(y0 + 1, x0 + 1, xsize, ysize, grd, roug, cutoff);
3601 /* Convert to normal format+ clean up */
3602 done = generate_fracave(y0 + 1, x0 + 1, xsize, ysize, cutoff, light, FALSE);
3606 static bool generate_lake(int y0, int x0, int xsize, int ysize, int c1, int c2, int c3, int type)
3608 int x, y, i, xhsize, yhsize;
3609 int feat1, feat2, feat3;
3611 /* offsets to middle from corner */
3615 /* Get features based on type */
3618 case GEN_LAKE_TYPE_LAVA: /* Lava */
3619 feat1 = FEAT_DEEP_LAVA;
3620 feat2 = FEAT_SHAL_LAVA;
3621 feat3 = floor_type[randint0(100)];
3623 case GEN_LAKE_TYPE_WATER: /* Water */
3624 feat1 = FEAT_DEEP_WATER;
3625 feat2 = FEAT_SHAL_WATER;
3626 feat3 = floor_type[randint0(100)];
3628 case GEN_LAKE_TYPE_CAVE: /* Collapsed cave */
3629 feat1 = floor_type[randint0(100)];
3630 feat2 = floor_type[randint0(100)];
3631 feat3 = FEAT_RUBBLE;
3633 case GEN_LAKE_TYPE_EARTH_VAULT: /* Earth vault */
3634 feat1 = FEAT_RUBBLE;
3635 feat2 = floor_type[randint0(100)];
3636 feat3 = FEAT_RUBBLE;
3638 case GEN_LAKE_TYPE_AIR_VAULT: /* Air vault */
3643 case GEN_LAKE_TYPE_WATER_VAULT: /* Water vault */
3644 feat1 = FEAT_SHAL_WATER;
3645 feat2 = FEAT_DEEP_WATER;
3646 feat3 = FEAT_SHAL_WATER;
3648 case GEN_LAKE_TYPE_FIRE_VAULT: /* Fire Vault */
3649 feat1 = FEAT_SHAL_LAVA;
3650 feat2 = FEAT_DEEP_LAVA;
3651 feat3 = FEAT_SHAL_LAVA;
3655 default: return FALSE;
3659 * select region connected to center of cave system
3660 * this gets rid of alot of isolated one-sqaures that
3661 * can make teleport traps instadeaths...
3669 /* features to fill with */
3670 fill_data.feat1 = feat1;
3671 fill_data.feat2 = feat2;
3672 fill_data.feat3 = feat3;
3674 fill_data.info1 = 0;
3675 fill_data.info2 = 0;
3676 fill_data.info3 = 0;
3678 /* number of filled squares */
3679 fill_data.amount = 0;
3681 /* select region connected to center of cave system
3682 * this gets rid of alot of isolated one-sqaures that
3683 * can make teleport traps instadeaths... */
3684 cave_fill((byte)y0, (byte)x0);
3686 /* if tally too small, try again */
3687 if (fill_data.amount < 10)
3689 /* too small -clear area and try again later */
3690 for (x = 0; x <= xsize; ++x)
3692 for (y = 0; y <= ysize; ++y)
3694 place_floor_bold(y0 + y - yhsize, x0 + x - xhsize);
3695 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY);
3701 /* Do boundarys- set to normal granite */
3702 for (i = 0; i <= xsize; ++i)
3704 place_extra_bold(y0 + 0 - yhsize, x0 + i - xhsize);
3705 place_extra_bold(y0 + ysize - yhsize, x0 + i - xhsize);
3707 /* clear the icky flag-don't need it any more */
3708 cave[y0 + 0 - yhsize][x0 + i - xhsize].info &= ~(CAVE_ICKY);
3709 cave[y0 + ysize - yhsize][x0 + i - xhsize].info &= ~(CAVE_ICKY);
3712 /* Do the left and right boundaries minus the corners (done above) */
3714 for (i = 1; i < ysize; ++i)
3716 place_extra_bold(y0 + i - yhsize, x0 + 0 - xhsize);
3717 place_extra_bold(y0 + i - yhsize, x0 + xsize - xhsize);
3719 /* clear icky flag -done with it */
3720 cave[y0 + i - yhsize][x0 + 0 - xhsize].info &= ~(CAVE_ICKY);
3721 cave[y0 + i - yhsize][x0 + xsize - xhsize].info &= ~(CAVE_ICKY);
3725 /* Do the rest: convert back to the normal format */
3726 for (x = 1; x < xsize; ++x)
3728 for (y = 1; y < ysize; ++y)
3730 /* Fill unconnected regions with granite */
3731 if ((!(cave[y0 + y - yhsize][x0 + x - xhsize].info & CAVE_ICKY)) ||
3732 is_outer_bold(y0 + y - yhsize, x0 + x - xhsize))
3733 place_extra_bold(y0 + y - yhsize, x0 + x - xhsize);
3735 /* turn off icky flag (no longer needed.) */
3736 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY | CAVE_ROOM);
3738 /* Light lava and trees */
3739 if ((cave[y0 + y - yhsize][x0 + x - xhsize].feat == FEAT_DEEP_LAVA) ||
3740 (cave[y0 + y - yhsize][x0 + x - xhsize].feat == FEAT_SHAL_LAVA))
3742 if (!(d_info[dungeon_type].flags1 & DF1_DARKNESS)) cave[y0 + y - yhsize][x0 + x - xhsize].info |= CAVE_GLOW;
3752 * makes a lake/collapsed cave system in the center of the dungeon
3754 void build_lake(int type)
3756 int grd, roug, xsize, ysize, x0, y0;
3760 /* paranoia - exit if lake type out of range. */
3761 if ((type < GEN_LAKE_TYPE_LAVA) || (type > GEN_LAKE_TYPE_FIRE_VAULT))
3763 msg_format("Invalid lake type (%d)", type);
3767 /* Make the size of the dungeon */
3768 xsize = cur_wid - 1;
3769 ysize = cur_hgt - 1;
3773 /* Paranoia: make size even */
3779 /* testing values for these parameters: feel free to adjust */
3780 grd = randint1(3) + 4;
3782 /* want average of about 16 */
3783 roug = randint1(8) * randint1(4);
3785 /* Make up size of various componants */
3789 /* Deep water/lava */
3790 c1 = randint0(c3 / 2) + randint0(c3 / 2) - 5;
3792 /* Shallow boundary */
3796 generate_hmap(y0 + 1, x0 + 1, xsize, ysize, grd, roug, c3);
3798 /* Convert to normal format+ clean up */
3799 done = generate_lake(y0 + 1, x0 + 1, xsize, ysize, c1, c2, c3, type);
3802 #endif /* ALLOW_CAVERNS_AND_LAKES */
3806 * Routine used by the random vault creators to add a door to a location
3807 * Note that range checking has to be done in the calling routine.
3809 * The doors must be INSIDE the allocated region.
3811 static void add_door(int x, int y)
3813 /* Need to have a wall in the center square */
3814 if (!is_outer_bold(y, x)) return;
3821 * where x=don't care
3825 if (is_floor_bold(y-1,x) && is_floor_bold(y+1,x) &&
3826 (is_outer_bold(y, x - 1) && is_outer_bold(y, x + 1)))
3829 place_secret_door(y, x);
3831 /* set boundarys so don't get wide doors */
3832 place_solid_bold(y, x - 1);
3833 place_solid_bold(y, x + 1);
3842 * where x = don't care
3845 if (is_outer_bold(y - 1, x) && is_outer_bold(y + 1, x) &&
3846 is_floor_bold(y,x-1) && is_floor_bold(y,x+1))
3849 place_secret_door(y, x);
3851 /* set boundarys so don't get wide doors */
3852 place_solid_bold(y - 1, x);
3853 place_solid_bold(y + 1, x);
3859 * Routine that fills the empty areas of a room with treasure and monsters.
3861 static void fill_treasure(int x1, int x2, int y1, int y2, int difficulty)
3863 int x, y, cx, cy, size;
3866 /* center of room:*/
3870 /* Rough measure of size of vault= sum of lengths of sides */
3871 size = abs(x2 - x1) + abs(y2 - y1);
3873 for (x = x1; x <= x2; x++)
3875 for (y = y1; y <= y2; y++)
3877 /* Thing added based on distance to center of vault
3878 * Difficulty is 1-easy to 10-hard */
3879 value = ((((s32b)(distance(cx, cy, x, y))) * 100) / size) + randint1(10) - difficulty;
3881 /* hack- empty square part of the time */
3882 if ((randint1(100) - difficulty * 3) > 50) value = 20;
3884 /* if floor, shallow water and lava */
3885 if (is_floor_bold(y, x) ||
3886 (cave[y][x].feat == FEAT_SHAL_WATER) ||
3887 (cave[y][x].feat == FEAT_SHAL_LAVA))
3889 /* The smaller 'value' is, the better the stuff */
3892 /* Meanest monster + treasure */
3893 monster_level = base_level + 40;
3894 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
3895 monster_level = base_level;
3896 object_level = base_level + 20;
3897 place_object(y, x, AM_GOOD);
3898 object_level = base_level;
3902 /* Mean monster +treasure */
3903 monster_level = base_level + 20;
3904 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
3905 monster_level = base_level;
3906 object_level = base_level + 10;
3907 place_object(y, x, AM_GOOD);
3908 object_level = base_level;
3910 else if (value < 10)
3913 monster_level = base_level + 9;
3914 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
3915 monster_level = base_level;
3917 else if (value < 17)
3919 /* Intentional Blank space */
3922 * (Want some of the vault to be empty
3923 * so have room for group monsters.
3924 * This is used in the hack above to lower
3925 * the density of stuff in the vault.)
3928 else if (value < 23)
3930 /* Object or trap */
3931 if (randint0(100) < 25)
3933 place_object(y, x, 0L);
3940 else if (value < 30)
3942 /* Monster and trap */
3943 monster_level = base_level + 5;
3944 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
3945 monster_level = base_level;
3948 else if (value < 40)
3950 /* Monster or object */
3951 if (randint0(100) < 50)
3953 monster_level = base_level + 3;
3954 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
3955 monster_level = base_level;
3957 if (randint0(100) < 50)
3959 object_level = base_level + 7;
3960 place_object(y, x, 0L);
3961 object_level = base_level;
3964 else if (value < 50)
3973 /* 20% monster, 40% trap, 20% object, 20% blank space */
3974 if (randint0(100) < 20)
3976 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
3978 else if (randint0(100) < 50)
3982 else if (randint0(100) < 50)
3984 place_object(y, x, 0L);
3995 * This function creates a random vault that looks like a collection of bubbles.
3996 * It works by getting a set of coordinates that represent the center of each
3997 * bubble. The entire room is made by seeing which bubble center is closest. If
3998 * two centers are equidistant then the square is a wall, otherwise it is a floor.
3999 * The only exception is for squares really near a center, these are always floor.
4000 * (It looks better than without this check.)
4002 * Note: If two centers are on the same point then this algorithm will create a
4003 * blank bubble filled with walls. - This is prevented from happening.
4005 static void build_bubble_vault(int x0, int y0, int xsize, int ysize)
4007 #define BUBBLENUM 10 /* number of bubbles */
4009 /* array of center points of bubbles */
4010 coord center[BUBBLENUM];
4013 u16b min1, min2, temp;
4016 /* Offset from center to top left hand corner */
4017 int xhsize = xsize / 2;
4018 int yhsize = ysize / 2;
4021 if (cheat_room) msg_print("Bubble Vault");
4023 /* Allocate center of bubbles */
4024 center[0].x = randint1(xsize - 3) + 1;
4025 center[0].y = randint1(ysize - 3) + 1;
4027 for (i = 1; i < BUBBLENUM; i++)
4031 /* get center and check to see if it is unique */
4036 x = randint1(xsize - 3) + 1;
4037 y = randint1(ysize - 3) + 1;
4039 for (j = 0; j < i; j++)
4041 /* rough test to see if there is an overlap */
4042 if ((x == center[j].x) && (y == center[j].y)) done = FALSE;
4051 /* Top and bottom boundaries */
4052 for (i = 0; i < xsize; i++)
4054 int x = x0 - xhsize + i;
4056 place_outer_noperm_bold(y0 - yhsize + 0, x);
4057 cave[y0 - yhsize + 0][x].info |= (CAVE_ROOM | CAVE_ICKY);
4058 place_outer_noperm_bold(y0 - yhsize + ysize - 1, x);
4059 cave[y0 - yhsize + ysize - 1][x].info |= (CAVE_ROOM | CAVE_ICKY);
4062 /* Left and right boundaries */
4063 for (i = 1; i < ysize - 1; i++)
4065 int y = y0 - yhsize + i;
4067 place_outer_noperm_bold(y, x0 - xhsize + 0);
4068 cave[y][x0 - xhsize + 0].info |= (CAVE_ROOM | CAVE_ICKY);
4069 place_outer_noperm_bold(y, x0 - xhsize + xsize - 1);
4070 cave[y][x0 - xhsize + xsize - 1].info |= (CAVE_ROOM | CAVE_ICKY);
4073 /* Fill in middle with bubbles */
4074 for (x = 1; x < xsize - 1; x++)
4076 for (y = 1; y < ysize - 1; y++)
4078 /* Get distances to two closest centers */
4081 min1 = distance(x, y, center[0].x, center[0].y);
4082 min2 = distance(x, y, center[1].x, center[1].y);
4086 /* swap if in wrong order */
4093 for (i = 2; i < BUBBLENUM; i++)
4095 temp = distance(x, y, center[i].x, center[i].y);
4103 else if (temp < min2)
4105 /* second smallest */
4109 if (((min2 - min1) <= 2) && (!(min1 < 3)))
4111 /* Boundary at midpoint+ not at inner region of bubble */
4112 place_outer_noperm_bold(y0 - yhsize + y, x0 - xhsize + x);
4116 /* middle of a bubble */
4117 place_floor_bold(y0 - yhsize + y, x0 - xhsize + x);
4120 /* clean up rest of flags */
4121 cave[y0 - yhsize + y][x0 - xhsize + x].info |= (CAVE_ROOM | CAVE_ICKY);
4125 /* Try to add some random doors */
4126 for (i = 0; i < 500; i++)
4128 x = randint1(xsize - 3) - xhsize + x0 + 1;
4129 y = randint1(ysize - 3) - yhsize + y0 + 1;
4133 /* Fill with monsters and treasure, low difficulty */
4134 fill_treasure(x0 - xhsize + 1, x0 - xhsize + xsize - 2, y0 - yhsize + 1, y0 - yhsize + ysize - 2, randint1(5));
4139 * Overlay a rectangular room given its bounds
4140 * This routine is used by build_room_vault
4141 * The area inside the walls is not touched:
4142 * only granite is removed- normal walls stay
4144 static void build_room(int x1, int x2, int y1, int y2)
4146 int x, y, i, xsize, ysize, temp;
4148 /* Check if rectangle has no width */
4149 if ((x1 == x2) || (y1 == y2)) return;
4154 /* Swap boundaries if in wrong order */
4162 /* Swap boundaries if in wrong order */
4168 /* get total widths */
4173 /* Top and bottom boundaries */
4174 for (i = 0; i <= xsize; i++)
4176 place_outer_noperm_bold(y1, x1 + i);
4177 cave[y1][x1 + i].info |= (CAVE_ROOM | CAVE_ICKY);
4178 place_outer_noperm_bold(y2, x1 + i);
4179 cave[y2][x1 + i].info |= (CAVE_ROOM | CAVE_ICKY);
4182 /* Left and right boundaries */
4183 for (i = 1; i < ysize; i++)
4185 place_outer_noperm_bold(y1 + i, x1);
4186 cave[y1 + i][x1].info|=(CAVE_ROOM | CAVE_ICKY);
4187 place_outer_noperm_bold(y1 + i, x2);
4188 cave[y1 + i][x2].info|=(CAVE_ROOM | CAVE_ICKY);
4192 for (x = 1; x < xsize; x++)
4194 for (y = 1; y < ysize; y++)
4196 if (is_extra_bold(y1+y, x1+x))
4198 /* clear the untouched region */
4199 place_floor_bold(y1 + y, x1 + x);
4200 cave[y1 + y][x1 + x].info |= (CAVE_ROOM | CAVE_ICKY);
4204 /* make it a room- but don't touch */
4205 cave[y1 + y][x1 + x].info |= (CAVE_ROOM | CAVE_ICKY);
4212 /* Create a random vault that looks like a collection of overlapping rooms */
4214 static void build_room_vault(int x0, int y0, int xsize, int ysize)
4216 int i, x1, x2, y1, y2, xhsize, yhsize;
4218 /* get offset from center */
4222 if (cheat_room) msg_print("Room Vault");
4224 /* fill area so don't get problems with arena levels */
4225 for (x1 = 0; x1 < xsize; x1++)
4227 int x = x0 - xhsize + x1;
4229 for (y1 = 0; y1 < ysize; y1++)
4231 int y = y0 - yhsize + y1;
4233 place_extra_bold(y, x);
4234 cave[y][x].info &= (~CAVE_ICKY);
4238 /* add ten random rooms */
4239 for (i = 0; i < 10; i++)
4241 x1 = randint1(xhsize) * 2 + x0 - xhsize;
4242 x2 = randint1(xhsize) * 2 + x0 - xhsize;
4243 y1 = randint1(yhsize) * 2 + y0 - yhsize;
4244 y2 = randint1(yhsize) * 2 + y0 - yhsize;
4245 build_room(x1, x2, y1, y2);
4248 /* Add some random doors */
4249 for (i = 0; i < 500; i++)
4251 x1 = randint1(xsize - 3) - xhsize + x0 + 1;
4252 y1 = randint1(ysize - 3) - yhsize + y0 + 1;
4256 /* Fill with monsters and treasure, high difficulty */
4257 fill_treasure(x0 - xhsize + 1, x0 - xhsize + xsize - 2, y0 - yhsize + 1, y0 - yhsize + ysize - 2, randint1(5) + 5);
4261 /* Create a random vault out of a fractal cave */
4262 static void build_cave_vault(int x0, int y0, int xsiz, int ysiz)
4264 int grd, roug, cutoff, xhsize, yhsize, xsize, ysize, x, y;
4265 bool done, light, room;
4267 /* round to make sizes even */
4273 if (cheat_room) msg_print("Cave Vault");
4275 light = done = FALSE;
4280 /* testing values for these parameters feel free to adjust */
4281 grd = 1 << randint0(4);
4283 /* want average of about 16 */
4284 roug = randint1(8) * randint1(4);
4287 cutoff = randint1(xsize / 4) + randint1(ysize / 4) +
4288 randint1(xsize / 4) + randint1(ysize / 4);
4291 generate_hmap(y0, x0, xsize, ysize, grd, roug, cutoff);
4293 /* Convert to normal format+ clean up */
4294 done = generate_fracave(y0, x0, xsize, ysize, cutoff, light, room);
4297 /* Set icky flag because is a vault */
4298 for (x = 0; x <= xsize; x++)
4300 for (y = 0; y <= ysize; y++)
4302 cave[y0 - yhsize + y][x0 - xhsize + x].info |= CAVE_ICKY;
4306 /* Fill with monsters and treasure, low difficulty */
4307 fill_treasure(x0 - xhsize + 1, x0 - xhsize + xsize - 1, y0 - yhsize + 1, y0 - yhsize + ysize - 1, randint1(5));
4311 * maze vault -- rectangular labyrinthine rooms
4313 * maze vault uses two routines:
4314 * r_visit - a recursive routine that builds the labyrinth
4315 * build_maze_vault - a driver routine that calls r_visit and adds
4316 * monsters, traps and treasure
4318 * The labyrinth is built by creating a spanning tree of a graph.
4319 * The graph vertices are at
4320 * (x, y) = (2j + x1, 2k + y1) j = 0,...,m-1 k = 0,...,n-1
4321 * and the edges are the vertical and horizontal nearest neighbors.
4323 * The spanning tree is created by performing a suitably randomized
4324 * depth-first traversal of the graph. The only adjustable parameter
4325 * is the randint0(3) below; it governs the relative density of
4326 * twists and turns in the labyrinth: smaller number, more twists.
4328 static void r_visit(int y1, int x1, int y2, int x2,
4329 int node, int dir, int *visited)
4331 int i, j, m, n, temp, x, y, adj[4];
4333 /* dimensions of vertex array */
4334 m = (x2 - x1) / 2 + 1;
4335 n = (y2 - y1) / 2 + 1;
4337 /* mark node visited and set it to a floor */
4339 x = 2 * (node % m) + x1;
4340 y = 2 * (node / m) + y1;
4341 place_floor_bold(y, x);
4343 /* setup order of adjacent node visits */
4346 /* pick a random ordering */
4347 for (i = 0; i < 4; i++)
4349 for (i = 0; i < 4; i++)
4360 /* pick a random ordering with dir first */
4362 for (i = 1; i < 4; i++)
4364 for (i = 1; i < 4; i++)
4366 j = 1 + randint0(3);
4373 for (i = 0; i < 4; i++)
4378 /* (0,+) - check for bottom boundary */
4379 if ((node / m < n - 1) && (visited[node + m] == 0))
4381 place_floor_bold(y + 1, x);
4382 r_visit(y1, x1, y2, x2, node + m, dir, visited);
4386 /* (0,-) - check for top boundary */
4387 if ((node / m > 0) && (visited[node - m] == 0))
4389 place_floor_bold(y - 1, x);
4390 r_visit(y1, x1, y2, x2, node - m, dir, visited);
4394 /* (+,0) - check for right boundary */
4395 if ((node % m < m - 1) && (visited[node + 1] == 0))
4397 place_floor_bold(y, x + 1);
4398 r_visit(y1, x1, y2, x2, node + 1, dir, visited);
4402 /* (-,0) - check for left boundary */
4403 if ((node % m > 0) && (visited[node - 1] == 0))
4405 place_floor_bold(y, x - 1);
4406 r_visit(y1, x1, y2, x2, node - 1, dir, visited);
4413 void build_maze_vault(int x0, int y0, int xsize, int ysize, bool is_vault)
4417 int m, n, num_vertices, *visited;
4422 if (cheat_room && is_vault) msg_print("Maze Vault");
4424 /* Choose lite or dark */
4425 light = ((dun_level <= randint1(25)) && is_vault && !(d_info[dungeon_type].flags1 & DF1_DARKNESS));
4427 /* Pick a random room size - randomized by calling routine */
4436 /* generate the room */
4437 for (y = y1 - 1; y <= y2 + 1; y++)
4439 for (x = x1 - 1; x <= x2 + 1; x++)
4441 c_ptr = &cave[y][x];
4442 c_ptr->info |= CAVE_ROOM;
4443 if (is_vault) c_ptr->info |= CAVE_ICKY;
4444 if ((x == x1 - 1) || (x == x2 + 1) || (y == y1 - 1) || (y == y2 + 1))
4446 place_outer_grid(c_ptr);
4450 place_extra_grid(c_ptr);
4454 place_inner_grid(c_ptr);
4456 if (light) c_ptr->info |= (CAVE_GLOW);
4460 /* dimensions of vertex array */
4463 num_vertices = m * n;
4465 /* initialize array of visited vertices */
4466 C_MAKE(visited, num_vertices, int);
4468 /* traverse the graph to create a spaning tree, pick a random root */
4469 r_visit(y1, x1, y2, x2, randint0(num_vertices), 0, visited);
4471 /* Fill with monsters and treasure, low difficulty */
4472 if (is_vault) fill_treasure(x1, x2, y1, y2, randint1(5));
4474 C_KILL(visited, num_vertices, int);
4478 /* Build a "mini" checkerboard vault
4480 * This is done by making a permanent wall maze and setting
4481 * the diagonal sqaures of the checker board to be granite.
4482 * The vault has two entrances on opposite sides to guarantee
4483 * a way to get in even if the vault abuts a side of the dungeon.
4485 static void build_mini_c_vault(int x0, int y0, int xsize, int ysize)
4488 int y1, x1, y2, x2, y, x, total;
4489 int m, n, num_vertices;
4492 if (cheat_room) msg_print("Mini Checker Board Vault");
4494 /* Pick a random room size */
4504 /* generate the room */
4505 for (x = x1 - 2; x <= x2 + 2; x++)
4507 if (!in_bounds(y1-2,x)) break;
4509 cave[y1-2][x].info |= (CAVE_ROOM | CAVE_ICKY);
4511 place_extra_noperm_bold(y1-2, x);
4514 for (x = x1 - 2; x <= x2 + 2; x++)
4516 if (!in_bounds(y2+2,x)) break;
4518 cave[y2+2][x].info |= (CAVE_ROOM | CAVE_ICKY);
4520 place_extra_noperm_bold(y2+2, x);
4523 for (y = y1 - 2; y <= y2 + 2; y++)
4525 if (!in_bounds(y,x1-2)) break;
4527 cave[y][x1-2].info |= (CAVE_ROOM | CAVE_ICKY);
4529 place_extra_noperm_bold(y, x1-2);
4532 for (y = y1 - 2; y <= y2 + 2; y++)
4534 if (!in_bounds(y,x2+2)) break;
4536 cave[y][x2+2].info |= (CAVE_ROOM | CAVE_ICKY);
4538 place_extra_noperm_bold(y, x2+2);
4541 for (y = y1 - 1; y <= y2 + 1; y++)
4543 for (x = x1 - 1; x <= x2 + 1; x++)
4545 cave[y][x].info |= (CAVE_ROOM | CAVE_ICKY);
4547 /* Permanent walls */
4548 cave[y][x].feat = FEAT_PERM_INNER;
4553 /* dimensions of vertex array */
4556 num_vertices = m * n;
4558 /* initialize array of visited vertices */
4559 C_MAKE(visited, num_vertices, int);
4561 /* traverse the graph to create a spannng tree, pick a random root */
4562 r_visit(y1, x1, y2, x2, randint0(num_vertices), 0, visited);
4564 /* Make it look like a checker board vault */
4565 for (x = x1; x <= x2; x++)
4567 for (y = y1; y <= y2; y++)
4569 total = x - x1 + y - y1;
4570 /* If total is odd- and is a floor then make a wall */
4571 if ((total % 2 == 1) && is_floor_bold(y, x))
4573 place_inner_bold(y, x);
4578 /* Make a couple of entrances */
4581 /* left and right */
4582 y = randint1(dy) + dy / 2;
4583 place_outer_noperm_bold(y1 + y, x1 - 1);
4584 place_outer_noperm_bold(y1 + y, x2 + 1);
4588 /* top and bottom */
4589 x = randint1(dx) + dx / 2;
4590 place_outer_noperm_bold(y1 - 1, x1 + x);
4591 place_outer_noperm_bold(y2 + 1, x1 + x);
4594 /* Fill with monsters and treasure, highest difficulty */
4595 fill_treasure(x1, x2, y1, y2, 10);
4597 C_KILL(visited, num_vertices, int);
4601 /* Build a town/ castle by using a recursive algorithm.
4602 * Basically divide each region in a probalistic way to create
4603 * smaller regions. When the regions get too small stop.
4605 * The power variable is a measure of how well defended a region is.
4606 * This alters the possible choices.
4608 static void build_recursive_room(int x1, int y1, int x2, int y2, int power)
4614 /* Temp variables */
4620 if ((power < 3) && (xsize > 12) && (ysize > 12))
4622 /* Need outside wall +keep */
4629 /* Make rooms + subdivide */
4630 if ((randint1(10) > 2) && (xsize < 8) && (ysize < 8))
4636 choice = randint1(2) + 1;
4641 /* Mostly subdivide */
4642 choice = randint1(3) + 1;
4646 /* Based on the choice made above, do something */
4654 /* top and bottom */
4655 for (x = x1; x <= x2; x++)
4657 place_outer_bold(y1, x);
4658 place_outer_bold(y2, x);
4661 /* left and right */
4662 for (y = y1 + 1; y < y2; y++)
4664 place_outer_bold(y, x1);
4665 place_outer_bold(y, x2);
4668 /* Make a couple of entrances */
4671 /* left and right */
4672 y = randint1(ysize) + y1;
4673 place_floor_bold(y, x1);
4674 place_floor_bold(y, x2);
4678 /* top and bottom */
4679 x = randint1(xsize) + x1;
4680 place_floor_bold(y1, x);
4681 place_floor_bold(y2, x);
4684 /* Select size of keep */
4685 t1 = randint1(ysize / 3) + y1;
4686 t2 = y2 - randint1(ysize / 3);
4687 t3 = randint1(xsize / 3) + x1;
4688 t4 = x2 - randint1(xsize / 3);
4690 /* Do outside areas */
4692 /* Above and below keep */
4693 build_recursive_room(x1 + 1, y1 + 1, x2 - 1, t1, power + 1);
4694 build_recursive_room(x1 + 1, t2, x2 - 1, y2, power + 1);
4696 /* Left and right of keep */
4697 build_recursive_room(x1 + 1, t1 + 1, t3, t2 - 1, power + 3);
4698 build_recursive_room(t4, t1 + 1, x2 - 1, t2 - 1, power + 3);
4700 /* Make the keep itself: */
4713 /* Try to build a room */
4714 if ((xsize < 3) || (ysize < 3))
4716 for (y = y1; y < y2; y++)
4718 for (x = x1; x < x2; x++)
4720 place_inner_bold(y, x);
4728 /* Make outside walls */
4729 /* top and bottom */
4730 for (x = x1 + 1; x <= x2 - 1; x++)
4732 place_inner_bold(y1 + 1, x);
4733 place_inner_bold(y2 - 1, x);
4736 /* left and right */
4737 for (y = y1 + 1; y <= y2 - 1; y++)
4739 place_inner_bold(y, x1 + 1);
4740 place_inner_bold(y, x2 - 1);
4744 y = randint1(ysize - 3) + y1 + 1;
4749 place_floor_bold(y, x1 + 1);
4754 place_floor_bold(y, x2 - 1);
4757 /* Build the room */
4758 build_recursive_room(x1 + 2, y1 + 2, x2 - 2, y2 - 2, power + 3);
4763 /* Try and divide vertically */
4767 for (y = y1; y < y2; y++)
4769 for (x = x1; x < x2; x++)
4771 place_inner_bold(y, x);
4777 t1 = randint1(xsize - 2) + x1 + 1;
4778 build_recursive_room(x1, y1, t1, y2, power - 2);
4779 build_recursive_room(t1 + 1, y1, x2, y2, power - 2);
4784 /* Try and divide horizontally */
4788 for (y = y1; y < y2; y++)
4790 for (x = x1; x < x2; x++)
4792 place_inner_bold(y, x);
4798 t1 = randint1(ysize - 2) + y1 + 1;
4799 build_recursive_room(x1, y1, x2, t1, power - 2);
4800 build_recursive_room(x1, t1 + 1, x2, y2, power - 2);
4807 /* Build a castle */
4809 /* Driver routine: clear the region and call the recursive
4812 *This makes a vault that looks like a castle/ city in the dungeon.
4814 static void build_castle_vault(int x0, int y0, int xsize, int ysize)
4820 /* Pick a random room size */
4829 if (cheat_room) msg_print("Castle Vault");
4831 /* generate the room */
4832 for (y = y1 - 1; y <= y2 + 1; y++)
4834 for (x = x1 - 1; x <= x2 + 1; x++)
4836 cave[y][x].info |= (CAVE_ROOM | CAVE_ICKY);
4837 /* Make everything a floor */
4838 place_floor_bold(y, x);
4842 /* Make the castle */
4843 build_recursive_room(x1, y1, x2, y2, randint1(5));
4845 /* Fill with monsters and treasure, low difficulty */
4846 fill_treasure(x1, x2, y1, y2, randint1(3));
4851 * Add outer wall to a floored region
4852 * Note: no range checking is done so must be inside dungeon
4853 * This routine also stomps on doors
4855 static void add_outer_wall(int x, int y, int light,
4856 int x1, int y1, int x2, int y2)
4860 if (!in_bounds(y, x)) return;
4862 /* hack- check to see if square has been visited before
4863 * if so, then exit (use room flag to do this) */
4864 if (cave[y][x].info & CAVE_ROOM) return;
4867 cave[y][x].info |= CAVE_ROOM;
4869 if (is_floor_bold(y, x))
4871 for (i = -1; i <= 1; i++)
4873 for (j = -1; j <= 1; j++)
4875 if ((x + i >= x1) && (x + i <= x2) &&
4876 (y + j >= y1) && (y + j <= y2))
4878 add_outer_wall(x + i, y + j, light, x1, y1, x2, y2);
4879 if (light) cave[y][x].info |= CAVE_GLOW;
4884 else if (is_extra_bold(y, x))
4886 /* Set bounding walls */
4887 place_outer_bold(y, x);
4888 if (light) cave[y][x].info |= CAVE_GLOW;
4890 else if (cave[y][x].feat == FEAT_PERM_OUTER)
4892 /* Set bounding walls */
4893 if (light) cave[y][x].info |= CAVE_GLOW;
4899 * Hacked distance formula - gives the 'wrong' answer.
4900 * Used to build crypts
4902 static int dist2(int x1, int y1, int x2, int y2,
4903 int h1, int h2, int h3, int h4)
4909 /* Basically this works by taking the normal pythagorean formula
4910 * and using an expansion to express this in a way without the
4911 * square root. This approximate formula is then perturbed to give
4912 * the distorted results. (I found this by making a mistake when I was
4913 * trying to fix the circular rooms.)
4916 /* h1-h4 are constants that describe the metric */
4917 if (dx >= 2 * dy) return (dx + (dy * h1) / h2);
4918 if (dy >= 2 * dx) return (dy + (dx * h1) / h2);
4919 return (((dx + dy) * 128) / 181 +
4920 (dx * dx / (dy * h3) + dy * dy / (dx * h3)) * h4);
4921 /* 128/181 is approx. 1/sqrt(2) */
4926 * Build target vault.
4927 * This is made by two concentric "crypts" with perpendicular
4928 * walls creating the cross-hairs.
4930 static void build_target_vault(int x0, int y0, int xsize, int ysize)
4934 /* Make a random metric */
4936 h1 = randint1(32) - 16;
4939 h4 = randint1(32) - 16;
4941 if (cheat_room) msg_print("Target Vault");
4943 /* work out outer radius */
4954 for (x = x0 - rad; x <= x0 + rad; x++)
4956 for (y = y0 - rad; y <= y0 + rad; y++)
4958 /* clear room flag */
4959 cave[y][x].info &= ~(CAVE_ROOM);
4961 /* Vault - so is "icky" */
4962 cave[y][x].info |= CAVE_ICKY;
4964 if (dist2(y0, x0, y, x, h1, h2, h3, h4) <= rad - 1)
4966 /* inside- so is floor */
4967 place_floor_bold(y, x);
4971 /* make granite outside so arena works */
4972 place_extra_bold(y, x);
4975 /* proper boundary for arena */
4976 if (((y + rad) == y0) || ((y - rad) == y0) ||
4977 ((x + rad) == x0) || ((x - rad) == x0))
4979 place_extra_bold(y, x);
4984 /* Find visible outer walls and set to be FEAT_OUTER */
4985 add_outer_wall(x0, y0, FALSE, x0 - rad - 1, y0 - rad - 1,
4986 x0 + rad + 1, y0 + rad + 1);
4988 /* Add inner wall */
4989 for (x = x0 - rad / 2; x <= x0 + rad / 2; x++)
4991 for (y = y0 - rad / 2; y <= y0 + rad / 2; y++)
4993 if (dist2(y0, x0, y, x, h1, h2, h3, h4) == rad / 2)
4995 /* Make an internal wall */
4996 place_inner_bold(y, x);
5001 /* Add perpendicular walls */
5002 for (x = x0 - rad; x <= x0 + rad; x++)
5004 place_inner_bold(y0, x);
5007 for (y = y0 - rad; y <= y0 + rad; y++)
5009 place_inner_bold(y, x0);
5012 /* Make inner vault */
5013 for (y = y0 - 1; y <= y0 + 1; y++)
5015 place_inner_bold(y, x0 - 1);
5016 place_inner_bold(y, x0 + 1);
5018 for (x = x0 - 1; x <= x0 + 1; x++)
5020 place_inner_bold(y0 - 1, x);
5021 place_inner_bold(y0 + 1, x);
5024 place_floor_bold(y0, x0);
5027 /* Add doors to vault */
5028 /* get two distances so can place doors relative to centre */
5029 x = (rad - 2) / 4 + 1;
5032 add_door(x0 + x, y0);
5033 add_door(x0 + y, y0);
5034 add_door(x0 - x, y0);
5035 add_door(x0 - y, y0);
5036 add_door(x0, y0 + x);
5037 add_door(x0, y0 + y);
5038 add_door(x0, y0 - x);
5039 add_door(x0, y0 - y);
5041 /* Fill with stuff - medium difficulty */
5042 fill_treasure(x0 - rad, x0 + rad, y0 - rad, y0 + rad, randint1(3) + 3);
5046 #ifdef ALLOW_CAVERNS_AND_LAKES
5048 * This routine uses a modified version of the lake code to make a
5049 * distribution of some terrain type over the vault. This type
5050 * depends on the dungeon depth.
5052 * Miniture rooms are then scattered across the vault.
5054 static void build_elemental_vault(int x0, int y0, int xsiz, int ysiz)
5059 int xsize, ysize, xhsize, yhsize, x, y, i;
5063 if (cheat_room) msg_print("Elemental Vault");
5065 /* round to make sizes even */
5073 /* Earth vault (Rubble) */
5074 type = GEN_LAKE_TYPE_EARTH_VAULT;
5076 else if (dun_level < 50)
5078 /* Air vault (Trees) */
5079 type = GEN_LAKE_TYPE_AIR_VAULT;
5081 else if (dun_level < 75)
5083 /* Water vault (shallow water) */
5084 type = GEN_LAKE_TYPE_WATER_VAULT;
5088 /* Fire vault (shallow lava) */
5089 type = GEN_LAKE_TYPE_FIRE_VAULT;
5094 /* testing values for these parameters: feel free to adjust */
5095 grd = 1 << (randint0(3));
5097 /* want average of about 16 */
5098 roug = randint1(8) * randint1(4);
5100 /* Make up size of various componants */
5104 /* Deep water/lava */
5105 c1 = randint0(c3 / 2) + randint0(c3 / 2) - 5;
5107 /* Shallow boundary */
5111 generate_hmap(y0, x0, xsize, ysize, grd, roug, c3);
5113 /* Convert to normal format+ clean up */
5114 done = generate_lake(y0, x0, xsize, ysize, c1, c2, c3, type);
5117 /* Set icky flag because is a vault */
5118 for (x = 0; x <= xsize; x++)
5120 for (y = 0; y <= ysize; y++)
5122 cave[y0 - yhsize + y][x0 - xhsize + x].info |= CAVE_ICKY;
5126 /* make a few rooms in the vault */
5127 for (i = 1; i <= (xsize * ysize) / 50; i++)
5129 build_small_room(x0 + randint0(xsize - 4) - xsize / 2 + 2,
5130 y0 + randint0(ysize - 4) - ysize / 2 + 2);
5133 /* Fill with monsters and treasure, low difficulty */
5134 fill_treasure(x0 - xhsize + 1, x0 - xhsize + xsize - 1,
5135 y0 - yhsize + 1, y0 - yhsize + ysize - 1, randint1(5));
5137 #endif /* ALLOW_CAVERNS_AND_LAKES */
5143 static void build_type10(int by0, int bx0)
5145 int y0, x0, xsize, ysize, vtype;
5148 /* big enough to look good, small enough to be fairly common. */
5149 xsize = randint1(22) + 22;
5150 ysize = randint1(11) + 11;
5152 /* Allocate in room_map. If will not fit, exit */
5153 if (!room_alloc(xsize + 1, ysize + 1, FALSE, by0, bx0, &x0, &y0)) return;
5155 /* Boost the rating- higher than lesser vaults and lower than greater vaults */
5158 /* (Sometimes) Cause a special feeling */
5159 if ((dun_level <= 50) ||
5160 (randint1((dun_level - 40) * (dun_level - 40) + 1) < 400))
5162 good_item_flag = TRUE;
5165 /* Select type of vault */
5166 #ifdef ALLOW_CAVERNS_AND_LAKES
5167 vtype = randint1(15);
5168 #else /* ALLOW_CAVERNS_AND_LAKES */
5169 vtype = randint1(7);
5170 #endif /* ALLOW_CAVERNS_AND_LAKES */
5174 /* Build an appropriate room */
5175 case 1: case 9: build_bubble_vault(x0, y0, xsize, ysize); break;
5176 case 2: case 10: build_room_vault(x0, y0, xsize, ysize); break;
5177 case 3: case 11: build_cave_vault(x0, y0, xsize, ysize); break;
5178 case 4: case 12: build_maze_vault(x0, y0, xsize, ysize, TRUE); break;
5179 case 5: case 13: build_mini_c_vault(x0, y0, xsize, ysize); break;
5180 case 6: case 14: build_castle_vault(x0, y0, xsize, ysize); break;
5181 case 7: case 15: build_target_vault(x0, y0, xsize, ysize); break;
5182 #ifdef ALLOW_CAVERNS_AND_LAKES
5183 case 8: build_elemental_vault(x0, y0, xsize, ysize); break;
5184 #endif /* ALLOW_CAVERNS_AND_LAKES */
5185 /* I know how to add a few more... give me some time. */
5194 * Build an vertical oval room.
5195 * For every grid in the possible square, check the distance.
5196 * If it's less than the radius, make it a room square.
5198 * When done fill from the inside to find the walls,
5200 static void build_type11(int by0, int bx0)
5202 int rad, x, y, x0, y0;
5205 /* Occasional light */
5206 if ((randint1(dun_level) <= 15) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS)) light = TRUE;
5210 /* Allocate in room_map. If will not fit, exit */
5211 if (!room_alloc(rad * 2 + 1, rad * 2 + 1, FALSE, by0, bx0, &x0, &y0)) return;
5213 /* Make circular floor */
5214 for (x = x0 - rad; x <= x0 + rad; x++)
5216 for (y = y0 - rad; y <= y0 + rad; y++)
5218 if (distance(y0, x0, y, x) <= rad - 1)
5220 /* inside- so is floor */
5221 place_floor_bold(y, x);
5223 else if (distance(y0, x0, y, x) <= rad + 1)
5225 /* make granite outside so arena works */
5226 place_extra_bold(y, x);
5231 /* Find visible outer walls and set to be FEAT_OUTER */
5232 add_outer_wall(x0, y0, light, x0 - rad, y0 - rad, x0 + rad, y0 + rad);
5238 * For every grid in the possible square, check the (fake) distance.
5239 * If it's less than the radius, make it a room square.
5241 * When done fill from the inside to find the walls,
5243 static void build_type12(int by0, int bx0)
5245 int rad, x, y, x0, y0;
5247 bool emptyflag = TRUE;
5249 /* Make a random metric */
5251 h1 = randint1(32) - 16;
5254 h4 = randint1(32) - 16;
5256 /* Occasional light */
5257 if ((randint1(dun_level) <= 5) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS)) light = TRUE;
5261 /* Allocate in room_map. If will not fit, exit */
5262 if (!room_alloc(rad * 2 + 3, rad * 2 + 3, FALSE, by0, bx0, &x0, &y0)) return;
5265 for (x = x0 - rad; x <= x0 + rad; x++)
5267 for (y = y0 - rad; y <= y0 + rad; y++)
5269 /* clear room flag */
5270 cave[y][x].info &= ~(CAVE_ROOM);
5272 if (dist2(y0, x0, y, x, h1, h2, h3, h4) <= rad - 1)
5274 /* inside - so is floor */
5275 place_floor_bold(y, x);
5277 else if (distance(y0, x0, y, x) < 3)
5279 place_floor_bold(y, x);
5283 /* make granite outside so arena works */
5284 place_extra_bold(y, x);
5287 /* proper boundary for arena */
5288 if (((y + rad) == y0) || ((y - rad) == y0) ||
5289 ((x + rad) == x0) || ((x - rad) == x0))
5291 place_extra_bold(y, x);
5296 /* Find visible outer walls and set to be FEAT_OUTER */
5297 add_outer_wall(x0, y0, light, x0 - rad - 1, y0 - rad - 1,
5298 x0 + rad + 1, y0 + rad + 1);
5300 /* Check to see if there is room for an inner vault */
5301 for (x = x0 - 2; x <= x0 + 2; x++)
5303 for (y = y0 - 2; y <= y0 + 2; y++)
5305 if (!is_floor_bold(y, x))
5307 /* Wall in the way */
5313 if (emptyflag && one_in_(2))
5315 /* Build the vault */
5316 build_small_room(x0, y0);
5318 /* Place a treasure in the vault */
5319 place_object(y0, x0, 0L);
5321 /* Let's guard the treasure well */
5322 vault_monsters(y0, x0, randint0(2) + 3);
5324 /* Traps naturally */
5325 vault_traps(y0, x0, 4, 4, randint0(3) + 2);
5331 * Helper function for "trapped monster pit"
5333 static bool vault_aux_trapped_pit(int r_idx)
5335 monster_race *r_ptr = &r_info[r_idx];
5337 /* Validate the monster */
5338 if (!vault_monster_okay(r_idx)) return (FALSE);
5340 /* No wall passing monster */
5341 if (r_ptr->flags2 & (RF2_PASS_WALL | RF2_KILL_WALL)) return (FALSE);
5349 * Type 12 -- Trapped monster pits
5351 * A trapped monster pit is a "big" room with a straight corridor in
5352 * which wall opening traps are placed, and with two "inner" rooms
5353 * containing a "collection" of monsters of a given type organized in
5356 * The trapped monster pit appears as shown below, where the actual
5357 * monsters in each location depend on the type of the pit
5359 * #########################
5361 * ####################### #
5362 * #####001123454321100### #
5363 * ###0012234567654322100# #
5364 * ####################### #
5366 * # #######################
5367 * # #0012234567654322100###
5368 * # ###001123454321100#####
5369 * # #######################
5371 * #########################
5373 * Note that the monsters in the pit are now chosen by using "get_mon_num()"
5374 * to request 16 "appropriate" monsters, sorting them by level, and using
5375 * the "even" entries in this sorted list for the contents of the pit.
5377 * Hack -- all of the "dragons" in a "dragon" pit must be the same "color",
5378 * which is handled by requiring a specific "breath" attack for all of the
5379 * dragons. This may include "multi-hued" breath. Note that "wyrms" may
5380 * be present in many of the dragon pits, if they have the proper breath.
5382 * Note the use of the "get_mon_num_prep()" function, and the special
5383 * "get_mon_num_hook()" restriction function, to prepare the "monster
5384 * allocation table" in such a way as to optimize the selection of
5385 * "appropriate" non-unique monsters for the pit.
5387 * Note that the "get_mon_num()" function may (rarely) fail, in which case
5388 * the pit will be empty, and will not effect the level rating.
5390 * Note that "monster pits" will never contain "unique" monsters.
5392 static void build_type13(int by0, int bx0)
5394 static int placing[][3] = {
5395 {-2, -9, 0}, {-2, -8, 0}, {-3, -7, 0}, {-3, -6, 0},
5396 {+2, -9, 0}, {+2, -8, 0}, {+3, -7, 0}, {+3, -6, 0},
5397 {-2, +9, 0}, {-2, +8, 0}, {-3, +7, 0}, {-3, +6, 0},
5398 {+2, +9, 0}, {+2, +8, 0}, {+3, +7, 0}, {+3, +6, 0},
5399 {-2, -7, 1}, {-3, -5, 1}, {-3, -4, 1},
5400 {+2, -7, 1}, {+3, -5, 1}, {+3, -4, 1},
5401 {-2, +7, 1}, {-3, +5, 1}, {-3, +4, 1},
5402 {+2, +7, 1}, {+3, +5, 1}, {+3, +4, 1},
5403 {-2, -6, 2}, {-2, -5, 2}, {-3, -3, 2},
5404 {+2, -6, 2}, {+2, -5, 2}, {+3, -3, 2},
5405 {-2, +6, 2}, {-2, +5, 2}, {-3, +3, 2},
5406 {+2, +6, 2}, {+2, +5, 2}, {+3, +3, 2},
5407 {-2, -4, 3}, {-3, -2, 3},
5408 {+2, -4, 3}, {+3, -2, 3},
5409 {-2, +4, 3}, {-3, +2, 3},
5410 {+2, +4, 3}, {+3, +2, 3},
5411 {-2, -3, 4}, {-3, -1, 4},
5412 {+2, -3, 4}, {+3, -1, 4},
5413 {-2, +3, 4}, {-3, +1, 4},
5414 {+2, +3, 4}, {+3, +1, 4},
5415 {-2, -2, 5}, {-3, 0, 5}, {-2, +2, 5},
5416 {+2, -2, 5}, {+3, 0, 5}, {+2, +2, 5},
5417 {-2, -1, 6}, {-2, +1, 6},
5418 {+2, -1, 6}, {+2, +1, 6},
5419 {-2, 0, 7}, {+2, 0, 7},
5423 int y, x, y1, x1, y2, x2, xval, yval;
5432 int cur_pit_type = pick_vault_type(pit_types, d_info[dungeon_type].pit);
5433 vault_aux_type *n_ptr;
5435 /* Only in Angband */
5436 if (dungeon_type != 1) return;
5438 /* Try to allocate space for room. */
5439 if (!room_alloc(25, 13, TRUE, by0, bx0, &xval, &yval)) return;
5441 /* No type available */
5442 if (cur_pit_type < 0) return;
5444 n_ptr = &pit_types[cur_pit_type];
5446 /* Process a preparation function if necessary */
5447 if (n_ptr->prep_func) (*(n_ptr->prep_func))();
5455 /* Fill with inner walls */
5456 for (y = y1 - 1; y <= y2 + 1; y++)
5458 for (x = x1 - 1; x <= x2 + 1; x++)
5460 c_ptr = &cave[y][x];
5461 place_inner_grid(c_ptr);
5462 c_ptr->info |= (CAVE_ROOM);
5466 /* Place the floor area 1 */
5467 for (x = x1 + 3; x <= x2 - 3; x++)
5469 c_ptr = &cave[yval-2][x];
5470 place_floor_grid(c_ptr);
5471 add_cave_info(yval-2, x, CAVE_ICKY);
5473 c_ptr = &cave[yval+2][x];
5474 place_floor_grid(c_ptr);
5475 add_cave_info(yval+2, x, CAVE_ICKY);
5478 /* Place the floor area 2 */
5479 for (x = x1 + 5; x <= x2 - 5; x++)
5481 c_ptr = &cave[yval-3][x];
5482 place_floor_grid(c_ptr);
5483 add_cave_info(yval-3, x, CAVE_ICKY);
5485 c_ptr = &cave[yval+3][x];
5486 place_floor_grid(c_ptr);
5487 add_cave_info(yval+3, x, CAVE_ICKY);
5491 for (x = x1; x <= x2; x++)
5493 c_ptr = &cave[yval][x];
5494 place_floor_grid(c_ptr);
5495 c_ptr = &cave[y1][x];
5496 place_floor_grid(c_ptr);
5497 c_ptr = &cave[y2][x];
5498 place_floor_grid(c_ptr);
5501 /* Place the outer walls */
5502 for (y = y1 - 1; y <= y2 + 1; y++)
5504 c_ptr = &cave[y][x1 - 1];
5505 place_outer_grid(c_ptr);
5506 c_ptr = &cave[y][x2 + 1];
5507 place_outer_grid(c_ptr);
5509 for (x = x1 - 1; x <= x2 + 1; x++)
5511 c_ptr = &cave[y1 - 1][x];
5512 place_outer_grid(c_ptr);
5513 c_ptr = &cave[y2 + 1][x];
5514 place_outer_grid(c_ptr);
5517 /* Random corridor */
5520 for (y = y1; y <= yval; y++)
5522 place_floor_bold(y, x2);
5523 place_solid_bold(y, x1-1);
5525 for (y = yval; y <= y2 + 1; y++)
5527 place_floor_bold(y, x1);
5528 place_solid_bold(y, x2+1);
5533 for (y = yval; y <= y2 + 1; y++)
5535 place_floor_bold(y, x1);
5536 place_solid_bold(y, x2+1);
5538 for (y = y1; y <= yval; y++)
5540 place_floor_bold(y, x2);
5541 place_solid_bold(y, x1-1);
5545 /* Place the wall open trap */
5546 cave[yval][xval].mimic = cave[yval][xval].feat;
5547 cave[yval][xval].feat = FEAT_TRAP_OPEN;
5549 /* Prepare allocation table */
5550 get_mon_num_prep(n_ptr->hook_func, vault_aux_trapped_pit);
5552 align.sub_align = SUB_ALIGN_NEUTRAL;
5554 /* Pick some monster types */
5555 for (i = 0; i < 16; i++)
5557 int r_idx = 0, attempts = 100;
5558 monster_race *r_ptr = NULL;
5562 /* Get a (hard) monster type */
5563 r_idx = get_mon_num(dun_level + 0);
5564 r_ptr = &r_info[r_idx];
5566 /* Decline incorrect alignment */
5567 if (monster_has_hostile_align(&align, 0, 0, r_ptr)) continue;
5569 /* Accept this monster */
5573 /* Notice failure */
5574 if (!r_idx || !attempts) return;
5576 /* Note the alignment */
5577 if (r_ptr->flags3 & RF3_EVIL) align.sub_align |= SUB_ALIGN_EVIL;
5578 if (r_ptr->flags3 & RF3_GOOD) align.sub_align |= SUB_ALIGN_GOOD;
5583 /* Sort the entries */
5584 for (i = 0; i < 16 - 1; i++)
5586 /* Sort the entries */
5587 for (j = 0; j < 16 - 1; j++)
5592 int p1 = r_info[what[i1]].level;
5593 int p2 = r_info[what[i2]].level;
5599 what[i1] = what[i2];
5610 msg_format("%s%s¤Î櫥ԥåÈ", n_ptr->name, pit_subtype_string(cur_pit_type, FALSE));
5612 msg_format("Trapped monster pit (%s%s)", n_ptr->name, pit_subtype_string(cur_pit_type, FALSE));
5616 /* Select the entries */
5617 for (i = 0; i < 8; i++)
5619 /* Every other entry */
5620 what[i] = what[i * 2];
5625 msg_print(r_name + r_info[what[i]].name);
5629 /* Increase the level rating */
5632 /* (Sometimes) Cause a "special feeling" (for "Monster Pits") */
5633 if ((dun_level <= 40) && (randint1(dun_level * dun_level + 50) < 300))
5635 good_item_flag = TRUE;
5639 for (i = 0; placing[i][2] >= 0; i++)
5641 y = yval + placing[i][0];
5642 x = xval + placing[i][1];
5643 place_monster_aux(0, y, x, what[placing[i][2]], PM_NO_KAGE);
5649 * Type 14 -- trapped rooms
5651 * A special trap is placed at center of the room
5653 static void build_type14(int by0, int bx0)
5655 int y, x, y2, x2, yval, xval;
5656 int y1, x1, xsize, ysize;
5663 /* Pick a room size */
5669 xsize = x1 + x2 + 1;
5670 ysize = y1 + y2 + 1;
5672 /* Try to allocate space for room. If fails, exit */
5673 if (!room_alloc(xsize + 2, ysize + 2, FALSE, by0, bx0, &xval, &yval)) return;
5675 /* Choose lite or dark */
5676 light = ((dun_level <= randint1(25)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS));
5679 /* Get corner values */
5680 y1 = yval - ysize / 2;
5681 x1 = xval - xsize / 2;
5682 y2 = yval + (ysize - 1) / 2;
5683 x2 = xval + (xsize - 1) / 2;
5686 /* Place a full floor under the room */
5687 for (y = y1 - 1; y <= y2 + 1; y++)
5689 for (x = x1 - 1; x <= x2 + 1; x++)
5691 c_ptr = &cave[y][x];
5692 place_floor_grid(c_ptr);
5693 c_ptr->info |= (CAVE_ROOM);
5694 if (light) c_ptr->info |= (CAVE_GLOW);
5698 /* Walls around the room */
5699 for (y = y1 - 1; y <= y2 + 1; y++)
5701 c_ptr = &cave[y][x1 - 1];
5702 place_outer_grid(c_ptr);
5703 c_ptr = &cave[y][x2 + 1];
5704 place_outer_grid(c_ptr);
5706 for (x = x1 - 1; x <= x2 + 1; x++)
5708 c_ptr = &cave[y1 - 1][x];
5709 place_outer_grid(c_ptr);
5710 c_ptr = &cave[y2 + 1][x];
5711 place_outer_grid(c_ptr);
5714 if (dun_level < 30 + randint1(30))
5715 trap = FEAT_TRAP_PIRANHA;
5717 trap = FEAT_TRAP_ARMAGEDDON;
5719 /* Place a special trap */
5720 c_ptr = &cave[rand_spread(yval, ysize/4)][rand_spread(xval, xsize/4)];
5721 c_ptr->mimic = c_ptr->feat;
5728 msg_format("%s¤ÎÉô²°", f_name + f_info[trap].name);
5730 msg_format("Room of %s", f_name + f_info[trap].name);
5737 * Attempt to build a room of the given type at the given block
5739 * Note that we restrict the number of "crowded" rooms to reduce
5740 * the chance of overflowing the monster list during level creation.
5742 bool room_build(int by0, int bx0, int typ)
5744 /* Restrict level */
5745 if ((dun_level < roomdep[typ]) && !ironman_rooms) return FALSE;
5747 /* Restrict "crowded" rooms */
5748 if ((dun->crowded >= 2) && ((typ == ROOM_BUILD_TYPE_NEST) ||
5749 (typ == ROOM_BUILD_TYPE_PIT) || (typ == ROOM_BUILD_TYPE_TRAP_PIT))) return FALSE;
5754 /* Build an appropriate room */
5755 case ROOM_BUILD_TYPE_NORMAL: build_type1(by0, bx0); break;
5756 case ROOM_BUILD_TYPE_OVERLAP: build_type2(by0, bx0); break;
5757 case ROOM_BUILD_TYPE_CROSS: build_type3(by0, bx0); break;
5758 case ROOM_BUILD_TYPE_INNER_FEAT: build_type4(by0, bx0); break;
5759 case ROOM_BUILD_TYPE_NEST: build_type5(by0, bx0, FALSE); break;
5760 case ROOM_BUILD_TYPE_PIT: build_type6(by0, bx0, FALSE); break;
5761 case ROOM_BUILD_TYPE_LESSER_VAULT: build_type7(by0, bx0); break;
5762 case ROOM_BUILD_TYPE_GREATER_VAULT: build_type8(by0, bx0); break;
5763 case ROOM_BUILD_TYPE_FRACAVE: build_type9(by0, bx0); break;
5764 case ROOM_BUILD_TYPE_RANDOM_VAULT: build_type10(by0, bx0); break;
5765 case ROOM_BUILD_TYPE_OVAL: build_type11(by0, bx0); break;
5766 case ROOM_BUILD_TYPE_CRYPT: build_type12(by0, bx0); break;
5767 case ROOM_BUILD_TYPE_TRAP_PIT: build_type13(by0, bx0); break;
5768 case ROOM_BUILD_TYPE_TRAP: build_type14(by0, bx0); break;
5771 default: return FALSE;