OSDN Git Service

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