OSDN Git Service

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