OSDN Git Service

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