OSDN Git Service

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