OSDN Git Service

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