OSDN Git Service

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