OSDN Git Service

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