OSDN Git Service

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