3 * @brief ダンジョンフロアの部屋生成処理 / make rooms. Used by generate.c when creating dungeons.
6 * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke\n
7 * This software may be copied and distributed for educational, research,\n
8 * and not for profit purposes provided that this copyright and statement\n
9 * are included in all such copies. Other copyrights may also apply.\n
10 * 2014 Deskull rearranged comment for Doxygen. \n
12 * Room building routines.\n
18 * 4 -- large room with features\n
19 * 5 -- monster nests\n
21 * 7 -- simple vaults\n
22 * 8 -- greater vaults\n
23 * 9 -- fractal caves\n
24 * 10 -- random vaults\n
25 * 11 -- circular rooms\n
27 * 13 -- trapped monster pits\n
28 * 14 -- trapped room\n
30 * 16 -- underground arcade\n
32 * Some functions are used to determine if the given monster\n
33 * is appropriate for inclusion in a monster nest or monster pit or\n
36 * None of the pits/nests are allowed to include "unique" monsters.\n
44 #include "rooms-normal.h"
45 #include "rooms-pitnest.h"
46 #include "rooms-vault.h"
51 *[from SAngband (originally from OAngband)]\n
53 * Table of values that control how many times each type of room will\n
54 * appear. Each type of room has its own row, and each column\n
55 * corresponds to dungeon levels 0, 10, 20, and so on. The final\n
56 * value is the minimum depth the room can appear at. -LM-\n
58 * Level 101 and below use the values for level 100.\n
60 * Rooms with lots of monsters or loot may not be generated if the\n
61 * object or monster lists are already nearly full. Rooms will not\n
62 * appear above their minimum depth. Tiny levels will not have space\n
63 * for all the rooms you ask for.\n
65 static room_info_type room_info_normal[ROOM_T_MAX] =
68 /* 0 10 20 30 40 50 60 70 80 90 100 min limit */
70 {{999,900,800,700,600,500,400,300,200,100, 0}, 0}, /*NORMAL */
71 {{ 1, 10, 20, 30, 40, 50, 60, 70, 80, 90,100}, 1}, /*OVERLAP */
72 {{ 1, 10, 20, 30, 40, 50, 60, 70, 80, 90,100}, 3}, /*CROSS */
73 {{ 1, 10, 20, 30, 40, 50, 60, 70, 80, 90,100}, 3}, /*INNER_F */
74 {{ 0, 1, 1, 1, 2, 3, 5, 6, 8, 10, 13}, 10}, /*NEST */
75 {{ 0, 1, 1, 2, 3, 4, 6, 8, 10, 13, 16}, 10}, /*PIT */
76 {{ 0, 1, 1, 1, 2, 2, 3, 5, 6, 8, 10}, 10}, /*LESSER_V */
77 {{ 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 4}, 20}, /*GREATER_V*/
78 {{ 0,100,200,300,400,500,600,700,800,900,999}, 10}, /*FRACAVE */
79 {{ 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2}, 10}, /*RANDOM_V */
80 {{ 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40}, 3}, /*OVAL */
81 {{ 1, 6, 12, 18, 24, 30, 36, 42, 48, 54, 60}, 10}, /*CRYPT */
82 {{ 0, 0, 1, 1, 1, 2, 3, 4, 5, 6, 8}, 20}, /*TRAP_PIT */
83 {{ 0, 0, 1, 1, 1, 2, 3, 4, 5, 6, 8}, 20}, /*TRAP */
84 {{ 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2}, 40}, /*GLASS */
85 {{ 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3}, 1}, /*ARCADE */
89 /*! 部屋の生成処理順 / Build rooms in descending order of difficulty. */
90 static byte room_build_order[ROOM_T_MAX] = {
110 * @brief 鍵のかかったドアを配置する
111 * @param y 配置したいフロアのY座標
112 * @param x 配置したいフロアのX座標
115 void place_locked_door(int y, int x)
117 if (d_info[dungeon_type].flags1 & DF1_NO_DOORS)
119 place_floor_bold(y, x);
123 set_cave_feat(y, x, feat_locked_door_random((d_info[dungeon_type].flags1 & DF1_GLASS_DOOR) ? DOOR_GLASS_DOOR : DOOR_DOOR));
124 cave[y][x].info &= ~(CAVE_FLOOR);
125 delete_monster(y, x);
131 * @param y 配置したいフロアのY座標
132 * @param x 配置したいフロアのX座標
133 * @param type DOOR_DEFAULT / DOOR_DOOR / DOOR_GLASS_DOOR / DOOR_CURTAIN のいずれか
136 void place_secret_door(int y, int x, int type)
138 if (d_info[dungeon_type].flags1 & DF1_NO_DOORS)
140 place_floor_bold(y, x);
144 cave_type *c_ptr = &cave[y][x];
146 if (type == DOOR_DEFAULT)
148 type = ((d_info[dungeon_type].flags1 & DF1_CURTAIN) &&
149 one_in_((d_info[dungeon_type].flags1 & DF1_NO_CAVE) ? 16 : 256)) ? DOOR_CURTAIN :
150 ((d_info[dungeon_type].flags1 & DF1_GLASS_DOOR) ? DOOR_GLASS_DOOR : DOOR_DOOR);
153 /* Create secret door */
154 place_closed_door(y, x, type);
156 if (type != DOOR_CURTAIN)
158 /* Hide by inner wall because this is used in rooms only */
159 c_ptr->mimic = feat_wall_inner;
161 /* Floor type terrain cannot hide a door */
162 if (feat_supports_los(c_ptr->mimic) && !feat_supports_los(c_ptr->feat))
164 if (have_flag(f_info[c_ptr->mimic].flags, FF_MOVE) || have_flag(f_info[c_ptr->mimic].flags, FF_CAN_FLY))
166 c_ptr->feat = one_in_(2) ? c_ptr->mimic : floor_type[randint0(100)];
172 c_ptr->info &= ~(CAVE_FLOOR);
173 delete_monster(y, x);
178 * @brief 1マスだけの部屋を作成し、上下左右いずれか一つに隠しドアを配置する。
179 * @param y0 配置したい中心のY座標
180 * @param x0 配置したい中心のX座標
182 * This funtion makes a very small room centred at (x0, y0)
183 * This is used in crypts, and random elemental vaults.
185 * Note - this should be used only on allocated regions
186 * within another room.
188 static void build_small_room(int x0, int y0)
192 for (y = y0 - 1; y <= y0 + 1; y++)
194 place_inner_bold(y, x0 - 1);
195 place_inner_bold(y, x0 + 1);
198 for (x = x0 - 1; x <= x0 + 1; x++)
200 place_inner_bold(y0 - 1, x);
201 place_inner_bold(y0 + 1, x);
204 /* Place a secret door on one side */
207 case 0: place_secret_door(y0, x0 - 1, DOOR_DEFAULT); break;
208 case 1: place_secret_door(y0, x0 + 1, DOOR_DEFAULT); break;
209 case 2: place_secret_door(y0 - 1, x0, DOOR_DEFAULT); break;
210 case 3: place_secret_door(y0 + 1, x0, DOOR_DEFAULT); break;
213 /* Clear mimic type */
214 cave[y0][x0].mimic = 0;
216 /* Add inner open space */
217 place_floor_bold(y0, x0);
222 * 指定範囲に通路が通っていることを確認した上で床で埋める
223 * This function tunnels around a room if it will cut off part of a cave system.
230 static void check_room_boundary(int x1, int y1, int x2, int y2)
233 bool old_is_floor, new_is_floor;
239 old_is_floor = get_is_floor(x1 - 1, y1);
242 * Count the number of floor-wall boundaries around the room
243 * Note: diagonal squares are ignored since the player can move diagonally
244 * to bypass these if needed.
247 /* Above the top boundary */
248 for (x = x1; x <= x2; x++)
250 new_is_floor = get_is_floor(x, y1 - 1);
252 /* Increment counter if they are different */
253 if (new_is_floor != old_is_floor) count++;
255 old_is_floor = new_is_floor;
259 for (y = y1; y <= y2; y++)
261 new_is_floor = get_is_floor(x2 + 1, y);
263 /* increment counter if they are different */
264 if (new_is_floor != old_is_floor) count++;
266 old_is_floor = new_is_floor;
269 /* Bottom boundary */
270 for (x = x2; x >= x1; x--)
272 new_is_floor = get_is_floor(x, y2 + 1);
274 /* increment counter if they are different */
275 if (new_is_floor != old_is_floor) count++;
277 old_is_floor = new_is_floor;
281 for (y = y2; y >= y1; y--)
283 new_is_floor = get_is_floor(x1 - 1, y);
285 /* increment counter if they are different */
286 if (new_is_floor != old_is_floor) count++;
288 old_is_floor = new_is_floor;
291 /* If all the same, or only one connection exit. */
292 if (count <= 2) return;
295 /* Tunnel around the room so to prevent problems with caves */
296 for (y = y1; y <= y2; y++)
298 for (x = x1; x <= x2; x++)
308 * find_space()の予備処理として部屋の生成が可能かを判定する /
309 * Helper function for find_space(). Is this a good location?
310 * @param blocks_high 範囲の高さ
311 * @param blocks_wide 範囲の幅
312 * @param block_y 範囲の上端
313 * @param block_x 範囲の左端
316 static bool find_space_aux(int blocks_high, int blocks_wide, int block_y, int block_x)
318 int by1, bx1, by2, bx2, by, bx;
320 /* Itty-bitty rooms must shift about within their rectangle */
323 if ((blocks_wide == 2) && (block_x % 3) == 2)
327 /* Rooms with width divisible by 3 must be fitted to a rectangle. */
328 else if ((blocks_wide % 3) == 0)
330 /* Must be aligned to the left edge of a 11x33 rectangle. */
331 if ((block_x % 3) != 0)
336 * Big rooms that do not have a width divisible by 3 must be
337 * aligned towards the edge of the dungeon closest to them.
341 /* Shift towards left edge of dungeon. */
342 if (block_x + (blocks_wide / 2) <= dun->col_rooms / 2)
344 if (((block_x % 3) == 2) && ((blocks_wide % 3) == 2))
346 if ((block_x % 3) == 1)
350 /* Shift toward right edge of dungeon. */
353 if (((block_x % 3) == 2) && ((blocks_wide % 3) == 2))
355 if ((block_x % 3) == 1)
363 by2 = block_y + blocks_high;
364 bx2 = block_x + blocks_wide;
366 /* Never run off the screen */
367 if ((by1 < 0) || (by2 > dun->row_rooms)) return FALSE;
368 if ((bx1 < 0) || (bx2 > dun->col_rooms)) return FALSE;
370 /* Verify available space */
371 for (by = by1; by < by2; by++)
373 for (bx = bx1; bx < bx2; bx++)
375 if (dun->room_map[by][bx])
382 /* This location is okay */
388 * @brief 部屋生成が可能なスペースを確保する / Find a good spot for the next room. -LM-
389 * @param y 部屋の生成が可能な中心Y座標を返す参照ポインタ
390 * @param x 部屋の生成が可能な中心X座標を返す参照ポインタ
391 * @param height 確保したい領域の高さ
392 * @param width 確保したい領域の幅
393 * @return 所定の範囲が確保できた場合TRUEを返す
395 * Find and allocate a free space in the dungeon large enough to hold\n
396 * the room calling this function.\n
398 * We allocate space in 11x11 blocks, but want to make sure that rooms\n
399 * align neatly on the standard screen. Therefore, we make them use\n
400 * blocks in few 11x33 rectangles as possible.\n
402 * Be careful to include the edges of the room in height and width!\n
404 * Return TRUE and values for the center of the room if all went well.\n
405 * Otherwise, return FALSE.\n
407 bool find_space(POSITION *y, POSITION *x, POSITION height, POSITION width)
409 int candidates, pick;
410 int by, bx, by1, bx1, by2, bx2;
411 int block_y = 0, block_x = 0;
414 /* Find out how many blocks we need. */
415 int blocks_high = 1 + ((height - 1) / BLOCK_HGT);
416 int blocks_wide = 1 + ((width - 1) / BLOCK_WID);
418 /* There are no way to allocate such huge space */
419 if (dun->row_rooms < blocks_high) return FALSE;
420 if (dun->col_rooms < blocks_wide) return FALSE;
425 /* Count the number of valid places */
426 for (block_y = dun->row_rooms - blocks_high; block_y >= 0; block_y--)
428 for (block_x = dun->col_rooms - blocks_wide; block_x >= 0; block_x--)
430 if (find_space_aux(blocks_high, blocks_wide, block_y, block_x))
432 /* Find a valid place */
445 if (!(d_info[dungeon_type].flags1 & DF1_NO_CAVE))
447 /* Choose a random one */
448 pick = randint1(candidates);
451 /* NO_CAVE dungeon (Castle) */
454 /* Always choose the center one */
455 pick = candidates/2 + 1;
458 /* Pick up the choosen location */
459 for (block_y = dun->row_rooms - blocks_high; block_y >= 0; block_y--)
461 for (block_x = dun->col_rooms - blocks_wide; block_x >= 0; block_x--)
463 if (find_space_aux(blocks_high, blocks_wide, block_y, block_x))
467 /* This one is picked? */
478 by2 = block_y + blocks_high;
479 bx2 = block_x + blocks_wide;
482 * It is *extremely* important that the following calculation
483 * be *exactly* correct to prevent memory errors
486 /* Acquire the location of the room */
487 (*y) = ((by1 + by2) * BLOCK_HGT) / 2;
488 (*x) = ((bx1 + bx2) * BLOCK_WID) / 2;
490 /* Save the room location */
491 if (dun->cent_n < CENT_MAX)
493 dun->cent[dun->cent_n].y = (byte_hack)*y;
494 dun->cent[dun->cent_n].x = (byte_hack)*x;
498 /* Reserve some blocks. */
499 for (by = by1; by < by2; by++)
501 for (bx = bx1; bx < bx2; bx++)
503 dun->room_map[by][bx] = TRUE;
509 * Hack- See if room will cut off a cavern.
511 * If so, fix by tunneling outside the room in such a
512 * way as to connect the caves.
514 check_room_boundary(*x - width / 2 - 1, *y - height / 2 - 1, *x + (width - 1) / 2 + 1, *y + (height - 1) / 2 + 1);
528 * Structure to hold all "fill" data
531 typedef struct fill_data_type fill_data_type;
533 struct fill_data_type
546 /* features to fill with */
555 /* number of filled squares */
559 static fill_data_type fill_data;
562 /* Store routine for the fractal cave generator */
563 /* this routine probably should be an inline function or a macro. */
564 static void store_height(int x, int y, int val)
566 /* if on boundary set val > cutoff so walls are not as square */
567 if (((x == fill_data.xmin) || (y == fill_data.ymin) ||
568 (x == fill_data.xmax) || (y == fill_data.ymax)) &&
569 (val <= fill_data.c1)) val = fill_data.c1 + 1;
571 /* store the value in height-map format */
572 cave[y][x].feat = (s16b)val;
579 * Explanation of the plasma fractal algorithm:
581 * A grid of points is created with the properties of a 'height-map'
582 * This is done by making the corners of the grid have a random value.
583 * The grid is then subdivided into one with twice the resolution.
584 * The new points midway between two 'known' points can be calculated
585 * by taking the average value of the 'known' ones and randomly adding
586 * or subtracting an amount proportional to the distance between those
587 * points. The final 'middle' points of the grid are then calculated
588 * by averaging all four of the originally 'known' corner points. An
589 * random amount is added or subtracted from this to get a value of the
590 * height at that point. The scaling factor here is adjusted to the
591 * slightly larger distance diagonally as compared to orthogonally.
593 * This is then repeated recursively to fill an entire 'height-map'
594 * A rectangular map is done the same way, except there are different
595 * scaling factors along the x and y directions.
597 * A hack to change the amount of correlation between points is done using
598 * the grd variable. If the current step size is greater than grd then
599 * the point will be random, otherwise it will be calculated by the
600 * above algorithm. This makes a maximum distance at which two points on
601 * the height map can affect each other.
603 * How fractal caves are made:
605 * When the map is complete, a cut-off value is used to create a cave.
606 * Heights below this value are "floor", and heights above are "wall".
607 * This also can be used to create lakes, by adding more height levels
608 * representing shallow and deep water/ lava etc.
610 * The grd variable affects the width of passages.
611 * The roug variable affects the roughness of those passages
613 * The tricky part is making sure the created cave is connected. This
614 * is done by 'filling' from the inside and only keeping the 'filled'
615 * floor. Walls bounding the 'filled' floor are also kept. Everything
616 * else is converted to the normal _extra_.
621 * Note that this uses the cave.feat array in a very hackish way
622 * the values are first set to zero, and then each array location
623 * is used as a "heightmap"
624 * The heightmap then needs to be converted back into the "feat" format.
626 * grd=level at which fractal turns on. smaller gives more mazelike caves
627 * roug=roughness level. 16=normal. higher values make things more convoluted
628 * small values are good for smooth walls.
629 * size=length of the side of the square cave system.
631 static void generate_hmap(int y0, int x0, int xsiz, int ysiz, int grd, int roug, int cutoff)
633 int xhsize, yhsize, xsize, ysize, maxsize;
636 * fixed point variables- these are stored as 256 x normal value
637 * this gives 8 binary places of fractional part + 8 places of normal part
640 u16b xstep, xhstep, ystep, yhstep;
641 u16b xstep2, xhstep2, ystep2, yhstep2;
642 u16b i, j, ii, jj, diagsize, xxsize, yysize;
644 /* Cache for speed */
647 /* redefine size so can change the value if out of range */
651 /* Paranoia about size of the system of caves */
652 if (xsize > 254) xsize = 254;
653 if (xsize < 4) xsize = 4;
654 if (ysize > 254) ysize = 254;
655 if (ysize < 4) ysize = 4;
657 /* get offsets to middle of array */
661 /* fix rounding problem */
665 /* get limits of region */
666 fill_data.xmin = x0 - xhsize;
667 fill_data.ymin = y0 - yhsize;
668 fill_data.xmax = x0 + xhsize;
669 fill_data.ymax = y0 + yhsize;
671 /* Store cutoff in global for quick access */
672 fill_data.c1 = cutoff;
675 * Scale factor for middle points:
676 * About sqrt(2) * 256 - correct for a square lattice
677 * approximately correct for everything else.
681 /* maximum of xsize and ysize */
682 maxsize = (xsize > ysize) ? xsize : ysize;
684 /* Clear the section */
685 for (i = 0; i <= xsize; i++)
687 for (j = 0; j <= ysize; j++)
689 /* -1 is a flag for "not done yet" */
690 cave[(int)(fill_data.ymin + j)][(int)(fill_data.xmin + i)].feat = -1;
691 /* Clear icky flag because may be redoing the cave */
692 cave[(int)(fill_data.ymin + j)][(int)(fill_data.xmin + i)].info &= ~(CAVE_ICKY);
696 /* Boundaries are walls */
697 cave[fill_data.ymin][fill_data.xmin].feat = (s16b)maxsize;
698 cave[fill_data.ymax][fill_data.xmin].feat = (s16b)maxsize;
699 cave[fill_data.ymin][fill_data.xmax].feat = (s16b)maxsize;
700 cave[fill_data.ymax][fill_data.xmax].feat = (s16b)maxsize;
702 /* Set the middle square to be an open area. */
703 cave[y0][x0].feat = 0;
705 /* Initialize the step sizes */
706 xstep = xhstep = xsize * 256;
707 ystep = yhstep = ysize * 256;
708 xxsize = xsize * 256;
709 yysize = ysize * 256;
712 * Fill in the rectangle with fractal height data -
713 * like the 'plasma fractal' in fractint.
715 while ((xhstep > 256) || (yhstep > 256))
717 /* Halve the step sizes */
723 /* cache well used values */
724 xstep2 = xstep / 256;
725 ystep2 = ystep / 256;
727 xhstep2 = xhstep / 256;
728 yhstep2 = yhstep / 256;
730 /* middle top to bottom. */
731 for (i = xhstep; i <= xxsize - xhstep; i += xstep)
733 for (j = 0; j <= yysize; j += ystep)
735 /* cache often used values */
736 ii = i / 256 + fill_data.xmin;
737 jj = j / 256 + fill_data.ymin;
740 if (cave[jj][ii].feat == -1)
744 /* If greater than 'grid' level then is random */
745 store_height(ii, jj, randint1(maxsize));
749 /* Average of left and right points +random bit */
751 (cave[jj][fill_data.xmin + (i - xhstep) / 256].feat
752 + cave[jj][fill_data.xmin + (i + xhstep) / 256].feat) / 2
753 + (randint1(xstep2) - xhstep2) * roug / 16);
760 /* middle left to right. */
761 for (j = yhstep; j <= yysize - yhstep; j += ystep)
763 for (i = 0; i <= xxsize; i += xstep)
765 /* cache often used values */
766 ii = i / 256 + fill_data.xmin;
767 jj = j / 256 + fill_data.ymin;
770 if (cave[jj][ii].feat == -1)
774 /* If greater than 'grid' level then is random */
775 store_height(ii, jj, randint1(maxsize));
779 /* Average of up and down points +random bit */
781 (cave[fill_data.ymin + (j - yhstep) / 256][ii].feat
782 + cave[fill_data.ymin + (j + yhstep) / 256][ii].feat) / 2
783 + (randint1(ystep2) - yhstep2) * roug / 16);
790 for (i = xhstep; i <= xxsize - xhstep; i += xstep)
792 for (j = yhstep; j <= yysize - yhstep; j += ystep)
794 /* cache often used values */
795 ii = i / 256 + fill_data.xmin;
796 jj = j / 256 + fill_data.ymin;
799 if (cave[jj][ii].feat == -1)
803 /* If greater than 'grid' level then is random */
804 store_height(ii, jj, randint1(maxsize));
808 /* Cache reused values. */
809 xm = fill_data.xmin + (i - xhstep) / 256;
810 xp = fill_data.xmin + (i + xhstep) / 256;
811 ym = fill_data.ymin + (j - yhstep) / 256;
812 yp = fill_data.ymin + (j + yhstep) / 256;
815 * Average over all four corners + scale by diagsize to
816 * reduce the effect of the square grid on the shape of the fractal
819 (cave[ym][xm].feat + cave[yp][xm].feat
820 + cave[ym][xp].feat + cave[yp][xp].feat) / 4
821 + (randint1(xstep2) - xhstep2) * (diagsize / 16) / 256 * roug);
830 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)
833 * function used to convert from height-map back to the
834 * normal angband cave format
836 if (cave[y][x].info & CAVE_ICKY)
843 /* Show that have looked at this square */
844 cave[y][x].info|= (CAVE_ICKY);
846 /* Use cutoffs c1-c3 to allocate regions of floor /water/ lava etc. */
847 if (cave[y][x].feat <= c1)
849 /* 25% of the time use the other tile : it looks better this way */
850 if (randint1(100) < 75)
852 cave[y][x].feat = (s16b)feat1;
853 cave[y][x].info &= ~(CAVE_MASK);
854 cave[y][x].info |= info1;
859 cave[y][x].feat = (s16b)feat2;
860 cave[y][x].info &= ~(CAVE_MASK);
861 cave[y][x].info |= info2;
865 else if (cave[y][x].feat <= c2)
867 /* 25% of the time use the other tile : it looks better this way */
868 if (randint1(100) < 75)
870 cave[y][x].feat = (s16b)feat2;
871 cave[y][x].info &= ~(CAVE_MASK);
872 cave[y][x].info |= info2;
877 cave[y][x].feat = (s16b)feat1;
878 cave[y][x].info &= ~(CAVE_MASK);
879 cave[y][x].info |= info1;
883 else if (cave[y][x].feat <= c3)
885 cave[y][x].feat = (s16b)feat3;
886 cave[y][x].info &= ~(CAVE_MASK);
887 cave[y][x].info |= info3;
890 /* if greater than cutoff then is a wall */
893 place_outer_bold(y, x);
903 * Quick and nasty fill routine used to find the connected region
904 * of floor in the middle of the cave
906 static void cave_fill(POSITION y, POSITION x)
917 /* Enqueue that entry */
922 /* Now process the queue */
923 while (flow_head != flow_tail)
925 /* Extract the next entry */
926 ty = temp_y[flow_head];
927 tx = temp_x[flow_head];
929 /* Forget that entry */
930 if (++flow_head == TEMP_MAX) flow_head = 0;
932 /* Add the "children" */
933 for (d = 0; d < 8; d++)
935 int old_head = flow_tail;
941 /* Paranoia Don't leave the cave */
942 if (!in_bounds(j, i))
944 /* affect boundary */
945 cave[j][i].info |= CAVE_ICKY;
949 /* If within bounds */
950 else if ((i > fill_data.xmin) && (i < fill_data.xmax)
951 && (j > fill_data.ymin) && (j < fill_data.ymax))
953 /* If not a wall or floor done before */
954 if (hack_isnt_wall(j, i,
955 fill_data.c1, fill_data.c2, fill_data.c3,
956 fill_data.feat1, fill_data.feat2, fill_data.feat3,
957 fill_data.info1, fill_data.info2, fill_data.info3))
959 /* Enqueue that entry */
960 temp_y[flow_tail] = (byte_hack)j;
961 temp_x[flow_tail] = (byte_hack)i;
963 /* Advance the queue */
964 if (++flow_tail == TEMP_MAX) flow_tail = 0;
966 /* Hack -- Overflow by forgetting new entry */
967 if (flow_tail == flow_head)
969 flow_tail = old_head;
973 /* keep tally of size of cave system */
974 (fill_data.amount)++;
980 /* affect boundary */
981 cave[j][i].info |= CAVE_ICKY;
988 static bool generate_fracave(int y0, int x0, int xsize, int ysize, int cutoff, bool light, bool room)
990 int x, y, i, xhsize, yhsize;
992 /* offsets to middle from corner */
998 * select region connected to center of cave system
999 * this gets rid of alot of isolated one-sqaures that
1000 * can make teleport traps instadeaths...
1004 fill_data.c1 = cutoff;
1008 /* features to fill with */
1009 fill_data.feat1 = floor_type[randint0(100)];
1010 fill_data.feat2 = floor_type[randint0(100)];
1011 fill_data.feat3 = floor_type[randint0(100)];
1013 fill_data.info1 = CAVE_FLOOR;
1014 fill_data.info2 = CAVE_FLOOR;
1015 fill_data.info3 = CAVE_FLOOR;
1017 /* number of filled squares */
1018 fill_data.amount = 0;
1020 cave_fill((byte)y0, (byte)x0);
1022 /* if tally too small, try again */
1023 if (fill_data.amount < 10)
1025 /* too small - clear area and try again later */
1026 for (x = 0; x <= xsize; ++x)
1028 for (y = 0; y <= ysize; ++y)
1030 place_extra_bold(y0 + y - yhsize, x0 + x - xhsize);
1031 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY | CAVE_ROOM);
1038 * Do boundarys-check to see if they are next to a filled region
1039 * If not then they are set to normal granite
1040 * If so then they are marked as room walls.
1042 for (i = 0; i <= xsize; ++i)
1045 if ((cave[0 + y0 - yhsize][i + x0 - xhsize].info & CAVE_ICKY) && (room))
1047 /* Next to a 'filled' region? - set to be room walls */
1048 place_outer_bold(y0 + 0 - yhsize, x0 + i - xhsize);
1049 if (light) cave[y0 + 0 - yhsize][x0 + i - xhsize].info |= (CAVE_GLOW);
1050 cave[y0 + 0 - yhsize][x0 + i - xhsize].info |= (CAVE_ROOM);
1051 place_outer_bold(y0 + 0 - yhsize, x0 + i - xhsize);
1055 /* set to be normal granite */
1056 place_extra_bold(y0 + 0 - yhsize, x0 + i - xhsize);
1059 /* bottom boundary */
1060 if ((cave[ysize + y0 - yhsize][i + x0 - xhsize].info & CAVE_ICKY) && (room))
1062 /* Next to a 'filled' region? - set to be room walls */
1063 place_outer_bold(y0 + ysize - yhsize, x0 + i - xhsize);
1064 if (light) cave[y0 + ysize - yhsize][x0 + i - xhsize].info|=(CAVE_GLOW);
1065 cave[y0 + ysize - yhsize][x0 + i - xhsize].info|=(CAVE_ROOM);
1066 place_outer_bold(y0 + ysize - yhsize, x0 + i - xhsize);
1070 /* set to be normal granite */
1071 place_extra_bold(y0 + ysize - yhsize, x0 + i - xhsize);
1074 /* clear the icky flag-don't need it any more */
1075 cave[y0 + 0 - yhsize][x0 + i - xhsize].info &= ~(CAVE_ICKY);
1076 cave[y0 + ysize - yhsize][x0 + i - xhsize].info &= ~(CAVE_ICKY);
1079 /* Do the left and right boundaries minus the corners (done above) */
1080 for (i = 1; i < ysize; ++i)
1083 if ((cave[i + y0 - yhsize][0 + x0 - xhsize].info & CAVE_ICKY) && room)
1086 place_outer_bold(y0 + i - yhsize, x0 + 0 - xhsize);
1087 if (light) cave[y0 + i - yhsize][x0 + 0 - xhsize].info |= (CAVE_GLOW);
1088 cave[y0 + i - yhsize][x0 + 0 - xhsize].info |= (CAVE_ROOM);
1089 place_outer_bold(y0 + i - yhsize, x0 + 0 - xhsize);
1094 place_extra_bold(y0 + i - yhsize, x0 + 0 - xhsize);
1096 /* right boundary */
1097 if ((cave[i + y0 - yhsize][xsize + x0 - xhsize].info & CAVE_ICKY) && room)
1100 place_outer_bold(y0 + i - yhsize, x0 + xsize - xhsize);
1101 if (light) cave[y0 + i - yhsize][x0 + xsize - xhsize].info |= (CAVE_GLOW);
1102 cave[y0 + i - yhsize][x0 + xsize - xhsize].info |= (CAVE_ROOM);
1103 place_outer_bold(y0 + i - yhsize, x0 + xsize - xhsize);
1108 place_extra_bold(y0 + i - yhsize, x0 + xsize - xhsize);
1111 /* clear icky flag -done with it */
1112 cave[y0 + i - yhsize][x0 + 0 - xhsize].info &= ~(CAVE_ICKY);
1113 cave[y0 + i - yhsize][x0 + xsize - xhsize].info &= ~(CAVE_ICKY);
1117 /* Do the rest: convert back to the normal format */
1118 for (x = 1; x < xsize; ++x)
1120 for (y = 1; y < ysize; ++y)
1122 if (is_floor_bold(y0 + y - yhsize, x0 + x - xhsize) &&
1123 (cave[y0 + y - yhsize][x0 + x - xhsize].info & CAVE_ICKY))
1125 /* Clear the icky flag in the filled region */
1126 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~CAVE_ICKY;
1128 /* Set appropriate flags */
1129 if (light) cave[y0 + y - yhsize][x0 + x - xhsize].info |= (CAVE_GLOW);
1130 if (room) cave[y0 + y - yhsize][x0 + x - xhsize].info |= (CAVE_ROOM);
1132 else if (is_outer_bold(y0 + y - yhsize, x0 + x - xhsize) &&
1133 (cave[y0 + y - yhsize][x0 + x - xhsize].info & CAVE_ICKY))
1136 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY);
1137 if (light) cave[y0 + y - yhsize][x0 + x - xhsize].info |= (CAVE_GLOW);
1140 cave[y0 + y - yhsize][x0 + x - xhsize].info |= (CAVE_ROOM);
1145 place_extra_bold(y0 + y - yhsize, x0 + x - xhsize);
1146 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ROOM);
1151 /* Clear the unconnected regions */
1152 place_extra_bold(y0 + y - yhsize, x0 + x - xhsize);
1153 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY | CAVE_ROOM);
1159 * XXX XXX XXX There is a slight problem when tunnels pierce the caves:
1160 * Extra doors appear inside the system. (Its not very noticeable though.)
1161 * This can be removed by "filling" from the outside in. This allows a separation
1162 * from _outer_ with _inner_. (Internal walls are _outer_ instead.)
1163 * The extra effort for what seems to be only a minor thing (even non-existant if you
1164 * think of the caves not as normal rooms, but as holes in the dungeon), doesn't seem
1173 * @brief タイプ9の部屋…フラクタルカーブによる洞窟生成 / Type 9 -- Driver routine to create fractal cave system
1176 static bool build_type9(void)
1178 int grd, roug, cutoff;
1179 POSITION xsize, ysize, y0, x0;
1181 bool done, light, room;
1183 /* get size: note 'Evenness'*/
1184 xsize = randint1(22) * 2 + 6;
1185 ysize = randint1(15) * 2 + 6;
1187 /* Find and reserve some space in the dungeon. Get center of room. */
1188 if (!find_space(&y0, &x0, ysize + 1, xsize + 1))
1190 /* Limit to the minimum room size, and retry */
1194 /* Find and reserve some space in the dungeon. Get center of room. */
1195 if (!find_space(&y0, &x0, ysize + 1, xsize + 1))
1201 return build_type1();
1205 light = done = FALSE;
1208 if ((dun_level <= randint1(25)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS)) light = TRUE;
1212 /* Note: size must be even or there are rounding problems
1213 * This causes the tunnels not to connect properly to the room */
1215 /* testing values for these parameters feel free to adjust */
1216 grd = 1 << (randint0(4));
1218 /* want average of about 16 */
1219 roug = randint1(8) * randint1(4);
1222 cutoff = randint1(xsize / 4) + randint1(ysize / 4) +
1223 randint1(xsize / 4) + randint1(ysize / 4);
1226 generate_hmap(y0, x0, xsize, ysize, grd, roug, cutoff);
1228 /* Convert to normal format + clean up */
1229 done = generate_fracave(y0, x0, xsize, ysize, cutoff, light, room);
1235 #ifdef ALLOW_CAVERNS_AND_LAKES
1237 * Builds a cave system in the center of the dungeon.
1239 void build_cavern(void)
1241 int grd, roug, cutoff, xsize, ysize, x0, y0;
1244 light = done = FALSE;
1245 if ((dun_level <= randint1(50)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS)) light = TRUE;
1247 /* Make a cave the size of the dungeon */
1248 xsize = cur_wid - 1;
1249 ysize = cur_hgt - 1;
1253 /* Paranoia: make size even */
1259 /* testing values for these parameters: feel free to adjust */
1260 grd = randint1(4) + 4;
1262 /* want average of about 16 */
1263 roug = randint1(8) * randint1(4);
1269 generate_hmap(y0 + 1, x0 + 1, xsize, ysize, grd, roug, cutoff);
1271 /* Convert to normal format+ clean up */
1272 done = generate_fracave(y0 + 1, x0 + 1, xsize, ysize, cutoff, light, FALSE);
1276 static bool generate_lake(int y0, int x0, int xsize, int ysize, int c1, int c2, int c3, int type)
1278 int x, y, i, xhsize, yhsize;
1279 int feat1, feat2, feat3;
1281 /* offsets to middle from corner */
1285 /* Get features based on type */
1288 case LAKE_T_LAVA: /* Lava */
1289 feat1 = feat_deep_lava;
1290 feat2 = feat_shallow_lava;
1291 feat3 = floor_type[randint0(100)];
1293 case LAKE_T_WATER: /* Water */
1294 feat1 = feat_deep_water;
1295 feat2 = feat_shallow_water;
1296 feat3 = floor_type[randint0(100)];
1298 case LAKE_T_CAVE: /* Collapsed cave */
1299 feat1 = floor_type[randint0(100)];
1300 feat2 = floor_type[randint0(100)];
1301 feat3 = feat_rubble;
1303 case LAKE_T_EARTH_VAULT: /* Earth vault */
1304 feat1 = feat_rubble;
1305 feat2 = floor_type[randint0(100)];
1306 feat3 = feat_rubble;
1308 case LAKE_T_AIR_VAULT: /* Air vault */
1313 case LAKE_T_WATER_VAULT: /* Water vault */
1314 feat1 = feat_shallow_water;
1315 feat2 = feat_deep_water;
1316 feat3 = feat_shallow_water;
1318 case LAKE_T_FIRE_VAULT: /* Fire Vault */
1319 feat1 = feat_shallow_lava;
1320 feat2 = feat_deep_lava;
1321 feat3 = feat_shallow_lava;
1325 default: return FALSE;
1329 * select region connected to center of cave system
1330 * this gets rid of alot of isolated one-sqaures that
1331 * can make teleport traps instadeaths...
1339 /* features to fill with */
1340 fill_data.feat1 = feat1;
1341 fill_data.feat2 = feat2;
1342 fill_data.feat3 = feat3;
1344 fill_data.info1 = 0;
1345 fill_data.info2 = 0;
1346 fill_data.info3 = 0;
1348 /* number of filled squares */
1349 fill_data.amount = 0;
1351 /* select region connected to center of cave system
1352 * this gets rid of alot of isolated one-sqaures that
1353 * can make teleport traps instadeaths... */
1354 cave_fill((byte)y0, (byte)x0);
1356 /* if tally too small, try again */
1357 if (fill_data.amount < 10)
1359 /* too small -clear area and try again later */
1360 for (x = 0; x <= xsize; ++x)
1362 for (y = 0; y <= ysize; ++y)
1364 place_floor_bold(y0 + y - yhsize, x0 + x - xhsize);
1365 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY);
1371 /* Do boundarys- set to normal granite */
1372 for (i = 0; i <= xsize; ++i)
1374 place_extra_bold(y0 + 0 - yhsize, x0 + i - xhsize);
1375 place_extra_bold(y0 + ysize - yhsize, x0 + i - xhsize);
1377 /* clear the icky flag-don't need it any more */
1378 cave[y0 + 0 - yhsize][x0 + i - xhsize].info &= ~(CAVE_ICKY);
1379 cave[y0 + ysize - yhsize][x0 + i - xhsize].info &= ~(CAVE_ICKY);
1382 /* Do the left and right boundaries minus the corners (done above) */
1384 for (i = 1; i < ysize; ++i)
1386 place_extra_bold(y0 + i - yhsize, x0 + 0 - xhsize);
1387 place_extra_bold(y0 + i - yhsize, x0 + xsize - xhsize);
1389 /* clear icky flag -done with it */
1390 cave[y0 + i - yhsize][x0 + 0 - xhsize].info &= ~(CAVE_ICKY);
1391 cave[y0 + i - yhsize][x0 + xsize - xhsize].info &= ~(CAVE_ICKY);
1395 /* Do the rest: convert back to the normal format */
1396 for (x = 1; x < xsize; ++x)
1398 for (y = 1; y < ysize; ++y)
1400 /* Fill unconnected regions with granite */
1401 if ((!(cave[y0 + y - yhsize][x0 + x - xhsize].info & CAVE_ICKY)) ||
1402 is_outer_bold(y0 + y - yhsize, x0 + x - xhsize))
1403 place_extra_bold(y0 + y - yhsize, x0 + x - xhsize);
1405 /* turn off icky flag (no longer needed.) */
1406 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY | CAVE_ROOM);
1409 if (cave_have_flag_bold(y0 + y - yhsize, x0 + x - xhsize, FF_LAVA))
1411 if (!(d_info[dungeon_type].flags1 & DF1_DARKNESS)) cave[y0 + y - yhsize][x0 + x - xhsize].info |= CAVE_GLOW;
1421 * makes a lake/collapsed cave system in the center of the dungeon
1423 void build_lake(int type)
1425 int grd, roug, xsize, ysize, x0, y0;
1429 /* paranoia - exit if lake type out of range. */
1430 if ((type < LAKE_T_LAVA) || (type > LAKE_T_FIRE_VAULT))
1432 msg_format("Invalid lake type (%d)", type);
1436 /* Make the size of the dungeon */
1437 xsize = cur_wid - 1;
1438 ysize = cur_hgt - 1;
1442 /* Paranoia: make size even */
1448 /* testing values for these parameters: feel free to adjust */
1449 grd = randint1(3) + 4;
1451 /* want average of about 16 */
1452 roug = randint1(8) * randint1(4);
1454 /* Make up size of various componants */
1458 /* Deep water/lava */
1459 c1 = randint0(c3 / 2) + randint0(c3 / 2) - 5;
1461 /* Shallow boundary */
1465 generate_hmap(y0 + 1, x0 + 1, xsize, ysize, grd, roug, c3);
1467 /* Convert to normal format+ clean up */
1468 done = generate_lake(y0 + 1, x0 + 1, xsize, ysize, c1, c2, c3, type);
1471 #endif /* ALLOW_CAVERNS_AND_LAKES */
1475 * Routine used by the random vault creators to add a door to a location
1476 * Note that range checking has to be done in the calling routine.
1478 * The doors must be INSIDE the allocated region.
1480 static void add_door(int x, int y)
1482 /* Need to have a wall in the center square */
1483 if (!is_outer_bold(y, x)) return;
1490 * where x=don't care
1494 if (is_floor_bold(y-1,x) && is_floor_bold(y+1,x) &&
1495 (is_outer_bold(y, x - 1) && is_outer_bold(y, x + 1)))
1498 place_secret_door(y, x, DOOR_DEFAULT);
1500 /* set boundarys so don't get wide doors */
1501 place_solid_bold(y, x - 1);
1502 place_solid_bold(y, x + 1);
1511 * where x = don't care
1514 if (is_outer_bold(y - 1, x) && is_outer_bold(y + 1, x) &&
1515 is_floor_bold(y,x-1) && is_floor_bold(y,x+1))
1518 place_secret_door(y, x, DOOR_DEFAULT);
1520 /* set boundarys so don't get wide doors */
1521 place_solid_bold(y - 1, x);
1522 place_solid_bold(y + 1, x);
1528 * Routine that fills the empty areas of a room with treasure and monsters.
1530 static void fill_treasure(int x1, int x2, int y1, int y2, int difficulty)
1532 int x, y, cx, cy, size;
1535 /* center of room:*/
1539 /* Rough measure of size of vault= sum of lengths of sides */
1540 size = abs(x2 - x1) + abs(y2 - y1);
1542 for (x = x1; x <= x2; x++)
1544 for (y = y1; y <= y2; y++)
1546 /* Thing added based on distance to center of vault
1547 * Difficulty is 1-easy to 10-hard */
1548 value = ((((s32b)(distance(cx, cy, x, y))) * 100) / size) + randint1(10) - difficulty;
1550 /* hack- empty square part of the time */
1551 if ((randint1(100) - difficulty * 3) > 50) value = 20;
1553 /* if floor, shallow water and lava */
1554 if (is_floor_bold(y, x) ||
1555 (cave_have_flag_bold(y, x, FF_PLACE) && cave_have_flag_bold(y, x, FF_DROP)))
1557 /* The smaller 'value' is, the better the stuff */
1560 /* Meanest monster + treasure */
1561 monster_level = base_level + 40;
1562 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
1563 monster_level = base_level;
1564 object_level = base_level + 20;
1565 place_object(y, x, AM_GOOD);
1566 object_level = base_level;
1570 /* Mean monster +treasure */
1571 monster_level = base_level + 20;
1572 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
1573 monster_level = base_level;
1574 object_level = base_level + 10;
1575 place_object(y, x, AM_GOOD);
1576 object_level = base_level;
1578 else if (value < 10)
1581 monster_level = base_level + 9;
1582 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
1583 monster_level = base_level;
1585 else if (value < 17)
1587 /* Intentional Blank space */
1590 * (Want some of the vault to be empty
1591 * so have room for group monsters.
1592 * This is used in the hack above to lower
1593 * the density of stuff in the vault.)
1596 else if (value < 23)
1598 /* Object or trap */
1599 if (randint0(100) < 25)
1601 place_object(y, x, 0L);
1608 else if (value < 30)
1610 /* Monster and trap */
1611 monster_level = base_level + 5;
1612 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
1613 monster_level = base_level;
1616 else if (value < 40)
1618 /* Monster or object */
1619 if (randint0(100) < 50)
1621 monster_level = base_level + 3;
1622 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
1623 monster_level = base_level;
1625 if (randint0(100) < 50)
1627 object_level = base_level + 7;
1628 place_object(y, x, 0L);
1629 object_level = base_level;
1632 else if (value < 50)
1641 /* 20% monster, 40% trap, 20% object, 20% blank space */
1642 if (randint0(100) < 20)
1644 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
1646 else if (randint0(100) < 50)
1650 else if (randint0(100) < 50)
1652 place_object(y, x, 0L);
1663 * This function creates a random vault that looks like a collection of bubbles.
1664 * It works by getting a set of coordinates that represent the center of each
1665 * bubble. The entire room is made by seeing which bubble center is closest. If
1666 * two centers are equidistant then the square is a wall, otherwise it is a floor.
1667 * The only exception is for squares really near a center, these are always floor.
1668 * (It looks better than without this check.)
1670 * Note: If two centers are on the same point then this algorithm will create a
1671 * blank bubble filled with walls. - This is prevented from happening.
1673 static void build_bubble_vault(int x0, int y0, int xsize, int ysize)
1675 #define BUBBLENUM 10 /* number of bubbles */
1677 /* array of center points of bubbles */
1678 coord center[BUBBLENUM];
1681 u16b min1, min2, temp;
1684 /* Offset from center to top left hand corner */
1685 int xhsize = xsize / 2;
1686 int yhsize = ysize / 2;
1688 msg_print_wizard(CHEAT_DUNGEON, _("泡型ランダムVaultを生成しました。", "Room Vault."));
1690 /* Allocate center of bubbles */
1691 center[0].x = (byte)randint1(xsize - 3) + 1;
1692 center[0].y = (byte)randint1(ysize - 3) + 1;
1694 for (i = 1; i < BUBBLENUM; i++)
1698 /* get center and check to see if it is unique */
1703 x = randint1(xsize - 3) + 1;
1704 y = randint1(ysize - 3) + 1;
1706 for (j = 0; j < i; j++)
1708 /* rough test to see if there is an overlap */
1709 if ((x == center[j].x) && (y == center[j].y)) done = FALSE;
1713 center[i].x = (byte_hack)x;
1714 center[i].y = (byte_hack)y;
1718 /* Top and bottom boundaries */
1719 for (i = 0; i < xsize; i++)
1721 int side_x = x0 - xhsize + i;
1723 place_outer_noperm_bold(y0 - yhsize + 0, side_x);
1724 cave[y0 - yhsize + 0][side_x].info |= (CAVE_ROOM | CAVE_ICKY);
1725 place_outer_noperm_bold(y0 - yhsize + ysize - 1, side_x);
1726 cave[y0 - yhsize + ysize - 1][side_x].info |= (CAVE_ROOM | CAVE_ICKY);
1729 /* Left and right boundaries */
1730 for (i = 1; i < ysize - 1; i++)
1732 int side_y = y0 - yhsize + i;
1734 place_outer_noperm_bold(side_y, x0 - xhsize + 0);
1735 cave[side_y][x0 - xhsize + 0].info |= (CAVE_ROOM | CAVE_ICKY);
1736 place_outer_noperm_bold(side_y, x0 - xhsize + xsize - 1);
1737 cave[side_y][x0 - xhsize + xsize - 1].info |= (CAVE_ROOM | CAVE_ICKY);
1740 /* Fill in middle with bubbles */
1741 for (x = 1; x < xsize - 1; x++)
1743 for (y = 1; y < ysize - 1; y++)
1745 /* Get distances to two closest centers */
1748 min1 = (u16b)distance(x, y, center[0].x, center[0].y);
1749 min2 = (u16b)distance(x, y, center[1].x, center[1].y);
1753 /* swap if in wrong order */
1760 for (i = 2; i < BUBBLENUM; i++)
1762 temp = (u16b)distance(x, y, center[i].x, center[i].y);
1770 else if (temp < min2)
1772 /* second smallest */
1776 if (((min2 - min1) <= 2) && (!(min1 < 3)))
1778 /* Boundary at midpoint+ not at inner region of bubble */
1779 place_outer_noperm_bold(y0 - yhsize + y, x0 - xhsize + x);
1783 /* middle of a bubble */
1784 place_floor_bold(y0 - yhsize + y, x0 - xhsize + x);
1787 /* clean up rest of flags */
1788 cave[y0 - yhsize + y][x0 - xhsize + x].info |= (CAVE_ROOM | CAVE_ICKY);
1792 /* Try to add some random doors */
1793 for (i = 0; i < 500; i++)
1795 x = randint1(xsize - 3) - xhsize + x0 + 1;
1796 y = randint1(ysize - 3) - yhsize + y0 + 1;
1800 /* Fill with monsters and treasure, low difficulty */
1801 fill_treasure(x0 - xhsize + 1, x0 - xhsize + xsize - 2, y0 - yhsize + 1, y0 - yhsize + ysize - 2, randint1(5));
1806 * Overlay a rectangular room given its bounds
1807 * This routine is used by build_room_vault
1808 * The area inside the walls is not touched:
1809 * only granite is removed- normal walls stay
1811 static void build_room(int x1, int x2, int y1, int y2)
1813 int x, y, i, xsize, ysize, temp;
1815 /* Check if rectangle has no width */
1816 if ((x1 == x2) || (y1 == y2)) return;
1821 /* Swap boundaries if in wrong order */
1829 /* Swap boundaries if in wrong order */
1835 /* get total widths */
1840 /* Top and bottom boundaries */
1841 for (i = 0; i <= xsize; i++)
1843 place_outer_noperm_bold(y1, x1 + i);
1844 cave[y1][x1 + i].info |= (CAVE_ROOM | CAVE_ICKY);
1845 place_outer_noperm_bold(y2, x1 + i);
1846 cave[y2][x1 + i].info |= (CAVE_ROOM | CAVE_ICKY);
1849 /* Left and right boundaries */
1850 for (i = 1; i < ysize; i++)
1852 place_outer_noperm_bold(y1 + i, x1);
1853 cave[y1 + i][x1].info|=(CAVE_ROOM | CAVE_ICKY);
1854 place_outer_noperm_bold(y1 + i, x2);
1855 cave[y1 + i][x2].info|=(CAVE_ROOM | CAVE_ICKY);
1859 for (x = 1; x < xsize; x++)
1861 for (y = 1; y < ysize; y++)
1863 if (is_extra_bold(y1+y, x1+x))
1865 /* clear the untouched region */
1866 place_floor_bold(y1 + y, x1 + x);
1867 cave[y1 + y][x1 + x].info |= (CAVE_ROOM | CAVE_ICKY);
1871 /* make it a room- but don't touch */
1872 cave[y1 + y][x1 + x].info |= (CAVE_ROOM | CAVE_ICKY);
1879 /* Create a random vault that looks like a collection of overlapping rooms */
1881 static void build_room_vault(int x0, int y0, int xsize, int ysize)
1883 int i, x1, x2, y1, y2, xhsize, yhsize;
1885 /* get offset from center */
1889 msg_print_wizard(CHEAT_DUNGEON, _("部屋型ランダムVaultを生成しました。", "Room Vault."));
1891 /* fill area so don't get problems with arena levels */
1892 for (x1 = 0; x1 < xsize; x1++)
1894 int x = x0 - xhsize + x1;
1896 for (y1 = 0; y1 < ysize; y1++)
1898 int y = y0 - yhsize + y1;
1900 place_extra_bold(y, x);
1901 cave[y][x].info &= (~CAVE_ICKY);
1905 /* add ten random rooms */
1906 for (i = 0; i < 10; i++)
1908 x1 = randint1(xhsize) * 2 + x0 - xhsize;
1909 x2 = randint1(xhsize) * 2 + x0 - xhsize;
1910 y1 = randint1(yhsize) * 2 + y0 - yhsize;
1911 y2 = randint1(yhsize) * 2 + y0 - yhsize;
1912 build_room(x1, x2, y1, y2);
1915 /* Add some random doors */
1916 for (i = 0; i < 500; i++)
1918 x1 = randint1(xsize - 3) - xhsize + x0 + 1;
1919 y1 = randint1(ysize - 3) - yhsize + y0 + 1;
1923 /* Fill with monsters and treasure, high difficulty */
1924 fill_treasure(x0 - xhsize + 1, x0 - xhsize + xsize - 2, y0 - yhsize + 1, y0 - yhsize + ysize - 2, randint1(5) + 5);
1928 /* Create a random vault out of a fractal cave */
1929 static void build_cave_vault(int x0, int y0, int xsiz, int ysiz)
1931 int grd, roug, cutoff, xhsize, yhsize, xsize, ysize, x, y;
1932 bool done, light, room;
1934 /* round to make sizes even */
1940 msg_print_wizard(CHEAT_DUNGEON, _("洞穴ランダムVaultを生成しました。", "Cave Vault."));
1942 light = done = FALSE;
1947 /* testing values for these parameters feel free to adjust */
1948 grd = 1 << randint0(4);
1950 /* want average of about 16 */
1951 roug = randint1(8) * randint1(4);
1954 cutoff = randint1(xsize / 4) + randint1(ysize / 4) +
1955 randint1(xsize / 4) + randint1(ysize / 4);
1958 generate_hmap(y0, x0, xsize, ysize, grd, roug, cutoff);
1960 /* Convert to normal format+ clean up */
1961 done = generate_fracave(y0, x0, xsize, ysize, cutoff, light, room);
1964 /* Set icky flag because is a vault */
1965 for (x = 0; x <= xsize; x++)
1967 for (y = 0; y <= ysize; y++)
1969 cave[y0 - yhsize + y][x0 - xhsize + x].info |= CAVE_ICKY;
1973 /* Fill with monsters and treasure, low difficulty */
1974 fill_treasure(x0 - xhsize + 1, x0 - xhsize + xsize - 1, y0 - yhsize + 1, y0 - yhsize + ysize - 1, randint1(5));
1978 * maze vault -- rectangular labyrinthine rooms
1980 * maze vault uses two routines:
1981 * r_visit - a recursive routine that builds the labyrinth
1982 * build_maze_vault - a driver routine that calls r_visit and adds
1983 * monsters, traps and treasure
1985 * The labyrinth is built by creating a spanning tree of a graph.
1986 * The graph vertices are at
1987 * (x, y) = (2j + x1, 2k + y1) j = 0,...,m-1 k = 0,...,n-1
1988 * and the edges are the vertical and horizontal nearest neighbors.
1990 * The spanning tree is created by performing a suitably randomized
1991 * depth-first traversal of the graph. The only adjustable parameter
1992 * is the randint0(3) below; it governs the relative density of
1993 * twists and turns in the labyrinth: smaller number, more twists.
1995 static void r_visit(int y1, int x1, int y2, int x2,
1996 int node, int dir, int *visited)
1998 int i, j, m, n, temp, x, y, adj[4];
2000 /* dimensions of vertex array */
2001 m = (x2 - x1) / 2 + 1;
2002 n = (y2 - y1) / 2 + 1;
2004 /* mark node visited and set it to a floor */
2006 x = 2 * (node % m) + x1;
2007 y = 2 * (node / m) + y1;
2008 place_floor_bold(y, x);
2010 /* setup order of adjacent node visits */
2013 /* pick a random ordering */
2014 for (i = 0; i < 4; i++)
2016 for (i = 0; i < 4; i++)
2027 /* pick a random ordering with dir first */
2029 for (i = 1; i < 4; i++)
2031 for (i = 1; i < 4; i++)
2033 j = 1 + randint0(3);
2040 for (i = 0; i < 4; i++)
2045 /* (0,+) - check for bottom boundary */
2046 if ((node / m < n - 1) && (visited[node + m] == 0))
2048 place_floor_bold(y + 1, x);
2049 r_visit(y1, x1, y2, x2, node + m, dir, visited);
2053 /* (0,-) - check for top boundary */
2054 if ((node / m > 0) && (visited[node - m] == 0))
2056 place_floor_bold(y - 1, x);
2057 r_visit(y1, x1, y2, x2, node - m, dir, visited);
2061 /* (+,0) - check for right boundary */
2062 if ((node % m < m - 1) && (visited[node + 1] == 0))
2064 place_floor_bold(y, x + 1);
2065 r_visit(y1, x1, y2, x2, node + 1, dir, visited);
2069 /* (-,0) - check for left boundary */
2070 if ((node % m > 0) && (visited[node - 1] == 0))
2072 place_floor_bold(y, x - 1);
2073 r_visit(y1, x1, y2, x2, node - 1, dir, visited);
2080 void build_maze_vault(int x0, int y0, int xsize, int ysize, bool is_vault)
2084 int m, n, num_vertices, *visited;
2088 msg_print_wizard(CHEAT_DUNGEON, _("迷路ランダムVaultを生成しました。", "Maze Vault."));
2090 /* Choose lite or dark */
2091 light = ((dun_level <= randint1(25)) && is_vault && !(d_info[dungeon_type].flags1 & DF1_DARKNESS));
2093 /* Pick a random room size - randomized by calling routine */
2102 /* generate the room */
2103 for (y = y1 - 1; y <= y2 + 1; y++)
2105 for (x = x1 - 1; x <= x2 + 1; x++)
2107 c_ptr = &cave[y][x];
2108 c_ptr->info |= CAVE_ROOM;
2109 if (is_vault) c_ptr->info |= CAVE_ICKY;
2110 if ((x == x1 - 1) || (x == x2 + 1) || (y == y1 - 1) || (y == y2 + 1))
2112 place_outer_grid(c_ptr);
2116 place_extra_grid(c_ptr);
2120 place_inner_grid(c_ptr);
2122 if (light) c_ptr->info |= (CAVE_GLOW);
2126 /* dimensions of vertex array */
2129 num_vertices = m * n;
2131 /* initialize array of visited vertices */
2132 C_MAKE(visited, num_vertices, int);
2134 /* traverse the graph to create a spaning tree, pick a random root */
2135 r_visit(y1, x1, y2, x2, randint0(num_vertices), 0, visited);
2137 /* Fill with monsters and treasure, low difficulty */
2138 if (is_vault) fill_treasure(x1, x2, y1, y2, randint1(5));
2140 C_KILL(visited, num_vertices, int);
2144 /* Build a "mini" checkerboard vault
2146 * This is done by making a permanent wall maze and setting
2147 * the diagonal sqaures of the checker board to be granite.
2148 * The vault has two entrances on opposite sides to guarantee
2149 * a way to get in even if the vault abuts a side of the dungeon.
2151 static void build_mini_c_vault(int x0, int y0, int xsize, int ysize)
2154 int y1, x1, y2, x2, y, x, total;
2155 int m, n, num_vertices;
2158 msg_print_wizard(CHEAT_DUNGEON, _("小型チェッカーランダムVaultを生成しました。", "Mini Checker Board Vault."));
2160 /* Pick a random room size */
2170 /* generate the room */
2171 for (x = x1 - 2; x <= x2 + 2; x++)
2173 if (!in_bounds(y1-2,x)) break;
2175 cave[y1-2][x].info |= (CAVE_ROOM | CAVE_ICKY);
2177 place_outer_noperm_bold(y1-2, x);
2180 for (x = x1 - 2; x <= x2 + 2; x++)
2182 if (!in_bounds(y2+2,x)) break;
2184 cave[y2+2][x].info |= (CAVE_ROOM | CAVE_ICKY);
2186 place_outer_noperm_bold(y2+2, x);
2189 for (y = y1 - 2; y <= y2 + 2; y++)
2191 if (!in_bounds(y,x1-2)) break;
2193 cave[y][x1-2].info |= (CAVE_ROOM | CAVE_ICKY);
2195 place_outer_noperm_bold(y, x1-2);
2198 for (y = y1 - 2; y <= y2 + 2; y++)
2200 if (!in_bounds(y,x2+2)) break;
2202 cave[y][x2+2].info |= (CAVE_ROOM | CAVE_ICKY);
2204 place_outer_noperm_bold(y, x2+2);
2207 for (y = y1 - 1; y <= y2 + 1; y++)
2209 for (x = x1 - 1; x <= x2 + 1; x++)
2211 cave_type *c_ptr = &cave[y][x];
2213 c_ptr->info |= (CAVE_ROOM | CAVE_ICKY);
2215 /* Permanent walls */
2216 place_inner_perm_grid(c_ptr);
2221 /* dimensions of vertex array */
2224 num_vertices = m * n;
2226 /* initialize array of visited vertices */
2227 C_MAKE(visited, num_vertices, int);
2229 /* traverse the graph to create a spannng tree, pick a random root */
2230 r_visit(y1, x1, y2, x2, randint0(num_vertices), 0, visited);
2232 /* Make it look like a checker board vault */
2233 for (x = x1; x <= x2; x++)
2235 for (y = y1; y <= y2; y++)
2237 total = x - x1 + y - y1;
2238 /* If total is odd- and is a floor then make a wall */
2239 if ((total % 2 == 1) && is_floor_bold(y, x))
2241 place_inner_bold(y, x);
2246 /* Make a couple of entrances */
2249 /* left and right */
2250 y = randint1(dy) + dy / 2;
2251 place_inner_bold(y1 + y, x1 - 1);
2252 place_inner_bold(y1 + y, x2 + 1);
2256 /* top and bottom */
2257 x = randint1(dx) + dx / 2;
2258 place_inner_bold(y1 - 1, x1 + x);
2259 place_inner_bold(y2 + 1, x1 + x);
2262 /* Fill with monsters and treasure, highest difficulty */
2263 fill_treasure(x1, x2, y1, y2, 10);
2265 C_KILL(visited, num_vertices, int);
2269 /* Build a town/ castle by using a recursive algorithm.
2270 * Basically divide each region in a probalistic way to create
2271 * smaller regions. When the regions get too small stop.
2273 * The power variable is a measure of how well defended a region is.
2274 * This alters the possible choices.
2276 static void build_recursive_room(int x1, int y1, int x2, int y2, int power)
2282 /* Temp variables */
2288 if ((power < 3) && (xsize > 12) && (ysize > 12))
2290 /* Need outside wall +keep */
2297 /* Make rooms + subdivide */
2298 if ((randint1(10) > 2) && (xsize < 8) && (ysize < 8))
2304 choice = randint1(2) + 1;
2309 /* Mostly subdivide */
2310 choice = randint1(3) + 1;
2314 /* Based on the choice made above, do something */
2322 /* top and bottom */
2323 for (x = x1; x <= x2; x++)
2325 place_outer_bold(y1, x);
2326 place_outer_bold(y2, x);
2329 /* left and right */
2330 for (y = y1 + 1; y < y2; y++)
2332 place_outer_bold(y, x1);
2333 place_outer_bold(y, x2);
2336 /* Make a couple of entrances */
2339 /* left and right */
2340 y = randint1(ysize) + y1;
2341 place_floor_bold(y, x1);
2342 place_floor_bold(y, x2);
2346 /* top and bottom */
2347 x = randint1(xsize) + x1;
2348 place_floor_bold(y1, x);
2349 place_floor_bold(y2, x);
2352 /* Select size of keep */
2353 t1 = randint1(ysize / 3) + y1;
2354 t2 = y2 - randint1(ysize / 3);
2355 t3 = randint1(xsize / 3) + x1;
2356 t4 = x2 - randint1(xsize / 3);
2358 /* Do outside areas */
2360 /* Above and below keep */
2361 build_recursive_room(x1 + 1, y1 + 1, x2 - 1, t1, power + 1);
2362 build_recursive_room(x1 + 1, t2, x2 - 1, y2, power + 1);
2364 /* Left and right of keep */
2365 build_recursive_room(x1 + 1, t1 + 1, t3, t2 - 1, power + 3);
2366 build_recursive_room(t4, t1 + 1, x2 - 1, t2 - 1, power + 3);
2368 /* Make the keep itself: */
2381 /* Try to build a room */
2382 if ((xsize < 3) || (ysize < 3))
2384 for (y = y1; y < y2; y++)
2386 for (x = x1; x < x2; x++)
2388 place_inner_bold(y, x);
2396 /* Make outside walls */
2397 /* top and bottom */
2398 for (x = x1 + 1; x <= x2 - 1; x++)
2400 place_inner_bold(y1 + 1, x);
2401 place_inner_bold(y2 - 1, x);
2404 /* left and right */
2405 for (y = y1 + 1; y <= y2 - 1; y++)
2407 place_inner_bold(y, x1 + 1);
2408 place_inner_bold(y, x2 - 1);
2412 y = randint1(ysize - 3) + y1 + 1;
2417 place_floor_bold(y, x1 + 1);
2422 place_floor_bold(y, x2 - 1);
2425 /* Build the room */
2426 build_recursive_room(x1 + 2, y1 + 2, x2 - 2, y2 - 2, power + 3);
2431 /* Try and divide vertically */
2435 for (y = y1; y < y2; y++)
2437 for (x = x1; x < x2; x++)
2439 place_inner_bold(y, x);
2445 t1 = randint1(xsize - 2) + x1 + 1;
2446 build_recursive_room(x1, y1, t1, y2, power - 2);
2447 build_recursive_room(t1 + 1, y1, x2, y2, power - 2);
2452 /* Try and divide horizontally */
2456 for (y = y1; y < y2; y++)
2458 for (x = x1; x < x2; x++)
2460 place_inner_bold(y, x);
2466 t1 = randint1(ysize - 2) + y1 + 1;
2467 build_recursive_room(x1, y1, x2, t1, power - 2);
2468 build_recursive_room(x1, t1 + 1, x2, y2, power - 2);
2475 /* Build a castle */
2477 /* Driver routine: clear the region and call the recursive
2480 *This makes a vault that looks like a castle/ city in the dungeon.
2482 static void build_castle_vault(int x0, int y0, int xsize, int ysize)
2488 /* Pick a random room size */
2497 msg_print_wizard(CHEAT_DUNGEON, _("城型ランダムVaultを生成しました。", "Castle Vault"));
2499 /* generate the room */
2500 for (y = y1 - 1; y <= y2 + 1; y++)
2502 for (x = x1 - 1; x <= x2 + 1; x++)
2504 cave[y][x].info |= (CAVE_ROOM | CAVE_ICKY);
2505 /* Make everything a floor */
2506 place_floor_bold(y, x);
2510 /* Make the castle */
2511 build_recursive_room(x1, y1, x2, y2, randint1(5));
2513 /* Fill with monsters and treasure, low difficulty */
2514 fill_treasure(x1, x2, y1, y2, randint1(3));
2519 * Add outer wall to a floored region
2520 * Note: no range checking is done so must be inside dungeon
2521 * This routine also stomps on doors
2523 static void add_outer_wall(int x, int y, int light, int x1, int y1, int x2, int y2)
2526 feature_type *f_ptr;
2529 if (!in_bounds(y, x)) return;
2531 c_ptr = &cave[y][x];
2533 /* hack- check to see if square has been visited before
2534 * if so, then exit (use room flag to do this) */
2535 if (c_ptr->info & CAVE_ROOM) return;
2538 c_ptr->info |= CAVE_ROOM;
2540 f_ptr = &f_info[c_ptr->feat];
2542 if (is_floor_bold(y, x))
2544 for (i = -1; i <= 1; i++)
2546 for (j = -1; j <= 1; j++)
2548 if ((x + i >= x1) && (x + i <= x2) &&
2549 (y + j >= y1) && (y + j <= y2))
2551 add_outer_wall(x + i, y + j, light, x1, y1, x2, y2);
2552 if (light) c_ptr->info |= CAVE_GLOW;
2557 else if (is_extra_bold(y, x))
2559 /* Set bounding walls */
2560 place_outer_bold(y, x);
2561 if (light) c_ptr->info |= CAVE_GLOW;
2563 else if (permanent_wall(f_ptr))
2565 /* Set bounding walls */
2566 if (light) c_ptr->info |= CAVE_GLOW;
2572 * Hacked distance formula - gives the 'wrong' answer.
2573 * Used to build crypts
2575 static int dist2(int x1, int y1, int x2, int y2,
2576 int h1, int h2, int h3, int h4)
2582 /* Basically this works by taking the normal pythagorean formula
2583 * and using an expansion to express this in a way without the
2584 * square root. This approximate formula is then perturbed to give
2585 * the distorted results. (I found this by making a mistake when I was
2586 * trying to fix the circular rooms.)
2589 /* h1-h4 are constants that describe the metric */
2590 if (dx >= 2 * dy) return (dx + (dy * h1) / h2);
2591 if (dy >= 2 * dx) return (dy + (dx * h1) / h2);
2592 return (((dx + dy) * 128) / 181 +
2593 (dx * dx / (dy * h3) + dy * dy / (dx * h3)) * h4);
2594 /* 128/181 is approx. 1/sqrt(2) */
2599 * Build target vault.
2600 * This is made by two concentric "crypts" with perpendicular
2601 * walls creating the cross-hairs.
2603 static void build_target_vault(int x0, int y0, int xsize, int ysize)
2607 /* Make a random metric */
2609 h1 = randint1(32) - 16;
2612 h4 = randint1(32) - 16;
2614 msg_print_wizard(CHEAT_DUNGEON, _("対称形ランダムVaultを生成しました。", "Elemental Vault"));
2616 /* work out outer radius */
2627 for (x = x0 - rad; x <= x0 + rad; x++)
2629 for (y = y0 - rad; y <= y0 + rad; y++)
2631 /* clear room flag */
2632 cave[y][x].info &= ~(CAVE_ROOM);
2634 /* Vault - so is "icky" */
2635 cave[y][x].info |= CAVE_ICKY;
2637 if (dist2(y0, x0, y, x, h1, h2, h3, h4) <= rad - 1)
2639 /* inside- so is floor */
2640 place_floor_bold(y, x);
2644 /* make granite outside so arena works */
2645 place_extra_bold(y, x);
2648 /* proper boundary for arena */
2649 if (((y + rad) == y0) || ((y - rad) == y0) ||
2650 ((x + rad) == x0) || ((x - rad) == x0))
2652 place_extra_bold(y, x);
2657 /* Find visible outer walls and set to be FEAT_OUTER */
2658 add_outer_wall(x0, y0, FALSE, x0 - rad - 1, y0 - rad - 1,
2659 x0 + rad + 1, y0 + rad + 1);
2661 /* Add inner wall */
2662 for (x = x0 - rad / 2; x <= x0 + rad / 2; x++)
2664 for (y = y0 - rad / 2; y <= y0 + rad / 2; y++)
2666 if (dist2(y0, x0, y, x, h1, h2, h3, h4) == rad / 2)
2668 /* Make an internal wall */
2669 place_inner_bold(y, x);
2674 /* Add perpendicular walls */
2675 for (x = x0 - rad; x <= x0 + rad; x++)
2677 place_inner_bold(y0, x);
2680 for (y = y0 - rad; y <= y0 + rad; y++)
2682 place_inner_bold(y, x0);
2685 /* Make inner vault */
2686 for (y = y0 - 1; y <= y0 + 1; y++)
2688 place_inner_bold(y, x0 - 1);
2689 place_inner_bold(y, x0 + 1);
2691 for (x = x0 - 1; x <= x0 + 1; x++)
2693 place_inner_bold(y0 - 1, x);
2694 place_inner_bold(y0 + 1, x);
2697 place_floor_bold(y0, x0);
2700 /* Add doors to vault */
2701 /* get two distances so can place doors relative to centre */
2702 x = (rad - 2) / 4 + 1;
2705 add_door(x0 + x, y0);
2706 add_door(x0 + y, y0);
2707 add_door(x0 - x, y0);
2708 add_door(x0 - y, y0);
2709 add_door(x0, y0 + x);
2710 add_door(x0, y0 + y);
2711 add_door(x0, y0 - x);
2712 add_door(x0, y0 - y);
2714 /* Fill with stuff - medium difficulty */
2715 fill_treasure(x0 - rad, x0 + rad, y0 - rad, y0 + rad, randint1(3) + 3);
2719 #ifdef ALLOW_CAVERNS_AND_LAKES
2721 * This routine uses a modified version of the lake code to make a
2722 * distribution of some terrain type over the vault. This type
2723 * depends on the dungeon depth.
2725 * Miniture rooms are then scattered across the vault.
2727 static void build_elemental_vault(int x0, int y0, int xsiz, int ysiz)
2732 int xsize, ysize, xhsize, yhsize, x, y, i;
2735 msg_print_wizard(CHEAT_DUNGEON, _("精霊界ランダムVaultを生成しました。", "Elemental Vault"));
2737 /* round to make sizes even */
2745 /* Earth vault (Rubble) */
2746 type = LAKE_T_EARTH_VAULT;
2748 else if (dun_level < 50)
2750 /* Air vault (Trees) */
2751 type = LAKE_T_AIR_VAULT;
2753 else if (dun_level < 75)
2755 /* Water vault (shallow water) */
2756 type = LAKE_T_WATER_VAULT;
2760 /* Fire vault (shallow lava) */
2761 type = LAKE_T_FIRE_VAULT;
2766 /* testing values for these parameters: feel free to adjust */
2767 grd = 1 << (randint0(3));
2769 /* want average of about 16 */
2770 roug = randint1(8) * randint1(4);
2772 /* Make up size of various componants */
2776 /* Deep water/lava */
2777 c1 = randint0(c3 / 2) + randint0(c3 / 2) - 5;
2779 /* Shallow boundary */
2783 generate_hmap(y0, x0, xsize, ysize, grd, roug, c3);
2785 /* Convert to normal format+ clean up */
2786 done = generate_lake(y0, x0, xsize, ysize, c1, c2, c3, type);
2789 /* Set icky flag because is a vault */
2790 for (x = 0; x <= xsize; x++)
2792 for (y = 0; y <= ysize; y++)
2794 cave[y0 - yhsize + y][x0 - xhsize + x].info |= CAVE_ICKY;
2798 /* make a few rooms in the vault */
2799 for (i = 1; i <= (xsize * ysize) / 50; i++)
2801 build_small_room(x0 + randint0(xsize - 4) - xsize / 2 + 2,
2802 y0 + randint0(ysize - 4) - ysize / 2 + 2);
2805 /* Fill with monsters and treasure, low difficulty */
2806 fill_treasure(x0 - xhsize + 1, x0 - xhsize + xsize - 1,
2807 y0 - yhsize + 1, y0 - yhsize + ysize - 1, randint1(5));
2809 #endif /* ALLOW_CAVERNS_AND_LAKES */
2813 * @brief タイプ10の部屋…ランダム生成vault / Type 10 -- Random vaults
2816 static bool build_type10(void)
2818 POSITION y0, x0, xsize, ysize, vtype;
2821 /* big enough to look good, small enough to be fairly common. */
2822 xsize = randint1(22) + 22;
2823 ysize = randint1(11) + 11;
2825 /* Find and reserve some space in the dungeon. Get center of room. */
2826 if (!find_space(&y0, &x0, ysize + 1, xsize + 1)) return FALSE;
2828 /* Select type of vault */
2829 #ifdef ALLOW_CAVERNS_AND_LAKES
2832 vtype = randint1(15);
2834 while ((d_info[dungeon_type].flags1 & DF1_NO_CAVE) &&
2835 ((vtype == 1) || (vtype == 3) || (vtype == 8) || (vtype == 9) || (vtype == 11)));
2836 #else /* ALLOW_CAVERNS_AND_LAKES */
2839 vtype = randint1(7);
2841 while ((d_info[dungeon_type].flags1 & DF1_NO_CAVE) &&
2842 ((vtype == 1) || (vtype == 3)));
2843 #endif /* ALLOW_CAVERNS_AND_LAKES */
2847 /* Build an appropriate room */
2848 case 1: case 9: build_bubble_vault(x0, y0, xsize, ysize); break;
2849 case 2: case 10: build_room_vault(x0, y0, xsize, ysize); break;
2850 case 3: case 11: build_cave_vault(x0, y0, xsize, ysize); break;
2851 case 4: case 12: build_maze_vault(x0, y0, xsize, ysize, TRUE); break;
2852 case 5: case 13: build_mini_c_vault(x0, y0, xsize, ysize); break;
2853 case 6: case 14: build_castle_vault(x0, y0, xsize, ysize); break;
2854 case 7: case 15: build_target_vault(x0, y0, xsize, ysize); break;
2855 #ifdef ALLOW_CAVERNS_AND_LAKES
2856 case 8: build_elemental_vault(x0, y0, xsize, ysize); break;
2857 #endif /* ALLOW_CAVERNS_AND_LAKES */
2858 /* I know how to add a few more... give me some time. */
2861 default: return FALSE;
2869 * @brief タイプ11の部屋…円形部屋の生成 / Type 11 -- Build an vertical oval room.
2872 * For every grid in the possible square, check the distance.\n
2873 * If it's less than the radius, make it a room square.\n
2875 * When done fill from the inside to find the walls,\n
2877 static bool build_type11(void)
2879 POSITION rad, x, y, x0, y0;
2882 /* Occasional light */
2883 if ((randint1(dun_level) <= 15) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS)) light = TRUE;
2887 /* Find and reserve some space in the dungeon. Get center of room. */
2888 if (!find_space(&y0, &x0, rad * 2 + 1, rad * 2 + 1)) return FALSE;
2890 /* Make circular floor */
2891 for (x = x0 - rad; x <= x0 + rad; x++)
2893 for (y = y0 - rad; y <= y0 + rad; y++)
2895 if (distance(y0, x0, y, x) <= rad - 1)
2897 /* inside- so is floor */
2898 place_floor_bold(y, x);
2900 else if (distance(y0, x0, y, x) <= rad + 1)
2902 /* make granite outside so arena works */
2903 place_extra_bold(y, x);
2908 /* Find visible outer walls and set to be FEAT_OUTER */
2909 add_outer_wall(x0, y0, light, x0 - rad, y0 - rad, x0 + rad, y0 + rad);
2916 * @brief タイプ12の部屋…ドーム型部屋の生成 / Type 12 -- Build crypt room.
2919 * For every grid in the possible square, check the (fake) distance.\n
2920 * If it's less than the radius, make it a room square.\n
2922 * When done fill from the inside to find the walls,\n
2924 static bool build_type12(void)
2926 POSITION rad, x, y, x0, y0;
2928 bool emptyflag = TRUE;
2930 /* Make a random metric */
2932 h1 = randint1(32) - 16;
2935 h4 = randint1(32) - 16;
2937 /* Occasional light */
2938 if ((randint1(dun_level) <= 5) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS)) light = TRUE;
2942 /* Find and reserve some space in the dungeon. Get center of room. */
2943 if (!find_space(&y0, &x0, rad * 2 + 3, rad * 2 + 3)) return FALSE;
2946 for (x = x0 - rad; x <= x0 + rad; x++)
2948 for (y = y0 - rad; y <= y0 + rad; y++)
2950 /* clear room flag */
2951 cave[y][x].info &= ~(CAVE_ROOM);
2953 if (dist2(y0, x0, y, x, h1, h2, h3, h4) <= rad - 1)
2955 /* inside - so is floor */
2956 place_floor_bold(y, x);
2958 else if (distance(y0, x0, y, x) < 3)
2960 place_floor_bold(y, x);
2964 /* make granite outside so arena works */
2965 place_extra_bold(y, x);
2968 /* proper boundary for arena */
2969 if (((y + rad) == y0) || ((y - rad) == y0) ||
2970 ((x + rad) == x0) || ((x - rad) == x0))
2972 place_extra_bold(y, x);
2977 /* Find visible outer walls and set to be FEAT_OUTER */
2978 add_outer_wall(x0, y0, light, x0 - rad - 1, y0 - rad - 1,
2979 x0 + rad + 1, y0 + rad + 1);
2981 /* Check to see if there is room for an inner vault */
2982 for (x = x0 - 2; x <= x0 + 2; x++)
2984 for (y = y0 - 2; y <= y0 + 2; y++)
2986 if (!is_floor_bold(y, x))
2988 /* Wall in the way */
2994 if (emptyflag && one_in_(2))
2996 /* Build the vault */
2997 build_small_room(x0, y0);
2999 /* Place a treasure in the vault */
3000 place_object(y0, x0, 0L);
3002 /* Let's guard the treasure well */
3003 vault_monsters(y0, x0, randint0(2) + 3);
3005 /* Traps naturally */
3006 vault_traps(y0, x0, 4, 4, randint0(3) + 2);
3015 * @brief タイプ14の部屋…特殊トラップ部屋の生成 / Type 14 -- trapped rooms
3018 * A special trap is placed at center of the room
3020 static bool build_type14(void)
3022 POSITION y, x, y2, x2, yval, xval;
3023 POSITION y1, x1, xsize, ysize;
3030 /* Pick a room size */
3036 xsize = x1 + x2 + 1;
3037 ysize = y1 + y2 + 1;
3039 /* Find and reserve some space in the dungeon. Get center of room. */
3040 if (!find_space(&yval, &xval, ysize + 2, xsize + 2)) return FALSE;
3042 /* Choose lite or dark */
3043 light = ((dun_level <= randint1(25)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS));
3046 /* Get corner values */
3047 y1 = yval - ysize / 2;
3048 x1 = xval - xsize / 2;
3049 y2 = yval + (ysize - 1) / 2;
3050 x2 = xval + (xsize - 1) / 2;
3053 /* Place a full floor under the room */
3054 for (y = y1 - 1; y <= y2 + 1; y++)
3056 for (x = x1 - 1; x <= x2 + 1; x++)
3058 c_ptr = &cave[y][x];
3059 place_floor_grid(c_ptr);
3060 c_ptr->info |= (CAVE_ROOM);
3061 if (light) c_ptr->info |= (CAVE_GLOW);
3065 /* Walls around the room */
3066 for (y = y1 - 1; y <= y2 + 1; y++)
3068 c_ptr = &cave[y][x1 - 1];
3069 place_outer_grid(c_ptr);
3070 c_ptr = &cave[y][x2 + 1];
3071 place_outer_grid(c_ptr);
3073 for (x = x1 - 1; x <= x2 + 1; x++)
3075 c_ptr = &cave[y1 - 1][x];
3076 place_outer_grid(c_ptr);
3077 c_ptr = &cave[y2 + 1][x];
3078 place_outer_grid(c_ptr);
3081 if (dun_level < 30 + randint1(30))
3082 trap = feat_trap_piranha;
3084 trap = feat_trap_armageddon;
3086 /* Place a special trap */
3087 c_ptr = &cave[rand_spread(yval, ysize/4)][rand_spread(xval, xsize/4)];
3088 c_ptr->mimic = c_ptr->feat;
3091 msg_format_wizard(CHEAT_DUNGEON, _("%sの部屋が生成されました。", "Room of %s was generated."), f_name + f_info[trap].name);
3098 * Helper function for "glass room"
3100 static bool vault_aux_lite(MONRACE_IDX r_idx)
3102 monster_race *r_ptr = &r_info[r_idx];
3104 /* Validate the monster */
3105 if (!vault_monster_okay(r_idx)) return FALSE;
3107 /* Require lite attack */
3108 if (!(r_ptr->flags4 & RF4_BR_LITE) && !(r_ptr->a_ability_flags1 & RF5_BA_LITE)) return FALSE;
3110 /* No wall passing monsters */
3111 if (r_ptr->flags2 & (RF2_PASS_WALL | RF2_KILL_WALL)) return FALSE;
3113 /* No disintegrating monsters */
3114 if (r_ptr->flags4 & RF4_BR_DISI) return FALSE;
3120 * Helper function for "glass room"
3122 static bool vault_aux_shards(MONRACE_IDX r_idx)
3124 monster_race *r_ptr = &r_info[r_idx];
3126 /* Validate the monster */
3127 if (!vault_monster_okay(r_idx)) return FALSE;
3129 /* Require shards breath attack */
3130 if (!(r_ptr->flags4 & RF4_BR_SHAR)) return FALSE;
3136 * Hack -- determine if a template is potion
3138 static bool kind_is_potion(KIND_OBJECT_IDX k_idx)
3140 return k_info[k_idx].tval == TV_POTION;
3144 * @brief タイプ15の部屋…ガラス部屋の生成 / Type 15 -- glass rooms
3147 static bool build_type15(void)
3149 POSITION y, x, y2, x2, yval, xval;
3150 POSITION y1, x1, xsize, ysize;
3155 /* Pick a room size */
3156 xsize = rand_range(9, 13);
3157 ysize = rand_range(9, 13);
3159 /* Find and reserve some space in the dungeon. Get center of room. */
3160 if (!find_space(&yval, &xval, ysize + 2, xsize + 2)) return FALSE;
3162 /* Choose lite or dark */
3163 light = ((dun_level <= randint1(25)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS));
3165 /* Get corner values */
3166 y1 = yval - ysize / 2;
3167 x1 = xval - xsize / 2;
3168 y2 = yval + (ysize - 1) / 2;
3169 x2 = xval + (xsize - 1) / 2;
3171 /* Place a full floor under the room */
3172 for (y = y1 - 1; y <= y2 + 1; y++)
3174 for (x = x1 - 1; x <= x2 + 1; x++)
3176 c_ptr = &cave[y][x];
3177 place_floor_grid(c_ptr);
3178 c_ptr->feat = feat_glass_floor;
3179 c_ptr->info |= (CAVE_ROOM);
3180 if (light) c_ptr->info |= (CAVE_GLOW);
3184 /* Walls around the room */
3185 for (y = y1 - 1; y <= y2 + 1; y++)
3187 c_ptr = &cave[y][x1 - 1];
3188 place_outer_grid(c_ptr);
3189 c_ptr->feat = feat_glass_wall;
3190 c_ptr = &cave[y][x2 + 1];
3191 place_outer_grid(c_ptr);
3192 c_ptr->feat = feat_glass_wall;
3194 for (x = x1 - 1; x <= x2 + 1; x++)
3196 c_ptr = &cave[y1 - 1][x];
3197 place_outer_grid(c_ptr);
3198 c_ptr->feat = feat_glass_wall;
3199 c_ptr = &cave[y2 + 1][x];
3200 place_outer_grid(c_ptr);
3201 c_ptr->feat = feat_glass_wall;
3204 switch (randint1(3))
3206 case 1: /* 4 lite breathers + potion */
3210 /* Prepare allocation table */
3211 get_mon_num_prep(vault_aux_lite, NULL);
3213 /* Place fixed lite berathers */
3214 for (dir1 = 4; dir1 < 8; dir1++)
3216 MONRACE_IDX r_idx = get_mon_num(dun_level);
3218 y = yval + 2 * ddy_ddd[dir1];
3219 x = xval + 2 * ddx_ddd[dir1];
3220 if (r_idx) place_monster_aux(0, y, x, r_idx, PM_ALLOW_SLEEP);
3222 /* Walls around the breather */
3223 for (dir2 = 0; dir2 < 8; dir2++)
3225 c_ptr = &cave[y + ddy_ddd[dir2]][x + ddx_ddd[dir2]];
3226 place_inner_grid(c_ptr);
3227 c_ptr->feat = feat_glass_wall;
3231 /* Walls around the potion */
3232 for (dir1 = 0; dir1 < 4; dir1++)
3234 y = yval + 2 * ddy_ddd[dir1];
3235 x = xval + 2 * ddx_ddd[dir1];
3236 c_ptr = &cave[y][x];
3237 place_inner_perm_grid(c_ptr);
3238 c_ptr->feat = feat_permanent_glass_wall;
3239 cave[yval + ddy_ddd[dir1]][xval + ddx_ddd[dir1]].info |= (CAVE_ICKY);
3244 y = yval + 2 * ddy_ddd[dir1];
3245 x = xval + 2 * ddx_ddd[dir1];
3246 place_secret_door(y, x, DOOR_GLASS_DOOR);
3247 c_ptr = &cave[y][x];
3248 if (is_closed_door(c_ptr->feat)) c_ptr->mimic = feat_glass_wall;
3250 /* Place a potion */
3251 get_obj_num_hook = kind_is_potion;
3252 place_object(yval, xval, AM_NO_FIXED_ART);
3253 cave[yval][xval].info |= (CAVE_ICKY);
3257 case 2: /* 1 lite breather + random object */
3263 c_ptr = &cave[y1 + 1][x1 + 1];
3264 place_inner_grid(c_ptr);
3265 c_ptr->feat = feat_glass_wall;
3267 c_ptr = &cave[y1 + 1][x2 - 1];
3268 place_inner_grid(c_ptr);
3269 c_ptr->feat = feat_glass_wall;
3271 c_ptr = &cave[y2 - 1][x1 + 1];
3272 place_inner_grid(c_ptr);
3273 c_ptr->feat = feat_glass_wall;
3275 c_ptr = &cave[y2 - 1][x2 - 1];
3276 place_inner_grid(c_ptr);
3277 c_ptr->feat = feat_glass_wall;
3279 /* Prepare allocation table */
3280 get_mon_num_prep(vault_aux_lite, NULL);
3282 r_idx = get_mon_num(dun_level);
3283 if (r_idx) place_monster_aux(0, yval, xval, r_idx, 0L);
3285 /* Walls around the breather */
3286 for (dir1 = 0; dir1 < 8; dir1++)
3288 c_ptr = &cave[yval + ddy_ddd[dir1]][xval + ddx_ddd[dir1]];
3289 place_inner_grid(c_ptr);
3290 c_ptr->feat = feat_glass_wall;
3293 /* Curtains around the breather */
3294 for (y = yval - 1; y <= yval + 1; y++)
3296 place_closed_door(y, xval - 2, DOOR_CURTAIN);
3297 place_closed_door(y, xval + 2, DOOR_CURTAIN);
3299 for (x = xval - 1; x <= xval + 1; x++)
3301 place_closed_door(yval - 2, x, DOOR_CURTAIN);
3302 place_closed_door(yval + 2, x, DOOR_CURTAIN);
3305 /* Place an object */
3306 place_object(yval, xval, AM_NO_FIXED_ART);
3307 cave[yval][xval].info |= (CAVE_ICKY);
3311 case 3: /* 4 shards breathers + 2 potions */
3315 /* Walls around the potion */
3316 for (y = yval - 2; y <= yval + 2; y++)
3318 c_ptr = &cave[y][xval - 3];
3319 place_inner_grid(c_ptr);
3320 c_ptr->feat = feat_glass_wall;
3321 c_ptr = &cave[y][xval + 3];
3322 place_inner_grid(c_ptr);
3323 c_ptr->feat = feat_glass_wall;
3325 for (x = xval - 2; x <= xval + 2; x++)
3327 c_ptr = &cave[yval - 3][x];
3328 place_inner_grid(c_ptr);
3329 c_ptr->feat = feat_glass_wall;
3330 c_ptr = &cave[yval + 3][x];
3331 place_inner_grid(c_ptr);
3332 c_ptr->feat = feat_glass_wall;
3334 for (dir1 = 4; dir1 < 8; dir1++)
3336 c_ptr = &cave[yval + 2 * ddy_ddd[dir1]][xval + 2 * ddx_ddd[dir1]];
3337 place_inner_grid(c_ptr);
3338 c_ptr->feat = feat_glass_wall;
3341 /* Prepare allocation table */
3342 get_mon_num_prep(vault_aux_shards, NULL);
3344 /* Place shard berathers */
3345 for (dir1 = 4; dir1 < 8; dir1++)
3347 MONRACE_IDX r_idx = get_mon_num(dun_level);
3349 y = yval + ddy_ddd[dir1];
3350 x = xval + ddx_ddd[dir1];
3351 if (r_idx) place_monster_aux(0, y, x, r_idx, 0L);
3354 /* Place two potions */
3357 get_obj_num_hook = kind_is_potion;
3358 place_object(yval, xval - 1, AM_NO_FIXED_ART);
3359 get_obj_num_hook = kind_is_potion;
3360 place_object(yval, xval + 1, AM_NO_FIXED_ART);
3364 get_obj_num_hook = kind_is_potion;
3365 place_object(yval - 1, xval, AM_NO_FIXED_ART);
3366 get_obj_num_hook = kind_is_potion;
3367 place_object(yval + 1, xval, AM_NO_FIXED_ART);
3370 for (y = yval - 2; y <= yval + 2; y++)
3371 for (x = xval - 2; x <= xval + 2; x++)
3372 cave[y][x].info |= (CAVE_ICKY);
3378 msg_print_wizard(CHEAT_DUNGEON, _("ガラスの部屋が生成されました。", "Glass room was generated."));
3384 /* Create a new floor room with optional light */
3385 void generate_room_floor(int y1, int x1, int y2, int x2, int light)
3391 for (y = y1; y <= y2; y++)
3393 for (x = x1; x <= x2; x++)
3396 c_ptr = &cave[y][x];
3397 place_floor_grid(c_ptr);
3398 c_ptr->info |= (CAVE_ROOM);
3399 if (light) c_ptr->info |= (CAVE_GLOW);
3404 void generate_fill_perm_bold(int y1, int x1, int y2, int x2)
3408 for (y = y1; y <= y2; y++)
3410 for (x = x1; x <= x2; x++)
3413 place_inner_perm_bold(y, x);
3418 /* Minimum & maximum town size */
3419 #define MIN_TOWN_WID ((MAX_WID / 3) / 2)
3420 #define MIN_TOWN_HGT ((MAX_HGT / 3) / 2)
3421 #define MAX_TOWN_WID ((MAX_WID / 3) * 2 / 3)
3422 #define MAX_TOWN_HGT ((MAX_HGT / 3) * 2 / 3)
3424 /* Struct for build underground buildings */
3427 int y0, x0; /* North-west corner (relative) */
3428 int y1, x1; /* South-east corner (relative) */
3432 ugbldg_type *ugbldg;
3435 * Precalculate buildings' location of underground arcade
3437 static bool precalc_ugarcade(int town_hgt, int town_wid, int n)
3439 int i, y, x, center_y, center_x, tmp, attempt = 10000;
3440 int max_bldg_hgt = 3 * town_hgt / MAX_TOWN_HGT;
3441 int max_bldg_wid = 5 * town_wid / MAX_TOWN_WID;
3442 ugbldg_type *cur_ugbldg;
3443 bool **ugarcade_used, abort;
3445 /* Allocate "ugarcade_used" array (2-dimension) */
3446 C_MAKE(ugarcade_used, town_hgt, bool *);
3447 C_MAKE(*ugarcade_used, town_hgt * town_wid, bool);
3448 for (y = 1; y < town_hgt; y++) ugarcade_used[y] = *ugarcade_used + y * town_wid;
3450 /* Calculate building locations */
3451 for (i = 0; i < n; i++)
3453 cur_ugbldg = &ugbldg[i];
3454 (void)WIPE(cur_ugbldg, ugbldg_type);
3458 /* Find the "center" of the store */
3459 center_y = rand_range(2, town_hgt - 3);
3460 center_x = rand_range(2, town_wid - 3);
3462 /* Determine the store boundaries */
3463 tmp = center_y - randint1(max_bldg_hgt);
3464 cur_ugbldg->y0 = MAX(tmp, 1);
3465 tmp = center_x - randint1(max_bldg_wid);
3466 cur_ugbldg->x0 = MAX(tmp, 1);
3467 tmp = center_y + randint1(max_bldg_hgt);
3468 cur_ugbldg->y1 = MIN(tmp, town_hgt - 2);
3469 tmp = center_x + randint1(max_bldg_wid);
3470 cur_ugbldg->x1 = MIN(tmp, town_wid - 2);
3472 /* Scan this building's area */
3473 for (abort = FALSE, y = cur_ugbldg->y0; (y <= cur_ugbldg->y1) && !abort; y++)
3475 for (x = cur_ugbldg->x0; x <= cur_ugbldg->x1; x++)
3477 if (ugarcade_used[y][x])
3487 while (abort && attempt); /* Accept this building if no overlapping */
3489 /* Failed to generate underground arcade */
3490 if (!attempt) break;
3493 * Mark to ugarcade_used[][] as "used"
3494 * Note: Building-adjacent grids are included for preventing
3495 * connected bulidings.
3497 for (y = cur_ugbldg->y0 - 1; y <= cur_ugbldg->y1 + 1; y++)
3499 for (x = cur_ugbldg->x0 - 1; x <= cur_ugbldg->x1 + 1; x++)
3501 ugarcade_used[y][x] = TRUE;
3506 /* Free "ugarcade_used" array (2-dimension) */
3507 C_KILL(*ugarcade_used, town_hgt * town_wid, bool);
3508 C_KILL(ugarcade_used, town_hgt, bool *);
3510 /* If i < n, generation is not allowed */
3515 * @brief タイプ16の部屋…地下都市生成のサブルーチン / Actually create buildings
3517 * @param ltcy 生成基準Y座標
3518 * @param ltcx 生成基準X座標
3519 * @param stotes[] 生成する店舗のリスト
3522 * Note: ltcy and ltcx indicate "left top corner".
3524 static void build_stores(int ltcy, int ltcx, int stores[], int n)
3528 ugbldg_type *cur_ugbldg;
3530 for (i = 0; i < n; i++)
3532 cur_ugbldg = &ugbldg[i];
3534 /* Generate new room */
3535 generate_room_floor(
3536 ltcy + cur_ugbldg->y0 - 2, ltcx + cur_ugbldg->x0 - 2,
3537 ltcy + cur_ugbldg->y1 + 2, ltcx + cur_ugbldg->x1 + 2,
3541 for (i = 0; i < n; i++)
3543 cur_ugbldg = &ugbldg[i];
3545 /* Build an invulnerable rectangular building */
3546 generate_fill_perm_bold(
3547 ltcy + cur_ugbldg->y0, ltcx + cur_ugbldg->x0,
3548 ltcy + cur_ugbldg->y1, ltcx + cur_ugbldg->x1);
3550 /* Pick a door direction (S,N,E,W) */
3551 switch (randint0(4))
3556 x = rand_range(cur_ugbldg->x0, cur_ugbldg->x1);
3562 x = rand_range(cur_ugbldg->x0, cur_ugbldg->x1);
3567 y = rand_range(cur_ugbldg->y0, cur_ugbldg->y1);
3573 y = rand_range(cur_ugbldg->y0, cur_ugbldg->y1);
3578 for (j = 0; j < max_f_idx; j++)
3580 if (have_flag(f_info[j].flags, FF_STORE))
3582 if (f_info[j].subtype == stores[i]) break;
3586 /* Clear previous contents, add a store door */
3589 cave_set_feat(ltcy + y, ltcx + x, j);
3592 store_init(NO_TOWN, stores[i]);
3599 * @brief タイプ16の部屋…地下都市の生成 / Type 16 -- Underground Arcade
3602 * Town logic flow for generation of new town\n
3603 * Originally from Vanilla 3.0.3\n
3605 * We start with a fully wiped cave of normal floors.\n
3607 * Note that town_gen_hack() plays games with the R.N.G.\n
3609 * This function does NOT do anything about the owners of the stores,\n
3610 * nor the contents thereof. It only handles the physical layout.\n
3612 static bool build_type16(void)
3616 STORE_GENERAL, STORE_ARMOURY, STORE_WEAPON, STORE_TEMPLE,
3617 STORE_ALCHEMIST, STORE_MAGIC, STORE_BLACK, STORE_BOOK,
3619 int n = sizeof stores / sizeof (int);
3620 POSITION i, y, x, y1, x1, yval, xval;
3621 int town_hgt = rand_range(MIN_TOWN_HGT, MAX_TOWN_HGT);
3622 int town_wid = rand_range(MIN_TOWN_WID, MAX_TOWN_WID);
3623 bool prevent_bm = FALSE;
3625 /* Hack -- If already exist black market, prevent building */
3626 for (y = 0; (y < cur_hgt) && !prevent_bm; y++)
3628 for (x = 0; x < cur_wid; x++)
3630 if (cave[y][x].feat == FF_STORE)
3632 prevent_bm = (f_info[cave[y][x].feat].subtype == STORE_BLACK);
3637 for (i = 0; i < n; i++)
3639 if ((stores[i] == STORE_BLACK) && prevent_bm) stores[i] = stores[--n];
3641 if (!n) return FALSE;
3643 /* Allocate buildings array */
3644 C_MAKE(ugbldg, n, ugbldg_type);
3646 /* If cannot build stores, abort */
3647 if (!precalc_ugarcade(town_hgt, town_wid, n))
3649 /* Free buildings array */
3650 C_KILL(ugbldg, n, ugbldg_type);
3654 /* Find and reserve some space in the dungeon. Get center of room. */
3655 if (!find_space(&yval, &xval, town_hgt + 4, town_wid + 4))
3657 /* Free buildings array */
3658 C_KILL(ugbldg, n, ugbldg_type);
3662 /* Get top left corner */
3663 y1 = yval - (town_hgt / 2);
3664 x1 = xval - (town_wid / 2);
3666 /* Generate new room */
3667 generate_room_floor(
3668 y1 + town_hgt / 3, x1 + town_wid / 3,
3669 y1 + town_hgt * 2 / 3, x1 + town_wid * 2 / 3, FALSE);
3672 build_stores(y1, x1, stores, n);
3674 msg_print_wizard(CHEAT_DUNGEON, _("地下街を生成しました", "Underground arcade was generated."));
3676 /* Free buildings array */
3677 C_KILL(ugbldg, n, ugbldg_type);
3684 * @brief 与えられた部屋型IDに応じて部屋の生成処理分岐を行い結果を返す / Attempt to build a room of the given type at the given block
3686 * @note that we restrict the number of "crowded" rooms to reduce the chance of overflowing the monster list during level creation.
3687 * @return 部屋の精製に成功した場合 TRUE を返す。
3689 static bool room_build(int typ)
3694 /* Build an appropriate room */
3695 case ROOM_T_NORMAL: return build_type1();
3696 case ROOM_T_OVERLAP: return build_type2();
3697 case ROOM_T_CROSS: return build_type3();
3698 case ROOM_T_INNER_FEAT: return build_type4();
3699 case ROOM_T_NEST: return build_type5();
3700 case ROOM_T_PIT: return build_type6();
3701 case ROOM_T_LESSER_VAULT: return build_type7();
3702 case ROOM_T_GREATER_VAULT: return build_type8();
3703 case ROOM_T_FRACAVE: return build_type9();
3704 case ROOM_T_RANDOM_VAULT: return build_type10();
3705 case ROOM_T_OVAL: return build_type11();
3706 case ROOM_T_CRYPT: return build_type12();
3707 case ROOM_T_TRAP_PIT: return build_type13();
3708 case ROOM_T_TRAP: return build_type14();
3709 case ROOM_T_GLASS: return build_type15();
3710 case ROOM_T_ARCADE: return build_type16();
3718 * @brief 指定した部屋の生成確率を別の部屋に加算し、指定した部屋の生成率を0にする
3719 * @param dst 確率を移す先の部屋種ID
3720 * @param src 確率を与える元の部屋種ID
3722 #define MOVE_PLIST(dst, src) (prob_list[dst] += prob_list[src], prob_list[src] = 0)
3725 * @brief 部屋生成処理のメインルーチン(Sangbandを経由してOangbandからの実装を引用) / Generate rooms in dungeon. Build bigger rooms at first. [from SAngband (originally from OAngband)]
3726 * @return 部屋生成に成功した場合 TRUE を返す。
3728 bool generate_rooms(void)
3734 int prob_list[ROOM_T_MAX];
3735 int rooms_built = 0;
3736 int area_size = 100 * (cur_hgt*cur_wid) / (MAX_HGT*MAX_WID);
3737 int level_index = MIN(10, div_round(dun_level, 10));
3739 /* Number of each type of room on this level */
3740 s16b room_num[ROOM_T_MAX];
3742 /* Limit number of rooms */
3743 int dun_rooms = DUN_ROOMS_MAX * area_size / 100;
3745 /* Assume normal cave */
3746 room_info_type *room_info_ptr = room_info_normal;
3749 * Initialize probability list.
3751 for (i = 0; i < ROOM_T_MAX; i++)
3753 /* No rooms allowed above their minimum depth. */
3754 if (dun_level < room_info_ptr[i].min_level)
3760 prob_list[i] = room_info_ptr[i].prob[level_index];
3765 * XXX -- Various dungeon types and options.
3768 /*! @details ダンジョンにBEGINNER、CHAMELEON、SMALLESTいずれのフラグもなく、かつ「常に通常でない部屋を生成する」フラグがONならば、GRATER_VAULTのみを生成対象とする。 / Ironman sees only Greater Vaults */
3769 if (ironman_rooms && !((d_info[dungeon_type].flags1 & (DF1_BEGINNER | DF1_CHAMELEON | DF1_SMALLEST))))
3771 for (i = 0; i < ROOM_T_MAX; i++)
3773 if (i == ROOM_T_GREATER_VAULT) prob_list[i] = 1;
3774 else prob_list[i] = 0;
3778 /*! @details ダンジョンにNO_VAULTフラグがあるならば、LESSER_VAULT / GREATER_VAULT/ RANDOM_VAULTを除外 / Forbidden vaults */
3779 else if (d_info[dungeon_type].flags1 & DF1_NO_VAULT)
3781 prob_list[ROOM_T_LESSER_VAULT] = 0;
3782 prob_list[ROOM_T_GREATER_VAULT] = 0;
3783 prob_list[ROOM_T_RANDOM_VAULT] = 0;
3786 /*! @details ダンジョンにNO_CAVEフラグがある場合、FRACAVEの生成枠がNORMALに与えられる。CRIPT、OVALの生成枠がINNER_Fに与えられる。/ NO_CAVE dungeon (Castle)*/
3787 if (d_info[dungeon_type].flags1 & DF1_NO_CAVE)
3789 MOVE_PLIST(ROOM_T_NORMAL, ROOM_T_FRACAVE);
3790 MOVE_PLIST(ROOM_T_INNER_FEAT, ROOM_T_CRYPT);
3791 MOVE_PLIST(ROOM_T_INNER_FEAT, ROOM_T_OVAL);
3794 /*! @details ダンジョンにCAVEフラグがある場合、NORMALの生成枠がFRACAVEに与えられる。/ CAVE dungeon (Orc cave etc.) */
3795 else if (d_info[dungeon_type].flags1 & DF1_CAVE)
3797 MOVE_PLIST(ROOM_T_FRACAVE, ROOM_T_NORMAL);
3800 /*! @details ダンジョンの基本地形が最初から渓谷かアリーナ型の場合 FRACAVE は生成から除外。 / No caves when a (random) cavern exists: they look bad */
3801 else if (dun->cavern || dun->empty_level)
3803 prob_list[ROOM_T_FRACAVE] = 0;
3806 /*! @details ダンジョンに最初からGLASS_ROOMフラグがある場合、GLASS を生成から除外。/ Forbidden glass rooms */
3807 if (!(d_info[dungeon_type].flags1 & DF1_GLASS_ROOM))
3809 prob_list[ROOM_T_GLASS] = 0;
3812 /*! @details ARCADEは同フラグがダンジョンにないと生成されない。 / Forbidden glass rooms */
3813 if (!(d_info[dungeon_type].flags1 & DF1_ARCADE))
3815 prob_list[ROOM_T_ARCADE] = 0;
3819 * Initialize number of rooms,
3820 * And calcurate total probability.
3822 for (total_prob = 0, i = 0; i < ROOM_T_MAX; i++)
3825 total_prob += prob_list[i];
3829 * Prepare the number of rooms, of all types, we should build
3832 for (i = dun_rooms; i > 0; i--)
3835 int rand = randint0(total_prob);
3837 /* Get room_type randomly */
3838 for (room_type = 0; room_type < ROOM_T_MAX; room_type++)
3840 if (rand < prob_list[room_type]) break;
3841 else rand -= prob_list[room_type];
3845 if (room_type >= ROOM_T_MAX) room_type = ROOM_T_NORMAL;
3847 /* Increase the number of rooms of that type we should build. */
3848 room_num[room_type]++;
3854 case ROOM_T_LESSER_VAULT:
3855 case ROOM_T_TRAP_PIT:
3863 case ROOM_T_GREATER_VAULT:
3864 case ROOM_T_RANDOM_VAULT:
3873 * Build each type of room one by one until we cannot build any more.
3874 * [from SAngband (originally from OAngband)]
3878 /* Assume no remaining rooms */
3881 for (i = 0; i < ROOM_T_MAX; i++)
3883 /* What type of room are we building now? */
3884 int room_type = room_build_order[i];
3886 /* Go next if none available */
3887 if (!room_num[room_type]) continue;
3889 /* Use up one unit */
3890 room_num[room_type]--;
3892 /* Build the room. */
3893 if (room_build(room_type))
3895 /* Increase the room built count. */
3898 /* Mark as there was some remaining rooms */
3905 case ROOM_T_TRAP_PIT:
3907 /* Avoid too many monsters */
3910 room_num[ROOM_T_PIT] = 0;
3911 room_num[ROOM_T_NEST] = 0;
3912 room_num[ROOM_T_TRAP_PIT] = 0;
3918 /* Avoid double-town */
3919 room_num[ROOM_T_ARCADE] = 0;
3925 /* End loop if no room remain */
3929 /*! @details 部屋生成数が2未満の場合生成失敗を返す */
3930 if (rooms_built < 2)
3932 msg_format_wizard(CHEAT_DUNGEON, _("部屋数が2未満でした。生成を再試行します。", "Number of rooms was under 2. Retry."), rooms_built);
3936 msg_format_wizard(CHEAT_DUNGEON, _("このダンジョンの部屋数は %d です。", "Number of Rooms: %d"), rooms_built);