OSDN Git Service

Merge remote-tracking branch 'remotes/origin/feature/Refactoring-Hourier' into For2...
[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 #ifdef ALLOW_MACROS
1384
1385
1386 /*!
1387  * @brief マクロ情報をprefファイルに保存する /
1388  * @param fname ファイル名
1389  * @return なし
1390  */
1391 static errr macro_dump(concptr fname)
1392 {
1393         static concptr mark = "Macro Dump";
1394         char buf[1024];
1395         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, fname);
1396
1397         /* File type is "TEXT" */
1398         FILE_TYPE(FILE_TYPE_TEXT);
1399
1400         /* Append to the file */
1401         if (!open_auto_dump(buf, mark)) return -1;
1402
1403         /* Start dumping */
1404         auto_dump_printf(_("\n# 自動マクロセーブ\n\n", "\n# Automatic macro dump\n\n"));
1405
1406         /* Dump them */
1407         for (int i = 0; i < macro__num; i++)
1408         {
1409                 /* Extract the action */
1410                 ascii_to_text(buf, macro__act[i]);
1411
1412                 /* Dump the macro */
1413                 auto_dump_printf("A:%s\n", buf);
1414
1415                 /* Extract the action */
1416                 ascii_to_text(buf, macro__pat[i]);
1417
1418                 /* Dump normal macros */
1419                 auto_dump_printf("P:%s\n", buf);
1420
1421                 /* End the macro */
1422                 auto_dump_printf("\n");
1423         }
1424
1425         close_auto_dump();
1426         return 0;
1427 }
1428
1429
1430 /*!
1431  * @brief マクロのトリガーキーを取得する /
1432  * Hack -- ask for a "trigger" (see below)
1433  * @param buf キー表記を保管するバッファ
1434  * @return なし
1435  * @details
1436  * <pre>
1437  * Note the complex use of the "inkey()" function from "util.c".
1438  *
1439  * Note that both "flush()" calls are extremely important.
1440  * </pre>
1441  */
1442 static void do_cmd_macro_aux(char *buf)
1443 {
1444         flush();
1445
1446         /* Do not process macros */
1447         inkey_base = TRUE;
1448
1449         /* First key */
1450         char i = inkey();
1451
1452         /* Read the pattern */
1453         int n = 0;
1454         while (i)
1455         {
1456                 /* Save the key */
1457                 buf[n++] = i;
1458
1459                 /* Do not process macros */
1460                 inkey_base = TRUE;
1461
1462                 /* Do not wait for keys */
1463                 inkey_scan = TRUE;
1464
1465                 /* Attempt to read a key */
1466                 i = inkey();
1467         }
1468
1469         /* Terminate */
1470         buf[n] = '\0';
1471
1472         flush();
1473
1474         /* Convert the trigger */
1475         char tmp[1024];
1476         ascii_to_text(tmp, buf);
1477
1478         /* Hack -- display the trigger */
1479         Term_addstr(-1, TERM_WHITE, tmp);
1480 }
1481
1482 #endif
1483
1484 /*!
1485  * @brief マクロのキー表記からアスキーコードを得てターミナルに表示する /
1486  * Hack -- ask for a keymap "trigger" (see below)
1487  * @param buf キー表記を取得するバッファ
1488  * @return なし
1489  * @details
1490  * <pre>
1491  * Note that both "flush()" calls are extremely important.  This may
1492  * no longer be true, since "util.c" is much simpler now.
1493  * </pre>
1494  */
1495 static void do_cmd_macro_aux_keymap(char *buf)
1496 {
1497         char tmp[1024];
1498
1499         flush();
1500
1501         /* Get a key */
1502         buf[0] = inkey();
1503         buf[1] = '\0';
1504
1505         /* Convert to ascii */
1506         ascii_to_text(tmp, buf);
1507
1508         /* Hack -- display the trigger */
1509         Term_addstr(-1, TERM_WHITE, tmp);
1510
1511         flush();
1512 }
1513
1514
1515 /*!
1516  * @brief キーマップをprefファイルにダンプする /
1517  * Hack -- append all keymaps to the given file
1518  * @param fname ファイルネーム
1519  * @return エラーコード
1520  * @details
1521  */
1522 static errr keymap_dump(concptr fname)
1523 {
1524         static concptr mark = "Keymap Dump";
1525         char key[1024];
1526         char buf[1024];
1527
1528         BIT_FLAGS mode;
1529
1530         /* Roguelike */
1531         if (rogue_like_commands)
1532         {
1533                 mode = KEYMAP_MODE_ROGUE;
1534         }
1535
1536         /* Original */
1537         else
1538         {
1539                 mode = KEYMAP_MODE_ORIG;
1540         }
1541
1542         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, fname);
1543
1544         /* File type is "TEXT" */
1545         FILE_TYPE(FILE_TYPE_TEXT);
1546
1547         /* Append to the file */
1548         if (!open_auto_dump(buf, mark)) return -1;
1549
1550         /* Start dumping */
1551         auto_dump_printf(_("\n# 自動キー配置セーブ\n\n", "\n# Automatic keymap dump\n\n"));
1552
1553         /* Dump them */
1554         for (int i = 0; i < 256; i++)
1555         {
1556                 concptr act;
1557
1558                 /* Loop up the keymap */
1559                 act = keymap_act[mode][i];
1560
1561                 /* Skip empty keymaps */
1562                 if (!act) continue;
1563
1564                 /* Encode the key */
1565                 buf[0] = (char)i;
1566                 buf[1] = '\0';
1567                 ascii_to_text(key, buf);
1568
1569                 /* Encode the action */
1570                 ascii_to_text(buf, act);
1571
1572                 /* Dump the macro */
1573                 auto_dump_printf("A:%s\n", buf);
1574                 auto_dump_printf("C:%d:%s\n", mode, key);
1575         }
1576
1577         close_auto_dump();
1578         return 0;
1579 }
1580
1581
1582 /*!
1583  * @brief マクロを設定するコマンドのメインルーチン /
1584  * Interact with "macros"
1585  * @return なし
1586  * @details
1587  * <pre>
1588  * Note that the macro "action" must be defined before the trigger.
1589  *
1590  * Could use some helpful instructions on this page.
1591  * </pre>
1592  */
1593 void do_cmd_macros(player_type *creature_ptr)
1594 {
1595         int i;
1596         char tmp[1024];
1597         char buf[1024];
1598         BIT_FLAGS mode;
1599
1600         /* Roguelike */
1601         if (rogue_like_commands)
1602         {
1603                 mode = KEYMAP_MODE_ROGUE;
1604         }
1605
1606         /* Original */
1607         else
1608         {
1609                 mode = KEYMAP_MODE_ORIG;
1610         }
1611
1612         /* File type is "TEXT" */
1613         FILE_TYPE(FILE_TYPE_TEXT);
1614
1615         screen_save();
1616
1617         /* Process requests until done */
1618         while (TRUE)
1619         {
1620                 Term_clear();
1621                 prt(_("[ マクロの設定 ]", "Interact with Macros"), 2, 0);
1622
1623                 /* Describe that action */
1624                 prt(_("マクロ行動が(もしあれば)下に表示されます:", "Current action (if any) shown below:"), 20, 0);
1625
1626                 /* Analyze the current action */
1627                 ascii_to_text(buf, macro__buf);
1628
1629                 /* Display the current action */
1630                 prt(buf, 22, 0);
1631
1632
1633                 /* Selections */
1634                 prt(_("(1) ユーザー設定ファイルのロード", "(1) Load a user pref file"), 4, 5);
1635 #ifdef ALLOW_MACROS
1636                 prt(_("(2) ファイルにマクロを追加", "(2) Append macros to a file"), 5, 5);
1637                 prt(_("(3) マクロの確認", "(3) Query a macro"), 6, 5);
1638                 prt(_("(4) マクロの作成", "(4) Create a macro"), 7, 5);
1639                 prt(_("(5) マクロの削除", "(5) Remove a macro"), 8, 5);
1640                 prt(_("(6) ファイルにキー配置を追加", "(6) Append keymaps to a file"), 9, 5);
1641                 prt(_("(7) キー配置の確認", "(7) Query a keymap"), 10, 5);
1642                 prt(_("(8) キー配置の作成", "(8) Create a keymap"), 11, 5);
1643                 prt(_("(9) キー配置の削除", "(9) Remove a keymap"), 12, 5);
1644                 prt(_("(0) マクロ行動の入力", "(0) Enter a new action"), 13, 5);
1645 #endif /* ALLOW_MACROS */
1646
1647                 /* Prompt */
1648                 prt(_("コマンド: ", "Command: "), 16, 0);
1649
1650                 i = inkey();
1651
1652                 /* Leave */
1653                 if (i == ESCAPE) break;
1654
1655                 /* Load a 'macro' file */
1656                 else if (i == '1')
1657                 {
1658                         errr err;
1659
1660                         /* Prompt */
1661                         prt(_("コマンド: ユーザー設定ファイルのロード", "Command: Load a user pref file"), 16, 0);
1662
1663                         /* Prompt */
1664                         prt(_("ファイル: ", "File: "), 18, 0);
1665
1666                         /* Default filename */
1667                         sprintf(tmp, "%s.prf", creature_ptr->base_name);
1668
1669                         /* Ask for a file */
1670                         if (!askfor(tmp, 80)) continue;
1671
1672                         /* Process the given filename */
1673                         err = process_pref_file(creature_ptr, tmp);
1674                         if (-2 == err)
1675                         {
1676                                 msg_format(_("標準の設定ファイル'%s'を読み込みました。", "Loaded default '%s'."), tmp);
1677                         }
1678                         else if (err)
1679                         {
1680                                 /* Prompt */
1681                                 msg_format(_("'%s'の読み込みに失敗しました!", "Failed to load '%s'!"), tmp);
1682                         }
1683                         else
1684                         {
1685                                 msg_format(_("'%s'を読み込みました。", "Loaded '%s'."), tmp);
1686                         }
1687                 }
1688
1689 #ifdef ALLOW_MACROS
1690                 /* Save macros */
1691                 else if (i == '2')
1692                 {
1693                         /* Prompt */
1694                         prt(_("コマンド: マクロをファイルに追加する", "Command: Append macros to a file"), 16, 0);
1695
1696                         /* Prompt */
1697                         prt(_("ファイル: ", "File: "), 18, 0);
1698
1699                         /* Default filename */
1700                         sprintf(tmp, "%s.prf", creature_ptr->base_name);
1701
1702                         /* Ask for a file */
1703                         if (!askfor(tmp, 80)) continue;
1704
1705                         /* Dump the macros */
1706                         (void)macro_dump(tmp);
1707
1708                         /* Prompt */
1709                         msg_print(_("マクロを追加しました。", "Appended macros."));
1710                 }
1711
1712                 /* Query a macro */
1713                 else if (i == '3')
1714                 {
1715                         int k;
1716
1717                         /* Prompt */
1718                         prt(_("コマンド: マクロの確認", "Command: Query a macro"), 16, 0);
1719
1720
1721                         /* Prompt */
1722                         prt(_("トリガーキー: ", "Trigger: "), 18, 0);
1723
1724                         /* Get a macro trigger */
1725                         do_cmd_macro_aux(buf);
1726
1727                         /* Acquire action */
1728                         k = macro_find_exact(buf);
1729
1730                         /* Nothing found */
1731                         if (k < 0)
1732                         {
1733                                 /* Prompt */
1734                                 msg_print(_("そのキーにはマクロは定義されていません。", "Found no macro."));
1735                         }
1736
1737                         /* Found one */
1738                         else
1739                         {
1740                                 /* Obtain the action */
1741                                 strcpy(macro__buf, macro__act[k]);
1742
1743                                 /* Analyze the current action */
1744                                 ascii_to_text(buf, macro__buf);
1745
1746                                 /* Display the current action */
1747                                 prt(buf, 22, 0);
1748
1749                                 /* Prompt */
1750                                 msg_print(_("マクロを確認しました。", "Found a macro."));
1751                         }
1752                 }
1753
1754                 /* Create a macro */
1755                 else if (i == '4')
1756                 {
1757                         /* Prompt */
1758                         prt(_("コマンド: マクロの作成", "Command: Create a macro"), 16, 0);
1759
1760                         /* Prompt */
1761                         prt(_("トリガーキー: ", "Trigger: "), 18, 0);
1762
1763                         /* Get a macro trigger */
1764                         do_cmd_macro_aux(buf);
1765                         clear_from(20);
1766
1767                         /* Help message */
1768                         c_prt(TERM_L_RED, _("カーソルキーの左右でカーソル位置を移動。BackspaceかDeleteで一文字削除。",
1769                                 "Press Left/Right arrow keys to move cursor. Backspace/Delete to delete a char."), 22, 0);
1770
1771                         /* Prompt */
1772                         prt(_("マクロ行動: ", "Action: "), 20, 0);
1773
1774                         /* Convert to text */
1775                         ascii_to_text(tmp, macro__buf);
1776
1777                         /* Get an encoded action */
1778                         if (askfor(tmp, 80))
1779                         {
1780                                 /* Convert to ascii */
1781                                 text_to_ascii(macro__buf, tmp);
1782
1783                                 /* Link the macro */
1784                                 macro_add(buf, macro__buf);
1785
1786                                 /* Prompt */
1787                                 msg_print(_("マクロを追加しました。", "Added a macro."));
1788                         }
1789                 }
1790
1791                 /* Remove a macro */
1792                 else if (i == '5')
1793                 {
1794                         /* Prompt */
1795                         prt(_("コマンド: マクロの削除", "Command: Remove a macro"), 16, 0);
1796
1797                         /* Prompt */
1798                         prt(_("トリガーキー: ", "Trigger: "), 18, 0);
1799
1800                         /* Get a macro trigger */
1801                         do_cmd_macro_aux(buf);
1802
1803                         /* Link the macro */
1804                         macro_add(buf, buf);
1805
1806                         /* Prompt */
1807                         msg_print(_("マクロを削除しました。", "Removed a macro."));
1808                 }
1809
1810                 /* Save keymaps */
1811                 else if (i == '6')
1812                 {
1813                         /* Prompt */
1814                         prt(_("コマンド: キー配置をファイルに追加する", "Command: Append keymaps to a file"), 16, 0);
1815
1816                         /* Prompt */
1817                         prt(_("ファイル: ", "File: "), 18, 0);
1818
1819                         /* Default filename */
1820                         sprintf(tmp, "%s.prf", creature_ptr->base_name);
1821
1822                         /* Ask for a file */
1823                         if (!askfor(tmp, 80)) continue;
1824
1825                         /* Dump the macros */
1826                         (void)keymap_dump(tmp);
1827
1828                         /* Prompt */
1829                         msg_print(_("キー配置を追加しました。", "Appended keymaps."));
1830                 }
1831
1832                 /* Query a keymap */
1833                 else if (i == '7')
1834                 {
1835                         concptr act;
1836
1837                         /* Prompt */
1838                         prt(_("コマンド: キー配置の確認", "Command: Query a keymap"), 16, 0);
1839
1840                         /* Prompt */
1841                         prt(_("押すキー: ", "Keypress: "), 18, 0);
1842
1843                         /* Get a keymap trigger */
1844                         do_cmd_macro_aux_keymap(buf);
1845
1846                         /* Look up the keymap */
1847                         act = keymap_act[mode][(byte)(buf[0])];
1848
1849                         /* Nothing found */
1850                         if (!act)
1851                         {
1852                                 /* Prompt */
1853                                 msg_print(_("キー配置は定義されていません。", "Found no keymap."));
1854                         }
1855
1856                         /* Found one */
1857                         else
1858                         {
1859                                 /* Obtain the action */
1860                                 strcpy(macro__buf, act);
1861
1862                                 /* Analyze the current action */
1863                                 ascii_to_text(buf, macro__buf);
1864
1865                                 /* Display the current action */
1866                                 prt(buf, 22, 0);
1867
1868                                 /* Prompt */
1869                                 msg_print(_("キー配置を確認しました。", "Found a keymap."));
1870                         }
1871                 }
1872
1873                 /* Create a keymap */
1874                 else if (i == '8')
1875                 {
1876                         /* Prompt */
1877                         prt(_("コマンド: キー配置の作成", "Command: Create a keymap"), 16, 0);
1878
1879                         /* Prompt */
1880                         prt(_("押すキー: ", "Keypress: "), 18, 0);
1881
1882                         /* Get a keymap trigger */
1883                         do_cmd_macro_aux_keymap(buf);
1884                         clear_from(20);
1885
1886                         /* Help message */
1887                         c_prt(TERM_L_RED, _("カーソルキーの左右でカーソル位置を移動。BackspaceかDeleteで一文字削除。",
1888                                 "Press Left/Right arrow keys to move cursor. Backspace/Delete to delete a char."), 22, 0);
1889
1890                         /* Prompt */
1891                         prt(_("行動: ", "Action: "), 20, 0);
1892
1893                         /* Convert to text */
1894                         ascii_to_text(tmp, macro__buf);
1895
1896                         /* Get an encoded action */
1897                         if (askfor(tmp, 80))
1898                         {
1899                                 /* Convert to ascii */
1900                                 text_to_ascii(macro__buf, tmp);
1901
1902                                 /* Free old keymap */
1903                                 string_free(keymap_act[mode][(byte)(buf[0])]);
1904
1905                                 /* Make new keymap */
1906                                 keymap_act[mode][(byte)(buf[0])] = string_make(macro__buf);
1907
1908                                 /* Prompt */
1909                                 msg_print(_("キー配置を追加しました。", "Added a keymap."));
1910                         }
1911                 }
1912
1913                 /* Remove a keymap */
1914                 else if (i == '9')
1915                 {
1916                         /* Prompt */
1917                         prt(_("コマンド: キー配置の削除", "Command: Remove a keymap"), 16, 0);
1918
1919                         /* Prompt */
1920                         prt(_("押すキー: ", "Keypress: "), 18, 0);
1921
1922                         /* Get a keymap trigger */
1923                         do_cmd_macro_aux_keymap(buf);
1924
1925                         /* Free old keymap */
1926                         string_free(keymap_act[mode][(byte)(buf[0])]);
1927
1928                         /* Make new keymap */
1929                         keymap_act[mode][(byte)(buf[0])] = NULL;
1930
1931                         /* Prompt */
1932                         msg_print(_("キー配置を削除しました。", "Removed a keymap."));
1933                 }
1934
1935                 /* Enter a new action */
1936                 else if (i == '0')
1937                 {
1938                         /* Prompt */
1939                         prt(_("コマンド: マクロ行動の入力", "Command: Enter a new action"), 16, 0);
1940                         clear_from(20);
1941
1942                         /* Help message */
1943                         c_prt(TERM_L_RED, _("カーソルキーの左右でカーソル位置を移動。BackspaceかDeleteで一文字削除。",
1944                                 "Press Left/Right arrow keys to move cursor. Backspace/Delete to delete a char."), 22, 0);
1945
1946                         /* Prompt */
1947                         prt(_("マクロ行動: ", "Action: "), 20, 0);
1948
1949                         /* Hack -- limit the value */
1950                         tmp[80] = '\0';
1951
1952                         /* Get an encoded action */
1953                         if (!askfor(buf, 80)) continue;
1954
1955                         /* Extract an action */
1956                         text_to_ascii(macro__buf, buf);
1957                 }
1958 #endif /* ALLOW_MACROS */
1959
1960                 else
1961                 {
1962                         bell();
1963                 }
1964
1965                 msg_erase();
1966         }
1967
1968         screen_load();
1969 }
1970
1971
1972 /*!
1973  * @brief キャラクタ色の明暗表現
1974  */
1975 static concptr lighting_level_str[F_LIT_MAX] =
1976 {
1977 #ifdef JP
1978         "標準色",
1979         "明色",
1980         "暗色",
1981 #else
1982         "standard",
1983         "brightly lit",
1984         "darkened",
1985 #endif
1986 };
1987
1988
1989 /*!
1990  * @brief キャラクタのビジュアルIDを変更する際の対象指定関数
1991  * @param i 指定対象となるキャラクタコード
1992  * @param num 指定されたビジュアルIDを返す参照ポインタ
1993  * @param max ビジュアルIDの最大数
1994  * @return 指定が実際に行われた場合TRUE、キャンセルされた場合FALSE
1995  */
1996 static bool cmd_visuals_aux(int i, IDX *num, IDX max)
1997 {
1998         if (iscntrl(i))
1999         {
2000                 char str[10] = "";
2001                 IDX tmp;
2002
2003                 sprintf(str, "%d", *num);
2004
2005                 if (!get_string(format("Input new number(0-%d): ", max - 1), str, 4))
2006                         return FALSE;
2007
2008                 tmp = (IDX)strtol(str, NULL, 0);
2009                 if (tmp >= 0 && tmp < max)
2010                         *num = tmp;
2011         }
2012         else if (isupper(i))
2013                 *num = (*num + max - 1) % max;
2014         else
2015                 *num = (*num + 1) % max;
2016
2017         return TRUE;
2018 }
2019
2020 /*!
2021  * @brief キャラクタの変更メニュー表示
2022  * @param choice_msg 選択メッセージ
2023  * @return なし
2024  */
2025 static void print_visuals_menu(concptr choice_msg)
2026 {
2027         prt(_("[ 画面表示の設定 ]", "Interact with Visuals"), 1, 0);
2028
2029         /* Give some choices */
2030         prt(_("(0) ユーザー設定ファイルのロード", "(0) Load a user pref file"), 3, 5);
2031
2032 #ifdef ALLOW_VISUALS
2033         prt(_("(1) モンスターの 色/文字 をファイルに書き出す", "(1) Dump monster attr/chars"), 4, 5);
2034         prt(_("(2) アイテムの   色/文字 をファイルに書き出す", "(2) Dump object attr/chars"), 5, 5);
2035         prt(_("(3) 地形の       色/文字 をファイルに書き出す", "(3) Dump feature attr/chars"), 6, 5);
2036         prt(_("(4) モンスターの 色/文字 を変更する (数値操作)", "(4) Change monster attr/chars (numeric operation)"), 7, 5);
2037         prt(_("(5) アイテムの   色/文字 を変更する (数値操作)", "(5) Change object attr/chars (numeric operation)"), 8, 5);
2038         prt(_("(6) 地形の       色/文字 を変更する (数値操作)", "(6) Change feature attr/chars (numeric operation)"), 9, 5);
2039         prt(_("(7) モンスターの 色/文字 を変更する (シンボルエディタ)", "(7) Change monster attr/chars (visual mode)"), 10, 5);
2040         prt(_("(8) アイテムの   色/文字 を変更する (シンボルエディタ)", "(8) Change object attr/chars (visual mode)"), 11, 5);
2041         prt(_("(9) 地形の       色/文字 を変更する (シンボルエディタ)", "(9) Change feature attr/chars (visual mode)"), 12, 5);
2042 #endif /* ALLOW_VISUALS */
2043
2044         prt(_("(R) 画面表示方法の初期化", "(R) Reset visuals"), 13, 5);
2045
2046         /* Prompt */
2047         prt(format("コマンド: %s", choice_msg ? choice_msg : _("", "")), 15, 0);
2048 }
2049
2050
2051 /*
2052  * Interact with "visuals"
2053  */
2054 void do_cmd_visuals(player_type *creature_ptr)
2055 {
2056         int i;
2057         char tmp[160];
2058         char buf[1024];
2059         bool need_redraw = FALSE;
2060         concptr empty_symbol = "<< ? >>";
2061
2062         if (use_bigtile) empty_symbol = "<< ?? >>";
2063
2064         /* File type is "TEXT" */
2065         FILE_TYPE(FILE_TYPE_TEXT);
2066         screen_save();
2067
2068         /* Interact until done */
2069         while (TRUE)
2070         {
2071                 Term_clear();
2072
2073                 /* Ask for a choice */
2074                 print_visuals_menu(NULL);
2075
2076                 /* Prompt */
2077                 i = inkey();
2078
2079                 if (i == ESCAPE) break;
2080
2081                 switch (i)
2082                 {
2083                         /* Load a 'pref' file */
2084                 case '0':
2085                         /* Prompt */
2086                         prt(_("コマンド: ユーザー設定ファイルのロード", "Command: Load a user pref file"), 15, 0);
2087
2088                         /* Prompt */
2089                         prt(_("ファイル: ", "File: "), 17, 0);
2090
2091                         /* Default filename */
2092                         sprintf(tmp, "%s.prf", creature_ptr->base_name);
2093
2094                         /* Query */
2095                         if (!askfor(tmp, 70)) continue;
2096
2097                         /* Process the given filename */
2098                         (void)process_pref_file(creature_ptr, tmp);
2099
2100                         need_redraw = TRUE;
2101                         break;
2102
2103 #ifdef ALLOW_VISUALS
2104
2105                         /* Dump monster attr/chars */
2106                 case '1':
2107                 {
2108                         static concptr mark = "Monster attr/chars";
2109
2110                         /* Prompt */
2111                         prt(_("コマンド: モンスターの[色/文字]をファイルに書き出します", "Command: Dump monster attr/chars"), 15, 0);
2112
2113                         /* Prompt */
2114                         prt(_("ファイル: ", "File: "), 17, 0);
2115
2116                         /* Default filename */
2117                         sprintf(tmp, "%s.prf", creature_ptr->base_name);
2118
2119                         /* Get a filename */
2120                         if (!askfor(tmp, 70)) continue;
2121                         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, tmp);
2122
2123                         /* Append to the file */
2124                         if (!open_auto_dump(buf, mark)) continue;
2125
2126                         /* Start dumping */
2127                         auto_dump_printf(_("\n# モンスターの[色/文字]の設定\n\n", "\n# Monster attr/char definitions\n\n"));
2128
2129                         /* Dump monsters */
2130                         for (i = 0; i < max_r_idx; i++)
2131                         {
2132                                 monster_race *r_ptr = &r_info[i];
2133
2134                                 /* Skip non-entries */
2135                                 if (!r_ptr->name) continue;
2136
2137                                 /* Dump a comment */
2138                                 auto_dump_printf("# %s\n", (r_name + r_ptr->name));
2139
2140                                 /* Dump the monster attr/char info */
2141                                 auto_dump_printf("R:%d:0x%02X/0x%02X\n\n", i,
2142                                         (byte)(r_ptr->x_attr), (byte)(r_ptr->x_char));
2143                         }
2144
2145                         /* Close */
2146                         close_auto_dump();
2147
2148                         msg_print(_("モンスターの[色/文字]をファイルに書き出しました。", "Dumped monster attr/chars."));
2149
2150                         break;
2151                 }
2152
2153                 /* Dump object attr/chars */
2154                 case '2':
2155                 {
2156                         static concptr mark = "Object attr/chars";
2157                         KIND_OBJECT_IDX k_idx;
2158
2159                         /* Prompt */
2160                         prt(_("コマンド: アイテムの[色/文字]をファイルに書き出します", "Command: Dump object attr/chars"), 15, 0);
2161
2162                         /* Prompt */
2163                         prt(_("ファイル: ", "File: "), 17, 0);
2164
2165                         /* Default filename */
2166                         sprintf(tmp, "%s.prf", creature_ptr->base_name);
2167
2168                         /* Get a filename */
2169                         if (!askfor(tmp, 70)) continue;
2170                         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, tmp);
2171
2172                         /* Append to the file */
2173                         if (!open_auto_dump(buf, mark)) continue;
2174
2175                         /* Start dumping */
2176                         auto_dump_printf(_("\n# アイテムの[色/文字]の設定\n\n", "\n# Object attr/char definitions\n\n"));
2177
2178                         /* Dump objects */
2179                         for (k_idx = 0; k_idx < max_k_idx; k_idx++)
2180                         {
2181                                 GAME_TEXT o_name[MAX_NLEN];
2182                                 object_kind *k_ptr = &k_info[k_idx];
2183
2184                                 /* Skip non-entries */
2185                                 if (!k_ptr->name) continue;
2186
2187                                 if (!k_ptr->flavor)
2188                                 {
2189                                         /* Tidy name */
2190                                         strip_name(o_name, k_idx);
2191                                 }
2192                                 else
2193                                 {
2194                                         object_type forge;
2195
2196                                         /* Prepare dummy object */
2197                                         object_prep(&forge, k_idx);
2198
2199                                         /* Get un-shuffled flavor name */
2200                                         object_desc(creature_ptr, o_name, &forge, OD_FORCE_FLAVOR);
2201                                 }
2202
2203                                 /* Dump a comment */
2204                                 auto_dump_printf("# %s\n", o_name);
2205
2206                                 /* Dump the object attr/char info */
2207                                 auto_dump_printf("K:%d:0x%02X/0x%02X\n\n", (int)k_idx,
2208                                         (byte)(k_ptr->x_attr), (byte)(k_ptr->x_char));
2209                         }
2210
2211                         /* Close */
2212                         close_auto_dump();
2213
2214                         msg_print(_("アイテムの[色/文字]をファイルに書き出しました。", "Dumped object attr/chars."));
2215
2216                         break;
2217                 }
2218
2219                 /* Dump feature attr/chars */
2220                 case '3':
2221                 {
2222                         static concptr mark = "Feature attr/chars";
2223
2224                         /* Prompt */
2225                         prt(_("コマンド: 地形の[色/文字]をファイルに書き出します", "Command: Dump feature attr/chars"), 15, 0);
2226
2227                         /* Prompt */
2228                         prt(_("ファイル: ", "File: "), 17, 0);
2229
2230                         /* Default filename */
2231                         sprintf(tmp, "%s.prf", creature_ptr->base_name);
2232
2233                         /* Get a filename */
2234                         if (!askfor(tmp, 70)) continue;
2235                         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, tmp);
2236
2237                         /* Append to the file */
2238                         if (!open_auto_dump(buf, mark)) continue;
2239
2240                         /* Start dumping */
2241                         auto_dump_printf(_("\n# 地形の[色/文字]の設定\n\n", "\n# Feature attr/char definitions\n\n"));
2242
2243                         /* Dump features */
2244                         for (i = 0; i < max_f_idx; i++)
2245                         {
2246                                 feature_type *f_ptr = &f_info[i];
2247
2248                                 /* Skip non-entries */
2249                                 if (!f_ptr->name) continue;
2250
2251                                 /* Skip mimiccing features */
2252                                 if (f_ptr->mimic != i) continue;
2253
2254                                 /* Dump a comment */
2255                                 auto_dump_printf("# %s\n", (f_name + f_ptr->name));
2256
2257                                 /* Dump the feature attr/char info */
2258                                 auto_dump_printf("F:%d:0x%02X/0x%02X:0x%02X/0x%02X:0x%02X/0x%02X\n\n", i,
2259                                         (byte)(f_ptr->x_attr[F_LIT_STANDARD]), (byte)(f_ptr->x_char[F_LIT_STANDARD]),
2260                                         (byte)(f_ptr->x_attr[F_LIT_LITE]), (byte)(f_ptr->x_char[F_LIT_LITE]),
2261                                         (byte)(f_ptr->x_attr[F_LIT_DARK]), (byte)(f_ptr->x_char[F_LIT_DARK]));
2262                         }
2263
2264                         /* Close */
2265                         close_auto_dump();
2266
2267                         msg_print(_("地形の[色/文字]をファイルに書き出しました。", "Dumped feature attr/chars."));
2268
2269                         break;
2270                 }
2271
2272                 /* Modify monster attr/chars (numeric operation) */
2273                 case '4':
2274                 {
2275                         static concptr choice_msg = _("モンスターの[色/文字]を変更します", "Change monster attr/chars");
2276                         static MONRACE_IDX r = 0;
2277
2278                         prt(format(_("コマンド: %s", "Command: %s"), choice_msg), 15, 0);
2279
2280                         /* Hack -- query until done */
2281                         while (TRUE)
2282                         {
2283                                 monster_race *r_ptr = &r_info[r];
2284                                 int c;
2285                                 IDX t;
2286
2287                                 TERM_COLOR da = r_ptr->d_attr;
2288                                 byte dc = r_ptr->d_char;
2289                                 TERM_COLOR ca = r_ptr->x_attr;
2290                                 byte cc = r_ptr->x_char;
2291
2292                                 /* Label the object */
2293                                 Term_putstr(5, 17, -1, TERM_WHITE,
2294                                         format(_("モンスター = %d, 名前 = %-40.40s", "Monster = %d, Name = %-40.40s"), r, (r_name + r_ptr->name)));
2295
2296                                 /* Label the Default values */
2297                                 Term_putstr(10, 19, -1, TERM_WHITE,
2298                                         format(_("初期値  色 / 文字 = %3u / %3u", "Default attr/char = %3u / %3u"), da, dc));
2299
2300                                 Term_putstr(40, 19, -1, TERM_WHITE, empty_symbol);
2301                                 Term_queue_bigchar(43, 19, da, dc, 0, 0);
2302
2303                                 /* Label the Current values */
2304                                 Term_putstr(10, 20, -1, TERM_WHITE,
2305                                         format(_("現在値  色 / 文字 = %3u / %3u", "Current attr/char = %3u / %3u"), ca, cc));
2306
2307                                 Term_putstr(40, 20, -1, TERM_WHITE, empty_symbol);
2308                                 Term_queue_bigchar(43, 20, ca, cc, 0, 0);
2309
2310                                 /* Prompt */
2311                                 Term_putstr(0, 22, -1, TERM_WHITE,
2312                                         _("コマンド (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): "));
2313
2314                                 i = inkey();
2315
2316                                 /* All done */
2317                                 if (i == ESCAPE) break;
2318
2319                                 if (iscntrl(i)) c = 'a' + i - KTRL('A');
2320                                 else if (isupper(i)) c = 'a' + i - 'A';
2321                                 else c = i;
2322
2323                                 switch (c)
2324                                 {
2325                                 case 'n':
2326                                 {
2327                                         IDX prev_r = r;
2328                                         do
2329                                         {
2330                                                 if (!cmd_visuals_aux(i, &r, max_r_idx))
2331                                                 {
2332                                                         r = prev_r;
2333                                                         break;
2334                                                 }
2335                                         } while (!r_info[r].name);
2336                                 }
2337                                 break;
2338                                 case 'a':
2339                                         t = (int)r_ptr->x_attr;
2340                                         (void)cmd_visuals_aux(i, &t, 256);
2341                                         r_ptr->x_attr = (byte)t;
2342                                         need_redraw = TRUE;
2343                                         break;
2344                                 case 'c':
2345                                         t = (int)r_ptr->x_char;
2346                                         (void)cmd_visuals_aux(i, &t, 256);
2347                                         r_ptr->x_char = (byte)t;
2348                                         need_redraw = TRUE;
2349                                         break;
2350                                 case 'v':
2351                                         do_cmd_knowledge_monsters(creature_ptr, &need_redraw, TRUE, r);
2352                                         Term_clear();
2353                                         print_visuals_menu(choice_msg);
2354                                         break;
2355                                 }
2356                         }
2357
2358                         break;
2359                 }
2360
2361                 /* Modify object attr/chars (numeric operation) */
2362                 case '5':
2363                 {
2364                         static concptr choice_msg = _("アイテムの[色/文字]を変更します", "Change object attr/chars");
2365                         static IDX k = 0;
2366                         prt(format(_("コマンド: %s", "Command: %s"), choice_msg), 15, 0);
2367
2368                         /* Hack -- query until done */
2369                         while (TRUE)
2370                         {
2371                                 object_kind *k_ptr = &k_info[k];
2372                                 int c;
2373                                 IDX t;
2374
2375                                 TERM_COLOR da = k_ptr->d_attr;
2376                                 SYMBOL_CODE dc = k_ptr->d_char;
2377                                 TERM_COLOR ca = k_ptr->x_attr;
2378                                 SYMBOL_CODE cc = k_ptr->x_char;
2379
2380                                 /* Label the object */
2381                                 Term_putstr(5, 17, -1, TERM_WHITE,
2382                                         format(_("アイテム = %d, 名前 = %-40.40s", "Object = %d, Name = %-40.40s"),
2383                                                 k, k_name + (!k_ptr->flavor ? k_ptr->name : k_ptr->flavor_name)));
2384
2385                                 /* Label the Default values */
2386                                 Term_putstr(10, 19, -1, TERM_WHITE,
2387                                         format(_("初期値  色 / 文字 = %3d / %3d", "Default attr/char = %3d / %3d"), da, dc));
2388
2389                                 Term_putstr(40, 19, -1, TERM_WHITE, empty_symbol);
2390                                 Term_queue_bigchar(43, 19, da, dc, 0, 0);
2391
2392                                 /* Label the Current values */
2393                                 Term_putstr(10, 20, -1, TERM_WHITE,
2394                                         format(_("現在値  色 / 文字 = %3d / %3d", "Current attr/char = %3d / %3d"), ca, cc));
2395
2396                                 Term_putstr(40, 20, -1, TERM_WHITE, empty_symbol);
2397                                 Term_queue_bigchar(43, 20, ca, cc, 0, 0);
2398
2399                                 /* Prompt */
2400                                 Term_putstr(0, 22, -1, TERM_WHITE,
2401                                         _("コマンド (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): "));
2402
2403                                 i = inkey();
2404
2405                                 /* All done */
2406                                 if (i == ESCAPE) break;
2407
2408                                 if (iscntrl(i)) c = 'a' + i - KTRL('A');
2409                                 else if (isupper(i)) c = 'a' + i - 'A';
2410                                 else c = i;
2411
2412                                 switch (c)
2413                                 {
2414                                 case 'n':
2415                                 {
2416                                         IDX prev_k = k;
2417                                         do
2418                                         {
2419                                                 if (!cmd_visuals_aux(i, &k, max_k_idx))
2420                                                 {
2421                                                         k = prev_k;
2422                                                         break;
2423                                                 }
2424                                         } while (!k_info[k].name);
2425                                 }
2426                                 break;
2427                                 case 'a':
2428                                         t = (int)k_ptr->x_attr;
2429                                         (void)cmd_visuals_aux(i, &t, 256);
2430                                         k_ptr->x_attr = (byte)t;
2431                                         need_redraw = TRUE;
2432                                         break;
2433                                 case 'c':
2434                                         t = (int)k_ptr->x_char;
2435                                         (void)cmd_visuals_aux(i, &t, 256);
2436                                         k_ptr->x_char = (byte)t;
2437                                         need_redraw = TRUE;
2438                                         break;
2439                                 case 'v':
2440                                         do_cmd_knowledge_objects(creature_ptr, &need_redraw, TRUE, k);
2441                                         Term_clear();
2442                                         print_visuals_menu(choice_msg);
2443                                         break;
2444                                 }
2445                         }
2446
2447                         break;
2448                 }
2449
2450                 /* Modify feature attr/chars (numeric operation) */
2451                 case '6':
2452                 {
2453                         static concptr choice_msg = _("地形の[色/文字]を変更します", "Change feature attr/chars");
2454                         static IDX f = 0;
2455                         static IDX lighting_level = F_LIT_STANDARD;
2456                         prt(format(_("コマンド: %s", "Command: %s"), choice_msg), 15, 0);
2457
2458                         /* Hack -- query until done */
2459                         while (TRUE)
2460                         {
2461                                 feature_type *f_ptr = &f_info[f];
2462                                 int c;
2463                                 IDX t;
2464
2465                                 TERM_COLOR da = f_ptr->d_attr[lighting_level];
2466                                 byte dc = f_ptr->d_char[lighting_level];
2467                                 TERM_COLOR ca = f_ptr->x_attr[lighting_level];
2468                                 byte cc = f_ptr->x_char[lighting_level];
2469
2470                                 /* Label the object */
2471                                 prt("", 17, 5);
2472                                 Term_putstr(5, 17, -1, TERM_WHITE,
2473                                         format(_("地形 = %d, 名前 = %s, 明度 = %s", "Terrain = %d, Name = %s, Lighting = %s"),
2474                                                 f, (f_name + f_ptr->name), lighting_level_str[lighting_level]));
2475
2476                                 /* Label the Default values */
2477                                 Term_putstr(10, 19, -1, TERM_WHITE,
2478                                         format(_("初期値  色 / 文字 = %3d / %3d", "Default attr/char = %3d / %3d"), da, dc));
2479
2480                                 Term_putstr(40, 19, -1, TERM_WHITE, empty_symbol);
2481                                 Term_queue_bigchar(43, 19, da, dc, 0, 0);
2482
2483                                 /* Label the Current values */
2484 #ifdef JP
2485                                 Term_putstr(10, 20, -1, TERM_WHITE,
2486                                         format("現在値  色 / 文字 = %3d / %3d", ca, cc));
2487 #else
2488                                 Term_putstr(10, 20, -1, TERM_WHITE,
2489                                         format("Current attr/char = %3d / %3d", ca, cc));
2490 #endif
2491
2492                                 Term_putstr(40, 20, -1, TERM_WHITE, empty_symbol);
2493                                 Term_queue_bigchar(43, 20, ca, cc, 0, 0);
2494
2495                                 /* Prompt */
2496 #ifdef JP
2497                                 Term_putstr(0, 22, -1, TERM_WHITE,
2498                                         "コマンド (n/N/^N/a/A/^A/c/C/^C/l/L/^L/d/D/^D/v/V/^V): ");
2499 #else
2500                                 Term_putstr(0, 22, -1, TERM_WHITE,
2501                                         "Command (n/N/^N/a/A/^A/c/C/^C/l/L/^L/d/D/^D/v/V/^V): ");
2502 #endif
2503
2504                                 i = inkey();
2505
2506                                 /* All done */
2507                                 if (i == ESCAPE) break;
2508
2509                                 if (iscntrl(i)) c = 'a' + i - KTRL('A');
2510                                 else if (isupper(i)) c = 'a' + i - 'A';
2511                                 else c = i;
2512
2513                                 switch (c)
2514                                 {
2515                                 case 'n':
2516                                 {
2517                                         IDX prev_f = f;
2518                                         do
2519                                         {
2520                                                 if (!cmd_visuals_aux(i, &f, max_f_idx))
2521                                                 {
2522                                                         f = prev_f;
2523                                                         break;
2524                                                 }
2525                                         } while (!f_info[f].name || (f_info[f].mimic != f));
2526                                 }
2527                                 break;
2528                                 case 'a':
2529                                         t = (int)f_ptr->x_attr[lighting_level];
2530                                         (void)cmd_visuals_aux(i, &t, 256);
2531                                         f_ptr->x_attr[lighting_level] = (byte)t;
2532                                         need_redraw = TRUE;
2533                                         break;
2534                                 case 'c':
2535                                         t = (int)f_ptr->x_char[lighting_level];
2536                                         (void)cmd_visuals_aux(i, &t, 256);
2537                                         f_ptr->x_char[lighting_level] = (byte)t;
2538                                         need_redraw = TRUE;
2539                                         break;
2540                                 case 'l':
2541                                         (void)cmd_visuals_aux(i, &lighting_level, F_LIT_MAX);
2542                                         break;
2543                                 case 'd':
2544                                         apply_default_feat_lighting(f_ptr->x_attr, f_ptr->x_char);
2545                                         need_redraw = TRUE;
2546                                         break;
2547                                 case 'v':
2548                                         do_cmd_knowledge_features(&need_redraw, TRUE, f, &lighting_level);
2549                                         Term_clear();
2550                                         print_visuals_menu(choice_msg);
2551                                         break;
2552                                 }
2553                         }
2554
2555                         break;
2556                 }
2557
2558                 /* Modify monster attr/chars (visual mode) */
2559                 case '7':
2560                         do_cmd_knowledge_monsters(creature_ptr, &need_redraw, TRUE, -1);
2561                         break;
2562
2563                         /* Modify object attr/chars (visual mode) */
2564                 case '8':
2565                         do_cmd_knowledge_objects(creature_ptr, &need_redraw, TRUE, -1);
2566                         break;
2567
2568                         /* Modify feature attr/chars (visual mode) */
2569                 case '9':
2570                 {
2571                         IDX lighting_level = F_LIT_STANDARD;
2572                         do_cmd_knowledge_features(&need_redraw, TRUE, -1, &lighting_level);
2573                         break;
2574                 }
2575
2576 #endif /* ALLOW_VISUALS */
2577
2578                 /* Reset visuals */
2579                 case 'R':
2580                 case 'r':
2581                         /* Reset */
2582                         reset_visuals(creature_ptr);
2583
2584                         msg_print(_("画面上の[色/文字]を初期値にリセットしました。", "Visual attr/char tables reset."));
2585                         need_redraw = TRUE;
2586                         break;
2587
2588                         /* Unknown option */
2589                 default:
2590                         bell();
2591                         break;
2592                 }
2593
2594                 msg_erase();
2595         }
2596
2597         screen_load();
2598
2599         if (need_redraw) do_cmd_redraw(creature_ptr);
2600 }
2601
2602
2603 /*
2604  * Interact with "colors"
2605  */
2606 void do_cmd_colors(player_type *creature_ptr)
2607 {
2608         int i;
2609         char tmp[160];
2610         char buf[1024];
2611
2612         /* File type is "TEXT" */
2613         FILE_TYPE(FILE_TYPE_TEXT);
2614
2615         screen_save();
2616
2617         /* Interact until done */
2618         while (TRUE)
2619         {
2620                 Term_clear();
2621
2622                 /* Ask for a choice */
2623                 prt(_("[ カラーの設定 ]", "Interact with Colors"), 2, 0);
2624
2625                 /* Give some choices */
2626                 prt(_("(1) ユーザー設定ファイルのロード", "(1) Load a user pref file"), 4, 5);
2627
2628 #ifdef ALLOW_COLORS
2629                 prt(_("(2) カラーの設定をファイルに書き出す", "(2) Dump colors"), 5, 5);
2630                 prt(_("(3) カラーの設定を変更する", "(3) Modify colors"), 6, 5);
2631 #endif
2632
2633                 /* Prompt */
2634                 prt(_("コマンド: ", "Command: "), 8, 0);
2635                 /* Prompt */
2636                 i = inkey();
2637
2638                 if (i == ESCAPE) break;
2639
2640                 /* Load a 'pref' file */
2641                 if (i == '1')
2642                 {
2643                         /* Prompt */
2644                         prt(_("コマンド: ユーザー設定ファイルをロードします", "Command: Load a user pref file"), 8, 0);
2645
2646                         /* Prompt */
2647                         prt(_("ファイル: ", "File: "), 10, 0);
2648
2649                         /* Default file */
2650                         sprintf(tmp, "%s.prf", creature_ptr->base_name);
2651
2652                         /* Query */
2653                         if (!askfor(tmp, 70)) continue;
2654
2655                         /* Process the given filename */
2656                         (void)process_pref_file(creature_ptr, tmp);
2657
2658                         /* Mega-Hack -- react to changes */
2659                         Term_xtra(TERM_XTRA_REACT, 0);
2660
2661                         /* Mega-Hack -- redraw */
2662                         Term_redraw();
2663                 }
2664
2665 #ifdef ALLOW_COLORS
2666
2667                 /* Dump colors */
2668                 else if (i == '2')
2669                 {
2670                         static concptr mark = "Colors";
2671
2672                         /* Prompt */
2673                         prt(_("コマンド: カラーの設定をファイルに書き出します", "Command: Dump colors"), 8, 0);
2674
2675                         /* Prompt */
2676                         prt(_("ファイル: ", "File: "), 10, 0);
2677
2678                         /* Default filename */
2679                         sprintf(tmp, "%s.prf", creature_ptr->base_name);
2680
2681                         /* Get a filename */
2682                         if (!askfor(tmp, 70)) continue;
2683                         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, tmp);
2684
2685                         /* Append to the file */
2686                         if (!open_auto_dump(buf, mark)) continue;
2687
2688                         /* Start dumping */
2689                         auto_dump_printf(_("\n# カラーの設定\n\n", "\n# Color redefinitions\n\n"));
2690
2691                         /* Dump colors */
2692                         for (i = 0; i < 256; i++)
2693                         {
2694                                 int kv = angband_color_table[i][0];
2695                                 int rv = angband_color_table[i][1];
2696                                 int gv = angband_color_table[i][2];
2697                                 int bv = angband_color_table[i][3];
2698
2699                                 concptr name = _("未知", "unknown");
2700
2701                                 /* Skip non-entries */
2702                                 if (!kv && !rv && !gv && !bv) continue;
2703
2704                                 /* Extract the color name */
2705                                 if (i < 16) name = color_names[i];
2706
2707                                 /* Dump a comment */
2708                                 auto_dump_printf(_("# カラー '%s'\n", "# Color '%s'\n"), name);
2709
2710                                 /* Dump the monster attr/char info */
2711                                 auto_dump_printf("V:%d:0x%02X:0x%02X:0x%02X:0x%02X\n\n",
2712                                         i, kv, rv, gv, bv);
2713                         }
2714
2715                         /* Close */
2716                         close_auto_dump();
2717
2718                         msg_print(_("カラーの設定をファイルに書き出しました。", "Dumped color redefinitions."));
2719                 }
2720
2721                 /* Edit colors */
2722                 else if (i == '3')
2723                 {
2724                         static byte a = 0;
2725
2726                         /* Prompt */
2727                         prt(_("コマンド: カラーの設定を変更します", "Command: Modify colors"), 8, 0);
2728
2729                         /* Hack -- query until done */
2730                         while (TRUE)
2731                         {
2732                                 concptr name;
2733                                 byte j;
2734                                 clear_from(10);
2735
2736                                 /* Exhibit the normal colors */
2737                                 for (j = 0; j < 16; j++)
2738                                 {
2739                                         /* Exhibit this color */
2740                                         Term_putstr(j * 4, 20, -1, a, "###");
2741
2742                                         /* Exhibit all colors */
2743                                         Term_putstr(j * 4, 22, -1, j, format("%3d", j));
2744                                 }
2745
2746                                 /* Describe the color */
2747                                 name = ((a < 16) ? color_names[a] : _("未定義", "undefined"));
2748
2749                                 /* Describe the color */
2750                                 Term_putstr(5, 10, -1, TERM_WHITE,
2751                                         format(_("カラー = %d, 名前 = %s", "Color = %d, Name = %s"), a, name));
2752
2753                                 /* Label the Current values */
2754                                 Term_putstr(5, 12, -1, TERM_WHITE,
2755                                         format("K = 0x%02x / R,G,B = 0x%02x,0x%02x,0x%02x",
2756                                                 angband_color_table[a][0],
2757                                                 angband_color_table[a][1],
2758                                                 angband_color_table[a][2],
2759                                                 angband_color_table[a][3]));
2760
2761                                 /* Prompt */
2762                                 Term_putstr(0, 14, -1, TERM_WHITE,
2763                                         _("コマンド (n/N/k/K/r/R/g/G/b/B): ", "Command (n/N/k/K/r/R/g/G/b/B): "));
2764
2765                                 i = inkey();
2766
2767                                 /* All done */
2768                                 if (i == ESCAPE) break;
2769
2770                                 /* Analyze */
2771                                 if (i == 'n') a = (byte)(a + 1);
2772                                 if (i == 'N') a = (byte)(a - 1);
2773                                 if (i == 'k') angband_color_table[a][0] = (byte)(angband_color_table[a][0] + 1);
2774                                 if (i == 'K') angband_color_table[a][0] = (byte)(angband_color_table[a][0] - 1);
2775                                 if (i == 'r') angband_color_table[a][1] = (byte)(angband_color_table[a][1] + 1);
2776                                 if (i == 'R') angband_color_table[a][1] = (byte)(angband_color_table[a][1] - 1);
2777                                 if (i == 'g') angband_color_table[a][2] = (byte)(angband_color_table[a][2] + 1);
2778                                 if (i == 'G') angband_color_table[a][2] = (byte)(angband_color_table[a][2] - 1);
2779                                 if (i == 'b') angband_color_table[a][3] = (byte)(angband_color_table[a][3] + 1);
2780                                 if (i == 'B') angband_color_table[a][3] = (byte)(angband_color_table[a][3] - 1);
2781
2782                                 /* Hack -- react to changes */
2783                                 Term_xtra(TERM_XTRA_REACT, 0);
2784
2785                                 /* Hack -- redraw */
2786                                 Term_redraw();
2787                         }
2788                 }
2789
2790 #endif
2791
2792                 /* Unknown option */
2793                 else
2794                 {
2795                         bell();
2796                 }
2797
2798                 msg_erase();
2799         }
2800
2801         screen_load();
2802 }
2803
2804
2805 /*
2806  * Note something in the message recall
2807  */
2808 void do_cmd_note(void)
2809 {
2810         char buf[80];
2811
2812         /* Default */
2813         strcpy(buf, "");
2814
2815         /* Input */
2816         if (!get_string(_("メモ: ", "Note: "), buf, 60)) return;
2817
2818         /* Ignore empty notes */
2819         if (!buf[0] || (buf[0] == ' ')) return;
2820
2821         /* Add the note to the message recall */
2822         msg_format(_("メモ: %s", "Note: %s"), buf);
2823 }
2824
2825
2826 /*
2827  * Mention the current version
2828  */
2829 void do_cmd_version(void)
2830 {
2831 #if FAKE_VER_EXTRA > 0
2832         msg_format(_("変愚蛮怒(Hengband) %d.%d.%d.%d", "You are playing Hengband %d.%d.%d.%d."),
2833                 FAKE_VER_MAJOR - 10, FAKE_VER_MINOR, FAKE_VER_PATCH, FAKE_VER_EXTRA);
2834 #else
2835         msg_format(_("変愚蛮怒(Hengband) %d.%d.%d", "You are playing Hengband %d.%d.%d."),
2836                 FAKE_VER_MAJOR - 10, FAKE_VER_MINOR, FAKE_VER_PATCH);
2837 #endif
2838 }
2839
2840
2841 /*
2842  * Array of feeling strings
2843  */
2844 static concptr do_cmd_feeling_text[11] =
2845 {
2846         _("この階の雰囲気を感じとれなかった...", "Looks like any other level."),
2847         _("この階には何か特別なものがあるような気がする。", "You feel there is something special about this level."),
2848         _("恐ろしい死の幻が目に浮かび、気絶しそうになった!", "You nearly faint as horrible visions of death fill your mind!"),
2849         _("この階はとても危険なようだ。", "This level looks very dangerous."),
2850         _("とても悪い予感がする...", "You have a very bad feeling..."),
2851         _("悪い予感がする...", "You have a bad feeling..."),
2852         _("何か緊張する。", "You feel nervous."),
2853         _("少し不運な気がする...", "You feel your luck is turning..."),
2854         _("この場所は好きになれない。", "You don't like the look of this place."),
2855         _("この階はそれなりに安全なようだ。", "This level looks reasonably safe."),
2856         _("なんて退屈なところだ...", "What a boring place...")
2857 };
2858
2859 static concptr do_cmd_feeling_text_combat[11] =
2860 {
2861         _("この階の雰囲気を感じとれなかった...", "Looks like any other level."),
2862         _("この階には何か特別なものがあるような気がする。", "You feel there is something special about this level."),
2863         _("今夜もまた、誰かが命を落とす...", "You nearly faint as horrible visions of death fill your mind!"),
2864         _("この階はとても危険なようだ。", "This level looks very dangerous."),
2865         _("とても悪い予感がする...", "You have a very bad feeling..."),
2866         _("悪い予感がする...", "You have a bad feeling..."),
2867         _("何か緊張する。", "You feel nervous."),
2868         _("少し不運な気がする...", "You feel your luck is turning..."),
2869         _("この場所は好きになれない。", "You don't like the look of this place."),
2870         _("この階はそれなりに安全なようだ。", "This level looks reasonably safe."),
2871         _("なんて退屈なところだ...", "What a boring place...")
2872 };
2873
2874 static concptr do_cmd_feeling_text_lucky[11] =
2875 {
2876         _("この階の雰囲気を感じとれなかった...", "Looks like any other level."),
2877         _("この階には何か特別なものがあるような気がする。", "You feel there is something special about this level."),
2878         _("この階はこの上なく素晴らしい感じがする。", "You have a superb feeling about this level."),
2879         _("素晴らしい感じがする...", "You have an excellent feeling..."),
2880         _("とても良い感じがする...", "You have a very good feeling..."),
2881         _("良い感じがする...", "You have a good feeling..."),
2882         _("ちょっと幸運な感じがする...", "You feel strangely lucky..."),
2883         _("多少は運が向いてきたか...", "You feel your luck is turning..."),
2884         _("見た感じ悪くはない...", "You like the look of this place..."),
2885         _("全然駄目ということはないが...", "This level can't be all bad..."),
2886         _("なんて退屈なところだ...", "What a boring place...")
2887 };
2888
2889
2890 /*
2891  * Note that "feeling" is set to zero unless some time has passed.
2892  * Note that this is done when the level is GENERATED, not entered.
2893  */
2894 void do_cmd_feeling(player_type *creature_ptr)
2895 {
2896         if (creature_ptr->wild_mode) return;
2897
2898         /* No useful feeling in quests */
2899         if (creature_ptr->current_floor_ptr->inside_quest && !random_quest_number(creature_ptr, creature_ptr->current_floor_ptr->dun_level))
2900         {
2901                 msg_print(_("典型的なクエストのダンジョンのようだ。", "Looks like a typical quest level."));
2902                 return;
2903         }
2904
2905         /* No useful feeling in town */
2906         if (creature_ptr->town_num && !creature_ptr->current_floor_ptr->dun_level)
2907         {
2908                 if (!strcmp(town_info[creature_ptr->town_num].name, _("荒野", "wilderness")))
2909                 {
2910                         msg_print(_("何かありそうな荒野のようだ。", "Looks like a strange wilderness."));
2911                         return;
2912                 }
2913
2914                 msg_print(_("典型的な町のようだ。", "Looks like a typical town."));
2915                 return;
2916         }
2917
2918         /* No useful feeling in the wilderness */
2919         if (!creature_ptr->current_floor_ptr->dun_level)
2920         {
2921                 msg_print(_("典型的な荒野のようだ。", "Looks like a typical wilderness."));
2922                 return;
2923         }
2924
2925         /* Display the feeling */
2926         if (creature_ptr->muta3 & MUT3_GOOD_LUCK)
2927                 msg_print(do_cmd_feeling_text_lucky[creature_ptr->feeling]);
2928         else if (creature_ptr->pseikaku == SEIKAKU_COMBAT ||
2929                 creature_ptr->inventory_list[INVEN_BOW].name1 == ART_CRIMSON)
2930                 msg_print(do_cmd_feeling_text_combat[creature_ptr->feeling]);
2931         else
2932                 msg_print(do_cmd_feeling_text[creature_ptr->feeling]);
2933 }
2934
2935
2936 /*
2937  * Description of each monster group.
2938  */
2939 static concptr monster_group_text[] =
2940 {
2941 #ifdef JP
2942         "ユニーク", /* "Uniques" */
2943         "乗馬可能なモンスター",       /* "Riding" */
2944         "賞金首", /* "Wanted */
2945         "アンバーの王族", /* "Ambertite" */
2946         "アリ",
2947         "コウモリ",
2948         "ムカデ",
2949         "ドラゴン",
2950         "目玉",
2951         "ネコ",
2952         "ゴーレム",
2953         "標準人間型生物",
2954         "ベトベト",
2955         "ゼリー",
2956         "コボルド",
2957         "水棲生物",
2958         "モルド",
2959         "ナーガ",
2960         "オーク",
2961         "人間",
2962         "四足獣",
2963         "ネズミ",
2964         "スケルトン",
2965         "デーモン",
2966         "ボルテックス",
2967         "イモムシ/大群",
2968         /* "unused", */
2969         "イーク",
2970         "ゾンビ/ミイラ",
2971         "天使",
2972         "鳥",
2973         "犬",
2974         /* "古代ドラゴン/ワイアーム", */
2975         "エレメンタル",
2976         "トンボ",
2977         "ゴースト",
2978         "雑種",
2979         "昆虫",
2980         "ヘビ",
2981         "キラー・ビートル",
2982         "リッチ",
2983         "多首の爬虫類",
2984         "謎の生物",
2985         "オーガ",
2986         "巨大人間型生物",
2987         "クイルスルグ",
2988         "爬虫類/両生類",
2989         "蜘蛛/サソリ/ダニ",
2990         "トロル",
2991         /* "上級デーモン", */
2992         "バンパイア",
2993         "ワイト/レイス/等",
2994         "ゾーン/ザレン/等",
2995         "イエティ",
2996         "ハウンド",
2997         "ミミック",
2998         "壁/植物/気体",
2999         "おばけキノコ",
3000         "球体",
3001         "プレイヤー",
3002 #else
3003         "Uniques",
3004         "Ridable monsters",
3005         "Wanted monsters",
3006         "Ambertite",
3007         "Ant",
3008         "Bat",
3009         "Centipede",
3010         "Dragon",
3011         "Floating Eye",
3012         "Feline",
3013         "Golem",
3014         "Hobbit/Elf/Dwarf",
3015         "Icky Thing",
3016         "Jelly",
3017         "Kobold",
3018         "Aquatic monster",
3019         "Mold",
3020         "Naga",
3021         "Orc",
3022         "Person/Human",
3023         "Quadruped",
3024         "Rodent",
3025         "Skeleton",
3026         "Demon",
3027         "Vortex",
3028         "Worm/Worm-Mass",
3029         /* "unused", */
3030         "Yeek",
3031         "Zombie/Mummy",
3032         "Angel",
3033         "Bird",
3034         "Canine",
3035         /* "Ancient Dragon/Wyrm", */
3036         "Elemental",
3037         "Dragon Fly",
3038         "Ghost",
3039         "Hybrid",
3040         "Insect",
3041         "Snake",
3042         "Killer Beetle",
3043         "Lich",
3044         "Multi-Headed Reptile",
3045         "Mystery Living",
3046         "Ogre",
3047         "Giant Humanoid",
3048         "Quylthulg",
3049         "Reptile/Amphibian",
3050         "Spider/Scorpion/Tick",
3051         "Troll",
3052         /* "Major Demon", */
3053         "Vampire",
3054         "Wight/Wraith/etc",
3055         "Xorn/Xaren/etc",
3056         "Yeti",
3057         "Zephyr Hound",
3058         "Mimic",
3059         "Wall/Plant/Gas",
3060         "Mushroom patch",
3061         "Ball",
3062         "Player",
3063 #endif
3064         NULL
3065 };
3066
3067
3068 /*
3069  * Symbols of monsters in each group. Note the "Uniques" group
3070  * is handled differently.
3071  */
3072 static concptr monster_group_char[] =
3073 {
3074         (char *)-1L,
3075         (char *)-2L,
3076         (char *)-3L,
3077         (char *)-4L,
3078         "a",
3079         "b",
3080         "c",
3081         "dD",
3082         "e",
3083         "f",
3084         "g",
3085         "h",
3086         "i",
3087         "j",
3088         "k",
3089         "l",
3090         "m",
3091         "n",
3092         "o",
3093         "pt",
3094         "q",
3095         "r",
3096         "s",
3097         "uU",
3098         "v",
3099         "w",
3100         /* "x", */
3101         "y",
3102         "z",
3103         "A",
3104         "B",
3105         "C",
3106         /* "D", */
3107         "E",
3108         "F",
3109         "G",
3110         "H",
3111         "I",
3112         "J",
3113         "K",
3114         "L",
3115         "M",
3116         "N",
3117         "O",
3118         "P",
3119         "Q",
3120         "R",
3121         "S",
3122         "T",
3123         /* "U", */
3124         "V",
3125         "W",
3126         "X",
3127         "Y",
3128         "Z",
3129         "!$&()+./=>?[\\]`{|~",
3130         "#%",
3131         ",",
3132         "*",
3133         "@",
3134         NULL
3135 };
3136
3137
3138 /*
3139  * todo 引数と戻り値について追記求む
3140  * Build a list of monster indexes in the given group.
3141  *
3142  * mode & 0x01 : check for non-empty group
3143  * mode & 0x02 : visual operation only
3144
3145  * @param creature_ptr プレーヤーへの参照ポインタ
3146  * @param grp_cur ???
3147  * @param mon_idx[] ???
3148  * @param mode ???
3149  * @return The number of monsters in the group
3150  */
3151 static IDX collect_monsters(player_type *creature_ptr, IDX grp_cur, IDX mon_idx[], BIT_FLAGS8 mode)
3152 {
3153         /* Get a list of x_char in this group */
3154         concptr group_char = monster_group_char[grp_cur];
3155
3156         bool grp_unique = (monster_group_char[grp_cur] == (char *)-1L);
3157         bool grp_riding = (monster_group_char[grp_cur] == (char *)-2L);
3158         bool grp_wanted = (monster_group_char[grp_cur] == (char *)-3L);
3159         bool grp_amberite = (monster_group_char[grp_cur] == (char *)-4L);
3160
3161         /* Check every race */
3162         IDX mon_cnt = 0;
3163         for (IDX i = 0; i < max_r_idx; i++)
3164         {
3165                 /* Access the race */
3166                 monster_race *r_ptr = &r_info[i];
3167
3168                 /* Skip empty race */
3169                 if (!r_ptr->name) continue;
3170
3171                 /* Require known monsters */
3172                 if (!(mode & 0x02) && !cheat_know && !r_ptr->r_sights) continue;
3173
3174                 if (grp_unique)
3175                 {
3176                         if (!(r_ptr->flags1 & RF1_UNIQUE)) continue;
3177                 }
3178
3179                 else if (grp_riding)
3180                 {
3181                         if (!(r_ptr->flags7 & RF7_RIDING)) continue;
3182                 }
3183
3184                 else if (grp_wanted)
3185                 {
3186                         bool wanted = FALSE;
3187                         int j;
3188                         for (j = 0; j < MAX_BOUNTY; j++)
3189                         {
3190                                 if (current_world_ptr->bounty_r_idx[j] == i || current_world_ptr->bounty_r_idx[j] - 10000 == i ||
3191                                         (creature_ptr->today_mon && creature_ptr->today_mon == i))
3192                                 {
3193                                         wanted = TRUE;
3194                                         break;
3195                                 }
3196                         }
3197                         if (!wanted) continue;
3198                 }
3199
3200                 else if (grp_amberite)
3201                 {
3202                         if (!(r_ptr->flags3 & RF3_AMBERITE)) continue;
3203                 }
3204
3205                 else
3206                 {
3207                         /* Check for race in the group */
3208                         if (!my_strchr(group_char, r_ptr->d_char)) continue;
3209                 }
3210
3211                 /* Add the race */
3212                 mon_idx[mon_cnt++] = i;
3213
3214                 /* XXX Hack -- Just checking for non-empty group */
3215                 if (mode & 0x01) break;
3216         }
3217
3218         /* Terminate the list */
3219         mon_idx[mon_cnt] = -1;
3220
3221         int dummy_why;
3222         ang_sort(mon_idx, &dummy_why, mon_cnt, ang_sort_comp_monster_level, ang_sort_swap_hook);
3223
3224         /* Return the number of races */
3225         return mon_cnt;
3226 }
3227
3228
3229 /*
3230  * Description of each monster group.
3231  */
3232 static concptr object_group_text[] =
3233 {
3234 #ifdef JP
3235         "キノコ",    /* "Mushrooms" */
3236         "薬",          /* "Potions" */
3237         "油つぼ",    /* "Flasks" */
3238         "巻物",               /* "Scrolls" */
3239         "指輪",               /* "Rings" */
3240         "アミュレット",   /* "Amulets" */
3241         "笛",          /* "Whistle" */
3242         "光源",               /* "Lanterns" */
3243         "魔法棒",    /* "Wands" */
3244         "杖",          /* "Staffs" */
3245         "ロッド",    /* "Rods" */
3246         "カード",    /* "Cards" */
3247         "キャプチャー・ボール",
3248         "羊皮紙",
3249         "くさび",
3250         "箱",
3251         "人形",
3252         "像",
3253         "ゴミ",
3254         "空のビン",
3255         "骨",
3256         "死体",
3257         "刀剣類",    /* "Swords" */
3258         "鈍器",               /* "Blunt Weapons" */
3259         "長柄武器", /* "Polearms" */
3260         "採掘道具", /* "Diggers" */
3261         "飛び道具", /* "Bows" */
3262         "弾",
3263         "矢",
3264         "ボルト",
3265         "軽装鎧",    /* "Soft Armor" */
3266         "重装鎧",    /* "Hard Armor" */
3267         "ドラゴン鎧",      /* "Dragon Armor" */
3268         "盾",  /* "Shields" */
3269         "クローク", /* "Cloaks" */
3270         "籠手",       /* "Gloves" */
3271         "ヘルメット",      /* "Helms" */
3272         "冠",  /* "Crowns" */
3273         "ブーツ",    /* "Boots" */
3274         "魔法書",
3275         "財宝",
3276         "何か",
3277 #else
3278         "Mushrooms",
3279         "Potions",
3280         "Flasks",
3281         "Scrolls",
3282         "Rings",
3283         "Amulets",
3284         "Whistle",
3285         "Lanterns",
3286         "Wands",
3287         "Staves",
3288         "Rods",
3289         "Cards",
3290         "Capture Balls",
3291         "Parchments",
3292         "Spikes",
3293         "Boxs",
3294         "Figurines",
3295         "Statues",
3296         "Junks",
3297         "Bottles",
3298         "Skeletons",
3299         "Corpses",
3300         "Swords",
3301         "Blunt Weapons",
3302         "Polearms",
3303         "Diggers",
3304         "Bows",
3305         "Shots",
3306         "Arrows",
3307         "Bolts",
3308         "Soft Armor",
3309         "Hard Armor",
3310         "Dragon Armor",
3311         "Shields",
3312         "Cloaks",
3313         "Gloves",
3314         "Helms",
3315         "Crowns",
3316         "Boots",
3317         "Spellbooks",
3318         "Treasure",
3319         "Something",
3320 #endif
3321         NULL
3322 };
3323
3324
3325 /*
3326  * TVALs of items in each group
3327  */
3328 static byte object_group_tval[] =
3329 {
3330         TV_FOOD,
3331         TV_POTION,
3332         TV_FLASK,
3333         TV_SCROLL,
3334         TV_RING,
3335         TV_AMULET,
3336         TV_WHISTLE,
3337         TV_LITE,
3338         TV_WAND,
3339         TV_STAFF,
3340         TV_ROD,
3341         TV_CARD,
3342         TV_CAPTURE,
3343         TV_PARCHMENT,
3344         TV_SPIKE,
3345         TV_CHEST,
3346         TV_FIGURINE,
3347         TV_STATUE,
3348         TV_JUNK,
3349         TV_BOTTLE,
3350         TV_SKELETON,
3351         TV_CORPSE,
3352         TV_SWORD,
3353         TV_HAFTED,
3354         TV_POLEARM,
3355         TV_DIGGING,
3356         TV_BOW,
3357         TV_SHOT,
3358         TV_ARROW,
3359         TV_BOLT,
3360         TV_SOFT_ARMOR,
3361         TV_HARD_ARMOR,
3362         TV_DRAG_ARMOR,
3363         TV_SHIELD,
3364         TV_CLOAK,
3365         TV_GLOVES,
3366         TV_HELM,
3367         TV_CROWN,
3368         TV_BOOTS,
3369         TV_LIFE_BOOK, /* Hack -- all spellbooks */
3370         TV_GOLD,
3371         0,
3372         0,
3373 };
3374
3375
3376 /*
3377  * Build a list of object indexes in the given group. Return the number
3378  * of objects in the group.
3379  *
3380  * mode & 0x01 : check for non-empty group
3381  * mode & 0x02 : visual operation only
3382  */
3383 static KIND_OBJECT_IDX collect_objects(int grp_cur, KIND_OBJECT_IDX object_idx[], BIT_FLAGS8 mode)
3384 {
3385         KIND_OBJECT_IDX i, object_cnt = 0;
3386         int j, k;
3387
3388         /* Get a list of x_char in this group */
3389         byte group_tval = object_group_tval[grp_cur];
3390
3391         /* Check every object */
3392         for (i = 0; i < max_k_idx; i++)
3393         {
3394                 /* Access the object */
3395                 object_kind *k_ptr = &k_info[i];
3396
3397                 /* Skip empty objects */
3398                 if (!k_ptr->name) continue;
3399
3400                 if (!(mode & 0x02))
3401                 {
3402                         if (!current_world_ptr->wizard)
3403                         {
3404                                 /* Skip non-flavoured objects */
3405                                 if (!k_ptr->flavor) continue;
3406
3407                                 /* Require objects ever seen */
3408                                 if (!k_ptr->aware) continue;
3409                         }
3410
3411                         /* Skip items with no distribution (special artifacts) */
3412                         for (j = 0, k = 0; j < 4; j++) k += k_ptr->chance[j];
3413                         if (!k) continue;
3414                 }
3415
3416                 /* Check for objects in the group */
3417                 if (TV_LIFE_BOOK == group_tval)
3418                 {
3419                         /* Hack -- All spell books */
3420                         if (TV_LIFE_BOOK <= k_ptr->tval && k_ptr->tval <= TV_HEX_BOOK)
3421                         {
3422                                 /* Add the object */
3423                                 object_idx[object_cnt++] = i;
3424                         }
3425                         else continue;
3426                 }
3427                 else if (k_ptr->tval == group_tval)
3428                 {
3429                         /* Add the object */
3430                         object_idx[object_cnt++] = i;
3431                 }
3432                 else continue;
3433
3434                 /* XXX Hack -- Just checking for non-empty group */
3435                 if (mode & 0x01) break;
3436         }
3437
3438         /* Terminate the list */
3439         object_idx[object_cnt] = -1;
3440
3441         /* Return the number of objects */
3442         return object_cnt;
3443 }
3444
3445
3446 /*
3447  * Description of each feature group.
3448  */
3449 static concptr feature_group_text[] =
3450 {
3451         "terrains",
3452         NULL
3453 };
3454
3455
3456 /*
3457  * Build a list of feature indexes in the given group. Return the number
3458  * of features in the group.
3459  *
3460  * mode & 0x01 : check for non-empty group
3461  */
3462 static FEAT_IDX collect_features(FEAT_IDX *feat_idx, BIT_FLAGS8 mode)
3463 {
3464         /* Check every feature */
3465         FEAT_IDX feat_cnt = 0;
3466         for (FEAT_IDX i = 0; i < max_f_idx; i++)
3467         {
3468                 feature_type *f_ptr = &f_info[i];
3469
3470                 /* Skip empty index */
3471                 if (!f_ptr->name) continue;
3472
3473                 /* Skip mimiccing features */
3474                 if (f_ptr->mimic != i) continue;
3475
3476                 /* Add the index */
3477                 feat_idx[feat_cnt++] = i;
3478
3479                 /* XXX Hack -- Just checking for non-empty group */
3480                 if (mode & 0x01) break;
3481         }
3482
3483         /* Terminate the list */
3484         feat_idx[feat_cnt] = -1;
3485
3486         /* Return the number of races */
3487         return feat_cnt;
3488 }
3489
3490
3491 /*
3492  * Hack -- load a screen dump from a file
3493  */
3494 void do_cmd_load_screen(void)
3495 {
3496         TERM_LEN y, x;
3497         TERM_COLOR a = 0;
3498         SYMBOL_CODE c = ' ';
3499         bool okay = TRUE;
3500         FILE *fff;
3501         char buf[1024];
3502         TERM_LEN wid, hgt;
3503
3504         Term_get_size(&wid, &hgt);
3505         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, "dump.txt");
3506
3507         /* Append to the file */
3508         fff = my_fopen(buf, "r");
3509
3510         if (!fff)
3511         {
3512                 msg_format(_("%s を開くことができませんでした。", "Failed to open %s."), buf);
3513                 msg_print(NULL);
3514                 return;
3515         }
3516
3517         screen_save();
3518         Term_clear();
3519
3520         /* Load the screen */
3521         for (y = 0; okay; y++)
3522         {
3523                 /* Get a line of data including control code */
3524                 if (!fgets(buf, 1024, fff)) okay = FALSE;
3525
3526                 /* Get the blank line */
3527                 if (buf[0] == '\n' || buf[0] == '\0') break;
3528
3529                 /* Ignore too large screen image */
3530                 if (y >= hgt) continue;
3531
3532                 /* Show each row */
3533                 for (x = 0; x < wid - 1; x++)
3534                 {
3535                         /* End of line */
3536                         if (buf[x] == '\n' || buf[x] == '\0') break;
3537
3538                         /* Put the attr/char */
3539                         Term_draw(x, y, TERM_WHITE, buf[x]);
3540                 }
3541         }
3542
3543         /* Dump the screen */
3544         for (y = 0; okay; y++)
3545         {
3546                 /* Get a line of data including control code */
3547                 if (!fgets(buf, 1024, fff)) okay = FALSE;
3548
3549                 /* Get the blank line */
3550                 if (buf[0] == '\n' || buf[0] == '\0') break;
3551
3552                 /* Ignore too large screen image */
3553                 if (y >= hgt) continue;
3554
3555                 /* Dump each row */
3556                 for (x = 0; x < wid - 1; x++)
3557                 {
3558                         /* End of line */
3559                         if (buf[x] == '\n' || buf[x] == '\0') break;
3560
3561                         /* Get the attr/char */
3562                         (void)(Term_what(x, y, &a, &c));
3563
3564                         /* Look up the attr */
3565                         for (int i = 0; i < 16; i++)
3566                         {
3567                                 /* Use attr matches */
3568                                 if (hack[i] == buf[x]) a = (byte_hack)i;
3569                         }
3570
3571                         /* Put the attr/char */
3572                         Term_draw(x, y, a, c);
3573                 }
3574         }
3575
3576         my_fclose(fff);
3577
3578         prt(_("ファイルに書き出された画面(記念撮影)をロードしました。", "Screen dump loaded."), 0, 0);
3579
3580         flush();
3581         inkey();
3582
3583         screen_load();
3584 }
3585
3586 // todo なぜこんな中途半端なところに? defineも…
3587 concptr inven_res_label = _("                               酸電火冷毒光闇破轟獄因沌劣 盲怖乱痺透命感消復浮",
3588         "                               AcElFiCoPoLiDkShSoNtNxCaDi BlFeCfFaSeHlEpSdRgLv");
3589
3590 #define IM_FLAG_STR  _("*", "* ")
3591 #define HAS_FLAG_STR _("+", "+ ")
3592 #define NO_FLAG_STR  _("・", ". ")
3593
3594 #define print_im_or_res_flag(IM, RES) \
3595 { \
3596         fputs(have_flag(flgs, (IM)) ? IM_FLAG_STR : \
3597               (have_flag(flgs, (RES)) ? HAS_FLAG_STR : NO_FLAG_STR), fff); \
3598 }
3599
3600 #define print_flag(TR) \
3601 { \
3602         fputs(have_flag(flgs, (TR)) ? HAS_FLAG_STR : NO_FLAG_STR, fff); \
3603 }
3604
3605
3606 /* XTRA HACK RESLIST */
3607 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)
3608 {
3609         GAME_TEXT o_name[MAX_NLEN];
3610         BIT_FLAGS flgs[TR_FLAG_SIZE];
3611
3612         if (!o_ptr->k_idx) return;
3613         if (o_ptr->tval != tval) return;
3614
3615         /* Identified items only */
3616         if (!object_is_known(o_ptr)) return;
3617
3618         /*
3619          * HACK:Ring of Lordly protection and Dragon equipment
3620          * have random resistances.
3621          */
3622         bool is_special_item_type = (object_is_wearable(o_ptr) && object_is_ego(o_ptr))
3623                 || ((tval == TV_AMULET) && (o_ptr->sval == SV_AMULET_RESISTANCE))
3624                 || ((tval == TV_RING) && (o_ptr->sval == SV_RING_LORDLY))
3625                 || ((tval == TV_SHIELD) && (o_ptr->sval == SV_DRAGON_SHIELD))
3626                 || ((tval == TV_HELM) && (o_ptr->sval == SV_DRAGON_HELM))
3627                 || ((tval == TV_GLOVES) && (o_ptr->sval == SV_SET_OF_DRAGON_GLOVES))
3628                 || ((tval == TV_BOOTS) && (o_ptr->sval == SV_PAIR_OF_DRAGON_GREAVE))
3629                 || object_is_artifact(o_ptr);
3630         if (!is_special_item_type)
3631         {
3632                 return;
3633         }
3634
3635         int i = 0;
3636         object_desc(creature_ptr, o_name, o_ptr, OD_NAME_ONLY);
3637
3638         while (o_name[i] && (i < 26))
3639         {
3640 #ifdef JP
3641                 if (iskanji(o_name[i])) i++;
3642 #endif
3643                 i++;
3644         }
3645
3646         if (i < 28)
3647         {
3648                 while (i < 28)
3649                 {
3650                         o_name[i] = ' '; i++;
3651                 }
3652         }
3653
3654         o_name[i] = '\0';
3655
3656         fprintf(fff, "%s %s", where, o_name);
3657
3658         if (!(o_ptr->ident & (IDENT_MENTAL)))
3659         {
3660                 fputs(_("-------不明--------------- -------不明---------\n",
3661                         "-------unknown------------ -------unknown------\n"), fff);
3662         }
3663         else
3664         {
3665                 object_flags_known(o_ptr, flgs);
3666
3667                 print_im_or_res_flag(TR_IM_ACID, TR_RES_ACID);
3668                 print_im_or_res_flag(TR_IM_ELEC, TR_RES_ELEC);
3669                 print_im_or_res_flag(TR_IM_FIRE, TR_RES_FIRE);
3670                 print_im_or_res_flag(TR_IM_COLD, TR_RES_COLD);
3671                 print_flag(TR_RES_POIS);
3672                 print_flag(TR_RES_LITE);
3673                 print_flag(TR_RES_DARK);
3674                 print_flag(TR_RES_SHARDS);
3675                 print_flag(TR_RES_SOUND);
3676                 print_flag(TR_RES_NETHER);
3677                 print_flag(TR_RES_NEXUS);
3678                 print_flag(TR_RES_CHAOS);
3679                 print_flag(TR_RES_DISEN);
3680
3681                 fputs(" ", fff);
3682
3683                 print_flag(TR_RES_BLIND);
3684                 print_flag(TR_RES_FEAR);
3685                 print_flag(TR_RES_CONF);
3686                 print_flag(TR_FREE_ACT);
3687                 print_flag(TR_SEE_INVIS);
3688                 print_flag(TR_HOLD_EXP);
3689                 print_flag(TR_TELEPATHY);
3690                 print_flag(TR_SLOW_DIGEST);
3691                 print_flag(TR_REGEN);
3692                 print_flag(TR_LEVITATION);
3693
3694                 fputc('\n', fff);
3695         }
3696
3697         (*j)++;
3698         if (*j == 9)
3699         {
3700                 *j = 0;
3701                 fprintf(fff, "%s\n", inven_res_label);
3702         }
3703 }
3704
3705 /*
3706  * Display *ID* ed weapons/armors's resistances
3707  */
3708 static void do_cmd_knowledge_inven(player_type *creature_ptr)
3709 {
3710         FILE *fff;
3711         GAME_TEXT file_name[1024];
3712         store_type  *st_ptr;
3713         OBJECT_TYPE_VALUE tval;
3714         int i = 0;
3715         int j = 0;
3716
3717         char where[32];
3718
3719         /* Open a new file */
3720         fff = my_fopen_temp(file_name, 1024);
3721         if (!fff)
3722         {
3723                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
3724                 msg_print(NULL);
3725                 return;
3726         }
3727
3728         fprintf(fff, "%s\n", inven_res_label);
3729
3730         for (tval = TV_WEARABLE_BEGIN; tval <= TV_WEARABLE_END; tval++)
3731         {
3732                 if (j != 0)
3733                 {
3734                         for (; j < 9; j++) fputc('\n', fff);
3735                         j = 0;
3736                         fprintf(fff, "%s\n", inven_res_label);
3737                 }
3738
3739                 strcpy(where, _("装", "E "));
3740                 for (i = INVEN_RARM; i < INVEN_TOTAL; i++)
3741                 {
3742                         do_cmd_knowledge_inven_aux(creature_ptr, fff, &creature_ptr->inventory_list[i], &j, tval, where);
3743                 }
3744
3745                 strcpy(where, _("持", "I "));
3746                 for (i = 0; i < INVEN_PACK; i++)
3747                 {
3748                         do_cmd_knowledge_inven_aux(creature_ptr, fff, &creature_ptr->inventory_list[i], &j, tval, where);
3749                 }
3750
3751                 st_ptr = &town_info[1].store[STORE_HOME];
3752                 strcpy(where, _("家", "H "));
3753                 for (i = 0; i < st_ptr->stock_num; i++)
3754                 {
3755                         do_cmd_knowledge_inven_aux(creature_ptr, fff, &st_ptr->stock[i], &j, tval, where);
3756                 }
3757         }
3758
3759         my_fclose(fff);
3760
3761         /* Display the file contents */
3762         show_file(creature_ptr, TRUE, file_name, _("*鑑定*済み武器/防具の耐性リスト", "Resistances of *identified* equipment"), 0, 0);
3763         fd_kill(file_name);
3764 }
3765
3766
3767 void do_cmd_save_screen_html_aux(char *filename, int message)
3768 {
3769         concptr tags[4] = {
3770                 "HEADER_START:",
3771                 "HEADER_END:",
3772                 "FOOTER_START:",
3773                 "FOOTER_END:",
3774         };
3775         concptr html_head[] = {
3776                 "<html>\n<body text=\"#ffffff\" bgcolor=\"#000000\">\n",
3777                 "<pre>",
3778                 0,
3779         };
3780         concptr html_foot[] = {
3781                 "</pre>\n",
3782                 "</body>\n</html>\n",
3783                 0,
3784         };
3785
3786         TERM_LEN wid, hgt;
3787         Term_get_size(&wid, &hgt);
3788
3789         /* File type is "TEXT" */
3790         FILE_TYPE(FILE_TYPE_TEXT);
3791
3792         /* Append to the file */
3793         FILE *fff;
3794         fff = my_fopen(filename, "w");
3795
3796         if (!fff)
3797         {
3798                 if (message)
3799                 {
3800                         msg_format(_("ファイル %s を開けませんでした。", "Failed to open file %s."), filename);
3801                         msg_print(NULL);
3802                 }
3803
3804                 return;
3805         }
3806
3807         if (message) screen_save();
3808         char buf[2048];
3809         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, "htmldump.prf");
3810         FILE *tmpfff;
3811         tmpfff = my_fopen(buf, "r");
3812         if (!tmpfff)
3813         {
3814                 for (int i = 0; html_head[i]; i++)
3815                         fputs(html_head[i], fff);
3816         }
3817         else
3818         {
3819                 bool is_first_line = TRUE;
3820                 while (!my_fgets(tmpfff, buf, sizeof(buf)))
3821                 {
3822                         if (is_first_line)
3823                         {
3824                                 if (strncmp(buf, tags[0], strlen(tags[0])) == 0)
3825                                         is_first_line = FALSE;
3826                         }
3827                         else
3828                         {
3829                                 if (strncmp(buf, tags[1], strlen(tags[1])) == 0)
3830                                         break;
3831                                 fprintf(fff, "%s\n", buf);
3832                         }
3833                 }
3834         }
3835
3836         /* Dump the screen */
3837         for (TERM_LEN y = 0; y < hgt; y++)
3838         {
3839                 /* Start the row */
3840                 if (y != 0) fprintf(fff, "\n");
3841
3842                 /* Dump each row */
3843                 TERM_COLOR a = 0, old_a = 0;
3844                 char c = ' ';
3845                 for (TERM_LEN x = 0; x < wid - 1; x++)
3846                 {
3847                         concptr cc = NULL;
3848                         /* Get the attr/char */
3849                         (void)(Term_what(x, y, &a, &c));
3850
3851                         switch (c)
3852                         {
3853                         case '&': cc = "&amp;"; break;
3854                         case '<': cc = "&lt;"; break;
3855                         case '>': cc = "&gt;"; break;
3856 #ifdef WINDOWS
3857                         case 0x1f: c = '.'; break;
3858                         case 0x7f: c = (a == 0x09) ? '%' : '#'; break;
3859 #endif
3860                         }
3861
3862                         a = a & 0x0F;
3863                         if ((y == 0 && x == 0) || a != old_a)
3864                         {
3865                                 int rv = angband_color_table[a][1];
3866                                 int gv = angband_color_table[a][2];
3867                                 int bv = angband_color_table[a][3];
3868                                 fprintf(fff, "%s<font color=\"#%02x%02x%02x\">",
3869                                         ((y == 0 && x == 0) ? "" : "</font>"), rv, gv, bv);
3870                                 old_a = a;
3871                         }
3872
3873                         if (cc)
3874                                 fprintf(fff, "%s", cc);
3875                         else
3876                                 fprintf(fff, "%c", c);
3877                 }
3878         }
3879
3880         fprintf(fff, "</font>");
3881
3882         if (!tmpfff)
3883         {
3884                 for (int i = 0; html_foot[i]; i++)
3885                         fputs(html_foot[i], fff);
3886         }
3887         else
3888         {
3889                 rewind(tmpfff);
3890                 bool is_first_line = TRUE;
3891                 while (!my_fgets(tmpfff, buf, sizeof(buf)))
3892                 {
3893                         if (is_first_line)
3894                         {
3895                                 if (strncmp(buf, tags[2], strlen(tags[2])) == 0)
3896                                         is_first_line = FALSE;
3897                         }
3898                         else
3899                         {
3900                                 if (strncmp(buf, tags[3], strlen(tags[3])) == 0)
3901                                         break;
3902                                 fprintf(fff, "%s\n", buf);
3903                         }
3904                 }
3905
3906                 my_fclose(tmpfff);
3907         }
3908
3909         /* Skip a line */
3910         fprintf(fff, "\n");
3911         my_fclose(fff);
3912
3913         if (message)
3914         {
3915                 msg_print(_("画面(記念撮影)をファイルに書き出しました。", "Screen dump saved."));
3916                 msg_print(NULL);
3917         }
3918
3919         if (message)
3920                 screen_load();
3921 }
3922
3923 /*
3924  * Hack -- save a screen dump to a file
3925  */
3926 static void do_cmd_save_screen_html(void)
3927 {
3928         char buf[1024], tmp[256] = "screen.html";
3929
3930         if (!get_string(_("ファイル名: ", "File name: "), tmp, 80))
3931                 return;
3932         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, tmp);
3933
3934         msg_print(NULL);
3935
3936         do_cmd_save_screen_html_aux(buf, 1);
3937 }
3938
3939
3940 /*
3941  * Redefinable "save_screen" action
3942  */
3943 void(*screendump_aux)(void) = NULL;
3944
3945
3946 /*
3947  * Save a screen dump to a file
3948  * @param creature_ptr プレーヤーへの参照ポインタ
3949  * @return なし
3950  */
3951 void do_cmd_save_screen(player_type *creature_ptr)
3952 {
3953         prt(_("記念撮影しますか? [(y)es/(h)tml/(n)o] ", "Save screen dump? [(y)es/(h)tml/(n)o] "), 0, 0);
3954         bool html_dump = FALSE;
3955         while (TRUE)
3956         {
3957                 char c = inkey();
3958                 if (c == 'Y' || c == 'y')
3959                         break;
3960                 else if (c == 'H' || c == 'h')
3961                 {
3962                         html_dump = TRUE;
3963                         break;
3964                 }
3965                 else
3966                 {
3967                         prt("", 0, 0);
3968                         return;
3969                 }
3970         }
3971
3972         int wid, hgt;
3973         Term_get_size(&wid, &hgt);
3974
3975         bool old_use_graphics = use_graphics;
3976         if (old_use_graphics)
3977         {
3978                 use_graphics = FALSE;
3979                 reset_visuals(creature_ptr);
3980                 creature_ptr->redraw |= (PR_WIPE | PR_BASIC | PR_EXTRA | PR_MAP | PR_EQUIPPY);
3981                 handle_stuff(creature_ptr);
3982         }
3983
3984         if (html_dump)
3985         {
3986                 do_cmd_save_screen_html();
3987                 do_cmd_redraw(creature_ptr);
3988         }
3989
3990         /* Do we use a special screendump function ? */
3991         else if (screendump_aux)
3992         {
3993                 /* Dump the screen to a graphics file */
3994                 (*screendump_aux)();
3995         }
3996         else /* Dump the screen as text */
3997         {
3998                 TERM_LEN y, x;
3999                 TERM_COLOR a = 0;
4000                 SYMBOL_CODE c = ' ';
4001                 FILE *fff;
4002                 char buf[1024];
4003                 path_build(buf, sizeof(buf), ANGBAND_DIR_USER, "dump.txt");
4004
4005                 /* File type is "TEXT" */
4006                 FILE_TYPE(FILE_TYPE_TEXT);
4007
4008                 /* Append to the file */
4009                 fff = my_fopen(buf, "w");
4010
4011                 if (!fff)
4012                 {
4013                         msg_format(_("ファイル %s を開けませんでした。", "Failed to open file %s."), buf);
4014                         msg_print(NULL);
4015                         return;
4016                 }
4017
4018                 screen_save();
4019
4020                 /* Dump the screen */
4021                 for (y = 0; y < hgt; y++)
4022                 {
4023                         /* Dump each row */
4024                         for (x = 0; x < wid - 1; x++)
4025                         {
4026                                 /* Get the attr/char */
4027                                 (void)(Term_what(x, y, &a, &c));
4028
4029                                 /* Dump it */
4030                                 buf[x] = c;
4031                         }
4032
4033                         /* Terminate */
4034                         buf[x] = '\0';
4035
4036                         /* End the row */
4037                         fprintf(fff, "%s\n", buf);
4038                 }
4039
4040                 /* Skip a line */
4041                 fprintf(fff, "\n");
4042
4043
4044                 /* Dump the screen */
4045                 for (y = 0; y < hgt; y++)
4046                 {
4047                         /* Dump each row */
4048                         for (x = 0; x < wid - 1; x++)
4049                         {
4050                                 /* Get the attr/char */
4051                                 (void)(Term_what(x, y, &a, &c));
4052
4053                                 /* Dump it */
4054                                 buf[x] = hack[a & 0x0F];
4055                         }
4056
4057                         /* Terminate */
4058                         buf[x] = '\0';
4059
4060                         /* End the row */
4061                         fprintf(fff, "%s\n", buf);
4062                 }
4063
4064                 /* Skip a line */
4065                 fprintf(fff, "\n");
4066                 my_fclose(fff);
4067
4068                 msg_print(_("画面(記念撮影)をファイルに書き出しました。", "Screen dump saved."));
4069                 msg_print(NULL);
4070                 screen_load();
4071         }
4072
4073         if (!old_use_graphics) return;
4074
4075         use_graphics = TRUE;
4076         reset_visuals(creature_ptr);
4077         creature_ptr->redraw |= (PR_WIPE | PR_BASIC | PR_EXTRA | PR_MAP | PR_EQUIPPY);
4078         handle_stuff(creature_ptr);
4079 }
4080
4081
4082 /*
4083  * todo okay = 既知のアーティファクト? と思われるが確証がない
4084  * 分かりやすい変数名へ変更求む&万が一未知である旨の配列なら負論理なのでゴソッと差し替えるべき
4085  * Check the status of "artifacts"
4086  * @param player_ptr プレーヤーへの参照ポインタ
4087  * @return なし
4088  */
4089 static void do_cmd_knowledge_artifacts(player_type *player_ptr)
4090 {
4091         /* Open a new file */
4092         FILE *fff;
4093         GAME_TEXT file_name[1024];
4094         fff = my_fopen_temp(file_name, 1024);
4095         if (!fff)
4096         {
4097                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
4098                 msg_print(NULL);
4099                 return;
4100         }
4101
4102         /* Allocate the "who" array */
4103         ARTIFACT_IDX *who;
4104         C_MAKE(who, max_a_idx, ARTIFACT_IDX);
4105
4106         /* Allocate the "okay" array */
4107         bool *okay;
4108         C_MAKE(okay, max_a_idx, bool);
4109
4110         /* Scan the artifacts */
4111         for (ARTIFACT_IDX k = 0; k < max_a_idx; k++)
4112         {
4113                 artifact_type *a_ptr = &a_info[k];
4114
4115                 /* Default */
4116                 okay[k] = FALSE;
4117
4118                 /* Skip "empty" artifacts */
4119                 if (!a_ptr->name) continue;
4120
4121                 /* Skip "uncreated" artifacts */
4122                 if (!a_ptr->cur_num) continue;
4123
4124                 /* Assume okay */
4125                 okay[k] = TRUE;
4126         }
4127
4128         /* Check the dungeon */
4129         for (POSITION y = 0; y < player_ptr->current_floor_ptr->height; y++)
4130         {
4131                 for (POSITION x = 0; x < player_ptr->current_floor_ptr->width; x++)
4132                 {
4133                         grid_type *g_ptr = &player_ptr->current_floor_ptr->grid_array[y][x];
4134
4135                         OBJECT_IDX this_o_idx, next_o_idx = 0;
4136
4137                         /* Scan all objects in the grid */
4138                         for (this_o_idx = g_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx)
4139                         {
4140                                 object_type *o_ptr;
4141                                 o_ptr = &player_ptr->current_floor_ptr->o_list[this_o_idx];
4142                                 next_o_idx = o_ptr->next_o_idx;
4143
4144                                 /* Ignore non-artifacts */
4145                                 if (!object_is_fixed_artifact(o_ptr)) continue;
4146
4147                                 /* Ignore known items */
4148                                 if (object_is_known(o_ptr)) continue;
4149
4150                                 /* Note the artifact */
4151                                 okay[o_ptr->name1] = FALSE;
4152                         }
4153                 }
4154         }
4155
4156         /* Check the player_ptr->inventory_list and equipment */
4157         for (ARTIFACT_IDX i = 0; i < INVEN_TOTAL; i++)
4158         {
4159                 object_type *o_ptr = &player_ptr->inventory_list[i];
4160
4161                 /* Ignore non-objects */
4162                 if (!o_ptr->k_idx) continue;
4163
4164                 /* Ignore non-artifacts */
4165                 if (!object_is_fixed_artifact(o_ptr)) continue;
4166
4167                 /* Ignore known items */
4168                 if (object_is_known(o_ptr)) continue;
4169
4170                 /* Note the artifact */
4171                 okay[o_ptr->name1] = FALSE;
4172         }
4173
4174         int n = 0;
4175         for (ARTIFACT_IDX k = 0; k < max_a_idx; k++)
4176         {
4177                 if (okay[k]) who[n++] = k;
4178         }
4179
4180         u16b why = 3;
4181         ang_sort(who, &why, n, ang_sort_art_comp, ang_sort_art_swap);
4182
4183         /* Scan the artifacts */
4184         for (ARTIFACT_IDX k = 0; k < n; k++)
4185         {
4186                 artifact_type *a_ptr = &a_info[who[k]];
4187                 GAME_TEXT base_name[MAX_NLEN];
4188                 strcpy(base_name, _("未知の伝説のアイテム", "Unknown Artifact"));
4189
4190                 /* Obtain the base object type */
4191                 ARTIFACT_IDX z = lookup_kind(a_ptr->tval, a_ptr->sval);
4192
4193                 /* Real object */
4194                 if (z)
4195                 {
4196                         object_type forge;
4197                         object_type *q_ptr;
4198                         q_ptr = &forge;
4199
4200                         /* Create fake object */
4201                         object_prep(q_ptr, z);
4202
4203                         /* Make it an artifact */
4204                         q_ptr->name1 = (byte)who[k];
4205
4206                         /* Display as if known */
4207                         q_ptr->ident |= IDENT_STORE;
4208
4209                         /* Describe the artifact */
4210                         object_desc(player_ptr, base_name, q_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY));
4211                 }
4212
4213                 /* Hack -- Build the artifact name */
4214                 fprintf(fff, _("     %s\n", "     The %s\n"), base_name);
4215         }
4216
4217         /* Free the "who" array */
4218         C_KILL(who, max_a_idx, ARTIFACT_IDX);
4219
4220         /* Free the "okay" array */
4221         C_KILL(okay, max_a_idx, bool);
4222         my_fclose(fff);
4223
4224         /* Display the file contents */
4225         show_file(player_ptr, TRUE, file_name, _("既知の伝説のアイテム", "Artifacts Seen"), 0, 0);
4226         fd_kill(file_name);
4227 }
4228
4229
4230 /*
4231  * Display known uniques
4232  * With "XTRA HACK UNIQHIST" (Originally from XAngband)
4233  */
4234 static void do_cmd_knowledge_uniques(player_type *creature_ptr)
4235 {
4236         u16b why = 2;
4237         IDX *who;
4238
4239         FILE *fff;
4240
4241         GAME_TEXT file_name[1024];
4242
4243         int n_alive[10];
4244         int n_alive_surface = 0;
4245         int n_alive_over100 = 0;
4246         int n_alive_total = 0;
4247         int max_lev = -1;
4248
4249         for (IDX i = 0; i < 10; i++) n_alive[i] = 0;
4250
4251         /* Open a new file */
4252         fff = my_fopen_temp(file_name, 1024);
4253
4254         if (!fff)
4255         {
4256                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
4257                 msg_print(NULL);
4258                 return;
4259         }
4260
4261         /* Allocate the "who" array */
4262         C_MAKE(who, max_r_idx, MONRACE_IDX);
4263
4264         /* Scan the monsters */
4265         int n = 0;
4266         for (IDX i = 1; i < max_r_idx; i++)
4267         {
4268                 monster_race *r_ptr = &r_info[i];
4269                 int          lev;
4270
4271                 if (!r_ptr->name) continue;
4272
4273                 /* Require unique monsters */
4274                 if (!(r_ptr->flags1 & RF1_UNIQUE)) continue;
4275
4276                 /* Only display "known" uniques */
4277                 if (!cheat_know && !r_ptr->r_sights) continue;
4278
4279                 /* Only print rarity <= 100 uniques */
4280                 if (!r_ptr->rarity || ((r_ptr->rarity > 100) && !(r_ptr->flags1 & RF1_QUESTOR))) continue;
4281
4282                 /* Only "alive" uniques */
4283                 if (r_ptr->max_num == 0) continue;
4284
4285                 if (r_ptr->level)
4286                 {
4287                         lev = (r_ptr->level - 1) / 10;
4288                         if (lev < 10)
4289                         {
4290                                 n_alive[lev]++;
4291                                 if (max_lev < lev) max_lev = lev;
4292                         }
4293                         else n_alive_over100++;
4294                 }
4295                 else n_alive_surface++;
4296
4297                 /* Collect "appropriate" monsters */
4298                 who[n++] = i;
4299         }
4300
4301         /* Sort the array by dungeon depth of monsters */
4302         ang_sort(who, &why, n, ang_sort_comp_hook, ang_sort_swap_hook);
4303
4304         if (n_alive_surface)
4305         {
4306                 fprintf(fff, _("     地上  生存: %3d体\n", "      Surface  alive: %3d\n"), n_alive_surface);
4307                 n_alive_total += n_alive_surface;
4308         }
4309
4310         for (IDX i = 0; i <= max_lev; i++)
4311         {
4312                 fprintf(fff, _("%3d-%3d階  生存: %3d体\n", "Level %3d-%3d  alive: %3d\n"), 1 + i * 10, 10 + i * 10, n_alive[i]);
4313                 n_alive_total += n_alive[i];
4314         }
4315
4316         if (n_alive_over100)
4317         {
4318                 fprintf(fff, _("101-   階  生存: %3d体\n", "Level 101-     alive: %3d\n"), n_alive_over100);
4319                 n_alive_total += n_alive_over100;
4320         }
4321
4322         if (n_alive_total)
4323         {
4324                 fputs(_("---------  -----------\n", "-------------  ----------\n"), fff);
4325                 fprintf(fff, _("     合計  生存: %3d体\n\n", "        Total  alive: %3d\n\n"), n_alive_total);
4326         }
4327         else
4328         {
4329                 fputs(_("現在は既知の生存ユニークはいません。\n", "No known uniques alive.\n"), fff);
4330         }
4331
4332         /* Scan the monster races */
4333         for (int k = 0; k < n; k++)
4334         {
4335                 monster_race *r_ptr = &r_info[who[k]];
4336                 fprintf(fff, _("     %s (レベル%d)\n", "     %s (level %d)\n"), r_name + r_ptr->name, (int)r_ptr->level);
4337         }
4338
4339         /* Free the "who" array */
4340         C_KILL(who, max_r_idx, s16b);
4341         my_fclose(fff);
4342
4343         /* Display the file contents */
4344         show_file(creature_ptr, TRUE, file_name, _("まだ生きているユニーク・モンスター", "Alive Uniques"), 0, 0);
4345         fd_kill(file_name);
4346 }
4347
4348
4349 /*
4350  * Display weapon-exp
4351  */
4352 static void do_cmd_knowledge_weapon_exp(player_type *creature_ptr)
4353 {
4354         /* Open a new file */
4355         FILE *fff;
4356         GAME_TEXT file_name[1024];
4357         fff = my_fopen_temp(file_name, 1024);
4358         if (!fff)
4359         {
4360                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
4361                 msg_print(NULL);
4362                 return;
4363         }
4364
4365         for (int i = 0; i < 5; i++)
4366         {
4367                 for (int num = 0; num < 64; num++)
4368                 {
4369                         SUB_EXP weapon_exp;
4370                         char tmp[30];
4371                         for (KIND_OBJECT_IDX j = 0; j < max_k_idx; j++)
4372                         {
4373                                 object_kind *k_ptr = &k_info[j];
4374
4375                                 if ((k_ptr->tval != TV_SWORD - i) || (k_ptr->sval != num)) continue;
4376                                 if ((k_ptr->tval == TV_BOW) && (k_ptr->sval == SV_CRIMSON || k_ptr->sval == SV_HARP)) continue;
4377
4378                                 weapon_exp = creature_ptr->weapon_exp[4 - i][num];
4379                                 strip_name(tmp, j);
4380                                 fprintf(fff, "%-25s ", tmp);
4381                                 if (weapon_exp >= s_info[creature_ptr->pclass].w_max[4 - i][num]) fprintf(fff, "!");
4382                                 else fprintf(fff, " ");
4383                                 fprintf(fff, "%s", exp_level_str[weapon_exp_level(weapon_exp)]);
4384                                 if (cheat_xtra) fprintf(fff, " %d", weapon_exp);
4385                                 fprintf(fff, "\n");
4386                                 break;
4387                         }
4388                 }
4389         }
4390
4391         my_fclose(fff);
4392
4393         /* Display the file contents */
4394         show_file(creature_ptr, TRUE, file_name, _("武器の経験値", "Weapon Proficiency"), 0, 0);
4395         fd_kill(file_name);
4396 }
4397
4398
4399 /*!
4400  * @brief 魔法の経験値を表示するコマンドのメインルーチン
4401  * Display spell-exp
4402  * @return なし
4403  */
4404 static void do_cmd_knowledge_spell_exp(player_type *creature_ptr)
4405 {
4406         /* Open a new file */
4407         FILE *fff;
4408         GAME_TEXT file_name[1024];
4409         fff = my_fopen_temp(file_name, 1024);
4410         if (!fff)
4411         {
4412                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
4413                 msg_print(NULL);
4414                 return;
4415         }
4416
4417         if (creature_ptr->realm1 != REALM_NONE)
4418         {
4419                 fprintf(fff, _("%sの魔法書\n", "%s Spellbook\n"), realm_names[creature_ptr->realm1]);
4420                 for (SPELL_IDX i = 0; i < 32; i++)
4421                 {
4422                         const magic_type *s_ptr;
4423                         if (!is_magic(creature_ptr->realm1))
4424                         {
4425                                 s_ptr = &technic_info[creature_ptr->realm1 - MIN_TECHNIC][i];
4426                         }
4427                         else
4428                         {
4429                                 s_ptr = &mp_ptr->info[creature_ptr->realm1 - 1][i];
4430                         }
4431
4432                         if (s_ptr->slevel >= 99) continue;
4433                         SUB_EXP spell_exp = creature_ptr->spell_exp[i];
4434                         int exp_level = spell_exp_level(spell_exp);
4435                         fprintf(fff, "%-25s ", exe_spell(creature_ptr, creature_ptr->realm1, i, SPELL_NAME));
4436                         if (creature_ptr->realm1 == REALM_HISSATSU)
4437                                 fprintf(fff, "[--]");
4438                         else
4439                         {
4440                                 if (exp_level >= EXP_LEVEL_MASTER) fprintf(fff, "!");
4441                                 else fprintf(fff, " ");
4442                                 fprintf(fff, "%s", exp_level_str[exp_level]);
4443                         }
4444
4445                         if (cheat_xtra) fprintf(fff, " %d", spell_exp);
4446                         fprintf(fff, "\n");
4447                 }
4448         }
4449
4450         if (creature_ptr->realm2 != REALM_NONE)
4451         {
4452                 fprintf(fff, _("%sの魔法書\n", "\n%s Spellbook\n"), realm_names[creature_ptr->realm2]);
4453                 for (SPELL_IDX i = 0; i < 32; i++)
4454                 {
4455                         const magic_type *s_ptr;
4456                         if (!is_magic(creature_ptr->realm1))
4457                         {
4458                                 s_ptr = &technic_info[creature_ptr->realm2 - MIN_TECHNIC][i];
4459                         }
4460                         else
4461                         {
4462                                 s_ptr = &mp_ptr->info[creature_ptr->realm2 - 1][i];
4463                         }
4464
4465                         if (s_ptr->slevel >= 99) continue;
4466
4467                         SUB_EXP spell_exp = creature_ptr->spell_exp[i + 32];
4468                         int exp_level = spell_exp_level(spell_exp);
4469                         fprintf(fff, "%-25s ", exe_spell(creature_ptr, creature_ptr->realm2, i, SPELL_NAME));
4470                         if (exp_level >= EXP_LEVEL_EXPERT) fprintf(fff, "!");
4471                         else fprintf(fff, " ");
4472                         fprintf(fff, "%s", exp_level_str[exp_level]);
4473                         if (cheat_xtra) fprintf(fff, " %d", spell_exp);
4474                         fprintf(fff, "\n");
4475                 }
4476         }
4477
4478         my_fclose(fff);
4479
4480         /* Display the file contents */
4481         show_file(creature_ptr, TRUE, file_name, _("魔法の経験値", "Spell Proficiency"), 0, 0);
4482         fd_kill(file_name);
4483 }
4484
4485
4486 /*!
4487  * @brief スキル情報を表示するコマンドのメインルーチン /
4488  * Display skill-exp
4489  * @return なし
4490  */
4491 static void do_cmd_knowledge_skill_exp(player_type *creature_ptr)
4492 {
4493         char skill_name[GINOU_TEMPMAX][20] =
4494         {
4495                 _("マーシャルアーツ", "Martial Arts    "),
4496                 _("二刀流          ", "Dual Wielding   "),
4497                 _("乗馬            ", "Riding          "),
4498                 _("盾              ", "Shield          ")
4499         };
4500
4501         /* Open a new file */
4502         FILE *fff;
4503         char file_name[1024];
4504         fff = my_fopen_temp(file_name, 1024);
4505         if (!fff)
4506         {
4507                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
4508                 msg_print(NULL);
4509                 return;
4510         }
4511
4512         for (int i = 0; i < GINOU_TEMPMAX; i++)
4513         {
4514                 int skill_exp = creature_ptr->skill_exp[i];
4515                 fprintf(fff, "%-20s ", skill_name[i]);
4516                 if (skill_exp >= s_info[creature_ptr->pclass].s_max[i]) fprintf(fff, "!");
4517                 else fprintf(fff, " ");
4518                 fprintf(fff, "%s", exp_level_str[(i == GINOU_RIDING) ? riding_exp_level(skill_exp) : weapon_exp_level(skill_exp)]);
4519                 if (cheat_xtra) fprintf(fff, " %d", skill_exp);
4520                 fprintf(fff, "\n");
4521         }
4522
4523         my_fclose(fff);
4524
4525         /* Display the file contents */
4526         show_file(creature_ptr, TRUE, file_name, _("技能の経験値", "Miscellaneous Proficiency"), 0, 0);
4527         fd_kill(file_name);
4528 }
4529
4530
4531 /*!
4532  * @brief 現在のペットを表示するコマンドのメインルーチン /
4533  * Display current pets
4534  * @param creature_ptr プレーヤーへの参照ポインタ
4535  * @return なし
4536  */
4537 static void do_cmd_knowledge_pets(player_type *creature_ptr)
4538 {
4539         /* Open a new file */
4540         GAME_TEXT file_name[1024];
4541         FILE *fff;
4542         fff = my_fopen_temp(file_name, 1024);
4543         if (!fff)
4544         {
4545                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
4546                 msg_print(NULL);
4547                 return;
4548         }
4549
4550         /* Process the monsters (backwards) */
4551         monster_type *m_ptr;
4552         GAME_TEXT pet_name[MAX_NLEN];
4553         int t_friends = 0;
4554         for (int i = creature_ptr->current_floor_ptr->m_max - 1; i >= 1; i--)
4555         {
4556                 m_ptr = &creature_ptr->current_floor_ptr->m_list[i];
4557
4558                 /* Ignore "dead" monsters */
4559                 if (!monster_is_valid(m_ptr)) continue;
4560
4561                 /* Calculate "upkeep" for pets */
4562                 if (!is_pet(m_ptr)) continue;
4563
4564                 t_friends++;
4565                 monster_desc(creature_ptr, pet_name, m_ptr, MD_ASSUME_VISIBLE | MD_INDEF_VISIBLE);
4566                 fprintf(fff, "%s (%s)\n", pet_name, look_mon_desc(m_ptr, 0x00));
4567         }
4568
4569         int show_upkeep = calculate_upkeep(creature_ptr);
4570
4571         fprintf(fff, "----------------------------------------------\n");
4572 #ifdef JP
4573         fprintf(fff, "    合計: %d 体のペット\n", t_friends);
4574 #else
4575         fprintf(fff, "   Total: %d pet%s.\n", t_friends, (t_friends == 1 ? "" : "s"));
4576 #endif
4577         fprintf(fff, _(" 維持コスト: %d%% MP\n", "   Upkeep: %d%% mana.\n"), show_upkeep);
4578
4579         my_fclose(fff);
4580
4581         /* Display the file contents */
4582         show_file(creature_ptr, TRUE, file_name, _("現在のペット", "Current Pets"), 0, 0);
4583         fd_kill(file_name);
4584 }
4585
4586
4587 /*!
4588  * @brief 現在のペットを表示するコマンドのメインルーチン /
4589  * @param creature_ptr プレーヤーへの参照ポインタ
4590  * Total kill count
4591  * @return なし
4592  * @note the player ghosts are ignored.
4593  */
4594 static void do_cmd_knowledge_kill_count(player_type *creature_ptr)
4595 {
4596         /* Open a new file */
4597         FILE *fff;
4598         GAME_TEXT file_name[1024];
4599         fff = my_fopen_temp(file_name, 1024);
4600         if (!fff)
4601         {
4602                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
4603                 msg_print(NULL);
4604                 return;
4605         }
4606
4607         /* Allocate the "who" array */
4608         MONRACE_IDX *who;
4609         C_MAKE(who, max_r_idx, MONRACE_IDX);
4610
4611         s32b total = 0;
4612         {
4613                 /* Monsters slain */
4614                 for (int kk = 1; kk < max_r_idx; kk++)
4615                 {
4616                         monster_race *r_ptr = &r_info[kk];
4617
4618                         if (r_ptr->flags1 & (RF1_UNIQUE))
4619                         {
4620                                 bool dead = (r_ptr->max_num == 0);
4621
4622                                 if (dead)
4623                                 {
4624                                         total++;
4625                                 }
4626                         }
4627                         else
4628                         {
4629                                 MONSTER_NUMBER this_monster = r_ptr->r_pkills;
4630
4631                                 if (this_monster > 0)
4632                                 {
4633                                         total += this_monster;
4634                                 }
4635                         }
4636                 }
4637
4638                 if (total < 1)
4639                         fprintf(fff, _("あなたはまだ敵を倒していない。\n\n", "You have defeated no enemies yet.\n\n"));
4640                 else
4641 #ifdef JP
4642                         fprintf(fff, "あなたは%ld体の敵を倒している。\n\n", (long int)total);
4643 #else
4644                         fprintf(fff, "You have defeated %ld %s.\n\n", (long int)total, (total == 1) ? "enemy" : "enemies");
4645 #endif
4646         }
4647
4648         total = 0;
4649
4650         /* Scan the monsters */
4651         int n = 0;
4652         for (MONRACE_IDX i = 1; i < max_r_idx; i++)
4653         {
4654                 monster_race *r_ptr = &r_info[i];
4655
4656                 /* Use that monster */
4657                 if (r_ptr->name) who[n++] = i;
4658         }
4659
4660         /* Sort the array by dungeon depth of monsters */
4661         u16b why = 2;
4662         ang_sort(who, &why, n, ang_sort_comp_hook, ang_sort_swap_hook);
4663
4664         /* Scan the monster races */
4665         for (int k = 0; k < n; k++)
4666         {
4667                 monster_race *r_ptr = &r_info[who[k]];
4668
4669                 if (r_ptr->flags1 & (RF1_UNIQUE))
4670                 {
4671                         bool dead = (r_ptr->max_num == 0);
4672
4673                         if (dead)
4674                         {
4675                                 fprintf(fff, "     %s\n", (r_name + r_ptr->name));
4676                                 total++;
4677                         }
4678
4679                         continue;
4680                 }
4681
4682                 MONSTER_NUMBER this_monster = r_ptr->r_pkills;
4683
4684                 if (this_monster <= 0) continue;
4685
4686 #ifdef JP
4687                 /* p,tは人と数える by ita */
4688                 if (my_strchr("pt", r_ptr->d_char))
4689                         fprintf(fff, "     %3d 人の %s\n", (int)this_monster, r_name + r_ptr->name);
4690                 else
4691                         fprintf(fff, "     %3d 体の %s\n", (int)this_monster, r_name + r_ptr->name);
4692 #else
4693                 if (this_monster < 2)
4694                 {
4695                         if (my_strstr(r_name + r_ptr->name, "coins"))
4696                         {
4697                                 fprintf(fff, "     1 pile of %s\n", (r_name + r_ptr->name));
4698                         }
4699                         else
4700                         {
4701                                 fprintf(fff, "     1 %s\n", (r_name + r_ptr->name));
4702                         }
4703                 }
4704                 else
4705                 {
4706                         char ToPlural[80];
4707                         strcpy(ToPlural, (r_name + r_ptr->name));
4708                         plural_aux(ToPlural);
4709                         fprintf(fff, "     %d %s\n", this_monster, ToPlural);
4710                 }
4711 #endif
4712                 total += this_monster;
4713         }
4714
4715         fprintf(fff, "----------------------------------------------\n");
4716 #ifdef JP
4717         fprintf(fff, "    合計: %lu 体を倒した。\n", (unsigned long int)total);
4718 #else
4719         fprintf(fff, "   Total: %lu creature%s killed.\n", (unsigned long int)total, (total == 1 ? "" : "s"));
4720 #endif
4721
4722         /* Free the "who" array */
4723         C_KILL(who, max_r_idx, s16b);
4724         my_fclose(fff);
4725
4726         /* Display the file contents */
4727         show_file(creature_ptr, TRUE, file_name, _("倒した敵の数", "Kill Count"), 0, 0);
4728         fd_kill(file_name);
4729 }
4730
4731
4732 /*!
4733  * @brief モンスター情報リスト中のグループを表示する /
4734  * Display the object groups.
4735  * @param col 開始行
4736  * @param row 開始列
4737  * @param wid 表示文字数幅
4738  * @param per_page リストの表示行
4739  * @param grp_idx グループのID配列
4740  * @param group_text グループ名の文字列配列
4741  * @param grp_cur 現在の選択ID
4742  * @param grp_top 現在の選択リスト最上部ID
4743  * @return なし
4744  */
4745 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)
4746 {
4747         /* Display lines until done */
4748         for (int i = 0; i < per_page && (grp_idx[i] >= 0); i++)
4749         {
4750                 /* Get the group index */
4751                 int grp = grp_idx[grp_top + i];
4752
4753                 /* Choose a color */
4754                 TERM_COLOR attr = (grp_top + i == grp_cur) ? TERM_L_BLUE : TERM_WHITE;
4755
4756                 /* Erase the entire line */
4757                 Term_erase(col, row + i, wid);
4758
4759                 /* Display the group label */
4760                 c_put_str(attr, group_text[grp], row + i, col);
4761         }
4762 }
4763
4764
4765 /*
4766  * Move the cursor in a browser window
4767  */
4768 static void browser_cursor(char ch, int *column, IDX *grp_cur, int grp_cnt,
4769         IDX *list_cur, int list_cnt)
4770 {
4771         int d;
4772         int col = *column;
4773         IDX grp = *grp_cur;
4774         IDX list = *list_cur;
4775
4776         /* Extract direction */
4777         if (ch == ' ')
4778         {
4779                 /* Hack -- scroll up full screen */
4780                 d = 3;
4781         }
4782         else if (ch == '-')
4783         {
4784                 /* Hack -- scroll down full screen */
4785                 d = 9;
4786         }
4787         else
4788         {
4789                 d = get_keymap_dir(ch);
4790         }
4791
4792         if (!d) return;
4793
4794         /* Diagonals - hack */
4795         if ((ddx[d] > 0) && ddy[d])
4796         {
4797                 int browser_rows;
4798                 int wid, hgt;
4799
4800                 Term_get_size(&wid, &hgt);
4801
4802                 browser_rows = hgt - 8;
4803
4804                 /* Browse group list */
4805                 if (!col)
4806                 {
4807                         int old_grp = grp;
4808
4809                         /* Move up or down */
4810                         grp += ddy[d] * (browser_rows - 1);
4811
4812                         /* Verify */
4813                         if (grp >= grp_cnt)     grp = grp_cnt - 1;
4814                         if (grp < 0) grp = 0;
4815                         if (grp != old_grp)     list = 0;
4816                 }
4817
4818                 /* Browse sub-list list */
4819                 else
4820                 {
4821                         /* Move up or down */
4822                         list += ddy[d] * browser_rows;
4823
4824                         /* Verify */
4825                         if (list >= list_cnt) list = list_cnt - 1;
4826                         if (list < 0) list = 0;
4827                 }
4828
4829                 (*grp_cur) = grp;
4830                 (*list_cur) = list;
4831
4832                 return;
4833         }
4834
4835         if (ddx[d])
4836         {
4837                 col += ddx[d];
4838                 if (col < 0) col = 0;
4839                 if (col > 1) col = 1;
4840
4841                 (*column) = col;
4842
4843                 return;
4844         }
4845
4846         /* Browse group list */
4847         if (!col)
4848         {
4849                 int old_grp = grp;
4850
4851                 /* Move up or down */
4852                 grp += (IDX)ddy[d];
4853
4854                 /* Verify */
4855                 if (grp >= grp_cnt)     grp = grp_cnt - 1;
4856                 if (grp < 0) grp = 0;
4857                 if (grp != old_grp)     list = 0;
4858         }
4859
4860         /* Browse sub-list list */
4861         else
4862         {
4863                 /* Move up or down */
4864                 list += (IDX)ddy[d];
4865
4866                 /* Verify */
4867                 if (list >= list_cnt) list = list_cnt - 1;
4868                 if (list < 0) list = 0;
4869         }
4870
4871         (*grp_cur) = grp;
4872         (*list_cur) = list;
4873 }
4874
4875
4876 /*
4877  * Display visuals.
4878  */
4879 static void display_visual_list(int col, int row, int height, int width, TERM_COLOR attr_top, byte char_left)
4880 {
4881         /* Clear the display lines */
4882         for (int i = 0; i < height; i++)
4883         {
4884                 Term_erase(col, row + i, width);
4885         }
4886
4887         /* Bigtile mode uses double width */
4888         if (use_bigtile) width /= 2;
4889
4890         /* Display lines until done */
4891         for (int i = 0; i < height; i++)
4892         {
4893                 /* Display columns until done */
4894                 for (int j = 0; j < width; j++)
4895                 {
4896                         TERM_LEN x = col + j;
4897                         TERM_LEN y = row + i;
4898
4899                         /* Bigtile mode uses double width */
4900                         if (use_bigtile) x += j;
4901
4902                         TERM_COLOR ia = attr_top + i;
4903                         SYMBOL_CODE ic = char_left + j;
4904
4905                         /* Ignore illegal characters */
4906                         if (ia > 0x7f || ic > 0xff || ic < ' ' ||
4907                                 (!use_graphics && ic > 0x7f))
4908                                 continue;
4909
4910                         TERM_COLOR a = ia;
4911                         SYMBOL_CODE c = ic;
4912
4913                         /* Force correct code for both ASCII character and tile */
4914                         if (c & 0x80) a |= 0x80;
4915
4916                         /* Display symbol */
4917                         Term_queue_bigchar(x, y, a, c, 0, 0);
4918                 }
4919         }
4920 }
4921
4922
4923 /*
4924  * Place the cursor at the collect position for visual mode
4925  */
4926 static void place_visual_list_cursor(TERM_LEN col, TERM_LEN row, TERM_COLOR a, byte c, TERM_COLOR attr_top, byte char_left)
4927 {
4928         int i = (a & 0x7f) - attr_top;
4929         int j = c - char_left;
4930
4931         TERM_LEN x = col + j;
4932         TERM_LEN y = row + i;
4933
4934         /* Bigtile mode uses double width */
4935         if (use_bigtile) x += j;
4936
4937         /* Place the cursor */
4938         Term_gotoxy(x, y);
4939 }
4940
4941
4942 /*
4943  *  Do visual mode command -- Change symbols
4944  */
4945 static bool visual_mode_command(char ch, bool *visual_list_ptr,
4946         int height, int width,
4947         TERM_COLOR *attr_top_ptr, byte *char_left_ptr,
4948         TERM_COLOR *cur_attr_ptr, SYMBOL_CODE *cur_char_ptr, bool *need_redraw)
4949 {
4950         static TERM_COLOR attr_old = 0;
4951         static SYMBOL_CODE char_old = 0;
4952
4953         switch (ch)
4954         {
4955         case ESCAPE:
4956                 if (*visual_list_ptr)
4957                 {
4958                         /* Cancel change */
4959                         *cur_attr_ptr = attr_old;
4960                         *cur_char_ptr = char_old;
4961                         *visual_list_ptr = FALSE;
4962
4963                         return TRUE;
4964                 }
4965                 break;
4966
4967         case '\n':
4968         case '\r':
4969                 if (*visual_list_ptr)
4970                 {
4971                         /* Accept change */
4972                         *visual_list_ptr = FALSE;
4973                         *need_redraw = TRUE;
4974
4975                         return TRUE;
4976                 }
4977                 break;
4978
4979         case 'V':
4980         case 'v':
4981                 if (!*visual_list_ptr)
4982                 {
4983                         *visual_list_ptr = TRUE;
4984
4985                         *attr_top_ptr = MAX(0, (*cur_attr_ptr & 0x7f) - 5);
4986                         *char_left_ptr = MAX(0, *cur_char_ptr - 10);
4987
4988                         attr_old = *cur_attr_ptr;
4989                         char_old = *cur_char_ptr;
4990
4991                         return TRUE;
4992                 }
4993                 break;
4994
4995         case 'C':
4996         case 'c':
4997         {
4998                 int i;
4999
5000                 /* Set the visual */
5001                 attr_idx = *cur_attr_ptr;
5002                 char_idx = *cur_char_ptr;
5003
5004                 /* Hack -- for feature lighting */
5005                 for (i = 0; i < F_LIT_MAX; i++)
5006                 {
5007                         attr_idx_feat[i] = 0;
5008                         char_idx_feat[i] = 0;
5009                 }
5010         }
5011         return TRUE;
5012
5013         case 'P':
5014         case 'p':
5015                 if (attr_idx || (!(char_idx & 0x80) && char_idx)) /* Allow TERM_DARK text */
5016                 {
5017                         /* Set the char */
5018                         *cur_attr_ptr = attr_idx;
5019                         *attr_top_ptr = MAX(0, (*cur_attr_ptr & 0x7f) - 5);
5020                         if (!*visual_list_ptr) *need_redraw = TRUE;
5021                 }
5022
5023                 if (char_idx)
5024                 {
5025                         /* Set the char */
5026                         *cur_char_ptr = char_idx;
5027                         *char_left_ptr = MAX(0, *cur_char_ptr - 10);
5028                         if (!*visual_list_ptr) *need_redraw = TRUE;
5029                 }
5030
5031                 return TRUE;
5032
5033         default:
5034                 if (*visual_list_ptr)
5035                 {
5036                         int eff_width;
5037                         int d = get_keymap_dir(ch);
5038                         TERM_COLOR a = (*cur_attr_ptr & 0x7f);
5039                         SYMBOL_CODE c = *cur_char_ptr;
5040
5041                         if (use_bigtile) eff_width = width / 2;
5042                         else eff_width = width;
5043
5044                         /* Restrict direction */
5045                         if ((a == 0) && (ddy[d] < 0)) d = 0;
5046                         if ((c == 0) && (ddx[d] < 0)) d = 0;
5047                         if ((a == 0x7f) && (ddy[d] > 0)) d = 0;
5048                         if ((c == 0xff) && (ddx[d] > 0)) d = 0;
5049
5050                         a += (TERM_COLOR)ddy[d];
5051                         c += (SYMBOL_CODE)ddx[d];
5052
5053                         /* Force correct code for both ASCII character and tile */
5054                         if (c & 0x80) a |= 0x80;
5055
5056                         /* Set the visual */
5057                         *cur_attr_ptr = a;
5058                         *cur_char_ptr = c;
5059
5060
5061                         /* Move the frame */
5062                         if ((ddx[d] < 0) && *char_left_ptr > MAX(0, (int)c - 10)) (*char_left_ptr)--;
5063                         if ((ddx[d] > 0) && *char_left_ptr + eff_width < MIN(0xff, (int)c + 10)) (*char_left_ptr)++;
5064                         if ((ddy[d] < 0) && *attr_top_ptr > MAX(0, (int)(a & 0x7f) - 4)) (*attr_top_ptr)--;
5065                         if ((ddy[d] > 0) && *attr_top_ptr + height < MIN(0x7f, (a & 0x7f) + 4)) (*attr_top_ptr)++;
5066                         return TRUE;
5067                 }
5068                 break;
5069         }
5070
5071         /* Visual mode command is not used */
5072         return FALSE;
5073 }
5074
5075
5076 /*
5077  * Display the monsters in a group.
5078  */
5079 static void display_monster_list(int col, int row, int per_page, s16b mon_idx[],
5080         int mon_cur, int mon_top, bool visual_only)
5081 {
5082         /* Display lines until done */
5083         int i;
5084         for (i = 0; i < per_page && (mon_idx[mon_top + i] >= 0); i++)
5085         {
5086                 TERM_COLOR attr;
5087
5088                 /* Get the race index */
5089                 MONRACE_IDX r_idx = mon_idx[mon_top + i];
5090
5091                 /* Access the race */
5092                 monster_race *r_ptr = &r_info[r_idx];
5093
5094                 /* Choose a color */
5095                 attr = ((i + mon_top == mon_cur) ? TERM_L_BLUE : TERM_WHITE);
5096
5097                 /* Display the name */
5098                 c_prt(attr, (r_name + r_ptr->name), row + i, col);
5099
5100                 /* Hack -- visual_list mode */
5101                 if (per_page == 1)
5102                 {
5103                         c_prt(attr, format("%02x/%02x", r_ptr->x_attr, r_ptr->x_char), row + i, (current_world_ptr->wizard || visual_only) ? 56 : 61);
5104                 }
5105
5106                 if (current_world_ptr->wizard || visual_only)
5107                 {
5108                         c_prt(attr, format("%d", r_idx), row + i, 62);
5109                 }
5110
5111                 /* Erase chars before overwritten by the race letter */
5112                 Term_erase(69, row + i, 255);
5113
5114                 /* Display symbol */
5115                 Term_queue_bigchar(use_bigtile ? 69 : 70, row + i, r_ptr->x_attr, r_ptr->x_char, 0, 0);
5116
5117                 if (!visual_only)
5118                 {
5119                         /* Display kills */
5120                         if (!(r_ptr->flags1 & RF1_UNIQUE))
5121                                 put_str(format("%5d", r_ptr->r_pkills), row + i, 73);
5122                         else
5123                                 c_put_str((r_ptr->max_num == 0 ? TERM_L_DARK : TERM_WHITE),
5124                                 (r_ptr->max_num == 0 ? _("死亡", " dead") : _("生存", "alive")), row + i, 74);
5125                 }
5126         }
5127
5128         /* Clear remaining lines */
5129         for (; i < per_page; i++)
5130         {
5131                 Term_erase(col, row + i, 255);
5132         }
5133 }
5134
5135
5136 /*
5137  * todo 引数の詳細について加筆求む
5138  * Display known monsters.
5139  * @param creature_ptr プレーヤーへの参照ポインタ
5140  * @param need_redraw 画面の再描画が必要な時TRUE
5141  * @param visual_only ???
5142  * @param direct_r_idx モンスターID
5143  * @return なし
5144  */
5145 static void do_cmd_knowledge_monsters(player_type *creature_ptr, bool *need_redraw, bool visual_only, IDX direct_r_idx)
5146 {
5147         TERM_LEN wid, hgt;
5148         Term_get_size(&wid, &hgt);
5149
5150         /* Allocate the "mon_idx" array */
5151         IDX *mon_idx;
5152         C_MAKE(mon_idx, max_r_idx, MONRACE_IDX);
5153
5154         int max = 0;
5155         IDX grp_cnt = 0;
5156         IDX grp_idx[100];
5157         IDX mon_cnt;
5158         bool visual_list = FALSE;
5159         TERM_COLOR attr_top = 0;
5160         byte char_left = 0;
5161         BIT_FLAGS8 mode;
5162         int browser_rows = hgt - 8;
5163         if (direct_r_idx < 0)
5164         {
5165                 mode = visual_only ? 0x03 : 0x01;
5166
5167                 /* Check every group */
5168                 int len;
5169                 for (IDX i = 0; monster_group_text[i] != NULL; i++)
5170                 {
5171                         /* Measure the label */
5172                         len = strlen(monster_group_text[i]);
5173
5174                         /* Save the maximum length */
5175                         if (len > max) max = len;
5176
5177                         /* See if any monsters are known */
5178                         if ((monster_group_char[i] == ((char *)-1L)) || collect_monsters(creature_ptr, i, mon_idx, mode))
5179                         {
5180                                 /* Build a list of groups with known monsters */
5181                                 grp_idx[grp_cnt++] = i;
5182                         }
5183                 }
5184
5185                 mon_cnt = 0;
5186         }
5187         else
5188         {
5189                 mon_idx[0] = direct_r_idx;
5190                 mon_cnt = 1;
5191
5192                 /* Terminate the list */
5193                 mon_idx[1] = -1;
5194
5195                 (void)visual_mode_command('v', &visual_list, browser_rows - 1, wid - (max + 3),
5196                         &attr_top, &char_left, &r_info[direct_r_idx].x_attr, &r_info[direct_r_idx].x_char, need_redraw);
5197         }
5198
5199         /* Terminate the list */
5200         grp_idx[grp_cnt] = -1;
5201
5202         mode = visual_only ? 0x02 : 0x00;
5203         IDX old_grp_cur = -1;
5204         IDX grp_cur = 0;
5205         IDX grp_top = 0;
5206         IDX mon_cur = 0;
5207         IDX mon_top = 0;
5208         int column = 0;
5209         bool flag = FALSE;
5210         bool redraw = TRUE;
5211         while (!flag)
5212         {
5213                 if (redraw)
5214                 {
5215                         clear_from(0);
5216                         prt(format(_("%s - モンスター", "%s - monsters"), !visual_only ? _("知識", "Knowledge") : _("表示", "Visuals")), 2, 0);
5217                         if (direct_r_idx < 0) prt(_("グループ", "Group"), 4, 0);
5218                         prt(_("名前", "Name"), 4, max + 3);
5219                         if (current_world_ptr->wizard || visual_only) prt("Idx", 4, 62);
5220                         prt(_("文字", "Sym"), 4, 67);
5221                         if (!visual_only) prt(_("殺害数", "Kills"), 4, 72);
5222
5223                         for (IDX i = 0; i < 78; i++)
5224                         {
5225                                 Term_putch(i, 5, TERM_WHITE, '=');
5226                         }
5227
5228                         if (direct_r_idx < 0)
5229                         {
5230                                 for (IDX i = 0; i < browser_rows; i++)
5231                                 {
5232                                         Term_putch(max + 1, 6 + i, TERM_WHITE, '|');
5233                                 }
5234                         }
5235
5236                         redraw = FALSE;
5237                 }
5238
5239                 if (direct_r_idx < 0)
5240                 {
5241                         /* Scroll group list */
5242                         if (grp_cur < grp_top) grp_top = grp_cur;
5243                         if (grp_cur >= grp_top + browser_rows) grp_top = grp_cur - browser_rows + 1;
5244
5245                         /* Display a list of monster groups */
5246                         display_group_list(0, 6, max, browser_rows, grp_idx, monster_group_text, grp_cur, grp_top);
5247
5248                         if (old_grp_cur != grp_cur)
5249                         {
5250                                 old_grp_cur = grp_cur;
5251
5252                                 /* Get a list of monsters in the current group */
5253                                 mon_cnt = collect_monsters(creature_ptr, grp_idx[grp_cur], mon_idx, mode);
5254                         }
5255
5256                         /* Scroll monster list */
5257                         while (mon_cur < mon_top)
5258                                 mon_top = MAX(0, mon_top - browser_rows / 2);
5259                         while (mon_cur >= mon_top + browser_rows)
5260                                 mon_top = MIN(mon_cnt - browser_rows, mon_top + browser_rows / 2);
5261                 }
5262
5263                 if (!visual_list)
5264                 {
5265                         /* Display a list of monsters in the current group */
5266                         display_monster_list(max + 3, 6, browser_rows, mon_idx, mon_cur, mon_top, visual_only);
5267                 }
5268                 else
5269                 {
5270                         mon_top = mon_cur;
5271
5272                         /* Display a monster name */
5273                         display_monster_list(max + 3, 6, 1, mon_idx, mon_cur, mon_top, visual_only);
5274
5275                         /* Display visual list below first monster */
5276                         display_visual_list(max + 3, 7, browser_rows - 1, wid - (max + 3), attr_top, char_left);
5277                 }
5278
5279                 /* Prompt */
5280                 prt(format(_("<方向>%s%s%s, ESC", "<dir>%s%s%s, ESC"),
5281                         (!visual_list && !visual_only) ? _(", 'r'で思い出を見る", ", 'r' to recall") : "",
5282                         visual_list ? _(", ENTERで決定", ", ENTER to accept") : _(", 'v'でシンボル変更", ", 'v' for visuals"),
5283                         (attr_idx || char_idx) ? _(", 'c', 'p'でペースト", ", 'c', 'p' to paste") : _(", 'c'でコピー", ", 'c' to copy")),
5284                         hgt - 1, 0);
5285
5286                 /* Get the current monster */
5287                 monster_race *r_ptr;
5288                 r_ptr = &r_info[mon_idx[mon_cur]];
5289
5290                 if (!visual_only)
5291                 {
5292                         /* Mega Hack -- track this monster race */
5293                         if (mon_cnt) monster_race_track(creature_ptr, mon_idx[mon_cur]);
5294                         handle_stuff(creature_ptr);
5295                 }
5296
5297                 if (visual_list)
5298                 {
5299                         place_visual_list_cursor(max + 3, 7, r_ptr->x_attr, r_ptr->x_char, attr_top, char_left);
5300                 }
5301                 else if (!column)
5302                 {
5303                         Term_gotoxy(0, 6 + (grp_cur - grp_top));
5304                 }
5305                 else
5306                 {
5307                         Term_gotoxy(max + 3, 6 + (mon_cur - mon_top));
5308                 }
5309
5310                 char ch = inkey();
5311
5312                 /* Do visual mode command if needed */
5313                 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))
5314                 {
5315                         if (direct_r_idx >= 0)
5316                         {
5317                                 switch (ch)
5318                                 {
5319                                 case '\n':
5320                                 case '\r':
5321                                 case ESCAPE:
5322                                         flag = TRUE;
5323                                         break;
5324                                 }
5325                         }
5326
5327                         continue;
5328                 }
5329
5330                 switch (ch)
5331                 {
5332                 case ESCAPE:
5333                 {
5334                         flag = TRUE;
5335                         break;
5336                 }
5337
5338                 case 'R':
5339                 case 'r':
5340                 {
5341                         /* Recall on screen */
5342                         if (!visual_list && !visual_only && (mon_idx[mon_cur] > 0))
5343                         {
5344                                 screen_roff(creature_ptr, mon_idx[mon_cur], 0);
5345
5346                                 (void)inkey();
5347
5348                                 redraw = TRUE;
5349                         }
5350
5351                         break;
5352                 }
5353
5354                 default:
5355                 {
5356                         /* Move the cursor */
5357                         browser_cursor(ch, &column, &grp_cur, grp_cnt, &mon_cur, mon_cnt);
5358
5359                         break;
5360                 }
5361                 }
5362         }
5363
5364         /* Free the "mon_idx" array */
5365         C_KILL(mon_idx, max_r_idx, MONRACE_IDX);
5366 }
5367
5368
5369 /*
5370  * Display the objects in a group.
5371  */
5372 static void display_object_list(int col, int row, int per_page, IDX object_idx[],
5373         int object_cur, int object_top, bool visual_only)
5374 {
5375         /* Display lines until done */
5376         int i;
5377         for (i = 0; i < per_page && (object_idx[object_top + i] >= 0); i++)
5378         {
5379                 GAME_TEXT o_name[MAX_NLEN];
5380                 TERM_COLOR a;
5381                 SYMBOL_CODE c;
5382                 object_kind *flavor_k_ptr;
5383
5384                 /* Get the object index */
5385                 KIND_OBJECT_IDX k_idx = object_idx[object_top + i];
5386
5387                 /* Access the object */
5388                 object_kind *k_ptr = &k_info[k_idx];
5389
5390                 /* Choose a color */
5391                 TERM_COLOR attr = ((k_ptr->aware || visual_only) ? TERM_WHITE : TERM_SLATE);
5392                 byte cursor = ((k_ptr->aware || visual_only) ? TERM_L_BLUE : TERM_BLUE);
5393
5394                 if (!visual_only && k_ptr->flavor)
5395                 {
5396                         /* Appearance of this object is shuffled */
5397                         flavor_k_ptr = &k_info[k_ptr->flavor];
5398                 }
5399                 else
5400                 {
5401                         /* Appearance of this object is very normal */
5402                         flavor_k_ptr = k_ptr;
5403                 }
5404
5405                 attr = ((i + object_top == object_cur) ? cursor : attr);
5406
5407                 if (!k_ptr->flavor || (!visual_only && k_ptr->aware))
5408                 {
5409                         /* Tidy name */
5410                         strip_name(o_name, k_idx);
5411                 }
5412                 else
5413                 {
5414                         /* Flavor name */
5415                         strcpy(o_name, k_name + flavor_k_ptr->flavor_name);
5416                 }
5417
5418                 /* Display the name */
5419                 c_prt(attr, o_name, row + i, col);
5420
5421                 /* Hack -- visual_list mode */
5422                 if (per_page == 1)
5423                 {
5424                         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);
5425                 }
5426
5427                 if (current_world_ptr->wizard || visual_only)
5428                 {
5429                         c_prt(attr, format("%d", k_idx), row + i, 70);
5430                 }
5431
5432                 a = flavor_k_ptr->x_attr;
5433                 c = flavor_k_ptr->x_char;
5434
5435                 /* Display symbol */
5436                 Term_queue_bigchar(use_bigtile ? 76 : 77, row + i, a, c, 0, 0);
5437         }
5438
5439         /* Clear remaining lines */
5440         for (; i < per_page; i++)
5441         {
5442                 Term_erase(col, row + i, 255);
5443         }
5444 }
5445
5446
5447 /*
5448  * Describe fake object
5449  */
5450 static void desc_obj_fake(player_type *creature_ptr, KIND_OBJECT_IDX k_idx)
5451 {
5452         object_type *o_ptr;
5453         object_type object_type_body;
5454         o_ptr = &object_type_body;
5455         object_wipe(o_ptr);
5456         object_prep(o_ptr, k_idx);
5457
5458         /* It's fully know */
5459         o_ptr->ident |= IDENT_KNOWN;
5460         handle_stuff(creature_ptr);
5461
5462         if (screen_object(creature_ptr, o_ptr, SCROBJ_FAKE_OBJECT | SCROBJ_FORCE_DETAIL)) return;
5463
5464         msg_print(_("特に変わったところはないようだ。", "You see nothing special."));
5465         msg_print(NULL);
5466 }
5467
5468
5469 /*
5470  * Display known objects
5471  */
5472 static void do_cmd_knowledge_objects(player_type *creature_ptr, bool *need_redraw, bool visual_only, IDX direct_k_idx)
5473 {
5474         IDX object_old, object_top;
5475         IDX grp_idx[100];
5476         int object_cnt;
5477         OBJECT_IDX *object_idx;
5478
5479         bool visual_list = FALSE;
5480         TERM_COLOR attr_top = 0;
5481         byte char_left = 0;
5482         byte mode;
5483
5484         TERM_LEN wid, hgt;
5485         Term_get_size(&wid, &hgt);
5486
5487         int browser_rows = hgt - 8;
5488
5489         /* Allocate the "object_idx" array */
5490         C_MAKE(object_idx, max_k_idx, KIND_OBJECT_IDX);
5491
5492         int len;
5493         int max = 0;
5494         int grp_cnt = 0;
5495         if (direct_k_idx < 0)
5496         {
5497                 mode = visual_only ? 0x03 : 0x01;
5498
5499                 /* Check every group */
5500                 for (IDX i = 0; object_group_text[i] != NULL; i++)
5501                 {
5502                         /* Measure the label */
5503                         len = strlen(object_group_text[i]);
5504
5505                         /* Save the maximum length */
5506                         if (len > max) max = len;
5507
5508                         /* See if any monsters are known */
5509                         if (collect_objects(i, object_idx, mode))
5510                         {
5511                                 /* Build a list of groups with known monsters */
5512                                 grp_idx[grp_cnt++] = i;
5513                         }
5514                 }
5515
5516                 object_old = -1;
5517                 object_cnt = 0;
5518         }
5519         else
5520         {
5521                 object_kind *k_ptr = &k_info[direct_k_idx];
5522                 object_kind *flavor_k_ptr;
5523
5524                 if (!visual_only && k_ptr->flavor)
5525                 {
5526                         /* Appearance of this object is shuffled */
5527                         flavor_k_ptr = &k_info[k_ptr->flavor];
5528                 }
5529                 else
5530                 {
5531                         /* Appearance of this object is very normal */
5532                         flavor_k_ptr = k_ptr;
5533                 }
5534
5535                 object_idx[0] = direct_k_idx;
5536                 object_old = direct_k_idx;
5537                 object_cnt = 1;
5538
5539                 /* Terminate the list */
5540                 object_idx[1] = -1;
5541
5542                 (void)visual_mode_command('v', &visual_list, browser_rows - 1, wid - (max + 3),
5543                         &attr_top, &char_left, &flavor_k_ptr->x_attr, &flavor_k_ptr->x_char, need_redraw);
5544         }
5545
5546         /* Terminate the list */
5547         grp_idx[grp_cnt] = -1;
5548
5549         mode = visual_only ? 0x02 : 0x00;
5550         IDX old_grp_cur = -1;
5551         IDX grp_cur = 0;
5552         IDX grp_top = 0;
5553         IDX object_cur = object_top = 0;
5554         bool flag = FALSE;
5555         bool redraw = TRUE;
5556         int column = 0;
5557         while (!flag)
5558         {
5559                 object_kind *k_ptr, *flavor_k_ptr;
5560
5561                 if (redraw)
5562                 {
5563                         clear_from(0);
5564
5565 #ifdef JP
5566                         prt(format("%s - アイテム", !visual_only ? "知識" : "表示"), 2, 0);
5567                         if (direct_k_idx < 0) prt("グループ", 4, 0);
5568                         prt("名前", 4, max + 3);
5569                         if (current_world_ptr->wizard || visual_only) prt("Idx", 4, 70);
5570                         prt("文字", 4, 74);
5571 #else
5572                         prt(format("%s - objects", !visual_only ? "Knowledge" : "Visuals"), 2, 0);
5573                         if (direct_k_idx < 0) prt("Group", 4, 0);
5574                         prt("Name", 4, max + 3);
5575                         if (current_world_ptr->wizard || visual_only) prt("Idx", 4, 70);
5576                         prt("Sym", 4, 75);
5577 #endif
5578
5579                         for (IDX i = 0; i < 78; i++)
5580                         {
5581                                 Term_putch(i, 5, TERM_WHITE, '=');
5582                         }
5583
5584                         if (direct_k_idx < 0)
5585                         {
5586                                 for (IDX i = 0; i < browser_rows; i++)
5587                                 {
5588                                         Term_putch(max + 1, 6 + i, TERM_WHITE, '|');
5589                                 }
5590                         }
5591
5592                         redraw = FALSE;
5593                 }
5594
5595                 if (direct_k_idx < 0)
5596                 {
5597                         /* Scroll group list */
5598                         if (grp_cur < grp_top) grp_top = grp_cur;
5599                         if (grp_cur >= grp_top + browser_rows) grp_top = grp_cur - browser_rows + 1;
5600
5601                         /* Display a list of object groups */
5602                         display_group_list(0, 6, max, browser_rows, grp_idx, object_group_text, grp_cur, grp_top);
5603
5604                         if (old_grp_cur != grp_cur)
5605                         {
5606                                 old_grp_cur = grp_cur;
5607
5608                                 /* Get a list of objects in the current group */
5609                                 object_cnt = collect_objects(grp_idx[grp_cur], object_idx, mode);
5610                         }
5611
5612                         /* Scroll object list */
5613                         while (object_cur < object_top)
5614                                 object_top = MAX(0, object_top - browser_rows / 2);
5615                         while (object_cur >= object_top + browser_rows)
5616                                 object_top = MIN(object_cnt - browser_rows, object_top + browser_rows / 2);
5617                 }
5618
5619                 if (!visual_list)
5620                 {
5621                         /* Display a list of objects in the current group */
5622                         display_object_list(max + 3, 6, browser_rows, object_idx, object_cur, object_top, visual_only);
5623                 }
5624                 else
5625                 {
5626                         object_top = object_cur;
5627
5628                         /* Display a list of objects in the current group */
5629                         display_object_list(max + 3, 6, 1, object_idx, object_cur, object_top, visual_only);
5630
5631                         /* Display visual list below first object */
5632                         display_visual_list(max + 3, 7, browser_rows - 1, wid - (max + 3), attr_top, char_left);
5633                 }
5634
5635                 /* Get the current object */
5636                 k_ptr = &k_info[object_idx[object_cur]];
5637
5638                 if (!visual_only && k_ptr->flavor)
5639                 {
5640                         /* Appearance of this object is shuffled */
5641                         flavor_k_ptr = &k_info[k_ptr->flavor];
5642                 }
5643                 else
5644                 {
5645                         /* Appearance of this object is very normal */
5646                         flavor_k_ptr = k_ptr;
5647                 }
5648
5649                 /* Prompt */
5650 #ifdef JP
5651                 prt(format("<方向>%s%s%s, ESC",
5652                         (!visual_list && !visual_only) ? ", 'r'で詳細を見る" : "",
5653                         visual_list ? ", ENTERで決定" : ", 'v'でシンボル変更",
5654                         (attr_idx || char_idx) ? ", 'c', 'p'でペースト" : ", 'c'でコピー"),
5655                         hgt - 1, 0);
5656 #else
5657                 prt(format("<dir>%s%s%s, ESC",
5658                         (!visual_list && !visual_only) ? ", 'r' to recall" : "",
5659                         visual_list ? ", ENTER to accept" : ", 'v' for visuals",
5660                         (attr_idx || char_idx) ? ", 'c', 'p' to paste" : ", 'c' to copy"),
5661                         hgt - 1, 0);
5662 #endif
5663
5664                 if (!visual_only)
5665                 {
5666                         /* Mega Hack -- track this object */
5667                         if (object_cnt) object_kind_track(creature_ptr, object_idx[object_cur]);
5668
5669                         /* The "current" object changed */
5670                         if (object_old != object_idx[object_cur])
5671                         {
5672                                 handle_stuff(creature_ptr);
5673
5674                                 /* Remember the "current" object */
5675                                 object_old = object_idx[object_cur];
5676                         }
5677                 }
5678
5679                 if (visual_list)
5680                 {
5681                         place_visual_list_cursor(max + 3, 7, flavor_k_ptr->x_attr, flavor_k_ptr->x_char, attr_top, char_left);
5682                 }
5683                 else if (!column)
5684                 {
5685                         Term_gotoxy(0, 6 + (grp_cur - grp_top));
5686                 }
5687                 else
5688                 {
5689                         Term_gotoxy(max + 3, 6 + (object_cur - object_top));
5690                 }
5691
5692                 char ch = inkey();
5693
5694                 /* Do visual mode command if needed */
5695                 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))
5696                 {
5697                         if (direct_k_idx >= 0)
5698                         {
5699                                 switch (ch)
5700                                 {
5701                                 case '\n':
5702                                 case '\r':
5703                                 case ESCAPE:
5704                                         flag = TRUE;
5705                                         break;
5706                                 }
5707                         }
5708                         continue;
5709                 }
5710
5711                 switch (ch)
5712                 {
5713                 case ESCAPE:
5714                 {
5715                         flag = TRUE;
5716                         break;
5717                 }
5718
5719                 case 'R':
5720                 case 'r':
5721                 {
5722                         /* Recall on screen */
5723                         if (!visual_list && !visual_only && (grp_cnt > 0))
5724                         {
5725                                 desc_obj_fake(creature_ptr, object_idx[object_cur]);
5726                                 redraw = TRUE;
5727                         }
5728                         break;
5729                 }
5730
5731                 default:
5732                 {
5733                         /* Move the cursor */
5734                         browser_cursor(ch, &column, &grp_cur, grp_cnt, &object_cur, object_cnt);
5735                         break;
5736                 }
5737                 }
5738         }
5739
5740         /* Free the "object_idx" array */
5741         C_KILL(object_idx, max_k_idx, KIND_OBJECT_IDX);
5742 }
5743
5744
5745 /*
5746  * Display the features in a group.
5747  */
5748 static void display_feature_list(int col, int row, int per_page, FEAT_IDX *feat_idx,
5749         FEAT_IDX feat_cur, FEAT_IDX feat_top, bool visual_only, int lighting_level)
5750 {
5751         int lit_col[F_LIT_MAX], i;
5752         int f_idx_col = use_bigtile ? 62 : 64;
5753
5754         /* Correct columns 1 and 4 */
5755         lit_col[F_LIT_STANDARD] = use_bigtile ? (71 - F_LIT_MAX) : 71;
5756         for (i = F_LIT_NS_BEGIN; i < F_LIT_MAX; i++)
5757                 lit_col[i] = lit_col[F_LIT_STANDARD] + 2 + (i - F_LIT_NS_BEGIN) * 2 + (use_bigtile ? i : 0);
5758
5759         /* Display lines until done */
5760         for (i = 0; i < per_page && (feat_idx[feat_top + i] >= 0); i++)
5761         {
5762                 TERM_COLOR attr;
5763                 FEAT_IDX f_idx = feat_idx[feat_top + i];
5764                 feature_type *f_ptr = &f_info[f_idx];
5765                 int row_i = row + i;
5766
5767                 /* Choose a color */
5768                 attr = ((i + feat_top == feat_cur) ? TERM_L_BLUE : TERM_WHITE);
5769
5770                 /* Display the name */
5771                 c_prt(attr, f_name + f_ptr->name, row_i, col);
5772
5773                 /* Hack -- visual_list mode */
5774                 if (per_page == 1)
5775                 {
5776                         /* Display lighting level */
5777                         c_prt(attr, format("(%s)", lighting_level_str[lighting_level]), row_i, col + 1 + strlen(f_name + f_ptr->name));
5778
5779                         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));
5780                 }
5781                 if (current_world_ptr->wizard || visual_only)
5782                 {
5783                         c_prt(attr, format("%d", f_idx), row_i, f_idx_col);
5784                 }
5785
5786                 /* Display symbol */
5787                 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);
5788
5789                 Term_putch(lit_col[F_LIT_NS_BEGIN], row_i, TERM_SLATE, '(');
5790                 for (int j = F_LIT_NS_BEGIN + 1; j < F_LIT_MAX; j++)
5791                 {
5792                         Term_putch(lit_col[j], row_i, TERM_SLATE, '/');
5793                 }
5794                 Term_putch(lit_col[F_LIT_MAX - 1] + (use_bigtile ? 3 : 2), row_i, TERM_SLATE, ')');
5795
5796                 /* Mega-hack -- Use non-standard colour */
5797                 for (int j = F_LIT_NS_BEGIN; j < F_LIT_MAX; j++)
5798                 {
5799                         Term_queue_bigchar(lit_col[j] + 1, row_i, f_ptr->x_attr[j], f_ptr->x_char[j], 0, 0);
5800                 }
5801         }
5802
5803         /* Clear remaining lines */
5804         for (; i < per_page; i++)
5805         {
5806                 Term_erase(col, row + i, 255);
5807         }
5808 }
5809
5810
5811 /*
5812  * Interact with feature visuals.
5813  */
5814 static void do_cmd_knowledge_features(bool *need_redraw, bool visual_only, IDX direct_f_idx, IDX *lighting_level)
5815 {
5816         TERM_COLOR attr_old[F_LIT_MAX];
5817         (void)C_WIPE(attr_old, F_LIT_MAX, TERM_COLOR);
5818         SYMBOL_CODE char_old[F_LIT_MAX];
5819         (void)C_WIPE(char_old, F_LIT_MAX, SYMBOL_CODE);
5820
5821         TERM_LEN wid, hgt;
5822         Term_get_size(&wid, &hgt);
5823
5824         /* Allocate the "feat_idx" array */
5825         FEAT_IDX *feat_idx;
5826         C_MAKE(feat_idx, max_f_idx, FEAT_IDX);
5827
5828         int len;
5829         int max = 0;
5830         int grp_cnt = 0;
5831         int feat_cnt;
5832         FEAT_IDX grp_idx[100];
5833         TERM_COLOR attr_top = 0;
5834         bool visual_list = FALSE;
5835         byte char_left = 0;
5836         TERM_LEN browser_rows = hgt - 8;
5837         if (direct_f_idx < 0)
5838         {
5839                 /* Check every group */
5840                 for (FEAT_IDX i = 0; feature_group_text[i] != NULL; i++)
5841                 {
5842                         /* Measure the label */
5843                         len = strlen(feature_group_text[i]);
5844
5845                         /* Save the maximum length */
5846                         if (len > max) max = len;
5847
5848                         /* See if any features are known */
5849                         if (collect_features(feat_idx, 0x01))
5850                         {
5851                                 /* Build a list of groups with known features */
5852                                 grp_idx[grp_cnt++] = i;
5853                         }
5854                 }
5855
5856                 feat_cnt = 0;
5857         }
5858         else
5859         {
5860                 feature_type *f_ptr = &f_info[direct_f_idx];
5861
5862                 feat_idx[0] = direct_f_idx;
5863                 feat_cnt = 1;
5864
5865                 /* Terminate the list */
5866                 feat_idx[1] = -1;
5867
5868                 (void)visual_mode_command('v', &visual_list, browser_rows - 1, wid - (max + 3),
5869                         &attr_top, &char_left, &f_ptr->x_attr[*lighting_level], &f_ptr->x_char[*lighting_level], need_redraw);
5870
5871                 for (FEAT_IDX i = 0; i < F_LIT_MAX; i++)
5872                 {
5873                         attr_old[i] = f_ptr->x_attr[i];
5874                         char_old[i] = f_ptr->x_char[i];
5875                 }
5876         }
5877
5878         /* Terminate the list */
5879         grp_idx[grp_cnt] = -1;
5880
5881         FEAT_IDX old_grp_cur = -1;
5882         FEAT_IDX grp_cur = 0;
5883         FEAT_IDX grp_top = 0;
5884         FEAT_IDX feat_cur = 0;
5885         FEAT_IDX feat_top = 0;
5886         TERM_LEN column = 0;
5887         bool flag = FALSE;
5888         bool redraw = TRUE;
5889         TERM_COLOR *cur_attr_ptr;
5890         SYMBOL_CODE *cur_char_ptr;
5891         while (!flag)
5892         {
5893                 char ch;
5894                 feature_type *f_ptr;
5895
5896                 if (redraw)
5897                 {
5898                         clear_from(0);
5899
5900                         prt(_("表示 - 地形", "Visuals - features"), 2, 0);
5901                         if (direct_f_idx < 0) prt(_("グループ", "Group"), 4, 0);
5902                         prt(_("名前", "Name"), 4, max + 3);
5903                         if (use_bigtile)
5904                         {
5905                                 if (current_world_ptr->wizard || visual_only) prt("Idx", 4, 62);
5906                                 prt(_("文字 ( l/ d)", "Sym ( l/ d)"), 4, 66);
5907                         }
5908                         else
5909                         {
5910                                 if (current_world_ptr->wizard || visual_only) prt("Idx", 4, 64);
5911                                 prt(_("文字 (l/d)", "Sym (l/d)"), 4, 68);
5912                         }
5913
5914                         for (FEAT_IDX i = 0; i < 78; i++)
5915                         {
5916                                 Term_putch(i, 5, TERM_WHITE, '=');
5917                         }
5918
5919                         if (direct_f_idx < 0)
5920                         {
5921                                 for (FEAT_IDX i = 0; i < browser_rows; i++)
5922                                 {
5923                                         Term_putch(max + 1, 6 + i, TERM_WHITE, '|');
5924                                 }
5925                         }
5926
5927                         redraw = FALSE;
5928                 }
5929
5930                 if (direct_f_idx < 0)
5931                 {
5932                         /* Scroll group list */
5933                         if (grp_cur < grp_top) grp_top = grp_cur;
5934                         if (grp_cur >= grp_top + browser_rows) grp_top = grp_cur - browser_rows + 1;
5935
5936                         /* Display a list of feature groups */
5937                         display_group_list(0, 6, max, browser_rows, grp_idx, feature_group_text, grp_cur, grp_top);
5938
5939                         if (old_grp_cur != grp_cur)
5940                         {
5941                                 old_grp_cur = grp_cur;
5942
5943                                 /* Get a list of features in the current group */
5944                                 feat_cnt = collect_features(feat_idx, 0x00);
5945                         }
5946
5947                         /* Scroll feature list */
5948                         while (feat_cur < feat_top)
5949                                 feat_top = MAX(0, feat_top - browser_rows / 2);
5950                         while (feat_cur >= feat_top + browser_rows)
5951                                 feat_top = MIN(feat_cnt - browser_rows, feat_top + browser_rows / 2);
5952                 }
5953
5954                 if (!visual_list)
5955                 {
5956                         /* Display a list of features in the current group */
5957                         display_feature_list(max + 3, 6, browser_rows, feat_idx, feat_cur, feat_top, visual_only, F_LIT_STANDARD);
5958                 }
5959                 else
5960                 {
5961                         feat_top = feat_cur;
5962
5963                         /* Display a list of features in the current group */
5964                         display_feature_list(max + 3, 6, 1, feat_idx, feat_cur, feat_top, visual_only, *lighting_level);
5965
5966                         /* Display visual list below first object */
5967                         display_visual_list(max + 3, 7, browser_rows - 1, wid - (max + 3), attr_top, char_left);
5968                 }
5969
5970                 /* Prompt */
5971                 prt(format(_("<方向>%s, 'd'で標準光源効果%s, ESC", "<dir>%s, 'd' for default lighting%s, ESC"),
5972                         visual_list ? _(", ENTERで決定, 'a'で対象明度変更", ", ENTER to accept, 'a' for lighting level") : _(", 'v'でシンボル変更", ", 'v' for visuals"),
5973                         (attr_idx || char_idx) ? _(", 'c', 'p'でペースト", ", 'c', 'p' to paste") : _(", 'c'でコピー", ", 'c' to copy")),
5974                         hgt - 1, 0);
5975
5976                 /* Get the current feature */
5977                 f_ptr = &f_info[feat_idx[feat_cur]];
5978                 cur_attr_ptr = &f_ptr->x_attr[*lighting_level];
5979                 cur_char_ptr = &f_ptr->x_char[*lighting_level];
5980
5981                 if (visual_list)
5982                 {
5983                         place_visual_list_cursor(max + 3, 7, *cur_attr_ptr, *cur_char_ptr, attr_top, char_left);
5984                 }
5985                 else if (!column)
5986                 {
5987                         Term_gotoxy(0, 6 + (grp_cur - grp_top));
5988                 }
5989                 else
5990                 {
5991                         Term_gotoxy(max + 3, 6 + (feat_cur - feat_top));
5992                 }
5993
5994                 ch = inkey();
5995
5996                 if (visual_list && ((ch == 'A') || (ch == 'a')))
5997                 {
5998                         int prev_lighting_level = *lighting_level;
5999
6000                         if (ch == 'A')
6001                         {
6002                                 if (*lighting_level <= 0) *lighting_level = F_LIT_MAX - 1;
6003                                 else (*lighting_level)--;
6004                         }
6005                         else
6006                         {
6007                                 if (*lighting_level >= F_LIT_MAX - 1) *lighting_level = 0;
6008                                 else (*lighting_level)++;
6009                         }
6010
6011                         if (f_ptr->x_attr[prev_lighting_level] != f_ptr->x_attr[*lighting_level])
6012                                 attr_top = MAX(0, (f_ptr->x_attr[*lighting_level] & 0x7f) - 5);
6013
6014                         if (f_ptr->x_char[prev_lighting_level] != f_ptr->x_char[*lighting_level])
6015                                 char_left = MAX(0, f_ptr->x_char[*lighting_level] - 10);
6016
6017                         continue;
6018                 }
6019
6020                 else if ((ch == 'D') || (ch == 'd'))
6021                 {
6022                         TERM_COLOR prev_x_attr = f_ptr->x_attr[*lighting_level];
6023                         byte prev_x_char = f_ptr->x_char[*lighting_level];
6024
6025                         apply_default_feat_lighting(f_ptr->x_attr, f_ptr->x_char);
6026
6027                         if (visual_list)
6028                         {
6029                                 if (prev_x_attr != f_ptr->x_attr[*lighting_level])
6030                                         attr_top = MAX(0, (f_ptr->x_attr[*lighting_level] & 0x7f) - 5);
6031
6032                                 if (prev_x_char != f_ptr->x_char[*lighting_level])
6033                                         char_left = MAX(0, f_ptr->x_char[*lighting_level] - 10);
6034                         }
6035                         else *need_redraw = TRUE;
6036
6037                         continue;
6038                 }
6039
6040                 /* Do visual mode command if needed */
6041                 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))
6042                 {
6043                         switch (ch)
6044                         {
6045                                 /* Restore previous visual settings */
6046                         case ESCAPE:
6047                                 for (FEAT_IDX i = 0; i < F_LIT_MAX; i++)
6048                                 {
6049                                         f_ptr->x_attr[i] = attr_old[i];
6050                                         f_ptr->x_char[i] = char_old[i];
6051                                 }
6052
6053                                 /* Fall through */
6054
6055                         case '\n':
6056                         case '\r':
6057                                 if (direct_f_idx >= 0) flag = TRUE;
6058                                 else *lighting_level = F_LIT_STANDARD;
6059                                 break;
6060
6061                                 /* Preserve current visual settings */
6062                         case 'V':
6063                         case 'v':
6064                                 for (FEAT_IDX i = 0; i < F_LIT_MAX; i++)
6065                                 {
6066                                         attr_old[i] = f_ptr->x_attr[i];
6067                                         char_old[i] = f_ptr->x_char[i];
6068                                 }
6069                                 *lighting_level = F_LIT_STANDARD;
6070                                 break;
6071
6072                         case 'C':
6073                         case 'c':
6074                                 if (!visual_list)
6075                                 {
6076                                         for (FEAT_IDX i = 0; i < F_LIT_MAX; i++)
6077                                         {
6078                                                 attr_idx_feat[i] = f_ptr->x_attr[i];
6079                                                 char_idx_feat[i] = f_ptr->x_char[i];
6080                                         }
6081                                 }
6082                                 break;
6083
6084                         case 'P':
6085                         case 'p':
6086                                 if (!visual_list)
6087                                 {
6088                                         /* Allow TERM_DARK text */
6089                                         for (FEAT_IDX i = F_LIT_NS_BEGIN; i < F_LIT_MAX; i++)
6090                                         {
6091                                                 if (attr_idx_feat[i] || (!(char_idx_feat[i] & 0x80) && char_idx_feat[i])) f_ptr->x_attr[i] = attr_idx_feat[i];
6092                                                 if (char_idx_feat[i]) f_ptr->x_char[i] = char_idx_feat[i];
6093                                         }
6094                                 }
6095                                 break;
6096                         }
6097                         continue;
6098                 }
6099
6100                 switch (ch)
6101                 {
6102                 case ESCAPE:
6103                 {
6104                         flag = TRUE;
6105                         break;
6106                 }
6107
6108                 default:
6109                 {
6110                         /* Move the cursor */
6111                         browser_cursor(ch, &column, &grp_cur, grp_cnt, &feat_cur, feat_cnt);
6112                         break;
6113                 }
6114                 }
6115         }
6116
6117         /* Free the "feat_idx" array */
6118         C_KILL(feat_idx, max_f_idx, FEAT_IDX);
6119 }
6120
6121
6122 /*
6123  * List wanted monsters
6124  * @param creature_ptr プレーヤーへの参照ポインタ
6125  * @return なし
6126  */
6127 static void do_cmd_knowledge_bounty(player_type *creature_ptr)
6128 {
6129         /* Open a new file */
6130         FILE *fff;
6131         GAME_TEXT file_name[1024];
6132         fff = my_fopen_temp(file_name, 1024);
6133         if (!fff)
6134         {
6135                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
6136                 msg_print(NULL);
6137                 return;
6138         }
6139
6140         fprintf(fff, _("今日のターゲット : %s\n", "Today target : %s\n"),
6141                 (creature_ptr->today_mon ? r_name + r_info[creature_ptr->today_mon].name : _("不明", "unknown")));
6142         fprintf(fff, "\n");
6143         fprintf(fff, _("賞金首リスト\n", "List of wanted monsters\n"));
6144         fprintf(fff, "----------------------------------------------\n");
6145
6146         bool listed = FALSE;
6147         for (int i = 0; i < MAX_BOUNTY; i++)
6148         {
6149                 if (current_world_ptr->bounty_r_idx[i] <= 10000)
6150                 {
6151                         fprintf(fff, "%s\n", r_name + r_info[current_world_ptr->bounty_r_idx[i]].name);
6152                         listed = TRUE;
6153                 }
6154         }
6155
6156         if (!listed)
6157         {
6158                 fprintf(fff, "\n%s\n", _("賞金首はもう残っていません。", "There is no more wanted monster."));
6159         }
6160
6161         my_fclose(fff);
6162
6163         /* Display the file contents */
6164         show_file(creature_ptr, TRUE, file_name, _("賞金首の一覧", "Wanted monsters"), 0, 0);
6165         fd_kill(file_name);
6166 }
6167
6168 /*
6169  * List virtues & status
6170  */
6171 static void do_cmd_knowledge_virtues(player_type *creature_ptr)
6172 {
6173         /* Open a new file */
6174         FILE *fff;
6175         GAME_TEXT file_name[1024];
6176         fff = my_fopen_temp(file_name, 1024);
6177         if (!fff)
6178         {
6179                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
6180                 msg_print(NULL);
6181                 return;
6182         }
6183
6184         fprintf(fff, _("現在の属性 : %s\n\n", "Your alighnment : %s\n\n"), your_alignment(creature_ptr));
6185         dump_virtues(creature_ptr, fff);
6186         my_fclose(fff);
6187
6188         /* Display the file contents */
6189         show_file(creature_ptr, TRUE, file_name, _("八つの徳", "Virtues"), 0, 0);
6190         fd_kill(file_name);
6191 }
6192
6193 /*
6194  * Dungeon
6195  */
6196 static void do_cmd_knowledge_dungeon(player_type *creature_ptr)
6197 {
6198         /* Open a new file */
6199         FILE *fff;
6200         GAME_TEXT file_name[1024];
6201         fff = my_fopen_temp(file_name, 1024);
6202         if (!fff)
6203         {
6204                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
6205                 msg_print(NULL);
6206                 return;
6207         }
6208
6209         for (int i = 1; i < current_world_ptr->max_d_idx; i++)
6210         {
6211                 bool seiha = FALSE;
6212
6213                 if (!d_info[i].maxdepth) continue;
6214                 if (!max_dlv[i]) continue;
6215                 if (d_info[i].final_guardian)
6216                 {
6217                         if (!r_info[d_info[i].final_guardian].max_num) seiha = TRUE;
6218                 }
6219                 else if (max_dlv[i] == d_info[i].maxdepth) seiha = TRUE;
6220
6221                 fprintf(fff, _("%c%-12s :  %3d 階\n", "%c%-16s :  level %3d\n"), seiha ? '!' : ' ', d_name + d_info[i].name, (int)max_dlv[i]);
6222         }
6223
6224         my_fclose(fff);
6225
6226         /* Display the file contents */
6227         show_file(creature_ptr, TRUE, file_name, _("今までに入ったダンジョン", "Dungeon"), 0, 0);
6228         fd_kill(file_name);
6229 }
6230
6231
6232 /*
6233 * List virtues & status
6234 *
6235 */
6236 static void do_cmd_knowledge_stat(player_type *creature_ptr)
6237 {
6238         /* Open a new file */
6239         FILE *fff;
6240         GAME_TEXT file_name[1024];
6241         fff = my_fopen_temp(file_name, 1024);
6242         if (!fff)
6243         {
6244                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
6245                 msg_print(NULL);
6246                 return;
6247         }
6248
6249         int percent = (int)(((long)creature_ptr->player_hp[PY_MAX_LEVEL - 1] * 200L) /
6250                 (2 * creature_ptr->hitdie +
6251                 ((PY_MAX_LEVEL - 1 + 3) * (creature_ptr->hitdie + 1))));
6252
6253         if (creature_ptr->knowledge & KNOW_HPRATE)
6254                 fprintf(fff, _("現在の体力ランク : %d/100\n\n", "Your current Life Rating is %d/100.\n\n"), percent);
6255         else fprintf(fff, _("現在の体力ランク : ???\n\n", "Your current Life Rating is ???.\n\n"));
6256
6257         fprintf(fff, _("能力の最大値\n\n", "Limits of maximum stats\n\n"));
6258         for (int v_nr = 0; v_nr < A_MAX; v_nr++)
6259         {
6260                 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);
6261                 else fprintf(fff, "%s ???\n", stat_names[v_nr]);
6262         }
6263
6264         dump_yourself(creature_ptr, fff);
6265         my_fclose(fff);
6266
6267         /* Display the file contents */
6268         show_file(creature_ptr, TRUE, file_name, _("自分に関する情報", "HP-rate & Max stat"), 0, 0);
6269         fd_kill(file_name);
6270 }
6271
6272
6273 /*
6274  * todo player_typeではなくQUEST_IDXを引数にすべきかもしれない
6275  * Print all active quests
6276  * @param creature_ptr プレーヤーへの参照ポインタ
6277  * @return なし
6278  */
6279 static void do_cmd_knowledge_quests_current(player_type *creature_ptr, FILE *fff)
6280 {
6281         char tmp_str[120];
6282         char rand_tmp_str[120] = "\0";
6283         GAME_TEXT name[MAX_NLEN];
6284         monster_race *r_ptr;
6285         int rand_level = 100;
6286         int total = 0;
6287
6288         fprintf(fff, _("《遂行中のクエスト》\n", "< Current Quest >\n"));
6289
6290         for (QUEST_IDX i = 1; i < max_q_idx; i++)
6291         {
6292                 bool is_no_print = quest[i].status != QUEST_STATUS_TAKEN;
6293                 is_no_print &= (quest[i].status != QUEST_STATUS_STAGE_COMPLETED) || (quest[i].type != QUEST_TYPE_TOWER);
6294                 is_no_print &= quest[i].status == QUEST_STATUS_COMPLETED;
6295                 if (is_no_print)
6296                         continue;
6297
6298                 /* Set the quest number temporary */
6299                 QUEST_IDX old_quest = creature_ptr->current_floor_ptr->inside_quest;
6300
6301                 /* Clear the text */
6302                 for (int j = 0; j < 10; j++) quest_text[j][0] = '\0';
6303                 quest_text_line = 0;
6304
6305                 creature_ptr->current_floor_ptr->inside_quest = i;
6306
6307                 /* Get the quest text */
6308                 init_flags = INIT_SHOW_TEXT;
6309
6310                 process_dungeon_file(creature_ptr, "q_info.txt", 0, 0, 0, 0);
6311
6312                 /* Reset the old quest number */
6313                 creature_ptr->current_floor_ptr->inside_quest = old_quest;
6314
6315                 /* No info from "silent" quests */
6316                 if (quest[i].flags & QUEST_FLAG_SILENT) continue;
6317
6318                 total++;
6319
6320                 if (quest[i].type != QUEST_TYPE_RANDOM)
6321                 {
6322                         char note[80] = "\0";
6323
6324                         if (quest[i].status == QUEST_STATUS_TAKEN || quest[i].status == QUEST_STATUS_STAGE_COMPLETED)
6325                         {
6326                                 switch (quest[i].type)
6327                                 {
6328                                 case QUEST_TYPE_KILL_LEVEL:
6329                                 case QUEST_TYPE_KILL_ANY_LEVEL:
6330                                         r_ptr = &r_info[quest[i].r_idx];
6331                                         strcpy(name, r_name + r_ptr->name);
6332                                         if (quest[i].max_num > 1)
6333                                         {
6334 #ifdef JP
6335                                                 sprintf(note, " - %d 体の%sを倒す。(あと %d 体)",
6336                                                         (int)quest[i].max_num, name, (int)(quest[i].max_num - quest[i].cur_num));
6337 #else
6338                                                 plural_aux(name);
6339                                                 sprintf(note, " - kill %d %s, have killed %d.",
6340                                                         (int)quest[i].max_num, name, (int)quest[i].cur_num);
6341 #endif
6342                                         }
6343                                         else
6344                                                 sprintf(note, _(" - %sを倒す。", " - kill %s."), name);
6345                                         break;
6346
6347                                 case QUEST_TYPE_FIND_ARTIFACT:
6348                                         if (quest[i].k_idx)
6349                                         {
6350                                                 artifact_type *a_ptr = &a_info[quest[i].k_idx];
6351                                                 object_type forge;
6352                                                 object_type *q_ptr = &forge;
6353                                                 KIND_OBJECT_IDX k_idx = lookup_kind(a_ptr->tval, a_ptr->sval);
6354                                                 object_prep(q_ptr, k_idx);
6355                                                 q_ptr->name1 = quest[i].k_idx;
6356                                                 q_ptr->ident = IDENT_STORE;
6357                                                 object_desc(creature_ptr, name, q_ptr, OD_NAME_ONLY);
6358                                         }
6359                                         sprintf(note, _("\n   - %sを見つけ出す。", "\n   - Find out %s."), name);
6360                                         break;
6361                                 case QUEST_TYPE_FIND_EXIT:
6362                                         sprintf(note, _(" - 出口に到達する。", " - Reach to Exit."));
6363                                         break;
6364
6365                                 case QUEST_TYPE_KILL_NUMBER:
6366 #ifdef JP
6367                                         sprintf(note, " - %d 体のモンスターを倒す。(あと %d 体)",
6368                                                 (int)quest[i].max_num, (int)(quest[i].max_num - quest[i].cur_num));
6369 #else
6370                                         sprintf(note, " - Kill %d monsters, have killed %d.",
6371                                                 (int)quest[i].max_num, (int)quest[i].cur_num);
6372 #endif
6373                                         break;
6374
6375                                 case QUEST_TYPE_KILL_ALL:
6376                                 case QUEST_TYPE_TOWER:
6377                                         sprintf(note, _(" - 全てのモンスターを倒す。", " - Kill all monsters."));
6378                                         break;
6379                                 }
6380                         }
6381
6382                         /* Print the quest info */
6383                         sprintf(tmp_str, _("  %s (危険度:%d階相当)%s\n", "  %s (Danger level: %d)%s\n"),
6384                                 quest[i].name, (int)quest[i].level, note);
6385
6386                         fputs(tmp_str, fff);
6387
6388                         if (quest[i].status == QUEST_STATUS_COMPLETED)
6389                         {
6390                                 sprintf(tmp_str, _("    クエスト達成 - まだ報酬を受けとってない。\n", "    Quest Completed - Unrewarded\n"));
6391                                 fputs(tmp_str, fff);
6392                                 continue;
6393                         }
6394
6395                         int k = 0;
6396                         while (quest_text[k][0] && k < 10)
6397                         {
6398                                 fprintf(fff, "    %s\n", quest_text[k]);
6399                                 k++;
6400                         }
6401
6402                         continue;
6403                 }
6404
6405                 /* QUEST_TYPE_RANDOM */
6406                 if (quest[i].level >= rand_level)
6407                         continue;
6408
6409                 /* New random */
6410                 rand_level = quest[i].level;
6411
6412                 if (max_dlv[DUNGEON_ANGBAND] < rand_level) continue;
6413
6414                 /* Print the quest info */
6415                 r_ptr = &r_info[quest[i].r_idx];
6416                 strcpy(name, r_name + r_ptr->name);
6417
6418                 if (quest[i].max_num <= 1)
6419                 {
6420                         sprintf(rand_tmp_str, _("  %s (%d 階) - %sを倒す。\n", "  %s (Dungeon level: %d)\n  Kill %s.\n"),
6421                                 quest[i].name, (int)quest[i].level, name);
6422                         continue;
6423                 }
6424
6425 #ifdef JP
6426                 sprintf(rand_tmp_str, "  %s (%d 階) - %d 体の%sを倒す。(あと %d 体)\n",
6427                         quest[i].name, (int)quest[i].level,
6428                         (int)quest[i].max_num, name, (int)(quest[i].max_num - quest[i].cur_num));
6429 #else
6430                 plural_aux(name);
6431
6432                 sprintf(rand_tmp_str, "  %s (Dungeon level: %d)\n  Kill %d %s, have killed %d.\n",
6433                         quest[i].name, (int)quest[i].level,
6434                         (int)quest[i].max_num, name, (int)quest[i].cur_num);
6435 #endif
6436         }
6437
6438         /* Print the current random quest  */
6439         if (rand_tmp_str[0]) fputs(rand_tmp_str, fff);
6440
6441         if (!total) fprintf(fff, _("  なし\n", "  Nothing.\n"));
6442 }
6443
6444
6445 static bool do_cmd_knowledge_quests_aux(player_type *player_ptr, FILE *fff, IDX q_idx)
6446 {
6447         char tmp_str[120];
6448         char playtime_str[16];
6449         quest_type* const q_ptr = &quest[q_idx];
6450
6451         floor_type *floor_ptr = player_ptr->current_floor_ptr;
6452         if (is_fixed_quest_idx(q_idx))
6453         {
6454                 /* Set the quest number temporary */
6455                 IDX old_quest = floor_ptr->inside_quest;
6456
6457                 floor_ptr->inside_quest = q_idx;
6458
6459                 /* Get the quest */
6460                 init_flags = INIT_NAME_ONLY;
6461
6462                 process_dungeon_file(player_ptr, "q_info.txt", 0, 0, 0, 0);
6463
6464                 /* Reset the old quest number */
6465                 floor_ptr->inside_quest = old_quest;
6466
6467                 /* No info from "silent" quests */
6468                 if (q_ptr->flags & QUEST_FLAG_SILENT) return FALSE;
6469         }
6470
6471         strnfmt(playtime_str, sizeof(playtime_str), "%02d:%02d:%02d",
6472                 q_ptr->comptime / (60 * 60), (q_ptr->comptime / 60) % 60, q_ptr->comptime % 60);
6473
6474         if (is_fixed_quest_idx(q_idx) && q_ptr->r_idx)
6475         {
6476                 /* Print the quest info */
6477                 sprintf(tmp_str,
6478                         _("  %-35s (危険度:%3d階相当) - レベル%2d - %s\n",
6479                                 "  %-35s (Danger  level: %3d) - level %2d - %s\n"),
6480                         q_ptr->name, (int)q_ptr->level, q_ptr->complev, playtime_str);
6481                 fputs(tmp_str, fff);
6482                 return TRUE;
6483         }
6484
6485         /* Print the quest info */
6486         if (q_ptr->complev == 0)
6487         {
6488                 sprintf(tmp_str,
6489                         _("  %-35s (%3d階)            -   不戦勝 - %s\n",
6490                                 "  %-35s (Dungeon level: %3d) - Unearned - %s\n"),
6491                         r_name + r_info[q_ptr->r_idx].name,
6492                         (int)q_ptr->level, playtime_str);
6493                 fputs(tmp_str, fff);
6494                 return TRUE;
6495         }
6496
6497         sprintf(tmp_str,
6498                 _("  %-35s (%3d階)            - レベル%2d - %s\n",
6499                         "  %-35s (Dungeon level: %3d) - level %2d - %s\n"),
6500                 r_name + r_info[q_ptr->r_idx].name,
6501                 (int)q_ptr->level,
6502                 q_ptr->complev,
6503                 playtime_str);
6504         fputs(tmp_str, fff);
6505         return TRUE;
6506 }
6507
6508
6509 /*
6510  * Print all finished quests
6511  * @param creature_ptr プレーヤーへの参照ポインタ
6512  * @param fff セーブファイル (展開済?)
6513  * @param quest_num[] 受注したことのあるクエスト群
6514  * @return なし
6515  */
6516 void do_cmd_knowledge_quests_completed(player_type *creature_ptr, FILE *fff, QUEST_IDX quest_num[])
6517 {
6518         fprintf(fff, _("《達成したクエスト》\n", "< Completed Quest >\n"));
6519         QUEST_IDX total = 0;
6520         for (QUEST_IDX i = 1; i < max_q_idx; i++)
6521         {
6522                 QUEST_IDX q_idx = quest_num[i];
6523                 quest_type* const q_ptr = &quest[q_idx];
6524
6525                 if (q_ptr->status == QUEST_STATUS_FINISHED && do_cmd_knowledge_quests_aux(creature_ptr, fff, q_idx))
6526                 {
6527                         ++total;
6528                 }
6529         }
6530
6531         if (!total) fprintf(fff, _("  なし\n", "  Nothing.\n"));
6532 }
6533
6534
6535 /*
6536  * Print all failed quests
6537  * @param creature_ptr プレーヤーへの参照ポインタ
6538  * @param fff セーブファイル (展開済?)
6539  * @param quest_num[] 受注したことのあるクエスト群
6540  * @return なし
6541 */
6542 void do_cmd_knowledge_quests_failed(player_type *creature_ptr, FILE *fff, QUEST_IDX quest_num[])
6543 {
6544         fprintf(fff, _("《失敗したクエスト》\n", "< Failed Quest >\n"));
6545         QUEST_IDX total = 0;
6546         for (QUEST_IDX i = 1; i < max_q_idx; i++)
6547         {
6548                 QUEST_IDX q_idx = quest_num[i];
6549                 quest_type* const q_ptr = &quest[q_idx];
6550
6551                 if (((q_ptr->status == QUEST_STATUS_FAILED_DONE) || (q_ptr->status == QUEST_STATUS_FAILED)) &&
6552                         do_cmd_knowledge_quests_aux(creature_ptr, fff, q_idx))
6553                 {
6554                         ++total;
6555                 }
6556         }
6557
6558         if (!total) fprintf(fff, _("  なし\n", "  Nothing.\n"));
6559 }
6560
6561
6562 /*
6563  * Print all random quests
6564  */
6565 static void do_cmd_knowledge_quests_wiz_random(FILE *fff)
6566 {
6567         fprintf(fff, _("《残りのランダムクエスト》\n", "< Remaining Random Quest >\n"));
6568         GAME_TEXT tmp_str[120];
6569         QUEST_IDX total = 0;
6570         for (QUEST_IDX i = 1; i < max_q_idx; i++)
6571         {
6572                 /* No info from "silent" quests */
6573                 if (quest[i].flags & QUEST_FLAG_SILENT) continue;
6574
6575                 if ((quest[i].type == QUEST_TYPE_RANDOM) && (quest[i].status == QUEST_STATUS_TAKEN))
6576                 {
6577                         total++;
6578
6579                         /* Print the quest info */
6580                         sprintf(tmp_str, _("  %s (%d階, %s)\n", "  %s (%d, %s)\n"),
6581                                 quest[i].name, (int)quest[i].level, r_name + r_info[quest[i].r_idx].name);
6582                         fputs(tmp_str, fff);
6583                 }
6584         }
6585
6586         if (!total) fprintf(fff, _("  なし\n", "  Nothing.\n"));
6587 }
6588
6589 /*
6590  * Print quest status of all active quests
6591  * @param creature_ptr プレーヤーへの参照ポインタ
6592  * @return なし
6593  */
6594 static void do_cmd_knowledge_quests(player_type *creature_ptr)
6595 {
6596         /* Open a new file */
6597         FILE *fff;
6598         GAME_TEXT file_name[1024];
6599         fff = my_fopen_temp(file_name, 1024);
6600         if (!fff)
6601         {
6602                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
6603                 msg_print(NULL);
6604                 return;
6605         }
6606
6607         /* Allocate Memory */
6608         IDX *quest_num;
6609         C_MAKE(quest_num, max_q_idx, QUEST_IDX);
6610
6611         /* Sort by compete level */
6612         for (IDX i = 1; i < max_q_idx; i++) quest_num[i] = i;
6613         int dummy;
6614         ang_sort(quest_num, &dummy, max_q_idx, ang_sort_comp_quest_num, ang_sort_swap_quest_num);
6615
6616         /* Dump Quest Information */
6617         do_cmd_knowledge_quests_current(creature_ptr, fff);
6618         fputc('\n', fff);
6619         do_cmd_knowledge_quests_completed(creature_ptr, fff, quest_num);
6620         fputc('\n', fff);
6621         do_cmd_knowledge_quests_failed(creature_ptr, fff, quest_num);
6622         if (current_world_ptr->wizard)
6623         {
6624                 fputc('\n', fff);
6625                 do_cmd_knowledge_quests_wiz_random(fff);
6626         }
6627
6628         my_fclose(fff);
6629
6630         /* Display the file contents */
6631         show_file(creature_ptr, TRUE, file_name, _("クエスト達成状況", "Quest status"), 0, 0);
6632         fd_kill(file_name);
6633
6634         /* Free Memory */
6635         C_KILL(quest_num, max_q_idx, QUEST_IDX);
6636 }
6637
6638
6639 /*
6640  * List my home
6641  * @param player_ptr プレーヤーへの参照ポインタ
6642  * @return なし
6643  */
6644 static void do_cmd_knowledge_home(player_type *player_ptr)
6645 {
6646         process_dungeon_file(player_ptr, "w_info.txt", 0, 0, current_world_ptr->max_wild_y, current_world_ptr->max_wild_x);
6647
6648         /* Open a new file */
6649         FILE *fff;
6650         GAME_TEXT file_name[1024];
6651         fff = my_fopen_temp(file_name, 1024);
6652         if (!fff)
6653         {
6654                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
6655                 msg_print(NULL);
6656                 return;
6657         }
6658
6659         /* Print all homes in the different towns */
6660         store_type *st_ptr;
6661         st_ptr = &town_info[1].store[STORE_HOME];
6662
6663         /* Home -- if anything there */
6664         if (st_ptr->stock_num)
6665         {
6666 #ifdef JP
6667                 TERM_LEN x = 1;
6668 #endif
6669                 /* Header with name of the town */
6670                 fprintf(fff, _("  [ 我が家のアイテム ]\n", "  [Home Inventory]\n"));
6671
6672                 /* Dump all available items */
6673                 concptr paren = ")";
6674                 GAME_TEXT o_name[MAX_NLEN];
6675                 for (int i = 0; i < st_ptr->stock_num; i++)
6676                 {
6677 #ifdef JP
6678                         if ((i % 12) == 0) fprintf(fff, "\n ( %d ページ )\n", x++);
6679                         object_desc(player_ptr, o_name, &st_ptr->stock[i], 0);
6680                         if (strlen(o_name) <= 80 - 3)
6681                         {
6682                                 fprintf(fff, "%c%s %s\n", I2A(i % 12), paren, o_name);
6683                         }
6684                         else
6685                         {
6686                                 int n;
6687                                 char *t;
6688                                 for (n = 0, t = o_name; n < 80 - 3; n++, t++)
6689                                         if (iskanji(*t)) { t++; n++; }
6690                                 if (n == 81 - 3) n = 79 - 3; /* 最後が漢字半分 */
6691
6692                                 fprintf(fff, "%c%s %.*s\n", I2A(i % 12), paren, n, o_name);
6693                                 fprintf(fff, "   %.77s\n", o_name + n);
6694                         }
6695 #else
6696                         object_desc(player_ptr, o_name, &st_ptr->stock[i], 0);
6697                         fprintf(fff, "%c%s %s\n", I2A(i % 12), paren, o_name);
6698 #endif
6699                 }
6700
6701                 /* Add an empty line */
6702                 fprintf(fff, "\n\n");
6703         }
6704
6705         my_fclose(fff);
6706
6707         /* Display the file contents */
6708         show_file(player_ptr, TRUE, file_name, _("我が家のアイテム", "Home Inventory"), 0, 0);
6709         fd_kill(file_name);
6710 }
6711
6712
6713 /*
6714  * Check the status of "autopick"
6715  */
6716 static void do_cmd_knowledge_autopick(player_type *creature_ptr)
6717 {
6718         /* Open a new file */
6719         FILE *fff;
6720         GAME_TEXT file_name[1024];
6721         fff = my_fopen_temp(file_name, 1024);
6722         if (!fff)
6723         {
6724                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
6725                 msg_print(NULL);
6726                 return;
6727         }
6728
6729         if (!max_autopick)
6730         {
6731                 fprintf(fff, _("自動破壊/拾いには何も登録されていません。", "No preference for auto picker/destroyer."));
6732         }
6733         else
6734         {
6735                 fprintf(fff, _("   自動拾い/破壊には現在 %d行登録されています。\n\n",
6736                         "   There are %d registered lines for auto picker/destroyer.\n\n"), max_autopick);
6737         }
6738
6739         for (int k = 0; k < max_autopick; k++)
6740         {
6741                 concptr tmp;
6742                 byte act = autopick_list[k].action;
6743                 if (act & DONT_AUTOPICK)
6744                 {
6745                         tmp = _("放置", "Leave");
6746                 }
6747                 else if (act & DO_AUTODESTROY)
6748                 {
6749                         tmp = _("破壊", "Destroy");
6750                 }
6751                 else if (act & DO_AUTOPICK)
6752                 {
6753                         tmp = _("拾う", "Pickup");
6754                 }
6755                 else
6756                 {
6757                         tmp = _("確認", "Query");
6758                 }
6759
6760                 if (act & DO_DISPLAY)
6761                         fprintf(fff, "%11s", format("[%s]", tmp));
6762                 else
6763                         fprintf(fff, "%11s", format("(%s)", tmp));
6764
6765                 tmp = autopick_line_from_entry(&autopick_list[k]);
6766                 fprintf(fff, " %s", tmp);
6767                 string_free(tmp);
6768                 fprintf(fff, "\n");
6769         }
6770
6771         my_fclose(fff);
6772
6773         /* Display the file contents */
6774         show_file(creature_ptr, TRUE, file_name, _("自動拾い/破壊 設定リスト", "Auto-picker/Destroyer"), 0, 0);
6775         fd_kill(file_name);
6776 }
6777
6778
6779 /*
6780  * Interact with "knowledge"
6781  */
6782 void do_cmd_knowledge(player_type *creature_ptr)
6783 {
6784         int i, p = 0;
6785         bool need_redraw = FALSE;
6786
6787         /* File type is "TEXT" */
6788         FILE_TYPE(FILE_TYPE_TEXT);
6789         screen_save();
6790
6791         /* Interact until done */
6792         while (TRUE)
6793         {
6794                 Term_clear();
6795
6796                 /* Ask for a choice */
6797                 prt(format(_("%d/2 ページ", "page %d/2"), (p + 1)), 2, 65);
6798                 prt(_("現在の知識を確認する", "Display current knowledge"), 3, 0);
6799
6800                 /* Give some choices */
6801 #ifdef JP
6802                 if (p == 0)
6803                 {
6804                         prt("(1) 既知の伝説のアイテム                 の一覧", 6, 5);
6805                         prt("(2) 既知のアイテム                       の一覧", 7, 5);
6806                         prt("(3) 既知の生きているユニーク・モンスター の一覧", 8, 5);
6807                         prt("(4) 既知のモンスター                     の一覧", 9, 5);
6808                         prt("(5) 倒した敵の数                         の一覧", 10, 5);
6809                         if (!vanilla_town) prt("(6) 賞金首                               の一覧", 11, 5);
6810                         prt("(7) 現在のペット                         の一覧", 12, 5);
6811                         prt("(8) 我が家のアイテム                     の一覧", 13, 5);
6812                         prt("(9) *鑑定*済み装備の耐性                 の一覧", 14, 5);
6813                         prt("(0) 地形の表示文字/タイル                の一覧", 15, 5);
6814                 }
6815                 else
6816                 {
6817                         prt("(a) 自分に関する情報                     の一覧", 6, 5);
6818                         prt("(b) 突然変異                             の一覧", 7, 5);
6819                         prt("(c) 武器の経験値                         の一覧", 8, 5);
6820                         prt("(d) 魔法の経験値                         の一覧", 9, 5);
6821                         prt("(e) 技能の経験値                         の一覧", 10, 5);
6822                         prt("(f) プレイヤーの徳                       の一覧", 11, 5);
6823                         prt("(g) 入ったダンジョン                     の一覧", 12, 5);
6824                         prt("(h) 実行中のクエスト                     の一覧", 13, 5);
6825                         prt("(i) 現在の自動拾い/破壊設定              の一覧", 14, 5);
6826                 }
6827 #else
6828                 if (p == 0)
6829                 {
6830                         prt("(1) Display known artifacts", 6, 5);
6831                         prt("(2) Display known objects", 7, 5);
6832                         prt("(3) Display remaining uniques", 8, 5);
6833                         prt("(4) Display known monster", 9, 5);
6834                         prt("(5) Display kill count", 10, 5);
6835                         if (!vanilla_town) prt("(6) Display wanted monsters", 11, 5);
6836                         prt("(7) Display current pets", 12, 5);
6837                         prt("(8) Display home inventory", 13, 5);
6838                         prt("(9) Display *identified* equip.", 14, 5);
6839                         prt("(0) Display terrain symbols.", 15, 5);
6840                 }
6841                 else
6842                 {
6843                         prt("(a) Display about yourself", 6, 5);
6844                         prt("(b) Display mutations", 7, 5);
6845                         prt("(c) Display weapon proficiency", 8, 5);
6846                         prt("(d) Display spell proficiency", 9, 5);
6847                         prt("(e) Display misc. proficiency", 10, 5);
6848                         prt("(f) Display virtues", 11, 5);
6849                         prt("(g) Display dungeons", 12, 5);
6850                         prt("(h) Display current quests", 13, 5);
6851                         prt("(i) Display auto pick/destroy", 14, 5);
6852                 }
6853 #endif
6854                 /* Prompt */
6855                 prt(_("-続く-", "-more-"), 17, 8);
6856                 prt(_("ESC) 抜ける", "ESC) Exit menu"), 21, 1);
6857                 prt(_("SPACE) 次ページ", "SPACE) Next page"), 21, 30);
6858                 /*prt("-) 前ページ", 21, 60);*/
6859                 prt(_("コマンド:", "Command: "), 20, 0);
6860                 i = inkey();
6861
6862                 if (i == ESCAPE) break;
6863                 switch (i)
6864                 {
6865                 case ' ': /* Page change */
6866                 case '-':
6867                         p = 1 - p;
6868                         break;
6869                 case '1': /* Artifacts */
6870                         do_cmd_knowledge_artifacts(creature_ptr);
6871                         break;
6872                 case '2': /* Objects */
6873                         do_cmd_knowledge_objects(creature_ptr, &need_redraw, FALSE, -1);
6874                         break;
6875                 case '3': /* Uniques */
6876                         do_cmd_knowledge_uniques(creature_ptr);
6877                         break;
6878                 case '4': /* Monsters */
6879                         do_cmd_knowledge_monsters(creature_ptr, &need_redraw, FALSE, -1);
6880                         break;
6881                 case '5': /* Kill count  */
6882                         do_cmd_knowledge_kill_count(creature_ptr);
6883                         break;
6884                 case '6': /* wanted */
6885                         if (!vanilla_town) do_cmd_knowledge_bounty(creature_ptr);
6886                         break;
6887                 case '7': /* Pets */
6888                         do_cmd_knowledge_pets(creature_ptr);
6889                         break;
6890                 case '8': /* Home */
6891                         do_cmd_knowledge_home(creature_ptr);
6892                         break;
6893                 case '9': /* Resist list */
6894                         do_cmd_knowledge_inven(creature_ptr);
6895                         break;
6896                 case '0': /* Feature list */
6897                 {
6898                         IDX lighting_level = F_LIT_STANDARD;
6899                         do_cmd_knowledge_features(&need_redraw, FALSE, -1, &lighting_level);
6900                 }
6901                 break;
6902                 /* Next page */
6903                 case 'a': /* Max stat */
6904                         do_cmd_knowledge_stat(creature_ptr);
6905                         break;
6906                 case 'b': /* Mutations */
6907                         do_cmd_knowledge_mutations(creature_ptr);
6908                         break;
6909                 case 'c': /* weapon-exp */
6910                         do_cmd_knowledge_weapon_exp(creature_ptr);
6911                         break;
6912                 case 'd': /* spell-exp */
6913                         do_cmd_knowledge_spell_exp(creature_ptr);
6914                         break;
6915                 case 'e': /* skill-exp */
6916                         do_cmd_knowledge_skill_exp(creature_ptr);
6917                         break;
6918                 case 'f': /* Virtues */
6919                         do_cmd_knowledge_virtues(creature_ptr);
6920                         break;
6921                 case 'g': /* Dungeon */
6922                         do_cmd_knowledge_dungeon(creature_ptr);
6923                         break;
6924                 case 'h': /* Quests */
6925                         do_cmd_knowledge_quests(creature_ptr);
6926                         break;
6927                 case 'i': /* Autopick */
6928                         do_cmd_knowledge_autopick(creature_ptr);
6929                         break;
6930                 default: /* Unknown option */
6931                         bell();
6932                 }
6933
6934                 msg_erase();
6935         }
6936
6937         screen_load();
6938         if (need_redraw) do_cmd_redraw(creature_ptr);
6939 }
6940
6941
6942 /*
6943  * Check on the status of an active quest
6944  * @param creature_ptr プレーヤーへの参照ポインタ
6945  * @return なし
6946  */
6947 void do_cmd_checkquest(player_type *creature_ptr)
6948 {
6949         /* File type is "TEXT" */
6950         FILE_TYPE(FILE_TYPE_TEXT);
6951         screen_save();
6952
6953         /* Quest info */
6954         do_cmd_knowledge_quests(creature_ptr);
6955         screen_load();
6956 }
6957
6958
6959 /*
6960  * Display the time and date
6961  * @param creature_ptr プレーヤーへの参照ポインタ
6962  * @return なし
6963  */
6964 void do_cmd_time(player_type *creature_ptr)
6965 {
6966         int day, hour, min;
6967         extract_day_hour_min(creature_ptr, &day, &hour, &min);
6968
6969         char desc[1024];
6970         strcpy(desc, _("変な時刻だ。", "It is a strange time."));
6971
6972         char day_buf[10];
6973         if (day < MAX_DAYS) sprintf(day_buf, "%d", day);
6974         else strcpy(day_buf, "*****");
6975
6976         msg_format(_("%s日目, 時刻は%d:%02d %sです。", "This is day %s. The time is %d:%02d %s."),
6977                 day_buf, (hour % 12 == 0) ? 12 : (hour % 12), min, (hour < 12) ? "AM" : "PM");
6978
6979         /* Find the path */
6980         char buf[1024];
6981         if (!randint0(10) || creature_ptr->image)
6982         {
6983                 path_build(buf, sizeof(buf), ANGBAND_DIR_FILE, _("timefun_j.txt", "timefun.txt"));
6984         }
6985         else
6986         {
6987                 path_build(buf, sizeof(buf), ANGBAND_DIR_FILE, _("timenorm_j.txt", "timenorm.txt"));
6988         }
6989
6990         /* Open this file */
6991         FILE *fff;
6992         fff = my_fopen(buf, "rt");
6993
6994         if (!fff) return;
6995
6996         /* Find this time */
6997         int full = hour * 100 + min;
6998         int start = 9999;
6999         int end = -9999;
7000         int num = 0;
7001         while (!my_fgets(fff, buf, sizeof(buf)))
7002         {
7003                 /* Ignore comments */
7004                 if (!buf[0] || (buf[0] == '#')) continue;
7005
7006                 /* Ignore invalid lines */
7007                 if (buf[1] != ':') continue;
7008
7009                 /* Process 'Start' */
7010                 if (buf[0] == 'S')
7011                 {
7012                         /* Extract the starting time */
7013                         start = atoi(buf + 2);
7014
7015                         /* Assume valid for an hour */
7016                         end = start + 59;
7017                         continue;
7018                 }
7019
7020                 /* Process 'End' */
7021                 if (buf[0] == 'E')
7022                 {
7023                         /* Extract the ending time */
7024                         end = atoi(buf + 2);
7025                         continue;
7026                 }
7027
7028                 /* Ignore incorrect range */
7029                 if ((start > full) || (full > end)) continue;
7030
7031                 /* Process 'Description' */
7032                 if (buf[0] == 'D')
7033                 {
7034                         num++;
7035
7036                         /* Apply the randomizer */
7037                         if (!randint0(num)) strcpy(desc, buf + 2);
7038                         continue;
7039                 }
7040         }
7041
7042         msg_print(desc);
7043         my_fclose(fff);
7044 }