OSDN Git Service

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