OSDN Git Service

Add Doxygen comment to wizard1.c.
[hengband/hengband.git] / src / wizard1.c
index 8b64682..fc987c4 100644 (file)
@@ -1,6 +1,14 @@
-/* File: wizard1.c */
-
-/* Purpose: Spoiler generation -BEN- */
+/*!
+ *  @file wizard1.c
+ *  @brief ¥¦¥£¥¶¡¼¥É¥â¡¼¥É¤Î½èÍý(¥¹¥Ý¥¤¥é¡¼½ÐÎÏÃæ¿´) / Spoiler generation -BEN-
+ *  @date 2014/02/17
+ *  @author
+ * Copyright (c) 1997 Ben Harrison, and others
+ * This software may be copied and distributed for educational, research,
+ * and not for profit purposes provided that this copyright and statement
+ * are included in all such copies.  Other copyrights may also apply.
+ * 2013 Deskull rearranged comment for Doxygen.
+ */
 
 #include "angband.h"
 
@@ -15,58 +23,69 @@ static FILE *fff = NULL;
 
 
 
-/*
+/*!
+ * @brief ¥·¥ó¥Ü¥ë¿¦¤Îµ­½Ò̾¤òÊÖ¤¹ /
  * Extract a textual representation of an attribute
+ * @param r_ptr ¥â¥ó¥¹¥¿¡¼¼ï²¤Î¹½Â¤ÂΥݥ¤¥ó¥¿
+ * @return ¥·¥ó¥Ü¥ë¿¦¤Îµ­½Ò̾
  */
