OSDN Git Service

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