diff --git a/src/effect/effect-feature.cpp b/src/effect/effect-feature.cpp index b3090ebd3d..15484050c7 100644 --- a/src/effect/effect-feature.cpp +++ b/src/effect/effect-feature.cpp @@ -268,7 +268,7 @@ bool affect_feature(PlayerType *player_ptr, MONSTER_IDX src_idx, POSITION r, POS if (player_ptr->is_located_at(pos)) { break; } - cave_set_feat(player_ptr, y, x, feat_door[DOOR_DOOR].closed); + cave_set_feat(player_ptr, pos, feat_door.at(DoorKind::DOOR).closed); if (grid.is_mark()) { obvious = true; } diff --git a/src/effect/effect-monster-psi.cpp b/src/effect/effect-monster-psi.cpp index 55bd4e0e42..4804fc23d6 100644 --- a/src/effect/effect-monster-psi.cpp +++ b/src/effect/effect-monster-psi.cpp @@ -209,7 +209,7 @@ ProcessResult effect_monster_psi(PlayerType *player_ptr, EffectMonster *em_ptr) if (em_ptr->seen) { em_ptr->obvious = true; } - if (!(los(player_ptr, em_ptr->m_ptr->fy, em_ptr->m_ptr->fx, player_ptr->y, player_ptr->x))) { + if (!los(*player_ptr->current_floor_ptr, em_ptr->m_ptr->get_position(), player_ptr->get_position())) { if (em_ptr->seen_msg) { msg_format(_("%sはあなたが見えないので影響されない!", "%s^ can't see you, and isn't affected!"), em_ptr->m_name); } diff --git a/src/effect/effect-processor.cpp b/src/effect/effect-processor.cpp index 96b0d9b242..05fa5e2217 100644 --- a/src/effect/effect-processor.cpp +++ b/src/effect/effect-processor.cpp @@ -225,7 +225,7 @@ ProjectResult project(PlayerType *player_ptr, const MONSTER_IDX src_idx, POSITIO switch (typ) { case AttributeType::LITE: case AttributeType::LITE_WEAK: - if (!los(player_ptr, pos_breath.y, pos_breath.x, pos.y, pos.x)) { + if (!los(floor, pos_breath, pos)) { continue; } break; diff --git a/src/floor/floor-changer.cpp b/src/floor/floor-changer.cpp index f0285de348..d3d9834953 100644 --- a/src/floor/floor-changer.cpp +++ b/src/floor/floor-changer.cpp @@ -226,7 +226,7 @@ static void set_player_grid(FloorType &floor, const Pos2D &p_pos) } auto &grid = floor.get_grid(p_pos); - if (feat_uses_special(grid.feat)) { + if (grid.has_special_terrain()) { return; } diff --git a/src/floor/floor-leaver.cpp b/src/floor/floor-leaver.cpp index d0de3157f2..75130c057e 100644 --- a/src/floor/floor-leaver.cpp +++ b/src/floor/floor-leaver.cpp @@ -10,7 +10,6 @@ #include "floor/wild.h" #include "game-option/birth-options.h" #include "game-option/play-record-options.h" -#include "grid/grid.h" #include "inventory/inventory-slot-types.h" #include "io/write-diary.h" #include "mind/mind-ninja.h" @@ -68,9 +67,10 @@ static bool check_pet_preservation_conditions(PlayerType *player_ptr, MonsterEnt } const auto should_preserve = m_ptr->is_named(); - auto sight_from_player = player_ptr->current_floor_ptr->has_los(m_pos); + const auto &floor = *player_ptr->current_floor_ptr; + auto sight_from_player = floor.has_los(m_pos); sight_from_player &= projectable(player_ptr, p_pos, m_pos); - auto sight_from_monster = los(player_ptr, m_ptr->fy, m_ptr->fx, player_ptr->y, player_ptr->x); + auto sight_from_monster = los(floor, m_pos, p_pos); sight_from_monster &= projectable(player_ptr, m_pos, p_pos); if (should_preserve && (sight_from_player || sight_from_monster)) { return dis > 3; @@ -199,7 +199,7 @@ static void locate_connected_stairs(PlayerType *player_ptr, FloorType &floor, sa if (num == 0) { FloorChangeModesStore::get_instace()->set({ FloorChangeMode::RANDOM_PLACE, FloorChangeMode::NO_RETURN }); auto &grid = floor.get_grid(player_ptr->get_position()); - if (!feat_uses_special(grid.feat)) { + if (!grid.has_special_terrain()) { grid.special = 0; } @@ -394,7 +394,7 @@ static void refresh_new_floor_id(PlayerType *player_ptr, Grid *g_ptr) } new_floor_id = get_unused_floor_id(player_ptr); - if ((g_ptr != nullptr) && !feat_uses_special(g_ptr->feat)) { + if ((g_ptr != nullptr) && !g_ptr->has_special_terrain()) { g_ptr->special = new_floor_id; } } diff --git a/src/floor/floor-util.cpp b/src/floor/floor-util.cpp index 589d47690f..65b327e78d 100644 --- a/src/floor/floor-util.cpp +++ b/src/floor/floor-util.cpp @@ -167,7 +167,7 @@ Pos2D scatter(PlayerType *player_ptr, const Pos2D &pos, int d, uint32_t mode) continue; } if (mode & PROJECT_LOS) { - if (los(player_ptr, pos.y, pos.x, pos_neighbor.y, pos_neighbor.x)) { + if (los(floor, pos, pos_neighbor)) { return pos_neighbor; } diff --git a/src/floor/line-of-sight.cpp b/src/floor/line-of-sight.cpp index 372add3ff6..adbbeec98b 100644 --- a/src/floor/line-of-sight.cpp +++ b/src/floor/line-of-sight.cpp @@ -1,25 +1,22 @@ #include "floor/line-of-sight.h" #include "floor/cave.h" #include "system/floor/floor-info.h" -#include "system/player-type-definition.h" /*! * @brief LOS(Line Of Sight / 視線が通っているか)の判定を行う。 - * @param player_ptr プレイヤーへの参照ポインタ - * @param y1 始点のy座標 - * @param x1 始点のx座標 - * @param y2 終点のy座標 - * @param x2 終点のx座標 + * @param floor フロアへの参照 + * @param pos_from 始点の座標 + * @param pos_to 終点の座標 * @return LOSが通っているならTRUEを返す。 * @details * A simple, fast, integer-based line-of-sight algorithm. By Joseph Hall,\n * 4116 Brewster Drive, Raleigh NC 27606. Email to jnh@ecemwl.ncsu.edu.\n *\n - * Returns TRUE if a line of sight can be traced from (x1,y1) to (x2,y2).\n + * Returns TRUE if a line of sight can be traced from (pos_from.x,pos_from.y) to (pos_to.x,pos_to.y).\n *\n - * The LOS begins at the center of the tile (x1,y1) and ends at the center of\n - * the tile (x2,y2). If los() is to return TRUE, all of the tiles this line\n - * passes through must be floor tiles, except for (x1,y1) and (x2,y2).\n + * The LOS begins at the center of the tile (pos_from.x,pos_from.y) and ends at the center of\n + * the tile (pos_to.x,pos_to.y). If los() is to return TRUE, all of the tiles this line\n + * passes through must be floor tiles, except for (pos_from.x,pos_from.y) and (pos_to.x,pos_to.y).\n *\n * We assume that the "mathematical corner" of a non-floor tile does not\n * block line of sight.\n @@ -46,24 +43,22 @@ *\n * Use the "update_view()" function to determine player line-of-sight.\n */ -bool los(PlayerType *player_ptr, POSITION y1, POSITION x1, POSITION y2, POSITION x2) +bool los(const FloorType &floor, const Pos2D &pos_from, const Pos2D &pos_to) { - POSITION dy = y2 - y1; - POSITION dx = x2 - x1; - POSITION ay = std::abs(dy); - POSITION ax = std::abs(dx); + const auto dy = pos_to.y - pos_from.y; + const auto dx = pos_to.x - pos_from.x; + const auto ay = std::abs(dy); + const auto ax = std::abs(dx); if ((ax < 2) && (ay < 2)) { return true; } /* Directly South/North */ - auto *floor_ptr = player_ptr->current_floor_ptr; - POSITION tx, ty; if (!dx) { /* South -- check for walls */ if (dy > 0) { - for (ty = y1 + 1; ty < y2; ty++) { - if (!cave_los_bold(floor_ptr, ty, x1)) { + for (auto ty = pos_from.y + 1; ty < pos_to.y; ty++) { + if (!cave_los_bold(&floor, ty, pos_from.x)) { return false; } } @@ -71,8 +66,8 @@ bool los(PlayerType *player_ptr, POSITION y1, POSITION x1, POSITION y2, POSITION /* North -- check for walls */ else { - for (ty = y1 - 1; ty > y2; ty--) { - if (!cave_los_bold(floor_ptr, ty, x1)) { + for (auto ty = pos_from.y - 1; ty > pos_to.y; ty--) { + if (!cave_los_bold(&floor, ty, pos_from.x)) { return false; } } @@ -86,8 +81,8 @@ bool los(PlayerType *player_ptr, POSITION y1, POSITION x1, POSITION y2, POSITION if (!dy) { /* East -- check for walls */ if (dx > 0) { - for (tx = x1 + 1; tx < x2; tx++) { - if (!cave_los_bold(floor_ptr, y1, tx)) { + for (auto tx = pos_from.x + 1; tx < pos_to.x; tx++) { + if (!cave_los_bold(&floor, pos_from.y, tx)) { return false; } } @@ -95,8 +90,8 @@ bool los(PlayerType *player_ptr, POSITION y1, POSITION x1, POSITION y2, POSITION /* West -- check for walls */ else { - for (tx = x1 - 1; tx > x2; tx--) { - if (!cave_los_bold(floor_ptr, y1, tx)) { + for (auto tx = pos_from.x - 1; tx > pos_to.x; tx--) { + if (!cave_los_bold(&floor, pos_from.y, tx)) { return false; } } @@ -105,42 +100,39 @@ bool los(PlayerType *player_ptr, POSITION y1, POSITION x1, POSITION y2, POSITION return true; } - POSITION sx = (dx < 0) ? -1 : 1; - POSITION sy = (dy < 0) ? -1 : 1; + const auto sx = (dx < 0) ? -1 : 1; + const auto sy = (dy < 0) ? -1 : 1; if (ax == 1) { if (ay == 2) { - if (cave_los_bold(floor_ptr, y1 + sy, x1)) { + if (cave_los_bold(&floor, pos_from.y + sy, pos_from.x)) { return true; } } } else if (ay == 1) { if (ax == 2) { - if (cave_los_bold(floor_ptr, y1, x1 + sx)) { + if (cave_los_bold(&floor, pos_from.y, pos_from.x + sx)) { return true; } } } - POSITION f2 = (ax * ay); - POSITION f1 = f2 << 1; - POSITION qy; - POSITION m; + const auto f2 = (ax * ay); + const auto f1 = f2 << 1; if (ax >= ay) { - qy = ay * ay; - m = qy << 1; - tx = x1 + sx; + auto qy = ay * ay; + const auto m = qy << 1; + auto ty = pos_from.y; + auto tx = pos_from.x + sx; if (qy == f2) { - ty = y1 + sy; + ty += sy; qy -= f1; - } else { - ty = y1; } /* Note (below) the case (qy == f2), where */ /* the LOS exactly meets the corner of a tile. */ - while (x2 - tx) { - if (!cave_los_bold(floor_ptr, ty, tx)) { + while (pos_to.x - tx) { + if (!cave_los_bold(&floor, ty, tx)) { return false; } @@ -153,7 +145,7 @@ bool los(PlayerType *player_ptr, POSITION y1, POSITION x1, POSITION y2, POSITION if (qy > f2) { ty += sy; - if (!cave_los_bold(floor_ptr, ty, tx)) { + if (!cave_los_bold(&floor, ty, tx)) { return false; } qy -= f1; @@ -170,20 +162,19 @@ bool los(PlayerType *player_ptr, POSITION y1, POSITION x1, POSITION y2, POSITION } /* Travel vertically */ - POSITION qx = ax * ax; - m = qx << 1; - ty = y1 + sy; + auto qx = ax * ax; + const auto m = qx << 1; + auto ty = pos_from.y + sy; + auto tx = pos_from.x; if (qx == f2) { - tx = x1 + sx; + tx += sx; qx -= f1; - } else { - tx = x1; } /* Note (below) the case (qx == f2), where */ /* the LOS exactly meets the corner of a tile. */ - while (y2 - ty) { - if (!cave_los_bold(floor_ptr, ty, tx)) { + while (pos_to.y - ty) { + if (!cave_los_bold(&floor, ty, tx)) { return false; } @@ -196,7 +187,7 @@ bool los(PlayerType *player_ptr, POSITION y1, POSITION x1, POSITION y2, POSITION if (qx > f2) { tx += sx; - if (!cave_los_bold(floor_ptr, ty, tx)) { + if (!cave_los_bold(&floor, ty, tx)) { return false; } qx -= f1; diff --git a/src/floor/line-of-sight.h b/src/floor/line-of-sight.h index 5a77a79526..ae42c8511a 100644 --- a/src/floor/line-of-sight.h +++ b/src/floor/line-of-sight.h @@ -1,6 +1,6 @@ #pragma once -#include "system/angband.h" +#include "util/point-2d.h" -class PlayerType; -bool los(PlayerType *player_ptr, POSITION y1, POSITION x1, POSITION y2, POSITION x2); +class FloorType; +bool los(const FloorType &floor, const Pos2D &pos_from, const Pos2D &pos_to); diff --git a/src/floor/pattern-walk.cpp b/src/floor/pattern-walk.cpp index 5b3953c0a1..fbaeb945b2 100644 --- a/src/floor/pattern-walk.cpp +++ b/src/floor/pattern-walk.cpp @@ -21,6 +21,7 @@ #include "status/experience.h" #include "system/dungeon/dungeon-definition.h" #include "system/enums/dungeon/dungeon-id.h" +#include "system/enums/terrain/terrain-tag.h" #include "system/floor/floor-info.h" #include "system/grid-type-definition.h" #include "system/player-type-definition.h" @@ -124,7 +125,7 @@ bool pattern_effect(PlayerType *player_ptr) (void)restore_level(player_ptr); (void)cure_critical_wounds(player_ptr, 1000); - cave_set_feat(player_ptr, player_ptr->y, player_ptr->x, feat_pattern_old); + cave_set_feat(player_ptr, player_ptr->get_position(), TerrainTag::PATTERN_OLD); msg_print(_("「パターン」のこの部分は他の部分より強力でないようだ。", "This section of the Pattern looks less powerful.")); /* diff --git a/src/grid/door.cpp b/src/grid/door.cpp index ccc296d264..08fb1baed8 100644 --- a/src/grid/door.cpp +++ b/src/grid/door.cpp @@ -35,7 +35,7 @@ void add_door(PlayerType *player_ptr, POSITION x, POSITION y) */ if (floor_ptr->grid_array[y - 1][x].is_floor() && floor_ptr->grid_array[y + 1][x].is_floor() && floor_ptr->grid_array[y][x - 1].is_outer() && floor_ptr->grid_array[y][x + 1].is_outer()) { - place_secret_door(player_ptr, y, x, DOOR_DEFAULT); + place_secret_door(player_ptr, y, x, DoorKind::DEFAULT); place_bold(player_ptr, y, x - 1, GB_SOLID); place_bold(player_ptr, y, x + 1, GB_SOLID); } @@ -49,7 +49,7 @@ void add_door(PlayerType *player_ptr, POSITION x, POSITION y) * .=floor, #=wall */ if (floor_ptr->grid_array[y - 1][x].is_outer() && floor_ptr->grid_array[y + 1][x].is_outer() && floor_ptr->grid_array[y][x - 1].is_floor() && floor_ptr->grid_array[y][x + 1].is_floor()) { - place_secret_door(player_ptr, y, x, DOOR_DEFAULT); + place_secret_door(player_ptr, y, x, DoorKind::DEFAULT); place_bold(player_ptr, y - 1, x, GB_SOLID); place_bold(player_ptr, y + 1, x, GB_SOLID); } @@ -62,7 +62,7 @@ void add_door(PlayerType *player_ptr, POSITION x, POSITION y) * @param x 配置したいフロアのX座標 * @param type DOOR_DEFAULT / DOOR_DOOR / DOOR_GLASS_DOOR / DOOR_CURTAIN のいずれか */ -void place_secret_door(PlayerType *player_ptr, POSITION y, POSITION x, int type) +void place_secret_door(PlayerType *player_ptr, POSITION y, POSITION x, DoorKind type) { auto &floor = *player_ptr->current_floor_ptr; const Pos2D pos(y, x); @@ -72,15 +72,15 @@ void place_secret_door(PlayerType *player_ptr, POSITION y, POSITION x, int type) return; } - if (type == DOOR_DEFAULT) { + if (type == DoorKind::DEFAULT) { type = (dungeon.flags.has(DungeonFeatureType::CURTAIN) && one_in_(dungeon.flags.has(DungeonFeatureType::NO_CAVE) ? 16 : 256)) - ? DOOR_CURTAIN - : (dungeon.flags.has(DungeonFeatureType::GLASS_DOOR) ? DOOR_GLASS_DOOR : DOOR_DOOR); + ? DoorKind::CURTAIN + : (dungeon.flags.has(DungeonFeatureType::GLASS_DOOR) ? DoorKind::GLASS_DOOR : DoorKind::DOOR); } place_closed_door(player_ptr, pos.y, pos.x, type); auto &grid = floor.get_grid(pos); - if (type != DOOR_CURTAIN) { + if (type != DoorKind::CURTAIN) { grid.mimic = feat_wall_inner; if (grid.has_los_terrain(TerrainKind::MIMIC_RAW) && !grid.has_los_terrain()) { const auto &terrain_mimic = grid.get_terrain(TerrainKind::MIMIC_RAW); @@ -112,7 +112,7 @@ void place_locked_door(PlayerType *player_ptr, POSITION y, POSITION x) return; } - floor.set_terrain_id_at(pos, feat_locked_door_random(dungeon.flags.has(DungeonFeatureType::GLASS_DOOR) ? DOOR_GLASS_DOOR : DOOR_DOOR)); + floor.set_terrain_id_at(pos, feat_locked_door_random(dungeon.flags.has(DungeonFeatureType::GLASS_DOOR) ? DoorKind::GLASS_DOOR : DoorKind::DOOR)); floor.get_grid(pos).info &= ~(CAVE_FLOOR); delete_monster(player_ptr, pos.y, pos.x); } @@ -136,21 +136,20 @@ void place_random_door(PlayerType *player_ptr, POSITION y, POSITION x, bool room return; } - auto type = (dungeon.flags.has(DungeonFeatureType::CURTAIN) && one_in_(dungeon.flags.has(DungeonFeatureType::NO_CAVE) ? 16 : 256)) - ? DOOR_CURTAIN - : (dungeon.flags.has(DungeonFeatureType::GLASS_DOOR) ? DOOR_GLASS_DOOR : DOOR_DOOR); + const auto type = (dungeon.flags.has(DungeonFeatureType::CURTAIN) && one_in_(dungeon.flags.has(DungeonFeatureType::NO_CAVE) ? 16 : 256)) + ? DoorKind::CURTAIN + : (dungeon.flags.has(DungeonFeatureType::GLASS_DOOR) ? DoorKind::GLASS_DOOR : DoorKind::DOOR); auto tmp = randint0(1000); - const auto &terrains = TerrainList::get_instance(); - const auto terrain_none = terrains.get_terrain_id(TerrainTag::NONE); + const auto terrain_none = TerrainTag::NONE; auto terrain_id = terrain_none; if (tmp < 300) { - terrain_id = feat_door[type].open; + terrain_id = feat_door.at(type).open; } else if (tmp < 400) { - terrain_id = feat_door[type].broken; + terrain_id = feat_door.at(type).broken; } else if (tmp < 600) { place_closed_door(player_ptr, y, x, type); - if (type != DOOR_CURTAIN) { + if (type != DoorKind::CURTAIN) { grid.mimic = room ? feat_wall_outer : rand_choice(feat_wall_type); if (grid.has_los_terrain(TerrainKind::MIMIC_RAW) && !grid.has_los_terrain()) { const auto &terrain_mimic = grid.get_terrain(TerrainKind::MIMIC_RAW); @@ -185,7 +184,7 @@ void place_random_door(PlayerType *player_ptr, POSITION y, POSITION x, bool room * @param x ドアの配置を試みたいマスのX座標 * @param type ドアの地形ID */ -void place_closed_door(PlayerType *player_ptr, POSITION y, POSITION x, int type) +void place_closed_door(PlayerType *player_ptr, POSITION y, POSITION x, DoorKind type) { const Pos2D pos(y, x); auto &floor = *player_ptr->current_floor_ptr; @@ -194,23 +193,21 @@ void place_closed_door(PlayerType *player_ptr, POSITION y, POSITION x, int type) return; } - const auto &terrains = TerrainList::get_instance(); - const auto terrain_none = terrains.get_terrain_id(TerrainTag::NONE); auto tmp = randint0(400); - auto terrain_id = terrain_none; + auto tag = TerrainTag::NONE; if (tmp < 300) { - terrain_id = feat_door[type].closed; + tag = feat_door.at(type).closed; } else if (tmp < 399) { - terrain_id = feat_locked_door_random(type); + tag = feat_locked_door_random(type); } else { - terrain_id = feat_jammed_door_random(type); + tag = feat_jammed_door_random(type); } - if (terrain_id == terrain_none) { + if (tag == TerrainTag::NONE) { place_bold(player_ptr, pos.y, pos.x, GB_FLOOR); return; } - cave_set_feat(player_ptr, pos.y, pos.x, terrain_id); + cave_set_feat(player_ptr, pos, tag); floor.get_grid(pos).info &= ~(CAVE_MASK); } diff --git a/src/grid/door.h b/src/grid/door.h index fa3c86ba86..bfb982a4f7 100644 --- a/src/grid/door.h +++ b/src/grid/door.h @@ -2,9 +2,10 @@ #include "system/angband.h" +enum class DoorKind; class PlayerType; void add_door(PlayerType *player_ptr, POSITION x, POSITION y); -void place_secret_door(PlayerType *player_ptr, POSITION y, POSITION x, int type); +void place_secret_door(PlayerType *player_ptr, POSITION y, POSITION x, DoorKind type); void place_locked_door(PlayerType *player_ptr, POSITION y, POSITION x); void place_random_door(PlayerType *player_ptr, POSITION y, POSITION x, bool room); -void place_closed_door(PlayerType *player_ptr, POSITION y, POSITION x, int type); +void place_closed_door(PlayerType *player_ptr, POSITION y, POSITION x, DoorKind type); diff --git a/src/grid/feature.cpp b/src/grid/feature.cpp index 364265eb55..f8337908b6 100644 --- a/src/grid/feature.cpp +++ b/src/grid/feature.cpp @@ -19,45 +19,23 @@ #include "system/terrain/terrain-list.h" #include "util/bit-flags-calculator.h" #include "world/world.h" -#include /*** Terrain feature variables ***/ - -/* Special traps */ -FEAT_IDX feat_trap_open; -FEAT_IDX feat_trap_armageddon; -FEAT_IDX feat_trap_piranha; - -/* Pattern */ -FEAT_IDX feat_pattern_start; -FEAT_IDX feat_pattern_1; -FEAT_IDX feat_pattern_2; -FEAT_IDX feat_pattern_3; -FEAT_IDX feat_pattern_4; -FEAT_IDX feat_pattern_end; -FEAT_IDX feat_pattern_old; -FEAT_IDX feat_pattern_exit; -FEAT_IDX feat_pattern_corrupted; - FEAT_IDX feat_wall_outer; FEAT_IDX feat_wall_inner; FEAT_IDX feat_wall_solid; FEAT_IDX feat_ground_type[100], feat_wall_type[100]; -FEAT_IDX feat_locked_door_random(int door_type) +TerrainTag feat_locked_door_random(DoorKind door_kind) { - const auto &terrains = TerrainList::get_instance(); - const auto &door = feat_door[door_type]; - std::span candidates(std::begin(door.locked), door.num_locked); - return candidates.empty() ? terrains.get_terrain_id(TerrainTag::NONE) : rand_choice(candidates); + const auto &door = feat_door.at(door_kind); + return rand_choice(door.locked); } -FEAT_IDX feat_jammed_door_random(int door_type) +TerrainTag feat_jammed_door_random(DoorKind door_kind) { - const auto &terrains = TerrainList::get_instance(); - const auto &door = feat_door[door_type]; - std::span candidates(std::begin(door.jammed), door.num_jammed); - return candidates.empty() ? terrains.get_terrain_id(TerrainTag::NONE) : rand_choice(candidates); + const auto &door = feat_door.at(door_kind); + return rand_choice(door.jammed); } void cave_set_feat(PlayerType *player_ptr, const Pos2D &pos, TerrainTag tag) diff --git a/src/grid/feature.h b/src/grid/feature.h index 5a3bcc11d1..042518706a 100644 --- a/src/grid/feature.h +++ b/src/grid/feature.h @@ -6,29 +6,17 @@ #include /*** Terrain feature variables ***/ -extern FEAT_IDX feat_trap_open; -extern FEAT_IDX feat_trap_armageddon; -extern FEAT_IDX feat_trap_piranha; -extern FEAT_IDX feat_pattern_start; -extern FEAT_IDX feat_pattern_1; -extern FEAT_IDX feat_pattern_2; -extern FEAT_IDX feat_pattern_3; -extern FEAT_IDX feat_pattern_4; -extern FEAT_IDX feat_pattern_end; -extern FEAT_IDX feat_pattern_old; -extern FEAT_IDX feat_pattern_exit; -extern FEAT_IDX feat_pattern_corrupted; - extern FEAT_IDX feat_wall_outer; extern FEAT_IDX feat_wall_inner; extern FEAT_IDX feat_wall_solid; extern FEAT_IDX feat_ground_type[100]; extern FEAT_IDX feat_wall_type[100]; +enum class DoorKind; enum class TerrainTag; class FloorType; class PlayerType; -FEAT_IDX feat_locked_door_random(int door_type); -FEAT_IDX feat_jammed_door_random(int door_type); +TerrainTag feat_locked_door_random(DoorKind door_kind); +TerrainTag feat_jammed_door_random(DoorKind door_kind); void cave_set_feat(PlayerType *player_ptr, const Pos2D &pos, TerrainTag tag); void cave_set_feat(PlayerType *player_ptr, POSITION y, POSITION x, FEAT_IDX feat); diff --git a/src/grid/grid.cpp b/src/grid/grid.cpp index e3f074cfa2..03c910f682 100644 --- a/src/grid/grid.cpp +++ b/src/grid/grid.cpp @@ -1009,14 +1009,6 @@ void place_bold(PlayerType *player_ptr, POSITION y, POSITION x, grid_bold_type g place_grid(player_ptr, g_ptr, gb_type); } -/*! - * @brief マス構造体のspecial要素を利用する地形かどうかを判定する. - */ -bool feat_uses_special(FEAT_IDX f_idx) -{ - return TerrainList::get_instance().get_terrain(f_idx).flags.has(TerrainCharacteristics::SPECIAL); -} - /* * This function allows us to efficiently add a grid to the "lite" array, * note that we are never called for illegal grids, or for grids which diff --git a/src/grid/grid.h b/src/grid/grid.h index 79e67d888a..381766243b 100644 --- a/src/grid/grid.h +++ b/src/grid/grid.h @@ -68,7 +68,6 @@ enum class GridCountKind; enum class TerrainCharacteristics; bool new_player_spot(PlayerType *player_ptr); bool player_can_enter(PlayerType *player_ptr, FEAT_IDX feature, BIT_FLAGS16 mode); -bool feat_uses_special(FEAT_IDX f_idx); void update_local_illumination(PlayerType *player_ptr, POSITION y, POSITION x); bool no_lite(PlayerType *player_ptr); void print_rel(PlayerType *player_ptr, const DisplaySymbol &symbol, POSITION y, POSITION x); diff --git a/src/grid/trap.cpp b/src/grid/trap.cpp index d8f9f55d86..ea68c826ed 100644 --- a/src/grid/trap.cpp +++ b/src/grid/trap.cpp @@ -38,15 +38,12 @@ #include "system/monster-entity.h" #include "system/player-type-definition.h" #include "system/terrain/terrain-definition.h" -#include "system/terrain/terrain-list.h" #include "target/projection-path-calculator.h" #include "timed-effect/timed-effects.h" #include "util/enum-converter.h" #include "view/display-messages.h" #include "world/world.h" -static std::vector normal_traps; - /*! * @brief 箱のトラップテーブル * @details @@ -125,65 +122,6 @@ const std::vector> chest_traps = { { ChestTrapType::EXPLODE, ChestTrapType::SUMMON }, }; -/*! - * @brief タグに従って、基本トラップテーブルを初期化する / Initialize arrays for normal traps - */ -void init_normal_traps(void) -{ - static constexpr auto normal_trap_tags = { - "TRAP_TRAPDOOR", - "TRAP_PIT", - "TRAP_SPIKED_PIT", - "TRAP_POISON_PIT", - "TRAP_TY_CURSE", - "TRAP_TELEPORT", - "TRAP_FIRE", - "TRAP_ACID", - "TRAP_SLOW", - "TRAP_LOSE_STR", - "TRAP_LOSE_DEX", - "TRAP_LOSE_CON", - "TRAP_BLIND", - "TRAP_CONFUSE", - "TRAP_POISON", - "TRAP_SLEEP", - "TRAP_TRAPS", - "TRAP_ALARM", - }; - - std::transform(normal_trap_tags.begin(), normal_trap_tags.end(), std::back_inserter(normal_traps), [](const auto &tag) { - return TerrainList::get_instance().get_terrain_id_by_tag(tag); - }); -} - -/*! - * @brief 基本トラップをランダムに選択する - * @param floor_ptr 現在フロアへの参照ポインタ - * @return 選択したトラップのID - * @details トラップドアでないならばそのID. - * トラップドアは、アリーナ・クエスト・ダンジョンの最下層には設置しない. - */ -short choose_random_trap(FloorType *floor_ptr) -{ - const auto &terrains = TerrainList::get_instance(); - while (true) { - const auto terrain_id = rand_choice(normal_traps); - if (terrains.get_terrain(terrain_id).flags.has_not(TerrainCharacteristics::MORE)) { - return terrain_id; - } - - if (floor_ptr->inside_arena || inside_quest(floor_ptr->get_quest_id())) { - continue; - } - - if (floor_ptr->dun_level >= floor_ptr->get_dungeon_definition().maxdepth) { - continue; - } - - return terrain_id; - } -} - /*! * @brief マスに存在する隠しトラップを公開する / * Disclose an invisible trap @@ -233,7 +171,7 @@ void place_trap(FloorType *floor_ptr, POSITION y, POSITION x) /* Place an invisible trap */ g_ptr->mimic = g_ptr->feat; - g_ptr->feat = choose_random_trap(floor_ptr); + g_ptr->set_terrain_id(floor_ptr->select_random_trap()); } /*! diff --git a/src/grid/trap.h b/src/grid/trap.h index f4124dc300..a69492ab23 100644 --- a/src/grid/trap.h +++ b/src/grid/trap.h @@ -57,8 +57,6 @@ extern const std::vector> chest_traps; class FloorType; class PlayerType; -void init_normal_traps(); -short choose_random_trap(FloorType *floor_ptr); void disclose_grid(PlayerType *player_ptr, POSITION y, POSITION x); void place_trap(FloorType *floor_ptr, POSITION y, POSITION x); void hit_trap(PlayerType *player_ptr, bool break_trap); diff --git a/src/info-reader/feature-info-tokens-table.cpp b/src/info-reader/feature-info-tokens-table.cpp index 160478540d..5d9a99ccb2 100644 --- a/src/info-reader/feature-info-tokens-table.cpp +++ b/src/info-reader/feature-info-tokens-table.cpp @@ -169,4 +169,80 @@ const std::unordered_map terrain_tags = { { "TREE", TerrainTag::TREE }, { "MOUNTAIN", TerrainTag::MOUNTAIN }, { "SWAMP", TerrainTag::SWAMP }, + + { "TRAP_TRAPDOOR", TerrainTag::TRAP_TRAPDOOR }, + { "TRAP_PIT", TerrainTag::TRAP_PIT }, + { "TRAP_SPIKED_PIT", TerrainTag::TRAP_SPIKED_PIT }, + { "TRAP_POISON_PIT", TerrainTag::TRAP_POISON_PIT }, + { "TRAP_TY_CURSE", TerrainTag::TRAP_TY_CURSE }, + { "TRAP_TELEPORT", TerrainTag::TRAP_TELEPORT }, + { "TRAP_FIRE", TerrainTag::TRAP_FIRE }, + { "TRAP_ACID", TerrainTag::TRAP_ACID }, + { "TRAP_SLOW", TerrainTag::TRAP_SLOW }, + { "TRAP_LOSE_STR", TerrainTag::TRAP_LOSE_STR }, + { "TRAP_LOSE_DEX", TerrainTag::TRAP_LOSE_DEX }, + { "TRAP_LOSE_CON", TerrainTag::TRAP_LOSE_CON }, + { "TRAP_BLIND", TerrainTag::TRAP_BLIND }, + { "TRAP_CONFUSE", TerrainTag::TRAP_CONFUSE }, + { "TRAP_POISON", TerrainTag::TRAP_POISON }, + { "TRAP_SLEEP", TerrainTag::TRAP_SLEEP }, + { "TRAP_TRAPS", TerrainTag::TRAP_TRAPS }, + { "TRAP_ALARM", TerrainTag::TRAP_ALARM }, + + { "TRAP_OPEN", TerrainTag::TRAP_OPEN }, + { "TRAP_PIRANHA", TerrainTag::TRAP_PIRANHA }, + { "TRAP_ARMAGEDDON", TerrainTag::TRAP_ARMAGEDDON }, + + { "PATTERN_START", TerrainTag::PATTERN_START }, + { "PATTERN_1", TerrainTag::PATTERN_1 }, + { "PATTERN_2", TerrainTag::PATTERN_2 }, + { "PATTERN_3", TerrainTag::PATTERN_3 }, + { "PATTERN_4", TerrainTag::PATTERN_4 }, + { "PATTERN_END", TerrainTag::PATTERN_END }, + { "PATTERN_OLD", TerrainTag::PATTERN_OLD }, + { "PATTERN_EXIT", TerrainTag::PATTERN_EXIT }, + { "PATTERN_CORRUPTED", TerrainTag::PATTERN_CORRUPTED }, + + { "LOCKED_DOOR_1", TerrainTag::LOCKED_DOOR_1 }, + { "LOCKED_DOOR_2", TerrainTag::LOCKED_DOOR_2 }, + { "LOCKED_DOOR_3", TerrainTag::LOCKED_DOOR_3 }, + { "LOCKED_DOOR_4", TerrainTag::LOCKED_DOOR_4 }, + { "LOCKED_DOOR_5", TerrainTag::LOCKED_DOOR_5 }, + { "LOCKED_DOOR_6", TerrainTag::LOCKED_DOOR_6 }, + { "LOCKED_DOOR_7", TerrainTag::LOCKED_DOOR_7 }, + + { "JAMMED_DOOR_0", TerrainTag::JAMMED_DOOR_0 }, + { "JAMMED_DOOR_1", TerrainTag::JAMMED_DOOR_1 }, + { "JAMMED_DOOR_2", TerrainTag::JAMMED_DOOR_2 }, + { "JAMMED_DOOR_3", TerrainTag::JAMMED_DOOR_3 }, + { "JAMMED_DOOR_4", TerrainTag::JAMMED_DOOR_4 }, + { "JAMMED_DOOR_5", TerrainTag::JAMMED_DOOR_5 }, + { "JAMMED_DOOR_6", TerrainTag::JAMMED_DOOR_6 }, + { "JAMMED_DOOR_7", TerrainTag::JAMMED_DOOR_7 }, + + { "LOCKED_GLASS_DOOR_1", TerrainTag::LOCKED_GLASS_DOOR_1 }, + { "LOCKED_GLASS_DOOR_2", TerrainTag::LOCKED_GLASS_DOOR_2 }, + { "LOCKED_GLASS_DOOR_3", TerrainTag::LOCKED_GLASS_DOOR_3 }, + { "LOCKED_GLASS_DOOR_4", TerrainTag::LOCKED_GLASS_DOOR_4 }, + { "LOCKED_GLASS_DOOR_5", TerrainTag::LOCKED_GLASS_DOOR_5 }, + { "LOCKED_GLASS_DOOR_6", TerrainTag::LOCKED_GLASS_DOOR_6 }, + { "LOCKED_GLASS_DOOR_7", TerrainTag::LOCKED_GLASS_DOOR_7 }, + + { "JAMMED_GLASS_DOOR_0", TerrainTag::JAMMED_GLASS_DOOR_0 }, + { "JAMMED_GLASS_DOOR_1", TerrainTag::JAMMED_GLASS_DOOR_1 }, + { "JAMMED_GLASS_DOOR_2", TerrainTag::JAMMED_GLASS_DOOR_2 }, + { "JAMMED_GLASS_DOOR_3", TerrainTag::JAMMED_GLASS_DOOR_3 }, + { "JAMMED_GLASS_DOOR_4", TerrainTag::JAMMED_GLASS_DOOR_4 }, + { "JAMMED_GLASS_DOOR_5", TerrainTag::JAMMED_GLASS_DOOR_5 }, + { "JAMMED_GLASS_DOOR_6", TerrainTag::JAMMED_GLASS_DOOR_6 }, + { "JAMMED_GLASS_DOOR_7", TerrainTag::JAMMED_GLASS_DOOR_7 }, + + { "OPEN_DOOR", TerrainTag::OPEN_DOOR }, + { "BROKEN_DOOR", TerrainTag::BROKEN_DOOR }, + { "CLOSED_DOOR", TerrainTag::CLOSED_DOOR }, + { "OPEN_GLASS_DOOR", TerrainTag::OPEN_GLASS_DOOR }, + { "BROKEN_GLASS_DOOR", TerrainTag::BROKEN_GLASS_DOOR }, + { "CLOSED_GLASS_DOOR", TerrainTag::CLOSED_GLASS_DOOR }, + { "OPEN_CURTAIN", TerrainTag::OPEN_CURTAIN }, + { "CLOSED_CURTAIN", TerrainTag::CLOSED_CURTAIN }, }; diff --git a/src/info-reader/feature-reader.cpp b/src/info-reader/feature-reader.cpp index 536bd61d60..94680c7c1e 100644 --- a/src/info-reader/feature-reader.cpp +++ b/src/info-reader/feature-reader.cpp @@ -2,18 +2,21 @@ #include "floor/wild.h" #include "grid/feature.h" #include "grid/grid.h" -#include "grid/trap.h" #include "info-reader/feature-info-tokens-table.h" #include "info-reader/info-reader-util.h" #include "info-reader/parse-error-types.h" #include "main/angband-headers.h" #include "room/door-definition.h" +#include "system/enums/terrain/terrain-tag.h" #include "system/terrain/terrain-definition.h" #include "system/terrain/terrain-list.h" #include "term/gameterm.h" #include "util/bit-flags-calculator.h" +#include "util/enum-range.h" #include "util/string-processor.h" #include "view/display-messages.h" +#include +#include /*! * @brief テキストトークンを走査してフラグを一つ得る(地形情報向け) / @@ -302,66 +305,34 @@ void init_feat_variables() terrains.emplace_tag(tag.first); } - feat_door[DOOR_DOOR].open = terrains.get_terrain_id_by_tag("OPEN_DOOR"); - feat_door[DOOR_DOOR].broken = terrains.get_terrain_id_by_tag("BROKEN_DOOR"); - feat_door[DOOR_DOOR].closed = terrains.get_terrain_id_by_tag("CLOSED_DOOR"); + /* Normal doors */ + feat_door[DoorKind::DOOR].open = TerrainTag::OPEN_DOOR; + feat_door[DoorKind::DOOR].broken = TerrainTag::BROKEN_DOOR; + feat_door[DoorKind::DOOR].closed = TerrainTag::CLOSED_DOOR; - /* Locked doors */ - for (auto i = 1; i < MAX_LJ_DOORS; i++) { - feat_door[DOOR_DOOR].locked[i - 1] = terrains.get_terrain_id_by_tag(format("LOCKED_DOOR_%d", i)); - } - feat_door[DOOR_DOOR].num_locked = MAX_LJ_DOORS - 1; + /* Glass doors */ + feat_door[DoorKind::GLASS_DOOR].open = TerrainTag::OPEN_GLASS_DOOR; + feat_door[DoorKind::GLASS_DOOR].broken = TerrainTag::BROKEN_GLASS_DOOR; + feat_door[DoorKind::GLASS_DOOR].closed = TerrainTag::CLOSED_GLASS_DOOR; - /* Jammed doors */ - for (auto i = 0; i < MAX_LJ_DOORS; i++) { - feat_door[DOOR_DOOR].jammed[i] = terrains.get_terrain_id_by_tag(format("JAMMED_DOOR_%d", i)); - } - feat_door[DOOR_DOOR].num_jammed = MAX_LJ_DOORS; + constexpr auto locked_door_tags = EnumRangeInclusive(TerrainTag::LOCKED_DOOR_1, TerrainTag::LOCKED_DOOR_7); + feat_door[DoorKind::DOOR].locked.assign(locked_door_tags.begin(), locked_door_tags.end()); - /* Glass doors */ - feat_door[DOOR_GLASS_DOOR].open = terrains.get_terrain_id_by_tag("OPEN_GLASS_DOOR"); - feat_door[DOOR_GLASS_DOOR].broken = terrains.get_terrain_id_by_tag("BROKEN_GLASS_DOOR"); - feat_door[DOOR_GLASS_DOOR].closed = terrains.get_terrain_id_by_tag("CLOSED_GLASS_DOOR"); + constexpr auto locked_glass_door_tags = EnumRangeInclusive(TerrainTag::LOCKED_GLASS_DOOR_1, TerrainTag::LOCKED_GLASS_DOOR_7); + feat_door[DoorKind::GLASS_DOOR].locked.assign(locked_glass_door_tags.begin(), locked_glass_door_tags.end()); - /* Locked glass doors */ - for (auto i = 1; i < MAX_LJ_DOORS; i++) { - feat_door[DOOR_GLASS_DOOR].locked[i - 1] = terrains.get_terrain_id_by_tag(format("LOCKED_GLASS_DOOR_%d", i)); - } - feat_door[DOOR_GLASS_DOOR].num_locked = MAX_LJ_DOORS - 1; + constexpr auto jammed_door_tags = EnumRangeInclusive(TerrainTag::JAMMED_DOOR_0, TerrainTag::JAMMED_DOOR_7); + feat_door[DoorKind::DOOR].jammed.assign(jammed_door_tags.begin(), jammed_door_tags.end()); - /* Jammed glass doors */ - for (auto i = 0; i < MAX_LJ_DOORS; i++) { - feat_door[DOOR_GLASS_DOOR].jammed[i] = terrains.get_terrain_id_by_tag(format("JAMMED_GLASS_DOOR_%d", i)); - } - feat_door[DOOR_GLASS_DOOR].num_jammed = MAX_LJ_DOORS; + constexpr auto jammed_glass_door_tags = EnumRangeInclusive(TerrainTag::JAMMED_GLASS_DOOR_0, TerrainTag::JAMMED_GLASS_DOOR_7); + feat_door[DoorKind::GLASS_DOOR].jammed.assign(jammed_glass_door_tags.begin(), jammed_glass_door_tags.end()); /* Curtains */ - feat_door[DOOR_CURTAIN].open = terrains.get_terrain_id_by_tag("OPEN_CURTAIN"); - feat_door[DOOR_CURTAIN].broken = feat_door[DOOR_CURTAIN].open; - feat_door[DOOR_CURTAIN].closed = terrains.get_terrain_id_by_tag("CLOSED_CURTAIN"); - feat_door[DOOR_CURTAIN].locked[0] = feat_door[DOOR_CURTAIN].closed; - feat_door[DOOR_CURTAIN].num_locked = 1; - feat_door[DOOR_CURTAIN].jammed[0] = feat_door[DOOR_CURTAIN].closed; - feat_door[DOOR_CURTAIN].num_jammed = 1; - - /* Normal traps */ - init_normal_traps(); - - /* Special traps */ - feat_trap_open = terrains.get_terrain_id_by_tag("TRAP_OPEN"); - feat_trap_armageddon = terrains.get_terrain_id_by_tag("TRAP_ARMAGEDDON"); - feat_trap_piranha = terrains.get_terrain_id_by_tag("TRAP_PIRANHA"); - - /* Pattern */ - feat_pattern_start = terrains.get_terrain_id_by_tag("PATTERN_START"); - feat_pattern_1 = terrains.get_terrain_id_by_tag("PATTERN_1"); - feat_pattern_2 = terrains.get_terrain_id_by_tag("PATTERN_2"); - feat_pattern_3 = terrains.get_terrain_id_by_tag("PATTERN_3"); - feat_pattern_4 = terrains.get_terrain_id_by_tag("PATTERN_4"); - feat_pattern_end = terrains.get_terrain_id_by_tag("PATTERN_END"); - feat_pattern_old = terrains.get_terrain_id_by_tag("PATTERN_OLD"); - feat_pattern_exit = terrains.get_terrain_id_by_tag("PATTERN_EXIT"); - feat_pattern_corrupted = terrains.get_terrain_id_by_tag("PATTERN_CORRUPTED"); + feat_door[DoorKind::CURTAIN].open = TerrainTag::OPEN_CURTAIN; + feat_door[DoorKind::CURTAIN].broken = TerrainTag::OPEN_CURTAIN; + feat_door[DoorKind::CURTAIN].closed = TerrainTag::CLOSED_CURTAIN; + feat_door[DoorKind::CURTAIN].locked.push_back(TerrainTag::CLOSED_CURTAIN); + feat_door[DoorKind::CURTAIN].jammed.push_back(TerrainTag::CLOSED_CURTAIN); init_wilderness_terrains(); } diff --git a/src/load/old/load-v1-5-0.cpp b/src/load/old/load-v1-5-0.cpp index 008065a249..7e6304569b 100644 --- a/src/load/old/load-v1-5-0.cpp +++ b/src/load/old/load-v1-5-0.cpp @@ -9,9 +9,7 @@ #include "artifact/fixed-art-types.h" #include "floor/floor-object.h" #include "game-option/birth-options.h" -#include "grid/feature.h" #include "grid/grid.h" -#include "grid/trap.h" #include "load/angband-version-comparer.h" #include "load/item/item-loader-factory.h" #include "load/item/item-loader-version-types.h" @@ -678,10 +676,10 @@ errr rd_dungeon_old(PlayerType *player_ptr) } else if (grid.info & CAVE_TRAP) { grid.info &= ~CAVE_TRAP; grid.set_mimic_terrain_id(TerrainTag::FLOOR); - grid.feat = choose_random_trap(&floor); + grid.set_terrain_id(floor.select_random_trap()); } else if (grid.feat == OLD_FEAT_INVIS) { grid.mimic = grid.feat; - grid.feat = feat_trap_open; + grid.set_terrain_id(TerrainTag::TRAP_OPEN); } } } diff --git a/src/melee/melee-spell-flags-checker.cpp b/src/melee/melee-spell-flags-checker.cpp index 6506382594..32c43d927e 100644 --- a/src/melee/melee-spell-flags-checker.cpp +++ b/src/melee/melee-spell-flags-checker.cpp @@ -164,7 +164,7 @@ static void check_melee_spell_distance(PlayerType *player_ptr, melee_spell_type auto should_preserve = !projectable(player_ptr, pos_real, p_pos); should_preserve &= ms_ptr->ability_flags.has(MonsterAbilityType::BA_LITE); should_preserve &= Grid::calc_distance(pos_real, p_pos) <= 4; - should_preserve &= los(player_ptr, pos_real.y, pos_real.x, p_pos.y, p_pos.x); + should_preserve &= los(*player_ptr->current_floor_ptr, pos_real, p_pos); if (should_preserve) { ms_ptr->ability_flags.reset(MonsterAbilityType::BA_LITE); return; @@ -375,7 +375,7 @@ bool check_melee_spell_set(PlayerType *player_ptr, melee_spell_type *ms_ptr) ms_ptr->x = ms_ptr->t_ptr->fx; ms_ptr->m_ptr->reset_target(); ms_ptr->ability_flags.reset({ MonsterAbilityType::WORLD, MonsterAbilityType::TRAPS, MonsterAbilityType::FORGET }); - if (ms_ptr->ability_flags.has(MonsterAbilityType::BR_LITE) && !los(player_ptr, ms_ptr->m_ptr->fy, ms_ptr->m_ptr->fx, ms_ptr->t_ptr->fy, ms_ptr->t_ptr->fx)) { + if (ms_ptr->ability_flags.has(MonsterAbilityType::BR_LITE) && !los(*player_ptr->current_floor_ptr, ms_ptr->m_ptr->get_position(), ms_ptr->t_ptr->get_position())) { ms_ptr->ability_flags.reset(MonsterAbilityType::BR_LITE); } diff --git a/src/monster-floor/monster-sweep-grid.cpp b/src/monster-floor/monster-sweep-grid.cpp index a3d1f66790..33134289cf 100644 --- a/src/monster-floor/monster-sweep-grid.cpp +++ b/src/monster-floor/monster-sweep-grid.cpp @@ -62,7 +62,7 @@ bool MonsterSweepGrid::get_movable_grid() if (t_m_idx > 0) { const auto is_enemies = monster_from.is_hostile_to_melee(floor.m_list[t_m_idx]); const Pos2D pos_from = monster_from.get_position(); - const auto is_los = los(this->player_ptr, pos_from.y, pos_from.x, pos_to.y, pos_to.x); + const auto is_los = los(floor, pos_from, pos_to); const auto is_projectable = projectable(this->player_ptr, pos_from, pos_to); if (is_enemies && is_los && is_projectable) { y = pos_from.y - pos_to.y; @@ -145,7 +145,7 @@ void MonsterSweepGrid::check_hiding_grid(POSITION *y, POSITION *x, POSITION *y2, const auto m_pos = monster.get_position(); const auto gf = monrace.get_grid_flow_type(); const auto distance = floor.get_grid(m_pos).get_distance(gf); - if ((!los(this->player_ptr, m_pos.y, m_pos.x, p_pos.y, p_pos.x) || !projectable(this->player_ptr, m_pos, p_pos))) { + if (!los(floor, m_pos, p_pos) || !projectable(this->player_ptr, m_pos, p_pos)) { if (distance >= MAX_PLAYER_SIGHT / 2) { return; } diff --git a/src/monster-floor/quantum-effect.cpp b/src/monster-floor/quantum-effect.cpp index 26a93c278a..7620658f74 100644 --- a/src/monster-floor/quantum-effect.cpp +++ b/src/monster-floor/quantum-effect.cpp @@ -51,8 +51,9 @@ static void vanish_nonunique(PlayerType *player_ptr, MONSTER_IDX m_idx, bool see */ static void produce_quantum_effect(PlayerType *player_ptr, MONSTER_IDX m_idx, bool see_m) { - auto *m_ptr = &player_ptr->current_floor_ptr->m_list[m_idx]; - bool coherent = los(player_ptr, m_ptr->fy, m_ptr->fx, player_ptr->y, player_ptr->x); + const auto &floor = *player_ptr->current_floor_ptr; + auto *m_ptr = &floor.m_list[m_idx]; + const auto coherent = los(floor, m_ptr->get_position(), player_ptr->get_position()); if (!see_m && !coherent) { return; } diff --git a/src/mspell/mspell-checker.cpp b/src/mspell/mspell-checker.cpp index d52d049d20..4f5ac05ad2 100644 --- a/src/mspell/mspell-checker.cpp +++ b/src/mspell/mspell-checker.cpp @@ -104,10 +104,10 @@ bool raise_possible(PlayerType *player_ptr, MonsterEntity *m_ptr) for (auto xx = m_pos.x - 5; xx <= m_pos.x + 5; xx++) { for (auto yy = m_pos.y - 5; yy <= m_pos.y + 5; yy++) { const Pos2D pos(yy, xx); - if (Grid::calc_distance(m_pos, { yy, xx }) > 5) { + if (Grid::calc_distance(m_pos, pos) > 5) { continue; } - if (!los(player_ptr, m_pos.y, m_pos.x, yy, xx)) { + if (!los(floor, m_pos, pos)) { continue; } if (!projectable(player_ptr, m_pos, pos)) { diff --git a/src/mspell/mspell-judgement.cpp b/src/mspell/mspell-judgement.cpp index e87fdfc729..bff1d21b45 100644 --- a/src/mspell/mspell-judgement.cpp +++ b/src/mspell/mspell-judgement.cpp @@ -131,10 +131,10 @@ bool breath_direct(PlayerType *player_ptr, const Pos2D &pos_source, const Pos2D hityou = true; } } else if (flg & PROJECT_LOS) { - if (los(player_ptr, pos_source.y, pos_source.x, pos_target.y, pos_target.x) && (Grid::calc_distance(pos_source, pos_target) <= rad)) { + if (los(floor, pos_source, pos_target) && (Grid::calc_distance(pos_source, pos_target) <= rad)) { hit2 = true; } - if (los(player_ptr, pos_source.y, pos_source.x, p_pos.y, p_pos.x) && (Grid::calc_distance(pos_source, p_pos) <= rad)) { + if (los(floor, pos_source, p_pos) && (Grid::calc_distance(pos_source, p_pos) <= rad)) { hityou = true; } } else { diff --git a/src/mspell/mspell-lite.cpp b/src/mspell/mspell-lite.cpp index ba248bb4d5..ac017bc2a9 100644 --- a/src/mspell/mspell-lite.cpp +++ b/src/mspell/mspell-lite.cpp @@ -55,7 +55,8 @@ bool adjacent_grid_check(PlayerType *player_ptr, MonsterEntity *m_ptr, POSITION for (int i = 0; i < 8; i++) { const Pos2DVec vec(tonari_y[next][i], tonari_x[next][i]); const auto pos_next = pos + vec; - const auto &grid = player_ptr->current_floor_ptr->get_grid(pos_next); + const auto &floor = *player_ptr->current_floor_ptr; + const auto &grid = floor.get_grid(pos_next); if (!grid.has(f_flag)) { continue; } @@ -66,7 +67,7 @@ bool adjacent_grid_check(PlayerType *player_ptr, MonsterEntity *m_ptr, POSITION check_result = projectable(player_ptr, m_ptr->get_position(), pos_next); break; case PathChecker::LOS: - check_result = los(player_ptr, m_ptr->fy, m_ptr->fx, pos_next.y, pos_next.x); + check_result = los(floor, m_ptr->get_position(), pos_next); break; default: THROW_EXCEPTION(std::logic_error, format("Invalid PathChecker is specified! %d", enum2i(checker))); @@ -90,9 +91,10 @@ void decide_lite_range(PlayerType *player_ptr, msa_type *msa_ptr) msa_ptr->y_br_lite = msa_ptr->y; msa_ptr->x_br_lite = msa_ptr->x; - if (los(player_ptr, msa_ptr->m_ptr->fy, msa_ptr->m_ptr->fx, msa_ptr->y_br_lite, msa_ptr->x_br_lite)) { + const auto &floor = *player_ptr->current_floor_ptr; + if (los(floor, msa_ptr->m_ptr->get_position(), { msa_ptr->y_br_lite, msa_ptr->x_br_lite })) { const Pos2D pos(msa_ptr->y_br_lite, msa_ptr->x_br_lite); - const auto &terrain = player_ptr->current_floor_ptr->get_grid(pos).get_terrain(); + const auto &terrain = floor.get_grid(pos).get_terrain(); if (terrain.flags.has_not(TerrainCharacteristics::LOS) && terrain.flags.has(TerrainCharacteristics::PROJECT) && one_in_(2)) { msa_ptr->ability_flags.reset(MonsterAbilityType::BR_LITE); } @@ -133,7 +135,8 @@ static void check_lite_area_by_mspell(PlayerType *player_ptr, msa_type *msa_ptr) light_by_disintegration &= msa_ptr->m_ptr->cdis < system.get_max_range() / 2; const auto pos = msa_ptr->get_position(); const auto m_pos = msa_ptr->m_ptr->get_position(); - light_by_disintegration &= in_disintegration_range(player_ptr->current_floor_ptr, m_pos.y, m_pos.x, pos.y, pos.x); + const auto &floor = *player_ptr->current_floor_ptr; + light_by_disintegration &= in_disintegration_range(&floor, m_pos.y, m_pos.x, pos.y, pos.x); light_by_disintegration &= one_in_(10) || (projectable(player_ptr, pos, m_pos) && one_in_(2)); if (light_by_disintegration) { msa_ptr->do_spell = DO_SPELL_BR_DISI; @@ -143,7 +146,7 @@ static void check_lite_area_by_mspell(PlayerType *player_ptr, msa_type *msa_ptr) auto light_by_lite = msa_ptr->ability_flags.has(MonsterAbilityType::BR_LITE); light_by_lite &= msa_ptr->m_ptr->cdis < system.get_max_range() / 2; - light_by_lite &= los(player_ptr, m_pos.y, m_pos.x, msa_ptr->y, msa_ptr->x); + light_by_lite &= los(floor, m_pos, pos); light_by_lite &= one_in_(5); if (light_by_lite) { msa_ptr->do_spell = DO_SPELL_BR_LITE; @@ -156,7 +159,7 @@ static void check_lite_area_by_mspell(PlayerType *player_ptr, msa_type *msa_ptr) } const auto pos_breath = get_project_point(player_ptr, m_pos, msa_ptr->get_position(), 0); - if ((Grid::calc_distance(pos_breath, pos) <= 3) && los(player_ptr, pos_breath.y, pos_breath.x, pos.y, pos.x) && one_in_(5)) { + if ((Grid::calc_distance(pos_breath, pos) <= 3) && los(floor, pos_breath, pos) && one_in_(5)) { msa_ptr->do_spell = DO_SPELL_BA_LITE; msa_ptr->success = true; } diff --git a/src/player/player-status.cpp b/src/player/player-status.cpp index 08d8d9c773..6d35c215fc 100644 --- a/src/player/player-status.cpp +++ b/src/player/player-status.cpp @@ -95,6 +95,7 @@ #include "status/base-status.h" #include "sv-definition/sv-lite-types.h" #include "sv-definition/sv-weapon-types.h" +#include "system/enums/terrain/terrain-tag.h" #include "system/floor/floor-info.h" #include "system/grid-type-definition.h" #include "system/item-entity.h" @@ -2753,11 +2754,11 @@ void wreck_the_pattern(PlayerType *player_ptr) while (to_ruin--) { const auto pos = scatter(player_ptr, p_pos, 4, PROJECT_NONE); if (pattern_tile(&floor, pos.y, pos.x) && (floor.get_grid(pos).get_terrain().subtype != PATTERN_TILE_WRECKED)) { - cave_set_feat(player_ptr, pos.y, pos.x, feat_pattern_corrupted); + cave_set_feat(player_ptr, pos, TerrainTag::PATTERN_CORRUPTED); } } - cave_set_feat(player_ptr, p_pos.y, p_pos.x, feat_pattern_corrupted); + cave_set_feat(player_ptr, p_pos, TerrainTag::PATTERN_CORRUPTED); } /*! diff --git a/src/player/player-view.cpp b/src/player/player-view.cpp index 0a9e270c2a..229d3cf9b7 100644 --- a/src/player/player-view.cpp +++ b/src/player/player-view.cpp @@ -71,7 +71,7 @@ static bool update_view_aux(PlayerType *player_ptr, POSITION y, POSITION x, POSI return wall; } - if (los(player_ptr, player_ptr->y, player_ptr->x, y, x)) { + if (los(*floor_ptr, player_ptr->get_position(), { y, x })) { cave_view_hack(floor_ptr, y, x); return wall; } diff --git a/src/room/door-definition.cpp b/src/room/door-definition.cpp index 133644b9ad..506b85fbf9 100644 --- a/src/room/door-definition.cpp +++ b/src/room/door-definition.cpp @@ -1,3 +1,3 @@ #include "room/door-definition.h" -door_type feat_door[MAX_DOOR_TYPES]; +std::map feat_door; diff --git a/src/room/door-definition.h b/src/room/door-definition.h index 7b5cf4309c..9bebee3c29 100644 --- a/src/room/door-definition.h +++ b/src/room/door-definition.h @@ -1,30 +1,33 @@ #pragma once -#include "system/angband.h" +#include +#include #define DUN_ROOMS_MAX 40 /*!< 部屋生成処理の基本比率(ダンジョンのサイズに比例する) / Max number rate of rooms */ -/* Maximum locked/jammed doors */ -#define MAX_LJ_DOORS 8 - -#define MAX_DOOR_TYPES 3 +enum class DoorKind { + DEFAULT = -1, + DOOR = 0, + GLASS_DOOR = 1, + CURTAIN = 2, +}; -enum door_kind_type { - DOOR_DEFAULT = -1, - DOOR_DOOR = 0, - DOOR_GLASS_DOOR = 1, - DOOR_CURTAIN = 2, +enum class LockJam { + LOCKED, + JAMMED, }; /* A structure type for doors */ -struct door_type { - FEAT_IDX open; - FEAT_IDX broken; - FEAT_IDX closed; - FEAT_IDX locked[MAX_LJ_DOORS]; - FEAT_IDX num_locked; - FEAT_IDX jammed[MAX_LJ_DOORS]; - FEAT_IDX num_jammed; +enum class TerrainTag; +class Door { +public: + Door() = default; + + TerrainTag open{}; + TerrainTag broken{}; + TerrainTag closed{}; + std::vector locked; + std::vector jammed; }; -extern door_type feat_door[MAX_DOOR_TYPES]; +extern std::map feat_door; diff --git a/src/room/rooms-builder.cpp b/src/room/rooms-builder.cpp index 322f4556df..edeef1ec19 100644 --- a/src/room/rooms-builder.cpp +++ b/src/room/rooms-builder.cpp @@ -76,7 +76,7 @@ void build_small_room(PlayerType *player_ptr, POSITION x0, POSITION y0) } const auto n = randint0(4); - place_secret_door(player_ptr, y0 + ddy_ddd[n], x0 + ddx_ddd[n], DOOR_DEFAULT); + place_secret_door(player_ptr, y0 + ddy_ddd[n], x0 + ddx_ddd[n], DoorKind::DEFAULT); player_ptr->current_floor_ptr->grid_array[y0][x0].mimic = 0; place_bold(player_ptr, y0, x0, GB_FLOOR); diff --git a/src/room/rooms-nest.cpp b/src/room/rooms-nest.cpp index 8b8194cd2c..750f193eca 100644 --- a/src/room/rooms-nest.cpp +++ b/src/room/rooms-nest.cpp @@ -104,16 +104,16 @@ void generate_inner_room(PlayerType *player_ptr, const Pos2D ¢er, Rect2D &re /* Place a secret door */ switch (randint1(4)) { case 1: - place_secret_door(player_ptr, inner_rectangle.top_left.y - 1, center.x, DOOR_DEFAULT); + place_secret_door(player_ptr, inner_rectangle.top_left.y - 1, center.x, DoorKind::DEFAULT); break; case 2: - place_secret_door(player_ptr, inner_rectangle.bottom_right.y + 1, center.x, DOOR_DEFAULT); + place_secret_door(player_ptr, inner_rectangle.bottom_right.y + 1, center.x, DoorKind::DEFAULT); break; case 3: - place_secret_door(player_ptr, center.y, inner_rectangle.top_left.x - 1, DOOR_DEFAULT); + place_secret_door(player_ptr, center.y, inner_rectangle.top_left.x - 1, DoorKind::DEFAULT); break; case 4: - place_secret_door(player_ptr, center.y, inner_rectangle.bottom_right.x + 1, DOOR_DEFAULT); + place_secret_door(player_ptr, center.y, inner_rectangle.bottom_right.x + 1, DoorKind::DEFAULT); break; } } diff --git a/src/room/rooms-normal.cpp b/src/room/rooms-normal.cpp index 60ca8e4066..113f625226 100644 --- a/src/room/rooms-normal.cpp +++ b/src/room/rooms-normal.cpp @@ -136,7 +136,7 @@ bool build_type1(PlayerType *player_ptr, DungeonData *dd_ptr) for (auto x = left; x <= right; x++) { place_bold(player_ptr, center->y, x, GB_INNER); if (should_close_curtain) { - floor.get_grid({ center->y, x }).feat = feat_door[DOOR_CURTAIN].closed; + floor.set_terrain_id_at({ center->y, x }, feat_door.at(DoorKind::CURTAIN).closed); } } @@ -148,7 +148,7 @@ bool build_type1(PlayerType *player_ptr, DungeonData *dd_ptr) for (auto y = top; y <= bottom; y++) { place_bold(player_ptr, y, center->x, GB_INNER); if (should_close_curtain) { - floor.get_grid({ y, center->x }).feat = feat_door[DOOR_CURTAIN].closed; + floor.set_terrain_id_at({ y, center->x }, feat_door.at(DoorKind::CURTAIN).closed); } } @@ -159,7 +159,7 @@ bool build_type1(PlayerType *player_ptr, DungeonData *dd_ptr) place_random_door(player_ptr, center->y, center->x, true); if (should_close_curtain) { - floor.get_grid(*center).feat = feat_door[DOOR_CURTAIN].closed; + floor.set_terrain_id_at(*center, feat_door.at(DoorKind::CURTAIN).closed); } return true; @@ -385,16 +385,16 @@ bool build_type3(PlayerType *player_ptr, DungeonData *dd_ptr) /* Place a secret door on the inner room */ switch (randint0(4)) { case 0: - place_secret_door(player_ptr, y1b, center->x, DOOR_DEFAULT); + place_secret_door(player_ptr, y1b, center->x, DoorKind::DEFAULT); break; case 1: - place_secret_door(player_ptr, y2b, center->x, DOOR_DEFAULT); + place_secret_door(player_ptr, y2b, center->x, DoorKind::DEFAULT); break; case 2: - place_secret_door(player_ptr, center->y, x1a, DOOR_DEFAULT); + place_secret_door(player_ptr, center->y, x1a, DoorKind::DEFAULT); break; case 3: - place_secret_door(player_ptr, center->y, x2a, DOOR_DEFAULT); + place_secret_door(player_ptr, center->y, x2a, DoorKind::DEFAULT); break; } @@ -436,9 +436,9 @@ bool build_type3(PlayerType *player_ptr, DungeonData *dd_ptr) /* Sometimes shut using secret doors */ if (one_in_(3)) { - int door_type = (dungeon.flags.has(DungeonFeatureType::CURTAIN) && one_in_(dungeon.flags.has(DungeonFeatureType::NO_CAVE) ? 16 : 256)) - ? DOOR_CURTAIN - : (dungeon.flags.has(DungeonFeatureType::GLASS_DOOR) ? DOOR_GLASS_DOOR : DOOR_DOOR); + const auto door_type = (dungeon.flags.has(DungeonFeatureType::CURTAIN) && one_in_(dungeon.flags.has(DungeonFeatureType::NO_CAVE) ? 16 : 256)) + ? DoorKind::CURTAIN + : (dungeon.flags.has(DungeonFeatureType::GLASS_DOOR) ? DoorKind::GLASS_DOOR : DoorKind::DOOR); place_secret_door(player_ptr, center->y, x1a - 1, door_type); place_secret_door(player_ptr, center->y, x2a + 1, door_type); @@ -542,16 +542,16 @@ bool build_type4(PlayerType *player_ptr, DungeonData *dd_ptr) /* Place a secret door */ switch (randint1(4)) { case 1: - place_secret_door(player_ptr, y1_inner - 1, center->x, DOOR_DEFAULT); + place_secret_door(player_ptr, y1_inner - 1, center->x, DoorKind::DEFAULT); break; case 2: - place_secret_door(player_ptr, y2_inner + 1, center->x, DOOR_DEFAULT); + place_secret_door(player_ptr, y2_inner + 1, center->x, DoorKind::DEFAULT); break; case 3: - place_secret_door(player_ptr, center->y, x1_inner - 1, DOOR_DEFAULT); + place_secret_door(player_ptr, center->y, x1_inner - 1, DoorKind::DEFAULT); break; case 4: - place_secret_door(player_ptr, center->y, x2_inner + 1, DOOR_DEFAULT); + place_secret_door(player_ptr, center->y, x2_inner + 1, DoorKind::DEFAULT); break; } @@ -566,16 +566,16 @@ bool build_type4(PlayerType *player_ptr, DungeonData *dd_ptr) /* Place a secret door */ switch (randint1(4)) { case 1: - place_secret_door(player_ptr, y1_inner - 1, center->x, DOOR_DEFAULT); + place_secret_door(player_ptr, y1_inner - 1, center->x, DoorKind::DEFAULT); break; case 2: - place_secret_door(player_ptr, y2_inner + 1, center->x, DOOR_DEFAULT); + place_secret_door(player_ptr, y2_inner + 1, center->x, DoorKind::DEFAULT); break; case 3: - place_secret_door(player_ptr, center->y, x1_inner - 1, DOOR_DEFAULT); + place_secret_door(player_ptr, center->y, x1_inner - 1, DoorKind::DEFAULT); break; case 4: - place_secret_door(player_ptr, center->y, x2_inner + 1, DOOR_DEFAULT); + place_secret_door(player_ptr, center->y, x2_inner + 1, DoorKind::DEFAULT); break; } @@ -626,16 +626,16 @@ bool build_type4(PlayerType *player_ptr, DungeonData *dd_ptr) /* Place a secret door */ switch (randint1(4)) { case 1: - place_secret_door(player_ptr, y1_inner - 1, center->x, DOOR_DEFAULT); + place_secret_door(player_ptr, y1_inner - 1, center->x, DoorKind::DEFAULT); break; case 2: - place_secret_door(player_ptr, y2_inner + 1, center->x, DOOR_DEFAULT); + place_secret_door(player_ptr, y2_inner + 1, center->x, DoorKind::DEFAULT); break; case 3: - place_secret_door(player_ptr, center->y, x1_inner - 1, DOOR_DEFAULT); + place_secret_door(player_ptr, center->y, x1_inner - 1, DoorKind::DEFAULT); break; case 4: - place_secret_door(player_ptr, center->y, x2_inner + 1, DOOR_DEFAULT); + place_secret_door(player_ptr, center->y, x2_inner + 1, DoorKind::DEFAULT); break; } @@ -662,9 +662,9 @@ bool build_type4(PlayerType *player_ptr, DungeonData *dd_ptr) /* Occasionally, some Inner rooms */ if (one_in_(3)) { - int door_type = (dungeon.flags.has(DungeonFeatureType::CURTAIN) && one_in_(dungeon.flags.has(DungeonFeatureType::NO_CAVE) ? 16 : 256)) - ? DOOR_CURTAIN - : (dungeon.flags.has(DungeonFeatureType::GLASS_DOOR) ? DOOR_GLASS_DOOR : DOOR_DOOR); + const auto door_type = (dungeon.flags.has(DungeonFeatureType::CURTAIN) && one_in_(dungeon.flags.has(DungeonFeatureType::NO_CAVE) ? 16 : 256)) + ? DoorKind::CURTAIN + : (dungeon.flags.has(DungeonFeatureType::GLASS_DOOR) ? DoorKind::GLASS_DOOR : DoorKind::DOOR); /* Long horizontal walls */ for (auto x = center->x - 5; x <= center->x + 5; x++) { @@ -701,16 +701,16 @@ bool build_type4(PlayerType *player_ptr, DungeonData *dd_ptr) /* Place a secret door */ switch (randint1(4)) { case 1: - place_secret_door(player_ptr, y1_inner - 1, center->x, DOOR_DEFAULT); + place_secret_door(player_ptr, y1_inner - 1, center->x, DoorKind::DEFAULT); break; case 2: - place_secret_door(player_ptr, y2_inner + 1, center->x, DOOR_DEFAULT); + place_secret_door(player_ptr, y2_inner + 1, center->x, DoorKind::DEFAULT); break; case 3: - place_secret_door(player_ptr, center->y, x1_inner - 1, DOOR_DEFAULT); + place_secret_door(player_ptr, center->y, x1_inner - 1, DoorKind::DEFAULT); break; case 4: - place_secret_door(player_ptr, center->y, x2_inner + 1, DOOR_DEFAULT); + place_secret_door(player_ptr, center->y, x2_inner + 1, DoorKind::DEFAULT); break; } @@ -739,9 +739,9 @@ bool build_type4(PlayerType *player_ptr, DungeonData *dd_ptr) /* Four small rooms. */ case 5: { - int door_type = (dungeon.flags.has(DungeonFeatureType::CURTAIN) && one_in_(dungeon.flags.has(DungeonFeatureType::NO_CAVE) ? 16 : 256)) - ? DOOR_CURTAIN - : (dungeon.flags.has(DungeonFeatureType::GLASS_DOOR) ? DOOR_GLASS_DOOR : DOOR_DOOR); + const auto door_type = (dungeon.flags.has(DungeonFeatureType::CURTAIN) && one_in_(dungeon.flags.has(DungeonFeatureType::NO_CAVE) ? 16 : 256)) + ? DoorKind::CURTAIN + : (dungeon.flags.has(DungeonFeatureType::GLASS_DOOR) ? DoorKind::GLASS_DOOR : DoorKind::DOOR); /* Inner "cross" */ for (auto y = y1_inner; y <= y2_inner; y++) { diff --git a/src/room/rooms-pit.cpp b/src/room/rooms-pit.cpp index 6fb3a337d0..19e6736fe0 100644 --- a/src/room/rooms-pit.cpp +++ b/src/room/rooms-pit.cpp @@ -2,7 +2,6 @@ #include "game-option/cheat-options.h" #include "game-option/cheat-types.h" #include "grid/door.h" -#include "grid/feature.h" #include "grid/grid.h" #include "monster-floor/monster-generator.h" #include "monster-floor/place-monster-types.h" @@ -12,6 +11,7 @@ #include "room/pit-nest-util.h" #include "room/space-finder.h" #include "system/enums/dungeon/dungeon-id.h" +#include "system/enums/terrain/terrain-tag.h" #include "system/floor/floor-info.h" #include "system/grid-type-definition.h" #include "system/monrace/monrace-definition.h" @@ -147,16 +147,16 @@ void place_pit_inner(PlayerType *player_ptr, const Pos2D ¢er) switch (randint1(4)) { case 1: - place_secret_door(player_ptr, rectangle.top_left.y - 1, center.x, DOOR_DEFAULT); + place_secret_door(player_ptr, rectangle.top_left.y - 1, center.x, DoorKind::DEFAULT); break; case 2: - place_secret_door(player_ptr, rectangle.bottom_right.y + 1, center.x, DOOR_DEFAULT); + place_secret_door(player_ptr, rectangle.bottom_right.y + 1, center.x, DoorKind::DEFAULT); break; case 3: - place_secret_door(player_ptr, center.y, rectangle.top_left.x - 1, DOOR_DEFAULT); + place_secret_door(player_ptr, center.y, rectangle.top_left.x - 1, DoorKind::DEFAULT); break; case 4: - place_secret_door(player_ptr, center.y, rectangle.bottom_right.x + 1, DOOR_DEFAULT); + place_secret_door(player_ptr, center.y, rectangle.bottom_right.x + 1, DoorKind::DEFAULT); break; } } @@ -448,7 +448,7 @@ bool build_type13(PlayerType *player_ptr, DungeonData *dd_ptr) /* Place the wall open trap */ auto &grid = floor.get_grid(*center); grid.mimic = grid.feat; - grid.feat = feat_trap_open; + grid.set_terrain_id(TerrainTag::TRAP_OPEN); const auto &monraces = MonraceList::get_instance(); std::stable_sort(whats->begin(), whats->end(), [&monraces](const auto monrace_id1, const auto monrace_id2) { return monraces.order_level(monrace_id2, monrace_id1); diff --git a/src/room/rooms-special.cpp b/src/room/rooms-special.cpp index 100763e0cf..45255bcfcd 100644 --- a/src/room/rooms-special.cpp +++ b/src/room/rooms-special.cpp @@ -128,7 +128,7 @@ bool build_type15(PlayerType *player_ptr, DungeonData *dd_ptr) const auto dir1 = randint0(4); const auto y = center->y + 2 * ddy_ddd[dir1]; const auto x = center->x + 2 * ddx_ddd[dir1]; - place_secret_door(player_ptr, y, x, DOOR_GLASS_DOOR); + place_secret_door(player_ptr, y, x, DoorKind::GLASS_DOOR); const Pos2D pos(y, x); if (floor.has_closed_door_at(pos)) { floor.get_grid(pos).set_mimic_terrain_id(TerrainTag::GLASS_WALL); @@ -161,13 +161,13 @@ bool build_type15(PlayerType *player_ptr, DungeonData *dd_ptr) /* Curtains around the breather */ for (auto y = center->y - 1; y <= center->y + 1; y++) { - place_secret_door(player_ptr, y, center->x - 2, DOOR_CURTAIN); - place_secret_door(player_ptr, y, center->x + 2, DOOR_CURTAIN); + place_secret_door(player_ptr, y, center->x - 2, DoorKind::CURTAIN); + place_secret_door(player_ptr, y, center->x + 2, DoorKind::CURTAIN); } for (auto x = center->x - 1; x <= center->x + 1; x++) { - place_secret_door(player_ptr, center->y - 2, x, DOOR_CURTAIN); - place_secret_door(player_ptr, center->y + 2, x, DOOR_CURTAIN); + place_secret_door(player_ptr, center->y - 2, x, DoorKind::CURTAIN); + place_secret_door(player_ptr, center->y + 2, x, DoorKind::CURTAIN); } /* Place an object */ diff --git a/src/room/rooms-trap.cpp b/src/room/rooms-trap.cpp index 95e89713d6..7628d4b084 100644 --- a/src/room/rooms-trap.cpp +++ b/src/room/rooms-trap.cpp @@ -2,11 +2,11 @@ #include "dungeon/dungeon-flag-types.h" #include "floor/floor-generator.h" #include "game-option/cheat-types.h" -#include "grid/feature.h" #include "grid/grid.h" #include "room/space-finder.h" #include "system/dungeon/dungeon-data-definition.h" #include "system/dungeon/dungeon-definition.h" +#include "system/enums/terrain/terrain-tag.h" #include "system/floor/floor-info.h" #include "system/grid-type-definition.h" #include "system/player-type-definition.h" @@ -69,12 +69,12 @@ bool build_type14(PlayerType *player_ptr, DungeonData *dd_ptr) place_grid(player_ptr, &floor.get_grid({ y2 + 1, x }), GB_OUTER); } - const auto trap = floor.dun_level < 30 + randint1(30) ? feat_trap_piranha : feat_trap_armageddon; + const auto trap = floor.dun_level < 30 + randint1(30) ? TerrainTag::TRAP_PIRANHA : TerrainTag::TRAP_ARMAGEDDON; const auto trap_y = rand_spread(center->y, ysize / 4); const auto trap_x = rand_spread(center->x, xsize / 4); auto &grid = floor.get_grid({ trap_y, trap_x }); grid.mimic = grid.feat; - grid.feat = trap; + grid.set_terrain_id(trap); constexpr auto fmt = _("%sの部屋が生成されました。", "Room of %s was generated."); msg_format_wizard(player_ptr, CHEAT_DUNGEON, fmt, TerrainList::get_instance().get_terrain(trap).name.data()); return true; diff --git a/src/room/rooms-vault.cpp b/src/room/rooms-vault.cpp index 2d1fb51970..700ba0fc22 100644 --- a/src/room/rooms-vault.cpp +++ b/src/room/rooms-vault.cpp @@ -13,7 +13,6 @@ #include "floor/wild.h" #include "game-option/cheat-types.h" #include "grid/door.h" -#include "grid/feature.h" #include "grid/grid.h" #include "grid/object-placer.h" #include "grid/trap.h" @@ -379,17 +378,17 @@ static void build_vault( grid.set_terrain_id(TerrainTag::TREE); break; case '+': - place_secret_door(player_ptr, pos.y, pos.x, DOOR_DEFAULT); + place_secret_door(player_ptr, pos.y, pos.x, DoorKind::DEFAULT); break; case '-': - place_secret_door(player_ptr, pos.y, pos.x, DOOR_GLASS_DOOR); + place_secret_door(player_ptr, pos.y, pos.x, DoorKind::GLASS_DOOR); if (floor.has_closed_door_at(pos)) { grid.set_mimic_terrain_id(TerrainTag::GLASS_WALL); } break; case '\'': - place_secret_door(player_ptr, pos.y, pos.x, DOOR_CURTAIN); + place_secret_door(player_ptr, pos.y, pos.x, DoorKind::CURTAIN); break; case '^': place_trap(&floor, pos.y, pos.x); @@ -399,25 +398,25 @@ static void build_vault( store_init(VALID_TOWNS, StoreSaleType::BLACK); break; case 'p': - floor.set_terrain_id_at(pos, feat_pattern_start); + floor.set_terrain_id_at(pos, TerrainTag::PATTERN_START); break; case 'a': - floor.set_terrain_id_at(pos, feat_pattern_1); + floor.set_terrain_id_at(pos, TerrainTag::PATTERN_1); break; case 'b': - floor.set_terrain_id_at(pos, feat_pattern_2); + floor.set_terrain_id_at(pos, TerrainTag::PATTERN_2); break; case 'c': - floor.set_terrain_id_at(pos, feat_pattern_3); + floor.set_terrain_id_at(pos, TerrainTag::PATTERN_3); break; case 'd': - floor.set_terrain_id_at(pos, feat_pattern_4); + floor.set_terrain_id_at(pos, TerrainTag::PATTERN_4); break; case 'P': - floor.set_terrain_id_at(pos, feat_pattern_end); + floor.set_terrain_id_at(pos, TerrainTag::PATTERN_END); break; case 'B': - floor.set_terrain_id_at(pos, feat_pattern_exit); + floor.set_terrain_id_at(pos, TerrainTag::PATTERN_EXIT); break; case 'A': floor.object_level = floor.base_level + 12; diff --git a/src/spell-kind/spells-grid.cpp b/src/spell-kind/spells-grid.cpp index ed59025619..1237aa51c1 100644 --- a/src/spell-kind/spells-grid.cpp +++ b/src/spell-kind/spells-grid.cpp @@ -119,7 +119,7 @@ void stair_creation(PlayerType *player_ptr) continue; } - if (feat_uses_special(grid.feat)) { + if (grid.has_special_terrain()) { continue; } diff --git a/src/spell-kind/spells-teleport.cpp b/src/spell-kind/spells-teleport.cpp index ab005c0b10..d82089bb4d 100644 --- a/src/spell-kind/spells-teleport.cpp +++ b/src/spell-kind/spells-teleport.cpp @@ -527,9 +527,9 @@ void teleport_player_to(PlayerType *player_ptr, POSITION ny, POSITION nx, telepo void teleport_away_followable(PlayerType *player_ptr, MONSTER_IDX m_idx) { - auto *m_ptr = &player_ptr->current_floor_ptr->m_list[m_idx]; - POSITION oldfy = m_ptr->fy; - POSITION oldfx = m_ptr->fx; + const auto &floor = *player_ptr->current_floor_ptr; + auto *m_ptr = &floor.m_list[m_idx]; + const auto old_m_pos = m_ptr->get_position(); bool old_ml = m_ptr->ml; POSITION old_cdis = m_ptr->cdis; @@ -539,7 +539,7 @@ void teleport_away_followable(PlayerType *player_ptr, MONSTER_IDX m_idx) is_followable &= old_cdis <= MAX_PLAYER_SIGHT; is_followable &= AngbandWorld::get_instance().timewalk_m_idx == 0; is_followable &= !AngbandSystem::get_instance().is_phase_out(); - is_followable &= los(player_ptr, player_ptr->y, player_ptr->x, oldfy, oldfx); + is_followable &= los(floor, player_ptr->get_position(), old_m_pos); if (!is_followable) { return; } diff --git a/src/spell/range-calc.cpp b/src/spell/range-calc.cpp index 16a5509b7f..94829ad227 100644 --- a/src/spell/range-calc.cpp +++ b/src/spell/range-calc.cpp @@ -40,7 +40,7 @@ POSITION dist_to_line(POSITION y, POSITION x, POSITION y1, POSITION x1, POSITION * Modified version of los() for calculation of disintegration balls. * Disintegration effects are stopped by permanent walls. */ -bool in_disintegration_range(FloorType *floor_ptr, POSITION y1, POSITION x1, POSITION y2, POSITION x2) +bool in_disintegration_range(const FloorType *floor_ptr, POSITION y1, POSITION x1, POSITION y2, POSITION x2) { POSITION delta_y = y2 - y1; POSITION delta_x = x2 - x1; @@ -207,7 +207,7 @@ void breath_shape(PlayerType *player_ptr, const ProjectionPath &path, int dist, auto path_n = 0; const auto mdis = Grid::calc_distance(pos_source, pos_target) + rad; int cdis; - auto *floor_ptr = player_ptr->current_floor_ptr; + const auto &floor = *player_ptr->current_floor_ptr; while (bdis <= mdis) { if ((0 < dist) && (path_n < dist)) { const auto &pos_path = path[path_n]; @@ -226,7 +226,7 @@ void breath_shape(PlayerType *player_ptr, const ProjectionPath &path, int dist, for (auto y = pos_breath.y - cdis; y <= pos_breath.y + cdis; y++) { for (auto x = pos_breath.x - cdis; x <= pos_breath.x + cdis; x++) { const Pos2D pos(y, x); - if (!in_bounds(floor_ptr, pos.y, pos.x)) { + if (!in_bounds(&floor, pos.y, pos.x)) { continue; } if (Grid::calc_distance(pos_source, pos) != bdis) { @@ -240,13 +240,13 @@ void breath_shape(PlayerType *player_ptr, const ProjectionPath &path, int dist, case AttributeType::LITE: case AttributeType::LITE_WEAK: /* Lights are stopped by opaque terrains */ - if (!los(player_ptr, pos_breath.y, pos_breath.x, pos.y, pos.x)) { + if (!los(floor, pos_breath, pos)) { continue; } break; case AttributeType::DISINTEGRATE: /* Disintegration are stopped only by perma-walls */ - if (!in_disintegration_range(floor_ptr, pos_breath.y, pos_breath.x, pos.y, pos.x)) { + if (!in_disintegration_range(&floor, pos_breath.y, pos_breath.x, pos.y, pos.x)) { continue; } break; diff --git a/src/spell/range-calc.h b/src/spell/range-calc.h index aca0be8ddd..69a96e26a2 100644 --- a/src/spell/range-calc.h +++ b/src/spell/range-calc.h @@ -9,6 +9,6 @@ class FloorType; class PlayerType; class ProjectionPath; -bool in_disintegration_range(FloorType *floor_ptr, POSITION y1, POSITION x1, POSITION y2, POSITION x2); +bool in_disintegration_range(const FloorType *floor_ptr, POSITION y1, POSITION x1, POSITION y2, POSITION x2); void breath_shape(PlayerType *player_ptr, const ProjectionPath &path, int dist, int *pgrids, std::span positions, std::span gm, int *pgm_rad, int rad, const Pos2D &pos_source, const Pos2D &pos_target, AttributeType typ); POSITION dist_to_line(POSITION y, POSITION x, POSITION y1, POSITION x1, POSITION y2, POSITION x2); diff --git a/src/spell/spells-summon.cpp b/src/spell/spells-summon.cpp index 5101afde27..1b91c3d072 100644 --- a/src/spell/spells-summon.cpp +++ b/src/spell/spells-summon.cpp @@ -309,7 +309,7 @@ void mitokohmon(PlayerType *player_ptr) } const auto m_pos = monster.get_position(); - if (!los(player_ptr, m_pos.y, m_pos.x, p_pos.y, p_pos.x)) { + if (!los(floor, m_pos, p_pos)) { continue; } if (!projectable(player_ptr, m_pos, p_pos)) { diff --git a/src/system/enums/terrain/terrain-tag.h b/src/system/enums/terrain/terrain-tag.h index 3daeec8ddd..6c14b4f98f 100644 --- a/src/system/enums/terrain/terrain-tag.h +++ b/src/system/enums/terrain/terrain-tag.h @@ -45,4 +45,79 @@ enum class TerrainTag { TREE, MOUNTAIN, SWAMP, + + TRAP_TRAPDOOR, + TRAP_PIT, + TRAP_SPIKED_PIT, + TRAP_POISON_PIT, + TRAP_TY_CURSE, + TRAP_TELEPORT, + TRAP_FIRE, + TRAP_ACID, + TRAP_SLOW, + TRAP_LOSE_STR, + TRAP_LOSE_DEX, + TRAP_LOSE_CON, + TRAP_BLIND, + TRAP_CONFUSE, + TRAP_POISON, + TRAP_SLEEP, + TRAP_TRAPS, + TRAP_ALARM, + + TRAP_OPEN, + TRAP_PIRANHA, + TRAP_ARMAGEDDON, + PATTERN_START, + PATTERN_1, + PATTERN_2, + PATTERN_3, + PATTERN_4, + PATTERN_END, + PATTERN_OLD, + PATTERN_EXIT, + PATTERN_CORRUPTED, + + LOCKED_DOOR_1, + LOCKED_DOOR_2, + LOCKED_DOOR_3, + LOCKED_DOOR_4, + LOCKED_DOOR_5, + LOCKED_DOOR_6, + LOCKED_DOOR_7, + + JAMMED_DOOR_0, + JAMMED_DOOR_1, + JAMMED_DOOR_2, + JAMMED_DOOR_3, + JAMMED_DOOR_4, + JAMMED_DOOR_5, + JAMMED_DOOR_6, + JAMMED_DOOR_7, + + LOCKED_GLASS_DOOR_1, + LOCKED_GLASS_DOOR_2, + LOCKED_GLASS_DOOR_3, + LOCKED_GLASS_DOOR_4, + LOCKED_GLASS_DOOR_5, + LOCKED_GLASS_DOOR_6, + LOCKED_GLASS_DOOR_7, + + JAMMED_GLASS_DOOR_0, + JAMMED_GLASS_DOOR_1, + JAMMED_GLASS_DOOR_2, + JAMMED_GLASS_DOOR_3, + JAMMED_GLASS_DOOR_4, + JAMMED_GLASS_DOOR_5, + JAMMED_GLASS_DOOR_6, + JAMMED_GLASS_DOOR_7, + + OPEN_DOOR, + BROKEN_DOOR, + CLOSED_DOOR, + OPEN_GLASS_DOOR, + BROKEN_GLASS_DOOR, + CLOSED_GLASS_DOOR, + OPEN_CURTAIN, + CLOSED_CURTAIN, }; diff --git a/src/system/floor/floor-info.cpp b/src/system/floor/floor-info.cpp index 9e434cc541..23d412101d 100644 --- a/src/system/floor/floor-info.cpp +++ b/src/system/floor/floor-info.cpp @@ -23,6 +23,8 @@ #include "system/monrace/monrace-list.h" #include "system/monster-entity.h" #include "system/services/dungeon-monrace-service.h" +#include "system/terrain/terrain-definition.h" +#include "system/terrain/terrain-list.h" #include "util/bit-flags-calculator.h" #include "util/enum-range.h" #include "world/world.h" @@ -363,6 +365,32 @@ bool FloorType::filter_monrace_terrain(MonraceId monrace_id, MonraceHookTerrain } } +/*! + * @brief 基本トラップをランダムに選択する + * @return 選択したトラップのタグ (トラップドアでないならばそのタグ) + * @details トラップドアは、アリーナ・クエスト・ダンジョンの最下層には設置しない. + */ +TerrainTag FloorType::select_random_trap() const +{ + const auto &terrains = TerrainList::get_instance(); + while (true) { + const auto tag = terrains.select_normal_trap(); + if (terrains.get_terrain(tag).flags.has_not(TerrainCharacteristics::MORE)) { + return tag; + } + + if (this->inside_arena || inside_quest(this->get_quest_id())) { + continue; + } + + if (this->dun_level >= this->get_dungeon_definition().maxdepth) { + continue; + } + + return tag; + } +} + /*! * @brief モンスターの時限ステータスリストを初期化する * @details リストは逆順に走査し、死んでいるモンスターは初期化対象外とする diff --git a/src/system/floor/floor-info.h b/src/system/floor/floor-info.h index 503429ec92..e2d03ca3a3 100644 --- a/src/system/floor/floor-info.h +++ b/src/system/floor/floor-info.h @@ -120,6 +120,7 @@ class FloorType { std::optional try_make_instant_artifact() const; short select_baseitem_id(int level_initial, uint32_t mode) const; bool filter_monrace_terrain(MonraceId monrace_id, MonraceHookTerrain hook) const; + TerrainTag select_random_trap() const; void reset_mproc(); void reset_mproc_max(); diff --git a/src/system/grid-type-definition.cpp b/src/system/grid-type-definition.cpp index f48fc6d674..acb829ea17 100644 --- a/src/system/grid-type-definition.cpp +++ b/src/system/grid-type-definition.cpp @@ -214,6 +214,11 @@ bool Grid::is_darkened() const return match_bits(this->info, CAVE_VIEW | CAVE_LITE | CAVE_MNLT | CAVE_MNDK, CAVE_VIEW | CAVE_MNDK); } +bool Grid::has_special_terrain() const +{ + return this->get_terrain().flags.has(TerrainCharacteristics::SPECIAL); +} + void Grid::reset_costs() { for (const auto gf : GRID_FLOW_RANGE) { @@ -270,7 +275,7 @@ const TerrainType &Grid::get_terrain(TerrainKind tk) const void Grid::place_closed_curtain() { - this->feat = feat_door[DOOR_CURTAIN].closed; + this->set_terrain_id(feat_door.at(DoorKind::CURTAIN).closed); this->info &= ~(CAVE_MASK); } diff --git a/src/system/grid-type-definition.h b/src/system/grid-type-definition.h index 63732d9370..651014a89d 100644 --- a/src/system/grid-type-definition.h +++ b/src/system/grid-type-definition.h @@ -100,6 +100,7 @@ class Grid { bool has(TerrainCharacteristics tc) const; bool is_symbol(const int ch) const; bool is_darkened() const; + bool has_special_terrain() const; void reset_costs(); void reset_dists(); bool has_los() const; diff --git a/src/system/terrain/terrain-list.cpp b/src/system/terrain/terrain-list.cpp index 825d4120b7..0e6e48066c 100644 --- a/src/system/terrain/terrain-list.cpp +++ b/src/system/terrain/terrain-list.cpp @@ -6,11 +6,36 @@ #include "system/terrain/terrain-list.h" #include "info-reader/feature-info-tokens-table.h" +#include "system/enums/terrain/terrain-tag.h" #include "system/terrain/terrain-definition.h" #include TerrainList TerrainList::instance{}; +TerrainList::TerrainList() +{ + this->normal_traps = { + TerrainTag::TRAP_TRAPDOOR, + TerrainTag::TRAP_PIT, + TerrainTag::TRAP_SPIKED_PIT, + TerrainTag::TRAP_POISON_PIT, + TerrainTag::TRAP_TY_CURSE, + TerrainTag::TRAP_TELEPORT, + TerrainTag::TRAP_FIRE, + TerrainTag::TRAP_ACID, + TerrainTag::TRAP_SLOW, + TerrainTag::TRAP_LOSE_STR, + TerrainTag::TRAP_LOSE_DEX, + TerrainTag::TRAP_LOSE_CON, + TerrainTag::TRAP_BLIND, + TerrainTag::TRAP_CONFUSE, + TerrainTag::TRAP_POISON, + TerrainTag::TRAP_SLEEP, + TerrainTag::TRAP_TRAPS, + TerrainTag::TRAP_ALARM, + }; +} + TerrainList &TerrainList::get_instance() { return instance; @@ -60,6 +85,11 @@ short TerrainList::get_terrain_id_by_tag(std::string_view tag) const return static_cast(std::distance(this->terrains.begin(), it)); } +TerrainTag TerrainList::select_normal_trap() const +{ + return rand_choice(this->normal_traps); +} + /*! * @brief 地形情報の各種タグからIDへ変換して結果を収める */ diff --git a/src/system/terrain/terrain-list.h b/src/system/terrain/terrain-list.h index 660b203c33..b9fd5963d6 100644 --- a/src/system/terrain/terrain-list.h +++ b/src/system/terrain/terrain-list.h @@ -28,16 +28,18 @@ class TerrainList : public util::AbstractVectorWrapper { const TerrainType &get_terrain(TerrainTag tag) const; short get_terrain_id(TerrainTag tag) const; short get_terrain_id_by_tag(std::string_view tag) const; + TerrainTag select_normal_trap() const; void retouch(); void emplace_tag(std::string_view tag); private: - TerrainList() = default; + TerrainList(); static TerrainList instance; std::vector terrains; std::map tags; //!< @details 全てのTerrainTag を繰り込んだら、terrains からlookupが可能になる. そうなったら削除する. + std::vector normal_traps; std::vector &get_inner_container() override { diff --git a/src/target/target-setter.cpp b/src/target/target-setter.cpp index e610f08340..22b7e21f66 100644 --- a/src/target/target-setter.cpp +++ b/src/target/target-setter.cpp @@ -26,72 +26,72 @@ #include "util/string-processor.h" #include "window/display-sub-windows.h" #include "window/main-window-util.h" +#include #include #include -// "interesting" な座標一覧を記録する配列 -static std::vector pos_interests; - -// Target Setter. -struct ts_type { +class TargetSetter { +public: + TargetSetter(PlayerType *player_ptr, target_type mode); + void sweep_target_grids(); + +private: + std::optional pick_nearest_interest_target(const Pos2D &pos, int dir); + std::string describe_projectablity() const; + char examine_target_grid(std::string_view info, std::optional append_mode = std::nullopt) const; + void change_interest_index(int amount); + std::optional switch_target_input(); + std::optional check_panel_changed(int dir); + std::optional sweep_targets(int dir, int panel_row_min_initial, int panel_col_min_initial); + bool set_target_grid(); + std::string describe_grid_wizard() const; + std::optional> switch_next_grid_command(); + void decide_change_panel(int dir, bool move_fast); + + PlayerType *player_ptr; target_type mode; - POSITION y; - POSITION x; - POSITION y2; // panel_row_min 退避用 - POSITION x2; // panel_col_min 退避用 - bool done; - bool flag; // 移動コマンド入力時、"interesting" な座標へ飛ぶかどうか - char query; - char info[80]; - Grid *g_ptr; - TERM_LEN wid, hgt; - int m; // "interesting" な座標たちのうち現在ターゲットしているもののインデックス - int distance; // カーソルの移動方向 (1,2,3,4,6,7,8,9) - int target_num; // target_pick() の結果 - bool move_fast; // カーソル移動を粗くする(1マスずつ移動しない) + Pos2D pos_target; + bool done = false; + std::vector pos_interests; // "interesting" な座標一覧を記録する配列 + std::optional interest_index = 0; // "interesting" な座標一覧のうち現在ターゲットしているもののインデックス }; -static ts_type *initialize_target_set_type(PlayerType *player_ptr, ts_type *ts_ptr, target_type mode) +TargetSetter::TargetSetter(PlayerType *player_ptr, target_type mode) + : player_ptr(player_ptr) + , mode(mode) + , pos_target(player_ptr->get_position()) + , pos_interests(target_set_prepare(player_ptr, mode)) { - ts_ptr->mode = mode; - ts_ptr->y = player_ptr->y; - ts_ptr->x = player_ptr->x; - ts_ptr->done = false; - ts_ptr->flag = true; - std::tie(ts_ptr->wid, ts_ptr->hgt) = get_screen_size(); - ts_ptr->m = 0; - return ts_ptr; } /*! * @brief フォーカスを当てるべきマップ描画の基準座標を指定する * @param player_ptr プレイヤーへの参照ポインタ - * @param y 変更先のフロアY座標 - * @param x 変更先のフロアX座標 + * @param pos 変更先のフロア座標 * @details * Handle a request to change the current panel * Return TRUE if the panel was changed. * Also used in do_cmd_locate * @return 実際に再描画が必要だった場合TRUEを返す */ -static bool change_panel_xy(PlayerType *player_ptr, POSITION y, POSITION x) +static bool change_panel_xy(PlayerType *player_ptr, const Pos2D &pos) { auto dy = 0; auto dx = 0; [[maybe_unused]] const auto &[wid, hgt] = get_screen_size(); - if (y < panel_row_min) { + if (pos.y < panel_row_min) { dy = -1; } - if (y > panel_row_max) { + if (pos.y > panel_row_max) { dy = 1; } - if (x < panel_col_min) { + if (pos.x < panel_col_min) { dx = -1; } - if (x > panel_col_max) { + if (pos.x > panel_col_max) { dx = 1; } @@ -103,478 +103,420 @@ static bool change_panel_xy(PlayerType *player_ptr, POSITION y, POSITION x) } /*! - * @brief "interesting" な座標たちのうち、(y1,x1) から (dy,dx) 方向にある最も近いもののインデックスを得る。 - * @param y1 現在地座標y - * @param x1 現在地座標x - * @param dy 現在地からの向きy [-1,1] - * @param dx 現在地からの向きx [-1,1] - * @return 最も近い座標のインデックス。適切なものがない場合 -1 + * @brief 基準の座標から見て目標の座標が dir の方向±45°の範囲にあるかどうかを判定する + * + * @param pos_from 基準の座標 + * @param pos_to 目標の座標 + * @param dir 方向 + * @return dirの方向にある場合 true */ -static POSITION_IDX target_pick(const POSITION y1, const POSITION x1, const POSITION dy, const POSITION dx) +static bool is_roughly_in_direction(const Pos2D &pos_from, const Pos2D &pos_to, int dir) { - // 最も近いもののインデックスとその距離。 - POSITION_IDX b_i = -1, b_v = 9999; - - for (POSITION_IDX i = 0; i < std::ssize(pos_interests); i++) { - const auto &[y2, x2] = pos_interests[i]; - - // (y1,x1) から (y2,x2) へ向かうベクトル。 - const POSITION x3 = (x2 - x1); - const POSITION y3 = (y2 - y1); + const auto dy = ddy[dir]; + const auto dx = ddx[dir]; + const auto vec = pos_to - pos_from; + const Pos2DVec vec_abs(std::abs(vec.y), std::abs(vec.x)); - // (dy,dx) 方向にないものを除外する。 - - // dx > 0 のとき、x3 <= 0 なるものは除外。 - // dx < 0 のとき、x3 >= 0 なるものは除外。 - if (dx && (x3 * dx <= 0)) { - continue; - } + if (dx != 0 && (vec.x * dx <= 0)) { + return false; + } + if (dy != 0 && (vec.y * dy <= 0)) { + return false; + } - // dy > 0 のとき、y3 <= 0 なるものは除外。 - // dy < 0 のとき、y3 >= 0 なるものは除外。 - if (dy && (y3 * dy <= 0)) { - continue; - } + if (dy != 0 && dx == 0 && (vec_abs.x > vec_abs.y)) { + return false; + } + if (dx != 0 && dy == 0 && (vec_abs.y > vec_abs.x)) { + return false; + } - const POSITION x4 = std::abs(x3); - const POSITION y4 = std::abs(y3); + return true; +} - // (dy,dx) が (-1,0) or (1,0) のとき、|x3| > |y3| なるものは除外。 - if (dy && !dx && (x4 > y4)) { - continue; - } +/*! + * @brief "interesting" な座標一覧のうち、pos から dir 方向にある最も近いもののインデックスを得る。 + * @param pos 基準座標 + * @param dir 基準座標からの向き + * @return 最も近い座標のインデックス。適切なものがない場合 std::nullopt + */ +std::optional TargetSetter::pick_nearest_interest_target(const Pos2D &pos, int dir) +{ + std::optional nearest_interest_index; + std::optional nearest_distance; - // (dy,dx) が (0,-1) or (0,1) のとき、|y3| > |x3| なるものは除外。 - if (dx && !dy && (y4 > x4)) { + for (auto i = 0; i < std::ssize(this->pos_interests); i++) { + if (!is_roughly_in_direction(pos, this->pos_interests[i], dir)) { continue; } - // (y1,x1), (y2,x2) 間の距離を求め、最も近いものを更新する。 - // 距離の定義は v の式を参照。 - const POSITION_IDX v = ((x4 > y4) ? (x4 + x4 + y4) : (y4 + y4 + x4)); - if ((b_i >= 0) && (v >= b_v)) { + const auto distance = Grid::calc_distance(pos, this->pos_interests[i]); + if (nearest_interest_index && (distance >= nearest_distance)) { continue; } - b_i = i; - b_v = v; + nearest_interest_index = i; + nearest_distance = distance; } - return b_i; + return nearest_interest_index; } -static void describe_projectablity(PlayerType *player_ptr, ts_type *ts_ptr) +std::string TargetSetter::describe_projectablity() const { - ts_ptr->y = pos_interests[ts_ptr->m].y; - ts_ptr->x = pos_interests[ts_ptr->m].x; - change_panel_xy(player_ptr, ts_ptr->y, ts_ptr->x); - if ((ts_ptr->mode & TARGET_LOOK) == 0) { - print_path(player_ptr, ts_ptr->y, ts_ptr->x); + change_panel_xy(this->player_ptr, this->pos_target); + if ((this->mode & TARGET_LOOK) == 0) { + print_path(this->player_ptr, this->pos_target.y, this->pos_target.x); } - ts_ptr->g_ptr = &player_ptr->current_floor_ptr->grid_array[ts_ptr->y][ts_ptr->x]; - if (target_able(player_ptr, ts_ptr->g_ptr->m_idx)) { - angband_strcpy(ts_ptr->info, _("q止 t決 p自 o現 +次 -前", "q,t,p,o,+,-,"), sizeof(ts_ptr->info)); + std::string info; + const auto &grid = this->player_ptr->current_floor_ptr->get_grid(this->pos_target); + if (target_able(this->player_ptr, grid.m_idx)) { + info = _("q止 t決 p自 o現 +次 -前", "q,t,p,o,+,-,"); } else { - angband_strcpy(ts_ptr->info, _("q止 p自 o現 +次 -前", "q,p,o,+,-,"), sizeof(ts_ptr->info)); + info = _("q止 p自 o現 +次 -前", "q,p,o,+,-,"); } if (!cheat_sight) { - return; + return info; } + const auto p_pos = this->player_ptr->get_position(); const auto cheatinfo = format(" X:%d Y:%d LOS:%d LOP:%d", - ts_ptr->x, ts_ptr->y, - los(player_ptr, player_ptr->y, player_ptr->x, ts_ptr->y, ts_ptr->x), - projectable(player_ptr, player_ptr->get_position(), { ts_ptr->y, ts_ptr->x })); - angband_strcat(ts_ptr->info, cheatinfo, sizeof(ts_ptr->info)); + this->pos_target.x, this->pos_target.y, + los(*this->player_ptr->current_floor_ptr, p_pos, this->pos_target), + projectable(this->player_ptr, p_pos, this->pos_target)); + return info.append(cheatinfo); +} + +char TargetSetter::examine_target_grid(std::string_view info, std::optional append_mode) const +{ + const auto target_mode = append_mode ? i2enum(this->mode | *append_mode) : this->mode; + while (true) { + const auto query = examine_grid(this->player_ptr, this->pos_target.y, this->pos_target.x, target_mode, info.data()); + if (query != '\0') { + return (use_menu && (query == '\r')) ? 't' : query; + } + } } -static void menu_target(ts_type *ts_ptr) +void TargetSetter::change_interest_index(int amount) { - if (!use_menu) { + if (!this->interest_index || this->pos_interests.empty()) { + this->interest_index = std::nullopt; + return; + } + *this->interest_index += amount; + + if (*this->interest_index >= 0 && *this->interest_index < std::ssize(this->pos_interests)) { return; } - if (ts_ptr->query == '\r') { - ts_ptr->query = 't'; + // wrap around + this->interest_index = (*this->interest_index < 0) ? std::ssize(this->pos_interests) - 1 : 0; + + if (!expand_list) { + this->done = true; } } -static void switch_target_input(PlayerType *player_ptr, ts_type *ts_ptr) +std::optional TargetSetter::switch_target_input() { - ts_ptr->distance = 0; - switch (ts_ptr->query) { + const auto info = this->describe_projectablity(); + const auto query = this->examine_target_grid(info); + switch (query) { case ESCAPE: case 'q': - ts_ptr->done = true; - return; + this->done = true; + return std::nullopt; case 't': case '.': case '5': - case '0': - if (!target_able(player_ptr, ts_ptr->g_ptr->m_idx)) { + case '0': { + const auto &grid = this->player_ptr->current_floor_ptr->get_grid(this->pos_target); + if (!target_able(this->player_ptr, grid.m_idx)) { bell(); - return; + return std::nullopt; } - health_track(player_ptr, ts_ptr->g_ptr->m_idx); - target_who = ts_ptr->g_ptr->m_idx; - target_row = ts_ptr->y; - target_col = ts_ptr->x; - ts_ptr->done = true; - return; + health_track(this->player_ptr, grid.m_idx); + target_who = grid.m_idx; + target_row = this->pos_target.y; + target_col = this->pos_target.x; + this->done = true; + return std::nullopt; + } case ' ': case '*': case '+': - if (++ts_ptr->m != std::ssize(pos_interests)) { - return; - } - - ts_ptr->m = 0; - if (!expand_list) { - ts_ptr->done = true; - } - - return; + this->change_interest_index(1); + return std::nullopt; case '-': - if (ts_ptr->m-- != 0) { - return; - } - - ts_ptr->m = std::ssize(pos_interests) - 1; - if (!expand_list) { - ts_ptr->done = true; - } - - return; + this->change_interest_index(-1); + return std::nullopt; case 'p': { - verify_panel(player_ptr); + verify_panel(this->player_ptr); auto &rfu = RedrawingFlagsUpdater::get_instance(); rfu.set_flag(StatusRecalculatingFlag::MONSTER_STATUSES); rfu.set_flag(MainWindowRedrawingFlag::MAP); rfu.set_flag(SubWindowRedrawingFlag::OVERHEAD); - handle_stuff(player_ptr); - pos_interests = target_set_prepare(player_ptr, ts_ptr->mode); - ts_ptr->y = player_ptr->y; - ts_ptr->x = player_ptr->x; + handle_stuff(this->player_ptr); + this->pos_interests = target_set_prepare(this->player_ptr, this->mode); + this->pos_target = this->player_ptr->get_position(); } [[fallthrough]]; case 'o': - ts_ptr->flag = false; - return; + this->interest_index = std::nullopt; + return std::nullopt; case 'm': - return; + return std::nullopt; default: { const char queried_command = rogue_like_commands ? 'x' : 'l'; - if (ts_ptr->query != queried_command) { - ts_ptr->distance = get_keymap_dir(ts_ptr->query); - if (ts_ptr->distance == 0) { + if (query != queried_command) { + const auto dir = get_keymap_dir(query); + if (dir == 0) { bell(); + return std::nullopt; } - return; - } - - if (++ts_ptr->m != std::ssize(pos_interests)) { - return; - } - - ts_ptr->m = 0; - if (!expand_list) { - ts_ptr->done = true; + return dir; } - return; + this->change_interest_index(1); + return std::nullopt; } } } /*! * @brief カーソル移動に伴い、描画範囲、"interesting" 座標リスト、現在のターゲットを更新する。 - * @return カーソル移動によって描画範囲が変化したかどうか + * @return カーソル移動によって "interesting" な座標が選択されたらそのインデックス、そうでなければ std::nullopt */ -static bool check_panel_changed(PlayerType *player_ptr, ts_type *ts_ptr) +std::optional TargetSetter::check_panel_changed(int dir) { - // カーソル移動によって描画範囲が変化しないなら何もせずその旨を返す。 - if (!change_panel(player_ptr, ddy[ts_ptr->distance], ddx[ts_ptr->distance])) { - return false; - } - // 描画範囲が変化した場合、"interesting" 座標リストおよび現在のターゲットを更新する必要がある。 // "interesting" 座標を探す起点。 - // ts_ptr->m が有効な座標を指していればそれを使う。 - // さもなくば (ts_ptr->y, ts_ptr->x) を使う。 - int v, u; - if (ts_ptr->m < std::ssize(pos_interests)) { - v = pos_interests[ts_ptr->m].y; - u = pos_interests[ts_ptr->m].x; - } else { - v = ts_ptr->y; - u = ts_ptr->x; - } + const auto is_point_interest = (this->interest_index && *this->interest_index < std::ssize(this->pos_interests)); + const auto pos = is_point_interest ? this->pos_interests[*this->interest_index] : this->pos_target; // 新たな描画範囲を用いて "interesting" 座標リストを更新。 - pos_interests = target_set_prepare(player_ptr, ts_ptr->mode); + this->pos_interests = target_set_prepare(this->player_ptr, this->mode); - // 新たな "interesting" 座標リストからターゲットを探す。 - ts_ptr->flag = true; - ts_ptr->target_num = target_pick(v, u, ddy[ts_ptr->distance], ddx[ts_ptr->distance]); - if (ts_ptr->target_num >= 0) { - ts_ptr->m = ts_ptr->target_num; - } - - return true; + // 新たな "interesting" 座標一覧からターゲットを探す。 + return pick_nearest_interest_target(pos, dir); } /*! * @brief カーソル移動方向に "interesting" な座標がなかったとき、画面外まで探す。 * - * 既に "interesting" な座標を発見している場合、この関数は何もしない。 + * @return 画面外を探し "interesting" な座標が見つかった場合はそのインデックス、それでも見つからなければ std::nullopt */ -static void sweep_targets(PlayerType *player_ptr, ts_type *ts_ptr) +std::optional TargetSetter::sweep_targets(int dir, int panel_row_min_initial, int panel_col_min_initial) { - auto *floor_ptr = player_ptr->current_floor_ptr; - auto &rfu = RedrawingFlagsUpdater::get_instance(); - while (ts_ptr->flag && (ts_ptr->target_num < 0)) { + while (change_panel(this->player_ptr, ddy[dir], ddx[dir])) { // カーソル移動に伴い、必要なだけ描画範囲を更新。 // "interesting" 座標リストおよび現在のターゲットも更新。 - if (check_panel_changed(player_ptr, ts_ptr)) { - continue; - } - - POSITION dx = ddx[ts_ptr->distance]; - POSITION dy = ddy[ts_ptr->distance]; - panel_row_min = ts_ptr->y2; - panel_col_min = ts_ptr->x2; - panel_bounds_center(); - rfu.set_flag(StatusRecalculatingFlag::MONSTER_STATUSES); - rfu.set_flag(MainWindowRedrawingFlag::MAP); - rfu.set_flag(SubWindowRedrawingFlag::OVERHEAD); - handle_stuff(player_ptr); - pos_interests = target_set_prepare(player_ptr, ts_ptr->mode); - ts_ptr->flag = false; - ts_ptr->x += dx; - ts_ptr->y += dy; - if (((ts_ptr->x < panel_col_min + ts_ptr->wid / 2) && (dx > 0)) || ((ts_ptr->x > panel_col_min + ts_ptr->wid / 2) && (dx < 0))) { - dx = 0; + const auto target_index = this->check_panel_changed(dir); + if (target_index) { + return target_index; } + } - if (((ts_ptr->y < panel_row_min + ts_ptr->hgt / 2) && (dy > 0)) || ((ts_ptr->y > panel_row_min + ts_ptr->hgt / 2) && (dy < 0))) { - dy = 0; - } + panel_row_min = panel_row_min_initial; + panel_col_min = panel_col_min_initial; + panel_bounds_center(); - if ((ts_ptr->y >= panel_row_min + ts_ptr->hgt) || (ts_ptr->y < panel_row_min) || (ts_ptr->x >= panel_col_min + ts_ptr->wid) || (ts_ptr->x < panel_col_min)) { - if (change_panel(player_ptr, dy, dx)) { - pos_interests = target_set_prepare(player_ptr, ts_ptr->mode); - } - } + auto &rfu = RedrawingFlagsUpdater::get_instance(); + rfu.set_flag(StatusRecalculatingFlag::MONSTER_STATUSES); + rfu.set_flag(MainWindowRedrawingFlag::MAP); + rfu.set_flag(SubWindowRedrawingFlag::OVERHEAD); + handle_stuff(this->player_ptr); + + this->pos_interests = target_set_prepare(this->player_ptr, this->mode); + + auto &[y, x] = this->pos_target; + auto dy = ddy[dir]; + auto dx = ddx[dir]; + x += dx; + y += dy; + const auto [wid, hgt] = get_screen_size(); + if (((x < panel_col_min + wid / 2) && (dx > 0)) || ((x > panel_col_min + wid / 2) && (dx < 0))) { + dx = 0; + } - if (ts_ptr->x >= floor_ptr->width - 1) { - ts_ptr->x = floor_ptr->width - 2; - } else if (ts_ptr->x <= 0) { - ts_ptr->x = 1; - } + if (((y < panel_row_min + hgt / 2) && (dy > 0)) || ((y > panel_row_min + hgt / 2) && (dy < 0))) { + dy = 0; + } - if (ts_ptr->y >= floor_ptr->height - 1) { - ts_ptr->y = floor_ptr->height - 2; - } else if (ts_ptr->y <= 0) { - ts_ptr->y = 1; + if ((y >= panel_row_min + hgt) || (y < panel_row_min) || (x >= panel_col_min + wid) || (x < panel_col_min)) { + if (change_panel(this->player_ptr, dy, dx)) { + this->pos_interests = target_set_prepare(this->player_ptr, this->mode); } } + + const auto &floor = *this->player_ptr->current_floor_ptr; + x = std::clamp(x, 1, floor.width - 2); + y = std::clamp(y, 1, floor.height - 2); + return std::nullopt; } -static bool set_target_grid(PlayerType *player_ptr, ts_type *ts_ptr) +bool TargetSetter::set_target_grid() { - if (!ts_ptr->flag || pos_interests.empty()) { + if (this->pos_interests.empty() || !this->interest_index) { return false; } - describe_projectablity(player_ptr, ts_ptr); - fix_floor_item_list(player_ptr, { ts_ptr->y, ts_ptr->x }); + this->pos_target = this->pos_interests[*this->interest_index]; - while (true) { - ts_ptr->query = examine_grid(player_ptr, ts_ptr->y, ts_ptr->x, ts_ptr->mode, ts_ptr->info); - if (ts_ptr->query) { - break; - } - } + fix_floor_item_list(this->player_ptr, this->pos_target); - menu_target(ts_ptr); - switch_target_input(player_ptr, ts_ptr); - if (ts_ptr->distance == 0) { + const auto dir = this->switch_target_input(); + if (!dir) { return true; } - ts_ptr->y2 = panel_row_min; - ts_ptr->x2 = panel_col_min; - { - ts_ptr->target_num = target_pick(pos_interests[ts_ptr->m].y, pos_interests[ts_ptr->m].x, ddy[ts_ptr->distance], ddx[ts_ptr->distance]); + auto target_index = pick_nearest_interest_target(this->pos_interests[*this->interest_index], *dir); + if (!target_index) { + target_index = this->sweep_targets(*dir, panel_row_min, panel_col_min); } - sweep_targets(player_ptr, ts_ptr); - ts_ptr->m = ts_ptr->target_num; + this->interest_index = target_index; return true; } -static void describe_grid_wizard(PlayerType *player_ptr, ts_type *ts_ptr) +std::string TargetSetter::describe_grid_wizard() const { if (!cheat_sight) { - return; + return ""; } + const auto &floor = *this->player_ptr->current_floor_ptr; + const auto &grid = floor.get_grid(this->pos_target); constexpr auto fmt = " X:%d Y:%d LOS:%d LOP:%d SPECIAL:%d"; - const auto is_los = los(player_ptr, player_ptr->y, player_ptr->x, ts_ptr->y, ts_ptr->x); - const auto is_projectable = projectable(player_ptr, player_ptr->get_position(), { ts_ptr->y, ts_ptr->x }); - const auto cheatinfo = format(fmt, ts_ptr->x, ts_ptr->y, is_los, is_projectable, ts_ptr->g_ptr->special); - angband_strcat(ts_ptr->info, cheatinfo, sizeof(ts_ptr->info)); + const auto p_pos = this->player_ptr->get_position(); + const auto is_los = los(floor, p_pos, this->pos_target); + const auto is_projectable = projectable(this->player_ptr, p_pos, this->pos_target); + const auto cheatinfo = format(fmt, this->pos_target.x, this->pos_target.y, is_los, is_projectable, grid.special); + return cheatinfo; } -static void switch_next_grid_command(PlayerType *player_ptr, ts_type *ts_ptr) +/*! + * @brief 隣接マスへのターゲット切り替えモードでのコマンドを処理する + * + * @return 移動方向と早く移動するかどうかのペア。移動しない場合はstd::nullopt + */ +std::optional> TargetSetter::switch_next_grid_command() { - switch (ts_ptr->query) { + std::string info = _("q止 t決 p自 m近 +次 -前", "q,t,p,m,+,-,"); + info.append(this->describe_grid_wizard()); + const auto query = this->examine_target_grid(info, TARGET_LOOK); + switch (query) { case ESCAPE: case 'q': - ts_ptr->done = true; - break; + this->done = true; + return std::nullopt; case 't': case '.': case '5': case '0': target_who = -1; - target_row = ts_ptr->y; - target_col = ts_ptr->x; - ts_ptr->done = true; - break; + target_row = this->pos_target.y; + target_col = this->pos_target.x; + this->done = true; + return std::nullopt; case 'p': { - verify_panel(player_ptr); + verify_panel(this->player_ptr); auto &rfu = RedrawingFlagsUpdater::get_instance(); rfu.set_flag(StatusRecalculatingFlag::MONSTER_STATUSES); rfu.set_flag(MainWindowRedrawingFlag::MAP); rfu.set_flag(SubWindowRedrawingFlag::OVERHEAD); - handle_stuff(player_ptr); - pos_interests = target_set_prepare(player_ptr, ts_ptr->mode); - ts_ptr->y = player_ptr->y; - ts_ptr->x = player_ptr->x; - break; + handle_stuff(this->player_ptr); + this->pos_interests = target_set_prepare(this->player_ptr, this->mode); + this->pos_target = this->player_ptr->get_position(); + return std::nullopt; } case 'o': // ターゲット時の「m近」「o現」の切り替え // すでに「o現」の時にoを押してもなにも起きない - break; + return std::nullopt; case ' ': case '*': case '+': case '-': case 'm': { - ts_ptr->flag = true; - ts_ptr->m = 0; - int bd = 999; - for (auto i = 0; i < std::ssize(pos_interests); i++) { - const auto t = Grid::calc_distance({ ts_ptr->y, ts_ptr->x }, pos_interests[i]); - if (t < bd) { - ts_ptr->m = i; - bd = t; - } + const auto begin = this->pos_interests.begin(); + const auto end = this->pos_interests.end(); + const auto target = std::min_element(begin, end, [&](const auto &lhs, const auto &rhs) { + return Grid::calc_distance(this->pos_target, lhs) < Grid::calc_distance(this->pos_target, rhs); + }); + if (target != end) { + this->interest_index = std::distance(this->pos_interests.begin(), target); + } else { + this->interest_index = std::nullopt; } - if (bd == 999) { - ts_ptr->flag = false; - } - - break; + return std::nullopt; } default: - ts_ptr->distance = get_keymap_dir(ts_ptr->query); - if (isupper(ts_ptr->query)) { - ts_ptr->move_fast = true; - } - - if (!ts_ptr->distance) { + const auto dir = get_keymap_dir(query); + if (dir == 0) { bell(); + return std::nullopt; } - break; + const auto move_fast = isupper(query) != 0; + return std::make_pair(dir, move_fast); } } -static void decide_change_panel(PlayerType *player_ptr, ts_type *ts_ptr) +void TargetSetter::decide_change_panel(int dir, bool move_fast) { - if (ts_ptr->distance == 0) { - return; - } - - POSITION dx = ddx[ts_ptr->distance]; - POSITION dy = ddy[ts_ptr->distance]; - if (ts_ptr->move_fast) { - int mag = std::min(ts_ptr->wid / 2, ts_ptr->hgt / 2); - ts_ptr->x += dx * mag; - ts_ptr->y += dy * mag; - } else { - ts_ptr->x += dx; - ts_ptr->y += dy; - } - - if (((ts_ptr->x < panel_col_min + ts_ptr->wid / 2) && (dx > 0)) || ((ts_ptr->x > panel_col_min + ts_ptr->wid / 2) && (dx < 0))) { + auto dx = ddx[dir]; + auto dy = ddy[dir]; + auto &[y, x] = this->pos_target; + const auto [wid, hgt] = get_screen_size(); + const auto mag = move_fast ? std::min(wid / 2, hgt / 2) : 1; + x += dx * mag; + y += dy * mag; + + if (((x < panel_col_min + wid / 2) && (dx > 0)) || ((x > panel_col_min + wid / 2) && (dx < 0))) { dx = 0; } - if (((ts_ptr->y < panel_row_min + ts_ptr->hgt / 2) && (dy > 0)) || ((ts_ptr->y > panel_row_min + ts_ptr->hgt / 2) && (dy < 0))) { + if (((y < panel_row_min + hgt / 2) && (dy > 0)) || ((y > panel_row_min + hgt / 2) && (dy < 0))) { dy = 0; } - auto should_change_panel = ts_ptr->y >= panel_row_min + ts_ptr->hgt; - should_change_panel |= ts_ptr->y < panel_row_min; - should_change_panel |= ts_ptr->x >= panel_col_min + ts_ptr->wid; - should_change_panel |= ts_ptr->x < panel_col_min; - if (should_change_panel && change_panel(player_ptr, dy, dx)) { - pos_interests = target_set_prepare(player_ptr, ts_ptr->mode); + auto should_change_panel = y >= panel_row_min + hgt; + should_change_panel |= y < panel_row_min; + should_change_panel |= x >= panel_col_min + wid; + should_change_panel |= x < panel_col_min; + if (should_change_panel && change_panel(this->player_ptr, dy, dx)) { + this->pos_interests = target_set_prepare(this->player_ptr, this->mode); } - auto *floor_ptr = player_ptr->current_floor_ptr; - if (ts_ptr->x >= floor_ptr->width - 1) { - ts_ptr->x = floor_ptr->width - 2; - } else if (ts_ptr->x <= 0) { - ts_ptr->x = 1; - } - - if (ts_ptr->y >= floor_ptr->height - 1) { - ts_ptr->y = floor_ptr->height - 2; - } else if (ts_ptr->y <= 0) { - ts_ptr->y = 1; - } + auto *floor_ptr = this->player_ptr->current_floor_ptr; + x = std::clamp(x, 1, floor_ptr->width - 2); + y = std::clamp(y, 1, floor_ptr->height - 2); } -static void sweep_target_grids(PlayerType *player_ptr, ts_type *ts_ptr) +void TargetSetter::sweep_target_grids() { - while (!ts_ptr->done) { - if (set_target_grid(player_ptr, ts_ptr)) { + while (!this->done) { + if (this->set_target_grid()) { continue; } - ts_ptr->move_fast = false; - if ((ts_ptr->mode & TARGET_LOOK) == 0) { - print_path(player_ptr, ts_ptr->y, ts_ptr->x); + if ((this->mode & TARGET_LOOK) == 0) { + print_path(this->player_ptr, this->pos_target.y, this->pos_target.x); } - ts_ptr->g_ptr = &player_ptr->current_floor_ptr->grid_array[ts_ptr->y][ts_ptr->x]; - strcpy(ts_ptr->info, _("q止 t決 p自 m近 +次 -前", "q,t,p,m,+,-,")); - describe_grid_wizard(player_ptr, ts_ptr); - fix_floor_item_list(player_ptr, { ts_ptr->y, ts_ptr->x }); + fix_floor_item_list(this->player_ptr, this->pos_target); - /* Describe and Prompt (enable "TARGET_LOOK") */ - const auto target = i2enum(ts_ptr->mode | TARGET_LOOK); - while ((ts_ptr->query = examine_grid(player_ptr, ts_ptr->y, ts_ptr->x, target, ts_ptr->info)) == 0) { - ; + if (auto dir_and_velocity = this->switch_next_grid_command(); dir_and_velocity) { + const auto &[dir, move_fast] = *dir_and_velocity; + this->decide_change_panel(dir, move_fast); } - - ts_ptr->distance = 0; - if (use_menu && (ts_ptr->query == '\r')) { - ts_ptr->query = 't'; - } - - switch_next_grid_command(player_ptr, ts_ptr); - decide_change_panel(player_ptr, ts_ptr); } } @@ -583,11 +525,9 @@ static void sweep_target_grids(PlayerType *player_ptr, ts_type *ts_ptr) */ bool target_set(PlayerType *player_ptr, target_type mode) { - ts_type tmp_ts; - ts_type *ts_ptr = initialize_target_set_type(player_ptr, &tmp_ts, mode); + TargetSetter ts(player_ptr, mode); target_who = 0; - pos_interests = target_set_prepare(player_ptr, mode); - sweep_target_grids(player_ptr, ts_ptr); + ts.sweep_target_grids(); prt("", 0, 0); verify_panel(player_ptr); auto &rfu = RedrawingFlagsUpdater::get_instance();