OSDN Git Service

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