OSDN Git Service

'%'からvisual modeを呼び出せるように変更. また, 各要素の編集中に'v'で
authornothere <nothere@0568b783-4c39-0410-ac80-bf13821ea2a2>
Thu, 11 Dec 2003 13:44:06 +0000 (13:44 +0000)
committernothere <nothere@0568b783-4c39-0410-ac80-bf13821ea2a2>
Thu, 11 Dec 2003 13:44:06 +0000 (13:44 +0000)
その要素のシンボル編集専用モードでvisual modeを使えるように変更. な
お, 以下の変更を含む.
* '%'でも設定が無意味な要素 (名前なし, flavor使用, mimic使用) は変更
  できないようにした. 要素番号指定では再入力を求められる.
* do_cmd_visuals()の処理分岐はswitch文で書き直した.
* do_cmd_visuals()での処理後は必要に応じて自動で画面を再描画するよう
  に変更.
* visual mode中は思い出や詳細は参照できないので, 'r'の説明を表示しな
  いように変更.
* visual modeでプレイヤー, 空のアイテム, 未知の地形も編集可能に変更.
* ウィザードモードまたは'%'からの呼び出しでは地形のidxを表示するよう
  に変更.
* リスト表示の各種情報の表示桁の微調整.

lib/help/commdesc.txt
lib/help/jcommdesc.txt
lib/help/jpref.txt
lib/help/pref.txt
src/cmd4.c

index 72238ab..2517635 100644 (file)
@@ -631,8 +631,7 @@ Interact with macros (@)
 Interact with visuals (%)
      Allow you to interact with visuals. You may load or save visuals
      from user pref files, or modify the attr/char mappings for the
-     monsters, objects, and terrain features. You must use the "redraw"
-     command (^R) to redraw the map after changing attr/char mappings.
+     monsters, objects, and terrain features.
 
 Interact with colors (&)
      Allow the user to interact with colors. This command only
index db97455..34fa9ad 100644 (file)
      ²èÌÌɽ¼¨¤Ë´Ø¤¹¤ëÀßÄê¤ò¤¹¤ë¤³¤È¤¬¤Ç¤­¤Þ¤¹¡£²èÌÌɽ¼¨¤ÎÀßÄê¤ò¥æ¡¼
      ¥¶¡¼ÀßÄê¥Õ¥¡¥¤¥ë¤«¤éÆɤ߹þ¤ó¤À¤ê¡¢¥æ¡¼¥¶¡¼ÀßÄê¥Õ¥¡¥¤¥ë¤Ë¥»¡¼¥Ö¤·
      ¤¿¤ê¡¢¥â¥ó¥¹¥¿¡¼¤ä¥¢¥¤¥Æ¥à¤äÃÏ·Á¤Î¿§¤äʸ»ú¤òÊѹ¹¤·¤¿¤ê¤¹¤ë¤³¤È¤¬
-     ¤Ç¤­¤Þ¤¹¡£ÀßÄê¤òÊѹ¹¤·¤¿¤é¡¢²èÌÌÉÁ¤­Ä¾¤·¥³¥Þ¥ó¥É (^R) ¤ò»È¤Ã¤Æ²è
-     Ì̤òÉÁ¤­Ä¾¤·¤Æ²¼¤µ¤¤¡£
+     ¤Ç¤­¤Þ¤¹¡£
 
 ¥«¥é¡¼¤ÎÀßÄê (&)
      ¥«¥é¡¼¤ÎÀßÄê¤ò¤¹¤ë¤³¤È¤¬¤Ç¤­¤Þ¤¹¡£¤³¤Î¥³¥Þ¥ó¥É¤Ï¥·¥¹¥Æ¥à¤Ë¤è¤Ã¤Æ
index 6019386..60ae19b 100644 (file)
@@ -83,8 +83,7 @@ pref file)
      ²èÌÌɽ¼¨¤Ë´Ø¤¹¤ëÀßÄê¤ò¤¹¤ë¤³¤È¤¬¤Ç¤­¤Þ¤¹¡£²èÌÌɽ¼¨¤ÎÀßÄê¤ò¥æ¡¼
      ¥¶¡¼ÀßÄê¥Õ¥¡¥¤¥ë¤«¤éÆɤ߹þ¤ó¤À¤ê¡¢¥æ¡¼¥¶¡¼ÀßÄê¥Õ¥¡¥¤¥ë¤Ë¥»¡¼¥Ö¤·
      ¤¿¤ê¡¢¥â¥ó¥¹¥¿¡¼¤ä¥¢¥¤¥Æ¥à¤äÃÏ·Á¤Î¿§¤äʸ»ú¤òÊѹ¹¤·¤¿¤ê¤¹¤ë¤³¤È¤¬
-     ¤Ç¤­¤Þ¤¹¡£ÀßÄê¤òÊѹ¹¤·¤¿¤é¡¢²èÌÌÉÁ¤­Ä¾¤·¥³¥Þ¥ó¥É (^R) ¤ò»È¤Ã¤Æ²è
-     Ì̤òÉÁ¤­Ä¾¤·¤Æ²¼¤µ¤¤¡£
+     ¤Ç¤­¤Þ¤¹¡£
 
 ¥«¥é¡¼¤ÎÀßÄê (&)
      ¥«¥é¡¼¤ÎÀßÄê¤ò¤¹¤ë¤³¤È¤¬¤Ç¤­¤Þ¤¹¡£¤³¤Î¥³¥Þ¥ó¥É¤Ï¥·¥¹¥Æ¥à¤Ë¤è¤Ã¤Æ
index fdcc57d..b3aa812 100644 (file)
@@ -76,8 +76,7 @@ Interact with macros (@)
 Interact with visuals (%)
      Allow you to interact with visuals. You may load or save visuals
      from user pref files, or modify the attr/char mappings for the
-     monsters, objects, and terrain features. You must use the "redraw"
-     command (^R) to redraw the map after changing attr/char mappings.
+     monsters, objects, and terrain features.
 
 Interact with colors (&)
      Allow the user to interact with colors. This command only
index 7e24eb7..26ab724 100644 (file)
@@ -3590,7 +3590,7 @@ static cptr lighting_level_str[F_LIT_MAX] =
 };
 
 
-static void cmd_visuals_aux(int i, int *num, int max)
+static bool cmd_visuals_aux(int i, int *num, int max)
 {
        if (iscntrl(i))
        {
@@ -3600,45 +3600,97 @@ static void cmd_visuals_aux(int i, int *num, int max)
                sprintf(str, "%d", *num);
 
                if (!get_string(format("Input new number(0-%d): ", max-1), str, 4))
-                       return;
+                       return FALSE;
 
                tmp = strtol(str, NULL, 0);
                if (tmp >= 0 && tmp < max)
                        *num = tmp;
-               return;
        }
        else if (isupper(i))
                *num = (*num + max - 1) % max;
        else
                *num = (*num + 1) % max;
 
-       return;
+       return TRUE;
 }
 
