OSDN Git Service

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