OSDN Git Service

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