2 * @brief prefファイルの内容を解釈しメモリに展開する
7 #include "io/interpret-pref-file.h"
8 #include "birth/character-builder.h"
9 #include "cmd-io/macro-util.h"
10 #include "game-option/game-play-options.h"
11 #include "game-option/option-flags.h"
12 #include "game-option/option-types-table.h"
13 #include "grid/feature.h"
14 #include "io/gf-descriptions.h"
15 #include "io/input-key-requester.h"
16 #include "io/tokenizer.h"
17 #include "monster-race/monster-race.h"
18 #include "object/object-kind.h"
19 #include "system/game-option-types.h"
20 #include "system/monster-race-definition.h"
21 #include "system/player-type-definition.h"
22 #include "term/gameterm.h"
23 #include "util/quarks.h"
24 #include "util/string-processor.h"
25 #include "view/display-messages.h"
26 #include "world/world.h"
28 #define MAX_MACRO_CHARS 16128 // 1つのマクロキー押下で実行可能なコマンド最大数 (エスケープシーケンス含む).
30 char *histpref_buf = nullptr;
33 * @brief Rトークンの解釈 / Process "R:<num>:<a>/<c>" -- attr/char for monster races
37 static errr interpret_r_token(char *buf)
40 if (tokenize(buf + 2, 3, zz, TOKENIZE_CHECKQUOTE) != 3)
44 int i = (int)strtol(zz[0], nullptr, 0);
45 TERM_COLOR n1 = (TERM_COLOR)strtol(zz[1], nullptr, 0);
46 SYMBOL_CODE n2 = (SYMBOL_CODE)strtol(zz[2], nullptr, 0);
47 if (i >= static_cast<int>(r_info.size()))
51 if (n1 || (!(n2 & 0x80) && n2))
52 r_ptr->x_attr = n1; /* Allow TERM_DARK text */
60 * @brief Kトークンの解釈 / Process "K:<num>:<a>/<c>" -- attr/char for object kinds
64 static errr interpret_k_token(char *buf)
67 if (tokenize(buf + 2, 3, zz, TOKENIZE_CHECKQUOTE) != 3)
71 int i = (int)strtol(zz[0], nullptr, 0);
72 TERM_COLOR n1 = (TERM_COLOR)strtol(zz[1], nullptr, 0);
73 SYMBOL_CODE n2 = (SYMBOL_CODE)strtol(zz[2], nullptr, 0);
74 if (i >= static_cast<int>(k_info.size()))
78 if (n1 || (!(n2 & 0x80) && n2))
79 k_ptr->x_attr = n1; /* Allow TERM_DARK text */
87 * @brief トークン数によって地形の文字形と色を決定する
92 static errr decide_feature_type(int i, int num, char **zz)
97 TERM_COLOR n1 = (TERM_COLOR)strtol(zz[1], nullptr, 0);
98 SYMBOL_CODE n2 = (SYMBOL_CODE)strtol(zz[2], nullptr, 0);
99 if (n1 || (!(n2 & 0x80) && n2))
100 f_ptr->x_attr[F_LIT_STANDARD] = n1; /* Allow TERM_DARK text */
102 f_ptr->x_char[F_LIT_STANDARD] = n2;
106 /* No lighting support */
107 n1 = f_ptr->x_attr[F_LIT_STANDARD];
108 n2 = f_ptr->x_char[F_LIT_STANDARD];
109 for (int j = F_LIT_NS_BEGIN; j < F_LIT_MAX; j++) {
110 f_ptr->x_attr[j] = n1;
111 f_ptr->x_char[j] = n2;
117 /* Use default lighting */
118 apply_default_feat_lighting(f_ptr->x_attr, f_ptr->x_char);
121 case F_LIT_MAX * 2 + 1: {
122 /* Use desired lighting */
123 for (int j = F_LIT_NS_BEGIN; j < F_LIT_MAX; j++) {
124 n1 = (TERM_COLOR)strtol(zz[j * 2 + 1], nullptr, 0);
125 n2 = (SYMBOL_CODE)strtol(zz[j * 2 + 2], nullptr, 0);
126 if (n1 || (!(n2 & 0x80) && n2))
127 f_ptr->x_attr[j] = n1; /* Allow TERM_DARK text */
129 f_ptr->x_char[j] = n2;
140 * @brief Fトークンの解釈 / Process "F:<num>:<a>/<c>" -- attr/char for terrain features
145 * "F:<num>:<a>/<c>:LIT"
146 * "F:<num>:<a>/<c>:<la>/<lc>:<da>/<dc>"
148 static errr interpret_f_token(char *buf)
151 int num = tokenize(buf + 2, F_LIT_MAX * 2 + 1, zz, TOKENIZE_CHECKQUOTE);
153 if ((num != 3) && (num != 4) && (num != F_LIT_MAX * 2 + 1))
155 else if ((num == 4) && !streq(zz[3], "LIT"))
158 int i = (int)strtol(zz[0], nullptr, 0);
159 if (i >= static_cast<int>(f_info.size()))
162 return decide_feature_type(i, num, zz);
166 * @brief Fトークンの解釈 / Process "S:<num>:<a>/<c>" -- attr/char for special things
170 static errr interpret_s_token(char *buf)
173 if (tokenize(buf + 2, 3, zz, TOKENIZE_CHECKQUOTE) != 3)
176 int j = (byte)strtol(zz[0], nullptr, 0);
177 TERM_COLOR n1 = (TERM_COLOR)strtol(zz[1], nullptr, 0);
178 SYMBOL_CODE n2 = (SYMBOL_CODE)strtol(zz[2], nullptr, 0);
179 misc_to_attr[j] = n1;
180 misc_to_char[j] = n2;
185 * @brief Uトークンの解釈 / Process "U:<tv>:<a>/<c>" -- attr/char for unaware items
189 static errr interpret_u_token(char *buf)
192 if (tokenize(buf + 2, 3, zz, TOKENIZE_CHECKQUOTE) != 3)
195 int j = (int)strtol(zz[0], nullptr, 0);
196 TERM_COLOR n1 = (TERM_COLOR)strtol(zz[1], nullptr, 0);
197 SYMBOL_CODE n2 = (SYMBOL_CODE)strtol(zz[2], nullptr, 0);
198 for (auto &k_ref : k_info) {
199 if ((k_ref.idx > 0) && (enum2i(k_ref.tval) == j)) {
211 * @brief Eトークンの解釈 / Process "E:<tv>:<a>" -- attribute for inventory objects
215 static errr interpret_e_token(char *buf)
218 if (tokenize(buf + 2, 2, zz, TOKENIZE_CHECKQUOTE) != 2)
221 int j = (byte)strtol(zz[0], nullptr, 0) % 128;
222 TERM_COLOR n1 = (TERM_COLOR)strtol(zz[1], nullptr, 0);
224 tval_to_attr[j] = n1;
229 * @brief Pトークンの解釈 / Process "P:<str>" -- normal macro
233 static errr interpret_p_token(char *buf)
236 text_to_ascii(tmp, buf + 2);
237 return macro_add(tmp, macro__buf.data());
241 * @brief Cトークンの解釈 / Process "C:<str>" -- create keymap
245 static errr interpret_c_token(char *buf)
248 if (tokenize(buf + 2, 2, zz, TOKENIZE_CHECKQUOTE) != 2)
251 int mode = strtol(zz[0], nullptr, 0);
252 if ((mode < 0) || (mode >= KEYMAP_MODES))
256 text_to_ascii(tmp, zz[1]);
257 if (!tmp[0] || tmp[1])
260 int i = (byte)(tmp[0]);
261 string_free(keymap_act[mode][i]);
262 keymap_act[mode][i] = string_make(macro__buf.data());
267 * @brief Vトークンの解釈 / Process "V:<num>:<kv>:<rv>:<gv>:<bv>" -- visual info
271 static errr interpret_v_token(char *buf)
274 if (tokenize(buf + 2, 5, zz, TOKENIZE_CHECKQUOTE) != 5)
277 int i = (byte)strtol(zz[0], nullptr, 0);
278 angband_color_table[i][0] = (byte)strtol(zz[1], nullptr, 0);
279 angband_color_table[i][1] = (byte)strtol(zz[2], nullptr, 0);
280 angband_color_table[i][2] = (byte)strtol(zz[3], nullptr, 0);
281 angband_color_table[i][3] = (byte)strtol(zz[4], nullptr, 0);
287 * @param player_ptr プレイヤーへの参照ポインタ
291 * Process "X:<str>" -- turn option off
292 * Process "Y:<str>" -- turn option on
294 static errr interpret_xy_token(player_type *player_ptr, char *buf)
296 for (int i = 0; option_info[i].o_desc; i++) {
297 bool is_option = option_info[i].o_var != nullptr;
298 is_option &= option_info[i].o_text != nullptr;
299 is_option &= streq(option_info[i].o_text, buf + 2);
303 int os = option_info[i].o_set;
304 int ob = option_info[i].o_bit;
306 if ((player_ptr->playing || w_ptr->character_xtra) && (OPT_PAGE_BIRTH == option_info[i].o_page) && !allow_debug_options) {
307 msg_format(_("初期オプションは変更できません! '%s'", "Birth options can not changed! '%s'"), buf);
313 option_flag[os] &= ~(1UL << ob);
314 (*option_info[i].o_var) = false;
318 option_flag[os] |= (1UL << ob);
319 (*option_info[i].o_var) = true;
323 msg_format(_("オプションの名前が正しくありません: %s", "Ignored invalid option: %s"), buf);
329 * @brief Zトークンの解釈 / Process "Z:<type>:<str>" -- set spell color
331 * @param zz トークン保管文字列
334 static errr interpret_z_token(char *buf)
336 char *t = angband_strchr(buf + 2, ':');
341 for (int i = 0; i < MAX_NAMED_NUM; i++) {
342 if (!streq(gf_desc[i].name, buf + 2))
345 gf_color[gf_desc[i].num] = (TERM_COLOR)quark_add(t);
353 * @brief Tトークンの解釈 / Process "T:<template>:<modifier chr>:<modifier name>:..." for 4 tokens
355 * @param zz トークン保管文字列
358 static errr decide_template_modifier(int tok, char **zz)
360 if (macro_template != nullptr) {
361 int macro_modifier_length = strlen(macro_modifier_chr);
362 string_free(macro_template);
363 macro_template = nullptr;
364 string_free(macro_modifier_chr);
365 for (int i = 0; i < macro_modifier_length; i++) {
366 string_free(macro_modifier_name[i]);
369 for (int i = 0; i < max_macrotrigger; i++) {
370 string_free(macro_trigger_name[i]);
371 string_free(macro_trigger_keycode[0][i]);
372 string_free(macro_trigger_keycode[1][i]);
375 max_macrotrigger = 0;
381 int zz_length = strlen(zz[1]);
382 zz_length = std::min(MAX_MACRO_MOD, zz_length);
383 if (2 + zz_length != tok)
386 macro_template = string_make(zz[0]);
387 macro_modifier_chr = string_make(zz[1]);
388 for (int i = 0; i < zz_length; i++) {
389 macro_modifier_name[i] = string_make(zz[2 + i]);
396 * @brief Tトークンの解釈 / Process "T:<trigger>:<keycode>:<shift-keycode>" for 2 or 3 tokens
398 * @param zz トークン保管文字列
401 static errr interpret_macro_keycodes(int tok, char **zz)
403 char buf_aux[MAX_MACRO_CHARS];
405 if (max_macrotrigger >= MAX_MACRO_TRIG) {
406 msg_print(_("マクロトリガーの設定が多すぎます!", "Too many macro triggers!"));
410 int m = max_macrotrigger;
421 macro_trigger_name[m] = string_make(buf_aux);
422 macro_trigger_keycode[0][m] = string_make(zz[1]);
424 macro_trigger_keycode[1][m] = string_make(zz[2]);
428 macro_trigger_keycode[1][m] = string_make(zz[1]);
433 * @brief Tトークンの個数調査 (解釈はサブルーチンで) / Initialize macro trigger names and a template
436 * @todo 2.2.1r時点のコードからトークン数0~1の場合もエラーコード0だが、1であるべきでは?
438 static errr interpret_t_token(char *buf)
441 int tok = tokenize(buf + 2, 2 + MAX_MACRO_MOD, zz, 0);
443 return decide_template_modifier(tok, zz);
447 return interpret_macro_keycodes(tok, zz);
451 * @brief 設定ファイルの各行から各種テキスト情報を取得する /
452 * Parse a sub-file of the "extra info" (format shown below)
453 * @param player_ptr プレイヤーへの参照ポインタ
454 * @param buf データテキストの参照ポインタ
458 * Each "action" line has an "action symbol" in the first column,
459 * followed by a colon, followed by some command specific info,
460 * usually in the form of "tokens" separated by colons or slashes.
461 * Blank lines, lines starting with white space, and lines starting
462 * with pound signs ("#") are ignored (as comments).
463 * Note the use of "tokenize()" to allow the use of both colons and
464 * slashes as delimeters, while still allowing final tokens which
465 * may contain any characters including "delimiters".
466 * Note the use of "strtol()" to allow all "integers" to be encoded
467 * in decimal, hexidecimal, or octal form.
468 * Note that "monster zero" is used for the "player" attr/char, "object
469 * zero" will be used for the "stack" attr/char, and "feature zero" is
470 * used for the "nothing" attr/char.
473 errr interpret_pref_file(player_type *player_ptr, char *buf)
480 /* Process "H:<history>" */
481 add_history_from_pref_line(buf + 2);
485 return interpret_r_token(buf);
487 return interpret_k_token(buf);
489 return interpret_f_token(buf);
491 return interpret_s_token(buf);
493 return interpret_u_token(buf);
495 return interpret_e_token(buf);
497 /* Process "A:<str>" -- save an "action" for later */
498 text_to_ascii(macro__buf.data(), buf + 2);
502 return interpret_p_token(buf);
504 return interpret_c_token(buf);
506 return interpret_v_token(buf);
509 return interpret_xy_token(player_ptr, buf);
511 return interpret_z_token(buf);
513 return interpret_t_token(buf);
520 * @brief 生い立ちメッセージの内容をバッファに加える。 / Hook function for reading the histpref.prf file.
522 void add_history_from_pref_line(concptr t)
527 angband_strcat(histpref_buf, t, HISTPREF_LIMIT);