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 */
42 static void place_locked_door(int y, int x)
44 if (d_info[dungeon_type].flags1 & DF1_NO_DOORS)
46 place_floor_bold(y, x);
50 set_cave_feat(y, x, FEAT_DOOR_HEAD+randint1(7));
51 cave[y][x].info &= ~(CAVE_FLOOR);
55 static void place_secret_door(int y, int x)
57 if (d_info[dungeon_type].flags1 & DF1_NO_DOORS)
59 place_floor_bold(y, x);
63 set_cave_feat(y, x, FEAT_SECRET);
64 cave[y][x].info &= ~(CAVE_FLOOR);
69 * This funtion makes a very small room centred at (x0, y0)
70 * This is used in crypts, and random elemental vaults.
72 * Note - this should be used only on allocated regions
73 * within another room.
75 static void build_small_room(int x0, int y0)
79 for (y = y0 - 1; y <= y0 + 1; y++)
81 place_inner_bold(y, x0 - 1);
82 place_inner_bold(y, x0 + 1);
85 for (x = x0 - 1; x <= x0 + 1; x++)
87 place_inner_bold(y0 - 1, x);
88 place_inner_bold(y0 + 1, x);
91 /* Place a secret door on one side */
94 case 0: place_secret_door(y0, x0 - 1); break;
95 case 1: place_secret_door(y0, x0 + 1); break;
96 case 2: place_secret_door(y0 - 1, x0); break;
97 case 3: place_secret_door(y0 + 1, x0); break;
100 /* Add inner open space */
101 place_floor_bold(y0, x0);
106 * This function tunnels around a room if
107 * it will cut off part of a cave system.
109 static void check_room_boundary(int x1, int y1, int x2, int y2)
112 bool old_is_floor, new_is_floor;
118 old_is_floor = get_is_floor(x1 - 1, y1);
121 * Count the number of floor-wall boundaries around the room
122 * Note: diagonal squares are ignored since the player can move diagonally
123 * to bypass these if needed.
126 /* Above the top boundary */
127 for (x = x1; x <= x2; x++)
129 new_is_floor = get_is_floor(x, y1 - 1);
131 /* Increment counter if they are different */
132 if (new_is_floor != old_is_floor) count++;
134 old_is_floor = new_is_floor;
138 for (y = y1; y <= y2; y++)
140 new_is_floor = get_is_floor(x2 + 1, y);
142 /* increment counter if they are different */
143 if (new_is_floor != old_is_floor) count++;
145 old_is_floor = new_is_floor;
148 /* Bottom boundary */
149 for (x = x2; x >= x1; x--)
151 new_is_floor = get_is_floor(x, y2 + 1);
153 /* increment counter if they are different */
154 if (new_is_floor != old_is_floor) count++;
156 old_is_floor = new_is_floor;
160 for (y = y2; y >= y1; y--)
162 new_is_floor = get_is_floor(x1 - 1, y);
164 /* increment counter if they are different */
165 if (new_is_floor != old_is_floor) count++;
167 old_is_floor = new_is_floor;
170 /* If all the same, or only one connection exit. */
171 if (count <= 2) return;
174 /* Tunnel around the room so to prevent problems with caves */
175 for (y = y1; y <= y2; y++)
177 for (x = x1; x <= x2; x++)
186 * This function is used to allocate the space needed by a room in the room_map
188 * x, y represent the size of the room (0...x-1) by (0...y-1).
189 * crowded is used to denote a monset nest.
190 * by0, bx0 are the positions in the room_map array given to the build_type'x'
192 * xx, yy are the returned center of the allocated room in coordinates for
193 * cave.feat and cave.info etc.
195 static bool room_alloc(int x, int y, bool crowded, int by0, int bx0, int *xx, int *yy)
197 int temp, bx1, bx2, by1, by2, by, bx;
199 /* Calculate number of room_map squares to allocate */
201 /* temp is total number along width */
202 temp = ((x - 1) / BLOCK_WID) + 1;
204 /* bx2 = ending block */
205 bx2 = temp / 2 + bx0;
207 /* bx1 = starting block (Note: rounding taken care of here.) */
208 bx1 = bx2 + 1 - temp;
210 /* temp is total number along height */
211 temp = ((y - 1) / BLOCK_HGT) + 1;
213 /* by2 = ending block */
214 by2 = temp / 2 + by0;
216 /* by1 = starting block */
217 by1 = by2 + 1 - temp;
220 /* Never run off the screen */
221 if ((by1 < 0) || (by2 >= dun->row_rooms)) return (FALSE);
222 if ((bx1 < 0) || (bx2 >= dun->col_rooms)) return (FALSE);
224 /* Verify open space */
225 for (by = by1; by <= by2; by++)
227 for (bx = bx1; bx <= bx2; bx++)
229 if (dun->room_map[by][bx]) return (FALSE);
233 /* It is *extremely* important that the following calculation */
234 /* be *exactly* correct to prevent memory errors XXX XXX XXX */
236 /* Acquire the location of the room */
237 *yy = ((by1 + by2 + 1) * BLOCK_HGT) / 2;
238 *xx = ((bx1 + bx2 + 1) * BLOCK_WID) / 2;
241 /* Save the room location */
242 if (dun->cent_n < CENT_MAX)
244 dun->cent[dun->cent_n].y = *yy;
245 dun->cent[dun->cent_n].x = *xx;
249 /* Reserve some blocks */
250 for (by = by1; by <= by2; by++)
252 for (bx = bx1; bx <= bx2; bx++)
254 dun->room_map[by][bx] = TRUE;
258 /* Count "crowded" rooms */
259 if (crowded) dun->crowded++;
262 * Hack- See if room will cut off a cavern.
263 * If so, fix by tunneling outside the room in such a way as to connect the caves.
265 check_room_boundary(*xx - x / 2 - 1, *yy - y / 2 - 1,
266 *xx + (x - 1) / 2 + 1, *yy + (y - 1) / 2 + 1);
273 * Room building routines.
279 * 4 -- large room with features
283 * 8 -- greater vaults
285 * 10 -- random vaults
286 * 11 -- circular rooms
288 * 13 -- trapped monster pits
293 * Type 1 -- normal rectangular rooms
295 static void build_type1(int by0, int bx0)
297 int y, x, y2, x2, yval, xval;
298 int y1, x1, xsize, ysize;
304 /* Pick a room size */
313 /* Try to allocate space for room. If fails, exit */
314 if (!room_alloc(xsize + 2, ysize + 2, FALSE, by0, bx0, &xval, &yval)) return;
316 /* Choose lite or dark */
317 light = ((dun_level <= randint1(25)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS));
320 /* Get corner values */
321 y1 = yval - ysize / 2;
322 x1 = xval - xsize / 2;
323 y2 = yval + (ysize - 1) / 2;
324 x2 = xval + (xsize - 1) / 2;
327 /* Place a full floor under the room */
328 for (y = y1 - 1; y <= y2 + 1; y++)
330 for (x = x1 - 1; x <= x2 + 1; x++)
333 place_floor_grid(c_ptr);
334 c_ptr->info |= (CAVE_ROOM);
335 if (light) c_ptr->info |= (CAVE_GLOW);
339 /* Walls around the room */
340 for (y = y1 - 1; y <= y2 + 1; y++)
342 c_ptr = &cave[y][x1 - 1];
343 place_outer_grid(c_ptr);
344 c_ptr = &cave[y][x2 + 1];
345 place_outer_grid(c_ptr);
347 for (x = x1 - 1; x <= x2 + 1; x++)
349 c_ptr = &cave[y1 - 1][x];
350 place_outer_grid(c_ptr);
351 c_ptr = &cave[y2 + 1][x];
352 place_outer_grid(c_ptr);
356 /* Hack -- Occasional pillar room */
359 for (y = y1; y <= y2; y += 2)
361 for (x = x1; x <= x2; x += 2)
364 place_inner_grid(c_ptr);
369 /* Hack -- Occasional room with four pillars */
370 else if (one_in_(20))
372 if ((y1 + 4 < y2) && (x1 + 4 < x2))
374 c_ptr = &cave[y1 + 1][x1 + 1];
375 place_inner_grid(c_ptr);
377 c_ptr = &cave[y1 + 1][x2 - 1];
378 place_inner_grid(c_ptr);
380 c_ptr = &cave[y2 - 1][x1 + 1];
381 place_inner_grid(c_ptr);
383 c_ptr = &cave[y2 - 1][x2 - 1];
384 place_inner_grid(c_ptr);
388 /* Hack -- Occasional ragged-edge room */
389 else if (one_in_(50))
391 for (y = y1 + 2; y <= y2 - 2; y += 2)
393 c_ptr = &cave[y][x1];
394 place_inner_grid(c_ptr);
395 c_ptr = &cave[y][x2];
396 place_inner_grid(c_ptr);
398 for (x = x1 + 2; x <= x2 - 2; x += 2)
400 c_ptr = &cave[y1][x];
401 place_inner_grid(c_ptr);
402 c_ptr = &cave[y2][x];
403 place_inner_grid(c_ptr);
406 /* Hack -- Occasional divided room */
407 else if (one_in_(50))
409 if (randint1(100) < 50)
411 /* Horizontal wall */
412 for (x = x1; x <= x2; x++)
414 place_inner_bold(yval, x);
417 /* Prevent edge of wall from being tunneled */
418 place_solid_bold(yval, x1 - 1);
419 place_solid_bold(yval, x2 + 1);
424 for (y = y1; y <= y2; y++)
426 place_inner_bold(y, xval);
429 /* Prevent edge of wall from being tunneled */
430 place_solid_bold(y1 - 1, xval);
431 place_solid_bold(y2 + 1, xval);
434 place_random_door(yval, xval);
440 * Type 2 -- Overlapping rectangular rooms
442 static void build_type2(int by0, int bx0)
444 int y, x, xval, yval;
445 int y1a, x1a, y2a, x2a;
446 int y1b, x1b, y2b, x2b;
451 /* Try to allocate space for room. If fails, exit */
452 if (!room_alloc(25, 11, FALSE, by0, bx0, &xval, &yval)) return;
454 /* Choose lite or dark */
455 light = ((dun_level <= randint1(25)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS));
457 /* Determine extents of the first room */
458 y1a = yval - randint1(4);
459 y2a = yval + randint1(3);
460 x1a = xval - randint1(11);
461 x2a = xval + randint1(10);
463 /* Determine extents of the second room */
464 y1b = yval - randint1(3);
465 y2b = yval + randint1(4);
466 x1b = xval - randint1(10);
467 x2b = xval + randint1(11);
470 /* Place a full floor for room "a" */
471 for (y = y1a - 1; y <= y2a + 1; y++)
473 for (x = x1a - 1; x <= x2a + 1; x++)
476 place_floor_grid(c_ptr);
477 c_ptr->info |= (CAVE_ROOM);
478 if (light) c_ptr->info |= (CAVE_GLOW);
482 /* Place a full floor for room "b" */
483 for (y = y1b - 1; y <= y2b + 1; y++)
485 for (x = x1b - 1; x <= x2b + 1; x++)
488 place_floor_grid(c_ptr);
489 c_ptr->info |= (CAVE_ROOM);
490 if (light) c_ptr->info |= (CAVE_GLOW);
495 /* Place the walls around room "a" */
496 for (y = y1a - 1; y <= y2a + 1; y++)
498 c_ptr = &cave[y][x1a - 1];
499 place_outer_grid(c_ptr);
500 c_ptr = &cave[y][x2a + 1];
501 place_outer_grid(c_ptr);
503 for (x = x1a - 1; x <= x2a + 1; x++)
505 c_ptr = &cave[y1a - 1][x];
506 place_outer_grid(c_ptr);
507 c_ptr = &cave[y2a + 1][x];
508 place_outer_grid(c_ptr);
511 /* Place the walls around room "b" */
512 for (y = y1b - 1; y <= y2b + 1; y++)
514 c_ptr = &cave[y][x1b - 1];
515 place_outer_grid(c_ptr);
516 c_ptr = &cave[y][x2b + 1];
517 place_outer_grid(c_ptr);
519 for (x = x1b - 1; x <= x2b + 1; x++)
521 c_ptr = &cave[y1b - 1][x];
522 place_outer_grid(c_ptr);
523 c_ptr = &cave[y2b + 1][x];
524 place_outer_grid(c_ptr);
529 /* Replace the floor for room "a" */
530 for (y = y1a; y <= y2a; y++)
532 for (x = x1a; x <= x2a; x++)
535 place_floor_grid(c_ptr);
539 /* Replace the floor for room "b" */
540 for (y = y1b; y <= y2b; y++)
542 for (x = x1b; x <= x2b; x++)
545 place_floor_grid(c_ptr);
553 * Type 3 -- Cross shaped rooms
555 * Builds a room at a row, column coordinate
557 * Room "a" runs north/south, and Room "b" runs east/east
558 * So the "central pillar" runs from x1a, y1b to x2a, y2b.
560 * Note that currently, the "center" is always 3x3, but I think that
561 * the code below will work (with "bounds checking") for 5x5, or even
562 * for unsymetric values like 4x3 or 5x3 or 3x4 or 3x5, or even larger.
564 static void build_type3(int by0, int bx0)
566 int y, x, dy, dx, wy, wx;
567 int y1a, x1a, y2a, x2a;
568 int y1b, x1b, y2b, x2b;
574 /* Try to allocate space for room. */
575 if (!room_alloc(25, 11, FALSE, by0, bx0, &xval, &yval)) return;
577 /* Choose lite or dark */
578 light = ((dun_level <= randint1(25)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS));
580 /* For now, always 3x3 */
583 /* Pick max vertical size (at most 4) */
584 dy = rand_range(3, 4);
586 /* Pick max horizontal size (at most 15) */
587 dx = rand_range(3, 11);
590 /* Determine extents of the north/south room */
596 /* Determine extents of the east/west room */
603 /* Place a full floor for room "a" */
604 for (y = y1a - 1; y <= y2a + 1; y++)
606 for (x = x1a - 1; x <= x2a + 1; x++)
609 place_floor_grid(c_ptr);
610 c_ptr->info |= (CAVE_ROOM);
611 if (light) c_ptr->info |= (CAVE_GLOW);
615 /* Place a full floor for room "b" */
616 for (y = y1b - 1; y <= y2b + 1; y++)
618 for (x = x1b - 1; x <= x2b + 1; x++)
621 place_floor_grid(c_ptr);
622 c_ptr->info |= (CAVE_ROOM);
623 if (light) c_ptr->info |= (CAVE_GLOW);
628 /* Place the walls around room "a" */
629 for (y = y1a - 1; y <= y2a + 1; y++)
631 c_ptr = &cave[y][x1a - 1];
632 place_outer_grid(c_ptr);
633 c_ptr = &cave[y][x2a + 1];
634 place_outer_grid(c_ptr);
636 for (x = x1a - 1; x <= x2a + 1; x++)
638 c_ptr = &cave[y1a - 1][x];
639 place_outer_grid(c_ptr);
640 c_ptr = &cave[y2a + 1][x];
641 place_outer_grid(c_ptr);
644 /* Place the walls around room "b" */
645 for (y = y1b - 1; y <= y2b + 1; y++)
647 c_ptr = &cave[y][x1b - 1];
648 place_outer_grid(c_ptr);
649 c_ptr = &cave[y][x2b + 1];
650 place_outer_grid(c_ptr);
652 for (x = x1b - 1; x <= x2b + 1; x++)
654 c_ptr = &cave[y1b - 1][x];
655 place_outer_grid(c_ptr);
656 c_ptr = &cave[y2b + 1][x];
657 place_outer_grid(c_ptr);
661 /* Replace the floor for room "a" */
662 for (y = y1a; y <= y2a; y++)
664 for (x = x1a; x <= x2a; x++)
667 place_floor_grid(c_ptr);
671 /* Replace the floor for room "b" */
672 for (y = y1b; y <= y2b; y++)
674 for (x = x1b; x <= x2b; x++)
677 place_floor_grid(c_ptr);
683 /* Special features (3/4) */
686 /* Large solid middle pillar */
689 for (y = y1b; y <= y2b; y++)
691 for (x = x1a; x <= x2a; x++)
694 place_inner_grid(c_ptr);
700 /* Inner treasure vault */
703 /* Build the vault */
704 for (y = y1b; y <= y2b; y++)
706 c_ptr = &cave[y][x1a];
707 place_inner_grid(c_ptr);
708 c_ptr = &cave[y][x2a];
709 place_inner_grid(c_ptr);
711 for (x = x1a; x <= x2a; x++)
713 c_ptr = &cave[y1b][x];
714 place_inner_grid(c_ptr);
715 c_ptr = &cave[y2b][x];
716 place_inner_grid(c_ptr);
719 /* Place a secret door on the inner room */
722 case 0: place_secret_door(y1b, xval); break;
723 case 1: place_secret_door(y2b, xval); break;
724 case 2: place_secret_door(yval, x1a); break;
725 case 3: place_secret_door(yval, x2a); break;
728 /* Place a treasure in the vault */
729 place_object(yval, xval, FALSE, FALSE);
731 /* Let's guard the treasure well */
732 vault_monsters(yval, xval, randint0(2) + 3);
734 /* Traps naturally */
735 vault_traps(yval, xval, 4, 4, randint0(3) + 2);
743 /* Occasionally pinch the center shut */
746 /* Pinch the east/west sides */
747 for (y = y1b; y <= y2b; y++)
749 if (y == yval) continue;
750 c_ptr = &cave[y][x1a - 1];
751 place_inner_grid(c_ptr);
752 c_ptr = &cave[y][x2a + 1];
753 place_inner_grid(c_ptr);
756 /* Pinch the north/south sides */
757 for (x = x1a; x <= x2a; x++)
759 if (x == xval) continue;
760 c_ptr = &cave[y1b - 1][x];
761 place_inner_grid(c_ptr);
762 c_ptr = &cave[y2b + 1][x];
763 place_inner_grid(c_ptr);
766 /* Sometimes shut using secret doors */
769 place_secret_door(yval, x1a - 1);
770 place_secret_door(yval, x2a + 1);
771 place_secret_door(y1b - 1, xval);
772 place_secret_door(y2b + 1, xval);
776 /* Occasionally put a "plus" in the center */
779 c_ptr = &cave[yval][xval];
780 place_inner_grid(c_ptr);
781 c_ptr = &cave[y1b][xval];
782 place_inner_grid(c_ptr);
783 c_ptr = &cave[y2b][xval];
784 place_inner_grid(c_ptr);
785 c_ptr = &cave[yval][x1a];
786 place_inner_grid(c_ptr);
787 c_ptr = &cave[yval][x2a];
788 place_inner_grid(c_ptr);
791 /* Occasionally put a pillar in the center */
794 c_ptr = &cave[yval][xval];
795 place_inner_grid(c_ptr);
805 * Type 4 -- Large room with inner features
807 * Possible sub-types:
808 * 1 - Just an inner room with one door
809 * 2 - An inner room within an inner room
810 * 3 - An inner room with pillar(s)
811 * 4 - Inner room has a maze
812 * 5 - A set of four inner rooms
814 static void build_type4(int by0, int bx0)
817 int y2, x2, tmp, yval, xval;
822 /* Try to allocate space for room. */
823 if (!room_alloc(25, 11, FALSE, by0, bx0, &xval, &yval)) return;
825 /* Choose lite or dark */
826 light = ((dun_level <= randint1(25)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS));
834 /* Place a full floor under the room */
835 for (y = y1 - 1; y <= y2 + 1; y++)
837 for (x = x1 - 1; x <= x2 + 1; x++)
840 place_floor_grid(c_ptr);
841 c_ptr->info |= (CAVE_ROOM);
842 if (light) c_ptr->info |= (CAVE_GLOW);
847 for (y = y1 - 1; y <= y2 + 1; y++)
849 c_ptr = &cave[y][x1 - 1];
850 place_outer_grid(c_ptr);
851 c_ptr = &cave[y][x2 + 1];
852 place_outer_grid(c_ptr);
854 for (x = x1 - 1; x <= x2 + 1; x++)
856 c_ptr = &cave[y1 - 1][x];
857 place_outer_grid(c_ptr);
858 c_ptr = &cave[y2 + 1][x];
859 place_outer_grid(c_ptr);
869 /* The inner walls */
870 for (y = y1 - 1; y <= y2 + 1; y++)
872 c_ptr = &cave[y][x1 - 1];
873 place_inner_grid(c_ptr);
874 c_ptr = &cave[y][x2 + 1];
875 place_inner_grid(c_ptr);
877 for (x = x1 - 1; x <= x2 + 1; x++)
879 c_ptr = &cave[y1 - 1][x];
880 place_inner_grid(c_ptr);
881 c_ptr = &cave[y2 + 1][x];
882 place_inner_grid(c_ptr);
886 /* Inner room variations */
889 /* Just an inner room with a monster */
892 /* Place a secret door */
895 case 1: place_secret_door(y1 - 1, xval); break;
896 case 2: place_secret_door(y2 + 1, xval); break;
897 case 3: place_secret_door(yval, x1 - 1); break;
898 case 4: place_secret_door(yval, x2 + 1); break;
901 /* Place a monster in the room */
902 vault_monsters(yval, xval, 1);
907 /* Treasure Vault (with a door) */
910 /* Place a secret door */
913 case 1: place_secret_door(y1 - 1, xval); break;
914 case 2: place_secret_door(y2 + 1, xval); break;
915 case 3: place_secret_door(yval, x1 - 1); break;
916 case 4: place_secret_door(yval, x2 + 1); break;
919 /* Place another inner room */
920 for (y = yval - 1; y <= yval + 1; y++)
922 for (x = xval - 1; x <= xval + 1; x++)
924 if ((x == xval) && (y == yval)) continue;
926 place_inner_grid(c_ptr);
930 /* Place a locked door on the inner room */
933 case 1: place_locked_door(yval - 1, xval); break;
934 case 2: place_locked_door(yval + 1, xval); break;
935 case 3: place_locked_door(yval, xval - 1); break;
936 case 4: place_locked_door(yval, xval + 1); break;
939 /* Monsters to guard the "treasure" */
940 vault_monsters(yval, xval, randint1(3) + 2);
943 if (randint0(100) < 80)
945 place_object(yval, xval, FALSE, FALSE);
951 place_random_stairs(yval, xval);
954 /* Traps to protect the treasure */
955 vault_traps(yval, xval, 4, 10, 2 + randint1(3));
960 /* Inner pillar(s). */
963 /* Place a secret door */
966 case 1: place_secret_door(y1 - 1, xval); break;
967 case 2: place_secret_door(y2 + 1, xval); break;
968 case 3: place_secret_door(yval, x1 - 1); break;
969 case 4: place_secret_door(yval, x2 + 1); break;
972 /* Large Inner Pillar */
973 for (y = yval - 1; y <= yval + 1; y++)
975 for (x = xval - 1; x <= xval + 1; x++)
978 place_inner_grid(c_ptr);
982 /* Occasionally, two more Large Inner Pillars */
986 for (y = yval - 1; y <= yval + 1; y++)
988 for (x = xval - 5 - tmp; x <= xval - 3 - tmp; x++)
991 place_inner_grid(c_ptr);
993 for (x = xval + 3 + tmp; x <= xval + 5 + tmp; x++)
996 place_inner_grid(c_ptr);
1001 /* Occasionally, some Inner rooms */
1004 /* Long horizontal walls */
1005 for (x = xval - 5; x <= xval + 5; x++)
1007 c_ptr = &cave[yval - 1][x];
1008 place_inner_grid(c_ptr);
1009 c_ptr = &cave[yval + 1][x];
1010 place_inner_grid(c_ptr);
1013 /* Close off the left/right edges */
1014 c_ptr = &cave[yval][xval - 5];
1015 place_inner_grid(c_ptr);
1016 c_ptr = &cave[yval][xval + 5];
1017 place_inner_grid(c_ptr);
1019 /* Secret doors (random top/bottom) */
1020 place_secret_door(yval - 3 + (randint1(2) * 2), xval - 3);
1021 place_secret_door(yval - 3 + (randint1(2) * 2), xval + 3);
1024 vault_monsters(yval, xval - 2, randint1(2));
1025 vault_monsters(yval, xval + 2, randint1(2));
1028 if (one_in_(3)) place_object(yval, xval - 2, FALSE, FALSE);
1029 if (one_in_(3)) place_object(yval, xval + 2, FALSE, FALSE);
1038 /* Place a secret door */
1039 switch (randint1(4))
1041 case 1: place_secret_door(y1 - 1, xval); break;
1042 case 2: place_secret_door(y2 + 1, xval); break;
1043 case 3: place_secret_door(yval, x1 - 1); break;
1044 case 4: place_secret_door(yval, x2 + 1); break;
1047 /* Maze (really a checkerboard) */
1048 for (y = y1; y <= y2; y++)
1050 for (x = x1; x <= x2; x++)
1054 c_ptr = &cave[y][x];
1055 place_inner_grid(c_ptr);
1060 /* Monsters just love mazes. */
1061 vault_monsters(yval, xval - 5, randint1(3));
1062 vault_monsters(yval, xval + 5, randint1(3));
1064 /* Traps make them entertaining. */
1065 vault_traps(yval, xval - 3, 2, 8, randint1(3));
1066 vault_traps(yval, xval + 3, 2, 8, randint1(3));
1068 /* Mazes should have some treasure too. */
1069 vault_objects(yval, xval, 3);
1074 /* Four small rooms. */
1078 for (y = y1; y <= y2; y++)
1080 c_ptr = &cave[y][xval];
1081 place_inner_grid(c_ptr);
1083 for (x = x1; x <= x2; x++)
1085 c_ptr = &cave[yval][x];
1086 place_inner_grid(c_ptr);
1089 /* Doors into the rooms */
1090 if (randint0(100) < 50)
1092 int i = randint1(10);
1093 place_secret_door(y1 - 1, xval - i);
1094 place_secret_door(y1 - 1, xval + i);
1095 place_secret_door(y2 + 1, xval - i);
1096 place_secret_door(y2 + 1, xval + i);
1100 int i = randint1(3);
1101 place_secret_door(yval + i, x1 - 1);
1102 place_secret_door(yval - i, x1 - 1);
1103 place_secret_door(yval + i, x2 + 1);
1104 place_secret_door(yval - i, x2 + 1);
1107 /* Treasure, centered at the center of the cross */
1108 vault_objects(yval, xval, 2 + randint1(2));
1110 /* Gotta have some monsters. */
1111 vault_monsters(yval + 1, xval - 4, randint1(4));
1112 vault_monsters(yval + 1, xval + 4, randint1(4));
1113 vault_monsters(yval - 1, xval - 4, randint1(4));
1114 vault_monsters(yval - 1, xval + 4, randint1(4));
1123 * The following functions are used to determine if the given monster
1124 * is appropriate for inclusion in a monster nest or monster pit or
1127 * None of the pits/nests are allowed to include "unique" monsters.
1132 * Monster validation macro
1134 * Line 1 -- forbid town monsters
1135 * Line 2 -- forbid uniques
1136 * Line 3 -- forbid aquatic monsters
1138 #define vault_monster_okay(I) \
1139 (monster_dungeon(I) && \
1140 !(r_info[I].flags1 & RF1_UNIQUE) && \
1141 !(r_info[I].flags7 & RF7_UNIQUE2) && \
1142 !(r_info[I].flags3 & RF3_RES_ALL) && \
1143 !(r_info[I].flags7 & RF7_AQUATIC))
1146 /* Race index for "monster pit (clone)" */
1147 static int vault_aux_race;
1149 /* Race index for "monster pit (symbol clone)" */
1150 static char vault_aux_char;
1152 /* Breath mask for "monster pit (dragon)" */
1153 static u32b vault_aux_dragon_mask4;
1157 * Helper monster selection function
1159 static bool vault_aux_simple(int r_idx)
1162 return (vault_monster_okay(r_idx));
1167 * Helper function for "monster nest (jelly)"
1169 static bool vault_aux_jelly(int r_idx)
1171 monster_race *r_ptr = &r_info[r_idx];
1173 /* Validate the monster */
1174 if (!vault_monster_okay(r_idx)) return (FALSE);
1176 if (r_ptr->flags2 & (RF2_KILL_BODY)) return (FALSE);
1178 /* Also decline evil jellies (like death molds and shoggoths) */
1179 if (r_ptr->flags3 & (RF3_EVIL)) return (FALSE);
1181 /* Require icky thing, jelly, mold, or mushroom */
1182 if (!strchr("ijm,", r_ptr->d_char)) return (FALSE);
1190 * Helper function for "monster nest (animal)"
1192 static bool vault_aux_animal(int r_idx)
1194 monster_race *r_ptr = &r_info[r_idx];
1196 /* Validate the monster */
1197 if (!vault_monster_okay(r_idx)) return (FALSE);
1199 /* Require "animal" flag */
1200 if (!(r_ptr->flags3 & (RF3_ANIMAL))) return (FALSE);
1208 * Helper function for "monster nest (undead)"
1210 static bool vault_aux_undead(int r_idx)
1212 monster_race *r_ptr = &r_info[r_idx];
1214 /* Validate the monster */
1215 if (!vault_monster_okay(r_idx)) return (FALSE);
1217 /* Require Undead */
1218 if (!(r_ptr->flags3 & (RF3_UNDEAD))) return (FALSE);
1226 * Helper function for "monster nest (chapel)"
1228 static bool vault_aux_chapel_g(int r_idx)
1230 static int chapel_list[] = {
1231 MON_NOV_PRIEST, MON_NOV_PALADIN, MON_NOV_PRIEST_G, MON_NOV_PALADIN_G,
1232 MON_PRIEST, MON_JADE_MONK, MON_IVORY_MONK, MON_ULTRA_PALADIN,
1233 MON_EBONY_MONK, MON_W_KNIGHT, MON_KNI_TEMPLAR, MON_PALADIN,
1238 monster_race *r_ptr = &r_info[r_idx];
1240 /* Validate the monster */
1241 if (!vault_monster_okay(r_idx)) return (FALSE);
1243 if (r_ptr->flags3 & (RF3_EVIL)) return (FALSE);
1244 if ((r_idx == MON_A_GOLD) || (r_idx == MON_A_SILVER)) return (FALSE);
1246 /* Require "priest" or Angel */
1248 if (r_ptr->d_char == 'A') return TRUE;
1250 for (i = 0; chapel_list[i]; i++)
1251 if (r_idx == chapel_list[i]) return TRUE;
1258 * Helper function for "monster nest (kennel)"
1260 static bool vault_aux_kennel(int r_idx)
1262 monster_race *r_ptr = &r_info[r_idx];
1264 /* Validate the monster */
1265 if (!vault_monster_okay(r_idx)) return (FALSE);
1267 /* Require a Zephyr Hound or a dog */
1268 if (!strchr("CZ", r_ptr->d_char)) return (FALSE);
1276 * Helper function for "monster nest (mimic)"
1278 static bool vault_aux_mimic(int r_idx)
1280 monster_race *r_ptr = &r_info[r_idx];
1282 /* Validate the monster */
1283 if (!vault_monster_okay(r_idx)) return (FALSE);
1286 if (!strchr("!|$?=", r_ptr->d_char)) return (FALSE);
1293 * Helper function for "monster nest (clone)"
1295 static bool vault_aux_clone(int r_idx)
1297 /* Validate the monster */
1298 if (!vault_monster_okay(r_idx)) return (FALSE);
1300 return (r_idx == vault_aux_race);
1305 * Helper function for "monster nest (symbol clone)"
1307 static bool vault_aux_symbol_e(int r_idx)
1309 monster_race *r_ptr = &r_info[r_idx];
1311 /* Validate the monster */
1312 if (!vault_monster_okay(r_idx)) return (FALSE);
1314 if (r_ptr->flags2 & (RF2_KILL_BODY)) return (FALSE);
1316 if (r_ptr->flags3 & (RF3_GOOD)) return (FALSE);
1318 /* Decline incorrect symbol */
1319 if (r_ptr->d_char != vault_aux_char) return (FALSE);
1327 * Helper function for "monster nest (symbol clone)"
1329 static bool vault_aux_symbol_g(int r_idx)
1331 monster_race *r_ptr = &r_info[r_idx];
1333 /* Validate the monster */
1334 if (!vault_monster_okay(r_idx)) return (FALSE);
1336 if (r_ptr->flags2 & (RF2_KILL_BODY)) return (FALSE);
1338 if (r_ptr->flags3 & (RF3_EVIL)) return (FALSE);
1340 /* Decline incorrect symbol */
1341 if (r_ptr->d_char != vault_aux_char) return (FALSE);
1349 * Helper function for "monster pit (orc)"
1351 static bool vault_aux_orc(int r_idx)
1353 monster_race *r_ptr = &r_info[r_idx];
1355 /* Validate the monster */
1356 if (!vault_monster_okay(r_idx)) return (FALSE);
1359 if (!(r_ptr->flags3 & RF3_ORC)) return (FALSE);
1361 /* Decline undead */
1362 if (r_ptr->flags3 & RF3_UNDEAD) return (FALSE);
1370 * Helper function for "monster pit (troll)"
1372 static bool vault_aux_troll(int r_idx)
1374 monster_race *r_ptr = &r_info[r_idx];
1376 /* Validate the monster */
1377 if (!vault_monster_okay(r_idx)) return (FALSE);
1380 if (!(r_ptr->flags3 & RF3_TROLL)) return (FALSE);
1382 /* Decline undead */
1383 if (r_ptr->flags3 & RF3_UNDEAD) return (FALSE);
1391 * Helper function for "monster pit (giant)"
1393 static bool vault_aux_giant(int r_idx)
1395 monster_race *r_ptr = &r_info[r_idx];
1397 /* Validate the monster */
1398 if (!vault_monster_okay(r_idx)) return (FALSE);
1401 if (!(r_ptr->flags3 & RF3_GIANT)) return (FALSE);
1403 if (r_ptr->flags3 & RF3_GOOD) return (FALSE);
1405 /* Decline undead */
1406 if (r_ptr->flags3 & RF3_UNDEAD) return (FALSE);
1414 * Helper function for "monster pit (dragon)"
1416 static bool vault_aux_dragon(int r_idx)
1418 monster_race *r_ptr = &r_info[r_idx];
1420 /* Validate the monster */
1421 if (!vault_monster_okay(r_idx)) return (FALSE);
1423 /* Require dragon */
1424 if (!(r_ptr->flags3 & RF3_DRAGON)) return (FALSE);
1426 /* Hack -- Require correct "breath attack" */
1427 if (r_ptr->flags4 != vault_aux_dragon_mask4) return (FALSE);
1429 /* Decline undead */
1430 if (r_ptr->flags3 & RF3_UNDEAD) return (FALSE);
1438 * Helper function for "monster pit (demon)"
1440 static bool vault_aux_demon(int r_idx)
1442 monster_race *r_ptr = &r_info[r_idx];
1444 /* Validate the monster */
1445 if (!vault_monster_okay(r_idx)) return (FALSE);
1447 if (r_ptr->flags2 & (RF2_KILL_BODY)) return (FALSE);
1450 if (!(r_ptr->flags3 & RF3_DEMON)) return (FALSE);
1458 * Helper function for "monster pit (lovecraftian)"
1460 static bool vault_aux_cthulhu(int r_idx)
1462 monster_race *r_ptr = &r_info[r_idx];
1464 /* Validate the monster */
1465 if (!vault_monster_okay(r_idx)) return (FALSE);
1467 if (r_ptr->flags2 & (RF2_KILL_BODY)) return (FALSE);
1469 /* Require eldritch horror */
1470 if (!(r_ptr->flags2 & (RF2_ELDRITCH_HORROR))) return (FALSE);
1478 * Helper function for "monster pit (clone)"
1480 static void vault_prep_clone(void)
1482 /* Apply the monster restriction */
1483 get_mon_num_prep(vault_aux_simple, NULL);
1485 /* Pick a race to clone */
1486 vault_aux_race = get_mon_num(dun_level + 10);
1488 /* Remove the monster restriction */
1489 get_mon_num_prep(NULL, NULL);
1494 * Helper function for "monster pit (symbol clone)"
1496 static void vault_prep_symbol(void)
1500 /* Apply the monster restriction */
1501 get_mon_num_prep(vault_aux_simple, NULL);
1503 /* Pick a race to clone */
1504 r_idx = get_mon_num(dun_level + 10);
1506 /* Remove the monster restriction */
1507 get_mon_num_prep(NULL, NULL);
1509 /* Extract the symbol */
1510 vault_aux_char = r_info[r_idx].d_char;
1515 * Helper function for "monster pit (dragon)"
1517 static void vault_prep_dragon(void)
1519 /* Pick dragon type */
1520 switch (randint0(6))
1525 /* Restrict dragon breath type */
1526 vault_aux_dragon_mask4 = RF4_BR_ACID;
1535 /* Restrict dragon breath type */
1536 vault_aux_dragon_mask4 = RF4_BR_ELEC;
1545 /* Restrict dragon breath type */
1546 vault_aux_dragon_mask4 = RF4_BR_FIRE;
1555 /* Restrict dragon breath type */
1556 vault_aux_dragon_mask4 = RF4_BR_COLD;
1565 /* Restrict dragon breath type */
1566 vault_aux_dragon_mask4 = RF4_BR_POIS;
1575 /* Restrict dragon breath type */
1576 vault_aux_dragon_mask4 = (RF4_BR_ACID | RF4_BR_ELEC |
1577 RF4_BR_FIRE | RF4_BR_COLD |
1590 typedef struct vault_aux_type vault_aux_type;
1593 struct vault_aux_type
1596 bool (*hook_func)(int r_idx);
1597 void (*prep_func)(void);
1603 static vault_aux_type *pick_vault_type(vault_aux_type *l_ptr, int room)
1605 int tmp, total, count;
1607 vault_aux_type *n_ptr;
1609 /* Calculate the total possibilities */
1610 for (n_ptr = l_ptr, total = 0, count = 0; TRUE; n_ptr++, count++)
1613 if (!n_ptr->name) break;
1615 /* Ignore excessive depth */
1616 if (n_ptr->level > dun_level) continue;
1618 if (room == ROOM_PIT)
1620 if (!(d_info[dungeon_type].pit & (1L << count))) continue;
1622 else if (room == ROOM_NEST)
1624 if(!(d_info[dungeon_type].nest & (1L << count))) continue;
1627 /* Count this possibility */
1628 total += n_ptr->chance * MAX_DEPTH / (MIN(dun_level, MAX_DEPTH - 1) - n_ptr->level + 5);
1631 /* Pick a random type */
1632 tmp = randint0(total);
1634 /* Find this type */
1635 for (n_ptr = l_ptr, total = 0, count = 0; TRUE; n_ptr++, count++)
1638 if (!n_ptr->name) break;
1640 /* Ignore excessive depth */
1641 if (n_ptr->level > dun_level) continue;
1643 if (room == ROOM_PIT)
1645 if (!(d_info[dungeon_type].pit & (1L << count))) continue;
1647 else if (room == ROOM_NEST)
1649 if(!(d_info[dungeon_type].nest & (1L << count))) continue;
1652 /* Count this possibility */
1653 total += n_ptr->chance * MAX_DEPTH / (MIN(dun_level, MAX_DEPTH - 1) - n_ptr->level + 5);
1655 /* Found the type */
1656 if (tmp < total) break;
1659 return (n_ptr->name ? n_ptr : NULL);
1662 static void build_type6(int by0, int bx0, bool nest);
1663 static void build_type5(int by0, int bx0, bool nest);
1665 static vault_aux_type nest_types[] =
1668 {"¥¯¥í¡¼¥ó", vault_aux_clone, vault_prep_clone, 5, 3},
1669 {"¥¼¥ê¡¼", vault_aux_jelly, NULL, 5, 6},
1670 {"¥·¥ó¥Ü¥ë(Á±)",vault_aux_symbol_g, vault_prep_symbol, 25, 2},
1671 {"¥·¥ó¥Ü¥ë(°)",vault_aux_symbol_e, vault_prep_symbol, 25, 2},
1672 {"¥ß¥ß¥Ã¥¯", vault_aux_mimic, NULL, 30, 4},
1673 {"¶¸µ¤", vault_aux_cthulhu, NULL, 70, 2},
1674 {"¸¤¾®²°", vault_aux_kennel, NULL, 45, 4},
1675 {"ưʪ±à", vault_aux_animal, NULL, 35, 5},
1676 {"¶µ²ñ", vault_aux_chapel_g, NULL, 75, 4},
1677 {"¥¢¥ó¥Ç¥Ã¥É", vault_aux_undead, NULL, 75, 5},
1678 {NULL, NULL, NULL, 0, 0},
1680 {"clone", vault_aux_clone, vault_prep_clone, 7, 3},
1681 {"jelly", vault_aux_jelly, NULL, 7, 6},
1682 {"symbol good",vault_aux_symbol_g, vault_prep_symbol, 25, 2},
1683 {"symbol evil",vault_aux_symbol_e, vault_prep_symbol, 25, 2},
1684 {"mimic", vault_aux_mimic, NULL, 45, 6},
1685 {"lovecraftian",vault_aux_cthulhu, NULL, 80, 2},
1686 {"kennel", vault_aux_kennel, NULL, 50, 2},
1687 {"animal", vault_aux_animal, NULL, 50, 4},
1688 {"chapel", vault_aux_chapel_g, NULL, 90, 2},
1689 {"undead", vault_aux_undead, NULL, 90, 4},
1690 {NULL, NULL, NULL, 0, 0},
1696 * Type 5 -- Monster nests
1698 * A monster nest is a "big" room, with an "inner" room, containing
1699 * a "collection" of monsters of a given type strewn about the room.
1701 * The monsters are chosen from a set of 64 randomly selected monster
1702 * races, to allow the nest creation to fail instead of having "holes".
1704 * Note the use of the "get_mon_num_prep()" function, and the special
1705 * "get_mon_num_hook()" restriction function, to prepare the "monster
1706 * allocation table" in such a way as to optimize the selection of
1707 * "appropriate" non-unique monsters for the nest.
1709 * Note that the "get_mon_num()" function may (rarely) fail, in which
1710 * case the nest will be empty, and will not affect the level rating.
1712 * Note that "monster nests" will never contain "unique" monsters.
1714 static void build_type5(int by0, int bx0, bool pit)
1716 int y, x, y1, x1, y2, x2, xval, yval;
1724 vault_aux_type *n_ptr = pick_vault_type(nest_types, ROOM_NEST);
1726 /* Try to allocate space for room. */
1727 if (!room_alloc(25, 11, TRUE, by0, bx0, &xval, &yval)) return;
1729 /* No type available */
1733 else {build_type6(by0, bx0, TRUE);return;}
1736 /* Process a preparation function if necessary */
1737 if (n_ptr->prep_func) (*(n_ptr->prep_func))();
1745 /* Place the floor area */
1746 for (y = y1 - 1; y <= y2 + 1; y++)
1748 for (x = x1 - 1; x <= x2 + 1; x++)
1750 c_ptr = &cave[y][x];
1751 place_floor_grid(c_ptr);
1752 c_ptr->info |= (CAVE_ROOM);
1756 /* Place the outer walls */
1757 for (y = y1 - 1; y <= y2 + 1; y++)
1759 c_ptr = &cave[y][x1 - 1];
1760 place_outer_grid(c_ptr);
1761 c_ptr = &cave[y][x2 + 1];
1762 place_outer_grid(c_ptr);
1764 for (x = x1 - 1; x <= x2 + 1; x++)
1766 c_ptr = &cave[y1 - 1][x];
1767 place_outer_grid(c_ptr);
1768 c_ptr = &cave[y2 + 1][x];
1769 place_outer_grid(c_ptr);
1773 /* Advance to the center room */
1779 /* The inner walls */
1780 for (y = y1 - 1; y <= y2 + 1; y++)
1782 c_ptr = &cave[y][x1 - 1];
1783 place_inner_grid(c_ptr);
1784 c_ptr = &cave[y][x2 + 1];
1785 place_inner_grid(c_ptr);
1788 for (x = x1 - 1; x <= x2 + 1; x++)
1790 c_ptr = &cave[y1 - 1][x];
1791 place_inner_grid(c_ptr);
1792 c_ptr = &cave[y2 + 1][x];
1793 place_inner_grid(c_ptr);
1795 for (y = y1; y <= y2; y++)
1797 for (x = x1; x <= x2; x++)
1799 add_cave_info(y, x, CAVE_ICKY);
1804 /* Place a secret door */
1805 switch (randint1(4))
1807 case 1: place_secret_door(y1 - 1, xval); break;
1808 case 2: place_secret_door(y2 + 1, xval); break;
1809 case 3: place_secret_door(yval, x1 - 1); break;
1810 case 4: place_secret_door(yval, x2 + 1); break;
1814 /* Prepare allocation table */
1815 get_mon_num_prep(n_ptr->hook_func, NULL);
1817 /* Pick some monster types */
1818 for (i = 0; i < 64; i++)
1820 int r_idx = 0, attempts = 100;
1824 /* Get a (hard) monster type */
1825 r_idx = get_mon_num(dun_level + 10);
1827 /* Decline incorrect alignment */
1828 if (((align < 0) && (r_info[r_idx].flags3 & RF3_GOOD)) ||
1829 ((align > 0) && (r_info[r_idx].flags3 & RF3_EVIL)))
1834 /* Accept this monster */
1838 /* Notice failure */
1839 if (!r_idx || !attempts) return;
1841 /* Note the alignment */
1842 if (r_info[r_idx].flags3 & RF3_GOOD) align++;
1843 else if (r_info[r_idx].flags3 & RF3_EVIL) align--;
1853 msg_format("¥â¥ó¥¹¥¿¡¼Éô²°(%s)", n_ptr->name);
1855 msg_format("Monster nest (%s)", n_ptr->name);
1861 /* Increase the level rating */
1864 /* (Sometimes) Cause a "special feeling" (for "Monster Nests") */
1865 if ((dun_level <= 40) && (randint1(dun_level * dun_level + 50) < 300))
1867 good_item_flag = TRUE;
1870 /* Place some monsters */
1871 for (y = yval - 2; y <= yval + 2; y++)
1873 for (x = xval - 9; x <= xval + 9; x++)
1875 int r_idx = what[randint0(64)];
1877 /* Place that "random" monster (no groups) */
1878 (void)place_monster_aux(0, y, x, r_idx, 0L);
1884 static vault_aux_type pit_types[] =
1887 {"¥ª¡¼¥¯", vault_aux_orc, NULL, 5, 6},
1888 {"¥È¥í¥ë", vault_aux_troll, NULL, 20, 6},
1889 {"¥¸¥ã¥¤¥¢¥ó¥È",vault_aux_giant, NULL, 50, 6},
1890 {"¶¸µ¤", vault_aux_cthulhu, NULL, 80, 2},
1891 {"¥·¥ó¥Ü¥ë(Á±)",vault_aux_symbol_g, vault_prep_symbol, 70, 1},
1892 {"¥·¥ó¥Ü¥ë(°)",vault_aux_symbol_e, vault_prep_symbol, 70, 1},
1893 {"¶µ²ñ", vault_aux_chapel_g, NULL, 65, 2},
1894 {"¥É¥é¥´¥ó", vault_aux_dragon, vault_prep_dragon, 70, 6},
1895 {"¥Ç¡¼¥â¥ó", vault_aux_demon, NULL, 80, 6},
1896 {NULL, NULL, NULL, 0, 0},
1898 {"orc", vault_aux_orc, NULL, 7, 4},
1899 {"troll", vault_aux_troll, NULL, 35, 4},
1900 {"giant", vault_aux_giant, NULL, 70, 4},
1901 {"lovecraftian",vault_aux_cthulhu, NULL, 90, 4},
1902 {"symbol good",vault_aux_symbol_g, vault_prep_symbol, 25, 2},
1903 {"symbol evil",vault_aux_symbol_e, vault_prep_symbol, 25, 2},
1904 {"chapel", vault_aux_chapel_g, NULL, 85, 1},
1905 {"dragon", vault_aux_dragon, vault_prep_dragon, 80, 4},
1906 {"demon", vault_aux_demon, NULL, 90, 4},
1907 {NULL, NULL, NULL, 0, 0},
1913 * Type 6 -- Monster pits
1915 * A monster pit is a "big" room, with an "inner" room, containing
1916 * a "collection" of monsters of a given type organized in the room.
1918 * The inside room in a monster pit appears as shown below, where the
1919 * actual monsters in each location depend on the type of the pit
1921 * #####################
1922 * #0000000000000000000#
1923 * #0112233455543322110#
1924 * #0112233467643322110#
1925 * #0112233455543322110#
1926 * #0000000000000000000#
1927 * #####################
1929 * Note that the monsters in the pit are now chosen by using "get_mon_num()"
1930 * to request 16 "appropriate" monsters, sorting them by level, and using
1931 * the "even" entries in this sorted list for the contents of the pit.
1933 * Hack -- all of the "dragons" in a "dragon" pit must be the same "color",
1934 * which is handled by requiring a specific "breath" attack for all of the
1935 * dragons. This may include "multi-hued" breath. Note that "wyrms" may
1936 * be present in many of the dragon pits, if they have the proper breath.
1938 * Note the use of the "get_mon_num_prep()" function, and the special
1939 * "get_mon_num_hook()" restriction function, to prepare the "monster
1940 * allocation table" in such a way as to optimize the selection of
1941 * "appropriate" non-unique monsters for the pit.
1943 * Note that the "get_mon_num()" function may (rarely) fail, in which case
1944 * the pit will be empty, and will not effect the level rating.
1946 * Note that "monster pits" will never contain "unique" monsters.
1948 static void build_type6(int by0, int bx0, bool nest)
1950 int y, x, y1, x1, y2, x2, xval, yval;
1959 vault_aux_type *n_ptr = pick_vault_type(pit_types, ROOM_PIT);
1961 /* Try to allocate space for room. */
1962 if (!room_alloc(25, 11, TRUE, by0, bx0, &xval, &yval)) return;
1964 /* No type available */
1968 else {build_type5(by0, bx0, TRUE);return;}
1971 /* Process a preparation function if necessary */
1972 if (n_ptr->prep_func) (*(n_ptr->prep_func))();
1980 /* Place the floor area */
1981 for (y = y1 - 1; y <= y2 + 1; y++)
1983 for (x = x1 - 1; x <= x2 + 1; x++)
1985 c_ptr = &cave[y][x];
1986 place_floor_grid(c_ptr);
1987 c_ptr->info |= (CAVE_ROOM);
1991 /* Place the outer walls */
1992 for (y = y1 - 1; y <= y2 + 1; y++)
1994 c_ptr = &cave[y][x1 - 1];
1995 place_outer_grid(c_ptr);
1996 c_ptr = &cave[y][x2 + 1];
1997 place_outer_grid(c_ptr);
1999 for (x = x1 - 1; x <= x2 + 1; x++)
2001 c_ptr = &cave[y1 - 1][x];
2002 place_outer_grid(c_ptr);
2003 c_ptr = &cave[y2 + 1][x];
2004 place_outer_grid(c_ptr);
2007 /* Advance to the center room */
2013 /* The inner walls */
2014 for (y = y1 - 1; y <= y2 + 1; y++)
2016 c_ptr = &cave[y][x1 - 1];
2017 place_inner_grid(c_ptr);
2018 c_ptr = &cave[y][x2 + 1];
2019 place_inner_grid(c_ptr);
2021 for (x = x1 - 1; x <= x2 + 1; x++)
2023 c_ptr = &cave[y1 - 1][x];
2024 place_inner_grid(c_ptr);
2025 c_ptr = &cave[y2 + 1][x];
2026 place_inner_grid(c_ptr);
2028 for (y = y1; y <= y2; y++)
2030 for (x = x1; x <= x2; x++)
2032 add_cave_info(y, x, CAVE_ICKY);
2036 /* Place a secret door */
2037 switch (randint1(4))
2039 case 1: place_secret_door(y1 - 1, xval); break;
2040 case 2: place_secret_door(y2 + 1, xval); break;
2041 case 3: place_secret_door(yval, x1 - 1); break;
2042 case 4: place_secret_door(yval, x2 + 1); break;
2046 /* Prepare allocation table */
2047 get_mon_num_prep(n_ptr->hook_func, NULL);
2049 /* Pick some monster types */
2050 for (i = 0; i < 16; i++)
2052 int r_idx = 0, attempts = 100;
2056 /* Get a (hard) monster type */
2057 r_idx = get_mon_num(dun_level + 10);
2059 /* Decline incorrect alignment */
2060 if (((align < 0) && (r_info[r_idx].flags3 & RF3_GOOD)) ||
2061 ((align > 0) && (r_info[r_idx].flags3 & RF3_EVIL)))
2066 /* Accept this monster */
2070 /* Notice failure */
2071 if (!r_idx || !attempts) return;
2073 /* Note the alignment */
2074 if (r_info[r_idx].flags3 & RF3_GOOD) align++;
2075 else if (r_info[r_idx].flags3 & RF3_EVIL) align--;
2080 /* Sort the entries */
2081 for (i = 0; i < 16 - 1; i++)
2083 /* Sort the entries */
2084 for (j = 0; j < 16 - 1; j++)
2089 int p1 = r_info[what[i1]].level;
2090 int p2 = r_info[what[i2]].level;
2096 what[i1] = what[i2];
2106 msg_format("%s¤ÎÁã", n_ptr->name);
2109 msg_format("Monster pit (%s)", n_ptr->name);
2113 /* Select the entries */
2114 for (i = 0; i < 8; i++)
2116 /* Every other entry */
2117 what[i] = what[i * 2];
2122 msg_print(r_name + r_info[what[i]].name);
2126 /* Increase the level rating */
2129 /* (Sometimes) Cause a "special feeling" (for "Monster Pits") */
2130 if ((dun_level <= 40) && (randint1(dun_level * dun_level + 50) < 300))
2132 good_item_flag = TRUE;
2135 /* Top and bottom rows */
2136 for (x = xval - 9; x <= xval + 9; x++)
2138 place_monster_aux(0, yval - 2, x, what[0], PM_NO_KAGE);
2139 place_monster_aux(0, yval + 2, x, what[0], PM_NO_KAGE);
2142 /* Middle columns */
2143 for (y = yval - 1; y <= yval + 1; y++)
2145 place_monster_aux(0, y, xval - 9, what[0], PM_NO_KAGE);
2146 place_monster_aux(0, y, xval + 9, what[0], PM_NO_KAGE);
2148 place_monster_aux(0, y, xval - 8, what[1], PM_NO_KAGE);
2149 place_monster_aux(0, y, xval + 8, what[1], PM_NO_KAGE);
2151 place_monster_aux(0, y, xval - 7, what[1], PM_NO_KAGE);
2152 place_monster_aux(0, y, xval + 7, what[1], PM_NO_KAGE);
2154 place_monster_aux(0, y, xval - 6, what[2], PM_NO_KAGE);
2155 place_monster_aux(0, y, xval + 6, what[2], PM_NO_KAGE);
2157 place_monster_aux(0, y, xval - 5, what[2], PM_NO_KAGE);
2158 place_monster_aux(0, y, xval + 5, what[2], PM_NO_KAGE);
2160 place_monster_aux(0, y, xval - 4, what[3], PM_NO_KAGE);
2161 place_monster_aux(0, y, xval + 4, what[3], PM_NO_KAGE);
2163 place_monster_aux(0, y, xval - 3, what[3], PM_NO_KAGE);
2164 place_monster_aux(0, y, xval + 3, what[3], PM_NO_KAGE);
2166 place_monster_aux(0, y, xval - 2, what[4], PM_NO_KAGE);
2167 place_monster_aux(0, y, xval + 2, what[4], PM_NO_KAGE);
2170 /* Above/Below the center monster */
2171 for (x = xval - 1; x <= xval + 1; x++)
2173 place_monster_aux(0, yval + 1, x, what[5], PM_NO_KAGE);
2174 place_monster_aux(0, yval - 1, x, what[5], PM_NO_KAGE);
2177 /* Next to the center monster */
2178 place_monster_aux(0, yval, xval + 1, what[6], PM_NO_KAGE);
2179 place_monster_aux(0, yval, xval - 1, what[6], PM_NO_KAGE);
2181 /* Center monster */
2182 place_monster_aux(0, yval, xval, what[7], PM_NO_KAGE);
2186 /* coordinate translation code */
2187 static void coord_trans(int *x, int *y, int xoffset, int yoffset, int transno)
2193 * transno specifies what transformation is required. (0-7)
2194 * The lower two bits indicate by how much the vault is rotated,
2195 * and the upper bit indicates a reflection.
2196 * This is done by using rotation matrices... however since
2197 * these are mostly zeros for rotations by 90 degrees this can
2198 * be expressed simply in terms of swapping and inverting the
2199 * x and y coordinates.
2201 for (i = 0; i <= transno % 4; i++)
2203 /* rotate by 90 degrees */
2211 /* Reflect depending on status of 3rd bit. */
2215 /* Add offsets so vault stays in the first quadrant */
2222 * Hack -- fill in "vault" rooms
2224 static void build_vault(int yval, int xval, int ymax, int xmax, cptr data,
2225 int xoffset, int yoffset, int transno)
2227 int dx, dy, x, y, i, j;
2234 /* Place dungeon features and objects */
2235 for (t = data, dy = 0; dy < ymax; dy++)
2237 for (dx = 0; dx < xmax; dx++, t++)
2239 /* prevent loop counter from being overwritten */
2244 coord_trans(&i, &j, xoffset, yoffset, transno);
2246 /* Extract the location */
2249 /* no swap of x/y */
2250 x = xval - (xmax / 2) + i;
2251 y = yval - (ymax / 2) + j;
2256 x = xval - (ymax / 2) + i;
2257 y = yval - (xmax / 2) + j;
2260 /* Hack -- skip "non-grids" */
2261 if (*t == ' ') continue;
2263 /* Access the grid */
2264 c_ptr = &cave[y][x];
2266 /* Lay down a floor */
2267 place_floor_grid(c_ptr);
2269 /* Part of a vault */
2270 c_ptr->info |= (CAVE_ROOM | CAVE_ICKY);
2272 /* Analyze the grid */
2275 /* Granite wall (outer) */
2277 place_outer_noperm_grid(c_ptr);
2280 /* Granite wall (inner) */
2282 place_inner_grid(c_ptr);
2285 /* Permanent wall (inner) */
2287 c_ptr->feat = FEAT_PERM_INNER;
2288 c_ptr->info &= ~(CAVE_MASK);
2289 c_ptr->info |= CAVE_INNER;
2294 if (randint0(100) < 75)
2296 place_object(y, x, FALSE, FALSE);
2306 place_secret_door(y, x);
2318 /* Place dungeon monsters and objects */
2319 for (t = data, dy = 0; dy < ymax; dy++)
2321 for (dx = 0; dx < xmax; dx++, t++)
2323 /* prevent loop counter from being overwritten */
2328 coord_trans(&i, &j, xoffset, yoffset, transno);
2330 /* Extract the location */
2333 /* no swap of x/y */
2334 x = xval - (xmax / 2) + i;
2335 y = yval - (ymax / 2) + j;
2340 x = xval - (ymax / 2) + i;
2341 y = yval - (xmax / 2) + j;
2344 /* Hack -- skip "non-grids" */
2345 if (*t == ' ') continue;
2347 /* Analyze the symbol */
2353 monster_level = base_level + 5;
2354 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
2355 monster_level = base_level;
2359 /* Meaner monster */
2362 monster_level = base_level + 11;
2363 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
2364 monster_level = base_level;
2368 /* Meaner monster, plus treasure */
2371 monster_level = base_level + 9;
2372 place_monster(y, x, PM_ALLOW_SLEEP);
2373 monster_level = base_level;
2374 object_level = base_level + 7;
2375 place_object(y, x, TRUE, FALSE);
2376 object_level = base_level;
2380 /* Nasty monster and treasure */
2383 monster_level = base_level + 40;
2384 place_monster(y, x, PM_ALLOW_SLEEP);
2385 monster_level = base_level;
2386 object_level = base_level + 20;
2387 place_object(y, x, TRUE, TRUE);
2388 object_level = base_level;
2392 /* Monster and/or object */
2395 if (randint0(100) < 50)
2397 monster_level = base_level + 3;
2398 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
2399 monster_level = base_level;
2401 if (randint0(100) < 50)
2403 object_level = base_level + 7;
2404 place_object(y, x, FALSE, FALSE);
2405 object_level = base_level;
2411 cave_set_feat(y, x, FEAT_SHOP_HEAD + STORE_BLACK);
2412 store_init(NO_TOWN, STORE_BLACK);
2416 cave_set_feat(y, x, FEAT_PATTERN_START);
2420 cave_set_feat(y, x, FEAT_PATTERN_1);
2424 cave_set_feat(y, x, FEAT_PATTERN_2);
2428 cave_set_feat(y, x, FEAT_PATTERN_3);
2432 cave_set_feat(y, x, FEAT_PATTERN_4);
2436 cave_set_feat(y, x, FEAT_PATTERN_END);
2440 cave_set_feat(y, x, FEAT_PATTERN_XTRA1);
2445 object_level = base_level + 12;
2446 place_object(y, x, TRUE, FALSE);
2447 object_level = base_level;
2457 * Type 7 -- simple vaults (see "v_info.txt")
2459 static void build_type7(int by0, int bx0)
2461 vault_type *v_ptr = NULL;
2465 int xoffset, yoffset;
2468 /* Pick a lesser vault */
2469 while (dummy < SAFE_MAX_ATTEMPTS)
2473 /* Access a random vault record */
2474 v_ptr = &v_info[randint0(max_v_idx)];
2476 /* Accept the first lesser vault */
2477 if (v_ptr->typ == 7) break;
2480 /* No lesser vault found */
2483 /* pick type of transformation (0-7) */
2484 transno = randint0(8);
2486 /* calculate offsets */
2490 coord_trans(&x, &y, 0, 0, transno);
2510 /* Try to allocate space for room. */
2511 if (!room_alloc(abs(x), abs(y), FALSE, by0, bx0, &xval, &yval)) return;
2513 if (dummy >= SAFE_MAX_ATTEMPTS)
2518 msg_print("·Ù¹ð¡ª¾®¤µ¤ÊÃϲ¼¼¼¤òÇÛÃ֤Ǥ¤Þ¤»¤ó¡ª");
2520 msg_print("Warning! Could not place lesser vault!");
2533 if (cheat_room) msg_format("%s", v_name + v_ptr->name);
2535 /* Boost the rating */
2536 rating += v_ptr->rat;
2538 /* (Sometimes) Cause a special feeling */
2539 if ((dun_level <= 50) ||
2540 (randint1((dun_level - 40) * (dun_level - 40) + 50) < 400))
2542 good_item_flag = TRUE;
2545 /* Hack -- Build the vault */
2546 build_vault(yval, xval, v_ptr->hgt, v_ptr->wid,
2547 v_text + v_ptr->text, xoffset, yoffset, transno);
2552 * Type 8 -- greater vaults (see "v_info.txt")
2554 static void build_type8(int by0, int bx0)
2556 vault_type *v_ptr = NULL;
2561 int xoffset, yoffset;
2563 /* Pick a greater vault */
2564 while (dummy < SAFE_MAX_ATTEMPTS)
2568 /* Access a random vault record */
2569 v_ptr = &v_info[randint0(max_v_idx)];
2571 /* Accept the first greater vault */
2572 if (v_ptr->typ == 8) break;
2575 /* No greater vault found */
2578 /* pick type of transformation (0-7) */
2579 transno = randint0(8);
2581 /* calculate offsets */
2585 coord_trans(&x, &y, 0, 0, transno);
2605 /* Try to allocate space for room. If fails, exit */
2606 if (!room_alloc(abs(x), abs(y), FALSE, by0, bx0, &xval, &yval)) return;
2608 if (dummy >= SAFE_MAX_ATTEMPTS)
2613 msg_print("·Ù¹ð¡ªµðÂç¤ÊÃϲ¼¼¼¤òÇÛÃ֤Ǥ¤Þ¤»¤ó¡ª");
2615 msg_print("Warning! Could not place greater vault!");
2624 v_ptr = &v_info[76 + randint1(3)];
2628 if (cheat_room) msg_format("%s", v_name + v_ptr->name);
2630 /* Boost the rating */
2631 rating += v_ptr->rat;
2633 /* (Sometimes) Cause a special feeling */
2634 if ((dun_level <= 50) ||
2635 (randint1((dun_level - 40) * (dun_level - 40) + 50) < 400))
2637 good_item_flag = TRUE;
2640 /* Hack -- Build the vault */
2641 build_vault(yval, xval, v_ptr->hgt, v_ptr->wid,
2642 v_text + v_ptr->text, xoffset, yoffset, transno);
2646 * Structure to hold all "fill" data
2649 typedef struct fill_data_type fill_data_type;
2651 struct fill_data_type
2664 /* features to fill with */
2673 /* number of filled squares */
2677 static fill_data_type fill_data;
2680 /* Store routine for the fractal cave generator */
2681 /* this routine probably should be an inline function or a macro. */
2682 static void store_height(int x, int y, int val)
2684 /* if on boundary set val > cutoff so walls are not as square */
2685 if (((x == fill_data.xmin) || (y == fill_data.ymin) ||
2686 (x == fill_data.xmax) || (y == fill_data.ymax)) &&
2687 (val <= fill_data.c1)) val = fill_data.c1 + 1;
2689 /* store the value in height-map format */
2690 cave[y][x].feat = val;
2697 * Explanation of the plasma fractal algorithm:
2699 * A grid of points is created with the properties of a 'height-map'
2700 * This is done by making the corners of the grid have a random value.
2701 * The grid is then subdivided into one with twice the resolution.
2702 * The new points midway between two 'known' points can be calculated
2703 * by taking the average value of the 'known' ones and randomly adding
2704 * or subtracting an amount proportional to the distance between those
2705 * points. The final 'middle' points of the grid are then calculated
2706 * by averaging all four of the originally 'known' corner points. An
2707 * random amount is added or subtracted from this to get a value of the
2708 * height at that point. The scaling factor here is adjusted to the
2709 * slightly larger distance diagonally as compared to orthogonally.
2711 * This is then repeated recursively to fill an entire 'height-map'
2712 * A rectangular map is done the same way, except there are different
2713 * scaling factors along the x and y directions.
2715 * A hack to change the amount of correlation between points is done using
2716 * the grd variable. If the current step size is greater than grd then
2717 * the point will be random, otherwise it will be calculated by the
2718 * above algorithm. This makes a maximum distance at which two points on
2719 * the height map can affect each other.
2721 * How fractal caves are made:
2723 * When the map is complete, a cut-off value is used to create a cave.
2724 * Heights below this value are "floor", and heights above are "wall".
2725 * This also can be used to create lakes, by adding more height levels
2726 * representing shallow and deep water/ lava etc.
2728 * The grd variable affects the width of passages.
2729 * The roug variable affects the roughness of those passages
2731 * The tricky part is making sure the created cave is connected. This
2732 * is done by 'filling' from the inside and only keeping the 'filled'
2733 * floor. Walls bounding the 'filled' floor are also kept. Everything
2734 * else is converted to the normal granite FEAT_WALL_EXTRA.
2739 * Note that this uses the cave.feat array in a very hackish way
2740 * the values are first set to zero, and then each array location
2741 * is used as a "heightmap"
2742 * The heightmap then needs to be converted back into the "feat" format.
2744 * grd=level at which fractal turns on. smaller gives more mazelike caves
2745 * roug=roughness level. 16=normal. higher values make things more convoluted
2746 * small values are good for smooth walls.
2747 * size=length of the side of the square cave system.
2749 static void generate_hmap(int y0, int x0, int xsiz, int ysiz, int grd, int roug, int cutoff)
2751 int xhsize, yhsize, xsize, ysize, maxsize;
2754 * fixed point variables- these are stored as 256 x normal value
2755 * this gives 8 binary places of fractional part + 8 places of normal part
2758 u16b xstep, xhstep, ystep, yhstep;
2759 u16b xstep2, xhstep2, ystep2, yhstep2;
2760 u16b i, j, ii, jj, diagsize, xxsize, yysize;
2762 /* Cache for speed */
2763 u16b xm, xp, ym, yp;
2765 /* redefine size so can change the value if out of range */
2769 /* Paranoia about size of the system of caves */
2770 if (xsize > 254) xsize = 254;
2771 if (xsize < 4) xsize = 4;
2772 if (ysize > 254) ysize = 254;
2773 if (ysize < 4) ysize = 4;
2775 /* get offsets to middle of array */
2779 /* fix rounding problem */
2783 /* get limits of region */
2784 fill_data.xmin = x0 - xhsize;
2785 fill_data.ymin = y0 - yhsize;
2786 fill_data.xmax = x0 + xhsize;
2787 fill_data.ymax = y0 + yhsize;
2789 /* Store cutoff in global for quick access */
2790 fill_data.c1 = cutoff;
2793 * Scale factor for middle points:
2794 * About sqrt(2) * 256 - correct for a square lattice
2795 * approximately correct for everything else.
2799 /* maximum of xsize and ysize */
2800 maxsize = (xsize > ysize) ? xsize : ysize;
2802 /* Clear the section */
2803 for (i = 0; i <= xsize; i++)
2805 for (j = 0; j <= ysize; j++)
2807 /* 255 is a flag for "not done yet" */
2808 cave[(int)(fill_data.ymin + j)][(int)(fill_data.xmin + i)].feat = 255;
2809 /* Clear icky flag because may be redoing the cave */
2810 cave[(int)(fill_data.ymin + j)][(int)(fill_data.xmin + i)].info &= ~(CAVE_ICKY);
2814 /* Boundaries are walls */
2815 cave[fill_data.ymin][fill_data.xmin].feat = maxsize;
2816 cave[fill_data.ymax][fill_data.xmin].feat = maxsize;
2817 cave[fill_data.ymin][fill_data.xmax].feat = maxsize;
2818 cave[fill_data.ymax][fill_data.xmax].feat = maxsize;
2820 /* Set the middle square to be an open area. */
2821 cave[y0][x0].feat = 0;
2823 /* Initialize the step sizes */
2824 xstep = xhstep = xsize * 256;
2825 ystep = yhstep = ysize * 256;
2826 xxsize = xsize * 256;
2827 yysize = ysize * 256;
2830 * Fill in the rectangle with fractal height data -
2831 * like the 'plasma fractal' in fractint.
2833 while ((xhstep > 256) || (yhstep > 256))
2835 /* Halve the step sizes */
2841 /* cache well used values */
2842 xstep2 = xstep / 256;
2843 ystep2 = ystep / 256;
2845 xhstep2 = xhstep / 256;
2846 yhstep2 = yhstep / 256;
2848 /* middle top to bottom. */
2849 for (i = xhstep; i <= xxsize - xhstep; i += xstep)
2851 for (j = 0; j <= yysize; j += ystep)
2853 /* cache often used values */
2854 ii = i / 256 + fill_data.xmin;
2855 jj = j / 256 + fill_data.ymin;
2858 if (cave[jj][ii].feat == 255)
2862 /* If greater than 'grid' level then is random */
2863 store_height(ii, jj, randint1(maxsize));
2867 /* Average of left and right points +random bit */
2868 store_height(ii, jj,
2869 (cave[jj][fill_data.xmin + (i - xhstep) / 256].feat
2870 + cave[jj][fill_data.xmin + (i + xhstep) / 256].feat) / 2
2871 + (randint1(xstep2) - xhstep2) * roug / 16);
2878 /* middle left to right. */
2879 for (j = yhstep; j <= yysize - yhstep; j += ystep)
2881 for (i = 0; i <= xxsize; i += xstep)
2883 /* cache often used values */
2884 ii = i / 256 + fill_data.xmin;
2885 jj = j / 256 + fill_data.ymin;
2888 if (cave[jj][ii].feat == 255)
2892 /* If greater than 'grid' level then is random */
2893 store_height(ii, jj, randint1(maxsize));
2897 /* Average of up and down points +random bit */
2898 store_height(ii, jj,
2899 (cave[fill_data.ymin + (j - yhstep) / 256][ii].feat
2900 + cave[fill_data.ymin + (j + yhstep) / 256][ii].feat) / 2
2901 + (randint1(ystep2) - yhstep2) * roug / 16);
2908 for (i = xhstep; i <= xxsize - xhstep; i += xstep)
2910 for (j = yhstep; j <= yysize - yhstep; j += ystep)
2912 /* cache often used values */
2913 ii = i / 256 + fill_data.xmin;
2914 jj = j / 256 + fill_data.ymin;
2917 if (cave[jj][ii].feat == 255)
2921 /* If greater than 'grid' level then is random */
2922 store_height(ii, jj, randint1(maxsize));
2926 /* Cache reused values. */
2927 xm = fill_data.xmin + (i - xhstep) / 256;
2928 xp = fill_data.xmin + (i + xhstep) / 256;
2929 ym = fill_data.ymin + (j - yhstep) / 256;
2930 yp = fill_data.ymin + (j + yhstep) / 256;
2933 * Average over all four corners + scale by diagsize to
2934 * reduce the effect of the square grid on the shape of the fractal
2936 store_height(ii, jj,
2937 (cave[ym][xm].feat + cave[yp][xm].feat
2938 + cave[ym][xp].feat + cave[yp][xp].feat) / 4
2939 + (randint1(xstep2) - xhstep2) * (diagsize / 16) / 256 * roug);
2948 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)
2951 * function used to convert from height-map back to the
2952 * normal angband cave format
2954 if (cave[y][x].info & CAVE_ICKY)
2961 /* Show that have looked at this square */
2962 cave[y][x].info|= (CAVE_ICKY);
2964 /* Use cutoffs c1-c3 to allocate regions of floor /water/ lava etc. */
2965 if (cave[y][x].feat <= c1)
2967 /* 25% of the time use the other tile : it looks better this way */
2968 if (randint1(100) < 75)
2970 cave[y][x].feat = feat1;
2971 cave[y][x].info &= ~(CAVE_MASK);
2972 cave[y][x].info |= info1;
2977 cave[y][x].feat = feat2;
2978 cave[y][x].info &= ~(CAVE_MASK);
2979 cave[y][x].info |= info2;
2983 else if (cave[y][x].feat <= c2)
2985 /* 25% of the time use the other tile : it looks better this way */
2986 if (randint1(100) < 75)
2988 cave[y][x].feat = feat2;
2989 cave[y][x].info &= ~(CAVE_MASK);
2990 cave[y][x].info |= info2;
2995 cave[y][x].feat = feat1;
2996 cave[y][x].info &= ~(CAVE_MASK);
2997 cave[y][x].info |= info1;
3001 else if (cave[y][x].feat <= c3)
3003 cave[y][x].feat = feat3;
3004 cave[y][x].info |= info3;
3007 /* if greater than cutoff then is a wall */
3010 place_outer_bold(y, x);
3020 * Quick and nasty fill routine used to find the connected region
3021 * of floor in the middle of the cave
3023 static void cave_fill(byte y, byte x)
3032 /*** Start Grid ***/
3034 /* Enqueue that entry */
3039 /* Now process the queue */
3040 while (flow_head != flow_tail)
3042 /* Extract the next entry */
3043 ty = temp_y[flow_head];
3044 tx = temp_x[flow_head];
3046 /* Forget that entry */
3047 if (++flow_head == TEMP_MAX) flow_head = 0;
3049 /* Add the "children" */
3050 for (d = 0; d < 8; d++)
3052 int old_head = flow_tail;
3054 /* Child location */
3055 j = ty + ddy_ddd[d];
3056 i = tx + ddx_ddd[d];
3058 /* Paranoia Don't leave the cave */
3059 if (!in_bounds(j, i))
3061 /* affect boundary */
3062 cave[j][i].info |= CAVE_ICKY;
3066 /* If within bounds */
3067 else if ((i > fill_data.xmin) && (i < fill_data.xmax)
3068 && (j > fill_data.ymin) && (j < fill_data.ymax))
3070 /* If not a wall or floor done before */
3071 if (hack_isnt_wall(j, i,
3072 fill_data.c1, fill_data.c2, fill_data.c3,
3073 fill_data.feat1, fill_data.feat2, fill_data.feat3,
3074 fill_data.info1, fill_data.info2, fill_data.info3))
3076 /* Enqueue that entry */
3077 temp_y[flow_tail] = j;
3078 temp_x[flow_tail] = i;
3080 /* Advance the queue */
3081 if (++flow_tail == TEMP_MAX) flow_tail = 0;
3083 /* Hack -- Overflow by forgetting new entry */
3084 if (flow_tail == flow_head)
3086 flow_tail = old_head;
3090 /* keep tally of size of cave system */
3091 (fill_data.amount)++;
3097 /* affect boundary */
3098 cave[j][i].info |= CAVE_ICKY;
3105 static bool generate_fracave(int y0, int x0, int xsize, int ysize, int cutoff, bool light, bool room)
3107 int x, y, i, xhsize, yhsize;
3110 /* offsets to middle from corner */
3116 * select region connected to center of cave system
3117 * this gets rid of alot of isolated one-sqaures that
3118 * can make teleport traps instadeaths...
3122 fill_data.c1 = cutoff;
3126 /* features to fill with */
3127 fill_data.feat1 = floor_type[randint0(100)];
3128 fill_data.feat2 = floor_type[randint0(100)];
3129 fill_data.feat3 = floor_type[randint0(100)];
3131 fill_data.info1 = CAVE_FLOOR;
3132 fill_data.info2 = CAVE_FLOOR;
3133 fill_data.info3 = CAVE_FLOOR;
3135 /* number of filled squares */
3136 fill_data.amount = 0;
3138 cave_fill((byte)y0, (byte)x0);
3140 /* if tally too small, try again */
3141 if (fill_data.amount < 10)
3143 /* too small - clear area and try again later */
3144 for (x = 0; x <= xsize; ++x)
3146 for (y = 0; y <= ysize; ++y)
3148 place_extra_bold(y0 + y - yhsize, x0 + x - xhsize);
3149 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY | CAVE_ROOM);
3156 * Do boundarys-check to see if they are next to a filled region
3157 * If not then they are set to normal granite
3158 * If so then they are marked as room walls.
3160 for (i = 0; i <= xsize; ++i)
3163 if ((cave[0 + y0 - yhsize][i + x0 - xhsize].info & CAVE_ICKY) && (room))
3165 /* Next to a 'filled' region? - set to be room walls */
3166 place_outer_bold(y0 + 0 - yhsize, x0 + i - xhsize);
3167 if (light) cave[y0 + 0 - yhsize][x0 + i - xhsize].info |= (CAVE_GLOW);
3168 cave[y0 + 0 - yhsize][x0 + i - xhsize].info |= (CAVE_ROOM);
3169 place_outer_bold(y0 + 0 - yhsize, x0 + i - xhsize);
3173 /* set to be normal granite */
3174 place_extra_bold(y0 + 0 - yhsize, x0 + i - xhsize);
3177 /* bottom boundary */
3178 if ((cave[ysize + y0 - yhsize][i + x0 - xhsize].info & CAVE_ICKY) && (room))
3180 /* Next to a 'filled' region? - set to be room walls */
3181 place_outer_bold(y0 + ysize - yhsize, x0 + i - xhsize);
3182 if (light) cave[y0 + ysize - yhsize][x0 + i - xhsize].info|=(CAVE_GLOW);
3183 cave[y0 + ysize - yhsize][x0 + i - xhsize].info|=(CAVE_ROOM);
3184 place_outer_bold(y0 + ysize - yhsize, x0 + i - xhsize);
3188 /* set to be normal granite */
3189 place_extra_bold(y0 + ysize - yhsize, x0 + i - xhsize);
3192 /* clear the icky flag-don't need it any more */
3193 cave[y0 + 0 - yhsize][x0 + i - xhsize].info &= ~(CAVE_ICKY);
3194 cave[y0 + ysize - yhsize][x0 + i - xhsize].info &= ~(CAVE_ICKY);
3197 /* Do the left and right boundaries minus the corners (done above) */
3198 for (i = 1; i < ysize; ++i)
3201 if ((cave[i + y0 - yhsize][0 + x0 - xhsize].info & CAVE_ICKY) && room)
3204 place_outer_bold(y0 + i - yhsize, x0 + 0 - xhsize);
3205 if (light) cave[y0 + i - yhsize][x0 + 0 - xhsize].info |= (CAVE_GLOW);
3206 cave[y0 + i - yhsize][x0 + 0 - xhsize].info |= (CAVE_ROOM);
3207 place_outer_bold(y0 + i - yhsize, x0 + 0 - xhsize);
3212 place_extra_bold(y0 + i - yhsize, x0 + 0 - xhsize);
3214 /* right boundary */
3215 if ((cave[i + y0 - yhsize][xsize + x0 - xhsize].info & CAVE_ICKY) && room)
3218 place_outer_bold(y0 + i - yhsize, x0 + xsize - xhsize);
3219 if (light) cave[y0 + i - yhsize][x0 + xsize - xhsize].info |= (CAVE_GLOW);
3220 cave[y0 + i - yhsize][x0 + xsize - xhsize].info |= (CAVE_ROOM);
3221 place_outer_bold(y0 + i - yhsize, x0 + xsize - xhsize);
3226 place_extra_bold(y0 + i - yhsize, x0 + xsize - xhsize);
3229 /* clear icky flag -done with it */
3230 cave[y0 + i - yhsize][x0 + 0 - xhsize].info &= ~(CAVE_ICKY);
3231 cave[y0 + i - yhsize][x0 + xsize - xhsize].info &= ~(CAVE_ICKY);
3235 /* Do the rest: convert back to the normal format */
3236 for (x = 1; x < xsize; ++x)
3238 for (y = 1; y < ysize; ++y)
3240 if (is_floor_bold(y0 + y - yhsize, x0 + x - xhsize) &&
3241 (cave[y0 + y - yhsize][x0 + x - xhsize].info & CAVE_ICKY))
3243 /* Clear the icky flag in the filled region */
3244 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~CAVE_ICKY;
3246 /* Set appropriate flags */
3247 if (light) cave[y0 + y - yhsize][x0 + x - xhsize].info |= (CAVE_GLOW);
3248 if (room) cave[y0 + y - yhsize][x0 + x - xhsize].info |= (CAVE_ROOM);
3250 else if (is_outer_bold(y0 + y - yhsize, x0 + x - xhsize) &&
3251 (cave[y0 + y - yhsize][x0 + x - xhsize].info & CAVE_ICKY))
3254 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY);
3255 if (light) cave[y0 + y - yhsize][x0 + x - xhsize].info |= (CAVE_GLOW);
3258 cave[y0 + y - yhsize][x0 + x - xhsize].info |= (CAVE_ROOM);
3263 place_extra_bold(y0 + y - yhsize, x0 + x - xhsize);
3264 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ROOM);
3269 /* Clear the unconnected regions */
3270 place_extra_bold(y0 + y - yhsize, x0 + x - xhsize);
3271 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY | CAVE_ROOM);
3277 * XXX XXX XXX There is a slight problem when tunnels pierce the caves:
3278 * Extra doors appear inside the system. (Its not very noticeable though.)
3279 * This can be removed by "filling" from the outside in. This allows a separation
3280 * from FEAT_WALL_OUTER with FEAT_WALL_INNER. (Internal walls are F.W.OUTER instead.)
3281 * The extra effort for what seems to be only a minor thing (even non-existant if you
3282 * think of the caves not as normal rooms, but as holes in the dungeon), doesn't seem
3291 * Driver routine to create fractal cave system
3293 static void build_type9(int by0, int bx0)
3295 int grd, roug, cutoff, xsize, ysize, y0, x0;
3297 bool done, light, room;
3299 /* get size: note 'Evenness'*/
3300 xsize = randint1(22) * 2 + 6;
3301 ysize = randint1(15) * 2 + 6;
3303 /* Try to allocate space for room. If fails, exit */
3304 if (!room_alloc(xsize + 1, ysize + 1, FALSE, by0, bx0, &x0, &y0)) return;
3306 light = done = FALSE;
3309 if ((dun_level <= randint1(25)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS)) light = TRUE;
3313 /* Note: size must be even or there are rounding problems
3314 * This causes the tunnels not to connect properly to the room */
3316 /* testing values for these parameters feel free to adjust */
3317 grd = 1 << (randint0(4));
3319 /* want average of about 16 */
3320 roug = randint1(8) * randint1(4);
3323 cutoff = randint1(xsize / 4) + randint1(ysize / 4) +
3324 randint1(xsize / 4) + randint1(ysize / 4);
3327 generate_hmap(y0, x0, xsize, ysize, grd, roug, cutoff);
3329 /* Convert to normal format + clean up */
3330 done = generate_fracave(y0, x0, xsize, ysize, cutoff, light, room);
3334 #ifdef ALLOW_CAVERNS_AND_LAKES
3336 * Builds a cave system in the center of the dungeon.
3338 void build_cavern(void)
3340 int grd, roug, cutoff, xsize, ysize, x0, y0;
3343 light = done = FALSE;
3344 if ((dun_level <= randint1(50)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS)) light = TRUE;
3346 /* Make a cave the size of the dungeon */
3347 xsize = cur_wid - 1;
3348 ysize = cur_hgt - 1;
3352 /* Paranoia: make size even */
3358 /* testing values for these parameters: feel free to adjust */
3359 grd = randint1(4) + 4;
3361 /* want average of about 16 */
3362 roug = randint1(8) * randint1(4);
3368 generate_hmap(y0 + 1, x0 + 1, xsize, ysize, grd, roug, cutoff);
3370 /* Convert to normal format+ clean up */
3371 done = generate_fracave(y0 + 1, x0 + 1, xsize, ysize, cutoff, light, FALSE);
3375 static bool generate_lake(int y0, int x0, int xsize, int ysize, int c1, int c2, int c3, int type)
3377 int x, y, i, xhsize, yhsize;
3378 int feat1, feat2, feat3;
3380 /* offsets to middle from corner */
3384 /* Get features based on type */
3389 feat1 = FEAT_DEEP_LAVA;
3390 feat2 = FEAT_SHAL_LAVA;
3391 feat3 = floor_type[randint0(100)];
3395 feat1 = FEAT_DEEP_WATER;
3396 feat2 = FEAT_SHAL_WATER;
3397 feat3 = floor_type[randint0(100)];
3400 /* Collapsed cave */
3401 feat1 = floor_type[randint0(100)];
3402 feat2 = floor_type[randint0(100)];
3403 feat3 = FEAT_RUBBLE;
3407 feat1 = FEAT_RUBBLE;
3408 feat2 = floor_type[randint0(100)];
3409 feat3 = FEAT_RUBBLE;
3419 feat1 = FEAT_SHAL_WATER;
3420 feat2 = FEAT_DEEP_WATER;
3421 feat3 = FEAT_SHAL_WATER;
3425 feat1 = FEAT_SHAL_LAVA;
3426 feat2 = FEAT_DEEP_LAVA;
3427 feat3 = FEAT_SHAL_LAVA;
3431 default: return FALSE;
3435 * select region connected to center of cave system
3436 * this gets rid of alot of isolated one-sqaures that
3437 * can make teleport traps instadeaths...
3445 /* features to fill with */
3446 fill_data.feat1 = feat1;
3447 fill_data.feat2 = feat2;
3448 fill_data.feat3 = feat3;
3450 fill_data.info1 = 0;
3451 fill_data.info2 = 0;
3452 fill_data.info3 = 0;
3454 /* number of filled squares */
3455 fill_data.amount = 0;
3457 /* select region connected to center of cave system
3458 * this gets rid of alot of isolated one-sqaures that
3459 * can make teleport traps instadeaths... */
3460 cave_fill((byte)y0, (byte)x0);
3462 /* if tally too small, try again */
3463 if (fill_data.amount < 10)
3465 /* too small -clear area and try again later */
3466 for (x = 0; x <= xsize; ++x)
3468 for (y = 0; y <= ysize; ++y)
3470 place_floor_bold(y0 + y - yhsize, x0 + x - xhsize);
3471 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY);
3477 /* Do boundarys- set to normal granite */
3478 for (i = 0; i <= xsize; ++i)
3480 place_extra_bold(y0 + 0 - yhsize, x0 + i - xhsize);
3481 place_extra_bold(y0 + ysize - yhsize, x0 + i - xhsize);
3483 /* clear the icky flag-don't need it any more */
3484 cave[y0 + 0 - yhsize][x0 + i - xhsize].info &= ~(CAVE_ICKY);
3485 cave[y0 + ysize - yhsize][x0 + i - xhsize].info &= ~(CAVE_ICKY);
3488 /* Do the left and right boundaries minus the corners (done above) */
3490 for (i = 1; i < ysize; ++i)
3492 place_extra_bold(y0 + i - yhsize, x0 + 0 - xhsize);
3493 place_extra_bold(y0 + i - yhsize, x0 + xsize - xhsize);
3495 /* clear icky flag -done with it */
3496 cave[y0 + i - yhsize][x0 + 0 - xhsize].info &= ~(CAVE_ICKY);
3497 cave[y0 + i - yhsize][x0 + xsize - xhsize].info &= ~(CAVE_ICKY);
3501 /* Do the rest: convert back to the normal format */
3502 for (x = 1; x < xsize; ++x)
3504 for (y = 1; y < ysize; ++y)
3506 /* Fill unconnected regions with granite */
3507 if ((!(cave[y0 + y - yhsize][x0 + x - xhsize].info & CAVE_ICKY)) ||
3508 is_outer_bold(y0 + y - yhsize, x0 + x - xhsize))
3509 place_extra_bold(y0 + y - yhsize, x0 + x - xhsize);
3511 /* turn off icky flag (no longer needed.) */
3512 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY | CAVE_ROOM);
3514 /* Light lava and trees */
3515 if ((cave[y0 + y - yhsize][x0 + x - xhsize].feat == FEAT_DEEP_LAVA) ||
3516 (cave[y0 + y - yhsize][x0 + x - xhsize].feat == FEAT_SHAL_LAVA))
3518 cave[y0 + y - yhsize][x0 + x - xhsize].info |= CAVE_GLOW;
3528 * makes a lake/collapsed cave system in the center of the dungeon
3530 void build_lake(int type)
3532 int grd, roug, xsize, ysize, x0, y0;
3536 /* paranoia - exit if lake type out of range. */
3537 if ((type < 1) || (type > 7))
3539 msg_format("Invalid lake type (%d)", type);
3543 /* Make the size of the dungeon */
3544 xsize = cur_wid - 1;
3545 ysize = cur_hgt - 1;
3549 /* Paranoia: make size even */
3555 /* testing values for these parameters: feel free to adjust */
3556 grd = randint1(3) + 4;
3558 /* want average of about 16 */
3559 roug = randint1(8) * randint1(4);
3561 /* Make up size of various componants */
3565 /* Deep water/lava */
3566 c1 = randint0(c3 / 2) + randint0(c3 / 2) - 5;
3568 /* Shallow boundary */
3572 generate_hmap(y0 + 1, x0 + 1, xsize, ysize, grd, roug, c3);
3574 /* Convert to normal format+ clean up */
3575 done = generate_lake(y0 + 1, x0 + 1, xsize, ysize, c1, c2, c3, type);
3578 #endif /* ALLOW_CAVERNS_AND_LAKES */
3582 * Routine used by the random vault creators to add a door to a location
3583 * Note that range checking has to be done in the calling routine.
3585 * The doors must be INSIDE the allocated region.
3587 static void add_door(int x, int y)
3589 /* Need to have a wall in the center square */
3590 if (!is_outer_bold(y, x)) return;
3597 * where x=don't care
3601 if (is_floor_bold(y-1,x) && is_floor_bold(y+1,x) &&
3602 (is_outer_bold(y, x - 1) && is_outer_bold(y, x + 1)))
3605 place_secret_door(y, x);
3607 /* set boundarys so don't get wide doors */
3608 place_solid_bold(y, x - 1);
3609 place_solid_bold(y, x + 1);
3618 * where x = don't care
3621 if (is_outer_bold(y - 1, x) && is_outer_bold(y + 1, x) &&
3622 is_floor_bold(y,x-1) && is_floor_bold(y,x+1))
3625 place_secret_door(y, x);
3627 /* set boundarys so don't get wide doors */
3628 place_solid_bold(y - 1, x);
3629 place_solid_bold(y + 1, x);
3635 * Routine that fills the empty areas of a room with treasure and monsters.
3637 static void fill_treasure(int x1, int x2, int y1, int y2, int difficulty)
3639 int x, y, cx, cy, size;
3642 /* center of room:*/
3646 /* Rough measure of size of vault= sum of lengths of sides */
3647 size = abs(x2 - x1) + abs(y2 - y1);
3649 for (x = x1; x <= x2; x++)
3651 for (y = y1; y <= y2; y++)
3653 /* Thing added based on distance to center of vault
3654 * Difficulty is 1-easy to 10-hard */
3655 value = ((((s32b)(distance(cx, cy, x, y))) * 100) / size) + randint1(10) - difficulty;
3657 /* hack- empty square part of the time */
3658 if ((randint1(100) - difficulty * 3) > 50) value = 20;
3660 /* if floor, shallow water and lava */
3661 if (is_floor_bold(y, x) ||
3662 (cave[y][x].feat == FEAT_SHAL_WATER) ||
3663 (cave[y][x].feat == FEAT_SHAL_LAVA))
3665 /* The smaller 'value' is, the better the stuff */
3668 /* Meanest monster + treasure */
3669 monster_level = base_level + 40;
3670 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
3671 monster_level = base_level;
3672 object_level = base_level + 20;
3673 place_object(y, x, TRUE, FALSE);
3674 object_level = base_level;
3678 /* Mean monster +treasure */
3679 monster_level = base_level + 20;
3680 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
3681 monster_level = base_level;
3682 object_level = base_level + 10;
3683 place_object(y, x, TRUE, FALSE);
3684 object_level = base_level;
3686 else if (value < 10)
3689 monster_level = base_level + 9;
3690 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
3691 monster_level = base_level;
3693 else if (value < 17)
3695 /* Intentional Blank space */
3698 * (Want some of the vault to be empty
3699 * so have room for group monsters.
3700 * This is used in the hack above to lower
3701 * the density of stuff in the vault.)
3704 else if (value < 23)
3706 /* Object or trap */
3707 if (randint0(100) < 25)
3709 place_object(y, x, FALSE, FALSE);
3716 else if (value < 30)
3718 /* Monster and trap */
3719 monster_level = base_level + 5;
3720 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
3721 monster_level = base_level;
3724 else if (value < 40)
3726 /* Monster or object */
3727 if (randint0(100) < 50)
3729 monster_level = base_level + 3;
3730 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
3731 monster_level = base_level;
3733 if (randint0(100) < 50)
3735 object_level = base_level + 7;
3736 place_object(y, x, FALSE, FALSE);
3737 object_level = base_level;
3740 else if (value < 50)
3749 /* 20% monster, 40% trap, 20% object, 20% blank space */
3750 if (randint0(100) < 20)
3752 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
3754 else if (randint0(100) < 50)
3758 else if (randint0(100) < 50)
3760 place_object(y, x, FALSE, FALSE);
3771 * This function creates a random vault that looks like a collection of bubbles.
3772 * It works by getting a set of coordinates that represent the center of each
3773 * bubble. The entire room is made by seeing which bubble center is closest. If
3774 * two centers are equidistant then the square is a wall, otherwise it is a floor.
3775 * The only exception is for squares really near a center, these are always floor.
3776 * (It looks better than without this check.)
3778 * Note: If two centers are on the same point then this algorithm will create a
3779 * blank bubble filled with walls. - This is prevented from happening.
3781 static void build_bubble_vault(int x0, int y0, int xsize, int ysize)
3783 #define BUBBLENUM 10 /* number of bubbles */
3785 /* array of center points of bubbles */
3786 coord center[BUBBLENUM];
3789 u16b min1, min2, temp;
3792 /* Offset from center to top left hand corner */
3793 int xhsize = xsize / 2;
3794 int yhsize = ysize / 2;
3797 if (cheat_room) msg_print("Bubble Vault");
3799 /* Allocate center of bubbles */
3800 center[0].x = randint1(xsize - 3) + 1;
3801 center[0].y = randint1(ysize - 3) + 1;
3803 for (i = 1; i < BUBBLENUM; i++)
3807 /* get center and check to see if it is unique */
3812 x = randint1(xsize - 3) + 1;
3813 y = randint1(ysize - 3) + 1;
3815 for (j = 0; j < i; j++)
3817 /* rough test to see if there is an overlap */
3818 if ((x == center[j].x) && (y == center[j].y)) done = FALSE;
3827 /* Top and bottom boundaries */
3828 for (i = 0; i < xsize; i++)
3830 int x = x0 - xhsize + i;
3832 place_outer_noperm_bold(y0 - yhsize + 0, x);
3833 cave[y0 - yhsize + 0][x].info |= (CAVE_ROOM | CAVE_ICKY);
3834 place_outer_noperm_bold(y0 - yhsize + ysize - 1, x);
3835 cave[y0 - yhsize + ysize - 1][x].info |= (CAVE_ROOM | CAVE_ICKY);
3838 /* Left and right boundaries */
3839 for (i = 1; i < ysize - 1; i++)
3841 int y = y0 - yhsize + i;
3843 place_outer_noperm_bold(y, x0 - xhsize + 0);
3844 cave[y][x0 - xhsize + 0].info |= (CAVE_ROOM | CAVE_ICKY);
3845 place_outer_noperm_bold(y, x0 - xhsize + xsize - 1);
3846 cave[y][x0 - xhsize + xsize - 1].info |= (CAVE_ROOM | CAVE_ICKY);
3849 /* Fill in middle with bubbles */
3850 for (x = 1; x < xsize - 1; x++)
3852 for (y = 1; y < ysize - 1; y++)
3854 /* Get distances to two closest centers */
3857 min1 = distance(x, y, center[0].x, center[0].y);
3858 min2 = distance(x, y, center[1].x, center[1].y);
3862 /* swap if in wrong order */
3869 for (i = 2; i < BUBBLENUM; i++)
3871 temp = distance(x, y, center[i].x, center[i].y);
3879 else if (temp < min2)
3881 /* second smallest */
3885 if (((min2 - min1) <= 2) && (!(min1 < 3)))
3887 /* Boundary at midpoint+ not at inner region of bubble */
3888 place_outer_noperm_bold(y0 - yhsize + y, x0 - xhsize + x);
3892 /* middle of a bubble */
3893 place_floor_bold(y0 - yhsize + y, x0 - xhsize + x);
3896 /* clean up rest of flags */
3897 cave[y0 - yhsize + y][x0 - xhsize + x].info |= (CAVE_ROOM | CAVE_ICKY);
3901 /* Try to add some random doors */
3902 for (i = 0; i < 500; i++)
3904 x = randint1(xsize - 3) - xhsize + x0 + 1;
3905 y = randint1(ysize - 3) - yhsize + y0 + 1;
3909 /* Fill with monsters and treasure, low difficulty */
3910 fill_treasure(x0 - xhsize + 1, x0 - xhsize + xsize - 2, y0 - yhsize + 1, y0 - yhsize + ysize - 2, randint1(5));
3915 * Overlay a rectangular room given its bounds
3916 * This routine is used by build_room_vault
3917 * The area inside the walls is not touched:
3918 * only granite is removed- normal walls stay
3920 static void build_room(int x1, int x2, int y1, int y2)
3922 int x, y, i, xsize, ysize, temp;
3924 /* Check if rectangle has no width */
3925 if ((x1 == x2) || (y1 == y2)) return;
3930 /* Swap boundaries if in wrong order */
3938 /* Swap boundaries if in wrong order */
3944 /* get total widths */
3949 /* Top and bottom boundaries */
3950 for (i = 0; i <= xsize; i++)
3952 place_outer_noperm_bold(y1, x1 + i);
3953 cave[y1][x1 + i].info |= (CAVE_ROOM | CAVE_ICKY);
3954 place_outer_noperm_bold(y2, x1 + i);
3955 cave[y2][x1 + i].info |= (CAVE_ROOM | CAVE_ICKY);
3958 /* Left and right boundaries */
3959 for (i = 1; i < ysize; i++)
3961 place_outer_noperm_bold(y1 + i, x1);
3962 cave[y1 + i][x1].info|=(CAVE_ROOM | CAVE_ICKY);
3963 place_outer_noperm_bold(y1 + i, x2);
3964 cave[y1 + i][x2].info|=(CAVE_ROOM | CAVE_ICKY);
3968 for (x = 1; x < xsize; x++)
3970 for (y = 1; y < ysize; y++)
3972 if (is_extra_bold(y1+y, x1+x))
3974 /* clear the untouched region */
3975 place_floor_bold(y1 + y, x1 + x);
3976 cave[y1 + y][x1 + x].info |= (CAVE_ROOM | CAVE_ICKY);
3980 /* make it a room- but don't touch */
3981 cave[y1 + y][x1 + x].info |= (CAVE_ROOM | CAVE_ICKY);
3988 /* Create a random vault that looks like a collection of overlapping rooms */
3990 static void build_room_vault(int x0, int y0, int xsize, int ysize)
3992 int i, x1, x2, y1, y2, xhsize, yhsize;
3994 /* get offset from center */
3998 if (cheat_room) msg_print("Room Vault");
4000 /* fill area so don't get problems with arena levels */
4001 for (x1 = 0; x1 < xsize; x1++)
4003 int x = x0 - xhsize + x1;
4005 for (y1 = 0; y1 < ysize; y1++)
4007 int y = y0 - yhsize + y1;
4009 place_extra_bold(y, x);
4010 cave[y][x].info &= (~CAVE_ICKY);
4014 /* add ten random rooms */
4015 for (i = 0; i < 10; i++)
4017 x1 = randint1(xhsize) * 2 + x0 - xhsize;
4018 x2 = randint1(xhsize) * 2 + x0 - xhsize;
4019 y1 = randint1(yhsize) * 2 + y0 - yhsize;
4020 y2 = randint1(yhsize) * 2 + y0 - yhsize;
4021 build_room(x1, x2, y1, y2);
4024 /* Add some random doors */
4025 for (i = 0; i < 500; i++)
4027 x1 = randint1(xsize - 3) - xhsize + x0 + 1;
4028 y1 = randint1(ysize - 3) - yhsize + y0 + 1;
4032 /* Fill with monsters and treasure, high difficulty */
4033 fill_treasure(x0 - xhsize + 1, x0 - xhsize + xsize - 2, y0 - yhsize + 1, y0 - yhsize + ysize - 2, randint1(5) + 5);
4037 /* Create a random vault out of a fractal cave */
4038 static void build_cave_vault(int x0, int y0, int xsiz, int ysiz)
4040 int grd, roug, cutoff, xhsize, yhsize, xsize, ysize, x, y;
4041 bool done, light, room;
4043 /* round to make sizes even */
4049 if (cheat_room) msg_print("Cave Vault");
4051 light = done = FALSE;
4056 /* testing values for these parameters feel free to adjust */
4057 grd = 1 << randint0(4);
4059 /* want average of about 16 */
4060 roug = randint1(8) * randint1(4);
4063 cutoff = randint1(xsize / 4) + randint1(ysize / 4) +
4064 randint1(xsize / 4) + randint1(ysize / 4);
4067 generate_hmap(y0, x0, xsize, ysize, grd, roug, cutoff);
4069 /* Convert to normal format+ clean up */
4070 done = generate_fracave(y0, x0, xsize, ysize, cutoff, light, room);
4073 /* Set icky flag because is a vault */
4074 for (x = 0; x <= xsize; x++)
4076 for (y = 0; y <= ysize; y++)
4078 cave[y0 - yhsize + y][x0 - xhsize + x].info |= CAVE_ICKY;
4082 /* Fill with monsters and treasure, low difficulty */
4083 fill_treasure(x0 - xhsize + 1, x0 - xhsize + xsize - 1, y0 - yhsize + 1, y0 - yhsize + ysize - 1, randint1(5));
4087 * maze vault -- rectangular labyrinthine rooms
4089 * maze vault uses two routines:
4090 * r_visit - a recursive routine that builds the labyrinth
4091 * build_maze_vault - a driver routine that calls r_visit and adds
4092 * monsters, traps and treasure
4094 * The labyrinth is built by creating a spanning tree of a graph.
4095 * The graph vertices are at
4096 * (x, y) = (2j + x1, 2k + y1) j = 0,...,m-1 k = 0,...,n-1
4097 * and the edges are the vertical and horizontal nearest neighbors.
4099 * The spanning tree is created by performing a suitably randomized
4100 * depth-first traversal of the graph. The only adjustable parameter
4101 * is the randint0(3) below; it governs the relative density of
4102 * twists and turns in the labyrinth: smaller number, more twists.
4104 static void r_visit(int y1, int x1, int y2, int x2,
4105 int node, int dir, int *visited)
4107 int i, j, m, n, temp, x, y, adj[4];
4109 /* dimensions of vertex array */
4110 m = (x2 - x1) / 2 + 1;
4111 n = (y2 - y1) / 2 + 1;
4113 /* mark node visited and set it to a floor */
4115 x = 2 * (node % m) + x1;
4116 y = 2 * (node / m) + y1;
4117 place_floor_bold(y, x);
4119 /* setup order of adjacent node visits */
4122 /* pick a random ordering */
4123 for (i = 0; i < 4; i++)
4125 for (i = 0; i < 4; i++)
4136 /* pick a random ordering with dir first */
4138 for (i = 1; i < 4; i++)
4140 for (i = 1; i < 4; i++)
4142 j = 1 + randint0(3);
4149 for (i = 0; i < 4; i++)
4154 /* (0,+) - check for bottom boundary */
4155 if ((node / m < n - 1) && (visited[node + m] == 0))
4157 place_floor_bold(y + 1, x);
4158 r_visit(y1, x1, y2, x2, node + m, dir, visited);
4162 /* (0,-) - check for top boundary */
4163 if ((node / m > 0) && (visited[node - m] == 0))
4165 place_floor_bold(y - 1, x);
4166 r_visit(y1, x1, y2, x2, node - m, dir, visited);
4170 /* (+,0) - check for right boundary */
4171 if ((node % m < m - 1) && (visited[node + 1] == 0))
4173 place_floor_bold(y, x + 1);
4174 r_visit(y1, x1, y2, x2, node + 1, dir, visited);
4178 /* (-,0) - check for left boundary */
4179 if ((node % m > 0) && (visited[node - 1] == 0))
4181 place_floor_bold(y, x - 1);
4182 r_visit(y1, x1, y2, x2, node - 1, dir, visited);
4189 void build_maze_vault(int x0, int y0, int xsize, int ysize, bool is_vault)
4193 int m, n, num_vertices, *visited;
4198 if (cheat_room && is_vault) msg_print("Maze Vault");
4200 /* Choose lite or dark */
4201 light = ((dun_level <= randint1(25)) && is_vault && !(d_info[dungeon_type].flags1 & DF1_DARKNESS));
4203 /* Pick a random room size - randomized by calling routine */
4212 /* generate the room */
4213 for (y = y1 - 1; y <= y2 + 1; y++)
4215 for (x = x1 - 1; x <= x2 + 1; x++)
4217 c_ptr = &cave[y][x];
4218 c_ptr->info |= CAVE_ROOM;
4219 if (is_vault) c_ptr->info |= CAVE_ICKY;
4220 if ((x == x1 - 1) || (x == x2 + 1) || (y == y1 - 1) || (y == y2 + 1))
4222 place_outer_grid(c_ptr);
4226 place_extra_grid(c_ptr);
4230 place_inner_grid(c_ptr);
4232 if (light) c_ptr->info |= (CAVE_GLOW);
4236 /* dimensions of vertex array */
4239 num_vertices = m * n;
4241 /* initialize array of visited vertices */
4242 C_MAKE(visited, num_vertices, int);
4244 /* traverse the graph to create a spaning tree, pick a random root */
4245 r_visit(y1, x1, y2, x2, randint0(num_vertices), 0, visited);
4247 /* Fill with monsters and treasure, low difficulty */
4248 if (is_vault) fill_treasure(x1, x2, y1, y2, randint1(5));
4250 C_KILL(visited, num_vertices, int);
4254 /* Build a "mini" checkerboard vault
4256 * This is done by making a permanent wall maze and setting
4257 * the diagonal sqaures of the checker board to be granite.
4258 * The vault has two entrances on opposite sides to guarantee
4259 * a way to get in even if the vault abuts a side of the dungeon.
4261 static void build_mini_c_vault(int x0, int y0, int xsize, int ysize)
4264 int y1, x1, y2, x2, y, x, total;
4265 int m, n, num_vertices;
4268 if (cheat_room) msg_print("Mini Checker Board Vault");
4270 /* Pick a random room size */
4280 /* generate the room */
4281 for (x = x1 - 2; x <= x2 + 2; x++)
4283 if (!in_bounds(y1-2,x)) break;
4285 cave[y1-2][x].info |= (CAVE_ROOM | CAVE_ICKY);
4287 place_extra_noperm_bold(y1-2, x);
4290 for (x = x1 - 2; x <= x2 + 2; x++)
4292 if (!in_bounds(y2+2,x)) break;
4294 cave[y2+2][x].info |= (CAVE_ROOM | CAVE_ICKY);
4296 place_extra_noperm_bold(y2+2, x);
4299 for (y = y1 - 2; y <= y2 + 2; y++)
4301 if (!in_bounds(y,x1-2)) break;
4303 cave[y][x1-2].info |= (CAVE_ROOM | CAVE_ICKY);
4305 place_extra_noperm_bold(y, x1-2);
4308 for (y = y1 - 2; y <= y2 + 2; y++)
4310 if (!in_bounds(y,x2+2)) break;
4312 cave[y][x2+2].info |= (CAVE_ROOM | CAVE_ICKY);
4314 place_extra_noperm_bold(y, x2+2);
4317 for (y = y1 - 1; y <= y2 + 1; y++)
4319 for (x = x1 - 1; x <= x2 + 1; x++)
4321 cave[y][x].info |= (CAVE_ROOM | CAVE_ICKY);
4323 /* Permanent walls */
4324 cave[y][x].feat = FEAT_PERM_INNER;
4329 /* dimensions of vertex array */
4332 num_vertices = m * n;
4334 /* initialize array of visited vertices */
4335 C_MAKE(visited, num_vertices, int);
4337 /* traverse the graph to create a spannng tree, pick a random root */
4338 r_visit(y1, x1, y2, x2, randint0(num_vertices), 0, visited);
4340 /* Make it look like a checker board vault */
4341 for (x = x1; x <= x2; x++)
4343 for (y = y1; y <= y2; y++)
4345 total = x - x1 + y - y1;
4346 /* If total is odd- and is a floor then make a wall */
4347 if ((total % 2 == 1) && is_floor_bold(y, x))
4349 place_inner_bold(y, x);
4354 /* Make a couple of entrances */
4357 /* left and right */
4358 y = randint1(dy) + dy / 2;
4359 place_outer_noperm_bold(y1 + y, x1 - 1);
4360 place_outer_noperm_bold(y1 + y, x2 + 1);
4364 /* top and bottom */
4365 x = randint1(dx) + dx / 2;
4366 place_outer_noperm_bold(y1 - 1, x1 + x);
4367 place_outer_noperm_bold(y2 + 1, x1 + x);
4370 /* Fill with monsters and treasure, highest difficulty */
4371 fill_treasure(x1, x2, y1, y2, 10);
4373 C_KILL(visited, num_vertices, int);
4377 /* Build a town/ castle by using a recursive algorithm.
4378 * Basically divide each region in a probalistic way to create
4379 * smaller regions. When the regions get too small stop.
4381 * The power variable is a measure of how well defended a region is.
4382 * This alters the possible choices.
4384 static void build_recursive_room(int x1, int y1, int x2, int y2, int power)
4390 /* Temp variables */
4396 if ((power < 3) && (xsize > 12) && (ysize > 12))
4398 /* Need outside wall +keep */
4405 /* Make rooms + subdivide */
4406 if ((randint1(10) > 2) && (xsize < 8) && (ysize < 8))
4412 choice = randint1(2) + 1;
4417 /* Mostly subdivide */
4418 choice = randint1(3) + 1;
4422 /* Based on the choice made above, do something */
4430 /* top and bottom */
4431 for (x = x1; x <= x2; x++)
4433 place_outer_bold(y1, x);
4434 place_outer_bold(y2, x);
4437 /* left and right */
4438 for (y = y1 + 1; y < y2; y++)
4440 place_outer_bold(y, x1);
4441 place_outer_bold(y, x2);
4444 /* Make a couple of entrances */
4447 /* left and right */
4448 y = randint1(ysize) + y1;
4449 place_floor_bold(y, x1);
4450 place_floor_bold(y, x2);
4454 /* top and bottom */
4455 x = randint1(xsize) + x1;
4456 place_floor_bold(y1, x);
4457 place_floor_bold(y2, x);
4460 /* Select size of keep */
4461 t1 = randint1(ysize / 3) + y1;
4462 t2 = y2 - randint1(ysize / 3);
4463 t3 = randint1(xsize / 3) + x1;
4464 t4 = x2 - randint1(xsize / 3);
4466 /* Do outside areas */
4468 /* Above and below keep */
4469 build_recursive_room(x1 + 1, y1 + 1, x2 - 1, t1, power + 1);
4470 build_recursive_room(x1 + 1, t2, x2 - 1, y2, power + 1);
4472 /* Left and right of keep */
4473 build_recursive_room(x1 + 1, t1 + 1, t3, t2 - 1, power + 3);
4474 build_recursive_room(t4, t1 + 1, x2 - 1, t2 - 1, power + 3);
4476 /* Make the keep itself: */
4489 /* Try to build a room */
4490 if ((xsize < 3) || (ysize < 3))
4492 for (y = y1; y < y2; y++)
4494 for (x = x1; x < x2; x++)
4496 place_inner_bold(y, x);
4504 /* Make outside walls */
4505 /* top and bottom */
4506 for (x = x1 + 1; x <= x2 - 1; x++)
4508 place_inner_bold(y1 + 1, x);
4509 place_inner_bold(y2 - 1, x);
4512 /* left and right */
4513 for (y = y1 + 1; y <= y2 - 1; y++)
4515 place_inner_bold(y, x1 + 1);
4516 place_inner_bold(y, x2 - 1);
4520 y = randint1(ysize - 3) + y1 + 1;
4525 place_floor_bold(y, x1 + 1);
4530 place_floor_bold(y, x2 - 1);
4533 /* Build the room */
4534 build_recursive_room(x1 + 2, y1 + 2, x2 - 2, y2 - 2, power + 3);
4539 /* Try and divide vertically */
4543 for (y = y1; y < y2; y++)
4545 for (x = x1; x < x2; x++)
4547 place_inner_bold(y, x);
4553 t1 = randint1(xsize - 2) + x1 + 1;
4554 build_recursive_room(x1, y1, t1, y2, power - 2);
4555 build_recursive_room(t1 + 1, y1, x2, y2, power - 2);
4560 /* Try and divide horizontally */
4564 for (y = y1; y < y2; y++)
4566 for (x = x1; x < x2; x++)
4568 place_inner_bold(y, x);
4574 t1 = randint1(ysize - 2) + y1 + 1;
4575 build_recursive_room(x1, y1, x2, t1, power - 2);
4576 build_recursive_room(x1, t1 + 1, x2, y2, power - 2);
4583 /* Build a castle */
4585 /* Driver routine: clear the region and call the recursive
4588 *This makes a vault that looks like a castle/ city in the dungeon.
4590 static void build_castle_vault(int x0, int y0, int xsize, int ysize)
4596 /* Pick a random room size */
4605 if (cheat_room) msg_print("Castle Vault");
4607 /* generate the room */
4608 for (y = y1 - 1; y <= y2 + 1; y++)
4610 for (x = x1 - 1; x <= x2 + 1; x++)
4612 cave[y][x].info |= (CAVE_ROOM | CAVE_ICKY);
4613 /* Make everything a floor */
4614 place_floor_bold(y, x);
4618 /* Make the castle */
4619 build_recursive_room(x1, y1, x2, y2, randint1(5));
4621 /* Fill with monsters and treasure, low difficulty */
4622 fill_treasure(x1, x2, y1, y2, randint1(3));
4627 * Add outer wall to a floored region
4628 * Note: no range checking is done so must be inside dungeon
4629 * This routine also stomps on doors
4631 static void add_outer_wall(int x, int y, int light,
4632 int x1, int y1, int x2, int y2)
4636 if (!in_bounds(y, x)) return;
4638 /* hack- check to see if square has been visited before
4639 * if so, then exit (use room flag to do this) */
4640 if (cave[y][x].info & CAVE_ROOM) return;
4643 cave[y][x].info |= CAVE_ROOM;
4645 if (is_floor_bold(y, x))
4647 for (i = -1; i <= 1; i++)
4649 for (j = -1; j <= 1; j++)
4651 if ((x + i >= x1) && (x + i <= x2) &&
4652 (y + j >= y1) && (y + j <= y2))
4654 add_outer_wall(x + i, y + j, light, x1, y1, x2, y2);
4655 if (light) cave[y][x].info |= CAVE_GLOW;
4660 else if (is_extra_bold(y, x))
4662 /* Set bounding walls */
4663 place_outer_bold(y, x);
4664 if (light == TRUE) cave[y][x].info |= CAVE_GLOW;
4666 else if (cave[y][x].feat == FEAT_PERM_OUTER)
4668 /* Set bounding walls */
4669 if (light == TRUE) cave[y][x].info |= CAVE_GLOW;
4675 * Hacked distance formula - gives the 'wrong' answer.
4676 * Used to build crypts
4678 static int dist2(int x1, int y1, int x2, int y2,
4679 int h1, int h2, int h3, int h4)
4685 /* Basically this works by taking the normal pythagorean formula
4686 * and using an expansion to express this in a way without the
4687 * square root. This approximate formula is then perturbed to give
4688 * the distorted results. (I found this by making a mistake when I was
4689 * trying to fix the circular rooms.)
4692 /* h1-h4 are constants that describe the metric */
4693 if (dx >= 2 * dy) return (dx + (dy * h1) / h2);
4694 if (dy >= 2 * dx) return (dy + (dx * h1) / h2);
4695 return (((dx + dy) * 128) / 181 +
4696 (dx * dx / (dy * h3) + dy * dy / (dx * h3)) * h4);
4697 /* 128/181 is approx. 1/sqrt(2) */
4702 * Build target vault.
4703 * This is made by two concentric "crypts" with perpendicular
4704 * walls creating the cross-hairs.
4706 static void build_target_vault(int x0, int y0, int xsize, int ysize)
4710 /* Make a random metric */
4712 h1 = randint1(32) - 16;
4715 h4 = randint1(32) - 16;
4717 if (cheat_room) msg_print("Target Vault");
4719 /* work out outer radius */
4730 for (x = x0 - rad; x <= x0 + rad; x++)
4732 for (y = y0 - rad; y <= y0 + rad; y++)
4734 /* clear room flag */
4735 cave[y][x].info &= ~(CAVE_ROOM);
4737 /* Vault - so is "icky" */
4738 cave[y][x].info |= CAVE_ICKY;
4740 if (dist2(y0, x0, y, x, h1, h2, h3, h4) <= rad - 1)
4742 /* inside- so is floor */
4743 place_floor_bold(y, x);
4747 /* make granite outside so arena works */
4748 place_extra_bold(y, x);
4751 /* proper boundary for arena */
4752 if (((y + rad) == y0) || ((y - rad) == y0) ||
4753 ((x + rad) == x0) || ((x - rad) == x0))
4755 place_extra_bold(y, x);
4760 /* Find visible outer walls and set to be FEAT_OUTER */
4761 add_outer_wall(x0, y0, FALSE, x0 - rad - 1, y0 - rad - 1,
4762 x0 + rad + 1, y0 + rad + 1);
4764 /* Add inner wall */
4765 for (x = x0 - rad / 2; x <= x0 + rad / 2; x++)
4767 for (y = y0 - rad / 2; y <= y0 + rad / 2; y++)
4769 if (dist2(y0, x0, y, x, h1, h2, h3, h4) == rad / 2)
4771 /* Make an internal wall */
4772 place_inner_bold(y, x);
4777 /* Add perpendicular walls */
4778 for (x = x0 - rad; x <= x0 + rad; x++)
4780 place_inner_bold(y0, x);
4783 for (y = y0 - rad; y <= y0 + rad; y++)
4785 place_inner_bold(y, x0);
4788 /* Make inner vault */
4789 for (y = y0 - 1; y <= y0 + 1; y++)
4791 place_inner_bold(y, x0 - 1);
4792 place_inner_bold(y, x0 + 1);
4794 for (x = x0 - 1; x <= x0 + 1; x++)
4796 place_inner_bold(y0 - 1, x);
4797 place_inner_bold(y0 + 1, x);
4800 place_floor_bold(y0, x0);
4803 /* Add doors to vault */
4804 /* get two distances so can place doors relative to centre */
4805 x = (rad - 2) / 4 + 1;
4808 add_door(x0 + x, y0);
4809 add_door(x0 + y, y0);
4810 add_door(x0 - x, y0);
4811 add_door(x0 - y, y0);
4812 add_door(x0, y0 + x);
4813 add_door(x0, y0 + y);
4814 add_door(x0, y0 - x);
4815 add_door(x0, y0 - y);
4817 /* Fill with stuff - medium difficulty */
4818 fill_treasure(x0 - rad, x0 + rad, y0 - rad, y0 + rad, randint1(3) + 3);
4822 #ifdef ALLOW_CAVERNS_AND_LAKES
4824 * This routine uses a modified version of the lake code to make a
4825 * distribution of some terrain type over the vault. This type
4826 * depends on the dungeon depth.
4828 * Miniture rooms are then scattered across the vault.
4830 static void build_elemental_vault(int x0, int y0, int xsiz, int ysiz)
4835 int xsize, ysize, xhsize, yhsize, x, y, i;
4839 if (cheat_room) msg_print("Elemental Vault");
4841 /* round to make sizes even */
4849 /* Earth vault (Rubble) */
4852 else if (dun_level < 50)
4854 /* Air vault (Trees) */
4857 else if (dun_level < 75)
4859 /* Water vault (shallow water) */
4864 /* Fire vault (shallow lava) */
4870 /* testing values for these parameters: feel free to adjust */
4871 grd = 1 << (randint0(3));
4873 /* want average of about 16 */
4874 roug = randint1(8) * randint1(4);
4876 /* Make up size of various componants */
4880 /* Deep water/lava */
4881 c1 = randint0(c3 / 2) + randint0(c3 / 2) - 5;
4883 /* Shallow boundary */
4887 generate_hmap(y0, x0, xsize, ysize, grd, roug, c3);
4889 /* Convert to normal format+ clean up */
4890 done = generate_lake(y0, x0, xsize, ysize, c1, c2, c3, type);
4893 /* Set icky flag because is a vault */
4894 for (x = 0; x <= xsize; x++)
4896 for (y = 0; y <= ysize; y++)
4898 cave[y0 - yhsize + y][x0 - xhsize + x].info |= CAVE_ICKY;
4902 /* make a few rooms in the vault */
4903 for (i = 1; i <= (xsize * ysize) / 50; i++)
4905 build_small_room(x0 + randint0(xsize - 4) - xsize / 2 + 2,
4906 y0 + randint0(ysize - 4) - ysize / 2 + 2);
4909 /* Fill with monsters and treasure, low difficulty */
4910 fill_treasure(x0 - xhsize + 1, x0 - xhsize + xsize - 1,
4911 y0 - yhsize + 1, y0 - yhsize + ysize - 1, randint1(5));
4913 #endif /* ALLOW_CAVERNS_AND_LAKES */
4919 static void build_type10(int by0, int bx0)
4921 int y0, x0, xsize, ysize, vtype;
4924 /* big enough to look good, small enough to be fairly common. */
4925 xsize = randint1(22) + 22;
4926 ysize = randint1(11) + 11;
4928 /* Allocate in room_map. If will not fit, exit */
4929 if (!room_alloc(xsize + 1, ysize + 1, FALSE, by0, bx0, &x0, &y0)) return;
4931 /* Boost the rating- higher than lesser vaults and lower than greater vaults */
4934 /* (Sometimes) Cause a special feeling */
4935 if ((dun_level <= 50) ||
4936 (randint1((dun_level - 40) * (dun_level - 40) + 1) < 400))
4938 good_item_flag = TRUE;
4941 /* Select type of vault */
4942 #ifdef ALLOW_CAVERNS_AND_LAKES
4943 vtype = randint1(15);
4944 #else /* ALLOW_CAVERNS_AND_LAKES */
4945 vtype = randint1(7);
4946 #endif /* ALLOW_CAVERNS_AND_LAKES */
4950 /* Build an appropriate room */
4951 case 1: case 9: build_bubble_vault(x0, y0, xsize, ysize); break;
4952 case 2: case 10: build_room_vault(x0, y0, xsize, ysize); break;
4953 case 3: case 11: build_cave_vault(x0, y0, xsize, ysize); break;
4954 case 4: case 12: build_maze_vault(x0, y0, xsize, ysize, TRUE); break;
4955 case 5: case 13: build_mini_c_vault(x0, y0, xsize, ysize); break;
4956 case 6: case 14: build_castle_vault(x0, y0, xsize, ysize); break;
4957 case 7: case 15: build_target_vault(x0, y0, xsize, ysize); break;
4958 #ifdef ALLOW_CAVERNS_AND_LAKES
4959 case 8: build_elemental_vault(x0, y0, xsize, ysize); break;
4960 #endif /* ALLOW_CAVERNS_AND_LAKES */
4961 /* I know how to add a few more... give me some time. */
4970 * Build an vertical oval room.
4971 * For every grid in the possible square, check the distance.
4972 * If it's less than the radius, make it a room square.
4974 * When done fill from the inside to find the walls,
4976 static void build_type11(int by0, int bx0)
4978 int rad, x, y, x0, y0;
4981 /* Occasional light */
4982 if ((randint1(dun_level) <= 15) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS)) light = TRUE;
4986 /* Allocate in room_map. If will not fit, exit */
4987 if (!room_alloc(rad * 2 + 1, rad * 2 + 1, FALSE, by0, bx0, &x0, &y0)) return;
4989 /* Make circular floor */
4990 for (x = x0 - rad; x <= x0 + rad; x++)
4992 for (y = y0 - rad; y <= y0 + rad; y++)
4994 if (distance(y0, x0, y, x) <= rad - 1)
4996 /* inside- so is floor */
4997 place_floor_bold(y, x);
4999 else if (distance(y0, x0, y, x) <= rad + 1)
5001 /* make granite outside so arena works */
5002 place_extra_bold(y, x);
5007 /* Find visible outer walls and set to be FEAT_OUTER */
5008 add_outer_wall(x0, y0, light, x0 - rad, y0 - rad, x0 + rad, y0 + rad);
5014 * For every grid in the possible square, check the (fake) distance.
5015 * If it's less than the radius, make it a room square.
5017 * When done fill from the inside to find the walls,
5019 static void build_type12(int by0, int bx0)
5021 int rad, x, y, x0, y0;
5023 bool emptyflag = TRUE;
5025 /* Make a random metric */
5027 h1 = randint1(32) - 16;
5030 h4 = randint1(32) - 16;
5032 /* Occasional light */
5033 if ((randint1(dun_level) <= 5) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS)) light = TRUE;
5037 /* Allocate in room_map. If will not fit, exit */
5038 if (!room_alloc(rad * 2 + 3, rad * 2 + 3, FALSE, by0, bx0, &x0, &y0)) return;
5041 for (x = x0 - rad; x <= x0 + rad; x++)
5043 for (y = y0 - rad; y <= y0 + rad; y++)
5045 /* clear room flag */
5046 cave[y][x].info &= ~(CAVE_ROOM);
5048 if (dist2(y0, x0, y, x, h1, h2, h3, h4) <= rad - 1)
5050 /* inside - so is floor */
5051 place_floor_bold(y, x);
5053 else if (distance(y0, x0, y, x) < 3)
5055 place_floor_bold(y, x);
5059 /* make granite outside so arena works */
5060 place_extra_bold(y, x);
5063 /* proper boundary for arena */
5064 if (((y + rad) == y0) || ((y - rad) == y0) ||
5065 ((x + rad) == x0) || ((x - rad) == x0))
5067 place_extra_bold(y, x);
5072 /* Find visible outer walls and set to be FEAT_OUTER */
5073 add_outer_wall(x0, y0, light, x0 - rad - 1, y0 - rad - 1,
5074 x0 + rad + 1, y0 + rad + 1);
5076 /* Check to see if there is room for an inner vault */
5077 for (x = x0 - 2; x <= x0 + 2; x++)
5079 for (y = y0 - 2; y <= y0 + 2; y++)
5081 if (!is_floor_bold(y, x))
5083 /* Wall in the way */
5089 if (emptyflag && one_in_(2))
5091 /* Build the vault */
5092 build_small_room(x0, y0);
5094 /* Place a treasure in the vault */
5095 place_object(y0, x0, FALSE, FALSE);
5097 /* Let's guard the treasure well */
5098 vault_monsters(y0, x0, randint0(2) + 3);
5100 /* Traps naturally */
5101 vault_traps(y0, x0, 4, 4, randint0(3) + 2);
5107 * Helper function for "trapped monster pit"
5109 static bool vault_aux_trapped_pit(int r_idx)
5111 monster_race *r_ptr = &r_info[r_idx];
5113 /* Validate the monster */
5114 if (!vault_monster_okay(r_idx)) return (FALSE);
5116 /* No wall passing monster */
5117 if (r_ptr->flags2 & (RF2_PASS_WALL | RF2_KILL_WALL)) return (FALSE);
5125 * Type 12 -- Trapped monster pits
5127 * A trapped monster pit is a "big" room with a straight corridor in
5128 * which wall opening traps are placed, and with two "inner" rooms
5129 * containing a "collection" of monsters of a given type organized in
5132 * The trapped monster pit appears as shown below, where the actual
5133 * monsters in each location depend on the type of the pit
5135 * #########################
5137 * ####################### #
5138 * #####001123454321100### #
5139 * ###0012234567654322100# #
5140 * ####################### #
5142 * # #######################
5143 * # #0012234567654322100###
5144 * # ###001123454321100#####
5145 * # #######################
5147 * #########################
5149 * Note that the monsters in the pit are now chosen by using "get_mon_num()"
5150 * to request 16 "appropriate" monsters, sorting them by level, and using
5151 * the "even" entries in this sorted list for the contents of the pit.
5153 * Hack -- all of the "dragons" in a "dragon" pit must be the same "color",
5154 * which is handled by requiring a specific "breath" attack for all of the
5155 * dragons. This may include "multi-hued" breath. Note that "wyrms" may
5156 * be present in many of the dragon pits, if they have the proper breath.
5158 * Note the use of the "get_mon_num_prep()" function, and the special
5159 * "get_mon_num_hook()" restriction function, to prepare the "monster
5160 * allocation table" in such a way as to optimize the selection of
5161 * "appropriate" non-unique monsters for the pit.
5163 * Note that the "get_mon_num()" function may (rarely) fail, in which case
5164 * the pit will be empty, and will not effect the level rating.
5166 * Note that "monster pits" will never contain "unique" monsters.
5168 static void build_type13(int by0, int bx0)
5170 static int placing[][3] = {
5171 {-2, -9, 0}, {-2, -8, 0}, {-3, -7, 0}, {-3, -6, 0},
5172 {+2, -9, 0}, {+2, -8, 0}, {+3, -7, 0}, {+3, -6, 0},
5173 {-2, +9, 0}, {-2, +8, 0}, {-3, +7, 0}, {-3, +6, 0},
5174 {+2, +9, 0}, {+2, +8, 0}, {+3, +7, 0}, {+3, +6, 0},
5175 {-2, -7, 1}, {-3, -5, 1}, {-3, -4, 1},
5176 {+2, -7, 1}, {+3, -5, 1}, {+3, -4, 1},
5177 {-2, +7, 1}, {-3, +5, 1}, {-3, +4, 1},
5178 {+2, +7, 1}, {+3, +5, 1}, {+3, +4, 1},
5179 {-2, -6, 2}, {-2, -5, 2}, {-3, -3, 2},
5180 {+2, -6, 2}, {+2, -5, 2}, {+3, -3, 2},
5181 {-2, +6, 2}, {-2, +5, 2}, {-3, +3, 2},
5182 {+2, +6, 2}, {+2, +5, 2}, {+3, +3, 2},
5183 {-2, -4, 3}, {-3, -2, 3},
5184 {+2, -4, 3}, {+3, -2, 3},
5185 {-2, +4, 3}, {-3, +2, 3},
5186 {+2, +4, 3}, {+3, +2, 3},
5187 {-2, -3, 4}, {-3, -1, 4},
5188 {+2, -3, 4}, {+3, -1, 4},
5189 {-2, +3, 4}, {-3, +1, 4},
5190 {+2, +3, 4}, {+3, +1, 4},
5191 {-2, -2, 5}, {-3, 0, 5}, {-2, +2, 5},
5192 {+2, -2, 5}, {+3, 0, 5}, {+2, +2, 5},
5193 {-2, -1, 6}, {-2, +1, 6},
5194 {+2, -1, 6}, {+2, +1, 6},
5195 {-2, 0, 7}, {+2, 0, 7},
5199 int y, x, y1, x1, y2, x2, xval, yval;
5208 vault_aux_type *n_ptr = pick_vault_type(pit_types, ROOM_PIT);
5210 /* Only in Angband */
5211 if (dungeon_type != 1) return;
5213 /* Try to allocate space for room. */
5214 if (!room_alloc(25, 13, TRUE, by0, bx0, &xval, &yval)) return;
5216 /* No type available */
5219 /* Process a preparation function if necessary */
5220 if (n_ptr->prep_func) (*(n_ptr->prep_func))();
5228 /* Fill with inner walls */
5229 for (y = y1 - 1; y <= y2 + 1; y++)
5231 for (x = x1 - 1; x <= x2 + 1; x++)
5233 c_ptr = &cave[y][x];
5234 place_solid_grid(c_ptr);
5238 /* Place the floor area 1 */
5239 for (x = x1 + 3; x <= x2 - 3; x++)
5241 c_ptr = &cave[yval-2][x];
5242 place_floor_grid(c_ptr);
5243 c_ptr->info |= (CAVE_ROOM);
5244 add_cave_info(yval-2, x, CAVE_ICKY);
5246 c_ptr = &cave[yval+2][x];
5247 place_floor_grid(c_ptr);
5248 c_ptr->info |= (CAVE_ROOM);
5249 add_cave_info(yval+2, x, CAVE_ICKY);
5252 /* Place the floor area 2 */
5253 for (x = x1 + 5; x <= x2 - 5; x++)
5255 c_ptr = &cave[yval-3][x];
5256 place_floor_grid(c_ptr);
5257 c_ptr->info |= (CAVE_ROOM);
5258 add_cave_info(yval-3, x, CAVE_ICKY);
5260 c_ptr = &cave[yval+3][x];
5261 place_floor_grid(c_ptr);
5262 c_ptr->info |= (CAVE_ROOM);
5263 add_cave_info(yval+3, x, CAVE_ICKY);
5267 for (x = x1; x <= x2; x++)
5269 c_ptr = &cave[yval][x];
5270 place_floor_grid(c_ptr);
5271 c_ptr = &cave[y1][x];
5272 place_floor_grid(c_ptr);
5273 c_ptr = &cave[y2][x];
5274 place_floor_grid(c_ptr);
5277 /* Random corridor */
5280 for (y = y1; y <= yval; y++)
5282 c_ptr = &cave[y][x1];
5283 place_floor_grid(c_ptr);
5285 for (y = yval; y <= y2 + 1; y++)
5287 c_ptr = &cave[y][x2];
5288 place_floor_grid(c_ptr);
5293 for (y = yval; y <= y2 + 1; y++)
5295 c_ptr = &cave[y][x1];
5296 place_floor_grid(c_ptr);
5298 for (y = y1; y <= yval; y++)
5300 c_ptr = &cave[y][x2];
5301 place_floor_grid(c_ptr);
5305 /* Place the outer walls */
5306 for (y = y1 - 1; y <= y2 + 1; y++)
5308 c_ptr = &cave[y][x1 - 1];
5309 place_outer_grid(c_ptr);
5310 c_ptr = &cave[y][x2 + 1];
5311 place_outer_grid(c_ptr);
5313 for (x = x1 - 1; x <= x2 + 1; x++)
5315 c_ptr = &cave[y1 - 1][x];
5316 place_outer_grid(c_ptr);
5317 c_ptr = &cave[y2 + 1][x];
5318 place_outer_grid(c_ptr);
5321 /* Place the wall open trap */
5322 cave[yval][xval].feat = FEAT_INVIS;
5323 add_cave_info(yval, xval, CAVE_ROOM);
5325 /* Prepare allocation table */
5326 get_mon_num_prep(n_ptr->hook_func, vault_aux_trapped_pit);
5328 /* Pick some monster types */
5329 for (i = 0; i < 16; i++)
5331 int r_idx = 0, attempts = 100;
5335 /* Get a (hard) monster type */
5336 r_idx = get_mon_num(dun_level + 0);
5338 /* Decline incorrect alignment */
5339 if (((align < 0) && (r_info[r_idx].flags3 & RF3_GOOD)) ||
5340 ((align > 0) && (r_info[r_idx].flags3 & RF3_EVIL)))
5345 /* Accept this monster */
5349 /* Notice failure */
5350 if (!r_idx || !attempts) return;
5352 /* Note the alignment */
5353 if (r_info[r_idx].flags3 & RF3_GOOD) align++;
5354 else if (r_info[r_idx].flags3 & RF3_EVIL) align--;
5359 /* Sort the entries */
5360 for (i = 0; i < 16 - 1; i++)
5362 /* Sort the entries */
5363 for (j = 0; j < 16 - 1; j++)
5368 int p1 = r_info[what[i1]].level;
5369 int p2 = r_info[what[i2]].level;
5375 what[i1] = what[i2];
5385 msg_format("%s¤Î櫥ԥåÈ", n_ptr->name);
5388 msg_format("Trapped monster pit (%s)", n_ptr->name);
5392 /* Select the entries */
5393 for (i = 0; i < 8; i++)
5395 /* Every other entry */
5396 what[i] = what[i * 2];
5401 msg_print(r_name + r_info[what[i]].name);
5405 /* Increase the level rating */
5408 /* (Sometimes) Cause a "special feeling" (for "Monster Pits") */
5409 if ((dun_level <= 40) && (randint1(dun_level * dun_level + 50) < 300))
5411 good_item_flag = TRUE;
5415 for (i = 0; placing[i][2] >= 0; i++)
5417 y = yval + placing[i][0];
5418 x = xval + placing[i][1];
5419 place_monster_aux(0, y, x, what[placing[i][2]], PM_NO_KAGE);
5425 * Attempt to build a room of the given type at the given block
5427 * Note that we restrict the number of "crowded" rooms to reduce
5428 * the chance of overflowing the monster list during level creation.
5430 bool room_build(int by0, int bx0, int typ)
5432 /* Restrict level */
5433 if ((dun_level < roomdep[typ]) && !ironman_rooms) return (FALSE);
5435 /* Restrict "crowded" rooms */
5436 if ((dun->crowded >= 2) && ((typ == 5) || (typ == 6) || (typ == 13))) return (FALSE);
5441 /* Build an appropriate room */
5442 case 13: build_type13(by0, bx0); break;
5443 case 12: build_type12(by0, bx0); break;
5444 case 11: build_type11(by0, bx0); break;
5445 case 10: build_type10(by0, bx0); break;
5446 case 9: build_type9(by0, bx0); break;
5447 case 8: build_type8(by0, bx0); break;
5448 case 7: build_type7(by0, bx0); break;
5449 case 6: build_type6(by0, bx0, FALSE); break;
5450 case 5: build_type5(by0, bx0, FALSE); break;
5451 case 4: build_type4(by0, bx0); break;
5452 case 3: build_type3(by0, bx0); break;
5453 case 2: build_type2(by0, bx0); break;
5454 case 1: build_type1(by0, bx0); break;
5457 default: return (FALSE);