3 * @brief プレイヤーのインターフェイスに関するコマンドの実装 / Interface commands
7 * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke
8 * This software may be copied and distributed for educational, research,
9 * and not for profit purposes provided that this copyright and statement
10 * are included in all such copies. Other copyrights may also apply.
14 * A set of functions to maintain automatic dumps of various kinds.
15 * The dump commands of original Angband simply add new lines to
16 * existing files; these files will become bigger and bigger unless
17 * an user deletes some or all of these files by hand at some
19 * These three functions automatically delete old dumped lines
20 * before adding new ones. Since there are various kinds of automatic
21 * dumps in a single file, we add a header and a footer with a type
22 * name for every automatic dump, and kill old lines only when the
23 * lines have the correct type of header and footer.
24 * We need to be quite paranoid about correctness; the user might
25 * (mistakenly) edit the file by hand, and see all their work come
26 * to nothing on the next auto dump otherwise. The current code only
27 * detects changes by noting inconsistencies between the actual number
28 * of lines and the number written in the footer. Note that this will
29 * not catch single-line edits.
34 #include "cmd/cmd-draw.h"
35 #include "cmd/cmd-dump.h"
36 #include "cmd/cmd-inventory.h"
37 #include "cmd/lighting-level-table.h"
38 #include "cmd/cmd-visuals.h"
39 #include "cmd/dump-util.h"
41 #include "core.h" // 暫定。後で消す.
42 #include "core/show-file.h"
43 #include "io/read-pref-file.h"
44 #include "io/interpret-pref-file.h"
46 #include "knowledge/knowledge-artifacts.h"
47 #include "knowledge/knowledge-experiences.h"
48 #include "knowledge/knowledge-monsters.h"
49 #include "knowledge/knowledge-quests.h"
50 #include "knowledge/knowledge-self.h"
51 #include "knowledge/knowledge-uniques.h"
56 #include "view/display-player.h" // 暫定。後で消す.
57 #include "player-personality.h"
61 #include "market/store.h"
63 #include "object-flavor.h"
64 #include "object/object-kind.h"
65 #include "floor-town.h"
66 #include "cmd/feeling-table.h"
67 #include "cmd/object-group-table.h"
68 #include "market/store-util.h"
69 #include "view-mainwindow.h" // 暫定。後で消す
72 #include "diary-subtitle-table.h"
73 #include "io/write-diary.h"
77 * @brief prefファイルを選択して処理する /
78 * Ask for a "user pref line" and process it
79 * @brief prf出力内容を消去する /
80 * Remove old lines automatically generated before.
81 * @param orig_file 消去を行うファイル名
83 static void remove_auto_dump(concptr orig_file, concptr auto_dump_mark)
86 bool between_mark = FALSE;
89 long header_location = 0;
90 char header_mark_str[80];
91 char footer_mark_str[80];
93 sprintf(header_mark_str, auto_dump_header, auto_dump_mark);
94 sprintf(footer_mark_str, auto_dump_footer, auto_dump_mark);
95 size_t mark_len = strlen(footer_mark_str);
98 orig_fff = my_fopen(orig_file, "r");
99 if (!orig_fff) return;
101 FILE *tmp_fff = NULL;
102 char tmp_file[FILE_NAME_SIZE];
103 if (!open_temporary_file(&tmp_fff, tmp_file)) return;
107 if (my_fgets(orig_fff, buf, sizeof(buf)))
111 fseek(orig_fff, header_location, SEEK_SET);
112 between_mark = FALSE;
123 if (!strcmp(buf, header_mark_str))
125 header_location = ftell(orig_fff);
132 fprintf(tmp_fff, "%s\n", buf);
138 if (!strncmp(buf, footer_mark_str, mark_len))
141 if (!sscanf(buf + mark_len, " (%d)", &tmp)
144 fseek(orig_fff, header_location, SEEK_SET);
147 between_mark = FALSE;
159 tmp_fff = my_fopen(tmp_file, "r");
160 orig_fff = my_fopen(orig_file, "w");
161 while (!my_fgets(tmp_fff, buf, sizeof(buf)))
162 fprintf(orig_fff, "%s\n", buf);
175 * @brief Return suffix of ordinal number
177 * @return pointer of suffix string.
179 concptr get_ordinal_number_suffix(int num)
181 num = ABS(num) % 100;
185 return (num == 11) ? "th" : "st";
187 return (num == 12) ? "th" : "nd";
189 return (num == 13) ? "th" : "rd";
197 * @brief 画面を再描画するコマンドのメインルーチン
198 * Hack -- redraw the screen
199 * @param creature_ptr プレーヤーへの参照ポインタ
202 * Allow absolute file names?
204 void do_cmd_pref(player_type *creature_ptr)
208 if (!get_string(_("設定変更コマンド: ", "Pref: "), buf, 80)) return;
210 (void)interpret_pref_file(creature_ptr, buf);
215 * @brief 自動拾い設定ファイルをロードするコマンドのメインルーチン /
216 * @param creature_ptr プレーヤーへの参照ポインタ
219 void do_cmd_reload_autopick(player_type *creature_ptr)
221 if (!get_check(_("自動拾い設定ファイルをロードしますか? ", "Reload auto-pick preference file? ")))
224 autopick_load_pref(creature_ptr, TRUE);
229 * Interact with "colors"
231 void do_cmd_colors(player_type *creature_ptr)
236 FILE *auto_dump_stream;
237 FILE_TYPE(FILE_TYPE_TEXT);
242 prt(_("[ カラーの設定 ]", "Interact with Colors"), 2, 0);
243 prt(_("(1) ユーザー設定ファイルのロード", "(1) Load a user pref file"), 4, 5);
244 prt(_("(2) カラーの設定をファイルに書き出す", "(2) Dump colors"), 5, 5);
245 prt(_("(3) カラーの設定を変更する", "(3) Modify colors"), 6, 5);
246 prt(_("コマンド: ", "Command: "), 8, 0);
248 if (i == ESCAPE) break;
252 prt(_("コマンド: ユーザー設定ファイルをロードします", "Command: Load a user pref file"), 8, 0);
253 prt(_("ファイル: ", "File: "), 10, 0);
254 sprintf(tmp, "%s.prf", creature_ptr->base_name);
255 if (!askfor(tmp, 70)) continue;
257 (void)process_pref_file(creature_ptr, tmp);
258 Term_xtra(TERM_XTRA_REACT, 0);
263 static concptr mark = "Colors";
264 prt(_("コマンド: カラーの設定をファイルに書き出します", "Command: Dump colors"), 8, 0);
265 prt(_("ファイル: ", "File: "), 10, 0);
266 sprintf(tmp, "%s.prf", creature_ptr->base_name);
267 if (!askfor(tmp, 70)) continue;
269 path_build(buf, sizeof(buf), ANGBAND_DIR_USER, tmp);
270 if (!open_auto_dump(&auto_dump_stream, buf, mark)) continue;
272 auto_dump_printf(auto_dump_stream, _("\n# カラーの設定\n\n", "\n# Color redefinitions\n\n"));
273 for (i = 0; i < 256; i++)
275 int kv = angband_color_table[i][0];
276 int rv = angband_color_table[i][1];
277 int gv = angband_color_table[i][2];
278 int bv = angband_color_table[i][3];
280 concptr name = _("未知", "unknown");
281 if (!kv && !rv && !gv && !bv) continue;
283 if (i < 16) name = color_names[i];
285 auto_dump_printf(auto_dump_stream, _("# カラー '%s'\n", "# Color '%s'\n"), name);
286 auto_dump_printf(auto_dump_stream, "V:%d:0x%02X:0x%02X:0x%02X:0x%02X\n\n",
290 close_auto_dump(&auto_dump_stream, mark);
291 msg_print(_("カラーの設定をファイルに書き出しました。", "Dumped color redefinitions."));
296 prt(_("コマンド: カラーの設定を変更します", "Command: Modify colors"), 8, 0);
301 for (byte j = 0; j < 16; j++)
303 Term_putstr(j * 4, 20, -1, a, "###");
304 Term_putstr(j * 4, 22, -1, j, format("%3d", j));
307 name = ((a < 16) ? color_names[a] : _("未定義", "undefined"));
308 Term_putstr(5, 10, -1, TERM_WHITE,
309 format(_("カラー = %d, 名前 = %s", "Color = %d, Name = %s"), a, name));
310 Term_putstr(5, 12, -1, TERM_WHITE,
311 format("K = 0x%02x / R,G,B = 0x%02x,0x%02x,0x%02x",
312 angband_color_table[a][0],
313 angband_color_table[a][1],
314 angband_color_table[a][2],
315 angband_color_table[a][3]));
316 Term_putstr(0, 14, -1, TERM_WHITE,
317 _("コマンド (n/N/k/K/r/R/g/G/b/B): ", "Command (n/N/k/K/r/R/g/G/b/B): "));
319 if (i == ESCAPE) break;
321 if (i == 'n') a = (byte)(a + 1);
322 if (i == 'N') a = (byte)(a - 1);
323 if (i == 'k') angband_color_table[a][0] = (byte)(angband_color_table[a][0] + 1);
324 if (i == 'K') angband_color_table[a][0] = (byte)(angband_color_table[a][0] - 1);
325 if (i == 'r') angband_color_table[a][1] = (byte)(angband_color_table[a][1] + 1);
326 if (i == 'R') angband_color_table[a][1] = (byte)(angband_color_table[a][1] - 1);
327 if (i == 'g') angband_color_table[a][2] = (byte)(angband_color_table[a][2] + 1);
328 if (i == 'G') angband_color_table[a][2] = (byte)(angband_color_table[a][2] - 1);
329 if (i == 'b') angband_color_table[a][3] = (byte)(angband_color_table[a][3] + 1);
330 if (i == 'B') angband_color_table[a][3] = (byte)(angband_color_table[a][3] - 1);
332 Term_xtra(TERM_XTRA_REACT, 0);
349 * Note something in the message recall
351 void do_cmd_note(void)
355 if (!get_string(_("メモ: ", "Note: "), buf, 60)) return;
356 if (!buf[0] || (buf[0] == ' ')) return;
358 msg_format(_("メモ: %s", "Note: %s"), buf);
363 * Mention the current version
365 void do_cmd_version(void)
367 #if FAKE_VER_EXTRA > 0
368 msg_format(_("変愚蛮怒(Hengband) %d.%d.%d.%d", "You are playing Hengband %d.%d.%d.%d."),
369 FAKE_VER_MAJOR - 10, FAKE_VER_MINOR, FAKE_VER_PATCH, FAKE_VER_EXTRA);
371 msg_format(_("変愚蛮怒(Hengband) %d.%d.%d", "You are playing Hengband %d.%d.%d."),
372 FAKE_VER_MAJOR - 10, FAKE_VER_MINOR, FAKE_VER_PATCH);
378 * Note that "feeling" is set to zero unless some time has passed.
379 * Note that this is done when the level is GENERATED, not entered.
381 void do_cmd_feeling(player_type *creature_ptr)
383 if (creature_ptr->wild_mode) return;
385 if (creature_ptr->current_floor_ptr->inside_quest && !random_quest_number(creature_ptr, creature_ptr->current_floor_ptr->dun_level))
387 msg_print(_("典型的なクエストのダンジョンのようだ。", "Looks like a typical quest level."));
391 if (creature_ptr->town_num && !creature_ptr->current_floor_ptr->dun_level)
393 if (!strcmp(town_info[creature_ptr->town_num].name, _("荒野", "wilderness")))
395 msg_print(_("何かありそうな荒野のようだ。", "Looks like a strange wilderness."));
399 msg_print(_("典型的な町のようだ。", "Looks like a typical town."));
403 if (!creature_ptr->current_floor_ptr->dun_level)
405 msg_print(_("典型的な荒野のようだ。", "Looks like a typical wilderness."));
409 if (creature_ptr->muta3 & MUT3_GOOD_LUCK)
410 msg_print(do_cmd_feeling_text_lucky[creature_ptr->feeling]);
411 else if (IS_ECHIZEN(creature_ptr))
412 msg_print(do_cmd_feeling_text_combat[creature_ptr->feeling]);
414 msg_print(do_cmd_feeling_text[creature_ptr->feeling]);
419 * Build a list of object indexes in the given group. Return the number
420 * of objects in the group.
422 * mode & 0x01 : check for non-empty group
423 * mode & 0x02 : visual operation only
425 static KIND_OBJECT_IDX collect_objects(int grp_cur, KIND_OBJECT_IDX object_idx[], BIT_FLAGS8 mode)
427 KIND_OBJECT_IDX object_cnt = 0;
428 byte group_tval = object_group_tval[grp_cur];
429 for (KIND_OBJECT_IDX i = 0; i < max_k_idx; i++)
431 object_kind *k_ptr = &k_info[i];
432 if (!k_ptr->name) continue;
436 if (!current_world_ptr->wizard)
438 if (!k_ptr->flavor) continue;
439 if (!k_ptr->aware) continue;
443 for (int j = 0; j < 4; j++)
444 k += k_ptr->chance[j];
448 if (TV_LIFE_BOOK == group_tval)
450 if (TV_LIFE_BOOK <= k_ptr->tval && k_ptr->tval <= TV_HEX_BOOK)
452 object_idx[object_cnt++] = i;
457 else if (k_ptr->tval == group_tval)
459 object_idx[object_cnt++] = i;
464 if (mode & 0x01) break;
467 object_idx[object_cnt] = -1;
473 * Build a list of feature indexes in the given group. Return the number
474 * of features in the group.
476 * mode & 0x01 : check for non-empty group
478 static FEAT_IDX collect_features(FEAT_IDX *feat_idx, BIT_FLAGS8 mode)
480 FEAT_IDX feat_cnt = 0;
481 for (FEAT_IDX i = 0; i < max_f_idx; i++)
483 feature_type *f_ptr = &f_info[i];
484 if (!f_ptr->name) continue;
485 if (f_ptr->mimic != i) continue;
487 feat_idx[feat_cnt++] = i;
488 if (mode & 0x01) break;
491 feat_idx[feat_cnt] = -1;
497 * Display the objects in a group.
499 static void display_object_list(int col, int row, int per_page, IDX object_idx[],
500 int object_cur, int object_top, bool visual_only)
503 for (i = 0; i < per_page && (object_idx[object_top + i] >= 0); i++)
505 GAME_TEXT o_name[MAX_NLEN];
508 object_kind *flavor_k_ptr;
509 KIND_OBJECT_IDX k_idx = object_idx[object_top + i];
510 object_kind *k_ptr = &k_info[k_idx];
511 TERM_COLOR attr = ((k_ptr->aware || visual_only) ? TERM_WHITE : TERM_SLATE);
512 byte cursor = ((k_ptr->aware || visual_only) ? TERM_L_BLUE : TERM_BLUE);
513 if (!visual_only && k_ptr->flavor)
515 flavor_k_ptr = &k_info[k_ptr->flavor];
519 flavor_k_ptr = k_ptr;
522 attr = ((i + object_top == object_cur) ? cursor : attr);
523 if (!k_ptr->flavor || (!visual_only && k_ptr->aware))
525 strip_name(o_name, k_idx);
529 strcpy(o_name, k_name + flavor_k_ptr->flavor_name);
532 c_prt(attr, o_name, row + i, col);
535 c_prt(attr, format("%02x/%02x", flavor_k_ptr->x_attr, flavor_k_ptr->x_char), row + i, (current_world_ptr->wizard || visual_only) ? 64 : 68);
538 if (current_world_ptr->wizard || visual_only)
540 c_prt(attr, format("%d", k_idx), row + i, 70);
543 a = flavor_k_ptr->x_attr;
544 c = flavor_k_ptr->x_char;
546 Term_queue_bigchar(use_bigtile ? 76 : 77, row + i, a, c, 0, 0);
549 for (; i < per_page; i++)
551 Term_erase(col, row + i, 255);
557 * Describe fake object
559 static void desc_obj_fake(player_type *creature_ptr, KIND_OBJECT_IDX k_idx)
562 object_type object_type_body;
563 o_ptr = &object_type_body;
565 object_prep(o_ptr, k_idx);
567 o_ptr->ident |= IDENT_KNOWN;
568 handle_stuff(creature_ptr);
570 if (screen_object(creature_ptr, o_ptr, SCROBJ_FAKE_OBJECT | SCROBJ_FORCE_DETAIL)) return;
572 msg_print(_("特に変わったところはないようだ。", "You see nothing special."));
578 * Display known objects
580 void do_cmd_knowledge_objects(player_type *creature_ptr, bool *need_redraw, bool visual_only, IDX direct_k_idx)
582 IDX object_old, object_top;
585 OBJECT_IDX *object_idx;
587 bool visual_list = FALSE;
588 TERM_COLOR attr_top = 0;
593 Term_get_size(&wid, &hgt);
595 int browser_rows = hgt - 8;
596 C_MAKE(object_idx, max_k_idx, KIND_OBJECT_IDX);
601 if (direct_k_idx < 0)
603 mode = visual_only ? 0x03 : 0x01;
604 for (IDX i = 0; object_group_text[i] != NULL; i++)
606 len = strlen(object_group_text[i]);
607 if (len > max) max = len;
609 if (collect_objects(i, object_idx, mode))
611 grp_idx[grp_cnt++] = i;
620 object_kind *k_ptr = &k_info[direct_k_idx];
621 object_kind *flavor_k_ptr;
623 if (!visual_only && k_ptr->flavor)
625 flavor_k_ptr = &k_info[k_ptr->flavor];
629 flavor_k_ptr = k_ptr;
632 object_idx[0] = direct_k_idx;
633 object_old = direct_k_idx;
636 (void)visual_mode_command('v', &visual_list, browser_rows - 1, wid - (max + 3),
637 &attr_top, &char_left, &flavor_k_ptr->x_attr, &flavor_k_ptr->x_char, need_redraw);
640 grp_idx[grp_cnt] = -1;
641 mode = visual_only ? 0x02 : 0x00;
642 IDX old_grp_cur = -1;
645 IDX object_cur = object_top = 0;
651 object_kind *k_ptr, *flavor_k_ptr;
658 prt(format("%s - アイテム", !visual_only ? "知識" : "表示"), 2, 0);
659 if (direct_k_idx < 0) prt("グループ", 4, 0);
660 prt("名前", 4, max + 3);
661 if (current_world_ptr->wizard || visual_only) prt("Idx", 4, 70);
664 prt(format("%s - objects", !visual_only ? "Knowledge" : "Visuals"), 2, 0);
665 if (direct_k_idx < 0) prt("Group", 4, 0);
666 prt("Name", 4, max + 3);
667 if (current_world_ptr->wizard || visual_only) prt("Idx", 4, 70);
671 for (IDX i = 0; i < 78; i++)
673 Term_putch(i, 5, TERM_WHITE, '=');
676 if (direct_k_idx < 0)
678 for (IDX i = 0; i < browser_rows; i++)
680 Term_putch(max + 1, 6 + i, TERM_WHITE, '|');
687 if (direct_k_idx < 0)
689 if (grp_cur < grp_top) grp_top = grp_cur;
690 if (grp_cur >= grp_top + browser_rows) grp_top = grp_cur - browser_rows + 1;
692 display_group_list(0, 6, max, browser_rows, grp_idx, object_group_text, grp_cur, grp_top);
693 if (old_grp_cur != grp_cur)
695 old_grp_cur = grp_cur;
696 object_cnt = collect_objects(grp_idx[grp_cur], object_idx, mode);
699 while (object_cur < object_top)
700 object_top = MAX(0, object_top - browser_rows / 2);
701 while (object_cur >= object_top + browser_rows)
702 object_top = MIN(object_cnt - browser_rows, object_top + browser_rows / 2);
707 display_object_list(max + 3, 6, browser_rows, object_idx, object_cur, object_top, visual_only);
711 object_top = object_cur;
712 display_object_list(max + 3, 6, 1, object_idx, object_cur, object_top, visual_only);
713 display_visual_list(max + 3, 7, browser_rows - 1, wid - (max + 3), attr_top, char_left);
716 k_ptr = &k_info[object_idx[object_cur]];
718 if (!visual_only && k_ptr->flavor)
720 flavor_k_ptr = &k_info[k_ptr->flavor];
724 flavor_k_ptr = k_ptr;
728 prt(format("<方向>%s%s%s, ESC",
729 (!visual_list && !visual_only) ? ", 'r'で詳細を見る" : "",
730 visual_list ? ", ENTERで決定" : ", 'v'でシンボル変更",
731 (attr_idx || char_idx) ? ", 'c', 'p'でペースト" : ", 'c'でコピー"),
734 prt(format("<dir>%s%s%s, ESC",
735 (!visual_list && !visual_only) ? ", 'r' to recall" : "",
736 visual_list ? ", ENTER to accept" : ", 'v' for visuals",
737 (attr_idx || char_idx) ? ", 'c', 'p' to paste" : ", 'c' to copy"),
743 if (object_cnt) object_kind_track(creature_ptr, object_idx[object_cur]);
745 if (object_old != object_idx[object_cur])
747 handle_stuff(creature_ptr);
748 object_old = object_idx[object_cur];
754 place_visual_list_cursor(max + 3, 7, flavor_k_ptr->x_attr, flavor_k_ptr->x_char, attr_top, char_left);
758 Term_gotoxy(0, 6 + (grp_cur - grp_top));
762 Term_gotoxy(max + 3, 6 + (object_cur - object_top));
766 if (visual_mode_command(ch, &visual_list, browser_rows - 1, wid - (max + 3), &attr_top, &char_left, &flavor_k_ptr->x_attr, &flavor_k_ptr->x_char, need_redraw))
768 if (direct_k_idx >= 0)
793 if (!visual_list && !visual_only && (grp_cnt > 0))
795 desc_obj_fake(creature_ptr, object_idx[object_cur]);
804 browser_cursor(ch, &column, &grp_cur, grp_cnt, &object_cur, object_cnt);
810 C_KILL(object_idx, max_k_idx, KIND_OBJECT_IDX);
815 * Display the features in a group.
817 static void display_feature_list(int col, int row, int per_page, FEAT_IDX *feat_idx,
818 FEAT_IDX feat_cur, FEAT_IDX feat_top, bool visual_only, int lighting_level)
820 int lit_col[F_LIT_MAX], i;
821 int f_idx_col = use_bigtile ? 62 : 64;
823 lit_col[F_LIT_STANDARD] = use_bigtile ? (71 - F_LIT_MAX) : 71;
824 for (i = F_LIT_NS_BEGIN; i < F_LIT_MAX; i++)
825 lit_col[i] = lit_col[F_LIT_STANDARD] + 2 + (i - F_LIT_NS_BEGIN) * 2 + (use_bigtile ? i : 0);
827 for (i = 0; i < per_page && (feat_idx[feat_top + i] >= 0); i++)
830 FEAT_IDX f_idx = feat_idx[feat_top + i];
831 feature_type *f_ptr = &f_info[f_idx];
833 attr = ((i + feat_top == feat_cur) ? TERM_L_BLUE : TERM_WHITE);
834 c_prt(attr, f_name + f_ptr->name, row_i, col);
837 c_prt(attr, format("(%s)", lighting_level_str[lighting_level]), row_i, col + 1 + strlen(f_name + f_ptr->name));
838 c_prt(attr, format("%02x/%02x", f_ptr->x_attr[lighting_level], f_ptr->x_char[lighting_level]), row_i, f_idx_col - ((current_world_ptr->wizard || visual_only) ? 6 : 2));
840 if (current_world_ptr->wizard || visual_only)
842 c_prt(attr, format("%d", f_idx), row_i, f_idx_col);
845 Term_queue_bigchar(lit_col[F_LIT_STANDARD], row_i, f_ptr->x_attr[F_LIT_STANDARD], f_ptr->x_char[F_LIT_STANDARD], 0, 0);
846 Term_putch(lit_col[F_LIT_NS_BEGIN], row_i, TERM_SLATE, '(');
847 for (int j = F_LIT_NS_BEGIN + 1; j < F_LIT_MAX; j++)
849 Term_putch(lit_col[j], row_i, TERM_SLATE, '/');
852 Term_putch(lit_col[F_LIT_MAX - 1] + (use_bigtile ? 3 : 2), row_i, TERM_SLATE, ')');
853 for (int j = F_LIT_NS_BEGIN; j < F_LIT_MAX; j++)
855 Term_queue_bigchar(lit_col[j] + 1, row_i, f_ptr->x_attr[j], f_ptr->x_char[j], 0, 0);
859 for (; i < per_page; i++)
861 Term_erase(col, row + i, 255);
867 * Interact with feature visuals.
869 void do_cmd_knowledge_features(bool *need_redraw, bool visual_only, IDX direct_f_idx, IDX *lighting_level)
871 TERM_COLOR attr_old[F_LIT_MAX];
872 (void)C_WIPE(attr_old, F_LIT_MAX, TERM_COLOR);
873 SYMBOL_CODE char_old[F_LIT_MAX];
874 (void)C_WIPE(char_old, F_LIT_MAX, SYMBOL_CODE);
877 Term_get_size(&wid, &hgt);
880 C_MAKE(feat_idx, max_f_idx, FEAT_IDX);
882 concptr feature_group_text[] = { "terrains", NULL };
887 FEAT_IDX grp_idx[100];
888 TERM_COLOR attr_top = 0;
889 bool visual_list = FALSE;
891 TERM_LEN browser_rows = hgt - 8;
892 if (direct_f_idx < 0)
894 for (FEAT_IDX i = 0; feature_group_text[i] != NULL; i++)
896 len = strlen(feature_group_text[i]);
897 if (len > max) max = len;
899 if (collect_features(feat_idx, 0x01))
901 grp_idx[grp_cnt++] = i;
909 feature_type *f_ptr = &f_info[direct_f_idx];
911 feat_idx[0] = direct_f_idx;
915 (void)visual_mode_command('v', &visual_list, browser_rows - 1, wid - (max + 3),
916 &attr_top, &char_left, &f_ptr->x_attr[*lighting_level], &f_ptr->x_char[*lighting_level], need_redraw);
918 for (FEAT_IDX i = 0; i < F_LIT_MAX; i++)
920 attr_old[i] = f_ptr->x_attr[i];
921 char_old[i] = f_ptr->x_char[i];
925 grp_idx[grp_cnt] = -1;
927 FEAT_IDX old_grp_cur = -1;
928 FEAT_IDX grp_cur = 0;
929 FEAT_IDX grp_top = 0;
930 FEAT_IDX feat_cur = 0;
931 FEAT_IDX feat_top = 0;
935 TERM_COLOR *cur_attr_ptr;
936 SYMBOL_CODE *cur_char_ptr;
946 prt(_("表示 - 地形", "Visuals - features"), 2, 0);
947 if (direct_f_idx < 0) prt(_("グループ", "Group"), 4, 0);
948 prt(_("名前", "Name"), 4, max + 3);
951 if (current_world_ptr->wizard || visual_only) prt("Idx", 4, 62);
952 prt(_("文字 ( l/ d)", "Sym ( l/ d)"), 4, 66);
956 if (current_world_ptr->wizard || visual_only) prt("Idx", 4, 64);
957 prt(_("文字 (l/d)", "Sym (l/d)"), 4, 68);
960 for (FEAT_IDX i = 0; i < 78; i++)
962 Term_putch(i, 5, TERM_WHITE, '=');
965 if (direct_f_idx < 0)
967 for (FEAT_IDX i = 0; i < browser_rows; i++)
969 Term_putch(max + 1, 6 + i, TERM_WHITE, '|');
976 if (direct_f_idx < 0)
978 if (grp_cur < grp_top) grp_top = grp_cur;
979 if (grp_cur >= grp_top + browser_rows) grp_top = grp_cur - browser_rows + 1;
981 display_group_list(0, 6, max, browser_rows, grp_idx, feature_group_text, grp_cur, grp_top);
982 if (old_grp_cur != grp_cur)
984 old_grp_cur = grp_cur;
985 feat_cnt = collect_features(feat_idx, 0x00);
988 while (feat_cur < feat_top)
989 feat_top = MAX(0, feat_top - browser_rows / 2);
990 while (feat_cur >= feat_top + browser_rows)
991 feat_top = MIN(feat_cnt - browser_rows, feat_top + browser_rows / 2);
996 display_feature_list(max + 3, 6, browser_rows, feat_idx, feat_cur, feat_top, visual_only, F_LIT_STANDARD);
1000 feat_top = feat_cur;
1001 display_feature_list(max + 3, 6, 1, feat_idx, feat_cur, feat_top, visual_only, *lighting_level);
1002 display_visual_list(max + 3, 7, browser_rows - 1, wid - (max + 3), attr_top, char_left);
1005 prt(format(_("<方向>%s, 'd'で標準光源効果%s, ESC", "<dir>%s, 'd' for default lighting%s, ESC"),
1006 visual_list ? _(", ENTERで決定, 'a'で対象明度変更", ", ENTER to accept, 'a' for lighting level") : _(", 'v'でシンボル変更", ", 'v' for visuals"),
1007 (attr_idx || char_idx) ? _(", 'c', 'p'でペースト", ", 'c', 'p' to paste") : _(", 'c'でコピー", ", 'c' to copy")),
1010 f_ptr = &f_info[feat_idx[feat_cur]];
1011 cur_attr_ptr = &f_ptr->x_attr[*lighting_level];
1012 cur_char_ptr = &f_ptr->x_char[*lighting_level];
1016 place_visual_list_cursor(max + 3, 7, *cur_attr_ptr, *cur_char_ptr, attr_top, char_left);
1020 Term_gotoxy(0, 6 + (grp_cur - grp_top));
1024 Term_gotoxy(max + 3, 6 + (feat_cur - feat_top));
1028 if (visual_list && ((ch == 'A') || (ch == 'a')))
1030 int prev_lighting_level = *lighting_level;
1034 if (*lighting_level <= 0) *lighting_level = F_LIT_MAX - 1;
1035 else (*lighting_level)--;
1039 if (*lighting_level >= F_LIT_MAX - 1) *lighting_level = 0;
1040 else (*lighting_level)++;
1043 if (f_ptr->x_attr[prev_lighting_level] != f_ptr->x_attr[*lighting_level])
1044 attr_top = MAX(0, (f_ptr->x_attr[*lighting_level] & 0x7f) - 5);
1046 if (f_ptr->x_char[prev_lighting_level] != f_ptr->x_char[*lighting_level])
1047 char_left = MAX(0, f_ptr->x_char[*lighting_level] - 10);
1051 else if ((ch == 'D') || (ch == 'd'))
1053 TERM_COLOR prev_x_attr = f_ptr->x_attr[*lighting_level];
1054 byte prev_x_char = f_ptr->x_char[*lighting_level];
1056 apply_default_feat_lighting(f_ptr->x_attr, f_ptr->x_char);
1060 if (prev_x_attr != f_ptr->x_attr[*lighting_level])
1061 attr_top = MAX(0, (f_ptr->x_attr[*lighting_level] & 0x7f) - 5);
1063 if (prev_x_char != f_ptr->x_char[*lighting_level])
1064 char_left = MAX(0, f_ptr->x_char[*lighting_level] - 10);
1066 else *need_redraw = TRUE;
1070 else if (visual_mode_command(ch, &visual_list, browser_rows - 1, wid - (max + 3), &attr_top, &char_left, cur_attr_ptr, cur_char_ptr, need_redraw))
1075 for (FEAT_IDX i = 0; i < F_LIT_MAX; i++)
1077 f_ptr->x_attr[i] = attr_old[i];
1078 f_ptr->x_char[i] = char_old[i];
1084 if (direct_f_idx >= 0) flag = TRUE;
1085 else *lighting_level = F_LIT_STANDARD;
1089 for (FEAT_IDX i = 0; i < F_LIT_MAX; i++)
1091 attr_old[i] = f_ptr->x_attr[i];
1092 char_old[i] = f_ptr->x_char[i];
1094 *lighting_level = F_LIT_STANDARD;
1101 for (FEAT_IDX i = 0; i < F_LIT_MAX; i++)
1103 attr_idx_feat[i] = f_ptr->x_attr[i];
1104 char_idx_feat[i] = f_ptr->x_char[i];
1113 for (FEAT_IDX i = F_LIT_NS_BEGIN; i < F_LIT_MAX; i++)
1115 if (attr_idx_feat[i] || (!(char_idx_feat[i] & 0x80) && char_idx_feat[i])) f_ptr->x_attr[i] = attr_idx_feat[i];
1116 if (char_idx_feat[i]) f_ptr->x_char[i] = char_idx_feat[i];
1134 browser_cursor(ch, &column, &grp_cur, grp_cnt, &feat_cur, feat_cnt);
1140 C_KILL(feat_idx, max_f_idx, FEAT_IDX);
1147 static void do_cmd_knowledge_dungeon(player_type *creature_ptr)
1150 GAME_TEXT file_name[FILE_NAME_SIZE];
1151 if (!open_temporary_file(&fff, file_name)) return;
1153 for (int i = 1; i < current_world_ptr->max_d_idx; i++)
1157 if (!d_info[i].maxdepth) continue;
1158 if (!max_dlv[i]) continue;
1159 if (d_info[i].final_guardian)
1161 if (!r_info[d_info[i].final_guardian].max_num) seiha = TRUE;
1163 else if (max_dlv[i] == d_info[i].maxdepth) seiha = TRUE;
1165 fprintf(fff, _("%c%-12s : %3d 階\n", "%c%-16s : level %3d\n"), seiha ? '!' : ' ', d_name + d_info[i].name, (int)max_dlv[i]);
1169 (void)show_file(creature_ptr, TRUE, file_name, _("今までに入ったダンジョン", "Dungeon"), 0, 0);
1175 * Check the status of "autopick"
1177 static void do_cmd_knowledge_autopick(player_type *creature_ptr)
1180 GAME_TEXT file_name[FILE_NAME_SIZE];
1181 if (!open_temporary_file(&fff, file_name)) return;
1185 fprintf(fff, _("自動破壊/拾いには何も登録されていません。", "No preference for auto picker/destroyer."));
1189 fprintf(fff, _(" 自動拾い/破壊には現在 %d行登録されています。\n\n",
1190 " There are %d registered lines for auto picker/destroyer.\n\n"), max_autopick);
1193 for (int k = 0; k < max_autopick; k++)
1196 byte act = autopick_list[k].action;
1197 if (act & DONT_AUTOPICK)
1199 tmp = _("放置", "Leave");
1201 else if (act & DO_AUTODESTROY)
1203 tmp = _("破壊", "Destroy");
1205 else if (act & DO_AUTOPICK)
1207 tmp = _("拾う", "Pickup");
1211 tmp = _("確認", "Query");
1214 if (act & DO_DISPLAY)
1215 fprintf(fff, "%11s", format("[%s]", tmp));
1217 fprintf(fff, "%11s", format("(%s)", tmp));
1219 tmp = autopick_line_from_entry(&autopick_list[k]);
1220 fprintf(fff, " %s", tmp);
1227 (void)show_file(creature_ptr, TRUE, file_name, _("自動拾い/破壊 設定リスト", "Auto-picker/Destroyer"), 0, 0);
1233 * Interact with "knowledge"
1235 void do_cmd_knowledge(player_type *creature_ptr)
1238 bool need_redraw = FALSE;
1239 FILE_TYPE(FILE_TYPE_TEXT);
1244 prt(format(_("%d/2 ページ", "page %d/2"), (p + 1)), 2, 65);
1245 prt(_("現在の知識を確認する", "Display current knowledge"), 3, 0);
1248 prt(_("(1) 既知の伝説のアイテム の一覧", "(1) Display known artifacts"), 6, 5);
1249 prt(_("(2) 既知のアイテム の一覧", "(2) Display known objects"), 7, 5);
1250 prt(_("(3) 既知の生きているユニーク・モンスター の一覧", "(3) Display remaining uniques"), 8, 5);
1251 prt(_("(4) 既知のモンスター の一覧", "(4) Display known monster"), 9, 5);
1252 prt(_("(5) 倒した敵の数 の一覧", "(5) Display kill count"), 10, 5);
1253 if (!vanilla_town) prt(_("(6) 賞金首 の一覧", "(6) Display wanted monsters"), 11, 5);
1254 prt(_("(7) 現在のペット の一覧", "(7) Display current pets"), 12, 5);
1255 prt(_("(8) 我が家のアイテム の一覧", "(8) Display home inventory"), 13, 5);
1256 prt(_("(9) *鑑定*済み装備の耐性 の一覧", "(9) Display *identified* equip."), 14, 5);
1257 prt(_("(0) 地形の表示文字/タイル の一覧", "(0) Display terrain symbols."), 15, 5);
1261 prt(_("(a) 自分に関する情報 の一覧", "(a) Display about yourself"), 6, 5);
1262 prt(_("(b) 突然変異 の一覧", "(b) Display mutations"), 7, 5);
1263 prt(_("(c) 武器の経験値 の一覧", "(c) Display weapon proficiency"), 8, 5);
1264 prt(_("(d) 魔法の経験値 の一覧", "(d) Display spell proficiency"), 9, 5);
1265 prt(_("(e) 技能の経験値 の一覧", "(e) Display misc. proficiency"), 10, 5);
1266 prt(_("(f) プレイヤーの徳 の一覧", "(f) Display virtues"), 11, 5);
1267 prt(_("(g) 入ったダンジョン の一覧", "(g) Display dungeons"), 12, 5);
1268 prt(_("(h) 実行中のクエスト の一覧", "(h) Display current quests"), 13, 5);
1269 prt(_("(i) 現在の自動拾い/破壊設定 の一覧", "(i) Display auto pick/destroy"), 14, 5);
1272 prt(_("-続く-", "-more-"), 17, 8);
1273 prt(_("ESC) 抜ける", "ESC) Exit menu"), 21, 1);
1274 prt(_("SPACE) 次ページ", "SPACE) Next page"), 21, 30);
1275 prt(_("コマンド:", "Command: "), 20, 0);
1278 if (i == ESCAPE) break;
1281 case ' ': /* Page change */
1285 case '1': /* Artifacts */
1286 do_cmd_knowledge_artifacts(creature_ptr);
1288 case '2': /* Objects */
1289 do_cmd_knowledge_objects(creature_ptr, &need_redraw, FALSE, -1);
1291 case '3': /* Uniques */
1292 do_cmd_knowledge_uniques(creature_ptr);
1294 case '4': /* Monsters */
1295 do_cmd_knowledge_monsters(creature_ptr, &need_redraw, FALSE, -1);
1297 case '5': /* Kill count */
1298 do_cmd_knowledge_kill_count(creature_ptr);
1300 case '6': /* wanted */
1301 if (!vanilla_town) do_cmd_knowledge_bounty(creature_ptr);
1303 case '7': /* Pets */
1304 do_cmd_knowledge_pets(creature_ptr);
1306 case '8': /* Home */
1307 do_cmd_knowledge_home(creature_ptr);
1309 case '9': /* Resist list */
1310 do_cmd_knowledge_inventory(creature_ptr);
1312 case '0': /* Feature list */
1314 IDX lighting_level = F_LIT_STANDARD;
1315 do_cmd_knowledge_features(&need_redraw, FALSE, -1, &lighting_level);
1319 case 'a': /* Max stat */
1320 do_cmd_knowledge_stat(creature_ptr);
1322 case 'b': /* Mutations */
1323 do_cmd_knowledge_mutations(creature_ptr);
1325 case 'c': /* weapon-exp */
1326 do_cmd_knowledge_weapon_exp(creature_ptr);
1328 case 'd': /* spell-exp */
1329 do_cmd_knowledge_spell_exp(creature_ptr);
1331 case 'e': /* skill-exp */
1332 do_cmd_knowledge_skill_exp(creature_ptr);
1334 case 'f': /* Virtues */
1335 do_cmd_knowledge_virtues(creature_ptr);
1337 case 'g': /* Dungeon */
1338 do_cmd_knowledge_dungeon(creature_ptr);
1340 case 'h': /* Quests */
1341 do_cmd_knowledge_quests(creature_ptr);
1343 case 'i': /* Autopick */
1344 do_cmd_knowledge_autopick(creature_ptr);
1346 default: /* Unknown option */
1354 if (need_redraw) do_cmd_redraw(creature_ptr);
1359 * Check on the status of an active quest
1360 * @param creature_ptr プレーヤーへの参照ポインタ
1363 void do_cmd_checkquest(player_type *creature_ptr)
1365 FILE_TYPE(FILE_TYPE_TEXT);
1367 do_cmd_knowledge_quests(creature_ptr);
1373 * Display the time and date
1374 * @param creature_ptr プレーヤーへの参照ポインタ
1377 void do_cmd_time(player_type *creature_ptr)
1380 extract_day_hour_min(creature_ptr, &day, &hour, &min);
1383 strcpy(desc, _("変な時刻だ。", "It is a strange time."));
1386 if (day < MAX_DAYS) sprintf(day_buf, "%d", day);
1387 else strcpy(day_buf, "*****");
1389 msg_format(_("%s日目, 時刻は%d:%02d %sです。", "This is day %s. The time is %d:%02d %s."),
1390 day_buf, (hour % 12 == 0) ? 12 : (hour % 12), min, (hour < 12) ? "AM" : "PM");
1393 if (!randint0(10) || creature_ptr->image)
1395 path_build(buf, sizeof(buf), ANGBAND_DIR_FILE, _("timefun_j.txt", "timefun.txt"));
1399 path_build(buf, sizeof(buf), ANGBAND_DIR_FILE, _("timenorm_j.txt", "timenorm.txt"));
1403 fff = my_fopen(buf, "rt");
1407 int full = hour * 100 + min;
1411 while (!my_fgets(fff, buf, sizeof(buf)))
1413 if (!buf[0] || (buf[0] == '#')) continue;
1414 if (buf[1] != ':') continue;
1418 start = atoi(buf + 2);
1425 end = atoi(buf + 2);
1429 if ((start > full) || (full > end)) continue;
1434 if (!randint0(num)) strcpy(desc, buf + 2);