OSDN Git Service

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