2 * @file info-initializer.cpp
3 * @brief 変愚蛮怒のゲームデータ解析処理定義
6 #include "main/info-initializer.h"
7 #include "floor/wild.h"
8 #include "info-reader/artifact-reader.h"
9 #include "info-reader/baseitem-reader.h"
10 #include "info-reader/dungeon-reader.h"
11 #include "info-reader/ego-reader.h"
12 #include "info-reader/feature-reader.h"
13 #include "info-reader/fixed-map-parser.h"
14 #include "info-reader/general-parser.h"
15 #include "info-reader/info-reader-util.h"
16 #include "info-reader/magic-reader.h"
17 #include "info-reader/race-reader.h"
18 #include "info-reader/skill-reader.h"
19 #include "info-reader/vault-reader.h"
20 #include "io/files-util.h"
21 #include "io/uid-checker.h"
22 #include "main/angband-headers.h"
23 #include "main/init-error-messages-table.h"
24 #include "monster-race/monster-race.h"
25 #include "object-enchant/object-ego.h"
26 #include "player-info/class-info.h"
27 #include "player/player-skill.h"
28 #include "room/rooms-vault.h"
29 #include "system/angband-version.h"
30 #include "system/artifact-type-definition.h"
31 #include "system/baseitem-info.h"
32 #include "system/dungeon-info.h"
33 #include "system/monster-race-info.h"
34 #include "system/player-type-definition.h"
35 #include "system/terrain-type-definition.h"
36 #include "util/angband-files.h"
37 #include "util/string-processor.h"
38 #include "view/display-messages.h"
39 #include "world/world.h"
42 #include <string_view>
45 #include <sys/types.h>
50 using Retoucher = void (*)(angband_header *);
53 struct is_vector : std::false_type {
56 template <typename T, typename Alloc>
57 struct is_vector<std::vector<T, Alloc>> : std::true_type {
61 * @brief 与えられた型 T が std::vector 型かどうか調べる
62 * T の型が std::vector<SomeType> に一致する時、is_vector_v<T> == true
63 * 一致しない時、is_vector_v<T> == false となる
67 constexpr bool is_vector_v = is_vector<T>::value;
73 * Initialize the header of an *_info.raw file.
74 * @param head rawファイルのヘッダ
79 static void init_header(angband_header *head, IDX num = 0)
82 head->info_num = (IDX)num;
86 * @brief 各種設定データをlib/edit/のテキストから読み込み
87 * Initialize the "*_info" array
88 * @param filename ファイル名(拡張子txt)
89 * @param head 処理に用いるヘッダ構造体
90 * @param info データ保管先の構造体ポインタ
93 * Note that we let each entry have a unique "name" and "text" string,
94 * even if the string happens to be empty (everyone has a unique '\0').
96 template <typename InfoType>
97 static errr init_info(std::string_view filename, angband_header &head, InfoType &info, Parser parser, Retoucher retouch = nullptr)
99 const auto &path = path_build(ANGBAND_DIR_EDIT, filename);
100 auto *fp = angband_fopen(path, FileOpenMode::READ);
102 quit_fmt(_("'%s'ファイルをオープンできません。", "Cannot open '%s' file."), filename.data());
105 constexpr auto info_is_vector = is_vector_v<InfoType>;
106 if constexpr (info_is_vector) {
107 using value_type = typename InfoType::value_type;
108 info.assign(head.info_num, value_type{});
112 const auto err = init_info_txt(fp, buf, &head, parser);
115 const auto oops = (((err > 0) && (err < PARSE_ERROR_MAX)) ? err_str[err] : _("未知の", "unknown"));
117 msg_format("'%s'ファイルの %d 行目にエラー。", filename.data(), error_line);
119 msg_format("Error %d at line %d of '%s'.", err, error_line, filename.data());
121 msg_format(_("レコード %d は '%s' エラーがあります。", "Record %d contains a '%s' error."), error_idx, oops);
122 msg_format(_("構文 '%s'。", "Parsing '%s'."), buf);
124 quit_fmt(_("'%s'ファイルにエラー", "Error in '%s' file."), filename.data());
127 if constexpr (info_is_vector) {
128 info.shrink_to_fit();
131 head.info_num = static_cast<uint16_t>(info.size());
140 * @brief 固定アーティファクト情報読み込みのメインルーチン
143 errr init_artifacts_info()
145 init_header(&artifacts_header);
146 return init_info("ArtifactDefinitions.txt", artifacts_header, artifacts_info, parse_artifacts_info);
150 * @brief ベースアイテム情報読み込みのメインルーチン
153 errr init_baseitems_info()
155 init_header(&baseitems_header);
156 return init_info("BaseitemDefinitions.txt", baseitems_header, baseitems_info, parse_baseitems_info);
160 * @brief 職業魔法情報読み込みのメインルーチン
163 errr init_class_magics_info()
165 init_header(&class_magics_header, PLAYER_CLASS_TYPE_MAX);
166 auto *parser = parse_class_magics_info;
167 return init_info("ClassMagicDefinitions.txt", class_magics_header, class_magics_info, parser);
171 * @brief 職業技能情報読み込みのメインルーチン
174 errr init_class_skills_info()
176 init_header(&class_skills_header, PLAYER_CLASS_TYPE_MAX);
177 return init_info("ClassSkillDefinitions.txt", class_skills_header, class_skills_info, parse_class_skills_info);
180 * @brief ダンジョン情報読み込みのメインルーチン
183 errr init_dungeons_info()
185 init_header(&dungeons_header);
186 return init_info("DungeonDefinitions.txt", dungeons_header, dungeons_info, parse_dungeons_info);
190 * @brief エゴ情報読み込みのメインルーチン
193 errr init_egos_info()
195 init_header(&egos_header);
196 return init_info("EgoDefinitions.txt", egos_header, egos_info, parse_egos_info);
200 * @brief 地形情報読み込みのメインルーチン
203 errr init_terrains_info()
205 init_header(&terrains_header);
206 auto *parser = parse_terrains_info;
207 auto *retoucher = retouch_terrains_info;
208 return init_info("TerrainDefinitions.txt", terrains_header, terrains_info, parser, retoucher);
212 * @brief モンスター種族情報読み込みのメインルーチン
215 errr init_monster_race_definitions()
217 init_header(&monraces_header);
218 return init_info("MonsterRaceDefinitions.txt", monraces_header, monraces_info, parse_monraces_info);
222 * @brief Vault情報読み込みのメインルーチン
225 * Note that we let each entry have a unique "name" and "text" string,
226 * even if the string happens to be empty (everyone has a unique '\0').
228 errr init_vaults_info()
230 init_header(&vaults_header);
231 return init_info("VaultDefinitions.txt", vaults_header, vaults_info, parse_vaults_info);
234 static bool read_wilderness_definition(std::ifstream &ifs)
238 if (!std::getline(ifs, line)) {
242 if (line.empty() || line.starts_with('#')) {
246 const auto &splits = str_split(line, ':');
247 if ((splits.size() != 3) || (splits[0] != "M")) {
251 if (splits[1] == "WX") {
252 w_ptr->max_wild_x = std::stoi(splits[2]);
253 } else if (splits[1] == "WY") {
254 w_ptr->max_wild_y = std::stoi(splits[2]);
259 if ((w_ptr->max_wild_x > 0) && (w_ptr->max_wild_y > 0)) {
260 wilderness.assign(w_ptr->max_wild_y, std::vector<wilderness_type>(w_ptr->max_wild_x));
261 init_wilderness_encounter();
273 bool init_wilderness()
275 const auto &path = path_build(ANGBAND_DIR_EDIT, WILDERNESS_DEFINITION);
276 std::ifstream ifs(path);
281 return read_wilderness_definition(ifs);