3 /* Purpose: Initialization (part 1) -BEN- */
10 char* _strchr(char* ptr, 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 "we_info" array, by parsing an ascii "template" file
847 errr init_we_info_txt(FILE *fp, char *buf)
850 int tval = 5, sval = 0;
853 weapon_exp_table *we_ptr = NULL;
855 /* Just before the first record */
858 /* Just before the first line */
861 /* Prepare the "fake" stuff */
862 we_head->name_size = 0;
863 we_head->text_size = 0;
866 while (0 == my_fgets(fp, buf, 1024))
868 /* Advance the line number */
871 /* Skip comments and blank lines */
872 if (!buf[0] || (buf[0] == '#')) continue;
874 /* Verify correct "colon" format */
875 if (buf[1] != ':') return (1);
878 /* Hack -- Process 'V' for "Version" */
886 /* Process 'N' for "New/Number/Name" */
892 /* Verify information */
893 if (i <= error_idx) return (4);
895 /* Verify information */
896 if (tval != 5 || sval != 0) return (4);
898 /* Verify information */
899 if (i >= we_head->info_num) return (2);
904 /* Point at the "info" */
905 we_ptr = &we_info[i];
913 /* There better be a current we_ptr */
914 if (!we_ptr) return (3);
916 /* Process 'I' for "Infomation" */
920 const s16b exp_conv_table[] = { 0, 4000, 6000, 7000, 8000 };
922 /* Scan for the values */
923 if (2 != sscanf(buf+2, "%d:%d",
924 &start, &max)) return (1);
926 if (start < 0 || start > 4 || max < 0 || max > 4) return (8);
928 /* Save the values */
929 we_ptr->start[tval][sval] = exp_conv_table[start];
930 we_ptr->max[tval][sval] = exp_conv_table[max];
947 /* Complete the "name" and "text" sizes */
948 ++we_head->name_size;
949 ++we_head->text_size;
957 * Initialize the "se_info" array, by parsing an ascii "template" file
959 errr init_se_info_txt(FILE *fp, char *buf)
964 skill_exp_table *se_ptr = NULL;
966 /* Just before the first record */
969 /* Just before the first line */
972 /* Prepare the "fake" stuff */
973 se_head->name_size = 0;
974 se_head->text_size = 0;
977 while (0 == my_fgets(fp, buf, 1024))
979 /* Advance the line number */
982 /* Skip comments and blank lines */
983 if (!buf[0] || (buf[0] == '#')) continue;
985 /* Verify correct "colon" format */
986 if (buf[1] != ':') return (1);
989 /* Hack -- Process 'V' for "Version" */
997 /* Process 'N' for "New/Number/Name" */
1003 /* Verify information */
1004 if (i <= error_idx) return (4);
1006 /* Verify information */
1007 if (i >= se_head->info_num) return (2);
1009 /* Save the index */
1012 /* Point at the "info" */
1013 se_ptr = &se_info[i];
1019 /* There better be a current se_ptr */
1020 if (!se_ptr) return (3);
1022 /* Process 'I' for "Infomation" */
1025 int num, start, max;
1027 /* Scan for the values */
1028 if (3 != sscanf(buf+2, "%d:%d:%d",
1029 &num, &start, &max)) return (1);
1031 if (start < 0 || start > 8000 || max < 0 || max > 8000) return (8);
1033 /* Save the values */
1034 se_ptr->start[num] = start;
1035 se_ptr->max[num] = max;
1046 /* Complete the "name" and "text" sizes */
1047 ++se_head->name_size;
1048 ++se_head->text_size;
1057 * Initialize the "m_info" array, by parsing an ascii "template" file
1059 errr init_m_info_txt(FILE *fp, char *buf)
1066 player_magic *m_ptr = NULL;
1069 /* Just before the first record */
1072 /* Just before the first line */
1076 /* Prepare the "fake" stuff */
1077 m_head->name_size = 0;
1078 m_head->text_size = 0;
1081 while (0 == my_fgets(fp, buf, 1024))
1083 /* Advance the line number */
1086 /* Skip comments and blank lines */
1087 if (!buf[0] || (buf[0] == '#')) continue;
1089 /* Verify correct "colon" format */
1090 if (buf[1] != ':') return (1);
1093 /* Hack -- Process 'V' for "Version" */
1101 /* Process 'N' for "New/Number/Name" */
1107 /* Verify information */
1108 if (i <= error_idx) return (4);
1110 /* Verify information */
1111 if (i >= m_head->info_num) return (2);
1113 /* Save the index */
1116 /* Point at the "info" */
1123 /* There better be a current m_ptr */
1124 if (!m_ptr) return (3);
1126 /* Process 'I' for "Info" (one line only) */
1130 int xtra, type, first, weight;
1132 /* Find the colon before the name */
1133 s = strchr(buf+2, ':');
1135 /* Verify that colon */
1138 /* Nuke the colon, advance to the name */
1143 if (streq(book, "SORCERY")) m_ptr->spell_book = TV_SORCERY_BOOK;
1144 else if (streq(book, "LIFE")) m_ptr->spell_book = TV_LIFE_BOOK;
1145 else if (streq(book, "MUSIC")) m_ptr->spell_book = TV_MUSIC_BOOK;
1146 else if (streq(book, "HISSATSU")) m_ptr->spell_book = TV_HISSATSU_BOOK;
1147 else if (streq(book, "NONE")) m_ptr->spell_book = 0;
1152 /* Find the colon before the name */
1155 /* Verify that colon */
1158 /* Nuke the colon, advance to the name */
1161 if (streq(stat, "STR")) m_ptr->spell_stat = A_STR;
1162 else if (streq(stat, "INT")) m_ptr->spell_stat = A_INT;
1163 else if (streq(stat, "WIS")) m_ptr->spell_stat = A_WIS;
1164 else if (streq(stat, "DEX")) m_ptr->spell_stat = A_DEX;
1165 else if (streq(stat, "CON")) m_ptr->spell_stat = A_CON;
1166 else if (streq(stat, "CHR")) m_ptr->spell_stat = A_CHR;
1170 /* Scan for the values */
1171 if (4 != sscanf(s, "%x:%d:%d:%d",
1172 &xtra, &type, &first, &weight)) return (1);
1174 m_ptr->spell_xtra = xtra;
1175 m_ptr->spell_type = type;
1176 m_ptr->spell_first = first;
1177 m_ptr->spell_weight = weight;
1184 /* Process 'R' for "Realm" (one line only) */
1187 int realm, readable, j;
1189 /* Scan for the values */
1190 if (2 != sscanf(buf+2, "%d:%d",
1191 &realm, &readable)) return (1);
1193 if (!readable) continue;
1195 for (j = 0; j < 32; j ++)
1197 int level, mana, fail, exp;
1199 /* Advance the line number */
1202 if (0 != my_fgets(fp, buf, 1024)) return(1);
1204 if (buf[0] != 'T') return (1);
1206 /* Scan for the values */
1207 if (4 != sscanf(buf+2, "%d:%d:%d:%d",
1208 &level, &mana, &fail, &exp)) return (1);
1210 m_ptr->info[realm][j].slevel = level;
1211 m_ptr->info[realm][j].smana = mana;
1212 m_ptr->info[realm][j].sfail = fail;
1213 m_ptr->info[realm][j].sexp = exp;
1226 /* Complete the "name" and "text" sizes */
1227 ++m_head->name_size;
1228 ++m_head->text_size;
1237 * Initialize the "f_info" array, by parsing an ascii "template" file
1239 errr init_f_info_txt(FILE *fp, char *buf)
1246 feature_type *f_ptr = NULL;
1249 /* Just before the first record */
1252 /* Just before the first line */
1256 /* Prepare the "fake" stuff */
1257 f_head->name_size = 0;
1260 f_head->E_name_size = 0;
1262 f_head->text_size = 0;
1265 while (0 == my_fgets(fp, buf, 1024))
1267 /* Advance the line number */
1270 /* Skip comments and blank lines */
1271 if (!buf[0] || (buf[0] == '#')) continue;
1273 /* Verify correct "colon" format */
1274 if (buf[1] != ':') return (1);
1277 /* Hack -- Process 'V' for "Version" */
1285 /* Process 'N' for "New/Number/Name" */
1288 /* Find the colon before the name */
1289 s = strchr(buf+2, ':');
1291 /* Verify that colon */
1294 /* Nuke the colon, advance to the name */
1298 /* Paranoia -- require a name */
1299 if (!*s) return (1);
1305 /* Verify information */
1306 if (i <= error_idx) return (4);
1308 /* Verify information */
1309 if (i >= f_head->info_num) return (2);
1311 /* Save the index */
1314 /* Point at the "info" */
1318 /* Hack -- Verify space */
1319 if (f_head->name_size + strlen(s) + 8 > fake_name_size) return (7);
1321 /* Advance and Save the name index */
1322 if (!f_ptr->name) f_ptr->name = ++f_head->name_size;
1324 /* Append chars to the name */
1325 strcpy(f_name + f_head->name_size, s);
1327 /* Advance the index */
1328 f_head->name_size += strlen(s);
1330 /* Default "mimic" */
1337 /* There better be a current f_ptr */
1338 if (!f_ptr) return (3);
1341 /* ±Ñ¸ì̾¤òÆɤà¥ë¡¼¥Á¥ó¤òÄɲà */
1342 /* 'E' ¤«¤é»Ï¤Þ¤ë¹Ô¤Ï±Ñ¸ì̾¤È¤·¤Æ¤¤¤ë */
1345 /* Acquire the Text */
1348 /* Hack -- Verify space */
1349 if (f_head->E_name_size + strlen(s) + 8 > E_fake_name_size) return (7);
1351 /* Advance and Save the name index */
1352 if (!f_ptr->E_name) f_ptr->E_name = ++f_head->E_name_size;
1354 /* Append chars to the name */
1355 strcpy(E_f_name+ f_head->E_name_size, s);
1357 /* Advance the index */
1358 f_head->E_name_size += strlen(s);
1366 /* Acquire the Text */
1369 /* Hack -- Verify space */
1370 if (f_head->name_size + strlen(s) + 8 > fake_name_size) return (7);
1372 /* Advance and Save the name index */
1373 if (!f_ptr->name) f_ptr->name = ++f_head->name_size;
1375 /* Append chars to the name */
1376 strcpy(f_name+ f_head->name_size, s);
1378 /* Advance the index */
1379 f_head->name_size += strlen(s);
1388 /* Process 'D' for "Description" */
1391 /* Acquire the text */
1394 /* Hack -- Verify space */
1395 if (f_head->text_size + strlen(s) + 8 > fake_text_size) return (7);
1397 /* Advance and Save the text index */
1398 if (!f_ptr->text) f_ptr->text = ++f_head->text_size;
1400 /* Append chars to the name */
1401 strcpy(f_text + f_head->text_size, s);
1403 /* Advance the index */
1404 f_head->text_size += strlen(s);
1413 /* Process 'M' for "Mimic" (one line only) */
1418 /* Scan for the values */
1419 if (1 != sscanf(buf+2, "%d",
1420 &mimic)) return (1);
1422 /* Save the values */
1423 f_ptr->mimic = mimic;
1430 /* Process 'G' for "Graphics" (one line only) */
1436 if (!buf[2]) return (1);
1437 if (!buf[3]) return (1);
1438 if (!buf[4]) return (1);
1440 /* Extract the color */
1441 tmp = color_char_to_attr(buf[4]);
1444 if (tmp < 0) return (1);
1446 /* Save the values */
1447 f_ptr->d_attr = tmp;
1448 f_ptr->d_char = buf[2];
1460 /* Complete the "name" and "text" sizes */
1461 ++f_head->name_size;
1464 ++f_head->E_name_size;
1466 ++f_head->text_size;
1475 * Grab one flag in an object_kind from a textual string
1477 static errr grab_one_kind_flag(object_kind *k_ptr, cptr what)
1482 for (i = 0; i < 32; i++)
1484 if (streq(what, k_info_flags1[i]))
1486 k_ptr->flags1 |= (1L << i);
1492 for (i = 0; i < 32; i++)
1494 if (streq(what, k_info_flags2[i]))
1496 k_ptr->flags2 |= (1L << i);
1502 for (i = 0; i < 32; i++)
1504 if (streq(what, k_info_flags3[i]))
1506 k_ptr->flags3 |= (1L << i);
1513 msg_format("̤ÃΤΥ¢¥¤¥Æ¥à¡¦¥Õ¥é¥° '%s'¡£", what);
1515 msg_format("Unknown object flag '%s'.", what);
1525 * Initialize the "k_info" array, by parsing an ascii "template" file
1527 errr init_k_info_txt(FILE *fp, char *buf)
1534 object_kind *k_ptr = NULL;
1537 /* Just before the first record */
1540 /* Just before the first line */
1544 /* Prepare the "fake" stuff */
1545 k_head->name_size = 0;
1548 k_head->E_name_size = 0;
1550 k_head->text_size = 0;
1553 while (0 == my_fgets(fp, buf, 1024))
1555 /* Advance the line number */
1558 /* Skip comments and blank lines */
1559 if (!buf[0] || (buf[0] == '#')) continue;
1561 /* Verify correct "colon" format */
1562 if (buf[1] != ':') return (1);
1565 /* Hack -- Process 'V' for "Version" */
1573 /* Process 'N' for "New/Number/Name" */
1576 /* Find the colon before the name */
1577 s = strchr(buf+2, ':');
1579 /* Verify that colon */
1582 /* Nuke the colon, advance to the name */
1586 /* Paranoia -- require a name */
1587 if (!*s) return (1);
1592 /* Verify information */
1593 if (i <= error_idx) return (4);
1595 /* Verify information */
1596 if (i >= k_head->info_num) return (2);
1598 /* Save the index */
1601 /* Point at the "info" */
1605 /* Hack -- Verify space */
1606 if (k_head->name_size + strlen(s) + 8 > fake_name_size)
1608 fake_name_size += 1000;
1610 /* Reallocate the extra memory */
1611 k_info = realloc(k_name, fake_name_size);
1614 /* Advance and Save the name index */
1615 if (!k_ptr->name) k_ptr->name = ++k_head->name_size;
1617 /* Append chars to the name */
1618 strcpy(k_name + k_head->name_size, s);
1620 /* Advance the index */
1621 k_head->name_size += strlen(s);
1627 /* There better be a current k_ptr */
1628 if (!k_ptr) return (3);
1632 /* ±Ñ¸ì̾¤òÆɤà¥ë¡¼¥Á¥ó¤òÄɲà */
1633 /* 'E' ¤«¤é»Ï¤Þ¤ë¹Ô¤Ï±Ñ¸ì̾¤È¤·¤Æ¤¤¤ë */
1636 /* Acquire the Text */
1639 /* Hack -- Verify space */
1640 if (k_head->E_name_size + strlen(s) + 8 > E_fake_name_size) return (7);
1642 /* Advance and Save the name index */
1643 if (!k_ptr->E_name) k_ptr->E_name = ++k_head->E_name_size;
1645 /* Append chars to the name */
1646 strcpy(E_k_name+ k_head->E_name_size, s);
1648 /* Advance the index */
1649 k_head->E_name_size += strlen(s);
1657 /* Acquire the Text */
1660 /* Hack -- Verify space */
1661 if (k_head->name_size + strlen(s) + 8 > fake_name_size) return (7);
1663 /* Advance and Save the name index */
1664 if (!k_ptr->name) k_ptr->name = ++k_head->name_size;
1666 /* Append chars to the name */
1667 strcpy(k_name+ k_head->name_size, s);
1669 /* Advance the index */
1670 k_head->name_size += strlen(s);
1678 /* Process 'D' for "Description" */
1681 /* Acquire the text */
1684 /* Hack -- Verify space */
1685 if (k_head->text_size + strlen(s) + 8 > fake_text_size) return (7);
1687 /* Advance and Save the text index */
1688 if (!k_ptr->text) k_ptr->text = ++k_head->text_size;
1690 /* Append chars to the name */
1691 strcpy(k_text + k_head->text_size, s);
1693 /* Advance the index */
1694 k_head->text_size += strlen(s);
1703 /* Process 'G' for "Graphics" (one line only) */
1710 if (!buf[2]) return (1);
1711 if (!buf[3]) return (1);
1712 if (!buf[4]) return (1);
1714 /* Extract the char */
1717 /* Extract the attr */
1718 tmp = color_char_to_attr(buf[4]);
1721 if (tmp < 0) return (1);
1723 /* Save the values */
1724 k_ptr->d_attr = tmp;
1725 k_ptr->d_char = sym;
1731 /* Process 'I' for "Info" (one line only) */
1734 int tval, sval, pval;
1736 /* Scan for the values */
1737 if (3 != sscanf(buf+2, "%d:%d:%d",
1738 &tval, &sval, &pval)) return (1);
1740 /* Save the values */
1749 /* Process 'W' for "More Info" (one line only) */
1752 int level, extra, wgt;
1755 /* Scan for the values */
1756 if (4 != sscanf(buf+2, "%d:%d:%d:%ld",
1757 &level, &extra, &wgt, &cost)) return (1);
1759 /* Save the values */
1760 k_ptr->level = level;
1761 k_ptr->extra = extra;
1762 k_ptr->weight = wgt;
1769 /* Process 'A' for "Allocation" (one line only) */
1774 /* XXX XXX XXX Simply read each number following a colon */
1775 for (i = 0, s = buf+1; s && (s[0] == ':') && s[1]; ++i)
1777 /* Default chance */
1778 k_ptr->chance[i] = 1;
1780 /* Store the attack damage index */
1781 k_ptr->locale[i] = atoi(s+1);
1783 /* Find the slash */
1784 t = strchr(s+1, '/');
1786 /* Find the next colon */
1787 s = strchr(s+1, ':');
1789 /* If the slash is "nearby", use it */
1790 if (t && (!s || t < s))
1792 int chance = atoi(t+1);
1793 if (chance > 0) k_ptr->chance[i] = chance;
1801 /* Hack -- Process 'P' for "power" and such */
1804 int ac, hd1, hd2, th, td, ta;
1806 /* Scan for the values */
1807 if (6 != sscanf(buf+2, "%d:%dd%d:%d:%d:%d",
1808 &ac, &hd1, &hd2, &th, &td, &ta)) return (1);
1821 /* Hack -- Process 'F' for flags */
1824 /* Parse every entry textually */
1825 for (s = buf + 2; *s; )
1827 /* Find the end of this entry */
1828 for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
1830 /* Nuke and skip any dividers */
1834 while (*t == ' ' || *t == '|') t++;
1837 /* Parse this entry */
1838 if (0 != grab_one_kind_flag(k_ptr, s)) return (5);
1840 /* Start the next entry */
1854 /* Complete the "name" and "text" sizes */
1855 ++k_head->name_size;
1858 ++k_head->E_name_size;
1860 ++k_head->text_size;
1869 * Grab one flag in an artifact_type from a textual string
1871 static errr grab_one_artifact_flag(artifact_type *a_ptr, cptr what)
1876 for (i = 0; i < 32; i++)
1878 if (streq(what, k_info_flags1[i]))
1880 a_ptr->flags1 |= (1L << i);
1886 for (i = 0; i < 32; i++)
1888 if (streq(what, k_info_flags2[i]))
1890 a_ptr->flags2 |= (1L << i);
1896 for (i = 0; i < 32; i++)
1898 if (streq(what, k_info_flags3[i]))
1900 a_ptr->flags3 |= (1L << i);
1907 msg_format("̤ÃΤÎÅÁÀâ¤Î¥¢¥¤¥Æ¥à¡¦¥Õ¥é¥° '%s'¡£", what);
1909 msg_format("Unknown artifact flag '%s'.", what);
1921 * Initialize the "a_info" array, by parsing an ascii "template" file
1923 errr init_a_info_txt(FILE *fp, char *buf)
1930 artifact_type *a_ptr = NULL;
1933 /* Just before the first record */
1936 /* Just before the first line */
1941 while (0 == my_fgets(fp, buf, 1024))
1943 /* Advance the line number */
1946 /* Skip comments and blank lines */
1947 if (!buf[0] || (buf[0] == '#')) continue;
1949 /* Verify correct "colon" format */
1950 if (buf[1] != ':') return (1);
1953 /* Hack -- Process 'V' for "Version" */
1961 /* Process 'N' for "New/Number/Name" */
1964 /* Find the colon before the name */
1965 s = strchr(buf+2, ':');
1967 /* Verify that colon */
1970 /* Nuke the colon, advance to the name */
1973 /* Paranoia -- require a name */
1974 if (!*s) return (1);
1979 /* Verify information */
1980 if (i < error_idx) return (4);
1982 /* Verify information */
1983 if (i >= a_head->info_num) return (2);
1985 /* Save the index */
1988 /* Point at the "info" */
1991 /* Ignore everything */
1992 a_ptr->flags3 |= (TR3_IGNORE_ACID);
1993 a_ptr->flags3 |= (TR3_IGNORE_ELEC);
1994 a_ptr->flags3 |= (TR3_IGNORE_FIRE);
1995 a_ptr->flags3 |= (TR3_IGNORE_COLD);
1997 /* Hack -- Verify space */
1998 if (a_head->name_size + strlen(s) + 8 > fake_name_size) return (7);
2000 /* Advance and Save the name index */
2001 if (!a_ptr->name) a_ptr->name = ++a_head->name_size;
2003 /* Append chars to the name */
2004 strcpy(a_name + a_head->name_size, s);
2006 /* Advance the index */
2007 a_head->name_size += strlen(s);
2013 /* There better be a current a_ptr */
2014 if (!a_ptr) return (3);
2018 /* ±Ñ¸ì̾¤òÆɤà¥ë¡¼¥Á¥ó¤òÄɲà */
2019 /* 'E' ¤«¤é»Ï¤Þ¤ë¹Ô¤Ï±Ñ¸ì̾¤È¤·¤Æ¤¤¤ë */
2022 /* Acquire the Text */
2025 /* Hack -- Verify space */
2026 if (a_head->E_name_size + strlen(s) + 8 > E_fake_name_size) return (7);
2028 /* Advance and Save the name index */
2029 if (!a_ptr->E_name) a_ptr->E_name = ++a_head->E_name_size;
2031 /* Append chars to the name */
2032 strcpy(E_a_name+ a_head->E_name_size, s);
2034 /* Advance the index */
2035 a_head->E_name_size += strlen(s);
2043 /* Acquire the Text */
2046 /* Hack -- Verify space */
2047 if (a_head->name_size + strlen(s) + 8 > fake_name_size) return (7);
2049 /* Advance and Save the name index */
2050 if (!a_ptr->name) a_ptr->name = ++a_head->name_size;
2052 /* Append chars to the name */
2053 strcpy(a_name+ a_head->name_size, s);
2055 /* Advance the index */
2056 a_head->name_size += strlen(s);
2063 /* Process 'D' for "Description" */
2069 /* Acquire the text */
2074 /* Acquire the text */
2078 /* Hack -- Verify space */
2079 if (a_head->text_size + strlen(s) + 8 > fake_text_size) return (7);
2081 /* Advance and Save the text index */
2082 if (!a_ptr->text) a_ptr->text = ++a_head->text_size;
2084 /* Append chars to the name */
2085 strcpy(a_text + a_head->text_size, s);
2087 /* Advance the index */
2088 a_head->text_size += strlen(s);
2095 /* Process 'I' for "Info" (one line only) */
2098 int tval, sval, pval;
2100 /* Scan for the values */
2101 if (3 != sscanf(buf+2, "%d:%d:%d",
2102 &tval, &sval, &pval)) return (1);
2104 /* Save the values */
2113 /* Process 'W' for "More Info" (one line only) */
2116 int level, rarity, wgt;
2119 /* Scan for the values */
2120 if (4 != sscanf(buf+2, "%d:%d:%d:%ld",
2121 &level, &rarity, &wgt, &cost)) return (1);
2123 /* Save the values */
2124 a_ptr->level = level;
2125 a_ptr->rarity = rarity;
2126 a_ptr->weight = wgt;
2133 /* Hack -- Process 'P' for "power" and such */
2136 int ac, hd1, hd2, th, td, ta;
2138 /* Scan for the values */
2139 if (6 != sscanf(buf+2, "%d:%dd%d:%d:%d:%d",
2140 &ac, &hd1, &hd2, &th, &td, &ta)) return (1);
2153 /* Hack -- Process 'F' for flags */
2156 /* Parse every entry textually */
2157 for (s = buf + 2; *s; )
2159 /* Find the end of this entry */
2160 for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
2162 /* Nuke and skip any dividers */
2166 while ((*t == ' ') || (*t == '|')) t++;
2169 /* Parse this entry */
2170 if (0 != grab_one_artifact_flag(a_ptr, s)) return (5);
2172 /* Start the next entry */
2186 /* Complete the "name" and "text" sizes */
2187 ++a_head->name_size;
2190 ++a_head->E_name_size;
2192 ++a_head->text_size;
2201 * Grab one flag in a ego-item_type from a textual string
2203 static bool grab_one_ego_item_flag(ego_item_type *e_ptr, cptr what)
2208 for (i = 0; i < 32; i++)
2210 if (streq(what, k_info_flags1[i]))
2212 e_ptr->flags1 |= (1L << i);
2218 for (i = 0; i < 32; i++)
2220 if (streq(what, k_info_flags2[i]))
2222 e_ptr->flags2 |= (1L << i);
2228 for (i = 0; i < 32; i++)
2230 if (streq(what, k_info_flags3[i]))
2232 e_ptr->flags3 |= (1L << i);
2239 msg_format("̤ÃΤÎ̾¤Î¤¢¤ë¥¢¥¤¥Æ¥à¡¦¥Õ¥é¥° '%s'¡£", what);
2241 msg_format("Unknown ego-item flag '%s'.", what);
2253 * Initialize the "e_info" array, by parsing an ascii "template" file
2255 errr init_e_info_txt(FILE *fp, char *buf)
2262 ego_item_type *e_ptr = NULL;
2265 /* Just before the first record */
2268 /* Just before the first line */
2273 while (0 == my_fgets(fp, buf, 1024))
2275 /* Advance the line number */
2278 /* Skip comments and blank lines */
2279 if (!buf[0] || (buf[0] == '#')) continue;
2281 /* Verify correct "colon" format */
2282 if (buf[1] != ':') return (1);
2285 /* Hack -- Process 'V' for "Version" */
2293 /* Process 'N' for "New/Number/Name" */
2296 /* Find the colon before the name */
2297 s = strchr(buf+2, ':');
2299 /* Verify that colon */
2302 /* Nuke the colon, advance to the name */
2305 /* Paranoia -- require a name */
2306 if (!*s) return (1);
2311 /* Verify information */
2312 if (i < error_idx) return (4);
2314 /* Verify information */
2315 if (i >= e_head->info_num) return (2);
2317 /* Save the index */
2320 /* Point at the "info" */
2323 /* Hack -- Verify space */
2324 if (e_head->name_size + strlen(s) + 8 > fake_name_size) return (7);
2326 /* Advance and Save the name index */
2327 if (!e_ptr->name) e_ptr->name = ++e_head->name_size;
2329 /* Append chars to the name */
2330 strcpy(e_name + e_head->name_size, s);
2332 /* Advance the index */
2333 e_head->name_size += strlen(s);
2339 /* There better be a current e_ptr */
2340 if (!e_ptr) return (3);
2344 /* ±Ñ¸ì̾¤òÆɤà¥ë¡¼¥Á¥ó¤òÄɲà */
2345 /* 'E' ¤«¤é»Ï¤Þ¤ë¹Ô¤Ï±Ñ¸ì̾ */
2348 /* Acquire the Text */
2351 /* Hack -- Verify space */
2352 if (e_head->E_name_size + strlen(s) + 8 > E_fake_name_size) return (7);
2354 /* Advance and Save the name index */
2355 if (!e_ptr->E_name) e_ptr->E_name = ++e_head->E_name_size;
2357 /* Append chars to the name */
2358 strcpy(E_e_name+ e_head->E_name_size, s);
2360 /* Advance the index */
2361 e_head->E_name_size += strlen(s);
2369 /* Acquire the Text */
2372 /* Hack -- Verify space */
2373 if (e_head->name_size + strlen(s) + 8 > fake_name_size) return (7);
2375 /* Advance and Save the name index */
2376 if (!e_ptr->name) e_ptr->name = ++e_head->name_size;
2378 /* Append chars to the name */
2379 strcpy(e_name+ e_head->name_size, s);
2381 /* Advance the index */
2382 e_head->name_size += strlen(s);
2390 /* Process 'D' for "Description" */
2393 /* Acquire the text */
2396 /* Hack -- Verify space */
2397 if (e_head->text_size + strlen(s) + 8 > fake_text_size) return (7);
2399 /* Advance and Save the text index */
2400 if (!e_ptr->text) e_ptr->text = ++e_head->text_size;
2402 /* Append chars to the name */
2403 strcpy(e_text + e_head->text_size, s);
2405 /* Advance the index */
2406 e_head->text_size += strlen(s);
2414 /* Process 'X' for "Xtra" (one line only) */
2419 /* Scan for the values */
2420 if (2 != sscanf(buf+2, "%d:%d",
2421 &slot, &rating)) return (1);
2423 /* Save the values */
2425 e_ptr->rating = rating;
2431 /* Process 'W' for "More Info" (one line only) */
2434 int level, rarity, pad2;
2437 /* Scan for the values */
2438 if (4 != sscanf(buf+2, "%d:%d:%d:%ld",
2439 &level, &rarity, &pad2, &cost)) return (1);
2441 /* Save the values */
2442 e_ptr->level = level;
2443 e_ptr->rarity = rarity;
2444 /* e_ptr->weight = wgt; */
2451 /* Hack -- Process 'C' for "creation" */
2456 /* Scan for the values */
2457 if (4 != sscanf(buf+2, "%d:%d:%d:%d",
2458 &th, &td, &ta, &pv)) return (1);
2460 e_ptr->max_to_h = th;
2461 e_ptr->max_to_d = td;
2462 e_ptr->max_to_a = ta;
2463 e_ptr->max_pval = pv;
2469 /* Hack -- Process 'F' for flags */
2472 /* Parse every entry textually */
2473 for (s = buf + 2; *s; )
2475 /* Find the end of this entry */
2476 for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
2478 /* Nuke and skip any dividers */
2482 while ((*t == ' ') || (*t == '|')) t++;
2485 /* Parse this entry */
2486 if (0 != grab_one_ego_item_flag(e_ptr, s)) return (5);
2488 /* Start the next entry */
2501 /* Complete the "name" and "text" sizes */
2502 ++e_head->name_size;
2505 ++e_head->E_name_size;
2507 ++e_head->text_size;
2516 * Grab one (basic) flag in a monster_race from a textual string
2518 static errr grab_one_basic_flag(monster_race *r_ptr, cptr what)
2523 for (i = 0; i < 32; i++)
2525 if (streq(what, r_info_flags1[i]))
2527 r_ptr->flags1 |= (1L << i);
2533 for (i = 0; i < 32; i++)
2535 if (streq(what, r_info_flags2[i]))
2537 r_ptr->flags2 |= (1L << i);
2543 for (i = 0; i < 32; i++)
2545 if (streq(what, r_info_flags3[i]))
2547 r_ptr->flags3 |= (1L << i);
2553 for (i = 0; i < 32; i++)
2555 if (streq(what, r_info_flags7[i]))
2557 r_ptr->flags7 |= (1L << i);
2563 for (i = 0; i < 32; i++)
2565 if (streq(what, r_info_flags8[i]))
2567 r_ptr->flags8 |= (1L << i);
2573 for (i = 0; i < 32; i++)
2575 if (streq(what, r_info_flags9[i]))
2577 r_ptr->flags9 |= (1L << i);
2584 msg_format("̤ÃΤΥâ¥ó¥¹¥¿¡¼¡¦¥Õ¥é¥° '%s'¡£", what);
2586 msg_format("Unknown monster flag '%s'.", what);
2596 * Grab one (spell) flag in a monster_race from a textual string
2598 static errr grab_one_spell_flag(monster_race *r_ptr, cptr what)
2603 for (i = 0; i < 32; i++)
2605 if (streq(what, r_info_flags4[i]))
2607 r_ptr->flags4 |= (1L << i);
2613 for (i = 0; i < 32; i++)
2615 if (streq(what, r_info_flags5[i]))
2617 r_ptr->flags5 |= (1L << i);
2623 for (i = 0; i < 32; i++)
2625 if (streq(what, r_info_flags6[i]))
2627 r_ptr->flags6 |= (1L << i);
2634 msg_format("̤ÃΤΥâ¥ó¥¹¥¿¡¼¡¦¥Õ¥é¥° '%s'¡£", what);
2636 msg_format("Unknown monster flag '%s'.", what);
2648 * Initialize the "r_info" array, by parsing an ascii "template" file
2650 errr init_r_info_txt(FILE *fp, char *buf)
2657 monster_race *r_ptr = NULL;
2660 /* Just before the first record */
2663 /* Just before the first line */
2667 /* Start the "fake" stuff */
2668 r_head->name_size = 0;
2669 r_head->text_size = 0;
2672 while (0 == my_fgets(fp, buf, 1024))
2674 /* Advance the line number */
2677 /* Skip comments and blank lines */
2678 if (!buf[0] || (buf[0] == '#')) continue;
2680 /* Verify correct "colon" format */
2681 if (buf[1] != ':') return (1);
2684 /* Hack -- Process 'V' for "Version" */
2692 /* Process 'N' for "New/Number/Name" */
2695 /* Find the colon before the name */
2696 s = strchr(buf+2, ':');
2698 /* Verify that colon */
2701 /* Nuke the colon, advance to the name */
2704 /* Paranoia -- require a name */
2705 if (!*s) return (1);
2710 /* Verify information */
2711 if (i < error_idx) return (4);
2713 /* Verify information */
2714 if (i >= r_head->info_num) return (2);
2716 /* Save the index */
2719 /* Point at the "info" */
2722 /* Hack -- Verify space */
2723 if (r_head->name_size + strlen(s) + 8 > fake_name_size) return (7);
2725 /* Advance and Save the name index */
2726 if (!r_ptr->name) r_ptr->name = ++r_head->name_size;
2728 /* Append chars to the name */
2729 strcpy(r_name + r_head->name_size, s);
2731 /* Advance the index */
2732 r_head->name_size += strlen(s);
2738 /* There better be a current r_ptr */
2739 if (!r_ptr) return (3);
2743 /* ±Ñ¸ì̾¤òÆɤà¥ë¡¼¥Á¥ó¤òÄɲà */
2744 /* 'E' ¤«¤é»Ï¤Þ¤ë¹Ô¤Ï±Ñ¸ì̾ */
2747 /* Acquire the Text */
2750 /* Hack -- Verify space */
2751 if (r_head->E_name_size + strlen(s) + 8 > E_fake_name_size) return (7);
2753 /* Advance and Save the name index */
2754 if (!r_ptr->E_name) r_ptr->E_name = ++r_head->E_name_size;
2756 /* Append chars to the name */
2757 strcpy(E_r_name+ r_head->E_name_size, s);
2759 /* Advance the index */
2760 r_head->E_name_size += strlen(s);
2768 /* Acquire the Text */
2771 /* Hack -- Verify space */
2772 if (r_head->name_size + strlen(s) + 8 > fake_name_size) return (7);
2774 /* Advance and Save the name index */
2775 if (!r_ptr->name) r_ptr->name = ++r_head->name_size;
2777 /* Append chars to the name */
2778 strcpy(r_name+ r_head->name_size, s);
2780 /* Advance the index */
2781 r_head->name_size += strlen(s);
2787 /* Process 'D' for "Description" */
2793 /* Acquire the text */
2798 /* Acquire the text */
2802 /* Hack -- Verify space */
2803 if (r_head->text_size + strlen(s) + 8 > fake_text_size) return (7);
2805 /* Advance and Save the text index */
2806 if (!r_ptr->text) r_ptr->text = ++r_head->text_size;
2808 /* Append chars to the name */
2809 strcpy(r_text + r_head->text_size, s);
2811 /* Advance the index */
2812 r_head->text_size += strlen(s);
2818 /* Process 'G' for "Graphics" (one line only) */
2825 if (!buf[2]) return (1);
2826 if (!buf[3]) return (1);
2827 if (!buf[4]) return (1);
2829 /* Extract the char */
2832 /* Extract the attr */
2833 tmp = color_char_to_attr(buf[4]);
2836 if (tmp < 0) return (1);
2838 /* Save the values */
2839 r_ptr->d_char = sym;
2840 r_ptr->d_attr = tmp;
2846 /* Process 'I' for "Info" (one line only) */
2849 int spd, hp1, hp2, aaf, ac, slp;
2851 /* Scan for the other values */
2852 if (6 != sscanf(buf+2, "%d:%dd%d:%d:%d:%d",
2853 &spd, &hp1, &hp2, &aaf, &ac, &slp)) return (1);
2855 /* Save the values */
2867 /* Process 'W' for "More Info" (one line only) */
2875 /* Scan for the values */
2876 if (6 != sscanf(buf+2, "%d:%d:%d:%ld:%ld:%d",
2877 &lev, &rar, &pad, &exp, &nextexp, &nextmon)) return (1);
2879 /* Save the values */
2881 r_ptr->rarity = rar;
2884 r_ptr->next_exp = nextexp;
2885 r_ptr->next_r_idx = nextmon;
2891 /* Process 'B' for "Blows" (up to four lines) */
2896 /* Find the next empty blow slot (if any) */
2897 for (i = 0; i < 4; i++) if (!r_ptr->blow[i].method) break;
2899 /* Oops, no more slots */
2900 if (i == 4) return (1);
2902 /* Analyze the first field */
2903 for (s = t = buf+2; *t && (*t != ':'); t++) /* loop */;
2905 /* Terminate the field (if necessary) */
2906 if (*t == ':') *t++ = '\0';
2908 /* Analyze the method */
2909 for (n1 = 0; r_info_blow_method[n1]; n1++)
2911 if (streq(s, r_info_blow_method[n1])) break;
2914 /* Invalid method */
2915 if (!r_info_blow_method[n1]) return (1);
2917 /* Analyze the second field */
2918 for (s = t; *t && (*t != ':'); t++) /* loop */;
2920 /* Terminate the field (if necessary) */
2921 if (*t == ':') *t++ = '\0';
2923 /* Analyze effect */
2924 for (n2 = 0; r_info_blow_effect[n2]; n2++)
2926 if (streq(s, r_info_blow_effect[n2])) break;
2929 /* Invalid effect */
2930 if (!r_info_blow_effect[n2]) return (1);
2932 /* Analyze the third field */
2933 for (s = t; *t && (*t != 'd'); t++) /* loop */;
2935 /* Terminate the field (if necessary) */
2936 if (*t == 'd') *t++ = '\0';
2938 /* Save the method */
2939 r_ptr->blow[i].method = n1;
2941 /* Save the effect */
2942 r_ptr->blow[i].effect = n2;
2944 /* Extract the damage dice and sides */
2945 r_ptr->blow[i].d_dice = atoi(s);
2946 r_ptr->blow[i].d_side = atoi(t);
2952 /* Process 'F' for "Basic Flags" (multiple lines) */
2955 /* Parse every entry */
2956 for (s = buf + 2; *s; )
2958 /* Find the end of this entry */
2959 for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
2961 /* Nuke and skip any dividers */
2965 while (*t == ' ' || *t == '|') t++;
2968 /* Parse this entry */
2969 if (0 != grab_one_basic_flag(r_ptr, s)) return (5);
2971 /* Start the next entry */
2979 /* Process 'S' for "Spell Flags" (multiple lines) */
2982 /* Parse every entry */
2983 for (s = buf + 2; *s; )
2985 /* Find the end of this entry */
2986 for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
2988 /* Nuke and skip any dividers */
2992 while ((*t == ' ') || (*t == '|')) t++;
2995 /* XXX XXX XXX Hack -- Read spell frequency */
2996 if (1 == sscanf(s, "1_IN_%d", &i))
2998 /* Extract a "frequency" */
2999 r_ptr->freq_spell = r_ptr->freq_inate = 100 / i;
3001 /* Start at next entry */
3008 /* Parse this entry */
3009 if (0 != grab_one_spell_flag(r_ptr, s)) return (5);
3011 /* Start the next entry */
3024 /* Complete the "name" and "text" sizes */
3025 ++r_head->name_size;
3028 ++r_head->E_name_size;
3030 ++r_head->text_size;
3033 for (i = 1; i < max_r_idx; i++)
3035 /* Invert flag WILD_ONLY <-> RF8_DUNGEON */
3036 r_info[i].flags8 ^= 1L;
3038 /* WILD_TOO without any other wilderness flags enables all flags */
3039 if ((r_info[i].flags8 & RF8_WILD_TOO) && !(r_info[i].flags8 & 0x7FFFFFFE))
3040 r_info[i].flags8 = 0x0463;
3049 * Grab one flag for a dungeon type from a textual string
3051 static errr grab_one_dungeon_flag(dungeon_info_type *d_ptr, cptr what)
3056 for (i = 0; i < 32; i++)
3058 if (streq(what, d_info_flags1[i]))
3060 d_ptr->flags1 |= (1L << i);
3067 msg_format("̤ÃΤΥÀ¥ó¥¸¥ç¥ó¡¦¥Õ¥é¥° '%s'¡£", what);
3069 msg_format("Unknown dungeon type flag '%s'.", what);
3077 * Grab one (basic) flag in a monster_race from a textual string
3079 static errr grab_one_basic_monster_flag(dungeon_info_type *d_ptr, cptr what)
3084 for (i = 0; i < 32; i++)
3086 if (streq(what, r_info_flags1[i]))
3088 d_ptr->mflags1 |= (1L << i);
3094 for (i = 0; i < 32; i++)
3096 if (streq(what, r_info_flags2[i]))
3098 d_ptr->mflags2 |= (1L << i);
3104 for (i = 0; i < 32; i++)
3106 if (streq(what, r_info_flags3[i]))
3108 d_ptr->mflags3 |= (1L << i);
3114 for (i = 0; i < 32; i++)
3116 if (streq(what, r_info_flags7[i]))
3118 d_ptr->mflags7 |= (1L << i);
3124 for (i = 0; i < 32; i++)
3126 if (streq(what, r_info_flags8[i]))
3128 d_ptr->mflags8 |= (1L << i);
3134 for (i = 0; i < 32; i++)
3136 if (streq(what, r_info_flags9[i]))
3138 d_ptr->mflags9 |= (1L << i);
3145 msg_format("̤ÃΤΥâ¥ó¥¹¥¿¡¼¡¦¥Õ¥é¥° '%s'¡£", what);
3147 msg_format("Unknown monster flag '%s'.", what);
3155 * Grab one (spell) flag in a monster_race from a textual string
3157 static errr grab_one_spell_monster_flag(dungeon_info_type *d_ptr, cptr what)
3162 for (i = 0; i < 32; i++)
3164 if (streq(what, r_info_flags4[i]))
3166 d_ptr->mflags4 |= (1L << i);
3172 for (i = 0; i < 32; i++)
3174 if (streq(what, r_info_flags5[i]))
3176 d_ptr->mflags5 |= (1L << i);
3182 for (i = 0; i < 32; i++)
3184 if (streq(what, r_info_flags6[i]))
3186 d_ptr->mflags6 |= (1L << i);
3193 msg_format("̤ÃΤΥâ¥ó¥¹¥¿¡¼¡¦¥Õ¥é¥° '%s'¡£", what);
3195 msg_format("Unknown monster flag '%s'.", what);
3203 * Initialize the "d_info" array, by parsing an ascii "template" file
3205 errr init_d_info_txt(FILE *fp, char *buf)
3212 dungeon_info_type *d_ptr = NULL;
3215 /* Just before the first record */
3218 /* Just before the first line */
3222 /* Start the "fake" stuff */
3223 d_head->name_size = 0;
3224 d_head->text_size = 0;
3227 while (0 == my_fgets(fp, buf, 1024))
3229 /* Advance the line number */
3232 /* Skip comments and blank lines */
3233 if (!buf[0] || (buf[0] == '#')) continue;
3235 /* Verify correct "colon" format */
3236 if (buf[1] != ':') return (1);
3239 /* Hack -- Process 'V' for "Version" */
3246 /* Process 'N' for "New/Number/Name" */
3249 /* Find the colon before the name */
3250 s = strchr(buf+2, ':');
3252 /* Verify that colon */
3255 /* Nuke the colon, advance to the name */
3258 /* Paranoia -- require a name */
3259 if (!*s) return (1);
3264 /* Verify information */
3265 if (i < error_idx) return (4);
3267 /* Verify information */
3268 if (i >= d_head->info_num) return (2);
3270 /* Save the index */
3273 /* Point at the "info" */
3276 /* Hack -- Verify space */
3277 if (d_head->name_size + strlen(s) + 8 > fake_name_size) return (7);
3279 /* Advance and Save the name index */
3280 if (!d_ptr->name) d_ptr->name = ++d_head->name_size;
3282 /* Append chars to the name */
3283 strcpy(d_name + d_head->name_size, s);
3285 /* Advance the index */
3286 d_head->name_size += strlen(s);
3298 /* Acquire the Text */
3301 /* Hack -- Verify space */
3302 if (d_head->name_size + strlen(s) + 8 > fake_name_size) return (7);
3304 /* Advance and Save the name index */
3305 if (!d_ptr->name) d_ptr->name = ++d_head->name_size;
3307 /* Append chars to the name */
3308 strcpy(d_name + d_head->name_size, s);
3310 /* Advance the index */
3311 d_head->name_size += strlen(s);
3318 /* Process 'D' for "Description */
3324 /* Acquire the text */
3329 /* Acquire the text */
3333 /* Hack -- Verify space */
3334 if (d_head->text_size + strlen(s) + 8 > fake_text_size) return (7);
3336 /* Advance and Save the text index */
3337 if (!d_ptr->text) d_ptr->text = ++d_head->text_size;
3339 /* Append chars to the name */
3340 strcpy(d_text + d_head->text_size, s);
3342 /* Advance the index */
3343 d_head->text_size += strlen(s);
3349 /* Process 'W' for "More Info" (one line only) */
3352 int min_lev, max_lev;
3354 int min_alloc, max_chance;
3355 int obj_good, obj_great;
3358 /* Scan for the values */
3359 if (10 != sscanf(buf+2, "%d:%d:%d:%d:%d:%d:%d:%d:%x:%x",
3360 &min_lev, &max_lev, &min_plev, &mode, &min_alloc, &max_chance, &obj_good, &obj_great, (unsigned int *)&pit, (unsigned int *)&nest)) return (1);
3362 /* Save the values */
3363 d_ptr->mindepth = min_lev;
3364 d_ptr->maxdepth = max_lev;
3365 d_ptr->min_plev = min_plev;
3367 d_ptr->min_m_alloc_level = min_alloc;
3368 d_ptr->max_m_alloc_chance = max_chance;
3369 d_ptr->obj_good = obj_good;
3370 d_ptr->obj_great = obj_great;
3378 /* Process 'P' for "Place Info" */
3383 /* Scan for the values */
3384 if (2 != sscanf(buf+2, "%d:%d", &dy, &dx)) return (1);
3386 /* Save the values */
3394 /* Process 'L' for "fLoor type" (one line only) */
3401 /* Scan for the values */
3402 if (7 != sscanf(buf+2, "%d:%d:%d:%d:%d:%d:%d",
3403 &f1, &p1, &f2, &p2, &f3, &p3, &tunnel)) return (1);
3405 /* Save the values */
3407 d_ptr->floor_percent1 = p1;
3409 d_ptr->floor_percent2 = p2;
3411 d_ptr->floor_percent3 = p3;
3412 d_ptr->tunnel_percent = tunnel;
3418 /* Process 'A' for "wAll type" (one line only) */
3421 int w1, w2, w3, outer, inner, stream1, stream2;
3424 /* Scan for the values */
3425 if (10 != sscanf(buf+2, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
3426 &w1, &p1, &w2, &p2, &w3, &p3, &outer, &inner, &stream1, &stream2)) return (1);
3428 /* Save the values */
3429 d_ptr->fill_type1 = w1;
3430 d_ptr->fill_percent1 = p1;
3431 d_ptr->fill_type2 = w2;
3432 d_ptr->fill_percent2 = p2;
3433 d_ptr->fill_type3 = w3;
3434 d_ptr->fill_percent3 = p3;
3435 d_ptr->outer_wall = outer;
3436 d_ptr->inner_wall = inner;
3437 d_ptr->stream1 = stream1;
3438 d_ptr->stream2 = stream2;
3444 /* Process 'F' for "Dungeon Flags" (multiple lines) */
3447 int artif = 0, monst = 0;
3449 /* Parse every entry */
3450 for (s = buf + 2; *s; )
3452 /* Find the end of this entry */
3453 for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
3455 /* Nuke and skip any dividers */
3459 while (*t == ' ' || *t == '|') t++;
3462 /* XXX XXX XXX Hack -- Read Final Artifact */
3463 if (1 == sscanf(s, "FINAL_ARTIFACT_%d", &artif))
3465 /* Extract a "Final Artifact" */
3466 d_ptr->final_artifact = artif;
3468 /* Start at next entry */
3475 /* XXX XXX XXX Hack -- Read Final Object */
3476 if (1 == sscanf(s, "FINAL_OBJECT_%d", &artif))
3478 /* Extract a "Final Artifact" */
3479 d_ptr->final_object = artif;
3481 /* Start at next entry */
3488 /* XXX XXX XXX Hack -- Read Artifact Guardian */
3489 if (1 == sscanf(s, "FINAL_GUARDIAN_%d", &monst))
3491 /* Extract a "Artifact Guardian" */
3492 d_ptr->final_guardian = monst;
3494 /* Start at next entry */
3501 /* XXX XXX XXX Hack -- Read Special Percentage */
3502 if (1 == sscanf(s, "MONSTER_DIV_%d", &monst))
3504 /* Extract a "Special %" */
3505 d_ptr->special_div = monst;
3507 /* Start at next entry */
3514 /* Parse this entry */
3515 if (0 != grab_one_dungeon_flag(d_ptr, s)) return (5);
3517 /* Start the next entry */
3525 /* Process 'M' for "Basic Flags" (multiple lines) */
3528 byte r_char_number = 0, r_char;
3530 /* Parse every entry */
3531 for (s = buf + 2; *s; )
3533 /* Find the end of this entry */
3534 for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
3536 /* Nuke and skip any dividers */
3540 while (*t == ' ' || *t == '|') t++;
3543 /* XXX XXX XXX Hack -- Read monster symbols */
3544 if (1 == sscanf(s, "R_CHAR_%c", &r_char))
3546 /* Limited to 5 races */
3547 if(r_char_number >= 5) continue;
3549 /* Extract a "frequency" */
3550 d_ptr->r_char[r_char_number++] = r_char;
3552 /* Start at next entry */
3559 /* Parse this entry */
3560 if (0 != grab_one_basic_monster_flag(d_ptr, s)) return (5);
3562 /* Start the next entry */
3570 /* Process 'S' for "Spell Flags" (multiple lines) */
3573 /* Parse every entry */
3574 for (s = buf + 2; *s; )
3576 /* Find the end of this entry */
3577 for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
3579 /* Nuke and skip any dividers */
3583 while ((*t == ' ') || (*t == '|')) t++;
3586 /* XXX XXX XXX Hack -- Read spell frequency */
3587 if (1 == sscanf(s, "1_IN_%d", &i))
3589 /* Start at next entry */
3596 /* Parse this entry */
3597 if (0 != grab_one_spell_monster_flag(d_ptr, s)) return (5);
3599 /* Start the next entry */
3611 ++d_head->text_size;
3618 #else /* ALLOW_TEMPLATES */
3624 #endif /* ALLOW_TEMPLATES */
3627 /* Random dungeon grid effects */
3628 #define RANDOM_NONE 0x00
3629 #define RANDOM_FEATURE 0x01
3630 #define RANDOM_MONSTER 0x02
3631 #define RANDOM_OBJECT 0x04
3632 #define RANDOM_EGO 0x08
3633 #define RANDOM_ARTIFACT 0x10
3634 #define RANDOM_TRAP 0x20
3637 typedef struct dungeon_grid dungeon_grid;
3641 int feature; /* Terrain feature */
3642 int monster; /* Monster */
3643 int object; /* Object */
3644 int ego; /* Ego-Item */
3645 int artifact; /* Artifact */
3646 int trap; /* Trap */
3647 int cave_info; /* Flags for CAVE_MARK, CAVE_GLOW, CAVE_ICKY, CAVE_ROOM */
3648 int special; /* Reserved for special terrain info */
3649 int random; /* Number of the random effect */
3653 static dungeon_grid letter[255];
3657 * Process "F:<letter>:<terrain>:<cave_info>:<monster>:<object>:<ego>:<artifact>:<trap>:<special>" -- info for dungeon grid
3659 static errr parse_line_feature(char *buf)
3665 if (init_flags & INIT_ONLY_BUILDINGS) return (0);
3667 /* Tokenize the line */
3668 if ((num = tokenize(buf+2, 9, zz, 0)) > 1)
3670 /* Letter to assign */
3671 int index = zz[0][0];
3673 /* Reset the info for the letter */
3674 letter[index].feature = 0;
3675 letter[index].monster = 0;
3676 letter[index].object = 0;
3677 letter[index].ego = 0;
3678 letter[index].artifact = 0;
3679 letter[index].trap = 0;
3680 letter[index].cave_info = 0;
3681 letter[index].special = 0;
3682 letter[index].random = 0;
3688 letter[index].special = atoi(zz[8]);
3692 if (zz[7][0] == '*')
3694 letter[index].random |= RANDOM_TRAP;
3699 letter[index].trap = atoi(zz[7]);
3704 letter[index].trap = atoi(zz[7]);
3709 if (zz[6][0] == '*')
3711 letter[index].random |= RANDOM_ARTIFACT;
3716 letter[index].artifact = atoi(zz[6]);
3721 letter[index].artifact = atoi(zz[6]);
3726 if (zz[5][0] == '*')
3728 letter[index].random |= RANDOM_EGO;
3733 letter[index].ego = atoi(zz[5]);
3738 letter[index].ego = atoi(zz[5]);
3743 if (zz[4][0] == '*')
3745 letter[index].random |= RANDOM_OBJECT;
3750 letter[index].object = atoi(zz[4]);
3755 letter[index].object = atoi(zz[4]);
3760 if (zz[3][0] == '*')
3762 letter[index].random |= RANDOM_MONSTER;
3766 letter[index].monster = atoi(zz[3]);
3771 letter[index].monster = atoi(zz[3]);
3776 letter[index].cave_info = atoi(zz[2]);
3780 if (zz[1][0] == '*')
3782 letter[index].random |= RANDOM_FEATURE;
3786 letter[index].feature = atoi(zz[1]);
3791 letter[index].feature = atoi(zz[1]);
3804 * Process "F:<letter>:<terrain>:<cave_info>:<monster>:<object>:<ego>:<artifact>:<trap>:<special>" -- info for dungeon grid
3806 static errr parse_line_building(char *buf)
3822 /* Get the building number */
3825 /* Find the colon after the building number */
3828 /* Verify that colon */
3831 /* Nuke the colon, advance to the sub-index */
3834 /* Paranoia -- require a sub-index */
3835 if (!*s) return (1);
3837 /* Building definition sub-index */
3840 /* Building name, owner, race */
3843 if (tokenize(s + 2, 3, zz, 0) == 3)
3845 /* Name of the building */
3846 strcpy(building[index].name, zz[0]);
3848 /* Name of the owner */
3849 strcpy(building[index].owner_name, zz[1]);
3851 /* Race of the owner */
3852 strcpy(building[index].owner_race, zz[2]);
3857 return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3860 /* Building Action */
3863 if (tokenize(s + 2, 8, zz, 0) >= 7)
3865 /* Index of the action */
3866 int action_index = atoi(zz[0]);
3868 /* Name of the action */
3869 strcpy(building[index].act_names[action_index], zz[1]);
3871 /* Cost of the action for members */
3872 building[index].member_costs[action_index] = atoi(zz[2]);
3874 /* Cost of the action for non-members */
3875 building[index].other_costs[action_index] = atoi(zz[3]);
3877 /* Letter assigned to the action */
3878 building[index].letters[action_index] = zz[4][0];
3881 building[index].actions[action_index] = atoi(zz[5]);
3883 /* Action restriction */
3884 building[index].action_restr[action_index] = atoi(zz[6]);
3889 return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3892 /* Building Classes */
3895 if (tokenize(s + 2, MAX_CLASS, zz, 0) == MAX_CLASS)
3897 for (i = 0; i < MAX_CLASS; i++)
3899 building[index].member_class[i] = atoi(zz[i]);
3905 return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3908 /* Building Races */
3911 if (tokenize(s+2, MAX_RACES, zz, 0) == MAX_RACES)
3913 for (i = 0; i < MAX_RACES; i++)
3915 building[index].member_race[i] = atoi(zz[i]);
3921 return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3924 /* Building Realms */
3927 if (tokenize(s+2, MAX_MAGIC, zz, 0) == MAX_MAGIC)
3929 for (i = 0; i < MAX_MAGIC; i++)
3931 building[index].member_realm[i+1] = atoi(zz[i]);
3937 return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3943 if (tokenize(s+2, 2, zz, 0) == 2)
3945 /* Index of the action */
3946 int action_index = atoi(zz[0]);
3948 /* Name of the action */
3949 strcpy(building[index].act_script[action_index], zz[1]);
3954 #else /* USE_SCRIPT */
3955 /* Ignore scripts */
3957 #endif /* USE_SCRIPT */
3962 return (PARSE_ERROR_UNDEFINED_DIRECTIVE);
3971 * Parse a sub-file of the "extra info"
3973 static errr process_dungeon_file_aux(char *buf, int ymin, int xmin, int ymax, int xmax, int *y, int *x)
3980 /* Skip "empty" lines */
3981 if (!buf[0]) return (0);
3983 /* Skip "blank" lines */
3984 if (isspace(buf[0])) return (0);
3987 if (buf[0] == '#') return (0);
3989 /* Require "?:*" format */
3990 if (buf[1] != ':') return (1);
3993 /* Process "%:<fname>" */
3996 /* Attempt to Process the given file */
3997 return (process_dungeon_file(buf + 2, ymin, xmin, ymax, xmax));
4000 /* Process "F:<letter>:<terrain>:<cave_info>:<monster>:<object>:<ego>:<artifact>:<trap>:<special>" -- info for dungeon grid */
4003 return parse_line_feature(buf);
4006 /* Process "D:<dungeon>" -- info for the cave grids */
4007 else if (buf[0] == 'D')
4009 object_type object_type_body;
4011 /* Acquire the text */
4014 /* Length of the text */
4015 int len = strlen(s);
4017 if (init_flags & INIT_ONLY_BUILDINGS) return (0);
4019 for (*x = xmin, i = 0; ((*x < xmax) && (i < len)); (*x)++, s++, i++)
4021 /* Access the grid */
4022 cave_type *c_ptr = &cave[*y][*x];
4026 int object_index = letter[idx].object;
4027 int monster_index = letter[idx].monster;
4028 int random = letter[idx].random;
4029 int artifact_index = letter[idx].artifact;
4031 /* Lay down a floor */
4032 c_ptr->feat = letter[idx].feature;
4034 /* Only the features */
4035 if (init_flags & INIT_ONLY_FEATURES) continue;
4038 c_ptr->info = letter[idx].cave_info;
4040 /* Create a monster */
4041 if (random & RANDOM_MONSTER)
4043 monster_level = base_level + monster_index;
4045 place_monster(*y, *x, TRUE, TRUE);
4047 monster_level = base_level;
4049 else if (monster_index)
4051 /* Make alive again */
4052 if (r_info[monster_index].flags1 & RF1_UNIQUE)
4054 r_info[monster_index].cur_num = 0;
4055 r_info[monster_index].max_num = 1;
4058 /* Make alive again */
4059 if (r_info[monster_index].flags7 & RF7_UNIQUE_7)
4061 if (r_info[monster_index].cur_num == r_info[monster_index].max_num)
4063 r_info[monster_index].max_num++;
4068 place_monster_aux(*y, *x, monster_index, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE);
4071 /* Object (and possible trap) */
4072 if ((random & RANDOM_OBJECT) && (random & RANDOM_TRAP))
4074 object_level = base_level + object_index;
4077 * Random trap and random treasure defined
4078 * 25% chance for trap and 75% chance for object
4080 if (rand_int(100) < 75)
4082 place_object(*y, *x, FALSE, FALSE);
4089 object_level = base_level;
4091 else if (random & RANDOM_OBJECT)
4093 object_level = base_level + object_index;
4095 /* Create an out of deep object */
4096 if (rand_int(100) < 75)
4097 place_object(*y, *x, FALSE, FALSE);
4098 else if (rand_int(100) < 80)
4099 place_object(*y, *x, TRUE, FALSE);
4101 place_object(*y, *x, TRUE, TRUE);
4103 object_level = base_level;
4106 else if (random & RANDOM_TRAP)
4110 else if (object_index)
4112 /* Get local object */
4113 object_type *o_ptr = &object_type_body;
4115 /* Create the item */
4116 object_prep(o_ptr, object_index);
4118 if (o_ptr->tval == TV_GOLD)
4120 coin_type = object_index - OBJ_GOLD_LIST;
4125 /* Apply magic (no messages, no artifacts) */
4126 apply_magic(o_ptr, base_level, FALSE, TRUE, FALSE, FALSE);
4129 o_ptr->python = object_create_callback(o_ptr);
4130 #endif /* USE_SCRIPT */
4132 (void)drop_near(o_ptr, -1, *y, *x);
4138 if (a_info[artifact_index].cur_num)
4142 object_type *q_ptr = &forge;
4144 object_prep(q_ptr, k_idx);
4146 q_ptr->python = object_create_callback(q_ptr);
4147 #endif /* USE_SCRIPT */
4149 /* Drop it in the dungeon */
4150 (void)drop_near(q_ptr, -1, *y, *x);
4154 /* Create the artifact */
4155 create_named_art(artifact_index, *y, *x);
4157 a_info[artifact_index].cur_num = 1;
4161 /* Terrain special */
4162 c_ptr->special = letter[idx].special;
4170 /* Process "Q:<number>:<command>:... -- quest info */
4171 else if (buf[0] == 'Q')
4178 num = tokenize(buf + 2, 33, zz, 0);
4182 num = tokenize(buf + 3, 33, zz, 0);
4185 /* Have we enough parameters? */
4186 if (num < 3) return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
4189 q_ptr = &(quest[atoi(zz[0])]);
4191 /* Process "Q:<q_index>:Q:<type>:<num_mon>:<cur_num>:<max_num>:<level>:<r_idx>:<k_idx>:<flags>" -- quest info */
4192 if (zz[1][0] == 'Q')
4194 if (init_flags & INIT_ASSIGN)
4196 monster_race *r_ptr;
4197 artifact_type *a_ptr;
4199 if (num < 9) return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
4201 q_ptr->type = atoi(zz[2]);
4202 q_ptr->num_mon = atoi(zz[3]);
4203 q_ptr->cur_num = atoi(zz[4]);
4204 q_ptr->max_num = atoi(zz[5]);
4205 q_ptr->level = atoi(zz[6]);
4206 q_ptr->r_idx = atoi(zz[7]);
4207 q_ptr->k_idx = atoi(zz[8]);
4208 q_ptr->dungeon = atoi(zz[9]);
4211 q_ptr->flags = atoi(zz[10]);
4213 r_ptr = &r_info[q_ptr->r_idx];
4214 if (r_ptr->flags1 & RF1_UNIQUE)
4215 r_ptr->flags1 |= RF1_QUESTOR;
4217 a_ptr = &a_info[q_ptr->k_idx];
4218 a_ptr->flags3 |= TR3_QUESTITEM;
4223 /* Process "Q:<q_index>:N:<name>" -- quest name */
4224 else if (zz[1][0] == 'N')
4226 if (init_flags & (INIT_ASSIGN | INIT_SHOW_TEXT))
4228 strcpy(q_ptr->name, zz[2]);
4234 /* Process "Q:<q_index>:T:<text>" -- quest description line */
4235 else if (zz[1][0] == 'T')
4237 if (init_flags & INIT_SHOW_TEXT)
4239 strcpy(quest_text[quest_text_line], zz[2]);
4247 /* Process "W:<command>: ..." -- info for the wilderness */
4248 else if (buf[0] == 'W')
4250 return parse_line_wilderness(buf, ymin, xmin, ymax, xmax, y, x);
4253 /* Process "P:<y>:<x>" -- player position */
4254 else if (buf[0] == 'P')
4256 if (init_flags & INIT_CREATE_DUNGEON)
4258 if (tokenize(buf + 2, 2, zz, 0) == 2)
4260 int panels_x, panels_y;
4262 /* Hack - Set the dungeon size */
4263 panels_y = (*y / SCREEN_HGT);
4264 if (*y % SCREEN_HGT) panels_y++;
4265 cur_hgt = panels_y * SCREEN_HGT;
4267 panels_x = (*x / SCREEN_WID);
4268 if (*x % SCREEN_WID) panels_x++;
4269 cur_wid = panels_x * SCREEN_WID;
4271 /* Choose a panel row */
4272 max_panel_rows = (cur_hgt / SCREEN_HGT) * 2 - 2;
4273 if (max_panel_rows < 0) max_panel_rows = 0;
4275 /* Choose a panel col */
4276 max_panel_cols = (cur_wid / SCREEN_WID) * 2 - 2;
4277 if (max_panel_cols < 0) max_panel_cols = 0;
4279 /* Assume illegal panel */
4280 panel_row = max_panel_rows;
4281 panel_col = max_panel_cols;
4283 /* Place player in a quest level */
4284 if (p_ptr->inside_quest)
4288 /* Delete the monster (if any) */
4289 delete_monster(py, px);
4297 /* Place player in the town */
4298 else if (!p_ptr->oldpx && !p_ptr->oldpy)
4300 p_ptr->oldpy = atoi(zz[0]);
4301 p_ptr->oldpx = atoi(zz[1]);
4309 /* Process "B:<Index>:<Command>:..." -- Building definition */
4310 else if (buf[0] == 'B')
4312 return parse_line_building(buf);
4315 /* Process "M:<type>:<maximum>" -- set maximum values */
4316 else if (buf[0] == 'M')
4318 if (tokenize(buf+2, 2, zz, 0) == 2)
4321 if (zz[0][0] == 'T')
4323 max_towns = atoi(zz[1]);
4326 /* Maximum quests */
4327 else if (zz[0][0] == 'Q')
4329 max_quests = atoi(zz[1]);
4333 else if (zz[0][0] == 'R')
4335 max_r_idx = atoi(zz[1]);
4339 else if (zz[0][0] == 'K')
4341 max_k_idx = atoi(zz[1]);
4345 else if (zz[0][0] == 'V')
4347 max_v_idx = atoi(zz[1]);
4351 else if (zz[0][0] == 'F')
4353 max_f_idx = atoi(zz[1]);
4357 else if (zz[0][0] == 'A')
4359 max_a_idx = atoi(zz[1]);
4363 else if (zz[0][0] == 'E')
4365 max_e_idx = atoi(zz[1]);
4369 else if (zz[0][0] == 'D')
4371 max_d_idx = atoi(zz[1]);
4375 else if (zz[0][0] == 'O')
4377 max_o_idx = atoi(zz[1]);
4381 else if (zz[0][0] == 'M')
4383 max_m_idx = atoi(zz[1]);
4386 /* Wilderness size */
4387 else if (zz[0][0] == 'W')
4389 /* Maximum wild_x_size */
4390 if (zz[0][1] == 'X')
4391 max_wild_x = atoi(zz[1]);
4392 /* Maximum wild_y_size */
4393 if (zz[0][1] == 'Y')
4394 max_wild_y = atoi(zz[1]);
4408 static cptr variant = "ZANGBAND";
4412 * Helper function for "process_dungeon_file()"
4414 static cptr process_dungeon_file_expr(char **sp, char *fp)
4430 while (isspace(*s)) s++;
4448 t = process_dungeon_file_expr(&s, &f);
4457 else if (streq(t, "IOR"))
4460 while (*s && (f != b2))
4462 t = process_dungeon_file_expr(&s, &f);
4463 if (*t && !streq(t, "0")) v = "1";
4468 else if (streq(t, "AND"))
4471 while (*s && (f != b2))
4473 t = process_dungeon_file_expr(&s, &f);
4474 if (*t && streq(t, "0")) v = "0";
4479 else if (streq(t, "NOT"))
4482 while (*s && (f != b2))
4484 t = process_dungeon_file_expr(&s, &f);
4485 if (*t && streq(t, "1")) v = "0";
4490 else if (streq(t, "EQU"))
4493 if (*s && (f != b2))
4495 t = process_dungeon_file_expr(&s, &f);
4497 while (*s && (f != b2))
4500 t = process_dungeon_file_expr(&s, &f);
4501 if (*t && !streq(p, t)) v = "0";
4506 else if (streq(t, "LEQ"))
4509 if (*s && (f != b2))
4511 t = process_dungeon_file_expr(&s, &f);
4513 while (*s && (f != b2))
4516 t = process_dungeon_file_expr(&s, &f);
4517 if (*t && (strcmp(p, t) > 0)) v = "0";
4522 else if (streq(t, "GEQ"))
4525 if (*s && (f != b2))
4527 t = process_dungeon_file_expr(&s, &f);
4529 while (*s && (f != b2))
4532 t = process_dungeon_file_expr(&s, &f);
4533 if (*t && (strcmp(p, t) < 0)) v = "0";
4540 while (*s && (f != b2))
4542 t = process_dungeon_file_expr(&s, &f);
4547 if (f != b2) v = "?x?x?";
4549 /* Extract final and Terminate */
4550 if ((f = *s) != '\0') *s++ = '\0';
4556 /* Accept all printables except spaces and brackets */
4557 while (isprint(*s) && !strchr(" []", *s)) ++s;
4559 /* Extract final and Terminate */
4560 if ((f = *s) != '\0') *s++ = '\0';
4566 if (streq(b+1, "SYS"))
4572 else if (streq(b+1, "GRAF"))
4577 else if (streq(b+1, "MONOCHROME"))
4586 else if (streq(b+1, "RACE"))
4589 v = rp_ptr->E_title;
4596 else if (streq(b+1, "CLASS"))
4599 v = cp_ptr->E_title;
4606 else if (streq(b+1, "REALM1"))
4609 v = E_realm_names[p_ptr->realm1];
4611 v = realm_names[p_ptr->realm1];
4616 else if (streq(b+1, "REALM2"))
4619 v = E_realm_names[p_ptr->realm2];
4621 v = realm_names[p_ptr->realm2];
4626 else if (streq(b+1, "PLAYER"))
4632 else if (streq(b+1, "TOWN"))
4634 sprintf(tmp, "%d", p_ptr->town_num);
4639 else if (streq(b+1, "LEVEL"))
4641 sprintf(tmp, "%d", p_ptr->lev);
4645 /* Current quest number */
4646 else if (streq(b+1, "QUEST_NUMBER"))
4648 sprintf(tmp, "%d", p_ptr->inside_quest);
4652 /* Number of last quest */
4653 else if (streq(b+1, "LEAVING_QUEST"))
4655 sprintf(tmp, "%d", leaving_quest);
4660 else if (prefix(b+1, "QUEST"))
4662 /* "QUEST" uses a special parameter to determine the number of the quest */
4663 sprintf(tmp, "%d", quest[atoi(b+6)].status);
4668 else if (prefix(b+1, "RANDOM"))
4670 /* "RANDOM" uses a special parameter to determine the number of the quest */
4671 sprintf(tmp, "%d", (int)(seed_town%atoi(b+7)));
4676 else if (streq(b+1, "VARIANT"))
4682 else if (streq(b+1, "WILDERNESS"))
4685 sprintf(tmp, "NONE");
4687 sprintf(tmp, "LITE");
4689 sprintf(tmp, "NORMAL");
4712 errr process_dungeon_file(cptr name, int ymin, int xmin, int ymax, int xmax)
4722 bool bypass = FALSE;
4724 int x = xmin, y = ymin;
4727 /* Build the filename */
4728 path_build(buf, 1024, ANGBAND_DIR_EDIT, name);
4731 fp = my_fopen(buf, "r");
4734 if (!fp) return (-1);
4737 /* Process the file */
4738 while (0 == my_fgets(fp, buf, 1024))
4744 /* Skip "empty" lines */
4745 if (!buf[0]) continue;
4747 /* Skip "blank" lines */
4748 if (isspace(buf[0])) continue;
4751 if (buf[0] == '#') continue;
4754 /* Process "?:<expr>" */
4755 if ((buf[0] == '?') && (buf[1] == ':'))
4764 /* Parse the expr */
4765 v = process_dungeon_file_expr(&s, &f);
4768 bypass = (streq(v, "0") ? TRUE : FALSE);
4774 /* Apply conditionals */
4775 if (bypass) continue;
4778 /* Process "%:<file>" */
4781 /* Process that file if allowed */
4782 (void)process_dungeon_file(buf + 2, ymin, xmin, ymax, xmax);
4789 /* Process the line */
4790 err = process_dungeon_file_aux(buf, ymin, xmin, ymax, xmax, &y, &x);
4802 oops = (((err > 0) && (err < PARSE_ERROR_MAX)) ? err_str[err] : "unknown");
4805 msg_format("Error %d (%s) at line %d of '%s'.", err, oops, num, name);
4807 msg_format("'%s'¤ò²òÀÏÃæ¡£", buf);
4809 msg_format("Parsing '%s'.", buf);
4816 /* Close the file */
4825 void write_r_info_txt(void)
4827 int i, j, z, fc, bc;
4835 monster_race *r_ptr;
4837 monster_blow *b_ptr;
4839 FILE *fff = fopen("output.txt", "wt");
4847 fprintf(fff, "# File: r_info.txt (autogenerated)\n\n");
4849 fprintf(fff, "# Version stamp (required)\n\n");
4852 fprintf(fff, "V:%d.%d.%d\n\n\n", r_head->v_major, r_head->v_minor, r_head->v_patch);
4855 fprintf(fff, "##### The Player #####\n\n");
4857 for (z = -1; z < alloc_race_size; z++)
4859 /* Output the monsters in order */
4860 i = (z >= 0) ? alloc_race_table[z].index : 0;
4862 /* Acquire the monster */
4865 /* Ignore empty monsters */
4866 if (!strlen(r_name + r_ptr->name)) continue;
4868 /* Ignore useless monsters */
4869 if (i && !r_ptr->speed) continue;
4871 /* Write a note if necessary */
4872 if (i && (!r_ptr->level != !mode))
4877 fprintf(fff, "\n##### Town monsters #####\n\n");
4879 /* Note the dungeon */
4882 fprintf(fff, "\n##### Normal monsters #####\n\n");
4885 /* Record the change */
4886 mode = r_ptr->level;
4889 /* Acquire the flags */
4890 f_ptr[0] = r_ptr->flags1; n_ptr[0] = r_info_flags1;
4891 f_ptr[1] = r_ptr->flags2; n_ptr[1] = r_info_flags2;
4892 f_ptr[2] = r_ptr->flags3; n_ptr[2] = r_info_flags3;
4893 f_ptr[3] = r_ptr->flags4; n_ptr[3] = r_info_flags4;
4894 f_ptr[4] = r_ptr->flags5; n_ptr[4] = r_info_flags5;
4895 f_ptr[5] = r_ptr->flags6; n_ptr[5] = r_info_flags6;
4896 f_ptr[6] = r_ptr->flags7; n_ptr[6] = r_info_flags7;
4897 f_ptr[7] = r_ptr->flags8; n_ptr[7] = r_info_flags8;
4898 f_ptr[8] = r_ptr->flags9; n_ptr[8] = r_info_flags9;
4900 /* Write New/Number/Name */
4901 fprintf(fff, "N:%d:%s\n", z + 1, r_name + r_ptr->name);
4904 fprintf(fff, "G:%c:%c\n", r_ptr->d_char, color_char[r_ptr->d_attr]);
4906 /* Write Information */
4907 fprintf(fff, "I:%d:%dd%d:%d:%d:%d\n", r_ptr->speed, r_ptr->hdice, r_ptr->hside,
4908 r_ptr->aaf, r_ptr->ac, r_ptr->sleep);
4910 /* Write more information */
4911 fprintf(fff, "W:%d:%d:%d:%ld\n", r_ptr->level, r_ptr->rarity, r_ptr->extra, r_ptr->mexp);
4914 for(j = 0; j < 4; j++)
4916 b_ptr = &(r_ptr->blow[j]);
4918 /* Stop when done */
4919 if (!b_ptr->method) break;
4921 /* Write the blows */
4922 fprintf(fff, "B:%s:%s:%dd%d\n", r_info_blow_method[b_ptr->method],
4923 r_info_blow_effect[b_ptr->effect],
4924 b_ptr->d_dice, b_ptr->d_side);
4927 /* Extract the flags */
4928 for (fc = 0, j = 0; j < 96; j++)
4930 /* Check this flag */
4931 if (f_ptr[j / 32] & (1L << (j % 32))) flags[fc++] = n_ptr[j / 32][j % 32];
4934 /* Extract the extra flags */
4935 for (j = 192; j < 288; j++)
4937 /* Check this flag */
4938 if (f_ptr[j / 32] & (1L << (j % 32))) flags[fc++] = n_ptr[j / 32][j % 32];
4941 /* Write the flags */
4942 for (j = 0; j < fc;)
4946 /* Start the line */
4949 for (bc = 0; (bc < 60) && (j < fc); j++)
4953 /* Format the flag */
4954 sprintf(t, "%s%s", flags[j], (j < fc - 1) ? " | " : "");
4956 /* Add it to the buffer */
4959 /* Note the length */
4963 /* Done with this line; write it */
4964 fprintf(fff, "%s\n", buf);
4967 /* Write Spells if applicable */
4968 if (r_ptr->freq_spell)
4970 /* Write the frequency */
4971 fprintf(fff, "S:1_IN_%d | \n", 100 / r_ptr->freq_spell);
4973 /* Extract the spell flags */
4974 for (fc = 0, j = 96; j < 192; j++)
4976 /* Check this flag */
4977 if (f_ptr[j / 32] & (1L << (j % 32))) flags[fc++] = n_ptr[j / 32][j % 32];
4980 /* Write the flags */
4981 for (j = 0; j < fc;)
4985 /* Start the line */
4988 for (bc = 0, t = buf + 2; (bc < 60) && (j < fc); j++)
4992 /* Format the flag */
4993 sprintf(t, "%s%s", flags[j], (j < fc - 1) ? " | " : "");
4997 /* Note the length */
5004 /* Done with this line; write it */
5005 fprintf(fff, "%s\n", buf);
5009 /* Acquire the description */
5010 desc = r_text + r_ptr->text;
5011 dlen = strlen(desc);
5013 /* Write Description */
5014 for (j = 0; j < dlen;)
5018 /* Start the line */
5021 for (bc = 0, t = buf + 2; ((bc < 60) || !isspace(desc[j])) && (j < dlen); j++, bc++, t++)
5029 /* Done with this line; write it */
5030 fprintf(fff, "%s\n", buf);
5033 /* Space between entries */