OSDN Git Service

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