OSDN Git Service

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