+static void print_visuals_menu(cptr choice_msg)
+{
+#ifdef JP
+       prt("²èÌÌɽ¼¨¤ÎÀßÄê", 1, 0);
+#else
+       prt("Interact with Visuals", 1, 0);
+#endif
+
+       /* Give some choices */
+#ifdef JP
+       prt("(0) ¥æ¡¼¥¶¡¼ÀßÄê¥Õ¥¡¥¤¥ë¤Î¥í¡¼¥É", 3, 5);
+#else
+       prt("(0) Load a user pref file", 3, 5);
+#endif
+
+#ifdef ALLOW_VISUALS
+#ifdef JP
+       prt("(1) ¥â¥ó¥¹¥¿¡¼¤Î ¿§/ʸ»ú ¤ò¥Õ¥¡¥¤¥ë¤Ë½ñ¤­½Ð¤¹", 4, 5);
+       prt("(2) ¥¢¥¤¥Æ¥à¤Î   ¿§/ʸ»ú ¤ò¥Õ¥¡¥¤¥ë¤Ë½ñ¤­½Ð¤¹", 5, 5);
+       prt("(3) ÃÏ·Á¤Î       ¿§/ʸ»ú ¤ò¥Õ¥¡¥¤¥ë¤Ë½ñ¤­½Ð¤¹", 6, 5);
+       prt("(4) ¥â¥ó¥¹¥¿¡¼¤Î ¿§/ʸ»ú ¤òÊѹ¹¤¹¤ë (¿ôÃÍÁàºî)", 7, 5);
+       prt("(5) ¥¢¥¤¥Æ¥à¤Î   ¿§/ʸ»ú ¤òÊѹ¹¤¹¤ë (¿ôÃÍÁàºî)", 8, 5);
+       prt("(6) ÃÏ·Á¤Î       ¿§/ʸ»ú ¤òÊѹ¹¤¹¤ë (¿ôÃÍÁàºî)", 9, 5);
+       prt("(7) ¥â¥ó¥¹¥¿¡¼¤Î ¿§/ʸ»ú ¤òÊѹ¹¤¹¤ë (¥·¥ó¥Ü¥ë¥¨¥Ç¥£¥¿)", 10, 5);
+       prt("(8) ¥¢¥¤¥Æ¥à¤Î   ¿§/ʸ»ú ¤òÊѹ¹¤¹¤ë (¥·¥ó¥Ü¥ë¥¨¥Ç¥£¥¿)", 11, 5);
+       prt("(9) ÃÏ·Á¤Î       ¿§/ʸ»ú ¤òÊѹ¹¤¹¤ë (¥·¥ó¥Ü¥ë¥¨¥Ç¥£¥¿)", 12, 5);
+#else
+       prt("(1) Dump monster attr/chars", 4, 5);
+       prt("(2) Dump object attr/chars", 5, 5);
+       prt("(3) Dump feature attr/chars", 6, 5);
+       prt("(4) Change monster attr/chars (numeric operation)", 7, 5);
+       prt("(5) Change object attr/chars (numeric operation)", 8, 5);
+       prt("(6) Change feature attr/chars (numeric operation)", 9, 5);
+       prt("(7) Change monster attr/chars (visual mode)", 10, 5);
+       prt("(8) Change object attr/chars (visual mode)", 11, 5);
+       prt("(9) Change feature attr/chars (visual mode)", 12, 5);
+#endif
+
+#endif /* ALLOW_VISUALS */
+
+#ifdef JP
+       prt("(R) ²èÌÌɽ¼¨ÊýË¡¤Î½é´ü²½", 13, 5);
+#else
+       prt("(R) Reset visuals", 13, 5);
+#endif
+
+       /* Prompt */
+#ifdef JP
+       prt(format("¥³¥Þ¥ó¥É: %s", choice_msg ? choice_msg : ""), 15, 0);
+#else
+       prt(format("Command: %s", choice_msg ? choice_msg : ""), 15, 0);
+#endif
+}
+
+static void do_cmd_knowledge_monsters(bool *need_redraw, bool visual_only, int direct_r_idx);
+static void do_cmd_knowledge_objects(bool *need_redraw, bool visual_only, int direct_k_idx);
+static void do_cmd_knowledge_features(bool *need_redraw, bool visual_only, int direct_f_idx, int *lighting_level);
+
 /*
  * Interact with "visuals"
  */
 void do_cmd_visuals(void)
 {
        int i;
-
        char tmp[160];
-
        char buf[1024];
-
+       bool need_redraw = FALSE;
        const char *empty_symbol = "<< ? >>";
 
        if (use_bigtile) empty_symbol = "<< ?? >>";
 
-
        /* File type is "TEXT" */
        FILE_TYPE(FILE_TYPE_TEXT);
 
-
        /* Save the screen */
        screen_save();
 
-
        /* Interact until done */
        while (1)
        {
@@ -3646,56 +3698,7 @@ void do_cmd_visuals(void)
                Term_clear();
 
                /* Ask for a choice */
-#ifdef JP
-               prt("²èÌÌɽ¼¨¤ÎÀßÄê", 2, 0);
-#else
-               prt("Interact with Visuals", 2, 0);
-#endif
-
-
-               /* Give some choices */
-#ifdef JP
-               prt("(1) ¥æ¡¼¥¶¡¼ÀßÄê¥Õ¥¡¥¤¥ë¤Î¥í¡¼¥É", 4, 5);
-#else
-               prt("(1) Load a user pref file", 4, 5);
-#endif
-
-#ifdef ALLOW_VISUALS
-#ifdef JP
-               prt("(2) ¥â¥ó¥¹¥¿¡¼¤Î ¿§/ʸ»ú ¤ò¥Õ¥¡¥¤¥ë¤Ë½ñ¤­½Ð¤¹", 5, 5);
-               prt("(3) ¥¢¥¤¥Æ¥à¤Î   ¿§/ʸ»ú ¤ò¥Õ¥¡¥¤¥ë¤Ë½ñ¤­½Ð¤¹", 6, 5);
-               prt("(4) ÃÏ·Á¤Î       ¿§/ʸ»ú ¤ò¥Õ¥¡¥¤¥ë¤Ë½ñ¤­½Ð¤¹", 7, 5);
-               prt("(5) (̤»ÈÍÑ)", 8, 5);
-               prt("(6) ¥â¥ó¥¹¥¿¡¼¤Î ¿§/ʸ»ú ¤òÊѹ¹¤¹¤ë", 9, 5);
-               prt("(7) ¥¢¥¤¥Æ¥à¤Î   ¿§/ʸ»ú ¤òÊѹ¹¤¹¤ë", 10, 5);
-               prt("(8) ÃÏ·Á¤Î       ¿§/ʸ»ú ¤òÊѹ¹¤¹¤ë", 11, 5);
-               prt("(9) (̤»ÈÍÑ)", 12, 5);
-#else
-               prt("(2) Dump monster attr/chars", 5, 5);
-               prt("(3) Dump object attr/chars", 6, 5);
-               prt("(4) Dump feature attr/chars", 7, 5);
-               prt("(5) (unused)", 8, 5);
-               prt("(6) Change monster attr/chars", 9, 5);
-               prt("(7) Change object attr/chars", 10, 5);
-               prt("(8) Change feature attr/chars", 11, 5);
-               prt("(9) (unused)", 12, 5);
-#endif
-
-#endif
-#ifdef JP
-               prt("(0) ²èÌÌɽ¼¨ÊýË¡¤Î½é´ü²½", 13, 5);
-#else
-               prt("(0) Reset visuals", 13, 5);
-#endif
-
-
-               /* Prompt */
-#ifdef JP
-               prt("¥³¥Þ¥ó¥É:", 15, 0);
-#else
-               prt("Command: ", 15, 0);
-#endif
-
+               print_visuals_menu(NULL);
 
                /* Prompt */
                i = inkey();
@@ -3703,9 +3706,10 @@ void do_cmd_visuals(void)
                /* Done */
                if (i == ESCAPE) break;
 
-               /* Load a 'pref' file */
-               else if (i == '1')
+               switch (i)
                {
+               /* Load a 'pref' file */
+               case '0':
                        /* Prompt */
 #ifdef JP
                        prt("¥³¥Þ¥ó¥É: ¥æ¡¼¥¶¡¼ÀßÄê¥Õ¥¡¥¤¥ë¤Î¥í¡¼¥É", 15, 0);
@@ -3713,7 +3717,6 @@ void do_cmd_visuals(void)
                        prt("Command: Load a user pref file", 15, 0);
 #endif
 
-
                        /* Prompt */
 #ifdef JP
                        prt("¥Õ¥¡¥¤¥ë: ", 17, 0);
@@ -3721,7 +3724,6 @@ void do_cmd_visuals(void)
                        prt("File: ", 17, 0);
 #endif
 
-
                        /* Default filename */
                        sprintf(tmp, "%s.prf", player_name);
 
@@ -3730,12 +3732,14 @@ void do_cmd_visuals(void)
 
                        /* Process the given filename */
                        (void)process_pref_file(tmp);
-               }
+
+                       need_redraw = TRUE;
+                       break;
 
 #ifdef ALLOW_VISUALS
 
                /* Dump monster attr/chars */
-               else if (i == '2')
+               case '1':
                {
                        static cptr mark = "Monster attr/chars";
 
@@ -3746,7 +3750,6 @@ void do_cmd_visuals(void)
                        prt("Command: Dump monster attr/chars", 15, 0);
 #endif
 
-
                        /* Prompt */
 #ifdef JP
                        prt("¥Õ¥¡¥¤¥ë: ", 17, 0);
@@ -3754,10 +3757,9 @@ void do_cmd_visuals(void)
                        prt("File: ", 17, 0);
 #endif
 
-
                        /* Default filename */
                        sprintf(tmp, "%s.prf", player_name);
-                       
+
                        /* Get a filename */
                        if (!askfor(tmp, 70)) continue;
 
@@ -3800,10 +3802,11 @@ void do_cmd_visuals(void)
                        msg_print("Dumped monster attr/chars.");
 #endif
 
+                       break;
                }
 
                /* Dump object attr/chars */
-               else if (i == '3')
+               case '2':
                {
                        static cptr mark = "Object attr/chars";
 
@@ -3814,7 +3817,6 @@ void do_cmd_visuals(void)
                        prt("Command: Dump object attr/chars", 15, 0);
 #endif
 
-
                        /* Prompt */
 #ifdef JP
                        prt("¥Õ¥¡¥¤¥ë: ", 17, 0);
@@ -3822,7 +3824,6 @@ void do_cmd_visuals(void)
                        prt("File: ", 17, 0);
 #endif
 
-
                        /* Default filename */
                        sprintf(tmp, "%s.prf", player_name);
 
@@ -3875,10 +3876,11 @@ void do_cmd_visuals(void)
                        msg_print("Dumped object attr/chars.");
 #endif
 
+                       break;
                }
 
                /* Dump feature attr/chars */
-               else if (i == '4')
+               case '3':
                {
                        static cptr mark = "Feature attr/chars";
 
@@ -3889,7 +3891,6 @@ void do_cmd_visuals(void)
                        prt("Command: Dump feature attr/chars", 15, 0);
 #endif
 
-
                        /* Prompt */
 #ifdef JP
                        prt("¥Õ¥¡¥¤¥ë: ", 17, 0);
@@ -3897,7 +3898,6 @@ void do_cmd_visuals(void)
                        prt("File: ", 17, 0);
 #endif
 
-
                        /* Default filename */
                        sprintf(tmp, "%s.prf", player_name);
 
@@ -3949,21 +3949,25 @@ void do_cmd_visuals(void)
                        msg_print("Dumped feature attr/chars.");
 #endif
 
+                       break;
                }
 
-               /* Modify monster attr/chars */
-               else if (i == '6')
+               /* Modify monster attr/chars (numeric operation) */
+               case '4':
                {
+#ifdef JP
+                       static cptr choice_msg = "¥â¥ó¥¹¥¿¡¼¤Î[¿§/ʸ»ú]¤òÊѹ¹¤·¤Þ¤¹";
+#else
+                       static cptr choice_msg = "Change monster attr/chars";
+#endif
                        static int r = 0;
 
-                       /* Prompt */
 #ifdef JP
-                       prt("¥³¥Þ¥ó¥É: ¥â¥ó¥¹¥¿¡¼¤Î[¿§/ʸ»ú]¤òÊѹ¹¤·¤Þ¤¹", 15, 0);
+                       prt(format("¥³¥Þ¥ó¥É: %s", choice_msg), 15, 0);
 #else
-                       prt("Command: Change monster attr/chars", 15, 0);
+                       prt(format("Command: %s", choice_msg), 15, 0);
 #endif
 
-
                        /* Hack -- query until done */
                        while (1)
                        {
@@ -3987,7 +3991,6 @@ void do_cmd_visuals(void)
                                                   r, (r_name + r_ptr->name)));
 #endif
 
-
                                /* Label the Default values */
 #ifdef JP
                                Term_putstr(10, 19, -1, TERM_WHITE,
@@ -4015,10 +4018,10 @@ void do_cmd_visuals(void)
                                /* Prompt */
 #ifdef JP
                                Term_putstr(0, 22, -1, TERM_WHITE,
-                                           "¥³¥Þ¥ó¥É (n/N/^N/a/A/^A/c/C/^C): ");
+                                           "¥³¥Þ¥ó¥É (n/N/^N/a/A/^A/c/C/^C/v/V/^V): ");
 #else
                                Term_putstr(0, 22, -1, TERM_WHITE,
-                                           "Command (n/N/^N/a/A/^A/c/C/^C): ");
+                                           "Command (n/N/^N/a/A/^A/c/C/^C/v/V/^V): ");
 #endif
 
                                /* Get a command */
@@ -4034,35 +4037,60 @@ void do_cmd_visuals(void)
                                switch (c)
                                {
                                case 'n':
-                                       cmd_visuals_aux(i, &r, max_r_idx);
+                                       {
+                                               int prev_r = r;
+                                               do
+                                               {
+                                                       if (!cmd_visuals_aux(i, &r, max_r_idx))
+                                                       {
+                                                               r = prev_r;
+                                                               break;
+                                                       }
+                                               }
+                                               while (!r_info[r].name);
+                                       }
                                        break;
                                case 'a':
                                        t = (int)r_ptr->x_attr;
-                                       cmd_visuals_aux(i, &t, 256);
+                                       (void)cmd_visuals_aux(i, &t, 256);
                                        r_ptr->x_attr = (byte)t;
+                                       need_redraw = TRUE;
                                        break;
                                case 'c':
                                        t = (int)r_ptr->x_char;
-                                       cmd_visuals_aux(i, &t, 256);
+                                       (void)cmd_visuals_aux(i, &t, 256);
                                        r_ptr->x_char = (byte)t;
+                                       need_redraw = TRUE;
+                                       break;
+                               case 'v':
+                                       do_cmd_knowledge_monsters(&need_redraw, TRUE, r);
+
+                                       /* Clear screen */
+                                       Term_clear();
+                                       print_visuals_menu(choice_msg);
                                        break;
                                }
                        }
