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.
16 * remove_auto_dump(orig_file, mark)
17 * Remove the old automatic dump of type "mark".
18 * auto_dump_printf(fmt, ...)
19 * Dump a formatted string using fprintf().
20 * open_auto_dump(buf, mark)
21 * Open a file, remove old dump, and add new header.
22 * close_auto_dump(void)
23 * Add a footer, and close the file.
24 * The dump commands of original Angband simply add new lines to
25 * existing files; these files will become bigger and bigger unless
26 * an user deletes some or all of these files by hand at some
28 * These three functions automatically delete old dumped lines
29 * before adding new ones. Since there are various kinds of automatic
30 * dumps in a single file, we add a header and a footer with a type
31 * name for every automatic dump, and kill old lines only when the
32 * lines have the correct type of header and footer.
33 * We need to be quite paranoid about correctness; the user might
34 * (mistakenly) edit the file by hand, and see all their work come
35 * to nothing on the next auto dump otherwise. The current code only
36 * detects changes by noting inconsistencies between the actual number
37 * of lines and the number written in the footer. Note that this will
38 * not catch single-line edits.
46 #include "core/show-file.h"
47 #include "io/read-pref-file.h"
48 #include "io/write-diary.h"
57 #include "view/display-player.h"
58 #include "player/process-name.h"
59 #include "player-effects.h"
60 #include "player-status.h"
61 #include "player-skill.h"
62 #include "player-personality.h"
69 #include "object-flavor.h"
70 #include "object-hook.h"
72 #include "monster-status.h"
73 #include "view-mainwindow.h"
74 #include "dungeon-file.h"
75 #include "io/interpret-pref-file.h"
78 #include "objectkind.h"
79 #include "floor-town.h"
80 #include "cmd/feeling-table.h"
81 #include "cmd/monster-group-table.h"
82 #include "cmd/diary-subtitle-table.h"
83 #include "cmd/object-group-table.h"
84 #include "view-mainwindow.h" // 暫定。後で消す
88 // Mark strings for auto dump
89 static char auto_dump_header[] = "# vvvvvvv== %s ==vvvvvvv";
90 static char auto_dump_footer[] = "# ^^^^^^^== %s ==^^^^^^^";
92 // Variables for auto dump
93 static FILE *auto_dump_stream;
94 static concptr auto_dump_mark;
95 static int auto_dump_line_num;
97 static void do_cmd_knowledge_monsters(player_type *creature_ptr, bool *need_redraw, bool visual_only, IDX direct_r_idx);
98 static void do_cmd_knowledge_objects(player_type *creature_ptr, bool *need_redraw, bool visual_only, IDX direct_k_idx);
99 static void do_cmd_knowledge_features(bool *need_redraw, bool visual_only, IDX direct_f_idx, IDX *lighting_level);
101 // Clipboard variables for copy&paste in visual mode
102 static TERM_COLOR attr_idx = 0;
103 static SYMBOL_CODE char_idx = 0;
105 static TERM_COLOR attr_idx_feat[F_LIT_MAX];
106 static SYMBOL_CODE char_idx_feat[F_LIT_MAX];
108 // Encode the screen colors
109 static char hack[17] = "dwsorgbuDWvyRGBU";
112 * @brief prf出力内容を消去する /
113 * Remove old lines automatically generated before.
114 * @param orig_file 消去を行うファイル名
116 static void remove_auto_dump(concptr orig_file)
118 FILE *tmp_fff, *orig_fff;
121 bool between_mark = FALSE;
122 bool changed = FALSE;
124 long header_location = 0;
125 char header_mark_str[80];
126 char footer_mark_str[80];
128 sprintf(header_mark_str, auto_dump_header, auto_dump_mark);
129 sprintf(footer_mark_str, auto_dump_footer, auto_dump_mark);
130 size_t mark_len = strlen(footer_mark_str);
131 orig_fff = my_fopen(orig_file, "r");
132 if (!orig_fff) return;
134 tmp_fff = my_fopen_temp(tmp_file, 1024);
137 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), tmp_file);
144 if (my_fgets(orig_fff, buf, sizeof(buf)))
148 fseek(orig_fff, header_location, SEEK_SET);
149 between_mark = FALSE;
160 if (!strcmp(buf, header_mark_str))
162 header_location = ftell(orig_fff);
169 fprintf(tmp_fff, "%s\n", buf);
175 if (!strncmp(buf, footer_mark_str, mark_len))
178 if (!sscanf(buf + mark_len, " (%d)", &tmp)
181 fseek(orig_fff, header_location, SEEK_SET);
184 between_mark = FALSE;
196 tmp_fff = my_fopen(tmp_file, "r");
197 orig_fff = my_fopen(orig_file, "w");
198 while (!my_fgets(tmp_fff, buf, sizeof(buf)))
199 fprintf(orig_fff, "%s\n", buf);
210 * @brief prfファイルのフォーマットに従った内容を出力する /
211 * Dump a formatted line, using "vstrnfmt()".
214 static void auto_dump_printf(concptr fmt, ...)
219 (void)vstrnfmt(buf, sizeof(buf), fmt, vp);
221 for (concptr p = buf; *p; p++)
223 if (*p == '\n') auto_dump_line_num++;
226 fprintf(auto_dump_stream, "%s", buf);
231 * @brief prfファイルをファイルオープンする /
232 * Open file to append auto dump.
234 * @param mark 出力するヘッダマーク
235 * @return ファイルポインタを取得できたらTRUEを返す
237 static bool open_auto_dump(concptr buf, concptr mark)
239 char header_mark_str[80];
240 auto_dump_mark = mark;
241 sprintf(header_mark_str, auto_dump_header, auto_dump_mark);
242 remove_auto_dump(buf);
243 auto_dump_stream = my_fopen(buf, "a");
244 if (!auto_dump_stream)
246 msg_format(_("%s を開くことができませんでした。", "Failed to open %s."), buf);
251 fprintf(auto_dump_stream, "%s\n", header_mark_str);
252 auto_dump_line_num = 0;
253 auto_dump_printf(_("# *警告!!* 以降の行は自動生成されたものです。\n",
254 "# *Warning!* The lines below are an automatic dump.\n"));
255 auto_dump_printf(_("# *警告!!* 後で自動的に削除されるので編集しないでください。\n",
256 "# Don't edit them; changes will be deleted and replaced automatically.\n"));
261 * @brief prfファイルをファイルクローズする /
262 * Append foot part and close auto dump.
265 static void close_auto_dump(void)
267 char footer_mark_str[80];
268 sprintf(footer_mark_str, auto_dump_footer, auto_dump_mark);
269 auto_dump_printf(_("# *警告!!* 以降の行は自動生成されたものです。\n",
270 "# *Warning!* The lines below are an automatic dump.\n"));
271 auto_dump_printf(_("# *警告!!* 後で自動的に削除されるので編集しないでください。\n",
272 "# Don't edit them; changes will be deleted and replaced automatically.\n"));
273 fprintf(auto_dump_stream, "%s (%d)\n", footer_mark_str, auto_dump_line_num);
274 my_fclose(auto_dump_stream);
281 * @brief Return suffix of ordinal number
283 * @return pointer of suffix string.
285 concptr get_ordinal_number_suffix(int num)
287 num = ABS(num) % 100;
291 return (num == 11) ? "th" : "st";
293 return (num == 12) ? "th" : "nd";
295 return (num == 13) ? "th" : "rd";
304 * @brief 日記のタイトル表記と内容出力
305 * @param creature_ptr プレーヤーへの参照ポインタ
308 static void display_diary(player_type *creature_ptr)
310 char diary_title[256];
311 GAME_TEXT file_name[MAX_NLEN];
314 sprintf(file_name, _("playrecord-%s.txt", "playrec-%s.txt"), savefile_base);
315 path_build(buf, sizeof(buf), ANGBAND_DIR_USER, file_name);
317 if (creature_ptr->pclass == CLASS_WARRIOR || creature_ptr->pclass == CLASS_MONK || creature_ptr->pclass == CLASS_SAMURAI || creature_ptr->pclass == CLASS_BERSERKER)
318 strcpy(tmp, subtitle[randint0(MAX_SUBTITLE - 1)]);
319 else if (IS_WIZARD_CLASS(creature_ptr))
320 strcpy(tmp, subtitle[randint0(MAX_SUBTITLE - 1) + 1]);
321 else strcpy(tmp, subtitle[randint0(MAX_SUBTITLE - 2) + 1]);
324 sprintf(diary_title, "「%s%s%sの伝説 -%s-」", ap_ptr->title, ap_ptr->no ? "の" : "", creature_ptr->name, tmp);
326 sprintf(diary_title, "Legend of %s %s '%s'", ap_ptr->title, creature_ptr->name, tmp);
329 (void)show_file(creature_ptr, FALSE, buf, diary_title, -1, 0);
334 * @brief 日記に任意の内容を表記するコマンドのメインルーチン /
337 static void add_diary_note(player_type *creature_ptr)
340 char bunshou[80] = "\0";
341 if (get_string(_("内容: ", "diary note: "), tmp, 79))
343 strcpy(bunshou, tmp);
344 exe_write_diary(creature_ptr, DIARY_DESCRIPTION, 0, bunshou);
349 * @brief 最後に取得したアイテムの情報を日記に追加するメインルーチン /
352 static void do_cmd_last_get(player_type *creaute_ptr)
354 if (record_o_name[0] == '\0') return;
357 sprintf(buf, _("%sの入手を記録します。", "Do you really want to record getting %s? "), record_o_name);
358 if (!get_check(buf)) return;
360 GAME_TURN turn_tmp = current_world_ptr->game_turn;
361 current_world_ptr->game_turn = record_turn;
362 sprintf(buf, _("%sを手に入れた。", "discover %s."), record_o_name);
363 exe_write_diary(creaute_ptr, DIARY_DESCRIPTION, 0, buf);
364 current_world_ptr->game_turn = turn_tmp;
369 * @brief ファイル中の全日記記録を消去する /
372 static void do_cmd_erase_diary(void)
374 GAME_TEXT file_name[MAX_NLEN];
378 if (!get_check(_("本当に記録を消去しますか?", "Do you really want to delete all your record? "))) return;
379 sprintf(file_name, _("playrecord-%s.txt", "playrec-%s.txt"), savefile_base);
380 path_build(buf, sizeof(buf), ANGBAND_DIR_USER, file_name);
383 fff = my_fopen(buf, "w");
387 msg_format(_("記録を消去しました。", "deleted record."));
391 msg_format(_("%s の消去に失敗しました。", "failed to delete %s."), buf);
400 * @param crerature_ptr プレーヤーへの参照ポインタ
403 void do_cmd_diary(player_type *creature_ptr)
405 FILE_TYPE(FILE_TYPE_TEXT);
411 prt(_("[ 記録の設定 ]", "[ Play Record ]"), 2, 0);
412 prt(_("(1) 記録を見る", "(1) Display your record"), 4, 5);
413 prt(_("(2) 文章を記録する", "(2) Add record"), 5, 5);
414 prt(_("(3) 直前に入手又は鑑定したものを記録する", "(3) Record the last item you got or identified"), 6, 5);
415 prt(_("(4) 記録を消去する", "(4) Delete your record"), 7, 5);
416 prt(_("(R) プレイ動画を記録する/中止する", "(R) Record playing movie / or stop it"), 9, 5);
417 prt(_("コマンド:", "Command: "), 18, 0);
419 if (i == ESCAPE) break;
424 display_diary(creature_ptr);
427 add_diary_note(creature_ptr);
430 do_cmd_last_get(creature_ptr);
433 do_cmd_erase_diary();
437 prepare_movie_hooks();
451 * @brief 画面を再描画するコマンドのメインルーチン
452 * Hack -- redraw the screen
453 * @param creature_ptr プレーヤーへの参照ポインタ
457 * This command performs various low level updates, clears all the "extra"
458 * windows, does a total redraw of the main window, and requests all of the
459 * interesting updates and redraws that I can think of.
461 * This command is also used to "instantiate" the results of the user
462 * selecting various things, such as graphics mode, so it must call
463 * the "TERM_XTRA_REACT" hook before redrawing the windows.
466 void do_cmd_redraw(player_type *creature_ptr)
468 Term_xtra(TERM_XTRA_REACT, 0);
470 creature_ptr->update |= (PU_COMBINE | PU_REORDER);
471 creature_ptr->update |= (PU_TORCH);
472 creature_ptr->update |= (PU_BONUS | PU_HP | PU_MANA | PU_SPELLS);
473 creature_ptr->update |= (PU_UN_VIEW | PU_UN_LITE);
474 creature_ptr->update |= (PU_VIEW | PU_LITE | PU_MON_LITE);
475 creature_ptr->update |= (PU_MONSTERS);
477 creature_ptr->redraw |= (PR_WIPE | PR_BASIC | PR_EXTRA | PR_MAP | PR_EQUIPPY);
479 creature_ptr->window |= (PW_INVEN | PW_EQUIP | PW_SPELL | PW_PLAYER);
480 creature_ptr->window |= (PW_MESSAGE | PW_OVERHEAD | PW_DUNGEON | PW_MONSTER | PW_OBJECT);
483 handle_stuff(creature_ptr);
484 if (creature_ptr->prace == RACE_ANDROID) calc_android_exp(creature_ptr);
487 for (int j = 0; j < 8; j++)
489 if (!angband_term[j]) continue;
491 Term_activate(angband_term[j]);
500 * @brief プレイヤーのステータス表示
503 void do_cmd_player_status(player_type *creature_ptr)
511 display_player(creature_ptr, mode, map_name);
516 display_player(creature_ptr, mode, map_name);
519 Term_putstr(2, 23, -1, TERM_WHITE,
520 _("['c'で名前変更, 'f'でファイルへ書出, 'h'でモード変更, ESCで終了]", "['c' to change name, 'f' to file, 'h' to change mode, or ESC]"));
522 if (c == ESCAPE) break;
526 get_name(creature_ptr);
527 process_player_name(creature_ptr, FALSE);
531 sprintf(tmp, "%s.txt", creature_ptr->base_name);
532 if (get_string(_("ファイル名: ", "File name: "), tmp, 80))
534 if (tmp[0] && (tmp[0] != ' '))
536 file_character(creature_ptr, tmp, update_playtime, display_player, map_name);
553 creature_ptr->redraw |= (PR_WIPE | PR_BASIC | PR_EXTRA | PR_MAP | PR_EQUIPPY);
554 handle_stuff(creature_ptr);
559 * @brief 最近表示されたメッセージを再表示するコマンドのメインルーチン
560 * Recall the most recent message
563 void do_cmd_message_one(void)
565 prt(format("> %s", message_str(0)), 0, 0);
570 * @brief メッセージのログを表示するコマンドのメインルーチン
571 * Recall the most recent message
575 * Show previous messages to the user -BEN-
577 * The screen format uses line 0 and 23 for headers and prompts,
578 * skips line 1 and 22, and uses line 2 thru 21 for old messages.
580 * This command shows you which commands you are viewing, and allows
581 * you to "search" for strings in the recall.
583 * Note that messages may be longer than 80 characters, but they are
584 * displayed using "infinite" length, with a special sub-command to
585 * "slide" the virtual display to the left or right.
587 * Attempt to only hilite the matching portions of the string.
590 void do_cmd_messages(int num_now)
595 concptr shower = NULL;
597 Term_get_size(&wid, &hgt);
598 int num_lines = hgt - 4;
599 strcpy(finder_str, "");
600 strcpy(shower_str, "");
601 int n = message_num();
609 for (j = 0; (j < num_lines) && (i + j < n); j++)
611 concptr msg = message_str(i + j);
612 c_prt((i + j < num_now ? TERM_WHITE : TERM_SLATE), msg, num_lines + 1 - j, 0);
613 if (!shower || !shower[0]) continue;
616 while ((str = my_strstr(str, shower)) != NULL)
618 int len = strlen(shower);
619 Term_putstr(str - msg, num_lines + 1 - j, len, TERM_YELLOW, shower);
624 for (; j < num_lines; j++)
625 Term_erase(0, num_lines + 1 - j, 255);
627 prt(format(_("以前のメッセージ %d-%d 全部で(%d)", "Message Recall (%d-%d of %d)"),
628 i, i + j - 1, n), 0, 0);
629 prt(_("[ 'p' で更に古いもの, 'n' で更に新しいもの, '/' で検索, ESC で中断 ]",
630 "[Press 'p' for older, 'n' for newer, ..., or ESCAPE]"), hgt - 1, 0);
631 skey = inkey_special(TRUE);
632 if (skey == ESCAPE) break;
638 prt(_("強調: ", "Show: "), hgt - 1, 0);
639 strcpy(back_str, shower_str);
640 if (askfor(shower_str, 80))
641 shower = shower_str[0] ? shower_str : NULL;
643 strcpy(shower_str, back_str);
649 prt(_("検索: ", "Find: "), hgt - 1, 0);
650 strcpy(back_str, finder_str);
651 if (!askfor(finder_str, 80))
653 strcpy(finder_str, back_str);
656 else if (!finder_str[0])
663 for (int z = i + 1; z < n; z++)
665 concptr msg = message_str(z);
666 if (my_strstr(msg, finder_str))
686 i = MIN(i + 1, n - num_lines);
689 i = MIN(i + 10, n - num_lines);
695 i = MIN(i + num_lines, n - num_lines);
700 i = MAX(0, i - num_lines);
719 * @brief prefファイルを選択して処理する /
720 * Ask for a "user pref line" and process it
721 * @param creature_ptr プレーヤーへの参照ポインタ
724 * Allow absolute file names?
726 void do_cmd_pref(player_type *creature_ptr)
730 if (!get_string(_("設定変更コマンド: ", "Pref: "), buf, 80)) return;
732 (void)interpret_pref_file(creature_ptr, buf);
737 * @brief 自動拾い設定ファイルをロードするコマンドのメインルーチン /
738 * @param creature_ptr プレーヤーへの参照ポインタ
741 void do_cmd_reload_autopick(player_type *creature_ptr)
743 if (!get_check(_("自動拾い設定ファイルをロードしますか? ", "Reload auto-pick preference file? ")))
746 autopick_load_pref(creature_ptr, TRUE);
751 * @brief マクロ情報をprefファイルに保存する /
755 static errr macro_dump(concptr fname)
757 static concptr mark = "Macro Dump";
759 path_build(buf, sizeof(buf), ANGBAND_DIR_USER, fname);
760 FILE_TYPE(FILE_TYPE_TEXT);
761 if (!open_auto_dump(buf, mark)) return -1;
763 auto_dump_printf(_("\n# 自動マクロセーブ\n\n", "\n# Automatic macro dump\n\n"));
764 for (int i = 0; i < macro__num; i++)
766 ascii_to_text(buf, macro__act[i]);
767 auto_dump_printf("A:%s\n", buf);
768 ascii_to_text(buf, macro__pat[i]);
769 auto_dump_printf("P:%s\n", buf);
770 auto_dump_printf("\n");
779 * @brief マクロのトリガーキーを取得する /
780 * Hack -- ask for a "trigger" (see below)
781 * @param buf キー表記を保管するバッファ
785 * Note the complex use of the "inkey()" function from "util.c".
787 * Note that both "flush()" calls are extremely important.
790 static void do_cmd_macro_aux(char *buf)
807 ascii_to_text(tmp, buf);
808 Term_addstr(-1, TERM_WHITE, tmp);
813 * @brief マクロのキー表記からアスキーコードを得てターミナルに表示する /
814 * Hack -- ask for a keymap "trigger" (see below)
815 * @param buf キー表記を取得するバッファ
819 * Note that both "flush()" calls are extremely important. This may
820 * no longer be true, since "util.c" is much simpler now.
823 static void do_cmd_macro_aux_keymap(char *buf)
829 ascii_to_text(tmp, buf);
830 Term_addstr(-1, TERM_WHITE, tmp);
836 * @brief キーマップをprefファイルにダンプする /
837 * Hack -- append all keymaps to the given file
838 * @param fname ファイルネーム
842 static errr keymap_dump(concptr fname)
844 static concptr mark = "Keymap Dump";
848 if (rogue_like_commands)
850 mode = KEYMAP_MODE_ROGUE;
854 mode = KEYMAP_MODE_ORIG;
857 path_build(buf, sizeof(buf), ANGBAND_DIR_USER, fname);
858 FILE_TYPE(FILE_TYPE_TEXT);
859 if (!open_auto_dump(buf, mark)) return -1;
861 auto_dump_printf(_("\n# 自動キー配置セーブ\n\n", "\n# Automatic keymap dump\n\n"));
862 for (int i = 0; i < 256; i++)
865 act = keymap_act[mode][i];
870 ascii_to_text(key, buf);
871 ascii_to_text(buf, act);
872 auto_dump_printf("A:%s\n", buf);
873 auto_dump_printf("C:%d:%s\n", mode, key);
882 * @brief マクロを設定するコマンドのメインルーチン /
883 * Interact with "macros"
887 * Note that the macro "action" must be defined before the trigger.
889 * Could use some helpful instructions on this page.
892 void do_cmd_macros(player_type *creature_ptr)
897 if (rogue_like_commands)
899 mode = KEYMAP_MODE_ROGUE;
903 mode = KEYMAP_MODE_ORIG;
906 FILE_TYPE(FILE_TYPE_TEXT);
911 prt(_("[ マクロの設定 ]", "Interact with Macros"), 2, 0);
912 prt(_("マクロ行動が(もしあれば)下に表示されます:", "Current action (if any) shown below:"), 20, 0);
913 ascii_to_text(buf, macro__buf);
916 prt(_("(1) ユーザー設定ファイルのロード", "(1) Load a user pref file"), 4, 5);
917 prt(_("(2) ファイルにマクロを追加", "(2) Append macros to a file"), 5, 5);
918 prt(_("(3) マクロの確認", "(3) Query a macro"), 6, 5);
919 prt(_("(4) マクロの作成", "(4) Create a macro"), 7, 5);
920 prt(_("(5) マクロの削除", "(5) Remove a macro"), 8, 5);
921 prt(_("(6) ファイルにキー配置を追加", "(6) Append keymaps to a file"), 9, 5);
922 prt(_("(7) キー配置の確認", "(7) Query a keymap"), 10, 5);
923 prt(_("(8) キー配置の作成", "(8) Create a keymap"), 11, 5);
924 prt(_("(9) キー配置の削除", "(9) Remove a keymap"), 12, 5);
925 prt(_("(0) マクロ行動の入力", "(0) Enter a new action"), 13, 5);
927 prt(_("コマンド: ", "Command: "), 16, 0);
929 if (i == ESCAPE) break;
933 prt(_("コマンド: ユーザー設定ファイルのロード", "Command: Load a user pref file"), 16, 0);
934 prt(_("ファイル: ", "File: "), 18, 0);
935 sprintf(tmp, "%s.prf", creature_ptr->base_name);
936 if (!askfor(tmp, 80)) continue;
938 errr err = process_pref_file(creature_ptr, tmp);
940 msg_format(_("標準の設定ファイル'%s'を読み込みました。", "Loaded default '%s'."), tmp);
942 msg_format(_("'%s'の読み込みに失敗しました!", "Failed to load '%s'!"), tmp);
944 msg_format(_("'%s'を読み込みました。", "Loaded '%s'."), tmp);
948 prt(_("コマンド: マクロをファイルに追加する", "Command: Append macros to a file"), 16, 0);
949 prt(_("ファイル: ", "File: "), 18, 0);
950 sprintf(tmp, "%s.prf", creature_ptr->base_name);
951 if (!askfor(tmp, 80)) continue;
953 (void)macro_dump(tmp);
954 msg_print(_("マクロを追加しました。", "Appended macros."));
958 prt(_("コマンド: マクロの確認", "Command: Query a macro"), 16, 0);
959 prt(_("トリガーキー: ", "Trigger: "), 18, 0);
960 do_cmd_macro_aux(buf);
961 int k = macro_find_exact(buf);
964 msg_print(_("そのキーにはマクロは定義されていません。", "Found no macro."));
968 strcpy(macro__buf, macro__act[k]);
969 ascii_to_text(buf, macro__buf);
971 msg_print(_("マクロを確認しました。", "Found a macro."));
976 prt(_("コマンド: マクロの作成", "Command: Create a macro"), 16, 0);
977 prt(_("トリガーキー: ", "Trigger: "), 18, 0);
978 do_cmd_macro_aux(buf);
980 c_prt(TERM_L_RED, _("カーソルキーの左右でカーソル位置を移動。BackspaceかDeleteで一文字削除。",
981 "Press Left/Right arrow keys to move cursor. Backspace/Delete to delete a char."), 22, 0);
982 prt(_("マクロ行動: ", "Action: "), 20, 0);
983 ascii_to_text(tmp, macro__buf);
986 text_to_ascii(macro__buf, tmp);
987 macro_add(buf, macro__buf);
988 msg_print(_("マクロを追加しました。", "Added a macro."));
993 prt(_("コマンド: マクロの削除", "Command: Remove a macro"), 16, 0);
994 prt(_("トリガーキー: ", "Trigger: "), 18, 0);
995 do_cmd_macro_aux(buf);
997 msg_print(_("マクロを削除しました。", "Removed a macro."));
1001 prt(_("コマンド: キー配置をファイルに追加する", "Command: Append keymaps to a file"), 16, 0);
1002 prt(_("ファイル: ", "File: "), 18, 0);
1003 sprintf(tmp, "%s.prf", creature_ptr->base_name);
1004 if (!askfor(tmp, 80)) continue;
1006 (void)keymap_dump(tmp);
1007 msg_print(_("キー配置を追加しました。", "Appended keymaps."));
1011 prt(_("コマンド: キー配置の確認", "Command: Query a keymap"), 16, 0);
1012 prt(_("押すキー: ", "Keypress: "), 18, 0);
1013 do_cmd_macro_aux_keymap(buf);
1014 concptr act = keymap_act[mode][(byte)(buf[0])];
1017 msg_print(_("キー配置は定義されていません。", "Found no keymap."));
1021 strcpy(macro__buf, act);
1022 ascii_to_text(buf, macro__buf);
1024 msg_print(_("キー配置を確認しました。", "Found a keymap."));
1029 prt(_("コマンド: キー配置の作成", "Command: Create a keymap"), 16, 0);
1030 prt(_("押すキー: ", "Keypress: "), 18, 0);
1031 do_cmd_macro_aux_keymap(buf);
1033 c_prt(TERM_L_RED, _("カーソルキーの左右でカーソル位置を移動。BackspaceかDeleteで一文字削除。",
1034 "Press Left/Right arrow keys to move cursor. Backspace/Delete to delete a char."), 22, 0);
1035 prt(_("行動: ", "Action: "), 20, 0);
1036 ascii_to_text(tmp, macro__buf);
1037 if (askfor(tmp, 80))
1039 text_to_ascii(macro__buf, tmp);
1040 string_free(keymap_act[mode][(byte)(buf[0])]);
1041 keymap_act[mode][(byte)(buf[0])] = string_make(macro__buf);
1042 msg_print(_("キー配置を追加しました。", "Added a keymap."));
1047 prt(_("コマンド: キー配置の削除", "Command: Remove a keymap"), 16, 0);
1048 prt(_("押すキー: ", "Keypress: "), 18, 0);
1049 do_cmd_macro_aux_keymap(buf);
1050 string_free(keymap_act[mode][(byte)(buf[0])]);
1051 keymap_act[mode][(byte)(buf[0])] = NULL;
1052 msg_print(_("キー配置を削除しました。", "Removed a keymap."));
1056 prt(_("コマンド: マクロ行動の入力", "Command: Enter a new action"), 16, 0);
1058 c_prt(TERM_L_RED, _("カーソルキーの左右でカーソル位置を移動。BackspaceかDeleteで一文字削除。",
1059 "Press Left/Right arrow keys to move cursor. Backspace/Delete to delete a char."), 22, 0);
1060 prt(_("マクロ行動: ", "Action: "), 20, 0);
1062 if (!askfor(buf, 80)) continue;
1064 text_to_ascii(macro__buf, buf);
1079 * @brief キャラクタ色の明暗表現
1081 static concptr lighting_level_str[F_LIT_MAX] =
1083 _("標準色", "standard"),
1084 _("明色", "brightly lit"),
1085 _("暗色", "darkened"),
1090 * @brief キャラクタのビジュアルIDを変更する際の対象指定関数
1091 * @param i 指定対象となるキャラクタコード
1092 * @param num 指定されたビジュアルIDを返す参照ポインタ
1093 * @param max ビジュアルIDの最大数
1094 * @return 指定が実際に行われた場合TRUE、キャンセルされた場合FALSE
1096 static bool cmd_visuals_aux(int i, IDX *num, IDX max)
1101 sprintf(str, "%d", *num);
1102 if (!get_string(format("Input new number(0-%d): ", max - 1), str, 4))
1105 IDX tmp = (IDX)strtol(str, NULL, 0);
1106 if (tmp >= 0 && tmp < max)
1109 else if (isupper(i))
1110 *num = (*num + max - 1) % max;
1112 *num = (*num + 1) % max;
1118 * @brief キャラクタの変更メニュー表示
1119 * @param choice_msg 選択メッセージ
1122 static void print_visuals_menu(concptr choice_msg)
1124 prt(_("[ 画面表示の設定 ]", "Interact with Visuals"), 1, 0);
1125 prt(_("(0) ユーザー設定ファイルのロード", "(0) Load a user pref file"), 3, 5);
1126 prt(_("(1) モンスターの 色/文字 をファイルに書き出す", "(1) Dump monster attr/chars"), 4, 5);
1127 prt(_("(2) アイテムの 色/文字 をファイルに書き出す", "(2) Dump object attr/chars"), 5, 5);
1128 prt(_("(3) 地形の 色/文字 をファイルに書き出す", "(3) Dump feature attr/chars"), 6, 5);
1129 prt(_("(4) モンスターの 色/文字 を変更する (数値操作)", "(4) Change monster attr/chars (numeric operation)"), 7, 5);
1130 prt(_("(5) アイテムの 色/文字 を変更する (数値操作)", "(5) Change object attr/chars (numeric operation)"), 8, 5);
1131 prt(_("(6) 地形の 色/文字 を変更する (数値操作)", "(6) Change feature attr/chars (numeric operation)"), 9, 5);
1132 prt(_("(7) モンスターの 色/文字 を変更する (シンボルエディタ)", "(7) Change monster attr/chars (visual mode)"), 10, 5);
1133 prt(_("(8) アイテムの 色/文字 を変更する (シンボルエディタ)", "(8) Change object attr/chars (visual mode)"), 11, 5);
1134 prt(_("(9) 地形の 色/文字 を変更する (シンボルエディタ)", "(9) Change feature attr/chars (visual mode)"), 12, 5);
1135 prt(_("(R) 画面表示方法の初期化", "(R) Reset visuals"), 13, 5);
1136 prt(format("コマンド: %s", choice_msg ? choice_msg : _("", "")), 15, 0);
1141 * Interact with "visuals"
1143 void do_cmd_visuals(player_type *creature_ptr)
1147 bool need_redraw = FALSE;
1148 concptr empty_symbol = "<< ? >>";
1149 if (use_bigtile) empty_symbol = "<< ?? >>";
1151 FILE_TYPE(FILE_TYPE_TEXT);
1156 print_visuals_menu(NULL);
1158 if (i == ESCAPE) break;
1164 prt(_("コマンド: ユーザー設定ファイルのロード", "Command: Load a user pref file"), 15, 0);
1165 prt(_("ファイル: ", "File: "), 17, 0);
1166 sprintf(tmp, "%s.prf", creature_ptr->base_name);
1167 if (!askfor(tmp, 70)) continue;
1169 (void)process_pref_file(creature_ptr, tmp);
1175 static concptr mark = "Monster attr/chars";
1176 prt(_("コマンド: モンスターの[色/文字]をファイルに書き出します", "Command: Dump monster attr/chars"), 15, 0);
1177 prt(_("ファイル: ", "File: "), 17, 0);
1178 sprintf(tmp, "%s.prf", creature_ptr->base_name);
1179 if (!askfor(tmp, 70)) continue;
1181 path_build(buf, sizeof(buf), ANGBAND_DIR_USER, tmp);
1182 if (!open_auto_dump(buf, mark)) continue;
1184 auto_dump_printf(_("\n# モンスターの[色/文字]の設定\n\n", "\n# Monster attr/char definitions\n\n"));
1185 for (i = 0; i < max_r_idx; i++)
1187 monster_race *r_ptr = &r_info[i];
1188 if (!r_ptr->name) continue;
1190 auto_dump_printf("# %s\n", (r_name + r_ptr->name));
1191 auto_dump_printf("R:%d:0x%02X/0x%02X\n\n", i,
1192 (byte)(r_ptr->x_attr), (byte)(r_ptr->x_char));
1196 msg_print(_("モンスターの[色/文字]をファイルに書き出しました。", "Dumped monster attr/chars."));
1201 static concptr mark = "Object attr/chars";
1202 prt(_("コマンド: アイテムの[色/文字]をファイルに書き出します", "Command: Dump object attr/chars"), 15, 0);
1203 prt(_("ファイル: ", "File: "), 17, 0);
1204 sprintf(tmp, "%s.prf", creature_ptr->base_name);
1205 if (!askfor(tmp, 70)) continue;
1207 path_build(buf, sizeof(buf), ANGBAND_DIR_USER, tmp);
1208 if (!open_auto_dump(buf, mark)) continue;
1210 auto_dump_printf(_("\n# アイテムの[色/文字]の設定\n\n", "\n# Object attr/char definitions\n\n"));
1211 for (KIND_OBJECT_IDX k_idx = 0; k_idx < max_k_idx; k_idx++)
1213 GAME_TEXT o_name[MAX_NLEN];
1214 object_kind *k_ptr = &k_info[k_idx];
1215 if (!k_ptr->name) continue;
1219 strip_name(o_name, k_idx);
1224 object_prep(&forge, k_idx);
1225 object_desc(creature_ptr, o_name, &forge, OD_FORCE_FLAVOR);
1228 auto_dump_printf("# %s\n", o_name);
1229 auto_dump_printf("K:%d:0x%02X/0x%02X\n\n", (int)k_idx,
1230 (byte)(k_ptr->x_attr), (byte)(k_ptr->x_char));
1234 msg_print(_("アイテムの[色/文字]をファイルに書き出しました。", "Dumped object attr/chars."));
1239 static concptr mark = "Feature attr/chars";
1240 prt(_("コマンド: 地形の[色/文字]をファイルに書き出します", "Command: Dump feature attr/chars"), 15, 0);
1241 prt(_("ファイル: ", "File: "), 17, 0);
1242 sprintf(tmp, "%s.prf", creature_ptr->base_name);
1243 if (!askfor(tmp, 70)) continue;
1245 path_build(buf, sizeof(buf), ANGBAND_DIR_USER, tmp);
1246 if (!open_auto_dump(buf, mark)) continue;
1248 auto_dump_printf(_("\n# 地形の[色/文字]の設定\n\n", "\n# Feature attr/char definitions\n\n"));
1249 for (i = 0; i < max_f_idx; i++)
1251 feature_type *f_ptr = &f_info[i];
1252 if (!f_ptr->name) continue;
1253 if (f_ptr->mimic != i) continue;
1255 auto_dump_printf("# %s\n", (f_name + f_ptr->name));
1256 auto_dump_printf("F:%d:0x%02X/0x%02X:0x%02X/0x%02X:0x%02X/0x%02X\n\n", i,
1257 (byte)(f_ptr->x_attr[F_LIT_STANDARD]), (byte)(f_ptr->x_char[F_LIT_STANDARD]),
1258 (byte)(f_ptr->x_attr[F_LIT_LITE]), (byte)(f_ptr->x_char[F_LIT_LITE]),
1259 (byte)(f_ptr->x_attr[F_LIT_DARK]), (byte)(f_ptr->x_char[F_LIT_DARK]));
1263 msg_print(_("地形の[色/文字]をファイルに書き出しました。", "Dumped feature attr/chars."));
1268 static concptr choice_msg = _("モンスターの[色/文字]を変更します", "Change monster attr/chars");
1269 static MONRACE_IDX r = 0;
1270 prt(format(_("コマンド: %s", "Command: %s"), choice_msg), 15, 0);
1273 monster_race *r_ptr = &r_info[r];
1277 TERM_COLOR da = r_ptr->d_attr;
1278 byte dc = r_ptr->d_char;
1279 TERM_COLOR ca = r_ptr->x_attr;
1280 byte cc = r_ptr->x_char;
1282 Term_putstr(5, 17, -1, TERM_WHITE,
1283 format(_("モンスター = %d, 名前 = %-40.40s", "Monster = %d, Name = %-40.40s"), r, (r_name + r_ptr->name)));
1284 Term_putstr(10, 19, -1, TERM_WHITE,
1285 format(_("初期値 色 / 文字 = %3u / %3u", "Default attr/char = %3u / %3u"), da, dc));
1286 Term_putstr(40, 19, -1, TERM_WHITE, empty_symbol);
1287 Term_queue_bigchar(43, 19, da, dc, 0, 0);
1288 Term_putstr(10, 20, -1, TERM_WHITE,
1289 format(_("現在値 色 / 文字 = %3u / %3u", "Current attr/char = %3u / %3u"), ca, cc));
1290 Term_putstr(40, 20, -1, TERM_WHITE, empty_symbol);
1291 Term_queue_bigchar(43, 20, ca, cc, 0, 0);
1292 Term_putstr(0, 22, -1, TERM_WHITE,
1293 _("コマンド (n/N/^N/a/A/^A/c/C/^C/v/V/^V): ", "Command (n/N/^N/a/A/^A/c/C/^C/v/V/^V): "));
1295 if (i == ESCAPE) break;
1297 if (iscntrl(i)) c = 'a' + i - KTRL('A');
1298 else if (isupper(i)) c = 'a' + i - 'A';
1308 if (!cmd_visuals_aux(i, &r, max_r_idx))
1313 } while (!r_info[r].name);
1318 t = (int)r_ptr->x_attr;
1319 (void)cmd_visuals_aux(i, &t, 256);
1320 r_ptr->x_attr = (byte)t;
1324 t = (int)r_ptr->x_char;
1325 (void)cmd_visuals_aux(i, &t, 256);
1326 r_ptr->x_char = (byte)t;
1330 do_cmd_knowledge_monsters(creature_ptr, &need_redraw, TRUE, r);
1332 print_visuals_menu(choice_msg);
1341 static concptr choice_msg = _("アイテムの[色/文字]を変更します", "Change object attr/chars");
1343 prt(format(_("コマンド: %s", "Command: %s"), choice_msg), 15, 0);
1346 object_kind *k_ptr = &k_info[k];
1350 TERM_COLOR da = k_ptr->d_attr;
1351 SYMBOL_CODE dc = k_ptr->d_char;
1352 TERM_COLOR ca = k_ptr->x_attr;
1353 SYMBOL_CODE cc = k_ptr->x_char;
1355 Term_putstr(5, 17, -1, TERM_WHITE,
1356 format(_("アイテム = %d, 名前 = %-40.40s", "Object = %d, Name = %-40.40s"),
1357 k, k_name + (!k_ptr->flavor ? k_ptr->name : k_ptr->flavor_name)));
1358 Term_putstr(10, 19, -1, TERM_WHITE,
1359 format(_("初期値 色 / 文字 = %3d / %3d", "Default attr/char = %3d / %3d"), da, dc));
1360 Term_putstr(40, 19, -1, TERM_WHITE, empty_symbol);
1361 Term_queue_bigchar(43, 19, da, dc, 0, 0);
1362 Term_putstr(10, 20, -1, TERM_WHITE,
1363 format(_("現在値 色 / 文字 = %3d / %3d", "Current attr/char = %3d / %3d"), ca, cc));
1364 Term_putstr(40, 20, -1, TERM_WHITE, empty_symbol);
1365 Term_queue_bigchar(43, 20, ca, cc, 0, 0);
1366 Term_putstr(0, 22, -1, TERM_WHITE,
1367 _("コマンド (n/N/^N/a/A/^A/c/C/^C/v/V/^V): ", "Command (n/N/^N/a/A/^A/c/C/^C/v/V/^V): "));
1370 if (i == ESCAPE) break;
1372 if (iscntrl(i)) c = 'a' + i - KTRL('A');
1373 else if (isupper(i)) c = 'a' + i - 'A';
1383 if (!cmd_visuals_aux(i, &k, max_k_idx))
1388 } while (!k_info[k].name);
1393 t = (int)k_ptr->x_attr;
1394 (void)cmd_visuals_aux(i, &t, 256);
1395 k_ptr->x_attr = (byte)t;
1399 t = (int)k_ptr->x_char;
1400 (void)cmd_visuals_aux(i, &t, 256);
1401 k_ptr->x_char = (byte)t;
1405 do_cmd_knowledge_objects(creature_ptr, &need_redraw, TRUE, k);
1407 print_visuals_menu(choice_msg);
1416 static concptr choice_msg = _("地形の[色/文字]を変更します", "Change feature attr/chars");
1418 static IDX lighting_level = F_LIT_STANDARD;
1419 prt(format(_("コマンド: %s", "Command: %s"), choice_msg), 15, 0);
1422 feature_type *f_ptr = &f_info[f];
1426 TERM_COLOR da = f_ptr->d_attr[lighting_level];
1427 byte dc = f_ptr->d_char[lighting_level];
1428 TERM_COLOR ca = f_ptr->x_attr[lighting_level];
1429 byte cc = f_ptr->x_char[lighting_level];
1432 Term_putstr(5, 17, -1, TERM_WHITE,
1433 format(_("地形 = %d, 名前 = %s, 明度 = %s", "Terrain = %d, Name = %s, Lighting = %s"),
1434 f, (f_name + f_ptr->name), lighting_level_str[lighting_level]));
1435 Term_putstr(10, 19, -1, TERM_WHITE,
1436 format(_("初期値 色 / 文字 = %3d / %3d", "Default attr/char = %3d / %3d"), da, dc));
1437 Term_putstr(40, 19, -1, TERM_WHITE, empty_symbol);
1438 Term_queue_bigchar(43, 19, da, dc, 0, 0);
1439 Term_putstr(10, 20, -1, TERM_WHITE,
1440 format(_("現在値 色 / 文字 = %3d / %3d", "Current attr/char = %3d / %3d"), ca, cc));
1441 Term_putstr(40, 20, -1, TERM_WHITE, empty_symbol);
1442 Term_queue_bigchar(43, 20, ca, cc, 0, 0);
1443 Term_putstr(0, 22, -1, TERM_WHITE,
1444 _("コマンド (n/N/^N/a/A/^A/c/C/^C/l/L/^L/d/D/^D/v/V/^V): ", "Command (n/N/^N/a/A/^A/c/C/^C/l/L/^L/d/D/^D/v/V/^V): "));
1447 if (i == ESCAPE) break;
1449 if (iscntrl(i)) c = 'a' + i - KTRL('A');
1450 else if (isupper(i)) c = 'a' + i - 'A';
1460 if (!cmd_visuals_aux(i, &f, max_f_idx))
1465 } while (!f_info[f].name || (f_info[f].mimic != f));
1470 t = (int)f_ptr->x_attr[lighting_level];
1471 (void)cmd_visuals_aux(i, &t, 256);
1472 f_ptr->x_attr[lighting_level] = (byte)t;
1476 t = (int)f_ptr->x_char[lighting_level];
1477 (void)cmd_visuals_aux(i, &t, 256);
1478 f_ptr->x_char[lighting_level] = (byte)t;
1482 (void)cmd_visuals_aux(i, &lighting_level, F_LIT_MAX);
1485 apply_default_feat_lighting(f_ptr->x_attr, f_ptr->x_char);
1489 do_cmd_knowledge_features(&need_redraw, TRUE, f, &lighting_level);
1491 print_visuals_menu(choice_msg);
1499 do_cmd_knowledge_monsters(creature_ptr, &need_redraw, TRUE, -1);
1502 do_cmd_knowledge_objects(creature_ptr, &need_redraw, TRUE, -1);
1506 IDX lighting_level = F_LIT_STANDARD;
1507 do_cmd_knowledge_features(&need_redraw, TRUE, -1, &lighting_level);
1512 reset_visuals(creature_ptr);
1513 msg_print(_("画面上の[色/文字]を初期値にリセットしました。", "Visual attr/char tables reset."));
1525 if (need_redraw) do_cmd_redraw(creature_ptr);
1530 * Interact with "colors"
1532 void do_cmd_colors(player_type *creature_ptr)
1537 FILE_TYPE(FILE_TYPE_TEXT);
1542 prt(_("[ カラーの設定 ]", "Interact with Colors"), 2, 0);
1543 prt(_("(1) ユーザー設定ファイルのロード", "(1) Load a user pref file"), 4, 5);
1544 prt(_("(2) カラーの設定をファイルに書き出す", "(2) Dump colors"), 5, 5);
1545 prt(_("(3) カラーの設定を変更する", "(3) Modify colors"), 6, 5);
1546 prt(_("コマンド: ", "Command: "), 8, 0);
1548 if (i == ESCAPE) break;
1552 prt(_("コマンド: ユーザー設定ファイルをロードします", "Command: Load a user pref file"), 8, 0);
1553 prt(_("ファイル: ", "File: "), 10, 0);
1554 sprintf(tmp, "%s.prf", creature_ptr->base_name);
1555 if (!askfor(tmp, 70)) continue;
1557 (void)process_pref_file(creature_ptr, tmp);
1558 Term_xtra(TERM_XTRA_REACT, 0);
1563 static concptr mark = "Colors";
1564 prt(_("コマンド: カラーの設定をファイルに書き出します", "Command: Dump colors"), 8, 0);
1565 prt(_("ファイル: ", "File: "), 10, 0);
1566 sprintf(tmp, "%s.prf", creature_ptr->base_name);
1567 if (!askfor(tmp, 70)) continue;
1569 path_build(buf, sizeof(buf), ANGBAND_DIR_USER, tmp);
1570 if (!open_auto_dump(buf, mark)) continue;
1572 auto_dump_printf(_("\n# カラーの設定\n\n", "\n# Color redefinitions\n\n"));
1573 for (i = 0; i < 256; i++)
1575 int kv = angband_color_table[i][0];
1576 int rv = angband_color_table[i][1];
1577 int gv = angband_color_table[i][2];
1578 int bv = angband_color_table[i][3];
1580 concptr name = _("未知", "unknown");
1581 if (!kv && !rv && !gv && !bv) continue;
1583 if (i < 16) name = color_names[i];
1585 auto_dump_printf(_("# カラー '%s'\n", "# Color '%s'\n"), name);
1586 auto_dump_printf("V:%d:0x%02X:0x%02X:0x%02X:0x%02X\n\n",
1591 msg_print(_("カラーの設定をファイルに書き出しました。", "Dumped color redefinitions."));
1596 prt(_("コマンド: カラーの設定を変更します", "Command: Modify colors"), 8, 0);
1601 for (byte j = 0; j < 16; j++)
1603 Term_putstr(j * 4, 20, -1, a, "###");
1604 Term_putstr(j * 4, 22, -1, j, format("%3d", j));
1607 name = ((a < 16) ? color_names[a] : _("未定義", "undefined"));
1608 Term_putstr(5, 10, -1, TERM_WHITE,
1609 format(_("カラー = %d, 名前 = %s", "Color = %d, Name = %s"), a, name));
1610 Term_putstr(5, 12, -1, TERM_WHITE,
1611 format("K = 0x%02x / R,G,B = 0x%02x,0x%02x,0x%02x",
1612 angband_color_table[a][0],
1613 angband_color_table[a][1],
1614 angband_color_table[a][2],
1615 angband_color_table[a][3]));
1616 Term_putstr(0, 14, -1, TERM_WHITE,
1617 _("コマンド (n/N/k/K/r/R/g/G/b/B): ", "Command (n/N/k/K/r/R/g/G/b/B): "));
1619 if (i == ESCAPE) break;
1621 if (i == 'n') a = (byte)(a + 1);
1622 if (i == 'N') a = (byte)(a - 1);
1623 if (i == 'k') angband_color_table[a][0] = (byte)(angband_color_table[a][0] + 1);
1624 if (i == 'K') angband_color_table[a][0] = (byte)(angband_color_table[a][0] - 1);
1625 if (i == 'r') angband_color_table[a][1] = (byte)(angband_color_table[a][1] + 1);
1626 if (i == 'R') angband_color_table[a][1] = (byte)(angband_color_table[a][1] - 1);
1627 if (i == 'g') angband_color_table[a][2] = (byte)(angband_color_table[a][2] + 1);
1628 if (i == 'G') angband_color_table[a][2] = (byte)(angband_color_table[a][2] - 1);
1629 if (i == 'b') angband_color_table[a][3] = (byte)(angband_color_table[a][3] + 1);
1630 if (i == 'B') angband_color_table[a][3] = (byte)(angband_color_table[a][3] - 1);
1632 Term_xtra(TERM_XTRA_REACT, 0);
1649 * Note something in the message recall
1651 void do_cmd_note(void)
1655 if (!get_string(_("メモ: ", "Note: "), buf, 60)) return;
1656 if (!buf[0] || (buf[0] == ' ')) return;
1658 msg_format(_("メモ: %s", "Note: %s"), buf);
1663 * Mention the current version
1665 void do_cmd_version(void)
1667 #if FAKE_VER_EXTRA > 0
1668 msg_format(_("変愚蛮怒(Hengband) %d.%d.%d.%d", "You are playing Hengband %d.%d.%d.%d."),
1669 FAKE_VER_MAJOR - 10, FAKE_VER_MINOR, FAKE_VER_PATCH, FAKE_VER_EXTRA);
1671 msg_format(_("変愚蛮怒(Hengband) %d.%d.%d", "You are playing Hengband %d.%d.%d."),
1672 FAKE_VER_MAJOR - 10, FAKE_VER_MINOR, FAKE_VER_PATCH);
1678 * Note that "feeling" is set to zero unless some time has passed.
1679 * Note that this is done when the level is GENERATED, not entered.
1681 void do_cmd_feeling(player_type *creature_ptr)
1683 if (creature_ptr->wild_mode) return;
1685 if (creature_ptr->current_floor_ptr->inside_quest && !random_quest_number(creature_ptr, creature_ptr->current_floor_ptr->dun_level))
1687 msg_print(_("典型的なクエストのダンジョンのようだ。", "Looks like a typical quest level."));
1691 if (creature_ptr->town_num && !creature_ptr->current_floor_ptr->dun_level)
1693 if (!strcmp(town_info[creature_ptr->town_num].name, _("荒野", "wilderness")))
1695 msg_print(_("何かありそうな荒野のようだ。", "Looks like a strange wilderness."));
1699 msg_print(_("典型的な町のようだ。", "Looks like a typical town."));
1703 if (!creature_ptr->current_floor_ptr->dun_level)
1705 msg_print(_("典型的な荒野のようだ。", "Looks like a typical wilderness."));
1709 if (creature_ptr->muta3 & MUT3_GOOD_LUCK)
1710 msg_print(do_cmd_feeling_text_lucky[creature_ptr->feeling]);
1711 else if (IS_ECHIZEN(creature_ptr))
1712 msg_print(do_cmd_feeling_text_combat[creature_ptr->feeling]);
1714 msg_print(do_cmd_feeling_text[creature_ptr->feeling]);
1719 * todo 引数と戻り値について追記求む
1720 * Build a list of monster indexes in the given group.
1722 * mode & 0x01 : check for non-empty group
1723 * mode & 0x02 : visual operation only
1725 * @param creature_ptr プレーヤーへの参照ポインタ
1726 * @param grp_cur ???
1727 * @param mon_idx[] ???
1729 * @return The number of monsters in the group
1731 static IDX collect_monsters(player_type *creature_ptr, IDX grp_cur, IDX mon_idx[], BIT_FLAGS8 mode)
1733 concptr group_char = monster_group_char[grp_cur];
1734 bool grp_unique = (monster_group_char[grp_cur] == (char *)-1L);
1735 bool grp_riding = (monster_group_char[grp_cur] == (char *)-2L);
1736 bool grp_wanted = (monster_group_char[grp_cur] == (char *)-3L);
1737 bool grp_amberite = (monster_group_char[grp_cur] == (char *)-4L);
1740 for (IDX i = 0; i < max_r_idx; i++)
1742 monster_race *r_ptr = &r_info[i];
1743 if (!r_ptr->name) continue;
1744 if (!(mode & 0x02) && !cheat_know && !r_ptr->r_sights) continue;
1748 if (!(r_ptr->flags1 & RF1_UNIQUE)) continue;
1750 else if (grp_riding)
1752 if (!(r_ptr->flags7 & RF7_RIDING)) continue;
1754 else if (grp_wanted)
1756 bool wanted = FALSE;
1757 for (int j = 0; j < MAX_BOUNTY; j++)
1759 if (current_world_ptr->bounty_r_idx[j] == i || current_world_ptr->bounty_r_idx[j] - 10000 == i ||
1760 (creature_ptr->today_mon && creature_ptr->today_mon == i))
1767 if (!wanted) continue;
1769 else if (grp_amberite)
1771 if (!(r_ptr->flags3 & RF3_AMBERITE)) continue;
1775 if (!my_strchr(group_char, r_ptr->d_char)) continue;
1778 mon_idx[mon_cnt++] = i;
1779 if (mode & 0x01) break;
1782 mon_idx[mon_cnt] = -1;
1784 ang_sort(mon_idx, &dummy_why, mon_cnt, ang_sort_comp_monster_level, ang_sort_swap_hook);
1790 * Build a list of object indexes in the given group. Return the number
1791 * of objects in the group.
1793 * mode & 0x01 : check for non-empty group
1794 * mode & 0x02 : visual operation only
1796 static KIND_OBJECT_IDX collect_objects(int grp_cur, KIND_OBJECT_IDX object_idx[], BIT_FLAGS8 mode)
1798 KIND_OBJECT_IDX object_cnt = 0;
1799 byte group_tval = object_group_tval[grp_cur];
1800 for (KIND_OBJECT_IDX i = 0; i < max_k_idx; i++)
1802 object_kind *k_ptr = &k_info[i];
1803 if (!k_ptr->name) continue;
1807 if (!current_world_ptr->wizard)
1809 if (!k_ptr->flavor) continue;
1810 if (!k_ptr->aware) continue;
1814 for (int j = 0; j < 4; j++)
1815 k += k_ptr->chance[j];
1819 if (TV_LIFE_BOOK == group_tval)
1821 if (TV_LIFE_BOOK <= k_ptr->tval && k_ptr->tval <= TV_HEX_BOOK)
1823 object_idx[object_cnt++] = i;
1828 else if (k_ptr->tval == group_tval)
1830 object_idx[object_cnt++] = i;
1835 if (mode & 0x01) break;
1838 object_idx[object_cnt] = -1;
1844 * Description of each feature group.
1846 static concptr feature_group_text[] =
1854 * Build a list of feature indexes in the given group. Return the number
1855 * of features in the group.
1857 * mode & 0x01 : check for non-empty group
1859 static FEAT_IDX collect_features(FEAT_IDX *feat_idx, BIT_FLAGS8 mode)
1861 FEAT_IDX feat_cnt = 0;
1862 for (FEAT_IDX i = 0; i < max_f_idx; i++)
1864 feature_type *f_ptr = &f_info[i];
1865 if (!f_ptr->name) continue;
1866 if (f_ptr->mimic != i) continue;
1868 feat_idx[feat_cnt++] = i;
1869 if (mode & 0x01) break;
1872 feat_idx[feat_cnt] = -1;
1878 * Hack -- load a screen dump from a file
1880 void do_cmd_load_screen(void)
1883 SYMBOL_CODE c = ' ';
1888 Term_get_size(&wid, &hgt);
1889 path_build(buf, sizeof(buf), ANGBAND_DIR_USER, "dump.txt");
1890 fff = my_fopen(buf, "r");
1893 msg_format(_("%s を開くことができませんでした。", "Failed to open %s."), buf);
1900 for (TERM_LEN y = 0; okay; y++)
1902 if (!fgets(buf, 1024, fff)) okay = FALSE;
1904 if (buf[0] == '\n' || buf[0] == '\0') break;
1905 if (y >= hgt) continue;
1907 for (TERM_LEN x = 0; x < wid - 1; x++)
1909 if (buf[x] == '\n' || buf[x] == '\0') break;
1911 Term_draw(x, y, TERM_WHITE, buf[x]);
1915 for (TERM_LEN y = 0; okay; y++)
1917 if (!fgets(buf, 1024, fff)) okay = FALSE;
1919 if (buf[0] == '\n' || buf[0] == '\0') break;
1920 if (y >= hgt) continue;
1922 for (TERM_LEN x = 0; x < wid - 1; x++)
1924 if (buf[x] == '\n' || buf[x] == '\0') break;
1926 (void)(Term_what(x, y, &a, &c));
1927 for (int i = 0; i < 16; i++)
1929 if (hack[i] == buf[x]) a = (byte)i;
1932 Term_draw(x, y, a, c);
1937 prt(_("ファイルに書き出された画面(記念撮影)をロードしました。", "Screen dump loaded."), 0, 0);
1943 // todo なぜこんな中途半端なところに? defineも…
1944 concptr inven_res_label = _(" 酸電火冷毒光闇破轟獄因沌劣 盲怖乱痺透命感消復浮",
1945 " AcElFiCoPoLiDkShSoNtNxCaDi BlFeCfFaSeHlEpSdRgLv");
1947 #define IM_FLAG_STR _("*", "* ")
1948 #define HAS_FLAG_STR _("+", "+ ")
1949 #define NO_FLAG_STR _("・", ". ")
1951 #define print_im_or_res_flag(IM, RES) \
1953 fputs(have_flag(flgs, (IM)) ? IM_FLAG_STR : \
1954 (have_flag(flgs, (RES)) ? HAS_FLAG_STR : NO_FLAG_STR), fff); \
1957 #define print_flag(TR) \
1959 fputs(have_flag(flgs, (TR)) ? HAS_FLAG_STR : NO_FLAG_STR, fff); \
1963 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)
1965 GAME_TEXT o_name[MAX_NLEN];
1966 BIT_FLAGS flgs[TR_FLAG_SIZE];
1967 if (!o_ptr->k_idx) return;
1968 if (o_ptr->tval != tval) return;
1969 if (!object_is_known(o_ptr)) return;
1971 bool is_special_item_type = (object_is_wearable(o_ptr) && object_is_ego(o_ptr))
1972 || ((tval == TV_AMULET) && (o_ptr->sval == SV_AMULET_RESISTANCE))
1973 || ((tval == TV_RING) && (o_ptr->sval == SV_RING_LORDLY))
1974 || ((tval == TV_SHIELD) && (o_ptr->sval == SV_DRAGON_SHIELD))
1975 || ((tval == TV_HELM) && (o_ptr->sval == SV_DRAGON_HELM))
1976 || ((tval == TV_GLOVES) && (o_ptr->sval == SV_SET_OF_DRAGON_GLOVES))
1977 || ((tval == TV_BOOTS) && (o_ptr->sval == SV_PAIR_OF_DRAGON_GREAVE))
1978 || object_is_artifact(o_ptr);
1979 if (!is_special_item_type)
1985 object_desc(creature_ptr, o_name, o_ptr, OD_NAME_ONLY);
1986 while (o_name[i] && (i < 26))
1989 if (iskanji(o_name[i])) i++;
1998 o_name[i] = ' '; i++;
2004 fprintf(fff, "%s %s", where, o_name);
2006 if (!OBJECT_IS_FULL_KNOWN(o_ptr))
2008 fputs(_("-------不明--------------- -------不明---------\n",
2009 "-------unknown------------ -------unknown------\n"), fff);
2013 object_flags_known(o_ptr, flgs);
2015 print_im_or_res_flag(TR_IM_ACID, TR_RES_ACID);
2016 print_im_or_res_flag(TR_IM_ELEC, TR_RES_ELEC);
2017 print_im_or_res_flag(TR_IM_FIRE, TR_RES_FIRE);
2018 print_im_or_res_flag(TR_IM_COLD, TR_RES_COLD);
2019 print_flag(TR_RES_POIS);
2020 print_flag(TR_RES_LITE);
2021 print_flag(TR_RES_DARK);
2022 print_flag(TR_RES_SHARDS);
2023 print_flag(TR_RES_SOUND);
2024 print_flag(TR_RES_NETHER);
2025 print_flag(TR_RES_NEXUS);
2026 print_flag(TR_RES_CHAOS);
2027 print_flag(TR_RES_DISEN);
2031 print_flag(TR_RES_BLIND);
2032 print_flag(TR_RES_FEAR);
2033 print_flag(TR_RES_CONF);
2034 print_flag(TR_FREE_ACT);
2035 print_flag(TR_SEE_INVIS);
2036 print_flag(TR_HOLD_EXP);
2037 print_flag(TR_TELEPATHY);
2038 print_flag(TR_SLOW_DIGEST);
2039 print_flag(TR_REGEN);
2040 print_flag(TR_LEVITATION);
2049 fprintf(fff, "%s\n", inven_res_label);
2054 * Display *ID* ed weapons/armors's resistances
2056 static void do_cmd_knowledge_inven(player_type *creature_ptr)
2059 GAME_TEXT file_name[1024];
2061 OBJECT_TYPE_VALUE tval;
2065 fff = my_fopen_temp(file_name, 1024);
2068 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
2073 fprintf(fff, "%s\n", inven_res_label);
2074 for (tval = TV_WEARABLE_BEGIN; tval <= TV_WEARABLE_END; tval++)
2078 for (; j < 9; j++) fputc('\n', fff);
2080 fprintf(fff, "%s\n", inven_res_label);
2083 strcpy(where, _("装", "E "));
2084 for (int i = INVEN_RARM; i < INVEN_TOTAL; i++)
2086 do_cmd_knowledge_inven_aux(creature_ptr, fff, &creature_ptr->inventory_list[i], &j, tval, where);
2089 strcpy(where, _("持", "I "));
2090 for (int i = 0; i < INVEN_PACK; i++)
2092 do_cmd_knowledge_inven_aux(creature_ptr, fff, &creature_ptr->inventory_list[i], &j, tval, where);
2095 st_ptr = &town_info[1].store[STORE_HOME];
2096 strcpy(where, _("家", "H "));
2097 for (int i = 0; i < st_ptr->stock_num; i++)
2099 do_cmd_knowledge_inven_aux(creature_ptr, fff, &st_ptr->stock[i], &j, tval, where);
2104 (void)show_file(creature_ptr, TRUE, file_name, _("*鑑定*済み武器/防具の耐性リスト", "Resistances of *identified* equipment"), 0, 0);
2109 void do_cmd_save_screen_html_aux(char *filename, int message)
2117 concptr html_head[] = {
2118 "<html>\n<body text=\"#ffffff\" bgcolor=\"#000000\">\n",
2122 concptr html_foot[] = {
2124 "</body>\n</html>\n",
2129 Term_get_size(&wid, &hgt);
2130 FILE_TYPE(FILE_TYPE_TEXT);
2132 fff = my_fopen(filename, "w");
2137 msg_format(_("ファイル %s を開けませんでした。", "Failed to open file %s."), filename);
2144 if (message) screen_save();
2147 path_build(buf, sizeof(buf), ANGBAND_DIR_USER, "htmldump.prf");
2149 tmpfff = my_fopen(buf, "r");
2152 for (int i = 0; html_head[i]; i++)
2153 fputs(html_head[i], fff);
2157 bool is_first_line = TRUE;
2158 while (!my_fgets(tmpfff, buf, sizeof(buf)))
2162 if (strncmp(buf, tags[0], strlen(tags[0])) == 0)
2163 is_first_line = FALSE;
2167 if (strncmp(buf, tags[1], strlen(tags[1])) == 0)
2169 fprintf(fff, "%s\n", buf);
2174 for (TERM_LEN y = 0; y < hgt; y++)
2176 if (y != 0) fprintf(fff, "\n");
2178 TERM_COLOR a = 0, old_a = 0;
2180 for (TERM_LEN x = 0; x < wid - 1; x++)
2183 (void)(Term_what(x, y, &a, &c));
2186 case '&': cc = "&"; break;
2187 case '<': cc = "<"; break;
2188 case '>': cc = ">"; break;
2190 case 0x1f: c = '.'; break;
2191 case 0x7f: c = (a == 0x09) ? '%' : '#'; break;
2196 if ((y == 0 && x == 0) || a != old_a)
2198 int rv = angband_color_table[a][1];
2199 int gv = angband_color_table[a][2];
2200 int bv = angband_color_table[a][3];
2201 fprintf(fff, "%s<font color=\"#%02x%02x%02x\">",
2202 ((y == 0 && x == 0) ? "" : "</font>"), rv, gv, bv);
2207 fprintf(fff, "%s", cc);
2209 fprintf(fff, "%c", c);
2213 fprintf(fff, "</font>");
2216 for (int i = 0; html_foot[i]; i++)
2217 fputs(html_foot[i], fff);
2222 bool is_first_line = TRUE;
2223 while (!my_fgets(tmpfff, buf, sizeof(buf)))
2227 if (strncmp(buf, tags[2], strlen(tags[2])) == 0)
2228 is_first_line = FALSE;
2232 if (strncmp(buf, tags[3], strlen(tags[3])) == 0)
2234 fprintf(fff, "%s\n", buf);
2245 msg_print(_("画面(記念撮影)をファイルに書き出しました。", "Screen dump saved."));
2255 * Hack -- save a screen dump to a file
2257 static void do_cmd_save_screen_html(void)
2259 char buf[1024], tmp[256] = "screen.html";
2261 if (!get_string(_("ファイル名: ", "File name: "), tmp, 80))
2263 path_build(buf, sizeof(buf), ANGBAND_DIR_USER, tmp);
2267 do_cmd_save_screen_html_aux(buf, 1);
2272 * Redefinable "save_screen" action
2274 void(*screendump_aux)(void) = NULL;
2278 * Save a screen dump to a file
2279 * @param creature_ptr プレーヤーへの参照ポインタ
2282 void do_cmd_save_screen(player_type *creature_ptr)
2284 prt(_("記念撮影しますか? [(y)es/(h)tml/(n)o] ", "Save screen dump? [(y)es/(h)tml/(n)o] "), 0, 0);
2285 bool html_dump = FALSE;
2289 if (c == 'Y' || c == 'y')
2291 else if (c == 'H' || c == 'h')
2304 Term_get_size(&wid, &hgt);
2306 bool old_use_graphics = use_graphics;
2307 if (old_use_graphics)
2309 use_graphics = FALSE;
2310 reset_visuals(creature_ptr);
2311 creature_ptr->redraw |= (PR_WIPE | PR_BASIC | PR_EXTRA | PR_MAP | PR_EQUIPPY);
2312 handle_stuff(creature_ptr);
2317 do_cmd_save_screen_html();
2318 do_cmd_redraw(creature_ptr);
2320 else if (screendump_aux)
2322 (*screendump_aux)();
2328 SYMBOL_CODE c = ' ';
2331 path_build(buf, sizeof(buf), ANGBAND_DIR_USER, "dump.txt");
2332 FILE_TYPE(FILE_TYPE_TEXT);
2333 fff = my_fopen(buf, "w");
2336 msg_format(_("ファイル %s を開けませんでした。", "Failed to open file %s."), buf);
2342 for (y = 0; y < hgt; y++)
2344 for (x = 0; x < wid - 1; x++)
2346 (void)(Term_what(x, y, &a, &c));
2351 fprintf(fff, "%s\n", buf);
2355 for (y = 0; y < hgt; y++)
2357 for (x = 0; x < wid - 1; x++)
2359 (void)(Term_what(x, y, &a, &c));
2360 buf[x] = hack[a & 0x0F];
2364 fprintf(fff, "%s\n", buf);
2369 msg_print(_("画面(記念撮影)をファイルに書き出しました。", "Screen dump saved."));
2374 if (!old_use_graphics) return;
2376 use_graphics = TRUE;
2377 reset_visuals(creature_ptr);
2378 creature_ptr->redraw |= (PR_WIPE | PR_BASIC | PR_EXTRA | PR_MAP | PR_EQUIPPY);
2379 handle_stuff(creature_ptr);
2384 * todo okay = 既知のアーティファクト? と思われるが確証がない
2385 * 分かりやすい変数名へ変更求む&万が一未知である旨の配列なら負論理なのでゴソッと差し替えるべき
2386 * Check the status of "artifacts"
2387 * @param player_ptr プレーヤーへの参照ポインタ
2390 static void do_cmd_knowledge_artifacts(player_type *player_ptr)
2393 GAME_TEXT file_name[1024];
2394 fff = my_fopen_temp(file_name, 1024);
2397 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
2403 C_MAKE(who, max_a_idx, ARTIFACT_IDX);
2405 C_MAKE(okay, max_a_idx, bool);
2407 for (ARTIFACT_IDX k = 0; k < max_a_idx; k++)
2409 artifact_type *a_ptr = &a_info[k];
2411 if (!a_ptr->name) continue;
2412 if (!a_ptr->cur_num) continue;
2417 for (POSITION y = 0; y < player_ptr->current_floor_ptr->height; y++)
2419 for (POSITION x = 0; x < player_ptr->current_floor_ptr->width; x++)
2421 grid_type *g_ptr = &player_ptr->current_floor_ptr->grid_array[y][x];
2422 OBJECT_IDX this_o_idx, next_o_idx = 0;
2423 for (this_o_idx = g_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx)
2426 o_ptr = &player_ptr->current_floor_ptr->o_list[this_o_idx];
2427 next_o_idx = o_ptr->next_o_idx;
2428 if (!object_is_fixed_artifact(o_ptr)) continue;
2429 if (object_is_known(o_ptr)) continue;
2431 okay[o_ptr->name1] = FALSE;
2436 for (ARTIFACT_IDX i = 0; i < INVEN_TOTAL; i++)
2438 object_type *o_ptr = &player_ptr->inventory_list[i];
2439 if (!o_ptr->k_idx) continue;
2440 if (!object_is_fixed_artifact(o_ptr)) continue;
2441 if (object_is_known(o_ptr)) continue;
2443 okay[o_ptr->name1] = FALSE;
2447 for (ARTIFACT_IDX k = 0; k < max_a_idx; k++)
2449 if (okay[k]) who[n++] = k;
2453 ang_sort(who, &why, n, ang_sort_art_comp, ang_sort_art_swap);
2454 for (ARTIFACT_IDX k = 0; k < n; k++)
2456 artifact_type *a_ptr = &a_info[who[k]];
2457 GAME_TEXT base_name[MAX_NLEN];
2458 strcpy(base_name, _("未知の伝説のアイテム", "Unknown Artifact"));
2459 ARTIFACT_IDX z = lookup_kind(a_ptr->tval, a_ptr->sval);
2465 object_prep(q_ptr, z);
2466 q_ptr->name1 = (byte)who[k];
2467 q_ptr->ident |= IDENT_STORE;
2468 object_desc(player_ptr, base_name, q_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY));
2471 fprintf(fff, _(" %s\n", " The %s\n"), base_name);
2474 C_KILL(who, max_a_idx, ARTIFACT_IDX);
2475 C_KILL(okay, max_a_idx, bool);
2477 (void)show_file(player_ptr, TRUE, file_name, _("既知の伝説のアイテム", "Artifacts Seen"), 0, 0);
2483 * Display known uniques
2484 * With "XTRA HACK UNIQHIST" (Originally from XAngband)
2486 static void do_cmd_knowledge_uniques(player_type *creature_ptr)
2490 GAME_TEXT file_name[1024];
2492 int n_alive_surface = 0;
2493 int n_alive_over100 = 0;
2494 int n_alive_total = 0;
2496 for (IDX i = 0; i < 10; i++)
2500 fff = my_fopen_temp(file_name, 1024);
2503 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
2508 C_MAKE(who, max_r_idx, MONRACE_IDX);
2510 for (IDX i = 1; i < max_r_idx; i++)
2512 monster_race *r_ptr = &r_info[i];
2513 if (!r_ptr->name) continue;
2514 if (!(r_ptr->flags1 & RF1_UNIQUE)) continue;
2515 if (!cheat_know && !r_ptr->r_sights) continue;
2516 if (!r_ptr->rarity || ((r_ptr->rarity > 100) && !(r_ptr->flags1 & RF1_QUESTOR))) continue;
2517 if (r_ptr->max_num == 0) continue;
2521 int lev = (r_ptr->level - 1) / 10;
2525 if (max_lev < lev) max_lev = lev;
2536 ang_sort(who, &why, n, ang_sort_comp_hook, ang_sort_swap_hook);
2537 if (n_alive_surface)
2539 fprintf(fff, _(" 地上 生存: %3d体\n", " Surface alive: %3d\n"), n_alive_surface);
2540 n_alive_total += n_alive_surface;
2543 for (IDX i = 0; i <= max_lev; i++)
2545 fprintf(fff, _("%3d-%3d階 生存: %3d体\n", "Level %3d-%3d alive: %3d\n"), 1 + i * 10, 10 + i * 10, n_alive[i]);
2546 n_alive_total += n_alive[i];
2549 if (n_alive_over100)
2551 fprintf(fff, _("101- 階 生存: %3d体\n", "Level 101- alive: %3d\n"), n_alive_over100);
2552 n_alive_total += n_alive_over100;
2557 fputs(_("--------- -----------\n", "------------- ----------\n"), fff);
2558 fprintf(fff, _(" 合計 生存: %3d体\n\n", " Total alive: %3d\n\n"), n_alive_total);
2562 fputs(_("現在は既知の生存ユニークはいません。\n", "No known uniques alive.\n"), fff);
2565 for (int k = 0; k < n; k++)
2567 monster_race *r_ptr = &r_info[who[k]];
2568 fprintf(fff, _(" %s (レベル%d)\n", " %s (level %d)\n"), r_name + r_ptr->name, (int)r_ptr->level);
2571 C_KILL(who, max_r_idx, s16b);
2573 (void)show_file(creature_ptr, TRUE, file_name, _("まだ生きているユニーク・モンスター", "Alive Uniques"), 0, 0);
2579 * Display weapon-exp
2581 static void do_cmd_knowledge_weapon_exp(player_type *creature_ptr)
2584 GAME_TEXT file_name[1024];
2585 fff = my_fopen_temp(file_name, 1024);
2588 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
2593 for (int i = 0; i < 5; i++)
2595 for (int num = 0; num < 64; num++)
2599 for (KIND_OBJECT_IDX j = 0; j < max_k_idx; j++)
2601 object_kind *k_ptr = &k_info[j];
2603 if ((k_ptr->tval != TV_SWORD - i) || (k_ptr->sval != num)) continue;
2604 if ((k_ptr->tval == TV_BOW) && (k_ptr->sval == SV_CRIMSON || k_ptr->sval == SV_HARP)) continue;
2606 weapon_exp = creature_ptr->weapon_exp[4 - i][num];
2608 fprintf(fff, "%-25s ", tmp);
2609 if (weapon_exp >= s_info[creature_ptr->pclass].w_max[4 - i][num]) fprintf(fff, "!");
2610 else fprintf(fff, " ");
2611 fprintf(fff, "%s", exp_level_str[weapon_exp_level(weapon_exp)]);
2612 if (cheat_xtra) fprintf(fff, " %d", weapon_exp);
2620 (void)show_file(creature_ptr, TRUE, file_name, _("武器の経験値", "Weapon Proficiency"), 0, 0);
2626 * @brief 魔法の経験値を表示するコマンドのメインルーチン
2630 static void do_cmd_knowledge_spell_exp(player_type *creature_ptr)
2633 GAME_TEXT file_name[1024];
2634 fff = my_fopen_temp(file_name, 1024);
2637 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
2642 if (creature_ptr->realm1 != REALM_NONE)
2644 fprintf(fff, _("%sの魔法書\n", "%s Spellbook\n"), realm_names[creature_ptr->realm1]);
2645 for (SPELL_IDX i = 0; i < 32; i++)
2647 const magic_type *s_ptr;
2648 if (!is_magic(creature_ptr->realm1))
2650 s_ptr = &technic_info[creature_ptr->realm1 - MIN_TECHNIC][i];
2654 s_ptr = &mp_ptr->info[creature_ptr->realm1 - 1][i];
2657 if (s_ptr->slevel >= 99) continue;
2658 SUB_EXP spell_exp = creature_ptr->spell_exp[i];
2659 int exp_level = spell_exp_level(spell_exp);
2660 fprintf(fff, "%-25s ", exe_spell(creature_ptr, creature_ptr->realm1, i, SPELL_NAME));
2661 if (creature_ptr->realm1 == REALM_HISSATSU)
2662 fprintf(fff, "[--]");
2665 if (exp_level >= EXP_LEVEL_MASTER) fprintf(fff, "!");
2666 else fprintf(fff, " ");
2667 fprintf(fff, "%s", exp_level_str[exp_level]);
2670 if (cheat_xtra) fprintf(fff, " %d", spell_exp);
2675 if (creature_ptr->realm2 != REALM_NONE)
2677 fprintf(fff, _("%sの魔法書\n", "\n%s Spellbook\n"), realm_names[creature_ptr->realm2]);
2678 for (SPELL_IDX i = 0; i < 32; i++)
2680 const magic_type *s_ptr;
2681 if (!is_magic(creature_ptr->realm1))
2683 s_ptr = &technic_info[creature_ptr->realm2 - MIN_TECHNIC][i];
2687 s_ptr = &mp_ptr->info[creature_ptr->realm2 - 1][i];
2690 if (s_ptr->slevel >= 99) continue;
2692 SUB_EXP spell_exp = creature_ptr->spell_exp[i + 32];
2693 int exp_level = spell_exp_level(spell_exp);
2694 fprintf(fff, "%-25s ", exe_spell(creature_ptr, creature_ptr->realm2, i, SPELL_NAME));
2695 if (exp_level >= EXP_LEVEL_EXPERT) fprintf(fff, "!");
2696 else fprintf(fff, " ");
2697 fprintf(fff, "%s", exp_level_str[exp_level]);
2698 if (cheat_xtra) fprintf(fff, " %d", spell_exp);
2704 (void)show_file(creature_ptr, TRUE, file_name, _("魔法の経験値", "Spell Proficiency"), 0, 0);
2710 * @brief スキル情報を表示するコマンドのメインルーチン /
2714 static void do_cmd_knowledge_skill_exp(player_type *creature_ptr)
2716 char skill_name[GINOU_TEMPMAX][20] =
2718 _("マーシャルアーツ", "Martial Arts "),
2719 _("二刀流 ", "Dual Wielding "),
2720 _("乗馬 ", "Riding "),
2725 char file_name[1024];
2726 fff = my_fopen_temp(file_name, 1024);
2729 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
2734 for (int i = 0; i < GINOU_TEMPMAX; i++)
2736 int skill_exp = creature_ptr->skill_exp[i];
2737 fprintf(fff, "%-20s ", skill_name[i]);
2738 if (skill_exp >= s_info[creature_ptr->pclass].s_max[i]) fprintf(fff, "!");
2739 else fprintf(fff, " ");
2740 fprintf(fff, "%s", exp_level_str[(i == GINOU_RIDING) ? riding_exp_level(skill_exp) : weapon_exp_level(skill_exp)]);
2741 if (cheat_xtra) fprintf(fff, " %d", skill_exp);
2746 (void)show_file(creature_ptr, TRUE, file_name, _("技能の経験値", "Miscellaneous Proficiency"), 0, 0);
2752 * @brief 現在のペットを表示するコマンドのメインルーチン /
2753 * Display current pets
2754 * @param creature_ptr プレーヤーへの参照ポインタ
2757 static void do_cmd_knowledge_pets(player_type *creature_ptr)
2759 GAME_TEXT file_name[1024];
2761 fff = my_fopen_temp(file_name, 1024);
2764 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
2769 monster_type *m_ptr;
2770 GAME_TEXT pet_name[MAX_NLEN];
2772 for (int i = creature_ptr->current_floor_ptr->m_max - 1; i >= 1; i--)
2774 m_ptr = &creature_ptr->current_floor_ptr->m_list[i];
2775 if (!monster_is_valid(m_ptr)) continue;
2776 if (!is_pet(m_ptr)) continue;
2779 monster_desc(creature_ptr, pet_name, m_ptr, MD_ASSUME_VISIBLE | MD_INDEF_VISIBLE);
2780 fprintf(fff, "%s (%s)\n", pet_name, look_mon_desc(m_ptr, 0x00));
2783 int show_upkeep = calculate_upkeep(creature_ptr);
2785 fprintf(fff, "----------------------------------------------\n");
2787 fprintf(fff, " 合計: %d 体のペット\n", t_friends);
2789 fprintf(fff, " Total: %d pet%s.\n", t_friends, (t_friends == 1 ? "" : "s"));
2791 fprintf(fff, _(" 維持コスト: %d%% MP\n", " Upkeep: %d%% mana.\n"), show_upkeep);
2794 (void)show_file(creature_ptr, TRUE, file_name, _("現在のペット", "Current Pets"), 0, 0);
2800 * @brief 現在のペットを表示するコマンドのメインルーチン /
2801 * @param creature_ptr プレーヤーへの参照ポインタ
2804 * @note the player ghosts are ignored.
2806 static void do_cmd_knowledge_kill_count(player_type *creature_ptr)
2809 GAME_TEXT file_name[1024];
2810 fff = my_fopen_temp(file_name, 1024);
2813 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
2819 C_MAKE(who, max_r_idx, MONRACE_IDX);
2821 for (int kk = 1; kk < max_r_idx; kk++)
2823 monster_race *r_ptr = &r_info[kk];
2825 if (r_ptr->flags1 & (RF1_UNIQUE))
2827 bool dead = (r_ptr->max_num == 0);
2836 MONSTER_NUMBER this_monster = r_ptr->r_pkills;
2838 if (this_monster > 0)
2840 total += this_monster;
2846 fprintf(fff, _("あなたはまだ敵を倒していない。\n\n", "You have defeated no enemies yet.\n\n"));
2849 fprintf(fff, "あなたは%ld体の敵を倒している。\n\n", (long int)total);
2851 fprintf(fff, "You have defeated %ld %s.\n\n", (long int)total, (total == 1) ? "enemy" : "enemies");
2856 for (MONRACE_IDX i = 1; i < max_r_idx; i++)
2858 monster_race *r_ptr = &r_info[i];
2859 if (r_ptr->name) who[n++] = i;
2863 ang_sort(who, &why, n, ang_sort_comp_hook, ang_sort_swap_hook);
2864 for (int k = 0; k < n; k++)
2866 monster_race *r_ptr = &r_info[who[k]];
2867 if (r_ptr->flags1 & (RF1_UNIQUE))
2869 bool dead = (r_ptr->max_num == 0);
2872 fprintf(fff, " %s\n", (r_name + r_ptr->name));
2879 MONSTER_NUMBER this_monster = r_ptr->r_pkills;
2880 if (this_monster <= 0) continue;
2883 if (my_strchr("pt", r_ptr->d_char))
2884 fprintf(fff, " %3d 人の %s\n", (int)this_monster, r_name + r_ptr->name);
2886 fprintf(fff, " %3d 体の %s\n", (int)this_monster, r_name + r_ptr->name);
2888 if (this_monster < 2)
2890 if (my_strstr(r_name + r_ptr->name, "coins"))
2892 fprintf(fff, " 1 pile of %s\n", (r_name + r_ptr->name));
2896 fprintf(fff, " 1 %s\n", (r_name + r_ptr->name));
2902 strcpy(ToPlural, (r_name + r_ptr->name));
2903 plural_aux(ToPlural);
2904 fprintf(fff, " %d %s\n", this_monster, ToPlural);
2907 total += this_monster;
2910 fprintf(fff, "----------------------------------------------\n");
2912 fprintf(fff, " 合計: %lu 体を倒した。\n", (unsigned long int)total);
2914 fprintf(fff, " Total: %lu creature%s killed.\n", (unsigned long int)total, (total == 1 ? "" : "s"));
2917 C_KILL(who, max_r_idx, s16b);
2919 (void)show_file(creature_ptr, TRUE, file_name, _("倒した敵の数", "Kill Count"), 0, 0);
2925 * @brief モンスター情報リスト中のグループを表示する /
2926 * Display the object groups.
2930 * @param per_page リストの表示行
2931 * @param grp_idx グループのID配列
2932 * @param group_text グループ名の文字列配列
2933 * @param grp_cur 現在の選択ID
2934 * @param grp_top 現在の選択リスト最上部ID
2937 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)
2939 for (int i = 0; i < per_page && (grp_idx[i] >= 0); i++)
2941 int grp = grp_idx[grp_top + i];
2942 TERM_COLOR attr = (grp_top + i == grp_cur) ? TERM_L_BLUE : TERM_WHITE;
2943 Term_erase(col, row + i, wid);
2944 c_put_str(attr, group_text[grp], row + i, col);
2950 * Move the cursor in a browser window
2952 static void browser_cursor(char ch, int *column, IDX *grp_cur, int grp_cnt, IDX *list_cur, int list_cnt)
2957 IDX list = *list_cur;
2963 d = get_keymap_dir(ch);
2967 if ((ddx[d] > 0) && ddy[d])
2971 Term_get_size(&wid, &hgt);
2972 browser_rows = hgt - 8;
2976 grp += ddy[d] * (browser_rows - 1);
2977 if (grp >= grp_cnt) grp = grp_cnt - 1;
2978 if (grp < 0) grp = 0;
2979 if (grp != old_grp) list = 0;
2983 list += ddy[d] * browser_rows;
2984 if (list >= list_cnt) list = list_cnt - 1;
2985 if (list < 0) list = 0;
2996 if (col < 0) col = 0;
2997 if (col > 1) col = 1;
3007 if (grp >= grp_cnt) grp = grp_cnt - 1;
3008 if (grp < 0) grp = 0;
3009 if (grp != old_grp) list = 0;
3013 list += (IDX)ddy[d];
3014 if (list >= list_cnt) list = list_cnt - 1;
3015 if (list < 0) list = 0;
3026 static void display_visual_list(int col, int row, int height, int width, TERM_COLOR attr_top, byte char_left)
3028 for (int i = 0; i < height; i++)
3030 Term_erase(col, row + i, width);
3033 if (use_bigtile) width /= 2;
3035 for (int i = 0; i < height; i++)
3037 for (int j = 0; j < width; j++)
3039 TERM_LEN x = col + j;
3040 TERM_LEN y = row + i;
3041 if (use_bigtile) x += j;
3043 TERM_COLOR ia = attr_top + i;
3044 SYMBOL_CODE ic = char_left + j;
3045 if (ia > 0x7f || ic > 0xff || ic < ' ' ||
3046 (!use_graphics && ic > 0x7f))
3051 if (c & 0x80) a |= 0x80;
3053 Term_queue_bigchar(x, y, a, c, 0, 0);
3060 * Place the cursor at the collect position for visual mode
3062 static void place_visual_list_cursor(TERM_LEN col, TERM_LEN row, TERM_COLOR a, byte c, TERM_COLOR attr_top, byte char_left)
3064 int i = (a & 0x7f) - attr_top;
3065 int j = c - char_left;
3067 TERM_LEN x = col + j;
3068 TERM_LEN y = row + i;
3069 if (use_bigtile) x += j;
3076 * Do visual mode command -- Change symbols
3078 static bool visual_mode_command(char ch, bool *visual_list_ptr,
3079 int height, int width,
3080 TERM_COLOR *attr_top_ptr, byte *char_left_ptr,
3081 TERM_COLOR *cur_attr_ptr, SYMBOL_CODE *cur_char_ptr, bool *need_redraw)
3083 static TERM_COLOR attr_old = 0;
3084 static SYMBOL_CODE char_old = 0;
3089 if (*visual_list_ptr)
3091 *cur_attr_ptr = attr_old;
3092 *cur_char_ptr = char_old;
3093 *visual_list_ptr = FALSE;
3102 if (*visual_list_ptr)
3104 *visual_list_ptr = FALSE;
3105 *need_redraw = TRUE;
3114 if (!*visual_list_ptr)
3116 *visual_list_ptr = TRUE;
3118 *attr_top_ptr = MAX(0, (*cur_attr_ptr & 0x7f) - 5);
3119 *char_left_ptr = MAX(0, *cur_char_ptr - 10);
3121 attr_old = *cur_attr_ptr;
3122 char_old = *cur_char_ptr;
3132 attr_idx = *cur_attr_ptr;
3133 char_idx = *cur_char_ptr;
3134 for (int i = 0; i < F_LIT_MAX; i++)
3136 attr_idx_feat[i] = 0;
3137 char_idx_feat[i] = 0;
3145 if (attr_idx || (!(char_idx & 0x80) && char_idx))
3147 *cur_attr_ptr = attr_idx;
3148 *attr_top_ptr = MAX(0, (*cur_attr_ptr & 0x7f) - 5);
3149 if (!*visual_list_ptr) *need_redraw = TRUE;
3155 *cur_char_ptr = char_idx;
3156 *char_left_ptr = MAX(0, *cur_char_ptr - 10);
3157 if (!*visual_list_ptr) *need_redraw = TRUE;
3163 if (*visual_list_ptr)
3166 int d = get_keymap_dir(ch);
3167 TERM_COLOR a = (*cur_attr_ptr & 0x7f);
3168 SYMBOL_CODE c = *cur_char_ptr;
3170 if (use_bigtile) eff_width = width / 2;
3171 else eff_width = width;
3173 if ((a == 0) && (ddy[d] < 0)) d = 0;
3174 if ((c == 0) && (ddx[d] < 0)) d = 0;
3175 if ((a == 0x7f) && (ddy[d] > 0)) d = 0;
3176 if ((c == 0xff) && (ddx[d] > 0)) d = 0;
3178 a += (TERM_COLOR)ddy[d];
3179 c += (SYMBOL_CODE)ddx[d];
3180 if (c & 0x80) a |= 0x80;
3184 if ((ddx[d] < 0) && *char_left_ptr > MAX(0, (int)c - 10)) (*char_left_ptr)--;
3185 if ((ddx[d] > 0) && *char_left_ptr + eff_width < MIN(0xff, (int)c + 10)) (*char_left_ptr)++;
3186 if ((ddy[d] < 0) && *attr_top_ptr > MAX(0, (int)(a & 0x7f) - 4)) (*attr_top_ptr)--;
3187 if ((ddy[d] > 0) && *attr_top_ptr + height < MIN(0x7f, (a & 0x7f) + 4)) (*attr_top_ptr)++;
3199 * Display the monsters in a group.
3201 static void display_monster_list(int col, int row, int per_page, s16b mon_idx[], int mon_cur, int mon_top, bool visual_only)
3204 for (i = 0; i < per_page && (mon_idx[mon_top + i] >= 0); i++)
3207 MONRACE_IDX r_idx = mon_idx[mon_top + i];
3208 monster_race *r_ptr = &r_info[r_idx];
3209 attr = ((i + mon_top == mon_cur) ? TERM_L_BLUE : TERM_WHITE);
3210 c_prt(attr, (r_name + r_ptr->name), row + i, col);
3213 c_prt(attr, format("%02x/%02x", r_ptr->x_attr, r_ptr->x_char), row + i, (current_world_ptr->wizard || visual_only) ? 56 : 61);
3216 if (current_world_ptr->wizard || visual_only)
3218 c_prt(attr, format("%d", r_idx), row + i, 62);
3221 Term_erase(69, row + i, 255);
3222 Term_queue_bigchar(use_bigtile ? 69 : 70, row + i, r_ptr->x_attr, r_ptr->x_char, 0, 0);
3225 if (!(r_ptr->flags1 & RF1_UNIQUE))
3226 put_str(format("%5d", r_ptr->r_pkills), row + i, 73);
3228 c_put_str((r_ptr->max_num == 0 ? TERM_L_DARK : TERM_WHITE),
3229 (r_ptr->max_num == 0 ? _("死亡", " dead") : _("生存", "alive")), row + i, 74);
3233 for (; i < per_page; i++)
3235 Term_erase(col, row + i, 255);
3241 * todo 引数の詳細について加筆求む
3242 * Display known monsters.
3243 * @param creature_ptr プレーヤーへの参照ポインタ
3244 * @param need_redraw 画面の再描画が必要な時TRUE
3245 * @param visual_only ???
3246 * @param direct_r_idx モンスターID
3249 static void do_cmd_knowledge_monsters(player_type *creature_ptr, bool *need_redraw, bool visual_only, IDX direct_r_idx)
3252 Term_get_size(&wid, &hgt);
3254 C_MAKE(mon_idx, max_r_idx, MONRACE_IDX);
3260 bool visual_list = FALSE;
3261 TERM_COLOR attr_top = 0;
3264 int browser_rows = hgt - 8;
3265 if (direct_r_idx < 0)
3267 mode = visual_only ? 0x03 : 0x01;
3269 for (IDX i = 0; monster_group_text[i] != NULL; i++)
3271 len = strlen(monster_group_text[i]);
3272 if (len > max) max = len;
3274 if ((monster_group_char[i] == ((char *)-1L)) || collect_monsters(creature_ptr, i, mon_idx, mode))
3276 grp_idx[grp_cnt++] = i;
3284 mon_idx[0] = direct_r_idx;
3288 (void)visual_mode_command('v', &visual_list, browser_rows - 1, wid - (max + 3),
3289 &attr_top, &char_left, &r_info[direct_r_idx].x_attr, &r_info[direct_r_idx].x_char, need_redraw);
3292 grp_idx[grp_cnt] = -1;
3293 mode = visual_only ? 0x02 : 0x00;
3294 IDX old_grp_cur = -1;
3307 prt(format(_("%s - モンスター", "%s - monsters"), !visual_only ? _("知識", "Knowledge") : _("表示", "Visuals")), 2, 0);
3308 if (direct_r_idx < 0) prt(_("グループ", "Group"), 4, 0);
3309 prt(_("名前", "Name"), 4, max + 3);
3310 if (current_world_ptr->wizard || visual_only) prt("Idx", 4, 62);
3311 prt(_("文字", "Sym"), 4, 67);
3312 if (!visual_only) prt(_("殺害数", "Kills"), 4, 72);
3314 for (IDX i = 0; i < 78; i++)
3316 Term_putch(i, 5, TERM_WHITE, '=');
3319 if (direct_r_idx < 0)
3321 for (IDX i = 0; i < browser_rows; i++)
3323 Term_putch(max + 1, 6 + i, TERM_WHITE, '|');
3330 if (direct_r_idx < 0)
3332 if (grp_cur < grp_top) grp_top = grp_cur;
3333 if (grp_cur >= grp_top + browser_rows) grp_top = grp_cur - browser_rows + 1;
3335 display_group_list(0, 6, max, browser_rows, grp_idx, monster_group_text, grp_cur, grp_top);
3336 if (old_grp_cur != grp_cur)
3338 old_grp_cur = grp_cur;
3339 mon_cnt = collect_monsters(creature_ptr, grp_idx[grp_cur], mon_idx, mode);
3342 while (mon_cur < mon_top)
3343 mon_top = MAX(0, mon_top - browser_rows / 2);
3344 while (mon_cur >= mon_top + browser_rows)
3345 mon_top = MIN(mon_cnt - browser_rows, mon_top + browser_rows / 2);
3350 display_monster_list(max + 3, 6, browser_rows, mon_idx, mon_cur, mon_top, visual_only);
3355 display_monster_list(max + 3, 6, 1, mon_idx, mon_cur, mon_top, visual_only);
3356 display_visual_list(max + 3, 7, browser_rows - 1, wid - (max + 3), attr_top, char_left);
3359 prt(format(_("<方向>%s%s%s, ESC", "<dir>%s%s%s, ESC"),
3360 (!visual_list && !visual_only) ? _(", 'r'で思い出を見る", ", 'r' to recall") : "",
3361 visual_list ? _(", ENTERで決定", ", ENTER to accept") : _(", 'v'でシンボル変更", ", 'v' for visuals"),
3362 (attr_idx || char_idx) ? _(", 'c', 'p'でペースト", ", 'c', 'p' to paste") : _(", 'c'でコピー", ", 'c' to copy")),
3365 monster_race *r_ptr;
3366 r_ptr = &r_info[mon_idx[mon_cur]];
3370 if (mon_cnt) monster_race_track(creature_ptr, mon_idx[mon_cur]);
3371 handle_stuff(creature_ptr);
3376 place_visual_list_cursor(max + 3, 7, r_ptr->x_attr, r_ptr->x_char, attr_top, char_left);
3380 Term_gotoxy(0, 6 + (grp_cur - grp_top));
3384 Term_gotoxy(max + 3, 6 + (mon_cur - mon_top));
3388 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))
3390 if (direct_r_idx >= 0)
3416 if (!visual_list && !visual_only && (mon_idx[mon_cur] > 0))
3418 screen_roff(creature_ptr, mon_idx[mon_cur], 0);
3430 browser_cursor(ch, &column, &grp_cur, grp_cnt, &mon_cur, mon_cnt);
3437 C_KILL(mon_idx, max_r_idx, MONRACE_IDX);
3442 * Display the objects in a group.
3444 static void display_object_list(int col, int row, int per_page, IDX object_idx[],
3445 int object_cur, int object_top, bool visual_only)
3448 for (i = 0; i < per_page && (object_idx[object_top + i] >= 0); i++)
3450 GAME_TEXT o_name[MAX_NLEN];
3453 object_kind *flavor_k_ptr;
3454 KIND_OBJECT_IDX k_idx = object_idx[object_top + i];
3455 object_kind *k_ptr = &k_info[k_idx];
3456 TERM_COLOR attr = ((k_ptr->aware || visual_only) ? TERM_WHITE : TERM_SLATE);
3457 byte cursor = ((k_ptr->aware || visual_only) ? TERM_L_BLUE : TERM_BLUE);
3458 if (!visual_only && k_ptr->flavor)
3460 flavor_k_ptr = &k_info[k_ptr->flavor];
3464 flavor_k_ptr = k_ptr;
3467 attr = ((i + object_top == object_cur) ? cursor : attr);
3468 if (!k_ptr->flavor || (!visual_only && k_ptr->aware))
3470 strip_name(o_name, k_idx);
3474 strcpy(o_name, k_name + flavor_k_ptr->flavor_name);
3477 c_prt(attr, o_name, row + i, col);
3480 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);
3483 if (current_world_ptr->wizard || visual_only)
3485 c_prt(attr, format("%d", k_idx), row + i, 70);
3488 a = flavor_k_ptr->x_attr;
3489 c = flavor_k_ptr->x_char;
3491 Term_queue_bigchar(use_bigtile ? 76 : 77, row + i, a, c, 0, 0);
3494 for (; i < per_page; i++)
3496 Term_erase(col, row + i, 255);
3502 * Describe fake object
3504 static void desc_obj_fake(player_type *creature_ptr, KIND_OBJECT_IDX k_idx)
3507 object_type object_type_body;
3508 o_ptr = &object_type_body;
3510 object_prep(o_ptr, k_idx);
3512 o_ptr->ident |= IDENT_KNOWN;
3513 handle_stuff(creature_ptr);
3515 if (screen_object(creature_ptr, o_ptr, SCROBJ_FAKE_OBJECT | SCROBJ_FORCE_DETAIL)) return;
3517 msg_print(_("特に変わったところはないようだ。", "You see nothing special."));
3523 * Display known objects
3525 static void do_cmd_knowledge_objects(player_type *creature_ptr, bool *need_redraw, bool visual_only, IDX direct_k_idx)
3527 IDX object_old, object_top;
3530 OBJECT_IDX *object_idx;
3532 bool visual_list = FALSE;
3533 TERM_COLOR attr_top = 0;
3538 Term_get_size(&wid, &hgt);
3540 int browser_rows = hgt - 8;
3541 C_MAKE(object_idx, max_k_idx, KIND_OBJECT_IDX);
3546 if (direct_k_idx < 0)
3548 mode = visual_only ? 0x03 : 0x01;
3549 for (IDX i = 0; object_group_text[i] != NULL; i++)
3551 len = strlen(object_group_text[i]);
3552 if (len > max) max = len;
3554 if (collect_objects(i, object_idx, mode))
3556 grp_idx[grp_cnt++] = i;
3565 object_kind *k_ptr = &k_info[direct_k_idx];
3566 object_kind *flavor_k_ptr;
3568 if (!visual_only && k_ptr->flavor)
3570 flavor_k_ptr = &k_info[k_ptr->flavor];
3574 flavor_k_ptr = k_ptr;
3577 object_idx[0] = direct_k_idx;
3578 object_old = direct_k_idx;
3581 (void)visual_mode_command('v', &visual_list, browser_rows - 1, wid - (max + 3),
3582 &attr_top, &char_left, &flavor_k_ptr->x_attr, &flavor_k_ptr->x_char, need_redraw);
3585 grp_idx[grp_cnt] = -1;
3586 mode = visual_only ? 0x02 : 0x00;
3587 IDX old_grp_cur = -1;
3590 IDX object_cur = object_top = 0;
3596 object_kind *k_ptr, *flavor_k_ptr;
3603 prt(format("%s - アイテム", !visual_only ? "知識" : "表示"), 2, 0);
3604 if (direct_k_idx < 0) prt("グループ", 4, 0);
3605 prt("名前", 4, max + 3);
3606 if (current_world_ptr->wizard || visual_only) prt("Idx", 4, 70);
3609 prt(format("%s - objects", !visual_only ? "Knowledge" : "Visuals"), 2, 0);
3610 if (direct_k_idx < 0) prt("Group", 4, 0);
3611 prt("Name", 4, max + 3);
3612 if (current_world_ptr->wizard || visual_only) prt("Idx", 4, 70);
3616 for (IDX i = 0; i < 78; i++)
3618 Term_putch(i, 5, TERM_WHITE, '=');
3621 if (direct_k_idx < 0)
3623 for (IDX i = 0; i < browser_rows; i++)
3625 Term_putch(max + 1, 6 + i, TERM_WHITE, '|');
3632 if (direct_k_idx < 0)
3634 if (grp_cur < grp_top) grp_top = grp_cur;
3635 if (grp_cur >= grp_top + browser_rows) grp_top = grp_cur - browser_rows + 1;
3637 display_group_list(0, 6, max, browser_rows, grp_idx, object_group_text, grp_cur, grp_top);
3638 if (old_grp_cur != grp_cur)
3640 old_grp_cur = grp_cur;
3641 object_cnt = collect_objects(grp_idx[grp_cur], object_idx, mode);
3644 while (object_cur < object_top)
3645 object_top = MAX(0, object_top - browser_rows / 2);
3646 while (object_cur >= object_top + browser_rows)
3647 object_top = MIN(object_cnt - browser_rows, object_top + browser_rows / 2);
3652 display_object_list(max + 3, 6, browser_rows, object_idx, object_cur, object_top, visual_only);
3656 object_top = object_cur;
3657 display_object_list(max + 3, 6, 1, object_idx, object_cur, object_top, visual_only);
3658 display_visual_list(max + 3, 7, browser_rows - 1, wid - (max + 3), attr_top, char_left);
3661 k_ptr = &k_info[object_idx[object_cur]];
3663 if (!visual_only && k_ptr->flavor)
3665 flavor_k_ptr = &k_info[k_ptr->flavor];
3669 flavor_k_ptr = k_ptr;
3673 prt(format("<方向>%s%s%s, ESC",
3674 (!visual_list && !visual_only) ? ", 'r'で詳細を見る" : "",
3675 visual_list ? ", ENTERで決定" : ", 'v'でシンボル変更",
3676 (attr_idx || char_idx) ? ", 'c', 'p'でペースト" : ", 'c'でコピー"),
3679 prt(format("<dir>%s%s%s, ESC",
3680 (!visual_list && !visual_only) ? ", 'r' to recall" : "",
3681 visual_list ? ", ENTER to accept" : ", 'v' for visuals",
3682 (attr_idx || char_idx) ? ", 'c', 'p' to paste" : ", 'c' to copy"),
3688 if (object_cnt) object_kind_track(creature_ptr, object_idx[object_cur]);
3690 if (object_old != object_idx[object_cur])
3692 handle_stuff(creature_ptr);
3693 object_old = object_idx[object_cur];
3699 place_visual_list_cursor(max + 3, 7, flavor_k_ptr->x_attr, flavor_k_ptr->x_char, attr_top, char_left);
3703 Term_gotoxy(0, 6 + (grp_cur - grp_top));
3707 Term_gotoxy(max + 3, 6 + (object_cur - object_top));
3711 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))
3713 if (direct_k_idx >= 0)
3738 if (!visual_list && !visual_only && (grp_cnt > 0))
3740 desc_obj_fake(creature_ptr, object_idx[object_cur]);
3749 browser_cursor(ch, &column, &grp_cur, grp_cnt, &object_cur, object_cnt);
3755 C_KILL(object_idx, max_k_idx, KIND_OBJECT_IDX);
3760 * Display the features in a group.
3762 static void display_feature_list(int col, int row, int per_page, FEAT_IDX *feat_idx,
3763 FEAT_IDX feat_cur, FEAT_IDX feat_top, bool visual_only, int lighting_level)
3765 int lit_col[F_LIT_MAX], i;
3766 int f_idx_col = use_bigtile ? 62 : 64;
3768 lit_col[F_LIT_STANDARD] = use_bigtile ? (71 - F_LIT_MAX) : 71;
3769 for (i = F_LIT_NS_BEGIN; i < F_LIT_MAX; i++)
3770 lit_col[i] = lit_col[F_LIT_STANDARD] + 2 + (i - F_LIT_NS_BEGIN) * 2 + (use_bigtile ? i : 0);
3772 for (i = 0; i < per_page && (feat_idx[feat_top + i] >= 0); i++)
3775 FEAT_IDX f_idx = feat_idx[feat_top + i];
3776 feature_type *f_ptr = &f_info[f_idx];
3777 int row_i = row + i;
3778 attr = ((i + feat_top == feat_cur) ? TERM_L_BLUE : TERM_WHITE);
3779 c_prt(attr, f_name + f_ptr->name, row_i, col);
3782 c_prt(attr, format("(%s)", lighting_level_str[lighting_level]), row_i, col + 1 + strlen(f_name + f_ptr->name));
3783 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));
3785 if (current_world_ptr->wizard || visual_only)
3787 c_prt(attr, format("%d", f_idx), row_i, f_idx_col);
3790 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);
3791 Term_putch(lit_col[F_LIT_NS_BEGIN], row_i, TERM_SLATE, '(');
3792 for (int j = F_LIT_NS_BEGIN + 1; j < F_LIT_MAX; j++)
3794 Term_putch(lit_col[j], row_i, TERM_SLATE, '/');
3797 Term_putch(lit_col[F_LIT_MAX - 1] + (use_bigtile ? 3 : 2), row_i, TERM_SLATE, ')');
3798 for (int j = F_LIT_NS_BEGIN; j < F_LIT_MAX; j++)
3800 Term_queue_bigchar(lit_col[j] + 1, row_i, f_ptr->x_attr[j], f_ptr->x_char[j], 0, 0);
3804 for (; i < per_page; i++)
3806 Term_erase(col, row + i, 255);
3812 * Interact with feature visuals.
3814 static void do_cmd_knowledge_features(bool *need_redraw, bool visual_only, IDX direct_f_idx, IDX *lighting_level)
3816 TERM_COLOR attr_old[F_LIT_MAX];
3817 (void)C_WIPE(attr_old, F_LIT_MAX, TERM_COLOR);
3818 SYMBOL_CODE char_old[F_LIT_MAX];
3819 (void)C_WIPE(char_old, F_LIT_MAX, SYMBOL_CODE);
3822 Term_get_size(&wid, &hgt);
3825 C_MAKE(feat_idx, max_f_idx, FEAT_IDX);
3831 FEAT_IDX grp_idx[100];
3832 TERM_COLOR attr_top = 0;
3833 bool visual_list = FALSE;
3835 TERM_LEN browser_rows = hgt - 8;
3836 if (direct_f_idx < 0)
3838 for (FEAT_IDX i = 0; feature_group_text[i] != NULL; i++)
3840 len = strlen(feature_group_text[i]);
3841 if (len > max) max = len;
3843 if (collect_features(feat_idx, 0x01))
3845 grp_idx[grp_cnt++] = i;
3853 feature_type *f_ptr = &f_info[direct_f_idx];
3855 feat_idx[0] = direct_f_idx;
3859 (void)visual_mode_command('v', &visual_list, browser_rows - 1, wid - (max + 3),
3860 &attr_top, &char_left, &f_ptr->x_attr[*lighting_level], &f_ptr->x_char[*lighting_level], need_redraw);
3862 for (FEAT_IDX i = 0; i < F_LIT_MAX; i++)
3864 attr_old[i] = f_ptr->x_attr[i];
3865 char_old[i] = f_ptr->x_char[i];
3869 grp_idx[grp_cnt] = -1;
3871 FEAT_IDX old_grp_cur = -1;
3872 FEAT_IDX grp_cur = 0;
3873 FEAT_IDX grp_top = 0;
3874 FEAT_IDX feat_cur = 0;
3875 FEAT_IDX feat_top = 0;
3876 TERM_LEN column = 0;
3879 TERM_COLOR *cur_attr_ptr;
3880 SYMBOL_CODE *cur_char_ptr;
3884 feature_type *f_ptr;
3890 prt(_("表示 - 地形", "Visuals - features"), 2, 0);
3891 if (direct_f_idx < 0) prt(_("グループ", "Group"), 4, 0);
3892 prt(_("名前", "Name"), 4, max + 3);
3895 if (current_world_ptr->wizard || visual_only) prt("Idx", 4, 62);
3896 prt(_("文字 ( l/ d)", "Sym ( l/ d)"), 4, 66);
3900 if (current_world_ptr->wizard || visual_only) prt("Idx", 4, 64);
3901 prt(_("文字 (l/d)", "Sym (l/d)"), 4, 68);
3904 for (FEAT_IDX i = 0; i < 78; i++)
3906 Term_putch(i, 5, TERM_WHITE, '=');
3909 if (direct_f_idx < 0)
3911 for (FEAT_IDX i = 0; i < browser_rows; i++)
3913 Term_putch(max + 1, 6 + i, TERM_WHITE, '|');
3920 if (direct_f_idx < 0)
3922 if (grp_cur < grp_top) grp_top = grp_cur;
3923 if (grp_cur >= grp_top + browser_rows) grp_top = grp_cur - browser_rows + 1;
3925 display_group_list(0, 6, max, browser_rows, grp_idx, feature_group_text, grp_cur, grp_top);
3926 if (old_grp_cur != grp_cur)
3928 old_grp_cur = grp_cur;
3929 feat_cnt = collect_features(feat_idx, 0x00);
3932 while (feat_cur < feat_top)
3933 feat_top = MAX(0, feat_top - browser_rows / 2);
3934 while (feat_cur >= feat_top + browser_rows)
3935 feat_top = MIN(feat_cnt - browser_rows, feat_top + browser_rows / 2);
3940 display_feature_list(max + 3, 6, browser_rows, feat_idx, feat_cur, feat_top, visual_only, F_LIT_STANDARD);
3944 feat_top = feat_cur;
3945 display_feature_list(max + 3, 6, 1, feat_idx, feat_cur, feat_top, visual_only, *lighting_level);
3946 display_visual_list(max + 3, 7, browser_rows - 1, wid - (max + 3), attr_top, char_left);
3949 prt(format(_("<方向>%s, 'd'で標準光源効果%s, ESC", "<dir>%s, 'd' for default lighting%s, ESC"),
3950 visual_list ? _(", ENTERで決定, 'a'で対象明度変更", ", ENTER to accept, 'a' for lighting level") : _(", 'v'でシンボル変更", ", 'v' for visuals"),
3951 (attr_idx || char_idx) ? _(", 'c', 'p'でペースト", ", 'c', 'p' to paste") : _(", 'c'でコピー", ", 'c' to copy")),
3954 f_ptr = &f_info[feat_idx[feat_cur]];
3955 cur_attr_ptr = &f_ptr->x_attr[*lighting_level];
3956 cur_char_ptr = &f_ptr->x_char[*lighting_level];
3960 place_visual_list_cursor(max + 3, 7, *cur_attr_ptr, *cur_char_ptr, attr_top, char_left);
3964 Term_gotoxy(0, 6 + (grp_cur - grp_top));
3968 Term_gotoxy(max + 3, 6 + (feat_cur - feat_top));
3972 if (visual_list && ((ch == 'A') || (ch == 'a')))
3974 int prev_lighting_level = *lighting_level;
3978 if (*lighting_level <= 0) *lighting_level = F_LIT_MAX - 1;
3979 else (*lighting_level)--;
3983 if (*lighting_level >= F_LIT_MAX - 1) *lighting_level = 0;
3984 else (*lighting_level)++;
3987 if (f_ptr->x_attr[prev_lighting_level] != f_ptr->x_attr[*lighting_level])
3988 attr_top = MAX(0, (f_ptr->x_attr[*lighting_level] & 0x7f) - 5);
3990 if (f_ptr->x_char[prev_lighting_level] != f_ptr->x_char[*lighting_level])
3991 char_left = MAX(0, f_ptr->x_char[*lighting_level] - 10);
3995 else if ((ch == 'D') || (ch == 'd'))
3997 TERM_COLOR prev_x_attr = f_ptr->x_attr[*lighting_level];
3998 byte prev_x_char = f_ptr->x_char[*lighting_level];
4000 apply_default_feat_lighting(f_ptr->x_attr, f_ptr->x_char);
4004 if (prev_x_attr != f_ptr->x_attr[*lighting_level])
4005 attr_top = MAX(0, (f_ptr->x_attr[*lighting_level] & 0x7f) - 5);
4007 if (prev_x_char != f_ptr->x_char[*lighting_level])
4008 char_left = MAX(0, f_ptr->x_char[*lighting_level] - 10);
4010 else *need_redraw = TRUE;
4014 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))
4019 for (FEAT_IDX i = 0; i < F_LIT_MAX; i++)
4021 f_ptr->x_attr[i] = attr_old[i];
4022 f_ptr->x_char[i] = char_old[i];
4028 if (direct_f_idx >= 0) flag = TRUE;
4029 else *lighting_level = F_LIT_STANDARD;
4033 for (FEAT_IDX i = 0; i < F_LIT_MAX; i++)
4035 attr_old[i] = f_ptr->x_attr[i];
4036 char_old[i] = f_ptr->x_char[i];
4038 *lighting_level = F_LIT_STANDARD;
4045 for (FEAT_IDX i = 0; i < F_LIT_MAX; i++)
4047 attr_idx_feat[i] = f_ptr->x_attr[i];
4048 char_idx_feat[i] = f_ptr->x_char[i];
4057 for (FEAT_IDX i = F_LIT_NS_BEGIN; i < F_LIT_MAX; i++)
4059 if (attr_idx_feat[i] || (!(char_idx_feat[i] & 0x80) && char_idx_feat[i])) f_ptr->x_attr[i] = attr_idx_feat[i];
4060 if (char_idx_feat[i]) f_ptr->x_char[i] = char_idx_feat[i];
4078 browser_cursor(ch, &column, &grp_cur, grp_cnt, &feat_cur, feat_cnt);
4084 C_KILL(feat_idx, max_f_idx, FEAT_IDX);
4089 * List wanted monsters
4090 * @param creature_ptr プレーヤーへの参照ポインタ
4093 static void do_cmd_knowledge_bounty(player_type *creature_ptr)
4096 GAME_TEXT file_name[1024];
4097 fff = my_fopen_temp(file_name, 1024);
4100 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
4105 fprintf(fff, _("今日のターゲット : %s\n", "Today's target : %s\n"),
4106 (creature_ptr->today_mon ? r_name + r_info[creature_ptr->today_mon].name : _("不明", "unknown")));
4108 fprintf(fff, _("賞金首リスト\n", "List of wanted monsters\n"));
4109 fprintf(fff, "----------------------------------------------\n");
4111 bool listed = FALSE;
4112 for (int i = 0; i < MAX_BOUNTY; i++)
4114 if (current_world_ptr->bounty_r_idx[i] <= 10000)
4116 fprintf(fff, "%s\n", r_name + r_info[current_world_ptr->bounty_r_idx[i]].name);
4123 fprintf(fff, "\n%s\n", _("賞金首はもう残っていません。", "There are no more wanted monster."));
4127 (void)show_file(creature_ptr, TRUE, file_name, _("賞金首の一覧", "Wanted monsters"), 0, 0);
4132 * List virtues & status
4134 static void do_cmd_knowledge_virtues(player_type *creature_ptr)
4137 GAME_TEXT file_name[1024];
4138 fff = my_fopen_temp(file_name, 1024);
4141 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
4146 fprintf(fff, _("現在の属性 : %s\n\n", "Your alignment : %s\n\n"), your_alignment(creature_ptr));
4147 dump_virtues(creature_ptr, fff);
4149 (void)show_file(creature_ptr, TRUE, file_name, _("八つの徳", "Virtues"), 0, 0);
4156 static void do_cmd_knowledge_dungeon(player_type *creature_ptr)
4159 GAME_TEXT file_name[1024];
4160 fff = my_fopen_temp(file_name, 1024);
4163 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
4168 for (int i = 1; i < current_world_ptr->max_d_idx; i++)
4172 if (!d_info[i].maxdepth) continue;
4173 if (!max_dlv[i]) continue;
4174 if (d_info[i].final_guardian)
4176 if (!r_info[d_info[i].final_guardian].max_num) seiha = TRUE;
4178 else if (max_dlv[i] == d_info[i].maxdepth) seiha = TRUE;
4180 fprintf(fff, _("%c%-12s : %3d 階\n", "%c%-16s : level %3d\n"), seiha ? '!' : ' ', d_name + d_info[i].name, (int)max_dlv[i]);
4184 (void)show_file(creature_ptr, TRUE, file_name, _("今までに入ったダンジョン", "Dungeon"), 0, 0);
4190 * List virtues & status
4193 static void do_cmd_knowledge_stat(player_type *creature_ptr)
4196 GAME_TEXT file_name[1024];
4197 fff = my_fopen_temp(file_name, 1024);
4200 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
4205 int percent = (int)(((long)creature_ptr->player_hp[PY_MAX_LEVEL - 1] * 200L) /
4206 (2 * creature_ptr->hitdie +
4207 ((PY_MAX_LEVEL - 1 + 3) * (creature_ptr->hitdie + 1))));
4209 if (creature_ptr->knowledge & KNOW_HPRATE)
4210 fprintf(fff, _("現在の体力ランク : %d/100\n\n", "Your current Life Rating is %d/100.\n\n"), percent);
4211 else fprintf(fff, _("現在の体力ランク : ???\n\n", "Your current Life Rating is ???.\n\n"));
4213 fprintf(fff, _("能力の最大値\n\n", "Limits of maximum stats\n\n"));
4214 for (int v_nr = 0; v_nr < A_MAX; v_nr++)
4216 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);
4217 else fprintf(fff, "%s ???\n", stat_names[v_nr]);
4220 dump_yourself(creature_ptr, fff);
4222 (void)show_file(creature_ptr, TRUE, file_name, _("自分に関する情報", "HP-rate & Max stat"), 0, 0);
4228 * todo player_typeではなくQUEST_IDXを引数にすべきかもしれない
4229 * Print all active quests
4230 * @param creature_ptr プレーヤーへの参照ポインタ
4233 static void do_cmd_knowledge_quests_current(player_type *creature_ptr, FILE *fff)
4236 char rand_tmp_str[120] = "\0";
4237 GAME_TEXT name[MAX_NLEN];
4238 monster_race *r_ptr;
4239 int rand_level = 100;
4242 fprintf(fff, _("《遂行中のクエスト》\n", "< Current Quest >\n"));
4244 for (QUEST_IDX i = 1; i < max_q_idx; i++)
4246 bool is_print = quest[i].status == QUEST_STATUS_TAKEN;
4247 is_print |= (quest[i].status == QUEST_STATUS_STAGE_COMPLETED) && (quest[i].type == QUEST_TYPE_TOWER);
4248 is_print |= quest[i].status == QUEST_STATUS_COMPLETED;
4252 QUEST_IDX old_quest = creature_ptr->current_floor_ptr->inside_quest;
4253 for (int j = 0; j < 10; j++)
4254 quest_text[j][0] = '\0';
4256 quest_text_line = 0;
4257 creature_ptr->current_floor_ptr->inside_quest = i;
4258 init_flags = INIT_SHOW_TEXT;
4259 process_dungeon_file(creature_ptr, "q_info.txt", 0, 0, 0, 0);
4260 creature_ptr->current_floor_ptr->inside_quest = old_quest;
4261 if (quest[i].flags & QUEST_FLAG_SILENT) continue;
4264 if (quest[i].type != QUEST_TYPE_RANDOM)
4266 char note[80] = "\0";
4268 if (quest[i].status == QUEST_STATUS_TAKEN || quest[i].status == QUEST_STATUS_STAGE_COMPLETED)
4270 switch (quest[i].type)
4272 case QUEST_TYPE_KILL_LEVEL:
4273 case QUEST_TYPE_KILL_ANY_LEVEL:
4274 r_ptr = &r_info[quest[i].r_idx];
4275 strcpy(name, r_name + r_ptr->name);
4276 if (quest[i].max_num > 1)
4279 sprintf(note, " - %d 体の%sを倒す。(あと %d 体)",
4280 (int)quest[i].max_num, name, (int)(quest[i].max_num - quest[i].cur_num));
4283 sprintf(note, " - kill %d %s, have killed %d.",
4284 (int)quest[i].max_num, name, (int)quest[i].cur_num);
4288 sprintf(note, _(" - %sを倒す。", " - kill %s."), name);
4291 case QUEST_TYPE_FIND_ARTIFACT:
4294 artifact_type *a_ptr = &a_info[quest[i].k_idx];
4296 object_type *q_ptr = &forge;
4297 KIND_OBJECT_IDX k_idx = lookup_kind(a_ptr->tval, a_ptr->sval);
4298 object_prep(q_ptr, k_idx);
4299 q_ptr->name1 = quest[i].k_idx;
4300 q_ptr->ident = IDENT_STORE;
4301 object_desc(creature_ptr, name, q_ptr, OD_NAME_ONLY);
4303 sprintf(note, _("\n - %sを見つけ出す。", "\n - Find %s."), name);
4305 case QUEST_TYPE_FIND_EXIT:
4306 sprintf(note, _(" - 出口に到達する。", " - Reach exit."));
4309 case QUEST_TYPE_KILL_NUMBER:
4311 sprintf(note, " - %d 体のモンスターを倒す。(あと %d 体)",
4312 (int)quest[i].max_num, (int)(quest[i].max_num - quest[i].cur_num));
4314 sprintf(note, " - Kill %d monsters, have killed %d.",
4315 (int)quest[i].max_num, (int)quest[i].cur_num);
4319 case QUEST_TYPE_KILL_ALL:
4320 case QUEST_TYPE_TOWER:
4321 sprintf(note, _(" - 全てのモンスターを倒す。", " - Kill all monsters."));
4326 sprintf(tmp_str, _(" %s (危険度:%d階相当)%s\n", " %s (Danger level: %d)%s\n"),
4327 quest[i].name, (int)quest[i].level, note);
4328 fputs(tmp_str, fff);
4329 if (quest[i].status == QUEST_STATUS_COMPLETED)
4331 sprintf(tmp_str, _(" クエスト達成 - まだ報酬を受けとってない。\n", " Quest Completed - Unrewarded\n"));
4332 fputs(tmp_str, fff);
4337 while (quest_text[k][0] && k < 10)
4339 fprintf(fff, " %s\n", quest_text[k]);
4346 if (quest[i].level >= rand_level)
4349 rand_level = quest[i].level;
4350 if (max_dlv[DUNGEON_ANGBAND] < rand_level) continue;
4352 r_ptr = &r_info[quest[i].r_idx];
4353 strcpy(name, r_name + r_ptr->name);
4354 if (quest[i].max_num <= 1)
4356 sprintf(rand_tmp_str, _(" %s (%d 階) - %sを倒す。\n", " %s (Dungeon level: %d)\n Kill %s.\n"),
4357 quest[i].name, (int)quest[i].level, name);
4362 sprintf(rand_tmp_str, " %s (%d 階) - %d 体の%sを倒す。(あと %d 体)\n",
4363 quest[i].name, (int)quest[i].level,
4364 (int)quest[i].max_num, name, (int)(quest[i].max_num - quest[i].cur_num));
4368 sprintf(rand_tmp_str, " %s (Dungeon level: %d)\n Kill %d %s, have killed %d.\n",
4369 quest[i].name, (int)quest[i].level,
4370 (int)quest[i].max_num, name, (int)quest[i].cur_num);
4374 if (rand_tmp_str[0]) fputs(rand_tmp_str, fff);
4376 if (!total) fprintf(fff, _(" なし\n", " Nothing.\n"));
4380 static bool do_cmd_knowledge_quests_aux(player_type *player_ptr, FILE *fff, IDX q_idx)
4383 char playtime_str[16];
4384 quest_type* const q_ptr = &quest[q_idx];
4386 floor_type *floor_ptr = player_ptr->current_floor_ptr;
4387 if (is_fixed_quest_idx(q_idx))
4389 IDX old_quest = floor_ptr->inside_quest;
4390 floor_ptr->inside_quest = q_idx;
4391 init_flags = INIT_NAME_ONLY;
4392 process_dungeon_file(player_ptr, "q_info.txt", 0, 0, 0, 0);
4393 floor_ptr->inside_quest = old_quest;
4394 if (q_ptr->flags & QUEST_FLAG_SILENT) return FALSE;
4397 strnfmt(playtime_str, sizeof(playtime_str), "%02d:%02d:%02d",
4398 q_ptr->comptime / (60 * 60), (q_ptr->comptime / 60) % 60, q_ptr->comptime % 60);
4400 if (is_fixed_quest_idx(q_idx) || (q_ptr->r_idx == 0))
4403 _(" %-35s (危険度:%3d階相当) - レベル%2d - %s\n",
4404 " %-35s (Danger level: %3d) - level %2d - %s\n"),
4405 q_ptr->name, (int)q_ptr->level, q_ptr->complev, playtime_str);
4406 fputs(tmp_str, fff);
4410 if (q_ptr->complev == 0)
4413 _(" %-35s (%3d階) - 不戦勝 - %s\n",
4414 " %-35s (Dungeon level: %3d) - Unearned - %s\n"),
4415 r_name + r_info[q_ptr->r_idx].name,
4416 (int)q_ptr->level, playtime_str);
4417 fputs(tmp_str, fff);
4422 _(" %-35s (%3d階) - レベル%2d - %s\n",
4423 " %-35s (Dungeon level: %3d) - level %2d - %s\n"),
4424 r_name + r_info[q_ptr->r_idx].name,
4428 fputs(tmp_str, fff);
4434 * Print all finished quests
4435 * @param creature_ptr プレーヤーへの参照ポインタ
4436 * @param fff セーブファイル (展開済?)
4437 * @param quest_num[] 受注したことのあるクエスト群
4440 void do_cmd_knowledge_quests_completed(player_type *creature_ptr, FILE *fff, QUEST_IDX quest_num[])
4442 fprintf(fff, _("《達成したクエスト》\n", "< Completed Quest >\n"));
4443 QUEST_IDX total = 0;
4444 for (QUEST_IDX i = 1; i < max_q_idx; i++)
4446 QUEST_IDX q_idx = quest_num[i];
4447 quest_type* const q_ptr = &quest[q_idx];
4449 if (q_ptr->status == QUEST_STATUS_FINISHED && do_cmd_knowledge_quests_aux(creature_ptr, fff, q_idx))
4455 if (!total) fprintf(fff, _(" なし\n", " Nothing.\n"));
4460 * Print all failed quests
4461 * @param creature_ptr プレーヤーへの参照ポインタ
4462 * @param fff セーブファイル (展開済?)
4463 * @param quest_num[] 受注したことのあるクエスト群
4466 void do_cmd_knowledge_quests_failed(player_type *creature_ptr, FILE *fff, QUEST_IDX quest_num[])
4468 fprintf(fff, _("《失敗したクエスト》\n", "< Failed Quest >\n"));
4469 QUEST_IDX total = 0;
4470 for (QUEST_IDX i = 1; i < max_q_idx; i++)
4472 QUEST_IDX q_idx = quest_num[i];
4473 quest_type* const q_ptr = &quest[q_idx];
4475 if (((q_ptr->status == QUEST_STATUS_FAILED_DONE) || (q_ptr->status == QUEST_STATUS_FAILED)) &&
4476 do_cmd_knowledge_quests_aux(creature_ptr, fff, q_idx))
4482 if (!total) fprintf(fff, _(" なし\n", " Nothing.\n"));
4487 * Print all random quests
4489 static void do_cmd_knowledge_quests_wiz_random(FILE *fff)
4491 fprintf(fff, _("《残りのランダムクエスト》\n", "< Remaining Random Quest >\n"));
4492 GAME_TEXT tmp_str[120];
4493 QUEST_IDX total = 0;
4494 for (QUEST_IDX i = 1; i < max_q_idx; i++)
4496 if (quest[i].flags & QUEST_FLAG_SILENT) continue;
4498 if ((quest[i].type == QUEST_TYPE_RANDOM) && (quest[i].status == QUEST_STATUS_TAKEN))
4501 sprintf(tmp_str, _(" %s (%d階, %s)\n", " %s (%d, %s)\n"),
4502 quest[i].name, (int)quest[i].level, r_name + r_info[quest[i].r_idx].name);
4503 fputs(tmp_str, fff);
4507 if (!total) fprintf(fff, _(" なし\n", " Nothing.\n"));
4511 * Print quest status of all active quests
4512 * @param creature_ptr プレーヤーへの参照ポインタ
4515 static void do_cmd_knowledge_quests(player_type *creature_ptr)
4518 GAME_TEXT file_name[1024];
4519 fff = my_fopen_temp(file_name, 1024);
4522 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
4528 C_MAKE(quest_num, max_q_idx, QUEST_IDX);
4530 for (IDX i = 1; i < max_q_idx; i++)
4534 ang_sort(quest_num, &dummy, max_q_idx, ang_sort_comp_quest_num, ang_sort_swap_quest_num);
4536 do_cmd_knowledge_quests_current(creature_ptr, fff);
4538 do_cmd_knowledge_quests_completed(creature_ptr, fff, quest_num);
4540 do_cmd_knowledge_quests_failed(creature_ptr, fff, quest_num);
4541 if (current_world_ptr->wizard)
4544 do_cmd_knowledge_quests_wiz_random(fff);
4548 (void)show_file(creature_ptr, TRUE, file_name, _("クエスト達成状況", "Quest status"), 0, 0);
4550 C_KILL(quest_num, max_q_idx, QUEST_IDX);
4556 * @param player_ptr プレーヤーへの参照ポインタ
4559 static void do_cmd_knowledge_home(player_type *player_ptr)
4561 process_dungeon_file(player_ptr, "w_info.txt", 0, 0, current_world_ptr->max_wild_y, current_world_ptr->max_wild_x);
4563 /* Open a new file */
4565 GAME_TEXT file_name[1024];
4566 fff = my_fopen_temp(file_name, 1024);
4569 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
4575 st_ptr = &town_info[1].store[STORE_HOME];
4577 if (st_ptr->stock_num)
4582 fprintf(fff, _(" [ 我が家のアイテム ]\n", " [Home Inventory]\n"));
4583 concptr paren = ")";
4584 GAME_TEXT o_name[MAX_NLEN];
4585 for (int i = 0; i < st_ptr->stock_num; i++)
4588 if ((i % 12) == 0) fprintf(fff, "\n ( %d ページ )\n", x++);
4589 object_desc(player_ptr, o_name, &st_ptr->stock[i], 0);
4590 if (strlen(o_name) <= 80 - 3)
4592 fprintf(fff, "%c%s %s\n", I2A(i % 12), paren, o_name);
4598 for (n = 0, t = o_name; n < 80 - 3; n++, t++)
4599 if (iskanji(*t)) { t++; n++; }
4600 if (n == 81 - 3) n = 79 - 3; /* 最後が漢字半分 */
4602 fprintf(fff, "%c%s %.*s\n", I2A(i % 12), paren, n, o_name);
4603 fprintf(fff, " %.77s\n", o_name + n);
4606 object_desc(player_ptr, o_name, &st_ptr->stock[i], 0);
4607 fprintf(fff, "%c%s %s\n", I2A(i % 12), paren, o_name);
4611 fprintf(fff, "\n\n");
4615 (void)show_file(player_ptr, TRUE, file_name, _("我が家のアイテム", "Home Inventory"), 0, 0);
4621 * Check the status of "autopick"
4623 static void do_cmd_knowledge_autopick(player_type *creature_ptr)
4625 /* Open a new file */
4627 GAME_TEXT file_name[1024];
4628 fff = my_fopen_temp(file_name, 1024);
4631 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
4638 fprintf(fff, _("自動破壊/拾いには何も登録されていません。", "No preference for auto picker/destroyer."));
4642 fprintf(fff, _(" 自動拾い/破壊には現在 %d行登録されています。\n\n",
4643 " There are %d registered lines for auto picker/destroyer.\n\n"), max_autopick);
4646 for (int k = 0; k < max_autopick; k++)
4649 byte act = autopick_list[k].action;
4650 if (act & DONT_AUTOPICK)
4652 tmp = _("放置", "Leave");
4654 else if (act & DO_AUTODESTROY)
4656 tmp = _("破壊", "Destroy");
4658 else if (act & DO_AUTOPICK)
4660 tmp = _("拾う", "Pickup");
4664 tmp = _("確認", "Query");
4667 if (act & DO_DISPLAY)
4668 fprintf(fff, "%11s", format("[%s]", tmp));
4670 fprintf(fff, "%11s", format("(%s)", tmp));
4672 tmp = autopick_line_from_entry(&autopick_list[k]);
4673 fprintf(fff, " %s", tmp);
4680 (void)show_file(creature_ptr, TRUE, file_name, _("自動拾い/破壊 設定リスト", "Auto-picker/Destroyer"), 0, 0);
4686 * Interact with "knowledge"
4688 void do_cmd_knowledge(player_type *creature_ptr)
4691 bool need_redraw = FALSE;
4692 FILE_TYPE(FILE_TYPE_TEXT);
4697 prt(format(_("%d/2 ページ", "page %d/2"), (p + 1)), 2, 65);
4698 prt(_("現在の知識を確認する", "Display current knowledge"), 3, 0);
4703 prt("(1) 既知の伝説のアイテム の一覧", 6, 5);
4704 prt("(2) 既知のアイテム の一覧", 7, 5);
4705 prt("(3) 既知の生きているユニーク・モンスター の一覧", 8, 5);
4706 prt("(4) 既知のモンスター の一覧", 9, 5);
4707 prt("(5) 倒した敵の数 の一覧", 10, 5);
4708 if (!vanilla_town) prt("(6) 賞金首 の一覧", 11, 5);
4709 prt("(7) 現在のペット の一覧", 12, 5);
4710 prt("(8) 我が家のアイテム の一覧", 13, 5);
4711 prt("(9) *鑑定*済み装備の耐性 の一覧", 14, 5);
4712 prt("(0) 地形の表示文字/タイル の一覧", 15, 5);
4716 prt("(a) 自分に関する情報 の一覧", 6, 5);
4717 prt("(b) 突然変異 の一覧", 7, 5);
4718 prt("(c) 武器の経験値 の一覧", 8, 5);
4719 prt("(d) 魔法の経験値 の一覧", 9, 5);
4720 prt("(e) 技能の経験値 の一覧", 10, 5);
4721 prt("(f) プレイヤーの徳 の一覧", 11, 5);
4722 prt("(g) 入ったダンジョン の一覧", 12, 5);
4723 prt("(h) 実行中のクエスト の一覧", 13, 5);
4724 prt("(i) 現在の自動拾い/破壊設定 の一覧", 14, 5);
4729 prt("(1) Display known artifacts", 6, 5);
4730 prt("(2) Display known objects", 7, 5);
4731 prt("(3) Display remaining uniques", 8, 5);
4732 prt("(4) Display known monster", 9, 5);
4733 prt("(5) Display kill count", 10, 5);
4734 if (!vanilla_town) prt("(6) Display wanted monsters", 11, 5);
4735 prt("(7) Display current pets", 12, 5);
4736 prt("(8) Display home inventory", 13, 5);
4737 prt("(9) Display *identified* equip.", 14, 5);
4738 prt("(0) Display terrain symbols.", 15, 5);
4742 prt("(a) Display about yourself", 6, 5);
4743 prt("(b) Display mutations", 7, 5);
4744 prt("(c) Display weapon proficiency", 8, 5);
4745 prt("(d) Display spell proficiency", 9, 5);
4746 prt("(e) Display misc. proficiency", 10, 5);
4747 prt("(f) Display virtues", 11, 5);
4748 prt("(g) Display dungeons", 12, 5);
4749 prt("(h) Display current quests", 13, 5);
4750 prt("(i) Display auto pick/destroy", 14, 5);
4753 prt(_("-続く-", "-more-"), 17, 8);
4754 prt(_("ESC) 抜ける", "ESC) Exit menu"), 21, 1);
4755 prt(_("SPACE) 次ページ", "SPACE) Next page"), 21, 30);
4756 prt(_("コマンド:", "Command: "), 20, 0);
4759 if (i == ESCAPE) break;
4762 case ' ': /* Page change */
4766 case '1': /* Artifacts */
4767 do_cmd_knowledge_artifacts(creature_ptr);
4769 case '2': /* Objects */
4770 do_cmd_knowledge_objects(creature_ptr, &need_redraw, FALSE, -1);
4772 case '3': /* Uniques */
4773 do_cmd_knowledge_uniques(creature_ptr);
4775 case '4': /* Monsters */
4776 do_cmd_knowledge_monsters(creature_ptr, &need_redraw, FALSE, -1);
4778 case '5': /* Kill count */
4779 do_cmd_knowledge_kill_count(creature_ptr);
4781 case '6': /* wanted */
4782 if (!vanilla_town) do_cmd_knowledge_bounty(creature_ptr);
4784 case '7': /* Pets */
4785 do_cmd_knowledge_pets(creature_ptr);
4787 case '8': /* Home */
4788 do_cmd_knowledge_home(creature_ptr);
4790 case '9': /* Resist list */
4791 do_cmd_knowledge_inven(creature_ptr);
4793 case '0': /* Feature list */
4795 IDX lighting_level = F_LIT_STANDARD;
4796 do_cmd_knowledge_features(&need_redraw, FALSE, -1, &lighting_level);
4800 case 'a': /* Max stat */
4801 do_cmd_knowledge_stat(creature_ptr);
4803 case 'b': /* Mutations */
4804 do_cmd_knowledge_mutations(creature_ptr);
4806 case 'c': /* weapon-exp */
4807 do_cmd_knowledge_weapon_exp(creature_ptr);
4809 case 'd': /* spell-exp */
4810 do_cmd_knowledge_spell_exp(creature_ptr);
4812 case 'e': /* skill-exp */
4813 do_cmd_knowledge_skill_exp(creature_ptr);
4815 case 'f': /* Virtues */
4816 do_cmd_knowledge_virtues(creature_ptr);
4818 case 'g': /* Dungeon */
4819 do_cmd_knowledge_dungeon(creature_ptr);
4821 case 'h': /* Quests */
4822 do_cmd_knowledge_quests(creature_ptr);
4824 case 'i': /* Autopick */
4825 do_cmd_knowledge_autopick(creature_ptr);
4827 default: /* Unknown option */
4835 if (need_redraw) do_cmd_redraw(creature_ptr);
4840 * Check on the status of an active quest
4841 * @param creature_ptr プレーヤーへの参照ポインタ
4844 void do_cmd_checkquest(player_type *creature_ptr)
4846 FILE_TYPE(FILE_TYPE_TEXT);
4848 do_cmd_knowledge_quests(creature_ptr);
4854 * Display the time and date
4855 * @param creature_ptr プレーヤーへの参照ポインタ
4858 void do_cmd_time(player_type *creature_ptr)
4861 extract_day_hour_min(creature_ptr, &day, &hour, &min);
4864 strcpy(desc, _("変な時刻だ。", "It is a strange time."));
4867 if (day < MAX_DAYS) sprintf(day_buf, "%d", day);
4868 else strcpy(day_buf, "*****");
4870 msg_format(_("%s日目, 時刻は%d:%02d %sです。", "This is day %s. The time is %d:%02d %s."),
4871 day_buf, (hour % 12 == 0) ? 12 : (hour % 12), min, (hour < 12) ? "AM" : "PM");
4874 if (!randint0(10) || creature_ptr->image)
4876 path_build(buf, sizeof(buf), ANGBAND_DIR_FILE, _("timefun_j.txt", "timefun.txt"));
4880 path_build(buf, sizeof(buf), ANGBAND_DIR_FILE, _("timenorm_j.txt", "timenorm.txt"));
4884 fff = my_fopen(buf, "rt");
4888 int full = hour * 100 + min;
4892 while (!my_fgets(fff, buf, sizeof(buf)))
4894 if (!buf[0] || (buf[0] == '#')) continue;
4895 if (buf[1] != ':') continue;
4899 start = atoi(buf + 2);
4906 end = atoi(buf + 2);
4910 if ((start > full) || (full > end)) continue;
4915 if (!randint0(num)) strcpy(desc, buf + 2);