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) */
41 static void place_locked_door(int y, int x)
43 if (d_info[dungeon_type].flags1 & DF1_NO_DOORS)
45 place_floor_bold(y, x);
49 set_cave_feat(y, x, FEAT_DOOR_HEAD+randint1(7));
50 cave[y][x].info &= ~(CAVE_FLOOR);
54 static void place_secret_door(int y, int x)
56 if (d_info[dungeon_type].flags1 & DF1_NO_DOORS)
58 place_floor_bold(y, x);
62 set_cave_feat(y, x, FEAT_SECRET);
63 cave[y][x].info &= ~(CAVE_FLOOR);
68 * This funtion makes a very small room centred at (x0, y0)
69 * This is used in crypts, and random elemental vaults.
71 * Note - this should be used only on allocated regions
72 * within another room.
74 static void build_small_room(int x0, int y0)
78 for (y = y0 - 1; y <= y0 + 1; y++)
80 place_inner_bold(y, x0 - 1);
81 place_inner_bold(y, x0 + 1);
84 for (x = x0 - 1; x <= x0 + 1; x++)
86 place_inner_bold(y0 - 1, x);
87 place_inner_bold(y0 + 1, x);
90 /* Place a secret door on one side */
93 case 0: place_secret_door(y0, x0 - 1); break;
94 case 1: place_secret_door(y0, x0 + 1); break;
95 case 2: place_secret_door(y0 - 1, x0); break;
96 case 3: place_secret_door(y0 + 1, x0); break;
99 /* Add inner open space */
100 place_floor_bold(y0, x0);
105 * This function tunnels around a room if
106 * it will cut off part of a cave system.
108 static void check_room_boundary(int x1, int y1, int x2, int y2)
111 bool old_is_floor, new_is_floor;
117 old_is_floor = get_is_floor(x1 - 1, y1);
120 * Count the number of floor-wall boundaries around the room
121 * Note: diagonal squares are ignored since the player can move diagonally
122 * to bypass these if needed.
125 /* Above the top boundary */
126 for (x = x1; x <= x2; x++)
128 new_is_floor = get_is_floor(x, y1 - 1);
130 /* Increment counter if they are different */
131 if (new_is_floor != old_is_floor) count++;
133 old_is_floor = new_is_floor;
137 for (y = y1; y <= y2; y++)
139 new_is_floor = get_is_floor(x2 + 1, y);
141 /* increment counter if they are different */
142 if (new_is_floor != old_is_floor) count++;
144 old_is_floor = new_is_floor;
147 /* Bottom boundary */
148 for (x = x2; x >= x1; x--)
150 new_is_floor = get_is_floor(x, y2 + 1);
152 /* increment counter if they are different */
153 if (new_is_floor != old_is_floor) count++;
155 old_is_floor = new_is_floor;
159 for (y = y2; y >= y1; y--)
161 new_is_floor = get_is_floor(x1 - 1, y);
163 /* increment counter if they are different */
164 if (new_is_floor != old_is_floor) count++;
166 old_is_floor = new_is_floor;
169 /* If all the same, or only one connection exit. */
170 if (count <= 2) return;
173 /* Tunnel around the room so to prevent problems with caves */
174 for (y = y1; y <= y2; y++)
176 for (x = x1; x <= x2; x++)
185 * This function is used to allocate the space needed by a room in the room_map
187 * x, y represent the size of the room (0...x-1) by (0...y-1).
188 * crowded is used to denote a monset nest.
189 * by0, bx0 are the positions in the room_map array given to the build_type'x'
191 * xx, yy are the returned center of the allocated room in coordinates for
192 * cave.feat and cave.info etc.
194 static bool room_alloc(int x, int y, bool crowded, int by0, int bx0, int *xx, int *yy)
196 int temp, bx1, bx2, by1, by2, by, bx;
198 /* Calculate number of room_map squares to allocate */
200 /* temp is total number along width */
201 temp = ((x - 1) / BLOCK_WID) + 1;
203 /* bx2 = ending block */
204 bx2 = temp / 2 + bx0;
206 /* bx1 = starting block (Note: rounding taken care of here.) */
207 bx1 = bx2 + 1 - temp;
209 /* temp is total number along height */
210 temp = ((y - 1) / BLOCK_HGT) + 1;
212 /* by2 = ending block */
213 by2 = temp / 2 + by0;
215 /* by1 = starting block */
216 by1 = by2 + 1 - temp;
219 /* Never run off the screen */
220 if ((by1 < 0) || (by2 >= dun->row_rooms)) return (FALSE);
221 if ((bx1 < 0) || (bx2 >= dun->col_rooms)) return (FALSE);
223 /* Verify open space */
224 for (by = by1; by <= by2; by++)
226 for (bx = bx1; bx <= bx2; bx++)
228 if (dun->room_map[by][bx]) return (FALSE);
232 /* It is *extremely* important that the following calculation */
233 /* be *exactly* correct to prevent memory errors XXX XXX XXX */
235 /* Acquire the location of the room */
236 *yy = ((by1 + by2 + 1) * BLOCK_HGT) / 2;
237 *xx = ((bx1 + bx2 + 1) * BLOCK_WID) / 2;
240 /* Save the room location */
241 if (dun->cent_n < CENT_MAX)
243 dun->cent[dun->cent_n].y = *yy;
244 dun->cent[dun->cent_n].x = *xx;
248 /* Reserve some blocks */
249 for (by = by1; by <= by2; by++)
251 for (bx = bx1; bx <= bx2; bx++)
253 dun->room_map[by][bx] = TRUE;
257 /* Count "crowded" rooms */
258 if (crowded) dun->crowded++;
261 * Hack- See if room will cut off a cavern.
262 * If so, fix by tunneling outside the room in such a way as to connect the caves.
264 check_room_boundary(*xx - x / 2 - 1, *yy - y / 2 - 1,
265 *xx + (x - 1) / 2 + 1, *yy + (y - 1) / 2 + 1);
272 * Room building routines.
278 * 4 -- large room with features
282 * 8 -- greater vaults
284 * 10 -- random vaults
285 * 11 -- circular rooms
291 * Type 1 -- normal rectangular rooms
293 static void build_type1(int by0, int bx0)
295 int y, x, y2, x2, yval, xval;
296 int y1, x1, xsize, ysize;
302 /* Pick a room size */
311 /* Try to allocate space for room. If fails, exit */
312 if (!room_alloc(xsize + 2, ysize + 2, FALSE, by0, bx0, &xval, &yval)) return;
314 /* Choose lite or dark */
315 light = ((dun_level <= randint1(25)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS));
318 /* Get corner values */
319 y1 = yval - ysize / 2;
320 x1 = xval - xsize / 2;
321 y2 = yval + (ysize - 1) / 2;
322 x2 = xval + (xsize - 1) / 2;
325 /* Place a full floor under the room */
326 for (y = y1 - 1; y <= y2 + 1; y++)
328 for (x = x1 - 1; x <= x2 + 1; x++)
331 place_floor_grid(c_ptr);
332 c_ptr->info |= (CAVE_ROOM);
333 if (light) c_ptr->info |= (CAVE_GLOW);
337 /* Walls around the room */
338 for (y = y1 - 1; y <= y2 + 1; y++)
340 c_ptr = &cave[y][x1 - 1];
341 place_outer_grid(c_ptr);
342 c_ptr = &cave[y][x2 + 1];
343 place_outer_grid(c_ptr);
345 for (x = x1 - 1; x <= x2 + 1; x++)
347 c_ptr = &cave[y1 - 1][x];
348 place_outer_grid(c_ptr);
349 c_ptr = &cave[y2 + 1][x];
350 place_outer_grid(c_ptr);
354 /* Hack -- Occasional pillar room */
357 for (y = y1; y <= y2; y += 2)
359 for (x = x1; x <= x2; x += 2)
362 place_inner_grid(c_ptr);
367 /* Hack -- Occasional room with four pillars */
368 else if (one_in_(20))
370 if ((y1 + 4 < y2) && (x1 + 4 < x2))
372 c_ptr = &cave[y1 + 1][x1 + 1];
373 place_inner_grid(c_ptr);
375 c_ptr = &cave[y1 + 1][x2 - 1];
376 place_inner_grid(c_ptr);
378 c_ptr = &cave[y2 - 1][x1 + 1];
379 place_inner_grid(c_ptr);
381 c_ptr = &cave[y2 - 1][x2 - 1];
382 place_inner_grid(c_ptr);
386 /* Hack -- Occasional ragged-edge room */
387 else if (one_in_(50))
389 for (y = y1 + 2; y <= y2 - 2; y += 2)
391 c_ptr = &cave[y][x1];
392 place_inner_grid(c_ptr);
393 c_ptr = &cave[y][x2];
394 place_inner_grid(c_ptr);
396 for (x = x1 + 2; x <= x2 - 2; x += 2)
398 c_ptr = &cave[y1][x];
399 place_inner_grid(c_ptr);
400 c_ptr = &cave[y2][x];
401 place_inner_grid(c_ptr);
404 /* Hack -- Occasional divided room */
405 else if (one_in_(50))
407 if (randint1(100) < 50)
409 /* Horizontal wall */
410 for (x = x1; x <= x2; x++)
412 place_inner_bold(yval, x);
415 /* Prevent edge of wall from being tunneled */
416 place_solid_bold(yval, x1 - 1);
417 place_solid_bold(yval, x2 + 1);
422 for (y = y1; y <= y2; y++)
424 place_inner_bold(y, xval);
427 /* Prevent edge of wall from being tunneled */
428 place_solid_bold(y1 - 1, xval);
429 place_solid_bold(y2 + 1, xval);
432 place_random_door(yval, xval);
438 * Type 2 -- Overlapping rectangular rooms
440 static void build_type2(int by0, int bx0)
442 int y, x, xval, yval;
443 int y1a, x1a, y2a, x2a;
444 int y1b, x1b, y2b, x2b;
449 /* Try to allocate space for room. If fails, exit */
450 if (!room_alloc(25, 11, FALSE, by0, bx0, &xval, &yval)) return;
452 /* Choose lite or dark */
453 light = ((dun_level <= randint1(25)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS));
455 /* Determine extents of the first room */
456 y1a = yval - randint1(4);
457 y2a = yval + randint1(3);
458 x1a = xval - randint1(11);
459 x2a = xval + randint1(10);
461 /* Determine extents of the second room */
462 y1b = yval - randint1(3);
463 y2b = yval + randint1(4);
464 x1b = xval - randint1(10);
465 x2b = xval + randint1(11);
468 /* Place a full floor for room "a" */
469 for (y = y1a - 1; y <= y2a + 1; y++)
471 for (x = x1a - 1; x <= x2a + 1; x++)
474 place_floor_grid(c_ptr);
475 c_ptr->info |= (CAVE_ROOM);
476 if (light) c_ptr->info |= (CAVE_GLOW);
480 /* Place a full floor for room "b" */
481 for (y = y1b - 1; y <= y2b + 1; y++)
483 for (x = x1b - 1; x <= x2b + 1; x++)
486 place_floor_grid(c_ptr);
487 c_ptr->info |= (CAVE_ROOM);
488 if (light) c_ptr->info |= (CAVE_GLOW);
493 /* Place the walls around room "a" */
494 for (y = y1a - 1; y <= y2a + 1; y++)
496 c_ptr = &cave[y][x1a - 1];
497 place_outer_grid(c_ptr);
498 c_ptr = &cave[y][x2a + 1];
499 place_outer_grid(c_ptr);
501 for (x = x1a - 1; x <= x2a + 1; x++)
503 c_ptr = &cave[y1a - 1][x];
504 place_outer_grid(c_ptr);
505 c_ptr = &cave[y2a + 1][x];
506 place_outer_grid(c_ptr);
509 /* Place the walls around room "b" */
510 for (y = y1b - 1; y <= y2b + 1; y++)
512 c_ptr = &cave[y][x1b - 1];
513 place_outer_grid(c_ptr);
514 c_ptr = &cave[y][x2b + 1];
515 place_outer_grid(c_ptr);
517 for (x = x1b - 1; x <= x2b + 1; x++)
519 c_ptr = &cave[y1b - 1][x];
520 place_outer_grid(c_ptr);
521 c_ptr = &cave[y2b + 1][x];
522 place_outer_grid(c_ptr);
527 /* Replace the floor for room "a" */
528 for (y = y1a; y <= y2a; y++)
530 for (x = x1a; x <= x2a; x++)
533 place_floor_grid(c_ptr);
537 /* Replace the floor for room "b" */
538 for (y = y1b; y <= y2b; y++)
540 for (x = x1b; x <= x2b; x++)
543 place_floor_grid(c_ptr);
551 * Type 3 -- Cross shaped rooms
553 * Builds a room at a row, column coordinate
555 * Room "a" runs north/south, and Room "b" runs east/east
556 * So the "central pillar" runs from x1a, y1b to x2a, y2b.
558 * Note that currently, the "center" is always 3x3, but I think that
559 * the code below will work (with "bounds checking") for 5x5, or even
560 * for unsymetric values like 4x3 or 5x3 or 3x4 or 3x5, or even larger.
562 static void build_type3(int by0, int bx0)
564 int y, x, dy, dx, wy, wx;
565 int y1a, x1a, y2a, x2a;
566 int y1b, x1b, y2b, x2b;
572 /* Try to allocate space for room. */
573 if (!room_alloc(25, 11, FALSE, by0, bx0, &xval, &yval)) return;
575 /* Choose lite or dark */
576 light = ((dun_level <= randint1(25)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS));
578 /* For now, always 3x3 */
581 /* Pick max vertical size (at most 4) */
582 dy = rand_range(3, 4);
584 /* Pick max horizontal size (at most 15) */
585 dx = rand_range(3, 11);
588 /* Determine extents of the north/south room */
594 /* Determine extents of the east/west room */
601 /* Place a full floor for room "a" */
602 for (y = y1a - 1; y <= y2a + 1; y++)
604 for (x = x1a - 1; x <= x2a + 1; x++)
607 place_floor_grid(c_ptr);
608 c_ptr->info |= (CAVE_ROOM);
609 if (light) c_ptr->info |= (CAVE_GLOW);
613 /* Place a full floor for room "b" */
614 for (y = y1b - 1; y <= y2b + 1; y++)
616 for (x = x1b - 1; x <= x2b + 1; x++)
619 place_floor_grid(c_ptr);
620 c_ptr->info |= (CAVE_ROOM);
621 if (light) c_ptr->info |= (CAVE_GLOW);
626 /* Place the walls around room "a" */
627 for (y = y1a - 1; y <= y2a + 1; y++)
629 c_ptr = &cave[y][x1a - 1];
630 place_outer_grid(c_ptr);
631 c_ptr = &cave[y][x2a + 1];
632 place_outer_grid(c_ptr);
634 for (x = x1a - 1; x <= x2a + 1; x++)
636 c_ptr = &cave[y1a - 1][x];
637 place_outer_grid(c_ptr);
638 c_ptr = &cave[y2a + 1][x];
639 place_outer_grid(c_ptr);
642 /* Place the walls around room "b" */
643 for (y = y1b - 1; y <= y2b + 1; y++)
645 c_ptr = &cave[y][x1b - 1];
646 place_outer_grid(c_ptr);
647 c_ptr = &cave[y][x2b + 1];
648 place_outer_grid(c_ptr);
650 for (x = x1b - 1; x <= x2b + 1; x++)
652 c_ptr = &cave[y1b - 1][x];
653 place_outer_grid(c_ptr);
654 c_ptr = &cave[y2b + 1][x];
655 place_outer_grid(c_ptr);
659 /* Replace the floor for room "a" */
660 for (y = y1a; y <= y2a; y++)
662 for (x = x1a; x <= x2a; x++)
665 place_floor_grid(c_ptr);
669 /* Replace the floor for room "b" */
670 for (y = y1b; y <= y2b; y++)
672 for (x = x1b; x <= x2b; x++)
675 place_floor_grid(c_ptr);
681 /* Special features (3/4) */
684 /* Large solid middle pillar */
687 for (y = y1b; y <= y2b; y++)
689 for (x = x1a; x <= x2a; x++)
692 place_inner_grid(c_ptr);
698 /* Inner treasure vault */
701 /* Build the vault */
702 for (y = y1b; y <= y2b; y++)
704 c_ptr = &cave[y][x1a];
705 place_inner_grid(c_ptr);
706 c_ptr = &cave[y][x2a];
707 place_inner_grid(c_ptr);
709 for (x = x1a; x <= x2a; x++)
711 c_ptr = &cave[y1b][x];
712 place_inner_grid(c_ptr);
713 c_ptr = &cave[y2b][x];
714 place_inner_grid(c_ptr);
717 /* Place a secret door on the inner room */
720 case 0: place_secret_door(y1b, xval); break;
721 case 1: place_secret_door(y2b, xval); break;
722 case 2: place_secret_door(yval, x1a); break;
723 case 3: place_secret_door(yval, x2a); break;
726 /* Place a treasure in the vault */
727 place_object(yval, xval, FALSE, FALSE);
729 /* Let's guard the treasure well */
730 vault_monsters(yval, xval, randint0(2) + 3);
732 /* Traps naturally */
733 vault_traps(yval, xval, 4, 4, randint0(3) + 2);
741 /* Occasionally pinch the center shut */
744 /* Pinch the east/west sides */
745 for (y = y1b; y <= y2b; y++)
747 if (y == yval) continue;
748 c_ptr = &cave[y][x1a - 1];
749 place_inner_grid(c_ptr);
750 c_ptr = &cave[y][x2a + 1];
751 place_inner_grid(c_ptr);
754 /* Pinch the north/south sides */
755 for (x = x1a; x <= x2a; x++)
757 if (x == xval) continue;
758 c_ptr = &cave[y1b - 1][x];
759 place_inner_grid(c_ptr);
760 c_ptr = &cave[y2b + 1][x];
761 place_inner_grid(c_ptr);
764 /* Sometimes shut using secret doors */
767 place_secret_door(yval, x1a - 1);
768 place_secret_door(yval, x2a + 1);
769 place_secret_door(y1b - 1, xval);
770 place_secret_door(y2b + 1, xval);
774 /* Occasionally put a "plus" in the center */
777 c_ptr = &cave[yval][xval];
778 place_inner_grid(c_ptr);
779 c_ptr = &cave[y1b][xval];
780 place_inner_grid(c_ptr);
781 c_ptr = &cave[y2b][xval];
782 place_inner_grid(c_ptr);
783 c_ptr = &cave[yval][x1a];
784 place_inner_grid(c_ptr);
785 c_ptr = &cave[yval][x2a];
786 place_inner_grid(c_ptr);
789 /* Occasionally put a pillar in the center */
792 c_ptr = &cave[yval][xval];
793 place_inner_grid(c_ptr);
803 * Type 4 -- Large room with inner features
805 * Possible sub-types:
806 * 1 - Just an inner room with one door
807 * 2 - An inner room within an inner room
808 * 3 - An inner room with pillar(s)
809 * 4 - Inner room has a maze
810 * 5 - A set of four inner rooms
812 static void build_type4(int by0, int bx0)
815 int y2, x2, tmp, yval, xval;
820 /* Try to allocate space for room. */
821 if (!room_alloc(25, 11, FALSE, by0, bx0, &xval, &yval)) return;
823 /* Choose lite or dark */
824 light = ((dun_level <= randint1(25)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS));
832 /* Place a full floor under the room */
833 for (y = y1 - 1; y <= y2 + 1; y++)
835 for (x = x1 - 1; x <= x2 + 1; x++)
838 place_floor_grid(c_ptr);
839 c_ptr->info |= (CAVE_ROOM);
840 if (light) c_ptr->info |= (CAVE_GLOW);
845 for (y = y1 - 1; y <= y2 + 1; y++)
847 c_ptr = &cave[y][x1 - 1];
848 place_outer_grid(c_ptr);
849 c_ptr = &cave[y][x2 + 1];
850 place_outer_grid(c_ptr);
852 for (x = x1 - 1; x <= x2 + 1; x++)
854 c_ptr = &cave[y1 - 1][x];
855 place_outer_grid(c_ptr);
856 c_ptr = &cave[y2 + 1][x];
857 place_outer_grid(c_ptr);
867 /* The inner walls */
868 for (y = y1 - 1; y <= y2 + 1; y++)
870 c_ptr = &cave[y][x1 - 1];
871 place_inner_grid(c_ptr);
872 c_ptr = &cave[y][x2 + 1];
873 place_inner_grid(c_ptr);
875 for (x = x1 - 1; x <= x2 + 1; x++)
877 c_ptr = &cave[y1 - 1][x];
878 place_inner_grid(c_ptr);
879 c_ptr = &cave[y2 + 1][x];
880 place_inner_grid(c_ptr);
884 /* Inner room variations */
887 /* Just an inner room with a monster */
890 /* Place a secret door */
893 case 1: place_secret_door(y1 - 1, xval); break;
894 case 2: place_secret_door(y2 + 1, xval); break;
895 case 3: place_secret_door(yval, x1 - 1); break;
896 case 4: place_secret_door(yval, x2 + 1); break;
899 /* Place a monster in the room */
900 vault_monsters(yval, xval, 1);
905 /* Treasure Vault (with a door) */
908 /* Place a secret door */
911 case 1: place_secret_door(y1 - 1, xval); break;
912 case 2: place_secret_door(y2 + 1, xval); break;
913 case 3: place_secret_door(yval, x1 - 1); break;
914 case 4: place_secret_door(yval, x2 + 1); break;
917 /* Place another inner room */
918 for (y = yval - 1; y <= yval + 1; y++)
920 for (x = xval - 1; x <= xval + 1; x++)
922 if ((x == xval) && (y == yval)) continue;
924 place_inner_grid(c_ptr);
928 /* Place a locked door on the inner room */
931 case 1: place_locked_door(yval - 1, xval); break;
932 case 2: place_locked_door(yval + 1, xval); break;
933 case 3: place_locked_door(yval, xval - 1); break;
934 case 4: place_locked_door(yval, xval + 1); break;
937 /* Monsters to guard the "treasure" */
938 vault_monsters(yval, xval, randint1(3) + 2);
941 if (randint0(100) < 80)
943 place_object(yval, xval, FALSE, FALSE);
949 place_random_stairs(yval, xval);
952 /* Traps to protect the treasure */
953 vault_traps(yval, xval, 4, 10, 2 + randint1(3));
958 /* Inner pillar(s). */
961 /* Place a secret door */
964 case 1: place_secret_door(y1 - 1, xval); break;
965 case 2: place_secret_door(y2 + 1, xval); break;
966 case 3: place_secret_door(yval, x1 - 1); break;
967 case 4: place_secret_door(yval, x2 + 1); break;
970 /* Large Inner Pillar */
971 for (y = yval - 1; y <= yval + 1; y++)
973 for (x = xval - 1; x <= xval + 1; x++)
976 place_inner_grid(c_ptr);
980 /* Occasionally, two more Large Inner Pillars */
984 for (y = yval - 1; y <= yval + 1; y++)
986 for (x = xval - 5 - tmp; x <= xval - 3 - tmp; x++)
989 place_inner_grid(c_ptr);
991 for (x = xval + 3 + tmp; x <= xval + 5 + tmp; x++)
994 place_inner_grid(c_ptr);
999 /* Occasionally, some Inner rooms */
1002 /* Long horizontal walls */
1003 for (x = xval - 5; x <= xval + 5; x++)
1005 c_ptr = &cave[yval - 1][x];
1006 place_inner_grid(c_ptr);
1007 c_ptr = &cave[yval + 1][x];
1008 place_inner_grid(c_ptr);
1011 /* Close off the left/right edges */
1012 c_ptr = &cave[yval][xval - 5];
1013 place_inner_grid(c_ptr);
1014 c_ptr = &cave[yval][xval + 5];
1015 place_inner_grid(c_ptr);
1017 /* Secret doors (random top/bottom) */
1018 place_secret_door(yval - 3 + (randint1(2) * 2), xval - 3);
1019 place_secret_door(yval - 3 + (randint1(2) * 2), xval + 3);
1022 vault_monsters(yval, xval - 2, randint1(2));
1023 vault_monsters(yval, xval + 2, randint1(2));
1026 if (one_in_(3)) place_object(yval, xval - 2, FALSE, FALSE);
1027 if (one_in_(3)) place_object(yval, xval + 2, FALSE, FALSE);
1036 /* Place a secret door */
1037 switch (randint1(4))
1039 case 1: place_secret_door(y1 - 1, xval); break;
1040 case 2: place_secret_door(y2 + 1, xval); break;
1041 case 3: place_secret_door(yval, x1 - 1); break;
1042 case 4: place_secret_door(yval, x2 + 1); break;
1045 /* Maze (really a checkerboard) */
1046 for (y = y1; y <= y2; y++)
1048 for (x = x1; x <= x2; x++)
1052 c_ptr = &cave[y][x];
1053 place_inner_grid(c_ptr);
1058 /* Monsters just love mazes. */
1059 vault_monsters(yval, xval - 5, randint1(3));
1060 vault_monsters(yval, xval + 5, randint1(3));
1062 /* Traps make them entertaining. */
1063 vault_traps(yval, xval - 3, 2, 8, randint1(3));
1064 vault_traps(yval, xval + 3, 2, 8, randint1(3));
1066 /* Mazes should have some treasure too. */
1067 vault_objects(yval, xval, 3);
1072 /* Four small rooms. */
1076 for (y = y1; y <= y2; y++)
1078 c_ptr = &cave[y][xval];
1079 place_inner_grid(c_ptr);
1081 for (x = x1; x <= x2; x++)
1083 c_ptr = &cave[yval][x];
1084 place_inner_grid(c_ptr);
1087 /* Doors into the rooms */
1088 if (randint0(100) < 50)
1090 int i = randint1(10);
1091 place_secret_door(y1 - 1, xval - i);
1092 place_secret_door(y1 - 1, xval + i);
1093 place_secret_door(y2 + 1, xval - i);
1094 place_secret_door(y2 + 1, xval + i);
1098 int i = randint1(3);
1099 place_secret_door(yval + i, x1 - 1);
1100 place_secret_door(yval - i, x1 - 1);
1101 place_secret_door(yval + i, x2 + 1);
1102 place_secret_door(yval - i, x2 + 1);
1105 /* Treasure, centered at the center of the cross */
1106 vault_objects(yval, xval, 2 + randint1(2));
1108 /* Gotta have some monsters. */
1109 vault_monsters(yval + 1, xval - 4, randint1(4));
1110 vault_monsters(yval + 1, xval + 4, randint1(4));
1111 vault_monsters(yval - 1, xval - 4, randint1(4));
1112 vault_monsters(yval - 1, xval + 4, randint1(4));
1121 * The following functions are used to determine if the given monster
1122 * is appropriate for inclusion in a monster nest or monster pit or
1125 * None of the pits/nests are allowed to include "unique" monsters.
1130 * Monster validation macro
1132 * Line 1 -- forbid town monsters
1133 * Line 2 -- forbid uniques
1134 * Line 3 -- forbid aquatic monsters
1136 #define vault_monster_okay(I) \
1137 (monster_dungeon(I) && \
1138 !(r_info[I].flags1 & RF1_UNIQUE) && \
1139 !(r_info[I].flags7 & RF7_UNIQUE2) && \
1140 !(r_info[I].flags3 & RF3_RES_ALL) && \
1141 !(r_info[I].flags7 & RF7_AQUATIC))
1144 /* Race index for "monster pit (clone)" */
1145 static int vault_aux_race;
1147 /* Race index for "monster pit (symbol clone)" */
1148 static char vault_aux_char;
1150 /* Breath mask for "monster pit (dragon)" */
1151 static u32b vault_aux_dragon_mask4;
1155 * Helper monster selection function
1157 static bool vault_aux_simple(int r_idx)
1160 return (vault_monster_okay(r_idx));
1165 * Helper function for "monster nest (jelly)"
1167 static bool vault_aux_jelly(int r_idx)
1169 monster_race *r_ptr = &r_info[r_idx];
1171 /* Validate the monster */
1172 if (!vault_monster_okay(r_idx)) return (FALSE);
1174 if (r_ptr->flags2 & (RF2_KILL_BODY)) return (FALSE);
1176 /* Also decline evil jellies (like death molds and shoggoths) */
1177 if (r_ptr->flags3 & (RF3_EVIL)) return (FALSE);
1179 /* Require icky thing, jelly, mold, or mushroom */
1180 if (!strchr("ijm,", r_ptr->d_char)) return (FALSE);
1188 * Helper function for "monster nest (animal)"
1190 static bool vault_aux_animal(int r_idx)
1192 monster_race *r_ptr = &r_info[r_idx];
1194 /* Validate the monster */
1195 if (!vault_monster_okay(r_idx)) return (FALSE);
1197 /* Require "animal" flag */
1198 if (!(r_ptr->flags3 & (RF3_ANIMAL))) return (FALSE);
1206 * Helper function for "monster nest (undead)"
1208 static bool vault_aux_undead(int r_idx)
1210 monster_race *r_ptr = &r_info[r_idx];
1212 /* Validate the monster */
1213 if (!vault_monster_okay(r_idx)) return (FALSE);
1215 /* Require Undead */
1216 if (!(r_ptr->flags3 & (RF3_UNDEAD))) return (FALSE);
1224 * Helper function for "monster nest (chapel)"
1226 static bool vault_aux_chapel_g(int r_idx)
1228 static int chapel_list[] = {
1229 MON_NOV_PRIEST, MON_NOV_PALADIN, MON_NOV_PRIEST_G, MON_NOV_PALADIN_G,
1230 MON_PRIEST, MON_JADE_MONK, MON_IVORY_MONK, MON_ULTRA_PALADIN,
1231 MON_EBONY_MONK, MON_KNI_TEMPLAR, MON_PALADIN, MON_TOPAZ_MONK,
1236 monster_race *r_ptr = &r_info[r_idx];
1238 /* Validate the monster */
1239 if (!vault_monster_okay(r_idx)) return (FALSE);
1241 if (r_ptr->flags3 & (RF3_EVIL)) return (FALSE);
1242 if ((r_idx == MON_A_GOLD) || (r_idx == MON_A_SILVER)) return (FALSE);
1244 /* Require "priest" or Angel */
1246 if (r_ptr->d_char == 'A') return TRUE;
1248 for (i = 0; chapel_list[i]; i++)
1249 if (r_idx == chapel_list[i]) return TRUE;
1256 * Helper function for "monster nest (kennel)"
1258 static bool vault_aux_kennel(int r_idx)
1260 monster_race *r_ptr = &r_info[r_idx];
1262 /* Validate the monster */
1263 if (!vault_monster_okay(r_idx)) return (FALSE);
1265 /* Require a Zephyr Hound or a dog */
1266 if (!strchr("CZ", r_ptr->d_char)) return (FALSE);
1274 * Helper function for "monster nest (mimic)"
1276 static bool vault_aux_mimic(int r_idx)
1278 monster_race *r_ptr = &r_info[r_idx];
1280 /* Validate the monster */
1281 if (!vault_monster_okay(r_idx)) return (FALSE);
1284 if (!strchr("!|$?=", r_ptr->d_char)) return (FALSE);
1291 * Helper function for "monster nest (clone)"
1293 static bool vault_aux_clone(int r_idx)
1295 /* Validate the monster */
1296 if (!vault_monster_okay(r_idx)) return (FALSE);
1298 return (r_idx == vault_aux_race);
1303 * Helper function for "monster nest (symbol clone)"
1305 static bool vault_aux_symbol_e(int r_idx)
1307 monster_race *r_ptr = &r_info[r_idx];
1309 /* Validate the monster */
1310 if (!vault_monster_okay(r_idx)) return (FALSE);
1312 if (r_ptr->flags2 & (RF2_KILL_BODY)) return (FALSE);
1314 if (r_ptr->flags3 & (RF3_GOOD)) return (FALSE);
1316 /* Decline incorrect symbol */
1317 if (r_ptr->d_char != vault_aux_char) return (FALSE);
1325 * Helper function for "monster nest (symbol clone)"
1327 static bool vault_aux_symbol_g(int r_idx)
1329 monster_race *r_ptr = &r_info[r_idx];
1331 /* Validate the monster */
1332 if (!vault_monster_okay(r_idx)) return (FALSE);
1334 if (r_ptr->flags2 & (RF2_KILL_BODY)) return (FALSE);
1336 if (r_ptr->flags3 & (RF3_EVIL)) return (FALSE);
1338 /* Decline incorrect symbol */
1339 if (r_ptr->d_char != vault_aux_char) return (FALSE);
1347 * Helper function for "monster pit (orc)"
1349 static bool vault_aux_orc(int r_idx)
1351 monster_race *r_ptr = &r_info[r_idx];
1353 /* Validate the monster */
1354 if (!vault_monster_okay(r_idx)) return (FALSE);
1357 if (!(r_ptr->flags3 & RF3_ORC)) return (FALSE);
1359 /* Decline undead */
1360 if (r_ptr->flags3 & RF3_UNDEAD) return (FALSE);
1368 * Helper function for "monster pit (troll)"
1370 static bool vault_aux_troll(int r_idx)
1372 monster_race *r_ptr = &r_info[r_idx];
1374 /* Validate the monster */
1375 if (!vault_monster_okay(r_idx)) return (FALSE);
1378 if (!(r_ptr->flags3 & RF3_TROLL)) return (FALSE);
1380 /* Decline undead */
1381 if (r_ptr->flags3 & RF3_UNDEAD) return (FALSE);
1389 * Helper function for "monster pit (giant)"
1391 static bool vault_aux_giant(int r_idx)
1393 monster_race *r_ptr = &r_info[r_idx];
1395 /* Validate the monster */
1396 if (!vault_monster_okay(r_idx)) return (FALSE);
1399 if (!(r_ptr->flags3 & RF3_GIANT)) return (FALSE);
1401 if (r_ptr->flags3 & RF3_GOOD) return (FALSE);
1403 /* Decline undead */
1404 if (r_ptr->flags3 & RF3_UNDEAD) return (FALSE);
1412 * Helper function for "monster pit (dragon)"
1414 static bool vault_aux_dragon(int r_idx)
1416 monster_race *r_ptr = &r_info[r_idx];
1418 /* Validate the monster */
1419 if (!vault_monster_okay(r_idx)) return (FALSE);
1421 /* Require dragon */
1422 if (!(r_ptr->flags3 & RF3_DRAGON)) return (FALSE);
1424 /* Hack -- Require correct "breath attack" */
1425 if (r_ptr->flags4 != vault_aux_dragon_mask4) return (FALSE);
1427 /* Decline undead */
1428 if (r_ptr->flags3 & RF3_UNDEAD) return (FALSE);
1436 * Helper function for "monster pit (demon)"
1438 static bool vault_aux_demon(int r_idx)
1440 monster_race *r_ptr = &r_info[r_idx];
1442 /* Validate the monster */
1443 if (!vault_monster_okay(r_idx)) return (FALSE);
1445 if (r_ptr->flags2 & (RF2_KILL_BODY)) return (FALSE);
1448 if (!(r_ptr->flags3 & RF3_DEMON)) return (FALSE);
1456 * Helper function for "monster pit (lovecraftian)"
1458 static bool vault_aux_cthulhu(int r_idx)
1460 monster_race *r_ptr = &r_info[r_idx];
1462 /* Validate the monster */
1463 if (!vault_monster_okay(r_idx)) return (FALSE);
1465 if (r_ptr->flags2 & (RF2_KILL_BODY)) return (FALSE);
1467 /* Require eldritch horror */
1468 if (!(r_ptr->flags2 & (RF2_ELDRITCH_HORROR))) return (FALSE);
1476 * Helper function for "monster pit (clone)"
1478 static void vault_prep_clone(void)
1480 /* Apply the monster restriction */
1481 get_mon_num_prep(vault_aux_simple, NULL);
1483 /* Pick a race to clone */
1484 vault_aux_race = get_mon_num(dun_level + 10);
1486 /* Remove the monster restriction */
1487 get_mon_num_prep(NULL, NULL);
1492 * Helper function for "monster pit (symbol clone)"
1494 static void vault_prep_symbol(void)
1498 /* Apply the monster restriction */
1499 get_mon_num_prep(vault_aux_simple, NULL);
1501 /* Pick a race to clone */
1502 r_idx = get_mon_num(dun_level + 10);
1504 /* Remove the monster restriction */
1505 get_mon_num_prep(NULL, NULL);
1507 /* Extract the symbol */
1508 vault_aux_char = r_info[r_idx].d_char;
1513 * Helper function for "monster pit (dragon)"
1515 static void vault_prep_dragon(void)
1517 /* Pick dragon type */
1518 switch (randint0(6))
1523 /* Restrict dragon breath type */
1524 vault_aux_dragon_mask4 = RF4_BR_ACID;
1533 /* Restrict dragon breath type */
1534 vault_aux_dragon_mask4 = RF4_BR_ELEC;
1543 /* Restrict dragon breath type */
1544 vault_aux_dragon_mask4 = RF4_BR_FIRE;
1553 /* Restrict dragon breath type */
1554 vault_aux_dragon_mask4 = RF4_BR_COLD;
1563 /* Restrict dragon breath type */
1564 vault_aux_dragon_mask4 = RF4_BR_POIS;
1573 /* Restrict dragon breath type */
1574 vault_aux_dragon_mask4 = (RF4_BR_ACID | RF4_BR_ELEC |
1575 RF4_BR_FIRE | RF4_BR_COLD |
1588 typedef struct vault_aux_type vault_aux_type;
1591 struct vault_aux_type
1594 bool (*hook_func)(int r_idx);
1595 void (*prep_func)(void);
1601 static vault_aux_type *pick_vault_type(vault_aux_type *l_ptr, int room)
1603 int tmp, total, count;
1605 vault_aux_type *n_ptr;
1607 /* Calculate the total possibilities */
1608 for (n_ptr = l_ptr, total = 0, count = 0; TRUE; n_ptr++, count++)
1611 if (!n_ptr->name) break;
1613 /* Ignore excessive depth */
1614 if (n_ptr->level > dun_level) continue;
1616 if (room == ROOM_PIT)
1618 if (!(d_info[dungeon_type].pit & (1L << count))) continue;
1620 else if (room == ROOM_NEST)
1622 if(!(d_info[dungeon_type].nest & (1L << count))) continue;
1625 /* Count this possibility */
1626 total += n_ptr->chance * MAX_DEPTH / (MIN(dun_level, MAX_DEPTH - 1) - n_ptr->level + 5);
1629 /* Pick a random type */
1630 tmp = randint0(total);
1632 /* Find this type */
1633 for (n_ptr = l_ptr, total = 0, count = 0; TRUE; n_ptr++, count++)
1636 if (!n_ptr->name) break;
1638 /* Ignore excessive depth */
1639 if (n_ptr->level > dun_level) continue;
1641 if (room == ROOM_PIT)
1643 if (!(d_info[dungeon_type].pit & (1L << count))) continue;
1645 else if (room == ROOM_NEST)
1647 if(!(d_info[dungeon_type].nest & (1L << count))) continue;
1650 /* Count this possibility */
1651 total += n_ptr->chance * MAX_DEPTH / (MIN(dun_level, MAX_DEPTH - 1) - n_ptr->level + 5);
1653 /* Found the type */
1654 if (tmp < total) break;
1657 return (n_ptr->name ? n_ptr : NULL);
1660 void build_type6(int by0, int bx0, bool nest);
1661 void build_type5(int by0, int bx0, bool nest);
1663 static vault_aux_type nest_types[] =
1666 {"¥¯¥í¡¼¥ó", vault_aux_clone, vault_prep_clone, 5, 3},
1667 {"¥¼¥ê¡¼", vault_aux_jelly, NULL, 5, 6},
1668 {"¥·¥ó¥Ü¥ë(Á±)",vault_aux_symbol_g, vault_prep_symbol, 25, 2},
1669 {"¥·¥ó¥Ü¥ë(°)",vault_aux_symbol_e, vault_prep_symbol, 25, 2},
1670 {"¥ß¥ß¥Ã¥¯", vault_aux_mimic, NULL, 30, 4},
1671 {"¶¸µ¤", vault_aux_cthulhu, NULL, 70, 2},
1672 {"¸¤¾®²°", vault_aux_kennel, NULL, 45, 4},
1673 {"ưʪ±à", vault_aux_animal, NULL, 35, 5},
1674 {"¶µ²ñ", vault_aux_chapel_g, NULL, 75, 4},
1675 {"¥¢¥ó¥Ç¥Ã¥É", vault_aux_undead, NULL, 75, 5},
1676 {NULL, NULL, NULL, 0, 0},
1678 {"clone", vault_aux_clone, vault_prep_clone, 7, 3},
1679 {"jelly", vault_aux_jelly, NULL, 7, 6},
1680 {"symbol good",vault_aux_symbol_g, vault_prep_symbol, 25, 2},
1681 {"symbol evil",vault_aux_symbol_e, vault_prep_symbol, 25, 2},
1682 {"mimic", vault_aux_mimic, NULL, 45, 6},
1683 {"lovecraftian",vault_aux_cthulhu, NULL, 80, 2},
1684 {"kennel", vault_aux_kennel, NULL, 50, 2},
1685 {"animal", vault_aux_animal, NULL, 50, 4},
1686 {"chapel", vault_aux_chapel_g, NULL, 90, 2},
1687 {"undead", vault_aux_undead, NULL, 90, 4},
1688 {NULL, NULL, NULL, 0, 0},
1694 * Type 5 -- Monster nests
1696 * A monster nest is a "big" room, with an "inner" room, containing
1697 * a "collection" of monsters of a given type strewn about the room.
1699 * The monsters are chosen from a set of 64 randomly selected monster
1700 * races, to allow the nest creation to fail instead of having "holes".
1702 * Note the use of the "get_mon_num_prep()" function, and the special
1703 * "get_mon_num_hook()" restriction function, to prepare the "monster
1704 * allocation table" in such a way as to optimize the selection of
1705 * "appropriate" non-unique monsters for the nest.
1707 * Note that the "get_mon_num()" function may (rarely) fail, in which
1708 * case the nest will be empty, and will not affect the level rating.
1710 * Note that "monster nests" will never contain "unique" monsters.
1712 void build_type5(int by0, int bx0, bool pit)
1714 int y, x, y1, x1, y2, x2, xval, yval;
1722 vault_aux_type *n_ptr = pick_vault_type(nest_types, ROOM_NEST);
1724 /* Try to allocate space for room. */
1725 if (!room_alloc(25, 11, TRUE, by0, bx0, &xval, &yval)) return;
1727 /* No type available */
1731 else {build_type6(by0, bx0, TRUE);return;}
1734 /* Process a preparation function if necessary */
1735 if (n_ptr->prep_func) (*(n_ptr->prep_func))();
1743 /* Place the floor area */
1744 for (y = y1 - 1; y <= y2 + 1; y++)
1746 for (x = x1 - 1; x <= x2 + 1; x++)
1748 c_ptr = &cave[y][x];
1749 place_floor_grid(c_ptr);
1750 c_ptr->info |= (CAVE_ROOM);
1754 /* Place the outer walls */
1755 for (y = y1 - 1; y <= y2 + 1; y++)
1757 c_ptr = &cave[y][x1 - 1];
1758 place_outer_grid(c_ptr);
1759 c_ptr = &cave[y][x2 + 1];
1760 place_outer_grid(c_ptr);
1762 for (x = x1 - 1; x <= x2 + 1; x++)
1764 c_ptr = &cave[y1 - 1][x];
1765 place_outer_grid(c_ptr);
1766 c_ptr = &cave[y2 + 1][x];
1767 place_outer_grid(c_ptr);
1771 /* Advance to the center room */
1777 /* The inner walls */
1778 for (y = y1 - 1; y <= y2 + 1; y++)
1780 c_ptr = &cave[y][x1 - 1];
1781 place_inner_grid(c_ptr);
1782 c_ptr = &cave[y][x2 + 1];
1783 place_inner_grid(c_ptr);
1786 for (x = x1 - 1; x <= x2 + 1; x++)
1788 c_ptr = &cave[y1 - 1][x];
1789 place_inner_grid(c_ptr);
1790 c_ptr = &cave[y2 + 1][x];
1791 place_inner_grid(c_ptr);
1793 for (y = y1; y <= y2; y++)
1795 for (x = x1; x <= x2; x++)
1797 add_cave_info(y, x, CAVE_ICKY);
1802 /* Place a secret door */
1803 switch (randint1(4))
1805 case 1: place_secret_door(y1 - 1, xval); break;
1806 case 2: place_secret_door(y2 + 1, xval); break;
1807 case 3: place_secret_door(yval, x1 - 1); break;
1808 case 4: place_secret_door(yval, x2 + 1); break;
1812 /* Prepare allocation table */
1813 get_mon_num_prep(n_ptr->hook_func, NULL);
1815 /* Pick some monster types */
1816 for (i = 0; i < 64; i++)
1818 int r_idx = 0, attempts = 100;
1822 /* Get a (hard) monster type */
1823 r_idx = get_mon_num(dun_level + 10);
1825 /* Decline incorrect alignment */
1826 if (((align < 0) && (r_info[r_idx].flags3 & RF3_GOOD)) ||
1827 ((align > 0) && (r_info[r_idx].flags3 & RF3_EVIL)))
1832 /* Accept this monster */
1836 /* Notice failure */
1837 if (!r_idx || !attempts) return;
1839 /* Note the alignment */
1840 if (r_info[r_idx].flags3 & RF3_GOOD) align++;
1841 else if (r_info[r_idx].flags3 & RF3_EVIL) align--;
1851 msg_format("¥â¥ó¥¹¥¿¡¼Éô²°(%s)", n_ptr->name);
1853 msg_format("Monster nest (%s)", n_ptr->name);
1859 /* Increase the level rating */
1862 /* (Sometimes) Cause a "special feeling" (for "Monster Nests") */
1863 if ((dun_level <= 40) && (randint1(dun_level * dun_level + 50) < 300))
1865 good_item_flag = TRUE;
1868 /* Place some monsters */
1869 for (y = yval - 2; y <= yval + 2; y++)
1871 for (x = xval - 9; x <= xval + 9; x++)
1873 int r_idx = what[randint0(64)];
1875 /* Place that "random" monster (no groups) */
1876 (void)place_monster_aux(y, x, r_idx, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE);
1882 static vault_aux_type pit_types[] =
1885 {"¥ª¡¼¥¯", vault_aux_orc, NULL, 5, 6},
1886 {"¥È¥í¥ë", vault_aux_troll, NULL, 20, 6},
1887 {"¥¸¥ã¥¤¥¢¥ó¥È",vault_aux_giant, NULL, 50, 6},
1888 {"¶¸µ¤", vault_aux_cthulhu, NULL, 80, 2},
1889 {"¥·¥ó¥Ü¥ë(Á±)",vault_aux_symbol_g, vault_prep_symbol, 70, 1},
1890 {"¥·¥ó¥Ü¥ë(°)",vault_aux_symbol_e, vault_prep_symbol, 70, 1},
1891 {"¶µ²ñ", vault_aux_chapel_g, NULL, 65, 2},
1892 {"¥É¥é¥´¥ó", vault_aux_dragon, vault_prep_dragon, 70, 6},
1893 {"¥Ç¡¼¥â¥ó", vault_aux_demon, NULL, 80, 6},
1894 {NULL, NULL, NULL, 0, 0},
1896 {"orc", vault_aux_orc, NULL, 7, 4},
1897 {"troll", vault_aux_troll, NULL, 35, 4},
1898 {"giant", vault_aux_giant, NULL, 70, 4},
1899 {"lovecraftian",vault_aux_cthulhu, NULL, 90, 4},
1900 {"symbol good",vault_aux_symbol_g, vault_prep_symbol, 25, 2},
1901 {"symbol evil",vault_aux_symbol_e, vault_prep_symbol, 25, 2},
1902 {"chapel", vault_aux_chapel_g, NULL, 85, 1},
1903 {"dragon", vault_aux_dragon, vault_prep_dragon, 80, 4},
1904 {"demon", vault_aux_demon, NULL, 90, 4},
1905 {NULL, NULL, NULL, 0, 0},
1911 * Type 6 -- Monster pits
1913 * A monster pit is a "big" room, with an "inner" room, containing
1914 * a "collection" of monsters of a given type organized in the room.
1916 * The inside room in a monster pit appears as shown below, where the
1917 * actual monsters in each location depend on the type of the pit
1919 * #####################
1920 * #0000000000000000000#
1921 * #0112233455543322110#
1922 * #0112233467643322110#
1923 * #0112233455543322110#
1924 * #0000000000000000000#
1925 * #####################
1927 * Note that the monsters in the pit are now chosen by using "get_mon_num()"
1928 * to request 16 "appropriate" monsters, sorting them by level, and using
1929 * the "even" entries in this sorted list for the contents of the pit.
1931 * Hack -- all of the "dragons" in a "dragon" pit must be the same "color",
1932 * which is handled by requiring a specific "breath" attack for all of the
1933 * dragons. This may include "multi-hued" breath. Note that "wyrms" may
1934 * be present in many of the dragon pits, if they have the proper breath.
1936 * Note the use of the "get_mon_num_prep()" function, and the special
1937 * "get_mon_num_hook()" restriction function, to prepare the "monster
1938 * allocation table" in such a way as to optimize the selection of
1939 * "appropriate" non-unique monsters for the pit.
1941 * Note that the "get_mon_num()" function may (rarely) fail, in which case
1942 * the pit will be empty, and will not effect the level rating.
1944 * Note that "monster pits" will never contain "unique" monsters.
1946 void build_type6(int by0, int bx0, bool nest)
1948 int y, x, y1, x1, y2, x2, xval, yval;
1957 vault_aux_type *n_ptr = pick_vault_type(pit_types, ROOM_PIT);
1959 /* Try to allocate space for room. */
1960 if (!room_alloc(25, 11, TRUE, by0, bx0, &xval, &yval)) return;
1962 /* No type available */
1966 else {build_type5(by0, bx0, TRUE);return;}
1969 /* Process a preparation function if necessary */
1970 if (n_ptr->prep_func) (*(n_ptr->prep_func))();
1978 /* Place the floor area */
1979 for (y = y1 - 1; y <= y2 + 1; y++)
1981 for (x = x1 - 1; x <= x2 + 1; x++)
1983 c_ptr = &cave[y][x];
1984 place_floor_grid(c_ptr);
1985 c_ptr->info |= (CAVE_ROOM);
1989 /* Place the outer walls */
1990 for (y = y1 - 1; y <= y2 + 1; y++)
1992 c_ptr = &cave[y][x1 - 1];
1993 place_outer_grid(c_ptr);
1994 c_ptr = &cave[y][x2 + 1];
1995 place_outer_grid(c_ptr);
1997 for (x = x1 - 1; x <= x2 + 1; x++)
1999 c_ptr = &cave[y1 - 1][x];
2000 place_outer_grid(c_ptr);
2001 c_ptr = &cave[y2 + 1][x];
2002 place_outer_grid(c_ptr);
2005 /* Advance to the center room */
2011 /* The inner walls */
2012 for (y = y1 - 1; y <= y2 + 1; y++)
2014 c_ptr = &cave[y][x1 - 1];
2015 place_inner_grid(c_ptr);
2016 c_ptr = &cave[y][x2 + 1];
2017 place_inner_grid(c_ptr);
2019 for (x = x1 - 1; x <= x2 + 1; x++)
2021 c_ptr = &cave[y1 - 1][x];
2022 place_inner_grid(c_ptr);
2023 c_ptr = &cave[y2 + 1][x];
2024 place_inner_grid(c_ptr);
2026 for (y = y1; y <= y2; y++)
2028 for (x = x1; x <= x2; x++)
2030 add_cave_info(y, x, CAVE_ICKY);
2034 /* Place a secret door */
2035 switch (randint1(4))
2037 case 1: place_secret_door(y1 - 1, xval); break;
2038 case 2: place_secret_door(y2 + 1, xval); break;
2039 case 3: place_secret_door(yval, x1 - 1); break;
2040 case 4: place_secret_door(yval, x2 + 1); break;
2044 /* Prepare allocation table */
2045 get_mon_num_prep(n_ptr->hook_func, NULL);
2047 /* Pick some monster types */
2048 for (i = 0; i < 16; i++)
2050 int r_idx = 0, attempts = 100;
2054 /* Get a (hard) monster type */
2055 r_idx = get_mon_num(dun_level + 10);
2057 /* Decline incorrect alignment */
2058 if (((align < 0) && (r_info[r_idx].flags3 & RF3_GOOD)) ||
2059 ((align > 0) && (r_info[r_idx].flags3 & RF3_EVIL)))
2064 /* Accept this monster */
2068 /* Notice failure */
2069 if (!r_idx || !attempts) return;
2071 /* Note the alignment */
2072 if (r_info[r_idx].flags3 & RF3_GOOD) align++;
2073 else if (r_info[r_idx].flags3 & RF3_EVIL) align--;
2078 /* Sort the entries */
2079 for (i = 0; i < 16 - 1; i++)
2081 /* Sort the entries */
2082 for (j = 0; j < 16 - 1; j++)
2087 int p1 = r_info[what[i1]].level;
2088 int p2 = r_info[what[i2]].level;
2094 what[i1] = what[i2];
2104 msg_format("%s¤ÎÁã", n_ptr->name);
2107 msg_format("Monster pit (%s)", n_ptr->name);
2111 /* Select the entries */
2112 for (i = 0; i < 8; i++)
2114 /* Every other entry */
2115 what[i] = what[i * 2];
2120 msg_print(r_name + r_info[what[i]].name);
2124 /* Increase the level rating */
2127 /* (Sometimes) Cause a "special feeling" (for "Monster Pits") */
2128 if ((dun_level <= 40) && (randint1(dun_level * dun_level + 50) < 300))
2130 good_item_flag = TRUE;
2133 /* Top and bottom rows */
2134 for (x = xval - 9; x <= xval + 9; x++)
2136 place_monster_aux(yval - 2, x, what[0], FALSE, FALSE, FALSE, FALSE, TRUE, FALSE);
2137 place_monster_aux(yval + 2, x, what[0], FALSE, FALSE, FALSE, FALSE, TRUE, FALSE);
2140 /* Middle columns */
2141 for (y = yval - 1; y <= yval + 1; y++)
2143 place_monster_aux(y, xval - 9, what[0], FALSE, FALSE, FALSE, FALSE, TRUE, FALSE);
2144 place_monster_aux(y, xval + 9, what[0], FALSE, FALSE, FALSE, FALSE, TRUE, FALSE);
2146 place_monster_aux(y, xval - 8, what[1], FALSE, FALSE, FALSE, FALSE, TRUE, FALSE);
2147 place_monster_aux(y, xval + 8, what[1], FALSE, FALSE, FALSE, FALSE, TRUE, FALSE);
2149 place_monster_aux(y, xval - 7, what[1], FALSE, FALSE, FALSE, FALSE, TRUE, FALSE);
2150 place_monster_aux(y, xval + 7, what[1], FALSE, FALSE, FALSE, FALSE, TRUE, FALSE);
2152 place_monster_aux(y, xval - 6, what[2], FALSE, FALSE, FALSE, FALSE, TRUE, FALSE);
2153 place_monster_aux(y, xval + 6, what[2], FALSE, FALSE, FALSE, FALSE, TRUE, FALSE);
2155 place_monster_aux(y, xval - 5, what[2], FALSE, FALSE, FALSE, FALSE, TRUE, FALSE);
2156 place_monster_aux(y, xval + 5, what[2], FALSE, FALSE, FALSE, FALSE, TRUE, FALSE);
2158 place_monster_aux(y, xval - 4, what[3], FALSE, FALSE, FALSE, FALSE, TRUE, FALSE);
2159 place_monster_aux(y, xval + 4, what[3], FALSE, FALSE, FALSE, FALSE, TRUE, FALSE);
2161 place_monster_aux(y, xval - 3, what[3], FALSE, FALSE, FALSE, FALSE, TRUE, FALSE);
2162 place_monster_aux(y, xval + 3, what[3], FALSE, FALSE, FALSE, FALSE, TRUE, FALSE);
2164 place_monster_aux(y, xval - 2, what[4], FALSE, FALSE, FALSE, FALSE, TRUE, FALSE);
2165 place_monster_aux(y, xval + 2, what[4], FALSE, FALSE, FALSE, FALSE, TRUE, FALSE);
2168 /* Above/Below the center monster */
2169 for (x = xval - 1; x <= xval + 1; x++)
2171 place_monster_aux(yval + 1, x, what[5], FALSE, FALSE, FALSE, FALSE, TRUE, FALSE);
2172 place_monster_aux(yval - 1, x, what[5], FALSE, FALSE, FALSE, FALSE, TRUE, FALSE);
2175 /* Next to the center monster */
2176 place_monster_aux(yval, xval + 1, what[6], FALSE, FALSE, FALSE, FALSE, TRUE, FALSE);
2177 place_monster_aux(yval, xval - 1, what[6], FALSE, FALSE, FALSE, FALSE, TRUE, FALSE);
2179 /* Center monster */
2180 place_monster_aux(yval, xval, what[7], FALSE, FALSE, FALSE, FALSE, TRUE, FALSE);
2184 /* coordinate translation code */
2185 static void coord_trans(int *x, int *y, int xoffset, int yoffset, int transno)
2191 * transno specifies what transformation is required. (0-7)
2192 * The lower two bits indicate by how much the vault is rotated,
2193 * and the upper bit indicates a reflection.
2194 * This is done by using rotation matrices... however since
2195 * these are mostly zeros for rotations by 90 degrees this can
2196 * be expressed simply in terms of swapping and inverting the
2197 * x and y coordinates.
2199 for (i = 0; i <= transno % 4; i++)
2201 /* rotate by 90 degrees */
2209 /* Reflect depending on status of 3rd bit. */
2213 /* Add offsets so vault stays in the first quadrant */
2220 * Hack -- fill in "vault" rooms
2222 static void build_vault(int yval, int xval, int ymax, int xmax, cptr data,
2223 int xoffset, int yoffset, int transno)
2225 int dx, dy, x, y, i, j;
2232 /* Place dungeon features and objects */
2233 for (t = data, dy = 0; dy < ymax; dy++)
2235 for (dx = 0; dx < xmax; dx++, t++)
2237 /* prevent loop counter from being overwritten */
2242 coord_trans(&i, &j, xoffset, yoffset, transno);
2244 /* Extract the location */
2247 /* no swap of x/y */
2248 x = xval - (xmax / 2) + i;
2249 y = yval - (ymax / 2) + j;
2254 x = xval - (ymax / 2) + i;
2255 y = yval - (xmax / 2) + j;
2258 /* Hack -- skip "non-grids" */
2259 if (*t == ' ') continue;
2261 /* Access the grid */
2262 c_ptr = &cave[y][x];
2264 /* Lay down a floor */
2265 place_floor_grid(c_ptr);
2267 /* Part of a vault */
2268 c_ptr->info |= (CAVE_ROOM | CAVE_ICKY);
2270 /* Analyze the grid */
2273 /* Granite wall (outer) */
2275 place_outer_noperm_grid(c_ptr);
2278 /* Granite wall (inner) */
2280 place_inner_grid(c_ptr);
2283 /* Permanent wall (inner) */
2285 c_ptr->feat = FEAT_PERM_INNER;
2286 c_ptr->info &= ~(CAVE_MASK);
2287 c_ptr->info |= CAVE_INNER;
2292 if (randint0(100) < 75)
2294 place_object(y, x, FALSE, FALSE);
2304 place_secret_door(y, x);
2316 /* Place dungeon monsters and objects */
2317 for (t = data, dy = 0; dy < ymax; dy++)
2319 for (dx = 0; dx < xmax; dx++, t++)
2321 /* prevent loop counter from being overwritten */
2326 coord_trans(&i, &j, xoffset, yoffset, transno);
2328 /* Extract the location */
2331 /* no swap of x/y */
2332 x = xval - (xmax / 2) + i;
2333 y = yval - (ymax / 2) + j;
2338 x = xval - (ymax / 2) + i;
2339 y = yval - (xmax / 2) + j;
2342 /* Hack -- skip "non-grids" */
2343 if (*t == ' ') continue;
2345 /* Analyze the symbol */
2351 monster_level = base_level + 5;
2352 place_monster(y, x, TRUE, TRUE);
2353 monster_level = base_level;
2357 /* Meaner monster */
2360 monster_level = base_level + 11;
2361 place_monster(y, x, TRUE, TRUE);
2362 monster_level = base_level;
2366 /* Meaner monster, plus treasure */
2369 monster_level = base_level + 9;
2370 place_monster(y, x, TRUE, FALSE);
2371 monster_level = base_level;
2372 object_level = base_level + 7;
2373 place_object(y, x, TRUE, FALSE);
2374 object_level = base_level;
2378 /* Nasty monster and treasure */
2381 monster_level = base_level + 40;
2382 place_monster(y, x, TRUE, FALSE);
2383 monster_level = base_level;
2384 object_level = base_level + 20;
2385 place_object(y, x, TRUE, TRUE);
2386 object_level = base_level;
2390 /* Monster and/or object */
2393 if (randint0(100) < 50)
2395 monster_level = base_level + 3;
2396 place_monster(y, x, TRUE, TRUE);
2397 monster_level = base_level;
2399 if (randint0(100) < 50)
2401 object_level = base_level + 7;
2402 place_object(y, x, FALSE, FALSE);
2403 object_level = base_level;
2409 cave_set_feat(y, x, FEAT_SHOP_HEAD + STORE_BLACK);
2410 store_init(NO_TOWN, STORE_BLACK);
2414 cave_set_feat(y, x, FEAT_PATTERN_START);
2418 cave_set_feat(y, x, FEAT_PATTERN_1);
2422 cave_set_feat(y, x, FEAT_PATTERN_2);
2426 cave_set_feat(y, x, FEAT_PATTERN_3);
2430 cave_set_feat(y, x, FEAT_PATTERN_4);
2434 cave_set_feat(y, x, FEAT_PATTERN_END);
2438 cave_set_feat(y, x, FEAT_PATTERN_XTRA1);
2443 object_level = base_level + 12;
2444 place_object(y, x, TRUE, FALSE);
2445 object_level = base_level;
2455 * Type 7 -- simple vaults (see "v_info.txt")
2457 static void build_type7(int by0, int bx0)
2459 vault_type *v_ptr = NULL;
2463 int xoffset, yoffset;
2466 /* Pick a lesser vault */
2467 while (dummy < SAFE_MAX_ATTEMPTS)
2471 /* Access a random vault record */
2472 v_ptr = &v_info[randint0(max_v_idx)];
2474 /* Accept the first lesser vault */
2475 if (v_ptr->typ == 7) break;
2478 /* No lesser vault found */
2481 /* pick type of transformation (0-7) */
2482 transno = randint0(8);
2484 /* calculate offsets */
2488 coord_trans(&x, &y, 0, 0, transno);
2508 /* Try to allocate space for room. */
2509 if (!room_alloc(abs(x), abs(y), FALSE, by0, bx0, &xval, &yval)) return;
2511 if (dummy >= SAFE_MAX_ATTEMPTS)
2516 msg_print("·Ù¹ð¡ª¾®¤µ¤ÊÃϲ¼¼¼¤òÇÛÃ֤Ǥ¤Þ¤»¤ó¡ª");
2518 msg_print("Warning! Could not place lesser vault!");
2531 if (cheat_room) msg_format("%s", v_name + v_ptr->name);
2533 /* Boost the rating */
2534 rating += v_ptr->rat;
2536 /* (Sometimes) Cause a special feeling */
2537 if ((dun_level <= 50) ||
2538 (randint1((dun_level - 40) * (dun_level - 40) + 50) < 400))
2540 good_item_flag = TRUE;
2543 /* Hack -- Build the vault */
2544 build_vault(yval, xval, v_ptr->hgt, v_ptr->wid,
2545 v_text + v_ptr->text, xoffset, yoffset, transno);
2550 * Type 8 -- greater vaults (see "v_info.txt")
2552 static void build_type8(int by0, int bx0)
2554 vault_type *v_ptr = NULL;
2559 int xoffset, yoffset;
2561 /* Pick a greater vault */
2562 while (dummy < SAFE_MAX_ATTEMPTS)
2566 /* Access a random vault record */
2567 v_ptr = &v_info[randint0(max_v_idx)];
2569 /* Accept the first greater vault */
2570 if (v_ptr->typ == 8) break;
2573 /* No greater vault found */
2576 /* pick type of transformation (0-7) */
2577 transno = randint0(8);
2579 /* calculate offsets */
2583 coord_trans(&x, &y, 0, 0, transno);
2603 /* Try to allocate space for room. If fails, exit */
2604 if (!room_alloc(abs(x), abs(y), FALSE, by0, bx0, &xval, &yval)) return;
2606 if (dummy >= SAFE_MAX_ATTEMPTS)
2611 msg_print("·Ù¹ð¡ªµðÂç¤ÊÃϲ¼¼¼¤òÇÛÃ֤Ǥ¤Þ¤»¤ó¡ª");
2613 msg_print("Warning! Could not place greater vault!");
2622 v_ptr = &v_info[76 + randint1(3)];
2626 if (cheat_room) msg_format("%s", v_name + v_ptr->name);
2628 /* Boost the rating */
2629 rating += v_ptr->rat;
2631 /* (Sometimes) Cause a special feeling */
2632 if ((dun_level <= 50) ||
2633 (randint1((dun_level - 40) * (dun_level - 40) + 50) < 400))
2635 good_item_flag = TRUE;
2638 /* Hack -- Build the vault */
2639 build_vault(yval, xval, v_ptr->hgt, v_ptr->wid,
2640 v_text + v_ptr->text, xoffset, yoffset, transno);
2644 * Structure to hold all "fill" data
2647 typedef struct fill_data_type fill_data_type;
2649 struct fill_data_type
2662 /* features to fill with */
2671 /* number of filled squares */
2675 static fill_data_type fill_data;
2678 /* Store routine for the fractal cave generator */
2679 /* this routine probably should be an inline function or a macro. */
2680 static void store_height(int x, int y, int val)
2682 /* if on boundary set val > cutoff so walls are not as square */
2683 if (((x == fill_data.xmin) || (y == fill_data.ymin) ||
2684 (x == fill_data.xmax) || (y == fill_data.ymax)) &&
2685 (val <= fill_data.c1)) val = fill_data.c1 + 1;
2687 /* store the value in height-map format */
2688 cave[y][x].feat = val;
2695 * Explanation of the plasma fractal algorithm:
2697 * A grid of points is created with the properties of a 'height-map'
2698 * This is done by making the corners of the grid have a random value.
2699 * The grid is then subdivided into one with twice the resolution.
2700 * The new points midway between two 'known' points can be calculated
2701 * by taking the average value of the 'known' ones and randomly adding
2702 * or subtracting an amount proportional to the distance between those
2703 * points. The final 'middle' points of the grid are then calculated
2704 * by averaging all four of the originally 'known' corner points. An
2705 * random amount is added or subtracted from this to get a value of the
2706 * height at that point. The scaling factor here is adjusted to the
2707 * slightly larger distance diagonally as compared to orthogonally.
2709 * This is then repeated recursively to fill an entire 'height-map'
2710 * A rectangular map is done the same way, except there are different
2711 * scaling factors along the x and y directions.
2713 * A hack to change the amount of correlation between points is done using
2714 * the grd variable. If the current step size is greater than grd then
2715 * the point will be random, otherwise it will be calculated by the
2716 * above algorithm. This makes a maximum distance at which two points on
2717 * the height map can affect each other.
2719 * How fractal caves are made:
2721 * When the map is complete, a cut-off value is used to create a cave.
2722 * Heights below this value are "floor", and heights above are "wall".
2723 * This also can be used to create lakes, by adding more height levels
2724 * representing shallow and deep water/ lava etc.
2726 * The grd variable affects the width of passages.
2727 * The roug variable affects the roughness of those passages
2729 * The tricky part is making sure the created cave is connected. This
2730 * is done by 'filling' from the inside and only keeping the 'filled'
2731 * floor. Walls bounding the 'filled' floor are also kept. Everything
2732 * else is converted to the normal granite FEAT_WALL_EXTRA.
2737 * Note that this uses the cave.feat array in a very hackish way
2738 * the values are first set to zero, and then each array location
2739 * is used as a "heightmap"
2740 * The heightmap then needs to be converted back into the "feat" format.
2742 * grd=level at which fractal turns on. smaller gives more mazelike caves
2743 * roug=roughness level. 16=normal. higher values make things more convoluted
2744 * small values are good for smooth walls.
2745 * size=length of the side of the square cave system.
2747 static void generate_hmap(int y0, int x0, int xsiz, int ysiz, int grd, int roug, int cutoff)
2749 int xhsize, yhsize, xsize, ysize, maxsize;
2752 * fixed point variables- these are stored as 256 x normal value
2753 * this gives 8 binary places of fractional part + 8 places of normal part
2756 u16b xstep, xhstep, ystep, yhstep;
2757 u16b xstep2, xhstep2, ystep2, yhstep2;
2758 u16b i, j, ii, jj, diagsize, xxsize, yysize;
2760 /* Cache for speed */
2761 u16b xm, xp, ym, yp;
2763 /* redefine size so can change the value if out of range */
2767 /* Paranoia about size of the system of caves */
2768 if (xsize > 254) xsize = 254;
2769 if (xsize < 4) xsize = 4;
2770 if (ysize > 254) ysize = 254;
2771 if (ysize < 4) ysize = 4;
2773 /* get offsets to middle of array */
2777 /* fix rounding problem */
2781 /* get limits of region */
2782 fill_data.xmin = x0 - xhsize;
2783 fill_data.ymin = y0 - yhsize;
2784 fill_data.xmax = x0 + xhsize;
2785 fill_data.ymax = y0 + yhsize;
2787 /* Store cutoff in global for quick access */
2788 fill_data.c1 = cutoff;
2791 * Scale factor for middle points:
2792 * About sqrt(2) * 256 - correct for a square lattice
2793 * approximately correct for everything else.
2797 /* maximum of xsize and ysize */
2798 maxsize = (xsize > ysize) ? xsize : ysize;
2800 /* Clear the section */
2801 for (i = 0; i <= xsize; i++)
2803 for (j = 0; j <= ysize; j++)
2805 /* 255 is a flag for "not done yet" */
2806 cave[(int)(fill_data.ymin + j)][(int)(fill_data.xmin + i)].feat = 255;
2807 /* Clear icky flag because may be redoing the cave */
2808 cave[(int)(fill_data.ymin + j)][(int)(fill_data.xmin + i)].info &= ~(CAVE_ICKY);
2812 /* Boundaries are walls */
2813 cave[fill_data.ymin][fill_data.xmin].feat = maxsize;
2814 cave[fill_data.ymax][fill_data.xmin].feat = maxsize;
2815 cave[fill_data.ymin][fill_data.xmax].feat = maxsize;
2816 cave[fill_data.ymax][fill_data.xmax].feat = maxsize;
2818 /* Set the middle square to be an open area. */
2819 cave[y0][x0].feat = 0;
2821 /* Initialize the step sizes */
2822 xstep = xhstep = xsize * 256;
2823 ystep = yhstep = ysize * 256;
2824 xxsize = xsize * 256;
2825 yysize = ysize * 256;
2828 * Fill in the rectangle with fractal height data -
2829 * like the 'plasma fractal' in fractint.
2831 while ((xhstep > 256) || (yhstep > 256))
2833 /* Halve the step sizes */
2839 /* cache well used values */
2840 xstep2 = xstep / 256;
2841 ystep2 = ystep / 256;
2843 xhstep2 = xhstep / 256;
2844 yhstep2 = yhstep / 256;
2846 /* middle top to bottom. */
2847 for (i = xhstep; i <= xxsize - xhstep; i += xstep)
2849 for (j = 0; j <= yysize; j += ystep)
2851 /* cache often used values */
2852 ii = i / 256 + fill_data.xmin;
2853 jj = j / 256 + fill_data.ymin;
2856 if (cave[jj][ii].feat == 255)
2860 /* If greater than 'grid' level then is random */
2861 store_height(ii, jj, randint1(maxsize));
2865 /* Average of left and right points +random bit */
2866 store_height(ii, jj,
2867 (cave[jj][fill_data.xmin + (i - xhstep) / 256].feat
2868 + cave[jj][fill_data.xmin + (i + xhstep) / 256].feat) / 2
2869 + (randint1(xstep2) - xhstep2) * roug / 16);
2876 /* middle left to right. */
2877 for (j = yhstep; j <= yysize - yhstep; j += ystep)
2879 for (i = 0; i <= xxsize; i += xstep)
2881 /* cache often used values */
2882 ii = i / 256 + fill_data.xmin;
2883 jj = j / 256 + fill_data.ymin;
2886 if (cave[jj][ii].feat == 255)
2890 /* If greater than 'grid' level then is random */
2891 store_height(ii, jj, randint1(maxsize));
2895 /* Average of up and down points +random bit */
2896 store_height(ii, jj,
2897 (cave[fill_data.ymin + (j - yhstep) / 256][ii].feat
2898 + cave[fill_data.ymin + (j + yhstep) / 256][ii].feat) / 2
2899 + (randint1(ystep2) - yhstep2) * roug / 16);
2906 for (i = xhstep; i <= xxsize - xhstep; i += xstep)
2908 for (j = yhstep; j <= yysize - yhstep; j += ystep)
2910 /* cache often used values */
2911 ii = i / 256 + fill_data.xmin;
2912 jj = j / 256 + fill_data.ymin;
2915 if (cave[jj][ii].feat == 255)
2919 /* If greater than 'grid' level then is random */
2920 store_height(ii, jj, randint1(maxsize));
2924 /* Cache reused values. */
2925 xm = fill_data.xmin + (i - xhstep) / 256;
2926 xp = fill_data.xmin + (i + xhstep) / 256;
2927 ym = fill_data.ymin + (j - yhstep) / 256;
2928 yp = fill_data.ymin + (j + yhstep) / 256;
2931 * Average over all four corners + scale by diagsize to
2932 * reduce the effect of the square grid on the shape of the fractal
2934 store_height(ii, jj,
2935 (cave[ym][xm].feat + cave[yp][xm].feat
2936 + cave[ym][xp].feat + cave[yp][xp].feat) / 4
2937 + (randint1(xstep2) - xhstep2) * (diagsize / 16) / 256 * roug);
2946 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)
2949 * function used to convert from height-map back to the
2950 * normal angband cave format
2952 if (cave[y][x].info & CAVE_ICKY)
2959 /* Show that have looked at this square */
2960 cave[y][x].info|= (CAVE_ICKY);
2962 /* Use cutoffs c1-c3 to allocate regions of floor /water/ lava etc. */
2963 if (cave[y][x].feat <= c1)
2965 /* 25% of the time use the other tile : it looks better this way */
2966 if (randint1(100) < 75)
2968 cave[y][x].feat = feat1;
2969 cave[y][x].info &= ~(CAVE_MASK);
2970 cave[y][x].info |= info1;
2975 cave[y][x].feat = feat2;
2976 cave[y][x].info &= ~(CAVE_MASK);
2977 cave[y][x].info |= info2;
2981 else if (cave[y][x].feat <= c2)
2983 /* 25% of the time use the other tile : it looks better this way */
2984 if (randint1(100) < 75)
2986 cave[y][x].feat = feat2;
2987 cave[y][x].info &= ~(CAVE_MASK);
2988 cave[y][x].info |= info2;
2993 cave[y][x].feat = feat1;
2994 cave[y][x].info &= ~(CAVE_MASK);
2995 cave[y][x].info |= info1;
2999 else if (cave[y][x].feat <= c3)
3001 cave[y][x].feat = feat3;
3002 cave[y][x].info |= info3;
3005 /* if greater than cutoff then is a wall */
3008 place_outer_bold(y, x);
3018 * Quick and nasty fill routine used to find the connected region
3019 * of floor in the middle of the cave
3021 static void cave_fill(byte y, byte x)
3030 /*** Start Grid ***/
3032 /* Enqueue that entry */
3037 /* Now process the queue */
3038 while (flow_head != flow_tail)
3040 /* Extract the next entry */
3041 ty = temp_y[flow_head];
3042 tx = temp_x[flow_head];
3044 /* Forget that entry */
3045 if (++flow_head == TEMP_MAX) flow_head = 0;
3047 /* Add the "children" */
3048 for (d = 0; d < 8; d++)
3050 int old_head = flow_tail;
3052 /* Child location */
3053 j = ty + ddy_ddd[d];
3054 i = tx + ddx_ddd[d];
3056 /* Paranoia Don't leave the cave */
3057 if (!in_bounds(j, i))
3059 /* affect boundary */
3060 cave[j][i].info |= CAVE_ICKY;
3064 /* If within bounds */
3065 else if ((i > fill_data.xmin) && (i < fill_data.xmax)
3066 && (j > fill_data.ymin) && (j < fill_data.ymax))
3068 /* If not a wall or floor done before */
3069 if (hack_isnt_wall(j, i,
3070 fill_data.c1, fill_data.c2, fill_data.c3,
3071 fill_data.feat1, fill_data.feat2, fill_data.feat3,
3072 fill_data.info1, fill_data.info2, fill_data.info3))
3074 /* Enqueue that entry */
3075 temp_y[flow_tail] = j;
3076 temp_x[flow_tail] = i;
3078 /* Advance the queue */
3079 if (++flow_tail == TEMP_MAX) flow_tail = 0;
3081 /* Hack -- Overflow by forgetting new entry */
3082 if (flow_tail == flow_head)
3084 flow_tail = old_head;
3088 /* keep tally of size of cave system */
3089 (fill_data.amount)++;
3095 /* affect boundary */
3096 cave[j][i].info |= CAVE_ICKY;
3103 static bool generate_fracave(int y0, int x0, int xsize, int ysize, int cutoff, bool light, bool room)
3105 int x, y, i, xhsize, yhsize;
3108 /* offsets to middle from corner */
3114 * select region connected to center of cave system
3115 * this gets rid of alot of isolated one-sqaures that
3116 * can make teleport traps instadeaths...
3120 fill_data.c1 = cutoff;
3124 /* features to fill with */
3125 fill_data.feat1 = floor_type[randint0(100)];
3126 fill_data.feat2 = floor_type[randint0(100)];
3127 fill_data.feat3 = floor_type[randint0(100)];
3129 fill_data.info1 = CAVE_FLOOR;
3130 fill_data.info2 = CAVE_FLOOR;
3131 fill_data.info3 = CAVE_FLOOR;
3133 /* number of filled squares */
3134 fill_data.amount = 0;
3136 cave_fill((byte)y0, (byte)x0);
3138 /* if tally too small, try again */
3139 if (fill_data.amount < 10)
3141 /* too small - clear area and try again later */
3142 for (x = 0; x <= xsize; ++x)
3144 for (y = 0; y <= ysize; ++y)
3146 place_extra_bold(y0 + y - yhsize, x0 + x - xhsize);
3147 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY | CAVE_ROOM);
3154 * Do boundarys-check to see if they are next to a filled region
3155 * If not then they are set to normal granite
3156 * If so then they are marked as room walls.
3158 for (i = 0; i <= xsize; ++i)
3161 if ((cave[0 + y0 - yhsize][i + x0 - xhsize].info & CAVE_ICKY) && (room))
3163 /* Next to a 'filled' region? - set to be room walls */
3164 place_outer_bold(y0 + 0 - yhsize, x0 + i - xhsize);
3165 if (light) cave[y0 + 0 - yhsize][x0 + i - xhsize].info |= (CAVE_GLOW);
3166 cave[y0 + 0 - yhsize][x0 + i - xhsize].info |= (CAVE_ROOM);
3167 place_outer_bold(y0 + 0 - yhsize, x0 + i - xhsize);
3171 /* set to be normal granite */
3172 place_extra_bold(y0 + 0 - yhsize, x0 + i - xhsize);
3175 /* bottom boundary */
3176 if ((cave[ysize + y0 - yhsize][i + x0 - xhsize].info & CAVE_ICKY) && (room))
3178 /* Next to a 'filled' region? - set to be room walls */
3179 place_outer_bold(y0 + ysize - yhsize, x0 + i - xhsize);
3180 if (light) cave[y0 + ysize - yhsize][x0 + i - xhsize].info|=(CAVE_GLOW);
3181 cave[y0 + ysize - yhsize][x0 + i - xhsize].info|=(CAVE_ROOM);
3182 place_outer_bold(y0 + ysize - yhsize, x0 + i - xhsize);
3186 /* set to be normal granite */
3187 place_extra_bold(y0 + ysize - yhsize, x0 + i - xhsize);
3190 /* clear the icky flag-don't need it any more */
3191 cave[y0 + 0 - yhsize][x0 + i - xhsize].info &= ~(CAVE_ICKY);
3192 cave[y0 + ysize - yhsize][x0 + i - xhsize].info &= ~(CAVE_ICKY);
3195 /* Do the left and right boundaries minus the corners (done above) */
3196 for (i = 1; i < ysize; ++i)
3199 if ((cave[i + y0 - yhsize][0 + x0 - xhsize].info & CAVE_ICKY) && room)
3202 place_outer_bold(y0 + i - yhsize, x0 + 0 - xhsize);
3203 if (light) cave[y0 + i - yhsize][x0 + 0 - xhsize].info |= (CAVE_GLOW);
3204 cave[y0 + i - yhsize][x0 + 0 - xhsize].info |= (CAVE_ROOM);
3205 place_outer_bold(y0 + i - yhsize, x0 + 0 - xhsize);
3210 place_extra_bold(y0 + i - yhsize, x0 + 0 - xhsize);
3212 /* right boundary */
3213 if ((cave[i + y0 - yhsize][xsize + x0 - xhsize].info & CAVE_ICKY) && room)
3216 place_outer_bold(y0 + i - yhsize, x0 + xsize - xhsize);
3217 if (light) cave[y0 + i - yhsize][x0 + xsize - xhsize].info |= (CAVE_GLOW);
3218 cave[y0 + i - yhsize][x0 + xsize - xhsize].info |= (CAVE_ROOM);
3219 place_outer_bold(y0 + i - yhsize, x0 + xsize - xhsize);
3224 place_extra_bold(y0 + i - yhsize, x0 + xsize - xhsize);
3227 /* clear icky flag -done with it */
3228 cave[y0 + i - yhsize][x0 + 0 - xhsize].info &= ~(CAVE_ICKY);
3229 cave[y0 + i - yhsize][x0 + xsize - xhsize].info &= ~(CAVE_ICKY);
3233 /* Do the rest: convert back to the normal format */
3234 for (x = 1; x < xsize; ++x)
3236 for (y = 1; y < ysize; ++y)
3238 if (is_floor_bold(y0 + y - yhsize, x0 + x - xhsize) &&
3239 (cave[y0 + y - yhsize][x0 + x - xhsize].info & CAVE_ICKY))
3241 /* Clear the icky flag in the filled region */
3242 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~CAVE_ICKY;
3244 /* Set appropriate flags */
3245 if (light) cave[y0 + y - yhsize][x0 + x - xhsize].info |= (CAVE_GLOW);
3246 if (room) cave[y0 + y - yhsize][x0 + x - xhsize].info |= (CAVE_ROOM);
3248 else if (is_outer_bold(y0 + y - yhsize, x0 + x - xhsize) &&
3249 (cave[y0 + y - yhsize][x0 + x - xhsize].info & CAVE_ICKY))
3252 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY);
3253 if (light) cave[y0 + y - yhsize][x0 + x - xhsize].info |= (CAVE_GLOW);
3256 cave[y0 + y - yhsize][x0 + x - xhsize].info |= (CAVE_ROOM);
3261 place_extra_bold(y0 + y - yhsize, x0 + x - xhsize);
3262 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ROOM);
3267 /* Clear the unconnected regions */
3268 place_extra_bold(y0 + y - yhsize, x0 + x - xhsize);
3269 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY | CAVE_ROOM);
3275 * XXX XXX XXX There is a slight problem when tunnels pierce the caves:
3276 * Extra doors appear inside the system. (Its not very noticeable though.)
3277 * This can be removed by "filling" from the outside in. This allows a separation
3278 * from FEAT_WALL_OUTER with FEAT_WALL_INNER. (Internal walls are F.W.OUTER instead.)
3279 * The extra effort for what seems to be only a minor thing (even non-existant if you
3280 * think of the caves not as normal rooms, but as holes in the dungeon), doesn't seem
3289 * Driver routine to create fractal cave system
3291 static void build_type9(int by0, int bx0)
3293 int grd, roug, cutoff, xsize, ysize, y0, x0;
3295 bool done, light, room;
3297 /* get size: note 'Evenness'*/
3298 xsize = randint1(22) * 2 + 6;
3299 ysize = randint1(15) * 2 + 6;
3301 /* Try to allocate space for room. If fails, exit */
3302 if (!room_alloc(xsize + 1, ysize + 1, FALSE, by0, bx0, &x0, &y0)) return;
3304 light = done = FALSE;
3307 if ((dun_level <= randint1(25)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS)) light = TRUE;
3311 /* Note: size must be even or there are rounding problems
3312 * This causes the tunnels not to connect properly to the room */
3314 /* testing values for these parameters feel free to adjust */
3315 grd = 1 << (randint0(4));
3317 /* want average of about 16 */
3318 roug = randint1(8) * randint1(4);
3321 cutoff = randint1(xsize / 4) + randint1(ysize / 4) +
3322 randint1(xsize / 4) + randint1(ysize / 4);
3325 generate_hmap(y0, x0, xsize, ysize, grd, roug, cutoff);
3327 /* Convert to normal format + clean up */
3328 done = generate_fracave(y0, x0, xsize, ysize, cutoff, light, room);
3332 #ifdef ALLOW_CAVERNS_AND_LAKES
3334 * Builds a cave system in the center of the dungeon.
3336 void build_cavern(void)
3338 int grd, roug, cutoff, xsize, ysize, x0, y0;
3341 light = done = FALSE;
3342 if ((dun_level <= randint1(50)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS)) light = TRUE;
3344 /* Make a cave the size of the dungeon */
3345 xsize = cur_wid - 1;
3346 ysize = cur_hgt - 1;
3350 /* Paranoia: make size even */
3356 /* testing values for these parameters: feel free to adjust */
3357 grd = randint1(4) + 4;
3359 /* want average of about 16 */
3360 roug = randint1(8) * randint1(4);
3366 generate_hmap(y0 + 1, x0 + 1, xsize, ysize, grd, roug, cutoff);
3368 /* Convert to normal format+ clean up */
3369 done = generate_fracave(y0 + 1, x0 + 1, xsize, ysize, cutoff, light, FALSE);
3373 static bool generate_lake(int y0, int x0, int xsize, int ysize, int c1, int c2, int c3, int type)
3375 int x, y, i, xhsize, yhsize;
3376 int feat1, feat2, feat3;
3378 /* offsets to middle from corner */
3382 /* Get features based on type */
3387 feat1 = FEAT_DEEP_LAVA;
3388 feat2 = FEAT_SHAL_LAVA;
3389 feat3 = floor_type[randint0(100)];
3393 feat1 = FEAT_DEEP_WATER;
3394 feat2 = FEAT_SHAL_WATER;
3395 feat3 = floor_type[randint0(100)];
3398 /* Collapsed cave */
3399 feat1 = floor_type[randint0(100)];
3400 feat2 = floor_type[randint0(100)];
3401 feat3 = FEAT_RUBBLE;
3405 feat1 = FEAT_RUBBLE;
3406 feat2 = floor_type[randint0(100)];
3407 feat3 = FEAT_RUBBLE;
3417 feat1 = FEAT_SHAL_WATER;
3418 feat2 = FEAT_DEEP_WATER;
3419 feat3 = FEAT_SHAL_WATER;
3423 feat1 = FEAT_SHAL_LAVA;
3424 feat2 = FEAT_DEEP_LAVA;
3425 feat3 = FEAT_SHAL_LAVA;
3429 default: return FALSE;
3433 * select region connected to center of cave system
3434 * this gets rid of alot of isolated one-sqaures that
3435 * can make teleport traps instadeaths...
3443 /* features to fill with */
3444 fill_data.feat1 = feat1;
3445 fill_data.feat2 = feat2;
3446 fill_data.feat3 = feat3;
3448 fill_data.info1 = 0;
3449 fill_data.info2 = 0;
3450 fill_data.info3 = 0;
3452 /* number of filled squares */
3453 fill_data.amount = 0;
3455 /* select region connected to center of cave system
3456 * this gets rid of alot of isolated one-sqaures that
3457 * can make teleport traps instadeaths... */
3458 cave_fill((byte)y0, (byte)x0);
3460 /* if tally too small, try again */
3461 if (fill_data.amount < 10)
3463 /* too small -clear area and try again later */
3464 for (x = 0; x <= xsize; ++x)
3466 for (y = 0; y <= ysize; ++y)
3468 place_floor_bold(y0 + y - yhsize, x0 + x - xhsize);
3469 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY);
3475 /* Do boundarys- set to normal granite */
3476 for (i = 0; i <= xsize; ++i)
3478 place_extra_bold(y0 + 0 - yhsize, x0 + i - xhsize);
3479 place_extra_bold(y0 + ysize - yhsize, x0 + i - xhsize);
3481 /* clear the icky flag-don't need it any more */
3482 cave[y0 + 0 - yhsize][x0 + i - xhsize].info &= ~(CAVE_ICKY);
3483 cave[y0 + ysize - yhsize][x0 + i - xhsize].info &= ~(CAVE_ICKY);
3486 /* Do the left and right boundaries minus the corners (done above) */
3488 for (i = 1; i < ysize; ++i)
3490 place_extra_bold(y0 + i - yhsize, x0 + 0 - xhsize);
3491 place_extra_bold(y0 + i - yhsize, x0 + xsize - xhsize);
3493 /* clear icky flag -done with it */
3494 cave[y0 + i - yhsize][x0 + 0 - xhsize].info &= ~(CAVE_ICKY);
3495 cave[y0 + i - yhsize][x0 + xsize - xhsize].info &= ~(CAVE_ICKY);
3499 /* Do the rest: convert back to the normal format */
3500 for (x = 1; x < xsize; ++x)
3502 for (y = 1; y < ysize; ++y)
3504 /* Fill unconnected regions with granite */
3505 if ((!(cave[y0 + y - yhsize][x0 + x - xhsize].info & CAVE_ICKY)) ||
3506 is_outer_bold(y0 + y - yhsize, x0 + x - xhsize))
3507 place_extra_bold(y0 + y - yhsize, x0 + x - xhsize);
3509 /* turn off icky flag (no longer needed.) */
3510 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY | CAVE_ROOM);
3512 /* Light lava and trees */
3513 if ((cave[y0 + y - yhsize][x0 + x - xhsize].feat == FEAT_DEEP_LAVA) ||
3514 (cave[y0 + y - yhsize][x0 + x - xhsize].feat == FEAT_SHAL_LAVA))
3516 cave[y0 + y - yhsize][x0 + x - xhsize].info |= CAVE_GLOW;
3526 * makes a lake/collapsed cave system in the center of the dungeon
3528 void build_lake(int type)
3530 int grd, roug, xsize, ysize, x0, y0;
3534 /* paranoia - exit if lake type out of range. */
3535 if ((type < 1) || (type > 7))
3537 msg_format("Invalid lake type (%d)", type);
3541 /* Make the size of the dungeon */
3542 xsize = cur_wid - 1;
3543 ysize = cur_hgt - 1;
3547 /* Paranoia: make size even */
3553 /* testing values for these parameters: feel free to adjust */
3554 grd = randint1(3) + 4;
3556 /* want average of about 16 */
3557 roug = randint1(8) * randint1(4);
3559 /* Make up size of various componants */
3563 /* Deep water/lava */
3564 c1 = randint0(c3 / 2) + randint0(c3 / 2) - 5;
3566 /* Shallow boundary */
3570 generate_hmap(y0 + 1, x0 + 1, xsize, ysize, grd, roug, c3);
3572 /* Convert to normal format+ clean up */
3573 done = generate_lake(y0 + 1, x0 + 1, xsize, ysize, c1, c2, c3, type);
3576 #endif /* ALLOW_CAVERNS_AND_LAKES */
3580 * Routine used by the random vault creators to add a door to a location
3581 * Note that range checking has to be done in the calling routine.
3583 * The doors must be INSIDE the allocated region.
3585 static void add_door(int x, int y)
3587 /* Need to have a wall in the center square */
3588 if (!is_outer_bold(y, x)) return;
3595 * where x=don't care
3599 if (is_floor_bold(y-1,x) && is_floor_bold(y+1,x) &&
3600 (is_outer_bold(y, x - 1) && is_outer_bold(y, x + 1)))
3603 place_secret_door(y, x);
3605 /* set boundarys so don't get wide doors */
3606 place_solid_bold(y, x - 1);
3607 place_solid_bold(y, x + 1);
3616 * where x = don't care
3619 if (is_outer_bold(y - 1, x) && is_outer_bold(y + 1, x) &&
3620 is_floor_bold(y,x-1) && is_floor_bold(y,x+1))
3623 place_secret_door(y, x);
3625 /* set boundarys so don't get wide doors */
3626 place_solid_bold(y - 1, x);
3627 place_solid_bold(y + 1, x);
3633 * Routine that fills the empty areas of a room with treasure and monsters.
3635 static void fill_treasure(int x1, int x2, int y1, int y2, int difficulty)
3637 int x, y, cx, cy, size;
3640 /* center of room:*/
3644 /* Rough measure of size of vault= sum of lengths of sides */
3645 size = abs(x2 - x1) + abs(y2 - y1);
3647 for (x = x1; x <= x2; x++)
3649 for (y = y1; y <= y2; y++)
3651 /* Thing added based on distance to center of vault
3652 * Difficulty is 1-easy to 10-hard */
3653 value = ((((s32b)(distance(cx, cy, x, y))) * 100) / size) + randint1(10) - difficulty;
3655 /* hack- empty square part of the time */
3656 if ((randint1(100) - difficulty * 3) > 50) value = 20;
3658 /* if floor, shallow water and lava */
3659 if (is_floor_bold(y, x) ||
3660 (cave[y][x].feat == FEAT_SHAL_WATER) ||
3661 (cave[y][x].feat == FEAT_SHAL_LAVA))
3663 /* The smaller 'value' is, the better the stuff */
3666 /* Meanest monster + treasure */
3667 monster_level = base_level + 40;
3668 place_monster(y, x, TRUE, TRUE);
3669 monster_level = base_level;
3670 object_level = base_level + 20;
3671 place_object(y, x, TRUE, FALSE);
3672 object_level = base_level;
3676 /* Mean monster +treasure */
3677 monster_level = base_level + 20;
3678 place_monster(y, x, TRUE, TRUE);
3679 monster_level = base_level;
3680 object_level = base_level + 10;
3681 place_object(y, x, TRUE, FALSE);
3682 object_level = base_level;
3684 else if (value < 10)
3687 monster_level = base_level + 9;
3688 place_monster(y, x, TRUE, TRUE);
3689 monster_level = base_level;
3691 else if (value < 17)
3693 /* Intentional Blank space */
3696 * (Want some of the vault to be empty
3697 * so have room for group monsters.
3698 * This is used in the hack above to lower
3699 * the density of stuff in the vault.)
3702 else if (value < 23)
3704 /* Object or trap */
3705 if (randint0(100) < 25)
3707 place_object(y, x, FALSE, FALSE);
3714 else if (value < 30)
3716 /* Monster and trap */
3717 monster_level = base_level + 5;
3718 place_monster(y, x, TRUE, TRUE);
3719 monster_level = base_level;
3722 else if (value < 40)
3724 /* Monster or object */
3725 if (randint0(100) < 50)
3727 monster_level = base_level + 3;
3728 place_monster(y, x, TRUE, TRUE);
3729 monster_level = base_level;
3731 if (randint0(100) < 50)
3733 object_level = base_level + 7;
3734 place_object(y, x, FALSE, FALSE);
3735 object_level = base_level;
3738 else if (value < 50)
3747 /* 20% monster, 40% trap, 20% object, 20% blank space */
3748 if (randint0(100) < 20)
3750 place_monster(y, x, TRUE, TRUE);
3752 else if (randint0(100) < 50)
3756 else if (randint0(100) < 50)
3758 place_object(y, x, FALSE, FALSE);
3769 * This function creates a random vault that looks like a collection of bubbles.
3770 * It works by getting a set of coordinates that represent the center of each
3771 * bubble. The entire room is made by seeing which bubble center is closest. If
3772 * two centers are equidistant then the square is a wall, otherwise it is a floor.
3773 * The only exception is for squares really near a center, these are always floor.
3774 * (It looks better than without this check.)
3776 * Note: If two centers are on the same point then this algorithm will create a
3777 * blank bubble filled with walls. - This is prevented from happening.
3779 static void build_bubble_vault(int x0, int y0, int xsize, int ysize)
3781 #define BUBBLENUM 10 /* number of bubbles */
3783 /* array of center points of bubbles */
3784 coord center[BUBBLENUM];
3787 u16b min1, min2, temp;
3790 /* Offset from center to top left hand corner */
3791 int xhsize = xsize / 2;
3792 int yhsize = ysize / 2;
3795 if (cheat_room) msg_print("Bubble Vault");
3797 /* Allocate center of bubbles */
3798 center[0].x = randint1(xsize - 3) + 1;
3799 center[0].y = randint1(ysize - 3) + 1;
3801 for (i = 1; i < BUBBLENUM; i++)
3805 /* get center and check to see if it is unique */
3810 x = randint1(xsize - 3) + 1;
3811 y = randint1(ysize - 3) + 1;
3813 for (j = 0; j < i; j++)
3815 /* rough test to see if there is an overlap */
3816 if ((x == center[j].x) && (y == center[j].y)) done = FALSE;
3825 /* Top and bottom boundaries */
3826 for (i = 0; i < xsize; i++)
3828 int x = x0 - xhsize + i;
3830 place_outer_noperm_bold(y0 - yhsize + 0, x);
3831 cave[y0 - yhsize + 0][x].info |= (CAVE_ROOM | CAVE_ICKY);
3832 place_outer_noperm_bold(y0 - yhsize + ysize - 1, x);
3833 cave[y0 - yhsize + ysize - 1][x].info |= (CAVE_ROOM | CAVE_ICKY);
3836 /* Left and right boundaries */
3837 for (i = 1; i < ysize - 1; i++)
3839 int y = y0 - yhsize + i;
3841 place_outer_noperm_bold(y, x0 - xhsize + 0);
3842 cave[y][x0 - xhsize + 0].info |= (CAVE_ROOM | CAVE_ICKY);
3843 place_outer_noperm_bold(y, x0 - xhsize + xsize - 1);
3844 cave[y][x0 - xhsize + xsize - 1].info |= (CAVE_ROOM | CAVE_ICKY);
3847 /* Fill in middle with bubbles */
3848 for (x = 1; x < xsize - 1; x++)
3850 for (y = 1; y < ysize - 1; y++)
3852 /* Get distances to two closest centers */
3855 min1 = distance(x, y, center[0].x, center[0].y);
3856 min2 = distance(x, y, center[1].x, center[1].y);
3860 /* swap if in wrong order */
3867 for (i = 2; i < BUBBLENUM; i++)
3869 temp = distance(x, y, center[i].x, center[i].y);
3877 else if (temp < min2)
3879 /* second smallest */
3883 if (((min2 - min1) <= 2) && (!(min1 < 3)))
3885 /* Boundary at midpoint+ not at inner region of bubble */
3886 place_outer_noperm_bold(y0 - yhsize + y, x0 - xhsize + x);
3890 /* middle of a bubble */
3891 place_floor_bold(y0 - yhsize + y, x0 - xhsize + x);
3894 /* clean up rest of flags */
3895 cave[y0 - yhsize + y][x0 - xhsize + x].info |= (CAVE_ROOM | CAVE_ICKY);
3899 /* Try to add some random doors */
3900 for (i = 0; i < 500; i++)
3902 x = randint1(xsize - 3) - xhsize + x0 + 1;
3903 y = randint1(ysize - 3) - yhsize + y0 + 1;
3907 /* Fill with monsters and treasure, low difficulty */
3908 fill_treasure(x0 - xhsize + 1, x0 - xhsize + xsize - 2, y0 - yhsize + 1, y0 - yhsize + ysize - 2, randint1(5));
3913 * Overlay a rectangular room given its bounds
3914 * This routine is used by build_room_vault
3915 * The area inside the walls is not touched:
3916 * only granite is removed- normal walls stay
3918 static void build_room(int x1, int x2, int y1, int y2)
3920 int x, y, i, xsize, ysize, temp;
3922 /* Check if rectangle has no width */
3923 if ((x1 == x2) || (y1 == y2)) return;
3928 /* Swap boundaries if in wrong order */
3936 /* Swap boundaries if in wrong order */
3942 /* get total widths */
3947 /* Top and bottom boundaries */
3948 for (i = 0; i <= xsize; i++)
3950 place_outer_noperm_bold(y1, x1 + i);
3951 cave[y1][x1 + i].info |= (CAVE_ROOM | CAVE_ICKY);
3952 place_outer_noperm_bold(y2, x1 + i);
3953 cave[y2][x1 + i].info |= (CAVE_ROOM | CAVE_ICKY);
3956 /* Left and right boundaries */
3957 for (i = 1; i < ysize; i++)
3959 place_outer_noperm_bold(y1 + i, x1);
3960 cave[y1 + i][x1].info|=(CAVE_ROOM | CAVE_ICKY);
3961 place_outer_noperm_bold(y1 + i, x2);
3962 cave[y1 + i][x2].info|=(CAVE_ROOM | CAVE_ICKY);
3966 for (x = 1; x < xsize; x++)
3968 for (y = 1; y < ysize; y++)
3970 if (is_extra_bold(y1+y, x1+x))
3972 /* clear the untouched region */
3973 place_floor_bold(y1 + y, x1 + x);
3974 cave[y1 + y][x1 + x].info |= (CAVE_ROOM | CAVE_ICKY);
3978 /* make it a room- but don't touch */
3979 cave[y1 + y][x1 + x].info |= (CAVE_ROOM | CAVE_ICKY);
3986 /* Create a random vault that looks like a collection of overlapping rooms */
3988 static void build_room_vault(int x0, int y0, int xsize, int ysize)
3990 int i, x1, x2, y1, y2, xhsize, yhsize;
3992 /* get offset from center */
3996 if (cheat_room) msg_print("Room Vault");
3998 /* fill area so don't get problems with arena levels */
3999 for (x1 = 0; x1 < xsize; x1++)
4001 int x = x0 - xhsize + x1;
4003 for (y1 = 0; y1 < ysize; y1++)
4005 int y = y0 - yhsize + y1;
4007 place_extra_bold(y, x);
4008 cave[y][x].info &= (~CAVE_ICKY);
4012 /* add ten random rooms */
4013 for (i = 0; i < 10; i++)
4015 x1 = randint1(xhsize) * 2 + x0 - xhsize;
4016 x2 = randint1(xhsize) * 2 + x0 - xhsize;
4017 y1 = randint1(yhsize) * 2 + y0 - yhsize;
4018 y2 = randint1(yhsize) * 2 + y0 - yhsize;
4019 build_room(x1, x2, y1, y2);
4022 /* Add some random doors */
4023 for (i = 0; i < 500; i++)
4025 x1 = randint1(xsize - 3) - xhsize + x0 + 1;
4026 y1 = randint1(ysize - 3) - yhsize + y0 + 1;
4030 /* Fill with monsters and treasure, high difficulty */
4031 fill_treasure(x0 - xhsize + 1, x0 - xhsize + xsize - 2, y0 - yhsize + 1, y0 - yhsize + ysize - 2, randint1(5) + 5);
4035 /* Create a random vault out of a fractal cave */
4036 static void build_cave_vault(int x0, int y0, int xsiz, int ysiz)
4038 int grd, roug, cutoff, xhsize, yhsize, xsize, ysize, x, y;
4039 bool done, light, room;
4041 /* round to make sizes even */
4047 if (cheat_room) msg_print("Cave Vault");
4049 light = done = FALSE;
4054 /* testing values for these parameters feel free to adjust */
4055 grd = 1 << randint0(4);
4057 /* want average of about 16 */
4058 roug = randint1(8) * randint1(4);
4061 cutoff = randint1(xsize / 4) + randint1(ysize / 4) +
4062 randint1(xsize / 4) + randint1(ysize / 4);
4065 generate_hmap(y0, x0, xsize, ysize, grd, roug, cutoff);
4067 /* Convert to normal format+ clean up */
4068 done = generate_fracave(y0, x0, xsize, ysize, cutoff, light, room);
4071 /* Set icky flag because is a vault */
4072 for (x = 0; x <= xsize; x++)
4074 for (y = 0; y <= ysize; y++)
4076 cave[y0 - yhsize + y][x0 - xhsize + x].info |= CAVE_ICKY;
4080 /* Fill with monsters and treasure, low difficulty */
4081 fill_treasure(x0 - xhsize + 1, x0 - xhsize + xsize - 1, y0 - yhsize + 1, y0 - yhsize + ysize - 1, randint1(5));
4085 * maze vault -- rectangular labyrinthine rooms
4087 * maze vault uses two routines:
4088 * r_visit - a recursive routine that builds the labyrinth
4089 * build_maze_vault - a driver routine that calls r_visit and adds
4090 * monsters, traps and treasure
4092 * The labyrinth is built by creating a spanning tree of a graph.
4093 * The graph vertices are at
4094 * (x, y) = (2j + x1, 2k + y1) j = 0,...,m-1 k = 0,...,n-1
4095 * and the edges are the vertical and horizontal nearest neighbors.
4097 * The spanning tree is created by performing a suitably randomized
4098 * depth-first traversal of the graph. The only adjustable parameter
4099 * is the randint0(3) below; it governs the relative density of
4100 * twists and turns in the labyrinth: smaller number, more twists.
4102 static void r_visit(int y1, int x1, int y2, int x2,
4103 int node, int dir, int *visited)
4105 int i, j, m, n, temp, x, y, adj[4];
4107 /* dimensions of vertex array */
4108 m = (x2 - x1) / 2 + 1;
4109 n = (y2 - y1) / 2 + 1;
4111 /* mark node visited and set it to a floor */
4113 x = 2 * (node % m) + x1;
4114 y = 2 * (node / m) + y1;
4115 place_floor_bold(y, x);
4117 /* setup order of adjacent node visits */
4120 /* pick a random ordering */
4121 for (i = 0; i < 4; i++)
4123 for (i = 0; i < 4; i++)
4134 /* pick a random ordering with dir first */
4136 for (i = 1; i < 4; i++)
4138 for (i = 1; i < 4; i++)
4140 j = 1 + randint0(3);
4147 for (i = 0; i < 4; i++)
4152 /* (0,+) - check for bottom boundary */
4153 if ((node / m < n - 1) && (visited[node + m] == 0))
4155 place_floor_bold(y + 1, x);
4156 r_visit(y1, x1, y2, x2, node + m, dir, visited);
4160 /* (0,-) - check for top boundary */
4161 if ((node / m > 0) && (visited[node - m] == 0))
4163 place_floor_bold(y - 1, x);
4164 r_visit(y1, x1, y2, x2, node - m, dir, visited);
4168 /* (+,0) - check for right boundary */
4169 if ((node % m < m - 1) && (visited[node + 1] == 0))
4171 place_floor_bold(y, x + 1);
4172 r_visit(y1, x1, y2, x2, node + 1, dir, visited);
4176 /* (-,0) - check for left boundary */
4177 if ((node % m > 0) && (visited[node - 1] == 0))
4179 place_floor_bold(y, x - 1);
4180 r_visit(y1, x1, y2, x2, node - 1, dir, visited);
4187 void build_maze_vault(int x0, int y0, int xsize, int ysize, bool is_vault)
4191 int m, n, num_vertices, *visited;
4196 if (cheat_room && is_vault) msg_print("Maze Vault");
4198 /* Choose lite or dark */
4199 light = ((dun_level <= randint1(25)) && is_vault && !(d_info[dungeon_type].flags1 & DF1_DARKNESS));
4201 /* Pick a random room size - randomized by calling routine */
4210 /* generate the room */
4211 for (y = y1 - 1; y <= y2 + 1; y++)
4213 for (x = x1 - 1; x <= x2 + 1; x++)
4215 c_ptr = &cave[y][x];
4216 c_ptr->info |= CAVE_ROOM;
4217 if (is_vault) c_ptr->info |= CAVE_ICKY;
4218 if ((x == x1 - 1) || (x == x2 + 1) || (y == y1 - 1) || (y == y2 + 1))
4220 place_outer_grid(c_ptr);
4224 place_extra_grid(c_ptr);
4228 place_inner_grid(c_ptr);
4230 if (light) c_ptr->info |= (CAVE_GLOW);
4234 /* dimensions of vertex array */
4237 num_vertices = m * n;
4239 /* initialize array of visited vertices */
4240 C_MAKE(visited, num_vertices, int);
4242 /* traverse the graph to create a spaning tree, pick a random root */
4243 r_visit(y1, x1, y2, x2, randint0(num_vertices), 0, visited);
4245 /* Fill with monsters and treasure, low difficulty */
4246 if (is_vault) fill_treasure(x1, x2, y1, y2, randint1(5));
4248 C_KILL(visited, num_vertices, int);
4252 /* Build a "mini" checkerboard vault
4254 * This is done by making a permanent wall maze and setting
4255 * the diagonal sqaures of the checker board to be granite.
4256 * The vault has two entrances on opposite sides to guarantee
4257 * a way to get in even if the vault abuts a side of the dungeon.
4259 static void build_mini_c_vault(int x0, int y0, int xsize, int ysize)
4262 int y1, x1, y2, x2, y, x, total;
4263 int m, n, num_vertices;
4266 if (cheat_room) msg_print("Mini Checker Board Vault");
4268 /* Pick a random room size */
4278 /* generate the room */
4279 for (x = x1 - 2; x <= x2 + 2; x++)
4281 if (!in_bounds(y1-2,x)) break;
4283 cave[y1-2][x].info |= (CAVE_ROOM | CAVE_ICKY);
4285 place_extra_noperm_bold(y1-2, x);
4288 for (x = x1 - 2; x <= x2 + 2; x++)
4290 if (!in_bounds(y2+2,x)) break;
4292 cave[y2+2][x].info |= (CAVE_ROOM | CAVE_ICKY);
4294 place_extra_noperm_bold(y2+2, x);
4297 for (y = y1 - 2; y <= y2 + 2; y++)
4299 if (!in_bounds(y,x1-2)) break;
4301 cave[y][x1-2].info |= (CAVE_ROOM | CAVE_ICKY);
4303 place_extra_noperm_bold(y, x1-2);
4306 for (y = y1 - 2; y <= y2 + 2; y++)
4308 if (!in_bounds(y,x2+2)) break;
4310 cave[y][x2+2].info |= (CAVE_ROOM | CAVE_ICKY);
4312 place_extra_noperm_bold(y, x2+2);
4315 for (y = y1 - 1; y <= y2 + 1; y++)
4317 for (x = x1 - 1; x <= x2 + 1; x++)
4319 cave[y][x].info |= (CAVE_ROOM | CAVE_ICKY);
4321 /* Permanent walls */
4322 cave[y][x].feat = FEAT_PERM_INNER;
4327 /* dimensions of vertex array */
4330 num_vertices = m * n;
4332 /* initialize array of visited vertices */
4333 C_MAKE(visited, num_vertices, int);
4335 /* traverse the graph to create a spannng tree, pick a random root */
4336 r_visit(y1, x1, y2, x2, randint0(num_vertices), 0, visited);
4338 /* Make it look like a checker board vault */
4339 for (x = x1; x <= x2; x++)
4341 for (y = y1; y <= y2; y++)
4343 total = x - x1 + y - y1;
4344 /* If total is odd- and is a floor then make a wall */
4345 if ((total % 2 == 1) && is_floor_bold(y, x))
4347 place_inner_bold(y, x);
4352 /* Make a couple of entrances */
4355 /* left and right */
4356 y = randint1(dy) + dy / 2;
4357 place_outer_noperm_bold(y1 + y, x1 - 1);
4358 place_outer_noperm_bold(y1 + y, x2 + 1);
4362 /* top and bottom */
4363 x = randint1(dx) + dx / 2;
4364 place_outer_noperm_bold(y1 - 1, x1 + x);
4365 place_outer_noperm_bold(y2 + 1, x1 + x);
4368 /* Fill with monsters and treasure, highest difficulty */
4369 fill_treasure(x1, x2, y1, y2, 10);
4371 C_KILL(visited, num_vertices, int);
4375 /* Build a town/ castle by using a recursive algorithm.
4376 * Basically divide each region in a probalistic way to create
4377 * smaller regions. When the regions get too small stop.
4379 * The power variable is a measure of how well defended a region is.
4380 * This alters the possible choices.
4382 static void build_recursive_room(int x1, int y1, int x2, int y2, int power)
4388 /* Temp variables */
4394 if ((power < 3) && (xsize > 12) && (ysize > 12))
4396 /* Need outside wall +keep */
4403 /* Make rooms + subdivide */
4404 if ((randint1(10) > 2) && (xsize < 8) && (ysize < 8))
4410 choice = randint1(2) + 1;
4415 /* Mostly subdivide */
4416 choice = randint1(3) + 1;
4420 /* Based on the choice made above, do something */
4428 /* top and bottom */
4429 for (x = x1; x <= x2; x++)
4431 place_outer_bold(y1, x);
4432 place_outer_bold(y2, x);
4435 /* left and right */
4436 for (y = y1 + 1; y < y2; y++)
4438 place_outer_bold(y, x1);
4439 place_outer_bold(y, x2);
4442 /* Make a couple of entrances */
4445 /* left and right */
4446 y = randint1(ysize) + y1;
4447 place_floor_bold(y, x1);
4448 place_floor_bold(y, x2);
4452 /* top and bottom */
4453 x = randint1(xsize) + x1;
4454 place_floor_bold(y1, x);
4455 place_floor_bold(y2, x);
4458 /* Select size of keep */
4459 t1 = randint1(ysize / 3) + y1;
4460 t2 = y2 - randint1(ysize / 3);
4461 t3 = randint1(xsize / 3) + x1;
4462 t4 = x2 - randint1(xsize / 3);
4464 /* Do outside areas */
4466 /* Above and below keep */
4467 build_recursive_room(x1 + 1, y1 + 1, x2 - 1, t1, power + 1);
4468 build_recursive_room(x1 + 1, t2, x2 - 1, y2, power + 1);
4470 /* Left and right of keep */
4471 build_recursive_room(x1 + 1, t1 + 1, t3, t2 - 1, power + 3);
4472 build_recursive_room(t4, t1 + 1, x2 - 1, t2 - 1, power + 3);
4474 /* Make the keep itself: */
4487 /* Try to build a room */
4488 if ((xsize < 3) || (ysize < 3))
4490 for (y = y1; y < y2; y++)
4492 for (x = x1; x < x2; x++)
4494 place_inner_bold(y, x);
4502 /* Make outside walls */
4503 /* top and bottom */
4504 for (x = x1 + 1; x <= x2 - 1; x++)
4506 place_inner_bold(y1 + 1, x);
4507 place_inner_bold(y2 - 1, x);
4510 /* left and right */
4511 for (y = y1 + 1; y <= y2 - 1; y++)
4513 place_inner_bold(y, x1 + 1);
4514 place_inner_bold(y, x2 - 1);
4518 y = randint1(ysize - 3) + y1 + 1;
4523 place_floor_bold(y, x1 + 1);
4528 place_floor_bold(y, x2 - 1);
4531 /* Build the room */
4532 build_recursive_room(x1 + 2, y1 + 2, x2 - 2, y2 - 2, power + 3);
4537 /* Try and divide vertically */
4541 for (y = y1; y < y2; y++)
4543 for (x = x1; x < x2; x++)
4545 place_inner_bold(y, x);
4551 t1 = randint1(xsize - 2) + x1 + 1;
4552 build_recursive_room(x1, y1, t1, y2, power - 2);
4553 build_recursive_room(t1 + 1, y1, x2, y2, power - 2);
4558 /* Try and divide horizontally */
4562 for (y = y1; y < y2; y++)
4564 for (x = x1; x < x2; x++)
4566 place_inner_bold(y, x);
4572 t1 = randint1(ysize - 2) + y1 + 1;
4573 build_recursive_room(x1, y1, x2, t1, power - 2);
4574 build_recursive_room(x1, t1 + 1, x2, y2, power - 2);
4581 /* Build a castle */
4583 /* Driver routine: clear the region and call the recursive
4586 *This makes a vault that looks like a castle/ city in the dungeon.
4588 static void build_castle_vault(int x0, int y0, int xsize, int ysize)
4594 /* Pick a random room size */
4603 if (cheat_room) msg_print("Castle Vault");
4605 /* generate the room */
4606 for (y = y1 - 1; y <= y2 + 1; y++)
4608 for (x = x1 - 1; x <= x2 + 1; x++)
4610 cave[y][x].info |= (CAVE_ROOM | CAVE_ICKY);
4611 /* Make everything a floor */
4612 place_floor_bold(y, x);
4616 /* Make the castle */
4617 build_recursive_room(x1, y1, x2, y2, randint1(5));
4619 /* Fill with monsters and treasure, low difficulty */
4620 fill_treasure(x1, x2, y1, y2, randint1(3));
4625 * Add outer wall to a floored region
4626 * Note: no range checking is done so must be inside dungeon
4627 * This routine also stomps on doors
4629 static void add_outer_wall(int x, int y, int light,
4630 int x1, int y1, int x2, int y2)
4634 if (!in_bounds(y, x)) return;
4636 /* hack- check to see if square has been visited before
4637 * if so, then exit (use room flag to do this) */
4638 if (cave[y][x].info & CAVE_ROOM) return;
4641 cave[y][x].info |= CAVE_ROOM;
4643 if (is_floor_bold(y, x))
4645 for (i = -1; i <= 1; i++)
4647 for (j = -1; j <= 1; j++)
4649 if ((x + i >= x1) && (x + i <= x2) &&
4650 (y + j >= y1) && (y + j <= y2))
4652 add_outer_wall(x + i, y + j, light, x1, y1, x2, y2);
4653 if (light) cave[y][x].info |= CAVE_GLOW;
4658 else if (is_extra_bold(y, x))
4660 /* Set bounding walls */
4661 place_outer_bold(y, x);
4662 if (light == TRUE) cave[y][x].info |= CAVE_GLOW;
4664 else if (cave[y][x].feat == FEAT_PERM_OUTER)
4666 /* Set bounding walls */
4667 if (light == TRUE) cave[y][x].info |= CAVE_GLOW;
4673 * Hacked distance formula - gives the 'wrong' answer.
4674 * Used to build crypts
4676 static int dist2(int x1, int y1, int x2, int y2,
4677 int h1, int h2, int h3, int h4)
4683 /* Basically this works by taking the normal pythagorean formula
4684 * and using an expansion to express this in a way without the
4685 * square root. This approximate formula is then perturbed to give
4686 * the distorted results. (I found this by making a mistake when I was
4687 * trying to fix the circular rooms.)
4690 /* h1-h4 are constants that describe the metric */
4691 if (dx >= 2 * dy) return (dx + (dy * h1) / h2);
4692 if (dy >= 2 * dx) return (dy + (dx * h1) / h2);
4693 return (((dx + dy) * 128) / 181 +
4694 (dx * dx / (dy * h3) + dy * dy / (dx * h3)) * h4);
4695 /* 128/181 is approx. 1/sqrt(2) */
4700 * Build target vault.
4701 * This is made by two concentric "crypts" with perpendicular
4702 * walls creating the cross-hairs.
4704 static void build_target_vault(int x0, int y0, int xsize, int ysize)
4708 /* Make a random metric */
4710 h1 = randint1(32) - 16;
4713 h4 = randint1(32) - 16;
4715 if (cheat_room) msg_print("Target Vault");
4717 /* work out outer radius */
4728 for (x = x0 - rad; x <= x0 + rad; x++)
4730 for (y = y0 - rad; y <= y0 + rad; y++)
4732 /* clear room flag */
4733 cave[y][x].info &= ~(CAVE_ROOM);
4735 /* Vault - so is "icky" */
4736 cave[y][x].info |= CAVE_ICKY;
4738 if (dist2(y0, x0, y, x, h1, h2, h3, h4) <= rad - 1)
4740 /* inside- so is floor */
4741 place_floor_bold(y, x);
4745 /* make granite outside so arena works */
4746 place_extra_bold(y, x);
4749 /* proper boundary for arena */
4750 if (((y + rad) == y0) || ((y - rad) == y0) ||
4751 ((x + rad) == x0) || ((x - rad) == x0))
4753 place_extra_bold(y, x);
4758 /* Find visible outer walls and set to be FEAT_OUTER */
4759 add_outer_wall(x0, y0, FALSE, x0 - rad - 1, y0 - rad - 1,
4760 x0 + rad + 1, y0 + rad + 1);
4762 /* Add inner wall */
4763 for (x = x0 - rad / 2; x <= x0 + rad / 2; x++)
4765 for (y = y0 - rad / 2; y <= y0 + rad / 2; y++)
4767 if (dist2(y0, x0, y, x, h1, h2, h3, h4) == rad / 2)
4769 /* Make an internal wall */
4770 place_inner_bold(y, x);
4775 /* Add perpendicular walls */
4776 for (x = x0 - rad; x <= x0 + rad; x++)
4778 place_inner_bold(y0, x);
4781 for (y = y0 - rad; y <= y0 + rad; y++)
4783 place_inner_bold(y, x0);
4786 /* Make inner vault */
4787 for (y = y0 - 1; y <= y0 + 1; y++)
4789 place_inner_bold(y, x0 - 1);
4790 place_inner_bold(y, x0 + 1);
4792 for (x = x0 - 1; x <= x0 + 1; x++)
4794 place_inner_bold(y0 - 1, x);
4795 place_inner_bold(y0 + 1, x);
4798 place_floor_bold(y0, x0);
4801 /* Add doors to vault */
4802 /* get two distances so can place doors relative to centre */
4803 x = (rad - 2) / 4 + 1;
4806 add_door(x0 + x, y0);
4807 add_door(x0 + y, y0);
4808 add_door(x0 - x, y0);
4809 add_door(x0 - y, y0);
4810 add_door(x0, y0 + x);
4811 add_door(x0, y0 + y);
4812 add_door(x0, y0 - x);
4813 add_door(x0, y0 - y);
4815 /* Fill with stuff - medium difficulty */
4816 fill_treasure(x0 - rad, x0 + rad, y0 - rad, y0 + rad, randint1(3) + 3);
4820 #ifdef ALLOW_CAVERNS_AND_LAKES
4822 * This routine uses a modified version of the lake code to make a
4823 * distribution of some terrain type over the vault. This type
4824 * depends on the dungeon depth.
4826 * Miniture rooms are then scattered across the vault.
4828 static void build_elemental_vault(int x0, int y0, int xsiz, int ysiz)
4833 int xsize, ysize, xhsize, yhsize, x, y, i;
4837 if (cheat_room) msg_print("Elemental Vault");
4839 /* round to make sizes even */
4847 /* Earth vault (Rubble) */
4850 else if (dun_level < 50)
4852 /* Air vault (Trees) */
4855 else if (dun_level < 75)
4857 /* Water vault (shallow water) */
4862 /* Fire vault (shallow lava) */
4868 /* testing values for these parameters: feel free to adjust */
4869 grd = 1 << (randint0(3));
4871 /* want average of about 16 */
4872 roug = randint1(8) * randint1(4);
4874 /* Make up size of various componants */
4878 /* Deep water/lava */
4879 c1 = randint0(c3 / 2) + randint0(c3 / 2) - 5;
4881 /* Shallow boundary */
4885 generate_hmap(y0, x0, xsize, ysize, grd, roug, c3);
4887 /* Convert to normal format+ clean up */
4888 done = generate_lake(y0, x0, xsize, ysize, c1, c2, c3, type);
4891 /* Set icky flag because is a vault */
4892 for (x = 0; x <= xsize; x++)
4894 for (y = 0; y <= ysize; y++)
4896 cave[y0 - yhsize + y][x0 - xhsize + x].info |= CAVE_ICKY;
4900 /* make a few rooms in the vault */
4901 for (i = 1; i <= (xsize * ysize) / 50; i++)
4903 build_small_room(x0 + randint0(xsize - 4) - xsize / 2 + 2,
4904 y0 + randint0(ysize - 4) - ysize / 2 + 2);
4907 /* Fill with monsters and treasure, low difficulty */
4908 fill_treasure(x0 - xhsize + 1, x0 - xhsize + xsize - 1,
4909 y0 - yhsize + 1, y0 - yhsize + ysize - 1, randint1(5));
4911 #endif /* ALLOW_CAVERNS_AND_LAKES */
4917 static void build_type10(int by0, int bx0)
4919 int y0, x0, xsize, ysize, vtype;
4922 /* big enough to look good, small enough to be fairly common. */
4923 xsize = randint1(22) + 22;
4924 ysize = randint1(11) + 11;
4926 /* Allocate in room_map. If will not fit, exit */
4927 if (!room_alloc(xsize + 1, ysize + 1, FALSE, by0, bx0, &x0, &y0)) return;
4929 /* Boost the rating- higher than lesser vaults and lower than greater vaults */
4932 /* (Sometimes) Cause a special feeling */
4933 if ((dun_level <= 50) ||
4934 (randint1((dun_level - 40) * (dun_level - 40) + 1) < 400))
4936 good_item_flag = TRUE;
4939 /* Select type of vault */
4940 #ifdef ALLOW_CAVERNS_AND_LAKES
4941 vtype = randint1(15);
4942 #else /* ALLOW_CAVERNS_AND_LAKES */
4943 vtype = randint1(7);
4944 #endif /* ALLOW_CAVERNS_AND_LAKES */
4948 /* Build an appropriate room */
4949 case 1: case 9: build_bubble_vault(x0, y0, xsize, ysize); break;
4950 case 2: case 10: build_room_vault(x0, y0, xsize, ysize); break;
4951 case 3: case 11: build_cave_vault(x0, y0, xsize, ysize); break;
4952 case 4: case 12: build_maze_vault(x0, y0, xsize, ysize, TRUE); break;
4953 case 5: case 13: build_mini_c_vault(x0, y0, xsize, ysize); break;
4954 case 6: case 14: build_castle_vault(x0, y0, xsize, ysize); break;
4955 case 7: case 15: build_target_vault(x0, y0, xsize, ysize); break;
4956 #ifdef ALLOW_CAVERNS_AND_LAKES
4957 case 8: build_elemental_vault(x0, y0, xsize, ysize); break;
4958 #endif /* ALLOW_CAVERNS_AND_LAKES */
4959 /* I know how to add a few more... give me some time. */
4968 * Build an vertical oval room.
4969 * For every grid in the possible square, check the distance.
4970 * If it's less than the radius, make it a room square.
4972 * When done fill from the inside to find the walls,
4974 static void build_type11(int by0, int bx0)
4976 int rad, x, y, x0, y0;
4979 /* Occasional light */
4980 if ((randint1(dun_level) <= 15) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS)) light = TRUE;
4984 /* Allocate in room_map. If will not fit, exit */
4985 if (!room_alloc(rad * 2 + 1, rad * 2 + 1, FALSE, by0, bx0, &x0, &y0)) return;
4987 /* Make circular floor */
4988 for (x = x0 - rad; x <= x0 + rad; x++)
4990 for (y = y0 - rad; y <= y0 + rad; y++)
4992 if (distance(y0, x0, y, x) <= rad - 1)
4994 /* inside- so is floor */
4995 place_floor_bold(y, x);
4997 else if (distance(y0, x0, y, x) <= rad + 1)
4999 /* make granite outside so arena works */
5000 place_extra_bold(y, x);
5005 /* Find visible outer walls and set to be FEAT_OUTER */
5006 add_outer_wall(x0, y0, light, x0 - rad, y0 - rad, x0 + rad, y0 + rad);
5012 * For every grid in the possible square, check the (fake) distance.
5013 * If it's less than the radius, make it a room square.
5015 * When done fill from the inside to find the walls,
5017 static void build_type12(int by0, int bx0)
5019 int rad, x, y, x0, y0;
5021 bool emptyflag = TRUE;
5023 /* Make a random metric */
5025 h1 = randint1(32) - 16;
5028 h4 = randint1(32) - 16;
5030 /* Occasional light */
5031 if ((randint1(dun_level) <= 5) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS)) light = TRUE;
5035 /* Allocate in room_map. If will not fit, exit */
5036 if (!room_alloc(rad * 2 + 3, rad * 2 + 3, FALSE, by0, bx0, &x0, &y0)) return;
5039 for (x = x0 - rad; x <= x0 + rad; x++)
5041 for (y = y0 - rad; y <= y0 + rad; y++)
5043 /* clear room flag */
5044 cave[y][x].info &= ~(CAVE_ROOM);
5046 if (dist2(y0, x0, y, x, h1, h2, h3, h4) <= rad - 1)
5048 /* inside - so is floor */
5049 place_floor_bold(y, x);
5051 else if (distance(y0, x0, y, x) < 3)
5053 place_floor_bold(y, x);
5057 /* make granite outside so arena works */
5058 place_extra_bold(y, x);
5061 /* proper boundary for arena */
5062 if (((y + rad) == y0) || ((y - rad) == y0) ||
5063 ((x + rad) == x0) || ((x - rad) == x0))
5065 place_extra_bold(y, x);
5070 /* Find visible outer walls and set to be FEAT_OUTER */
5071 add_outer_wall(x0, y0, light, x0 - rad - 1, y0 - rad - 1,
5072 x0 + rad + 1, y0 + rad + 1);
5074 /* Check to see if there is room for an inner vault */
5075 for (x = x0 - 2; x <= x0 + 2; x++)
5077 for (y = y0 - 2; y <= y0 + 2; y++)
5079 if (!is_floor_bold(y, x))
5081 /* Wall in the way */
5087 if (emptyflag && one_in_(2))
5089 /* Build the vault */
5090 build_small_room(x0, y0);
5092 /* Place a treasure in the vault */
5093 place_object(y0, x0, FALSE, FALSE);
5095 /* Let's guard the treasure well */
5096 vault_monsters(y0, x0, randint0(2) + 3);
5098 /* Traps naturally */
5099 vault_traps(y0, x0, 4, 4, randint0(3) + 2);
5105 * Attempt to build a room of the given type at the given block
5107 * Note that we restrict the number of "crowded" rooms to reduce
5108 * the chance of overflowing the monster list during level creation.
5110 bool room_build(int by0, int bx0, int typ)
5112 /* Restrict level */
5113 if ((dun_level < roomdep[typ]) && !ironman_rooms) return (FALSE);
5115 /* Restrict "crowded" rooms */
5116 if ((dun->crowded >= 2) && ((typ == 5) || (typ == 6))) return (FALSE);
5121 /* Build an appropriate room */
5122 case 12: build_type12(by0, bx0); break;
5123 case 11: build_type11(by0, bx0); break;
5124 case 10: build_type10(by0, bx0); break;
5125 case 9: build_type9(by0, bx0); break;
5126 case 8: build_type8(by0, bx0); break;
5127 case 7: build_type7(by0, bx0); break;
5128 case 6: build_type6(by0, bx0, FALSE); break;
5129 case 5: build_type5(by0, bx0, FALSE); break;
5130 case 4: build_type4(by0, bx0); break;
5131 case 3: build_type3(by0, bx0); break;
5132 case 2: build_type2(by0, bx0); break;
5133 case 1: build_type1(by0, bx0); break;
5136 default: return (FALSE);