OSDN Git Service

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