OSDN Git Service

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