OSDN Git Service

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