OSDN Git Service

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