OSDN Git Service

[Refactor] #40236 Separated knowledge-quests.c/h from cmd-dump.c/h
[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 #include "knowledge/knowledge-experiences.h"
48 #include "knowledge/knowledge-quests.h"
49 #include "knowledge/knowledge-uniques.h"
50
51 #include "autopick.h"
52 #include "birth.h"
53 #include "dungeon.h"
54 #include "world.h"
55 #include "view/display-player.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 "monster-status.h"
65 #include "dungeon-file.h"
66 #include "object/object-kind.h"
67 #include "floor-town.h"
68 #include "cmd/feeling-table.h"
69 #include "cmd/monster-group-table.h"
70 #include "cmd/object-group-table.h"
71 #include "market/store-util.h"
72 #include "view-mainwindow.h" // 暫定。後で消す
73 #include "english.h"
74
75 #include "diary-subtitle-table.h"
76 #include "io/write-diary.h"
77 #include "chuukei.h"
78
79 /*!
80  * @brief prefファイルを選択して処理する /
81  * Ask for a "user pref line" and process it
82  * @brief prf出力内容を消去する /
83  * Remove old lines automatically generated before.
84  * @param orig_file 消去を行うファイル名
85  */
86 static void remove_auto_dump(concptr orig_file, concptr auto_dump_mark)
87 {
88         char buf[1024];
89         bool between_mark = FALSE;
90         bool changed = FALSE;
91         int line_num = 0;
92         long header_location = 0;
93         char header_mark_str[80];
94         char footer_mark_str[80];
95
96         sprintf(header_mark_str, auto_dump_header, auto_dump_mark);
97         sprintf(footer_mark_str, auto_dump_footer, auto_dump_mark);
98         size_t mark_len = strlen(footer_mark_str);
99
100         FILE *orig_fff;
101         orig_fff = my_fopen(orig_file, "r");
102         if (!orig_fff) return;
103
104         FILE *tmp_fff = NULL;
105         char tmp_file[FILE_NAME_SIZE];
106         if (!open_temporary_file(&tmp_fff, tmp_file)) return;
107
108         while (TRUE)
109         {
110                 if (my_fgets(orig_fff, buf, sizeof(buf)))
111                 {
112                         if (between_mark)
113                         {
114                                 fseek(orig_fff, header_location, SEEK_SET);
115                                 between_mark = FALSE;
116                                 continue;
117                         }
118                         else
119                         {
120                                 break;
121                         }
122                 }
123
124                 if (!between_mark)
125                 {
126                         if (!strcmp(buf, header_mark_str))
127                         {
128                                 header_location = ftell(orig_fff);
129                                 line_num = 0;
130                                 between_mark = TRUE;
131                                 changed = TRUE;
132                         }
133                         else
134                         {
135                                 fprintf(tmp_fff, "%s\n", buf);
136                         }
137
138                         continue;
139                 }
140
141                 if (!strncmp(buf, footer_mark_str, mark_len))
142                 {
143                         int tmp;
144                         if (!sscanf(buf + mark_len, " (%d)", &tmp)
145                                 || tmp != line_num)
146                         {
147                                 fseek(orig_fff, header_location, SEEK_SET);
148                         }
149
150                         between_mark = FALSE;
151                         continue;
152                 }
153
154                 line_num++;
155         }
156
157         my_fclose(orig_fff);
158         my_fclose(tmp_fff);
159
160         if (changed)
161         {
162                 tmp_fff = my_fopen(tmp_file, "r");
163                 orig_fff = my_fopen(orig_file, "w");
164                 while (!my_fgets(tmp_fff, buf, sizeof(buf)))
165                         fprintf(orig_fff, "%s\n", buf);
166
167                 my_fclose(orig_fff);
168                 my_fclose(tmp_fff);
169         }
170
171         fd_kill(tmp_file);
172 }
173
174
175 #ifdef JP
176 #else
177 /*!
178  * @brief Return suffix of ordinal number
179  * @param num number
180  * @return pointer of suffix string.
181  */
182 concptr get_ordinal_number_suffix(int num)
183 {
184         num = ABS(num) % 100;
185         switch (num % 10)
186         {
187         case 1:
188                 return (num == 11) ? "th" : "st";
189         case 2:
190                 return (num == 12) ? "th" : "nd";
191         case 3:
192                 return (num == 13) ? "th" : "rd";
193         default:
194                 return "th";
195         }
196 }
197 #endif
198
199 /*!
200  * @brief 画面を再描画するコマンドのメインルーチン
201  * Hack -- redraw the screen
202  * @param creature_ptr プレーヤーへの参照ポインタ
203  * @return なし
204  * @details
205  * Allow absolute file names?
206  */
207 void do_cmd_pref(player_type *creature_ptr)
208 {
209         char buf[80];
210         strcpy(buf, "");
211         if (!get_string(_("設定変更コマンド: ", "Pref: "), buf, 80)) return;
212
213         (void)interpret_pref_file(creature_ptr, buf);
214 }
215
216
217 /*!
218  * @brief 自動拾い設定ファイルをロードするコマンドのメインルーチン /
219  * @param creature_ptr プレーヤーへの参照ポインタ
220  * @return なし
221  */
222 void do_cmd_reload_autopick(player_type *creature_ptr)
223 {
224         if (!get_check(_("自動拾い設定ファイルをロードしますか? ", "Reload auto-pick preference file? ")))
225                 return;
226
227         autopick_load_pref(creature_ptr, TRUE);
228 }
229
230
231 /*
232  * Interact with "colors"
233  */
234 void do_cmd_colors(player_type *creature_ptr)
235 {
236         int i;
237         char tmp[160];
238         char buf[1024];
239         FILE *auto_dump_stream;
240         FILE_TYPE(FILE_TYPE_TEXT);
241         screen_save();
242         while (TRUE)
243         {
244                 Term_clear();
245                 prt(_("[ カラーの設定 ]", "Interact with Colors"), 2, 0);
246                 prt(_("(1) ユーザー設定ファイルのロード", "(1) Load a user pref file"), 4, 5);
247                 prt(_("(2) カラーの設定をファイルに書き出す", "(2) Dump colors"), 5, 5);
248                 prt(_("(3) カラーの設定を変更する", "(3) Modify colors"), 6, 5);
249                 prt(_("コマンド: ", "Command: "), 8, 0);
250                 i = inkey();
251                 if (i == ESCAPE) break;
252
253                 if (i == '1')
254                 {
255                         prt(_("コマンド: ユーザー設定ファイルをロードします", "Command: Load a user pref file"), 8, 0);
256                         prt(_("ファイル: ", "File: "), 10, 0);
257                         sprintf(tmp, "%s.prf", creature_ptr->base_name);
258                         if (!askfor(tmp, 70)) continue;
259
260                         (void)process_pref_file(creature_ptr, tmp);
261                         Term_xtra(TERM_XTRA_REACT, 0);
262                         Term_redraw();
263                 }
264                 else if (i == '2')
265                 {
266                         static concptr mark = "Colors";
267                         prt(_("コマンド: カラーの設定をファイルに書き出します", "Command: Dump colors"), 8, 0);
268                         prt(_("ファイル: ", "File: "), 10, 0);
269                         sprintf(tmp, "%s.prf", creature_ptr->base_name);
270                         if (!askfor(tmp, 70)) continue;
271
272                         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, tmp);
273                         if (!open_auto_dump(&auto_dump_stream, buf, mark)) continue;
274
275                         auto_dump_printf(auto_dump_stream, _("\n# カラーの設定\n\n", "\n# Color redefinitions\n\n"));
276                         for (i = 0; i < 256; i++)
277                         {
278                                 int kv = angband_color_table[i][0];
279                                 int rv = angband_color_table[i][1];
280                                 int gv = angband_color_table[i][2];
281                                 int bv = angband_color_table[i][3];
282
283                                 concptr name = _("未知", "unknown");
284                                 if (!kv && !rv && !gv && !bv) continue;
285
286                                 if (i < 16) name = color_names[i];
287
288                                 auto_dump_printf(auto_dump_stream, _("# カラー '%s'\n", "# Color '%s'\n"), name);
289                                 auto_dump_printf(auto_dump_stream, "V:%d:0x%02X:0x%02X:0x%02X:0x%02X\n\n",
290                                         i, kv, rv, gv, bv);
291                         }
292
293                         close_auto_dump(&auto_dump_stream, mark);
294                         msg_print(_("カラーの設定をファイルに書き出しました。", "Dumped color redefinitions."));
295                 }
296                 else if (i == '3')
297                 {
298                         static byte a = 0;
299                         prt(_("コマンド: カラーの設定を変更します", "Command: Modify colors"), 8, 0);
300                         while (TRUE)
301                         {
302                                 concptr name;
303                                 clear_from(10);
304                                 for (byte j = 0; j < 16; j++)
305                                 {
306                                         Term_putstr(j * 4, 20, -1, a, "###");
307                                         Term_putstr(j * 4, 22, -1, j, format("%3d", j));
308                                 }
309
310                                 name = ((a < 16) ? color_names[a] : _("未定義", "undefined"));
311                                 Term_putstr(5, 10, -1, TERM_WHITE,
312                                         format(_("カラー = %d, 名前 = %s", "Color = %d, Name = %s"), a, name));
313                                 Term_putstr(5, 12, -1, TERM_WHITE,
314                                         format("K = 0x%02x / R,G,B = 0x%02x,0x%02x,0x%02x",
315                                                 angband_color_table[a][0],
316                                                 angband_color_table[a][1],
317                                                 angband_color_table[a][2],
318                                                 angband_color_table[a][3]));
319                                 Term_putstr(0, 14, -1, TERM_WHITE,
320                                         _("コマンド (n/N/k/K/r/R/g/G/b/B): ", "Command (n/N/k/K/r/R/g/G/b/B): "));
321                                 i = inkey();
322                                 if (i == ESCAPE) break;
323
324                                 if (i == 'n') a = (byte)(a + 1);
325                                 if (i == 'N') a = (byte)(a - 1);
326                                 if (i == 'k') angband_color_table[a][0] = (byte)(angband_color_table[a][0] + 1);
327                                 if (i == 'K') angband_color_table[a][0] = (byte)(angband_color_table[a][0] - 1);
328                                 if (i == 'r') angband_color_table[a][1] = (byte)(angband_color_table[a][1] + 1);
329                                 if (i == 'R') angband_color_table[a][1] = (byte)(angband_color_table[a][1] - 1);
330                                 if (i == 'g') angband_color_table[a][2] = (byte)(angband_color_table[a][2] + 1);
331                                 if (i == 'G') angband_color_table[a][2] = (byte)(angband_color_table[a][2] - 1);
332                                 if (i == 'b') angband_color_table[a][3] = (byte)(angband_color_table[a][3] + 1);
333                                 if (i == 'B') angband_color_table[a][3] = (byte)(angband_color_table[a][3] - 1);
334
335                                 Term_xtra(TERM_XTRA_REACT, 0);
336                                 Term_redraw();
337                         }
338                 }
339                 else
340                 {
341                         bell();
342                 }
343
344                 msg_erase();
345         }
346
347         screen_load();
348 }
349
350
351 /*
352  * Note something in the message recall
353  */
354 void do_cmd_note(void)
355 {
356         char buf[80];
357         strcpy(buf, "");
358         if (!get_string(_("メモ: ", "Note: "), buf, 60)) return;
359         if (!buf[0] || (buf[0] == ' ')) return;
360
361         msg_format(_("メモ: %s", "Note: %s"), buf);
362 }
363
364
365 /*
366  * Mention the current version
367  */
368 void do_cmd_version(void)
369 {
370 #if FAKE_VER_EXTRA > 0
371         msg_format(_("変愚蛮怒(Hengband) %d.%d.%d.%d", "You are playing Hengband %d.%d.%d.%d."),
372                 FAKE_VER_MAJOR - 10, FAKE_VER_MINOR, FAKE_VER_PATCH, FAKE_VER_EXTRA);
373 #else
374         msg_format(_("変愚蛮怒(Hengband) %d.%d.%d", "You are playing Hengband %d.%d.%d."),
375                 FAKE_VER_MAJOR - 10, FAKE_VER_MINOR, FAKE_VER_PATCH);
376 #endif
377 }
378
379
380 /*
381  * Note that "feeling" is set to zero unless some time has passed.
382  * Note that this is done when the level is GENERATED, not entered.
383  */
384 void do_cmd_feeling(player_type *creature_ptr)
385 {
386         if (creature_ptr->wild_mode) return;
387
388         if (creature_ptr->current_floor_ptr->inside_quest && !random_quest_number(creature_ptr, creature_ptr->current_floor_ptr->dun_level))
389         {
390                 msg_print(_("典型的なクエストのダンジョンのようだ。", "Looks like a typical quest level."));
391                 return;
392         }
393
394         if (creature_ptr->town_num && !creature_ptr->current_floor_ptr->dun_level)
395         {
396                 if (!strcmp(town_info[creature_ptr->town_num].name, _("荒野", "wilderness")))
397                 {
398                         msg_print(_("何かありそうな荒野のようだ。", "Looks like a strange wilderness."));
399                         return;
400                 }
401
402                 msg_print(_("典型的な町のようだ。", "Looks like a typical town."));
403                 return;
404         }
405
406         if (!creature_ptr->current_floor_ptr->dun_level)
407         {
408                 msg_print(_("典型的な荒野のようだ。", "Looks like a typical wilderness."));
409                 return;
410         }
411
412         if (creature_ptr->muta3 & MUT3_GOOD_LUCK)
413                 msg_print(do_cmd_feeling_text_lucky[creature_ptr->feeling]);
414         else if (IS_ECHIZEN(creature_ptr))
415                 msg_print(do_cmd_feeling_text_combat[creature_ptr->feeling]);
416         else
417                 msg_print(do_cmd_feeling_text[creature_ptr->feeling]);
418 }
419
420
421 /*
422  * todo 引数と戻り値について追記求む
423  * Build a list of monster indexes in the given group.
424  *
425  * mode & 0x01 : check for non-empty group
426  * mode & 0x02 : visual operation only
427
428  * @param creature_ptr プレーヤーへの参照ポインタ
429  * @param grp_cur ???
430  * @param mon_idx[] ???
431  * @param mode ???
432  * @return The number of monsters in the group
433  */
434 static IDX collect_monsters(player_type *creature_ptr, IDX grp_cur, IDX mon_idx[], BIT_FLAGS8 mode)
435 {
436         concptr group_char = monster_group_char[grp_cur];
437         bool grp_unique = (monster_group_char[grp_cur] == (char *)-1L);
438         bool grp_riding = (monster_group_char[grp_cur] == (char *)-2L);
439         bool grp_wanted = (monster_group_char[grp_cur] == (char *)-3L);
440         bool grp_amberite = (monster_group_char[grp_cur] == (char *)-4L);
441
442         IDX mon_cnt = 0;
443         for (IDX i = 0; i < max_r_idx; i++)
444         {
445                 monster_race *r_ptr = &r_info[i];
446                 if (!r_ptr->name) continue;
447                 if (!(mode & 0x02) && !cheat_know && !r_ptr->r_sights) continue;
448
449                 if (grp_unique)
450                 {
451                         if (!(r_ptr->flags1 & RF1_UNIQUE)) continue;
452                 }
453                 else if (grp_riding)
454                 {
455                         if (!(r_ptr->flags7 & RF7_RIDING)) continue;
456                 }
457                 else if (grp_wanted)
458                 {
459                         bool wanted = FALSE;
460                         for (int j = 0; j < MAX_BOUNTY; j++)
461                         {
462                                 if (current_world_ptr->bounty_r_idx[j] == i || current_world_ptr->bounty_r_idx[j] - 10000 == i ||
463                                         (creature_ptr->today_mon && creature_ptr->today_mon == i))
464                                 {
465                                         wanted = TRUE;
466                                         break;
467                                 }
468                         }
469
470                         if (!wanted) continue;
471                 }
472                 else if (grp_amberite)
473                 {
474                         if (!(r_ptr->flags3 & RF3_AMBERITE)) continue;
475                 }
476                 else
477                 {
478                         if (!my_strchr(group_char, r_ptr->d_char)) continue;
479                 }
480
481                 mon_idx[mon_cnt++] = i;
482                 if (mode & 0x01) break;
483         }
484
485         mon_idx[mon_cnt] = -1;
486         int dummy_why;
487         ang_sort(mon_idx, &dummy_why, mon_cnt, ang_sort_comp_monster_level, ang_sort_swap_hook);
488         return mon_cnt;
489 }
490
491
492 /*
493  * Build a list of object indexes in the given group. Return the number
494  * of objects in the group.
495  *
496  * mode & 0x01 : check for non-empty group
497  * mode & 0x02 : visual operation only
498  */
499 static KIND_OBJECT_IDX collect_objects(int grp_cur, KIND_OBJECT_IDX object_idx[], BIT_FLAGS8 mode)
500 {
501         KIND_OBJECT_IDX object_cnt = 0;
502         byte group_tval = object_group_tval[grp_cur];
503         for (KIND_OBJECT_IDX i = 0; i < max_k_idx; i++)
504         {
505                 object_kind *k_ptr = &k_info[i];
506                 if (!k_ptr->name) continue;
507
508                 if (!(mode & 0x02))
509                 {
510                         if (!current_world_ptr->wizard)
511                         {
512                                 if (!k_ptr->flavor) continue;
513                                 if (!k_ptr->aware) continue;
514                         }
515
516                         int k = 0;
517                         for (int j = 0; j < 4; j++)
518                                 k += k_ptr->chance[j];
519                         if (!k) continue;
520                 }
521
522                 if (TV_LIFE_BOOK == group_tval)
523                 {
524                         if (TV_LIFE_BOOK <= k_ptr->tval && k_ptr->tval <= TV_HEX_BOOK)
525                         {
526                                 object_idx[object_cnt++] = i;
527                         }
528                         else
529                                 continue;
530                 }
531                 else if (k_ptr->tval == group_tval)
532                 {
533                         object_idx[object_cnt++] = i;
534                 }
535                 else
536                         continue;
537
538                 if (mode & 0x01) break;
539         }
540
541         object_idx[object_cnt] = -1;
542         return object_cnt;
543 }
544
545
546 /*
547  * Build a list of feature indexes in the given group. Return the number
548  * of features in the group.
549  *
550  * mode & 0x01 : check for non-empty group
551  */
552 static FEAT_IDX collect_features(FEAT_IDX *feat_idx, BIT_FLAGS8 mode)
553 {
554         FEAT_IDX feat_cnt = 0;
555         for (FEAT_IDX i = 0; i < max_f_idx; i++)
556         {
557                 feature_type *f_ptr = &f_info[i];
558                 if (!f_ptr->name) continue;
559                 if (f_ptr->mimic != i) continue;
560
561                 feat_idx[feat_cnt++] = i;
562                 if (mode & 0x01) break;
563         }
564
565         feat_idx[feat_cnt] = -1;
566         return feat_cnt;
567 }
568
569
570 /*!
571  * @brief 現在のペットを表示するコマンドのメインルーチン /
572  * Display current pets
573  * @param creature_ptr プレーヤーへの参照ポインタ
574  * @return なし
575  */
576 static void do_cmd_knowledge_pets(player_type *creature_ptr)
577 {
578         FILE *fff = NULL;
579         GAME_TEXT file_name[FILE_NAME_SIZE];
580         if (!open_temporary_file(&fff, file_name)) return;
581
582         monster_type *m_ptr;
583         GAME_TEXT pet_name[MAX_NLEN];
584         int t_friends = 0;
585         for (int i = creature_ptr->current_floor_ptr->m_max - 1; i >= 1; i--)
586         {
587                 m_ptr = &creature_ptr->current_floor_ptr->m_list[i];
588                 if (!monster_is_valid(m_ptr)) continue;
589                 if (!is_pet(m_ptr)) continue;
590
591                 t_friends++;
592                 monster_desc(creature_ptr, pet_name, m_ptr, MD_ASSUME_VISIBLE | MD_INDEF_VISIBLE);
593                 fprintf(fff, "%s (%s)\n", pet_name, look_mon_desc(m_ptr, 0x00));
594         }
595
596         int show_upkeep = calculate_upkeep(creature_ptr);
597
598         fprintf(fff, "----------------------------------------------\n");
599 #ifdef JP
600         fprintf(fff, "    合計: %d 体のペット\n", t_friends);
601 #else
602         fprintf(fff, "   Total: %d pet%s.\n", t_friends, (t_friends == 1 ? "" : "s"));
603 #endif
604         fprintf(fff, _(" 維持コスト: %d%% MP\n", "   Upkeep: %d%% mana.\n"), show_upkeep);
605
606         my_fclose(fff);
607         (void)show_file(creature_ptr, TRUE, file_name, _("現在のペット", "Current Pets"), 0, 0);
608         fd_kill(file_name);
609 }
610
611
612 /*!
613  * @brief 現在のペットを表示するコマンドのメインルーチン /
614  * @param creature_ptr プレーヤーへの参照ポインタ
615  * Total kill count
616  * @return なし
617  * @note the player ghosts are ignored.
618  */
619 static void do_cmd_knowledge_kill_count(player_type *creature_ptr)
620 {
621         FILE *fff = NULL;
622         GAME_TEXT file_name[FILE_NAME_SIZE];
623         if (!open_temporary_file(&fff, file_name)) return;
624
625         MONRACE_IDX *who;
626         C_MAKE(who, max_r_idx, MONRACE_IDX);
627         s32b total = 0;
628         for (int kk = 1; kk < max_r_idx; kk++)
629         {
630                 monster_race *r_ptr = &r_info[kk];
631
632                 if (r_ptr->flags1 & (RF1_UNIQUE))
633                 {
634                         bool dead = (r_ptr->max_num == 0);
635
636                         if (dead)
637                         {
638                                 total++;
639                         }
640                 }
641                 else
642                 {
643                         MONSTER_NUMBER this_monster = r_ptr->r_pkills;
644
645                         if (this_monster > 0)
646                         {
647                                 total += this_monster;
648                         }
649                 }
650         }
651
652         if (total < 1)
653                 fprintf(fff, _("あなたはまだ敵を倒していない。\n\n", "You have defeated no enemies yet.\n\n"));
654         else
655 #ifdef JP
656                 fprintf(fff, "あなたは%ld体の敵を倒している。\n\n", (long int)total);
657 #else
658                 fprintf(fff, "You have defeated %ld %s.\n\n", (long int)total, (total == 1) ? "enemy" : "enemies");
659 #endif
660
661         total = 0;
662         int n = 0;
663         for (MONRACE_IDX i = 1; i < max_r_idx; i++)
664         {
665                 monster_race *r_ptr = &r_info[i];
666                 if (r_ptr->name) who[n++] = i;
667         }
668
669         u16b why = 2;
670         ang_sort(who, &why, n, ang_sort_comp_hook, ang_sort_swap_hook);
671         for (int k = 0; k < n; k++)
672         {
673                 monster_race *r_ptr = &r_info[who[k]];
674                 if (r_ptr->flags1 & (RF1_UNIQUE))
675                 {
676                         bool dead = (r_ptr->max_num == 0);
677                         if (dead)
678                         {
679                                 fprintf(fff, "     %s\n", (r_name + r_ptr->name));
680                                 total++;
681                         }
682
683                         continue;
684                 }
685
686                 MONSTER_NUMBER this_monster = r_ptr->r_pkills;
687                 if (this_monster <= 0) continue;
688
689 #ifdef JP
690                 if (my_strchr("pt", r_ptr->d_char))
691                         fprintf(fff, "     %3d 人の %s\n", (int)this_monster, r_name + r_ptr->name);
692                 else
693                         fprintf(fff, "     %3d 体の %s\n", (int)this_monster, r_name + r_ptr->name);
694 #else
695                 if (this_monster < 2)
696                 {
697                         if (my_strstr(r_name + r_ptr->name, "coins"))
698                         {
699                                 fprintf(fff, "     1 pile of %s\n", (r_name + r_ptr->name));
700                         }
701                         else
702                         {
703                                 fprintf(fff, "     1 %s\n", (r_name + r_ptr->name));
704                         }
705                 }
706                 else
707                 {
708                         char ToPlural[80];
709                         strcpy(ToPlural, (r_name + r_ptr->name));
710                         plural_aux(ToPlural);
711                         fprintf(fff, "     %d %s\n", this_monster, ToPlural);
712                 }
713 #endif
714                 total += this_monster;
715         }
716
717         fprintf(fff, "----------------------------------------------\n");
718 #ifdef JP
719         fprintf(fff, "    合計: %lu 体を倒した。\n", (unsigned long int)total);
720 #else
721         fprintf(fff, "   Total: %lu creature%s killed.\n", (unsigned long int)total, (total == 1 ? "" : "s"));
722 #endif
723
724         C_KILL(who, max_r_idx, s16b);
725         my_fclose(fff);
726         (void)show_file(creature_ptr, TRUE, file_name, _("倒した敵の数", "Kill Count"), 0, 0);
727         fd_kill(file_name);
728 }
729
730
731 /*!
732  * @brief モンスター情報リスト中のグループを表示する /
733  * Display the object groups.
734  * @param col 開始行
735  * @param row 開始列
736  * @param wid 表示文字数幅
737  * @param per_page リストの表示行
738  * @param grp_idx グループのID配列
739  * @param group_text グループ名の文字列配列
740  * @param grp_cur 現在の選択ID
741  * @param grp_top 現在の選択リスト最上部ID
742  * @return なし
743  */
744 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)
745 {
746         for (int i = 0; i < per_page && (grp_idx[i] >= 0); i++)
747         {
748                 int grp = grp_idx[grp_top + i];
749                 TERM_COLOR attr = (grp_top + i == grp_cur) ? TERM_L_BLUE : TERM_WHITE;
750                 Term_erase(col, row + i, wid);
751                 c_put_str(attr, group_text[grp], row + i, col);
752         }
753 }
754
755
756 /*
757  * Move the cursor in a browser window
758  */
759 static void browser_cursor(char ch, int *column, IDX *grp_cur, int grp_cnt, IDX *list_cur, int list_cnt)
760 {
761         int d;
762         int col = *column;
763         IDX grp = *grp_cur;
764         IDX list = *list_cur;
765         if (ch == ' ')
766                 d = 3;
767         else if (ch == '-')
768                 d = 9;
769         else
770                 d = get_keymap_dir(ch);
771
772         if (!d) return;
773
774         if ((ddx[d] > 0) && ddy[d])
775         {
776                 int browser_rows;
777                 int wid, hgt;
778                 Term_get_size(&wid, &hgt);
779                 browser_rows = hgt - 8;
780                 if (!col)
781                 {
782                         int old_grp = grp;
783                         grp += ddy[d] * (browser_rows - 1);
784                         if (grp >= grp_cnt)     grp = grp_cnt - 1;
785                         if (grp < 0) grp = 0;
786                         if (grp != old_grp)     list = 0;
787                 }
788                 else
789                 {
790                         list += ddy[d] * browser_rows;
791                         if (list >= list_cnt) list = list_cnt - 1;
792                         if (list < 0) list = 0;
793                 }
794
795                 (*grp_cur) = grp;
796                 (*list_cur) = list;
797                 return;
798         }
799
800         if (ddx[d])
801         {
802                 col += ddx[d];
803                 if (col < 0) col = 0;
804                 if (col > 1) col = 1;
805
806                 (*column) = col;
807                 return;
808         }
809
810         if (!col)
811         {
812                 int old_grp = grp;
813                 grp += (IDX)ddy[d];
814                 if (grp >= grp_cnt)     grp = grp_cnt - 1;
815                 if (grp < 0) grp = 0;
816                 if (grp != old_grp)     list = 0;
817         }
818         else
819         {
820                 list += (IDX)ddy[d];
821                 if (list >= list_cnt) list = list_cnt - 1;
822                 if (list < 0) list = 0;
823         }
824
825         (*grp_cur) = grp;
826         (*list_cur) = list;
827 }
828
829
830 /*
831  * Display visuals.
832  */
833 static void display_visual_list(int col, int row, int height, int width, TERM_COLOR attr_top, byte char_left)
834 {
835         for (int i = 0; i < height; i++)
836         {
837                 Term_erase(col, row + i, width);
838         }
839
840         if (use_bigtile) width /= 2;
841
842         for (int i = 0; i < height; i++)
843         {
844                 for (int j = 0; j < width; j++)
845                 {
846                         TERM_LEN x = col + j;
847                         TERM_LEN y = row + i;
848                         if (use_bigtile) x += j;
849
850                         int ia = attr_top + i;
851                         int ic = char_left + j;
852                         if (ia > 0x7f || ic > 0xff || ic < ' ' ||
853                                 (!use_graphics && ic > 0x7f))
854                                 continue;
855
856                         TERM_COLOR a = (TERM_COLOR)ia;
857                         SYMBOL_CODE c = (SYMBOL_CODE)ic;
858                         if (c & 0x80) a |= 0x80;
859
860                         Term_queue_bigchar(x, y, a, c, 0, 0);
861                 }
862         }
863 }
864
865
866 /*
867  * Place the cursor at the collect position for visual mode
868  */
869 static void place_visual_list_cursor(TERM_LEN col, TERM_LEN row, TERM_COLOR a, byte c, TERM_COLOR attr_top, byte char_left)
870 {
871         int i = (a & 0x7f) - attr_top;
872         int j = c - char_left;
873
874         TERM_LEN x = col + j;
875         TERM_LEN y = row + i;
876         if (use_bigtile) x += j;
877
878         Term_gotoxy(x, y);
879 }
880
881
882 /*
883  * Display the monsters in a group.
884  */
885 static void display_monster_list(int col, int row, int per_page, s16b mon_idx[], int mon_cur, int mon_top, bool visual_only)
886 {
887         int i;
888         for (i = 0; i < per_page && (mon_idx[mon_top + i] >= 0); i++)
889         {
890                 TERM_COLOR attr;
891                 MONRACE_IDX r_idx = mon_idx[mon_top + i];
892                 monster_race *r_ptr = &r_info[r_idx];
893                 attr = ((i + mon_top == mon_cur) ? TERM_L_BLUE : TERM_WHITE);
894                 c_prt(attr, (r_name + r_ptr->name), row + i, col);
895                 if (per_page == 1)
896                 {
897                         c_prt(attr, format("%02x/%02x", r_ptr->x_attr, r_ptr->x_char), row + i, (current_world_ptr->wizard || visual_only) ? 56 : 61);
898                 }
899
900                 if (current_world_ptr->wizard || visual_only)
901                 {
902                         c_prt(attr, format("%d", r_idx), row + i, 62);
903                 }
904
905                 Term_erase(69, row + i, 255);
906                 Term_queue_bigchar(use_bigtile ? 69 : 70, row + i, r_ptr->x_attr, r_ptr->x_char, 0, 0);
907                 if (!visual_only)
908                 {
909                         if (!(r_ptr->flags1 & RF1_UNIQUE))
910                                 put_str(format("%5d", r_ptr->r_pkills), row + i, 73);
911                         else
912                                 c_put_str((r_ptr->max_num == 0 ? TERM_L_DARK : TERM_WHITE),
913                                 (r_ptr->max_num == 0 ? _("死亡", " dead") : _("生存", "alive")), row + i, 74);
914                 }
915         }
916
917         for (; i < per_page; i++)
918         {
919                 Term_erase(col, row + i, 255);
920         }
921 }
922
923
924 /*
925  * todo 引数の詳細について加筆求む
926  * Display known monsters.
927  * @param creature_ptr プレーヤーへの参照ポインタ
928  * @param need_redraw 画面の再描画が必要な時TRUE
929  * @param visual_only ???
930  * @param direct_r_idx モンスターID
931  * @return なし
932  */
933 void do_cmd_knowledge_monsters(player_type *creature_ptr, bool *need_redraw, bool visual_only, IDX direct_r_idx)
934 {
935         TERM_LEN wid, hgt;
936         Term_get_size(&wid, &hgt);
937         IDX *mon_idx;
938         C_MAKE(mon_idx, max_r_idx, MONRACE_IDX);
939
940         int max = 0;
941         IDX grp_cnt = 0;
942         IDX grp_idx[100];
943         IDX mon_cnt;
944         bool visual_list = FALSE;
945         TERM_COLOR attr_top = 0;
946         byte char_left = 0;
947         BIT_FLAGS8 mode;
948         int browser_rows = hgt - 8;
949         if (direct_r_idx < 0)
950         {
951                 mode = visual_only ? 0x03 : 0x01;
952                 int len;
953                 for (IDX i = 0; monster_group_text[i] != NULL; i++)
954                 {
955                         len = strlen(monster_group_text[i]);
956                         if (len > max) max = len;
957
958                         if ((monster_group_char[i] == ((char *)-1L)) || collect_monsters(creature_ptr, i, mon_idx, mode))
959                         {
960                                 grp_idx[grp_cnt++] = i;
961                         }
962                 }
963
964                 mon_cnt = 0;
965         }
966         else
967         {
968                 mon_idx[0] = direct_r_idx;
969                 mon_cnt = 1;
970                 mon_idx[1] = -1;
971
972                 (void)visual_mode_command('v', &visual_list, browser_rows - 1, wid - (max + 3),
973                         &attr_top, &char_left, &r_info[direct_r_idx].x_attr, &r_info[direct_r_idx].x_char, need_redraw);
974         }
975
976         grp_idx[grp_cnt] = -1;
977         mode = visual_only ? 0x02 : 0x00;
978         IDX old_grp_cur = -1;
979         IDX grp_cur = 0;
980         IDX grp_top = 0;
981         IDX mon_cur = 0;
982         IDX mon_top = 0;
983         int column = 0;
984         bool flag = FALSE;
985         bool redraw = TRUE;
986         while (!flag)
987         {
988                 if (redraw)
989                 {
990                         clear_from(0);
991                         prt(format(_("%s - モンスター", "%s - monsters"), !visual_only ? _("知識", "Knowledge") : _("表示", "Visuals")), 2, 0);
992                         if (direct_r_idx < 0) prt(_("グループ", "Group"), 4, 0);
993                         prt(_("名前", "Name"), 4, max + 3);
994                         if (current_world_ptr->wizard || visual_only) prt("Idx", 4, 62);
995                         prt(_("文字", "Sym"), 4, 67);
996                         if (!visual_only) prt(_("殺害数", "Kills"), 4, 72);
997
998                         for (IDX i = 0; i < 78; i++)
999                         {
1000                                 Term_putch(i, 5, TERM_WHITE, '=');
1001                         }
1002
1003                         if (direct_r_idx < 0)
1004                         {
1005                                 for (IDX i = 0; i < browser_rows; i++)
1006                                 {
1007                                         Term_putch(max + 1, 6 + i, TERM_WHITE, '|');
1008                                 }
1009                         }
1010
1011                         redraw = FALSE;
1012                 }
1013
1014                 if (direct_r_idx < 0)
1015                 {
1016                         if (grp_cur < grp_top) grp_top = grp_cur;
1017                         if (grp_cur >= grp_top + browser_rows) grp_top = grp_cur - browser_rows + 1;
1018
1019                         display_group_list(0, 6, max, browser_rows, grp_idx, monster_group_text, grp_cur, grp_top);
1020                         if (old_grp_cur != grp_cur)
1021                         {
1022                                 old_grp_cur = grp_cur;
1023                                 mon_cnt = collect_monsters(creature_ptr, grp_idx[grp_cur], mon_idx, mode);
1024                         }
1025
1026                         while (mon_cur < mon_top)
1027                                 mon_top = MAX(0, mon_top - browser_rows / 2);
1028                         while (mon_cur >= mon_top + browser_rows)
1029                                 mon_top = MIN(mon_cnt - browser_rows, mon_top + browser_rows / 2);
1030                 }
1031
1032                 if (!visual_list)
1033                 {
1034                         display_monster_list(max + 3, 6, browser_rows, mon_idx, mon_cur, mon_top, visual_only);
1035                 }
1036                 else
1037                 {
1038                         mon_top = mon_cur;
1039                         display_monster_list(max + 3, 6, 1, mon_idx, mon_cur, mon_top, visual_only);
1040                         display_visual_list(max + 3, 7, browser_rows - 1, wid - (max + 3), attr_top, char_left);
1041                 }
1042
1043                 prt(format(_("<方向>%s%s%s, ESC", "<dir>%s%s%s, ESC"),
1044                         (!visual_list && !visual_only) ? _(", 'r'で思い出を見る", ", 'r' to recall") : "",
1045                         visual_list ? _(", ENTERで決定", ", ENTER to accept") : _(", 'v'でシンボル変更", ", 'v' for visuals"),
1046                         (attr_idx || char_idx) ? _(", 'c', 'p'でペースト", ", 'c', 'p' to paste") : _(", 'c'でコピー", ", 'c' to copy")),
1047                         hgt - 1, 0);
1048
1049                 monster_race *r_ptr;
1050                 r_ptr = &r_info[mon_idx[mon_cur]];
1051
1052                 if (!visual_only)
1053                 {
1054                         if (mon_cnt) monster_race_track(creature_ptr, mon_idx[mon_cur]);
1055                         handle_stuff(creature_ptr);
1056                 }
1057
1058                 if (visual_list)
1059                 {
1060                         place_visual_list_cursor(max + 3, 7, r_ptr->x_attr, r_ptr->x_char, attr_top, char_left);
1061                 }
1062                 else if (!column)
1063                 {
1064                         Term_gotoxy(0, 6 + (grp_cur - grp_top));
1065                 }
1066                 else
1067                 {
1068                         Term_gotoxy(max + 3, 6 + (mon_cur - mon_top));
1069                 }
1070
1071                 char ch = inkey();
1072                 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))
1073                 {
1074                         if (direct_r_idx >= 0)
1075                         {
1076                                 switch (ch)
1077                                 {
1078                                 case '\n':
1079                                 case '\r':
1080                                 case ESCAPE:
1081                                         flag = TRUE;
1082                                         break;
1083                                 }
1084                         }
1085
1086                         continue;
1087                 }
1088
1089                 switch (ch)
1090                 {
1091                 case ESCAPE:
1092                 {
1093                         flag = TRUE;
1094                         break;
1095                 }
1096
1097                 case 'R':
1098                 case 'r':
1099                 {
1100                         if (!visual_list && !visual_only && (mon_idx[mon_cur] > 0))
1101                         {
1102                                 screen_roff(creature_ptr, mon_idx[mon_cur], 0);
1103
1104                                 (void)inkey();
1105
1106                                 redraw = TRUE;
1107                         }
1108
1109                         break;
1110                 }
1111
1112                 default:
1113                 {
1114                         browser_cursor(ch, &column, &grp_cur, grp_cnt, &mon_cur, mon_cnt);
1115
1116                         break;
1117                 }
1118                 }
1119         }
1120
1121         C_KILL(mon_idx, max_r_idx, MONRACE_IDX);
1122 }
1123
1124
1125 /*
1126  * Display the objects in a group.
1127  */
1128 static void display_object_list(int col, int row, int per_page, IDX object_idx[],
1129         int object_cur, int object_top, bool visual_only)
1130 {
1131         int i;
1132         for (i = 0; i < per_page && (object_idx[object_top + i] >= 0); i++)
1133         {
1134                 GAME_TEXT o_name[MAX_NLEN];
1135                 TERM_COLOR a;
1136                 SYMBOL_CODE c;
1137                 object_kind *flavor_k_ptr;
1138                 KIND_OBJECT_IDX k_idx = object_idx[object_top + i];
1139                 object_kind *k_ptr = &k_info[k_idx];
1140                 TERM_COLOR attr = ((k_ptr->aware || visual_only) ? TERM_WHITE : TERM_SLATE);
1141                 byte cursor = ((k_ptr->aware || visual_only) ? TERM_L_BLUE : TERM_BLUE);
1142                 if (!visual_only && k_ptr->flavor)
1143                 {
1144                         flavor_k_ptr = &k_info[k_ptr->flavor];
1145                 }
1146                 else
1147                 {
1148                         flavor_k_ptr = k_ptr;
1149                 }
1150
1151                 attr = ((i + object_top == object_cur) ? cursor : attr);
1152                 if (!k_ptr->flavor || (!visual_only && k_ptr->aware))
1153                 {
1154                         strip_name(o_name, k_idx);
1155                 }
1156                 else
1157                 {
1158                         strcpy(o_name, k_name + flavor_k_ptr->flavor_name);
1159                 }
1160
1161                 c_prt(attr, o_name, row + i, col);
1162                 if (per_page == 1)
1163                 {
1164                         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);
1165                 }
1166
1167                 if (current_world_ptr->wizard || visual_only)
1168                 {
1169                         c_prt(attr, format("%d", k_idx), row + i, 70);
1170                 }
1171
1172                 a = flavor_k_ptr->x_attr;
1173                 c = flavor_k_ptr->x_char;
1174
1175                 Term_queue_bigchar(use_bigtile ? 76 : 77, row + i, a, c, 0, 0);
1176         }
1177
1178         for (; i < per_page; i++)
1179         {
1180                 Term_erase(col, row + i, 255);
1181         }
1182 }
1183
1184
1185 /*
1186  * Describe fake object
1187  */
1188 static void desc_obj_fake(player_type *creature_ptr, KIND_OBJECT_IDX k_idx)
1189 {
1190         object_type *o_ptr;
1191         object_type object_type_body;
1192         o_ptr = &object_type_body;
1193         object_wipe(o_ptr);
1194         object_prep(o_ptr, k_idx);
1195
1196         o_ptr->ident |= IDENT_KNOWN;
1197         handle_stuff(creature_ptr);
1198
1199         if (screen_object(creature_ptr, o_ptr, SCROBJ_FAKE_OBJECT | SCROBJ_FORCE_DETAIL)) return;
1200
1201         msg_print(_("特に変わったところはないようだ。", "You see nothing special."));
1202         msg_print(NULL);
1203 }
1204
1205
1206 /*
1207  * Display known objects
1208  */
1209 void do_cmd_knowledge_objects(player_type *creature_ptr, bool *need_redraw, bool visual_only, IDX direct_k_idx)
1210 {
1211         IDX object_old, object_top;
1212         IDX grp_idx[100];
1213         int object_cnt;
1214         OBJECT_IDX *object_idx;
1215
1216         bool visual_list = FALSE;
1217         TERM_COLOR attr_top = 0;
1218         byte char_left = 0;
1219         byte mode;
1220
1221         TERM_LEN wid, hgt;
1222         Term_get_size(&wid, &hgt);
1223
1224         int browser_rows = hgt - 8;
1225         C_MAKE(object_idx, max_k_idx, KIND_OBJECT_IDX);
1226
1227         int len;
1228         int max = 0;
1229         int grp_cnt = 0;
1230         if (direct_k_idx < 0)
1231         {
1232                 mode = visual_only ? 0x03 : 0x01;
1233                 for (IDX i = 0; object_group_text[i] != NULL; i++)
1234                 {
1235                         len = strlen(object_group_text[i]);
1236                         if (len > max) max = len;
1237
1238                         if (collect_objects(i, object_idx, mode))
1239                         {
1240                                 grp_idx[grp_cnt++] = i;
1241                         }
1242                 }
1243
1244                 object_old = -1;
1245                 object_cnt = 0;
1246         }
1247         else
1248         {
1249                 object_kind *k_ptr = &k_info[direct_k_idx];
1250                 object_kind *flavor_k_ptr;
1251
1252                 if (!visual_only && k_ptr->flavor)
1253                 {
1254                         flavor_k_ptr = &k_info[k_ptr->flavor];
1255                 }
1256                 else
1257                 {
1258                         flavor_k_ptr = k_ptr;
1259                 }
1260
1261                 object_idx[0] = direct_k_idx;
1262                 object_old = direct_k_idx;
1263                 object_cnt = 1;
1264                 object_idx[1] = -1;
1265                 (void)visual_mode_command('v', &visual_list, browser_rows - 1, wid - (max + 3),
1266                         &attr_top, &char_left, &flavor_k_ptr->x_attr, &flavor_k_ptr->x_char, need_redraw);
1267         }
1268
1269         grp_idx[grp_cnt] = -1;
1270         mode = visual_only ? 0x02 : 0x00;
1271         IDX old_grp_cur = -1;
1272         IDX grp_cur = 0;
1273         IDX grp_top = 0;
1274         IDX object_cur = object_top = 0;
1275         bool flag = FALSE;
1276         bool redraw = TRUE;
1277         int column = 0;
1278         while (!flag)
1279         {
1280                 object_kind *k_ptr, *flavor_k_ptr;
1281
1282                 if (redraw)
1283                 {
1284                         clear_from(0);
1285
1286 #ifdef JP
1287                         prt(format("%s - アイテム", !visual_only ? "知識" : "表示"), 2, 0);
1288                         if (direct_k_idx < 0) prt("グループ", 4, 0);
1289                         prt("名前", 4, max + 3);
1290                         if (current_world_ptr->wizard || visual_only) prt("Idx", 4, 70);
1291                         prt("文字", 4, 74);
1292 #else
1293                         prt(format("%s - objects", !visual_only ? "Knowledge" : "Visuals"), 2, 0);
1294                         if (direct_k_idx < 0) prt("Group", 4, 0);
1295                         prt("Name", 4, max + 3);
1296                         if (current_world_ptr->wizard || visual_only) prt("Idx", 4, 70);
1297                         prt("Sym", 4, 75);
1298 #endif
1299
1300                         for (IDX i = 0; i < 78; i++)
1301                         {
1302                                 Term_putch(i, 5, TERM_WHITE, '=');
1303                         }
1304
1305                         if (direct_k_idx < 0)
1306                         {
1307                                 for (IDX i = 0; i < browser_rows; i++)
1308                                 {
1309                                         Term_putch(max + 1, 6 + i, TERM_WHITE, '|');
1310                                 }
1311                         }
1312
1313                         redraw = FALSE;
1314                 }
1315
1316                 if (direct_k_idx < 0)
1317                 {
1318                         if (grp_cur < grp_top) grp_top = grp_cur;
1319                         if (grp_cur >= grp_top + browser_rows) grp_top = grp_cur - browser_rows + 1;
1320
1321                         display_group_list(0, 6, max, browser_rows, grp_idx, object_group_text, grp_cur, grp_top);
1322                         if (old_grp_cur != grp_cur)
1323                         {
1324                                 old_grp_cur = grp_cur;
1325                                 object_cnt = collect_objects(grp_idx[grp_cur], object_idx, mode);
1326                         }
1327
1328                         while (object_cur < object_top)
1329                                 object_top = MAX(0, object_top - browser_rows / 2);
1330                         while (object_cur >= object_top + browser_rows)
1331                                 object_top = MIN(object_cnt - browser_rows, object_top + browser_rows / 2);
1332                 }
1333
1334                 if (!visual_list)
1335                 {
1336                         display_object_list(max + 3, 6, browser_rows, object_idx, object_cur, object_top, visual_only);
1337                 }
1338                 else
1339                 {
1340                         object_top = object_cur;
1341                         display_object_list(max + 3, 6, 1, object_idx, object_cur, object_top, visual_only);
1342                         display_visual_list(max + 3, 7, browser_rows - 1, wid - (max + 3), attr_top, char_left);
1343                 }
1344
1345                 k_ptr = &k_info[object_idx[object_cur]];
1346
1347                 if (!visual_only && k_ptr->flavor)
1348                 {
1349                         flavor_k_ptr = &k_info[k_ptr->flavor];
1350                 }
1351                 else
1352                 {
1353                         flavor_k_ptr = k_ptr;
1354                 }
1355
1356 #ifdef JP
1357                 prt(format("<方向>%s%s%s, ESC",
1358                         (!visual_list && !visual_only) ? ", 'r'で詳細を見る" : "",
1359                         visual_list ? ", ENTERで決定" : ", 'v'でシンボル変更",
1360                         (attr_idx || char_idx) ? ", 'c', 'p'でペースト" : ", 'c'でコピー"),
1361                         hgt - 1, 0);
1362 #else
1363                 prt(format("<dir>%s%s%s, ESC",
1364                         (!visual_list && !visual_only) ? ", 'r' to recall" : "",
1365                         visual_list ? ", ENTER to accept" : ", 'v' for visuals",
1366                         (attr_idx || char_idx) ? ", 'c', 'p' to paste" : ", 'c' to copy"),
1367                         hgt - 1, 0);
1368 #endif
1369
1370                 if (!visual_only)
1371                 {
1372                         if (object_cnt) object_kind_track(creature_ptr, object_idx[object_cur]);
1373
1374                         if (object_old != object_idx[object_cur])
1375                         {
1376                                 handle_stuff(creature_ptr);
1377                                 object_old = object_idx[object_cur];
1378                         }
1379                 }
1380
1381                 if (visual_list)
1382                 {
1383                         place_visual_list_cursor(max + 3, 7, flavor_k_ptr->x_attr, flavor_k_ptr->x_char, attr_top, char_left);
1384                 }
1385                 else if (!column)
1386                 {
1387                         Term_gotoxy(0, 6 + (grp_cur - grp_top));
1388                 }
1389                 else
1390                 {
1391                         Term_gotoxy(max + 3, 6 + (object_cur - object_top));
1392                 }
1393
1394                 char ch = inkey();
1395                 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))
1396                 {
1397                         if (direct_k_idx >= 0)
1398                         {
1399                                 switch (ch)
1400                                 {
1401                                 case '\n':
1402                                 case '\r':
1403                                 case ESCAPE:
1404                                         flag = TRUE;
1405                                         break;
1406                                 }
1407                         }
1408                         continue;
1409                 }
1410
1411                 switch (ch)
1412                 {
1413                 case ESCAPE:
1414                 {
1415                         flag = TRUE;
1416                         break;
1417                 }
1418
1419                 case 'R':
1420                 case 'r':
1421                 {
1422                         if (!visual_list && !visual_only && (grp_cnt > 0))
1423                         {
1424                                 desc_obj_fake(creature_ptr, object_idx[object_cur]);
1425                                 redraw = TRUE;
1426                         }
1427
1428                         break;
1429                 }
1430
1431                 default:
1432                 {
1433                         browser_cursor(ch, &column, &grp_cur, grp_cnt, &object_cur, object_cnt);
1434                         break;
1435                 }
1436                 }
1437         }
1438
1439         C_KILL(object_idx, max_k_idx, KIND_OBJECT_IDX);
1440 }
1441
1442
1443 /*
1444  * Display the features in a group.
1445  */
1446 static void display_feature_list(int col, int row, int per_page, FEAT_IDX *feat_idx,
1447         FEAT_IDX feat_cur, FEAT_IDX feat_top, bool visual_only, int lighting_level)
1448 {
1449         int lit_col[F_LIT_MAX], i;
1450         int f_idx_col = use_bigtile ? 62 : 64;
1451
1452         lit_col[F_LIT_STANDARD] = use_bigtile ? (71 - F_LIT_MAX) : 71;
1453         for (i = F_LIT_NS_BEGIN; i < F_LIT_MAX; i++)
1454                 lit_col[i] = lit_col[F_LIT_STANDARD] + 2 + (i - F_LIT_NS_BEGIN) * 2 + (use_bigtile ? i : 0);
1455
1456         for (i = 0; i < per_page && (feat_idx[feat_top + i] >= 0); i++)
1457         {
1458                 TERM_COLOR attr;
1459                 FEAT_IDX f_idx = feat_idx[feat_top + i];
1460                 feature_type *f_ptr = &f_info[f_idx];
1461                 int row_i = row + i;
1462                 attr = ((i + feat_top == feat_cur) ? TERM_L_BLUE : TERM_WHITE);
1463                 c_prt(attr, f_name + f_ptr->name, row_i, col);
1464                 if (per_page == 1)
1465                 {
1466                         c_prt(attr, format("(%s)", lighting_level_str[lighting_level]), row_i, col + 1 + strlen(f_name + f_ptr->name));
1467                         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));
1468                 }
1469                 if (current_world_ptr->wizard || visual_only)
1470                 {
1471                         c_prt(attr, format("%d", f_idx), row_i, f_idx_col);
1472                 }
1473
1474                 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);
1475                 Term_putch(lit_col[F_LIT_NS_BEGIN], row_i, TERM_SLATE, '(');
1476                 for (int j = F_LIT_NS_BEGIN + 1; j < F_LIT_MAX; j++)
1477                 {
1478                         Term_putch(lit_col[j], row_i, TERM_SLATE, '/');
1479                 }
1480
1481                 Term_putch(lit_col[F_LIT_MAX - 1] + (use_bigtile ? 3 : 2), row_i, TERM_SLATE, ')');
1482                 for (int j = F_LIT_NS_BEGIN; j < F_LIT_MAX; j++)
1483                 {
1484                         Term_queue_bigchar(lit_col[j] + 1, row_i, f_ptr->x_attr[j], f_ptr->x_char[j], 0, 0);
1485                 }
1486         }
1487
1488         for (; i < per_page; i++)
1489         {
1490                 Term_erase(col, row + i, 255);
1491         }
1492 }
1493
1494
1495 /*
1496  * Interact with feature visuals.
1497  */
1498 void do_cmd_knowledge_features(bool *need_redraw, bool visual_only, IDX direct_f_idx, IDX *lighting_level)
1499 {
1500         TERM_COLOR attr_old[F_LIT_MAX];
1501         (void)C_WIPE(attr_old, F_LIT_MAX, TERM_COLOR);
1502         SYMBOL_CODE char_old[F_LIT_MAX];
1503         (void)C_WIPE(char_old, F_LIT_MAX, SYMBOL_CODE);
1504
1505         TERM_LEN wid, hgt;
1506         Term_get_size(&wid, &hgt);
1507
1508         FEAT_IDX *feat_idx;
1509         C_MAKE(feat_idx, max_f_idx, FEAT_IDX);
1510
1511         concptr feature_group_text[] = { "terrains", NULL };
1512         int len;
1513         int max = 0;
1514         int grp_cnt = 0;
1515         int feat_cnt;
1516         FEAT_IDX grp_idx[100];
1517         TERM_COLOR attr_top = 0;
1518         bool visual_list = FALSE;
1519         byte char_left = 0;
1520         TERM_LEN browser_rows = hgt - 8;
1521         if (direct_f_idx < 0)
1522         {
1523                 for (FEAT_IDX i = 0; feature_group_text[i] != NULL; i++)
1524                 {
1525                         len = strlen(feature_group_text[i]);
1526                         if (len > max) max = len;
1527
1528                         if (collect_features(feat_idx, 0x01))
1529                         {
1530                                 grp_idx[grp_cnt++] = i;
1531                         }
1532                 }
1533
1534                 feat_cnt = 0;
1535         }
1536         else
1537         {
1538                 feature_type *f_ptr = &f_info[direct_f_idx];
1539
1540                 feat_idx[0] = direct_f_idx;
1541                 feat_cnt = 1;
1542                 feat_idx[1] = -1;
1543
1544                 (void)visual_mode_command('v', &visual_list, browser_rows - 1, wid - (max + 3),
1545                         &attr_top, &char_left, &f_ptr->x_attr[*lighting_level], &f_ptr->x_char[*lighting_level], need_redraw);
1546
1547                 for (FEAT_IDX i = 0; i < F_LIT_MAX; i++)
1548                 {
1549                         attr_old[i] = f_ptr->x_attr[i];
1550                         char_old[i] = f_ptr->x_char[i];
1551                 }
1552         }
1553
1554         grp_idx[grp_cnt] = -1;
1555
1556         FEAT_IDX old_grp_cur = -1;
1557         FEAT_IDX grp_cur = 0;
1558         FEAT_IDX grp_top = 0;
1559         FEAT_IDX feat_cur = 0;
1560         FEAT_IDX feat_top = 0;
1561         TERM_LEN column = 0;
1562         bool flag = FALSE;
1563         bool redraw = TRUE;
1564         TERM_COLOR *cur_attr_ptr;
1565         SYMBOL_CODE *cur_char_ptr;
1566         while (!flag)
1567         {
1568                 char ch;
1569                 feature_type *f_ptr;
1570
1571                 if (redraw)
1572                 {
1573                         clear_from(0);
1574
1575                         prt(_("表示 - 地形", "Visuals - features"), 2, 0);
1576                         if (direct_f_idx < 0) prt(_("グループ", "Group"), 4, 0);
1577                         prt(_("名前", "Name"), 4, max + 3);
1578                         if (use_bigtile)
1579                         {
1580                                 if (current_world_ptr->wizard || visual_only) prt("Idx", 4, 62);
1581                                 prt(_("文字 ( l/ d)", "Sym ( l/ d)"), 4, 66);
1582                         }
1583                         else
1584                         {
1585                                 if (current_world_ptr->wizard || visual_only) prt("Idx", 4, 64);
1586                                 prt(_("文字 (l/d)", "Sym (l/d)"), 4, 68);
1587                         }
1588
1589                         for (FEAT_IDX i = 0; i < 78; i++)
1590                         {
1591                                 Term_putch(i, 5, TERM_WHITE, '=');
1592                         }
1593
1594                         if (direct_f_idx < 0)
1595                         {
1596                                 for (FEAT_IDX i = 0; i < browser_rows; i++)
1597                                 {
1598                                         Term_putch(max + 1, 6 + i, TERM_WHITE, '|');
1599                                 }
1600                         }
1601
1602                         redraw = FALSE;
1603                 }
1604
1605                 if (direct_f_idx < 0)
1606                 {
1607                         if (grp_cur < grp_top) grp_top = grp_cur;
1608                         if (grp_cur >= grp_top + browser_rows) grp_top = grp_cur - browser_rows + 1;
1609
1610                         display_group_list(0, 6, max, browser_rows, grp_idx, feature_group_text, grp_cur, grp_top);
1611                         if (old_grp_cur != grp_cur)
1612                         {
1613                                 old_grp_cur = grp_cur;
1614                                 feat_cnt = collect_features(feat_idx, 0x00);
1615                         }
1616
1617                         while (feat_cur < feat_top)
1618                                 feat_top = MAX(0, feat_top - browser_rows / 2);
1619                         while (feat_cur >= feat_top + browser_rows)
1620                                 feat_top = MIN(feat_cnt - browser_rows, feat_top + browser_rows / 2);
1621                 }
1622
1623                 if (!visual_list)
1624                 {
1625                         display_feature_list(max + 3, 6, browser_rows, feat_idx, feat_cur, feat_top, visual_only, F_LIT_STANDARD);
1626                 }
1627                 else
1628                 {
1629                         feat_top = feat_cur;
1630                         display_feature_list(max + 3, 6, 1, feat_idx, feat_cur, feat_top, visual_only, *lighting_level);
1631                         display_visual_list(max + 3, 7, browser_rows - 1, wid - (max + 3), attr_top, char_left);
1632                 }
1633
1634                 prt(format(_("<方向>%s, 'd'で標準光源効果%s, ESC", "<dir>%s, 'd' for default lighting%s, ESC"),
1635                         visual_list ? _(", ENTERで決定, 'a'で対象明度変更", ", ENTER to accept, 'a' for lighting level") : _(", 'v'でシンボル変更", ", 'v' for visuals"),
1636                         (attr_idx || char_idx) ? _(", 'c', 'p'でペースト", ", 'c', 'p' to paste") : _(", 'c'でコピー", ", 'c' to copy")),
1637                         hgt - 1, 0);
1638
1639                 f_ptr = &f_info[feat_idx[feat_cur]];
1640                 cur_attr_ptr = &f_ptr->x_attr[*lighting_level];
1641                 cur_char_ptr = &f_ptr->x_char[*lighting_level];
1642
1643                 if (visual_list)
1644                 {
1645                         place_visual_list_cursor(max + 3, 7, *cur_attr_ptr, *cur_char_ptr, attr_top, char_left);
1646                 }
1647                 else if (!column)
1648                 {
1649                         Term_gotoxy(0, 6 + (grp_cur - grp_top));
1650                 }
1651                 else
1652                 {
1653                         Term_gotoxy(max + 3, 6 + (feat_cur - feat_top));
1654                 }
1655
1656                 ch = inkey();
1657                 if (visual_list && ((ch == 'A') || (ch == 'a')))
1658                 {
1659                         int prev_lighting_level = *lighting_level;
1660
1661                         if (ch == 'A')
1662                         {
1663                                 if (*lighting_level <= 0) *lighting_level = F_LIT_MAX - 1;
1664                                 else (*lighting_level)--;
1665                         }
1666                         else
1667                         {
1668                                 if (*lighting_level >= F_LIT_MAX - 1) *lighting_level = 0;
1669                                 else (*lighting_level)++;
1670                         }
1671
1672                         if (f_ptr->x_attr[prev_lighting_level] != f_ptr->x_attr[*lighting_level])
1673                                 attr_top = MAX(0, (f_ptr->x_attr[*lighting_level] & 0x7f) - 5);
1674
1675                         if (f_ptr->x_char[prev_lighting_level] != f_ptr->x_char[*lighting_level])
1676                                 char_left = MAX(0, f_ptr->x_char[*lighting_level] - 10);
1677
1678                         continue;
1679                 }
1680                 else if ((ch == 'D') || (ch == 'd'))
1681                 {
1682                         TERM_COLOR prev_x_attr = f_ptr->x_attr[*lighting_level];
1683                         byte prev_x_char = f_ptr->x_char[*lighting_level];
1684
1685                         apply_default_feat_lighting(f_ptr->x_attr, f_ptr->x_char);
1686
1687                         if (visual_list)
1688                         {
1689                                 if (prev_x_attr != f_ptr->x_attr[*lighting_level])
1690                                         attr_top = MAX(0, (f_ptr->x_attr[*lighting_level] & 0x7f) - 5);
1691
1692                                 if (prev_x_char != f_ptr->x_char[*lighting_level])
1693                                         char_left = MAX(0, f_ptr->x_char[*lighting_level] - 10);
1694                         }
1695                         else *need_redraw = TRUE;
1696
1697                         continue;
1698                 }
1699                 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))
1700                 {
1701                         switch (ch)
1702                         {
1703                         case ESCAPE:
1704                                 for (FEAT_IDX i = 0; i < F_LIT_MAX; i++)
1705                                 {
1706                                         f_ptr->x_attr[i] = attr_old[i];
1707                                         f_ptr->x_char[i] = char_old[i];
1708                                 }
1709
1710                                 /* Fall through */
1711                         case '\n':
1712                         case '\r':
1713                                 if (direct_f_idx >= 0) flag = TRUE;
1714                                 else *lighting_level = F_LIT_STANDARD;
1715                                 break;
1716                         case 'V':
1717                         case 'v':
1718                                 for (FEAT_IDX i = 0; i < F_LIT_MAX; i++)
1719                                 {
1720                                         attr_old[i] = f_ptr->x_attr[i];
1721                                         char_old[i] = f_ptr->x_char[i];
1722                                 }
1723                                 *lighting_level = F_LIT_STANDARD;
1724                                 break;
1725
1726                         case 'C':
1727                         case 'c':
1728                                 if (!visual_list)
1729                                 {
1730                                         for (FEAT_IDX i = 0; i < F_LIT_MAX; i++)
1731                                         {
1732                                                 attr_idx_feat[i] = f_ptr->x_attr[i];
1733                                                 char_idx_feat[i] = f_ptr->x_char[i];
1734                                         }
1735                                 }
1736                                 break;
1737
1738                         case 'P':
1739                         case 'p':
1740                                 if (!visual_list)
1741                                 {
1742                                         for (FEAT_IDX i = F_LIT_NS_BEGIN; i < F_LIT_MAX; i++)
1743                                         {
1744                                                 if (attr_idx_feat[i] || (!(char_idx_feat[i] & 0x80) && char_idx_feat[i])) f_ptr->x_attr[i] = attr_idx_feat[i];
1745                                                 if (char_idx_feat[i]) f_ptr->x_char[i] = char_idx_feat[i];
1746                                         }
1747                                 }
1748                                 break;
1749                         }
1750                         continue;
1751                 }
1752
1753                 switch (ch)
1754                 {
1755                 case ESCAPE:
1756                 {
1757                         flag = TRUE;
1758                         break;
1759                 }
1760
1761                 default:
1762                 {
1763                         browser_cursor(ch, &column, &grp_cur, grp_cnt, &feat_cur, feat_cnt);
1764                         break;
1765                 }
1766                 }
1767         }
1768
1769         C_KILL(feat_idx, max_f_idx, FEAT_IDX);
1770 }
1771
1772
1773 /*
1774  * List wanted monsters
1775  * @param creature_ptr プレーヤーへの参照ポインタ
1776  * @return なし
1777  */
1778 static void do_cmd_knowledge_bounty(player_type *creature_ptr)
1779 {
1780         FILE *fff = NULL;
1781         GAME_TEXT file_name[FILE_NAME_SIZE];
1782         if (!open_temporary_file(&fff, file_name)) return;
1783
1784         fprintf(fff, _("今日のターゲット : %s\n", "Today's target : %s\n"),
1785                 (creature_ptr->today_mon ? r_name + r_info[creature_ptr->today_mon].name : _("不明", "unknown")));
1786         fprintf(fff, "\n");
1787         fprintf(fff, _("賞金首リスト\n", "List of wanted monsters\n"));
1788         fprintf(fff, "----------------------------------------------\n");
1789
1790         bool listed = FALSE;
1791         for (int i = 0; i < MAX_BOUNTY; i++)
1792         {
1793                 if (current_world_ptr->bounty_r_idx[i] <= 10000)
1794                 {
1795                         fprintf(fff, "%s\n", r_name + r_info[current_world_ptr->bounty_r_idx[i]].name);
1796                         listed = TRUE;
1797                 }
1798         }
1799
1800         if (!listed)
1801         {
1802                 fprintf(fff, "\n%s\n", _("賞金首はもう残っていません。", "There are no more wanted monster."));
1803         }
1804
1805         my_fclose(fff);
1806         (void)show_file(creature_ptr, TRUE, file_name, _("賞金首の一覧", "Wanted monsters"), 0, 0);
1807         fd_kill(file_name);
1808 }
1809
1810 /*
1811  * List virtues & status
1812  */
1813 static void do_cmd_knowledge_virtues(player_type *creature_ptr)
1814 {
1815         FILE *fff = NULL;
1816         GAME_TEXT file_name[FILE_NAME_SIZE];
1817         if (!open_temporary_file(&fff, file_name)) return;
1818
1819         fprintf(fff, _("現在の属性 : %s\n\n", "Your alignment : %s\n\n"), your_alignment(creature_ptr));
1820         dump_virtues(creature_ptr, fff);
1821         my_fclose(fff);
1822         (void)show_file(creature_ptr, TRUE, file_name, _("八つの徳", "Virtues"), 0, 0);
1823         fd_kill(file_name);
1824 }
1825
1826 /*
1827  * Dungeon
1828  */
1829 static void do_cmd_knowledge_dungeon(player_type *creature_ptr)
1830 {
1831         FILE *fff = NULL;
1832         GAME_TEXT file_name[FILE_NAME_SIZE];
1833         if (!open_temporary_file(&fff, file_name)) return;
1834
1835         for (int i = 1; i < current_world_ptr->max_d_idx; i++)
1836         {
1837                 bool seiha = FALSE;
1838
1839                 if (!d_info[i].maxdepth) continue;
1840                 if (!max_dlv[i]) continue;
1841                 if (d_info[i].final_guardian)
1842                 {
1843                         if (!r_info[d_info[i].final_guardian].max_num) seiha = TRUE;
1844                 }
1845                 else if (max_dlv[i] == d_info[i].maxdepth) seiha = TRUE;
1846
1847                 fprintf(fff, _("%c%-12s :  %3d 階\n", "%c%-16s :  level %3d\n"), seiha ? '!' : ' ', d_name + d_info[i].name, (int)max_dlv[i]);
1848         }
1849
1850         my_fclose(fff);
1851         (void)show_file(creature_ptr, TRUE, file_name, _("今までに入ったダンジョン", "Dungeon"), 0, 0);
1852         fd_kill(file_name);
1853 }
1854
1855
1856 /*
1857 * List virtues & status
1858 *
1859 */
1860 static void do_cmd_knowledge_stat(player_type *creature_ptr)
1861 {
1862         FILE *fff = NULL;
1863         GAME_TEXT file_name[FILE_NAME_SIZE];
1864         if (!open_temporary_file(&fff, file_name)) return;
1865
1866         int percent = (int)(((long)creature_ptr->player_hp[PY_MAX_LEVEL - 1] * 200L) /
1867                 (2 * creature_ptr->hitdie +
1868                 ((PY_MAX_LEVEL - 1 + 3) * (creature_ptr->hitdie + 1))));
1869
1870         if (creature_ptr->knowledge & KNOW_HPRATE)
1871                 fprintf(fff, _("現在の体力ランク : %d/100\n\n", "Your current Life Rating is %d/100.\n\n"), percent);
1872         else fprintf(fff, _("現在の体力ランク : ???\n\n", "Your current Life Rating is ???.\n\n"));
1873
1874         fprintf(fff, _("能力の最大値\n\n", "Limits of maximum stats\n\n"));
1875         for (int v_nr = 0; v_nr < A_MAX; v_nr++)
1876         {
1877                 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);
1878                 else fprintf(fff, "%s ???\n", stat_names[v_nr]);
1879         }
1880
1881         dump_yourself(creature_ptr, fff);
1882         my_fclose(fff);
1883         (void)show_file(creature_ptr, TRUE, file_name, _("自分に関する情報", "HP-rate & Max stat"), 0, 0);
1884         fd_kill(file_name);
1885 }
1886
1887
1888 /*
1889  * List my home
1890  * @param player_ptr プレーヤーへの参照ポインタ
1891  * @return なし
1892  */
1893 static void do_cmd_knowledge_home(player_type *player_ptr)
1894 {
1895         process_dungeon_file(player_ptr, "w_info.txt", 0, 0, current_world_ptr->max_wild_y, current_world_ptr->max_wild_x);
1896
1897         FILE *fff = NULL;
1898         GAME_TEXT file_name[FILE_NAME_SIZE];
1899         if (!open_temporary_file(&fff, file_name)) return;
1900
1901         store_type *store_ptr;
1902         store_ptr = &town_info[1].store[STORE_HOME];
1903
1904         if (store_ptr->stock_num)
1905         {
1906 #ifdef JP
1907                 TERM_LEN x = 1;
1908 #endif
1909                 fprintf(fff, _("  [ 我が家のアイテム ]\n", "  [Home Inventory]\n"));
1910                 concptr paren = ")";
1911                 GAME_TEXT o_name[MAX_NLEN];
1912                 for (int i = 0; i < store_ptr->stock_num; i++)
1913                 {
1914 #ifdef JP
1915                         if ((i % 12) == 0) fprintf(fff, "\n ( %d ページ )\n", x++);
1916                         object_desc(player_ptr, o_name, &store_ptr->stock[i], 0);
1917                         if (strlen(o_name) <= 80 - 3)
1918                         {
1919                                 fprintf(fff, "%c%s %s\n", I2A(i % 12), paren, o_name);
1920                         }
1921                         else
1922                         {
1923                                 int n;
1924                                 char *t;
1925                                 for (n = 0, t = o_name; n < 80 - 3; n++, t++)
1926                                         if (iskanji(*t)) { t++; n++; }
1927                                 if (n == 81 - 3) n = 79 - 3; /* 最後が漢字半分 */
1928
1929                                 fprintf(fff, "%c%s %.*s\n", I2A(i % 12), paren, n, o_name);
1930                                 fprintf(fff, "   %.77s\n", o_name + n);
1931                         }
1932 #else
1933                         object_desc(player_ptr, o_name, &store_ptr->stock[i], 0);
1934                         fprintf(fff, "%c%s %s\n", I2A(i % 12), paren, o_name);
1935 #endif
1936                 }
1937
1938                 fprintf(fff, "\n\n");
1939         }
1940
1941         my_fclose(fff);
1942         (void)show_file(player_ptr, TRUE, file_name, _("我が家のアイテム", "Home Inventory"), 0, 0);
1943         fd_kill(file_name);
1944 }
1945
1946
1947 /*
1948  * Check the status of "autopick"
1949  */
1950 static void do_cmd_knowledge_autopick(player_type *creature_ptr)
1951 {
1952         FILE *fff = NULL;
1953         GAME_TEXT file_name[FILE_NAME_SIZE];
1954         if (!open_temporary_file(&fff, file_name)) return;
1955
1956         if (!max_autopick)
1957         {
1958                 fprintf(fff, _("自動破壊/拾いには何も登録されていません。", "No preference for auto picker/destroyer."));
1959         }
1960         else
1961         {
1962                 fprintf(fff, _("   自動拾い/破壊には現在 %d行登録されています。\n\n",
1963                         "   There are %d registered lines for auto picker/destroyer.\n\n"), max_autopick);
1964         }
1965
1966         for (int k = 0; k < max_autopick; k++)
1967         {
1968                 concptr tmp;
1969                 byte act = autopick_list[k].action;
1970                 if (act & DONT_AUTOPICK)
1971                 {
1972                         tmp = _("放置", "Leave");
1973                 }
1974                 else if (act & DO_AUTODESTROY)
1975                 {
1976                         tmp = _("破壊", "Destroy");
1977                 }
1978                 else if (act & DO_AUTOPICK)
1979                 {
1980                         tmp = _("拾う", "Pickup");
1981                 }
1982                 else
1983                 {
1984                         tmp = _("確認", "Query");
1985                 }
1986
1987                 if (act & DO_DISPLAY)
1988                         fprintf(fff, "%11s", format("[%s]", tmp));
1989                 else
1990                         fprintf(fff, "%11s", format("(%s)", tmp));
1991
1992                 tmp = autopick_line_from_entry(&autopick_list[k]);
1993                 fprintf(fff, " %s", tmp);
1994                 string_free(tmp);
1995                 fprintf(fff, "\n");
1996         }
1997
1998         my_fclose(fff);
1999
2000         (void)show_file(creature_ptr, TRUE, file_name, _("自動拾い/破壊 設定リスト", "Auto-picker/Destroyer"), 0, 0);
2001         fd_kill(file_name);
2002 }
2003
2004
2005 /*
2006  * Interact with "knowledge"
2007  */
2008 void do_cmd_knowledge(player_type *creature_ptr)
2009 {
2010         int i, p = 0;
2011         bool need_redraw = FALSE;
2012         FILE_TYPE(FILE_TYPE_TEXT);
2013         screen_save();
2014         while (TRUE)
2015         {
2016                 Term_clear();
2017                 prt(format(_("%d/2 ページ", "page %d/2"), (p + 1)), 2, 65);
2018                 prt(_("現在の知識を確認する", "Display current knowledge"), 3, 0);
2019                 if (p == 0)
2020                 {
2021                         prt(_("(1) 既知の伝説のアイテム                 の一覧", "(1) Display known artifacts"), 6, 5);
2022                         prt(_("(2) 既知のアイテム                       の一覧", "(2) Display known objects"), 7, 5);
2023                         prt(_("(3) 既知の生きているユニーク・モンスター の一覧", "(3) Display remaining uniques"), 8, 5);
2024                         prt(_("(4) 既知のモンスター                     の一覧", "(4) Display known monster"), 9, 5);
2025                         prt(_("(5) 倒した敵の数                         の一覧", "(5) Display kill count"), 10, 5);
2026                         if (!vanilla_town) prt(_("(6) 賞金首                               の一覧", "(6) Display wanted monsters"), 11, 5);
2027                         prt(_("(7) 現在のペット                         の一覧", "(7) Display current pets"), 12, 5);
2028                         prt(_("(8) 我が家のアイテム                     の一覧", "(8) Display home inventory"), 13, 5);
2029                         prt(_("(9) *鑑定*済み装備の耐性                 の一覧", "(9) Display *identified* equip."), 14, 5);
2030                         prt(_("(0) 地形の表示文字/タイル                の一覧", "(0) Display terrain symbols."), 15, 5);
2031                 }
2032                 else
2033                 {
2034                         prt(_("(a) 自分に関する情報                     の一覧", "(a) Display about yourself"), 6, 5);
2035                         prt(_("(b) 突然変異                             の一覧", "(b) Display mutations"), 7, 5);
2036                         prt(_("(c) 武器の経験値                         の一覧", "(c) Display weapon proficiency"), 8, 5);
2037                         prt(_("(d) 魔法の経験値                         の一覧", "(d) Display spell proficiency"), 9, 5);
2038                         prt(_("(e) 技能の経験値                         の一覧", "(e) Display misc. proficiency"), 10, 5);
2039                         prt(_("(f) プレイヤーの徳                       の一覧", "(f) Display virtues"), 11, 5);
2040                         prt(_("(g) 入ったダンジョン                     の一覧", "(g) Display dungeons"), 12, 5);
2041                         prt(_("(h) 実行中のクエスト                     の一覧", "(h) Display current quests"), 13, 5);
2042                         prt(_("(i) 現在の自動拾い/破壊設定              の一覧", "(i) Display auto pick/destroy"), 14, 5);
2043                 }
2044
2045                 prt(_("-続く-", "-more-"), 17, 8);
2046                 prt(_("ESC) 抜ける", "ESC) Exit menu"), 21, 1);
2047                 prt(_("SPACE) 次ページ", "SPACE) Next page"), 21, 30);
2048                 prt(_("コマンド:", "Command: "), 20, 0);
2049                 i = inkey();
2050
2051                 if (i == ESCAPE) break;
2052                 switch (i)
2053                 {
2054                 case ' ': /* Page change */
2055                 case '-':
2056                         p = 1 - p;
2057                         break;
2058                 case '1': /* Artifacts */
2059                         do_cmd_knowledge_artifacts(creature_ptr);
2060                         break;
2061                 case '2': /* Objects */
2062                         do_cmd_knowledge_objects(creature_ptr, &need_redraw, FALSE, -1);
2063                         break;
2064                 case '3': /* Uniques */
2065                         do_cmd_knowledge_uniques(creature_ptr);
2066                         break;
2067                 case '4': /* Monsters */
2068                         do_cmd_knowledge_monsters(creature_ptr, &need_redraw, FALSE, -1);
2069                         break;
2070                 case '5': /* Kill count  */
2071                         do_cmd_knowledge_kill_count(creature_ptr);
2072                         break;
2073                 case '6': /* wanted */
2074                         if (!vanilla_town) do_cmd_knowledge_bounty(creature_ptr);
2075                         break;
2076                 case '7': /* Pets */
2077                         do_cmd_knowledge_pets(creature_ptr);
2078                         break;
2079                 case '8': /* Home */
2080                         do_cmd_knowledge_home(creature_ptr);
2081                         break;
2082                 case '9': /* Resist list */
2083                         do_cmd_knowledge_inventory(creature_ptr);
2084                         break;
2085                 case '0': /* Feature list */
2086                 {
2087                         IDX lighting_level = F_LIT_STANDARD;
2088                         do_cmd_knowledge_features(&need_redraw, FALSE, -1, &lighting_level);
2089                 }
2090                 break;
2091                 /* Next page */
2092                 case 'a': /* Max stat */
2093                         do_cmd_knowledge_stat(creature_ptr);
2094                         break;
2095                 case 'b': /* Mutations */
2096                         do_cmd_knowledge_mutations(creature_ptr);
2097                         break;
2098                 case 'c': /* weapon-exp */
2099                         do_cmd_knowledge_weapon_exp(creature_ptr);
2100                         break;
2101                 case 'd': /* spell-exp */
2102                         do_cmd_knowledge_spell_exp(creature_ptr);
2103                         break;
2104                 case 'e': /* skill-exp */
2105                         do_cmd_knowledge_skill_exp(creature_ptr);
2106                         break;
2107                 case 'f': /* Virtues */
2108                         do_cmd_knowledge_virtues(creature_ptr);
2109                         break;
2110                 case 'g': /* Dungeon */
2111                         do_cmd_knowledge_dungeon(creature_ptr);
2112                         break;
2113                 case 'h': /* Quests */
2114                         do_cmd_knowledge_quests(creature_ptr);
2115                         break;
2116                 case 'i': /* Autopick */
2117                         do_cmd_knowledge_autopick(creature_ptr);
2118                         break;
2119                 default: /* Unknown option */
2120                         bell();
2121                 }
2122
2123                 msg_erase();
2124         }
2125
2126         screen_load();
2127         if (need_redraw) do_cmd_redraw(creature_ptr);
2128 }
2129
2130
2131 /*
2132  * Check on the status of an active quest
2133  * @param creature_ptr プレーヤーへの参照ポインタ
2134  * @return なし
2135  */
2136 void do_cmd_checkquest(player_type *creature_ptr)
2137 {
2138         FILE_TYPE(FILE_TYPE_TEXT);
2139         screen_save();
2140         do_cmd_knowledge_quests(creature_ptr);
2141         screen_load();
2142 }
2143
2144
2145 /*
2146  * Display the time and date
2147  * @param creature_ptr プレーヤーへの参照ポインタ
2148  * @return なし
2149  */
2150 void do_cmd_time(player_type *creature_ptr)
2151 {
2152         int day, hour, min;
2153         extract_day_hour_min(creature_ptr, &day, &hour, &min);
2154
2155         char desc[1024];
2156         strcpy(desc, _("変な時刻だ。", "It is a strange time."));
2157
2158         char day_buf[10];
2159         if (day < MAX_DAYS) sprintf(day_buf, "%d", day);
2160         else strcpy(day_buf, "*****");
2161
2162         msg_format(_("%s日目, 時刻は%d:%02d %sです。", "This is day %s. The time is %d:%02d %s."),
2163                 day_buf, (hour % 12 == 0) ? 12 : (hour % 12), min, (hour < 12) ? "AM" : "PM");
2164
2165         char buf[1024];
2166         if (!randint0(10) || creature_ptr->image)
2167         {
2168                 path_build(buf, sizeof(buf), ANGBAND_DIR_FILE, _("timefun_j.txt", "timefun.txt"));
2169         }
2170         else
2171         {
2172                 path_build(buf, sizeof(buf), ANGBAND_DIR_FILE, _("timenorm_j.txt", "timenorm.txt"));
2173         }
2174
2175         FILE *fff;
2176         fff = my_fopen(buf, "rt");
2177
2178         if (!fff) return;
2179
2180         int full = hour * 100 + min;
2181         int start = 9999;
2182         int end = -9999;
2183         int num = 0;
2184         while (!my_fgets(fff, buf, sizeof(buf)))
2185         {
2186                 if (!buf[0] || (buf[0] == '#')) continue;
2187                 if (buf[1] != ':') continue;
2188
2189                 if (buf[0] == 'S')
2190                 {
2191                         start = atoi(buf + 2);
2192                         end = start + 59;
2193                         continue;
2194                 }
2195
2196                 if (buf[0] == 'E')
2197                 {
2198                         end = atoi(buf + 2);
2199                         continue;
2200                 }
2201
2202                 if ((start > full) || (full > end)) continue;
2203
2204                 if (buf[0] == 'D')
2205                 {
2206                         num++;
2207                         if (!randint0(num)) strcpy(desc, buf + 2);
2208
2209                         continue;
2210                 }
2211         }
2212
2213         msg_print(desc);
2214         my_fclose(fff);
2215 }