OSDN Git Service

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