OSDN Git Service

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