+ /* Save the standard values */
+ f_ptr->d_attr[F_LIT_STANDARD] = s_attr;
+ f_ptr->d_char[F_LIT_STANDARD] = char_tmp[F_LIT_STANDARD];
+
+ /* Is this feature supports lighting? */
+ if (buf[5] == ':')
+ {
+ /* G:c:a:LIT (default) */
+ apply_default_feat_lighting(f_ptr->d_attr, f_ptr->d_char);
+
+ /* G:c:a:lc:la:dc:da */
+ if (!streq(buf + 6, "LIT"))
+ {
+ char attr_lite_tmp[F_LIT_MAX - F_LIT_NS_BEGIN];
+
+ if ((F_LIT_MAX - F_LIT_NS_BEGIN) * 2 != sscanf(buf + 6, "%c:%c:%c:%c",
+ &char_tmp[F_LIT_LITE], &attr_lite_tmp[F_LIT_LITE - F_LIT_NS_BEGIN],
+ &char_tmp[F_LIT_DARK], &attr_lite_tmp[F_LIT_DARK - F_LIT_NS_BEGIN])) return 1;
+ if (buf[F_LIT_MAX * 4 + 1]) return 1;
+
+ for (j = F_LIT_NS_BEGIN; j < F_LIT_MAX; j++)
+ {
+ switch (attr_lite_tmp[j - F_LIT_NS_BEGIN])
+ {
+ case '*':
+ /* Use default lighting */
+ break;
+ case '-':
+ /* No lighting support */
+ f_ptr->d_attr[j] = f_ptr->d_attr[F_LIT_STANDARD];
+ break;
+ default:
+ /* Extract the color */
+ f_ptr->d_attr[j] = color_char_to_attr(attr_lite_tmp[j - F_LIT_NS_BEGIN]);
+ if (f_ptr->d_attr[j] > 127) return 1;
+ break;
+ }
+ f_ptr->d_char[j] = char_tmp[j];
+ }
+ }
+ }
+ else if (!buf[5])
+ {
+ for (j = F_LIT_NS_BEGIN; j < F_LIT_MAX; j++)
+ {
+ f_ptr->d_attr[j] = s_attr;
+ f_ptr->d_char[j] = char_tmp[F_LIT_STANDARD];
+ }
+ }
+ else return 1;
+ }
+
+ /* Hack -- Process 'F' for flags */
+ else if (buf[0] == 'F')
+ {
+ /* Parse every entry textually */
+ for (s = buf + 2; *s; )
+ {
+ /* Find the end of this entry */
+ for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
+
+ /* Nuke and skip any dividers */
+ if (*t)
+ {
+ *t++ = '\0';
+ while (*t == ' ' || *t == '|') t++;
+ }
+
+ /* XXX XXX XXX Hack -- Read feature subtype */
+ if (1 == sscanf(s, "SUBTYPE_%d", &i))
+ {
+ /* Extract a "subtype" */
+ f_ptr->subtype = i;
+
+ /* Start at next entry */
+ s = t;
+
+ /* Continue */
+ continue;
+ }
+
+ /* XXX XXX XXX Hack -- Read feature power */
+ if (1 == sscanf(s, "POWER_%d", &i))
+ {
+ /* Extract a "power" */
+ f_ptr->power = i;
+
+ /* Start at next entry */
+ s = t;
+
+ /* Continue */
+ continue;
+ }
+
+ /* Parse this entry */
+ if (0 != grab_one_feat_flag(f_ptr, s)) return (PARSE_ERROR_INVALID_FLAG);
+
+ /* Start the next entry */
+ s = t;
+ }
+ }
+
+ /* Process 'W' for "More Info" (one line only) */
+ else if (buf[0] == 'W')
+ {
+ int priority;
+
+ /* Scan for the value */
+ if (1 != sscanf(buf+2, "%d", &priority)) return (PARSE_ERROR_GENERIC);
+
+ /* Save the value */
+ f_ptr->priority = priority;
+ }
+
+ /* Process 'K' for "States" (up to four lines + default (which cannot be last)) */
+ else if (buf[0] == 'K')
+ {
+ s16b offset;
+
+ /* Find the next empty state slot (if any) */
+ for (i = 0; i < MAX_FEAT_STATES; i++) if (f_ptr->state[i].action == FF_FLAG_MAX) break;
+
+ /* Oops, no more slots */
+ if (i == MAX_FEAT_STATES) return PARSE_ERROR_GENERIC;
+
+ /* Analyze the first field */
+ for (s = t = buf+2; *t && (*t != ':'); t++) /* loop */;
+
+ /* Terminate the field (if necessary) */
+ if (*t == ':') *t++ = '\0';
+
+ /* Is this default entry? */
+ if (streq(s, "DESTROYED"))
+ {
+ if (!add_tag(&offset, head, t)) return PARSE_ERROR_OUT_OF_MEMORY;
+
+ /* Record a fake tag index */
+ f_ptr->destroyed = -offset;
+ }
+ else
+ {
+ /* Reset */
+ f_ptr->state[i].action = 0;
+
+ /* Parse this entry */
+ if (0 != grab_one_feat_action(f_ptr, s, i)) return PARSE_ERROR_INVALID_FLAG;
+
+ if (!add_tag(&offset, head, t)) return PARSE_ERROR_OUT_OF_MEMORY;
+
+ /* Record a fake tag index */
+ f_ptr->state[i].result = -offset;
+ }
+ }
+
+ /* Oops */
+ else return (6);
+
+ /* Success */
+ return (0);
+}
+
+
+/*
+ * Convert a fake tag to a real feat index
+ */
+s16b f_tag_to_index(cptr str)
+{
+ u16b i;
+
+ /* Search for real index corresponding to this fake tag */
+ for (i = 0; i < f_head.info_num; i++)
+ {
+ if (streq(f_tag + f_info[i].tag, str))
+ {
+ /* Return the index */
+ return (s16b)i;
+ }
+ }
+
+ /* Not found */
+ return -1;
+}
+
+
+/*
+ * Search for real index corresponding to this fake tag
+ */
+static void search_real_feat(s16b *feat)
+{
+ int i;
+
+ /* Don't convert non-fake tag */
+ if (*feat >= 0) return;
+
+ /* Search for real index corresponding to this fake tag */
+ for (i = 0; i < f_head.info_num; i++)
+ {
+ if ((-(*feat)) == f_info[i].tag)
+ {
+ /* Record real index */
+ *feat = (s16b)i;
+ return;
+ }
+ }
+
+ /* Undefined tag */
+#ifdef JP
+ msg_format("̤ÄêµÁ¤Î¥¿¥° '%s'¡£", f_tag + (-(*feat)));
+#else
+ msg_format("%s is undefined.", f_tag + (-(*feat)));
+#endif
+}
+
+
+/*
+ * Retouch fake tags of f_info
+ */
+void retouch_f_info(header *head)
+{
+ int i;
+
+ /* Convert fake tags to real feat indices */
+ for (i = 0; i < head->info_num; i++)
+ {
+ feature_type *f_ptr = &f_info[i];
+ int j;