OSDN Git Service

[Refactor] #1700 RandomArtActTypeのACT_* を*に変更した
[hengbandforosx/hengbandosx.git] / src / info-reader / ego-reader.cpp
1 #include "info-reader/ego-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/object-ego.h"
8 #include "object-enchant/tr-types.h"
9 #include "util/bit-flags-calculator.h"
10 #include "util/string-processor.h"
11 #include "view/display-messages.h"
12
13 /*!
14  * @brief テキストトークンを走査してフラグを一つ得る(エゴ用) /
15  * Grab one flag in a ego-item_type from a textual string
16  * @param e_ptr 保管先のエゴ構造体参照ポインタ
17  * @param what 参照元の文字列ポインタ
18  * @return 見つけたらtrue
19  */
20 static bool grab_one_ego_item_flag(ego_item_type *e_ptr, std::string_view what)
21 {
22     if (TrFlags::grab_one_flag(e_ptr->flags, k_info_flags, what))
23         return true;
24
25     if (EnumClassFlagGroup<TRG>::grab_one_flag(e_ptr->gen_flags, k_info_gen_flags, what))
26         return true;
27
28     msg_format(_("未知の名のあるアイテム・フラグ '%s'。", "Unknown ego-item flag '%s'."), what.data());
29     return false;
30 }
31
32 /*!
33  * @brief テキストトークンを走査して生成フラグを一つ得る(エゴ用) /
34  * Grab one genetation flag in a ego-item_type from a textual string
35  * @param e_ptr 保管先のエゴ構造体参照ポインタ
36  * @param what 参照元の文字列ポインタ
37  * @return 見つけたらtrue
38  */
39 static bool grab_ego_generate_flags(ego_generate_type &xtra, std::string_view what)
40 {
41     if (auto it = k_info_flags.find(what); it != k_info_flags.end()) {
42         xtra.tr_flags.push_back(it->second);
43         return true;
44     }
45
46     if (auto it = k_info_gen_flags.find(what); it != k_info_gen_flags.end()) {
47         xtra.trg_flags.push_back(it->second);
48         return true;
49     }
50
51     return false;
52 }
53
54 /*!
55  * @brief アイテムエゴ情報(e_info)のパース関数 /
56  * Initialize the "e_info" array, by parsing an ascii "template" file
57  * @param buf テキスト列
58  * @param head ヘッダ構造体
59  * @return エラーコード
60  */
61 errr parse_e_info(std::string_view buf, angband_header *)
62 {
63     static ego_item_type *e_ptr = nullptr;
64     const auto &tokens = str_split(buf, ':', false, 10);
65
66     error_idx = 0; //!< @note 順不同で登録しているため
67
68     if (tokens[0] == "N") {
69         // N:index:name_ja
70         if (tokens.size() < 3 || tokens[1].size() == 0)
71             return PARSE_ERROR_GENERIC;
72
73         auto i = std::stoi(tokens[1]);
74         if (i < error_idx)
75             return PARSE_ERROR_NON_SEQUENTIAL_RECORDS;
76         if (i >= static_cast<int>(e_info.size())) {
77             e_info.resize(i + 1);
78         }
79
80         error_idx = i;
81         e_ptr = &e_info[i];
82         e_ptr->idx = static_cast<EGO_IDX>(i);
83 #ifdef JP
84         e_ptr->name = tokens[2];
85 #endif
86     } else if (!e_ptr)
87         return PARSE_ERROR_MISSING_RECORD_HEADER;
88     else if (tokens[0] == "E") {
89         // E:name_en
90 #ifndef JP
91         if (tokens[1].size() == 0)
92             return PARSE_ERROR_TOO_FEW_ARGUMENTS;
93         e_ptr->name = tokens[1];
94 #endif
95     } else if (tokens[0] == "X") {
96         // X:slot:rating
97         if (tokens.size() < 3)
98             return PARSE_ERROR_TOO_FEW_ARGUMENTS;
99
100         info_set_value(e_ptr->slot, tokens[1]);
101         info_set_value(e_ptr->rating, tokens[2]);
102     } else if (tokens[0] == "W") {
103         // W:level:ratiry:xtra:cost
104         // xtra is not used
105         if (tokens.size() < 5)
106             return PARSE_ERROR_TOO_FEW_ARGUMENTS;
107
108         info_set_value(e_ptr->level, tokens[1]);
109         info_set_value(e_ptr->rarity, tokens[2]);
110         info_set_value(e_ptr->cost, tokens[4]);
111     } else if (tokens[0] == "B") {
112         // Base bonuses
113         // B:to_hit:to_dam:to_ac
114         if (tokens.size() < 4)
115             return PARSE_ERROR_TOO_FEW_ARGUMENTS;
116
117         info_set_value(e_ptr->base_to_h, tokens[1]);
118         info_set_value(e_ptr->base_to_d, tokens[2]);
119         info_set_value(e_ptr->base_to_a, tokens[3]);
120     } else if (tokens[0] == "C") {
121         // Creation bonuses (random plus)
122         // C:to_hit:to_dam:to_ac:pval
123         if (tokens.size() < 5)
124             return PARSE_ERROR_TOO_FEW_ARGUMENTS;
125
126         info_set_value(e_ptr->max_to_h, tokens[1]);
127         info_set_value(e_ptr->max_to_d, tokens[2]);
128         info_set_value(e_ptr->max_to_a, tokens[3]);
129         info_set_value(e_ptr->max_pval, tokens[4]);
130     } else if (tokens[0] == "U") {
131         // U:activation_flag
132         if (tokens.size() < 2 || tokens[1].size() == 0)
133             return PARSE_ERROR_TOO_FEW_ARGUMENTS;
134
135         auto n = grab_one_activation_flag(tokens[1].c_str());
136         if (n <=RandomArtActType::NONE)
137             return PARSE_ERROR_INVALID_FLAG;
138
139         e_ptr->act_idx = n;
140     } else if (tokens[0] == "F") {
141         // F:flags
142         if (tokens.size() < 2 || tokens[1].size() == 0)
143             return PARSE_ERROR_TOO_FEW_ARGUMENTS;
144
145         const auto& flags = str_split(tokens[1], '|', true, 10);
146         for (const auto& f : flags) {
147             if (f.size() == 0)
148                 continue;
149             if (!grab_one_ego_item_flag(e_ptr, f))
150                 return PARSE_ERROR_INVALID_FLAG;
151         }
152     } else if (tokens[0] == "G") {
153         // G:mul/dev:flags
154         if (tokens.size() < 3)
155             return PARSE_ERROR_TOO_FEW_ARGUMENTS;
156
157         const auto &prob = str_split(tokens[1], '/', false, 2);
158         if (prob.size() != 2 || tokens[1].size() == 0 || tokens[2].size() == 0)
159             return PARSE_ERROR_TOO_FEW_ARGUMENTS;
160
161         ego_generate_type xtra;
162         xtra.mul = std::stoi(prob[0]);
163         xtra.dev = std::stoi(prob[1]);
164
165         const auto& flags = str_split(tokens[2], '|', true, 10);
166         for (const auto& f : flags) {
167             if (f.size() == 0)
168                 continue;
169             if (!grab_ego_generate_flags(xtra, f))
170                 return PARSE_ERROR_INVALID_FLAG;
171         }
172
173         e_ptr->xtra_flags.push_back(std::move(xtra));
174     } else
175         return PARSE_ERROR_UNDEFINED_DIRECTIVE;
176
177     return PARSE_ERROR_NONE;
178 }