3 * Purpose: make rooms. Used by generate.c when creating dungeons.
7 * Copyright (c) 1989 James E. Wilson, Robert A. Koeneke
9 * This software may be copied and distributed for educational, research, and
10 * not for profit purposes provided that this copyright and statement are
11 * included in all such copies.
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);
56 static void place_secret_door(int y, int x)
58 if (d_info[dungeon_type].flags1 & DF1_NO_DOORS)
60 place_floor_bold(y, x);
64 cave_type *c_ptr = &cave[y][x];
66 /* Create secret door */
67 place_closed_door(y, x);
70 c_ptr->mimic = fill_type[randint0(100)];
72 /* Floor type terrain cannot hide a door */
73 if (!(c_ptr->mimic & 0x20))
75 c_ptr->feat = c_ptr->mimic;
79 c_ptr->info &= ~(CAVE_FLOOR);
84 * This funtion makes a very small room centred at (x0, y0)
85 * This is used in crypts, and random elemental vaults.
87 * Note - this should be used only on allocated regions
88 * within another room.
90 static void build_small_room(int x0, int y0)
94 for (y = y0 - 1; y <= y0 + 1; y++)
96 place_inner_bold(y, x0 - 1);
97 place_inner_bold(y, x0 + 1);
100 for (x = x0 - 1; x <= x0 + 1; x++)
102 place_inner_bold(y0 - 1, x);
103 place_inner_bold(y0 + 1, x);
106 /* Place a secret door on one side */
109 case 0: place_secret_door(y0, x0 - 1); break;
110 case 1: place_secret_door(y0, x0 + 1); break;
111 case 2: place_secret_door(y0 - 1, x0); break;
112 case 3: place_secret_door(y0 + 1, x0); break;
115 /* Add inner open space */
116 place_floor_bold(y0, x0);
121 * This function tunnels around a room if
122 * it will cut off part of a cave system.
124 static void check_room_boundary(int x1, int y1, int x2, int y2)
127 bool old_is_floor, new_is_floor;
133 old_is_floor = get_is_floor(x1 - 1, y1);
136 * Count the number of floor-wall boundaries around the room
137 * Note: diagonal squares are ignored since the player can move diagonally
138 * to bypass these if needed.
141 /* Above the top boundary */
142 for (x = x1; x <= x2; x++)
144 new_is_floor = get_is_floor(x, y1 - 1);
146 /* Increment counter if they are different */
147 if (new_is_floor != old_is_floor) count++;
149 old_is_floor = new_is_floor;
153 for (y = y1; y <= y2; y++)
155 new_is_floor = get_is_floor(x2 + 1, y);
157 /* increment counter if they are different */
158 if (new_is_floor != old_is_floor) count++;
160 old_is_floor = new_is_floor;
163 /* Bottom boundary */
164 for (x = x2; x >= x1; x--)
166 new_is_floor = get_is_floor(x, y2 + 1);
168 /* increment counter if they are different */
169 if (new_is_floor != old_is_floor) count++;
171 old_is_floor = new_is_floor;
175 for (y = y2; y >= y1; y--)
177 new_is_floor = get_is_floor(x1 - 1, y);
179 /* increment counter if they are different */
180 if (new_is_floor != old_is_floor) count++;
182 old_is_floor = new_is_floor;
185 /* If all the same, or only one connection exit. */
186 if (count <= 2) return;
189 /* Tunnel around the room so to prevent problems with caves */
190 for (y = y1; y <= y2; y++)
192 for (x = x1; x <= x2; x++)
201 * This function is used to allocate the space needed by a room in the room_map
203 * x, y represent the size of the room (0...x-1) by (0...y-1).
204 * crowded is used to denote a monset nest.
205 * by0, bx0 are the positions in the room_map array given to the build_type'x'
207 * xx, yy are the returned center of the allocated room in coordinates for
208 * cave.feat and cave.info etc.
210 static bool room_alloc(int x, int y, bool crowded, int by0, int bx0, int *xx, int *yy)
212 int temp, bx1, bx2, by1, by2, by, bx;
214 /* Calculate number of room_map squares to allocate */
216 /* temp is total number along width */
217 temp = ((x - 1) / BLOCK_WID) + 1;
219 /* bx2 = ending block */
220 bx2 = temp / 2 + bx0;
222 /* bx1 = starting block (Note: rounding taken care of here.) */
223 bx1 = bx2 + 1 - temp;
225 /* temp is total number along height */
226 temp = ((y - 1) / BLOCK_HGT) + 1;
228 /* by2 = ending block */
229 by2 = temp / 2 + by0;
231 /* by1 = starting block */
232 by1 = by2 + 1 - temp;
235 /* Never run off the screen */
236 if ((by1 < 0) || (by2 >= dun->row_rooms)) return (FALSE);
237 if ((bx1 < 0) || (bx2 >= dun->col_rooms)) return (FALSE);
239 /* Verify open space */
240 for (by = by1; by <= by2; by++)
242 for (bx = bx1; bx <= bx2; bx++)
244 if (dun->room_map[by][bx]) return (FALSE);
248 /* It is *extremely* important that the following calculation */
249 /* be *exactly* correct to prevent memory errors XXX XXX XXX */
251 /* Acquire the location of the room */
252 *yy = ((by1 + by2 + 1) * BLOCK_HGT) / 2;
253 *xx = ((bx1 + bx2 + 1) * BLOCK_WID) / 2;
256 /* Save the room location */
257 if (dun->cent_n < CENT_MAX)
259 dun->cent[dun->cent_n].y = *yy;
260 dun->cent[dun->cent_n].x = *xx;
264 /* Reserve some blocks */
265 for (by = by1; by <= by2; by++)
267 for (bx = bx1; bx <= bx2; bx++)
269 dun->room_map[by][bx] = TRUE;
273 /* Count "crowded" rooms */
274 if (crowded) dun->crowded++;
277 * Hack- See if room will cut off a cavern.
278 * If so, fix by tunneling outside the room in such a way as to connect the caves.
280 check_room_boundary(*xx - x / 2 - 1, *yy - y / 2 - 1,
281 *xx + (x - 1) / 2 + 1, *yy + (y - 1) / 2 + 1);
288 * Room building routines.
294 * 4 -- large room with features
298 * 8 -- greater vaults
300 * 10 -- random vaults
301 * 11 -- circular rooms
303 * 13 -- trapped monster pits
309 * Type 1 -- normal rectangular rooms
311 static void build_type1(int by0, int bx0)
313 int y, x, y2, x2, yval, xval;
314 int y1, x1, xsize, ysize;
320 /* Pick a room size */
329 /* Try to allocate space for room. If fails, exit */
330 if (!room_alloc(xsize + 2, ysize + 2, FALSE, by0, bx0, &xval, &yval)) return;
332 /* Choose lite or dark */
333 light = ((dun_level <= randint1(25)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS));
336 /* Get corner values */
337 y1 = yval - ysize / 2;
338 x1 = xval - xsize / 2;
339 y2 = yval + (ysize - 1) / 2;
340 x2 = xval + (xsize - 1) / 2;
343 /* Place a full floor under the room */
344 for (y = y1 - 1; y <= y2 + 1; y++)
346 for (x = x1 - 1; x <= x2 + 1; x++)
349 place_floor_grid(c_ptr);
350 c_ptr->info |= (CAVE_ROOM);
351 if (light) c_ptr->info |= (CAVE_GLOW);
355 /* Walls around the room */
356 for (y = y1 - 1; y <= y2 + 1; y++)
358 c_ptr = &cave[y][x1 - 1];
359 place_outer_grid(c_ptr);
360 c_ptr = &cave[y][x2 + 1];
361 place_outer_grid(c_ptr);
363 for (x = x1 - 1; x <= x2 + 1; x++)
365 c_ptr = &cave[y1 - 1][x];
366 place_outer_grid(c_ptr);
367 c_ptr = &cave[y2 + 1][x];
368 place_outer_grid(c_ptr);
372 /* Hack -- Occasional pillar room */
375 for (y = y1; y <= y2; y += 2)
377 for (x = x1; x <= x2; x += 2)
380 place_inner_grid(c_ptr);
385 /* Hack -- Occasional room with four pillars */
386 else if (one_in_(20))
388 if ((y1 + 4 < y2) && (x1 + 4 < x2))
390 c_ptr = &cave[y1 + 1][x1 + 1];
391 place_inner_grid(c_ptr);
393 c_ptr = &cave[y1 + 1][x2 - 1];
394 place_inner_grid(c_ptr);
396 c_ptr = &cave[y2 - 1][x1 + 1];
397 place_inner_grid(c_ptr);
399 c_ptr = &cave[y2 - 1][x2 - 1];
400 place_inner_grid(c_ptr);
404 /* Hack -- Occasional ragged-edge room */
405 else if (one_in_(50))
407 for (y = y1 + 2; y <= y2 - 2; y += 2)
409 c_ptr = &cave[y][x1];
410 place_inner_grid(c_ptr);
411 c_ptr = &cave[y][x2];
412 place_inner_grid(c_ptr);
414 for (x = x1 + 2; x <= x2 - 2; x += 2)
416 c_ptr = &cave[y1][x];
417 place_inner_grid(c_ptr);
418 c_ptr = &cave[y2][x];
419 place_inner_grid(c_ptr);
422 /* Hack -- Occasional divided room */
423 else if (one_in_(50))
425 if (randint1(100) < 50)
427 /* Horizontal wall */
428 for (x = x1; x <= x2; x++)
430 place_inner_bold(yval, x);
433 /* Prevent edge of wall from being tunneled */
434 place_solid_bold(yval, x1 - 1);
435 place_solid_bold(yval, x2 + 1);
440 for (y = y1; y <= y2; y++)
442 place_inner_bold(y, xval);
445 /* Prevent edge of wall from being tunneled */
446 place_solid_bold(y1 - 1, xval);
447 place_solid_bold(y2 + 1, xval);
450 place_random_door(yval, xval);
456 * Type 2 -- Overlapping rectangular rooms
458 static void build_type2(int by0, int bx0)
460 int y, x, xval, yval;
461 int y1a, x1a, y2a, x2a;
462 int y1b, x1b, y2b, x2b;
467 /* Try to allocate space for room. If fails, exit */
468 if (!room_alloc(25, 11, FALSE, by0, bx0, &xval, &yval)) return;
470 /* Choose lite or dark */
471 light = ((dun_level <= randint1(25)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS));
473 /* Determine extents of the first room */
474 y1a = yval - randint1(4);
475 y2a = yval + randint1(3);
476 x1a = xval - randint1(11);
477 x2a = xval + randint1(10);
479 /* Determine extents of the second room */
480 y1b = yval - randint1(3);
481 y2b = yval + randint1(4);
482 x1b = xval - randint1(10);
483 x2b = xval + randint1(11);
486 /* Place a full floor for room "a" */
487 for (y = y1a - 1; y <= y2a + 1; y++)
489 for (x = x1a - 1; x <= x2a + 1; x++)
492 place_floor_grid(c_ptr);
493 c_ptr->info |= (CAVE_ROOM);
494 if (light) c_ptr->info |= (CAVE_GLOW);
498 /* Place a full floor for room "b" */
499 for (y = y1b - 1; y <= y2b + 1; y++)
501 for (x = x1b - 1; x <= x2b + 1; x++)
504 place_floor_grid(c_ptr);
505 c_ptr->info |= (CAVE_ROOM);
506 if (light) c_ptr->info |= (CAVE_GLOW);
511 /* Place the walls around room "a" */
512 for (y = y1a - 1; y <= y2a + 1; y++)
514 c_ptr = &cave[y][x1a - 1];
515 place_outer_grid(c_ptr);
516 c_ptr = &cave[y][x2a + 1];
517 place_outer_grid(c_ptr);
519 for (x = x1a - 1; x <= x2a + 1; x++)
521 c_ptr = &cave[y1a - 1][x];
522 place_outer_grid(c_ptr);
523 c_ptr = &cave[y2a + 1][x];
524 place_outer_grid(c_ptr);
527 /* Place the walls around room "b" */
528 for (y = y1b - 1; y <= y2b + 1; y++)
530 c_ptr = &cave[y][x1b - 1];
531 place_outer_grid(c_ptr);
532 c_ptr = &cave[y][x2b + 1];
533 place_outer_grid(c_ptr);
535 for (x = x1b - 1; x <= x2b + 1; x++)
537 c_ptr = &cave[y1b - 1][x];
538 place_outer_grid(c_ptr);
539 c_ptr = &cave[y2b + 1][x];
540 place_outer_grid(c_ptr);
545 /* Replace the floor for room "a" */
546 for (y = y1a; y <= y2a; y++)
548 for (x = x1a; x <= x2a; x++)
551 place_floor_grid(c_ptr);
555 /* Replace the floor for room "b" */
556 for (y = y1b; y <= y2b; y++)
558 for (x = x1b; x <= x2b; x++)
561 place_floor_grid(c_ptr);
569 * Type 3 -- Cross shaped rooms
571 * Builds a room at a row, column coordinate
573 * Room "a" runs north/south, and Room "b" runs east/east
574 * So the "central pillar" runs from x1a, y1b to x2a, y2b.
576 * Note that currently, the "center" is always 3x3, but I think that
577 * the code below will work (with "bounds checking") for 5x5, or even
578 * for unsymetric values like 4x3 or 5x3 or 3x4 or 3x5, or even larger.
580 static void build_type3(int by0, int bx0)
582 int y, x, dy, dx, wy, wx;
583 int y1a, x1a, y2a, x2a;
584 int y1b, x1b, y2b, x2b;
590 /* Try to allocate space for room. */
591 if (!room_alloc(25, 11, FALSE, by0, bx0, &xval, &yval)) return;
593 /* Choose lite or dark */
594 light = ((dun_level <= randint1(25)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS));
596 /* For now, always 3x3 */
599 /* Pick max vertical size (at most 4) */
600 dy = rand_range(3, 4);
602 /* Pick max horizontal size (at most 15) */
603 dx = rand_range(3, 11);
606 /* Determine extents of the north/south room */
612 /* Determine extents of the east/west room */
619 /* Place a full floor for room "a" */
620 for (y = y1a - 1; y <= y2a + 1; y++)
622 for (x = x1a - 1; x <= x2a + 1; x++)
625 place_floor_grid(c_ptr);
626 c_ptr->info |= (CAVE_ROOM);
627 if (light) c_ptr->info |= (CAVE_GLOW);
631 /* Place a full floor for room "b" */
632 for (y = y1b - 1; y <= y2b + 1; y++)
634 for (x = x1b - 1; x <= x2b + 1; x++)
637 place_floor_grid(c_ptr);
638 c_ptr->info |= (CAVE_ROOM);
639 if (light) c_ptr->info |= (CAVE_GLOW);
644 /* Place the walls around room "a" */
645 for (y = y1a - 1; y <= y2a + 1; y++)
647 c_ptr = &cave[y][x1a - 1];
648 place_outer_grid(c_ptr);
649 c_ptr = &cave[y][x2a + 1];
650 place_outer_grid(c_ptr);
652 for (x = x1a - 1; x <= x2a + 1; x++)
654 c_ptr = &cave[y1a - 1][x];
655 place_outer_grid(c_ptr);
656 c_ptr = &cave[y2a + 1][x];
657 place_outer_grid(c_ptr);
660 /* Place the walls around room "b" */
661 for (y = y1b - 1; y <= y2b + 1; y++)
663 c_ptr = &cave[y][x1b - 1];
664 place_outer_grid(c_ptr);
665 c_ptr = &cave[y][x2b + 1];
666 place_outer_grid(c_ptr);
668 for (x = x1b - 1; x <= x2b + 1; x++)
670 c_ptr = &cave[y1b - 1][x];
671 place_outer_grid(c_ptr);
672 c_ptr = &cave[y2b + 1][x];
673 place_outer_grid(c_ptr);
677 /* Replace the floor for room "a" */
678 for (y = y1a; y <= y2a; y++)
680 for (x = x1a; x <= x2a; x++)
683 place_floor_grid(c_ptr);
687 /* Replace the floor for room "b" */
688 for (y = y1b; y <= y2b; y++)
690 for (x = x1b; x <= x2b; x++)
693 place_floor_grid(c_ptr);
699 /* Special features (3/4) */
702 /* Large solid middle pillar */
705 for (y = y1b; y <= y2b; y++)
707 for (x = x1a; x <= x2a; x++)
710 place_inner_grid(c_ptr);
716 /* Inner treasure vault */
719 /* Build the vault */
720 for (y = y1b; y <= y2b; y++)
722 c_ptr = &cave[y][x1a];
723 place_inner_grid(c_ptr);
724 c_ptr = &cave[y][x2a];
725 place_inner_grid(c_ptr);
727 for (x = x1a; x <= x2a; x++)
729 c_ptr = &cave[y1b][x];
730 place_inner_grid(c_ptr);
731 c_ptr = &cave[y2b][x];
732 place_inner_grid(c_ptr);
735 /* Place a secret door on the inner room */
738 case 0: place_secret_door(y1b, xval); break;
739 case 1: place_secret_door(y2b, xval); break;
740 case 2: place_secret_door(yval, x1a); break;
741 case 3: place_secret_door(yval, x2a); break;
744 /* Place a treasure in the vault */
745 place_object(yval, xval, FALSE, FALSE);
747 /* Let's guard the treasure well */
748 vault_monsters(yval, xval, randint0(2) + 3);
750 /* Traps naturally */
751 vault_traps(yval, xval, 4, 4, randint0(3) + 2);
759 /* Occasionally pinch the center shut */
762 /* Pinch the east/west sides */
763 for (y = y1b; y <= y2b; y++)
765 if (y == yval) continue;
766 c_ptr = &cave[y][x1a - 1];
767 place_inner_grid(c_ptr);
768 c_ptr = &cave[y][x2a + 1];
769 place_inner_grid(c_ptr);
772 /* Pinch the north/south sides */
773 for (x = x1a; x <= x2a; x++)
775 if (x == xval) continue;
776 c_ptr = &cave[y1b - 1][x];
777 place_inner_grid(c_ptr);
778 c_ptr = &cave[y2b + 1][x];
779 place_inner_grid(c_ptr);
782 /* Sometimes shut using secret doors */
785 place_secret_door(yval, x1a - 1);
786 place_secret_door(yval, x2a + 1);
787 place_secret_door(y1b - 1, xval);
788 place_secret_door(y2b + 1, xval);
792 /* Occasionally put a "plus" in the center */
795 c_ptr = &cave[yval][xval];
796 place_inner_grid(c_ptr);
797 c_ptr = &cave[y1b][xval];
798 place_inner_grid(c_ptr);
799 c_ptr = &cave[y2b][xval];
800 place_inner_grid(c_ptr);
801 c_ptr = &cave[yval][x1a];
802 place_inner_grid(c_ptr);
803 c_ptr = &cave[yval][x2a];
804 place_inner_grid(c_ptr);
807 /* Occasionally put a pillar in the center */
810 c_ptr = &cave[yval][xval];
811 place_inner_grid(c_ptr);
821 * Type 4 -- Large room with inner features
823 * Possible sub-types:
824 * 1 - Just an inner room with one door
825 * 2 - An inner room within an inner room
826 * 3 - An inner room with pillar(s)
827 * 4 - Inner room has a maze
828 * 5 - A set of four inner rooms
830 static void build_type4(int by0, int bx0)
833 int y2, x2, tmp, yval, xval;
838 /* Try to allocate space for room. */
839 if (!room_alloc(25, 11, FALSE, by0, bx0, &xval, &yval)) return;
841 /* Choose lite or dark */
842 light = ((dun_level <= randint1(25)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS));
850 /* Place a full floor under the room */
851 for (y = y1 - 1; y <= y2 + 1; y++)
853 for (x = x1 - 1; x <= x2 + 1; x++)
856 place_floor_grid(c_ptr);
857 c_ptr->info |= (CAVE_ROOM);
858 if (light) c_ptr->info |= (CAVE_GLOW);
863 for (y = y1 - 1; y <= y2 + 1; y++)
865 c_ptr = &cave[y][x1 - 1];
866 place_outer_grid(c_ptr);
867 c_ptr = &cave[y][x2 + 1];
868 place_outer_grid(c_ptr);
870 for (x = x1 - 1; x <= x2 + 1; x++)
872 c_ptr = &cave[y1 - 1][x];
873 place_outer_grid(c_ptr);
874 c_ptr = &cave[y2 + 1][x];
875 place_outer_grid(c_ptr);
885 /* The inner walls */
886 for (y = y1 - 1; y <= y2 + 1; y++)
888 c_ptr = &cave[y][x1 - 1];
889 place_inner_grid(c_ptr);
890 c_ptr = &cave[y][x2 + 1];
891 place_inner_grid(c_ptr);
893 for (x = x1 - 1; x <= x2 + 1; x++)
895 c_ptr = &cave[y1 - 1][x];
896 place_inner_grid(c_ptr);
897 c_ptr = &cave[y2 + 1][x];
898 place_inner_grid(c_ptr);
902 /* Inner room variations */
905 /* Just an inner room with a monster */
908 /* Place a secret door */
911 case 1: place_secret_door(y1 - 1, xval); break;
912 case 2: place_secret_door(y2 + 1, xval); break;
913 case 3: place_secret_door(yval, x1 - 1); break;
914 case 4: place_secret_door(yval, x2 + 1); break;
917 /* Place a monster in the room */
918 vault_monsters(yval, xval, 1);
923 /* Treasure Vault (with a door) */
926 /* Place a secret door */
929 case 1: place_secret_door(y1 - 1, xval); break;
930 case 2: place_secret_door(y2 + 1, xval); break;
931 case 3: place_secret_door(yval, x1 - 1); break;
932 case 4: place_secret_door(yval, x2 + 1); break;
935 /* Place another inner room */
936 for (y = yval - 1; y <= yval + 1; y++)
938 for (x = xval - 1; x <= xval + 1; x++)
940 if ((x == xval) && (y == yval)) continue;
942 place_inner_grid(c_ptr);
946 /* Place a locked door on the inner room */
949 case 1: place_locked_door(yval - 1, xval); break;
950 case 2: place_locked_door(yval + 1, xval); break;
951 case 3: place_locked_door(yval, xval - 1); break;
952 case 4: place_locked_door(yval, xval + 1); break;
955 /* Monsters to guard the "treasure" */
956 vault_monsters(yval, xval, randint1(3) + 2);
959 if (randint0(100) < 80)
961 place_object(yval, xval, FALSE, FALSE);
967 place_random_stairs(yval, xval);
970 /* Traps to protect the treasure */
971 vault_traps(yval, xval, 4, 10, 2 + randint1(3));
976 /* Inner pillar(s). */
979 /* Place a secret door */
982 case 1: place_secret_door(y1 - 1, xval); break;
983 case 2: place_secret_door(y2 + 1, xval); break;
984 case 3: place_secret_door(yval, x1 - 1); break;
985 case 4: place_secret_door(yval, x2 + 1); break;
988 /* Large Inner Pillar */
989 for (y = yval - 1; y <= yval + 1; y++)
991 for (x = xval - 1; x <= xval + 1; x++)
994 place_inner_grid(c_ptr);
998 /* Occasionally, two more Large Inner Pillars */
1002 for (y = yval - 1; y <= yval + 1; y++)
1004 for (x = xval - 5 - tmp; x <= xval - 3 - tmp; x++)
1006 c_ptr = &cave[y][x];
1007 place_inner_grid(c_ptr);
1009 for (x = xval + 3 + tmp; x <= xval + 5 + tmp; x++)
1011 c_ptr = &cave[y][x];
1012 place_inner_grid(c_ptr);
1017 /* Occasionally, some Inner rooms */
1020 /* Long horizontal walls */
1021 for (x = xval - 5; x <= xval + 5; x++)
1023 c_ptr = &cave[yval - 1][x];
1024 place_inner_grid(c_ptr);
1025 c_ptr = &cave[yval + 1][x];
1026 place_inner_grid(c_ptr);
1029 /* Close off the left/right edges */
1030 c_ptr = &cave[yval][xval - 5];
1031 place_inner_grid(c_ptr);
1032 c_ptr = &cave[yval][xval + 5];
1033 place_inner_grid(c_ptr);
1035 /* Secret doors (random top/bottom) */
1036 place_secret_door(yval - 3 + (randint1(2) * 2), xval - 3);
1037 place_secret_door(yval - 3 + (randint1(2) * 2), xval + 3);
1040 vault_monsters(yval, xval - 2, randint1(2));
1041 vault_monsters(yval, xval + 2, randint1(2));
1044 if (one_in_(3)) place_object(yval, xval - 2, FALSE, FALSE);
1045 if (one_in_(3)) place_object(yval, xval + 2, FALSE, FALSE);
1054 /* Place a secret door */
1055 switch (randint1(4))
1057 case 1: place_secret_door(y1 - 1, xval); break;
1058 case 2: place_secret_door(y2 + 1, xval); break;
1059 case 3: place_secret_door(yval, x1 - 1); break;
1060 case 4: place_secret_door(yval, x2 + 1); break;
1063 /* Maze (really a checkerboard) */
1064 for (y = y1; y <= y2; y++)
1066 for (x = x1; x <= x2; x++)
1070 c_ptr = &cave[y][x];
1071 place_inner_grid(c_ptr);
1076 /* Monsters just love mazes. */
1077 vault_monsters(yval, xval - 5, randint1(3));
1078 vault_monsters(yval, xval + 5, randint1(3));
1080 /* Traps make them entertaining. */
1081 vault_traps(yval, xval - 3, 2, 8, randint1(3));
1082 vault_traps(yval, xval + 3, 2, 8, randint1(3));
1084 /* Mazes should have some treasure too. */
1085 vault_objects(yval, xval, 3);
1090 /* Four small rooms. */
1094 for (y = y1; y <= y2; y++)
1096 c_ptr = &cave[y][xval];
1097 place_inner_grid(c_ptr);
1099 for (x = x1; x <= x2; x++)
1101 c_ptr = &cave[yval][x];
1102 place_inner_grid(c_ptr);
1105 /* Doors into the rooms */
1106 if (randint0(100) < 50)
1108 int i = randint1(10);
1109 place_secret_door(y1 - 1, xval - i);
1110 place_secret_door(y1 - 1, xval + i);
1111 place_secret_door(y2 + 1, xval - i);
1112 place_secret_door(y2 + 1, xval + i);
1116 int i = randint1(3);
1117 place_secret_door(yval + i, x1 - 1);
1118 place_secret_door(yval - i, x1 - 1);
1119 place_secret_door(yval + i, x2 + 1);
1120 place_secret_door(yval - i, x2 + 1);
1123 /* Treasure, centered at the center of the cross */
1124 vault_objects(yval, xval, 2 + randint1(2));
1126 /* Gotta have some monsters. */
1127 vault_monsters(yval + 1, xval - 4, randint1(4));
1128 vault_monsters(yval + 1, xval + 4, randint1(4));
1129 vault_monsters(yval - 1, xval - 4, randint1(4));
1130 vault_monsters(yval - 1, xval + 4, randint1(4));
1139 * The following functions are used to determine if the given monster
1140 * is appropriate for inclusion in a monster nest or monster pit or
1143 * None of the pits/nests are allowed to include "unique" monsters.
1148 * Monster validation macro
1150 * Line 1 -- forbid town monsters
1151 * Line 2 -- forbid uniques
1152 * Line 3 -- forbid aquatic monsters
1154 #define vault_monster_okay(I) \
1155 (monster_dungeon(I) && \
1156 !(r_info[I].flags1 & RF1_UNIQUE) && \
1157 !(r_info[I].flags7 & RF7_UNIQUE2) && \
1158 !(r_info[I].flags3 & RF3_RES_ALL) && \
1159 !(r_info[I].flags7 & RF7_AQUATIC))
1162 /* Race index for "monster pit (clone)" */
1163 static int vault_aux_race;
1165 /* Race index for "monster pit (symbol clone)" */
1166 static char vault_aux_char;
1168 /* Breath mask for "monster pit (dragon)" */
1169 static u32b vault_aux_dragon_mask4;
1173 * Helper monster selection function
1175 static bool vault_aux_simple(int r_idx)
1178 return (vault_monster_okay(r_idx));
1183 * Helper function for "monster nest (jelly)"
1185 static bool vault_aux_jelly(int r_idx)
1187 monster_race *r_ptr = &r_info[r_idx];
1189 /* Validate the monster */
1190 if (!vault_monster_okay(r_idx)) return (FALSE);
1192 if (r_ptr->flags2 & (RF2_KILL_BODY)) return (FALSE);
1194 /* Also decline evil jellies (like death molds and shoggoths) */
1195 if (r_ptr->flags3 & (RF3_EVIL)) return (FALSE);
1197 /* Require icky thing, jelly, mold, or mushroom */
1198 if (!strchr("ijm,", r_ptr->d_char)) return (FALSE);
1206 * Helper function for "monster nest (animal)"
1208 static bool vault_aux_animal(int r_idx)
1210 monster_race *r_ptr = &r_info[r_idx];
1212 /* Validate the monster */
1213 if (!vault_monster_okay(r_idx)) return (FALSE);
1215 /* Require "animal" flag */
1216 if (!(r_ptr->flags3 & (RF3_ANIMAL))) return (FALSE);
1224 * Helper function for "monster nest (undead)"
1226 static bool vault_aux_undead(int r_idx)
1228 monster_race *r_ptr = &r_info[r_idx];
1230 /* Validate the monster */
1231 if (!vault_monster_okay(r_idx)) return (FALSE);
1233 /* Require Undead */
1234 if (!(r_ptr->flags3 & (RF3_UNDEAD))) return (FALSE);
1242 * Helper function for "monster nest (chapel)"
1244 static bool vault_aux_chapel_g(int r_idx)
1246 static int chapel_list[] = {
1247 MON_NOV_PRIEST, MON_NOV_PALADIN, MON_NOV_PRIEST_G, MON_NOV_PALADIN_G,
1248 MON_PRIEST, MON_JADE_MONK, MON_IVORY_MONK, MON_ULTRA_PALADIN,
1249 MON_EBONY_MONK, MON_W_KNIGHT, MON_KNI_TEMPLAR, MON_PALADIN,
1254 monster_race *r_ptr = &r_info[r_idx];
1256 /* Validate the monster */
1257 if (!vault_monster_okay(r_idx)) return (FALSE);
1259 if (r_ptr->flags3 & (RF3_EVIL)) return (FALSE);
1260 if ((r_idx == MON_A_GOLD) || (r_idx == MON_A_SILVER)) return (FALSE);
1262 /* Require "priest" or Angel */
1264 if (r_ptr->d_char == 'A') return TRUE;
1266 for (i = 0; chapel_list[i]; i++)
1267 if (r_idx == chapel_list[i]) return TRUE;
1274 * Helper function for "monster nest (kennel)"
1276 static bool vault_aux_kennel(int r_idx)
1278 monster_race *r_ptr = &r_info[r_idx];
1280 /* Validate the monster */
1281 if (!vault_monster_okay(r_idx)) return (FALSE);
1283 /* Require a Zephyr Hound or a dog */
1284 if (!strchr("CZ", r_ptr->d_char)) return (FALSE);
1292 * Helper function for "monster nest (mimic)"
1294 static bool vault_aux_mimic(int r_idx)
1296 monster_race *r_ptr = &r_info[r_idx];
1298 /* Validate the monster */
1299 if (!vault_monster_okay(r_idx)) return (FALSE);
1302 if (!strchr("!|$?=", r_ptr->d_char)) return (FALSE);
1309 * Helper function for "monster nest (clone)"
1311 static bool vault_aux_clone(int r_idx)
1313 /* Validate the monster */
1314 if (!vault_monster_okay(r_idx)) return (FALSE);
1316 return (r_idx == vault_aux_race);
1321 * Helper function for "monster nest (symbol clone)"
1323 static bool vault_aux_symbol_e(int r_idx)
1325 monster_race *r_ptr = &r_info[r_idx];
1327 /* Validate the monster */
1328 if (!vault_monster_okay(r_idx)) return (FALSE);
1330 if (r_ptr->flags2 & (RF2_KILL_BODY)) return (FALSE);
1332 if (r_ptr->flags3 & (RF3_GOOD)) return (FALSE);
1334 /* Decline incorrect symbol */
1335 if (r_ptr->d_char != vault_aux_char) return (FALSE);
1343 * Helper function for "monster nest (symbol clone)"
1345 static bool vault_aux_symbol_g(int r_idx)
1347 monster_race *r_ptr = &r_info[r_idx];
1349 /* Validate the monster */
1350 if (!vault_monster_okay(r_idx)) return (FALSE);
1352 if (r_ptr->flags2 & (RF2_KILL_BODY)) return (FALSE);
1354 if (r_ptr->flags3 & (RF3_EVIL)) return (FALSE);
1356 /* Decline incorrect symbol */
1357 if (r_ptr->d_char != vault_aux_char) return (FALSE);
1365 * Helper function for "monster pit (orc)"
1367 static bool vault_aux_orc(int r_idx)
1369 monster_race *r_ptr = &r_info[r_idx];
1371 /* Validate the monster */
1372 if (!vault_monster_okay(r_idx)) return (FALSE);
1375 if (!(r_ptr->flags3 & RF3_ORC)) return (FALSE);
1377 /* Decline undead */
1378 if (r_ptr->flags3 & RF3_UNDEAD) return (FALSE);
1386 * Helper function for "monster pit (troll)"
1388 static bool vault_aux_troll(int r_idx)
1390 monster_race *r_ptr = &r_info[r_idx];
1392 /* Validate the monster */
1393 if (!vault_monster_okay(r_idx)) return (FALSE);
1396 if (!(r_ptr->flags3 & RF3_TROLL)) return (FALSE);
1398 /* Decline undead */
1399 if (r_ptr->flags3 & RF3_UNDEAD) return (FALSE);
1407 * Helper function for "monster pit (giant)"
1409 static bool vault_aux_giant(int r_idx)
1411 monster_race *r_ptr = &r_info[r_idx];
1413 /* Validate the monster */
1414 if (!vault_monster_okay(r_idx)) return (FALSE);
1417 if (!(r_ptr->flags3 & RF3_GIANT)) return (FALSE);
1419 if (r_ptr->flags3 & RF3_GOOD) return (FALSE);
1421 /* Decline undead */
1422 if (r_ptr->flags3 & RF3_UNDEAD) return (FALSE);
1430 * Helper function for "monster pit (dragon)"
1432 static bool vault_aux_dragon(int r_idx)
1434 monster_race *r_ptr = &r_info[r_idx];
1436 /* Validate the monster */
1437 if (!vault_monster_okay(r_idx)) return (FALSE);
1439 /* Require dragon */
1440 if (!(r_ptr->flags3 & RF3_DRAGON)) return (FALSE);
1442 /* Hack -- Require correct "breath attack" */
1443 if (r_ptr->flags4 != vault_aux_dragon_mask4) return (FALSE);
1445 /* Decline undead */
1446 if (r_ptr->flags3 & RF3_UNDEAD) return (FALSE);
1454 * Helper function for "monster pit (demon)"
1456 static bool vault_aux_demon(int r_idx)
1458 monster_race *r_ptr = &r_info[r_idx];
1460 /* Validate the monster */
1461 if (!vault_monster_okay(r_idx)) return (FALSE);
1463 if (r_ptr->flags2 & (RF2_KILL_BODY)) return (FALSE);
1466 if (!(r_ptr->flags3 & RF3_DEMON)) return (FALSE);
1474 * Helper function for "monster pit (lovecraftian)"
1476 static bool vault_aux_cthulhu(int r_idx)
1478 monster_race *r_ptr = &r_info[r_idx];
1480 /* Validate the monster */
1481 if (!vault_monster_okay(r_idx)) return (FALSE);
1483 if (r_ptr->flags2 & (RF2_KILL_BODY)) return (FALSE);
1485 /* Require eldritch horror */
1486 if (!(r_ptr->flags2 & (RF2_ELDRITCH_HORROR))) return (FALSE);
1494 * Helper function for "monster pit (clone)"
1496 static void vault_prep_clone(void)
1498 /* Apply the monster restriction */
1499 get_mon_num_prep(vault_aux_simple, NULL);
1501 /* Pick a race to clone */
1502 vault_aux_race = get_mon_num(dun_level + 10);
1504 /* Remove the monster restriction */
1505 get_mon_num_prep(NULL, NULL);
1510 * Helper function for "monster pit (symbol clone)"
1512 static void vault_prep_symbol(void)
1516 /* Apply the monster restriction */
1517 get_mon_num_prep(vault_aux_simple, NULL);
1519 /* Pick a race to clone */
1520 r_idx = get_mon_num(dun_level + 10);
1522 /* Remove the monster restriction */
1523 get_mon_num_prep(NULL, NULL);
1525 /* Extract the symbol */
1526 vault_aux_char = r_info[r_idx].d_char;
1531 * Helper function for "monster pit (dragon)"
1533 static void vault_prep_dragon(void)
1535 /* Pick dragon type */
1536 switch (randint0(6))
1541 /* Restrict dragon breath type */
1542 vault_aux_dragon_mask4 = RF4_BR_ACID;
1551 /* Restrict dragon breath type */
1552 vault_aux_dragon_mask4 = RF4_BR_ELEC;
1561 /* Restrict dragon breath type */
1562 vault_aux_dragon_mask4 = RF4_BR_FIRE;
1571 /* Restrict dragon breath type */
1572 vault_aux_dragon_mask4 = RF4_BR_COLD;
1581 /* Restrict dragon breath type */
1582 vault_aux_dragon_mask4 = RF4_BR_POIS;
1591 /* Restrict dragon breath type */
1592 vault_aux_dragon_mask4 = (RF4_BR_ACID | RF4_BR_ELEC |
1593 RF4_BR_FIRE | RF4_BR_COLD |
1606 typedef struct vault_aux_type vault_aux_type;
1609 struct vault_aux_type
1612 bool (*hook_func)(int r_idx);
1613 void (*prep_func)(void);
1619 static vault_aux_type *pick_vault_type(vault_aux_type *l_ptr, int room)
1621 int tmp, total, count;
1623 vault_aux_type *n_ptr;
1625 /* Calculate the total possibilities */
1626 for (n_ptr = l_ptr, total = 0, count = 0; TRUE; n_ptr++, count++)
1629 if (!n_ptr->name) break;
1631 /* Ignore excessive depth */
1632 if (n_ptr->level > dun_level) continue;
1634 if (room == ROOM_PIT)
1636 if (!(d_info[dungeon_type].pit & (1L << count))) continue;
1638 else if (room == ROOM_NEST)
1640 if(!(d_info[dungeon_type].nest & (1L << count))) continue;
1643 /* Count this possibility */
1644 total += n_ptr->chance * MAX_DEPTH / (MIN(dun_level, MAX_DEPTH - 1) - n_ptr->level + 5);
1647 /* Pick a random type */
1648 tmp = randint0(total);
1650 /* Find this type */
1651 for (n_ptr = l_ptr, total = 0, count = 0; TRUE; n_ptr++, count++)
1654 if (!n_ptr->name) break;
1656 /* Ignore excessive depth */
1657 if (n_ptr->level > dun_level) continue;
1659 if (room == ROOM_PIT)
1661 if (!(d_info[dungeon_type].pit & (1L << count))) continue;
1663 else if (room == ROOM_NEST)
1665 if(!(d_info[dungeon_type].nest & (1L << count))) continue;
1668 /* Count this possibility */
1669 total += n_ptr->chance * MAX_DEPTH / (MIN(dun_level, MAX_DEPTH - 1) - n_ptr->level + 5);
1671 /* Found the type */
1672 if (tmp < total) break;
1675 return (n_ptr->name ? n_ptr : NULL);
1678 static void build_type6(int by0, int bx0, bool nest);
1679 static void build_type5(int by0, int bx0, bool nest);
1681 static vault_aux_type nest_types[] =
1684 {"¥¯¥í¡¼¥ó", vault_aux_clone, vault_prep_clone, 5, 3},
1685 {"¥¼¥ê¡¼", vault_aux_jelly, NULL, 5, 6},
1686 {"¥·¥ó¥Ü¥ë(Á±)",vault_aux_symbol_g, vault_prep_symbol, 25, 2},
1687 {"¥·¥ó¥Ü¥ë(°)",vault_aux_symbol_e, vault_prep_symbol, 25, 2},
1688 {"¥ß¥ß¥Ã¥¯", vault_aux_mimic, NULL, 30, 4},
1689 {"¶¸µ¤", vault_aux_cthulhu, NULL, 70, 2},
1690 {"¸¤¾®²°", vault_aux_kennel, NULL, 45, 4},
1691 {"ưʪ±à", vault_aux_animal, NULL, 35, 5},
1692 {"¶µ²ñ", vault_aux_chapel_g, NULL, 75, 4},
1693 {"¥¢¥ó¥Ç¥Ã¥É", vault_aux_undead, NULL, 75, 5},
1694 {NULL, NULL, NULL, 0, 0},
1696 {"clone", vault_aux_clone, vault_prep_clone, 5, 3},
1697 {"jelly", vault_aux_jelly, NULL, 5, 6},
1698 {"symbol good",vault_aux_symbol_g, vault_prep_symbol, 25, 2},
1699 {"symbol evil",vault_aux_symbol_e, vault_prep_symbol, 25, 2},
1700 {"mimic", vault_aux_mimic, NULL, 30, 4},
1701 {"lovecraftian",vault_aux_cthulhu, NULL, 70, 2},
1702 {"kennel", vault_aux_kennel, NULL, 45, 4},
1703 {"animal", vault_aux_animal, NULL, 35, 5},
1704 {"chapel", vault_aux_chapel_g, NULL, 75, 4},
1705 {"undead", vault_aux_undead, NULL, 75, 5},
1706 {NULL, NULL, NULL, 0, 0},
1712 * Type 5 -- Monster nests
1714 * A monster nest is a "big" room, with an "inner" room, containing
1715 * a "collection" of monsters of a given type strewn about the room.
1717 * The monsters are chosen from a set of 64 randomly selected monster
1718 * races, to allow the nest creation to fail instead of having "holes".
1720 * Note the use of the "get_mon_num_prep()" function, and the special
1721 * "get_mon_num_hook()" restriction function, to prepare the "monster
1722 * allocation table" in such a way as to optimize the selection of
1723 * "appropriate" non-unique monsters for the nest.
1725 * Note that the "get_mon_num()" function may (rarely) fail, in which
1726 * case the nest will be empty, and will not affect the level rating.
1728 * Note that "monster nests" will never contain "unique" monsters.
1730 static void build_type5(int by0, int bx0, bool pit)
1732 int y, x, y1, x1, y2, x2, xval, yval;
1740 vault_aux_type *n_ptr = pick_vault_type(nest_types, ROOM_NEST);
1742 /* Try to allocate space for room. */
1743 if (!room_alloc(25, 11, TRUE, by0, bx0, &xval, &yval)) return;
1745 /* No type available */
1749 else {build_type6(by0, bx0, TRUE);return;}
1752 /* Process a preparation function if necessary */
1753 if (n_ptr->prep_func) (*(n_ptr->prep_func))();
1761 /* Place the floor area */
1762 for (y = y1 - 1; y <= y2 + 1; y++)
1764 for (x = x1 - 1; x <= x2 + 1; x++)
1766 c_ptr = &cave[y][x];
1767 place_floor_grid(c_ptr);
1768 c_ptr->info |= (CAVE_ROOM);
1772 /* Place the outer walls */
1773 for (y = y1 - 1; y <= y2 + 1; y++)
1775 c_ptr = &cave[y][x1 - 1];
1776 place_outer_grid(c_ptr);
1777 c_ptr = &cave[y][x2 + 1];
1778 place_outer_grid(c_ptr);
1780 for (x = x1 - 1; x <= x2 + 1; x++)
1782 c_ptr = &cave[y1 - 1][x];
1783 place_outer_grid(c_ptr);
1784 c_ptr = &cave[y2 + 1][x];
1785 place_outer_grid(c_ptr);
1789 /* Advance to the center room */
1795 /* The inner walls */
1796 for (y = y1 - 1; y <= y2 + 1; y++)
1798 c_ptr = &cave[y][x1 - 1];
1799 place_inner_grid(c_ptr);
1800 c_ptr = &cave[y][x2 + 1];
1801 place_inner_grid(c_ptr);
1804 for (x = x1 - 1; x <= x2 + 1; x++)
1806 c_ptr = &cave[y1 - 1][x];
1807 place_inner_grid(c_ptr);
1808 c_ptr = &cave[y2 + 1][x];
1809 place_inner_grid(c_ptr);
1811 for (y = y1; y <= y2; y++)
1813 for (x = x1; x <= x2; x++)
1815 add_cave_info(y, x, CAVE_ICKY);
1820 /* Place a secret door */
1821 switch (randint1(4))
1823 case 1: place_secret_door(y1 - 1, xval); break;
1824 case 2: place_secret_door(y2 + 1, xval); break;
1825 case 3: place_secret_door(yval, x1 - 1); break;
1826 case 4: place_secret_door(yval, x2 + 1); break;
1830 /* Prepare allocation table */
1831 get_mon_num_prep(n_ptr->hook_func, NULL);
1833 /* Pick some monster types */
1834 for (i = 0; i < 64; i++)
1836 int r_idx = 0, attempts = 100;
1840 /* Get a (hard) monster type */
1841 r_idx = get_mon_num(dun_level + 10);
1843 /* Decline incorrect alignment */
1844 if (((align < 0) && (r_info[r_idx].flags3 & RF3_GOOD)) ||
1845 ((align > 0) && (r_info[r_idx].flags3 & RF3_EVIL)))
1850 /* Accept this monster */
1854 /* Notice failure */
1855 if (!r_idx || !attempts) return;
1857 /* Note the alignment */
1858 if (r_info[r_idx].flags3 & RF3_GOOD) align++;
1859 else if (r_info[r_idx].flags3 & RF3_EVIL) align--;
1869 msg_format("¥â¥ó¥¹¥¿¡¼Éô²°(%s)", n_ptr->name);
1871 msg_format("Monster nest (%s)", n_ptr->name);
1877 /* Increase the level rating */
1880 /* (Sometimes) Cause a "special feeling" (for "Monster Nests") */
1881 if ((dun_level <= 40) && (randint1(dun_level * dun_level + 50) < 300))
1883 good_item_flag = TRUE;
1886 /* Place some monsters */
1887 for (y = yval - 2; y <= yval + 2; y++)
1889 for (x = xval - 9; x <= xval + 9; x++)
1891 int r_idx = what[randint0(64)];
1893 /* Place that "random" monster (no groups) */
1894 (void)place_monster_aux(0, y, x, r_idx, 0L);
1900 static vault_aux_type pit_types[] =
1903 {"¥ª¡¼¥¯", vault_aux_orc, NULL, 5, 6},
1904 {"¥È¥í¥ë", vault_aux_troll, NULL, 20, 6},
1905 {"¥¸¥ã¥¤¥¢¥ó¥È",vault_aux_giant, NULL, 50, 6},
1906 {"¶¸µ¤", vault_aux_cthulhu, NULL, 80, 2},
1907 {"¥·¥ó¥Ü¥ë(Á±)",vault_aux_symbol_g, vault_prep_symbol, 70, 1},
1908 {"¥·¥ó¥Ü¥ë(°)",vault_aux_symbol_e, vault_prep_symbol, 70, 1},
1909 {"¶µ²ñ", vault_aux_chapel_g, NULL, 65, 2},
1910 {"¥É¥é¥´¥ó", vault_aux_dragon, vault_prep_dragon, 70, 6},
1911 {"¥Ç¡¼¥â¥ó", vault_aux_demon, NULL, 80, 6},
1912 {NULL, NULL, NULL, 0, 0},
1914 {"orc", vault_aux_orc, NULL, 5, 6},
1915 {"troll", vault_aux_troll, NULL, 20, 6},
1916 {"giant", vault_aux_giant, NULL, 50, 6},
1917 {"lovecraftian",vault_aux_cthulhu, NULL, 80, 2},
1918 {"symbol good",vault_aux_symbol_g, vault_prep_symbol, 70, 1},
1919 {"symbol evil",vault_aux_symbol_e, vault_prep_symbol, 70, 1},
1920 {"chapel", vault_aux_chapel_g, NULL, 65, 2},
1921 {"dragon", vault_aux_dragon, vault_prep_dragon, 70, 6},
1922 {"demon", vault_aux_demon, NULL, 80, 6},
1923 {NULL, NULL, NULL, 0, 0},
1929 * Type 6 -- Monster pits
1931 * A monster pit is a "big" room, with an "inner" room, containing
1932 * a "collection" of monsters of a given type organized in the room.
1934 * The inside room in a monster pit appears as shown below, where the
1935 * actual monsters in each location depend on the type of the pit
1937 * #####################
1938 * #0000000000000000000#
1939 * #0112233455543322110#
1940 * #0112233467643322110#
1941 * #0112233455543322110#
1942 * #0000000000000000000#
1943 * #####################
1945 * Note that the monsters in the pit are now chosen by using "get_mon_num()"
1946 * to request 16 "appropriate" monsters, sorting them by level, and using
1947 * the "even" entries in this sorted list for the contents of the pit.
1949 * Hack -- all of the "dragons" in a "dragon" pit must be the same "color",
1950 * which is handled by requiring a specific "breath" attack for all of the
1951 * dragons. This may include "multi-hued" breath. Note that "wyrms" may
1952 * be present in many of the dragon pits, if they have the proper breath.
1954 * Note the use of the "get_mon_num_prep()" function, and the special
1955 * "get_mon_num_hook()" restriction function, to prepare the "monster
1956 * allocation table" in such a way as to optimize the selection of
1957 * "appropriate" non-unique monsters for the pit.
1959 * Note that the "get_mon_num()" function may (rarely) fail, in which case
1960 * the pit will be empty, and will not effect the level rating.
1962 * Note that "monster pits" will never contain "unique" monsters.
1964 static void build_type6(int by0, int bx0, bool nest)
1966 int y, x, y1, x1, y2, x2, xval, yval;
1975 vault_aux_type *n_ptr = pick_vault_type(pit_types, ROOM_PIT);
1977 /* Try to allocate space for room. */
1978 if (!room_alloc(25, 11, TRUE, by0, bx0, &xval, &yval)) return;
1980 /* No type available */
1984 else {build_type5(by0, bx0, TRUE);return;}
1987 /* Process a preparation function if necessary */
1988 if (n_ptr->prep_func) (*(n_ptr->prep_func))();
1996 /* Place the floor area */
1997 for (y = y1 - 1; y <= y2 + 1; y++)
1999 for (x = x1 - 1; x <= x2 + 1; x++)
2001 c_ptr = &cave[y][x];
2002 place_floor_grid(c_ptr);
2003 c_ptr->info |= (CAVE_ROOM);
2007 /* Place the outer walls */
2008 for (y = y1 - 1; y <= y2 + 1; y++)
2010 c_ptr = &cave[y][x1 - 1];
2011 place_outer_grid(c_ptr);
2012 c_ptr = &cave[y][x2 + 1];
2013 place_outer_grid(c_ptr);
2015 for (x = x1 - 1; x <= x2 + 1; x++)
2017 c_ptr = &cave[y1 - 1][x];
2018 place_outer_grid(c_ptr);
2019 c_ptr = &cave[y2 + 1][x];
2020 place_outer_grid(c_ptr);
2023 /* Advance to the center room */
2029 /* The inner walls */
2030 for (y = y1 - 1; y <= y2 + 1; y++)
2032 c_ptr = &cave[y][x1 - 1];
2033 place_inner_grid(c_ptr);
2034 c_ptr = &cave[y][x2 + 1];
2035 place_inner_grid(c_ptr);
2037 for (x = x1 - 1; x <= x2 + 1; x++)
2039 c_ptr = &cave[y1 - 1][x];
2040 place_inner_grid(c_ptr);
2041 c_ptr = &cave[y2 + 1][x];
2042 place_inner_grid(c_ptr);
2044 for (y = y1; y <= y2; y++)
2046 for (x = x1; x <= x2; x++)
2048 add_cave_info(y, x, CAVE_ICKY);
2052 /* Place a secret door */
2053 switch (randint1(4))
2055 case 1: place_secret_door(y1 - 1, xval); break;
2056 case 2: place_secret_door(y2 + 1, xval); break;
2057 case 3: place_secret_door(yval, x1 - 1); break;
2058 case 4: place_secret_door(yval, x2 + 1); break;
2062 /* Prepare allocation table */
2063 get_mon_num_prep(n_ptr->hook_func, NULL);
2065 /* Pick some monster types */
2066 for (i = 0; i < 16; i++)
2068 int r_idx = 0, attempts = 100;
2072 /* Get a (hard) monster type */
2073 r_idx = get_mon_num(dun_level + 10);
2075 /* Decline incorrect alignment */
2076 if (((align < 0) && (r_info[r_idx].flags3 & RF3_GOOD)) ||
2077 ((align > 0) && (r_info[r_idx].flags3 & RF3_EVIL)))
2082 /* Accept this monster */
2086 /* Notice failure */
2087 if (!r_idx || !attempts) return;
2089 /* Note the alignment */
2090 if (r_info[r_idx].flags3 & RF3_GOOD) align++;
2091 else if (r_info[r_idx].flags3 & RF3_EVIL) align--;
2096 /* Sort the entries */
2097 for (i = 0; i < 16 - 1; i++)
2099 /* Sort the entries */
2100 for (j = 0; j < 16 - 1; j++)
2105 int p1 = r_info[what[i1]].level;
2106 int p2 = r_info[what[i2]].level;
2112 what[i1] = what[i2];
2122 msg_format("%s¤ÎÁã", n_ptr->name);
2125 msg_format("Monster pit (%s)", n_ptr->name);
2129 /* Select the entries */
2130 for (i = 0; i < 8; i++)
2132 /* Every other entry */
2133 what[i] = what[i * 2];
2138 msg_print(r_name + r_info[what[i]].name);
2142 /* Increase the level rating */
2145 /* (Sometimes) Cause a "special feeling" (for "Monster Pits") */
2146 if ((dun_level <= 40) && (randint1(dun_level * dun_level + 50) < 300))
2148 good_item_flag = TRUE;
2151 /* Top and bottom rows */
2152 for (x = xval - 9; x <= xval + 9; x++)
2154 place_monster_aux(0, yval - 2, x, what[0], PM_NO_KAGE);
2155 place_monster_aux(0, yval + 2, x, what[0], PM_NO_KAGE);
2158 /* Middle columns */
2159 for (y = yval - 1; y <= yval + 1; y++)
2161 place_monster_aux(0, y, xval - 9, what[0], PM_NO_KAGE);
2162 place_monster_aux(0, y, xval + 9, what[0], PM_NO_KAGE);
2164 place_monster_aux(0, y, xval - 8, what[1], PM_NO_KAGE);
2165 place_monster_aux(0, y, xval + 8, what[1], PM_NO_KAGE);
2167 place_monster_aux(0, y, xval - 7, what[1], PM_NO_KAGE);
2168 place_monster_aux(0, y, xval + 7, what[1], PM_NO_KAGE);
2170 place_monster_aux(0, y, xval - 6, what[2], PM_NO_KAGE);
2171 place_monster_aux(0, y, xval + 6, what[2], PM_NO_KAGE);
2173 place_monster_aux(0, y, xval - 5, what[2], PM_NO_KAGE);
2174 place_monster_aux(0, y, xval + 5, what[2], PM_NO_KAGE);
2176 place_monster_aux(0, y, xval - 4, what[3], PM_NO_KAGE);
2177 place_monster_aux(0, y, xval + 4, what[3], PM_NO_KAGE);
2179 place_monster_aux(0, y, xval - 3, what[3], PM_NO_KAGE);
2180 place_monster_aux(0, y, xval + 3, what[3], PM_NO_KAGE);
2182 place_monster_aux(0, y, xval - 2, what[4], PM_NO_KAGE);
2183 place_monster_aux(0, y, xval + 2, what[4], PM_NO_KAGE);
2186 /* Above/Below the center monster */
2187 for (x = xval - 1; x <= xval + 1; x++)
2189 place_monster_aux(0, yval + 1, x, what[5], PM_NO_KAGE);
2190 place_monster_aux(0, yval - 1, x, what[5], PM_NO_KAGE);
2193 /* Next to the center monster */
2194 place_monster_aux(0, yval, xval + 1, what[6], PM_NO_KAGE);
2195 place_monster_aux(0, yval, xval - 1, what[6], PM_NO_KAGE);
2197 /* Center monster */
2198 place_monster_aux(0, yval, xval, what[7], PM_NO_KAGE);
2202 /* coordinate translation code */
2203 static void coord_trans(int *x, int *y, int xoffset, int yoffset, int transno)
2209 * transno specifies what transformation is required. (0-7)
2210 * The lower two bits indicate by how much the vault is rotated,
2211 * and the upper bit indicates a reflection.
2212 * This is done by using rotation matrices... however since
2213 * these are mostly zeros for rotations by 90 degrees this can
2214 * be expressed simply in terms of swapping and inverting the
2215 * x and y coordinates.
2217 for (i = 0; i <= transno % 4; i++)
2219 /* rotate by 90 degrees */
2227 /* Reflect depending on status of 3rd bit. */
2231 /* Add offsets so vault stays in the first quadrant */
2238 * Hack -- fill in "vault" rooms
2240 static void build_vault(int yval, int xval, int ymax, int xmax, cptr data,
2241 int xoffset, int yoffset, int transno)
2243 int dx, dy, x, y, i, j;
2250 /* Place dungeon features and objects */
2251 for (t = data, dy = 0; dy < ymax; dy++)
2253 for (dx = 0; dx < xmax; dx++, t++)
2255 /* prevent loop counter from being overwritten */
2260 coord_trans(&i, &j, xoffset, yoffset, transno);
2262 /* Extract the location */
2265 /* no swap of x/y */
2266 x = xval - (xmax / 2) + i;
2267 y = yval - (ymax / 2) + j;
2272 x = xval - (ymax / 2) + i;
2273 y = yval - (xmax / 2) + j;
2276 /* Hack -- skip "non-grids" */
2277 if (*t == ' ') continue;
2279 /* Access the grid */
2280 c_ptr = &cave[y][x];
2282 /* Lay down a floor */
2283 place_floor_grid(c_ptr);
2285 /* Remove any mimic */
2288 /* Part of a vault */
2289 c_ptr->info |= (CAVE_ICKY);
2291 /* Analyze the grid */
2294 /* Granite wall (outer) */
2296 place_outer_noperm_grid(c_ptr);
2299 /* Granite wall (inner) */
2301 place_inner_grid(c_ptr);
2304 /* Permanent wall (inner) */
2306 c_ptr->feat = FEAT_PERM_INNER;
2307 c_ptr->info &= ~(CAVE_MASK);
2308 c_ptr->info |= CAVE_INNER;
2313 if (randint0(100) < 75)
2315 place_object(y, x, FALSE, FALSE);
2325 place_secret_door(y, x);
2333 /* Black market in a dungeon */
2335 set_cave_feat(y, x, FEAT_SHOP_HEAD + STORE_BLACK);
2336 store_init(NO_TOWN, STORE_BLACK);
2341 set_cave_feat(y, x, FEAT_PATTERN_START);
2345 set_cave_feat(y, x, FEAT_PATTERN_1);
2349 set_cave_feat(y, x, FEAT_PATTERN_2);
2353 set_cave_feat(y, x, FEAT_PATTERN_3);
2357 set_cave_feat(y, x, FEAT_PATTERN_4);
2361 set_cave_feat(y, x, FEAT_PATTERN_END);
2365 set_cave_feat(y, x, FEAT_PATTERN_XTRA1);
2369 /* Reward for Pattern walk */
2370 object_level = base_level + 12;
2371 place_object(y, x, TRUE, FALSE);
2372 object_level = base_level;
2379 /* Place dungeon monsters and objects */
2380 for (t = data, dy = 0; dy < ymax; dy++)
2382 for (dx = 0; dx < xmax; dx++, t++)
2384 /* prevent loop counter from being overwritten */
2389 coord_trans(&i, &j, xoffset, yoffset, transno);
2391 /* Extract the location */
2394 /* no swap of x/y */
2395 x = xval - (xmax / 2) + i;
2396 y = yval - (ymax / 2) + j;
2401 x = xval - (ymax / 2) + i;
2402 y = yval - (xmax / 2) + j;
2405 /* Hack -- skip "non-grids" */
2406 if (*t == ' ') continue;
2408 /* Analyze the symbol */
2414 monster_level = base_level + 5;
2415 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
2416 monster_level = base_level;
2420 /* Meaner monster */
2423 monster_level = base_level + 11;
2424 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
2425 monster_level = base_level;
2429 /* Meaner monster, plus treasure */
2432 monster_level = base_level + 9;
2433 place_monster(y, x, PM_ALLOW_SLEEP);
2434 monster_level = base_level;
2435 object_level = base_level + 7;
2436 place_object(y, x, TRUE, FALSE);
2437 object_level = base_level;
2441 /* Nasty monster and treasure */
2444 monster_level = base_level + 40;
2445 place_monster(y, x, PM_ALLOW_SLEEP);
2446 monster_level = base_level;
2447 object_level = base_level + 20;
2448 place_object(y, x, TRUE, TRUE);
2449 object_level = base_level;
2453 /* Monster and/or object */
2456 if (randint0(100) < 50)
2458 monster_level = base_level + 3;
2459 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
2460 monster_level = base_level;
2462 if (randint0(100) < 50)
2464 object_level = base_level + 7;
2465 place_object(y, x, FALSE, FALSE);
2466 object_level = base_level;
2478 * Type 7 -- simple vaults (see "v_info.txt")
2480 static void build_type7(int by0, int bx0)
2482 vault_type *v_ptr = NULL;
2486 int xoffset, yoffset;
2489 /* Pick a lesser vault */
2490 while (dummy < SAFE_MAX_ATTEMPTS)
2494 /* Access a random vault record */
2495 v_ptr = &v_info[randint0(max_v_idx)];
2497 /* Accept the first lesser vault */
2498 if (v_ptr->typ == 7) break;
2501 /* No lesser vault found */
2504 /* pick type of transformation (0-7) */
2505 transno = randint0(8);
2507 /* calculate offsets */
2511 coord_trans(&x, &y, 0, 0, transno);
2531 /* Try to allocate space for room. */
2532 if (!room_alloc(abs(x), abs(y), FALSE, by0, bx0, &xval, &yval)) return;
2534 if (dummy >= SAFE_MAX_ATTEMPTS)
2539 msg_print("·Ù¹ð¡ª¾®¤µ¤ÊÃϲ¼¼¼¤òÇÛÃ֤Ǥ¤Þ¤»¤ó¡ª");
2541 msg_print("Warning! Could not place lesser vault!");
2554 if (cheat_room) msg_format("%s", v_name + v_ptr->name);
2556 /* Boost the rating */
2557 rating += v_ptr->rat;
2559 /* (Sometimes) Cause a special feeling */
2560 if ((dun_level <= 50) ||
2561 (randint1((dun_level - 40) * (dun_level - 40) + 50) < 400))
2563 good_item_flag = TRUE;
2566 /* Hack -- Build the vault */
2567 build_vault(yval, xval, v_ptr->hgt, v_ptr->wid,
2568 v_text + v_ptr->text, xoffset, yoffset, transno);
2573 * Type 8 -- greater vaults (see "v_info.txt")
2575 static void build_type8(int by0, int bx0)
2577 vault_type *v_ptr = NULL;
2582 int xoffset, yoffset;
2584 /* Pick a greater vault */
2585 while (dummy < SAFE_MAX_ATTEMPTS)
2589 /* Access a random vault record */
2590 v_ptr = &v_info[randint0(max_v_idx)];
2592 /* Accept the first greater vault */
2593 if (v_ptr->typ == 8) break;
2596 /* No greater vault found */
2599 /* pick type of transformation (0-7) */
2600 transno = randint0(8);
2602 /* calculate offsets */
2606 coord_trans(&x, &y, 0, 0, transno);
2626 /* Try to allocate space for room. If fails, exit */
2627 if (!room_alloc(abs(x), abs(y), FALSE, by0, bx0, &xval, &yval)) return;
2629 if (dummy >= SAFE_MAX_ATTEMPTS)
2634 msg_print("·Ù¹ð¡ªµðÂç¤ÊÃϲ¼¼¼¤òÇÛÃ֤Ǥ¤Þ¤»¤ó¡ª");
2636 msg_print("Warning! Could not place greater vault!");
2645 v_ptr = &v_info[76 + randint1(3)];
2649 if (cheat_room) msg_format("%s", v_name + v_ptr->name);
2651 /* Boost the rating */
2652 rating += v_ptr->rat;
2654 /* (Sometimes) Cause a special feeling */
2655 if ((dun_level <= 50) ||
2656 (randint1((dun_level - 40) * (dun_level - 40) + 50) < 400))
2658 good_item_flag = TRUE;
2661 /* Hack -- Build the vault */
2662 build_vault(yval, xval, v_ptr->hgt, v_ptr->wid,
2663 v_text + v_ptr->text, xoffset, yoffset, transno);
2667 * Structure to hold all "fill" data
2670 typedef struct fill_data_type fill_data_type;
2672 struct fill_data_type
2685 /* features to fill with */
2694 /* number of filled squares */
2698 static fill_data_type fill_data;
2701 /* Store routine for the fractal cave generator */
2702 /* this routine probably should be an inline function or a macro. */
2703 static void store_height(int x, int y, int val)
2705 /* if on boundary set val > cutoff so walls are not as square */
2706 if (((x == fill_data.xmin) || (y == fill_data.ymin) ||
2707 (x == fill_data.xmax) || (y == fill_data.ymax)) &&
2708 (val <= fill_data.c1)) val = fill_data.c1 + 1;
2710 /* store the value in height-map format */
2711 cave[y][x].feat = val;
2718 * Explanation of the plasma fractal algorithm:
2720 * A grid of points is created with the properties of a 'height-map'
2721 * This is done by making the corners of the grid have a random value.
2722 * The grid is then subdivided into one with twice the resolution.
2723 * The new points midway between two 'known' points can be calculated
2724 * by taking the average value of the 'known' ones and randomly adding
2725 * or subtracting an amount proportional to the distance between those
2726 * points. The final 'middle' points of the grid are then calculated
2727 * by averaging all four of the originally 'known' corner points. An
2728 * random amount is added or subtracted from this to get a value of the
2729 * height at that point. The scaling factor here is adjusted to the
2730 * slightly larger distance diagonally as compared to orthogonally.
2732 * This is then repeated recursively to fill an entire 'height-map'
2733 * A rectangular map is done the same way, except there are different
2734 * scaling factors along the x and y directions.
2736 * A hack to change the amount of correlation between points is done using
2737 * the grd variable. If the current step size is greater than grd then
2738 * the point will be random, otherwise it will be calculated by the
2739 * above algorithm. This makes a maximum distance at which two points on
2740 * the height map can affect each other.
2742 * How fractal caves are made:
2744 * When the map is complete, a cut-off value is used to create a cave.
2745 * Heights below this value are "floor", and heights above are "wall".
2746 * This also can be used to create lakes, by adding more height levels
2747 * representing shallow and deep water/ lava etc.
2749 * The grd variable affects the width of passages.
2750 * The roug variable affects the roughness of those passages
2752 * The tricky part is making sure the created cave is connected. This
2753 * is done by 'filling' from the inside and only keeping the 'filled'
2754 * floor. Walls bounding the 'filled' floor are also kept. Everything
2755 * else is converted to the normal granite FEAT_WALL_EXTRA.
2760 * Note that this uses the cave.feat array in a very hackish way
2761 * the values are first set to zero, and then each array location
2762 * is used as a "heightmap"
2763 * The heightmap then needs to be converted back into the "feat" format.
2765 * grd=level at which fractal turns on. smaller gives more mazelike caves
2766 * roug=roughness level. 16=normal. higher values make things more convoluted
2767 * small values are good for smooth walls.
2768 * size=length of the side of the square cave system.
2770 static void generate_hmap(int y0, int x0, int xsiz, int ysiz, int grd, int roug, int cutoff)
2772 int xhsize, yhsize, xsize, ysize, maxsize;
2775 * fixed point variables- these are stored as 256 x normal value
2776 * this gives 8 binary places of fractional part + 8 places of normal part
2779 u16b xstep, xhstep, ystep, yhstep;
2780 u16b xstep2, xhstep2, ystep2, yhstep2;
2781 u16b i, j, ii, jj, diagsize, xxsize, yysize;
2783 /* Cache for speed */
2784 u16b xm, xp, ym, yp;
2786 /* redefine size so can change the value if out of range */
2790 /* Paranoia about size of the system of caves */
2791 if (xsize > 254) xsize = 254;
2792 if (xsize < 4) xsize = 4;
2793 if (ysize > 254) ysize = 254;
2794 if (ysize < 4) ysize = 4;
2796 /* get offsets to middle of array */
2800 /* fix rounding problem */
2804 /* get limits of region */
2805 fill_data.xmin = x0 - xhsize;
2806 fill_data.ymin = y0 - yhsize;
2807 fill_data.xmax = x0 + xhsize;
2808 fill_data.ymax = y0 + yhsize;
2810 /* Store cutoff in global for quick access */
2811 fill_data.c1 = cutoff;
2814 * Scale factor for middle points:
2815 * About sqrt(2) * 256 - correct for a square lattice
2816 * approximately correct for everything else.
2820 /* maximum of xsize and ysize */
2821 maxsize = (xsize > ysize) ? xsize : ysize;
2823 /* Clear the section */
2824 for (i = 0; i <= xsize; i++)
2826 for (j = 0; j <= ysize; j++)
2828 /* 255 is a flag for "not done yet" */
2829 cave[(int)(fill_data.ymin + j)][(int)(fill_data.xmin + i)].feat = 255;
2830 /* Clear icky flag because may be redoing the cave */
2831 cave[(int)(fill_data.ymin + j)][(int)(fill_data.xmin + i)].info &= ~(CAVE_ICKY);
2835 /* Boundaries are walls */
2836 cave[fill_data.ymin][fill_data.xmin].feat = maxsize;
2837 cave[fill_data.ymax][fill_data.xmin].feat = maxsize;
2838 cave[fill_data.ymin][fill_data.xmax].feat = maxsize;
2839 cave[fill_data.ymax][fill_data.xmax].feat = maxsize;
2841 /* Set the middle square to be an open area. */
2842 cave[y0][x0].feat = 0;
2844 /* Initialize the step sizes */
2845 xstep = xhstep = xsize * 256;
2846 ystep = yhstep = ysize * 256;
2847 xxsize = xsize * 256;
2848 yysize = ysize * 256;
2851 * Fill in the rectangle with fractal height data -
2852 * like the 'plasma fractal' in fractint.
2854 while ((xhstep > 256) || (yhstep > 256))
2856 /* Halve the step sizes */
2862 /* cache well used values */
2863 xstep2 = xstep / 256;
2864 ystep2 = ystep / 256;
2866 xhstep2 = xhstep / 256;
2867 yhstep2 = yhstep / 256;
2869 /* middle top to bottom. */
2870 for (i = xhstep; i <= xxsize - xhstep; i += xstep)
2872 for (j = 0; j <= yysize; j += ystep)
2874 /* cache often used values */
2875 ii = i / 256 + fill_data.xmin;
2876 jj = j / 256 + fill_data.ymin;
2879 if (cave[jj][ii].feat == 255)
2883 /* If greater than 'grid' level then is random */
2884 store_height(ii, jj, randint1(maxsize));
2888 /* Average of left and right points +random bit */
2889 store_height(ii, jj,
2890 (cave[jj][fill_data.xmin + (i - xhstep) / 256].feat
2891 + cave[jj][fill_data.xmin + (i + xhstep) / 256].feat) / 2
2892 + (randint1(xstep2) - xhstep2) * roug / 16);
2899 /* middle left to right. */
2900 for (j = yhstep; j <= yysize - yhstep; j += ystep)
2902 for (i = 0; i <= xxsize; i += xstep)
2904 /* cache often used values */
2905 ii = i / 256 + fill_data.xmin;
2906 jj = j / 256 + fill_data.ymin;
2909 if (cave[jj][ii].feat == 255)
2913 /* If greater than 'grid' level then is random */
2914 store_height(ii, jj, randint1(maxsize));
2918 /* Average of up and down points +random bit */
2919 store_height(ii, jj,
2920 (cave[fill_data.ymin + (j - yhstep) / 256][ii].feat
2921 + cave[fill_data.ymin + (j + yhstep) / 256][ii].feat) / 2
2922 + (randint1(ystep2) - yhstep2) * roug / 16);
2929 for (i = xhstep; i <= xxsize - xhstep; i += xstep)
2931 for (j = yhstep; j <= yysize - yhstep; j += ystep)
2933 /* cache often used values */
2934 ii = i / 256 + fill_data.xmin;
2935 jj = j / 256 + fill_data.ymin;
2938 if (cave[jj][ii].feat == 255)
2942 /* If greater than 'grid' level then is random */
2943 store_height(ii, jj, randint1(maxsize));
2947 /* Cache reused values. */
2948 xm = fill_data.xmin + (i - xhstep) / 256;
2949 xp = fill_data.xmin + (i + xhstep) / 256;
2950 ym = fill_data.ymin + (j - yhstep) / 256;
2951 yp = fill_data.ymin + (j + yhstep) / 256;
2954 * Average over all four corners + scale by diagsize to
2955 * reduce the effect of the square grid on the shape of the fractal
2957 store_height(ii, jj,
2958 (cave[ym][xm].feat + cave[yp][xm].feat
2959 + cave[ym][xp].feat + cave[yp][xp].feat) / 4
2960 + (randint1(xstep2) - xhstep2) * (diagsize / 16) / 256 * roug);
2969 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)
2972 * function used to convert from height-map back to the
2973 * normal angband cave format
2975 if (cave[y][x].info & CAVE_ICKY)
2982 /* Show that have looked at this square */
2983 cave[y][x].info|= (CAVE_ICKY);
2985 /* Use cutoffs c1-c3 to allocate regions of floor /water/ lava etc. */
2986 if (cave[y][x].feat <= c1)
2988 /* 25% of the time use the other tile : it looks better this way */
2989 if (randint1(100) < 75)
2991 cave[y][x].feat = feat1;
2992 cave[y][x].info &= ~(CAVE_MASK);
2993 cave[y][x].info |= info1;
2998 cave[y][x].feat = feat2;
2999 cave[y][x].info &= ~(CAVE_MASK);
3000 cave[y][x].info |= info2;
3004 else if (cave[y][x].feat <= c2)
3006 /* 25% of the time use the other tile : it looks better this way */
3007 if (randint1(100) < 75)
3009 cave[y][x].feat = feat2;
3010 cave[y][x].info &= ~(CAVE_MASK);
3011 cave[y][x].info |= info2;
3016 cave[y][x].feat = feat1;
3017 cave[y][x].info &= ~(CAVE_MASK);
3018 cave[y][x].info |= info1;
3022 else if (cave[y][x].feat <= c3)
3024 cave[y][x].feat = feat3;
3025 cave[y][x].info |= info3;
3028 /* if greater than cutoff then is a wall */
3031 place_outer_bold(y, x);
3041 * Quick and nasty fill routine used to find the connected region
3042 * of floor in the middle of the cave
3044 static void cave_fill(byte y, byte x)
3053 /*** Start Grid ***/
3055 /* Enqueue that entry */
3060 /* Now process the queue */
3061 while (flow_head != flow_tail)
3063 /* Extract the next entry */
3064 ty = temp_y[flow_head];
3065 tx = temp_x[flow_head];
3067 /* Forget that entry */
3068 if (++flow_head == TEMP_MAX) flow_head = 0;
3070 /* Add the "children" */
3071 for (d = 0; d < 8; d++)
3073 int old_head = flow_tail;
3075 /* Child location */
3076 j = ty + ddy_ddd[d];
3077 i = tx + ddx_ddd[d];
3079 /* Paranoia Don't leave the cave */
3080 if (!in_bounds(j, i))
3082 /* affect boundary */
3083 cave[j][i].info |= CAVE_ICKY;
3087 /* If within bounds */
3088 else if ((i > fill_data.xmin) && (i < fill_data.xmax)
3089 && (j > fill_data.ymin) && (j < fill_data.ymax))
3091 /* If not a wall or floor done before */
3092 if (hack_isnt_wall(j, i,
3093 fill_data.c1, fill_data.c2, fill_data.c3,
3094 fill_data.feat1, fill_data.feat2, fill_data.feat3,
3095 fill_data.info1, fill_data.info2, fill_data.info3))
3097 /* Enqueue that entry */
3098 temp_y[flow_tail] = j;
3099 temp_x[flow_tail] = i;
3101 /* Advance the queue */
3102 if (++flow_tail == TEMP_MAX) flow_tail = 0;
3104 /* Hack -- Overflow by forgetting new entry */
3105 if (flow_tail == flow_head)
3107 flow_tail = old_head;
3111 /* keep tally of size of cave system */
3112 (fill_data.amount)++;
3118 /* affect boundary */
3119 cave[j][i].info |= CAVE_ICKY;
3126 static bool generate_fracave(int y0, int x0, int xsize, int ysize, int cutoff, bool light, bool room)
3128 int x, y, i, xhsize, yhsize;
3131 /* offsets to middle from corner */
3137 * select region connected to center of cave system
3138 * this gets rid of alot of isolated one-sqaures that
3139 * can make teleport traps instadeaths...
3143 fill_data.c1 = cutoff;
3147 /* features to fill with */
3148 fill_data.feat1 = floor_type[randint0(100)];
3149 fill_data.feat2 = floor_type[randint0(100)];
3150 fill_data.feat3 = floor_type[randint0(100)];
3152 fill_data.info1 = CAVE_FLOOR;
3153 fill_data.info2 = CAVE_FLOOR;
3154 fill_data.info3 = CAVE_FLOOR;
3156 /* number of filled squares */
3157 fill_data.amount = 0;
3159 cave_fill((byte)y0, (byte)x0);
3161 /* if tally too small, try again */
3162 if (fill_data.amount < 10)
3164 /* too small - clear area and try again later */
3165 for (x = 0; x <= xsize; ++x)
3167 for (y = 0; y <= ysize; ++y)
3169 place_extra_bold(y0 + y - yhsize, x0 + x - xhsize);
3170 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY | CAVE_ROOM);
3177 * Do boundarys-check to see if they are next to a filled region
3178 * If not then they are set to normal granite
3179 * If so then they are marked as room walls.
3181 for (i = 0; i <= xsize; ++i)
3184 if ((cave[0 + y0 - yhsize][i + x0 - xhsize].info & CAVE_ICKY) && (room))
3186 /* Next to a 'filled' region? - set to be room walls */
3187 place_outer_bold(y0 + 0 - yhsize, x0 + i - xhsize);
3188 if (light) cave[y0 + 0 - yhsize][x0 + i - xhsize].info |= (CAVE_GLOW);
3189 cave[y0 + 0 - yhsize][x0 + i - xhsize].info |= (CAVE_ROOM);
3190 place_outer_bold(y0 + 0 - yhsize, x0 + i - xhsize);
3194 /* set to be normal granite */
3195 place_extra_bold(y0 + 0 - yhsize, x0 + i - xhsize);
3198 /* bottom boundary */
3199 if ((cave[ysize + y0 - yhsize][i + x0 - xhsize].info & CAVE_ICKY) && (room))
3201 /* Next to a 'filled' region? - set to be room walls */
3202 place_outer_bold(y0 + ysize - yhsize, x0 + i - xhsize);
3203 if (light) cave[y0 + ysize - yhsize][x0 + i - xhsize].info|=(CAVE_GLOW);
3204 cave[y0 + ysize - yhsize][x0 + i - xhsize].info|=(CAVE_ROOM);
3205 place_outer_bold(y0 + ysize - yhsize, x0 + i - xhsize);
3209 /* set to be normal granite */
3210 place_extra_bold(y0 + ysize - yhsize, x0 + i - xhsize);
3213 /* clear the icky flag-don't need it any more */
3214 cave[y0 + 0 - yhsize][x0 + i - xhsize].info &= ~(CAVE_ICKY);
3215 cave[y0 + ysize - yhsize][x0 + i - xhsize].info &= ~(CAVE_ICKY);
3218 /* Do the left and right boundaries minus the corners (done above) */
3219 for (i = 1; i < ysize; ++i)
3222 if ((cave[i + y0 - yhsize][0 + x0 - xhsize].info & CAVE_ICKY) && room)
3225 place_outer_bold(y0 + i - yhsize, x0 + 0 - xhsize);
3226 if (light) cave[y0 + i - yhsize][x0 + 0 - xhsize].info |= (CAVE_GLOW);
3227 cave[y0 + i - yhsize][x0 + 0 - xhsize].info |= (CAVE_ROOM);
3228 place_outer_bold(y0 + i - yhsize, x0 + 0 - xhsize);
3233 place_extra_bold(y0 + i - yhsize, x0 + 0 - xhsize);
3235 /* right boundary */
3236 if ((cave[i + y0 - yhsize][xsize + x0 - xhsize].info & CAVE_ICKY) && room)
3239 place_outer_bold(y0 + i - yhsize, x0 + xsize - xhsize);
3240 if (light) cave[y0 + i - yhsize][x0 + xsize - xhsize].info |= (CAVE_GLOW);
3241 cave[y0 + i - yhsize][x0 + xsize - xhsize].info |= (CAVE_ROOM);
3242 place_outer_bold(y0 + i - yhsize, x0 + xsize - xhsize);
3247 place_extra_bold(y0 + i - yhsize, x0 + xsize - xhsize);
3250 /* clear icky flag -done with it */
3251 cave[y0 + i - yhsize][x0 + 0 - xhsize].info &= ~(CAVE_ICKY);
3252 cave[y0 + i - yhsize][x0 + xsize - xhsize].info &= ~(CAVE_ICKY);
3256 /* Do the rest: convert back to the normal format */
3257 for (x = 1; x < xsize; ++x)
3259 for (y = 1; y < ysize; ++y)
3261 if (is_floor_bold(y0 + y - yhsize, x0 + x - xhsize) &&
3262 (cave[y0 + y - yhsize][x0 + x - xhsize].info & CAVE_ICKY))
3264 /* Clear the icky flag in the filled region */
3265 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~CAVE_ICKY;
3267 /* Set appropriate flags */
3268 if (light) cave[y0 + y - yhsize][x0 + x - xhsize].info |= (CAVE_GLOW);
3269 if (room) cave[y0 + y - yhsize][x0 + x - xhsize].info |= (CAVE_ROOM);
3271 else if (is_outer_bold(y0 + y - yhsize, x0 + x - xhsize) &&
3272 (cave[y0 + y - yhsize][x0 + x - xhsize].info & CAVE_ICKY))
3275 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY);
3276 if (light) cave[y0 + y - yhsize][x0 + x - xhsize].info |= (CAVE_GLOW);
3279 cave[y0 + y - yhsize][x0 + x - xhsize].info |= (CAVE_ROOM);
3284 place_extra_bold(y0 + y - yhsize, x0 + x - xhsize);
3285 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ROOM);
3290 /* Clear the unconnected regions */
3291 place_extra_bold(y0 + y - yhsize, x0 + x - xhsize);
3292 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY | CAVE_ROOM);
3298 * XXX XXX XXX There is a slight problem when tunnels pierce the caves:
3299 * Extra doors appear inside the system. (Its not very noticeable though.)
3300 * This can be removed by "filling" from the outside in. This allows a separation
3301 * from FEAT_WALL_OUTER with FEAT_WALL_INNER. (Internal walls are F.W.OUTER instead.)
3302 * The extra effort for what seems to be only a minor thing (even non-existant if you
3303 * think of the caves not as normal rooms, but as holes in the dungeon), doesn't seem
3312 * Driver routine to create fractal cave system
3314 static void build_type9(int by0, int bx0)
3316 int grd, roug, cutoff, xsize, ysize, y0, x0;
3318 bool done, light, room;
3320 /* get size: note 'Evenness'*/
3321 xsize = randint1(22) * 2 + 6;
3322 ysize = randint1(15) * 2 + 6;
3324 /* Try to allocate space for room. If fails, exit */
3325 if (!room_alloc(xsize + 1, ysize + 1, FALSE, by0, bx0, &x0, &y0)) return;
3327 light = done = FALSE;
3330 if ((dun_level <= randint1(25)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS)) light = TRUE;
3334 /* Note: size must be even or there are rounding problems
3335 * This causes the tunnels not to connect properly to the room */
3337 /* testing values for these parameters feel free to adjust */
3338 grd = 1 << (randint0(4));
3340 /* want average of about 16 */
3341 roug = randint1(8) * randint1(4);
3344 cutoff = randint1(xsize / 4) + randint1(ysize / 4) +
3345 randint1(xsize / 4) + randint1(ysize / 4);
3348 generate_hmap(y0, x0, xsize, ysize, grd, roug, cutoff);
3350 /* Convert to normal format + clean up */
3351 done = generate_fracave(y0, x0, xsize, ysize, cutoff, light, room);
3355 #ifdef ALLOW_CAVERNS_AND_LAKES
3357 * Builds a cave system in the center of the dungeon.
3359 void build_cavern(void)
3361 int grd, roug, cutoff, xsize, ysize, x0, y0;
3364 light = done = FALSE;
3365 if ((dun_level <= randint1(50)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS)) light = TRUE;
3367 /* Make a cave the size of the dungeon */
3368 xsize = cur_wid - 1;
3369 ysize = cur_hgt - 1;
3373 /* Paranoia: make size even */
3379 /* testing values for these parameters: feel free to adjust */
3380 grd = randint1(4) + 4;
3382 /* want average of about 16 */
3383 roug = randint1(8) * randint1(4);
3389 generate_hmap(y0 + 1, x0 + 1, xsize, ysize, grd, roug, cutoff);
3391 /* Convert to normal format+ clean up */
3392 done = generate_fracave(y0 + 1, x0 + 1, xsize, ysize, cutoff, light, FALSE);
3396 static bool generate_lake(int y0, int x0, int xsize, int ysize, int c1, int c2, int c3, int type)
3398 int x, y, i, xhsize, yhsize;
3399 int feat1, feat2, feat3;
3401 /* offsets to middle from corner */
3405 /* Get features based on type */
3410 feat1 = FEAT_DEEP_LAVA;
3411 feat2 = FEAT_SHAL_LAVA;
3412 feat3 = floor_type[randint0(100)];
3416 feat1 = FEAT_DEEP_WATER;
3417 feat2 = FEAT_SHAL_WATER;
3418 feat3 = floor_type[randint0(100)];
3421 /* Collapsed cave */
3422 feat1 = floor_type[randint0(100)];
3423 feat2 = floor_type[randint0(100)];
3424 feat3 = FEAT_RUBBLE;
3428 feat1 = FEAT_RUBBLE;
3429 feat2 = floor_type[randint0(100)];
3430 feat3 = FEAT_RUBBLE;
3440 feat1 = FEAT_SHAL_WATER;
3441 feat2 = FEAT_DEEP_WATER;
3442 feat3 = FEAT_SHAL_WATER;
3446 feat1 = FEAT_SHAL_LAVA;
3447 feat2 = FEAT_DEEP_LAVA;
3448 feat3 = FEAT_SHAL_LAVA;
3452 default: return FALSE;
3456 * select region connected to center of cave system
3457 * this gets rid of alot of isolated one-sqaures that
3458 * can make teleport traps instadeaths...
3466 /* features to fill with */
3467 fill_data.feat1 = feat1;
3468 fill_data.feat2 = feat2;
3469 fill_data.feat3 = feat3;
3471 fill_data.info1 = 0;
3472 fill_data.info2 = 0;
3473 fill_data.info3 = 0;
3475 /* number of filled squares */
3476 fill_data.amount = 0;
3478 /* select region connected to center of cave system
3479 * this gets rid of alot of isolated one-sqaures that
3480 * can make teleport traps instadeaths... */
3481 cave_fill((byte)y0, (byte)x0);
3483 /* if tally too small, try again */
3484 if (fill_data.amount < 10)
3486 /* too small -clear area and try again later */
3487 for (x = 0; x <= xsize; ++x)
3489 for (y = 0; y <= ysize; ++y)
3491 place_floor_bold(y0 + y - yhsize, x0 + x - xhsize);
3492 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY);
3498 /* Do boundarys- set to normal granite */
3499 for (i = 0; i <= xsize; ++i)
3501 place_extra_bold(y0 + 0 - yhsize, x0 + i - xhsize);
3502 place_extra_bold(y0 + ysize - yhsize, x0 + i - xhsize);
3504 /* clear the icky flag-don't need it any more */
3505 cave[y0 + 0 - yhsize][x0 + i - xhsize].info &= ~(CAVE_ICKY);
3506 cave[y0 + ysize - yhsize][x0 + i - xhsize].info &= ~(CAVE_ICKY);
3509 /* Do the left and right boundaries minus the corners (done above) */
3511 for (i = 1; i < ysize; ++i)
3513 place_extra_bold(y0 + i - yhsize, x0 + 0 - xhsize);
3514 place_extra_bold(y0 + i - yhsize, x0 + xsize - xhsize);
3516 /* clear icky flag -done with it */
3517 cave[y0 + i - yhsize][x0 + 0 - xhsize].info &= ~(CAVE_ICKY);
3518 cave[y0 + i - yhsize][x0 + xsize - xhsize].info &= ~(CAVE_ICKY);
3522 /* Do the rest: convert back to the normal format */
3523 for (x = 1; x < xsize; ++x)
3525 for (y = 1; y < ysize; ++y)
3527 /* Fill unconnected regions with granite */
3528 if ((!(cave[y0 + y - yhsize][x0 + x - xhsize].info & CAVE_ICKY)) ||
3529 is_outer_bold(y0 + y - yhsize, x0 + x - xhsize))
3530 place_extra_bold(y0 + y - yhsize, x0 + x - xhsize);
3532 /* turn off icky flag (no longer needed.) */
3533 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY | CAVE_ROOM);
3535 /* Light lava and trees */
3536 if ((cave[y0 + y - yhsize][x0 + x - xhsize].feat == FEAT_DEEP_LAVA) ||
3537 (cave[y0 + y - yhsize][x0 + x - xhsize].feat == FEAT_SHAL_LAVA))
3539 cave[y0 + y - yhsize][x0 + x - xhsize].info |= CAVE_GLOW;
3549 * makes a lake/collapsed cave system in the center of the dungeon
3551 void build_lake(int type)
3553 int grd, roug, xsize, ysize, x0, y0;
3557 /* paranoia - exit if lake type out of range. */
3558 if ((type < 1) || (type > 7))
3560 msg_format("Invalid lake type (%d)", type);
3564 /* Make the size of the dungeon */
3565 xsize = cur_wid - 1;
3566 ysize = cur_hgt - 1;
3570 /* Paranoia: make size even */
3576 /* testing values for these parameters: feel free to adjust */
3577 grd = randint1(3) + 4;
3579 /* want average of about 16 */
3580 roug = randint1(8) * randint1(4);
3582 /* Make up size of various componants */
3586 /* Deep water/lava */
3587 c1 = randint0(c3 / 2) + randint0(c3 / 2) - 5;
3589 /* Shallow boundary */
3593 generate_hmap(y0 + 1, x0 + 1, xsize, ysize, grd, roug, c3);
3595 /* Convert to normal format+ clean up */
3596 done = generate_lake(y0 + 1, x0 + 1, xsize, ysize, c1, c2, c3, type);
3599 #endif /* ALLOW_CAVERNS_AND_LAKES */
3603 * Routine used by the random vault creators to add a door to a location
3604 * Note that range checking has to be done in the calling routine.
3606 * The doors must be INSIDE the allocated region.
3608 static void add_door(int x, int y)
3610 /* Need to have a wall in the center square */
3611 if (!is_outer_bold(y, x)) return;
3618 * where x=don't care
3622 if (is_floor_bold(y-1,x) && is_floor_bold(y+1,x) &&
3623 (is_outer_bold(y, x - 1) && is_outer_bold(y, x + 1)))
3626 place_secret_door(y, x);
3628 /* set boundarys so don't get wide doors */
3629 place_solid_bold(y, x - 1);
3630 place_solid_bold(y, x + 1);
3639 * where x = don't care
3642 if (is_outer_bold(y - 1, x) && is_outer_bold(y + 1, x) &&
3643 is_floor_bold(y,x-1) && is_floor_bold(y,x+1))
3646 place_secret_door(y, x);
3648 /* set boundarys so don't get wide doors */
3649 place_solid_bold(y - 1, x);
3650 place_solid_bold(y + 1, x);
3656 * Routine that fills the empty areas of a room with treasure and monsters.
3658 static void fill_treasure(int x1, int x2, int y1, int y2, int difficulty)
3660 int x, y, cx, cy, size;
3663 /* center of room:*/
3667 /* Rough measure of size of vault= sum of lengths of sides */
3668 size = abs(x2 - x1) + abs(y2 - y1);
3670 for (x = x1; x <= x2; x++)
3672 for (y = y1; y <= y2; y++)
3674 /* Thing added based on distance to center of vault
3675 * Difficulty is 1-easy to 10-hard */
3676 value = ((((s32b)(distance(cx, cy, x, y))) * 100) / size) + randint1(10) - difficulty;
3678 /* hack- empty square part of the time */
3679 if ((randint1(100) - difficulty * 3) > 50) value = 20;
3681 /* if floor, shallow water and lava */
3682 if (is_floor_bold(y, x) ||
3683 (cave[y][x].feat == FEAT_SHAL_WATER) ||
3684 (cave[y][x].feat == FEAT_SHAL_LAVA))
3686 /* The smaller 'value' is, the better the stuff */
3689 /* Meanest monster + treasure */
3690 monster_level = base_level + 40;
3691 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
3692 monster_level = base_level;
3693 object_level = base_level + 20;
3694 place_object(y, x, TRUE, FALSE);
3695 object_level = base_level;
3699 /* Mean monster +treasure */
3700 monster_level = base_level + 20;
3701 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
3702 monster_level = base_level;
3703 object_level = base_level + 10;
3704 place_object(y, x, TRUE, FALSE);
3705 object_level = base_level;
3707 else if (value < 10)
3710 monster_level = base_level + 9;
3711 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
3712 monster_level = base_level;
3714 else if (value < 17)
3716 /* Intentional Blank space */
3719 * (Want some of the vault to be empty
3720 * so have room for group monsters.
3721 * This is used in the hack above to lower
3722 * the density of stuff in the vault.)
3725 else if (value < 23)
3727 /* Object or trap */
3728 if (randint0(100) < 25)
3730 place_object(y, x, FALSE, FALSE);
3737 else if (value < 30)
3739 /* Monster and trap */
3740 monster_level = base_level + 5;
3741 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
3742 monster_level = base_level;
3745 else if (value < 40)
3747 /* Monster or object */
3748 if (randint0(100) < 50)
3750 monster_level = base_level + 3;
3751 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
3752 monster_level = base_level;
3754 if (randint0(100) < 50)
3756 object_level = base_level + 7;
3757 place_object(y, x, FALSE, FALSE);
3758 object_level = base_level;
3761 else if (value < 50)
3770 /* 20% monster, 40% trap, 20% object, 20% blank space */
3771 if (randint0(100) < 20)
3773 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
3775 else if (randint0(100) < 50)
3779 else if (randint0(100) < 50)
3781 place_object(y, x, FALSE, FALSE);
3792 * This function creates a random vault that looks like a collection of bubbles.
3793 * It works by getting a set of coordinates that represent the center of each
3794 * bubble. The entire room is made by seeing which bubble center is closest. If
3795 * two centers are equidistant then the square is a wall, otherwise it is a floor.
3796 * The only exception is for squares really near a center, these are always floor.
3797 * (It looks better than without this check.)
3799 * Note: If two centers are on the same point then this algorithm will create a
3800 * blank bubble filled with walls. - This is prevented from happening.
3802 static void build_bubble_vault(int x0, int y0, int xsize, int ysize)
3804 #define BUBBLENUM 10 /* number of bubbles */
3806 /* array of center points of bubbles */
3807 coord center[BUBBLENUM];
3810 u16b min1, min2, temp;
3813 /* Offset from center to top left hand corner */
3814 int xhsize = xsize / 2;
3815 int yhsize = ysize / 2;
3818 if (cheat_room) msg_print("Bubble Vault");
3820 /* Allocate center of bubbles */
3821 center[0].x = randint1(xsize - 3) + 1;
3822 center[0].y = randint1(ysize - 3) + 1;
3824 for (i = 1; i < BUBBLENUM; i++)
3828 /* get center and check to see if it is unique */
3833 x = randint1(xsize - 3) + 1;
3834 y = randint1(ysize - 3) + 1;
3836 for (j = 0; j < i; j++)
3838 /* rough test to see if there is an overlap */
3839 if ((x == center[j].x) && (y == center[j].y)) done = FALSE;
3848 /* Top and bottom boundaries */
3849 for (i = 0; i < xsize; i++)
3851 int x = x0 - xhsize + i;
3853 place_outer_noperm_bold(y0 - yhsize + 0, x);
3854 cave[y0 - yhsize + 0][x].info |= (CAVE_ROOM | CAVE_ICKY);
3855 place_outer_noperm_bold(y0 - yhsize + ysize - 1, x);
3856 cave[y0 - yhsize + ysize - 1][x].info |= (CAVE_ROOM | CAVE_ICKY);
3859 /* Left and right boundaries */
3860 for (i = 1; i < ysize - 1; i++)
3862 int y = y0 - yhsize + i;
3864 place_outer_noperm_bold(y, x0 - xhsize + 0);
3865 cave[y][x0 - xhsize + 0].info |= (CAVE_ROOM | CAVE_ICKY);
3866 place_outer_noperm_bold(y, x0 - xhsize + xsize - 1);
3867 cave[y][x0 - xhsize + xsize - 1].info |= (CAVE_ROOM | CAVE_ICKY);
3870 /* Fill in middle with bubbles */
3871 for (x = 1; x < xsize - 1; x++)
3873 for (y = 1; y < ysize - 1; y++)
3875 /* Get distances to two closest centers */
3878 min1 = distance(x, y, center[0].x, center[0].y);
3879 min2 = distance(x, y, center[1].x, center[1].y);
3883 /* swap if in wrong order */
3890 for (i = 2; i < BUBBLENUM; i++)
3892 temp = distance(x, y, center[i].x, center[i].y);
3900 else if (temp < min2)
3902 /* second smallest */
3906 if (((min2 - min1) <= 2) && (!(min1 < 3)))
3908 /* Boundary at midpoint+ not at inner region of bubble */
3909 place_outer_noperm_bold(y0 - yhsize + y, x0 - xhsize + x);
3913 /* middle of a bubble */
3914 place_floor_bold(y0 - yhsize + y, x0 - xhsize + x);
3917 /* clean up rest of flags */
3918 cave[y0 - yhsize + y][x0 - xhsize + x].info |= (CAVE_ROOM | CAVE_ICKY);
3922 /* Try to add some random doors */
3923 for (i = 0; i < 500; i++)
3925 x = randint1(xsize - 3) - xhsize + x0 + 1;
3926 y = randint1(ysize - 3) - yhsize + y0 + 1;
3930 /* Fill with monsters and treasure, low difficulty */
3931 fill_treasure(x0 - xhsize + 1, x0 - xhsize + xsize - 2, y0 - yhsize + 1, y0 - yhsize + ysize - 2, randint1(5));
3936 * Overlay a rectangular room given its bounds
3937 * This routine is used by build_room_vault
3938 * The area inside the walls is not touched:
3939 * only granite is removed- normal walls stay
3941 static void build_room(int x1, int x2, int y1, int y2)
3943 int x, y, i, xsize, ysize, temp;
3945 /* Check if rectangle has no width */
3946 if ((x1 == x2) || (y1 == y2)) return;
3951 /* Swap boundaries if in wrong order */
3959 /* Swap boundaries if in wrong order */
3965 /* get total widths */
3970 /* Top and bottom boundaries */
3971 for (i = 0; i <= xsize; i++)
3973 place_outer_noperm_bold(y1, x1 + i);
3974 cave[y1][x1 + i].info |= (CAVE_ROOM | CAVE_ICKY);
3975 place_outer_noperm_bold(y2, x1 + i);
3976 cave[y2][x1 + i].info |= (CAVE_ROOM | CAVE_ICKY);
3979 /* Left and right boundaries */
3980 for (i = 1; i < ysize; i++)
3982 place_outer_noperm_bold(y1 + i, x1);
3983 cave[y1 + i][x1].info|=(CAVE_ROOM | CAVE_ICKY);
3984 place_outer_noperm_bold(y1 + i, x2);
3985 cave[y1 + i][x2].info|=(CAVE_ROOM | CAVE_ICKY);
3989 for (x = 1; x < xsize; x++)
3991 for (y = 1; y < ysize; y++)
3993 if (is_extra_bold(y1+y, x1+x))
3995 /* clear the untouched region */
3996 place_floor_bold(y1 + y, x1 + x);
3997 cave[y1 + y][x1 + x].info |= (CAVE_ROOM | CAVE_ICKY);
4001 /* make it a room- but don't touch */
4002 cave[y1 + y][x1 + x].info |= (CAVE_ROOM | CAVE_ICKY);
4009 /* Create a random vault that looks like a collection of overlapping rooms */
4011 static void build_room_vault(int x0, int y0, int xsize, int ysize)
4013 int i, x1, x2, y1, y2, xhsize, yhsize;
4015 /* get offset from center */
4019 if (cheat_room) msg_print("Room Vault");
4021 /* fill area so don't get problems with arena levels */
4022 for (x1 = 0; x1 < xsize; x1++)
4024 int x = x0 - xhsize + x1;
4026 for (y1 = 0; y1 < ysize; y1++)
4028 int y = y0 - yhsize + y1;
4030 place_extra_bold(y, x);
4031 cave[y][x].info &= (~CAVE_ICKY);
4035 /* add ten random rooms */
4036 for (i = 0; i < 10; i++)
4038 x1 = randint1(xhsize) * 2 + x0 - xhsize;
4039 x2 = randint1(xhsize) * 2 + x0 - xhsize;
4040 y1 = randint1(yhsize) * 2 + y0 - yhsize;
4041 y2 = randint1(yhsize) * 2 + y0 - yhsize;
4042 build_room(x1, x2, y1, y2);
4045 /* Add some random doors */
4046 for (i = 0; i < 500; i++)
4048 x1 = randint1(xsize - 3) - xhsize + x0 + 1;
4049 y1 = randint1(ysize - 3) - yhsize + y0 + 1;
4053 /* Fill with monsters and treasure, high difficulty */
4054 fill_treasure(x0 - xhsize + 1, x0 - xhsize + xsize - 2, y0 - yhsize + 1, y0 - yhsize + ysize - 2, randint1(5) + 5);
4058 /* Create a random vault out of a fractal cave */
4059 static void build_cave_vault(int x0, int y0, int xsiz, int ysiz)
4061 int grd, roug, cutoff, xhsize, yhsize, xsize, ysize, x, y;
4062 bool done, light, room;
4064 /* round to make sizes even */
4070 if (cheat_room) msg_print("Cave Vault");
4072 light = done = FALSE;
4077 /* testing values for these parameters feel free to adjust */
4078 grd = 1 << randint0(4);
4080 /* want average of about 16 */
4081 roug = randint1(8) * randint1(4);
4084 cutoff = randint1(xsize / 4) + randint1(ysize / 4) +
4085 randint1(xsize / 4) + randint1(ysize / 4);
4088 generate_hmap(y0, x0, xsize, ysize, grd, roug, cutoff);
4090 /* Convert to normal format+ clean up */
4091 done = generate_fracave(y0, x0, xsize, ysize, cutoff, light, room);
4094 /* Set icky flag because is a vault */
4095 for (x = 0; x <= xsize; x++)
4097 for (y = 0; y <= ysize; y++)
4099 cave[y0 - yhsize + y][x0 - xhsize + x].info |= CAVE_ICKY;
4103 /* Fill with monsters and treasure, low difficulty */
4104 fill_treasure(x0 - xhsize + 1, x0 - xhsize + xsize - 1, y0 - yhsize + 1, y0 - yhsize + ysize - 1, randint1(5));
4108 * maze vault -- rectangular labyrinthine rooms
4110 * maze vault uses two routines:
4111 * r_visit - a recursive routine that builds the labyrinth
4112 * build_maze_vault - a driver routine that calls r_visit and adds
4113 * monsters, traps and treasure
4115 * The labyrinth is built by creating a spanning tree of a graph.
4116 * The graph vertices are at
4117 * (x, y) = (2j + x1, 2k + y1) j = 0,...,m-1 k = 0,...,n-1
4118 * and the edges are the vertical and horizontal nearest neighbors.
4120 * The spanning tree is created by performing a suitably randomized
4121 * depth-first traversal of the graph. The only adjustable parameter
4122 * is the randint0(3) below; it governs the relative density of
4123 * twists and turns in the labyrinth: smaller number, more twists.
4125 static void r_visit(int y1, int x1, int y2, int x2,
4126 int node, int dir, int *visited)
4128 int i, j, m, n, temp, x, y, adj[4];
4130 /* dimensions of vertex array */
4131 m = (x2 - x1) / 2 + 1;
4132 n = (y2 - y1) / 2 + 1;
4134 /* mark node visited and set it to a floor */
4136 x = 2 * (node % m) + x1;
4137 y = 2 * (node / m) + y1;
4138 place_floor_bold(y, x);
4140 /* setup order of adjacent node visits */
4143 /* pick a random ordering */
4144 for (i = 0; i < 4; i++)
4146 for (i = 0; i < 4; i++)
4157 /* pick a random ordering with dir first */
4159 for (i = 1; i < 4; i++)
4161 for (i = 1; i < 4; i++)
4163 j = 1 + randint0(3);
4170 for (i = 0; i < 4; i++)
4175 /* (0,+) - check for bottom boundary */
4176 if ((node / m < n - 1) && (visited[node + m] == 0))
4178 place_floor_bold(y + 1, x);
4179 r_visit(y1, x1, y2, x2, node + m, dir, visited);
4183 /* (0,-) - check for top boundary */
4184 if ((node / m > 0) && (visited[node - m] == 0))
4186 place_floor_bold(y - 1, x);
4187 r_visit(y1, x1, y2, x2, node - m, dir, visited);
4191 /* (+,0) - check for right boundary */
4192 if ((node % m < m - 1) && (visited[node + 1] == 0))
4194 place_floor_bold(y, x + 1);
4195 r_visit(y1, x1, y2, x2, node + 1, dir, visited);
4199 /* (-,0) - check for left boundary */
4200 if ((node % m > 0) && (visited[node - 1] == 0))
4202 place_floor_bold(y, x - 1);
4203 r_visit(y1, x1, y2, x2, node - 1, dir, visited);
4210 void build_maze_vault(int x0, int y0, int xsize, int ysize, bool is_vault)
4214 int m, n, num_vertices, *visited;
4219 if (cheat_room && is_vault) msg_print("Maze Vault");
4221 /* Choose lite or dark */
4222 light = ((dun_level <= randint1(25)) && is_vault && !(d_info[dungeon_type].flags1 & DF1_DARKNESS));
4224 /* Pick a random room size - randomized by calling routine */
4233 /* generate the room */
4234 for (y = y1 - 1; y <= y2 + 1; y++)
4236 for (x = x1 - 1; x <= x2 + 1; x++)
4238 c_ptr = &cave[y][x];
4239 c_ptr->info |= CAVE_ROOM;
4240 if (is_vault) c_ptr->info |= CAVE_ICKY;
4241 if ((x == x1 - 1) || (x == x2 + 1) || (y == y1 - 1) || (y == y2 + 1))
4243 place_outer_grid(c_ptr);
4247 place_extra_grid(c_ptr);
4251 place_inner_grid(c_ptr);
4253 if (light) c_ptr->info |= (CAVE_GLOW);
4257 /* dimensions of vertex array */
4260 num_vertices = m * n;
4262 /* initialize array of visited vertices */
4263 C_MAKE(visited, num_vertices, int);
4265 /* traverse the graph to create a spaning tree, pick a random root */
4266 r_visit(y1, x1, y2, x2, randint0(num_vertices), 0, visited);
4268 /* Fill with monsters and treasure, low difficulty */
4269 if (is_vault) fill_treasure(x1, x2, y1, y2, randint1(5));
4271 C_KILL(visited, num_vertices, int);
4275 /* Build a "mini" checkerboard vault
4277 * This is done by making a permanent wall maze and setting
4278 * the diagonal sqaures of the checker board to be granite.
4279 * The vault has two entrances on opposite sides to guarantee
4280 * a way to get in even if the vault abuts a side of the dungeon.
4282 static void build_mini_c_vault(int x0, int y0, int xsize, int ysize)
4285 int y1, x1, y2, x2, y, x, total;
4286 int m, n, num_vertices;
4289 if (cheat_room) msg_print("Mini Checker Board Vault");
4291 /* Pick a random room size */
4301 /* generate the room */
4302 for (x = x1 - 2; x <= x2 + 2; x++)
4304 if (!in_bounds(y1-2,x)) break;
4306 cave[y1-2][x].info |= (CAVE_ROOM | CAVE_ICKY);
4308 place_extra_noperm_bold(y1-2, x);
4311 for (x = x1 - 2; x <= x2 + 2; x++)
4313 if (!in_bounds(y2+2,x)) break;
4315 cave[y2+2][x].info |= (CAVE_ROOM | CAVE_ICKY);
4317 place_extra_noperm_bold(y2+2, x);
4320 for (y = y1 - 2; y <= y2 + 2; y++)
4322 if (!in_bounds(y,x1-2)) break;
4324 cave[y][x1-2].info |= (CAVE_ROOM | CAVE_ICKY);
4326 place_extra_noperm_bold(y, x1-2);
4329 for (y = y1 - 2; y <= y2 + 2; y++)
4331 if (!in_bounds(y,x2+2)) break;
4333 cave[y][x2+2].info |= (CAVE_ROOM | CAVE_ICKY);
4335 place_extra_noperm_bold(y, x2+2);
4338 for (y = y1 - 1; y <= y2 + 1; y++)
4340 for (x = x1 - 1; x <= x2 + 1; x++)
4342 cave[y][x].info |= (CAVE_ROOM | CAVE_ICKY);
4344 /* Permanent walls */
4345 cave[y][x].feat = FEAT_PERM_INNER;
4350 /* dimensions of vertex array */
4353 num_vertices = m * n;
4355 /* initialize array of visited vertices */
4356 C_MAKE(visited, num_vertices, int);
4358 /* traverse the graph to create a spannng tree, pick a random root */
4359 r_visit(y1, x1, y2, x2, randint0(num_vertices), 0, visited);
4361 /* Make it look like a checker board vault */
4362 for (x = x1; x <= x2; x++)
4364 for (y = y1; y <= y2; y++)
4366 total = x - x1 + y - y1;
4367 /* If total is odd- and is a floor then make a wall */
4368 if ((total % 2 == 1) && is_floor_bold(y, x))
4370 place_inner_bold(y, x);
4375 /* Make a couple of entrances */
4378 /* left and right */
4379 y = randint1(dy) + dy / 2;
4380 place_outer_noperm_bold(y1 + y, x1 - 1);
4381 place_outer_noperm_bold(y1 + y, x2 + 1);
4385 /* top and bottom */
4386 x = randint1(dx) + dx / 2;
4387 place_outer_noperm_bold(y1 - 1, x1 + x);
4388 place_outer_noperm_bold(y2 + 1, x1 + x);
4391 /* Fill with monsters and treasure, highest difficulty */
4392 fill_treasure(x1, x2, y1, y2, 10);
4394 C_KILL(visited, num_vertices, int);
4398 /* Build a town/ castle by using a recursive algorithm.
4399 * Basically divide each region in a probalistic way to create
4400 * smaller regions. When the regions get too small stop.
4402 * The power variable is a measure of how well defended a region is.
4403 * This alters the possible choices.
4405 static void build_recursive_room(int x1, int y1, int x2, int y2, int power)
4411 /* Temp variables */
4417 if ((power < 3) && (xsize > 12) && (ysize > 12))
4419 /* Need outside wall +keep */
4426 /* Make rooms + subdivide */
4427 if ((randint1(10) > 2) && (xsize < 8) && (ysize < 8))
4433 choice = randint1(2) + 1;
4438 /* Mostly subdivide */
4439 choice = randint1(3) + 1;
4443 /* Based on the choice made above, do something */
4451 /* top and bottom */
4452 for (x = x1; x <= x2; x++)
4454 place_outer_bold(y1, x);
4455 place_outer_bold(y2, x);
4458 /* left and right */
4459 for (y = y1 + 1; y < y2; y++)
4461 place_outer_bold(y, x1);
4462 place_outer_bold(y, x2);
4465 /* Make a couple of entrances */
4468 /* left and right */
4469 y = randint1(ysize) + y1;
4470 place_floor_bold(y, x1);
4471 place_floor_bold(y, x2);
4475 /* top and bottom */
4476 x = randint1(xsize) + x1;
4477 place_floor_bold(y1, x);
4478 place_floor_bold(y2, x);
4481 /* Select size of keep */
4482 t1 = randint1(ysize / 3) + y1;
4483 t2 = y2 - randint1(ysize / 3);
4484 t3 = randint1(xsize / 3) + x1;
4485 t4 = x2 - randint1(xsize / 3);
4487 /* Do outside areas */
4489 /* Above and below keep */
4490 build_recursive_room(x1 + 1, y1 + 1, x2 - 1, t1, power + 1);
4491 build_recursive_room(x1 + 1, t2, x2 - 1, y2, power + 1);
4493 /* Left and right of keep */
4494 build_recursive_room(x1 + 1, t1 + 1, t3, t2 - 1, power + 3);
4495 build_recursive_room(t4, t1 + 1, x2 - 1, t2 - 1, power + 3);
4497 /* Make the keep itself: */
4510 /* Try to build a room */
4511 if ((xsize < 3) || (ysize < 3))
4513 for (y = y1; y < y2; y++)
4515 for (x = x1; x < x2; x++)
4517 place_inner_bold(y, x);
4525 /* Make outside walls */
4526 /* top and bottom */
4527 for (x = x1 + 1; x <= x2 - 1; x++)
4529 place_inner_bold(y1 + 1, x);
4530 place_inner_bold(y2 - 1, x);
4533 /* left and right */
4534 for (y = y1 + 1; y <= y2 - 1; y++)
4536 place_inner_bold(y, x1 + 1);
4537 place_inner_bold(y, x2 - 1);
4541 y = randint1(ysize - 3) + y1 + 1;
4546 place_floor_bold(y, x1 + 1);
4551 place_floor_bold(y, x2 - 1);
4554 /* Build the room */
4555 build_recursive_room(x1 + 2, y1 + 2, x2 - 2, y2 - 2, power + 3);
4560 /* Try and divide vertically */
4564 for (y = y1; y < y2; y++)
4566 for (x = x1; x < x2; x++)
4568 place_inner_bold(y, x);
4574 t1 = randint1(xsize - 2) + x1 + 1;
4575 build_recursive_room(x1, y1, t1, y2, power - 2);
4576 build_recursive_room(t1 + 1, y1, x2, y2, power - 2);
4581 /* Try and divide horizontally */
4585 for (y = y1; y < y2; y++)
4587 for (x = x1; x < x2; x++)
4589 place_inner_bold(y, x);
4595 t1 = randint1(ysize - 2) + y1 + 1;
4596 build_recursive_room(x1, y1, x2, t1, power - 2);
4597 build_recursive_room(x1, t1 + 1, x2, y2, power - 2);
4604 /* Build a castle */
4606 /* Driver routine: clear the region and call the recursive
4609 *This makes a vault that looks like a castle/ city in the dungeon.
4611 static void build_castle_vault(int x0, int y0, int xsize, int ysize)
4617 /* Pick a random room size */
4626 if (cheat_room) msg_print("Castle Vault");
4628 /* generate the room */
4629 for (y = y1 - 1; y <= y2 + 1; y++)
4631 for (x = x1 - 1; x <= x2 + 1; x++)
4633 cave[y][x].info |= (CAVE_ROOM | CAVE_ICKY);
4634 /* Make everything a floor */
4635 place_floor_bold(y, x);
4639 /* Make the castle */
4640 build_recursive_room(x1, y1, x2, y2, randint1(5));
4642 /* Fill with monsters and treasure, low difficulty */
4643 fill_treasure(x1, x2, y1, y2, randint1(3));
4648 * Add outer wall to a floored region
4649 * Note: no range checking is done so must be inside dungeon
4650 * This routine also stomps on doors
4652 static void add_outer_wall(int x, int y, int light,
4653 int x1, int y1, int x2, int y2)
4657 if (!in_bounds(y, x)) return;
4659 /* hack- check to see if square has been visited before
4660 * if so, then exit (use room flag to do this) */
4661 if (cave[y][x].info & CAVE_ROOM) return;
4664 cave[y][x].info |= CAVE_ROOM;
4666 if (is_floor_bold(y, x))
4668 for (i = -1; i <= 1; i++)
4670 for (j = -1; j <= 1; j++)
4672 if ((x + i >= x1) && (x + i <= x2) &&
4673 (y + j >= y1) && (y + j <= y2))
4675 add_outer_wall(x + i, y + j, light, x1, y1, x2, y2);
4676 if (light) cave[y][x].info |= CAVE_GLOW;
4681 else if (is_extra_bold(y, x))
4683 /* Set bounding walls */
4684 place_outer_bold(y, x);
4685 if (light == TRUE) cave[y][x].info |= CAVE_GLOW;
4687 else if (cave[y][x].feat == FEAT_PERM_OUTER)
4689 /* Set bounding walls */
4690 if (light == TRUE) cave[y][x].info |= CAVE_GLOW;
4696 * Hacked distance formula - gives the 'wrong' answer.
4697 * Used to build crypts
4699 static int dist2(int x1, int y1, int x2, int y2,
4700 int h1, int h2, int h3, int h4)
4706 /* Basically this works by taking the normal pythagorean formula
4707 * and using an expansion to express this in a way without the
4708 * square root. This approximate formula is then perturbed to give
4709 * the distorted results. (I found this by making a mistake when I was
4710 * trying to fix the circular rooms.)
4713 /* h1-h4 are constants that describe the metric */
4714 if (dx >= 2 * dy) return (dx + (dy * h1) / h2);
4715 if (dy >= 2 * dx) return (dy + (dx * h1) / h2);
4716 return (((dx + dy) * 128) / 181 +
4717 (dx * dx / (dy * h3) + dy * dy / (dx * h3)) * h4);
4718 /* 128/181 is approx. 1/sqrt(2) */
4723 * Build target vault.
4724 * This is made by two concentric "crypts" with perpendicular
4725 * walls creating the cross-hairs.
4727 static void build_target_vault(int x0, int y0, int xsize, int ysize)
4731 /* Make a random metric */
4733 h1 = randint1(32) - 16;
4736 h4 = randint1(32) - 16;
4738 if (cheat_room) msg_print("Target Vault");
4740 /* work out outer radius */
4751 for (x = x0 - rad; x <= x0 + rad; x++)
4753 for (y = y0 - rad; y <= y0 + rad; y++)
4755 /* clear room flag */
4756 cave[y][x].info &= ~(CAVE_ROOM);
4758 /* Vault - so is "icky" */
4759 cave[y][x].info |= CAVE_ICKY;
4761 if (dist2(y0, x0, y, x, h1, h2, h3, h4) <= rad - 1)
4763 /* inside- so is floor */
4764 place_floor_bold(y, x);
4768 /* make granite outside so arena works */
4769 place_extra_bold(y, x);
4772 /* proper boundary for arena */
4773 if (((y + rad) == y0) || ((y - rad) == y0) ||
4774 ((x + rad) == x0) || ((x - rad) == x0))
4776 place_extra_bold(y, x);
4781 /* Find visible outer walls and set to be FEAT_OUTER */
4782 add_outer_wall(x0, y0, FALSE, x0 - rad - 1, y0 - rad - 1,
4783 x0 + rad + 1, y0 + rad + 1);
4785 /* Add inner wall */
4786 for (x = x0 - rad / 2; x <= x0 + rad / 2; x++)
4788 for (y = y0 - rad / 2; y <= y0 + rad / 2; y++)
4790 if (dist2(y0, x0, y, x, h1, h2, h3, h4) == rad / 2)
4792 /* Make an internal wall */
4793 place_inner_bold(y, x);
4798 /* Add perpendicular walls */
4799 for (x = x0 - rad; x <= x0 + rad; x++)
4801 place_inner_bold(y0, x);
4804 for (y = y0 - rad; y <= y0 + rad; y++)
4806 place_inner_bold(y, x0);
4809 /* Make inner vault */
4810 for (y = y0 - 1; y <= y0 + 1; y++)
4812 place_inner_bold(y, x0 - 1);
4813 place_inner_bold(y, x0 + 1);
4815 for (x = x0 - 1; x <= x0 + 1; x++)
4817 place_inner_bold(y0 - 1, x);
4818 place_inner_bold(y0 + 1, x);
4821 place_floor_bold(y0, x0);
4824 /* Add doors to vault */
4825 /* get two distances so can place doors relative to centre */
4826 x = (rad - 2) / 4 + 1;
4829 add_door(x0 + x, y0);
4830 add_door(x0 + y, y0);
4831 add_door(x0 - x, y0);
4832 add_door(x0 - y, y0);
4833 add_door(x0, y0 + x);
4834 add_door(x0, y0 + y);
4835 add_door(x0, y0 - x);
4836 add_door(x0, y0 - y);
4838 /* Fill with stuff - medium difficulty */
4839 fill_treasure(x0 - rad, x0 + rad, y0 - rad, y0 + rad, randint1(3) + 3);
4843 #ifdef ALLOW_CAVERNS_AND_LAKES
4845 * This routine uses a modified version of the lake code to make a
4846 * distribution of some terrain type over the vault. This type
4847 * depends on the dungeon depth.
4849 * Miniture rooms are then scattered across the vault.
4851 static void build_elemental_vault(int x0, int y0, int xsiz, int ysiz)
4856 int xsize, ysize, xhsize, yhsize, x, y, i;
4860 if (cheat_room) msg_print("Elemental Vault");
4862 /* round to make sizes even */
4870 /* Earth vault (Rubble) */
4873 else if (dun_level < 50)
4875 /* Air vault (Trees) */
4878 else if (dun_level < 75)
4880 /* Water vault (shallow water) */
4885 /* Fire vault (shallow lava) */
4891 /* testing values for these parameters: feel free to adjust */
4892 grd = 1 << (randint0(3));
4894 /* want average of about 16 */
4895 roug = randint1(8) * randint1(4);
4897 /* Make up size of various componants */
4901 /* Deep water/lava */
4902 c1 = randint0(c3 / 2) + randint0(c3 / 2) - 5;
4904 /* Shallow boundary */
4908 generate_hmap(y0, x0, xsize, ysize, grd, roug, c3);
4910 /* Convert to normal format+ clean up */
4911 done = generate_lake(y0, x0, xsize, ysize, c1, c2, c3, type);
4914 /* Set icky flag because is a vault */
4915 for (x = 0; x <= xsize; x++)
4917 for (y = 0; y <= ysize; y++)
4919 cave[y0 - yhsize + y][x0 - xhsize + x].info |= CAVE_ICKY;
4923 /* make a few rooms in the vault */
4924 for (i = 1; i <= (xsize * ysize) / 50; i++)
4926 build_small_room(x0 + randint0(xsize - 4) - xsize / 2 + 2,
4927 y0 + randint0(ysize - 4) - ysize / 2 + 2);
4930 /* Fill with monsters and treasure, low difficulty */
4931 fill_treasure(x0 - xhsize + 1, x0 - xhsize + xsize - 1,
4932 y0 - yhsize + 1, y0 - yhsize + ysize - 1, randint1(5));
4934 #endif /* ALLOW_CAVERNS_AND_LAKES */
4940 static void build_type10(int by0, int bx0)
4942 int y0, x0, xsize, ysize, vtype;
4945 /* big enough to look good, small enough to be fairly common. */
4946 xsize = randint1(22) + 22;
4947 ysize = randint1(11) + 11;
4949 /* Allocate in room_map. If will not fit, exit */
4950 if (!room_alloc(xsize + 1, ysize + 1, FALSE, by0, bx0, &x0, &y0)) return;
4952 /* Boost the rating- higher than lesser vaults and lower than greater vaults */
4955 /* (Sometimes) Cause a special feeling */
4956 if ((dun_level <= 50) ||
4957 (randint1((dun_level - 40) * (dun_level - 40) + 1) < 400))
4959 good_item_flag = TRUE;
4962 /* Select type of vault */
4963 #ifdef ALLOW_CAVERNS_AND_LAKES
4964 vtype = randint1(15);
4965 #else /* ALLOW_CAVERNS_AND_LAKES */
4966 vtype = randint1(7);
4967 #endif /* ALLOW_CAVERNS_AND_LAKES */
4971 /* Build an appropriate room */
4972 case 1: case 9: build_bubble_vault(x0, y0, xsize, ysize); break;
4973 case 2: case 10: build_room_vault(x0, y0, xsize, ysize); break;
4974 case 3: case 11: build_cave_vault(x0, y0, xsize, ysize); break;
4975 case 4: case 12: build_maze_vault(x0, y0, xsize, ysize, TRUE); break;
4976 case 5: case 13: build_mini_c_vault(x0, y0, xsize, ysize); break;
4977 case 6: case 14: build_castle_vault(x0, y0, xsize, ysize); break;
4978 case 7: case 15: build_target_vault(x0, y0, xsize, ysize); break;
4979 #ifdef ALLOW_CAVERNS_AND_LAKES
4980 case 8: build_elemental_vault(x0, y0, xsize, ysize); break;
4981 #endif /* ALLOW_CAVERNS_AND_LAKES */
4982 /* I know how to add a few more... give me some time. */
4991 * Build an vertical oval room.
4992 * For every grid in the possible square, check the distance.
4993 * If it's less than the radius, make it a room square.
4995 * When done fill from the inside to find the walls,
4997 static void build_type11(int by0, int bx0)
4999 int rad, x, y, x0, y0;
5002 /* Occasional light */
5003 if ((randint1(dun_level) <= 15) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS)) light = TRUE;
5007 /* Allocate in room_map. If will not fit, exit */
5008 if (!room_alloc(rad * 2 + 1, rad * 2 + 1, FALSE, by0, bx0, &x0, &y0)) return;
5010 /* Make circular floor */
5011 for (x = x0 - rad; x <= x0 + rad; x++)
5013 for (y = y0 - rad; y <= y0 + rad; y++)
5015 if (distance(y0, x0, y, x) <= rad - 1)
5017 /* inside- so is floor */
5018 place_floor_bold(y, x);
5020 else if (distance(y0, x0, y, x) <= rad + 1)
5022 /* make granite outside so arena works */
5023 place_extra_bold(y, x);
5028 /* Find visible outer walls and set to be FEAT_OUTER */
5029 add_outer_wall(x0, y0, light, x0 - rad, y0 - rad, x0 + rad, y0 + rad);
5035 * For every grid in the possible square, check the (fake) distance.
5036 * If it's less than the radius, make it a room square.
5038 * When done fill from the inside to find the walls,
5040 static void build_type12(int by0, int bx0)
5042 int rad, x, y, x0, y0;
5044 bool emptyflag = TRUE;
5046 /* Make a random metric */
5048 h1 = randint1(32) - 16;
5051 h4 = randint1(32) - 16;
5053 /* Occasional light */
5054 if ((randint1(dun_level) <= 5) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS)) light = TRUE;
5058 /* Allocate in room_map. If will not fit, exit */
5059 if (!room_alloc(rad * 2 + 3, rad * 2 + 3, FALSE, by0, bx0, &x0, &y0)) return;
5062 for (x = x0 - rad; x <= x0 + rad; x++)
5064 for (y = y0 - rad; y <= y0 + rad; y++)
5066 /* clear room flag */
5067 cave[y][x].info &= ~(CAVE_ROOM);
5069 if (dist2(y0, x0, y, x, h1, h2, h3, h4) <= rad - 1)
5071 /* inside - so is floor */
5072 place_floor_bold(y, x);
5074 else if (distance(y0, x0, y, x) < 3)
5076 place_floor_bold(y, x);
5080 /* make granite outside so arena works */
5081 place_extra_bold(y, x);
5084 /* proper boundary for arena */
5085 if (((y + rad) == y0) || ((y - rad) == y0) ||
5086 ((x + rad) == x0) || ((x - rad) == x0))
5088 place_extra_bold(y, x);
5093 /* Find visible outer walls and set to be FEAT_OUTER */
5094 add_outer_wall(x0, y0, light, x0 - rad - 1, y0 - rad - 1,
5095 x0 + rad + 1, y0 + rad + 1);
5097 /* Check to see if there is room for an inner vault */
5098 for (x = x0 - 2; x <= x0 + 2; x++)
5100 for (y = y0 - 2; y <= y0 + 2; y++)
5102 if (!is_floor_bold(y, x))
5104 /* Wall in the way */
5110 if (emptyflag && one_in_(2))
5112 /* Build the vault */
5113 build_small_room(x0, y0);
5115 /* Place a treasure in the vault */
5116 place_object(y0, x0, FALSE, FALSE);
5118 /* Let's guard the treasure well */
5119 vault_monsters(y0, x0, randint0(2) + 3);
5121 /* Traps naturally */
5122 vault_traps(y0, x0, 4, 4, randint0(3) + 2);
5128 * Helper function for "trapped monster pit"
5130 static bool vault_aux_trapped_pit(int r_idx)
5132 monster_race *r_ptr = &r_info[r_idx];
5134 /* Validate the monster */
5135 if (!vault_monster_okay(r_idx)) return (FALSE);
5137 /* No wall passing monster */
5138 if (r_ptr->flags2 & (RF2_PASS_WALL | RF2_KILL_WALL)) return (FALSE);
5146 * Type 12 -- Trapped monster pits
5148 * A trapped monster pit is a "big" room with a straight corridor in
5149 * which wall opening traps are placed, and with two "inner" rooms
5150 * containing a "collection" of monsters of a given type organized in
5153 * The trapped monster pit appears as shown below, where the actual
5154 * monsters in each location depend on the type of the pit
5156 * #########################
5158 * ####################### #
5159 * #####001123454321100### #
5160 * ###0012234567654322100# #
5161 * ####################### #
5163 * # #######################
5164 * # #0012234567654322100###
5165 * # ###001123454321100#####
5166 * # #######################
5168 * #########################
5170 * Note that the monsters in the pit are now chosen by using "get_mon_num()"
5171 * to request 16 "appropriate" monsters, sorting them by level, and using
5172 * the "even" entries in this sorted list for the contents of the pit.
5174 * Hack -- all of the "dragons" in a "dragon" pit must be the same "color",
5175 * which is handled by requiring a specific "breath" attack for all of the
5176 * dragons. This may include "multi-hued" breath. Note that "wyrms" may
5177 * be present in many of the dragon pits, if they have the proper breath.
5179 * Note the use of the "get_mon_num_prep()" function, and the special
5180 * "get_mon_num_hook()" restriction function, to prepare the "monster
5181 * allocation table" in such a way as to optimize the selection of
5182 * "appropriate" non-unique monsters for the pit.
5184 * Note that the "get_mon_num()" function may (rarely) fail, in which case
5185 * the pit will be empty, and will not effect the level rating.
5187 * Note that "monster pits" will never contain "unique" monsters.
5189 static void build_type13(int by0, int bx0)
5191 static int placing[][3] = {
5192 {-2, -9, 0}, {-2, -8, 0}, {-3, -7, 0}, {-3, -6, 0},
5193 {+2, -9, 0}, {+2, -8, 0}, {+3, -7, 0}, {+3, -6, 0},
5194 {-2, +9, 0}, {-2, +8, 0}, {-3, +7, 0}, {-3, +6, 0},
5195 {+2, +9, 0}, {+2, +8, 0}, {+3, +7, 0}, {+3, +6, 0},
5196 {-2, -7, 1}, {-3, -5, 1}, {-3, -4, 1},
5197 {+2, -7, 1}, {+3, -5, 1}, {+3, -4, 1},
5198 {-2, +7, 1}, {-3, +5, 1}, {-3, +4, 1},
5199 {+2, +7, 1}, {+3, +5, 1}, {+3, +4, 1},
5200 {-2, -6, 2}, {-2, -5, 2}, {-3, -3, 2},
5201 {+2, -6, 2}, {+2, -5, 2}, {+3, -3, 2},
5202 {-2, +6, 2}, {-2, +5, 2}, {-3, +3, 2},
5203 {+2, +6, 2}, {+2, +5, 2}, {+3, +3, 2},
5204 {-2, -4, 3}, {-3, -2, 3},
5205 {+2, -4, 3}, {+3, -2, 3},
5206 {-2, +4, 3}, {-3, +2, 3},
5207 {+2, +4, 3}, {+3, +2, 3},
5208 {-2, -3, 4}, {-3, -1, 4},
5209 {+2, -3, 4}, {+3, -1, 4},
5210 {-2, +3, 4}, {-3, +1, 4},
5211 {+2, +3, 4}, {+3, +1, 4},
5212 {-2, -2, 5}, {-3, 0, 5}, {-2, +2, 5},
5213 {+2, -2, 5}, {+3, 0, 5}, {+2, +2, 5},
5214 {-2, -1, 6}, {-2, +1, 6},
5215 {+2, -1, 6}, {+2, +1, 6},
5216 {-2, 0, 7}, {+2, 0, 7},
5220 int y, x, y1, x1, y2, x2, xval, yval;
5229 vault_aux_type *n_ptr = pick_vault_type(pit_types, ROOM_PIT);
5231 /* Only in Angband */
5232 if (dungeon_type != 1) return;
5234 /* Try to allocate space for room. */
5235 if (!room_alloc(25, 13, TRUE, by0, bx0, &xval, &yval)) return;
5237 /* No type available */
5240 /* Process a preparation function if necessary */
5241 if (n_ptr->prep_func) (*(n_ptr->prep_func))();
5249 /* Fill with inner walls */
5250 for (y = y1 - 1; y <= y2 + 1; y++)
5252 for (x = x1 - 1; x <= x2 + 1; x++)
5254 c_ptr = &cave[y][x];
5255 place_inner_grid(c_ptr);
5256 c_ptr->info |= (CAVE_ROOM);
5260 /* Place the floor area 1 */
5261 for (x = x1 + 3; x <= x2 - 3; x++)
5263 c_ptr = &cave[yval-2][x];
5264 place_floor_grid(c_ptr);
5265 add_cave_info(yval-2, x, CAVE_ICKY);
5267 c_ptr = &cave[yval+2][x];
5268 place_floor_grid(c_ptr);
5269 add_cave_info(yval+2, x, CAVE_ICKY);
5272 /* Place the floor area 2 */
5273 for (x = x1 + 5; x <= x2 - 5; x++)
5275 c_ptr = &cave[yval-3][x];
5276 place_floor_grid(c_ptr);
5277 add_cave_info(yval-3, x, CAVE_ICKY);
5279 c_ptr = &cave[yval+3][x];
5280 place_floor_grid(c_ptr);
5281 add_cave_info(yval+3, x, CAVE_ICKY);
5285 for (x = x1; x <= x2; x++)
5287 c_ptr = &cave[yval][x];
5288 place_floor_grid(c_ptr);
5289 c_ptr = &cave[y1][x];
5290 place_floor_grid(c_ptr);
5291 c_ptr = &cave[y2][x];
5292 place_floor_grid(c_ptr);
5295 /* Place the outer walls */
5296 for (y = y1 - 1; y <= y2 + 1; y++)
5298 c_ptr = &cave[y][x1 - 1];
5299 place_outer_grid(c_ptr);
5300 c_ptr = &cave[y][x2 + 1];
5301 place_outer_grid(c_ptr);
5303 for (x = x1 - 1; x <= x2 + 1; x++)
5305 c_ptr = &cave[y1 - 1][x];
5306 place_outer_grid(c_ptr);
5307 c_ptr = &cave[y2 + 1][x];
5308 place_outer_grid(c_ptr);
5311 /* Random corridor */
5314 for (y = y1; y <= yval; y++)
5316 place_floor_bold(y, x2);
5317 place_solid_bold(y, x1-1);
5319 for (y = yval; y <= y2 + 1; y++)
5321 place_floor_bold(y, x1);
5322 place_solid_bold(y, x2+1);
5327 for (y = yval; y <= y2 + 1; y++)
5329 place_floor_bold(y, x1);
5330 place_solid_bold(y, x2+1);
5332 for (y = y1; y <= yval; y++)
5334 place_floor_bold(y, x2);
5335 place_solid_bold(y, x1-1);
5339 /* Place the wall open trap */
5340 cave[yval][xval].mimic = cave[yval][xval].feat;
5341 cave[yval][xval].feat = FEAT_TRAP_OPEN;
5343 /* Prepare allocation table */
5344 get_mon_num_prep(n_ptr->hook_func, vault_aux_trapped_pit);
5346 /* Pick some monster types */
5347 for (i = 0; i < 16; i++)
5349 int r_idx = 0, attempts = 100;
5353 /* Get a (hard) monster type */
5354 r_idx = get_mon_num(dun_level + 0);
5356 /* Decline incorrect alignment */
5357 if (((align < 0) && (r_info[r_idx].flags3 & RF3_GOOD)) ||
5358 ((align > 0) && (r_info[r_idx].flags3 & RF3_EVIL)))
5363 /* Accept this monster */
5367 /* Notice failure */
5368 if (!r_idx || !attempts) return;
5370 /* Note the alignment */
5371 if (r_info[r_idx].flags3 & RF3_GOOD) align++;
5372 else if (r_info[r_idx].flags3 & RF3_EVIL) align--;
5377 /* Sort the entries */
5378 for (i = 0; i < 16 - 1; i++)
5380 /* Sort the entries */
5381 for (j = 0; j < 16 - 1; j++)
5386 int p1 = r_info[what[i1]].level;
5387 int p2 = r_info[what[i2]].level;
5393 what[i1] = what[i2];
5403 msg_format("%s¤Î櫥ԥåÈ", n_ptr->name);
5406 msg_format("Trapped monster pit (%s)", n_ptr->name);
5410 /* Select the entries */
5411 for (i = 0; i < 8; i++)
5413 /* Every other entry */
5414 what[i] = what[i * 2];
5419 msg_print(r_name + r_info[what[i]].name);
5423 /* Increase the level rating */
5426 /* (Sometimes) Cause a "special feeling" (for "Monster Pits") */
5427 if ((dun_level <= 40) && (randint1(dun_level * dun_level + 50) < 300))
5429 good_item_flag = TRUE;
5433 for (i = 0; placing[i][2] >= 0; i++)
5435 y = yval + placing[i][0];
5436 x = xval + placing[i][1];
5437 place_monster_aux(0, y, x, what[placing[i][2]], PM_NO_KAGE);
5443 * Type 14 -- trapped rooms
5445 * A special trap is placed at center of the room
5447 static void build_type14(int by0, int bx0)
5449 int y, x, y2, x2, yval, xval;
5450 int y1, x1, xsize, ysize;
5457 /* Pick a room size */
5463 xsize = x1 + x2 + 1;
5464 ysize = y1 + y2 + 1;
5466 /* Try to allocate space for room. If fails, exit */
5467 if (!room_alloc(xsize + 2, ysize + 2, FALSE, by0, bx0, &xval, &yval)) return;
5469 /* Choose lite or dark */
5470 light = ((dun_level <= randint1(25)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS));
5473 /* Get corner values */
5474 y1 = yval - ysize / 2;
5475 x1 = xval - xsize / 2;
5476 y2 = yval + (ysize - 1) / 2;
5477 x2 = xval + (xsize - 1) / 2;
5480 /* Place a full floor under the room */
5481 for (y = y1 - 1; y <= y2 + 1; y++)
5483 for (x = x1 - 1; x <= x2 + 1; x++)
5485 c_ptr = &cave[y][x];
5486 place_floor_grid(c_ptr);
5487 c_ptr->info |= (CAVE_ROOM);
5488 if (light) c_ptr->info |= (CAVE_GLOW);
5492 /* Walls around the room */
5493 for (y = y1 - 1; y <= y2 + 1; y++)
5495 c_ptr = &cave[y][x1 - 1];
5496 place_outer_grid(c_ptr);
5497 c_ptr = &cave[y][x2 + 1];
5498 place_outer_grid(c_ptr);
5500 for (x = x1 - 1; x <= x2 + 1; x++)
5502 c_ptr = &cave[y1 - 1][x];
5503 place_outer_grid(c_ptr);
5504 c_ptr = &cave[y2 + 1][x];
5505 place_outer_grid(c_ptr);
5508 if (dun_level < 30 + randint1(30))
5509 trap = FEAT_TRAP_PIRANHA;
5511 trap = FEAT_TRAP_ARMAGEDDON;
5513 /* Place a special trap */
5514 cave[yval][xval].mimic = cave[yval][xval].feat;
5515 cave[yval][xval].feat = trap;
5521 msg_format("%s¤ÎÉô²°", f_name + f_info[trap].name);
5523 msg_format("Room of %s", f_name + f_info[trap].name);
5530 * Attempt to build a room of the given type at the given block
5532 * Note that we restrict the number of "crowded" rooms to reduce
5533 * the chance of overflowing the monster list during level creation.
5535 bool room_build(int by0, int bx0, int typ)
5537 /* Restrict level */
5538 if ((dun_level < roomdep[typ]) && !ironman_rooms) return (FALSE);
5540 /* Restrict "crowded" rooms */
5541 if ((dun->crowded >= 2) && ((typ == 5) || (typ == 6) || (typ == 13))) return (FALSE);
5546 /* Build an appropriate room */
5547 case 14: build_type14(by0, bx0); break;
5548 case 13: build_type13(by0, bx0); break;
5549 case 12: build_type12(by0, bx0); break;
5550 case 11: build_type11(by0, bx0); break;
5551 case 10: build_type10(by0, bx0); break;
5552 case 9: build_type9(by0, bx0); break;
5553 case 8: build_type8(by0, bx0); break;
5554 case 7: build_type7(by0, bx0); break;
5555 case 6: build_type6(by0, bx0, FALSE); break;
5556 case 5: build_type5(by0, bx0, FALSE); break;
5557 case 4: build_type4(by0, bx0); break;
5558 case 3: build_type3(by0, bx0); break;
5559 case 2: build_type2(by0, bx0); break;
5560 case 1: build_type1(by0, bx0); break;
5563 default: return (FALSE);