OSDN Git Service

[Refactor] #2610 artifact_type::idx の型をARTIFACT_IDX (short) からFixedArtifactType に変えた
[hengbandforosx/hengbandosx.git] / src / info-reader / artifact-reader.cpp
1 #include "info-reader/artifact-reader.h"
2 #include "artifact/random-art-effects.h"
3 #include "info-reader/info-reader-util.h"
4 #include "info-reader/kind-info-tokens-table.h"
5 #include "info-reader/parse-error-types.h"
6 #include "main/angband-headers.h"
7 #include "object-enchant/tr-types.h"
8 #include "system/artifact-type-definition.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"
13
14 /*!
15  * @brief テキストトークンを走査してフラグを一つ得る(アーティファクト用) /
16  * Grab one activation index flag
17  * @param a_ptr 保管先のアーティファクト構造体参照ポインタ
18  * @param what 参照元の文字列ポインタ
19  * @return 見つかったらtrue
20  */
21 static bool grab_one_artifact_flag(artifact_type *a_ptr, std::string_view what)
22 {
23     if (TrFlags::grab_one_flag(a_ptr->flags, k_info_flags, what)) {
24         return true;
25     }
26
27     if (EnumClassFlagGroup<ItemGenerationTraitType>::grab_one_flag(a_ptr->gen_flags, k_info_gen_flags, what)) {
28         return true;
29     }
30
31     msg_format(_("未知の伝説のアイテム・フラグ '%s'。", "Unknown artifact flag '%s'."), what.data());
32     return false;
33 }
34
35 /*!
36  * @brief 固定アーティファクト情報(a_info)のパース関数 /
37  * Initialize the "a_info" array, by parsing an ascii "template" file
38  * @param buf テキスト列
39  * @param head ヘッダ構造体
40  * @return エラーコード
41  */
42 errr parse_a_info(std::string_view buf, angband_header *)
43 {
44     static artifact_type *a_ptr = nullptr;
45     const auto &tokens = str_split(buf, ':', false, 10);
46
47     if (tokens[0] == "N") {
48         // N:index:name_ja
49         if (tokens.size() < 3 || tokens[1].size() == 0) {
50             return PARSE_ERROR_GENERIC;
51         }
52
53         auto i = std::stoi(tokens[1]);
54         if (i < error_idx) {
55             return PARSE_ERROR_NON_SEQUENTIAL_RECORDS;
56         }
57         if (i >= static_cast<int>(a_info.size())) {
58             a_info.resize(i + 1);
59         }
60
61         error_idx = i;
62         a_ptr = &a_info[i];
63         a_ptr->idx = i2enum<FixedArtifactId>(i);
64         a_ptr->flags.set(TR_IGNORE_ACID);
65         a_ptr->flags.set(TR_IGNORE_ELEC);
66         a_ptr->flags.set(TR_IGNORE_FIRE);
67         a_ptr->flags.set(TR_IGNORE_COLD);
68
69 #ifdef JP
70         a_ptr->name = tokens[2];
71 #endif
72     } else if (!a_ptr) {
73         return PARSE_ERROR_MISSING_RECORD_HEADER;
74     } else if (tokens[0] == "E") {
75         // E:name_en
76 #ifndef JP
77         if (tokens[1].size() == 0) {
78             return PARSE_ERROR_TOO_FEW_ARGUMENTS;
79         }
80         a_ptr->name = tokens[1];
81 #endif
82     } else if (tokens[0] == "D") {
83         // D:JapaneseText
84         // D:$EnglishText
85         if (tokens.size() < 2 || tokens[1].size() == 0) {
86             return PARSE_ERROR_NON_SEQUENTIAL_RECORDS;
87         }
88 #ifdef JP
89         if (tokens[1][0] == '$') {
90             return PARSE_ERROR_NONE;
91         }
92         a_ptr->text.append(buf.substr(2));
93 #else
94         if (tokens[1][0] != '$') {
95             return PARSE_ERROR_NONE;
96         }
97         append_english_text(a_ptr->text, buf.substr(3));
98 #endif
99     } else if (tokens[0] == "I") {
100         // I:tval:sval:pval
101         if (tokens.size() < 4) {
102             return PARSE_ERROR_TOO_FEW_ARGUMENTS;
103         }
104
105         info_set_value(a_ptr->tval, tokens[1]);
106         info_set_value(a_ptr->sval, tokens[2]);
107         info_set_value(a_ptr->pval, tokens[3]);
108     } else if (tokens[0] == "W") {
109         // W:level:ratiry:weight:cost
110         if (tokens.size() < 5) {
111             return PARSE_ERROR_TOO_FEW_ARGUMENTS;
112         }
113
114         info_set_value(a_ptr->level, tokens[1]);
115         info_set_value(a_ptr->rarity, tokens[2]);
116         info_set_value(a_ptr->weight, tokens[3]);
117         info_set_value(a_ptr->cost, tokens[4]);
118     } else if (tokens[0] == "P") {
119         // P:ac:dd:ds:to_h:to_d:to_a
120         if (tokens.size() < 6) {
121             return PARSE_ERROR_TOO_FEW_ARGUMENTS;
122         }
123
124         const auto &dice = str_split(tokens[2], 'd', false, 2);
125         if (dice.size() != 2) {
126             return PARSE_ERROR_NON_SEQUENTIAL_RECORDS;
127         }
128
129         info_set_value(a_ptr->ac, tokens[1]);
130         info_set_value(a_ptr->dd, dice[0]);
131         info_set_value(a_ptr->ds, dice[1]);
132         info_set_value(a_ptr->to_h, tokens[3]);
133         info_set_value(a_ptr->to_d, tokens[4]);
134         info_set_value(a_ptr->to_a, tokens[5]);
135     } else if (tokens[0] == "U") {
136         // U:activation_flag
137         if (tokens.size() < 2 || tokens[1].size() == 0) {
138             return PARSE_ERROR_TOO_FEW_ARGUMENTS;
139         }
140         auto n = grab_one_activation_flag(tokens[1].c_str());
141         if (n <= RandomArtActType::NONE) {
142             return PARSE_ERROR_INVALID_FLAG;
143         }
144
145         a_ptr->act_idx = n;
146     } else if (tokens[0] == "F") {
147         // F:flags
148         if (tokens.size() < 2 || tokens[1].size() == 0) {
149             return PARSE_ERROR_TOO_FEW_ARGUMENTS;
150         }
151
152         const auto &flags = str_split(tokens[1], '|', true, 10);
153         for (const auto &f : flags) {
154             if (f.size() == 0) {
155                 continue;
156             }
157             if (!grab_one_artifact_flag(a_ptr, f)) {
158                 return PARSE_ERROR_INVALID_FLAG;
159             }
160         }
161     } else {
162         return PARSE_ERROR_UNDEFINED_DIRECTIVE;
163     }
164
165     return PARSE_ERROR_NONE;
166 }