OSDN Git Service

Merge branch 'For2.2.2-Refactoring' of git.osdn.net:/gitroot/hengband/hengband into...
[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 "cmd-dump.h"
44 #include "term.h"
45 #include "core.h"
46 #include "core/show-file.h"
47 #include "io/read-pref-file.h"
48 #include "io/write-diary.h"
49 #include "chuukei.h"
50
51 #include "autopick.h"
52
53 #include "inet.h"
54 #include "birth.h"
55 #include "dungeon.h"
56 #include "world.h"
57 #include "view/display-player.h"
58 #include "player/process-name.h"
59 #include "player-effects.h"
60 #include "player-status.h"
61 #include "player-skill.h"
62 #include "player-personality.h"
63 #include "sort.h"
64 #include "mutation.h"
65 #include "quest.h"
66 #include "store.h"
67 #include "artifact.h"
68 #include "avatar.h"
69 #include "object-flavor.h"
70 #include "object-hook.h"
71 #include "monster.h"
72 #include "monster-status.h"
73 #include "view-mainwindow.h"
74 #include "dungeon-file.h"
75 #include "io/interpret-pref-file.h"
76 #include "files.h"
77 #include "spells.h"
78 #include "objectkind.h"
79 #include "floor-town.h"
80 #include "cmd/feeling-table.h"
81 #include "cmd/monster-group-table.h"
82 #include "cmd/diary-subtitle-table.h"
83 #include "cmd/object-group-table.h"
84 #include "view-mainwindow.h" // 暫定。後で消す
85
86 #include "english.h"
87
88 // Mark strings for auto dump
89 static char auto_dump_header[] = "# vvvvvvv== %s ==vvvvvvv";
90 static char auto_dump_footer[] = "# ^^^^^^^== %s ==^^^^^^^";
91
92 // Variables for auto dump
93 static FILE *auto_dump_stream;
94 static concptr auto_dump_mark;
95 static int auto_dump_line_num;
96
97 static void do_cmd_knowledge_monsters(player_type *creature_ptr, bool *need_redraw, bool visual_only, IDX direct_r_idx);
98 static void do_cmd_knowledge_objects(player_type *creature_ptr, bool *need_redraw, bool visual_only, IDX direct_k_idx);
99 static void do_cmd_knowledge_features(bool *need_redraw, bool visual_only, IDX direct_f_idx, IDX *lighting_level);
100
101 // Clipboard variables for copy&paste in visual mode
102 static TERM_COLOR attr_idx = 0;
103 static SYMBOL_CODE char_idx = 0;
104
105 static TERM_COLOR attr_idx_feat[F_LIT_MAX];
106 static SYMBOL_CODE char_idx_feat[F_LIT_MAX];
107
108 // Encode the screen colors
109 static char hack[17] = "dwsorgbuDWvyRGBU";
110
111 /*!
112  * @brief prf出力内容を消去する /
113  * Remove old lines automatically generated before.
114  * @param orig_file 消去を行うファイル名
115  */
116 static void remove_auto_dump(concptr orig_file)
117 {
118         FILE *tmp_fff, *orig_fff;
119         char tmp_file[1024];
120         char buf[1024];
121         bool between_mark = FALSE;
122         bool changed = FALSE;
123         int line_num = 0;
124         long header_location = 0;
125         char header_mark_str[80];
126         char footer_mark_str[80];
127
128         sprintf(header_mark_str, auto_dump_header, auto_dump_mark);
129         sprintf(footer_mark_str, auto_dump_footer, auto_dump_mark);
130         size_t mark_len = strlen(footer_mark_str);
131         orig_fff = my_fopen(orig_file, "r");
132         if (!orig_fff) return;
133
134         tmp_fff = my_fopen_temp(tmp_file, 1024);
135         if (!tmp_fff)
136         {
137                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), tmp_file);
138                 msg_print(NULL);
139                 return;
140         }
141
142         while (TRUE)
143         {
144                 if (my_fgets(orig_fff, buf, sizeof(buf)))
145                 {
146                         if (between_mark)
147                         {
148                                 fseek(orig_fff, header_location, SEEK_SET);
149                                 between_mark = FALSE;
150                                 continue;
151                         }
152                         else
153                         {
154                                 break;
155                         }
156                 }
157
158                 if (!between_mark)
159                 {
160                         if (!strcmp(buf, header_mark_str))
161                         {
162                                 header_location = ftell(orig_fff);
163                                 line_num = 0;
164                                 between_mark = TRUE;
165                                 changed = TRUE;
166                         }
167                         else
168                         {
169                                 fprintf(tmp_fff, "%s\n", buf);
170                         }
171
172                         continue;
173                 }
174
175                 if (!strncmp(buf, footer_mark_str, mark_len))
176                 {
177                         int tmp;
178                         if (!sscanf(buf + mark_len, " (%d)", &tmp)
179                                 || tmp != line_num)
180                         {
181                                 fseek(orig_fff, header_location, SEEK_SET);
182                         }
183
184                         between_mark = FALSE;
185                         continue;
186                 }
187
188                 line_num++;
189         }
190
191         my_fclose(orig_fff);
192         my_fclose(tmp_fff);
193
194         if (changed)
195         {
196                 tmp_fff = my_fopen(tmp_file, "r");
197                 orig_fff = my_fopen(orig_file, "w");
198                 while (!my_fgets(tmp_fff, buf, sizeof(buf)))
199                         fprintf(orig_fff, "%s\n", buf);
200
201                 my_fclose(orig_fff);
202                 my_fclose(tmp_fff);
203         }
204
205         fd_kill(tmp_file);
206 }
207
208
209 /*!
210  * @brief prfファイルのフォーマットに従った内容を出力する /
211  * Dump a formatted line, using "vstrnfmt()".
212  * @param fmt 出力内容
213  */
214 static void auto_dump_printf(concptr fmt, ...)
215 {
216         va_list vp;
217         char buf[1024];
218         va_start(vp, fmt);
219         (void)vstrnfmt(buf, sizeof(buf), fmt, vp);
220         va_end(vp);
221         for (concptr p = buf; *p; p++)
222         {
223                 if (*p == '\n') auto_dump_line_num++;
224         }
225
226         fprintf(auto_dump_stream, "%s", buf);
227 }
228
229
230 /*!
231  * @brief prfファイルをファイルオープンする /
232  * Open file to append auto dump.
233  * @param buf ファイル名
234  * @param mark 出力するヘッダマーク
235  * @return ファイルポインタを取得できたらTRUEを返す
236  */
237 static bool open_auto_dump(concptr buf, concptr mark)
238 {
239         char header_mark_str[80];
240         auto_dump_mark = mark;
241         sprintf(header_mark_str, auto_dump_header, auto_dump_mark);
242         remove_auto_dump(buf);
243         auto_dump_stream = my_fopen(buf, "a");
244         if (!auto_dump_stream)
245         {
246                 msg_format(_("%s を開くことができませんでした。", "Failed to open %s."), buf);
247                 msg_print(NULL);
248                 return FALSE;
249         }
250
251         fprintf(auto_dump_stream, "%s\n", header_mark_str);
252         auto_dump_line_num = 0;
253         auto_dump_printf(_("# *警告!!* 以降の行は自動生成されたものです。\n",
254                 "# *Warning!*  The lines below are an automatic dump.\n"));
255         auto_dump_printf(_("# *警告!!* 後で自動的に削除されるので編集しないでください。\n",
256                 "# Don't edit them; changes will be deleted and replaced automatically.\n"));
257         return TRUE;
258 }
259
260 /*!
261  * @brief prfファイルをファイルクローズする /
262  * Append foot part and close auto dump.
263  * @return なし
264  */
265 static void close_auto_dump(void)
266 {
267         char footer_mark_str[80];
268         sprintf(footer_mark_str, auto_dump_footer, auto_dump_mark);
269         auto_dump_printf(_("# *警告!!* 以降の行は自動生成されたものです。\n",
270                 "# *Warning!*  The lines below are an automatic dump.\n"));
271         auto_dump_printf(_("# *警告!!* 後で自動的に削除されるので編集しないでください。\n",
272                 "# Don't edit them; changes will be deleted and replaced automatically.\n"));
273         fprintf(auto_dump_stream, "%s (%d)\n", footer_mark_str, auto_dump_line_num);
274         my_fclose(auto_dump_stream);
275 }
276
277
278 #ifdef JP
279 #else
280 /*!
281  * @brief Return suffix of ordinal number
282  * @param num number
283  * @return pointer of suffix string.
284  */
285 concptr get_ordinal_number_suffix(int num)
286 {
287         num = ABS(num) % 100;
288         switch (num % 10)
289         {
290         case 1:
291                 return (num == 11) ? "th" : "st";
292         case 2:
293                 return (num == 12) ? "th" : "nd";
294         case 3:
295                 return (num == 13) ? "th" : "rd";
296         default:
297                 return "th";
298         }
299 }
300 #endif
301
302
303 /*!
304  * @brief 日記のタイトル表記と内容出力
305  * @param creature_ptr プレーヤーへの参照ポインタ
306  * @return なし
307  */
308 static void display_diary(player_type *creature_ptr)
309 {
310         char diary_title[256];
311         GAME_TEXT file_name[MAX_NLEN];
312         char buf[1024];
313         char tmp[80];
314         sprintf(file_name, _("playrecord-%s.txt", "playrec-%s.txt"), savefile_base);
315         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, file_name);
316
317         if (creature_ptr->pclass == CLASS_WARRIOR || creature_ptr->pclass == CLASS_MONK || creature_ptr->pclass == CLASS_SAMURAI || creature_ptr->pclass == CLASS_BERSERKER)
318                 strcpy(tmp, subtitle[randint0(MAX_SUBTITLE - 1)]);
319         else if (IS_WIZARD_CLASS(creature_ptr))
320                 strcpy(tmp, subtitle[randint0(MAX_SUBTITLE - 1) + 1]);
321         else strcpy(tmp, subtitle[randint0(MAX_SUBTITLE - 2) + 1]);
322
323 #ifdef JP
324         sprintf(diary_title, "「%s%s%sの伝説 -%s-」", ap_ptr->title, ap_ptr->no ? "の" : "", creature_ptr->name, tmp);
325 #else
326         sprintf(diary_title, "Legend of %s %s '%s'", ap_ptr->title, creature_ptr->name, tmp);
327 #endif
328
329         (void)show_file(creature_ptr, FALSE, buf, diary_title, -1, 0);
330 }
331
332
333 /*!
334  * @brief 日記に任意の内容を表記するコマンドのメインルーチン /
335  * @return なし
336  */
337 static void add_diary_note(player_type *creature_ptr)
338 {
339         char tmp[80] = "\0";
340         char bunshou[80] = "\0";
341         if (get_string(_("内容: ", "diary note: "), tmp, 79))
342         {
343                 strcpy(bunshou, tmp);
344                 exe_write_diary(creature_ptr, DIARY_DESCRIPTION, 0, bunshou);
345         }
346 }
347
348 /*!
349  * @brief 最後に取得したアイテムの情報を日記に追加するメインルーチン /
350  * @return なし
351  */
352 static void do_cmd_last_get(player_type *creaute_ptr)
353 {
354         if (record_o_name[0] == '\0') return;
355
356         char buf[256];
357         sprintf(buf, _("%sの入手を記録します。", "Do you really want to record getting %s? "), record_o_name);
358         if (!get_check(buf)) return;
359
360         GAME_TURN turn_tmp = current_world_ptr->game_turn;
361         current_world_ptr->game_turn = record_turn;
362         sprintf(buf, _("%sを手に入れた。", "discover %s."), record_o_name);
363         exe_write_diary(creaute_ptr, DIARY_DESCRIPTION, 0, buf);
364         current_world_ptr->game_turn = turn_tmp;
365 }
366
367
368 /*!
369  * @brief ファイル中の全日記記録を消去する /
370  * @return なし
371  */
372 static void do_cmd_erase_diary(void)
373 {
374         GAME_TEXT file_name[MAX_NLEN];
375         char buf[256];
376         FILE *fff = NULL;
377
378         if (!get_check(_("本当に記録を消去しますか?", "Do you really want to delete all your record? "))) return;
379         sprintf(file_name, _("playrecord-%s.txt", "playrec-%s.txt"), savefile_base);
380         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, file_name);
381         fd_kill(buf);
382
383         fff = my_fopen(buf, "w");
384         if (fff)
385         {
386                 my_fclose(fff);
387                 msg_format(_("記録を消去しました。", "deleted record."));
388         }
389         else
390         {
391                 msg_format(_("%s の消去に失敗しました。", "failed to delete %s."), buf);
392         }
393
394         msg_print(NULL);
395 }
396
397
398 /*!
399  * @brief 日記コマンド
400  * @param crerature_ptr プレーヤーへの参照ポインタ
401  * @return なし
402  */
403 void do_cmd_diary(player_type *creature_ptr)
404 {
405         FILE_TYPE(FILE_TYPE_TEXT);
406         screen_save();
407         int i;
408         while (TRUE)
409         {
410                 Term_clear();
411                 prt(_("[ 記録の設定 ]", "[ Play Record ]"), 2, 0);
412                 prt(_("(1) 記録を見る", "(1) Display your record"), 4, 5);
413                 prt(_("(2) 文章を記録する", "(2) Add record"), 5, 5);
414                 prt(_("(3) 直前に入手又は鑑定したものを記録する", "(3) Record the last item you got or identified"), 6, 5);
415                 prt(_("(4) 記録を消去する", "(4) Delete your record"), 7, 5);
416                 prt(_("(R) プレイ動画を記録する/中止する", "(R) Record playing movie / or stop it"), 9, 5);
417                 prt(_("コマンド:", "Command: "), 18, 0);
418                 i = inkey();
419                 if (i == ESCAPE) break;
420
421                 switch (i)
422                 {
423                 case '1':
424                         display_diary(creature_ptr);
425                         break;
426                 case '2':
427                         add_diary_note(creature_ptr);
428                         break;
429                 case '3':
430                         do_cmd_last_get(creature_ptr);
431                         break;
432                 case '4':
433                         do_cmd_erase_diary();
434                         break;
435                 case 'r': case 'R':
436                         screen_load();
437                         prepare_movie_hooks();
438                         return;
439                 default:
440                         bell();
441                 }
442
443                 msg_erase();
444         }
445
446         screen_load();
447 }
448
449
450 /*!
451  * @brief 画面を再描画するコマンドのメインルーチン
452  * Hack -- redraw the screen
453  * @param creature_ptr プレーヤーへの参照ポインタ
454  * @return なし
455  * @details
456  * <pre>
457  * This command performs various low level updates, clears all the "extra"
458  * windows, does a total redraw of the main window, and requests all of the
459  * interesting updates and redraws that I can think of.
460  *
461  * This command is also used to "instantiate" the results of the user
462  * selecting various things, such as graphics mode, so it must call
463  * the "TERM_XTRA_REACT" hook before redrawing the windows.
464  * </pre>
465  */
466 void do_cmd_redraw(player_type *creature_ptr)
467 {
468         Term_xtra(TERM_XTRA_REACT, 0);
469
470         creature_ptr->update |= (PU_COMBINE | PU_REORDER);
471         creature_ptr->update |= (PU_TORCH);
472         creature_ptr->update |= (PU_BONUS | PU_HP | PU_MANA | PU_SPELLS);
473         creature_ptr->update |= (PU_UN_VIEW | PU_UN_LITE);
474         creature_ptr->update |= (PU_VIEW | PU_LITE | PU_MON_LITE);
475         creature_ptr->update |= (PU_MONSTERS);
476
477         creature_ptr->redraw |= (PR_WIPE | PR_BASIC | PR_EXTRA | PR_MAP | PR_EQUIPPY);
478
479         creature_ptr->window |= (PW_INVEN | PW_EQUIP | PW_SPELL | PW_PLAYER);
480         creature_ptr->window |= (PW_MESSAGE | PW_OVERHEAD | PW_DUNGEON | PW_MONSTER | PW_OBJECT);
481
482         update_playtime();
483         handle_stuff(creature_ptr);
484         if (creature_ptr->prace == RACE_ANDROID) calc_android_exp(creature_ptr);
485
486         term *old = Term;
487         for (int j = 0; j < 8; j++)
488         {
489                 if (!angband_term[j]) continue;
490
491                 Term_activate(angband_term[j]);
492                 Term_redraw();
493                 Term_fresh();
494                 Term_activate(old);
495         }
496 }
497
498
499 /*!
500  * @brief プレイヤーのステータス表示
501  * @return なし
502  */
503 void do_cmd_player_status(player_type *creature_ptr)
504 {
505         int mode = 0;
506         char tmp[160];
507         screen_save();
508         while (TRUE)
509         {
510                 update_playtime();
511                 display_player(creature_ptr, mode, map_name);
512
513                 if (mode == 4)
514                 {
515                         mode = 0;
516                         display_player(creature_ptr, mode, map_name);
517                 }
518
519                 Term_putstr(2, 23, -1, TERM_WHITE,
520                         _("['c'で名前変更, 'f'でファイルへ書出, 'h'でモード変更, ESCで終了]", "['c' to change name, 'f' to file, 'h' to change mode, or ESC]"));
521                 char c = inkey();
522                 if (c == ESCAPE) break;
523
524                 if (c == 'c')
525                 {
526                         get_name(creature_ptr);
527                         process_player_name(creature_ptr, FALSE);
528                 }
529                 else if (c == 'f')
530                 {
531                         sprintf(tmp, "%s.txt", creature_ptr->base_name);
532                         if (get_string(_("ファイル名: ", "File name: "), tmp, 80))
533                         {
534                                 if (tmp[0] && (tmp[0] != ' '))
535                                 {
536                                         file_character(creature_ptr, tmp, update_playtime, display_player, map_name);
537                                 }
538                         }
539                 }
540                 else if (c == 'h')
541                 {
542                         mode++;
543                 }
544                 else
545                 {
546                         bell();
547                 }
548
549                 msg_erase();
550         }
551
552         screen_load();
553         creature_ptr->redraw |= (PR_WIPE | PR_BASIC | PR_EXTRA | PR_MAP | PR_EQUIPPY);
554         handle_stuff(creature_ptr);
555 }
556
557
558 /*!
559  * @brief 最近表示されたメッセージを再表示するコマンドのメインルーチン
560  * Recall the most recent message
561  * @return なし
562  */
563 void do_cmd_message_one(void)
564 {
565         prt(format("> %s", message_str(0)), 0, 0);
566 }
567
568
569 /*!
570  * @brief メッセージのログを表示するコマンドのメインルーチン
571  * Recall the most recent message
572  * @return なし
573  * @details
574  * <pre>
575  * Show previous messages to the user   -BEN-
576  *
577  * The screen format uses line 0 and 23 for headers and prompts,
578  * skips line 1 and 22, and uses line 2 thru 21 for old messages.
579  *
580  * This command shows you which commands you are viewing, and allows
581  * you to "search" for strings in the recall.
582  *
583  * Note that messages may be longer than 80 characters, but they are
584  * displayed using "infinite" length, with a special sub-command to
585  * "slide" the virtual display to the left or right.
586  *
587  * Attempt to only hilite the matching portions of the string.
588  * </pre>
589  */
590 void do_cmd_messages(int num_now)
591 {
592         char shower_str[81];
593         char finder_str[81];
594         char back_str[81];
595         concptr shower = NULL;
596         int wid, hgt;
597         Term_get_size(&wid, &hgt);
598         int num_lines = hgt - 4;
599         strcpy(finder_str, "");
600         strcpy(shower_str, "");
601         int n = message_num();
602         int i = 0;
603         screen_save();
604         Term_clear();
605         while (TRUE)
606         {
607                 int j;
608                 int skey;
609                 for (j = 0; (j < num_lines) && (i + j < n); j++)
610                 {
611                         concptr msg = message_str(i + j);
612                         c_prt((i + j < num_now ? TERM_WHITE : TERM_SLATE), msg, num_lines + 1 - j, 0);
613                         if (!shower || !shower[0]) continue;
614
615                         concptr str = msg;
616                         while ((str = my_strstr(str, shower)) != NULL)
617                         {
618                                 int len = strlen(shower);
619                                 Term_putstr(str - msg, num_lines + 1 - j, len, TERM_YELLOW, shower);
620                                 str += len;
621                         }
622                 }
623
624                 for (; j < num_lines; j++)
625                         Term_erase(0, num_lines + 1 - j, 255);
626
627                 prt(format(_("以前のメッセージ %d-%d 全部で(%d)", "Message Recall (%d-%d of %d)"),
628                         i, i + j - 1, n), 0, 0);
629                 prt(_("[ 'p' で更に古いもの, 'n' で更に新しいもの, '/' で検索, ESC で中断 ]",
630                         "[Press 'p' for older, 'n' for newer, ..., or ESCAPE]"), hgt - 1, 0);
631                 skey = inkey_special(TRUE);
632                 if (skey == ESCAPE) break;
633
634                 j = i;
635                 switch (skey)
636                 {
637                 case '=':
638                         prt(_("強調: ", "Show: "), hgt - 1, 0);
639                         strcpy(back_str, shower_str);
640                         if (askfor(shower_str, 80))
641                                 shower = shower_str[0] ? shower_str : NULL;
642                         else
643                                 strcpy(shower_str, back_str);
644
645                         continue;
646                 case '/':
647                 case KTRL('s'):
648                 {
649                         prt(_("検索: ", "Find: "), hgt - 1, 0);
650                         strcpy(back_str, finder_str);
651                         if (!askfor(finder_str, 80))
652                         {
653                                 strcpy(finder_str, back_str);
654                                 continue;
655                         }
656                         else if (!finder_str[0])
657                         {
658                                 shower = NULL;
659                                 continue;
660                         }
661
662                         shower = finder_str;
663                         for (int z = i + 1; z < n; z++)
664                         {
665                                 concptr msg = message_str(z);
666                                 if (my_strstr(msg, finder_str))
667                                 {
668                                         i = z;
669                                         break;
670                                 }
671                         }
672                 }
673
674                 break;
675
676                 case SKEY_TOP:
677                         i = n - num_lines;
678                         break;
679                 case SKEY_BOTTOM:
680                         i = 0;
681                         break;
682                 case '8':
683                 case SKEY_UP:
684                 case '\n':
685                 case '\r':
686                         i = MIN(i + 1, n - num_lines);
687                         break;
688                 case '+':
689                         i = MIN(i + 10, n - num_lines);
690                         break;
691                 case 'p':
692                 case KTRL('P'):
693                 case ' ':
694                 case SKEY_PGUP:
695                         i = MIN(i + num_lines, n - num_lines);
696                         break;
697                 case 'n':
698                 case KTRL('N'):
699                 case SKEY_PGDOWN:
700                         i = MAX(0, i - num_lines);
701                         break;
702                 case '-':
703                         i = MAX(0, i - 10);
704                         break;
705                 case '2':
706                 case SKEY_DOWN:
707                         i = MAX(0, i - 1);
708                         break;
709                 }
710
711                 if (i == j) bell();
712         }
713
714         screen_load();
715 }
716
717
718 /*!
719  * @brief prefファイルを選択して処理する /
720  * Ask for a "user pref line" and process it
721  * @param creature_ptr プレーヤーへの参照ポインタ
722  * @return なし
723  * @details
724  * Allow absolute file names?
725  */
726 void do_cmd_pref(player_type *creature_ptr)
727 {
728         char buf[80];
729         strcpy(buf, "");
730         if (!get_string(_("設定変更コマンド: ", "Pref: "), buf, 80)) return;
731
732         (void)interpret_pref_file(creature_ptr, buf);
733 }
734
735
736 /*!
737  * @brief 自動拾い設定ファイルをロードするコマンドのメインルーチン /
738  * @param creature_ptr プレーヤーへの参照ポインタ
739  * @return なし
740  */
741 void do_cmd_reload_autopick(player_type *creature_ptr)
742 {
743         if (!get_check(_("自動拾い設定ファイルをロードしますか? ", "Reload auto-pick preference file? ")))
744                 return;
745
746         autopick_load_pref(creature_ptr, TRUE);
747 }
748
749
750 /*!
751  * @brief マクロ情報をprefファイルに保存する /
752  * @param fname ファイル名
753  * @return なし
754  */
755 static errr macro_dump(concptr fname)
756 {
757         static concptr mark = "Macro Dump";
758         char buf[1024];
759         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, fname);
760         FILE_TYPE(FILE_TYPE_TEXT);
761         if (!open_auto_dump(buf, mark)) return -1;
762
763         auto_dump_printf(_("\n# 自動マクロセーブ\n\n", "\n# Automatic macro dump\n\n"));
764         for (int i = 0; i < macro__num; i++)
765         {
766                 ascii_to_text(buf, macro__act[i]);
767                 auto_dump_printf("A:%s\n", buf);
768                 ascii_to_text(buf, macro__pat[i]);
769                 auto_dump_printf("P:%s\n", buf);
770                 auto_dump_printf("\n");
771         }
772
773         close_auto_dump();
774         return 0;
775 }
776
777
778 /*!
779  * @brief マクロのトリガーキーを取得する /
780  * Hack -- ask for a "trigger" (see below)
781  * @param buf キー表記を保管するバッファ
782  * @return なし
783  * @details
784  * <pre>
785  * Note the complex use of the "inkey()" function from "util.c".
786  *
787  * Note that both "flush()" calls are extremely important.
788  * </pre>
789  */
790 static void do_cmd_macro_aux(char *buf)
791 {
792         flush();
793         inkey_base = TRUE;
794         char i = inkey();
795         int n = 0;
796         while (i)
797         {
798                 buf[n++] = i;
799                 inkey_base = TRUE;
800                 inkey_scan = TRUE;
801                 i = inkey();
802         }
803
804         buf[n] = '\0';
805         flush();
806         char tmp[1024];
807         ascii_to_text(tmp, buf);
808         Term_addstr(-1, TERM_WHITE, tmp);
809 }
810
811
812 /*!
813  * @brief マクロのキー表記からアスキーコードを得てターミナルに表示する /
814  * Hack -- ask for a keymap "trigger" (see below)
815  * @param buf キー表記を取得するバッファ
816  * @return なし
817  * @details
818  * <pre>
819  * Note that both "flush()" calls are extremely important.  This may
820  * no longer be true, since "util.c" is much simpler now.
821  * </pre>
822  */
823 static void do_cmd_macro_aux_keymap(char *buf)
824 {
825         char tmp[1024];
826         flush();
827         buf[0] = inkey();
828         buf[1] = '\0';
829         ascii_to_text(tmp, buf);
830         Term_addstr(-1, TERM_WHITE, tmp);
831         flush();
832 }
833
834
835 /*!
836  * @brief キーマップをprefファイルにダンプする /
837  * Hack -- append all keymaps to the given file
838  * @param fname ファイルネーム
839  * @return エラーコード
840  * @details
841  */
842 static errr keymap_dump(concptr fname)
843 {
844         static concptr mark = "Keymap Dump";
845         char key[1024];
846         char buf[1024];
847         BIT_FLAGS mode;
848         if (rogue_like_commands)
849         {
850                 mode = KEYMAP_MODE_ROGUE;
851         }
852         else
853         {
854                 mode = KEYMAP_MODE_ORIG;
855         }
856
857         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, fname);
858         FILE_TYPE(FILE_TYPE_TEXT);
859         if (!open_auto_dump(buf, mark)) return -1;
860
861         auto_dump_printf(_("\n# 自動キー配置セーブ\n\n", "\n# Automatic keymap dump\n\n"));
862         for (int i = 0; i < 256; i++)
863         {
864                 concptr act;
865                 act = keymap_act[mode][i];
866                 if (!act) continue;
867
868                 buf[0] = (char)i;
869                 buf[1] = '\0';
870                 ascii_to_text(key, buf);
871                 ascii_to_text(buf, act);
872                 auto_dump_printf("A:%s\n", buf);
873                 auto_dump_printf("C:%d:%s\n", mode, key);
874         }
875
876         close_auto_dump();
877         return 0;
878 }
879
880
881 /*!
882  * @brief マクロを設定するコマンドのメインルーチン /
883  * Interact with "macros"
884  * @return なし
885  * @details
886  * <pre>
887  * Note that the macro "action" must be defined before the trigger.
888  *
889  * Could use some helpful instructions on this page.
890  * </pre>
891  */
892 void do_cmd_macros(player_type *creature_ptr)
893 {
894         char tmp[1024];
895         char buf[1024];
896         BIT_FLAGS mode;
897         if (rogue_like_commands)
898         {
899                 mode = KEYMAP_MODE_ROGUE;
900         }
901         else
902         {
903                 mode = KEYMAP_MODE_ORIG;
904         }
905
906         FILE_TYPE(FILE_TYPE_TEXT);
907         screen_save();
908         while (TRUE)
909         {
910                 Term_clear();
911                 prt(_("[ マクロの設定 ]", "Interact with Macros"), 2, 0);
912                 prt(_("マクロ行動が(もしあれば)下に表示されます:", "Current action (if any) shown below:"), 20, 0);
913                 ascii_to_text(buf, macro__buf);
914                 prt(buf, 22, 0);
915
916                 prt(_("(1) ユーザー設定ファイルのロード", "(1) Load a user pref file"), 4, 5);
917                 prt(_("(2) ファイルにマクロを追加", "(2) Append macros to a file"), 5, 5);
918                 prt(_("(3) マクロの確認", "(3) Query a macro"), 6, 5);
919                 prt(_("(4) マクロの作成", "(4) Create a macro"), 7, 5);
920                 prt(_("(5) マクロの削除", "(5) Remove a macro"), 8, 5);
921                 prt(_("(6) ファイルにキー配置を追加", "(6) Append keymaps to a file"), 9, 5);
922                 prt(_("(7) キー配置の確認", "(7) Query a keymap"), 10, 5);
923                 prt(_("(8) キー配置の作成", "(8) Create a keymap"), 11, 5);
924                 prt(_("(9) キー配置の削除", "(9) Remove a keymap"), 12, 5);
925                 prt(_("(0) マクロ行動の入力", "(0) Enter a new action"), 13, 5);
926
927                 prt(_("コマンド: ", "Command: "), 16, 0);
928                 int i = inkey();
929                 if (i == ESCAPE) break;
930
931                 else if (i == '1')
932                 {
933                         prt(_("コマンド: ユーザー設定ファイルのロード", "Command: Load a user pref file"), 16, 0);
934                         prt(_("ファイル: ", "File: "), 18, 0);
935                         sprintf(tmp, "%s.prf", creature_ptr->base_name);
936                         if (!askfor(tmp, 80)) continue;
937
938                         errr err = process_pref_file(creature_ptr, tmp);
939                         if (-2 == err)
940                                 msg_format(_("標準の設定ファイル'%s'を読み込みました。", "Loaded default '%s'."), tmp);
941                         else if (err)
942                                 msg_format(_("'%s'の読み込みに失敗しました!", "Failed to load '%s'!"), tmp);
943                         else
944                                 msg_format(_("'%s'を読み込みました。", "Loaded '%s'."), tmp);
945                 }
946                 else if (i == '2')
947                 {
948                         prt(_("コマンド: マクロをファイルに追加する", "Command: Append macros to a file"), 16, 0);
949                         prt(_("ファイル: ", "File: "), 18, 0);
950                         sprintf(tmp, "%s.prf", creature_ptr->base_name);
951                         if (!askfor(tmp, 80)) continue;
952
953                         (void)macro_dump(tmp);
954                         msg_print(_("マクロを追加しました。", "Appended macros."));
955                 }
956                 else if (i == '3')
957                 {
958                         prt(_("コマンド: マクロの確認", "Command: Query a macro"), 16, 0);
959                         prt(_("トリガーキー: ", "Trigger: "), 18, 0);
960                         do_cmd_macro_aux(buf);
961                         int k = macro_find_exact(buf);
962                         if (k < 0)
963                         {
964                                 msg_print(_("そのキーにはマクロは定義されていません。", "Found no macro."));
965                         }
966                         else
967                         {
968                                 strcpy(macro__buf, macro__act[k]);
969                                 ascii_to_text(buf, macro__buf);
970                                 prt(buf, 22, 0);
971                                 msg_print(_("マクロを確認しました。", "Found a macro."));
972                         }
973                 }
974                 else if (i == '4')
975                 {
976                         prt(_("コマンド: マクロの作成", "Command: Create a macro"), 16, 0);
977                         prt(_("トリガーキー: ", "Trigger: "), 18, 0);
978                         do_cmd_macro_aux(buf);
979                         clear_from(20);
980                         c_prt(TERM_L_RED, _("カーソルキーの左右でカーソル位置を移動。BackspaceかDeleteで一文字削除。",
981                                 "Press Left/Right arrow keys to move cursor. Backspace/Delete to delete a char."), 22, 0);
982                         prt(_("マクロ行動: ", "Action: "), 20, 0);
983                         ascii_to_text(tmp, macro__buf);
984                         if (askfor(tmp, 80))
985                         {
986                                 text_to_ascii(macro__buf, tmp);
987                                 macro_add(buf, macro__buf);
988                                 msg_print(_("マクロを追加しました。", "Added a macro."));
989                         }
990                 }
991                 else if (i == '5')
992                 {
993                         prt(_("コマンド: マクロの削除", "Command: Remove a macro"), 16, 0);
994                         prt(_("トリガーキー: ", "Trigger: "), 18, 0);
995                         do_cmd_macro_aux(buf);
996                         macro_add(buf, buf);
997                         msg_print(_("マクロを削除しました。", "Removed a macro."));
998                 }
999                 else if (i == '6')
1000                 {
1001                         prt(_("コマンド: キー配置をファイルに追加する", "Command: Append keymaps to a file"), 16, 0);
1002                         prt(_("ファイル: ", "File: "), 18, 0);
1003                         sprintf(tmp, "%s.prf", creature_ptr->base_name);
1004                         if (!askfor(tmp, 80)) continue;
1005
1006                         (void)keymap_dump(tmp);
1007                         msg_print(_("キー配置を追加しました。", "Appended keymaps."));
1008                 }
1009                 else if (i == '7')
1010                 {
1011                         prt(_("コマンド: キー配置の確認", "Command: Query a keymap"), 16, 0);
1012                         prt(_("押すキー: ", "Keypress: "), 18, 0);
1013                         do_cmd_macro_aux_keymap(buf);
1014                         concptr act = keymap_act[mode][(byte)(buf[0])];
1015                         if (!act)
1016                         {
1017                                 msg_print(_("キー配置は定義されていません。", "Found no keymap."));
1018                         }
1019                         else
1020                         {
1021                                 strcpy(macro__buf, act);
1022                                 ascii_to_text(buf, macro__buf);
1023                                 prt(buf, 22, 0);
1024                                 msg_print(_("キー配置を確認しました。", "Found a keymap."));
1025                         }
1026                 }
1027                 else if (i == '8')
1028                 {
1029                         prt(_("コマンド: キー配置の作成", "Command: Create a keymap"), 16, 0);
1030                         prt(_("押すキー: ", "Keypress: "), 18, 0);
1031                         do_cmd_macro_aux_keymap(buf);
1032                         clear_from(20);
1033                         c_prt(TERM_L_RED, _("カーソルキーの左右でカーソル位置を移動。BackspaceかDeleteで一文字削除。",
1034                                 "Press Left/Right arrow keys to move cursor. Backspace/Delete to delete a char."), 22, 0);
1035                         prt(_("行動: ", "Action: "), 20, 0);
1036                         ascii_to_text(tmp, macro__buf);
1037                         if (askfor(tmp, 80))
1038                         {
1039                                 text_to_ascii(macro__buf, tmp);
1040                                 string_free(keymap_act[mode][(byte)(buf[0])]);
1041                                 keymap_act[mode][(byte)(buf[0])] = string_make(macro__buf);
1042                                 msg_print(_("キー配置を追加しました。", "Added a keymap."));
1043                         }
1044                 }
1045                 else if (i == '9')
1046                 {
1047                         prt(_("コマンド: キー配置の削除", "Command: Remove a keymap"), 16, 0);
1048                         prt(_("押すキー: ", "Keypress: "), 18, 0);
1049                         do_cmd_macro_aux_keymap(buf);
1050                         string_free(keymap_act[mode][(byte)(buf[0])]);
1051                         keymap_act[mode][(byte)(buf[0])] = NULL;
1052                         msg_print(_("キー配置を削除しました。", "Removed a keymap."));
1053                 }
1054                 else if (i == '0')
1055                 {
1056                         prt(_("コマンド: マクロ行動の入力", "Command: Enter a new action"), 16, 0);
1057                         clear_from(20);
1058                         c_prt(TERM_L_RED, _("カーソルキーの左右でカーソル位置を移動。BackspaceかDeleteで一文字削除。",
1059                                 "Press Left/Right arrow keys to move cursor. Backspace/Delete to delete a char."), 22, 0);
1060                         prt(_("マクロ行動: ", "Action: "), 20, 0);
1061                         tmp[80] = '\0';
1062                         if (!askfor(buf, 80)) continue;
1063
1064                         text_to_ascii(macro__buf, buf);
1065                 }
1066                 else
1067                 {
1068                         bell();
1069                 }
1070
1071                 msg_erase();
1072         }
1073
1074         screen_load();
1075 }
1076
1077
1078 /*!
1079  * @brief キャラクタ色の明暗表現
1080  */
1081 static concptr lighting_level_str[F_LIT_MAX] =
1082 {
1083         _("標準色", "standard"),
1084         _("明色", "brightly lit"),
1085         _("暗色", "darkened"),
1086 };
1087
1088
1089 /*!
1090  * @brief キャラクタのビジュアルIDを変更する際の対象指定関数
1091  * @param i 指定対象となるキャラクタコード
1092  * @param num 指定されたビジュアルIDを返す参照ポインタ
1093  * @param max ビジュアルIDの最大数
1094  * @return 指定が実際に行われた場合TRUE、キャンセルされた場合FALSE
1095  */
1096 static bool cmd_visuals_aux(int i, IDX *num, IDX max)
1097 {
1098         if (iscntrl(i))
1099         {
1100                 char str[10] = "";
1101                 sprintf(str, "%d", *num);
1102                 if (!get_string(format("Input new number(0-%d): ", max - 1), str, 4))
1103                         return FALSE;
1104
1105                 IDX tmp = (IDX)strtol(str, NULL, 0);
1106                 if (tmp >= 0 && tmp < max)
1107                         *num = tmp;
1108         }
1109         else if (isupper(i))
1110                 *num = (*num + max - 1) % max;
1111         else
1112                 *num = (*num + 1) % max;
1113
1114         return TRUE;
1115 }
1116
1117 /*!
1118  * @brief キャラクタの変更メニュー表示
1119  * @param choice_msg 選択メッセージ
1120  * @return なし
1121  */
1122 static void print_visuals_menu(concptr choice_msg)
1123 {
1124         prt(_("[ 画面表示の設定 ]", "Interact with Visuals"), 1, 0);
1125         prt(_("(0) ユーザー設定ファイルのロード", "(0) Load a user pref file"), 3, 5);
1126         prt(_("(1) モンスターの 色/文字 をファイルに書き出す", "(1) Dump monster attr/chars"), 4, 5);
1127         prt(_("(2) アイテムの   色/文字 をファイルに書き出す", "(2) Dump object attr/chars"), 5, 5);
1128         prt(_("(3) 地形の       色/文字 をファイルに書き出す", "(3) Dump feature attr/chars"), 6, 5);
1129         prt(_("(4) モンスターの 色/文字 を変更する (数値操作)", "(4) Change monster attr/chars (numeric operation)"), 7, 5);
1130         prt(_("(5) アイテムの   色/文字 を変更する (数値操作)", "(5) Change object attr/chars (numeric operation)"), 8, 5);
1131         prt(_("(6) 地形の       色/文字 を変更する (数値操作)", "(6) Change feature attr/chars (numeric operation)"), 9, 5);
1132         prt(_("(7) モンスターの 色/文字 を変更する (シンボルエディタ)", "(7) Change monster attr/chars (visual mode)"), 10, 5);
1133         prt(_("(8) アイテムの   色/文字 を変更する (シンボルエディタ)", "(8) Change object attr/chars (visual mode)"), 11, 5);
1134         prt(_("(9) 地形の       色/文字 を変更する (シンボルエディタ)", "(9) Change feature attr/chars (visual mode)"), 12, 5);
1135         prt(_("(R) 画面表示方法の初期化", "(R) Reset visuals"), 13, 5);
1136         prt(format("コマンド: %s", choice_msg ? choice_msg : _("", "")), 15, 0);
1137 }
1138
1139
1140 /*
1141  * Interact with "visuals"
1142  */
1143 void do_cmd_visuals(player_type *creature_ptr)
1144 {
1145         char tmp[160];
1146         char buf[1024];
1147         bool need_redraw = FALSE;
1148         concptr empty_symbol = "<< ? >>";
1149         if (use_bigtile) empty_symbol = "<< ?? >>";
1150
1151         FILE_TYPE(FILE_TYPE_TEXT);
1152         screen_save();
1153         while (TRUE)
1154         {
1155                 Term_clear();
1156                 print_visuals_menu(NULL);
1157                 int i = inkey();
1158                 if (i == ESCAPE) break;
1159
1160                 switch (i)
1161                 {
1162                 case '0':
1163                 {
1164                         prt(_("コマンド: ユーザー設定ファイルのロード", "Command: Load a user pref file"), 15, 0);
1165                         prt(_("ファイル: ", "File: "), 17, 0);
1166                         sprintf(tmp, "%s.prf", creature_ptr->base_name);
1167                         if (!askfor(tmp, 70)) continue;
1168
1169                         (void)process_pref_file(creature_ptr, tmp);
1170                         need_redraw = TRUE;
1171                         break;
1172                 }
1173                 case '1':
1174                 {
1175                         static concptr mark = "Monster attr/chars";
1176                         prt(_("コマンド: モンスターの[色/文字]をファイルに書き出します", "Command: Dump monster attr/chars"), 15, 0);
1177                         prt(_("ファイル: ", "File: "), 17, 0);
1178                         sprintf(tmp, "%s.prf", creature_ptr->base_name);
1179                         if (!askfor(tmp, 70)) continue;
1180
1181                         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, tmp);
1182                         if (!open_auto_dump(buf, mark)) continue;
1183
1184                         auto_dump_printf(_("\n# モンスターの[色/文字]の設定\n\n", "\n# Monster attr/char definitions\n\n"));
1185                         for (i = 0; i < max_r_idx; i++)
1186                         {
1187                                 monster_race *r_ptr = &r_info[i];
1188                                 if (!r_ptr->name) continue;
1189
1190                                 auto_dump_printf("# %s\n", (r_name + r_ptr->name));
1191                                 auto_dump_printf("R:%d:0x%02X/0x%02X\n\n", i,
1192                                         (byte)(r_ptr->x_attr), (byte)(r_ptr->x_char));
1193                         }
1194
1195                         close_auto_dump();
1196                         msg_print(_("モンスターの[色/文字]をファイルに書き出しました。", "Dumped monster attr/chars."));
1197                         break;
1198                 }
1199                 case '2':
1200                 {
1201                         static concptr mark = "Object attr/chars";
1202                         prt(_("コマンド: アイテムの[色/文字]をファイルに書き出します", "Command: Dump object attr/chars"), 15, 0);
1203                         prt(_("ファイル: ", "File: "), 17, 0);
1204                         sprintf(tmp, "%s.prf", creature_ptr->base_name);
1205                         if (!askfor(tmp, 70)) continue;
1206
1207                         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, tmp);
1208                         if (!open_auto_dump(buf, mark)) continue;
1209
1210                         auto_dump_printf(_("\n# アイテムの[色/文字]の設定\n\n", "\n# Object attr/char definitions\n\n"));
1211                         for (KIND_OBJECT_IDX k_idx = 0; k_idx < max_k_idx; k_idx++)
1212                         {
1213                                 GAME_TEXT o_name[MAX_NLEN];
1214                                 object_kind *k_ptr = &k_info[k_idx];
1215                                 if (!k_ptr->name) continue;
1216
1217                                 if (!k_ptr->flavor)
1218                                 {
1219                                         strip_name(o_name, k_idx);
1220                                 }
1221                                 else
1222                                 {
1223                                         object_type forge;
1224                                         object_prep(&forge, k_idx);
1225                                         object_desc(creature_ptr, o_name, &forge, OD_FORCE_FLAVOR);
1226                                 }
1227
1228                                 auto_dump_printf("# %s\n", o_name);
1229                                 auto_dump_printf("K:%d:0x%02X/0x%02X\n\n", (int)k_idx,
1230                                         (byte)(k_ptr->x_attr), (byte)(k_ptr->x_char));
1231                         }
1232
1233                         close_auto_dump();
1234                         msg_print(_("アイテムの[色/文字]をファイルに書き出しました。", "Dumped object attr/chars."));
1235                         break;
1236                 }
1237                 case '3':
1238                 {
1239                         static concptr mark = "Feature attr/chars";
1240                         prt(_("コマンド: 地形の[色/文字]をファイルに書き出します", "Command: Dump feature attr/chars"), 15, 0);
1241                         prt(_("ファイル: ", "File: "), 17, 0);
1242                         sprintf(tmp, "%s.prf", creature_ptr->base_name);
1243                         if (!askfor(tmp, 70)) continue;
1244
1245                         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, tmp);
1246                         if (!open_auto_dump(buf, mark)) continue;
1247
1248                         auto_dump_printf(_("\n# 地形の[色/文字]の設定\n\n", "\n# Feature attr/char definitions\n\n"));
1249                         for (i = 0; i < max_f_idx; i++)
1250                         {
1251                                 feature_type *f_ptr = &f_info[i];
1252                                 if (!f_ptr->name) continue;
1253                                 if (f_ptr->mimic != i) continue;
1254
1255                                 auto_dump_printf("# %s\n", (f_name + f_ptr->name));
1256                                 auto_dump_printf("F:%d:0x%02X/0x%02X:0x%02X/0x%02X:0x%02X/0x%02X\n\n", i,
1257                                         (byte)(f_ptr->x_attr[F_LIT_STANDARD]), (byte)(f_ptr->x_char[F_LIT_STANDARD]),
1258                                         (byte)(f_ptr->x_attr[F_LIT_LITE]), (byte)(f_ptr->x_char[F_LIT_LITE]),
1259                                         (byte)(f_ptr->x_attr[F_LIT_DARK]), (byte)(f_ptr->x_char[F_LIT_DARK]));
1260                         }
1261
1262                         close_auto_dump();
1263                         msg_print(_("地形の[色/文字]をファイルに書き出しました。", "Dumped feature attr/chars."));
1264                         break;
1265                 }
1266                 case '4':
1267                 {
1268                         static concptr choice_msg = _("モンスターの[色/文字]を変更します", "Change monster attr/chars");
1269                         static MONRACE_IDX r = 0;
1270                         prt(format(_("コマンド: %s", "Command: %s"), choice_msg), 15, 0);
1271                         while (TRUE)
1272                         {
1273                                 monster_race *r_ptr = &r_info[r];
1274                                 int c;
1275                                 IDX t;
1276
1277                                 TERM_COLOR da = r_ptr->d_attr;
1278                                 byte dc = r_ptr->d_char;
1279                                 TERM_COLOR ca = r_ptr->x_attr;
1280                                 byte cc = r_ptr->x_char;
1281
1282                                 Term_putstr(5, 17, -1, TERM_WHITE,
1283                                         format(_("モンスター = %d, 名前 = %-40.40s", "Monster = %d, Name = %-40.40s"), r, (r_name + r_ptr->name)));
1284                                 Term_putstr(10, 19, -1, TERM_WHITE,
1285                                         format(_("初期値  色 / 文字 = %3u / %3u", "Default attr/char = %3u / %3u"), da, dc));
1286                                 Term_putstr(40, 19, -1, TERM_WHITE, empty_symbol);
1287                                 Term_queue_bigchar(43, 19, da, dc, 0, 0);
1288                                 Term_putstr(10, 20, -1, TERM_WHITE,
1289                                         format(_("現在値  色 / 文字 = %3u / %3u", "Current attr/char = %3u / %3u"), ca, cc));
1290                                 Term_putstr(40, 20, -1, TERM_WHITE, empty_symbol);
1291                                 Term_queue_bigchar(43, 20, ca, cc, 0, 0);
1292                                 Term_putstr(0, 22, -1, TERM_WHITE,
1293                                         _("コマンド (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): "));
1294                                 i = inkey();
1295                                 if (i == ESCAPE) break;
1296
1297                                 if (iscntrl(i)) c = 'a' + i - KTRL('A');
1298                                 else if (isupper(i)) c = 'a' + i - 'A';
1299                                 else c = i;
1300
1301                                 switch (c)
1302                                 {
1303                                 case 'n':
1304                                 {
1305                                         IDX prev_r = r;
1306                                         do
1307                                         {
1308                                                 if (!cmd_visuals_aux(i, &r, max_r_idx))
1309                                                 {
1310                                                         r = prev_r;
1311                                                         break;
1312                                                 }
1313                                         } while (!r_info[r].name);
1314                                 }
1315
1316                                 break;
1317                                 case 'a':
1318                                         t = (int)r_ptr->x_attr;
1319                                         (void)cmd_visuals_aux(i, &t, 256);
1320                                         r_ptr->x_attr = (byte)t;
1321                                         need_redraw = TRUE;
1322                                         break;
1323                                 case 'c':
1324                                         t = (int)r_ptr->x_char;
1325                                         (void)cmd_visuals_aux(i, &t, 256);
1326                                         r_ptr->x_char = (byte)t;
1327                                         need_redraw = TRUE;
1328                                         break;
1329                                 case 'v':
1330                                         do_cmd_knowledge_monsters(creature_ptr, &need_redraw, TRUE, r);
1331                                         Term_clear();
1332                                         print_visuals_menu(choice_msg);
1333                                         break;
1334                                 }
1335                         }
1336
1337                         break;
1338                 }
1339                 case '5':
1340                 {
1341                         static concptr choice_msg = _("アイテムの[色/文字]を変更します", "Change object attr/chars");
1342                         static IDX k = 0;
1343                         prt(format(_("コマンド: %s", "Command: %s"), choice_msg), 15, 0);
1344                         while (TRUE)
1345                         {
1346                                 object_kind *k_ptr = &k_info[k];
1347                                 int c;
1348                                 IDX t;
1349
1350                                 TERM_COLOR da = k_ptr->d_attr;
1351                                 SYMBOL_CODE dc = k_ptr->d_char;
1352                                 TERM_COLOR ca = k_ptr->x_attr;
1353                                 SYMBOL_CODE cc = k_ptr->x_char;
1354
1355                                 Term_putstr(5, 17, -1, TERM_WHITE,
1356                                         format(_("アイテム = %d, 名前 = %-40.40s", "Object = %d, Name = %-40.40s"),
1357                                                 k, k_name + (!k_ptr->flavor ? k_ptr->name : k_ptr->flavor_name)));
1358                                 Term_putstr(10, 19, -1, TERM_WHITE,
1359                                         format(_("初期値  色 / 文字 = %3d / %3d", "Default attr/char = %3d / %3d"), da, dc));
1360                                 Term_putstr(40, 19, -1, TERM_WHITE, empty_symbol);
1361                                 Term_queue_bigchar(43, 19, da, dc, 0, 0);
1362                                 Term_putstr(10, 20, -1, TERM_WHITE,
1363                                         format(_("現在値  色 / 文字 = %3d / %3d", "Current attr/char = %3d / %3d"), ca, cc));
1364                                 Term_putstr(40, 20, -1, TERM_WHITE, empty_symbol);
1365                                 Term_queue_bigchar(43, 20, ca, cc, 0, 0);
1366                                 Term_putstr(0, 22, -1, TERM_WHITE,
1367                                         _("コマンド (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): "));
1368
1369                                 i = inkey();
1370                                 if (i == ESCAPE) break;
1371
1372                                 if (iscntrl(i)) c = 'a' + i - KTRL('A');
1373                                 else if (isupper(i)) c = 'a' + i - 'A';
1374                                 else c = i;
1375
1376                                 switch (c)
1377                                 {
1378                                 case 'n':
1379                                 {
1380                                         IDX prev_k = k;
1381                                         do
1382                                         {
1383                                                 if (!cmd_visuals_aux(i, &k, max_k_idx))
1384                                                 {
1385                                                         k = prev_k;
1386                                                         break;
1387                                                 }
1388                                         } while (!k_info[k].name);
1389                                 }
1390
1391                                 break;
1392                                 case 'a':
1393                                         t = (int)k_ptr->x_attr;
1394                                         (void)cmd_visuals_aux(i, &t, 256);
1395                                         k_ptr->x_attr = (byte)t;
1396                                         need_redraw = TRUE;
1397                                         break;
1398                                 case 'c':
1399                                         t = (int)k_ptr->x_char;
1400                                         (void)cmd_visuals_aux(i, &t, 256);
1401                                         k_ptr->x_char = (byte)t;
1402                                         need_redraw = TRUE;
1403                                         break;
1404                                 case 'v':
1405                                         do_cmd_knowledge_objects(creature_ptr, &need_redraw, TRUE, k);
1406                                         Term_clear();
1407                                         print_visuals_menu(choice_msg);
1408                                         break;
1409                                 }
1410                         }
1411
1412                         break;
1413                 }
1414                 case '6':
1415                 {
1416                         static concptr choice_msg = _("地形の[色/文字]を変更します", "Change feature attr/chars");
1417                         static IDX f = 0;
1418                         static IDX lighting_level = F_LIT_STANDARD;
1419                         prt(format(_("コマンド: %s", "Command: %s"), choice_msg), 15, 0);
1420                         while (TRUE)
1421                         {
1422                                 feature_type *f_ptr = &f_info[f];
1423                                 int c;
1424                                 IDX t;
1425
1426                                 TERM_COLOR da = f_ptr->d_attr[lighting_level];
1427                                 byte dc = f_ptr->d_char[lighting_level];
1428                                 TERM_COLOR ca = f_ptr->x_attr[lighting_level];
1429                                 byte cc = f_ptr->x_char[lighting_level];
1430
1431                                 prt("", 17, 5);
1432                                 Term_putstr(5, 17, -1, TERM_WHITE,
1433                                         format(_("地形 = %d, 名前 = %s, 明度 = %s", "Terrain = %d, Name = %s, Lighting = %s"),
1434                                                 f, (f_name + f_ptr->name), lighting_level_str[lighting_level]));
1435                                 Term_putstr(10, 19, -1, TERM_WHITE,
1436                                         format(_("初期値  色 / 文字 = %3d / %3d", "Default attr/char = %3d / %3d"), da, dc));
1437                                 Term_putstr(40, 19, -1, TERM_WHITE, empty_symbol);
1438                                 Term_queue_bigchar(43, 19, da, dc, 0, 0);
1439                                 Term_putstr(10, 20, -1, TERM_WHITE,
1440                                         format(_("現在値  色 / 文字 = %3d / %3d", "Current attr/char = %3d / %3d"), ca, cc));
1441                                 Term_putstr(40, 20, -1, TERM_WHITE, empty_symbol);
1442                                 Term_queue_bigchar(43, 20, ca, cc, 0, 0);
1443                                 Term_putstr(0, 22, -1, TERM_WHITE,
1444                                         _("コマンド (n/N/^N/a/A/^A/c/C/^C/l/L/^L/d/D/^D/v/V/^V): ", "Command (n/N/^N/a/A/^A/c/C/^C/l/L/^L/d/D/^D/v/V/^V): "));
1445
1446                                 i = inkey();
1447                                 if (i == ESCAPE) break;
1448
1449                                 if (iscntrl(i)) c = 'a' + i - KTRL('A');
1450                                 else if (isupper(i)) c = 'a' + i - 'A';
1451                                 else c = i;
1452
1453                                 switch (c)
1454                                 {
1455                                 case 'n':
1456                                 {
1457                                         IDX prev_f = f;
1458                                         do
1459                                         {
1460                                                 if (!cmd_visuals_aux(i, &f, max_f_idx))
1461                                                 {
1462                                                         f = prev_f;
1463                                                         break;
1464                                                 }
1465                                         } while (!f_info[f].name || (f_info[f].mimic != f));
1466                                 }
1467
1468                                 break;
1469                                 case 'a':
1470                                         t = (int)f_ptr->x_attr[lighting_level];
1471                                         (void)cmd_visuals_aux(i, &t, 256);
1472                                         f_ptr->x_attr[lighting_level] = (byte)t;
1473                                         need_redraw = TRUE;
1474                                         break;
1475                                 case 'c':
1476                                         t = (int)f_ptr->x_char[lighting_level];
1477                                         (void)cmd_visuals_aux(i, &t, 256);
1478                                         f_ptr->x_char[lighting_level] = (byte)t;
1479                                         need_redraw = TRUE;
1480                                         break;
1481                                 case 'l':
1482                                         (void)cmd_visuals_aux(i, &lighting_level, F_LIT_MAX);
1483                                         break;
1484                                 case 'd':
1485                                         apply_default_feat_lighting(f_ptr->x_attr, f_ptr->x_char);
1486                                         need_redraw = TRUE;
1487                                         break;
1488                                 case 'v':
1489                                         do_cmd_knowledge_features(&need_redraw, TRUE, f, &lighting_level);
1490                                         Term_clear();
1491                                         print_visuals_menu(choice_msg);
1492                                         break;
1493                                 }
1494                         }
1495
1496                         break;
1497                 }
1498                 case '7':
1499                         do_cmd_knowledge_monsters(creature_ptr, &need_redraw, TRUE, -1);
1500                         break;
1501                 case '8':
1502                         do_cmd_knowledge_objects(creature_ptr, &need_redraw, TRUE, -1);
1503                         break;
1504                 case '9':
1505                 {
1506                         IDX lighting_level = F_LIT_STANDARD;
1507                         do_cmd_knowledge_features(&need_redraw, TRUE, -1, &lighting_level);
1508                         break;
1509                 }
1510                 case 'R':
1511                 case 'r':
1512                         reset_visuals(creature_ptr);
1513                         msg_print(_("画面上の[色/文字]を初期値にリセットしました。", "Visual attr/char tables reset."));
1514                         need_redraw = TRUE;
1515                         break;
1516                 default:
1517                         bell();
1518                         break;
1519                 }
1520
1521                 msg_erase();
1522         }
1523
1524         screen_load();
1525         if (need_redraw) do_cmd_redraw(creature_ptr);
1526 }
1527
1528
1529 /*
1530  * Interact with "colors"
1531  */
1532 void do_cmd_colors(player_type *creature_ptr)
1533 {
1534         int i;
1535         char tmp[160];
1536         char buf[1024];
1537         FILE_TYPE(FILE_TYPE_TEXT);
1538         screen_save();
1539         while (TRUE)
1540         {
1541                 Term_clear();
1542                 prt(_("[ カラーの設定 ]", "Interact with Colors"), 2, 0);
1543                 prt(_("(1) ユーザー設定ファイルのロード", "(1) Load a user pref file"), 4, 5);
1544                 prt(_("(2) カラーの設定をファイルに書き出す", "(2) Dump colors"), 5, 5);
1545                 prt(_("(3) カラーの設定を変更する", "(3) Modify colors"), 6, 5);
1546                 prt(_("コマンド: ", "Command: "), 8, 0);
1547                 i = inkey();
1548                 if (i == ESCAPE) break;
1549
1550                 if (i == '1')
1551                 {
1552                         prt(_("コマンド: ユーザー設定ファイルをロードします", "Command: Load a user pref file"), 8, 0);
1553                         prt(_("ファイル: ", "File: "), 10, 0);
1554                         sprintf(tmp, "%s.prf", creature_ptr->base_name);
1555                         if (!askfor(tmp, 70)) continue;
1556
1557                         (void)process_pref_file(creature_ptr, tmp);
1558                         Term_xtra(TERM_XTRA_REACT, 0);
1559                         Term_redraw();
1560                 }
1561                 else if (i == '2')
1562                 {
1563                         static concptr mark = "Colors";
1564                         prt(_("コマンド: カラーの設定をファイルに書き出します", "Command: Dump colors"), 8, 0);
1565                         prt(_("ファイル: ", "File: "), 10, 0);
1566                         sprintf(tmp, "%s.prf", creature_ptr->base_name);
1567                         if (!askfor(tmp, 70)) continue;
1568
1569                         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, tmp);
1570                         if (!open_auto_dump(buf, mark)) continue;
1571
1572                         auto_dump_printf(_("\n# カラーの設定\n\n", "\n# Color redefinitions\n\n"));
1573                         for (i = 0; i < 256; i++)
1574                         {
1575                                 int kv = angband_color_table[i][0];
1576                                 int rv = angband_color_table[i][1];
1577                                 int gv = angband_color_table[i][2];
1578                                 int bv = angband_color_table[i][3];
1579
1580                                 concptr name = _("未知", "unknown");
1581                                 if (!kv && !rv && !gv && !bv) continue;
1582
1583                                 if (i < 16) name = color_names[i];
1584
1585                                 auto_dump_printf(_("# カラー '%s'\n", "# Color '%s'\n"), name);
1586                                 auto_dump_printf("V:%d:0x%02X:0x%02X:0x%02X:0x%02X\n\n",
1587                                         i, kv, rv, gv, bv);
1588                         }
1589
1590                         close_auto_dump();
1591                         msg_print(_("カラーの設定をファイルに書き出しました。", "Dumped color redefinitions."));
1592                 }
1593                 else if (i == '3')
1594                 {
1595                         static byte a = 0;
1596                         prt(_("コマンド: カラーの設定を変更します", "Command: Modify colors"), 8, 0);
1597                         while (TRUE)
1598                         {
1599                                 concptr name;
1600                                 clear_from(10);
1601                                 for (byte j = 0; j < 16; j++)
1602                                 {
1603                                         Term_putstr(j * 4, 20, -1, a, "###");
1604                                         Term_putstr(j * 4, 22, -1, j, format("%3d", j));
1605                                 }
1606
1607                                 name = ((a < 16) ? color_names[a] : _("未定義", "undefined"));
1608                                 Term_putstr(5, 10, -1, TERM_WHITE,
1609                                         format(_("カラー = %d, 名前 = %s", "Color = %d, Name = %s"), a, name));
1610                                 Term_putstr(5, 12, -1, TERM_WHITE,
1611                                         format("K = 0x%02x / R,G,B = 0x%02x,0x%02x,0x%02x",
1612                                                 angband_color_table[a][0],
1613                                                 angband_color_table[a][1],
1614                                                 angband_color_table[a][2],
1615                                                 angband_color_table[a][3]));
1616                                 Term_putstr(0, 14, -1, TERM_WHITE,
1617                                         _("コマンド (n/N/k/K/r/R/g/G/b/B): ", "Command (n/N/k/K/r/R/g/G/b/B): "));
1618                                 i = inkey();
1619                                 if (i == ESCAPE) break;
1620
1621                                 if (i == 'n') a = (byte)(a + 1);
1622                                 if (i == 'N') a = (byte)(a - 1);
1623                                 if (i == 'k') angband_color_table[a][0] = (byte)(angband_color_table[a][0] + 1);
1624                                 if (i == 'K') angband_color_table[a][0] = (byte)(angband_color_table[a][0] - 1);
1625                                 if (i == 'r') angband_color_table[a][1] = (byte)(angband_color_table[a][1] + 1);
1626                                 if (i == 'R') angband_color_table[a][1] = (byte)(angband_color_table[a][1] - 1);
1627                                 if (i == 'g') angband_color_table[a][2] = (byte)(angband_color_table[a][2] + 1);
1628                                 if (i == 'G') angband_color_table[a][2] = (byte)(angband_color_table[a][2] - 1);
1629                                 if (i == 'b') angband_color_table[a][3] = (byte)(angband_color_table[a][3] + 1);
1630                                 if (i == 'B') angband_color_table[a][3] = (byte)(angband_color_table[a][3] - 1);
1631
1632                                 Term_xtra(TERM_XTRA_REACT, 0);
1633                                 Term_redraw();
1634                         }
1635                 }
1636                 else
1637                 {
1638                         bell();
1639                 }
1640
1641                 msg_erase();
1642         }
1643
1644         screen_load();
1645 }
1646
1647
1648 /*
1649  * Note something in the message recall
1650  */
1651 void do_cmd_note(void)
1652 {
1653         char buf[80];
1654         strcpy(buf, "");
1655         if (!get_string(_("メモ: ", "Note: "), buf, 60)) return;
1656         if (!buf[0] || (buf[0] == ' ')) return;
1657
1658         msg_format(_("メモ: %s", "Note: %s"), buf);
1659 }
1660
1661
1662 /*
1663  * Mention the current version
1664  */
1665 void do_cmd_version(void)
1666 {
1667 #if FAKE_VER_EXTRA > 0
1668         msg_format(_("変愚蛮怒(Hengband) %d.%d.%d.%d", "You are playing Hengband %d.%d.%d.%d."),
1669                 FAKE_VER_MAJOR - 10, FAKE_VER_MINOR, FAKE_VER_PATCH, FAKE_VER_EXTRA);
1670 #else
1671         msg_format(_("変愚蛮怒(Hengband) %d.%d.%d", "You are playing Hengband %d.%d.%d."),
1672                 FAKE_VER_MAJOR - 10, FAKE_VER_MINOR, FAKE_VER_PATCH);
1673 #endif
1674 }
1675
1676
1677 /*
1678  * Note that "feeling" is set to zero unless some time has passed.
1679  * Note that this is done when the level is GENERATED, not entered.
1680  */
1681 void do_cmd_feeling(player_type *creature_ptr)
1682 {
1683         if (creature_ptr->wild_mode) return;
1684
1685         if (creature_ptr->current_floor_ptr->inside_quest && !random_quest_number(creature_ptr, creature_ptr->current_floor_ptr->dun_level))
1686         {
1687                 msg_print(_("典型的なクエストのダンジョンのようだ。", "Looks like a typical quest level."));
1688                 return;
1689         }
1690
1691         if (creature_ptr->town_num && !creature_ptr->current_floor_ptr->dun_level)
1692         {
1693                 if (!strcmp(town_info[creature_ptr->town_num].name, _("荒野", "wilderness")))
1694                 {
1695                         msg_print(_("何かありそうな荒野のようだ。", "Looks like a strange wilderness."));
1696                         return;
1697                 }
1698
1699                 msg_print(_("典型的な町のようだ。", "Looks like a typical town."));
1700                 return;
1701         }
1702
1703         if (!creature_ptr->current_floor_ptr->dun_level)
1704         {
1705                 msg_print(_("典型的な荒野のようだ。", "Looks like a typical wilderness."));
1706                 return;
1707         }
1708
1709         if (creature_ptr->muta3 & MUT3_GOOD_LUCK)
1710                 msg_print(do_cmd_feeling_text_lucky[creature_ptr->feeling]);
1711         else if (IS_ECHIZEN(creature_ptr))
1712                 msg_print(do_cmd_feeling_text_combat[creature_ptr->feeling]);
1713         else
1714                 msg_print(do_cmd_feeling_text[creature_ptr->feeling]);
1715 }
1716
1717
1718 /*
1719  * todo 引数と戻り値について追記求む
1720  * Build a list of monster indexes in the given group.
1721  *
1722  * mode & 0x01 : check for non-empty group
1723  * mode & 0x02 : visual operation only
1724
1725  * @param creature_ptr プレーヤーへの参照ポインタ
1726  * @param grp_cur ???
1727  * @param mon_idx[] ???
1728  * @param mode ???
1729  * @return The number of monsters in the group
1730  */
1731 static IDX collect_monsters(player_type *creature_ptr, IDX grp_cur, IDX mon_idx[], BIT_FLAGS8 mode)
1732 {
1733         concptr group_char = monster_group_char[grp_cur];
1734         bool grp_unique = (monster_group_char[grp_cur] == (char *)-1L);
1735         bool grp_riding = (monster_group_char[grp_cur] == (char *)-2L);
1736         bool grp_wanted = (monster_group_char[grp_cur] == (char *)-3L);
1737         bool grp_amberite = (monster_group_char[grp_cur] == (char *)-4L);
1738
1739         IDX mon_cnt = 0;
1740         for (IDX i = 0; i < max_r_idx; i++)
1741         {
1742                 monster_race *r_ptr = &r_info[i];
1743                 if (!r_ptr->name) continue;
1744                 if (!(mode & 0x02) && !cheat_know && !r_ptr->r_sights) continue;
1745
1746                 if (grp_unique)
1747                 {
1748                         if (!(r_ptr->flags1 & RF1_UNIQUE)) continue;
1749                 }
1750                 else if (grp_riding)
1751                 {
1752                         if (!(r_ptr->flags7 & RF7_RIDING)) continue;
1753                 }
1754                 else if (grp_wanted)
1755                 {
1756                         bool wanted = FALSE;
1757                         for (int j = 0; j < MAX_BOUNTY; j++)
1758                         {
1759                                 if (current_world_ptr->bounty_r_idx[j] == i || current_world_ptr->bounty_r_idx[j] - 10000 == i ||
1760                                         (creature_ptr->today_mon && creature_ptr->today_mon == i))
1761                                 {
1762                                         wanted = TRUE;
1763                                         break;
1764                                 }
1765                         }
1766
1767                         if (!wanted) continue;
1768                 }
1769                 else if (grp_amberite)
1770                 {
1771                         if (!(r_ptr->flags3 & RF3_AMBERITE)) continue;
1772                 }
1773                 else
1774                 {
1775                         if (!my_strchr(group_char, r_ptr->d_char)) continue;
1776                 }
1777
1778                 mon_idx[mon_cnt++] = i;
1779                 if (mode & 0x01) break;
1780         }
1781
1782         mon_idx[mon_cnt] = -1;
1783         int dummy_why;
1784         ang_sort(mon_idx, &dummy_why, mon_cnt, ang_sort_comp_monster_level, ang_sort_swap_hook);
1785         return mon_cnt;
1786 }
1787
1788
1789 /*
1790  * Build a list of object indexes in the given group. Return the number
1791  * of objects in the group.
1792  *
1793  * mode & 0x01 : check for non-empty group
1794  * mode & 0x02 : visual operation only
1795  */
1796 static KIND_OBJECT_IDX collect_objects(int grp_cur, KIND_OBJECT_IDX object_idx[], BIT_FLAGS8 mode)
1797 {
1798         KIND_OBJECT_IDX object_cnt = 0;
1799         byte group_tval = object_group_tval[grp_cur];
1800         for (KIND_OBJECT_IDX i = 0; i < max_k_idx; i++)
1801         {
1802                 object_kind *k_ptr = &k_info[i];
1803                 if (!k_ptr->name) continue;
1804
1805                 if (!(mode & 0x02))
1806                 {
1807                         if (!current_world_ptr->wizard)
1808                         {
1809                                 if (!k_ptr->flavor) continue;
1810                                 if (!k_ptr->aware) continue;
1811                         }
1812
1813                         int k = 0;
1814                         for (int j = 0; j < 4; j++)
1815                                 k += k_ptr->chance[j];
1816                         if (!k) continue;
1817                 }
1818
1819                 if (TV_LIFE_BOOK == group_tval)
1820                 {
1821                         if (TV_LIFE_BOOK <= k_ptr->tval && k_ptr->tval <= TV_HEX_BOOK)
1822                         {
1823                                 object_idx[object_cnt++] = i;
1824                         }
1825                         else
1826                                 continue;
1827                 }
1828                 else if (k_ptr->tval == group_tval)
1829                 {
1830                         object_idx[object_cnt++] = i;
1831                 }
1832                 else
1833                         continue;
1834
1835                 if (mode & 0x01) break;
1836         }
1837
1838         object_idx[object_cnt] = -1;
1839         return object_cnt;
1840 }
1841
1842
1843 /*
1844  * Description of each feature group.
1845  */
1846 static concptr feature_group_text[] =
1847 {
1848         "terrains",
1849         NULL
1850 };
1851
1852
1853 /*
1854  * Build a list of feature indexes in the given group. Return the number
1855  * of features in the group.
1856  *
1857  * mode & 0x01 : check for non-empty group
1858  */
1859 static FEAT_IDX collect_features(FEAT_IDX *feat_idx, BIT_FLAGS8 mode)
1860 {
1861         FEAT_IDX feat_cnt = 0;
1862         for (FEAT_IDX i = 0; i < max_f_idx; i++)
1863         {
1864                 feature_type *f_ptr = &f_info[i];
1865                 if (!f_ptr->name) continue;
1866                 if (f_ptr->mimic != i) continue;
1867
1868                 feat_idx[feat_cnt++] = i;
1869                 if (mode & 0x01) break;
1870         }
1871
1872         feat_idx[feat_cnt] = -1;
1873         return feat_cnt;
1874 }
1875
1876
1877 /*
1878  * Hack -- load a screen dump from a file
1879  */
1880 void do_cmd_load_screen(void)
1881 {
1882         TERM_COLOR a = 0;
1883         SYMBOL_CODE c = ' ';
1884         bool okay = TRUE;
1885         FILE *fff;
1886         char buf[1024];
1887         TERM_LEN wid, hgt;
1888         Term_get_size(&wid, &hgt);
1889         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, "dump.txt");
1890         fff = my_fopen(buf, "r");
1891         if (!fff)
1892         {
1893                 msg_format(_("%s を開くことができませんでした。", "Failed to open %s."), buf);
1894                 msg_print(NULL);
1895                 return;
1896         }
1897
1898         screen_save();
1899         Term_clear();
1900         for (TERM_LEN y = 0; okay; y++)
1901         {
1902                 if (!fgets(buf, 1024, fff)) okay = FALSE;
1903
1904                 if (buf[0] == '\n' || buf[0] == '\0') break;
1905                 if (y >= hgt) continue;
1906
1907                 for (TERM_LEN x = 0; x < wid - 1; x++)
1908                 {
1909                         if (buf[x] == '\n' || buf[x] == '\0') break;
1910
1911                         Term_draw(x, y, TERM_WHITE, buf[x]);
1912                 }
1913         }
1914
1915         for (TERM_LEN y = 0; okay; y++)
1916         {
1917                 if (!fgets(buf, 1024, fff)) okay = FALSE;
1918
1919                 if (buf[0] == '\n' || buf[0] == '\0') break;
1920                 if (y >= hgt) continue;
1921
1922                 for (TERM_LEN x = 0; x < wid - 1; x++)
1923                 {
1924                         if (buf[x] == '\n' || buf[x] == '\0') break;
1925
1926                         (void)(Term_what(x, y, &a, &c));
1927                         for (int i = 0; i < 16; i++)
1928                         {
1929                                 if (hack[i] == buf[x]) a = (byte)i;
1930                         }
1931
1932                         Term_draw(x, y, a, c);
1933                 }
1934         }
1935
1936         my_fclose(fff);
1937         prt(_("ファイルに書き出された画面(記念撮影)をロードしました。", "Screen dump loaded."), 0, 0);
1938         flush();
1939         inkey();
1940         screen_load();
1941 }
1942
1943 // todo なぜこんな中途半端なところに? defineも…
1944 concptr inven_res_label = _("                               酸電火冷毒光闇破轟獄因沌劣 盲怖乱痺透命感消復浮",
1945         "                               AcElFiCoPoLiDkShSoNtNxCaDi BlFeCfFaSeHlEpSdRgLv");
1946
1947 #define IM_FLAG_STR  _("*", "* ")
1948 #define HAS_FLAG_STR _("+", "+ ")
1949 #define NO_FLAG_STR  _("・", ". ")
1950
1951 #define print_im_or_res_flag(IM, RES) \
1952 { \
1953         fputs(have_flag(flgs, (IM)) ? IM_FLAG_STR : \
1954               (have_flag(flgs, (RES)) ? HAS_FLAG_STR : NO_FLAG_STR), fff); \
1955 }
1956
1957 #define print_flag(TR) \
1958 { \
1959         fputs(have_flag(flgs, (TR)) ? HAS_FLAG_STR : NO_FLAG_STR, fff); \
1960 }
1961
1962
1963 static void do_cmd_knowledge_inven_aux(player_type *creature_ptr, FILE *fff, object_type *o_ptr, int *j, OBJECT_TYPE_VALUE tval, char *where)
1964 {
1965         GAME_TEXT o_name[MAX_NLEN];
1966         BIT_FLAGS flgs[TR_FLAG_SIZE];
1967         if (!o_ptr->k_idx) return;
1968         if (o_ptr->tval != tval) return;
1969         if (!object_is_known(o_ptr)) return;
1970
1971         bool is_special_item_type = (object_is_wearable(o_ptr) && object_is_ego(o_ptr))
1972                 || ((tval == TV_AMULET) && (o_ptr->sval == SV_AMULET_RESISTANCE))
1973                 || ((tval == TV_RING) && (o_ptr->sval == SV_RING_LORDLY))
1974                 || ((tval == TV_SHIELD) && (o_ptr->sval == SV_DRAGON_SHIELD))
1975                 || ((tval == TV_HELM) && (o_ptr->sval == SV_DRAGON_HELM))
1976                 || ((tval == TV_GLOVES) && (o_ptr->sval == SV_SET_OF_DRAGON_GLOVES))
1977                 || ((tval == TV_BOOTS) && (o_ptr->sval == SV_PAIR_OF_DRAGON_GREAVE))
1978                 || object_is_artifact(o_ptr);
1979         if (!is_special_item_type)
1980         {
1981                 return;
1982         }
1983
1984         int i = 0;
1985         object_desc(creature_ptr, o_name, o_ptr, OD_NAME_ONLY);
1986         while (o_name[i] && (i < 26))
1987         {
1988 #ifdef JP
1989                 if (iskanji(o_name[i])) i++;
1990 #endif
1991                 i++;
1992         }
1993
1994         if (i < 28)
1995         {
1996                 while (i < 28)
1997                 {
1998                         o_name[i] = ' '; i++;
1999                 }
2000         }
2001
2002         o_name[i] = '\0';
2003
2004         fprintf(fff, "%s %s", where, o_name);
2005
2006         if (!OBJECT_IS_FULL_KNOWN(o_ptr))
2007         {
2008                 fputs(_("-------不明--------------- -------不明---------\n",
2009                         "-------unknown------------ -------unknown------\n"), fff);
2010         }
2011         else
2012         {
2013                 object_flags_known(o_ptr, flgs);
2014
2015                 print_im_or_res_flag(TR_IM_ACID, TR_RES_ACID);
2016                 print_im_or_res_flag(TR_IM_ELEC, TR_RES_ELEC);
2017                 print_im_or_res_flag(TR_IM_FIRE, TR_RES_FIRE);
2018                 print_im_or_res_flag(TR_IM_COLD, TR_RES_COLD);
2019                 print_flag(TR_RES_POIS);
2020                 print_flag(TR_RES_LITE);
2021                 print_flag(TR_RES_DARK);
2022                 print_flag(TR_RES_SHARDS);
2023                 print_flag(TR_RES_SOUND);
2024                 print_flag(TR_RES_NETHER);
2025                 print_flag(TR_RES_NEXUS);
2026                 print_flag(TR_RES_CHAOS);
2027                 print_flag(TR_RES_DISEN);
2028
2029                 fputs(" ", fff);
2030
2031                 print_flag(TR_RES_BLIND);
2032                 print_flag(TR_RES_FEAR);
2033                 print_flag(TR_RES_CONF);
2034                 print_flag(TR_FREE_ACT);
2035                 print_flag(TR_SEE_INVIS);
2036                 print_flag(TR_HOLD_EXP);
2037                 print_flag(TR_TELEPATHY);
2038                 print_flag(TR_SLOW_DIGEST);
2039                 print_flag(TR_REGEN);
2040                 print_flag(TR_LEVITATION);
2041
2042                 fputc('\n', fff);
2043         }
2044
2045         (*j)++;
2046         if (*j == 9)
2047         {
2048                 *j = 0;
2049                 fprintf(fff, "%s\n", inven_res_label);
2050         }
2051 }
2052
2053 /*
2054  * Display *ID* ed weapons/armors's resistances
2055  */
2056 static void do_cmd_knowledge_inven(player_type *creature_ptr)
2057 {
2058         FILE *fff;
2059         GAME_TEXT file_name[1024];
2060         store_type  *st_ptr;
2061         OBJECT_TYPE_VALUE tval;
2062         int j = 0;
2063
2064         char where[32];
2065         fff = my_fopen_temp(file_name, 1024);
2066         if (!fff)
2067         {
2068                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
2069                 msg_print(NULL);
2070                 return;
2071         }
2072
2073         fprintf(fff, "%s\n", inven_res_label);
2074         for (tval = TV_WEARABLE_BEGIN; tval <= TV_WEARABLE_END; tval++)
2075         {
2076                 if (j != 0)
2077                 {
2078                         for (; j < 9; j++) fputc('\n', fff);
2079                         j = 0;
2080                         fprintf(fff, "%s\n", inven_res_label);
2081                 }
2082
2083                 strcpy(where, _("装", "E "));
2084                 for (int i = INVEN_RARM; i < INVEN_TOTAL; i++)
2085                 {
2086                         do_cmd_knowledge_inven_aux(creature_ptr, fff, &creature_ptr->inventory_list[i], &j, tval, where);
2087                 }
2088
2089                 strcpy(where, _("持", "I "));
2090                 for (int i = 0; i < INVEN_PACK; i++)
2091                 {
2092                         do_cmd_knowledge_inven_aux(creature_ptr, fff, &creature_ptr->inventory_list[i], &j, tval, where);
2093                 }
2094
2095                 st_ptr = &town_info[1].store[STORE_HOME];
2096                 strcpy(where, _("家", "H "));
2097                 for (int i = 0; i < st_ptr->stock_num; i++)
2098                 {
2099                         do_cmd_knowledge_inven_aux(creature_ptr, fff, &st_ptr->stock[i], &j, tval, where);
2100                 }
2101         }
2102
2103         my_fclose(fff);
2104         (void)show_file(creature_ptr, TRUE, file_name, _("*鑑定*済み武器/防具の耐性リスト", "Resistances of *identified* equipment"), 0, 0);
2105         fd_kill(file_name);
2106 }
2107
2108
2109 void do_cmd_save_screen_html_aux(char *filename, int message)
2110 {
2111         concptr tags[4] = {
2112                 "HEADER_START:",
2113                 "HEADER_END:",
2114                 "FOOTER_START:",
2115                 "FOOTER_END:",
2116         };
2117         concptr html_head[] = {
2118                 "<html>\n<body text=\"#ffffff\" bgcolor=\"#000000\">\n",
2119                 "<pre>",
2120                 0,
2121         };
2122         concptr html_foot[] = {
2123                 "</pre>\n",
2124                 "</body>\n</html>\n",
2125                 0,
2126         };
2127
2128         TERM_LEN wid, hgt;
2129         Term_get_size(&wid, &hgt);
2130         FILE_TYPE(FILE_TYPE_TEXT);
2131         FILE *fff;
2132         fff = my_fopen(filename, "w");
2133         if (!fff)
2134         {
2135                 if (message)
2136                 {
2137                         msg_format(_("ファイル %s を開けませんでした。", "Failed to open file %s."), filename);
2138                         msg_print(NULL);
2139                 }
2140
2141                 return;
2142         }
2143
2144         if (message) screen_save();
2145
2146         char buf[2048];
2147         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, "htmldump.prf");
2148         FILE *tmpfff;
2149         tmpfff = my_fopen(buf, "r");
2150         if (!tmpfff)
2151         {
2152                 for (int i = 0; html_head[i]; i++)
2153                         fputs(html_head[i], fff);
2154         }
2155         else
2156         {
2157                 bool is_first_line = TRUE;
2158                 while (!my_fgets(tmpfff, buf, sizeof(buf)))
2159                 {
2160                         if (is_first_line)
2161                         {
2162                                 if (strncmp(buf, tags[0], strlen(tags[0])) == 0)
2163                                         is_first_line = FALSE;
2164                         }
2165                         else
2166                         {
2167                                 if (strncmp(buf, tags[1], strlen(tags[1])) == 0)
2168                                         break;
2169                                 fprintf(fff, "%s\n", buf);
2170                         }
2171                 }
2172         }
2173
2174         for (TERM_LEN y = 0; y < hgt; y++)
2175         {
2176                 if (y != 0) fprintf(fff, "\n");
2177
2178                 TERM_COLOR a = 0, old_a = 0;
2179                 char c = ' ';
2180                 for (TERM_LEN x = 0; x < wid - 1; x++)
2181                 {
2182                         concptr cc = NULL;
2183                         (void)(Term_what(x, y, &a, &c));
2184                         switch (c)
2185                         {
2186                         case '&': cc = "&amp;"; break;
2187                         case '<': cc = "&lt;"; break;
2188                         case '>': cc = "&gt;"; break;
2189 #ifdef WINDOWS
2190                         case 0x1f: c = '.'; break;
2191                         case 0x7f: c = (a == 0x09) ? '%' : '#'; break;
2192 #endif
2193                         }
2194
2195                         a = a & 0x0F;
2196                         if ((y == 0 && x == 0) || a != old_a)
2197                         {
2198                                 int rv = angband_color_table[a][1];
2199                                 int gv = angband_color_table[a][2];
2200                                 int bv = angband_color_table[a][3];
2201                                 fprintf(fff, "%s<font color=\"#%02x%02x%02x\">",
2202                                         ((y == 0 && x == 0) ? "" : "</font>"), rv, gv, bv);
2203                                 old_a = a;
2204                         }
2205
2206                         if (cc)
2207                                 fprintf(fff, "%s", cc);
2208                         else
2209                                 fprintf(fff, "%c", c);
2210                 }
2211         }
2212
2213         fprintf(fff, "</font>");
2214         if (!tmpfff)
2215         {
2216                 for (int i = 0; html_foot[i]; i++)
2217                         fputs(html_foot[i], fff);
2218         }
2219         else
2220         {
2221                 rewind(tmpfff);
2222                 bool is_first_line = TRUE;
2223                 while (!my_fgets(tmpfff, buf, sizeof(buf)))
2224                 {
2225                         if (is_first_line)
2226                         {
2227                                 if (strncmp(buf, tags[2], strlen(tags[2])) == 0)
2228                                         is_first_line = FALSE;
2229                         }
2230                         else
2231                         {
2232                                 if (strncmp(buf, tags[3], strlen(tags[3])) == 0)
2233                                         break;
2234                                 fprintf(fff, "%s\n", buf);
2235                         }
2236                 }
2237
2238                 my_fclose(tmpfff);
2239         }
2240
2241         fprintf(fff, "\n");
2242         my_fclose(fff);
2243         if (message)
2244         {
2245                 msg_print(_("画面(記念撮影)をファイルに書き出しました。", "Screen dump saved."));
2246                 msg_print(NULL);
2247         }
2248
2249         if (message)
2250                 screen_load();
2251 }
2252
2253
2254 /*
2255  * Hack -- save a screen dump to a file
2256  */
2257 static void do_cmd_save_screen_html(void)
2258 {
2259         char buf[1024], tmp[256] = "screen.html";
2260
2261         if (!get_string(_("ファイル名: ", "File name: "), tmp, 80))
2262                 return;
2263         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, tmp);
2264
2265         msg_print(NULL);
2266
2267         do_cmd_save_screen_html_aux(buf, 1);
2268 }
2269
2270
2271 /*
2272  * Redefinable "save_screen" action
2273  */
2274 void(*screendump_aux)(void) = NULL;
2275
2276
2277 /*
2278  * Save a screen dump to a file
2279  * @param creature_ptr プレーヤーへの参照ポインタ
2280  * @return なし
2281  */
2282 void do_cmd_save_screen(player_type *creature_ptr)
2283 {
2284         prt(_("記念撮影しますか? [(y)es/(h)tml/(n)o] ", "Save screen dump? [(y)es/(h)tml/(n)o] "), 0, 0);
2285         bool html_dump = FALSE;
2286         while (TRUE)
2287         {
2288                 char c = inkey();
2289                 if (c == 'Y' || c == 'y')
2290                         break;
2291                 else if (c == 'H' || c == 'h')
2292                 {
2293                         html_dump = TRUE;
2294                         break;
2295                 }
2296                 else
2297                 {
2298                         prt("", 0, 0);
2299                         return;
2300                 }
2301         }
2302
2303         int wid, hgt;
2304         Term_get_size(&wid, &hgt);
2305
2306         bool old_use_graphics = use_graphics;
2307         if (old_use_graphics)
2308         {
2309                 use_graphics = FALSE;
2310                 reset_visuals(creature_ptr);
2311                 creature_ptr->redraw |= (PR_WIPE | PR_BASIC | PR_EXTRA | PR_MAP | PR_EQUIPPY);
2312                 handle_stuff(creature_ptr);
2313         }
2314
2315         if (html_dump)
2316         {
2317                 do_cmd_save_screen_html();
2318                 do_cmd_redraw(creature_ptr);
2319         }
2320         else if (screendump_aux)
2321         {
2322                 (*screendump_aux)();
2323         }
2324         else
2325         {
2326                 TERM_LEN y, x;
2327                 TERM_COLOR a = 0;
2328                 SYMBOL_CODE c = ' ';
2329                 FILE *fff;
2330                 char buf[1024];
2331                 path_build(buf, sizeof(buf), ANGBAND_DIR_USER, "dump.txt");
2332                 FILE_TYPE(FILE_TYPE_TEXT);
2333                 fff = my_fopen(buf, "w");
2334                 if (!fff)
2335                 {
2336                         msg_format(_("ファイル %s を開けませんでした。", "Failed to open file %s."), buf);
2337                         msg_print(NULL);
2338                         return;
2339                 }
2340
2341                 screen_save();
2342                 for (y = 0; y < hgt; y++)
2343                 {
2344                         for (x = 0; x < wid - 1; x++)
2345                         {
2346                                 (void)(Term_what(x, y, &a, &c));
2347                                 buf[x] = c;
2348                         }
2349
2350                         buf[x] = '\0';
2351                         fprintf(fff, "%s\n", buf);
2352                 }
2353
2354                 fprintf(fff, "\n");
2355                 for (y = 0; y < hgt; y++)
2356                 {
2357                         for (x = 0; x < wid - 1; x++)
2358                         {
2359                                 (void)(Term_what(x, y, &a, &c));
2360                                 buf[x] = hack[a & 0x0F];
2361                         }
2362
2363                         buf[x] = '\0';
2364                         fprintf(fff, "%s\n", buf);
2365                 }
2366
2367                 fprintf(fff, "\n");
2368                 my_fclose(fff);
2369                 msg_print(_("画面(記念撮影)をファイルに書き出しました。", "Screen dump saved."));
2370                 msg_print(NULL);
2371                 screen_load();
2372         }
2373
2374         if (!old_use_graphics) return;
2375
2376         use_graphics = TRUE;
2377         reset_visuals(creature_ptr);
2378         creature_ptr->redraw |= (PR_WIPE | PR_BASIC | PR_EXTRA | PR_MAP | PR_EQUIPPY);
2379         handle_stuff(creature_ptr);
2380 }
2381
2382
2383 /*
2384  * todo okay = 既知のアーティファクト? と思われるが確証がない
2385  * 分かりやすい変数名へ変更求む&万が一未知である旨の配列なら負論理なのでゴソッと差し替えるべき
2386  * Check the status of "artifacts"
2387  * @param player_ptr プレーヤーへの参照ポインタ
2388  * @return なし
2389  */
2390 static void do_cmd_knowledge_artifacts(player_type *player_ptr)
2391 {
2392         FILE *fff;
2393         GAME_TEXT file_name[1024];
2394         fff = my_fopen_temp(file_name, 1024);
2395         if (!fff)
2396         {
2397                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
2398                 msg_print(NULL);
2399                 return;
2400         }
2401
2402         ARTIFACT_IDX *who;
2403         C_MAKE(who, max_a_idx, ARTIFACT_IDX);
2404         bool *okay;
2405         C_MAKE(okay, max_a_idx, bool);
2406
2407         for (ARTIFACT_IDX k = 0; k < max_a_idx; k++)
2408         {
2409                 artifact_type *a_ptr = &a_info[k];
2410                 okay[k] = FALSE;
2411                 if (!a_ptr->name) continue;
2412                 if (!a_ptr->cur_num) continue;
2413
2414                 okay[k] = TRUE;
2415         }
2416
2417         for (POSITION y = 0; y < player_ptr->current_floor_ptr->height; y++)
2418         {
2419                 for (POSITION x = 0; x < player_ptr->current_floor_ptr->width; x++)
2420                 {
2421                         grid_type *g_ptr = &player_ptr->current_floor_ptr->grid_array[y][x];
2422                         OBJECT_IDX this_o_idx, next_o_idx = 0;
2423                         for (this_o_idx = g_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx)
2424                         {
2425                                 object_type *o_ptr;
2426                                 o_ptr = &player_ptr->current_floor_ptr->o_list[this_o_idx];
2427                                 next_o_idx = o_ptr->next_o_idx;
2428                                 if (!object_is_fixed_artifact(o_ptr)) continue;
2429                                 if (object_is_known(o_ptr)) continue;
2430
2431                                 okay[o_ptr->name1] = FALSE;
2432                         }
2433                 }
2434         }
2435
2436         for (ARTIFACT_IDX i = 0; i < INVEN_TOTAL; i++)
2437         {
2438                 object_type *o_ptr = &player_ptr->inventory_list[i];
2439                 if (!o_ptr->k_idx) continue;
2440                 if (!object_is_fixed_artifact(o_ptr)) continue;
2441                 if (object_is_known(o_ptr)) continue;
2442
2443                 okay[o_ptr->name1] = FALSE;
2444         }
2445
2446         int n = 0;
2447         for (ARTIFACT_IDX k = 0; k < max_a_idx; k++)
2448         {
2449                 if (okay[k]) who[n++] = k;
2450         }
2451
2452         u16b why = 3;
2453         ang_sort(who, &why, n, ang_sort_art_comp, ang_sort_art_swap);
2454         for (ARTIFACT_IDX k = 0; k < n; k++)
2455         {
2456                 artifact_type *a_ptr = &a_info[who[k]];
2457                 GAME_TEXT base_name[MAX_NLEN];
2458                 strcpy(base_name, _("未知の伝説のアイテム", "Unknown Artifact"));
2459                 ARTIFACT_IDX z = lookup_kind(a_ptr->tval, a_ptr->sval);
2460                 if (z)
2461                 {
2462                         object_type forge;
2463                         object_type *q_ptr;
2464                         q_ptr = &forge;
2465                         object_prep(q_ptr, z);
2466                         q_ptr->name1 = (byte)who[k];
2467                         q_ptr->ident |= IDENT_STORE;
2468                         object_desc(player_ptr, base_name, q_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY));
2469                 }
2470
2471                 fprintf(fff, _("     %s\n", "     The %s\n"), base_name);
2472         }
2473
2474         C_KILL(who, max_a_idx, ARTIFACT_IDX);
2475         C_KILL(okay, max_a_idx, bool);
2476         my_fclose(fff);
2477         (void)show_file(player_ptr, TRUE, file_name, _("既知の伝説のアイテム", "Artifacts Seen"), 0, 0);
2478         fd_kill(file_name);
2479 }
2480
2481
2482 /*
2483  * Display known uniques
2484  * With "XTRA HACK UNIQHIST" (Originally from XAngband)
2485  */
2486 static void do_cmd_knowledge_uniques(player_type *creature_ptr)
2487 {
2488         u16b why = 2;
2489         IDX *who;
2490         GAME_TEXT file_name[1024];
2491         int n_alive[10];
2492         int n_alive_surface = 0;
2493         int n_alive_over100 = 0;
2494         int n_alive_total = 0;
2495         int max_lev = -1;
2496         for (IDX i = 0; i < 10; i++)
2497                 n_alive[i] = 0;
2498
2499         FILE *fff;
2500         fff = my_fopen_temp(file_name, 1024);
2501         if (!fff)
2502         {
2503                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
2504                 msg_print(NULL);
2505                 return;
2506         }
2507
2508         C_MAKE(who, max_r_idx, MONRACE_IDX);
2509         int n = 0;
2510         for (IDX i = 1; i < max_r_idx; i++)
2511         {
2512                 monster_race *r_ptr = &r_info[i];
2513                 if (!r_ptr->name) continue;
2514                 if (!(r_ptr->flags1 & RF1_UNIQUE)) continue;
2515                 if (!cheat_know && !r_ptr->r_sights) continue;
2516                 if (!r_ptr->rarity || ((r_ptr->rarity > 100) && !(r_ptr->flags1 & RF1_QUESTOR))) continue;
2517                 if (r_ptr->max_num == 0) continue;
2518
2519                 if (r_ptr->level)
2520                 {
2521                         int lev = (r_ptr->level - 1) / 10;
2522                         if (lev < 10)
2523                         {
2524                                 n_alive[lev]++;
2525                                 if (max_lev < lev) max_lev = lev;
2526                         }
2527                         else
2528                                 n_alive_over100++;
2529                 }
2530                 else
2531                         n_alive_surface++;
2532
2533                 who[n++] = i;
2534         }
2535
2536         ang_sort(who, &why, n, ang_sort_comp_hook, ang_sort_swap_hook);
2537         if (n_alive_surface)
2538         {
2539                 fprintf(fff, _("     地上  生存: %3d体\n", "      Surface  alive: %3d\n"), n_alive_surface);
2540                 n_alive_total += n_alive_surface;
2541         }
2542
2543         for (IDX i = 0; i <= max_lev; i++)
2544         {
2545                 fprintf(fff, _("%3d-%3d階  生存: %3d体\n", "Level %3d-%3d  alive: %3d\n"), 1 + i * 10, 10 + i * 10, n_alive[i]);
2546                 n_alive_total += n_alive[i];
2547         }
2548
2549         if (n_alive_over100)
2550         {
2551                 fprintf(fff, _("101-   階  生存: %3d体\n", "Level 101-     alive: %3d\n"), n_alive_over100);
2552                 n_alive_total += n_alive_over100;
2553         }
2554
2555         if (n_alive_total)
2556         {
2557                 fputs(_("---------  -----------\n", "-------------  ----------\n"), fff);
2558                 fprintf(fff, _("     合計  生存: %3d体\n\n", "        Total  alive: %3d\n\n"), n_alive_total);
2559         }
2560         else
2561         {
2562                 fputs(_("現在は既知の生存ユニークはいません。\n", "No known uniques alive.\n"), fff);
2563         }
2564
2565         for (int k = 0; k < n; k++)
2566         {
2567                 monster_race *r_ptr = &r_info[who[k]];
2568                 fprintf(fff, _("     %s (レベル%d)\n", "     %s (level %d)\n"), r_name + r_ptr->name, (int)r_ptr->level);
2569         }
2570
2571         C_KILL(who, max_r_idx, s16b);
2572         my_fclose(fff);
2573         (void)show_file(creature_ptr, TRUE, file_name, _("まだ生きているユニーク・モンスター", "Alive Uniques"), 0, 0);
2574         fd_kill(file_name);
2575 }
2576
2577
2578 /*
2579  * Display weapon-exp
2580  */
2581 static void do_cmd_knowledge_weapon_exp(player_type *creature_ptr)
2582 {
2583         FILE *fff;
2584         GAME_TEXT file_name[1024];
2585         fff = my_fopen_temp(file_name, 1024);
2586         if (!fff)
2587         {
2588                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
2589                 msg_print(NULL);
2590                 return;
2591         }
2592
2593         for (int i = 0; i < 5; i++)
2594         {
2595                 for (int num = 0; num < 64; num++)
2596                 {
2597                         SUB_EXP weapon_exp;
2598                         char tmp[30];
2599                         for (KIND_OBJECT_IDX j = 0; j < max_k_idx; j++)
2600                         {
2601                                 object_kind *k_ptr = &k_info[j];
2602
2603                                 if ((k_ptr->tval != TV_SWORD - i) || (k_ptr->sval != num)) continue;
2604                                 if ((k_ptr->tval == TV_BOW) && (k_ptr->sval == SV_CRIMSON || k_ptr->sval == SV_HARP)) continue;
2605
2606                                 weapon_exp = creature_ptr->weapon_exp[4 - i][num];
2607                                 strip_name(tmp, j);
2608                                 fprintf(fff, "%-25s ", tmp);
2609                                 if (weapon_exp >= s_info[creature_ptr->pclass].w_max[4 - i][num]) fprintf(fff, "!");
2610                                 else fprintf(fff, " ");
2611                                 fprintf(fff, "%s", exp_level_str[weapon_exp_level(weapon_exp)]);
2612                                 if (cheat_xtra) fprintf(fff, " %d", weapon_exp);
2613                                 fprintf(fff, "\n");
2614                                 break;
2615                         }
2616                 }
2617         }
2618
2619         my_fclose(fff);
2620         (void)show_file(creature_ptr, TRUE, file_name, _("武器の経験値", "Weapon Proficiency"), 0, 0);
2621         fd_kill(file_name);
2622 }
2623
2624
2625 /*!
2626  * @brief 魔法の経験値を表示するコマンドのメインルーチン
2627  * Display spell-exp
2628  * @return なし
2629  */
2630 static void do_cmd_knowledge_spell_exp(player_type *creature_ptr)
2631 {
2632         FILE *fff;
2633         GAME_TEXT file_name[1024];
2634         fff = my_fopen_temp(file_name, 1024);
2635         if (!fff)
2636         {
2637                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
2638                 msg_print(NULL);
2639                 return;
2640         }
2641
2642         if (creature_ptr->realm1 != REALM_NONE)
2643         {
2644                 fprintf(fff, _("%sの魔法書\n", "%s Spellbook\n"), realm_names[creature_ptr->realm1]);
2645                 for (SPELL_IDX i = 0; i < 32; i++)
2646                 {
2647                         const magic_type *s_ptr;
2648                         if (!is_magic(creature_ptr->realm1))
2649                         {
2650                                 s_ptr = &technic_info[creature_ptr->realm1 - MIN_TECHNIC][i];
2651                         }
2652                         else
2653                         {
2654                                 s_ptr = &mp_ptr->info[creature_ptr->realm1 - 1][i];
2655                         }
2656
2657                         if (s_ptr->slevel >= 99) continue;
2658                         SUB_EXP spell_exp = creature_ptr->spell_exp[i];
2659                         int exp_level = spell_exp_level(spell_exp);
2660                         fprintf(fff, "%-25s ", exe_spell(creature_ptr, creature_ptr->realm1, i, SPELL_NAME));
2661                         if (creature_ptr->realm1 == REALM_HISSATSU)
2662                                 fprintf(fff, "[--]");
2663                         else
2664                         {
2665                                 if (exp_level >= EXP_LEVEL_MASTER) fprintf(fff, "!");
2666                                 else fprintf(fff, " ");
2667                                 fprintf(fff, "%s", exp_level_str[exp_level]);
2668                         }
2669
2670                         if (cheat_xtra) fprintf(fff, " %d", spell_exp);
2671                         fprintf(fff, "\n");
2672                 }
2673         }
2674
2675         if (creature_ptr->realm2 != REALM_NONE)
2676         {
2677                 fprintf(fff, _("%sの魔法書\n", "\n%s Spellbook\n"), realm_names[creature_ptr->realm2]);
2678                 for (SPELL_IDX i = 0; i < 32; i++)
2679                 {
2680                         const magic_type *s_ptr;
2681                         if (!is_magic(creature_ptr->realm1))
2682                         {
2683                                 s_ptr = &technic_info[creature_ptr->realm2 - MIN_TECHNIC][i];
2684                         }
2685                         else
2686                         {
2687                                 s_ptr = &mp_ptr->info[creature_ptr->realm2 - 1][i];
2688                         }
2689
2690                         if (s_ptr->slevel >= 99) continue;
2691
2692                         SUB_EXP spell_exp = creature_ptr->spell_exp[i + 32];
2693                         int exp_level = spell_exp_level(spell_exp);
2694                         fprintf(fff, "%-25s ", exe_spell(creature_ptr, creature_ptr->realm2, i, SPELL_NAME));
2695                         if (exp_level >= EXP_LEVEL_EXPERT) fprintf(fff, "!");
2696                         else fprintf(fff, " ");
2697                         fprintf(fff, "%s", exp_level_str[exp_level]);
2698                         if (cheat_xtra) fprintf(fff, " %d", spell_exp);
2699                         fprintf(fff, "\n");
2700                 }
2701         }
2702
2703         my_fclose(fff);
2704         (void)show_file(creature_ptr, TRUE, file_name, _("魔法の経験値", "Spell Proficiency"), 0, 0);
2705         fd_kill(file_name);
2706 }
2707
2708
2709 /*!
2710  * @brief スキル情報を表示するコマンドのメインルーチン /
2711  * Display skill-exp
2712  * @return なし
2713  */
2714 static void do_cmd_knowledge_skill_exp(player_type *creature_ptr)
2715 {
2716         char skill_name[GINOU_TEMPMAX][20] =
2717         {
2718                 _("マーシャルアーツ", "Martial Arts    "),
2719                 _("二刀流          ", "Dual Wielding   "),
2720                 _("乗馬            ", "Riding          "),
2721                 _("盾              ", "Shield          ")
2722         };
2723
2724         FILE *fff;
2725         char file_name[1024];
2726         fff = my_fopen_temp(file_name, 1024);
2727         if (!fff)
2728         {
2729                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
2730                 msg_print(NULL);
2731                 return;
2732         }
2733
2734         for (int i = 0; i < GINOU_TEMPMAX; i++)
2735         {
2736                 int skill_exp = creature_ptr->skill_exp[i];
2737                 fprintf(fff, "%-20s ", skill_name[i]);
2738                 if (skill_exp >= s_info[creature_ptr->pclass].s_max[i]) fprintf(fff, "!");
2739                 else fprintf(fff, " ");
2740                 fprintf(fff, "%s", exp_level_str[(i == GINOU_RIDING) ? riding_exp_level(skill_exp) : weapon_exp_level(skill_exp)]);
2741                 if (cheat_xtra) fprintf(fff, " %d", skill_exp);
2742                 fprintf(fff, "\n");
2743         }
2744
2745         my_fclose(fff);
2746         (void)show_file(creature_ptr, TRUE, file_name, _("技能の経験値", "Miscellaneous Proficiency"), 0, 0);
2747         fd_kill(file_name);
2748 }
2749
2750
2751 /*!
2752  * @brief 現在のペットを表示するコマンドのメインルーチン /
2753  * Display current pets
2754  * @param creature_ptr プレーヤーへの参照ポインタ
2755  * @return なし
2756  */
2757 static void do_cmd_knowledge_pets(player_type *creature_ptr)
2758 {
2759         GAME_TEXT file_name[1024];
2760         FILE *fff;
2761         fff = my_fopen_temp(file_name, 1024);
2762         if (!fff)
2763         {
2764                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
2765                 msg_print(NULL);
2766                 return;
2767         }
2768
2769         monster_type *m_ptr;
2770         GAME_TEXT pet_name[MAX_NLEN];
2771         int t_friends = 0;
2772         for (int i = creature_ptr->current_floor_ptr->m_max - 1; i >= 1; i--)
2773         {
2774                 m_ptr = &creature_ptr->current_floor_ptr->m_list[i];
2775                 if (!monster_is_valid(m_ptr)) continue;
2776                 if (!is_pet(m_ptr)) continue;
2777
2778                 t_friends++;
2779                 monster_desc(creature_ptr, pet_name, m_ptr, MD_ASSUME_VISIBLE | MD_INDEF_VISIBLE);
2780                 fprintf(fff, "%s (%s)\n", pet_name, look_mon_desc(m_ptr, 0x00));
2781         }
2782
2783         int show_upkeep = calculate_upkeep(creature_ptr);
2784
2785         fprintf(fff, "----------------------------------------------\n");
2786 #ifdef JP
2787         fprintf(fff, "    合計: %d 体のペット\n", t_friends);
2788 #else
2789         fprintf(fff, "   Total: %d pet%s.\n", t_friends, (t_friends == 1 ? "" : "s"));
2790 #endif
2791         fprintf(fff, _(" 維持コスト: %d%% MP\n", "   Upkeep: %d%% mana.\n"), show_upkeep);
2792
2793         my_fclose(fff);
2794         (void)show_file(creature_ptr, TRUE, file_name, _("現在のペット", "Current Pets"), 0, 0);
2795         fd_kill(file_name);
2796 }
2797
2798
2799 /*!
2800  * @brief 現在のペットを表示するコマンドのメインルーチン /
2801  * @param creature_ptr プレーヤーへの参照ポインタ
2802  * Total kill count
2803  * @return なし
2804  * @note the player ghosts are ignored.
2805  */
2806 static void do_cmd_knowledge_kill_count(player_type *creature_ptr)
2807 {
2808         FILE *fff;
2809         GAME_TEXT file_name[1024];
2810         fff = my_fopen_temp(file_name, 1024);
2811         if (!fff)
2812         {
2813                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
2814                 msg_print(NULL);
2815                 return;
2816         }
2817
2818         MONRACE_IDX *who;
2819         C_MAKE(who, max_r_idx, MONRACE_IDX);
2820         s32b total = 0;
2821         for (int kk = 1; kk < max_r_idx; kk++)
2822         {
2823                 monster_race *r_ptr = &r_info[kk];
2824
2825                 if (r_ptr->flags1 & (RF1_UNIQUE))
2826                 {
2827                         bool dead = (r_ptr->max_num == 0);
2828
2829                         if (dead)
2830                         {
2831                                 total++;
2832                         }
2833                 }
2834                 else
2835                 {
2836                         MONSTER_NUMBER this_monster = r_ptr->r_pkills;
2837
2838                         if (this_monster > 0)
2839                         {
2840                                 total += this_monster;
2841                         }
2842                 }
2843         }
2844
2845         if (total < 1)
2846                 fprintf(fff, _("あなたはまだ敵を倒していない。\n\n", "You have defeated no enemies yet.\n\n"));
2847         else
2848 #ifdef JP
2849                 fprintf(fff, "あなたは%ld体の敵を倒している。\n\n", (long int)total);
2850 #else
2851                 fprintf(fff, "You have defeated %ld %s.\n\n", (long int)total, (total == 1) ? "enemy" : "enemies");
2852 #endif
2853
2854         total = 0;
2855         int n = 0;
2856         for (MONRACE_IDX i = 1; i < max_r_idx; i++)
2857         {
2858                 monster_race *r_ptr = &r_info[i];
2859                 if (r_ptr->name) who[n++] = i;
2860         }
2861
2862         u16b why = 2;
2863         ang_sort(who, &why, n, ang_sort_comp_hook, ang_sort_swap_hook);
2864         for (int k = 0; k < n; k++)
2865         {
2866                 monster_race *r_ptr = &r_info[who[k]];
2867                 if (r_ptr->flags1 & (RF1_UNIQUE))
2868                 {
2869                         bool dead = (r_ptr->max_num == 0);
2870                         if (dead)
2871                         {
2872                                 fprintf(fff, "     %s\n", (r_name + r_ptr->name));
2873                                 total++;
2874                         }
2875
2876                         continue;
2877                 }
2878
2879                 MONSTER_NUMBER this_monster = r_ptr->r_pkills;
2880                 if (this_monster <= 0) continue;
2881
2882 #ifdef JP
2883                 if (my_strchr("pt", r_ptr->d_char))
2884                         fprintf(fff, "     %3d 人の %s\n", (int)this_monster, r_name + r_ptr->name);
2885                 else
2886                         fprintf(fff, "     %3d 体の %s\n", (int)this_monster, r_name + r_ptr->name);
2887 #else
2888                 if (this_monster < 2)
2889                 {
2890                         if (my_strstr(r_name + r_ptr->name, "coins"))
2891                         {
2892                                 fprintf(fff, "     1 pile of %s\n", (r_name + r_ptr->name));
2893                         }
2894                         else
2895                         {
2896                                 fprintf(fff, "     1 %s\n", (r_name + r_ptr->name));
2897                         }
2898                 }
2899                 else
2900                 {
2901                         char ToPlural[80];
2902                         strcpy(ToPlural, (r_name + r_ptr->name));
2903                         plural_aux(ToPlural);
2904                         fprintf(fff, "     %d %s\n", this_monster, ToPlural);
2905                 }
2906 #endif
2907                 total += this_monster;
2908         }
2909
2910         fprintf(fff, "----------------------------------------------\n");
2911 #ifdef JP
2912         fprintf(fff, "    合計: %lu 体を倒した。\n", (unsigned long int)total);
2913 #else
2914         fprintf(fff, "   Total: %lu creature%s killed.\n", (unsigned long int)total, (total == 1 ? "" : "s"));
2915 #endif
2916
2917         C_KILL(who, max_r_idx, s16b);
2918         my_fclose(fff);
2919         (void)show_file(creature_ptr, TRUE, file_name, _("倒した敵の数", "Kill Count"), 0, 0);
2920         fd_kill(file_name);
2921 }
2922
2923
2924 /*!
2925  * @brief モンスター情報リスト中のグループを表示する /
2926  * Display the object groups.
2927  * @param col 開始行
2928  * @param row 開始列
2929  * @param wid 表示文字数幅
2930  * @param per_page リストの表示行
2931  * @param grp_idx グループのID配列
2932  * @param group_text グループ名の文字列配列
2933  * @param grp_cur 現在の選択ID
2934  * @param grp_top 現在の選択リスト最上部ID
2935  * @return なし
2936  */
2937 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)
2938 {
2939         for (int i = 0; i < per_page && (grp_idx[i] >= 0); i++)
2940         {
2941                 int grp = grp_idx[grp_top + i];
2942                 TERM_COLOR attr = (grp_top + i == grp_cur) ? TERM_L_BLUE : TERM_WHITE;
2943                 Term_erase(col, row + i, wid);
2944                 c_put_str(attr, group_text[grp], row + i, col);
2945         }
2946 }
2947
2948
2949 /*
2950  * Move the cursor in a browser window
2951  */
2952 static void browser_cursor(char ch, int *column, IDX *grp_cur, int grp_cnt, IDX *list_cur, int list_cnt)
2953 {
2954         int d;
2955         int col = *column;
2956         IDX grp = *grp_cur;
2957         IDX list = *list_cur;
2958         if (ch == ' ')
2959                 d = 3;
2960         else if (ch == '-')
2961                 d = 9;
2962         else
2963                 d = get_keymap_dir(ch);
2964
2965         if (!d) return;
2966
2967         if ((ddx[d] > 0) && ddy[d])
2968         {
2969                 int browser_rows;
2970                 int wid, hgt;
2971                 Term_get_size(&wid, &hgt);
2972                 browser_rows = hgt - 8;
2973                 if (!col)
2974                 {
2975                         int old_grp = grp;
2976                         grp += ddy[d] * (browser_rows - 1);
2977                         if (grp >= grp_cnt)     grp = grp_cnt - 1;
2978                         if (grp < 0) grp = 0;
2979                         if (grp != old_grp)     list = 0;
2980                 }
2981                 else
2982                 {
2983                         list += ddy[d] * browser_rows;
2984                         if (list >= list_cnt) list = list_cnt - 1;
2985                         if (list < 0) list = 0;
2986                 }
2987
2988                 (*grp_cur) = grp;
2989                 (*list_cur) = list;
2990                 return;
2991         }
2992
2993         if (ddx[d])
2994         {
2995                 col += ddx[d];
2996                 if (col < 0) col = 0;
2997                 if (col > 1) col = 1;
2998
2999                 (*column) = col;
3000                 return;
3001         }
3002
3003         if (!col)
3004         {
3005                 int old_grp = grp;
3006                 grp += (IDX)ddy[d];
3007                 if (grp >= grp_cnt)     grp = grp_cnt - 1;
3008                 if (grp < 0) grp = 0;
3009                 if (grp != old_grp)     list = 0;
3010         }
3011         else
3012         {
3013                 list += (IDX)ddy[d];
3014                 if (list >= list_cnt) list = list_cnt - 1;
3015                 if (list < 0) list = 0;
3016         }
3017
3018         (*grp_cur) = grp;
3019         (*list_cur) = list;
3020 }
3021
3022
3023 /*
3024  * Display visuals.
3025  */
3026 static void display_visual_list(int col, int row, int height, int width, TERM_COLOR attr_top, byte char_left)
3027 {
3028         for (int i = 0; i < height; i++)
3029         {
3030                 Term_erase(col, row + i, width);
3031         }
3032
3033         if (use_bigtile) width /= 2;
3034
3035         for (int i = 0; i < height; i++)
3036         {
3037                 for (int j = 0; j < width; j++)
3038                 {
3039                         TERM_LEN x = col + j;
3040                         TERM_LEN y = row + i;
3041                         if (use_bigtile) x += j;
3042
3043                         TERM_COLOR ia = attr_top + i;
3044                         SYMBOL_CODE ic = char_left + j;
3045                         if (ia > 0x7f || ic > 0xff || ic < ' ' ||
3046                                 (!use_graphics && ic > 0x7f))
3047                                 continue;
3048
3049                         TERM_COLOR a = ia;
3050                         SYMBOL_CODE c = ic;
3051                         if (c & 0x80) a |= 0x80;
3052
3053                         Term_queue_bigchar(x, y, a, c, 0, 0);
3054                 }
3055         }
3056 }
3057
3058
3059 /*
3060  * Place the cursor at the collect position for visual mode
3061  */
3062 static void place_visual_list_cursor(TERM_LEN col, TERM_LEN row, TERM_COLOR a, byte c, TERM_COLOR attr_top, byte char_left)
3063 {
3064         int i = (a & 0x7f) - attr_top;
3065         int j = c - char_left;
3066
3067         TERM_LEN x = col + j;
3068         TERM_LEN y = row + i;
3069         if (use_bigtile) x += j;
3070
3071         Term_gotoxy(x, y);
3072 }
3073
3074
3075 /*
3076  *  Do visual mode command -- Change symbols
3077  */
3078 static bool visual_mode_command(char ch, bool *visual_list_ptr,
3079         int height, int width,
3080         TERM_COLOR *attr_top_ptr, byte *char_left_ptr,
3081         TERM_COLOR *cur_attr_ptr, SYMBOL_CODE *cur_char_ptr, bool *need_redraw)
3082 {
3083         static TERM_COLOR attr_old = 0;
3084         static SYMBOL_CODE char_old = 0;
3085
3086         switch (ch)
3087         {
3088         case ESCAPE:
3089                 if (*visual_list_ptr)
3090                 {
3091                         *cur_attr_ptr = attr_old;
3092                         *cur_char_ptr = char_old;
3093                         *visual_list_ptr = FALSE;
3094
3095                         return TRUE;
3096                 }
3097
3098                 break;
3099
3100         case '\n':
3101         case '\r':
3102                 if (*visual_list_ptr)
3103                 {
3104                         *visual_list_ptr = FALSE;
3105                         *need_redraw = TRUE;
3106
3107                         return TRUE;
3108                 }
3109
3110                 break;
3111
3112         case 'V':
3113         case 'v':
3114                 if (!*visual_list_ptr)
3115                 {
3116                         *visual_list_ptr = TRUE;
3117
3118                         *attr_top_ptr = MAX(0, (*cur_attr_ptr & 0x7f) - 5);
3119                         *char_left_ptr = MAX(0, *cur_char_ptr - 10);
3120
3121                         attr_old = *cur_attr_ptr;
3122                         char_old = *cur_char_ptr;
3123
3124                         return TRUE;
3125                 }
3126
3127                 break;
3128
3129         case 'C':
3130         case 'c':
3131         {
3132                 attr_idx = *cur_attr_ptr;
3133                 char_idx = *cur_char_ptr;
3134                 for (int i = 0; i < F_LIT_MAX; i++)
3135                 {
3136                         attr_idx_feat[i] = 0;
3137                         char_idx_feat[i] = 0;
3138                 }
3139         }
3140
3141         return TRUE;
3142
3143         case 'P':
3144         case 'p':
3145                 if (attr_idx || (!(char_idx & 0x80) && char_idx))
3146                 {
3147                         *cur_attr_ptr = attr_idx;
3148                         *attr_top_ptr = MAX(0, (*cur_attr_ptr & 0x7f) - 5);
3149                         if (!*visual_list_ptr) *need_redraw = TRUE;
3150                 }
3151
3152                 if (char_idx)
3153                 {
3154                         /* Set the char */
3155                         *cur_char_ptr = char_idx;
3156                         *char_left_ptr = MAX(0, *cur_char_ptr - 10);
3157                         if (!*visual_list_ptr) *need_redraw = TRUE;
3158                 }
3159
3160                 return TRUE;
3161
3162         default:
3163                 if (*visual_list_ptr)
3164                 {
3165                         int eff_width;
3166                         int d = get_keymap_dir(ch);
3167                         TERM_COLOR a = (*cur_attr_ptr & 0x7f);
3168                         SYMBOL_CODE c = *cur_char_ptr;
3169
3170                         if (use_bigtile) eff_width = width / 2;
3171                         else eff_width = width;
3172
3173                         if ((a == 0) && (ddy[d] < 0)) d = 0;
3174                         if ((c == 0) && (ddx[d] < 0)) d = 0;
3175                         if ((a == 0x7f) && (ddy[d] > 0)) d = 0;
3176                         if ((c == 0xff) && (ddx[d] > 0)) d = 0;
3177
3178                         a += (TERM_COLOR)ddy[d];
3179                         c += (SYMBOL_CODE)ddx[d];
3180                         if (c & 0x80) a |= 0x80;
3181
3182                         *cur_attr_ptr = a;
3183                         *cur_char_ptr = c;
3184                         if ((ddx[d] < 0) && *char_left_ptr > MAX(0, (int)c - 10)) (*char_left_ptr)--;
3185                         if ((ddx[d] > 0) && *char_left_ptr + eff_width < MIN(0xff, (int)c + 10)) (*char_left_ptr)++;
3186                         if ((ddy[d] < 0) && *attr_top_ptr > MAX(0, (int)(a & 0x7f) - 4)) (*attr_top_ptr)--;
3187                         if ((ddy[d] > 0) && *attr_top_ptr + height < MIN(0x7f, (a & 0x7f) + 4)) (*attr_top_ptr)++;
3188                         return TRUE;
3189                 }
3190
3191                 break;
3192         }
3193
3194         return FALSE;
3195 }
3196
3197
3198 /*
3199  * Display the monsters in a group.
3200  */
3201 static void display_monster_list(int col, int row, int per_page, s16b mon_idx[], int mon_cur, int mon_top, bool visual_only)
3202 {
3203         int i;
3204         for (i = 0; i < per_page && (mon_idx[mon_top + i] >= 0); i++)
3205         {
3206                 TERM_COLOR attr;
3207                 MONRACE_IDX r_idx = mon_idx[mon_top + i];
3208                 monster_race *r_ptr = &r_info[r_idx];
3209                 attr = ((i + mon_top == mon_cur) ? TERM_L_BLUE : TERM_WHITE);
3210                 c_prt(attr, (r_name + r_ptr->name), row + i, col);
3211                 if (per_page == 1)
3212                 {
3213                         c_prt(attr, format("%02x/%02x", r_ptr->x_attr, r_ptr->x_char), row + i, (current_world_ptr->wizard || visual_only) ? 56 : 61);
3214                 }
3215
3216                 if (current_world_ptr->wizard || visual_only)
3217                 {
3218                         c_prt(attr, format("%d", r_idx), row + i, 62);
3219                 }
3220
3221                 Term_erase(69, row + i, 255);
3222                 Term_queue_bigchar(use_bigtile ? 69 : 70, row + i, r_ptr->x_attr, r_ptr->x_char, 0, 0);
3223                 if (!visual_only)
3224                 {
3225                         if (!(r_ptr->flags1 & RF1_UNIQUE))
3226                                 put_str(format("%5d", r_ptr->r_pkills), row + i, 73);
3227                         else
3228                                 c_put_str((r_ptr->max_num == 0 ? TERM_L_DARK : TERM_WHITE),
3229                                 (r_ptr->max_num == 0 ? _("死亡", " dead") : _("生存", "alive")), row + i, 74);
3230                 }
3231         }
3232
3233         for (; i < per_page; i++)
3234         {
3235                 Term_erase(col, row + i, 255);
3236         }
3237 }
3238
3239
3240 /*
3241  * todo 引数の詳細について加筆求む
3242  * Display known monsters.
3243  * @param creature_ptr プレーヤーへの参照ポインタ
3244  * @param need_redraw 画面の再描画が必要な時TRUE
3245  * @param visual_only ???
3246  * @param direct_r_idx モンスターID
3247  * @return なし
3248  */
3249 static void do_cmd_knowledge_monsters(player_type *creature_ptr, bool *need_redraw, bool visual_only, IDX direct_r_idx)
3250 {
3251         TERM_LEN wid, hgt;
3252         Term_get_size(&wid, &hgt);
3253         IDX *mon_idx;
3254         C_MAKE(mon_idx, max_r_idx, MONRACE_IDX);
3255
3256         int max = 0;
3257         IDX grp_cnt = 0;
3258         IDX grp_idx[100];
3259         IDX mon_cnt;
3260         bool visual_list = FALSE;
3261         TERM_COLOR attr_top = 0;
3262         byte char_left = 0;
3263         BIT_FLAGS8 mode;
3264         int browser_rows = hgt - 8;
3265         if (direct_r_idx < 0)
3266         {
3267                 mode = visual_only ? 0x03 : 0x01;
3268                 int len;
3269                 for (IDX i = 0; monster_group_text[i] != NULL; i++)
3270                 {
3271                         len = strlen(monster_group_text[i]);
3272                         if (len > max) max = len;
3273
3274                         if ((monster_group_char[i] == ((char *)-1L)) || collect_monsters(creature_ptr, i, mon_idx, mode))
3275                         {
3276                                 grp_idx[grp_cnt++] = i;
3277                         }
3278                 }
3279
3280                 mon_cnt = 0;
3281         }
3282         else
3283         {
3284                 mon_idx[0] = direct_r_idx;
3285                 mon_cnt = 1;
3286                 mon_idx[1] = -1;
3287
3288                 (void)visual_mode_command('v', &visual_list, browser_rows - 1, wid - (max + 3),
3289                         &attr_top, &char_left, &r_info[direct_r_idx].x_attr, &r_info[direct_r_idx].x_char, need_redraw);
3290         }
3291
3292         grp_idx[grp_cnt] = -1;
3293         mode = visual_only ? 0x02 : 0x00;
3294         IDX old_grp_cur = -1;
3295         IDX grp_cur = 0;
3296         IDX grp_top = 0;
3297         IDX mon_cur = 0;
3298         IDX mon_top = 0;
3299         int column = 0;
3300         bool flag = FALSE;
3301         bool redraw = TRUE;
3302         while (!flag)
3303         {
3304                 if (redraw)
3305                 {
3306                         clear_from(0);
3307                         prt(format(_("%s - モンスター", "%s - monsters"), !visual_only ? _("知識", "Knowledge") : _("表示", "Visuals")), 2, 0);
3308                         if (direct_r_idx < 0) prt(_("グループ", "Group"), 4, 0);
3309                         prt(_("名前", "Name"), 4, max + 3);
3310                         if (current_world_ptr->wizard || visual_only) prt("Idx", 4, 62);
3311                         prt(_("文字", "Sym"), 4, 67);
3312                         if (!visual_only) prt(_("殺害数", "Kills"), 4, 72);
3313
3314                         for (IDX i = 0; i < 78; i++)
3315                         {
3316                                 Term_putch(i, 5, TERM_WHITE, '=');
3317                         }
3318
3319                         if (direct_r_idx < 0)
3320                         {
3321                                 for (IDX i = 0; i < browser_rows; i++)
3322                                 {
3323                                         Term_putch(max + 1, 6 + i, TERM_WHITE, '|');
3324                                 }
3325                         }
3326
3327                         redraw = FALSE;
3328                 }
3329
3330                 if (direct_r_idx < 0)
3331                 {
3332                         if (grp_cur < grp_top) grp_top = grp_cur;
3333                         if (grp_cur >= grp_top + browser_rows) grp_top = grp_cur - browser_rows + 1;
3334
3335                         display_group_list(0, 6, max, browser_rows, grp_idx, monster_group_text, grp_cur, grp_top);
3336                         if (old_grp_cur != grp_cur)
3337                         {
3338                                 old_grp_cur = grp_cur;
3339                                 mon_cnt = collect_monsters(creature_ptr, grp_idx[grp_cur], mon_idx, mode);
3340                         }
3341
3342                         while (mon_cur < mon_top)
3343                                 mon_top = MAX(0, mon_top - browser_rows / 2);
3344                         while (mon_cur >= mon_top + browser_rows)
3345                                 mon_top = MIN(mon_cnt - browser_rows, mon_top + browser_rows / 2);
3346                 }
3347
3348                 if (!visual_list)
3349                 {
3350                         display_monster_list(max + 3, 6, browser_rows, mon_idx, mon_cur, mon_top, visual_only);
3351                 }
3352                 else
3353                 {
3354                         mon_top = mon_cur;
3355                         display_monster_list(max + 3, 6, 1, mon_idx, mon_cur, mon_top, visual_only);
3356                         display_visual_list(max + 3, 7, browser_rows - 1, wid - (max + 3), attr_top, char_left);
3357                 }
3358
3359                 prt(format(_("<方向>%s%s%s, ESC", "<dir>%s%s%s, ESC"),
3360                         (!visual_list && !visual_only) ? _(", 'r'で思い出を見る", ", 'r' to recall") : "",
3361                         visual_list ? _(", ENTERで決定", ", ENTER to accept") : _(", 'v'でシンボル変更", ", 'v' for visuals"),
3362                         (attr_idx || char_idx) ? _(", 'c', 'p'でペースト", ", 'c', 'p' to paste") : _(", 'c'でコピー", ", 'c' to copy")),
3363                         hgt - 1, 0);
3364
3365                 monster_race *r_ptr;
3366                 r_ptr = &r_info[mon_idx[mon_cur]];
3367
3368                 if (!visual_only)
3369                 {
3370                         if (mon_cnt) monster_race_track(creature_ptr, mon_idx[mon_cur]);
3371                         handle_stuff(creature_ptr);
3372                 }
3373
3374                 if (visual_list)
3375                 {
3376                         place_visual_list_cursor(max + 3, 7, r_ptr->x_attr, r_ptr->x_char, attr_top, char_left);
3377                 }
3378                 else if (!column)
3379                 {
3380                         Term_gotoxy(0, 6 + (grp_cur - grp_top));
3381                 }
3382                 else
3383                 {
3384                         Term_gotoxy(max + 3, 6 + (mon_cur - mon_top));
3385                 }
3386
3387                 char ch = inkey();
3388                 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))
3389                 {
3390                         if (direct_r_idx >= 0)
3391                         {
3392                                 switch (ch)
3393                                 {
3394                                 case '\n':
3395                                 case '\r':
3396                                 case ESCAPE:
3397                                         flag = TRUE;
3398                                         break;
3399                                 }
3400                         }
3401
3402                         continue;
3403                 }
3404
3405                 switch (ch)
3406                 {
3407                 case ESCAPE:
3408                 {
3409                         flag = TRUE;
3410                         break;
3411                 }
3412
3413                 case 'R':
3414                 case 'r':
3415                 {
3416                         if (!visual_list && !visual_only && (mon_idx[mon_cur] > 0))
3417                         {
3418                                 screen_roff(creature_ptr, mon_idx[mon_cur], 0);
3419
3420                                 (void)inkey();
3421
3422                                 redraw = TRUE;
3423                         }
3424
3425                         break;
3426                 }
3427
3428                 default:
3429                 {
3430                         browser_cursor(ch, &column, &grp_cur, grp_cnt, &mon_cur, mon_cnt);
3431
3432                         break;
3433                 }
3434                 }
3435         }
3436
3437         C_KILL(mon_idx, max_r_idx, MONRACE_IDX);
3438 }
3439
3440
3441 /*
3442  * Display the objects in a group.
3443  */
3444 static void display_object_list(int col, int row, int per_page, IDX object_idx[],
3445         int object_cur, int object_top, bool visual_only)
3446 {
3447         int i;
3448         for (i = 0; i < per_page && (object_idx[object_top + i] >= 0); i++)
3449         {
3450                 GAME_TEXT o_name[MAX_NLEN];
3451                 TERM_COLOR a;
3452                 SYMBOL_CODE c;
3453                 object_kind *flavor_k_ptr;
3454                 KIND_OBJECT_IDX k_idx = object_idx[object_top + i];
3455                 object_kind *k_ptr = &k_info[k_idx];
3456                 TERM_COLOR attr = ((k_ptr->aware || visual_only) ? TERM_WHITE : TERM_SLATE);
3457                 byte cursor = ((k_ptr->aware || visual_only) ? TERM_L_BLUE : TERM_BLUE);
3458                 if (!visual_only && k_ptr->flavor)
3459                 {
3460                         flavor_k_ptr = &k_info[k_ptr->flavor];
3461                 }
3462                 else
3463                 {
3464                         flavor_k_ptr = k_ptr;
3465                 }
3466
3467                 attr = ((i + object_top == object_cur) ? cursor : attr);
3468                 if (!k_ptr->flavor || (!visual_only && k_ptr->aware))
3469                 {
3470                         strip_name(o_name, k_idx);
3471                 }
3472                 else
3473                 {
3474                         strcpy(o_name, k_name + flavor_k_ptr->flavor_name);
3475                 }
3476
3477                 c_prt(attr, o_name, row + i, col);
3478                 if (per_page == 1)
3479                 {
3480                         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);
3481                 }
3482
3483                 if (current_world_ptr->wizard || visual_only)
3484                 {
3485                         c_prt(attr, format("%d", k_idx), row + i, 70);
3486                 }
3487
3488                 a = flavor_k_ptr->x_attr;
3489                 c = flavor_k_ptr->x_char;
3490
3491                 Term_queue_bigchar(use_bigtile ? 76 : 77, row + i, a, c, 0, 0);
3492         }
3493
3494         for (; i < per_page; i++)
3495         {
3496                 Term_erase(col, row + i, 255);
3497         }
3498 }
3499
3500
3501 /*
3502  * Describe fake object
3503  */
3504 static void desc_obj_fake(player_type *creature_ptr, KIND_OBJECT_IDX k_idx)
3505 {
3506         object_type *o_ptr;
3507         object_type object_type_body;
3508         o_ptr = &object_type_body;
3509         object_wipe(o_ptr);
3510         object_prep(o_ptr, k_idx);
3511
3512         o_ptr->ident |= IDENT_KNOWN;
3513         handle_stuff(creature_ptr);
3514
3515         if (screen_object(creature_ptr, o_ptr, SCROBJ_FAKE_OBJECT | SCROBJ_FORCE_DETAIL)) return;
3516
3517         msg_print(_("特に変わったところはないようだ。", "You see nothing special."));
3518         msg_print(NULL);
3519 }
3520
3521
3522 /*
3523  * Display known objects
3524  */
3525 static void do_cmd_knowledge_objects(player_type *creature_ptr, bool *need_redraw, bool visual_only, IDX direct_k_idx)
3526 {
3527         IDX object_old, object_top;
3528         IDX grp_idx[100];
3529         int object_cnt;
3530         OBJECT_IDX *object_idx;
3531
3532         bool visual_list = FALSE;
3533         TERM_COLOR attr_top = 0;
3534         byte char_left = 0;
3535         byte mode;
3536
3537         TERM_LEN wid, hgt;
3538         Term_get_size(&wid, &hgt);
3539
3540         int browser_rows = hgt - 8;
3541         C_MAKE(object_idx, max_k_idx, KIND_OBJECT_IDX);
3542
3543         int len;
3544         int max = 0;
3545         int grp_cnt = 0;
3546         if (direct_k_idx < 0)
3547         {
3548                 mode = visual_only ? 0x03 : 0x01;
3549                 for (IDX i = 0; object_group_text[i] != NULL; i++)
3550                 {
3551                         len = strlen(object_group_text[i]);
3552                         if (len > max) max = len;
3553
3554                         if (collect_objects(i, object_idx, mode))
3555                         {
3556                                 grp_idx[grp_cnt++] = i;
3557                         }
3558                 }
3559
3560                 object_old = -1;
3561                 object_cnt = 0;
3562         }
3563         else
3564         {
3565                 object_kind *k_ptr = &k_info[direct_k_idx];
3566                 object_kind *flavor_k_ptr;
3567
3568                 if (!visual_only && k_ptr->flavor)
3569                 {
3570                         flavor_k_ptr = &k_info[k_ptr->flavor];
3571                 }
3572                 else
3573                 {
3574                         flavor_k_ptr = k_ptr;
3575                 }
3576
3577                 object_idx[0] = direct_k_idx;
3578                 object_old = direct_k_idx;
3579                 object_cnt = 1;
3580                 object_idx[1] = -1;
3581                 (void)visual_mode_command('v', &visual_list, browser_rows - 1, wid - (max + 3),
3582                         &attr_top, &char_left, &flavor_k_ptr->x_attr, &flavor_k_ptr->x_char, need_redraw);
3583         }
3584
3585         grp_idx[grp_cnt] = -1;
3586         mode = visual_only ? 0x02 : 0x00;
3587         IDX old_grp_cur = -1;
3588         IDX grp_cur = 0;
3589         IDX grp_top = 0;
3590         IDX object_cur = object_top = 0;
3591         bool flag = FALSE;
3592         bool redraw = TRUE;
3593         int column = 0;
3594         while (!flag)
3595         {
3596                 object_kind *k_ptr, *flavor_k_ptr;
3597
3598                 if (redraw)
3599                 {
3600                         clear_from(0);
3601
3602 #ifdef JP
3603                         prt(format("%s - アイテム", !visual_only ? "知識" : "表示"), 2, 0);
3604                         if (direct_k_idx < 0) prt("グループ", 4, 0);
3605                         prt("名前", 4, max + 3);
3606                         if (current_world_ptr->wizard || visual_only) prt("Idx", 4, 70);
3607                         prt("文字", 4, 74);
3608 #else
3609                         prt(format("%s - objects", !visual_only ? "Knowledge" : "Visuals"), 2, 0);
3610                         if (direct_k_idx < 0) prt("Group", 4, 0);
3611                         prt("Name", 4, max + 3);
3612                         if (current_world_ptr->wizard || visual_only) prt("Idx", 4, 70);
3613                         prt("Sym", 4, 75);
3614 #endif
3615
3616                         for (IDX i = 0; i < 78; i++)
3617                         {
3618                                 Term_putch(i, 5, TERM_WHITE, '=');
3619                         }
3620
3621                         if (direct_k_idx < 0)
3622                         {
3623                                 for (IDX i = 0; i < browser_rows; i++)
3624                                 {
3625                                         Term_putch(max + 1, 6 + i, TERM_WHITE, '|');
3626                                 }
3627                         }
3628
3629                         redraw = FALSE;
3630                 }
3631
3632                 if (direct_k_idx < 0)
3633                 {
3634                         if (grp_cur < grp_top) grp_top = grp_cur;
3635                         if (grp_cur >= grp_top + browser_rows) grp_top = grp_cur - browser_rows + 1;
3636
3637                         display_group_list(0, 6, max, browser_rows, grp_idx, object_group_text, grp_cur, grp_top);
3638                         if (old_grp_cur != grp_cur)
3639                         {
3640                                 old_grp_cur = grp_cur;
3641                                 object_cnt = collect_objects(grp_idx[grp_cur], object_idx, mode);
3642                         }
3643
3644                         while (object_cur < object_top)
3645                                 object_top = MAX(0, object_top - browser_rows / 2);
3646                         while (object_cur >= object_top + browser_rows)
3647                                 object_top = MIN(object_cnt - browser_rows, object_top + browser_rows / 2);
3648                 }
3649
3650                 if (!visual_list)
3651                 {
3652                         display_object_list(max + 3, 6, browser_rows, object_idx, object_cur, object_top, visual_only);
3653                 }
3654                 else
3655                 {
3656                         object_top = object_cur;
3657                         display_object_list(max + 3, 6, 1, object_idx, object_cur, object_top, visual_only);
3658                         display_visual_list(max + 3, 7, browser_rows - 1, wid - (max + 3), attr_top, char_left);
3659                 }
3660
3661                 k_ptr = &k_info[object_idx[object_cur]];
3662
3663                 if (!visual_only && k_ptr->flavor)
3664                 {
3665                         flavor_k_ptr = &k_info[k_ptr->flavor];
3666                 }
3667                 else
3668                 {
3669                         flavor_k_ptr = k_ptr;
3670                 }
3671
3672 #ifdef JP
3673                 prt(format("<方向>%s%s%s, ESC",
3674                         (!visual_list && !visual_only) ? ", 'r'で詳細を見る" : "",
3675                         visual_list ? ", ENTERで決定" : ", 'v'でシンボル変更",
3676                         (attr_idx || char_idx) ? ", 'c', 'p'でペースト" : ", 'c'でコピー"),
3677                         hgt - 1, 0);
3678 #else
3679                 prt(format("<dir>%s%s%s, ESC",
3680                         (!visual_list && !visual_only) ? ", 'r' to recall" : "",
3681                         visual_list ? ", ENTER to accept" : ", 'v' for visuals",
3682                         (attr_idx || char_idx) ? ", 'c', 'p' to paste" : ", 'c' to copy"),
3683                         hgt - 1, 0);
3684 #endif
3685
3686                 if (!visual_only)
3687                 {
3688                         if (object_cnt) object_kind_track(creature_ptr, object_idx[object_cur]);
3689
3690                         if (object_old != object_idx[object_cur])
3691                         {
3692                                 handle_stuff(creature_ptr);
3693                                 object_old = object_idx[object_cur];
3694                         }
3695                 }
3696
3697                 if (visual_list)
3698                 {
3699                         place_visual_list_cursor(max + 3, 7, flavor_k_ptr->x_attr, flavor_k_ptr->x_char, attr_top, char_left);
3700                 }
3701                 else if (!column)
3702                 {
3703                         Term_gotoxy(0, 6 + (grp_cur - grp_top));
3704                 }
3705                 else
3706                 {
3707                         Term_gotoxy(max + 3, 6 + (object_cur - object_top));
3708                 }
3709
3710                 char ch = inkey();
3711                 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))
3712                 {
3713                         if (direct_k_idx >= 0)
3714                         {
3715                                 switch (ch)
3716                                 {
3717                                 case '\n':
3718                                 case '\r':
3719                                 case ESCAPE:
3720                                         flag = TRUE;
3721                                         break;
3722                                 }
3723                         }
3724                         continue;
3725                 }
3726
3727                 switch (ch)
3728                 {
3729                 case ESCAPE:
3730                 {
3731                         flag = TRUE;
3732                         break;
3733                 }
3734
3735                 case 'R':
3736                 case 'r':
3737                 {
3738                         if (!visual_list && !visual_only && (grp_cnt > 0))
3739                         {
3740                                 desc_obj_fake(creature_ptr, object_idx[object_cur]);
3741                                 redraw = TRUE;
3742                         }
3743
3744                         break;
3745                 }
3746
3747                 default:
3748                 {
3749                         browser_cursor(ch, &column, &grp_cur, grp_cnt, &object_cur, object_cnt);
3750                         break;
3751                 }
3752                 }
3753         }
3754
3755         C_KILL(object_idx, max_k_idx, KIND_OBJECT_IDX);
3756 }
3757
3758
3759 /*
3760  * Display the features in a group.
3761  */
3762 static void display_feature_list(int col, int row, int per_page, FEAT_IDX *feat_idx,
3763         FEAT_IDX feat_cur, FEAT_IDX feat_top, bool visual_only, int lighting_level)
3764 {
3765         int lit_col[F_LIT_MAX], i;
3766         int f_idx_col = use_bigtile ? 62 : 64;
3767
3768         lit_col[F_LIT_STANDARD] = use_bigtile ? (71 - F_LIT_MAX) : 71;
3769         for (i = F_LIT_NS_BEGIN; i < F_LIT_MAX; i++)
3770                 lit_col[i] = lit_col[F_LIT_STANDARD] + 2 + (i - F_LIT_NS_BEGIN) * 2 + (use_bigtile ? i : 0);
3771
3772         for (i = 0; i < per_page && (feat_idx[feat_top + i] >= 0); i++)
3773         {
3774                 TERM_COLOR attr;
3775                 FEAT_IDX f_idx = feat_idx[feat_top + i];
3776                 feature_type *f_ptr = &f_info[f_idx];
3777                 int row_i = row + i;
3778                 attr = ((i + feat_top == feat_cur) ? TERM_L_BLUE : TERM_WHITE);
3779                 c_prt(attr, f_name + f_ptr->name, row_i, col);
3780                 if (per_page == 1)
3781                 {
3782                         c_prt(attr, format("(%s)", lighting_level_str[lighting_level]), row_i, col + 1 + strlen(f_name + f_ptr->name));
3783                         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));
3784                 }
3785                 if (current_world_ptr->wizard || visual_only)
3786                 {
3787                         c_prt(attr, format("%d", f_idx), row_i, f_idx_col);
3788                 }
3789
3790                 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);
3791                 Term_putch(lit_col[F_LIT_NS_BEGIN], row_i, TERM_SLATE, '(');
3792                 for (int j = F_LIT_NS_BEGIN + 1; j < F_LIT_MAX; j++)
3793                 {
3794                         Term_putch(lit_col[j], row_i, TERM_SLATE, '/');
3795                 }
3796
3797                 Term_putch(lit_col[F_LIT_MAX - 1] + (use_bigtile ? 3 : 2), row_i, TERM_SLATE, ')');
3798                 for (int j = F_LIT_NS_BEGIN; j < F_LIT_MAX; j++)
3799                 {
3800                         Term_queue_bigchar(lit_col[j] + 1, row_i, f_ptr->x_attr[j], f_ptr->x_char[j], 0, 0);
3801                 }
3802         }
3803
3804         for (; i < per_page; i++)
3805         {
3806                 Term_erase(col, row + i, 255);
3807         }
3808 }
3809
3810
3811 /*
3812  * Interact with feature visuals.
3813  */
3814 static void do_cmd_knowledge_features(bool *need_redraw, bool visual_only, IDX direct_f_idx, IDX *lighting_level)
3815 {
3816         TERM_COLOR attr_old[F_LIT_MAX];
3817         (void)C_WIPE(attr_old, F_LIT_MAX, TERM_COLOR);
3818         SYMBOL_CODE char_old[F_LIT_MAX];
3819         (void)C_WIPE(char_old, F_LIT_MAX, SYMBOL_CODE);
3820
3821         TERM_LEN wid, hgt;
3822         Term_get_size(&wid, &hgt);
3823
3824         FEAT_IDX *feat_idx;
3825         C_MAKE(feat_idx, max_f_idx, FEAT_IDX);
3826
3827         int len;
3828         int max = 0;
3829         int grp_cnt = 0;
3830         int feat_cnt;
3831         FEAT_IDX grp_idx[100];
3832         TERM_COLOR attr_top = 0;
3833         bool visual_list = FALSE;
3834         byte char_left = 0;
3835         TERM_LEN browser_rows = hgt - 8;
3836         if (direct_f_idx < 0)
3837         {
3838                 for (FEAT_IDX i = 0; feature_group_text[i] != NULL; i++)
3839                 {
3840                         len = strlen(feature_group_text[i]);
3841                         if (len > max) max = len;
3842
3843                         if (collect_features(feat_idx, 0x01))
3844                         {
3845                                 grp_idx[grp_cnt++] = i;
3846                         }
3847                 }
3848
3849                 feat_cnt = 0;
3850         }
3851         else
3852         {
3853                 feature_type *f_ptr = &f_info[direct_f_idx];
3854
3855                 feat_idx[0] = direct_f_idx;
3856                 feat_cnt = 1;
3857                 feat_idx[1] = -1;
3858
3859                 (void)visual_mode_command('v', &visual_list, browser_rows - 1, wid - (max + 3),
3860                         &attr_top, &char_left, &f_ptr->x_attr[*lighting_level], &f_ptr->x_char[*lighting_level], need_redraw);
3861
3862                 for (FEAT_IDX i = 0; i < F_LIT_MAX; i++)
3863                 {
3864                         attr_old[i] = f_ptr->x_attr[i];
3865                         char_old[i] = f_ptr->x_char[i];
3866                 }
3867         }
3868
3869         grp_idx[grp_cnt] = -1;
3870
3871         FEAT_IDX old_grp_cur = -1;
3872         FEAT_IDX grp_cur = 0;
3873         FEAT_IDX grp_top = 0;
3874         FEAT_IDX feat_cur = 0;
3875         FEAT_IDX feat_top = 0;
3876         TERM_LEN column = 0;
3877         bool flag = FALSE;
3878         bool redraw = TRUE;
3879         TERM_COLOR *cur_attr_ptr;
3880         SYMBOL_CODE *cur_char_ptr;
3881         while (!flag)
3882         {
3883                 char ch;
3884                 feature_type *f_ptr;
3885
3886                 if (redraw)
3887                 {
3888                         clear_from(0);
3889
3890                         prt(_("表示 - 地形", "Visuals - features"), 2, 0);
3891                         if (direct_f_idx < 0) prt(_("グループ", "Group"), 4, 0);
3892                         prt(_("名前", "Name"), 4, max + 3);
3893                         if (use_bigtile)
3894                         {
3895                                 if (current_world_ptr->wizard || visual_only) prt("Idx", 4, 62);
3896                                 prt(_("文字 ( l/ d)", "Sym ( l/ d)"), 4, 66);
3897                         }
3898                         else
3899                         {
3900                                 if (current_world_ptr->wizard || visual_only) prt("Idx", 4, 64);
3901                                 prt(_("文字 (l/d)", "Sym (l/d)"), 4, 68);
3902                         }
3903
3904                         for (FEAT_IDX i = 0; i < 78; i++)
3905                         {
3906                                 Term_putch(i, 5, TERM_WHITE, '=');
3907                         }
3908
3909                         if (direct_f_idx < 0)
3910                         {
3911                                 for (FEAT_IDX i = 0; i < browser_rows; i++)
3912                                 {
3913                                         Term_putch(max + 1, 6 + i, TERM_WHITE, '|');
3914                                 }
3915                         }
3916
3917                         redraw = FALSE;
3918                 }
3919
3920                 if (direct_f_idx < 0)
3921                 {
3922                         if (grp_cur < grp_top) grp_top = grp_cur;
3923                         if (grp_cur >= grp_top + browser_rows) grp_top = grp_cur - browser_rows + 1;
3924
3925                         display_group_list(0, 6, max, browser_rows, grp_idx, feature_group_text, grp_cur, grp_top);
3926                         if (old_grp_cur != grp_cur)
3927                         {
3928                                 old_grp_cur = grp_cur;
3929                                 feat_cnt = collect_features(feat_idx, 0x00);
3930                         }
3931
3932                         while (feat_cur < feat_top)
3933                                 feat_top = MAX(0, feat_top - browser_rows / 2);
3934                         while (feat_cur >= feat_top + browser_rows)
3935                                 feat_top = MIN(feat_cnt - browser_rows, feat_top + browser_rows / 2);
3936                 }
3937
3938                 if (!visual_list)
3939                 {
3940                         display_feature_list(max + 3, 6, browser_rows, feat_idx, feat_cur, feat_top, visual_only, F_LIT_STANDARD);
3941                 }
3942                 else
3943                 {
3944                         feat_top = feat_cur;
3945                         display_feature_list(max + 3, 6, 1, feat_idx, feat_cur, feat_top, visual_only, *lighting_level);
3946                         display_visual_list(max + 3, 7, browser_rows - 1, wid - (max + 3), attr_top, char_left);
3947                 }
3948
3949                 prt(format(_("<方向>%s, 'd'で標準光源効果%s, ESC", "<dir>%s, 'd' for default lighting%s, ESC"),
3950                         visual_list ? _(", ENTERで決定, 'a'で対象明度変更", ", ENTER to accept, 'a' for lighting level") : _(", 'v'でシンボル変更", ", 'v' for visuals"),
3951                         (attr_idx || char_idx) ? _(", 'c', 'p'でペースト", ", 'c', 'p' to paste") : _(", 'c'でコピー", ", 'c' to copy")),
3952                         hgt - 1, 0);
3953
3954                 f_ptr = &f_info[feat_idx[feat_cur]];
3955                 cur_attr_ptr = &f_ptr->x_attr[*lighting_level];
3956                 cur_char_ptr = &f_ptr->x_char[*lighting_level];
3957
3958                 if (visual_list)
3959                 {
3960                         place_visual_list_cursor(max + 3, 7, *cur_attr_ptr, *cur_char_ptr, attr_top, char_left);
3961                 }
3962                 else if (!column)
3963                 {
3964                         Term_gotoxy(0, 6 + (grp_cur - grp_top));
3965                 }
3966                 else
3967                 {
3968                         Term_gotoxy(max + 3, 6 + (feat_cur - feat_top));
3969                 }
3970
3971                 ch = inkey();
3972                 if (visual_list && ((ch == 'A') || (ch == 'a')))
3973                 {
3974                         int prev_lighting_level = *lighting_level;
3975
3976                         if (ch == 'A')
3977                         {
3978                                 if (*lighting_level <= 0) *lighting_level = F_LIT_MAX - 1;
3979                                 else (*lighting_level)--;
3980                         }
3981                         else
3982                         {
3983                                 if (*lighting_level >= F_LIT_MAX - 1) *lighting_level = 0;
3984                                 else (*lighting_level)++;
3985                         }
3986
3987                         if (f_ptr->x_attr[prev_lighting_level] != f_ptr->x_attr[*lighting_level])
3988                                 attr_top = MAX(0, (f_ptr->x_attr[*lighting_level] & 0x7f) - 5);
3989
3990                         if (f_ptr->x_char[prev_lighting_level] != f_ptr->x_char[*lighting_level])
3991                                 char_left = MAX(0, f_ptr->x_char[*lighting_level] - 10);
3992
3993                         continue;
3994                 }
3995                 else if ((ch == 'D') || (ch == 'd'))
3996                 {
3997                         TERM_COLOR prev_x_attr = f_ptr->x_attr[*lighting_level];
3998                         byte prev_x_char = f_ptr->x_char[*lighting_level];
3999
4000                         apply_default_feat_lighting(f_ptr->x_attr, f_ptr->x_char);
4001
4002                         if (visual_list)
4003                         {
4004                                 if (prev_x_attr != f_ptr->x_attr[*lighting_level])
4005                                         attr_top = MAX(0, (f_ptr->x_attr[*lighting_level] & 0x7f) - 5);
4006
4007                                 if (prev_x_char != f_ptr->x_char[*lighting_level])
4008                                         char_left = MAX(0, f_ptr->x_char[*lighting_level] - 10);
4009                         }
4010                         else *need_redraw = TRUE;
4011
4012                         continue;
4013                 }
4014                 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))
4015                 {
4016                         switch (ch)
4017                         {
4018                         case ESCAPE:
4019                                 for (FEAT_IDX i = 0; i < F_LIT_MAX; i++)
4020                                 {
4021                                         f_ptr->x_attr[i] = attr_old[i];
4022                                         f_ptr->x_char[i] = char_old[i];
4023                                 }
4024
4025                                 /* Fall through */
4026                         case '\n':
4027                         case '\r':
4028                                 if (direct_f_idx >= 0) flag = TRUE;
4029                                 else *lighting_level = F_LIT_STANDARD;
4030                                 break;
4031                         case 'V':
4032                         case 'v':
4033                                 for (FEAT_IDX i = 0; i < F_LIT_MAX; i++)
4034                                 {
4035                                         attr_old[i] = f_ptr->x_attr[i];
4036                                         char_old[i] = f_ptr->x_char[i];
4037                                 }
4038                                 *lighting_level = F_LIT_STANDARD;
4039                                 break;
4040
4041                         case 'C':
4042                         case 'c':
4043                                 if (!visual_list)
4044                                 {
4045                                         for (FEAT_IDX i = 0; i < F_LIT_MAX; i++)
4046                                         {
4047                                                 attr_idx_feat[i] = f_ptr->x_attr[i];
4048                                                 char_idx_feat[i] = f_ptr->x_char[i];
4049                                         }
4050                                 }
4051                                 break;
4052
4053                         case 'P':
4054                         case 'p':
4055                                 if (!visual_list)
4056                                 {
4057                                         for (FEAT_IDX i = F_LIT_NS_BEGIN; i < F_LIT_MAX; i++)
4058                                         {
4059                                                 if (attr_idx_feat[i] || (!(char_idx_feat[i] & 0x80) && char_idx_feat[i])) f_ptr->x_attr[i] = attr_idx_feat[i];
4060                                                 if (char_idx_feat[i]) f_ptr->x_char[i] = char_idx_feat[i];
4061                                         }
4062                                 }
4063                                 break;
4064                         }
4065                         continue;
4066                 }
4067
4068                 switch (ch)
4069                 {
4070                 case ESCAPE:
4071                 {
4072                         flag = TRUE;
4073                         break;
4074                 }
4075
4076                 default:
4077                 {
4078                         browser_cursor(ch, &column, &grp_cur, grp_cnt, &feat_cur, feat_cnt);
4079                         break;
4080                 }
4081                 }
4082         }
4083
4084         C_KILL(feat_idx, max_f_idx, FEAT_IDX);
4085 }
4086
4087
4088 /*
4089  * List wanted monsters
4090  * @param creature_ptr プレーヤーへの参照ポインタ
4091  * @return なし
4092  */
4093 static void do_cmd_knowledge_bounty(player_type *creature_ptr)
4094 {
4095         FILE *fff;
4096         GAME_TEXT file_name[1024];
4097         fff = my_fopen_temp(file_name, 1024);
4098         if (!fff)
4099         {
4100                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
4101                 msg_print(NULL);
4102                 return;
4103         }
4104
4105         fprintf(fff, _("今日のターゲット : %s\n", "Today's target : %s\n"),
4106                 (creature_ptr->today_mon ? r_name + r_info[creature_ptr->today_mon].name : _("不明", "unknown")));
4107         fprintf(fff, "\n");
4108         fprintf(fff, _("賞金首リスト\n", "List of wanted monsters\n"));
4109         fprintf(fff, "----------------------------------------------\n");
4110
4111         bool listed = FALSE;
4112         for (int i = 0; i < MAX_BOUNTY; i++)
4113         {
4114                 if (current_world_ptr->bounty_r_idx[i] <= 10000)
4115                 {
4116                         fprintf(fff, "%s\n", r_name + r_info[current_world_ptr->bounty_r_idx[i]].name);
4117                         listed = TRUE;
4118                 }
4119         }
4120
4121         if (!listed)
4122         {
4123                 fprintf(fff, "\n%s\n", _("賞金首はもう残っていません。", "There are no more wanted monster."));
4124         }
4125
4126         my_fclose(fff);
4127         (void)show_file(creature_ptr, TRUE, file_name, _("賞金首の一覧", "Wanted monsters"), 0, 0);
4128         fd_kill(file_name);
4129 }
4130
4131 /*
4132  * List virtues & status
4133  */
4134 static void do_cmd_knowledge_virtues(player_type *creature_ptr)
4135 {
4136         FILE *fff;
4137         GAME_TEXT file_name[1024];
4138         fff = my_fopen_temp(file_name, 1024);
4139         if (!fff)
4140         {
4141                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
4142                 msg_print(NULL);
4143                 return;
4144         }
4145
4146         fprintf(fff, _("現在の属性 : %s\n\n", "Your alignment : %s\n\n"), your_alignment(creature_ptr));
4147         dump_virtues(creature_ptr, fff);
4148         my_fclose(fff);
4149         (void)show_file(creature_ptr, TRUE, file_name, _("八つの徳", "Virtues"), 0, 0);
4150         fd_kill(file_name);
4151 }
4152
4153 /*
4154  * Dungeon
4155  */
4156 static void do_cmd_knowledge_dungeon(player_type *creature_ptr)
4157 {
4158         FILE *fff;
4159         GAME_TEXT file_name[1024];
4160         fff = my_fopen_temp(file_name, 1024);
4161         if (!fff)
4162         {
4163                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
4164                 msg_print(NULL);
4165                 return;
4166         }
4167
4168         for (int i = 1; i < current_world_ptr->max_d_idx; i++)
4169         {
4170                 bool seiha = FALSE;
4171
4172                 if (!d_info[i].maxdepth) continue;
4173                 if (!max_dlv[i]) continue;
4174                 if (d_info[i].final_guardian)
4175                 {
4176                         if (!r_info[d_info[i].final_guardian].max_num) seiha = TRUE;
4177                 }
4178                 else if (max_dlv[i] == d_info[i].maxdepth) seiha = TRUE;
4179
4180                 fprintf(fff, _("%c%-12s :  %3d 階\n", "%c%-16s :  level %3d\n"), seiha ? '!' : ' ', d_name + d_info[i].name, (int)max_dlv[i]);
4181         }
4182
4183         my_fclose(fff);
4184         (void)show_file(creature_ptr, TRUE, file_name, _("今までに入ったダンジョン", "Dungeon"), 0, 0);
4185         fd_kill(file_name);
4186 }
4187
4188
4189 /*
4190 * List virtues & status
4191 *
4192 */
4193 static void do_cmd_knowledge_stat(player_type *creature_ptr)
4194 {
4195         FILE *fff;
4196         GAME_TEXT file_name[1024];
4197         fff = my_fopen_temp(file_name, 1024);
4198         if (!fff)
4199         {
4200                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
4201                 msg_print(NULL);
4202                 return;
4203         }
4204
4205         int percent = (int)(((long)creature_ptr->player_hp[PY_MAX_LEVEL - 1] * 200L) /
4206                 (2 * creature_ptr->hitdie +
4207                 ((PY_MAX_LEVEL - 1 + 3) * (creature_ptr->hitdie + 1))));
4208
4209         if (creature_ptr->knowledge & KNOW_HPRATE)
4210                 fprintf(fff, _("現在の体力ランク : %d/100\n\n", "Your current Life Rating is %d/100.\n\n"), percent);
4211         else fprintf(fff, _("現在の体力ランク : ???\n\n", "Your current Life Rating is ???.\n\n"));
4212
4213         fprintf(fff, _("能力の最大値\n\n", "Limits of maximum stats\n\n"));
4214         for (int v_nr = 0; v_nr < A_MAX; v_nr++)
4215         {
4216                 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);
4217                 else fprintf(fff, "%s ???\n", stat_names[v_nr]);
4218         }
4219
4220         dump_yourself(creature_ptr, fff);
4221         my_fclose(fff);
4222         (void)show_file(creature_ptr, TRUE, file_name, _("自分に関する情報", "HP-rate & Max stat"), 0, 0);
4223         fd_kill(file_name);
4224 }
4225
4226
4227 /*
4228  * todo player_typeではなくQUEST_IDXを引数にすべきかもしれない
4229  * Print all active quests
4230  * @param creature_ptr プレーヤーへの参照ポインタ
4231  * @return なし
4232  */
4233 static void do_cmd_knowledge_quests_current(player_type *creature_ptr, FILE *fff)
4234 {
4235         char tmp_str[120];
4236         char rand_tmp_str[120] = "\0";
4237         GAME_TEXT name[MAX_NLEN];
4238         monster_race *r_ptr;
4239         int rand_level = 100;
4240         int total = 0;
4241
4242         fprintf(fff, _("《遂行中のクエスト》\n", "< Current Quest >\n"));
4243
4244         for (QUEST_IDX i = 1; i < max_q_idx; i++)
4245         {
4246                 bool is_print = quest[i].status == QUEST_STATUS_TAKEN;
4247                 is_print |= (quest[i].status == QUEST_STATUS_STAGE_COMPLETED) && (quest[i].type == QUEST_TYPE_TOWER);
4248                 is_print |= quest[i].status == QUEST_STATUS_COMPLETED;
4249                 if (!is_print)
4250                         continue;
4251
4252                 QUEST_IDX old_quest = creature_ptr->current_floor_ptr->inside_quest;
4253                 for (int j = 0; j < 10; j++)
4254                         quest_text[j][0] = '\0';
4255
4256                 quest_text_line = 0;
4257                 creature_ptr->current_floor_ptr->inside_quest = i;
4258                 init_flags = INIT_SHOW_TEXT;
4259                 process_dungeon_file(creature_ptr, "q_info.txt", 0, 0, 0, 0);
4260                 creature_ptr->current_floor_ptr->inside_quest = old_quest;
4261                 if (quest[i].flags & QUEST_FLAG_SILENT) continue;
4262
4263                 total++;
4264                 if (quest[i].type != QUEST_TYPE_RANDOM)
4265                 {
4266                         char note[80] = "\0";
4267
4268                         if (quest[i].status == QUEST_STATUS_TAKEN || quest[i].status == QUEST_STATUS_STAGE_COMPLETED)
4269                         {
4270                                 switch (quest[i].type)
4271                                 {
4272                                 case QUEST_TYPE_KILL_LEVEL:
4273                                 case QUEST_TYPE_KILL_ANY_LEVEL:
4274                                         r_ptr = &r_info[quest[i].r_idx];
4275                                         strcpy(name, r_name + r_ptr->name);
4276                                         if (quest[i].max_num > 1)
4277                                         {
4278 #ifdef JP
4279                                                 sprintf(note, " - %d 体の%sを倒す。(あと %d 体)",
4280                                                         (int)quest[i].max_num, name, (int)(quest[i].max_num - quest[i].cur_num));
4281 #else
4282                                                 plural_aux(name);
4283                                                 sprintf(note, " - kill %d %s, have killed %d.",
4284                                                         (int)quest[i].max_num, name, (int)quest[i].cur_num);
4285 #endif
4286                                         }
4287                                         else
4288                                                 sprintf(note, _(" - %sを倒す。", " - kill %s."), name);
4289                                         break;
4290
4291                                 case QUEST_TYPE_FIND_ARTIFACT:
4292                                         if (quest[i].k_idx)
4293                                         {
4294                                                 artifact_type *a_ptr = &a_info[quest[i].k_idx];
4295                                                 object_type forge;
4296                                                 object_type *q_ptr = &forge;
4297                                                 KIND_OBJECT_IDX k_idx = lookup_kind(a_ptr->tval, a_ptr->sval);
4298                                                 object_prep(q_ptr, k_idx);
4299                                                 q_ptr->name1 = quest[i].k_idx;
4300                                                 q_ptr->ident = IDENT_STORE;
4301                                                 object_desc(creature_ptr, name, q_ptr, OD_NAME_ONLY);
4302                                         }
4303                                         sprintf(note, _("\n   - %sを見つけ出す。", "\n   - Find %s."), name);
4304                                         break;
4305                                 case QUEST_TYPE_FIND_EXIT:
4306                                         sprintf(note, _(" - 出口に到達する。", " - Reach exit."));
4307                                         break;
4308
4309                                 case QUEST_TYPE_KILL_NUMBER:
4310 #ifdef JP
4311                                         sprintf(note, " - %d 体のモンスターを倒す。(あと %d 体)",
4312                                                 (int)quest[i].max_num, (int)(quest[i].max_num - quest[i].cur_num));
4313 #else
4314                                         sprintf(note, " - Kill %d monsters, have killed %d.",
4315                                                 (int)quest[i].max_num, (int)quest[i].cur_num);
4316 #endif
4317                                         break;
4318
4319                                 case QUEST_TYPE_KILL_ALL:
4320                                 case QUEST_TYPE_TOWER:
4321                                         sprintf(note, _(" - 全てのモンスターを倒す。", " - Kill all monsters."));
4322                                         break;
4323                                 }
4324                         }
4325
4326                         sprintf(tmp_str, _("  %s (危険度:%d階相当)%s\n", "  %s (Danger level: %d)%s\n"),
4327                                 quest[i].name, (int)quest[i].level, note);
4328                         fputs(tmp_str, fff);
4329                         if (quest[i].status == QUEST_STATUS_COMPLETED)
4330                         {
4331                                 sprintf(tmp_str, _("    クエスト達成 - まだ報酬を受けとってない。\n", "    Quest Completed - Unrewarded\n"));
4332                                 fputs(tmp_str, fff);
4333                                 continue;
4334                         }
4335
4336                         int k = 0;
4337                         while (quest_text[k][0] && k < 10)
4338                         {
4339                                 fprintf(fff, "    %s\n", quest_text[k]);
4340                                 k++;
4341                         }
4342
4343                         continue;
4344                 }
4345
4346                 if (quest[i].level >= rand_level)
4347                         continue;
4348
4349                 rand_level = quest[i].level;
4350                 if (max_dlv[DUNGEON_ANGBAND] < rand_level) continue;
4351
4352                 r_ptr = &r_info[quest[i].r_idx];
4353                 strcpy(name, r_name + r_ptr->name);
4354                 if (quest[i].max_num <= 1)
4355                 {
4356                         sprintf(rand_tmp_str, _("  %s (%d 階) - %sを倒す。\n", "  %s (Dungeon level: %d)\n  Kill %s.\n"),
4357                                 quest[i].name, (int)quest[i].level, name);
4358                         continue;
4359                 }
4360
4361 #ifdef JP
4362                 sprintf(rand_tmp_str, "  %s (%d 階) - %d 体の%sを倒す。(あと %d 体)\n",
4363                         quest[i].name, (int)quest[i].level,
4364                         (int)quest[i].max_num, name, (int)(quest[i].max_num - quest[i].cur_num));
4365 #else
4366                 plural_aux(name);
4367
4368                 sprintf(rand_tmp_str, "  %s (Dungeon level: %d)\n  Kill %d %s, have killed %d.\n",
4369                         quest[i].name, (int)quest[i].level,
4370                         (int)quest[i].max_num, name, (int)quest[i].cur_num);
4371 #endif
4372         }
4373
4374         if (rand_tmp_str[0]) fputs(rand_tmp_str, fff);
4375
4376         if (!total) fprintf(fff, _("  なし\n", "  Nothing.\n"));
4377 }
4378
4379
4380 static bool do_cmd_knowledge_quests_aux(player_type *player_ptr, FILE *fff, IDX q_idx)
4381 {
4382         char tmp_str[120];
4383         char playtime_str[16];
4384         quest_type* const q_ptr = &quest[q_idx];
4385
4386         floor_type *floor_ptr = player_ptr->current_floor_ptr;
4387         if (is_fixed_quest_idx(q_idx))
4388         {
4389                 IDX old_quest = floor_ptr->inside_quest;
4390                 floor_ptr->inside_quest = q_idx;
4391                 init_flags = INIT_NAME_ONLY;
4392                 process_dungeon_file(player_ptr, "q_info.txt", 0, 0, 0, 0);
4393                 floor_ptr->inside_quest = old_quest;
4394                 if (q_ptr->flags & QUEST_FLAG_SILENT) return FALSE;
4395         }
4396
4397         strnfmt(playtime_str, sizeof(playtime_str), "%02d:%02d:%02d",
4398                 q_ptr->comptime / (60 * 60), (q_ptr->comptime / 60) % 60, q_ptr->comptime % 60);
4399
4400         if (is_fixed_quest_idx(q_idx) || (q_ptr->r_idx == 0))
4401         {
4402                 sprintf(tmp_str,
4403                         _("  %-35s (危険度:%3d階相当) - レベル%2d - %s\n",
4404                                 "  %-35s (Danger  level: %3d) - level %2d - %s\n"),
4405                         q_ptr->name, (int)q_ptr->level, q_ptr->complev, playtime_str);
4406                 fputs(tmp_str, fff);
4407                 return TRUE;
4408         }
4409
4410         if (q_ptr->complev == 0)
4411         {
4412                 sprintf(tmp_str,
4413                         _("  %-35s (%3d階)            -   不戦勝 - %s\n",
4414                                 "  %-35s (Dungeon level: %3d) - Unearned - %s\n"),
4415                         r_name + r_info[q_ptr->r_idx].name,
4416                         (int)q_ptr->level, playtime_str);
4417                 fputs(tmp_str, fff);
4418                 return TRUE;
4419         }
4420
4421         sprintf(tmp_str,
4422                 _("  %-35s (%3d階)            - レベル%2d - %s\n",
4423                         "  %-35s (Dungeon level: %3d) - level %2d - %s\n"),
4424                 r_name + r_info[q_ptr->r_idx].name,
4425                 (int)q_ptr->level,
4426                 q_ptr->complev,
4427                 playtime_str);
4428         fputs(tmp_str, fff);
4429         return TRUE;
4430 }
4431
4432
4433 /*
4434  * Print all finished quests
4435  * @param creature_ptr プレーヤーへの参照ポインタ
4436  * @param fff セーブファイル (展開済?)
4437  * @param quest_num[] 受注したことのあるクエスト群
4438  * @return なし
4439  */
4440 void do_cmd_knowledge_quests_completed(player_type *creature_ptr, FILE *fff, QUEST_IDX quest_num[])
4441 {
4442         fprintf(fff, _("《達成したクエスト》\n", "< Completed Quest >\n"));
4443         QUEST_IDX total = 0;
4444         for (QUEST_IDX i = 1; i < max_q_idx; i++)
4445         {
4446                 QUEST_IDX q_idx = quest_num[i];
4447                 quest_type* const q_ptr = &quest[q_idx];
4448
4449                 if (q_ptr->status == QUEST_STATUS_FINISHED && do_cmd_knowledge_quests_aux(creature_ptr, fff, q_idx))
4450                 {
4451                         ++total;
4452                 }
4453         }
4454
4455         if (!total) fprintf(fff, _("  なし\n", "  Nothing.\n"));
4456 }
4457
4458
4459 /*
4460  * Print all failed quests
4461  * @param creature_ptr プレーヤーへの参照ポインタ
4462  * @param fff セーブファイル (展開済?)
4463  * @param quest_num[] 受注したことのあるクエスト群
4464  * @return なし
4465 */
4466 void do_cmd_knowledge_quests_failed(player_type *creature_ptr, FILE *fff, QUEST_IDX quest_num[])
4467 {
4468         fprintf(fff, _("《失敗したクエスト》\n", "< Failed Quest >\n"));
4469         QUEST_IDX total = 0;
4470         for (QUEST_IDX i = 1; i < max_q_idx; i++)
4471         {
4472                 QUEST_IDX q_idx = quest_num[i];
4473                 quest_type* const q_ptr = &quest[q_idx];
4474
4475                 if (((q_ptr->status == QUEST_STATUS_FAILED_DONE) || (q_ptr->status == QUEST_STATUS_FAILED)) &&
4476                         do_cmd_knowledge_quests_aux(creature_ptr, fff, q_idx))
4477                 {
4478                         ++total;
4479                 }
4480         }
4481
4482         if (!total) fprintf(fff, _("  なし\n", "  Nothing.\n"));
4483 }
4484
4485
4486 /*
4487  * Print all random quests
4488  */
4489 static void do_cmd_knowledge_quests_wiz_random(FILE *fff)
4490 {
4491         fprintf(fff, _("《残りのランダムクエスト》\n", "< Remaining Random Quest >\n"));
4492         GAME_TEXT tmp_str[120];
4493         QUEST_IDX total = 0;
4494         for (QUEST_IDX i = 1; i < max_q_idx; i++)
4495         {
4496                 if (quest[i].flags & QUEST_FLAG_SILENT) continue;
4497
4498                 if ((quest[i].type == QUEST_TYPE_RANDOM) && (quest[i].status == QUEST_STATUS_TAKEN))
4499                 {
4500                         total++;
4501                         sprintf(tmp_str, _("  %s (%d階, %s)\n", "  %s (%d, %s)\n"),
4502                                 quest[i].name, (int)quest[i].level, r_name + r_info[quest[i].r_idx].name);
4503                         fputs(tmp_str, fff);
4504                 }
4505         }
4506
4507         if (!total) fprintf(fff, _("  なし\n", "  Nothing.\n"));
4508 }
4509
4510 /*
4511  * Print quest status of all active quests
4512  * @param creature_ptr プレーヤーへの参照ポインタ
4513  * @return なし
4514  */
4515 static void do_cmd_knowledge_quests(player_type *creature_ptr)
4516 {
4517         FILE *fff;
4518         GAME_TEXT file_name[1024];
4519         fff = my_fopen_temp(file_name, 1024);
4520         if (!fff)
4521         {
4522                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
4523                 msg_print(NULL);
4524                 return;
4525         }
4526
4527         IDX *quest_num;
4528         C_MAKE(quest_num, max_q_idx, QUEST_IDX);
4529
4530         for (IDX i = 1; i < max_q_idx; i++)
4531                 quest_num[i] = i;
4532
4533         int dummy;
4534         ang_sort(quest_num, &dummy, max_q_idx, ang_sort_comp_quest_num, ang_sort_swap_quest_num);
4535
4536         do_cmd_knowledge_quests_current(creature_ptr, fff);
4537         fputc('\n', fff);
4538         do_cmd_knowledge_quests_completed(creature_ptr, fff, quest_num);
4539         fputc('\n', fff);
4540         do_cmd_knowledge_quests_failed(creature_ptr, fff, quest_num);
4541         if (current_world_ptr->wizard)
4542         {
4543                 fputc('\n', fff);
4544                 do_cmd_knowledge_quests_wiz_random(fff);
4545         }
4546
4547         my_fclose(fff);
4548         (void)show_file(creature_ptr, TRUE, file_name, _("クエスト達成状況", "Quest status"), 0, 0);
4549         fd_kill(file_name);
4550         C_KILL(quest_num, max_q_idx, QUEST_IDX);
4551 }
4552
4553
4554 /*
4555  * List my home
4556  * @param player_ptr プレーヤーへの参照ポインタ
4557  * @return なし
4558  */
4559 static void do_cmd_knowledge_home(player_type *player_ptr)
4560 {
4561         process_dungeon_file(player_ptr, "w_info.txt", 0, 0, current_world_ptr->max_wild_y, current_world_ptr->max_wild_x);
4562
4563         /* Open a new file */
4564         FILE *fff;
4565         GAME_TEXT file_name[1024];
4566         fff = my_fopen_temp(file_name, 1024);
4567         if (!fff)
4568         {
4569                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
4570                 msg_print(NULL);
4571                 return;
4572         }
4573
4574         store_type *st_ptr;
4575         st_ptr = &town_info[1].store[STORE_HOME];
4576
4577         if (st_ptr->stock_num)
4578         {
4579 #ifdef JP
4580                 TERM_LEN x = 1;
4581 #endif
4582                 fprintf(fff, _("  [ 我が家のアイテム ]\n", "  [Home Inventory]\n"));
4583                 concptr paren = ")";
4584                 GAME_TEXT o_name[MAX_NLEN];
4585                 for (int i = 0; i < st_ptr->stock_num; i++)
4586                 {
4587 #ifdef JP
4588                         if ((i % 12) == 0) fprintf(fff, "\n ( %d ページ )\n", x++);
4589                         object_desc(player_ptr, o_name, &st_ptr->stock[i], 0);
4590                         if (strlen(o_name) <= 80 - 3)
4591                         {
4592                                 fprintf(fff, "%c%s %s\n", I2A(i % 12), paren, o_name);
4593                         }
4594                         else
4595                         {
4596                                 int n;
4597                                 char *t;
4598                                 for (n = 0, t = o_name; n < 80 - 3; n++, t++)
4599                                         if (iskanji(*t)) { t++; n++; }
4600                                 if (n == 81 - 3) n = 79 - 3; /* 最後が漢字半分 */
4601
4602                                 fprintf(fff, "%c%s %.*s\n", I2A(i % 12), paren, n, o_name);
4603                                 fprintf(fff, "   %.77s\n", o_name + n);
4604                         }
4605 #else
4606                         object_desc(player_ptr, o_name, &st_ptr->stock[i], 0);
4607                         fprintf(fff, "%c%s %s\n", I2A(i % 12), paren, o_name);
4608 #endif
4609                 }
4610
4611                 fprintf(fff, "\n\n");
4612         }
4613
4614         my_fclose(fff);
4615         (void)show_file(player_ptr, TRUE, file_name, _("我が家のアイテム", "Home Inventory"), 0, 0);
4616         fd_kill(file_name);
4617 }
4618
4619
4620 /*
4621  * Check the status of "autopick"
4622  */
4623 static void do_cmd_knowledge_autopick(player_type *creature_ptr)
4624 {
4625         /* Open a new file */
4626         FILE *fff;
4627         GAME_TEXT file_name[1024];
4628         fff = my_fopen_temp(file_name, 1024);
4629         if (!fff)
4630         {
4631                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
4632                 msg_print(NULL);
4633                 return;
4634         }
4635
4636         if (!max_autopick)
4637         {
4638                 fprintf(fff, _("自動破壊/拾いには何も登録されていません。", "No preference for auto picker/destroyer."));
4639         }
4640         else
4641         {
4642                 fprintf(fff, _("   自動拾い/破壊には現在 %d行登録されています。\n\n",
4643                         "   There are %d registered lines for auto picker/destroyer.\n\n"), max_autopick);
4644         }
4645
4646         for (int k = 0; k < max_autopick; k++)
4647         {
4648                 concptr tmp;
4649                 byte act = autopick_list[k].action;
4650                 if (act & DONT_AUTOPICK)
4651                 {
4652                         tmp = _("放置", "Leave");
4653                 }
4654                 else if (act & DO_AUTODESTROY)
4655                 {
4656                         tmp = _("破壊", "Destroy");
4657                 }
4658                 else if (act & DO_AUTOPICK)
4659                 {
4660                         tmp = _("拾う", "Pickup");
4661                 }
4662                 else
4663                 {
4664                         tmp = _("確認", "Query");
4665                 }
4666
4667                 if (act & DO_DISPLAY)
4668                         fprintf(fff, "%11s", format("[%s]", tmp));
4669                 else
4670                         fprintf(fff, "%11s", format("(%s)", tmp));
4671
4672                 tmp = autopick_line_from_entry(&autopick_list[k]);
4673                 fprintf(fff, " %s", tmp);
4674                 string_free(tmp);
4675                 fprintf(fff, "\n");
4676         }
4677
4678         my_fclose(fff);
4679
4680         (void)show_file(creature_ptr, TRUE, file_name, _("自動拾い/破壊 設定リスト", "Auto-picker/Destroyer"), 0, 0);
4681         fd_kill(file_name);
4682 }
4683
4684
4685 /*
4686  * Interact with "knowledge"
4687  */
4688 void do_cmd_knowledge(player_type *creature_ptr)
4689 {
4690         int i, p = 0;
4691         bool need_redraw = FALSE;
4692         FILE_TYPE(FILE_TYPE_TEXT);
4693         screen_save();
4694         while (TRUE)
4695         {
4696                 Term_clear();
4697                 prt(format(_("%d/2 ページ", "page %d/2"), (p + 1)), 2, 65);
4698                 prt(_("現在の知識を確認する", "Display current knowledge"), 3, 0);
4699
4700 #ifdef JP
4701                 if (p == 0)
4702                 {
4703                         prt("(1) 既知の伝説のアイテム                 の一覧", 6, 5);
4704                         prt("(2) 既知のアイテム                       の一覧", 7, 5);
4705                         prt("(3) 既知の生きているユニーク・モンスター の一覧", 8, 5);
4706                         prt("(4) 既知のモンスター                     の一覧", 9, 5);
4707                         prt("(5) 倒した敵の数                         の一覧", 10, 5);
4708                         if (!vanilla_town) prt("(6) 賞金首                               の一覧", 11, 5);
4709                         prt("(7) 現在のペット                         の一覧", 12, 5);
4710                         prt("(8) 我が家のアイテム                     の一覧", 13, 5);
4711                         prt("(9) *鑑定*済み装備の耐性                 の一覧", 14, 5);
4712                         prt("(0) 地形の表示文字/タイル                の一覧", 15, 5);
4713                 }
4714                 else
4715                 {
4716                         prt("(a) 自分に関する情報                     の一覧", 6, 5);
4717                         prt("(b) 突然変異                             の一覧", 7, 5);
4718                         prt("(c) 武器の経験値                         の一覧", 8, 5);
4719                         prt("(d) 魔法の経験値                         の一覧", 9, 5);
4720                         prt("(e) 技能の経験値                         の一覧", 10, 5);
4721                         prt("(f) プレイヤーの徳                       の一覧", 11, 5);
4722                         prt("(g) 入ったダンジョン                     の一覧", 12, 5);
4723                         prt("(h) 実行中のクエスト                     の一覧", 13, 5);
4724                         prt("(i) 現在の自動拾い/破壊設定              の一覧", 14, 5);
4725                 }
4726 #else
4727                 if (p == 0)
4728                 {
4729                         prt("(1) Display known artifacts", 6, 5);
4730                         prt("(2) Display known objects", 7, 5);
4731                         prt("(3) Display remaining uniques", 8, 5);
4732                         prt("(4) Display known monster", 9, 5);
4733                         prt("(5) Display kill count", 10, 5);
4734                         if (!vanilla_town) prt("(6) Display wanted monsters", 11, 5);
4735                         prt("(7) Display current pets", 12, 5);
4736                         prt("(8) Display home inventory", 13, 5);
4737                         prt("(9) Display *identified* equip.", 14, 5);
4738                         prt("(0) Display terrain symbols.", 15, 5);
4739                 }
4740                 else
4741                 {
4742                         prt("(a) Display about yourself", 6, 5);
4743                         prt("(b) Display mutations", 7, 5);
4744                         prt("(c) Display weapon proficiency", 8, 5);
4745                         prt("(d) Display spell proficiency", 9, 5);
4746                         prt("(e) Display misc. proficiency", 10, 5);
4747                         prt("(f) Display virtues", 11, 5);
4748                         prt("(g) Display dungeons", 12, 5);
4749                         prt("(h) Display current quests", 13, 5);
4750                         prt("(i) Display auto pick/destroy", 14, 5);
4751                 }
4752 #endif
4753                 prt(_("-続く-", "-more-"), 17, 8);
4754                 prt(_("ESC) 抜ける", "ESC) Exit menu"), 21, 1);
4755                 prt(_("SPACE) 次ページ", "SPACE) Next page"), 21, 30);
4756                 prt(_("コマンド:", "Command: "), 20, 0);
4757                 i = inkey();
4758
4759                 if (i == ESCAPE) break;
4760                 switch (i)
4761                 {
4762                 case ' ': /* Page change */
4763                 case '-':
4764                         p = 1 - p;
4765                         break;
4766                 case '1': /* Artifacts */
4767                         do_cmd_knowledge_artifacts(creature_ptr);
4768                         break;
4769                 case '2': /* Objects */
4770                         do_cmd_knowledge_objects(creature_ptr, &need_redraw, FALSE, -1);
4771                         break;
4772                 case '3': /* Uniques */
4773                         do_cmd_knowledge_uniques(creature_ptr);
4774                         break;
4775                 case '4': /* Monsters */
4776                         do_cmd_knowledge_monsters(creature_ptr, &need_redraw, FALSE, -1);
4777                         break;
4778                 case '5': /* Kill count  */
4779                         do_cmd_knowledge_kill_count(creature_ptr);
4780                         break;
4781                 case '6': /* wanted */
4782                         if (!vanilla_town) do_cmd_knowledge_bounty(creature_ptr);
4783                         break;
4784                 case '7': /* Pets */
4785                         do_cmd_knowledge_pets(creature_ptr);
4786                         break;
4787                 case '8': /* Home */
4788                         do_cmd_knowledge_home(creature_ptr);
4789                         break;
4790                 case '9': /* Resist list */
4791                         do_cmd_knowledge_inven(creature_ptr);
4792                         break;
4793                 case '0': /* Feature list */
4794                 {
4795                         IDX lighting_level = F_LIT_STANDARD;
4796                         do_cmd_knowledge_features(&need_redraw, FALSE, -1, &lighting_level);
4797                 }
4798                 break;
4799                 /* Next page */
4800                 case 'a': /* Max stat */
4801                         do_cmd_knowledge_stat(creature_ptr);
4802                         break;
4803                 case 'b': /* Mutations */
4804                         do_cmd_knowledge_mutations(creature_ptr);
4805                         break;
4806                 case 'c': /* weapon-exp */
4807                         do_cmd_knowledge_weapon_exp(creature_ptr);
4808                         break;
4809                 case 'd': /* spell-exp */
4810                         do_cmd_knowledge_spell_exp(creature_ptr);
4811                         break;
4812                 case 'e': /* skill-exp */
4813                         do_cmd_knowledge_skill_exp(creature_ptr);
4814                         break;
4815                 case 'f': /* Virtues */
4816                         do_cmd_knowledge_virtues(creature_ptr);
4817                         break;
4818                 case 'g': /* Dungeon */
4819                         do_cmd_knowledge_dungeon(creature_ptr);
4820                         break;
4821                 case 'h': /* Quests */
4822                         do_cmd_knowledge_quests(creature_ptr);
4823                         break;
4824                 case 'i': /* Autopick */
4825                         do_cmd_knowledge_autopick(creature_ptr);
4826                         break;
4827                 default: /* Unknown option */
4828                         bell();
4829                 }
4830
4831                 msg_erase();
4832         }
4833
4834         screen_load();
4835         if (need_redraw) do_cmd_redraw(creature_ptr);
4836 }
4837
4838
4839 /*
4840  * Check on the status of an active quest
4841  * @param creature_ptr プレーヤーへの参照ポインタ
4842  * @return なし
4843  */
4844 void do_cmd_checkquest(player_type *creature_ptr)
4845 {
4846         FILE_TYPE(FILE_TYPE_TEXT);
4847         screen_save();
4848         do_cmd_knowledge_quests(creature_ptr);
4849         screen_load();
4850 }
4851
4852
4853 /*
4854  * Display the time and date
4855  * @param creature_ptr プレーヤーへの参照ポインタ
4856  * @return なし
4857  */
4858 void do_cmd_time(player_type *creature_ptr)
4859 {
4860         int day, hour, min;
4861         extract_day_hour_min(creature_ptr, &day, &hour, &min);
4862
4863         char desc[1024];
4864         strcpy(desc, _("変な時刻だ。", "It is a strange time."));
4865
4866         char day_buf[10];
4867         if (day < MAX_DAYS) sprintf(day_buf, "%d", day);
4868         else strcpy(day_buf, "*****");
4869
4870         msg_format(_("%s日目, 時刻は%d:%02d %sです。", "This is day %s. The time is %d:%02d %s."),
4871                 day_buf, (hour % 12 == 0) ? 12 : (hour % 12), min, (hour < 12) ? "AM" : "PM");
4872
4873         char buf[1024];
4874         if (!randint0(10) || creature_ptr->image)
4875         {
4876                 path_build(buf, sizeof(buf), ANGBAND_DIR_FILE, _("timefun_j.txt", "timefun.txt"));
4877         }
4878         else
4879         {
4880                 path_build(buf, sizeof(buf), ANGBAND_DIR_FILE, _("timenorm_j.txt", "timenorm.txt"));
4881         }
4882
4883         FILE *fff;
4884         fff = my_fopen(buf, "rt");
4885
4886         if (!fff) return;
4887
4888         int full = hour * 100 + min;
4889         int start = 9999;
4890         int end = -9999;
4891         int num = 0;
4892         while (!my_fgets(fff, buf, sizeof(buf)))
4893         {
4894                 if (!buf[0] || (buf[0] == '#')) continue;
4895                 if (buf[1] != ':') continue;
4896
4897                 if (buf[0] == 'S')
4898                 {
4899                         start = atoi(buf + 2);
4900                         end = start + 59;
4901                         continue;
4902                 }
4903
4904                 if (buf[0] == 'E')
4905                 {
4906                         end = atoi(buf + 2);
4907                         continue;
4908                 }
4909
4910                 if ((start > full) || (full > end)) continue;
4911
4912                 if (buf[0] == 'D')
4913                 {
4914                         num++;
4915                         if (!randint0(num)) strcpy(desc, buf + 2);
4916
4917                         continue;
4918                 }
4919         }
4920
4921         msg_print(desc);
4922         my_fclose(fff);
4923 }