OSDN Git Service

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