OSDN Git Service

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