OSDN Git Service

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