OSDN Git Service

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