OSDN Git Service

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