3 * @brief ダンジョンの生成処理の基幹部分 / low-level dungeon creation primitives
6 * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke\n
8 * This software may be copied and distributed for educational, research,\n
9 * and not for profit purposes provided that this copyright and statement\n
10 * are included in all such copies. Other copyrights may also apply.\n
12 * 2014 Deskull Doxygen向けのコメント整理\n
22 * @brief 新規フロアに入りたてのプレイヤーをランダムな場所に配置する / Returns random co-ordinates for player/monster/object
23 * @return 配置に成功したらTRUEを返す
25 bool new_player_spot(void)
27 POSITION y = 0, x = 0;
28 int max_attempts = 10000;
33 /* Place the player */
34 while (max_attempts--)
36 /* Pick a legal spot */
37 y = (POSITION)rand_range(1, cur_hgt - 2);
38 x = (POSITION)rand_range(1, cur_wid - 2);
42 /* Must be a "naked" floor grid */
43 if (c_ptr->m_idx) continue;
46 f_ptr = &f_info[c_ptr->feat];
48 if (max_attempts > 5000) /* Rule 1 */
50 if (!have_flag(f_ptr->flags, FF_FLOOR)) continue;
54 if (!have_flag(f_ptr->flags, FF_MOVE)) continue;
55 if (have_flag(f_ptr->flags, FF_HIT_TRAP)) continue;
58 /* Refuse to start on anti-teleport grids in dungeon */
59 if (!have_flag(f_ptr->flags, FF_TELEPORTABLE)) continue;
61 if (!player_can_enter(c_ptr->feat, 0)) continue;
62 if (!in_bounds(y, x)) continue;
64 /* Refuse to start on anti-teleport grids */
65 if (c_ptr->info & (CAVE_ICKY)) continue;
70 if (max_attempts < 1) /* Should be -1, actually if we failed... */
73 /* Save the new player grid */
83 * @brief 所定の位置に上り階段か下り階段を配置する / Place an up/down staircase at given location
84 * @param y 配置を試みたいマスのY座標
85 * @param x 配置を試みたいマスのX座標
88 void place_random_stairs(POSITION y, POSITION x)
90 bool up_stairs = TRUE;
91 bool down_stairs = TRUE;
96 if (!is_floor_grid(c_ptr) || c_ptr->o_idx) return;
99 if (!dun_level) up_stairs = FALSE;
102 if (ironman_downward) up_stairs = FALSE;
105 if (dun_level >= d_info[dungeon_type].maxdepth) down_stairs = FALSE;
108 if (quest_number(dun_level) && (dun_level > 1)) down_stairs = FALSE;
110 /* We can't place both */
111 if (down_stairs && up_stairs)
113 /* Choose a staircase randomly */
114 if (randint0(100) < 50) up_stairs = FALSE;
115 else down_stairs = FALSE;
118 /* Place the stairs */
119 if (up_stairs) place_up_stairs(y, x);
120 else if (down_stairs) place_down_stairs(y, x);
124 * @brief 所定の位置にさまざまな状態や種類のドアを配置する / Place a random type of door at the given location
125 * @param y ドアの配置を試みたいマスのY座標
126 * @param x ドアの配置を試みたいマスのX座標
127 * @param room 部屋に接している場合向けのドア生成か否か
130 void place_random_door(POSITION y, POSITION x, bool room)
133 FEAT_IDX feat = feat_none;
134 cave_type *c_ptr = &cave[y][x];
136 /* Initialize mimic info */
139 if (d_info[dungeon_type].flags1 & DF1_NO_DOORS)
141 place_floor_bold(y, x);
145 type = ((d_info[dungeon_type].flags1 & DF1_CURTAIN) &&
146 one_in_((d_info[dungeon_type].flags1 & DF1_NO_CAVE) ? 16 : 256)) ? DOOR_CURTAIN :
147 ((d_info[dungeon_type].flags1 & DF1_GLASS_DOOR) ? DOOR_GLASS_DOOR : DOOR_DOOR);
149 /* Choose an object */
150 tmp = randint0(1000);
152 /* Open doors (300/1000) */
155 /* Create open door */
156 feat = feat_door[type].open;
159 /* Broken doors (100/1000) */
162 /* Create broken door */
163 feat = feat_door[type].broken;
166 /* Secret doors (200/1000) */
169 /* Create secret door */
170 place_closed_door(y, x, type);
172 if (type != DOOR_CURTAIN)
174 /* Hide. If on the edge of room, use outer wall. */
175 c_ptr->mimic = room ? feat_wall_outer : fill_type[randint0(100)];
177 /* Floor type terrain cannot hide a door */
178 if (feat_supports_los(c_ptr->mimic) && !feat_supports_los(c_ptr->feat))
180 if (have_flag(f_info[c_ptr->mimic].flags, FF_MOVE) || have_flag(f_info[c_ptr->mimic].flags, FF_CAN_FLY))
182 c_ptr->feat = one_in_(2) ? c_ptr->mimic : floor_type[randint0(100)];
189 /* Closed, locked, or stuck doors (400/1000) */
190 else place_closed_door(y, x, type);
194 if (feat != feat_none)
196 set_cave_feat(y, x, feat);
200 place_floor_bold(y, x);
204 delete_monster(y, x);
208 * @brief 所定の位置に各種の閉じたドアを配置する / Place a random type of normal door at the given location.
209 * @param y ドアの配置を試みたいマスのY座標
210 * @param x ドアの配置を試みたいマスのX座標
211 * @param type ドアの地形ID
214 void place_closed_door(POSITION y, POSITION x, int type)
217 FEAT_IDX feat = feat_none;
219 if (d_info[dungeon_type].flags1 & DF1_NO_DOORS)
221 place_floor_bold(y, x);
225 /* Choose an object */
228 /* Closed doors (300/400) */
231 /* Create closed door */
232 feat = feat_door[type].closed;
235 /* Locked doors (99/400) */
238 /* Create locked door */
239 feat = feat_locked_door_random(type);
242 /* Stuck doors (1/400) */
245 /* Create jammed door */
246 feat = feat_jammed_door_random(type);
249 if (feat != feat_none)
251 cave_set_feat(y, x, feat);
253 /* Now it is not floor */
254 cave[y][x].info &= ~(CAVE_MASK);
258 place_floor_bold(y, x);
263 * @brief 鍵のかかったドアを配置する
264 * @param y 配置したいフロアのY座標
265 * @param x 配置したいフロアのX座標
268 void place_locked_door(POSITION y, POSITION x)
270 if (d_info[dungeon_type].flags1 & DF1_NO_DOORS)
272 place_floor_bold(y, x);
276 set_cave_feat(y, x, feat_locked_door_random((d_info[dungeon_type].flags1 & DF1_GLASS_DOOR) ? DOOR_GLASS_DOOR : DOOR_DOOR));
277 cave[y][x].info &= ~(CAVE_FLOOR);
278 delete_monster(y, x);
285 * @param y 配置したいフロアのY座標
286 * @param x 配置したいフロアのX座標
287 * @param type DOOR_DEFAULT / DOOR_DOOR / DOOR_GLASS_DOOR / DOOR_CURTAIN のいずれか
290 void place_secret_door(POSITION y, POSITION x, int type)
292 if (d_info[dungeon_type].flags1 & DF1_NO_DOORS)
294 place_floor_bold(y, x);
298 cave_type *c_ptr = &cave[y][x];
300 if (type == DOOR_DEFAULT)
302 type = ((d_info[dungeon_type].flags1 & DF1_CURTAIN) &&
303 one_in_((d_info[dungeon_type].flags1 & DF1_NO_CAVE) ? 16 : 256)) ? DOOR_CURTAIN :
304 ((d_info[dungeon_type].flags1 & DF1_GLASS_DOOR) ? DOOR_GLASS_DOOR : DOOR_DOOR);
307 /* Create secret door */
308 place_closed_door(y, x, type);
310 if (type != DOOR_CURTAIN)
312 /* Hide by inner wall because this is used in rooms only */
313 c_ptr->mimic = feat_wall_inner;
315 /* Floor type terrain cannot hide a door */
316 if (feat_supports_los(c_ptr->mimic) && !feat_supports_los(c_ptr->feat))
318 if (have_flag(f_info[c_ptr->mimic].flags, FF_MOVE) || have_flag(f_info[c_ptr->mimic].flags, FF_CAN_FLY))
320 c_ptr->feat = one_in_(2) ? c_ptr->mimic : floor_type[randint0(100)];
326 c_ptr->info &= ~(CAVE_FLOOR);
327 delete_monster(y, x);
332 * Routine used by the random vault creators to add a door to a location
333 * Note that range checking has to be done in the calling routine.
335 * The doors must be INSIDE the allocated region.
337 void add_door(POSITION x, POSITION y)
339 /* Need to have a wall in the center square */
340 if (!is_outer_bold(y, x)) return;
351 if (is_floor_bold(y - 1, x) && is_floor_bold(y + 1, x) &&
352 (is_outer_bold(y, x - 1) && is_outer_bold(y, x + 1)))
355 place_secret_door(y, x, DOOR_DEFAULT);
357 /* set boundarys so don't get wide doors */
358 place_solid_bold(y, x - 1);
359 place_solid_bold(y, x + 1);
368 * where x = don't care
371 if (is_outer_bold(y - 1, x) && is_outer_bold(y + 1, x) &&
372 is_floor_bold(y, x - 1) && is_floor_bold(y, x + 1))
375 place_secret_door(y, x, DOOR_DEFAULT);
377 /* set boundarys so don't get wide doors */
378 place_solid_bold(y - 1, x);
379 place_solid_bold(y + 1, x);
384 * @brief 隣接4マスに存在する通路の数を返す / Count the number of "corridor" grids adjacent to the given grid.
385 * @param y1 基準となるマスのY座標
386 * @param x1 基準となるマスのX座標
388 * @note Assumes "in_bounds(y1, x1)"
390 * XXX XXX This routine currently only counts actual "empty floor"\n
391 * grids which are not in rooms. We might want to also count stairs,\n
392 * open doors, closed doors, etc.
394 static int next_to_corr(POSITION y1, POSITION x1)
401 /* Scan adjacent grids */
402 for (i = 0; i < 4; i++)
404 /* Extract the location */
409 /* Skip non floors */
410 if (cave_have_flag_grid(c_ptr, FF_WALL)) continue;
412 /* Skip non "empty floor" grids */
413 if (!is_floor_grid(c_ptr))
416 /* Skip grids inside rooms */
417 if (c_ptr->info & (CAVE_ROOM)) continue;
419 /* Count these grids */
423 /* Return the number of corridors */
428 * @brief ドアを設置可能な地形かを返す / Determine if the given location is "between" two walls, and "next to" two corridor spaces.
429 * @param y 判定を行いたいマスのY座標
430 * @param x 判定を行いたいマスのX座標
431 * @return ドアを設置可能ならばTRUEを返す
432 * @note Assumes "in_bounds(y1, x1)"
435 * Assumes "in_bounds(y, x)"\n
437 static bool possible_doorway(POSITION y, POSITION x)
439 /* Count the adjacent corridors */
440 if (next_to_corr(y, x) >= 2)
443 if (cave_have_flag_bold(y - 1, x, FF_WALL) &&
444 cave_have_flag_bold(y + 1, x, FF_WALL))
449 /* Check Horizontal */
450 if (cave_have_flag_bold(y, x - 1, FF_WALL) &&
451 cave_have_flag_bold(y, x + 1, FF_WALL))
462 * @brief ドアの設置を試みる / Places door at y, x position if at least 2 walls found
463 * @param y 設置を行いたいマスのY座標
464 * @param x 設置を行いたいマスのX座標
467 void try_door(POSITION y, POSITION x)
470 if (!in_bounds(y, x)) return;
473 if (cave_have_flag_bold(y, x, FF_WALL)) return;
475 /* Ignore room grids */
476 if (cave[y][x].info & (CAVE_ROOM)) return;
478 /* Occasional door (if allowed) */
479 if ((randint0(100) < dun_tun_jct) && possible_doorway(y, x) && !(d_info[dungeon_type].flags1 & DF1_NO_DOORS))
482 place_random_door(y, x, FALSE);
488 * @brief 長方形の空洞を生成する / Make an empty square floor, for the middle of rooms
489 * @param x1 長方形の左端X座標(-1)
490 * @param x2 長方形の右端X座標(+1)
491 * @param y1 長方形の上端Y座標(-1)
492 * @param y2 長方形の下端Y座標(+1)
496 void place_floor(POSITION x1, POSITION x2, POSITION y1, POSITION y2, bool light)
500 /* Place a full floor under the room */
501 for (y = y1 - 1; y <= y2 + 1; y++)
503 for (x = x1 - 1; x <= x2 + 1; x++)
505 place_floor_bold(y, x);
506 add_cave_info(y, x, CAVE_ROOM);
507 if (light) add_cave_info(y, x, CAVE_GLOW);
514 * @brief 長方形の部屋を生成する / Make an empty square room, only floor and wall grids
515 * @param x1 長方形の左端X座標(-1)
516 * @param x2 長方形の右端X座標(+1)
517 * @param y1 長方形の上端Y座標(-1)
518 * @param y2 長方形の下端Y座標(+1)
522 void place_room(POSITION x1, POSITION x2, POSITION y1, POSITION y2, bool light)
526 place_floor(x1, x2, y1, y2, light);
528 /* Walls around the room */
529 for (y = y1 - 1; y <= y2 + 1; y++)
531 place_outer_bold(y, x1 - 1);
532 place_outer_bold(y, x2 + 1);
534 for (x = x1 - 1; x <= x2 + 1; x++)
536 place_outer_bold(y1 - 1, x);
537 place_outer_bold(y2 + 1, x);
543 * @brief 特殊な部屋向けに各種アイテムを配置する / Create up to "num" objects near the given coordinates
544 * @param y 配置したい中心マスのY座標
545 * @param x 配置したい中心マスのX座標
549 * Only really called by some of the "vault" routines.
551 void vault_objects(POSITION y, POSITION x, int num)
554 int i = 0, j = y, k = x;
559 /* Attempt to place 'num' objects */
560 for (; num > 0; --num)
562 /* Try up to 11 spots looking for empty space */
563 for (i = 0; i < 11; ++i)
565 /* Pick a random location */
566 while (dummy < SAFE_MAX_ATTEMPTS)
568 j = rand_spread(y, 2);
569 k = rand_spread(x, 3);
571 if (!in_bounds(j, k)) continue;
575 if (dummy >= SAFE_MAX_ATTEMPTS && cheat_room)
577 msg_print(_("警告!地下室のアイテムを配置できません!", "Warning! Could not place vault object!"));
580 /* Require "clean" floor space */
582 if (!is_floor_grid(c_ptr) || c_ptr->o_idx) continue;
584 if (randint0(100) < 75)
586 place_object(j, k, 0L);
593 /* Placement accomplished */
600 * @brief 特殊な部屋向けに各種アイテムを配置する(vault_trapのサブセット) / Place a trap with a given displacement of point
601 * @param y トラップを配置したいマスの中心Y座標
602 * @param x トラップを配置したいマスの中心X座標
603 * @param yd Y方向の配置分散マス数
604 * @param xd X方向の配置分散マス数
607 * Only really called by some of the "vault" routines.
609 void vault_trap_aux(POSITION y, POSITION x, POSITION yd, POSITION xd)
611 int count = 0, y1 = y, x1 = x;
617 for (count = 0; count <= 5; count++)
620 while (dummy < SAFE_MAX_ATTEMPTS)
622 y1 = rand_spread(y, yd);
623 x1 = rand_spread(x, xd);
625 if (!in_bounds(y1, x1)) continue;
629 if (dummy >= SAFE_MAX_ATTEMPTS && cheat_room)
631 msg_print(_("警告!地下室のトラップを配置できません!", "Warning! Could not place vault trap!"));
634 /* Require "naked" floor grids */
635 c_ptr = &cave[y1][x1];
636 if (!is_floor_grid(c_ptr) || c_ptr->o_idx || c_ptr->m_idx) continue;
646 * @brief 特殊な部屋向けに各種アイテムを配置する(メインルーチン) / Place some traps with a given displacement of given location
647 * @param y トラップを配置したいマスの中心Y座標
648 * @param x トラップを配置したいマスの中心X座標
649 * @param yd Y方向の配置分散マス数
650 * @param xd X方向の配置分散マス数
651 * @param num 配置したいトラップの数
654 * Only really called by some of the "vault" routines.
656 void vault_traps(POSITION y, POSITION x, POSITION yd, POSITION xd, int num)
660 for (i = 0; i < num; i++)
662 vault_trap_aux(y, x, yd, xd);
667 * @brief 特殊な部屋地形向けにモンスターを配置する / Hack -- Place some sleeping monsters near the given location
668 * @param y1 モンスターを配置したいマスの中心Y座標
669 * @param x1 モンスターを配置したいマスの中心X座標
670 * @param num 配置したいモンスターの数
673 * Only really called by some of the "vault" routines.
675 void vault_monsters(POSITION y1, POSITION x1, int num)
681 /* Try to summon "num" monsters "near" the given location */
682 for (k = 0; k < num; k++)
684 /* Try nine locations */
685 for (i = 0; i < 9; i++)
689 /* Pick a nearby location */
690 scatter(&y, &x, y1, x1, d, 0);
692 /* Require "empty" floor grids */
694 if (!cave_empty_grid(c_ptr)) continue;
696 /* Place the monster (allow groups) */
697 monster_level = base_level + 2;
698 (void)place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
699 monster_level = base_level;
706 * @brief build_tunnel用に通路を掘るための方向を位置関係通りに決める / Always picks a correct direction
707 * @param rdir Y方向に取るべきベクトル値を返す参照ポインタ
708 * @param cdir X方向に取るべきベクトル値を返す参照ポインタ
715 void correct_dir(POSITION *rdir, POSITION *cdir, POSITION y1, POSITION x1, POSITION y2, POSITION x2)
717 /* Extract vertical and horizontal directions */
718 *rdir = (y1 == y2) ? 0 : (y1 < y2) ? 1 : -1;
719 *cdir = (x1 == x2) ? 0 : (x1 < x2) ? 1 : -1;
721 /* Never move diagonally */
724 if (randint0(100) < 50)
732 * @brief build_tunnel用に通路を掘るための方向をランダムに決める / Pick a random direction
733 * @param rdir Y方向に取るべきベクトル値を返す参照ポインタ
734 * @param cdir X方向に取るべきベクトル値を返す参照ポインタ
737 void rand_dir(POSITION *rdir, POSITION *cdir)
739 /* Pick a random direction */
742 /* Extract the dy/dx components */
748 * @brief 指定のマスが床系地形であるかを返す / Function that sees if a square is a floor. (Includes range checking.)
749 * @param x チェックするマスのX座標
750 * @param y チェックするマスのY座標
751 * @return 床系地形ならばTRUE
753 bool get_is_floor(POSITION x, POSITION y)
755 if (!in_bounds(y, x))
761 /* Do the real check */
762 if (is_floor_bold(y, x)) return (TRUE);
768 * @brief 指定のマスを床地形に変える / Set a square to be floor. (Includes range checking.)
769 * @param x 地形を変えたいマスのX座標
770 * @param y 地形を変えたいマスのY座標
773 void set_floor(POSITION x, POSITION y)
775 if (!in_bounds(y, x))
781 if (cave[y][x].info & CAVE_ROOM)
783 /* A room border don't touch. */
787 /* Set to be floor if is a wall (don't touch lakes). */
788 if (is_extra_bold(y, x))
789 place_floor_bold(y, x);