OSDN Git Service

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