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+randint(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 <= randint(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 */
355 if (rand_int(20) == 0)
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 (rand_int(20) == 0)
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 (rand_int(50) == 0)
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 (rand_int(50) == 0)
407 if (randint(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 <= randint(25)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS));
455 /* Determine extents of the first room */
456 y1a = yval - randint(4);
457 y2a = yval + randint(3);
458 x1a = xval - randint(11);
459 x2a = xval + randint(10);
461 /* Determine extents of the second room */
462 y1b = yval - randint(3);
463 y2b = yval + randint(4);
464 x1b = xval - randint(10);
465 x2b = xval + randint(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 <= randint(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, rand_int(2) + 3);
732 /* Traps naturally */
733 vault_traps(yval, xval, 4, 4, rand_int(3) + 2);
741 /* Occasionally pinch the center shut */
742 if (rand_int(3) == 0)
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 */
765 if (rand_int(3) == 0)
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 */
775 else if (rand_int(3) == 0)
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 */
790 else if (rand_int(3) == 0)
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 <= randint(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, randint(3) + 2);
941 if (rand_int(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 + randint(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 */
981 if (rand_int(2) == 0)
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 */
1000 if (rand_int(3) == 0)
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 + (randint(2) * 2), xval - 3);
1019 place_secret_door(yval - 3 + (randint(2) * 2), xval + 3);
1022 vault_monsters(yval, xval - 2, randint(2));
1023 vault_monsters(yval, xval + 2, randint(2));
1026 if (rand_int(3) == 0) place_object(yval, xval - 2, FALSE, FALSE);
1027 if (rand_int(3) == 0) place_object(yval, xval + 2, FALSE, FALSE);
1036 /* Place a secret door */
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, randint(3));
1060 vault_monsters(yval, xval + 5, randint(3));
1062 /* Traps make them entertaining. */
1063 vault_traps(yval, xval - 3, 2, 8, randint(3));
1064 vault_traps(yval, xval + 3, 2, 8, randint(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 (rand_int(100) < 50)
1090 int i = randint(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);
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 + randint(2));
1108 /* Gotta have some monsters. */
1109 vault_monsters(yval + 1, xval - 4, randint(4));
1110 vault_monsters(yval + 1, xval + 4, randint(4));
1111 vault_monsters(yval - 1, xval - 4, randint(4));
1112 vault_monsters(yval - 1, xval + 4, randint(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 monster_race *r_ptr = &r_info[r_idx];
1230 /* Validate the monster */
1231 if (!vault_monster_okay(r_idx)) return (FALSE);
1233 if (r_ptr->flags3 & (RF3_EVIL)) return (FALSE);
1234 if ((r_idx == MON_A_GOLD) || (r_idx == MON_A_SILVER)) return (FALSE);
1236 /* Require "priest" or Angel */
1237 if (!((r_ptr->d_char == 'A') ||
1239 strstr((r_name + r_ptr->E_name),"aladin") ||
1241 strstr((r_name + r_ptr->name),"aladin") ||
1244 strstr((r_name + r_ptr->E_name)," monk") ||
1246 strstr((r_name + r_ptr->name)," monk") ||
1249 strstr((r_name + r_ptr->E_name),"riest")))
1251 strstr((r_name + r_ptr->name),"riest")))
1264 * Helper function for "monster nest (kennel)"
1266 static bool vault_aux_kennel(int r_idx)
1268 monster_race *r_ptr = &r_info[r_idx];
1270 /* Validate the monster */
1271 if (!vault_monster_okay(r_idx)) return (FALSE);
1273 /* Require a Zephyr Hound or a dog */
1274 if (!strchr("CZ", r_ptr->d_char)) return (FALSE);
1282 * Helper function for "monster nest (mimic)"
1284 static bool vault_aux_mimic(int r_idx)
1286 monster_race *r_ptr = &r_info[r_idx];
1288 /* Validate the monster */
1289 if (!vault_monster_okay(r_idx)) return (FALSE);
1292 if (!strchr("!|$?=`", r_ptr->d_char)) return (FALSE);
1299 * Helper function for "monster nest (clone)"
1301 static bool vault_aux_clone(int r_idx)
1303 /* Validate the monster */
1304 if (!vault_monster_okay(r_idx)) return (FALSE);
1306 return (r_idx == vault_aux_race);
1311 * Helper function for "monster nest (symbol clone)"
1313 static bool vault_aux_symbol_e(int r_idx)
1315 monster_race *r_ptr = &r_info[r_idx];
1317 /* Validate the monster */
1318 if (!vault_monster_okay(r_idx)) return (FALSE);
1320 if (r_ptr->flags2 & (RF2_KILL_BODY)) return (FALSE);
1322 if (r_ptr->flags3 & (RF3_GOOD)) return (FALSE);
1324 /* Decline incorrect symbol */
1325 if (r_ptr->d_char != vault_aux_char) return (FALSE);
1333 * Helper function for "monster nest (symbol clone)"
1335 static bool vault_aux_symbol_g(int r_idx)
1337 monster_race *r_ptr = &r_info[r_idx];
1339 /* Validate the monster */
1340 if (!vault_monster_okay(r_idx)) return (FALSE);
1342 if (r_ptr->flags2 & (RF2_KILL_BODY)) return (FALSE);
1344 if (r_ptr->flags3 & (RF3_EVIL)) return (FALSE);
1346 /* Decline incorrect symbol */
1347 if (r_ptr->d_char != vault_aux_char) return (FALSE);
1355 * Helper function for "monster pit (orc)"
1357 static bool vault_aux_orc(int r_idx)
1359 monster_race *r_ptr = &r_info[r_idx];
1361 /* Validate the monster */
1362 if (!vault_monster_okay(r_idx)) return (FALSE);
1365 if (!(r_ptr->flags3 & RF3_ORC)) return (FALSE);
1367 /* Decline undead */
1368 if (r_ptr->flags3 & RF3_UNDEAD) return (FALSE);
1376 * Helper function for "monster pit (troll)"
1378 static bool vault_aux_troll(int r_idx)
1380 monster_race *r_ptr = &r_info[r_idx];
1382 /* Validate the monster */
1383 if (!vault_monster_okay(r_idx)) return (FALSE);
1386 if (!(r_ptr->flags3 & RF3_TROLL)) return (FALSE);
1388 /* Decline undead */
1389 if (r_ptr->flags3 & RF3_UNDEAD) return (FALSE);
1397 * Helper function for "monster pit (giant)"
1399 static bool vault_aux_giant(int r_idx)
1401 monster_race *r_ptr = &r_info[r_idx];
1403 /* Validate the monster */
1404 if (!vault_monster_okay(r_idx)) return (FALSE);
1407 if (!(r_ptr->flags3 & RF3_GIANT)) return (FALSE);
1409 if (r_ptr->flags3 & RF3_GOOD) return (FALSE);
1411 /* Decline undead */
1412 if (r_ptr->flags3 & RF3_UNDEAD) return (FALSE);
1420 * Helper function for "monster pit (dragon)"
1422 static bool vault_aux_dragon(int r_idx)
1424 monster_race *r_ptr = &r_info[r_idx];
1426 /* Validate the monster */
1427 if (!vault_monster_okay(r_idx)) return (FALSE);
1429 /* Require dragon */
1430 if (!(r_ptr->flags3 & RF3_DRAGON)) return (FALSE);
1432 /* Hack -- Require correct "breath attack" */
1433 if (r_ptr->flags4 != vault_aux_dragon_mask4) return (FALSE);
1435 /* Decline undead */
1436 if (r_ptr->flags3 & RF3_UNDEAD) return (FALSE);
1444 * Helper function for "monster pit (demon)"
1446 static bool vault_aux_demon(int r_idx)
1448 monster_race *r_ptr = &r_info[r_idx];
1450 /* Validate the monster */
1451 if (!vault_monster_okay(r_idx)) return (FALSE);
1453 if (r_ptr->flags2 & (RF2_KILL_BODY)) return (FALSE);
1456 if (!(r_ptr->flags3 & RF3_DEMON)) return (FALSE);
1464 * Helper function for "monster pit (lovecraftian)"
1466 static bool vault_aux_cthulhu(int r_idx)
1468 monster_race *r_ptr = &r_info[r_idx];
1470 /* Validate the monster */
1471 if (!vault_monster_okay(r_idx)) return (FALSE);
1473 if (r_ptr->flags2 & (RF2_KILL_BODY)) return (FALSE);
1475 /* Require eldritch horror */
1476 if (!(r_ptr->flags2 & (RF2_ELDRITCH_HORROR))) return (FALSE);
1484 * Helper function for "monster pit (clone)"
1486 static void vault_prep_clone(void)
1488 /* Apply the monster restriction */
1489 get_mon_num_prep(vault_aux_simple, NULL);
1491 /* Pick a race to clone */
1492 vault_aux_race = get_mon_num(dun_level + 10);
1494 /* Remove the monster restriction */
1495 get_mon_num_prep(NULL, NULL);
1500 * Helper function for "monster pit (symbol clone)"
1502 static void vault_prep_symbol(void)
1506 /* Apply the monster restriction */
1507 get_mon_num_prep(vault_aux_simple, NULL);
1509 /* Pick a race to clone */
1510 r_idx = get_mon_num(dun_level + 10);
1512 /* Remove the monster restriction */
1513 get_mon_num_prep(NULL, NULL);
1515 /* Extract the symbol */
1516 vault_aux_char = r_info[r_idx].d_char;
1521 * Helper function for "monster pit (dragon)"
1523 static void vault_prep_dragon(void)
1525 /* Pick dragon type */
1526 switch (rand_int(6))
1531 /* Restrict dragon breath type */
1532 vault_aux_dragon_mask4 = RF4_BR_ACID;
1541 /* Restrict dragon breath type */
1542 vault_aux_dragon_mask4 = RF4_BR_ELEC;
1551 /* Restrict dragon breath type */
1552 vault_aux_dragon_mask4 = RF4_BR_FIRE;
1561 /* Restrict dragon breath type */
1562 vault_aux_dragon_mask4 = RF4_BR_COLD;
1571 /* Restrict dragon breath type */
1572 vault_aux_dragon_mask4 = RF4_BR_POIS;
1581 /* Restrict dragon breath type */
1582 vault_aux_dragon_mask4 = (RF4_BR_ACID | RF4_BR_ELEC |
1583 RF4_BR_FIRE | RF4_BR_COLD |
1596 typedef struct vault_aux_type vault_aux_type;
1599 struct vault_aux_type
1602 bool (*hook_func)(int r_idx);
1603 void (*prep_func)(void);
1609 static vault_aux_type *pick_vault_type(vault_aux_type *l_ptr, int room)
1611 int tmp, total, count;
1613 vault_aux_type *n_ptr;
1615 /* Calculate the total possibilities */
1616 for (n_ptr = l_ptr, total = 0, count = 0; TRUE; n_ptr++, count++)
1619 if (!n_ptr->name) break;
1621 /* Ignore excessive depth */
1622 if (n_ptr->level > dun_level) continue;
1624 if (room == ROOM_PIT)
1626 if (!(d_info[dungeon_type].pit & (1L << count))) continue;
1628 else if (room == ROOM_NEST)
1630 if(!(d_info[dungeon_type].nest & (1L << count))) continue;
1633 /* Count this possibility */
1634 total += n_ptr->chance * MAX_DEPTH / (MIN(dun_level, MAX_DEPTH - 1) - n_ptr->level + 5);
1637 /* Pick a random type */
1638 tmp = rand_int(total);
1640 /* Find this type */
1641 for (n_ptr = l_ptr, total = 0, count = 0; TRUE; n_ptr++, count++)
1644 if (!n_ptr->name) break;
1646 /* Ignore excessive depth */
1647 if (n_ptr->level > dun_level) continue;
1649 if (room == ROOM_PIT)
1651 if (!(d_info[dungeon_type].pit & (1L << count))) continue;
1653 else if (room == ROOM_NEST)
1655 if(!(d_info[dungeon_type].nest & (1L << count))) continue;
1658 /* Count this possibility */
1659 total += n_ptr->chance * MAX_DEPTH / (MIN(dun_level, MAX_DEPTH - 1) - n_ptr->level + 5);
1661 /* Found the type */
1662 if (tmp < total) break;
1665 return (n_ptr->name ? n_ptr : NULL);
1668 void build_type6(int by0, int bx0, bool nest);
1669 void build_type5(int by0, int bx0, bool nest);
1671 static vault_aux_type nest_types[] =
1674 {"¥¯¥í¡¼¥ó", vault_aux_clone, vault_prep_clone, 5, 3},
1675 {"¥¼¥ê¡¼", vault_aux_jelly, NULL, 5, 6},
1676 {"¥·¥ó¥Ü¥ë(Á±)",vault_aux_symbol_g, vault_prep_symbol, 25, 2},
1677 {"¥·¥ó¥Ü¥ë(°)",vault_aux_symbol_e, vault_prep_symbol, 25, 2},
1678 {"¥ß¥ß¥Ã¥¯", vault_aux_mimic, NULL, 30, 4},
1679 {"¶¸µ¤", vault_aux_cthulhu, NULL, 70, 2},
1680 {"¸¤¾®²°", vault_aux_kennel, NULL, 45, 4},
1681 {"ưʪ±à", vault_aux_animal, NULL, 35, 5},
1682 {"¶µ²ñ", vault_aux_chapel_g, NULL, 75, 4},
1683 {"¥¢¥ó¥Ç¥Ã¥É", vault_aux_undead, NULL, 75, 5},
1684 {NULL, NULL, NULL, 0, 0},
1686 {"clone", vault_aux_clone, vault_prep_clone, 7, 3},
1687 {"jelly", vault_aux_jelly, NULL, 7, 6},
1688 {"symbol good",vault_aux_symbol_g, vault_prep_symbol, 25, 2},
1689 {"symbol evil",vault_aux_symbol_e, vault_prep_symbol, 25, 2},
1690 {"mimic", vault_aux_mimic, NULL, 45, 6},
1691 {"lovecraftian",vault_aux_cthulhu, NULL, 80, 2},
1692 {"kennel", vault_aux_kennel, NULL, 50, 2},
1693 {"animal", vault_aux_animal, NULL, 50, 4},
1694 {"chapel", vault_aux_chapel_g, NULL, 90, 2},
1695 {"undead", vault_aux_undead, NULL, 90, 4},
1696 {NULL, NULL, NULL, 0, 0},
1702 * Type 5 -- Monster nests
1704 * A monster nest is a "big" room, with an "inner" room, containing
1705 * a "collection" of monsters of a given type strewn about the room.
1707 * The monsters are chosen from a set of 64 randomly selected monster
1708 * races, to allow the nest creation to fail instead of having "holes".
1710 * Note the use of the "get_mon_num_prep()" function, and the special
1711 * "get_mon_num_hook()" restriction function, to prepare the "monster
1712 * allocation table" in such a way as to optimize the selection of
1713 * "appropriate" non-unique monsters for the nest.
1715 * Note that the "get_mon_num()" function may (rarely) fail, in which
1716 * case the nest will be empty, and will not affect the level rating.
1718 * Note that "monster nests" will never contain "unique" monsters.
1720 void build_type5(int by0, int bx0, bool pit)
1722 int y, x, y1, x1, y2, x2, xval, yval;
1730 vault_aux_type *n_ptr = pick_vault_type(nest_types, ROOM_NEST);
1732 /* Try to allocate space for room. */
1733 if (!room_alloc(25, 11, TRUE, by0, bx0, &xval, &yval)) return;
1735 /* No type available */
1739 else {build_type6(by0, bx0, TRUE);return;}
1742 /* Process a preparation function if necessary */
1743 if (n_ptr->prep_func) (*(n_ptr->prep_func))();
1751 /* Place the floor area */
1752 for (y = y1 - 1; y <= y2 + 1; y++)
1754 for (x = x1 - 1; x <= x2 + 1; x++)
1756 c_ptr = &cave[y][x];
1757 place_floor_grid(c_ptr);
1758 c_ptr->info |= (CAVE_ROOM);
1762 /* Place the outer walls */
1763 for (y = y1 - 1; y <= y2 + 1; y++)
1765 c_ptr = &cave[y][x1 - 1];
1766 place_outer_grid(c_ptr);
1767 c_ptr = &cave[y][x2 + 1];
1768 place_outer_grid(c_ptr);
1770 for (x = x1 - 1; x <= x2 + 1; x++)
1772 c_ptr = &cave[y1 - 1][x];
1773 place_outer_grid(c_ptr);
1774 c_ptr = &cave[y2 + 1][x];
1775 place_outer_grid(c_ptr);
1779 /* Advance to the center room */
1785 /* The inner walls */
1786 for (y = y1 - 1; y <= y2 + 1; y++)
1788 c_ptr = &cave[y][x1 - 1];
1789 place_inner_grid(c_ptr);
1790 c_ptr = &cave[y][x2 + 1];
1791 place_inner_grid(c_ptr);
1794 for (x = x1 - 1; x <= x2 + 1; x++)
1796 c_ptr = &cave[y1 - 1][x];
1797 place_inner_grid(c_ptr);
1798 c_ptr = &cave[y2 + 1][x];
1799 place_inner_grid(c_ptr);
1801 for (y = y1; y <= y2; y++)
1803 for (x = x1; x <= x2; x++)
1805 add_cave_info(y, x, CAVE_ICKY);
1810 /* Place a secret door */
1813 case 1: place_secret_door(y1 - 1, xval); break;
1814 case 2: place_secret_door(y2 + 1, xval); break;
1815 case 3: place_secret_door(yval, x1 - 1); break;
1816 case 4: place_secret_door(yval, x2 + 1); break;
1820 /* Prepare allocation table */
1821 get_mon_num_prep(n_ptr->hook_func, NULL);
1823 /* Pick some monster types */
1824 for (i = 0; i < 64; i++)
1826 int r_idx = 0, attempts = 100;
1830 /* Get a (hard) monster type */
1831 r_idx = get_mon_num(dun_level + 10);
1833 /* Decline incorrect alignment */
1834 if (((align < 0) && (r_info[r_idx].flags3 & RF3_GOOD)) ||
1835 ((align > 0) && (r_info[r_idx].flags3 & RF3_EVIL)))
1840 /* Accept this monster */
1844 /* Notice failure */
1845 if (!r_idx || !attempts) return;
1847 /* Note the alignment */
1848 if (r_info[r_idx].flags3 & RF3_GOOD) align++;
1849 else if (r_info[r_idx].flags3 & RF3_EVIL) align--;
1859 msg_format("¥â¥ó¥¹¥¿¡¼Éô²°(%s)", n_ptr->name);
1861 msg_format("Monster nest (%s)", n_ptr->name);
1867 /* Increase the level rating */
1870 /* (Sometimes) Cause a "special feeling" (for "Monster Nests") */
1871 if ((dun_level <= 40) && (randint(dun_level * dun_level + 50) < 300))
1873 good_item_flag = TRUE;
1876 /* Place some monsters */
1877 for (y = yval - 2; y <= yval + 2; y++)
1879 for (x = xval - 9; x <= xval + 9; x++)
1881 int r_idx = what[rand_int(64)];
1883 /* Place that "random" monster (no groups) */
1884 (void)place_monster_aux(y, x, r_idx, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE);
1890 static vault_aux_type pit_types[] =
1893 {"¥ª¡¼¥¯", vault_aux_orc, NULL, 5, 6},
1894 {"¥È¥í¥ë", vault_aux_troll, NULL, 20, 6},
1895 {"¥¸¥ã¥¤¥¢¥ó¥È",vault_aux_giant, NULL, 50, 6},
1896 {"¶¸µ¤", vault_aux_cthulhu, NULL, 80, 2},
1897 {"¥·¥ó¥Ü¥ë(Á±)",vault_aux_symbol_g, vault_prep_symbol, 70, 1},
1898 {"¥·¥ó¥Ü¥ë(°)",vault_aux_symbol_e, vault_prep_symbol, 70, 1},
1899 {"¶µ²ñ", vault_aux_chapel_g, NULL, 65, 2},
1900 {"¥É¥é¥´¥ó", vault_aux_dragon, vault_prep_dragon, 70, 6},
1901 {"¥Ç¡¼¥â¥ó", vault_aux_demon, NULL, 80, 6},
1902 {NULL, NULL, NULL, 0, 0},
1904 {"orc", vault_aux_orc, NULL, 7, 4},
1905 {"troll", vault_aux_troll, NULL, 35, 4},
1906 {"giant", vault_aux_giant, NULL, 70, 4},
1907 {"lovecraftian",vault_aux_cthulhu, NULL, 90, 4},
1908 {"symbol good",vault_aux_symbol_g, vault_prep_symbol, 25, 2},
1909 {"symbol evil",vault_aux_symbol_e, vault_prep_symbol, 25, 2},
1910 {"chapel", vault_aux_chapel_g, NULL, 85, 1},
1911 {"dragon", vault_aux_dragon, vault_prep_dragon, 80, 4},
1912 {"demon", vault_aux_demon, NULL, 90, 4},
1913 {NULL, NULL, NULL, 0, 0},
1919 * Type 6 -- Monster pits
1921 * A monster pit is a "big" room, with an "inner" room, containing
1922 * a "collection" of monsters of a given type organized in the room.
1924 * The inside room in a monster pit appears as shown below, where the
1925 * actual monsters in each location depend on the type of the pit
1927 * #####################
1928 * #0000000000000000000#
1929 * #0112233455543322110#
1930 * #0112233467643322110#
1931 * #0112233455543322110#
1932 * #0000000000000000000#
1933 * #####################
1935 * Note that the monsters in the pit are now chosen by using "get_mon_num()"
1936 * to request 16 "appropriate" monsters, sorting them by level, and using
1937 * the "even" entries in this sorted list for the contents of the pit.
1939 * Hack -- all of the "dragons" in a "dragon" pit must be the same "color",
1940 * which is handled by requiring a specific "breath" attack for all of the
1941 * dragons. This may include "multi-hued" breath. Note that "wyrms" may
1942 * be present in many of the dragon pits, if they have the proper breath.
1944 * Note the use of the "get_mon_num_prep()" function, and the special
1945 * "get_mon_num_hook()" restriction function, to prepare the "monster
1946 * allocation table" in such a way as to optimize the selection of
1947 * "appropriate" non-unique monsters for the pit.
1949 * Note that the "get_mon_num()" function may (rarely) fail, in which case
1950 * the pit will be empty, and will not effect the level rating.
1952 * Note that "monster pits" will never contain "unique" monsters.
1954 void build_type6(int by0, int bx0, bool nest)
1956 int y, x, y1, x1, y2, x2, xval, yval;
1965 vault_aux_type *n_ptr = pick_vault_type(pit_types, ROOM_PIT);
1967 /* Try to allocate space for room. */
1968 if (!room_alloc(25, 11, TRUE, by0, bx0, &xval, &yval)) return;
1970 /* No type available */
1974 else {build_type5(by0, bx0, TRUE);return;}
1977 /* Process a preparation function if necessary */
1978 if (n_ptr->prep_func) (*(n_ptr->prep_func))();
1986 /* Place the floor area */
1987 for (y = y1 - 1; y <= y2 + 1; y++)
1989 for (x = x1 - 1; x <= x2 + 1; x++)
1991 c_ptr = &cave[y][x];
1992 place_floor_grid(c_ptr);
1993 c_ptr->info |= (CAVE_ROOM);
1997 /* Place the outer walls */
1998 for (y = y1 - 1; y <= y2 + 1; y++)
2000 c_ptr = &cave[y][x1 - 1];
2001 place_outer_grid(c_ptr);
2002 c_ptr = &cave[y][x2 + 1];
2003 place_outer_grid(c_ptr);
2005 for (x = x1 - 1; x <= x2 + 1; x++)
2007 c_ptr = &cave[y1 - 1][x];
2008 place_outer_grid(c_ptr);
2009 c_ptr = &cave[y2 + 1][x];
2010 place_outer_grid(c_ptr);
2013 /* Advance to the center room */
2019 /* The inner walls */
2020 for (y = y1 - 1; y <= y2 + 1; y++)
2022 c_ptr = &cave[y][x1 - 1];
2023 place_inner_grid(c_ptr);
2024 c_ptr = &cave[y][x2 + 1];
2025 place_inner_grid(c_ptr);
2027 for (x = x1 - 1; x <= x2 + 1; x++)
2029 c_ptr = &cave[y1 - 1][x];
2030 place_inner_grid(c_ptr);
2031 c_ptr = &cave[y2 + 1][x];
2032 place_inner_grid(c_ptr);
2034 for (y = y1; y <= y2; y++)
2036 for (x = x1; x <= x2; x++)
2038 add_cave_info(y, x, CAVE_ICKY);
2042 /* Place a secret door */
2045 case 1: place_secret_door(y1 - 1, xval); break;
2046 case 2: place_secret_door(y2 + 1, xval); break;
2047 case 3: place_secret_door(yval, x1 - 1); break;
2048 case 4: place_secret_door(yval, x2 + 1); break;
2052 /* Prepare allocation table */
2053 get_mon_num_prep(n_ptr->hook_func, NULL);
2055 /* Pick some monster types */
2056 for (i = 0; i < 16; i++)
2058 int r_idx = 0, attempts = 100;
2062 /* Get a (hard) monster type */
2063 r_idx = get_mon_num(dun_level + 10);
2065 /* Decline incorrect alignment */
2066 if (((align < 0) && (r_info[r_idx].flags3 & RF3_GOOD)) ||
2067 ((align > 0) && (r_info[r_idx].flags3 & RF3_EVIL)))
2072 /* Accept this monster */
2076 /* Notice failure */
2077 if (!r_idx || !attempts) return;
2079 /* Note the alignment */
2080 if (r_info[r_idx].flags3 & RF3_GOOD) align++;
2081 else if (r_info[r_idx].flags3 & RF3_EVIL) align--;
2086 /* Sort the entries */
2087 for (i = 0; i < 16 - 1; i++)
2089 /* Sort the entries */
2090 for (j = 0; j < 16 - 1; j++)
2095 int p1 = r_info[what[i1]].level;
2096 int p2 = r_info[what[i2]].level;
2102 what[i1] = what[i2];
2112 msg_format("%s¤ÎÁã", n_ptr->name);
2115 msg_format("Monster pit (%s)", n_ptr->name);
2119 /* Select the entries */
2120 for (i = 0; i < 8; i++)
2122 /* Every other entry */
2123 what[i] = what[i * 2];
2128 msg_print(r_name + r_info[what[i]].name);
2132 /* Increase the level rating */
2135 /* (Sometimes) Cause a "special feeling" (for "Monster Pits") */
2136 if ((dun_level <= 40) && (randint(dun_level * dun_level + 50) < 300))
2138 good_item_flag = TRUE;
2141 /* Top and bottom rows */
2142 for (x = xval - 9; x <= xval + 9; x++)
2144 place_monster_aux(yval - 2, x, what[0], FALSE, FALSE, FALSE, FALSE, TRUE, FALSE);
2145 place_monster_aux(yval + 2, x, what[0], FALSE, FALSE, FALSE, FALSE, TRUE, FALSE);
2148 /* Middle columns */
2149 for (y = yval - 1; y <= yval + 1; y++)
2151 place_monster_aux(y, xval - 9, what[0], FALSE, FALSE, FALSE, FALSE, TRUE, FALSE);
2152 place_monster_aux(y, xval + 9, what[0], FALSE, FALSE, FALSE, FALSE, TRUE, FALSE);
2154 place_monster_aux(y, xval - 8, what[1], FALSE, FALSE, FALSE, FALSE, TRUE, FALSE);
2155 place_monster_aux(y, xval + 8, what[1], FALSE, FALSE, FALSE, FALSE, TRUE, FALSE);
2157 place_monster_aux(y, xval - 7, what[1], FALSE, FALSE, FALSE, FALSE, TRUE, FALSE);
2158 place_monster_aux(y, xval + 7, what[1], FALSE, FALSE, FALSE, FALSE, TRUE, FALSE);
2160 place_monster_aux(y, xval - 6, what[2], FALSE, FALSE, FALSE, FALSE, TRUE, FALSE);
2161 place_monster_aux(y, xval + 6, what[2], FALSE, FALSE, FALSE, FALSE, TRUE, FALSE);
2163 place_monster_aux(y, xval - 5, what[2], FALSE, FALSE, FALSE, FALSE, TRUE, FALSE);
2164 place_monster_aux(y, xval + 5, what[2], FALSE, FALSE, FALSE, FALSE, TRUE, FALSE);
2166 place_monster_aux(y, xval - 4, what[3], FALSE, FALSE, FALSE, FALSE, TRUE, FALSE);
2167 place_monster_aux(y, xval + 4, what[3], FALSE, FALSE, FALSE, FALSE, TRUE, FALSE);
2169 place_monster_aux(y, xval - 3, what[3], FALSE, FALSE, FALSE, FALSE, TRUE, FALSE);
2170 place_monster_aux(y, xval + 3, what[3], FALSE, FALSE, FALSE, FALSE, TRUE, FALSE);
2172 place_monster_aux(y, xval - 2, what[4], FALSE, FALSE, FALSE, FALSE, TRUE, FALSE);
2173 place_monster_aux(y, xval + 2, what[4], FALSE, FALSE, FALSE, FALSE, TRUE, FALSE);
2176 /* Above/Below the center monster */
2177 for (x = xval - 1; x <= xval + 1; x++)
2179 place_monster_aux(yval + 1, x, what[5], FALSE, FALSE, FALSE, FALSE, TRUE, FALSE);
2180 place_monster_aux(yval - 1, x, what[5], FALSE, FALSE, FALSE, FALSE, TRUE, FALSE);
2183 /* Next to the center monster */
2184 place_monster_aux(yval, xval + 1, what[6], FALSE, FALSE, FALSE, FALSE, TRUE, FALSE);
2185 place_monster_aux(yval, xval - 1, what[6], FALSE, FALSE, FALSE, FALSE, TRUE, FALSE);
2187 /* Center monster */
2188 place_monster_aux(yval, xval, what[7], FALSE, FALSE, FALSE, FALSE, TRUE, FALSE);
2192 /* coordinate translation code */
2193 static void coord_trans(int *x, int *y, int xoffset, int yoffset, int transno)
2199 * transno specifies what transformation is required. (0-7)
2200 * The lower two bits indicate by how much the vault is rotated,
2201 * and the upper bit indicates a reflection.
2202 * This is done by using rotation matrices... however since
2203 * these are mostly zeros for rotations by 90 degrees this can
2204 * be expressed simply in terms of swapping and inverting the
2205 * x and y coordinates.
2207 for (i = 0; i <= transno % 4; i++)
2209 /* rotate by 90 degrees */
2217 /* Reflect depending on status of 3rd bit. */
2221 /* Add offsets so vault stays in the first quadrant */
2228 * Hack -- fill in "vault" rooms
2230 static void build_vault(int yval, int xval, int ymax, int xmax, cptr data,
2231 int xoffset, int yoffset, int transno)
2233 int dx, dy, x, y, i, j;
2240 /* Place dungeon features and objects */
2241 for (t = data, dy = 0; dy < ymax; dy++)
2243 for (dx = 0; dx < xmax; dx++, t++)
2245 /* prevent loop counter from being overwritten */
2250 coord_trans(&i, &j, xoffset, yoffset, transno);
2252 /* Extract the location */
2255 /* no swap of x/y */
2256 x = xval - (xmax / 2) + i;
2257 y = yval - (ymax / 2) + j;
2262 x = xval - (ymax / 2) + i;
2263 y = yval - (xmax / 2) + j;
2266 /* Hack -- skip "non-grids" */
2267 if (*t == ' ') continue;
2269 /* Access the grid */
2270 c_ptr = &cave[y][x];
2272 /* Lay down a floor */
2273 place_floor_grid(c_ptr);
2275 /* Part of a vault */
2276 c_ptr->info |= (CAVE_ROOM | CAVE_ICKY);
2278 /* Analyze the grid */
2281 /* Granite wall (outer) */
2283 place_outer_noperm_grid(c_ptr);
2286 /* Granite wall (inner) */
2288 place_inner_grid(c_ptr);
2291 /* Permanent wall (inner) */
2293 c_ptr->feat = FEAT_PERM_INNER;
2294 c_ptr->info &= ~(CAVE_MASK);
2295 c_ptr->info |= CAVE_INNER;
2300 if (rand_int(100) < 75)
2302 place_object(y, x, FALSE, FALSE);
2312 place_secret_door(y, x);
2324 /* Place dungeon monsters and objects */
2325 for (t = data, dy = 0; dy < ymax; dy++)
2327 for (dx = 0; dx < xmax; dx++, t++)
2329 /* prevent loop counter from being overwritten */
2334 coord_trans(&i, &j, xoffset, yoffset, transno);
2336 /* Extract the location */
2339 /* no swap of x/y */
2340 x = xval - (xmax / 2) + i;
2341 y = yval - (ymax / 2) + j;
2346 x = xval - (ymax / 2) + i;
2347 y = yval - (xmax / 2) + j;
2350 /* Hack -- skip "non-grids" */
2351 if (*t == ' ') continue;
2353 /* Analyze the symbol */
2359 monster_level = base_level + 5;
2360 place_monster(y, x, TRUE, TRUE);
2361 monster_level = base_level;
2365 /* Meaner monster */
2368 monster_level = base_level + 11;
2369 place_monster(y, x, TRUE, TRUE);
2370 monster_level = base_level;
2374 /* Meaner monster, plus treasure */
2377 monster_level = base_level + 9;
2378 place_monster(y, x, TRUE, TRUE);
2379 monster_level = base_level;
2380 object_level = base_level + 7;
2381 place_object(y, x, TRUE, FALSE);
2382 object_level = base_level;
2386 /* Nasty monster and treasure */
2389 monster_level = base_level + 40;
2390 place_monster(y, x, TRUE, TRUE);
2391 monster_level = base_level;
2392 object_level = base_level + 20;
2393 place_object(y, x, TRUE, TRUE);
2394 object_level = base_level;
2398 /* Monster and/or object */
2401 if (rand_int(100) < 50)
2403 monster_level = base_level + 3;
2404 place_monster(y, x, TRUE, TRUE);
2405 monster_level = base_level;
2407 if (rand_int(100) < 50)
2409 object_level = base_level + 7;
2410 place_object(y, x, FALSE, FALSE);
2411 object_level = base_level;
2417 cave_set_feat(y, x, FEAT_SHOP_HEAD + STORE_BLACK);
2418 store_init(NO_TOWN, STORE_BLACK);
2422 cave_set_feat(y, x, FEAT_PATTERN_START);
2426 cave_set_feat(y, x, FEAT_PATTERN_1);
2430 cave_set_feat(y, x, FEAT_PATTERN_2);
2434 cave_set_feat(y, x, FEAT_PATTERN_3);
2438 cave_set_feat(y, x, FEAT_PATTERN_4);
2442 cave_set_feat(y, x, FEAT_PATTERN_END);
2446 cave_set_feat(y, x, FEAT_PATTERN_XTRA1);
2451 object_level = base_level + 12;
2452 place_object(y, x, TRUE, FALSE);
2453 object_level = base_level;
2463 * Type 7 -- simple vaults (see "v_info.txt")
2465 static void build_type7(int by0, int bx0)
2467 vault_type *v_ptr = NULL;
2471 int xoffset, yoffset;
2474 /* Pick a lesser vault */
2475 while (dummy < SAFE_MAX_ATTEMPTS)
2479 /* Access a random vault record */
2480 v_ptr = &v_info[rand_int(max_v_idx)];
2482 /* Accept the first lesser vault */
2483 if (v_ptr->typ == 7) break;
2486 /* No lesser vault found */
2489 /* pick type of transformation (0-7) */
2490 transno = rand_int(8);
2492 /* calculate offsets */
2496 coord_trans(&x, &y, 0, 0, transno);
2516 /* Try to allocate space for room. */
2517 if (!room_alloc(abs(x), abs(y), FALSE, by0, bx0, &xval, &yval)) return;
2519 if (dummy >= SAFE_MAX_ATTEMPTS)
2524 msg_print("·Ù¹ð¡ª¾®¤µ¤ÊÃϲ¼¼¼¤òÇÛÃ֤Ǥ¤Þ¤»¤ó¡ª");
2526 msg_print("Warning! Could not place lesser vault!");
2539 if (cheat_room) msg_format("%s", v_name + v_ptr->name);
2541 /* Boost the rating */
2542 rating += v_ptr->rat;
2544 /* (Sometimes) Cause a special feeling */
2545 if ((dun_level <= 50) ||
2546 (randint((dun_level - 40) * (dun_level - 40) + 50) < 400))
2548 good_item_flag = TRUE;
2551 /* Hack -- Build the vault */
2552 build_vault(yval, xval, v_ptr->hgt, v_ptr->wid,
2553 v_text + v_ptr->text, xoffset, yoffset, transno);
2558 * Type 8 -- greater vaults (see "v_info.txt")
2560 static void build_type8(int by0, int bx0)
2562 vault_type *v_ptr = NULL;
2567 int xoffset, yoffset;
2569 /* Pick a greater vault */
2570 while (dummy < SAFE_MAX_ATTEMPTS)
2574 /* Access a random vault record */
2575 v_ptr = &v_info[rand_int(max_v_idx)];
2577 /* Accept the first greater vault */
2578 if (v_ptr->typ == 8) break;
2581 /* No greater vault found */
2584 /* pick type of transformation (0-7) */
2585 transno = rand_int(8);
2587 /* calculate offsets */
2591 coord_trans(&x, &y, 0, 0, transno);
2611 /* Try to allocate space for room. If fails, exit */
2612 if (!room_alloc(abs(x), abs(y), FALSE, by0, bx0, &xval, &yval)) return;
2614 if (dummy >= SAFE_MAX_ATTEMPTS)
2619 msg_print("·Ù¹ð¡ªµðÂç¤ÊÃϲ¼¼¼¤òÇÛÃ֤Ǥ¤Þ¤»¤ó¡ª");
2621 msg_print("Warning! Could not place greater vault!");
2630 v_ptr = &v_info[76 + randint(3)];
2634 if (cheat_room) msg_format("%s", v_name + v_ptr->name);
2636 /* Boost the rating */
2637 rating += v_ptr->rat;
2639 /* (Sometimes) Cause a special feeling */
2640 if ((dun_level <= 50) ||
2641 (randint((dun_level - 40) * (dun_level - 40) + 50) < 400))
2643 good_item_flag = TRUE;
2646 /* Hack -- Build the vault */
2647 build_vault(yval, xval, v_ptr->hgt, v_ptr->wid,
2648 v_text + v_ptr->text, xoffset, yoffset, transno);
2652 * Structure to hold all "fill" data
2655 typedef struct fill_data_type fill_data_type;
2657 struct fill_data_type
2670 /* features to fill with */
2679 /* number of filled squares */
2683 static fill_data_type fill_data;
2686 /* Store routine for the fractal cave generator */
2687 /* this routine probably should be an inline function or a macro. */
2688 static void store_height(int x, int y, int val)
2690 /* if on boundary set val > cutoff so walls are not as square */
2691 if (((x == fill_data.xmin) || (y == fill_data.ymin) ||
2692 (x == fill_data.xmax) || (y == fill_data.ymax)) &&
2693 (val <= fill_data.c1)) val = fill_data.c1 + 1;
2695 /* store the value in height-map format */
2696 cave[y][x].feat = val;
2703 * Explanation of the plasma fractal algorithm:
2705 * A grid of points is created with the properties of a 'height-map'
2706 * This is done by making the corners of the grid have a random value.
2707 * The grid is then subdivided into one with twice the resolution.
2708 * The new points midway between two 'known' points can be calculated
2709 * by taking the average value of the 'known' ones and randomly adding
2710 * or subtracting an amount proportional to the distance between those
2711 * points. The final 'middle' points of the grid are then calculated
2712 * by averaging all four of the originally 'known' corner points. An
2713 * random amount is added or subtracted from this to get a value of the
2714 * height at that point. The scaling factor here is adjusted to the
2715 * slightly larger distance diagonally as compared to orthogonally.
2717 * This is then repeated recursively to fill an entire 'height-map'
2718 * A rectangular map is done the same way, except there are different
2719 * scaling factors along the x and y directions.
2721 * A hack to change the amount of correlation between points is done using
2722 * the grd variable. If the current step size is greater than grd then
2723 * the point will be random, otherwise it will be calculated by the
2724 * above algorithm. This makes a maximum distance at which two points on
2725 * the height map can affect each other.
2727 * How fractal caves are made:
2729 * When the map is complete, a cut-off value is used to create a cave.
2730 * Heights below this value are "floor", and heights above are "wall".
2731 * This also can be used to create lakes, by adding more height levels
2732 * representing shallow and deep water/ lava etc.
2734 * The grd variable affects the width of passages.
2735 * The roug variable affects the roughness of those passages
2737 * The tricky part is making sure the created cave is connected. This
2738 * is done by 'filling' from the inside and only keeping the 'filled'
2739 * floor. Walls bounding the 'filled' floor are also kept. Everything
2740 * else is converted to the normal granite FEAT_WALL_EXTRA.
2745 * Note that this uses the cave.feat array in a very hackish way
2746 * the values are first set to zero, and then each array location
2747 * is used as a "heightmap"
2748 * The heightmap then needs to be converted back into the "feat" format.
2750 * grd=level at which fractal turns on. smaller gives more mazelike caves
2751 * roug=roughness level. 16=normal. higher values make things more convoluted
2752 * small values are good for smooth walls.
2753 * size=length of the side of the square cave system.
2755 static void generate_hmap(int y0, int x0, int xsiz, int ysiz, int grd, int roug, int cutoff)
2757 int xhsize, yhsize, xsize, ysize, maxsize;
2760 * fixed point variables- these are stored as 256 x normal value
2761 * this gives 8 binary places of fractional part + 8 places of normal part
2764 u16b xstep, xhstep, ystep, yhstep;
2765 u16b xstep2, xhstep2, ystep2, yhstep2;
2766 u16b i, j, ii, jj, diagsize, xxsize, yysize;
2768 /* Cache for speed */
2769 u16b xm, xp, ym, yp;
2771 /* redefine size so can change the value if out of range */
2775 /* Paranoia about size of the system of caves */
2776 if (xsize > 254) xsize = 254;
2777 if (xsize < 4) xsize = 4;
2778 if (ysize > 254) ysize = 254;
2779 if (ysize < 4) ysize = 4;
2781 /* get offsets to middle of array */
2785 /* fix rounding problem */
2789 /* get limits of region */
2790 fill_data.xmin = x0 - xhsize;
2791 fill_data.ymin = y0 - yhsize;
2792 fill_data.xmax = x0 + xhsize;
2793 fill_data.ymax = y0 + yhsize;
2795 /* Store cutoff in global for quick access */
2796 fill_data.c1 = cutoff;
2799 * Scale factor for middle points:
2800 * About sqrt(2) * 256 - correct for a square lattice
2801 * approximately correct for everything else.
2805 /* maximum of xsize and ysize */
2806 maxsize = (xsize > ysize) ? xsize : ysize;
2808 /* Clear the section */
2809 for (i = 0; i <= xsize; i++)
2811 for (j = 0; j <= ysize; j++)
2813 /* 255 is a flag for "not done yet" */
2814 cave[(int)(fill_data.ymin + j)][(int)(fill_data.xmin + i)].feat = 255;
2815 /* Clear icky flag because may be redoing the cave */
2816 cave[(int)(fill_data.ymin + j)][(int)(fill_data.xmin + i)].info &= ~(CAVE_ICKY);
2820 /* Boundaries are walls */
2821 cave[fill_data.ymin][fill_data.xmin].feat = maxsize;
2822 cave[fill_data.ymax][fill_data.xmin].feat = maxsize;
2823 cave[fill_data.ymin][fill_data.xmax].feat = maxsize;
2824 cave[fill_data.ymax][fill_data.xmax].feat = maxsize;
2826 /* Set the middle square to be an open area. */
2827 cave[y0][x0].feat = 0;
2829 /* Initialize the step sizes */
2830 xstep = xhstep = xsize * 256;
2831 ystep = yhstep = ysize * 256;
2832 xxsize = xsize * 256;
2833 yysize = ysize * 256;
2836 * Fill in the rectangle with fractal height data -
2837 * like the 'plasma fractal' in fractint.
2839 while ((xhstep > 256) || (yhstep > 256))
2841 /* Halve the step sizes */
2847 /* cache well used values */
2848 xstep2 = xstep / 256;
2849 ystep2 = ystep / 256;
2851 xhstep2 = xhstep / 256;
2852 yhstep2 = yhstep / 256;
2854 /* middle top to bottom. */
2855 for (i = xhstep; i <= xxsize - xhstep; i += xstep)
2857 for (j = 0; j <= yysize; j += ystep)
2859 /* cache often used values */
2860 ii = i / 256 + fill_data.xmin;
2861 jj = j / 256 + fill_data.ymin;
2864 if (cave[jj][ii].feat == 255)
2868 /* If greater than 'grid' level then is random */
2869 store_height(ii, jj, randint(maxsize));
2873 /* Average of left and right points +random bit */
2874 store_height(ii, jj,
2875 (cave[jj][fill_data.xmin + (i - xhstep) / 256].feat
2876 + cave[jj][fill_data.xmin + (i + xhstep) / 256].feat) / 2
2877 + (randint(xstep2) - xhstep2) * roug / 16);
2884 /* middle left to right. */
2885 for (j = yhstep; j <= yysize - yhstep; j += ystep)
2887 for (i = 0; i <= xxsize; i += xstep)
2889 /* cache often used values */
2890 ii = i / 256 + fill_data.xmin;
2891 jj = j / 256 + fill_data.ymin;
2894 if (cave[jj][ii].feat == 255)
2898 /* If greater than 'grid' level then is random */
2899 store_height(ii, jj, randint(maxsize));
2903 /* Average of up and down points +random bit */
2904 store_height(ii, jj,
2905 (cave[fill_data.ymin + (j - yhstep) / 256][ii].feat
2906 + cave[fill_data.ymin + (j + yhstep) / 256][ii].feat) / 2
2907 + (randint(ystep2) - yhstep2) * roug / 16);
2914 for (i = xhstep; i <= xxsize - xhstep; i += xstep)
2916 for (j = yhstep; j <= yysize - yhstep; j += ystep)
2918 /* cache often used values */
2919 ii = i / 256 + fill_data.xmin;
2920 jj = j / 256 + fill_data.ymin;
2923 if (cave[jj][ii].feat == 255)
2927 /* If greater than 'grid' level then is random */
2928 store_height(ii, jj, randint(maxsize));
2932 /* Cache reused values. */
2933 xm = fill_data.xmin + (i - xhstep) / 256;
2934 xp = fill_data.xmin + (i + xhstep) / 256;
2935 ym = fill_data.ymin + (j - yhstep) / 256;
2936 yp = fill_data.ymin + (j + yhstep) / 256;
2939 * Average over all four corners + scale by diagsize to
2940 * reduce the effect of the square grid on the shape of the fractal
2942 store_height(ii, jj,
2943 (cave[ym][xm].feat + cave[yp][xm].feat
2944 + cave[ym][xp].feat + cave[yp][xp].feat) / 4
2945 + (randint(xstep2) - xhstep2) * (diagsize / 16) / 256 * roug);
2954 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)
2957 * function used to convert from height-map back to the
2958 * normal angband cave format
2960 if (cave[y][x].info & CAVE_ICKY)
2967 /* Show that have looked at this square */
2968 cave[y][x].info|= (CAVE_ICKY);
2970 /* Use cutoffs c1-c3 to allocate regions of floor /water/ lava etc. */
2971 if (cave[y][x].feat <= c1)
2973 /* 25% of the time use the other tile : it looks better this way */
2974 if (randint(100) < 75)
2976 cave[y][x].feat = feat1;
2977 cave[y][x].info &= ~(CAVE_MASK);
2978 cave[y][x].info |= info1;
2983 cave[y][x].feat = feat2;
2984 cave[y][x].info &= ~(CAVE_MASK);
2985 cave[y][x].info |= info2;
2989 else if (cave[y][x].feat <= c2)
2991 /* 25% of the time use the other tile : it looks better this way */
2992 if (randint(100) < 75)
2994 cave[y][x].feat = feat2;
2995 cave[y][x].info &= ~(CAVE_MASK);
2996 cave[y][x].info |= info2;
3001 cave[y][x].feat = feat1;
3002 cave[y][x].info &= ~(CAVE_MASK);
3003 cave[y][x].info |= info1;
3007 else if (cave[y][x].feat <= c3)
3009 cave[y][x].feat = feat3;
3010 cave[y][x].info |= info3;
3013 /* if greater than cutoff then is a wall */
3016 place_outer_bold(y, x);
3026 * Quick and nasty fill routine used to find the connected region
3027 * of floor in the middle of the cave
3029 static void cave_fill(byte y, byte x)
3038 /*** Start Grid ***/
3040 /* Enqueue that entry */
3045 /* Now process the queue */
3046 while (flow_head != flow_tail)
3048 /* Extract the next entry */
3049 ty = temp_y[flow_head];
3050 tx = temp_x[flow_head];
3052 /* Forget that entry */
3053 if (++flow_head == TEMP_MAX) flow_head = 0;
3055 /* Add the "children" */
3056 for (d = 0; d < 8; d++)
3058 int old_head = flow_tail;
3060 /* Child location */
3061 j = ty + ddy_ddd[d];
3062 i = tx + ddx_ddd[d];
3064 /* Paranoia Don't leave the cave */
3065 if (!in_bounds(j, i))
3067 /* affect boundary */
3068 cave[j][i].info |= CAVE_ICKY;
3072 /* If within bounds */
3073 else if ((i > fill_data.xmin) && (i < fill_data.xmax)
3074 && (j > fill_data.ymin) && (j < fill_data.ymax))
3076 /* If not a wall or floor done before */
3077 if (hack_isnt_wall(j, i,
3078 fill_data.c1, fill_data.c2, fill_data.c3,
3079 fill_data.feat1, fill_data.feat2, fill_data.feat3,
3080 fill_data.info1, fill_data.info2, fill_data.info3))
3082 /* Enqueue that entry */
3083 temp_y[flow_tail] = j;
3084 temp_x[flow_tail] = i;
3086 /* Advance the queue */
3087 if (++flow_tail == TEMP_MAX) flow_tail = 0;
3089 /* Hack -- Overflow by forgetting new entry */
3090 if (flow_tail == flow_head)
3092 flow_tail = old_head;
3096 /* keep tally of size of cave system */
3097 (fill_data.amount)++;
3103 /* affect boundary */
3104 cave[j][i].info |= CAVE_ICKY;
3111 static bool generate_fracave(int y0, int x0, int xsize, int ysize, int cutoff, bool light, bool room)
3113 int x, y, i, xhsize, yhsize;
3116 /* offsets to middle from corner */
3122 * select region connected to center of cave system
3123 * this gets rid of alot of isolated one-sqaures that
3124 * can make teleport traps instadeaths...
3128 fill_data.c1 = cutoff;
3132 /* features to fill with */
3133 fill_data.feat1 = floor_type[rand_int(100)];
3134 fill_data.feat2 = floor_type[rand_int(100)];
3135 fill_data.feat3 = floor_type[rand_int(100)];
3137 fill_data.info1 = CAVE_FLOOR;
3138 fill_data.info2 = CAVE_FLOOR;
3139 fill_data.info3 = CAVE_FLOOR;
3141 /* number of filled squares */
3142 fill_data.amount = 0;
3144 cave_fill((byte)y0, (byte)x0);
3146 /* if tally too small, try again */
3147 if (fill_data.amount < 10)
3149 /* too small - clear area and try again later */
3150 for (x = 0; x <= xsize; ++x)
3152 for (y = 0; y <= ysize; ++y)
3154 place_extra_bold(y0 + y - yhsize, x0 + x - xhsize);
3155 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY | CAVE_ROOM);
3162 * Do boundarys-check to see if they are next to a filled region
3163 * If not then they are set to normal granite
3164 * If so then they are marked as room walls.
3166 for (i = 0; i <= xsize; ++i)
3169 if ((cave[0 + y0 - yhsize][i + x0 - xhsize].info & CAVE_ICKY) && (room))
3171 /* Next to a 'filled' region? - set to be room walls */
3172 place_outer_bold(y0 + 0 - yhsize, x0 + i - xhsize);
3173 if (light) cave[y0 + 0 - yhsize][x0 + i - xhsize].info |= (CAVE_GLOW);
3174 cave[y0 + 0 - yhsize][x0 + i - xhsize].info |= (CAVE_ROOM);
3175 place_outer_bold(y0 + 0 - yhsize, x0 + i - xhsize);
3179 /* set to be normal granite */
3180 place_extra_bold(y0 + 0 - yhsize, x0 + i - xhsize);
3183 /* bottom boundary */
3184 if ((cave[ysize + y0 - yhsize][i + x0 - xhsize].info & CAVE_ICKY) && (room))
3186 /* Next to a 'filled' region? - set to be room walls */
3187 place_outer_bold(y0 + ysize - yhsize, x0 + i - xhsize);
3188 if (light) cave[y0 + ysize - yhsize][x0 + i - xhsize].info|=(CAVE_GLOW);
3189 cave[y0 + ysize - yhsize][x0 + i - xhsize].info|=(CAVE_ROOM);
3190 place_outer_bold(y0 + ysize - yhsize, x0 + i - xhsize);
3194 /* set to be normal granite */
3195 place_extra_bold(y0 + ysize - yhsize, x0 + i - xhsize);
3198 /* clear the icky flag-don't need it any more */
3199 cave[y0 + 0 - yhsize][x0 + i - xhsize].info &= ~(CAVE_ICKY);
3200 cave[y0 + ysize - yhsize][x0 + i - xhsize].info &= ~(CAVE_ICKY);
3203 /* Do the left and right boundaries minus the corners (done above) */
3204 for (i = 1; i < ysize; ++i)
3207 if ((cave[i + y0 - yhsize][0 + x0 - xhsize].info & CAVE_ICKY) && room)
3210 place_outer_bold(y0 + i - yhsize, x0 + 0 - xhsize);
3211 if (light) cave[y0 + i - yhsize][x0 + 0 - xhsize].info |= (CAVE_GLOW);
3212 cave[y0 + i - yhsize][x0 + 0 - xhsize].info |= (CAVE_ROOM);
3213 place_outer_bold(y0 + i - yhsize, x0 + 0 - xhsize);
3218 place_extra_bold(y0 + i - yhsize, x0 + 0 - xhsize);
3220 /* right boundary */
3221 if ((cave[i + y0 - yhsize][xsize + x0 - xhsize].info & CAVE_ICKY) && room)
3224 place_outer_bold(y0 + i - yhsize, x0 + xsize - xhsize);
3225 if (light) cave[y0 + i - yhsize][x0 + xsize - xhsize].info |= (CAVE_GLOW);
3226 cave[y0 + i - yhsize][x0 + xsize - xhsize].info |= (CAVE_ROOM);
3227 place_outer_bold(y0 + i - yhsize, x0 + xsize - xhsize);
3232 place_extra_bold(y0 + i - yhsize, x0 + xsize - xhsize);
3235 /* clear icky flag -done with it */
3236 cave[y0 + i - yhsize][x0 + 0 - xhsize].info &= ~(CAVE_ICKY);
3237 cave[y0 + i - yhsize][x0 + xsize - xhsize].info &= ~(CAVE_ICKY);
3241 /* Do the rest: convert back to the normal format */
3242 for (x = 1; x < xsize; ++x)
3244 for (y = 1; y < ysize; ++y)
3246 if (is_floor_bold(y0 + y - yhsize, x0 + x - xhsize) &&
3247 (cave[y0 + y - yhsize][x0 + x - xhsize].info & CAVE_ICKY))
3249 /* Clear the icky flag in the filled region */
3250 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~CAVE_ICKY;
3252 /* Set appropriate flags */
3253 if (light) cave[y0 + y - yhsize][x0 + x - xhsize].info |= (CAVE_GLOW);
3254 if (room) cave[y0 + y - yhsize][x0 + x - xhsize].info |= (CAVE_ROOM);
3256 else if (is_outer_bold(y0 + y - yhsize, x0 + x - xhsize) &&
3257 (cave[y0 + y - yhsize][x0 + x - xhsize].info & CAVE_ICKY))
3260 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY);
3261 if (light) cave[y0 + y - yhsize][x0 + x - xhsize].info |= (CAVE_GLOW);
3264 cave[y0 + y - yhsize][x0 + x - xhsize].info |= (CAVE_ROOM);
3269 place_extra_bold(y0 + y - yhsize, x0 + x - xhsize);
3270 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ROOM);
3275 /* Clear the unconnected regions */
3276 place_extra_bold(y0 + y - yhsize, x0 + x - xhsize);
3277 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY | CAVE_ROOM);
3283 * XXX XXX XXX There is a slight problem when tunnels pierce the caves:
3284 * Extra doors appear inside the system. (Its not very noticeable though.)
3285 * This can be removed by "filling" from the outside in. This allows a separation
3286 * from FEAT_WALL_OUTER with FEAT_WALL_INNER. (Internal walls are F.W.OUTER instead.)
3287 * The extra effort for what seems to be only a minor thing (even non-existant if you
3288 * think of the caves not as normal rooms, but as holes in the dungeon), doesn't seem
3297 * Driver routine to create fractal cave system
3299 static void build_type9(int by0, int bx0)
3301 int grd, roug, cutoff, xsize, ysize, y0, x0;
3303 bool done, light, room;
3305 /* get size: note 'Evenness'*/
3306 xsize = randint(22) * 2 + 6;
3307 ysize = randint(15) * 2 + 6;
3309 /* Try to allocate space for room. If fails, exit */
3310 if (!room_alloc(xsize + 1, ysize + 1, FALSE, by0, bx0, &x0, &y0)) return;
3312 light = done = FALSE;
3315 if ((dun_level <= randint(25)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS)) light = TRUE;
3319 /* Note: size must be even or there are rounding problems
3320 * This causes the tunnels not to connect properly to the room */
3322 /* testing values for these parameters feel free to adjust */
3323 grd = 1 << (rand_int(4));
3325 /* want average of about 16 */
3326 roug = randint(8) * randint(4);
3329 cutoff = randint(xsize / 4) + randint(ysize / 4) +
3330 randint(xsize / 4) + randint(ysize / 4);
3333 generate_hmap(y0, x0, xsize, ysize, grd, roug, cutoff);
3335 /* Convert to normal format + clean up */
3336 done = generate_fracave(y0, x0, xsize, ysize, cutoff, light, room);
3340 #ifdef ALLOW_CAVERNS_AND_LAKES
3342 * Builds a cave system in the center of the dungeon.
3344 void build_cavern(void)
3346 int grd, roug, cutoff, xsize, ysize, x0, y0;
3349 light = done = FALSE;
3350 if ((dun_level <= randint(50)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS)) light = TRUE;
3352 /* Make a cave the size of the dungeon */
3353 xsize = cur_wid - 1;
3354 ysize = cur_hgt - 1;
3358 /* Paranoia: make size even */
3364 /* testing values for these parameters: feel free to adjust */
3365 grd = randint(4) + 4;
3367 /* want average of about 16 */
3368 roug = randint(8) * randint(4);
3374 generate_hmap(y0 + 1, x0 + 1, xsize, ysize, grd, roug, cutoff);
3376 /* Convert to normal format+ clean up */
3377 done = generate_fracave(y0 + 1, x0 + 1, xsize, ysize, cutoff, light, FALSE);
3381 static bool generate_lake(int y0, int x0, int xsize, int ysize, int c1, int c2, int c3, int type)
3383 int x, y, i, xhsize, yhsize;
3384 int feat1, feat2, feat3;
3386 /* offsets to middle from corner */
3390 /* Get features based on type */
3395 feat1 = FEAT_DEEP_LAVA;
3396 feat2 = FEAT_SHAL_LAVA;
3397 feat3 = floor_type[rand_int(100)];
3401 feat1 = FEAT_DEEP_WATER;
3402 feat2 = FEAT_SHAL_WATER;
3403 feat3 = floor_type[rand_int(100)];
3406 /* Collapsed cave */
3407 feat1 = floor_type[rand_int(100)];
3408 feat2 = floor_type[rand_int(100)];
3409 feat3 = FEAT_RUBBLE;
3413 feat1 = FEAT_RUBBLE;
3414 feat2 = floor_type[rand_int(100)];
3415 feat3 = FEAT_RUBBLE;
3425 feat1 = FEAT_SHAL_WATER;
3426 feat2 = FEAT_DEEP_WATER;
3427 feat3 = FEAT_SHAL_WATER;
3431 feat1 = FEAT_SHAL_LAVA;
3432 feat2 = FEAT_DEEP_LAVA;
3433 feat3 = FEAT_SHAL_LAVA;
3437 default: return FALSE;
3441 * select region connected to center of cave system
3442 * this gets rid of alot of isolated one-sqaures that
3443 * can make teleport traps instadeaths...
3451 /* features to fill with */
3452 fill_data.feat1 = feat1;
3453 fill_data.feat2 = feat2;
3454 fill_data.feat3 = feat3;
3456 fill_data.info1 = 0;
3457 fill_data.info2 = 0;
3458 fill_data.info3 = 0;
3460 /* number of filled squares */
3461 fill_data.amount = 0;
3463 /* select region connected to center of cave system
3464 * this gets rid of alot of isolated one-sqaures that
3465 * can make teleport traps instadeaths... */
3466 cave_fill((byte)y0, (byte)x0);
3468 /* if tally too small, try again */
3469 if (fill_data.amount < 10)
3471 /* too small -clear area and try again later */
3472 for (x = 0; x <= xsize; ++x)
3474 for (y = 0; y <= ysize; ++y)
3476 place_floor_bold(y0 + y - yhsize, x0 + x - xhsize);
3477 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY);
3483 /* Do boundarys- set to normal granite */
3484 for (i = 0; i <= xsize; ++i)
3486 place_extra_bold(y0 + 0 - yhsize, x0 + i - xhsize);
3487 place_extra_bold(y0 + ysize - yhsize, x0 + i - xhsize);
3489 /* clear the icky flag-don't need it any more */
3490 cave[y0 + 0 - yhsize][x0 + i - xhsize].info &= ~(CAVE_ICKY);
3491 cave[y0 + ysize - yhsize][x0 + i - xhsize].info &= ~(CAVE_ICKY);
3494 /* Do the left and right boundaries minus the corners (done above) */
3496 for (i = 1; i < ysize; ++i)
3498 place_extra_bold(y0 + i - yhsize, x0 + 0 - xhsize);
3499 place_extra_bold(y0 + i - yhsize, x0 + xsize - xhsize);
3501 /* clear icky flag -done with it */
3502 cave[y0 + i - yhsize][x0 + 0 - xhsize].info &= ~(CAVE_ICKY);
3503 cave[y0 + i - yhsize][x0 + xsize - xhsize].info &= ~(CAVE_ICKY);
3507 /* Do the rest: convert back to the normal format */
3508 for (x = 1; x < xsize; ++x)
3510 for (y = 1; y < ysize; ++y)
3512 /* Fill unconnected regions with granite */
3513 if ((!(cave[y0 + y - yhsize][x0 + x - xhsize].info & CAVE_ICKY)) ||
3514 is_outer_bold(y0 + y - yhsize, x0 + x - xhsize))
3515 place_extra_bold(y0 + y - yhsize, x0 + x - xhsize);
3517 /* turn off icky flag (no longer needed.) */
3518 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY | CAVE_ROOM);
3520 /* Light lava and trees */
3521 if ((cave[y0 + y - yhsize][x0 + x - xhsize].feat == FEAT_DEEP_LAVA) ||
3522 (cave[y0 + y - yhsize][x0 + x - xhsize].feat == FEAT_SHAL_LAVA))
3524 cave[y0 + y - yhsize][x0 + x - xhsize].info |= CAVE_GLOW;
3534 * makes a lake/collapsed cave system in the center of the dungeon
3536 void build_lake(int type)
3538 int grd, roug, xsize, ysize, x0, y0;
3542 /* paranoia - exit if lake type out of range. */
3543 if ((type < 1) || (type > 7))
3545 msg_format("Invalid lake type (%d)", type);
3549 /* Make the size of the dungeon */
3550 xsize = cur_wid - 1;
3551 ysize = cur_hgt - 1;
3555 /* Paranoia: make size even */
3561 /* testing values for these parameters: feel free to adjust */
3562 grd = randint(3) + 4;
3564 /* want average of about 16 */
3565 roug = randint(8) * randint(4);
3567 /* Make up size of various componants */
3571 /* Deep water/lava */
3572 c1 = rand_int(c3 / 2) + rand_int(c3 / 2) - 5;
3574 /* Shallow boundary */
3578 generate_hmap(y0 + 1, x0 + 1, xsize, ysize, grd, roug, c3);
3580 /* Convert to normal format+ clean up */
3581 done = generate_lake(y0 + 1, x0 + 1, xsize, ysize, c1, c2, c3, type);
3584 #endif /* ALLOW_CAVERNS_AND_LAKES */
3588 * Routine used by the random vault creators to add a door to a location
3589 * Note that range checking has to be done in the calling routine.
3591 * The doors must be INSIDE the allocated region.
3593 static void add_door(int x, int y)
3595 /* Need to have a wall in the center square */
3596 if (!is_outer_bold(y, x)) return;
3603 * where x=don't care
3607 if (is_floor_bold(y-1,x) && is_floor_bold(y+1,x) &&
3608 (is_outer_bold(y, x - 1) && is_outer_bold(y, x + 1)))
3611 place_secret_door(y, x);
3613 /* set boundarys so don't get wide doors */
3614 place_solid_bold(y, x - 1);
3615 place_solid_bold(y, x + 1);
3624 * where x = don't care
3627 if (is_outer_bold(y - 1, x) && is_outer_bold(y + 1, x) &&
3628 is_floor_bold(y,x-1) && is_floor_bold(y,x+1))
3631 place_secret_door(y, x);
3633 /* set boundarys so don't get wide doors */
3634 place_solid_bold(y - 1, x);
3635 place_solid_bold(y + 1, x);
3641 * Routine that fills the empty areas of a room with treasure and monsters.
3643 static void fill_treasure(int x1, int x2, int y1, int y2, int difficulty)
3645 int x, y, cx, cy, size;
3648 /* center of room:*/
3652 /* Rough measure of size of vault= sum of lengths of sides */
3653 size = abs(x2 - x1) + abs(y2 - y1);
3655 for (x = x1; x <= x2; x++)
3657 for (y = y1; y <= y2; y++)
3659 /* Thing added based on distance to center of vault
3660 * Difficulty is 1-easy to 10-hard */
3661 value = ((((s32b)(distance(cx, cy, x, y))) * 100) / size) + randint(10) - difficulty;
3663 /* hack- empty square part of the time */
3664 if ((randint(100) - difficulty * 3) > 50) value = 20;
3666 /* if floor, shallow water and lava */
3667 if (is_floor_bold(y, x) ||
3668 (cave[y][x].feat == FEAT_SHAL_WATER) ||
3669 (cave[y][x].feat == FEAT_SHAL_LAVA))
3671 /* The smaller 'value' is, the better the stuff */
3674 /* Meanest monster + treasure */
3675 monster_level = base_level + 40;
3676 place_monster(y, x, TRUE, TRUE);
3677 monster_level = base_level;
3678 object_level = base_level + 20;
3679 place_object(y, x, TRUE, FALSE);
3680 object_level = base_level;
3684 /* Mean monster +treasure */
3685 monster_level = base_level + 20;
3686 place_monster(y, x, TRUE, TRUE);
3687 monster_level = base_level;
3688 object_level = base_level + 10;
3689 place_object(y, x, TRUE, FALSE);
3690 object_level = base_level;
3692 else if (value < 10)
3695 monster_level = base_level + 9;
3696 place_monster(y, x, TRUE, TRUE);
3697 monster_level = base_level;
3699 else if (value < 17)
3701 /* Intentional Blank space */
3704 * (Want some of the vault to be empty
3705 * so have room for group monsters.
3706 * This is used in the hack above to lower
3707 * the density of stuff in the vault.)
3710 else if (value < 23)
3712 /* Object or trap */
3713 if (rand_int(100) < 25)
3715 place_object(y, x, FALSE, FALSE);
3722 else if (value < 30)
3724 /* Monster and trap */
3725 monster_level = base_level + 5;
3726 place_monster(y, x, TRUE, TRUE);
3727 monster_level = base_level;
3730 else if (value < 40)
3732 /* Monster or object */
3733 if (rand_int(100) < 50)
3735 monster_level = base_level + 3;
3736 place_monster(y, x, TRUE, TRUE);
3737 monster_level = base_level;
3739 if (rand_int(100) < 50)
3741 object_level = base_level + 7;
3742 place_object(y, x, FALSE, FALSE);
3743 object_level = base_level;
3746 else if (value < 50)
3755 /* 20% monster, 40% trap, 20% object, 20% blank space */
3756 if (rand_int(100) < 20)
3758 place_monster(y, x, TRUE, TRUE);
3760 else if (rand_int(100) < 50)
3764 else if (rand_int(100) < 50)
3766 place_object(y, x, FALSE, FALSE);
3777 * This function creates a random vault that looks like a collection of bubbles.
3778 * It works by getting a set of coordinates that represent the center of each
3779 * bubble. The entire room is made by seeing which bubble center is closest. If
3780 * two centers are equidistant then the square is a wall, otherwise it is a floor.
3781 * The only exception is for squares really near a center, these are always floor.
3782 * (It looks better than without this check.)
3784 * Note: If two centers are on the same point then this algorithm will create a
3785 * blank bubble filled with walls. - This is prevented from happening.
3787 static void build_bubble_vault(int x0, int y0, int xsize, int ysize)
3789 #define BUBBLENUM 10 /* number of bubbles */
3791 /* array of center points of bubbles */
3792 coord center[BUBBLENUM];
3795 u16b min1, min2, temp;
3798 /* Offset from center to top left hand corner */
3799 int xhsize = xsize / 2;
3800 int yhsize = ysize / 2;
3803 if (cheat_room) msg_print("Bubble Vault");
3805 /* Allocate center of bubbles */
3806 center[0].x = randint(xsize - 3) + 1;
3807 center[0].y = randint(ysize - 3) + 1;
3809 for (i = 1; i < BUBBLENUM; i++)
3813 /* get center and check to see if it is unique */
3818 x = randint(xsize - 3) + 1;
3819 y = randint(ysize - 3) + 1;
3821 for (j = 0; j < i; j++)
3823 /* rough test to see if there is an overlap */
3824 if ((x == center[j].x) && (y == center[j].y)) done = FALSE;
3833 /* Top and bottom boundaries */
3834 for (i = 0; i < xsize; i++)
3836 int x = x0 - xhsize + i;
3838 place_outer_noperm_bold(y0 - yhsize + 0, x);
3839 cave[y0 - yhsize + 0][x].info |= (CAVE_ROOM | CAVE_ICKY);
3840 place_outer_noperm_bold(y0 - yhsize + ysize - 1, x);
3841 cave[y0 - yhsize + ysize - 1][x].info |= (CAVE_ROOM | CAVE_ICKY);
3844 /* Left and right boundaries */
3845 for (i = 1; i < ysize - 1; i++)
3847 int y = y0 - yhsize + i;
3849 place_outer_noperm_bold(y, x0 - xhsize + 0);
3850 cave[y][x0 - xhsize + 0].info |= (CAVE_ROOM | CAVE_ICKY);
3851 place_outer_noperm_bold(y, x0 - xhsize + xsize - 1);
3852 cave[y][x0 - xhsize + xsize - 1].info |= (CAVE_ROOM | CAVE_ICKY);
3855 /* Fill in middle with bubbles */
3856 for (x = 1; x < xsize - 1; x++)
3858 for (y = 1; y < ysize - 1; y++)
3860 /* Get distances to two closest centers */
3863 min1 = distance(x, y, center[0].x, center[0].y);
3864 min2 = distance(x, y, center[1].x, center[1].y);
3868 /* swap if in wrong order */
3875 for (i = 2; i < BUBBLENUM; i++)
3877 temp = distance(x, y, center[i].x, center[i].y);
3885 else if (temp < min2)
3887 /* second smallest */
3891 if (((min2 - min1) <= 2) && (!(min1 < 3)))
3893 /* Boundary at midpoint+ not at inner region of bubble */
3894 place_outer_noperm_bold(y0 - yhsize + y, x0 - xhsize + x);
3898 /* middle of a bubble */
3899 place_floor_bold(y0 - yhsize + y, x0 - xhsize + x);
3902 /* clean up rest of flags */
3903 cave[y0 - yhsize + y][x0 - xhsize + x].info |= (CAVE_ROOM | CAVE_ICKY);
3907 /* Try to add some random doors */
3908 for (i = 0; i < 500; i++)
3910 x = randint(xsize - 3) - xhsize + x0 + 1;
3911 y = randint(ysize - 3) - yhsize + y0 + 1;
3915 /* Fill with monsters and treasure, low difficulty */
3916 fill_treasure(x0 - xhsize + 1, x0 - xhsize + xsize - 2, y0 - yhsize + 1, y0 - yhsize + ysize - 2, randint(5));
3921 * Overlay a rectangular room given its bounds
3922 * This routine is used by build_room_vault
3923 * The area inside the walls is not touched:
3924 * only granite is removed- normal walls stay
3926 static void build_room(int x1, int x2, int y1, int y2)
3928 int x, y, i, xsize, ysize, temp;
3930 /* Check if rectangle has no width */
3931 if ((x1 == x2) || (y1 == y2)) return;
3936 /* Swap boundaries if in wrong order */
3944 /* Swap boundaries if in wrong order */
3950 /* get total widths */
3955 /* Top and bottom boundaries */
3956 for (i = 0; i <= xsize; i++)
3958 place_outer_noperm_bold(y1, x1 + i);
3959 cave[y1][x1 + i].info |= (CAVE_ROOM | CAVE_ICKY);
3960 place_outer_noperm_bold(y2, x1 + i);
3961 cave[y2][x1 + i].info |= (CAVE_ROOM | CAVE_ICKY);
3964 /* Left and right boundaries */
3965 for (i = 1; i < ysize; i++)
3967 place_outer_noperm_bold(y1 + i, x1);
3968 cave[y1 + i][x1].info|=(CAVE_ROOM | CAVE_ICKY);
3969 place_outer_noperm_bold(y1 + i, x2);
3970 cave[y1 + i][x2].info|=(CAVE_ROOM | CAVE_ICKY);
3974 for (x = 1; x < xsize; x++)
3976 for (y = 1; y < ysize; y++)
3978 if (is_extra_bold(y1+y, x1+x))
3980 /* clear the untouched region */
3981 place_floor_bold(y1 + y, x1 + x);
3982 cave[y1 + y][x1 + x].info |= (CAVE_ROOM | CAVE_ICKY);
3986 /* make it a room- but don't touch */
3987 cave[y1 + y][x1 + x].info |= (CAVE_ROOM | CAVE_ICKY);
3994 /* Create a random vault that looks like a collection of overlapping rooms */
3996 static void build_room_vault(int x0, int y0, int xsize, int ysize)
3998 int i, x1, x2, y1, y2, xhsize, yhsize;
4000 /* get offset from center */
4004 if (cheat_room) msg_print("Room Vault");
4006 /* fill area so don't get problems with arena levels */
4007 for (x1 = 0; x1 < xsize; x1++)
4009 int x = x0 - xhsize + x1;
4011 for (y1 = 0; y1 < ysize; y1++)
4013 int y = y0 - yhsize + y1;
4015 place_extra_bold(y, x);
4016 cave[y][x].info &= (~CAVE_ICKY);
4020 /* add ten random rooms */
4021 for (i = 0; i < 10; i++)
4023 x1 = randint(xhsize) * 2 + x0 - xhsize;
4024 x2 = randint(xhsize) * 2 + x0 - xhsize;
4025 y1 = randint(yhsize) * 2 + y0 - yhsize;
4026 y2 = randint(yhsize) * 2 + y0 - yhsize;
4027 build_room(x1, x2, y1, y2);
4030 /* Add some random doors */
4031 for (i = 0; i < 500; i++)
4033 x1 = randint(xsize - 3) - xhsize + x0 + 1;
4034 y1 = randint(ysize - 3) - yhsize + y0 + 1;
4038 /* Fill with monsters and treasure, high difficulty */
4039 fill_treasure(x0 - xhsize + 1, x0 - xhsize + xsize - 2, y0 - yhsize + 1, y0 - yhsize + ysize - 2, randint(5) + 5);
4043 /* Create a random vault out of a fractal cave */
4044 static void build_cave_vault(int x0, int y0, int xsiz, int ysiz)
4046 int grd, roug, cutoff, xhsize, yhsize, xsize, ysize, x, y;
4047 bool done, light, room;
4049 /* round to make sizes even */
4055 if (cheat_room) msg_print("Cave Vault");
4057 light = done = FALSE;
4062 /* testing values for these parameters feel free to adjust */
4063 grd = 1 << rand_int(4);
4065 /* want average of about 16 */
4066 roug = randint(8) * randint(4);
4069 cutoff = randint(xsize / 4) + randint(ysize / 4) +
4070 randint(xsize / 4) + randint(ysize / 4);
4073 generate_hmap(y0, x0, xsize, ysize, grd, roug, cutoff);
4075 /* Convert to normal format+ clean up */
4076 done = generate_fracave(y0, x0, xsize, ysize, cutoff, light, room);
4079 /* Set icky flag because is a vault */
4080 for (x = 0; x <= xsize; x++)
4082 for (y = 0; y <= ysize; y++)
4084 cave[y0 - yhsize + y][x0 - xhsize + x].info |= CAVE_ICKY;
4088 /* Fill with monsters and treasure, low difficulty */
4089 fill_treasure(x0 - xhsize + 1, x0 - xhsize + xsize - 1, y0 - yhsize + 1, y0 - yhsize + ysize - 1, randint(5));
4093 * maze vault -- rectangular labyrinthine rooms
4095 * maze vault uses two routines:
4096 * r_visit - a recursive routine that builds the labyrinth
4097 * build_maze_vault - a driver routine that calls r_visit and adds
4098 * monsters, traps and treasure
4100 * The labyrinth is built by creating a spanning tree of a graph.
4101 * The graph vertices are at
4102 * (x, y) = (2j + x1, 2k + y1) j = 0,...,m-1 k = 0,...,n-1
4103 * and the edges are the vertical and horizontal nearest neighbors.
4105 * The spanning tree is created by performing a suitably randomized
4106 * depth-first traversal of the graph. The only adjustable parameter
4107 * is the rand_int(3) below; it governs the relative density of
4108 * twists and turns in the labyrinth: smaller number, more twists.
4110 static void r_visit(int y1, int x1, int y2, int x2,
4111 int node, int dir, int *visited)
4113 int i, j, m, n, temp, x, y, adj[4];
4115 /* dimensions of vertex array */
4116 m = (x2 - x1) / 2 + 1;
4117 n = (y2 - y1) / 2 + 1;
4119 /* mark node visited and set it to a floor */
4121 x = 2 * (node % m) + x1;
4122 y = 2 * (node / m) + y1;
4123 place_floor_bold(y, x);
4125 /* setup order of adjacent node visits */
4126 if (rand_int(3) == 0)
4128 /* pick a random ordering */
4129 for (i = 0; i < 4; i++)
4131 for (i = 0; i < 4; i++)
4142 /* pick a random ordering with dir first */
4144 for (i = 1; i < 4; i++)
4146 for (i = 1; i < 4; i++)
4148 j = 1 + rand_int(3);
4155 for (i = 0; i < 4; i++)
4160 /* (0,+) - check for bottom boundary */
4161 if ((node / m < n - 1) && (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 top boundary */
4169 if ((node / m > 0) && (visited[node - m] == 0))
4171 place_floor_bold(y - 1, x);
4172 r_visit(y1, x1, y2, x2, node - m, dir, visited);
4176 /* (+,0) - check for right boundary */
4177 if ((node % m < m - 1) && (visited[node + 1] == 0))
4179 place_floor_bold(y, x + 1);
4180 r_visit(y1, x1, y2, x2, node + 1, dir, visited);
4184 /* (-,0) - check for left boundary */
4185 if ((node % m > 0) && (visited[node - 1] == 0))
4187 place_floor_bold(y, x - 1);
4188 r_visit(y1, x1, y2, x2, node - 1, dir, visited);
4195 void build_maze_vault(int x0, int y0, int xsize, int ysize, bool is_vault)
4199 int i, m, n, num_vertices, *visited;
4204 if (cheat_room && is_vault) msg_print("Maze Vault");
4206 /* Choose lite or dark */
4207 light = ((dun_level <= randint(25)) && is_vault && !(d_info[dungeon_type].flags1 & DF1_DARKNESS));
4209 /* Pick a random room size - randomized by calling routine */
4218 /* generate the room */
4219 for (y = y1 - 1; y <= y2 + 1; y++)
4221 for (x = x1 - 1; x <= x2 + 1; x++)
4223 c_ptr = &cave[y][x];
4224 c_ptr->info |= CAVE_ROOM;
4225 if (is_vault) c_ptr->info |= CAVE_ICKY;
4226 if ((x == x1 - 1) || (x == x2 + 1) || (y == y1 - 1) || (y == y2 + 1))
4228 place_outer_grid(c_ptr);
4232 place_extra_grid(c_ptr);
4236 place_inner_grid(c_ptr);
4238 if (light) c_ptr->info |= (CAVE_GLOW);
4242 /* dimensions of vertex array */
4245 num_vertices = m * n;
4247 /* initialize array of visited vertices */
4248 /* use ralloc here ? */
4249 visited = (int *)malloc(num_vertices * sizeof(int));
4250 for (i = 0; i < num_vertices; i++)
4253 /* traverse the graph to create a spaning tree, pick a random root */
4254 r_visit(y1, x1, y2, x2, rand_int(num_vertices), 0, visited);
4256 /* Fill with monsters and treasure, low difficulty */
4257 if (is_vault) fill_treasure(x1, x2, y1, y2, randint(5));
4263 /* Build a "mini" checkerboard vault
4265 * This is done by making a permanent wall maze and setting
4266 * the diagonal sqaures of the checker board to be granite.
4267 * The vault has two entrances on opposite sides to guarantee
4268 * a way to get in even if the vault abuts a side of the dungeon.
4270 static void build_mini_c_vault(int x0, int y0, int xsize, int ysize)
4273 int y1, x1, y2, x2, y, x, total;
4274 int i, m, n, num_vertices;
4277 if (cheat_room) msg_print("Mini Checker Board Vault");
4279 /* Pick a random room size */
4289 /* generate the room */
4290 for (x = x1 - 2; x <= x2 + 2; x++)
4292 if (!in_bounds(y1-2,x)) break;
4294 cave[y1-2][x].info |= (CAVE_ROOM | CAVE_ICKY);
4296 place_extra_noperm_bold(y1-2, x);
4299 for (x = x1 - 2; x <= x2 + 2; x++)
4301 if (!in_bounds(y2+2,x)) break;
4303 cave[y2+2][x].info |= (CAVE_ROOM | CAVE_ICKY);
4305 place_extra_noperm_bold(y2+2, x);
4308 for (y = y1 - 2; y <= y2 + 2; y++)
4310 if (!in_bounds(y,x1-2)) break;
4312 cave[y][x1-2].info |= (CAVE_ROOM | CAVE_ICKY);
4314 place_extra_noperm_bold(y, x1-2);
4317 for (y = y1 - 2; y <= y2 + 2; y++)
4319 if (!in_bounds(y,x2+2)) break;
4321 cave[y][x2+2].info |= (CAVE_ROOM | CAVE_ICKY);
4323 place_extra_noperm_bold(y, x2+2);
4326 for (y = y1 - 1; y <= y2 + 1; y++)
4328 for (x = x1 - 1; x <= x2 + 1; x++)
4330 cave[y][x].info |= (CAVE_ROOM | CAVE_ICKY);
4332 /* Permanent walls */
4333 cave[y][x].feat = FEAT_PERM_INNER;
4338 /* dimensions of vertex array */
4341 num_vertices = m * n;
4343 /* initialize array of visited vertices */
4344 /* use ralloc here ? */
4345 visited = (int *) malloc(num_vertices * sizeof(int));
4346 for (i = 0; i < num_vertices; i++)
4349 /* traverse the graph to create a spannng tree, pick a random root */
4350 r_visit(y1, x1, y2, x2, rand_int(num_vertices), 0, visited);
4352 /* Make it look like a checker board vault */
4353 for (x = x1; x <= x2; x++)
4355 for (y = y1; y <= y2; y++)
4357 total = x - x1 + y - y1;
4358 /* If total is odd- and is a floor then make a wall */
4359 if ((total % 2 == 1) && is_floor_bold(y, x))
4361 place_inner_bold(y, x);
4366 /* Make a couple of entrances */
4367 if (randint(2) == 1)
4369 /* left and right */
4370 y = randint(dy) + dy / 2;
4371 place_outer_noperm_bold(y1 + y, x1 - 1);
4372 place_outer_noperm_bold(y1 + y, x2 + 1);
4376 /* top and bottom */
4377 x = randint(dx) + dx / 2;
4378 place_outer_noperm_bold(y1 - 1, x1 + x);
4379 place_outer_noperm_bold(y2 + 1, x1 + x);
4382 /* Fill with monsters and treasure, highest difficulty */
4383 fill_treasure(x1, x2, y1, y2, 10);
4385 /* rnfree(visited, num_vertices * sizeof(int)); */
4390 /* Build a town/ castle by using a recursive algorithm.
4391 * Basically divide each region in a probalistic way to create
4392 * smaller regions. When the regions get too small stop.
4394 * The power variable is a measure of how well defended a region is.
4395 * This alters the possible choices.
4397 static void build_recursive_room(int x1, int y1, int x2, int y2, int power)
4403 /* Temp variables */
4409 if ((power < 3) && (xsize > 12) && (ysize > 12))
4411 /* Need outside wall +keep */
4418 /* Make rooms + subdivide */
4419 if ((randint(10) > 2) && (xsize < 8) && (ysize < 8))
4425 choice = randint(2) + 1;
4430 /* Mostly subdivide */
4431 choice = randint(3) + 1;
4435 /* Based on the choice made above, do something */
4443 /* top and bottom */
4444 for (x = x1; x <= x2; x++)
4446 place_outer_bold(y1, x);
4447 place_outer_bold(y2, x);
4450 /* left and right */
4451 for (y = y1 + 1; y < y2; y++)
4453 place_outer_bold(y, x1);
4454 place_outer_bold(y, x2);
4457 /* Make a couple of entrances */
4458 if (randint(2) == 1)
4460 /* left and right */
4461 y = randint(ysize) + y1;
4462 place_floor_bold(y, x1);
4463 place_floor_bold(y, x2);
4467 /* top and bottom */
4468 x = randint(xsize) + x1;
4469 place_floor_bold(y1, x);
4470 place_floor_bold(y2, x);
4473 /* Select size of keep */
4474 t1 = randint(ysize / 3) + y1;
4475 t2 = y2 - randint(ysize / 3);
4476 t3 = randint(xsize / 3) + x1;
4477 t4 = x2 - randint(xsize / 3);
4479 /* Do outside areas */
4481 /* Above and below keep */
4482 build_recursive_room(x1 + 1, y1 + 1, x2 - 1, t1, power + 1);
4483 build_recursive_room(x1 + 1, t2, x2 - 1, y2, power + 1);
4485 /* Left and right of keep */
4486 build_recursive_room(x1 + 1, t1 + 1, t3, t2 - 1, power + 3);
4487 build_recursive_room(t4, t1 + 1, x2 - 1, t2 - 1, power + 3);
4489 /* Make the keep itself: */
4502 /* Try to build a room */
4503 if ((xsize < 3) || (ysize < 3))
4505 for (y = y1; y < y2; y++)
4507 for (x = x1; x < x2; x++)
4509 place_inner_bold(y, x);
4517 /* Make outside walls */
4518 /* top and bottom */
4519 for (x = x1 + 1; x <= x2 - 1; x++)
4521 place_inner_bold(y1 + 1, x);
4522 place_inner_bold(y2 - 1, x);
4525 /* left and right */
4526 for (y = y1 + 1; y <= y2 - 1; y++)
4528 place_inner_bold(y, x1 + 1);
4529 place_inner_bold(y, x2 - 1);
4533 y = randint(ysize - 3) + y1 + 1;
4535 if (randint(2) == 1)
4538 place_floor_bold(y, x1 + 1);
4543 place_floor_bold(y, x2 - 1);
4546 /* Build the room */
4547 build_recursive_room(x1 + 2, y1 + 2, x2 - 2, y2 - 2, power + 3);
4552 /* Try and divide vertically */
4556 for (y = y1; y < y2; y++)
4558 for (x = x1; x < x2; x++)
4560 place_inner_bold(y, x);
4566 t1 = randint(xsize - 2) + x1 + 1;
4567 build_recursive_room(x1, y1, t1, y2, power - 2);
4568 build_recursive_room(t1 + 1, y1, x2, y2, power - 2);
4573 /* Try and divide horizontally */
4577 for (y = y1; y < y2; y++)
4579 for (x = x1; x < x2; x++)
4581 place_inner_bold(y, x);
4587 t1 = randint(ysize - 2) + y1 + 1;
4588 build_recursive_room(x1, y1, x2, t1, power - 2);
4589 build_recursive_room(x1, t1 + 1, x2, y2, power - 2);
4596 /* Build a castle */
4598 /* Driver routine: clear the region and call the recursive
4601 *This makes a vault that looks like a castle/ city in the dungeon.
4603 static void build_castle_vault(int x0, int y0, int xsize, int ysize)
4609 /* Pick a random room size */
4618 if (cheat_room) msg_print("Castle Vault");
4620 /* generate the room */
4621 for (y = y1 - 1; y <= y2 + 1; y++)
4623 for (x = x1 - 1; x <= x2 + 1; x++)
4625 cave[y][x].info |= (CAVE_ROOM | CAVE_ICKY);
4626 /* Make everything a floor */
4627 place_floor_bold(y, x);
4631 /* Make the castle */
4632 build_recursive_room(x1, y1, x2, y2, randint(5));
4634 /* Fill with monsters and treasure, low difficulty */
4635 fill_treasure(x1, x2, y1, y2, randint(3));
4640 * Add outer wall to a floored region
4641 * Note: no range checking is done so must be inside dungeon
4642 * This routine also stomps on doors
4644 static void add_outer_wall(int x, int y, int light,
4645 int x1, int y1, int x2, int y2)
4649 if (!in_bounds(y, x)) return;
4651 /* hack- check to see if square has been visited before
4652 * if so, then exit (use room flag to do this) */
4653 if (cave[y][x].info & CAVE_ROOM) return;
4656 cave[y][x].info |= CAVE_ROOM;
4658 if (is_floor_bold(y, x))
4660 for (i = -1; i <= 1; i++)
4662 for (j = -1; j <= 1; j++)
4664 if ((x + i >= x1) && (x + i <= x2) &&
4665 (y + j >= y1) && (y + j <= y2))
4667 add_outer_wall(x + i, y + j, light, x1, y1, x2, y2);
4668 if (light) cave[y][x].info |= CAVE_GLOW;
4673 else if (is_extra_bold(y, x))
4675 /* Set bounding walls */
4676 place_outer_bold(y, x);
4677 if (light == TRUE) cave[y][x].info |= CAVE_GLOW;
4679 else if (cave[y][x].feat == FEAT_PERM_OUTER)
4681 /* Set bounding walls */
4682 if (light == TRUE) cave[y][x].info |= CAVE_GLOW;
4688 * Hacked distance formula - gives the 'wrong' answer.
4689 * Used to build crypts
4691 static int dist2(int x1, int y1, int x2, int y2,
4692 int h1, int h2, int h3, int h4)
4698 /* Basically this works by taking the normal pythagorean formula
4699 * and using an expansion to express this in a way without the
4700 * square root. This approximate formula is then perturbed to give
4701 * the distorted results. (I found this by making a mistake when I was
4702 * trying to fix the circular rooms.)
4705 /* h1-h4 are constants that describe the metric */
4706 if (dx >= 2 * dy) return (dx + (dy * h1) / h2);
4707 if (dy >= 2 * dx) return (dy + (dx * h1) / h2);
4708 return (((dx + dy) * 128) / 181 +
4709 (dx * dx / (dy * h3) + dy * dy / (dx * h3)) * h4);
4710 /* 128/181 is approx. 1/sqrt(2) */
4715 * Build target vault.
4716 * This is made by two concentric "crypts" with perpendicular
4717 * walls creating the cross-hairs.
4719 static void build_target_vault(int x0, int y0, int xsize, int ysize)
4723 /* Make a random metric */
4725 h1 = randint(32) - 16;
4728 h4 = randint(32) - 16;
4730 if (cheat_room) msg_print("Target Vault");
4732 /* work out outer radius */
4743 for (x = x0 - rad; x <= x0 + rad; x++)
4745 for (y = y0 - rad; y <= y0 + rad; y++)
4747 /* clear room flag */
4748 cave[y][x].info &= ~(CAVE_ROOM);
4750 /* Vault - so is "icky" */
4751 cave[y][x].info |= CAVE_ICKY;
4753 if (dist2(y0, x0, y, x, h1, h2, h3, h4) <= rad - 1)
4755 /* inside- so is floor */
4756 place_floor_bold(y, x);
4760 /* make granite outside so arena works */
4761 place_extra_bold(y, x);
4764 /* proper boundary for arena */
4765 if (((y + rad) == y0) || ((y - rad) == y0) ||
4766 ((x + rad) == x0) || ((x - rad) == x0))
4768 place_extra_bold(y, x);
4773 /* Find visible outer walls and set to be FEAT_OUTER */
4774 add_outer_wall(x0, y0, FALSE, x0 - rad - 1, y0 - rad - 1,
4775 x0 + rad + 1, y0 + rad + 1);
4777 /* Add inner wall */
4778 for (x = x0 - rad / 2; x <= x0 + rad / 2; x++)
4780 for (y = y0 - rad / 2; y <= y0 + rad / 2; y++)
4782 if (dist2(y0, x0, y, x, h1, h2, h3, h4) == rad / 2)
4784 /* Make an internal wall */
4785 place_inner_bold(y, x);
4790 /* Add perpendicular walls */
4791 for (x = x0 - rad; x <= x0 + rad; x++)
4793 place_inner_bold(y0, x);
4796 for (y = y0 - rad; y <= y0 + rad; y++)
4798 place_inner_bold(y, x0);
4801 /* Make inner vault */
4802 for (y = y0 - 1; y <= y0 + 1; y++)
4804 place_inner_bold(y, x0 - 1);
4805 place_inner_bold(y, x0 + 1);
4807 for (x = x0 - 1; x <= x0 + 1; x++)
4809 place_inner_bold(y0 - 1, x);
4810 place_inner_bold(y0 + 1, x);
4813 place_floor_bold(y0, x0);
4816 /* Add doors to vault */
4817 /* get two distances so can place doors relative to centre */
4818 x = (rad - 2) / 4 + 1;
4821 add_door(x0 + x, y0);
4822 add_door(x0 + y, y0);
4823 add_door(x0 - x, y0);
4824 add_door(x0 - y, y0);
4825 add_door(x0, y0 + x);
4826 add_door(x0, y0 + y);
4827 add_door(x0, y0 - x);
4828 add_door(x0, y0 - y);
4830 /* Fill with stuff - medium difficulty */
4831 fill_treasure(x0 - rad, x0 + rad, y0 - rad, y0 + rad, randint(3) + 3);
4835 #ifdef ALLOW_CAVERNS_AND_LAKES
4837 * This routine uses a modified version of the lake code to make a
4838 * distribution of some terrain type over the vault. This type
4839 * depends on the dungeon depth.
4841 * Miniture rooms are then scattered across the vault.
4843 static void build_elemental_vault(int x0, int y0, int xsiz, int ysiz)
4848 int xsize, ysize, xhsize, yhsize, x, y, i;
4852 if (cheat_room) msg_print("Elemental Vault");
4854 /* round to make sizes even */
4862 /* Earth vault (Rubble) */
4865 else if (dun_level < 50)
4867 /* Air vault (Trees) */
4870 else if (dun_level < 75)
4872 /* Water vault (shallow water) */
4877 /* Fire vault (shallow lava) */
4883 /* testing values for these parameters: feel free to adjust */
4884 grd = 1 << (rand_int(3));
4886 /* want average of about 16 */
4887 roug = randint(8) * randint(4);
4889 /* Make up size of various componants */
4893 /* Deep water/lava */
4894 c1 = rand_int(c3 / 2) + rand_int(c3 / 2) - 5;
4896 /* Shallow boundary */
4900 generate_hmap(y0, x0, xsize, ysize, grd, roug, c3);
4902 /* Convert to normal format+ clean up */
4903 done = generate_lake(y0, x0, xsize, ysize, c1, c2, c3, type);
4906 /* Set icky flag because is a vault */
4907 for (x = 0; x <= xsize; x++)
4909 for (y = 0; y <= ysize; y++)
4911 cave[y0 - yhsize + y][x0 - xhsize + x].info |= CAVE_ICKY;
4915 /* make a few rooms in the vault */
4916 for (i = 1; i <= (xsize * ysize) / 50; i++)
4918 build_small_room(x0 + rand_int(xsize - 4) - xsize / 2 + 2,
4919 y0 + rand_int(ysize - 4) - ysize / 2 + 2);
4922 /* Fill with monsters and treasure, low difficulty */
4923 fill_treasure(x0 - xhsize + 1, x0 - xhsize + xsize - 1,
4924 y0 - yhsize + 1, y0 - yhsize + ysize - 1, randint(5));
4926 #endif /* ALLOW_CAVERNS_AND_LAKES */
4932 static void build_type10(int by0, int bx0)
4934 int y0, x0, xsize, ysize, vtype;
4937 /* big enough to look good, small enough to be fairly common. */
4938 xsize = randint(22) + 22;
4939 ysize = randint(11) + 11;
4941 /* Allocate in room_map. If will not fit, exit */
4942 if (!room_alloc(xsize + 1, ysize + 1, FALSE, by0, bx0, &x0, &y0)) return;
4944 /* Boost the rating- higher than lesser vaults and lower than greater vaults */
4947 /* (Sometimes) Cause a special feeling */
4948 if ((dun_level <= 50) ||
4949 (randint((dun_level - 40) * (dun_level - 40) + 1) < 400))
4951 good_item_flag = TRUE;
4954 /* Select type of vault */
4955 #ifdef ALLOW_CAVERNS_AND_LAKES
4956 vtype = randint(15);
4957 #else /* ALLOW_CAVERNS_AND_LAKES */
4959 #endif /* ALLOW_CAVERNS_AND_LAKES */
4963 /* Build an appropriate room */
4964 case 1: case 9: build_bubble_vault(x0, y0, xsize, ysize); break;
4965 case 2: case 10: build_room_vault(x0, y0, xsize, ysize); break;
4966 case 3: case 11: build_cave_vault(x0, y0, xsize, ysize); break;
4967 case 4: case 12: build_maze_vault(x0, y0, xsize, ysize, TRUE); break;
4968 case 5: case 13: build_mini_c_vault(x0, y0, xsize, ysize); break;
4969 case 6: case 14: build_castle_vault(x0, y0, xsize, ysize); break;
4970 case 7: case 15: build_target_vault(x0, y0, xsize, ysize); break;
4971 #ifdef ALLOW_CAVERNS_AND_LAKES
4972 case 8: build_elemental_vault(x0, y0, xsize, ysize); break;
4973 #endif /* ALLOW_CAVERNS_AND_LAKES */
4974 /* I know how to add a few more... give me some time. */
4983 * Build an vertical oval room.
4984 * For every grid in the possible square, check the distance.
4985 * If it's less than the radius, make it a room square.
4987 * When done fill from the inside to find the walls,
4989 static void build_type11(int by0, int bx0)
4991 int rad, x, y, x0, y0;
4994 /* Occasional light */
4995 if ((randint(dun_level) <= 15) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS)) light = TRUE;
4999 /* Allocate in room_map. If will not fit, exit */
5000 if (!room_alloc(rad * 2 + 1, rad * 2 + 1, FALSE, by0, bx0, &x0, &y0)) return;
5002 /* Make circular floor */
5003 for (x = x0 - rad; x <= x0 + rad; x++)
5005 for (y = y0 - rad; y <= y0 + rad; y++)
5007 if (distance(y0, x0, y, x) <= rad - 1)
5009 /* inside- so is floor */
5010 place_floor_bold(y, x);
5012 else if (distance(y0, x0, y, x) <= rad + 1)
5014 /* make granite outside so arena works */
5015 place_extra_bold(y, x);
5020 /* Find visible outer walls and set to be FEAT_OUTER */
5021 add_outer_wall(x0, y0, light, x0 - rad, y0 - rad, x0 + rad, y0 + rad);
5027 * For every grid in the possible square, check the (fake) distance.
5028 * If it's less than the radius, make it a room square.
5030 * When done fill from the inside to find the walls,
5032 static void build_type12(int by0, int bx0)
5034 int rad, x, y, x0, y0;
5036 bool emptyflag = TRUE;
5038 /* Make a random metric */
5040 h1 = randint(32) - 16;
5043 h4 = randint(32) - 16;
5045 /* Occasional light */
5046 if ((randint(dun_level) <= 5) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS)) light = TRUE;
5050 /* Allocate in room_map. If will not fit, exit */
5051 if (!room_alloc(rad * 2 + 3, rad * 2 + 3, FALSE, by0, bx0, &x0, &y0)) return;
5054 for (x = x0 - rad; x <= x0 + rad; x++)
5056 for (y = y0 - rad; y <= y0 + rad; y++)
5058 /* clear room flag */
5059 cave[y][x].info &= ~(CAVE_ROOM);
5061 if (dist2(y0, x0, y, x, h1, h2, h3, h4) <= rad - 1)
5063 /* inside - so is floor */
5064 place_floor_bold(y, x);
5066 else if (distance(y0, x0, y, x) < 3)
5068 place_floor_bold(y, x);
5072 /* make granite outside so arena works */
5073 place_extra_bold(y, x);
5076 /* proper boundary for arena */
5077 if (((y + rad) == y0) || ((y - rad) == y0) ||
5078 ((x + rad) == x0) || ((x - rad) == x0))
5080 place_extra_bold(y, x);
5085 /* Find visible outer walls and set to be FEAT_OUTER */
5086 add_outer_wall(x0, y0, light, x0 - rad - 1, y0 - rad - 1,
5087 x0 + rad + 1, y0 + rad + 1);
5089 /* Check to see if there is room for an inner vault */
5090 for (x = x0 - 2; x <= x0 + 2; x++)
5092 for (y = y0 - 2; y <= y0 + 2; y++)
5094 if (!is_floor_bold(y, x))
5096 /* Wall in the way */
5102 if (emptyflag && (randint(2) == 1))
5104 /* Build the vault */
5105 build_small_room(x0, y0);
5107 /* Place a treasure in the vault */
5108 place_object(y0, x0, FALSE, FALSE);
5110 /* Let's guard the treasure well */
5111 vault_monsters(y0, x0, rand_int(2) + 3);
5113 /* Traps naturally */
5114 vault_traps(y0, x0, 4, 4, rand_int(3) + 2);
5120 * Attempt to build a room of the given type at the given block
5122 * Note that we restrict the number of "crowded" rooms to reduce
5123 * the chance of overflowing the monster list during level creation.
5125 bool room_build(int by0, int bx0, int typ)
5127 /* Restrict level */
5128 if ((dun_level < roomdep[typ]) && !ironman_rooms) return (FALSE);
5130 /* Restrict "crowded" rooms */
5131 if ((dun->crowded >= 2) && ((typ == 5) || (typ == 6))) return (FALSE);
5136 /* Build an appropriate room */
5137 case 12: build_type12(by0, bx0); break;
5138 case 11: build_type11(by0, bx0); break;
5139 case 10: build_type10(by0, bx0); break;
5140 case 9: build_type9(by0, bx0); break;
5141 case 8: build_type8(by0, bx0); break;
5142 case 7: build_type7(by0, bx0); break;
5143 case 6: build_type6(by0, bx0, FALSE); break;
5144 case 5: build_type5(by0, bx0, FALSE); break;
5145 case 4: build_type4(by0, bx0); break;
5146 case 3: build_type3(by0, bx0); break;
5147 case 2: build_type2(by0, bx0); break;
5148 case 1: build_type1(by0, bx0); break;
5151 default: return (FALSE);