OSDN Git Service

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