OSDN Git Service

[fix] #40233 リファクタリングで起きている大量のビルドエラーを修正中。差し当たり、インクルード抜けを1件修正. / Add a lost #include.
[hengband/hengband.git] / src / cmd / cmd-dump.c
1 /*!
2  * @file cmd-dump.c
3  * @brief プレイヤーのインターフェイスに関するコマンドの実装 / Interface commands
4  * @date 2014/01/02
5  * @author
6  * <pre>
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.
11  * </pre>
12  * @details
13  * <pre>
14  * A set of functions to maintain automatic dumps of various kinds.
15  * The dump commands of original Angband simply add new lines to
16  * existing files; these files will become bigger and bigger unless
17  * an user deletes some or all of these files by hand at some
18  * point.
19  * These three functions automatically delete old dumped lines
20  * before adding new ones.  Since there are various kinds of automatic
21  * dumps in a single file, we add a header and a footer with a type
22  * name for every automatic dump, and kill old lines only when the
23  * lines have the correct type of header and footer.
24  * We need to be quite paranoid about correctness; the user might
25  * (mistakenly) edit the file by hand, and see all their work come
26  * to nothing on the next auto dump otherwise.  The current code only
27  * detects changes by noting inconsistencies between the actual number
28  * of lines and the number written in the footer.  Note that this will
29  * not catch single-line edits.
30  * </pre>
31  */
32
33 #include "angband.h"
34 #include "cmd/cmd-draw.h"
35 #include "cmd/cmd-dump.h"
36 #include "cmd/lighting-level-table.h"
37 #include "cmd/cmd-visuals.h"
38 #include "term.h"
39 #include "core.h" // 暫定。後で消す.
40 #include "core/show-file.h"
41 #include "io/read-pref-file.h"
42 #include "io/interpret-pref-file.h"
43 #include "autopick.h"
44 #include "birth.h"
45 #include "dungeon.h"
46 #include "world.h"
47 #include "view/display-player.h" // 暫定。後で消す.
48 #include "player/process-name.h"
49 #include "player-effects.h"
50 #include "player-skill.h"
51 #include "player-personality.h"
52 #include "sort.h"
53 #include "mutation.h"
54 #include "quest.h"
55 #include "store.h"
56 #include "artifact.h"
57 #include "avatar.h"
58 #include "object-flavor.h"
59 #include "object-hook.h"
60 #include "monster-status.h"
61 #include "dungeon-file.h"
62 #include "objectkind.h"
63 #include "floor-town.h"
64 #include "cmd/feeling-table.h"
65 #include "cmd/monster-group-table.h"
66 #include "cmd/object-group-table.h"
67 #include "market/store-util.h"
68 #include "view-mainwindow.h" // 暫定。後で消す
69 #include "english.h"
70
71 #include "diary-subtitle-table.h"
72
73 // Clipboard variables for copy&paste in visual mode
74 static TERM_COLOR attr_idx = 0;
75 static SYMBOL_CODE char_idx = 0;
76
77 static TERM_COLOR attr_idx_feat[F_LIT_MAX];
78 static SYMBOL_CODE char_idx_feat[F_LIT_MAX];
79
80 // Encode the screen colors
81 static char hack[17] = "dwsorgbuDWvyRGBU";
82
83 /*!
84 <<<<<<< HEAD
85  * @brief prefファイルを選択して処理する /
86  * Ask for a "user pref line" and process it
87 =======
88  * @brief prf出力内容を消去する /
89  * Remove old lines automatically generated before.
90  * @param orig_file 消去を行うファイル名
91  */
92 static void remove_auto_dump(concptr orig_file)
93 {
94         FILE *tmp_fff, *orig_fff;
95         char tmp_file[1024];
96         char buf[1024];
97         bool between_mark = FALSE;
98         bool changed = FALSE;
99         int line_num = 0;
100         long header_location = 0;
101         char header_mark_str[80];
102         char footer_mark_str[80];
103
104         sprintf(header_mark_str, auto_dump_header, auto_dump_mark);
105         sprintf(footer_mark_str, auto_dump_footer, auto_dump_mark);
106         size_t mark_len = strlen(footer_mark_str);
107         orig_fff = my_fopen(orig_file, "r");
108         if (!orig_fff) return;
109
110         tmp_fff = my_fopen_temp(tmp_file, 1024);
111         if (!tmp_fff)
112         {
113                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), tmp_file);
114                 msg_print(NULL);
115                 return;
116         }
117
118         while (TRUE)
119         {
120                 if (my_fgets(orig_fff, buf, sizeof(buf)))
121                 {
122                         if (between_mark)
123                         {
124                                 fseek(orig_fff, header_location, SEEK_SET);
125                                 between_mark = FALSE;
126                                 continue;
127                         }
128                         else
129                         {
130                                 break;
131                         }
132                 }
133
134                 if (!between_mark)
135                 {
136                         if (!strcmp(buf, header_mark_str))
137                         {
138                                 header_location = ftell(orig_fff);
139                                 line_num = 0;
140                                 between_mark = TRUE;
141                                 changed = TRUE;
142                         }
143                         else
144                         {
145                                 fprintf(tmp_fff, "%s\n", buf);
146                         }
147
148                         continue;
149                 }
150
151                 if (!strncmp(buf, footer_mark_str, mark_len))
152                 {
153                         int tmp;
154                         if (!sscanf(buf + mark_len, " (%d)", &tmp)
155                                 || tmp != line_num)
156                         {
157                                 fseek(orig_fff, header_location, SEEK_SET);
158                         }
159
160                         between_mark = FALSE;
161                         continue;
162                 }
163
164                 line_num++;
165         }
166
167         my_fclose(orig_fff);
168         my_fclose(tmp_fff);
169
170         if (changed)
171         {
172                 tmp_fff = my_fopen(tmp_file, "r");
173                 orig_fff = my_fopen(orig_file, "w");
174                 while (!my_fgets(tmp_fff, buf, sizeof(buf)))
175                         fprintf(orig_fff, "%s\n", buf);
176
177                 my_fclose(orig_fff);
178                 my_fclose(tmp_fff);
179         }
180
181         fd_kill(tmp_file);
182 }
183
184
185 /*!
186  * @brief prfファイルのフォーマットに従った内容を出力する /
187  * Dump a formatted line, using "vstrnfmt()".
188  * @param fmt 出力内容
189  */
190 static void auto_dump_printf(concptr fmt, ...)
191 {
192         va_list vp;
193         char buf[1024];
194         va_start(vp, fmt);
195         (void)vstrnfmt(buf, sizeof(buf), fmt, vp);
196         va_end(vp);
197         for (concptr p = buf; *p; p++)
198         {
199                 if (*p == '\n') auto_dump_line_num++;
200         }
201
202         fprintf(auto_dump_stream, "%s", buf);
203 }
204
205
206 /*!
207  * @brief prfファイルをファイルオープンする /
208  * Open file to append auto dump.
209  * @param buf ファイル名
210  * @param mark 出力するヘッダマーク
211  * @return ファイルポインタを取得できたらTRUEを返す
212  */
213 static bool open_auto_dump(concptr buf, concptr mark)
214 {
215         char header_mark_str[80];
216         auto_dump_mark = mark;
217         sprintf(header_mark_str, auto_dump_header, auto_dump_mark);
218         remove_auto_dump(buf);
219         auto_dump_stream = my_fopen(buf, "a");
220         if (!auto_dump_stream)
221         {
222                 msg_format(_("%s を開くことができませんでした。", "Failed to open %s."), buf);
223                 msg_print(NULL);
224                 return FALSE;
225         }
226
227         fprintf(auto_dump_stream, "%s\n", header_mark_str);
228         auto_dump_line_num = 0;
229         auto_dump_printf(_("# *警告!!* 以降の行は自動生成されたものです。\n",
230                 "# *Warning!*  The lines below are an automatic dump.\n"));
231         auto_dump_printf(_("# *警告!!* 後で自動的に削除されるので編集しないでください。\n",
232                 "# Don't edit them; changes will be deleted and replaced automatically.\n"));
233         return TRUE;
234 }
235
236 /*!
237  * @brief prfファイルをファイルクローズする /
238  * Append foot part and close auto dump.
239  * @return なし
240  */
241 static void close_auto_dump(void)
242 {
243         char footer_mark_str[80];
244         sprintf(footer_mark_str, auto_dump_footer, auto_dump_mark);
245         auto_dump_printf(_("# *警告!!* 以降の行は自動生成されたものです。\n",
246                 "# *Warning!*  The lines below are an automatic dump.\n"));
247         auto_dump_printf(_("# *警告!!* 後で自動的に削除されるので編集しないでください。\n",
248                 "# Don't edit them; changes will be deleted and replaced automatically.\n"));
249         fprintf(auto_dump_stream, "%s (%d)\n", footer_mark_str, auto_dump_line_num);
250         my_fclose(auto_dump_stream);
251 }
252
253
254 #ifdef JP
255 #else
256 /*!
257  * @brief Return suffix of ordinal number
258  * @param num number
259  * @return pointer of suffix string.
260  */
261 concptr get_ordinal_number_suffix(int num)
262 {
263         num = ABS(num) % 100;
264         switch (num % 10)
265         {
266         case 1:
267                 return (num == 11) ? "th" : "st";
268         case 2:
269                 return (num == 12) ? "th" : "nd";
270         case 3:
271                 return (num == 13) ? "th" : "rd";
272         default:
273                 return "th";
274         }
275 }
276 #endif
277
278
279 /*!
280  * @brief 日記のタイトル表記と内容出力
281  * @param creature_ptr プレーヤーへの参照ポインタ
282  * @return なし
283  */
284 static void display_diary(player_type *creature_ptr)
285 {
286         char diary_title[256];
287         GAME_TEXT file_name[MAX_NLEN];
288         char buf[1024];
289         char tmp[80];
290         sprintf(file_name, _("playrecord-%s.txt", "playrec-%s.txt"), savefile_base);
291         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, file_name);
292
293         if (creature_ptr->pclass == CLASS_WARRIOR || creature_ptr->pclass == CLASS_MONK || creature_ptr->pclass == CLASS_SAMURAI || creature_ptr->pclass == CLASS_BERSERKER)
294                 strcpy(tmp, subtitle[randint0(MAX_SUBTITLE - 1)]);
295         else if (IS_WIZARD_CLASS(creature_ptr))
296                 strcpy(tmp, subtitle[randint0(MAX_SUBTITLE - 1) + 1]);
297         else strcpy(tmp, subtitle[randint0(MAX_SUBTITLE - 2) + 1]);
298
299 #ifdef JP
300         sprintf(diary_title, "「%s%s%sの伝説 -%s-」", ap_ptr->title, ap_ptr->no ? "の" : "", creature_ptr->name, tmp);
301 #else
302         sprintf(diary_title, "Legend of %s %s '%s'", ap_ptr->title, creature_ptr->name, tmp);
303 #endif
304
305         (void)show_file(creature_ptr, FALSE, buf, diary_title, -1, 0);
306 }
307
308
309 /*!
310  * @brief 日記に任意の内容を表記するコマンドのメインルーチン /
311  * @return なし
312  */
313 static void add_diary_note(player_type *creature_ptr)
314 {
315         char tmp[80] = "\0";
316         char bunshou[80] = "\0";
317         if (get_string(_("内容: ", "diary note: "), tmp, 79))
318         {
319                 strcpy(bunshou, tmp);
320                 exe_write_diary(creature_ptr, DIARY_DESCRIPTION, 0, bunshou);
321         }
322 }
323
324 /*!
325  * @brief 最後に取得したアイテムの情報を日記に追加するメインルーチン /
326  * @return なし
327  */
328 static void do_cmd_last_get(player_type *creaute_ptr)
329 {
330         if (record_o_name[0] == '\0') return;
331
332         char buf[256];
333         sprintf(buf, _("%sの入手を記録します。", "Do you really want to record getting %s? "), record_o_name);
334         if (!get_check(buf)) return;
335
336         GAME_TURN turn_tmp = current_world_ptr->game_turn;
337         current_world_ptr->game_turn = record_turn;
338         sprintf(buf, _("%sを手に入れた。", "discovered %s."), record_o_name);
339         exe_write_diary(creaute_ptr, DIARY_DESCRIPTION, 0, buf);
340         current_world_ptr->game_turn = turn_tmp;
341 }
342
343
344 /*!
345  * @brief ファイル中の全日記記録を消去する /
346  * @return なし
347  */
348 static void do_cmd_erase_diary(void)
349 {
350         GAME_TEXT file_name[MAX_NLEN];
351         char buf[256];
352         FILE *fff = NULL;
353
354         if (!get_check(_("本当に記録を消去しますか?", "Do you really want to delete all your record? "))) return;
355         sprintf(file_name, _("playrecord-%s.txt", "playrec-%s.txt"), savefile_base);
356         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, file_name);
357         fd_kill(buf);
358
359         fff = my_fopen(buf, "w");
360         if (fff)
361         {
362                 my_fclose(fff);
363                 msg_format(_("記録を消去しました。", "deleted record."));
364         }
365         else
366         {
367                 msg_format(_("%s の消去に失敗しました。", "failed to delete %s."), buf);
368         }
369
370         msg_print(NULL);
371 }
372
373
374 /*!
375  * @brief 日記コマンド
376  * @param crerature_ptr プレーヤーへの参照ポインタ
377  * @return なし
378  */
379 void do_cmd_diary(player_type *creature_ptr)
380 {
381         FILE_TYPE(FILE_TYPE_TEXT);
382         screen_save();
383         int i;
384         while (TRUE)
385         {
386                 Term_clear();
387                 prt(_("[ 記録の設定 ]", "[ Play Record ]"), 2, 0);
388                 prt(_("(1) 記録を見る", "(1) Display your record"), 4, 5);
389                 prt(_("(2) 文章を記録する", "(2) Add record"), 5, 5);
390                 prt(_("(3) 直前に入手又は鑑定したものを記録する", "(3) Record the last item you got or identified"), 6, 5);
391                 prt(_("(4) 記録を消去する", "(4) Delete your record"), 7, 5);
392                 prt(_("(R) プレイ動画を記録する/中止する", "(R) Record playing movie / or stop it"), 9, 5);
393                 prt(_("コマンド:", "Command: "), 18, 0);
394                 i = inkey();
395                 if (i == ESCAPE) break;
396
397                 switch (i)
398                 {
399                 case '1':
400                         display_diary(creature_ptr);
401                         break;
402                 case '2':
403                         add_diary_note(creature_ptr);
404                         break;
405                 case '3':
406                         do_cmd_last_get(creature_ptr);
407                         break;
408                 case '4':
409                         do_cmd_erase_diary();
410                         break;
411                 case 'r': case 'R':
412                         screen_load();
413                         prepare_movie_hooks();
414                         return;
415                 default:
416                         bell();
417                 }
418
419                 msg_erase();
420         }
421
422         screen_load();
423 }
424
425
426 /*!
427  * @brief 画面を再描画するコマンドのメインルーチン
428  * Hack -- redraw the screen
429 >>>>>>> aed56f4e1a8c71b3fc97b2fa5265f3c13efc2da1
430  * @param creature_ptr プレーヤーへの参照ポインタ
431  * @return なし
432  * @details
433  * Allow absolute file names?
434  */
435 void do_cmd_pref(player_type *creature_ptr)
436 {
437         char buf[80];
438         strcpy(buf, "");
439         if (!get_string(_("設定変更コマンド: ", "Pref: "), buf, 80)) return;
440
441         (void)interpret_pref_file(creature_ptr, buf);
442 }
443
444
445 /*!
446  * @brief 自動拾い設定ファイルをロードするコマンドのメインルーチン /
447  * @param creature_ptr プレーヤーへの参照ポインタ
448  * @return なし
449  */
450 void do_cmd_reload_autopick(player_type *creature_ptr)
451 {
452         if (!get_check(_("自動拾い設定ファイルをロードしますか? ", "Reload auto-pick preference file? ")))
453                 return;
454
455         autopick_load_pref(creature_ptr, TRUE);
456 }
457
458
459 /*
460  * Interact with "colors"
461  */
462 void do_cmd_colors(player_type *creature_ptr)
463 {
464         int i;
465         char tmp[160];
466         char buf[1024];
467         FILE_TYPE(FILE_TYPE_TEXT);
468         screen_save();
469         while (TRUE)
470         {
471                 Term_clear();
472                 prt(_("[ カラーの設定 ]", "Interact with Colors"), 2, 0);
473                 prt(_("(1) ユーザー設定ファイルのロード", "(1) Load a user pref file"), 4, 5);
474                 prt(_("(2) カラーの設定をファイルに書き出す", "(2) Dump colors"), 5, 5);
475                 prt(_("(3) カラーの設定を変更する", "(3) Modify colors"), 6, 5);
476                 prt(_("コマンド: ", "Command: "), 8, 0);
477                 i = inkey();
478                 if (i == ESCAPE) break;
479
480                 if (i == '1')
481                 {
482                         prt(_("コマンド: ユーザー設定ファイルをロードします", "Command: Load a user pref file"), 8, 0);
483                         prt(_("ファイル: ", "File: "), 10, 0);
484                         sprintf(tmp, "%s.prf", creature_ptr->base_name);
485                         if (!askfor(tmp, 70)) continue;
486
487                         (void)process_pref_file(creature_ptr, tmp);
488                         Term_xtra(TERM_XTRA_REACT, 0);
489                         Term_redraw();
490                 }
491                 else if (i == '2')
492                 {
493                         static concptr mark = "Colors";
494                         prt(_("コマンド: カラーの設定をファイルに書き出します", "Command: Dump colors"), 8, 0);
495                         prt(_("ファイル: ", "File: "), 10, 0);
496                         sprintf(tmp, "%s.prf", creature_ptr->base_name);
497                         if (!askfor(tmp, 70)) continue;
498
499                         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, tmp);
500                         if (!open_auto_dump(buf, mark)) continue;
501
502                         auto_dump_printf(_("\n# カラーの設定\n\n", "\n# Color redefinitions\n\n"));
503                         for (i = 0; i < 256; i++)
504                         {
505                                 int kv = angband_color_table[i][0];
506                                 int rv = angband_color_table[i][1];
507                                 int gv = angband_color_table[i][2];
508                                 int bv = angband_color_table[i][3];
509
510                                 concptr name = _("未知", "unknown");
511                                 if (!kv && !rv && !gv && !bv) continue;
512
513                                 if (i < 16) name = color_names[i];
514
515                                 auto_dump_printf(_("# カラー '%s'\n", "# Color '%s'\n"), name);
516                                 auto_dump_printf("V:%d:0x%02X:0x%02X:0x%02X:0x%02X\n\n",
517                                         i, kv, rv, gv, bv);
518                         }
519
520                         close_auto_dump();
521                         msg_print(_("カラーの設定をファイルに書き出しました。", "Dumped color redefinitions."));
522                 }
523                 else if (i == '3')
524                 {
525                         static byte a = 0;
526                         prt(_("コマンド: カラーの設定を変更します", "Command: Modify colors"), 8, 0);
527                         while (TRUE)
528                         {
529                                 concptr name;
530                                 clear_from(10);
531                                 for (byte j = 0; j < 16; j++)
532                                 {
533                                         Term_putstr(j * 4, 20, -1, a, "###");
534                                         Term_putstr(j * 4, 22, -1, j, format("%3d", j));
535                                 }
536
537                                 name = ((a < 16) ? color_names[a] : _("未定義", "undefined"));
538                                 Term_putstr(5, 10, -1, TERM_WHITE,
539                                         format(_("カラー = %d, 名前 = %s", "Color = %d, Name = %s"), a, name));
540                                 Term_putstr(5, 12, -1, TERM_WHITE,
541                                         format("K = 0x%02x / R,G,B = 0x%02x,0x%02x,0x%02x",
542                                                 angband_color_table[a][0],
543                                                 angband_color_table[a][1],
544                                                 angband_color_table[a][2],
545                                                 angband_color_table[a][3]));
546                                 Term_putstr(0, 14, -1, TERM_WHITE,
547                                         _("コマンド (n/N/k/K/r/R/g/G/b/B): ", "Command (n/N/k/K/r/R/g/G/b/B): "));
548                                 i = inkey();
549                                 if (i == ESCAPE) break;
550
551                                 if (i == 'n') a = (byte)(a + 1);
552                                 if (i == 'N') a = (byte)(a - 1);
553                                 if (i == 'k') angband_color_table[a][0] = (byte)(angband_color_table[a][0] + 1);
554                                 if (i == 'K') angband_color_table[a][0] = (byte)(angband_color_table[a][0] - 1);
555                                 if (i == 'r') angband_color_table[a][1] = (byte)(angband_color_table[a][1] + 1);
556                                 if (i == 'R') angband_color_table[a][1] = (byte)(angband_color_table[a][1] - 1);
557                                 if (i == 'g') angband_color_table[a][2] = (byte)(angband_color_table[a][2] + 1);
558                                 if (i == 'G') angband_color_table[a][2] = (byte)(angband_color_table[a][2] - 1);
559                                 if (i == 'b') angband_color_table[a][3] = (byte)(angband_color_table[a][3] + 1);
560                                 if (i == 'B') angband_color_table[a][3] = (byte)(angband_color_table[a][3] - 1);
561
562                                 Term_xtra(TERM_XTRA_REACT, 0);
563                                 Term_redraw();
564                         }
565                 }
566                 else
567                 {
568                         bell();
569                 }
570
571                 msg_erase();
572         }
573
574         screen_load();
575 }
576
577
578 /*
579  * Note something in the message recall
580  */
581 void do_cmd_note(void)
582 {
583         char buf[80];
584         strcpy(buf, "");
585         if (!get_string(_("メモ: ", "Note: "), buf, 60)) return;
586         if (!buf[0] || (buf[0] == ' ')) return;
587
588         msg_format(_("メモ: %s", "Note: %s"), buf);
589 }
590
591
592 /*
593  * Mention the current version
594  */
595 void do_cmd_version(void)
596 {
597 #if FAKE_VER_EXTRA > 0
598         msg_format(_("変愚蛮怒(Hengband) %d.%d.%d.%d", "You are playing Hengband %d.%d.%d.%d."),
599                 FAKE_VER_MAJOR - 10, FAKE_VER_MINOR, FAKE_VER_PATCH, FAKE_VER_EXTRA);
600 #else
601         msg_format(_("変愚蛮怒(Hengband) %d.%d.%d", "You are playing Hengband %d.%d.%d."),
602                 FAKE_VER_MAJOR - 10, FAKE_VER_MINOR, FAKE_VER_PATCH);
603 #endif
604 }
605
606
607 /*
608  * Note that "feeling" is set to zero unless some time has passed.
609  * Note that this is done when the level is GENERATED, not entered.
610  */
611 void do_cmd_feeling(player_type *creature_ptr)
612 {
613         if (creature_ptr->wild_mode) return;
614
615         if (creature_ptr->current_floor_ptr->inside_quest && !random_quest_number(creature_ptr, creature_ptr->current_floor_ptr->dun_level))
616         {
617                 msg_print(_("典型的なクエストのダンジョンのようだ。", "Looks like a typical quest level."));
618                 return;
619         }
620
621         if (creature_ptr->town_num && !creature_ptr->current_floor_ptr->dun_level)
622         {
623                 if (!strcmp(town_info[creature_ptr->town_num].name, _("荒野", "wilderness")))
624                 {
625                         msg_print(_("何かありそうな荒野のようだ。", "Looks like a strange wilderness."));
626                         return;
627                 }
628
629                 msg_print(_("典型的な町のようだ。", "Looks like a typical town."));
630                 return;
631         }
632
633         if (!creature_ptr->current_floor_ptr->dun_level)
634         {
635                 msg_print(_("典型的な荒野のようだ。", "Looks like a typical wilderness."));
636                 return;
637         }
638
639         if (creature_ptr->muta3 & MUT3_GOOD_LUCK)
640                 msg_print(do_cmd_feeling_text_lucky[creature_ptr->feeling]);
641         else if (IS_ECHIZEN(creature_ptr))
642                 msg_print(do_cmd_feeling_text_combat[creature_ptr->feeling]);
643         else
644                 msg_print(do_cmd_feeling_text[creature_ptr->feeling]);
645 }
646
647
648 /*
649  * todo 引数と戻り値について追記求む
650  * Build a list of monster indexes in the given group.
651  *
652  * mode & 0x01 : check for non-empty group
653  * mode & 0x02 : visual operation only
654
655  * @param creature_ptr プレーヤーへの参照ポインタ
656  * @param grp_cur ???
657  * @param mon_idx[] ???
658  * @param mode ???
659  * @return The number of monsters in the group
660  */
661 static IDX collect_monsters(player_type *creature_ptr, IDX grp_cur, IDX mon_idx[], BIT_FLAGS8 mode)
662 {
663         concptr group_char = monster_group_char[grp_cur];
664         bool grp_unique = (monster_group_char[grp_cur] == (char *)-1L);
665         bool grp_riding = (monster_group_char[grp_cur] == (char *)-2L);
666         bool grp_wanted = (monster_group_char[grp_cur] == (char *)-3L);
667         bool grp_amberite = (monster_group_char[grp_cur] == (char *)-4L);
668
669         IDX mon_cnt = 0;
670         for (IDX i = 0; i < max_r_idx; i++)
671         {
672                 monster_race *r_ptr = &r_info[i];
673                 if (!r_ptr->name) continue;
674                 if (!(mode & 0x02) && !cheat_know && !r_ptr->r_sights) continue;
675
676                 if (grp_unique)
677                 {
678                         if (!(r_ptr->flags1 & RF1_UNIQUE)) continue;
679                 }
680                 else if (grp_riding)
681                 {
682                         if (!(r_ptr->flags7 & RF7_RIDING)) continue;
683                 }
684                 else if (grp_wanted)
685                 {
686                         bool wanted = FALSE;
687                         for (int j = 0; j < MAX_BOUNTY; j++)
688                         {
689                                 if (current_world_ptr->bounty_r_idx[j] == i || current_world_ptr->bounty_r_idx[j] - 10000 == i ||
690                                         (creature_ptr->today_mon && creature_ptr->today_mon == i))
691                                 {
692                                         wanted = TRUE;
693                                         break;
694                                 }
695                         }
696
697                         if (!wanted) continue;
698                 }
699                 else if (grp_amberite)
700                 {
701                         if (!(r_ptr->flags3 & RF3_AMBERITE)) continue;
702                 }
703                 else
704                 {
705                         if (!my_strchr(group_char, r_ptr->d_char)) continue;
706                 }
707
708                 mon_idx[mon_cnt++] = i;
709                 if (mode & 0x01) break;
710         }
711
712         mon_idx[mon_cnt] = -1;
713         int dummy_why;
714         ang_sort(mon_idx, &dummy_why, mon_cnt, ang_sort_comp_monster_level, ang_sort_swap_hook);
715         return mon_cnt;
716 }
717
718
719 /*
720  * Build a list of object indexes in the given group. Return the number
721  * of objects in the group.
722  *
723  * mode & 0x01 : check for non-empty group
724  * mode & 0x02 : visual operation only
725  */
726 static KIND_OBJECT_IDX collect_objects(int grp_cur, KIND_OBJECT_IDX object_idx[], BIT_FLAGS8 mode)
727 {
728         KIND_OBJECT_IDX object_cnt = 0;
729         byte group_tval = object_group_tval[grp_cur];
730         for (KIND_OBJECT_IDX i = 0; i < max_k_idx; i++)
731         {
732                 object_kind *k_ptr = &k_info[i];
733                 if (!k_ptr->name) continue;
734
735                 if (!(mode & 0x02))
736                 {
737                         if (!current_world_ptr->wizard)
738                         {
739                                 if (!k_ptr->flavor) continue;
740                                 if (!k_ptr->aware) continue;
741                         }
742
743                         int k = 0;
744                         for (int j = 0; j < 4; j++)
745                                 k += k_ptr->chance[j];
746                         if (!k) continue;
747                 }
748
749                 if (TV_LIFE_BOOK == group_tval)
750                 {
751                         if (TV_LIFE_BOOK <= k_ptr->tval && k_ptr->tval <= TV_HEX_BOOK)
752                         {
753                                 object_idx[object_cnt++] = i;
754                         }
755                         else
756                                 continue;
757                 }
758                 else if (k_ptr->tval == group_tval)
759                 {
760                         object_idx[object_cnt++] = i;
761                 }
762                 else
763                         continue;
764
765                 if (mode & 0x01) break;
766         }
767
768         object_idx[object_cnt] = -1;
769         return object_cnt;
770 }
771
772
773 /*
774  * Description of each feature group.
775  */
776 static concptr feature_group_text[] =
777 {
778         "terrains",
779         NULL
780 };
781
782
783 /*
784  * Build a list of feature indexes in the given group. Return the number
785  * of features in the group.
786  *
787  * mode & 0x01 : check for non-empty group
788  */
789 static FEAT_IDX collect_features(FEAT_IDX *feat_idx, BIT_FLAGS8 mode)
790 {
791         FEAT_IDX feat_cnt = 0;
792         for (FEAT_IDX i = 0; i < max_f_idx; i++)
793         {
794                 feature_type *f_ptr = &f_info[i];
795                 if (!f_ptr->name) continue;
796                 if (f_ptr->mimic != i) continue;
797
798                 feat_idx[feat_cnt++] = i;
799                 if (mode & 0x01) break;
800         }
801
802         feat_idx[feat_cnt] = -1;
803         return feat_cnt;
804 }
805
806
807 /*
808  * Hack -- load a screen dump from a file
809  */
810 void do_cmd_load_screen(void)
811 {
812         TERM_COLOR a = 0;
813         SYMBOL_CODE c = ' ';
814         bool okay = TRUE;
815         FILE *fff;
816         char buf[1024];
817         TERM_LEN wid, hgt;
818         Term_get_size(&wid, &hgt);
819         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, "dump.txt");
820         fff = my_fopen(buf, "r");
821         if (!fff)
822         {
823                 msg_format(_("%s を開くことができませんでした。", "Failed to open %s."), buf);
824                 msg_print(NULL);
825                 return;
826         }
827
828         screen_save();
829         Term_clear();
830         for (TERM_LEN y = 0; okay; y++)
831         {
832                 if (!fgets(buf, 1024, fff)) okay = FALSE;
833
834                 if (buf[0] == '\n' || buf[0] == '\0') break;
835                 if (y >= hgt) continue;
836
837                 for (TERM_LEN x = 0; x < wid - 1; x++)
838                 {
839                         if (buf[x] == '\n' || buf[x] == '\0') break;
840
841                         Term_draw(x, y, TERM_WHITE, buf[x]);
842                 }
843         }
844
845         for (TERM_LEN y = 0; okay; y++)
846         {
847                 if (!fgets(buf, 1024, fff)) okay = FALSE;
848
849                 if (buf[0] == '\n' || buf[0] == '\0') break;
850                 if (y >= hgt) continue;
851
852                 for (TERM_LEN x = 0; x < wid - 1; x++)
853                 {
854                         if (buf[x] == '\n' || buf[x] == '\0') break;
855
856                         (void)(Term_what(x, y, &a, &c));
857                         for (int i = 0; i < 16; i++)
858                         {
859                                 if (hack[i] == buf[x]) a = (byte)i;
860                         }
861
862                         Term_draw(x, y, a, c);
863                 }
864         }
865
866         my_fclose(fff);
867         prt(_("ファイルに書き出された画面(記念撮影)をロードしました。", "Screen dump loaded."), 0, 0);
868         flush();
869         inkey();
870         screen_load();
871 }
872
873 // todo なぜこんな中途半端なところに? defineも…
874 concptr inven_res_label = _("                               酸電火冷毒光闇破轟獄因沌劣 盲怖乱痺透命感消復浮",
875         "                               AcElFiCoPoLiDkShSoNtNxCaDi BlFeCfFaSeHlEpSdRgLv");
876
877 #define IM_FLAG_STR  _("*", "* ")
878 #define HAS_FLAG_STR _("+", "+ ")
879 #define NO_FLAG_STR  _("・", ". ")
880
881 #define print_im_or_res_flag(IM, RES) \
882 { \
883         fputs(have_flag(flgs, (IM)) ? IM_FLAG_STR : \
884               (have_flag(flgs, (RES)) ? HAS_FLAG_STR : NO_FLAG_STR), fff); \
885 }
886
887 #define print_flag(TR) \
888 { \
889         fputs(have_flag(flgs, (TR)) ? HAS_FLAG_STR : NO_FLAG_STR, fff); \
890 }
891
892
893 static void do_cmd_knowledge_inven_aux(player_type *creature_ptr, FILE *fff, object_type *o_ptr, int *j, OBJECT_TYPE_VALUE tval, char *where)
894 {
895         GAME_TEXT o_name[MAX_NLEN];
896         BIT_FLAGS flgs[TR_FLAG_SIZE];
897         if (!o_ptr->k_idx) return;
898         if (o_ptr->tval != tval) return;
899         if (!object_is_known(o_ptr)) return;
900
901         bool is_special_item_type = (object_is_wearable(o_ptr) && object_is_ego(o_ptr))
902                 || ((tval == TV_AMULET) && (o_ptr->sval == SV_AMULET_RESISTANCE))
903                 || ((tval == TV_RING) && (o_ptr->sval == SV_RING_LORDLY))
904                 || ((tval == TV_SHIELD) && (o_ptr->sval == SV_DRAGON_SHIELD))
905                 || ((tval == TV_HELM) && (o_ptr->sval == SV_DRAGON_HELM))
906                 || ((tval == TV_GLOVES) && (o_ptr->sval == SV_SET_OF_DRAGON_GLOVES))
907                 || ((tval == TV_BOOTS) && (o_ptr->sval == SV_PAIR_OF_DRAGON_GREAVE))
908                 || object_is_artifact(o_ptr);
909         if (!is_special_item_type)
910         {
911                 return;
912         }
913
914         int i = 0;
915         object_desc(creature_ptr, o_name, o_ptr, OD_NAME_ONLY);
916         while (o_name[i] && (i < 26))
917         {
918 #ifdef JP
919                 if (iskanji(o_name[i])) i++;
920 #endif
921                 i++;
922         }
923
924         if (i < 28)
925         {
926                 while (i < 28)
927                 {
928                         o_name[i] = ' '; i++;
929                 }
930         }
931
932         o_name[i] = '\0';
933
934         fprintf(fff, "%s %s", where, o_name);
935
936         if (!OBJECT_IS_FULL_KNOWN(o_ptr))
937         {
938                 fputs(_("-------不明--------------- -------不明---------\n",
939                         "-------unknown------------ -------unknown------\n"), fff);
940         }
941         else
942         {
943                 object_flags_known(o_ptr, flgs);
944
945                 print_im_or_res_flag(TR_IM_ACID, TR_RES_ACID);
946                 print_im_or_res_flag(TR_IM_ELEC, TR_RES_ELEC);
947                 print_im_or_res_flag(TR_IM_FIRE, TR_RES_FIRE);
948                 print_im_or_res_flag(TR_IM_COLD, TR_RES_COLD);
949                 print_flag(TR_RES_POIS);
950                 print_flag(TR_RES_LITE);
951                 print_flag(TR_RES_DARK);
952                 print_flag(TR_RES_SHARDS);
953                 print_flag(TR_RES_SOUND);
954                 print_flag(TR_RES_NETHER);
955                 print_flag(TR_RES_NEXUS);
956                 print_flag(TR_RES_CHAOS);
957                 print_flag(TR_RES_DISEN);
958
959                 fputs(" ", fff);
960
961                 print_flag(TR_RES_BLIND);
962                 print_flag(TR_RES_FEAR);
963                 print_flag(TR_RES_CONF);
964                 print_flag(TR_FREE_ACT);
965                 print_flag(TR_SEE_INVIS);
966                 print_flag(TR_HOLD_EXP);
967                 print_flag(TR_TELEPATHY);
968                 print_flag(TR_SLOW_DIGEST);
969                 print_flag(TR_REGEN);
970                 print_flag(TR_LEVITATION);
971
972                 fputc('\n', fff);
973         }
974
975         (*j)++;
976         if (*j == 9)
977         {
978                 *j = 0;
979                 fprintf(fff, "%s\n", inven_res_label);
980         }
981 }
982
983 /*
984  * Display *ID* ed weapons/armors's resistances
985  */
986 static void do_cmd_knowledge_inven(player_type *creature_ptr)
987 {
988         FILE *fff;
989         GAME_TEXT file_name[1024];
990         store_type *store_ptr;
991         OBJECT_TYPE_VALUE tval;
992         int j = 0;
993
994         char where[32];
995         fff = my_fopen_temp(file_name, 1024);
996         if (!fff)
997         {
998                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
999                 msg_print(NULL);
1000                 return;
1001         }
1002
1003         fprintf(fff, "%s\n", inven_res_label);
1004         for (tval = TV_WEARABLE_BEGIN; tval <= TV_WEARABLE_END; tval++)
1005         {
1006                 if (j != 0)
1007                 {
1008                         for (; j < 9; j++) fputc('\n', fff);
1009                         j = 0;
1010                         fprintf(fff, "%s\n", inven_res_label);
1011                 }
1012
1013                 strcpy(where, _("装", "E "));
1014                 for (int i = INVEN_RARM; i < INVEN_TOTAL; i++)
1015                 {
1016                         do_cmd_knowledge_inven_aux(creature_ptr, fff, &creature_ptr->inventory_list[i], &j, tval, where);
1017                 }
1018
1019                 strcpy(where, _("持", "I "));
1020                 for (int i = 0; i < INVEN_PACK; i++)
1021                 {
1022                         do_cmd_knowledge_inven_aux(creature_ptr, fff, &creature_ptr->inventory_list[i], &j, tval, where);
1023                 }
1024
1025                 store_ptr = &town_info[1].store[STORE_HOME];
1026                 strcpy(where, _("家", "H "));
1027                 for (int i = 0; i < store_ptr->stock_num; i++)
1028                 {
1029                         do_cmd_knowledge_inven_aux(creature_ptr, fff, &store_ptr->stock[i], &j, tval, where);
1030                 }
1031         }
1032
1033         my_fclose(fff);
1034         (void)show_file(creature_ptr, TRUE, file_name, _("*鑑定*済み武器/防具の耐性リスト", "Resistances of *identified* equipment"), 0, 0);
1035         fd_kill(file_name);
1036 }
1037
1038
1039 void do_cmd_save_screen_html_aux(char *filename, int message)
1040 {
1041         concptr tags[4] = {
1042                 "HEADER_START:",
1043                 "HEADER_END:",
1044                 "FOOTER_START:",
1045                 "FOOTER_END:",
1046         };
1047         concptr html_head[] = {
1048                 "<html>\n<body text=\"#ffffff\" bgcolor=\"#000000\">\n",
1049                 "<pre>",
1050                 0,
1051         };
1052         concptr html_foot[] = {
1053                 "</pre>\n",
1054                 "</body>\n</html>\n",
1055                 0,
1056         };
1057
1058         TERM_LEN wid, hgt;
1059         Term_get_size(&wid, &hgt);
1060         FILE_TYPE(FILE_TYPE_TEXT);
1061         FILE *fff;
1062         fff = my_fopen(filename, "w");
1063         if (!fff)
1064         {
1065                 if (message)
1066                 {
1067                         msg_format(_("ファイル %s を開けませんでした。", "Failed to open file %s."), filename);
1068                         msg_print(NULL);
1069                 }
1070
1071                 return;
1072         }
1073
1074         if (message) screen_save();
1075
1076         char buf[2048];
1077         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, "htmldump.prf");
1078         FILE *tmpfff;
1079         tmpfff = my_fopen(buf, "r");
1080         if (!tmpfff)
1081         {
1082                 for (int i = 0; html_head[i]; i++)
1083                         fputs(html_head[i], fff);
1084         }
1085         else
1086         {
1087                 bool is_first_line = TRUE;
1088                 while (!my_fgets(tmpfff, buf, sizeof(buf)))
1089                 {
1090                         if (is_first_line)
1091                         {
1092                                 if (strncmp(buf, tags[0], strlen(tags[0])) == 0)
1093                                         is_first_line = FALSE;
1094                         }
1095                         else
1096                         {
1097                                 if (strncmp(buf, tags[1], strlen(tags[1])) == 0)
1098                                         break;
1099                                 fprintf(fff, "%s\n", buf);
1100                         }
1101                 }
1102         }
1103
1104         for (TERM_LEN y = 0; y < hgt; y++)
1105         {
1106                 if (y != 0) fprintf(fff, "\n");
1107
1108                 TERM_COLOR a = 0, old_a = 0;
1109                 char c = ' ';
1110                 for (TERM_LEN x = 0; x < wid - 1; x++)
1111                 {
1112                         concptr cc = NULL;
1113                         (void)(Term_what(x, y, &a, &c));
1114                         switch (c)
1115                         {
1116                         case '&': cc = "&amp;"; break;
1117                         case '<': cc = "&lt;"; break;
1118                         case '>': cc = "&gt;"; break;
1119 #ifdef WINDOWS
1120                         case 0x1f: c = '.'; break;
1121                         case 0x7f: c = (a == 0x09) ? '%' : '#'; break;
1122 #endif
1123                         }
1124
1125                         a = a & 0x0F;
1126                         if ((y == 0 && x == 0) || a != old_a)
1127                         {
1128                                 int rv = angband_color_table[a][1];
1129                                 int gv = angband_color_table[a][2];
1130                                 int bv = angband_color_table[a][3];
1131                                 fprintf(fff, "%s<font color=\"#%02x%02x%02x\">",
1132                                         ((y == 0 && x == 0) ? "" : "</font>"), rv, gv, bv);
1133                                 old_a = a;
1134                         }
1135
1136                         if (cc)
1137                                 fprintf(fff, "%s", cc);
1138                         else
1139                                 fprintf(fff, "%c", c);
1140                 }
1141         }
1142
1143         fprintf(fff, "</font>");
1144         if (!tmpfff)
1145         {
1146                 for (int i = 0; html_foot[i]; i++)
1147                         fputs(html_foot[i], fff);
1148         }
1149         else
1150         {
1151                 rewind(tmpfff);
1152                 bool is_first_line = TRUE;
1153                 while (!my_fgets(tmpfff, buf, sizeof(buf)))
1154                 {
1155                         if (is_first_line)
1156                         {
1157                                 if (strncmp(buf, tags[2], strlen(tags[2])) == 0)
1158                                         is_first_line = FALSE;
1159                         }
1160                         else
1161                         {
1162                                 if (strncmp(buf, tags[3], strlen(tags[3])) == 0)
1163                                         break;
1164                                 fprintf(fff, "%s\n", buf);
1165                         }
1166                 }
1167
1168                 my_fclose(tmpfff);
1169         }
1170
1171         fprintf(fff, "\n");
1172         my_fclose(fff);
1173         if (message)
1174         {
1175                 msg_print(_("画面(記念撮影)をファイルに書き出しました。", "Screen dump saved."));
1176                 msg_print(NULL);
1177         }
1178
1179         if (message)
1180                 screen_load();
1181 }
1182
1183
1184 /*
1185  * Hack -- save a screen dump to a file
1186  */
1187 static void do_cmd_save_screen_html(void)
1188 {
1189         char buf[1024], tmp[256] = "screen.html";
1190
1191         if (!get_string(_("ファイル名: ", "File name: "), tmp, 80))
1192                 return;
1193         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, tmp);
1194
1195         msg_print(NULL);
1196
1197         do_cmd_save_screen_html_aux(buf, 1);
1198 }
1199
1200
1201 /*
1202  * Redefinable "save_screen" action
1203  */
1204 void(*screendump_aux)(void) = NULL;
1205
1206
1207 /*
1208  * Save a screen dump to a file
1209  * @param creature_ptr プレーヤーへの参照ポインタ
1210  * @return なし
1211  */
1212 void do_cmd_save_screen(player_type *creature_ptr)
1213 {
1214         prt(_("記念撮影しますか? [(y)es/(h)tml/(n)o] ", "Save screen dump? [(y)es/(h)tml/(n)o] "), 0, 0);
1215         bool html_dump = FALSE;
1216         while (TRUE)
1217         {
1218                 char c = inkey();
1219                 if (c == 'Y' || c == 'y')
1220                         break;
1221                 else if (c == 'H' || c == 'h')
1222                 {
1223                         html_dump = TRUE;
1224                         break;
1225                 }
1226                 else
1227                 {
1228                         prt("", 0, 0);
1229                         return;
1230                 }
1231         }
1232
1233         int wid, hgt;
1234         Term_get_size(&wid, &hgt);
1235
1236         bool old_use_graphics = use_graphics;
1237         if (old_use_graphics)
1238         {
1239                 use_graphics = FALSE;
1240                 reset_visuals(creature_ptr);
1241                 creature_ptr->redraw |= (PR_WIPE | PR_BASIC | PR_EXTRA | PR_MAP | PR_EQUIPPY);
1242                 handle_stuff(creature_ptr);
1243         }
1244
1245         if (html_dump)
1246         {
1247                 do_cmd_save_screen_html();
1248                 do_cmd_redraw(creature_ptr);
1249         }
1250         else if (screendump_aux)
1251         {
1252                 (*screendump_aux)();
1253         }
1254         else
1255         {
1256                 TERM_LEN y, x;
1257                 TERM_COLOR a = 0;
1258                 SYMBOL_CODE c = ' ';
1259                 FILE *fff;
1260                 char buf[1024];
1261                 path_build(buf, sizeof(buf), ANGBAND_DIR_USER, "dump.txt");
1262                 FILE_TYPE(FILE_TYPE_TEXT);
1263                 fff = my_fopen(buf, "w");
1264                 if (!fff)
1265                 {
1266                         msg_format(_("ファイル %s を開けませんでした。", "Failed to open file %s."), buf);
1267                         msg_print(NULL);
1268                         return;
1269                 }
1270
1271                 screen_save();
1272                 for (y = 0; y < hgt; y++)
1273                 {
1274                         for (x = 0; x < wid - 1; x++)
1275                         {
1276                                 (void)(Term_what(x, y, &a, &c));
1277                                 buf[x] = c;
1278                         }
1279
1280                         buf[x] = '\0';
1281                         fprintf(fff, "%s\n", buf);
1282                 }
1283
1284                 fprintf(fff, "\n");
1285                 for (y = 0; y < hgt; y++)
1286                 {
1287                         for (x = 0; x < wid - 1; x++)
1288                         {
1289                                 (void)(Term_what(x, y, &a, &c));
1290                                 buf[x] = hack[a & 0x0F];
1291                         }
1292
1293                         buf[x] = '\0';
1294                         fprintf(fff, "%s\n", buf);
1295                 }
1296
1297                 fprintf(fff, "\n");
1298                 my_fclose(fff);
1299                 msg_print(_("画面(記念撮影)をファイルに書き出しました。", "Screen dump saved."));
1300                 msg_print(NULL);
1301                 screen_load();
1302         }
1303
1304         if (!old_use_graphics) return;
1305
1306         use_graphics = TRUE;
1307         reset_visuals(creature_ptr);
1308         creature_ptr->redraw |= (PR_WIPE | PR_BASIC | PR_EXTRA | PR_MAP | PR_EQUIPPY);
1309         handle_stuff(creature_ptr);
1310 }
1311
1312
1313 /*
1314  * todo okay = 既知のアーティファクト? と思われるが確証がない
1315  * 分かりやすい変数名へ変更求む&万が一未知である旨の配列なら負論理なのでゴソッと差し替えるべき
1316  * Check the status of "artifacts"
1317  * @param player_ptr プレーヤーへの参照ポインタ
1318  * @return なし
1319  */
1320 static void do_cmd_knowledge_artifacts(player_type *player_ptr)
1321 {
1322         FILE *fff;
1323         GAME_TEXT file_name[1024];
1324         fff = my_fopen_temp(file_name, 1024);
1325         if (!fff)
1326         {
1327                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
1328                 msg_print(NULL);
1329                 return;
1330         }
1331
1332         ARTIFACT_IDX *who;
1333         C_MAKE(who, max_a_idx, ARTIFACT_IDX);
1334         bool *okay;
1335         C_MAKE(okay, max_a_idx, bool);
1336
1337         for (ARTIFACT_IDX k = 0; k < max_a_idx; k++)
1338         {
1339                 artifact_type *a_ptr = &a_info[k];
1340                 okay[k] = FALSE;
1341                 if (!a_ptr->name) continue;
1342                 if (!a_ptr->cur_num) continue;
1343
1344                 okay[k] = TRUE;
1345         }
1346
1347         for (POSITION y = 0; y < player_ptr->current_floor_ptr->height; y++)
1348         {
1349                 for (POSITION x = 0; x < player_ptr->current_floor_ptr->width; x++)
1350                 {
1351                         grid_type *g_ptr = &player_ptr->current_floor_ptr->grid_array[y][x];
1352                         OBJECT_IDX this_o_idx, next_o_idx = 0;
1353                         for (this_o_idx = g_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx)
1354                         {
1355                                 object_type *o_ptr;
1356                                 o_ptr = &player_ptr->current_floor_ptr->o_list[this_o_idx];
1357                                 next_o_idx = o_ptr->next_o_idx;
1358                                 if (!object_is_fixed_artifact(o_ptr)) continue;
1359                                 if (object_is_known(o_ptr)) continue;
1360
1361                                 okay[o_ptr->name1] = FALSE;
1362                         }
1363                 }
1364         }
1365
1366         for (ARTIFACT_IDX i = 0; i < INVEN_TOTAL; i++)
1367         {
1368                 object_type *o_ptr = &player_ptr->inventory_list[i];
1369                 if (!o_ptr->k_idx) continue;
1370                 if (!object_is_fixed_artifact(o_ptr)) continue;
1371                 if (object_is_known(o_ptr)) continue;
1372
1373                 okay[o_ptr->name1] = FALSE;
1374         }
1375
1376         int n = 0;
1377         for (ARTIFACT_IDX k = 0; k < max_a_idx; k++)
1378         {
1379                 if (okay[k]) who[n++] = k;
1380         }
1381
1382         u16b why = 3;
1383         ang_sort(who, &why, n, ang_sort_art_comp, ang_sort_art_swap);
1384         for (ARTIFACT_IDX k = 0; k < n; k++)
1385         {
1386                 artifact_type *a_ptr = &a_info[who[k]];
1387                 GAME_TEXT base_name[MAX_NLEN];
1388                 strcpy(base_name, _("未知の伝説のアイテム", "Unknown Artifact"));
1389                 ARTIFACT_IDX z = lookup_kind(a_ptr->tval, a_ptr->sval);
1390                 if (z)
1391                 {
1392                         object_type forge;
1393                         object_type *q_ptr;
1394                         q_ptr = &forge;
1395                         object_prep(q_ptr, z);
1396                         q_ptr->name1 = (byte)who[k];
1397                         q_ptr->ident |= IDENT_STORE;
1398                         object_desc(player_ptr, base_name, q_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY));
1399                 }
1400
1401                 fprintf(fff, _("     %s\n", "     The %s\n"), base_name);
1402         }
1403
1404         C_KILL(who, max_a_idx, ARTIFACT_IDX);
1405         C_KILL(okay, max_a_idx, bool);
1406         my_fclose(fff);
1407         (void)show_file(player_ptr, TRUE, file_name, _("既知の伝説のアイテム", "Artifacts Seen"), 0, 0);
1408         fd_kill(file_name);
1409 }
1410
1411
1412 /*
1413  * Display known uniques
1414  * With "XTRA HACK UNIQHIST" (Originally from XAngband)
1415  */
1416 static void do_cmd_knowledge_uniques(player_type *creature_ptr)
1417 {
1418         u16b why = 2;
1419         IDX *who;
1420         GAME_TEXT file_name[1024];
1421         int n_alive[10];
1422         int n_alive_surface = 0;
1423         int n_alive_over100 = 0;
1424         int n_alive_total = 0;
1425         int max_lev = -1;
1426         for (IDX i = 0; i < 10; i++)
1427                 n_alive[i] = 0;
1428
1429         FILE *fff;
1430         fff = my_fopen_temp(file_name, 1024);
1431         if (!fff)
1432         {
1433                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
1434                 msg_print(NULL);
1435                 return;
1436         }
1437
1438         C_MAKE(who, max_r_idx, MONRACE_IDX);
1439         int n = 0;
1440         for (IDX i = 1; i < max_r_idx; i++)
1441         {
1442                 monster_race *r_ptr = &r_info[i];
1443                 if (!r_ptr->name) continue;
1444                 if (!(r_ptr->flags1 & RF1_UNIQUE)) continue;
1445                 if (!cheat_know && !r_ptr->r_sights) continue;
1446                 if (!r_ptr->rarity || ((r_ptr->rarity > 100) && !(r_ptr->flags1 & RF1_QUESTOR))) continue;
1447                 if (r_ptr->max_num == 0) continue;
1448
1449                 if (r_ptr->level)
1450                 {
1451                         int lev = (r_ptr->level - 1) / 10;
1452                         if (lev < 10)
1453                         {
1454                                 n_alive[lev]++;
1455                                 if (max_lev < lev) max_lev = lev;
1456                         }
1457                         else
1458                                 n_alive_over100++;
1459                 }
1460                 else
1461                         n_alive_surface++;
1462
1463                 who[n++] = i;
1464         }
1465
1466         ang_sort(who, &why, n, ang_sort_comp_hook, ang_sort_swap_hook);
1467         if (n_alive_surface)
1468         {
1469                 fprintf(fff, _("     地上  生存: %3d体\n", "      Surface  alive: %3d\n"), n_alive_surface);
1470                 n_alive_total += n_alive_surface;
1471         }
1472
1473         for (IDX i = 0; i <= max_lev; i++)
1474         {
1475                 fprintf(fff, _("%3d-%3d階  生存: %3d体\n", "Level %3d-%3d  alive: %3d\n"), 1 + i * 10, 10 + i * 10, n_alive[i]);
1476                 n_alive_total += n_alive[i];
1477         }
1478
1479         if (n_alive_over100)
1480         {
1481                 fprintf(fff, _("101-   階  生存: %3d体\n", "Level 101-     alive: %3d\n"), n_alive_over100);
1482                 n_alive_total += n_alive_over100;
1483         }
1484
1485         if (n_alive_total)
1486         {
1487                 fputs(_("---------  -----------\n", "-------------  ----------\n"), fff);
1488                 fprintf(fff, _("     合計  生存: %3d体\n\n", "        Total  alive: %3d\n\n"), n_alive_total);
1489         }
1490         else
1491         {
1492                 fputs(_("現在は既知の生存ユニークはいません。\n", "No known uniques alive.\n"), fff);
1493         }
1494
1495         for (int k = 0; k < n; k++)
1496         {
1497                 monster_race *r_ptr = &r_info[who[k]];
1498                 fprintf(fff, _("     %s (レベル%d)\n", "     %s (level %d)\n"), r_name + r_ptr->name, (int)r_ptr->level);
1499         }
1500
1501         C_KILL(who, max_r_idx, s16b);
1502         my_fclose(fff);
1503         (void)show_file(creature_ptr, TRUE, file_name, _("まだ生きているユニーク・モンスター", "Alive Uniques"), 0, 0);
1504         fd_kill(file_name);
1505 }
1506
1507
1508 /*
1509  * Display weapon-exp
1510  */
1511 static void do_cmd_knowledge_weapon_exp(player_type *creature_ptr)
1512 {
1513         FILE *fff;
1514         GAME_TEXT file_name[1024];
1515         fff = my_fopen_temp(file_name, 1024);
1516         if (!fff)
1517         {
1518                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
1519                 msg_print(NULL);
1520                 return;
1521         }
1522
1523         for (int i = 0; i < 5; i++)
1524         {
1525                 for (int num = 0; num < 64; num++)
1526                 {
1527                         SUB_EXP weapon_exp;
1528                         char tmp[30];
1529                         for (KIND_OBJECT_IDX j = 0; j < max_k_idx; j++)
1530                         {
1531                                 object_kind *k_ptr = &k_info[j];
1532
1533                                 if ((k_ptr->tval != TV_SWORD - i) || (k_ptr->sval != num)) continue;
1534                                 if ((k_ptr->tval == TV_BOW) && (k_ptr->sval == SV_CRIMSON || k_ptr->sval == SV_HARP)) continue;
1535
1536                                 weapon_exp = creature_ptr->weapon_exp[4 - i][num];
1537                                 strip_name(tmp, j);
1538                                 fprintf(fff, "%-25s ", tmp);
1539                                 if (weapon_exp >= s_info[creature_ptr->pclass].w_max[4 - i][num]) fprintf(fff, "!");
1540                                 else fprintf(fff, " ");
1541                                 fprintf(fff, "%s", exp_level_str[weapon_exp_level(weapon_exp)]);
1542                                 if (cheat_xtra) fprintf(fff, " %d", weapon_exp);
1543                                 fprintf(fff, "\n");
1544                                 break;
1545                         }
1546                 }
1547         }
1548
1549         my_fclose(fff);
1550         (void)show_file(creature_ptr, TRUE, file_name, _("武器の経験値", "Weapon Proficiency"), 0, 0);
1551         fd_kill(file_name);
1552 }
1553
1554
1555 /*!
1556  * @brief 魔法の経験値を表示するコマンドのメインルーチン
1557  * Display spell-exp
1558  * @return なし
1559  */
1560 static void do_cmd_knowledge_spell_exp(player_type *creature_ptr)
1561 {
1562         FILE *fff;
1563         GAME_TEXT file_name[1024];
1564         fff = my_fopen_temp(file_name, 1024);
1565         if (!fff)
1566         {
1567                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
1568                 msg_print(NULL);
1569                 return;
1570         }
1571
1572         if (creature_ptr->realm1 != REALM_NONE)
1573         {
1574                 fprintf(fff, _("%sの魔法書\n", "%s Spellbook\n"), realm_names[creature_ptr->realm1]);
1575                 for (SPELL_IDX i = 0; i < 32; i++)
1576                 {
1577                         const magic_type *s_ptr;
1578                         if (!is_magic(creature_ptr->realm1))
1579                         {
1580                                 s_ptr = &technic_info[creature_ptr->realm1 - MIN_TECHNIC][i];
1581                         }
1582                         else
1583                         {
1584                                 s_ptr = &mp_ptr->info[creature_ptr->realm1 - 1][i];
1585                         }
1586
1587                         if (s_ptr->slevel >= 99) continue;
1588                         SUB_EXP spell_exp = creature_ptr->spell_exp[i];
1589                         int exp_level = spell_exp_level(spell_exp);
1590                         fprintf(fff, "%-25s ", exe_spell(creature_ptr, creature_ptr->realm1, i, SPELL_NAME));
1591                         if (creature_ptr->realm1 == REALM_HISSATSU)
1592                                 fprintf(fff, "[--]");
1593                         else
1594                         {
1595                                 if (exp_level >= EXP_LEVEL_MASTER) fprintf(fff, "!");
1596                                 else fprintf(fff, " ");
1597                                 fprintf(fff, "%s", exp_level_str[exp_level]);
1598                         }
1599
1600                         if (cheat_xtra) fprintf(fff, " %d", spell_exp);
1601                         fprintf(fff, "\n");
1602                 }
1603         }
1604
1605         if (creature_ptr->realm2 != REALM_NONE)
1606         {
1607                 fprintf(fff, _("%sの魔法書\n", "\n%s Spellbook\n"), realm_names[creature_ptr->realm2]);
1608                 for (SPELL_IDX i = 0; i < 32; i++)
1609                 {
1610                         const magic_type *s_ptr;
1611                         if (!is_magic(creature_ptr->realm1))
1612                         {
1613                                 s_ptr = &technic_info[creature_ptr->realm2 - MIN_TECHNIC][i];
1614                         }
1615                         else
1616                         {
1617                                 s_ptr = &mp_ptr->info[creature_ptr->realm2 - 1][i];
1618                         }
1619
1620                         if (s_ptr->slevel >= 99) continue;
1621
1622                         SUB_EXP spell_exp = creature_ptr->spell_exp[i + 32];
1623                         int exp_level = spell_exp_level(spell_exp);
1624                         fprintf(fff, "%-25s ", exe_spell(creature_ptr, creature_ptr->realm2, i, SPELL_NAME));
1625                         if (exp_level >= EXP_LEVEL_EXPERT) fprintf(fff, "!");
1626                         else fprintf(fff, " ");
1627                         fprintf(fff, "%s", exp_level_str[exp_level]);
1628                         if (cheat_xtra) fprintf(fff, " %d", spell_exp);
1629                         fprintf(fff, "\n");
1630                 }
1631         }
1632
1633         my_fclose(fff);
1634         (void)show_file(creature_ptr, TRUE, file_name, _("魔法の経験値", "Spell Proficiency"), 0, 0);
1635         fd_kill(file_name);
1636 }
1637
1638
1639 /*!
1640  * @brief スキル情報を表示するコマンドのメインルーチン /
1641  * Display skill-exp
1642  * @return なし
1643  */
1644 static void do_cmd_knowledge_skill_exp(player_type *creature_ptr)
1645 {
1646         char skill_name[GINOU_TEMPMAX][20] =
1647         {
1648                 _("マーシャルアーツ", "Martial Arts    "),
1649                 _("二刀流          ", "Dual Wielding   "),
1650                 _("乗馬            ", "Riding          "),
1651                 _("盾              ", "Shield          ")
1652         };
1653
1654         FILE *fff;
1655         char file_name[1024];
1656         fff = my_fopen_temp(file_name, 1024);
1657         if (!fff)
1658         {
1659                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
1660                 msg_print(NULL);
1661                 return;
1662         }
1663
1664         for (int i = 0; i < GINOU_TEMPMAX; i++)
1665         {
1666                 int skill_exp = creature_ptr->skill_exp[i];
1667                 fprintf(fff, "%-20s ", skill_name[i]);
1668                 if (skill_exp >= s_info[creature_ptr->pclass].s_max[i]) fprintf(fff, "!");
1669                 else fprintf(fff, " ");
1670                 fprintf(fff, "%s", exp_level_str[(i == GINOU_RIDING) ? riding_exp_level(skill_exp) : weapon_exp_level(skill_exp)]);
1671                 if (cheat_xtra) fprintf(fff, " %d", skill_exp);
1672                 fprintf(fff, "\n");
1673         }
1674
1675         my_fclose(fff);
1676         (void)show_file(creature_ptr, TRUE, file_name, _("技能の経験値", "Miscellaneous Proficiency"), 0, 0);
1677         fd_kill(file_name);
1678 }
1679
1680
1681 /*!
1682  * @brief 現在のペットを表示するコマンドのメインルーチン /
1683  * Display current pets
1684  * @param creature_ptr プレーヤーへの参照ポインタ
1685  * @return なし
1686  */
1687 static void do_cmd_knowledge_pets(player_type *creature_ptr)
1688 {
1689         GAME_TEXT file_name[1024];
1690         FILE *fff;
1691         fff = my_fopen_temp(file_name, 1024);
1692         if (!fff)
1693         {
1694                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
1695                 msg_print(NULL);
1696                 return;
1697         }
1698
1699         monster_type *m_ptr;
1700         GAME_TEXT pet_name[MAX_NLEN];
1701         int t_friends = 0;
1702         for (int i = creature_ptr->current_floor_ptr->m_max - 1; i >= 1; i--)
1703         {
1704                 m_ptr = &creature_ptr->current_floor_ptr->m_list[i];
1705                 if (!monster_is_valid(m_ptr)) continue;
1706                 if (!is_pet(m_ptr)) continue;
1707
1708                 t_friends++;
1709                 monster_desc(creature_ptr, pet_name, m_ptr, MD_ASSUME_VISIBLE | MD_INDEF_VISIBLE);
1710                 fprintf(fff, "%s (%s)\n", pet_name, look_mon_desc(m_ptr, 0x00));
1711         }
1712
1713         int show_upkeep = calculate_upkeep(creature_ptr);
1714
1715         fprintf(fff, "----------------------------------------------\n");
1716 #ifdef JP
1717         fprintf(fff, "    合計: %d 体のペット\n", t_friends);
1718 #else
1719         fprintf(fff, "   Total: %d pet%s.\n", t_friends, (t_friends == 1 ? "" : "s"));
1720 #endif
1721         fprintf(fff, _(" 維持コスト: %d%% MP\n", "   Upkeep: %d%% mana.\n"), show_upkeep);
1722
1723         my_fclose(fff);
1724         (void)show_file(creature_ptr, TRUE, file_name, _("現在のペット", "Current Pets"), 0, 0);
1725         fd_kill(file_name);
1726 }
1727
1728
1729 /*!
1730  * @brief 現在のペットを表示するコマンドのメインルーチン /
1731  * @param creature_ptr プレーヤーへの参照ポインタ
1732  * Total kill count
1733  * @return なし
1734  * @note the player ghosts are ignored.
1735  */
1736 static void do_cmd_knowledge_kill_count(player_type *creature_ptr)
1737 {
1738         FILE *fff;
1739         GAME_TEXT file_name[1024];
1740         fff = my_fopen_temp(file_name, 1024);
1741         if (!fff)
1742         {
1743                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
1744                 msg_print(NULL);
1745                 return;
1746         }
1747
1748         MONRACE_IDX *who;
1749         C_MAKE(who, max_r_idx, MONRACE_IDX);
1750         s32b total = 0;
1751         for (int kk = 1; kk < max_r_idx; kk++)
1752         {
1753                 monster_race *r_ptr = &r_info[kk];
1754
1755                 if (r_ptr->flags1 & (RF1_UNIQUE))
1756                 {
1757                         bool dead = (r_ptr->max_num == 0);
1758
1759                         if (dead)
1760                         {
1761                                 total++;
1762                         }
1763                 }
1764                 else
1765                 {
1766                         MONSTER_NUMBER this_monster = r_ptr->r_pkills;
1767
1768                         if (this_monster > 0)
1769                         {
1770                                 total += this_monster;
1771                         }
1772                 }
1773         }
1774
1775         if (total < 1)
1776                 fprintf(fff, _("あなたはまだ敵を倒していない。\n\n", "You have defeated no enemies yet.\n\n"));
1777         else
1778 #ifdef JP
1779                 fprintf(fff, "あなたは%ld体の敵を倒している。\n\n", (long int)total);
1780 #else
1781                 fprintf(fff, "You have defeated %ld %s.\n\n", (long int)total, (total == 1) ? "enemy" : "enemies");
1782 #endif
1783
1784         total = 0;
1785         int n = 0;
1786         for (MONRACE_IDX i = 1; i < max_r_idx; i++)
1787         {
1788                 monster_race *r_ptr = &r_info[i];
1789                 if (r_ptr->name) who[n++] = i;
1790         }
1791
1792         u16b why = 2;
1793         ang_sort(who, &why, n, ang_sort_comp_hook, ang_sort_swap_hook);
1794         for (int k = 0; k < n; k++)
1795         {
1796                 monster_race *r_ptr = &r_info[who[k]];
1797                 if (r_ptr->flags1 & (RF1_UNIQUE))
1798                 {
1799                         bool dead = (r_ptr->max_num == 0);
1800                         if (dead)
1801                         {
1802                                 fprintf(fff, "     %s\n", (r_name + r_ptr->name));
1803                                 total++;
1804                         }
1805
1806                         continue;
1807                 }
1808
1809                 MONSTER_NUMBER this_monster = r_ptr->r_pkills;
1810                 if (this_monster <= 0) continue;
1811
1812 #ifdef JP
1813                 if (my_strchr("pt", r_ptr->d_char))
1814                         fprintf(fff, "     %3d 人の %s\n", (int)this_monster, r_name + r_ptr->name);
1815                 else
1816                         fprintf(fff, "     %3d 体の %s\n", (int)this_monster, r_name + r_ptr->name);
1817 #else
1818                 if (this_monster < 2)
1819                 {
1820                         if (my_strstr(r_name + r_ptr->name, "coins"))
1821                         {
1822                                 fprintf(fff, "     1 pile of %s\n", (r_name + r_ptr->name));
1823                         }
1824                         else
1825                         {
1826                                 fprintf(fff, "     1 %s\n", (r_name + r_ptr->name));
1827                         }
1828                 }
1829                 else
1830                 {
1831                         char ToPlural[80];
1832                         strcpy(ToPlural, (r_name + r_ptr->name));
1833                         plural_aux(ToPlural);
1834                         fprintf(fff, "     %d %s\n", this_monster, ToPlural);
1835                 }
1836 #endif
1837                 total += this_monster;
1838         }
1839
1840         fprintf(fff, "----------------------------------------------\n");
1841 #ifdef JP
1842         fprintf(fff, "    合計: %lu 体を倒した。\n", (unsigned long int)total);
1843 #else
1844         fprintf(fff, "   Total: %lu creature%s killed.\n", (unsigned long int)total, (total == 1 ? "" : "s"));
1845 #endif
1846
1847         C_KILL(who, max_r_idx, s16b);
1848         my_fclose(fff);
1849         (void)show_file(creature_ptr, TRUE, file_name, _("倒した敵の数", "Kill Count"), 0, 0);
1850         fd_kill(file_name);
1851 }
1852
1853
1854 /*!
1855  * @brief モンスター情報リスト中のグループを表示する /
1856  * Display the object groups.
1857  * @param col 開始行
1858  * @param row 開始列
1859  * @param wid 表示文字数幅
1860  * @param per_page リストの表示行
1861  * @param grp_idx グループのID配列
1862  * @param group_text グループ名の文字列配列
1863  * @param grp_cur 現在の選択ID
1864  * @param grp_top 現在の選択リスト最上部ID
1865  * @return なし
1866  */
1867 static void display_group_list(int col, int row, int wid, int per_page, IDX grp_idx[], concptr group_text[], int grp_cur, int grp_top)
1868 {
1869         for (int i = 0; i < per_page && (grp_idx[i] >= 0); i++)
1870         {
1871                 int grp = grp_idx[grp_top + i];
1872                 TERM_COLOR attr = (grp_top + i == grp_cur) ? TERM_L_BLUE : TERM_WHITE;
1873                 Term_erase(col, row + i, wid);
1874                 c_put_str(attr, group_text[grp], row + i, col);
1875         }
1876 }
1877
1878
1879 /*
1880  * Move the cursor in a browser window
1881  */
1882 static void browser_cursor(char ch, int *column, IDX *grp_cur, int grp_cnt, IDX *list_cur, int list_cnt)
1883 {
1884         int d;
1885         int col = *column;
1886         IDX grp = *grp_cur;
1887         IDX list = *list_cur;
1888         if (ch == ' ')
1889                 d = 3;
1890         else if (ch == '-')
1891                 d = 9;
1892         else
1893                 d = get_keymap_dir(ch);
1894
1895         if (!d) return;
1896
1897         if ((ddx[d] > 0) && ddy[d])
1898         {
1899                 int browser_rows;
1900                 int wid, hgt;
1901                 Term_get_size(&wid, &hgt);
1902                 browser_rows = hgt - 8;
1903                 if (!col)
1904                 {
1905                         int old_grp = grp;
1906                         grp += ddy[d] * (browser_rows - 1);
1907                         if (grp >= grp_cnt)     grp = grp_cnt - 1;
1908                         if (grp < 0) grp = 0;
1909                         if (grp != old_grp)     list = 0;
1910                 }
1911                 else
1912                 {
1913                         list += ddy[d] * browser_rows;
1914                         if (list >= list_cnt) list = list_cnt - 1;
1915                         if (list < 0) list = 0;
1916                 }
1917
1918                 (*grp_cur) = grp;
1919                 (*list_cur) = list;
1920                 return;
1921         }
1922
1923         if (ddx[d])
1924         {
1925                 col += ddx[d];
1926                 if (col < 0) col = 0;
1927                 if (col > 1) col = 1;
1928
1929                 (*column) = col;
1930                 return;
1931         }
1932
1933         if (!col)
1934         {
1935                 int old_grp = grp;
1936                 grp += (IDX)ddy[d];
1937                 if (grp >= grp_cnt)     grp = grp_cnt - 1;
1938                 if (grp < 0) grp = 0;
1939                 if (grp != old_grp)     list = 0;
1940         }
1941         else
1942         {
1943                 list += (IDX)ddy[d];
1944                 if (list >= list_cnt) list = list_cnt - 1;
1945                 if (list < 0) list = 0;
1946         }
1947
1948         (*grp_cur) = grp;
1949         (*list_cur) = list;
1950 }
1951
1952
1953 /*
1954  * Display visuals.
1955  */
1956 static void display_visual_list(int col, int row, int height, int width, TERM_COLOR attr_top, byte char_left)
1957 {
1958         for (int i = 0; i < height; i++)
1959         {
1960                 Term_erase(col, row + i, width);
1961         }
1962
1963         if (use_bigtile) width /= 2;
1964
1965         for (int i = 0; i < height; i++)
1966         {
1967                 for (int j = 0; j < width; j++)
1968                 {
1969                         TERM_LEN x = col + j;
1970                         TERM_LEN y = row + i;
1971                         if (use_bigtile) x += j;
1972
1973                         TERM_COLOR ia = attr_top + i;
1974                         SYMBOL_CODE ic = char_left + j;
1975                         if (ia > 0x7f || ic > 0xff || ic < ' ' ||
1976                                 (!use_graphics && ic > 0x7f))
1977                                 continue;
1978
1979                         TERM_COLOR a = ia;
1980                         SYMBOL_CODE c = ic;
1981                         if (c & 0x80) a |= 0x80;
1982
1983                         Term_queue_bigchar(x, y, a, c, 0, 0);
1984                 }
1985         }
1986 }
1987
1988
1989 /*
1990  * Place the cursor at the collect position for visual mode
1991  */
1992 static void place_visual_list_cursor(TERM_LEN col, TERM_LEN row, TERM_COLOR a, byte c, TERM_COLOR attr_top, byte char_left)
1993 {
1994         int i = (a & 0x7f) - attr_top;
1995         int j = c - char_left;
1996
1997         TERM_LEN x = col + j;
1998         TERM_LEN y = row + i;
1999         if (use_bigtile) x += j;
2000
2001         Term_gotoxy(x, y);
2002 }
2003
2004
2005 /*
2006  *  Do visual mode command -- Change symbols
2007  */
2008 static bool visual_mode_command(char ch, bool *visual_list_ptr,
2009         int height, int width,
2010         TERM_COLOR *attr_top_ptr, byte *char_left_ptr,
2011         TERM_COLOR *cur_attr_ptr, SYMBOL_CODE *cur_char_ptr, bool *need_redraw)
2012 {
2013         static TERM_COLOR attr_old = 0;
2014         static SYMBOL_CODE char_old = 0;
2015
2016         switch (ch)
2017         {
2018         case ESCAPE:
2019                 if (*visual_list_ptr)
2020                 {
2021                         *cur_attr_ptr = attr_old;
2022                         *cur_char_ptr = char_old;
2023                         *visual_list_ptr = FALSE;
2024
2025                         return TRUE;
2026                 }
2027
2028                 break;
2029
2030         case '\n':
2031         case '\r':
2032                 if (*visual_list_ptr)
2033                 {
2034                         *visual_list_ptr = FALSE;
2035                         *need_redraw = TRUE;
2036
2037                         return TRUE;
2038                 }
2039
2040                 break;
2041
2042         case 'V':
2043         case 'v':
2044                 if (!*visual_list_ptr)
2045                 {
2046                         *visual_list_ptr = TRUE;
2047
2048                         *attr_top_ptr = MAX(0, (*cur_attr_ptr & 0x7f) - 5);
2049                         *char_left_ptr = MAX(0, *cur_char_ptr - 10);
2050
2051                         attr_old = *cur_attr_ptr;
2052                         char_old = *cur_char_ptr;
2053
2054                         return TRUE;
2055                 }
2056
2057                 break;
2058
2059         case 'C':
2060         case 'c':
2061         {
2062                 attr_idx = *cur_attr_ptr;
2063                 char_idx = *cur_char_ptr;
2064                 for (int i = 0; i < F_LIT_MAX; i++)
2065                 {
2066                         attr_idx_feat[i] = 0;
2067                         char_idx_feat[i] = 0;
2068                 }
2069         }
2070
2071         return TRUE;
2072
2073         case 'P':
2074         case 'p':
2075                 if (attr_idx || (!(char_idx & 0x80) && char_idx))
2076                 {
2077                         *cur_attr_ptr = attr_idx;
2078                         *attr_top_ptr = MAX(0, (*cur_attr_ptr & 0x7f) - 5);
2079                         if (!*visual_list_ptr) *need_redraw = TRUE;
2080                 }
2081
2082                 if (char_idx)
2083                 {
2084                         /* Set the char */
2085                         *cur_char_ptr = char_idx;
2086                         *char_left_ptr = MAX(0, *cur_char_ptr - 10);
2087                         if (!*visual_list_ptr) *need_redraw = TRUE;
2088                 }
2089
2090                 return TRUE;
2091
2092         default:
2093                 if (*visual_list_ptr)
2094                 {
2095                         int eff_width;
2096                         int d = get_keymap_dir(ch);
2097                         TERM_COLOR a = (*cur_attr_ptr & 0x7f);
2098                         SYMBOL_CODE c = *cur_char_ptr;
2099
2100                         if (use_bigtile) eff_width = width / 2;
2101                         else eff_width = width;
2102
2103                         if ((a == 0) && (ddy[d] < 0)) d = 0;
2104                         if ((c == 0) && (ddx[d] < 0)) d = 0;
2105                         if ((a == 0x7f) && (ddy[d] > 0)) d = 0;
2106                         if ((c == 0xff) && (ddx[d] > 0)) d = 0;
2107
2108                         a += (TERM_COLOR)ddy[d];
2109                         c += (SYMBOL_CODE)ddx[d];
2110                         if (c & 0x80) a |= 0x80;
2111
2112                         *cur_attr_ptr = a;
2113                         *cur_char_ptr = c;
2114                         if ((ddx[d] < 0) && *char_left_ptr > MAX(0, (int)c - 10)) (*char_left_ptr)--;
2115                         if ((ddx[d] > 0) && *char_left_ptr + eff_width < MIN(0xff, (int)c + 10)) (*char_left_ptr)++;
2116                         if ((ddy[d] < 0) && *attr_top_ptr > MAX(0, (int)(a & 0x7f) - 4)) (*attr_top_ptr)--;
2117                         if ((ddy[d] > 0) && *attr_top_ptr + height < MIN(0x7f, (a & 0x7f) + 4)) (*attr_top_ptr)++;
2118                         return TRUE;
2119                 }
2120
2121                 break;
2122         }
2123
2124         return FALSE;
2125 }
2126
2127
2128 /*
2129  * Display the monsters in a group.
2130  */
2131 static void display_monster_list(int col, int row, int per_page, s16b mon_idx[], int mon_cur, int mon_top, bool visual_only)
2132 {
2133         int i;
2134         for (i = 0; i < per_page && (mon_idx[mon_top + i] >= 0); i++)
2135         {
2136                 TERM_COLOR attr;
2137                 MONRACE_IDX r_idx = mon_idx[mon_top + i];
2138                 monster_race *r_ptr = &r_info[r_idx];
2139                 attr = ((i + mon_top == mon_cur) ? TERM_L_BLUE : TERM_WHITE);
2140                 c_prt(attr, (r_name + r_ptr->name), row + i, col);
2141                 if (per_page == 1)
2142                 {
2143                         c_prt(attr, format("%02x/%02x", r_ptr->x_attr, r_ptr->x_char), row + i, (current_world_ptr->wizard || visual_only) ? 56 : 61);
2144                 }
2145
2146                 if (current_world_ptr->wizard || visual_only)
2147                 {
2148                         c_prt(attr, format("%d", r_idx), row + i, 62);
2149                 }
2150
2151                 Term_erase(69, row + i, 255);
2152                 Term_queue_bigchar(use_bigtile ? 69 : 70, row + i, r_ptr->x_attr, r_ptr->x_char, 0, 0);
2153                 if (!visual_only)
2154                 {
2155                         if (!(r_ptr->flags1 & RF1_UNIQUE))
2156                                 put_str(format("%5d", r_ptr->r_pkills), row + i, 73);
2157                         else
2158                                 c_put_str((r_ptr->max_num == 0 ? TERM_L_DARK : TERM_WHITE),
2159                                 (r_ptr->max_num == 0 ? _("死亡", " dead") : _("生存", "alive")), row + i, 74);
2160                 }
2161         }
2162
2163         for (; i < per_page; i++)
2164         {
2165                 Term_erase(col, row + i, 255);
2166         }
2167 }
2168
2169
2170 /*
2171  * todo 引数の詳細について加筆求む
2172  * Display known monsters.
2173  * @param creature_ptr プレーヤーへの参照ポインタ
2174  * @param need_redraw 画面の再描画が必要な時TRUE
2175  * @param visual_only ???
2176  * @param direct_r_idx モンスターID
2177  * @return なし
2178  */
2179 void do_cmd_knowledge_monsters(player_type *creature_ptr, bool *need_redraw, bool visual_only, IDX direct_r_idx)
2180 {
2181         TERM_LEN wid, hgt;
2182         Term_get_size(&wid, &hgt);
2183         IDX *mon_idx;
2184         C_MAKE(mon_idx, max_r_idx, MONRACE_IDX);
2185
2186         int max = 0;
2187         IDX grp_cnt = 0;
2188         IDX grp_idx[100];
2189         IDX mon_cnt;
2190         bool visual_list = FALSE;
2191         TERM_COLOR attr_top = 0;
2192         byte char_left = 0;
2193         BIT_FLAGS8 mode;
2194         int browser_rows = hgt - 8;
2195         if (direct_r_idx < 0)
2196         {
2197                 mode = visual_only ? 0x03 : 0x01;
2198                 int len;
2199                 for (IDX i = 0; monster_group_text[i] != NULL; i++)
2200                 {
2201                         len = strlen(monster_group_text[i]);
2202                         if (len > max) max = len;
2203
2204                         if ((monster_group_char[i] == ((char *)-1L)) || collect_monsters(creature_ptr, i, mon_idx, mode))
2205                         {
2206                                 grp_idx[grp_cnt++] = i;
2207                         }
2208                 }
2209
2210                 mon_cnt = 0;
2211         }
2212         else
2213         {
2214                 mon_idx[0] = direct_r_idx;
2215                 mon_cnt = 1;
2216                 mon_idx[1] = -1;
2217
2218                 (void)visual_mode_command('v', &visual_list, browser_rows - 1, wid - (max + 3),
2219                         &attr_top, &char_left, &r_info[direct_r_idx].x_attr, &r_info[direct_r_idx].x_char, need_redraw);
2220         }
2221
2222         grp_idx[grp_cnt] = -1;
2223         mode = visual_only ? 0x02 : 0x00;
2224         IDX old_grp_cur = -1;
2225         IDX grp_cur = 0;
2226         IDX grp_top = 0;
2227         IDX mon_cur = 0;
2228         IDX mon_top = 0;
2229         int column = 0;
2230         bool flag = FALSE;
2231         bool redraw = TRUE;
2232         while (!flag)
2233         {
2234                 if (redraw)
2235                 {
2236                         clear_from(0);
2237                         prt(format(_("%s - モンスター", "%s - monsters"), !visual_only ? _("知識", "Knowledge") : _("表示", "Visuals")), 2, 0);
2238                         if (direct_r_idx < 0) prt(_("グループ", "Group"), 4, 0);
2239                         prt(_("名前", "Name"), 4, max + 3);
2240                         if (current_world_ptr->wizard || visual_only) prt("Idx", 4, 62);
2241                         prt(_("文字", "Sym"), 4, 67);
2242                         if (!visual_only) prt(_("殺害数", "Kills"), 4, 72);
2243
2244                         for (IDX i = 0; i < 78; i++)
2245                         {
2246                                 Term_putch(i, 5, TERM_WHITE, '=');
2247                         }
2248
2249                         if (direct_r_idx < 0)
2250                         {
2251                                 for (IDX i = 0; i < browser_rows; i++)
2252                                 {
2253                                         Term_putch(max + 1, 6 + i, TERM_WHITE, '|');
2254                                 }
2255                         }
2256
2257                         redraw = FALSE;
2258                 }
2259
2260                 if (direct_r_idx < 0)
2261                 {
2262                         if (grp_cur < grp_top) grp_top = grp_cur;
2263                         if (grp_cur >= grp_top + browser_rows) grp_top = grp_cur - browser_rows + 1;
2264
2265                         display_group_list(0, 6, max, browser_rows, grp_idx, monster_group_text, grp_cur, grp_top);
2266                         if (old_grp_cur != grp_cur)
2267                         {
2268                                 old_grp_cur = grp_cur;
2269                                 mon_cnt = collect_monsters(creature_ptr, grp_idx[grp_cur], mon_idx, mode);
2270                         }
2271
2272                         while (mon_cur < mon_top)
2273                                 mon_top = MAX(0, mon_top - browser_rows / 2);
2274                         while (mon_cur >= mon_top + browser_rows)
2275                                 mon_top = MIN(mon_cnt - browser_rows, mon_top + browser_rows / 2);
2276                 }
2277
2278                 if (!visual_list)
2279                 {
2280                         display_monster_list(max + 3, 6, browser_rows, mon_idx, mon_cur, mon_top, visual_only);
2281                 }
2282                 else
2283                 {
2284                         mon_top = mon_cur;
2285                         display_monster_list(max + 3, 6, 1, mon_idx, mon_cur, mon_top, visual_only);
2286                         display_visual_list(max + 3, 7, browser_rows - 1, wid - (max + 3), attr_top, char_left);
2287                 }
2288
2289                 prt(format(_("<方向>%s%s%s, ESC", "<dir>%s%s%s, ESC"),
2290                         (!visual_list && !visual_only) ? _(", 'r'で思い出を見る", ", 'r' to recall") : "",
2291                         visual_list ? _(", ENTERで決定", ", ENTER to accept") : _(", 'v'でシンボル変更", ", 'v' for visuals"),
2292                         (attr_idx || char_idx) ? _(", 'c', 'p'でペースト", ", 'c', 'p' to paste") : _(", 'c'でコピー", ", 'c' to copy")),
2293                         hgt - 1, 0);
2294
2295                 monster_race *r_ptr;
2296                 r_ptr = &r_info[mon_idx[mon_cur]];
2297
2298                 if (!visual_only)
2299                 {
2300                         if (mon_cnt) monster_race_track(creature_ptr, mon_idx[mon_cur]);
2301                         handle_stuff(creature_ptr);
2302                 }
2303
2304                 if (visual_list)
2305                 {
2306                         place_visual_list_cursor(max + 3, 7, r_ptr->x_attr, r_ptr->x_char, attr_top, char_left);
2307                 }
2308                 else if (!column)
2309                 {
2310                         Term_gotoxy(0, 6 + (grp_cur - grp_top));
2311                 }
2312                 else
2313                 {
2314                         Term_gotoxy(max + 3, 6 + (mon_cur - mon_top));
2315                 }
2316
2317                 char ch = inkey();
2318                 if (visual_mode_command(ch, &visual_list, browser_rows - 1, wid - (max + 3), &attr_top, &char_left, &r_ptr->x_attr, &r_ptr->x_char, need_redraw))
2319                 {
2320                         if (direct_r_idx >= 0)
2321                         {
2322                                 switch (ch)
2323                                 {
2324                                 case '\n':
2325                                 case '\r':
2326                                 case ESCAPE:
2327                                         flag = TRUE;
2328                                         break;
2329                                 }
2330                         }
2331
2332                         continue;
2333                 }
2334
2335                 switch (ch)
2336                 {
2337                 case ESCAPE:
2338                 {
2339                         flag = TRUE;
2340                         break;
2341                 }
2342
2343                 case 'R':
2344                 case 'r':
2345                 {
2346                         if (!visual_list && !visual_only && (mon_idx[mon_cur] > 0))
2347                         {
2348                                 screen_roff(creature_ptr, mon_idx[mon_cur], 0);
2349
2350                                 (void)inkey();
2351
2352                                 redraw = TRUE;
2353                         }
2354
2355                         break;
2356                 }
2357
2358                 default:
2359                 {
2360                         browser_cursor(ch, &column, &grp_cur, grp_cnt, &mon_cur, mon_cnt);
2361
2362                         break;
2363                 }
2364                 }
2365         }
2366
2367         C_KILL(mon_idx, max_r_idx, MONRACE_IDX);
2368 }
2369
2370
2371 /*
2372  * Display the objects in a group.
2373  */
2374 static void display_object_list(int col, int row, int per_page, IDX object_idx[],
2375         int object_cur, int object_top, bool visual_only)
2376 {
2377         int i;
2378         for (i = 0; i < per_page && (object_idx[object_top + i] >= 0); i++)
2379         {
2380                 GAME_TEXT o_name[MAX_NLEN];
2381                 TERM_COLOR a;
2382                 SYMBOL_CODE c;
2383                 object_kind *flavor_k_ptr;
2384                 KIND_OBJECT_IDX k_idx = object_idx[object_top + i];
2385                 object_kind *k_ptr = &k_info[k_idx];
2386                 TERM_COLOR attr = ((k_ptr->aware || visual_only) ? TERM_WHITE : TERM_SLATE);
2387                 byte cursor = ((k_ptr->aware || visual_only) ? TERM_L_BLUE : TERM_BLUE);
2388                 if (!visual_only && k_ptr->flavor)
2389                 {
2390                         flavor_k_ptr = &k_info[k_ptr->flavor];
2391                 }
2392                 else
2393                 {
2394                         flavor_k_ptr = k_ptr;
2395                 }
2396
2397                 attr = ((i + object_top == object_cur) ? cursor : attr);
2398                 if (!k_ptr->flavor || (!visual_only && k_ptr->aware))
2399                 {
2400                         strip_name(o_name, k_idx);
2401                 }
2402                 else
2403                 {
2404                         strcpy(o_name, k_name + flavor_k_ptr->flavor_name);
2405                 }
2406
2407                 c_prt(attr, o_name, row + i, col);
2408                 if (per_page == 1)
2409                 {
2410                         c_prt(attr, format("%02x/%02x", flavor_k_ptr->x_attr, flavor_k_ptr->x_char), row + i, (current_world_ptr->wizard || visual_only) ? 64 : 68);
2411                 }
2412
2413                 if (current_world_ptr->wizard || visual_only)
2414                 {
2415                         c_prt(attr, format("%d", k_idx), row + i, 70);
2416                 }
2417
2418                 a = flavor_k_ptr->x_attr;
2419                 c = flavor_k_ptr->x_char;
2420
2421                 Term_queue_bigchar(use_bigtile ? 76 : 77, row + i, a, c, 0, 0);
2422         }
2423
2424         for (; i < per_page; i++)
2425         {
2426                 Term_erase(col, row + i, 255);
2427         }
2428 }
2429
2430
2431 /*
2432  * Describe fake object
2433  */
2434 static void desc_obj_fake(player_type *creature_ptr, KIND_OBJECT_IDX k_idx)
2435 {
2436         object_type *o_ptr;
2437         object_type object_type_body;
2438         o_ptr = &object_type_body;
2439         object_wipe(o_ptr);
2440         object_prep(o_ptr, k_idx);
2441
2442         o_ptr->ident |= IDENT_KNOWN;
2443         handle_stuff(creature_ptr);
2444
2445         if (screen_object(creature_ptr, o_ptr, SCROBJ_FAKE_OBJECT | SCROBJ_FORCE_DETAIL)) return;
2446
2447         msg_print(_("特に変わったところはないようだ。", "You see nothing special."));
2448         msg_print(NULL);
2449 }
2450
2451
2452 /*
2453  * Display known objects
2454  */
2455 void do_cmd_knowledge_objects(player_type *creature_ptr, bool *need_redraw, bool visual_only, IDX direct_k_idx)
2456 {
2457         IDX object_old, object_top;
2458         IDX grp_idx[100];
2459         int object_cnt;
2460         OBJECT_IDX *object_idx;
2461
2462         bool visual_list = FALSE;
2463         TERM_COLOR attr_top = 0;
2464         byte char_left = 0;
2465         byte mode;
2466
2467         TERM_LEN wid, hgt;
2468         Term_get_size(&wid, &hgt);
2469
2470         int browser_rows = hgt - 8;
2471         C_MAKE(object_idx, max_k_idx, KIND_OBJECT_IDX);
2472
2473         int len;
2474         int max = 0;
2475         int grp_cnt = 0;
2476         if (direct_k_idx < 0)
2477         {
2478                 mode = visual_only ? 0x03 : 0x01;
2479                 for (IDX i = 0; object_group_text[i] != NULL; i++)
2480                 {
2481                         len = strlen(object_group_text[i]);
2482                         if (len > max) max = len;
2483
2484                         if (collect_objects(i, object_idx, mode))
2485                         {
2486                                 grp_idx[grp_cnt++] = i;
2487                         }
2488                 }
2489
2490                 object_old = -1;
2491                 object_cnt = 0;
2492         }
2493         else
2494         {
2495                 object_kind *k_ptr = &k_info[direct_k_idx];
2496                 object_kind *flavor_k_ptr;
2497
2498                 if (!visual_only && k_ptr->flavor)
2499                 {
2500                         flavor_k_ptr = &k_info[k_ptr->flavor];
2501                 }
2502                 else
2503                 {
2504                         flavor_k_ptr = k_ptr;
2505                 }
2506
2507                 object_idx[0] = direct_k_idx;
2508                 object_old = direct_k_idx;
2509                 object_cnt = 1;
2510                 object_idx[1] = -1;
2511                 (void)visual_mode_command('v', &visual_list, browser_rows - 1, wid - (max + 3),
2512                         &attr_top, &char_left, &flavor_k_ptr->x_attr, &flavor_k_ptr->x_char, need_redraw);
2513         }
2514
2515         grp_idx[grp_cnt] = -1;
2516         mode = visual_only ? 0x02 : 0x00;
2517         IDX old_grp_cur = -1;
2518         IDX grp_cur = 0;
2519         IDX grp_top = 0;
2520         IDX object_cur = object_top = 0;
2521         bool flag = FALSE;
2522         bool redraw = TRUE;
2523         int column = 0;
2524         while (!flag)
2525         {
2526                 object_kind *k_ptr, *flavor_k_ptr;
2527
2528                 if (redraw)
2529                 {
2530                         clear_from(0);
2531
2532 #ifdef JP
2533                         prt(format("%s - アイテム", !visual_only ? "知識" : "表示"), 2, 0);
2534                         if (direct_k_idx < 0) prt("グループ", 4, 0);
2535                         prt("名前", 4, max + 3);
2536                         if (current_world_ptr->wizard || visual_only) prt("Idx", 4, 70);
2537                         prt("文字", 4, 74);
2538 #else
2539                         prt(format("%s - objects", !visual_only ? "Knowledge" : "Visuals"), 2, 0);
2540                         if (direct_k_idx < 0) prt("Group", 4, 0);
2541                         prt("Name", 4, max + 3);
2542                         if (current_world_ptr->wizard || visual_only) prt("Idx", 4, 70);
2543                         prt("Sym", 4, 75);
2544 #endif
2545
2546                         for (IDX i = 0; i < 78; i++)
2547                         {
2548                                 Term_putch(i, 5, TERM_WHITE, '=');
2549                         }
2550
2551                         if (direct_k_idx < 0)
2552                         {
2553                                 for (IDX i = 0; i < browser_rows; i++)
2554                                 {
2555                                         Term_putch(max + 1, 6 + i, TERM_WHITE, '|');
2556                                 }
2557                         }
2558
2559                         redraw = FALSE;
2560                 }
2561
2562                 if (direct_k_idx < 0)
2563                 {
2564                         if (grp_cur < grp_top) grp_top = grp_cur;
2565                         if (grp_cur >= grp_top + browser_rows) grp_top = grp_cur - browser_rows + 1;
2566
2567                         display_group_list(0, 6, max, browser_rows, grp_idx, object_group_text, grp_cur, grp_top);
2568                         if (old_grp_cur != grp_cur)
2569                         {
2570                                 old_grp_cur = grp_cur;
2571                                 object_cnt = collect_objects(grp_idx[grp_cur], object_idx, mode);
2572                         }
2573
2574                         while (object_cur < object_top)
2575                                 object_top = MAX(0, object_top - browser_rows / 2);
2576                         while (object_cur >= object_top + browser_rows)
2577                                 object_top = MIN(object_cnt - browser_rows, object_top + browser_rows / 2);
2578                 }
2579
2580                 if (!visual_list)
2581                 {
2582                         display_object_list(max + 3, 6, browser_rows, object_idx, object_cur, object_top, visual_only);
2583                 }
2584                 else
2585                 {
2586                         object_top = object_cur;
2587                         display_object_list(max + 3, 6, 1, object_idx, object_cur, object_top, visual_only);
2588                         display_visual_list(max + 3, 7, browser_rows - 1, wid - (max + 3), attr_top, char_left);
2589                 }
2590
2591                 k_ptr = &k_info[object_idx[object_cur]];
2592
2593                 if (!visual_only && k_ptr->flavor)
2594                 {
2595                         flavor_k_ptr = &k_info[k_ptr->flavor];
2596                 }
2597                 else
2598                 {
2599                         flavor_k_ptr = k_ptr;
2600                 }
2601
2602 #ifdef JP
2603                 prt(format("<方向>%s%s%s, ESC",
2604                         (!visual_list && !visual_only) ? ", 'r'で詳細を見る" : "",
2605                         visual_list ? ", ENTERで決定" : ", 'v'でシンボル変更",
2606                         (attr_idx || char_idx) ? ", 'c', 'p'でペースト" : ", 'c'でコピー"),
2607                         hgt - 1, 0);
2608 #else
2609                 prt(format("<dir>%s%s%s, ESC",
2610                         (!visual_list && !visual_only) ? ", 'r' to recall" : "",
2611                         visual_list ? ", ENTER to accept" : ", 'v' for visuals",
2612                         (attr_idx || char_idx) ? ", 'c', 'p' to paste" : ", 'c' to copy"),
2613                         hgt - 1, 0);
2614 #endif
2615
2616                 if (!visual_only)
2617                 {
2618                         if (object_cnt) object_kind_track(creature_ptr, object_idx[object_cur]);
2619
2620                         if (object_old != object_idx[object_cur])
2621                         {
2622                                 handle_stuff(creature_ptr);
2623                                 object_old = object_idx[object_cur];
2624                         }
2625                 }
2626
2627                 if (visual_list)
2628                 {
2629                         place_visual_list_cursor(max + 3, 7, flavor_k_ptr->x_attr, flavor_k_ptr->x_char, attr_top, char_left);
2630                 }
2631                 else if (!column)
2632                 {
2633                         Term_gotoxy(0, 6 + (grp_cur - grp_top));
2634                 }
2635                 else
2636                 {
2637                         Term_gotoxy(max + 3, 6 + (object_cur - object_top));
2638                 }
2639
2640                 char ch = inkey();
2641                 if (visual_mode_command(ch, &visual_list, browser_rows - 1, wid - (max + 3), &attr_top, &char_left, &flavor_k_ptr->x_attr, &flavor_k_ptr->x_char, need_redraw))
2642                 {
2643                         if (direct_k_idx >= 0)
2644                         {
2645                                 switch (ch)
2646                                 {
2647                                 case '\n':
2648                                 case '\r':
2649                                 case ESCAPE:
2650                                         flag = TRUE;
2651                                         break;
2652                                 }
2653                         }
2654                         continue;
2655                 }
2656
2657                 switch (ch)
2658                 {
2659                 case ESCAPE:
2660                 {
2661                         flag = TRUE;
2662                         break;
2663                 }
2664
2665                 case 'R':
2666                 case 'r':
2667                 {
2668                         if (!visual_list && !visual_only && (grp_cnt > 0))
2669                         {
2670                                 desc_obj_fake(creature_ptr, object_idx[object_cur]);
2671                                 redraw = TRUE;
2672                         }
2673
2674                         break;
2675                 }
2676
2677                 default:
2678                 {
2679                         browser_cursor(ch, &column, &grp_cur, grp_cnt, &object_cur, object_cnt);
2680                         break;
2681                 }
2682                 }
2683         }
2684
2685         C_KILL(object_idx, max_k_idx, KIND_OBJECT_IDX);
2686 }
2687
2688
2689 /*
2690  * Display the features in a group.
2691  */
2692 static void display_feature_list(int col, int row, int per_page, FEAT_IDX *feat_idx,
2693         FEAT_IDX feat_cur, FEAT_IDX feat_top, bool visual_only, int lighting_level)
2694 {
2695         int lit_col[F_LIT_MAX], i;
2696         int f_idx_col = use_bigtile ? 62 : 64;
2697
2698         lit_col[F_LIT_STANDARD] = use_bigtile ? (71 - F_LIT_MAX) : 71;
2699         for (i = F_LIT_NS_BEGIN; i < F_LIT_MAX; i++)
2700                 lit_col[i] = lit_col[F_LIT_STANDARD] + 2 + (i - F_LIT_NS_BEGIN) * 2 + (use_bigtile ? i : 0);
2701
2702         for (i = 0; i < per_page && (feat_idx[feat_top + i] >= 0); i++)
2703         {
2704                 TERM_COLOR attr;
2705                 FEAT_IDX f_idx = feat_idx[feat_top + i];
2706                 feature_type *f_ptr = &f_info[f_idx];
2707                 int row_i = row + i;
2708                 attr = ((i + feat_top == feat_cur) ? TERM_L_BLUE : TERM_WHITE);
2709                 c_prt(attr, f_name + f_ptr->name, row_i, col);
2710                 if (per_page == 1)
2711                 {
2712                         c_prt(attr, format("(%s)", lighting_level_str[lighting_level]), row_i, col + 1 + strlen(f_name + f_ptr->name));
2713                         c_prt(attr, format("%02x/%02x", f_ptr->x_attr[lighting_level], f_ptr->x_char[lighting_level]), row_i, f_idx_col - ((current_world_ptr->wizard || visual_only) ? 6 : 2));
2714                 }
2715                 if (current_world_ptr->wizard || visual_only)
2716                 {
2717                         c_prt(attr, format("%d", f_idx), row_i, f_idx_col);
2718                 }
2719
2720                 Term_queue_bigchar(lit_col[F_LIT_STANDARD], row_i, f_ptr->x_attr[F_LIT_STANDARD], f_ptr->x_char[F_LIT_STANDARD], 0, 0);
2721                 Term_putch(lit_col[F_LIT_NS_BEGIN], row_i, TERM_SLATE, '(');
2722                 for (int j = F_LIT_NS_BEGIN + 1; j < F_LIT_MAX; j++)
2723                 {
2724                         Term_putch(lit_col[j], row_i, TERM_SLATE, '/');
2725                 }
2726
2727                 Term_putch(lit_col[F_LIT_MAX - 1] + (use_bigtile ? 3 : 2), row_i, TERM_SLATE, ')');
2728                 for (int j = F_LIT_NS_BEGIN; j < F_LIT_MAX; j++)
2729                 {
2730                         Term_queue_bigchar(lit_col[j] + 1, row_i, f_ptr->x_attr[j], f_ptr->x_char[j], 0, 0);
2731                 }
2732         }
2733
2734         for (; i < per_page; i++)
2735         {
2736                 Term_erase(col, row + i, 255);
2737         }
2738 }
2739
2740
2741 /*
2742  * Interact with feature visuals.
2743  */
2744 void do_cmd_knowledge_features(bool *need_redraw, bool visual_only, IDX direct_f_idx, IDX *lighting_level)
2745 {
2746         TERM_COLOR attr_old[F_LIT_MAX];
2747         (void)C_WIPE(attr_old, F_LIT_MAX, TERM_COLOR);
2748         SYMBOL_CODE char_old[F_LIT_MAX];
2749         (void)C_WIPE(char_old, F_LIT_MAX, SYMBOL_CODE);
2750
2751         TERM_LEN wid, hgt;
2752         Term_get_size(&wid, &hgt);
2753
2754         FEAT_IDX *feat_idx;
2755         C_MAKE(feat_idx, max_f_idx, FEAT_IDX);
2756
2757         int len;
2758         int max = 0;
2759         int grp_cnt = 0;
2760         int feat_cnt;
2761         FEAT_IDX grp_idx[100];
2762         TERM_COLOR attr_top = 0;
2763         bool visual_list = FALSE;
2764         byte char_left = 0;
2765         TERM_LEN browser_rows = hgt - 8;
2766         if (direct_f_idx < 0)
2767         {
2768                 for (FEAT_IDX i = 0; feature_group_text[i] != NULL; i++)
2769                 {
2770                         len = strlen(feature_group_text[i]);
2771                         if (len > max) max = len;
2772
2773                         if (collect_features(feat_idx, 0x01))
2774                         {
2775                                 grp_idx[grp_cnt++] = i;
2776                         }
2777                 }
2778
2779                 feat_cnt = 0;
2780         }
2781         else
2782         {
2783                 feature_type *f_ptr = &f_info[direct_f_idx];
2784
2785                 feat_idx[0] = direct_f_idx;
2786                 feat_cnt = 1;
2787                 feat_idx[1] = -1;
2788
2789                 (void)visual_mode_command('v', &visual_list, browser_rows - 1, wid - (max + 3),
2790                         &attr_top, &char_left, &f_ptr->x_attr[*lighting_level], &f_ptr->x_char[*lighting_level], need_redraw);
2791
2792                 for (FEAT_IDX i = 0; i < F_LIT_MAX; i++)
2793                 {
2794                         attr_old[i] = f_ptr->x_attr[i];
2795                         char_old[i] = f_ptr->x_char[i];
2796                 }
2797         }
2798
2799         grp_idx[grp_cnt] = -1;
2800
2801         FEAT_IDX old_grp_cur = -1;
2802         FEAT_IDX grp_cur = 0;
2803         FEAT_IDX grp_top = 0;
2804         FEAT_IDX feat_cur = 0;
2805         FEAT_IDX feat_top = 0;
2806         TERM_LEN column = 0;
2807         bool flag = FALSE;
2808         bool redraw = TRUE;
2809         TERM_COLOR *cur_attr_ptr;
2810         SYMBOL_CODE *cur_char_ptr;
2811         while (!flag)
2812         {
2813                 char ch;
2814                 feature_type *f_ptr;
2815
2816                 if (redraw)
2817                 {
2818                         clear_from(0);
2819
2820                         prt(_("表示 - 地形", "Visuals - features"), 2, 0);
2821                         if (direct_f_idx < 0) prt(_("グループ", "Group"), 4, 0);
2822                         prt(_("名前", "Name"), 4, max + 3);
2823                         if (use_bigtile)
2824                         {
2825                                 if (current_world_ptr->wizard || visual_only) prt("Idx", 4, 62);
2826                                 prt(_("文字 ( l/ d)", "Sym ( l/ d)"), 4, 66);
2827                         }
2828                         else
2829                         {
2830                                 if (current_world_ptr->wizard || visual_only) prt("Idx", 4, 64);
2831                                 prt(_("文字 (l/d)", "Sym (l/d)"), 4, 68);
2832                         }
2833
2834                         for (FEAT_IDX i = 0; i < 78; i++)
2835                         {
2836                                 Term_putch(i, 5, TERM_WHITE, '=');
2837                         }
2838
2839                         if (direct_f_idx < 0)
2840                         {
2841                                 for (FEAT_IDX i = 0; i < browser_rows; i++)
2842                                 {
2843                                         Term_putch(max + 1, 6 + i, TERM_WHITE, '|');
2844                                 }
2845                         }
2846
2847                         redraw = FALSE;
2848                 }
2849
2850                 if (direct_f_idx < 0)
2851                 {
2852                         if (grp_cur < grp_top) grp_top = grp_cur;
2853                         if (grp_cur >= grp_top + browser_rows) grp_top = grp_cur - browser_rows + 1;
2854
2855                         display_group_list(0, 6, max, browser_rows, grp_idx, feature_group_text, grp_cur, grp_top);
2856                         if (old_grp_cur != grp_cur)
2857                         {
2858                                 old_grp_cur = grp_cur;
2859                                 feat_cnt = collect_features(feat_idx, 0x00);
2860                         }
2861
2862                         while (feat_cur < feat_top)
2863                                 feat_top = MAX(0, feat_top - browser_rows / 2);
2864                         while (feat_cur >= feat_top + browser_rows)
2865                                 feat_top = MIN(feat_cnt - browser_rows, feat_top + browser_rows / 2);
2866                 }
2867
2868                 if (!visual_list)
2869                 {
2870                         display_feature_list(max + 3, 6, browser_rows, feat_idx, feat_cur, feat_top, visual_only, F_LIT_STANDARD);
2871                 }
2872                 else
2873                 {
2874                         feat_top = feat_cur;
2875                         display_feature_list(max + 3, 6, 1, feat_idx, feat_cur, feat_top, visual_only, *lighting_level);
2876                         display_visual_list(max + 3, 7, browser_rows - 1, wid - (max + 3), attr_top, char_left);
2877                 }
2878
2879                 prt(format(_("<方向>%s, 'd'で標準光源効果%s, ESC", "<dir>%s, 'd' for default lighting%s, ESC"),
2880                         visual_list ? _(", ENTERで決定, 'a'で対象明度変更", ", ENTER to accept, 'a' for lighting level") : _(", 'v'でシンボル変更", ", 'v' for visuals"),
2881                         (attr_idx || char_idx) ? _(", 'c', 'p'でペースト", ", 'c', 'p' to paste") : _(", 'c'でコピー", ", 'c' to copy")),
2882                         hgt - 1, 0);
2883
2884                 f_ptr = &f_info[feat_idx[feat_cur]];
2885                 cur_attr_ptr = &f_ptr->x_attr[*lighting_level];
2886                 cur_char_ptr = &f_ptr->x_char[*lighting_level];
2887
2888                 if (visual_list)
2889                 {
2890                         place_visual_list_cursor(max + 3, 7, *cur_attr_ptr, *cur_char_ptr, attr_top, char_left);
2891                 }
2892                 else if (!column)
2893                 {
2894                         Term_gotoxy(0, 6 + (grp_cur - grp_top));
2895                 }
2896                 else
2897                 {
2898                         Term_gotoxy(max + 3, 6 + (feat_cur - feat_top));
2899                 }
2900
2901                 ch = inkey();
2902                 if (visual_list && ((ch == 'A') || (ch == 'a')))
2903                 {
2904                         int prev_lighting_level = *lighting_level;
2905
2906                         if (ch == 'A')
2907                         {
2908                                 if (*lighting_level <= 0) *lighting_level = F_LIT_MAX - 1;
2909                                 else (*lighting_level)--;
2910                         }
2911                         else
2912                         {
2913                                 if (*lighting_level >= F_LIT_MAX - 1) *lighting_level = 0;
2914                                 else (*lighting_level)++;
2915                         }
2916
2917                         if (f_ptr->x_attr[prev_lighting_level] != f_ptr->x_attr[*lighting_level])
2918                                 attr_top = MAX(0, (f_ptr->x_attr[*lighting_level] & 0x7f) - 5);
2919
2920                         if (f_ptr->x_char[prev_lighting_level] != f_ptr->x_char[*lighting_level])
2921                                 char_left = MAX(0, f_ptr->x_char[*lighting_level] - 10);
2922
2923                         continue;
2924                 }
2925                 else if ((ch == 'D') || (ch == 'd'))
2926                 {
2927                         TERM_COLOR prev_x_attr = f_ptr->x_attr[*lighting_level];
2928                         byte prev_x_char = f_ptr->x_char[*lighting_level];
2929
2930                         apply_default_feat_lighting(f_ptr->x_attr, f_ptr->x_char);
2931
2932                         if (visual_list)
2933                         {
2934                                 if (prev_x_attr != f_ptr->x_attr[*lighting_level])
2935                                         attr_top = MAX(0, (f_ptr->x_attr[*lighting_level] & 0x7f) - 5);
2936
2937                                 if (prev_x_char != f_ptr->x_char[*lighting_level])
2938                                         char_left = MAX(0, f_ptr->x_char[*lighting_level] - 10);
2939                         }
2940                         else *need_redraw = TRUE;
2941
2942                         continue;
2943                 }
2944                 else if (visual_mode_command(ch, &visual_list, browser_rows - 1, wid - (max + 3), &attr_top, &char_left, cur_attr_ptr, cur_char_ptr, need_redraw))
2945                 {
2946                         switch (ch)
2947                         {
2948                         case ESCAPE:
2949                                 for (FEAT_IDX i = 0; i < F_LIT_MAX; i++)
2950                                 {
2951                                         f_ptr->x_attr[i] = attr_old[i];
2952                                         f_ptr->x_char[i] = char_old[i];
2953                                 }
2954
2955                                 /* Fall through */
2956                         case '\n':
2957                         case '\r':
2958                                 if (direct_f_idx >= 0) flag = TRUE;
2959                                 else *lighting_level = F_LIT_STANDARD;
2960                                 break;
2961                         case 'V':
2962                         case 'v':
2963                                 for (FEAT_IDX i = 0; i < F_LIT_MAX; i++)
2964                                 {
2965                                         attr_old[i] = f_ptr->x_attr[i];
2966                                         char_old[i] = f_ptr->x_char[i];
2967                                 }
2968                                 *lighting_level = F_LIT_STANDARD;
2969                                 break;
2970
2971                         case 'C':
2972                         case 'c':
2973                                 if (!visual_list)
2974                                 {
2975                                         for (FEAT_IDX i = 0; i < F_LIT_MAX; i++)
2976                                         {
2977                                                 attr_idx_feat[i] = f_ptr->x_attr[i];
2978                                                 char_idx_feat[i] = f_ptr->x_char[i];
2979                                         }
2980                                 }
2981                                 break;
2982
2983                         case 'P':
2984                         case 'p':
2985                                 if (!visual_list)
2986                                 {
2987                                         for (FEAT_IDX i = F_LIT_NS_BEGIN; i < F_LIT_MAX; i++)
2988                                         {
2989                                                 if (attr_idx_feat[i] || (!(char_idx_feat[i] & 0x80) && char_idx_feat[i])) f_ptr->x_attr[i] = attr_idx_feat[i];
2990                                                 if (char_idx_feat[i]) f_ptr->x_char[i] = char_idx_feat[i];
2991                                         }
2992                                 }
2993                                 break;
2994                         }
2995                         continue;
2996                 }
2997
2998                 switch (ch)
2999                 {
3000                 case ESCAPE:
3001                 {
3002                         flag = TRUE;
3003                         break;
3004                 }
3005
3006                 default:
3007                 {
3008                         browser_cursor(ch, &column, &grp_cur, grp_cnt, &feat_cur, feat_cnt);
3009                         break;
3010                 }
3011                 }
3012         }
3013
3014         C_KILL(feat_idx, max_f_idx, FEAT_IDX);
3015 }
3016
3017
3018 /*
3019  * List wanted monsters
3020  * @param creature_ptr プレーヤーへの参照ポインタ
3021  * @return なし
3022  */
3023 static void do_cmd_knowledge_bounty(player_type *creature_ptr)
3024 {
3025         FILE *fff;
3026         GAME_TEXT file_name[1024];
3027         fff = my_fopen_temp(file_name, 1024);
3028         if (!fff)
3029         {
3030                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
3031                 msg_print(NULL);
3032                 return;
3033         }
3034
3035         fprintf(fff, _("今日のターゲット : %s\n", "Today's target : %s\n"),
3036                 (creature_ptr->today_mon ? r_name + r_info[creature_ptr->today_mon].name : _("不明", "unknown")));
3037         fprintf(fff, "\n");
3038         fprintf(fff, _("賞金首リスト\n", "List of wanted monsters\n"));
3039         fprintf(fff, "----------------------------------------------\n");
3040
3041         bool listed = FALSE;
3042         for (int i = 0; i < MAX_BOUNTY; i++)
3043         {
3044                 if (current_world_ptr->bounty_r_idx[i] <= 10000)
3045                 {
3046                         fprintf(fff, "%s\n", r_name + r_info[current_world_ptr->bounty_r_idx[i]].name);
3047                         listed = TRUE;
3048                 }
3049         }
3050
3051         if (!listed)
3052         {
3053                 fprintf(fff, "\n%s\n", _("賞金首はもう残っていません。", "There are no more wanted monster."));
3054         }
3055
3056         my_fclose(fff);
3057         (void)show_file(creature_ptr, TRUE, file_name, _("賞金首の一覧", "Wanted monsters"), 0, 0);
3058         fd_kill(file_name);
3059 }
3060
3061 /*
3062  * List virtues & status
3063  */
3064 static void do_cmd_knowledge_virtues(player_type *creature_ptr)
3065 {
3066         FILE *fff;
3067         GAME_TEXT file_name[1024];
3068         fff = my_fopen_temp(file_name, 1024);
3069         if (!fff)
3070         {
3071                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
3072                 msg_print(NULL);
3073                 return;
3074         }
3075
3076         fprintf(fff, _("現在の属性 : %s\n\n", "Your alignment : %s\n\n"), your_alignment(creature_ptr));
3077         dump_virtues(creature_ptr, fff);
3078         my_fclose(fff);
3079         (void)show_file(creature_ptr, TRUE, file_name, _("八つの徳", "Virtues"), 0, 0);
3080         fd_kill(file_name);
3081 }
3082
3083 /*
3084  * Dungeon
3085  */
3086 static void do_cmd_knowledge_dungeon(player_type *creature_ptr)
3087 {
3088         FILE *fff;
3089         GAME_TEXT file_name[1024];
3090         fff = my_fopen_temp(file_name, 1024);
3091         if (!fff)
3092         {
3093                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
3094                 msg_print(NULL);
3095                 return;
3096         }
3097
3098         for (int i = 1; i < current_world_ptr->max_d_idx; i++)
3099         {
3100                 bool seiha = FALSE;
3101
3102                 if (!d_info[i].maxdepth) continue;
3103                 if (!max_dlv[i]) continue;
3104                 if (d_info[i].final_guardian)
3105                 {
3106                         if (!r_info[d_info[i].final_guardian].max_num) seiha = TRUE;
3107                 }
3108                 else if (max_dlv[i] == d_info[i].maxdepth) seiha = TRUE;
3109
3110                 fprintf(fff, _("%c%-12s :  %3d 階\n", "%c%-16s :  level %3d\n"), seiha ? '!' : ' ', d_name + d_info[i].name, (int)max_dlv[i]);
3111         }
3112
3113         my_fclose(fff);
3114         (void)show_file(creature_ptr, TRUE, file_name, _("今までに入ったダンジョン", "Dungeon"), 0, 0);
3115         fd_kill(file_name);
3116 }
3117
3118
3119 /*
3120 * List virtues & status
3121 *
3122 */
3123 static void do_cmd_knowledge_stat(player_type *creature_ptr)
3124 {
3125         FILE *fff;
3126         GAME_TEXT file_name[1024];
3127         fff = my_fopen_temp(file_name, 1024);
3128         if (!fff)
3129         {
3130                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
3131                 msg_print(NULL);
3132                 return;
3133         }
3134
3135         int percent = (int)(((long)creature_ptr->player_hp[PY_MAX_LEVEL - 1] * 200L) /
3136                 (2 * creature_ptr->hitdie +
3137                 ((PY_MAX_LEVEL - 1 + 3) * (creature_ptr->hitdie + 1))));
3138
3139         if (creature_ptr->knowledge & KNOW_HPRATE)
3140                 fprintf(fff, _("現在の体力ランク : %d/100\n\n", "Your current Life Rating is %d/100.\n\n"), percent);
3141         else fprintf(fff, _("現在の体力ランク : ???\n\n", "Your current Life Rating is ???.\n\n"));
3142
3143         fprintf(fff, _("能力の最大値\n\n", "Limits of maximum stats\n\n"));
3144         for (int v_nr = 0; v_nr < A_MAX; v_nr++)
3145         {
3146                 if ((creature_ptr->knowledge & KNOW_STAT) || creature_ptr->stat_max[v_nr] == creature_ptr->stat_max_max[v_nr]) fprintf(fff, "%s 18/%d\n", stat_names[v_nr], creature_ptr->stat_max_max[v_nr] - 18);
3147                 else fprintf(fff, "%s ???\n", stat_names[v_nr]);
3148         }
3149
3150         dump_yourself(creature_ptr, fff);
3151         my_fclose(fff);
3152         (void)show_file(creature_ptr, TRUE, file_name, _("自分に関する情報", "HP-rate & Max stat"), 0, 0);
3153         fd_kill(file_name);
3154 }
3155
3156
3157 /*
3158  * todo player_typeではなくQUEST_IDXを引数にすべきかもしれない
3159  * Print all active quests
3160  * @param creature_ptr プレーヤーへの参照ポインタ
3161  * @return なし
3162  */
3163 static void do_cmd_knowledge_quests_current(player_type *creature_ptr, FILE *fff)
3164 {
3165         char tmp_str[120];
3166         char rand_tmp_str[120] = "\0";
3167         GAME_TEXT name[MAX_NLEN];
3168         monster_race *r_ptr;
3169         int rand_level = 100;
3170         int total = 0;
3171
3172         fprintf(fff, _("《遂行中のクエスト》\n", "< Current Quest >\n"));
3173
3174         for (QUEST_IDX i = 1; i < max_q_idx; i++)
3175         {
3176                 bool is_print = quest[i].status == QUEST_STATUS_TAKEN;
3177                 is_print |= (quest[i].status == QUEST_STATUS_STAGE_COMPLETED) && (quest[i].type == QUEST_TYPE_TOWER);
3178                 is_print |= quest[i].status == QUEST_STATUS_COMPLETED;
3179                 if (!is_print)
3180                         continue;
3181
3182                 QUEST_IDX old_quest = creature_ptr->current_floor_ptr->inside_quest;
3183                 for (int j = 0; j < 10; j++)
3184                         quest_text[j][0] = '\0';
3185
3186                 quest_text_line = 0;
3187                 creature_ptr->current_floor_ptr->inside_quest = i;
3188                 init_flags = INIT_SHOW_TEXT;
3189                 process_dungeon_file(creature_ptr, "q_info.txt", 0, 0, 0, 0);
3190                 creature_ptr->current_floor_ptr->inside_quest = old_quest;
3191                 if (quest[i].flags & QUEST_FLAG_SILENT) continue;
3192
3193                 total++;
3194                 if (quest[i].type != QUEST_TYPE_RANDOM)
3195                 {
3196                         char note[80] = "\0";
3197
3198                         if (quest[i].status == QUEST_STATUS_TAKEN || quest[i].status == QUEST_STATUS_STAGE_COMPLETED)
3199                         {
3200                                 switch (quest[i].type)
3201                                 {
3202                                 case QUEST_TYPE_KILL_LEVEL:
3203                                 case QUEST_TYPE_KILL_ANY_LEVEL:
3204                                         r_ptr = &r_info[quest[i].r_idx];
3205                                         strcpy(name, r_name + r_ptr->name);
3206                                         if (quest[i].max_num > 1)
3207                                         {
3208 #ifdef JP
3209                                                 sprintf(note, " - %d 体の%sを倒す。(あと %d 体)",
3210                                                         (int)quest[i].max_num, name, (int)(quest[i].max_num - quest[i].cur_num));
3211 #else
3212                                                 plural_aux(name);
3213                                                 sprintf(note, " - kill %d %s, have killed %d.",
3214                                                         (int)quest[i].max_num, name, (int)quest[i].cur_num);
3215 #endif
3216                                         }
3217                                         else
3218                                                 sprintf(note, _(" - %sを倒す。", " - kill %s."), name);
3219                                         break;
3220
3221                                 case QUEST_TYPE_FIND_ARTIFACT:
3222                                         if (quest[i].k_idx)
3223                                         {
3224                                                 artifact_type *a_ptr = &a_info[quest[i].k_idx];
3225                                                 object_type forge;
3226                                                 object_type *q_ptr = &forge;
3227                                                 KIND_OBJECT_IDX k_idx = lookup_kind(a_ptr->tval, a_ptr->sval);
3228                                                 object_prep(q_ptr, k_idx);
3229                                                 q_ptr->name1 = quest[i].k_idx;
3230                                                 q_ptr->ident = IDENT_STORE;
3231                                                 object_desc(creature_ptr, name, q_ptr, OD_NAME_ONLY);
3232                                         }
3233                                         sprintf(note, _("\n   - %sを見つけ出す。", "\n   - Find %s."), name);
3234                                         break;
3235                                 case QUEST_TYPE_FIND_EXIT:
3236                                         sprintf(note, _(" - 出口に到達する。", " - Reach exit."));
3237                                         break;
3238
3239                                 case QUEST_TYPE_KILL_NUMBER:
3240 #ifdef JP
3241                                         sprintf(note, " - %d 体のモンスターを倒す。(あと %d 体)",
3242                                                 (int)quest[i].max_num, (int)(quest[i].max_num - quest[i].cur_num));
3243 #else
3244                                         sprintf(note, " - Kill %d monsters, have killed %d.",
3245                                                 (int)quest[i].max_num, (int)quest[i].cur_num);
3246 #endif
3247                                         break;
3248
3249                                 case QUEST_TYPE_KILL_ALL:
3250                                 case QUEST_TYPE_TOWER:
3251                                         sprintf(note, _(" - 全てのモンスターを倒す。", " - Kill all monsters."));
3252                                         break;
3253                                 }
3254                         }
3255
3256                         sprintf(tmp_str, _("  %s (危険度:%d階相当)%s\n", "  %s (Danger level: %d)%s\n"),
3257                                 quest[i].name, (int)quest[i].level, note);
3258                         fputs(tmp_str, fff);
3259                         if (quest[i].status == QUEST_STATUS_COMPLETED)
3260                         {
3261                                 sprintf(tmp_str, _("    クエスト達成 - まだ報酬を受けとってない。\n", "    Quest Completed - Unrewarded\n"));
3262                                 fputs(tmp_str, fff);
3263                                 continue;
3264                         }
3265
3266                         int k = 0;
3267                         while (quest_text[k][0] && k < 10)
3268                         {
3269                                 fprintf(fff, "    %s\n", quest_text[k]);
3270                                 k++;
3271                         }
3272
3273                         continue;
3274                 }
3275
3276                 if (quest[i].level >= rand_level)
3277                         continue;
3278
3279                 rand_level = quest[i].level;
3280                 if (max_dlv[DUNGEON_ANGBAND] < rand_level) continue;
3281
3282                 r_ptr = &r_info[quest[i].r_idx];
3283                 strcpy(name, r_name + r_ptr->name);
3284                 if (quest[i].max_num <= 1)
3285                 {
3286                         sprintf(rand_tmp_str, _("  %s (%d 階) - %sを倒す。\n", "  %s (Dungeon level: %d)\n  Kill %s.\n"),
3287                                 quest[i].name, (int)quest[i].level, name);
3288                         continue;
3289                 }
3290
3291 #ifdef JP
3292                 sprintf(rand_tmp_str, "  %s (%d 階) - %d 体の%sを倒す。(あと %d 体)\n",
3293                         quest[i].name, (int)quest[i].level,
3294                         (int)quest[i].max_num, name, (int)(quest[i].max_num - quest[i].cur_num));
3295 #else
3296                 plural_aux(name);
3297
3298                 sprintf(rand_tmp_str, "  %s (Dungeon level: %d)\n  Kill %d %s, have killed %d.\n",
3299                         quest[i].name, (int)quest[i].level,
3300                         (int)quest[i].max_num, name, (int)quest[i].cur_num);
3301 #endif
3302         }
3303
3304         if (rand_tmp_str[0]) fputs(rand_tmp_str, fff);
3305
3306         if (!total) fprintf(fff, _("  なし\n", "  Nothing.\n"));
3307 }
3308
3309
3310 static bool do_cmd_knowledge_quests_aux(player_type *player_ptr, FILE *fff, IDX q_idx)
3311 {
3312         char tmp_str[120];
3313         char playtime_str[16];
3314         quest_type* const q_ptr = &quest[q_idx];
3315
3316         floor_type *floor_ptr = player_ptr->current_floor_ptr;
3317         if (is_fixed_quest_idx(q_idx))
3318         {
3319                 IDX old_quest = floor_ptr->inside_quest;
3320                 floor_ptr->inside_quest = q_idx;
3321                 init_flags = INIT_NAME_ONLY;
3322                 process_dungeon_file(player_ptr, "q_info.txt", 0, 0, 0, 0);
3323                 floor_ptr->inside_quest = old_quest;
3324                 if (q_ptr->flags & QUEST_FLAG_SILENT) return FALSE;
3325         }
3326
3327         strnfmt(playtime_str, sizeof(playtime_str), "%02d:%02d:%02d",
3328                 q_ptr->comptime / (60 * 60), (q_ptr->comptime / 60) % 60, q_ptr->comptime % 60);
3329
3330         if (is_fixed_quest_idx(q_idx) || (q_ptr->r_idx == 0))
3331         {
3332                 sprintf(tmp_str,
3333                         _("  %-35s (危険度:%3d階相当) - レベル%2d - %s\n",
3334                                 "  %-35s (Danger  level: %3d) - level %2d - %s\n"),
3335                         q_ptr->name, (int)q_ptr->level, q_ptr->complev, playtime_str);
3336                 fputs(tmp_str, fff);
3337                 return TRUE;
3338         }
3339
3340         if (q_ptr->complev == 0)
3341         {
3342                 sprintf(tmp_str,
3343                         _("  %-35s (%3d階)            -   不戦勝 - %s\n",
3344                                 "  %-35s (Dungeon level: %3d) - Unearned - %s\n"),
3345                         r_name + r_info[q_ptr->r_idx].name,
3346                         (int)q_ptr->level, playtime_str);
3347                 fputs(tmp_str, fff);
3348                 return TRUE;
3349         }
3350
3351         sprintf(tmp_str,
3352                 _("  %-35s (%3d階)            - レベル%2d - %s\n",
3353                         "  %-35s (Dungeon level: %3d) - level %2d - %s\n"),
3354                 r_name + r_info[q_ptr->r_idx].name,
3355                 (int)q_ptr->level,
3356                 q_ptr->complev,
3357                 playtime_str);
3358         fputs(tmp_str, fff);
3359         return TRUE;
3360 }
3361
3362
3363 /*
3364  * Print all finished quests
3365  * @param creature_ptr プレーヤーへの参照ポインタ
3366  * @param fff セーブファイル (展開済?)
3367  * @param quest_num[] 受注したことのあるクエスト群
3368  * @return なし
3369  */
3370 void do_cmd_knowledge_quests_completed(player_type *creature_ptr, FILE *fff, QUEST_IDX quest_num[])
3371 {
3372         fprintf(fff, _("《達成したクエスト》\n", "< Completed Quest >\n"));
3373         QUEST_IDX total = 0;
3374         for (QUEST_IDX i = 1; i < max_q_idx; i++)
3375         {
3376                 QUEST_IDX q_idx = quest_num[i];
3377                 quest_type* const q_ptr = &quest[q_idx];
3378
3379                 if (q_ptr->status == QUEST_STATUS_FINISHED && do_cmd_knowledge_quests_aux(creature_ptr, fff, q_idx))
3380                 {
3381                         ++total;
3382                 }
3383         }
3384
3385         if (!total) fprintf(fff, _("  なし\n", "  Nothing.\n"));
3386 }
3387
3388
3389 /*
3390  * Print all failed quests
3391  * @param creature_ptr プレーヤーへの参照ポインタ
3392  * @param fff セーブファイル (展開済?)
3393  * @param quest_num[] 受注したことのあるクエスト群
3394  * @return なし
3395 */
3396 void do_cmd_knowledge_quests_failed(player_type *creature_ptr, FILE *fff, QUEST_IDX quest_num[])
3397 {
3398         fprintf(fff, _("《失敗したクエスト》\n", "< Failed Quest >\n"));
3399         QUEST_IDX total = 0;
3400         for (QUEST_IDX i = 1; i < max_q_idx; i++)
3401         {
3402                 QUEST_IDX q_idx = quest_num[i];
3403                 quest_type* const q_ptr = &quest[q_idx];
3404
3405                 if (((q_ptr->status == QUEST_STATUS_FAILED_DONE) || (q_ptr->status == QUEST_STATUS_FAILED)) &&
3406                         do_cmd_knowledge_quests_aux(creature_ptr, fff, q_idx))
3407                 {
3408                         ++total;
3409                 }
3410         }
3411
3412         if (!total) fprintf(fff, _("  なし\n", "  Nothing.\n"));
3413 }
3414
3415
3416 /*
3417  * Print all random quests
3418  */
3419 static void do_cmd_knowledge_quests_wiz_random(FILE *fff)
3420 {
3421         fprintf(fff, _("《残りのランダムクエスト》\n", "< Remaining Random Quest >\n"));
3422         GAME_TEXT tmp_str[120];
3423         QUEST_IDX total = 0;
3424         for (QUEST_IDX i = 1; i < max_q_idx; i++)
3425         {
3426                 if (quest[i].flags & QUEST_FLAG_SILENT) continue;
3427
3428                 if ((quest[i].type == QUEST_TYPE_RANDOM) && (quest[i].status == QUEST_STATUS_TAKEN))
3429                 {
3430                         total++;
3431                         sprintf(tmp_str, _("  %s (%d階, %s)\n", "  %s (%d, %s)\n"),
3432                                 quest[i].name, (int)quest[i].level, r_name + r_info[quest[i].r_idx].name);
3433                         fputs(tmp_str, fff);
3434                 }
3435         }
3436
3437         if (!total) fprintf(fff, _("  なし\n", "  Nothing.\n"));
3438 }
3439
3440 /*
3441  * Print quest status of all active quests
3442  * @param creature_ptr プレーヤーへの参照ポインタ
3443  * @return なし
3444  */
3445 static void do_cmd_knowledge_quests(player_type *creature_ptr)
3446 {
3447         FILE *fff;
3448         GAME_TEXT file_name[1024];
3449         fff = my_fopen_temp(file_name, 1024);
3450         if (!fff)
3451         {
3452                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
3453                 msg_print(NULL);
3454                 return;
3455         }
3456
3457         IDX *quest_num;
3458         C_MAKE(quest_num, max_q_idx, QUEST_IDX);
3459
3460         for (IDX i = 1; i < max_q_idx; i++)
3461                 quest_num[i] = i;
3462
3463         int dummy;
3464         ang_sort(quest_num, &dummy, max_q_idx, ang_sort_comp_quest_num, ang_sort_swap_quest_num);
3465
3466         do_cmd_knowledge_quests_current(creature_ptr, fff);
3467         fputc('\n', fff);
3468         do_cmd_knowledge_quests_completed(creature_ptr, fff, quest_num);
3469         fputc('\n', fff);
3470         do_cmd_knowledge_quests_failed(creature_ptr, fff, quest_num);
3471         if (current_world_ptr->wizard)
3472         {
3473                 fputc('\n', fff);
3474                 do_cmd_knowledge_quests_wiz_random(fff);
3475         }
3476
3477         my_fclose(fff);
3478         (void)show_file(creature_ptr, TRUE, file_name, _("クエスト達成状況", "Quest status"), 0, 0);
3479         fd_kill(file_name);
3480         C_KILL(quest_num, max_q_idx, QUEST_IDX);
3481 }
3482
3483
3484 /*
3485  * List my home
3486  * @param player_ptr プレーヤーへの参照ポインタ
3487  * @return なし
3488  */
3489 static void do_cmd_knowledge_home(player_type *player_ptr)
3490 {
3491         process_dungeon_file(player_ptr, "w_info.txt", 0, 0, current_world_ptr->max_wild_y, current_world_ptr->max_wild_x);
3492
3493         /* Open a new file */
3494         FILE *fff;
3495         GAME_TEXT file_name[1024];
3496         fff = my_fopen_temp(file_name, 1024);
3497         if (!fff)
3498         {
3499                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
3500                 msg_print(NULL);
3501                 return;
3502         }
3503
3504         store_type *store_ptr;
3505         store_ptr = &town_info[1].store[STORE_HOME];
3506
3507         if (store_ptr->stock_num)
3508         {
3509 #ifdef JP
3510                 TERM_LEN x = 1;
3511 #endif
3512                 fprintf(fff, _("  [ 我が家のアイテム ]\n", "  [Home Inventory]\n"));
3513                 concptr paren = ")";
3514                 GAME_TEXT o_name[MAX_NLEN];
3515                 for (int i = 0; i < store_ptr->stock_num; i++)
3516                 {
3517 #ifdef JP
3518                         if ((i % 12) == 0) fprintf(fff, "\n ( %d ページ )\n", x++);
3519                         object_desc(player_ptr, o_name, &store_ptr->stock[i], 0);
3520                         if (strlen(o_name) <= 80 - 3)
3521                         {
3522                                 fprintf(fff, "%c%s %s\n", I2A(i % 12), paren, o_name);
3523                         }
3524                         else
3525                         {
3526                                 int n;
3527                                 char *t;
3528                                 for (n = 0, t = o_name; n < 80 - 3; n++, t++)
3529                                         if (iskanji(*t)) { t++; n++; }
3530                                 if (n == 81 - 3) n = 79 - 3; /* 最後が漢字半分 */
3531
3532                                 fprintf(fff, "%c%s %.*s\n", I2A(i % 12), paren, n, o_name);
3533                                 fprintf(fff, "   %.77s\n", o_name + n);
3534                         }
3535 #else
3536                         object_desc(player_ptr, o_name, &store_ptr->stock[i], 0);
3537                         fprintf(fff, "%c%s %s\n", I2A(i % 12), paren, o_name);
3538 #endif
3539                 }
3540
3541                 fprintf(fff, "\n\n");
3542         }
3543
3544         my_fclose(fff);
3545         (void)show_file(player_ptr, TRUE, file_name, _("我が家のアイテム", "Home Inventory"), 0, 0);
3546         fd_kill(file_name);
3547 }
3548
3549
3550 /*
3551  * Check the status of "autopick"
3552  */
3553 static void do_cmd_knowledge_autopick(player_type *creature_ptr)
3554 {
3555         /* Open a new file */
3556         FILE *fff;
3557         GAME_TEXT file_name[1024];
3558         fff = my_fopen_temp(file_name, 1024);
3559         if (!fff)
3560         {
3561                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
3562                 msg_print(NULL);
3563                 return;
3564         }
3565
3566         if (!max_autopick)
3567         {
3568                 fprintf(fff, _("自動破壊/拾いには何も登録されていません。", "No preference for auto picker/destroyer."));
3569         }
3570         else
3571         {
3572                 fprintf(fff, _("   自動拾い/破壊には現在 %d行登録されています。\n\n",
3573                         "   There are %d registered lines for auto picker/destroyer.\n\n"), max_autopick);
3574         }
3575
3576         for (int k = 0; k < max_autopick; k++)
3577         {
3578                 concptr tmp;
3579                 byte act = autopick_list[k].action;
3580                 if (act & DONT_AUTOPICK)
3581                 {
3582                         tmp = _("放置", "Leave");
3583                 }
3584                 else if (act & DO_AUTODESTROY)
3585                 {
3586                         tmp = _("破壊", "Destroy");
3587                 }
3588                 else if (act & DO_AUTOPICK)
3589                 {
3590                         tmp = _("拾う", "Pickup");
3591                 }
3592                 else
3593                 {
3594                         tmp = _("確認", "Query");
3595                 }
3596
3597                 if (act & DO_DISPLAY)
3598                         fprintf(fff, "%11s", format("[%s]", tmp));
3599                 else
3600                         fprintf(fff, "%11s", format("(%s)", tmp));
3601
3602                 tmp = autopick_line_from_entry(&autopick_list[k]);
3603                 fprintf(fff, " %s", tmp);
3604                 string_free(tmp);
3605                 fprintf(fff, "\n");
3606         }
3607
3608         my_fclose(fff);
3609
3610         (void)show_file(creature_ptr, TRUE, file_name, _("自動拾い/破壊 設定リスト", "Auto-picker/Destroyer"), 0, 0);
3611         fd_kill(file_name);
3612 }
3613
3614
3615 /*
3616  * Interact with "knowledge"
3617  */
3618 void do_cmd_knowledge(player_type *creature_ptr)
3619 {
3620         int i, p = 0;
3621         bool need_redraw = FALSE;
3622         FILE_TYPE(FILE_TYPE_TEXT);
3623         screen_save();
3624         while (TRUE)
3625         {
3626                 Term_clear();
3627                 prt(format(_("%d/2 ページ", "page %d/2"), (p + 1)), 2, 65);
3628                 prt(_("現在の知識を確認する", "Display current knowledge"), 3, 0);
3629
3630 #ifdef JP
3631                 if (p == 0)
3632                 {
3633                         prt("(1) 既知の伝説のアイテム                 の一覧", 6, 5);
3634                         prt("(2) 既知のアイテム                       の一覧", 7, 5);
3635                         prt("(3) 既知の生きているユニーク・モンスター の一覧", 8, 5);
3636                         prt("(4) 既知のモンスター                     の一覧", 9, 5);
3637                         prt("(5) 倒した敵の数                         の一覧", 10, 5);
3638                         if (!vanilla_town) prt("(6) 賞金首                               の一覧", 11, 5);
3639                         prt("(7) 現在のペット                         の一覧", 12, 5);
3640                         prt("(8) 我が家のアイテム                     の一覧", 13, 5);
3641                         prt("(9) *鑑定*済み装備の耐性                 の一覧", 14, 5);
3642                         prt("(0) 地形の表示文字/タイル                の一覧", 15, 5);
3643                 }
3644                 else
3645                 {
3646                         prt("(a) 自分に関する情報                     の一覧", 6, 5);
3647                         prt("(b) 突然変異                             の一覧", 7, 5);
3648                         prt("(c) 武器の経験値                         の一覧", 8, 5);
3649                         prt("(d) 魔法の経験値                         の一覧", 9, 5);
3650                         prt("(e) 技能の経験値                         の一覧", 10, 5);
3651                         prt("(f) プレイヤーの徳                       の一覧", 11, 5);
3652                         prt("(g) 入ったダンジョン                     の一覧", 12, 5);
3653                         prt("(h) 実行中のクエスト                     の一覧", 13, 5);
3654                         prt("(i) 現在の自動拾い/破壊設定              の一覧", 14, 5);
3655                 }
3656 #else
3657                 if (p == 0)
3658                 {
3659                         prt("(1) Display known artifacts", 6, 5);
3660                         prt("(2) Display known objects", 7, 5);
3661                         prt("(3) Display remaining uniques", 8, 5);
3662                         prt("(4) Display known monster", 9, 5);
3663                         prt("(5) Display kill count", 10, 5);
3664                         if (!vanilla_town) prt("(6) Display wanted monsters", 11, 5);
3665                         prt("(7) Display current pets", 12, 5);
3666                         prt("(8) Display home inventory", 13, 5);
3667                         prt("(9) Display *identified* equip.", 14, 5);
3668                         prt("(0) Display terrain symbols.", 15, 5);
3669                 }
3670                 else
3671                 {
3672                         prt("(a) Display about yourself", 6, 5);
3673                         prt("(b) Display mutations", 7, 5);
3674                         prt("(c) Display weapon proficiency", 8, 5);
3675                         prt("(d) Display spell proficiency", 9, 5);
3676                         prt("(e) Display misc. proficiency", 10, 5);
3677                         prt("(f) Display virtues", 11, 5);
3678                         prt("(g) Display dungeons", 12, 5);
3679                         prt("(h) Display current quests", 13, 5);
3680                         prt("(i) Display auto pick/destroy", 14, 5);
3681                 }
3682 #endif
3683                 prt(_("-続く-", "-more-"), 17, 8);
3684                 prt(_("ESC) 抜ける", "ESC) Exit menu"), 21, 1);
3685                 prt(_("SPACE) 次ページ", "SPACE) Next page"), 21, 30);
3686                 prt(_("コマンド:", "Command: "), 20, 0);
3687                 i = inkey();
3688
3689                 if (i == ESCAPE) break;
3690                 switch (i)
3691                 {
3692                 case ' ': /* Page change */
3693                 case '-':
3694                         p = 1 - p;
3695                         break;
3696                 case '1': /* Artifacts */
3697                         do_cmd_knowledge_artifacts(creature_ptr);
3698                         break;
3699                 case '2': /* Objects */
3700                         do_cmd_knowledge_objects(creature_ptr, &need_redraw, FALSE, -1);
3701                         break;
3702                 case '3': /* Uniques */
3703                         do_cmd_knowledge_uniques(creature_ptr);
3704                         break;
3705                 case '4': /* Monsters */
3706                         do_cmd_knowledge_monsters(creature_ptr, &need_redraw, FALSE, -1);
3707                         break;
3708                 case '5': /* Kill count  */
3709                         do_cmd_knowledge_kill_count(creature_ptr);
3710                         break;
3711                 case '6': /* wanted */
3712                         if (!vanilla_town) do_cmd_knowledge_bounty(creature_ptr);
3713                         break;
3714                 case '7': /* Pets */
3715                         do_cmd_knowledge_pets(creature_ptr);
3716                         break;
3717                 case '8': /* Home */
3718                         do_cmd_knowledge_home(creature_ptr);
3719                         break;
3720                 case '9': /* Resist list */
3721                         do_cmd_knowledge_inven(creature_ptr);
3722                         break;
3723                 case '0': /* Feature list */
3724                 {
3725                         IDX lighting_level = F_LIT_STANDARD;
3726                         do_cmd_knowledge_features(&need_redraw, FALSE, -1, &lighting_level);
3727                 }
3728                 break;
3729                 /* Next page */
3730                 case 'a': /* Max stat */
3731                         do_cmd_knowledge_stat(creature_ptr);
3732                         break;
3733                 case 'b': /* Mutations */
3734                         do_cmd_knowledge_mutations(creature_ptr);
3735                         break;
3736                 case 'c': /* weapon-exp */
3737                         do_cmd_knowledge_weapon_exp(creature_ptr);
3738                         break;
3739                 case 'd': /* spell-exp */
3740                         do_cmd_knowledge_spell_exp(creature_ptr);
3741                         break;
3742                 case 'e': /* skill-exp */
3743                         do_cmd_knowledge_skill_exp(creature_ptr);
3744                         break;
3745                 case 'f': /* Virtues */
3746                         do_cmd_knowledge_virtues(creature_ptr);
3747                         break;
3748                 case 'g': /* Dungeon */
3749                         do_cmd_knowledge_dungeon(creature_ptr);
3750                         break;
3751                 case 'h': /* Quests */
3752                         do_cmd_knowledge_quests(creature_ptr);
3753                         break;
3754                 case 'i': /* Autopick */
3755                         do_cmd_knowledge_autopick(creature_ptr);
3756                         break;
3757                 default: /* Unknown option */
3758                         bell();
3759                 }
3760
3761                 msg_erase();
3762         }
3763
3764         screen_load();
3765         if (need_redraw) do_cmd_redraw(creature_ptr);
3766 }
3767
3768
3769 /*
3770  * Check on the status of an active quest
3771  * @param creature_ptr プレーヤーへの参照ポインタ
3772  * @return なし
3773  */
3774 void do_cmd_checkquest(player_type *creature_ptr)
3775 {
3776         FILE_TYPE(FILE_TYPE_TEXT);
3777         screen_save();
3778         do_cmd_knowledge_quests(creature_ptr);
3779         screen_load();
3780 }
3781
3782
3783 /*
3784  * Display the time and date
3785  * @param creature_ptr プレーヤーへの参照ポインタ
3786  * @return なし
3787  */
3788 void do_cmd_time(player_type *creature_ptr)
3789 {
3790         int day, hour, min;
3791         extract_day_hour_min(creature_ptr, &day, &hour, &min);
3792
3793         char desc[1024];
3794         strcpy(desc, _("変な時刻だ。", "It is a strange time."));
3795
3796         char day_buf[10];
3797         if (day < MAX_DAYS) sprintf(day_buf, "%d", day);
3798         else strcpy(day_buf, "*****");
3799
3800         msg_format(_("%s日目, 時刻は%d:%02d %sです。", "This is day %s. The time is %d:%02d %s."),
3801                 day_buf, (hour % 12 == 0) ? 12 : (hour % 12), min, (hour < 12) ? "AM" : "PM");
3802
3803         char buf[1024];
3804         if (!randint0(10) || creature_ptr->image)
3805         {
3806                 path_build(buf, sizeof(buf), ANGBAND_DIR_FILE, _("timefun_j.txt", "timefun.txt"));
3807         }
3808         else
3809         {
3810                 path_build(buf, sizeof(buf), ANGBAND_DIR_FILE, _("timenorm_j.txt", "timenorm.txt"));
3811         }
3812
3813         FILE *fff;
3814         fff = my_fopen(buf, "rt");
3815
3816         if (!fff) return;
3817
3818         int full = hour * 100 + min;
3819         int start = 9999;
3820         int end = -9999;
3821         int num = 0;
3822         while (!my_fgets(fff, buf, sizeof(buf)))
3823         {
3824                 if (!buf[0] || (buf[0] == '#')) continue;
3825                 if (buf[1] != ':') continue;
3826
3827                 if (buf[0] == 'S')
3828                 {
3829                         start = atoi(buf + 2);
3830                         end = start + 59;
3831                         continue;
3832                 }
3833
3834                 if (buf[0] == 'E')
3835                 {
3836                         end = atoi(buf + 2);
3837                         continue;
3838                 }
3839
3840                 if ((start > full) || (full > end)) continue;
3841
3842                 if (buf[0] == 'D')
3843                 {
3844                         num++;
3845                         if (!randint0(num)) strcpy(desc, buf + 2);
3846
3847                         continue;
3848                 }
3849         }
3850
3851         msg_print(desc);
3852         my_fclose(fff);
3853 }