OSDN Git Service

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