OSDN Git Service

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