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"
49 *[from SAngband (originally from OAngband)]\n
51 * Table of values that control how many times each type of room will\n
52 * appear. Each type of room has its own row, and each column\n
53 * corresponds to dungeon levels 0, 10, 20, and so on. The final\n
54 * value is the minimum depth the room can appear at. -LM-\n
56 * Level 101 and below use the values for level 100.\n
58 * Rooms with lots of monsters or loot may not be generated if the\n
59 * object or monster lists are already nearly full. Rooms will not\n
60 * appear above their minimum depth. Tiny levels will not have space\n
61 * for all the rooms you ask for.\n
63 static room_info_type room_info_normal[ROOM_T_MAX] =
66 /* 0 10 20 30 40 50 60 70 80 90 100 min limit */
68 {{999,900,800,700,600,500,400,300,200,100, 0}, 0}, /*NORMAL */
69 {{ 1, 10, 20, 30, 40, 50, 60, 70, 80, 90,100}, 1}, /*OVERLAP */
70 {{ 1, 10, 20, 30, 40, 50, 60, 70, 80, 90,100}, 3}, /*CROSS */
71 {{ 1, 10, 20, 30, 40, 50, 60, 70, 80, 90,100}, 3}, /*INNER_F */
72 {{ 0, 1, 1, 1, 2, 3, 5, 6, 8, 10, 13}, 10}, /*NEST */
73 {{ 0, 1, 1, 2, 3, 4, 6, 8, 10, 13, 16}, 10}, /*PIT */
74 {{ 0, 1, 1, 1, 2, 2, 3, 5, 6, 8, 10}, 10}, /*LESSER_V */
75 {{ 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 4}, 20}, /*GREATER_V*/
76 {{ 0,100,200,300,400,500,600,700,800,900,999}, 10}, /*FRACAVE */
77 {{ 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2}, 10}, /*RANDOM_V */
78 {{ 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40}, 3}, /*OVAL */
79 {{ 1, 6, 12, 18, 24, 30, 36, 42, 48, 54, 60}, 10}, /*CRYPT */
80 {{ 0, 0, 1, 1, 1, 2, 3, 4, 5, 6, 8}, 20}, /*TRAP_PIT */
81 {{ 0, 0, 1, 1, 1, 2, 3, 4, 5, 6, 8}, 20}, /*TRAP */
82 {{ 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2}, 40}, /*GLASS */
83 {{ 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3}, 1}, /*ARCADE */
87 /*! 部屋の生成処理順 / Build rooms in descending order of difficulty. */
88 static byte room_build_order[ROOM_T_MAX] = {
108 * @brief 鍵のかかったドアを配置する
109 * @param y 配置したいフロアのY座標
110 * @param x 配置したいフロアのX座標
113 void place_locked_door(int y, int x)
115 if (d_info[dungeon_type].flags1 & DF1_NO_DOORS)
117 place_floor_bold(y, x);
121 set_cave_feat(y, x, feat_locked_door_random((d_info[dungeon_type].flags1 & DF1_GLASS_DOOR) ? DOOR_GLASS_DOOR : DOOR_DOOR));
122 cave[y][x].info &= ~(CAVE_FLOOR);
123 delete_monster(y, x);
129 * @param y 配置したいフロアのY座標
130 * @param x 配置したいフロアのX座標
131 * @param type DOOR_DEFAULT / DOOR_DOOR / DOOR_GLASS_DOOR / DOOR_CURTAIN のいずれか
134 void place_secret_door(int y, int x, int type)
136 if (d_info[dungeon_type].flags1 & DF1_NO_DOORS)
138 place_floor_bold(y, x);
142 cave_type *c_ptr = &cave[y][x];
144 if (type == DOOR_DEFAULT)
146 type = ((d_info[dungeon_type].flags1 & DF1_CURTAIN) &&
147 one_in_((d_info[dungeon_type].flags1 & DF1_NO_CAVE) ? 16 : 256)) ? DOOR_CURTAIN :
148 ((d_info[dungeon_type].flags1 & DF1_GLASS_DOOR) ? DOOR_GLASS_DOOR : DOOR_DOOR);
151 /* Create secret door */
152 place_closed_door(y, x, type);
154 if (type != DOOR_CURTAIN)
156 /* Hide by inner wall because this is used in rooms only */
157 c_ptr->mimic = feat_wall_inner;
159 /* Floor type terrain cannot hide a door */
160 if (feat_supports_los(c_ptr->mimic) && !feat_supports_los(c_ptr->feat))
162 if (have_flag(f_info[c_ptr->mimic].flags, FF_MOVE) || have_flag(f_info[c_ptr->mimic].flags, FF_CAN_FLY))
164 c_ptr->feat = one_in_(2) ? c_ptr->mimic : floor_type[randint0(100)];
170 c_ptr->info &= ~(CAVE_FLOOR);
171 delete_monster(y, x);
176 * @brief 1マスだけの部屋を作成し、上下左右いずれか一つに隠しドアを配置する。
177 * @param y0 配置したい中心のY座標
178 * @param x0 配置したい中心のX座標
180 * This funtion makes a very small room centred at (x0, y0)
181 * This is used in crypts, and random elemental vaults.
183 * Note - this should be used only on allocated regions
184 * within another room.
186 static void build_small_room(int x0, int y0)
190 for (y = y0 - 1; y <= y0 + 1; y++)
192 place_inner_bold(y, x0 - 1);
193 place_inner_bold(y, x0 + 1);
196 for (x = x0 - 1; x <= x0 + 1; x++)
198 place_inner_bold(y0 - 1, x);
199 place_inner_bold(y0 + 1, x);
202 /* Place a secret door on one side */
205 case 0: place_secret_door(y0, x0 - 1, DOOR_DEFAULT); break;
206 case 1: place_secret_door(y0, x0 + 1, DOOR_DEFAULT); break;
207 case 2: place_secret_door(y0 - 1, x0, DOOR_DEFAULT); break;
208 case 3: place_secret_door(y0 + 1, x0, DOOR_DEFAULT); break;
211 /* Clear mimic type */
212 cave[y0][x0].mimic = 0;
214 /* Add inner open space */
215 place_floor_bold(y0, x0);
220 * 指定範囲に通路が通っていることを確認した上で床で埋める
221 * This function tunnels around a room if it will cut off part of a cave system.
228 static void check_room_boundary(int x1, int y1, int x2, int y2)
231 bool old_is_floor, new_is_floor;
237 old_is_floor = get_is_floor(x1 - 1, y1);
240 * Count the number of floor-wall boundaries around the room
241 * Note: diagonal squares are ignored since the player can move diagonally
242 * to bypass these if needed.
245 /* Above the top boundary */
246 for (x = x1; x <= x2; x++)
248 new_is_floor = get_is_floor(x, y1 - 1);
250 /* Increment counter if they are different */
251 if (new_is_floor != old_is_floor) count++;
253 old_is_floor = new_is_floor;
257 for (y = y1; y <= y2; y++)
259 new_is_floor = get_is_floor(x2 + 1, y);
261 /* increment counter if they are different */
262 if (new_is_floor != old_is_floor) count++;
264 old_is_floor = new_is_floor;
267 /* Bottom boundary */
268 for (x = x2; x >= x1; x--)
270 new_is_floor = get_is_floor(x, y2 + 1);
272 /* increment counter if they are different */
273 if (new_is_floor != old_is_floor) count++;
275 old_is_floor = new_is_floor;
279 for (y = y2; y >= y1; y--)
281 new_is_floor = get_is_floor(x1 - 1, y);
283 /* increment counter if they are different */
284 if (new_is_floor != old_is_floor) count++;
286 old_is_floor = new_is_floor;
289 /* If all the same, or only one connection exit. */
290 if (count <= 2) return;
293 /* Tunnel around the room so to prevent problems with caves */
294 for (y = y1; y <= y2; y++)
296 for (x = x1; x <= x2; x++)
306 * find_space()の予備処理として部屋の生成が可能かを判定する /
307 * Helper function for find_space(). Is this a good location?
308 * @param blocks_high 範囲の高さ
309 * @param blocks_wide 範囲の幅
310 * @param block_y 範囲の上端
311 * @param block_x 範囲の左端
314 static bool find_space_aux(int blocks_high, int blocks_wide, int block_y, int block_x)
316 int by1, bx1, by2, bx2, by, bx;
318 /* Itty-bitty rooms must shift about within their rectangle */
321 if ((blocks_wide == 2) && (block_x % 3) == 2)
325 /* Rooms with width divisible by 3 must be fitted to a rectangle. */
326 else if ((blocks_wide % 3) == 0)
328 /* Must be aligned to the left edge of a 11x33 rectangle. */
329 if ((block_x % 3) != 0)
334 * Big rooms that do not have a width divisible by 3 must be
335 * aligned towards the edge of the dungeon closest to them.
339 /* Shift towards left edge of dungeon. */
340 if (block_x + (blocks_wide / 2) <= dun->col_rooms / 2)
342 if (((block_x % 3) == 2) && ((blocks_wide % 3) == 2))
344 if ((block_x % 3) == 1)
348 /* Shift toward right edge of dungeon. */
351 if (((block_x % 3) == 2) && ((blocks_wide % 3) == 2))
353 if ((block_x % 3) == 1)
361 by2 = block_y + blocks_high;
362 bx2 = block_x + blocks_wide;
364 /* Never run off the screen */
365 if ((by1 < 0) || (by2 > dun->row_rooms)) return FALSE;
366 if ((bx1 < 0) || (bx2 > dun->col_rooms)) return FALSE;
368 /* Verify available space */
369 for (by = by1; by < by2; by++)
371 for (bx = bx1; bx < bx2; bx++)
373 if (dun->room_map[by][bx])
380 /* This location is okay */
386 * @brief 部屋生成が可能なスペースを確保する / Find a good spot for the next room. -LM-
387 * @param y 部屋の生成が可能な中心Y座標を返す参照ポインタ
388 * @param x 部屋の生成が可能な中心X座標を返す参照ポインタ
389 * @param height 確保したい領域の高さ
390 * @param width 確保したい領域の幅
391 * @return 所定の範囲が確保できた場合TRUEを返す
393 * Find and allocate a free space in the dungeon large enough to hold\n
394 * the room calling this function.\n
396 * We allocate space in 11x11 blocks, but want to make sure that rooms\n
397 * align neatly on the standard screen. Therefore, we make them use\n
398 * blocks in few 11x33 rectangles as possible.\n
400 * Be careful to include the edges of the room in height and width!\n
402 * Return TRUE and values for the center of the room if all went well.\n
403 * Otherwise, return FALSE.\n
405 bool find_space(POSITION *y, POSITION *x, POSITION height, POSITION width)
407 int candidates, pick;
408 int by, bx, by1, bx1, by2, bx2;
409 int block_y = 0, block_x = 0;
412 /* Find out how many blocks we need. */
413 int blocks_high = 1 + ((height - 1) / BLOCK_HGT);
414 int blocks_wide = 1 + ((width - 1) / BLOCK_WID);
416 /* There are no way to allocate such huge space */
417 if (dun->row_rooms < blocks_high) return FALSE;
418 if (dun->col_rooms < blocks_wide) return FALSE;
423 /* Count the number of valid places */
424 for (block_y = dun->row_rooms - blocks_high; block_y >= 0; block_y--)
426 for (block_x = dun->col_rooms - blocks_wide; block_x >= 0; block_x--)
428 if (find_space_aux(blocks_high, blocks_wide, block_y, block_x))
430 /* Find a valid place */
443 if (!(d_info[dungeon_type].flags1 & DF1_NO_CAVE))
445 /* Choose a random one */
446 pick = randint1(candidates);
449 /* NO_CAVE dungeon (Castle) */
452 /* Always choose the center one */
453 pick = candidates/2 + 1;
456 /* Pick up the choosen location */
457 for (block_y = dun->row_rooms - blocks_high; block_y >= 0; block_y--)
459 for (block_x = dun->col_rooms - blocks_wide; block_x >= 0; block_x--)
461 if (find_space_aux(blocks_high, blocks_wide, block_y, block_x))
465 /* This one is picked? */
476 by2 = block_y + blocks_high;
477 bx2 = block_x + blocks_wide;
480 * It is *extremely* important that the following calculation
481 * be *exactly* correct to prevent memory errors
484 /* Acquire the location of the room */
485 (*y) = ((by1 + by2) * BLOCK_HGT) / 2;
486 (*x) = ((bx1 + bx2) * BLOCK_WID) / 2;
488 /* Save the room location */
489 if (dun->cent_n < CENT_MAX)
491 dun->cent[dun->cent_n].y = (byte_hack)*y;
492 dun->cent[dun->cent_n].x = (byte_hack)*x;
496 /* Reserve some blocks. */
497 for (by = by1; by < by2; by++)
499 for (bx = bx1; bx < bx2; bx++)
501 dun->room_map[by][bx] = TRUE;
507 * Hack- See if room will cut off a cavern.
509 * If so, fix by tunneling outside the room in such a
510 * way as to connect the caves.
512 check_room_boundary(*x - width / 2 - 1, *y - height / 2 - 1, *x + (width - 1) / 2 + 1, *y + (height - 1) / 2 + 1);
525 * vaultに配置可能なモンスターの条件を指定するマクロ / Monster validation macro
527 * Line 1 -- forbid town monsters
528 * Line 2 -- forbid uniques
529 * Line 3 -- forbid aquatic monsters
531 #define vault_monster_okay(I) \
532 (mon_hook_dungeon(I) && \
533 !(r_info[I].flags1 & RF1_UNIQUE) && \
534 !(r_info[I].flags7 & RF7_UNIQUE2) && \
535 !(r_info[I].flagsr & RFR_RES_ALL) && \
536 !(r_info[I].flags7 & RF7_AQUATIC))
539 /*! 通常pit生成時のモンスターの構成条件ID / Race index for "monster pit (clone)" */
540 static int vault_aux_race;
542 /*! 単一シンボルpit生成時の指定シンボル / Race index for "monster pit (symbol clone)" */
543 static char vault_aux_char;
545 /*! ブレス属性に基づくドラゴンpit生成時条件マスク / Breath mask for "monster pit (dragon)" */
546 static u32b vault_aux_dragon_mask4;
550 * @brief モンスターがVault生成の最低必要条件を満たしているかを返す /
551 * Helper monster selection function
552 * @param r_idx 確認したいモンスター種族ID
553 * @return Vault生成の最低必要条件を満たしているならTRUEを返す。
555 static bool vault_aux_simple(MONRACE_IDX r_idx)
558 return (vault_monster_okay(r_idx));
563 * @brief モンスターがゼリーnestの生成必要条件を満たしているかを返す /
564 * Helper function for "monster nest (jelly)"
565 * @param r_idx 確認したいモンスター種族ID
566 * @return 生成必要条件を満たしているならTRUEを返す。
568 static bool vault_aux_jelly(MONRACE_IDX r_idx)
570 monster_race *r_ptr = &r_info[r_idx];
572 /* Validate the monster */
573 if (!vault_monster_okay(r_idx)) return (FALSE);
575 if ((r_ptr->flags2 & RF2_KILL_BODY) && !(r_ptr->flags1 & RF1_NEVER_BLOW)) return (FALSE);
577 /* Also decline evil jellies (like death molds and shoggoths) */
578 if (r_ptr->flags3 & (RF3_EVIL)) return (FALSE);
580 /* Require icky thing, jelly, mold, or mushroom */
581 if (!my_strchr("ijm,", r_ptr->d_char)) return (FALSE);
588 * @brief モンスターが動物nestの生成必要条件を満たしているかを返す /
589 * Helper function for "monster nest (animal)"
590 * @param r_idx 確認したいモンスター種族ID
591 * @return 生成必要条件を満たしているならTRUEを返す。
593 static bool vault_aux_animal(MONRACE_IDX r_idx)
595 monster_race *r_ptr = &r_info[r_idx];
597 /* Validate the monster */
598 if (!vault_monster_okay(r_idx)) return (FALSE);
600 /* Require "animal" flag */
601 if (!(r_ptr->flags3 & (RF3_ANIMAL))) return (FALSE);
609 * @brief モンスターがアンデッドnestの生成必要条件を満たしているかを返す /
610 * Helper function for "monster nest (undead)"
611 * @param r_idx 確認したいモンスター種族ID
612 * @return 生成必要条件を満たしているならTRUEを返す。
614 static bool vault_aux_undead(MONRACE_IDX r_idx)
616 monster_race *r_ptr = &r_info[r_idx];
618 /* Validate the monster */
619 if (!vault_monster_okay(r_idx)) return (FALSE);
622 if (!(r_ptr->flags3 & (RF3_UNDEAD))) return (FALSE);
629 * @brief モンスターが聖堂nestの生成必要条件を満たしているかを返す /
630 * Helper function for "monster nest (chapel)"
631 * @param r_idx 確認したいモンスター種族ID
632 * @return 生成必要条件を満たしているならTRUEを返す。
634 static bool vault_aux_chapel_g(MONRACE_IDX r_idx)
636 static int chapel_list[] = {
637 MON_NOV_PRIEST, MON_NOV_PALADIN, MON_NOV_PRIEST_G, MON_NOV_PALADIN_G,
638 MON_PRIEST, MON_JADE_MONK, MON_IVORY_MONK, MON_ULTRA_PALADIN,
639 MON_EBONY_MONK, MON_W_KNIGHT, MON_KNI_TEMPLAR, MON_PALADIN,
644 monster_race *r_ptr = &r_info[r_idx];
646 /* Validate the monster */
647 if (!vault_monster_okay(r_idx)) return (FALSE);
649 if (r_ptr->flags3 & (RF3_EVIL)) return (FALSE);
650 if ((r_idx == MON_A_GOLD) || (r_idx == MON_A_SILVER)) return (FALSE);
652 /* Require "priest" or Angel */
654 if (r_ptr->d_char == 'A') return TRUE;
656 for (i = 0; chapel_list[i]; i++)
657 if (r_idx == chapel_list[i]) return TRUE;
663 * @brief モンスターが犬小屋nestの生成必要条件を満たしているかを返す /
664 * Helper function for "monster nest (kennel)"
665 * @param r_idx 確認したいモンスター種族ID
666 * @return 生成必要条件を満たしているならTRUEを返す。
668 static bool vault_aux_kennel(MONRACE_IDX r_idx)
670 monster_race *r_ptr = &r_info[r_idx];
672 /* Validate the monster */
673 if (!vault_monster_okay(r_idx)) return (FALSE);
675 /* Require a Zephyr Hound or a dog */
676 if (!my_strchr("CZ", r_ptr->d_char)) return (FALSE);
683 * @brief モンスターがミミックnestの生成必要条件を満たしているかを返す /
684 * Helper function for "monster nest (mimic)"
685 * @param r_idx 確認したいモンスター種族ID
686 * @return 生成必要条件を満たしているならTRUEを返す。
688 static bool vault_aux_mimic(MONRACE_IDX r_idx)
690 monster_race *r_ptr = &r_info[r_idx];
692 /* Validate the monster */
693 if (!vault_monster_okay(r_idx)) return (FALSE);
696 if (!my_strchr("!$&(/=?[\\|", r_ptr->d_char)) return (FALSE);
703 * @brief モンスターが単一クローンnestの生成必要条件を満たしているかを返す /
704 * Helper function for "monster nest (clone)"
705 * @param r_idx 確認したいモンスター種族ID
706 * @return 生成必要条件を満たしているならTRUEを返す。
708 static bool vault_aux_clone(MONRACE_IDX r_idx)
710 /* Validate the monster */
711 if (!vault_monster_okay(r_idx)) return (FALSE);
713 return (r_idx == vault_aux_race);
718 * @brief モンスターが邪悪属性シンボルクローンnestの生成必要条件を満たしているかを返す /
719 * Helper function for "monster nest (symbol clone)"
720 * @param r_idx 確認したいモンスター種族ID
721 * @return 生成必要条件を満たしているならTRUEを返す。
723 static bool vault_aux_symbol_e(MONRACE_IDX r_idx)
725 monster_race *r_ptr = &r_info[r_idx];
727 /* Validate the monster */
728 if (!vault_monster_okay(r_idx)) return (FALSE);
730 if ((r_ptr->flags2 & RF2_KILL_BODY) && !(r_ptr->flags1 & RF1_NEVER_BLOW)) return (FALSE);
732 if (r_ptr->flags3 & (RF3_GOOD)) return (FALSE);
734 /* Decline incorrect symbol */
735 if (r_ptr->d_char != vault_aux_char) return (FALSE);
743 * @brief モンスターが善良属性シンボルクローンnestの生成必要条件を満たしているかを返す /
744 * Helper function for "monster nest (symbol clone)"
745 * @param r_idx 確認したいモンスター種族ID
746 * @return 生成必要条件を満たしているならTRUEを返す。
748 static bool vault_aux_symbol_g(MONRACE_IDX r_idx)
750 monster_race *r_ptr = &r_info[r_idx];
752 /* Validate the monster */
753 if (!vault_monster_okay(r_idx)) return (FALSE);
755 if ((r_ptr->flags2 & RF2_KILL_BODY) && !(r_ptr->flags1 & RF1_NEVER_BLOW)) return (FALSE);
757 if (r_ptr->flags3 & (RF3_EVIL)) return (FALSE);
759 /* Decline incorrect symbol */
760 if (r_ptr->d_char != vault_aux_char) return (FALSE);
768 * @brief モンスターがオークpitの生成必要条件を満たしているかを返す /
769 * Helper function for "monster pit (orc)"
770 * @param r_idx 確認したいモンスター種族ID
771 * @return 生成必要条件を満たしているならTRUEを返す。
773 static bool vault_aux_orc(MONRACE_IDX r_idx)
775 monster_race *r_ptr = &r_info[r_idx];
777 /* Validate the monster */
778 if (!vault_monster_okay(r_idx)) return (FALSE);
781 if (!(r_ptr->flags3 & RF3_ORC)) return (FALSE);
784 if (r_ptr->flags3 & RF3_UNDEAD) return (FALSE);
792 * @brief モンスターがトロルpitの生成必要条件を満たしているかを返す /
793 * Helper function for "monster pit (troll)"
794 * @param r_idx 確認したいモンスター種族ID
795 * @return 生成必要条件を満たしているならTRUEを返す。
797 static bool vault_aux_troll(MONRACE_IDX r_idx)
799 monster_race *r_ptr = &r_info[r_idx];
801 /* Validate the monster */
802 if (!vault_monster_okay(r_idx)) return (FALSE);
805 if (!(r_ptr->flags3 & RF3_TROLL)) return (FALSE);
808 if (r_ptr->flags3 & RF3_UNDEAD) return (FALSE);
816 * @brief モンスターが巨人pitの生成必要条件を満たしているかを返す /
817 * Helper function for "monster pit (giant)"
818 * @param r_idx 確認したいモンスター種族ID
819 * @return 生成必要条件を満たしているならTRUEを返す。
821 static bool vault_aux_giant(MONRACE_IDX r_idx)
823 monster_race *r_ptr = &r_info[r_idx];
825 /* Validate the monster */
826 if (!vault_monster_okay(r_idx)) return (FALSE);
829 if (!(r_ptr->flags3 & RF3_GIANT)) return (FALSE);
831 if (r_ptr->flags3 & RF3_GOOD) return (FALSE);
834 if (r_ptr->flags3 & RF3_UNDEAD) return (FALSE);
842 * @brief モンスターがドラゴンpitの生成必要条件を満たしているかを返す /
843 * Helper function for "monster pit (dragon)"
844 * @param r_idx 確認したいモンスター種族ID
845 * @return 生成必要条件を満たしているならTRUEを返す。
847 static bool vault_aux_dragon(MONRACE_IDX r_idx)
849 monster_race *r_ptr = &r_info[r_idx];
851 /* Validate the monster */
852 if (!vault_monster_okay(r_idx)) return (FALSE);
855 if (!(r_ptr->flags3 & RF3_DRAGON)) return (FALSE);
857 /* Hack -- Require correct "breath attack" */
858 if (r_ptr->flags4 != vault_aux_dragon_mask4) return (FALSE);
861 if (r_ptr->flags3 & RF3_UNDEAD) return (FALSE);
869 * @brief モンスターが悪魔pitの生成必要条件を満たしているかを返す /
870 * Helper function for "monster pit (demon)"
871 * @param r_idx 確認したいモンスター種族ID
872 * @return 生成必要条件を満たしているならTRUEを返す。
874 static bool vault_aux_demon(MONRACE_IDX r_idx)
876 monster_race *r_ptr = &r_info[r_idx];
878 /* Validate the monster */
879 if (!vault_monster_okay(r_idx)) return (FALSE);
881 if ((r_ptr->flags2 & RF2_KILL_BODY) && !(r_ptr->flags1 & RF1_NEVER_BLOW)) return (FALSE);
884 if (!(r_ptr->flags3 & RF3_DEMON)) return (FALSE);
892 * @brief モンスターが狂気pitの生成必要条件を満たしているかを返す /
893 * Helper function for "monster pit (lovecraftian)"
894 * @param r_idx 確認したいモンスター種族ID
895 * @return 生成必要条件を満たしているならTRUEを返す。
897 static bool vault_aux_cthulhu(MONRACE_IDX r_idx)
899 monster_race *r_ptr = &r_info[r_idx];
901 /* Validate the monster */
902 if (!vault_monster_okay(r_idx)) return (FALSE);
904 if ((r_ptr->flags2 & RF2_KILL_BODY) && !(r_ptr->flags1 & RF1_NEVER_BLOW)) return (FALSE);
906 /* Require eldritch horror */
907 if (!(r_ptr->flags2 & (RF2_ELDRITCH_HORROR))) return (FALSE);
915 * @brief pit/nestの基準となる単種モンスターを決める /
918 static void vault_prep_clone(void)
920 /* Apply the monster restriction */
921 get_mon_num_prep(vault_aux_simple, NULL);
923 /* Pick a race to clone */
924 vault_aux_race = get_mon_num(dun_level + 10);
926 /* Remove the monster restriction */
927 get_mon_num_prep(NULL, NULL);
932 * @brief pit/nestの基準となるモンスターシンボルを決める /
935 static void vault_prep_symbol(void)
939 /* Apply the monster restriction */
940 get_mon_num_prep(vault_aux_simple, NULL);
942 /* Pick a race to clone */
943 r_idx = get_mon_num(dun_level + 10);
945 /* Remove the monster restriction */
946 get_mon_num_prep(NULL, NULL);
948 /* Extract the symbol */
949 vault_aux_char = r_info[r_idx].d_char;
953 * @brief pit/nestの基準となるドラゴンの種類を決める /
956 static void vault_prep_dragon(void)
958 /* Pick dragon type */
964 /* Restrict dragon breath type */
965 vault_aux_dragon_mask4 = RF4_BR_ACID;
974 /* Restrict dragon breath type */
975 vault_aux_dragon_mask4 = RF4_BR_ELEC;
984 /* Restrict dragon breath type */
985 vault_aux_dragon_mask4 = RF4_BR_FIRE;
994 /* Restrict dragon breath type */
995 vault_aux_dragon_mask4 = RF4_BR_COLD;
1004 /* Restrict dragon breath type */
1005 vault_aux_dragon_mask4 = RF4_BR_POIS;
1014 /* Restrict dragon breath type */
1015 vault_aux_dragon_mask4 = (RF4_BR_ACID | RF4_BR_ELEC |
1016 RF4_BR_FIRE | RF4_BR_COLD |
1027 * @brief モンスターがダークエルフpitの生成必要条件を満たしているかを返す /
1028 * Helper function for "monster pit (dark elf)"
1029 * @param r_idx 確認したいモンスター種族ID
1030 * @return 生成必要条件を満たしているならTRUEを返す。
1032 static bool vault_aux_dark_elf(MONRACE_IDX r_idx)
1035 static int dark_elf_list[] =
1037 MON_D_ELF, MON_D_ELF_MAGE, MON_D_ELF_WARRIOR, MON_D_ELF_PRIEST,
1038 MON_D_ELF_LORD, MON_D_ELF_WARLOCK, MON_D_ELF_DRUID, MON_NIGHTBLADE,
1039 MON_D_ELF_SORC, MON_D_ELF_SHADE, 0,
1042 /* Validate the monster */
1043 if (!vault_monster_okay(r_idx)) return FALSE;
1045 /* Require dark elves */
1046 for (i = 0; dark_elf_list[i]; i++)
1047 if (r_idx == dark_elf_list[i]) return TRUE;
1053 /*! pit/nest型情報のtypedef */
1054 typedef struct vault_aux_type vault_aux_type;
1056 /*! pit/nest型情報の構造体定義 */
1057 struct vault_aux_type
1060 bool (*hook_func)(MONRACE_IDX r_idx);
1061 void (*prep_func)(void);
1067 * @brief ダンジョン毎に指定されたピット配列を基準にランダムなpit/nestタイプを決める
1068 * @param l_ptr 選択されたpit/nest情報を返す参照ポインタ
1069 * @param allow_flag_mask 生成が許されるpit/nestのビット配列
1070 * @return 選択されたpit/nestのID、選択失敗した場合-1を返す。
1072 static int pick_vault_type(vault_aux_type *l_ptr, s16b allow_flag_mask)
1074 int tmp, total, count;
1076 vault_aux_type *n_ptr;
1078 /* Calculate the total possibilities */
1079 for (n_ptr = l_ptr, total = 0, count = 0; TRUE; n_ptr++, count++)
1082 if (!n_ptr->name) break;
1084 /* Ignore excessive depth */
1085 if (n_ptr->level > dun_level) continue;
1087 /* Not matched with pit/nest flag */
1088 if (!(allow_flag_mask & (1L << count))) continue;
1090 /* Count this possibility */
1091 total += n_ptr->chance * MAX_DEPTH / (MIN(dun_level, MAX_DEPTH - 1) - n_ptr->level + 5);
1094 /* Pick a random type */
1095 tmp = randint0(total);
1097 /* Find this type */
1098 for (n_ptr = l_ptr, total = 0, count = 0; TRUE; n_ptr++, count++)
1101 if (!n_ptr->name) break;
1103 /* Ignore excessive depth */
1104 if (n_ptr->level > dun_level) continue;
1106 /* Not matched with pit/nest flag */
1107 if (!(allow_flag_mask & (1L << count))) continue;
1109 /* Count this possibility */
1110 total += n_ptr->chance * MAX_DEPTH / (MIN(dun_level, MAX_DEPTH - 1) - n_ptr->level + 5);
1112 /* Found the type */
1113 if (tmp < total) break;
1116 return n_ptr->name ? count : -1;
1120 static vault_aux_type nest_types[] =
1123 {"クローン", vault_aux_clone, vault_prep_clone, 5, 3},
1124 {"ゼリー", vault_aux_jelly, NULL, 5, 6},
1125 {"シンボル(善)", vault_aux_symbol_g, vault_prep_symbol, 25, 2},
1126 {"シンボル(悪)", vault_aux_symbol_e, vault_prep_symbol, 25, 2},
1127 {"ミミック", vault_aux_mimic, NULL, 30, 4},
1128 {"狂気", vault_aux_cthulhu, NULL, 70, 2},
1129 {"犬小屋", vault_aux_kennel, NULL, 45, 4},
1130 {"動物園", vault_aux_animal, NULL, 35, 5},
1131 {"教会", vault_aux_chapel_g, NULL, 75, 4},
1132 {"アンデッド", vault_aux_undead, NULL, 75, 5},
1133 {NULL, NULL, NULL, 0, 0},
1135 {"clone", vault_aux_clone, vault_prep_clone, 5, 3},
1136 {"jelly", vault_aux_jelly, NULL, 5, 6},
1137 {"symbol good", vault_aux_symbol_g, vault_prep_symbol, 25, 2},
1138 {"symbol evil", vault_aux_symbol_e, vault_prep_symbol, 25, 2},
1139 {"mimic", vault_aux_mimic, NULL, 30, 4},
1140 {"lovecraftian", vault_aux_cthulhu, NULL, 70, 2},
1141 {"kennel", vault_aux_kennel, NULL, 45, 4},
1142 {"animal", vault_aux_animal, NULL, 35, 5},
1143 {"chapel", vault_aux_chapel_g, NULL, 75, 4},
1144 {"undead", vault_aux_undead, NULL, 75, 5},
1145 {NULL, NULL, NULL, 0, 0},
1150 static vault_aux_type pit_types[] =
1153 {"オーク", vault_aux_orc, NULL, 5, 6},
1154 {"トロル", vault_aux_troll, NULL, 20, 6},
1155 {"ジャイアント", vault_aux_giant, NULL, 50, 6},
1156 {"狂気", vault_aux_cthulhu, NULL, 80, 2},
1157 {"シンボル(善)", vault_aux_symbol_g, vault_prep_symbol, 70, 1},
1158 {"シンボル(悪)", vault_aux_symbol_e, vault_prep_symbol, 70, 1},
1159 {"教会", vault_aux_chapel_g, NULL, 65, 2},
1160 {"ドラゴン", vault_aux_dragon, vault_prep_dragon, 70, 6},
1161 {"デーモン", vault_aux_demon, NULL, 80, 6},
1162 {"ダークエルフ", vault_aux_dark_elf, NULL, 45, 4},
1163 {NULL, NULL, NULL, 0, 0},
1165 {"orc", vault_aux_orc, NULL, 5, 6},
1166 {"troll", vault_aux_troll, NULL, 20, 6},
1167 {"giant", vault_aux_giant, NULL, 50, 6},
1168 {"lovecraftian", vault_aux_cthulhu, NULL, 80, 2},
1169 {"symbol good", vault_aux_symbol_g, vault_prep_symbol, 70, 1},
1170 {"symbol evil", vault_aux_symbol_e, vault_prep_symbol, 70, 1},
1171 {"chapel", vault_aux_chapel_g, NULL, 65, 2},
1172 {"dragon", vault_aux_dragon, vault_prep_dragon, 70, 6},
1173 {"demon", vault_aux_demon, NULL, 80, 6},
1174 {"dark elf", vault_aux_dark_elf, NULL, 45, 4},
1175 {NULL, NULL, NULL, 0, 0},
1180 /*! nestのID定義 / Nest types code */
1181 #define NEST_TYPE_CLONE 0
1182 #define NEST_TYPE_JELLY 1
1183 #define NEST_TYPE_SYMBOL_GOOD 2
1184 #define NEST_TYPE_SYMBOL_EVIL 3
1185 #define NEST_TYPE_MIMIC 4
1186 #define NEST_TYPE_LOVECRAFTIAN 5
1187 #define NEST_TYPE_KENNEL 6
1188 #define NEST_TYPE_ANIMAL 7
1189 #define NEST_TYPE_CHAPEL 8
1190 #define NEST_TYPE_UNDEAD 9
1192 /*! pitのID定義 / Pit types code */
1193 #define PIT_TYPE_ORC 0
1194 #define PIT_TYPE_TROLL 1
1195 #define PIT_TYPE_GIANT 2
1196 #define PIT_TYPE_LOVECRAFTIAN 3
1197 #define PIT_TYPE_SYMBOL_GOOD 4
1198 #define PIT_TYPE_SYMBOL_EVIL 5
1199 #define PIT_TYPE_CHAPEL 6
1200 #define PIT_TYPE_DRAGON 7
1201 #define PIT_TYPE_DEMON 8
1202 #define PIT_TYPE_DARK_ELF 9
1206 * @brief デバッグ時に生成されたpit/nestの型を出力する処理
1207 * @param type pit/nestの型ID
1208 * @param nest TRUEならばnest、FALSEならばpit
1209 * @return デバッグ表示文字列の参照ポインタ
1211 * Hack -- Get the string describing subtype of pit/nest
1212 * Determined in prepare function (some pit/nest only)
1214 static cptr pit_subtype_string(int type, bool nest)
1216 static char inner_buf[256] = "";
1218 inner_buf[0] = '\0'; /* Init string */
1220 if (nest) /* Nests */
1224 case NEST_TYPE_CLONE:
1225 sprintf(inner_buf, "(%s)", r_name + r_info[vault_aux_race].name);
1227 case NEST_TYPE_SYMBOL_GOOD:
1228 case NEST_TYPE_SYMBOL_EVIL:
1229 sprintf(inner_buf, "(%c)", vault_aux_char);
1237 case PIT_TYPE_SYMBOL_GOOD:
1238 case PIT_TYPE_SYMBOL_EVIL:
1239 sprintf(inner_buf, "(%c)", vault_aux_char);
1241 case PIT_TYPE_DRAGON:
1242 switch (vault_aux_dragon_mask4)
1245 case RF4_BR_ACID: strcpy(inner_buf, "(酸)"); break;
1246 case RF4_BR_ELEC: strcpy(inner_buf, "(稲妻)"); break;
1247 case RF4_BR_FIRE: strcpy(inner_buf, "(火炎)"); break;
1248 case RF4_BR_COLD: strcpy(inner_buf, "(冷気)"); break;
1249 case RF4_BR_POIS: strcpy(inner_buf, "(毒)"); break;
1250 case (RF4_BR_ACID | RF4_BR_ELEC | RF4_BR_FIRE | RF4_BR_COLD | RF4_BR_POIS):
1251 strcpy(inner_buf, "(万色)"); break;
1252 default: strcpy(inner_buf, "(未定義)"); break;
1254 case RF4_BR_ACID: strcpy(inner_buf, "(acid)"); break;
1255 case RF4_BR_ELEC: strcpy(inner_buf, "(lightning)"); break;
1256 case RF4_BR_FIRE: strcpy(inner_buf, "(fire)"); break;
1257 case RF4_BR_COLD: strcpy(inner_buf, "(frost)"); break;
1258 case RF4_BR_POIS: strcpy(inner_buf, "(poison)"); break;
1259 case (RF4_BR_ACID | RF4_BR_ELEC | RF4_BR_FIRE | RF4_BR_COLD | RF4_BR_POIS):
1260 strcpy(inner_buf, "(multi-hued)"); break;
1261 default: strcpy(inner_buf, "(undefined)"); break;
1272 /*! デバッグ時にnestのモンスター情報を確認するための構造体 / A struct for nest monster information with cheat_hear */
1282 *! @brief nestのモンスターリストをソートするための関数 /
1283 * Comp function for sorting nest monster information
1284 * @param u ソート処理対象配列ポインタ
1286 * @param a 比較対象参照ID1
1287 * @param b 比較対象参照ID2
1289 static bool ang_sort_comp_nest_mon_info(vptr u, vptr v, int a, int b)
1291 nest_mon_info_type *nest_mon_info = (nest_mon_info_type *)u;
1292 int w1 = nest_mon_info[a].r_idx;
1293 int w2 = nest_mon_info[b].r_idx;
1294 monster_race *r1_ptr = &r_info[w1];
1295 monster_race *r2_ptr = &r_info[w2];
1301 /* Extract used info */
1302 z1 = nest_mon_info[a].used;
1303 z2 = nest_mon_info[b].used;
1305 /* Compare used status */
1306 if (z1 < z2) return FALSE;
1307 if (z1 > z2) return TRUE;
1309 /* Compare levels */
1310 if (r1_ptr->level < r2_ptr->level) return TRUE;
1311 if (r1_ptr->level > r2_ptr->level) return FALSE;
1313 /* Compare experience */
1314 if (r1_ptr->mexp < r2_ptr->mexp) return TRUE;
1315 if (r1_ptr->mexp > r2_ptr->mexp) return FALSE;
1317 /* Compare indexes */
1322 * @brief nestのモンスターリストをスワップするための関数 /
1323 * Swap function for sorting nest monster information
1324 * @param u スワップ処理対象配列ポインタ
1326 * @param a スワップ対象参照ID1
1327 * @param b スワップ対象参照ID2
1329 static void ang_sort_swap_nest_mon_info(vptr u, vptr v, int a, int b)
1331 nest_mon_info_type *nest_mon_info = (nest_mon_info_type *)u;
1332 nest_mon_info_type holder;
1338 holder = nest_mon_info[a];
1339 nest_mon_info[a] = nest_mon_info[b];
1340 nest_mon_info[b] = holder;
1344 #define NUM_NEST_MON_TYPE 64 /*!<nestの種別数 */
1348 * @brief タイプ5の部屋…nestを生成する / Type 5 -- Monster nests
1351 * A monster nest is a "big" room, with an "inner" room, containing\n
1352 * a "collection" of monsters of a given type strewn about the room.\n
1354 * The monsters are chosen from a set of 64 randomly selected monster\n
1355 * races, to allow the nest creation to fail instead of having "holes".\n
1357 * Note the use of the "get_mon_num_prep()" function, and the special\n
1358 * "get_mon_num_hook()" restriction function, to prepare the "monster\n
1359 * allocation table" in such a way as to optimize the selection of\n
1360 * "appropriate" non-unique monsters for the nest.\n
1362 * Note that the "get_mon_num()" function may (rarely) fail, in which\n
1363 * case the nest will be empty.\n
1365 * Note that "monster nests" will never contain "unique" monsters.\n
1367 static bool build_type5(void)
1369 POSITION y, x, y1, x1, y2, x2, xval, yval;
1371 nest_mon_info_type nest_mon_info[NUM_NEST_MON_TYPE];
1377 int cur_nest_type = pick_vault_type(nest_types, d_info[dungeon_type].nest);
1378 vault_aux_type *n_ptr;
1380 /* No type available */
1381 if (cur_nest_type < 0) return FALSE;
1383 n_ptr = &nest_types[cur_nest_type];
1385 /* Process a preparation function if necessary */
1386 if (n_ptr->prep_func) (*(n_ptr->prep_func))();
1388 /* Prepare allocation table */
1389 get_mon_num_prep(n_ptr->hook_func, NULL);
1391 align.sub_align = SUB_ALIGN_NEUTRAL;
1393 /* Pick some monster types */
1394 for (i = 0; i < NUM_NEST_MON_TYPE; i++)
1396 MONRACE_IDX r_idx = 0;
1398 monster_race *r_ptr = NULL;
1402 /* Get a (hard) monster type */
1403 r_idx = get_mon_num(dun_level + 11);
1404 r_ptr = &r_info[r_idx];
1406 /* Decline incorrect alignment */
1407 if (monster_has_hostile_align(&align, 0, 0, r_ptr)) continue;
1409 /* Accept this monster */
1413 /* Notice failure */
1414 if (!r_idx || !attempts) return FALSE;
1416 /* Note the alignment */
1417 if (r_ptr->flags3 & RF3_EVIL) align.sub_align |= SUB_ALIGN_EVIL;
1418 if (r_ptr->flags3 & RF3_GOOD) align.sub_align |= SUB_ALIGN_GOOD;
1420 nest_mon_info[i].r_idx = (s16b)r_idx;
1421 nest_mon_info[i].used = FALSE;
1424 /* Find and reserve some space in the dungeon. Get center of room. */
1425 if (!find_space(&yval, &xval, 11, 25)) return FALSE;
1433 /* Place the floor area */
1434 for (y = y1 - 1; y <= y2 + 1; y++)
1436 for (x = x1 - 1; x <= x2 + 1; x++)
1438 c_ptr = &cave[y][x];
1439 place_floor_grid(c_ptr);
1440 c_ptr->info |= (CAVE_ROOM);
1444 /* Place the outer walls */
1445 for (y = y1 - 1; y <= y2 + 1; y++)
1447 c_ptr = &cave[y][x1 - 1];
1448 place_outer_grid(c_ptr);
1449 c_ptr = &cave[y][x2 + 1];
1450 place_outer_grid(c_ptr);
1452 for (x = x1 - 1; x <= x2 + 1; x++)
1454 c_ptr = &cave[y1 - 1][x];
1455 place_outer_grid(c_ptr);
1456 c_ptr = &cave[y2 + 1][x];
1457 place_outer_grid(c_ptr);
1461 /* Advance to the center room */
1467 /* The inner walls */
1468 for (y = y1 - 1; y <= y2 + 1; y++)
1470 c_ptr = &cave[y][x1 - 1];
1471 place_inner_grid(c_ptr);
1472 c_ptr = &cave[y][x2 + 1];
1473 place_inner_grid(c_ptr);
1476 for (x = x1 - 1; x <= x2 + 1; x++)
1478 c_ptr = &cave[y1 - 1][x];
1479 place_inner_grid(c_ptr);
1480 c_ptr = &cave[y2 + 1][x];
1481 place_inner_grid(c_ptr);
1483 for (y = y1; y <= y2; y++)
1485 for (x = x1; x <= x2; x++)
1487 add_cave_info(y, x, CAVE_ICKY);
1491 /* Place a secret door */
1492 switch (randint1(4))
1494 case 1: place_secret_door(y1 - 1, xval, DOOR_DEFAULT); break;
1495 case 2: place_secret_door(y2 + 1, xval, DOOR_DEFAULT); break;
1496 case 3: place_secret_door(yval, x1 - 1, DOOR_DEFAULT); break;
1497 case 4: place_secret_door(yval, x2 + 1, DOOR_DEFAULT); break;
1500 msg_format_wizard(CHEAT_DUNGEON, _("モンスター部屋(nest)(%s%s)を生成します。", "Monster nest (%s%s)"), n_ptr->name, pit_subtype_string(cur_nest_type, TRUE));
1502 /* Place some monsters */
1503 for (y = yval - 2; y <= yval + 2; y++)
1505 for (x = xval - 9; x <= xval + 9; x++)
1509 i = randint0(NUM_NEST_MON_TYPE);
1510 r_idx = nest_mon_info[i].r_idx;
1512 /* Place that "random" monster (no groups) */
1513 (void)place_monster_aux(0, y, x, r_idx, 0L);
1515 nest_mon_info[i].used = TRUE;
1521 ang_sort_comp = ang_sort_comp_nest_mon_info;
1522 ang_sort_swap = ang_sort_swap_nest_mon_info;
1523 ang_sort(nest_mon_info, NULL, NUM_NEST_MON_TYPE);
1525 /* Dump the entries (prevent multi-printing) */
1526 for (i = 0; i < NUM_NEST_MON_TYPE; i++)
1528 if (!nest_mon_info[i].used) break;
1529 for (; i < NUM_NEST_MON_TYPE - 1; i++)
1531 if (nest_mon_info[i].r_idx != nest_mon_info[i + 1].r_idx) break;
1532 if (!nest_mon_info[i + 1].used) break;
1534 msg_format_wizard(CHEAT_DUNGEON, "Nest構成モンスターNo.%d:%s", i, r_name + r_info[nest_mon_info[i].r_idx].name);
1543 * @brief タイプ6の部屋…pitを生成する / Type 6 -- Monster pits
1546 * A monster pit is a "big" room, with an "inner" room, containing\n
1547 * a "collection" of monsters of a given type organized in the room.\n
1549 * The inside room in a monster pit appears as shown below, where the\n
1550 * actual monsters in each location depend on the type of the pit\n
1552 * XXXXXXXXXXXXXXXXXXXXX\n
1553 * X0000000000000000000X\n
1554 * X0112233455543322110X\n
1555 * X0112233467643322110X\n
1556 * X0112233455543322110X\n
1557 * X0000000000000000000X\n
1558 * XXXXXXXXXXXXXXXXXXXXX\n
1560 * Note that the monsters in the pit are now chosen by using "get_mon_num()"\n
1561 * to request 16 "appropriate" monsters, sorting them by level, and using\n
1562 * the "even" entries in this sorted list for the contents of the pit.\n
1564 * Hack -- all of the "dragons" in a "dragon" pit must be the same "color",\n
1565 * which is handled by requiring a specific "breath" attack for all of the\n
1566 * dragons. This may include "multi-hued" breath. Note that "wyrms" may\n
1567 * be present in many of the dragon pits, if they have the proper breath.\n
1569 * Note the use of the "get_mon_num_prep()" function, and the special\n
1570 * "get_mon_num_hook()" restriction function, to prepare the "monster\n
1571 * allocation table" in such a way as to optimize the selection of\n
1572 * "appropriate" non-unique monsters for the pit.\n
1574 * Note that the "get_mon_num()" function may (rarely) fail, in which case\n
1575 * the pit will be empty.\n
1577 * Note that "monster pits" will never contain "unique" monsters.\n
1579 static bool build_type6(void)
1581 POSITION y, x, y1, x1, y2, x2, xval, yval;
1584 MONRACE_IDX what[16];
1590 int cur_pit_type = pick_vault_type(pit_types, d_info[dungeon_type].pit);
1591 vault_aux_type *n_ptr;
1593 /* No type available */
1594 if (cur_pit_type < 0) return FALSE;
1596 n_ptr = &pit_types[cur_pit_type];
1598 /* Process a preparation function if necessary */
1599 if (n_ptr->prep_func) (*(n_ptr->prep_func))();
1601 /* Prepare allocation table */
1602 get_mon_num_prep(n_ptr->hook_func, NULL);
1604 align.sub_align = SUB_ALIGN_NEUTRAL;
1606 /* Pick some monster types */
1607 for (i = 0; i < 16; i++)
1609 MONRACE_IDX r_idx = 0;
1611 monster_race *r_ptr = NULL;
1615 /* Get a (hard) monster type */
1616 r_idx = get_mon_num(dun_level + 11);
1617 r_ptr = &r_info[r_idx];
1619 /* Decline incorrect alignment */
1620 if (monster_has_hostile_align(&align, 0, 0, r_ptr)) continue;
1622 /* Accept this monster */
1626 /* Notice failure */
1627 if (!r_idx || !attempts) return FALSE;
1629 /* Note the alignment */
1630 if (r_ptr->flags3 & RF3_EVIL) align.sub_align |= SUB_ALIGN_EVIL;
1631 if (r_ptr->flags3 & RF3_GOOD) align.sub_align |= SUB_ALIGN_GOOD;
1636 /* Find and reserve some space in the dungeon. Get center of room. */
1637 if (!find_space(&yval, &xval, 11, 25)) return FALSE;
1645 /* Place the floor area */
1646 for (y = y1 - 1; y <= y2 + 1; y++)
1648 for (x = x1 - 1; x <= x2 + 1; x++)
1650 c_ptr = &cave[y][x];
1651 place_floor_grid(c_ptr);
1652 c_ptr->info |= (CAVE_ROOM);
1656 /* Place the outer walls */
1657 for (y = y1 - 1; y <= y2 + 1; y++)
1659 c_ptr = &cave[y][x1 - 1];
1660 place_outer_grid(c_ptr);
1661 c_ptr = &cave[y][x2 + 1];
1662 place_outer_grid(c_ptr);
1664 for (x = x1 - 1; x <= x2 + 1; x++)
1666 c_ptr = &cave[y1 - 1][x];
1667 place_outer_grid(c_ptr);
1668 c_ptr = &cave[y2 + 1][x];
1669 place_outer_grid(c_ptr);
1672 /* Advance to the center room */
1678 /* The inner walls */
1679 for (y = y1 - 1; y <= y2 + 1; y++)
1681 c_ptr = &cave[y][x1 - 1];
1682 place_inner_grid(c_ptr);
1683 c_ptr = &cave[y][x2 + 1];
1684 place_inner_grid(c_ptr);
1686 for (x = x1 - 1; x <= x2 + 1; x++)
1688 c_ptr = &cave[y1 - 1][x];
1689 place_inner_grid(c_ptr);
1690 c_ptr = &cave[y2 + 1][x];
1691 place_inner_grid(c_ptr);
1693 for (y = y1; y <= y2; y++)
1695 for (x = x1; x <= x2; x++)
1697 add_cave_info(y, x, CAVE_ICKY);
1701 /* Place a secret door */
1702 switch (randint1(4))
1704 case 1: place_secret_door(y1 - 1, xval, DOOR_DEFAULT); break;
1705 case 2: place_secret_door(y2 + 1, xval, DOOR_DEFAULT); break;
1706 case 3: place_secret_door(yval, x1 - 1, DOOR_DEFAULT); break;
1707 case 4: place_secret_door(yval, x2 + 1, DOOR_DEFAULT); break;
1710 /* Sort the entries */
1711 for (i = 0; i < 16 - 1; i++)
1713 /* Sort the entries */
1714 for (j = 0; j < 16 - 1; j++)
1719 int p1 = r_info[what[i1]].level;
1720 int p2 = r_info[what[i2]].level;
1725 MONRACE_IDX tmp = what[i1];
1726 what[i1] = what[i2];
1732 msg_format_wizard(CHEAT_DUNGEON, _("モンスター部屋(pit)(%s%s)を生成します。", "Monster pit (%s%s)"), n_ptr->name, pit_subtype_string(cur_pit_type, FALSE));
1734 /* Select the entries */
1735 for (i = 0; i < 8; i++)
1737 /* Every other entry */
1738 what[i] = what[i * 2];
1739 msg_format_wizard(CHEAT_DUNGEON, _("Nest構成モンスター選択No.%d:%s", "Nest Monster Select No.%d:%s"), i, r_name + r_info[what[i]].name);
1742 /* Top and bottom rows */
1743 for (x = xval - 9; x <= xval + 9; x++)
1745 place_monster_aux(0, yval - 2, x, what[0], PM_NO_KAGE);
1746 place_monster_aux(0, yval + 2, x, what[0], PM_NO_KAGE);
1749 /* Middle columns */
1750 for (y = yval - 1; y <= yval + 1; y++)
1752 place_monster_aux(0, y, xval - 9, what[0], PM_NO_KAGE);
1753 place_monster_aux(0, y, xval + 9, what[0], PM_NO_KAGE);
1755 place_monster_aux(0, y, xval - 8, what[1], PM_NO_KAGE);
1756 place_monster_aux(0, y, xval + 8, what[1], PM_NO_KAGE);
1758 place_monster_aux(0, y, xval - 7, what[1], PM_NO_KAGE);
1759 place_monster_aux(0, y, xval + 7, what[1], PM_NO_KAGE);
1761 place_monster_aux(0, y, xval - 6, what[2], PM_NO_KAGE);
1762 place_monster_aux(0, y, xval + 6, what[2], PM_NO_KAGE);
1764 place_monster_aux(0, y, xval - 5, what[2], PM_NO_KAGE);
1765 place_monster_aux(0, y, xval + 5, what[2], PM_NO_KAGE);
1767 place_monster_aux(0, y, xval - 4, what[3], PM_NO_KAGE);
1768 place_monster_aux(0, y, xval + 4, what[3], PM_NO_KAGE);
1770 place_monster_aux(0, y, xval - 3, what[3], PM_NO_KAGE);
1771 place_monster_aux(0, y, xval + 3, what[3], PM_NO_KAGE);
1773 place_monster_aux(0, y, xval - 2, what[4], PM_NO_KAGE);
1774 place_monster_aux(0, y, xval + 2, what[4], PM_NO_KAGE);
1777 /* Above/Below the center monster */
1778 for (x = xval - 1; x <= xval + 1; x++)
1780 place_monster_aux(0, yval + 1, x, what[5], PM_NO_KAGE);
1781 place_monster_aux(0, yval - 1, x, what[5], PM_NO_KAGE);
1784 /* Next to the center monster */
1785 place_monster_aux(0, yval, xval + 1, what[6], PM_NO_KAGE);
1786 place_monster_aux(0, yval, xval - 1, what[6], PM_NO_KAGE);
1788 /* Center monster */
1789 place_monster_aux(0, yval, xval, what[7], PM_NO_KAGE);
1796 * @brief Vault地形を回転、上下左右反転するための座標変換を返す / coordinate translation code
1797 * @param x 変換したい点のX座標参照ポインタ
1798 * @param y 変換したい点のY座標参照ポインタ
1799 * @param xoffset Vault生成時の基準X座標
1800 * @param yoffset Vault生成時の基準Y座標
1801 * @param transno 処理ID
1804 static void coord_trans(POSITION *x, POSITION *y, POSITION xoffset, POSITION yoffset, int transno)
1810 * transno specifies what transformation is required. (0-7)
1811 * The lower two bits indicate by how much the vault is rotated,
1812 * and the upper bit indicates a reflection.
1813 * This is done by using rotation matrices... however since
1814 * these are mostly zeros for rotations by 90 degrees this can
1815 * be expressed simply in terms of swapping and inverting the
1816 * x and y coordinates.
1818 for (i = 0; i < transno % 4; i++)
1820 /* rotate by 90 degrees */
1828 /* Reflect depending on status of 3rd bit. */
1832 /* Add offsets so vault stays in the first quadrant */
1838 * @brief Vaultをフロアに配置する / Hack -- fill in "vault" rooms
1839 * @param yval 生成基準Y座標
1840 * @param xval 生成基準X座標
1841 * @param ymax VaultのYサイズ
1842 * @param xmax VaultのXサイズ
1843 * @param data Vaultのデータ文字列
1844 * @param xoffset 変換基準X座標
1845 * @param yoffset 変換基準Y座標
1846 * @param transno 変換ID
1849 static void build_vault(POSITION yval, POSITION xval, POSITION ymax, POSITION xmax, cptr data,
1850 POSITION xoffset, POSITION yoffset, int transno)
1852 POSITION dx, dy, x, y, i, j;
1856 /* Place dungeon features and objects */
1857 for (t = data, dy = 0; dy < ymax; dy++)
1859 for (dx = 0; dx < xmax; dx++, t++)
1861 /* prevent loop counter from being overwritten */
1866 coord_trans(&i, &j, xoffset, yoffset, transno);
1868 /* Extract the location */
1869 if (transno % 2 == 0)
1871 /* no swap of x/y */
1872 x = xval - (xmax / 2) + i;
1873 y = yval - (ymax / 2) + j;
1878 x = xval - (ymax / 2) + i;
1879 y = yval - (xmax / 2) + j;
1882 /* Hack -- skip "non-grids" */
1883 if (*t == ' ') continue;
1885 /* Access the grid */
1886 c_ptr = &cave[y][x];
1888 /* Lay down a floor */
1889 place_floor_grid(c_ptr);
1891 /* Remove any mimic */
1894 /* Part of a vault */
1895 c_ptr->info |= (CAVE_ROOM | CAVE_ICKY);
1897 /* Analyze the grid */
1900 /* Granite wall (outer) */
1902 place_outer_noperm_grid(c_ptr);
1905 /* Granite wall (inner) */
1907 place_inner_grid(c_ptr);
1910 /* Glass wall (inner) */
1912 place_inner_grid(c_ptr);
1913 c_ptr->feat = feat_glass_wall;
1916 /* Permanent wall (inner) */
1918 place_inner_perm_grid(c_ptr);
1921 /* Permanent glass wall (inner) */
1923 place_inner_perm_grid(c_ptr);
1924 c_ptr->feat = feat_permanent_glass_wall;
1929 if (randint0(100) < 75)
1931 place_object(y, x, 0L);
1941 place_secret_door(y, x, DOOR_DEFAULT);
1944 /* Secret glass doors */
1946 place_secret_door(y, x, DOOR_GLASS_DOOR);
1947 if (is_closed_door(c_ptr->feat)) c_ptr->mimic = feat_glass_wall;
1952 place_secret_door(y, x, DOOR_CURTAIN);
1960 /* Black market in a dungeon */
1962 set_cave_feat(y, x, feat_black_market);
1963 store_init(NO_TOWN, STORE_BLACK);
1968 set_cave_feat(y, x, feat_pattern_start);
1972 set_cave_feat(y, x, feat_pattern_1);
1976 set_cave_feat(y, x, feat_pattern_2);
1980 set_cave_feat(y, x, feat_pattern_3);
1984 set_cave_feat(y, x, feat_pattern_4);
1988 set_cave_feat(y, x, feat_pattern_end);
1992 set_cave_feat(y, x, feat_pattern_exit);
1996 /* Reward for Pattern walk */
1997 object_level = base_level + 12;
1998 place_object(y, x, AM_GOOD | AM_GREAT);
1999 object_level = base_level;
2006 /* Place dungeon monsters and objects */
2007 for (t = data, dy = 0; dy < ymax; dy++)
2009 for (dx = 0; dx < xmax; dx++, t++)
2011 /* prevent loop counter from being overwritten */
2016 coord_trans(&i, &j, xoffset, yoffset, transno);
2018 /* Extract the location */
2019 if (transno % 2 == 0)
2021 /* no swap of x/y */
2022 x = xval - (xmax / 2) + i;
2023 y = yval - (ymax / 2) + j;
2028 x = xval - (ymax / 2) + i;
2029 y = yval - (xmax / 2) + j;
2032 /* Hack -- skip "non-grids" */
2033 if (*t == ' ') continue;
2035 /* Analyze the symbol */
2041 monster_level = base_level + 5;
2042 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
2043 monster_level = base_level;
2047 /* Meaner monster */
2050 monster_level = base_level + 11;
2051 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
2052 monster_level = base_level;
2056 /* Meaner monster, plus treasure */
2059 monster_level = base_level + 9;
2060 place_monster(y, x, PM_ALLOW_SLEEP);
2061 monster_level = base_level;
2062 object_level = base_level + 7;
2063 place_object(y, x, AM_GOOD);
2064 object_level = base_level;
2068 /* Nasty monster and treasure */
2071 monster_level = base_level + 40;
2072 place_monster(y, x, PM_ALLOW_SLEEP);
2073 monster_level = base_level;
2074 object_level = base_level + 20;
2075 place_object(y, x, AM_GOOD | AM_GREAT);
2076 object_level = base_level;
2080 /* Monster and/or object */
2083 if (randint0(100) < 50)
2085 monster_level = base_level + 3;
2086 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
2087 monster_level = base_level;
2089 if (randint0(100) < 50)
2091 object_level = base_level + 7;
2092 place_object(y, x, 0L);
2093 object_level = base_level;
2105 * @brief タイプ7の部屋…v_info.txtより小型vaultを生成する / Type 7 -- simple vaults (see "v_info.txt")
2108 static bool build_type7(void)
2110 vault_type *v_ptr = NULL;
2113 POSITION xval, yval;
2114 POSITION xoffset, yoffset;
2117 /* Pick a lesser vault */
2118 for (dummy = 0; dummy < SAFE_MAX_ATTEMPTS; dummy++)
2120 /* Access a random vault record */
2121 v_ptr = &v_info[randint0(max_v_idx)];
2123 /* Accept the first lesser vault */
2124 if (v_ptr->typ == 7) break;
2127 /* No lesser vault found */
2128 if (dummy >= SAFE_MAX_ATTEMPTS)
2130 msg_print_wizard(CHEAT_DUNGEON, _("小型固定Vaultを配置できませんでした。", "Could not place lesser vault."));
2134 /* pick type of transformation (0-7) */
2135 transno = randint0(8);
2137 /* calculate offsets */
2141 /* Some huge vault cannot be ratated to fit in the dungeon */
2142 if (x+2 > cur_hgt-2)
2144 /* Forbid 90 or 270 degree ratation */
2148 coord_trans(&x, &y, 0, 0, transno);
2168 /* Find and reserve some space in the dungeon. Get center of room. */
2169 if (!find_space(&yval, &xval, abs(y), abs(x))) return FALSE;
2176 msg_format_wizard(CHEAT_DUNGEON, _("小型Vault(%s)を生成しました。", "Lesser vault (%s)."), v_name + v_ptr->name);
2178 /* Hack -- Build the vault */
2179 build_vault(yval, xval, v_ptr->hgt, v_ptr->wid,
2180 v_text + v_ptr->text, xoffset, yoffset, transno);
2186 * @brief タイプ8の部屋…v_info.txtより大型vaultを生成する / Type 8 -- greater vaults (see "v_info.txt")
2189 static bool build_type8(void)
2193 POSITION xval, yval;
2196 int xoffset, yoffset;
2198 /* Pick a greater vault */
2199 for (dummy = 0; dummy < SAFE_MAX_ATTEMPTS; dummy++)
2201 /* Access a random vault record */
2202 v_ptr = &v_info[randint0(max_v_idx)];
2204 /* Accept the first greater vault */
2205 if (v_ptr->typ == 8) break;
2208 /* No greater vault found */
2209 if (dummy >= SAFE_MAX_ATTEMPTS)
2211 msg_print_wizard(CHEAT_DUNGEON, _("大型固定Vaultを配置できませんでした。", "Could not place greater vault."));
2215 /* pick type of transformation (0-7) */
2216 transno = randint0(8);
2218 /* calculate offsets */
2222 /* Some huge vault cannot be ratated to fit in the dungeon */
2223 if (x+2 > cur_hgt-2)
2225 /* Forbid 90 or 270 degree ratation */
2229 coord_trans(&x, &y, 0, 0, transno);
2250 * Try to allocate space for room. If fails, exit
2252 * Hack -- Prepare a bit larger space (+2, +2) to
2253 * prevent generation of vaults with no-entrance.
2255 /* Find and reserve some space in the dungeon. Get center of room. */
2256 if (!find_space(&yval, &xval, (POSITION)(abs(y) + 2), (POSITION)(abs(x) + 2))) return FALSE;
2259 v_ptr = &v_info[76 + randint1(3)];
2262 msg_format_wizard(CHEAT_DUNGEON, _("大型固定Vault(%s)を生成しました。", "Greater vault (%s)."), v_name + v_ptr->name);
2264 /* Hack -- Build the vault */
2265 build_vault(yval, xval, v_ptr->hgt, v_ptr->wid,
2266 v_text + v_ptr->text, xoffset, yoffset, transno);
2272 * Structure to hold all "fill" data
2275 typedef struct fill_data_type fill_data_type;
2277 struct fill_data_type
2290 /* features to fill with */
2299 /* number of filled squares */
2303 static fill_data_type fill_data;
2306 /* Store routine for the fractal cave generator */
2307 /* this routine probably should be an inline function or a macro. */
2308 static void store_height(int x, int y, int val)
2310 /* if on boundary set val > cutoff so walls are not as square */
2311 if (((x == fill_data.xmin) || (y == fill_data.ymin) ||
2312 (x == fill_data.xmax) || (y == fill_data.ymax)) &&
2313 (val <= fill_data.c1)) val = fill_data.c1 + 1;
2315 /* store the value in height-map format */
2316 cave[y][x].feat = (s16b)val;
2323 * Explanation of the plasma fractal algorithm:
2325 * A grid of points is created with the properties of a 'height-map'
2326 * This is done by making the corners of the grid have a random value.
2327 * The grid is then subdivided into one with twice the resolution.
2328 * The new points midway between two 'known' points can be calculated
2329 * by taking the average value of the 'known' ones and randomly adding
2330 * or subtracting an amount proportional to the distance between those
2331 * points. The final 'middle' points of the grid are then calculated
2332 * by averaging all four of the originally 'known' corner points. An
2333 * random amount is added or subtracted from this to get a value of the
2334 * height at that point. The scaling factor here is adjusted to the
2335 * slightly larger distance diagonally as compared to orthogonally.
2337 * This is then repeated recursively to fill an entire 'height-map'
2338 * A rectangular map is done the same way, except there are different
2339 * scaling factors along the x and y directions.
2341 * A hack to change the amount of correlation between points is done using
2342 * the grd variable. If the current step size is greater than grd then
2343 * the point will be random, otherwise it will be calculated by the
2344 * above algorithm. This makes a maximum distance at which two points on
2345 * the height map can affect each other.
2347 * How fractal caves are made:
2349 * When the map is complete, a cut-off value is used to create a cave.
2350 * Heights below this value are "floor", and heights above are "wall".
2351 * This also can be used to create lakes, by adding more height levels
2352 * representing shallow and deep water/ lava etc.
2354 * The grd variable affects the width of passages.
2355 * The roug variable affects the roughness of those passages
2357 * The tricky part is making sure the created cave is connected. This
2358 * is done by 'filling' from the inside and only keeping the 'filled'
2359 * floor. Walls bounding the 'filled' floor are also kept. Everything
2360 * else is converted to the normal _extra_.
2365 * Note that this uses the cave.feat array in a very hackish way
2366 * the values are first set to zero, and then each array location
2367 * is used as a "heightmap"
2368 * The heightmap then needs to be converted back into the "feat" format.
2370 * grd=level at which fractal turns on. smaller gives more mazelike caves
2371 * roug=roughness level. 16=normal. higher values make things more convoluted
2372 * small values are good for smooth walls.
2373 * size=length of the side of the square cave system.
2375 static void generate_hmap(int y0, int x0, int xsiz, int ysiz, int grd, int roug, int cutoff)
2377 int xhsize, yhsize, xsize, ysize, maxsize;
2380 * fixed point variables- these are stored as 256 x normal value
2381 * this gives 8 binary places of fractional part + 8 places of normal part
2384 u16b xstep, xhstep, ystep, yhstep;
2385 u16b xstep2, xhstep2, ystep2, yhstep2;
2386 u16b i, j, ii, jj, diagsize, xxsize, yysize;
2388 /* Cache for speed */
2389 u16b xm, xp, ym, yp;
2391 /* redefine size so can change the value if out of range */
2395 /* Paranoia about size of the system of caves */
2396 if (xsize > 254) xsize = 254;
2397 if (xsize < 4) xsize = 4;
2398 if (ysize > 254) ysize = 254;
2399 if (ysize < 4) ysize = 4;
2401 /* get offsets to middle of array */
2405 /* fix rounding problem */
2409 /* get limits of region */
2410 fill_data.xmin = x0 - xhsize;
2411 fill_data.ymin = y0 - yhsize;
2412 fill_data.xmax = x0 + xhsize;
2413 fill_data.ymax = y0 + yhsize;
2415 /* Store cutoff in global for quick access */
2416 fill_data.c1 = cutoff;
2419 * Scale factor for middle points:
2420 * About sqrt(2) * 256 - correct for a square lattice
2421 * approximately correct for everything else.
2425 /* maximum of xsize and ysize */
2426 maxsize = (xsize > ysize) ? xsize : ysize;
2428 /* Clear the section */
2429 for (i = 0; i <= xsize; i++)
2431 for (j = 0; j <= ysize; j++)
2433 /* -1 is a flag for "not done yet" */
2434 cave[(int)(fill_data.ymin + j)][(int)(fill_data.xmin + i)].feat = -1;
2435 /* Clear icky flag because may be redoing the cave */
2436 cave[(int)(fill_data.ymin + j)][(int)(fill_data.xmin + i)].info &= ~(CAVE_ICKY);
2440 /* Boundaries are walls */
2441 cave[fill_data.ymin][fill_data.xmin].feat = (s16b)maxsize;
2442 cave[fill_data.ymax][fill_data.xmin].feat = (s16b)maxsize;
2443 cave[fill_data.ymin][fill_data.xmax].feat = (s16b)maxsize;
2444 cave[fill_data.ymax][fill_data.xmax].feat = (s16b)maxsize;
2446 /* Set the middle square to be an open area. */
2447 cave[y0][x0].feat = 0;
2449 /* Initialize the step sizes */
2450 xstep = xhstep = xsize * 256;
2451 ystep = yhstep = ysize * 256;
2452 xxsize = xsize * 256;
2453 yysize = ysize * 256;
2456 * Fill in the rectangle with fractal height data -
2457 * like the 'plasma fractal' in fractint.
2459 while ((xhstep > 256) || (yhstep > 256))
2461 /* Halve the step sizes */
2467 /* cache well used values */
2468 xstep2 = xstep / 256;
2469 ystep2 = ystep / 256;
2471 xhstep2 = xhstep / 256;
2472 yhstep2 = yhstep / 256;
2474 /* middle top to bottom. */
2475 for (i = xhstep; i <= xxsize - xhstep; i += xstep)
2477 for (j = 0; j <= yysize; j += ystep)
2479 /* cache often used values */
2480 ii = i / 256 + fill_data.xmin;
2481 jj = j / 256 + fill_data.ymin;
2484 if (cave[jj][ii].feat == -1)
2488 /* If greater than 'grid' level then is random */
2489 store_height(ii, jj, randint1(maxsize));
2493 /* Average of left and right points +random bit */
2494 store_height(ii, jj,
2495 (cave[jj][fill_data.xmin + (i - xhstep) / 256].feat
2496 + cave[jj][fill_data.xmin + (i + xhstep) / 256].feat) / 2
2497 + (randint1(xstep2) - xhstep2) * roug / 16);
2504 /* middle left to right. */
2505 for (j = yhstep; j <= yysize - yhstep; j += ystep)
2507 for (i = 0; i <= xxsize; i += xstep)
2509 /* cache often used values */
2510 ii = i / 256 + fill_data.xmin;
2511 jj = j / 256 + fill_data.ymin;
2514 if (cave[jj][ii].feat == -1)
2518 /* If greater than 'grid' level then is random */
2519 store_height(ii, jj, randint1(maxsize));
2523 /* Average of up and down points +random bit */
2524 store_height(ii, jj,
2525 (cave[fill_data.ymin + (j - yhstep) / 256][ii].feat
2526 + cave[fill_data.ymin + (j + yhstep) / 256][ii].feat) / 2
2527 + (randint1(ystep2) - yhstep2) * roug / 16);
2534 for (i = xhstep; i <= xxsize - xhstep; i += xstep)
2536 for (j = yhstep; j <= yysize - yhstep; j += ystep)
2538 /* cache often used values */
2539 ii = i / 256 + fill_data.xmin;
2540 jj = j / 256 + fill_data.ymin;
2543 if (cave[jj][ii].feat == -1)
2547 /* If greater than 'grid' level then is random */
2548 store_height(ii, jj, randint1(maxsize));
2552 /* Cache reused values. */
2553 xm = fill_data.xmin + (i - xhstep) / 256;
2554 xp = fill_data.xmin + (i + xhstep) / 256;
2555 ym = fill_data.ymin + (j - yhstep) / 256;
2556 yp = fill_data.ymin + (j + yhstep) / 256;
2559 * Average over all four corners + scale by diagsize to
2560 * reduce the effect of the square grid on the shape of the fractal
2562 store_height(ii, jj,
2563 (cave[ym][xm].feat + cave[yp][xm].feat
2564 + cave[ym][xp].feat + cave[yp][xp].feat) / 4
2565 + (randint1(xstep2) - xhstep2) * (diagsize / 16) / 256 * roug);
2574 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)
2577 * function used to convert from height-map back to the
2578 * normal angband cave format
2580 if (cave[y][x].info & CAVE_ICKY)
2587 /* Show that have looked at this square */
2588 cave[y][x].info|= (CAVE_ICKY);
2590 /* Use cutoffs c1-c3 to allocate regions of floor /water/ lava etc. */
2591 if (cave[y][x].feat <= c1)
2593 /* 25% of the time use the other tile : it looks better this way */
2594 if (randint1(100) < 75)
2596 cave[y][x].feat = (s16b)feat1;
2597 cave[y][x].info &= ~(CAVE_MASK);
2598 cave[y][x].info |= info1;
2603 cave[y][x].feat = (s16b)feat2;
2604 cave[y][x].info &= ~(CAVE_MASK);
2605 cave[y][x].info |= info2;
2609 else if (cave[y][x].feat <= c2)
2611 /* 25% of the time use the other tile : it looks better this way */
2612 if (randint1(100) < 75)
2614 cave[y][x].feat = (s16b)feat2;
2615 cave[y][x].info &= ~(CAVE_MASK);
2616 cave[y][x].info |= info2;
2621 cave[y][x].feat = (s16b)feat1;
2622 cave[y][x].info &= ~(CAVE_MASK);
2623 cave[y][x].info |= info1;
2627 else if (cave[y][x].feat <= c3)
2629 cave[y][x].feat = (s16b)feat3;
2630 cave[y][x].info &= ~(CAVE_MASK);
2631 cave[y][x].info |= info3;
2634 /* if greater than cutoff then is a wall */
2637 place_outer_bold(y, x);
2647 * Quick and nasty fill routine used to find the connected region
2648 * of floor in the middle of the cave
2650 static void cave_fill(POSITION y, POSITION x)
2659 /*** Start Grid ***/
2661 /* Enqueue that entry */
2666 /* Now process the queue */
2667 while (flow_head != flow_tail)
2669 /* Extract the next entry */
2670 ty = temp_y[flow_head];
2671 tx = temp_x[flow_head];
2673 /* Forget that entry */
2674 if (++flow_head == TEMP_MAX) flow_head = 0;
2676 /* Add the "children" */
2677 for (d = 0; d < 8; d++)
2679 int old_head = flow_tail;
2681 /* Child location */
2682 j = ty + ddy_ddd[d];
2683 i = tx + ddx_ddd[d];
2685 /* Paranoia Don't leave the cave */
2686 if (!in_bounds(j, i))
2688 /* affect boundary */
2689 cave[j][i].info |= CAVE_ICKY;
2693 /* If within bounds */
2694 else if ((i > fill_data.xmin) && (i < fill_data.xmax)
2695 && (j > fill_data.ymin) && (j < fill_data.ymax))
2697 /* If not a wall or floor done before */
2698 if (hack_isnt_wall(j, i,
2699 fill_data.c1, fill_data.c2, fill_data.c3,
2700 fill_data.feat1, fill_data.feat2, fill_data.feat3,
2701 fill_data.info1, fill_data.info2, fill_data.info3))
2703 /* Enqueue that entry */
2704 temp_y[flow_tail] = (byte_hack)j;
2705 temp_x[flow_tail] = (byte_hack)i;
2707 /* Advance the queue */
2708 if (++flow_tail == TEMP_MAX) flow_tail = 0;
2710 /* Hack -- Overflow by forgetting new entry */
2711 if (flow_tail == flow_head)
2713 flow_tail = old_head;
2717 /* keep tally of size of cave system */
2718 (fill_data.amount)++;
2724 /* affect boundary */
2725 cave[j][i].info |= CAVE_ICKY;
2732 static bool generate_fracave(int y0, int x0, int xsize, int ysize, int cutoff, bool light, bool room)
2734 int x, y, i, xhsize, yhsize;
2736 /* offsets to middle from corner */
2742 * select region connected to center of cave system
2743 * this gets rid of alot of isolated one-sqaures that
2744 * can make teleport traps instadeaths...
2748 fill_data.c1 = cutoff;
2752 /* features to fill with */
2753 fill_data.feat1 = floor_type[randint0(100)];
2754 fill_data.feat2 = floor_type[randint0(100)];
2755 fill_data.feat3 = floor_type[randint0(100)];
2757 fill_data.info1 = CAVE_FLOOR;
2758 fill_data.info2 = CAVE_FLOOR;
2759 fill_data.info3 = CAVE_FLOOR;
2761 /* number of filled squares */
2762 fill_data.amount = 0;
2764 cave_fill((byte)y0, (byte)x0);
2766 /* if tally too small, try again */
2767 if (fill_data.amount < 10)
2769 /* too small - clear area and try again later */
2770 for (x = 0; x <= xsize; ++x)
2772 for (y = 0; y <= ysize; ++y)
2774 place_extra_bold(y0 + y - yhsize, x0 + x - xhsize);
2775 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY | CAVE_ROOM);
2782 * Do boundarys-check to see if they are next to a filled region
2783 * If not then they are set to normal granite
2784 * If so then they are marked as room walls.
2786 for (i = 0; i <= xsize; ++i)
2789 if ((cave[0 + y0 - yhsize][i + x0 - xhsize].info & CAVE_ICKY) && (room))
2791 /* Next to a 'filled' region? - set to be room walls */
2792 place_outer_bold(y0 + 0 - yhsize, x0 + i - xhsize);
2793 if (light) cave[y0 + 0 - yhsize][x0 + i - xhsize].info |= (CAVE_GLOW);
2794 cave[y0 + 0 - yhsize][x0 + i - xhsize].info |= (CAVE_ROOM);
2795 place_outer_bold(y0 + 0 - yhsize, x0 + i - xhsize);
2799 /* set to be normal granite */
2800 place_extra_bold(y0 + 0 - yhsize, x0 + i - xhsize);
2803 /* bottom boundary */
2804 if ((cave[ysize + y0 - yhsize][i + x0 - xhsize].info & CAVE_ICKY) && (room))
2806 /* Next to a 'filled' region? - set to be room walls */
2807 place_outer_bold(y0 + ysize - yhsize, x0 + i - xhsize);
2808 if (light) cave[y0 + ysize - yhsize][x0 + i - xhsize].info|=(CAVE_GLOW);
2809 cave[y0 + ysize - yhsize][x0 + i - xhsize].info|=(CAVE_ROOM);
2810 place_outer_bold(y0 + ysize - yhsize, x0 + i - xhsize);
2814 /* set to be normal granite */
2815 place_extra_bold(y0 + ysize - yhsize, x0 + i - xhsize);
2818 /* clear the icky flag-don't need it any more */
2819 cave[y0 + 0 - yhsize][x0 + i - xhsize].info &= ~(CAVE_ICKY);
2820 cave[y0 + ysize - yhsize][x0 + i - xhsize].info &= ~(CAVE_ICKY);
2823 /* Do the left and right boundaries minus the corners (done above) */
2824 for (i = 1; i < ysize; ++i)
2827 if ((cave[i + y0 - yhsize][0 + x0 - xhsize].info & CAVE_ICKY) && room)
2830 place_outer_bold(y0 + i - yhsize, x0 + 0 - xhsize);
2831 if (light) cave[y0 + i - yhsize][x0 + 0 - xhsize].info |= (CAVE_GLOW);
2832 cave[y0 + i - yhsize][x0 + 0 - xhsize].info |= (CAVE_ROOM);
2833 place_outer_bold(y0 + i - yhsize, x0 + 0 - xhsize);
2838 place_extra_bold(y0 + i - yhsize, x0 + 0 - xhsize);
2840 /* right boundary */
2841 if ((cave[i + y0 - yhsize][xsize + x0 - xhsize].info & CAVE_ICKY) && room)
2844 place_outer_bold(y0 + i - yhsize, x0 + xsize - xhsize);
2845 if (light) cave[y0 + i - yhsize][x0 + xsize - xhsize].info |= (CAVE_GLOW);
2846 cave[y0 + i - yhsize][x0 + xsize - xhsize].info |= (CAVE_ROOM);
2847 place_outer_bold(y0 + i - yhsize, x0 + xsize - xhsize);
2852 place_extra_bold(y0 + i - yhsize, x0 + xsize - xhsize);
2855 /* clear icky flag -done with it */
2856 cave[y0 + i - yhsize][x0 + 0 - xhsize].info &= ~(CAVE_ICKY);
2857 cave[y0 + i - yhsize][x0 + xsize - xhsize].info &= ~(CAVE_ICKY);
2861 /* Do the rest: convert back to the normal format */
2862 for (x = 1; x < xsize; ++x)
2864 for (y = 1; y < ysize; ++y)
2866 if (is_floor_bold(y0 + y - yhsize, x0 + x - xhsize) &&
2867 (cave[y0 + y - yhsize][x0 + x - xhsize].info & CAVE_ICKY))
2869 /* Clear the icky flag in the filled region */
2870 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~CAVE_ICKY;
2872 /* Set appropriate flags */
2873 if (light) cave[y0 + y - yhsize][x0 + x - xhsize].info |= (CAVE_GLOW);
2874 if (room) cave[y0 + y - yhsize][x0 + x - xhsize].info |= (CAVE_ROOM);
2876 else if (is_outer_bold(y0 + y - yhsize, x0 + x - xhsize) &&
2877 (cave[y0 + y - yhsize][x0 + x - xhsize].info & CAVE_ICKY))
2880 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY);
2881 if (light) cave[y0 + y - yhsize][x0 + x - xhsize].info |= (CAVE_GLOW);
2884 cave[y0 + y - yhsize][x0 + x - xhsize].info |= (CAVE_ROOM);
2889 place_extra_bold(y0 + y - yhsize, x0 + x - xhsize);
2890 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ROOM);
2895 /* Clear the unconnected regions */
2896 place_extra_bold(y0 + y - yhsize, x0 + x - xhsize);
2897 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY | CAVE_ROOM);
2903 * XXX XXX XXX There is a slight problem when tunnels pierce the caves:
2904 * Extra doors appear inside the system. (Its not very noticeable though.)
2905 * This can be removed by "filling" from the outside in. This allows a separation
2906 * from _outer_ with _inner_. (Internal walls are _outer_ instead.)
2907 * The extra effort for what seems to be only a minor thing (even non-existant if you
2908 * think of the caves not as normal rooms, but as holes in the dungeon), doesn't seem
2917 * @brief タイプ9の部屋…フラクタルカーブによる洞窟生成 / Type 9 -- Driver routine to create fractal cave system
2920 static bool build_type9(void)
2922 int grd, roug, cutoff;
2923 POSITION xsize, ysize, y0, x0;
2925 bool done, light, room;
2927 /* get size: note 'Evenness'*/
2928 xsize = randint1(22) * 2 + 6;
2929 ysize = randint1(15) * 2 + 6;
2931 /* Find and reserve some space in the dungeon. Get center of room. */
2932 if (!find_space(&y0, &x0, ysize + 1, xsize + 1))
2934 /* Limit to the minimum room size, and retry */
2938 /* Find and reserve some space in the dungeon. Get center of room. */
2939 if (!find_space(&y0, &x0, ysize + 1, xsize + 1))
2945 return build_type1();
2949 light = done = FALSE;
2952 if ((dun_level <= randint1(25)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS)) light = TRUE;
2956 /* Note: size must be even or there are rounding problems
2957 * This causes the tunnels not to connect properly to the room */
2959 /* testing values for these parameters feel free to adjust */
2960 grd = 1 << (randint0(4));
2962 /* want average of about 16 */
2963 roug = randint1(8) * randint1(4);
2966 cutoff = randint1(xsize / 4) + randint1(ysize / 4) +
2967 randint1(xsize / 4) + randint1(ysize / 4);
2970 generate_hmap(y0, x0, xsize, ysize, grd, roug, cutoff);
2972 /* Convert to normal format + clean up */
2973 done = generate_fracave(y0, x0, xsize, ysize, cutoff, light, room);
2979 #ifdef ALLOW_CAVERNS_AND_LAKES
2981 * Builds a cave system in the center of the dungeon.
2983 void build_cavern(void)
2985 int grd, roug, cutoff, xsize, ysize, x0, y0;
2988 light = done = FALSE;
2989 if ((dun_level <= randint1(50)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS)) light = TRUE;
2991 /* Make a cave the size of the dungeon */
2992 xsize = cur_wid - 1;
2993 ysize = cur_hgt - 1;
2997 /* Paranoia: make size even */
3003 /* testing values for these parameters: feel free to adjust */
3004 grd = randint1(4) + 4;
3006 /* want average of about 16 */
3007 roug = randint1(8) * randint1(4);
3013 generate_hmap(y0 + 1, x0 + 1, xsize, ysize, grd, roug, cutoff);
3015 /* Convert to normal format+ clean up */
3016 done = generate_fracave(y0 + 1, x0 + 1, xsize, ysize, cutoff, light, FALSE);
3020 static bool generate_lake(int y0, int x0, int xsize, int ysize, int c1, int c2, int c3, int type)
3022 int x, y, i, xhsize, yhsize;
3023 int feat1, feat2, feat3;
3025 /* offsets to middle from corner */
3029 /* Get features based on type */
3032 case LAKE_T_LAVA: /* Lava */
3033 feat1 = feat_deep_lava;
3034 feat2 = feat_shallow_lava;
3035 feat3 = floor_type[randint0(100)];
3037 case LAKE_T_WATER: /* Water */
3038 feat1 = feat_deep_water;
3039 feat2 = feat_shallow_water;
3040 feat3 = floor_type[randint0(100)];
3042 case LAKE_T_CAVE: /* Collapsed cave */
3043 feat1 = floor_type[randint0(100)];
3044 feat2 = floor_type[randint0(100)];
3045 feat3 = feat_rubble;
3047 case LAKE_T_EARTH_VAULT: /* Earth vault */
3048 feat1 = feat_rubble;
3049 feat2 = floor_type[randint0(100)];
3050 feat3 = feat_rubble;
3052 case LAKE_T_AIR_VAULT: /* Air vault */
3057 case LAKE_T_WATER_VAULT: /* Water vault */
3058 feat1 = feat_shallow_water;
3059 feat2 = feat_deep_water;
3060 feat3 = feat_shallow_water;
3062 case LAKE_T_FIRE_VAULT: /* Fire Vault */
3063 feat1 = feat_shallow_lava;
3064 feat2 = feat_deep_lava;
3065 feat3 = feat_shallow_lava;
3069 default: return FALSE;
3073 * select region connected to center of cave system
3074 * this gets rid of alot of isolated one-sqaures that
3075 * can make teleport traps instadeaths...
3083 /* features to fill with */
3084 fill_data.feat1 = feat1;
3085 fill_data.feat2 = feat2;
3086 fill_data.feat3 = feat3;
3088 fill_data.info1 = 0;
3089 fill_data.info2 = 0;
3090 fill_data.info3 = 0;
3092 /* number of filled squares */
3093 fill_data.amount = 0;
3095 /* select region connected to center of cave system
3096 * this gets rid of alot of isolated one-sqaures that
3097 * can make teleport traps instadeaths... */
3098 cave_fill((byte)y0, (byte)x0);
3100 /* if tally too small, try again */
3101 if (fill_data.amount < 10)
3103 /* too small -clear area and try again later */
3104 for (x = 0; x <= xsize; ++x)
3106 for (y = 0; y <= ysize; ++y)
3108 place_floor_bold(y0 + y - yhsize, x0 + x - xhsize);
3109 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY);
3115 /* Do boundarys- set to normal granite */
3116 for (i = 0; i <= xsize; ++i)
3118 place_extra_bold(y0 + 0 - yhsize, x0 + i - xhsize);
3119 place_extra_bold(y0 + ysize - yhsize, x0 + i - xhsize);
3121 /* clear the icky flag-don't need it any more */
3122 cave[y0 + 0 - yhsize][x0 + i - xhsize].info &= ~(CAVE_ICKY);
3123 cave[y0 + ysize - yhsize][x0 + i - xhsize].info &= ~(CAVE_ICKY);
3126 /* Do the left and right boundaries minus the corners (done above) */
3128 for (i = 1; i < ysize; ++i)
3130 place_extra_bold(y0 + i - yhsize, x0 + 0 - xhsize);
3131 place_extra_bold(y0 + i - yhsize, x0 + xsize - xhsize);
3133 /* clear icky flag -done with it */
3134 cave[y0 + i - yhsize][x0 + 0 - xhsize].info &= ~(CAVE_ICKY);
3135 cave[y0 + i - yhsize][x0 + xsize - xhsize].info &= ~(CAVE_ICKY);
3139 /* Do the rest: convert back to the normal format */
3140 for (x = 1; x < xsize; ++x)
3142 for (y = 1; y < ysize; ++y)
3144 /* Fill unconnected regions with granite */
3145 if ((!(cave[y0 + y - yhsize][x0 + x - xhsize].info & CAVE_ICKY)) ||
3146 is_outer_bold(y0 + y - yhsize, x0 + x - xhsize))
3147 place_extra_bold(y0 + y - yhsize, x0 + x - xhsize);
3149 /* turn off icky flag (no longer needed.) */
3150 cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY | CAVE_ROOM);
3153 if (cave_have_flag_bold(y0 + y - yhsize, x0 + x - xhsize, FF_LAVA))
3155 if (!(d_info[dungeon_type].flags1 & DF1_DARKNESS)) cave[y0 + y - yhsize][x0 + x - xhsize].info |= CAVE_GLOW;
3165 * makes a lake/collapsed cave system in the center of the dungeon
3167 void build_lake(int type)
3169 int grd, roug, xsize, ysize, x0, y0;
3173 /* paranoia - exit if lake type out of range. */
3174 if ((type < LAKE_T_LAVA) || (type > LAKE_T_FIRE_VAULT))
3176 msg_format("Invalid lake type (%d)", type);
3180 /* Make the size of the dungeon */
3181 xsize = cur_wid - 1;
3182 ysize = cur_hgt - 1;
3186 /* Paranoia: make size even */
3192 /* testing values for these parameters: feel free to adjust */
3193 grd = randint1(3) + 4;
3195 /* want average of about 16 */
3196 roug = randint1(8) * randint1(4);
3198 /* Make up size of various componants */
3202 /* Deep water/lava */
3203 c1 = randint0(c3 / 2) + randint0(c3 / 2) - 5;
3205 /* Shallow boundary */
3209 generate_hmap(y0 + 1, x0 + 1, xsize, ysize, grd, roug, c3);
3211 /* Convert to normal format+ clean up */
3212 done = generate_lake(y0 + 1, x0 + 1, xsize, ysize, c1, c2, c3, type);
3215 #endif /* ALLOW_CAVERNS_AND_LAKES */
3219 * Routine used by the random vault creators to add a door to a location
3220 * Note that range checking has to be done in the calling routine.
3222 * The doors must be INSIDE the allocated region.
3224 static void add_door(int x, int y)
3226 /* Need to have a wall in the center square */
3227 if (!is_outer_bold(y, x)) return;
3234 * where x=don't care
3238 if (is_floor_bold(y-1,x) && is_floor_bold(y+1,x) &&
3239 (is_outer_bold(y, x - 1) && is_outer_bold(y, x + 1)))
3242 place_secret_door(y, x, DOOR_DEFAULT);
3244 /* set boundarys so don't get wide doors */
3245 place_solid_bold(y, x - 1);
3246 place_solid_bold(y, x + 1);
3255 * where x = don't care
3258 if (is_outer_bold(y - 1, x) && is_outer_bold(y + 1, x) &&
3259 is_floor_bold(y,x-1) && is_floor_bold(y,x+1))
3262 place_secret_door(y, x, DOOR_DEFAULT);
3264 /* set boundarys so don't get wide doors */
3265 place_solid_bold(y - 1, x);
3266 place_solid_bold(y + 1, x);
3272 * Routine that fills the empty areas of a room with treasure and monsters.
3274 static void fill_treasure(int x1, int x2, int y1, int y2, int difficulty)
3276 int x, y, cx, cy, size;
3279 /* center of room:*/
3283 /* Rough measure of size of vault= sum of lengths of sides */
3284 size = abs(x2 - x1) + abs(y2 - y1);
3286 for (x = x1; x <= x2; x++)
3288 for (y = y1; y <= y2; y++)
3290 /* Thing added based on distance to center of vault
3291 * Difficulty is 1-easy to 10-hard */
3292 value = ((((s32b)(distance(cx, cy, x, y))) * 100) / size) + randint1(10) - difficulty;
3294 /* hack- empty square part of the time */
3295 if ((randint1(100) - difficulty * 3) > 50) value = 20;
3297 /* if floor, shallow water and lava */
3298 if (is_floor_bold(y, x) ||
3299 (cave_have_flag_bold(y, x, FF_PLACE) && cave_have_flag_bold(y, x, FF_DROP)))
3301 /* The smaller 'value' is, the better the stuff */
3304 /* Meanest monster + treasure */
3305 monster_level = base_level + 40;
3306 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
3307 monster_level = base_level;
3308 object_level = base_level + 20;
3309 place_object(y, x, AM_GOOD);
3310 object_level = base_level;
3314 /* Mean monster +treasure */
3315 monster_level = base_level + 20;
3316 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
3317 monster_level = base_level;
3318 object_level = base_level + 10;
3319 place_object(y, x, AM_GOOD);
3320 object_level = base_level;
3322 else if (value < 10)
3325 monster_level = base_level + 9;
3326 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
3327 monster_level = base_level;
3329 else if (value < 17)
3331 /* Intentional Blank space */
3334 * (Want some of the vault to be empty
3335 * so have room for group monsters.
3336 * This is used in the hack above to lower
3337 * the density of stuff in the vault.)
3340 else if (value < 23)
3342 /* Object or trap */
3343 if (randint0(100) < 25)
3345 place_object(y, x, 0L);
3352 else if (value < 30)
3354 /* Monster and trap */
3355 monster_level = base_level + 5;
3356 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
3357 monster_level = base_level;
3360 else if (value < 40)
3362 /* Monster or object */
3363 if (randint0(100) < 50)
3365 monster_level = base_level + 3;
3366 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
3367 monster_level = base_level;
3369 if (randint0(100) < 50)
3371 object_level = base_level + 7;
3372 place_object(y, x, 0L);
3373 object_level = base_level;
3376 else if (value < 50)
3385 /* 20% monster, 40% trap, 20% object, 20% blank space */
3386 if (randint0(100) < 20)
3388 place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
3390 else if (randint0(100) < 50)
3394 else if (randint0(100) < 50)
3396 place_object(y, x, 0L);
3407 * This function creates a random vault that looks like a collection of bubbles.
3408 * It works by getting a set of coordinates that represent the center of each
3409 * bubble. The entire room is made by seeing which bubble center is closest. If
3410 * two centers are equidistant then the square is a wall, otherwise it is a floor.
3411 * The only exception is for squares really near a center, these are always floor.
3412 * (It looks better than without this check.)
3414 * Note: If two centers are on the same point then this algorithm will create a
3415 * blank bubble filled with walls. - This is prevented from happening.
3417 static void build_bubble_vault(int x0, int y0, int xsize, int ysize)
3419 #define BUBBLENUM 10 /* number of bubbles */
3421 /* array of center points of bubbles */
3422 coord center[BUBBLENUM];
3425 u16b min1, min2, temp;
3428 /* Offset from center to top left hand corner */
3429 int xhsize = xsize / 2;
3430 int yhsize = ysize / 2;
3432 msg_print_wizard(CHEAT_DUNGEON, _("泡型ランダムVaultを生成しました。", "Room Vault."));
3434 /* Allocate center of bubbles */
3435 center[0].x = (byte)randint1(xsize - 3) + 1;
3436 center[0].y = (byte)randint1(ysize - 3) + 1;
3438 for (i = 1; i < BUBBLENUM; i++)
3442 /* get center and check to see if it is unique */
3447 x = randint1(xsize - 3) + 1;
3448 y = randint1(ysize - 3) + 1;
3450 for (j = 0; j < i; j++)
3452 /* rough test to see if there is an overlap */
3453 if ((x == center[j].x) && (y == center[j].y)) done = FALSE;
3457 center[i].x = (byte_hack)x;
3458 center[i].y = (byte_hack)y;
3462 /* Top and bottom boundaries */
3463 for (i = 0; i < xsize; i++)
3465 int side_x = x0 - xhsize + i;
3467 place_outer_noperm_bold(y0 - yhsize + 0, side_x);
3468 cave[y0 - yhsize + 0][side_x].info |= (CAVE_ROOM | CAVE_ICKY);
3469 place_outer_noperm_bold(y0 - yhsize + ysize - 1, side_x);
3470 cave[y0 - yhsize + ysize - 1][side_x].info |= (CAVE_ROOM | CAVE_ICKY);
3473 /* Left and right boundaries */
3474 for (i = 1; i < ysize - 1; i++)
3476 int side_y = y0 - yhsize + i;
3478 place_outer_noperm_bold(side_y, x0 - xhsize + 0);
3479 cave[side_y][x0 - xhsize + 0].info |= (CAVE_ROOM | CAVE_ICKY);
3480 place_outer_noperm_bold(side_y, x0 - xhsize + xsize - 1);
3481 cave[side_y][x0 - xhsize + xsize - 1].info |= (CAVE_ROOM | CAVE_ICKY);
3484 /* Fill in middle with bubbles */
3485 for (x = 1; x < xsize - 1; x++)
3487 for (y = 1; y < ysize - 1; y++)
3489 /* Get distances to two closest centers */
3492 min1 = (u16b)distance(x, y, center[0].x, center[0].y);
3493 min2 = (u16b)distance(x, y, center[1].x, center[1].y);
3497 /* swap if in wrong order */
3504 for (i = 2; i < BUBBLENUM; i++)
3506 temp = (u16b)distance(x, y, center[i].x, center[i].y);
3514 else if (temp < min2)
3516 /* second smallest */
3520 if (((min2 - min1) <= 2) && (!(min1 < 3)))
3522 /* Boundary at midpoint+ not at inner region of bubble */
3523 place_outer_noperm_bold(y0 - yhsize + y, x0 - xhsize + x);
3527 /* middle of a bubble */
3528 place_floor_bold(y0 - yhsize + y, x0 - xhsize + x);
3531 /* clean up rest of flags */
3532 cave[y0 - yhsize + y][x0 - xhsize + x].info |= (CAVE_ROOM | CAVE_ICKY);
3536 /* Try to add some random doors */
3537 for (i = 0; i < 500; i++)
3539 x = randint1(xsize - 3) - xhsize + x0 + 1;
3540 y = randint1(ysize - 3) - yhsize + y0 + 1;
3544 /* Fill with monsters and treasure, low difficulty */
3545 fill_treasure(x0 - xhsize + 1, x0 - xhsize + xsize - 2, y0 - yhsize + 1, y0 - yhsize + ysize - 2, randint1(5));
3550 * Overlay a rectangular room given its bounds
3551 * This routine is used by build_room_vault
3552 * The area inside the walls is not touched:
3553 * only granite is removed- normal walls stay
3555 static void build_room(int x1, int x2, int y1, int y2)
3557 int x, y, i, xsize, ysize, temp;
3559 /* Check if rectangle has no width */
3560 if ((x1 == x2) || (y1 == y2)) return;
3565 /* Swap boundaries if in wrong order */
3573 /* Swap boundaries if in wrong order */
3579 /* get total widths */
3584 /* Top and bottom boundaries */
3585 for (i = 0; i <= xsize; i++)
3587 place_outer_noperm_bold(y1, x1 + i);
3588 cave[y1][x1 + i].info |= (CAVE_ROOM | CAVE_ICKY);
3589 place_outer_noperm_bold(y2, x1 + i);
3590 cave[y2][x1 + i].info |= (CAVE_ROOM | CAVE_ICKY);
3593 /* Left and right boundaries */
3594 for (i = 1; i < ysize; i++)
3596 place_outer_noperm_bold(y1 + i, x1);
3597 cave[y1 + i][x1].info|=(CAVE_ROOM | CAVE_ICKY);
3598 place_outer_noperm_bold(y1 + i, x2);
3599 cave[y1 + i][x2].info|=(CAVE_ROOM | CAVE_ICKY);
3603 for (x = 1; x < xsize; x++)
3605 for (y = 1; y < ysize; y++)
3607 if (is_extra_bold(y1+y, x1+x))
3609 /* clear the untouched region */
3610 place_floor_bold(y1 + y, x1 + x);
3611 cave[y1 + y][x1 + x].info |= (CAVE_ROOM | CAVE_ICKY);
3615 /* make it a room- but don't touch */
3616 cave[y1 + y][x1 + x].info |= (CAVE_ROOM | CAVE_ICKY);
3623 /* Create a random vault that looks like a collection of overlapping rooms */
3625 static void build_room_vault(int x0, int y0, int xsize, int ysize)
3627 int i, x1, x2, y1, y2, xhsize, yhsize;
3629 /* get offset from center */
3633 msg_print_wizard(CHEAT_DUNGEON, _("部屋型ランダムVaultを生成しました。", "Room Vault."));
3635 /* fill area so don't get problems with arena levels */
3636 for (x1 = 0; x1 < xsize; x1++)
3638 int x = x0 - xhsize + x1;
3640 for (y1 = 0; y1 < ysize; y1++)
3642 int y = y0 - yhsize + y1;
3644 place_extra_bold(y, x);
3645 cave[y][x].info &= (~CAVE_ICKY);
3649 /* add ten random rooms */
3650 for (i = 0; i < 10; i++)
3652 x1 = randint1(xhsize) * 2 + x0 - xhsize;
3653 x2 = randint1(xhsize) * 2 + x0 - xhsize;
3654 y1 = randint1(yhsize) * 2 + y0 - yhsize;
3655 y2 = randint1(yhsize) * 2 + y0 - yhsize;
3656 build_room(x1, x2, y1, y2);
3659 /* Add some random doors */
3660 for (i = 0; i < 500; i++)
3662 x1 = randint1(xsize - 3) - xhsize + x0 + 1;
3663 y1 = randint1(ysize - 3) - yhsize + y0 + 1;
3667 /* Fill with monsters and treasure, high difficulty */
3668 fill_treasure(x0 - xhsize + 1, x0 - xhsize + xsize - 2, y0 - yhsize + 1, y0 - yhsize + ysize - 2, randint1(5) + 5);
3672 /* Create a random vault out of a fractal cave */
3673 static void build_cave_vault(int x0, int y0, int xsiz, int ysiz)
3675 int grd, roug, cutoff, xhsize, yhsize, xsize, ysize, x, y;
3676 bool done, light, room;
3678 /* round to make sizes even */
3684 msg_print_wizard(CHEAT_DUNGEON, _("洞穴ランダムVaultを生成しました。", "Cave Vault."));
3686 light = done = FALSE;
3691 /* testing values for these parameters feel free to adjust */
3692 grd = 1 << randint0(4);
3694 /* want average of about 16 */
3695 roug = randint1(8) * randint1(4);
3698 cutoff = randint1(xsize / 4) + randint1(ysize / 4) +
3699 randint1(xsize / 4) + randint1(ysize / 4);
3702 generate_hmap(y0, x0, xsize, ysize, grd, roug, cutoff);
3704 /* Convert to normal format+ clean up */
3705 done = generate_fracave(y0, x0, xsize, ysize, cutoff, light, room);
3708 /* Set icky flag because is a vault */
3709 for (x = 0; x <= xsize; x++)
3711 for (y = 0; y <= ysize; y++)
3713 cave[y0 - yhsize + y][x0 - xhsize + x].info |= CAVE_ICKY;
3717 /* Fill with monsters and treasure, low difficulty */
3718 fill_treasure(x0 - xhsize + 1, x0 - xhsize + xsize - 1, y0 - yhsize + 1, y0 - yhsize + ysize - 1, randint1(5));
3722 * maze vault -- rectangular labyrinthine rooms
3724 * maze vault uses two routines:
3725 * r_visit - a recursive routine that builds the labyrinth
3726 * build_maze_vault - a driver routine that calls r_visit and adds
3727 * monsters, traps and treasure
3729 * The labyrinth is built by creating a spanning tree of a graph.
3730 * The graph vertices are at
3731 * (x, y) = (2j + x1, 2k + y1) j = 0,...,m-1 k = 0,...,n-1
3732 * and the edges are the vertical and horizontal nearest neighbors.
3734 * The spanning tree is created by performing a suitably randomized
3735 * depth-first traversal of the graph. The only adjustable parameter
3736 * is the randint0(3) below; it governs the relative density of
3737 * twists and turns in the labyrinth: smaller number, more twists.
3739 static void r_visit(int y1, int x1, int y2, int x2,
3740 int node, int dir, int *visited)
3742 int i, j, m, n, temp, x, y, adj[4];
3744 /* dimensions of vertex array */
3745 m = (x2 - x1) / 2 + 1;
3746 n = (y2 - y1) / 2 + 1;
3748 /* mark node visited and set it to a floor */
3750 x = 2 * (node % m) + x1;
3751 y = 2 * (node / m) + y1;
3752 place_floor_bold(y, x);
3754 /* setup order of adjacent node visits */
3757 /* pick a random ordering */
3758 for (i = 0; i < 4; i++)
3760 for (i = 0; i < 4; i++)
3771 /* pick a random ordering with dir first */
3773 for (i = 1; i < 4; i++)
3775 for (i = 1; i < 4; i++)
3777 j = 1 + randint0(3);
3784 for (i = 0; i < 4; i++)
3789 /* (0,+) - check for bottom boundary */
3790 if ((node / m < n - 1) && (visited[node + m] == 0))
3792 place_floor_bold(y + 1, x);
3793 r_visit(y1, x1, y2, x2, node + m, dir, visited);
3797 /* (0,-) - check for top boundary */
3798 if ((node / m > 0) && (visited[node - m] == 0))
3800 place_floor_bold(y - 1, x);
3801 r_visit(y1, x1, y2, x2, node - m, dir, visited);
3805 /* (+,0) - check for right boundary */
3806 if ((node % m < m - 1) && (visited[node + 1] == 0))
3808 place_floor_bold(y, x + 1);
3809 r_visit(y1, x1, y2, x2, node + 1, dir, visited);
3813 /* (-,0) - check for left boundary */
3814 if ((node % m > 0) && (visited[node - 1] == 0))
3816 place_floor_bold(y, x - 1);
3817 r_visit(y1, x1, y2, x2, node - 1, dir, visited);
3824 void build_maze_vault(int x0, int y0, int xsize, int ysize, bool is_vault)
3828 int m, n, num_vertices, *visited;
3832 msg_print_wizard(CHEAT_DUNGEON, _("迷路ランダムVaultを生成しました。", "Maze Vault."));
3834 /* Choose lite or dark */
3835 light = ((dun_level <= randint1(25)) && is_vault && !(d_info[dungeon_type].flags1 & DF1_DARKNESS));
3837 /* Pick a random room size - randomized by calling routine */
3846 /* generate the room */
3847 for (y = y1 - 1; y <= y2 + 1; y++)
3849 for (x = x1 - 1; x <= x2 + 1; x++)
3851 c_ptr = &cave[y][x];
3852 c_ptr->info |= CAVE_ROOM;
3853 if (is_vault) c_ptr->info |= CAVE_ICKY;
3854 if ((x == x1 - 1) || (x == x2 + 1) || (y == y1 - 1) || (y == y2 + 1))
3856 place_outer_grid(c_ptr);
3860 place_extra_grid(c_ptr);
3864 place_inner_grid(c_ptr);
3866 if (light) c_ptr->info |= (CAVE_GLOW);
3870 /* dimensions of vertex array */
3873 num_vertices = m * n;
3875 /* initialize array of visited vertices */
3876 C_MAKE(visited, num_vertices, int);
3878 /* traverse the graph to create a spaning tree, pick a random root */
3879 r_visit(y1, x1, y2, x2, randint0(num_vertices), 0, visited);
3881 /* Fill with monsters and treasure, low difficulty */
3882 if (is_vault) fill_treasure(x1, x2, y1, y2, randint1(5));
3884 C_KILL(visited, num_vertices, int);
3888 /* Build a "mini" checkerboard vault
3890 * This is done by making a permanent wall maze and setting
3891 * the diagonal sqaures of the checker board to be granite.
3892 * The vault has two entrances on opposite sides to guarantee
3893 * a way to get in even if the vault abuts a side of the dungeon.
3895 static void build_mini_c_vault(int x0, int y0, int xsize, int ysize)
3898 int y1, x1, y2, x2, y, x, total;
3899 int m, n, num_vertices;
3902 msg_print_wizard(CHEAT_DUNGEON, _("小型チェッカーランダムVaultを生成しました。", "Mini Checker Board Vault."));
3904 /* Pick a random room size */
3914 /* generate the room */
3915 for (x = x1 - 2; x <= x2 + 2; x++)
3917 if (!in_bounds(y1-2,x)) break;
3919 cave[y1-2][x].info |= (CAVE_ROOM | CAVE_ICKY);
3921 place_outer_noperm_bold(y1-2, x);
3924 for (x = x1 - 2; x <= x2 + 2; x++)
3926 if (!in_bounds(y2+2,x)) break;
3928 cave[y2+2][x].info |= (CAVE_ROOM | CAVE_ICKY);
3930 place_outer_noperm_bold(y2+2, x);
3933 for (y = y1 - 2; y <= y2 + 2; y++)
3935 if (!in_bounds(y,x1-2)) break;
3937 cave[y][x1-2].info |= (CAVE_ROOM | CAVE_ICKY);
3939 place_outer_noperm_bold(y, x1-2);
3942 for (y = y1 - 2; y <= y2 + 2; y++)
3944 if (!in_bounds(y,x2+2)) break;
3946 cave[y][x2+2].info |= (CAVE_ROOM | CAVE_ICKY);
3948 place_outer_noperm_bold(y, x2+2);
3951 for (y = y1 - 1; y <= y2 + 1; y++)
3953 for (x = x1 - 1; x <= x2 + 1; x++)
3955 cave_type *c_ptr = &cave[y][x];
3957 c_ptr->info |= (CAVE_ROOM | CAVE_ICKY);
3959 /* Permanent walls */
3960 place_inner_perm_grid(c_ptr);
3965 /* dimensions of vertex array */
3968 num_vertices = m * n;
3970 /* initialize array of visited vertices */
3971 C_MAKE(visited, num_vertices, int);
3973 /* traverse the graph to create a spannng tree, pick a random root */
3974 r_visit(y1, x1, y2, x2, randint0(num_vertices), 0, visited);
3976 /* Make it look like a checker board vault */
3977 for (x = x1; x <= x2; x++)
3979 for (y = y1; y <= y2; y++)
3981 total = x - x1 + y - y1;
3982 /* If total is odd- and is a floor then make a wall */
3983 if ((total % 2 == 1) && is_floor_bold(y, x))
3985 place_inner_bold(y, x);
3990 /* Make a couple of entrances */
3993 /* left and right */
3994 y = randint1(dy) + dy / 2;
3995 place_inner_bold(y1 + y, x1 - 1);
3996 place_inner_bold(y1 + y, x2 + 1);
4000 /* top and bottom */
4001 x = randint1(dx) + dx / 2;
4002 place_inner_bold(y1 - 1, x1 + x);
4003 place_inner_bold(y2 + 1, x1 + x);
4006 /* Fill with monsters and treasure, highest difficulty */
4007 fill_treasure(x1, x2, y1, y2, 10);
4009 C_KILL(visited, num_vertices, int);
4013 /* Build a town/ castle by using a recursive algorithm.
4014 * Basically divide each region in a probalistic way to create
4015 * smaller regions. When the regions get too small stop.
4017 * The power variable is a measure of how well defended a region is.
4018 * This alters the possible choices.
4020 static void build_recursive_room(int x1, int y1, int x2, int y2, int power)
4026 /* Temp variables */
4032 if ((power < 3) && (xsize > 12) && (ysize > 12))
4034 /* Need outside wall +keep */
4041 /* Make rooms + subdivide */
4042 if ((randint1(10) > 2) && (xsize < 8) && (ysize < 8))
4048 choice = randint1(2) + 1;
4053 /* Mostly subdivide */
4054 choice = randint1(3) + 1;
4058 /* Based on the choice made above, do something */
4066 /* top and bottom */
4067 for (x = x1; x <= x2; x++)
4069 place_outer_bold(y1, x);
4070 place_outer_bold(y2, x);
4073 /* left and right */
4074 for (y = y1 + 1; y < y2; y++)
4076 place_outer_bold(y, x1);
4077 place_outer_bold(y, x2);
4080 /* Make a couple of entrances */
4083 /* left and right */
4084 y = randint1(ysize) + y1;
4085 place_floor_bold(y, x1);
4086 place_floor_bold(y, x2);
4090 /* top and bottom */
4091 x = randint1(xsize) + x1;
4092 place_floor_bold(y1, x);
4093 place_floor_bold(y2, x);
4096 /* Select size of keep */
4097 t1 = randint1(ysize / 3) + y1;
4098 t2 = y2 - randint1(ysize / 3);
4099 t3 = randint1(xsize / 3) + x1;
4100 t4 = x2 - randint1(xsize / 3);
4102 /* Do outside areas */
4104 /* Above and below keep */
4105 build_recursive_room(x1 + 1, y1 + 1, x2 - 1, t1, power + 1);
4106 build_recursive_room(x1 + 1, t2, x2 - 1, y2, power + 1);
4108 /* Left and right of keep */
4109 build_recursive_room(x1 + 1, t1 + 1, t3, t2 - 1, power + 3);
4110 build_recursive_room(t4, t1 + 1, x2 - 1, t2 - 1, power + 3);
4112 /* Make the keep itself: */
4125 /* Try to build a room */
4126 if ((xsize < 3) || (ysize < 3))
4128 for (y = y1; y < y2; y++)
4130 for (x = x1; x < x2; x++)
4132 place_inner_bold(y, x);
4140 /* Make outside walls */
4141 /* top and bottom */
4142 for (x = x1 + 1; x <= x2 - 1; x++)
4144 place_inner_bold(y1 + 1, x);
4145 place_inner_bold(y2 - 1, x);
4148 /* left and right */
4149 for (y = y1 + 1; y <= y2 - 1; y++)
4151 place_inner_bold(y, x1 + 1);
4152 place_inner_bold(y, x2 - 1);
4156 y = randint1(ysize - 3) + y1 + 1;
4161 place_floor_bold(y, x1 + 1);
4166 place_floor_bold(y, x2 - 1);
4169 /* Build the room */
4170 build_recursive_room(x1 + 2, y1 + 2, x2 - 2, y2 - 2, power + 3);
4175 /* Try and divide vertically */
4179 for (y = y1; y < y2; y++)
4181 for (x = x1; x < x2; x++)
4183 place_inner_bold(y, x);
4189 t1 = randint1(xsize - 2) + x1 + 1;
4190 build_recursive_room(x1, y1, t1, y2, power - 2);
4191 build_recursive_room(t1 + 1, y1, x2, y2, power - 2);
4196 /* Try and divide horizontally */
4200 for (y = y1; y < y2; y++)
4202 for (x = x1; x < x2; x++)
4204 place_inner_bold(y, x);
4210 t1 = randint1(ysize - 2) + y1 + 1;
4211 build_recursive_room(x1, y1, x2, t1, power - 2);
4212 build_recursive_room(x1, t1 + 1, x2, y2, power - 2);
4219 /* Build a castle */
4221 /* Driver routine: clear the region and call the recursive
4224 *This makes a vault that looks like a castle/ city in the dungeon.
4226 static void build_castle_vault(int x0, int y0, int xsize, int ysize)
4232 /* Pick a random room size */
4241 msg_print_wizard(CHEAT_DUNGEON, _("城型ランダムVaultを生成しました。", "Castle Vault"));
4243 /* generate the room */
4244 for (y = y1 - 1; y <= y2 + 1; y++)
4246 for (x = x1 - 1; x <= x2 + 1; x++)
4248 cave[y][x].info |= (CAVE_ROOM | CAVE_ICKY);
4249 /* Make everything a floor */
4250 place_floor_bold(y, x);
4254 /* Make the castle */
4255 build_recursive_room(x1, y1, x2, y2, randint1(5));
4257 /* Fill with monsters and treasure, low difficulty */
4258 fill_treasure(x1, x2, y1, y2, randint1(3));
4263 * Add outer wall to a floored region
4264 * Note: no range checking is done so must be inside dungeon
4265 * This routine also stomps on doors
4267 static void add_outer_wall(int x, int y, int light, int x1, int y1, int x2, int y2)
4270 feature_type *f_ptr;
4273 if (!in_bounds(y, x)) return;
4275 c_ptr = &cave[y][x];
4277 /* hack- check to see if square has been visited before
4278 * if so, then exit (use room flag to do this) */
4279 if (c_ptr->info & CAVE_ROOM) return;
4282 c_ptr->info |= CAVE_ROOM;
4284 f_ptr = &f_info[c_ptr->feat];
4286 if (is_floor_bold(y, x))
4288 for (i = -1; i <= 1; i++)
4290 for (j = -1; j <= 1; j++)
4292 if ((x + i >= x1) && (x + i <= x2) &&
4293 (y + j >= y1) && (y + j <= y2))
4295 add_outer_wall(x + i, y + j, light, x1, y1, x2, y2);
4296 if (light) c_ptr->info |= CAVE_GLOW;
4301 else if (is_extra_bold(y, x))
4303 /* Set bounding walls */
4304 place_outer_bold(y, x);
4305 if (light) c_ptr->info |= CAVE_GLOW;
4307 else if (permanent_wall(f_ptr))
4309 /* Set bounding walls */
4310 if (light) c_ptr->info |= CAVE_GLOW;
4316 * Hacked distance formula - gives the 'wrong' answer.
4317 * Used to build crypts
4319 static int dist2(int x1, int y1, int x2, int y2,
4320 int h1, int h2, int h3, int h4)
4326 /* Basically this works by taking the normal pythagorean formula
4327 * and using an expansion to express this in a way without the
4328 * square root. This approximate formula is then perturbed to give
4329 * the distorted results. (I found this by making a mistake when I was
4330 * trying to fix the circular rooms.)
4333 /* h1-h4 are constants that describe the metric */
4334 if (dx >= 2 * dy) return (dx + (dy * h1) / h2);
4335 if (dy >= 2 * dx) return (dy + (dx * h1) / h2);
4336 return (((dx + dy) * 128) / 181 +
4337 (dx * dx / (dy * h3) + dy * dy / (dx * h3)) * h4);
4338 /* 128/181 is approx. 1/sqrt(2) */
4343 * Build target vault.
4344 * This is made by two concentric "crypts" with perpendicular
4345 * walls creating the cross-hairs.
4347 static void build_target_vault(int x0, int y0, int xsize, int ysize)
4351 /* Make a random metric */
4353 h1 = randint1(32) - 16;
4356 h4 = randint1(32) - 16;
4358 msg_print_wizard(CHEAT_DUNGEON, _("対称形ランダムVaultを生成しました。", "Elemental Vault"));
4360 /* work out outer radius */
4371 for (x = x0 - rad; x <= x0 + rad; x++)
4373 for (y = y0 - rad; y <= y0 + rad; y++)
4375 /* clear room flag */
4376 cave[y][x].info &= ~(CAVE_ROOM);
4378 /* Vault - so is "icky" */
4379 cave[y][x].info |= CAVE_ICKY;
4381 if (dist2(y0, x0, y, x, h1, h2, h3, h4) <= rad - 1)
4383 /* inside- so is floor */
4384 place_floor_bold(y, x);
4388 /* make granite outside so arena works */
4389 place_extra_bold(y, x);
4392 /* proper boundary for arena */
4393 if (((y + rad) == y0) || ((y - rad) == y0) ||
4394 ((x + rad) == x0) || ((x - rad) == x0))
4396 place_extra_bold(y, x);
4401 /* Find visible outer walls and set to be FEAT_OUTER */
4402 add_outer_wall(x0, y0, FALSE, x0 - rad - 1, y0 - rad - 1,
4403 x0 + rad + 1, y0 + rad + 1);
4405 /* Add inner wall */
4406 for (x = x0 - rad / 2; x <= x0 + rad / 2; x++)
4408 for (y = y0 - rad / 2; y <= y0 + rad / 2; y++)
4410 if (dist2(y0, x0, y, x, h1, h2, h3, h4) == rad / 2)
4412 /* Make an internal wall */
4413 place_inner_bold(y, x);
4418 /* Add perpendicular walls */
4419 for (x = x0 - rad; x <= x0 + rad; x++)
4421 place_inner_bold(y0, x);
4424 for (y = y0 - rad; y <= y0 + rad; y++)
4426 place_inner_bold(y, x0);
4429 /* Make inner vault */
4430 for (y = y0 - 1; y <= y0 + 1; y++)
4432 place_inner_bold(y, x0 - 1);
4433 place_inner_bold(y, x0 + 1);
4435 for (x = x0 - 1; x <= x0 + 1; x++)
4437 place_inner_bold(y0 - 1, x);
4438 place_inner_bold(y0 + 1, x);
4441 place_floor_bold(y0, x0);
4444 /* Add doors to vault */
4445 /* get two distances so can place doors relative to centre */
4446 x = (rad - 2) / 4 + 1;
4449 add_door(x0 + x, y0);
4450 add_door(x0 + y, y0);
4451 add_door(x0 - x, y0);
4452 add_door(x0 - y, y0);
4453 add_door(x0, y0 + x);
4454 add_door(x0, y0 + y);
4455 add_door(x0, y0 - x);
4456 add_door(x0, y0 - y);
4458 /* Fill with stuff - medium difficulty */
4459 fill_treasure(x0 - rad, x0 + rad, y0 - rad, y0 + rad, randint1(3) + 3);
4463 #ifdef ALLOW_CAVERNS_AND_LAKES
4465 * This routine uses a modified version of the lake code to make a
4466 * distribution of some terrain type over the vault. This type
4467 * depends on the dungeon depth.
4469 * Miniture rooms are then scattered across the vault.
4471 static void build_elemental_vault(int x0, int y0, int xsiz, int ysiz)
4476 int xsize, ysize, xhsize, yhsize, x, y, i;
4479 msg_print_wizard(CHEAT_DUNGEON, _("精霊界ランダムVaultを生成しました。", "Elemental Vault"));
4481 /* round to make sizes even */
4489 /* Earth vault (Rubble) */
4490 type = LAKE_T_EARTH_VAULT;
4492 else if (dun_level < 50)
4494 /* Air vault (Trees) */
4495 type = LAKE_T_AIR_VAULT;
4497 else if (dun_level < 75)
4499 /* Water vault (shallow water) */
4500 type = LAKE_T_WATER_VAULT;
4504 /* Fire vault (shallow lava) */
4505 type = LAKE_T_FIRE_VAULT;
4510 /* testing values for these parameters: feel free to adjust */
4511 grd = 1 << (randint0(3));
4513 /* want average of about 16 */
4514 roug = randint1(8) * randint1(4);
4516 /* Make up size of various componants */
4520 /* Deep water/lava */
4521 c1 = randint0(c3 / 2) + randint0(c3 / 2) - 5;
4523 /* Shallow boundary */
4527 generate_hmap(y0, x0, xsize, ysize, grd, roug, c3);
4529 /* Convert to normal format+ clean up */
4530 done = generate_lake(y0, x0, xsize, ysize, c1, c2, c3, type);
4533 /* Set icky flag because is a vault */
4534 for (x = 0; x <= xsize; x++)
4536 for (y = 0; y <= ysize; y++)
4538 cave[y0 - yhsize + y][x0 - xhsize + x].info |= CAVE_ICKY;
4542 /* make a few rooms in the vault */
4543 for (i = 1; i <= (xsize * ysize) / 50; i++)
4545 build_small_room(x0 + randint0(xsize - 4) - xsize / 2 + 2,
4546 y0 + randint0(ysize - 4) - ysize / 2 + 2);
4549 /* Fill with monsters and treasure, low difficulty */
4550 fill_treasure(x0 - xhsize + 1, x0 - xhsize + xsize - 1,
4551 y0 - yhsize + 1, y0 - yhsize + ysize - 1, randint1(5));
4553 #endif /* ALLOW_CAVERNS_AND_LAKES */
4557 * @brief タイプ10の部屋…ランダム生成vault / Type 10 -- Random vaults
4560 static bool build_type10(void)
4562 POSITION y0, x0, xsize, ysize, vtype;
4565 /* big enough to look good, small enough to be fairly common. */
4566 xsize = randint1(22) + 22;
4567 ysize = randint1(11) + 11;
4569 /* Find and reserve some space in the dungeon. Get center of room. */
4570 if (!find_space(&y0, &x0, ysize + 1, xsize + 1)) return FALSE;
4572 /* Select type of vault */
4573 #ifdef ALLOW_CAVERNS_AND_LAKES
4576 vtype = randint1(15);
4578 while ((d_info[dungeon_type].flags1 & DF1_NO_CAVE) &&
4579 ((vtype == 1) || (vtype == 3) || (vtype == 8) || (vtype == 9) || (vtype == 11)));
4580 #else /* ALLOW_CAVERNS_AND_LAKES */
4583 vtype = randint1(7);
4585 while ((d_info[dungeon_type].flags1 & DF1_NO_CAVE) &&
4586 ((vtype == 1) || (vtype == 3)));
4587 #endif /* ALLOW_CAVERNS_AND_LAKES */
4591 /* Build an appropriate room */
4592 case 1: case 9: build_bubble_vault(x0, y0, xsize, ysize); break;
4593 case 2: case 10: build_room_vault(x0, y0, xsize, ysize); break;
4594 case 3: case 11: build_cave_vault(x0, y0, xsize, ysize); break;
4595 case 4: case 12: build_maze_vault(x0, y0, xsize, ysize, TRUE); break;
4596 case 5: case 13: build_mini_c_vault(x0, y0, xsize, ysize); break;
4597 case 6: case 14: build_castle_vault(x0, y0, xsize, ysize); break;
4598 case 7: case 15: build_target_vault(x0, y0, xsize, ysize); break;
4599 #ifdef ALLOW_CAVERNS_AND_LAKES
4600 case 8: build_elemental_vault(x0, y0, xsize, ysize); break;
4601 #endif /* ALLOW_CAVERNS_AND_LAKES */
4602 /* I know how to add a few more... give me some time. */
4605 default: return FALSE;
4613 * @brief タイプ11の部屋…円形部屋の生成 / Type 11 -- Build an vertical oval room.
4616 * For every grid in the possible square, check the distance.\n
4617 * If it's less than the radius, make it a room square.\n
4619 * When done fill from the inside to find the walls,\n
4621 static bool build_type11(void)
4623 POSITION rad, x, y, x0, y0;
4626 /* Occasional light */
4627 if ((randint1(dun_level) <= 15) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS)) light = TRUE;
4631 /* Find and reserve some space in the dungeon. Get center of room. */
4632 if (!find_space(&y0, &x0, rad * 2 + 1, rad * 2 + 1)) return FALSE;
4634 /* Make circular floor */
4635 for (x = x0 - rad; x <= x0 + rad; x++)
4637 for (y = y0 - rad; y <= y0 + rad; y++)
4639 if (distance(y0, x0, y, x) <= rad - 1)
4641 /* inside- so is floor */
4642 place_floor_bold(y, x);
4644 else if (distance(y0, x0, y, x) <= rad + 1)
4646 /* make granite outside so arena works */
4647 place_extra_bold(y, x);
4652 /* Find visible outer walls and set to be FEAT_OUTER */
4653 add_outer_wall(x0, y0, light, x0 - rad, y0 - rad, x0 + rad, y0 + rad);
4660 * @brief タイプ12の部屋…ドーム型部屋の生成 / Type 12 -- Build crypt room.
4663 * For every grid in the possible square, check the (fake) distance.\n
4664 * If it's less than the radius, make it a room square.\n
4666 * When done fill from the inside to find the walls,\n
4668 static bool build_type12(void)
4670 POSITION rad, x, y, x0, y0;
4672 bool emptyflag = TRUE;
4674 /* Make a random metric */
4676 h1 = randint1(32) - 16;
4679 h4 = randint1(32) - 16;
4681 /* Occasional light */
4682 if ((randint1(dun_level) <= 5) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS)) light = TRUE;
4686 /* Find and reserve some space in the dungeon. Get center of room. */
4687 if (!find_space(&y0, &x0, rad * 2 + 3, rad * 2 + 3)) return FALSE;
4690 for (x = x0 - rad; x <= x0 + rad; x++)
4692 for (y = y0 - rad; y <= y0 + rad; y++)
4694 /* clear room flag */
4695 cave[y][x].info &= ~(CAVE_ROOM);
4697 if (dist2(y0, x0, y, x, h1, h2, h3, h4) <= rad - 1)
4699 /* inside - so is floor */
4700 place_floor_bold(y, x);
4702 else if (distance(y0, x0, y, x) < 3)
4704 place_floor_bold(y, x);
4708 /* make granite outside so arena works */
4709 place_extra_bold(y, x);
4712 /* proper boundary for arena */
4713 if (((y + rad) == y0) || ((y - rad) == y0) ||
4714 ((x + rad) == x0) || ((x - rad) == x0))
4716 place_extra_bold(y, x);
4721 /* Find visible outer walls and set to be FEAT_OUTER */
4722 add_outer_wall(x0, y0, light, x0 - rad - 1, y0 - rad - 1,
4723 x0 + rad + 1, y0 + rad + 1);
4725 /* Check to see if there is room for an inner vault */
4726 for (x = x0 - 2; x <= x0 + 2; x++)
4728 for (y = y0 - 2; y <= y0 + 2; y++)
4730 if (!is_floor_bold(y, x))
4732 /* Wall in the way */
4738 if (emptyflag && one_in_(2))
4740 /* Build the vault */
4741 build_small_room(x0, y0);
4743 /* Place a treasure in the vault */
4744 place_object(y0, x0, 0L);
4746 /* Let's guard the treasure well */
4747 vault_monsters(y0, x0, randint0(2) + 3);
4749 /* Traps naturally */
4750 vault_traps(y0, x0, 4, 4, randint0(3) + 2);
4758 * Helper function for "trapped monster pit"
4760 static bool vault_aux_trapped_pit(MONRACE_IDX r_idx)
4762 monster_race *r_ptr = &r_info[r_idx];
4764 /* Validate the monster */
4765 if (!vault_monster_okay(r_idx)) return (FALSE);
4767 /* No wall passing monster */
4768 if (r_ptr->flags2 & (RF2_PASS_WALL | RF2_KILL_WALL)) return (FALSE);
4776 * @brief タイプ13の部屋…トラップpitの生成 / Type 13 -- Trapped monster pits
4779 * A trapped monster pit is a "big" room with a straight corridor in\n
4780 * which wall opening traps are placed, and with two "inner" rooms\n
4781 * containing a "collection" of monsters of a given type organized in\n
4784 * The trapped monster pit appears as shown below, where the actual\n
4785 * monsters in each location depend on the type of the pit\n
4787 * XXXXXXXXXXXXXXXXXXXXXXXXX\n
4789 * XXXXXXXXXXXXXXXXXXXXXXX X\n
4790 * XXXXX001123454321100XXX X\n
4791 * XXX0012234567654322100X X\n
4792 * XXXXXXXXXXXXXXXXXXXXXXX X\n
4794 * X XXXXXXXXXXXXXXXXXXXXXXX\n
4795 * X X0012234567654322100XXX\n
4796 * X XXX001123454321100XXXXX\n
4797 * X XXXXXXXXXXXXXXXXXXXXXXX\n
4799 * XXXXXXXXXXXXXXXXXXXXXXXXX\n
4801 * Note that the monsters in the pit are now chosen by using "get_mon_num()"\n
4802 * to request 16 "appropriate" monsters, sorting them by level, and using\n
4803 * the "even" entries in this sorted list for the contents of the pit.\n
4805 * Hack -- all of the "dragons" in a "dragon" pit must be the same "color",\n
4806 * which is handled by requiring a specific "breath" attack for all of the\n
4807 * dragons. This may include "multi-hued" breath. Note that "wyrms" may\n
4808 * be present in many of the dragon pits, if they have the proper breath.\n
4810 * Note the use of the "get_mon_num_prep()" function, and the special\n
4811 * "get_mon_num_hook()" restriction function, to prepare the "monster\n
4812 * allocation table" in such a way as to optimize the selection of\n
4813 * "appropriate" non-unique monsters for the pit.\n
4815 * Note that the "get_mon_num()" function may (rarely) fail, in which case\n
4816 * the pit will be empty.\n
4818 * Note that "monster pits" will never contain "unique" monsters.\n
4820 static bool build_type13(void)
4822 static int placing[][3] = {
4823 {-2, -9, 0}, {-2, -8, 0}, {-3, -7, 0}, {-3, -6, 0},
4824 {+2, -9, 0}, {+2, -8, 0}, {+3, -7, 0}, {+3, -6, 0},
4825 {-2, +9, 0}, {-2, +8, 0}, {-3, +7, 0}, {-3, +6, 0},
4826 {+2, +9, 0}, {+2, +8, 0}, {+3, +7, 0}, {+3, +6, 0},
4827 {-2, -7, 1}, {-3, -5, 1}, {-3, -4, 1},
4828 {+2, -7, 1}, {+3, -5, 1}, {+3, -4, 1},
4829 {-2, +7, 1}, {-3, +5, 1}, {-3, +4, 1},
4830 {+2, +7, 1}, {+3, +5, 1}, {+3, +4, 1},
4831 {-2, -6, 2}, {-2, -5, 2}, {-3, -3, 2},
4832 {+2, -6, 2}, {+2, -5, 2}, {+3, -3, 2},
4833 {-2, +6, 2}, {-2, +5, 2}, {-3, +3, 2},
4834 {+2, +6, 2}, {+2, +5, 2}, {+3, +3, 2},
4835 {-2, -4, 3}, {-3, -2, 3},
4836 {+2, -4, 3}, {+3, -2, 3},
4837 {-2, +4, 3}, {-3, +2, 3},
4838 {+2, +4, 3}, {+3, +2, 3},
4839 {-2, -3, 4}, {-3, -1, 4},
4840 {+2, -3, 4}, {+3, -1, 4},
4841 {-2, +3, 4}, {-3, +1, 4},
4842 {+2, +3, 4}, {+3, +1, 4},
4843 {-2, -2, 5}, {-3, 0, 5}, {-2, +2, 5},
4844 {+2, -2, 5}, {+3, 0, 5}, {+2, +2, 5},
4845 {-2, -1, 6}, {-2, +1, 6},
4846 {+2, -1, 6}, {+2, +1, 6},
4847 {-2, 0, 7}, {+2, 0, 7},
4851 POSITION y, x, y1, x1, y2, x2, xval, yval;
4854 MONRACE_IDX what[16];
4860 int cur_pit_type = pick_vault_type(pit_types, d_info[dungeon_type].pit);
4861 vault_aux_type *n_ptr;
4863 /* Only in Angband */
4864 if (dungeon_type != DUNGEON_ANGBAND) return FALSE;
4866 /* No type available */
4867 if (cur_pit_type < 0) return FALSE;
4869 n_ptr = &pit_types[cur_pit_type];
4871 /* Process a preparation function if necessary */
4872 if (n_ptr->prep_func) (*(n_ptr->prep_func))();
4874 /* Prepare allocation table */
4875 get_mon_num_prep(n_ptr->hook_func, vault_aux_trapped_pit);
4877 align.sub_align = SUB_ALIGN_NEUTRAL;
4879 /* Pick some monster types */
4880 for (i = 0; i < 16; i++)
4882 MONRACE_IDX r_idx = 0;
4884 monster_race *r_ptr = NULL;
4888 /* Get a (hard) monster type */
4889 r_idx = get_mon_num(dun_level + 0);
4890 r_ptr = &r_info[r_idx];
4892 /* Decline incorrect alignment */
4893 if (monster_has_hostile_align(&align, 0, 0, r_ptr)) continue;
4895 /* Accept this monster */
4899 /* Notice failure */
4900 if (!r_idx || !attempts) return FALSE;
4902 /* Note the alignment */
4903 if (r_ptr->flags3 & RF3_EVIL) align.sub_align |= SUB_ALIGN_EVIL;
4904 if (r_ptr->flags3 & RF3_GOOD) align.sub_align |= SUB_ALIGN_GOOD;
4909 /* Find and reserve some space in the dungeon. Get center of room. */
4910 if (!find_space(&yval, &xval, 13, 25)) return FALSE;
4918 /* Fill with inner walls */
4919 for (y = y1 - 1; y <= y2 + 1; y++)
4921 for (x = x1 - 1; x <= x2 + 1; x++)
4923 c_ptr = &cave[y][x];
4924 place_inner_grid(c_ptr);
4925 c_ptr->info |= (CAVE_ROOM);
4929 /* Place the floor area 1 */
4930 for (x = x1 + 3; x <= x2 - 3; x++)
4932 c_ptr = &cave[yval-2][x];
4933 place_floor_grid(c_ptr);
4934 add_cave_info(yval-2, x, CAVE_ICKY);
4936 c_ptr = &cave[yval+2][x];
4937 place_floor_grid(c_ptr);
4938 add_cave_info(yval+2, x, CAVE_ICKY);
4941 /* Place the floor area 2 */
4942 for (x = x1 + 5; x <= x2 - 5; x++)
4944 c_ptr = &cave[yval-3][x];
4945 place_floor_grid(c_ptr);
4946 add_cave_info(yval-3, x, CAVE_ICKY);
4948 c_ptr = &cave[yval+3][x];
4949 place_floor_grid(c_ptr);
4950 add_cave_info(yval+3, x, CAVE_ICKY);
4954 for (x = x1; x <= x2; x++)
4956 c_ptr = &cave[yval][x];
4957 place_floor_grid(c_ptr);
4958 c_ptr = &cave[y1][x];
4959 place_floor_grid(c_ptr);
4960 c_ptr = &cave[y2][x];
4961 place_floor_grid(c_ptr);
4964 /* Place the outer walls */
4965 for (y = y1 - 1; y <= y2 + 1; y++)
4967 c_ptr = &cave[y][x1 - 1];
4968 place_outer_grid(c_ptr);
4969 c_ptr = &cave[y][x2 + 1];
4970 place_outer_grid(c_ptr);
4972 for (x = x1 - 1; x <= x2 + 1; x++)
4974 c_ptr = &cave[y1 - 1][x];
4975 place_outer_grid(c_ptr);
4976 c_ptr = &cave[y2 + 1][x];
4977 place_outer_grid(c_ptr);
4980 /* Random corridor */
4983 for (y = y1; y <= yval; y++)
4985 place_floor_bold(y, x2);
4986 place_solid_bold(y, x1-1);
4988 for (y = yval; y <= y2 + 1; y++)
4990 place_floor_bold(y, x1);
4991 place_solid_bold(y, x2+1);
4996 for (y = yval; y <= y2 + 1; y++)
4998 place_floor_bold(y, x1);
4999 place_solid_bold(y, x2+1);
5001 for (y = y1; y <= yval; y++)
5003 place_floor_bold(y, x2);
5004 place_solid_bold(y, x1-1);
5008 /* Place the wall open trap */
5009 cave[yval][xval].mimic = cave[yval][xval].feat;
5010 cave[yval][xval].feat = feat_trap_open;
5012 /* Sort the entries */
5013 for (i = 0; i < 16 - 1; i++)
5015 /* Sort the entries */
5016 for (j = 0; j < 16 - 1; j++)
5021 int p1 = r_info[what[i1]].level;
5022 int p2 = r_info[what[i2]].level;
5027 MONRACE_IDX tmp = what[i1];
5028 what[i1] = what[i2];
5034 msg_format_wizard(CHEAT_DUNGEON, _("%s%sの罠ピットが生成されました。", "Trapped monster pit (%s%s)"),
5035 n_ptr->name, pit_subtype_string(cur_pit_type, FALSE));
5037 /* Select the entries */
5038 for (i = 0; i < 8; i++)
5040 /* Every other entry */
5041 what[i] = what[i * 2];
5046 msg_print(r_name + r_info[what[i]].name);
5050 for (i = 0; placing[i][2] >= 0; i++)
5052 y = yval + placing[i][0];
5053 x = xval + placing[i][1];
5054 place_monster_aux(0, y, x, what[placing[i][2]], PM_NO_KAGE);
5062 * @brief タイプ14の部屋…特殊トラップ部屋の生成 / Type 14 -- trapped rooms
5065 * A special trap is placed at center of the room
5067 static bool build_type14(void)
5069 POSITION y, x, y2, x2, yval, xval;
5070 POSITION y1, x1, xsize, ysize;
5077 /* Pick a room size */
5083 xsize = x1 + x2 + 1;
5084 ysize = y1 + y2 + 1;
5086 /* Find and reserve some space in the dungeon. Get center of room. */
5087 if (!find_space(&yval, &xval, ysize + 2, xsize + 2)) return FALSE;
5089 /* Choose lite or dark */
5090 light = ((dun_level <= randint1(25)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS));
5093 /* Get corner values */
5094 y1 = yval - ysize / 2;
5095 x1 = xval - xsize / 2;
5096 y2 = yval + (ysize - 1) / 2;
5097 x2 = xval + (xsize - 1) / 2;
5100 /* Place a full floor under the room */
5101 for (y = y1 - 1; y <= y2 + 1; y++)
5103 for (x = x1 - 1; x <= x2 + 1; x++)
5105 c_ptr = &cave[y][x];
5106 place_floor_grid(c_ptr);
5107 c_ptr->info |= (CAVE_ROOM);
5108 if (light) c_ptr->info |= (CAVE_GLOW);
5112 /* Walls around the room */
5113 for (y = y1 - 1; y <= y2 + 1; y++)
5115 c_ptr = &cave[y][x1 - 1];
5116 place_outer_grid(c_ptr);
5117 c_ptr = &cave[y][x2 + 1];
5118 place_outer_grid(c_ptr);
5120 for (x = x1 - 1; x <= x2 + 1; x++)
5122 c_ptr = &cave[y1 - 1][x];
5123 place_outer_grid(c_ptr);
5124 c_ptr = &cave[y2 + 1][x];
5125 place_outer_grid(c_ptr);
5128 if (dun_level < 30 + randint1(30))
5129 trap = feat_trap_piranha;
5131 trap = feat_trap_armageddon;
5133 /* Place a special trap */
5134 c_ptr = &cave[rand_spread(yval, ysize/4)][rand_spread(xval, xsize/4)];
5135 c_ptr->mimic = c_ptr->feat;
5138 msg_format_wizard(CHEAT_DUNGEON, _("%sの部屋が生成されました。", "Room of %s was generated."), f_name + f_info[trap].name);
5145 * Helper function for "glass room"
5147 static bool vault_aux_lite(MONRACE_IDX r_idx)
5149 monster_race *r_ptr = &r_info[r_idx];
5151 /* Validate the monster */
5152 if (!vault_monster_okay(r_idx)) return FALSE;
5154 /* Require lite attack */
5155 if (!(r_ptr->flags4 & RF4_BR_LITE) && !(r_ptr->a_ability_flags1 & RF5_BA_LITE)) return FALSE;
5157 /* No wall passing monsters */
5158 if (r_ptr->flags2 & (RF2_PASS_WALL | RF2_KILL_WALL)) return FALSE;
5160 /* No disintegrating monsters */
5161 if (r_ptr->flags4 & RF4_BR_DISI) return FALSE;
5167 * Helper function for "glass room"
5169 static bool vault_aux_shards(MONRACE_IDX r_idx)
5171 monster_race *r_ptr = &r_info[r_idx];
5173 /* Validate the monster */
5174 if (!vault_monster_okay(r_idx)) return FALSE;
5176 /* Require shards breath attack */
5177 if (!(r_ptr->flags4 & RF4_BR_SHAR)) return FALSE;
5183 * Hack -- determine if a template is potion
5185 static bool kind_is_potion(KIND_OBJECT_IDX k_idx)
5187 return k_info[k_idx].tval == TV_POTION;
5191 * @brief タイプ15の部屋…ガラス部屋の生成 / Type 15 -- glass rooms
5194 static bool build_type15(void)
5196 POSITION y, x, y2, x2, yval, xval;
5197 POSITION y1, x1, xsize, ysize;
5202 /* Pick a room size */
5203 xsize = rand_range(9, 13);
5204 ysize = rand_range(9, 13);
5206 /* Find and reserve some space in the dungeon. Get center of room. */
5207 if (!find_space(&yval, &xval, ysize + 2, xsize + 2)) return FALSE;
5209 /* Choose lite or dark */
5210 light = ((dun_level <= randint1(25)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS));
5212 /* Get corner values */
5213 y1 = yval - ysize / 2;
5214 x1 = xval - xsize / 2;
5215 y2 = yval + (ysize - 1) / 2;
5216 x2 = xval + (xsize - 1) / 2;
5218 /* Place a full floor under the room */
5219 for (y = y1 - 1; y <= y2 + 1; y++)
5221 for (x = x1 - 1; x <= x2 + 1; x++)
5223 c_ptr = &cave[y][x];
5224 place_floor_grid(c_ptr);
5225 c_ptr->feat = feat_glass_floor;
5226 c_ptr->info |= (CAVE_ROOM);
5227 if (light) c_ptr->info |= (CAVE_GLOW);
5231 /* Walls around the room */
5232 for (y = y1 - 1; y <= y2 + 1; y++)
5234 c_ptr = &cave[y][x1 - 1];
5235 place_outer_grid(c_ptr);
5236 c_ptr->feat = feat_glass_wall;
5237 c_ptr = &cave[y][x2 + 1];
5238 place_outer_grid(c_ptr);
5239 c_ptr->feat = feat_glass_wall;
5241 for (x = x1 - 1; x <= x2 + 1; x++)
5243 c_ptr = &cave[y1 - 1][x];
5244 place_outer_grid(c_ptr);
5245 c_ptr->feat = feat_glass_wall;
5246 c_ptr = &cave[y2 + 1][x];
5247 place_outer_grid(c_ptr);
5248 c_ptr->feat = feat_glass_wall;
5251 switch (randint1(3))
5253 case 1: /* 4 lite breathers + potion */
5257 /* Prepare allocation table */
5258 get_mon_num_prep(vault_aux_lite, NULL);
5260 /* Place fixed lite berathers */
5261 for (dir1 = 4; dir1 < 8; dir1++)
5263 MONRACE_IDX r_idx = get_mon_num(dun_level);
5265 y = yval + 2 * ddy_ddd[dir1];
5266 x = xval + 2 * ddx_ddd[dir1];
5267 if (r_idx) place_monster_aux(0, y, x, r_idx, PM_ALLOW_SLEEP);
5269 /* Walls around the breather */
5270 for (dir2 = 0; dir2 < 8; dir2++)
5272 c_ptr = &cave[y + ddy_ddd[dir2]][x + ddx_ddd[dir2]];
5273 place_inner_grid(c_ptr);
5274 c_ptr->feat = feat_glass_wall;
5278 /* Walls around the potion */
5279 for (dir1 = 0; dir1 < 4; dir1++)
5281 y = yval + 2 * ddy_ddd[dir1];
5282 x = xval + 2 * ddx_ddd[dir1];
5283 c_ptr = &cave[y][x];
5284 place_inner_perm_grid(c_ptr);
5285 c_ptr->feat = feat_permanent_glass_wall;
5286 cave[yval + ddy_ddd[dir1]][xval + ddx_ddd[dir1]].info |= (CAVE_ICKY);
5291 y = yval + 2 * ddy_ddd[dir1];
5292 x = xval + 2 * ddx_ddd[dir1];
5293 place_secret_door(y, x, DOOR_GLASS_DOOR);
5294 c_ptr = &cave[y][x];
5295 if (is_closed_door(c_ptr->feat)) c_ptr->mimic = feat_glass_wall;
5297 /* Place a potion */
5298 get_obj_num_hook = kind_is_potion;
5299 place_object(yval, xval, AM_NO_FIXED_ART);
5300 cave[yval][xval].info |= (CAVE_ICKY);
5304 case 2: /* 1 lite breather + random object */
5310 c_ptr = &cave[y1 + 1][x1 + 1];
5311 place_inner_grid(c_ptr);
5312 c_ptr->feat = feat_glass_wall;
5314 c_ptr = &cave[y1 + 1][x2 - 1];
5315 place_inner_grid(c_ptr);
5316 c_ptr->feat = feat_glass_wall;
5318 c_ptr = &cave[y2 - 1][x1 + 1];
5319 place_inner_grid(c_ptr);
5320 c_ptr->feat = feat_glass_wall;
5322 c_ptr = &cave[y2 - 1][x2 - 1];
5323 place_inner_grid(c_ptr);
5324 c_ptr->feat = feat_glass_wall;
5326 /* Prepare allocation table */
5327 get_mon_num_prep(vault_aux_lite, NULL);
5329 r_idx = get_mon_num(dun_level);
5330 if (r_idx) place_monster_aux(0, yval, xval, r_idx, 0L);
5332 /* Walls around the breather */
5333 for (dir1 = 0; dir1 < 8; dir1++)
5335 c_ptr = &cave[yval + ddy_ddd[dir1]][xval + ddx_ddd[dir1]];
5336 place_inner_grid(c_ptr);
5337 c_ptr->feat = feat_glass_wall;
5340 /* Curtains around the breather */
5341 for (y = yval - 1; y <= yval + 1; y++)
5343 place_closed_door(y, xval - 2, DOOR_CURTAIN);
5344 place_closed_door(y, xval + 2, DOOR_CURTAIN);
5346 for (x = xval - 1; x <= xval + 1; x++)
5348 place_closed_door(yval - 2, x, DOOR_CURTAIN);
5349 place_closed_door(yval + 2, x, DOOR_CURTAIN);
5352 /* Place an object */
5353 place_object(yval, xval, AM_NO_FIXED_ART);
5354 cave[yval][xval].info |= (CAVE_ICKY);
5358 case 3: /* 4 shards breathers + 2 potions */
5362 /* Walls around the potion */
5363 for (y = yval - 2; y <= yval + 2; y++)
5365 c_ptr = &cave[y][xval - 3];
5366 place_inner_grid(c_ptr);
5367 c_ptr->feat = feat_glass_wall;
5368 c_ptr = &cave[y][xval + 3];
5369 place_inner_grid(c_ptr);
5370 c_ptr->feat = feat_glass_wall;
5372 for (x = xval - 2; x <= xval + 2; x++)
5374 c_ptr = &cave[yval - 3][x];
5375 place_inner_grid(c_ptr);
5376 c_ptr->feat = feat_glass_wall;
5377 c_ptr = &cave[yval + 3][x];
5378 place_inner_grid(c_ptr);
5379 c_ptr->feat = feat_glass_wall;
5381 for (dir1 = 4; dir1 < 8; dir1++)
5383 c_ptr = &cave[yval + 2 * ddy_ddd[dir1]][xval + 2 * ddx_ddd[dir1]];
5384 place_inner_grid(c_ptr);
5385 c_ptr->feat = feat_glass_wall;
5388 /* Prepare allocation table */
5389 get_mon_num_prep(vault_aux_shards, NULL);
5391 /* Place shard berathers */
5392 for (dir1 = 4; dir1 < 8; dir1++)
5394 MONRACE_IDX r_idx = get_mon_num(dun_level);
5396 y = yval + ddy_ddd[dir1];
5397 x = xval + ddx_ddd[dir1];
5398 if (r_idx) place_monster_aux(0, y, x, r_idx, 0L);
5401 /* Place two potions */
5404 get_obj_num_hook = kind_is_potion;
5405 place_object(yval, xval - 1, AM_NO_FIXED_ART);
5406 get_obj_num_hook = kind_is_potion;
5407 place_object(yval, xval + 1, AM_NO_FIXED_ART);
5411 get_obj_num_hook = kind_is_potion;
5412 place_object(yval - 1, xval, AM_NO_FIXED_ART);
5413 get_obj_num_hook = kind_is_potion;
5414 place_object(yval + 1, xval, AM_NO_FIXED_ART);
5417 for (y = yval - 2; y <= yval + 2; y++)
5418 for (x = xval - 2; x <= xval + 2; x++)
5419 cave[y][x].info |= (CAVE_ICKY);
5425 msg_print_wizard(CHEAT_DUNGEON, _("ガラスの部屋が生成されました。", "Glass room was generated."));
5431 /* Create a new floor room with optional light */
5432 void generate_room_floor(int y1, int x1, int y2, int x2, int light)
5438 for (y = y1; y <= y2; y++)
5440 for (x = x1; x <= x2; x++)
5443 c_ptr = &cave[y][x];
5444 place_floor_grid(c_ptr);
5445 c_ptr->info |= (CAVE_ROOM);
5446 if (light) c_ptr->info |= (CAVE_GLOW);
5451 void generate_fill_perm_bold(int y1, int x1, int y2, int x2)
5455 for (y = y1; y <= y2; y++)
5457 for (x = x1; x <= x2; x++)
5460 place_inner_perm_bold(y, x);
5465 /* Minimum & maximum town size */
5466 #define MIN_TOWN_WID ((MAX_WID / 3) / 2)
5467 #define MIN_TOWN_HGT ((MAX_HGT / 3) / 2)
5468 #define MAX_TOWN_WID ((MAX_WID / 3) * 2 / 3)
5469 #define MAX_TOWN_HGT ((MAX_HGT / 3) * 2 / 3)
5471 /* Struct for build underground buildings */
5474 int y0, x0; /* North-west corner (relative) */
5475 int y1, x1; /* South-east corner (relative) */
5479 ugbldg_type *ugbldg;
5482 * Precalculate buildings' location of underground arcade
5484 static bool precalc_ugarcade(int town_hgt, int town_wid, int n)
5486 int i, y, x, center_y, center_x, tmp, attempt = 10000;
5487 int max_bldg_hgt = 3 * town_hgt / MAX_TOWN_HGT;
5488 int max_bldg_wid = 5 * town_wid / MAX_TOWN_WID;
5489 ugbldg_type *cur_ugbldg;
5490 bool **ugarcade_used, abort;
5492 /* Allocate "ugarcade_used" array (2-dimension) */
5493 C_MAKE(ugarcade_used, town_hgt, bool *);
5494 C_MAKE(*ugarcade_used, town_hgt * town_wid, bool);
5495 for (y = 1; y < town_hgt; y++) ugarcade_used[y] = *ugarcade_used + y * town_wid;
5497 /* Calculate building locations */
5498 for (i = 0; i < n; i++)
5500 cur_ugbldg = &ugbldg[i];
5501 (void)WIPE(cur_ugbldg, ugbldg_type);
5505 /* Find the "center" of the store */
5506 center_y = rand_range(2, town_hgt - 3);
5507 center_x = rand_range(2, town_wid - 3);
5509 /* Determine the store boundaries */
5510 tmp = center_y - randint1(max_bldg_hgt);
5511 cur_ugbldg->y0 = MAX(tmp, 1);
5512 tmp = center_x - randint1(max_bldg_wid);
5513 cur_ugbldg->x0 = MAX(tmp, 1);
5514 tmp = center_y + randint1(max_bldg_hgt);
5515 cur_ugbldg->y1 = MIN(tmp, town_hgt - 2);
5516 tmp = center_x + randint1(max_bldg_wid);
5517 cur_ugbldg->x1 = MIN(tmp, town_wid - 2);
5519 /* Scan this building's area */
5520 for (abort = FALSE, y = cur_ugbldg->y0; (y <= cur_ugbldg->y1) && !abort; y++)
5522 for (x = cur_ugbldg->x0; x <= cur_ugbldg->x1; x++)
5524 if (ugarcade_used[y][x])
5534 while (abort && attempt); /* Accept this building if no overlapping */
5536 /* Failed to generate underground arcade */
5537 if (!attempt) break;
5540 * Mark to ugarcade_used[][] as "used"
5541 * Note: Building-adjacent grids are included for preventing
5542 * connected bulidings.
5544 for (y = cur_ugbldg->y0 - 1; y <= cur_ugbldg->y1 + 1; y++)
5546 for (x = cur_ugbldg->x0 - 1; x <= cur_ugbldg->x1 + 1; x++)
5548 ugarcade_used[y][x] = TRUE;
5553 /* Free "ugarcade_used" array (2-dimension) */
5554 C_KILL(*ugarcade_used, town_hgt * town_wid, bool);
5555 C_KILL(ugarcade_used, town_hgt, bool *);
5557 /* If i < n, generation is not allowed */
5562 * @brief タイプ16の部屋…地下都市生成のサブルーチン / Actually create buildings
5564 * @param ltcy 生成基準Y座標
5565 * @param ltcx 生成基準X座標
5566 * @param stotes[] 生成する店舗のリスト
5569 * Note: ltcy and ltcx indicate "left top corner".
5571 static void build_stores(int ltcy, int ltcx, int stores[], int n)
5575 ugbldg_type *cur_ugbldg;
5577 for (i = 0; i < n; i++)
5579 cur_ugbldg = &ugbldg[i];
5581 /* Generate new room */
5582 generate_room_floor(
5583 ltcy + cur_ugbldg->y0 - 2, ltcx + cur_ugbldg->x0 - 2,
5584 ltcy + cur_ugbldg->y1 + 2, ltcx + cur_ugbldg->x1 + 2,
5588 for (i = 0; i < n; i++)
5590 cur_ugbldg = &ugbldg[i];
5592 /* Build an invulnerable rectangular building */
5593 generate_fill_perm_bold(
5594 ltcy + cur_ugbldg->y0, ltcx + cur_ugbldg->x0,
5595 ltcy + cur_ugbldg->y1, ltcx + cur_ugbldg->x1);
5597 /* Pick a door direction (S,N,E,W) */
5598 switch (randint0(4))
5603 x = rand_range(cur_ugbldg->x0, cur_ugbldg->x1);
5609 x = rand_range(cur_ugbldg->x0, cur_ugbldg->x1);
5614 y = rand_range(cur_ugbldg->y0, cur_ugbldg->y1);
5620 y = rand_range(cur_ugbldg->y0, cur_ugbldg->y1);
5625 for (j = 0; j < max_f_idx; j++)
5627 if (have_flag(f_info[j].flags, FF_STORE))
5629 if (f_info[j].subtype == stores[i]) break;
5633 /* Clear previous contents, add a store door */
5636 cave_set_feat(ltcy + y, ltcx + x, j);
5639 store_init(NO_TOWN, stores[i]);
5646 * @brief タイプ16の部屋…地下都市の生成 / Type 16 -- Underground Arcade
5649 * Town logic flow for generation of new town\n
5650 * Originally from Vanilla 3.0.3\n
5652 * We start with a fully wiped cave of normal floors.\n
5654 * Note that town_gen_hack() plays games with the R.N.G.\n
5656 * This function does NOT do anything about the owners of the stores,\n
5657 * nor the contents thereof. It only handles the physical layout.\n
5659 static bool build_type16(void)
5663 STORE_GENERAL, STORE_ARMOURY, STORE_WEAPON, STORE_TEMPLE,
5664 STORE_ALCHEMIST, STORE_MAGIC, STORE_BLACK, STORE_BOOK,
5666 int n = sizeof stores / sizeof (int);
5667 POSITION i, y, x, y1, x1, yval, xval;
5668 int town_hgt = rand_range(MIN_TOWN_HGT, MAX_TOWN_HGT);
5669 int town_wid = rand_range(MIN_TOWN_WID, MAX_TOWN_WID);
5670 bool prevent_bm = FALSE;
5672 /* Hack -- If already exist black market, prevent building */
5673 for (y = 0; (y < cur_hgt) && !prevent_bm; y++)
5675 for (x = 0; x < cur_wid; x++)
5677 if (cave[y][x].feat == FF_STORE)
5679 prevent_bm = (f_info[cave[y][x].feat].subtype == STORE_BLACK);
5684 for (i = 0; i < n; i++)
5686 if ((stores[i] == STORE_BLACK) && prevent_bm) stores[i] = stores[--n];
5688 if (!n) return FALSE;
5690 /* Allocate buildings array */
5691 C_MAKE(ugbldg, n, ugbldg_type);
5693 /* If cannot build stores, abort */
5694 if (!precalc_ugarcade(town_hgt, town_wid, n))
5696 /* Free buildings array */
5697 C_KILL(ugbldg, n, ugbldg_type);
5701 /* Find and reserve some space in the dungeon. Get center of room. */
5702 if (!find_space(&yval, &xval, town_hgt + 4, town_wid + 4))
5704 /* Free buildings array */
5705 C_KILL(ugbldg, n, ugbldg_type);
5709 /* Get top left corner */
5710 y1 = yval - (town_hgt / 2);
5711 x1 = xval - (town_wid / 2);
5713 /* Generate new room */
5714 generate_room_floor(
5715 y1 + town_hgt / 3, x1 + town_wid / 3,
5716 y1 + town_hgt * 2 / 3, x1 + town_wid * 2 / 3, FALSE);
5719 build_stores(y1, x1, stores, n);
5721 msg_print_wizard(CHEAT_DUNGEON, _("地下街を生成しました", "Underground arcade was generated."));
5723 /* Free buildings array */
5724 C_KILL(ugbldg, n, ugbldg_type);
5731 * @brief 与えられた部屋型IDに応じて部屋の生成処理分岐を行い結果を返す / Attempt to build a room of the given type at the given block
5733 * @note that we restrict the number of "crowded" rooms to reduce the chance of overflowing the monster list during level creation.
5734 * @return 部屋の精製に成功した場合 TRUE を返す。
5736 static bool room_build(int typ)
5741 /* Build an appropriate room */
5742 case ROOM_T_NORMAL: return build_type1();
5743 case ROOM_T_OVERLAP: return build_type2();
5744 case ROOM_T_CROSS: return build_type3();
5745 case ROOM_T_INNER_FEAT: return build_type4();
5746 case ROOM_T_NEST: return build_type5();
5747 case ROOM_T_PIT: return build_type6();
5748 case ROOM_T_LESSER_VAULT: return build_type7();
5749 case ROOM_T_GREATER_VAULT: return build_type8();
5750 case ROOM_T_FRACAVE: return build_type9();
5751 case ROOM_T_RANDOM_VAULT: return build_type10();
5752 case ROOM_T_OVAL: return build_type11();
5753 case ROOM_T_CRYPT: return build_type12();
5754 case ROOM_T_TRAP_PIT: return build_type13();
5755 case ROOM_T_TRAP: return build_type14();
5756 case ROOM_T_GLASS: return build_type15();
5757 case ROOM_T_ARCADE: return build_type16();
5765 * @brief 指定した部屋の生成確率を別の部屋に加算し、指定した部屋の生成率を0にする
5766 * @param dst 確率を移す先の部屋種ID
5767 * @param src 確率を与える元の部屋種ID
5769 #define MOVE_PLIST(dst, src) (prob_list[dst] += prob_list[src], prob_list[src] = 0)
5772 * @brief 部屋生成処理のメインルーチン(Sangbandを経由してOangbandからの実装を引用) / Generate rooms in dungeon. Build bigger rooms at first. [from SAngband (originally from OAngband)]
5773 * @return 部屋生成に成功した場合 TRUE を返す。
5775 bool generate_rooms(void)
5781 int prob_list[ROOM_T_MAX];
5782 int rooms_built = 0;
5783 int area_size = 100 * (cur_hgt*cur_wid) / (MAX_HGT*MAX_WID);
5784 int level_index = MIN(10, div_round(dun_level, 10));
5786 /* Number of each type of room on this level */
5787 s16b room_num[ROOM_T_MAX];
5789 /* Limit number of rooms */
5790 int dun_rooms = DUN_ROOMS_MAX * area_size / 100;
5792 /* Assume normal cave */
5793 room_info_type *room_info_ptr = room_info_normal;
5796 * Initialize probability list.
5798 for (i = 0; i < ROOM_T_MAX; i++)
5800 /* No rooms allowed above their minimum depth. */
5801 if (dun_level < room_info_ptr[i].min_level)
5807 prob_list[i] = room_info_ptr[i].prob[level_index];
5812 * XXX -- Various dungeon types and options.
5815 /*! @details ダンジョンにBEGINNER、CHAMELEON、SMALLESTいずれのフラグもなく、かつ「常に通常でない部屋を生成する」フラグがONならば、GRATER_VAULTのみを生成対象とする。 / Ironman sees only Greater Vaults */
5816 if (ironman_rooms && !((d_info[dungeon_type].flags1 & (DF1_BEGINNER | DF1_CHAMELEON | DF1_SMALLEST))))
5818 for (i = 0; i < ROOM_T_MAX; i++)
5820 if (i == ROOM_T_GREATER_VAULT) prob_list[i] = 1;
5821 else prob_list[i] = 0;
5825 /*! @details ダンジョンにNO_VAULTフラグがあるならば、LESSER_VAULT / GREATER_VAULT/ RANDOM_VAULTを除外 / Forbidden vaults */
5826 else if (d_info[dungeon_type].flags1 & DF1_NO_VAULT)
5828 prob_list[ROOM_T_LESSER_VAULT] = 0;
5829 prob_list[ROOM_T_GREATER_VAULT] = 0;
5830 prob_list[ROOM_T_RANDOM_VAULT] = 0;
5833 /*! @details ダンジョンにNO_CAVEフラグがある場合、FRACAVEの生成枠がNORMALに与えられる。CRIPT、OVALの生成枠がINNER_Fに与えられる。/ NO_CAVE dungeon (Castle)*/
5834 if (d_info[dungeon_type].flags1 & DF1_NO_CAVE)
5836 MOVE_PLIST(ROOM_T_NORMAL, ROOM_T_FRACAVE);
5837 MOVE_PLIST(ROOM_T_INNER_FEAT, ROOM_T_CRYPT);
5838 MOVE_PLIST(ROOM_T_INNER_FEAT, ROOM_T_OVAL);
5841 /*! @details ダンジョンにCAVEフラグがある場合、NORMALの生成枠がFRACAVEに与えられる。/ CAVE dungeon (Orc cave etc.) */
5842 else if (d_info[dungeon_type].flags1 & DF1_CAVE)
5844 MOVE_PLIST(ROOM_T_FRACAVE, ROOM_T_NORMAL);
5847 /*! @details ダンジョンの基本地形が最初から渓谷かアリーナ型の場合 FRACAVE は生成から除外。 / No caves when a (random) cavern exists: they look bad */
5848 else if (dun->cavern || dun->empty_level)
5850 prob_list[ROOM_T_FRACAVE] = 0;
5853 /*! @details ダンジョンに最初からGLASS_ROOMフラグがある場合、GLASS を生成から除外。/ Forbidden glass rooms */
5854 if (!(d_info[dungeon_type].flags1 & DF1_GLASS_ROOM))
5856 prob_list[ROOM_T_GLASS] = 0;
5859 /*! @details ARCADEは同フラグがダンジョンにないと生成されない。 / Forbidden glass rooms */
5860 if (!(d_info[dungeon_type].flags1 & DF1_ARCADE))
5862 prob_list[ROOM_T_ARCADE] = 0;
5866 * Initialize number of rooms,
5867 * And calcurate total probability.
5869 for (total_prob = 0, i = 0; i < ROOM_T_MAX; i++)
5872 total_prob += prob_list[i];
5876 * Prepare the number of rooms, of all types, we should build
5879 for (i = dun_rooms; i > 0; i--)
5882 int rand = randint0(total_prob);
5884 /* Get room_type randomly */
5885 for (room_type = 0; room_type < ROOM_T_MAX; room_type++)
5887 if (rand < prob_list[room_type]) break;
5888 else rand -= prob_list[room_type];
5892 if (room_type >= ROOM_T_MAX) room_type = ROOM_T_NORMAL;
5894 /* Increase the number of rooms of that type we should build. */
5895 room_num[room_type]++;
5901 case ROOM_T_LESSER_VAULT:
5902 case ROOM_T_TRAP_PIT:
5910 case ROOM_T_GREATER_VAULT:
5911 case ROOM_T_RANDOM_VAULT:
5920 * Build each type of room one by one until we cannot build any more.
5921 * [from SAngband (originally from OAngband)]
5925 /* Assume no remaining rooms */
5928 for (i = 0; i < ROOM_T_MAX; i++)
5930 /* What type of room are we building now? */
5931 int room_type = room_build_order[i];
5933 /* Go next if none available */
5934 if (!room_num[room_type]) continue;
5936 /* Use up one unit */
5937 room_num[room_type]--;
5939 /* Build the room. */
5940 if (room_build(room_type))
5942 /* Increase the room built count. */
5945 /* Mark as there was some remaining rooms */
5952 case ROOM_T_TRAP_PIT:
5954 /* Avoid too many monsters */
5957 room_num[ROOM_T_PIT] = 0;
5958 room_num[ROOM_T_NEST] = 0;
5959 room_num[ROOM_T_TRAP_PIT] = 0;
5965 /* Avoid double-town */
5966 room_num[ROOM_T_ARCADE] = 0;
5972 /* End loop if no room remain */
5976 /*! @details 部屋生成数が2未満の場合生成失敗を返す */
5977 if (rooms_built < 2)
5979 msg_format_wizard(CHEAT_DUNGEON, _("部屋数が2未満でした。生成を再試行します。", "Number of rooms was under 2. Retry."), rooms_built);
5983 msg_format_wizard(CHEAT_DUNGEON, _("このダンジョンの部屋数は %d です。", "Number of Rooms: %d"), rooms_built);