OSDN Git Service

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