-static cptr attr_to_text(byte a)
+static cptr attr_to_text(monster_race *r_ptr)
 {
-       switch (a)
-       {
 #ifdef JP000
-case TERM_DARK:    return ("XXX¤¤");
-case TERM_WHITE:   return ("Çò¤¤");
-case TERM_SLATE:   return ("Àij¥¿§¤Î");
-case TERM_ORANGE:  return ("¥ª¥ì¥ó¥¸¤Î");
-case TERM_RED:     return ("ÀÖ¤¤");
-case TERM_GREEN:   return ("ÎФÎ");
-case TERM_BLUE:    return ("ÀĤ¤");
-case TERM_UMBER:   return ("àèàῧ¤Î");
-case TERM_L_DARK:  return ("³¥¿§¤Î");
-case TERM_L_WHITE: return ("ÌÀÀij¥¿§¤Î");
-case TERM_VIOLET:  return ("»ç¤Î");
-case TERM_YELLOW:  return ("²«¿§¤¤");
-case TERM_L_RED:   return ("ÌÀ¤¤ÀÖ¤Î");
-case TERM_L_GREEN: return ("ÌÀ¤¤ÎФÎ");
-case TERM_L_BLUE:  return ("ÌÀ¤¤ÀĤÎ");
-case TERM_L_UMBER: return ("ÌÀ¤¤àèàῧ¤Î");
+       if (r_ptr->flags1 & RF1_ATTR_CLEAR)    return "Æ©ÌÀ¤Ê";
+       if (r_ptr->flags1 & RF1_ATTR_MULTI)    return "Ëü¿§¤Î";
+       if (r_ptr->flags1 & RF1_ATTR_SEMIRAND) return "½à¥é¥ó¥À¥à¤Ê";
 #else
-               case TERM_DARK:    return ("xxx");
-               case TERM_WHITE:   return ("White");
-               case TERM_SLATE:   return ("Slate");
-               case TERM_ORANGE:  return ("Orange");
-               case TERM_RED:     return ("Red");
-               case TERM_GREEN:   return ("Green");
-               case TERM_BLUE:    return ("Blue");
-               case TERM_UMBER:   return ("Umber");
-               case TERM_L_DARK:  return ("L.Dark");
-               case TERM_L_WHITE: return ("L.Slate");
-               case TERM_VIOLET:  return ("Violet");
-               case TERM_YELLOW:  return ("Yellow");
-               case TERM_L_RED:   return ("L.Red");
-               case TERM_L_GREEN: return ("L.Green");
-               case TERM_L_BLUE:  return ("L.Blue");
-               case TERM_L_UMBER: return ("L.Umber");
+       if (r_ptr->flags1 & RF1_ATTR_CLEAR)    return "Clear";
+       if (r_ptr->flags1 & RF1_ATTR_MULTI)    return "Multi";
+       if (r_ptr->flags1 & RF1_ATTR_SEMIRAND) return "S.Rand";
 #endif
 
+       switch (r_ptr->d_attr)
+       {
+#ifdef JP000
+       case TERM_DARK:    return "XXX¤¤";
+       case TERM_WHITE:   return "Çò¤¤";
+       case TERM_SLATE:   return "Àij¥¿§¤Î";
+       case TERM_ORANGE:  return "¥ª¥ì¥ó¥¸¤Î";
+       case TERM_RED:     return "ÀÖ¤¤";
+       case TERM_GREEN:   return "ÎФÎ";
+       case TERM_BLUE:    return "ÀĤ¤";
+       case TERM_UMBER:   return "àèàῧ¤Î";
+       case TERM_L_DARK:  return "³¥¿§¤Î";
+       case TERM_L_WHITE: return "ÌÀÀij¥¿§¤Î";
+       case TERM_VIOLET:  return "»ç¤Î";
+       case TERM_YELLOW:  return "²«¿§¤¤";
+       case TERM_L_RED:   return "ÌÀ¤¤ÀÖ¤Î";
+       case TERM_L_GREEN: return "ÌÀ¤¤ÎФÎ";
+       case TERM_L_BLUE:  return "ÌÀ¤¤ÀĤÎ";
+       case TERM_L_UMBER: return "ÌÀ¤¤àèàῧ¤Î";
+#else
+       case TERM_DARK:    return "xxx";
+       case TERM_WHITE:   return "White";
+       case TERM_SLATE:   return "Slate";
+       case TERM_ORANGE:  return "Orange";
+       case TERM_RED:     return "Red";
+       case TERM_GREEN:   return "Green";
+       case TERM_BLUE:    return "Blue";
+       case TERM_UMBER:   return "Umber";
+       case TERM_L_DARK:  return "L.Dark";
+       case TERM_L_WHITE: return "L.Slate";
+       case TERM_VIOLET:  return "Violet";
+       case TERM_YELLOW:  return "Yellow";
+       case TERM_L_RED:   return "L.Red";
+       case TERM_L_GREEN: return "L.Green";
+       case TERM_L_BLUE:  return "L.Blue";
+       case TERM_L_UMBER: return "L.Umber";
+#endif
        }
 
        /* Oops */
 #ifdef JP000
-return ("ÊѤÊ");
+       return "ÊѤÊ";
 #else
-       return ("Icky");
+       return "Icky";
 #endif
-
 }
 
 
@@ -93,7 +112,7 @@ typedef struct
 static grouper group_item[] =
 {
 #ifdef JP
-{ TV_SHOT,          "¼Í·âʪ" },
+       { TV_SHOT,          "¼Í·âʪ" },
 #else
        { TV_SHOT,          "Ammo" },
 #endif
@@ -102,24 +121,23 @@ static grouper group_item[] =
        { TV_BOLT,          NULL },
 
 #ifdef JP
-{ TV_BOW,           "µÝ" },
+       { TV_BOW,           "µÝ" },
 #else
        { TV_BOW,           "Bows" },
 #endif
 
-
 #ifdef JP
-{ TV_SWORD,         "Éð´ï" },
+       { TV_DIGGING,       "Éð´ï" },
 #else
-       { TV_SWORD,         "Weapons" },
+       { TV_DIGGING,       "Weapons" },
 #endif
 
        { TV_POLEARM,       NULL },
        { TV_HAFTED,        NULL },
-       { TV_DIGGING,       NULL },
+       { TV_SWORD,         NULL },
 
 #ifdef JP
-{ TV_SOFT_ARMOR,    "Ëɶñ¡ÊÂΡË" },
+       { TV_SOFT_ARMOR,    "Ëɶñ (ÂÎ)" },
 #else
        { TV_SOFT_ARMOR,    "Armour (Body)" },
 #endif
@@ -128,60 +146,61 @@ static grouper group_item[] =
        { TV_DRAG_ARMOR,    NULL },
 
 #ifdef JP
-{ TV_CLOAK,         "Ëɶñ¡Ê¤½¤Î¾¡Ë" },
+       { TV_BOOTS,         "Ëɶñ (¤½¤Î¾)" },
 #else
-       { TV_CLOAK,         "Armour (Misc)" },
+       { TV_BOOTS,         "Armour (Misc)" },
 #endif
 
-       { TV_SHIELD,        NULL },
+       { TV_GLOVES,        NULL },
        { TV_HELM,          NULL },
        { TV_CROWN,         NULL },
-       { TV_GLOVES,        NULL },
-       { TV_BOOTS,         NULL },
+       { TV_SHIELD,        NULL },
+       { TV_CLOAK,         NULL },
 
 #ifdef JP
-{ TV_AMULET,        "¥¢¥ß¥å¥ì¥Ã¥È" },
-{ TV_RING,          "»ØÎØ" },
+       { TV_LITE,          "¸÷¸»" },
+       { TV_AMULET,        "¥¢¥ß¥å¥ì¥Ã¥È" },
+       { TV_RING,          "»ØÎØ" },
 #else
+       { TV_LITE,          "Light Sources" },
        { TV_AMULET,        "Amulets" },
        { TV_RING,          "Rings" },
 #endif
 
-
 #ifdef JP
-{ TV_SCROLL,        "´¬Êª" },
-{ TV_POTION,        "Ìô" },
-{ TV_FOOD,          "¿©ÎÁ" },
+       { TV_STAFF,         "¾ó" },
+       { TV_WAND,          "ËâË¡ËÀ" },
+       { TV_ROD,           "¥í¥Ã¥É" },
 #else
-       { TV_SCROLL,        "Scrolls" },
-       { TV_POTION,        "Potions" },
-       { TV_FOOD,          "Food" },
+       { TV_STAFF,         "Staffs" },
+       { TV_WAND,          "Wands" },
+       { TV_ROD,           "Rods" },
 #endif
 
-
 #ifdef JP
-{ TV_ROD,           "¥í¥Ã¥É" },
-{ TV_WAND,          "ËâË¡ËÀ" },
-{ TV_STAFF,         "¾ó" },
+       { TV_SCROLL,        "´¬Êª" },
+       { TV_POTION,        "Ìô" },
+       { TV_FOOD,          "¿©ÎÁ" },
 #else
-       { TV_ROD,           "Rods" },
-       { TV_WAND,          "Wands" },
-       { TV_STAFF,         "Staffs" },
+       { TV_SCROLL,        "Scrolls" },
+       { TV_POTION,        "Potions" },
+       { TV_FOOD,          "Food" },
 #endif
 
-
 #ifdef JP
-{ TV_LIFE_BOOK,     "ËâË¡½ñ¡ÊÀ¸Ì¿¡Ë" },
-{ TV_SORCERY_BOOK,  "ËâË¡½ñ¡ÊÀç½Ñ¡Ë" },
-{ TV_NATURE_BOOK,   "ËâË¡½ñ¡Ê¼«Á³¡Ë" },
-{ TV_CHAOS_BOOK,    "ËâË¡½ñ¡Ê¥«¥ª¥¹¡Ë" },
-{ TV_DEATH_BOOK,    "ËâË¡½ñ¡Ê°Å¹õ¡Ë" },
-{ TV_TRUMP_BOOK,    "ËâË¡½ñ¡Ê¥È¥é¥ó¥×¡Ë" },
-{ TV_ARCANE_BOOK,   "ËâË¡½ñ¡ÊÈë½Ñ¡Ë" },
-{ TV_ENCHANT_BOOK,  "ËâË¡½ñ¡Ê¾¢¡Ë" },
-{ TV_DAEMON_BOOK,   "ËâË¡½ñ¡Ê°­Ëâ¡Ë" },
-{ TV_MUSIC_BOOK,    "²Î½¸" },
-{ TV_HISSATSU_BOOK, "Éð·Ý¤Î½ñ" },
+       { TV_LIFE_BOOK,     "ËâË¡½ñ (À¸Ì¿)" },
+       { TV_SORCERY_BOOK,  "ËâË¡½ñ (Àç½Ñ)" },
+       { TV_NATURE_BOOK,   "ËâË¡½ñ (¼«Á³)" },
+       { TV_CHAOS_BOOK,    "ËâË¡½ñ (¥«¥ª¥¹)" },
+       { TV_DEATH_BOOK,    "ËâË¡½ñ (°Å¹õ)" },
+       { TV_TRUMP_BOOK,    "ËâË¡½ñ (¥È¥é¥ó¥×)" },
+       { TV_ARCANE_BOOK,   "ËâË¡½ñ (Èë½Ñ)" },
+       { TV_CRAFT_BOOK,    "ËâË¡½ñ (¾¢)" },
+       { TV_DAEMON_BOOK,   "ËâË¡½ñ (°­Ëâ)" },
+       { TV_CRUSADE_BOOK,  "ËâË¡½ñ (Ç˼Ù)" },
+       { TV_MUSIC_BOOK,    "²Î½¸" },
+       { TV_HISSATSU_BOOK, "Éð·Ý¤Î½ñ" },
+       { TV_HEX_BOOK,      "ËâË¡½ñ (¼ö½Ñ)" },
 #else
        { TV_LIFE_BOOK,     "Books (Life)" },
        { TV_SORCERY_BOOK,  "Books (Sorcery)" },
@@ -190,64 +209,66 @@ static grouper group_item[] =
        { TV_DEATH_BOOK,    "Books (Death)" },
        { TV_TRUMP_BOOK,    "Books (Trump)" },
        { TV_ARCANE_BOOK,   "Books (Arcane)" },
-       { TV_ENCHANT_BOOK,  "Books (Craft)" },
+       { TV_CRAFT_BOOK,    "Books (Craft)" },
        { TV_DAEMON_BOOK,   "Books (Daemon)" },
+       { TV_CRUSADE_BOOK,  "Books (Crusade)" },
        { TV_MUSIC_BOOK,    "Song Books" },
        { TV_HISSATSU_BOOK, "Books (Kendo)" },
+       { TV_HEX_BOOK,      "Books (Hex)" },
 #endif
 
 #ifdef JP
-{ TV_PARCHEMENT,    "ÍÓÈé»æ" },
+       { TV_WHISTLE,       "ū" },
+       { TV_CAPTURE,       "¥­¥ã¥×¥Á¥ã¡¼¡¦¥Ü¡¼¥ë" },
+       { TV_CARD,          "¥¨¥¯¥¹¥×¥ì¥¹¥«¡¼¥É" },
 #else
-{ TV_PARCHEMENT,    "Parchement" },
+       { TV_WHISTLE,       "Whistle" },
+       { TV_CAPTURE,       "Capture Ball" },
+       { TV_CARD,          "Express Card" },
 #endif
 
 #ifdef JP
-{ TV_CHEST,         "Ȣ" },
+       { TV_CHEST,         "Ȣ" },
 #else
        { TV_CHEST,         "Chests" },
 #endif
 
 #ifdef JP
-{ TV_CAPTURE,         "¥­¥ã¥×¥Á¥ã¡¼¡¦¥Ü¡¼¥ë" },
-#else
-       { TV_CAPTURE,         "Capture Ball" },
-#endif
-
-#ifdef JP
-{ TV_CARD,         "¥¨¥¯¥¹¥×¥ì¥¹¥«¡¼¥É" },
+       { TV_FIGURINE,      "¿Í·Á" },
+       { TV_STATUE,        "Áü" },
+       { TV_CORPSE,        "»àÂÎ" },
 #else
-       { TV_CARD,         "Express Card" },
-#endif
-
        { TV_FIGURINE,      "Magical Figurines" },
        { TV_STATUE,        "Statues" },
        { TV_CORPSE,        "Corpses" },
-
-#ifdef JP
-{ TV_WHISTLE,         "ū" },
-#else
-       { TV_WHISTLE,         "Whistle" },
 #endif
 
 #ifdef JP
-{ TV_SPIKE,         "¤¯¤µ¤Ó" },
+       { TV_SKELETON,      "¤½¤Î¾" },
 #else
-       { TV_SPIKE,         "Spike" },
+       { TV_SKELETON,      "Misc" },
 #endif
 
-       { TV_LITE,          NULL },
-       { TV_FLASK,         NULL },
-       { TV_JUNK,          NULL },
        { TV_BOTTLE,        NULL },
-       { TV_SKELETON,      NULL },
+       { TV_JUNK,          NULL },
+       { TV_SPIKE,         NULL },
+       { TV_FLASK,         NULL },
+       { TV_PARCHMENT,     NULL },
 
        { 0, "" }
 };
 
 
-/*
+/*!
+ * @brief ¥Ù¡¼¥¹¥¢¥¤¥Æ¥à¤Î³Æ¾ðÊó¤òʸ»úÎ󲽤¹¤ë /
  * Describe the kind
+ * @param buf Ì¾¾Î¤òÊÖ¤¹¥Ð¥Ã¥Õ¥¡»²¾È¥Ý¥¤¥ó¥¿
+ * @param dam ¥À¥á¡¼¥¸¥À¥¤¥¹µ­½Ò¤òÊÖ¤¹¥Ð¥Ã¥Õ¥¡»²¾È¥Ý¥¤¥ó¥¿
+ * @param wgt ½ÅÎ̵­½Ò¤òÊÖ¤¹¥Ð¥Ã¥Õ¥¡»²¾È¥Ý¥¤¥ó¥¿
+ * @param lev À¸À®³¬µ­½Ò¤òÊÖ¤¹¥Ð¥Ã¥Õ¥¡»²¾È¥Ý¥¤¥ó¥¿
+ * @param val ²ÁÃͤòÊÖ¤¹¥Ð¥Ã¥Õ¥¡»²¾È¥Ý¥¤¥ó¥¿
+ * @param k ¥Ù¡¼¥¹¥¢¥¤¥Æ¥àID
+ * @return ¤Ê¤·
  */
 static void kind_info(char *buf, char *dam, char *wgt, int *lev, s32b *val, int k)
 {
@@ -272,7 +293,7 @@ static void kind_info(char *buf, char *dam, char *wgt, int *lev, s32b *val, int
 
 
        /* Level */
-       (*lev) = get_object_level(q_ptr);
+       (*lev) = k_info[q_ptr->k_idx].level;
 
        /* Value */
        (*val) = object_value(q_ptr);
@@ -283,7 +304,7 @@ static void kind_info(char *buf, char *dam, char *wgt, int *lev, s32b *val, int
 
 
        /* Description (too brief) */
-       object_desc_store(buf, q_ptr, FALSE, 0);
+       object_desc(buf, q_ptr, (OD_NAME_ONLY | OD_STORE));
 
 
        /* Misc info */
@@ -339,12 +360,15 @@ static void kind_info(char *buf, char *dam, char *wgt, int *lev, s32b *val, int
 }
 
 
-/*
+/*!
+ * @brief ³Æ¥Ù¡¼¥¹¥¢¥¤¥Æ¥à¤Î¾ðÊó¤ò°ì¹ÔËè¤Ëµ­½Ò¤¹¤ë /
  * Create a spoiler file for items
+ * @param fname ¥Õ¥¡¥¤¥ë̾
+ * @return ¤Ê¤·
  */
 static void spoil_obj_desc(cptr fname)
 {
-       int i, k, s, t, n = 0;
+       int i, k, s, t, n = 0, group_start = 0;
 
        u16b who[200];
 
@@ -355,7 +379,7 @@ static void spoil_obj_desc(cptr fname)
 
 
        /* Build the filename */
-       path_build(buf, 1024, ANGBAND_DIR_USER, fname);
+       path_build(buf, sizeof(buf), ANGBAND_DIR_USER, fname);
 
        /* File type is "TEXT" */
        FILE_TYPE(FILE_TYPE_TEXT);
@@ -388,54 +412,59 @@ static void spoil_obj_desc(cptr fname)
                /* Write out the group title */
                if (group_item[i].name)
                {
-                       /* Hack -- bubble-sort by cost and then level */
-                       for (s = 0; s < n - 1; s++)
+                       if (n)
                        {
-                               for (t = 0; t < n - 1; t++)
+                               /* Hack -- bubble-sort by cost and then level */
+                               for (s = 0; s < n - 1; s++)
                                {
-                                       int i1 = t;
-                                       int i2 = t + 1;
+                                       for (t = 0; t < n - 1; t++)
+                                       {
+                                               int i1 = t;
+                                               int i2 = t + 1;
 
-                                       int e1;
-                                       int e2;
+                                               int e1;
+                                               int e2;
 
-                                       s32b t1;
-                                       s32b t2;
+                                               s32b t1;
+                                               s32b t2;
 
-                                       kind_info(NULL, NULL, NULL, &e1, &t1, who[i1]);
-                                       kind_info(NULL, NULL, NULL, &e2, &t2, who[i2]);
+                                               kind_info(NULL, NULL, NULL, &e1, &t1, who[i1]);
+                                               kind_info(NULL, NULL, NULL, &e2, &t2, who[i2]);
 
-                                       if ((t1 > t2) || ((t1 == t2) && (e1 > e2)))
-                                       {
-                                               int tmp = who[i1];
-                                               who[i1] = who[i2];
-                                               who[i2] = tmp;
+                                               if ((t1 > t2) || ((t1 == t2) && (e1 > e2)))
+                                               {
+                                                       int tmp = who[i1];
+                                                       who[i1] = who[i2];
+                                                       who[i2] = tmp;
+                                               }
                                        }
                                }
-                       }
 
-                       /* Spoil each item */
-                       for (s = 0; s < n; s++)
-                       {
-                               int e;
-                               s32b v;
+                               fprintf(fff, "\n\n%s\n\n", group_item[group_start].name);
 
-                               /* Describe the kind */
-                               kind_info(buf, dam, wgt, &e, &v, who[s]);
+                               /* Spoil each item */
+                               for (s = 0; s < n; s++)
+                               {
+                                       int e;
+                                       s32b v;
 
-                               /* Dump it */
-                               fprintf(fff, "     %-45s%8s%7s%5d%9ld\n",
-                                       buf, dam, wgt, e, (long)(v));
-                       }
+                                       /* Describe the kind */
+                                       kind_info(buf, dam, wgt, &e, &v, who[s]);
 
-                       /* Start a new set */
-                       n = 0;
+                                       /* Dump it */
+                                       fprintf(fff, "     %-45s%8s%7s%5d%9ld\n",
+                                               buf, dam, wgt, e, (long)(v));
+                               }
+
+                               /* Start a new set */
+                               n = 0;
+                       }
 
                        /* Notice the end */
                        if (!group_item[i].tval) break;
 
                        /* Start a new set */
-                       fprintf(fff, "\n\n%s\n\n", group_item[i].name);
+                       group_start = i;
                }
 
                /* Acquire legal item types */
@@ -508,6 +537,7 @@ static grouper group_artifact[] =
        { TV_DIGGING,           "¥·¥ã¥Ù¥ë/¤Ä¤ë¤Ï¤·" },
        { TV_BOW,               "Èô¤ÓÆ»¶ñ" },
        { TV_ARROW,             "Ìð" },
+       { TV_BOLT,              NULL },
 
        { TV_SOFT_ARMOR,        "³»" },
        { TV_HARD_ARMOR,        NULL },
@@ -531,6 +561,7 @@ static grouper group_artifact[] =
        { TV_DIGGING,           "Shovels/Picks" },
        { TV_BOW,               "Bows" },
        { TV_ARROW,             "Ammo" },
+       { TV_BOLT,              NULL },
 
        { TV_SOFT_ARMOR,        "Body Armor" },
        { TV_HARD_ARMOR,        NULL },
@@ -568,7 +599,7 @@ typedef struct flag_desc flag_desc;
 
 struct flag_desc
 {
-       const u32b flag;
+       const int flag;
        const char *const desc;
 };
 
@@ -584,19 +615,19 @@ struct flag_desc
 static flag_desc stat_flags_desc[] =
 {
 #ifdef JP
-       { TR1_STR,        "ÏÓÎÏ" },
-       { TR1_INT,        "ÃÎǽ" },
-       { TR1_WIS,        "¸­¤µ" },
-       { TR1_DEX,        "´ïÍѤµ" },
-       { TR1_CON,        "Âѵ×ÎÏ" },
-       { TR1_CHR,        "Ì¥ÎÏ" }
+       { TR_STR,        "ÏÓÎÏ" },
+       { TR_INT,        "ÃÎǽ" },
+       { TR_WIS,        "¸­¤µ" },
+       { TR_DEX,        "´ïÍѤµ" },
+       { TR_CON,        "Âѵ×ÎÏ" },
+       { TR_CHR,        "Ì¥ÎÏ" }
 #else
-       { TR1_STR,        "STR" },
-       { TR1_INT,        "INT" },
-       { TR1_WIS,        "WIS" },
-       { TR1_DEX,        "DEX" },
-       { TR1_CON,        "CON" },
-       { TR1_CHR,        "CHR" }
+       { TR_STR,        "STR" },
+       { TR_INT,        "INT" },
+       { TR_WIS,        "WIS" },
+       { TR_DEX,        "DEX" },
+       { TR_CON,        "CON" },
+       { TR_CHR,        "CHR" }
 #endif
 };
 
@@ -608,20 +639,20 @@ static flag_desc stat_flags_desc[] =
 static flag_desc pval_flags1_desc[] =
 {
 #ifdef JP
-       { TR1_MAGIC_MASTERY,    "ËâË¡Æ»¶ñ»ÈÍÑǽÎÏ" },
-       { TR1_STEALTH,    "±£Ì©" },
-       { TR1_SEARCH,     "õº÷" },
-       { TR1_INFRA,      "ÀÖ³°Àþ»ëÎÏ" },
-       { TR1_TUNNEL,     "ºÎ·¡" },
-       { TR1_BLOWS,      "¹¶·â²ó¿ô" },
-       { TR1_SPEED,      "¥¹¥Ô¡¼¥É" }
+       { TR_MAGIC_MASTERY,    "ËâË¡Æ»¶ñ»ÈÍÑǽÎÏ" },
+       { TR_STEALTH,    "±£Ì©" },
+       { TR_SEARCH,     "õº÷" },
+       { TR_INFRA,      "ÀÖ³°Àþ»ëÎÏ" },
+       { TR_TUNNEL,     "ºÎ·¡" },
+       { TR_BLOWS,      "¹¶·â²ó¿ô" },
+       { TR_SPEED,      "¥¹¥Ô¡¼¥É" }
 #else
-       { TR1_STEALTH,    "Stealth" },
-       { TR1_SEARCH,     "Searching" },
-       { TR1_INFRA,      "Infravision" },
-       { TR1_TUNNEL,     "Tunneling" },
-       { TR1_BLOWS,      "Attacks" },
-       { TR1_SPEED,      "Speed" }
+       { TR_STEALTH,    "Stealth" },
+       { TR_SEARCH,     "Searching" },
+       { TR_INFRA,      "Infravision" },
+       { TR_TUNNEL,     "Tunneling" },
+       { TR_BLOWS,      "Attacks" },
+       { TR_SPEED,      "Speed" }
 #endif
 };
 
@@ -632,27 +663,43 @@ static flag_desc pval_flags1_desc[] =
 static flag_desc slay_flags_desc[] =
 {
 #ifdef JP
-       { TR1_SLAY_ANIMAL,        "ưʪ" },
-       { TR1_SLAY_EVIL,          "¼Ù°­" },
-       { TR3_SLAY_HUMAN,         "¿Í´Ö" },
-       { TR1_SLAY_UNDEAD,        "¥¢¥ó¥Ç¥Ã¥É" },
-       { TR1_SLAY_DEMON,         "°­Ëâ" },
-       { TR1_SLAY_ORC,           "¥ª¡¼¥¯" },
-       { TR1_SLAY_TROLL,         "¥È¥í¥ë" },
-       { TR1_SLAY_GIANT,         "µð¿Í" },
-       { TR1_SLAY_DRAGON,        "¥É¥é¥´¥ó" },
-       { TR1_KILL_DRAGON,        "*¥É¥é¥´¥ó*" },
+       { TR_SLAY_ANIMAL,        "ưʪ" },
+       { TR_KILL_ANIMAL,        "*ưʪ*" },
+       { TR_SLAY_EVIL,          "¼Ù°­" },
+       { TR_KILL_EVIL,          "*¼Ù°­*" },
+       { TR_SLAY_HUMAN,         "¿Í´Ö" },
+       { TR_KILL_HUMAN,         "*¿Í´Ö*" },
+       { TR_SLAY_UNDEAD,        "¥¢¥ó¥Ç¥Ã¥É" },
+       { TR_KILL_UNDEAD,        "*¥¢¥ó¥Ç¥Ã¥É*" },
+       { TR_SLAY_DEMON,         "°­Ëâ" },
+       { TR_KILL_DEMON,         "*°­Ëâ*" },
+       { TR_SLAY_ORC,           "¥ª¡¼¥¯" },
+       { TR_KILL_ORC,           "*¥ª¡¼¥¯*" },
+       { TR_SLAY_TROLL,         "¥È¥í¥ë" },
+       { TR_KILL_TROLL,         "*¥È¥í¥ë*" },
+       { TR_SLAY_GIANT,         "µð¿Í" },
+       { TR_KILL_GIANT,         "*µð¿Í*" },
+       { TR_SLAY_DRAGON,        "¥É¥é¥´¥ó" },
+       { TR_KILL_DRAGON,        "*¥É¥é¥´¥ó*" },
 #else
-       { TR1_SLAY_ANIMAL,        "Animal" },
-       { TR1_SLAY_EVIL,          "Evil" },
-       { TR3_SLAY_HUMAN,         "Human" },
-       { TR1_SLAY_UNDEAD,        "Undead" },
-       { TR1_SLAY_DEMON,         "Demon" },
-       { TR1_SLAY_ORC,           "Orc" },
-       { TR1_SLAY_TROLL,         "Troll" },
-       { TR1_SLAY_GIANT,         "Giant" },
-       { TR1_SLAY_DRAGON,        "Dragon" },
-       { TR1_KILL_DRAGON,        "Xdragon" }
+       { TR_SLAY_ANIMAL,        "Animal" },
+       { TR_KILL_ANIMAL,        "XAnimal" },
+       { TR_SLAY_EVIL,          "Evil" },
+       { TR_KILL_EVIL,          "XEvil" },
+       { TR_SLAY_HUMAN,         "Human" },
+       { TR_KILL_HUMAN,         "XHuman" },
+       { TR_SLAY_UNDEAD,        "Undead" },
+       { TR_KILL_UNDEAD,        "XUndead" },
+       { TR_SLAY_DEMON,         "Demon" },
+       { TR_KILL_DEMON,         "XDemon" },
+       { TR_SLAY_ORC,           "Orc" },
+       { TR_KILL_ORC,           "XOrc" },
+       { TR_SLAY_TROLL,         "Troll" },
+       { TR_KILL_TROLL,         "XTroll" },
+       { TR_SLAY_GIANT,         "Giant" },
+       { TR_KILL_GIANT,         "Xgiant" },
+       { TR_SLAY_DRAGON,        "Dragon" },
+       { TR_KILL_DRAGON,        "Xdragon" }
 #endif
 };
 
@@ -667,29 +714,29 @@ static flag_desc slay_flags_desc[] =
 static flag_desc brand_flags_desc[] =
 {
 #ifdef JP
-       { TR1_BRAND_ACID,         "Íϲò" },
-       { TR1_BRAND_ELEC,         "ÅÅ·â" },
-       { TR1_BRAND_FIRE,         "¾Æ´þ" },
-       { TR1_BRAND_COLD,         "Åà·ë" },
-       { TR1_BRAND_POIS,         "ÆÇ»¦" },
-
-       { TR1_FORCE_WEAPON,       "ÍýÎÏ" },
-       { TR1_CHAOTIC,            "º®ÆÙ" },
-       { TR1_VAMPIRIC,           "µÛ·ì" },
-       { TR1_IMPACT,             "ÃÏ¿Ì" },
-       { TR1_VORPAL,             "ÀÚ¤ìÌ£" },
+       { TR_BRAND_ACID,         "Íϲò" },
+       { TR_BRAND_ELEC,         "ÅÅ·â" },
+       { TR_BRAND_FIRE,         "¾Æ´þ" },
+       { TR_BRAND_COLD,         "Åà·ë" },
+       { TR_BRAND_POIS,         "ÆÇ»¦" },
+
+       { TR_FORCE_WEAPON,       "ÍýÎÏ" },
+       { TR_CHAOTIC,            "º®ÆÙ" },
+       { TR_VAMPIRIC,           "µÛ·ì" },
+       { TR_IMPACT,             "ÃÏ¿Ì" },
+       { TR_VORPAL,             "ÀÚ¤ìÌ£" },
 #else
-       { TR1_BRAND_ACID,         "Acid Brand" },
-       { TR1_BRAND_ELEC,         "Lightning Brand" },
-       { TR1_BRAND_FIRE,         "Flame Tongue" },
-       { TR1_BRAND_COLD,         "Frost Brand" },
-       { TR1_BRAND_POIS,         "Poisoned" },
-
-       { TR1_FORCE_WEAPON,       "Force" },
-       { TR1_CHAOTIC,            "Mark of Chaos" },
-       { TR1_VAMPIRIC,           "Vampiric" },
-       { TR1_IMPACT,             "Earthquake impact on hit" },
-       { TR1_VORPAL,             "Very sharp" },
+       { TR_BRAND_ACID,         "Acid Brand" },
+       { TR_BRAND_ELEC,         "Lightning Brand" },
+       { TR_BRAND_FIRE,         "Flame Tongue" },
+       { TR_BRAND_COLD,         "Frost Brand" },
+       { TR_BRAND_POIS,         "Poisoned" },
+
+       { TR_FORCE_WEAPON,       "Force" },
+       { TR_CHAOTIC,            "Mark of Chaos" },
+       { TR_VAMPIRIC,           "Vampiric" },
+       { TR_IMPACT,             "Earthquake impact on hit" },
+       { TR_VORPAL,             "Very sharp" },
 #endif
 };
 
@@ -700,39 +747,39 @@ static flag_desc brand_flags_desc[] =
 static const flag_desc resist_flags_desc[] =
 {
 #ifdef JP
-       { TR2_RES_ACID,   "»À" },
-       { TR2_RES_ELEC,   "ÅÅ·â" },
-       { TR2_RES_FIRE,   "²Ð±ê" },
-       { TR2_RES_COLD,   "Î䵤" },
-       { TR2_RES_POIS,   "ÆÇ" },
-       { TR2_RES_FEAR,   "¶²ÉÝ"},
-       { TR2_RES_LITE,   "Á®¸÷" },
-       { TR2_RES_DARK,   "°Å¹õ" },
-       { TR2_RES_BLIND,  "ÌÕÌÜ" },
-       { TR2_RES_CONF,   "º®Íð" },
-       { TR2_RES_SOUND,  "¹ì²»" },
-       { TR2_RES_SHARDS, "ÇËÊÒ" },
-       { TR2_RES_NETHER, "ÃϹö" },
-       { TR2_RES_NEXUS,  "°ø²Ìº®Íð" },
-       { TR2_RES_CHAOS,  "¥«¥ª¥¹" },
-       { TR2_RES_DISEN,  "Îô²½" },
+       { TR_RES_ACID,   "»À" },
+       { TR_RES_ELEC,   "ÅÅ·â" },
+       { TR_RES_FIRE,   "²Ð±ê" },
+       { TR_RES_COLD,   "Î䵤" },
+       { TR_RES_POIS,   "ÆÇ" },
+       { TR_RES_FEAR,   "¶²ÉÝ"},
+       { TR_RES_LITE,   "Á®¸÷" },
+       { TR_RES_DARK,   "°Å¹õ" },
+       { TR_RES_BLIND,  "ÌÕÌÜ" },
+       { TR_RES_CONF,   "º®Íð" },
+       { TR_RES_SOUND,  "¹ì²»" },
+       { TR_RES_SHARDS, "ÇËÊÒ" },
+       { TR_RES_NETHER, "ÃϹö" },
+       { TR_RES_NEXUS,  "°ø²Ìº®Íð" },
+       { TR_RES_CHAOS,  "¥«¥ª¥¹" },
+       { TR_RES_DISEN,  "Îô²½" },
 #else
-       { TR2_RES_ACID,   "Acid" },
-       { TR2_RES_ELEC,   "Lightning" },
-       { TR2_RES_FIRE,   "Fire" },
-       { TR2_RES_COLD,   "Cold" },
-       { TR2_RES_POIS,   "Poison" },
-       { TR2_RES_FEAR,   "Fear"},
-       { TR2_RES_LITE,   "Light" },
-       { TR2_RES_DARK,   "Dark" },
-       { TR2_RES_BLIND,  "Blindness" },
-       { TR2_RES_CONF,   "Confusion" },
-       { TR2_RES_SOUND,  "Sound" },
-       { TR2_RES_SHARDS, "Shards" },
-       { TR2_RES_NETHER, "Nether" },
-       { TR2_RES_NEXUS,  "Nexus" },
-       { TR2_RES_CHAOS,  "Chaos" },
-       { TR2_RES_DISEN,  "Disenchantment" },
+       { TR_RES_ACID,   "Acid" },
+       { TR_RES_ELEC,   "Lightning" },
+       { TR_RES_FIRE,   "Fire" },
+       { TR_RES_COLD,   "Cold" },
+       { TR_RES_POIS,   "Poison" },
+       { TR_RES_FEAR,   "Fear"},
+       { TR_RES_LITE,   "Light" },
+       { TR_RES_DARK,   "Dark" },
+       { TR_RES_BLIND,  "Blindness" },
+       { TR_RES_CONF,   "Confusion" },
+       { TR_RES_SOUND,  "Sound" },
+       { TR_RES_SHARDS, "Shards" },
+       { TR_RES_NETHER, "Nether" },
+       { TR_RES_NEXUS,  "Nexus" },
+       { TR_RES_CHAOS,  "Chaos" },
+       { TR_RES_DISEN,  "Disenchantment" },
 #endif
 };
 
@@ -743,15 +790,15 @@ static const flag_desc resist_flags_desc[] =
 static const flag_desc immune_flags_desc[] =
 {
 #ifdef JP
-       { TR2_IM_ACID,    "»À" },
-       { TR2_IM_ELEC,    "ÅÅ·â" },
-       { TR2_IM_FIRE,    "²Ð±ê" },
-       { TR2_IM_COLD,    "Î䵤" },
+       { TR_IM_ACID,    "»À" },
+       { TR_IM_ELEC,    "ÅÅ·â" },
+       { TR_IM_FIRE,    "²Ð±ê" },
+       { TR_IM_COLD,    "Î䵤" },
 #else
-       { TR2_IM_ACID,    "Acid" },
-       { TR2_IM_ELEC,    "Lightning" },
-       { TR2_IM_FIRE,    "Fire" },
-       { TR2_IM_COLD,    "Cold" },
+       { TR_IM_ACID,    "Acid" },
+       { TR_IM_ELEC,    "Lightning" },
+       { TR_IM_FIRE,    "Fire" },
+       { TR_IM_COLD,    "Cold" },
 #endif
 };
 
@@ -762,19 +809,19 @@ static const flag_desc immune_flags_desc[] =
 static const flag_desc sustain_flags_desc[] =
 {
 #ifdef JP
-       { TR2_SUST_STR,   "ÏÓÎÏ" },
-       { TR2_SUST_INT,   "ÃÎǽ" },
-       { TR2_SUST_WIS,   "¸­¤µ" },
-       { TR2_SUST_DEX,   "´ïÍѤµ" },
-       { TR2_SUST_CON,   "Âѵ×ÎÏ" },
-       { TR2_SUST_CHR,   "Ì¥ÎÏ" },
+       { TR_SUST_STR,   "ÏÓÎÏ" },
+       { TR_SUST_INT,   "ÃÎǽ" },
+       { TR_SUST_WIS,   "¸­¤µ" },
+       { TR_SUST_DEX,   "´ïÍѤµ" },
+       { TR_SUST_CON,   "Âѵ×ÎÏ" },
+       { TR_SUST_CHR,   "Ì¥ÎÏ" },
 #else
-       { TR2_SUST_STR,   "STR" },
-       { TR2_SUST_INT,   "INT" },
-       { TR2_SUST_WIS,   "WIS" },
-       { TR2_SUST_DEX,   "DEX" },
-       { TR2_SUST_CON,   "CON" },
-       { TR2_SUST_CHR,   "CHR" },
+       { TR_SUST_STR,   "STR" },
+       { TR_SUST_INT,   "INT" },
+       { TR_SUST_WIS,   "WIS" },
+       { TR_SUST_DEX,   "DEX" },
+       { TR_SUST_CON,   "CON" },
+       { TR_SUST_CHR,   "CHR" },
 #endif
 };
 
@@ -785,15 +832,15 @@ static const flag_desc sustain_flags_desc[] =
 static const flag_desc misc_flags2_desc[] =
 {
 #ifdef JP
-       { TR2_THROW,      "ÅêÚ³" },
-       { TR2_REFLECT,    "È¿¼Í" },
-       { TR2_FREE_ACT,   "ËãáãÃΤ餺" },
-       { TR2_HOLD_LIFE,  "À¸Ì¿ÎÏ°Ý»ý" },
+       { TR_THROW,      "ÅêÚ³" },
+       { TR_REFLECT,    "È¿¼Í" },
+       { TR_FREE_ACT,   "ËãáãÃΤ餺" },
+       { TR_HOLD_EXP,   "·Ð¸³ÃÍ°Ý»ý" },
 #else
-       { TR2_THROW,      "Throwing" },
-       { TR2_REFLECT,    "Reflection" },
-       { TR2_FREE_ACT,   "Free Action" },
-       { TR2_HOLD_LIFE,  "Hold Life" },
+       { TR_THROW,      "Throwing" },
+       { TR_REFLECT,    "Reflection" },
+       { TR_FREE_ACT,   "Free Action" },
+       { TR_HOLD_EXP,   "Hold Experience" },
 #endif
 };
 
@@ -807,41 +854,65 @@ static const flag_desc misc_flags2_desc[] =
 static const flag_desc misc_flags3_desc[] =
 {
 #ifdef JP
-       { TR3_SH_FIRE,            "²Ð±ê¥ª¡¼¥é" },
-       { TR3_SH_ELEC,            "Åŷ⥪¡¼¥é" },
-       { TR3_SH_COLD,            "Î䵤¥ª¡¼¥é" },
-       { TR3_NO_TELE,            "È¿¥Æ¥ì¥Ý¡¼¥È" },
-       { TR3_NO_MAGIC,           "È¿ËâË¡" },
-       { TR3_FEATHER,            "ÉâÍ·" },
-       { TR3_SEE_INVIS,          "²Ä»ëÆ©ÌÀ" },
-       { TR3_TELEPATHY,          "¥Æ¥ì¥Ñ¥·¡¼" },
-       { TR3_SLOW_DIGEST,        "Ãپò½" },
-       { TR3_REGEN,              "µÞ®²óÉü" },
-       { TR3_WARNING,            "·Ù¹ð" },
-/*     { TR3_XTRA_MIGHT,         "¶¯Îϼͷâ" }, */
-       { TR3_XTRA_SHOTS,         "Äɲüͷâ" },        /* always +1? */
-       { TR3_DRAIN_EXP,          "·Ð¸³Ã͵ۼý" },
-       { TR3_AGGRAVATE,          "È¿´¶" },
-       { TR3_BLESSED,            "½ËÊ¡" },
-       { TR3_DEC_MANA,           "¾ÃÈñËâÎϸº¾¯" },
+       { TR_SH_FIRE,            "²Ð±ê¥ª¡¼¥é" },
+       { TR_SH_ELEC,            "Åŷ⥪¡¼¥é" },
+       { TR_SH_COLD,            "Î䵤¥ª¡¼¥é" },
+       { TR_NO_TELE,            "È¿¥Æ¥ì¥Ý¡¼¥È" },
+       { TR_NO_MAGIC,           "È¿ËâË¡" },
+       { TR_LEVITATION,         "ÉâÍ·" },
+       { TR_SEE_INVIS,          "²Ä»ëÆ©ÌÀ" },
+       { TR_TELEPATHY,          "¥Æ¥ì¥Ñ¥·¡¼" },
+       { TR_ESP_ANIMAL,         "ưʪ´¶ÃÎ" },
+       { TR_ESP_UNDEAD,         "ÉԻശÃÎ" },
+       { TR_ESP_DEMON,          "°­Ëâ´¶ÃÎ" },
+       { TR_ESP_ORC,            "¥ª¡¼¥¯´¶ÃÎ" },
+       { TR_ESP_TROLL,          "¥È¥í¥ë´¶ÃÎ" },
+       { TR_ESP_GIANT,          "µð¿Í´¶ÃÎ" },
+       { TR_ESP_DRAGON,         "¥É¥é¥´¥ó´¶ÃÎ" },
+       { TR_ESP_HUMAN,          "¿Í´Ö´¶ÃÎ" },
+       { TR_ESP_EVIL,           "¼Ù°­´¶ÃÎ" },
+       { TR_ESP_GOOD,           "Á±ÎÉ´¶ÃÎ" },
+       { TR_ESP_NONLIVING,      "̵À¸Êª´¶ÃÎ" },
+       { TR_ESP_UNIQUE,         "¥æ¥Ë¡¼¥¯´¶ÃÎ" },
+       { TR_SLOW_DIGEST,        "Ãپò½" },
+       { TR_REGEN,              "µÞ®²óÉü" },
+       { TR_WARNING,            "·Ù¹ð" },
+/*     { TR_XTRA_MIGHT,         "¶¯Îϼͷâ" }, */
+       { TR_XTRA_SHOTS,         "Äɲüͷâ" },        /* always +1? */
+       { TR_DRAIN_EXP,          "·Ð¸³Ã͵ۼý" },
+       { TR_AGGRAVATE,          "È¿´¶" },
+       { TR_BLESSED,            "½ËÊ¡" },
+       { TR_DEC_MANA,           "¾ÃÈñËâÎϸº¾¯" },
 #else
-       { TR3_SH_FIRE,            "Fiery Aura" },
-       { TR3_SH_ELEC,            "Electric Aura" },
-       { TR3_SH_COLD,            "Coldly Aura" },
-       { TR3_NO_TELE,            "Prevent Teleportation" },
-       { TR3_NO_MAGIC,           "Anti-Magic" },
-       { TR3_FEATHER,            "Levitation" },
-       { TR3_SEE_INVIS,          "See Invisible" },
-       { TR3_TELEPATHY,          "ESP" },
-       { TR3_SLOW_DIGEST,        "Slow Digestion" },
-       { TR3_REGEN,              "Regeneration" },
-       { TR3_WARNING,            "Warning" },
-/*     { TR3_XTRA_MIGHT,         "Extra Might" }, */
-       { TR3_XTRA_SHOTS,         "+1 Extra Shot" },        /* always +1? */
-       { TR3_DRAIN_EXP,          "Drains Experience" },
-       { TR3_AGGRAVATE,          "Aggravates" },
-       { TR3_BLESSED,            "Blessed Blade" },
-       { TR3_DEC_MANA,           "Decrease Shouhi Mana" },
+       { TR_SH_FIRE,            "Fiery Aura" },
+       { TR_SH_ELEC,            "Electric Aura" },
+       { TR_SH_COLD,            "Coldly Aura" },
+       { TR_NO_TELE,            "Prevent Teleportation" },
+       { TR_NO_MAGIC,           "Anti-Magic" },
+       { TR_LEVITATION,            "Levitation" },
+       { TR_SEE_INVIS,          "See Invisible" },
+       { TR_TELEPATHY,          "ESP" },
+       { TR_ESP_ANIMAL,         "Sense Animal" },
+       { TR_ESP_UNDEAD,         "Sense Undead" },
+       { TR_ESP_DEMON,          "Sense Demon" },
+       { TR_ESP_ORC,            "Sense Orc" },
+       { TR_ESP_TROLL,          "Sense Troll" },
+       { TR_ESP_GIANT,          "Sense Giant" },
+       { TR_ESP_DRAGON,         "Sense Dragon" },
+       { TR_ESP_HUMAN,          "Sense Human" },
+       { TR_ESP_EVIL,           "Sense Evil" },
+       { TR_ESP_GOOD,           "Sense Good" },
+       { TR_ESP_NONLIVING,      "Sense Nonliving" },
+       { TR_ESP_UNIQUE,         "Sense Unique" },
+       { TR_SLOW_DIGEST,        "Slow Digestion" },
+       { TR_REGEN,              "Regeneration" },
+       { TR_WARNING,            "Warning" },
+/*     { TR_XTRA_MIGHT,         "Extra Might" }, */
+       { TR_XTRA_SHOTS,         "+1 Extra Shot" },        /* always +1? */
+       { TR_DRAIN_EXP,          "Drains Experience" },
+       { TR_AGGRAVATE,          "Aggravates" },
+       { TR_BLESSED,            "Blessed Blade" },
+       { TR_DEC_MANA,           "Decrease Mana Consumption Rate" },
 #endif
 };
 
@@ -914,6 +985,9 @@ typedef struct
                        + 1       /* type of curse */
                        + 1];     /* sentinel NULL */
 
+       /* Additional ability or resistance */
+       char addition[80];
+
        /* A string describing an artifact's activation */
        cptr activation;
 
@@ -962,14 +1036,15 @@ static void spoiler_underline(cptr str)
  *
  * The possibly updated description pointer is returned.
  */
-static cptr *spoiler_flag_aux(const u32b art_flags, const flag_desc *flag_ptr,
+static cptr *spoiler_flag_aux(const u32b art_flags[TR_FLAG_SIZE],
+                             const flag_desc *flag_ptr,
                              cptr *desc_ptr, const int n_elmnts)
 {
        int i;
 
        for (i = 0; i < n_elmnts; ++i)
        {
-               if (art_flags & flag_ptr[i].flag)
+               if (have_flag(art_flags, flag_ptr[i].flag))
                {
                        *desc_ptr++ = flag_ptr[i].desc;
                }
@@ -982,10 +1057,10 @@ static cptr *spoiler_flag_aux(const u32b art_flags, const flag_desc *flag_ptr,
 /*
  * Acquire a "basic" description "The Cloak of Death [1,+10]"
  */
-static void analyze_general (object_type *o_ptr, char *desc_ptr)
+static void analyze_general(object_type *o_ptr, char *desc_ptr)
 {
        /* Get a "useful" description of the object */
-       object_desc_store(desc_ptr, o_ptr, TRUE, 1);
+       object_desc(desc_ptr, o_ptr, (OD_NAME_AND_ENCHANT | OD_STORE));
 }
 
 
@@ -993,12 +1068,9 @@ static void analyze_general (object_type *o_ptr, char *desc_ptr)
  * List "player traits" altered by an artifact's pval. These include stats,
  * speed, infravision, tunneling, stealth, searching, and extra attacks.
  */
-static void analyze_pval (object_type *o_ptr, pval_info_type *p_ptr)
+static void analyze_pval(object_type *o_ptr, pval_info_type *p_ptr)
 {
-       const u32b all_stats = (TR1_STR | TR1_INT | TR1_WIS |
-                               TR1_DEX | TR1_CON | TR1_CHR);
-
-       u32b f1, f2, f3;
+       u32b flgs[TR_FLAG_SIZE];
 
        cptr *affects_list;
 
@@ -1011,7 +1083,7 @@ static void analyze_pval (object_type *o_ptr, pval_info_type *p_ptr)
        }
 
        /* Extract the flags */
-       object_flags(o_ptr, &f1, &f2, &f3);
+       object_flags(o_ptr, flgs);
 
        affects_list = p_ptr->pval_affects;
 
@@ -1019,7 +1091,9 @@ static void analyze_pval (object_type *o_ptr, pval_info_type *p_ptr)
        sprintf(p_ptr->pval_desc, "%s%d", POSITIZE(o_ptr->pval), o_ptr->pval);
 
        /* First, check to see if the pval affects all stats */
-       if ((f1 & all_stats) == all_stats)
+       if (have_flag(flgs, TR_STR) && have_flag(flgs, TR_INT) &&
+           have_flag(flgs, TR_WIS) && have_flag(flgs, TR_DEX) &&
+           have_flag(flgs, TR_CON) && have_flag(flgs, TR_CHR))
        {
 #ifdef JP
                *affects_list++ = "Á´Ç½ÎÏ";
@@ -1029,15 +1103,17 @@ static void analyze_pval (object_type *o_ptr, pval_info_type *p_ptr)
        }
 
        /* Are any stats affected? */
-       else if (f1 & all_stats)
+       else if (have_flag(flgs, TR_STR) || have_flag(flgs, TR_INT) ||
+                have_flag(flgs, TR_WIS) || have_flag(flgs, TR_DEX) ||
+                have_flag(flgs, TR_CON) || have_flag(flgs, TR_CHR))
        {
-               affects_list = spoiler_flag_aux(f1, stat_flags_desc,
+               affects_list = spoiler_flag_aux(flgs, stat_flags_desc,
                                                affects_list,
                                                N_ELEMENTS(stat_flags_desc));
        }
 
        /* And now the "rest" */
-       affects_list = spoiler_flag_aux(f1, pval_flags1_desc,
+       affects_list = spoiler_flag_aux(flgs, pval_flags1_desc,
                                        affects_list,
                                        N_ELEMENTS(pval_flags1_desc));
 
@@ -1047,13 +1123,13 @@ static void analyze_pval (object_type *o_ptr, pval_info_type *p_ptr)
 
 
 /* Note the slaying specialties of a weapon */
-static void analyze_slay (object_type *o_ptr, cptr *slay_list)
+static void analyze_slay(object_type *o_ptr, cptr *slay_list)
 {
-       u32b f1, f2, f3;
+       u32b flgs[TR_FLAG_SIZE];
 
-       object_flags(o_ptr, &f1, &f2, &f3);
+       object_flags(o_ptr, flgs);
 
-       slay_list = spoiler_flag_aux(f1, slay_flags_desc, slay_list,
+       slay_list = spoiler_flag_aux(flgs, slay_flags_desc, slay_list,
                                     N_ELEMENTS(slay_flags_desc));
 
        /* Terminate the description list */
@@ -1061,13 +1137,13 @@ static void analyze_slay (object_type *o_ptr, cptr *slay_list)
 }
 
 /* Note an object's elemental brands */
-static void analyze_brand (object_type *o_ptr, cptr *brand_list)
+static void analyze_brand(object_type *o_ptr, cptr *brand_list)
 {
-       u32b f1, f2, f3;
+       u32b flgs[TR_FLAG_SIZE];
 
-       object_flags(o_ptr, &f1, &f2, &f3);
+       object_flags(o_ptr, flgs);
 
-       brand_list = spoiler_flag_aux(f1, brand_flags_desc, brand_list,
+       brand_list = spoiler_flag_aux(flgs, brand_flags_desc, brand_list,
                                      N_ELEMENTS(brand_flags_desc));
 
        /* Terminate the description list */
@@ -1076,13 +1152,13 @@ static void analyze_brand (object_type *o_ptr, cptr *brand_list)
 
 
 /* Note the resistances granted by an object */
-static void analyze_resist (object_type *o_ptr, cptr *resist_list)
+static void analyze_resist(object_type *o_ptr, cptr *resist_list)
 {
-       u32b f1, f2, f3;
+       u32b flgs[TR_FLAG_SIZE];
 
-       object_flags(o_ptr, &f1, &f2, &f3);
+       object_flags(o_ptr, flgs);
 
-       resist_list = spoiler_flag_aux(f2, resist_flags_desc,
+       resist_list = spoiler_flag_aux(flgs, resist_flags_desc,
                                       resist_list, N_ELEMENTS(resist_flags_desc));
 
        /* Terminate the description list */
@@ -1091,32 +1167,31 @@ static void analyze_resist (object_type *o_ptr, cptr *resist_list)
 
 
 /* Note the immunities granted by an object */
-static void analyze_immune (object_type *o_ptr, cptr *immune_list)
+static void analyze_immune(object_type *o_ptr, cptr *immune_list)
 {
-       u32b f1, f2, f3;
+       u32b flgs[TR_FLAG_SIZE];
 
-       object_flags(o_ptr, &f1, &f2, &f3);
+       object_flags(o_ptr, flgs);
 
-       immune_list = spoiler_flag_aux(f2, immune_flags_desc,
+       immune_list = spoiler_flag_aux(flgs, immune_flags_desc,
                                       immune_list, N_ELEMENTS(immune_flags_desc));
 
        /* Terminate the description list */
        *immune_list = NULL;
 }
 
-/* Note which stats an object sustains */
 
-static void analyze_sustains (object_type *o_ptr, cptr *sustain_list)
+/* Note which stats an object sustains */
+static void analyze_sustains(object_type *o_ptr, cptr *sustain_list)
 {
-       const u32b all_sustains = (TR2_SUST_STR | TR2_SUST_INT | TR2_SUST_WIS |
-                                  TR2_SUST_DEX | TR2_SUST_CON | TR2_SUST_CHR);
-
-       u32b f1, f2, f3;
+       u32b flgs[TR_FLAG_SIZE];
 
-       object_flags(o_ptr, &f1, &f2, &f3);
+       object_flags(o_ptr, flgs);
 
        /* Simplify things if an item sustains all stats */
-       if ((f2 & all_sustains) == all_sustains)
+       if (have_flag(flgs, TR_SUST_STR) && have_flag(flgs, TR_SUST_INT) &&
+           have_flag(flgs, TR_SUST_WIS) && have_flag(flgs, TR_SUST_DEX) &&
+           have_flag(flgs, TR_SUST_CON) && have_flag(flgs, TR_SUST_CHR))
        {
 #ifdef JP
                *sustain_list++ = "Á´Ç½ÎÏ";
@@ -1126,9 +1201,11 @@ static void analyze_sustains (object_type *o_ptr, cptr *sustain_list)
        }
 
        /* Should we bother? */
-       else if ((f2 & all_sustains))
+       else if (have_flag(flgs, TR_SUST_STR) || have_flag(flgs, TR_SUST_INT) ||
+                have_flag(flgs, TR_SUST_WIS) || have_flag(flgs, TR_SUST_DEX) ||
+                have_flag(flgs, TR_SUST_CON) || have_flag(flgs, TR_SUST_CHR))
        {
-               sustain_list = spoiler_flag_aux(f2, sustain_flags_desc,
+               sustain_list = spoiler_flag_aux(flgs, sustain_flags_desc,
                                                sustain_list,
                                                N_ELEMENTS(sustain_flags_desc));
        }
@@ -1142,83 +1219,77 @@ static void analyze_sustains (object_type *o_ptr, cptr *sustain_list)
  * Note miscellaneous powers bestowed by an artifact such as see invisible,
  * free action, permanent light, etc.
  */
-static void analyze_misc_magic (object_type *o_ptr, cptr *misc_list)
+static void analyze_misc_magic(object_type *o_ptr, cptr *misc_list)
 {
-       u32b f1, f2, f3;
+       u32b flgs[TR_FLAG_SIZE];
+       int rad;
+       char desc[256];
 
-       object_flags(o_ptr, &f1, &f2, &f3);
+       object_flags(o_ptr, flgs);
 
-       misc_list = spoiler_flag_aux(f2, misc_flags2_desc, misc_list,
+       misc_list = spoiler_flag_aux(flgs, misc_flags2_desc, misc_list,
                                     N_ELEMENTS(misc_flags2_desc));
 
-       misc_list = spoiler_flag_aux(f3, misc_flags3_desc, misc_list,
+       misc_list = spoiler_flag_aux(flgs, misc_flags3_desc, misc_list,
                                     N_ELEMENTS(misc_flags3_desc));
 
        /*
-        * Artifact lights -- large radius light.
-        */
-       if ((o_ptr->tval == TV_LITE) && artifact_p(o_ptr))
+        * Glowing artifacts -- small radius light.
+       */      
+       rad = 0;
+       if (have_flag(flgs, TR_LITE_1))  rad += 1;
+       if (have_flag(flgs, TR_LITE_2))  rad += 2;
+       if (have_flag(flgs, TR_LITE_3))  rad += 3;
+       if (have_flag(flgs, TR_LITE_M1)) rad -= 1;
+       if (have_flag(flgs, TR_LITE_M2)) rad -= 2;
+       if (have_flag(flgs, TR_LITE_M3)) rad -= 3;
+       
+       if(o_ptr->name2 == EGO_LITE_SHINE) rad++;
+
+       if (have_flag(flgs, TR_LITE_FUEL))
        {
-#ifdef JP
-               *misc_list++ = "±Êµ×¸÷¸»(Ⱦ·Â3)";
-#else
-               *misc_list++ = "Permanent Light(3)";
-#endif
+               if(rad > 0) sprintf(desc, _("¤½¤ì¤ÏdzÎÁÊäµë¤Ë¤è¤Ã¤ÆÌÀ¤«¤ê(Ⱦ·Â %d)¤ò¼ø¤±¤ë¡£", "It provides light (radius %d) when fueled."), rad);     
        }
-
-       /*
-        * Glowing artifacts -- small radius light.
-        */
-       if (f3 & (TR3_LITE))
+       else
        {
-#ifdef JP
-               *misc_list++ = "±Êµ×¸÷¸»(Ⱦ·Â1)";
-#else
-               *misc_list++ = "Permanent Light(1)";
-#endif
+               if(rad > 0) sprintf(desc, _("±Êµ×¸÷¸»(Ⱦ·Â %d)", "Permanent Light(radius %d)"), rad);   
+               if(rad < 0) sprintf(desc, _("±Êµ×¸÷¸»(Ⱦ·Â-%d)¡£", "Permanent Light(radius -%d)"), -rad);
        }
 
+       if(rad != 0) *misc_list++ = quark_str(quark_add(desc));
+
        /*
         * Handle cursed objects here to avoid redundancies such as noting
         * that a permanently cursed object is heavily cursed as well as
         * being "lightly cursed".
         */
 
-/*     if (cursed_p(o_ptr)) */
-       if (1)
+/*     if (object_is_cursed(o_ptr)) */
        {
-               if (f3 & TR3_TY_CURSE)
+               if (have_flag(flgs, TR_TY_CURSE))
                {
-#ifdef JP
-                       *misc_list++ = "ÂÀ¸Å¤Î±åÇ°";
-#else
-                       *misc_list++ = "Ancient Curse";
-#endif
+                       *misc_list++ = _("ÂÀ¸Å¤Î±åÇ°", "Ancient Curse");
                }
                if (o_ptr->curse_flags & TRC_PERMA_CURSE)
                {
-#ifdef JP
-                       *misc_list++ = "±Ê±ó¤Î¼ö¤¤";
-#else
-                       *misc_list++ = "Permanently Cursed";
-#endif
+                       *misc_list++ = _("±Ê±ó¤Î¼ö¤¤", "Permanently Cursed");
                }
                else if (o_ptr->curse_flags & TRC_HEAVY_CURSE)
                {
-#ifdef JP
-                       *misc_list++ = "¶¯ÎϤʼö¤¤";
-#else
-                       *misc_list++ = "Heavily Cursed";
-#endif
+                       *misc_list++ = _("¶¯ÎϤʼö¤¤", "Heavily Cursed");
                }
 /*             else */
                else if (o_ptr->curse_flags & TRC_CURSED)
                {
-#ifdef JP
-                       *misc_list++ = "¼ö¤¤";
-#else
-                       *misc_list++ = "Cursed";
-#endif
+                       *misc_list++ = _("¼ö¤¤", "Cursed");
+               }
+               if (have_flag(flgs, TR_ADD_L_CURSE))
+               {
+                       *misc_list++ = _("¼ö¤¤¤òÁý¤ä¤¹", "Cursing");
+               }
+               if (have_flag(flgs, TR_ADD_H_CURSE))
+               {
+                       *misc_list++ = _("¶¯ÎϤʼö¤¤¤òÁý¤ä¤¹", "Heavily Cursing");
                }
        }
 
@@ -1227,20 +1298,58 @@ static void analyze_misc_magic (object_type *o_ptr, cptr *misc_list)
 }
 
 
+/*
+ * Note additional ability and/or resistance of fixed artifacts
+ */
+static void analyze_addition(object_type *o_ptr, char *addition)
+{
+       artifact_type *a_ptr = &a_info[o_ptr->name1];
+
+       /* Init */
+       strcpy(addition, "");
+
+#ifdef JP
+       if ((a_ptr->gen_flags & TRG_XTRA_POWER) && (a_ptr->gen_flags & TRG_XTRA_H_RES)) strcat(addition, "ǽÎÏandÂÑÀ­");
+       else if (a_ptr->gen_flags & TRG_XTRA_POWER)
+       {
+               strcat(addition, "ǽÎÏ");
+               if (a_ptr->gen_flags & TRG_XTRA_RES_OR_POWER) strcat(addition, "(1/2¤ÇandÂÑÀ­)");
+       }
+       else if (a_ptr->gen_flags & TRG_XTRA_H_RES)
+       {
+               strcat(addition, "ÂÑÀ­");
+               if (a_ptr->gen_flags & TRG_XTRA_RES_OR_POWER) strcat(addition, "(1/2¤ÇandǽÎÏ)");
+       }
+       else if (a_ptr->gen_flags & TRG_XTRA_RES_OR_POWER) strcat(addition, "ǽÎÏorÂÑÀ­");
+#else
+       if ((a_ptr->gen_flags & TRG_XTRA_POWER) && (a_ptr->gen_flags & TRG_XTRA_H_RES)) strcat(addition, "Ability and Resistance");
+       else if (a_ptr->gen_flags & TRG_XTRA_POWER)
+       {
+               strcat(addition, "Ability");
+               if (a_ptr->gen_flags & TRG_XTRA_RES_OR_POWER) strcat(addition, "(plus Resistance about 1/2)");
+       }
+       else if (a_ptr->gen_flags & TRG_XTRA_H_RES)
+       {
+               strcat(addition, "Resistance");
+               if (a_ptr->gen_flags & TRG_XTRA_RES_OR_POWER) strcat(addition, "(plus Ability about 1/2)");
+       }
+       else if (a_ptr->gen_flags & TRG_XTRA_RES_OR_POWER) strcat(addition, "Ability or Resistance");
+#endif
+}
 
 
 /*
  * Determine the minimum depth an artifact can appear, its rarity, its weight,
  * and its value in gold pieces
  */
-static void analyze_misc (object_type *o_ptr, char *misc_desc)
+static void analyze_misc(object_type *o_ptr, char *misc_desc)
 {
        artifact_type *a_ptr = &a_info[o_ptr->name1];
 
 #ifdef JP
        sprintf(misc_desc, "¥ì¥Ù¥ë %u, ´õ¾¯ÅÙ %u, %d.%d kg, ¡ð%ld",
                a_ptr->level, a_ptr->rarity,
-               lbtokg1(a_ptr->weight), lbtokg2(a_ptr->weight), a_ptr->cost);
+               lbtokg1(a_ptr->weight), lbtokg2(a_ptr->weight), (long int)a_ptr->cost);
 #else
        sprintf(misc_desc, "Level %u, Rarity %u, %d.%d lbs, %ld Gold",
                a_ptr->level, a_ptr->rarity,
@@ -1255,23 +1364,15 @@ static void analyze_misc (object_type *o_ptr, char *misc_desc)
 static void object_analyze(object_type *o_ptr, obj_desc_list *desc_ptr)
 {
        analyze_general(o_ptr, desc_ptr->description);
-
        analyze_pval(o_ptr, &desc_ptr->pval_info);
-
        analyze_brand(o_ptr, desc_ptr->brands);
-
        analyze_slay(o_ptr, desc_ptr->slays);
-
        analyze_immune(o_ptr, desc_ptr->immunities);
-
        analyze_resist(o_ptr, desc_ptr->resistances);
-
        analyze_sustains(o_ptr, desc_ptr->sustains);
-
        analyze_misc_magic(o_ptr, desc_ptr->misc_magic);
-
+       analyze_addition(o_ptr, desc_ptr->addition);
        analyze_misc(o_ptr, desc_ptr->misc_desc);
-
        desc_ptr->activation = item_activation(o_ptr);
 }
 
@@ -1280,16 +1381,9 @@ static void print_header(void)
 {
        char buf[80];
 
-#ifndef FAKE_VERSION
-       sprintf(buf, "Artifact Spoilers for Angband Version %d.%d.%d",
-               VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH);
-       spoiler_underline(buf);
-#else /* FAKE_VERSION */
        sprintf(buf, "Artifact Spoilers for Hengband Version %d.%d.%d",
-               FAKE_VER_MAJOR-10, FAKE_VER_MINOR, FAKE_VER_PATCH);
+               FAKE_VER_MAJOR-10, FAKE_VER_MINOR, FAKE_VER_PATCH);
        spoiler_underline(buf);
-#endif /* FAKE_VERSION */
-
 }
 
 /*
@@ -1453,27 +1547,27 @@ static void spoiler_print_art(obj_desc_list *art_ptr)
 
 #ifdef JP
        spoiler_outlist("ÂÐ:", art_ptr->slays, ITEM_SEP);
-
        spoiler_outlist("Éð´ï°À­:", art_ptr->brands, LIST_SEP);
-
        spoiler_outlist("ÌȱÖ:", art_ptr->immunities, ITEM_SEP);
-
        spoiler_outlist("ÂÑÀ­:", art_ptr->resistances, ITEM_SEP);
-
        spoiler_outlist("°Ý»ý:", art_ptr->sustains, ITEM_SEP);
 #else
        spoiler_outlist("Slay", art_ptr->slays, ITEM_SEP);
-
        spoiler_outlist("", art_ptr->brands, LIST_SEP);
-
        spoiler_outlist("Immunity to", art_ptr->immunities, ITEM_SEP);
-
        spoiler_outlist("Resist", art_ptr->resistances, ITEM_SEP);
-
        spoiler_outlist("Sustain", art_ptr->sustains, ITEM_SEP);
 #endif
        spoiler_outlist("", art_ptr->misc_magic, LIST_SEP);
 
+       if (art_ptr->addition[0])
+       {
+#ifdef JP
+               fprintf(fff, "%sÄɲÃ: %s\n", INDENT1, art_ptr->addition);
+#else
+               fprintf(fff, "%sAdditional %s\n", INDENT1, art_ptr->addition);
+#endif
+       }
 
        /* Write out the possible activation at the primary indention level */
        if (art_ptr->activation)
@@ -1546,7 +1640,7 @@ static void spoil_artifact(cptr fname)
 
 
        /* Build the filename */
-       path_build(buf, 1024, ANGBAND_DIR_USER, fname);
+       path_build(buf, sizeof(buf), ANGBAND_DIR_USER, fname);
 
        /* File type is "TEXT" */
        FILE_TYPE(FILE_TYPE_TEXT);
@@ -1636,7 +1730,7 @@ static void spoil_mon_desc(cptr fname)
        char exp[80];
 
        /* Build the filename */
-       path_build(buf, 1024, ANGBAND_DIR_USER, fname);
+       path_build(buf, sizeof(buf), ANGBAND_DIR_USER, fname);
 
        /* File type is "TEXT" */
        FILE_TYPE(FILE_TYPE_TEXT);
@@ -1655,16 +1749,9 @@ static void spoil_mon_desc(cptr fname)
        C_MAKE(who, max_r_idx, s16b);
 
        /* Dump the header */
-
-#ifndef FAKE_VERSION
-       fprintf(fff, "Monster Spoilers for Angband Version %d.%d.%d\n",
-               VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH);
-       fprintf(fff, "------------------------------------------\n\n");
-#else
        fprintf(fff, "Monster Spoilers for Hengband Version %d.%d.%d\n",
-               FAKE_VER_MAJOR-10, FAKE_VER_MINOR, FAKE_VER_PATCH);
+               FAKE_VER_MAJOR-10, FAKE_VER_MINOR, FAKE_VER_PATCH);
        fprintf(fff, "------------------------------------------\n\n");
-#endif
 
        /* Dump the header */
        fprintf(fff, "    %-38.38s%4s%4s%4s%7s%5s  %11.11s\n",
@@ -1682,12 +1769,12 @@ static void spoil_mon_desc(cptr fname)
                if (r_ptr->name) who[n++] = i;
        }
 
-        /* Select the sort method */
-        ang_sort_comp = ang_sort_comp_hook;
-        ang_sort_swap = ang_sort_swap_hook;
+       /* Select the sort method */
+       ang_sort_comp = ang_sort_comp_hook;
+       ang_sort_swap = ang_sort_swap_hook;
 
-        /* Sort the array by dungeon depth of monsters */
-        ang_sort(who, &why, n);
+       /* Sort the array by dungeon depth of monsters */
+       ang_sort(who, &why, n);
 
        /* Scan again */
        for (i = 0; i < n; i++)
@@ -1698,11 +1785,12 @@ static void spoil_mon_desc(cptr fname)
                if (r_ptr->flags7 & (RF7_KAGE)) continue;
 
                /* Get the "name" */
-/*             if (r_ptr->flags1 & (RF1_QUESTOR)) */
-               if (0)
+               /*
+               else if (r_ptr->flags1 & (RF1_QUESTOR))
                {
                        sprintf(nam, "[Q] %s", name);
                }
+               */
                else if (r_ptr->flags1 & (RF1_UNIQUE))
                {
                        sprintf(nam, "[U] %s", name);
@@ -1751,7 +1839,7 @@ static void spoil_mon_desc(cptr fname)
                sprintf(exp, "%ld", (long)(r_ptr->mexp));
 
                /* Hack -- use visual instead */
-               sprintf(exp, "%s '%c'", attr_to_text(r_ptr->d_attr), r_ptr->d_char);
+               sprintf(exp, "%s '%c'", attr_to_text(r_ptr), r_ptr->d_char);
 
                /* Dump the info */
                fprintf(fff, "%-42.42s%4s%4s%4s%7s%5s  %11.11s\n",
@@ -1798,8 +1886,11 @@ static void spoil_out(cptr str)
        /* Line buffer */
        static char roff_buf[256];
 
+       /* Delay buffer */
+       static char roff_waiting_buf[256];
+
 #ifdef JP
-       char iskanji2=0;
+       bool iskanji_flag = FALSE;
 #endif
        /* Current pointer into line roff_buf */
        static char *roff_p = roff_buf;
@@ -1807,17 +1898,28 @@ static void spoil_out(cptr str)
        /* Last space saved into roff_buf */
        static char *roff_s = NULL;
 
+       /* Mega-Hack -- Delayed output */
+       static bool waiting_output = FALSE;
+
        /* Special handling for "new sequence" */
        if (!str)
        {
+               if (waiting_output)
+               {
+                       fputs(roff_waiting_buf, fff);
+                       waiting_output = FALSE;
+               }
+
                if (roff_p != roff_buf) roff_p--;
                while (*roff_p == ' ' && roff_p != roff_buf) roff_p--;
+
                if (roff_p == roff_buf) fprintf(fff, "\n");
                else
                {
                        *(roff_p + 1) = '\0';
                        fprintf(fff, "%s\n\n", roff_buf);
                }
+
                roff_p = roff_buf;
                roff_s = NULL;
                roff_buf[0] = '\0';
@@ -1828,27 +1930,62 @@ static void spoil_out(cptr str)
        for (; *str; str++)
        {
 #ifdef JP
-               char cbak;
-                int k_flag = iskanji((unsigned char)(*str));
+               char cbak;
+               bool k_flag = iskanji((unsigned char)(*str));
 #endif
                char ch = *str;
-               int wrap = (ch == '\n');
+               bool wrap = (ch == '\n');
 
 #ifdef JP
-                if (!isprint(ch) && !k_flag && !iskanji2) ch = ' ';
-               if(k_flag && !iskanji2)iskanji2=1;else iskanji2=0;
+               if (!isprint(ch) && !k_flag && !iskanji_flag) ch = ' ';
+               iskanji_flag = k_flag && !iskanji_flag;
 #else
                if (!isprint(ch)) ch = ' ';
 #endif
 
+               if (waiting_output)
+               {
+                       fputs(roff_waiting_buf, fff);
+                       if (!wrap) fputc('\n', fff);
+                       waiting_output = FALSE;
+               }
+
+               if (!wrap)
+               {
 #ifdef JP
-                if ( roff_p >= roff_buf+( (k_flag) ? 74 : 75) ) wrap=1;
-               if ((ch == ' ') && (roff_p + 2 >= roff_buf + ((k_flag) ? 74 : 75))) wrap = 1;
+                       if (roff_p >= roff_buf + (k_flag ? 74 : 75)) wrap = TRUE;
+                       else if ((ch == ' ') && (roff_p >= roff_buf + (k_flag ? 72 : 73))) wrap = TRUE;
 #else
-               if (roff_p >= roff_buf + 75) wrap = 1;
-               if ((ch == ' ') && (roff_p + 2 >= roff_buf + 75)) wrap = 1;
+                       if (roff_p >= roff_buf + 75) wrap = TRUE;
+                       else if ((ch == ' ') && (roff_p >= roff_buf + 73)) wrap = TRUE;
 #endif
 
+                       if (wrap)
+                       {
+#ifdef JP
+                               bool k_flag_local;
+                               bool iskanji_flag_local = FALSE;
+                               cptr tail = str + (k_flag ? 2 : 1);
+#else
+                               cptr tail = str + 1;
+#endif
+
+                               for (; *tail; tail++)
+                               {
+                                       if (*tail == ' ') continue;
+
+#ifdef JP
+                                       k_flag_local = iskanji((unsigned char)(*tail));
+                                       if (isprint(*tail) || k_flag_local || iskanji_flag_local) break;
+                                       iskanji_flag_local = k_flag_local && !iskanji_flag_local;
+#else
+                                       if (isprint(*tail)) break;
+#endif
+                               }
+
+                               if (!*tail) waiting_output = TRUE;
+                       }
+               }
 
                /* Handle line-wrap */
                if (wrap)
@@ -1856,21 +1993,22 @@ static void spoil_out(cptr str)
                        *roff_p = '\0';
                        r = roff_p;
 #ifdef JP
-                                cbak=' ';
+                       cbak = ' ';
 #endif
                        if (roff_s && (ch != ' '))
                        {
 #ifdef JP
-                               cbak=*roff_s;
+                               cbak = *roff_s;
 #endif
                                *roff_s = '\0';
                                r = roff_s + 1;
                        }
-                       fprintf(fff, "%s\n", roff_buf);
+                       if (!waiting_output) fprintf(fff, "%s\n", roff_buf);
+                       else strcpy(roff_waiting_buf, roff_buf);
                        roff_s = NULL;
                        roff_p = roff_buf;
 #ifdef JP
-                       if(cbak != ' ') *roff_p++ = cbak; 
+                       if (cbak != ' ') *roff_p++ = cbak;
 #endif
                        while (*r) *roff_p++ = *r++;
                }
@@ -1879,16 +2017,18 @@ static void spoil_out(cptr str)
                if ((roff_p > roff_buf) || (ch != ' '))
                {
 #ifdef JP
-                 if( !k_flag ){
-                       if (ch == ' ' || ch == '(' ) roff_s = roff_p;
-                 }
-                 else{
-                   if( iskanji2 && 
-                        strncmp(str, "¡£", 2) != 0 && 
-                       strncmp(str, "¡¢", 2) != 0 &&
-                       strncmp(str, "¥£", 2) != 0 &&
-                       strncmp(str, "¡¼", 2) != 0) roff_s = roff_p;
-                 }
+                       if (!k_flag)
+                       {
+                               if ((ch == ' ') || (ch == '(')) roff_s = roff_p;
+                       }
+                       else
+                       {
+                               if (iskanji_flag &&
+                                   strncmp(str, "¡£", 2) != 0 &&
+                                   strncmp(str, "¡¢", 2) != 0 &&
+                                   strncmp(str, "¥£", 2) != 0 &&
+                                   strncmp(str, "¡¼", 2) != 0) roff_s = roff_p;
+                       }
 #else
                        if (ch == ' ') roff_s = roff_p;
 #endif
@@ -1903,8 +2043,11 @@ static void spoil_out(cptr str)
 /*
  *  Hook function used in spoil_mon_info()
  */
-void roff_func(byte attr, cptr str)
+static void roff_func(byte attr, cptr str)
 {
+       /* Unused */
+       (void)attr;
+
        spoil_out(str);
 }
 
@@ -1915,15 +2058,14 @@ void roff_func(byte attr, cptr str)
 static void spoil_mon_info(cptr fname)
 {
        char buf[1024];
-       int msex, i, l, n=0;
-       bool breath, magic;
-       u32b flags1, flags2, flags3, flags4, flags5, flags6, flags7;
+       int i, l, n = 0;
+       u32b flags1;
 
        u16b why = 2;
        s16b *who;
 
        /* Build the filename */
-       path_build(buf, 1024, ANGBAND_DIR_USER, fname);
+       path_build(buf, sizeof(buf), ANGBAND_DIR_USER, fname);
 
        /* File type is "TEXT" */
        FILE_TYPE(FILE_TYPE_TEXT);
@@ -1940,13 +2082,8 @@ static void spoil_mon_info(cptr fname)
 
 
        /* Dump the header */
-#ifndef FAKE_VERSION
-       sprintf(buf, "Monster Spoilers for Angband Version %d.%d.%d\n",
-               VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH);
-#else
        sprintf(buf, "Monster Spoilers for Hengband Version %d.%d.%d\n",
             FAKE_VER_MAJOR-10, FAKE_VER_MINOR, FAKE_VER_PATCH);
-#endif
 
        spoil_out(buf);
        spoil_out("------------------------------------------\n\n");
@@ -1980,27 +2117,16 @@ static void spoil_mon_info(cptr fname)
 
                /* Extract the flags */
                flags1 = r_ptr->flags1;
-               flags2 = r_ptr->flags2;
-               flags3 = r_ptr->flags3;
-               flags4 = r_ptr->flags4;
-               flags5 = r_ptr->flags5;
-               flags6 = r_ptr->flags6;
-               flags7 = r_ptr->flags7;
-               breath = FALSE;
-               magic = FALSE;
-
-               /* Extract a gender (if applicable) */
-               if (flags1 & (RF1_FEMALE)) msex = 2;
-               else if (flags1 & (RF1_MALE)) msex = 1;
-               else msex = 0;
-
 
                /* Prefix */
+               /*
                if (flags1 & (RF1_QUESTOR))
                {
                        spoil_out("[Q] ");
                }
-               else if (flags1 & (RF1_UNIQUE))
+               else
+               */
+               if (flags1 & (RF1_UNIQUE))
                {
                        spoil_out("[U] ");
                }
@@ -2021,7 +2147,7 @@ static void spoil_mon_info(cptr fname)
                spoil_out(buf);
 
                /* Color */
-               spoil_out(attr_to_text(r_ptr->d_attr));
+               spoil_out(attr_to_text(r_ptr));
 
                /* Symbol --(-- */
                sprintf(buf, " '%c')\n", r_ptr->d_char);
@@ -2033,7 +2159,7 @@ static void spoil_mon_info(cptr fname)
                spoil_out(buf);
 
                /* Number */
-               sprintf(buf, "Num:%d  ", n);
+               sprintf(buf, "Num:%d  ", who[l]);
                spoil_out(buf);
 
                /* Level */
@@ -2095,6 +2221,243 @@ static void spoil_mon_info(cptr fname)
 
 
 
+#define MAX_EVOL_DEPTH 64
+
+
+/*
+ * Compare two int-type array like strncmp() and return TRUE if equals
+ */
+static bool int_n_cmp(int *a, int *b, int length)
+{
+       /* Null-string comparation is always TRUE */
+       if (!length) return TRUE;
+
+       do
+       {
+               if (*a != *(b++)) return FALSE;
+               if (!(*(a++))) break;
+       }
+       while (--length);
+
+       return TRUE;
+}
+
+
+/*
+ * Returns TRUE if an evolution tree is "partial tree"
+ */
+static bool is_partial_tree(int *tree, int *partial_tree)
+{
+       int pt_head = *(partial_tree++);
+       int pt_len = 0;
+
+       while (partial_tree[pt_len]) pt_len++;
+
+       while (*tree)
+       {
+               if (*(tree++) == pt_head)
+               {
+                       if (int_n_cmp(tree, partial_tree, pt_len)) return TRUE;
+               }
+       }
+
+       return FALSE;
+}
+
+
+/*
+ * Sorting hook -- Comp function
+ */
+static bool ang_sort_comp_evol_tree(vptr u, vptr v, int a, int b)
+{
+       int **evol_tree = (int **)u;
+
+       int w1 = evol_tree[a][0];
+       int w2 = evol_tree[b][0];
+       monster_race *r1_ptr = &r_info[w1];
+       monster_race *r2_ptr = &r_info[w2];
+
+       /* Unused */
+       (void)v;
+
+       /* Used tree first */
+       if (w1 && !w2) return TRUE;
+       if (!w1 && w2) return FALSE;
+
+       /* Sort by monster level */
+       if (r1_ptr->level < r2_ptr->level) return TRUE;
+       if (r1_ptr->level > r2_ptr->level) return FALSE;
+
+       /* Sort by monster experience */
+       if (r1_ptr->mexp < r2_ptr->mexp) return TRUE;
+       if (r1_ptr->mexp > r2_ptr->mexp) return FALSE;
+
+       /* Compare indexes */
+       return w1 <= w2;
+}
+
+
+/*
+ * Sorting hook -- Swap function
+ */
+static void ang_sort_swap_evol_tree(vptr u, vptr v, int a, int b)
+{
+       int **evol_tree = (int **)u;
+       int *holder;
+
+       /* Unused */
+       (void)v;
+
+       /* Swap */
+       holder = evol_tree[a];
+       evol_tree[a] = evol_tree[b];
+       evol_tree[b] = holder;
+}
+
+
+/*
+ * Print monsters' evolution information to file
+ */
+static void spoil_mon_evol(cptr fname)
+{
+       char buf[1024];
+       monster_race *r_ptr;
+       int **evol_tree, i, j, n, r_idx;
+       int *evol_tree_zero; /* For C_KILL() */
+
+       /* Build the filename */
+       path_build(buf, sizeof buf, ANGBAND_DIR_USER, fname);
+
+       /* File type is "TEXT" */
+       FILE_TYPE(FILE_TYPE_TEXT);
+
+       /* Open the file */
+       fff = my_fopen(buf, "w");
+
+       /* Oops */
+       if (!fff)
+       {
+               msg_print("Cannot create spoiler file.");
+           return;
+       }
+
+       /* Dump the header */
+       sprintf(buf, "Monster Spoilers for Hengband Version %d.%d.%d\n",
+            FAKE_VER_MAJOR-10, FAKE_VER_MINOR, FAKE_VER_PATCH);
+
+       spoil_out(buf);
+       spoil_out("------------------------------------------\n\n");
+
+       /* Allocate the "evol_tree" array (2-dimension) */
+       C_MAKE(evol_tree, max_r_idx, int *);
+       C_MAKE(*evol_tree, max_r_idx * (MAX_EVOL_DEPTH + 1), int);
+       for (i = 1; i < max_r_idx; i++) evol_tree[i] = *evol_tree + i * (MAX_EVOL_DEPTH + 1);
+       evol_tree_zero = *evol_tree;
+
+       /* Step 1: Build the evolution tree */
+       for (i = 1; i < max_r_idx; i++)
+       {
+               r_ptr = &r_info[i];
+
+               /* No evolution */
+               if (!r_ptr->next_exp) continue;
+
+               /* Trace evolution */
+               n = 0;
+               evol_tree[i][n++] = i;
+               do
+               {
+                       evol_tree[i][n++] = r_ptr->next_r_idx;
+                       r_ptr = &r_info[r_ptr->next_r_idx];
+               }
+               while (r_ptr->next_exp && (n < MAX_EVOL_DEPTH));
+       }
+
+       /* Step 2: Scan the evolution trees and remove "partial tree" */
+       for (i = 1; i < max_r_idx; i++)
+       {
+               /* Not evolution tree */
+               if (!evol_tree[i][0]) continue;
+
+               for (j = 1; j < max_r_idx; j++)
+               {
+                       /* Same tree */
+                       if (i == j) continue;
+
+                       /* Not evolution tree */
+                       if (!evol_tree[j][0]) continue;
+
+                       /* Is evolution tree[i] is part of [j]? */
+                       if (is_partial_tree(evol_tree[j], evol_tree[i]))
+                       {
+                               /* Remove this evolution tree */
+                               evol_tree[i][0] = 0;
+                               break;
+                       }
+               }
+       }
+
+       /* Step 3: Sort the evolution trees */
+
+       /* Select the sort method */
+       ang_sort_comp = ang_sort_comp_evol_tree;
+       ang_sort_swap = ang_sort_swap_evol_tree;
+
+       /* Sort the array */
+       ang_sort(evol_tree, NULL, max_r_idx);
+
+       /* Step 4: Print the evolution trees */
+       for (i = 0; i < max_r_idx; i++)
+       {
+               r_idx = evol_tree[i][0];
+
+               /* No evolution or removed evolution tree */
+               if (!r_idx) continue;
+
+               /* Trace the evolution tree */
+               r_ptr = &r_info[r_idx];
+#ifdef JP
+               fprintf(fff, "[%d]: %s (¥ì¥Ù¥ë%d, '%c')\n", r_idx,
+                       r_name + r_ptr->name, r_ptr->level, r_ptr->d_char);
+#else
+               fprintf(fff, "[%d]: %s (Level %d, '%c')\n", r_idx,
+                       r_name + r_ptr->name, r_ptr->level, r_ptr->d_char);
+#endif
+               for (n = 1; r_ptr->next_exp; n++)
+               {
+                       fprintf(fff, "%*s-(%ld)-> ", n * 2, "", (long int)r_ptr->next_exp);
+                       fprintf(fff, "[%d]: ", r_ptr->next_r_idx);
+                       r_ptr = &r_info[r_ptr->next_r_idx];
+#ifdef JP
+                       fprintf(fff, "%s (¥ì¥Ù¥ë%d, '%c')\n",
+                               r_name + r_ptr->name, r_ptr->level, r_ptr->d_char);
+#else
+                       fprintf(fff, "%s (Level %d, '%c')\n",
+                               r_name + r_ptr->name, r_ptr->level, r_ptr->d_char);
+#endif
+               }
+
+               /* End of evolution tree */
+               fputc('\n', fff);
+       }
+
+       /* Free the "evol_tree" array (2-dimension) */
+       C_KILL(evol_tree_zero, max_r_idx * (MAX_EVOL_DEPTH + 1), int);
+       C_KILL(evol_tree, max_r_idx, int *);
+
+       /* Check for errors */
+       if (ferror(fff) || my_fclose(fff))
+       {
+               msg_print("Cannot close spoiler file.");
+               return;
+       }
+
+       /* Message */
+       msg_print("Successfully created a spoiler file.");
+}
+
+
+
 /*
  * Forward declare
  */
@@ -2105,17 +2468,9 @@ extern void do_cmd_spoilers(void);
  */
 void do_cmd_spoilers(void)
 {
-       int i;
-
-
        /* Save the screen */
        screen_save();
 
-
-       /* Drop priv's */
-       safe_setuid_drop();
-
-
        /* Interact */
        while (1)
        {
@@ -2130,65 +2485,58 @@ void do_cmd_spoilers(void)
                prt("(2) Brief Artifact Info (artifact.spo)", 6, 5);
                prt("(3) Brief Monster Info (mon-desc.spo)", 7, 5);
                prt("(4) Full Monster Info (mon-info.spo)", 8, 5);
+               prt("(5) Monster Evolution Info (mon-evol.spo)", 9, 5);
 
                /* Prompt */
 #ifdef JP
-prt("¥³¥Þ¥ó¥É:", 18, 0);
+               prt("¥³¥Þ¥ó¥É:", 18, 0);
 #else
                prt("Command: ", 12, 0);
 #endif
 
-
                /* Get a choice */
-               i = inkey();
-
-               /* Escape */
-               if (i == ESCAPE)
+               switch (inkey())
                {
-                       break;
-               }
+               /* Escape */
+               case ESCAPE:
+                       /* Restore the screen */
+                       screen_load();
+                       return;
 
                /* Option (1) */
-               else if (i == '1')
-               {
+               case '1':
                        spoil_obj_desc("obj-desc.spo");
-               }
+                       break;
 
                /* Option (2) */
-               else if (i == '2')
-               {
+               case '2':
                        spoil_artifact("artifact.spo");
-               }
+                       break;
 
                /* Option (3) */
-               else if (i == '3')
-               {
+               case '3':
                        spoil_mon_desc("mon-desc.spo");
-               }
+                       break;
 
                /* Option (4) */
-               else if (i == '4')
-               {
+               case '4':
                        spoil_mon_info("mon-info.spo");
-               }
+                       break;
+
+               /* Option (5) */
+               case '5':
+                       spoil_mon_evol("mon-evol.spo");
+                       break;
 
                /* Oops */
-               else
-               {
+               default:
                        bell();
+                       break;
                }
 
                /* Flush messages */
                msg_print(NULL);
        }
-
-
-       /* Grab priv's */
-       safe_setuid_grab();
-
-
-       /* Restore the screen */
-       screen_load();
 }
 
 /*
@@ -2246,7 +2594,7 @@ static void spoiler_print_randart(object_type *o_ptr, obj_desc_list *art_ptr)
 #endif
                        spoiler_outlist(buf, pval_ptr->pval_affects, ITEM_SEP);
                }
-         
+
                /* Now deal with the description lists */
 
 #ifdef JP
@@ -2284,7 +2632,7 @@ static void spoil_random_artifact_aux(object_type *o_ptr, int i)
 {
        obj_desc_list artifact;
 
-       if (!object_known_p(o_ptr) || !o_ptr->art_name
+       if (!object_is_known(o_ptr) || !o_ptr->art_name
                || o_ptr->tval != group_artifact[i].tval)
                return;
 
@@ -2308,11 +2656,8 @@ void spoil_random_artifact(cptr fname)
        char buf[1024];
 
 
-       /* Drop priv's */
-       safe_setuid_drop();
-
        /* Build the filename */
-       path_build(buf, 1024, ANGBAND_DIR_USER, fname);
+       path_build(buf, sizeof(buf), ANGBAND_DIR_USER, fname);
 
        /* File type is "TEXT" */
        FILE_TYPE(FILE_TYPE_TEXT);
@@ -2372,9 +2717,6 @@ void spoil_random_artifact(cptr fname)
                return;
        }
 
-       /* Grab priv's */
-       safe_setuid_grab();
-
        /* Message */
        msg_print("Successfully created a list file.");
 }