+
+                       break;
                }
 
-               /* Modify object attr/chars */
-               else if (i == '7')
+               /* Modify object attr/chars (numeric operation) */
+               case '5':
                {
+#ifdef JP
+                       static cptr choice_msg = "¥¢¥¤¥Æ¥à¤Î[¿§/ʸ»ú]¤òÊѹ¹¤·¤Þ¤¹";
+#else
+                       static cptr choice_msg = "Change object attr/chars";
+#endif
                        static int k = 0;
 
-                       /* Prompt */
 #ifdef JP
-                       prt("¥³¥Þ¥ó¥É: ¥¢¥¤¥Æ¥à¤Î[¿§/ʸ»ú]¤òÊѹ¹¤·¤Þ¤¹", 15, 0);
+                       prt(format("¥³¥Þ¥ó¥É: %s", choice_msg), 15, 0);
 #else
-                       prt("Command: Change object attr/chars", 15, 0);
+                       prt(format("Command: %s", choice_msg), 15, 0);
 #endif
 
-
                        /* Hack -- query until done */
                        while (1)
                        {
@@ -4086,7 +4114,6 @@ void do_cmd_visuals(void)
                                                   k, (k_name + k_ptr->name)));
 #endif
 
-
                                /* Label the Default values */
 #ifdef JP
                                Term_putstr(10, 19, -1, TERM_WHITE,
@@ -4114,10 +4141,10 @@ void do_cmd_visuals(void)
                                /* Prompt */
 #ifdef JP
                                Term_putstr(0, 22, -1, TERM_WHITE,
-                                           "¥³¥Þ¥ó¥É (n/N/^N/a/A/^A/c/C/^C): ");
+                                           "¥³¥Þ¥ó¥É (n/N/^N/a/A/^A/c/C/^C/v/V/^V): ");
 #else
                                Term_putstr(0, 22, -1, TERM_WHITE,
-                                           "Command (n/N/^N/a/A/^A/c/C/^C): ");
+                                           "Command (n/N/^N/a/A/^A/c/C/^C/v/V/^V): ");
 #endif
 
                                /* Get a command */
@@ -4133,36 +4160,61 @@ void do_cmd_visuals(void)
                                switch (c)
                                {
                                case 'n':
-                                       cmd_visuals_aux(i, &k, max_k_idx);
+                                       {
+                                               int prev_k = k;
+                                               do
+                                               {
+                                                       if (!cmd_visuals_aux(i, &k, max_k_idx))
+                                                       {
+                                                               k = prev_k;
+                                                               break;
+                                                       }
+                                               }
+                                               while (!k_info[k].name || k_info[k].flavor);
+                                       }
                                        break;
                                case 'a':
                                        t = (int)k_ptr->x_attr;
-                                       cmd_visuals_aux(i, &t, 256);
+                                       (void)cmd_visuals_aux(i, &t, 256);
                                        k_ptr->x_attr = (byte)t;
+                                       need_redraw = TRUE;
                                        break;
                                case 'c':
                                        t = (int)k_ptr->x_char;
-                                       cmd_visuals_aux(i, &t, 256);
+                                       (void)cmd_visuals_aux(i, &t, 256);
                                        k_ptr->x_char = (byte)t;
+                                       need_redraw = TRUE;
+                                       break;
+                               case 'v':
+                                       do_cmd_knowledge_objects(&need_redraw, TRUE, k);
+
+                                       /* Clear screen */
+                                       Term_clear();
+                                       print_visuals_menu(choice_msg);
                                        break;
                                }
                        }
+
+                       break;
                }
 
-               /* Modify feature attr/chars */
-               else if (i == '8')
+               /* Modify feature attr/chars (numeric operation) */
+               case '6':
                {
+#ifdef JP
+                       static cptr choice_msg = "ÃÏ·Á¤Î[¿§/ʸ»ú]¤òÊѹ¹¤·¤Þ¤¹";
+#else
+                       static cptr choice_msg = "Change feature attr/chars";
+#endif
                        static int f = 0;
                        static int lighting_level = F_LIT_STANDARD;
 
-                       /* Prompt */
 #ifdef JP
-                       prt("¥³¥Þ¥ó¥É: ÃÏ·Á¤Î[¿§/ʸ»ú]¤òÊѹ¹¤·¤Þ¤¹", 15, 0);
+                       prt(format("¥³¥Þ¥ó¥É: %s", choice_msg), 15, 0);
 #else
-                       prt("Command: Change feature attr/chars", 15, 0);
+                       prt(format("Command: %s", choice_msg), 15, 0);
 #endif
 
-
                        /* Hack -- query until done */
                        while (1)
                        {
@@ -4187,7 +4239,6 @@ void do_cmd_visuals(void)
                                                   f, (f_name + f_ptr->name), lighting_level_str[lighting_level]));
 #endif
 
-
                                /* Label the Default values */
 #ifdef JP
                                Term_putstr(10, 19, -1, TERM_WHITE,
@@ -4201,7 +4252,6 @@ void do_cmd_visuals(void)
 
                                Term_queue_bigchar(43, 19, da, dc, 0, 0);
 
-
                                /* Label the Current values */
 #ifdef JP
                                Term_putstr(10, 20, -1, TERM_WHITE,
@@ -4217,10 +4267,10 @@ void do_cmd_visuals(void)
                                /* Prompt */
 #ifdef JP
                                Term_putstr(0, 22, -1, TERM_WHITE,
-                                           "¥³¥Þ¥ó¥É (n/N/^N/a/A/^A/c/C/^C/l/L/^L/d/D/^D): ");
+                                           "¥³¥Þ¥ó¥É (n/N/^N/a/A/^A/c/C/^C/l/L/^L/d/D/^D/v/V/^V): ");
 #else
                                Term_putstr(0, 22, -1, TERM_WHITE,
-                                           "Command (n/N/^N/a/A/^A/c/C/^C/l/L/^L/d/D/^D): ");
+                                           "Command (n/N/^N/a/A/^A/c/C/^C/l/L/^L/d/D/^D/v/V/^V): ");
 #endif
 
                                /* Get a command */
@@ -4236,33 +4286,74 @@ void do_cmd_visuals(void)
                                switch (c)
                                {
                                case 'n':
-                                       cmd_visuals_aux(i, &f, max_f_idx);
+                                       {
+                                               int prev_f = f;
+                                               do
+                                               {
+                                                       if (!cmd_visuals_aux(i, &f, max_f_idx))
+                                                       {
+                                                               f = prev_f;
+                                                               break;
+                                                       }
+                                               }
+                                               while (!f_info[f].name || (f_info[f].mimic != f));
+                                       }
                                        break;
                                case 'a':
                                        t = (int)f_ptr->x_attr[lighting_level];
-                                       cmd_visuals_aux(i, &t, 256);
+                                       (void)cmd_visuals_aux(i, &t, 256);
                                        f_ptr->x_attr[lighting_level] = (byte)t;
+                                       need_redraw = TRUE;
                                        break;
                                case 'c':
                                        t = (int)f_ptr->x_char[lighting_level];
-                                       cmd_visuals_aux(i, &t, 256);
+                                       (void)cmd_visuals_aux(i, &t, 256);
                                        f_ptr->x_char[lighting_level] = (byte)t;
+                                       need_redraw = TRUE;
                                        break;
                                case 'l':
-                                       cmd_visuals_aux(i, &lighting_level, F_LIT_MAX);
+                                       (void)cmd_visuals_aux(i, &lighting_level, F_LIT_MAX);
                                        break;
                                case 'd':
                                        apply_default_feat_lighting(f_ptr->x_attr, f_ptr->x_char);
+                                       need_redraw = TRUE;
+                                       break;
+                               case 'v':
+                                       do_cmd_knowledge_features(&need_redraw, TRUE, f, &lighting_level);
+
+                                       /* Clear screen */
+                                       Term_clear();
+                                       print_visuals_menu(choice_msg);
                                        break;
                                }
                        }
+
+                       break;
                }
 
-#endif
+               /* Modify monster attr/chars (visual mode) */
+               case '7':
+                       do_cmd_knowledge_monsters(&need_redraw, TRUE, -1);
+                       break;
 
-               /* Reset visuals */
-               else if (i == '0')
+               /* Modify object attr/chars (visual mode) */
+               case '8':
+                       do_cmd_knowledge_objects(&need_redraw, TRUE, -1);
+                       break;
+
+               /* Modify feature attr/chars (visual mode) */
+               case '9':
                {
+                       int lighting_level = F_LIT_STANDARD;
+                       do_cmd_knowledge_features(&need_redraw, TRUE, -1, &lighting_level);
+                       break;
+               }
+
+#endif /* ALLOW_VISUALS */
+
+               /* Reset visuals */
+               case 'R':
+               case 'r':
                        /* Reset */
                        reset_visuals();
 
@@ -4273,21 +4364,23 @@ void do_cmd_visuals(void)
                        msg_print("Visual attr/char tables reset.");
 #endif
 
-               }
+                       need_redraw = TRUE;
+                       break;
 
                /* Unknown option */
-               else
-               {
+               default:
                        bell();
+                       break;
                }
 
                /* Flush messages */
                msg_print(NULL);
        }
 
-
        /* Restore the screen */
        screen_load();
+
+       if (need_redraw) do_cmd_redraw();
 }
 
 
@@ -4957,6 +5050,7 @@ static cptr monster_group_text[] =
        "ÊÉ/¿¢Êª/µ¤ÂÎ",
        "¤ª¤Ð¤±¥­¥Î¥³",
        "µåÂÎ",
+       "¥×¥ì¥¤¥ä¡¼",
 #else
        "Uniques",
        "Ridable monsters",
@@ -5015,6 +5109,7 @@ static cptr monster_group_text[] =
        "Wall/Plant/Gas",
        "Mushroom patch",
        "Ball",
+       "Player",
 #endif
        NULL
 };
@@ -5083,6 +5178,7 @@ static cptr monster_group_char[] =
        "#",
        ",",
        "*",
+       "@",
        NULL
 };
 
@@ -5116,7 +5212,7 @@ static bool ang_sort_comp_monster_level(vptr u, vptr v, int a, int b)
  * of monsters in the group.
  *
  * mode & 0x01 : check for non-empty group
