OSDN Git Service

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