2 * @brief ベースアイテム定義の読み込み処理
7 #include "info-reader/baseitem-reader.h"
8 #include "artifact/random-art-effects.h"
9 #include "info-reader/baseitem-tokens-table.h"
10 #include "info-reader/info-reader-util.h"
11 #include "info-reader/parse-error-types.h"
12 #include "main/angband-headers.h"
13 #include "object-enchant/tr-types.h"
14 #include "object/tval-types.h"
15 #include "system/baseitem-info.h"
16 #include "term/gameterm.h"
17 #include "util/bit-flags-calculator.h"
18 #include "util/enum-converter.h"
19 #include "util/string-processor.h"
20 #include "view/display-messages.h"
23 * @brief テキストトークンを走査してフラグを一つ得る(ベースアイテム用) /
24 * Grab one flag in an BaseitemInfo from a textual string
25 * @param bii_ptr 保管先のベースアイテム構造体参照ポインタ
26 * @param what 参照元の文字列ポインタ
29 static bool grab_one_baseitem_flag(BaseitemInfo *bii_ptr, std::string_view what)
31 if (TrFlags::grab_one_flag(bii_ptr->flags, baseitem_flags, what)) {
35 if (EnumClassFlagGroup<ItemGenerationTraitType>::grab_one_flag(bii_ptr->gen_flags, baseitem_geneneration_flags, what)) {
39 msg_format(_("未知のアイテム・フラグ '%s'。", "Unknown object flag '%s'."), what.data());
44 * @brief ベースアイテム(BaseitemDefinitions)のパース関数
49 errr parse_baseitems_info(std::string_view buf, angband_header *head)
52 static BaseitemInfo *bii_ptr = nullptr;
53 const auto &tokens = str_split(buf, ':', false, 10);
55 if (tokens[0] == "N") {
57 if (tokens.size() < 3 || tokens[1].size() == 0) {
58 return PARSE_ERROR_TOO_FEW_ARGUMENTS;
61 auto i = std::stoi(tokens[1]);
63 return PARSE_ERROR_NON_SEQUENTIAL_RECORDS;
65 if (i >= static_cast<int>(baseitems_info.size())) {
66 baseitems_info.resize(i + 1);
70 bii_ptr = &baseitems_info[i];
71 bii_ptr->idx = static_cast<short>(i);
73 bii_ptr->name = tokens[2];
75 if (tokens.size() > 3) {
76 bii_ptr->flavor_name = tokens[3];
79 } else if (!bii_ptr) {
80 return PARSE_ERROR_MISSING_RECORD_HEADER;
81 } else if (tokens[0] == "E") {
84 if (tokens.size() < 2 || tokens[1].size() == 0) {
85 return PARSE_ERROR_TOO_FEW_ARGUMENTS;
87 bii_ptr->name = tokens[1];
89 if (tokens.size() > 2) {
90 bii_ptr->flavor_name = tokens[2];
93 } else if (tokens[0] == "D") {
96 if (tokens.size() < 2 || tokens[1].size() == 0) {
97 return PARSE_ERROR_TOO_FEW_ARGUMENTS;
100 if (tokens[1][0] == '$') {
101 return PARSE_ERROR_NONE;
103 bii_ptr->text.append(buf.substr(2));
105 if (tokens[1][0] != '$') {
106 return PARSE_ERROR_NONE;
108 append_english_text(bii_ptr->text, buf.substr(3));
110 } else if (tokens[0] == "G") {
112 if (tokens.size() < 3 || tokens[1].size() == 0 || tokens[2].size() == 0) {
113 return PARSE_ERROR_TOO_FEW_ARGUMENTS;
116 auto a = color_char_to_attr(tokens[2][0]);
118 return PARSE_ERROR_GENERIC;
122 bii_ptr->d_char = tokens[1][0];
123 } else if (tokens[0] == "I") {
125 if (tokens.size() < 4) {
126 return PARSE_ERROR_TOO_FEW_ARGUMENTS;
129 constexpr auto base = 10;
130 const auto tval = i2enum<ItemKindType>(std::stoi(tokens[1], nullptr, base));
131 const auto sval = std::stoi(tokens[2], nullptr, base);
132 bii_ptr->bi_key = { tval, sval };
133 info_set_value(bii_ptr->pval, tokens[3]);
134 if ((tval == ItemKindType::ROD) && (bii_ptr->pval <= 0)) {
135 return PAESE_ERROR_INVALID_PVAL;
137 } else if (tokens[0] == "W") {
138 // W:level:weight:cost
139 if (tokens.size() < 4) {
140 return PARSE_ERROR_TOO_FEW_ARGUMENTS;
143 info_set_value(bii_ptr->level, tokens[1]);
144 info_set_value(bii_ptr->weight, tokens[2]);
145 info_set_value(bii_ptr->cost, tokens[3]);
146 } else if (tokens[0] == "A") {
147 // A:level/chance(:level/chance:level/chance:level/chance)
148 if (tokens.size() < 2 || tokens.size() > 5) {
149 return PARSE_ERROR_TOO_FEW_ARGUMENTS;
153 for (auto t = tokens.begin() + 1; t != tokens.end(); t++) {
154 const auto &rarity = str_split(*t, '/', false, 2);
155 if (rarity.size() != 2 || rarity[0].size() == 0 || rarity[1].size() == 0) {
156 return PARSE_ERROR_NON_SEQUENTIAL_RECORDS;
159 auto &table = bii_ptr->alloc_tables[i];
160 info_set_value(table.level, rarity[0]);
161 info_set_value(table.chance, rarity[1]);
164 } else if (tokens[0] == "P") {
165 // P:ac:dd:ds:to_h:to_d:to_a
166 if (tokens.size() < 6) {
167 return PARSE_ERROR_TOO_FEW_ARGUMENTS;
170 const auto &dice = str_split(tokens[2], 'd', false, 2);
171 if (dice.size() != 2) {
172 return PARSE_ERROR_NON_SEQUENTIAL_RECORDS;
175 info_set_value(bii_ptr->ac, tokens[1]);
176 info_set_value(bii_ptr->dd, dice[0]);
177 info_set_value(bii_ptr->ds, dice[1]);
178 info_set_value(bii_ptr->to_h, tokens[3]);
179 info_set_value(bii_ptr->to_d, tokens[4]);
180 info_set_value(bii_ptr->to_a, tokens[5]);
181 } else if (tokens[0] == "U") {
183 if (tokens.size() < 2 || tokens[1].size() == 0) {
184 return PARSE_ERROR_TOO_FEW_ARGUMENTS;
186 auto n = grab_one_activation_flag(tokens[1].data());
187 if (n <= RandomArtActType::NONE) {
188 return PARSE_ERROR_INVALID_FLAG;
191 bii_ptr->act_idx = n;
192 } else if (tokens[0] == "F") {
194 if (tokens.size() < 2 || tokens[1].size() == 0) {
195 return PARSE_ERROR_TOO_FEW_ARGUMENTS;
198 const auto &flags = str_split(tokens[1], '|', true, 10);
199 for (const auto &f : flags) {
203 if (!grab_one_baseitem_flag(bii_ptr, f)) {
204 return PARSE_ERROR_INVALID_FLAG;
208 return PARSE_ERROR_UNDEFINED_DIRECTIVE;
211 return PARSE_ERROR_NONE;