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                 /* Access the index */
4474                 feature_type *f_ptr = &f_info[i];
4475
4476                 /* Skip empty index */
4477                 if (!f_ptr->name) continue;
4478
4479                 /* Skip mimiccing features */
4480                 if (f_ptr->mimic != i) continue;
4481
4482                 /* Add the index */
4483                 feat_idx[feat_cnt++] = i;
4484
4485                 /* XXX Hack -- Just checking for non-empty group */
4486                 if (mode & 0x01) break;
4487         }
4488
4489         /* Terminate the list */
4490         feat_idx[feat_cnt] = -1;
4491
4492         /* Return the number of races */
4493         return feat_cnt;
4494 }
4495
4496
4497 #if 0
4498 /*
4499  * Build a list of monster indexes in the given group. Return the number
4500  * of monsters in the group.
4501  */
4502 static int collect_artifacts(int grp_cur, int object_idx[])
4503 {
4504         int i, object_cnt = 0;
4505
4506         /* Get a list of x_char in this group */
4507         byte group_tval = object_group_tval[grp_cur];
4508
4509         /* Check every object */
4510         for (i = 0; i < max_a_idx; i++)
4511         {
4512                 /* Access the artifact */
4513                 artifact_type *a_ptr = &a_info[i];
4514
4515                 /* Skip empty artifacts */
4516                 if (!a_ptr->name) continue;
4517
4518                 /* Skip "uncreated" artifacts */
4519                 if (!a_ptr->cur_num) continue;
4520
4521                 /* Check for race in the group */
4522                 if (a_ptr->tval == group_tval)
4523                 {
4524                         /* Add the race */
4525                         object_idx[object_cnt++] = i;
4526                 }
4527         }
4528
4529         /* Terminate the list */
4530         object_idx[object_cnt] = 0;
4531
4532         /* Return the number of races */
4533         return object_cnt;
4534 }
4535 #endif /* 0 */
4536
4537
4538 /*
4539  * Encode the screen colors
4540  */
4541 static char hack[17] = "dwsorgbuDWvyRGBU";
4542
4543
4544 /*
4545  * Hack -- load a screen dump from a file
4546  */
4547 void do_cmd_load_screen(void)
4548 {
4549         int i;
4550         TERM_LEN y, x;
4551         TERM_COLOR a = 0;
4552         SYMBOL_CODE c = ' ';
4553         bool okay = TRUE;
4554         FILE *fff;
4555         char buf[1024];
4556         TERM_LEN wid, hgt;
4557
4558         Term_get_size(&wid, &hgt);
4559
4560         /* Build the filename */
4561         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, "dump.txt");
4562
4563         /* Append to the file */
4564         fff = my_fopen(buf, "r");
4565
4566         if (!fff) {
4567                 msg_format(_("%s を開くことができませんでした。", "Failed to open %s."), buf);
4568                 msg_print(NULL);
4569                 return;
4570         }
4571
4572         screen_save();
4573         Term_clear();
4574
4575         /* Load the screen */
4576         for (y = 0; okay; y++)
4577         {
4578                 /* Get a line of data including control code */
4579                 if (!fgets(buf, 1024, fff)) okay = FALSE;
4580
4581                 /* Get the blank line */
4582                 if (buf[0] == '\n' || buf[0] == '\0') break;
4583
4584                 /* Ignore too large screen image */
4585                 if (y >= hgt) continue;
4586
4587                 /* Show each row */
4588                 for (x = 0; x < wid - 1; x++)
4589                 {
4590                         /* End of line */
4591                         if (buf[x] == '\n' || buf[x] == '\0') break;
4592
4593                         /* Put the attr/char */
4594                         Term_draw(x, y, TERM_WHITE, buf[x]);
4595                 }
4596         }
4597
4598         /* Dump the screen */
4599         for (y = 0; okay; y++)
4600         {
4601                 /* Get a line of data including control code */
4602                 if (!fgets(buf, 1024, fff)) okay = FALSE;
4603
4604                 /* Get the blank line */
4605                 if (buf[0] == '\n' || buf[0] == '\0') break;
4606
4607                 /* Ignore too large screen image */
4608                 if (y >= hgt) continue;
4609
4610                 /* Dump each row */
4611                 for (x = 0; x < wid - 1; x++)
4612                 {
4613                         /* End of line */
4614                         if (buf[x] == '\n' || buf[x] == '\0') break;
4615
4616                         /* Get the attr/char */
4617                         (void)(Term_what(x, y, &a, &c));
4618
4619                         /* Look up the attr */
4620                         for (i = 0; i < 16; i++)
4621                         {
4622                                 /* Use attr matches */
4623                                 if (hack[i] == buf[x]) a = (byte_hack)i;
4624                         }
4625
4626                         /* Put the attr/char */
4627                         Term_draw(x, y, a, c);
4628                 }
4629         }
4630         my_fclose(fff);
4631
4632         prt(_("ファイルに書き出された画面(記念撮影)をロードしました。", "Screen dump loaded."), 0, 0);
4633
4634         flush();
4635         inkey();
4636
4637         screen_load();
4638 }
4639
4640
4641
4642
4643 concptr inven_res_label = _("                               酸電火冷毒光闇破轟獄因沌劣 盲怖乱痺透命感消復浮",
4644                                                  "                               AcElFiCoPoLiDkShSoNtNxCaDi BlFeCfFaSeHlEpSdRgLv");
4645
4646
4647 #define IM_FLAG_STR  _("*", "* ")
4648 #define HAS_FLAG_STR _("+", "+ ")
4649 #define NO_FLAG_STR  _("・", ". ")
4650
4651 #define print_im_or_res_flag(IM, RES) \
4652 { \
4653         fputs(have_flag(flgs, (IM)) ? IM_FLAG_STR : \
4654               (have_flag(flgs, (RES)) ? HAS_FLAG_STR : NO_FLAG_STR), fff); \
4655 }
4656
4657 #define print_flag(TR) \
4658 { \
4659         fputs(have_flag(flgs, (TR)) ? HAS_FLAG_STR : NO_FLAG_STR, fff); \
4660 }
4661
4662
4663 /* XTRA HACK RESLIST */
4664 static void do_cmd_knowledge_inven_aux(FILE *fff, object_type *o_ptr, int *j, OBJECT_TYPE_VALUE tval, char *where)
4665 {
4666         GAME_TEXT o_name[MAX_NLEN];
4667         BIT_FLAGS flgs[TR_FLAG_SIZE];
4668
4669         if (!o_ptr->k_idx) return;
4670         if (o_ptr->tval != tval) return;
4671
4672         /* Identified items only */
4673         if (!object_is_known(o_ptr)) return;
4674
4675         /*
4676          * HACK:Ring of Lordly protection and Dragon equipment
4677          * have random resistances.
4678          */
4679         if ((object_is_wearable(o_ptr) && object_is_ego(o_ptr))
4680             || ((tval == TV_AMULET) && (o_ptr->sval == SV_AMULET_RESISTANCE))
4681             || ((tval == TV_RING) && (o_ptr->sval == SV_RING_LORDLY))
4682             || ((tval == TV_SHIELD) && (o_ptr->sval == SV_DRAGON_SHIELD))
4683             || ((tval == TV_HELM) && (o_ptr->sval == SV_DRAGON_HELM))
4684             || ((tval == TV_GLOVES) && (o_ptr->sval == SV_SET_OF_DRAGON_GLOVES))
4685             || ((tval == TV_BOOTS) && (o_ptr->sval == SV_PAIR_OF_DRAGON_GREAVE))
4686             || object_is_artifact(o_ptr))
4687         {
4688                 int i = 0;
4689                 object_desc(o_name, o_ptr, OD_NAME_ONLY);
4690
4691                 while (o_name[i] && (i < 26))
4692                 {
4693 #ifdef JP
4694                         if (iskanji(o_name[i])) i++;
4695 #endif
4696                         i++;
4697                 }
4698
4699                 if (i < 28)
4700                 {
4701                         while (i < 28)
4702                         {
4703                                 o_name[i] = ' '; i++;
4704                         }
4705                 }
4706                 o_name[i] = '\0';
4707
4708                 fprintf(fff, "%s %s", where, o_name);
4709
4710                 if (!(o_ptr->ident & (IDENT_MENTAL)))
4711                 {
4712                         fputs(_("-------不明--------------- -------不明---------\n", 
4713                                         "-------unknown------------ -------unknown------\n"), fff);
4714                 }
4715                 else
4716                 {
4717                         object_flags_known(o_ptr, flgs);
4718
4719                         print_im_or_res_flag(TR_IM_ACID, TR_RES_ACID);
4720                         print_im_or_res_flag(TR_IM_ELEC, TR_RES_ELEC);
4721                         print_im_or_res_flag(TR_IM_FIRE, TR_RES_FIRE);
4722                         print_im_or_res_flag(TR_IM_COLD, TR_RES_COLD);
4723                         print_flag(TR_RES_POIS);
4724                         print_flag(TR_RES_LITE);
4725                         print_flag(TR_RES_DARK);
4726                         print_flag(TR_RES_SHARDS);
4727                         print_flag(TR_RES_SOUND);
4728                         print_flag(TR_RES_NETHER);
4729                         print_flag(TR_RES_NEXUS);
4730                         print_flag(TR_RES_CHAOS);
4731                         print_flag(TR_RES_DISEN);
4732
4733                         fputs(" ", fff);
4734
4735                         print_flag(TR_RES_BLIND);
4736                         print_flag(TR_RES_FEAR);
4737                         print_flag(TR_RES_CONF);
4738                         print_flag(TR_FREE_ACT);
4739                         print_flag(TR_SEE_INVIS);
4740                         print_flag(TR_HOLD_EXP);
4741                         print_flag(TR_TELEPATHY);
4742                         print_flag(TR_SLOW_DIGEST);
4743                         print_flag(TR_REGEN);
4744                         print_flag(TR_LEVITATION);
4745
4746                         fputc('\n', fff);
4747                 }
4748                 (*j)++;
4749                 if (*j == 9)
4750                 {
4751                         *j = 0;
4752                         fprintf(fff, "%s\n", inven_res_label);
4753                 }
4754         }
4755 }
4756
4757 /*
4758  * Display *ID* ed weapons/armors's resistances
4759  */
4760 static void do_cmd_knowledge_inven(void)
4761 {
4762         FILE *fff;
4763         GAME_TEXT file_name[1024];
4764         store_type  *st_ptr;
4765         OBJECT_TYPE_VALUE tval;
4766         int i = 0;
4767         int j = 0;
4768
4769         char where[32];
4770
4771         /* Open a new file */
4772         fff = my_fopen_temp(file_name, 1024);
4773         if (!fff)
4774         {
4775             msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
4776             msg_print(NULL);
4777             return;
4778         }
4779         fprintf(fff, "%s\n", inven_res_label);
4780
4781         for (tval = TV_WEARABLE_BEGIN; tval <= TV_WEARABLE_END; tval++)
4782         {
4783                 if (j != 0)
4784                 {
4785                         for (; j < 9; j++) fputc('\n', fff);
4786                         j = 0;
4787                         fprintf(fff, "%s\n", inven_res_label);
4788                 }
4789                 strcpy(where, _("装", "E "));
4790                 for (i = INVEN_RARM; i < INVEN_TOTAL; i++)
4791                 {
4792                         do_cmd_knowledge_inven_aux(fff, &inventory[i], &j, tval, where);
4793                 }
4794                 strcpy(where, _("持", "I "));
4795                 for (i = 0; i < INVEN_PACK; i++)
4796                 {
4797                         do_cmd_knowledge_inven_aux(fff, &inventory[i], &j, tval, where);
4798                 }
4799
4800                 st_ptr = &town_info[1].store[STORE_HOME];
4801                 strcpy(where, _("家", "H "));
4802                 for (i = 0; i < st_ptr->stock_num; i++)
4803                 {
4804                         do_cmd_knowledge_inven_aux(fff, &st_ptr->stock[i], &j, tval, where);
4805                 }
4806         }
4807         my_fclose(fff);
4808
4809         /* Display the file contents */
4810         show_file(TRUE, file_name, _("*鑑定*済み武器/防具の耐性リスト", "Resistances of *identified* equipment"), 0, 0);
4811         fd_kill(file_name);
4812 }
4813
4814
4815 void do_cmd_save_screen_html_aux(char *filename, int message)
4816 {
4817         TERM_LEN y, x;
4818         int i;
4819
4820         TERM_COLOR a = 0, old_a = 0;
4821         char c = ' ';
4822
4823         FILE *fff, *tmpfff;
4824         char buf[2048];
4825
4826         int yomikomu = 0;
4827         concptr tags[4] = {
4828                 "HEADER_START:",
4829                 "HEADER_END:",
4830                 "FOOTER_START:",
4831                 "FOOTER_END:",
4832         };
4833
4834         concptr html_head[] = {
4835                 "<html>\n<body text=\"#ffffff\" bgcolor=\"#000000\">\n",
4836                 "<pre>",
4837                 0,
4838         };
4839         concptr html_foot[] = {
4840                 "</pre>\n",
4841                 "</body>\n</html>\n",
4842                 0,
4843         };
4844
4845         TERM_LEN wid, hgt;
4846
4847         Term_get_size(&wid, &hgt);
4848
4849         /* File type is "TEXT" */
4850         FILE_TYPE(FILE_TYPE_TEXT);
4851
4852         /* Append to the file */
4853         fff = my_fopen(filename, "w");
4854
4855         if (!fff) {
4856                 if (message) {
4857                     msg_format(_("ファイル %s を開けませんでした。", "Failed to open file %s."), filename);
4858                     msg_print(NULL);
4859                 }
4860                 
4861                 return;
4862         }
4863         if (message) screen_save();
4864
4865         /* Build the filename */
4866         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, "htmldump.prf");
4867         tmpfff = my_fopen(buf, "r");
4868         if (!tmpfff) {
4869                 for (i = 0; html_head[i]; i++)
4870                         fputs(html_head[i], fff);
4871         }
4872         else {
4873                 yomikomu = 0;
4874                 while (!my_fgets(tmpfff, buf, sizeof(buf))) {
4875                         if (!yomikomu) {
4876                                 if (strncmp(buf, tags[0], strlen(tags[0])) == 0)
4877                                         yomikomu = 1;
4878                         }
4879                         else {
4880                                 if (strncmp(buf, tags[1], strlen(tags[1])) == 0)
4881                                         break;
4882                                 fprintf(fff, "%s\n", buf);
4883                         }
4884                 }
4885         }
4886
4887         /* Dump the screen */
4888         for (y = 0; y < hgt; y++)
4889         {
4890                 /* Start the row */
4891                 if (y != 0)
4892                         fprintf(fff, "\n");
4893
4894                 /* Dump each row */
4895                 for (x = 0; x < wid - 1; x++)
4896                 {
4897                         int rv, gv, bv;
4898                         concptr cc = NULL;
4899                         /* Get the attr/char */
4900                         (void)(Term_what(x, y, &a, &c));
4901
4902                         switch (c)
4903                         {
4904                         case '&': cc = "&amp;"; break;
4905                         case '<': cc = "&lt;"; break;
4906                         case '>': cc = "&gt;"; break;
4907 #ifdef WINDOWS
4908                         case 0x1f: c = '.'; break;
4909                         case 0x7f: c = (a == 0x09) ? '%' : '#'; break;
4910 #endif
4911                         }
4912
4913                         a = a & 0x0F;
4914                         if ((y == 0 && x == 0) || a != old_a) {
4915                                 rv = angband_color_table[a][1];
4916                                 gv = angband_color_table[a][2];
4917                                 bv = angband_color_table[a][3];
4918                                 fprintf(fff, "%s<font color=\"#%02x%02x%02x\">", 
4919                                         ((y == 0 && x == 0) ? "" : "</font>"), rv, gv, bv);
4920                                 old_a = a;
4921                         }
4922                         if (cc)
4923                                 fprintf(fff, "%s", cc);
4924                         else
4925                                 fprintf(fff, "%c", c);
4926                 }
4927         }
4928         fprintf(fff, "</font>");
4929
4930         if (!tmpfff) {
4931                 for (i = 0; html_foot[i]; i++)
4932                         fputs(html_foot[i], fff);
4933         }
4934         else {
4935                 rewind(tmpfff);
4936                 yomikomu = 0;
4937                 while (!my_fgets(tmpfff, buf, sizeof(buf))) {
4938                         if (!yomikomu) {
4939                                 if (strncmp(buf, tags[2], strlen(tags[2])) == 0)
4940                                         yomikomu = 1;
4941                         }
4942                         else {
4943                                 if (strncmp(buf, tags[3], strlen(tags[3])) == 0)
4944                                         break;
4945                                 fprintf(fff, "%s\n", buf);
4946                         }
4947                 }
4948                 my_fclose(tmpfff);
4949         }
4950
4951         /* Skip a line */
4952         fprintf(fff, "\n");
4953         my_fclose(fff);
4954
4955         if (message) {
4956                 msg_print(_("画面(記念撮影)をファイルに書き出しました。", "Screen dump saved."));
4957                 msg_print(NULL);
4958         }
4959         if (message)
4960                 screen_load();
4961 }
4962
4963 /*
4964  * Hack -- save a screen dump to a file
4965  */
4966 static void do_cmd_save_screen_html(void)
4967 {
4968         char buf[1024], tmp[256] = "screen.html";
4969
4970         if (!get_string(_("ファイル名: ", "File name: "), tmp, 80))
4971                 return;
4972
4973         /* Build the filename */
4974         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, tmp);
4975
4976         msg_print(NULL);
4977
4978         do_cmd_save_screen_html_aux(buf, 1);
4979 }
4980
4981
4982 /*
4983  * Redefinable "save_screen" action
4984  */
4985 void (*screendump_aux)(void) = NULL;
4986
4987
4988 /*
4989  * Hack -- save a screen dump to a file
4990  */
4991 void do_cmd_save_screen(void)
4992 {
4993         bool old_use_graphics = use_graphics;
4994         bool html_dump = FALSE;
4995
4996         int wid, hgt;
4997
4998         prt(_("記念撮影しますか? [(y)es/(h)tml/(n)o] ", "Save screen dump? [(y)es/(h)tml/(n)o] "), 0, 0);
4999         while(TRUE)
5000         {
5001                 char c = inkey();
5002                 if (c == 'Y' || c == 'y')
5003                         break;
5004                 else if (c == 'H' || c == 'h')
5005                 {
5006                         html_dump = TRUE;
5007                         break;
5008                 }
5009                 else
5010                 {
5011                         prt("", 0, 0);
5012                         return;
5013                 }
5014         }
5015
5016         Term_get_size(&wid, &hgt);
5017
5018         if (old_use_graphics)
5019         {
5020                 use_graphics = FALSE;
5021                 reset_visuals();
5022                 p_ptr->redraw |= (PR_WIPE | PR_BASIC | PR_EXTRA | PR_MAP | PR_EQUIPPY);
5023                 handle_stuff();
5024         }
5025
5026         if (html_dump)
5027         {
5028                 do_cmd_save_screen_html();
5029                 do_cmd_redraw();
5030         }
5031
5032         /* Do we use a special screendump function ? */
5033         else if (screendump_aux)
5034         {
5035                 /* Dump the screen to a graphics file */
5036                 (*screendump_aux)();
5037         }
5038         else /* Dump the screen as text */
5039         {
5040                 TERM_LEN y, x;
5041                 TERM_COLOR a = 0;
5042                 SYMBOL_CODE c = ' ';
5043                 FILE *fff;
5044                 char buf[1024];
5045
5046                 /* Build the filename */
5047                 path_build(buf, sizeof(buf), ANGBAND_DIR_USER, "dump.txt");
5048
5049                 /* File type is "TEXT" */
5050                 FILE_TYPE(FILE_TYPE_TEXT);
5051
5052                 /* Append to the file */
5053                 fff = my_fopen(buf, "w");
5054
5055                 if (!fff)
5056                 {
5057                         msg_format(_("ファイル %s を開けませんでした。", "Failed to open file %s."), buf);
5058                         msg_print(NULL);
5059                         return;
5060                 }
5061
5062                 screen_save();
5063
5064
5065                 /* Dump the screen */
5066                 for (y = 0; y < hgt; y++)
5067                 {
5068                         /* Dump each row */
5069                         for (x = 0; x < wid - 1; x++)
5070                         {
5071                                 /* Get the attr/char */
5072                                 (void)(Term_what(x, y, &a, &c));
5073
5074                                 /* Dump it */
5075                                 buf[x] = c;
5076                         }
5077
5078                         /* Terminate */
5079                         buf[x] = '\0';
5080
5081                         /* End the row */
5082                         fprintf(fff, "%s\n", buf);
5083                 }
5084
5085                 /* Skip a line */
5086                 fprintf(fff, "\n");
5087
5088
5089                 /* Dump the screen */
5090                 for (y = 0; y < hgt; y++)
5091                 {
5092                         /* Dump each row */
5093                         for (x = 0; x < wid - 1; x++)
5094                         {
5095                                 /* Get the attr/char */
5096                                 (void)(Term_what(x, y, &a, &c));
5097
5098                                 /* Dump it */
5099                                 buf[x] = hack[a&0x0F];
5100                         }
5101
5102                         /* Terminate */
5103                         buf[x] = '\0';
5104
5105                         /* End the row */
5106                         fprintf(fff, "%s\n", buf);
5107                 }
5108
5109                 /* Skip a line */
5110                 fprintf(fff, "\n");
5111                 my_fclose(fff);
5112
5113                 msg_print(_("画面(記念撮影)をファイルに書き出しました。", "Screen dump saved."));
5114                 msg_print(NULL);
5115                 screen_load();
5116         }
5117
5118         if (old_use_graphics)
5119         {
5120                 use_graphics = TRUE;
5121                 reset_visuals();
5122                 p_ptr->redraw |= (PR_WIPE | PR_BASIC | PR_EXTRA | PR_MAP | PR_EQUIPPY);
5123                 handle_stuff();
5124         }
5125 }
5126
5127
5128 /*
5129  * Sorting hook -- Comp function -- see below
5130  *
5131  * We use "u" to point to array of monster indexes,
5132  * and "v" to select the type of sorting to perform on "u".
5133  */
5134 static bool ang_sort_art_comp(vptr u, vptr v, int a, int b)
5135 {
5136         u16b *who = (u16b*)(u);
5137
5138         u16b *why = (u16b*)(v);
5139
5140         int w1 = who[a];
5141         int w2 = who[b];
5142
5143         int z1, z2;
5144
5145         /* Sort by total kills */
5146         if (*why >= 3)
5147         {
5148                 /* Extract total kills */
5149                 z1 = a_info[w1].tval;
5150                 z2 = a_info[w2].tval;
5151
5152                 /* Compare total kills */
5153                 if (z1 < z2) return (TRUE);
5154                 if (z1 > z2) return (FALSE);
5155         }
5156
5157
5158         /* Sort by monster level */
5159         if (*why >= 2)
5160         {
5161                 /* Extract levels */
5162                 z1 = a_info[w1].sval;
5163                 z2 = a_info[w2].sval;
5164
5165                 /* Compare levels */
5166                 if (z1 < z2) return (TRUE);
5167                 if (z1 > z2) return (FALSE);
5168         }
5169
5170
5171         /* Sort by monster experience */
5172         if (*why >= 1)
5173         {
5174                 /* Extract experience */
5175                 z1 = a_info[w1].level;
5176                 z2 = a_info[w2].level;
5177
5178                 /* Compare experience */
5179                 if (z1 < z2) return (TRUE);
5180                 if (z1 > z2) return (FALSE);
5181         }
5182
5183
5184         /* Compare indexes */
5185         return (w1 <= w2);
5186 }
5187
5188
5189 /*
5190  * Sorting hook -- Swap function -- see below
5191  *
5192  * We use "u" to point to array of monster indexes,
5193  * and "v" to select the type of sorting to perform.
5194  */
5195 static void ang_sort_art_swap(vptr u, vptr v, int a, int b)
5196 {
5197         u16b *who = (u16b*)(u);
5198
5199         u16b holder;
5200
5201         /* Unused */
5202         (void)v;
5203
5204         /* Swap */
5205         holder = who[a];
5206         who[a] = who[b];
5207         who[b] = holder;
5208 }
5209
5210
5211 /*
5212  * Check the status of "artifacts"
5213  */
5214 static void do_cmd_knowledge_artifacts(void)
5215 {
5216         ARTIFACT_IDX i;
5217         ARTIFACT_IDX k;
5218         POSITION x, y;
5219         int n = 0;
5220         ARTIFACT_IDX z;
5221         u16b why = 3;
5222         ARTIFACT_IDX *who;
5223         FILE *fff;
5224         GAME_TEXT file_name[1024];
5225         GAME_TEXT base_name[MAX_NLEN];
5226
5227         bool *okay;
5228
5229         /* Open a new file */
5230         fff = my_fopen_temp(file_name, 1024);
5231
5232         if (!fff) {
5233             msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
5234             msg_print(NULL);
5235             return;
5236         }
5237
5238         /* Allocate the "who" array */
5239         C_MAKE(who, max_a_idx, ARTIFACT_IDX);
5240
5241         /* Allocate the "okay" array */
5242         C_MAKE(okay, max_a_idx, bool);
5243
5244         /* Scan the artifacts */
5245         for (k = 0; k < max_a_idx; k++)
5246         {
5247                 artifact_type *a_ptr = &a_info[k];
5248
5249                 /* Default */
5250                 okay[k] = FALSE;
5251
5252                 /* Skip "empty" artifacts */
5253                 if (!a_ptr->name) continue;
5254
5255                 /* Skip "uncreated" artifacts */
5256                 if (!a_ptr->cur_num) continue;
5257
5258                 /* Assume okay */
5259                 okay[k] = TRUE;
5260         }
5261
5262         /* Check the dungeon */
5263         for (y = 0; y < current_floor_ptr->height; y++)
5264         {
5265                 for (x = 0; x < current_floor_ptr->width; x++)
5266                 {
5267                         grid_type *g_ptr = &current_floor_ptr->grid_array[y][x];
5268
5269                         OBJECT_IDX this_o_idx, next_o_idx = 0;
5270
5271                         /* Scan all objects in the grid */
5272                         for (this_o_idx = g_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx)
5273                         {
5274                                 object_type *o_ptr;
5275                                 o_ptr = &current_floor_ptr->o_list[this_o_idx];
5276                                 next_o_idx = o_ptr->next_o_idx;
5277
5278                                 /* Ignore non-artifacts */
5279                                 if (!object_is_fixed_artifact(o_ptr)) continue;
5280
5281                                 /* Ignore known items */
5282                                 if (object_is_known(o_ptr)) continue;
5283
5284                                 /* Note the artifact */
5285                                 okay[o_ptr->name1] = FALSE;
5286                         }
5287                 }
5288         }
5289
5290         /* Check the inventory and equipment */
5291         for (i = 0; i < INVEN_TOTAL; i++)
5292         {
5293                 object_type *o_ptr = &inventory[i];
5294
5295                 /* Ignore non-objects */
5296                 if (!o_ptr->k_idx) continue;
5297
5298                 /* Ignore non-artifacts */
5299                 if (!object_is_fixed_artifact(o_ptr)) continue;
5300
5301                 /* Ignore known items */
5302                 if (object_is_known(o_ptr)) continue;
5303
5304                 /* Note the artifact */
5305                 okay[o_ptr->name1] = FALSE;
5306         }
5307
5308         for (k = 0; k < max_a_idx; k++)
5309         {
5310                 if (okay[k]) who[n++] = k;
5311         }
5312
5313         /* Select the sort method */
5314         ang_sort_comp = ang_sort_art_comp;
5315         ang_sort_swap = ang_sort_art_swap;
5316
5317         /* Sort the array by dungeon depth of monsters */
5318         ang_sort(who, &why, n);
5319
5320         /* Scan the artifacts */
5321         for (k = 0; k < n; k++)
5322         {
5323                 artifact_type *a_ptr = &a_info[who[k]];
5324
5325                 /* Paranoia */
5326                 strcpy(base_name, _("未知の伝説のアイテム", "Unknown Artifact"));
5327
5328                 /* Obtain the base object type */
5329                 z = lookup_kind(a_ptr->tval, a_ptr->sval);
5330
5331                 /* Real object */
5332                 if (z)
5333                 {
5334                         object_type forge;
5335                         object_type *q_ptr;
5336                         q_ptr = &forge;
5337
5338                         /* Create fake object */
5339                         object_prep(q_ptr, z);
5340
5341                         /* Make it an artifact */
5342                         q_ptr->name1 = (byte)who[k];
5343
5344                         /* Display as if known */
5345                         q_ptr->ident |= IDENT_STORE;
5346
5347                         /* Describe the artifact */
5348                         object_desc(base_name, q_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY));
5349                 }
5350
5351                 /* Hack -- Build the artifact name */
5352                 fprintf(fff, _("     %s\n", "     The %s\n"), base_name);
5353         }
5354
5355         /* Free the "who" array */
5356         C_KILL(who, max_a_idx, ARTIFACT_IDX);
5357
5358         /* Free the "okay" array */
5359         C_KILL(okay, max_a_idx, bool);
5360         my_fclose(fff);
5361
5362         /* Display the file contents */
5363         show_file(TRUE, file_name, _("既知の伝説のアイテム", "Artifacts Seen"), 0, 0);
5364         fd_kill(file_name);
5365 }
5366
5367
5368 /*
5369  * Display known uniques
5370  * With "XTRA HACK UNIQHIST" (Originally from XAngband)
5371  */
5372 static void do_cmd_knowledge_uniques(void)
5373 {
5374         IDX i;
5375         int k, n = 0;
5376         u16b why = 2;
5377         IDX *who;
5378
5379         FILE *fff;
5380
5381         GAME_TEXT file_name[1024];
5382
5383         int n_alive[10];
5384         int n_alive_surface = 0;
5385         int n_alive_over100 = 0;
5386         int n_alive_total = 0;
5387         int max_lev = -1;
5388
5389         for (i = 0; i < 10; i++) n_alive[i] = 0;
5390
5391         /* Open a new file */
5392         fff = my_fopen_temp(file_name, 1024);
5393
5394         if (!fff)
5395         {
5396                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
5397                 msg_print(NULL);
5398                 return;
5399         }
5400
5401         /* Allocate the "who" array */
5402         C_MAKE(who, max_r_idx, MONRACE_IDX);
5403
5404         /* Scan the monsters */
5405         for (i = 1; i < max_r_idx; i++)
5406         {
5407                 monster_race *r_ptr = &r_info[i];
5408                 int          lev;
5409
5410                 if (!r_ptr->name) continue;
5411
5412                 /* Require unique monsters */
5413                 if (!(r_ptr->flags1 & RF1_UNIQUE)) continue;
5414
5415                 /* Only display "known" uniques */
5416                 if (!cheat_know && !r_ptr->r_sights) continue;
5417
5418                 /* Only print rarity <= 100 uniques */
5419                 if (!r_ptr->rarity || ((r_ptr->rarity > 100) && !(r_ptr->flags1 & RF1_QUESTOR))) continue;
5420
5421                 /* Only "alive" uniques */
5422                 if (r_ptr->max_num == 0) continue;
5423
5424                 if (r_ptr->level)
5425                 {
5426                         lev = (r_ptr->level - 1) / 10;
5427                         if (lev < 10)
5428                         {
5429                                 n_alive[lev]++;
5430                                 if (max_lev < lev) max_lev = lev;
5431                         }
5432                         else n_alive_over100++;
5433                 }
5434                 else n_alive_surface++;
5435
5436                 /* Collect "appropriate" monsters */
5437                 who[n++] = i;
5438         }
5439
5440         /* Select the sort method */
5441         ang_sort_comp = ang_sort_comp_hook;
5442         ang_sort_swap = ang_sort_swap_hook;
5443
5444         /* Sort the array by dungeon depth of monsters */
5445         ang_sort(who, &why, n);
5446
5447         if (n_alive_surface)
5448         {
5449                 fprintf(fff, _("     地上  生存: %3d体\n", "      Surface  alive: %3d\n"), n_alive_surface);
5450                 n_alive_total += n_alive_surface;
5451         }
5452         for (i = 0; i <= max_lev; i++)
5453         {
5454                 fprintf(fff, _("%3d-%3d階  生存: %3d体\n", "Level %3d-%3d  alive: %3d\n"), 1 + i * 10, 10 + i * 10, n_alive[i]);
5455                 n_alive_total += n_alive[i];
5456         }
5457         if (n_alive_over100)
5458         {
5459                 fprintf(fff, _("101-   階  生存: %3d体\n", "Level 101-     alive: %3d\n"), n_alive_over100);
5460                 n_alive_total += n_alive_over100;
5461         }
5462
5463         if (n_alive_total)
5464         {
5465                 fputs(_("---------  -----------\n", "-------------  ----------\n"), fff);
5466                 fprintf(fff, _("     合計  生存: %3d体\n\n", "        Total  alive: %3d\n\n"), n_alive_total);
5467         }
5468         else
5469         {
5470                 fputs(_("現在は既知の生存ユニークはいません。\n", "No known uniques alive.\n"), fff);
5471         }
5472
5473         /* Scan the monster races */
5474         for (k = 0; k < n; k++)
5475         {
5476                 monster_race *r_ptr = &r_info[who[k]];
5477
5478                 fprintf(fff, _("     %s (レベル%d)\n", "     %s (level %d)\n"), r_name + r_ptr->name, (int)r_ptr->level);
5479         }
5480
5481         /* Free the "who" array */
5482         C_KILL(who, max_r_idx, s16b);
5483         my_fclose(fff);
5484
5485         /* Display the file contents */
5486         show_file(TRUE, file_name, _("まだ生きているユニーク・モンスター", "Alive Uniques"), 0, 0);
5487         fd_kill(file_name);
5488 }
5489
5490
5491 /*
5492  * Display weapon-exp
5493  */
5494 static void do_cmd_knowledge_weapon_exp(void)
5495 {
5496         int i, num;
5497         SUB_EXP weapon_exp;
5498         KIND_OBJECT_IDX j;
5499
5500         FILE *fff;
5501
5502         GAME_TEXT file_name[1024];
5503         char tmp[30];
5504
5505         /* Open a new file */
5506         fff = my_fopen_temp(file_name, 1024);
5507         if (!fff) {
5508             msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
5509             msg_print(NULL);
5510             return;
5511         }
5512
5513         for (i = 0; i < 5; i++)
5514         {
5515                 for (num = 0; num < 64; num++)
5516                 {
5517                         for (j = 0; j < max_k_idx; j++)
5518                         {
5519                                 object_kind *k_ptr = &k_info[j];
5520
5521                                 if ((k_ptr->tval == TV_SWORD - i) && (k_ptr->sval == num))
5522                                 {
5523                                         if ((k_ptr->tval == TV_BOW) && (k_ptr->sval == SV_CRIMSON || k_ptr->sval == SV_HARP)) continue;
5524
5525                                         weapon_exp = p_ptr->weapon_exp[4 - i][num];
5526                                         strip_name(tmp, j);
5527                                         fprintf(fff, "%-25s ", tmp);
5528                                         if (weapon_exp >= s_info[p_ptr->pclass].w_max[4 - i][num]) fprintf(fff, "!");
5529                                         else fprintf(fff, " ");
5530                                         fprintf(fff, "%s", exp_level_str[weapon_exp_level(weapon_exp)]);
5531                                         if (cheat_xtra) fprintf(fff, " %d", weapon_exp);
5532                                         fprintf(fff, "\n");
5533                                         break;
5534                                 }
5535                         }
5536                 }
5537         }
5538         my_fclose(fff);
5539
5540         /* Display the file contents */
5541         show_file(TRUE, file_name, _("武器の経験値", "Weapon Proficiency"), 0, 0);
5542         fd_kill(file_name);
5543 }
5544
5545
5546 /*!
5547  * @brief 魔法の経験値を表示するコマンドのメインルーチン
5548  * Display spell-exp
5549  * @return なし
5550  */
5551 static void do_cmd_knowledge_spell_exp(void)
5552 {
5553         SPELL_IDX i = 0;
5554         SUB_EXP spell_exp;
5555         int exp_level;
5556
5557         FILE *fff;
5558         const magic_type *s_ptr;
5559
5560         GAME_TEXT file_name[1024];
5561
5562         /* Open a new file */
5563         fff = my_fopen_temp(file_name, 1024);
5564         if (!fff) {
5565             msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
5566             msg_print(NULL);
5567             return;
5568         }
5569
5570         if (p_ptr->realm1 != REALM_NONE)
5571         {
5572                 fprintf(fff, _("%sの魔法書\n", "%s Spellbook\n"), realm_names[p_ptr->realm1]);
5573                 for (i = 0; i < 32; i++)
5574                 {
5575                         if (!is_magic(p_ptr->realm1))
5576                         {
5577                                 s_ptr = &technic_info[p_ptr->realm1 - MIN_TECHNIC][i];
5578                         }
5579                         else
5580                         {
5581                                 s_ptr = &mp_ptr->info[p_ptr->realm1 - 1][i];
5582                         }
5583                         if (s_ptr->slevel >= 99) continue;
5584                         spell_exp = p_ptr->spell_exp[i];
5585                         exp_level = spell_exp_level(spell_exp);
5586                         fprintf(fff, "%-25s ", do_spell(p_ptr->realm1, i, SPELL_NAME));
5587                         if (p_ptr->realm1 == REALM_HISSATSU)
5588                                 fprintf(fff, "[--]");
5589                         else
5590                         {
5591                                 if (exp_level >= EXP_LEVEL_MASTER) fprintf(fff, "!");
5592                                 else fprintf(fff, " ");
5593                                 fprintf(fff, "%s", exp_level_str[exp_level]);
5594                         }
5595                         if (cheat_xtra) fprintf(fff, " %d", spell_exp);
5596                         fprintf(fff, "\n");
5597                 }
5598         }
5599
5600         if (p_ptr->realm2 != REALM_NONE)
5601         {
5602                 fprintf(fff, _("%sの魔法書\n", "\n%s Spellbook\n"), realm_names[p_ptr->realm2]);
5603                 for (i = 0; i < 32; i++)
5604                 {
5605                         if (!is_magic(p_ptr->realm1))
5606                         {
5607                                 s_ptr = &technic_info[p_ptr->realm2 - MIN_TECHNIC][i];
5608                         }
5609                         else
5610                         {
5611                                 s_ptr = &mp_ptr->info[p_ptr->realm2 - 1][i];
5612                         }
5613                         if (s_ptr->slevel >= 99) continue;
5614
5615                         spell_exp = p_ptr->spell_exp[i + 32];
5616                         exp_level = spell_exp_level(spell_exp);
5617                         fprintf(fff, "%-25s ", do_spell(p_ptr->realm2, i, SPELL_NAME));
5618                         if (exp_level >= EXP_LEVEL_EXPERT) fprintf(fff, "!");
5619                         else fprintf(fff, " ");
5620                         fprintf(fff, "%s", exp_level_str[exp_level]);
5621                         if (cheat_xtra) fprintf(fff, " %d", spell_exp);
5622                         fprintf(fff, "\n");
5623                 }
5624         }
5625         my_fclose(fff);
5626
5627         /* Display the file contents */
5628         show_file(TRUE, file_name, _("魔法の経験値", "Spell Proficiency"), 0, 0);
5629         fd_kill(file_name);
5630 }
5631
5632
5633 /*!
5634  * @brief スキル情報を表示するコマンドのメインルーチン /
5635  * Display skill-exp
5636  * @return なし
5637  */
5638 static void do_cmd_knowledge_skill_exp(void)
5639 {
5640         int i = 0, skill_exp;
5641
5642         FILE *fff;
5643
5644         char file_name[1024];
5645         char skill_name[GINOU_TEMPMAX][20] =
5646         {
5647                 _("マーシャルアーツ", "Martial Arts    "),
5648                 _("二刀流          ", "Dual Wielding   "), 
5649                 _("乗馬            ", "Riding          "),
5650                 _("盾              ", "Shield          ")
5651         };
5652
5653         /* Open a new file */
5654         fff = my_fopen_temp(file_name, 1024);
5655         if (!fff) {
5656             msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
5657             msg_print(NULL);
5658             return;
5659         }
5660
5661         for (i = 0; i < GINOU_TEMPMAX; i++)
5662         {
5663                 skill_exp = p_ptr->skill_exp[i];
5664                 fprintf(fff, "%-20s ", skill_name[i]);
5665                 if (skill_exp >= s_info[p_ptr->pclass].s_max[i]) fprintf(fff, "!");
5666                 else fprintf(fff, " ");
5667                 fprintf(fff, "%s", exp_level_str[(i == GINOU_RIDING) ? riding_exp_level(skill_exp) : weapon_exp_level(skill_exp)]);
5668                 if (cheat_xtra) fprintf(fff, " %d", skill_exp);
5669                 fprintf(fff, "\n");
5670         }
5671         my_fclose(fff);
5672
5673         /* Display the file contents */
5674         show_file(TRUE, file_name, _("技能の経験値", "Miscellaneous Proficiency"), 0, 0);
5675         fd_kill(file_name);
5676 }
5677
5678
5679 /*!
5680  * @brief 英単語、句、説を複数形を変換する / Pluralize a monster name
5681  * @param Name 変換したい文字列の参照ポインタ
5682  * @return なし
5683  */
5684 void plural_aux(char *Name)
5685 {
5686         int NameLen = strlen(Name);
5687
5688         if (my_strstr(Name, "Disembodied hand"))
5689         {
5690                 strcpy(Name, "Disembodied hands that strangled people");
5691         }
5692         else if (my_strstr(Name, "Colour out of space"))
5693         {
5694                 strcpy(Name, "Colours out of space");
5695         }
5696         else if (my_strstr(Name, "stairway to hell"))
5697         {
5698                 strcpy(Name, "stairways to hell");
5699         }
5700         else if (my_strstr(Name, "Dweller on the threshold"))
5701         {
5702                 strcpy(Name, "Dwellers on the threshold");
5703         }
5704         else if (my_strstr(Name, " of "))
5705         {
5706                 concptr aider = my_strstr(Name, " of ");
5707                 char dummy[80];
5708                 int i = 0;
5709                 concptr ctr = Name;
5710
5711                 while (ctr < aider)
5712                 {
5713                         dummy[i] = *ctr;
5714                         ctr++; i++;
5715                 }
5716
5717                 if (dummy[i-1] == 's')
5718                 {
5719                         strcpy(&(dummy[i]), "es");
5720                         i++;
5721                 }
5722                 else
5723                 {
5724                         strcpy(&(dummy[i]), "s");
5725                 }
5726
5727                 strcpy(&(dummy[i+1]), aider);
5728                 strcpy(Name, dummy);
5729         }
5730         else if (my_strstr(Name, "coins"))
5731         {
5732                 char dummy[80];
5733                 strcpy(dummy, "piles of ");
5734                 strcat(dummy, Name);
5735                 strcpy(Name, dummy);
5736                 return;
5737         }
5738         else if (my_strstr(Name, "Manes"))
5739         {
5740                 return;
5741         }
5742         else if (streq(&(Name[NameLen - 2]), "ey"))
5743         {
5744                 strcpy(&(Name[NameLen - 2]), "eys");
5745         }
5746         else if (Name[NameLen - 1] == 'y')
5747         {
5748                 strcpy(&(Name[NameLen - 1]), "ies");
5749         }
5750         else if (streq(&(Name[NameLen - 4]), "ouse"))
5751         {
5752                 strcpy(&(Name[NameLen - 4]), "ice");
5753         }
5754         else if (streq(&(Name[NameLen - 2]), "us"))
5755         {
5756                 strcpy(&(Name[NameLen - 2]), "i");
5757         }
5758         else if (streq(&(Name[NameLen - 6]), "kelman"))
5759         {
5760                 strcpy(&(Name[NameLen - 6]), "kelmen");
5761         }
5762         else if (streq(&(Name[NameLen - 8]), "wordsman"))
5763         {
5764                 strcpy(&(Name[NameLen - 8]), "wordsmen");
5765         }
5766         else if (streq(&(Name[NameLen - 7]), "oodsman"))
5767         {
5768                 strcpy(&(Name[NameLen - 7]), "oodsmen");
5769         }
5770         else if (streq(&(Name[NameLen - 7]), "eastman"))
5771         {
5772                 strcpy(&(Name[NameLen - 7]), "eastmen");
5773         }
5774         else if (streq(&(Name[NameLen - 8]), "izardman"))
5775         {
5776                 strcpy(&(Name[NameLen - 8]), "izardmen");
5777         }
5778         else if (streq(&(Name[NameLen - 5]), "geist"))
5779         {
5780                 strcpy(&(Name[NameLen - 5]), "geister");
5781         }
5782         else if (streq(&(Name[NameLen - 2]), "ex"))
5783         {
5784                 strcpy(&(Name[NameLen - 2]), "ices");
5785         }
5786         else if (streq(&(Name[NameLen - 2]), "lf"))
5787         {
5788                 strcpy(&(Name[NameLen - 2]), "lves");
5789         }
5790         else if (suffix(Name, "ch") ||
5791                  suffix(Name, "sh") ||
5792                          suffix(Name, "nx") ||
5793                          suffix(Name, "s") ||
5794                          suffix(Name, "o"))
5795         {
5796                 strcpy(&(Name[NameLen]), "es");
5797         }
5798         else
5799         {
5800                 strcpy(&(Name[NameLen]), "s");
5801         }
5802 }
5803
5804 /*!
5805  * @brief 現在のペットを表示するコマンドのメインルーチン /
5806  * Display current pets
5807  * @return なし
5808  */
5809 static void do_cmd_knowledge_pets(void)
5810 {
5811         int             i;
5812         FILE            *fff;
5813         monster_type    *m_ptr;
5814         GAME_TEXT pet_name[MAX_NLEN];
5815         int             t_friends = 0;
5816         int             show_upkeep = 0;
5817         GAME_TEXT file_name[1024];
5818
5819
5820         /* Open a new file */
5821         fff = my_fopen_temp(file_name, 1024);
5822         if (!fff) {
5823             msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
5824             msg_print(NULL);
5825             return;
5826         }
5827
5828         /* Process the monsters (backwards) */
5829         for (i = m_max - 1; i >= 1; i--)
5830         {
5831                 /* Access the monster */
5832                 m_ptr = &current_floor_ptr->m_list[i];
5833
5834                 /* Ignore "dead" monsters */
5835                 if (!m_ptr->r_idx) continue;
5836
5837                 /* Calculate "upkeep" for pets */
5838                 if (is_pet(m_ptr))
5839                 {
5840                         t_friends++;
5841                         monster_desc(pet_name, m_ptr, MD_ASSUME_VISIBLE | MD_INDEF_VISIBLE);
5842                         fprintf(fff, "%s (%s)\n", pet_name, look_mon_desc(m_ptr, 0x00));
5843                 }
5844         }
5845
5846         show_upkeep = calculate_upkeep();
5847
5848         fprintf(fff, "----------------------------------------------\n");
5849 #ifdef JP
5850         fprintf(fff, "    合計: %d 体のペット\n", t_friends);
5851 #else
5852         fprintf(fff, "   Total: %d pet%s.\n", t_friends, (t_friends == 1 ? "" : "s"));
5853 #endif
5854         fprintf(fff, _(" 維持コスト: %d%% MP\n", "   Upkeep: %d%% mana.\n"), show_upkeep);
5855
5856
5857         my_fclose(fff);
5858
5859         /* Display the file contents */
5860         show_file(TRUE, file_name, _("現在のペット", "Current Pets"), 0, 0);
5861         fd_kill(file_name);
5862 }
5863
5864
5865 /*!
5866  * @brief 現在のペットを表示するコマンドのメインルーチン /
5867  * Total kill count
5868  * @return なし
5869  * @note the player ghosts are ignored.  
5870  */
5871 static void do_cmd_knowledge_kill_count(void)
5872 {
5873         MONRACE_IDX i;
5874         int k, n = 0;
5875         u16b why = 2;
5876         MONRACE_IDX *who;
5877         FILE *fff;
5878         GAME_TEXT file_name[1024];
5879
5880         s32b Total = 0;
5881
5882
5883         /* Open a new file */
5884         fff = my_fopen_temp(file_name, 1024);
5885
5886         if (!fff) {
5887                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
5888                 msg_print(NULL);
5889                 return;
5890         }
5891
5892         /* Allocate the "who" array */
5893         C_MAKE(who, max_r_idx, MONRACE_IDX);
5894
5895         {
5896                 /* Monsters slain */
5897                 int kk;
5898
5899                 for (kk = 1; kk < max_r_idx; kk++)
5900                 {
5901                         monster_race *r_ptr = &r_info[kk];
5902
5903                         if (r_ptr->flags1 & (RF1_UNIQUE))
5904                         {
5905                                 bool dead = (r_ptr->max_num == 0);
5906
5907                                 if (dead)
5908                                 {
5909                                         Total++;
5910                                 }
5911                         }
5912                         else
5913                         {
5914                                 MONSTER_NUMBER This = r_ptr->r_pkills;
5915
5916                                 if (This > 0)
5917                                 {
5918                                         Total += This;
5919                                 }
5920                         }
5921                 }
5922
5923                 if (Total < 1)
5924                         fprintf(fff,_("あなたはまだ敵を倒していない。\n\n", "You have defeated no enemies yet.\n\n"));
5925                 else
5926 #ifdef JP
5927                         fprintf(fff,"あなたは%ld体の敵を倒している。\n\n", (long int)Total);
5928 #else
5929                         fprintf(fff,"You have defeated %ld %s.\n\n", (long int)Total, (Total == 1) ? "enemy" : "enemies");
5930 #endif
5931         }
5932
5933         Total = 0;
5934
5935         /* Scan the monsters */
5936         for (i = 1; i < max_r_idx; i++)
5937         {
5938                 monster_race *r_ptr = &r_info[i];
5939
5940                 /* Use that monster */
5941                 if (r_ptr->name) who[n++] = i;
5942         }
5943
5944         /* Select the sort method */
5945         ang_sort_comp = ang_sort_comp_hook;
5946         ang_sort_swap = ang_sort_swap_hook;
5947
5948         /* Sort the array by dungeon depth of monsters */
5949         ang_sort(who, &why, n);
5950
5951         /* Scan the monster races */
5952         for (k = 0; k < n; k++)
5953         {
5954                 monster_race *r_ptr = &r_info[who[k]];
5955
5956                 if (r_ptr->flags1 & (RF1_UNIQUE))
5957                 {
5958                         bool dead = (r_ptr->max_num == 0);
5959
5960                         if (dead)
5961                         {
5962                                 fprintf(fff, "     %s\n", (r_name + r_ptr->name));
5963                                 Total++;
5964                         }
5965                 }
5966                 else
5967                 {
5968                         MONSTER_NUMBER This = r_ptr->r_pkills;
5969
5970                         if (This > 0)
5971                         {
5972 #ifdef JP
5973                                 /* p,tは人と数える by ita */
5974                                 if (my_strchr("pt", r_ptr->d_char))
5975                                         fprintf(fff, "     %3d 人の %s\n", (int)This, r_name + r_ptr->name);
5976                                 else
5977                                         fprintf(fff, "     %3d 体の %s\n", (int)This, r_name + r_ptr->name);
5978 #else
5979                                 if (This < 2)
5980                                 {
5981                                         if (my_strstr(r_name + r_ptr->name, "coins"))
5982                                         {
5983                                                 fprintf(fff, "     1 pile of %s\n", (r_name + r_ptr->name));
5984                                         }
5985                                         else
5986                                         {
5987                                                 fprintf(fff, "     1 %s\n", (r_name + r_ptr->name));
5988                                         }
5989                                 }
5990                                 else
5991                                 {
5992                                         char ToPlural[80];
5993                                         strcpy(ToPlural, (r_name + r_ptr->name));
5994                                         plural_aux(ToPlural);
5995                                         fprintf(fff, "     %d %s\n", This, ToPlural);
5996                                 }
5997 #endif
5998
5999
6000                                 Total += This;
6001                         }
6002                 }
6003         }
6004
6005         fprintf(fff,"----------------------------------------------\n");
6006 #ifdef JP
6007         fprintf(fff,"    合計: %lu 体を倒した。\n", (unsigned long int)Total);
6008 #else
6009         fprintf(fff,"   Total: %lu creature%s killed.\n", (unsigned long int)Total, (Total == 1 ? "" : "s"));
6010 #endif
6011
6012
6013         /* Free the "who" array */
6014         C_KILL(who, max_r_idx, s16b);
6015         my_fclose(fff);
6016
6017         /* Display the file contents */
6018         show_file(TRUE, file_name, _("倒した敵の数", "Kill Count"), 0, 0);
6019         fd_kill(file_name);
6020 }
6021
6022
6023 /*!
6024  * @brief モンスター情報リスト中のグループを表示する /
6025  * Display the object groups.
6026  * @param col 開始行
6027  * @param row 開始列
6028  * @param wid 表示文字数幅
6029  * @param per_page リストの表示行
6030  * @param grp_idx グループのID配列
6031  * @param group_text グループ名の文字列配列
6032  * @param grp_cur 現在の選択ID
6033  * @param grp_top 現在の選択リスト最上部ID
6034  * @return なし
6035  */
6036 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)
6037 {
6038         int i;
6039
6040         /* Display lines until done */
6041         for (i = 0; i < per_page && (grp_idx[i] >= 0); i++)
6042         {
6043                 /* Get the group index */
6044                 int grp = grp_idx[grp_top + i];
6045
6046                 /* Choose a color */
6047                 TERM_COLOR attr = (grp_top + i == grp_cur) ? TERM_L_BLUE : TERM_WHITE;
6048
6049                 /* Erase the entire line */
6050                 Term_erase(col, row + i, wid);
6051
6052                 /* Display the group label */
6053                 c_put_str(attr, group_text[grp], row + i, col);
6054         }
6055 }
6056
6057
6058 /* 
6059  * Move the cursor in a browser window 
6060  */
6061 static void browser_cursor(char ch, int *column, IDX *grp_cur, int grp_cnt, 
6062                                                    IDX *list_cur, int list_cnt)
6063 {
6064         int d;
6065         int col = *column;
6066         IDX grp = *grp_cur;
6067         IDX list = *list_cur;
6068
6069         /* Extract direction */
6070         if (ch == ' ')
6071         {
6072                 /* Hack -- scroll up full screen */
6073                 d = 3;
6074         }
6075         else if (ch == '-')
6076         {
6077                 /* Hack -- scroll down full screen */
6078                 d = 9;
6079         }
6080         else
6081         {
6082                 d = get_keymap_dir(ch);
6083         }
6084
6085         if (!d) return;
6086
6087         /* Diagonals - hack */
6088         if ((ddx[d] > 0) && ddy[d])
6089         {
6090                 int browser_rows;
6091                 int wid, hgt;
6092
6093                 Term_get_size(&wid, &hgt);
6094
6095                 browser_rows = hgt - 8;
6096
6097                 /* Browse group list */
6098                 if (!col)
6099                 {
6100                         int old_grp = grp;
6101
6102                         /* Move up or down */
6103                         grp += ddy[d] * (browser_rows - 1);
6104
6105                         /* Verify */
6106                         if (grp >= grp_cnt)     grp = grp_cnt - 1;
6107                         if (grp < 0) grp = 0;
6108                         if (grp != old_grp)     list = 0;
6109                 }
6110
6111                 /* Browse sub-list list */
6112                 else
6113                 {
6114                         /* Move up or down */
6115                         list += ddy[d] * browser_rows;
6116
6117                         /* Verify */
6118                         if (list >= list_cnt) list = list_cnt - 1;
6119                         if (list < 0) list = 0;
6120                 }
6121
6122                 (*grp_cur) = grp;
6123                 (*list_cur) = list;
6124
6125                 return;
6126         }
6127
6128         if (ddx[d])
6129         {
6130                 col += ddx[d];
6131                 if (col < 0) col = 0;
6132                 if (col > 1) col = 1;
6133
6134                 (*column) = col;
6135
6136                 return;
6137         }
6138
6139         /* Browse group list */
6140         if (!col)
6141         {
6142                 int old_grp = grp;
6143
6144                 /* Move up or down */
6145                 grp += (IDX)ddy[d];
6146
6147                 /* Verify */
6148                 if (grp >= grp_cnt)     grp = grp_cnt - 1;
6149                 if (grp < 0) grp = 0;
6150                 if (grp != old_grp)     list = 0;
6151         }
6152
6153         /* Browse sub-list list */
6154         else
6155         {
6156                 /* Move up or down */
6157                 list += (IDX)ddy[d];
6158
6159                 /* Verify */
6160                 if (list >= list_cnt) list = list_cnt - 1;
6161                 if (list < 0) list = 0;
6162         }
6163
6164         (*grp_cur) = grp;
6165         (*list_cur) = list;
6166 }
6167
6168
6169 /*
6170  * Display visuals.
6171  */
6172 static void display_visual_list(int col, int row, int height, int width, TERM_COLOR attr_top, byte char_left)
6173 {
6174         int i, j;
6175
6176         /* Clear the display lines */
6177         for (i = 0; i < height; i++)
6178         {
6179                 Term_erase(col, row + i, width);
6180         }
6181
6182         /* Bigtile mode uses double width */
6183         if (use_bigtile) width /= 2;
6184
6185         /* Display lines until done */
6186         for (i = 0; i < height; i++)
6187         {
6188                 /* Display columns until done */
6189                 for (j = 0; j < width; j++)
6190                 {
6191                         TERM_COLOR a, ia;
6192                         SYMBOL_CODE c, ic;
6193                         TERM_LEN x = col + j;
6194                         TERM_LEN y = row + i;
6195
6196                         /* Bigtile mode uses double width */
6197                         if (use_bigtile) x += j;
6198
6199                         ia = attr_top + i;
6200                         ic = char_left + j;
6201
6202                         /* Ignore illegal characters */
6203                         if (ia > 0x7f || ic > 0xff || ic < ' ' ||
6204                             (!use_graphics && ic > 0x7f))
6205                                 continue;
6206
6207                         a = ia;
6208                         c = ic;
6209
6210                         /* Force correct code for both ASCII character and tile */
6211                         if (c & 0x80) a |= 0x80;
6212
6213                         /* Display symbol */
6214                         Term_queue_bigchar(x, y, a, c, 0, 0);
6215                 }
6216         }
6217 }
6218
6219
6220 /*
6221  * Place the cursor at the collect position for visual mode
6222  */
6223 static void place_visual_list_cursor(TERM_LEN col, TERM_LEN row, TERM_COLOR a, byte c, TERM_COLOR attr_top, byte char_left)
6224 {
6225         int i = (a & 0x7f) - attr_top;
6226         int j = c - char_left;
6227
6228         TERM_LEN x = col + j;
6229         TERM_LEN y = row + i;
6230
6231         /* Bigtile mode uses double width */
6232         if (use_bigtile) x += j;
6233
6234         /* Place the cursor */
6235         Term_gotoxy(x, y);
6236 }
6237
6238
6239 /*
6240  *  Clipboard variables for copy&paste in visual mode
6241  */
6242 static TERM_COLOR attr_idx = 0;
6243 static SYMBOL_CODE char_idx = 0;
6244
6245 /* Hack -- for feature lighting */
6246 static TERM_COLOR attr_idx_feat[F_LIT_MAX];
6247 static SYMBOL_CODE char_idx_feat[F_LIT_MAX];
6248
6249 /*
6250  *  Do visual mode command -- Change symbols
6251  */
6252 static bool visual_mode_command(char ch, bool *visual_list_ptr,
6253                                 int height, int width,
6254                                 TERM_COLOR *attr_top_ptr, byte *char_left_ptr,
6255                                 TERM_COLOR *cur_attr_ptr, SYMBOL_CODE *cur_char_ptr, bool *need_redraw)
6256 {
6257         static TERM_COLOR attr_old = 0;
6258         static SYMBOL_CODE char_old = 0;
6259
6260         switch (ch)
6261         {
6262         case ESCAPE:
6263                 if (*visual_list_ptr)
6264                 {
6265                         /* Cancel change */
6266                         *cur_attr_ptr = attr_old;
6267                         *cur_char_ptr = char_old;
6268                         *visual_list_ptr = FALSE;
6269
6270                         return TRUE;
6271                 }
6272                 break;
6273
6274         case '\n':
6275         case '\r':
6276                 if (*visual_list_ptr)
6277                 {
6278                         /* Accept change */
6279                         *visual_list_ptr = FALSE;
6280                         *need_redraw = TRUE;
6281
6282                         return TRUE;
6283                 }
6284                 break;
6285
6286         case 'V':
6287         case 'v':
6288                 if (!*visual_list_ptr)
6289                 {
6290                         *visual_list_ptr = TRUE;
6291
6292                         *attr_top_ptr = MAX(0, (*cur_attr_ptr & 0x7f) - 5);
6293                         *char_left_ptr = MAX(0, *cur_char_ptr - 10);
6294
6295                         attr_old = *cur_attr_ptr;
6296                         char_old = *cur_char_ptr;
6297
6298                         return TRUE;
6299                 }
6300                 break;
6301
6302         case 'C':
6303         case 'c':
6304                 {
6305                         int i;
6306
6307                         /* Set the visual */
6308                         attr_idx = *cur_attr_ptr;
6309                         char_idx = *cur_char_ptr;
6310
6311                         /* Hack -- for feature lighting */
6312                         for (i = 0; i < F_LIT_MAX; i++)
6313                         {
6314                                 attr_idx_feat[i] = 0;
6315                                 char_idx_feat[i] = 0;
6316                         }
6317                 }
6318                 return TRUE;
6319
6320         case 'P':
6321         case 'p':
6322                 if (attr_idx || (!(char_idx & 0x80) && char_idx)) /* Allow TERM_DARK text */
6323                 {
6324                         /* Set the char */
6325                         *cur_attr_ptr = attr_idx;
6326                         *attr_top_ptr = MAX(0, (*cur_attr_ptr & 0x7f) - 5);
6327                         if (!*visual_list_ptr) *need_redraw = TRUE;
6328                 }
6329
6330                 if (char_idx)
6331                 {
6332                         /* Set the char */
6333                         *cur_char_ptr = char_idx;
6334                         *char_left_ptr = MAX(0, *cur_char_ptr - 10);
6335                         if (!*visual_list_ptr) *need_redraw = TRUE;
6336                 }
6337
6338                 return TRUE;
6339
6340         default:
6341                 if (*visual_list_ptr)
6342                 {
6343                         int eff_width;
6344                         int d = get_keymap_dir(ch);
6345                         TERM_COLOR a = (*cur_attr_ptr & 0x7f);
6346                         SYMBOL_CODE c = *cur_char_ptr;
6347
6348                         if (use_bigtile) eff_width = width / 2;
6349                         else eff_width = width;
6350
6351                         /* Restrict direction */
6352                         if ((a == 0) && (ddy[d] < 0)) d = 0;
6353                         if ((c == 0) && (ddx[d] < 0)) d = 0;
6354                         if ((a == 0x7f) && (ddy[d] > 0)) d = 0;
6355                         if ((c == 0xff) && (ddx[d] > 0)) d = 0;
6356
6357                         a += (TERM_COLOR)ddy[d];
6358                         c += (SYMBOL_CODE)ddx[d];
6359
6360                         /* Force correct code for both ASCII character and tile */
6361                         if (c & 0x80) a |= 0x80;
6362
6363                         /* Set the visual */
6364                         *cur_attr_ptr = a;
6365                         *cur_char_ptr = c;
6366
6367
6368                         /* Move the frame */
6369                         if ((ddx[d] < 0) && *char_left_ptr > MAX(0, (int)c - 10)) (*char_left_ptr)--;
6370                         if ((ddx[d] > 0) && *char_left_ptr + eff_width < MIN(0xff, (int)c + 10)) (*char_left_ptr)++;
6371                         if ((ddy[d] < 0) && *attr_top_ptr > MAX(0, (int)(a & 0x7f) - 4)) (*attr_top_ptr)--;
6372                         if ((ddy[d] > 0) && *attr_top_ptr + height < MIN(0x7f, (a & 0x7f) + 4)) (*attr_top_ptr)++;
6373                         return TRUE;
6374                 }
6375                 break;
6376         }
6377
6378         /* Visual mode command is not used */
6379         return FALSE;
6380 }
6381
6382
6383 /*
6384  * Display the monsters in a group.
6385  */
6386 static void display_monster_list(int col, int row, int per_page, s16b mon_idx[],
6387         int mon_cur, int mon_top, bool visual_only)
6388 {
6389         int i;
6390
6391         /* Display lines until done */
6392         for (i = 0; i < per_page && (mon_idx[mon_top + i] >= 0); i++)
6393         {
6394                 TERM_COLOR attr;
6395
6396                 /* Get the race index */
6397                 MONRACE_IDX r_idx = mon_idx[mon_top + i] ;
6398
6399                 /* Access the race */
6400                 monster_race *r_ptr = &r_info[r_idx];
6401
6402                 /* Choose a color */
6403                 attr = ((i + mon_top == mon_cur) ? TERM_L_BLUE : TERM_WHITE);
6404
6405                 /* Display the name */
6406                 c_prt(attr, (r_name + r_ptr->name), row + i, col);
6407
6408                 /* Hack -- visual_list mode */
6409                 if (per_page == 1)
6410                 {
6411                         c_prt(attr, format("%02x/%02x", r_ptr->x_attr, r_ptr->x_char), row + i, (p_ptr->wizard || visual_only) ? 56 : 61);
6412                 }
6413                 if (p_ptr->wizard || visual_only)
6414                 {
6415                         c_prt(attr, format("%d", r_idx), row + i, 62);
6416                 }
6417
6418                 /* Erase chars before overwritten by the race letter */
6419                 Term_erase(69, row + i, 255);
6420
6421                 /* Display symbol */
6422                 Term_queue_bigchar(use_bigtile ? 69 : 70, row + i, r_ptr->x_attr, r_ptr->x_char, 0, 0);
6423
6424                 if (!visual_only)
6425                 {
6426                         /* Display kills */
6427                         if (!(r_ptr->flags1 & RF1_UNIQUE)) 
6428                                 put_str(format("%5d", r_ptr->r_pkills), row + i, 73);
6429                         else 
6430                                 c_put_str((r_ptr->max_num == 0 ? TERM_L_DARK : TERM_WHITE), 
6431                                                   (r_ptr->max_num == 0 ? _("死亡", " dead") : _("生存", "alive")), row + i, 74);
6432                 }
6433         }
6434
6435         /* Clear remaining lines */
6436         for (; i < per_page; i++)
6437         {
6438                 Term_erase(col, row + i, 255);
6439         }
6440 }
6441
6442
6443 /*
6444  * Display known monsters.
6445  */
6446 static void do_cmd_knowledge_monsters(bool *need_redraw, bool visual_only, IDX direct_r_idx)
6447 {
6448         IDX i;
6449         int len, max;
6450         IDX grp_cur, grp_top, old_grp_cur;
6451         IDX mon_cur, mon_top;
6452         IDX grp_cnt, grp_idx[100];
6453         IDX mon_cnt;
6454         IDX *mon_idx;
6455
6456         int column = 0;
6457         bool flag;
6458         bool redraw;
6459
6460         bool visual_list = FALSE;
6461         TERM_COLOR attr_top = 0;
6462         byte char_left = 0;
6463
6464         int browser_rows;
6465         TERM_LEN wid, hgt;
6466
6467         BIT_FLAGS8 mode;
6468
6469         Term_get_size(&wid, &hgt);
6470
6471         browser_rows = hgt - 8;
6472
6473         /* Allocate the "mon_idx" array */
6474         C_MAKE(mon_idx, max_r_idx, MONRACE_IDX);
6475
6476         max = 0;
6477         grp_cnt = 0;
6478
6479         if (direct_r_idx < 0)
6480         {
6481                 mode = visual_only ? 0x03 : 0x01;
6482
6483                 /* Check every group */
6484                 for (i = 0; monster_group_text[i] != NULL; i++)
6485                 {
6486                         /* Measure the label */
6487                         len = strlen(monster_group_text[i]);
6488
6489                         /* Save the maximum length */
6490                         if (len > max) max = len;
6491
6492                         /* See if any monsters are known */
6493                         if ((monster_group_char[i] == ((char *) -1L)) || collect_monsters(i, mon_idx, mode))
6494                         {
6495                                 /* Build a list of groups with known monsters */
6496                                 grp_idx[grp_cnt++] = i;
6497                         }
6498                 }
6499
6500                 mon_cnt = 0;
6501         }
6502         else
6503         {
6504                 mon_idx[0] = direct_r_idx;
6505                 mon_cnt = 1;
6506
6507                 /* Terminate the list */
6508                 mon_idx[1] = -1;
6509
6510                 (void)visual_mode_command('v', &visual_list, browser_rows - 1, wid - (max + 3),
6511                         &attr_top, &char_left, &r_info[direct_r_idx].x_attr, &r_info[direct_r_idx].x_char, need_redraw);
6512         }
6513
6514         /* Terminate the list */
6515         grp_idx[grp_cnt] = -1;
6516
6517         old_grp_cur = -1;
6518         grp_cur = grp_top = 0;
6519         mon_cur = mon_top = 0;
6520
6521         flag = FALSE;
6522         redraw = TRUE;
6523
6524         mode = visual_only ? 0x02 : 0x00;
6525
6526         while (!flag)
6527         {
6528                 char ch;
6529                 monster_race *r_ptr;
6530
6531                 if (redraw)
6532                 {
6533                         clear_from(0);
6534                         prt(format(_("%s - モンスター", "%s - monsters"), !visual_only ? _("知識", "Knowledge") : _("表示", "Visuals")), 2, 0);
6535                         if (direct_r_idx < 0) prt(_("グループ", "Group"), 4, 0);
6536                         prt(_("名前", "Name"), 4, max + 3);
6537                         if (p_ptr->wizard || visual_only) prt("Idx", 4, 62);
6538                         prt(_("文字", "Sym"), 4, 67);
6539                         if (!visual_only) prt(_("殺害数", "Kills"), 4, 72);
6540
6541                         for (i = 0; i < 78; i++)
6542                         {
6543                                 Term_putch(i, 5, TERM_WHITE, '=');
6544                         }
6545
6546                         if (direct_r_idx < 0)
6547                         {
6548                                 for (i = 0; i < browser_rows; i++)
6549                                 {
6550                                         Term_putch(max + 1, 6 + i, TERM_WHITE, '|');
6551                                 }
6552                         }
6553
6554                         redraw = FALSE;
6555                 }
6556
6557                 if (direct_r_idx < 0)
6558                 {
6559                         /* Scroll group list */
6560                         if (grp_cur < grp_top) grp_top = grp_cur;
6561                         if (grp_cur >= grp_top + browser_rows) grp_top = grp_cur - browser_rows + 1;
6562
6563                         /* Display a list of monster groups */
6564                         display_group_list(0, 6, max, browser_rows, grp_idx, monster_group_text, grp_cur, grp_top);
6565
6566                         if (old_grp_cur != grp_cur)
6567                         {
6568                                 old_grp_cur = grp_cur;
6569
6570                                 /* Get a list of monsters in the current group */
6571                                 mon_cnt = collect_monsters(grp_idx[grp_cur], mon_idx, mode);
6572                         }
6573
6574                         /* Scroll monster list */
6575                         while (mon_cur < mon_top)
6576                                 mon_top = MAX(0, mon_top - browser_rows/2);
6577                         while (mon_cur >= mon_top + browser_rows)
6578                                 mon_top = MIN(mon_cnt - browser_rows, mon_top + browser_rows/2);
6579                 }
6580
6581                 if (!visual_list)
6582                 {
6583                         /* Display a list of monsters in the current group */
6584                         display_monster_list(max + 3, 6, browser_rows, mon_idx, mon_cur, mon_top, visual_only);
6585                 }
6586                 else
6587                 {
6588                         mon_top = mon_cur;
6589
6590                         /* Display a monster name */
6591                         display_monster_list(max + 3, 6, 1, mon_idx, mon_cur, mon_top, visual_only);
6592
6593                         /* Display visual list below first monster */
6594                         display_visual_list(max + 3, 7, browser_rows-1, wid - (max + 3), attr_top, char_left);
6595                 }
6596
6597                 /* Prompt */
6598                 prt(format(_("<方向>%s%s%s, ESC", "<dir>%s%s%s, ESC"),
6599                         (!visual_list && !visual_only) ? _(", 'r'で思い出を見る", ", 'r' to recall") : "",
6600                         visual_list ? _(", ENTERで決定", ", ENTER to accept") : _(", 'v'でシンボル変更", ", 'v' for visuals"),
6601                         (attr_idx || char_idx) ? _(", 'c', 'p'でペースト", ", 'c', 'p' to paste") : _(", 'c'でコピー", ", 'c' to copy")),
6602                         hgt - 1, 0);
6603
6604                 /* Get the current monster */
6605                 r_ptr = &r_info[mon_idx[mon_cur]];
6606
6607                 if (!visual_only)
6608                 {
6609                         /* Mega Hack -- track this monster race */
6610                         if (mon_cnt) monster_race_track(mon_idx[mon_cur]);
6611                         handle_stuff();
6612                 }
6613
6614                 if (visual_list)
6615                 {
6616                         place_visual_list_cursor(max + 3, 7, r_ptr->x_attr, r_ptr->x_char, attr_top, char_left);
6617                 }
6618                 else if (!column)
6619                 {
6620                         Term_gotoxy(0, 6 + (grp_cur - grp_top));
6621                 }
6622                 else
6623                 {
6624                         Term_gotoxy(max + 3, 6 + (mon_cur - mon_top));
6625                 }
6626
6627                 ch = inkey();
6628
6629                 /* Do visual mode command if needed */
6630                 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))
6631                 {
6632                         if (direct_r_idx >= 0)
6633                         {
6634                                 switch (ch)
6635                                 {
6636                                 case '\n':
6637                                 case '\r':
6638                                 case ESCAPE:
6639                                         flag = TRUE;
6640                                         break;
6641                                 }
6642                         }
6643                         continue;
6644                 }
6645
6646                 switch (ch)
6647                 {
6648                         case ESCAPE:
6649                         {
6650                                 flag = TRUE;
6651                                 break;
6652                         }
6653
6654                         case 'R':
6655                         case 'r':
6656                         {
6657                                 /* Recall on screen */
6658                                 if (!visual_list && !visual_only && (mon_idx[mon_cur] > 0))
6659                                 {
6660                                         screen_roff(mon_idx[mon_cur], 0);
6661
6662                                         (void)inkey();
6663
6664                                         redraw = TRUE;
6665                                 }
6666                                 break;
6667                         }
6668
6669                         default:
6670                         {
6671                                 /* Move the cursor */
6672                                 browser_cursor(ch, &column, &grp_cur, grp_cnt, &mon_cur, mon_cnt);
6673
6674                                 break;
6675                         }
6676                 }
6677         }
6678
6679         /* Free the "mon_idx" array */
6680         C_KILL(mon_idx, max_r_idx, MONRACE_IDX);
6681 }
6682
6683
6684 /*
6685  * Display the objects in a group.
6686  */
6687 static void display_object_list(int col, int row, int per_page, IDX object_idx[],
6688         int object_cur, int object_top, bool visual_only)
6689 {
6690         int i;
6691
6692         /* Display lines until done */
6693         for (i = 0; i < per_page && (object_idx[object_top + i] >= 0); i++)
6694         {
6695                 GAME_TEXT o_name[MAX_NLEN];
6696                 TERM_COLOR a;
6697                 SYMBOL_CODE c;
6698                 object_kind *flavor_k_ptr;
6699
6700                 /* Get the object index */
6701                 KIND_OBJECT_IDX k_idx = object_idx[object_top + i];
6702
6703                 /* Access the object */
6704                 object_kind *k_ptr = &k_info[k_idx];
6705
6706                 /* Choose a color */
6707                 TERM_COLOR attr = ((k_ptr->aware || visual_only) ? TERM_WHITE : TERM_SLATE);
6708                 byte cursor = ((k_ptr->aware || visual_only) ? TERM_L_BLUE : TERM_BLUE);
6709
6710
6711                 if (!visual_only && k_ptr->flavor)
6712                 {
6713                         /* Appearance of this object is shuffled */
6714                         flavor_k_ptr = &k_info[k_ptr->flavor];
6715                 }
6716                 else
6717                 {
6718                         /* Appearance of this object is very normal */
6719                         flavor_k_ptr = k_ptr;
6720                 }
6721
6722
6723
6724                 attr = ((i + object_top == object_cur) ? cursor : attr);
6725
6726                 if (!k_ptr->flavor || (!visual_only && k_ptr->aware))
6727                 {
6728                         /* Tidy name */
6729                         strip_name(o_name, k_idx);
6730                 }
6731                 else
6732                 {
6733                         /* Flavor name */
6734                         strcpy(o_name, k_name + flavor_k_ptr->flavor_name);
6735                 }
6736
6737                 /* Display the name */
6738                 c_prt(attr, o_name, row + i, col);
6739
6740                 /* Hack -- visual_list mode */
6741                 if (per_page == 1)
6742                 {
6743                         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);
6744                 }
6745                 if (p_ptr->wizard || visual_only)
6746                 {
6747                         c_prt(attr, format("%d", k_idx), row + i, 70);
6748                 }
6749
6750                 a = flavor_k_ptr->x_attr;
6751                 c = flavor_k_ptr->x_char;
6752
6753                 /* Display symbol */
6754                 Term_queue_bigchar(use_bigtile ? 76 : 77, row + i, a, c, 0, 0);
6755         }
6756
6757         /* Clear remaining lines */
6758         for (; i < per_page; i++)
6759         {
6760                 Term_erase(col, row + i, 255);
6761         }
6762 }
6763
6764 /*
6765  * Describe fake object
6766  */
6767 static void desc_obj_fake(KIND_OBJECT_IDX k_idx)
6768 {
6769         object_type *o_ptr;
6770         object_type object_type_body;
6771         o_ptr = &object_type_body;
6772         object_wipe(o_ptr);
6773
6774         /* Create the artifact */
6775         object_prep(o_ptr, k_idx);
6776
6777         /* It's fully know */
6778         o_ptr->ident |= IDENT_KNOWN;
6779
6780         /* Track the object */
6781         /* object_actual_track(o_ptr); */
6782
6783         /* Hack - mark as fake */
6784         /* term_obj_real = FALSE; */
6785         handle_stuff();
6786
6787         if (!screen_object(o_ptr, SCROBJ_FAKE_OBJECT | SCROBJ_FORCE_DETAIL))
6788         {
6789                 msg_print(_("特に変わったところはないようだ。", "You see nothing special."));
6790                 msg_print(NULL);
6791         }
6792 }
6793
6794
6795
6796 /*
6797  * Display known objects
6798  */
6799 static void do_cmd_knowledge_objects(bool *need_redraw, bool visual_only, IDX direct_k_idx)
6800 {
6801         IDX i;
6802         int len, max;
6803         IDX grp_cur, grp_top, old_grp_cur;
6804         IDX object_old, object_cur, object_top;
6805         int grp_cnt;
6806         IDX grp_idx[100];
6807         int object_cnt;
6808         OBJECT_IDX *object_idx;
6809
6810         int column = 0;
6811         bool flag;
6812         bool redraw;
6813
6814         bool visual_list = FALSE;
6815         TERM_COLOR attr_top = 0;
6816         byte char_left = 0;
6817
6818         int browser_rows;
6819         TERM_LEN wid, hgt;
6820
6821         byte mode;
6822
6823         Term_get_size(&wid, &hgt);
6824
6825         browser_rows = hgt - 8;
6826
6827         /* Allocate the "object_idx" array */
6828         C_MAKE(object_idx, max_k_idx, KIND_OBJECT_IDX);
6829
6830         max = 0;
6831         grp_cnt = 0;
6832
6833         if (direct_k_idx < 0)
6834         {
6835                 mode = visual_only ? 0x03 : 0x01;
6836
6837                 /* Check every group */
6838                 for (i = 0; object_group_text[i] != NULL; i++)
6839                 {
6840                         /* Measure the label */
6841                         len = strlen(object_group_text[i]);
6842
6843                         /* Save the maximum length */
6844                         if (len > max) max = len;
6845
6846                         /* See if any monsters are known */
6847                         if (collect_objects(i, object_idx, mode))
6848                         {
6849                                 /* Build a list of groups with known monsters */
6850                                 grp_idx[grp_cnt++] = i;
6851                         }
6852                 }
6853
6854                 object_old = -1;
6855                 object_cnt = 0;
6856         }
6857         else
6858         {
6859                 object_kind *k_ptr = &k_info[direct_k_idx];
6860                 object_kind *flavor_k_ptr;
6861
6862                 if (!visual_only && k_ptr->flavor)
6863                 {
6864                         /* Appearance of this object is shuffled */
6865                         flavor_k_ptr = &k_info[k_ptr->flavor];
6866                 }
6867                 else
6868                 {
6869                         /* Appearance of this object is very normal */
6870                         flavor_k_ptr = k_ptr;
6871                 }
6872
6873                 object_idx[0] = direct_k_idx;
6874                 object_old = direct_k_idx;
6875                 object_cnt = 1;
6876
6877                 /* Terminate the list */
6878                 object_idx[1] = -1;
6879
6880                 (void)visual_mode_command('v', &visual_list, browser_rows - 1, wid - (max + 3),
6881                         &attr_top, &char_left, &flavor_k_ptr->x_attr, &flavor_k_ptr->x_char, need_redraw);
6882         }
6883
6884         /* Terminate the list */
6885         grp_idx[grp_cnt] = -1;
6886
6887         old_grp_cur = -1;
6888         grp_cur = grp_top = 0;
6889         object_cur = object_top = 0;
6890
6891         flag = FALSE;
6892         redraw = TRUE;
6893
6894         mode = visual_only ? 0x02 : 0x00;
6895
6896         while (!flag)
6897         {
6898                 char ch;
6899                 object_kind *k_ptr, *flavor_k_ptr;
6900
6901                 if (redraw)
6902                 {
6903                         clear_from(0);
6904
6905 #ifdef JP
6906                         prt(format("%s - アイテム", !visual_only ? "知識" : "表示"), 2, 0);
6907                         if (direct_k_idx < 0) prt("グループ", 4, 0);
6908                         prt("名前", 4, max + 3);
6909                         if (p_ptr->wizard || visual_only) prt("Idx", 4, 70);
6910                         prt("文字", 4, 74);
6911 #else
6912                         prt(format("%s - objects", !visual_only ? "Knowledge" : "Visuals"), 2, 0);
6913                         if (direct_k_idx < 0) prt("Group", 4, 0);
6914                         prt("Name", 4, max + 3);
6915                         if (p_ptr->wizard || visual_only) prt("Idx", 4, 70);
6916                         prt("Sym", 4, 75);
6917 #endif
6918
6919                         for (i = 0; i < 78; i++)
6920                         {
6921                                 Term_putch(i, 5, TERM_WHITE, '=');
6922                         }
6923
6924                         if (direct_k_idx < 0)
6925                         {
6926                                 for (i = 0; i < browser_rows; i++)
6927                                 {
6928                                         Term_putch(max + 1, 6 + i, TERM_WHITE, '|');
6929                                 }
6930                         }
6931
6932                         redraw = FALSE;
6933                 }
6934
6935                 if (direct_k_idx < 0)
6936                 {
6937                         /* Scroll group list */
6938                         if (grp_cur < grp_top) grp_top = grp_cur;
6939                         if (grp_cur >= grp_top + browser_rows) grp_top = grp_cur - browser_rows + 1;
6940
6941                         /* Display a list of object groups */
6942                         display_group_list(0, 6, max, browser_rows, grp_idx, object_group_text, grp_cur, grp_top);
6943
6944                         if (old_grp_cur != grp_cur)
6945                         {
6946                                 old_grp_cur = grp_cur;
6947
6948                                 /* Get a list of objects in the current group */
6949                                 object_cnt = collect_objects(grp_idx[grp_cur], object_idx, mode);
6950                         }
6951
6952                         /* Scroll object list */
6953                         while (object_cur < object_top)
6954                                 object_top = MAX(0, object_top - browser_rows/2);
6955                         while (object_cur >= object_top + browser_rows)
6956                                 object_top = MIN(object_cnt - browser_rows, object_top + browser_rows/2);
6957                 }
6958
6959                 if (!visual_list)
6960                 {
6961                         /* Display a list of objects in the current group */
6962                         display_object_list(max + 3, 6, browser_rows, object_idx, object_cur, object_top, visual_only);
6963                 }
6964                 else
6965                 {
6966                         object_top = object_cur;
6967
6968                         /* Display a list of objects in the current group */
6969                         display_object_list(max + 3, 6, 1, object_idx, object_cur, object_top, visual_only);
6970
6971                         /* Display visual list below first object */
6972                         display_visual_list(max + 3, 7, browser_rows-1, wid - (max + 3), attr_top, char_left);
6973                 }
6974
6975                 /* Get the current object */
6976                 k_ptr = &k_info[object_idx[object_cur]];
6977
6978                 if (!visual_only && k_ptr->flavor)
6979                 {
6980                         /* Appearance of this object is shuffled */
6981                         flavor_k_ptr = &k_info[k_ptr->flavor];
6982                 }
6983                 else
6984                 {
6985                         /* Appearance of this object is very normal */
6986                         flavor_k_ptr = k_ptr;
6987                 }
6988
6989                 /* Prompt */
6990 #ifdef JP
6991                 prt(format("<方向>%s%s%s, ESC",
6992                         (!visual_list && !visual_only) ? ", 'r'で詳細を見る" : "",
6993                         visual_list ? ", ENTERで決定" : ", 'v'でシンボル変更",
6994                         (attr_idx || char_idx) ? ", 'c', 'p'でペースト" : ", 'c'でコピー"),
6995                         hgt - 1, 0);
6996 #else
6997                 prt(format("<dir>%s%s%s, ESC",
6998                         (!visual_list && !visual_only) ? ", 'r' to recall" : "",
6999                         visual_list ? ", ENTER to accept" : ", 'v' for visuals",
7000                         (attr_idx || char_idx) ? ", 'c', 'p' to paste" : ", 'c' to copy"),
7001                         hgt - 1, 0);
7002 #endif
7003
7004                 if (!visual_only)
7005                 {
7006                         /* Mega Hack -- track this object */
7007                         if (object_cnt) object_kind_track(object_idx[object_cur]);
7008
7009                         /* The "current" object changed */
7010                         if (object_old != object_idx[object_cur])
7011                         {
7012                                 handle_stuff();
7013
7014                                 /* Remember the "current" object */
7015                                 object_old = object_idx[object_cur];
7016                         }
7017                 }
7018
7019                 if (visual_list)
7020                 {
7021                         place_visual_list_cursor(max + 3, 7, flavor_k_ptr->x_attr, flavor_k_ptr->x_char, attr_top, char_left);
7022                 }
7023                 else if (!column)
7024                 {
7025                         Term_gotoxy(0, 6 + (grp_cur - grp_top));
7026                 }
7027                 else
7028                 {
7029                         Term_gotoxy(max + 3, 6 + (object_cur - object_top));
7030                 }
7031
7032                 ch = inkey();
7033
7034                 /* Do visual mode command if needed */
7035                 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))
7036                 {
7037                         if (direct_k_idx >= 0)
7038                         {
7039                                 switch (ch)
7040                                 {
7041                                 case '\n':
7042                                 case '\r':
7043                                 case ESCAPE:
7044                                         flag = TRUE;
7045                                         break;
7046                                 }
7047                         }
7048                         continue;
7049                 }
7050
7051                 switch (ch)
7052                 {
7053                         case ESCAPE:
7054                         {
7055                                 flag = TRUE;
7056                                 break;
7057                         }
7058
7059                         case 'R':
7060                         case 'r':
7061                         {
7062                                 /* Recall on screen */
7063                                 if (!visual_list && !visual_only && (grp_cnt > 0))
7064                                 {
7065                                         desc_obj_fake(object_idx[object_cur]);
7066                                         redraw = TRUE;
7067                                 }
7068                                 break;
7069                         }
7070
7071                         default:
7072                         {
7073                                 /* Move the cursor */
7074                                 browser_cursor(ch, &column, &grp_cur, grp_cnt, &object_cur, object_cnt);
7075                                 break;
7076                         }
7077                 }
7078         }
7079
7080         /* Free the "object_idx" array */
7081         C_KILL(object_idx, max_k_idx, KIND_OBJECT_IDX);
7082 }
7083
7084
7085 /*
7086  * Display the features in a group.
7087  */
7088 static void display_feature_list(int col, int row, int per_page, FEAT_IDX *feat_idx,
7089         FEAT_IDX feat_cur, FEAT_IDX feat_top, bool visual_only, int lighting_level)
7090 {
7091         int lit_col[F_LIT_MAX], i, j;
7092         int f_idx_col = use_bigtile ? 62 : 64;
7093
7094         /* Correct columns 1 and 4 */
7095         lit_col[F_LIT_STANDARD] = use_bigtile ? (71 - F_LIT_MAX) : 71;
7096         for (i = F_LIT_NS_BEGIN; i < F_LIT_MAX; i++)
7097                 lit_col[i] = lit_col[F_LIT_STANDARD] + 2 + (i - F_LIT_NS_BEGIN) * 2 + (use_bigtile ? i : 0);
7098
7099         /* Display lines until done */
7100         for (i = 0; i < per_page && (feat_idx[feat_top + i] >= 0); i++)
7101         {
7102                 TERM_COLOR attr;
7103
7104                 /* Get the index */
7105                 FEAT_IDX f_idx = feat_idx[feat_top + i];
7106
7107                 /* Access the index */
7108                 feature_type *f_ptr = &f_info[f_idx];
7109
7110                 int row_i = row + i;
7111
7112                 /* Choose a color */
7113                 attr = ((i + feat_top == feat_cur) ? TERM_L_BLUE : TERM_WHITE);
7114
7115                 /* Display the name */
7116                 c_prt(attr, f_name + f_ptr->name, row_i, col);
7117
7118                 /* Hack -- visual_list mode */
7119                 if (per_page == 1)
7120                 {
7121                         /* Display lighting level */
7122                         c_prt(attr, format("(%s)", lighting_level_str[lighting_level]), row_i, col + 1 + strlen(f_name + f_ptr->name));
7123
7124                         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));
7125                 }
7126                 if (p_ptr->wizard || visual_only)
7127                 {
7128                         c_prt(attr, format("%d", f_idx), row_i, f_idx_col);
7129                 }
7130
7131                 /* Display symbol */
7132                 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);
7133
7134                 Term_putch(lit_col[F_LIT_NS_BEGIN], row_i, TERM_SLATE, '(');
7135                 for (j = F_LIT_NS_BEGIN + 1; j < F_LIT_MAX; j++)
7136                 {
7137                         Term_putch(lit_col[j], row_i, TERM_SLATE, '/');
7138                 }
7139                 Term_putch(lit_col[F_LIT_MAX - 1] + (use_bigtile ? 3 : 2), row_i, TERM_SLATE, ')');
7140
7141                 /* Mega-hack -- Use non-standard colour */
7142                 for (j = F_LIT_NS_BEGIN; j < F_LIT_MAX; j++)
7143                 {
7144                         Term_queue_bigchar(lit_col[j] + 1, row_i, f_ptr->x_attr[j], f_ptr->x_char[j], 0, 0);
7145                 }
7146         }
7147
7148         /* Clear remaining lines */
7149         for (; i < per_page; i++)
7150         {
7151                 Term_erase(col, row + i, 255);
7152         }
7153 }
7154
7155
7156 /*
7157  * Interact with feature visuals.
7158  */
7159 static void do_cmd_knowledge_features(bool *need_redraw, bool visual_only, IDX direct_f_idx, IDX *lighting_level)
7160 {
7161         FEAT_IDX i;
7162         int len, max;
7163         FEAT_IDX grp_cur, grp_top, old_grp_cur;
7164         FEAT_IDX feat_cur, feat_top;
7165         int grp_cnt;
7166         FEAT_IDX grp_idx[100];
7167         int feat_cnt;
7168         FEAT_IDX *feat_idx;
7169
7170         TERM_LEN column = 0;
7171         bool flag;
7172         bool redraw;
7173
7174         bool visual_list = FALSE;
7175         TERM_COLOR attr_top = 0;
7176         byte char_left = 0;
7177
7178         TERM_LEN browser_rows;
7179         TERM_LEN wid, hgt;
7180
7181         TERM_COLOR attr_old[F_LIT_MAX];
7182         SYMBOL_CODE char_old[F_LIT_MAX];
7183         TERM_COLOR *cur_attr_ptr;
7184         SYMBOL_CODE *cur_char_ptr;
7185
7186         (void)C_WIPE(attr_old, F_LIT_MAX, TERM_COLOR);
7187         (void)C_WIPE(char_old, F_LIT_MAX, SYMBOL_CODE);
7188
7189         Term_get_size(&wid, &hgt);
7190
7191         browser_rows = hgt - 8;
7192
7193         /* Allocate the "feat_idx" array */
7194         C_MAKE(feat_idx, max_f_idx, FEAT_IDX);
7195
7196         max = 0;
7197         grp_cnt = 0;
7198
7199         if (direct_f_idx < 0)
7200         {
7201                 /* Check every group */
7202                 for (i = 0; feature_group_text[i] != NULL; i++)
7203                 {
7204                         /* Measure the label */
7205                         len = strlen(feature_group_text[i]);
7206
7207                         /* Save the maximum length */
7208                         if (len > max) max = len;
7209
7210                         /* See if any features are known */
7211                         if (collect_features(i, feat_idx, 0x01))
7212                         {
7213                                 /* Build a list of groups with known features */
7214                                 grp_idx[grp_cnt++] = i;
7215                         }
7216                 }
7217
7218                 feat_cnt = 0;
7219         }
7220         else
7221         {
7222                 feature_type *f_ptr = &f_info[direct_f_idx];
7223
7224                 feat_idx[0] = direct_f_idx;
7225                 feat_cnt = 1;
7226
7227                 /* Terminate the list */
7228                 feat_idx[1] = -1;
7229
7230                 (void)visual_mode_command('v', &visual_list, browser_rows - 1, wid - (max + 3),
7231                         &attr_top, &char_left, &f_ptr->x_attr[*lighting_level], &f_ptr->x_char[*lighting_level], need_redraw);
7232
7233                 for (i = 0; i < F_LIT_MAX; i++)
7234                 {
7235                         attr_old[i] = f_ptr->x_attr[i];
7236                         char_old[i] = f_ptr->x_char[i];
7237                 }
7238         }
7239
7240         /* Terminate the list */
7241         grp_idx[grp_cnt] = -1;
7242
7243         old_grp_cur = -1;
7244         grp_cur = grp_top = 0;
7245         feat_cur = feat_top = 0;
7246
7247         flag = FALSE;
7248         redraw = TRUE;
7249
7250         while (!flag)
7251         {
7252                 char ch;
7253                 feature_type *f_ptr;
7254
7255                 if (redraw)
7256                 {
7257                         clear_from(0);
7258
7259                         prt(_("表示 - 地形", "Visuals - features"), 2, 0);
7260                         if (direct_f_idx < 0) prt(_("グループ", "Group"), 4, 0);
7261                         prt(_("名前", "Name"), 4, max + 3);
7262                         if (use_bigtile)
7263                         {
7264                                 if (p_ptr->wizard || visual_only) prt("Idx", 4, 62);
7265                                 prt(_("文字 ( l/ d)", "Sym ( l/ d)"), 4, 66);
7266                         }
7267                         else
7268                         {
7269                                 if (p_ptr->wizard || visual_only) prt("Idx", 4, 64);
7270                                 prt(_("文字 (l/d)", "Sym (l/d)"), 4, 68);
7271                         }
7272
7273                         for (i = 0; i < 78; i++)
7274                         {
7275                                 Term_putch(i, 5, TERM_WHITE, '=');
7276                         }
7277
7278                         if (direct_f_idx < 0)
7279                         {
7280                                 for (i = 0; i < browser_rows; i++)
7281                                 {
7282                                         Term_putch(max + 1, 6 + i, TERM_WHITE, '|');
7283                                 }
7284                         }
7285
7286                         redraw = FALSE;
7287                 }
7288
7289                 if (direct_f_idx < 0)
7290                 {
7291                         /* Scroll group list */
7292                         if (grp_cur < grp_top) grp_top = grp_cur;
7293                         if (grp_cur >= grp_top + browser_rows) grp_top = grp_cur - browser_rows + 1;
7294
7295                         /* Display a list of feature groups */
7296                         display_group_list(0, 6, max, browser_rows, grp_idx, feature_group_text, grp_cur, grp_top);
7297
7298                         if (old_grp_cur != grp_cur)
7299                         {
7300                                 old_grp_cur = grp_cur;
7301
7302                                 /* Get a list of features in the current group */
7303                                 feat_cnt = collect_features(grp_idx[grp_cur], feat_idx, 0x00);
7304                         }
7305
7306                         /* Scroll feature list */
7307                         while (feat_cur < feat_top)
7308                                 feat_top = MAX(0, feat_top - browser_rows/2);
7309                         while (feat_cur >= feat_top + browser_rows)
7310                                 feat_top = MIN(feat_cnt - browser_rows, feat_top + browser_rows/2);
7311                 }
7312
7313                 if (!visual_list)
7314                 {
7315                         /* Display a list of features in the current group */
7316                         display_feature_list(max + 3, 6, browser_rows, feat_idx, feat_cur, feat_top, visual_only, F_LIT_STANDARD);
7317                 }
7318                 else
7319                 {
7320                         feat_top = feat_cur;
7321
7322                         /* Display a list of features in the current group */
7323                         display_feature_list(max + 3, 6, 1, feat_idx, feat_cur, feat_top, visual_only, *lighting_level);
7324
7325                         /* Display visual list below first object */
7326                         display_visual_list(max + 3, 7, browser_rows-1, wid - (max + 3), attr_top, char_left);
7327                 }
7328
7329                 /* Prompt */
7330                 prt(format(_("<方向>%s, 'd'で標準光源効果%s, ESC", "<dir>%s, 'd' for default lighting%s, ESC"),
7331                         visual_list ? _(", ENTERで決定, 'a'で対象明度変更", ", ENTER to accept, 'a' for lighting level") : _(", 'v'でシンボル変更", ", 'v' for visuals"),
7332                         (attr_idx || char_idx) ? _(", 'c', 'p'でペースト", ", 'c', 'p' to paste") : _(", 'c'でコピー", ", 'c' to copy")),
7333                         hgt - 1, 0);
7334
7335                 /* Get the current feature */
7336                 f_ptr = &f_info[feat_idx[feat_cur]];
7337                 cur_attr_ptr = &f_ptr->x_attr[*lighting_level];
7338                 cur_char_ptr = &f_ptr->x_char[*lighting_level];
7339
7340                 if (visual_list)
7341                 {
7342                         place_visual_list_cursor(max + 3, 7, *cur_attr_ptr, *cur_char_ptr, attr_top, char_left);
7343                 }
7344                 else if (!column)
7345                 {
7346                         Term_gotoxy(0, 6 + (grp_cur - grp_top));
7347                 }
7348                 else
7349                 {
7350                         Term_gotoxy(max + 3, 6 + (feat_cur - feat_top));
7351                 }
7352
7353                 ch = inkey();
7354
7355                 if (visual_list && ((ch == 'A') || (ch == 'a')))
7356                 {
7357                         int prev_lighting_level = *lighting_level;
7358
7359                         if (ch == 'A')
7360                         {
7361                                 if (*lighting_level <= 0) *lighting_level = F_LIT_MAX - 1;
7362                                 else (*lighting_level)--;
7363                         }
7364                         else
7365                         {
7366                                 if (*lighting_level >= F_LIT_MAX - 1) *lighting_level = 0;
7367                                 else (*lighting_level)++;
7368                         }
7369
7370                         if (f_ptr->x_attr[prev_lighting_level] != f_ptr->x_attr[*lighting_level])
7371                                 attr_top = MAX(0, (f_ptr->x_attr[*lighting_level] & 0x7f) - 5);
7372
7373                         if (f_ptr->x_char[prev_lighting_level] != f_ptr->x_char[*lighting_level])
7374                                 char_left = MAX(0, f_ptr->x_char[*lighting_level] - 10);
7375
7376                         continue;
7377                 }
7378
7379                 else if ((ch == 'D') || (ch == 'd'))
7380                 {
7381                         TERM_COLOR prev_x_attr = f_ptr->x_attr[*lighting_level];
7382                         byte prev_x_char = f_ptr->x_char[*lighting_level];
7383
7384                         apply_default_feat_lighting(f_ptr->x_attr, f_ptr->x_char);
7385
7386                         if (visual_list)
7387                         {
7388                                 if (prev_x_attr != f_ptr->x_attr[*lighting_level])
7389                                          attr_top = MAX(0, (f_ptr->x_attr[*lighting_level] & 0x7f) - 5);
7390
7391                                 if (prev_x_char != f_ptr->x_char[*lighting_level])
7392                                         char_left = MAX(0, f_ptr->x_char[*lighting_level] - 10);
7393                         }
7394                         else *need_redraw = TRUE;
7395
7396                         continue;
7397                 }
7398
7399                 /* Do visual mode command if needed */
7400                 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))
7401                 {
7402                         switch (ch)
7403                         {
7404                         /* Restore previous visual settings */
7405                         case ESCAPE:
7406                                 for (i = 0; i < F_LIT_MAX; i++)
7407                                 {
7408                                         f_ptr->x_attr[i] = attr_old[i];
7409                                         f_ptr->x_char[i] = char_old[i];
7410                                 }
7411
7412                                 /* Fall through */
7413
7414                         case '\n':
7415                         case '\r':
7416                                 if (direct_f_idx >= 0) flag = TRUE;
7417                                 else *lighting_level = F_LIT_STANDARD;
7418                                 break;
7419
7420                         /* Preserve current visual settings */
7421                         case 'V':
7422                         case 'v':
7423                                 for (i = 0; i < F_LIT_MAX; i++)
7424                                 {
7425                                         attr_old[i] = f_ptr->x_attr[i];
7426                                         char_old[i] = f_ptr->x_char[i];
7427                                 }
7428                                 *lighting_level = F_LIT_STANDARD;
7429                                 break;
7430
7431                         case 'C':
7432                         case 'c':
7433                                 if (!visual_list)
7434                                 {
7435                                         for (i = 0; i < F_LIT_MAX; i++)
7436                                         {
7437                                                 attr_idx_feat[i] = f_ptr->x_attr[i];
7438                                                 char_idx_feat[i] = f_ptr->x_char[i];
7439                                         }
7440                                 }
7441                                 break;
7442
7443                         case 'P':
7444                         case 'p':
7445                                 if (!visual_list)
7446                                 {
7447                                         /* Allow TERM_DARK text */
7448                                         for (i = F_LIT_NS_BEGIN; i < F_LIT_MAX; i++)
7449                                         {
7450                                                 if (attr_idx_feat[i] || (!(char_idx_feat[i] & 0x80) && char_idx_feat[i])) f_ptr->x_attr[i] = attr_idx_feat[i];
7451                                                 if (char_idx_feat[i]) f_ptr->x_char[i] = char_idx_feat[i];
7452                                         }
7453                                 }
7454                                 break;
7455                         }
7456                         continue;
7457                 }
7458
7459                 switch (ch)
7460                 {
7461                         case ESCAPE:
7462                         {
7463                                 flag = TRUE;
7464                                 break;
7465                         }
7466
7467                         default:
7468                         {
7469                                 /* Move the cursor */
7470                                 browser_cursor(ch, &column, &grp_cur, grp_cnt, &feat_cur, feat_cnt);
7471                                 break;
7472                         }
7473                 }
7474         }
7475
7476         /* Free the "feat_idx" array */
7477         C_KILL(feat_idx, max_f_idx, FEAT_IDX);
7478 }
7479
7480
7481 /*
7482  * List wanted monsters
7483  */
7484 static void do_cmd_knowledge_kubi(void)
7485 {
7486         int i;
7487         FILE *fff;
7488         
7489         GAME_TEXT file_name[1024];
7490         
7491         
7492         /* Open a new file */
7493         fff = my_fopen_temp(file_name, 1024);
7494         if (!fff) {
7495             msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
7496             msg_print(NULL);
7497             return;
7498         }
7499         
7500         if (fff)
7501         {
7502                 bool listed = FALSE;
7503
7504                 fprintf(fff, _("今日のターゲット : %s\n", "Today target : %s\n"),
7505                         (p_ptr->today_mon ? r_name + r_info[p_ptr->today_mon].name : _("不明", "unknown")));
7506                 fprintf(fff, "\n");
7507                 fprintf(fff, _("賞金首リスト\n", "List of wanted monsters\n"));
7508                 fprintf(fff, "----------------------------------------------\n");
7509
7510                 for (i = 0; i < MAX_KUBI; i++)
7511                 {
7512                         if (current_world_ptr->bounty_r_idx[i] <= 10000)
7513                         {
7514                                 fprintf(fff,"%s\n", r_name + r_info[current_world_ptr->bounty_r_idx[i]].name);
7515
7516                                 listed = TRUE;
7517                         }
7518                 }
7519
7520                 if (!listed)
7521                 {
7522                         fprintf(fff,"\n%s\n", _("賞金首はもう残っていません。", "There is no more wanted monster."));
7523                 }
7524         }
7525                 my_fclose(fff);
7526         
7527         /* Display the file contents */
7528         show_file(TRUE, file_name, _("賞金首の一覧", "Wanted monsters"), 0, 0);
7529         fd_kill(file_name);
7530 }
7531
7532 /*
7533  * List virtues & status
7534  */
7535 static void do_cmd_knowledge_virtues(void)
7536 {
7537         FILE *fff;      
7538         GAME_TEXT file_name[1024];
7539                 
7540         /* Open a new file */
7541         fff = my_fopen_temp(file_name, 1024);
7542         if (!fff) {
7543             msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
7544             msg_print(NULL);
7545             return;
7546         }
7547         
7548         if (fff)
7549         {
7550                 fprintf(fff, _("現在の属性 : %s\n\n", "Your alighnment : %s\n\n"), your_alignment());
7551                 dump_virtues(fff);
7552         }
7553                 my_fclose(fff);
7554         
7555         /* Display the file contents */
7556         show_file(TRUE, file_name, _("八つの徳", "Virtues"), 0, 0);
7557         fd_kill(file_name);
7558 }
7559
7560 /*
7561  * Dungeon
7562  */
7563 static void do_cmd_knowledge_dungeon(void)
7564 {
7565         FILE *fff;
7566         
7567         GAME_TEXT file_name[1024];
7568         int i;
7569                 
7570         /* Open a new file */
7571         fff = my_fopen_temp(file_name, 1024);
7572         if (!fff) {
7573             msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
7574             msg_print(NULL);
7575             return;
7576         }
7577         
7578         if (fff)
7579         {
7580                 for (i = 1; i < max_d_idx; i++)
7581                 {
7582                         bool seiha = FALSE;
7583
7584                         if (!d_info[i].maxdepth) continue;
7585                         if (!max_dlv[i]) continue;
7586                         if (d_info[i].final_guardian)
7587                         {
7588                                 if (!r_info[d_info[i].final_guardian].max_num) seiha = TRUE;
7589                         }
7590                         else if (max_dlv[i] == d_info[i].maxdepth) seiha = TRUE;
7591                         
7592                         fprintf(fff, _("%c%-12s :  %3d 階\n", "%c%-16s :  level %3d\n"), seiha ? '!' : ' ', d_name + d_info[i].name, (int)max_dlv[i]);
7593                 }
7594         }
7595                 my_fclose(fff);
7596         
7597         /* Display the file contents */
7598         show_file(TRUE, file_name, _("今までに入ったダンジョン", "Dungeon"), 0, 0);
7599         fd_kill(file_name);
7600 }
7601
7602 /*
7603 * List virtues & status
7604 *
7605 */
7606 static void do_cmd_knowledge_stat(void)
7607 {
7608         FILE *fff;
7609         
7610         GAME_TEXT file_name[1024];
7611         int percent, v_nr;
7612         
7613         /* Open a new file */
7614         fff = my_fopen_temp(file_name, 1024);
7615         if (!fff) {
7616             msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
7617             msg_print(NULL);
7618             return;
7619         }
7620         
7621         if (fff)
7622         {
7623                 percent = (int)(((long)p_ptr->player_hp[PY_MAX_LEVEL - 1] * 200L) /
7624                         (2 * p_ptr->hitdie +
7625                         ((PY_MAX_LEVEL - 1+3) * (p_ptr->hitdie + 1))));
7626
7627                 if (p_ptr->knowledge & KNOW_HPRATE)
7628                         fprintf(fff, _("現在の体力ランク : %d/100\n\n", "Your current Life Rating is %d/100.\n\n"), percent);
7629                 else fprintf(fff, _("現在の体力ランク : ???\n\n", "Your current Life Rating is ???.\n\n"));
7630
7631                 fprintf(fff, _("能力の最大値\n\n", "Limits of maximum stats\n\n"));
7632                 for (v_nr = 0; v_nr < A_MAX; v_nr++)
7633                 {
7634                         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);
7635                         else fprintf(fff, "%s ???\n", stat_names[v_nr]);
7636                 }
7637         }
7638
7639         dump_yourself(fff);
7640         my_fclose(fff);
7641         
7642         /* Display the file contents */
7643         show_file(TRUE, file_name, _("自分に関する情報", "HP-rate & Max stat"), 0, 0);
7644         fd_kill(file_name);
7645 }
7646
7647
7648 /*
7649  * Print all active quests
7650  */
7651 static void do_cmd_knowledge_quests_current(FILE *fff)
7652 {
7653         char tmp_str[120];
7654         char rand_tmp_str[120] = "\0";
7655         GAME_TEXT name[MAX_NLEN];
7656         monster_race *r_ptr;
7657         QUEST_IDX i;
7658         int rand_level = 100;
7659         int total = 0;
7660
7661         fprintf(fff, _("《遂行中のクエスト》\n", "< Current Quest >\n"));
7662
7663         for (i = 1; i < max_q_idx; i++)
7664         {
7665                 if ((quest[i].status == QUEST_STATUS_TAKEN) ||
7666                         ((quest[i].status == QUEST_STATUS_STAGE_COMPLETED) && (quest[i].type == QUEST_TYPE_TOWER)) ||
7667                         (quest[i].status == QUEST_STATUS_COMPLETED))
7668                 {
7669                         /* Set the quest number temporary */
7670                         QUEST_IDX old_quest = p_ptr->inside_quest;
7671                         int j;
7672
7673                         /* Clear the text */
7674                         for (j = 0; j < 10; j++) quest_text[j][0] = '\0';
7675                         quest_text_line = 0;
7676
7677                         p_ptr->inside_quest = i;
7678
7679                         /* Get the quest text */
7680                         init_flags = INIT_SHOW_TEXT;
7681
7682                         process_dungeon_file("q_info.txt", 0, 0, 0, 0);
7683
7684                         /* Reset the old quest number */
7685                         p_ptr->inside_quest = old_quest;
7686
7687                         /* No info from "silent" quests */
7688                         if (quest[i].flags & QUEST_FLAG_SILENT) continue;
7689
7690                         total++;
7691
7692                         if (quest[i].type != QUEST_TYPE_RANDOM)
7693                         {
7694                                 char note[80] = "\0";
7695
7696                                 if (quest[i].status == QUEST_STATUS_TAKEN || quest[i].status == QUEST_STATUS_STAGE_COMPLETED)
7697                                 {
7698                                         switch (quest[i].type)
7699                                         {
7700                                         case QUEST_TYPE_KILL_LEVEL:
7701                                         case QUEST_TYPE_KILL_ANY_LEVEL:
7702                                                 r_ptr = &r_info[quest[i].r_idx];
7703                                                 strcpy(name, r_name + r_ptr->name);
7704                                                 if (quest[i].max_num > 1)
7705                                                 {
7706 #ifdef JP
7707                                                         sprintf(note," - %d 体の%sを倒す。(あと %d 体)",
7708                                                                 (int)quest[i].max_num, name, (int)(quest[i].max_num - quest[i].cur_num));
7709 #else
7710                                                         plural_aux(name);
7711                                                         sprintf(note," - kill %d %s, have killed %d.",
7712                                                                 (int)quest[i].max_num, name, (int)quest[i].cur_num);
7713 #endif
7714                                                 }
7715                                                 else
7716                                                         sprintf(note,_(" - %sを倒す。", " - kill %s."),name);
7717                                                 break;
7718
7719                                         case QUEST_TYPE_FIND_ARTIFACT:
7720                                                 if (quest[i].k_idx)
7721                                                 {
7722                                                         artifact_type *a_ptr = &a_info[quest[i].k_idx];
7723                                                         object_type forge;
7724                                                         object_type *q_ptr = &forge;
7725                                                         KIND_OBJECT_IDX k_idx = lookup_kind(a_ptr->tval, a_ptr->sval);
7726                                                         object_prep(q_ptr, k_idx);
7727                                                         q_ptr->name1 = quest[i].k_idx;
7728                                                         q_ptr->ident = IDENT_STORE;
7729                                                         object_desc(name, q_ptr, OD_NAME_ONLY);
7730                                                 }
7731                                                 sprintf(note,_("\n   - %sを見つけ出す。", "\n   - Find out %s."), name);
7732                                                 break;
7733                                         case QUEST_TYPE_FIND_EXIT:
7734                                                 sprintf(note,_(" - 出口に到達する。", " - Reach to Exit."));
7735                                                 break;
7736
7737                                         case QUEST_TYPE_KILL_NUMBER:
7738 #ifdef JP
7739                                                 sprintf(note," - %d 体のモンスターを倒す。(あと %d 体)",
7740                                                         (int)quest[i].max_num, (int)(quest[i].max_num - quest[i].cur_num));
7741 #else
7742                                                 sprintf(note," - Kill %d monsters, have killed %d.",
7743                                                         (int)quest[i].max_num, (int)quest[i].cur_num);
7744 #endif
7745                                                 break;
7746
7747                                         case QUEST_TYPE_KILL_ALL:
7748                                         case QUEST_TYPE_TOWER:
7749                                                 sprintf(note,_(" - 全てのモンスターを倒す。", " - Kill all monsters."));
7750                                                 break;
7751                                         }
7752                                 }
7753
7754                                 /* Print the quest info */
7755                                 sprintf(tmp_str, _("  %s (危険度:%d階相当)%s\n", "  %s (Danger level: %d)%s\n"),
7756                                         quest[i].name, (int)quest[i].level, note);
7757
7758                                 fputs(tmp_str, fff);
7759
7760                                 if (quest[i].status == QUEST_STATUS_COMPLETED)
7761                                 {
7762                                         sprintf(tmp_str, _("    クエスト達成 - まだ報酬を受けとってない。\n", "    Quest Completed - Unrewarded\n"));
7763                                         fputs(tmp_str, fff);
7764                                 }
7765                                 else
7766                                 {
7767                                         j = 0;
7768
7769                                         while (quest_text[j][0] && j < 10)
7770                                         {
7771                                                 fprintf(fff, "    %s\n", quest_text[j]);
7772                                                 j++;
7773                                         }
7774                                 }
7775                         }
7776                         else if (quest[i].level < rand_level) /* QUEST_TYPE_RANDOM */
7777                         {
7778                                 /* New random */
7779                                 rand_level = quest[i].level;
7780
7781                                 if (max_dlv[DUNGEON_ANGBAND] >= rand_level)
7782                                 {
7783                                         /* Print the quest info */
7784                                         r_ptr = &r_info[quest[i].r_idx];
7785                                         strcpy(name, r_name + r_ptr->name);
7786
7787                                         if (quest[i].max_num > 1)
7788                                         {
7789 #ifdef JP
7790                                                 sprintf(rand_tmp_str,"  %s (%d 階) - %d 体の%sを倒す。(あと %d 体)\n",
7791                                                         quest[i].name, (int)quest[i].level,
7792                                                         (int)quest[i].max_num, name, (int)(quest[i].max_num - quest[i].cur_num));
7793 #else
7794                                                 plural_aux(name);
7795
7796                                                 sprintf(rand_tmp_str,"  %s (Dungeon level: %d)\n  Kill %d %s, have killed %d.\n",
7797                                                         quest[i].name, (int)quest[i].level,
7798                                                         (int)quest[i].max_num, name, (int)quest[i].cur_num);
7799 #endif
7800                                         }
7801                                         else
7802                                         {
7803                                                 sprintf(rand_tmp_str,_("  %s (%d 階) - %sを倒す。\n", "  %s (Dungeon level: %d)\n  Kill %s.\n"),
7804                                                         quest[i].name, (int)quest[i].level, name);
7805                                         }
7806                                 }
7807                         }
7808                 }
7809         }
7810
7811         /* Print the current random quest  */
7812         if (rand_tmp_str[0]) fputs(rand_tmp_str, fff);
7813
7814         if (!total) fprintf(fff, _("  なし\n", "  Nothing.\n"));
7815 }
7816
7817
7818 static bool do_cmd_knowledge_quests_aux(FILE *fff, IDX q_idx)
7819 {
7820         char tmp_str[120];
7821         char playtime_str[16];
7822         quest_type* const q_ptr = &quest[q_idx];
7823
7824         if (is_fixed_quest_idx(q_idx))
7825         {
7826                 /* Set the quest number temporary */
7827                 IDX old_quest = p_ptr->inside_quest;
7828
7829                 p_ptr->inside_quest = q_idx;
7830
7831                 /* Get the quest */
7832                 init_flags = INIT_NAME_ONLY;
7833
7834                 process_dungeon_file("q_info.txt", 0, 0, 0, 0);
7835
7836                 /* Reset the old quest number */
7837                 p_ptr->inside_quest = old_quest;
7838
7839                 /* No info from "silent" quests */
7840                 if (q_ptr->flags & QUEST_FLAG_SILENT) return FALSE;
7841         }
7842
7843         strnfmt(playtime_str, sizeof(playtime_str), "%02d:%02d:%02d",
7844                 q_ptr->comptime/(60*60), (q_ptr->comptime/60)%60, q_ptr->comptime%60);
7845
7846         if (!is_fixed_quest_idx(q_idx) && q_ptr->r_idx)
7847         {
7848                 /* Print the quest info */
7849                 if (q_ptr->complev == 0)
7850                 {
7851                         sprintf(tmp_str,
7852                                 _("  %-35s (%3d階)            -   不戦勝 - %s\n",
7853                                   "  %-35s (Dungeon level: %3d) - Unearned - %s\n") ,
7854                                 r_name+r_info[q_ptr->r_idx].name,
7855                                 (int)q_ptr->level, playtime_str);
7856                 }
7857                 else
7858                 {
7859                         sprintf(tmp_str,
7860                                 _("  %-35s (%3d階)            - レベル%2d - %s\n",
7861                                   "  %-35s (Dungeon level: %3d) - level %2d - %s\n") ,
7862                                 r_name+r_info[q_ptr->r_idx].name,
7863                                 (int)q_ptr->level,
7864                                 q_ptr->complev,
7865                                 playtime_str);
7866                 }
7867         }
7868         else
7869         {
7870                 /* Print the quest info */
7871                 sprintf(tmp_str,
7872                         _("  %-35s (危険度:%3d階相当) - レベル%2d - %s\n",
7873                           "  %-35s (Danger  level: %3d) - level %2d - %s\n") ,
7874                         q_ptr->name, (int)q_ptr->level, q_ptr->complev, playtime_str);
7875         }
7876
7877         fputs(tmp_str, fff);
7878
7879         return TRUE;
7880 }
7881
7882 /*
7883  * Print all finished quests
7884  */
7885 void do_cmd_knowledge_quests_completed(FILE *fff, QUEST_IDX quest_num[])
7886 {
7887         QUEST_IDX i;
7888         QUEST_IDX total = 0;
7889
7890         fprintf(fff, _("《達成したクエスト》\n", "< Completed Quest >\n"));
7891         for (i = 1; i < max_q_idx; i++)
7892         {
7893                 QUEST_IDX q_idx = quest_num[i];
7894                 quest_type* const q_ptr = &quest[q_idx];
7895
7896                 if (q_ptr->status == QUEST_STATUS_FINISHED && do_cmd_knowledge_quests_aux(fff, q_idx))
7897                 {
7898                         ++total;
7899                 }
7900         }
7901         if (!total) fprintf(fff, _("  なし\n", "  Nothing.\n"));
7902 }
7903
7904
7905 /*
7906  * Print all failed quests
7907  */
7908 void do_cmd_knowledge_quests_failed(FILE *fff, QUEST_IDX quest_num[])
7909 {
7910         QUEST_IDX i;
7911         QUEST_IDX total = 0;
7912
7913         fprintf(fff, _("《失敗したクエスト》\n", "< Failed Quest >\n"));
7914         for (i = 1; i < max_q_idx; i++)
7915         {
7916                 QUEST_IDX q_idx = quest_num[i];
7917                 quest_type* const q_ptr = &quest[q_idx];
7918
7919                 if (((q_ptr->status == QUEST_STATUS_FAILED_DONE) || (q_ptr->status == QUEST_STATUS_FAILED)) &&
7920                     do_cmd_knowledge_quests_aux(fff, q_idx))
7921                 {
7922                         ++total;
7923                 }
7924         }
7925         if (!total) fprintf(fff, _("  なし\n", "  Nothing.\n"));
7926 }
7927
7928
7929 /*
7930  * Print all random quests
7931  */
7932 static void do_cmd_knowledge_quests_wiz_random(FILE *fff)
7933 {
7934         GAME_TEXT tmp_str[120];
7935         QUEST_IDX i;
7936         QUEST_IDX total = 0;
7937
7938         fprintf(fff, _("《残りのランダムクエスト》\n", "< Remaining Random Quest >\n"));
7939         for (i = 1; i < max_q_idx; i++)
7940         {
7941                 /* No info from "silent" quests */
7942                 if (quest[i].flags & QUEST_FLAG_SILENT) continue;
7943
7944                 if ((quest[i].type == QUEST_TYPE_RANDOM) && (quest[i].status == QUEST_STATUS_TAKEN))
7945                 {
7946                         total++;
7947
7948                         /* Print the quest info */
7949                         sprintf(tmp_str, _("  %s (%d階, %s)\n", "  %s (%d, %s)\n"),
7950                                 quest[i].name, (int)quest[i].level, r_name+r_info[quest[i].r_idx].name);
7951                         fputs(tmp_str, fff);
7952                 }
7953         }
7954         if (!total) fprintf(fff, _("  なし\n", "  Nothing.\n"));
7955 }
7956
7957
7958 bool ang_sort_comp_quest_num(vptr u, vptr v, int a, int b)
7959 {
7960         QUEST_IDX *q_num = (QUEST_IDX *)u;
7961         quest_type *qa = &quest[q_num[a]];
7962         quest_type *qb = &quest[q_num[b]];
7963
7964         /* Unused */
7965         (void)v;
7966
7967         return (qa->comptime != qb->comptime) ?
7968                 (qa->comptime < qb->comptime) :
7969                 (qa->level <= qb->level);
7970 }
7971
7972 void ang_sort_swap_quest_num(vptr u, vptr v, int a, int b)
7973 {
7974         QUEST_IDX *q_num = (QUEST_IDX *)u;
7975         QUEST_IDX tmp;
7976
7977         /* Unused */
7978         (void)v;
7979
7980         tmp = q_num[a];
7981         q_num[a] = q_num[b];
7982         q_num[b] = tmp;
7983 }
7984
7985
7986 /*
7987  * Print quest status of all active quests
7988  */
7989 static void do_cmd_knowledge_quests(void)
7990 {
7991         FILE *fff;
7992         GAME_TEXT file_name[1024];
7993         IDX *quest_num;
7994         int dummy;
7995         IDX i;
7996
7997         /* Open a new file */
7998         fff = my_fopen_temp(file_name, 1024);
7999         if (!fff)
8000         {
8001             msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
8002             msg_print(NULL);
8003             return;
8004         }
8005
8006         /* Allocate Memory */
8007         C_MAKE(quest_num, max_q_idx, QUEST_IDX);
8008
8009         /* Sort by compete level */
8010         for (i = 1; i < max_q_idx; i++) quest_num[i] = i;
8011         ang_sort_comp = ang_sort_comp_quest_num;
8012         ang_sort_swap = ang_sort_swap_quest_num;
8013         ang_sort(quest_num, &dummy, max_q_idx);
8014
8015         /* Dump Quest Information */
8016         do_cmd_knowledge_quests_current(fff);
8017         fputc('\n', fff);
8018         do_cmd_knowledge_quests_completed(fff, quest_num);
8019         fputc('\n', fff);
8020         do_cmd_knowledge_quests_failed(fff, quest_num);
8021         if (p_ptr->wizard)
8022         {
8023                 fputc('\n', fff);
8024                 do_cmd_knowledge_quests_wiz_random(fff);
8025         }
8026         my_fclose(fff);
8027
8028         /* Display the file contents */
8029         show_file(TRUE, file_name, _("クエスト達成状況", "Quest status"), 0, 0);
8030         fd_kill(file_name);
8031
8032         /* Free Memory */
8033         C_KILL(quest_num, max_q_idx, QUEST_IDX);
8034 }
8035
8036
8037 /*
8038  * List my home
8039  */
8040 static void do_cmd_knowledge_home(void)
8041 {
8042         FILE *fff;
8043
8044         int i;
8045         GAME_TEXT file_name[1024];
8046         store_type  *st_ptr;
8047         GAME_TEXT o_name[MAX_NLEN];
8048         concptr         paren = ")";
8049
8050         process_dungeon_file("w_info.txt", 0, 0, current_world_ptr->max_wild_y, current_world_ptr->max_wild_x);
8051
8052         /* Open a new file */
8053         fff = my_fopen_temp(file_name, 1024);
8054         if (!fff) {
8055                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
8056                 msg_print(NULL);
8057                 return;
8058         }
8059
8060         if (fff)
8061         {
8062                 /* Print all homes in the different towns */
8063                 st_ptr = &town_info[1].store[STORE_HOME];
8064
8065                 /* Home -- if anything there */
8066                 if (st_ptr->stock_num)
8067                 {
8068 #ifdef JP
8069                         TERM_LEN x = 1;
8070 #endif
8071                         /* Header with name of the town */
8072                         fprintf(fff, _("  [ 我が家のアイテム ]\n", "  [Home Inventory]\n"));
8073
8074                         /* Dump all available items */
8075                         for (i = 0; i < st_ptr->stock_num; i++)
8076                         {
8077 #ifdef JP
8078                                 if ((i % 12) == 0) fprintf(fff, "\n ( %d ページ )\n", x++);
8079                                 object_desc(o_name, &st_ptr->stock[i], 0);
8080                                 if (strlen(o_name) <= 80-3)
8081                                 {
8082                                         fprintf(fff, "%c%s %s\n", I2A(i%12), paren, o_name);
8083                                 }
8084                                 else
8085                                 {
8086                                         int n;
8087                                         char *t;
8088                                         for (n = 0, t = o_name; n < 80-3; n++, t++)
8089                                                 if(iskanji(*t)) {t++; n++;}
8090                                         if (n == 81-3) n = 79-3; /* 最後が漢字半分 */
8091
8092                                         fprintf(fff, "%c%s %.*s\n", I2A(i%12), paren, n, o_name);
8093                                         fprintf(fff, "   %.77s\n", o_name+n);
8094                                 }
8095 #else
8096                                 object_desc(o_name, &st_ptr->stock[i], 0);
8097                                 fprintf(fff, "%c%s %s\n", I2A(i%12), paren, o_name);
8098 #endif
8099
8100                         }
8101
8102                         /* Add an empty line */
8103                         fprintf(fff, "\n\n");
8104                 }
8105         }
8106         my_fclose(fff);
8107
8108         /* Display the file contents */
8109         show_file(TRUE, file_name, _("我が家のアイテム", "Home Inventory"), 0, 0);
8110         fd_kill(file_name);
8111 }
8112
8113
8114 /*
8115  * Check the status of "autopick"
8116  */
8117 static void do_cmd_knowledge_autopick(void)
8118 {
8119         int k;
8120         FILE *fff;
8121         GAME_TEXT file_name[1024];
8122
8123         /* Open a new file */
8124         fff = my_fopen_temp(file_name, 1024);
8125
8126         if (!fff)
8127         {
8128             msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
8129             msg_print(NULL);
8130             return;
8131         }
8132
8133         if (!max_autopick)
8134         {
8135             fprintf(fff, _("自動破壊/拾いには何も登録されていません。", "No preference for auto picker/destroyer."));
8136         }
8137         else
8138         {
8139                 fprintf(fff, _("   自動拾い/破壊には現在 %d行登録されています。\n\n",
8140                                            "   There are %d registered lines for auto picker/destroyer.\n\n"), max_autopick);
8141         }
8142
8143         for (k = 0; k < max_autopick; k++)
8144         {
8145                 concptr tmp;
8146                 byte act = autopick_list[k].action;
8147                 if (act & DONT_AUTOPICK)
8148                 {
8149                         tmp = _("放置", "Leave");
8150                 }
8151                 else if (act & DO_AUTODESTROY)
8152                 {
8153                         tmp = _("破壊", "Destroy");
8154                 }
8155                 else if (act & DO_AUTOPICK)
8156                 {
8157                         tmp = _("拾う", "Pickup");
8158                 }
8159                 else
8160                 {
8161                         tmp = _("確認", "Query");
8162                 }
8163
8164                 if (act & DO_DISPLAY)
8165                         fprintf(fff, "%11s", format("[%s]", tmp));
8166                 else
8167                         fprintf(fff, "%11s", format("(%s)", tmp));
8168
8169                 tmp = autopick_line_from_entry(&autopick_list[k]);
8170                 fprintf(fff, " %s", tmp);
8171                 string_free(tmp);
8172                 fprintf(fff, "\n");
8173         }
8174         my_fclose(fff);
8175         /* Display the file contents */
8176         show_file(TRUE, file_name, _("自動拾い/破壊 設定リスト", "Auto-picker/Destroyer"), 0, 0);
8177         fd_kill(file_name);
8178 }
8179
8180
8181 /*
8182  * Interact with "knowledge"
8183  */
8184 void do_cmd_knowledge(void)
8185 {
8186         int i, p = 0;
8187         bool need_redraw = FALSE;
8188
8189         /* File type is "TEXT" */
8190         FILE_TYPE(FILE_TYPE_TEXT);
8191         screen_save();
8192
8193         /* Interact until done */
8194         while (1)
8195         {
8196                 Term_clear();
8197
8198                 /* Ask for a choice */
8199                 prt(format(_("%d/2 ページ", "page %d/2"), (p+1)), 2, 65);
8200                 prt(_("現在の知識を確認する", "Display current knowledge"), 3, 0);
8201
8202                 /* Give some choices */
8203 #ifdef JP
8204                 if (p == 0)
8205                 {
8206                         prt("(1) 既知の伝説のアイテム                 の一覧", 6, 5);
8207                         prt("(2) 既知のアイテム                       の一覧", 7, 5);
8208                         prt("(3) 既知の生きているユニーク・モンスター の一覧", 8, 5);
8209                         prt("(4) 既知のモンスター                     の一覧", 9, 5);
8210                         prt("(5) 倒した敵の数                         の一覧", 10, 5);
8211                         if (!vanilla_town) prt("(6) 賞金首                               の一覧", 11, 5);
8212                         prt("(7) 現在のペット                         の一覧", 12, 5);
8213                         prt("(8) 我が家のアイテム                     の一覧", 13, 5);
8214                         prt("(9) *鑑定*済み装備の耐性                 の一覧", 14, 5);
8215                         prt("(0) 地形の表示文字/タイル                の一覧", 15, 5);
8216                 }
8217                 else
8218                 {
8219                         prt("(a) 自分に関する情報                     の一覧", 6, 5);
8220                         prt("(b) 突然変異                             の一覧", 7, 5);
8221                         prt("(c) 武器の経験値                         の一覧", 8, 5);
8222                         prt("(d) 魔法の経験値                         の一覧", 9, 5);
8223                         prt("(e) 技能の経験値                         の一覧", 10, 5);
8224                         prt("(f) プレイヤーの徳                       の一覧", 11, 5);
8225                         prt("(g) 入ったダンジョン                     の一覧", 12, 5);
8226                         prt("(h) 実行中のクエスト                     の一覧", 13, 5);
8227                         prt("(i) 現在の自動拾い/破壊設定              の一覧", 14, 5);
8228                 }
8229 #else
8230                 if (p == 0)
8231                 {
8232                         prt("(1) Display known artifacts", 6, 5);
8233                         prt("(2) Display known objects", 7, 5);
8234                         prt("(3) Display remaining uniques", 8, 5);
8235                         prt("(4) Display known monster", 9, 5);
8236                         prt("(5) Display kill count", 10, 5);
8237                         if (!vanilla_town) prt("(6) Display wanted monsters", 11, 5);
8238                         prt("(7) Display current pets", 12, 5);
8239                         prt("(8) Display home inventory", 13, 5);
8240                         prt("(9) Display *identified* equip.", 14, 5);
8241                         prt("(0) Display terrain symbols.", 15, 5);
8242                 }
8243                 else
8244                 {
8245                         prt("(a) Display about yourself", 6, 5);
8246                         prt("(b) Display mutations", 7, 5);
8247                         prt("(c) Display weapon proficiency", 8, 5);
8248                         prt("(d) Display spell proficiency", 9, 5);
8249                         prt("(e) Display misc. proficiency", 10, 5);
8250                         prt("(f) Display virtues", 11, 5);
8251                         prt("(g) Display dungeons", 12, 5);
8252                         prt("(h) Display current quests", 13, 5);
8253                         prt("(i) Display auto pick/destroy", 14, 5);
8254                 }
8255 #endif
8256                 /* Prompt */
8257                 prt(_("-続く-", "-more-"), 17, 8);
8258                 prt(_("ESC) 抜ける", "ESC) Exit menu"), 21, 1);
8259                 prt(_("SPACE) 次ページ", "SPACE) Next page"), 21, 30);
8260                 /*prt("-) 前ページ", 21, 60);*/
8261                 prt(_("コマンド:", "Command: "), 20, 0);
8262                 i = inkey();
8263
8264                 if (i == ESCAPE) break;
8265                 switch (i)
8266                 {
8267                 case ' ': /* Page change */
8268                 case '-':
8269                         p = 1 - p;
8270                         break;
8271                 case '1': /* Artifacts */
8272                         do_cmd_knowledge_artifacts();
8273                         break;
8274                 case '2': /* Objects */
8275                         do_cmd_knowledge_objects(&need_redraw, FALSE, -1);
8276                         break;
8277                 case '3': /* Uniques */
8278                         do_cmd_knowledge_uniques();
8279                         break;
8280                 case '4': /* Monsters */
8281                         do_cmd_knowledge_monsters(&need_redraw, FALSE, -1);
8282                         break;
8283                 case '5': /* Kill count  */
8284                         do_cmd_knowledge_kill_count();
8285                         break;
8286                 case '6': /* wanted */
8287                         if (!vanilla_town) do_cmd_knowledge_kubi();
8288                         break;
8289                 case '7': /* Pets */
8290                         do_cmd_knowledge_pets();
8291                         break;
8292                 case '8': /* Home */
8293                         do_cmd_knowledge_home();
8294                         break;
8295                 case '9': /* Resist list */
8296                         do_cmd_knowledge_inven();
8297                         break;
8298                 case '0': /* Feature list */
8299                         {
8300                                 IDX lighting_level = F_LIT_STANDARD;
8301                                 do_cmd_knowledge_features(&need_redraw, FALSE, -1, &lighting_level);
8302                         }
8303                         break;
8304                 /* Next page */
8305                 case 'a': /* Max stat */
8306                         do_cmd_knowledge_stat();
8307                         break;
8308                 case 'b': /* Mutations */
8309                         do_cmd_knowledge_mutations();
8310                         break;
8311                 case 'c': /* weapon-exp */
8312                         do_cmd_knowledge_weapon_exp();
8313                         break;
8314                 case 'd': /* spell-exp */
8315                         do_cmd_knowledge_spell_exp();
8316                         break;
8317                 case 'e': /* skill-exp */
8318                         do_cmd_knowledge_skill_exp();
8319                         break;
8320                 case 'f': /* Virtues */
8321                         do_cmd_knowledge_virtues();
8322                         break;
8323                 case 'g': /* Dungeon */
8324                         do_cmd_knowledge_dungeon();
8325                         break;
8326                 case 'h': /* Quests */
8327                         do_cmd_knowledge_quests();
8328                         break;
8329                 case 'i': /* Autopick */
8330                         do_cmd_knowledge_autopick();
8331                         break;
8332                 default: /* Unknown option */
8333                         bell();
8334                 }
8335
8336                 msg_erase();
8337         }
8338         screen_load();
8339
8340         if (need_redraw) do_cmd_redraw();
8341 }
8342
8343
8344 /*
8345  * Check on the status of an active quest
8346  */
8347 void do_cmd_checkquest(void)
8348 {
8349         /* File type is "TEXT" */
8350         FILE_TYPE(FILE_TYPE_TEXT);
8351         screen_save();
8352
8353         /* Quest info */
8354         do_cmd_knowledge_quests();
8355         screen_load();
8356 }
8357
8358
8359 /*
8360  * Display the time and date
8361  */
8362 void do_cmd_time(void)
8363 {
8364         int day, hour, min, full, start, end, num;
8365         char desc[1024];
8366
8367         char buf[1024];
8368         char day_buf[10];
8369
8370         FILE *fff;
8371
8372         extract_day_hour_min(&day, &hour, &min);
8373
8374         full = hour * 100 + min;
8375
8376         start = 9999;
8377         end = -9999;
8378
8379         num = 0;
8380
8381         strcpy(desc, _("変な時刻だ。", "It is a strange time."));
8382
8383         if (day < MAX_DAYS) sprintf(day_buf, "%d", day);
8384         else strcpy(day_buf, "*****");
8385
8386         msg_format(_("%s日目, 時刻は%d:%02d %sです。", "This is day %s. The time is %d:%02d %s."),
8387                    day_buf, (hour % 12 == 0) ? 12 : (hour % 12), min, (hour < 12) ? "AM" : "PM");
8388
8389         /* Find the path */
8390         if (!randint0(10) || p_ptr->image)
8391         {
8392                 path_build(buf, sizeof(buf), ANGBAND_DIR_FILE, _("timefun_j.txt", "timefun.txt"));
8393         }
8394         else
8395         {
8396                 path_build(buf, sizeof(buf), ANGBAND_DIR_FILE, _("timenorm_j.txt", "timenorm.txt"));
8397         }
8398
8399         /* Open this file */
8400         fff = my_fopen(buf, "rt");
8401
8402         if (!fff) return;
8403
8404         /* Find this time */
8405         while (!my_fgets(fff, buf, sizeof(buf)))
8406         {
8407                 /* Ignore comments */
8408                 if (!buf[0] || (buf[0] == '#')) continue;
8409
8410                 /* Ignore invalid lines */
8411                 if (buf[1] != ':') continue;
8412
8413                 /* Process 'Start' */
8414                 if (buf[0] == 'S')
8415                 {
8416                         /* Extract the starting time */
8417                         start = atoi(buf + 2);
8418
8419                         /* Assume valid for an hour */
8420                         end = start + 59;
8421
8422                         /* Next... */
8423                         continue;
8424                 }
8425
8426                 /* Process 'End' */
8427                 if (buf[0] == 'E')
8428                 {
8429                         /* Extract the ending time */
8430                         end = atoi(buf + 2);
8431
8432                         /* Next... */
8433                         continue;
8434                 }
8435
8436                 /* Ignore incorrect range */
8437                 if ((start > full) || (full > end)) continue;
8438
8439                 /* Process 'Description' */
8440                 if (buf[0] == 'D')
8441                 {
8442                         num++;
8443
8444                         /* Apply the randomizer */
8445                         if (!randint0(num)) strcpy(desc, buf + 2);
8446
8447                         /* Next... */
8448                         continue;
8449                 }
8450         }
8451
8452         msg_print(desc);
8453         my_fclose(fff);
8454 }