OSDN Git Service

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