OSDN Git Service

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