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