OSDN Git Service

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