- * mode & 0x02 : cheat?
+ * mode & 0x02 : visual operation only
  */
 static int collect_monsters(int grp_cur, s16b mon_idx[], byte mode)
 {
@@ -5142,7 +5238,7 @@ static int collect_monsters(int grp_cur, s16b mon_idx[], byte mode)
                if (!r_ptr->name) continue ;
 
                /* Require known monsters */
-               if (!(mode & 0x02) && !cheat_know && !r_ptr->r_sights ) continue;
+               if (!(mode & 0x02) && !cheat_know && !r_ptr->r_sights) continue;
 
                if (grp_unique)
                {
@@ -5168,7 +5264,7 @@ static int collect_monsters(int grp_cur, s16b mon_idx[], byte mode)
        }
 
        /* Terminate the list */
-       mon_idx[mon_cnt] = 0;
+       mon_idx[mon_cnt] = -1;
 
        /* Select the sort method */
        ang_sort_comp = ang_sort_comp_monster_level;
@@ -5227,6 +5323,7 @@ static cptr object_group_text[] =
        "´§",   /* "Crowns" */
        "¥Ö¡¼¥Ä",       /* "Boots" */
        "ËâË¡½ñ",
+       "²¿¤«",
 #else
        "Mushrooms",
        "Potions",
@@ -5267,6 +5364,7 @@ static cptr object_group_text[] =
        "Crowns",
        "Boots",
        "Spellbooks",
+       "Something",
 #endif
        NULL
 };
@@ -5316,15 +5414,19 @@ static byte object_group_tval[] =
        TV_CROWN,
        TV_BOOTS,
        TV_LIFE_BOOK, /* Hack -- all spellbooks */
-       0
+       0,
+       0,
 };
 
 
 /*
- * Build a list of monster indexes in the given group. Return the number
- * of monsters in the group.
+ * Build a list of object indexes in the given group. Return the number
+ * of objects in the group.
+ *
+ * mode & 0x01 : check for non-empty group
+ * mode & 0x02 : visual operation only
  */
-static int collect_objects(int grp_cur, int object_idx[])
+static int collect_objects(int grp_cur, int object_idx[], byte mode)
 {
        int i, j, k, object_cnt = 0;
 
@@ -5334,43 +5436,58 @@ static int collect_objects(int grp_cur, int object_idx[])
        /* Check every object */
        for (i = 0; i < max_k_idx; i++)
        {
-               /* Access the race */
+               /* Access the object */
                object_kind *k_ptr = &k_info[i];
 
                /* Skip empty objects */
                if (!k_ptr->name) continue;
 
-               /* Skip non-flavoured objects */
-               if (!k_ptr->flavor && !p_ptr->wizard) continue;
+               if (mode & 0x02)
+               {
+                       if (k_ptr->flavor) continue;
+               }
+               else
+               {
+                       if (!p_ptr->wizard)
+                       {
+                               /* Skip non-flavoured objects */
+                               if (!k_ptr->flavor) continue;
 
-               /* Skip items with no distribution (special artifacts) */
-               for (j = 0, k = 0; j < 4; j++) k += k_ptr->chance[j];
-               if (!(k))  continue; 
+                               /* Require objects ever seen */
+                               if (!k_ptr->aware) continue;
+                       }
 
-               /* Require objects ever seen*/
-               if (!k_ptr->aware && !p_ptr->wizard) continue;
+                       /* Skip items with no distribution (special artifacts) */
+                       for (j = 0, k = 0; j < 4; j++) k += k_ptr->chance[j];
+                       if (!k) continue;
+               }
 
-               /* Check for race in the group */
+               /* Check for objects in the group */
                if (TV_LIFE_BOOK == group_tval)
                {
                        /* Hack -- All spell books */
                        if (TV_LIFE_BOOK <= k_ptr->tval && k_ptr->tval <= TV_HISSATSU_BOOK)
                        {
-                               /* Add the race */
+                               /* Add the object */
                                object_idx[object_cnt++] = i;
                        }
+                       else continue;
                }
                else if (k_ptr->tval == group_tval)
                {
-                       /* Add the race */
+                       /* Add the object */
                        object_idx[object_cnt++] = i;
                }
+               else continue;
+
+               /* XXX Hack -- Just checking for non-empty group */
+               if (mode & 0x01) break;
        }
 
        /* Terminate the list */
-       object_idx[object_cnt] = 0;
+       object_idx[object_cnt] = -1;
 
-       /* Return the number of races */
+       /* Return the number of objects */
        return object_cnt;
 }
 
@@ -5388,8 +5505,10 @@ static cptr feature_group_text[] =
 /*
  * Build a list of feature indexes in the given group. Return the number
  * of features in the group.
+ *
+ * mode & 0x01 : check for non-empty group
  */
