3 /* Purpose: Initialization (part 1) -BEN- */
10 char* _strchr(unsigned char* ptr, unsigned char ch)
14 for ( ; *ptr != '\0'; ++ptr)
25 #define strchr _strchr
28 * This file is used to initialize various variables and arrays for the
29 * Angband game. Note the use of "fd_read()" and "fd_write()" to bypass
30 * the common limitation of "read()" and "write()" to only 32767 bytes
33 * Several of the arrays for Angband are built from "template" files in
34 * the "lib/file" directory, from which quick-load binary "image" files
35 * are constructed whenever they are not present in the "lib/data"
36 * directory, or if those files become obsolete, if we are allowed.
38 * Warning -- the "ascii" file parsers use a minor hack to collect the
39 * name and text information in a single pass. Thus, the game will not
40 * be able to load any template file with more than 20K of names or 60K
41 * of text, even though technically, up to 64K should be legal.
43 * Note that if "ALLOW_TEMPLATES" is not defined, then a lot of the code
44 * in this file is compiled out, and the game will not run unless valid
45 * "binary template files" already exist in "lib/data". Thus, one can
46 * compile Angband with ALLOW_TEMPLATES defined, run once to create the
47 * "*.raw" files in "lib/data", and then quit, and recompile without
48 * defining ALLOW_TEMPLATES, which will both save 20K and prevent people
49 * from changing the ascii template files in potentially dangerous ways.
51 * The code could actually be removed and placed into a "stand-alone"
52 * program, but that feels a little silly, especially considering some
53 * of the platforms that we currently support.
57 #ifdef ALLOW_TEMPLATES
60 /*** Helper arrays for parsing ascii template files ***/
63 * Monster Blow Methods
65 static cptr r_info_blow_method[] =
97 * Monster Blow Effects
99 static cptr r_info_blow_effect[] =
142 static cptr r_info_flags1[] =
181 static cptr r_info_flags2[] =
220 static cptr r_info_flags3[] =
259 static cptr r_info_flags4[] =
298 static cptr r_info_flags5[] =
337 static cptr r_info_flags6[] =
354 "ANIM_DEAD", /* ToDo: Implement ANIM_DEAD */
377 static cptr r_info_flags7[] =
416 static cptr r_info_flags8[] =
448 "WILD_SWAMP", /* ToDo: Implement Swamp */
454 * Monster race flags - Drops
456 static cptr r_info_flags9[] =
497 static cptr k_info_flags1[] =
536 static cptr k_info_flags2[] =
575 static cptr k_info_flags3[] =
615 static cptr d_info_flags1[] =
653 * Convert a "color letter" into an "actual" color
654 * The colors are: dwsorgbuDWvyRGBU, as shown below
656 static int color_char_to_attr(char c)
660 case 'd': return (TERM_DARK);
661 case 'w': return (TERM_WHITE);
662 case 's': return (TERM_SLATE);
663 case 'o': return (TERM_ORANGE);
664 case 'r': return (TERM_RED);
665 case 'g': return (TERM_GREEN);
666 case 'b': return (TERM_BLUE);
667 case 'u': return (TERM_UMBER);
669 case 'D': return (TERM_L_DARK);
670 case 'W': return (TERM_L_WHITE);
671 case 'v': return (TERM_VIOLET);
672 case 'y': return (TERM_YELLOW);
673 case 'R': return (TERM_L_RED);
674 case 'G': return (TERM_L_GREEN);
675 case 'B': return (TERM_L_BLUE);
676 case 'U': return (TERM_L_UMBER);
684 /*** Initialize from ascii template files ***/
688 * Initialize the "v_info" array, by parsing an ascii "template" file
690 errr init_v_info_txt(FILE *fp, char *buf, bool start)
696 vault_type *v_ptr = NULL;
700 /* Just before the first record */
703 /* Just before the first line */
706 /* Prepare the "fake" stuff */
707 v_head->name_size = 0;
708 v_head->text_size = 0;
712 while (0 == my_fgets(fp, buf, 1024))
714 /* Advance the line number */
717 /* Skip comments and blank lines */
718 if (!buf[0] || (buf[0] == '#')) continue;
719 if ((buf[0] == 'Q') || (buf[0] == 'T')) continue;
721 /* Verify correct "colon" format */
722 if (buf[1] != ':') return (1);
725 /* Hack -- Process 'V' for "Version" */
733 /* Process 'N' for "New/Number/Name" */
736 /* Find the colon before the name */
737 s = strchr(buf+2, ':');
739 /* Verify that colon */
742 /* Nuke the colon, advance to the name */
745 /* Paranoia -- require a name */
751 /* Verify information */
752 if (i <= error_idx) return (4);
754 /* Verify information */
755 if (i >= v_head->info_num) return (2);
760 /* Point at the "info" */
763 /* Hack -- Verify space */
764 if (v_head->name_size + strlen(s) + 8 > fake_name_size) return (7);
766 /* Advance and Save the name index */
767 if (!v_ptr->name) v_ptr->name = ++v_head->name_size;
769 /* Append chars to the name */
770 strcpy(v_name + v_head->name_size, s);
772 /* Advance the index */
773 v_head->name_size += strlen(s);
779 /* There better be a current v_ptr */
780 if (!v_ptr) return (3);
782 /* Process 'D' for "Description" */
785 /* Acquire the text */
788 /* Hack -- Verify space */
789 if (v_head->text_size + strlen(s) + 8 > fake_text_size) return (7);
791 /* Advance and Save the text index */
792 if (!v_ptr->text) v_ptr->text = ++v_head->text_size;
794 /* Append chars to the name */
795 strcpy(v_text + v_head->text_size, s);
797 /* Advance the index */
798 v_head->text_size += strlen(s);
805 /* Process 'X' for "Extra info" (one line only) */
808 int typ, rat, hgt, wid;
810 /* Scan for the values */
811 if (4 != sscanf(buf+2, "%d:%d:%d:%d",
812 &typ, &rat, &hgt, &wid)) return (1);
814 /* Save the values */
830 /* Complete the "name" and "text" sizes */
845 * Initialize the "f_info" array, by parsing an ascii "template" file
847 errr init_f_info_txt(FILE *fp, char *buf)
854 feature_type *f_ptr = NULL;
857 /* Just before the first record */
860 /* Just before the first line */
864 /* Prepare the "fake" stuff */
865 f_head->name_size = 0;
868 f_head->E_name_size = 0;
870 f_head->text_size = 0;
873 while (0 == my_fgets(fp, buf, 1024))
875 /* Advance the line number */
878 /* Skip comments and blank lines */
879 if (!buf[0] || (buf[0] == '#')) continue;
881 /* Verify correct "colon" format */
882 if (buf[1] != ':') return (1);
885 /* Hack -- Process 'V' for "Version" */
893 /* Process 'N' for "New/Number/Name" */
896 /* Find the colon before the name */
897 s = strchr(buf+2, ':');
899 /* Verify that colon */
902 /* Nuke the colon, advance to the name */
906 /* Paranoia -- require a name */
913 /* Verify information */
914 if (i <= error_idx) return (4);
916 /* Verify information */
917 if (i >= f_head->info_num) return (2);
922 /* Point at the "info" */
926 /* Hack -- Verify space */
927 if (f_head->name_size + strlen(s) + 8 > fake_name_size) return (7);
929 /* Advance and Save the name index */
930 if (!f_ptr->name) f_ptr->name = ++f_head->name_size;
932 /* Append chars to the name */
933 strcpy(f_name + f_head->name_size, s);
935 /* Advance the index */
936 f_head->name_size += strlen(s);
938 /* Default "mimic" */
945 /* There better be a current f_ptr */
946 if (!f_ptr) return (3);
949 /* ±Ñ¸ì̾¤òÆɤà¥ë¡¼¥Á¥ó¤òÄɲà */
950 /* 'E' ¤«¤é»Ï¤Þ¤ë¹Ô¤Ï±Ñ¸ì̾¤È¤·¤Æ¤¤¤ë */
953 /* Acquire the Text */
956 /* Hack -- Verify space */
957 if (f_head->E_name_size + strlen(s) + 8 > E_fake_name_size) return (7);
959 /* Advance and Save the name index */
960 if (!f_ptr->E_name) f_ptr->E_name = ++f_head->E_name_size;
962 /* Append chars to the name */
963 strcpy(E_f_name+ f_head->E_name_size, s);
965 /* Advance the index */
966 f_head->E_name_size += strlen(s);
974 /* Acquire the Text */
977 /* Hack -- Verify space */
978 if (f_head->name_size + strlen(s) + 8 > fake_name_size) return (7);
980 /* Advance and Save the name index */
981 if (!f_ptr->name) f_ptr->name = ++f_head->name_size;
983 /* Append chars to the name */
984 strcpy(f_name+ f_head->name_size, s);
986 /* Advance the index */
987 f_head->name_size += strlen(s);
996 /* Process 'D' for "Description" */
999 /* Acquire the text */
1002 /* Hack -- Verify space */
1003 if (f_head->text_size + strlen(s) + 8 > fake_text_size) return (7);
1005 /* Advance and Save the text index */
1006 if (!f_ptr->text) f_ptr->text = ++f_head->text_size;
1008 /* Append chars to the name */
1009 strcpy(f_text + f_head->text_size, s);
1011 /* Advance the index */
1012 f_head->text_size += strlen(s);
1021 /* Process 'M' for "Mimic" (one line only) */
1026 /* Scan for the values */
1027 if (1 != sscanf(buf+2, "%d",
1028 &mimic)) return (1);
1030 /* Save the values */
1031 f_ptr->mimic = mimic;
1038 /* Process 'G' for "Graphics" (one line only) */
1044 if (!buf[2]) return (1);
1045 if (!buf[3]) return (1);
1046 if (!buf[4]) return (1);
1048 /* Extract the color */
1049 tmp = color_char_to_attr(buf[4]);
1052 if (tmp < 0) return (1);
1054 /* Save the values */
1055 f_ptr->d_attr = tmp;
1056 f_ptr->d_char = buf[2];
1068 /* Complete the "name" and "text" sizes */
1069 ++f_head->name_size;
1072 ++f_head->E_name_size;
1074 ++f_head->text_size;
1083 * Grab one flag in an object_kind from a textual string
1085 static errr grab_one_kind_flag(object_kind *k_ptr, cptr what)
1090 for (i = 0; i < 32; i++)
1092 if (streq(what, k_info_flags1[i]))
1094 k_ptr->flags1 |= (1L << i);
1100 for (i = 0; i < 32; i++)
1102 if (streq(what, k_info_flags2[i]))
1104 k_ptr->flags2 |= (1L << i);
1110 for (i = 0; i < 32; i++)
1112 if (streq(what, k_info_flags3[i]))
1114 k_ptr->flags3 |= (1L << i);
1121 msg_format("̤ÃΤΥ¢¥¤¥Æ¥à¡¦¥Õ¥é¥° '%s'¡£", what);
1123 msg_format("Unknown object flag '%s'.", what);
1133 * Initialize the "k_info" array, by parsing an ascii "template" file
1135 errr init_k_info_txt(FILE *fp, char *buf)
1142 object_kind *k_ptr = NULL;
1145 /* Just before the first record */
1148 /* Just before the first line */
1152 /* Prepare the "fake" stuff */
1153 k_head->name_size = 0;
1156 k_head->E_name_size = 0;
1158 k_head->text_size = 0;
1161 while (0 == my_fgets(fp, buf, 1024))
1163 /* Advance the line number */
1166 /* Skip comments and blank lines */
1167 if (!buf[0] || (buf[0] == '#')) continue;
1169 /* Verify correct "colon" format */
1170 if (buf[1] != ':') return (1);
1173 /* Hack -- Process 'V' for "Version" */
1181 /* Process 'N' for "New/Number/Name" */
1184 /* Find the colon before the name */
1185 s = strchr(buf+2, ':');
1187 /* Verify that colon */
1190 /* Nuke the colon, advance to the name */
1194 /* Paranoia -- require a name */
1195 if (!*s) return (1);
1200 /* Verify information */
1201 if (i <= error_idx) return (4);
1203 /* Verify information */
1204 if (i >= k_head->info_num) return (2);
1206 /* Save the index */
1209 /* Point at the "info" */
1213 /* Hack -- Verify space */
1214 if (k_head->name_size + strlen(s) + 8 > fake_name_size)
1216 fake_name_size += 1000;
1218 /* Reallocate the extra memory */
1219 k_info = realloc(k_name, fake_name_size);
1222 /* Advance and Save the name index */
1223 if (!k_ptr->name) k_ptr->name = ++k_head->name_size;
1225 /* Append chars to the name */
1226 strcpy(k_name + k_head->name_size, s);
1228 /* Advance the index */
1229 k_head->name_size += strlen(s);
1235 /* There better be a current k_ptr */
1236 if (!k_ptr) return (3);
1240 /* ±Ñ¸ì̾¤òÆɤà¥ë¡¼¥Á¥ó¤òÄɲà */
1241 /* 'E' ¤«¤é»Ï¤Þ¤ë¹Ô¤Ï±Ñ¸ì̾¤È¤·¤Æ¤¤¤ë */
1244 /* Acquire the Text */
1247 /* Hack -- Verify space */
1248 if (k_head->E_name_size + strlen(s) + 8 > E_fake_name_size) return (7);
1250 /* Advance and Save the name index */
1251 if (!k_ptr->E_name) k_ptr->E_name = ++k_head->E_name_size;
1253 /* Append chars to the name */
1254 strcpy(E_k_name+ k_head->E_name_size, s);
1256 /* Advance the index */
1257 k_head->E_name_size += strlen(s);
1265 /* Acquire the Text */
1268 /* Hack -- Verify space */
1269 if (k_head->name_size + strlen(s) + 8 > fake_name_size) return (7);
1271 /* Advance and Save the name index */
1272 if (!k_ptr->name) k_ptr->name = ++k_head->name_size;
1274 /* Append chars to the name */
1275 strcpy(k_name+ k_head->name_size, s);
1277 /* Advance the index */
1278 k_head->name_size += strlen(s);
1286 /* Process 'D' for "Description" */
1289 /* Acquire the text */
1292 /* Hack -- Verify space */
1293 if (k_head->text_size + strlen(s) + 8 > fake_text_size) return (7);
1295 /* Advance and Save the text index */
1296 if (!k_ptr->text) k_ptr->text = ++k_head->text_size;
1298 /* Append chars to the name */
1299 strcpy(k_text + k_head->text_size, s);
1301 /* Advance the index */
1302 k_head->text_size += strlen(s);
1311 /* Process 'G' for "Graphics" (one line only) */
1318 if (!buf[2]) return (1);
1319 if (!buf[3]) return (1);
1320 if (!buf[4]) return (1);
1322 /* Extract the char */
1325 /* Extract the attr */
1326 tmp = color_char_to_attr(buf[4]);
1329 if (tmp < 0) return (1);
1331 /* Save the values */
1332 k_ptr->d_attr = tmp;
1333 k_ptr->d_char = sym;
1339 /* Process 'I' for "Info" (one line only) */
1342 int tval, sval, pval;
1344 /* Scan for the values */
1345 if (3 != sscanf(buf+2, "%d:%d:%d",
1346 &tval, &sval, &pval)) return (1);
1348 /* Save the values */
1357 /* Process 'W' for "More Info" (one line only) */
1360 int level, extra, wgt;
1363 /* Scan for the values */
1364 if (4 != sscanf(buf+2, "%d:%d:%d:%ld",
1365 &level, &extra, &wgt, &cost)) return (1);
1367 /* Save the values */
1368 k_ptr->level = level;
1369 k_ptr->extra = extra;
1370 k_ptr->weight = wgt;
1377 /* Process 'A' for "Allocation" (one line only) */
1382 /* XXX XXX XXX Simply read each number following a colon */
1383 for (i = 0, s = buf+1; s && (s[0] == ':') && s[1]; ++i)
1385 /* Default chance */
1386 k_ptr->chance[i] = 1;
1388 /* Store the attack damage index */
1389 k_ptr->locale[i] = atoi(s+1);
1391 /* Find the slash */
1392 t = strchr(s+1, '/');
1394 /* Find the next colon */
1395 s = strchr(s+1, ':');
1397 /* If the slash is "nearby", use it */
1398 if (t && (!s || t < s))
1400 int chance = atoi(t+1);
1401 if (chance > 0) k_ptr->chance[i] = chance;
1409 /* Hack -- Process 'P' for "power" and such */
1412 int ac, hd1, hd2, th, td, ta;
1414 /* Scan for the values */
1415 if (6 != sscanf(buf+2, "%d:%dd%d:%d:%d:%d",
1416 &ac, &hd1, &hd2, &th, &td, &ta)) return (1);
1429 /* Hack -- Process 'F' for flags */
1432 /* Parse every entry textually */
1433 for (s = buf + 2; *s; )
1435 /* Find the end of this entry */
1436 for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
1438 /* Nuke and skip any dividers */
1442 while (*t == ' ' || *t == '|') t++;
1445 /* Parse this entry */
1446 if (0 != grab_one_kind_flag(k_ptr, s)) return (5);
1448 /* Start the next entry */
1462 /* Complete the "name" and "text" sizes */
1463 ++k_head->name_size;
1466 ++k_head->E_name_size;
1468 ++k_head->text_size;
1477 * Grab one flag in an artifact_type from a textual string
1479 static errr grab_one_artifact_flag(artifact_type *a_ptr, cptr what)
1484 for (i = 0; i < 32; i++)
1486 if (streq(what, k_info_flags1[i]))
1488 a_ptr->flags1 |= (1L << i);
1494 for (i = 0; i < 32; i++)
1496 if (streq(what, k_info_flags2[i]))
1498 a_ptr->flags2 |= (1L << i);
1504 for (i = 0; i < 32; i++)
1506 if (streq(what, k_info_flags3[i]))
1508 a_ptr->flags3 |= (1L << i);
1515 msg_format("̤ÃΤÎÅÁÀâ¤Î¥¢¥¤¥Æ¥à¡¦¥Õ¥é¥° '%s'¡£", what);
1517 msg_format("Unknown artifact flag '%s'.", what);
1529 * Initialize the "a_info" array, by parsing an ascii "template" file
1531 errr init_a_info_txt(FILE *fp, char *buf)
1538 artifact_type *a_ptr = NULL;
1541 /* Just before the first record */
1544 /* Just before the first line */
1549 while (0 == my_fgets(fp, buf, 1024))
1551 /* Advance the line number */
1554 /* Skip comments and blank lines */
1555 if (!buf[0] || (buf[0] == '#')) continue;
1557 /* Verify correct "colon" format */
1558 if (buf[1] != ':') return (1);
1561 /* Hack -- Process 'V' for "Version" */
1569 /* Process 'N' for "New/Number/Name" */
1572 /* Find the colon before the name */
1573 s = strchr(buf+2, ':');
1575 /* Verify that colon */
1578 /* Nuke the colon, advance to the name */
1581 /* Paranoia -- require a name */
1582 if (!*s) return (1);
1587 /* Verify information */
1588 if (i < error_idx) return (4);
1590 /* Verify information */
1591 if (i >= a_head->info_num) return (2);
1593 /* Save the index */
1596 /* Point at the "info" */
1599 /* Ignore everything */
1600 a_ptr->flags3 |= (TR3_IGNORE_ACID);
1601 a_ptr->flags3 |= (TR3_IGNORE_ELEC);
1602 a_ptr->flags3 |= (TR3_IGNORE_FIRE);
1603 a_ptr->flags3 |= (TR3_IGNORE_COLD);
1605 /* Hack -- Verify space */
1606 if (a_head->name_size + strlen(s) + 8 > fake_name_size) return (7);
1608 /* Advance and Save the name index */
1609 if (!a_ptr->name) a_ptr->name = ++a_head->name_size;
1611 /* Append chars to the name */
1612 strcpy(a_name + a_head->name_size, s);
1614 /* Advance the index */
1615 a_head->name_size += strlen(s);
1621 /* There better be a current a_ptr */
1622 if (!a_ptr) return (3);
1626 /* ±Ñ¸ì̾¤òÆɤà¥ë¡¼¥Á¥ó¤òÄɲà */
1627 /* 'E' ¤«¤é»Ï¤Þ¤ë¹Ô¤Ï±Ñ¸ì̾¤È¤·¤Æ¤¤¤ë */
1630 /* Acquire the Text */
1633 /* Hack -- Verify space */
1634 if (a_head->E_name_size + strlen(s) + 8 > E_fake_name_size) return (7);
1636 /* Advance and Save the name index */
1637 if (!a_ptr->E_name) a_ptr->E_name = ++a_head->E_name_size;
1639 /* Append chars to the name */
1640 strcpy(E_a_name+ a_head->E_name_size, s);
1642 /* Advance the index */
1643 a_head->E_name_size += strlen(s);
1651 /* Acquire the Text */
1654 /* Hack -- Verify space */
1655 if (a_head->name_size + strlen(s) + 8 > fake_name_size) return (7);
1657 /* Advance and Save the name index */
1658 if (!a_ptr->name) a_ptr->name = ++a_head->name_size;
1660 /* Append chars to the name */
1661 strcpy(a_name+ a_head->name_size, s);
1663 /* Advance the index */
1664 a_head->name_size += strlen(s);
1671 /* Process 'D' for "Description" */
1677 /* Acquire the text */
1682 /* Acquire the text */
1686 /* Hack -- Verify space */
1687 if (a_head->text_size + strlen(s) + 8 > fake_text_size) return (7);
1689 /* Advance and Save the text index */
1690 if (!a_ptr->text) a_ptr->text = ++a_head->text_size;
1692 /* Append chars to the name */
1693 strcpy(a_text + a_head->text_size, s);
1695 /* Advance the index */
1696 a_head->text_size += strlen(s);
1703 /* Process 'I' for "Info" (one line only) */
1706 int tval, sval, pval;
1708 /* Scan for the values */
1709 if (3 != sscanf(buf+2, "%d:%d:%d",
1710 &tval, &sval, &pval)) return (1);
1712 /* Save the values */
1721 /* Process 'W' for "More Info" (one line only) */
1724 int level, rarity, wgt;
1727 /* Scan for the values */
1728 if (4 != sscanf(buf+2, "%d:%d:%d:%ld",
1729 &level, &rarity, &wgt, &cost)) return (1);
1731 /* Save the values */
1732 a_ptr->level = level;
1733 a_ptr->rarity = rarity;
1734 a_ptr->weight = wgt;
1741 /* Hack -- Process 'P' for "power" and such */
1744 int ac, hd1, hd2, th, td, ta;
1746 /* Scan for the values */
1747 if (6 != sscanf(buf+2, "%d:%dd%d:%d:%d:%d",
1748 &ac, &hd1, &hd2, &th, &td, &ta)) return (1);
1761 /* Hack -- Process 'F' for flags */
1764 /* Parse every entry textually */
1765 for (s = buf + 2; *s; )
1767 /* Find the end of this entry */
1768 for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
1770 /* Nuke and skip any dividers */
1774 while ((*t == ' ') || (*t == '|')) t++;
1777 /* Parse this entry */
1778 if (0 != grab_one_artifact_flag(a_ptr, s)) return (5);
1780 /* Start the next entry */
1794 /* Complete the "name" and "text" sizes */
1795 ++a_head->name_size;
1798 ++a_head->E_name_size;
1800 ++a_head->text_size;
1809 * Grab one flag in a ego-item_type from a textual string
1811 static bool grab_one_ego_item_flag(ego_item_type *e_ptr, cptr what)
1816 for (i = 0; i < 32; i++)
1818 if (streq(what, k_info_flags1[i]))
1820 e_ptr->flags1 |= (1L << i);
1826 for (i = 0; i < 32; i++)
1828 if (streq(what, k_info_flags2[i]))
1830 e_ptr->flags2 |= (1L << i);
1836 for (i = 0; i < 32; i++)
1838 if (streq(what, k_info_flags3[i]))
1840 e_ptr->flags3 |= (1L << i);
1847 msg_format("̤ÃΤÎ̾¤Î¤¢¤ë¥¢¥¤¥Æ¥à¡¦¥Õ¥é¥° '%s'¡£", what);
1849 msg_format("Unknown ego-item flag '%s'.", what);
1861 * Initialize the "e_info" array, by parsing an ascii "template" file
1863 errr init_e_info_txt(FILE *fp, char *buf)
1870 ego_item_type *e_ptr = NULL;
1873 /* Just before the first record */
1876 /* Just before the first line */
1881 while (0 == my_fgets(fp, buf, 1024))
1883 /* Advance the line number */
1886 /* Skip comments and blank lines */
1887 if (!buf[0] || (buf[0] == '#')) continue;
1889 /* Verify correct "colon" format */
1890 if (buf[1] != ':') return (1);
1893 /* Hack -- Process 'V' for "Version" */
1901 /* Process 'N' for "New/Number/Name" */
1904 /* Find the colon before the name */
1905 s = strchr(buf+2, ':');
1907 /* Verify that colon */
1910 /* Nuke the colon, advance to the name */
1913 /* Paranoia -- require a name */
1914 if (!*s) return (1);
1919 /* Verify information */
1920 if (i < error_idx) return (4);
1922 /* Verify information */
1923 if (i >= e_head->info_num) return (2);
1925 /* Save the index */
1928 /* Point at the "info" */
1931 /* Hack -- Verify space */
1932 if (e_head->name_size + strlen(s) + 8 > fake_name_size) return (7);
1934 /* Advance and Save the name index */
1935 if (!e_ptr->name) e_ptr->name = ++e_head->name_size;
1937 /* Append chars to the name */
1938 strcpy(e_name + e_head->name_size, s);
1940 /* Advance the index */
1941 e_head->name_size += strlen(s);
1947 /* There better be a current e_ptr */
1948 if (!e_ptr) return (3);
1952 /* ±Ñ¸ì̾¤òÆɤà¥ë¡¼¥Á¥ó¤òÄɲà */
1953 /* 'E' ¤«¤é»Ï¤Þ¤ë¹Ô¤Ï±Ñ¸ì̾ */
1956 /* Acquire the Text */
1959 /* Hack -- Verify space */
1960 if (e_head->E_name_size + strlen(s) + 8 > E_fake_name_size) return (7);
1962 /* Advance and Save the name index */
1963 if (!e_ptr->E_name) e_ptr->E_name = ++e_head->E_name_size;
1965 /* Append chars to the name */
1966 strcpy(E_e_name+ e_head->E_name_size, s);
1968 /* Advance the index */
1969 e_head->E_name_size += strlen(s);
1977 /* Acquire the Text */
1980 /* Hack -- Verify space */
1981 if (e_head->name_size + strlen(s) + 8 > fake_name_size) return (7);
1983 /* Advance and Save the name index */
1984 if (!e_ptr->name) e_ptr->name = ++e_head->name_size;
1986 /* Append chars to the name */
1987 strcpy(e_name+ e_head->name_size, s);
1989 /* Advance the index */
1990 e_head->name_size += strlen(s);
1998 /* Process 'D' for "Description" */
2001 /* Acquire the text */
2004 /* Hack -- Verify space */
2005 if (e_head->text_size + strlen(s) + 8 > fake_text_size) return (7);
2007 /* Advance and Save the text index */
2008 if (!e_ptr->text) e_ptr->text = ++e_head->text_size;
2010 /* Append chars to the name */
2011 strcpy(e_text + e_head->text_size, s);
2013 /* Advance the index */
2014 e_head->text_size += strlen(s);
2022 /* Process 'X' for "Xtra" (one line only) */
2027 /* Scan for the values */
2028 if (2 != sscanf(buf+2, "%d:%d",
2029 &slot, &rating)) return (1);
2031 /* Save the values */
2033 e_ptr->rating = rating;
2039 /* Process 'W' for "More Info" (one line only) */
2042 int level, rarity, pad2;
2045 /* Scan for the values */
2046 if (4 != sscanf(buf+2, "%d:%d:%d:%ld",
2047 &level, &rarity, &pad2, &cost)) return (1);
2049 /* Save the values */
2050 e_ptr->level = level;
2051 e_ptr->rarity = rarity;
2052 /* e_ptr->weight = wgt; */
2059 /* Hack -- Process 'C' for "creation" */
2064 /* Scan for the values */
2065 if (4 != sscanf(buf+2, "%d:%d:%d:%d",
2066 &th, &td, &ta, &pv)) return (1);
2068 e_ptr->max_to_h = th;
2069 e_ptr->max_to_d = td;
2070 e_ptr->max_to_a = ta;
2071 e_ptr->max_pval = pv;
2077 /* Hack -- Process 'F' for flags */
2080 /* Parse every entry textually */
2081 for (s = buf + 2; *s; )
2083 /* Find the end of this entry */
2084 for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
2086 /* Nuke and skip any dividers */
2090 while ((*t == ' ') || (*t == '|')) t++;
2093 /* Parse this entry */
2094 if (0 != grab_one_ego_item_flag(e_ptr, s)) return (5);
2096 /* Start the next entry */
2109 /* Complete the "name" and "text" sizes */
2110 ++e_head->name_size;
2113 ++e_head->E_name_size;
2115 ++e_head->text_size;
2124 * Grab one (basic) flag in a monster_race from a textual string
2126 static errr grab_one_basic_flag(monster_race *r_ptr, cptr what)
2131 for (i = 0; i < 32; i++)
2133 if (streq(what, r_info_flags1[i]))
2135 r_ptr->flags1 |= (1L << i);
2141 for (i = 0; i < 32; i++)
2143 if (streq(what, r_info_flags2[i]))
2145 r_ptr->flags2 |= (1L << i);
2151 for (i = 0; i < 32; i++)
2153 if (streq(what, r_info_flags3[i]))
2155 r_ptr->flags3 |= (1L << i);
2161 for (i = 0; i < 32; i++)
2163 if (streq(what, r_info_flags7[i]))
2165 r_ptr->flags7 |= (1L << i);
2171 for (i = 0; i < 32; i++)
2173 if (streq(what, r_info_flags8[i]))
2175 r_ptr->flags8 |= (1L << i);
2181 for (i = 0; i < 32; i++)
2183 if (streq(what, r_info_flags9[i]))
2185 r_ptr->flags9 |= (1L << i);
2192 msg_format("̤ÃΤΥâ¥ó¥¹¥¿¡¼¡¦¥Õ¥é¥° '%s'¡£", what);
2194 msg_format("Unknown monster flag '%s'.", what);
2204 * Grab one (spell) flag in a monster_race from a textual string
2206 static errr grab_one_spell_flag(monster_race *r_ptr, cptr what)
2211 for (i = 0; i < 32; i++)
2213 if (streq(what, r_info_flags4[i]))
2215 r_ptr->flags4 |= (1L << i);
2221 for (i = 0; i < 32; i++)
2223 if (streq(what, r_info_flags5[i]))
2225 r_ptr->flags5 |= (1L << i);
2231 for (i = 0; i < 32; i++)
2233 if (streq(what, r_info_flags6[i]))
2235 r_ptr->flags6 |= (1L << i);
2242 msg_format("̤ÃΤΥâ¥ó¥¹¥¿¡¼¡¦¥Õ¥é¥° '%s'¡£", what);
2244 msg_format("Unknown monster flag '%s'.", what);
2256 * Initialize the "r_info" array, by parsing an ascii "template" file
2258 errr init_r_info_txt(FILE *fp, char *buf)
2265 monster_race *r_ptr = NULL;
2268 /* Just before the first record */
2271 /* Just before the first line */
2275 /* Start the "fake" stuff */
2276 r_head->name_size = 0;
2277 r_head->text_size = 0;
2280 while (0 == my_fgets(fp, buf, 1024))
2282 /* Advance the line number */
2285 /* Skip comments and blank lines */
2286 if (!buf[0] || (buf[0] == '#')) continue;
2288 /* Verify correct "colon" format */
2289 if (buf[1] != ':') return (1);
2292 /* Hack -- Process 'V' for "Version" */
2300 /* Process 'N' for "New/Number/Name" */
2303 /* Find the colon before the name */
2304 s = strchr(buf+2, ':');
2306 /* Verify that colon */
2309 /* Nuke the colon, advance to the name */
2312 /* Paranoia -- require a name */
2313 if (!*s) return (1);
2318 /* Verify information */
2319 if (i < error_idx) return (4);
2321 /* Verify information */
2322 if (i >= r_head->info_num) return (2);
2324 /* Save the index */
2327 /* Point at the "info" */
2330 /* Hack -- Verify space */
2331 if (r_head->name_size + strlen(s) + 8 > fake_name_size) return (7);
2333 /* Advance and Save the name index */
2334 if (!r_ptr->name) r_ptr->name = ++r_head->name_size;
2336 /* Append chars to the name */
2337 strcpy(r_name + r_head->name_size, s);
2339 /* Advance the index */
2340 r_head->name_size += strlen(s);
2346 /* There better be a current r_ptr */
2347 if (!r_ptr) return (3);
2351 /* ±Ñ¸ì̾¤òÆɤà¥ë¡¼¥Á¥ó¤òÄɲà */
2352 /* 'E' ¤«¤é»Ï¤Þ¤ë¹Ô¤Ï±Ñ¸ì̾ */
2355 /* Acquire the Text */
2358 /* Hack -- Verify space */
2359 if (r_head->E_name_size + strlen(s) + 8 > E_fake_name_size) return (7);
2361 /* Advance and Save the name index */
2362 if (!r_ptr->E_name) r_ptr->E_name = ++r_head->E_name_size;
2364 /* Append chars to the name */
2365 strcpy(E_r_name+ r_head->E_name_size, s);
2367 /* Advance the index */
2368 r_head->E_name_size += strlen(s);
2376 /* Acquire the Text */
2379 /* Hack -- Verify space */
2380 if (r_head->name_size + strlen(s) + 8 > fake_name_size) return (7);
2382 /* Advance and Save the name index */
2383 if (!r_ptr->name) r_ptr->name = ++r_head->name_size;
2385 /* Append chars to the name */
2386 strcpy(r_name+ r_head->name_size, s);
2388 /* Advance the index */
2389 r_head->name_size += strlen(s);
2395 /* Process 'D' for "Description" */
2401 /* Acquire the text */
2406 /* Acquire the text */
2410 /* Hack -- Verify space */
2411 if (r_head->text_size + strlen(s) + 8 > fake_text_size) return (7);
2413 /* Advance and Save the text index */
2414 if (!r_ptr->text) r_ptr->text = ++r_head->text_size;
2416 /* Append chars to the name */
2417 strcpy(r_text + r_head->text_size, s);
2419 /* Advance the index */
2420 r_head->text_size += strlen(s);
2426 /* Process 'G' for "Graphics" (one line only) */
2433 if (!buf[2]) return (1);
2434 if (!buf[3]) return (1);
2435 if (!buf[4]) return (1);
2437 /* Extract the char */
2440 /* Extract the attr */
2441 tmp = color_char_to_attr(buf[4]);
2444 if (tmp < 0) return (1);
2446 /* Save the values */
2447 r_ptr->d_char = sym;
2448 r_ptr->d_attr = tmp;
2454 /* Process 'I' for "Info" (one line only) */
2457 int spd, hp1, hp2, aaf, ac, slp;
2459 /* Scan for the other values */
2460 if (6 != sscanf(buf+2, "%d:%dd%d:%d:%d:%d",
2461 &spd, &hp1, &hp2, &aaf, &ac, &slp)) return (1);
2463 /* Save the values */
2475 /* Process 'W' for "More Info" (one line only) */
2483 /* Scan for the values */
2484 if (6 != sscanf(buf+2, "%d:%d:%d:%ld:%ld:%d",
2485 &lev, &rar, &pad, &exp, &nextexp, &nextmon)) return (1);
2487 /* Save the values */
2489 r_ptr->rarity = rar;
2492 r_ptr->next_exp = nextexp;
2493 r_ptr->next_r_idx = nextmon;
2499 /* Process 'B' for "Blows" (up to four lines) */
2504 /* Find the next empty blow slot (if any) */
2505 for (i = 0; i < 4; i++) if (!r_ptr->blow[i].method) break;
2507 /* Oops, no more slots */
2508 if (i == 4) return (1);
2510 /* Analyze the first field */
2511 for (s = t = buf+2; *t && (*t != ':'); t++) /* loop */;
2513 /* Terminate the field (if necessary) */
2514 if (*t == ':') *t++ = '\0';
2516 /* Analyze the method */
2517 for (n1 = 0; r_info_blow_method[n1]; n1++)
2519 if (streq(s, r_info_blow_method[n1])) break;
2522 /* Invalid method */
2523 if (!r_info_blow_method[n1]) return (1);
2525 /* Analyze the second field */
2526 for (s = t; *t && (*t != ':'); t++) /* loop */;
2528 /* Terminate the field (if necessary) */
2529 if (*t == ':') *t++ = '\0';
2531 /* Analyze effect */
2532 for (n2 = 0; r_info_blow_effect[n2]; n2++)
2534 if (streq(s, r_info_blow_effect[n2])) break;
2537 /* Invalid effect */
2538 if (!r_info_blow_effect[n2]) return (1);
2540 /* Analyze the third field */
2541 for (s = t; *t && (*t != 'd'); t++) /* loop */;
2543 /* Terminate the field (if necessary) */
2544 if (*t == 'd') *t++ = '\0';
2546 /* Save the method */
2547 r_ptr->blow[i].method = n1;
2549 /* Save the effect */
2550 r_ptr->blow[i].effect = n2;
2552 /* Extract the damage dice and sides */
2553 r_ptr->blow[i].d_dice = atoi(s);
2554 r_ptr->blow[i].d_side = atoi(t);
2560 /* Process 'F' for "Basic Flags" (multiple lines) */
2563 /* Parse every entry */
2564 for (s = buf + 2; *s; )
2566 /* Find the end of this entry */
2567 for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
2569 /* Nuke and skip any dividers */
2573 while (*t == ' ' || *t == '|') t++;
2576 /* Parse this entry */
2577 if (0 != grab_one_basic_flag(r_ptr, s)) return (5);
2579 /* Start the next entry */
2587 /* Process 'S' for "Spell Flags" (multiple lines) */
2590 /* Parse every entry */
2591 for (s = buf + 2; *s; )
2593 /* Find the end of this entry */
2594 for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
2596 /* Nuke and skip any dividers */
2600 while ((*t == ' ') || (*t == '|')) t++;
2603 /* XXX XXX XXX Hack -- Read spell frequency */
2604 if (1 == sscanf(s, "1_IN_%d", &i))
2606 /* Extract a "frequency" */
2607 r_ptr->freq_spell = r_ptr->freq_inate = 100 / i;
2609 /* Start at next entry */
2616 /* Parse this entry */
2617 if (0 != grab_one_spell_flag(r_ptr, s)) return (5);
2619 /* Start the next entry */
2632 /* Complete the "name" and "text" sizes */
2633 ++r_head->name_size;
2636 ++r_head->E_name_size;
2638 ++r_head->text_size;
2641 for (i = 1; i < max_r_idx; i++)
2643 /* Invert flag WILD_ONLY <-> RF8_DUNGEON */
2644 r_info[i].flags8 ^= 1L;
2646 /* WILD_TOO without any other wilderness flags enables all flags */
2647 if ((r_info[i].flags8 & RF8_WILD_TOO) && !(r_info[i].flags8 & 0x7FFFFFFE))
2648 r_info[i].flags8 = 0x0463;
2657 * Grab one flag for a dungeon type from a textual string
2659 static errr grab_one_dungeon_flag(dungeon_info_type *d_ptr, cptr what)
2664 for (i = 0; i < 32; i++)
2666 if (streq(what, d_info_flags1[i]))
2668 d_ptr->flags1 |= (1L << i);
2675 msg_format("̤ÃΤΥÀ¥ó¥¸¥ç¥ó¡¦¥Õ¥é¥° '%s'¡£", what);
2677 msg_format("Unknown dungeon type flag '%s'.", what);
2685 * Grab one (basic) flag in a monster_race from a textual string
2687 static errr grab_one_basic_monster_flag(dungeon_info_type *d_ptr, cptr what)
2692 for (i = 0; i < 32; i++)
2694 if (streq(what, r_info_flags1[i]))
2696 d_ptr->mflags1 |= (1L << i);
2702 for (i = 0; i < 32; i++)
2704 if (streq(what, r_info_flags2[i]))
2706 d_ptr->mflags2 |= (1L << i);
2712 for (i = 0; i < 32; i++)
2714 if (streq(what, r_info_flags3[i]))
2716 d_ptr->mflags3 |= (1L << i);
2722 for (i = 0; i < 32; i++)
2724 if (streq(what, r_info_flags7[i]))
2726 d_ptr->mflags7 |= (1L << i);
2732 for (i = 0; i < 32; i++)
2734 if (streq(what, r_info_flags8[i]))
2736 d_ptr->mflags8 |= (1L << i);
2742 for (i = 0; i < 32; i++)
2744 if (streq(what, r_info_flags9[i]))
2746 d_ptr->mflags9 |= (1L << i);
2753 msg_format("̤ÃΤΥâ¥ó¥¹¥¿¡¼¡¦¥Õ¥é¥° '%s'¡£", what);
2755 msg_format("Unknown monster flag '%s'.", what);
2763 * Grab one (spell) flag in a monster_race from a textual string
2765 static errr grab_one_spell_monster_flag(dungeon_info_type *d_ptr, cptr what)
2770 for (i = 0; i < 32; i++)
2772 if (streq(what, r_info_flags4[i]))
2774 d_ptr->mflags4 |= (1L << i);
2780 for (i = 0; i < 32; i++)
2782 if (streq(what, r_info_flags5[i]))
2784 d_ptr->mflags5 |= (1L << i);
2790 for (i = 0; i < 32; i++)
2792 if (streq(what, r_info_flags6[i]))
2794 d_ptr->mflags6 |= (1L << i);
2801 msg_format("̤ÃΤΥâ¥ó¥¹¥¿¡¼¡¦¥Õ¥é¥° '%s'¡£", what);
2803 msg_format("Unknown monster flag '%s'.", what);
2811 * Initialize the "d_info" array, by parsing an ascii "template" file
2813 errr init_d_info_txt(FILE *fp, char *buf)
2820 dungeon_info_type *d_ptr = NULL;
2823 /* Just before the first record */
2826 /* Just before the first line */
2830 /* Start the "fake" stuff */
2831 d_head->name_size = 0;
2832 d_head->text_size = 0;
2835 while (0 == my_fgets(fp, buf, 1024))
2837 /* Advance the line number */
2840 /* Skip comments and blank lines */
2841 if (!buf[0] || (buf[0] == '#')) continue;
2843 /* Verify correct "colon" format */
2844 if (buf[1] != ':') return (1);
2847 /* Hack -- Process 'V' for "Version" */
2854 /* Process 'N' for "New/Number/Name" */
2857 /* Find the colon before the name */
2858 s = strchr(buf+2, ':');
2860 /* Verify that colon */
2863 /* Nuke the colon, advance to the name */
2866 /* Paranoia -- require a name */
2867 if (!*s) return (1);
2872 /* Verify information */
2873 if (i < error_idx) return (4);
2875 /* Verify information */
2876 if (i >= d_head->info_num) return (2);
2878 /* Save the index */
2881 /* Point at the "info" */
2884 /* Hack -- Verify space */
2885 if (d_head->name_size + strlen(s) + 8 > fake_name_size) return (7);
2887 /* Advance and Save the name index */
2888 if (!d_ptr->name) d_ptr->name = ++d_head->name_size;
2890 /* Append chars to the name */
2891 strcpy(d_name + d_head->name_size, s);
2893 /* Advance the index */
2894 d_head->name_size += strlen(s);
2906 /* Acquire the Text */
2909 /* Hack -- Verify space */
2910 if (d_head->name_size + strlen(s) + 8 > fake_name_size) return (7);
2912 /* Advance and Save the name index */
2913 if (!d_ptr->name) d_ptr->name = ++d_head->name_size;
2915 /* Append chars to the name */
2916 strcpy(d_name + d_head->name_size, s);
2918 /* Advance the index */
2919 d_head->name_size += strlen(s);
2926 /* Process 'D' for "Description */
2932 /* Acquire the text */
2937 /* Acquire the text */
2941 /* Hack -- Verify space */
2942 if (d_head->text_size + strlen(s) + 8 > fake_text_size) return (7);
2944 /* Advance and Save the text index */
2945 if (!d_ptr->text) d_ptr->text = ++d_head->text_size;
2947 /* Append chars to the name */
2948 strcpy(d_text + d_head->text_size, s);
2950 /* Advance the index */
2951 d_head->text_size += strlen(s);
2957 /* Process 'W' for "More Info" (one line only) */
2960 int min_lev, max_lev;
2962 int min_alloc, max_chance;
2963 int obj_good, obj_great;
2966 /* Scan for the values */
2967 if (10 != sscanf(buf+2, "%d:%d:%d:%d:%d:%d:%d:%d:%x:%x",
2968 &min_lev, &max_lev, &min_plev, &mode, &min_alloc, &max_chance, &obj_good, &obj_great, &pit, &nest)) return (1);
2970 /* Save the values */
2971 d_ptr->mindepth = min_lev;
2972 d_ptr->maxdepth = max_lev;
2973 d_ptr->min_plev = min_plev;
2975 d_ptr->min_m_alloc_level = min_alloc;
2976 d_ptr->max_m_alloc_chance = max_chance;
2977 d_ptr->obj_good = obj_good;
2978 d_ptr->obj_great = obj_great;
2986 /* Process 'P' for "Place Info" */
2991 /* Scan for the values */
2992 if (2 != sscanf(buf+2, "%d:%d", &dy, &dx)) return (1);
2994 /* Save the values */
3002 /* Process 'L' for "fLoor type" (one line only) */
3009 /* Scan for the values */
3010 if (7 != sscanf(buf+2, "%d:%d:%d:%d:%d:%d:%d",
3011 &f1, &p1, &f2, &p2, &f3, &p3, &tunnel)) return (1);
3013 /* Save the values */
3015 d_ptr->floor_percent1 = p1;
3017 d_ptr->floor_percent2 = p2;
3019 d_ptr->floor_percent3 = p3;
3020 d_ptr->tunnel_percent = tunnel;
3026 /* Process 'A' for "wAll type" (one line only) */
3029 int w1, w2, w3, outer, inner, stream1, stream2;
3032 /* Scan for the values */
3033 if (10 != sscanf(buf+2, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
3034 &w1, &p1, &w2, &p2, &w3, &p3, &outer, &inner, &stream1, &stream2)) return (1);
3036 /* Save the values */
3037 d_ptr->fill_type1 = w1;
3038 d_ptr->fill_percent1 = p1;
3039 d_ptr->fill_type2 = w2;
3040 d_ptr->fill_percent2 = p2;
3041 d_ptr->fill_type3 = w3;
3042 d_ptr->fill_percent3 = p3;
3043 d_ptr->outer_wall = outer;
3044 d_ptr->inner_wall = inner;
3045 d_ptr->stream1 = stream1;
3046 d_ptr->stream2 = stream2;
3052 /* Process 'F' for "Dungeon Flags" (multiple lines) */
3055 int artif = 0, monst = 0;
3057 /* Parse every entry */
3058 for (s = buf + 2; *s; )
3060 /* Find the end of this entry */
3061 for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
3063 /* Nuke and skip any dividers */
3067 while (*t == ' ' || *t == '|') t++;
3070 /* XXX XXX XXX Hack -- Read Final Artifact */
3071 if (1 == sscanf(s, "FINAL_ARTIFACT_%d", &artif))
3073 /* Extract a "Final Artifact" */
3074 d_ptr->final_artifact = artif;
3076 /* Start at next entry */
3083 /* XXX XXX XXX Hack -- Read Final Object */
3084 if (1 == sscanf(s, "FINAL_OBJECT_%d", &artif))
3086 /* Extract a "Final Artifact" */
3087 d_ptr->final_object = artif;
3089 /* Start at next entry */
3096 /* XXX XXX XXX Hack -- Read Artifact Guardian */
3097 if (1 == sscanf(s, "FINAL_GUARDIAN_%d", &monst))
3099 /* Extract a "Artifact Guardian" */
3100 d_ptr->final_guardian = monst;
3102 /* Start at next entry */
3109 /* XXX XXX XXX Hack -- Read Special Percentage */
3110 if (1 == sscanf(s, "MONSTER_DIV_%d", &monst))
3112 /* Extract a "Special %" */
3113 d_ptr->special_div = monst;
3115 /* Start at next entry */
3122 /* Parse this entry */
3123 if (0 != grab_one_dungeon_flag(d_ptr, s)) return (5);
3125 /* Start the next entry */
3133 /* Process 'M' for "Basic Flags" (multiple lines) */
3136 byte r_char_number = 0, r_char;
3138 /* Parse every entry */
3139 for (s = buf + 2; *s; )
3141 /* Find the end of this entry */
3142 for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
3144 /* Nuke and skip any dividers */
3148 while (*t == ' ' || *t == '|') t++;
3151 /* XXX XXX XXX Hack -- Read monster symbols */
3152 if (1 == sscanf(s, "R_CHAR_%c", &r_char))
3154 /* Limited to 5 races */
3155 if(r_char_number >= 5) continue;
3157 /* Extract a "frequency" */
3158 d_ptr->r_char[r_char_number++] = r_char;
3160 /* Start at next entry */
3167 /* Parse this entry */
3168 if (0 != grab_one_basic_monster_flag(d_ptr, s)) return (5);
3170 /* Start the next entry */
3178 /* Process 'S' for "Spell Flags" (multiple lines) */
3181 /* Parse every entry */
3182 for (s = buf + 2; *s; )
3184 /* Find the end of this entry */
3185 for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
3187 /* Nuke and skip any dividers */
3191 while ((*t == ' ') || (*t == '|')) t++;
3194 /* XXX XXX XXX Hack -- Read spell frequency */
3195 if (1 == sscanf(s, "1_IN_%d", &i))
3197 /* Start at next entry */
3204 /* Parse this entry */
3205 if (0 != grab_one_spell_monster_flag(d_ptr, s)) return (5);
3207 /* Start the next entry */
3219 ++d_head->text_size;
3226 #else /* ALLOW_TEMPLATES */
3232 #endif /* ALLOW_TEMPLATES */
3235 /* Random dungeon grid effects */
3236 #define RANDOM_NONE 0x00
3237 #define RANDOM_FEATURE 0x01
3238 #define RANDOM_MONSTER 0x02
3239 #define RANDOM_OBJECT 0x04
3240 #define RANDOM_EGO 0x08
3241 #define RANDOM_ARTIFACT 0x10
3242 #define RANDOM_TRAP 0x20
3245 typedef struct dungeon_grid dungeon_grid;
3249 int feature; /* Terrain feature */
3250 int monster; /* Monster */
3251 int object; /* Object */
3252 int ego; /* Ego-Item */
3253 int artifact; /* Artifact */
3254 int trap; /* Trap */
3255 int cave_info; /* Flags for CAVE_MARK, CAVE_GLOW, CAVE_ICKY, CAVE_ROOM */
3256 int special; /* Reserved for special terrain info */
3257 int random; /* Number of the random effect */
3261 static dungeon_grid letter[255];
3265 * Process "F:<letter>:<terrain>:<cave_info>:<monster>:<object>:<ego>:<artifact>:<trap>:<special>" -- info for dungeon grid
3267 static errr parse_line_feature(char *buf)
3273 if (init_flags & INIT_ONLY_BUILDINGS) return (0);
3275 /* Tokenize the line */
3276 if ((num = tokenize(buf+2, 9, zz, 0)) > 1)
3278 /* Letter to assign */
3279 int index = zz[0][0];
3281 /* Reset the info for the letter */
3282 letter[index].feature = 0;
3283 letter[index].monster = 0;
3284 letter[index].object = 0;
3285 letter[index].ego = 0;
3286 letter[index].artifact = 0;
3287 letter[index].trap = 0;
3288 letter[index].cave_info = 0;
3289 letter[index].special = 0;
3290 letter[index].random = 0;
3296 letter[index].special = atoi(zz[8]);
3300 if (zz[7][0] == '*')
3302 letter[index].random |= RANDOM_TRAP;
3307 letter[index].trap = atoi(zz[7]);
3312 letter[index].trap = atoi(zz[7]);
3317 if (zz[6][0] == '*')
3319 letter[index].random |= RANDOM_ARTIFACT;
3324 letter[index].artifact = atoi(zz[6]);
3329 letter[index].artifact = atoi(zz[6]);
3334 if (zz[5][0] == '*')
3336 letter[index].random |= RANDOM_EGO;
3341 letter[index].ego = atoi(zz[5]);
3346 letter[index].ego = atoi(zz[5]);
3351 if (zz[4][0] == '*')
3353 letter[index].random |= RANDOM_OBJECT;
3358 letter[index].object = atoi(zz[4]);
3363 letter[index].object = atoi(zz[4]);
3368 if (zz[3][0] == '*')
3370 letter[index].random |= RANDOM_MONSTER;
3374 letter[index].monster = atoi(zz[3]);
3379 letter[index].monster = atoi(zz[3]);
3384 letter[index].cave_info = atoi(zz[2]);
3388 if (zz[1][0] == '*')
3390 letter[index].random |= RANDOM_FEATURE;
3394 letter[index].feature = atoi(zz[1]);
3399 letter[index].feature = atoi(zz[1]);
3412 * Process "F:<letter>:<terrain>:<cave_info>:<monster>:<object>:<ego>:<artifact>:<trap>:<special>" -- info for dungeon grid
3414 static errr parse_line_building(char *buf)
3430 /* Get the building number */
3433 /* Find the colon after the building number */
3436 /* Verify that colon */
3439 /* Nuke the colon, advance to the sub-index */
3442 /* Paranoia -- require a sub-index */
3443 if (!*s) return (1);
3445 /* Building definition sub-index */
3448 /* Building name, owner, race */
3451 if (tokenize(s + 2, 3, zz, 0) == 3)
3453 /* Name of the building */
3454 strcpy(building[index].name, zz[0]);
3456 /* Name of the owner */
3457 strcpy(building[index].owner_name, zz[1]);
3459 /* Race of the owner */
3460 strcpy(building[index].owner_race, zz[2]);
3465 return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3468 /* Building Action */
3471 if (tokenize(s + 2, 8, zz, 0) >= 7)
3473 /* Index of the action */
3474 int action_index = atoi(zz[0]);
3476 /* Name of the action */
3477 strcpy(building[index].act_names[action_index], zz[1]);
3479 /* Cost of the action for members */
3480 building[index].member_costs[action_index] = atoi(zz[2]);
3482 /* Cost of the action for non-members */
3483 building[index].other_costs[action_index] = atoi(zz[3]);
3485 /* Letter assigned to the action */
3486 building[index].letters[action_index] = zz[4][0];
3489 building[index].actions[action_index] = atoi(zz[5]);
3491 /* Action restriction */
3492 building[index].action_restr[action_index] = atoi(zz[6]);
3497 return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3500 /* Building Classes */
3503 if (tokenize(s + 2, MAX_CLASS, zz, 0) == MAX_CLASS)
3505 for (i = 0; i < MAX_CLASS; i++)
3507 building[index].member_class[i] = atoi(zz[i]);
3513 return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3516 /* Building Races */
3519 if (tokenize(s+2, MAX_RACES, zz, 0) == MAX_RACES)
3521 for (i = 0; i < MAX_RACES; i++)
3523 building[index].member_race[i] = atoi(zz[i]);
3529 return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3532 /* Building Realms */
3535 if (tokenize(s+2, MAX_MAGIC, zz, 0) == MAX_MAGIC)
3537 for (i = 0; i < MAX_MAGIC; i++)
3539 building[index].member_realm[i+1] = atoi(zz[i]);
3545 return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3551 if (tokenize(s+2, 2, zz, 0) == 2)
3553 /* Index of the action */
3554 int action_index = atoi(zz[0]);
3556 /* Name of the action */
3557 strcpy(building[index].act_script[action_index], zz[1]);
3562 #else /* USE_SCRIPT */
3563 /* Ignore scripts */
3565 #endif /* USE_SCRIPT */
3570 return (PARSE_ERROR_UNDEFINED_DIRECTIVE);
3579 * Parse a sub-file of the "extra info"
3581 static errr process_dungeon_file_aux(char *buf, int ymin, int xmin, int ymax, int xmax, int *y, int *x)
3588 /* Skip "empty" lines */
3589 if (!buf[0]) return (0);
3591 /* Skip "blank" lines */
3592 if (isspace(buf[0])) return (0);
3595 if (buf[0] == '#') return (0);
3597 /* Require "?:*" format */
3598 if (buf[1] != ':') return (1);
3601 /* Process "%:<fname>" */
3604 /* Attempt to Process the given file */
3605 return (process_dungeon_file(buf + 2, ymin, xmin, ymax, xmax));
3608 /* Process "F:<letter>:<terrain>:<cave_info>:<monster>:<object>:<ego>:<artifact>:<trap>:<special>" -- info for dungeon grid */
3611 return parse_line_feature(buf);
3614 /* Process "D:<dungeon>" -- info for the cave grids */
3615 else if (buf[0] == 'D')
3617 object_type object_type_body;
3619 /* Acquire the text */
3622 /* Length of the text */
3623 int len = strlen(s);
3625 if (init_flags & INIT_ONLY_BUILDINGS) return (0);
3627 for (*x = xmin, i = 0; ((*x < xmax) && (i < len)); (*x)++, s++, i++)
3629 /* Access the grid */
3630 cave_type *c_ptr = &cave[*y][*x];
3634 int object_index = letter[idx].object;
3635 int monster_index = letter[idx].monster;
3636 int random = letter[idx].random;
3637 int artifact_index = letter[idx].artifact;
3639 /* Lay down a floor */
3640 c_ptr->feat = letter[idx].feature;
3642 /* Only the features */
3643 if (init_flags & INIT_ONLY_FEATURES) continue;
3646 c_ptr->info = letter[idx].cave_info;
3648 /* Create a monster */
3649 if (random & RANDOM_MONSTER)
3651 monster_level = base_level + monster_index;
3653 place_monster(*y, *x, TRUE, TRUE);
3655 monster_level = base_level;
3657 else if (monster_index)
3659 /* Make alive again */
3660 if (r_info[monster_index].flags1 & RF1_UNIQUE)
3662 r_info[monster_index].cur_num = 0;
3663 r_info[monster_index].max_num = 1;
3666 /* Make alive again */
3667 if (r_info[monster_index].flags7 & RF7_UNIQUE_7)
3669 if (r_info[monster_index].cur_num == r_info[monster_index].max_num)
3671 r_info[monster_index].max_num++;
3676 place_monster_aux(*y, *x, monster_index, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE);
3679 /* Object (and possible trap) */
3680 if ((random & RANDOM_OBJECT) && (random & RANDOM_TRAP))
3682 object_level = base_level + object_index;
3685 * Random trap and random treasure defined
3686 * 25% chance for trap and 75% chance for object
3688 if (rand_int(100) < 75)
3690 place_object(*y, *x, FALSE, FALSE);
3697 object_level = base_level;
3699 else if (random & RANDOM_OBJECT)
3701 object_level = base_level + object_index;
3703 /* Create an out of deep object */
3704 if (rand_int(100) < 75)
3705 place_object(*y, *x, FALSE, FALSE);
3706 else if (rand_int(100) < 80)
3707 place_object(*y, *x, TRUE, FALSE);
3709 place_object(*y, *x, TRUE, TRUE);
3711 object_level = base_level;
3714 else if (random & RANDOM_TRAP)
3718 else if (object_index)
3720 /* Get local object */
3721 object_type *o_ptr = &object_type_body;
3723 /* Create the item */
3724 object_prep(o_ptr, object_index);
3726 if (o_ptr->tval == TV_GOLD)
3728 coin_type = object_index - OBJ_GOLD_LIST;
3733 /* Apply magic (no messages, no artifacts) */
3734 apply_magic(o_ptr, base_level, FALSE, TRUE, FALSE, FALSE);
3737 o_ptr->python = object_create_callback(o_ptr);
3738 #endif /* USE_SCRIPT */
3740 (void)drop_near(o_ptr, -1, *y, *x);
3746 if (a_info[artifact_index].cur_num)
3750 object_type *q_ptr = &forge;
3752 object_prep(q_ptr, k_idx);
3754 q_ptr->python = object_create_callback(q_ptr);
3755 #endif /* USE_SCRIPT */
3757 /* Drop it in the dungeon */
3758 (void)drop_near(q_ptr, -1, *y, *x);
3762 /* Create the artifact */
3763 create_named_art(artifact_index, *y, *x);
3765 a_info[artifact_index].cur_num = 1;
3769 /* Terrain special */
3770 c_ptr->special = letter[idx].special;
3778 /* Process "Q:<number>:<command>:... -- quest info */
3779 else if (buf[0] == 'Q')
3786 num = tokenize(buf + 2, 33, zz, 0);
3790 num = tokenize(buf + 3, 33, zz, 0);
3793 /* Have we enough parameters? */
3794 if (num < 3) return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3797 q_ptr = &(quest[atoi(zz[0])]);
3799 /* Process "Q:<q_index>:Q:<type>:<num_mon>:<cur_num>:<max_num>:<level>:<r_idx>:<k_idx>:<flags>" -- quest info */
3800 if (zz[1][0] == 'Q')
3802 if (init_flags & INIT_ASSIGN)
3804 monster_race *r_ptr;
3805 artifact_type *a_ptr;
3807 if (num < 9) return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3809 q_ptr->type = atoi(zz[2]);
3810 q_ptr->num_mon = atoi(zz[3]);
3811 q_ptr->cur_num = atoi(zz[4]);
3812 q_ptr->max_num = atoi(zz[5]);
3813 q_ptr->level = atoi(zz[6]);
3814 q_ptr->r_idx = atoi(zz[7]);
3815 q_ptr->k_idx = atoi(zz[8]);
3816 q_ptr->dungeon = atoi(zz[9]);
3819 q_ptr->flags = atoi(zz[10]);
3821 r_ptr = &r_info[q_ptr->r_idx];
3822 if (r_ptr->flags1 & RF1_UNIQUE)
3823 r_ptr->flags1 |= RF1_QUESTOR;
3825 a_ptr = &a_info[q_ptr->k_idx];
3826 a_ptr->flags3 |= TR3_QUESTITEM;
3831 /* Process "Q:<q_index>:N:<name>" -- quest name */
3832 else if (zz[1][0] == 'N')
3834 if (init_flags & (INIT_ASSIGN | INIT_SHOW_TEXT))
3836 strcpy(q_ptr->name, zz[2]);
3842 /* Process "Q:<q_index>:T:<text>" -- quest description line */
3843 else if (zz[1][0] == 'T')
3845 if (init_flags & INIT_SHOW_TEXT)
3847 strcpy(quest_text[quest_text_line], zz[2]);
3855 /* Process "W:<command>: ..." -- info for the wilderness */
3856 else if (buf[0] == 'W')
3858 return parse_line_wilderness(buf, ymin, xmin, ymax, xmax, y, x);
3861 /* Process "P:<y>:<x>" -- player position */
3862 else if (buf[0] == 'P')
3864 if (init_flags & INIT_CREATE_DUNGEON)
3866 if (tokenize(buf + 2, 2, zz, 0) == 2)
3868 int panels_x, panels_y;
3870 /* Hack - Set the dungeon size */
3871 panels_y = (*y / SCREEN_HGT);
3872 if (*y % SCREEN_HGT) panels_y++;
3873 cur_hgt = panels_y * SCREEN_HGT;
3875 panels_x = (*x / SCREEN_WID);
3876 if (*x % SCREEN_WID) panels_x++;
3877 cur_wid = panels_x * SCREEN_WID;
3879 /* Choose a panel row */
3880 max_panel_rows = (cur_hgt / SCREEN_HGT) * 2 - 2;
3881 if (max_panel_rows < 0) max_panel_rows = 0;
3883 /* Choose a panel col */
3884 max_panel_cols = (cur_wid / SCREEN_WID) * 2 - 2;
3885 if (max_panel_cols < 0) max_panel_cols = 0;
3887 /* Assume illegal panel */
3888 panel_row = max_panel_rows;
3889 panel_col = max_panel_cols;
3891 /* Place player in a quest level */
3892 if (p_ptr->inside_quest)
3896 /* Delete the monster (if any) */
3897 delete_monster(py, px);
3905 /* Place player in the town */
3906 else if (!p_ptr->oldpx && !p_ptr->oldpy)
3908 p_ptr->oldpy = atoi(zz[0]);
3909 p_ptr->oldpx = atoi(zz[1]);
3917 /* Process "B:<Index>:<Command>:..." -- Building definition */
3918 else if (buf[0] == 'B')
3920 return parse_line_building(buf);
3923 /* Process "M:<type>:<maximum>" -- set maximum values */
3924 else if (buf[0] == 'M')
3926 if (tokenize(buf+2, 2, zz, 0) == 2)
3929 if (zz[0][0] == 'T')
3931 max_towns = atoi(zz[1]);
3934 /* Maximum quests */
3935 else if (zz[0][0] == 'Q')
3937 max_quests = atoi(zz[1]);
3941 else if (zz[0][0] == 'R')
3943 max_r_idx = atoi(zz[1]);
3947 else if (zz[0][0] == 'K')
3949 max_k_idx = atoi(zz[1]);
3953 else if (zz[0][0] == 'V')
3955 max_v_idx = atoi(zz[1]);
3959 else if (zz[0][0] == 'F')
3961 max_f_idx = atoi(zz[1]);
3965 else if (zz[0][0] == 'A')
3967 max_a_idx = atoi(zz[1]);
3971 else if (zz[0][0] == 'E')
3973 max_e_idx = atoi(zz[1]);
3977 else if (zz[0][0] == 'D')
3979 max_d_idx = atoi(zz[1]);
3983 else if (zz[0][0] == 'O')
3985 max_o_idx = atoi(zz[1]);
3989 else if (zz[0][0] == 'M')
3991 max_m_idx = atoi(zz[1]);
3994 /* Wilderness size */
3995 else if (zz[0][0] == 'W')
3997 /* Maximum wild_x_size */
3998 if (zz[0][1] == 'X')
3999 max_wild_x = atoi(zz[1]);
4000 /* Maximum wild_y_size */
4001 if (zz[0][1] == 'Y')
4002 max_wild_y = atoi(zz[1]);
4016 static cptr variant = "ZANGBAND";
4020 * Helper function for "process_dungeon_file()"
4022 static cptr process_dungeon_file_expr(char **sp, char *fp)
4038 while (isspace(*s)) s++;
4056 t = process_dungeon_file_expr(&s, &f);
4065 else if (streq(t, "IOR"))
4068 while (*s && (f != b2))
4070 t = process_dungeon_file_expr(&s, &f);
4071 if (*t && !streq(t, "0")) v = "1";
4076 else if (streq(t, "AND"))
4079 while (*s && (f != b2))
4081 t = process_dungeon_file_expr(&s, &f);
4082 if (*t && streq(t, "0")) v = "0";
4087 else if (streq(t, "NOT"))
4090 while (*s && (f != b2))
4092 t = process_dungeon_file_expr(&s, &f);
4093 if (*t && streq(t, "1")) v = "0";
4098 else if (streq(t, "EQU"))
4101 if (*s && (f != b2))
4103 t = process_dungeon_file_expr(&s, &f);
4105 while (*s && (f != b2))
4108 t = process_dungeon_file_expr(&s, &f);
4109 if (*t && !streq(p, t)) v = "0";
4114 else if (streq(t, "LEQ"))
4117 if (*s && (f != b2))
4119 t = process_dungeon_file_expr(&s, &f);
4121 while (*s && (f != b2))
4124 t = process_dungeon_file_expr(&s, &f);
4125 if (*t && (strcmp(p, t) > 0)) v = "0";
4130 else if (streq(t, "GEQ"))
4133 if (*s && (f != b2))
4135 t = process_dungeon_file_expr(&s, &f);
4137 while (*s && (f != b2))
4140 t = process_dungeon_file_expr(&s, &f);
4141 if (*t && (strcmp(p, t) < 0)) v = "0";
4148 while (*s && (f != b2))
4150 t = process_dungeon_file_expr(&s, &f);
4155 if (f != b2) v = "?x?x?";
4157 /* Extract final and Terminate */
4158 if ((f = *s) != '\0') *s++ = '\0';
4164 /* Accept all printables except spaces and brackets */
4165 while (isprint(*s) && !strchr(" []", *s)) ++s;
4167 /* Extract final and Terminate */
4168 if ((f = *s) != '\0') *s++ = '\0';
4174 if (streq(b+1, "SYS"))
4180 else if (streq(b+1, "GRAF"))
4185 else if (streq(b+1, "MONOCHROME"))
4194 else if (streq(b+1, "RACE"))
4197 v = rp_ptr->E_title;
4204 else if (streq(b+1, "CLASS"))
4207 v = cp_ptr->E_title;
4214 else if (streq(b+1, "REALM1"))
4217 v = E_realm_names[p_ptr->realm1];
4219 v = realm_names[p_ptr->realm1];
4224 else if (streq(b+1, "REALM2"))
4227 v = E_realm_names[p_ptr->realm2];
4229 v = realm_names[p_ptr->realm2];
4234 else if (streq(b+1, "PLAYER"))
4240 else if (streq(b+1, "TOWN"))
4242 sprintf(tmp, "%d", p_ptr->town_num);
4247 else if (streq(b+1, "LEVEL"))
4249 sprintf(tmp, "%d", p_ptr->lev);
4253 /* Current quest number */
4254 else if (streq(b+1, "QUEST_NUMBER"))
4256 sprintf(tmp, "%d", p_ptr->inside_quest);
4260 /* Number of last quest */
4261 else if (streq(b+1, "LEAVING_QUEST"))
4263 sprintf(tmp, "%d", leaving_quest);
4268 else if (prefix(b+1, "QUEST"))
4270 /* "QUEST" uses a special parameter to determine the number of the quest */
4271 sprintf(tmp, "%d", quest[atoi(b+6)].status);
4276 else if (prefix(b+1, "RANDOM"))
4278 /* "RANDOM" uses a special parameter to determine the number of the quest */
4279 sprintf(tmp, "%d", (int)(seed_town%atoi(b+7)));
4284 else if (streq(b+1, "VARIANT"))
4290 else if (streq(b+1, "WILDERNESS"))
4293 sprintf(tmp, "NONE");
4295 sprintf(tmp, "LITE");
4297 sprintf(tmp, "NORMAL");
4320 errr process_dungeon_file(cptr name, int ymin, int xmin, int ymax, int xmax)
4330 bool bypass = FALSE;
4332 int x = xmin, y = ymin;
4335 /* Build the filename */
4336 path_build(buf, 1024, ANGBAND_DIR_EDIT, name);
4339 fp = my_fopen(buf, "r");
4342 if (!fp) return (-1);
4345 /* Process the file */
4346 while (0 == my_fgets(fp, buf, 1024))
4352 /* Skip "empty" lines */
4353 if (!buf[0]) continue;
4355 /* Skip "blank" lines */
4356 if (isspace(buf[0])) continue;
4359 if (buf[0] == '#') continue;
4362 /* Process "?:<expr>" */
4363 if ((buf[0] == '?') && (buf[1] == ':'))
4372 /* Parse the expr */
4373 v = process_dungeon_file_expr(&s, &f);
4376 bypass = (streq(v, "0") ? TRUE : FALSE);
4382 /* Apply conditionals */
4383 if (bypass) continue;
4386 /* Process "%:<file>" */
4389 /* Process that file if allowed */
4390 (void)process_dungeon_file(buf + 2, ymin, xmin, ymax, xmax);
4397 /* Process the line */
4398 err = process_dungeon_file_aux(buf, ymin, xmin, ymax, xmax, &y, &x);
4410 oops = (((err > 0) && (err < PARSE_ERROR_MAX)) ? err_str[err] : "unknown");
4413 msg_format("Error %d (%s) at line %d of '%s'.", err, oops, num, name);
4415 msg_format("'%s'¤ò²òÀÏÃæ¡£", buf);
4417 msg_format("Parsing '%s'.", buf);
4424 /* Close the file */
4433 void write_r_info_txt(void)
4435 int i, j, z, fc, bc;
4443 monster_race *r_ptr;
4445 monster_blow *b_ptr;
4447 FILE *fff = fopen("output.txt", "wt");
4455 fprintf(fff, "# File: r_info.txt (autogenerated)\n\n");
4457 fprintf(fff, "# Version stamp (required)\n\n");
4460 fprintf(fff, "V:%d.%d.%d\n\n\n", r_head->v_major, r_head->v_minor, r_head->v_patch);
4463 fprintf(fff, "##### The Player #####\n\n");
4465 for (z = -1; z < alloc_race_size; z++)
4467 /* Output the monsters in order */
4468 i = (z >= 0) ? alloc_race_table[z].index : 0;
4470 /* Acquire the monster */
4473 /* Ignore empty monsters */
4474 if (!strlen(r_name + r_ptr->name)) continue;
4476 /* Ignore useless monsters */
4477 if (i && !r_ptr->speed) continue;
4479 /* Write a note if necessary */
4480 if (i && (!r_ptr->level != !mode))
4485 fprintf(fff, "\n##### Town monsters #####\n\n");
4487 /* Note the dungeon */
4490 fprintf(fff, "\n##### Normal monsters #####\n\n");
4493 /* Record the change */
4494 mode = r_ptr->level;
4497 /* Acquire the flags */
4498 f_ptr[0] = r_ptr->flags1; n_ptr[0] = r_info_flags1;
4499 f_ptr[1] = r_ptr->flags2; n_ptr[1] = r_info_flags2;
4500 f_ptr[2] = r_ptr->flags3; n_ptr[2] = r_info_flags3;
4501 f_ptr[3] = r_ptr->flags4; n_ptr[3] = r_info_flags4;
4502 f_ptr[4] = r_ptr->flags5; n_ptr[4] = r_info_flags5;
4503 f_ptr[5] = r_ptr->flags6; n_ptr[5] = r_info_flags6;
4504 f_ptr[6] = r_ptr->flags7; n_ptr[6] = r_info_flags7;
4505 f_ptr[7] = r_ptr->flags8; n_ptr[7] = r_info_flags8;
4506 f_ptr[8] = r_ptr->flags9; n_ptr[8] = r_info_flags9;
4508 /* Write New/Number/Name */
4509 fprintf(fff, "N:%d:%s\n", z + 1, r_name + r_ptr->name);
4512 fprintf(fff, "G:%c:%c\n", r_ptr->d_char, color_char[r_ptr->d_attr]);
4514 /* Write Information */
4515 fprintf(fff, "I:%d:%dd%d:%d:%d:%d\n", r_ptr->speed, r_ptr->hdice, r_ptr->hside,
4516 r_ptr->aaf, r_ptr->ac, r_ptr->sleep);
4518 /* Write more information */
4519 fprintf(fff, "W:%d:%d:%d:%ld\n", r_ptr->level, r_ptr->rarity, r_ptr->extra, r_ptr->mexp);
4522 for(j = 0; j < 4; j++)
4524 b_ptr = &(r_ptr->blow[j]);
4526 /* Stop when done */
4527 if (!b_ptr->method) break;
4529 /* Write the blows */
4530 fprintf(fff, "B:%s:%s:%dd%d\n", r_info_blow_method[b_ptr->method],
4531 r_info_blow_effect[b_ptr->effect],
4532 b_ptr->d_dice, b_ptr->d_side);
4535 /* Extract the flags */
4536 for (fc = 0, j = 0; j < 96; j++)
4538 /* Check this flag */
4539 if (f_ptr[j / 32] & (1L << (j % 32))) flags[fc++] = n_ptr[j / 32][j % 32];
4542 /* Extract the extra flags */
4543 for (j = 192; j < 288; j++)
4545 /* Check this flag */
4546 if (f_ptr[j / 32] & (1L << (j % 32))) flags[fc++] = n_ptr[j / 32][j % 32];
4549 /* Write the flags */
4550 for (j = 0; j < fc;)
4554 /* Start the line */
4557 for (bc = 0; (bc < 60) && (j < fc); j++)
4561 /* Format the flag */
4562 sprintf(t, "%s%s", flags[j], (j < fc - 1) ? " | " : "");
4564 /* Add it to the buffer */
4567 /* Note the length */
4571 /* Done with this line; write it */
4572 fprintf(fff, "%s\n", buf);
4575 /* Write Spells if applicable */
4576 if (r_ptr->freq_spell)
4578 /* Write the frequency */
4579 fprintf(fff, "S:1_IN_%d | \n", 100 / r_ptr->freq_spell);
4581 /* Extract the spell flags */
4582 for (fc = 0, j = 96; j < 192; j++)
4584 /* Check this flag */
4585 if (f_ptr[j / 32] & (1L << (j % 32))) flags[fc++] = n_ptr[j / 32][j % 32];
4588 /* Write the flags */
4589 for (j = 0; j < fc;)
4593 /* Start the line */
4596 for (bc = 0, t = buf + 2; (bc < 60) && (j < fc); j++)
4600 /* Format the flag */
4601 sprintf(t, "%s%s", flags[j], (j < fc - 1) ? " | " : "");
4605 /* Note the length */
4612 /* Done with this line; write it */
4613 fprintf(fff, "%s\n", buf);
4617 /* Acquire the description */
4618 desc = r_text + r_ptr->text;
4619 dlen = strlen(desc);
4621 /* Write Description */
4622 for (j = 0; j < dlen;)
4626 /* Start the line */
4629 for (bc = 0, t = buf + 2; ((bc < 60) || !isspace(desc[j])) && (j < dlen); j++, bc++, t++)
4637 /* Done with this line; write it */
4638 fprintf(fff, "%s\n", buf);
4641 /* Space between entries */