OSDN Git Service

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