-static int collect_features(int grp_cur, int *feat_idx)
+static int collect_features(int grp_cur, int *feat_idx, byte mode)
 {
        int i, feat_cnt = 0;
 
@@ -5397,7 +5516,7 @@ static int collect_features(int grp_cur, int *feat_idx)
        (void)grp_cur;
 
        /* Check every feature */
-       for (i = 1; i < max_f_idx; i++)
+       for (i = 0; i < max_f_idx; i++)
        {
                /* Access the index */
                feature_type *f_ptr = &f_info[i];
@@ -5410,10 +5529,13 @@ static int collect_features(int grp_cur, int *feat_idx)
 
                /* Add the index */
                feat_idx[feat_cnt++] = i;
+
+               /* XXX Hack -- Just checking for non-empty group */
+               if (mode & 0x01) break;
        }
 
        /* Terminate the list */
-       feat_idx[feat_cnt] = 0;
+       feat_idx[feat_cnt] = -1;
 
        /* Return the number of races */
        return feat_cnt;
@@ -7498,12 +7620,12 @@ static bool visual_mode_command(char ch, bool *visual_list_ptr,
  * Display the monsters in a group.
  */
 static void display_monster_list(int col, int row, int per_page, s16b mon_idx[],
-       int mon_cur, int mon_top)
+       int mon_cur, int mon_top, bool visual_only)
 {
        int i;
 
        /* Display lines until done */
-       for (i = 0; i < per_page && mon_idx[mon_top + i]; i++)
+       for (i = 0; i < per_page && (mon_idx[mon_top + i] >= 0); i++)
        {
                byte attr;
 
@@ -7513,7 +7635,6 @@ static void display_monster_list(int col, int row, int per_page, s16b mon_idx[],
                /* Access the race */
                monster_race *r_ptr = &r_info[r_idx];
 
-
                /* Choose a color */
                attr = ((i + mon_top == mon_cur) ? TERM_L_BLUE : TERM_WHITE);
 
@@ -7523,28 +7644,29 @@ static void display_monster_list(int col, int row, int per_page, s16b mon_idx[],
                /* Hack -- visual_list mode */
                if (per_page == 1)
                {
-                       c_prt(attr, format("%02x/%02x", r_ptr->x_attr, r_ptr->x_char), row + i, 60);
+                       c_prt(attr, format("%02x/%02x", r_ptr->x_attr, r_ptr->x_char), row + i, (p_ptr->wizard || visual_only) ? 56 : 61);
                }
-               else if (p_ptr->wizard) 
+               if (p_ptr->wizard || visual_only)
                {
-                       c_prt(attr, format("%d", r_idx), row + i, 60);
+                       c_prt(attr, format("%d", r_idx), row + i, 62);
                }
 
                /* Erase chars before overwritten by the race letter */
                Term_erase(69, row + i, 255);
 
                /* Display symbol */
-               Term_queue_bigchar(70, row + i, r_ptr->x_attr, r_ptr->x_char, 0, 0);
+               Term_queue_bigchar(use_bigtile ? 69 : 70, row + i, r_ptr->x_attr, r_ptr->x_char, 0, 0);
 
-
-               /* Display kills */
-               if (!(r_ptr->flags1 & RF1_UNIQUE)) put_str(format("%5d", r_ptr->r_pkills), row + i, 73);
+               if (!visual_only)
+               {
+                       /* Display kills */
+                       if (!(r_ptr->flags1 & RF1_UNIQUE)) put_str(format("%5d", r_ptr->r_pkills), row + i, 73);
 #ifdef JP
-               else c_put_str((r_ptr->max_num == 0 ? TERM_L_DARK : TERM_WHITE), (r_ptr->max_num == 0 ? "»àË´" : "À¸Â¸"), row + i, 73);
+                       else c_put_str((r_ptr->max_num == 0 ? TERM_L_DARK : TERM_WHITE), (r_ptr->max_num == 0 ? "»àË´" : "À¸Â¸"), row + i, 74);
 #else
-               else c_put_str((r_ptr->max_num == 0 ? TERM_L_DARK : TERM_WHITE), (r_ptr->max_num == 0 ? "dead" : "alive"), row + i, 73);
+                       else c_put_str((r_ptr->max_num == 0 ? TERM_L_DARK : TERM_WHITE), (r_ptr->max_num == 0 ? " dead" : "alive"), row + i, 73);
 #endif
-       
+               }
        }
 
        /* Clear remaining lines */
@@ -7558,7 +7680,7 @@ static void display_monster_list(int col, int row, int per_page, s16b mon_idx[],
 /*
  * Display known monsters.
  */
-static void do_cmd_knowledge_monsters(bool *need_redraw)
+static void do_cmd_knowledge_monsters(bool *need_redraw, bool visual_only, int direct_r_idx)
 {
        int i, len, max;
        int grp_cur, grp_top, old_grp_cur;
@@ -7577,6 +7699,8 @@ static void do_cmd_knowledge_monsters(bool *need_redraw)
        int browser_rows;
        int wid, hgt;
 
+       byte mode;
+
        /* Get size */
        Term_get_size(&wid, &hgt);
 
@@ -7588,21 +7712,39 @@ static void do_cmd_knowledge_monsters(bool *need_redraw)
        max = 0;
        grp_cnt = 0;
 
-       /* Check every group */
-       for (i = 0; monster_group_text[i] != NULL; i++)
+       if (direct_r_idx < 0)
        {
-               /* Measure the label */
-               len = strlen(monster_group_text[i]);
+               mode = visual_only ? 0x03 : 0x01;
 
-               /* Save the maximum length */
-               if (len > max) max = len;
-
-               /* See if any monsters are known */
-               if ((monster_group_char[i] == ((char *) -1L)) || collect_monsters(i, mon_idx, 0x01))
+               /* Check every group */
+               for (i = 0; monster_group_text[i] != NULL; i++)
                {
-                       /* Build a list of groups with known monsters */
-                       grp_idx[grp_cnt++] = i;
+                       /* Measure the label */
+                       len = strlen(monster_group_text[i]);
+
+                       /* Save the maximum length */
+                       if (len > max) max = len;
+
+                       /* See if any monsters are known */
+                       if ((monster_group_char[i] == ((char *) -1L)) || collect_monsters(i, mon_idx, mode))
+                       {
+                               /* Build a list of groups with known monsters */
+                               grp_idx[grp_cnt++] = i;
+                       }
                }
+
+               mon_cnt = 0;
+       }
+       else
+       {
+               mon_idx[0] = direct_r_idx;
+               mon_cnt = 1;
+
+               /* Terminate the list */
+               mon_idx[1] = -1;
+
+               (void)visual_mode_command('v', &visual_list, browser_rows - 1, wid - (max + 3),
+                       &attr_top, &char_left, &r_info[direct_r_idx].x_attr, &r_info[direct_r_idx].x_char, need_redraw);
        }
 
        /* Terminate the list */
@@ -7611,11 +7753,12 @@ static void do_cmd_knowledge_monsters(bool *need_redraw)
        old_grp_cur = -1;
        grp_cur = grp_top = 0;
        mon_cur = mon_top = 0;
-       mon_cnt = 0;
 
        flag = FALSE;
        redraw = TRUE;
 
+       mode = visual_only ? 0x02 : 0x00;
+
        while (!flag)
        {
                char ch;
@@ -7624,19 +7767,21 @@ static void do_cmd_knowledge_monsters(bool *need_redraw)
                if (redraw)
                {
                        clear_from(0);
-               
+
 #ifdef JP
-                       prt("Ãμ± - ¥â¥ó¥¹¥¿¡¼", 2, 0);
-                       prt("¥°¥ë¡¼¥×", 4, 0);
+                       prt(format("%s - ¥â¥ó¥¹¥¿¡¼", !visual_only ? "Ãμ±" : "ɽ¼¨"), 2, 0);
+                       if (direct_r_idx < 0) prt("¥°¥ë¡¼¥×", 4, 0);
                        prt("̾Á°", 4, max + 3);
-                       if (p_ptr->wizard) prt("Idx", 4, 60);
-                       prt("ʸ»ú »¦³²¿ô", 4, 67);
+                       if (p_ptr->wizard || visual_only) prt("Idx", 4, 62);
+                       prt("ʸ»ú", 4, 67);
+                       if (!visual_only) prt("»¦³²¿ô", 4, 72);
 #else
-                       prt("Knowledge - Monsters", 2, 0);
-                       prt("Group", 4, 0);
+                       prt(format("%s - monsters", !visual_only ? "Knowledge" : "Visuals"), 2, 0);
+                       if (direct_r_idx < 0) prt("Group", 4, 0);
                        prt("Name", 4, max + 3);
-                       if (p_ptr->wizard) prt("Idx", 4, 60);
-                       prt("Sym   Kills", 4, 67);
+                       if (p_ptr->wizard || visual_only) prt("Idx", 4, 62);
+                       prt("Sym  ", 4, 67);
+                       if (!visual_only) prt(" Kills", 4, 72);
 #endif
 
                        for (i = 0; i < 78; i++)
@@ -7644,46 +7789,52 @@ static void do_cmd_knowledge_monsters(bool *need_redraw)
                                Term_putch(i, 5, TERM_WHITE, '=');
                        }
 
-                       for (i = 0; i < browser_rows; i++)
+                       if (direct_r_idx < 0)
                        {
-                               Term_putch(max + 1, 6 + i, TERM_WHITE, '|');
+                               for (i = 0; i < browser_rows; i++)
+                               {
+                                       Term_putch(max + 1, 6 + i, TERM_WHITE, '|');
+                               }
                        }
 
                        redraw = FALSE;
                }
 
-               /* Scroll group list */
-               if (grp_cur < grp_top) grp_top = grp_cur;
-               if (grp_cur >= grp_top + browser_rows) grp_top = grp_cur - browser_rows + 1;
+               if (direct_r_idx < 0)
+               {
+                       /* Scroll group list */
+                       if (grp_cur < grp_top) grp_top = grp_cur;
+                       if (grp_cur >= grp_top + browser_rows) grp_top = grp_cur - browser_rows + 1;
 
-               /* Display a list of monster groups */
-               display_group_list(0, 6, max, browser_rows, grp_idx, monster_group_text, grp_cur, grp_top);
+                       /* Display a list of monster groups */
+                       display_group_list(0, 6, max, browser_rows, grp_idx, monster_group_text, grp_cur, grp_top);
 
-               if (old_grp_cur != grp_cur)
-               {
-                       old_grp_cur = grp_cur;
+                       if (old_grp_cur != grp_cur)
+                       {
+                               old_grp_cur = grp_cur;
 
-                       /* Get a list of monsters in the current group */
-                       mon_cnt = collect_monsters(grp_idx[grp_cur], mon_idx, 0x00);
-               }
+                               /* Get a list of monsters in the current group */
+                               mon_cnt = collect_monsters(grp_idx[grp_cur], mon_idx, mode);
+                       }
 
-               /* Scroll monster list */
-               while (mon_cur < mon_top)
-                       mon_top = MAX(0, mon_top - browser_rows/2);
-               while (mon_cur >= mon_top + browser_rows)
-                       mon_top = MIN(mon_cnt - browser_rows, mon_top + browser_rows/2);
+                       /* Scroll monster list */
+                       while (mon_cur < mon_top)
+                               mon_top = MAX(0, mon_top - browser_rows/2);
+                       while (mon_cur >= mon_top + browser_rows)
+                               mon_top = MIN(mon_cnt - browser_rows, mon_top + browser_rows/2);
+               }
 
                if (!visual_list)
                {
                        /* Display a list of monsters in the current group */
-                       display_monster_list(max + 3, 6, browser_rows, mon_idx, mon_cur, mon_top);
+                       display_monster_list(max + 3, 6, browser_rows, mon_idx, mon_cur, mon_top, visual_only);
                }
                else
                {
                        mon_top = mon_cur;
 
                        /* Display a monster name */
-                       display_monster_list(max + 3, 6, 1, mon_idx, mon_cur, mon_top);
+                       display_monster_list(max + 3, 6, 1, mon_idx, mon_cur, mon_top, visual_only);
 
                        /* Display visual list below first monster */
                        display_visual_list(max + 3, 7, browser_rows-1, wid - (max + 3), attr_top, char_left);
@@ -7691,19 +7842,30 @@ static void do_cmd_knowledge_monsters(bool *need_redraw)
 
                /* Prompt */
 #ifdef JP
-               prt(format("<Êý¸þ>, 'r'¤Ç»×¤¤½Ð¤ò¸«¤ë%s%s, ESC", visual_list ? ", ENTER¤Ç·èÄê" : ", 'v'¤Ç¥·¥ó¥Ü¥ëÊѹ¹", (attr_idx||char_idx) ? ", 'c', 'p'¤Ç¥Ú¡¼¥¹¥È" : ", 'c'¤Ç¥³¥Ô¡¼"), hgt - 1, 0);
+               prt(format("<Êý¸þ>%s%s%s, ESC",
+                       (!visual_list && !visual_only) ? ", 'r'¤Ç»×¤¤½Ð¤ò¸«¤ë" : "",
+                       visual_list ? ", ENTER¤Ç·èÄê" : ", 'v'¤Ç¥·¥ó¥Ü¥ëÊѹ¹",
+                       (attr_idx || char_idx) ? ", 'c', 'p'¤Ç¥Ú¡¼¥¹¥È" : ", 'c'¤Ç¥³¥Ô¡¼"),
+                       hgt - 1, 0);
 #else
-               prt(format("<dir>, 'r' to recall%s%s, ESC", visual_list ? ", ENTER to accept" : ", 'v' for visuals", (attr_idx||char_idx) ? ", 'c', 'p' to paste" : ", 'c' to copy"), hgt - 1, 0);
+               prt(format("<dir>%s%s%s, ESC",
+                       (!visual_list && !visual_only) ? ", 'r' to recall" : "",
+                       visual_list ? ", ENTER to accept" : ", 'v' for visuals",
+                       (attr_idx || char_idx) ? ", 'c', 'p' to paste" : ", 'c' to copy"),
+                       hgt - 1, 0);
 #endif
 
                /* Get the current monster */
                r_ptr = &r_info[mon_idx[mon_cur]];
 
-               /* Mega Hack -- track this monster race */
-               if (mon_cnt) monster_race_track(mon_idx[mon_cur]);
+               if (!visual_only)
+               {
+                       /* Mega Hack -- track this monster race */
+                       if (mon_cnt) monster_race_track(mon_idx[mon_cur]);
 
-               /* Hack -- handle stuff */
-               handle_stuff();
+                       /* Hack -- handle stuff */
+                       handle_stuff();
+               }
 
                if (visual_list)
                {
@@ -7721,7 +7883,21 @@ static void do_cmd_knowledge_monsters(bool *need_redraw)
                ch = inkey();
 
                /* Do visual mode command if needed */
-               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)) continue;
+               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))
+               {
+                       if (direct_r_idx >= 0)
+                       {
+                               switch (ch)
+                               {
+                               case '\n':
+                               case '\r':
+                               case ESCAPE:
+                                       flag = TRUE;
+                                       break;
+                               }
+                       }
+                       continue;
+               }
 
                switch (ch)
                {
@@ -7735,12 +7911,12 @@ static void do_cmd_knowledge_monsters(bool *need_redraw)
                        case 'r':
                        {
                                /* Recall on screen */
-                               if (mon_idx[mon_cur])
+                               if (!visual_list && !visual_only && (mon_idx[mon_cur] > 0))
                                {
                                        screen_roff(mon_idx[mon_cur], 0);
 
                                        (void)inkey();
-       
+
                                        redraw = TRUE;
                                }
                                break;
@@ -7765,12 +7941,12 @@ static void do_cmd_knowledge_monsters(bool *need_redraw)
  * Display the objects in a group.
  */
 static void display_object_list(int col, int row, int per_page, int object_idx[],
-       int object_cur, int object_top)
+       int object_cur, int object_top, bool visual_only)
 {
        int i;
 
        /* Display lines until done */
-       for (i = 0; i < per_page && object_idx[object_top + i]; i++)
+       for (i = 0; i < per_page && (object_idx[object_top + i] >= 0); i++)
        {
                char o_name[80];
                byte a, c;
@@ -7782,11 +7958,11 @@ static void display_object_list(int col, int row, int per_page, int object_idx[]
                object_kind *k_ptr = &k_info[k_idx];
 
                /* Choose a color */
-               byte attr = (k_ptr->aware ? TERM_WHITE : TERM_SLATE);
-               byte cursor = (k_ptr->aware ? TERM_L_BLUE : TERM_BLUE);
+               byte attr = ((k_ptr->aware || visual_only) ? TERM_WHITE : TERM_SLATE);
+               byte cursor = ((k_ptr->aware || visual_only) ? TERM_L_BLUE : TERM_BLUE);
 
                attr = ((i + object_top == object_cur) ? cursor : attr);
-               
+
                /* Tidy name */
                strip_name(o_name, k_idx);
 
@@ -7796,17 +7972,17 @@ static void display_object_list(int col, int row, int per_page, int object_idx[]
                /* Hack -- visual_list mode */
                if (per_page == 1)
                {
-                       c_prt(attr, format("%02x/%02x", k_ptr->x_attr, k_ptr->x_char), row + i, 60);
+                       c_prt(attr, format("%02x/%02x", k_ptr->x_attr, k_ptr->x_char), row + i, (p_ptr->wizard || visual_only) ? 64 : 68);
                }
-               else if (p_ptr->wizard)
+               if (p_ptr->wizard || visual_only)
                {
-                       c_prt(attr, format ("%d", k_idx), row + i, 70);
+                       c_prt(attr, format("%d", k_idx), row + i, 70);
                }
 
                a = k_ptr->flavor ? misc_to_attr[k_ptr->flavor] : k_ptr->x_attr;
                c = k_ptr->flavor ? misc_to_char[k_ptr->flavor] : k_ptr->x_char;
 
-               /* Symbol is unknown */ 
+               /* Symbol is unknown */
                if (!k_ptr->aware && !p_ptr->wizard)
                {
                        c = ' ';
@@ -7814,7 +7990,7 @@ static void display_object_list(int col, int row, int per_page, int object_idx[]
                }
 
                /* Display symbol */
-               Term_queue_bigchar(76, row + i, a, c, 0, 0);
+               Term_queue_bigchar(use_bigtile ? 76 : 77, row + i, a, c, 0, 0);
        }
 
        /* Clear remaining lines */
@@ -7869,7 +8045,7 @@ static void desc_obj_fake(int k_idx)
 /*
  * Display known objects
  */
-static void do_cmd_knowledge_objects(bool *need_redraw)
+static void do_cmd_knowledge_objects(bool *need_redraw, bool visual_only, int direct_k_idx)
 {
        int i, len, max;
        int grp_cur, grp_top, old_grp_cur;
@@ -7888,6 +8064,8 @@ static void do_cmd_knowledge_objects(bool *need_redraw)
        int browser_rows;
        int wid, hgt;
 
+       byte mode;
+
        /* Get size */
        Term_get_size(&wid, &hgt);
 
@@ -7899,21 +8077,41 @@ static void do_cmd_knowledge_objects(bool *need_redraw)
        max = 0;
        grp_cnt = 0;
 
-       /* Check every group */
-       for (i = 0; object_group_text[i] != NULL; i++)
+       if (direct_k_idx < 0)
        {
-               /* Measure the label */
-               len = strlen(object_group_text[i]);
+               mode = visual_only ? 0x03 : 0x01;
 
-               /* Save the maximum length */
-               if (len > max) max = len;
-
-               /* See if any monsters are known */
-               if (collect_objects(i, object_idx))
+               /* Check every group */
+               for (i = 0; object_group_text[i] != NULL; i++)
                {
-                       /* Build a list of groups with known monsters */
-                       grp_idx[grp_cnt++] = i;
+                       /* Measure the label */
+                       len = strlen(object_group_text[i]);
+
+                       /* Save the maximum length */
+                       if (len > max) max = len;
+
+                       /* See if any monsters are known */
+                       if (collect_objects(i, object_idx, mode))
+                       {
+                               /* Build a list of groups with known monsters */
+                               grp_idx[grp_cnt++] = i;
+                       }
                }
+
+               object_old = -1;
+               object_cnt = 0;
+       }
+       else
+       {
+               object_idx[0] = direct_k_idx;
+               object_old = direct_k_idx;
+               object_cnt = 1;
+
+               /* Terminate the list */
+               object_idx[1] = -1;
+
+               (void)visual_mode_command('v', &visual_list, browser_rows - 1, wid - (max + 3),
+                       &attr_top, &char_left, &k_info[direct_k_idx].x_attr, &k_info[direct_k_idx].x_char, need_redraw);
        }
 
        /* Terminate the list */
@@ -7922,12 +8120,12 @@ static void do_cmd_knowledge_objects(bool *need_redraw)
        old_grp_cur = -1;
        grp_cur = grp_top = 0;
        object_cur = object_top = 0;
-       object_old = -1;
-       object_cnt = 0;
 
        flag = FALSE;
        redraw = TRUE;
 
+       mode = visual_only ? 0x02 : 0x00;
+
        while (!flag)
        {
                char ch;
@@ -7936,18 +8134,18 @@ static void do_cmd_knowledge_objects(bool *need_redraw)
                if (redraw)
                {
                        clear_from(0);
-               
+
 #ifdef JP
-                       prt("Ãμ± - ¥¢¥¤¥Æ¥à", 2, 0);
-                       prt("¥°¥ë¡¼¥×", 4, 0);
+                       prt(format("%s - ¥¢¥¤¥Æ¥à", !visual_only ? "Ãμ±" : "ɽ¼¨"), 2, 0);
+                       if (direct_k_idx < 0) prt("¥°¥ë¡¼¥×", 4, 0);
                        prt("̾Á°", 4, max + 3);
-                       if (p_ptr->wizard) prt("Idx", 4, 70);
-                       prt("ʸ»ú", 4, 75);
+                       if (p_ptr->wizard || visual_only) prt("Idx", 4, 70);
+                       prt("ʸ»ú", 4, 74);
 #else
-                       prt("Knowledge - objects", 2, 0);
-                       prt("Group", 4, 0);
+                       prt(format("%s - objects", !visual_only ? "Knowledge" : "Visuals"), 2, 0);
+                       if (direct_k_idx < 0) prt("Group", 4, 0);
                        prt("Name", 4, max + 3);
-                       if (p_ptr->wizard) prt("Idx", 4, 70);
+                       if (p_ptr->wizard || visual_only) prt("Idx", 4, 70);
                        prt("Sym", 4, 75);
 #endif
 
@@ -7956,46 +8154,52 @@ static void do_cmd_knowledge_objects(bool *need_redraw)
                                Term_putch(i, 5, TERM_WHITE, '=');
                        }
 
-                       for (i = 0; i < browser_rows; i++)
+                       if (direct_k_idx < 0)
                        {
-                               Term_putch(max + 1, 6 + i, TERM_WHITE, '|');
+                               for (i = 0; i < browser_rows; i++)
+                               {
+                                       Term_putch(max + 1, 6 + i, TERM_WHITE, '|');
+                               }
                        }
 
                        redraw = FALSE;
                }
 
-               /* Scroll group list */
-               if (grp_cur < grp_top) grp_top = grp_cur;
-               if (grp_cur >= grp_top + browser_rows) grp_top = grp_cur - browser_rows + 1;
+               if (direct_k_idx < 0)
+               {
+                       /* Scroll group list */
+                       if (grp_cur < grp_top) grp_top = grp_cur;
+                       if (grp_cur >= grp_top + browser_rows) grp_top = grp_cur - browser_rows + 1;
 
-               /* Display a list of object groups */
-               display_group_list(0, 6, max, browser_rows, grp_idx, object_group_text, grp_cur, grp_top);
+                       /* Display a list of object groups */
+                       display_group_list(0, 6, max, browser_rows, grp_idx, object_group_text, grp_cur, grp_top);
 
-               if (old_grp_cur != grp_cur)
-               {
-                       old_grp_cur = grp_cur;
+                       if (old_grp_cur != grp_cur)
+                       {
+                               old_grp_cur = grp_cur;
 
-                       /* Get a list of objects in the current group */
-                       object_cnt = collect_objects(grp_idx[grp_cur], object_idx);
-               }
+                               /* Get a list of objects in the current group */
+                               object_cnt = collect_objects(grp_idx[grp_cur], object_idx, mode);
+                       }
 
-               /* Scroll object list */
-               while (object_cur < object_top)
-                       object_top = MAX(0, object_top - browser_rows/2);
-               while (object_cur >= object_top + browser_rows)
-                       object_top = MIN(object_cnt - browser_rows, object_top + browser_rows/2);
+                       /* Scroll object list */
+                       while (object_cur < object_top)
+                               object_top = MAX(0, object_top - browser_rows/2);
+                       while (object_cur >= object_top + browser_rows)
+                               object_top = MIN(object_cnt - browser_rows, object_top + browser_rows/2);
+               }
 
                if (!visual_list)
                {
                        /* Display a list of objects in the current group */
-                       display_object_list(max + 3, 6, browser_rows, object_idx, object_cur, object_top);
+                       display_object_list(max + 3, 6, browser_rows, object_idx, object_cur, object_top, visual_only);
                }
                else
                {
                        object_top = object_cur;
 
                        /* Display a list of objects in the current group */
-                       display_object_list(max + 3, 6, 1, object_idx, object_cur, object_top);
+                       display_object_list(max + 3, 6, 1, object_idx, object_cur, object_top, visual_only);
 
                        /* Display visual list below first object */
                        display_visual_list(max + 3, 7, browser_rows-1, wid - (max + 3), attr_top, char_left);
@@ -8004,24 +8208,35 @@ static void do_cmd_knowledge_objects(bool *need_redraw)
                /* Get the current object */
                k_ptr = &k_info[object_idx[object_cur]];
 
-               /* Mega Hack -- track this object */
-               if (object_cnt) object_kind_track(object_idx[object_cur]);
-
                /* Prompt */
 #ifdef JP
-               prt(format("<Êý¸þ>, 'r'¤Ç¾ÜºÙ¤ò¸«¤ë%s%s, ESC", k_ptr->flavor ? "" : visual_list ? ", ENTER¤Ç·èÄê" : ", 'v'¤Ç¥·¥ó¥Ü¥ëÊѹ¹", (attr_idx||char_idx) ? ", 'c', 'p'¤Ç¥Ú¡¼¥¹¥È" : ", 'c'¤Ç¥³¥Ô¡¼"), hgt - 1, 0);
+               prt(format("<Êý¸þ>%s%s%s, ESC",
+                       (!visual_list && !visual_only) ? ", 'r'¤Ç¾ÜºÙ¤ò¸«¤ë" : "",
+                       k_ptr->flavor ? "" : visual_list ? ", ENTER¤Ç·èÄê" : ", 'v'¤Ç¥·¥ó¥Ü¥ëÊѹ¹",
+                       (attr_idx || char_idx) ? ", 'c', 'p'¤Ç¥Ú¡¼¥¹¥È" : ", 'c'¤Ç¥³¥Ô¡¼"),
+                       hgt - 1, 0);
 #else
-               prt(format("<dir>, 'r' to recall%s%s, ESC", k_ptr->flavor ? "" : visual_list ? ", ENTER to accept" : ", 'v' for visuals", (attr_idx||char_idx) ? ", 'c', 'p' to paste" : ", 'c' to copy"), hgt - 1, 0);
+               prt(format("<dir>%s%s%s, ESC",
+                       (!visual_list && !visual_only) ? ", 'r' to recall" : "",
+                       k_ptr->flavor ? "" : visual_list ? ", ENTER to accept" : ", 'v' for visuals",
+                       (attr_idx || char_idx) ? ", 'c', 'p' to paste" : ", 'c' to copy"),
+                       hgt - 1, 0);
 #endif
 
-               /* The "current" object changed */
-               if (object_old != object_idx[object_cur])
+               if (!visual_only)
                {
-                       /* Hack -- handle stuff */
-                       handle_stuff();
+                       /* Mega Hack -- track this object */
+                       if (object_cnt) object_kind_track(object_idx[object_cur]);
+
+                       /* The "current" object changed */
+                       if (object_old != object_idx[object_cur])
+                       {
+                               /* Hack -- handle stuff */
+                               handle_stuff();
 
-                       /* Remember the "current" object */
-                       object_old = object_idx[object_cur];
+                               /* Remember the "current" object */
+                               object_old = object_idx[object_cur];
+                       }
                }
 
                if (visual_list)
@@ -8041,7 +8256,21 @@ static void do_cmd_knowledge_objects(bool *need_redraw)
 
                /* Do visual mode command if needed */
                /* Symbol of objects with flavor cannot be changed */
-               if (!k_ptr->flavor && visual_mode_command(ch, &visual_list, browser_rows-1, wid - (max + 3), &attr_top, &char_left, &k_ptr->x_attr, &k_ptr->x_char, need_redraw)) continue;
+               if (!k_ptr->flavor && visual_mode_command(ch, &visual_list, browser_rows-1, wid - (max + 3), &attr_top, &char_left, &k_ptr->x_attr, &k_ptr->x_char, need_redraw))
+               {
+                       if (direct_k_idx >= 0)
+                       {
+                               switch (ch)
+                               {
+                               case '\n':
+                               case '\r':
+                               case ESCAPE:
+                                       flag = TRUE;
+                                       break;
+                               }
+                       }
+                       continue;
+               }
 
                switch (ch)
                {
@@ -8055,10 +8284,11 @@ static void do_cmd_knowledge_objects(bool *need_redraw)
                        case 'r':
                        {
                                /* Recall on screen */
-                               if (grp_cnt > 0)
+                               if (!visual_list && !visual_only && (grp_cnt > 0))
+                               {
                                        desc_obj_fake(object_idx[object_cur]);
-
-                               redraw = TRUE;
+                                       redraw = TRUE;
+                               }
                                break;
                        }
 
@@ -8076,23 +8306,22 @@ static void do_cmd_knowledge_objects(bool *need_redraw)
 }
 
 
-#define NS_LIT_NUM       (F_LIT_MAX - F_LIT_NS_BEGIN)
-#define ROW_LIT_STANDARD 65
-
 /*
  * Display the features in a group.
  */
 static void display_feature_list(int col, int row, int per_page, int *feat_idx,
-       int feat_cur, int feat_top, int lighting_level)
+       int feat_cur, int feat_top, bool visual_only, int lighting_level)
 {
-       int ns_lit_col[NS_LIT_NUM], i, j;
+       int lit_col[F_LIT_MAX], i, j;
+       int f_idx_col = use_bigtile ? 59 : 62;
 
        /* Correct columns 1 and 4 */
-       for (i = 0; i < NS_LIT_NUM; i++)
-               ns_lit_col[i] = ROW_LIT_STANDARD + 2 + i * 2 + (use_bigtile ? (1 + i) : 0);
+       lit_col[F_LIT_STANDARD] = use_bigtile ? (69 - F_LIT_MAX) : 69;
+       for (i = F_LIT_NS_BEGIN; i < F_LIT_MAX; i++)
+               lit_col[i] = lit_col[F_LIT_STANDARD] + 2 + (i - F_LIT_NS_BEGIN) * 2 + (use_bigtile ? i : 0);
 
        /* Display lines until done */
-       for (i = 0; i < per_page && feat_idx[feat_top + i]; i++)
+       for (i = 0; i < per_page && (feat_idx[feat_top + i] >= 0); i++)
        {
                byte attr;
 
@@ -8116,23 +8345,27 @@ static void display_feature_list(int col, int row, int per_page, int *feat_idx,
                        /* Display lighting level */
                        c_prt(attr, format("(%s)", lighting_level_str[lighting_level]), row_i, col + 1 + strlen(f_name + f_ptr->name));
 
-                       c_prt(attr, format("%02x/%02x", f_ptr->x_attr[lighting_level], f_ptr->x_char[lighting_level]), row_i, ROW_LIT_STANDARD - 9);
+                       c_prt(attr, format("%02x/%02x", f_ptr->x_attr[lighting_level], f_ptr->x_char[lighting_level]), row_i, f_idx_col - ((p_ptr->wizard || visual_only) ? 6 : 2));
+               }
+               if (p_ptr->wizard || visual_only)
+               {
+                       c_prt(attr, format("%d", f_idx), row_i, f_idx_col);
                }
 
                /* Display symbol */
-               Term_queue_bigchar(ROW_LIT_STANDARD, row_i, f_ptr->x_attr[F_LIT_STANDARD], f_ptr->x_char[F_LIT_STANDARD], 0, 0);
+               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);
 
-               Term_putch(ns_lit_col[0], row_i, TERM_SLATE, '(');
-               for (j = 1; j < NS_LIT_NUM; j++)
+               Term_putch(lit_col[F_LIT_NS_BEGIN], row_i, TERM_SLATE, '(');
+               for (j = F_LIT_NS_BEGIN + 1; j < F_LIT_MAX; j++)
                {
-                       Term_putch(ns_lit_col[j], row_i, TERM_SLATE, '/');
+                       Term_putch(lit_col[j], row_i, TERM_SLATE, '/');
                }
-               Term_putch(ns_lit_col[NS_LIT_NUM - 1] + (use_bigtile ? 3 : 2), row_i, TERM_SLATE, ')');
+               Term_putch(lit_col[F_LIT_MAX - 1] + (use_bigtile ? 3 : 2), row_i, TERM_SLATE, ')');
 
                /* Mega-hack -- Use non-standard colour */
-               for (j = 0; j < NS_LIT_NUM; j++)
+               for (j = F_LIT_NS_BEGIN; j < F_LIT_MAX; j++)
                {
-                       Term_queue_bigchar(ns_lit_col[j] + 1, row_i, f_ptr->x_attr[F_LIT_NS_BEGIN + j], f_ptr->x_char[F_LIT_NS_BEGIN + j], 0, 0);
+                       Term_queue_bigchar(lit_col[j] + 1, row_i, f_ptr->x_attr[j], f_ptr->x_char[j], 0, 0);
                }
        }
 
@@ -8147,7 +8380,7 @@ static void display_feature_list(int col, int row, int per_page, int *feat_idx,
 /*
  * Interact with feature visuals.
  */
-static void do_cmd_knowledge_features(bool *need_redraw)
+static void do_cmd_knowledge_features(bool *need_redraw, bool visual_only, int direct_f_idx, int *lighting_level)
 {
        int i, len, max;
        int grp_cur, grp_top, old_grp_cur;
@@ -8169,7 +8402,6 @@ static void do_cmd_knowledge_features(bool *need_redraw)
        byte attr_old[F_LIT_MAX];
        byte char_old[F_LIT_MAX];
        byte *cur_attr_ptr, *cur_char_ptr;
-       int lighting_level = F_LIT_STANDARD;
 
        C_WIPE(attr_old, F_LIT_MAX, byte);
        C_WIPE(char_old, F_LIT_MAX, byte);
@@ -8185,20 +8417,44 @@ static void do_cmd_knowledge_features(bool *need_redraw)
        max = 0;
        grp_cnt = 0;
 
-       /* Check every group */
-       for (i = 0; feature_group_text[i] != NULL; i++)
+       if (direct_f_idx < 0)
        {
-               /* Measure the label */
-               len = strlen(feature_group_text[i]);
+               /* Check every group */
+               for (i = 0; feature_group_text[i] != NULL; i++)
+               {
+                       /* Measure the label */
+                       len = strlen(feature_group_text[i]);
+
+                       /* Save the maximum length */
+                       if (len > max) max = len;
 
-               /* Save the maximum length */
-               if (len > max) max = len;
+                       /* See if any features are known */
+                       if (collect_features(i, feat_idx, 0x01))
+                       {
+                               /* Build a list of groups with known features */
+                               grp_idx[grp_cnt++] = i;
+                       }
+               }
 
-               /* See if any features are known */
-               if (collect_features(i, feat_idx))
+               feat_cnt = 0;
+       }
+       else
+       {
+               feature_type *f_ptr = &f_info[direct_f_idx];
+
+               feat_idx[0] = direct_f_idx;
+               feat_cnt = 1;
+
+               /* Terminate the list */
+               feat_idx[1] = -1;
+
+               (void)visual_mode_command('v', &visual_list, browser_rows - 1, wid - (max + 3),
+                       &attr_top, &char_left, &f_ptr->x_attr[*lighting_level], &f_ptr->x_char[*lighting_level], need_redraw);
+
+               for (i = 0; i < F_LIT_MAX; i++)
                {
-                       /* Build a list of groups with known features */
-                       grp_idx[grp_cnt++] = i;
+                       attr_old[i] = f_ptr->x_attr[i];
+                       char_old[i] = f_ptr->x_char[i];
                }
        }
 
@@ -8208,12 +8464,11 @@ static void do_cmd_knowledge_features(bool *need_redraw)
        old_grp_cur = -1;
        grp_cur = grp_top = 0;
        feat_cur = feat_top = 0;
-       feat_cnt = 0;
 
        flag = FALSE;
        redraw = TRUE;
 
-       while ((!flag) && (grp_cnt))
+       while (!flag)
        {
                char ch;
                feature_type *f_ptr;
@@ -8224,16 +8479,32 @@ static void do_cmd_knowledge_features(bool *need_redraw)
 
 #ifdef JP
                        prt("ɽ¼¨ - ÃÏ·Á", 2, 0);
-                       prt("¥°¥ë¡¼¥×", 4, 0);
+                       if (direct_f_idx < 0) prt("¥°¥ë¡¼¥×", 4, 0);
                        prt("̾Á°", 4, max + 3);
-                       if (use_bigtile) prt("ʸ»ú ( l/ d/ D)", 4, 63);
-                       else prt("ʸ»ú (l/d/D)", 4, 62);
+                       if (use_bigtile)
+                       {
+                               if (p_ptr->wizard || visual_only) prt("Idx", 4, 59);
+                               prt("ʸ»ú ( l/ d/ D)", 4, 63);
+                       }
+                       else
+                       {
+                               if (p_ptr->wizard || visual_only) prt("Idx", 4, 62);
+                               prt("ʸ»ú (l/d/D)", 4, 66);
+                       }
 #else
                        prt("Visuals - features", 2, 0);
-                       prt("Group", 4, 0);
+                       if (direct_f_idx < 0) prt("Group", 4, 0);
                        prt("Name", 4, max + 3);
-                       if (use_bigtile) prt("Sym ( l/ d/ D)", 4, 64);
-                       else prt("Sym (l/d/D)", 4, 63);
+                       if (use_bigtile)
+                       {
+                               if (p_ptr->wizard || visual_only) prt("Idx", 4, 59);
+                               prt("Sym ( l/ d/ D)", 4, 64);
+                       }
+                       else
+                       {
+                               if (p_ptr->wizard || visual_only) prt("Idx", 4, 62);
+                               prt("Sym (l/d/D)", 4, 67);
+                       }
 #endif
 
                        for (i = 0; i < 78; i++)
@@ -8241,46 +8512,52 @@ static void do_cmd_knowledge_features(bool *need_redraw)
                                Term_putch(i, 5, TERM_WHITE, '=');
                        }
 
-                       for (i = 0; i < browser_rows; i++)
+                       if (direct_f_idx < 0)
                        {
-                               Term_putch(max + 1, 6 + i, TERM_WHITE, '|');
+                               for (i = 0; i < browser_rows; i++)
+                               {
+                                       Term_putch(max + 1, 6 + i, TERM_WHITE, '|');
+                               }
                        }
 
                        redraw = FALSE;
                }
 
-               /* Scroll group list */
-               if (grp_cur < grp_top) grp_top = grp_cur;
-               if (grp_cur >= grp_top + browser_rows) grp_top = grp_cur - browser_rows + 1;
+               if (direct_f_idx < 0)
+               {
+                       /* Scroll group list */
+                       if (grp_cur < grp_top) grp_top = grp_cur;
+                       if (grp_cur >= grp_top + browser_rows) grp_top = grp_cur - browser_rows + 1;
 
-               /* Display a list of feature groups */
-               display_group_list(0, 6, max, browser_rows, grp_idx, feature_group_text, grp_cur, grp_top);
+                       /* Display a list of feature groups */
+                       display_group_list(0, 6, max, browser_rows, grp_idx, feature_group_text, grp_cur, grp_top);
 
-               if (old_grp_cur != grp_cur)
-               {
-                       old_grp_cur = grp_cur;
+                       if (old_grp_cur != grp_cur)
+                       {
+                               old_grp_cur = grp_cur;
 
-                       /* Get a list of features in the current group */
-                       feat_cnt = collect_features(grp_idx[grp_cur], feat_idx);
-               }
+                               /* Get a list of features in the current group */
+                               feat_cnt = collect_features(grp_idx[grp_cur], feat_idx, 0x00);
+                       }
 
-               /* Scroll feature list */
-               while (feat_cur < feat_top)
-                       feat_top = MAX(0, feat_top - browser_rows/2);
-               while (feat_cur >= feat_top + browser_rows)
-                       feat_top = MIN(feat_cnt - browser_rows, feat_top + browser_rows/2);
+                       /* Scroll feature list */
+                       while (feat_cur < feat_top)
+                               feat_top = MAX(0, feat_top - browser_rows/2);
+                       while (feat_cur >= feat_top + browser_rows)
+                               feat_top = MIN(feat_cnt - browser_rows, feat_top + browser_rows/2);
+               }
 
                if (!visual_list)
                {
                        /* Display a list of features in the current group */
-                       display_feature_list(max + 3, 6, browser_rows, feat_idx, feat_cur, feat_top, F_LIT_STANDARD);
+                       display_feature_list(max + 3, 6, browser_rows, feat_idx, feat_cur, feat_top, visual_only, F_LIT_STANDARD);
                }
                else
                {
                        feat_top = feat_cur;
 
                        /* Display a list of features in the current group */
-                       display_feature_list(max + 3, 6, 1, feat_idx, feat_cur, feat_top, lighting_level);
+                       display_feature_list(max + 3, 6, 1, feat_idx, feat_cur, feat_top, visual_only, *lighting_level);
 
                        /* Display visual list below first object */
                        display_visual_list(max + 3, 7, browser_rows-1, wid - (max + 3), attr_top, char_left);
@@ -8288,15 +8565,21 @@ static void do_cmd_knowledge_features(bool *need_redraw)
 
                /* Prompt */
 #ifdef JP
-               prt(format("<Êý¸þ>%s, 'd'¤Çɸ½à¸÷¸»¸ú²Ì%s, ESC", visual_list ? ", ENTER¤Ç·èÄê, 'a'¤ÇÂоÝÌÀÅÙÊѹ¹" : ", 'v'¤Ç¥·¥ó¥Ü¥ëÊѹ¹", (attr_idx||char_idx) ? ", 'c', 'p'¤Ç¥Ú¡¼¥¹¥È" : ", 'c'¤Ç¥³¥Ô¡¼"), hgt - 1, 0);
+               prt(format("<Êý¸þ>%s, 'd'¤Çɸ½à¸÷¸»¸ú²Ì%s, ESC",
+                       visual_list ? ", ENTER¤Ç·èÄê, 'a'¤ÇÂоÝÌÀÅÙÊѹ¹" : ", 'v'¤Ç¥·¥ó¥Ü¥ëÊѹ¹",
+                       (attr_idx || char_idx) ? ", 'c', 'p'¤Ç¥Ú¡¼¥¹¥È" : ", 'c'¤Ç¥³¥Ô¡¼"),
+                       hgt - 1, 0);
 #else
-               prt(format("<dir>%s, 'd' for default lighting%s, ESC", visual_list ? ", ENTER to accept, 'a' for lighting level" : ", 'v' for visuals", (attr_idx||char_idx) ? ", 'c', 'p' to paste" : ", 'c' to copy"), hgt - 1, 0);
+               prt(format("<dir>%s, 'd' for default lighting%s, ESC",
+                       visual_list ? ", ENTER to accept, 'a' for lighting level" : ", 'v' for visuals",
+                       (attr_idx || char_idx) ? ", 'c', 'p' to paste" : ", 'c' to copy"),
+                       hgt - 1, 0);
 #endif
 
                /* Get the current feature */
                f_ptr = &f_info[feat_idx[feat_cur]];
-               cur_attr_ptr = &f_ptr->x_attr[lighting_level];
-               cur_char_ptr = &f_ptr->x_char[lighting_level];
+               cur_attr_ptr = &f_ptr->x_attr[*lighting_level];
+               cur_char_ptr = &f_ptr->x_char[*lighting_level];
 
                if (visual_list)
                {
@@ -8315,42 +8598,42 @@ static void do_cmd_knowledge_features(bool *need_redraw)
 
                if (visual_list && ((ch == 'A') || (ch == 'a')))
                {
-                       int prev_lighting_level = lighting_level;
+                       int prev_lighting_level = *lighting_level;
 
                        if (ch == 'A')
                        {
-                               if (lighting_level <= 0) lighting_level = F_LIT_MAX - 1;
-                               else lighting_level--;
+                               if (*lighting_level <= 0) *lighting_level = F_LIT_MAX - 1;
+                               else (*lighting_level)--;
                        }
                        else
                        {
-                               if (lighting_level >= F_LIT_MAX - 1) lighting_level = 0;
-                               else lighting_level++;
+                               if (*lighting_level >= F_LIT_MAX - 1) *lighting_level = 0;
+                               else (*lighting_level)++;
                        }
 
-                       if (f_ptr->x_attr[prev_lighting_level] != f_ptr->x_attr[lighting_level])
-                               attr_top = MAX(0, (f_ptr->x_attr[lighting_level] & 0x7f) - 5);
+                       if (f_ptr->x_attr[prev_lighting_level] != f_ptr->x_attr[*lighting_level])
+                               attr_top = MAX(0, (f_ptr->x_attr[*lighting_level] & 0x7f) - 5);
 
-                       if (f_ptr->x_char[prev_lighting_level] != f_ptr->x_char[lighting_level])
-                               char_left = MAX(0, f_ptr->x_char[lighting_level] - 10);
+                       if (f_ptr->x_char[prev_lighting_level] != f_ptr->x_char[*lighting_level])
+                               char_left = MAX(0, f_ptr->x_char[*lighting_level] - 10);
 
                        continue;
                }
 
                else if ((ch == 'D') || (ch == 'd'))
                {
-                       byte prev_x_attr = f_ptr->x_attr[lighting_level];
-                       byte prev_x_char = f_ptr->x_char[lighting_level];
+                       byte prev_x_attr = f_ptr->x_attr[*lighting_level];
+                       byte prev_x_char = f_ptr->x_char[*lighting_level];
 
                        apply_default_feat_lighting(f_ptr->x_attr, f_ptr->x_char);
 
                        if (visual_list)
                        {
-                               if (prev_x_attr != f_ptr->x_attr[lighting_level])
-                                        attr_top = MAX(0, (f_ptr->x_attr[lighting_level] & 0x7f) - 5);
+                               if (prev_x_attr != f_ptr->x_attr[*lighting_level])
+                                        attr_top = MAX(0, (f_ptr->x_attr[*lighting_level] & 0x7f) - 5);
 
-                               if (prev_x_char != f_ptr->x_char[lighting_level])
-                                       char_left = MAX(0, f_ptr->x_char[lighting_level] - 10);
+                               if (prev_x_char != f_ptr->x_char[*lighting_level])
+                                       char_left = MAX(0, f_ptr->x_char[*lighting_level] - 10);
                        }
                        else *need_redraw = TRUE;
 
@@ -8374,7 +8657,8 @@ static void do_cmd_knowledge_features(bool *need_redraw)
 
                        case '\n':
                        case '\r':
-                               lighting_level = F_LIT_STANDARD;
+                               if (direct_f_idx >= 0) flag = TRUE;
+                               else *lighting_level = F_LIT_STANDARD;
                                break;
 
                        /* Preserve current visual settings */
@@ -8385,7 +8669,7 @@ static void do_cmd_knowledge_features(bool *need_redraw)
                                        attr_old[i] = f_ptr->x_attr[i];
                                        char_old[i] = f_ptr->x_char[i];
                                }
-                               lighting_level = F_LIT_STANDARD;
+                               *lighting_level = F_LIT_STANDARD;
                                break;
 
                        case 'C':
@@ -8433,9 +8717,6 @@ static void do_cmd_knowledge_features(bool *need_redraw)
                }
        }
 
-       /* Prompt */
-       if (!grp_cnt) msg_print("No features known.");
-
        /* Free the "feat_idx" array */
        C_KILL(feat_idx, max_f_idx, int);
 }
@@ -9486,13 +9767,13 @@ void do_cmd_knowledge(void)
                        do_cmd_knowledge_artifacts();
                        break;
                case '2': /* Objects */
-                       do_cmd_knowledge_objects(&need_redraw);
+                       do_cmd_knowledge_objects(&need_redraw, FALSE, -1);
                        break;
                case '3': /* Uniques */
                        do_cmd_knowledge_uniques();
                        break;
                case '4': /* Monsters */
-                       do_cmd_knowledge_monsters(&need_redraw);
+                       do_cmd_knowledge_monsters(&need_redraw, FALSE, -1);
                        break;
                case '5': /* Kill count  */
                        do_cmd_knowledge_kill_count();
@@ -9510,7 +9791,10 @@ void do_cmd_knowledge(void)
                        do_cmd_knowledge_inven();
                        break;
                case '0': /* Feature list */
-                       do_cmd_knowledge_features(&need_redraw);
+                       {
+                               int lighting_level = F_LIT_STANDARD;
+                               do_cmd_knowledge_features(&need_redraw, FALSE, -1, &lighting_level);
+                       }
                        break;
                /* Next page */
                case 'a': /* Max stat */