OSDN Git Service

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