3 /* Purpose: Initialization (part 1) -BEN- */
10 static char *_strchr(const char *ptr, char ch)
12 for ( ; *ptr != '\0'; ++ptr)
14 if (*ptr == ch) return (char *)ptr;
15 if (iskanji(*ptr)) ++ptr;
20 #define strchr _strchr
23 * This file is used to initialize various variables and arrays for the
24 * Angband game. Note the use of "fd_read()" and "fd_write()" to bypass
25 * the common limitation of "read()" and "write()" to only 32767 bytes
28 * Several of the arrays for Angband are built from "template" files in
29 * the "lib/file" directory, from which quick-load binary "image" files
30 * are constructed whenever they are not present in the "lib/data"
31 * directory, or if those files become obsolete, if we are allowed.
33 * Warning -- the "ascii" file parsers use a minor hack to collect the
34 * name and text information in a single pass. Thus, the game will not
35 * be able to load any template file with more than 20K of names or 60K
36 * of text, even though technically, up to 64K should be legal.
38 * Note that if "ALLOW_TEMPLATES" is not defined, then a lot of the code
39 * in this file is compiled out, and the game will not run unless valid
40 * "binary template files" already exist in "lib/data". Thus, one can
41 * compile Angband with ALLOW_TEMPLATES defined, run once to create the
42 * "*.raw" files in "lib/data", and then quit, and recompile without
43 * defining ALLOW_TEMPLATES, which will both save 20K and prevent people
44 * from changing the ascii template files in potentially dangerous ways.
46 * The code could actually be removed and placed into a "stand-alone"
47 * program, but that feels a little silly, especially considering some
48 * of the platforms that we currently support.
51 #ifdef ALLOW_TEMPLATES
56 /*** Helper arrays for parsing ascii template files ***/
59 * Monster Blow Methods
61 static cptr r_info_blow_method[] =
94 * Monster Blow Effects
96 static cptr r_info_blow_effect[] =
139 static cptr r_info_flags1[] =
178 static cptr r_info_flags2[] =
217 static cptr r_info_flags3[] =
256 static cptr r_info_flags4[] =
295 static cptr r_info_flags5[] =
334 static cptr r_info_flags6[] =
351 "ANIM_DEAD", /* ToDo: Implement ANIM_DEAD */
374 static cptr r_info_flags7[] =
413 static cptr r_info_flags8[] =
445 "WILD_SWAMP", /* ToDo: Implement Swamp */
451 * Monster race flags - Drops
453 static cptr r_info_flags9[] =
494 static cptr k_info_flags[] =
619 static cptr k_info_gen_flags[] =
659 static cptr d_info_flags1[] =
697 * Add a text to the text-storage and store offset to it.
699 * Returns FALSE when there isn't enough space available to store
702 static bool add_text(u32b *offset, header *head, cptr buf)
704 /* Hack -- Verify space */
705 if (head->text_size + strlen(buf) + 8 > FAKE_TEXT_SIZE)
711 /* Advance and save the text index */
712 *offset = ++head->text_size;
715 /* Append chars to the text */
716 strcpy(head->text_ptr + head->text_size, buf);
718 /* Advance the index */
719 head->text_size += strlen(buf);
727 * Add a name to the name-storage and return an offset to it.
729 * Returns FALSE when there isn't enough space available to store
732 static bool add_name(u32b *offset, header *head, cptr buf)
734 /* Hack -- Verify space */
735 if (head->name_size + strlen(buf) + 8 > FAKE_NAME_SIZE)
741 /* Advance and save the name index */
742 *offset = ++head->name_size;
745 /* Append chars to the names */
746 strcpy(head->name_ptr + head->name_size, buf);
748 /* Advance the index */
749 head->name_size += strlen(buf);
757 * Convert a "color letter" into an "actual" color
758 * The colors are: dwsorgbuDWvyRGBU, as shown below
760 byte color_char_to_attr(char c)
764 case 'd': return (TERM_DARK);
765 case 'w': return (TERM_WHITE);
766 case 's': return (TERM_SLATE);
767 case 'o': return (TERM_ORANGE);
768 case 'r': return (TERM_RED);
769 case 'g': return (TERM_GREEN);
770 case 'b': return (TERM_BLUE);
771 case 'u': return (TERM_UMBER);
773 case 'D': return (TERM_L_DARK);
774 case 'W': return (TERM_L_WHITE);
775 case 'v': return (TERM_VIOLET);
776 case 'y': return (TERM_YELLOW);
777 case 'R': return (TERM_L_RED);
778 case 'G': return (TERM_L_GREEN);
779 case 'B': return (TERM_L_BLUE);
780 case 'U': return (TERM_L_UMBER);
788 /*** Initialize from ascii template files ***/
792 * Initialize an "*_info" array, by parsing an ascii "template" file
794 errr init_info_txt(FILE *fp, char *buf, header *head,
795 parse_info_txt_func parse_info_txt_line)
799 /* Just before the first record */
802 /* Just before the first line */
806 /* Prepare the "fake" stuff */
811 while (0 == my_fgets(fp, buf, sizeof(buf)))
813 /* Advance the line number */
816 /* Skip comments and blank lines */
817 if (!buf[0] || (buf[0] == '#')) continue;
819 /* Verify correct "colon" format */
820 if (buf[1] != ':') return (PARSE_ERROR_GENERIC);
823 /* Hack -- Process 'V' for "Version" */
831 if ((err = (*parse_info_txt_line)(buf, head)) != 0)
836 /* Complete the "name" and "text" sizes */
837 if (head->name_size) head->name_size++;
838 if (head->text_size) head->text_size++;
846 * Initialize the "v_info" array, by parsing an ascii "template" file
848 errr parse_v_info(char *buf, header *head)
854 static vault_type *v_ptr = NULL;
856 /* Process 'N' for "New/Number/Name" */
859 /* Find the colon before the name */
860 s = strchr(buf+2, ':');
862 /* Verify that colon */
865 /* Nuke the colon, advance to the name */
868 /* Paranoia -- require a name */
874 /* Verify information */
875 if (i <= error_idx) return (4);
877 /* Verify information */
878 if (i >= head->info_num) return (2);
883 /* Point at the "info" */
887 if (!add_name(&v_ptr->name, head, s)) return (7);
890 /* There better be a current v_ptr */
891 else if (!v_ptr) return (3);
893 /* Process 'D' for "Description" */
894 else if (buf[0] == 'D')
896 /* Acquire the text */
900 if (!add_text(&v_ptr->text, head, s)) return (7);
903 /* Process 'X' for "Extra info" (one line only) */
904 else if (buf[0] == 'X')
906 int typ, rat, hgt, wid;
908 /* Scan for the values */
909 if (4 != sscanf(buf+2, "%d:%d:%d:%d",
910 &typ, &rat, &hgt, &wid)) return (1);
912 /* Save the values */
929 * Initialize the "s_info" array, by parsing an ascii "template" file
931 errr parse_s_info(char *buf, header *head)
936 static skill_table *s_ptr = NULL;
939 /* Process 'N' for "New/Number/Name" */
945 /* Verify information */
946 if (i <= error_idx) return (4);
948 /* Verify information */
949 if (i >= head->info_num) return (2);
954 /* Point at the "info" */
958 /* There better be a current s_ptr */
959 else if (!s_ptr) return (3);
961 /* Process 'W' for "Weapon exp" */
962 else if (buf[0] == 'W')
964 int tval, sval, start, max;
965 const s16b exp_conv_table[] = { 0, 4000, 6000, 7000, 8000 };
967 /* Scan for the values */
968 if (4 != sscanf(buf+2, "%d:%d:%d:%d",
969 &tval, &sval, &start, &max)) return (1);
971 if (start < 0 || start > 4 || max < 0 || max > 4) return (8);
973 /* Save the values */
974 s_ptr->w_start[tval][sval] = exp_conv_table[start];
975 s_ptr->w_max[tval][sval] = exp_conv_table[max];
978 /* Process 'S' for "Skill exp" */
979 else if (buf[0] == 'S')
983 /* Scan for the values */
984 if (3 != sscanf(buf+2, "%d:%d:%d",
985 &num, &start, &max)) return (1);
987 if (start < 0 || start > 8000 || max < 0 || max > 8000) return (8);
989 /* Save the values */
990 s_ptr->s_start[num] = start;
991 s_ptr->s_max[num] = max;
1004 * Initialize the "m_info" array, by parsing an ascii "template" file
1006 errr parse_m_info(char *buf, header *head)
1013 static player_magic *m_ptr = NULL;
1016 static int realm, magic_idx = 0, readable = 0;
1019 /* Process 'N' for "New/Number/Name" */
1025 /* Verify information */
1026 if (i <= error_idx) return (4);
1028 /* Verify information */
1029 if (i >= head->info_num) return (2);
1031 /* Save the index */
1034 /* Point at the "info" */
1038 /* There better be a current m_ptr */
1039 else if (!m_ptr) return (3);
1041 /* Process 'I' for "Info" (one line only) */
1042 else if (buf[0] == 'I')
1045 int xtra, type, first, weight;
1047 /* Find the colon before the name */
1048 s = strchr(buf+2, ':');
1050 /* Verify that colon */
1053 /* Nuke the colon, advance to the name */
1058 if (streq(book, "SORCERY")) m_ptr->spell_book = TV_SORCERY_BOOK;
1059 else if (streq(book, "LIFE")) m_ptr->spell_book = TV_LIFE_BOOK;
1060 else if (streq(book, "MUSIC")) m_ptr->spell_book = TV_MUSIC_BOOK;
1061 else if (streq(book, "HISSATSU")) m_ptr->spell_book = TV_HISSATSU_BOOK;
1062 else if (streq(book, "NONE")) m_ptr->spell_book = 0;
1067 /* Find the colon before the name */
1070 /* Verify that colon */
1073 /* Nuke the colon, advance to the name */
1076 if (streq(stat, "STR")) m_ptr->spell_stat = A_STR;
1077 else if (streq(stat, "INT")) m_ptr->spell_stat = A_INT;
1078 else if (streq(stat, "WIS")) m_ptr->spell_stat = A_WIS;
1079 else if (streq(stat, "DEX")) m_ptr->spell_stat = A_DEX;
1080 else if (streq(stat, "CON")) m_ptr->spell_stat = A_CON;
1081 else if (streq(stat, "CHR")) m_ptr->spell_stat = A_CHR;
1085 /* Scan for the values */
1086 if (4 != sscanf(s, "%x:%d:%d:%d",
1087 (uint *)&xtra, &type, &first, &weight)) return (1);
1089 m_ptr->spell_xtra = xtra;
1090 m_ptr->spell_type = type;
1091 m_ptr->spell_first = first;
1092 m_ptr->spell_weight = weight;
1096 /* Process 'R' for "Realm" (one line only) */
1097 else if (buf[0] == 'R')
1099 /* Scan for the values */
1100 if (2 != sscanf(buf+2, "%d:%d",
1101 &realm, &readable)) return (1);
1106 else if (buf[0] == 'T')
1108 int level, mana, fail, exp;
1110 if (!readable) return (1);
1111 /* Scan for the values */
1112 if (4 != sscanf(buf+2, "%d:%d:%d:%d",
1113 &level, &mana, &fail, &exp)) return (1);
1115 m_ptr->info[realm][magic_idx].slevel = level;
1116 m_ptr->info[realm][magic_idx].smana = mana;
1117 m_ptr->info[realm][magic_idx].sfail = fail;
1118 m_ptr->info[realm][magic_idx].sexp = exp;
1132 * Initialize the "f_info" array, by parsing an ascii "template" file
1134 errr parse_f_info(char *buf, header *head)
1141 static feature_type *f_ptr = NULL;
1144 /* Process 'N' for "New/Number/Name" */
1147 /* Find the colon before the name */
1148 s = strchr(buf+2, ':');
1150 /* Verify that colon */
1153 /* Nuke the colon, advance to the name */
1157 /* Paranoia -- require a name */
1158 if (!*s) return (1);
1164 /* Verify information */
1165 if (i <= error_idx) return (4);
1167 /* Verify information */
1168 if (i >= head->info_num) return (2);
1170 /* Save the index */
1173 /* Point at the "info" */
1177 /* Store the name */
1178 if (!add_name(&f_ptr->name, head, s)) return (7);
1180 /* Default "mimic" */
1184 /* There better be a current f_ptr */
1185 else if (!f_ptr) return (3);
1188 /* ±Ñ¸ì̾¤òÆɤà¥ë¡¼¥Á¥ó¤òÄɲà */
1189 /* 'E' ¤«¤é»Ï¤Þ¤ë¹Ô¤Ï±Ñ¸ì̾¤È¤·¤Æ¤¤¤ë */
1190 else if (buf[0] == 'E')
1195 else if (buf[0] == 'E')
1197 /* Acquire the Text */
1200 /* Store the name */
1201 if (!add_name(&f_ptr->name, head, s)) return (7);
1207 /* Process 'D' for "Description" */
1208 else if (buf[0] == 'D')
1210 /* Acquire the text */
1213 /* Store the text */
1214 if (!add_text(&f_ptr->text, head, s)) return (7);
1220 /* Process 'M' for "Mimic" (one line only) */
1221 else if (buf[0] == 'M')
1225 /* Scan for the values */
1226 if (1 != sscanf(buf+2, "%d",
1227 &mimic)) return (1);
1229 /* Save the values */
1230 f_ptr->mimic = mimic;
1235 /* Process 'G' for "Graphics" (one line only) */
1236 else if (buf[0] == 'G')
1241 if (!buf[2]) return (1);
1242 if (!buf[3]) return (1);
1243 if (!buf[4]) return (1);
1245 /* Extract the color */
1246 tmp = color_char_to_attr(buf[4]);
1249 if (tmp > 127) return (1);
1251 /* Save the values */
1252 f_ptr->d_attr = tmp;
1253 f_ptr->d_char = buf[2];
1266 * Grab one flag in an object_kind from a textual string
1268 static errr grab_one_kind_flag(object_kind *k_ptr, cptr what)
1273 for (i = 0; i < TR_FLAG_MAX; i++)
1275 if (streq(what, k_info_flags[i]))
1277 add_flag(k_ptr->flags, i);
1282 /* Check gen_flags */
1283 for (i = 0; i < 32; i++)
1285 if (streq(what, k_info_gen_flags[i]))
1287 k_ptr->gen_flags |= (1L << i);
1294 msg_format("̤ÃΤΥ¢¥¤¥Æ¥à¡¦¥Õ¥é¥° '%s'¡£", what);
1296 msg_format("Unknown object flag '%s'.", what);
1306 * Initialize the "k_info" array, by parsing an ascii "template" file
1308 errr parse_k_info(char *buf, header *head)
1315 static object_kind *k_ptr = NULL;
1318 /* Process 'N' for "New/Number/Name" */
1321 /* Find the colon before the name */
1322 s = strchr(buf+2, ':');
1324 /* Verify that colon */
1327 /* Nuke the colon, advance to the name */
1331 /* Paranoia -- require a name */
1332 if (!*s) return (1);
1337 /* Verify information */
1338 if (i <= error_idx) return (4);
1340 /* Verify information */
1341 if (i >= head->info_num) return (2);
1343 /* Save the index */
1346 /* Point at the "info" */
1350 /* Store the name */
1351 if (!add_name(&k_ptr->name, head, s)) return (7);
1355 /* There better be a current k_ptr */
1356 else if (!k_ptr) return (3);
1360 /* ±Ñ¸ì̾¤òÆɤà¥ë¡¼¥Á¥ó¤òÄɲà */
1361 /* 'E' ¤«¤é»Ï¤Þ¤ë¹Ô¤Ï±Ñ¸ì̾¤È¤·¤Æ¤¤¤ë */
1362 else if (buf[0] == 'E')
1367 else if (buf[0] == 'E')
1369 /* Acquire the Text */
1372 /* Store the name */
1373 if (!add_name(&k_ptr->name, head, s)) return (7);
1377 /* Process 'D' for "Description" */
1378 else if (buf[0] == 'D')
1383 /* Acquire the text */
1388 /* Acquire the text */
1392 /* Store the text */
1393 if (!add_text(&k_ptr->text, head, s)) return (7);
1396 /* Process 'G' for "Graphics" (one line only) */
1397 else if (buf[0] == 'G')
1403 if (!buf[2]) return (1);
1404 if (!buf[3]) return (1);
1405 if (!buf[4]) return (1);
1407 /* Extract the char */
1410 /* Extract the attr */
1411 tmp = color_char_to_attr(buf[4]);
1414 if (tmp > 127) return (1);
1416 /* Save the values */
1417 k_ptr->d_attr = tmp;
1418 k_ptr->d_char = sym;
1421 /* Process 'I' for "Info" (one line only) */
1422 else if (buf[0] == 'I')
1424 int tval, sval, pval;
1426 /* Scan for the values */
1427 if (3 != sscanf(buf+2, "%d:%d:%d",
1428 &tval, &sval, &pval)) return (1);
1430 /* Save the values */
1436 /* Process 'W' for "More Info" (one line only) */
1437 else if (buf[0] == 'W')
1439 int level, extra, wgt;
1442 /* Scan for the values */
1443 if (4 != sscanf(buf+2, "%d:%d:%d:%ld",
1444 &level, &extra, &wgt, &cost)) return (1);
1446 /* Save the values */
1447 k_ptr->level = level;
1448 k_ptr->extra = extra;
1449 k_ptr->weight = wgt;
1453 /* Process 'A' for "Allocation" (one line only) */
1454 else if (buf[0] == 'A')
1458 /* XXX XXX XXX Simply read each number following a colon */
1459 for (i = 0, s = buf+1; s && (s[0] == ':') && s[1]; ++i)
1461 /* Default chance */
1462 k_ptr->chance[i] = 1;
1464 /* Store the attack damage index */
1465 k_ptr->locale[i] = atoi(s+1);
1467 /* Find the slash */
1468 t = strchr(s+1, '/');
1470 /* Find the next colon */
1471 s = strchr(s+1, ':');
1473 /* If the slash is "nearby", use it */
1474 if (t && (!s || t < s))
1476 int chance = atoi(t+1);
1477 if (chance > 0) k_ptr->chance[i] = chance;
1482 /* Hack -- Process 'P' for "power" and such */
1483 else if (buf[0] == 'P')
1485 int ac, hd1, hd2, th, td, ta;
1487 /* Scan for the values */
1488 if (6 != sscanf(buf+2, "%d:%dd%d:%d:%d:%d",
1489 &ac, &hd1, &hd2, &th, &td, &ta)) return (1);
1499 /* Hack -- Process 'F' for flags */
1500 else if (buf[0] == 'F')
1502 /* Parse every entry textually */
1503 for (s = buf + 2; *s; )
1505 /* Find the end of this entry */
1506 for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
1508 /* Nuke and skip any dividers */
1512 while (*t == ' ' || *t == '|') t++;
1515 /* Parse this entry */
1516 if (0 != grab_one_kind_flag(k_ptr, s)) return (5);
1518 /* Start the next entry */
1534 * Grab one flag in an artifact_type from a textual string
1536 static errr grab_one_artifact_flag(artifact_type *a_ptr, cptr what)
1541 for (i = 0; i < TR_FLAG_MAX; i++)
1543 if (streq(what, k_info_flags[i]))
1545 add_flag(a_ptr->flags, i);
1550 /* Check gen_flags */
1551 for (i = 0; i < 32; i++)
1553 if (streq(what, k_info_gen_flags[i]))
1555 a_ptr->gen_flags |= (1L << i);
1562 msg_format("̤ÃΤÎÅÁÀâ¤Î¥¢¥¤¥Æ¥à¡¦¥Õ¥é¥° '%s'¡£", what);
1564 msg_format("Unknown artifact flag '%s'.", what);
1576 * Initialize the "a_info" array, by parsing an ascii "template" file
1578 errr parse_a_info(char *buf, header *head)
1585 static artifact_type *a_ptr = NULL;
1588 /* Process 'N' for "New/Number/Name" */
1591 /* Find the colon before the name */
1592 s = strchr(buf+2, ':');
1594 /* Verify that colon */
1597 /* Nuke the colon, advance to the name */
1600 /* Paranoia -- require a name */
1601 if (!*s) return (1);
1606 /* Verify information */
1607 if (i < error_idx) return (4);
1609 /* Verify information */
1610 if (i >= head->info_num) return (2);
1612 /* Save the index */
1615 /* Point at the "info" */
1618 /* Ignore everything */
1619 add_flag(a_ptr->flags, TR_IGNORE_ACID);
1620 add_flag(a_ptr->flags, TR_IGNORE_ELEC);
1621 add_flag(a_ptr->flags, TR_IGNORE_FIRE);
1622 add_flag(a_ptr->flags, TR_IGNORE_COLD);
1624 /* Store the name */
1625 if (!add_name(&a_ptr->name, head, s)) return (7);
1629 /* There better be a current a_ptr */
1630 else if (!a_ptr) return (3);
1634 /* ±Ñ¸ì̾¤òÆɤà¥ë¡¼¥Á¥ó¤òÄɲà */
1635 /* 'E' ¤«¤é»Ï¤Þ¤ë¹Ô¤Ï±Ñ¸ì̾¤È¤·¤Æ¤¤¤ë */
1636 else if (buf[0] == 'E')
1641 else if (buf[0] == 'E')
1643 /* Acquire the Text */
1646 /* Store the name */
1647 if (!add_name(&a_ptr->name, head, s)) return (7);
1651 /* Process 'D' for "Description" */
1652 else if (buf[0] == 'D')
1657 /* Acquire the text */
1662 /* Acquire the text */
1666 /* Store the text */
1667 if (!add_text(&a_ptr->text, head, s)) return (7);
1671 /* Process 'I' for "Info" (one line only) */
1672 else if (buf[0] == 'I')
1674 int tval, sval, pval;
1676 /* Scan for the values */
1677 if (3 != sscanf(buf+2, "%d:%d:%d",
1678 &tval, &sval, &pval)) return (1);
1680 /* Save the values */
1686 /* Process 'W' for "More Info" (one line only) */
1687 else if (buf[0] == 'W')
1689 int level, rarity, wgt;
1692 /* Scan for the values */
1693 if (4 != sscanf(buf+2, "%d:%d:%d:%ld",
1694 &level, &rarity, &wgt, &cost)) return (1);
1696 /* Save the values */
1697 a_ptr->level = level;
1698 a_ptr->rarity = rarity;
1699 a_ptr->weight = wgt;
1703 /* Hack -- Process 'P' for "power" and such */
1704 else if (buf[0] == 'P')
1706 int ac, hd1, hd2, th, td, ta;
1708 /* Scan for the values */
1709 if (6 != sscanf(buf+2, "%d:%dd%d:%d:%d:%d",
1710 &ac, &hd1, &hd2, &th, &td, &ta)) return (1);
1720 /* Hack -- Process 'F' for flags */
1721 else if (buf[0] == 'F')
1723 /* Parse every entry textually */
1724 for (s = buf + 2; *s; )
1726 /* Find the end of this entry */
1727 for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
1729 /* Nuke and skip any dividers */
1733 while ((*t == ' ') || (*t == '|')) t++;
1736 /* Parse this entry */
1737 if (0 != grab_one_artifact_flag(a_ptr, s)) return (5);
1739 /* Start the next entry */
1755 * Grab one flag in a ego-item_type from a textual string
1757 static bool grab_one_ego_item_flag(ego_item_type *e_ptr, cptr what)
1762 for (i = 0; i < TR_FLAG_MAX; i++)
1764 if (streq(what, k_info_flags[i]))
1766 add_flag(e_ptr->flags, i);
1771 /* Check gen_flags */
1772 for (i = 0; i < 32; i++)
1774 if (streq(what, k_info_gen_flags[i]))
1776 e_ptr->gen_flags |= (1L << i);
1783 msg_format("̤ÃΤÎ̾¤Î¤¢¤ë¥¢¥¤¥Æ¥à¡¦¥Õ¥é¥° '%s'¡£", what);
1785 msg_format("Unknown ego-item flag '%s'.", what);
1797 * Initialize the "e_info" array, by parsing an ascii "template" file
1799 errr parse_e_info(char *buf, header *head)
1806 static ego_item_type *e_ptr = NULL;
1809 /* Just before the first record */
1812 /* Just before the first line */
1816 /* Process 'N' for "New/Number/Name" */
1819 /* Find the colon before the name */
1820 s = strchr(buf+2, ':');
1822 /* Verify that colon */
1825 /* Nuke the colon, advance to the name */
1828 /* Paranoia -- require a name */
1829 if (!*s) return (1);
1834 /* Verify information */
1835 if (i < error_idx) return (4);
1837 /* Verify information */
1838 if (i >= head->info_num) return (2);
1840 /* Save the index */
1843 /* Point at the "info" */
1846 /* Store the name */
1847 if (!add_name(&e_ptr->name, head, s)) return (7);
1851 /* There better be a current e_ptr */
1852 else if (!e_ptr) return (3);
1856 /* ±Ñ¸ì̾¤òÆɤà¥ë¡¼¥Á¥ó¤òÄɲà */
1857 /* 'E' ¤«¤é»Ï¤Þ¤ë¹Ô¤Ï±Ñ¸ì̾ */
1858 else if (buf[0] == 'E')
1863 else if (buf[0] == 'E')
1865 /* Acquire the Text */
1868 /* Store the name */
1869 if (!add_name(&e_ptr->name, head, s)) return (7);
1874 /* Process 'D' for "Description" */
1875 else if (buf[0] == 'D')
1877 /* Acquire the text */
1880 /* Store the text */
1881 if (!add_text(&e_ptr->text, head, s)) return (7);
1886 /* Process 'X' for "Xtra" (one line only) */
1887 else if (buf[0] == 'X')
1891 /* Scan for the values */
1892 if (2 != sscanf(buf+2, "%d:%d",
1893 &slot, &rating)) return (1);
1895 /* Save the values */
1897 e_ptr->rating = rating;
1900 /* Process 'W' for "More Info" (one line only) */
1901 else if (buf[0] == 'W')
1903 int level, rarity, pad2;
1906 /* Scan for the values */
1907 if (4 != sscanf(buf+2, "%d:%d:%d:%ld",
1908 &level, &rarity, &pad2, &cost)) return (1);
1910 /* Save the values */
1911 e_ptr->level = level;
1912 e_ptr->rarity = rarity;
1913 /* e_ptr->weight = wgt; */
1917 /* Hack -- Process 'C' for "creation" */
1918 else if (buf[0] == 'C')
1922 /* Scan for the values */
1923 if (4 != sscanf(buf+2, "%d:%d:%d:%d",
1924 &th, &td, &ta, &pv)) return (1);
1926 e_ptr->max_to_h = th;
1927 e_ptr->max_to_d = td;
1928 e_ptr->max_to_a = ta;
1929 e_ptr->max_pval = pv;
1932 /* Hack -- Process 'F' for flags */
1933 else if (buf[0] == 'F')
1935 /* Parse every entry textually */
1936 for (s = buf + 2; *s; )
1938 /* Find the end of this entry */
1939 for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
1941 /* Nuke and skip any dividers */
1945 while ((*t == ' ') || (*t == '|')) t++;
1948 /* Parse this entry */
1949 if (0 != grab_one_ego_item_flag(e_ptr, s)) return (5);
1951 /* Start the next entry */
1965 * Grab one (basic) flag in a monster_race from a textual string
1967 static errr grab_one_basic_flag(monster_race *r_ptr, cptr what)
1972 for (i = 0; i < 32; i++)
1974 if (streq(what, r_info_flags1[i]))
1976 r_ptr->flags1 |= (1L << i);
1982 for (i = 0; i < 32; i++)
1984 if (streq(what, r_info_flags2[i]))
1986 r_ptr->flags2 |= (1L << i);
1992 for (i = 0; i < 32; i++)
1994 if (streq(what, r_info_flags3[i]))
1996 r_ptr->flags3 |= (1L << i);
2002 for (i = 0; i < 32; i++)
2004 if (streq(what, r_info_flags7[i]))
2006 r_ptr->flags7 |= (1L << i);
2012 for (i = 0; i < 32; i++)
2014 if (streq(what, r_info_flags8[i]))
2016 r_ptr->flags8 |= (1L << i);
2022 for (i = 0; i < 32; i++)
2024 if (streq(what, r_info_flags9[i]))
2026 r_ptr->flags9 |= (1L << i);
2033 msg_format("̤ÃΤΥâ¥ó¥¹¥¿¡¼¡¦¥Õ¥é¥° '%s'¡£", what);
2035 msg_format("Unknown monster flag '%s'.", what);
2045 * Grab one (spell) flag in a monster_race from a textual string
2047 static errr grab_one_spell_flag(monster_race *r_ptr, cptr what)
2052 for (i = 0; i < 32; i++)
2054 if (streq(what, r_info_flags4[i]))
2056 r_ptr->flags4 |= (1L << i);
2062 for (i = 0; i < 32; i++)
2064 if (streq(what, r_info_flags5[i]))
2066 r_ptr->flags5 |= (1L << i);
2072 for (i = 0; i < 32; i++)
2074 if (streq(what, r_info_flags6[i]))
2076 r_ptr->flags6 |= (1L << i);
2083 msg_format("̤ÃΤΥâ¥ó¥¹¥¿¡¼¡¦¥Õ¥é¥° '%s'¡£", what);
2085 msg_format("Unknown monster flag '%s'.", what);
2097 * Initialize the "r_info" array, by parsing an ascii "template" file
2099 errr parse_r_info(char *buf, header *head)
2106 static monster_race *r_ptr = NULL;
2109 /* Process 'N' for "New/Number/Name" */
2112 /* Find the colon before the name */
2113 s = strchr(buf+2, ':');
2115 /* Verify that colon */
2118 /* Nuke the colon, advance to the name */
2121 /* Paranoia -- require a name */
2122 if (!*s) return (1);
2127 /* Verify information */
2128 if (i < error_idx) return (4);
2130 /* Verify information */
2131 if (i >= head->info_num) return (2);
2133 /* Save the index */
2136 /* Point at the "info" */
2139 /* Store the name */
2140 if (!add_name(&r_ptr->name, head, s)) return (7);
2144 /* There better be a current r_ptr */
2145 else if (!r_ptr) return (3);
2149 /* ±Ñ¸ì̾¤òÆɤà¥ë¡¼¥Á¥ó¤òÄɲà */
2150 /* 'E' ¤«¤é»Ï¤Þ¤ë¹Ô¤Ï±Ñ¸ì̾ */
2151 else if (buf[0] == 'E')
2153 /* Acquire the Text */
2156 /* Store the name */
2157 if (!add_name(&r_ptr->E_name, head, s)) return (7);
2160 else if (buf[0] == 'E')
2162 /* Acquire the Text */
2165 /* Store the name */
2166 if (!add_name(&r_ptr->name, head, s)) return (7);
2169 /* Process 'D' for "Description" */
2170 else if (buf[0] == 'D')
2175 /* Acquire the text */
2180 /* Acquire the text */
2184 /* Store the text */
2185 if (!add_text(&r_ptr->text, head, s)) return (7);
2188 /* Process 'G' for "Graphics" (one line only) */
2189 else if (buf[0] == 'G')
2195 if (!buf[2]) return (1);
2196 if (!buf[3]) return (1);
2197 if (!buf[4]) return (1);
2199 /* Extract the char */
2202 /* Extract the attr */
2203 tmp = color_char_to_attr(buf[4]);
2206 if (tmp > 127) return (1);
2208 /* Save the values */
2209 r_ptr->d_char = sym;
2210 r_ptr->d_attr = tmp;
2213 /* Process 'I' for "Info" (one line only) */
2214 else if (buf[0] == 'I')
2216 int spd, hp1, hp2, aaf, ac, slp;
2218 /* Scan for the other values */
2219 if (6 != sscanf(buf+2, "%d:%dd%d:%d:%d:%d",
2220 &spd, &hp1, &hp2, &aaf, &ac, &slp)) return (1);
2222 /* Save the values */
2231 /* Process 'W' for "More Info" (one line only) */
2232 else if (buf[0] == 'W')
2239 /* Scan for the values */
2240 if (6 != sscanf(buf+2, "%d:%d:%d:%ld:%ld:%d",
2241 &lev, &rar, &pad, &exp, &nextexp, &nextmon)) return (1);
2243 /* Save the values */
2245 r_ptr->rarity = rar;
2248 r_ptr->next_exp = nextexp;
2249 r_ptr->next_r_idx = nextmon;
2252 /* Process 'B' for "Blows" (up to four lines) */
2253 else if (buf[0] == 'B')
2257 /* Find the next empty blow slot (if any) */
2258 for (i = 0; i < 4; i++) if (!r_ptr->blow[i].method) break;
2260 /* Oops, no more slots */
2261 if (i == 4) return (1);
2263 /* Analyze the first field */
2264 for (s = t = buf+2; *t && (*t != ':'); t++) /* loop */;
2266 /* Terminate the field (if necessary) */
2267 if (*t == ':') *t++ = '\0';
2269 /* Analyze the method */
2270 for (n1 = 0; r_info_blow_method[n1]; n1++)
2272 if (streq(s, r_info_blow_method[n1])) break;
2275 /* Invalid method */
2276 if (!r_info_blow_method[n1]) return (1);
2278 /* Analyze the second field */
2279 for (s = t; *t && (*t != ':'); t++) /* loop */;
2281 /* Terminate the field (if necessary) */
2282 if (*t == ':') *t++ = '\0';
2284 /* Analyze effect */
2285 for (n2 = 0; r_info_blow_effect[n2]; n2++)
2287 if (streq(s, r_info_blow_effect[n2])) break;
2290 /* Invalid effect */
2291 if (!r_info_blow_effect[n2]) return (1);
2293 /* Analyze the third field */
2294 for (s = t; *t && (*t != 'd'); t++) /* loop */;
2296 /* Terminate the field (if necessary) */
2297 if (*t == 'd') *t++ = '\0';
2299 /* Save the method */
2300 r_ptr->blow[i].method = n1;
2302 /* Save the effect */
2303 r_ptr->blow[i].effect = n2;
2305 /* Extract the damage dice and sides */
2306 r_ptr->blow[i].d_dice = atoi(s);
2307 r_ptr->blow[i].d_side = atoi(t);
2310 /* Process 'F' for "Basic Flags" (multiple lines) */
2311 else if (buf[0] == 'F')
2313 /* Parse every entry */
2314 for (s = buf + 2; *s; )
2316 /* Find the end of this entry */
2317 for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
2319 /* Nuke and skip any dividers */
2323 while (*t == ' ' || *t == '|') t++;
2326 /* Parse this entry */
2327 if (0 != grab_one_basic_flag(r_ptr, s)) return (5);
2329 /* Start the next entry */
2334 /* Process 'S' for "Spell Flags" (multiple lines) */
2335 else if (buf[0] == 'S')
2337 /* Parse every entry */
2338 for (s = buf + 2; *s; )
2340 /* Find the end of this entry */
2341 for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
2343 /* Nuke and skip any dividers */
2347 while ((*t == ' ') || (*t == '|')) t++;
2350 /* XXX XXX XXX Hack -- Read spell frequency */
2351 if (1 == sscanf(s, "1_IN_%d", &i))
2353 /* Extract a "frequency" */
2354 r_ptr->freq_spell = r_ptr->freq_inate = 100 / i;
2356 /* Start at next entry */
2363 /* Parse this entry */
2364 if (0 != grab_one_spell_flag(r_ptr, s)) return (5);
2366 /* Start the next entry */
2381 * Grab one flag for a dungeon type from a textual string
2383 static errr grab_one_dungeon_flag(dungeon_info_type *d_ptr, cptr what)
2388 for (i = 0; i < 32; i++)
2390 if (streq(what, d_info_flags1[i]))
2392 d_ptr->flags1 |= (1L << i);
2399 msg_format("̤ÃΤΥÀ¥ó¥¸¥ç¥ó¡¦¥Õ¥é¥° '%s'¡£", what);
2401 msg_format("Unknown dungeon type flag '%s'.", what);
2409 * Grab one (basic) flag in a monster_race from a textual string
2411 static errr grab_one_basic_monster_flag(dungeon_info_type *d_ptr, cptr what)
2416 for (i = 0; i < 32; i++)
2418 if (streq(what, r_info_flags1[i]))
2420 d_ptr->mflags1 |= (1L << i);
2426 for (i = 0; i < 32; i++)
2428 if (streq(what, r_info_flags2[i]))
2430 d_ptr->mflags2 |= (1L << i);
2436 for (i = 0; i < 32; i++)
2438 if (streq(what, r_info_flags3[i]))
2440 d_ptr->mflags3 |= (1L << i);
2446 for (i = 0; i < 32; i++)
2448 if (streq(what, r_info_flags7[i]))
2450 d_ptr->mflags7 |= (1L << i);
2456 for (i = 0; i < 32; i++)
2458 if (streq(what, r_info_flags8[i]))
2460 d_ptr->mflags8 |= (1L << i);
2466 for (i = 0; i < 32; i++)
2468 if (streq(what, r_info_flags9[i]))
2470 d_ptr->mflags9 |= (1L << i);
2477 msg_format("̤ÃΤΥâ¥ó¥¹¥¿¡¼¡¦¥Õ¥é¥° '%s'¡£", what);
2479 msg_format("Unknown monster flag '%s'.", what);
2487 * Grab one (spell) flag in a monster_race from a textual string
2489 static errr grab_one_spell_monster_flag(dungeon_info_type *d_ptr, cptr what)
2494 for (i = 0; i < 32; i++)
2496 if (streq(what, r_info_flags4[i]))
2498 d_ptr->mflags4 |= (1L << i);
2504 for (i = 0; i < 32; i++)
2506 if (streq(what, r_info_flags5[i]))
2508 d_ptr->mflags5 |= (1L << i);
2514 for (i = 0; i < 32; i++)
2516 if (streq(what, r_info_flags6[i]))
2518 d_ptr->mflags6 |= (1L << i);
2525 msg_format("̤ÃΤΥâ¥ó¥¹¥¿¡¼¡¦¥Õ¥é¥° '%s'¡£", what);
2527 msg_format("Unknown monster flag '%s'.", what);
2535 * Initialize the "d_info" array, by parsing an ascii "template" file
2537 errr parse_d_info(char *buf, header *head)
2544 static dungeon_info_type *d_ptr = NULL;
2547 /* Process 'N' for "New/Number/Name" */
2550 /* Find the colon before the name */
2551 s = strchr(buf+2, ':');
2553 /* Verify that colon */
2556 /* Nuke the colon, advance to the name */
2559 /* Paranoia -- require a name */
2560 if (!*s) return (1);
2565 /* Verify information */
2566 if (i < error_idx) return (4);
2568 /* Verify information */
2569 if (i >= head->info_num) return (2);
2571 /* Save the index */
2574 /* Point at the "info" */
2577 /* Store the name */
2578 if (!add_name(&d_ptr->name, head, s)) return (7);
2583 else if (buf[0] == 'E') return (0);
2585 else if (buf[0] == 'E')
2587 /* Acquire the Text */
2590 /* Store the name */
2591 if (!add_name(&d_ptr->name, head, s)) return (7);
2595 /* Process 'D' for "Description */
2596 else if (buf[0] == 'D')
2601 /* Acquire the text */
2606 /* Acquire the text */
2610 /* Store the text */
2611 if (!add_text(&d_ptr->text, head, s)) return (7);
2614 /* Process 'W' for "More Info" (one line only) */
2615 else if (buf[0] == 'W')
2617 int min_lev, max_lev;
2619 int min_alloc, max_chance;
2620 int obj_good, obj_great;
2623 /* Scan for the values */
2624 if (10 != sscanf(buf+2, "%d:%d:%d:%d:%d:%d:%d:%d:%x:%x",
2625 &min_lev, &max_lev, &min_plev, &mode, &min_alloc, &max_chance, &obj_good, &obj_great, (unsigned int *)&pit, (unsigned int *)&nest)) return (1);
2627 /* Save the values */
2628 d_ptr->mindepth = min_lev;
2629 d_ptr->maxdepth = max_lev;
2630 d_ptr->min_plev = min_plev;
2632 d_ptr->min_m_alloc_level = min_alloc;
2633 d_ptr->max_m_alloc_chance = max_chance;
2634 d_ptr->obj_good = obj_good;
2635 d_ptr->obj_great = obj_great;
2640 /* Process 'P' for "Place Info" */
2641 else if (buf[0] == 'P')
2645 /* Scan for the values */
2646 if (2 != sscanf(buf+2, "%d:%d", &dy, &dx)) return (1);
2648 /* Save the values */
2653 /* Process 'L' for "fLoor type" (one line only) */
2654 else if (buf[0] == 'L')
2660 /* Scan for the values */
2661 if (7 != sscanf(buf+2, "%d:%d:%d:%d:%d:%d:%d",
2662 &f1, &p1, &f2, &p2, &f3, &p3, &tunnel)) return (1);
2664 /* Save the values */
2666 d_ptr->floor_percent1 = p1;
2668 d_ptr->floor_percent2 = p2;
2670 d_ptr->floor_percent3 = p3;
2671 d_ptr->tunnel_percent = tunnel;
2674 /* Process 'A' for "wAll type" (one line only) */
2675 else if (buf[0] == 'A')
2677 int w1, w2, w3, outer, inner, stream1, stream2;
2680 /* Scan for the values */
2681 if (10 != sscanf(buf+2, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
2682 &w1, &p1, &w2, &p2, &w3, &p3, &outer, &inner, &stream1, &stream2)) return (1);
2684 /* Save the values */
2685 d_ptr->fill_type1 = w1;
2686 d_ptr->fill_percent1 = p1;
2687 d_ptr->fill_type2 = w2;
2688 d_ptr->fill_percent2 = p2;
2689 d_ptr->fill_type3 = w3;
2690 d_ptr->fill_percent3 = p3;
2691 d_ptr->outer_wall = outer;
2692 d_ptr->inner_wall = inner;
2693 d_ptr->stream1 = stream1;
2694 d_ptr->stream2 = stream2;
2697 /* Process 'F' for "Dungeon Flags" (multiple lines) */
2698 else if (buf[0] == 'F')
2700 int artif = 0, monst = 0;
2702 /* Parse every entry */
2703 for (s = buf + 2; *s; )
2705 /* Find the end of this entry */
2706 for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
2708 /* Nuke and skip any dividers */
2712 while (*t == ' ' || *t == '|') t++;
2715 /* XXX XXX XXX Hack -- Read Final Artifact */
2716 if (1 == sscanf(s, "FINAL_ARTIFACT_%d", &artif))
2718 /* Extract a "Final Artifact" */
2719 d_ptr->final_artifact = artif;
2721 /* Start at next entry */
2728 /* XXX XXX XXX Hack -- Read Final Object */
2729 if (1 == sscanf(s, "FINAL_OBJECT_%d", &artif))
2731 /* Extract a "Final Artifact" */
2732 d_ptr->final_object = artif;
2734 /* Start at next entry */
2741 /* XXX XXX XXX Hack -- Read Artifact Guardian */
2742 if (1 == sscanf(s, "FINAL_GUARDIAN_%d", &monst))
2744 /* Extract a "Artifact Guardian" */
2745 d_ptr->final_guardian = monst;
2747 /* Start at next entry */
2754 /* XXX XXX XXX Hack -- Read Special Percentage */
2755 if (1 == sscanf(s, "MONSTER_DIV_%d", &monst))
2757 /* Extract a "Special %" */
2758 d_ptr->special_div = monst;
2760 /* Start at next entry */
2767 /* Parse this entry */
2768 if (0 != grab_one_dungeon_flag(d_ptr, s)) return (5);
2770 /* Start the next entry */
2775 /* Process 'M' for "Basic Flags" (multiple lines) */
2776 else if (buf[0] == 'M')
2778 byte r_char_number = 0, r_char;
2780 /* Parse every entry */
2781 for (s = buf + 2; *s; )
2783 /* Find the end of this entry */
2784 for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
2786 /* Nuke and skip any dividers */
2790 while (*t == ' ' || *t == '|') t++;
2793 /* XXX XXX XXX Hack -- Read monster symbols */
2794 if (1 == sscanf(s, "R_CHAR_%c", &r_char))
2796 /* Limited to 5 races */
2797 if(r_char_number >= 5) continue;
2799 /* Extract a "frequency" */
2800 d_ptr->r_char[r_char_number++] = r_char;
2802 /* Start at next entry */
2809 /* Parse this entry */
2810 if (0 != grab_one_basic_monster_flag(d_ptr, s)) return (5);
2812 /* Start the next entry */
2817 /* Process 'S' for "Spell Flags" (multiple lines) */
2818 else if (buf[0] == 'S')
2820 /* Parse every entry */
2821 for (s = buf + 2; *s; )
2823 /* Find the end of this entry */
2824 for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
2826 /* Nuke and skip any dividers */
2830 while ((*t == ' ') || (*t == '|')) t++;
2833 /* XXX XXX XXX Hack -- Read spell frequency */
2834 if (1 == sscanf(s, "1_IN_%d", &i))
2836 /* Start at next entry */
2843 /* Parse this entry */
2844 if (0 != grab_one_spell_monster_flag(d_ptr, s)) return (5);
2846 /* Start the next entry */
2859 #else /* ALLOW_TEMPLATES */
2865 #endif /* ALLOW_TEMPLATES */
2868 /* Random dungeon grid effects */
2869 #define RANDOM_NONE 0x00
2870 #define RANDOM_FEATURE 0x01
2871 #define RANDOM_MONSTER 0x02
2872 #define RANDOM_OBJECT 0x04
2873 #define RANDOM_EGO 0x08
2874 #define RANDOM_ARTIFACT 0x10
2875 #define RANDOM_TRAP 0x20
2878 typedef struct dungeon_grid dungeon_grid;
2882 int feature; /* Terrain feature */
2883 int monster; /* Monster */
2884 int object; /* Object */
2885 int ego; /* Ego-Item */
2886 int artifact; /* Artifact */
2887 int trap; /* Trap */
2888 int cave_info; /* Flags for CAVE_MARK, CAVE_GLOW, CAVE_ICKY, CAVE_ROOM */
2889 int special; /* Reserved for special terrain info */
2890 int random; /* Number of the random effect */
2894 static dungeon_grid letter[255];
2898 * Process "F:<letter>:<terrain>:<cave_info>:<monster>:<object>:<ego>:<artifact>:<trap>:<special>" -- info for dungeon grid
2900 static errr parse_line_feature(char *buf)
2906 if (init_flags & INIT_ONLY_BUILDINGS) return (0);
2908 /* Tokenize the line */
2909 if ((num = tokenize(buf+2, 9, zz, 0)) > 1)
2911 /* Letter to assign */
2912 int index = zz[0][0];
2914 /* Reset the info for the letter */
2915 letter[index].feature = 0;
2916 letter[index].monster = 0;
2917 letter[index].object = 0;
2918 letter[index].ego = 0;
2919 letter[index].artifact = 0;
2920 letter[index].trap = 0;
2921 letter[index].cave_info = 0;
2922 letter[index].special = 0;
2923 letter[index].random = 0;
2929 letter[index].special = atoi(zz[8]);
2933 if (zz[7][0] == '*')
2935 letter[index].random |= RANDOM_TRAP;
2940 letter[index].trap = atoi(zz[7]);
2945 letter[index].trap = atoi(zz[7]);
2950 if (zz[6][0] == '*')
2952 letter[index].random |= RANDOM_ARTIFACT;
2957 letter[index].artifact = atoi(zz[6]);
2962 letter[index].artifact = atoi(zz[6]);
2967 if (zz[5][0] == '*')
2969 letter[index].random |= RANDOM_EGO;
2974 letter[index].ego = atoi(zz[5]);
2979 letter[index].ego = atoi(zz[5]);
2984 if (zz[4][0] == '*')
2986 letter[index].random |= RANDOM_OBJECT;
2991 letter[index].object = atoi(zz[4]);
2996 letter[index].object = atoi(zz[4]);
3001 if (zz[3][0] == '*')
3003 letter[index].random |= RANDOM_MONSTER;
3007 letter[index].monster = atoi(zz[3]);
3010 else if (zz[3][0] == 'c')
3012 letter[index].monster = - atoi(zz[3]+1);
3016 letter[index].monster = atoi(zz[3]);
3021 letter[index].cave_info = atoi(zz[2]);
3025 if (zz[1][0] == '*')
3027 letter[index].random |= RANDOM_FEATURE;
3031 letter[index].feature = atoi(zz[1]);
3036 letter[index].feature = atoi(zz[1]);
3049 * Process "F:<letter>:<terrain>:<cave_info>:<monster>:<object>:<ego>:<artifact>:<trap>:<special>" -- info for dungeon grid
3051 static errr parse_line_building(char *buf)
3067 /* Get the building number */
3070 /* Find the colon after the building number */
3073 /* Verify that colon */
3076 /* Nuke the colon, advance to the sub-index */
3079 /* Paranoia -- require a sub-index */
3080 if (!*s) return (1);
3082 /* Building definition sub-index */
3085 /* Building name, owner, race */
3088 if (tokenize(s + 2, 3, zz, 0) == 3)
3090 /* Name of the building */
3091 strcpy(building[index].name, zz[0]);
3093 /* Name of the owner */
3094 strcpy(building[index].owner_name, zz[1]);
3096 /* Race of the owner */
3097 strcpy(building[index].owner_race, zz[2]);
3102 return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3105 /* Building Action */
3108 if (tokenize(s + 2, 8, zz, 0) >= 7)
3110 /* Index of the action */
3111 int action_index = atoi(zz[0]);
3113 /* Name of the action */
3114 strcpy(building[index].act_names[action_index], zz[1]);
3116 /* Cost of the action for members */
3117 building[index].member_costs[action_index] = atoi(zz[2]);
3119 /* Cost of the action for non-members */
3120 building[index].other_costs[action_index] = atoi(zz[3]);
3122 /* Letter assigned to the action */
3123 building[index].letters[action_index] = zz[4][0];
3126 building[index].actions[action_index] = atoi(zz[5]);
3128 /* Action restriction */
3129 building[index].action_restr[action_index] = atoi(zz[6]);
3134 return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3137 /* Building Classes */
3140 if (tokenize(s + 2, MAX_CLASS, zz, 0) == MAX_CLASS)
3142 for (i = 0; i < MAX_CLASS; i++)
3144 building[index].member_class[i] = atoi(zz[i]);
3150 return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3153 /* Building Races */
3156 if (tokenize(s+2, MAX_RACES, zz, 0) == MAX_RACES)
3158 for (i = 0; i < MAX_RACES; i++)
3160 building[index].member_race[i] = atoi(zz[i]);
3166 return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3169 /* Building Realms */
3172 if (tokenize(s+2, MAX_MAGIC, zz, 0) == MAX_MAGIC)
3174 for (i = 0; i < MAX_MAGIC; i++)
3176 building[index].member_realm[i+1] = atoi(zz[i]);
3182 return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3187 /* Ignore scripts */
3193 return (PARSE_ERROR_UNDEFINED_DIRECTIVE);
3202 * Parse a sub-file of the "extra info"
3204 static errr process_dungeon_file_aux(char *buf, int ymin, int xmin, int ymax, int xmax, int *y, int *x)
3211 /* Skip "empty" lines */
3212 if (!buf[0]) return (0);
3214 /* Skip "blank" lines */
3215 if (isspace(buf[0])) return (0);
3218 if (buf[0] == '#') return (0);
3220 /* Require "?:*" format */
3221 if (buf[1] != ':') return (1);
3224 /* Process "%:<fname>" */
3227 /* Attempt to Process the given file */
3228 return (process_dungeon_file(buf + 2, ymin, xmin, ymax, xmax));
3231 /* Process "F:<letter>:<terrain>:<cave_info>:<monster>:<object>:<ego>:<artifact>:<trap>:<special>" -- info for dungeon grid */
3234 return parse_line_feature(buf);
3237 /* Process "D:<dungeon>" -- info for the cave grids */
3238 else if (buf[0] == 'D')
3240 object_type object_type_body;
3242 /* Acquire the text */
3245 /* Length of the text */
3246 int len = strlen(s);
3248 if (init_flags & INIT_ONLY_BUILDINGS) return (0);
3250 for (*x = xmin, i = 0; ((*x < xmax) && (i < len)); (*x)++, s++, i++)
3252 /* Access the grid */
3253 cave_type *c_ptr = &cave[*y][*x];
3257 int object_index = letter[idx].object;
3258 int monster_index = letter[idx].monster;
3259 int random = letter[idx].random;
3260 int artifact_index = letter[idx].artifact;
3262 /* Lay down a floor */
3263 c_ptr->feat = letter[idx].feature;
3265 /* Only the features */
3266 if (init_flags & INIT_ONLY_FEATURES) continue;
3269 c_ptr->info = letter[idx].cave_info;
3271 /* Create a monster */
3272 if (random & RANDOM_MONSTER)
3274 monster_level = base_level + monster_index;
3276 place_monster(*y, *x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
3278 monster_level = base_level;
3280 else if (monster_index)
3282 int old_cur_num, old_max_num;
3285 if (monster_index < 0)
3287 monster_index = -monster_index;
3290 old_cur_num = r_info[monster_index].cur_num;
3291 old_max_num = r_info[monster_index].max_num;
3293 /* Make alive again */
3294 if (r_info[monster_index].flags1 & RF1_UNIQUE)
3296 r_info[monster_index].cur_num = 0;
3297 r_info[monster_index].max_num = 1;
3300 /* Make alive again */
3301 if (r_info[monster_index].flags7 & RF7_UNIQUE_7)
3303 if (r_info[monster_index].cur_num == r_info[monster_index].max_num)
3305 r_info[monster_index].max_num++;
3310 place_monster_aux(0, *y, *x, monster_index, (PM_ALLOW_SLEEP | PM_NO_KAGE));
3314 m_list[hack_m_idx_ii].smart |= SM_CLONED;
3316 /* Make alive again for real unique monster */
3317 r_info[monster_index].cur_num = old_cur_num;
3318 r_info[monster_index].max_num = old_max_num;
3322 /* Object (and possible trap) */
3323 if ((random & RANDOM_OBJECT) && (random & RANDOM_TRAP))
3325 object_level = base_level + object_index;
3328 * Random trap and random treasure defined
3329 * 25% chance for trap and 75% chance for object
3331 if (randint0(100) < 75)
3333 place_object(*y, *x, FALSE, FALSE);
3340 object_level = base_level;
3342 else if (random & RANDOM_OBJECT)
3344 object_level = base_level + object_index;
3346 /* Create an out of deep object */
3347 if (randint0(100) < 75)
3348 place_object(*y, *x, FALSE, FALSE);
3349 else if (randint0(100) < 80)
3350 place_object(*y, *x, TRUE, FALSE);
3352 place_object(*y, *x, TRUE, TRUE);
3354 object_level = base_level;
3357 else if (random & RANDOM_TRAP)
3361 else if (object_index)
3363 /* Get local object */
3364 object_type *o_ptr = &object_type_body;
3366 /* Create the item */
3367 object_prep(o_ptr, object_index);
3369 if (o_ptr->tval == TV_GOLD)
3371 coin_type = object_index - OBJ_GOLD_LIST;
3376 /* Apply magic (no messages, no artifacts) */
3377 apply_magic(o_ptr, base_level, FALSE, TRUE, FALSE, FALSE);
3379 (void)drop_near(o_ptr, -1, *y, *x);
3385 if (a_info[artifact_index].cur_num)
3389 object_type *q_ptr = &forge;
3391 object_prep(q_ptr, k_idx);
3393 /* Drop it in the dungeon */
3394 (void)drop_near(q_ptr, -1, *y, *x);
3398 /* Create the artifact */
3399 create_named_art(artifact_index, *y, *x);
3401 a_info[artifact_index].cur_num = 1;
3405 /* Terrain special */
3406 c_ptr->special = letter[idx].special;
3414 /* Process "Q:<number>:<command>:... -- quest info */
3415 else if (buf[0] == 'Q')
3422 num = tokenize(buf + 2, 33, zz, 0);
3426 num = tokenize(buf + 3, 33, zz, 0);
3429 /* Have we enough parameters? */
3430 if (num < 3) return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3433 q_ptr = &(quest[atoi(zz[0])]);
3435 /* Process "Q:<q_index>:Q:<type>:<num_mon>:<cur_num>:<max_num>:<level>:<r_idx>:<k_idx>:<flags>" -- quest info */
3436 if (zz[1][0] == 'Q')
3438 if (init_flags & INIT_ASSIGN)
3440 monster_race *r_ptr;
3441 artifact_type *a_ptr;
3443 if (num < 9) return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3445 q_ptr->type = atoi(zz[2]);
3446 q_ptr->num_mon = atoi(zz[3]);
3447 q_ptr->cur_num = atoi(zz[4]);
3448 q_ptr->max_num = atoi(zz[5]);
3449 q_ptr->level = atoi(zz[6]);
3450 q_ptr->r_idx = atoi(zz[7]);
3451 q_ptr->k_idx = atoi(zz[8]);
3452 q_ptr->dungeon = atoi(zz[9]);
3455 q_ptr->flags = atoi(zz[10]);
3457 r_ptr = &r_info[q_ptr->r_idx];
3458 if (r_ptr->flags1 & RF1_UNIQUE)
3459 r_ptr->flags1 |= RF1_QUESTOR;
3461 a_ptr = &a_info[q_ptr->k_idx];
3462 a_ptr->gen_flags |= TRG_QUESTITEM;
3467 /* Process "Q:<q_index>:N:<name>" -- quest name */
3468 else if (zz[1][0] == 'N')
3470 if (init_flags & (INIT_ASSIGN | INIT_SHOW_TEXT))
3472 strcpy(q_ptr->name, zz[2]);
3478 /* Process "Q:<q_index>:T:<text>" -- quest description line */
3479 else if (zz[1][0] == 'T')
3481 if (init_flags & INIT_SHOW_TEXT)
3483 strcpy(quest_text[quest_text_line], zz[2]);
3491 /* Process "W:<command>: ..." -- info for the wilderness */
3492 else if (buf[0] == 'W')
3494 return parse_line_wilderness(buf, ymin, xmin, ymax, xmax, y, x);
3497 /* Process "P:<y>:<x>" -- player position */
3498 else if (buf[0] == 'P')
3500 if (init_flags & INIT_CREATE_DUNGEON)
3502 if (tokenize(buf + 2, 2, zz, 0) == 2)
3504 int panels_x, panels_y;
3506 /* Hack - Set the dungeon size */
3507 panels_y = (*y / SCREEN_HGT);
3508 if (*y % SCREEN_HGT) panels_y++;
3509 cur_hgt = panels_y * SCREEN_HGT;
3511 panels_x = (*x / SCREEN_WID);
3512 if (*x % SCREEN_WID) panels_x++;
3513 cur_wid = panels_x * SCREEN_WID;
3515 /* Assume illegal panel */
3516 panel_row_min = cur_hgt;
3517 panel_col_min = cur_wid;
3519 /* Place player in a quest level */
3520 if (p_ptr->inside_quest)
3524 /* Delete the monster (if any) */
3525 delete_monster(py, px);
3533 /* Place player in the town */
3534 else if (!p_ptr->oldpx && !p_ptr->oldpy)
3536 p_ptr->oldpy = atoi(zz[0]);
3537 p_ptr->oldpx = atoi(zz[1]);
3545 /* Process "B:<Index>:<Command>:..." -- Building definition */
3546 else if (buf[0] == 'B')
3548 return parse_line_building(buf);
3551 /* Process "M:<type>:<maximum>" -- set maximum values */
3552 else if (buf[0] == 'M')
3554 if (tokenize(buf+2, 2, zz, 0) == 2)
3557 if (zz[0][0] == 'T')
3559 max_towns = atoi(zz[1]);
3562 /* Maximum quests */
3563 else if (zz[0][0] == 'Q')
3565 max_quests = atoi(zz[1]);
3569 else if (zz[0][0] == 'R')
3571 max_r_idx = atoi(zz[1]);
3575 else if (zz[0][0] == 'K')
3577 max_k_idx = atoi(zz[1]);
3581 else if (zz[0][0] == 'V')
3583 max_v_idx = atoi(zz[1]);
3587 else if (zz[0][0] == 'F')
3589 max_f_idx = atoi(zz[1]);
3593 else if (zz[0][0] == 'A')
3595 max_a_idx = atoi(zz[1]);
3599 else if (zz[0][0] == 'E')
3601 max_e_idx = atoi(zz[1]);
3605 else if (zz[0][0] == 'D')
3607 max_d_idx = atoi(zz[1]);
3611 else if (zz[0][0] == 'O')
3613 max_o_idx = atoi(zz[1]);
3617 else if (zz[0][0] == 'M')
3619 max_m_idx = atoi(zz[1]);
3622 /* Wilderness size */
3623 else if (zz[0][0] == 'W')
3625 /* Maximum wild_x_size */
3626 if (zz[0][1] == 'X')
3627 max_wild_x = atoi(zz[1]);
3628 /* Maximum wild_y_size */
3629 if (zz[0][1] == 'Y')
3630 max_wild_y = atoi(zz[1]);
3644 static cptr variant = "ZANGBAND";
3648 * Helper function for "process_dungeon_file()"
3650 static cptr process_dungeon_file_expr(char **sp, char *fp)
3666 while (isspace(*s)) s++;
3684 t = process_dungeon_file_expr(&s, &f);
3693 else if (streq(t, "IOR"))
3696 while (*s && (f != b2))
3698 t = process_dungeon_file_expr(&s, &f);
3699 if (*t && !streq(t, "0")) v = "1";
3704 else if (streq(t, "AND"))
3707 while (*s && (f != b2))
3709 t = process_dungeon_file_expr(&s, &f);
3710 if (*t && streq(t, "0")) v = "0";
3715 else if (streq(t, "NOT"))
3718 while (*s && (f != b2))
3720 t = process_dungeon_file_expr(&s, &f);
3721 if (*t && streq(t, "1")) v = "0";
3726 else if (streq(t, "EQU"))
3729 if (*s && (f != b2))
3731 t = process_dungeon_file_expr(&s, &f);
3733 while (*s && (f != b2))
3736 t = process_dungeon_file_expr(&s, &f);
3737 if (*t && !streq(p, t)) v = "0";
3742 else if (streq(t, "LEQ"))
3745 if (*s && (f != b2))
3747 t = process_dungeon_file_expr(&s, &f);
3749 while (*s && (f != b2))
3752 t = process_dungeon_file_expr(&s, &f);
3753 if (*t && (strcmp(p, t) > 0)) v = "0";
3758 else if (streq(t, "GEQ"))
3761 if (*s && (f != b2))
3763 t = process_dungeon_file_expr(&s, &f);
3765 while (*s && (f != b2))
3768 t = process_dungeon_file_expr(&s, &f);
3769 if (*t && (strcmp(p, t) < 0)) v = "0";
3776 while (*s && (f != b2))
3778 t = process_dungeon_file_expr(&s, &f);
3783 if (f != b2) v = "?x?x?";
3785 /* Extract final and Terminate */
3786 if ((f = *s) != '\0') *s++ = '\0';
3792 /* Accept all printables except spaces and brackets */
3793 while (isprint(*s) && !strchr(" []", *s)) ++s;
3795 /* Extract final and Terminate */
3796 if ((f = *s) != '\0') *s++ = '\0';
3802 if (streq(b+1, "SYS"))
3808 else if (streq(b+1, "GRAF"))
3813 else if (streq(b+1, "MONOCHROME"))
3822 else if (streq(b+1, "RACE"))
3825 v = rp_ptr->E_title;
3832 else if (streq(b+1, "CLASS"))
3835 v = cp_ptr->E_title;
3842 else if (streq(b+1, "REALM1"))
3845 v = E_realm_names[p_ptr->realm1];
3847 v = realm_names[p_ptr->realm1];
3852 else if (streq(b+1, "REALM2"))
3855 v = E_realm_names[p_ptr->realm2];
3857 v = realm_names[p_ptr->realm2];
3862 else if (streq(b+1, "PLAYER"))
3868 else if (streq(b+1, "TOWN"))
3870 sprintf(tmp, "%d", p_ptr->town_num);
3875 else if (streq(b+1, "LEVEL"))
3877 sprintf(tmp, "%d", p_ptr->lev);
3881 /* Current quest number */
3882 else if (streq(b+1, "QUEST_NUMBER"))
3884 sprintf(tmp, "%d", p_ptr->inside_quest);
3888 /* Number of last quest */
3889 else if (streq(b+1, "LEAVING_QUEST"))
3891 sprintf(tmp, "%d", leaving_quest);
3896 else if (prefix(b+1, "QUEST"))
3898 /* "QUEST" uses a special parameter to determine the number of the quest */
3899 sprintf(tmp, "%d", quest[atoi(b+6)].status);
3904 else if (prefix(b+1, "RANDOM"))
3906 /* "RANDOM" uses a special parameter to determine the number of the quest */
3907 sprintf(tmp, "%d", (int)(seed_town%atoi(b+7)));
3912 else if (streq(b+1, "VARIANT"))
3918 else if (streq(b+1, "WILDERNESS"))
3921 sprintf(tmp, "NONE");
3923 sprintf(tmp, "LITE");
3925 sprintf(tmp, "NORMAL");
3948 errr process_dungeon_file(cptr name, int ymin, int xmin, int ymax, int xmax)
3958 bool bypass = FALSE;
3960 int x = xmin, y = ymin;
3963 /* Build the filename */
3964 path_build(buf, sizeof(buf), ANGBAND_DIR_EDIT, name);
3967 fp = my_fopen(buf, "r");
3970 if (!fp) return (-1);
3973 /* Process the file */
3974 while (0 == my_fgets(fp, buf, sizeof(buf)))
3980 /* Skip "empty" lines */
3981 if (!buf[0]) continue;
3983 /* Skip "blank" lines */
3984 if (isspace(buf[0])) continue;
3987 if (buf[0] == '#') continue;
3990 /* Process "?:<expr>" */
3991 if ((buf[0] == '?') && (buf[1] == ':'))
4000 /* Parse the expr */
4001 v = process_dungeon_file_expr(&s, &f);
4004 bypass = (streq(v, "0") ? TRUE : FALSE);
4010 /* Apply conditionals */
4011 if (bypass) continue;
4014 /* Process "%:<file>" */
4017 /* Process that file if allowed */
4018 (void)process_dungeon_file(buf + 2, ymin, xmin, ymax, xmax);
4025 /* Process the line */
4026 err = process_dungeon_file_aux(buf, ymin, xmin, ymax, xmax, &y, &x);
4038 oops = (((err > 0) && (err < PARSE_ERROR_MAX)) ? err_str[err] : "unknown");
4041 msg_format("Error %d (%s) at line %d of '%s'.", err, oops, num, name);
4043 msg_format("'%s'¤ò²òÀÏÃæ¡£", buf);
4045 msg_format("Parsing '%s'.", buf);
4052 /* Close the file */
4062 void write_r_info_txt(void)
4064 int i, j, z, fc, bc;
4072 monster_race *r_ptr;
4074 monster_blow *b_ptr;
4076 FILE *fff = fopen("output.txt", "wt");
4084 fprintf(fff, "# File: r_info.txt (autogenerated)\n\n");
4086 fprintf(fff, "# Version stamp (required)\n\n");
4089 fprintf(fff, "V:%d.%d.%d\n\n\n", r_head->v_major, r_head->v_minor, r_head->v_patch);
4092 fprintf(fff, "##### The Player #####\n\n");
4094 for (z = -1; z < alloc_race_size; z++)
4096 /* Output the monsters in order */
4097 i = (z >= 0) ? alloc_race_table[z].index : 0;
4099 /* Acquire the monster */
4102 /* Ignore empty monsters */
4103 if (!strlen(r_name + r_ptr->name)) continue;
4105 /* Ignore useless monsters */
4106 if (i && !r_ptr->speed) continue;
4108 /* Write a note if necessary */
4109 if (i && (!r_ptr->level != !mode))
4114 fprintf(fff, "\n##### Town monsters #####\n\n");
4116 /* Note the dungeon */
4119 fprintf(fff, "\n##### Normal monsters #####\n\n");
4122 /* Record the change */
4123 mode = r_ptr->level;
4126 /* Acquire the flags */
4127 f_ptr[0] = r_ptr->flags1; n_ptr[0] = r_info_flags1;
4128 f_ptr[1] = r_ptr->flags2; n_ptr[1] = r_info_flags2;
4129 f_ptr[2] = r_ptr->flags3; n_ptr[2] = r_info_flags3;
4130 f_ptr[3] = r_ptr->flags4; n_ptr[3] = r_info_flags4;
4131 f_ptr[4] = r_ptr->flags5; n_ptr[4] = r_info_flags5;
4132 f_ptr[5] = r_ptr->flags6; n_ptr[5] = r_info_flags6;
4133 f_ptr[6] = r_ptr->flags7; n_ptr[6] = r_info_flags7;
4134 f_ptr[7] = r_ptr->flags8; n_ptr[7] = r_info_flags8;
4135 f_ptr[8] = r_ptr->flags9; n_ptr[8] = r_info_flags9;
4137 /* Write New/Number/Name */
4138 fprintf(fff, "N:%d:%s\n", z + 1, r_name + r_ptr->name);
4141 fprintf(fff, "G:%c:%c\n", r_ptr->d_char, color_char[r_ptr->d_attr]);
4143 /* Write Information */
4144 fprintf(fff, "I:%d:%dd%d:%d:%d:%d\n", r_ptr->speed, r_ptr->hdice, r_ptr->hside,
4145 r_ptr->aaf, r_ptr->ac, r_ptr->sleep);
4147 /* Write more information */
4148 fprintf(fff, "W:%d:%d:%d:%ld\n", r_ptr->level, r_ptr->rarity, r_ptr->extra, r_ptr->mexp);
4151 for(j = 0; j < 4; j++)
4153 b_ptr = &(r_ptr->blow[j]);
4155 /* Stop when done */
4156 if (!b_ptr->method) break;
4158 /* Write the blows */
4159 fprintf(fff, "B:%s:%s:%dd%d\n", r_info_blow_method[b_ptr->method],
4160 r_info_blow_effect[b_ptr->effect],
4161 b_ptr->d_dice, b_ptr->d_side);
4164 /* Extract the flags */
4165 for (fc = 0, j = 0; j < 96; j++)
4167 /* Check this flag */
4168 if (f_ptr[j / 32] & (1L << (j % 32))) flags[fc++] = n_ptr[j / 32][j % 32];
4171 /* Extract the extra flags */
4172 for (j = 192; j < 288; j++)
4174 /* Check this flag */
4175 if (f_ptr[j / 32] & (1L << (j % 32))) flags[fc++] = n_ptr[j / 32][j % 32];
4178 /* Write the flags */
4179 for (j = 0; j < fc;)
4183 /* Start the line */
4186 for (bc = 0; (bc < 60) && (j < fc); j++)
4190 /* Format the flag */
4191 sprintf(t, "%s%s", flags[j], (j < fc - 1) ? " | " : "");
4193 /* Add it to the buffer */
4196 /* Note the length */
4200 /* Done with this line; write it */
4201 fprintf(fff, "%s\n", buf);
4204 /* Write Spells if applicable */
4205 if (r_ptr->freq_spell)
4207 /* Write the frequency */
4208 fprintf(fff, "S:1_IN_%d | \n", 100 / r_ptr->freq_spell);
4210 /* Extract the spell flags */
4211 for (fc = 0, j = 96; j < 192; j++)
4213 /* Check this flag */
4214 if (f_ptr[j / 32] & (1L << (j % 32))) flags[fc++] = n_ptr[j / 32][j % 32];
4217 /* Write the flags */
4218 for (j = 0; j < fc;)
4222 /* Start the line */
4225 for (bc = 0, t = buf + 2; (bc < 60) && (j < fc); j++)
4229 /* Format the flag */
4230 sprintf(t, "%s%s", flags[j], (j < fc - 1) ? " | " : "");
4234 /* Note the length */
4241 /* Done with this line; write it */
4242 fprintf(fff, "%s\n", buf);
4246 /* Acquire the description */
4247 desc = r_text + r_ptr->text;
4248 dlen = strlen(desc);
4250 /* Write Description */
4251 for (j = 0; j < dlen;)
4255 /* Start the line */
4258 for (bc = 0, t = buf + 2; ((bc < 60) || !isspace(desc[j])) && (j < dlen); j++, bc++, t++)
4266 /* Done with this line; write it */
4267 fprintf(fff, "%s\n", buf);
4270 /* Space between entries */