OSDN Git Service

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