OSDN Git Service

[Refactor] #40236 Separated write-diary.c/h from cmd-dump.c/h
[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  * -Mogami-
16  * remove_auto_dump(orig_file, mark)
17  *     Remove the old automatic dump of type "mark".
18  * auto_dump_printf(fmt, ...)
19  *     Dump a formatted string using fprintf().
20  * open_auto_dump(buf, mark)
21  *     Open a file, remove old dump, and add new header.
22  * close_auto_dump(void)
23  *     Add a footer, and close the file.
24  *    The dump commands of original Angband simply add new lines to
25  * existing files; these files will become bigger and bigger unless
26  * an user deletes some or all of these files by hand at some
27  * point.
28  *     These three functions automatically delete old dumped lines
29  * before adding new ones.  Since there are various kinds of automatic
30  * dumps in a single file, we add a header and a footer with a type
31  * name for every automatic dump, and kill old lines only when the
32  * lines have the correct type of header and footer.
33  *     We need to be quite paranoid about correctness; the user might
34  * (mistakenly) edit the file by hand, and see all their work come
35  * to nothing on the next auto dump otherwise.  The current code only
36  * detects changes by noting inconsistencies between the actual number
37  * of lines and the number written in the footer.  Note that this will
38  * not catch single-line edits.
39  * </pre>
40  */
41
42 #include "angband.h"
43 #include "cmd-dump.h"
44 #include "term.h"
45 #include "core.h"
46 #include "core/show-file.h"
47 #include "io/read-pref-file.h"
48 #include "io/write-diary.h"
49 #include "chuukei.h"
50
51 #include "autopick.h"
52
53 #include "inet.h"
54 #include "birth.h"
55 #include "dungeon.h"
56 #include "world.h"
57 #include "view/display-player.h"
58 #include "player/process-name.h"
59 #include "player-effects.h"
60 #include "player-status.h"
61 #include "player-skill.h"
62 #include "player-personality.h"
63 #include "sort.h"
64 #include "mutation.h"
65 #include "quest.h"
66 #include "store.h"
67 #include "artifact.h"
68 #include "avatar.h"
69 #include "object-flavor.h"
70 #include "object-hook.h"
71 #include "monster.h"
72 #include "monster-status.h"
73 #include "view-mainwindow.h"
74 #include "dungeon-file.h"
75 #include "io/interpret-pref-file.h"
76 #include "files.h"
77 #include "spells.h"
78 #include "objectkind.h"
79 #include "floor-town.h"
80 #include "view-mainwindow.h" // 暫定。後で消す
81
82 #include "english.h"
83
84  // Mark strings for auto dump
85 static char auto_dump_header[] = "# vvvvvvv== %s ==vvvvvvv";
86 static char auto_dump_footer[] = "# ^^^^^^^== %s ==^^^^^^^";
87
88 // Variables for auto dump
89 static FILE *auto_dump_stream;
90 static concptr auto_dump_mark;
91 static int auto_dump_line_num;
92
93 static void do_cmd_knowledge_monsters(player_type *creature_ptr, bool *need_redraw, bool visual_only, IDX direct_r_idx);
94 static void do_cmd_knowledge_objects(player_type *creature_ptr, bool *need_redraw, bool visual_only, IDX direct_k_idx);
95 static void do_cmd_knowledge_features(bool *need_redraw, bool visual_only, IDX direct_f_idx, IDX *lighting_level);
96
97 // Clipboard variables for copy&paste in visual mode
98 static TERM_COLOR attr_idx = 0;
99 static SYMBOL_CODE char_idx = 0;
100
101 /* Hack -- for feature lighting */
102 static TERM_COLOR attr_idx_feat[F_LIT_MAX];
103 static SYMBOL_CODE char_idx_feat[F_LIT_MAX];
104
105 // Encode the screen colors
106 static char hack[17] = "dwsorgbuDWvyRGBU";
107
108 /*!
109  * @brief prf出力内容を消去する /
110  * Remove old lines automatically generated before.
111  * @param orig_file 消去を行うファイル名
112  */
113 static void remove_auto_dump(concptr orig_file)
114 {
115         FILE *tmp_fff, *orig_fff;
116
117         char tmp_file[1024];
118         char buf[1024];
119         bool between_mark = FALSE;
120         bool changed = FALSE;
121         int line_num = 0;
122         long header_location = 0;
123         char header_mark_str[80];
124         char footer_mark_str[80];
125         size_t mark_len;
126
127         /* Prepare a header/footer mark string */
128         sprintf(header_mark_str, auto_dump_header, auto_dump_mark);
129         sprintf(footer_mark_str, auto_dump_footer, auto_dump_mark);
130
131         mark_len = strlen(footer_mark_str);
132
133         /* Open an old dump file in read-only mode */
134         orig_fff = my_fopen(orig_file, "r");
135
136         /* If original file does not exist, nothing to do */
137         if (!orig_fff) return;
138
139         /* Open a new (temporary) file */
140         tmp_fff = my_fopen_temp(tmp_file, 1024);
141
142         if (!tmp_fff)
143         {
144                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), tmp_file);
145                 msg_print(NULL);
146                 return;
147         }
148
149         /* Loop for every line */
150         while (TRUE)
151         {
152                 /* Read a line */
153                 if (my_fgets(orig_fff, buf, sizeof(buf)))
154                 {
155                         /* Read error: Assume End of File */
156
157                         /*
158                          * Was looking for the footer, but not found.
159                          *
160                          * Since automatic dump might be edited by hand,
161                          * it's dangerous to kill these lines.
162                          * Seek back to the next line of the (pseudo) header,
163                          * and read again.
164                          */
165                         if (between_mark)
166                         {
167                                 fseek(orig_fff, header_location, SEEK_SET);
168                                 between_mark = FALSE;
169                                 continue;
170                         }
171
172                         /* Success -- End the loop */
173                         else
174                         {
175                                 break;
176                         }
177                 }
178
179                 /* We are looking for the header mark of automatic dump */
180                 if (!between_mark)
181                 {
182                         /* Is this line a header? */
183                         if (!strcmp(buf, header_mark_str))
184                         {
185                                 /* Memorise seek point of this line */
186                                 header_location = ftell(orig_fff);
187
188                                 /* Initialize counter for number of lines */
189                                 line_num = 0;
190
191                                 /* Look for the footer from now */
192                                 between_mark = TRUE;
193
194                                 /* There are some changes */
195                                 changed = TRUE;
196                         }
197
198                         /* Not a header */
199                         else
200                         {
201                                 /* Copy orginally lines */
202                                 fprintf(tmp_fff, "%s\n", buf);
203                         }
204
205                         continue;
206                 }
207
208                 /* todo 処理よりもコメントが邪魔でif文を反転できない*/
209                 /* We are looking for the footer mark of automatic dump */
210                 /* Is this line a footer? */
211                 if (!strncmp(buf, footer_mark_str, mark_len))
212                 {
213                         int tmp;
214
215                         /*
216                          * Compare the number of lines
217                          *
218                          * If there is an inconsistency between
219                          * actual number of lines and the
220                          * number here, the automatic dump
221                          * might be edited by hand.  So it's
222                          * dangerous to kill these lines.
223                          * Seek back to the next line of the
224                          * (pseudo) header, and read again.
225                          */
226                         if (!sscanf(buf + mark_len, " (%d)", &tmp)
227                                 || tmp != line_num)
228                         {
229                                 fseek(orig_fff, header_location, SEEK_SET);
230                         }
231
232                         /* Look for another header */
233                         between_mark = FALSE;
234                         continue;
235                 }
236
237                 /* Not a footer */
238                 /* Ignore old line, and count number of lines */
239                 line_num++;
240         }
241
242         /* Close files */
243         my_fclose(orig_fff);
244         my_fclose(tmp_fff);
245
246         /* If there are some changes, overwrite the original file with new one */
247         if (changed)
248         {
249                 /* Copy contents of temporary file */
250                 tmp_fff = my_fopen(tmp_file, "r");
251                 orig_fff = my_fopen(orig_file, "w");
252
253                 while (!my_fgets(tmp_fff, buf, sizeof(buf)))
254                         fprintf(orig_fff, "%s\n", buf);
255
256                 my_fclose(orig_fff);
257                 my_fclose(tmp_fff);
258         }
259
260         fd_kill(tmp_file);
261 }
262
263
264 /*!
265  * @brief prfファイルのフォーマットに従った内容を出力する /
266  * Dump a formatted line, using "vstrnfmt()".
267  * @param fmt 出力内容
268  */
269 static void auto_dump_printf(concptr fmt, ...)
270 {
271         concptr p;
272         va_list vp;
273
274         char buf[1024];
275
276         /* Begin the Varargs Stuff */
277         va_start(vp, fmt);
278
279         /* Format the args, save the length */
280         (void)vstrnfmt(buf, sizeof(buf), fmt, vp);
281
282         /* End the Varargs Stuff */
283         va_end(vp);
284
285         /* Count number of lines */
286         for (p = buf; *p; p++)
287         {
288                 if (*p == '\n') auto_dump_line_num++;
289         }
290
291         /* Dump it */
292         fprintf(auto_dump_stream, "%s", buf);
293 }
294
295
296 /*!
297  * @brief prfファイルをファイルオープンする /
298  * Open file to append auto dump.
299  * @param buf ファイル名
300  * @param mark 出力するヘッダマーク
301  * @return ファイルポインタを取得できたらTRUEを返す
302  */
303 static bool open_auto_dump(concptr buf, concptr mark)
304 {
305         char header_mark_str[80];
306
307         /* Save the mark string */
308         auto_dump_mark = mark;
309
310         /* Prepare a header mark string */
311         sprintf(header_mark_str, auto_dump_header, auto_dump_mark);
312
313         /* Remove old macro dumps */
314         remove_auto_dump(buf);
315
316         /* Append to the file */
317         auto_dump_stream = my_fopen(buf, "a");
318
319         /* Failure */
320         if (!auto_dump_stream)
321         {
322                 msg_format(_("%s を開くことができませんでした。", "Failed to open %s."), buf);
323                 msg_print(NULL);
324
325                 /* Failed */
326                 return FALSE;
327         }
328
329         /* Start dumping */
330         fprintf(auto_dump_stream, "%s\n", header_mark_str);
331
332         /* Initialize counter */
333         auto_dump_line_num = 0;
334
335         auto_dump_printf(_("# *警告!!* 以降の行は自動生成されたものです。\n",
336                 "# *Warning!*  The lines below are an automatic dump.\n"));
337         auto_dump_printf(_("# *警告!!* 後で自動的に削除されるので編集しないでください。\n",
338                 "# Don't edit them; changes will be deleted and replaced automatically.\n"));
339         return TRUE;
340 }
341
342 /*!
343  * @brief prfファイルをファイルクローズする /
344  * Append foot part and close auto dump.
345  * @return なし
346  */
347 static void close_auto_dump(void)
348 {
349         char footer_mark_str[80];
350
351         /* Prepare a footer mark string */
352         sprintf(footer_mark_str, auto_dump_footer, auto_dump_mark);
353
354         auto_dump_printf(_("# *警告!!* 以降の行は自動生成されたものです。\n",
355                 "# *Warning!*  The lines below are an automatic dump.\n"));
356         auto_dump_printf(_("# *警告!!* 後で自動的に削除されるので編集しないでください。\n",
357                 "# Don't edit them; changes will be deleted and replaced automatically.\n"));
358         /* End of dump */
359         fprintf(auto_dump_stream, "%s (%d)\n", footer_mark_str, auto_dump_line_num);
360
361         my_fclose(auto_dump_stream);
362 }
363
364
365 #ifdef JP
366 #else
367 /*!
368  * @brief Return suffix of ordinal number
369  * @param num number
370  * @return pointer of suffix string.
371  */
372 concptr get_ordinal_number_suffix(int num)
373 {
374         num = ABS(num) % 100;
375         switch (num % 10)
376         {
377         case 1:
378                 return (num == 11) ? "th" : "st";
379         case 2:
380                 return (num == 12) ? "th" : "nd";
381         case 3:
382                 return (num == 13) ? "th" : "rd";
383         default:
384                 return "th";
385         }
386 }
387 #endif
388
389 #define MAX_SUBTITLE (sizeof(subtitle)/sizeof(subtitle[0]))
390
391 /*!
392  * @brief 日記のタイトル表記と内容出力 /
393  * @return なし
394  * @details
395  * 日記のタイトルは本関数の subtitle ローカル変数で定義されている。
396  */
397 static void display_diary(player_type *creature_ptr)
398 {
399         char diary_title[256];
400         GAME_TEXT file_name[MAX_NLEN];
401         char buf[1024];
402         char tmp[80];
403 #ifdef JP
404         static const char subtitle[][30] = {
405                 "最強の肉体を求めて",
406                 "人生それははかない",
407                 "明日に向かって",
408                 "棚からぼたもち",
409                 "あとの祭り",
410                 "それはいい考えだ",
411                 "何とでも言え",
412                 "兎にも角にも",
413                 "ウソだけど",
414                 "もはやこれまで",
415                 "なんでこうなるの",
416                 "それは無理だ",
417                 "倒すべき敵はゲ○ツ",
418                 "ん~?聞こえんなぁ",
419                 "オレの名を言ってみろ",
420                 "頭が変になっちゃった",
421                 "互換しません",
422                 "せっかくだから",
423                 "まだまだ甘いね",
424                 "むごいむごすぎる",
425                 "こんなもんじゃない",
426                 "だめだこりゃ",
427                 "次いってみよう",
428                 "ちょっとだけよ",
429                 "哀しき冒険者",
430                 "野望の果て",
431                 "無限地獄",
432                 "神に喧嘩を売る者",
433                 "未知の世界へ",
434                 "最高の頭脳を求めて"
435         };
436 #else
437         static const char subtitle[][51] = {
438                 "Quest of The World's Toughest Body",
439                 "Attack is the best form of defence.",
440                 "Might is right.",
441                 "An unexpected windfall",
442                 "A drowning man will catch at a straw",
443                 "Don't count your chickens before they are hatched.",
444                 "It is no use crying over spilt milk.",
445                 "Seeing is believing.",
446                 "Strike the iron while it is hot.",
447                 "I don't care what follows.",
448                 "To dig a well to put out a house on fire.",
449                 "Tomorrow is another day.",
450                 "Easy come, easy go.",
451                 "The more haste, the less speed.",
452                 "Where there is life, there is hope.",
453                 "There is no royal road to *WINNER*.",
454                 "Danger past, God forgotten.",
455                 "The best thing to do now is to run away.",
456                 "Life is but an empty dream.",
457                 "Dead men tell no tales.",
458                 "A book that remains shut is but a block.",
459                 "Misfortunes never come singly.",
460                 "A little knowledge is a dangerous thing.",
461                 "History repeats itself.",
462                 "*WINNER* was not built in a day.",
463                 "Ignorance is bliss.",
464                 "To lose is to win?",
465                 "No medicine can cure folly.",
466                 "All good things come to an end.",
467                 "M$ Empire strikes back.",
468                 "To see is to believe",
469                 "Time is money.",
470                 "Quest of The World's Greatest Brain"
471         };
472 #endif
473         sprintf(file_name, _("playrecord-%s.txt", "playrec-%s.txt"), savefile_base);
474         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, file_name);
475
476         if (creature_ptr->pclass == CLASS_WARRIOR || creature_ptr->pclass == CLASS_MONK || creature_ptr->pclass == CLASS_SAMURAI || creature_ptr->pclass == CLASS_BERSERKER)
477                 strcpy(tmp, subtitle[randint0(MAX_SUBTITLE - 1)]);
478         else if (IS_WIZARD_CLASS(creature_ptr))
479                 strcpy(tmp, subtitle[randint0(MAX_SUBTITLE - 1) + 1]);
480         else strcpy(tmp, subtitle[randint0(MAX_SUBTITLE - 2) + 1]);
481
482 #ifdef JP
483         sprintf(diary_title, "「%s%s%sの伝説 -%s-」", ap_ptr->title, ap_ptr->no ? "の" : "", creature_ptr->name, tmp);
484 #else
485         sprintf(diary_title, "Legend of %s %s '%s'", ap_ptr->title, creature_ptr->name, tmp);
486 #endif
487
488         /* Display the file contents */
489         (void)show_file(creature_ptr, FALSE, buf, diary_title, -1, 0);
490 }
491
492
493 /*!
494  * @brief 日記に任意の内容を表記するコマンドのメインルーチン /
495  * @return なし
496  */
497 static void add_diary_note(player_type *creature_ptr)
498 {
499         char tmp[80] = "\0";
500         char bunshou[80] = "\0";
501
502         if (get_string(_("内容: ", "diary note: "), tmp, 79))
503         {
504                 strcpy(bunshou, tmp);
505                 exe_write_diary(creature_ptr, DIARY_DESCRIPTION, 0, bunshou);
506         }
507 }
508
509 /*!
510  * @brief 最後に取得したアイテムの情報を日記に追加するメインルーチン /
511  * @return なし
512  */
513 static void do_cmd_last_get(player_type *creaute_ptr)
514 {
515         if (record_o_name[0] == '\0') return;
516
517         char buf[256];
518         sprintf(buf, _("%sの入手を記録します。", "Do you really want to record getting %s? "), record_o_name);
519         if (!get_check(buf)) return;
520
521         GAME_TURN turn_tmp = current_world_ptr->game_turn;
522         current_world_ptr->game_turn = record_turn;
523         sprintf(buf, _("%sを手に入れた。", "discover %s."), record_o_name);
524         exe_write_diary(creaute_ptr, DIARY_DESCRIPTION, 0, buf);
525         current_world_ptr->game_turn = turn_tmp;
526 }
527
528
529 /*!
530  * @brief ファイル中の全日記記録を消去する /
531  * @return なし
532  */
533 static void do_cmd_erase_diary(void)
534 {
535         GAME_TEXT file_name[MAX_NLEN];
536         char buf[256];
537         FILE *fff = NULL;
538
539         if (!get_check(_("本当に記録を消去しますか?", "Do you really want to delete all your record? "))) return;
540         sprintf(file_name, _("playrecord-%s.txt", "playrec-%s.txt"), savefile_base);
541         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, file_name);
542         fd_kill(buf);
543
544         fff = my_fopen(buf, "w");
545         if (fff)
546         {
547                 my_fclose(fff);
548                 msg_format(_("記録を消去しました。", "deleted record."));
549         }
550         else
551         {
552                 msg_format(_("%s の消去に失敗しました。", "failed to delete %s."), buf);
553         }
554
555         msg_print(NULL);
556 }
557
558
559 /*!
560  * @brief 日記コマンド
561  * @param crerature_ptr プレーヤーへの参照ポインタ
562  * @return なし
563  */
564 void do_cmd_diary(player_type *creature_ptr)
565 {
566         /* File type is "TEXT" */
567         FILE_TYPE(FILE_TYPE_TEXT);
568         screen_save();
569
570         /* Interact until done */
571         int i;
572         while (TRUE)
573         {
574                 Term_clear();
575
576                 /* Ask for a choice */
577                 prt(_("[ 記録の設定 ]", "[ Play Record ]"), 2, 0);
578
579                 /* Give some choices */
580                 prt(_("(1) 記録を見る", "(1) Display your record"), 4, 5);
581                 prt(_("(2) 文章を記録する", "(2) Add record"), 5, 5);
582                 prt(_("(3) 直前に入手又は鑑定したものを記録する", "(3) Record the last item you got or identified"), 6, 5);
583                 prt(_("(4) 記録を消去する", "(4) Delete your record"), 7, 5);
584
585                 prt(_("(R) プレイ動画を記録する/中止する", "(R) Record playing movie / or stop it"), 9, 5);
586
587                 /* Prompt */
588                 prt(_("コマンド:", "Command: "), 18, 0);
589
590                 /* Prompt */
591                 i = inkey();
592
593                 if (i == ESCAPE) break;
594
595                 switch (i)
596                 {
597                 case '1':
598                         display_diary(creature_ptr);
599                         break;
600                 case '2':
601                         add_diary_note(creature_ptr);
602                         break;
603                 case '3':
604                         do_cmd_last_get(creature_ptr);
605                         break;
606                 case '4':
607                         do_cmd_erase_diary();
608                         break;
609                 case 'r': case 'R':
610                         screen_load();
611                         prepare_movie_hooks();
612                         return;
613                 default: /* Unknown option */
614                         bell();
615                 }
616
617                 msg_erase();
618         }
619
620         screen_load();
621 }
622
623
624 /*!
625  * @brief 画面を再描画するコマンドのメインルーチン
626  * Hack -- redraw the screen
627  * @param creature_ptr プレーヤーへの参照ポインタ
628  * @return なし
629  * @details
630  * <pre>
631  * This command performs various low level updates, clears all the "extra"
632  * windows, does a total redraw of the main window, and requests all of the
633  * interesting updates and redraws that I can think of.
634  *
635  * This command is also used to "instantiate" the results of the user
636  * selecting various things, such as graphics mode, so it must call
637  * the "TERM_XTRA_REACT" hook before redrawing the windows.
638  * </pre>
639  */
640 void do_cmd_redraw(player_type *creature_ptr)
641 {
642         Term_xtra(TERM_XTRA_REACT, 0);
643
644         /* Combine and Reorder the pack (later) */
645         creature_ptr->update |= (PU_COMBINE | PU_REORDER);
646         creature_ptr->update |= (PU_TORCH);
647         creature_ptr->update |= (PU_BONUS | PU_HP | PU_MANA | PU_SPELLS);
648         creature_ptr->update |= (PU_UN_VIEW | PU_UN_LITE);
649         creature_ptr->update |= (PU_VIEW | PU_LITE | PU_MON_LITE);
650         creature_ptr->update |= (PU_MONSTERS);
651
652         creature_ptr->redraw |= (PR_WIPE | PR_BASIC | PR_EXTRA | PR_MAP | PR_EQUIPPY);
653
654         creature_ptr->window |= (PW_INVEN | PW_EQUIP | PW_SPELL | PW_PLAYER);
655         creature_ptr->window |= (PW_MESSAGE | PW_OVERHEAD | PW_DUNGEON | PW_MONSTER | PW_OBJECT);
656
657         update_playtime();
658         handle_stuff(creature_ptr);
659
660         if (creature_ptr->prace == RACE_ANDROID) calc_android_exp(creature_ptr);
661
662         /* Redraw every window */
663         term *old = Term;
664         for (int j = 0; j < 8; j++)
665         {
666                 /* Dead window */
667                 if (!angband_term[j]) continue;
668
669                 /* Activate */
670                 Term_activate(angband_term[j]);
671                 Term_redraw();
672                 Term_fresh();
673                 Term_activate(old);
674         }
675 }
676
677
678 /*!
679  * @brief プレイヤーのステータス表示
680  * @return なし
681  */
682 void do_cmd_player_status(player_type *creature_ptr)
683 {
684         char c;
685         int mode = 0;
686         char tmp[160];
687         screen_save();
688
689         /* Forever */
690         while (TRUE)
691         {
692                 update_playtime();
693                 display_player(creature_ptr, mode, map_name);
694
695                 if (mode == 4)
696                 {
697                         mode = 0;
698                         display_player(creature_ptr, mode, map_name);
699                 }
700
701                 /* Prompt */
702                 Term_putstr(2, 23, -1, TERM_WHITE,
703                         _("['c'で名前変更, 'f'でファイルへ書出, 'h'でモード変更, ESCで終了]", "['c' to change name, 'f' to file, 'h' to change mode, or ESC]"));
704
705                 /* Query */
706                 c = inkey();
707                 if (c == ESCAPE) break;
708
709                 /* Change name */
710                 if (c == 'c')
711                 {
712                         get_name(creature_ptr);
713
714                         /* Process the player name */
715                         process_player_name(creature_ptr, FALSE);
716                 }
717
718                 /* File dump */
719                 else if (c == 'f')
720                 {
721                         sprintf(tmp, "%s.txt", creature_ptr->base_name);
722                         if (get_string(_("ファイル名: ", "File name: "), tmp, 80))
723                         {
724                                 if (tmp[0] && (tmp[0] != ' '))
725                                 {
726                                         file_character(creature_ptr, tmp, update_playtime, display_player, map_name);
727                                 }
728                         }
729                 }
730
731                 else if (c == 'h')
732                 {
733                         mode++;
734                 }
735                 else
736                 {
737                         bell();
738                 }
739
740                 msg_erase();
741         }
742
743         screen_load();
744         creature_ptr->redraw |= (PR_WIPE | PR_BASIC | PR_EXTRA | PR_MAP | PR_EQUIPPY);
745
746         handle_stuff(creature_ptr);
747 }
748
749
750 /*!
751  * @brief 最近表示されたメッセージを再表示するコマンドのメインルーチン
752  * Recall the most recent message
753  * @return なし
754  */
755 void do_cmd_message_one(void)
756 {
757         /* Recall one message */
758         prt(format("> %s", message_str(0)), 0, 0);
759 }
760
761
762 /*!
763  * @brief メッセージのログを表示するコマンドのメインルーチン
764  * Recall the most recent message
765  * @return なし
766  * @details
767  * <pre>
768  * Show previous messages to the user   -BEN-
769  *
770  * The screen format uses line 0 and 23 for headers and prompts,
771  * skips line 1 and 22, and uses line 2 thru 21 for old messages.
772  *
773  * This command shows you which commands you are viewing, and allows
774  * you to "search" for strings in the recall.
775  *
776  * Note that messages may be longer than 80 characters, but they are
777  * displayed using "infinite" length, with a special sub-command to
778  * "slide" the virtual display to the left or right.
779  *
780  * Attempt to only hilite the matching portions of the string.
781  * </pre>
782  */
783 void do_cmd_messages(int num_now)
784 {
785         char shower_str[81];
786         char finder_str[81];
787         char back_str[81];
788         concptr shower = NULL;
789         int wid, hgt;
790         int num_lines;
791
792         Term_get_size(&wid, &hgt);
793
794         /* Number of message lines in a screen */
795         num_lines = hgt - 4;
796
797         /* Wipe finder */
798         strcpy(finder_str, "");
799
800         /* Wipe shower */
801         strcpy(shower_str, "");
802
803         /* Total messages */
804         int n = message_num();
805
806         /* Start on first message */
807         int i = 0;
808         screen_save();
809         Term_clear();
810
811         /* Process requests until done */
812         while (TRUE)
813         {
814                 int j;
815                 int skey;
816
817                 /* Dump up to 20 lines of messages */
818                 for (j = 0; (j < num_lines) && (i + j < n); j++)
819                 {
820                         concptr msg = message_str(i + j);
821
822                         /* Dump the messages, bottom to top */
823                         c_prt((i + j < num_now ? TERM_WHITE : TERM_SLATE), msg, num_lines + 1 - j, 0);
824
825                         if (!shower || !shower[0]) continue;
826
827                         /* Hilite "shower" */
828                         concptr str = msg;
829
830                         /* Display matches */
831                         while ((str = my_strstr(str, shower)) != NULL)
832                         {
833                                 int len = strlen(shower);
834
835                                 /* Display the match */
836                                 Term_putstr(str - msg, num_lines + 1 - j, len, TERM_YELLOW, shower);
837
838                                 /* Advance */
839                                 str += len;
840                         }
841                 }
842
843                 /* Erase remaining lines */
844                 for (; j < num_lines; j++) Term_erase(0, num_lines + 1 - j, 255);
845
846                 /* Display header */
847                 /* translation */
848                 prt(format(_("以前のメッセージ %d-%d 全部で(%d)", "Message Recall (%d-%d of %d)"),
849                         i, i + j - 1, n), 0, 0);
850
851                 /* Display prompt (not very informative) */
852                 prt(_("[ 'p' で更に古いもの, 'n' で更に新しいもの, '/' で検索, ESC で中断 ]",
853                         "[Press 'p' for older, 'n' for newer, ..., or ESCAPE]"), hgt - 1, 0);
854
855                 skey = inkey_special(TRUE);
856
857                 /* Exit on Escape */
858                 if (skey == ESCAPE) break;
859
860                 /* Hack -- Save the old index */
861                 j = i;
862
863                 switch (skey)
864                 {
865                         /* Hack -- handle show */
866                 case '=':
867                         /* Prompt */
868                         prt(_("強調: ", "Show: "), hgt - 1, 0);
869
870                         /* Get a "shower" string, or continue */
871                         strcpy(back_str, shower_str);
872                         if (askfor(shower_str, 80))
873                         {
874                                 /* Show it */
875                                 shower = shower_str[0] ? shower_str : NULL;
876                         }
877                         else strcpy(shower_str, back_str);
878
879                         continue;
880
881                         /* Hack -- handle find */
882                 case '/':
883                 case KTRL('s'):
884                 {
885                         int z;
886
887                         /* Prompt */
888                         prt(_("検索: ", "Find: "), hgt - 1, 0);
889
890                         /* Get a "finder" string, or continue */
891                         strcpy(back_str, finder_str);
892                         if (!askfor(finder_str, 80))
893                         {
894                                 strcpy(finder_str, back_str);
895                                 continue;
896                         }
897                         else if (!finder_str[0])
898                         {
899                                 shower = NULL; /* Stop showing */
900                                 continue;
901                         }
902
903                         /* Show it */
904                         shower = finder_str;
905
906                         /* Scan messages */
907                         for (z = i + 1; z < n; z++)
908                         {
909                                 concptr msg = message_str(z);
910
911                                 /* Search for it */
912                                 if (my_strstr(msg, finder_str))
913                                 {
914                                         /* New location */
915                                         i = z;
916
917                                         break;
918                                 }
919                         }
920                 }
921                 break;
922
923                 /* Recall 1 older message */
924                 case SKEY_TOP:
925                         /* Go to the oldest line */
926                         i = n - num_lines;
927                         break;
928
929                         /* Recall 1 newer message */
930                 case SKEY_BOTTOM:
931                         /* Go to the newest line */
932                         i = 0;
933                         break;
934
935                         /* Recall 1 older message */
936                 case '8':
937                 case SKEY_UP:
938                 case '\n':
939                 case '\r':
940                         /* Go older if legal */
941                         i = MIN(i + 1, n - num_lines);
942                         break;
943
944                         /* Recall 10 older messages */
945                 case '+':
946                         /* Go older if legal */
947                         i = MIN(i + 10, n - num_lines);
948                         break;
949
950                         /* Recall 20 older messages */
951                 case 'p':
952                 case KTRL('P'):
953                 case ' ':
954                 case SKEY_PGUP:
955                         /* Go older if legal */
956                         i = MIN(i + num_lines, n - num_lines);
957                         break;
958
959                         /* Recall 20 newer messages */
960                 case 'n':
961                 case KTRL('N'):
962                 case SKEY_PGDOWN:
963                         /* Go newer (if able) */
964                         i = MAX(0, i - num_lines);
965                         break;
966
967                         /* Recall 10 newer messages */
968                 case '-':
969                         /* Go newer (if able) */
970                         i = MAX(0, i - 10);
971                         break;
972
973                         /* Recall 1 newer messages */
974                 case '2':
975                 case SKEY_DOWN:
976                         /* Go newer (if able) */
977                         i = MAX(0, i - 1);
978                         break;
979                 }
980
981                 /* Hack -- Error of some kind */
982                 if (i == j) bell();
983         }
984
985         screen_load();
986 }
987
988
989 /*!
990  * @brief prefファイルを選択して処理する /
991  * Ask for a "user pref line" and process it
992  * @param creature_ptr プレーヤーへの参照ポインタ
993  * @return なし
994  * @details
995  * Allow absolute file names?
996  */
997 void do_cmd_pref(player_type *creature_ptr)
998 {
999         char buf[80];
1000         strcpy(buf, "");
1001
1002         /* Ask for a "user pref command" */
1003         if (!get_string(_("設定変更コマンド: ", "Pref: "), buf, 80)) return;
1004
1005         /* Process that pref command */
1006         (void)interpret_pref_file(creature_ptr, buf);
1007 }
1008
1009
1010 /*!
1011  * @brief 自動拾い設定ファイルをロードするコマンドのメインルーチン /
1012  * @param creature_ptr プレーヤーへの参照ポインタ
1013  * @return なし
1014  */
1015 void do_cmd_reload_autopick(player_type *creature_ptr)
1016 {
1017         if (!get_check(_("自動拾い設定ファイルをロードしますか? ", "Reload auto-pick preference file? "))) return;
1018         /* Load the file with messages */
1019         autopick_load_pref(creature_ptr, TRUE);
1020 }
1021
1022
1023 /*!
1024  * @brief マクロ情報をprefファイルに保存する /
1025  * @param fname ファイル名
1026  * @return なし
1027  */
1028 static errr macro_dump(concptr fname)
1029 {
1030         static concptr mark = "Macro Dump";
1031         char buf[1024];
1032         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, fname);
1033
1034         /* File type is "TEXT" */
1035         FILE_TYPE(FILE_TYPE_TEXT);
1036
1037         /* Append to the file */
1038         if (!open_auto_dump(buf, mark)) return -1;
1039
1040         /* Start dumping */
1041         auto_dump_printf(_("\n# 自動マクロセーブ\n\n", "\n# Automatic macro dump\n\n"));
1042
1043         /* Dump them */
1044         for (int i = 0; i < macro__num; i++)
1045         {
1046                 /* Extract the action */
1047                 ascii_to_text(buf, macro__act[i]);
1048
1049                 /* Dump the macro */
1050                 auto_dump_printf("A:%s\n", buf);
1051
1052                 /* Extract the action */
1053                 ascii_to_text(buf, macro__pat[i]);
1054
1055                 /* Dump normal macros */
1056                 auto_dump_printf("P:%s\n", buf);
1057
1058                 /* End the macro */
1059                 auto_dump_printf("\n");
1060         }
1061
1062         close_auto_dump();
1063         return 0;
1064 }
1065
1066
1067 /*!
1068  * @brief マクロのトリガーキーを取得する /
1069  * Hack -- ask for a "trigger" (see below)
1070  * @param buf キー表記を保管するバッファ
1071  * @return なし
1072  * @details
1073  * <pre>
1074  * Note the complex use of the "inkey()" function from "util.c".
1075  *
1076  * Note that both "flush()" calls are extremely important.
1077  * </pre>
1078  */
1079 static void do_cmd_macro_aux(char *buf)
1080 {
1081         flush();
1082
1083         /* Do not process macros */
1084         inkey_base = TRUE;
1085
1086         /* First key */
1087         char i = inkey();
1088
1089         /* Read the pattern */
1090         int n = 0;
1091         while (i)
1092         {
1093                 /* Save the key */
1094                 buf[n++] = i;
1095
1096                 /* Do not process macros */
1097                 inkey_base = TRUE;
1098
1099                 /* Do not wait for keys */
1100                 inkey_scan = TRUE;
1101
1102                 /* Attempt to read a key */
1103                 i = inkey();
1104         }
1105
1106         /* Terminate */
1107         buf[n] = '\0';
1108
1109         flush();
1110
1111         /* Convert the trigger */
1112         char tmp[1024];
1113         ascii_to_text(tmp, buf);
1114
1115         /* Hack -- display the trigger */
1116         Term_addstr(-1, TERM_WHITE, tmp);
1117 }
1118
1119
1120 /*!
1121  * @brief マクロのキー表記からアスキーコードを得てターミナルに表示する /
1122  * Hack -- ask for a keymap "trigger" (see below)
1123  * @param buf キー表記を取得するバッファ
1124  * @return なし
1125  * @details
1126  * <pre>
1127  * Note that both "flush()" calls are extremely important.  This may
1128  * no longer be true, since "util.c" is much simpler now.
1129  * </pre>
1130  */
1131 static void do_cmd_macro_aux_keymap(char *buf)
1132 {
1133         char tmp[1024];
1134
1135         flush();
1136
1137         /* Get a key */
1138         buf[0] = inkey();
1139         buf[1] = '\0';
1140
1141         /* Convert to ascii */
1142         ascii_to_text(tmp, buf);
1143
1144         /* Hack -- display the trigger */
1145         Term_addstr(-1, TERM_WHITE, tmp);
1146
1147         flush();
1148 }
1149
1150
1151 /*!
1152  * @brief キーマップをprefファイルにダンプする /
1153  * Hack -- append all keymaps to the given file
1154  * @param fname ファイルネーム
1155  * @return エラーコード
1156  * @details
1157  */
1158 static errr keymap_dump(concptr fname)
1159 {
1160         static concptr mark = "Keymap Dump";
1161         char key[1024];
1162         char buf[1024];
1163
1164         BIT_FLAGS mode;
1165
1166         /* Roguelike */
1167         if (rogue_like_commands)
1168         {
1169                 mode = KEYMAP_MODE_ROGUE;
1170         }
1171
1172         /* Original */
1173         else
1174         {
1175                 mode = KEYMAP_MODE_ORIG;
1176         }
1177
1178         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, fname);
1179
1180         /* File type is "TEXT" */
1181         FILE_TYPE(FILE_TYPE_TEXT);
1182
1183         /* Append to the file */
1184         if (!open_auto_dump(buf, mark)) return -1;
1185
1186         /* Start dumping */
1187         auto_dump_printf(_("\n# 自動キー配置セーブ\n\n", "\n# Automatic keymap dump\n\n"));
1188
1189         /* Dump them */
1190         for (int i = 0; i < 256; i++)
1191         {
1192                 concptr act;
1193
1194                 /* Loop up the keymap */
1195                 act = keymap_act[mode][i];
1196
1197                 /* Skip empty keymaps */
1198                 if (!act) continue;
1199
1200                 /* Encode the key */
1201                 buf[0] = (char)i;
1202                 buf[1] = '\0';
1203                 ascii_to_text(key, buf);
1204
1205                 /* Encode the action */
1206                 ascii_to_text(buf, act);
1207
1208                 /* Dump the macro */
1209                 auto_dump_printf("A:%s\n", buf);
1210                 auto_dump_printf("C:%d:%s\n", mode, key);
1211         }
1212
1213         close_auto_dump();
1214         return 0;
1215 }
1216
1217
1218 /*!
1219  * @brief マクロを設定するコマンドのメインルーチン /
1220  * Interact with "macros"
1221  * @return なし
1222  * @details
1223  * <pre>
1224  * Note that the macro "action" must be defined before the trigger.
1225  *
1226  * Could use some helpful instructions on this page.
1227  * </pre>
1228  */
1229 void do_cmd_macros(player_type *creature_ptr)
1230 {
1231         int i;
1232         char tmp[1024];
1233         char buf[1024];
1234         BIT_FLAGS mode;
1235
1236         /* Roguelike */
1237         if (rogue_like_commands)
1238         {
1239                 mode = KEYMAP_MODE_ROGUE;
1240         }
1241
1242         /* Original */
1243         else
1244         {
1245                 mode = KEYMAP_MODE_ORIG;
1246         }
1247
1248         /* File type is "TEXT" */
1249         FILE_TYPE(FILE_TYPE_TEXT);
1250
1251         screen_save();
1252
1253         /* Process requests until done */
1254         while (TRUE)
1255         {
1256                 Term_clear();
1257                 prt(_("[ マクロの設定 ]", "Interact with Macros"), 2, 0);
1258
1259                 /* Describe that action */
1260                 prt(_("マクロ行動が(もしあれば)下に表示されます:", "Current action (if any) shown below:"), 20, 0);
1261
1262                 /* Analyze the current action */
1263                 ascii_to_text(buf, macro__buf);
1264
1265                 /* Display the current action */
1266                 prt(buf, 22, 0);
1267
1268
1269                 /* Selections */
1270                 prt(_("(1) ユーザー設定ファイルのロード", "(1) Load a user pref file"), 4, 5);
1271                 prt(_("(2) ファイルにマクロを追加", "(2) Append macros to a file"), 5, 5);
1272                 prt(_("(3) マクロの確認", "(3) Query a macro"), 6, 5);
1273                 prt(_("(4) マクロの作成", "(4) Create a macro"), 7, 5);
1274                 prt(_("(5) マクロの削除", "(5) Remove a macro"), 8, 5);
1275                 prt(_("(6) ファイルにキー配置を追加", "(6) Append keymaps to a file"), 9, 5);
1276                 prt(_("(7) キー配置の確認", "(7) Query a keymap"), 10, 5);
1277                 prt(_("(8) キー配置の作成", "(8) Create a keymap"), 11, 5);
1278                 prt(_("(9) キー配置の削除", "(9) Remove a keymap"), 12, 5);
1279                 prt(_("(0) マクロ行動の入力", "(0) Enter a new action"), 13, 5);
1280
1281                 /* Prompt */
1282                 prt(_("コマンド: ", "Command: "), 16, 0);
1283
1284                 i = inkey();
1285
1286                 /* Leave */
1287                 if (i == ESCAPE) break;
1288
1289                 /* Load a 'macro' file */
1290                 else if (i == '1')
1291                 {
1292                         errr err;
1293
1294                         /* Prompt */
1295                         prt(_("コマンド: ユーザー設定ファイルのロード", "Command: Load a user pref file"), 16, 0);
1296
1297                         /* Prompt */
1298                         prt(_("ファイル: ", "File: "), 18, 0);
1299
1300                         /* Default filename */
1301                         sprintf(tmp, "%s.prf", creature_ptr->base_name);
1302
1303                         /* Ask for a file */
1304                         if (!askfor(tmp, 80)) continue;
1305
1306                         /* Process the given filename */
1307                         err = process_pref_file(creature_ptr, tmp);
1308                         if (-2 == err)
1309                         {
1310                                 msg_format(_("標準の設定ファイル'%s'を読み込みました。", "Loaded default '%s'."), tmp);
1311                         }
1312                         else if (err)
1313                         {
1314                                 /* Prompt */
1315                                 msg_format(_("'%s'の読み込みに失敗しました!", "Failed to load '%s'!"), tmp);
1316                         }
1317                         else
1318                         {
1319                                 msg_format(_("'%s'を読み込みました。", "Loaded '%s'."), tmp);
1320                         }
1321                 }
1322
1323                 /* Save macros */
1324                 else if (i == '2')
1325                 {
1326                         /* Prompt */
1327                         prt(_("コマンド: マクロをファイルに追加する", "Command: Append macros to a file"), 16, 0);
1328
1329                         /* Prompt */
1330                         prt(_("ファイル: ", "File: "), 18, 0);
1331
1332                         /* Default filename */
1333                         sprintf(tmp, "%s.prf", creature_ptr->base_name);
1334
1335                         /* Ask for a file */
1336                         if (!askfor(tmp, 80)) continue;
1337
1338                         /* Dump the macros */
1339                         (void)macro_dump(tmp);
1340
1341                         /* Prompt */
1342                         msg_print(_("マクロを追加しました。", "Appended macros."));
1343                 }
1344
1345                 /* Query a macro */
1346                 else if (i == '3')
1347                 {
1348                         int k;
1349
1350                         /* Prompt */
1351                         prt(_("コマンド: マクロの確認", "Command: Query a macro"), 16, 0);
1352
1353
1354                         /* Prompt */
1355                         prt(_("トリガーキー: ", "Trigger: "), 18, 0);
1356
1357                         /* Get a macro trigger */
1358                         do_cmd_macro_aux(buf);
1359
1360                         /* Acquire action */
1361                         k = macro_find_exact(buf);
1362
1363                         /* Nothing found */
1364                         if (k < 0)
1365                         {
1366                                 /* Prompt */
1367                                 msg_print(_("そのキーにはマクロは定義されていません。", "Found no macro."));
1368                         }
1369
1370                         /* Found one */
1371                         else
1372                         {
1373                                 /* Obtain the action */
1374                                 strcpy(macro__buf, macro__act[k]);
1375
1376                                 /* Analyze the current action */
1377                                 ascii_to_text(buf, macro__buf);
1378
1379                                 /* Display the current action */
1380                                 prt(buf, 22, 0);
1381
1382                                 /* Prompt */
1383                                 msg_print(_("マクロを確認しました。", "Found a macro."));
1384                         }
1385                 }
1386
1387                 /* Create a macro */
1388                 else if (i == '4')
1389                 {
1390                         /* Prompt */
1391                         prt(_("コマンド: マクロの作成", "Command: Create a macro"), 16, 0);
1392
1393                         /* Prompt */
1394                         prt(_("トリガーキー: ", "Trigger: "), 18, 0);
1395
1396                         /* Get a macro trigger */
1397                         do_cmd_macro_aux(buf);
1398                         clear_from(20);
1399
1400                         /* Help message */
1401                         c_prt(TERM_L_RED, _("カーソルキーの左右でカーソル位置を移動。BackspaceかDeleteで一文字削除。",
1402                                 "Press Left/Right arrow keys to move cursor. Backspace/Delete to delete a char."), 22, 0);
1403
1404                         /* Prompt */
1405                         prt(_("マクロ行動: ", "Action: "), 20, 0);
1406
1407                         /* Convert to text */
1408                         ascii_to_text(tmp, macro__buf);
1409
1410                         /* Get an encoded action */
1411                         if (askfor(tmp, 80))
1412                         {
1413                                 /* Convert to ascii */
1414                                 text_to_ascii(macro__buf, tmp);
1415
1416                                 /* Link the macro */
1417                                 macro_add(buf, macro__buf);
1418
1419                                 /* Prompt */
1420                                 msg_print(_("マクロを追加しました。", "Added a macro."));
1421                         }
1422                 }
1423
1424                 /* Remove a macro */
1425                 else if (i == '5')
1426                 {
1427                         /* Prompt */
1428                         prt(_("コマンド: マクロの削除", "Command: Remove a macro"), 16, 0);
1429
1430                         /* Prompt */
1431                         prt(_("トリガーキー: ", "Trigger: "), 18, 0);
1432
1433                         /* Get a macro trigger */
1434                         do_cmd_macro_aux(buf);
1435
1436                         /* Link the macro */
1437                         macro_add(buf, buf);
1438
1439                         /* Prompt */
1440                         msg_print(_("マクロを削除しました。", "Removed a macro."));
1441                 }
1442
1443                 /* Save keymaps */
1444                 else if (i == '6')
1445                 {
1446                         /* Prompt */
1447                         prt(_("コマンド: キー配置をファイルに追加する", "Command: Append keymaps to a file"), 16, 0);
1448
1449                         /* Prompt */
1450                         prt(_("ファイル: ", "File: "), 18, 0);
1451
1452                         /* Default filename */
1453                         sprintf(tmp, "%s.prf", creature_ptr->base_name);
1454
1455                         /* Ask for a file */
1456                         if (!askfor(tmp, 80)) continue;
1457
1458                         /* Dump the macros */
1459                         (void)keymap_dump(tmp);
1460
1461                         /* Prompt */
1462                         msg_print(_("キー配置を追加しました。", "Appended keymaps."));
1463                 }
1464
1465                 /* Query a keymap */
1466                 else if (i == '7')
1467                 {
1468                         concptr act;
1469
1470                         /* Prompt */
1471                         prt(_("コマンド: キー配置の確認", "Command: Query a keymap"), 16, 0);
1472
1473                         /* Prompt */
1474                         prt(_("押すキー: ", "Keypress: "), 18, 0);
1475
1476                         /* Get a keymap trigger */
1477                         do_cmd_macro_aux_keymap(buf);
1478
1479                         /* Look up the keymap */
1480                         act = keymap_act[mode][(byte)(buf[0])];
1481
1482                         /* Nothing found */
1483                         if (!act)
1484                         {
1485                                 /* Prompt */
1486                                 msg_print(_("キー配置は定義されていません。", "Found no keymap."));
1487                         }
1488
1489                         /* Found one */
1490                         else
1491                         {
1492                                 /* Obtain the action */
1493                                 strcpy(macro__buf, act);
1494
1495                                 /* Analyze the current action */
1496                                 ascii_to_text(buf, macro__buf);
1497
1498                                 /* Display the current action */
1499                                 prt(buf, 22, 0);
1500
1501                                 /* Prompt */
1502                                 msg_print(_("キー配置を確認しました。", "Found a keymap."));
1503                         }
1504                 }
1505
1506                 /* Create a keymap */
1507                 else if (i == '8')
1508                 {
1509                         /* Prompt */
1510                         prt(_("コマンド: キー配置の作成", "Command: Create a keymap"), 16, 0);
1511
1512                         /* Prompt */
1513                         prt(_("押すキー: ", "Keypress: "), 18, 0);
1514
1515                         /* Get a keymap trigger */
1516                         do_cmd_macro_aux_keymap(buf);
1517                         clear_from(20);
1518
1519                         /* Help message */
1520                         c_prt(TERM_L_RED, _("カーソルキーの左右でカーソル位置を移動。BackspaceかDeleteで一文字削除。",
1521                                 "Press Left/Right arrow keys to move cursor. Backspace/Delete to delete a char."), 22, 0);
1522
1523                         /* Prompt */
1524                         prt(_("行動: ", "Action: "), 20, 0);
1525
1526                         /* Convert to text */
1527                         ascii_to_text(tmp, macro__buf);
1528
1529                         /* Get an encoded action */
1530                         if (askfor(tmp, 80))
1531                         {
1532                                 /* Convert to ascii */
1533                                 text_to_ascii(macro__buf, tmp);
1534
1535                                 /* Free old keymap */
1536                                 string_free(keymap_act[mode][(byte)(buf[0])]);
1537
1538                                 /* Make new keymap */
1539                                 keymap_act[mode][(byte)(buf[0])] = string_make(macro__buf);
1540
1541                                 /* Prompt */
1542                                 msg_print(_("キー配置を追加しました。", "Added a keymap."));
1543                         }
1544                 }
1545
1546                 /* Remove a keymap */
1547                 else if (i == '9')
1548                 {
1549                         /* Prompt */
1550                         prt(_("コマンド: キー配置の削除", "Command: Remove a keymap"), 16, 0);
1551
1552                         /* Prompt */
1553                         prt(_("押すキー: ", "Keypress: "), 18, 0);
1554
1555                         /* Get a keymap trigger */
1556                         do_cmd_macro_aux_keymap(buf);
1557
1558                         /* Free old keymap */
1559                         string_free(keymap_act[mode][(byte)(buf[0])]);
1560
1561                         /* Make new keymap */
1562                         keymap_act[mode][(byte)(buf[0])] = NULL;
1563
1564                         /* Prompt */
1565                         msg_print(_("キー配置を削除しました。", "Removed a keymap."));
1566                 }
1567
1568                 /* Enter a new action */
1569                 else if (i == '0')
1570                 {
1571                         /* Prompt */
1572                         prt(_("コマンド: マクロ行動の入力", "Command: Enter a new action"), 16, 0);
1573                         clear_from(20);
1574
1575                         /* Help message */
1576                         c_prt(TERM_L_RED, _("カーソルキーの左右でカーソル位置を移動。BackspaceかDeleteで一文字削除。",
1577                                 "Press Left/Right arrow keys to move cursor. Backspace/Delete to delete a char."), 22, 0);
1578
1579                         /* Prompt */
1580                         prt(_("マクロ行動: ", "Action: "), 20, 0);
1581
1582                         /* Hack -- limit the value */
1583                         tmp[80] = '\0';
1584
1585                         /* Get an encoded action */
1586                         if (!askfor(buf, 80)) continue;
1587
1588                         /* Extract an action */
1589                         text_to_ascii(macro__buf, buf);
1590                 }
1591
1592                 else
1593                 {
1594                         bell();
1595                 }
1596
1597                 msg_erase();
1598         }
1599
1600         screen_load();
1601 }
1602
1603
1604 /*!
1605  * @brief キャラクタ色の明暗表現
1606  */
1607 static concptr lighting_level_str[F_LIT_MAX] =
1608 {
1609 #ifdef JP
1610         "標準色",
1611         "明色",
1612         "暗色",
1613 #else
1614         "standard",
1615         "brightly lit",
1616         "darkened",
1617 #endif
1618 };
1619
1620
1621 /*!
1622  * @brief キャラクタのビジュアルIDを変更する際の対象指定関数
1623  * @param i 指定対象となるキャラクタコード
1624  * @param num 指定されたビジュアルIDを返す参照ポインタ
1625  * @param max ビジュアルIDの最大数
1626  * @return 指定が実際に行われた場合TRUE、キャンセルされた場合FALSE
1627  */
1628 static bool cmd_visuals_aux(int i, IDX *num, IDX max)
1629 {
1630         if (iscntrl(i))
1631         {
1632                 char str[10] = "";
1633                 IDX tmp;
1634
1635                 sprintf(str, "%d", *num);
1636
1637                 if (!get_string(format("Input new number(0-%d): ", max - 1), str, 4))
1638                         return FALSE;
1639
1640                 tmp = (IDX)strtol(str, NULL, 0);
1641                 if (tmp >= 0 && tmp < max)
1642                         *num = tmp;
1643         }
1644         else if (isupper(i))
1645                 *num = (*num + max - 1) % max;
1646         else
1647                 *num = (*num + 1) % max;
1648
1649         return TRUE;
1650 }
1651
1652 /*!
1653  * @brief キャラクタの変更メニュー表示
1654  * @param choice_msg 選択メッセージ
1655  * @return なし
1656  */
1657 static void print_visuals_menu(concptr choice_msg)
1658 {
1659         prt(_("[ 画面表示の設定 ]", "Interact with Visuals"), 1, 0);
1660
1661         /* Give some choices */
1662         prt(_("(0) ユーザー設定ファイルのロード", "(0) Load a user pref file"), 3, 5);
1663         prt(_("(1) モンスターの 色/文字 をファイルに書き出す", "(1) Dump monster attr/chars"), 4, 5);
1664         prt(_("(2) アイテムの   色/文字 をファイルに書き出す", "(2) Dump object attr/chars"), 5, 5);
1665         prt(_("(3) 地形の       色/文字 をファイルに書き出す", "(3) Dump feature attr/chars"), 6, 5);
1666         prt(_("(4) モンスターの 色/文字 を変更する (数値操作)", "(4) Change monster attr/chars (numeric operation)"), 7, 5);
1667         prt(_("(5) アイテムの   色/文字 を変更する (数値操作)", "(5) Change object attr/chars (numeric operation)"), 8, 5);
1668         prt(_("(6) 地形の       色/文字 を変更する (数値操作)", "(6) Change feature attr/chars (numeric operation)"), 9, 5);
1669         prt(_("(7) モンスターの 色/文字 を変更する (シンボルエディタ)", "(7) Change monster attr/chars (visual mode)"), 10, 5);
1670         prt(_("(8) アイテムの   色/文字 を変更する (シンボルエディタ)", "(8) Change object attr/chars (visual mode)"), 11, 5);
1671         prt(_("(9) 地形の       色/文字 を変更する (シンボルエディタ)", "(9) Change feature attr/chars (visual mode)"), 12, 5);
1672         prt(_("(R) 画面表示方法の初期化", "(R) Reset visuals"), 13, 5);
1673
1674         /* Prompt */
1675         prt(format("コマンド: %s", choice_msg ? choice_msg : _("", "")), 15, 0);
1676 }
1677
1678
1679 /*
1680  * Interact with "visuals"
1681  */
1682 void do_cmd_visuals(player_type *creature_ptr)
1683 {
1684         int i;
1685         char tmp[160];
1686         char buf[1024];
1687         bool need_redraw = FALSE;
1688         concptr empty_symbol = "<< ? >>";
1689
1690         if (use_bigtile) empty_symbol = "<< ?? >>";
1691
1692         /* File type is "TEXT" */
1693         FILE_TYPE(FILE_TYPE_TEXT);
1694         screen_save();
1695
1696         /* Interact until done */
1697         while (TRUE)
1698         {
1699                 Term_clear();
1700
1701                 /* Ask for a choice */
1702                 print_visuals_menu(NULL);
1703
1704                 /* Prompt */
1705                 i = inkey();
1706
1707                 if (i == ESCAPE) break;
1708
1709                 switch (i)
1710                 {
1711                         /* Load a 'pref' file */
1712                 case '0':
1713                         /* Prompt */
1714                         prt(_("コマンド: ユーザー設定ファイルのロード", "Command: Load a user pref file"), 15, 0);
1715
1716                         /* Prompt */
1717                         prt(_("ファイル: ", "File: "), 17, 0);
1718
1719                         /* Default filename */
1720                         sprintf(tmp, "%s.prf", creature_ptr->base_name);
1721
1722                         /* Query */
1723                         if (!askfor(tmp, 70)) continue;
1724
1725                         /* Process the given filename */
1726                         (void)process_pref_file(creature_ptr, tmp);
1727
1728                         need_redraw = TRUE;
1729                         break;
1730
1731                         /* Dump monster attr/chars */
1732                 case '1':
1733                 {
1734                         static concptr mark = "Monster attr/chars";
1735
1736                         /* Prompt */
1737                         prt(_("コマンド: モンスターの[色/文字]をファイルに書き出します", "Command: Dump monster attr/chars"), 15, 0);
1738
1739                         /* Prompt */
1740                         prt(_("ファイル: ", "File: "), 17, 0);
1741
1742                         /* Default filename */
1743                         sprintf(tmp, "%s.prf", creature_ptr->base_name);
1744
1745                         /* Get a filename */
1746                         if (!askfor(tmp, 70)) continue;
1747                         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, tmp);
1748
1749                         /* Append to the file */
1750                         if (!open_auto_dump(buf, mark)) continue;
1751
1752                         /* Start dumping */
1753                         auto_dump_printf(_("\n# モンスターの[色/文字]の設定\n\n", "\n# Monster attr/char definitions\n\n"));
1754
1755                         /* Dump monsters */
1756                         for (i = 0; i < max_r_idx; i++)
1757                         {
1758                                 monster_race *r_ptr = &r_info[i];
1759
1760                                 /* Skip non-entries */
1761                                 if (!r_ptr->name) continue;
1762
1763                                 /* Dump a comment */
1764                                 auto_dump_printf("# %s\n", (r_name + r_ptr->name));
1765
1766                                 /* Dump the monster attr/char info */
1767                                 auto_dump_printf("R:%d:0x%02X/0x%02X\n\n", i,
1768                                         (byte)(r_ptr->x_attr), (byte)(r_ptr->x_char));
1769                         }
1770
1771                         /* Close */
1772                         close_auto_dump();
1773
1774                         msg_print(_("モンスターの[色/文字]をファイルに書き出しました。", "Dumped monster attr/chars."));
1775
1776                         break;
1777                 }
1778
1779                 /* Dump object attr/chars */
1780                 case '2':
1781                 {
1782                         static concptr mark = "Object attr/chars";
1783                         KIND_OBJECT_IDX k_idx;
1784
1785                         /* Prompt */
1786                         prt(_("コマンド: アイテムの[色/文字]をファイルに書き出します", "Command: Dump object attr/chars"), 15, 0);
1787
1788                         /* Prompt */
1789                         prt(_("ファイル: ", "File: "), 17, 0);
1790
1791                         /* Default filename */
1792                         sprintf(tmp, "%s.prf", creature_ptr->base_name);
1793
1794                         /* Get a filename */
1795                         if (!askfor(tmp, 70)) continue;
1796                         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, tmp);
1797
1798                         /* Append to the file */
1799                         if (!open_auto_dump(buf, mark)) continue;
1800
1801                         /* Start dumping */
1802                         auto_dump_printf(_("\n# アイテムの[色/文字]の設定\n\n", "\n# Object attr/char definitions\n\n"));
1803
1804                         /* Dump objects */
1805                         for (k_idx = 0; k_idx < max_k_idx; k_idx++)
1806                         {
1807                                 GAME_TEXT o_name[MAX_NLEN];
1808                                 object_kind *k_ptr = &k_info[k_idx];
1809
1810                                 /* Skip non-entries */
1811                                 if (!k_ptr->name) continue;
1812
1813                                 if (!k_ptr->flavor)
1814                                 {
1815                                         /* Tidy name */
1816                                         strip_name(o_name, k_idx);
1817                                 }
1818                                 else
1819                                 {
1820                                         object_type forge;
1821
1822                                         /* Prepare dummy object */
1823                                         object_prep(&forge, k_idx);
1824
1825                                         /* Get un-shuffled flavor name */
1826                                         object_desc(creature_ptr, o_name, &forge, OD_FORCE_FLAVOR);
1827                                 }
1828
1829                                 /* Dump a comment */
1830                                 auto_dump_printf("# %s\n", o_name);
1831
1832                                 /* Dump the object attr/char info */
1833                                 auto_dump_printf("K:%d:0x%02X/0x%02X\n\n", (int)k_idx,
1834                                         (byte)(k_ptr->x_attr), (byte)(k_ptr->x_char));
1835                         }
1836
1837                         /* Close */
1838                         close_auto_dump();
1839
1840                         msg_print(_("アイテムの[色/文字]をファイルに書き出しました。", "Dumped object attr/chars."));
1841
1842                         break;
1843                 }
1844
1845                 /* Dump feature attr/chars */
1846                 case '3':
1847                 {
1848                         static concptr mark = "Feature attr/chars";
1849
1850                         /* Prompt */
1851                         prt(_("コマンド: 地形の[色/文字]をファイルに書き出します", "Command: Dump feature attr/chars"), 15, 0);
1852
1853                         /* Prompt */
1854                         prt(_("ファイル: ", "File: "), 17, 0);
1855
1856                         /* Default filename */
1857                         sprintf(tmp, "%s.prf", creature_ptr->base_name);
1858
1859                         /* Get a filename */
1860                         if (!askfor(tmp, 70)) continue;
1861                         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, tmp);
1862
1863                         /* Append to the file */
1864                         if (!open_auto_dump(buf, mark)) continue;
1865
1866                         /* Start dumping */
1867                         auto_dump_printf(_("\n# 地形の[色/文字]の設定\n\n", "\n# Feature attr/char definitions\n\n"));
1868
1869                         /* Dump features */
1870                         for (i = 0; i < max_f_idx; i++)
1871                         {
1872                                 feature_type *f_ptr = &f_info[i];
1873
1874                                 /* Skip non-entries */
1875                                 if (!f_ptr->name) continue;
1876
1877                                 /* Skip mimiccing features */
1878                                 if (f_ptr->mimic != i) continue;
1879
1880                                 /* Dump a comment */
1881                                 auto_dump_printf("# %s\n", (f_name + f_ptr->name));
1882
1883                                 /* Dump the feature attr/char info */
1884                                 auto_dump_printf("F:%d:0x%02X/0x%02X:0x%02X/0x%02X:0x%02X/0x%02X\n\n", i,
1885                                         (byte)(f_ptr->x_attr[F_LIT_STANDARD]), (byte)(f_ptr->x_char[F_LIT_STANDARD]),
1886                                         (byte)(f_ptr->x_attr[F_LIT_LITE]), (byte)(f_ptr->x_char[F_LIT_LITE]),
1887                                         (byte)(f_ptr->x_attr[F_LIT_DARK]), (byte)(f_ptr->x_char[F_LIT_DARK]));
1888                         }
1889
1890                         /* Close */
1891                         close_auto_dump();
1892
1893                         msg_print(_("地形の[色/文字]をファイルに書き出しました。", "Dumped feature attr/chars."));
1894
1895                         break;
1896                 }
1897
1898                 /* Modify monster attr/chars (numeric operation) */
1899                 case '4':
1900                 {
1901                         static concptr choice_msg = _("モンスターの[色/文字]を変更します", "Change monster attr/chars");
1902                         static MONRACE_IDX r = 0;
1903
1904                         prt(format(_("コマンド: %s", "Command: %s"), choice_msg), 15, 0);
1905
1906                         /* Hack -- query until done */
1907                         while (TRUE)
1908                         {
1909                                 monster_race *r_ptr = &r_info[r];
1910                                 int c;
1911                                 IDX t;
1912
1913                                 TERM_COLOR da = r_ptr->d_attr;
1914                                 byte dc = r_ptr->d_char;
1915                                 TERM_COLOR ca = r_ptr->x_attr;
1916                                 byte cc = r_ptr->x_char;
1917
1918                                 /* Label the object */
1919                                 Term_putstr(5, 17, -1, TERM_WHITE,
1920                                         format(_("モンスター = %d, 名前 = %-40.40s", "Monster = %d, Name = %-40.40s"), r, (r_name + r_ptr->name)));
1921
1922                                 /* Label the Default values */
1923                                 Term_putstr(10, 19, -1, TERM_WHITE,
1924                                         format(_("初期値  色 / 文字 = %3u / %3u", "Default attr/char = %3u / %3u"), da, dc));
1925
1926                                 Term_putstr(40, 19, -1, TERM_WHITE, empty_symbol);
1927                                 Term_queue_bigchar(43, 19, da, dc, 0, 0);
1928
1929                                 /* Label the Current values */
1930                                 Term_putstr(10, 20, -1, TERM_WHITE,
1931                                         format(_("現在値  色 / 文字 = %3u / %3u", "Current attr/char = %3u / %3u"), ca, cc));
1932
1933                                 Term_putstr(40, 20, -1, TERM_WHITE, empty_symbol);
1934                                 Term_queue_bigchar(43, 20, ca, cc, 0, 0);
1935
1936                                 /* Prompt */
1937                                 Term_putstr(0, 22, -1, TERM_WHITE,
1938                                         _("コマンド (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): "));
1939
1940                                 i = inkey();
1941
1942                                 /* All done */
1943                                 if (i == ESCAPE) break;
1944
1945                                 if (iscntrl(i)) c = 'a' + i - KTRL('A');
1946                                 else if (isupper(i)) c = 'a' + i - 'A';
1947                                 else c = i;
1948
1949                                 switch (c)
1950                                 {
1951                                 case 'n':
1952                                 {
1953                                         IDX prev_r = r;
1954                                         do
1955                                         {
1956                                                 if (!cmd_visuals_aux(i, &r, max_r_idx))
1957                                                 {
1958                                                         r = prev_r;
1959                                                         break;
1960                                                 }
1961                                         } while (!r_info[r].name);
1962                                 }
1963                                 break;
1964                                 case 'a':
1965                                         t = (int)r_ptr->x_attr;
1966                                         (void)cmd_visuals_aux(i, &t, 256);
1967                                         r_ptr->x_attr = (byte)t;
1968                                         need_redraw = TRUE;
1969                                         break;
1970                                 case 'c':
1971                                         t = (int)r_ptr->x_char;
1972                                         (void)cmd_visuals_aux(i, &t, 256);
1973                                         r_ptr->x_char = (byte)t;
1974                                         need_redraw = TRUE;
1975                                         break;
1976                                 case 'v':
1977                                         do_cmd_knowledge_monsters(creature_ptr, &need_redraw, TRUE, r);
1978                                         Term_clear();
1979                                         print_visuals_menu(choice_msg);
1980                                         break;
1981                                 }
1982                         }
1983
1984                         break;
1985                 }
1986
1987                 /* Modify object attr/chars (numeric operation) */
1988                 case '5':
1989                 {
1990                         static concptr choice_msg = _("アイテムの[色/文字]を変更します", "Change object attr/chars");
1991                         static IDX k = 0;
1992                         prt(format(_("コマンド: %s", "Command: %s"), choice_msg), 15, 0);
1993
1994                         /* Hack -- query until done */
1995                         while (TRUE)
1996                         {
1997                                 object_kind *k_ptr = &k_info[k];
1998                                 int c;
1999                                 IDX t;
2000
2001                                 TERM_COLOR da = k_ptr->d_attr;
2002                                 SYMBOL_CODE dc = k_ptr->d_char;
2003                                 TERM_COLOR ca = k_ptr->x_attr;
2004                                 SYMBOL_CODE cc = k_ptr->x_char;
2005
2006                                 /* Label the object */
2007                                 Term_putstr(5, 17, -1, TERM_WHITE,
2008                                         format(_("アイテム = %d, 名前 = %-40.40s", "Object = %d, Name = %-40.40s"),
2009                                                 k, k_name + (!k_ptr->flavor ? k_ptr->name : k_ptr->flavor_name)));
2010
2011                                 /* Label the Default values */
2012                                 Term_putstr(10, 19, -1, TERM_WHITE,
2013                                         format(_("初期値  色 / 文字 = %3d / %3d", "Default attr/char = %3d / %3d"), da, dc));
2014
2015                                 Term_putstr(40, 19, -1, TERM_WHITE, empty_symbol);
2016                                 Term_queue_bigchar(43, 19, da, dc, 0, 0);
2017
2018                                 /* Label the Current values */
2019                                 Term_putstr(10, 20, -1, TERM_WHITE,
2020                                         format(_("現在値  色 / 文字 = %3d / %3d", "Current attr/char = %3d / %3d"), ca, cc));
2021
2022                                 Term_putstr(40, 20, -1, TERM_WHITE, empty_symbol);
2023                                 Term_queue_bigchar(43, 20, ca, cc, 0, 0);
2024
2025                                 /* Prompt */
2026                                 Term_putstr(0, 22, -1, TERM_WHITE,
2027                                         _("コマンド (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): "));
2028
2029                                 i = inkey();
2030
2031                                 /* All done */
2032                                 if (i == ESCAPE) break;
2033
2034                                 if (iscntrl(i)) c = 'a' + i - KTRL('A');
2035                                 else if (isupper(i)) c = 'a' + i - 'A';
2036                                 else c = i;
2037
2038                                 switch (c)
2039                                 {
2040                                 case 'n':
2041                                 {
2042                                         IDX prev_k = k;
2043                                         do
2044                                         {
2045                                                 if (!cmd_visuals_aux(i, &k, max_k_idx))
2046                                                 {
2047                                                         k = prev_k;
2048                                                         break;
2049                                                 }
2050                                         } while (!k_info[k].name);
2051                                 }
2052                                 break;
2053                                 case 'a':
2054                                         t = (int)k_ptr->x_attr;
2055                                         (void)cmd_visuals_aux(i, &t, 256);
2056                                         k_ptr->x_attr = (byte)t;
2057                                         need_redraw = TRUE;
2058                                         break;
2059                                 case 'c':
2060                                         t = (int)k_ptr->x_char;
2061                                         (void)cmd_visuals_aux(i, &t, 256);
2062                                         k_ptr->x_char = (byte)t;
2063                                         need_redraw = TRUE;
2064                                         break;
2065                                 case 'v':
2066                                         do_cmd_knowledge_objects(creature_ptr, &need_redraw, TRUE, k);
2067                                         Term_clear();
2068                                         print_visuals_menu(choice_msg);
2069                                         break;
2070                                 }
2071                         }
2072
2073                         break;
2074                 }
2075
2076                 /* Modify feature attr/chars (numeric operation) */
2077                 case '6':
2078                 {
2079                         static concptr choice_msg = _("地形の[色/文字]を変更します", "Change feature attr/chars");
2080                         static IDX f = 0;
2081                         static IDX lighting_level = F_LIT_STANDARD;
2082                         prt(format(_("コマンド: %s", "Command: %s"), choice_msg), 15, 0);
2083
2084                         /* Hack -- query until done */
2085                         while (TRUE)
2086                         {
2087                                 feature_type *f_ptr = &f_info[f];
2088                                 int c;
2089                                 IDX t;
2090
2091                                 TERM_COLOR da = f_ptr->d_attr[lighting_level];
2092                                 byte dc = f_ptr->d_char[lighting_level];
2093                                 TERM_COLOR ca = f_ptr->x_attr[lighting_level];
2094                                 byte cc = f_ptr->x_char[lighting_level];
2095
2096                                 /* Label the object */
2097                                 prt("", 17, 5);
2098                                 Term_putstr(5, 17, -1, TERM_WHITE,
2099                                         format(_("地形 = %d, 名前 = %s, 明度 = %s", "Terrain = %d, Name = %s, Lighting = %s"),
2100                                                 f, (f_name + f_ptr->name), lighting_level_str[lighting_level]));
2101
2102                                 /* Label the Default values */
2103                                 Term_putstr(10, 19, -1, TERM_WHITE,
2104                                         format(_("初期値  色 / 文字 = %3d / %3d", "Default attr/char = %3d / %3d"), da, dc));
2105
2106                                 Term_putstr(40, 19, -1, TERM_WHITE, empty_symbol);
2107                                 Term_queue_bigchar(43, 19, da, dc, 0, 0);
2108
2109                                 /* Label the Current values */
2110 #ifdef JP
2111                                 Term_putstr(10, 20, -1, TERM_WHITE,
2112                                         format("現在値  色 / 文字 = %3d / %3d", ca, cc));
2113 #else
2114                                 Term_putstr(10, 20, -1, TERM_WHITE,
2115                                         format("Current attr/char = %3d / %3d", ca, cc));
2116 #endif
2117
2118                                 Term_putstr(40, 20, -1, TERM_WHITE, empty_symbol);
2119                                 Term_queue_bigchar(43, 20, ca, cc, 0, 0);
2120
2121                                 /* Prompt */
2122 #ifdef JP
2123                                 Term_putstr(0, 22, -1, TERM_WHITE,
2124                                         "コマンド (n/N/^N/a/A/^A/c/C/^C/l/L/^L/d/D/^D/v/V/^V): ");
2125 #else
2126                                 Term_putstr(0, 22, -1, TERM_WHITE,
2127                                         "Command (n/N/^N/a/A/^A/c/C/^C/l/L/^L/d/D/^D/v/V/^V): ");
2128 #endif
2129
2130                                 i = inkey();
2131
2132                                 /* All done */
2133                                 if (i == ESCAPE) break;
2134
2135                                 if (iscntrl(i)) c = 'a' + i - KTRL('A');
2136                                 else if (isupper(i)) c = 'a' + i - 'A';
2137                                 else c = i;
2138
2139                                 switch (c)
2140                                 {
2141                                 case 'n':
2142                                 {
2143                                         IDX prev_f = f;
2144                                         do
2145                                         {
2146                                                 if (!cmd_visuals_aux(i, &f, max_f_idx))
2147                                                 {
2148                                                         f = prev_f;
2149                                                         break;
2150                                                 }
2151                                         } while (!f_info[f].name || (f_info[f].mimic != f));
2152                                 }
2153                                 break;
2154                                 case 'a':
2155                                         t = (int)f_ptr->x_attr[lighting_level];
2156                                         (void)cmd_visuals_aux(i, &t, 256);
2157                                         f_ptr->x_attr[lighting_level] = (byte)t;
2158                                         need_redraw = TRUE;
2159                                         break;
2160                                 case 'c':
2161                                         t = (int)f_ptr->x_char[lighting_level];
2162                                         (void)cmd_visuals_aux(i, &t, 256);
2163                                         f_ptr->x_char[lighting_level] = (byte)t;
2164                                         need_redraw = TRUE;
2165                                         break;
2166                                 case 'l':
2167                                         (void)cmd_visuals_aux(i, &lighting_level, F_LIT_MAX);
2168                                         break;
2169                                 case 'd':
2170                                         apply_default_feat_lighting(f_ptr->x_attr, f_ptr->x_char);
2171                                         need_redraw = TRUE;
2172                                         break;
2173                                 case 'v':
2174                                         do_cmd_knowledge_features(&need_redraw, TRUE, f, &lighting_level);
2175                                         Term_clear();
2176                                         print_visuals_menu(choice_msg);
2177                                         break;
2178                                 }
2179                         }
2180
2181                         break;
2182                 }
2183
2184                 /* Modify monster attr/chars (visual mode) */
2185                 case '7':
2186                         do_cmd_knowledge_monsters(creature_ptr, &need_redraw, TRUE, -1);
2187                         break;
2188
2189                         /* Modify object attr/chars (visual mode) */
2190                 case '8':
2191                         do_cmd_knowledge_objects(creature_ptr, &need_redraw, TRUE, -1);
2192                         break;
2193
2194                         /* Modify feature attr/chars (visual mode) */
2195                 case '9':
2196                 {
2197                         IDX lighting_level = F_LIT_STANDARD;
2198                         do_cmd_knowledge_features(&need_redraw, TRUE, -1, &lighting_level);
2199                         break;
2200                 }
2201
2202                 /* Reset visuals */
2203                 case 'R':
2204                 case 'r':
2205                         /* Reset */
2206                         reset_visuals(creature_ptr);
2207
2208                         msg_print(_("画面上の[色/文字]を初期値にリセットしました。", "Visual attr/char tables reset."));
2209                         need_redraw = TRUE;
2210                         break;
2211
2212                         /* Unknown option */
2213                 default:
2214                         bell();
2215                         break;
2216                 }
2217
2218                 msg_erase();
2219         }
2220
2221         screen_load();
2222
2223         if (need_redraw) do_cmd_redraw(creature_ptr);
2224 }
2225
2226
2227 /*
2228  * Interact with "colors"
2229  */
2230 void do_cmd_colors(player_type *creature_ptr)
2231 {
2232         int i;
2233         char tmp[160];
2234         char buf[1024];
2235
2236         /* File type is "TEXT" */
2237         FILE_TYPE(FILE_TYPE_TEXT);
2238
2239         screen_save();
2240
2241         /* Interact until done */
2242         while (TRUE)
2243         {
2244                 Term_clear();
2245
2246                 /* Ask for a choice */
2247                 prt(_("[ カラーの設定 ]", "Interact with Colors"), 2, 0);
2248
2249                 /* Give some choices */
2250                 prt(_("(1) ユーザー設定ファイルのロード", "(1) Load a user pref file"), 4, 5);
2251                 prt(_("(2) カラーの設定をファイルに書き出す", "(2) Dump colors"), 5, 5);
2252                 prt(_("(3) カラーの設定を変更する", "(3) Modify colors"), 6, 5);
2253
2254                 /* Prompt */
2255                 prt(_("コマンド: ", "Command: "), 8, 0);
2256                 /* Prompt */
2257                 i = inkey();
2258
2259                 if (i == ESCAPE) break;
2260
2261                 /* Load a 'pref' file */
2262                 if (i == '1')
2263                 {
2264                         /* Prompt */
2265                         prt(_("コマンド: ユーザー設定ファイルをロードします", "Command: Load a user pref file"), 8, 0);
2266
2267                         /* Prompt */
2268                         prt(_("ファイル: ", "File: "), 10, 0);
2269
2270                         /* Default file */
2271                         sprintf(tmp, "%s.prf", creature_ptr->base_name);
2272
2273                         /* Query */
2274                         if (!askfor(tmp, 70)) continue;
2275
2276                         /* Process the given filename */
2277                         (void)process_pref_file(creature_ptr, tmp);
2278
2279                         /* Mega-Hack -- react to changes */
2280                         Term_xtra(TERM_XTRA_REACT, 0);
2281
2282                         /* Mega-Hack -- redraw */
2283                         Term_redraw();
2284                 }
2285
2286                 /* Dump colors */
2287                 else if (i == '2')
2288                 {
2289                         static concptr mark = "Colors";
2290
2291                         /* Prompt */
2292                         prt(_("コマンド: カラーの設定をファイルに書き出します", "Command: Dump colors"), 8, 0);
2293
2294                         /* Prompt */
2295                         prt(_("ファイル: ", "File: "), 10, 0);
2296
2297                         /* Default filename */
2298                         sprintf(tmp, "%s.prf", creature_ptr->base_name);
2299
2300                         /* Get a filename */
2301                         if (!askfor(tmp, 70)) continue;
2302                         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, tmp);
2303
2304                         /* Append to the file */
2305                         if (!open_auto_dump(buf, mark)) continue;
2306
2307                         /* Start dumping */
2308                         auto_dump_printf(_("\n# カラーの設定\n\n", "\n# Color redefinitions\n\n"));
2309
2310                         /* Dump colors */
2311                         for (i = 0; i < 256; i++)
2312                         {
2313                                 int kv = angband_color_table[i][0];
2314                                 int rv = angband_color_table[i][1];
2315                                 int gv = angband_color_table[i][2];
2316                                 int bv = angband_color_table[i][3];
2317
2318                                 concptr name = _("未知", "unknown");
2319
2320                                 /* Skip non-entries */
2321                                 if (!kv && !rv && !gv && !bv) continue;
2322
2323                                 /* Extract the color name */
2324                                 if (i < 16) name = color_names[i];
2325
2326                                 /* Dump a comment */
2327                                 auto_dump_printf(_("# カラー '%s'\n", "# Color '%s'\n"), name);
2328
2329                                 /* Dump the monster attr/char info */
2330                                 auto_dump_printf("V:%d:0x%02X:0x%02X:0x%02X:0x%02X\n\n",
2331                                         i, kv, rv, gv, bv);
2332                         }
2333
2334                         /* Close */
2335                         close_auto_dump();
2336
2337                         msg_print(_("カラーの設定をファイルに書き出しました。", "Dumped color redefinitions."));
2338                 }
2339
2340                 /* Edit colors */
2341                 else if (i == '3')
2342                 {
2343                         static byte a = 0;
2344
2345                         /* Prompt */
2346                         prt(_("コマンド: カラーの設定を変更します", "Command: Modify colors"), 8, 0);
2347
2348                         /* Hack -- query until done */
2349                         while (TRUE)
2350                         {
2351                                 concptr name;
2352                                 byte j;
2353                                 clear_from(10);
2354
2355                                 /* Exhibit the normal colors */
2356                                 for (j = 0; j < 16; j++)
2357                                 {
2358                                         /* Exhibit this color */
2359                                         Term_putstr(j * 4, 20, -1, a, "###");
2360
2361                                         /* Exhibit all colors */
2362                                         Term_putstr(j * 4, 22, -1, j, format("%3d", j));
2363                                 }
2364
2365                                 /* Describe the color */
2366                                 name = ((a < 16) ? color_names[a] : _("未定義", "undefined"));
2367
2368                                 /* Describe the color */
2369                                 Term_putstr(5, 10, -1, TERM_WHITE,
2370                                         format(_("カラー = %d, 名前 = %s", "Color = %d, Name = %s"), a, name));
2371
2372                                 /* Label the Current values */
2373                                 Term_putstr(5, 12, -1, TERM_WHITE,
2374                                         format("K = 0x%02x / R,G,B = 0x%02x,0x%02x,0x%02x",
2375                                                 angband_color_table[a][0],
2376                                                 angband_color_table[a][1],
2377                                                 angband_color_table[a][2],
2378                                                 angband_color_table[a][3]));
2379
2380                                 /* Prompt */
2381                                 Term_putstr(0, 14, -1, TERM_WHITE,
2382                                         _("コマンド (n/N/k/K/r/R/g/G/b/B): ", "Command (n/N/k/K/r/R/g/G/b/B): "));
2383
2384                                 i = inkey();
2385
2386                                 /* All done */
2387                                 if (i == ESCAPE) break;
2388
2389                                 /* Analyze */
2390                                 if (i == 'n') a = (byte)(a + 1);
2391                                 if (i == 'N') a = (byte)(a - 1);
2392                                 if (i == 'k') angband_color_table[a][0] = (byte)(angband_color_table[a][0] + 1);
2393                                 if (i == 'K') angband_color_table[a][0] = (byte)(angband_color_table[a][0] - 1);
2394                                 if (i == 'r') angband_color_table[a][1] = (byte)(angband_color_table[a][1] + 1);
2395                                 if (i == 'R') angband_color_table[a][1] = (byte)(angband_color_table[a][1] - 1);
2396                                 if (i == 'g') angband_color_table[a][2] = (byte)(angband_color_table[a][2] + 1);
2397                                 if (i == 'G') angband_color_table[a][2] = (byte)(angband_color_table[a][2] - 1);
2398                                 if (i == 'b') angband_color_table[a][3] = (byte)(angband_color_table[a][3] + 1);
2399                                 if (i == 'B') angband_color_table[a][3] = (byte)(angband_color_table[a][3] - 1);
2400
2401                                 /* Hack -- react to changes */
2402                                 Term_xtra(TERM_XTRA_REACT, 0);
2403
2404                                 /* Hack -- redraw */
2405                                 Term_redraw();
2406                         }
2407                 }
2408
2409                 /* Unknown option */
2410                 else
2411                 {
2412                         bell();
2413                 }
2414
2415                 msg_erase();
2416         }
2417
2418         screen_load();
2419 }
2420
2421
2422 /*
2423  * Note something in the message recall
2424  */
2425 void do_cmd_note(void)
2426 {
2427         char buf[80];
2428
2429         /* Default */
2430         strcpy(buf, "");
2431
2432         /* Input */
2433         if (!get_string(_("メモ: ", "Note: "), buf, 60)) return;
2434
2435         /* Ignore empty notes */
2436         if (!buf[0] || (buf[0] == ' ')) return;
2437
2438         /* Add the note to the message recall */
2439         msg_format(_("メモ: %s", "Note: %s"), buf);
2440 }
2441
2442
2443 /*
2444  * Mention the current version
2445  */
2446 void do_cmd_version(void)
2447 {
2448 #if FAKE_VER_EXTRA > 0
2449         msg_format(_("変愚蛮怒(Hengband) %d.%d.%d.%d", "You are playing Hengband %d.%d.%d.%d."),
2450                 FAKE_VER_MAJOR - 10, FAKE_VER_MINOR, FAKE_VER_PATCH, FAKE_VER_EXTRA);
2451 #else
2452         msg_format(_("変愚蛮怒(Hengband) %d.%d.%d", "You are playing Hengband %d.%d.%d."),
2453                 FAKE_VER_MAJOR - 10, FAKE_VER_MINOR, FAKE_VER_PATCH);
2454 #endif
2455 }
2456
2457
2458 /*
2459  * Array of feeling strings
2460  */
2461 static concptr do_cmd_feeling_text[11] =
2462 {
2463         _("この階の雰囲気を感じとれなかった...", "Looks like any other level."),
2464         _("この階には何か特別なものがあるような気がする。", "You feel there is something special about this level."),
2465         _("恐ろしい死の幻が目に浮かび、気絶しそうになった!", "You nearly faint as horrible visions of death fill your mind!"),
2466         _("この階はとても危険なようだ。", "This level looks very dangerous."),
2467         _("とても悪い予感がする...", "You have a very bad feeling..."),
2468         _("悪い予感がする...", "You have a bad feeling..."),
2469         _("何か緊張する。", "You feel nervous."),
2470         _("少し不運な気がする...", "You feel your luck is turning..."),
2471         _("この場所は好きになれない。", "You don't like the look of this place."),
2472         _("この階はそれなりに安全なようだ。", "This level looks reasonably safe."),
2473         _("なんて退屈なところだ...", "What a boring place...")
2474 };
2475
2476 static concptr do_cmd_feeling_text_combat[11] =
2477 {
2478         _("この階の雰囲気を感じとれなかった...", "Looks like any other level."),
2479         _("この階には何か特別なものがあるような気がする。", "You feel there is something special about this level."),
2480         _("今夜もまた、誰かが命を落とす...", "You nearly faint as horrible visions of death fill your mind!"),
2481         _("この階はとても危険なようだ。", "This level looks very dangerous."),
2482         _("とても悪い予感がする...", "You have a very bad feeling..."),
2483         _("悪い予感がする...", "You have a bad feeling..."),
2484         _("何か緊張する。", "You feel nervous."),
2485         _("少し不運な気がする...", "You feel your luck is turning..."),
2486         _("この場所は好きになれない。", "You don't like the look of this place."),
2487         _("この階はそれなりに安全なようだ。", "This level looks reasonably safe."),
2488         _("なんて退屈なところだ...", "What a boring place...")
2489 };
2490
2491 static concptr do_cmd_feeling_text_lucky[11] =
2492 {
2493         _("この階の雰囲気を感じとれなかった...", "Looks like any other level."),
2494         _("この階には何か特別なものがあるような気がする。", "You feel there is something special about this level."),
2495         _("この階はこの上なく素晴らしい感じがする。", "You have a superb feeling about this level."),
2496         _("素晴らしい感じがする...", "You have an excellent feeling..."),
2497         _("とても良い感じがする...", "You have a very good feeling..."),
2498         _("良い感じがする...", "You have a good feeling..."),
2499         _("ちょっと幸運な感じがする...", "You feel strangely lucky..."),
2500         _("多少は運が向いてきたか...", "You feel your luck is turning..."),
2501         _("見た感じ悪くはない...", "You like the look of this place..."),
2502         _("全然駄目ということはないが...", "This level can't be all bad..."),
2503         _("なんて退屈なところだ...", "What a boring place...")
2504 };
2505
2506
2507 /*
2508  * Note that "feeling" is set to zero unless some time has passed.
2509  * Note that this is done when the level is GENERATED, not entered.
2510  */
2511 void do_cmd_feeling(player_type *creature_ptr)
2512 {
2513         if (creature_ptr->wild_mode) return;
2514
2515         /* No useful feeling in quests */
2516         if (creature_ptr->current_floor_ptr->inside_quest && !random_quest_number(creature_ptr, creature_ptr->current_floor_ptr->dun_level))
2517         {
2518                 msg_print(_("典型的なクエストのダンジョンのようだ。", "Looks like a typical quest level."));
2519                 return;
2520         }
2521
2522         /* No useful feeling in town */
2523         if (creature_ptr->town_num && !creature_ptr->current_floor_ptr->dun_level)
2524         {
2525                 if (!strcmp(town_info[creature_ptr->town_num].name, _("荒野", "wilderness")))
2526                 {
2527                         msg_print(_("何かありそうな荒野のようだ。", "Looks like a strange wilderness."));
2528                         return;
2529                 }
2530
2531                 msg_print(_("典型的な町のようだ。", "Looks like a typical town."));
2532                 return;
2533         }
2534
2535         /* No useful feeling in the wilderness */
2536         if (!creature_ptr->current_floor_ptr->dun_level)
2537         {
2538                 msg_print(_("典型的な荒野のようだ。", "Looks like a typical wilderness."));
2539                 return;
2540         }
2541
2542         /* Display the feeling */
2543         if (creature_ptr->muta3 & MUT3_GOOD_LUCK)
2544                 msg_print(do_cmd_feeling_text_lucky[creature_ptr->feeling]);
2545         else if (IS_ECHIZEN(creature_ptr))
2546                 msg_print(do_cmd_feeling_text_combat[creature_ptr->feeling]);
2547         else
2548                 msg_print(do_cmd_feeling_text[creature_ptr->feeling]);
2549 }
2550
2551
2552 /*
2553  * Description of each monster group.
2554  */
2555 static concptr monster_group_text[] =
2556 {
2557 #ifdef JP
2558         "ユニーク", /* "Uniques" */
2559         "乗馬可能なモンスター",       /* "Riding" */
2560         "賞金首", /* "Wanted */
2561         "アンバーの王族", /* "Amberite" */
2562         "アリ",
2563         "コウモリ",
2564         "ムカデ",
2565         "ドラゴン",
2566         "目玉",
2567         "ネコ",
2568         "ゴーレム",
2569         "標準人間型生物",
2570         "ベトベト",
2571         "ゼリー",
2572         "コボルド",
2573         "水棲生物",
2574         "モルド",
2575         "ナーガ",
2576         "オーク",
2577         "人間",
2578         "四足獣",
2579         "ネズミ",
2580         "スケルトン",
2581         "デーモン",
2582         "ボルテックス",
2583         "イモムシ/大群",
2584         /* "unused", */
2585         "イーク",
2586         "ゾンビ/ミイラ",
2587         "天使",
2588         "鳥",
2589         "犬",
2590         /* "古代ドラゴン/ワイアーム", */
2591         "エレメンタル",
2592         "トンボ",
2593         "ゴースト",
2594         "雑種",
2595         "昆虫",
2596         "ヘビ",
2597         "キラー・ビートル",
2598         "リッチ",
2599         "多首の爬虫類",
2600         "謎の生物",
2601         "オーガ",
2602         "巨大人間型生物",
2603         "クイルスルグ",
2604         "爬虫類/両生類",
2605         "蜘蛛/サソリ/ダニ",
2606         "トロル",
2607         /* "上級デーモン", */
2608         "バンパイア",
2609         "ワイト/レイス/等",
2610         "ゾーン/ザレン/等",
2611         "イエティ",
2612         "ハウンド",
2613         "ミミック",
2614         "壁/植物/気体",
2615         "おばけキノコ",
2616         "球体",
2617         "プレイヤー",
2618 #else
2619         "Uniques",
2620         "Ridable monsters",
2621         "Wanted monsters",
2622         "Amberite",
2623         "Ant",
2624         "Bat",
2625         "Centipede",
2626         "Dragon",
2627         "Floating Eye",
2628         "Feline",
2629         "Golem",
2630         "Hobbit/Elf/Dwarf",
2631         "Icky Thing",
2632         "Jelly",
2633         "Kobold",
2634         "Aquatic monster",
2635         "Mold",
2636         "Naga",
2637         "Orc",
2638         "Person/Human",
2639         "Quadruped",
2640         "Rodent",
2641         "Skeleton",
2642         "Demon",
2643         "Vortex",
2644         "Worm/Worm-Mass",
2645         /* "unused", */
2646         "Yeek",
2647         "Zombie/Mummy",
2648         "Angel",
2649         "Bird",
2650         "Canine",
2651         /* "Ancient Dragon/Wyrm", */
2652         "Elemental",
2653         "Dragon Fly",
2654         "Ghost",
2655         "Hybrid",
2656         "Insect",
2657         "Snake",
2658         "Killer Beetle",
2659         "Lich",
2660         "Multi-Headed Reptile",
2661         "Mystery Living",
2662         "Ogre",
2663         "Giant Humanoid",
2664         "Quylthulg",
2665         "Reptile/Amphibian",
2666         "Spider/Scorpion/Tick",
2667         "Troll",
2668         /* "Major Demon", */
2669         "Vampire",
2670         "Wight/Wraith/etc",
2671         "Xorn/Xaren/etc",
2672         "Yeti",
2673         "Zephyr Hound",
2674         "Mimic",
2675         "Wall/Plant/Gas",
2676         "Mushroom patch",
2677         "Ball",
2678         "Player",
2679 #endif
2680         NULL
2681 };
2682
2683
2684 /*
2685  * Symbols of monsters in each group. Note the "Uniques" group
2686  * is handled differently.
2687  */
2688 static concptr monster_group_char[] =
2689 {
2690         (char *)-1L,
2691         (char *)-2L,
2692         (char *)-3L,
2693         (char *)-4L,
2694         "a",
2695         "b",
2696         "c",
2697         "dD",
2698         "e",
2699         "f",
2700         "g",
2701         "h",
2702         "i",
2703         "j",
2704         "k",
2705         "l",
2706         "m",
2707         "n",
2708         "o",
2709         "pt",
2710         "q",
2711         "r",
2712         "s",
2713         "uU",
2714         "v",
2715         "w",
2716         /* "x", */
2717         "y",
2718         "z",
2719         "A",
2720         "B",
2721         "C",
2722         /* "D", */
2723         "E",
2724         "F",
2725         "G",
2726         "H",
2727         "I",
2728         "J",
2729         "K",
2730         "L",
2731         "M",
2732         "N",
2733         "O",
2734         "P",
2735         "Q",
2736         "R",
2737         "S",
2738         "T",
2739         /* "U", */
2740         "V",
2741         "W",
2742         "X",
2743         "Y",
2744         "Z",
2745         "!$&()+./=>?[\\]`{|~",
2746         "#%",
2747         ",",
2748         "*",
2749         "@",
2750         NULL
2751 };
2752
2753
2754 /*
2755  * todo 引数と戻り値について追記求む
2756  * Build a list of monster indexes in the given group.
2757  *
2758  * mode & 0x01 : check for non-empty group
2759  * mode & 0x02 : visual operation only
2760
2761  * @param creature_ptr プレーヤーへの参照ポインタ
2762  * @param grp_cur ???
2763  * @param mon_idx[] ???
2764  * @param mode ???
2765  * @return The number of monsters in the group
2766  */
2767 static IDX collect_monsters(player_type *creature_ptr, IDX grp_cur, IDX mon_idx[], BIT_FLAGS8 mode)
2768 {
2769         /* Get a list of x_char in this group */
2770         concptr group_char = monster_group_char[grp_cur];
2771
2772         bool grp_unique = (monster_group_char[grp_cur] == (char *)-1L);
2773         bool grp_riding = (monster_group_char[grp_cur] == (char *)-2L);
2774         bool grp_wanted = (monster_group_char[grp_cur] == (char *)-3L);
2775         bool grp_amberite = (monster_group_char[grp_cur] == (char *)-4L);
2776
2777         /* Check every race */
2778         IDX mon_cnt = 0;
2779         for (IDX i = 0; i < max_r_idx; i++)
2780         {
2781                 /* Access the race */
2782                 monster_race *r_ptr = &r_info[i];
2783
2784                 /* Skip empty race */
2785                 if (!r_ptr->name) continue;
2786
2787                 /* Require known monsters */
2788                 if (!(mode & 0x02) && !cheat_know && !r_ptr->r_sights) continue;
2789
2790                 if (grp_unique)
2791                 {
2792                         if (!(r_ptr->flags1 & RF1_UNIQUE)) continue;
2793                 }
2794
2795                 else if (grp_riding)
2796                 {
2797                         if (!(r_ptr->flags7 & RF7_RIDING)) continue;
2798                 }
2799
2800                 else if (grp_wanted)
2801                 {
2802                         bool wanted = FALSE;
2803                         int j;
2804                         for (j = 0; j < MAX_BOUNTY; j++)
2805                         {
2806                                 if (current_world_ptr->bounty_r_idx[j] == i || current_world_ptr->bounty_r_idx[j] - 10000 == i ||
2807                                         (creature_ptr->today_mon && creature_ptr->today_mon == i))
2808                                 {
2809                                         wanted = TRUE;
2810                                         break;
2811                                 }
2812                         }
2813                         if (!wanted) continue;
2814                 }
2815
2816                 else if (grp_amberite)
2817                 {
2818                         if (!(r_ptr->flags3 & RF3_AMBERITE)) continue;
2819                 }
2820
2821                 else
2822                 {
2823                         /* Check for race in the group */
2824                         if (!my_strchr(group_char, r_ptr->d_char)) continue;
2825                 }
2826
2827                 /* Add the race */
2828                 mon_idx[mon_cnt++] = i;
2829
2830                 /* XXX Hack -- Just checking for non-empty group */
2831                 if (mode & 0x01) break;
2832         }
2833
2834         /* Terminate the list */
2835         mon_idx[mon_cnt] = -1;
2836
2837         int dummy_why;
2838         ang_sort(mon_idx, &dummy_why, mon_cnt, ang_sort_comp_monster_level, ang_sort_swap_hook);
2839
2840         /* Return the number of races */
2841         return mon_cnt;
2842 }
2843
2844
2845 /*
2846  * Description of each monster group.
2847  */
2848 static concptr object_group_text[] =
2849 {
2850 #ifdef JP
2851         "キノコ",    /* "Mushrooms" */
2852         "薬",          /* "Potions" */
2853         "油つぼ",    /* "Flasks" */
2854         "巻物",               /* "Scrolls" */
2855         "指輪",               /* "Rings" */
2856         "アミュレット",   /* "Amulets" */
2857         "笛",          /* "Whistle" */
2858         "光源",               /* "Lanterns" */
2859         "魔法棒",    /* "Wands" */
2860         "杖",          /* "Staffs" */
2861         "ロッド",    /* "Rods" */
2862         "カード",    /* "Cards" */
2863         "キャプチャー・ボール",
2864         "羊皮紙",
2865         "くさび",
2866         "箱",
2867         "人形",
2868         "像",
2869         "ゴミ",
2870         "空のビン",
2871         "骨",
2872         "死体",
2873         "刀剣類",    /* "Swords" */
2874         "鈍器",               /* "Blunt Weapons" */
2875         "長柄武器", /* "Polearms" */
2876         "採掘道具", /* "Diggers" */
2877         "飛び道具", /* "Bows" */
2878         "弾",
2879         "矢",
2880         "ボルト",
2881         "軽装鎧",    /* "Soft Armor" */
2882         "重装鎧",    /* "Hard Armor" */
2883         "ドラゴン鎧",      /* "Dragon Armor" */
2884         "盾",  /* "Shields" */
2885         "クローク", /* "Cloaks" */
2886         "籠手",       /* "Gloves" */
2887         "ヘルメット",      /* "Helms" */
2888         "冠",  /* "Crowns" */
2889         "ブーツ",    /* "Boots" */
2890         "魔法書",
2891         "財宝",
2892         "何か",
2893 #else
2894         "Mushrooms",
2895         "Potions",
2896         "Flasks",
2897         "Scrolls",
2898         "Rings",
2899         "Amulets",
2900         "Whistle",
2901         "Lanterns",
2902         "Wands",
2903         "Staffs",
2904         "Rods",
2905         "Cards",
2906         "Capture Balls",
2907         "Parchments",
2908         "Spikes",
2909         "Boxs",
2910         "Figurines",
2911         "Statues",
2912         "Junks",
2913         "Bottles",
2914         "Skeletons",
2915         "Corpses",
2916         "Swords",
2917         "Blunt Weapons",
2918         "Polearms",
2919         "Diggers",
2920         "Bows",
2921         "Shots",
2922         "Arrows",
2923         "Bolts",
2924         "Soft Armor",
2925         "Hard Armor",
2926         "Dragon Armor",
2927         "Shields",
2928         "Cloaks",
2929         "Gloves",
2930         "Helms",
2931         "Crowns",
2932         "Boots",
2933         "Spellbooks",
2934         "Treasure",
2935         "Something",
2936 #endif
2937         NULL
2938 };
2939
2940
2941 /*
2942  * TVALs of items in each group
2943  */
2944 static byte object_group_tval[] =
2945 {
2946         TV_FOOD,
2947         TV_POTION,
2948         TV_FLASK,
2949         TV_SCROLL,
2950         TV_RING,
2951         TV_AMULET,
2952         TV_WHISTLE,
2953         TV_LITE,
2954         TV_WAND,
2955         TV_STAFF,
2956         TV_ROD,
2957         TV_CARD,
2958         TV_CAPTURE,
2959         TV_PARCHMENT,
2960         TV_SPIKE,
2961         TV_CHEST,
2962         TV_FIGURINE,
2963         TV_STATUE,
2964         TV_JUNK,
2965         TV_BOTTLE,
2966         TV_SKELETON,
2967         TV_CORPSE,
2968         TV_SWORD,
2969         TV_HAFTED,
2970         TV_POLEARM,
2971         TV_DIGGING,
2972         TV_BOW,
2973         TV_SHOT,
2974         TV_ARROW,
2975         TV_BOLT,
2976         TV_SOFT_ARMOR,
2977         TV_HARD_ARMOR,
2978         TV_DRAG_ARMOR,
2979         TV_SHIELD,
2980         TV_CLOAK,
2981         TV_GLOVES,
2982         TV_HELM,
2983         TV_CROWN,
2984         TV_BOOTS,
2985         TV_LIFE_BOOK, /* Hack -- all spellbooks */
2986         TV_GOLD,
2987         0,
2988         0,
2989 };
2990
2991
2992 /*
2993  * Build a list of object indexes in the given group. Return the number
2994  * of objects in the group.
2995  *
2996  * mode & 0x01 : check for non-empty group
2997  * mode & 0x02 : visual operation only
2998  */
2999 static KIND_OBJECT_IDX collect_objects(int grp_cur, KIND_OBJECT_IDX object_idx[], BIT_FLAGS8 mode)
3000 {
3001         KIND_OBJECT_IDX i, object_cnt = 0;
3002         int j, k;
3003
3004         /* Get a list of x_char in this group */
3005         byte group_tval = object_group_tval[grp_cur];
3006
3007         /* Check every object */
3008         for (i = 0; i < max_k_idx; i++)
3009         {
3010                 /* Access the object */
3011                 object_kind *k_ptr = &k_info[i];
3012
3013                 /* Skip empty objects */
3014                 if (!k_ptr->name) continue;
3015
3016                 if (!(mode & 0x02))
3017                 {
3018                         if (!current_world_ptr->wizard)
3019                         {
3020                                 /* Skip non-flavoured objects */
3021                                 if (!k_ptr->flavor) continue;
3022
3023                                 /* Require objects ever seen */
3024                                 if (!k_ptr->aware) continue;
3025                         }
3026
3027                         /* Skip items with no distribution (special artifacts) */
3028                         for (j = 0, k = 0; j < 4; j++) k += k_ptr->chance[j];
3029                         if (!k) continue;
3030                 }
3031
3032                 /* Check for objects in the group */
3033                 if (TV_LIFE_BOOK == group_tval)
3034                 {
3035                         /* Hack -- All spell books */
3036                         if (TV_LIFE_BOOK <= k_ptr->tval && k_ptr->tval <= TV_HEX_BOOK)
3037                         {
3038                                 /* Add the object */
3039                                 object_idx[object_cnt++] = i;
3040                         }
3041                         else continue;
3042                 }
3043                 else if (k_ptr->tval == group_tval)
3044                 {
3045                         /* Add the object */
3046                         object_idx[object_cnt++] = i;
3047                 }
3048                 else continue;
3049
3050                 /* XXX Hack -- Just checking for non-empty group */
3051                 if (mode & 0x01) break;
3052         }
3053
3054         /* Terminate the list */
3055         object_idx[object_cnt] = -1;
3056
3057         /* Return the number of objects */
3058         return object_cnt;
3059 }
3060
3061
3062 /*
3063  * Description of each feature group.
3064  */
3065 static concptr feature_group_text[] =
3066 {
3067         "terrains",
3068         NULL
3069 };
3070
3071
3072 /*
3073  * Build a list of feature indexes in the given group. Return the number
3074  * of features in the group.
3075  *
3076  * mode & 0x01 : check for non-empty group
3077  */
3078 static FEAT_IDX collect_features(FEAT_IDX *feat_idx, BIT_FLAGS8 mode)
3079 {
3080         /* Check every feature */
3081         FEAT_IDX feat_cnt = 0;
3082         for (FEAT_IDX i = 0; i < max_f_idx; i++)
3083         {
3084                 feature_type *f_ptr = &f_info[i];
3085
3086                 /* Skip empty index */
3087                 if (!f_ptr->name) continue;
3088
3089                 /* Skip mimiccing features */
3090                 if (f_ptr->mimic != i) continue;
3091
3092                 /* Add the index */
3093                 feat_idx[feat_cnt++] = i;
3094
3095                 /* XXX Hack -- Just checking for non-empty group */
3096                 if (mode & 0x01) break;
3097         }
3098
3099         /* Terminate the list */
3100         feat_idx[feat_cnt] = -1;
3101
3102         /* Return the number of races */
3103         return feat_cnt;
3104 }
3105
3106
3107 /*
3108  * Hack -- load a screen dump from a file
3109  */
3110 void do_cmd_load_screen(void)
3111 {
3112         TERM_LEN y, x;
3113         TERM_COLOR a = 0;
3114         SYMBOL_CODE c = ' ';
3115         bool okay = TRUE;
3116         FILE *fff;
3117         char buf[1024];
3118         TERM_LEN wid, hgt;
3119
3120         Term_get_size(&wid, &hgt);
3121         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, "dump.txt");
3122
3123         /* Append to the file */
3124         fff = my_fopen(buf, "r");
3125
3126         if (!fff)
3127         {
3128                 msg_format(_("%s を開くことができませんでした。", "Failed to open %s."), buf);
3129                 msg_print(NULL);
3130                 return;
3131         }
3132
3133         screen_save();
3134         Term_clear();
3135
3136         /* Load the screen */
3137         for (y = 0; okay; y++)
3138         {
3139                 /* Get a line of data including control code */
3140                 if (!fgets(buf, 1024, fff)) okay = FALSE;
3141
3142                 /* Get the blank line */
3143                 if (buf[0] == '\n' || buf[0] == '\0') break;
3144
3145                 /* Ignore too large screen image */
3146                 if (y >= hgt) continue;
3147
3148                 /* Show each row */
3149                 for (x = 0; x < wid - 1; x++)
3150                 {
3151                         /* End of line */
3152                         if (buf[x] == '\n' || buf[x] == '\0') break;
3153
3154                         /* Put the attr/char */
3155                         Term_draw(x, y, TERM_WHITE, buf[x]);
3156                 }
3157         }
3158
3159         /* Dump the screen */
3160         for (y = 0; okay; y++)
3161         {
3162                 /* Get a line of data including control code */
3163                 if (!fgets(buf, 1024, fff)) okay = FALSE;
3164
3165                 /* Get the blank line */
3166                 if (buf[0] == '\n' || buf[0] == '\0') break;
3167
3168                 /* Ignore too large screen image */
3169                 if (y >= hgt) continue;
3170
3171                 /* Dump each row */
3172                 for (x = 0; x < wid - 1; x++)
3173                 {
3174                         /* End of line */
3175                         if (buf[x] == '\n' || buf[x] == '\0') break;
3176
3177                         /* Get the attr/char */
3178                         (void)(Term_what(x, y, &a, &c));
3179
3180                         /* Look up the attr */
3181                         for (int i = 0; i < 16; i++)
3182                         {
3183                                 /* Use attr matches */
3184                                 if (hack[i] == buf[x]) a = (byte)i;
3185                         }
3186
3187                         /* Put the attr/char */
3188                         Term_draw(x, y, a, c);
3189                 }
3190         }
3191
3192         my_fclose(fff);
3193
3194         prt(_("ファイルに書き出された画面(記念撮影)をロードしました。", "Screen dump loaded."), 0, 0);
3195
3196         flush();
3197         inkey();
3198
3199         screen_load();
3200 }
3201
3202 // todo なぜこんな中途半端なところに? defineも…
3203 concptr inven_res_label = _("                               酸電火冷毒光闇破轟獄因沌劣 盲怖乱痺透命感消復浮",
3204         "                               AcElFiCoPoLiDkShSoNtNxCaDi BlFeCfFaSeHlEpSdRgLv");
3205
3206 #define IM_FLAG_STR  _("*", "* ")
3207 #define HAS_FLAG_STR _("+", "+ ")
3208 #define NO_FLAG_STR  _("・", ". ")
3209
3210 #define print_im_or_res_flag(IM, RES) \
3211 { \
3212         fputs(have_flag(flgs, (IM)) ? IM_FLAG_STR : \
3213               (have_flag(flgs, (RES)) ? HAS_FLAG_STR : NO_FLAG_STR), fff); \
3214 }
3215
3216 #define print_flag(TR) \
3217 { \
3218         fputs(have_flag(flgs, (TR)) ? HAS_FLAG_STR : NO_FLAG_STR, fff); \
3219 }
3220
3221
3222 /* XTRA HACK RESLIST */
3223 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)
3224 {
3225         GAME_TEXT o_name[MAX_NLEN];
3226         BIT_FLAGS flgs[TR_FLAG_SIZE];
3227
3228         if (!o_ptr->k_idx) return;
3229         if (o_ptr->tval != tval) return;
3230
3231         /* Identified items only */
3232         if (!object_is_known(o_ptr)) return;
3233
3234         /*
3235          * HACK:Ring of Lordly protection and Dragon equipment
3236          * have random resistances.
3237          */
3238         bool is_special_item_type = (object_is_wearable(o_ptr) && object_is_ego(o_ptr))
3239                 || ((tval == TV_AMULET) && (o_ptr->sval == SV_AMULET_RESISTANCE))
3240                 || ((tval == TV_RING) && (o_ptr->sval == SV_RING_LORDLY))
3241                 || ((tval == TV_SHIELD) && (o_ptr->sval == SV_DRAGON_SHIELD))
3242                 || ((tval == TV_HELM) && (o_ptr->sval == SV_DRAGON_HELM))
3243                 || ((tval == TV_GLOVES) && (o_ptr->sval == SV_SET_OF_DRAGON_GLOVES))
3244                 || ((tval == TV_BOOTS) && (o_ptr->sval == SV_PAIR_OF_DRAGON_GREAVE))
3245                 || object_is_artifact(o_ptr);
3246         if (!is_special_item_type)
3247         {
3248                 return;
3249         }
3250
3251         int i = 0;
3252         object_desc(creature_ptr, o_name, o_ptr, OD_NAME_ONLY);
3253
3254         while (o_name[i] && (i < 26))
3255         {
3256 #ifdef JP
3257                 if (iskanji(o_name[i])) i++;
3258 #endif
3259                 i++;
3260         }
3261
3262         if (i < 28)
3263         {
3264                 while (i < 28)
3265                 {
3266                         o_name[i] = ' '; i++;
3267                 }
3268         }
3269
3270         o_name[i] = '\0';
3271
3272         fprintf(fff, "%s %s", where, o_name);
3273
3274         if (!OBJECT_IS_FULL_KNOWN(o_ptr))
3275         {
3276                 fputs(_("-------不明--------------- -------不明---------\n",
3277                         "-------unknown------------ -------unknown------\n"), fff);
3278         }
3279         else
3280         {
3281                 object_flags_known(o_ptr, flgs);
3282
3283                 print_im_or_res_flag(TR_IM_ACID, TR_RES_ACID);
3284                 print_im_or_res_flag(TR_IM_ELEC, TR_RES_ELEC);
3285                 print_im_or_res_flag(TR_IM_FIRE, TR_RES_FIRE);
3286                 print_im_or_res_flag(TR_IM_COLD, TR_RES_COLD);
3287                 print_flag(TR_RES_POIS);
3288                 print_flag(TR_RES_LITE);
3289                 print_flag(TR_RES_DARK);
3290                 print_flag(TR_RES_SHARDS);
3291                 print_flag(TR_RES_SOUND);
3292                 print_flag(TR_RES_NETHER);
3293                 print_flag(TR_RES_NEXUS);
3294                 print_flag(TR_RES_CHAOS);
3295                 print_flag(TR_RES_DISEN);
3296
3297                 fputs(" ", fff);
3298
3299                 print_flag(TR_RES_BLIND);
3300                 print_flag(TR_RES_FEAR);
3301                 print_flag(TR_RES_CONF);
3302                 print_flag(TR_FREE_ACT);
3303                 print_flag(TR_SEE_INVIS);
3304                 print_flag(TR_HOLD_EXP);
3305                 print_flag(TR_TELEPATHY);
3306                 print_flag(TR_SLOW_DIGEST);
3307                 print_flag(TR_REGEN);
3308                 print_flag(TR_LEVITATION);
3309
3310                 fputc('\n', fff);
3311         }
3312
3313         (*j)++;
3314         if (*j == 9)
3315         {
3316                 *j = 0;
3317                 fprintf(fff, "%s\n", inven_res_label);
3318         }
3319 }
3320
3321 /*
3322  * Display *ID* ed weapons/armors's resistances
3323  */
3324 static void do_cmd_knowledge_inven(player_type *creature_ptr)
3325 {
3326         FILE *fff;
3327         GAME_TEXT file_name[1024];
3328         store_type  *st_ptr;
3329         OBJECT_TYPE_VALUE tval;
3330         int i = 0;
3331         int j = 0;
3332
3333         char where[32];
3334
3335         /* Open a new file */
3336         fff = my_fopen_temp(file_name, 1024);
3337         if (!fff)
3338         {
3339                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
3340                 msg_print(NULL);
3341                 return;
3342         }
3343
3344         fprintf(fff, "%s\n", inven_res_label);
3345
3346         for (tval = TV_WEARABLE_BEGIN; tval <= TV_WEARABLE_END; tval++)
3347         {
3348                 if (j != 0)
3349                 {
3350                         for (; j < 9; j++) fputc('\n', fff);
3351                         j = 0;
3352                         fprintf(fff, "%s\n", inven_res_label);
3353                 }
3354
3355                 strcpy(where, _("装", "E "));
3356                 for (i = INVEN_RARM; i < INVEN_TOTAL; i++)
3357                 {
3358                         do_cmd_knowledge_inven_aux(creature_ptr, fff, &creature_ptr->inventory_list[i], &j, tval, where);
3359                 }
3360
3361                 strcpy(where, _("持", "I "));
3362                 for (i = 0; i < INVEN_PACK; i++)
3363                 {
3364                         do_cmd_knowledge_inven_aux(creature_ptr, fff, &creature_ptr->inventory_list[i], &j, tval, where);
3365                 }
3366
3367                 st_ptr = &town_info[1].store[STORE_HOME];
3368                 strcpy(where, _("家", "H "));
3369                 for (i = 0; i < st_ptr->stock_num; i++)
3370                 {
3371                         do_cmd_knowledge_inven_aux(creature_ptr, fff, &st_ptr->stock[i], &j, tval, where);
3372                 }
3373         }
3374
3375         my_fclose(fff);
3376
3377         /* Display the file contents */
3378         (void)show_file(creature_ptr, TRUE, file_name, _("*鑑定*済み武器/防具の耐性リスト", "Resistances of *identified* equipment"), 0, 0);
3379         fd_kill(file_name);
3380 }
3381
3382
3383 void do_cmd_save_screen_html_aux(char *filename, int message)
3384 {
3385         concptr tags[4] = {
3386                 "HEADER_START:",
3387                 "HEADER_END:",
3388                 "FOOTER_START:",
3389                 "FOOTER_END:",
3390         };
3391         concptr html_head[] = {
3392                 "<html>\n<body text=\"#ffffff\" bgcolor=\"#000000\">\n",
3393                 "<pre>",
3394                 0,
3395         };
3396         concptr html_foot[] = {
3397                 "</pre>\n",
3398                 "</body>\n</html>\n",
3399                 0,
3400         };
3401
3402         TERM_LEN wid, hgt;
3403         Term_get_size(&wid, &hgt);
3404
3405         /* File type is "TEXT" */
3406         FILE_TYPE(FILE_TYPE_TEXT);
3407
3408         /* Append to the file */
3409         FILE *fff;
3410         fff = my_fopen(filename, "w");
3411
3412         if (!fff)
3413         {
3414                 if (message)
3415                 {
3416                         msg_format(_("ファイル %s を開けませんでした。", "Failed to open file %s."), filename);
3417                         msg_print(NULL);
3418                 }
3419
3420                 return;
3421         }
3422
3423         if (message) screen_save();
3424         char buf[2048];
3425         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, "htmldump.prf");
3426         FILE *tmpfff;
3427         tmpfff = my_fopen(buf, "r");
3428         if (!tmpfff)
3429         {
3430                 for (int i = 0; html_head[i]; i++)
3431                         fputs(html_head[i], fff);
3432         }
3433         else
3434         {
3435                 bool is_first_line = TRUE;
3436                 while (!my_fgets(tmpfff, buf, sizeof(buf)))
3437                 {
3438                         if (is_first_line)
3439                         {
3440                                 if (strncmp(buf, tags[0], strlen(tags[0])) == 0)
3441                                         is_first_line = FALSE;
3442                         }
3443                         else
3444                         {
3445                                 if (strncmp(buf, tags[1], strlen(tags[1])) == 0)
3446                                         break;
3447                                 fprintf(fff, "%s\n", buf);
3448                         }
3449                 }
3450         }
3451
3452         /* Dump the screen */
3453         for (TERM_LEN y = 0; y < hgt; y++)
3454         {
3455                 /* Start the row */
3456                 if (y != 0) fprintf(fff, "\n");
3457
3458                 /* Dump each row */
3459                 TERM_COLOR a = 0, old_a = 0;
3460                 char c = ' ';
3461                 for (TERM_LEN x = 0; x < wid - 1; x++)
3462                 {
3463                         concptr cc = NULL;
3464                         /* Get the attr/char */
3465                         (void)(Term_what(x, y, &a, &c));
3466
3467                         switch (c)
3468                         {
3469                         case '&': cc = "&amp;"; break;
3470                         case '<': cc = "&lt;"; break;
3471                         case '>': cc = "&gt;"; break;
3472 #ifdef WINDOWS
3473                         case 0x1f: c = '.'; break;
3474                         case 0x7f: c = (a == 0x09) ? '%' : '#'; break;
3475 #endif
3476                         }
3477
3478                         a = a & 0x0F;
3479                         if ((y == 0 && x == 0) || a != old_a)
3480                         {
3481                                 int rv = angband_color_table[a][1];
3482                                 int gv = angband_color_table[a][2];
3483                                 int bv = angband_color_table[a][3];
3484                                 fprintf(fff, "%s<font color=\"#%02x%02x%02x\">",
3485                                         ((y == 0 && x == 0) ? "" : "</font>"), rv, gv, bv);
3486                                 old_a = a;
3487                         }
3488
3489                         if (cc)
3490                                 fprintf(fff, "%s", cc);
3491                         else
3492                                 fprintf(fff, "%c", c);
3493                 }
3494         }
3495
3496         fprintf(fff, "</font>");
3497
3498         if (!tmpfff)
3499         {
3500                 for (int i = 0; html_foot[i]; i++)
3501                         fputs(html_foot[i], fff);
3502         }
3503         else
3504         {
3505                 rewind(tmpfff);
3506                 bool is_first_line = TRUE;
3507                 while (!my_fgets(tmpfff, buf, sizeof(buf)))
3508                 {
3509                         if (is_first_line)
3510                         {
3511                                 if (strncmp(buf, tags[2], strlen(tags[2])) == 0)
3512                                         is_first_line = FALSE;
3513                         }
3514                         else
3515                         {
3516                                 if (strncmp(buf, tags[3], strlen(tags[3])) == 0)
3517                                         break;
3518                                 fprintf(fff, "%s\n", buf);
3519                         }
3520                 }
3521
3522                 my_fclose(tmpfff);
3523         }
3524
3525         /* Skip a line */
3526         fprintf(fff, "\n");
3527         my_fclose(fff);
3528
3529         if (message)
3530         {
3531                 msg_print(_("画面(記念撮影)をファイルに書き出しました。", "Screen dump saved."));
3532                 msg_print(NULL);
3533         }
3534
3535         if (message)
3536                 screen_load();
3537 }
3538
3539 /*
3540  * Hack -- save a screen dump to a file
3541  */
3542 static void do_cmd_save_screen_html(void)
3543 {
3544         char buf[1024], tmp[256] = "screen.html";
3545
3546         if (!get_string(_("ファイル名: ", "File name: "), tmp, 80))
3547                 return;
3548         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, tmp);
3549
3550         msg_print(NULL);
3551
3552         do_cmd_save_screen_html_aux(buf, 1);
3553 }
3554
3555
3556 /*
3557  * Redefinable "save_screen" action
3558  */
3559 void(*screendump_aux)(void) = NULL;
3560
3561
3562 /*
3563  * Save a screen dump to a file
3564  * @param creature_ptr プレーヤーへの参照ポインタ
3565  * @return なし
3566  */
3567 void do_cmd_save_screen(player_type *creature_ptr)
3568 {
3569         prt(_("記念撮影しますか? [(y)es/(h)tml/(n)o] ", "Save screen dump? [(y)es/(h)tml/(n)o] "), 0, 0);
3570         bool html_dump = FALSE;
3571         while (TRUE)
3572         {
3573                 char c = inkey();
3574                 if (c == 'Y' || c == 'y')
3575                         break;
3576                 else if (c == 'H' || c == 'h')
3577                 {
3578                         html_dump = TRUE;
3579                         break;
3580                 }
3581                 else
3582                 {
3583                         prt("", 0, 0);
3584                         return;
3585                 }
3586         }
3587
3588         int wid, hgt;
3589         Term_get_size(&wid, &hgt);
3590
3591         bool old_use_graphics = use_graphics;
3592         if (old_use_graphics)
3593         {
3594                 use_graphics = FALSE;
3595                 reset_visuals(creature_ptr);
3596                 creature_ptr->redraw |= (PR_WIPE | PR_BASIC | PR_EXTRA | PR_MAP | PR_EQUIPPY);
3597                 handle_stuff(creature_ptr);
3598         }
3599
3600         if (html_dump)
3601         {
3602                 do_cmd_save_screen_html();
3603                 do_cmd_redraw(creature_ptr);
3604         }
3605
3606         /* Do we use a special screendump function ? */
3607         else if (screendump_aux)
3608         {
3609                 /* Dump the screen to a graphics file */
3610                 (*screendump_aux)();
3611         }
3612         else /* Dump the screen as text */
3613         {
3614                 TERM_LEN y, x;
3615                 TERM_COLOR a = 0;
3616                 SYMBOL_CODE c = ' ';
3617                 FILE *fff;
3618                 char buf[1024];
3619                 path_build(buf, sizeof(buf), ANGBAND_DIR_USER, "dump.txt");
3620
3621                 /* File type is "TEXT" */
3622                 FILE_TYPE(FILE_TYPE_TEXT);
3623
3624                 /* Append to the file */
3625                 fff = my_fopen(buf, "w");
3626
3627                 if (!fff)
3628                 {
3629                         msg_format(_("ファイル %s を開けませんでした。", "Failed to open file %s."), buf);
3630                         msg_print(NULL);
3631                         return;
3632                 }
3633
3634                 screen_save();
3635
3636                 /* Dump the screen */
3637                 for (y = 0; y < hgt; y++)
3638                 {
3639                         /* Dump each row */
3640                         for (x = 0; x < wid - 1; x++)
3641                         {
3642                                 /* Get the attr/char */
3643                                 (void)(Term_what(x, y, &a, &c));
3644
3645                                 /* Dump it */
3646                                 buf[x] = c;
3647                         }
3648
3649                         /* Terminate */
3650                         buf[x] = '\0';
3651
3652                         /* End the row */
3653                         fprintf(fff, "%s\n", buf);
3654                 }
3655
3656                 /* Skip a line */
3657                 fprintf(fff, "\n");
3658
3659
3660                 /* Dump the screen */
3661                 for (y = 0; y < hgt; y++)
3662                 {
3663                         /* Dump each row */
3664                         for (x = 0; x < wid - 1; x++)
3665                         {
3666                                 /* Get the attr/char */
3667                                 (void)(Term_what(x, y, &a, &c));
3668
3669                                 /* Dump it */
3670                                 buf[x] = hack[a & 0x0F];
3671                         }
3672
3673                         /* Terminate */
3674                         buf[x] = '\0';
3675
3676                         /* End the row */
3677                         fprintf(fff, "%s\n", buf);
3678                 }
3679
3680                 /* Skip a line */
3681                 fprintf(fff, "\n");
3682                 my_fclose(fff);
3683
3684                 msg_print(_("画面(記念撮影)をファイルに書き出しました。", "Screen dump saved."));
3685                 msg_print(NULL);
3686                 screen_load();
3687         }
3688
3689         if (!old_use_graphics) return;
3690
3691         use_graphics = TRUE;
3692         reset_visuals(creature_ptr);
3693         creature_ptr->redraw |= (PR_WIPE | PR_BASIC | PR_EXTRA | PR_MAP | PR_EQUIPPY);
3694         handle_stuff(creature_ptr);
3695 }
3696
3697
3698 /*
3699  * todo okay = 既知のアーティファクト? と思われるが確証がない
3700  * 分かりやすい変数名へ変更求む&万が一未知である旨の配列なら負論理なのでゴソッと差し替えるべき
3701  * Check the status of "artifacts"
3702  * @param player_ptr プレーヤーへの参照ポインタ
3703  * @return なし
3704  */
3705 static void do_cmd_knowledge_artifacts(player_type *player_ptr)
3706 {
3707         /* Open a new file */
3708         FILE *fff;
3709         GAME_TEXT file_name[1024];
3710         fff = my_fopen_temp(file_name, 1024);
3711         if (!fff)
3712         {
3713                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
3714                 msg_print(NULL);
3715                 return;
3716         }
3717
3718         /* Allocate the "who" array */
3719         ARTIFACT_IDX *who;
3720         C_MAKE(who, max_a_idx, ARTIFACT_IDX);
3721
3722         /* Allocate the "okay" array */
3723         bool *okay;
3724         C_MAKE(okay, max_a_idx, bool);
3725
3726         /* Scan the artifacts */
3727         for (ARTIFACT_IDX k = 0; k < max_a_idx; k++)
3728         {
3729                 artifact_type *a_ptr = &a_info[k];
3730
3731                 /* Default */
3732                 okay[k] = FALSE;
3733
3734                 /* Skip "empty" artifacts */
3735                 if (!a_ptr->name) continue;
3736
3737                 /* Skip "uncreated" artifacts */
3738                 if (!a_ptr->cur_num) continue;
3739
3740                 /* Assume okay */
3741                 okay[k] = TRUE;
3742         }
3743
3744         /* Check the dungeon */
3745         for (POSITION y = 0; y < player_ptr->current_floor_ptr->height; y++)
3746         {
3747                 for (POSITION x = 0; x < player_ptr->current_floor_ptr->width; x++)
3748                 {
3749                         grid_type *g_ptr = &player_ptr->current_floor_ptr->grid_array[y][x];
3750
3751                         OBJECT_IDX this_o_idx, next_o_idx = 0;
3752
3753                         /* Scan all objects in the grid */
3754                         for (this_o_idx = g_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx)
3755                         {
3756                                 object_type *o_ptr;
3757                                 o_ptr = &player_ptr->current_floor_ptr->o_list[this_o_idx];
3758                                 next_o_idx = o_ptr->next_o_idx;
3759
3760                                 /* Ignore non-artifacts */
3761                                 if (!object_is_fixed_artifact(o_ptr)) continue;
3762
3763                                 /* Ignore known items */
3764                                 if (object_is_known(o_ptr)) continue;
3765
3766                                 /* Note the artifact */
3767                                 okay[o_ptr->name1] = FALSE;
3768                         }
3769                 }
3770         }
3771
3772         /* Check the player_ptr->inventory_list and equipment */
3773         for (ARTIFACT_IDX i = 0; i < INVEN_TOTAL; i++)
3774         {
3775                 object_type *o_ptr = &player_ptr->inventory_list[i];
3776
3777                 /* Ignore non-objects */
3778                 if (!o_ptr->k_idx) continue;
3779
3780                 /* Ignore non-artifacts */
3781                 if (!object_is_fixed_artifact(o_ptr)) continue;
3782
3783                 /* Ignore known items */
3784                 if (object_is_known(o_ptr)) continue;
3785
3786                 /* Note the artifact */
3787                 okay[o_ptr->name1] = FALSE;
3788         }
3789
3790         int n = 0;
3791         for (ARTIFACT_IDX k = 0; k < max_a_idx; k++)
3792         {
3793                 if (okay[k]) who[n++] = k;
3794         }
3795
3796         u16b why = 3;
3797         ang_sort(who, &why, n, ang_sort_art_comp, ang_sort_art_swap);
3798
3799         /* Scan the artifacts */
3800         for (ARTIFACT_IDX k = 0; k < n; k++)
3801         {
3802                 artifact_type *a_ptr = &a_info[who[k]];
3803                 GAME_TEXT base_name[MAX_NLEN];
3804                 strcpy(base_name, _("未知の伝説のアイテム", "Unknown Artifact"));
3805
3806                 /* Obtain the base object type */
3807                 ARTIFACT_IDX z = lookup_kind(a_ptr->tval, a_ptr->sval);
3808
3809                 /* Real object */
3810                 if (z)
3811                 {
3812                         object_type forge;
3813                         object_type *q_ptr;
3814                         q_ptr = &forge;
3815
3816                         /* Create fake object */
3817                         object_prep(q_ptr, z);
3818
3819                         /* Make it an artifact */
3820                         q_ptr->name1 = (byte)who[k];
3821
3822                         /* Display as if known */
3823                         q_ptr->ident |= IDENT_STORE;
3824
3825                         /* Describe the artifact */
3826                         object_desc(player_ptr, base_name, q_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY));
3827                 }
3828
3829                 /* Hack -- Build the artifact name */
3830                 fprintf(fff, _("     %s\n", "     The %s\n"), base_name);
3831         }
3832
3833         /* Free the "who" array */
3834         C_KILL(who, max_a_idx, ARTIFACT_IDX);
3835
3836         /* Free the "okay" array */
3837         C_KILL(okay, max_a_idx, bool);
3838         my_fclose(fff);
3839
3840         /* Display the file contents */
3841         (void)show_file(player_ptr, TRUE, file_name, _("既知の伝説のアイテム", "Artifacts Seen"), 0, 0);
3842         fd_kill(file_name);
3843 }
3844
3845
3846 /*
3847  * Display known uniques
3848  * With "XTRA HACK UNIQHIST" (Originally from XAngband)
3849  */
3850 static void do_cmd_knowledge_uniques(player_type *creature_ptr)
3851 {
3852         u16b why = 2;
3853         IDX *who;
3854
3855         FILE *fff;
3856
3857         GAME_TEXT file_name[1024];
3858
3859         int n_alive[10];
3860         int n_alive_surface = 0;
3861         int n_alive_over100 = 0;
3862         int n_alive_total = 0;
3863         int max_lev = -1;
3864
3865         for (IDX i = 0; i < 10; i++) n_alive[i] = 0;
3866
3867         /* Open a new file */
3868         fff = my_fopen_temp(file_name, 1024);
3869
3870         if (!fff)
3871         {
3872                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
3873                 msg_print(NULL);
3874                 return;
3875         }
3876
3877         /* Allocate the "who" array */
3878         C_MAKE(who, max_r_idx, MONRACE_IDX);
3879
3880         /* Scan the monsters */
3881         int n = 0;
3882         for (IDX i = 1; i < max_r_idx; i++)
3883         {
3884                 monster_race *r_ptr = &r_info[i];
3885                 int          lev;
3886
3887                 if (!r_ptr->name) continue;
3888
3889                 /* Require unique monsters */
3890                 if (!(r_ptr->flags1 & RF1_UNIQUE)) continue;
3891
3892                 /* Only display "known" uniques */
3893                 if (!cheat_know && !r_ptr->r_sights) continue;
3894
3895                 /* Only print rarity <= 100 uniques */
3896                 if (!r_ptr->rarity || ((r_ptr->rarity > 100) && !(r_ptr->flags1 & RF1_QUESTOR))) continue;
3897
3898                 /* Only "alive" uniques */
3899                 if (r_ptr->max_num == 0) continue;
3900
3901                 if (r_ptr->level)
3902                 {
3903                         lev = (r_ptr->level - 1) / 10;
3904                         if (lev < 10)
3905                         {
3906                                 n_alive[lev]++;
3907                                 if (max_lev < lev) max_lev = lev;
3908                         }
3909                         else n_alive_over100++;
3910                 }
3911                 else n_alive_surface++;
3912
3913                 /* Collect "appropriate" monsters */
3914                 who[n++] = i;
3915         }
3916
3917         /* Sort the array by dungeon depth of monsters */
3918         ang_sort(who, &why, n, ang_sort_comp_hook, ang_sort_swap_hook);
3919
3920         if (n_alive_surface)
3921         {
3922                 fprintf(fff, _("     地上  生存: %3d体\n", "      Surface  alive: %3d\n"), n_alive_surface);
3923                 n_alive_total += n_alive_surface;
3924         }
3925
3926         for (IDX i = 0; i <= max_lev; i++)
3927         {
3928                 fprintf(fff, _("%3d-%3d階  生存: %3d体\n", "Level %3d-%3d  alive: %3d\n"), 1 + i * 10, 10 + i * 10, n_alive[i]);
3929                 n_alive_total += n_alive[i];
3930         }
3931
3932         if (n_alive_over100)
3933         {
3934                 fprintf(fff, _("101-   階  生存: %3d体\n", "Level 101-     alive: %3d\n"), n_alive_over100);
3935                 n_alive_total += n_alive_over100;
3936         }
3937
3938         if (n_alive_total)
3939         {
3940                 fputs(_("---------  -----------\n", "-------------  ----------\n"), fff);
3941                 fprintf(fff, _("     合計  生存: %3d体\n\n", "        Total  alive: %3d\n\n"), n_alive_total);
3942         }
3943         else
3944         {
3945                 fputs(_("現在は既知の生存ユニークはいません。\n", "No known uniques alive.\n"), fff);
3946         }
3947
3948         /* Scan the monster races */
3949         for (int k = 0; k < n; k++)
3950         {
3951                 monster_race *r_ptr = &r_info[who[k]];
3952                 fprintf(fff, _("     %s (レベル%d)\n", "     %s (level %d)\n"), r_name + r_ptr->name, (int)r_ptr->level);
3953         }
3954
3955         /* Free the "who" array */
3956         C_KILL(who, max_r_idx, s16b);
3957         my_fclose(fff);
3958
3959         /* Display the file contents */
3960         (void)show_file(creature_ptr, TRUE, file_name, _("まだ生きているユニーク・モンスター", "Alive Uniques"), 0, 0);
3961         fd_kill(file_name);
3962 }
3963
3964
3965 /*
3966  * Display weapon-exp
3967  */
3968 static void do_cmd_knowledge_weapon_exp(player_type *creature_ptr)
3969 {
3970         /* Open a new file */
3971         FILE *fff;
3972         GAME_TEXT file_name[1024];
3973         fff = my_fopen_temp(file_name, 1024);
3974         if (!fff)
3975         {
3976                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
3977                 msg_print(NULL);
3978                 return;
3979         }
3980
3981         for (int i = 0; i < 5; i++)
3982         {
3983                 for (int num = 0; num < 64; num++)
3984                 {
3985                         SUB_EXP weapon_exp;
3986                         char tmp[30];
3987                         for (KIND_OBJECT_IDX j = 0; j < max_k_idx; j++)
3988                         {
3989                                 object_kind *k_ptr = &k_info[j];
3990
3991                                 if ((k_ptr->tval != TV_SWORD - i) || (k_ptr->sval != num)) continue;
3992                                 if ((k_ptr->tval == TV_BOW) && (k_ptr->sval == SV_CRIMSON || k_ptr->sval == SV_HARP)) continue;
3993
3994                                 weapon_exp = creature_ptr->weapon_exp[4 - i][num];
3995                                 strip_name(tmp, j);
3996                                 fprintf(fff, "%-25s ", tmp);
3997                                 if (weapon_exp >= s_info[creature_ptr->pclass].w_max[4 - i][num]) fprintf(fff, "!");
3998                                 else fprintf(fff, " ");
3999                                 fprintf(fff, "%s", exp_level_str[weapon_exp_level(weapon_exp)]);
4000                                 if (cheat_xtra) fprintf(fff, " %d", weapon_exp);
4001                                 fprintf(fff, "\n");
4002                                 break;
4003                         }
4004                 }
4005         }
4006
4007         my_fclose(fff);
4008
4009         /* Display the file contents */
4010         (void)show_file(creature_ptr, TRUE, file_name, _("武器の経験値", "Weapon Proficiency"), 0, 0);
4011         fd_kill(file_name);
4012 }
4013
4014
4015 /*!
4016  * @brief 魔法の経験値を表示するコマンドのメインルーチン
4017  * Display spell-exp
4018  * @return なし
4019  */
4020 static void do_cmd_knowledge_spell_exp(player_type *creature_ptr)
4021 {
4022         /* Open a new file */
4023         FILE *fff;
4024         GAME_TEXT file_name[1024];
4025         fff = my_fopen_temp(file_name, 1024);
4026         if (!fff)
4027         {
4028                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
4029                 msg_print(NULL);
4030                 return;
4031         }
4032
4033         if (creature_ptr->realm1 != REALM_NONE)
4034         {
4035                 fprintf(fff, _("%sの魔法書\n", "%s Spellbook\n"), realm_names[creature_ptr->realm1]);
4036                 for (SPELL_IDX i = 0; i < 32; i++)
4037                 {
4038                         const magic_type *s_ptr;
4039                         if (!is_magic(creature_ptr->realm1))
4040                         {
4041                                 s_ptr = &technic_info[creature_ptr->realm1 - MIN_TECHNIC][i];
4042                         }
4043                         else
4044                         {
4045                                 s_ptr = &mp_ptr->info[creature_ptr->realm1 - 1][i];
4046                         }
4047
4048                         if (s_ptr->slevel >= 99) continue;
4049                         SUB_EXP spell_exp = creature_ptr->spell_exp[i];
4050                         int exp_level = spell_exp_level(spell_exp);
4051                         fprintf(fff, "%-25s ", exe_spell(creature_ptr, creature_ptr->realm1, i, SPELL_NAME));
4052                         if (creature_ptr->realm1 == REALM_HISSATSU)
4053                                 fprintf(fff, "[--]");
4054                         else
4055                         {
4056                                 if (exp_level >= EXP_LEVEL_MASTER) fprintf(fff, "!");
4057                                 else fprintf(fff, " ");
4058                                 fprintf(fff, "%s", exp_level_str[exp_level]);
4059                         }
4060
4061                         if (cheat_xtra) fprintf(fff, " %d", spell_exp);
4062                         fprintf(fff, "\n");
4063                 }
4064         }
4065
4066         if (creature_ptr->realm2 != REALM_NONE)
4067         {
4068                 fprintf(fff, _("%sの魔法書\n", "\n%s Spellbook\n"), realm_names[creature_ptr->realm2]);
4069                 for (SPELL_IDX i = 0; i < 32; i++)
4070                 {
4071                         const magic_type *s_ptr;
4072                         if (!is_magic(creature_ptr->realm1))
4073                         {
4074                                 s_ptr = &technic_info[creature_ptr->realm2 - MIN_TECHNIC][i];
4075                         }
4076                         else
4077                         {
4078                                 s_ptr = &mp_ptr->info[creature_ptr->realm2 - 1][i];
4079                         }
4080
4081                         if (s_ptr->slevel >= 99) continue;
4082
4083                         SUB_EXP spell_exp = creature_ptr->spell_exp[i + 32];
4084                         int exp_level = spell_exp_level(spell_exp);
4085                         fprintf(fff, "%-25s ", exe_spell(creature_ptr, creature_ptr->realm2, i, SPELL_NAME));
4086                         if (exp_level >= EXP_LEVEL_EXPERT) fprintf(fff, "!");
4087                         else fprintf(fff, " ");
4088                         fprintf(fff, "%s", exp_level_str[exp_level]);
4089                         if (cheat_xtra) fprintf(fff, " %d", spell_exp);
4090                         fprintf(fff, "\n");
4091                 }
4092         }
4093
4094         my_fclose(fff);
4095
4096         /* Display the file contents */
4097         (void)show_file(creature_ptr, TRUE, file_name, _("魔法の経験値", "Spell Proficiency"), 0, 0);
4098         fd_kill(file_name);
4099 }
4100
4101
4102 /*!
4103  * @brief スキル情報を表示するコマンドのメインルーチン /
4104  * Display skill-exp
4105  * @return なし
4106  */
4107 static void do_cmd_knowledge_skill_exp(player_type *creature_ptr)
4108 {
4109         char skill_name[GINOU_TEMPMAX][20] =
4110         {
4111                 _("マーシャルアーツ", "Martial Arts    "),
4112                 _("二刀流          ", "Dual Wielding   "),
4113                 _("乗馬            ", "Riding          "),
4114                 _("盾              ", "Shield          ")
4115         };
4116
4117         /* Open a new file */
4118         FILE *fff;
4119         char file_name[1024];
4120         fff = my_fopen_temp(file_name, 1024);
4121         if (!fff)
4122         {
4123                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
4124                 msg_print(NULL);
4125                 return;
4126         }
4127
4128         for (int i = 0; i < GINOU_TEMPMAX; i++)
4129         {
4130                 int skill_exp = creature_ptr->skill_exp[i];
4131                 fprintf(fff, "%-20s ", skill_name[i]);
4132                 if (skill_exp >= s_info[creature_ptr->pclass].s_max[i]) fprintf(fff, "!");
4133                 else fprintf(fff, " ");
4134                 fprintf(fff, "%s", exp_level_str[(i == GINOU_RIDING) ? riding_exp_level(skill_exp) : weapon_exp_level(skill_exp)]);
4135                 if (cheat_xtra) fprintf(fff, " %d", skill_exp);
4136                 fprintf(fff, "\n");
4137         }
4138
4139         my_fclose(fff);
4140
4141         /* Display the file contents */
4142         (void)show_file(creature_ptr, TRUE, file_name, _("技能の経験値", "Miscellaneous Proficiency"), 0, 0);
4143         fd_kill(file_name);
4144 }
4145
4146
4147 /*!
4148  * @brief 現在のペットを表示するコマンドのメインルーチン /
4149  * Display current pets
4150  * @param creature_ptr プレーヤーへの参照ポインタ
4151  * @return なし
4152  */
4153 static void do_cmd_knowledge_pets(player_type *creature_ptr)
4154 {
4155         /* Open a new file */
4156         GAME_TEXT file_name[1024];
4157         FILE *fff;
4158         fff = my_fopen_temp(file_name, 1024);
4159         if (!fff)
4160         {
4161                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
4162                 msg_print(NULL);
4163                 return;
4164         }
4165
4166         /* Process the monsters (backwards) */
4167         monster_type *m_ptr;
4168         GAME_TEXT pet_name[MAX_NLEN];
4169         int t_friends = 0;
4170         for (int i = creature_ptr->current_floor_ptr->m_max - 1; i >= 1; i--)
4171         {
4172                 m_ptr = &creature_ptr->current_floor_ptr->m_list[i];
4173
4174                 /* Ignore "dead" monsters */
4175                 if (!monster_is_valid(m_ptr)) continue;
4176
4177                 /* Calculate "upkeep" for pets */
4178                 if (!is_pet(m_ptr)) continue;
4179
4180                 t_friends++;
4181                 monster_desc(creature_ptr, pet_name, m_ptr, MD_ASSUME_VISIBLE | MD_INDEF_VISIBLE);
4182                 fprintf(fff, "%s (%s)\n", pet_name, look_mon_desc(m_ptr, 0x00));
4183         }
4184
4185         int show_upkeep = calculate_upkeep(creature_ptr);
4186
4187         fprintf(fff, "----------------------------------------------\n");
4188 #ifdef JP
4189         fprintf(fff, "    合計: %d 体のペット\n", t_friends);
4190 #else
4191         fprintf(fff, "   Total: %d pet%s.\n", t_friends, (t_friends == 1 ? "" : "s"));
4192 #endif
4193         fprintf(fff, _(" 維持コスト: %d%% MP\n", "   Upkeep: %d%% mana.\n"), show_upkeep);
4194
4195         my_fclose(fff);
4196
4197         /* Display the file contents */
4198         (void)show_file(creature_ptr, TRUE, file_name, _("現在のペット", "Current Pets"), 0, 0);
4199         fd_kill(file_name);
4200 }
4201
4202
4203 /*!
4204  * @brief 現在のペットを表示するコマンドのメインルーチン /
4205  * @param creature_ptr プレーヤーへの参照ポインタ
4206  * Total kill count
4207  * @return なし
4208  * @note the player ghosts are ignored.
4209  */
4210 static void do_cmd_knowledge_kill_count(player_type *creature_ptr)
4211 {
4212         /* Open a new file */
4213         FILE *fff;
4214         GAME_TEXT file_name[1024];
4215         fff = my_fopen_temp(file_name, 1024);
4216         if (!fff)
4217         {
4218                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
4219                 msg_print(NULL);
4220                 return;
4221         }
4222
4223         /* Allocate the "who" array */
4224         MONRACE_IDX *who;
4225         C_MAKE(who, max_r_idx, MONRACE_IDX);
4226
4227         s32b total = 0;
4228         {
4229                 /* Monsters slain */
4230                 for (int kk = 1; kk < max_r_idx; kk++)
4231                 {
4232                         monster_race *r_ptr = &r_info[kk];
4233
4234                         if (r_ptr->flags1 & (RF1_UNIQUE))
4235                         {
4236                                 bool dead = (r_ptr->max_num == 0);
4237
4238                                 if (dead)
4239                                 {
4240                                         total++;
4241                                 }
4242                         }
4243                         else
4244                         {
4245                                 MONSTER_NUMBER this_monster = r_ptr->r_pkills;
4246
4247                                 if (this_monster > 0)
4248                                 {
4249                                         total += this_monster;
4250                                 }
4251                         }
4252                 }
4253
4254                 if (total < 1)
4255                         fprintf(fff, _("あなたはまだ敵を倒していない。\n\n", "You have defeated no enemies yet.\n\n"));
4256                 else
4257 #ifdef JP
4258                         fprintf(fff, "あなたは%ld体の敵を倒している。\n\n", (long int)total);
4259 #else
4260                         fprintf(fff, "You have defeated %ld %s.\n\n", (long int)total, (total == 1) ? "enemy" : "enemies");
4261 #endif
4262         }
4263
4264         total = 0;
4265
4266         /* Scan the monsters */
4267         int n = 0;
4268         for (MONRACE_IDX i = 1; i < max_r_idx; i++)
4269         {
4270                 monster_race *r_ptr = &r_info[i];
4271
4272                 /* Use that monster */
4273                 if (r_ptr->name) who[n++] = i;
4274         }
4275
4276         /* Sort the array by dungeon depth of monsters */
4277         u16b why = 2;
4278         ang_sort(who, &why, n, ang_sort_comp_hook, ang_sort_swap_hook);
4279
4280         /* Scan the monster races */
4281         for (int k = 0; k < n; k++)
4282         {
4283                 monster_race *r_ptr = &r_info[who[k]];
4284
4285                 if (r_ptr->flags1 & (RF1_UNIQUE))
4286                 {
4287                         bool dead = (r_ptr->max_num == 0);
4288
4289                         if (dead)
4290                         {
4291                                 fprintf(fff, "     %s\n", (r_name + r_ptr->name));
4292                                 total++;
4293                         }
4294
4295                         continue;
4296                 }
4297
4298                 MONSTER_NUMBER this_monster = r_ptr->r_pkills;
4299
4300                 if (this_monster <= 0) continue;
4301
4302 #ifdef JP
4303                 /* p,tは人と数える by ita */
4304                 if (my_strchr("pt", r_ptr->d_char))
4305                         fprintf(fff, "     %3d 人の %s\n", (int)this_monster, r_name + r_ptr->name);
4306                 else
4307                         fprintf(fff, "     %3d 体の %s\n", (int)this_monster, r_name + r_ptr->name);
4308 #else
4309                 if (this_monster < 2)
4310                 {
4311                         if (my_strstr(r_name + r_ptr->name, "coins"))
4312                         {
4313                                 fprintf(fff, "     1 pile of %s\n", (r_name + r_ptr->name));
4314                         }
4315                         else
4316                         {
4317                                 fprintf(fff, "     1 %s\n", (r_name + r_ptr->name));
4318                         }
4319                 }
4320                 else
4321                 {
4322                         char ToPlural[80];
4323                         strcpy(ToPlural, (r_name + r_ptr->name));
4324                         plural_aux(ToPlural);
4325                         fprintf(fff, "     %d %s\n", this_monster, ToPlural);
4326                 }
4327 #endif
4328                 total += this_monster;
4329         }
4330
4331         fprintf(fff, "----------------------------------------------\n");
4332 #ifdef JP
4333         fprintf(fff, "    合計: %lu 体を倒した。\n", (unsigned long int)total);
4334 #else
4335         fprintf(fff, "   Total: %lu creature%s killed.\n", (unsigned long int)total, (total == 1 ? "" : "s"));
4336 #endif
4337
4338         /* Free the "who" array */
4339         C_KILL(who, max_r_idx, s16b);
4340         my_fclose(fff);
4341
4342         /* Display the file contents */
4343         (void)show_file(creature_ptr, TRUE, file_name, _("倒した敵の数", "Kill Count"), 0, 0);
4344         fd_kill(file_name);
4345 }
4346
4347
4348 /*!
4349  * @brief モンスター情報リスト中のグループを表示する /
4350  * Display the object groups.
4351  * @param col 開始行
4352  * @param row 開始列
4353  * @param wid 表示文字数幅
4354  * @param per_page リストの表示行
4355  * @param grp_idx グループのID配列
4356  * @param group_text グループ名の文字列配列
4357  * @param grp_cur 現在の選択ID
4358  * @param grp_top 現在の選択リスト最上部ID
4359  * @return なし
4360  */
4361 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)
4362 {
4363         /* Display lines until done */
4364         for (int i = 0; i < per_page && (grp_idx[i] >= 0); i++)
4365         {
4366                 /* Get the group index */
4367                 int grp = grp_idx[grp_top + i];
4368
4369                 /* Choose a color */
4370                 TERM_COLOR attr = (grp_top + i == grp_cur) ? TERM_L_BLUE : TERM_WHITE;
4371
4372                 /* Erase the entire line */
4373                 Term_erase(col, row + i, wid);
4374
4375                 /* Display the group label */
4376                 c_put_str(attr, group_text[grp], row + i, col);
4377         }
4378 }
4379
4380
4381 /*
4382  * Move the cursor in a browser window
4383  */
4384 static void browser_cursor(char ch, int *column, IDX *grp_cur, int grp_cnt,
4385         IDX *list_cur, int list_cnt)
4386 {
4387         int d;
4388         int col = *column;
4389         IDX grp = *grp_cur;
4390         IDX list = *list_cur;
4391
4392         /* Extract direction */
4393         if (ch == ' ')
4394         {
4395                 /* Hack -- scroll up full screen */
4396                 d = 3;
4397         }
4398         else if (ch == '-')
4399         {
4400                 /* Hack -- scroll down full screen */
4401                 d = 9;
4402         }
4403         else
4404         {
4405                 d = get_keymap_dir(ch);
4406         }
4407
4408         if (!d) return;
4409
4410         /* Diagonals - hack */
4411         if ((ddx[d] > 0) && ddy[d])
4412         {
4413                 int browser_rows;
4414                 int wid, hgt;
4415
4416                 Term_get_size(&wid, &hgt);
4417
4418                 browser_rows = hgt - 8;
4419
4420                 /* Browse group list */
4421                 if (!col)
4422                 {
4423                         int old_grp = grp;
4424
4425                         /* Move up or down */
4426                         grp += ddy[d] * (browser_rows - 1);
4427
4428                         /* Verify */
4429                         if (grp >= grp_cnt)     grp = grp_cnt - 1;
4430                         if (grp < 0) grp = 0;
4431                         if (grp != old_grp)     list = 0;
4432                 }
4433
4434                 /* Browse sub-list list */
4435                 else
4436                 {
4437                         /* Move up or down */
4438                         list += ddy[d] * browser_rows;
4439
4440                         /* Verify */
4441                         if (list >= list_cnt) list = list_cnt - 1;
4442                         if (list < 0) list = 0;
4443                 }
4444
4445                 (*grp_cur) = grp;
4446                 (*list_cur) = list;
4447
4448                 return;
4449         }
4450
4451         if (ddx[d])
4452         {
4453                 col += ddx[d];
4454                 if (col < 0) col = 0;
4455                 if (col > 1) col = 1;
4456
4457                 (*column) = col;
4458
4459                 return;
4460         }
4461
4462         /* Browse group list */
4463         if (!col)
4464         {
4465                 int old_grp = grp;
4466
4467                 /* Move up or down */
4468                 grp += (IDX)ddy[d];
4469
4470                 /* Verify */
4471                 if (grp >= grp_cnt)     grp = grp_cnt - 1;
4472                 if (grp < 0) grp = 0;
4473                 if (grp != old_grp)     list = 0;
4474         }
4475
4476         /* Browse sub-list list */
4477         else
4478         {
4479                 /* Move up or down */
4480                 list += (IDX)ddy[d];
4481
4482                 /* Verify */
4483                 if (list >= list_cnt) list = list_cnt - 1;
4484                 if (list < 0) list = 0;
4485         }
4486
4487         (*grp_cur) = grp;
4488         (*list_cur) = list;
4489 }
4490
4491
4492 /*
4493  * Display visuals.
4494  */
4495 static void display_visual_list(int col, int row, int height, int width, TERM_COLOR attr_top, byte char_left)
4496 {
4497         /* Clear the display lines */
4498         for (int i = 0; i < height; i++)
4499         {
4500                 Term_erase(col, row + i, width);
4501         }
4502
4503         /* Bigtile mode uses double width */
4504         if (use_bigtile) width /= 2;
4505
4506         /* Display lines until done */
4507         for (int i = 0; i < height; i++)
4508         {
4509                 /* Display columns until done */
4510                 for (int j = 0; j < width; j++)
4511                 {
4512                         TERM_LEN x = col + j;
4513                         TERM_LEN y = row + i;
4514
4515                         /* Bigtile mode uses double width */
4516                         if (use_bigtile) x += j;
4517
4518                         TERM_COLOR ia = attr_top + i;
4519                         SYMBOL_CODE ic = char_left + j;
4520
4521                         /* Ignore illegal characters */
4522                         if (ia > 0x7f || ic > 0xff || ic < ' ' ||
4523                                 (!use_graphics && ic > 0x7f))
4524                                 continue;
4525
4526                         TERM_COLOR a = ia;
4527                         SYMBOL_CODE c = ic;
4528
4529                         /* Force correct code for both ASCII character and tile */
4530                         if (c & 0x80) a |= 0x80;
4531
4532                         /* Display symbol */
4533                         Term_queue_bigchar(x, y, a, c, 0, 0);
4534                 }
4535         }
4536 }
4537
4538
4539 /*
4540  * Place the cursor at the collect position for visual mode
4541  */
4542 static void place_visual_list_cursor(TERM_LEN col, TERM_LEN row, TERM_COLOR a, byte c, TERM_COLOR attr_top, byte char_left)
4543 {
4544         int i = (a & 0x7f) - attr_top;
4545         int j = c - char_left;
4546
4547         TERM_LEN x = col + j;
4548         TERM_LEN y = row + i;
4549
4550         /* Bigtile mode uses double width */
4551         if (use_bigtile) x += j;
4552
4553         /* Place the cursor */
4554         Term_gotoxy(x, y);
4555 }
4556
4557
4558 /*
4559  *  Do visual mode command -- Change symbols
4560  */
4561 static bool visual_mode_command(char ch, bool *visual_list_ptr,
4562         int height, int width,
4563         TERM_COLOR *attr_top_ptr, byte *char_left_ptr,
4564         TERM_COLOR *cur_attr_ptr, SYMBOL_CODE *cur_char_ptr, bool *need_redraw)
4565 {
4566         static TERM_COLOR attr_old = 0;
4567         static SYMBOL_CODE char_old = 0;
4568
4569         switch (ch)
4570         {
4571         case ESCAPE:
4572                 if (*visual_list_ptr)
4573                 {
4574                         /* Cancel change */
4575                         *cur_attr_ptr = attr_old;
4576                         *cur_char_ptr = char_old;
4577                         *visual_list_ptr = FALSE;
4578
4579                         return TRUE;
4580                 }
4581                 break;
4582
4583         case '\n':
4584         case '\r':
4585                 if (*visual_list_ptr)
4586                 {
4587                         /* Accept change */
4588                         *visual_list_ptr = FALSE;
4589                         *need_redraw = TRUE;
4590
4591                         return TRUE;
4592                 }
4593                 break;
4594
4595         case 'V':
4596         case 'v':
4597                 if (!*visual_list_ptr)
4598                 {
4599                         *visual_list_ptr = TRUE;
4600
4601                         *attr_top_ptr = MAX(0, (*cur_attr_ptr & 0x7f) - 5);
4602                         *char_left_ptr = MAX(0, *cur_char_ptr - 10);
4603
4604                         attr_old = *cur_attr_ptr;
4605                         char_old = *cur_char_ptr;
4606
4607                         return TRUE;
4608                 }
4609                 break;
4610
4611         case 'C':
4612         case 'c':
4613         {
4614                 int i;
4615
4616                 /* Set the visual */
4617                 attr_idx = *cur_attr_ptr;
4618                 char_idx = *cur_char_ptr;
4619
4620                 /* Hack -- for feature lighting */
4621                 for (i = 0; i < F_LIT_MAX; i++)
4622                 {
4623                         attr_idx_feat[i] = 0;
4624                         char_idx_feat[i] = 0;
4625                 }
4626         }
4627         return TRUE;
4628
4629         case 'P':
4630         case 'p':
4631                 if (attr_idx || (!(char_idx & 0x80) && char_idx)) /* Allow TERM_DARK text */
4632                 {
4633                         /* Set the char */
4634                         *cur_attr_ptr = attr_idx;
4635                         *attr_top_ptr = MAX(0, (*cur_attr_ptr & 0x7f) - 5);
4636                         if (!*visual_list_ptr) *need_redraw = TRUE;
4637                 }
4638
4639                 if (char_idx)
4640                 {
4641                         /* Set the char */
4642                         *cur_char_ptr = char_idx;
4643                         *char_left_ptr = MAX(0, *cur_char_ptr - 10);
4644                         if (!*visual_list_ptr) *need_redraw = TRUE;
4645                 }
4646
4647                 return TRUE;
4648
4649         default:
4650                 if (*visual_list_ptr)
4651                 {
4652                         int eff_width;
4653                         int d = get_keymap_dir(ch);
4654                         TERM_COLOR a = (*cur_attr_ptr & 0x7f);
4655                         SYMBOL_CODE c = *cur_char_ptr;
4656
4657                         if (use_bigtile) eff_width = width / 2;
4658                         else eff_width = width;
4659
4660                         /* Restrict direction */
4661                         if ((a == 0) && (ddy[d] < 0)) d = 0;
4662                         if ((c == 0) && (ddx[d] < 0)) d = 0;
4663                         if ((a == 0x7f) && (ddy[d] > 0)) d = 0;
4664                         if ((c == 0xff) && (ddx[d] > 0)) d = 0;
4665
4666                         a += (TERM_COLOR)ddy[d];
4667                         c += (SYMBOL_CODE)ddx[d];
4668
4669                         /* Force correct code for both ASCII character and tile */
4670                         if (c & 0x80) a |= 0x80;
4671
4672                         /* Set the visual */
4673                         *cur_attr_ptr = a;
4674                         *cur_char_ptr = c;
4675
4676
4677                         /* Move the frame */
4678                         if ((ddx[d] < 0) && *char_left_ptr > MAX(0, (int)c - 10)) (*char_left_ptr)--;
4679                         if ((ddx[d] > 0) && *char_left_ptr + eff_width < MIN(0xff, (int)c + 10)) (*char_left_ptr)++;
4680                         if ((ddy[d] < 0) && *attr_top_ptr > MAX(0, (int)(a & 0x7f) - 4)) (*attr_top_ptr)--;
4681                         if ((ddy[d] > 0) && *attr_top_ptr + height < MIN(0x7f, (a & 0x7f) + 4)) (*attr_top_ptr)++;
4682                         return TRUE;
4683                 }
4684                 break;
4685         }
4686
4687         /* Visual mode command is not used */
4688         return FALSE;
4689 }
4690
4691
4692 /*
4693  * Display the monsters in a group.
4694  */
4695 static void display_monster_list(int col, int row, int per_page, s16b mon_idx[],
4696         int mon_cur, int mon_top, bool visual_only)
4697 {
4698         /* Display lines until done */
4699         int i;
4700         for (i = 0; i < per_page && (mon_idx[mon_top + i] >= 0); i++)
4701         {
4702                 TERM_COLOR attr;
4703
4704                 /* Get the race index */
4705                 MONRACE_IDX r_idx = mon_idx[mon_top + i];
4706
4707                 /* Access the race */
4708                 monster_race *r_ptr = &r_info[r_idx];
4709
4710                 /* Choose a color */
4711                 attr = ((i + mon_top == mon_cur) ? TERM_L_BLUE : TERM_WHITE);
4712
4713                 /* Display the name */
4714                 c_prt(attr, (r_name + r_ptr->name), row + i, col);
4715
4716                 /* Hack -- visual_list mode */
4717                 if (per_page == 1)
4718                 {
4719                         c_prt(attr, format("%02x/%02x", r_ptr->x_attr, r_ptr->x_char), row + i, (current_world_ptr->wizard || visual_only) ? 56 : 61);
4720                 }
4721
4722                 if (current_world_ptr->wizard || visual_only)
4723                 {
4724                         c_prt(attr, format("%d", r_idx), row + i, 62);
4725                 }
4726
4727                 /* Erase chars before overwritten by the race letter */
4728                 Term_erase(69, row + i, 255);
4729
4730                 /* Display symbol */
4731                 Term_queue_bigchar(use_bigtile ? 69 : 70, row + i, r_ptr->x_attr, r_ptr->x_char, 0, 0);
4732
4733                 if (!visual_only)
4734                 {
4735                         /* Display kills */
4736                         if (!(r_ptr->flags1 & RF1_UNIQUE))
4737                                 put_str(format("%5d", r_ptr->r_pkills), row + i, 73);
4738                         else
4739                                 c_put_str((r_ptr->max_num == 0 ? TERM_L_DARK : TERM_WHITE),
4740                                 (r_ptr->max_num == 0 ? _("死亡", " dead") : _("生存", "alive")), row + i, 74);
4741                 }
4742         }
4743
4744         /* Clear remaining lines */
4745         for (; i < per_page; i++)
4746         {
4747                 Term_erase(col, row + i, 255);
4748         }
4749 }
4750
4751
4752 /*
4753  * todo 引数の詳細について加筆求む
4754  * Display known monsters.
4755  * @param creature_ptr プレーヤーへの参照ポインタ
4756  * @param need_redraw 画面の再描画が必要な時TRUE
4757  * @param visual_only ???
4758  * @param direct_r_idx モンスターID
4759  * @return なし
4760  */
4761 static void do_cmd_knowledge_monsters(player_type *creature_ptr, bool *need_redraw, bool visual_only, IDX direct_r_idx)
4762 {
4763         TERM_LEN wid, hgt;
4764         Term_get_size(&wid, &hgt);
4765
4766         /* Allocate the "mon_idx" array */
4767         IDX *mon_idx;
4768         C_MAKE(mon_idx, max_r_idx, MONRACE_IDX);
4769
4770         int max = 0;
4771         IDX grp_cnt = 0;
4772         IDX grp_idx[100];
4773         IDX mon_cnt;
4774         bool visual_list = FALSE;
4775         TERM_COLOR attr_top = 0;
4776         byte char_left = 0;
4777         BIT_FLAGS8 mode;
4778         int browser_rows = hgt - 8;
4779         if (direct_r_idx < 0)
4780         {
4781                 mode = visual_only ? 0x03 : 0x01;
4782
4783                 /* Check every group */
4784                 int len;
4785                 for (IDX i = 0; monster_group_text[i] != NULL; i++)
4786                 {
4787                         /* Measure the label */
4788                         len = strlen(monster_group_text[i]);
4789
4790                         /* Save the maximum length */
4791                         if (len > max) max = len;
4792
4793                         /* See if any monsters are known */
4794                         if ((monster_group_char[i] == ((char *)-1L)) || collect_monsters(creature_ptr, i, mon_idx, mode))
4795                         {
4796                                 /* Build a list of groups with known monsters */
4797                                 grp_idx[grp_cnt++] = i;
4798                         }
4799                 }
4800
4801                 mon_cnt = 0;
4802         }
4803         else
4804         {
4805                 mon_idx[0] = direct_r_idx;
4806                 mon_cnt = 1;
4807
4808                 /* Terminate the list */
4809                 mon_idx[1] = -1;
4810
4811                 (void)visual_mode_command('v', &visual_list, browser_rows - 1, wid - (max + 3),
4812                         &attr_top, &char_left, &r_info[direct_r_idx].x_attr, &r_info[direct_r_idx].x_char, need_redraw);
4813         }
4814
4815         /* Terminate the list */
4816         grp_idx[grp_cnt] = -1;
4817
4818         mode = visual_only ? 0x02 : 0x00;
4819         IDX old_grp_cur = -1;
4820         IDX grp_cur = 0;
4821         IDX grp_top = 0;
4822         IDX mon_cur = 0;
4823         IDX mon_top = 0;
4824         int column = 0;
4825         bool flag = FALSE;
4826         bool redraw = TRUE;
4827         while (!flag)
4828         {
4829                 if (redraw)
4830                 {
4831                         clear_from(0);
4832                         prt(format(_("%s - モンスター", "%s - monsters"), !visual_only ? _("知識", "Knowledge") : _("表示", "Visuals")), 2, 0);
4833                         if (direct_r_idx < 0) prt(_("グループ", "Group"), 4, 0);
4834                         prt(_("名前", "Name"), 4, max + 3);
4835                         if (current_world_ptr->wizard || visual_only) prt("Idx", 4, 62);
4836                         prt(_("文字", "Sym"), 4, 67);
4837                         if (!visual_only) prt(_("殺害数", "Kills"), 4, 72);
4838
4839                         for (IDX i = 0; i < 78; i++)
4840                         {
4841                                 Term_putch(i, 5, TERM_WHITE, '=');
4842                         }
4843
4844                         if (direct_r_idx < 0)
4845                         {
4846                                 for (IDX i = 0; i < browser_rows; i++)
4847                                 {
4848                                         Term_putch(max + 1, 6 + i, TERM_WHITE, '|');
4849                                 }
4850                         }
4851
4852                         redraw = FALSE;
4853                 }
4854
4855                 if (direct_r_idx < 0)
4856                 {
4857                         /* Scroll group list */
4858                         if (grp_cur < grp_top) grp_top = grp_cur;
4859                         if (grp_cur >= grp_top + browser_rows) grp_top = grp_cur - browser_rows + 1;
4860
4861                         /* Display a list of monster groups */
4862                         display_group_list(0, 6, max, browser_rows, grp_idx, monster_group_text, grp_cur, grp_top);
4863
4864                         if (old_grp_cur != grp_cur)
4865                         {
4866                                 old_grp_cur = grp_cur;
4867
4868                                 /* Get a list of monsters in the current group */
4869                                 mon_cnt = collect_monsters(creature_ptr, grp_idx[grp_cur], mon_idx, mode);
4870                         }
4871
4872                         /* Scroll monster list */
4873                         while (mon_cur < mon_top)
4874                                 mon_top = MAX(0, mon_top - browser_rows / 2);
4875                         while (mon_cur >= mon_top + browser_rows)
4876                                 mon_top = MIN(mon_cnt - browser_rows, mon_top + browser_rows / 2);
4877                 }
4878
4879                 if (!visual_list)
4880                 {
4881                         /* Display a list of monsters in the current group */
4882                         display_monster_list(max + 3, 6, browser_rows, mon_idx, mon_cur, mon_top, visual_only);
4883                 }
4884                 else
4885                 {
4886                         mon_top = mon_cur;
4887
4888                         /* Display a monster name */
4889                         display_monster_list(max + 3, 6, 1, mon_idx, mon_cur, mon_top, visual_only);
4890
4891                         /* Display visual list below first monster */
4892                         display_visual_list(max + 3, 7, browser_rows - 1, wid - (max + 3), attr_top, char_left);
4893                 }
4894
4895                 /* Prompt */
4896                 prt(format(_("<方向>%s%s%s, ESC", "<dir>%s%s%s, ESC"),
4897                         (!visual_list && !visual_only) ? _(", 'r'で思い出を見る", ", 'r' to recall") : "",
4898                         visual_list ? _(", ENTERで決定", ", ENTER to accept") : _(", 'v'でシンボル変更", ", 'v' for visuals"),
4899                         (attr_idx || char_idx) ? _(", 'c', 'p'でペースト", ", 'c', 'p' to paste") : _(", 'c'でコピー", ", 'c' to copy")),
4900                         hgt - 1, 0);
4901
4902                 /* Get the current monster */
4903                 monster_race *r_ptr;
4904                 r_ptr = &r_info[mon_idx[mon_cur]];
4905
4906                 if (!visual_only)
4907                 {
4908                         /* Mega Hack -- track this monster race */
4909                         if (mon_cnt) monster_race_track(creature_ptr, mon_idx[mon_cur]);
4910                         handle_stuff(creature_ptr);
4911                 }
4912
4913                 if (visual_list)
4914                 {
4915                         place_visual_list_cursor(max + 3, 7, r_ptr->x_attr, r_ptr->x_char, attr_top, char_left);
4916                 }
4917                 else if (!column)
4918                 {
4919                         Term_gotoxy(0, 6 + (grp_cur - grp_top));
4920                 }
4921                 else
4922                 {
4923                         Term_gotoxy(max + 3, 6 + (mon_cur - mon_top));
4924                 }
4925
4926                 char ch = inkey();
4927
4928                 /* Do visual mode command if needed */
4929                 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))
4930                 {
4931                         if (direct_r_idx >= 0)
4932                         {
4933                                 switch (ch)
4934                                 {
4935                                 case '\n':
4936                                 case '\r':
4937                                 case ESCAPE:
4938                                         flag = TRUE;
4939                                         break;
4940                                 }
4941                         }
4942
4943                         continue;
4944                 }
4945
4946                 switch (ch)
4947                 {
4948                 case ESCAPE:
4949                 {
4950                         flag = TRUE;
4951                         break;
4952                 }
4953
4954                 case 'R':
4955                 case 'r':
4956                 {
4957                         /* Recall on screen */
4958                         if (!visual_list && !visual_only && (mon_idx[mon_cur] > 0))
4959                         {
4960                                 screen_roff(creature_ptr, mon_idx[mon_cur], 0);
4961
4962                                 (void)inkey();
4963
4964                                 redraw = TRUE;
4965                         }
4966
4967                         break;
4968                 }
4969
4970                 default:
4971                 {
4972                         /* Move the cursor */
4973                         browser_cursor(ch, &column, &grp_cur, grp_cnt, &mon_cur, mon_cnt);
4974
4975                         break;
4976                 }
4977                 }
4978         }
4979
4980         /* Free the "mon_idx" array */
4981         C_KILL(mon_idx, max_r_idx, MONRACE_IDX);
4982 }
4983
4984
4985 /*
4986  * Display the objects in a group.
4987  */
4988 static void display_object_list(int col, int row, int per_page, IDX object_idx[],
4989         int object_cur, int object_top, bool visual_only)
4990 {
4991         /* Display lines until done */
4992         int i;
4993         for (i = 0; i < per_page && (object_idx[object_top + i] >= 0); i++)
4994         {
4995                 GAME_TEXT o_name[MAX_NLEN];
4996                 TERM_COLOR a;
4997                 SYMBOL_CODE c;
4998                 object_kind *flavor_k_ptr;
4999
5000                 /* Get the object index */
5001                 KIND_OBJECT_IDX k_idx = object_idx[object_top + i];
5002
5003                 /* Access the object */
5004                 object_kind *k_ptr = &k_info[k_idx];
5005
5006                 /* Choose a color */
5007                 TERM_COLOR attr = ((k_ptr->aware || visual_only) ? TERM_WHITE : TERM_SLATE);
5008                 byte cursor = ((k_ptr->aware || visual_only) ? TERM_L_BLUE : TERM_BLUE);
5009
5010                 if (!visual_only && k_ptr->flavor)
5011                 {
5012                         /* Appearance of this object is shuffled */
5013                         flavor_k_ptr = &k_info[k_ptr->flavor];
5014                 }
5015                 else
5016                 {
5017                         /* Appearance of this object is very normal */
5018                         flavor_k_ptr = k_ptr;
5019                 }
5020
5021                 attr = ((i + object_top == object_cur) ? cursor : attr);
5022
5023                 if (!k_ptr->flavor || (!visual_only && k_ptr->aware))
5024                 {
5025                         /* Tidy name */
5026                         strip_name(o_name, k_idx);
5027                 }
5028                 else
5029                 {
5030                         /* Flavor name */
5031                         strcpy(o_name, k_name + flavor_k_ptr->flavor_name);
5032                 }
5033
5034                 /* Display the name */
5035                 c_prt(attr, o_name, row + i, col);
5036
5037                 /* Hack -- visual_list mode */
5038                 if (per_page == 1)
5039                 {
5040                         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);
5041                 }
5042
5043                 if (current_world_ptr->wizard || visual_only)
5044                 {
5045                         c_prt(attr, format("%d", k_idx), row + i, 70);
5046                 }
5047
5048                 a = flavor_k_ptr->x_attr;
5049                 c = flavor_k_ptr->x_char;
5050
5051                 /* Display symbol */
5052                 Term_queue_bigchar(use_bigtile ? 76 : 77, row + i, a, c, 0, 0);
5053         }
5054
5055         /* Clear remaining lines */
5056         for (; i < per_page; i++)
5057         {
5058                 Term_erase(col, row + i, 255);
5059         }
5060 }
5061
5062
5063 /*
5064  * Describe fake object
5065  */
5066 static void desc_obj_fake(player_type *creature_ptr, KIND_OBJECT_IDX k_idx)
5067 {
5068         object_type *o_ptr;
5069         object_type object_type_body;
5070         o_ptr = &object_type_body;
5071         object_wipe(o_ptr);
5072         object_prep(o_ptr, k_idx);
5073
5074         /* It's fully know */
5075         o_ptr->ident |= IDENT_KNOWN;
5076         handle_stuff(creature_ptr);
5077
5078         if (screen_object(creature_ptr, o_ptr, SCROBJ_FAKE_OBJECT | SCROBJ_FORCE_DETAIL)) return;
5079
5080         msg_print(_("特に変わったところはないようだ。", "You see nothing special."));
5081         msg_print(NULL);
5082 }
5083
5084
5085 /*
5086  * Display known objects
5087  */
5088 static void do_cmd_knowledge_objects(player_type *creature_ptr, bool *need_redraw, bool visual_only, IDX direct_k_idx)
5089 {
5090         IDX object_old, object_top;
5091         IDX grp_idx[100];
5092         int object_cnt;
5093         OBJECT_IDX *object_idx;
5094
5095         bool visual_list = FALSE;
5096         TERM_COLOR attr_top = 0;
5097         byte char_left = 0;
5098         byte mode;
5099
5100         TERM_LEN wid, hgt;
5101         Term_get_size(&wid, &hgt);
5102
5103         int browser_rows = hgt - 8;
5104
5105         /* Allocate the "object_idx" array */
5106         C_MAKE(object_idx, max_k_idx, KIND_OBJECT_IDX);
5107
5108         int len;
5109         int max = 0;
5110         int grp_cnt = 0;
5111         if (direct_k_idx < 0)
5112         {
5113                 mode = visual_only ? 0x03 : 0x01;
5114
5115                 /* Check every group */
5116                 for (IDX i = 0; object_group_text[i] != NULL; i++)
5117                 {
5118                         /* Measure the label */
5119                         len = strlen(object_group_text[i]);
5120
5121                         /* Save the maximum length */
5122                         if (len > max) max = len;
5123
5124                         /* See if any monsters are known */
5125                         if (collect_objects(i, object_idx, mode))
5126                         {
5127                                 /* Build a list of groups with known monsters */
5128                                 grp_idx[grp_cnt++] = i;
5129                         }
5130                 }
5131
5132                 object_old = -1;
5133                 object_cnt = 0;
5134         }
5135         else
5136         {
5137                 object_kind *k_ptr = &k_info[direct_k_idx];
5138                 object_kind *flavor_k_ptr;
5139
5140                 if (!visual_only && k_ptr->flavor)
5141                 {
5142                         /* Appearance of this object is shuffled */
5143                         flavor_k_ptr = &k_info[k_ptr->flavor];
5144                 }
5145                 else
5146                 {
5147                         /* Appearance of this object is very normal */
5148                         flavor_k_ptr = k_ptr;
5149                 }
5150
5151                 object_idx[0] = direct_k_idx;
5152                 object_old = direct_k_idx;
5153                 object_cnt = 1;
5154
5155                 /* Terminate the list */
5156                 object_idx[1] = -1;
5157
5158                 (void)visual_mode_command('v', &visual_list, browser_rows - 1, wid - (max + 3),
5159                         &attr_top, &char_left, &flavor_k_ptr->x_attr, &flavor_k_ptr->x_char, need_redraw);
5160         }
5161
5162         /* Terminate the list */
5163         grp_idx[grp_cnt] = -1;
5164
5165         mode = visual_only ? 0x02 : 0x00;
5166         IDX old_grp_cur = -1;
5167         IDX grp_cur = 0;
5168         IDX grp_top = 0;
5169         IDX object_cur = object_top = 0;
5170         bool flag = FALSE;
5171         bool redraw = TRUE;
5172         int column = 0;
5173         while (!flag)
5174         {
5175                 object_kind *k_ptr, *flavor_k_ptr;
5176
5177                 if (redraw)
5178                 {
5179                         clear_from(0);
5180
5181 #ifdef JP
5182                         prt(format("%s - アイテム", !visual_only ? "知識" : "表示"), 2, 0);
5183                         if (direct_k_idx < 0) prt("グループ", 4, 0);
5184                         prt("名前", 4, max + 3);
5185                         if (current_world_ptr->wizard || visual_only) prt("Idx", 4, 70);
5186                         prt("文字", 4, 74);
5187 #else
5188                         prt(format("%s - objects", !visual_only ? "Knowledge" : "Visuals"), 2, 0);
5189                         if (direct_k_idx < 0) prt("Group", 4, 0);
5190                         prt("Name", 4, max + 3);
5191                         if (current_world_ptr->wizard || visual_only) prt("Idx", 4, 70);
5192                         prt("Sym", 4, 75);
5193 #endif
5194
5195                         for (IDX i = 0; i < 78; i++)
5196                         {
5197                                 Term_putch(i, 5, TERM_WHITE, '=');
5198                         }
5199
5200                         if (direct_k_idx < 0)
5201                         {
5202                                 for (IDX i = 0; i < browser_rows; i++)
5203                                 {
5204                                         Term_putch(max + 1, 6 + i, TERM_WHITE, '|');
5205                                 }
5206                         }
5207
5208                         redraw = FALSE;
5209                 }
5210
5211                 if (direct_k_idx < 0)
5212                 {
5213                         /* Scroll group list */
5214                         if (grp_cur < grp_top) grp_top = grp_cur;
5215                         if (grp_cur >= grp_top + browser_rows) grp_top = grp_cur - browser_rows + 1;
5216
5217                         /* Display a list of object groups */
5218                         display_group_list(0, 6, max, browser_rows, grp_idx, object_group_text, grp_cur, grp_top);
5219
5220                         if (old_grp_cur != grp_cur)
5221                         {
5222                                 old_grp_cur = grp_cur;
5223
5224                                 /* Get a list of objects in the current group */
5225                                 object_cnt = collect_objects(grp_idx[grp_cur], object_idx, mode);
5226                         }
5227
5228                         /* Scroll object list */
5229                         while (object_cur < object_top)
5230                                 object_top = MAX(0, object_top - browser_rows / 2);
5231                         while (object_cur >= object_top + browser_rows)
5232                                 object_top = MIN(object_cnt - browser_rows, object_top + browser_rows / 2);
5233                 }
5234
5235                 if (!visual_list)
5236                 {
5237                         /* Display a list of objects in the current group */
5238                         display_object_list(max + 3, 6, browser_rows, object_idx, object_cur, object_top, visual_only);
5239                 }
5240                 else
5241                 {
5242                         object_top = object_cur;
5243
5244                         /* Display a list of objects in the current group */
5245                         display_object_list(max + 3, 6, 1, object_idx, object_cur, object_top, visual_only);
5246
5247                         /* Display visual list below first object */
5248                         display_visual_list(max + 3, 7, browser_rows - 1, wid - (max + 3), attr_top, char_left);
5249                 }
5250
5251                 /* Get the current object */
5252                 k_ptr = &k_info[object_idx[object_cur]];
5253
5254                 if (!visual_only && k_ptr->flavor)
5255                 {
5256                         /* Appearance of this object is shuffled */
5257                         flavor_k_ptr = &k_info[k_ptr->flavor];
5258                 }
5259                 else
5260                 {
5261                         /* Appearance of this object is very normal */
5262                         flavor_k_ptr = k_ptr;
5263                 }
5264
5265                 /* Prompt */
5266 #ifdef JP
5267                 prt(format("<方向>%s%s%s, ESC",
5268                         (!visual_list && !visual_only) ? ", 'r'で詳細を見る" : "",
5269                         visual_list ? ", ENTERで決定" : ", 'v'でシンボル変更",
5270                         (attr_idx || char_idx) ? ", 'c', 'p'でペースト" : ", 'c'でコピー"),
5271                         hgt - 1, 0);
5272 #else
5273                 prt(format("<dir>%s%s%s, ESC",
5274                         (!visual_list && !visual_only) ? ", 'r' to recall" : "",
5275                         visual_list ? ", ENTER to accept" : ", 'v' for visuals",
5276                         (attr_idx || char_idx) ? ", 'c', 'p' to paste" : ", 'c' to copy"),
5277                         hgt - 1, 0);
5278 #endif
5279
5280                 if (!visual_only)
5281                 {
5282                         /* Mega Hack -- track this object */
5283                         if (object_cnt) object_kind_track(creature_ptr, object_idx[object_cur]);
5284
5285                         /* The "current" object changed */
5286                         if (object_old != object_idx[object_cur])
5287                         {
5288                                 handle_stuff(creature_ptr);
5289
5290                                 /* Remember the "current" object */
5291                                 object_old = object_idx[object_cur];
5292                         }
5293                 }
5294
5295                 if (visual_list)
5296                 {
5297                         place_visual_list_cursor(max + 3, 7, flavor_k_ptr->x_attr, flavor_k_ptr->x_char, attr_top, char_left);
5298                 }
5299                 else if (!column)
5300                 {
5301                         Term_gotoxy(0, 6 + (grp_cur - grp_top));
5302                 }
5303                 else
5304                 {
5305                         Term_gotoxy(max + 3, 6 + (object_cur - object_top));
5306                 }
5307
5308                 char ch = inkey();
5309
5310                 /* Do visual mode command if needed */
5311                 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))
5312                 {
5313                         if (direct_k_idx >= 0)
5314                         {
5315                                 switch (ch)
5316                                 {
5317                                 case '\n':
5318                                 case '\r':
5319                                 case ESCAPE:
5320                                         flag = TRUE;
5321                                         break;
5322                                 }
5323                         }
5324                         continue;
5325                 }
5326
5327                 switch (ch)
5328                 {
5329                 case ESCAPE:
5330                 {
5331                         flag = TRUE;
5332                         break;
5333                 }
5334
5335                 case 'R':
5336                 case 'r':
5337                 {
5338                         /* Recall on screen */
5339                         if (!visual_list && !visual_only && (grp_cnt > 0))
5340                         {
5341                                 desc_obj_fake(creature_ptr, object_idx[object_cur]);
5342                                 redraw = TRUE;
5343                         }
5344                         break;
5345                 }
5346
5347                 default:
5348                 {
5349                         /* Move the cursor */
5350                         browser_cursor(ch, &column, &grp_cur, grp_cnt, &object_cur, object_cnt);
5351                         break;
5352                 }
5353                 }
5354         }
5355
5356         /* Free the "object_idx" array */
5357         C_KILL(object_idx, max_k_idx, KIND_OBJECT_IDX);
5358 }
5359
5360
5361 /*
5362  * Display the features in a group.
5363  */
5364 static void display_feature_list(int col, int row, int per_page, FEAT_IDX *feat_idx,
5365         FEAT_IDX feat_cur, FEAT_IDX feat_top, bool visual_only, int lighting_level)
5366 {
5367         int lit_col[F_LIT_MAX], i;
5368         int f_idx_col = use_bigtile ? 62 : 64;
5369
5370         /* Correct columns 1 and 4 */
5371         lit_col[F_LIT_STANDARD] = use_bigtile ? (71 - F_LIT_MAX) : 71;
5372         for (i = F_LIT_NS_BEGIN; i < F_LIT_MAX; i++)
5373                 lit_col[i] = lit_col[F_LIT_STANDARD] + 2 + (i - F_LIT_NS_BEGIN) * 2 + (use_bigtile ? i : 0);
5374
5375         /* Display lines until done */
5376         for (i = 0; i < per_page && (feat_idx[feat_top + i] >= 0); i++)
5377         {
5378                 TERM_COLOR attr;
5379                 FEAT_IDX f_idx = feat_idx[feat_top + i];
5380                 feature_type *f_ptr = &f_info[f_idx];
5381                 int row_i = row + i;
5382
5383                 /* Choose a color */
5384                 attr = ((i + feat_top == feat_cur) ? TERM_L_BLUE : TERM_WHITE);
5385
5386                 /* Display the name */
5387                 c_prt(attr, f_name + f_ptr->name, row_i, col);
5388
5389                 /* Hack -- visual_list mode */
5390                 if (per_page == 1)
5391                 {
5392                         /* Display lighting level */
5393                         c_prt(attr, format("(%s)", lighting_level_str[lighting_level]), row_i, col + 1 + strlen(f_name + f_ptr->name));
5394
5395                         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));
5396                 }
5397                 if (current_world_ptr->wizard || visual_only)
5398                 {
5399                         c_prt(attr, format("%d", f_idx), row_i, f_idx_col);
5400                 }
5401
5402                 /* Display symbol */
5403                 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);
5404
5405                 Term_putch(lit_col[F_LIT_NS_BEGIN], row_i, TERM_SLATE, '(');
5406                 for (int j = F_LIT_NS_BEGIN + 1; j < F_LIT_MAX; j++)
5407                 {
5408                         Term_putch(lit_col[j], row_i, TERM_SLATE, '/');
5409                 }
5410                 Term_putch(lit_col[F_LIT_MAX - 1] + (use_bigtile ? 3 : 2), row_i, TERM_SLATE, ')');
5411
5412                 /* Mega-hack -- Use non-standard colour */
5413                 for (int j = F_LIT_NS_BEGIN; j < F_LIT_MAX; j++)
5414                 {
5415                         Term_queue_bigchar(lit_col[j] + 1, row_i, f_ptr->x_attr[j], f_ptr->x_char[j], 0, 0);
5416                 }
5417         }
5418
5419         /* Clear remaining lines */
5420         for (; i < per_page; i++)
5421         {
5422                 Term_erase(col, row + i, 255);
5423         }
5424 }
5425
5426
5427 /*
5428  * Interact with feature visuals.
5429  */
5430 static void do_cmd_knowledge_features(bool *need_redraw, bool visual_only, IDX direct_f_idx, IDX *lighting_level)
5431 {
5432         TERM_COLOR attr_old[F_LIT_MAX];
5433         (void)C_WIPE(attr_old, F_LIT_MAX, TERM_COLOR);
5434         SYMBOL_CODE char_old[F_LIT_MAX];
5435         (void)C_WIPE(char_old, F_LIT_MAX, SYMBOL_CODE);
5436
5437         TERM_LEN wid, hgt;
5438         Term_get_size(&wid, &hgt);
5439
5440         /* Allocate the "feat_idx" array */
5441         FEAT_IDX *feat_idx;
5442         C_MAKE(feat_idx, max_f_idx, FEAT_IDX);
5443
5444         int len;
5445         int max = 0;
5446         int grp_cnt = 0;
5447         int feat_cnt;
5448         FEAT_IDX grp_idx[100];
5449         TERM_COLOR attr_top = 0;
5450         bool visual_list = FALSE;
5451         byte char_left = 0;
5452         TERM_LEN browser_rows = hgt - 8;
5453         if (direct_f_idx < 0)
5454         {
5455                 /* Check every group */
5456                 for (FEAT_IDX i = 0; feature_group_text[i] != NULL; i++)
5457                 {
5458                         /* Measure the label */
5459                         len = strlen(feature_group_text[i]);
5460
5461                         /* Save the maximum length */
5462                         if (len > max) max = len;
5463
5464                         /* See if any features are known */
5465                         if (collect_features(feat_idx, 0x01))
5466                         {
5467                                 /* Build a list of groups with known features */
5468                                 grp_idx[grp_cnt++] = i;
5469                         }
5470                 }
5471
5472                 feat_cnt = 0;
5473         }
5474         else
5475         {
5476                 feature_type *f_ptr = &f_info[direct_f_idx];
5477
5478                 feat_idx[0] = direct_f_idx;
5479                 feat_cnt = 1;
5480
5481                 /* Terminate the list */
5482                 feat_idx[1] = -1;
5483
5484                 (void)visual_mode_command('v', &visual_list, browser_rows - 1, wid - (max + 3),
5485                         &attr_top, &char_left, &f_ptr->x_attr[*lighting_level], &f_ptr->x_char[*lighting_level], need_redraw);
5486
5487                 for (FEAT_IDX i = 0; i < F_LIT_MAX; i++)
5488                 {
5489                         attr_old[i] = f_ptr->x_attr[i];
5490                         char_old[i] = f_ptr->x_char[i];
5491                 }
5492         }
5493
5494         /* Terminate the list */
5495         grp_idx[grp_cnt] = -1;
5496
5497         FEAT_IDX old_grp_cur = -1;
5498         FEAT_IDX grp_cur = 0;
5499         FEAT_IDX grp_top = 0;
5500         FEAT_IDX feat_cur = 0;
5501         FEAT_IDX feat_top = 0;
5502         TERM_LEN column = 0;
5503         bool flag = FALSE;
5504         bool redraw = TRUE;
5505         TERM_COLOR *cur_attr_ptr;
5506         SYMBOL_CODE *cur_char_ptr;
5507         while (!flag)
5508         {
5509                 char ch;
5510                 feature_type *f_ptr;
5511
5512                 if (redraw)
5513                 {
5514                         clear_from(0);
5515
5516                         prt(_("表示 - 地形", "Visuals - features"), 2, 0);
5517                         if (direct_f_idx < 0) prt(_("グループ", "Group"), 4, 0);
5518                         prt(_("名前", "Name"), 4, max + 3);
5519                         if (use_bigtile)
5520                         {
5521                                 if (current_world_ptr->wizard || visual_only) prt("Idx", 4, 62);
5522                                 prt(_("文字 ( l/ d)", "Sym ( l/ d)"), 4, 66);
5523                         }
5524                         else
5525                         {
5526                                 if (current_world_ptr->wizard || visual_only) prt("Idx", 4, 64);
5527                                 prt(_("文字 (l/d)", "Sym (l/d)"), 4, 68);
5528                         }
5529
5530                         for (FEAT_IDX i = 0; i < 78; i++)
5531                         {
5532                                 Term_putch(i, 5, TERM_WHITE, '=');
5533                         }
5534
5535                         if (direct_f_idx < 0)
5536                         {
5537                                 for (FEAT_IDX i = 0; i < browser_rows; i++)
5538                                 {
5539                                         Term_putch(max + 1, 6 + i, TERM_WHITE, '|');
5540                                 }
5541                         }
5542
5543                         redraw = FALSE;
5544                 }
5545
5546                 if (direct_f_idx < 0)
5547                 {
5548                         /* Scroll group list */
5549                         if (grp_cur < grp_top) grp_top = grp_cur;
5550                         if (grp_cur >= grp_top + browser_rows) grp_top = grp_cur - browser_rows + 1;
5551
5552                         /* Display a list of feature groups */
5553                         display_group_list(0, 6, max, browser_rows, grp_idx, feature_group_text, grp_cur, grp_top);
5554
5555                         if (old_grp_cur != grp_cur)
5556                         {
5557                                 old_grp_cur = grp_cur;
5558
5559                                 /* Get a list of features in the current group */
5560                                 feat_cnt = collect_features(feat_idx, 0x00);
5561                         }
5562
5563                         /* Scroll feature list */
5564                         while (feat_cur < feat_top)
5565                                 feat_top = MAX(0, feat_top - browser_rows / 2);
5566                         while (feat_cur >= feat_top + browser_rows)
5567                                 feat_top = MIN(feat_cnt - browser_rows, feat_top + browser_rows / 2);
5568                 }
5569
5570                 if (!visual_list)
5571                 {
5572                         /* Display a list of features in the current group */
5573                         display_feature_list(max + 3, 6, browser_rows, feat_idx, feat_cur, feat_top, visual_only, F_LIT_STANDARD);
5574                 }
5575                 else
5576                 {
5577                         feat_top = feat_cur;
5578
5579                         /* Display a list of features in the current group */
5580                         display_feature_list(max + 3, 6, 1, feat_idx, feat_cur, feat_top, visual_only, *lighting_level);
5581
5582                         /* Display visual list below first object */
5583                         display_visual_list(max + 3, 7, browser_rows - 1, wid - (max + 3), attr_top, char_left);
5584                 }
5585
5586                 /* Prompt */
5587                 prt(format(_("<方向>%s, 'd'で標準光源効果%s, ESC", "<dir>%s, 'd' for default lighting%s, ESC"),
5588                         visual_list ? _(", ENTERで決定, 'a'で対象明度変更", ", ENTER to accept, 'a' for lighting level") : _(", 'v'でシンボル変更", ", 'v' for visuals"),
5589                         (attr_idx || char_idx) ? _(", 'c', 'p'でペースト", ", 'c', 'p' to paste") : _(", 'c'でコピー", ", 'c' to copy")),
5590                         hgt - 1, 0);
5591
5592                 /* Get the current feature */
5593                 f_ptr = &f_info[feat_idx[feat_cur]];
5594                 cur_attr_ptr = &f_ptr->x_attr[*lighting_level];
5595                 cur_char_ptr = &f_ptr->x_char[*lighting_level];
5596
5597                 if (visual_list)
5598                 {
5599                         place_visual_list_cursor(max + 3, 7, *cur_attr_ptr, *cur_char_ptr, attr_top, char_left);
5600                 }
5601                 else if (!column)
5602                 {
5603                         Term_gotoxy(0, 6 + (grp_cur - grp_top));
5604                 }
5605                 else
5606                 {
5607                         Term_gotoxy(max + 3, 6 + (feat_cur - feat_top));
5608                 }
5609
5610                 ch = inkey();
5611
5612                 if (visual_list && ((ch == 'A') || (ch == 'a')))
5613                 {
5614                         int prev_lighting_level = *lighting_level;
5615
5616                         if (ch == 'A')
5617                         {
5618                                 if (*lighting_level <= 0) *lighting_level = F_LIT_MAX - 1;
5619                                 else (*lighting_level)--;
5620                         }
5621                         else
5622                         {
5623                                 if (*lighting_level >= F_LIT_MAX - 1) *lighting_level = 0;
5624                                 else (*lighting_level)++;
5625                         }
5626
5627                         if (f_ptr->x_attr[prev_lighting_level] != f_ptr->x_attr[*lighting_level])
5628                                 attr_top = MAX(0, (f_ptr->x_attr[*lighting_level] & 0x7f) - 5);
5629
5630                         if (f_ptr->x_char[prev_lighting_level] != f_ptr->x_char[*lighting_level])
5631                                 char_left = MAX(0, f_ptr->x_char[*lighting_level] - 10);
5632
5633                         continue;
5634                 }
5635
5636                 else if ((ch == 'D') || (ch == 'd'))
5637                 {
5638                         TERM_COLOR prev_x_attr = f_ptr->x_attr[*lighting_level];
5639                         byte prev_x_char = f_ptr->x_char[*lighting_level];
5640
5641                         apply_default_feat_lighting(f_ptr->x_attr, f_ptr->x_char);
5642
5643                         if (visual_list)
5644                         {
5645                                 if (prev_x_attr != f_ptr->x_attr[*lighting_level])
5646                                         attr_top = MAX(0, (f_ptr->x_attr[*lighting_level] & 0x7f) - 5);
5647
5648                                 if (prev_x_char != f_ptr->x_char[*lighting_level])
5649                                         char_left = MAX(0, f_ptr->x_char[*lighting_level] - 10);
5650                         }
5651                         else *need_redraw = TRUE;
5652
5653                         continue;
5654                 }
5655
5656                 /* Do visual mode command if needed */
5657                 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))
5658                 {
5659                         switch (ch)
5660                         {
5661                                 /* Restore previous visual settings */
5662                         case ESCAPE:
5663                                 for (FEAT_IDX i = 0; i < F_LIT_MAX; i++)
5664                                 {
5665                                         f_ptr->x_attr[i] = attr_old[i];
5666                                         f_ptr->x_char[i] = char_old[i];
5667                                 }
5668
5669                                 /* Fall through */
5670
5671                         case '\n':
5672                         case '\r':
5673                                 if (direct_f_idx >= 0) flag = TRUE;
5674                                 else *lighting_level = F_LIT_STANDARD;
5675                                 break;
5676
5677                                 /* Preserve current visual settings */
5678                         case 'V':
5679                         case 'v':
5680                                 for (FEAT_IDX i = 0; i < F_LIT_MAX; i++)
5681                                 {
5682                                         attr_old[i] = f_ptr->x_attr[i];
5683                                         char_old[i] = f_ptr->x_char[i];
5684                                 }
5685                                 *lighting_level = F_LIT_STANDARD;
5686                                 break;
5687
5688                         case 'C':
5689                         case 'c':
5690                                 if (!visual_list)
5691                                 {
5692                                         for (FEAT_IDX i = 0; i < F_LIT_MAX; i++)
5693                                         {
5694                                                 attr_idx_feat[i] = f_ptr->x_attr[i];
5695                                                 char_idx_feat[i] = f_ptr->x_char[i];
5696                                         }
5697                                 }
5698                                 break;
5699
5700                         case 'P':
5701                         case 'p':
5702                                 if (!visual_list)
5703                                 {
5704                                         /* Allow TERM_DARK text */
5705                                         for (FEAT_IDX i = F_LIT_NS_BEGIN; i < F_LIT_MAX; i++)
5706                                         {
5707                                                 if (attr_idx_feat[i] || (!(char_idx_feat[i] & 0x80) && char_idx_feat[i])) f_ptr->x_attr[i] = attr_idx_feat[i];
5708                                                 if (char_idx_feat[i]) f_ptr->x_char[i] = char_idx_feat[i];
5709                                         }
5710                                 }
5711                                 break;
5712                         }
5713                         continue;
5714                 }
5715
5716                 switch (ch)
5717                 {
5718                 case ESCAPE:
5719                 {
5720                         flag = TRUE;
5721                         break;
5722                 }
5723
5724                 default:
5725                 {
5726                         /* Move the cursor */
5727                         browser_cursor(ch, &column, &grp_cur, grp_cnt, &feat_cur, feat_cnt);
5728                         break;
5729                 }
5730                 }
5731         }
5732
5733         /* Free the "feat_idx" array */
5734         C_KILL(feat_idx, max_f_idx, FEAT_IDX);
5735 }
5736
5737
5738 /*
5739  * List wanted monsters
5740  * @param creature_ptr プレーヤーへの参照ポインタ
5741  * @return なし
5742  */
5743 static void do_cmd_knowledge_bounty(player_type *creature_ptr)
5744 {
5745         /* Open a new file */
5746         FILE *fff;
5747         GAME_TEXT file_name[1024];
5748         fff = my_fopen_temp(file_name, 1024);
5749         if (!fff)
5750         {
5751                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
5752                 msg_print(NULL);
5753                 return;
5754         }
5755
5756         fprintf(fff, _("今日のターゲット : %s\n", "Today's target : %s\n"),
5757                 (creature_ptr->today_mon ? r_name + r_info[creature_ptr->today_mon].name : _("不明", "unknown")));
5758         fprintf(fff, "\n");
5759         fprintf(fff, _("賞金首リスト\n", "List of wanted monsters\n"));
5760         fprintf(fff, "----------------------------------------------\n");
5761
5762         bool listed = FALSE;
5763         for (int i = 0; i < MAX_BOUNTY; i++)
5764         {
5765                 if (current_world_ptr->bounty_r_idx[i] <= 10000)
5766                 {
5767                         fprintf(fff, "%s\n", r_name + r_info[current_world_ptr->bounty_r_idx[i]].name);
5768                         listed = TRUE;
5769                 }
5770         }
5771
5772         if (!listed)
5773         {
5774                 fprintf(fff, "\n%s\n", _("賞金首はもう残っていません。", "There are no more wanted monster."));
5775         }
5776
5777         my_fclose(fff);
5778
5779         /* Display the file contents */
5780         (void)show_file(creature_ptr, TRUE, file_name, _("賞金首の一覧", "Wanted monsters"), 0, 0);
5781         fd_kill(file_name);
5782 }
5783
5784 /*
5785  * List virtues & status
5786  */
5787 static void do_cmd_knowledge_virtues(player_type *creature_ptr)
5788 {
5789         /* Open a new file */
5790         FILE *fff;
5791         GAME_TEXT file_name[1024];
5792         fff = my_fopen_temp(file_name, 1024);
5793         if (!fff)
5794         {
5795                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
5796                 msg_print(NULL);
5797                 return;
5798         }
5799
5800         fprintf(fff, _("現在の属性 : %s\n\n", "Your alignment : %s\n\n"), your_alignment(creature_ptr));
5801         dump_virtues(creature_ptr, fff);
5802         my_fclose(fff);
5803
5804         /* Display the file contents */
5805         (void)show_file(creature_ptr, TRUE, file_name, _("八つの徳", "Virtues"), 0, 0);
5806         fd_kill(file_name);
5807 }
5808
5809 /*
5810  * Dungeon
5811  */
5812 static void do_cmd_knowledge_dungeon(player_type *creature_ptr)
5813 {
5814         /* Open a new file */
5815         FILE *fff;
5816         GAME_TEXT file_name[1024];
5817         fff = my_fopen_temp(file_name, 1024);
5818         if (!fff)
5819         {
5820                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
5821                 msg_print(NULL);
5822                 return;
5823         }
5824
5825         for (int i = 1; i < current_world_ptr->max_d_idx; i++)
5826         {
5827                 bool seiha = FALSE;
5828
5829                 if (!d_info[i].maxdepth) continue;
5830                 if (!max_dlv[i]) continue;
5831                 if (d_info[i].final_guardian)
5832                 {
5833                         if (!r_info[d_info[i].final_guardian].max_num) seiha = TRUE;
5834                 }
5835                 else if (max_dlv[i] == d_info[i].maxdepth) seiha = TRUE;
5836
5837                 fprintf(fff, _("%c%-12s :  %3d 階\n", "%c%-16s :  level %3d\n"), seiha ? '!' : ' ', d_name + d_info[i].name, (int)max_dlv[i]);
5838         }
5839
5840         my_fclose(fff);
5841
5842         /* Display the file contents */
5843         (void)show_file(creature_ptr, TRUE, file_name, _("今までに入ったダンジョン", "Dungeon"), 0, 0);
5844         fd_kill(file_name);
5845 }
5846
5847
5848 /*
5849 * List virtues & status
5850 *
5851 */
5852 static void do_cmd_knowledge_stat(player_type *creature_ptr)
5853 {
5854         /* Open a new file */
5855         FILE *fff;
5856         GAME_TEXT file_name[1024];
5857         fff = my_fopen_temp(file_name, 1024);
5858         if (!fff)
5859         {
5860                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
5861                 msg_print(NULL);
5862                 return;
5863         }
5864
5865         int percent = (int)(((long)creature_ptr->player_hp[PY_MAX_LEVEL - 1] * 200L) /
5866                 (2 * creature_ptr->hitdie +
5867                 ((PY_MAX_LEVEL - 1 + 3) * (creature_ptr->hitdie + 1))));
5868
5869         if (creature_ptr->knowledge & KNOW_HPRATE)
5870                 fprintf(fff, _("現在の体力ランク : %d/100\n\n", "Your current Life Rating is %d/100.\n\n"), percent);
5871         else fprintf(fff, _("現在の体力ランク : ???\n\n", "Your current Life Rating is ???.\n\n"));
5872
5873         fprintf(fff, _("能力の最大値\n\n", "Limits of maximum stats\n\n"));
5874         for (int v_nr = 0; v_nr < A_MAX; v_nr++)
5875         {
5876                 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);
5877                 else fprintf(fff, "%s ???\n", stat_names[v_nr]);
5878         }
5879
5880         dump_yourself(creature_ptr, fff);
5881         my_fclose(fff);
5882
5883         /* Display the file contents */
5884         (void)show_file(creature_ptr, TRUE, file_name, _("自分に関する情報", "HP-rate & Max stat"), 0, 0);
5885         fd_kill(file_name);
5886 }
5887
5888
5889 /*
5890  * todo player_typeではなくQUEST_IDXを引数にすべきかもしれない
5891  * Print all active quests
5892  * @param creature_ptr プレーヤーへの参照ポインタ
5893  * @return なし
5894  */
5895 static void do_cmd_knowledge_quests_current(player_type *creature_ptr, FILE *fff)
5896 {
5897         char tmp_str[120];
5898         char rand_tmp_str[120] = "\0";
5899         GAME_TEXT name[MAX_NLEN];
5900         monster_race *r_ptr;
5901         int rand_level = 100;
5902         int total = 0;
5903
5904         fprintf(fff, _("《遂行中のクエスト》\n", "< Current Quest >\n"));
5905
5906         for (QUEST_IDX i = 1; i < max_q_idx; i++)
5907         {
5908                 bool is_print = quest[i].status == QUEST_STATUS_TAKEN;
5909                 is_print |= (quest[i].status == QUEST_STATUS_STAGE_COMPLETED) && (quest[i].type == QUEST_TYPE_TOWER);
5910                 is_print |= quest[i].status == QUEST_STATUS_COMPLETED;
5911                 if (!is_print)
5912                         continue;
5913
5914                 /* Set the quest number temporary */
5915                 QUEST_IDX old_quest = creature_ptr->current_floor_ptr->inside_quest;
5916
5917                 /* Clear the text */
5918                 for (int j = 0; j < 10; j++) quest_text[j][0] = '\0';
5919                 quest_text_line = 0;
5920
5921                 creature_ptr->current_floor_ptr->inside_quest = i;
5922
5923                 /* Get the quest text */
5924                 init_flags = INIT_SHOW_TEXT;
5925
5926                 process_dungeon_file(creature_ptr, "q_info.txt", 0, 0, 0, 0);
5927
5928                 /* Reset the old quest number */
5929                 creature_ptr->current_floor_ptr->inside_quest = old_quest;
5930
5931                 /* No info from "silent" quests */
5932                 if (quest[i].flags & QUEST_FLAG_SILENT) continue;
5933
5934                 total++;
5935
5936                 if (quest[i].type != QUEST_TYPE_RANDOM)
5937                 {
5938                         char note[80] = "\0";
5939
5940                         if (quest[i].status == QUEST_STATUS_TAKEN || quest[i].status == QUEST_STATUS_STAGE_COMPLETED)
5941                         {
5942                                 switch (quest[i].type)
5943                                 {
5944                                 case QUEST_TYPE_KILL_LEVEL:
5945                                 case QUEST_TYPE_KILL_ANY_LEVEL:
5946                                         r_ptr = &r_info[quest[i].r_idx];
5947                                         strcpy(name, r_name + r_ptr->name);
5948                                         if (quest[i].max_num > 1)
5949                                         {
5950 #ifdef JP
5951                                                 sprintf(note, " - %d 体の%sを倒す。(あと %d 体)",
5952                                                         (int)quest[i].max_num, name, (int)(quest[i].max_num - quest[i].cur_num));
5953 #else
5954                                                 plural_aux(name);
5955                                                 sprintf(note, " - kill %d %s, have killed %d.",
5956                                                         (int)quest[i].max_num, name, (int)quest[i].cur_num);
5957 #endif
5958                                         }
5959                                         else
5960                                                 sprintf(note, _(" - %sを倒す。", " - kill %s."), name);
5961                                         break;
5962
5963                                 case QUEST_TYPE_FIND_ARTIFACT:
5964                                         if (quest[i].k_idx)
5965                                         {
5966                                                 artifact_type *a_ptr = &a_info[quest[i].k_idx];
5967                                                 object_type forge;
5968                                                 object_type *q_ptr = &forge;
5969                                                 KIND_OBJECT_IDX k_idx = lookup_kind(a_ptr->tval, a_ptr->sval);
5970                                                 object_prep(q_ptr, k_idx);
5971                                                 q_ptr->name1 = quest[i].k_idx;
5972                                                 q_ptr->ident = IDENT_STORE;
5973                                                 object_desc(creature_ptr, name, q_ptr, OD_NAME_ONLY);
5974                                         }
5975                                         sprintf(note, _("\n   - %sを見つけ出す。", "\n   - Find %s."), name);
5976                                         break;
5977                                 case QUEST_TYPE_FIND_EXIT:
5978                                         sprintf(note, _(" - 出口に到達する。", " - Reach exit."));
5979                                         break;
5980
5981                                 case QUEST_TYPE_KILL_NUMBER:
5982 #ifdef JP
5983                                         sprintf(note, " - %d 体のモンスターを倒す。(あと %d 体)",
5984                                                 (int)quest[i].max_num, (int)(quest[i].max_num - quest[i].cur_num));
5985 #else
5986                                         sprintf(note, " - Kill %d monsters, have killed %d.",
5987                                                 (int)quest[i].max_num, (int)quest[i].cur_num);
5988 #endif
5989                                         break;
5990
5991                                 case QUEST_TYPE_KILL_ALL:
5992                                 case QUEST_TYPE_TOWER:
5993                                         sprintf(note, _(" - 全てのモンスターを倒す。", " - Kill all monsters."));
5994                                         break;
5995                                 }
5996                         }
5997
5998                         /* Print the quest info */
5999                         sprintf(tmp_str, _("  %s (危険度:%d階相当)%s\n", "  %s (Danger level: %d)%s\n"),
6000                                 quest[i].name, (int)quest[i].level, note);
6001
6002                         fputs(tmp_str, fff);
6003
6004                         if (quest[i].status == QUEST_STATUS_COMPLETED)
6005                         {
6006                                 sprintf(tmp_str, _("    クエスト達成 - まだ報酬を受けとってない。\n", "    Quest Completed - Unrewarded\n"));
6007                                 fputs(tmp_str, fff);
6008                                 continue;
6009                         }
6010
6011                         int k = 0;
6012                         while (quest_text[k][0] && k < 10)
6013                         {
6014                                 fprintf(fff, "    %s\n", quest_text[k]);
6015                                 k++;
6016                         }
6017
6018                         continue;
6019                 }
6020
6021                 /* QUEST_TYPE_RANDOM */
6022                 if (quest[i].level >= rand_level)
6023                         continue;
6024
6025                 /* New random */
6026                 rand_level = quest[i].level;
6027
6028                 if (max_dlv[DUNGEON_ANGBAND] < rand_level) continue;
6029
6030                 /* Print the quest info */
6031                 r_ptr = &r_info[quest[i].r_idx];
6032                 strcpy(name, r_name + r_ptr->name);
6033
6034                 if (quest[i].max_num <= 1)
6035                 {
6036                         sprintf(rand_tmp_str, _("  %s (%d 階) - %sを倒す。\n", "  %s (Dungeon level: %d)\n  Kill %s.\n"),
6037                                 quest[i].name, (int)quest[i].level, name);
6038                         continue;
6039                 }
6040
6041 #ifdef JP
6042                 sprintf(rand_tmp_str, "  %s (%d 階) - %d 体の%sを倒す。(あと %d 体)\n",
6043                         quest[i].name, (int)quest[i].level,
6044                         (int)quest[i].max_num, name, (int)(quest[i].max_num - quest[i].cur_num));
6045 #else
6046                 plural_aux(name);
6047
6048                 sprintf(rand_tmp_str, "  %s (Dungeon level: %d)\n  Kill %d %s, have killed %d.\n",
6049                         quest[i].name, (int)quest[i].level,
6050                         (int)quest[i].max_num, name, (int)quest[i].cur_num);
6051 #endif
6052         }
6053
6054         /* Print the current random quest  */
6055         if (rand_tmp_str[0]) fputs(rand_tmp_str, fff);
6056
6057         if (!total) fprintf(fff, _("  なし\n", "  Nothing.\n"));
6058 }
6059
6060
6061 static bool do_cmd_knowledge_quests_aux(player_type *player_ptr, FILE *fff, IDX q_idx)
6062 {
6063         char tmp_str[120];
6064         char playtime_str[16];
6065         quest_type* const q_ptr = &quest[q_idx];
6066
6067         floor_type *floor_ptr = player_ptr->current_floor_ptr;
6068         if (is_fixed_quest_idx(q_idx))
6069         {
6070                 /* Set the quest number temporary */
6071                 IDX old_quest = floor_ptr->inside_quest;
6072
6073                 floor_ptr->inside_quest = q_idx;
6074
6075                 /* Get the quest */
6076                 init_flags = INIT_NAME_ONLY;
6077
6078                 process_dungeon_file(player_ptr, "q_info.txt", 0, 0, 0, 0);
6079
6080                 /* Reset the old quest number */
6081                 floor_ptr->inside_quest = old_quest;
6082
6083                 /* No info from "silent" quests */
6084                 if (q_ptr->flags & QUEST_FLAG_SILENT) return FALSE;
6085         }
6086
6087         strnfmt(playtime_str, sizeof(playtime_str), "%02d:%02d:%02d",
6088                 q_ptr->comptime / (60 * 60), (q_ptr->comptime / 60) % 60, q_ptr->comptime % 60);
6089
6090         if (is_fixed_quest_idx(q_idx) || (q_ptr->r_idx == 0))
6091         {
6092                 /* Print the quest info */
6093                 sprintf(tmp_str,
6094                         _("  %-35s (危険度:%3d階相当) - レベル%2d - %s\n",
6095                                 "  %-35s (Danger  level: %3d) - level %2d - %s\n"),
6096                         q_ptr->name, (int)q_ptr->level, q_ptr->complev, playtime_str);
6097                 fputs(tmp_str, fff);
6098                 return TRUE;
6099         }
6100
6101         /* Print the quest info */
6102         if (q_ptr->complev == 0)
6103         {
6104                 sprintf(tmp_str,
6105                         _("  %-35s (%3d階)            -   不戦勝 - %s\n",
6106                                 "  %-35s (Dungeon level: %3d) - Unearned - %s\n"),
6107                         r_name + r_info[q_ptr->r_idx].name,
6108                         (int)q_ptr->level, playtime_str);
6109                 fputs(tmp_str, fff);
6110                 return TRUE;
6111         }
6112
6113         sprintf(tmp_str,
6114                 _("  %-35s (%3d階)            - レベル%2d - %s\n",
6115                         "  %-35s (Dungeon level: %3d) - level %2d - %s\n"),
6116                 r_name + r_info[q_ptr->r_idx].name,
6117                 (int)q_ptr->level,
6118                 q_ptr->complev,
6119                 playtime_str);
6120         fputs(tmp_str, fff);
6121         return TRUE;
6122 }
6123
6124
6125 /*
6126  * Print all finished quests
6127  * @param creature_ptr プレーヤーへの参照ポインタ
6128  * @param fff セーブファイル (展開済?)
6129  * @param quest_num[] 受注したことのあるクエスト群
6130  * @return なし
6131  */
6132 void do_cmd_knowledge_quests_completed(player_type *creature_ptr, FILE *fff, QUEST_IDX quest_num[])
6133 {
6134         fprintf(fff, _("《達成したクエスト》\n", "< Completed Quest >\n"));
6135         QUEST_IDX total = 0;
6136         for (QUEST_IDX i = 1; i < max_q_idx; i++)
6137         {
6138                 QUEST_IDX q_idx = quest_num[i];
6139                 quest_type* const q_ptr = &quest[q_idx];
6140
6141                 if (q_ptr->status == QUEST_STATUS_FINISHED && do_cmd_knowledge_quests_aux(creature_ptr, fff, q_idx))
6142                 {
6143                         ++total;
6144                 }
6145         }
6146
6147         if (!total) fprintf(fff, _("  なし\n", "  Nothing.\n"));
6148 }
6149
6150
6151 /*
6152  * Print all failed quests
6153  * @param creature_ptr プレーヤーへの参照ポインタ
6154  * @param fff セーブファイル (展開済?)
6155  * @param quest_num[] 受注したことのあるクエスト群
6156  * @return なし
6157 */
6158 void do_cmd_knowledge_quests_failed(player_type *creature_ptr, FILE *fff, QUEST_IDX quest_num[])
6159 {
6160         fprintf(fff, _("《失敗したクエスト》\n", "< Failed Quest >\n"));
6161         QUEST_IDX total = 0;
6162         for (QUEST_IDX i = 1; i < max_q_idx; i++)
6163         {
6164                 QUEST_IDX q_idx = quest_num[i];
6165                 quest_type* const q_ptr = &quest[q_idx];
6166
6167                 if (((q_ptr->status == QUEST_STATUS_FAILED_DONE) || (q_ptr->status == QUEST_STATUS_FAILED)) &&
6168                         do_cmd_knowledge_quests_aux(creature_ptr, fff, q_idx))
6169                 {
6170                         ++total;
6171                 }
6172         }
6173
6174         if (!total) fprintf(fff, _("  なし\n", "  Nothing.\n"));
6175 }
6176
6177
6178 /*
6179  * Print all random quests
6180  */
6181 static void do_cmd_knowledge_quests_wiz_random(FILE *fff)
6182 {
6183         fprintf(fff, _("《残りのランダムクエスト》\n", "< Remaining Random Quest >\n"));
6184         GAME_TEXT tmp_str[120];
6185         QUEST_IDX total = 0;
6186         for (QUEST_IDX i = 1; i < max_q_idx; i++)
6187         {
6188                 /* No info from "silent" quests */
6189                 if (quest[i].flags & QUEST_FLAG_SILENT) continue;
6190
6191                 if ((quest[i].type == QUEST_TYPE_RANDOM) && (quest[i].status == QUEST_STATUS_TAKEN))
6192                 {
6193                         total++;
6194
6195                         /* Print the quest info */
6196                         sprintf(tmp_str, _("  %s (%d階, %s)\n", "  %s (%d, %s)\n"),
6197                                 quest[i].name, (int)quest[i].level, r_name + r_info[quest[i].r_idx].name);
6198                         fputs(tmp_str, fff);
6199                 }
6200         }
6201
6202         if (!total) fprintf(fff, _("  なし\n", "  Nothing.\n"));
6203 }
6204
6205 /*
6206  * Print quest status of all active quests
6207  * @param creature_ptr プレーヤーへの参照ポインタ
6208  * @return なし
6209  */
6210 static void do_cmd_knowledge_quests(player_type *creature_ptr)
6211 {
6212         /* Open a new file */
6213         FILE *fff;
6214         GAME_TEXT file_name[1024];
6215         fff = my_fopen_temp(file_name, 1024);
6216         if (!fff)
6217         {
6218                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
6219                 msg_print(NULL);
6220                 return;
6221         }
6222
6223         /* Allocate Memory */
6224         IDX *quest_num;
6225         C_MAKE(quest_num, max_q_idx, QUEST_IDX);
6226
6227         /* Sort by compete level */
6228         for (IDX i = 1; i < max_q_idx; i++) quest_num[i] = i;
6229         int dummy;
6230         ang_sort(quest_num, &dummy, max_q_idx, ang_sort_comp_quest_num, ang_sort_swap_quest_num);
6231
6232         /* Dump Quest Information */
6233         do_cmd_knowledge_quests_current(creature_ptr, fff);
6234         fputc('\n', fff);
6235         do_cmd_knowledge_quests_completed(creature_ptr, fff, quest_num);
6236         fputc('\n', fff);
6237         do_cmd_knowledge_quests_failed(creature_ptr, fff, quest_num);
6238         if (current_world_ptr->wizard)
6239         {
6240                 fputc('\n', fff);
6241                 do_cmd_knowledge_quests_wiz_random(fff);
6242         }
6243
6244         my_fclose(fff);
6245
6246         /* Display the file contents */
6247         (void)show_file(creature_ptr, TRUE, file_name, _("クエスト達成状況", "Quest status"), 0, 0);
6248         fd_kill(file_name);
6249
6250         /* Free Memory */
6251         C_KILL(quest_num, max_q_idx, QUEST_IDX);
6252 }
6253
6254
6255 /*
6256  * List my home
6257  * @param player_ptr プレーヤーへの参照ポインタ
6258  * @return なし
6259  */
6260 static void do_cmd_knowledge_home(player_type *player_ptr)
6261 {
6262         process_dungeon_file(player_ptr, "w_info.txt", 0, 0, current_world_ptr->max_wild_y, current_world_ptr->max_wild_x);
6263
6264         /* Open a new file */
6265         FILE *fff;
6266         GAME_TEXT file_name[1024];
6267         fff = my_fopen_temp(file_name, 1024);
6268         if (!fff)
6269         {
6270                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
6271                 msg_print(NULL);
6272                 return;
6273         }
6274
6275         /* Print all homes in the different towns */
6276         store_type *st_ptr;
6277         st_ptr = &town_info[1].store[STORE_HOME];
6278
6279         /* Home -- if anything there */
6280         if (st_ptr->stock_num)
6281         {
6282 #ifdef JP
6283                 TERM_LEN x = 1;
6284 #endif
6285                 /* Header with name of the town */
6286                 fprintf(fff, _("  [ 我が家のアイテム ]\n", "  [Home Inventory]\n"));
6287
6288                 /* Dump all available items */
6289                 concptr paren = ")";
6290                 GAME_TEXT o_name[MAX_NLEN];
6291                 for (int i = 0; i < st_ptr->stock_num; i++)
6292                 {
6293 #ifdef JP
6294                         if ((i % 12) == 0) fprintf(fff, "\n ( %d ページ )\n", x++);
6295                         object_desc(player_ptr, o_name, &st_ptr->stock[i], 0);
6296                         if (strlen(o_name) <= 80 - 3)
6297                         {
6298                                 fprintf(fff, "%c%s %s\n", I2A(i % 12), paren, o_name);
6299                         }
6300                         else
6301                         {
6302                                 int n;
6303                                 char *t;
6304                                 for (n = 0, t = o_name; n < 80 - 3; n++, t++)
6305                                         if (iskanji(*t)) { t++; n++; }
6306                                 if (n == 81 - 3) n = 79 - 3; /* 最後が漢字半分 */
6307
6308                                 fprintf(fff, "%c%s %.*s\n", I2A(i % 12), paren, n, o_name);
6309                                 fprintf(fff, "   %.77s\n", o_name + n);
6310                         }
6311 #else
6312                         object_desc(player_ptr, o_name, &st_ptr->stock[i], 0);
6313                         fprintf(fff, "%c%s %s\n", I2A(i % 12), paren, o_name);
6314 #endif
6315                 }
6316
6317                 /* Add an empty line */
6318                 fprintf(fff, "\n\n");
6319         }
6320
6321         my_fclose(fff);
6322
6323         /* Display the file contents */
6324         (void)show_file(player_ptr, TRUE, file_name, _("我が家のアイテム", "Home Inventory"), 0, 0);
6325         fd_kill(file_name);
6326 }
6327
6328
6329 /*
6330  * Check the status of "autopick"
6331  */
6332 static void do_cmd_knowledge_autopick(player_type *creature_ptr)
6333 {
6334         /* Open a new file */
6335         FILE *fff;
6336         GAME_TEXT file_name[1024];
6337         fff = my_fopen_temp(file_name, 1024);
6338         if (!fff)
6339         {
6340                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
6341                 msg_print(NULL);
6342                 return;
6343         }
6344
6345         if (!max_autopick)
6346         {
6347                 fprintf(fff, _("自動破壊/拾いには何も登録されていません。", "No preference for auto picker/destroyer."));
6348         }
6349         else
6350         {
6351                 fprintf(fff, _("   自動拾い/破壊には現在 %d行登録されています。\n\n",
6352                         "   There are %d registered lines for auto picker/destroyer.\n\n"), max_autopick);
6353         }
6354
6355         for (int k = 0; k < max_autopick; k++)
6356         {
6357                 concptr tmp;
6358                 byte act = autopick_list[k].action;
6359                 if (act & DONT_AUTOPICK)
6360                 {
6361                         tmp = _("放置", "Leave");
6362                 }
6363                 else if (act & DO_AUTODESTROY)
6364                 {
6365                         tmp = _("破壊", "Destroy");
6366                 }
6367                 else if (act & DO_AUTOPICK)
6368                 {
6369                         tmp = _("拾う", "Pickup");
6370                 }
6371                 else
6372                 {
6373                         tmp = _("確認", "Query");
6374                 }
6375
6376                 if (act & DO_DISPLAY)
6377                         fprintf(fff, "%11s", format("[%s]", tmp));
6378                 else
6379                         fprintf(fff, "%11s", format("(%s)", tmp));
6380
6381                 tmp = autopick_line_from_entry(&autopick_list[k]);
6382                 fprintf(fff, " %s", tmp);
6383                 string_free(tmp);
6384                 fprintf(fff, "\n");
6385         }
6386
6387         my_fclose(fff);
6388
6389         /* Display the file contents */
6390         (void)show_file(creature_ptr, TRUE, file_name, _("自動拾い/破壊 設定リスト", "Auto-picker/Destroyer"), 0, 0);
6391         fd_kill(file_name);
6392 }
6393
6394
6395 /*
6396  * Interact with "knowledge"
6397  */
6398 void do_cmd_knowledge(player_type *creature_ptr)
6399 {
6400         int i, p = 0;
6401         bool need_redraw = FALSE;
6402
6403         /* File type is "TEXT" */
6404         FILE_TYPE(FILE_TYPE_TEXT);
6405         screen_save();
6406
6407         /* Interact until done */
6408         while (TRUE)
6409         {
6410                 Term_clear();
6411
6412                 /* Ask for a choice */
6413                 prt(format(_("%d/2 ページ", "page %d/2"), (p + 1)), 2, 65);
6414                 prt(_("現在の知識を確認する", "Display current knowledge"), 3, 0);
6415
6416                 /* Give some choices */
6417 #ifdef JP
6418                 if (p == 0)
6419                 {
6420                         prt("(1) 既知の伝説のアイテム                 の一覧", 6, 5);
6421                         prt("(2) 既知のアイテム                       の一覧", 7, 5);
6422                         prt("(3) 既知の生きているユニーク・モンスター の一覧", 8, 5);
6423                         prt("(4) 既知のモンスター                     の一覧", 9, 5);
6424                         prt("(5) 倒した敵の数                         の一覧", 10, 5);
6425                         if (!vanilla_town) prt("(6) 賞金首                               の一覧", 11, 5);
6426                         prt("(7) 現在のペット                         の一覧", 12, 5);
6427                         prt("(8) 我が家のアイテム                     の一覧", 13, 5);
6428                         prt("(9) *鑑定*済み装備の耐性                 の一覧", 14, 5);
6429                         prt("(0) 地形の表示文字/タイル                の一覧", 15, 5);
6430                 }
6431                 else
6432                 {
6433                         prt("(a) 自分に関する情報                     の一覧", 6, 5);
6434                         prt("(b) 突然変異                             の一覧", 7, 5);
6435                         prt("(c) 武器の経験値                         の一覧", 8, 5);
6436                         prt("(d) 魔法の経験値                         の一覧", 9, 5);
6437                         prt("(e) 技能の経験値                         の一覧", 10, 5);
6438                         prt("(f) プレイヤーの徳                       の一覧", 11, 5);
6439                         prt("(g) 入ったダンジョン                     の一覧", 12, 5);
6440                         prt("(h) 実行中のクエスト                     の一覧", 13, 5);
6441                         prt("(i) 現在の自動拾い/破壊設定              の一覧", 14, 5);
6442                 }
6443 #else
6444                 if (p == 0)
6445                 {
6446                         prt("(1) Display known artifacts", 6, 5);
6447                         prt("(2) Display known objects", 7, 5);
6448                         prt("(3) Display remaining uniques", 8, 5);
6449                         prt("(4) Display known monster", 9, 5);
6450                         prt("(5) Display kill count", 10, 5);
6451                         if (!vanilla_town) prt("(6) Display wanted monsters", 11, 5);
6452                         prt("(7) Display current pets", 12, 5);
6453                         prt("(8) Display home inventory", 13, 5);
6454                         prt("(9) Display *identified* equip.", 14, 5);
6455                         prt("(0) Display terrain symbols.", 15, 5);
6456                 }
6457                 else
6458                 {
6459                         prt("(a) Display about yourself", 6, 5);
6460                         prt("(b) Display mutations", 7, 5);
6461                         prt("(c) Display weapon proficiency", 8, 5);
6462                         prt("(d) Display spell proficiency", 9, 5);
6463                         prt("(e) Display misc. proficiency", 10, 5);
6464                         prt("(f) Display virtues", 11, 5);
6465                         prt("(g) Display dungeons", 12, 5);
6466                         prt("(h) Display current quests", 13, 5);
6467                         prt("(i) Display auto pick/destroy", 14, 5);
6468                 }
6469 #endif
6470                 /* Prompt */
6471                 prt(_("-続く-", "-more-"), 17, 8);
6472                 prt(_("ESC) 抜ける", "ESC) Exit menu"), 21, 1);
6473                 prt(_("SPACE) 次ページ", "SPACE) Next page"), 21, 30);
6474                 /*prt("-) 前ページ", 21, 60);*/
6475                 prt(_("コマンド:", "Command: "), 20, 0);
6476                 i = inkey();
6477
6478                 if (i == ESCAPE) break;
6479                 switch (i)
6480                 {
6481                 case ' ': /* Page change */
6482                 case '-':
6483                         p = 1 - p;
6484                         break;
6485                 case '1': /* Artifacts */
6486                         do_cmd_knowledge_artifacts(creature_ptr);
6487                         break;
6488                 case '2': /* Objects */
6489                         do_cmd_knowledge_objects(creature_ptr, &need_redraw, FALSE, -1);
6490                         break;
6491                 case '3': /* Uniques */
6492                         do_cmd_knowledge_uniques(creature_ptr);
6493                         break;
6494                 case '4': /* Monsters */
6495                         do_cmd_knowledge_monsters(creature_ptr, &need_redraw, FALSE, -1);
6496                         break;
6497                 case '5': /* Kill count  */
6498                         do_cmd_knowledge_kill_count(creature_ptr);
6499                         break;
6500                 case '6': /* wanted */
6501                         if (!vanilla_town) do_cmd_knowledge_bounty(creature_ptr);
6502                         break;
6503                 case '7': /* Pets */
6504                         do_cmd_knowledge_pets(creature_ptr);
6505                         break;
6506                 case '8': /* Home */
6507                         do_cmd_knowledge_home(creature_ptr);
6508                         break;
6509                 case '9': /* Resist list */
6510                         do_cmd_knowledge_inven(creature_ptr);
6511                         break;
6512                 case '0': /* Feature list */
6513                 {
6514                         IDX lighting_level = F_LIT_STANDARD;
6515                         do_cmd_knowledge_features(&need_redraw, FALSE, -1, &lighting_level);
6516                 }
6517                 break;
6518                 /* Next page */
6519                 case 'a': /* Max stat */
6520                         do_cmd_knowledge_stat(creature_ptr);
6521                         break;
6522                 case 'b': /* Mutations */
6523                         do_cmd_knowledge_mutations(creature_ptr);
6524                         break;
6525                 case 'c': /* weapon-exp */
6526                         do_cmd_knowledge_weapon_exp(creature_ptr);
6527                         break;
6528                 case 'd': /* spell-exp */
6529                         do_cmd_knowledge_spell_exp(creature_ptr);
6530                         break;
6531                 case 'e': /* skill-exp */
6532                         do_cmd_knowledge_skill_exp(creature_ptr);
6533                         break;
6534                 case 'f': /* Virtues */
6535                         do_cmd_knowledge_virtues(creature_ptr);
6536                         break;
6537                 case 'g': /* Dungeon */
6538                         do_cmd_knowledge_dungeon(creature_ptr);
6539                         break;
6540                 case 'h': /* Quests */
6541                         do_cmd_knowledge_quests(creature_ptr);
6542                         break;
6543                 case 'i': /* Autopick */
6544                         do_cmd_knowledge_autopick(creature_ptr);
6545                         break;
6546                 default: /* Unknown option */
6547                         bell();
6548                 }
6549
6550                 msg_erase();
6551         }
6552
6553         screen_load();
6554         if (need_redraw) do_cmd_redraw(creature_ptr);
6555 }
6556
6557
6558 /*
6559  * Check on the status of an active quest
6560  * @param creature_ptr プレーヤーへの参照ポインタ
6561  * @return なし
6562  */
6563 void do_cmd_checkquest(player_type *creature_ptr)
6564 {
6565         /* File type is "TEXT" */
6566         FILE_TYPE(FILE_TYPE_TEXT);
6567         screen_save();
6568
6569         /* Quest info */
6570         do_cmd_knowledge_quests(creature_ptr);
6571         screen_load();
6572 }
6573
6574
6575 /*
6576  * Display the time and date
6577  * @param creature_ptr プレーヤーへの参照ポインタ
6578  * @return なし
6579  */
6580 void do_cmd_time(player_type *creature_ptr)
6581 {
6582         int day, hour, min;
6583         extract_day_hour_min(creature_ptr, &day, &hour, &min);
6584
6585         char desc[1024];
6586         strcpy(desc, _("変な時刻だ。", "It is a strange time."));
6587
6588         char day_buf[10];
6589         if (day < MAX_DAYS) sprintf(day_buf, "%d", day);
6590         else strcpy(day_buf, "*****");
6591
6592         msg_format(_("%s日目, 時刻は%d:%02d %sです。", "This is day %s. The time is %d:%02d %s."),
6593                 day_buf, (hour % 12 == 0) ? 12 : (hour % 12), min, (hour < 12) ? "AM" : "PM");
6594
6595         /* Find the path */
6596         char buf[1024];
6597         if (!randint0(10) || creature_ptr->image)
6598         {
6599                 path_build(buf, sizeof(buf), ANGBAND_DIR_FILE, _("timefun_j.txt", "timefun.txt"));
6600         }
6601         else
6602         {
6603                 path_build(buf, sizeof(buf), ANGBAND_DIR_FILE, _("timenorm_j.txt", "timenorm.txt"));
6604         }
6605
6606         /* Open this file */
6607         FILE *fff;
6608         fff = my_fopen(buf, "rt");
6609
6610         if (!fff) return;
6611
6612         /* Find this time */
6613         int full = hour * 100 + min;
6614         int start = 9999;
6615         int end = -9999;
6616         int num = 0;
6617         while (!my_fgets(fff, buf, sizeof(buf)))
6618         {
6619                 /* Ignore comments */
6620                 if (!buf[0] || (buf[0] == '#')) continue;
6621
6622                 /* Ignore invalid lines */
6623                 if (buf[1] != ':') continue;
6624
6625                 /* Process 'Start' */
6626                 if (buf[0] == 'S')
6627                 {
6628                         /* Extract the starting time */
6629                         start = atoi(buf + 2);
6630
6631                         /* Assume valid for an hour */
6632                         end = start + 59;
6633                         continue;
6634                 }
6635
6636                 /* Process 'End' */
6637                 if (buf[0] == 'E')
6638                 {
6639                         /* Extract the ending time */
6640                         end = atoi(buf + 2);
6641                         continue;
6642                 }
6643
6644                 /* Ignore incorrect range */
6645                 if ((start > full) || (full > end)) continue;
6646
6647                 /* Process 'Description' */
6648                 if (buf[0] == 'D')
6649                 {
6650                         num++;
6651
6652                         /* Apply the randomizer */
6653                         if (!randint0(num)) strcpy(desc, buf + 2);
6654                         continue;
6655                 }
6656         }
6657
6658         msg_print(desc);
6659         my_fclose(fff);
6660 }