X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=src%2Fgenerate.c;h=77d28990509cf2d110b0d87992f36868b32b8262;hb=cca4b64b4b587d1857334815d94b2d3253a10f10;hp=dac60fe1c693dd3cac3c825402cc815e1ed095a6;hpb=a3a421d67e9ce00712a478fdf81877bba0a26ae5;p=hengband%2Fhengband.git diff --git a/src/generate.c b/src/generate.c index dac60fe1c..77d289905 100644 --- a/src/generate.c +++ b/src/generate.c @@ -1,101 +1,99 @@ -/* File: generate.c */ - -/* - * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke - * - * This software may be copied and distributed for educational, research, - * and not for profit purposes provided that this copyright and statement - * are included in all such copies. Other copyrights may also apply. - */ - -/* Purpose: Dungeon generation */ - -/* - * Note that Level generation is *not* an important bottleneck, - * though it can be annoyingly slow on older machines... Thus - * we emphasize "simplicity" and "correctness" over "speed". - * - * This entire file is only needed for generating levels. - * This may allow smart compilers to only load it when needed. - * - * Consider the "v_info.txt" file for vault generation. - * - * In this file, we use the "special" granite and perma-wall sub-types, - * where "basic" is normal, "inner" is inside a room, "outer" is the - * outer wall of a room, and "solid" is the outer wall of the dungeon - * or any walls that may not be pierced by corridors. Thus the only - * wall type that may be pierced by a corridor is the "outer granite" - * type. The "basic granite" type yields the "actual" corridors. - * - * Note that we use the special "solid" granite wall type to prevent - * multiple corridors from piercing a wall in two adjacent locations, - * which would be messy, and we use the special "outer" granite wall - * to indicate which walls "surround" rooms, and may thus be "pierced" - * by corridors entering or leaving the room. - * - * Note that a tunnel which attempts to leave a room near the "edge" - * of the dungeon in a direction toward that edge will cause "silly" - * wall piercings, but will have no permanently incorrect effects, - * as long as the tunnel can *eventually* exit from another side. - * And note that the wall may not come back into the room by the - * hole it left through, so it must bend to the left or right and - * then optionally re-enter the room (at least 2 grids away). This - * is not a problem since every room that is large enough to block - * the passage of tunnels is also large enough to allow the tunnel - * to pierce the room itself several times. - * - * Note that no two corridors may enter a room through adjacent grids, - * they must either share an entryway or else use entryways at least - * two grids apart. This prevents "large" (or "silly") doorways. - * - * To create rooms in the dungeon, we first divide the dungeon up - * into "blocks" of 11x11 grids each, and require that all rooms - * occupy a rectangular group of blocks. As long as each room type - * reserves a sufficient number of blocks, the room building routines - * will not need to check bounds. Note that most of the normal rooms - * actually only use 23x11 grids, and so reserve 33x11 grids. - * - * Note that the use of 11x11 blocks (instead of the old 33x11 blocks) - * allows more variability in the horizontal placement of rooms, and - * at the same time has the disadvantage that some rooms (two thirds - * of the normal rooms) may be "split" by panel boundaries. This can - * induce a situation where a player is in a room and part of the room - * is off the screen. It may be annoying enough to go back to 33x11 - * blocks to prevent this visual situation. - * - * Note that the dungeon generation routines are much different (2.7.5) - * and perhaps "DUN_ROOMS" should be less than 50. - * - * XXX XXX XXX Note that it is possible to create a room which is only - * connected to itself, because the "tunnel generation" code allows a - * tunnel to leave a room, wander around, and then re-enter the room. - * - * XXX XXX XXX Note that it is possible to create a set of rooms which - * are only connected to other rooms in that set, since there is nothing - * explicit in the code to prevent this from happening. But this is less - * likely than the "isolated room" problem, because each room attempts to - * connect to another room, in a giant cycle, thus requiring at least two - * bizarre occurances to create an isolated section of the dungeon. - * - * Note that (2.7.9) monster pits have been split into monster "nests" - * and monster "pits". The "nests" have a collection of monsters of a - * given type strewn randomly around the room (jelly, animal, or undead), - * while the "pits" have a collection of monsters of a given type placed - * around the room in an organized manner (orc, troll, giant, dragon, or - * demon). Note that both "nests" and "pits" are now "level dependant", - * and both make 16 "expensive" calls to the "get_mon_num()" function. - * - * Note that the cave grid flags changed in a rather drastic manner - * for Angband 2.8.0 (and 2.7.9+), in particular, dungeon terrain - * features, such as doors and stairs and traps and rubble and walls, - * are all handled as a set of 64 possible "terrain features", and - * not as "fake" objects (440-479) as in pre-2.8.0 versions. - * - * The 64 new "dungeon features" will also be used for "visual display" - * but we must be careful not to allow, for example, the user to display - * hidden traps in a different way from floors, or secret doors in a way - * different from granite walls, or even permanent granite in a different - * way from granite. XXX XXX XXX +/*! + * @file generate.c + * @brief ダンジョンの生成 / Dungeon generation + * @date 2014/01/04 + * @author + * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke\n + * This software may be copied and distributed for educational, research,\n + * and not for profit purposes provided that this copyright and statement\n + * are included in all such copies. Other copyrights may also apply.\n + * 2014 Deskull rearranged comment for Doxygen. \n + * @details + * Note that Level generation is *not* an important bottleneck,\n + * though it can be annoyingly slow on older machines... Thus\n + * we emphasize "simplicity" and "correctness" over "speed".\n + *\n + * This entire file is only needed for generating levels.\n + * This may allow smart compilers to only load it when needed.\n + *\n + * Consider the "v_info.txt" file for vault generation.\n + *\n + * In this file, we use the "special" granite and perma-wall sub-types,\n + * where "basic" is normal, "inner" is inside a room, "outer" is the\n + * outer wall of a room, and "solid" is the outer wall of the dungeon\n + * or any walls that may not be pierced by corridors. Thus the only\n + * wall type that may be pierced by a corridor is the "outer granite"\n + * type. The "basic granite" type yields the "actual" corridors.\n + *\n + * Note that we use the special "solid" granite wall type to prevent\n + * multiple corridors from piercing a wall in two adjacent locations,\n + * which would be messy, and we use the special "outer" granite wall\n + * to indicate which walls "surround" rooms, and may thus be "pierced"\n + * by corridors entering or leaving the room.\n + *\n + * Note that a tunnel which attempts to leave a room near the "edge"\n + * of the dungeon in a direction toward that edge will cause "silly"\n + * wall piercings, but will have no permanently incorrect effects,\n + * as long as the tunnel can *eventually* exit from another side.\n + * And note that the wall may not come back into the room by the\n + * hole it left through, so it must bend to the left or right and\n + * then optionally re-enter the room (at least 2 grids away). This\n + * is not a problem since every room that is large enough to block\n + * the passage of tunnels is also large enough to allow the tunnel\n + * to pierce the room itself several times.\n + *\n + * Note that no two corridors may enter a room through adjacent grids,\n + * they must either share an entryway or else use entryways at least\n + * two grids apart. This prevents "large" (or "silly") doorways.\n + *\n + * To create rooms in the dungeon, we first divide the dungeon up\n + * into "blocks" of 11x11 grids each, and require that all rooms\n + * occupy a rectangular group of blocks. As long as each room type\n + * reserves a sufficient number of blocks, the room building routines\n + * will not need to check bounds. Note that most of the normal rooms\n + * actually only use 23x11 grids, and so reserve 33x11 grids.\n + *\n + * Note that the use of 11x11 blocks (instead of the old 33x11 blocks)\n + * allows more variability in the horizontal placement of rooms, and\n + * at the same time has the disadvantage that some rooms (two thirds\n + * of the normal rooms) may be "split" by panel boundaries. This can\n + * induce a situation where a player is in a room and part of the room\n + * is off the screen. It may be annoying enough to go back to 33x11\n + * blocks to prevent this visual situation.\n + *\n + * Note that the dungeon generation routines are much different (2.7.5)\n + * and perhaps "DUN_ROOMS" should be less than 50.\n + *\n + * XXX XXX XXX Note that it is possible to create a room which is only\n + * connected to itself, because the "tunnel generation" code allows a\n + * tunnel to leave a room, wander around, and then re-enter the room.\n + *\n + * XXX XXX XXX Note that it is possible to create a set of rooms which\n + * are only connected to other rooms in that set, since there is nothing\n + * explicit in the code to prevent this from happening. But this is less\n + * likely than the "isolated room" problem, because each room attempts to\n + * connect to another room, in a giant cycle, thus requiring at least two\n + * bizarre occurances to create an isolated section of the dungeon.\n + *\n + * Note that (2.7.9) monster pits have been split into monster "nests"\n + * and monster "pits". The "nests" have a collection of monsters of a\n + * given type strewn randomly around the room (jelly, animal, or undead),\n + * while the "pits" have a collection of monsters of a given type placed\n + * around the room in an organized manner (orc, troll, giant, dragon, or\n + * demon). Note that both "nests" and "pits" are now "level dependant",\n + * and both make 16 "expensive" calls to the "get_mon_num()" function.\n + *\n + * Note that the cave grid flags changed in a rather drastic manner\n + * for Angband 2.8.0 (and 2.7.9+), in particular, dungeon terrain\n + * features, such as doors and stairs and traps and rubble and walls,\n + * are all handled as a set of 64 possible "terrain features", and\n + * not as "fake" objects (440-479) as in pre-2.8.0 versions.\n + *\n + * The 64 new "dungeon features" will also be used for "visual display"\n + * but we must be careful not to allow, for example, the user to display\n + * hidden traps in a different way from floors, or secret doors in a way\n + * different from granite walls, or even permanent granite in a different\n + * way from granite. XXX XXX XXX\n */ #include "angband.h" @@ -104,38 +102,86 @@ #include "rooms.h" #include "streams.h" -int dun_rooms; - -int dun_tun_rnd; +int dun_tun_rnd; int dun_tun_chg; int dun_tun_con; int dun_tun_pen; int dun_tun_jct; -/* +/*! * Dungeon generation data -- see "cave_gen()" */ dun_data *dun; -/* - * Places some staircases near walls + +/*! + * @brief 上下左右の外壁数をカウントする / Count the number of walls adjacent to the given grid. + * @param y 基準のy座標 + * @param x 基準のx座標 + * @return 隣接する外壁の数 + * @note Assumes "in_bounds(y, x)" + * @details We count only granite walls and permanent walls. + */ +static int next_to_walls(int y, int x) +{ + int k = 0; + + if (in_bounds(y + 1, x) && is_extra_bold(y + 1, x)) k++; + if (in_bounds(y - 1, x) && is_extra_bold(y - 1, x)) k++; + if (in_bounds(y, x + 1) && is_extra_bold(y, x + 1)) k++; + if (in_bounds(y, x - 1) && is_extra_bold(y, x - 1)) k++; + + return (k); +} + +/*! + * @brief alloc_stairs()の補助として指定の位置に階段を生成できるかの判定を行う / Helper function for alloc_stairs(). Is this a good location for stairs? + * @param y 基準のy座標 + * @param x 基準のx座標 + * @param walls 最低減隣接させたい外壁の数 + * @return 階段を生成して問題がないならばTRUEを返す。 + */ +static bool alloc_stairs_aux(int y, int x, int walls) +{ + /* Access the grid */ + cave_type *c_ptr = &cave[y][x]; + + /* Require "naked" floor grid */ + if (!is_floor_grid(c_ptr)) return FALSE; + if (pattern_tile(y, x)) return FALSE; + if (c_ptr->o_idx || c_ptr->m_idx) return FALSE; + + /* Require a certain number of adjacent walls */ + if (next_to_walls(y, x) < walls) return FALSE; + + return TRUE; +} + + +/*! + * @brief 外壁に隣接させて階段を生成する / Places some staircases near walls + * @param feat 配置したい地形ID + * @param num 配置したい階段の数 + * @param walls 最低減隣接させたい外壁の数 + * @return 規定数通りに生成に成功したらTRUEを返す。 */ static bool alloc_stairs(int feat, int num, int walls) { - int y, x, i, j, flag; - int more_num = 0; - cave_type *c_ptr; + int i; + int shaft_num = 0; + + feature_type *f_ptr = &f_info[feat]; - if (feat == FEAT_LESS) + if (have_flag(f_ptr->flags, FF_LESS)) { /* No up stairs in town or in ironman mode */ if (ironman_downward || !dun_level) return TRUE; if (dun_level > d_info[dungeon_type].mindepth) - more_num = (randint1(num+1))/2; + shaft_num = (randint1(num+1))/2; } - else if (feat == FEAT_MORE) + else if (have_flag(f_ptr->flags, FF_MORE)) { int q_idx = quest_number(dun_level); @@ -153,53 +199,91 @@ static bool alloc_stairs(int feat, int num, int walls) if (dun_level >= d_info[dungeon_type].maxdepth) return TRUE; if ((dun_level < d_info[dungeon_type].maxdepth-1) && !quest_number(dun_level+1)) - more_num = (randint1(num)+1)/2; + shaft_num = (randint1(num)+1)/2; } + /* Paranoia */ + else return FALSE; + + /* Place "num" stairs */ for (i = 0; i < num; i++) { - /* Place some stairs */ - for (flag = FALSE; !flag; ) + while (TRUE) { - /* Try several times, then decrease "walls" */ - for (j = 0; !flag && j <= 3000; j++) + int y = 0, x = 0; + cave_type *c_ptr; + + int candidates = 0; + int pick; + + for (y = 1; y < cur_hgt - 1; y++) { - /* Pick a random grid */ - y = randint1(cur_hgt-2); - x = randint1(cur_wid-2); + for (x = 1; x < cur_wid - 1; x++) + { + if (alloc_stairs_aux(y, x, walls)) + { + /* A valid space found */ + candidates++; + } + } + } - /* Access the grid */ - c_ptr = &cave[y][x]; + /* No valid place! */ + if (!candidates) + { + /* There are exactly no place! */ + if (walls <= 0) return FALSE; - /* Require "naked" floor grid */ - if (!is_floor_grid(c_ptr) || pattern_tile(y,x) || c_ptr->o_idx || c_ptr->m_idx) continue; + /* Decrease walls limit, and try again */ + walls--; + continue; + } - /* Require a certain number of adjacent walls */ - if (next_to_walls(y, x) < walls) continue; + /* Choose a random one */ + pick = randint1(candidates); - /* Clear possible garbage of hidden trap */ - c_ptr->mimic = 0; + for (y = 1; y < cur_hgt - 1; y++) + { + for (x = 1; x < cur_wid - 1; x++) + { + if (alloc_stairs_aux(y, x, walls)) + { + pick--; - /* Clear previous contents, add stairs */ - if (i < more_num) c_ptr->feat = feat+0x07; - else c_ptr->feat = feat; + /* Is this a picked one? */ + if (!pick) break; + } + } - /* All done */ - flag = TRUE; + if (!pick) break; } - if (!flag) return FALSE; - /* Require fewer walls */ - if (walls) walls--; + /* Access the grid */ + c_ptr = &cave[y][x]; + + /* Clear possible garbage of hidden trap */ + c_ptr->mimic = 0; + + /* Clear previous contents, add stairs */ + c_ptr->feat = (i < shaft_num) ? feat_state(feat, FF_SHAFT) : feat; + + /* No longer "FLOOR" */ + c_ptr->info &= ~(CAVE_FLOOR); + + /* Success */ + break; } } return TRUE; } - -/* - * Allocates some objects (using "place" and "type") +/*! + * @brief フロア上のランダム位置に各種オブジェクトを配置する / Allocates some objects (using "place" and "type") + * @param set 配置したい地形の種類 + * @param typ 配置したいオブジェクトの種類 + * @param num 配置したい数 + * @return 規定数通りに生成に成功したらTRUEを返す。 */ static void alloc_object(int set, int typ, int num) { @@ -207,6 +291,9 @@ static void alloc_object(int set, int typ, int num) int dummy = 0; cave_type *c_ptr; + /* A small level has few objects. */ + num = num * cur_hgt * cur_wid / (MAX_HGT*MAX_WID) +1; + /* Place some objects */ for (k = 0; k < num; k++) { @@ -227,7 +314,7 @@ static void alloc_object(int set, int typ, int num) if (!is_floor_grid(c_ptr) || c_ptr->o_idx || c_ptr->m_idx) continue; /* Avoid player location */ - if (py == y && px == x) continue; + if (player_bold(y, x)) continue; /* Check for "room" */ room = (cave[y][x].info & CAVE_ROOM) ? TRUE : FALSE; @@ -247,7 +334,7 @@ static void alloc_object(int set, int typ, int num) if (cheat_room) { #ifdef JP -msg_print("·Ù¹ð¡ª¥¢¥¤¥Æ¥à¤òÇÛÃ֤Ǥ­¤Þ¤»¤ó¡ª"); +msg_print("警告!アイテムを配置できません!"); #else msg_print("Warning! Could not place object!"); #endif @@ -289,14 +376,15 @@ msg_print(" } } - -/* - * Count the number of "corridor" grids adjacent to the given grid. - * - * Note -- Assumes "in_bounds(y1, x1)" - * - * XXX XXX This routine currently only counts actual "empty floor" - * grids which are not in rooms. We might want to also count stairs, +/*! + * @brief 隣接4マスに存在する通路の数を返す / Count the number of "corridor" grids adjacent to the given grid. + * @param y1 基準となるマスのY座標 + * @param x1 基準となるマスのX座標 + * @return 通路の数 + * @note Assumes "in_bounds(y1, x1)" + * @details + * XXX XXX This routine currently only counts actual "empty floor"\n + * grids which are not in rooms. We might want to also count stairs,\n * open doors, closed doors, etc. */ static int next_to_corr(int y1, int x1) @@ -316,7 +404,7 @@ static int next_to_corr(int y1, int x1) c_ptr = &cave[y][x]; /* Skip non floors */ - if (!cave_floor_grid(c_ptr)) continue; + if (cave_have_flag_grid(c_ptr, FF_WALL)) continue; /* Skip non "empty floor" grids */ if (!is_floor_grid(c_ptr)) @@ -334,11 +422,15 @@ static int next_to_corr(int y1, int x1) } -/* - * Determine if the given location is "between" two walls, - * and "next to" two corridor spaces. XXX XXX XXX - * - * Assumes "in_bounds(y, x)" +/*! + * @brief ドアを設置可能な地形かを返す / Determine if the given location is "between" two walls, and "next to" two corridor spaces. + * @param y 判定を行いたいマスのY座標 + * @param x 判定を行いたいマスのX座標 + * @return ドアを設置可能ならばTRUEを返す + * @note Assumes "in_bounds(y1, x1)" + * @details + * XXX XXX XXX\n + * Assumes "in_bounds(y, x)"\n */ static bool possible_doorway(int y, int x) { @@ -346,15 +438,15 @@ static bool possible_doorway(int y, int x) if (next_to_corr(y, x) >= 2) { /* Check Vertical */ - if ((cave[y-1][x].feat >= FEAT_MAGMA) && - (cave[y+1][x].feat >= FEAT_MAGMA)) + if (cave_have_flag_bold(y - 1, x, FF_WALL) && + cave_have_flag_bold(y + 1, x, FF_WALL)) { return (TRUE); } /* Check Horizontal */ - if ((cave[y][x-1].feat >= FEAT_MAGMA) && - (cave[y][x+1].feat >= FEAT_MAGMA)) + if (cave_have_flag_bold(y, x - 1, FF_WALL) && + cave_have_flag_bold(y, x + 1, FF_WALL)) { return (TRUE); } @@ -364,9 +456,11 @@ static bool possible_doorway(int y, int x) return (FALSE); } - -/* - * Places door at y, x position if at least 2 walls found +/*! + * @brief ドアの設置を試みる / Places door at y, x position if at least 2 walls found + * @param y 設置を行いたいマスのY座標 + * @param x 設置を行いたいマスのX座標 + * @return なし */ static void try_door(int y, int x) { @@ -374,7 +468,7 @@ static void try_door(int y, int x) if (!in_bounds(y, x)) return; /* Ignore walls */ - if (!cave_floor_bold(y, x)) return; + if (cave_have_flag_bold(y, x, FF_WALL)) return; /* Ignore room grids */ if (cave[y][x].info & (CAVE_ROOM)) return; @@ -388,8 +482,11 @@ static void try_door(int y, int x) } -/* Place quest monsters */ -void place_quest_monsters(void) +/*! + * @brief クエストに関わるモンスターの配置を行う / Place quest monsters + * @return 成功したならばTRUEを返す + */ +bool place_quest_monsters(void) { int i; @@ -399,7 +496,7 @@ void place_quest_monsters(void) monster_race *r_ptr; u32b mode; int j; - + if (quest[i].status != QUEST_STATUS_TAKEN || (quest[i].type != QUEST_TYPE_KILL_LEVEL && quest[i].type != QUEST_TYPE_RANDOM) || @@ -428,25 +525,30 @@ void place_quest_monsters(void) for (k = 0; k < SAFE_MAX_ATTEMPTS; k++) { - int x, y; + int x = 0, y = 0; int l; /* Find an empty grid */ for (l = SAFE_MAX_ATTEMPTS; l > 0; l--) { - cave_type *c_ptr; + cave_type *c_ptr; + feature_type *f_ptr; y = randint0(cur_hgt); x = randint0(cur_wid); + c_ptr = &cave[y][x]; + f_ptr = &f_info[c_ptr->feat]; - if (!cave_floor_grid(c_ptr) || c_ptr->o_idx || c_ptr->m_idx) continue; - if (distance(y, x, py, px) < 10) continue; + if (!have_flag(f_ptr->flags, FF_MOVE) && !have_flag(f_ptr->flags, FF_CAN_FLY)) continue; + if (!monster_can_enter(y, x, r_ptr, 0)) continue; + if (distance(y, x, p_ptr->y, p_ptr->x) < 10) continue; + if (c_ptr->info & CAVE_ICKY) continue; else break; } /* Failed to place */ - if (!l) break; + if (!l) return FALSE; /* Try to place the monster */ if (place_monster_aux(0, y, x, quest[i].r_idx, mode)) @@ -460,53 +562,171 @@ void place_quest_monsters(void) continue; } } + + /* Failed to place */ + if (k == SAFE_MAX_ATTEMPTS) return FALSE; } } + + return TRUE; } -/* - * Generate a new dungeon level - * - * Note that "dun_body" adds about 4000 bytes of memory to the stack. +/*! + * @brief マスにフロア端用の永久壁を配置する / Set boundary mimic and add "solid" perma-wall + * @param c_ptr 永久壁を廃止したいマス構造体の参照ポインタ + * @return なし */ -static bool cave_gen(void) +static void set_bound_perm_wall(cave_type *c_ptr) { - int i, j, k, y, x, y1, x1; + if (bound_walls_perm) + { + /* Clear boundary mimic */ + c_ptr->mimic = 0; + } + else + { + feature_type *f_ptr = &f_info[c_ptr->feat]; - int max_vault_ok = 2; + /* Hack -- Decline boundary walls with known treasure */ + if ((have_flag(f_ptr->flags, FF_HAS_GOLD) || have_flag(f_ptr->flags, FF_HAS_ITEM)) && + !have_flag(f_ptr->flags, FF_SECRET)) + c_ptr->feat = feat_state(c_ptr->feat, FF_ENSECRET); - int feat1 = 0, feat2 = 0; + /* Set boundary mimic */ + c_ptr->mimic = c_ptr->feat; + } - cave_type *c_ptr; + /* Add "solid" perma-wall */ + place_solid_perm_grid(c_ptr); +} - bool destroyed = FALSE; - bool empty_level = FALSE; - bool cavern = FALSE; - int laketype = 0; +/*! + * @brief フロアに洞窟や湖を配置する / Generate various caverns and lakes + * @details There were moved from cave_gen(). + * @return なし + */ +static void gen_caverns_and_lakes(void) +{ +#ifdef ALLOW_CAVERNS_AND_LAKES + /* Possible "destroyed" level */ + if ((dun_level > 30) && one_in_(DUN_DEST*2) && (small_levels) && (d_info[dungeon_type].flags1 & DF1_DESTROY)) + { + dun->destroyed = TRUE; + /* extra rubble around the place looks cool */ + build_lake(one_in_(2) ? LAKE_T_CAVE : LAKE_T_EARTH_VAULT); + } - dun_data dun_body; + /* Make a lake some of the time */ + if (one_in_(LAKE_LEVEL) && !dun->empty_level && !dun->destroyed && + (d_info[dungeon_type].flags1 & DF1_LAKE_MASK)) + { + int count = 0; + if (d_info[dungeon_type].flags1 & DF1_LAKE_WATER) count += 3; + if (d_info[dungeon_type].flags1 & DF1_LAKE_LAVA) count += 3; + if (d_info[dungeon_type].flags1 & DF1_LAKE_RUBBLE) count += 3; + if (d_info[dungeon_type].flags1 & DF1_LAKE_TREE) count += 3; - /* Fill the arrays of floors and walls in the good proportions */ - set_floor_and_wall(dungeon_type); + if (d_info[dungeon_type].flags1 & DF1_LAKE_LAVA) + { + /* Lake of Lava */ + if ((dun_level > 80) && (randint0(count) < 2)) dun->laketype = LAKE_T_LAVA; + count -= 2; + /* Lake of Lava2 */ + if (!dun->laketype && (dun_level > 80) && one_in_(count)) dun->laketype = LAKE_T_FIRE_VAULT; + count--; + } - /* Prepare allocation table */ - get_mon_num_prep(get_monster_hook(), NULL); + if ((d_info[dungeon_type].flags1 & DF1_LAKE_WATER) && !dun->laketype) + { + /* Lake of Water */ + if ((dun_level > 50) && randint0(count) < 2) dun->laketype = LAKE_T_WATER; + count -= 2; - feat_wall_outer = d_info[dungeon_type].outer_wall; - feat_wall_inner = d_info[dungeon_type].inner_wall; - feat_wall_solid = d_info[dungeon_type].outer_wall; + /* Lake of Water2 */ + if (!dun->laketype && (dun_level > 50) && one_in_(count)) dun->laketype = LAKE_T_WATER_VAULT; + count--; + } + + if ((d_info[dungeon_type].flags1 & DF1_LAKE_RUBBLE) && !dun->laketype) + { + /* Lake of rubble */ + if ((dun_level > 35) && (randint0(count) < 2)) dun->laketype = LAKE_T_CAVE; + count -= 2; + + /* Lake of rubble2 */ + if (!dun->laketype && (dun_level > 35) && one_in_(count)) dun->laketype = LAKE_T_EARTH_VAULT; + count--; + } + + /* Lake of tree */ + if ((dun_level > 5) && (d_info[dungeon_type].flags1 & DF1_LAKE_TREE) && !dun->laketype) dun->laketype = LAKE_T_AIR_VAULT; + + if (dun->laketype) + { + if (cheat_room) +#ifdef JP + msg_print("湖を生成。"); +#else + msg_print("Lake on the level."); +#endif + + build_lake(dun->laketype); + } + } + + if ((dun_level > DUN_CAVERN) && !dun->empty_level && + (d_info[dungeon_type].flags1 & DF1_CAVERN) && + !dun->laketype && !dun->destroyed && (randint1(1000) < dun_level)) + { + dun->cavern = TRUE; + + /* make a large fractal cave in the middle of the dungeon */ + + if (cheat_room) +#ifdef JP + msg_print("洞窟を生成。"); +#else + msg_print("Cavern on level."); +#endif + + build_cavern(); + } +#endif /* ALLOW_CAVERNS_AND_LAKES */ + + /* Hack -- No destroyed "quest" levels */ + if (quest_number(dun_level)) dun->destroyed = FALSE; +} + + +/*! + * @brief ダンジョン生成のメインルーチン / Generate a new dungeon level + * @details Note that "dun_body" adds about 4000 bytes of memory to the stack. + * @return ダンジョン生成が全て無事に成功したらTRUEを返す。 + */ +static bool cave_gen(void) +{ + int i, k, y, x; + + dun_data dun_body; /* Global data */ dun = &dun_body; - if (cur_hgt <= SCREEN_HGT / 2 - 2) max_vault_ok--; - if (cur_wid <= SCREEN_WID / 2 - 2) max_vault_ok--; + dun->destroyed = FALSE; + dun->empty_level = FALSE; + dun->cavern = FALSE; + dun->laketype = 0; + + /* Fill the arrays of floors and walls in the good proportions */ + set_floor_and_wall(dungeon_type); + + /* Prepare allocation table */ + get_mon_num_prep(get_monster_hook(), NULL); /* Randomize the dungeon creation values */ - dun_rooms = rand_range(DUN_ROOMS_MIN, DUN_ROOMS_MAX); dun_tun_rnd = rand_range(DUN_TUN_RND_MIN, DUN_TUN_RND_MAX); dun_tun_chg = rand_range(DUN_TUN_CHG_MIN, DUN_TUN_CHG_MAX); dun_tun_con = rand_range(DUN_TUN_CON_MIN, DUN_TUN_CON_MAX); @@ -526,26 +746,23 @@ static bool cave_gen(void) } } - /* No "crowded" rooms yet */ - dun->crowded = 0; - /* No rooms yet */ dun->cent_n = 0; /* Empty arena levels */ if (ironman_empty_levels || ((d_info[dungeon_type].flags1 & DF1_ARENA) && (empty_levels && one_in_(EMPTY_LEVEL)))) { - empty_level = TRUE; + dun->empty_level = TRUE; if (cheat_room) #ifdef JP - msg_print("¥¢¥ê¡¼¥Ê¥ì¥Ù¥ë"); + msg_print("アリーナレベル"); #else msg_print("Arena level."); #endif } - if (empty_level) + if (dun->empty_level) { /* Start with floors */ for (y = 0; y < cur_hgt; y++) @@ -582,96 +799,10 @@ static bool cave_gen(void) } } -#ifdef ALLOW_CAVERNS_AND_LAKES - /* Possible "destroyed" level */ - if ((dun_level > 30) && one_in_(DUN_DEST*2) && (small_levels) && (d_info[dungeon_type].flags1 & DF1_DESTROY)) - { - destroyed = TRUE; - /* extra rubble around the place looks cool */ - build_lake(one_in_(2) ? GEN_LAKE_TYPE_CAVE : GEN_LAKE_TYPE_EARTH_VAULT); - } + /* Generate various caverns and lakes */ + gen_caverns_and_lakes(); - /* Make a lake some of the time */ - if (one_in_(LAKE_LEVEL) && !empty_level && !destroyed && - (d_info[dungeon_type].flags1 & DF1_LAKE_MASK)) - { - int count = 0; - if (d_info[dungeon_type].flags1 & DF1_LAKE_WATER) count += 3; - if (d_info[dungeon_type].flags1 & DF1_LAKE_LAVA) count += 3; - if (d_info[dungeon_type].flags1 & DF1_LAKE_RUBBLE) count += 3; - if (d_info[dungeon_type].flags1 & DF1_LAKE_TREE) count += 3; - - if (d_info[dungeon_type].flags1 & DF1_LAKE_LAVA) - { - /* Lake of Lava */ - if ((dun_level > 80) && (randint0(count) < 2)) laketype = GEN_LAKE_TYPE_LAVA; - count -= 2; - - /* Lake of Lava2 */ - if (!laketype && (dun_level > 80) && one_in_(count)) laketype = GEN_LAKE_TYPE_FIRE_VAULT; - count--; - } - - if ((d_info[dungeon_type].flags1 & DF1_LAKE_WATER) && !laketype) - { - /* Lake of Water */ - if ((dun_level > 50) && randint0(count) < 2) laketype = GEN_LAKE_TYPE_WATER; - count -= 2; - - /* Lake of Water2 */ - if (!laketype && (dun_level > 50) && one_in_(count)) laketype = GEN_LAKE_TYPE_WATER_VAULT; - count--; - } - - if ((d_info[dungeon_type].flags1 & DF1_LAKE_RUBBLE) && !laketype) - { - /* Lake of rubble */ - if ((dun_level > 35) && (randint0(count) < 2)) laketype = GEN_LAKE_TYPE_CAVE; - count -= 2; - - /* Lake of rubble2 */ - if (!laketype && (dun_level > 35) && one_in_(count)) laketype = GEN_LAKE_TYPE_EARTH_VAULT; - count--; - } - - /* Lake of tree */ - if ((dun_level > 5) && (d_info[dungeon_type].flags1 & DF1_LAKE_TREE) && !laketype) laketype = GEN_LAKE_TYPE_AIR_VAULT; - - if (laketype) - { - if (cheat_room) -#ifdef JP - msg_print("¸Ð¤òÀ¸À®¡£"); -#else - msg_print("Lake on the level."); -#endif - - build_lake(laketype); - } - } - - if ((dun_level > DUN_CAVERN) && !empty_level && - (d_info[dungeon_type].flags1 & DF1_CAVERN) && - !laketype && !destroyed && (randint1(1000) < dun_level)) - { - cavern = TRUE; - - /* make a large fractal cave in the middle of the dungeon */ - - if (cheat_room) -#ifdef JP - msg_print("ƶ·¢¤òÀ¸À®¡£"); -#else - msg_print("Cavern on level."); -#endif - - build_cavern(); - } -#endif /* ALLOW_CAVERNS_AND_LAKES */ - - /* Hack -- No destroyed "quest" levels */ - if (quest_number(dun_level)) destroyed = FALSE; /* Build maze */ if (d_info[dungeon_type].flags1 & DF1_MAZE) @@ -679,145 +810,22 @@ static bool cave_gen(void) build_maze_vault(cur_wid/2-1, cur_hgt/2-1, cur_wid-4, cur_hgt-4, FALSE); /* Place 3 or 4 down stairs near some walls */ - if (!alloc_stairs(FEAT_MORE, rand_range(2, 3), 3)) return FALSE; + if (!alloc_stairs(feat_down_stair, rand_range(2, 3), 3)) return FALSE; /* Place 1 or 2 up stairs near some walls */ - if (!alloc_stairs(FEAT_LESS, 1, 3)) return FALSE; + if (!alloc_stairs(feat_up_stair, 1, 3)) return FALSE; } /* Build some rooms */ else { - for (i = 0; i < dun_rooms; i++) - { - bool force_rooms = (ironman_rooms && !((d_info[dungeon_type].flags1 & DF1_BEGINNER) || (d_info[dungeon_type].flags1 & DF1_CHAMELEON))); - - /* Pick a block for the room */ - y = randint0(dun->row_rooms); - x = randint0(dun->col_rooms); - - /* Align dungeon rooms */ - if (d_info[dungeon_type].flags1 & DF1_NO_CAVE) - { - /* Slide some rooms right */ - if ((x % 3) == 0) x++; - - /* Slide some rooms left */ - if ((x % 3) == 2) x--; - } - - /* Attempt an "unusual" room */ - if (force_rooms || (randint0(DUN_UNUSUAL) < dun_level)) - { - /* Roll for room type */ - while (1) - { - k = (force_rooms ? 0 : randint0(100)); - if (force_rooms) break; - if ((d_info[dungeon_type].flags1 & DF1_NO_VAULT) && (k < 14)) continue; - break; - } - - /* Attempt a very unusual room */ - if (force_rooms || (randint0(DUN_UNUSUAL) < dun_level)) - { -#ifdef FORCE_V_IDX - if (room_build(y, x, ROOM_BUILD_TYPE_GREATER_VAULT)) continue; -#else - /* Type 8 -- Greater vault (4%) */ - if (k < 4) - { - if (max_vault_ok > 1) - { - if (room_build(y, x, ROOM_BUILD_TYPE_GREATER_VAULT)) continue; - } - else - { -#ifdef JP - if (cheat_room) msg_print("µðÂç¤ÊÃϲ¼¼¼¤òµÑ²¼¤·¤Þ¤¹¡£"); -#else - if (cheat_room) msg_print("Refusing a greater vault."); -#endif - } - } - - /* Type 7 -- Lesser vault (6%) */ - if (k < 10) - { - if (max_vault_ok > 0) - { - if (room_build(y, x, ROOM_BUILD_TYPE_LESSER_VAULT)) continue; - } - else - { -#ifdef JP - if (cheat_room) msg_print("¾®¤µ¤ÊÃϲ¼¼¼¤òµÑ²¼¤·¤Þ¤¹¡£"); -#else - if (cheat_room) msg_print("Refusing a lesser vault."); -#endif - } - } - - - /* Type 10 -- Random vault (4%) */ - if ((k < 14) && room_build(y, x, ROOM_BUILD_TYPE_RANDOM_VAULT)) continue; - - /* Type 5 -- Monster nest (8%) */ - if ((k < 22) && room_build(y, x, ROOM_BUILD_TYPE_NEST)) continue; - - /* Type 6 -- Monster pit (10%) */ - if ((k < 32) && room_build(y, x, ROOM_BUILD_TYPE_PIT)) continue; - - /* Type 13 -- Trapped monster pit (5%) */ - if ((k < 37) && room_build(y, x, ROOM_BUILD_TYPE_TRAP_PIT)) continue; - - /* Type 14 -- Trapped room (5%) */ - if ((k < 42) && room_build(y, x, ROOM_BUILD_TYPE_TRAP)) continue; -#endif - } - - /* Type 2 -- Overlapping (25%) */ - if ((k < 25) && room_build(y, x, ROOM_BUILD_TYPE_OVERLAP)) continue; - - /* Type 3 -- Cross room (25%) */ - if ((k < 50) && room_build(y, x, ROOM_BUILD_TYPE_CROSS)) continue; + int tunnel_fail_count = 0; - if (d_info[dungeon_type].flags1 & DF1_NO_CAVE) - { - if (room_build(y, x, ROOM_BUILD_TYPE_INNER_FEAT)) continue; - } - else - { - /* Type 4 -- Large room (25%) */ - if ((k < 75) && room_build(y, x, ROOM_BUILD_TYPE_INNER_FEAT)) continue; - - /* Type 11 -- Circular (10%) */ - if ((k < 85) && room_build(y, x, ROOM_BUILD_TYPE_OVAL)) continue; - - /* Type 12 -- Crypt (15%) */ - if ((k < 100) && room_build(y, x, ROOM_BUILD_TYPE_CRYPT)) continue; - } - } - - /* The deeper you are, the more cavelike the rooms are */ - k = randint1(100); - - /* No caves when a cavern exists: they look bad */ - if (((k < dun_level) || (d_info[dungeon_type].flags1 & DF1_CAVE)) - && !cavern && !empty_level && !laketype - && !(d_info[dungeon_type].flags1 & DF1_NO_CAVE)) - { - /* Type 9 -- Fractal cave */ - if (room_build(y, x, ROOM_BUILD_TYPE_FRACAVE)) continue; - } - else - { - /* Attempt a "trivial" room */ - if (room_build(y, x, ROOM_BUILD_TYPE_NORMAL)) continue; - } + /* + * Build each type of room in turn until we cannot build any more. + */ + if (!generate_rooms()) return FALSE; - continue; - } /* Make a hole in the dungeon roof sometimes at level 1 */ if (dun_level == 1) @@ -829,45 +837,52 @@ static bool cave_gen(void) } /* Destroy the level if necessary */ - if (destroyed) destroy_level(); + if (dun->destroyed) destroy_level(); /* Hack -- Add some rivers */ if (one_in_(3) && (randint1(dun_level) > 5)) { + int feat1 = 0, feat2 = 0; + /* Choose water or lava */ if ((randint1(MAX_DEPTH * 2) - 1 > dun_level) && (d_info[dungeon_type].flags1 & DF1_WATER_RIVER)) { - feat1 = FEAT_DEEP_WATER; - feat2 = FEAT_SHAL_WATER; + feat1 = feat_deep_water; + feat2 = feat_shallow_water; } else if (d_info[dungeon_type].flags1 & DF1_LAVA_RIVER) { - feat1 = FEAT_DEEP_LAVA; - feat2 = FEAT_SHAL_LAVA; + feat1 = feat_deep_lava; + feat2 = feat_shallow_lava; } else feat1 = 0; - - /* Only add river if matches lake type or if have no lake at all */ - if ((((laketype == GEN_LAKE_TYPE_LAVA) && (feat1 == FEAT_DEEP_LAVA)) || - ((laketype == GEN_LAKE_TYPE_WATER) && (feat1 == FEAT_DEEP_WATER)) || - !laketype) && feat1) + if (feat1) { - add_river(feat1, feat2); + feature_type *f_ptr = &f_info[feat1]; + + /* Only add river if matches lake type or if have no lake at all */ + if (((dun->laketype == LAKE_T_LAVA) && have_flag(f_ptr->flags, FF_LAVA)) || + ((dun->laketype == LAKE_T_WATER) && have_flag(f_ptr->flags, FF_WATER)) || + !dun->laketype) + { + add_river(feat1, feat2); + } } } /* Hack -- Scramble the room order */ for (i = 0; i < dun->cent_n; i++) { - int pick1 = randint0(dun->cent_n); - int pick2 = randint0(dun->cent_n); - y1 = dun->cent[pick1].y; - x1 = dun->cent[pick1].x; - dun->cent[pick1].y = dun->cent[pick2].y; - dun->cent[pick1].x = dun->cent[pick2].x; - dun->cent[pick2].y = y1; - dun->cent[pick2].x = x1; + int ty, tx; + int pick = rand_range(0, i); + + ty = dun->cent[i].y; + tx = dun->cent[i].x; + dun->cent[i].y = dun->cent[pick].y; + dun->cent[i].x = dun->cent[pick].x; + dun->cent[pick].y = ty; + dun->cent[pick].x = tx; } /* Start with no tunnel doors */ @@ -880,6 +895,8 @@ static bool cave_gen(void) /* Connect all the rooms together */ for (i = 0; i < dun->cent_n; i++) { + int j; + /* Reset the arrays */ dun->tunn_n = 0; dun->wall_n = 0; @@ -888,27 +905,32 @@ static bool cave_gen(void) if (randint1(dun_level) > d_info[dungeon_type].tunnel_percent) { /* make cave-like tunnel */ - build_tunnel2(dun->cent[i].x, dun->cent[i].y, x, y, 2, 2); + (void)build_tunnel2(dun->cent[i].x, dun->cent[i].y, x, y, 2, 2); } else { /* make normal tunnel */ - build_tunnel(dun->cent[i].y, dun->cent[i].x, y, x); + if (!build_tunnel(dun->cent[i].y, dun->cent[i].x, y, x)) tunnel_fail_count++; } + if (tunnel_fail_count >= 2) return FALSE; + /* Turn the tunnel into corridor */ for (j = 0; j < dun->tunn_n; j++) { + cave_type *c_ptr; + feature_type *f_ptr; + /* Access the grid */ y = dun->tunn[j].y; x = dun->tunn[j].x; /* Access the grid */ c_ptr = &cave[y][x]; + f_ptr = &f_info[c_ptr->feat]; /* Clear previous contents (if not a lake), add a floor */ - if ((c_ptr->feat < FEAT_DEEP_WATER) || - (c_ptr->feat > FEAT_SHAL_LAVA)) + if (!have_flag(f_ptr->flags, FF_MOVE) || (!have_flag(f_ptr->flags, FF_WATER) && !have_flag(f_ptr->flags, FF_LAVA))) { /* Clear mimic type */ c_ptr->mimic = 0; @@ -920,6 +942,8 @@ static bool cave_gen(void) /* Apply the piercings that we found */ for (j = 0; j < dun->wall_n; j++) { + cave_type *c_ptr; + /* Access the grid */ y = dun->wall[j].y; x = dun->wall[j].x; @@ -961,13 +985,13 @@ static bool cave_gen(void) } /* Place 3 or 4 down stairs near some walls */ - if (!alloc_stairs(FEAT_MORE, rand_range(3, 4), 3)) return FALSE; + if (!alloc_stairs(feat_down_stair, rand_range(3, 4), 3)) return FALSE; /* Place 1 or 2 up stairs near some walls */ - if (!alloc_stairs(FEAT_LESS, rand_range(1, 2), 3)) return FALSE; + if (!alloc_stairs(feat_up_stair, rand_range(1, 2), 3)) return FALSE; } - if (!laketype) + if (!dun->laketype) { if (d_info[dungeon_type].stream2) { @@ -991,39 +1015,21 @@ static bool cave_gen(void) /* Special boundary walls -- Top and bottom */ for (x = 0; x < cur_wid; x++) { - cave_type *c_ptr = &cave[0][x]; - - /* Set boundary mimic and add "solid" perma-wall */ - c_ptr->mimic = f_info[c_ptr->feat].mimic; - c_ptr->feat = FEAT_PERM_SOLID; - - c_ptr = &cave[cur_hgt - 1][x]; - - /* Set boundary mimic and add "solid" perma-wall */ - c_ptr->mimic = f_info[c_ptr->feat].mimic; - c_ptr->feat = FEAT_PERM_SOLID; + set_bound_perm_wall(&cave[0][x]); + set_bound_perm_wall(&cave[cur_hgt - 1][x]); } /* Special boundary walls -- Left and right */ for (y = 1; y < (cur_hgt - 1); y++) { - cave_type *c_ptr = &cave[y][0]; - - /* Set boundary mimic and add "solid" perma-wall */ - c_ptr->mimic = f_info[c_ptr->feat].mimic; - c_ptr->feat = FEAT_PERM_SOLID; - - c_ptr = &cave[y][cur_wid - 1]; - - /* Set boundary mimic and add "solid" perma-wall */ - c_ptr->mimic = f_info[c_ptr->feat].mimic; - c_ptr->feat = FEAT_PERM_SOLID; + set_bound_perm_wall(&cave[y][0]); + set_bound_perm_wall(&cave[y][cur_wid - 1]); } /* Determine the character location */ if (!new_player_spot()) return FALSE; - place_quest_monsters(); + if (!place_quest_monsters()) return FALSE; /* Basic "amount" */ k = (dun_level / 3); @@ -1046,7 +1052,7 @@ static bool cave_gen(void) else if (cheat_hear) { #ifdef JP -msg_format("¥â¥ó¥¹¥¿¡¼¿ô´ðËÜÃͤò %d ¤«¤é %d ¤Ë¸º¤é¤·¤Þ¤¹", small_tester, i); +msg_format("モンスター数基本値を %d から %d に減らします", small_tester, i); #else msg_format("Reduced monsters base from %d to %d", small_tester, i); #endif @@ -1065,50 +1071,30 @@ msg_format(" /* Place some traps in the dungeon */ alloc_object(ALLOC_SET_BOTH, ALLOC_TYP_TRAP, randint1(k)); - /* Put some rubble in corridors */ - alloc_object(ALLOC_SET_CORR, ALLOC_TYP_RUBBLE, randint1(k)); + /* Put some rubble in corridors (except NO_CAVE dungeon (Castle)) */ + if (!(d_info[dungeon_type].flags1 & DF1_NO_CAVE)) alloc_object(ALLOC_SET_CORR, ALLOC_TYP_RUBBLE, randint1(k)); /* Mega Hack -- No object at first level of deeper dungeon */ if (p_ptr->enter_dungeon && dun_level > 1) { /* No stair scum! */ + object_level = 1; } - else - { - /* Put some objects in rooms */ - alloc_object(ALLOC_SET_ROOM, ALLOC_TYP_OBJECT, randnor(DUN_AMT_ROOM, 3)); - /* Put some objects/gold in the dungeon */ - alloc_object(ALLOC_SET_BOTH, ALLOC_TYP_OBJECT, randnor(DUN_AMT_ITEM, 3)); - alloc_object(ALLOC_SET_BOTH, ALLOC_TYP_GOLD, randnor(DUN_AMT_GOLD, 3)); - } + /* Put some objects in rooms */ + alloc_object(ALLOC_SET_ROOM, ALLOC_TYP_OBJECT, randnor(DUN_AMT_ROOM, 3)); - /* Put an Artifact and Artifact Guardian is requested */ - if (d_info[dungeon_type].final_guardian && (d_info[dungeon_type].maxdepth == dun_level)) - { - int oy; - int ox; - int try = 4000; + /* Put some objects/gold in the dungeon */ + alloc_object(ALLOC_SET_BOTH, ALLOC_TYP_OBJECT, randnor(DUN_AMT_ITEM, 3)); + alloc_object(ALLOC_SET_BOTH, ALLOC_TYP_GOLD, randnor(DUN_AMT_GOLD, 3)); - /* Find a good position */ - while(try) - { - /* Get a random spot */ - oy = randint1(cur_hgt - 4) + 2; - ox = randint1(cur_wid - 4) + 2; + /* Set back to default */ + object_level = base_level; - /* Is it a good spot ? */ - if (cave_empty_bold2(oy, ox) && monster_can_cross_terrain(cave[oy][ox].feat, &r_info[d_info[dungeon_type].final_guardian])) - { - /* Place the guardian */ - if (place_monster_aux(0, oy, ox, d_info[dungeon_type].final_guardian, (PM_ALLOW_GROUP | PM_NO_KAGE | PM_NO_PET))) break; - } - /* One less try */ - try--; - } - } + /* Put the Guardian */ + if (!alloc_guardian(TRUE)) return FALSE; - if (empty_level && (!one_in_(DARK_EMPTY) || (randint1(100) > dun_level)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS)) + if (dun->empty_level && (!one_in_(DARK_EMPTY) || (randint1(100) > dun_level)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS)) { /* Lite the cave */ for (y = 0; y < cur_hgt; y++) @@ -1123,9 +1109,9 @@ msg_format(" return TRUE; } - -/* - * Builds the arena after it is entered -KMW- +/*! + * @brief 闘技場用のアリーナ地形を作成する / Builds the arena after it is entered -KMW- + * @return なし */ static void build_arena(void) { @@ -1142,47 +1128,47 @@ static void build_arena(void) for (i = y_height; i <= y_height + 5; i++) for (j = x_left; j <= x_right; j++) { - cave[i][j].feat = FEAT_PERM_EXTRA; + place_extra_perm_bold(i, j); cave[i][j].info |= (CAVE_GLOW | CAVE_MARK); } for (i = y_depth; i >= y_depth - 5; i--) for (j = x_left; j <= x_right; j++) { - cave[i][j].feat = FEAT_PERM_EXTRA; + place_extra_perm_bold(i, j); cave[i][j].info |= (CAVE_GLOW | CAVE_MARK); } for (j = x_left; j <= x_left + 17; j++) for (i = y_height; i <= y_depth; i++) { - cave[i][j].feat = FEAT_PERM_EXTRA; + place_extra_perm_bold(i, j); cave[i][j].info |= (CAVE_GLOW | CAVE_MARK); } for (j = x_right; j >= x_right - 17; j--) for (i = y_height; i <= y_depth; i++) { - cave[i][j].feat = FEAT_PERM_EXTRA; + place_extra_perm_bold(i, j); cave[i][j].info |= (CAVE_GLOW | CAVE_MARK); } - cave[y_height+6][x_left+18].feat = FEAT_PERM_EXTRA; + place_extra_perm_bold(y_height+6, x_left+18); cave[y_height+6][x_left+18].info |= (CAVE_GLOW | CAVE_MARK); - cave[y_depth-6][x_left+18].feat = FEAT_PERM_EXTRA; + place_extra_perm_bold(y_depth-6, x_left+18); cave[y_depth-6][x_left+18].info |= (CAVE_GLOW | CAVE_MARK); - cave[y_height+6][x_right-18].feat = FEAT_PERM_EXTRA; + place_extra_perm_bold(y_height+6, x_right-18); cave[y_height+6][x_right-18].info |= (CAVE_GLOW | CAVE_MARK); - cave[y_depth-6][x_right-18].feat = FEAT_PERM_EXTRA; + place_extra_perm_bold(y_depth-6, x_right-18); cave[y_depth-6][x_right-18].info |= (CAVE_GLOW | CAVE_MARK); i = y_height + 5; j = xval; - cave[i][j].feat = FEAT_BLDG_HEAD + 2; + cave[i][j].feat = f_tag_to_index("ARENA_GATE"); cave[i][j].info |= (CAVE_GLOW | CAVE_MARK); - player_place(i + 1, j); + player_place(i, j); } - -/* - * Town logic flow for generation of arena -KMW- +/*! + * @brief 闘技場への入場処理 / Town logic flow for generation of arena -KMW- + * @return なし */ static void arena_gen(void) { @@ -1200,7 +1186,7 @@ static void arena_gen(void) for (x = 0; x < MAX_WID; x++) { /* Create "solid" perma-wall */ - cave[y][x].feat = FEAT_PERM_SOLID; + place_solid_perm_bold(y, x); /* Illuminate and memorize the walls */ cave[y][x].info |= (CAVE_GLOW | CAVE_MARK); @@ -1213,20 +1199,28 @@ static void arena_gen(void) for (x = qx + 1; x < qx + SCREEN_WID - 1; x++) { /* Create empty floor */ - cave[y][x].feat = FEAT_FLOOR; + cave[y][x].feat = feat_floor; } } build_arena(); - place_monster_aux(0, py + 5, px, arena_info[p_ptr->arena_number].r_idx, - (PM_NO_KAGE | PM_NO_PET)); -} - + if(!place_monster_aux(0, p_ptr->y + 5, p_ptr->x, arena_info[p_ptr->arena_number].r_idx, (PM_NO_KAGE | PM_NO_PET))) + { + p_ptr->exit_bldg = TRUE; + p_ptr->arena_number++; +#ifdef JP + msg_print("相手は欠場した。あなたの不戦勝だ。"); +#else + msg_print("The enemy is unable appear. You won by default."); +#endif + } +} -/* - * Builds the arena after it is entered -KMW- +/*! + * @brief モンスター闘技場のフロア生成 / Builds the arena after it is entered -KMW- + * @return なし */ static void build_battle(void) { @@ -1243,47 +1237,53 @@ static void build_battle(void) for (i = y_height; i <= y_height + 5; i++) for (j = x_left; j <= x_right; j++) { - cave[i][j].feat = FEAT_PERM_EXTRA; + place_extra_perm_bold(i, j); cave[i][j].info |= (CAVE_GLOW | CAVE_MARK); } for (i = y_depth; i >= y_depth - 3; i--) for (j = x_left; j <= x_right; j++) { - cave[i][j].feat = FEAT_PERM_EXTRA; + place_extra_perm_bold(i, j); cave[i][j].info |= (CAVE_GLOW | CAVE_MARK); } for (j = x_left; j <= x_left + 17; j++) for (i = y_height; i <= y_depth; i++) { - cave[i][j].feat = FEAT_PERM_EXTRA; + place_extra_perm_bold(i, j); cave[i][j].info |= (CAVE_GLOW | CAVE_MARK); } for (j = x_right; j >= x_right - 17; j--) for (i = y_height; i <= y_depth; i++) { - cave[i][j].feat = FEAT_PERM_EXTRA; + place_extra_perm_bold(i, j); cave[i][j].info |= (CAVE_GLOW | CAVE_MARK); } - cave[y_height+6][x_left+18].feat = FEAT_PERM_EXTRA; + place_extra_perm_bold(y_height+6, x_left+18); cave[y_height+6][x_left+18].info |= (CAVE_GLOW | CAVE_MARK); - cave[y_depth-4][x_left+18].feat = FEAT_PERM_EXTRA; + place_extra_perm_bold(y_depth-4, x_left+18); cave[y_depth-4][x_left+18].info |= (CAVE_GLOW | CAVE_MARK); - cave[y_height+6][x_right-18].feat = FEAT_PERM_EXTRA; + place_extra_perm_bold(y_height+6, x_right-18); cave[y_height+6][x_right-18].info |= (CAVE_GLOW | CAVE_MARK); - cave[y_depth-4][x_right-18].feat = FEAT_PERM_EXTRA; + place_extra_perm_bold(y_depth-4, x_right-18); cave[y_depth-4][x_right-18].info |= (CAVE_GLOW | CAVE_MARK); - i = y_height + 4; + for (i = y_height + 1; i <= y_height + 5; i++) + for (j = x_left + 20 + 2 * (y_height + 5 - i); j <= x_right - 20 - 2 * (y_height + 5 - i); j++) + { + cave[i][j].feat = feat_permanent_glass_wall; + } + + i = y_height + 1; j = xval; - cave[i][j].feat = FEAT_BLDG_HEAD + 3; + cave[i][j].feat = f_tag_to_index("BUILDING_3"); cave[i][j].info |= (CAVE_GLOW | CAVE_MARK); player_place(i, j); } - -/* - * Town logic flow for generation of arena -KMW- +/*! + * @brief モンスター闘技場への導入処理 / Town logic flow for generation of arena -KMW- + * @return なし */ static void battle_gen(void) { @@ -1297,7 +1297,7 @@ static void battle_gen(void) for (x = 0; x < MAX_WID; x++) { /* Create "solid" perma-wall */ - cave[y][x].feat = FEAT_PERM_SOLID; + place_solid_perm_bold(y, x); /* Illuminate and memorize the walls */ cave[y][x].info |= (CAVE_GLOW | CAVE_MARK); @@ -1310,7 +1310,7 @@ static void battle_gen(void) for (x = qx + 1; x < qx + SCREEN_WID - 1; x++) { /* Create empty floor */ - cave[y][x].feat = FEAT_FLOOR; + cave[y][x].feat = feat_floor; } } @@ -1318,9 +1318,9 @@ static void battle_gen(void) for(i=0;i<4;i++) { - place_monster_aux(0, py + 5 + (i/2)*4, px - 2 + (i%2)*4, battle_mon[i], + place_monster_aux(0, p_ptr->y + 8 + (i/2)*4, p_ptr->x - 2 + (i%2)*4, battle_mon[i], (PM_NO_KAGE | PM_NO_PET)); - set_friendly(&m_list[cave[py+5+(i/2)*4][px-2+(i%2)*4].m_idx]); + set_friendly(&m_list[cave[p_ptr->y+8+(i/2)*4][p_ptr->x-2+(i%2)*4].m_idx]); } for(i = 1; i < m_max; i++) { @@ -1336,9 +1336,9 @@ static void battle_gen(void) } } - -/* - * Generate a quest level +/*! + * @brief 固定マップクエストのフロア生成 / Generate a quest level + * @return なし */ static void quest_gen(void) { @@ -1350,7 +1350,7 @@ static void quest_gen(void) { for (x = 0; x < cur_wid; x++) { - cave[y][x].feat = FEAT_PERM_SOLID; + place_solid_perm_bold(y, x); } } @@ -1365,12 +1365,15 @@ static void quest_gen(void) /* Prepare allocation table */ get_mon_num_prep(get_monster_hook(), NULL); - init_flags = INIT_CREATE_DUNGEON | INIT_ASSIGN; + init_flags = INIT_CREATE_DUNGEON; process_dungeon_file("q_info.txt", 0, 0, MAX_HGT, MAX_WID); } -/* Make a real level */ +/*! + * @brief ダンジョン時のランダムフロア生成 / Make a real level + * @return フロアの生成に成功したらTRUE + */ static bool level_gen(cptr *why) { int level_height, level_width; @@ -1383,12 +1386,11 @@ static bool level_gen(cptr *why) { if (cheat_room) #ifdef JP -msg_print("¾®¤µ¤Ê¥Õ¥í¥¢"); + msg_print("小さなフロア"); #else - msg_print("A 'small' dungeon level."); + msg_print("A 'small' dungeon level."); #endif - if (d_info[dungeon_type].flags1 & DF1_SMALLEST) { level_height = 1; @@ -1418,7 +1420,7 @@ msg_print(" panel_col_min = cur_wid; if (cheat_room) - msg_format("X:%d, Y:%d.", cur_hgt, cur_wid); + msg_format("X:%d, Y:%d.", cur_wid, cur_hgt); } else { @@ -1435,7 +1437,7 @@ msg_print(" if (!cave_gen()) { #ifdef JP -*why = "¥À¥ó¥¸¥ç¥óÀ¸À®¤Ë¼ºÇÔ"; +*why = "ダンジョン生成に失敗"; #else *why = "could not place player"; #endif @@ -1445,34 +1447,11 @@ msg_print(" else return TRUE; } -static byte extract_feeling(void) -{ - /* Hack -- no feeling in the town */ - if (!dun_level) return 0; - - /* Hack -- Have a special feeling sometimes */ - if (good_item_flag && !preserve_mode) return 1; - - if (rating > 100) return 2; - if (rating > 80) return 3; - if (rating > 60) return 4; - if (rating > 40) return 5; - if (rating > 30) return 6; - if (rating > 20) return 7; - if (rating > 10) return 8; - if (rating > 0) return 9; - - if((turn - old_turn) > TURNS_PER_TICK * TOWN_DAWN /2) - chg_virtue(V_PATIENCE, 1); - - return 10; -} - - -/* - * Wipe all unnecessary flags after cave generation +/*! + * @brief フロアに存在する全マスの記憶状態を初期化する / Wipe all unnecessary flags after cave generation + * @return なし */ -static void wipe_generate_cave_flags(void) +void wipe_generate_cave_flags(void) { int x, y; @@ -1498,25 +1477,28 @@ static void wipe_generate_cave_flags(void) } } - -/* - * Clear and empty the cave +/*! + * @brief フロアの全情報を初期化する / Clear and empty the cave + * @return なし */ void clear_cave(void) { int x, y, i; /* Very simplified version of wipe_o_list() */ - C_WIPE(o_list, o_max, object_type); + (void)C_WIPE(o_list, o_max, object_type); o_max = 1; o_cnt = 0; /* Very simplified version of wipe_m_list() */ for (i = 1; i < max_r_idx; i++) r_info[i].cur_num = 0; - C_WIPE(m_list, m_max, monster_type); + (void)C_WIPE(m_list, m_max, monster_type); m_max = 1; m_cnt = 0; + for (i = 0; i < MAX_MTIMED; i++) mproc_max[i] = 0; + + /* Pre-calc cur_num of pets in party_mon[] */ precalc_cur_num_of_pet(); @@ -1553,7 +1535,7 @@ void clear_cave(void) } /* Mega-Hack -- no player yet */ - px = py = 0; + p_ptr->x = p_ptr->y = 0; /* Set the base level */ base_level = dun_level; @@ -1563,21 +1545,13 @@ void clear_cave(void) /* Reset the object generation level */ object_level = base_level; - - /* Nothing special here yet */ - good_item_flag = FALSE; - - /* Nothing good here yet */ - rating = 0; } -/* - * Generates a random dungeon level -RAK- - * - * Hack -- regenerate any "overflow" levels - * - * Hack -- allow auto-scumming via a gameplay option. +/*! + * ダンジョンのランダムフロアを生成する / Generates a random dungeon level -RAK- + * @return なし + * @note Hack -- regenerate any "overflow" levels */ void generate_cave(void) { @@ -1596,8 +1570,6 @@ void generate_cave(void) /* Clear and empty the cave */ clear_cave(); - if ((d_info[dungeon_type].fill_type1 == FEAT_MAGMA_K) || (d_info[dungeon_type].fill_type2 == FEAT_MAGMA_K) || (d_info[dungeon_type].fill_type3 == FEAT_MAGMA_K)) rating += 40; - /* Build the arena -KMW- */ if (p_ptr->inside_arena) { @@ -1631,15 +1603,13 @@ void generate_cave(void) okay = level_gen(&why); } - /* Extract the feeling */ - feeling = extract_feeling(); /* Prevent object over-flow */ if (o_max >= max_o_idx) { /* Message */ #ifdef JP -why = "¥¢¥¤¥Æ¥à¤¬Â¿¤¹¤®¤ë"; +why = "アイテムが多すぎる"; #else why = "too many objects"; #endif @@ -1653,7 +1623,7 @@ why = " { /* Message */ #ifdef JP -why = "¥â¥ó¥¹¥¿¡¼¤¬Â¿¤¹¤®¤ë"; +why = "モンスターが多すぎる"; #else why = "too many monsters"; #endif @@ -1663,43 +1633,12 @@ why = " okay = FALSE; } - /* Mega-Hack -- "auto-scum" */ - else if ((auto_scum || ironman_autoscum) && (num < 100) && - !p_ptr->inside_quest && - !(d_info[dungeon_type].flags1 & DF1_BEGINNER) && - !p_ptr->enter_dungeon) - { - /* Require "goodness" */ - if ((feeling > 9) || - ((dun_level >= 7) && (feeling > 8)) || - ((dun_level >= 15) && (feeling > 7)) || - ((dun_level >= 35) && (feeling > 6)) || - ((dun_level >= 70) && (feeling > 5))) - { - /* Give message to cheaters */ - if (cheat_room || cheat_hear || - cheat_peek || cheat_xtra) - { - /* Message */ -#ifdef JP -why = "Âà¶þ¤Ê³¬"; -#else - why = "boring level"; -#endif - - } - - /* Try again */ - okay = FALSE; - } - } - /* Accept */ if (okay) break; /* Message */ #ifdef JP -if (why) msg_format("À¸À®¤ä¤êľ¤·(%s)", why); +if (why) msg_format("生成やり直し(%s)", why); #else if (why) msg_format("Generation restarted (%s)", why); #endif @@ -1712,8 +1651,8 @@ if (why) msg_format(" wipe_m_list(); } - /* Glow deep lava */ - glow_deep_lava(); + /* Glow deep lava and building entrances */ + glow_deep_lava_and_bldg(); /* Reset flag */ p_ptr->enter_dungeon = FALSE;