OSDN Git Service

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