OSDN Git Service

b9601f2a224ee2fab4c77c8b2c7236a1b9738dbd
[hengband/hengband.git] / src / io / interpret-pref-file.c
1 /*!
2  * @brief prefファイルの内容を解釈しメモリに展開する
3  * @date 2020/03/01
4  * @author Hourier
5  */
6
7 #include "io/interpret-pref-file.h"
8 #include "io/gf-descriptions.h"
9 #include "io/tokenizer.h"
10 #include "object/object-kind.h"
11 #include "birth.h"
12 #include "world.h"
13 #include "gameterm.h"
14 #include "view-mainwindow.h" // 暫定。apply_default_feat_lighting()。後で消す.
15
16 #define MAX_MACRO_CHARS 65536 // 1つのマクロキー押下で実行可能なコマンド最大数 (エスケープシーケンス含む).
17
18 /*!
19  * @brief Rトークンの解釈 / Process "R:<num>:<a>/<c>" -- attr/char for monster races
20  * @param buf バッファ
21  * @return エラーコード
22  */
23 static errr interpret_r_token(char *buf)
24 {
25         char *zz[16];
26         if (tokenize(buf + 2, 3, zz, TOKENIZE_CHECKQUOTE) != 3) return 1;
27
28         monster_race *r_ptr;
29         int i = (int)strtol(zz[0], NULL, 0);
30         TERM_COLOR n1 = (TERM_COLOR)strtol(zz[1], NULL, 0);
31         SYMBOL_CODE n2 = (SYMBOL_CODE)strtol(zz[2], NULL, 0);
32         if (i >= max_r_idx) return 1;
33
34         r_ptr = &r_info[i];
35         if (n1 || (!(n2 & 0x80) && n2)) r_ptr->x_attr = n1; /* Allow TERM_DARK text */
36         if (n2) r_ptr->x_char = n2;
37
38         return 0;
39 }
40
41
42 /*!
43  * @brief Kトークンの解釈 / Process "K:<num>:<a>/<c>"  -- attr/char for object kinds
44  * @param buf バッファ
45  * @return エラーコード
46  */
47 static errr interpret_k_token(char *buf)
48 {
49         char *zz[16];
50         if (tokenize(buf + 2, 3, zz, TOKENIZE_CHECKQUOTE) != 3) return 1;
51
52         object_kind *k_ptr;
53         int i = (int)strtol(zz[0], NULL, 0);
54         TERM_COLOR n1 = (TERM_COLOR)strtol(zz[1], NULL, 0);
55         SYMBOL_CODE n2 = (SYMBOL_CODE)strtol(zz[2], NULL, 0);
56         if (i >= max_k_idx) return 1;
57
58         k_ptr = &k_info[i];
59         if (n1 || (!(n2 & 0x80) && n2)) k_ptr->x_attr = n1; /* Allow TERM_DARK text */
60         if (n2) k_ptr->x_char = n2;
61
62         return 0;
63 }
64
65
66 /*!
67  * @brief トークン数によって地形の文字形と色を決定する
68  * @param i 地形種別
69  * @param num トークン数
70  * @return エラーコード
71  */
72 static errr decide_feature_type(int i, int num, char **zz)
73 {
74         feature_type *f_ptr;
75         f_ptr = &f_info[i];
76
77         TERM_COLOR n1 = (TERM_COLOR)strtol(zz[1], NULL, 0);
78         SYMBOL_CODE n2 = (SYMBOL_CODE)strtol(zz[2], NULL, 0);
79         if (n1 || (!(n2 & 0x80) && n2)) f_ptr->x_attr[F_LIT_STANDARD] = n1; /* Allow TERM_DARK text */
80         if (n2) f_ptr->x_char[F_LIT_STANDARD] = n2;
81
82         switch (num)
83         {
84         case 3:
85         {
86                 /* No lighting support */
87                 n1 = f_ptr->x_attr[F_LIT_STANDARD];
88                 n2 = f_ptr->x_char[F_LIT_STANDARD];
89                 for (int j = F_LIT_NS_BEGIN; j < F_LIT_MAX; j++)
90                 {
91                         f_ptr->x_attr[j] = n1;
92                         f_ptr->x_char[j] = n2;
93                 }
94
95                 return 0;
96         }
97         case 4:
98         {
99                 /* Use default lighting */
100                 apply_default_feat_lighting(f_ptr->x_attr, f_ptr->x_char);
101                 return 0;
102         }
103         case F_LIT_MAX * 2 + 1:
104         {
105                 /* Use desired lighting */
106                 for (int j = F_LIT_NS_BEGIN; j < F_LIT_MAX; j++)
107                 {
108                         n1 = (TERM_COLOR)strtol(zz[j * 2 + 1], NULL, 0);
109                         n2 = (SYMBOL_CODE)strtol(zz[j * 2 + 2], NULL, 0);
110                         if (n1 || (!(n2 & 0x80) && n2)) f_ptr->x_attr[j] = n1; /* Allow TERM_DARK text */
111                         if (n2) f_ptr->x_char[j] = n2;
112                 }
113
114                 return 0;
115         }
116         default:
117                 return 0;
118         }
119 }
120
121
122 /*!
123  * @brief Fトークンの解釈 / Process "F:<num>:<a>/<c>" -- attr/char for terrain features
124  * @param buf バッファ
125  * @return エラーコード
126  * @details
127  * "F:<num>:<a>/<c>"
128  * "F:<num>:<a>/<c>:LIT"
129  * "F:<num>:<a>/<c>:<la>/<lc>:<da>/<dc>"
130  */
131 static errr interpret_f_token(char *buf)
132 {
133         char *zz[16];
134         int num = tokenize(buf + 2, F_LIT_MAX * 2 + 1, zz, TOKENIZE_CHECKQUOTE);
135
136         if ((num != 3) && (num != 4) && (num != F_LIT_MAX * 2 + 1)) return 1;
137         else if ((num == 4) && !streq(zz[3], "LIT")) return 1;
138
139         int i = (int)strtol(zz[0], NULL, 0);
140         if (i >= max_f_idx) return 1;
141
142         return decide_feature_type(i, num, zz);
143 }
144
145
146 /*!
147  * @brief Fトークンの解釈 / Process "S:<num>:<a>/<c>" -- attr/char for special things
148  * @param buf バッファ
149  * @return エラーコード
150  */
151 static errr interpret_s_token(char *buf)
152 {
153         char *zz[16];
154         if (tokenize(buf + 2, 3, zz, TOKENIZE_CHECKQUOTE) != 3) return 1;
155
156         int j = (byte)strtol(zz[0], NULL, 0);
157         TERM_COLOR n1 = (TERM_COLOR)strtol(zz[1], NULL, 0);
158         SYMBOL_CODE n2 = (SYMBOL_CODE)strtol(zz[2], NULL, 0);
159         misc_to_attr[j] = n1;
160         misc_to_char[j] = n2;
161         return 0;
162 }
163
164
165 /*!
166  * @brief Uトークンの解釈 / Process "U:<tv>:<a>/<c>" -- attr/char for unaware items
167  * @param buf バッファ
168  * @return エラーコード
169  */
170 static errr interpret_u_token(char *buf)
171 {
172         char *zz[16];
173         if (tokenize(buf + 2, 3, zz, TOKENIZE_CHECKQUOTE) != 3) return 1;
174
175         int j = (int)strtol(zz[0], NULL, 0);
176         TERM_COLOR n1 = (TERM_COLOR)strtol(zz[1], NULL, 0);
177         SYMBOL_CODE n2 = (SYMBOL_CODE)strtol(zz[2], NULL, 0);
178         for (int i = 1; i < max_k_idx; i++)
179         {
180                 object_kind *k_ptr = &k_info[i];
181                 if (k_ptr->tval == j)
182                 {
183                         if (n1) k_ptr->d_attr = n1;
184                         if (n2) k_ptr->d_char = n2;
185                 }
186         }
187
188         return 0;
189 }
190
191
192 /*!
193  * @brief Eトークンの解釈 / Process "E:<tv>:<a>" -- attribute for inventory objects
194  * @param buf バッファ
195  * @return エラーコード
196  */
197 static errr interpret_e_token(char *buf)
198 {
199         char *zz[16];
200         if (tokenize(buf + 2, 2, zz, TOKENIZE_CHECKQUOTE) != 2) return 1;
201
202         int j = (byte)strtol(zz[0], NULL, 0) % 128;
203         TERM_COLOR n1 = (TERM_COLOR)strtol(zz[1], NULL, 0);
204         if (n1) tval_to_attr[j] = n1;
205         return 0;
206 }
207
208
209 /*!
210  * @brief Pトークンの解釈 / Process "P:<str>" -- normal macro
211  * @param buf バッファ
212  * @return エラーコード
213  */
214 static errr interpret_p_token(char *buf)
215 {
216         char tmp[1024];
217         text_to_ascii(tmp, buf + 2);
218         macro_add(tmp, macro__buf);
219         return 0;
220 }
221
222
223 /*!
224  * @brief Cトークンの解釈 / Process "C:<str>" -- create keymap
225  * @param buf バッファ
226  * @return エラーコード
227  */
228 static errr interpret_c_token(char *buf)
229 {
230         char *zz[16];
231         if (tokenize(buf + 2, 2, zz, TOKENIZE_CHECKQUOTE) != 2) return 1;
232
233         int mode = strtol(zz[0], NULL, 0);
234         if ((mode < 0) || (mode >= KEYMAP_MODES)) return 1;
235
236         char tmp[1024];
237         text_to_ascii(tmp, zz[1]);
238         if (!tmp[0] || tmp[1]) return 1;
239
240         int i = (byte)(tmp[0]);
241         string_free(keymap_act[mode][i]);
242         keymap_act[mode][i] = string_make(macro__buf);
243         return 0;
244 }
245
246
247 /*!
248  * @brief Vトークンの解釈 / Process "V:<num>:<kv>:<rv>:<gv>:<bv>" -- visual info
249  * @param buf バッファ
250  * @return エラーコード
251  */
252 static errr interpret_v_token(char *buf)
253 {
254         char *zz[16];
255         if (tokenize(buf + 2, 5, zz, TOKENIZE_CHECKQUOTE) != 5) return 1;
256
257         int i = (byte)strtol(zz[0], NULL, 0);
258         angband_color_table[i][0] = (byte)strtol(zz[1], NULL, 0);
259         angband_color_table[i][1] = (byte)strtol(zz[2], NULL, 0);
260         angband_color_table[i][2] = (byte)strtol(zz[3], NULL, 0);
261         angband_color_table[i][3] = (byte)strtol(zz[4], NULL, 0);
262         return 0;
263 }
264
265
266 /*!
267  * @brief X/Yトークンの解釈
268  * @param creature_ptr プレーヤーへの参照ポインタ
269  * @param buf バッファ
270  * @return エラーコード
271  * @details
272  * Process "X:<str>" -- turn option off
273  * Process "Y:<str>" -- turn option on
274  */
275 static errr interpret_xy_token(player_type *creature_ptr, char *buf)
276 {
277         for (int i = 0; option_info[i].o_desc; i++)
278         {
279                 bool is_option = option_info[i].o_var != NULL;
280                 is_option &= option_info[i].o_text != NULL;
281                 is_option &= streq(option_info[i].o_text, buf + 2);
282                 if (!is_option) continue;
283
284                 int os = option_info[i].o_set;
285                 int ob = option_info[i].o_bit;
286
287                 if ((creature_ptr->playing || current_world_ptr->character_xtra) &&
288                         (OPT_PAGE_BIRTH == option_info[i].o_page) && !current_world_ptr->wizard)
289                 {
290                         msg_format(_("初期オプションは変更できません! '%s'", "Birth options can not changed! '%s'"), buf);
291                         msg_print(NULL);
292                         return 0;
293                 }
294
295                 if (buf[0] == 'X')
296                 {
297                         option_flag[os] &= ~(1L << ob);
298                         (*option_info[i].o_var) = FALSE;
299                         return 0;
300                 }
301
302                 option_flag[os] |= (1L << ob);
303                 (*option_info[i].o_var) = TRUE;
304                 return 0;
305         }
306
307         msg_format(_("オプションの名前が正しくありません: %s", "Ignored invalid option: %s"), buf);
308         msg_print(NULL);
309         return 0;
310 }
311
312
313 /*!
314  * @brief Zトークンの解釈 / Process "Z:<type>:<str>" -- set spell color
315  * @param buf バッファ
316  * @param zz トークン保管文字列
317  * @return エラーコード
318  */
319 static errr interpret_z_token(char *buf)
320 {
321         char *t = my_strchr(buf + 2, ':');
322         if (!t) return 1;
323
324         *(t++) = '\0';
325         for (int i = 0; i < MAX_NAMED_NUM; i++)
326         {
327                 if (!streq(gf_desc[i].name, buf + 2)) continue;
328
329                 gf_color[gf_desc[i].num] = (TERM_COLOR)quark_add(t);
330                 return 0;
331         }
332
333         return 1;
334 }
335
336
337 /*!
338  * @brief Tトークンの解釈 / Process "T:<template>:<modifier chr>:<modifier name>:..." for 4 tokens
339  * @param buf バッファ
340  * @param zz トークン保管文字列
341  * @return エラーコード
342  */
343 static errr decide_template_modifier(int tok, char **zz)
344 {
345         if (macro_template != NULL)
346         {
347                 int macro_modifier_length = strlen(macro_modifier_chr);
348                 string_free(macro_template);
349                 macro_template = NULL;
350                 string_free(macro_modifier_chr);
351                 for (int i = 0; i < macro_modifier_length; i++)
352                 {
353                         string_free(macro_modifier_name[i]);
354                 }
355
356                 for (int i = 0; i < max_macrotrigger; i++)
357                 {
358                         string_free(macro_trigger_name[i]);
359                         string_free(macro_trigger_keycode[0][i]);
360                         string_free(macro_trigger_keycode[1][i]);
361                 }
362
363                 max_macrotrigger = 0;
364         }
365
366         if (*zz[0] == '\0') return 0;
367
368         int zz_length = strlen(zz[1]);
369         zz_length = MIN(MAX_MACRO_MOD, zz_length);
370         if (2 + zz_length != tok) return 1;
371
372         macro_template = string_make(zz[0]);
373         macro_modifier_chr = string_make(zz[1]);
374         for (int i = 0; i < zz_length; i++)
375         {
376                 macro_modifier_name[i] = string_make(zz[2 + i]);
377         }
378
379         return 0;
380 }
381
382
383 /*!
384  * @brief Tトークンの解釈 / Process "T:<trigger>:<keycode>:<shift-keycode>" for 2 or 3 tokens
385  * @param tok トークン数
386  * @param zz トークン保管文字列
387  * @return エラーコード
388  */
389 static errr interpret_macro_keycodes(int tok, char **zz)
390 {
391         char buf_aux[MAX_MACRO_CHARS];
392         char *t, *s;
393         if (max_macrotrigger >= MAX_MACRO_TRIG)
394         {
395                 msg_print(_("マクロトリガーの設定が多すぎます!", "Too many macro triggers!"));
396                 return 1;
397         }
398
399         int m = max_macrotrigger;
400         max_macrotrigger++;
401         t = buf_aux;
402         s = zz[0];
403         while (*s)
404         {
405                 if ('\\' == *s) s++;
406                 *t++ = *s++;
407         }
408
409         *t = '\0';
410         macro_trigger_name[m] = string_make(buf_aux);
411         macro_trigger_keycode[0][m] = string_make(zz[1]);
412         if (tok == 3)
413         {
414                 macro_trigger_keycode[1][m] = string_make(zz[2]);
415                 return 0;
416         }
417
418         macro_trigger_keycode[1][m] = string_make(zz[1]);
419         return 0;
420 }
421
422
423 /*!
424  * todo 2.2.1r時点のコードからトークン数0~1の場合もエラーコード0だが、1であるべきでは?
425  * @brief Tトークンの個数調査 (解釈はサブルーチンで) / Initialize macro trigger names and a template
426  * @param buf バッファ
427  * @return エラーコード
428  */
429 static errr interpret_t_token(char *buf)
430 {
431         char *zz[16];
432         int tok = tokenize(buf + 2, 2 + MAX_MACRO_MOD, zz, 0);
433         if (tok >= 4) return decide_template_modifier(tok, zz);
434         if (tok < 2) return 0;
435
436         return interpret_macro_keycodes(tok, zz);
437 }
438
439
440 /*!
441  * @brief 設定ファイルの各行から各種テキスト情報を取得する /
442  * Parse a sub-file of the "extra info" (format shown below)
443  * @param creature_ptr プレーヤーへの参照ポインタ
444  * @param buf データテキストの参照ポインタ
445  * @return エラーコード
446  * @details
447  * <pre>
448  * Each "action" line has an "action symbol" in the first column,
449  * followed by a colon, followed by some command specific info,
450  * usually in the form of "tokens" separated by colons or slashes.
451  * Blank lines, lines starting with white space, and lines starting
452  * with pound signs ("#") are ignored (as comments).
453  * Note the use of "tokenize()" to allow the use of both colons and
454  * slashes as delimeters, while still allowing final tokens which
455  * may contain any characters including "delimiters".
456  * Note the use of "strtol()" to allow all "integers" to be encoded
457  * in decimal, hexidecimal, or octal form.
458  * Note that "monster zero" is used for the "player" attr/char, "object
459  * zero" will be used for the "stack" attr/char, and "feature zero" is
460  * used for the "nothing" attr/char.
461  * </pre>
462  */
463 errr interpret_pref_file(player_type *creature_ptr, char *buf)
464 {
465         if (buf[1] != ':') return 1;
466
467         switch (buf[0])
468         {
469         case 'H':
470         {
471                 /* Process "H:<history>" */
472                 add_history_from_pref_line(buf + 2);
473                 return 0;
474         }
475         case 'R':
476                 return interpret_r_token(buf);
477         case 'K':
478                 return interpret_k_token(buf);
479         case 'F':
480                 return interpret_f_token(buf);
481         case 'S':
482                 return interpret_s_token(buf);
483         case 'U':
484                 return interpret_u_token(buf);
485         case 'E':
486                 return interpret_e_token(buf);
487         case 'A':
488         {
489                 /* Process "A:<str>" -- save an "action" for later */
490                 text_to_ascii(macro__buf, buf + 2);
491                 return 0;
492         }
493         case 'P':
494                 return interpret_p_token(buf);
495         case 'C':
496                 return interpret_c_token(buf);
497         case 'V':
498                 return interpret_v_token(buf);
499         case 'X':
500         case 'Y':
501                 return interpret_xy_token(creature_ptr, buf);
502         case 'Z':
503                 return interpret_z_token(buf);
504         case 'T':
505                 return interpret_t_token(buf);
506         default:
507                 return 1;
508         }
509 }