OSDN Git Service

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