OSDN Git Service

Merge pull request #3569 from sikabane-works/release/3.0.0.88-alpha
[hengbandforosx/hengbandosx.git] / src / info-reader / artifact-reader.cpp
1 #include "info-reader/artifact-reader.h"
2 #include "artifact/fixed-art-types.h"
3 #include "artifact/random-art-effects.h"
4 #include "info-reader/baseitem-tokens-table.h"
5 #include "info-reader/info-reader-util.h"
6 #include "info-reader/parse-error-types.h"
7 #include "main/angband-headers.h"
8 #include "object-enchant/tr-types.h"
9 #include "system/artifact-type-definition.h"
10 #include "util/bit-flags-calculator.h"
11 #include "util/enum-converter.h"
12 #include "util/string-processor.h"
13 #include "view/display-messages.h"
14
15 /*!
16  * @brief テキストトークンを走査してフラグを一つ得る(アーティファクト用) /
17  * Grab one activation index flag
18  * @param a_ptr 保管先のアーティファクト構造体参照ポインタ
19  * @param what 参照元の文字列ポインタ
20  * @return 見つかったらtrue
21  */
22 static bool grab_one_artifact_flag(ArtifactType *a_ptr, std::string_view what)
23 {
24     if (TrFlags::grab_one_flag(a_ptr->flags, baseitem_flags, what)) {
25         return true;
26     }
27
28     if (EnumClassFlagGroup<ItemGenerationTraitType>::grab_one_flag(a_ptr->gen_flags, baseitem_geneneration_flags, what)) {
29         return true;
30     }
31
32     msg_format(_("未知の伝説のアイテム・フラグ '%s'。", "Unknown artifact flag '%s'."), what.data());
33     return false;
34 }
35
36 /*!
37  * @brief 固定アーティファクト定義(ArtifactDefinitions)のパース関数
38  * @param buf テキスト列
39  * @param head ヘッダ構造体
40  * @return エラーコード
41  */
42 errr parse_artifacts_info(std::string_view buf, angband_header *)
43 {
44     const auto &tokens = str_split(buf, ':', false, 10);
45     if (tokens[0] == "N") {
46         // N:index:name_ja
47         if (tokens.size() < 3 || tokens[1].size() == 0) {
48             return PARSE_ERROR_GENERIC;
49         }
50
51         const auto int_idx = std::stoi(tokens[1]);
52         const auto a_idx = i2enum<FixedArtifactId>(int_idx);
53         if (int_idx < error_idx) {
54             return PARSE_ERROR_NON_SEQUENTIAL_RECORDS;
55         }
56
57         error_idx = int_idx;
58         ArtifactType artifact;
59         artifact.flags.set(TR_IGNORE_ACID);
60         artifact.flags.set(TR_IGNORE_ELEC);
61         artifact.flags.set(TR_IGNORE_FIRE);
62         artifact.flags.set(TR_IGNORE_COLD);
63 #ifdef JP
64         artifact.name = tokens[2];
65 #endif
66         artifacts_info.emplace(a_idx, artifact);
67         return PARSE_ERROR_NONE;
68     }
69
70     if (tokens[0] == "E") {
71         // E:name_en
72 #ifdef JP
73         return PARSE_ERROR_NONE;
74 #else
75         if (tokens[1].size() == 0) {
76             return PARSE_ERROR_TOO_FEW_ARGUMENTS;
77         }
78
79         const auto it = artifacts_info.rbegin();
80         auto &artifact = it->second;
81         artifact.name = tokens[1];
82         return PARSE_ERROR_NONE;
83 #endif
84     }
85
86     if (tokens[0] == "D") {
87         // D:JapaneseText
88         // D:$EnglishText
89         if (tokens.size() < 2 || tokens[1].size() == 0) {
90             return PARSE_ERROR_NON_SEQUENTIAL_RECORDS;
91         }
92 #ifdef JP
93         if (tokens[1][0] == '$') {
94             return PARSE_ERROR_NONE;
95         }
96
97         const auto it = artifacts_info.rbegin();
98         auto &artifact = it->second;
99         artifact.text.append(tokens[1]);
100 #else
101         if (tokens[1][0] != '$') {
102             return PARSE_ERROR_NONE;
103         }
104
105         const auto it = artifacts_info.rbegin();
106         auto &artifact = it->second;
107         append_english_text(artifact.text, tokens[1].substr(1));
108 #endif
109         return PARSE_ERROR_NONE;
110     }
111
112     if (tokens[0] == "I") {
113         // I:tval:sval:pval
114         if (tokens.size() < 4) {
115             return PARSE_ERROR_TOO_FEW_ARGUMENTS;
116         }
117
118         const auto it = artifacts_info.rbegin();
119         auto &artifact = it->second;
120         constexpr auto base = 10;
121         const auto tval = i2enum<ItemKindType>(std::stoi(tokens[1], nullptr, base));
122         const auto sval = std::stoi(tokens[2], nullptr, base);
123         artifact.bi_key = { tval, sval };
124         info_set_value(artifact.pval, tokens[3]);
125         return PARSE_ERROR_NONE;
126     }
127
128     if (tokens[0] == "W") {
129         // W:level:ratiry:weight:cost
130         if (tokens.size() < 5) {
131             return PARSE_ERROR_TOO_FEW_ARGUMENTS;
132         }
133
134         const auto it = artifacts_info.rbegin();
135         auto &artifact = it->second;
136         info_set_value(artifact.level, tokens[1]);
137         info_set_value(artifact.rarity, tokens[2]);
138         info_set_value(artifact.weight, tokens[3]);
139         info_set_value(artifact.cost, tokens[4]);
140         return PARSE_ERROR_NONE;
141     }
142
143     if (tokens[0] == "P") {
144         // P:ac:dd:ds:to_h:to_d:to_a
145         if (tokens.size() < 6) {
146             return PARSE_ERROR_TOO_FEW_ARGUMENTS;
147         }
148
149         const auto &dice = str_split(tokens[2], 'd', false, 2);
150         if (dice.size() != 2) {
151             return PARSE_ERROR_NON_SEQUENTIAL_RECORDS;
152         }
153
154         const auto it = artifacts_info.rbegin();
155         auto &artifact = it->second;
156         info_set_value(artifact.ac, tokens[1]);
157         info_set_value(artifact.dd, dice[0]);
158         info_set_value(artifact.ds, dice[1]);
159         info_set_value(artifact.to_h, tokens[3]);
160         info_set_value(artifact.to_d, tokens[4]);
161         info_set_value(artifact.to_a, tokens[5]);
162         return PARSE_ERROR_NONE;
163     }
164
165     if (tokens[0] == "U") {
166         // U:activation_flag
167         if (tokens.size() < 2 || tokens[1].size() == 0) {
168             return PARSE_ERROR_TOO_FEW_ARGUMENTS;
169         }
170
171         auto n = grab_one_activation_flag(tokens[1].data());
172         if (n <= RandomArtActType::NONE) {
173             return PARSE_ERROR_INVALID_FLAG;
174         }
175
176         const auto it = artifacts_info.rbegin();
177         auto &artifact = it->second;
178         artifact.act_idx = n;
179         return PARSE_ERROR_NONE;
180     }
181
182     if (tokens[0] == "F") {
183         // F:flags
184         if (tokens.size() < 2 || tokens[1].size() == 0) {
185             return PARSE_ERROR_TOO_FEW_ARGUMENTS;
186         }
187
188         const auto &flags = str_split(tokens[1], '|', true, 10);
189         for (const auto &f : flags) {
190             if (f.size() == 0) {
191                 continue;
192             }
193
194             const auto it = artifacts_info.rbegin();
195             auto *a_ptr = &it->second;
196             if (!grab_one_artifact_flag(a_ptr, f)) {
197                 return PARSE_ERROR_INVALID_FLAG;
198             }
199         }
200
201         return PARSE_ERROR_NONE;
202     }
203
204     return PARSE_ERROR_UNDEFINED_DIRECTIVE;
205 }