OSDN Git Service

[Implement] #37285 Expanded buffer size of monsters' name
[hengband/hengband.git] / src / info-reader / race-reader.c
1 #include "info-reader/race-reader.h"
2 #include "info-reader/parse-error-types.h"
3 #include "info-reader/race-info-tokens-table.h"
4 #include "main/angband-headers.h"
5 #include "monster-race/monster-race.h"
6 #include "term/gameterm.h"
7 #include "util/string-processor.h"
8 #include "view/display-messages.h"
9
10 /*!
11  * @brief テキストトークンを走査してフラグを一つ得る(モンスター用1) /
12  * Grab one (basic) flag in a monster_race from a textual string
13  * @param r_ptr 保管先のモンスター種族構造体参照ポインタ
14  * @param what 参照元の文字列ポインタ
15  * @return エラーコード
16  */
17 static errr grab_one_basic_flag(monster_race *r_ptr, concptr what)
18 {
19     if (grab_one_flag(&r_ptr->flags1, r_info_flags1, what) == 0)
20         return PARSE_ERROR_NONE;
21
22     if (grab_one_flag(&r_ptr->flags2, r_info_flags2, what) == 0)
23         return PARSE_ERROR_NONE;
24
25     if (grab_one_flag(&r_ptr->flags3, r_info_flags3, what) == 0)
26         return PARSE_ERROR_NONE;
27
28     if (grab_one_flag(&r_ptr->flags7, r_info_flags7, what) == 0)
29         return PARSE_ERROR_NONE;
30
31     if (grab_one_flag(&r_ptr->flags8, r_info_flags8, what) == 0)
32         return PARSE_ERROR_NONE;
33
34     if (grab_one_flag(&r_ptr->flags9, r_info_flags9, what) == 0)
35         return PARSE_ERROR_NONE;
36
37     if (grab_one_flag(&r_ptr->flagsr, r_info_flagsr, what) == 0)
38         return PARSE_ERROR_NONE;
39
40     msg_format(_("未知のモンスター・フラグ '%s'。", "Unknown monster flag '%s'."), what);
41     return PARSE_ERROR_GENERIC;
42 }
43
44 /*!
45  * @brief テキストトークンを走査してフラグを一つ得る(モンスター用2) /
46  * Grab one (spell) flag in a monster_race from a textual string
47  * @param r_ptr 保管先のモンスター種族構造体参照ポインタ
48  * @param what 参照元の文字列ポインタ
49  * @return エラーコード
50  */
51 static errr grab_one_spell_flag(monster_race *r_ptr, concptr what)
52 {
53     if (grab_one_flag(&r_ptr->flags4, r_info_flags4, what) == 0)
54         return PARSE_ERROR_NONE;
55
56     if (grab_one_flag(&r_ptr->a_ability_flags1, r_a_ability_flags1, what) == 0)
57         return PARSE_ERROR_NONE;
58
59     if (grab_one_flag(&r_ptr->a_ability_flags2, r_a_ability_flags2, what) == 0)
60         return PARSE_ERROR_NONE;
61
62     msg_format(_("未知のモンスター・フラグ '%s'。", "Unknown monster flag '%s'."), what);
63     return PARSE_ERROR_GENERIC;
64 }
65
66 /*!
67  * @brief モンスター種族情報(r_info)のパース関数 /
68  * Initialize the "r_info" array, by parsing an ascii "template" file
69  * @param buf テキスト列
70  * @param head ヘッダ構造体
71  * @return エラーコード
72  */
73 errr parse_r_info(char *buf, angband_header *head)
74 {
75     static monster_race *r_ptr = NULL;
76     char *s, *t;
77     if (buf[0] == 'N') {
78         s = angband_strchr(buf + 2, ':');
79         if (!s)
80             return PARSE_ERROR_GENERIC;
81
82         *s++ = '\0';
83 #ifdef JP
84         if (!*s)
85             return PARSE_ERROR_GENERIC;
86 #endif
87
88         int i = atoi(buf + 2);
89         if (i < error_idx)
90             return PARSE_ERROR_NON_SEQUENTIAL_RECORDS;
91
92         if (i >= head->info_num)
93             return PARSE_ERROR_ABSOLETE_FILE;
94
95         error_idx = i;
96         r_ptr = &r_info[i];
97 #ifdef JP
98         if (!add_name(&r_ptr->name, head, s))
99             return PARSE_ERROR_OUT_OF_MEMORY;
100 #endif
101     } else if (!r_ptr) {
102         return PARSE_ERROR_MISSING_RECORD_HEADER;
103     }
104 #ifdef JP
105     /* 英語名を読むルーチンを追加 */
106     /* 'E' から始まる行は英語名 */
107     else if (buf[0] == 'E') {
108         s = buf + 2;
109         if (!add_name(&r_ptr->E_name, head, s))
110             return PARSE_ERROR_OUT_OF_MEMORY;
111     }
112 #else
113     else if (buf[0] == 'E') {
114         s = buf + 2;
115         if (!add_name(&r_ptr->name, head, s))
116             return PARSE_ERROR_OUT_OF_MEMORY;
117     }
118 #endif
119     else if (buf[0] == 'D') {
120 #ifdef JP
121         if (buf[2] == '$')
122             return PARSE_ERROR_NONE;
123
124         s = buf + 2;
125 #else
126         if (buf[2] != '$')
127             return PARSE_ERROR_NONE;
128         s = buf + 3;
129 #endif
130         if (!add_text(&r_ptr->text, head, s, TRUE))
131             return PARSE_ERROR_OUT_OF_MEMORY;
132     } else if (buf[0] == 'G') {
133         if ((buf[1] != ':') || !buf[2] || (buf[3] != ':') || !buf[4])
134             return PARSE_ERROR_GENERIC;
135
136         char sym = buf[2];
137         byte tmp = color_char_to_attr(buf[4]);
138         if (tmp > 127)
139             return PARSE_ERROR_GENERIC;
140
141         r_ptr->d_char = sym;
142         r_ptr->d_attr = tmp;
143     } else if (buf[0] == 'I') {
144         int spd, hp1, hp2, aaf, ac, slp;
145         if (sscanf(buf + 2, "%d:%dd%d:%d:%d:%d", &spd, &hp1, &hp2, &aaf, &ac, &slp) != 6)
146             return PARSE_ERROR_GENERIC;
147
148         r_ptr->speed = (SPEED)spd;
149         r_ptr->hdice = (DICE_NUMBER)MAX(hp1, 1);
150         r_ptr->hside = (DICE_SID)MAX(hp2, 1);
151         r_ptr->aaf = (POSITION)aaf;
152         r_ptr->ac = (ARMOUR_CLASS)ac;
153         r_ptr->sleep = (SLEEP_DEGREE)slp;
154     } else if (buf[0] == 'W') {
155         int lev, rar, pad;
156         long exp;
157         long nextexp;
158         int nextmon;
159         if (sscanf(buf + 2, "%d:%d:%d:%ld:%ld:%d", &lev, &rar, &pad, &exp, &nextexp, &nextmon) != 6)
160             return PARSE_ERROR_GENERIC;
161
162         r_ptr->level = (DEPTH)lev;
163         r_ptr->rarity = (RARITY)rar;
164         r_ptr->extra = (BIT_FLAGS16)pad;
165         r_ptr->mexp = (EXP)exp;
166         r_ptr->next_exp = (EXP)nextexp;
167         r_ptr->next_r_idx = (MONRACE_IDX)nextmon;
168     } else if (buf[0] == 'R') {
169         int id, ds, dd;
170         int i = 0;
171         for (; i < A_MAX; i++)
172             if (r_ptr->reinforce_id[i] == 0)
173                 break;
174
175         if ((i == 6) || (sscanf(buf + 2, "%d:%dd%d", &id, &dd, &ds) != 3))
176             return PARSE_ERROR_GENERIC;
177
178         r_ptr->reinforce_id[i] = (MONRACE_IDX)id;
179         r_ptr->reinforce_dd[i] = (DICE_NUMBER)dd;
180         r_ptr->reinforce_ds[i] = (DICE_SID)ds;
181     } else if (buf[0] == 'B') {
182         int n1, n2;
183         int i = 0;
184         for (i = 0; i < 4; i++)
185             if (!r_ptr->blow[i].method)
186                 break;
187
188         if (i == 4)
189             return PARSE_ERROR_GENERIC;
190
191         /* loop */
192         for (s = t = buf + 2; *t && (*t != ':'); t++)
193             ;
194
195         if (*t == ':')
196             *t++ = '\0';
197
198         for (n1 = 0; r_info_blow_method[n1]; n1++) {
199             if (streq(s, r_info_blow_method[n1]))
200                 break;
201         }
202
203         if (!r_info_blow_method[n1])
204             return PARSE_ERROR_GENERIC;
205
206         /* loop */
207         for (s = t; *t && (*t != ':'); t++)
208             ;
209
210         if (*t == ':')
211             *t++ = '\0';
212
213         for (n2 = 0; r_info_blow_effect[n2]; n2++) {
214             if (streq(s, r_info_blow_effect[n2]))
215                 break;
216         }
217
218         if (!r_info_blow_effect[n2])
219             return PARSE_ERROR_GENERIC;
220
221         /* loop */
222         for (s = t; *t && (*t != 'd'); t++)
223             ;
224
225         if (*t == 'd')
226             *t++ = '\0';
227
228         r_ptr->blow[i].method = (rbm_type)n1;
229         r_ptr->blow[i].effect = (rbe_type)n2;
230         r_ptr->blow[i].d_dice = atoi(s);
231         r_ptr->blow[i].d_side = atoi(t);
232     } else if (buf[0] == 'F') {
233         for (s = buf + 2; *s;) {
234             /* loop */
235             for (t = s; *t && (*t != ' ') && (*t != '|'); ++t)
236                 ;
237
238             if (*t) {
239                 *t++ = '\0';
240                 while (*t == ' ' || *t == '|')
241                     t++;
242             }
243
244             if (0 != grab_one_basic_flag(r_ptr, s))
245                 return PARSE_ERROR_INVALID_FLAG;
246
247             s = t;
248         }
249     } else if (buf[0] == 'S') {
250         for (s = buf + 2; *s;) {
251
252             /* loop */
253             for (t = s; *t && (*t != ' ') && (*t != '|'); ++t)
254                 ;
255
256             if (*t) {
257                 *t++ = '\0';
258                 while ((*t == ' ') || (*t == '|'))
259                     t++;
260             }
261
262             int i;
263             if (1 == sscanf(s, "1_IN_%d", &i)) {
264                 r_ptr->freq_spell = 100 / i;
265                 s = t;
266                 continue;
267             }
268
269             if (grab_one_spell_flag(r_ptr, s) != PARSE_ERROR_NONE)
270                 return PARSE_ERROR_INVALID_FLAG;
271
272             s = t;
273         }
274     } else if (buf[0] == 'A') {
275         int id, per, rarity;
276         int i = 0;
277         for (i = 0; i < 4; i++)
278             if (!r_ptr->artifact_id[i])
279                 break;
280
281         if ((i == 4) || (sscanf(buf + 2, "%d:%d:%d", &id, &rarity, &per) != 3))
282             return PARSE_ERROR_GENERIC;
283
284         r_ptr->artifact_id[i] = (ARTIFACT_IDX)id;
285         r_ptr->artifact_rarity[i] = (RARITY)rarity;
286         r_ptr->artifact_percent[i] = (PERCENTAGE)per;
287     } else if (buf[0] == 'V') {
288         int val;
289         if (sscanf(buf + 2, "%d", &val) != 3)
290             return 1;
291
292         r_ptr->arena_ratio = (PERCENTAGE)val;
293     } else {
294         return PARSE_ERROR_UNDEFINED_DIRECTIVE;
295     }
296
297     return PARSE_ERROR_NONE;
298 }