OSDN Git Service

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