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, 1024))
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" */
830 /* Mega Hack -- Calculate Check Sum */
831 if (buf[0] != 'N' && buf[0] != 'D')
834 for (i = 0; buf[i]; i++)
836 head->v_extra += (byte)buf[i];
837 head->v_extra ^= (1 << (i % 8));
842 if ((err = (*parse_info_txt_line)(buf, head)) != 0)
847 /* Complete the "name" and "text" sizes */
848 if (head->name_size) head->name_size++;
849 if (head->text_size) head->text_size++;
857 * Initialize the "v_info" array, by parsing an ascii "template" file
859 errr parse_v_info(char *buf, header *head)
865 static vault_type *v_ptr = NULL;
867 /* Process 'N' for "New/Number/Name" */
870 /* Find the colon before the name */
871 s = strchr(buf+2, ':');
873 /* Verify that colon */
876 /* Nuke the colon, advance to the name */
879 /* Paranoia -- require a name */
885 /* Verify information */
886 if (i <= error_idx) return (4);
888 /* Verify information */
889 if (i >= head->info_num) return (2);
894 /* Point at the "info" */
898 if (!add_name(&v_ptr->name, head, s)) return (7);
901 /* There better be a current v_ptr */
902 else if (!v_ptr) return (3);
904 /* Process 'D' for "Description" */
905 else if (buf[0] == 'D')
907 /* Acquire the text */
911 if (!add_text(&v_ptr->text, head, s)) return (7);
914 /* Process 'X' for "Extra info" (one line only) */
915 else if (buf[0] == 'X')
917 int typ, rat, hgt, wid;
919 /* Scan for the values */
920 if (4 != sscanf(buf+2, "%d:%d:%d:%d",
921 &typ, &rat, &hgt, &wid)) return (1);
923 /* Save the values */
940 * Initialize the "s_info" array, by parsing an ascii "template" file
942 errr parse_s_info(char *buf, header *head)
947 static skill_table *s_ptr = NULL;
950 /* Process 'N' for "New/Number/Name" */
956 /* Verify information */
957 if (i <= error_idx) return (4);
959 /* Verify information */
960 if (i >= head->info_num) return (2);
965 /* Point at the "info" */
969 /* There better be a current s_ptr */
970 else if (!s_ptr) return (3);
972 /* Process 'W' for "Weapon exp" */
973 else if (buf[0] == 'W')
975 int tval, sval, start, max;
976 const s16b exp_conv_table[] = { 0, 4000, 6000, 7000, 8000 };
978 /* Scan for the values */
979 if (4 != sscanf(buf+2, "%d:%d:%d:%d",
980 &tval, &sval, &start, &max)) return (1);
982 if (start < 0 || start > 4 || max < 0 || max > 4) return (8);
984 /* Save the values */
985 s_ptr->w_start[tval][sval] = exp_conv_table[start];
986 s_ptr->w_max[tval][sval] = exp_conv_table[max];
989 /* Process 'S' for "Skill exp" */
990 else if (buf[0] == 'S')
994 /* Scan for the values */
995 if (3 != sscanf(buf+2, "%d:%d:%d",
996 &num, &start, &max)) return (1);
998 if (start < 0 || start > 8000 || max < 0 || max > 8000) return (8);
1000 /* Save the values */
1001 s_ptr->s_start[num] = start;
1002 s_ptr->s_max[num] = max;
1015 * Initialize the "m_info" array, by parsing an ascii "template" file
1017 errr parse_m_info(char *buf, header *head)
1024 static player_magic *m_ptr = NULL;
1027 static int realm, magic_idx = 0, readable = 0;
1030 /* Process 'N' for "New/Number/Name" */
1036 /* Verify information */
1037 if (i <= error_idx) return (4);
1039 /* Verify information */
1040 if (i >= head->info_num) return (2);
1042 /* Save the index */
1045 /* Point at the "info" */
1049 /* There better be a current m_ptr */
1050 else if (!m_ptr) return (3);
1052 /* Process 'I' for "Info" (one line only) */
1053 else if (buf[0] == 'I')
1056 int xtra, type, first, weight;
1058 /* Find the colon before the name */
1059 s = strchr(buf+2, ':');
1061 /* Verify that colon */
1064 /* Nuke the colon, advance to the name */
1069 if (streq(book, "SORCERY")) m_ptr->spell_book = TV_SORCERY_BOOK;
1070 else if (streq(book, "LIFE")) m_ptr->spell_book = TV_LIFE_BOOK;
1071 else if (streq(book, "MUSIC")) m_ptr->spell_book = TV_MUSIC_BOOK;
1072 else if (streq(book, "HISSATSU")) m_ptr->spell_book = TV_HISSATSU_BOOK;
1073 else if (streq(book, "NONE")) m_ptr->spell_book = 0;
1078 /* Find the colon before the name */
1081 /* Verify that colon */
1084 /* Nuke the colon, advance to the name */
1087 if (streq(stat, "STR")) m_ptr->spell_stat = A_STR;
1088 else if (streq(stat, "INT")) m_ptr->spell_stat = A_INT;
1089 else if (streq(stat, "WIS")) m_ptr->spell_stat = A_WIS;
1090 else if (streq(stat, "DEX")) m_ptr->spell_stat = A_DEX;
1091 else if (streq(stat, "CON")) m_ptr->spell_stat = A_CON;
1092 else if (streq(stat, "CHR")) m_ptr->spell_stat = A_CHR;
1096 /* Scan for the values */
1097 if (4 != sscanf(s, "%x:%d:%d:%d",
1098 (uint *)&xtra, &type, &first, &weight)) return (1);
1100 m_ptr->spell_xtra = xtra;
1101 m_ptr->spell_type = type;
1102 m_ptr->spell_first = first;
1103 m_ptr->spell_weight = weight;
1107 /* Process 'R' for "Realm" (one line only) */
1108 else if (buf[0] == 'R')
1110 /* Scan for the values */
1111 if (2 != sscanf(buf+2, "%d:%d",
1112 &realm, &readable)) return (1);
1117 else if (buf[0] == 'T')
1119 int level, mana, fail, exp;
1121 if (!readable) return (1);
1122 /* Scan for the values */
1123 if (4 != sscanf(buf+2, "%d:%d:%d:%d",
1124 &level, &mana, &fail, &exp)) return (1);
1126 m_ptr->info[realm][magic_idx].slevel = level;
1127 m_ptr->info[realm][magic_idx].smana = mana;
1128 m_ptr->info[realm][magic_idx].sfail = fail;
1129 m_ptr->info[realm][magic_idx].sexp = exp;
1143 * Initialize the "f_info" array, by parsing an ascii "template" file
1145 errr parse_f_info(char *buf, header *head)
1152 static feature_type *f_ptr = NULL;
1155 /* Process 'N' for "New/Number/Name" */
1158 /* Find the colon before the name */
1159 s = strchr(buf+2, ':');
1161 /* Verify that colon */
1164 /* Nuke the colon, advance to the name */
1168 /* Paranoia -- require a name */
1169 if (!*s) return (1);
1175 /* Verify information */
1176 if (i <= error_idx) return (4);
1178 /* Verify information */
1179 if (i >= head->info_num) return (2);
1181 /* Save the index */
1184 /* Point at the "info" */
1188 /* Store the name */
1189 if (!add_name(&f_ptr->name, head, s)) return (7);
1191 /* Default "mimic" */
1195 /* There better be a current f_ptr */
1196 else if (!f_ptr) return (3);
1199 /* ±Ñ¸ì̾¤òÆɤà¥ë¡¼¥Á¥ó¤òÄɲà */
1200 /* 'E' ¤«¤é»Ï¤Þ¤ë¹Ô¤Ï±Ñ¸ì̾¤È¤·¤Æ¤¤¤ë */
1201 else if (buf[0] == 'E')
1206 else if (buf[0] == 'E')
1208 /* Acquire the Text */
1211 /* Store the name */
1212 if (!add_name(&f_ptr->name, head, s)) return (7);
1217 /* Process 'M' for "Mimic" (one line only) */
1218 else if (buf[0] == 'M')
1222 /* Scan for the values */
1223 if (1 != sscanf(buf+2, "%d",
1224 &mimic)) return (1);
1226 /* Save the values */
1227 f_ptr->mimic = mimic;
1232 /* Process 'G' for "Graphics" (one line only) */
1233 else if (buf[0] == 'G')
1238 if (!buf[2]) return (1);
1239 if (!buf[3]) return (1);
1240 if (!buf[4]) return (1);
1242 /* Extract the color */
1243 tmp = color_char_to_attr(buf[4]);
1246 if (tmp > 127) return (1);
1248 /* Save the values */
1249 f_ptr->d_attr = tmp;
1250 f_ptr->d_char = buf[2];
1263 * Grab one flag in an object_kind from a textual string
1265 static errr grab_one_kind_flag(object_kind *k_ptr, cptr what)
1270 for (i = 0; i < TR_FLAG_MAX; i++)
1272 if (streq(what, k_info_flags[i]))
1274 add_flag(k_ptr->flags, i);
1279 /* Check gen_flags */
1280 for (i = 0; i < 32; i++)
1282 if (streq(what, k_info_gen_flags[i]))
1284 k_ptr->gen_flags |= (1L << i);
1291 msg_format("̤ÃΤΥ¢¥¤¥Æ¥à¡¦¥Õ¥é¥° '%s'¡£", what);
1293 msg_format("Unknown object flag '%s'.", what);
1303 * Initialize the "k_info" array, by parsing an ascii "template" file
1305 errr parse_k_info(char *buf, header *head)
1312 static object_kind *k_ptr = NULL;
1315 /* Process 'N' for "New/Number/Name" */
1318 /* Find the colon before the name */
1319 s = strchr(buf+2, ':');
1321 /* Verify that colon */
1324 /* Nuke the colon, advance to the name */
1328 /* Paranoia -- require a name */
1329 if (!*s) return (1);
1334 /* Verify information */
1335 if (i <= error_idx) return (4);
1337 /* Verify information */
1338 if (i >= head->info_num) return (2);
1340 /* Save the index */
1343 /* Point at the "info" */
1347 /* Store the name */
1348 if (!add_name(&k_ptr->name, head, s)) return (7);
1352 /* There better be a current k_ptr */
1353 else if (!k_ptr) return (3);
1357 /* ±Ñ¸ì̾¤òÆɤà¥ë¡¼¥Á¥ó¤òÄɲà */
1358 /* 'E' ¤«¤é»Ï¤Þ¤ë¹Ô¤Ï±Ñ¸ì̾¤È¤·¤Æ¤¤¤ë */
1359 else if (buf[0] == 'E')
1364 else if (buf[0] == 'E')
1366 /* Acquire the Text */
1369 /* Store the name */
1370 if (!add_name(&k_ptr->name, head, s)) return (7);
1374 /* Process 'D' for "Description" */
1375 else if (buf[0] == 'D')
1380 /* Acquire the text */
1385 /* Acquire the text */
1389 /* Store the text */
1390 if (!add_text(&k_ptr->text, head, s)) return (7);
1393 /* Process 'G' for "Graphics" (one line only) */
1394 else if (buf[0] == 'G')
1400 if (!buf[2]) return (1);
1401 if (!buf[3]) return (1);
1402 if (!buf[4]) return (1);
1404 /* Extract the char */
1407 /* Extract the attr */
1408 tmp = color_char_to_attr(buf[4]);
1411 if (tmp > 127) return (1);
1413 /* Save the values */
1414 k_ptr->d_attr = tmp;
1415 k_ptr->d_char = sym;
1418 /* Process 'I' for "Info" (one line only) */
1419 else if (buf[0] == 'I')
1421 int tval, sval, pval;
1423 /* Scan for the values */
1424 if (3 != sscanf(buf+2, "%d:%d:%d",
1425 &tval, &sval, &pval)) return (1);
1427 /* Save the values */
1433 /* Process 'W' for "More Info" (one line only) */
1434 else if (buf[0] == 'W')
1436 int level, extra, wgt;
1439 /* Scan for the values */
1440 if (4 != sscanf(buf+2, "%d:%d:%d:%ld",
1441 &level, &extra, &wgt, &cost)) return (1);
1443 /* Save the values */
1444 k_ptr->level = level;
1445 k_ptr->extra = extra;
1446 k_ptr->weight = wgt;
1450 /* Process 'A' for "Allocation" (one line only) */
1451 else if (buf[0] == 'A')
1455 /* XXX XXX XXX Simply read each number following a colon */
1456 for (i = 0, s = buf+1; s && (s[0] == ':') && s[1]; ++i)
1458 /* Default chance */
1459 k_ptr->chance[i] = 1;
1461 /* Store the attack damage index */
1462 k_ptr->locale[i] = atoi(s+1);
1464 /* Find the slash */
1465 t = strchr(s+1, '/');
1467 /* Find the next colon */
1468 s = strchr(s+1, ':');
1470 /* If the slash is "nearby", use it */
1471 if (t && (!s || t < s))
1473 int chance = atoi(t+1);
1474 if (chance > 0) k_ptr->chance[i] = chance;
1479 /* Hack -- Process 'P' for "power" and such */
1480 else if (buf[0] == 'P')
1482 int ac, hd1, hd2, th, td, ta;
1484 /* Scan for the values */
1485 if (6 != sscanf(buf+2, "%d:%dd%d:%d:%d:%d",
1486 &ac, &hd1, &hd2, &th, &td, &ta)) return (1);
1496 /* Hack -- Process 'F' for flags */
1497 else if (buf[0] == 'F')
1499 /* Parse every entry textually */
1500 for (s = buf + 2; *s; )
1502 /* Find the end of this entry */
1503 for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
1505 /* Nuke and skip any dividers */
1509 while (*t == ' ' || *t == '|') t++;
1512 /* Parse this entry */
1513 if (0 != grab_one_kind_flag(k_ptr, s)) return (5);
1515 /* Start the next entry */
1531 * Grab one flag in an artifact_type from a textual string
1533 static errr grab_one_artifact_flag(artifact_type *a_ptr, cptr what)
1538 for (i = 0; i < TR_FLAG_MAX; i++)
1540 if (streq(what, k_info_flags[i]))
1542 add_flag(a_ptr->flags, i);
1547 /* Check gen_flags */
1548 for (i = 0; i < 32; i++)
1550 if (streq(what, k_info_gen_flags[i]))
1552 a_ptr->gen_flags |= (1L << i);
1559 msg_format("̤ÃΤÎÅÁÀâ¤Î¥¢¥¤¥Æ¥à¡¦¥Õ¥é¥° '%s'¡£", what);
1561 msg_format("Unknown artifact flag '%s'.", what);
1573 * Initialize the "a_info" array, by parsing an ascii "template" file
1575 errr parse_a_info(char *buf, header *head)
1582 static artifact_type *a_ptr = NULL;
1585 /* Process 'N' for "New/Number/Name" */
1588 /* Find the colon before the name */
1589 s = strchr(buf+2, ':');
1591 /* Verify that colon */
1594 /* Nuke the colon, advance to the name */
1597 /* Paranoia -- require a name */
1598 if (!*s) return (1);
1603 /* Verify information */
1604 if (i < error_idx) return (4);
1606 /* Verify information */
1607 if (i >= head->info_num) return (2);
1609 /* Save the index */
1612 /* Point at the "info" */
1615 /* Ignore everything */
1616 add_flag(a_ptr->flags, TR_IGNORE_ACID);
1617 add_flag(a_ptr->flags, TR_IGNORE_ELEC);
1618 add_flag(a_ptr->flags, TR_IGNORE_FIRE);
1619 add_flag(a_ptr->flags, TR_IGNORE_COLD);
1621 /* Store the name */
1622 if (!add_name(&a_ptr->name, head, s)) return (7);
1626 /* There better be a current a_ptr */
1627 else if (!a_ptr) return (3);
1631 /* ±Ñ¸ì̾¤òÆɤà¥ë¡¼¥Á¥ó¤òÄɲà */
1632 /* 'E' ¤«¤é»Ï¤Þ¤ë¹Ô¤Ï±Ñ¸ì̾¤È¤·¤Æ¤¤¤ë */
1633 else if (buf[0] == 'E')
1638 else if (buf[0] == 'E')
1640 /* Acquire the Text */
1643 /* Store the name */
1644 if (!add_name(&a_ptr->name, head, s)) return (7);
1648 /* Process 'D' for "Description" */
1649 else if (buf[0] == 'D')
1654 /* Acquire the text */
1659 /* Acquire the text */
1663 /* Store the text */
1664 if (!add_text(&a_ptr->text, head, s)) return (7);
1668 /* Process 'I' for "Info" (one line only) */
1669 else if (buf[0] == 'I')
1671 int tval, sval, pval;
1673 /* Scan for the values */
1674 if (3 != sscanf(buf+2, "%d:%d:%d",
1675 &tval, &sval, &pval)) return (1);
1677 /* Save the values */
1683 /* Process 'W' for "More Info" (one line only) */
1684 else if (buf[0] == 'W')
1686 int level, rarity, wgt;
1689 /* Scan for the values */
1690 if (4 != sscanf(buf+2, "%d:%d:%d:%ld",
1691 &level, &rarity, &wgt, &cost)) return (1);
1693 /* Save the values */
1694 a_ptr->level = level;
1695 a_ptr->rarity = rarity;
1696 a_ptr->weight = wgt;
1700 /* Hack -- Process 'P' for "power" and such */
1701 else if (buf[0] == 'P')
1703 int ac, hd1, hd2, th, td, ta;
1705 /* Scan for the values */
1706 if (6 != sscanf(buf+2, "%d:%dd%d:%d:%d:%d",
1707 &ac, &hd1, &hd2, &th, &td, &ta)) return (1);
1717 /* Hack -- Process 'F' for flags */
1718 else if (buf[0] == 'F')
1720 /* Parse every entry textually */
1721 for (s = buf + 2; *s; )
1723 /* Find the end of this entry */
1724 for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
1726 /* Nuke and skip any dividers */
1730 while ((*t == ' ') || (*t == '|')) t++;
1733 /* Parse this entry */
1734 if (0 != grab_one_artifact_flag(a_ptr, s)) return (5);
1736 /* Start the next entry */
1752 * Grab one flag in a ego-item_type from a textual string
1754 static bool grab_one_ego_item_flag(ego_item_type *e_ptr, cptr what)
1759 for (i = 0; i < TR_FLAG_MAX; i++)
1761 if (streq(what, k_info_flags[i]))
1763 add_flag(e_ptr->flags, i);
1768 /* Check gen_flags */
1769 for (i = 0; i < 32; i++)
1771 if (streq(what, k_info_gen_flags[i]))
1773 e_ptr->gen_flags |= (1L << i);
1780 msg_format("̤ÃΤÎ̾¤Î¤¢¤ë¥¢¥¤¥Æ¥à¡¦¥Õ¥é¥° '%s'¡£", what);
1782 msg_format("Unknown ego-item flag '%s'.", what);
1794 * Initialize the "e_info" array, by parsing an ascii "template" file
1796 errr parse_e_info(char *buf, header *head)
1803 static ego_item_type *e_ptr = NULL;
1806 /* Just before the first record */
1809 /* Just before the first line */
1813 /* Process 'N' for "New/Number/Name" */
1816 /* Find the colon before the name */
1817 s = strchr(buf+2, ':');
1819 /* Verify that colon */
1822 /* Nuke the colon, advance to the name */
1825 /* Paranoia -- require a name */
1826 if (!*s) return (1);
1831 /* Verify information */
1832 if (i < error_idx) return (4);
1834 /* Verify information */
1835 if (i >= head->info_num) return (2);
1837 /* Save the index */
1840 /* Point at the "info" */
1843 /* Store the name */
1844 if (!add_name(&e_ptr->name, head, s)) return (7);
1848 /* There better be a current e_ptr */
1849 else if (!e_ptr) return (3);
1853 /* ±Ñ¸ì̾¤òÆɤà¥ë¡¼¥Á¥ó¤òÄɲà */
1854 /* 'E' ¤«¤é»Ï¤Þ¤ë¹Ô¤Ï±Ñ¸ì̾ */
1855 else if (buf[0] == 'E')
1860 else if (buf[0] == 'E')
1862 /* Acquire the Text */
1865 /* Store the name */
1866 if (!add_name(&e_ptr->name, head, s)) return (7);
1871 /* Process 'D' for "Description" */
1872 else if (buf[0] == 'D')
1874 /* Acquire the text */
1877 /* Store the text */
1878 if (!add_text(&e_ptr->text, head, s)) return (7);
1883 /* Process 'X' for "Xtra" (one line only) */
1884 else if (buf[0] == 'X')
1888 /* Scan for the values */
1889 if (2 != sscanf(buf+2, "%d:%d",
1890 &slot, &rating)) return (1);
1892 /* Save the values */
1894 e_ptr->rating = rating;
1897 /* Process 'W' for "More Info" (one line only) */
1898 else if (buf[0] == 'W')
1900 int level, rarity, pad2;
1903 /* Scan for the values */
1904 if (4 != sscanf(buf+2, "%d:%d:%d:%ld",
1905 &level, &rarity, &pad2, &cost)) return (1);
1907 /* Save the values */
1908 e_ptr->level = level;
1909 e_ptr->rarity = rarity;
1910 /* e_ptr->weight = wgt; */
1914 /* Hack -- Process 'C' for "creation" */
1915 else if (buf[0] == 'C')
1919 /* Scan for the values */
1920 if (4 != sscanf(buf+2, "%d:%d:%d:%d",
1921 &th, &td, &ta, &pv)) return (1);
1923 e_ptr->max_to_h = th;
1924 e_ptr->max_to_d = td;
1925 e_ptr->max_to_a = ta;
1926 e_ptr->max_pval = pv;
1929 /* Hack -- Process 'F' for flags */
1930 else if (buf[0] == 'F')
1932 /* Parse every entry textually */
1933 for (s = buf + 2; *s; )
1935 /* Find the end of this entry */
1936 for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
1938 /* Nuke and skip any dividers */
1942 while ((*t == ' ') || (*t == '|')) t++;
1945 /* Parse this entry */
1946 if (0 != grab_one_ego_item_flag(e_ptr, s)) return (5);
1948 /* Start the next entry */
1962 * Grab one (basic) flag in a monster_race from a textual string
1964 static errr grab_one_basic_flag(monster_race *r_ptr, cptr what)
1969 for (i = 0; i < 32; i++)
1971 if (streq(what, r_info_flags1[i]))
1973 r_ptr->flags1 |= (1L << i);
1979 for (i = 0; i < 32; i++)
1981 if (streq(what, r_info_flags2[i]))
1983 r_ptr->flags2 |= (1L << i);
1989 for (i = 0; i < 32; i++)
1991 if (streq(what, r_info_flags3[i]))
1993 r_ptr->flags3 |= (1L << i);
1999 for (i = 0; i < 32; i++)
2001 if (streq(what, r_info_flags7[i]))
2003 r_ptr->flags7 |= (1L << i);
2009 for (i = 0; i < 32; i++)
2011 if (streq(what, r_info_flags8[i]))
2013 r_ptr->flags8 |= (1L << i);
2019 for (i = 0; i < 32; i++)
2021 if (streq(what, r_info_flags9[i]))
2023 r_ptr->flags9 |= (1L << i);
2030 msg_format("̤ÃΤΥâ¥ó¥¹¥¿¡¼¡¦¥Õ¥é¥° '%s'¡£", what);
2032 msg_format("Unknown monster flag '%s'.", what);
2042 * Grab one (spell) flag in a monster_race from a textual string
2044 static errr grab_one_spell_flag(monster_race *r_ptr, cptr what)
2049 for (i = 0; i < 32; i++)
2051 if (streq(what, r_info_flags4[i]))
2053 r_ptr->flags4 |= (1L << i);
2059 for (i = 0; i < 32; i++)
2061 if (streq(what, r_info_flags5[i]))
2063 r_ptr->flags5 |= (1L << i);
2069 for (i = 0; i < 32; i++)
2071 if (streq(what, r_info_flags6[i]))
2073 r_ptr->flags6 |= (1L << i);
2080 msg_format("̤ÃΤΥâ¥ó¥¹¥¿¡¼¡¦¥Õ¥é¥° '%s'¡£", what);
2082 msg_format("Unknown monster flag '%s'.", what);
2094 * Initialize the "r_info" array, by parsing an ascii "template" file
2096 errr parse_r_info(char *buf, header *head)
2103 static monster_race *r_ptr = NULL;
2106 /* Process 'N' for "New/Number/Name" */
2109 /* Find the colon before the name */
2110 s = strchr(buf+2, ':');
2112 /* Verify that colon */
2115 /* Nuke the colon, advance to the name */
2118 /* Paranoia -- require a name */
2119 if (!*s) return (1);
2124 /* Verify information */
2125 if (i < error_idx) return (4);
2127 /* Verify information */
2128 if (i >= head->info_num) return (2);
2130 /* Save the index */
2133 /* Point at the "info" */
2136 /* Store the name */
2137 if (!add_name(&r_ptr->name, head, s)) return (7);
2141 /* There better be a current r_ptr */
2142 else if (!r_ptr) return (3);
2146 /* ±Ñ¸ì̾¤òÆɤà¥ë¡¼¥Á¥ó¤òÄɲà */
2147 /* 'E' ¤«¤é»Ï¤Þ¤ë¹Ô¤Ï±Ñ¸ì̾ */
2148 else if (buf[0] == 'E')
2150 /* Acquire the Text */
2153 /* Store the name */
2154 if (!add_name(&r_ptr->E_name, head, s)) return (7);
2157 else if (buf[0] == 'E')
2159 /* Acquire the Text */
2162 /* Store the name */
2163 if (!add_name(&r_ptr->name, head, s)) return (7);
2166 /* Process 'D' for "Description" */
2167 else if (buf[0] == 'D')
2172 /* Acquire the text */
2177 /* Acquire the text */
2181 /* Store the text */
2182 if (!add_text(&r_ptr->text, head, s)) return (7);
2185 /* Process 'G' for "Graphics" (one line only) */
2186 else if (buf[0] == 'G')
2192 if (!buf[2]) return (1);
2193 if (!buf[3]) return (1);
2194 if (!buf[4]) return (1);
2196 /* Extract the char */
2199 /* Extract the attr */
2200 tmp = color_char_to_attr(buf[4]);
2203 if (tmp > 127) return (1);
2205 /* Save the values */
2206 r_ptr->d_char = sym;
2207 r_ptr->d_attr = tmp;
2210 /* Process 'I' for "Info" (one line only) */
2211 else if (buf[0] == 'I')
2213 int spd, hp1, hp2, aaf, ac, slp;
2215 /* Scan for the other values */
2216 if (6 != sscanf(buf+2, "%d:%dd%d:%d:%d:%d",
2217 &spd, &hp1, &hp2, &aaf, &ac, &slp)) return (1);
2219 /* Save the values */
2228 /* Process 'W' for "More Info" (one line only) */
2229 else if (buf[0] == 'W')
2236 /* Scan for the values */
2237 if (6 != sscanf(buf+2, "%d:%d:%d:%ld:%ld:%d",
2238 &lev, &rar, &pad, &exp, &nextexp, &nextmon)) return (1);
2240 /* Save the values */
2242 r_ptr->rarity = rar;
2245 r_ptr->next_exp = nextexp;
2246 r_ptr->next_r_idx = nextmon;
2249 /* Process 'B' for "Blows" (up to four lines) */
2250 else if (buf[0] == 'B')
2254 /* Find the next empty blow slot (if any) */
2255 for (i = 0; i < 4; i++) if (!r_ptr->blow[i].method) break;
2257 /* Oops, no more slots */
2258 if (i == 4) return (1);
2260 /* Analyze the first field */
2261 for (s = t = buf+2; *t && (*t != ':'); t++) /* loop */;
2263 /* Terminate the field (if necessary) */
2264 if (*t == ':') *t++ = '\0';
2266 /* Analyze the method */
2267 for (n1 = 0; r_info_blow_method[n1]; n1++)
2269 if (streq(s, r_info_blow_method[n1])) break;
2272 /* Invalid method */
2273 if (!r_info_blow_method[n1]) return (1);
2275 /* Analyze the second field */
2276 for (s = t; *t && (*t != ':'); t++) /* loop */;
2278 /* Terminate the field (if necessary) */
2279 if (*t == ':') *t++ = '\0';
2281 /* Analyze effect */
2282 for (n2 = 0; r_info_blow_effect[n2]; n2++)
2284 if (streq(s, r_info_blow_effect[n2])) break;
2287 /* Invalid effect */
2288 if (!r_info_blow_effect[n2]) return (1);
2290 /* Analyze the third field */
2291 for (s = t; *t && (*t != 'd'); t++) /* loop */;
2293 /* Terminate the field (if necessary) */
2294 if (*t == 'd') *t++ = '\0';
2296 /* Save the method */
2297 r_ptr->blow[i].method = n1;
2299 /* Save the effect */
2300 r_ptr->blow[i].effect = n2;
2302 /* Extract the damage dice and sides */
2303 r_ptr->blow[i].d_dice = atoi(s);
2304 r_ptr->blow[i].d_side = atoi(t);
2307 /* Process 'F' for "Basic Flags" (multiple lines) */
2308 else if (buf[0] == 'F')
2310 /* Parse every entry */
2311 for (s = buf + 2; *s; )
2313 /* Find the end of this entry */
2314 for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
2316 /* Nuke and skip any dividers */
2320 while (*t == ' ' || *t == '|') t++;
2323 /* Parse this entry */
2324 if (0 != grab_one_basic_flag(r_ptr, s)) return (5);
2326 /* Start the next entry */
2331 /* Process 'S' for "Spell Flags" (multiple lines) */
2332 else if (buf[0] == 'S')
2334 /* Parse every entry */
2335 for (s = buf + 2; *s; )
2337 /* Find the end of this entry */
2338 for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
2340 /* Nuke and skip any dividers */
2344 while ((*t == ' ') || (*t == '|')) t++;
2347 /* XXX XXX XXX Hack -- Read spell frequency */
2348 if (1 == sscanf(s, "1_IN_%d", &i))
2350 /* Extract a "frequency" */
2351 r_ptr->freq_spell = r_ptr->freq_inate = 100 / i;
2353 /* Start at next entry */
2360 /* Parse this entry */
2361 if (0 != grab_one_spell_flag(r_ptr, s)) return (5);
2363 /* Start the next entry */
2378 * Grab one flag for a dungeon type from a textual string
2380 static errr grab_one_dungeon_flag(dungeon_info_type *d_ptr, cptr what)
2385 for (i = 0; i < 32; i++)
2387 if (streq(what, d_info_flags1[i]))
2389 d_ptr->flags1 |= (1L << i);
2396 msg_format("̤ÃΤΥÀ¥ó¥¸¥ç¥ó¡¦¥Õ¥é¥° '%s'¡£", what);
2398 msg_format("Unknown dungeon type flag '%s'.", what);
2406 * Grab one (basic) flag in a monster_race from a textual string
2408 static errr grab_one_basic_monster_flag(dungeon_info_type *d_ptr, cptr what)
2413 for (i = 0; i < 32; i++)
2415 if (streq(what, r_info_flags1[i]))
2417 d_ptr->mflags1 |= (1L << i);
2423 for (i = 0; i < 32; i++)
2425 if (streq(what, r_info_flags2[i]))
2427 d_ptr->mflags2 |= (1L << i);
2433 for (i = 0; i < 32; i++)
2435 if (streq(what, r_info_flags3[i]))
2437 d_ptr->mflags3 |= (1L << i);
2443 for (i = 0; i < 32; i++)
2445 if (streq(what, r_info_flags7[i]))
2447 d_ptr->mflags7 |= (1L << i);
2453 for (i = 0; i < 32; i++)
2455 if (streq(what, r_info_flags8[i]))
2457 d_ptr->mflags8 |= (1L << i);
2463 for (i = 0; i < 32; i++)
2465 if (streq(what, r_info_flags9[i]))
2467 d_ptr->mflags9 |= (1L << i);
2474 msg_format("̤ÃΤΥâ¥ó¥¹¥¿¡¼¡¦¥Õ¥é¥° '%s'¡£", what);
2476 msg_format("Unknown monster flag '%s'.", what);
2484 * Grab one (spell) flag in a monster_race from a textual string
2486 static errr grab_one_spell_monster_flag(dungeon_info_type *d_ptr, cptr what)
2491 for (i = 0; i < 32; i++)
2493 if (streq(what, r_info_flags4[i]))
2495 d_ptr->mflags4 |= (1L << i);
2501 for (i = 0; i < 32; i++)
2503 if (streq(what, r_info_flags5[i]))
2505 d_ptr->mflags5 |= (1L << i);
2511 for (i = 0; i < 32; i++)
2513 if (streq(what, r_info_flags6[i]))
2515 d_ptr->mflags6 |= (1L << i);
2522 msg_format("̤ÃΤΥâ¥ó¥¹¥¿¡¼¡¦¥Õ¥é¥° '%s'¡£", what);
2524 msg_format("Unknown monster flag '%s'.", what);
2532 * Initialize the "d_info" array, by parsing an ascii "template" file
2534 errr parse_d_info(char *buf, header *head)
2541 static dungeon_info_type *d_ptr = NULL;
2544 /* Process 'N' for "New/Number/Name" */
2547 /* Find the colon before the name */
2548 s = strchr(buf+2, ':');
2550 /* Verify that colon */
2553 /* Nuke the colon, advance to the name */
2556 /* Paranoia -- require a name */
2557 if (!*s) return (1);
2562 /* Verify information */
2563 if (i < error_idx) return (4);
2565 /* Verify information */
2566 if (i >= head->info_num) return (2);
2568 /* Save the index */
2571 /* Point at the "info" */
2574 /* Store the name */
2575 if (!add_name(&d_ptr->name, head, s)) return (7);
2580 else if (buf[0] == 'E') return (0);
2582 else if (buf[0] == 'E')
2584 /* Acquire the Text */
2587 /* Store the name */
2588 if (!add_name(&d_ptr->name, head, s)) return (7);
2592 /* Process 'D' for "Description */
2593 else if (buf[0] == 'D')
2598 /* Acquire the text */
2603 /* Acquire the text */
2607 /* Store the text */
2608 if (!add_text(&d_ptr->text, head, s)) return (7);
2611 /* Process 'W' for "More Info" (one line only) */
2612 else if (buf[0] == 'W')
2614 int min_lev, max_lev;
2616 int min_alloc, max_chance;
2617 int obj_good, obj_great;
2620 /* Scan for the values */
2621 if (10 != sscanf(buf+2, "%d:%d:%d:%d:%d:%d:%d:%d:%x:%x",
2622 &min_lev, &max_lev, &min_plev, &mode, &min_alloc, &max_chance, &obj_good, &obj_great, (unsigned int *)&pit, (unsigned int *)&nest)) return (1);
2624 /* Save the values */
2625 d_ptr->mindepth = min_lev;
2626 d_ptr->maxdepth = max_lev;
2627 d_ptr->min_plev = min_plev;
2629 d_ptr->min_m_alloc_level = min_alloc;
2630 d_ptr->max_m_alloc_chance = max_chance;
2631 d_ptr->obj_good = obj_good;
2632 d_ptr->obj_great = obj_great;
2637 /* Process 'P' for "Place Info" */
2638 else if (buf[0] == 'P')
2642 /* Scan for the values */
2643 if (2 != sscanf(buf+2, "%d:%d", &dy, &dx)) return (1);
2645 /* Save the values */
2650 /* Process 'L' for "fLoor type" (one line only) */
2651 else if (buf[0] == 'L')
2657 /* Scan for the values */
2658 if (7 != sscanf(buf+2, "%d:%d:%d:%d:%d:%d:%d",
2659 &f1, &p1, &f2, &p2, &f3, &p3, &tunnel)) return (1);
2661 /* Save the values */
2663 d_ptr->floor_percent1 = p1;
2665 d_ptr->floor_percent2 = p2;
2667 d_ptr->floor_percent3 = p3;
2668 d_ptr->tunnel_percent = tunnel;
2671 /* Process 'A' for "wAll type" (one line only) */
2672 else if (buf[0] == 'A')
2674 int w1, w2, w3, outer, inner, stream1, stream2;
2677 /* Scan for the values */
2678 if (10 != sscanf(buf+2, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
2679 &w1, &p1, &w2, &p2, &w3, &p3, &outer, &inner, &stream1, &stream2)) return (1);
2681 /* Save the values */
2682 d_ptr->fill_type1 = w1;
2683 d_ptr->fill_percent1 = p1;
2684 d_ptr->fill_type2 = w2;
2685 d_ptr->fill_percent2 = p2;
2686 d_ptr->fill_type3 = w3;
2687 d_ptr->fill_percent3 = p3;
2688 d_ptr->outer_wall = outer;
2689 d_ptr->inner_wall = inner;
2690 d_ptr->stream1 = stream1;
2691 d_ptr->stream2 = stream2;
2694 /* Process 'F' for "Dungeon Flags" (multiple lines) */
2695 else if (buf[0] == 'F')
2697 int artif = 0, monst = 0;
2699 /* Parse every entry */
2700 for (s = buf + 2; *s; )
2702 /* Find the end of this entry */
2703 for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
2705 /* Nuke and skip any dividers */
2709 while (*t == ' ' || *t == '|') t++;
2712 /* XXX XXX XXX Hack -- Read Final Artifact */
2713 if (1 == sscanf(s, "FINAL_ARTIFACT_%d", &artif))
2715 /* Extract a "Final Artifact" */
2716 d_ptr->final_artifact = artif;
2718 /* Start at next entry */
2725 /* XXX XXX XXX Hack -- Read Final Object */
2726 if (1 == sscanf(s, "FINAL_OBJECT_%d", &artif))
2728 /* Extract a "Final Artifact" */
2729 d_ptr->final_object = artif;
2731 /* Start at next entry */
2738 /* XXX XXX XXX Hack -- Read Artifact Guardian */
2739 if (1 == sscanf(s, "FINAL_GUARDIAN_%d", &monst))
2741 /* Extract a "Artifact Guardian" */
2742 d_ptr->final_guardian = monst;
2744 /* Start at next entry */
2751 /* XXX XXX XXX Hack -- Read Special Percentage */
2752 if (1 == sscanf(s, "MONSTER_DIV_%d", &monst))
2754 /* Extract a "Special %" */
2755 d_ptr->special_div = monst;
2757 /* Start at next entry */
2764 /* Parse this entry */
2765 if (0 != grab_one_dungeon_flag(d_ptr, s)) return (5);
2767 /* Start the next entry */
2772 /* Process 'M' for "Basic Flags" (multiple lines) */
2773 else if (buf[0] == 'M')
2775 /* Parse every entry */
2776 for (s = buf + 2; *s; )
2778 /* Find the end of this entry */
2779 for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
2781 /* Nuke and skip any dividers */
2785 while (*t == ' ' || *t == '|') t++;
2788 /* Hack -- Read monster symbols */
2789 if (!strncmp(s, "R_CHAR_", 7))
2791 /* Skip "R_CHAR_" */
2795 strncpy(d_ptr->r_char, s, sizeof(d_ptr->r_char));
2797 /* Start at next entry */
2804 /* Parse this entry */
2805 if (0 != grab_one_basic_monster_flag(d_ptr, s)) return (5);
2807 /* Start the next entry */
2812 /* Process 'S' for "Spell Flags" (multiple lines) */
2813 else if (buf[0] == 'S')
2815 /* Parse every entry */
2816 for (s = buf + 2; *s; )
2818 /* Find the end of this entry */
2819 for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
2821 /* Nuke and skip any dividers */
2825 while ((*t == ' ') || (*t == '|')) t++;
2828 /* XXX XXX XXX Hack -- Read spell frequency */
2829 if (1 == sscanf(s, "1_IN_%d", &i))
2831 /* Start at next entry */
2838 /* Parse this entry */
2839 if (0 != grab_one_spell_monster_flag(d_ptr, s)) return (5);
2841 /* Start the next entry */
2854 #else /* ALLOW_TEMPLATES */
2860 #endif /* ALLOW_TEMPLATES */
2863 /* Random dungeon grid effects */
2864 #define RANDOM_NONE 0x00
2865 #define RANDOM_FEATURE 0x01
2866 #define RANDOM_MONSTER 0x02
2867 #define RANDOM_OBJECT 0x04
2868 #define RANDOM_EGO 0x08
2869 #define RANDOM_ARTIFACT 0x10
2870 #define RANDOM_TRAP 0x20
2873 typedef struct dungeon_grid dungeon_grid;
2877 int feature; /* Terrain feature */
2878 int monster; /* Monster */
2879 int object; /* Object */
2880 int ego; /* Ego-Item */
2881 int artifact; /* Artifact */
2882 int trap; /* Trap */
2883 int cave_info; /* Flags for CAVE_MARK, CAVE_GLOW, CAVE_ICKY, CAVE_ROOM */
2884 int special; /* Reserved for special terrain info */
2885 int random; /* Number of the random effect */
2889 static dungeon_grid letter[255];
2893 * Process "F:<letter>:<terrain>:<cave_info>:<monster>:<object>:<ego>:<artifact>:<trap>:<special>" -- info for dungeon grid
2895 static errr parse_line_feature(char *buf)
2901 if (init_flags & INIT_ONLY_BUILDINGS) return (0);
2903 /* Tokenize the line */
2904 if ((num = tokenize(buf+2, 9, zz, 0)) > 1)
2906 /* Letter to assign */
2907 int index = zz[0][0];
2909 /* Reset the info for the letter */
2910 letter[index].feature = 0;
2911 letter[index].monster = 0;
2912 letter[index].object = 0;
2913 letter[index].ego = 0;
2914 letter[index].artifact = 0;
2915 letter[index].trap = 0;
2916 letter[index].cave_info = 0;
2917 letter[index].special = 0;
2918 letter[index].random = 0;
2924 letter[index].special = atoi(zz[8]);
2928 if (zz[7][0] == '*')
2930 letter[index].random |= RANDOM_TRAP;
2935 letter[index].trap = atoi(zz[7]);
2940 letter[index].trap = atoi(zz[7]);
2945 if (zz[6][0] == '*')
2947 letter[index].random |= RANDOM_ARTIFACT;
2952 letter[index].artifact = atoi(zz[6]);
2957 letter[index].artifact = atoi(zz[6]);
2962 if (zz[5][0] == '*')
2964 letter[index].random |= RANDOM_EGO;
2969 letter[index].ego = atoi(zz[5]);
2974 letter[index].ego = atoi(zz[5]);
2979 if (zz[4][0] == '*')
2981 letter[index].random |= RANDOM_OBJECT;
2986 letter[index].object = atoi(zz[4]);
2991 letter[index].object = atoi(zz[4]);
2996 if (zz[3][0] == '*')
2998 letter[index].random |= RANDOM_MONSTER;
3002 letter[index].monster = atoi(zz[3]);
3005 else if (zz[3][0] == 'c')
3007 letter[index].monster = - atoi(zz[3]+1);
3011 letter[index].monster = atoi(zz[3]);
3016 letter[index].cave_info = atoi(zz[2]);
3020 if (zz[1][0] == '*')
3022 letter[index].random |= RANDOM_FEATURE;
3026 letter[index].feature = atoi(zz[1]);
3031 letter[index].feature = atoi(zz[1]);
3044 * Process "F:<letter>:<terrain>:<cave_info>:<monster>:<object>:<ego>:<artifact>:<trap>:<special>" -- info for dungeon grid
3046 static errr parse_line_building(char *buf)
3062 /* Get the building number */
3065 /* Find the colon after the building number */
3068 /* Verify that colon */
3071 /* Nuke the colon, advance to the sub-index */
3074 /* Paranoia -- require a sub-index */
3075 if (!*s) return (1);
3077 /* Building definition sub-index */
3080 /* Building name, owner, race */
3083 if (tokenize(s + 2, 3, zz, 0) == 3)
3085 /* Name of the building */
3086 strcpy(building[index].name, zz[0]);
3088 /* Name of the owner */
3089 strcpy(building[index].owner_name, zz[1]);
3091 /* Race of the owner */
3092 strcpy(building[index].owner_race, zz[2]);
3097 return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3100 /* Building Action */
3103 if (tokenize(s + 2, 8, zz, 0) >= 7)
3105 /* Index of the action */
3106 int action_index = atoi(zz[0]);
3108 /* Name of the action */
3109 strcpy(building[index].act_names[action_index], zz[1]);
3111 /* Cost of the action for members */
3112 building[index].member_costs[action_index] = atoi(zz[2]);
3114 /* Cost of the action for non-members */
3115 building[index].other_costs[action_index] = atoi(zz[3]);
3117 /* Letter assigned to the action */
3118 building[index].letters[action_index] = zz[4][0];
3121 building[index].actions[action_index] = atoi(zz[5]);
3123 /* Action restriction */
3124 building[index].action_restr[action_index] = atoi(zz[6]);
3129 return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3132 /* Building Classes */
3135 if (tokenize(s + 2, MAX_CLASS, zz, 0) == MAX_CLASS)
3137 for (i = 0; i < MAX_CLASS; i++)
3139 building[index].member_class[i] = atoi(zz[i]);
3145 return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3148 /* Building Races */
3151 if (tokenize(s+2, MAX_RACES, zz, 0) == MAX_RACES)
3153 for (i = 0; i < MAX_RACES; i++)
3155 building[index].member_race[i] = atoi(zz[i]);
3161 return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3164 /* Building Realms */
3167 if (tokenize(s+2, MAX_MAGIC, zz, 0) == MAX_MAGIC)
3169 for (i = 0; i < MAX_MAGIC; i++)
3171 building[index].member_realm[i+1] = atoi(zz[i]);
3177 return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3182 /* Ignore scripts */
3188 return (PARSE_ERROR_UNDEFINED_DIRECTIVE);
3197 * Parse a sub-file of the "extra info"
3199 static errr process_dungeon_file_aux(char *buf, int ymin, int xmin, int ymax, int xmax, int *y, int *x)
3206 /* Skip "empty" lines */
3207 if (!buf[0]) return (0);
3209 /* Skip "blank" lines */
3210 if (isspace(buf[0])) return (0);
3213 if (buf[0] == '#') return (0);
3215 /* Require "?:*" format */
3216 if (buf[1] != ':') return (1);
3219 /* Process "%:<fname>" */
3222 /* Attempt to Process the given file */
3223 return (process_dungeon_file(buf + 2, ymin, xmin, ymax, xmax));
3226 /* Process "F:<letter>:<terrain>:<cave_info>:<monster>:<object>:<ego>:<artifact>:<trap>:<special>" -- info for dungeon grid */
3229 return parse_line_feature(buf);
3232 /* Process "D:<dungeon>" -- info for the cave grids */
3233 else if (buf[0] == 'D')
3235 object_type object_type_body;
3237 /* Acquire the text */
3240 /* Length of the text */
3241 int len = strlen(s);
3243 if (init_flags & INIT_ONLY_BUILDINGS) return (0);
3245 for (*x = xmin, i = 0; ((*x < xmax) && (i < len)); (*x)++, s++, i++)
3247 /* Access the grid */
3248 cave_type *c_ptr = &cave[*y][*x];
3252 int object_index = letter[idx].object;
3253 int monster_index = letter[idx].monster;
3254 int random = letter[idx].random;
3255 int artifact_index = letter[idx].artifact;
3257 /* Lay down a floor */
3258 c_ptr->feat = letter[idx].feature;
3260 /* Only the features */
3261 if (init_flags & INIT_ONLY_FEATURES) continue;
3264 c_ptr->info = letter[idx].cave_info;
3266 /* Create a monster */
3267 if (random & RANDOM_MONSTER)
3269 monster_level = base_level + monster_index;
3271 place_monster(*y, *x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
3273 monster_level = base_level;
3275 else if (monster_index)
3277 int old_cur_num, old_max_num;
3280 if (monster_index < 0)
3282 monster_index = -monster_index;
3285 old_cur_num = r_info[monster_index].cur_num;
3286 old_max_num = r_info[monster_index].max_num;
3288 /* Make alive again */
3289 if (r_info[monster_index].flags1 & RF1_UNIQUE)
3291 r_info[monster_index].cur_num = 0;
3292 r_info[monster_index].max_num = 1;
3295 /* Make alive again */
3296 if (r_info[monster_index].flags7 & RF7_UNIQUE_7)
3298 if (r_info[monster_index].cur_num == r_info[monster_index].max_num)
3300 r_info[monster_index].max_num++;
3305 place_monster_aux(0, *y, *x, monster_index, (PM_ALLOW_SLEEP | PM_NO_KAGE));
3309 m_list[hack_m_idx_ii].smart |= SM_CLONED;
3311 /* Make alive again for real unique monster */
3312 r_info[monster_index].cur_num = old_cur_num;
3313 r_info[monster_index].max_num = old_max_num;
3317 /* Object (and possible trap) */
3318 if ((random & RANDOM_OBJECT) && (random & RANDOM_TRAP))
3320 object_level = base_level + object_index;
3323 * Random trap and random treasure defined
3324 * 25% chance for trap and 75% chance for object
3326 if (randint0(100) < 75)
3328 place_object(*y, *x, FALSE, FALSE);
3335 object_level = base_level;
3337 else if (random & RANDOM_OBJECT)
3339 object_level = base_level + object_index;
3341 /* Create an out of deep object */
3342 if (randint0(100) < 75)
3343 place_object(*y, *x, FALSE, FALSE);
3344 else if (randint0(100) < 80)
3345 place_object(*y, *x, TRUE, FALSE);
3347 place_object(*y, *x, TRUE, TRUE);
3349 object_level = base_level;
3352 else if (random & RANDOM_TRAP)
3356 /* Hidden trap (or door) */
3357 else if (letter[idx].trap)
3359 c_ptr->mimic = c_ptr->feat;
3360 c_ptr->feat = letter[idx].trap;
3362 else if (object_index)
3364 /* Get local object */
3365 object_type *o_ptr = &object_type_body;
3367 /* Create the item */
3368 object_prep(o_ptr, object_index);
3370 if (o_ptr->tval == TV_GOLD)
3372 coin_type = object_index - OBJ_GOLD_LIST;
3377 /* Apply magic (no messages, no artifacts) */
3378 apply_magic(o_ptr, base_level, FALSE, TRUE, FALSE, FALSE);
3380 (void)drop_near(o_ptr, -1, *y, *x);
3386 if (a_info[artifact_index].cur_num)
3390 object_type *q_ptr = &forge;
3392 object_prep(q_ptr, k_idx);
3394 /* Drop it in the dungeon */
3395 (void)drop_near(q_ptr, -1, *y, *x);
3399 /* Create the artifact */
3400 create_named_art(artifact_index, *y, *x);
3402 a_info[artifact_index].cur_num = 1;
3406 /* Terrain special */
3407 c_ptr->special = letter[idx].special;
3415 /* Process "Q:<number>:<command>:... -- quest info */
3416 else if (buf[0] == 'Q')
3423 num = tokenize(buf + 2, 33, zz, 0);
3427 num = tokenize(buf + 3, 33, zz, 0);
3430 /* Have we enough parameters? */
3431 if (num < 3) return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3434 q_ptr = &(quest[atoi(zz[0])]);
3436 /* Process "Q:<q_index>:Q:<type>:<num_mon>:<cur_num>:<max_num>:<level>:<r_idx>:<k_idx>:<flags>" -- quest info */
3437 if (zz[1][0] == 'Q')
3439 if (init_flags & INIT_ASSIGN)
3441 monster_race *r_ptr;
3442 artifact_type *a_ptr;
3444 if (num < 9) return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3446 q_ptr->type = atoi(zz[2]);
3447 q_ptr->num_mon = atoi(zz[3]);
3448 q_ptr->cur_num = atoi(zz[4]);
3449 q_ptr->max_num = atoi(zz[5]);
3450 q_ptr->level = atoi(zz[6]);
3451 q_ptr->r_idx = atoi(zz[7]);
3452 q_ptr->k_idx = atoi(zz[8]);
3453 q_ptr->dungeon = atoi(zz[9]);
3456 q_ptr->flags = atoi(zz[10]);
3458 r_ptr = &r_info[q_ptr->r_idx];
3459 if (r_ptr->flags1 & RF1_UNIQUE)
3460 r_ptr->flags1 |= RF1_QUESTOR;
3462 a_ptr = &a_info[q_ptr->k_idx];
3463 a_ptr->gen_flags |= TRG_QUESTITEM;
3468 /* Process "Q:<q_index>:N:<name>" -- quest name */
3469 else if (zz[1][0] == 'N')
3471 if (init_flags & (INIT_ASSIGN | INIT_SHOW_TEXT))
3473 strcpy(q_ptr->name, zz[2]);
3479 /* Process "Q:<q_index>:T:<text>" -- quest description line */
3480 else if (zz[1][0] == 'T')
3482 if (init_flags & INIT_SHOW_TEXT)
3484 strcpy(quest_text[quest_text_line], zz[2]);
3492 /* Process "W:<command>: ..." -- info for the wilderness */
3493 else if (buf[0] == 'W')
3495 return parse_line_wilderness(buf, ymin, xmin, ymax, xmax, y, x);
3498 /* Process "P:<y>:<x>" -- player position */
3499 else if (buf[0] == 'P')
3501 if (init_flags & INIT_CREATE_DUNGEON)
3503 if (tokenize(buf + 2, 2, zz, 0) == 2)
3505 int panels_x, panels_y;
3507 /* Hack - Set the dungeon size */
3508 panels_y = (*y / SCREEN_HGT);
3509 if (*y % SCREEN_HGT) panels_y++;
3510 cur_hgt = panels_y * SCREEN_HGT;
3512 panels_x = (*x / SCREEN_WID);
3513 if (*x % SCREEN_WID) panels_x++;
3514 cur_wid = panels_x * SCREEN_WID;
3516 /* Assume illegal panel */
3517 panel_row_min = cur_hgt;
3518 panel_col_min = cur_wid;
3520 /* Place player in a quest level */
3521 if (p_ptr->inside_quest)
3525 /* Delete the monster (if any) */
3526 delete_monster(py, px);
3534 /* Place player in the town */
3535 else if (!p_ptr->oldpx && !p_ptr->oldpy)
3537 p_ptr->oldpy = atoi(zz[0]);
3538 p_ptr->oldpx = atoi(zz[1]);
3546 /* Process "B:<Index>:<Command>:..." -- Building definition */
3547 else if (buf[0] == 'B')
3549 return parse_line_building(buf);
3552 /* Process "M:<type>:<maximum>" -- set maximum values */
3553 else if (buf[0] == 'M')
3555 if (tokenize(buf+2, 2, zz, 0) == 2)
3558 if (zz[0][0] == 'T')
3560 max_towns = atoi(zz[1]);
3563 /* Maximum quests */
3564 else if (zz[0][0] == 'Q')
3566 max_quests = atoi(zz[1]);
3570 else if (zz[0][0] == 'R')
3572 max_r_idx = atoi(zz[1]);
3576 else if (zz[0][0] == 'K')
3578 max_k_idx = atoi(zz[1]);
3582 else if (zz[0][0] == 'V')
3584 max_v_idx = atoi(zz[1]);
3588 else if (zz[0][0] == 'F')
3590 max_f_idx = atoi(zz[1]);
3594 else if (zz[0][0] == 'A')
3596 max_a_idx = atoi(zz[1]);
3600 else if (zz[0][0] == 'E')
3602 max_e_idx = atoi(zz[1]);
3606 else if (zz[0][0] == 'D')
3608 max_d_idx = atoi(zz[1]);
3612 else if (zz[0][0] == 'O')
3614 max_o_idx = atoi(zz[1]);
3618 else if (zz[0][0] == 'M')
3620 max_m_idx = atoi(zz[1]);
3623 /* Wilderness size */
3624 else if (zz[0][0] == 'W')
3626 /* Maximum wild_x_size */
3627 if (zz[0][1] == 'X')
3628 max_wild_x = atoi(zz[1]);
3629 /* Maximum wild_y_size */
3630 if (zz[0][1] == 'Y')
3631 max_wild_y = atoi(zz[1]);
3645 static cptr variant = "ZANGBAND";
3649 * Helper function for "process_dungeon_file()"
3651 static cptr process_dungeon_file_expr(char **sp, char *fp)
3667 while (isspace(*s)) s++;
3685 t = process_dungeon_file_expr(&s, &f);
3694 else if (streq(t, "IOR"))
3697 while (*s && (f != b2))
3699 t = process_dungeon_file_expr(&s, &f);
3700 if (*t && !streq(t, "0")) v = "1";
3705 else if (streq(t, "AND"))
3708 while (*s && (f != b2))
3710 t = process_dungeon_file_expr(&s, &f);
3711 if (*t && streq(t, "0")) v = "0";
3716 else if (streq(t, "NOT"))
3719 while (*s && (f != b2))
3721 t = process_dungeon_file_expr(&s, &f);
3722 if (*t && streq(t, "1")) v = "0";
3727 else if (streq(t, "EQU"))
3730 if (*s && (f != b2))
3732 t = process_dungeon_file_expr(&s, &f);
3734 while (*s && (f != b2))
3737 t = process_dungeon_file_expr(&s, &f);
3738 if (*t && !streq(p, t)) v = "0";
3743 else if (streq(t, "LEQ"))
3746 if (*s && (f != b2))
3748 t = process_dungeon_file_expr(&s, &f);
3750 while (*s && (f != b2))
3753 t = process_dungeon_file_expr(&s, &f);
3754 if (*t && (strcmp(p, t) > 0)) v = "0";
3759 else if (streq(t, "GEQ"))
3762 if (*s && (f != b2))
3764 t = process_dungeon_file_expr(&s, &f);
3766 while (*s && (f != b2))
3769 t = process_dungeon_file_expr(&s, &f);
3770 if (*t && (strcmp(p, t) < 0)) v = "0";
3777 while (*s && (f != b2))
3779 t = process_dungeon_file_expr(&s, &f);
3784 if (f != b2) v = "?x?x?";
3786 /* Extract final and Terminate */
3787 if ((f = *s) != '\0') *s++ = '\0';
3793 /* Accept all printables except spaces and brackets */
3794 while (isprint(*s) && !strchr(" []", *s)) ++s;
3796 /* Extract final and Terminate */
3797 if ((f = *s) != '\0') *s++ = '\0';
3803 if (streq(b+1, "SYS"))
3809 else if (streq(b+1, "GRAF"))
3814 else if (streq(b+1, "MONOCHROME"))
3823 else if (streq(b+1, "RACE"))
3826 v = rp_ptr->E_title;
3833 else if (streq(b+1, "CLASS"))
3836 v = cp_ptr->E_title;
3843 else if (streq(b+1, "REALM1"))
3846 v = E_realm_names[p_ptr->realm1];
3848 v = realm_names[p_ptr->realm1];
3853 else if (streq(b+1, "REALM2"))
3856 v = E_realm_names[p_ptr->realm2];
3858 v = realm_names[p_ptr->realm2];
3863 else if (streq(b+1, "PLAYER"))
3869 else if (streq(b+1, "TOWN"))
3871 sprintf(tmp, "%d", p_ptr->town_num);
3876 else if (streq(b+1, "LEVEL"))
3878 sprintf(tmp, "%d", p_ptr->lev);
3882 /* Current quest number */
3883 else if (streq(b+1, "QUEST_NUMBER"))
3885 sprintf(tmp, "%d", p_ptr->inside_quest);
3889 /* Number of last quest */
3890 else if (streq(b+1, "LEAVING_QUEST"))
3892 sprintf(tmp, "%d", leaving_quest);
3897 else if (prefix(b+1, "QUEST"))
3899 /* "QUEST" uses a special parameter to determine the number of the quest */
3900 sprintf(tmp, "%d", quest[atoi(b+6)].status);
3905 else if (prefix(b+1, "RANDOM"))
3907 /* "RANDOM" uses a special parameter to determine the number of the quest */
3908 sprintf(tmp, "%d", (int)(seed_town%atoi(b+7)));
3913 else if (streq(b+1, "VARIANT"))
3919 else if (streq(b+1, "WILDERNESS"))
3922 sprintf(tmp, "NONE");
3924 sprintf(tmp, "LITE");
3926 sprintf(tmp, "NORMAL");
3949 errr process_dungeon_file(cptr name, int ymin, int xmin, int ymax, int xmax)
3959 bool bypass = FALSE;
3961 int x = xmin, y = ymin;
3964 /* Build the filename */
3965 path_build(buf, sizeof(buf), ANGBAND_DIR_EDIT, name);
3968 fp = my_fopen(buf, "r");
3971 if (!fp) return (-1);
3974 /* Process the file */
3975 while (0 == my_fgets(fp, buf, sizeof(buf)))
3981 /* Skip "empty" lines */
3982 if (!buf[0]) continue;
3984 /* Skip "blank" lines */
3985 if (isspace(buf[0])) continue;
3988 if (buf[0] == '#') continue;
3991 /* Process "?:<expr>" */
3992 if ((buf[0] == '?') && (buf[1] == ':'))
4001 /* Parse the expr */
4002 v = process_dungeon_file_expr(&s, &f);
4005 bypass = (streq(v, "0") ? TRUE : FALSE);
4011 /* Apply conditionals */
4012 if (bypass) continue;
4014 /* Process the line */
4015 err = process_dungeon_file_aux(buf, ymin, xmin, ymax, xmax, &y, &x);
4027 oops = (((err > 0) && (err < PARSE_ERROR_MAX)) ? err_str[err] : "unknown");
4030 msg_format("Error %d (%s) at line %d of '%s'.", err, oops, num, name);
4032 msg_format("'%s'¤ò²òÀÏÃæ¡£", buf);
4034 msg_format("Parsing '%s'.", buf);
4041 /* Close the file */
4051 void write_r_info_txt(void)
4053 int i, j, z, fc, bc;
4061 monster_race *r_ptr;
4063 monster_blow *b_ptr;
4065 FILE *fff = fopen("output.txt", "wt");
4073 fprintf(fff, "# File: r_info.txt (autogenerated)\n\n");
4075 fprintf(fff, "# Version stamp (required)\n\n");
4078 fprintf(fff, "V:%d.%d.%d\n\n\n", r_head->v_major, r_head->v_minor, r_head->v_patch);
4081 fprintf(fff, "##### The Player #####\n\n");
4083 for (z = -1; z < alloc_race_size; z++)
4085 /* Output the monsters in order */
4086 i = (z >= 0) ? alloc_race_table[z].index : 0;
4088 /* Acquire the monster */
4091 /* Ignore empty monsters */
4092 if (!strlen(r_name + r_ptr->name)) continue;
4094 /* Ignore useless monsters */
4095 if (i && !r_ptr->speed) continue;
4097 /* Write a note if necessary */
4098 if (i && (!r_ptr->level != !mode))
4103 fprintf(fff, "\n##### Town monsters #####\n\n");
4105 /* Note the dungeon */
4108 fprintf(fff, "\n##### Normal monsters #####\n\n");
4111 /* Record the change */
4112 mode = r_ptr->level;
4115 /* Acquire the flags */
4116 f_ptr[0] = r_ptr->flags1; n_ptr[0] = r_info_flags1;
4117 f_ptr[1] = r_ptr->flags2; n_ptr[1] = r_info_flags2;
4118 f_ptr[2] = r_ptr->flags3; n_ptr[2] = r_info_flags3;
4119 f_ptr[3] = r_ptr->flags4; n_ptr[3] = r_info_flags4;
4120 f_ptr[4] = r_ptr->flags5; n_ptr[4] = r_info_flags5;
4121 f_ptr[5] = r_ptr->flags6; n_ptr[5] = r_info_flags6;
4122 f_ptr[6] = r_ptr->flags7; n_ptr[6] = r_info_flags7;
4123 f_ptr[7] = r_ptr->flags8; n_ptr[7] = r_info_flags8;
4124 f_ptr[8] = r_ptr->flags9; n_ptr[8] = r_info_flags9;
4126 /* Write New/Number/Name */
4127 fprintf(fff, "N:%d:%s\n", z + 1, r_name + r_ptr->name);
4130 fprintf(fff, "G:%c:%c\n", r_ptr->d_char, color_char[r_ptr->d_attr]);
4132 /* Write Information */
4133 fprintf(fff, "I:%d:%dd%d:%d:%d:%d\n", r_ptr->speed, r_ptr->hdice, r_ptr->hside,
4134 r_ptr->aaf, r_ptr->ac, r_ptr->sleep);
4136 /* Write more information */
4137 fprintf(fff, "W:%d:%d:%d:%ld\n", r_ptr->level, r_ptr->rarity, r_ptr->extra, r_ptr->mexp);
4140 for(j = 0; j < 4; j++)
4142 b_ptr = &(r_ptr->blow[j]);
4144 /* Stop when done */
4145 if (!b_ptr->method) break;
4147 /* Write the blows */
4148 fprintf(fff, "B:%s:%s:%dd%d\n", r_info_blow_method[b_ptr->method],
4149 r_info_blow_effect[b_ptr->effect],
4150 b_ptr->d_dice, b_ptr->d_side);
4153 /* Extract the flags */
4154 for (fc = 0, j = 0; j < 96; j++)
4156 /* Check this flag */
4157 if (f_ptr[j / 32] & (1L << (j % 32))) flags[fc++] = n_ptr[j / 32][j % 32];
4160 /* Extract the extra flags */
4161 for (j = 192; j < 288; j++)
4163 /* Check this flag */
4164 if (f_ptr[j / 32] & (1L << (j % 32))) flags[fc++] = n_ptr[j / 32][j % 32];
4167 /* Write the flags */
4168 for (j = 0; j < fc;)
4172 /* Start the line */
4175 for (bc = 0; (bc < 60) && (j < fc); j++)
4179 /* Format the flag */
4180 sprintf(t, "%s%s", flags[j], (j < fc - 1) ? " | " : "");
4182 /* Add it to the buffer */
4185 /* Note the length */
4189 /* Done with this line; write it */
4190 fprintf(fff, "%s\n", buf);
4193 /* Write Spells if applicable */
4194 if (r_ptr->freq_spell)
4196 /* Write the frequency */
4197 fprintf(fff, "S:1_IN_%d | \n", 100 / r_ptr->freq_spell);
4199 /* Extract the spell flags */
4200 for (fc = 0, j = 96; j < 192; j++)
4202 /* Check this flag */
4203 if (f_ptr[j / 32] & (1L << (j % 32))) flags[fc++] = n_ptr[j / 32][j % 32];
4206 /* Write the flags */
4207 for (j = 0; j < fc;)
4211 /* Start the line */
4214 for (bc = 0, t = buf + 2; (bc < 60) && (j < fc); j++)
4218 /* Format the flag */
4219 sprintf(t, "%s%s", flags[j], (j < fc - 1) ? " | " : "");
4223 /* Note the length */
4230 /* Done with this line; write it */
4231 fprintf(fff, "%s\n", buf);
4235 /* Acquire the description */
4236 desc = r_text + r_ptr->text;
4237 dlen = strlen(desc);
4239 /* Write Description */
4240 for (j = 0; j < dlen;)
4244 /* Start the line */
4247 for (bc = 0, t = buf + 2; ((bc < 60) || !isspace(desc[j])) && (j < dlen); j++, bc++, t++)
4255 /* Done with this line; write it */
4256 fprintf(fff, "%s\n", buf);
4259 /* Space between entries */