OSDN Git Service

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