OSDN Git Service

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