1 #include "info-reader/ego-reader.h"
2 #include "artifact/random-art-effects.h"
3 #include "info-reader/baseitem-tokens-table.h"
4 #include "info-reader/info-reader-util.h"
5 #include "info-reader/parse-error-types.h"
6 #include "main/angband-headers.h"
7 #include "object-enchant/object-ego.h"
8 #include "object-enchant/tr-types.h"
9 #include "util/bit-flags-calculator.h"
10 #include "util/enum-converter.h"
11 #include "util/string-processor.h"
12 #include "view/display-messages.h"
15 * @brief テキストトークンを走査してフラグを一つ得る(エゴ用) /
16 * Grab one flag in a ego-item_type from a textual string
17 * @param e_ptr 保管先のエゴ構造体参照ポインタ
18 * @param what 参照元の文字列ポインタ
21 static bool grab_one_ego_item_flag(EgoItemDefinition *e_ptr, std::string_view what)
23 if (TrFlags::grab_one_flag(e_ptr->flags, baseitem_flags, what)) {
27 if (EnumClassFlagGroup<ItemGenerationTraitType>::grab_one_flag(e_ptr->gen_flags, baseitem_geneneration_flags, what)) {
31 msg_format(_("未知の名のあるアイテム・フラグ '%s'。", "Unknown ego-item flag '%s'."), what.data());
36 * @brief テキストトークンを走査して生成フラグを一つ得る(エゴ用) /
37 * Grab one genetation flag in a ego-item_type from a textual string
38 * @param e_ptr 保管先のエゴ構造体参照ポインタ
39 * @param what 参照元の文字列ポインタ
42 static bool grab_ego_generate_flags(ego_generate_type &xtra, std::string_view what)
44 if (auto it = baseitem_flags.find(what); it != baseitem_flags.end()) {
45 xtra.tr_flags.push_back(it->second);
49 if (auto it = baseitem_geneneration_flags.find(what); it != baseitem_geneneration_flags.end()) {
50 xtra.trg_flags.push_back(it->second);
58 * @brief アイテムエゴ情報(EgoDefinitions)のパース関数
63 errr parse_egos_info(std::string_view buf, angband_header *)
65 static EgoItemDefinition *e_ptr = nullptr;
66 const auto &tokens = str_split(buf, ':', false, 10);
68 error_idx = 0; //!< @note 順不同で登録しているため
70 if (tokens[0] == "N") {
72 if (tokens.size() < 3 || tokens[1].size() == 0) {
73 return PARSE_ERROR_GENERIC;
76 auto i = std::stoi(tokens[1]);
78 return PARSE_ERROR_NON_SEQUENTIAL_RECORDS;
82 e_ptr = &(egos_info.emplace_hint(egos_info.end(), i2enum<EgoType>(i), EgoItemDefinition{})->second);
83 e_ptr->idx = i2enum<EgoType>(i);
85 e_ptr->name = tokens[2];
88 return PARSE_ERROR_MISSING_RECORD_HEADER;
89 } else if (tokens[0] == "E") {
92 if (tokens[1].size() == 0) {
93 return PARSE_ERROR_TOO_FEW_ARGUMENTS;
95 e_ptr->name = tokens[1];
97 } else if (tokens[0] == "X") {
99 if (tokens.size() < 3) {
100 return PARSE_ERROR_TOO_FEW_ARGUMENTS;
103 info_set_value(e_ptr->slot, tokens[1]);
104 info_set_value(e_ptr->rating, tokens[2]);
105 } else if (tokens[0] == "W") {
106 // W:level:ratiry:xtra:cost
108 if (tokens.size() < 5) {
109 return PARSE_ERROR_TOO_FEW_ARGUMENTS;
112 info_set_value(e_ptr->level, tokens[1]);
113 info_set_value(e_ptr->rarity, tokens[2]);
114 info_set_value(e_ptr->cost, tokens[4]);
115 } else if (tokens[0] == "B") {
117 // B:to_hit:to_dam:to_ac
118 if (tokens.size() < 4) {
119 return PARSE_ERROR_TOO_FEW_ARGUMENTS;
122 info_set_value(e_ptr->base_to_h, tokens[1]);
123 info_set_value(e_ptr->base_to_d, tokens[2]);
124 info_set_value(e_ptr->base_to_a, tokens[3]);
125 } else if (tokens[0] == "C") {
126 // Creation bonuses (random plus)
127 // C:to_hit:to_dam:to_ac:pval
128 if (tokens.size() < 5) {
129 return PARSE_ERROR_TOO_FEW_ARGUMENTS;
132 info_set_value(e_ptr->max_to_h, tokens[1]);
133 info_set_value(e_ptr->max_to_d, tokens[2]);
134 info_set_value(e_ptr->max_to_a, tokens[3]);
135 info_set_value(e_ptr->max_pval, tokens[4]);
136 } else if (tokens[0] == "U") {
138 if (tokens.size() < 2 || tokens[1].size() == 0) {
139 return PARSE_ERROR_TOO_FEW_ARGUMENTS;
142 auto n = grab_one_activation_flag(tokens[1]);
143 if (n <= RandomArtActType::NONE) {
144 return PARSE_ERROR_INVALID_FLAG;
148 } else if (tokens[0] == "F") {
150 if (tokens.size() < 2 || tokens[1].size() == 0) {
151 return PARSE_ERROR_TOO_FEW_ARGUMENTS;
154 const auto &flags = str_split(tokens[1], '|', true, 10);
155 for (const auto &f : flags) {
159 if (!grab_one_ego_item_flag(e_ptr, f)) {
160 return PARSE_ERROR_INVALID_FLAG;
163 } else if (tokens[0] == "G") {
165 if (tokens.size() < 3) {
166 return PARSE_ERROR_TOO_FEW_ARGUMENTS;
169 const auto &prob = str_split(tokens[1], '/', false, 2);
170 if (prob.size() != 2 || tokens[1].size() == 0 || tokens[2].size() == 0) {
171 return PARSE_ERROR_TOO_FEW_ARGUMENTS;
174 ego_generate_type xtra;
175 xtra.mul = std::stoi(prob[0]);
176 xtra.dev = std::stoi(prob[1]);
178 const auto &flags = str_split(tokens[2], '|', true, 10);
179 for (const auto &f : flags) {
183 if (!grab_ego_generate_flags(xtra, f)) {
184 return PARSE_ERROR_INVALID_FLAG;
188 e_ptr->xtra_flags.push_back(std::move(xtra));
190 return PARSE_ERROR_UNDEFINED_DIRECTIVE;
193 return PARSE_ERROR_NONE;