OSDN Git Service

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