OSDN Git Service

[Refactor] #40236 Separated knowledge-artifacts.c/h from cmd-dump.c
[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  * The dump commands of original Angband simply add new lines to
16  * existing files; these files will become bigger and bigger unless
17  * an user deletes some or all of these files by hand at some
18  * point.
19  * These three functions automatically delete old dumped lines
20  * before adding new ones.  Since there are various kinds of automatic
21  * dumps in a single file, we add a header and a footer with a type
22  * name for every automatic dump, and kill old lines only when the
23  * lines have the correct type of header and footer.
24  * We need to be quite paranoid about correctness; the user might
25  * (mistakenly) edit the file by hand, and see all their work come
26  * to nothing on the next auto dump otherwise.  The current code only
27  * detects changes by noting inconsistencies between the actual number
28  * of lines and the number written in the footer.  Note that this will
29  * not catch single-line edits.
30  * </pre>
31  */
32
33 #include "angband.h"
34 #include "cmd/cmd-draw.h"
35 #include "cmd/cmd-dump.h"
36 #include "cmd/cmd-inventory.h"
37 #include "cmd/lighting-level-table.h"
38 #include "cmd/cmd-visuals.h"
39 #include "cmd/dump-util.h"
40 #include "gameterm.h"
41 #include "core.h" // 暫定。後で消す.
42 #include "core/show-file.h"
43 #include "io/read-pref-file.h"
44 #include "io/interpret-pref-file.h"
45
46 #include "knowledge/knowledge-artifacts.h"
47
48 #include "autopick.h"
49 #include "birth.h"
50 #include "dungeon.h"
51 #include "world.h"
52 #include "view/display-player.h" // 暫定。後で消す.
53 #include "player/process-name.h"
54 #include "player-effects.h"
55 #include "player-skill.h"
56 #include "player-personality.h"
57 #include "sort.h"
58 #include "mutation.h"
59 #include "quest.h"
60 #include "market/store.h"
61 #include "artifact.h"
62 #include "avatar.h"
63 #include "object-flavor.h"
64 #include "object-hook.h"
65 #include "monster-status.h"
66 #include "dungeon-file.h"
67 #include "objectkind.h"
68 #include "floor-town.h"
69 #include "cmd/feeling-table.h"
70 #include "cmd/monster-group-table.h"
71 #include "cmd/object-group-table.h"
72 #include "market/store-util.h"
73 #include "view-mainwindow.h" // 暫定。後で消す
74 #include "english.h"
75
76 #include "diary-subtitle-table.h"
77 #include "io/write-diary.h"
78 #include "chuukei.h"
79
80 /*!
81  * @brief prefファイルを選択して処理する /
82  * Ask for a "user pref line" and process it
83  * @brief prf出力内容を消去する /
84  * Remove old lines automatically generated before.
85  * @param orig_file 消去を行うファイル名
86  */
87 static void remove_auto_dump(concptr orig_file, concptr auto_dump_mark)
88 {
89         char buf[1024];
90         bool between_mark = FALSE;
91         bool changed = FALSE;
92         int line_num = 0;
93         long header_location = 0;
94         char header_mark_str[80];
95         char footer_mark_str[80];
96
97         sprintf(header_mark_str, auto_dump_header, auto_dump_mark);
98         sprintf(footer_mark_str, auto_dump_footer, auto_dump_mark);
99         size_t mark_len = strlen(footer_mark_str);
100
101         FILE *orig_fff;
102         orig_fff = my_fopen(orig_file, "r");
103         if (!orig_fff) return;
104
105         FILE *tmp_fff = NULL;
106         char tmp_file[FILE_NAME_SIZE];
107         if (!open_temporary_file(&tmp_fff, tmp_file)) return;
108
109         while (TRUE)
110         {
111                 if (my_fgets(orig_fff, buf, sizeof(buf)))
112                 {
113                         if (between_mark)
114                         {
115                                 fseek(orig_fff, header_location, SEEK_SET);
116                                 between_mark = FALSE;
117                                 continue;
118                         }
119                         else
120                         {
121                                 break;
122                         }
123                 }
124
125                 if (!between_mark)
126                 {
127                         if (!strcmp(buf, header_mark_str))
128                         {
129                                 header_location = ftell(orig_fff);
130                                 line_num = 0;
131                                 between_mark = TRUE;
132                                 changed = TRUE;
133                         }
134                         else
135                         {
136                                 fprintf(tmp_fff, "%s\n", buf);
137                         }
138
139                         continue;
140                 }
141
142                 if (!strncmp(buf, footer_mark_str, mark_len))
143                 {
144                         int tmp;
145                         if (!sscanf(buf + mark_len, " (%d)", &tmp)
146                                 || tmp != line_num)
147                         {
148                                 fseek(orig_fff, header_location, SEEK_SET);
149                         }
150
151                         between_mark = FALSE;
152                         continue;
153                 }
154
155                 line_num++;
156         }
157
158         my_fclose(orig_fff);
159         my_fclose(tmp_fff);
160
161         if (changed)
162         {
163                 tmp_fff = my_fopen(tmp_file, "r");
164                 orig_fff = my_fopen(orig_file, "w");
165                 while (!my_fgets(tmp_fff, buf, sizeof(buf)))
166                         fprintf(orig_fff, "%s\n", buf);
167
168                 my_fclose(orig_fff);
169                 my_fclose(tmp_fff);
170         }
171
172         fd_kill(tmp_file);
173 }
174
175
176 #ifdef JP
177 #else
178 /*!
179  * @brief Return suffix of ordinal number
180  * @param num number
181  * @return pointer of suffix string.
182  */
183 concptr get_ordinal_number_suffix(int num)
184 {
185         num = ABS(num) % 100;
186         switch (num % 10)
187         {
188         case 1:
189                 return (num == 11) ? "th" : "st";
190         case 2:
191                 return (num == 12) ? "th" : "nd";
192         case 3:
193                 return (num == 13) ? "th" : "rd";
194         default:
195                 return "th";
196         }
197 }
198 #endif
199
200 /*!
201  * @brief 画面を再描画するコマンドのメインルーチン
202  * Hack -- redraw the screen
203  * @param creature_ptr プレーヤーへの参照ポインタ
204  * @return なし
205  * @details
206  * Allow absolute file names?
207  */
208 void do_cmd_pref(player_type *creature_ptr)
209 {
210         char buf[80];
211         strcpy(buf, "");
212         if (!get_string(_("設定変更コマンド: ", "Pref: "), buf, 80)) return;
213
214         (void)interpret_pref_file(creature_ptr, buf);
215 }
216
217
218 /*!
219  * @brief 自動拾い設定ファイルをロードするコマンドのメインルーチン /
220  * @param creature_ptr プレーヤーへの参照ポインタ
221  * @return なし
222  */
223 void do_cmd_reload_autopick(player_type *creature_ptr)
224 {
225         if (!get_check(_("自動拾い設定ファイルをロードしますか? ", "Reload auto-pick preference file? ")))
226                 return;
227
228         autopick_load_pref(creature_ptr, TRUE);
229 }
230
231
232 /*
233  * Interact with "colors"
234  */
235 void do_cmd_colors(player_type *creature_ptr)
236 {
237         int i;
238         char tmp[160];
239         char buf[1024];
240         FILE *auto_dump_stream;
241         FILE_TYPE(FILE_TYPE_TEXT);
242         screen_save();
243         while (TRUE)
244         {
245                 Term_clear();
246                 prt(_("[ カラーの設定 ]", "Interact with Colors"), 2, 0);
247                 prt(_("(1) ユーザー設定ファイルのロード", "(1) Load a user pref file"), 4, 5);
248                 prt(_("(2) カラーの設定をファイルに書き出す", "(2) Dump colors"), 5, 5);
249                 prt(_("(3) カラーの設定を変更する", "(3) Modify colors"), 6, 5);
250                 prt(_("コマンド: ", "Command: "), 8, 0);
251                 i = inkey();
252                 if (i == ESCAPE) break;
253
254                 if (i == '1')
255                 {
256                         prt(_("コマンド: ユーザー設定ファイルをロードします", "Command: Load a user pref file"), 8, 0);
257                         prt(_("ファイル: ", "File: "), 10, 0);
258                         sprintf(tmp, "%s.prf", creature_ptr->base_name);
259                         if (!askfor(tmp, 70)) continue;
260
261                         (void)process_pref_file(creature_ptr, tmp);
262                         Term_xtra(TERM_XTRA_REACT, 0);
263                         Term_redraw();
264                 }
265                 else if (i == '2')
266                 {
267                         static concptr mark = "Colors";
268                         prt(_("コマンド: カラーの設定をファイルに書き出します", "Command: Dump colors"), 8, 0);
269                         prt(_("ファイル: ", "File: "), 10, 0);
270                         sprintf(tmp, "%s.prf", creature_ptr->base_name);
271                         if (!askfor(tmp, 70)) continue;
272
273                         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, tmp);
274                         if (!open_auto_dump(&auto_dump_stream, buf, mark)) continue;
275
276                         auto_dump_printf(auto_dump_stream, _("\n# カラーの設定\n\n", "\n# Color redefinitions\n\n"));
277                         for (i = 0; i < 256; i++)
278                         {
279                                 int kv = angband_color_table[i][0];
280                                 int rv = angband_color_table[i][1];
281                                 int gv = angband_color_table[i][2];
282                                 int bv = angband_color_table[i][3];
283
284                                 concptr name = _("未知", "unknown");
285                                 if (!kv && !rv && !gv && !bv) continue;
286
287                                 if (i < 16) name = color_names[i];
288
289                                 auto_dump_printf(auto_dump_stream, _("# カラー '%s'\n", "# Color '%s'\n"), name);
290                                 auto_dump_printf(auto_dump_stream, "V:%d:0x%02X:0x%02X:0x%02X:0x%02X\n\n",
291                                         i, kv, rv, gv, bv);
292                         }
293
294                         close_auto_dump(&auto_dump_stream, mark);
295                         msg_print(_("カラーの設定をファイルに書き出しました。", "Dumped color redefinitions."));
296                 }
297                 else if (i == '3')
298                 {
299                         static byte a = 0;
300                         prt(_("コマンド: カラーの設定を変更します", "Command: Modify colors"), 8, 0);
301                         while (TRUE)
302                         {
303                                 concptr name;
304                                 clear_from(10);
305                                 for (byte j = 0; j < 16; j++)
306                                 {
307                                         Term_putstr(j * 4, 20, -1, a, "###");
308                                         Term_putstr(j * 4, 22, -1, j, format("%3d", j));
309                                 }
310
311                                 name = ((a < 16) ? color_names[a] : _("未定義", "undefined"));
312                                 Term_putstr(5, 10, -1, TERM_WHITE,
313                                         format(_("カラー = %d, 名前 = %s", "Color = %d, Name = %s"), a, name));
314                                 Term_putstr(5, 12, -1, TERM_WHITE,
315                                         format("K = 0x%02x / R,G,B = 0x%02x,0x%02x,0x%02x",
316                                                 angband_color_table[a][0],
317                                                 angband_color_table[a][1],
318                                                 angband_color_table[a][2],
319                                                 angband_color_table[a][3]));
320                                 Term_putstr(0, 14, -1, TERM_WHITE,
321                                         _("コマンド (n/N/k/K/r/R/g/G/b/B): ", "Command (n/N/k/K/r/R/g/G/b/B): "));
322                                 i = inkey();
323                                 if (i == ESCAPE) break;
324
325                                 if (i == 'n') a = (byte)(a + 1);
326                                 if (i == 'N') a = (byte)(a - 1);
327                                 if (i == 'k') angband_color_table[a][0] = (byte)(angband_color_table[a][0] + 1);
328                                 if (i == 'K') angband_color_table[a][0] = (byte)(angband_color_table[a][0] - 1);
329                                 if (i == 'r') angband_color_table[a][1] = (byte)(angband_color_table[a][1] + 1);
330                                 if (i == 'R') angband_color_table[a][1] = (byte)(angband_color_table[a][1] - 1);
331                                 if (i == 'g') angband_color_table[a][2] = (byte)(angband_color_table[a][2] + 1);
332                                 if (i == 'G') angband_color_table[a][2] = (byte)(angband_color_table[a][2] - 1);
333                                 if (i == 'b') angband_color_table[a][3] = (byte)(angband_color_table[a][3] + 1);
334                                 if (i == 'B') angband_color_table[a][3] = (byte)(angband_color_table[a][3] - 1);
335
336                                 Term_xtra(TERM_XTRA_REACT, 0);
337                                 Term_redraw();
338                         }
339                 }
340                 else
341                 {
342                         bell();
343                 }
344
345                 msg_erase();
346         }
347
348         screen_load();
349 }
350
351
352 /*
353  * Note something in the message recall
354  */
355 void do_cmd_note(void)
356 {
357         char buf[80];
358         strcpy(buf, "");
359         if (!get_string(_("メモ: ", "Note: "), buf, 60)) return;
360         if (!buf[0] || (buf[0] == ' ')) return;
361
362         msg_format(_("メモ: %s", "Note: %s"), buf);
363 }
364
365
366 /*
367  * Mention the current version
368  */
369 void do_cmd_version(void)
370 {
371 #if FAKE_VER_EXTRA > 0
372         msg_format(_("変愚蛮怒(Hengband) %d.%d.%d.%d", "You are playing Hengband %d.%d.%d.%d."),
373                 FAKE_VER_MAJOR - 10, FAKE_VER_MINOR, FAKE_VER_PATCH, FAKE_VER_EXTRA);
374 #else
375         msg_format(_("変愚蛮怒(Hengband) %d.%d.%d", "You are playing Hengband %d.%d.%d."),
376                 FAKE_VER_MAJOR - 10, FAKE_VER_MINOR, FAKE_VER_PATCH);
377 #endif
378 }
379
380
381 /*
382  * Note that "feeling" is set to zero unless some time has passed.
383  * Note that this is done when the level is GENERATED, not entered.
384  */
385 void do_cmd_feeling(player_type *creature_ptr)
386 {
387         if (creature_ptr->wild_mode) return;
388
389         if (creature_ptr->current_floor_ptr->inside_quest && !random_quest_number(creature_ptr, creature_ptr->current_floor_ptr->dun_level))
390         {
391                 msg_print(_("典型的なクエストのダンジョンのようだ。", "Looks like a typical quest level."));
392                 return;
393         }
394
395         if (creature_ptr->town_num && !creature_ptr->current_floor_ptr->dun_level)
396         {
397                 if (!strcmp(town_info[creature_ptr->town_num].name, _("荒野", "wilderness")))
398                 {
399                         msg_print(_("何かありそうな荒野のようだ。", "Looks like a strange wilderness."));
400                         return;
401                 }
402
403                 msg_print(_("典型的な町のようだ。", "Looks like a typical town."));
404                 return;
405         }
406
407         if (!creature_ptr->current_floor_ptr->dun_level)
408         {
409                 msg_print(_("典型的な荒野のようだ。", "Looks like a typical wilderness."));
410                 return;
411         }
412
413         if (creature_ptr->muta3 & MUT3_GOOD_LUCK)
414                 msg_print(do_cmd_feeling_text_lucky[creature_ptr->feeling]);
415         else if (IS_ECHIZEN(creature_ptr))
416                 msg_print(do_cmd_feeling_text_combat[creature_ptr->feeling]);
417         else
418                 msg_print(do_cmd_feeling_text[creature_ptr->feeling]);
419 }
420
421
422 /*
423  * todo 引数と戻り値について追記求む
424  * Build a list of monster indexes in the given group.
425  *
426  * mode & 0x01 : check for non-empty group
427  * mode & 0x02 : visual operation only
428
429  * @param creature_ptr プレーヤーへの参照ポインタ
430  * @param grp_cur ???
431  * @param mon_idx[] ???
432  * @param mode ???
433  * @return The number of monsters in the group
434  */
435 static IDX collect_monsters(player_type *creature_ptr, IDX grp_cur, IDX mon_idx[], BIT_FLAGS8 mode)
436 {
437         concptr group_char = monster_group_char[grp_cur];
438         bool grp_unique = (monster_group_char[grp_cur] == (char *)-1L);
439         bool grp_riding = (monster_group_char[grp_cur] == (char *)-2L);
440         bool grp_wanted = (monster_group_char[grp_cur] == (char *)-3L);
441         bool grp_amberite = (monster_group_char[grp_cur] == (char *)-4L);
442
443         IDX mon_cnt = 0;
444         for (IDX i = 0; i < max_r_idx; i++)
445         {
446                 monster_race *r_ptr = &r_info[i];
447                 if (!r_ptr->name) continue;
448                 if (!(mode & 0x02) && !cheat_know && !r_ptr->r_sights) continue;
449
450                 if (grp_unique)
451                 {
452                         if (!(r_ptr->flags1 & RF1_UNIQUE)) continue;
453                 }
454                 else if (grp_riding)
455                 {
456                         if (!(r_ptr->flags7 & RF7_RIDING)) continue;
457                 }
458                 else if (grp_wanted)
459                 {
460                         bool wanted = FALSE;
461                         for (int j = 0; j < MAX_BOUNTY; j++)
462                         {
463                                 if (current_world_ptr->bounty_r_idx[j] == i || current_world_ptr->bounty_r_idx[j] - 10000 == i ||
464                                         (creature_ptr->today_mon && creature_ptr->today_mon == i))
465                                 {
466                                         wanted = TRUE;
467                                         break;
468                                 }
469                         }
470
471                         if (!wanted) continue;
472                 }
473                 else if (grp_amberite)
474                 {
475                         if (!(r_ptr->flags3 & RF3_AMBERITE)) continue;
476                 }
477                 else
478                 {
479                         if (!my_strchr(group_char, r_ptr->d_char)) continue;
480                 }
481
482                 mon_idx[mon_cnt++] = i;
483                 if (mode & 0x01) break;
484         }
485
486         mon_idx[mon_cnt] = -1;
487         int dummy_why;
488         ang_sort(mon_idx, &dummy_why, mon_cnt, ang_sort_comp_monster_level, ang_sort_swap_hook);
489         return mon_cnt;
490 }
491
492
493 /*
494  * Build a list of object indexes in the given group. Return the number
495  * of objects in the group.
496  *
497  * mode & 0x01 : check for non-empty group
498  * mode & 0x02 : visual operation only
499  */
500 static KIND_OBJECT_IDX collect_objects(int grp_cur, KIND_OBJECT_IDX object_idx[], BIT_FLAGS8 mode)
501 {
502         KIND_OBJECT_IDX object_cnt = 0;
503         byte group_tval = object_group_tval[grp_cur];
504         for (KIND_OBJECT_IDX i = 0; i < max_k_idx; i++)
505         {
506                 object_kind *k_ptr = &k_info[i];
507                 if (!k_ptr->name) continue;
508
509                 if (!(mode & 0x02))
510                 {
511                         if (!current_world_ptr->wizard)
512                         {
513                                 if (!k_ptr->flavor) continue;
514                                 if (!k_ptr->aware) continue;
515                         }
516
517                         int k = 0;
518                         for (int j = 0; j < 4; j++)
519                                 k += k_ptr->chance[j];
520                         if (!k) continue;
521                 }
522
523                 if (TV_LIFE_BOOK == group_tval)
524                 {
525                         if (TV_LIFE_BOOK <= k_ptr->tval && k_ptr->tval <= TV_HEX_BOOK)
526                         {
527                                 object_idx[object_cnt++] = i;
528                         }
529                         else
530                                 continue;
531                 }
532                 else if (k_ptr->tval == group_tval)
533                 {
534                         object_idx[object_cnt++] = i;
535                 }
536                 else
537                         continue;
538
539                 if (mode & 0x01) break;
540         }
541
542         object_idx[object_cnt] = -1;
543         return object_cnt;
544 }
545
546
547 /*
548  * Build a list of feature indexes in the given group. Return the number
549  * of features in the group.
550  *
551  * mode & 0x01 : check for non-empty group
552  */
553 static FEAT_IDX collect_features(FEAT_IDX *feat_idx, BIT_FLAGS8 mode)
554 {
555         FEAT_IDX feat_cnt = 0;
556         for (FEAT_IDX i = 0; i < max_f_idx; i++)
557         {
558                 feature_type *f_ptr = &f_info[i];
559                 if (!f_ptr->name) continue;
560                 if (f_ptr->mimic != i) continue;
561
562                 feat_idx[feat_cnt++] = i;
563                 if (mode & 0x01) break;
564         }
565
566         feat_idx[feat_cnt] = -1;
567         return feat_cnt;
568 }
569
570
571 /*
572  * Display known uniques
573  * With "XTRA HACK UNIQHIST" (Originally from XAngband)
574  */
575 static void do_cmd_knowledge_uniques(player_type *creature_ptr)
576 {
577         u16b why = 2;
578         IDX *who;
579         int n_alive[10];
580         int n_alive_surface = 0;
581         int n_alive_over100 = 0;
582         int n_alive_total = 0;
583         int max_lev = -1;
584         for (IDX i = 0; i < 10; i++)
585                 n_alive[i] = 0;
586
587         FILE *fff = NULL;
588         GAME_TEXT file_name[FILE_NAME_SIZE];
589         if (!open_temporary_file(&fff, file_name)) return;
590
591         C_MAKE(who, max_r_idx, MONRACE_IDX);
592         int n = 0;
593         for (IDX i = 1; i < max_r_idx; i++)
594         {
595                 monster_race *r_ptr = &r_info[i];
596                 if (!r_ptr->name) continue;
597                 if (!(r_ptr->flags1 & RF1_UNIQUE)) continue;
598                 if (!cheat_know && !r_ptr->r_sights) continue;
599                 if (!r_ptr->rarity || ((r_ptr->rarity > 100) && !(r_ptr->flags1 & RF1_QUESTOR))) continue;
600                 if (r_ptr->max_num == 0) continue;
601
602                 if (r_ptr->level)
603                 {
604                         int lev = (r_ptr->level - 1) / 10;
605                         if (lev < 10)
606                         {
607                                 n_alive[lev]++;
608                                 if (max_lev < lev) max_lev = lev;
609                         }
610                         else
611                                 n_alive_over100++;
612                 }
613                 else
614                         n_alive_surface++;
615
616                 who[n++] = i;
617         }
618
619         ang_sort(who, &why, n, ang_sort_comp_hook, ang_sort_swap_hook);
620         if (n_alive_surface)
621         {
622                 fprintf(fff, _("     地上  生存: %3d体\n", "      Surface  alive: %3d\n"), n_alive_surface);
623                 n_alive_total += n_alive_surface;
624         }
625
626         for (IDX i = 0; i <= max_lev; i++)
627         {
628                 fprintf(fff, _("%3d-%3d階  生存: %3d体\n", "Level %3d-%3d  alive: %3d\n"), 1 + i * 10, 10 + i * 10, n_alive[i]);
629                 n_alive_total += n_alive[i];
630         }
631
632         if (n_alive_over100)
633         {
634                 fprintf(fff, _("101-   階  生存: %3d体\n", "Level 101-     alive: %3d\n"), n_alive_over100);
635                 n_alive_total += n_alive_over100;
636         }
637
638         if (n_alive_total)
639         {
640                 fputs(_("---------  -----------\n", "-------------  ----------\n"), fff);
641                 fprintf(fff, _("     合計  生存: %3d体\n\n", "        Total  alive: %3d\n\n"), n_alive_total);
642         }
643         else
644         {
645                 fputs(_("現在は既知の生存ユニークはいません。\n", "No known uniques alive.\n"), fff);
646         }
647
648         for (int k = 0; k < n; k++)
649         {
650                 monster_race *r_ptr = &r_info[who[k]];
651                 fprintf(fff, _("     %s (レベル%d)\n", "     %s (level %d)\n"), r_name + r_ptr->name, (int)r_ptr->level);
652         }
653
654         C_KILL(who, max_r_idx, s16b);
655         my_fclose(fff);
656         (void)show_file(creature_ptr, TRUE, file_name, _("まだ生きているユニーク・モンスター", "Alive Uniques"), 0, 0);
657         fd_kill(file_name);
658 }
659
660
661 /*
662  * Display weapon-exp
663  */
664 static void do_cmd_knowledge_weapon_exp(player_type *creature_ptr)
665 {
666         FILE *fff = NULL;
667         GAME_TEXT file_name[FILE_NAME_SIZE];
668         if (!open_temporary_file(&fff, file_name)) return;
669
670         for (int i = 0; i < 5; i++)
671         {
672                 for (int num = 0; num < 64; num++)
673                 {
674                         SUB_EXP weapon_exp;
675                         char tmp[30];
676                         for (KIND_OBJECT_IDX j = 0; j < max_k_idx; j++)
677                         {
678                                 object_kind *k_ptr = &k_info[j];
679
680                                 if ((k_ptr->tval != TV_SWORD - i) || (k_ptr->sval != num)) continue;
681                                 if ((k_ptr->tval == TV_BOW) && (k_ptr->sval == SV_CRIMSON || k_ptr->sval == SV_HARP)) continue;
682
683                                 weapon_exp = creature_ptr->weapon_exp[4 - i][num];
684                                 strip_name(tmp, j);
685                                 fprintf(fff, "%-25s ", tmp);
686                                 if (weapon_exp >= s_info[creature_ptr->pclass].w_max[4 - i][num]) fprintf(fff, "!");
687                                 else fprintf(fff, " ");
688                                 fprintf(fff, "%s", exp_level_str[weapon_exp_level(weapon_exp)]);
689                                 if (cheat_xtra) fprintf(fff, " %d", weapon_exp);
690                                 fprintf(fff, "\n");
691                                 break;
692                         }
693                 }
694         }
695
696         my_fclose(fff);
697         (void)show_file(creature_ptr, TRUE, file_name, _("武器の経験値", "Weapon Proficiency"), 0, 0);
698         fd_kill(file_name);
699 }
700
701
702 /*!
703  * @brief 魔法の経験値を表示するコマンドのメインルーチン
704  * Display spell-exp
705  * @return なし
706  */
707 static void do_cmd_knowledge_spell_exp(player_type *creature_ptr)
708 {
709         FILE *fff = NULL;
710         GAME_TEXT file_name[FILE_NAME_SIZE];
711         if (!open_temporary_file(&fff, file_name)) return;
712
713         if (creature_ptr->realm1 != REALM_NONE)
714         {
715                 fprintf(fff, _("%sの魔法書\n", "%s Spellbook\n"), realm_names[creature_ptr->realm1]);
716                 for (SPELL_IDX i = 0; i < 32; i++)
717                 {
718                         const magic_type *s_ptr;
719                         if (!is_magic(creature_ptr->realm1))
720                         {
721                                 s_ptr = &technic_info[creature_ptr->realm1 - MIN_TECHNIC][i];
722                         }
723                         else
724                         {
725                                 s_ptr = &mp_ptr->info[creature_ptr->realm1 - 1][i];
726                         }
727
728                         if (s_ptr->slevel >= 99) continue;
729                         SUB_EXP spell_exp = creature_ptr->spell_exp[i];
730                         int exp_level = spell_exp_level(spell_exp);
731                         fprintf(fff, "%-25s ", exe_spell(creature_ptr, creature_ptr->realm1, i, SPELL_NAME));
732                         if (creature_ptr->realm1 == REALM_HISSATSU)
733                                 fprintf(fff, "[--]");
734                         else
735                         {
736                                 if (exp_level >= EXP_LEVEL_MASTER) fprintf(fff, "!");
737                                 else fprintf(fff, " ");
738                                 fprintf(fff, "%s", exp_level_str[exp_level]);
739                         }
740
741                         if (cheat_xtra) fprintf(fff, " %d", spell_exp);
742                         fprintf(fff, "\n");
743                 }
744         }
745
746         if (creature_ptr->realm2 != REALM_NONE)
747         {
748                 fprintf(fff, _("%sの魔法書\n", "\n%s Spellbook\n"), realm_names[creature_ptr->realm2]);
749                 for (SPELL_IDX i = 0; i < 32; i++)
750                 {
751                         const magic_type *s_ptr;
752                         if (!is_magic(creature_ptr->realm1))
753                         {
754                                 s_ptr = &technic_info[creature_ptr->realm2 - MIN_TECHNIC][i];
755                         }
756                         else
757                         {
758                                 s_ptr = &mp_ptr->info[creature_ptr->realm2 - 1][i];
759                         }
760
761                         if (s_ptr->slevel >= 99) continue;
762
763                         SUB_EXP spell_exp = creature_ptr->spell_exp[i + 32];
764                         int exp_level = spell_exp_level(spell_exp);
765                         fprintf(fff, "%-25s ", exe_spell(creature_ptr, creature_ptr->realm2, i, SPELL_NAME));
766                         if (exp_level >= EXP_LEVEL_EXPERT) fprintf(fff, "!");
767                         else fprintf(fff, " ");
768                         fprintf(fff, "%s", exp_level_str[exp_level]);
769                         if (cheat_xtra) fprintf(fff, " %d", spell_exp);
770                         fprintf(fff, "\n");
771                 }
772         }
773
774         my_fclose(fff);
775         (void)show_file(creature_ptr, TRUE, file_name, _("魔法の経験値", "Spell Proficiency"), 0, 0);
776         fd_kill(file_name);
777 }
778
779
780 /*!
781  * @brief スキル情報を表示するコマンドのメインルーチン /
782  * Display skill-exp
783  * @return なし
784  */
785 static void do_cmd_knowledge_skill_exp(player_type *creature_ptr)
786 {
787         char skill_name[GINOU_TEMPMAX][20] =
788         {
789                 _("マーシャルアーツ", "Martial Arts    "),
790                 _("二刀流          ", "Dual Wielding   "),
791                 _("乗馬            ", "Riding          "),
792                 _("盾              ", "Shield          ")
793         };
794
795         FILE *fff = NULL;
796         char file_name[FILE_NAME_SIZE];
797         if (!open_temporary_file(&fff, file_name)) return;
798
799         for (int i = 0; i < GINOU_TEMPMAX; i++)
800         {
801                 int skill_exp = creature_ptr->skill_exp[i];
802                 fprintf(fff, "%-20s ", skill_name[i]);
803                 if (skill_exp >= s_info[creature_ptr->pclass].s_max[i]) fprintf(fff, "!");
804                 else fprintf(fff, " ");
805                 fprintf(fff, "%s", exp_level_str[(i == GINOU_RIDING) ? riding_exp_level(skill_exp) : weapon_exp_level(skill_exp)]);
806                 if (cheat_xtra) fprintf(fff, " %d", skill_exp);
807                 fprintf(fff, "\n");
808         }
809
810         my_fclose(fff);
811         (void)show_file(creature_ptr, TRUE, file_name, _("技能の経験値", "Miscellaneous Proficiency"), 0, 0);
812         fd_kill(file_name);
813 }
814
815
816 /*!
817  * @brief 現在のペットを表示するコマンドのメインルーチン /
818  * Display current pets
819  * @param creature_ptr プレーヤーへの参照ポインタ
820  * @return なし
821  */
822 static void do_cmd_knowledge_pets(player_type *creature_ptr)
823 {
824         FILE *fff = NULL;
825         GAME_TEXT file_name[FILE_NAME_SIZE];
826         if (!open_temporary_file(&fff, file_name)) return;
827
828         monster_type *m_ptr;
829         GAME_TEXT pet_name[MAX_NLEN];
830         int t_friends = 0;
831         for (int i = creature_ptr->current_floor_ptr->m_max - 1; i >= 1; i--)
832         {
833                 m_ptr = &creature_ptr->current_floor_ptr->m_list[i];
834                 if (!monster_is_valid(m_ptr)) continue;
835                 if (!is_pet(m_ptr)) continue;
836
837                 t_friends++;
838                 monster_desc(creature_ptr, pet_name, m_ptr, MD_ASSUME_VISIBLE | MD_INDEF_VISIBLE);
839                 fprintf(fff, "%s (%s)\n", pet_name, look_mon_desc(m_ptr, 0x00));
840         }
841
842         int show_upkeep = calculate_upkeep(creature_ptr);
843
844         fprintf(fff, "----------------------------------------------\n");
845 #ifdef JP
846         fprintf(fff, "    合計: %d 体のペット\n", t_friends);
847 #else
848         fprintf(fff, "   Total: %d pet%s.\n", t_friends, (t_friends == 1 ? "" : "s"));
849 #endif
850         fprintf(fff, _(" 維持コスト: %d%% MP\n", "   Upkeep: %d%% mana.\n"), show_upkeep);
851
852         my_fclose(fff);
853         (void)show_file(creature_ptr, TRUE, file_name, _("現在のペット", "Current Pets"), 0, 0);
854         fd_kill(file_name);
855 }
856
857
858 /*!
859  * @brief 現在のペットを表示するコマンドのメインルーチン /
860  * @param creature_ptr プレーヤーへの参照ポインタ
861  * Total kill count
862  * @return なし
863  * @note the player ghosts are ignored.
864  */
865 static void do_cmd_knowledge_kill_count(player_type *creature_ptr)
866 {
867         FILE *fff = NULL;
868         GAME_TEXT file_name[FILE_NAME_SIZE];
869         if (!open_temporary_file(&fff, file_name)) return;
870
871         MONRACE_IDX *who;
872         C_MAKE(who, max_r_idx, MONRACE_IDX);
873         s32b total = 0;
874         for (int kk = 1; kk < max_r_idx; kk++)
875         {
876                 monster_race *r_ptr = &r_info[kk];
877
878                 if (r_ptr->flags1 & (RF1_UNIQUE))
879                 {
880                         bool dead = (r_ptr->max_num == 0);
881
882                         if (dead)
883                         {
884                                 total++;
885                         }
886                 }
887                 else
888                 {
889                         MONSTER_NUMBER this_monster = r_ptr->r_pkills;
890
891                         if (this_monster > 0)
892                         {
893                                 total += this_monster;
894                         }
895                 }
896         }
897
898         if (total < 1)
899                 fprintf(fff, _("あなたはまだ敵を倒していない。\n\n", "You have defeated no enemies yet.\n\n"));
900         else
901 #ifdef JP
902                 fprintf(fff, "あなたは%ld体の敵を倒している。\n\n", (long int)total);
903 #else
904                 fprintf(fff, "You have defeated %ld %s.\n\n", (long int)total, (total == 1) ? "enemy" : "enemies");
905 #endif
906
907         total = 0;
908         int n = 0;
909         for (MONRACE_IDX i = 1; i < max_r_idx; i++)
910         {
911                 monster_race *r_ptr = &r_info[i];
912                 if (r_ptr->name) who[n++] = i;
913         }
914
915         u16b why = 2;
916         ang_sort(who, &why, n, ang_sort_comp_hook, ang_sort_swap_hook);
917         for (int k = 0; k < n; k++)
918         {
919                 monster_race *r_ptr = &r_info[who[k]];
920                 if (r_ptr->flags1 & (RF1_UNIQUE))
921                 {
922                         bool dead = (r_ptr->max_num == 0);
923                         if (dead)
924                         {
925                                 fprintf(fff, "     %s\n", (r_name + r_ptr->name));
926                                 total++;
927                         }
928
929                         continue;
930                 }
931
932                 MONSTER_NUMBER this_monster = r_ptr->r_pkills;
933                 if (this_monster <= 0) continue;
934
935 #ifdef JP
936                 if (my_strchr("pt", r_ptr->d_char))
937                         fprintf(fff, "     %3d 人の %s\n", (int)this_monster, r_name + r_ptr->name);
938                 else
939                         fprintf(fff, "     %3d 体の %s\n", (int)this_monster, r_name + r_ptr->name);
940 #else
941                 if (this_monster < 2)
942                 {
943                         if (my_strstr(r_name + r_ptr->name, "coins"))
944                         {
945                                 fprintf(fff, "     1 pile of %s\n", (r_name + r_ptr->name));
946                         }
947                         else
948                         {
949                                 fprintf(fff, "     1 %s\n", (r_name + r_ptr->name));
950                         }
951                 }
952                 else
953                 {
954                         char ToPlural[80];
955                         strcpy(ToPlural, (r_name + r_ptr->name));
956                         plural_aux(ToPlural);
957                         fprintf(fff, "     %d %s\n", this_monster, ToPlural);
958                 }
959 #endif
960                 total += this_monster;
961         }
962
963         fprintf(fff, "----------------------------------------------\n");
964 #ifdef JP
965         fprintf(fff, "    合計: %lu 体を倒した。\n", (unsigned long int)total);
966 #else
967         fprintf(fff, "   Total: %lu creature%s killed.\n", (unsigned long int)total, (total == 1 ? "" : "s"));
968 #endif
969
970         C_KILL(who, max_r_idx, s16b);
971         my_fclose(fff);
972         (void)show_file(creature_ptr, TRUE, file_name, _("倒した敵の数", "Kill Count"), 0, 0);
973         fd_kill(file_name);
974 }
975
976
977 /*!
978  * @brief モンスター情報リスト中のグループを表示する /
979  * Display the object groups.
980  * @param col 開始行
981  * @param row 開始列
982  * @param wid 表示文字数幅
983  * @param per_page リストの表示行
984  * @param grp_idx グループのID配列
985  * @param group_text グループ名の文字列配列
986  * @param grp_cur 現在の選択ID
987  * @param grp_top 現在の選択リスト最上部ID
988  * @return なし
989  */
990 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)
991 {
992         for (int i = 0; i < per_page && (grp_idx[i] >= 0); i++)
993         {
994                 int grp = grp_idx[grp_top + i];
995                 TERM_COLOR attr = (grp_top + i == grp_cur) ? TERM_L_BLUE : TERM_WHITE;
996                 Term_erase(col, row + i, wid);
997                 c_put_str(attr, group_text[grp], row + i, col);
998         }
999 }
1000
1001
1002 /*
1003  * Move the cursor in a browser window
1004  */
1005 static void browser_cursor(char ch, int *column, IDX *grp_cur, int grp_cnt, IDX *list_cur, int list_cnt)
1006 {
1007         int d;
1008         int col = *column;
1009         IDX grp = *grp_cur;
1010         IDX list = *list_cur;
1011         if (ch == ' ')
1012                 d = 3;
1013         else if (ch == '-')
1014                 d = 9;
1015         else
1016                 d = get_keymap_dir(ch);
1017
1018         if (!d) return;
1019
1020         if ((ddx[d] > 0) && ddy[d])
1021         {
1022                 int browser_rows;
1023                 int wid, hgt;
1024                 Term_get_size(&wid, &hgt);
1025                 browser_rows = hgt - 8;
1026                 if (!col)
1027                 {
1028                         int old_grp = grp;
1029                         grp += ddy[d] * (browser_rows - 1);
1030                         if (grp >= grp_cnt)     grp = grp_cnt - 1;
1031                         if (grp < 0) grp = 0;
1032                         if (grp != old_grp)     list = 0;
1033                 }
1034                 else
1035                 {
1036                         list += ddy[d] * browser_rows;
1037                         if (list >= list_cnt) list = list_cnt - 1;
1038                         if (list < 0) list = 0;
1039                 }
1040
1041                 (*grp_cur) = grp;
1042                 (*list_cur) = list;
1043                 return;
1044         }
1045
1046         if (ddx[d])
1047         {
1048                 col += ddx[d];
1049                 if (col < 0) col = 0;
1050                 if (col > 1) col = 1;
1051
1052                 (*column) = col;
1053                 return;
1054         }
1055
1056         if (!col)
1057         {
1058                 int old_grp = grp;
1059                 grp += (IDX)ddy[d];
1060                 if (grp >= grp_cnt)     grp = grp_cnt - 1;
1061                 if (grp < 0) grp = 0;
1062                 if (grp != old_grp)     list = 0;
1063         }
1064         else
1065         {
1066                 list += (IDX)ddy[d];
1067                 if (list >= list_cnt) list = list_cnt - 1;
1068                 if (list < 0) list = 0;
1069         }
1070
1071         (*grp_cur) = grp;
1072         (*list_cur) = list;
1073 }
1074
1075
1076 /*
1077  * Display visuals.
1078  */
1079 static void display_visual_list(int col, int row, int height, int width, TERM_COLOR attr_top, byte char_left)
1080 {
1081         for (int i = 0; i < height; i++)
1082         {
1083                 Term_erase(col, row + i, width);
1084         }
1085
1086         if (use_bigtile) width /= 2;
1087
1088         for (int i = 0; i < height; i++)
1089         {
1090                 for (int j = 0; j < width; j++)
1091                 {
1092                         TERM_LEN x = col + j;
1093                         TERM_LEN y = row + i;
1094                         if (use_bigtile) x += j;
1095
1096                         int ia = attr_top + i;
1097                         int ic = char_left + j;
1098                         if (ia > 0x7f || ic > 0xff || ic < ' ' ||
1099                                 (!use_graphics && ic > 0x7f))
1100                                 continue;
1101
1102                         TERM_COLOR a = (TERM_COLOR)ia;
1103                         SYMBOL_CODE c = (SYMBOL_CODE)ic;
1104                         if (c & 0x80) a |= 0x80;
1105
1106                         Term_queue_bigchar(x, y, a, c, 0, 0);
1107                 }
1108         }
1109 }
1110
1111
1112 /*
1113  * Place the cursor at the collect position for visual mode
1114  */
1115 static void place_visual_list_cursor(TERM_LEN col, TERM_LEN row, TERM_COLOR a, byte c, TERM_COLOR attr_top, byte char_left)
1116 {
1117         int i = (a & 0x7f) - attr_top;
1118         int j = c - char_left;
1119
1120         TERM_LEN x = col + j;
1121         TERM_LEN y = row + i;
1122         if (use_bigtile) x += j;
1123
1124         Term_gotoxy(x, y);
1125 }
1126
1127
1128 /*
1129  * Display the monsters in a group.
1130  */
1131 static void display_monster_list(int col, int row, int per_page, s16b mon_idx[], int mon_cur, int mon_top, bool visual_only)
1132 {
1133         int i;
1134         for (i = 0; i < per_page && (mon_idx[mon_top + i] >= 0); i++)
1135         {
1136                 TERM_COLOR attr;
1137                 MONRACE_IDX r_idx = mon_idx[mon_top + i];
1138                 monster_race *r_ptr = &r_info[r_idx];
1139                 attr = ((i + mon_top == mon_cur) ? TERM_L_BLUE : TERM_WHITE);
1140                 c_prt(attr, (r_name + r_ptr->name), row + i, col);
1141                 if (per_page == 1)
1142                 {
1143                         c_prt(attr, format("%02x/%02x", r_ptr->x_attr, r_ptr->x_char), row + i, (current_world_ptr->wizard || visual_only) ? 56 : 61);
1144                 }
1145
1146                 if (current_world_ptr->wizard || visual_only)
1147                 {
1148                         c_prt(attr, format("%d", r_idx), row + i, 62);
1149                 }
1150
1151                 Term_erase(69, row + i, 255);
1152                 Term_queue_bigchar(use_bigtile ? 69 : 70, row + i, r_ptr->x_attr, r_ptr->x_char, 0, 0);
1153                 if (!visual_only)
1154                 {
1155                         if (!(r_ptr->flags1 & RF1_UNIQUE))
1156                                 put_str(format("%5d", r_ptr->r_pkills), row + i, 73);
1157                         else
1158                                 c_put_str((r_ptr->max_num == 0 ? TERM_L_DARK : TERM_WHITE),
1159                                 (r_ptr->max_num == 0 ? _("死亡", " dead") : _("生存", "alive")), row + i, 74);
1160                 }
1161         }
1162
1163         for (; i < per_page; i++)
1164         {
1165                 Term_erase(col, row + i, 255);
1166         }
1167 }
1168
1169
1170 /*
1171  * todo 引数の詳細について加筆求む
1172  * Display known monsters.
1173  * @param creature_ptr プレーヤーへの参照ポインタ
1174  * @param need_redraw 画面の再描画が必要な時TRUE
1175  * @param visual_only ???
1176  * @param direct_r_idx モンスターID
1177  * @return なし
1178  */
1179 void do_cmd_knowledge_monsters(player_type *creature_ptr, bool *need_redraw, bool visual_only, IDX direct_r_idx)
1180 {
1181         TERM_LEN wid, hgt;
1182         Term_get_size(&wid, &hgt);
1183         IDX *mon_idx;
1184         C_MAKE(mon_idx, max_r_idx, MONRACE_IDX);
1185
1186         int max = 0;
1187         IDX grp_cnt = 0;
1188         IDX grp_idx[100];
1189         IDX mon_cnt;
1190         bool visual_list = FALSE;
1191         TERM_COLOR attr_top = 0;
1192         byte char_left = 0;
1193         BIT_FLAGS8 mode;
1194         int browser_rows = hgt - 8;
1195         if (direct_r_idx < 0)
1196         {
1197                 mode = visual_only ? 0x03 : 0x01;
1198                 int len;
1199                 for (IDX i = 0; monster_group_text[i] != NULL; i++)
1200                 {
1201                         len = strlen(monster_group_text[i]);
1202                         if (len > max) max = len;
1203
1204                         if ((monster_group_char[i] == ((char *)-1L)) || collect_monsters(creature_ptr, i, mon_idx, mode))
1205                         {
1206                                 grp_idx[grp_cnt++] = i;
1207                         }
1208                 }
1209
1210                 mon_cnt = 0;
1211         }
1212         else
1213         {
1214                 mon_idx[0] = direct_r_idx;
1215                 mon_cnt = 1;
1216                 mon_idx[1] = -1;
1217
1218                 (void)visual_mode_command('v', &visual_list, browser_rows - 1, wid - (max + 3),
1219                         &attr_top, &char_left, &r_info[direct_r_idx].x_attr, &r_info[direct_r_idx].x_char, need_redraw);
1220         }
1221
1222         grp_idx[grp_cnt] = -1;
1223         mode = visual_only ? 0x02 : 0x00;
1224         IDX old_grp_cur = -1;
1225         IDX grp_cur = 0;
1226         IDX grp_top = 0;
1227         IDX mon_cur = 0;
1228         IDX mon_top = 0;
1229         int column = 0;
1230         bool flag = FALSE;
1231         bool redraw = TRUE;
1232         while (!flag)
1233         {
1234                 if (redraw)
1235                 {
1236                         clear_from(0);
1237                         prt(format(_("%s - モンスター", "%s - monsters"), !visual_only ? _("知識", "Knowledge") : _("表示", "Visuals")), 2, 0);
1238                         if (direct_r_idx < 0) prt(_("グループ", "Group"), 4, 0);
1239                         prt(_("名前", "Name"), 4, max + 3);
1240                         if (current_world_ptr->wizard || visual_only) prt("Idx", 4, 62);
1241                         prt(_("文字", "Sym"), 4, 67);
1242                         if (!visual_only) prt(_("殺害数", "Kills"), 4, 72);
1243
1244                         for (IDX i = 0; i < 78; i++)
1245                         {
1246                                 Term_putch(i, 5, TERM_WHITE, '=');
1247                         }
1248
1249                         if (direct_r_idx < 0)
1250                         {
1251                                 for (IDX i = 0; i < browser_rows; i++)
1252                                 {
1253                                         Term_putch(max + 1, 6 + i, TERM_WHITE, '|');
1254                                 }
1255                         }
1256
1257                         redraw = FALSE;
1258                 }
1259
1260                 if (direct_r_idx < 0)
1261                 {
1262                         if (grp_cur < grp_top) grp_top = grp_cur;
1263                         if (grp_cur >= grp_top + browser_rows) grp_top = grp_cur - browser_rows + 1;
1264
1265                         display_group_list(0, 6, max, browser_rows, grp_idx, monster_group_text, grp_cur, grp_top);
1266                         if (old_grp_cur != grp_cur)
1267                         {
1268                                 old_grp_cur = grp_cur;
1269                                 mon_cnt = collect_monsters(creature_ptr, grp_idx[grp_cur], mon_idx, mode);
1270                         }
1271
1272                         while (mon_cur < mon_top)
1273                                 mon_top = MAX(0, mon_top - browser_rows / 2);
1274                         while (mon_cur >= mon_top + browser_rows)
1275                                 mon_top = MIN(mon_cnt - browser_rows, mon_top + browser_rows / 2);
1276                 }
1277
1278                 if (!visual_list)
1279                 {
1280                         display_monster_list(max + 3, 6, browser_rows, mon_idx, mon_cur, mon_top, visual_only);
1281                 }
1282                 else
1283                 {
1284                         mon_top = mon_cur;
1285                         display_monster_list(max + 3, 6, 1, mon_idx, mon_cur, mon_top, visual_only);
1286                         display_visual_list(max + 3, 7, browser_rows - 1, wid - (max + 3), attr_top, char_left);
1287                 }
1288
1289                 prt(format(_("<方向>%s%s%s, ESC", "<dir>%s%s%s, ESC"),
1290                         (!visual_list && !visual_only) ? _(", 'r'で思い出を見る", ", 'r' to recall") : "",
1291                         visual_list ? _(", ENTERで決定", ", ENTER to accept") : _(", 'v'でシンボル変更", ", 'v' for visuals"),
1292                         (attr_idx || char_idx) ? _(", 'c', 'p'でペースト", ", 'c', 'p' to paste") : _(", 'c'でコピー", ", 'c' to copy")),
1293                         hgt - 1, 0);
1294
1295                 monster_race *r_ptr;
1296                 r_ptr = &r_info[mon_idx[mon_cur]];
1297
1298                 if (!visual_only)
1299                 {
1300                         if (mon_cnt) monster_race_track(creature_ptr, mon_idx[mon_cur]);
1301                         handle_stuff(creature_ptr);
1302                 }
1303
1304                 if (visual_list)
1305                 {
1306                         place_visual_list_cursor(max + 3, 7, r_ptr->x_attr, r_ptr->x_char, attr_top, char_left);
1307                 }
1308                 else if (!column)
1309                 {
1310                         Term_gotoxy(0, 6 + (grp_cur - grp_top));
1311                 }
1312                 else
1313                 {
1314                         Term_gotoxy(max + 3, 6 + (mon_cur - mon_top));
1315                 }
1316
1317                 char ch = inkey();
1318                 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))
1319                 {
1320                         if (direct_r_idx >= 0)
1321                         {
1322                                 switch (ch)
1323                                 {
1324                                 case '\n':
1325                                 case '\r':
1326                                 case ESCAPE:
1327                                         flag = TRUE;
1328                                         break;
1329                                 }
1330                         }
1331
1332                         continue;
1333                 }
1334
1335                 switch (ch)
1336                 {
1337                 case ESCAPE:
1338                 {
1339                         flag = TRUE;
1340                         break;
1341                 }
1342
1343                 case 'R':
1344                 case 'r':
1345                 {
1346                         if (!visual_list && !visual_only && (mon_idx[mon_cur] > 0))
1347                         {
1348                                 screen_roff(creature_ptr, mon_idx[mon_cur], 0);
1349
1350                                 (void)inkey();
1351
1352                                 redraw = TRUE;
1353                         }
1354
1355                         break;
1356                 }
1357
1358                 default:
1359                 {
1360                         browser_cursor(ch, &column, &grp_cur, grp_cnt, &mon_cur, mon_cnt);
1361
1362                         break;
1363                 }
1364                 }
1365         }
1366
1367         C_KILL(mon_idx, max_r_idx, MONRACE_IDX);
1368 }
1369
1370
1371 /*
1372  * Display the objects in a group.
1373  */
1374 static void display_object_list(int col, int row, int per_page, IDX object_idx[],
1375         int object_cur, int object_top, bool visual_only)
1376 {
1377         int i;
1378         for (i = 0; i < per_page && (object_idx[object_top + i] >= 0); i++)
1379         {
1380                 GAME_TEXT o_name[MAX_NLEN];
1381                 TERM_COLOR a;
1382                 SYMBOL_CODE c;
1383                 object_kind *flavor_k_ptr;
1384                 KIND_OBJECT_IDX k_idx = object_idx[object_top + i];
1385                 object_kind *k_ptr = &k_info[k_idx];
1386                 TERM_COLOR attr = ((k_ptr->aware || visual_only) ? TERM_WHITE : TERM_SLATE);
1387                 byte cursor = ((k_ptr->aware || visual_only) ? TERM_L_BLUE : TERM_BLUE);
1388                 if (!visual_only && k_ptr->flavor)
1389                 {
1390                         flavor_k_ptr = &k_info[k_ptr->flavor];
1391                 }
1392                 else
1393                 {
1394                         flavor_k_ptr = k_ptr;
1395                 }
1396
1397                 attr = ((i + object_top == object_cur) ? cursor : attr);
1398                 if (!k_ptr->flavor || (!visual_only && k_ptr->aware))
1399                 {
1400                         strip_name(o_name, k_idx);
1401                 }
1402                 else
1403                 {
1404                         strcpy(o_name, k_name + flavor_k_ptr->flavor_name);
1405                 }
1406
1407                 c_prt(attr, o_name, row + i, col);
1408                 if (per_page == 1)
1409                 {
1410                         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);
1411                 }
1412
1413                 if (current_world_ptr->wizard || visual_only)
1414                 {
1415                         c_prt(attr, format("%d", k_idx), row + i, 70);
1416                 }
1417
1418                 a = flavor_k_ptr->x_attr;
1419                 c = flavor_k_ptr->x_char;
1420
1421                 Term_queue_bigchar(use_bigtile ? 76 : 77, row + i, a, c, 0, 0);
1422         }
1423
1424         for (; i < per_page; i++)
1425         {
1426                 Term_erase(col, row + i, 255);
1427         }
1428 }
1429
1430
1431 /*
1432  * Describe fake object
1433  */
1434 static void desc_obj_fake(player_type *creature_ptr, KIND_OBJECT_IDX k_idx)
1435 {
1436         object_type *o_ptr;
1437         object_type object_type_body;
1438         o_ptr = &object_type_body;
1439         object_wipe(o_ptr);
1440         object_prep(o_ptr, k_idx);
1441
1442         o_ptr->ident |= IDENT_KNOWN;
1443         handle_stuff(creature_ptr);
1444
1445         if (screen_object(creature_ptr, o_ptr, SCROBJ_FAKE_OBJECT | SCROBJ_FORCE_DETAIL)) return;
1446
1447         msg_print(_("特に変わったところはないようだ。", "You see nothing special."));
1448         msg_print(NULL);
1449 }
1450
1451
1452 /*
1453  * Display known objects
1454  */
1455 void do_cmd_knowledge_objects(player_type *creature_ptr, bool *need_redraw, bool visual_only, IDX direct_k_idx)
1456 {
1457         IDX object_old, object_top;
1458         IDX grp_idx[100];
1459         int object_cnt;
1460         OBJECT_IDX *object_idx;
1461
1462         bool visual_list = FALSE;
1463         TERM_COLOR attr_top = 0;
1464         byte char_left = 0;
1465         byte mode;
1466
1467         TERM_LEN wid, hgt;
1468         Term_get_size(&wid, &hgt);
1469
1470         int browser_rows = hgt - 8;
1471         C_MAKE(object_idx, max_k_idx, KIND_OBJECT_IDX);
1472
1473         int len;
1474         int max = 0;
1475         int grp_cnt = 0;
1476         if (direct_k_idx < 0)
1477         {
1478                 mode = visual_only ? 0x03 : 0x01;
1479                 for (IDX i = 0; object_group_text[i] != NULL; i++)
1480                 {
1481                         len = strlen(object_group_text[i]);
1482                         if (len > max) max = len;
1483
1484                         if (collect_objects(i, object_idx, mode))
1485                         {
1486                                 grp_idx[grp_cnt++] = i;
1487                         }
1488                 }
1489
1490                 object_old = -1;
1491                 object_cnt = 0;
1492         }
1493         else
1494         {
1495                 object_kind *k_ptr = &k_info[direct_k_idx];
1496                 object_kind *flavor_k_ptr;
1497
1498                 if (!visual_only && k_ptr->flavor)
1499                 {
1500                         flavor_k_ptr = &k_info[k_ptr->flavor];
1501                 }
1502                 else
1503                 {
1504                         flavor_k_ptr = k_ptr;
1505                 }
1506
1507                 object_idx[0] = direct_k_idx;
1508                 object_old = direct_k_idx;
1509                 object_cnt = 1;
1510                 object_idx[1] = -1;
1511                 (void)visual_mode_command('v', &visual_list, browser_rows - 1, wid - (max + 3),
1512                         &attr_top, &char_left, &flavor_k_ptr->x_attr, &flavor_k_ptr->x_char, need_redraw);
1513         }
1514
1515         grp_idx[grp_cnt] = -1;
1516         mode = visual_only ? 0x02 : 0x00;
1517         IDX old_grp_cur = -1;
1518         IDX grp_cur = 0;
1519         IDX grp_top = 0;
1520         IDX object_cur = object_top = 0;
1521         bool flag = FALSE;
1522         bool redraw = TRUE;
1523         int column = 0;
1524         while (!flag)
1525         {
1526                 object_kind *k_ptr, *flavor_k_ptr;
1527
1528                 if (redraw)
1529                 {
1530                         clear_from(0);
1531
1532 #ifdef JP
1533                         prt(format("%s - アイテム", !visual_only ? "知識" : "表示"), 2, 0);
1534                         if (direct_k_idx < 0) prt("グループ", 4, 0);
1535                         prt("名前", 4, max + 3);
1536                         if (current_world_ptr->wizard || visual_only) prt("Idx", 4, 70);
1537                         prt("文字", 4, 74);
1538 #else
1539                         prt(format("%s - objects", !visual_only ? "Knowledge" : "Visuals"), 2, 0);
1540                         if (direct_k_idx < 0) prt("Group", 4, 0);
1541                         prt("Name", 4, max + 3);
1542                         if (current_world_ptr->wizard || visual_only) prt("Idx", 4, 70);
1543                         prt("Sym", 4, 75);
1544 #endif
1545
1546                         for (IDX i = 0; i < 78; i++)
1547                         {
1548                                 Term_putch(i, 5, TERM_WHITE, '=');
1549                         }
1550
1551                         if (direct_k_idx < 0)
1552                         {
1553                                 for (IDX i = 0; i < browser_rows; i++)
1554                                 {
1555                                         Term_putch(max + 1, 6 + i, TERM_WHITE, '|');
1556                                 }
1557                         }
1558
1559                         redraw = FALSE;
1560                 }
1561
1562                 if (direct_k_idx < 0)
1563                 {
1564                         if (grp_cur < grp_top) grp_top = grp_cur;
1565                         if (grp_cur >= grp_top + browser_rows) grp_top = grp_cur - browser_rows + 1;
1566
1567                         display_group_list(0, 6, max, browser_rows, grp_idx, object_group_text, grp_cur, grp_top);
1568                         if (old_grp_cur != grp_cur)
1569                         {
1570                                 old_grp_cur = grp_cur;
1571                                 object_cnt = collect_objects(grp_idx[grp_cur], object_idx, mode);
1572                         }
1573
1574                         while (object_cur < object_top)
1575                                 object_top = MAX(0, object_top - browser_rows / 2);
1576                         while (object_cur >= object_top + browser_rows)
1577                                 object_top = MIN(object_cnt - browser_rows, object_top + browser_rows / 2);
1578                 }
1579
1580                 if (!visual_list)
1581                 {
1582                         display_object_list(max + 3, 6, browser_rows, object_idx, object_cur, object_top, visual_only);
1583                 }
1584                 else
1585                 {
1586                         object_top = object_cur;
1587                         display_object_list(max + 3, 6, 1, object_idx, object_cur, object_top, visual_only);
1588                         display_visual_list(max + 3, 7, browser_rows - 1, wid - (max + 3), attr_top, char_left);
1589                 }
1590
1591                 k_ptr = &k_info[object_idx[object_cur]];
1592
1593                 if (!visual_only && k_ptr->flavor)
1594                 {
1595                         flavor_k_ptr = &k_info[k_ptr->flavor];
1596                 }
1597                 else
1598                 {
1599                         flavor_k_ptr = k_ptr;
1600                 }
1601
1602 #ifdef JP
1603                 prt(format("<方向>%s%s%s, ESC",
1604                         (!visual_list && !visual_only) ? ", 'r'で詳細を見る" : "",
1605                         visual_list ? ", ENTERで決定" : ", 'v'でシンボル変更",
1606                         (attr_idx || char_idx) ? ", 'c', 'p'でペースト" : ", 'c'でコピー"),
1607                         hgt - 1, 0);
1608 #else
1609                 prt(format("<dir>%s%s%s, ESC",
1610                         (!visual_list && !visual_only) ? ", 'r' to recall" : "",
1611                         visual_list ? ", ENTER to accept" : ", 'v' for visuals",
1612                         (attr_idx || char_idx) ? ", 'c', 'p' to paste" : ", 'c' to copy"),
1613                         hgt - 1, 0);
1614 #endif
1615
1616                 if (!visual_only)
1617                 {
1618                         if (object_cnt) object_kind_track(creature_ptr, object_idx[object_cur]);
1619
1620                         if (object_old != object_idx[object_cur])
1621                         {
1622                                 handle_stuff(creature_ptr);
1623                                 object_old = object_idx[object_cur];
1624                         }
1625                 }
1626
1627                 if (visual_list)
1628                 {
1629                         place_visual_list_cursor(max + 3, 7, flavor_k_ptr->x_attr, flavor_k_ptr->x_char, attr_top, char_left);
1630                 }
1631                 else if (!column)
1632                 {
1633                         Term_gotoxy(0, 6 + (grp_cur - grp_top));
1634                 }
1635                 else
1636                 {
1637                         Term_gotoxy(max + 3, 6 + (object_cur - object_top));
1638                 }
1639
1640                 char ch = inkey();
1641                 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))
1642                 {
1643                         if (direct_k_idx >= 0)
1644                         {
1645                                 switch (ch)
1646                                 {
1647                                 case '\n':
1648                                 case '\r':
1649                                 case ESCAPE:
1650                                         flag = TRUE;
1651                                         break;
1652                                 }
1653                         }
1654                         continue;
1655                 }
1656
1657                 switch (ch)
1658                 {
1659                 case ESCAPE:
1660                 {
1661                         flag = TRUE;
1662                         break;
1663                 }
1664
1665                 case 'R':
1666                 case 'r':
1667                 {
1668                         if (!visual_list && !visual_only && (grp_cnt > 0))
1669                         {
1670                                 desc_obj_fake(creature_ptr, object_idx[object_cur]);
1671                                 redraw = TRUE;
1672                         }
1673
1674                         break;
1675                 }
1676
1677                 default:
1678                 {
1679                         browser_cursor(ch, &column, &grp_cur, grp_cnt, &object_cur, object_cnt);
1680                         break;
1681                 }
1682                 }
1683         }
1684
1685         C_KILL(object_idx, max_k_idx, KIND_OBJECT_IDX);
1686 }
1687
1688
1689 /*
1690  * Display the features in a group.
1691  */
1692 static void display_feature_list(int col, int row, int per_page, FEAT_IDX *feat_idx,
1693         FEAT_IDX feat_cur, FEAT_IDX feat_top, bool visual_only, int lighting_level)
1694 {
1695         int lit_col[F_LIT_MAX], i;
1696         int f_idx_col = use_bigtile ? 62 : 64;
1697
1698         lit_col[F_LIT_STANDARD] = use_bigtile ? (71 - F_LIT_MAX) : 71;
1699         for (i = F_LIT_NS_BEGIN; i < F_LIT_MAX; i++)
1700                 lit_col[i] = lit_col[F_LIT_STANDARD] + 2 + (i - F_LIT_NS_BEGIN) * 2 + (use_bigtile ? i : 0);
1701
1702         for (i = 0; i < per_page && (feat_idx[feat_top + i] >= 0); i++)
1703         {
1704                 TERM_COLOR attr;
1705                 FEAT_IDX f_idx = feat_idx[feat_top + i];
1706                 feature_type *f_ptr = &f_info[f_idx];
1707                 int row_i = row + i;
1708                 attr = ((i + feat_top == feat_cur) ? TERM_L_BLUE : TERM_WHITE);
1709                 c_prt(attr, f_name + f_ptr->name, row_i, col);
1710                 if (per_page == 1)
1711                 {
1712                         c_prt(attr, format("(%s)", lighting_level_str[lighting_level]), row_i, col + 1 + strlen(f_name + f_ptr->name));
1713                         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));
1714                 }
1715                 if (current_world_ptr->wizard || visual_only)
1716                 {
1717                         c_prt(attr, format("%d", f_idx), row_i, f_idx_col);
1718                 }
1719
1720                 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);
1721                 Term_putch(lit_col[F_LIT_NS_BEGIN], row_i, TERM_SLATE, '(');
1722                 for (int j = F_LIT_NS_BEGIN + 1; j < F_LIT_MAX; j++)
1723                 {
1724                         Term_putch(lit_col[j], row_i, TERM_SLATE, '/');
1725                 }
1726
1727                 Term_putch(lit_col[F_LIT_MAX - 1] + (use_bigtile ? 3 : 2), row_i, TERM_SLATE, ')');
1728                 for (int j = F_LIT_NS_BEGIN; j < F_LIT_MAX; j++)
1729                 {
1730                         Term_queue_bigchar(lit_col[j] + 1, row_i, f_ptr->x_attr[j], f_ptr->x_char[j], 0, 0);
1731                 }
1732         }
1733
1734         for (; i < per_page; i++)
1735         {
1736                 Term_erase(col, row + i, 255);
1737         }
1738 }
1739
1740
1741 /*
1742  * Interact with feature visuals.
1743  */
1744 void do_cmd_knowledge_features(bool *need_redraw, bool visual_only, IDX direct_f_idx, IDX *lighting_level)
1745 {
1746         TERM_COLOR attr_old[F_LIT_MAX];
1747         (void)C_WIPE(attr_old, F_LIT_MAX, TERM_COLOR);
1748         SYMBOL_CODE char_old[F_LIT_MAX];
1749         (void)C_WIPE(char_old, F_LIT_MAX, SYMBOL_CODE);
1750
1751         TERM_LEN wid, hgt;
1752         Term_get_size(&wid, &hgt);
1753
1754         FEAT_IDX *feat_idx;
1755         C_MAKE(feat_idx, max_f_idx, FEAT_IDX);
1756
1757         concptr feature_group_text[] = { "terrains", NULL };
1758         int len;
1759         int max = 0;
1760         int grp_cnt = 0;
1761         int feat_cnt;
1762         FEAT_IDX grp_idx[100];
1763         TERM_COLOR attr_top = 0;
1764         bool visual_list = FALSE;
1765         byte char_left = 0;
1766         TERM_LEN browser_rows = hgt - 8;
1767         if (direct_f_idx < 0)
1768         {
1769                 for (FEAT_IDX i = 0; feature_group_text[i] != NULL; i++)
1770                 {
1771                         len = strlen(feature_group_text[i]);
1772                         if (len > max) max = len;
1773
1774                         if (collect_features(feat_idx, 0x01))
1775                         {
1776                                 grp_idx[grp_cnt++] = i;
1777                         }
1778                 }
1779
1780                 feat_cnt = 0;
1781         }
1782         else
1783         {
1784                 feature_type *f_ptr = &f_info[direct_f_idx];
1785
1786                 feat_idx[0] = direct_f_idx;
1787                 feat_cnt = 1;
1788                 feat_idx[1] = -1;
1789
1790                 (void)visual_mode_command('v', &visual_list, browser_rows - 1, wid - (max + 3),
1791                         &attr_top, &char_left, &f_ptr->x_attr[*lighting_level], &f_ptr->x_char[*lighting_level], need_redraw);
1792
1793                 for (FEAT_IDX i = 0; i < F_LIT_MAX; i++)
1794                 {
1795                         attr_old[i] = f_ptr->x_attr[i];
1796                         char_old[i] = f_ptr->x_char[i];
1797                 }
1798         }
1799
1800         grp_idx[grp_cnt] = -1;
1801
1802         FEAT_IDX old_grp_cur = -1;
1803         FEAT_IDX grp_cur = 0;
1804         FEAT_IDX grp_top = 0;
1805         FEAT_IDX feat_cur = 0;
1806         FEAT_IDX feat_top = 0;
1807         TERM_LEN column = 0;
1808         bool flag = FALSE;
1809         bool redraw = TRUE;
1810         TERM_COLOR *cur_attr_ptr;
1811         SYMBOL_CODE *cur_char_ptr;
1812         while (!flag)
1813         {
1814                 char ch;
1815                 feature_type *f_ptr;
1816
1817                 if (redraw)
1818                 {
1819                         clear_from(0);
1820
1821                         prt(_("表示 - 地形", "Visuals - features"), 2, 0);
1822                         if (direct_f_idx < 0) prt(_("グループ", "Group"), 4, 0);
1823                         prt(_("名前", "Name"), 4, max + 3);
1824                         if (use_bigtile)
1825                         {
1826                                 if (current_world_ptr->wizard || visual_only) prt("Idx", 4, 62);
1827                                 prt(_("文字 ( l/ d)", "Sym ( l/ d)"), 4, 66);
1828                         }
1829                         else
1830                         {
1831                                 if (current_world_ptr->wizard || visual_only) prt("Idx", 4, 64);
1832                                 prt(_("文字 (l/d)", "Sym (l/d)"), 4, 68);
1833                         }
1834
1835                         for (FEAT_IDX i = 0; i < 78; i++)
1836                         {
1837                                 Term_putch(i, 5, TERM_WHITE, '=');
1838                         }
1839
1840                         if (direct_f_idx < 0)
1841                         {
1842                                 for (FEAT_IDX i = 0; i < browser_rows; i++)
1843                                 {
1844                                         Term_putch(max + 1, 6 + i, TERM_WHITE, '|');
1845                                 }
1846                         }
1847
1848                         redraw = FALSE;
1849                 }
1850
1851                 if (direct_f_idx < 0)
1852                 {
1853                         if (grp_cur < grp_top) grp_top = grp_cur;
1854                         if (grp_cur >= grp_top + browser_rows) grp_top = grp_cur - browser_rows + 1;
1855
1856                         display_group_list(0, 6, max, browser_rows, grp_idx, feature_group_text, grp_cur, grp_top);
1857                         if (old_grp_cur != grp_cur)
1858                         {
1859                                 old_grp_cur = grp_cur;
1860                                 feat_cnt = collect_features(feat_idx, 0x00);
1861                         }
1862
1863                         while (feat_cur < feat_top)
1864                                 feat_top = MAX(0, feat_top - browser_rows / 2);
1865                         while (feat_cur >= feat_top + browser_rows)
1866                                 feat_top = MIN(feat_cnt - browser_rows, feat_top + browser_rows / 2);
1867                 }
1868
1869                 if (!visual_list)
1870                 {
1871                         display_feature_list(max + 3, 6, browser_rows, feat_idx, feat_cur, feat_top, visual_only, F_LIT_STANDARD);
1872                 }
1873                 else
1874                 {
1875                         feat_top = feat_cur;
1876                         display_feature_list(max + 3, 6, 1, feat_idx, feat_cur, feat_top, visual_only, *lighting_level);
1877                         display_visual_list(max + 3, 7, browser_rows - 1, wid - (max + 3), attr_top, char_left);
1878                 }
1879
1880                 prt(format(_("<方向>%s, 'd'で標準光源効果%s, ESC", "<dir>%s, 'd' for default lighting%s, ESC"),
1881                         visual_list ? _(", ENTERで決定, 'a'で対象明度変更", ", ENTER to accept, 'a' for lighting level") : _(", 'v'でシンボル変更", ", 'v' for visuals"),
1882                         (attr_idx || char_idx) ? _(", 'c', 'p'でペースト", ", 'c', 'p' to paste") : _(", 'c'でコピー", ", 'c' to copy")),
1883                         hgt - 1, 0);
1884
1885                 f_ptr = &f_info[feat_idx[feat_cur]];
1886                 cur_attr_ptr = &f_ptr->x_attr[*lighting_level];
1887                 cur_char_ptr = &f_ptr->x_char[*lighting_level];
1888
1889                 if (visual_list)
1890                 {
1891                         place_visual_list_cursor(max + 3, 7, *cur_attr_ptr, *cur_char_ptr, attr_top, char_left);
1892                 }
1893                 else if (!column)
1894                 {
1895                         Term_gotoxy(0, 6 + (grp_cur - grp_top));
1896                 }
1897                 else
1898                 {
1899                         Term_gotoxy(max + 3, 6 + (feat_cur - feat_top));
1900                 }
1901
1902                 ch = inkey();
1903                 if (visual_list && ((ch == 'A') || (ch == 'a')))
1904                 {
1905                         int prev_lighting_level = *lighting_level;
1906
1907                         if (ch == 'A')
1908                         {
1909                                 if (*lighting_level <= 0) *lighting_level = F_LIT_MAX - 1;
1910                                 else (*lighting_level)--;
1911                         }
1912                         else
1913                         {
1914                                 if (*lighting_level >= F_LIT_MAX - 1) *lighting_level = 0;
1915                                 else (*lighting_level)++;
1916                         }
1917
1918                         if (f_ptr->x_attr[prev_lighting_level] != f_ptr->x_attr[*lighting_level])
1919                                 attr_top = MAX(0, (f_ptr->x_attr[*lighting_level] & 0x7f) - 5);
1920
1921                         if (f_ptr->x_char[prev_lighting_level] != f_ptr->x_char[*lighting_level])
1922                                 char_left = MAX(0, f_ptr->x_char[*lighting_level] - 10);
1923
1924                         continue;
1925                 }
1926                 else if ((ch == 'D') || (ch == 'd'))
1927                 {
1928                         TERM_COLOR prev_x_attr = f_ptr->x_attr[*lighting_level];
1929                         byte prev_x_char = f_ptr->x_char[*lighting_level];
1930
1931                         apply_default_feat_lighting(f_ptr->x_attr, f_ptr->x_char);
1932
1933                         if (visual_list)
1934                         {
1935                                 if (prev_x_attr != f_ptr->x_attr[*lighting_level])
1936                                         attr_top = MAX(0, (f_ptr->x_attr[*lighting_level] & 0x7f) - 5);
1937
1938                                 if (prev_x_char != f_ptr->x_char[*lighting_level])
1939                                         char_left = MAX(0, f_ptr->x_char[*lighting_level] - 10);
1940                         }
1941                         else *need_redraw = TRUE;
1942
1943                         continue;
1944                 }
1945                 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))
1946                 {
1947                         switch (ch)
1948                         {
1949                         case ESCAPE:
1950                                 for (FEAT_IDX i = 0; i < F_LIT_MAX; i++)
1951                                 {
1952                                         f_ptr->x_attr[i] = attr_old[i];
1953                                         f_ptr->x_char[i] = char_old[i];
1954                                 }
1955
1956                                 /* Fall through */
1957                         case '\n':
1958                         case '\r':
1959                                 if (direct_f_idx >= 0) flag = TRUE;
1960                                 else *lighting_level = F_LIT_STANDARD;
1961                                 break;
1962                         case 'V':
1963                         case 'v':
1964                                 for (FEAT_IDX i = 0; i < F_LIT_MAX; i++)
1965                                 {
1966                                         attr_old[i] = f_ptr->x_attr[i];
1967                                         char_old[i] = f_ptr->x_char[i];
1968                                 }
1969                                 *lighting_level = F_LIT_STANDARD;
1970                                 break;
1971
1972                         case 'C':
1973                         case 'c':
1974                                 if (!visual_list)
1975                                 {
1976                                         for (FEAT_IDX i = 0; i < F_LIT_MAX; i++)
1977                                         {
1978                                                 attr_idx_feat[i] = f_ptr->x_attr[i];
1979                                                 char_idx_feat[i] = f_ptr->x_char[i];
1980                                         }
1981                                 }
1982                                 break;
1983
1984                         case 'P':
1985                         case 'p':
1986                                 if (!visual_list)
1987                                 {
1988                                         for (FEAT_IDX i = F_LIT_NS_BEGIN; i < F_LIT_MAX; i++)
1989                                         {
1990                                                 if (attr_idx_feat[i] || (!(char_idx_feat[i] & 0x80) && char_idx_feat[i])) f_ptr->x_attr[i] = attr_idx_feat[i];
1991                                                 if (char_idx_feat[i]) f_ptr->x_char[i] = char_idx_feat[i];
1992                                         }
1993                                 }
1994                                 break;
1995                         }
1996                         continue;
1997                 }
1998
1999                 switch (ch)
2000                 {
2001                 case ESCAPE:
2002                 {
2003                         flag = TRUE;
2004                         break;
2005                 }
2006
2007                 default:
2008                 {
2009                         browser_cursor(ch, &column, &grp_cur, grp_cnt, &feat_cur, feat_cnt);
2010                         break;
2011                 }
2012                 }
2013         }
2014
2015         C_KILL(feat_idx, max_f_idx, FEAT_IDX);
2016 }
2017
2018
2019 /*
2020  * List wanted monsters
2021  * @param creature_ptr プレーヤーへの参照ポインタ
2022  * @return なし
2023  */
2024 static void do_cmd_knowledge_bounty(player_type *creature_ptr)
2025 {
2026         FILE *fff = NULL;
2027         GAME_TEXT file_name[FILE_NAME_SIZE];
2028         if (!open_temporary_file(&fff, file_name)) return;
2029
2030         fprintf(fff, _("今日のターゲット : %s\n", "Today's target : %s\n"),
2031                 (creature_ptr->today_mon ? r_name + r_info[creature_ptr->today_mon].name : _("不明", "unknown")));
2032         fprintf(fff, "\n");
2033         fprintf(fff, _("賞金首リスト\n", "List of wanted monsters\n"));
2034         fprintf(fff, "----------------------------------------------\n");
2035
2036         bool listed = FALSE;
2037         for (int i = 0; i < MAX_BOUNTY; i++)
2038         {
2039                 if (current_world_ptr->bounty_r_idx[i] <= 10000)
2040                 {
2041                         fprintf(fff, "%s\n", r_name + r_info[current_world_ptr->bounty_r_idx[i]].name);
2042                         listed = TRUE;
2043                 }
2044         }
2045
2046         if (!listed)
2047         {
2048                 fprintf(fff, "\n%s\n", _("賞金首はもう残っていません。", "There are no more wanted monster."));
2049         }
2050
2051         my_fclose(fff);
2052         (void)show_file(creature_ptr, TRUE, file_name, _("賞金首の一覧", "Wanted monsters"), 0, 0);
2053         fd_kill(file_name);
2054 }
2055
2056 /*
2057  * List virtues & status
2058  */
2059 static void do_cmd_knowledge_virtues(player_type *creature_ptr)
2060 {
2061         FILE *fff = NULL;
2062         GAME_TEXT file_name[FILE_NAME_SIZE];
2063         if (!open_temporary_file(&fff, file_name)) return;
2064
2065         fprintf(fff, _("現在の属性 : %s\n\n", "Your alignment : %s\n\n"), your_alignment(creature_ptr));
2066         dump_virtues(creature_ptr, fff);
2067         my_fclose(fff);
2068         (void)show_file(creature_ptr, TRUE, file_name, _("八つの徳", "Virtues"), 0, 0);
2069         fd_kill(file_name);
2070 }
2071
2072 /*
2073  * Dungeon
2074  */
2075 static void do_cmd_knowledge_dungeon(player_type *creature_ptr)
2076 {
2077         FILE *fff = NULL;
2078         GAME_TEXT file_name[FILE_NAME_SIZE];
2079         if (!open_temporary_file(&fff, file_name)) return;
2080
2081         for (int i = 1; i < current_world_ptr->max_d_idx; i++)
2082         {
2083                 bool seiha = FALSE;
2084
2085                 if (!d_info[i].maxdepth) continue;
2086                 if (!max_dlv[i]) continue;
2087                 if (d_info[i].final_guardian)
2088                 {
2089                         if (!r_info[d_info[i].final_guardian].max_num) seiha = TRUE;
2090                 }
2091                 else if (max_dlv[i] == d_info[i].maxdepth) seiha = TRUE;
2092
2093                 fprintf(fff, _("%c%-12s :  %3d 階\n", "%c%-16s :  level %3d\n"), seiha ? '!' : ' ', d_name + d_info[i].name, (int)max_dlv[i]);
2094         }
2095
2096         my_fclose(fff);
2097         (void)show_file(creature_ptr, TRUE, file_name, _("今までに入ったダンジョン", "Dungeon"), 0, 0);
2098         fd_kill(file_name);
2099 }
2100
2101
2102 /*
2103 * List virtues & status
2104 *
2105 */
2106 static void do_cmd_knowledge_stat(player_type *creature_ptr)
2107 {
2108         FILE *fff = NULL;
2109         GAME_TEXT file_name[FILE_NAME_SIZE];
2110         if (!open_temporary_file(&fff, file_name)) return;
2111
2112         int percent = (int)(((long)creature_ptr->player_hp[PY_MAX_LEVEL - 1] * 200L) /
2113                 (2 * creature_ptr->hitdie +
2114                 ((PY_MAX_LEVEL - 1 + 3) * (creature_ptr->hitdie + 1))));
2115
2116         if (creature_ptr->knowledge & KNOW_HPRATE)
2117                 fprintf(fff, _("現在の体力ランク : %d/100\n\n", "Your current Life Rating is %d/100.\n\n"), percent);
2118         else fprintf(fff, _("現在の体力ランク : ???\n\n", "Your current Life Rating is ???.\n\n"));
2119
2120         fprintf(fff, _("能力の最大値\n\n", "Limits of maximum stats\n\n"));
2121         for (int v_nr = 0; v_nr < A_MAX; v_nr++)
2122         {
2123                 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);
2124                 else fprintf(fff, "%s ???\n", stat_names[v_nr]);
2125         }
2126
2127         dump_yourself(creature_ptr, fff);
2128         my_fclose(fff);
2129         (void)show_file(creature_ptr, TRUE, file_name, _("自分に関する情報", "HP-rate & Max stat"), 0, 0);
2130         fd_kill(file_name);
2131 }
2132
2133
2134 /*
2135  * todo player_typeではなくQUEST_IDXを引数にすべきかもしれない
2136  * Print all active quests
2137  * @param creature_ptr プレーヤーへの参照ポインタ
2138  * @return なし
2139  */
2140 static void do_cmd_knowledge_quests_current(player_type *creature_ptr, FILE *fff)
2141 {
2142         char tmp_str[120];
2143         char rand_tmp_str[120] = "\0";
2144         GAME_TEXT name[MAX_NLEN];
2145         monster_race *r_ptr;
2146         int rand_level = 100;
2147         int total = 0;
2148
2149         fprintf(fff, _("《遂行中のクエスト》\n", "< Current Quest >\n"));
2150
2151         for (QUEST_IDX i = 1; i < max_q_idx; i++)
2152         {
2153                 bool is_print = quest[i].status == QUEST_STATUS_TAKEN;
2154                 is_print |= (quest[i].status == QUEST_STATUS_STAGE_COMPLETED) && (quest[i].type == QUEST_TYPE_TOWER);
2155                 is_print |= quest[i].status == QUEST_STATUS_COMPLETED;
2156                 if (!is_print)
2157                         continue;
2158
2159                 QUEST_IDX old_quest = creature_ptr->current_floor_ptr->inside_quest;
2160                 for (int j = 0; j < 10; j++)
2161                         quest_text[j][0] = '\0';
2162
2163                 quest_text_line = 0;
2164                 creature_ptr->current_floor_ptr->inside_quest = i;
2165                 init_flags = INIT_SHOW_TEXT;
2166                 process_dungeon_file(creature_ptr, "q_info.txt", 0, 0, 0, 0);
2167                 creature_ptr->current_floor_ptr->inside_quest = old_quest;
2168                 if (quest[i].flags & QUEST_FLAG_SILENT) continue;
2169
2170                 total++;
2171                 if (quest[i].type != QUEST_TYPE_RANDOM)
2172                 {
2173                         char note[80] = "\0";
2174
2175                         if (quest[i].status == QUEST_STATUS_TAKEN || quest[i].status == QUEST_STATUS_STAGE_COMPLETED)
2176                         {
2177                                 switch (quest[i].type)
2178                                 {
2179                                 case QUEST_TYPE_KILL_LEVEL:
2180                                 case QUEST_TYPE_KILL_ANY_LEVEL:
2181                                         r_ptr = &r_info[quest[i].r_idx];
2182                                         strcpy(name, r_name + r_ptr->name);
2183                                         if (quest[i].max_num > 1)
2184                                         {
2185 #ifdef JP
2186                                                 sprintf(note, " - %d 体の%sを倒す。(あと %d 体)",
2187                                                         (int)quest[i].max_num, name, (int)(quest[i].max_num - quest[i].cur_num));
2188 #else
2189                                                 plural_aux(name);
2190                                                 sprintf(note, " - kill %d %s, have killed %d.",
2191                                                         (int)quest[i].max_num, name, (int)quest[i].cur_num);
2192 #endif
2193                                         }
2194                                         else
2195                                                 sprintf(note, _(" - %sを倒す。", " - kill %s."), name);
2196                                         break;
2197
2198                                 case QUEST_TYPE_FIND_ARTIFACT:
2199                                         if (quest[i].k_idx)
2200                                         {
2201                                                 artifact_type *a_ptr = &a_info[quest[i].k_idx];
2202                                                 object_type forge;
2203                                                 object_type *q_ptr = &forge;
2204                                                 KIND_OBJECT_IDX k_idx = lookup_kind(a_ptr->tval, a_ptr->sval);
2205                                                 object_prep(q_ptr, k_idx);
2206                                                 q_ptr->name1 = quest[i].k_idx;
2207                                                 q_ptr->ident = IDENT_STORE;
2208                                                 object_desc(creature_ptr, name, q_ptr, OD_NAME_ONLY);
2209                                         }
2210                                         sprintf(note, _("\n   - %sを見つけ出す。", "\n   - Find %s."), name);
2211                                         break;
2212                                 case QUEST_TYPE_FIND_EXIT:
2213                                         sprintf(note, _(" - 出口に到達する。", " - Reach exit."));
2214                                         break;
2215
2216                                 case QUEST_TYPE_KILL_NUMBER:
2217 #ifdef JP
2218                                         sprintf(note, " - %d 体のモンスターを倒す。(あと %d 体)",
2219                                                 (int)quest[i].max_num, (int)(quest[i].max_num - quest[i].cur_num));
2220 #else
2221                                         sprintf(note, " - Kill %d monsters, have killed %d.",
2222                                                 (int)quest[i].max_num, (int)quest[i].cur_num);
2223 #endif
2224                                         break;
2225
2226                                 case QUEST_TYPE_KILL_ALL:
2227                                 case QUEST_TYPE_TOWER:
2228                                         sprintf(note, _(" - 全てのモンスターを倒す。", " - Kill all monsters."));
2229                                         break;
2230                                 }
2231                         }
2232
2233                         sprintf(tmp_str, _("  %s (危険度:%d階相当)%s\n", "  %s (Danger level: %d)%s\n"),
2234                                 quest[i].name, (int)quest[i].level, note);
2235                         fputs(tmp_str, fff);
2236                         if (quest[i].status == QUEST_STATUS_COMPLETED)
2237                         {
2238                                 sprintf(tmp_str, _("    クエスト達成 - まだ報酬を受けとってない。\n", "    Quest Completed - Unrewarded\n"));
2239                                 fputs(tmp_str, fff);
2240                                 continue;
2241                         }
2242
2243                         int k = 0;
2244                         while (quest_text[k][0] && k < 10)
2245                         {
2246                                 fprintf(fff, "    %s\n", quest_text[k]);
2247                                 k++;
2248                         }
2249
2250                         continue;
2251                 }
2252
2253                 if (quest[i].level >= rand_level)
2254                         continue;
2255
2256                 rand_level = quest[i].level;
2257                 if (max_dlv[DUNGEON_ANGBAND] < rand_level) continue;
2258
2259                 r_ptr = &r_info[quest[i].r_idx];
2260                 strcpy(name, r_name + r_ptr->name);
2261                 if (quest[i].max_num <= 1)
2262                 {
2263                         sprintf(rand_tmp_str, _("  %s (%d 階) - %sを倒す。\n", "  %s (Dungeon level: %d)\n  Kill %s.\n"),
2264                                 quest[i].name, (int)quest[i].level, name);
2265                         continue;
2266                 }
2267
2268 #ifdef JP
2269                 sprintf(rand_tmp_str, "  %s (%d 階) - %d 体の%sを倒す。(あと %d 体)\n",
2270                         quest[i].name, (int)quest[i].level,
2271                         (int)quest[i].max_num, name, (int)(quest[i].max_num - quest[i].cur_num));
2272 #else
2273                 plural_aux(name);
2274
2275                 sprintf(rand_tmp_str, "  %s (Dungeon level: %d)\n  Kill %d %s, have killed %d.\n",
2276                         quest[i].name, (int)quest[i].level,
2277                         (int)quest[i].max_num, name, (int)quest[i].cur_num);
2278 #endif
2279         }
2280
2281         if (rand_tmp_str[0]) fputs(rand_tmp_str, fff);
2282
2283         if (!total) fprintf(fff, _("  なし\n", "  Nothing.\n"));
2284 }
2285
2286
2287 static bool do_cmd_knowledge_quests_aux(player_type *player_ptr, FILE *fff, IDX q_idx)
2288 {
2289         char tmp_str[120];
2290         char playtime_str[16];
2291         quest_type* const q_ptr = &quest[q_idx];
2292
2293         floor_type *floor_ptr = player_ptr->current_floor_ptr;
2294         if (is_fixed_quest_idx(q_idx))
2295         {
2296                 IDX old_quest = floor_ptr->inside_quest;
2297                 floor_ptr->inside_quest = q_idx;
2298                 init_flags = INIT_NAME_ONLY;
2299                 process_dungeon_file(player_ptr, "q_info.txt", 0, 0, 0, 0);
2300                 floor_ptr->inside_quest = old_quest;
2301                 if (q_ptr->flags & QUEST_FLAG_SILENT) return FALSE;
2302         }
2303
2304         strnfmt(playtime_str, sizeof(playtime_str), "%02d:%02d:%02d",
2305                 q_ptr->comptime / (60 * 60), (q_ptr->comptime / 60) % 60, q_ptr->comptime % 60);
2306
2307         if (is_fixed_quest_idx(q_idx) || (q_ptr->r_idx == 0))
2308         {
2309                 sprintf(tmp_str,
2310                         _("  %-35s (危険度:%3d階相当) - レベル%2d - %s\n",
2311                                 "  %-35s (Danger  level: %3d) - level %2d - %s\n"),
2312                         q_ptr->name, (int)q_ptr->level, q_ptr->complev, playtime_str);
2313                 fputs(tmp_str, fff);
2314                 return TRUE;
2315         }
2316
2317         if (q_ptr->complev == 0)
2318         {
2319                 sprintf(tmp_str,
2320                         _("  %-35s (%3d階)            -   不戦勝 - %s\n",
2321                                 "  %-35s (Dungeon level: %3d) - Unearned - %s\n"),
2322                         r_name + r_info[q_ptr->r_idx].name,
2323                         (int)q_ptr->level, playtime_str);
2324                 fputs(tmp_str, fff);
2325                 return TRUE;
2326         }
2327
2328         sprintf(tmp_str,
2329                 _("  %-35s (%3d階)            - レベル%2d - %s\n",
2330                         "  %-35s (Dungeon level: %3d) - level %2d - %s\n"),
2331                 r_name + r_info[q_ptr->r_idx].name,
2332                 (int)q_ptr->level,
2333                 q_ptr->complev,
2334                 playtime_str);
2335         fputs(tmp_str, fff);
2336         return TRUE;
2337 }
2338
2339
2340 /*
2341  * Print all finished quests
2342  * @param creature_ptr プレーヤーへの参照ポインタ
2343  * @param fff セーブファイル (展開済?)
2344  * @param quest_num[] 受注したことのあるクエスト群
2345  * @return なし
2346  */
2347 void do_cmd_knowledge_quests_completed(player_type *creature_ptr, FILE *fff, QUEST_IDX quest_num[])
2348 {
2349         fprintf(fff, _("《達成したクエスト》\n", "< Completed Quest >\n"));
2350         QUEST_IDX total = 0;
2351         for (QUEST_IDX i = 1; i < max_q_idx; i++)
2352         {
2353                 QUEST_IDX q_idx = quest_num[i];
2354                 quest_type* const q_ptr = &quest[q_idx];
2355
2356                 if (q_ptr->status == QUEST_STATUS_FINISHED && do_cmd_knowledge_quests_aux(creature_ptr, fff, q_idx))
2357                 {
2358                         ++total;
2359                 }
2360         }
2361
2362         if (!total) fprintf(fff, _("  なし\n", "  Nothing.\n"));
2363 }
2364
2365
2366 /*
2367  * Print all failed quests
2368  * @param creature_ptr プレーヤーへの参照ポインタ
2369  * @param fff セーブファイル (展開済?)
2370  * @param quest_num[] 受注したことのあるクエスト群
2371  * @return なし
2372 */
2373 void do_cmd_knowledge_quests_failed(player_type *creature_ptr, FILE *fff, QUEST_IDX quest_num[])
2374 {
2375         fprintf(fff, _("《失敗したクエスト》\n", "< Failed Quest >\n"));
2376         QUEST_IDX total = 0;
2377         for (QUEST_IDX i = 1; i < max_q_idx; i++)
2378         {
2379                 QUEST_IDX q_idx = quest_num[i];
2380                 quest_type* const q_ptr = &quest[q_idx];
2381
2382                 if (((q_ptr->status == QUEST_STATUS_FAILED_DONE) || (q_ptr->status == QUEST_STATUS_FAILED)) &&
2383                         do_cmd_knowledge_quests_aux(creature_ptr, fff, q_idx))
2384                 {
2385                         ++total;
2386                 }
2387         }
2388
2389         if (!total) fprintf(fff, _("  なし\n", "  Nothing.\n"));
2390 }
2391
2392
2393 /*
2394  * Print all random quests
2395  */
2396 static void do_cmd_knowledge_quests_wiz_random(FILE *fff)
2397 {
2398         fprintf(fff, _("《残りのランダムクエスト》\n", "< Remaining Random Quest >\n"));
2399         GAME_TEXT tmp_str[120];
2400         QUEST_IDX total = 0;
2401         for (QUEST_IDX i = 1; i < max_q_idx; i++)
2402         {
2403                 if (quest[i].flags & QUEST_FLAG_SILENT) continue;
2404
2405                 if ((quest[i].type == QUEST_TYPE_RANDOM) && (quest[i].status == QUEST_STATUS_TAKEN))
2406                 {
2407                         total++;
2408                         sprintf(tmp_str, _("  %s (%d階, %s)\n", "  %s (%d, %s)\n"),
2409                                 quest[i].name, (int)quest[i].level, r_name + r_info[quest[i].r_idx].name);
2410                         fputs(tmp_str, fff);
2411                 }
2412         }
2413
2414         if (!total) fprintf(fff, _("  なし\n", "  Nothing.\n"));
2415 }
2416
2417 /*
2418  * Print quest status of all active quests
2419  * @param creature_ptr プレーヤーへの参照ポインタ
2420  * @return なし
2421  */
2422 static void do_cmd_knowledge_quests(player_type *creature_ptr)
2423 {
2424         FILE *fff = NULL;
2425         GAME_TEXT file_name[FILE_NAME_SIZE];
2426         if (!open_temporary_file(&fff, file_name)) return;
2427
2428         IDX *quest_num;
2429         C_MAKE(quest_num, max_q_idx, QUEST_IDX);
2430
2431         for (IDX i = 1; i < max_q_idx; i++)
2432                 quest_num[i] = i;
2433
2434         int dummy;
2435         ang_sort(quest_num, &dummy, max_q_idx, ang_sort_comp_quest_num, ang_sort_swap_quest_num);
2436
2437         do_cmd_knowledge_quests_current(creature_ptr, fff);
2438         fputc('\n', fff);
2439         do_cmd_knowledge_quests_completed(creature_ptr, fff, quest_num);
2440         fputc('\n', fff);
2441         do_cmd_knowledge_quests_failed(creature_ptr, fff, quest_num);
2442         if (current_world_ptr->wizard)
2443         {
2444                 fputc('\n', fff);
2445                 do_cmd_knowledge_quests_wiz_random(fff);
2446         }
2447
2448         my_fclose(fff);
2449         (void)show_file(creature_ptr, TRUE, file_name, _("クエスト達成状況", "Quest status"), 0, 0);
2450         fd_kill(file_name);
2451         C_KILL(quest_num, max_q_idx, QUEST_IDX);
2452 }
2453
2454
2455 /*
2456  * List my home
2457  * @param player_ptr プレーヤーへの参照ポインタ
2458  * @return なし
2459  */
2460 static void do_cmd_knowledge_home(player_type *player_ptr)
2461 {
2462         process_dungeon_file(player_ptr, "w_info.txt", 0, 0, current_world_ptr->max_wild_y, current_world_ptr->max_wild_x);
2463
2464         FILE *fff = NULL;
2465         GAME_TEXT file_name[FILE_NAME_SIZE];
2466         if (!open_temporary_file(&fff, file_name)) return;
2467
2468         store_type *store_ptr;
2469         store_ptr = &town_info[1].store[STORE_HOME];
2470
2471         if (store_ptr->stock_num)
2472         {
2473 #ifdef JP
2474                 TERM_LEN x = 1;
2475 #endif
2476                 fprintf(fff, _("  [ 我が家のアイテム ]\n", "  [Home Inventory]\n"));
2477                 concptr paren = ")";
2478                 GAME_TEXT o_name[MAX_NLEN];
2479                 for (int i = 0; i < store_ptr->stock_num; i++)
2480                 {
2481 #ifdef JP
2482                         if ((i % 12) == 0) fprintf(fff, "\n ( %d ページ )\n", x++);
2483                         object_desc(player_ptr, o_name, &store_ptr->stock[i], 0);
2484                         if (strlen(o_name) <= 80 - 3)
2485                         {
2486                                 fprintf(fff, "%c%s %s\n", I2A(i % 12), paren, o_name);
2487                         }
2488                         else
2489                         {
2490                                 int n;
2491                                 char *t;
2492                                 for (n = 0, t = o_name; n < 80 - 3; n++, t++)
2493                                         if (iskanji(*t)) { t++; n++; }
2494                                 if (n == 81 - 3) n = 79 - 3; /* 最後が漢字半分 */
2495
2496                                 fprintf(fff, "%c%s %.*s\n", I2A(i % 12), paren, n, o_name);
2497                                 fprintf(fff, "   %.77s\n", o_name + n);
2498                         }
2499 #else
2500                         object_desc(player_ptr, o_name, &store_ptr->stock[i], 0);
2501                         fprintf(fff, "%c%s %s\n", I2A(i % 12), paren, o_name);
2502 #endif
2503                 }
2504
2505                 fprintf(fff, "\n\n");
2506         }
2507
2508         my_fclose(fff);
2509         (void)show_file(player_ptr, TRUE, file_name, _("我が家のアイテム", "Home Inventory"), 0, 0);
2510         fd_kill(file_name);
2511 }
2512
2513
2514 /*
2515  * Check the status of "autopick"
2516  */
2517 static void do_cmd_knowledge_autopick(player_type *creature_ptr)
2518 {
2519         FILE *fff = NULL;
2520         GAME_TEXT file_name[FILE_NAME_SIZE];
2521         if (!open_temporary_file(&fff, file_name)) return;
2522
2523         if (!max_autopick)
2524         {
2525                 fprintf(fff, _("自動破壊/拾いには何も登録されていません。", "No preference for auto picker/destroyer."));
2526         }
2527         else
2528         {
2529                 fprintf(fff, _("   自動拾い/破壊には現在 %d行登録されています。\n\n",
2530                         "   There are %d registered lines for auto picker/destroyer.\n\n"), max_autopick);
2531         }
2532
2533         for (int k = 0; k < max_autopick; k++)
2534         {
2535                 concptr tmp;
2536                 byte act = autopick_list[k].action;
2537                 if (act & DONT_AUTOPICK)
2538                 {
2539                         tmp = _("放置", "Leave");
2540                 }
2541                 else if (act & DO_AUTODESTROY)
2542                 {
2543                         tmp = _("破壊", "Destroy");
2544                 }
2545                 else if (act & DO_AUTOPICK)
2546                 {
2547                         tmp = _("拾う", "Pickup");
2548                 }
2549                 else
2550                 {
2551                         tmp = _("確認", "Query");
2552                 }
2553
2554                 if (act & DO_DISPLAY)
2555                         fprintf(fff, "%11s", format("[%s]", tmp));
2556                 else
2557                         fprintf(fff, "%11s", format("(%s)", tmp));
2558
2559                 tmp = autopick_line_from_entry(&autopick_list[k]);
2560                 fprintf(fff, " %s", tmp);
2561                 string_free(tmp);
2562                 fprintf(fff, "\n");
2563         }
2564
2565         my_fclose(fff);
2566
2567         (void)show_file(creature_ptr, TRUE, file_name, _("自動拾い/破壊 設定リスト", "Auto-picker/Destroyer"), 0, 0);
2568         fd_kill(file_name);
2569 }
2570
2571
2572 /*
2573  * Interact with "knowledge"
2574  */
2575 void do_cmd_knowledge(player_type *creature_ptr)
2576 {
2577         int i, p = 0;
2578         bool need_redraw = FALSE;
2579         FILE_TYPE(FILE_TYPE_TEXT);
2580         screen_save();
2581         while (TRUE)
2582         {
2583                 Term_clear();
2584                 prt(format(_("%d/2 ページ", "page %d/2"), (p + 1)), 2, 65);
2585                 prt(_("現在の知識を確認する", "Display current knowledge"), 3, 0);
2586                 if (p == 0)
2587                 {
2588                         prt(_("(1) 既知の伝説のアイテム                 の一覧", "(1) Display known artifacts"), 6, 5);
2589                         prt(_("(2) 既知のアイテム                       の一覧", "(2) Display known objects"), 7, 5);
2590                         prt(_("(3) 既知の生きているユニーク・モンスター の一覧", "(3) Display remaining uniques"), 8, 5);
2591                         prt(_("(4) 既知のモンスター                     の一覧", "(4) Display known monster"), 9, 5);
2592                         prt(_("(5) 倒した敵の数                         の一覧", "(5) Display kill count"), 10, 5);
2593                         if (!vanilla_town) prt(_("(6) 賞金首                               の一覧", "(6) Display wanted monsters"), 11, 5);
2594                         prt(_("(7) 現在のペット                         の一覧", "(7) Display current pets"), 12, 5);
2595                         prt(_("(8) 我が家のアイテム                     の一覧", "(8) Display home inventory"), 13, 5);
2596                         prt(_("(9) *鑑定*済み装備の耐性                 の一覧", "(9) Display *identified* equip."), 14, 5);
2597                         prt(_("(0) 地形の表示文字/タイル                の一覧", "(0) Display terrain symbols."), 15, 5);
2598                 }
2599                 else
2600                 {
2601                         prt(_("(a) 自分に関する情報                     の一覧", "(a) Display about yourself"), 6, 5);
2602                         prt(_("(b) 突然変異                             の一覧", "(b) Display mutations"), 7, 5);
2603                         prt(_("(c) 武器の経験値                         の一覧", "(c) Display weapon proficiency"), 8, 5);
2604                         prt(_("(d) 魔法の経験値                         の一覧", "(d) Display spell proficiency"), 9, 5);
2605                         prt(_("(e) 技能の経験値                         の一覧", "(e) Display misc. proficiency"), 10, 5);
2606                         prt(_("(f) プレイヤーの徳                       の一覧", "(f) Display virtues"), 11, 5);
2607                         prt(_("(g) 入ったダンジョン                     の一覧", "(g) Display dungeons"), 12, 5);
2608                         prt(_("(h) 実行中のクエスト                     の一覧", "(h) Display current quests"), 13, 5);
2609                         prt(_("(i) 現在の自動拾い/破壊設定              の一覧", "(i) Display auto pick/destroy"), 14, 5);
2610                 }
2611
2612                 prt(_("-続く-", "-more-"), 17, 8);
2613                 prt(_("ESC) 抜ける", "ESC) Exit menu"), 21, 1);
2614                 prt(_("SPACE) 次ページ", "SPACE) Next page"), 21, 30);
2615                 prt(_("コマンド:", "Command: "), 20, 0);
2616                 i = inkey();
2617
2618                 if (i == ESCAPE) break;
2619                 switch (i)
2620                 {
2621                 case ' ': /* Page change */
2622                 case '-':
2623                         p = 1 - p;
2624                         break;
2625                 case '1': /* Artifacts */
2626                         do_cmd_knowledge_artifacts(creature_ptr);
2627                         break;
2628                 case '2': /* Objects */
2629                         do_cmd_knowledge_objects(creature_ptr, &need_redraw, FALSE, -1);
2630                         break;
2631                 case '3': /* Uniques */
2632                         do_cmd_knowledge_uniques(creature_ptr);
2633                         break;
2634                 case '4': /* Monsters */
2635                         do_cmd_knowledge_monsters(creature_ptr, &need_redraw, FALSE, -1);
2636                         break;
2637                 case '5': /* Kill count  */
2638                         do_cmd_knowledge_kill_count(creature_ptr);
2639                         break;
2640                 case '6': /* wanted */
2641                         if (!vanilla_town) do_cmd_knowledge_bounty(creature_ptr);
2642                         break;
2643                 case '7': /* Pets */
2644                         do_cmd_knowledge_pets(creature_ptr);
2645                         break;
2646                 case '8': /* Home */
2647                         do_cmd_knowledge_home(creature_ptr);
2648                         break;
2649                 case '9': /* Resist list */
2650                         do_cmd_knowledge_inventory(creature_ptr);
2651                         break;
2652                 case '0': /* Feature list */
2653                 {
2654                         IDX lighting_level = F_LIT_STANDARD;
2655                         do_cmd_knowledge_features(&need_redraw, FALSE, -1, &lighting_level);
2656                 }
2657                 break;
2658                 /* Next page */
2659                 case 'a': /* Max stat */
2660                         do_cmd_knowledge_stat(creature_ptr);
2661                         break;
2662                 case 'b': /* Mutations */
2663                         do_cmd_knowledge_mutations(creature_ptr);
2664                         break;
2665                 case 'c': /* weapon-exp */
2666                         do_cmd_knowledge_weapon_exp(creature_ptr);
2667                         break;
2668                 case 'd': /* spell-exp */
2669                         do_cmd_knowledge_spell_exp(creature_ptr);
2670                         break;
2671                 case 'e': /* skill-exp */
2672                         do_cmd_knowledge_skill_exp(creature_ptr);
2673                         break;
2674                 case 'f': /* Virtues */
2675                         do_cmd_knowledge_virtues(creature_ptr);
2676                         break;
2677                 case 'g': /* Dungeon */
2678                         do_cmd_knowledge_dungeon(creature_ptr);
2679                         break;
2680                 case 'h': /* Quests */
2681                         do_cmd_knowledge_quests(creature_ptr);
2682                         break;
2683                 case 'i': /* Autopick */
2684                         do_cmd_knowledge_autopick(creature_ptr);
2685                         break;
2686                 default: /* Unknown option */
2687                         bell();
2688                 }
2689
2690                 msg_erase();
2691         }
2692
2693         screen_load();
2694         if (need_redraw) do_cmd_redraw(creature_ptr);
2695 }
2696
2697
2698 /*
2699  * Check on the status of an active quest
2700  * @param creature_ptr プレーヤーへの参照ポインタ
2701  * @return なし
2702  */
2703 void do_cmd_checkquest(player_type *creature_ptr)
2704 {
2705         FILE_TYPE(FILE_TYPE_TEXT);
2706         screen_save();
2707         do_cmd_knowledge_quests(creature_ptr);
2708         screen_load();
2709 }
2710
2711
2712 /*
2713  * Display the time and date
2714  * @param creature_ptr プレーヤーへの参照ポインタ
2715  * @return なし
2716  */
2717 void do_cmd_time(player_type *creature_ptr)
2718 {
2719         int day, hour, min;
2720         extract_day_hour_min(creature_ptr, &day, &hour, &min);
2721
2722         char desc[1024];
2723         strcpy(desc, _("変な時刻だ。", "It is a strange time."));
2724
2725         char day_buf[10];
2726         if (day < MAX_DAYS) sprintf(day_buf, "%d", day);
2727         else strcpy(day_buf, "*****");
2728
2729         msg_format(_("%s日目, 時刻は%d:%02d %sです。", "This is day %s. The time is %d:%02d %s."),
2730                 day_buf, (hour % 12 == 0) ? 12 : (hour % 12), min, (hour < 12) ? "AM" : "PM");
2731
2732         char buf[1024];
2733         if (!randint0(10) || creature_ptr->image)
2734         {
2735                 path_build(buf, sizeof(buf), ANGBAND_DIR_FILE, _("timefun_j.txt", "timefun.txt"));
2736         }
2737         else
2738         {
2739                 path_build(buf, sizeof(buf), ANGBAND_DIR_FILE, _("timenorm_j.txt", "timenorm.txt"));
2740         }
2741
2742         FILE *fff;
2743         fff = my_fopen(buf, "rt");
2744
2745         if (!fff) return;
2746
2747         int full = hour * 100 + min;
2748         int start = 9999;
2749         int end = -9999;
2750         int num = 0;
2751         while (!my_fgets(fff, buf, sizeof(buf)))
2752         {
2753                 if (!buf[0] || (buf[0] == '#')) continue;
2754                 if (buf[1] != ':') continue;
2755
2756                 if (buf[0] == 'S')
2757                 {
2758                         start = atoi(buf + 2);
2759                         end = start + 59;
2760                         continue;
2761                 }
2762
2763                 if (buf[0] == 'E')
2764                 {
2765                         end = atoi(buf + 2);
2766                         continue;
2767                 }
2768
2769                 if ((start > full) || (full > end)) continue;
2770
2771                 if (buf[0] == 'D')
2772                 {
2773                         num++;
2774                         if (!randint0(num)) strcpy(desc, buf + 2);
2775
2776                         continue;
2777                 }
2778         }
2779
2780         msg_print(desc);
2781         my_fclose(fff);
2782 }