OSDN Git Service

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