OSDN Git Service

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