OSDN Git Service

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