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/lighting-level-table.h"
37 #include "cmd/cmd-visuals.h"
39 #include "core.h" // 暫定。後で消す.
40 #include "core/show-file.h"
41 #include "io/read-pref-file.h"
42 #include "io/interpret-pref-file.h"
47 #include "view/display-player.h" // 暫定。後で消す.
48 #include "player/process-name.h"
49 #include "player-effects.h"
50 #include "player-skill.h"
51 #include "player-personality.h"
58 #include "object-flavor.h"
59 #include "object-hook.h"
60 #include "monster-status.h"
61 #include "dungeon-file.h"
62 #include "objectkind.h"
63 #include "floor-town.h"
64 #include "cmd/feeling-table.h"
65 #include "cmd/monster-group-table.h"
66 #include "cmd/object-group-table.h"
67 #include "market/store-util.h"
68 #include "view-mainwindow.h" // 暫定。後で消す
71 #include "diary-subtitle-table.h"
73 // Clipboard variables for copy&paste in visual mode
74 static TERM_COLOR attr_idx = 0;
75 static SYMBOL_CODE char_idx = 0;
77 static TERM_COLOR attr_idx_feat[F_LIT_MAX];
78 static SYMBOL_CODE char_idx_feat[F_LIT_MAX];
80 // Encode the screen colors
81 static char hack[17] = "dwsorgbuDWvyRGBU";
85 * @brief prefファイルを選択して処理する /
86 * Ask for a "user pref line" and process it
88 * @brief prf出力内容を消去する /
89 * Remove old lines automatically generated before.
90 * @param orig_file 消去を行うファイル名
92 static void remove_auto_dump(concptr orig_file)
94 FILE *tmp_fff, *orig_fff;
97 bool between_mark = FALSE;
100 long header_location = 0;
101 char header_mark_str[80];
102 char footer_mark_str[80];
104 sprintf(header_mark_str, auto_dump_header, auto_dump_mark);
105 sprintf(footer_mark_str, auto_dump_footer, auto_dump_mark);
106 size_t mark_len = strlen(footer_mark_str);
107 orig_fff = my_fopen(orig_file, "r");
108 if (!orig_fff) return;
110 tmp_fff = my_fopen_temp(tmp_file, 1024);
113 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), tmp_file);
120 if (my_fgets(orig_fff, buf, sizeof(buf)))
124 fseek(orig_fff, header_location, SEEK_SET);
125 between_mark = FALSE;
136 if (!strcmp(buf, header_mark_str))
138 header_location = ftell(orig_fff);
145 fprintf(tmp_fff, "%s\n", buf);
151 if (!strncmp(buf, footer_mark_str, mark_len))
154 if (!sscanf(buf + mark_len, " (%d)", &tmp)
157 fseek(orig_fff, header_location, SEEK_SET);
160 between_mark = FALSE;
172 tmp_fff = my_fopen(tmp_file, "r");
173 orig_fff = my_fopen(orig_file, "w");
174 while (!my_fgets(tmp_fff, buf, sizeof(buf)))
175 fprintf(orig_fff, "%s\n", buf);
186 * @brief prfファイルのフォーマットに従った内容を出力する /
187 * Dump a formatted line, using "vstrnfmt()".
190 static void auto_dump_printf(concptr fmt, ...)
195 (void)vstrnfmt(buf, sizeof(buf), fmt, vp);
197 for (concptr p = buf; *p; p++)
199 if (*p == '\n') auto_dump_line_num++;
202 fprintf(auto_dump_stream, "%s", buf);
207 * @brief prfファイルをファイルオープンする /
208 * Open file to append auto dump.
210 * @param mark 出力するヘッダマーク
211 * @return ファイルポインタを取得できたらTRUEを返す
213 static bool open_auto_dump(concptr buf, concptr mark)
215 char header_mark_str[80];
216 auto_dump_mark = mark;
217 sprintf(header_mark_str, auto_dump_header, auto_dump_mark);
218 remove_auto_dump(buf);
219 auto_dump_stream = my_fopen(buf, "a");
220 if (!auto_dump_stream)
222 msg_format(_("%s を開くことができませんでした。", "Failed to open %s."), buf);
227 fprintf(auto_dump_stream, "%s\n", header_mark_str);
228 auto_dump_line_num = 0;
229 auto_dump_printf(_("# *警告!!* 以降の行は自動生成されたものです。\n",
230 "# *Warning!* The lines below are an automatic dump.\n"));
231 auto_dump_printf(_("# *警告!!* 後で自動的に削除されるので編集しないでください。\n",
232 "# Don't edit them; changes will be deleted and replaced automatically.\n"));
237 * @brief prfファイルをファイルクローズする /
238 * Append foot part and close auto dump.
241 static void close_auto_dump(void)
243 char footer_mark_str[80];
244 sprintf(footer_mark_str, auto_dump_footer, auto_dump_mark);
245 auto_dump_printf(_("# *警告!!* 以降の行は自動生成されたものです。\n",
246 "# *Warning!* The lines below are an automatic dump.\n"));
247 auto_dump_printf(_("# *警告!!* 後で自動的に削除されるので編集しないでください。\n",
248 "# Don't edit them; changes will be deleted and replaced automatically.\n"));
249 fprintf(auto_dump_stream, "%s (%d)\n", footer_mark_str, auto_dump_line_num);
250 my_fclose(auto_dump_stream);
257 * @brief Return suffix of ordinal number
259 * @return pointer of suffix string.
261 concptr get_ordinal_number_suffix(int num)
263 num = ABS(num) % 100;
267 return (num == 11) ? "th" : "st";
269 return (num == 12) ? "th" : "nd";
271 return (num == 13) ? "th" : "rd";
280 * @brief 日記のタイトル表記と内容出力
281 * @param creature_ptr プレーヤーへの参照ポインタ
284 static void display_diary(player_type *creature_ptr)
286 char diary_title[256];
287 GAME_TEXT file_name[MAX_NLEN];
290 sprintf(file_name, _("playrecord-%s.txt", "playrec-%s.txt"), savefile_base);
291 path_build(buf, sizeof(buf), ANGBAND_DIR_USER, file_name);
293 if (creature_ptr->pclass == CLASS_WARRIOR || creature_ptr->pclass == CLASS_MONK || creature_ptr->pclass == CLASS_SAMURAI || creature_ptr->pclass == CLASS_BERSERKER)
294 strcpy(tmp, subtitle[randint0(MAX_SUBTITLE - 1)]);
295 else if (IS_WIZARD_CLASS(creature_ptr))
296 strcpy(tmp, subtitle[randint0(MAX_SUBTITLE - 1) + 1]);
297 else strcpy(tmp, subtitle[randint0(MAX_SUBTITLE - 2) + 1]);
300 sprintf(diary_title, "「%s%s%sの伝説 -%s-」", ap_ptr->title, ap_ptr->no ? "の" : "", creature_ptr->name, tmp);
302 sprintf(diary_title, "Legend of %s %s '%s'", ap_ptr->title, creature_ptr->name, tmp);
305 (void)show_file(creature_ptr, FALSE, buf, diary_title, -1, 0);
310 * @brief 日記に任意の内容を表記するコマンドのメインルーチン /
313 static void add_diary_note(player_type *creature_ptr)
316 char bunshou[80] = "\0";
317 if (get_string(_("内容: ", "diary note: "), tmp, 79))
319 strcpy(bunshou, tmp);
320 exe_write_diary(creature_ptr, DIARY_DESCRIPTION, 0, bunshou);
325 * @brief 最後に取得したアイテムの情報を日記に追加するメインルーチン /
328 static void do_cmd_last_get(player_type *creaute_ptr)
330 if (record_o_name[0] == '\0') return;
333 sprintf(buf, _("%sの入手を記録します。", "Do you really want to record getting %s? "), record_o_name);
334 if (!get_check(buf)) return;
336 GAME_TURN turn_tmp = current_world_ptr->game_turn;
337 current_world_ptr->game_turn = record_turn;
338 sprintf(buf, _("%sを手に入れた。", "discovered %s."), record_o_name);
339 exe_write_diary(creaute_ptr, DIARY_DESCRIPTION, 0, buf);
340 current_world_ptr->game_turn = turn_tmp;
345 * @brief ファイル中の全日記記録を消去する /
348 static void do_cmd_erase_diary(void)
350 GAME_TEXT file_name[MAX_NLEN];
354 if (!get_check(_("本当に記録を消去しますか?", "Do you really want to delete all your record? "))) return;
355 sprintf(file_name, _("playrecord-%s.txt", "playrec-%s.txt"), savefile_base);
356 path_build(buf, sizeof(buf), ANGBAND_DIR_USER, file_name);
359 fff = my_fopen(buf, "w");
363 msg_format(_("記録を消去しました。", "deleted record."));
367 msg_format(_("%s の消去に失敗しました。", "failed to delete %s."), buf);
376 * @param crerature_ptr プレーヤーへの参照ポインタ
379 void do_cmd_diary(player_type *creature_ptr)
381 FILE_TYPE(FILE_TYPE_TEXT);
387 prt(_("[ 記録の設定 ]", "[ Play Record ]"), 2, 0);
388 prt(_("(1) 記録を見る", "(1) Display your record"), 4, 5);
389 prt(_("(2) 文章を記録する", "(2) Add record"), 5, 5);
390 prt(_("(3) 直前に入手又は鑑定したものを記録する", "(3) Record the last item you got or identified"), 6, 5);
391 prt(_("(4) 記録を消去する", "(4) Delete your record"), 7, 5);
392 prt(_("(R) プレイ動画を記録する/中止する", "(R) Record playing movie / or stop it"), 9, 5);
393 prt(_("コマンド:", "Command: "), 18, 0);
395 if (i == ESCAPE) break;
400 display_diary(creature_ptr);
403 add_diary_note(creature_ptr);
406 do_cmd_last_get(creature_ptr);
409 do_cmd_erase_diary();
413 prepare_movie_hooks();
427 * @brief 画面を再描画するコマンドのメインルーチン
428 * Hack -- redraw the screen
429 >>>>>>> aed56f4e1a8c71b3fc97b2fa5265f3c13efc2da1
430 * @param creature_ptr プレーヤーへの参照ポインタ
433 * Allow absolute file names?
435 void do_cmd_pref(player_type *creature_ptr)
439 if (!get_string(_("設定変更コマンド: ", "Pref: "), buf, 80)) return;
441 (void)interpret_pref_file(creature_ptr, buf);
446 * @brief 自動拾い設定ファイルをロードするコマンドのメインルーチン /
447 * @param creature_ptr プレーヤーへの参照ポインタ
450 void do_cmd_reload_autopick(player_type *creature_ptr)
452 if (!get_check(_("自動拾い設定ファイルをロードしますか? ", "Reload auto-pick preference file? ")))
455 autopick_load_pref(creature_ptr, TRUE);
460 * Interact with "colors"
462 void do_cmd_colors(player_type *creature_ptr)
467 FILE_TYPE(FILE_TYPE_TEXT);
472 prt(_("[ カラーの設定 ]", "Interact with Colors"), 2, 0);
473 prt(_("(1) ユーザー設定ファイルのロード", "(1) Load a user pref file"), 4, 5);
474 prt(_("(2) カラーの設定をファイルに書き出す", "(2) Dump colors"), 5, 5);
475 prt(_("(3) カラーの設定を変更する", "(3) Modify colors"), 6, 5);
476 prt(_("コマンド: ", "Command: "), 8, 0);
478 if (i == ESCAPE) break;
482 prt(_("コマンド: ユーザー設定ファイルをロードします", "Command: Load a user pref file"), 8, 0);
483 prt(_("ファイル: ", "File: "), 10, 0);
484 sprintf(tmp, "%s.prf", creature_ptr->base_name);
485 if (!askfor(tmp, 70)) continue;
487 (void)process_pref_file(creature_ptr, tmp);
488 Term_xtra(TERM_XTRA_REACT, 0);
493 static concptr mark = "Colors";
494 prt(_("コマンド: カラーの設定をファイルに書き出します", "Command: Dump colors"), 8, 0);
495 prt(_("ファイル: ", "File: "), 10, 0);
496 sprintf(tmp, "%s.prf", creature_ptr->base_name);
497 if (!askfor(tmp, 70)) continue;
499 path_build(buf, sizeof(buf), ANGBAND_DIR_USER, tmp);
500 if (!open_auto_dump(buf, mark)) continue;
502 auto_dump_printf(_("\n# カラーの設定\n\n", "\n# Color redefinitions\n\n"));
503 for (i = 0; i < 256; i++)
505 int kv = angband_color_table[i][0];
506 int rv = angband_color_table[i][1];
507 int gv = angband_color_table[i][2];
508 int bv = angband_color_table[i][3];
510 concptr name = _("未知", "unknown");
511 if (!kv && !rv && !gv && !bv) continue;
513 if (i < 16) name = color_names[i];
515 auto_dump_printf(_("# カラー '%s'\n", "# Color '%s'\n"), name);
516 auto_dump_printf("V:%d:0x%02X:0x%02X:0x%02X:0x%02X\n\n",
521 msg_print(_("カラーの設定をファイルに書き出しました。", "Dumped color redefinitions."));
526 prt(_("コマンド: カラーの設定を変更します", "Command: Modify colors"), 8, 0);
531 for (byte j = 0; j < 16; j++)
533 Term_putstr(j * 4, 20, -1, a, "###");
534 Term_putstr(j * 4, 22, -1, j, format("%3d", j));
537 name = ((a < 16) ? color_names[a] : _("未定義", "undefined"));
538 Term_putstr(5, 10, -1, TERM_WHITE,
539 format(_("カラー = %d, 名前 = %s", "Color = %d, Name = %s"), a, name));
540 Term_putstr(5, 12, -1, TERM_WHITE,
541 format("K = 0x%02x / R,G,B = 0x%02x,0x%02x,0x%02x",
542 angband_color_table[a][0],
543 angband_color_table[a][1],
544 angband_color_table[a][2],
545 angband_color_table[a][3]));
546 Term_putstr(0, 14, -1, TERM_WHITE,
547 _("コマンド (n/N/k/K/r/R/g/G/b/B): ", "Command (n/N/k/K/r/R/g/G/b/B): "));
549 if (i == ESCAPE) break;
551 if (i == 'n') a = (byte)(a + 1);
552 if (i == 'N') a = (byte)(a - 1);
553 if (i == 'k') angband_color_table[a][0] = (byte)(angband_color_table[a][0] + 1);
554 if (i == 'K') angband_color_table[a][0] = (byte)(angband_color_table[a][0] - 1);
555 if (i == 'r') angband_color_table[a][1] = (byte)(angband_color_table[a][1] + 1);
556 if (i == 'R') angband_color_table[a][1] = (byte)(angband_color_table[a][1] - 1);
557 if (i == 'g') angband_color_table[a][2] = (byte)(angband_color_table[a][2] + 1);
558 if (i == 'G') angband_color_table[a][2] = (byte)(angband_color_table[a][2] - 1);
559 if (i == 'b') angband_color_table[a][3] = (byte)(angband_color_table[a][3] + 1);
560 if (i == 'B') angband_color_table[a][3] = (byte)(angband_color_table[a][3] - 1);
562 Term_xtra(TERM_XTRA_REACT, 0);
579 * Note something in the message recall
581 void do_cmd_note(void)
585 if (!get_string(_("メモ: ", "Note: "), buf, 60)) return;
586 if (!buf[0] || (buf[0] == ' ')) return;
588 msg_format(_("メモ: %s", "Note: %s"), buf);
593 * Mention the current version
595 void do_cmd_version(void)
597 #if FAKE_VER_EXTRA > 0
598 msg_format(_("変愚蛮怒(Hengband) %d.%d.%d.%d", "You are playing Hengband %d.%d.%d.%d."),
599 FAKE_VER_MAJOR - 10, FAKE_VER_MINOR, FAKE_VER_PATCH, FAKE_VER_EXTRA);
601 msg_format(_("変愚蛮怒(Hengband) %d.%d.%d", "You are playing Hengband %d.%d.%d."),
602 FAKE_VER_MAJOR - 10, FAKE_VER_MINOR, FAKE_VER_PATCH);
608 * Note that "feeling" is set to zero unless some time has passed.
609 * Note that this is done when the level is GENERATED, not entered.
611 void do_cmd_feeling(player_type *creature_ptr)
613 if (creature_ptr->wild_mode) return;
615 if (creature_ptr->current_floor_ptr->inside_quest && !random_quest_number(creature_ptr, creature_ptr->current_floor_ptr->dun_level))
617 msg_print(_("典型的なクエストのダンジョンのようだ。", "Looks like a typical quest level."));
621 if (creature_ptr->town_num && !creature_ptr->current_floor_ptr->dun_level)
623 if (!strcmp(town_info[creature_ptr->town_num].name, _("荒野", "wilderness")))
625 msg_print(_("何かありそうな荒野のようだ。", "Looks like a strange wilderness."));
629 msg_print(_("典型的な町のようだ。", "Looks like a typical town."));
633 if (!creature_ptr->current_floor_ptr->dun_level)
635 msg_print(_("典型的な荒野のようだ。", "Looks like a typical wilderness."));
639 if (creature_ptr->muta3 & MUT3_GOOD_LUCK)
640 msg_print(do_cmd_feeling_text_lucky[creature_ptr->feeling]);
641 else if (IS_ECHIZEN(creature_ptr))
642 msg_print(do_cmd_feeling_text_combat[creature_ptr->feeling]);
644 msg_print(do_cmd_feeling_text[creature_ptr->feeling]);
649 * todo 引数と戻り値について追記求む
650 * Build a list of monster indexes in the given group.
652 * mode & 0x01 : check for non-empty group
653 * mode & 0x02 : visual operation only
655 * @param creature_ptr プレーヤーへの参照ポインタ
657 * @param mon_idx[] ???
659 * @return The number of monsters in the group
661 static IDX collect_monsters(player_type *creature_ptr, IDX grp_cur, IDX mon_idx[], BIT_FLAGS8 mode)
663 concptr group_char = monster_group_char[grp_cur];
664 bool grp_unique = (monster_group_char[grp_cur] == (char *)-1L);
665 bool grp_riding = (monster_group_char[grp_cur] == (char *)-2L);
666 bool grp_wanted = (monster_group_char[grp_cur] == (char *)-3L);
667 bool grp_amberite = (monster_group_char[grp_cur] == (char *)-4L);
670 for (IDX i = 0; i < max_r_idx; i++)
672 monster_race *r_ptr = &r_info[i];
673 if (!r_ptr->name) continue;
674 if (!(mode & 0x02) && !cheat_know && !r_ptr->r_sights) continue;
678 if (!(r_ptr->flags1 & RF1_UNIQUE)) continue;
682 if (!(r_ptr->flags7 & RF7_RIDING)) continue;
687 for (int j = 0; j < MAX_BOUNTY; j++)
689 if (current_world_ptr->bounty_r_idx[j] == i || current_world_ptr->bounty_r_idx[j] - 10000 == i ||
690 (creature_ptr->today_mon && creature_ptr->today_mon == i))
697 if (!wanted) continue;
699 else if (grp_amberite)
701 if (!(r_ptr->flags3 & RF3_AMBERITE)) continue;
705 if (!my_strchr(group_char, r_ptr->d_char)) continue;
708 mon_idx[mon_cnt++] = i;
709 if (mode & 0x01) break;
712 mon_idx[mon_cnt] = -1;
714 ang_sort(mon_idx, &dummy_why, mon_cnt, ang_sort_comp_monster_level, ang_sort_swap_hook);
720 * Build a list of object indexes in the given group. Return the number
721 * of objects in the group.
723 * mode & 0x01 : check for non-empty group
724 * mode & 0x02 : visual operation only
726 static KIND_OBJECT_IDX collect_objects(int grp_cur, KIND_OBJECT_IDX object_idx[], BIT_FLAGS8 mode)
728 KIND_OBJECT_IDX object_cnt = 0;
729 byte group_tval = object_group_tval[grp_cur];
730 for (KIND_OBJECT_IDX i = 0; i < max_k_idx; i++)
732 object_kind *k_ptr = &k_info[i];
733 if (!k_ptr->name) continue;
737 if (!current_world_ptr->wizard)
739 if (!k_ptr->flavor) continue;
740 if (!k_ptr->aware) continue;
744 for (int j = 0; j < 4; j++)
745 k += k_ptr->chance[j];
749 if (TV_LIFE_BOOK == group_tval)
751 if (TV_LIFE_BOOK <= k_ptr->tval && k_ptr->tval <= TV_HEX_BOOK)
753 object_idx[object_cnt++] = i;
758 else if (k_ptr->tval == group_tval)
760 object_idx[object_cnt++] = i;
765 if (mode & 0x01) break;
768 object_idx[object_cnt] = -1;
774 * Description of each feature group.
776 static concptr feature_group_text[] =
784 * Build a list of feature indexes in the given group. Return the number
785 * of features in the group.
787 * mode & 0x01 : check for non-empty group
789 static FEAT_IDX collect_features(FEAT_IDX *feat_idx, BIT_FLAGS8 mode)
791 FEAT_IDX feat_cnt = 0;
792 for (FEAT_IDX i = 0; i < max_f_idx; i++)
794 feature_type *f_ptr = &f_info[i];
795 if (!f_ptr->name) continue;
796 if (f_ptr->mimic != i) continue;
798 feat_idx[feat_cnt++] = i;
799 if (mode & 0x01) break;
802 feat_idx[feat_cnt] = -1;
808 * Hack -- load a screen dump from a file
810 void do_cmd_load_screen(void)
818 Term_get_size(&wid, &hgt);
819 path_build(buf, sizeof(buf), ANGBAND_DIR_USER, "dump.txt");
820 fff = my_fopen(buf, "r");
823 msg_format(_("%s を開くことができませんでした。", "Failed to open %s."), buf);
830 for (TERM_LEN y = 0; okay; y++)
832 if (!fgets(buf, 1024, fff)) okay = FALSE;
834 if (buf[0] == '\n' || buf[0] == '\0') break;
835 if (y >= hgt) continue;
837 for (TERM_LEN x = 0; x < wid - 1; x++)
839 if (buf[x] == '\n' || buf[x] == '\0') break;
841 Term_draw(x, y, TERM_WHITE, buf[x]);
845 for (TERM_LEN y = 0; okay; y++)
847 if (!fgets(buf, 1024, fff)) okay = FALSE;
849 if (buf[0] == '\n' || buf[0] == '\0') break;
850 if (y >= hgt) continue;
852 for (TERM_LEN x = 0; x < wid - 1; x++)
854 if (buf[x] == '\n' || buf[x] == '\0') break;
856 (void)(Term_what(x, y, &a, &c));
857 for (int i = 0; i < 16; i++)
859 if (hack[i] == buf[x]) a = (byte)i;
862 Term_draw(x, y, a, c);
867 prt(_("ファイルに書き出された画面(記念撮影)をロードしました。", "Screen dump loaded."), 0, 0);
873 // todo なぜこんな中途半端なところに? defineも…
874 concptr inven_res_label = _(" 酸電火冷毒光闇破轟獄因沌劣 盲怖乱痺透命感消復浮",
875 " AcElFiCoPoLiDkShSoNtNxCaDi BlFeCfFaSeHlEpSdRgLv");
877 #define IM_FLAG_STR _("*", "* ")
878 #define HAS_FLAG_STR _("+", "+ ")
879 #define NO_FLAG_STR _("・", ". ")
881 #define print_im_or_res_flag(IM, RES) \
883 fputs(have_flag(flgs, (IM)) ? IM_FLAG_STR : \
884 (have_flag(flgs, (RES)) ? HAS_FLAG_STR : NO_FLAG_STR), fff); \
887 #define print_flag(TR) \
889 fputs(have_flag(flgs, (TR)) ? HAS_FLAG_STR : NO_FLAG_STR, fff); \
893 static void do_cmd_knowledge_inven_aux(player_type *creature_ptr, FILE *fff, object_type *o_ptr, int *j, OBJECT_TYPE_VALUE tval, char *where)
895 GAME_TEXT o_name[MAX_NLEN];
896 BIT_FLAGS flgs[TR_FLAG_SIZE];
897 if (!o_ptr->k_idx) return;
898 if (o_ptr->tval != tval) return;
899 if (!object_is_known(o_ptr)) return;
901 bool is_special_item_type = (object_is_wearable(o_ptr) && object_is_ego(o_ptr))
902 || ((tval == TV_AMULET) && (o_ptr->sval == SV_AMULET_RESISTANCE))
903 || ((tval == TV_RING) && (o_ptr->sval == SV_RING_LORDLY))
904 || ((tval == TV_SHIELD) && (o_ptr->sval == SV_DRAGON_SHIELD))
905 || ((tval == TV_HELM) && (o_ptr->sval == SV_DRAGON_HELM))
906 || ((tval == TV_GLOVES) && (o_ptr->sval == SV_SET_OF_DRAGON_GLOVES))
907 || ((tval == TV_BOOTS) && (o_ptr->sval == SV_PAIR_OF_DRAGON_GREAVE))
908 || object_is_artifact(o_ptr);
909 if (!is_special_item_type)
915 object_desc(creature_ptr, o_name, o_ptr, OD_NAME_ONLY);
916 while (o_name[i] && (i < 26))
919 if (iskanji(o_name[i])) i++;
928 o_name[i] = ' '; i++;
934 fprintf(fff, "%s %s", where, o_name);
936 if (!OBJECT_IS_FULL_KNOWN(o_ptr))
938 fputs(_("-------不明--------------- -------不明---------\n",
939 "-------unknown------------ -------unknown------\n"), fff);
943 object_flags_known(o_ptr, flgs);
945 print_im_or_res_flag(TR_IM_ACID, TR_RES_ACID);
946 print_im_or_res_flag(TR_IM_ELEC, TR_RES_ELEC);
947 print_im_or_res_flag(TR_IM_FIRE, TR_RES_FIRE);
948 print_im_or_res_flag(TR_IM_COLD, TR_RES_COLD);
949 print_flag(TR_RES_POIS);
950 print_flag(TR_RES_LITE);
951 print_flag(TR_RES_DARK);
952 print_flag(TR_RES_SHARDS);
953 print_flag(TR_RES_SOUND);
954 print_flag(TR_RES_NETHER);
955 print_flag(TR_RES_NEXUS);
956 print_flag(TR_RES_CHAOS);
957 print_flag(TR_RES_DISEN);
961 print_flag(TR_RES_BLIND);
962 print_flag(TR_RES_FEAR);
963 print_flag(TR_RES_CONF);
964 print_flag(TR_FREE_ACT);
965 print_flag(TR_SEE_INVIS);
966 print_flag(TR_HOLD_EXP);
967 print_flag(TR_TELEPATHY);
968 print_flag(TR_SLOW_DIGEST);
969 print_flag(TR_REGEN);
970 print_flag(TR_LEVITATION);
979 fprintf(fff, "%s\n", inven_res_label);
984 * Display *ID* ed weapons/armors's resistances
986 static void do_cmd_knowledge_inven(player_type *creature_ptr)
989 GAME_TEXT file_name[1024];
990 store_type *store_ptr;
991 OBJECT_TYPE_VALUE tval;
995 fff = my_fopen_temp(file_name, 1024);
998 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
1003 fprintf(fff, "%s\n", inven_res_label);
1004 for (tval = TV_WEARABLE_BEGIN; tval <= TV_WEARABLE_END; tval++)
1008 for (; j < 9; j++) fputc('\n', fff);
1010 fprintf(fff, "%s\n", inven_res_label);
1013 strcpy(where, _("装", "E "));
1014 for (int i = INVEN_RARM; i < INVEN_TOTAL; i++)
1016 do_cmd_knowledge_inven_aux(creature_ptr, fff, &creature_ptr->inventory_list[i], &j, tval, where);
1019 strcpy(where, _("持", "I "));
1020 for (int i = 0; i < INVEN_PACK; i++)
1022 do_cmd_knowledge_inven_aux(creature_ptr, fff, &creature_ptr->inventory_list[i], &j, tval, where);
1025 store_ptr = &town_info[1].store[STORE_HOME];
1026 strcpy(where, _("家", "H "));
1027 for (int i = 0; i < store_ptr->stock_num; i++)
1029 do_cmd_knowledge_inven_aux(creature_ptr, fff, &store_ptr->stock[i], &j, tval, where);
1034 (void)show_file(creature_ptr, TRUE, file_name, _("*鑑定*済み武器/防具の耐性リスト", "Resistances of *identified* equipment"), 0, 0);
1039 void do_cmd_save_screen_html_aux(char *filename, int message)
1047 concptr html_head[] = {
1048 "<html>\n<body text=\"#ffffff\" bgcolor=\"#000000\">\n",
1052 concptr html_foot[] = {
1054 "</body>\n</html>\n",
1059 Term_get_size(&wid, &hgt);
1060 FILE_TYPE(FILE_TYPE_TEXT);
1062 fff = my_fopen(filename, "w");
1067 msg_format(_("ファイル %s を開けませんでした。", "Failed to open file %s."), filename);
1074 if (message) screen_save();
1077 path_build(buf, sizeof(buf), ANGBAND_DIR_USER, "htmldump.prf");
1079 tmpfff = my_fopen(buf, "r");
1082 for (int i = 0; html_head[i]; i++)
1083 fputs(html_head[i], fff);
1087 bool is_first_line = TRUE;
1088 while (!my_fgets(tmpfff, buf, sizeof(buf)))
1092 if (strncmp(buf, tags[0], strlen(tags[0])) == 0)
1093 is_first_line = FALSE;
1097 if (strncmp(buf, tags[1], strlen(tags[1])) == 0)
1099 fprintf(fff, "%s\n", buf);
1104 for (TERM_LEN y = 0; y < hgt; y++)
1106 if (y != 0) fprintf(fff, "\n");
1108 TERM_COLOR a = 0, old_a = 0;
1110 for (TERM_LEN x = 0; x < wid - 1; x++)
1113 (void)(Term_what(x, y, &a, &c));
1116 case '&': cc = "&"; break;
1117 case '<': cc = "<"; break;
1118 case '>': cc = ">"; break;
1120 case 0x1f: c = '.'; break;
1121 case 0x7f: c = (a == 0x09) ? '%' : '#'; break;
1126 if ((y == 0 && x == 0) || a != old_a)
1128 int rv = angband_color_table[a][1];
1129 int gv = angband_color_table[a][2];
1130 int bv = angband_color_table[a][3];
1131 fprintf(fff, "%s<font color=\"#%02x%02x%02x\">",
1132 ((y == 0 && x == 0) ? "" : "</font>"), rv, gv, bv);
1137 fprintf(fff, "%s", cc);
1139 fprintf(fff, "%c", c);
1143 fprintf(fff, "</font>");
1146 for (int i = 0; html_foot[i]; i++)
1147 fputs(html_foot[i], fff);
1152 bool is_first_line = TRUE;
1153 while (!my_fgets(tmpfff, buf, sizeof(buf)))
1157 if (strncmp(buf, tags[2], strlen(tags[2])) == 0)
1158 is_first_line = FALSE;
1162 if (strncmp(buf, tags[3], strlen(tags[3])) == 0)
1164 fprintf(fff, "%s\n", buf);
1175 msg_print(_("画面(記念撮影)をファイルに書き出しました。", "Screen dump saved."));
1185 * Hack -- save a screen dump to a file
1187 static void do_cmd_save_screen_html(void)
1189 char buf[1024], tmp[256] = "screen.html";
1191 if (!get_string(_("ファイル名: ", "File name: "), tmp, 80))
1193 path_build(buf, sizeof(buf), ANGBAND_DIR_USER, tmp);
1197 do_cmd_save_screen_html_aux(buf, 1);
1202 * Redefinable "save_screen" action
1204 void(*screendump_aux)(void) = NULL;
1208 * Save a screen dump to a file
1209 * @param creature_ptr プレーヤーへの参照ポインタ
1212 void do_cmd_save_screen(player_type *creature_ptr)
1214 prt(_("記念撮影しますか? [(y)es/(h)tml/(n)o] ", "Save screen dump? [(y)es/(h)tml/(n)o] "), 0, 0);
1215 bool html_dump = FALSE;
1219 if (c == 'Y' || c == 'y')
1221 else if (c == 'H' || c == 'h')
1234 Term_get_size(&wid, &hgt);
1236 bool old_use_graphics = use_graphics;
1237 if (old_use_graphics)
1239 use_graphics = FALSE;
1240 reset_visuals(creature_ptr);
1241 creature_ptr->redraw |= (PR_WIPE | PR_BASIC | PR_EXTRA | PR_MAP | PR_EQUIPPY);
1242 handle_stuff(creature_ptr);
1247 do_cmd_save_screen_html();
1248 do_cmd_redraw(creature_ptr);
1250 else if (screendump_aux)
1252 (*screendump_aux)();
1258 SYMBOL_CODE c = ' ';
1261 path_build(buf, sizeof(buf), ANGBAND_DIR_USER, "dump.txt");
1262 FILE_TYPE(FILE_TYPE_TEXT);
1263 fff = my_fopen(buf, "w");
1266 msg_format(_("ファイル %s を開けませんでした。", "Failed to open file %s."), buf);
1272 for (y = 0; y < hgt; y++)
1274 for (x = 0; x < wid - 1; x++)
1276 (void)(Term_what(x, y, &a, &c));
1281 fprintf(fff, "%s\n", buf);
1285 for (y = 0; y < hgt; y++)
1287 for (x = 0; x < wid - 1; x++)
1289 (void)(Term_what(x, y, &a, &c));
1290 buf[x] = hack[a & 0x0F];
1294 fprintf(fff, "%s\n", buf);
1299 msg_print(_("画面(記念撮影)をファイルに書き出しました。", "Screen dump saved."));
1304 if (!old_use_graphics) return;
1306 use_graphics = TRUE;
1307 reset_visuals(creature_ptr);
1308 creature_ptr->redraw |= (PR_WIPE | PR_BASIC | PR_EXTRA | PR_MAP | PR_EQUIPPY);
1309 handle_stuff(creature_ptr);
1314 * todo okay = 既知のアーティファクト? と思われるが確証がない
1315 * 分かりやすい変数名へ変更求む&万が一未知である旨の配列なら負論理なのでゴソッと差し替えるべき
1316 * Check the status of "artifacts"
1317 * @param player_ptr プレーヤーへの参照ポインタ
1320 static void do_cmd_knowledge_artifacts(player_type *player_ptr)
1323 GAME_TEXT file_name[1024];
1324 fff = my_fopen_temp(file_name, 1024);
1327 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
1333 C_MAKE(who, max_a_idx, ARTIFACT_IDX);
1335 C_MAKE(okay, max_a_idx, bool);
1337 for (ARTIFACT_IDX k = 0; k < max_a_idx; k++)
1339 artifact_type *a_ptr = &a_info[k];
1341 if (!a_ptr->name) continue;
1342 if (!a_ptr->cur_num) continue;
1347 for (POSITION y = 0; y < player_ptr->current_floor_ptr->height; y++)
1349 for (POSITION x = 0; x < player_ptr->current_floor_ptr->width; x++)
1351 grid_type *g_ptr = &player_ptr->current_floor_ptr->grid_array[y][x];
1352 OBJECT_IDX this_o_idx, next_o_idx = 0;
1353 for (this_o_idx = g_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx)
1356 o_ptr = &player_ptr->current_floor_ptr->o_list[this_o_idx];
1357 next_o_idx = o_ptr->next_o_idx;
1358 if (!object_is_fixed_artifact(o_ptr)) continue;
1359 if (object_is_known(o_ptr)) continue;
1361 okay[o_ptr->name1] = FALSE;
1366 for (ARTIFACT_IDX i = 0; i < INVEN_TOTAL; i++)
1368 object_type *o_ptr = &player_ptr->inventory_list[i];
1369 if (!o_ptr->k_idx) continue;
1370 if (!object_is_fixed_artifact(o_ptr)) continue;
1371 if (object_is_known(o_ptr)) continue;
1373 okay[o_ptr->name1] = FALSE;
1377 for (ARTIFACT_IDX k = 0; k < max_a_idx; k++)
1379 if (okay[k]) who[n++] = k;
1383 ang_sort(who, &why, n, ang_sort_art_comp, ang_sort_art_swap);
1384 for (ARTIFACT_IDX k = 0; k < n; k++)
1386 artifact_type *a_ptr = &a_info[who[k]];
1387 GAME_TEXT base_name[MAX_NLEN];
1388 strcpy(base_name, _("未知の伝説のアイテム", "Unknown Artifact"));
1389 ARTIFACT_IDX z = lookup_kind(a_ptr->tval, a_ptr->sval);
1395 object_prep(q_ptr, z);
1396 q_ptr->name1 = (byte)who[k];
1397 q_ptr->ident |= IDENT_STORE;
1398 object_desc(player_ptr, base_name, q_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY));
1401 fprintf(fff, _(" %s\n", " The %s\n"), base_name);
1404 C_KILL(who, max_a_idx, ARTIFACT_IDX);
1405 C_KILL(okay, max_a_idx, bool);
1407 (void)show_file(player_ptr, TRUE, file_name, _("既知の伝説のアイテム", "Artifacts Seen"), 0, 0);
1413 * Display known uniques
1414 * With "XTRA HACK UNIQHIST" (Originally from XAngband)
1416 static void do_cmd_knowledge_uniques(player_type *creature_ptr)
1420 GAME_TEXT file_name[1024];
1422 int n_alive_surface = 0;
1423 int n_alive_over100 = 0;
1424 int n_alive_total = 0;
1426 for (IDX i = 0; i < 10; i++)
1430 fff = my_fopen_temp(file_name, 1024);
1433 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
1438 C_MAKE(who, max_r_idx, MONRACE_IDX);
1440 for (IDX i = 1; i < max_r_idx; i++)
1442 monster_race *r_ptr = &r_info[i];
1443 if (!r_ptr->name) continue;
1444 if (!(r_ptr->flags1 & RF1_UNIQUE)) continue;
1445 if (!cheat_know && !r_ptr->r_sights) continue;
1446 if (!r_ptr->rarity || ((r_ptr->rarity > 100) && !(r_ptr->flags1 & RF1_QUESTOR))) continue;
1447 if (r_ptr->max_num == 0) continue;
1451 int lev = (r_ptr->level - 1) / 10;
1455 if (max_lev < lev) max_lev = lev;
1466 ang_sort(who, &why, n, ang_sort_comp_hook, ang_sort_swap_hook);
1467 if (n_alive_surface)
1469 fprintf(fff, _(" 地上 生存: %3d体\n", " Surface alive: %3d\n"), n_alive_surface);
1470 n_alive_total += n_alive_surface;
1473 for (IDX i = 0; i <= max_lev; i++)
1475 fprintf(fff, _("%3d-%3d階 生存: %3d体\n", "Level %3d-%3d alive: %3d\n"), 1 + i * 10, 10 + i * 10, n_alive[i]);
1476 n_alive_total += n_alive[i];
1479 if (n_alive_over100)
1481 fprintf(fff, _("101- 階 生存: %3d体\n", "Level 101- alive: %3d\n"), n_alive_over100);
1482 n_alive_total += n_alive_over100;
1487 fputs(_("--------- -----------\n", "------------- ----------\n"), fff);
1488 fprintf(fff, _(" 合計 生存: %3d体\n\n", " Total alive: %3d\n\n"), n_alive_total);
1492 fputs(_("現在は既知の生存ユニークはいません。\n", "No known uniques alive.\n"), fff);
1495 for (int k = 0; k < n; k++)
1497 monster_race *r_ptr = &r_info[who[k]];
1498 fprintf(fff, _(" %s (レベル%d)\n", " %s (level %d)\n"), r_name + r_ptr->name, (int)r_ptr->level);
1501 C_KILL(who, max_r_idx, s16b);
1503 (void)show_file(creature_ptr, TRUE, file_name, _("まだ生きているユニーク・モンスター", "Alive Uniques"), 0, 0);
1509 * Display weapon-exp
1511 static void do_cmd_knowledge_weapon_exp(player_type *creature_ptr)
1514 GAME_TEXT file_name[1024];
1515 fff = my_fopen_temp(file_name, 1024);
1518 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
1523 for (int i = 0; i < 5; i++)
1525 for (int num = 0; num < 64; num++)
1529 for (KIND_OBJECT_IDX j = 0; j < max_k_idx; j++)
1531 object_kind *k_ptr = &k_info[j];
1533 if ((k_ptr->tval != TV_SWORD - i) || (k_ptr->sval != num)) continue;
1534 if ((k_ptr->tval == TV_BOW) && (k_ptr->sval == SV_CRIMSON || k_ptr->sval == SV_HARP)) continue;
1536 weapon_exp = creature_ptr->weapon_exp[4 - i][num];
1538 fprintf(fff, "%-25s ", tmp);
1539 if (weapon_exp >= s_info[creature_ptr->pclass].w_max[4 - i][num]) fprintf(fff, "!");
1540 else fprintf(fff, " ");
1541 fprintf(fff, "%s", exp_level_str[weapon_exp_level(weapon_exp)]);
1542 if (cheat_xtra) fprintf(fff, " %d", weapon_exp);
1550 (void)show_file(creature_ptr, TRUE, file_name, _("武器の経験値", "Weapon Proficiency"), 0, 0);
1556 * @brief 魔法の経験値を表示するコマンドのメインルーチン
1560 static void do_cmd_knowledge_spell_exp(player_type *creature_ptr)
1563 GAME_TEXT file_name[1024];
1564 fff = my_fopen_temp(file_name, 1024);
1567 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
1572 if (creature_ptr->realm1 != REALM_NONE)
1574 fprintf(fff, _("%sの魔法書\n", "%s Spellbook\n"), realm_names[creature_ptr->realm1]);
1575 for (SPELL_IDX i = 0; i < 32; i++)
1577 const magic_type *s_ptr;
1578 if (!is_magic(creature_ptr->realm1))
1580 s_ptr = &technic_info[creature_ptr->realm1 - MIN_TECHNIC][i];
1584 s_ptr = &mp_ptr->info[creature_ptr->realm1 - 1][i];
1587 if (s_ptr->slevel >= 99) continue;
1588 SUB_EXP spell_exp = creature_ptr->spell_exp[i];
1589 int exp_level = spell_exp_level(spell_exp);
1590 fprintf(fff, "%-25s ", exe_spell(creature_ptr, creature_ptr->realm1, i, SPELL_NAME));
1591 if (creature_ptr->realm1 == REALM_HISSATSU)
1592 fprintf(fff, "[--]");
1595 if (exp_level >= EXP_LEVEL_MASTER) fprintf(fff, "!");
1596 else fprintf(fff, " ");
1597 fprintf(fff, "%s", exp_level_str[exp_level]);
1600 if (cheat_xtra) fprintf(fff, " %d", spell_exp);
1605 if (creature_ptr->realm2 != REALM_NONE)
1607 fprintf(fff, _("%sの魔法書\n", "\n%s Spellbook\n"), realm_names[creature_ptr->realm2]);
1608 for (SPELL_IDX i = 0; i < 32; i++)
1610 const magic_type *s_ptr;
1611 if (!is_magic(creature_ptr->realm1))
1613 s_ptr = &technic_info[creature_ptr->realm2 - MIN_TECHNIC][i];
1617 s_ptr = &mp_ptr->info[creature_ptr->realm2 - 1][i];
1620 if (s_ptr->slevel >= 99) continue;
1622 SUB_EXP spell_exp = creature_ptr->spell_exp[i + 32];
1623 int exp_level = spell_exp_level(spell_exp);
1624 fprintf(fff, "%-25s ", exe_spell(creature_ptr, creature_ptr->realm2, i, SPELL_NAME));
1625 if (exp_level >= EXP_LEVEL_EXPERT) fprintf(fff, "!");
1626 else fprintf(fff, " ");
1627 fprintf(fff, "%s", exp_level_str[exp_level]);
1628 if (cheat_xtra) fprintf(fff, " %d", spell_exp);
1634 (void)show_file(creature_ptr, TRUE, file_name, _("魔法の経験値", "Spell Proficiency"), 0, 0);
1640 * @brief スキル情報を表示するコマンドのメインルーチン /
1644 static void do_cmd_knowledge_skill_exp(player_type *creature_ptr)
1646 char skill_name[GINOU_TEMPMAX][20] =
1648 _("マーシャルアーツ", "Martial Arts "),
1649 _("二刀流 ", "Dual Wielding "),
1650 _("乗馬 ", "Riding "),
1655 char file_name[1024];
1656 fff = my_fopen_temp(file_name, 1024);
1659 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
1664 for (int i = 0; i < GINOU_TEMPMAX; i++)
1666 int skill_exp = creature_ptr->skill_exp[i];
1667 fprintf(fff, "%-20s ", skill_name[i]);
1668 if (skill_exp >= s_info[creature_ptr->pclass].s_max[i]) fprintf(fff, "!");
1669 else fprintf(fff, " ");
1670 fprintf(fff, "%s", exp_level_str[(i == GINOU_RIDING) ? riding_exp_level(skill_exp) : weapon_exp_level(skill_exp)]);
1671 if (cheat_xtra) fprintf(fff, " %d", skill_exp);
1676 (void)show_file(creature_ptr, TRUE, file_name, _("技能の経験値", "Miscellaneous Proficiency"), 0, 0);
1682 * @brief 現在のペットを表示するコマンドのメインルーチン /
1683 * Display current pets
1684 * @param creature_ptr プレーヤーへの参照ポインタ
1687 static void do_cmd_knowledge_pets(player_type *creature_ptr)
1689 GAME_TEXT file_name[1024];
1691 fff = my_fopen_temp(file_name, 1024);
1694 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
1699 monster_type *m_ptr;
1700 GAME_TEXT pet_name[MAX_NLEN];
1702 for (int i = creature_ptr->current_floor_ptr->m_max - 1; i >= 1; i--)
1704 m_ptr = &creature_ptr->current_floor_ptr->m_list[i];
1705 if (!monster_is_valid(m_ptr)) continue;
1706 if (!is_pet(m_ptr)) continue;
1709 monster_desc(creature_ptr, pet_name, m_ptr, MD_ASSUME_VISIBLE | MD_INDEF_VISIBLE);
1710 fprintf(fff, "%s (%s)\n", pet_name, look_mon_desc(m_ptr, 0x00));
1713 int show_upkeep = calculate_upkeep(creature_ptr);
1715 fprintf(fff, "----------------------------------------------\n");
1717 fprintf(fff, " 合計: %d 体のペット\n", t_friends);
1719 fprintf(fff, " Total: %d pet%s.\n", t_friends, (t_friends == 1 ? "" : "s"));
1721 fprintf(fff, _(" 維持コスト: %d%% MP\n", " Upkeep: %d%% mana.\n"), show_upkeep);
1724 (void)show_file(creature_ptr, TRUE, file_name, _("現在のペット", "Current Pets"), 0, 0);
1730 * @brief 現在のペットを表示するコマンドのメインルーチン /
1731 * @param creature_ptr プレーヤーへの参照ポインタ
1734 * @note the player ghosts are ignored.
1736 static void do_cmd_knowledge_kill_count(player_type *creature_ptr)
1739 GAME_TEXT file_name[1024];
1740 fff = my_fopen_temp(file_name, 1024);
1743 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
1749 C_MAKE(who, max_r_idx, MONRACE_IDX);
1751 for (int kk = 1; kk < max_r_idx; kk++)
1753 monster_race *r_ptr = &r_info[kk];
1755 if (r_ptr->flags1 & (RF1_UNIQUE))
1757 bool dead = (r_ptr->max_num == 0);
1766 MONSTER_NUMBER this_monster = r_ptr->r_pkills;
1768 if (this_monster > 0)
1770 total += this_monster;
1776 fprintf(fff, _("あなたはまだ敵を倒していない。\n\n", "You have defeated no enemies yet.\n\n"));
1779 fprintf(fff, "あなたは%ld体の敵を倒している。\n\n", (long int)total);
1781 fprintf(fff, "You have defeated %ld %s.\n\n", (long int)total, (total == 1) ? "enemy" : "enemies");
1786 for (MONRACE_IDX i = 1; i < max_r_idx; i++)
1788 monster_race *r_ptr = &r_info[i];
1789 if (r_ptr->name) who[n++] = i;
1793 ang_sort(who, &why, n, ang_sort_comp_hook, ang_sort_swap_hook);
1794 for (int k = 0; k < n; k++)
1796 monster_race *r_ptr = &r_info[who[k]];
1797 if (r_ptr->flags1 & (RF1_UNIQUE))
1799 bool dead = (r_ptr->max_num == 0);
1802 fprintf(fff, " %s\n", (r_name + r_ptr->name));
1809 MONSTER_NUMBER this_monster = r_ptr->r_pkills;
1810 if (this_monster <= 0) continue;
1813 if (my_strchr("pt", r_ptr->d_char))
1814 fprintf(fff, " %3d 人の %s\n", (int)this_monster, r_name + r_ptr->name);
1816 fprintf(fff, " %3d 体の %s\n", (int)this_monster, r_name + r_ptr->name);
1818 if (this_monster < 2)
1820 if (my_strstr(r_name + r_ptr->name, "coins"))
1822 fprintf(fff, " 1 pile of %s\n", (r_name + r_ptr->name));
1826 fprintf(fff, " 1 %s\n", (r_name + r_ptr->name));
1832 strcpy(ToPlural, (r_name + r_ptr->name));
1833 plural_aux(ToPlural);
1834 fprintf(fff, " %d %s\n", this_monster, ToPlural);
1837 total += this_monster;
1840 fprintf(fff, "----------------------------------------------\n");
1842 fprintf(fff, " 合計: %lu 体を倒した。\n", (unsigned long int)total);
1844 fprintf(fff, " Total: %lu creature%s killed.\n", (unsigned long int)total, (total == 1 ? "" : "s"));
1847 C_KILL(who, max_r_idx, s16b);
1849 (void)show_file(creature_ptr, TRUE, file_name, _("倒した敵の数", "Kill Count"), 0, 0);
1855 * @brief モンスター情報リスト中のグループを表示する /
1856 * Display the object groups.
1860 * @param per_page リストの表示行
1861 * @param grp_idx グループのID配列
1862 * @param group_text グループ名の文字列配列
1863 * @param grp_cur 現在の選択ID
1864 * @param grp_top 現在の選択リスト最上部ID
1867 static void display_group_list(int col, int row, int wid, int per_page, IDX grp_idx[], concptr group_text[], int grp_cur, int grp_top)
1869 for (int i = 0; i < per_page && (grp_idx[i] >= 0); i++)
1871 int grp = grp_idx[grp_top + i];
1872 TERM_COLOR attr = (grp_top + i == grp_cur) ? TERM_L_BLUE : TERM_WHITE;
1873 Term_erase(col, row + i, wid);
1874 c_put_str(attr, group_text[grp], row + i, col);
1880 * Move the cursor in a browser window
1882 static void browser_cursor(char ch, int *column, IDX *grp_cur, int grp_cnt, IDX *list_cur, int list_cnt)
1887 IDX list = *list_cur;
1893 d = get_keymap_dir(ch);
1897 if ((ddx[d] > 0) && ddy[d])
1901 Term_get_size(&wid, &hgt);
1902 browser_rows = hgt - 8;
1906 grp += ddy[d] * (browser_rows - 1);
1907 if (grp >= grp_cnt) grp = grp_cnt - 1;
1908 if (grp < 0) grp = 0;
1909 if (grp != old_grp) list = 0;
1913 list += ddy[d] * browser_rows;
1914 if (list >= list_cnt) list = list_cnt - 1;
1915 if (list < 0) list = 0;
1926 if (col < 0) col = 0;
1927 if (col > 1) col = 1;
1937 if (grp >= grp_cnt) grp = grp_cnt - 1;
1938 if (grp < 0) grp = 0;
1939 if (grp != old_grp) list = 0;
1943 list += (IDX)ddy[d];
1944 if (list >= list_cnt) list = list_cnt - 1;
1945 if (list < 0) list = 0;
1956 static void display_visual_list(int col, int row, int height, int width, TERM_COLOR attr_top, byte char_left)
1958 for (int i = 0; i < height; i++)
1960 Term_erase(col, row + i, width);
1963 if (use_bigtile) width /= 2;
1965 for (int i = 0; i < height; i++)
1967 for (int j = 0; j < width; j++)
1969 TERM_LEN x = col + j;
1970 TERM_LEN y = row + i;
1971 if (use_bigtile) x += j;
1973 TERM_COLOR ia = attr_top + i;
1974 SYMBOL_CODE ic = char_left + j;
1975 if (ia > 0x7f || ic > 0xff || ic < ' ' ||
1976 (!use_graphics && ic > 0x7f))
1981 if (c & 0x80) a |= 0x80;
1983 Term_queue_bigchar(x, y, a, c, 0, 0);
1990 * Place the cursor at the collect position for visual mode
1992 static void place_visual_list_cursor(TERM_LEN col, TERM_LEN row, TERM_COLOR a, byte c, TERM_COLOR attr_top, byte char_left)
1994 int i = (a & 0x7f) - attr_top;
1995 int j = c - char_left;
1997 TERM_LEN x = col + j;
1998 TERM_LEN y = row + i;
1999 if (use_bigtile) x += j;
2006 * Do visual mode command -- Change symbols
2008 static bool visual_mode_command(char ch, bool *visual_list_ptr,
2009 int height, int width,
2010 TERM_COLOR *attr_top_ptr, byte *char_left_ptr,
2011 TERM_COLOR *cur_attr_ptr, SYMBOL_CODE *cur_char_ptr, bool *need_redraw)
2013 static TERM_COLOR attr_old = 0;
2014 static SYMBOL_CODE char_old = 0;
2019 if (*visual_list_ptr)
2021 *cur_attr_ptr = attr_old;
2022 *cur_char_ptr = char_old;
2023 *visual_list_ptr = FALSE;
2032 if (*visual_list_ptr)
2034 *visual_list_ptr = FALSE;
2035 *need_redraw = TRUE;
2044 if (!*visual_list_ptr)
2046 *visual_list_ptr = TRUE;
2048 *attr_top_ptr = MAX(0, (*cur_attr_ptr & 0x7f) - 5);
2049 *char_left_ptr = MAX(0, *cur_char_ptr - 10);
2051 attr_old = *cur_attr_ptr;
2052 char_old = *cur_char_ptr;
2062 attr_idx = *cur_attr_ptr;
2063 char_idx = *cur_char_ptr;
2064 for (int i = 0; i < F_LIT_MAX; i++)
2066 attr_idx_feat[i] = 0;
2067 char_idx_feat[i] = 0;
2075 if (attr_idx || (!(char_idx & 0x80) && char_idx))
2077 *cur_attr_ptr = attr_idx;
2078 *attr_top_ptr = MAX(0, (*cur_attr_ptr & 0x7f) - 5);
2079 if (!*visual_list_ptr) *need_redraw = TRUE;
2085 *cur_char_ptr = char_idx;
2086 *char_left_ptr = MAX(0, *cur_char_ptr - 10);
2087 if (!*visual_list_ptr) *need_redraw = TRUE;
2093 if (*visual_list_ptr)
2096 int d = get_keymap_dir(ch);
2097 TERM_COLOR a = (*cur_attr_ptr & 0x7f);
2098 SYMBOL_CODE c = *cur_char_ptr;
2100 if (use_bigtile) eff_width = width / 2;
2101 else eff_width = width;
2103 if ((a == 0) && (ddy[d] < 0)) d = 0;
2104 if ((c == 0) && (ddx[d] < 0)) d = 0;
2105 if ((a == 0x7f) && (ddy[d] > 0)) d = 0;
2106 if ((c == 0xff) && (ddx[d] > 0)) d = 0;
2108 a += (TERM_COLOR)ddy[d];
2109 c += (SYMBOL_CODE)ddx[d];
2110 if (c & 0x80) a |= 0x80;
2114 if ((ddx[d] < 0) && *char_left_ptr > MAX(0, (int)c - 10)) (*char_left_ptr)--;
2115 if ((ddx[d] > 0) && *char_left_ptr + eff_width < MIN(0xff, (int)c + 10)) (*char_left_ptr)++;
2116 if ((ddy[d] < 0) && *attr_top_ptr > MAX(0, (int)(a & 0x7f) - 4)) (*attr_top_ptr)--;
2117 if ((ddy[d] > 0) && *attr_top_ptr + height < MIN(0x7f, (a & 0x7f) + 4)) (*attr_top_ptr)++;
2129 * Display the monsters in a group.
2131 static void display_monster_list(int col, int row, int per_page, s16b mon_idx[], int mon_cur, int mon_top, bool visual_only)
2134 for (i = 0; i < per_page && (mon_idx[mon_top + i] >= 0); i++)
2137 MONRACE_IDX r_idx = mon_idx[mon_top + i];
2138 monster_race *r_ptr = &r_info[r_idx];
2139 attr = ((i + mon_top == mon_cur) ? TERM_L_BLUE : TERM_WHITE);
2140 c_prt(attr, (r_name + r_ptr->name), row + i, col);
2143 c_prt(attr, format("%02x/%02x", r_ptr->x_attr, r_ptr->x_char), row + i, (current_world_ptr->wizard || visual_only) ? 56 : 61);
2146 if (current_world_ptr->wizard || visual_only)
2148 c_prt(attr, format("%d", r_idx), row + i, 62);
2151 Term_erase(69, row + i, 255);
2152 Term_queue_bigchar(use_bigtile ? 69 : 70, row + i, r_ptr->x_attr, r_ptr->x_char, 0, 0);
2155 if (!(r_ptr->flags1 & RF1_UNIQUE))
2156 put_str(format("%5d", r_ptr->r_pkills), row + i, 73);
2158 c_put_str((r_ptr->max_num == 0 ? TERM_L_DARK : TERM_WHITE),
2159 (r_ptr->max_num == 0 ? _("死亡", " dead") : _("生存", "alive")), row + i, 74);
2163 for (; i < per_page; i++)
2165 Term_erase(col, row + i, 255);
2171 * todo 引数の詳細について加筆求む
2172 * Display known monsters.
2173 * @param creature_ptr プレーヤーへの参照ポインタ
2174 * @param need_redraw 画面の再描画が必要な時TRUE
2175 * @param visual_only ???
2176 * @param direct_r_idx モンスターID
2179 void do_cmd_knowledge_monsters(player_type *creature_ptr, bool *need_redraw, bool visual_only, IDX direct_r_idx)
2182 Term_get_size(&wid, &hgt);
2184 C_MAKE(mon_idx, max_r_idx, MONRACE_IDX);
2190 bool visual_list = FALSE;
2191 TERM_COLOR attr_top = 0;
2194 int browser_rows = hgt - 8;
2195 if (direct_r_idx < 0)
2197 mode = visual_only ? 0x03 : 0x01;
2199 for (IDX i = 0; monster_group_text[i] != NULL; i++)
2201 len = strlen(monster_group_text[i]);
2202 if (len > max) max = len;
2204 if ((monster_group_char[i] == ((char *)-1L)) || collect_monsters(creature_ptr, i, mon_idx, mode))
2206 grp_idx[grp_cnt++] = i;
2214 mon_idx[0] = direct_r_idx;
2218 (void)visual_mode_command('v', &visual_list, browser_rows - 1, wid - (max + 3),
2219 &attr_top, &char_left, &r_info[direct_r_idx].x_attr, &r_info[direct_r_idx].x_char, need_redraw);
2222 grp_idx[grp_cnt] = -1;
2223 mode = visual_only ? 0x02 : 0x00;
2224 IDX old_grp_cur = -1;
2237 prt(format(_("%s - モンスター", "%s - monsters"), !visual_only ? _("知識", "Knowledge") : _("表示", "Visuals")), 2, 0);
2238 if (direct_r_idx < 0) prt(_("グループ", "Group"), 4, 0);
2239 prt(_("名前", "Name"), 4, max + 3);
2240 if (current_world_ptr->wizard || visual_only) prt("Idx", 4, 62);
2241 prt(_("文字", "Sym"), 4, 67);
2242 if (!visual_only) prt(_("殺害数", "Kills"), 4, 72);
2244 for (IDX i = 0; i < 78; i++)
2246 Term_putch(i, 5, TERM_WHITE, '=');
2249 if (direct_r_idx < 0)
2251 for (IDX i = 0; i < browser_rows; i++)
2253 Term_putch(max + 1, 6 + i, TERM_WHITE, '|');
2260 if (direct_r_idx < 0)
2262 if (grp_cur < grp_top) grp_top = grp_cur;
2263 if (grp_cur >= grp_top + browser_rows) grp_top = grp_cur - browser_rows + 1;
2265 display_group_list(0, 6, max, browser_rows, grp_idx, monster_group_text, grp_cur, grp_top);
2266 if (old_grp_cur != grp_cur)
2268 old_grp_cur = grp_cur;
2269 mon_cnt = collect_monsters(creature_ptr, grp_idx[grp_cur], mon_idx, mode);
2272 while (mon_cur < mon_top)
2273 mon_top = MAX(0, mon_top - browser_rows / 2);
2274 while (mon_cur >= mon_top + browser_rows)
2275 mon_top = MIN(mon_cnt - browser_rows, mon_top + browser_rows / 2);
2280 display_monster_list(max + 3, 6, browser_rows, mon_idx, mon_cur, mon_top, visual_only);
2285 display_monster_list(max + 3, 6, 1, mon_idx, mon_cur, mon_top, visual_only);
2286 display_visual_list(max + 3, 7, browser_rows - 1, wid - (max + 3), attr_top, char_left);
2289 prt(format(_("<方向>%s%s%s, ESC", "<dir>%s%s%s, ESC"),
2290 (!visual_list && !visual_only) ? _(", 'r'で思い出を見る", ", 'r' to recall") : "",
2291 visual_list ? _(", ENTERで決定", ", ENTER to accept") : _(", 'v'でシンボル変更", ", 'v' for visuals"),
2292 (attr_idx || char_idx) ? _(", 'c', 'p'でペースト", ", 'c', 'p' to paste") : _(", 'c'でコピー", ", 'c' to copy")),
2295 monster_race *r_ptr;
2296 r_ptr = &r_info[mon_idx[mon_cur]];
2300 if (mon_cnt) monster_race_track(creature_ptr, mon_idx[mon_cur]);
2301 handle_stuff(creature_ptr);
2306 place_visual_list_cursor(max + 3, 7, r_ptr->x_attr, r_ptr->x_char, attr_top, char_left);
2310 Term_gotoxy(0, 6 + (grp_cur - grp_top));
2314 Term_gotoxy(max + 3, 6 + (mon_cur - mon_top));
2318 if (visual_mode_command(ch, &visual_list, browser_rows - 1, wid - (max + 3), &attr_top, &char_left, &r_ptr->x_attr, &r_ptr->x_char, need_redraw))
2320 if (direct_r_idx >= 0)
2346 if (!visual_list && !visual_only && (mon_idx[mon_cur] > 0))
2348 screen_roff(creature_ptr, mon_idx[mon_cur], 0);
2360 browser_cursor(ch, &column, &grp_cur, grp_cnt, &mon_cur, mon_cnt);
2367 C_KILL(mon_idx, max_r_idx, MONRACE_IDX);
2372 * Display the objects in a group.
2374 static void display_object_list(int col, int row, int per_page, IDX object_idx[],
2375 int object_cur, int object_top, bool visual_only)
2378 for (i = 0; i < per_page && (object_idx[object_top + i] >= 0); i++)
2380 GAME_TEXT o_name[MAX_NLEN];
2383 object_kind *flavor_k_ptr;
2384 KIND_OBJECT_IDX k_idx = object_idx[object_top + i];
2385 object_kind *k_ptr = &k_info[k_idx];
2386 TERM_COLOR attr = ((k_ptr->aware || visual_only) ? TERM_WHITE : TERM_SLATE);
2387 byte cursor = ((k_ptr->aware || visual_only) ? TERM_L_BLUE : TERM_BLUE);
2388 if (!visual_only && k_ptr->flavor)
2390 flavor_k_ptr = &k_info[k_ptr->flavor];
2394 flavor_k_ptr = k_ptr;
2397 attr = ((i + object_top == object_cur) ? cursor : attr);
2398 if (!k_ptr->flavor || (!visual_only && k_ptr->aware))
2400 strip_name(o_name, k_idx);
2404 strcpy(o_name, k_name + flavor_k_ptr->flavor_name);
2407 c_prt(attr, o_name, row + i, col);
2410 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);
2413 if (current_world_ptr->wizard || visual_only)
2415 c_prt(attr, format("%d", k_idx), row + i, 70);
2418 a = flavor_k_ptr->x_attr;
2419 c = flavor_k_ptr->x_char;
2421 Term_queue_bigchar(use_bigtile ? 76 : 77, row + i, a, c, 0, 0);
2424 for (; i < per_page; i++)
2426 Term_erase(col, row + i, 255);
2432 * Describe fake object
2434 static void desc_obj_fake(player_type *creature_ptr, KIND_OBJECT_IDX k_idx)
2437 object_type object_type_body;
2438 o_ptr = &object_type_body;
2440 object_prep(o_ptr, k_idx);
2442 o_ptr->ident |= IDENT_KNOWN;
2443 handle_stuff(creature_ptr);
2445 if (screen_object(creature_ptr, o_ptr, SCROBJ_FAKE_OBJECT | SCROBJ_FORCE_DETAIL)) return;
2447 msg_print(_("特に変わったところはないようだ。", "You see nothing special."));
2453 * Display known objects
2455 void do_cmd_knowledge_objects(player_type *creature_ptr, bool *need_redraw, bool visual_only, IDX direct_k_idx)
2457 IDX object_old, object_top;
2460 OBJECT_IDX *object_idx;
2462 bool visual_list = FALSE;
2463 TERM_COLOR attr_top = 0;
2468 Term_get_size(&wid, &hgt);
2470 int browser_rows = hgt - 8;
2471 C_MAKE(object_idx, max_k_idx, KIND_OBJECT_IDX);
2476 if (direct_k_idx < 0)
2478 mode = visual_only ? 0x03 : 0x01;
2479 for (IDX i = 0; object_group_text[i] != NULL; i++)
2481 len = strlen(object_group_text[i]);
2482 if (len > max) max = len;
2484 if (collect_objects(i, object_idx, mode))
2486 grp_idx[grp_cnt++] = i;
2495 object_kind *k_ptr = &k_info[direct_k_idx];
2496 object_kind *flavor_k_ptr;
2498 if (!visual_only && k_ptr->flavor)
2500 flavor_k_ptr = &k_info[k_ptr->flavor];
2504 flavor_k_ptr = k_ptr;
2507 object_idx[0] = direct_k_idx;
2508 object_old = direct_k_idx;
2511 (void)visual_mode_command('v', &visual_list, browser_rows - 1, wid - (max + 3),
2512 &attr_top, &char_left, &flavor_k_ptr->x_attr, &flavor_k_ptr->x_char, need_redraw);
2515 grp_idx[grp_cnt] = -1;
2516 mode = visual_only ? 0x02 : 0x00;
2517 IDX old_grp_cur = -1;
2520 IDX object_cur = object_top = 0;
2526 object_kind *k_ptr, *flavor_k_ptr;
2533 prt(format("%s - アイテム", !visual_only ? "知識" : "表示"), 2, 0);
2534 if (direct_k_idx < 0) prt("グループ", 4, 0);
2535 prt("名前", 4, max + 3);
2536 if (current_world_ptr->wizard || visual_only) prt("Idx", 4, 70);
2539 prt(format("%s - objects", !visual_only ? "Knowledge" : "Visuals"), 2, 0);
2540 if (direct_k_idx < 0) prt("Group", 4, 0);
2541 prt("Name", 4, max + 3);
2542 if (current_world_ptr->wizard || visual_only) prt("Idx", 4, 70);
2546 for (IDX i = 0; i < 78; i++)
2548 Term_putch(i, 5, TERM_WHITE, '=');
2551 if (direct_k_idx < 0)
2553 for (IDX i = 0; i < browser_rows; i++)
2555 Term_putch(max + 1, 6 + i, TERM_WHITE, '|');
2562 if (direct_k_idx < 0)
2564 if (grp_cur < grp_top) grp_top = grp_cur;
2565 if (grp_cur >= grp_top + browser_rows) grp_top = grp_cur - browser_rows + 1;
2567 display_group_list(0, 6, max, browser_rows, grp_idx, object_group_text, grp_cur, grp_top);
2568 if (old_grp_cur != grp_cur)
2570 old_grp_cur = grp_cur;
2571 object_cnt = collect_objects(grp_idx[grp_cur], object_idx, mode);
2574 while (object_cur < object_top)
2575 object_top = MAX(0, object_top - browser_rows / 2);
2576 while (object_cur >= object_top + browser_rows)
2577 object_top = MIN(object_cnt - browser_rows, object_top + browser_rows / 2);
2582 display_object_list(max + 3, 6, browser_rows, object_idx, object_cur, object_top, visual_only);
2586 object_top = object_cur;
2587 display_object_list(max + 3, 6, 1, object_idx, object_cur, object_top, visual_only);
2588 display_visual_list(max + 3, 7, browser_rows - 1, wid - (max + 3), attr_top, char_left);
2591 k_ptr = &k_info[object_idx[object_cur]];
2593 if (!visual_only && k_ptr->flavor)
2595 flavor_k_ptr = &k_info[k_ptr->flavor];
2599 flavor_k_ptr = k_ptr;
2603 prt(format("<方向>%s%s%s, ESC",
2604 (!visual_list && !visual_only) ? ", 'r'で詳細を見る" : "",
2605 visual_list ? ", ENTERで決定" : ", 'v'でシンボル変更",
2606 (attr_idx || char_idx) ? ", 'c', 'p'でペースト" : ", 'c'でコピー"),
2609 prt(format("<dir>%s%s%s, ESC",
2610 (!visual_list && !visual_only) ? ", 'r' to recall" : "",
2611 visual_list ? ", ENTER to accept" : ", 'v' for visuals",
2612 (attr_idx || char_idx) ? ", 'c', 'p' to paste" : ", 'c' to copy"),
2618 if (object_cnt) object_kind_track(creature_ptr, object_idx[object_cur]);
2620 if (object_old != object_idx[object_cur])
2622 handle_stuff(creature_ptr);
2623 object_old = object_idx[object_cur];
2629 place_visual_list_cursor(max + 3, 7, flavor_k_ptr->x_attr, flavor_k_ptr->x_char, attr_top, char_left);
2633 Term_gotoxy(0, 6 + (grp_cur - grp_top));
2637 Term_gotoxy(max + 3, 6 + (object_cur - object_top));
2641 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))
2643 if (direct_k_idx >= 0)
2668 if (!visual_list && !visual_only && (grp_cnt > 0))
2670 desc_obj_fake(creature_ptr, object_idx[object_cur]);
2679 browser_cursor(ch, &column, &grp_cur, grp_cnt, &object_cur, object_cnt);
2685 C_KILL(object_idx, max_k_idx, KIND_OBJECT_IDX);
2690 * Display the features in a group.
2692 static void display_feature_list(int col, int row, int per_page, FEAT_IDX *feat_idx,
2693 FEAT_IDX feat_cur, FEAT_IDX feat_top, bool visual_only, int lighting_level)
2695 int lit_col[F_LIT_MAX], i;
2696 int f_idx_col = use_bigtile ? 62 : 64;
2698 lit_col[F_LIT_STANDARD] = use_bigtile ? (71 - F_LIT_MAX) : 71;
2699 for (i = F_LIT_NS_BEGIN; i < F_LIT_MAX; i++)
2700 lit_col[i] = lit_col[F_LIT_STANDARD] + 2 + (i - F_LIT_NS_BEGIN) * 2 + (use_bigtile ? i : 0);
2702 for (i = 0; i < per_page && (feat_idx[feat_top + i] >= 0); i++)
2705 FEAT_IDX f_idx = feat_idx[feat_top + i];
2706 feature_type *f_ptr = &f_info[f_idx];
2707 int row_i = row + i;
2708 attr = ((i + feat_top == feat_cur) ? TERM_L_BLUE : TERM_WHITE);
2709 c_prt(attr, f_name + f_ptr->name, row_i, col);
2712 c_prt(attr, format("(%s)", lighting_level_str[lighting_level]), row_i, col + 1 + strlen(f_name + f_ptr->name));
2713 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));
2715 if (current_world_ptr->wizard || visual_only)
2717 c_prt(attr, format("%d", f_idx), row_i, f_idx_col);
2720 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);
2721 Term_putch(lit_col[F_LIT_NS_BEGIN], row_i, TERM_SLATE, '(');
2722 for (int j = F_LIT_NS_BEGIN + 1; j < F_LIT_MAX; j++)
2724 Term_putch(lit_col[j], row_i, TERM_SLATE, '/');
2727 Term_putch(lit_col[F_LIT_MAX - 1] + (use_bigtile ? 3 : 2), row_i, TERM_SLATE, ')');
2728 for (int j = F_LIT_NS_BEGIN; j < F_LIT_MAX; j++)
2730 Term_queue_bigchar(lit_col[j] + 1, row_i, f_ptr->x_attr[j], f_ptr->x_char[j], 0, 0);
2734 for (; i < per_page; i++)
2736 Term_erase(col, row + i, 255);
2742 * Interact with feature visuals.
2744 void do_cmd_knowledge_features(bool *need_redraw, bool visual_only, IDX direct_f_idx, IDX *lighting_level)
2746 TERM_COLOR attr_old[F_LIT_MAX];
2747 (void)C_WIPE(attr_old, F_LIT_MAX, TERM_COLOR);
2748 SYMBOL_CODE char_old[F_LIT_MAX];
2749 (void)C_WIPE(char_old, F_LIT_MAX, SYMBOL_CODE);
2752 Term_get_size(&wid, &hgt);
2755 C_MAKE(feat_idx, max_f_idx, FEAT_IDX);
2761 FEAT_IDX grp_idx[100];
2762 TERM_COLOR attr_top = 0;
2763 bool visual_list = FALSE;
2765 TERM_LEN browser_rows = hgt - 8;
2766 if (direct_f_idx < 0)
2768 for (FEAT_IDX i = 0; feature_group_text[i] != NULL; i++)
2770 len = strlen(feature_group_text[i]);
2771 if (len > max) max = len;
2773 if (collect_features(feat_idx, 0x01))
2775 grp_idx[grp_cnt++] = i;
2783 feature_type *f_ptr = &f_info[direct_f_idx];
2785 feat_idx[0] = direct_f_idx;
2789 (void)visual_mode_command('v', &visual_list, browser_rows - 1, wid - (max + 3),
2790 &attr_top, &char_left, &f_ptr->x_attr[*lighting_level], &f_ptr->x_char[*lighting_level], need_redraw);
2792 for (FEAT_IDX i = 0; i < F_LIT_MAX; i++)
2794 attr_old[i] = f_ptr->x_attr[i];
2795 char_old[i] = f_ptr->x_char[i];
2799 grp_idx[grp_cnt] = -1;
2801 FEAT_IDX old_grp_cur = -1;
2802 FEAT_IDX grp_cur = 0;
2803 FEAT_IDX grp_top = 0;
2804 FEAT_IDX feat_cur = 0;
2805 FEAT_IDX feat_top = 0;
2806 TERM_LEN column = 0;
2809 TERM_COLOR *cur_attr_ptr;
2810 SYMBOL_CODE *cur_char_ptr;
2814 feature_type *f_ptr;
2820 prt(_("表示 - 地形", "Visuals - features"), 2, 0);
2821 if (direct_f_idx < 0) prt(_("グループ", "Group"), 4, 0);
2822 prt(_("名前", "Name"), 4, max + 3);
2825 if (current_world_ptr->wizard || visual_only) prt("Idx", 4, 62);
2826 prt(_("文字 ( l/ d)", "Sym ( l/ d)"), 4, 66);
2830 if (current_world_ptr->wizard || visual_only) prt("Idx", 4, 64);
2831 prt(_("文字 (l/d)", "Sym (l/d)"), 4, 68);
2834 for (FEAT_IDX i = 0; i < 78; i++)
2836 Term_putch(i, 5, TERM_WHITE, '=');
2839 if (direct_f_idx < 0)
2841 for (FEAT_IDX i = 0; i < browser_rows; i++)
2843 Term_putch(max + 1, 6 + i, TERM_WHITE, '|');
2850 if (direct_f_idx < 0)
2852 if (grp_cur < grp_top) grp_top = grp_cur;
2853 if (grp_cur >= grp_top + browser_rows) grp_top = grp_cur - browser_rows + 1;
2855 display_group_list(0, 6, max, browser_rows, grp_idx, feature_group_text, grp_cur, grp_top);
2856 if (old_grp_cur != grp_cur)
2858 old_grp_cur = grp_cur;
2859 feat_cnt = collect_features(feat_idx, 0x00);
2862 while (feat_cur < feat_top)
2863 feat_top = MAX(0, feat_top - browser_rows / 2);
2864 while (feat_cur >= feat_top + browser_rows)
2865 feat_top = MIN(feat_cnt - browser_rows, feat_top + browser_rows / 2);
2870 display_feature_list(max + 3, 6, browser_rows, feat_idx, feat_cur, feat_top, visual_only, F_LIT_STANDARD);
2874 feat_top = feat_cur;
2875 display_feature_list(max + 3, 6, 1, feat_idx, feat_cur, feat_top, visual_only, *lighting_level);
2876 display_visual_list(max + 3, 7, browser_rows - 1, wid - (max + 3), attr_top, char_left);
2879 prt(format(_("<方向>%s, 'd'で標準光源効果%s, ESC", "<dir>%s, 'd' for default lighting%s, ESC"),
2880 visual_list ? _(", ENTERで決定, 'a'で対象明度変更", ", ENTER to accept, 'a' for lighting level") : _(", 'v'でシンボル変更", ", 'v' for visuals"),
2881 (attr_idx || char_idx) ? _(", 'c', 'p'でペースト", ", 'c', 'p' to paste") : _(", 'c'でコピー", ", 'c' to copy")),
2884 f_ptr = &f_info[feat_idx[feat_cur]];
2885 cur_attr_ptr = &f_ptr->x_attr[*lighting_level];
2886 cur_char_ptr = &f_ptr->x_char[*lighting_level];
2890 place_visual_list_cursor(max + 3, 7, *cur_attr_ptr, *cur_char_ptr, attr_top, char_left);
2894 Term_gotoxy(0, 6 + (grp_cur - grp_top));
2898 Term_gotoxy(max + 3, 6 + (feat_cur - feat_top));
2902 if (visual_list && ((ch == 'A') || (ch == 'a')))
2904 int prev_lighting_level = *lighting_level;
2908 if (*lighting_level <= 0) *lighting_level = F_LIT_MAX - 1;
2909 else (*lighting_level)--;
2913 if (*lighting_level >= F_LIT_MAX - 1) *lighting_level = 0;
2914 else (*lighting_level)++;
2917 if (f_ptr->x_attr[prev_lighting_level] != f_ptr->x_attr[*lighting_level])
2918 attr_top = MAX(0, (f_ptr->x_attr[*lighting_level] & 0x7f) - 5);
2920 if (f_ptr->x_char[prev_lighting_level] != f_ptr->x_char[*lighting_level])
2921 char_left = MAX(0, f_ptr->x_char[*lighting_level] - 10);
2925 else if ((ch == 'D') || (ch == 'd'))
2927 TERM_COLOR prev_x_attr = f_ptr->x_attr[*lighting_level];
2928 byte prev_x_char = f_ptr->x_char[*lighting_level];
2930 apply_default_feat_lighting(f_ptr->x_attr, f_ptr->x_char);
2934 if (prev_x_attr != f_ptr->x_attr[*lighting_level])
2935 attr_top = MAX(0, (f_ptr->x_attr[*lighting_level] & 0x7f) - 5);
2937 if (prev_x_char != f_ptr->x_char[*lighting_level])
2938 char_left = MAX(0, f_ptr->x_char[*lighting_level] - 10);
2940 else *need_redraw = TRUE;
2944 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))
2949 for (FEAT_IDX i = 0; i < F_LIT_MAX; i++)
2951 f_ptr->x_attr[i] = attr_old[i];
2952 f_ptr->x_char[i] = char_old[i];
2958 if (direct_f_idx >= 0) flag = TRUE;
2959 else *lighting_level = F_LIT_STANDARD;
2963 for (FEAT_IDX i = 0; i < F_LIT_MAX; i++)
2965 attr_old[i] = f_ptr->x_attr[i];
2966 char_old[i] = f_ptr->x_char[i];
2968 *lighting_level = F_LIT_STANDARD;
2975 for (FEAT_IDX i = 0; i < F_LIT_MAX; i++)
2977 attr_idx_feat[i] = f_ptr->x_attr[i];
2978 char_idx_feat[i] = f_ptr->x_char[i];
2987 for (FEAT_IDX i = F_LIT_NS_BEGIN; i < F_LIT_MAX; i++)
2989 if (attr_idx_feat[i] || (!(char_idx_feat[i] & 0x80) && char_idx_feat[i])) f_ptr->x_attr[i] = attr_idx_feat[i];
2990 if (char_idx_feat[i]) f_ptr->x_char[i] = char_idx_feat[i];
3008 browser_cursor(ch, &column, &grp_cur, grp_cnt, &feat_cur, feat_cnt);
3014 C_KILL(feat_idx, max_f_idx, FEAT_IDX);
3019 * List wanted monsters
3020 * @param creature_ptr プレーヤーへの参照ポインタ
3023 static void do_cmd_knowledge_bounty(player_type *creature_ptr)
3026 GAME_TEXT file_name[1024];
3027 fff = my_fopen_temp(file_name, 1024);
3030 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
3035 fprintf(fff, _("今日のターゲット : %s\n", "Today's target : %s\n"),
3036 (creature_ptr->today_mon ? r_name + r_info[creature_ptr->today_mon].name : _("不明", "unknown")));
3038 fprintf(fff, _("賞金首リスト\n", "List of wanted monsters\n"));
3039 fprintf(fff, "----------------------------------------------\n");
3041 bool listed = FALSE;
3042 for (int i = 0; i < MAX_BOUNTY; i++)
3044 if (current_world_ptr->bounty_r_idx[i] <= 10000)
3046 fprintf(fff, "%s\n", r_name + r_info[current_world_ptr->bounty_r_idx[i]].name);
3053 fprintf(fff, "\n%s\n", _("賞金首はもう残っていません。", "There are no more wanted monster."));
3057 (void)show_file(creature_ptr, TRUE, file_name, _("賞金首の一覧", "Wanted monsters"), 0, 0);
3062 * List virtues & status
3064 static void do_cmd_knowledge_virtues(player_type *creature_ptr)
3067 GAME_TEXT file_name[1024];
3068 fff = my_fopen_temp(file_name, 1024);
3071 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
3076 fprintf(fff, _("現在の属性 : %s\n\n", "Your alignment : %s\n\n"), your_alignment(creature_ptr));
3077 dump_virtues(creature_ptr, fff);
3079 (void)show_file(creature_ptr, TRUE, file_name, _("八つの徳", "Virtues"), 0, 0);
3086 static void do_cmd_knowledge_dungeon(player_type *creature_ptr)
3089 GAME_TEXT file_name[1024];
3090 fff = my_fopen_temp(file_name, 1024);
3093 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
3098 for (int i = 1; i < current_world_ptr->max_d_idx; i++)
3102 if (!d_info[i].maxdepth) continue;
3103 if (!max_dlv[i]) continue;
3104 if (d_info[i].final_guardian)
3106 if (!r_info[d_info[i].final_guardian].max_num) seiha = TRUE;
3108 else if (max_dlv[i] == d_info[i].maxdepth) seiha = TRUE;
3110 fprintf(fff, _("%c%-12s : %3d 階\n", "%c%-16s : level %3d\n"), seiha ? '!' : ' ', d_name + d_info[i].name, (int)max_dlv[i]);
3114 (void)show_file(creature_ptr, TRUE, file_name, _("今までに入ったダンジョン", "Dungeon"), 0, 0);
3120 * List virtues & status
3123 static void do_cmd_knowledge_stat(player_type *creature_ptr)
3126 GAME_TEXT file_name[1024];
3127 fff = my_fopen_temp(file_name, 1024);
3130 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
3135 int percent = (int)(((long)creature_ptr->player_hp[PY_MAX_LEVEL - 1] * 200L) /
3136 (2 * creature_ptr->hitdie +
3137 ((PY_MAX_LEVEL - 1 + 3) * (creature_ptr->hitdie + 1))));
3139 if (creature_ptr->knowledge & KNOW_HPRATE)
3140 fprintf(fff, _("現在の体力ランク : %d/100\n\n", "Your current Life Rating is %d/100.\n\n"), percent);
3141 else fprintf(fff, _("現在の体力ランク : ???\n\n", "Your current Life Rating is ???.\n\n"));
3143 fprintf(fff, _("能力の最大値\n\n", "Limits of maximum stats\n\n"));
3144 for (int v_nr = 0; v_nr < A_MAX; v_nr++)
3146 if ((creature_ptr->knowledge & KNOW_STAT) || creature_ptr->stat_max[v_nr] == creature_ptr->stat_max_max[v_nr]) fprintf(fff, "%s 18/%d\n", stat_names[v_nr], creature_ptr->stat_max_max[v_nr] - 18);
3147 else fprintf(fff, "%s ???\n", stat_names[v_nr]);
3150 dump_yourself(creature_ptr, fff);
3152 (void)show_file(creature_ptr, TRUE, file_name, _("自分に関する情報", "HP-rate & Max stat"), 0, 0);
3158 * todo player_typeではなくQUEST_IDXを引数にすべきかもしれない
3159 * Print all active quests
3160 * @param creature_ptr プレーヤーへの参照ポインタ
3163 static void do_cmd_knowledge_quests_current(player_type *creature_ptr, FILE *fff)
3166 char rand_tmp_str[120] = "\0";
3167 GAME_TEXT name[MAX_NLEN];
3168 monster_race *r_ptr;
3169 int rand_level = 100;
3172 fprintf(fff, _("《遂行中のクエスト》\n", "< Current Quest >\n"));
3174 for (QUEST_IDX i = 1; i < max_q_idx; i++)
3176 bool is_print = quest[i].status == QUEST_STATUS_TAKEN;
3177 is_print |= (quest[i].status == QUEST_STATUS_STAGE_COMPLETED) && (quest[i].type == QUEST_TYPE_TOWER);
3178 is_print |= quest[i].status == QUEST_STATUS_COMPLETED;
3182 QUEST_IDX old_quest = creature_ptr->current_floor_ptr->inside_quest;
3183 for (int j = 0; j < 10; j++)
3184 quest_text[j][0] = '\0';
3186 quest_text_line = 0;
3187 creature_ptr->current_floor_ptr->inside_quest = i;
3188 init_flags = INIT_SHOW_TEXT;
3189 process_dungeon_file(creature_ptr, "q_info.txt", 0, 0, 0, 0);
3190 creature_ptr->current_floor_ptr->inside_quest = old_quest;
3191 if (quest[i].flags & QUEST_FLAG_SILENT) continue;
3194 if (quest[i].type != QUEST_TYPE_RANDOM)
3196 char note[80] = "\0";
3198 if (quest[i].status == QUEST_STATUS_TAKEN || quest[i].status == QUEST_STATUS_STAGE_COMPLETED)
3200 switch (quest[i].type)
3202 case QUEST_TYPE_KILL_LEVEL:
3203 case QUEST_TYPE_KILL_ANY_LEVEL:
3204 r_ptr = &r_info[quest[i].r_idx];
3205 strcpy(name, r_name + r_ptr->name);
3206 if (quest[i].max_num > 1)
3209 sprintf(note, " - %d 体の%sを倒す。(あと %d 体)",
3210 (int)quest[i].max_num, name, (int)(quest[i].max_num - quest[i].cur_num));
3213 sprintf(note, " - kill %d %s, have killed %d.",
3214 (int)quest[i].max_num, name, (int)quest[i].cur_num);
3218 sprintf(note, _(" - %sを倒す。", " - kill %s."), name);
3221 case QUEST_TYPE_FIND_ARTIFACT:
3224 artifact_type *a_ptr = &a_info[quest[i].k_idx];
3226 object_type *q_ptr = &forge;
3227 KIND_OBJECT_IDX k_idx = lookup_kind(a_ptr->tval, a_ptr->sval);
3228 object_prep(q_ptr, k_idx);
3229 q_ptr->name1 = quest[i].k_idx;
3230 q_ptr->ident = IDENT_STORE;
3231 object_desc(creature_ptr, name, q_ptr, OD_NAME_ONLY);
3233 sprintf(note, _("\n - %sを見つけ出す。", "\n - Find %s."), name);
3235 case QUEST_TYPE_FIND_EXIT:
3236 sprintf(note, _(" - 出口に到達する。", " - Reach exit."));
3239 case QUEST_TYPE_KILL_NUMBER:
3241 sprintf(note, " - %d 体のモンスターを倒す。(あと %d 体)",
3242 (int)quest[i].max_num, (int)(quest[i].max_num - quest[i].cur_num));
3244 sprintf(note, " - Kill %d monsters, have killed %d.",
3245 (int)quest[i].max_num, (int)quest[i].cur_num);
3249 case QUEST_TYPE_KILL_ALL:
3250 case QUEST_TYPE_TOWER:
3251 sprintf(note, _(" - 全てのモンスターを倒す。", " - Kill all monsters."));
3256 sprintf(tmp_str, _(" %s (危険度:%d階相当)%s\n", " %s (Danger level: %d)%s\n"),
3257 quest[i].name, (int)quest[i].level, note);
3258 fputs(tmp_str, fff);
3259 if (quest[i].status == QUEST_STATUS_COMPLETED)
3261 sprintf(tmp_str, _(" クエスト達成 - まだ報酬を受けとってない。\n", " Quest Completed - Unrewarded\n"));
3262 fputs(tmp_str, fff);
3267 while (quest_text[k][0] && k < 10)
3269 fprintf(fff, " %s\n", quest_text[k]);
3276 if (quest[i].level >= rand_level)
3279 rand_level = quest[i].level;
3280 if (max_dlv[DUNGEON_ANGBAND] < rand_level) continue;
3282 r_ptr = &r_info[quest[i].r_idx];
3283 strcpy(name, r_name + r_ptr->name);
3284 if (quest[i].max_num <= 1)
3286 sprintf(rand_tmp_str, _(" %s (%d 階) - %sを倒す。\n", " %s (Dungeon level: %d)\n Kill %s.\n"),
3287 quest[i].name, (int)quest[i].level, name);
3292 sprintf(rand_tmp_str, " %s (%d 階) - %d 体の%sを倒す。(あと %d 体)\n",
3293 quest[i].name, (int)quest[i].level,
3294 (int)quest[i].max_num, name, (int)(quest[i].max_num - quest[i].cur_num));
3298 sprintf(rand_tmp_str, " %s (Dungeon level: %d)\n Kill %d %s, have killed %d.\n",
3299 quest[i].name, (int)quest[i].level,
3300 (int)quest[i].max_num, name, (int)quest[i].cur_num);
3304 if (rand_tmp_str[0]) fputs(rand_tmp_str, fff);
3306 if (!total) fprintf(fff, _(" なし\n", " Nothing.\n"));
3310 static bool do_cmd_knowledge_quests_aux(player_type *player_ptr, FILE *fff, IDX q_idx)
3313 char playtime_str[16];
3314 quest_type* const q_ptr = &quest[q_idx];
3316 floor_type *floor_ptr = player_ptr->current_floor_ptr;
3317 if (is_fixed_quest_idx(q_idx))
3319 IDX old_quest = floor_ptr->inside_quest;
3320 floor_ptr->inside_quest = q_idx;
3321 init_flags = INIT_NAME_ONLY;
3322 process_dungeon_file(player_ptr, "q_info.txt", 0, 0, 0, 0);
3323 floor_ptr->inside_quest = old_quest;
3324 if (q_ptr->flags & QUEST_FLAG_SILENT) return FALSE;
3327 strnfmt(playtime_str, sizeof(playtime_str), "%02d:%02d:%02d",
3328 q_ptr->comptime / (60 * 60), (q_ptr->comptime / 60) % 60, q_ptr->comptime % 60);
3330 if (is_fixed_quest_idx(q_idx) || (q_ptr->r_idx == 0))
3333 _(" %-35s (危険度:%3d階相当) - レベル%2d - %s\n",
3334 " %-35s (Danger level: %3d) - level %2d - %s\n"),
3335 q_ptr->name, (int)q_ptr->level, q_ptr->complev, playtime_str);
3336 fputs(tmp_str, fff);
3340 if (q_ptr->complev == 0)
3343 _(" %-35s (%3d階) - 不戦勝 - %s\n",
3344 " %-35s (Dungeon level: %3d) - Unearned - %s\n"),
3345 r_name + r_info[q_ptr->r_idx].name,
3346 (int)q_ptr->level, playtime_str);
3347 fputs(tmp_str, fff);
3352 _(" %-35s (%3d階) - レベル%2d - %s\n",
3353 " %-35s (Dungeon level: %3d) - level %2d - %s\n"),
3354 r_name + r_info[q_ptr->r_idx].name,
3358 fputs(tmp_str, fff);
3364 * Print all finished quests
3365 * @param creature_ptr プレーヤーへの参照ポインタ
3366 * @param fff セーブファイル (展開済?)
3367 * @param quest_num[] 受注したことのあるクエスト群
3370 void do_cmd_knowledge_quests_completed(player_type *creature_ptr, FILE *fff, QUEST_IDX quest_num[])
3372 fprintf(fff, _("《達成したクエスト》\n", "< Completed Quest >\n"));
3373 QUEST_IDX total = 0;
3374 for (QUEST_IDX i = 1; i < max_q_idx; i++)
3376 QUEST_IDX q_idx = quest_num[i];
3377 quest_type* const q_ptr = &quest[q_idx];
3379 if (q_ptr->status == QUEST_STATUS_FINISHED && do_cmd_knowledge_quests_aux(creature_ptr, fff, q_idx))
3385 if (!total) fprintf(fff, _(" なし\n", " Nothing.\n"));
3390 * Print all failed quests
3391 * @param creature_ptr プレーヤーへの参照ポインタ
3392 * @param fff セーブファイル (展開済?)
3393 * @param quest_num[] 受注したことのあるクエスト群
3396 void do_cmd_knowledge_quests_failed(player_type *creature_ptr, FILE *fff, QUEST_IDX quest_num[])
3398 fprintf(fff, _("《失敗したクエスト》\n", "< Failed Quest >\n"));
3399 QUEST_IDX total = 0;
3400 for (QUEST_IDX i = 1; i < max_q_idx; i++)
3402 QUEST_IDX q_idx = quest_num[i];
3403 quest_type* const q_ptr = &quest[q_idx];
3405 if (((q_ptr->status == QUEST_STATUS_FAILED_DONE) || (q_ptr->status == QUEST_STATUS_FAILED)) &&
3406 do_cmd_knowledge_quests_aux(creature_ptr, fff, q_idx))
3412 if (!total) fprintf(fff, _(" なし\n", " Nothing.\n"));
3417 * Print all random quests
3419 static void do_cmd_knowledge_quests_wiz_random(FILE *fff)
3421 fprintf(fff, _("《残りのランダムクエスト》\n", "< Remaining Random Quest >\n"));
3422 GAME_TEXT tmp_str[120];
3423 QUEST_IDX total = 0;
3424 for (QUEST_IDX i = 1; i < max_q_idx; i++)
3426 if (quest[i].flags & QUEST_FLAG_SILENT) continue;
3428 if ((quest[i].type == QUEST_TYPE_RANDOM) && (quest[i].status == QUEST_STATUS_TAKEN))
3431 sprintf(tmp_str, _(" %s (%d階, %s)\n", " %s (%d, %s)\n"),
3432 quest[i].name, (int)quest[i].level, r_name + r_info[quest[i].r_idx].name);
3433 fputs(tmp_str, fff);
3437 if (!total) fprintf(fff, _(" なし\n", " Nothing.\n"));
3441 * Print quest status of all active quests
3442 * @param creature_ptr プレーヤーへの参照ポインタ
3445 static void do_cmd_knowledge_quests(player_type *creature_ptr)
3448 GAME_TEXT file_name[1024];
3449 fff = my_fopen_temp(file_name, 1024);
3452 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
3458 C_MAKE(quest_num, max_q_idx, QUEST_IDX);
3460 for (IDX i = 1; i < max_q_idx; i++)
3464 ang_sort(quest_num, &dummy, max_q_idx, ang_sort_comp_quest_num, ang_sort_swap_quest_num);
3466 do_cmd_knowledge_quests_current(creature_ptr, fff);
3468 do_cmd_knowledge_quests_completed(creature_ptr, fff, quest_num);
3470 do_cmd_knowledge_quests_failed(creature_ptr, fff, quest_num);
3471 if (current_world_ptr->wizard)
3474 do_cmd_knowledge_quests_wiz_random(fff);
3478 (void)show_file(creature_ptr, TRUE, file_name, _("クエスト達成状況", "Quest status"), 0, 0);
3480 C_KILL(quest_num, max_q_idx, QUEST_IDX);
3486 * @param player_ptr プレーヤーへの参照ポインタ
3489 static void do_cmd_knowledge_home(player_type *player_ptr)
3491 process_dungeon_file(player_ptr, "w_info.txt", 0, 0, current_world_ptr->max_wild_y, current_world_ptr->max_wild_x);
3493 /* Open a new file */
3495 GAME_TEXT file_name[1024];
3496 fff = my_fopen_temp(file_name, 1024);
3499 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
3504 store_type *store_ptr;
3505 store_ptr = &town_info[1].store[STORE_HOME];
3507 if (store_ptr->stock_num)
3512 fprintf(fff, _(" [ 我が家のアイテム ]\n", " [Home Inventory]\n"));
3513 concptr paren = ")";
3514 GAME_TEXT o_name[MAX_NLEN];
3515 for (int i = 0; i < store_ptr->stock_num; i++)
3518 if ((i % 12) == 0) fprintf(fff, "\n ( %d ページ )\n", x++);
3519 object_desc(player_ptr, o_name, &store_ptr->stock[i], 0);
3520 if (strlen(o_name) <= 80 - 3)
3522 fprintf(fff, "%c%s %s\n", I2A(i % 12), paren, o_name);
3528 for (n = 0, t = o_name; n < 80 - 3; n++, t++)
3529 if (iskanji(*t)) { t++; n++; }
3530 if (n == 81 - 3) n = 79 - 3; /* 最後が漢字半分 */
3532 fprintf(fff, "%c%s %.*s\n", I2A(i % 12), paren, n, o_name);
3533 fprintf(fff, " %.77s\n", o_name + n);
3536 object_desc(player_ptr, o_name, &store_ptr->stock[i], 0);
3537 fprintf(fff, "%c%s %s\n", I2A(i % 12), paren, o_name);
3541 fprintf(fff, "\n\n");
3545 (void)show_file(player_ptr, TRUE, file_name, _("我が家のアイテム", "Home Inventory"), 0, 0);
3551 * Check the status of "autopick"
3553 static void do_cmd_knowledge_autopick(player_type *creature_ptr)
3555 /* Open a new file */
3557 GAME_TEXT file_name[1024];
3558 fff = my_fopen_temp(file_name, 1024);
3561 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
3568 fprintf(fff, _("自動破壊/拾いには何も登録されていません。", "No preference for auto picker/destroyer."));
3572 fprintf(fff, _(" 自動拾い/破壊には現在 %d行登録されています。\n\n",
3573 " There are %d registered lines for auto picker/destroyer.\n\n"), max_autopick);
3576 for (int k = 0; k < max_autopick; k++)
3579 byte act = autopick_list[k].action;
3580 if (act & DONT_AUTOPICK)
3582 tmp = _("放置", "Leave");
3584 else if (act & DO_AUTODESTROY)
3586 tmp = _("破壊", "Destroy");
3588 else if (act & DO_AUTOPICK)
3590 tmp = _("拾う", "Pickup");
3594 tmp = _("確認", "Query");
3597 if (act & DO_DISPLAY)
3598 fprintf(fff, "%11s", format("[%s]", tmp));
3600 fprintf(fff, "%11s", format("(%s)", tmp));
3602 tmp = autopick_line_from_entry(&autopick_list[k]);
3603 fprintf(fff, " %s", tmp);
3610 (void)show_file(creature_ptr, TRUE, file_name, _("自動拾い/破壊 設定リスト", "Auto-picker/Destroyer"), 0, 0);
3616 * Interact with "knowledge"
3618 void do_cmd_knowledge(player_type *creature_ptr)
3621 bool need_redraw = FALSE;
3622 FILE_TYPE(FILE_TYPE_TEXT);
3627 prt(format(_("%d/2 ページ", "page %d/2"), (p + 1)), 2, 65);
3628 prt(_("現在の知識を確認する", "Display current knowledge"), 3, 0);
3633 prt("(1) 既知の伝説のアイテム の一覧", 6, 5);
3634 prt("(2) 既知のアイテム の一覧", 7, 5);
3635 prt("(3) 既知の生きているユニーク・モンスター の一覧", 8, 5);
3636 prt("(4) 既知のモンスター の一覧", 9, 5);
3637 prt("(5) 倒した敵の数 の一覧", 10, 5);
3638 if (!vanilla_town) prt("(6) 賞金首 の一覧", 11, 5);
3639 prt("(7) 現在のペット の一覧", 12, 5);
3640 prt("(8) 我が家のアイテム の一覧", 13, 5);
3641 prt("(9) *鑑定*済み装備の耐性 の一覧", 14, 5);
3642 prt("(0) 地形の表示文字/タイル の一覧", 15, 5);
3646 prt("(a) 自分に関する情報 の一覧", 6, 5);
3647 prt("(b) 突然変異 の一覧", 7, 5);
3648 prt("(c) 武器の経験値 の一覧", 8, 5);
3649 prt("(d) 魔法の経験値 の一覧", 9, 5);
3650 prt("(e) 技能の経験値 の一覧", 10, 5);
3651 prt("(f) プレイヤーの徳 の一覧", 11, 5);
3652 prt("(g) 入ったダンジョン の一覧", 12, 5);
3653 prt("(h) 実行中のクエスト の一覧", 13, 5);
3654 prt("(i) 現在の自動拾い/破壊設定 の一覧", 14, 5);
3659 prt("(1) Display known artifacts", 6, 5);
3660 prt("(2) Display known objects", 7, 5);
3661 prt("(3) Display remaining uniques", 8, 5);
3662 prt("(4) Display known monster", 9, 5);
3663 prt("(5) Display kill count", 10, 5);
3664 if (!vanilla_town) prt("(6) Display wanted monsters", 11, 5);
3665 prt("(7) Display current pets", 12, 5);
3666 prt("(8) Display home inventory", 13, 5);
3667 prt("(9) Display *identified* equip.", 14, 5);
3668 prt("(0) Display terrain symbols.", 15, 5);
3672 prt("(a) Display about yourself", 6, 5);
3673 prt("(b) Display mutations", 7, 5);
3674 prt("(c) Display weapon proficiency", 8, 5);
3675 prt("(d) Display spell proficiency", 9, 5);
3676 prt("(e) Display misc. proficiency", 10, 5);
3677 prt("(f) Display virtues", 11, 5);
3678 prt("(g) Display dungeons", 12, 5);
3679 prt("(h) Display current quests", 13, 5);
3680 prt("(i) Display auto pick/destroy", 14, 5);
3683 prt(_("-続く-", "-more-"), 17, 8);
3684 prt(_("ESC) 抜ける", "ESC) Exit menu"), 21, 1);
3685 prt(_("SPACE) 次ページ", "SPACE) Next page"), 21, 30);
3686 prt(_("コマンド:", "Command: "), 20, 0);
3689 if (i == ESCAPE) break;
3692 case ' ': /* Page change */
3696 case '1': /* Artifacts */
3697 do_cmd_knowledge_artifacts(creature_ptr);
3699 case '2': /* Objects */
3700 do_cmd_knowledge_objects(creature_ptr, &need_redraw, FALSE, -1);
3702 case '3': /* Uniques */
3703 do_cmd_knowledge_uniques(creature_ptr);
3705 case '4': /* Monsters */
3706 do_cmd_knowledge_monsters(creature_ptr, &need_redraw, FALSE, -1);
3708 case '5': /* Kill count */
3709 do_cmd_knowledge_kill_count(creature_ptr);
3711 case '6': /* wanted */
3712 if (!vanilla_town) do_cmd_knowledge_bounty(creature_ptr);
3714 case '7': /* Pets */
3715 do_cmd_knowledge_pets(creature_ptr);
3717 case '8': /* Home */
3718 do_cmd_knowledge_home(creature_ptr);
3720 case '9': /* Resist list */
3721 do_cmd_knowledge_inven(creature_ptr);
3723 case '0': /* Feature list */
3725 IDX lighting_level = F_LIT_STANDARD;
3726 do_cmd_knowledge_features(&need_redraw, FALSE, -1, &lighting_level);
3730 case 'a': /* Max stat */
3731 do_cmd_knowledge_stat(creature_ptr);
3733 case 'b': /* Mutations */
3734 do_cmd_knowledge_mutations(creature_ptr);
3736 case 'c': /* weapon-exp */
3737 do_cmd_knowledge_weapon_exp(creature_ptr);
3739 case 'd': /* spell-exp */
3740 do_cmd_knowledge_spell_exp(creature_ptr);
3742 case 'e': /* skill-exp */
3743 do_cmd_knowledge_skill_exp(creature_ptr);
3745 case 'f': /* Virtues */
3746 do_cmd_knowledge_virtues(creature_ptr);
3748 case 'g': /* Dungeon */
3749 do_cmd_knowledge_dungeon(creature_ptr);
3751 case 'h': /* Quests */
3752 do_cmd_knowledge_quests(creature_ptr);
3754 case 'i': /* Autopick */
3755 do_cmd_knowledge_autopick(creature_ptr);
3757 default: /* Unknown option */
3765 if (need_redraw) do_cmd_redraw(creature_ptr);
3770 * Check on the status of an active quest
3771 * @param creature_ptr プレーヤーへの参照ポインタ
3774 void do_cmd_checkquest(player_type *creature_ptr)
3776 FILE_TYPE(FILE_TYPE_TEXT);
3778 do_cmd_knowledge_quests(creature_ptr);
3784 * Display the time and date
3785 * @param creature_ptr プレーヤーへの参照ポインタ
3788 void do_cmd_time(player_type *creature_ptr)
3791 extract_day_hour_min(creature_ptr, &day, &hour, &min);
3794 strcpy(desc, _("変な時刻だ。", "It is a strange time."));
3797 if (day < MAX_DAYS) sprintf(day_buf, "%d", day);
3798 else strcpy(day_buf, "*****");
3800 msg_format(_("%s日目, 時刻は%d:%02d %sです。", "This is day %s. The time is %d:%02d %s."),
3801 day_buf, (hour % 12 == 0) ? 12 : (hour % 12), min, (hour < 12) ? "AM" : "PM");
3804 if (!randint0(10) || creature_ptr->image)
3806 path_build(buf, sizeof(buf), ANGBAND_DIR_FILE, _("timefun_j.txt", "timefun.txt"));
3810 path_build(buf, sizeof(buf), ANGBAND_DIR_FILE, _("timenorm_j.txt", "timenorm.txt"));
3814 fff = my_fopen(buf, "rt");
3818 int full = hour * 100 + min;
3822 while (!my_fgets(fff, buf, sizeof(buf)))
3824 if (!buf[0] || (buf[0] == '#')) continue;
3825 if (buf[1] != ':') continue;
3829 start = atoi(buf + 2);
3836 end = atoi(buf + 2);
3840 if ((start > full) || (full > end)) continue;
3845 if (!randint0(num)) strcpy(desc, buf + 2);