OSDN Git Service

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