4 * Copyright (c) 1997 Ben Harrison
6 * This software may be copied and distributed for educational, research,
7 * and not for profit purposes provided that this copyright and statement
8 * are included in all such copies. Other copyrights may also apply.
11 /* Purpose: Initialization (part 1) -BEN- */
18 static char *_strchr(const char *ptr, char ch)
20 for ( ; *ptr != '\0'; ++ptr)
22 if (*ptr == ch) return (char *)ptr;
23 if (iskanji(*ptr)) ++ptr;
28 #define strchr _strchr
31 * This file is used to initialize various variables and arrays for the
32 * Angband game. Note the use of "fd_read()" and "fd_write()" to bypass
33 * the common limitation of "read()" and "write()" to only 32767 bytes
36 * Several of the arrays for Angband are built from "template" files in
37 * the "lib/file" directory, from which quick-load binary "image" files
38 * are constructed whenever they are not present in the "lib/data"
39 * directory, or if those files become obsolete, if we are allowed.
41 * Warning -- the "ascii" file parsers use a minor hack to collect the
42 * name and text information in a single pass. Thus, the game will not
43 * be able to load any template file with more than 20K of names or 60K
44 * of text, even though technically, up to 64K should be legal.
46 * Note that if "ALLOW_TEMPLATES" is not defined, then a lot of the code
47 * in this file is compiled out, and the game will not run unless valid
48 * "binary template files" already exist in "lib/data". Thus, one can
49 * compile Angband with ALLOW_TEMPLATES defined, run once to create the
50 * "*.raw" files in "lib/data", and then quit, and recompile without
51 * defining ALLOW_TEMPLATES, which will both save 20K and prevent people
52 * from changing the ascii template files in potentially dangerous ways.
54 * The code could actually be removed and placed into a "stand-alone"
55 * program, but that feels a little silly, especially considering some
56 * of the platforms that we currently support.
59 #ifdef ALLOW_TEMPLATES
64 /*** Helper arrays for parsing ascii template files ***/
67 * Monster Blow Methods
69 static cptr r_info_blow_method[] =
102 * Monster Blow Effects
104 static cptr r_info_blow_effect[] =
147 static cptr r_info_flags1[] =
186 static cptr r_info_flags2[] =
225 static cptr r_info_flags3[] =
264 static cptr r_info_flags4[] =
303 static cptr r_info_flags5[] =
342 static cptr r_info_flags6[] =
359 "ANIM_DEAD", /* ToDo: Implement ANIM_DEAD */
382 static cptr r_info_flags7[] =
421 static cptr r_info_flags8[] =
453 "WILD_SWAMP", /* ToDo: Implement Swamp */
459 * Monster race flags - Drops
461 static cptr r_info_flags9[] =
502 static cptr k_info_flags[] =
627 static cptr k_info_gen_flags[] =
667 static cptr d_info_flags1[] =
705 * Add a text to the text-storage and store offset to it.
707 * Returns FALSE when there isn't enough space available to store
710 static bool add_text(u32b *offset, header *head, cptr buf)
712 /* Hack -- Verify space */
713 if (head->text_size + strlen(buf) + 8 > FAKE_TEXT_SIZE)
719 /* Advance and save the text index */
720 *offset = ++head->text_size;
723 /* Append chars to the text */
724 strcpy(head->text_ptr + head->text_size, buf);
726 /* Advance the index */
727 head->text_size += strlen(buf);
735 * Add a name to the name-storage and return an offset to it.
737 * Returns FALSE when there isn't enough space available to store
740 static bool add_name(u32b *offset, header *head, cptr buf)
742 /* Hack -- Verify space */
743 if (head->name_size + strlen(buf) + 8 > FAKE_NAME_SIZE)
749 /* Advance and save the name index */
750 *offset = ++head->name_size;
753 /* Append chars to the names */
754 strcpy(head->name_ptr + head->name_size, buf);
756 /* Advance the index */
757 head->name_size += strlen(buf);
765 * Convert a "color letter" into an "actual" color
766 * The colors are: dwsorgbuDWvyRGBU, as shown below
768 byte color_char_to_attr(char c)
772 case 'd': return (TERM_DARK);
773 case 'w': return (TERM_WHITE);
774 case 's': return (TERM_SLATE);
775 case 'o': return (TERM_ORANGE);
776 case 'r': return (TERM_RED);
777 case 'g': return (TERM_GREEN);
778 case 'b': return (TERM_BLUE);
779 case 'u': return (TERM_UMBER);
781 case 'D': return (TERM_L_DARK);
782 case 'W': return (TERM_L_WHITE);
783 case 'v': return (TERM_VIOLET);
784 case 'y': return (TERM_YELLOW);
785 case 'R': return (TERM_L_RED);
786 case 'G': return (TERM_L_GREEN);
787 case 'B': return (TERM_L_BLUE);
788 case 'U': return (TERM_L_UMBER);
796 /*** Initialize from ascii template files ***/
800 * Initialize an "*_info" array, by parsing an ascii "template" file
802 errr init_info_txt(FILE *fp, char *buf, header *head,
803 parse_info_txt_func parse_info_txt_line)
807 /* Just before the first record */
810 /* Just before the first line */
814 /* Prepare the "fake" stuff */
819 while (0 == my_fgets(fp, buf, 1024))
821 /* Advance the line number */
824 /* Skip comments and blank lines */
825 if (!buf[0] || (buf[0] == '#')) continue;
827 /* Verify correct "colon" format */
828 if (buf[1] != ':') return (PARSE_ERROR_GENERIC);
831 /* Hack -- Process 'V' for "Version" */
838 /* Mega Hack -- Calculate Check Sum */
839 if (buf[0] != 'N' && buf[0] != 'D')
842 for (i = 0; buf[i]; i++)
844 head->v_extra += (byte)buf[i];
845 head->v_extra ^= (1 << (i % 8));
850 if ((err = (*parse_info_txt_line)(buf, head)) != 0)
855 /* Complete the "name" and "text" sizes */
856 if (head->name_size) head->name_size++;
857 if (head->text_size) head->text_size++;
865 * Initialize the "v_info" array, by parsing an ascii "template" file
867 errr parse_v_info(char *buf, header *head)
873 static vault_type *v_ptr = NULL;
875 /* Process 'N' for "New/Number/Name" */
878 /* Find the colon before the name */
879 s = strchr(buf+2, ':');
881 /* Verify that colon */
884 /* Nuke the colon, advance to the name */
887 /* Paranoia -- require a name */
893 /* Verify information */
894 if (i <= error_idx) return (4);
896 /* Verify information */
897 if (i >= head->info_num) return (2);
902 /* Point at the "info" */
906 if (!add_name(&v_ptr->name, head, s)) return (7);
909 /* There better be a current v_ptr */
910 else if (!v_ptr) return (3);
912 /* Process 'D' for "Description" */
913 else if (buf[0] == 'D')
915 /* Acquire the text */
919 if (!add_text(&v_ptr->text, head, s)) return (7);
922 /* Process 'X' for "Extra info" (one line only) */
923 else if (buf[0] == 'X')
925 int typ, rat, hgt, wid;
927 /* Scan for the values */
928 if (4 != sscanf(buf+2, "%d:%d:%d:%d",
929 &typ, &rat, &hgt, &wid)) return (1);
931 /* Save the values */
948 * Initialize the "s_info" array, by parsing an ascii "template" file
950 errr parse_s_info(char *buf, header *head)
955 static skill_table *s_ptr = NULL;
958 /* Process 'N' for "New/Number/Name" */
964 /* Verify information */
965 if (i <= error_idx) return (4);
967 /* Verify information */
968 if (i >= head->info_num) return (2);
973 /* Point at the "info" */
977 /* There better be a current s_ptr */
978 else if (!s_ptr) return (3);
980 /* Process 'W' for "Weapon exp" */
981 else if (buf[0] == 'W')
983 int tval, sval, start, max;
984 const s16b exp_conv_table[] =
986 WEAPON_EXP_UNSKILLED, WEAPON_EXP_BEGINNER, WEAPON_EXP_SKILLED,
987 WEAPON_EXP_EXPERT, WEAPON_EXP_MASTER
990 /* Scan for the values */
991 if (4 != sscanf(buf+2, "%d:%d:%d:%d",
992 &tval, &sval, &start, &max)) return (1);
994 if (start < EXP_LEVEL_UNSKILLED || start > EXP_LEVEL_MASTER
995 || max < EXP_LEVEL_UNSKILLED || max > EXP_LEVEL_MASTER) return (8);
997 /* Save the values */
998 s_ptr->w_start[tval][sval] = exp_conv_table[start];
999 s_ptr->w_max[tval][sval] = exp_conv_table[max];
1002 /* Process 'S' for "Skill exp" */
1003 else if (buf[0] == 'S')
1005 int num, start, max;
1007 /* Scan for the values */
1008 if (3 != sscanf(buf+2, "%d:%d:%d",
1009 &num, &start, &max)) return (1);
1011 if (start < WEAPON_EXP_UNSKILLED || start > WEAPON_EXP_MASTER
1012 || max < WEAPON_EXP_UNSKILLED || max > WEAPON_EXP_MASTER) return (8);
1014 /* Save the values */
1015 s_ptr->s_start[num] = start;
1016 s_ptr->s_max[num] = max;
1029 * Initialize the "m_info" array, by parsing an ascii "template" file
1031 errr parse_m_info(char *buf, header *head)
1038 static player_magic *m_ptr = NULL;
1041 static int realm, magic_idx = 0, readable = 0;
1044 /* Process 'N' for "New/Number/Name" */
1050 /* Verify information */
1051 if (i <= error_idx) return (4);
1053 /* Verify information */
1054 if (i >= head->info_num) return (2);
1056 /* Save the index */
1059 /* Point at the "info" */
1063 /* There better be a current m_ptr */
1064 else if (!m_ptr) return (3);
1066 /* Process 'I' for "Info" (one line only) */
1067 else if (buf[0] == 'I')
1070 int xtra, type, first, weight;
1072 /* Find the colon before the name */
1073 s = strchr(buf+2, ':');
1075 /* Verify that colon */
1078 /* Nuke the colon, advance to the name */
1083 if (streq(book, "SORCERY")) m_ptr->spell_book = TV_SORCERY_BOOK;
1084 else if (streq(book, "LIFE")) m_ptr->spell_book = TV_LIFE_BOOK;
1085 else if (streq(book, "MUSIC")) m_ptr->spell_book = TV_MUSIC_BOOK;
1086 else if (streq(book, "HISSATSU")) m_ptr->spell_book = TV_HISSATSU_BOOK;
1087 else if (streq(book, "NONE")) m_ptr->spell_book = 0;
1092 /* Find the colon before the name */
1095 /* Verify that colon */
1098 /* Nuke the colon, advance to the name */
1101 if (streq(stat, "STR")) m_ptr->spell_stat = A_STR;
1102 else if (streq(stat, "INT")) m_ptr->spell_stat = A_INT;
1103 else if (streq(stat, "WIS")) m_ptr->spell_stat = A_WIS;
1104 else if (streq(stat, "DEX")) m_ptr->spell_stat = A_DEX;
1105 else if (streq(stat, "CON")) m_ptr->spell_stat = A_CON;
1106 else if (streq(stat, "CHR")) m_ptr->spell_stat = A_CHR;
1110 /* Scan for the values */
1111 if (4 != sscanf(s, "%x:%d:%d:%d",
1112 (uint *)&xtra, &type, &first, &weight)) return (1);
1114 m_ptr->spell_xtra = xtra;
1115 m_ptr->spell_type = type;
1116 m_ptr->spell_first = first;
1117 m_ptr->spell_weight = weight;
1121 /* Process 'R' for "Realm" (one line only) */
1122 else if (buf[0] == 'R')
1124 /* Scan for the values */
1125 if (2 != sscanf(buf+2, "%d:%d",
1126 &realm, &readable)) return (1);
1131 else if (buf[0] == 'T')
1133 int level, mana, fail, exp;
1135 if (!readable) return (1);
1136 /* Scan for the values */
1137 if (4 != sscanf(buf+2, "%d:%d:%d:%d",
1138 &level, &mana, &fail, &exp)) return (1);
1140 m_ptr->info[realm][magic_idx].slevel = level;
1141 m_ptr->info[realm][magic_idx].smana = mana;
1142 m_ptr->info[realm][magic_idx].sfail = fail;
1143 m_ptr->info[realm][magic_idx].sexp = exp;
1157 * Initialize the "f_info" array, by parsing an ascii "template" file
1159 errr parse_f_info(char *buf, header *head)
1166 static feature_type *f_ptr = NULL;
1169 /* Process 'N' for "New/Number/Name" */
1172 /* Find the colon before the name */
1173 s = strchr(buf+2, ':');
1175 /* Verify that colon */
1178 /* Nuke the colon, advance to the name */
1182 /* Paranoia -- require a name */
1183 if (!*s) return (1);
1189 /* Verify information */
1190 if (i <= error_idx) return (4);
1192 /* Verify information */
1193 if (i >= head->info_num) return (2);
1195 /* Save the index */
1198 /* Point at the "info" */
1202 /* Store the name */
1203 if (!add_name(&f_ptr->name, head, s)) return (7);
1205 /* Default "mimic" */
1209 /* There better be a current f_ptr */
1210 else if (!f_ptr) return (3);
1213 /* ±Ñ¸ì̾¤òÆɤà¥ë¡¼¥Á¥ó¤òÄɲà */
1214 /* 'E' ¤«¤é»Ï¤Þ¤ë¹Ô¤Ï±Ñ¸ì̾¤È¤·¤Æ¤¤¤ë */
1215 else if (buf[0] == 'E')
1220 else if (buf[0] == 'E')
1222 /* Acquire the Text */
1225 /* Store the name */
1226 if (!add_name(&f_ptr->name, head, s)) return (7);
1231 /* Process 'M' for "Mimic" (one line only) */
1232 else if (buf[0] == 'M')
1236 /* Scan for the values */
1237 if (1 != sscanf(buf+2, "%d",
1238 &mimic)) return (1);
1240 /* Save the values */
1241 f_ptr->mimic = mimic;
1246 /* Process 'G' for "Graphics" (one line only) */
1247 else if (buf[0] == 'G')
1252 if (!buf[2]) return (1);
1253 if (!buf[3]) return (1);
1254 if (!buf[4]) return (1);
1256 /* Extract the color */
1257 tmp = color_char_to_attr(buf[4]);
1260 if (tmp > 127) return (1);
1262 /* Save the values */
1263 f_ptr->d_attr = tmp;
1264 f_ptr->d_char = buf[2];
1277 * Grab one flag in an object_kind from a textual string
1279 static errr grab_one_kind_flag(object_kind *k_ptr, cptr what)
1284 for (i = 0; i < TR_FLAG_MAX; i++)
1286 if (streq(what, k_info_flags[i]))
1288 add_flag(k_ptr->flags, i);
1293 /* Check gen_flags */
1294 for (i = 0; i < 32; i++)
1296 if (streq(what, k_info_gen_flags[i]))
1298 k_ptr->gen_flags |= (1L << i);
1305 msg_format("̤ÃΤΥ¢¥¤¥Æ¥à¡¦¥Õ¥é¥° '%s'¡£", what);
1307 msg_format("Unknown object flag '%s'.", what);
1317 * Initialize the "k_info" array, by parsing an ascii "template" file
1319 errr parse_k_info(char *buf, header *head)
1326 static object_kind *k_ptr = NULL;
1329 /* Process 'N' for "New/Number/Name" */
1332 /* Find the colon before the name */
1333 s = strchr(buf+2, ':');
1335 /* Verify that colon */
1338 /* Nuke the colon, advance to the name */
1342 /* Paranoia -- require a name */
1343 if (!*s) return (1);
1348 /* Verify information */
1349 if (i <= error_idx) return (4);
1351 /* Verify information */
1352 if (i >= head->info_num) return (2);
1354 /* Save the index */
1357 /* Point at the "info" */
1361 /* Store the name */
1362 if (!add_name(&k_ptr->name, head, s)) return (7);
1366 /* There better be a current k_ptr */
1367 else if (!k_ptr) return (3);
1371 /* ±Ñ¸ì̾¤òÆɤà¥ë¡¼¥Á¥ó¤òÄɲà */
1372 /* 'E' ¤«¤é»Ï¤Þ¤ë¹Ô¤Ï±Ñ¸ì̾¤È¤·¤Æ¤¤¤ë */
1373 else if (buf[0] == 'E')
1378 else if (buf[0] == 'E')
1380 /* Acquire the Text */
1383 /* Store the name */
1384 if (!add_name(&k_ptr->name, head, s)) return (7);
1388 /* Process 'D' for "Description" */
1389 else if (buf[0] == 'D')
1394 /* Acquire the text */
1399 /* Acquire the text */
1403 /* Store the text */
1404 if (!add_text(&k_ptr->text, head, s)) return (7);
1407 /* Process 'G' for "Graphics" (one line only) */
1408 else if (buf[0] == 'G')
1414 if (!buf[2]) return (1);
1415 if (!buf[3]) return (1);
1416 if (!buf[4]) return (1);
1418 /* Extract the char */
1421 /* Extract the attr */
1422 tmp = color_char_to_attr(buf[4]);
1425 if (tmp > 127) return (1);
1427 /* Save the values */
1428 k_ptr->d_attr = tmp;
1429 k_ptr->d_char = sym;
1432 /* Process 'I' for "Info" (one line only) */
1433 else if (buf[0] == 'I')
1435 int tval, sval, pval;
1437 /* Scan for the values */
1438 if (3 != sscanf(buf+2, "%d:%d:%d",
1439 &tval, &sval, &pval)) return (1);
1441 /* Save the values */
1447 /* Process 'W' for "More Info" (one line only) */
1448 else if (buf[0] == 'W')
1450 int level, extra, wgt;
1453 /* Scan for the values */
1454 if (4 != sscanf(buf+2, "%d:%d:%d:%ld",
1455 &level, &extra, &wgt, &cost)) return (1);
1457 /* Save the values */
1458 k_ptr->level = level;
1459 k_ptr->extra = extra;
1460 k_ptr->weight = wgt;
1464 /* Process 'A' for "Allocation" (one line only) */
1465 else if (buf[0] == 'A')
1469 /* XXX XXX XXX Simply read each number following a colon */
1470 for (i = 0, s = buf+1; s && (s[0] == ':') && s[1]; ++i)
1472 /* Default chance */
1473 k_ptr->chance[i] = 1;
1475 /* Store the attack damage index */
1476 k_ptr->locale[i] = atoi(s+1);
1478 /* Find the slash */
1479 t = strchr(s+1, '/');
1481 /* Find the next colon */
1482 s = strchr(s+1, ':');
1484 /* If the slash is "nearby", use it */
1485 if (t && (!s || t < s))
1487 int chance = atoi(t+1);
1488 if (chance > 0) k_ptr->chance[i] = chance;
1493 /* Hack -- Process 'P' for "power" and such */
1494 else if (buf[0] == 'P')
1496 int ac, hd1, hd2, th, td, ta;
1498 /* Scan for the values */
1499 if (6 != sscanf(buf+2, "%d:%dd%d:%d:%d:%d",
1500 &ac, &hd1, &hd2, &th, &td, &ta)) return (1);
1510 /* Hack -- Process 'F' for flags */
1511 else if (buf[0] == 'F')
1513 /* Parse every entry textually */
1514 for (s = buf + 2; *s; )
1516 /* Find the end of this entry */
1517 for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
1519 /* Nuke and skip any dividers */
1523 while (*t == ' ' || *t == '|') t++;
1526 /* Parse this entry */
1527 if (0 != grab_one_kind_flag(k_ptr, s)) return (5);
1529 /* Start the next entry */
1545 * Grab one flag in an artifact_type from a textual string
1547 static errr grab_one_artifact_flag(artifact_type *a_ptr, cptr what)
1552 for (i = 0; i < TR_FLAG_MAX; i++)
1554 if (streq(what, k_info_flags[i]))
1556 add_flag(a_ptr->flags, i);
1561 /* Check gen_flags */
1562 for (i = 0; i < 32; i++)
1564 if (streq(what, k_info_gen_flags[i]))
1566 a_ptr->gen_flags |= (1L << i);
1573 msg_format("̤ÃΤÎÅÁÀâ¤Î¥¢¥¤¥Æ¥à¡¦¥Õ¥é¥° '%s'¡£", what);
1575 msg_format("Unknown artifact flag '%s'.", what);
1587 * Initialize the "a_info" array, by parsing an ascii "template" file
1589 errr parse_a_info(char *buf, header *head)
1596 static artifact_type *a_ptr = NULL;
1599 /* Process 'N' for "New/Number/Name" */
1602 /* Find the colon before the name */
1603 s = strchr(buf+2, ':');
1605 /* Verify that colon */
1608 /* Nuke the colon, advance to the name */
1611 /* Paranoia -- require a name */
1612 if (!*s) return (1);
1617 /* Verify information */
1618 if (i < error_idx) return (4);
1620 /* Verify information */
1621 if (i >= head->info_num) return (2);
1623 /* Save the index */
1626 /* Point at the "info" */
1629 /* Ignore everything */
1630 add_flag(a_ptr->flags, TR_IGNORE_ACID);
1631 add_flag(a_ptr->flags, TR_IGNORE_ELEC);
1632 add_flag(a_ptr->flags, TR_IGNORE_FIRE);
1633 add_flag(a_ptr->flags, TR_IGNORE_COLD);
1635 /* Store the name */
1636 if (!add_name(&a_ptr->name, head, s)) return (7);
1640 /* There better be a current a_ptr */
1641 else if (!a_ptr) return (3);
1645 /* ±Ñ¸ì̾¤òÆɤà¥ë¡¼¥Á¥ó¤òÄɲà */
1646 /* 'E' ¤«¤é»Ï¤Þ¤ë¹Ô¤Ï±Ñ¸ì̾¤È¤·¤Æ¤¤¤ë */
1647 else if (buf[0] == 'E')
1652 else if (buf[0] == 'E')
1654 /* Acquire the Text */
1657 /* Store the name */
1658 if (!add_name(&a_ptr->name, head, s)) return (7);
1662 /* Process 'D' for "Description" */
1663 else if (buf[0] == 'D')
1668 /* Acquire the text */
1673 /* Acquire the text */
1677 /* Store the text */
1678 if (!add_text(&a_ptr->text, head, s)) return (7);
1682 /* Process 'I' for "Info" (one line only) */
1683 else if (buf[0] == 'I')
1685 int tval, sval, pval;
1687 /* Scan for the values */
1688 if (3 != sscanf(buf+2, "%d:%d:%d",
1689 &tval, &sval, &pval)) return (1);
1691 /* Save the values */
1697 /* Process 'W' for "More Info" (one line only) */
1698 else if (buf[0] == 'W')
1700 int level, rarity, wgt;
1703 /* Scan for the values */
1704 if (4 != sscanf(buf+2, "%d:%d:%d:%ld",
1705 &level, &rarity, &wgt, &cost)) return (1);
1707 /* Save the values */
1708 a_ptr->level = level;
1709 a_ptr->rarity = rarity;
1710 a_ptr->weight = wgt;
1714 /* Hack -- Process 'P' for "power" and such */
1715 else if (buf[0] == 'P')
1717 int ac, hd1, hd2, th, td, ta;
1719 /* Scan for the values */
1720 if (6 != sscanf(buf+2, "%d:%dd%d:%d:%d:%d",
1721 &ac, &hd1, &hd2, &th, &td, &ta)) return (1);
1731 /* Hack -- Process 'F' for flags */
1732 else if (buf[0] == 'F')
1734 /* Parse every entry textually */
1735 for (s = buf + 2; *s; )
1737 /* Find the end of this entry */
1738 for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
1740 /* Nuke and skip any dividers */
1744 while ((*t == ' ') || (*t == '|')) t++;
1747 /* Parse this entry */
1748 if (0 != grab_one_artifact_flag(a_ptr, s)) return (5);
1750 /* Start the next entry */
1766 * Grab one flag in a ego-item_type from a textual string
1768 static bool grab_one_ego_item_flag(ego_item_type *e_ptr, cptr what)
1773 for (i = 0; i < TR_FLAG_MAX; i++)
1775 if (streq(what, k_info_flags[i]))
1777 add_flag(e_ptr->flags, i);
1782 /* Check gen_flags */
1783 for (i = 0; i < 32; i++)
1785 if (streq(what, k_info_gen_flags[i]))
1787 e_ptr->gen_flags |= (1L << i);
1794 msg_format("̤ÃΤÎ̾¤Î¤¢¤ë¥¢¥¤¥Æ¥à¡¦¥Õ¥é¥° '%s'¡£", what);
1796 msg_format("Unknown ego-item flag '%s'.", what);
1808 * Initialize the "e_info" array, by parsing an ascii "template" file
1810 errr parse_e_info(char *buf, header *head)
1817 static ego_item_type *e_ptr = NULL;
1820 /* Just before the first record */
1823 /* Just before the first line */
1827 /* Process 'N' for "New/Number/Name" */
1830 /* Find the colon before the name */
1831 s = strchr(buf+2, ':');
1833 /* Verify that colon */
1836 /* Nuke the colon, advance to the name */
1839 /* Paranoia -- require a name */
1840 if (!*s) return (1);
1845 /* Verify information */
1846 if (i < error_idx) return (4);
1848 /* Verify information */
1849 if (i >= head->info_num) return (2);
1851 /* Save the index */
1854 /* Point at the "info" */
1857 /* Store the name */
1858 if (!add_name(&e_ptr->name, head, s)) return (7);
1862 /* There better be a current e_ptr */
1863 else if (!e_ptr) return (3);
1867 /* ±Ñ¸ì̾¤òÆɤà¥ë¡¼¥Á¥ó¤òÄɲà */
1868 /* 'E' ¤«¤é»Ï¤Þ¤ë¹Ô¤Ï±Ñ¸ì̾ */
1869 else if (buf[0] == 'E')
1874 else if (buf[0] == 'E')
1876 /* Acquire the Text */
1879 /* Store the name */
1880 if (!add_name(&e_ptr->name, head, s)) return (7);
1885 /* Process 'D' for "Description" */
1886 else if (buf[0] == 'D')
1888 /* Acquire the text */
1891 /* Store the text */
1892 if (!add_text(&e_ptr->text, head, s)) return (7);
1897 /* Process 'X' for "Xtra" (one line only) */
1898 else if (buf[0] == 'X')
1902 /* Scan for the values */
1903 if (2 != sscanf(buf+2, "%d:%d",
1904 &slot, &rating)) return (1);
1906 /* Save the values */
1908 e_ptr->rating = rating;
1911 /* Process 'W' for "More Info" (one line only) */
1912 else if (buf[0] == 'W')
1914 int level, rarity, pad2;
1917 /* Scan for the values */
1918 if (4 != sscanf(buf+2, "%d:%d:%d:%ld",
1919 &level, &rarity, &pad2, &cost)) return (1);
1921 /* Save the values */
1922 e_ptr->level = level;
1923 e_ptr->rarity = rarity;
1924 /* e_ptr->weight = wgt; */
1928 /* Hack -- Process 'C' for "creation" */
1929 else if (buf[0] == 'C')
1933 /* Scan for the values */
1934 if (4 != sscanf(buf+2, "%d:%d:%d:%d",
1935 &th, &td, &ta, &pv)) return (1);
1937 e_ptr->max_to_h = th;
1938 e_ptr->max_to_d = td;
1939 e_ptr->max_to_a = ta;
1940 e_ptr->max_pval = pv;
1943 /* Hack -- Process 'F' for flags */
1944 else if (buf[0] == 'F')
1946 /* Parse every entry textually */
1947 for (s = buf + 2; *s; )
1949 /* Find the end of this entry */
1950 for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
1952 /* Nuke and skip any dividers */
1956 while ((*t == ' ') || (*t == '|')) t++;
1959 /* Parse this entry */
1960 if (0 != grab_one_ego_item_flag(e_ptr, s)) return (5);
1962 /* Start the next entry */
1976 * Grab one (basic) flag in a monster_race from a textual string
1978 static errr grab_one_basic_flag(monster_race *r_ptr, cptr what)
1983 for (i = 0; i < 32; i++)
1985 if (streq(what, r_info_flags1[i]))
1987 r_ptr->flags1 |= (1L << i);
1993 for (i = 0; i < 32; i++)
1995 if (streq(what, r_info_flags2[i]))
1997 r_ptr->flags2 |= (1L << i);
2003 for (i = 0; i < 32; i++)
2005 if (streq(what, r_info_flags3[i]))
2007 r_ptr->flags3 |= (1L << i);
2013 for (i = 0; i < 32; i++)
2015 if (streq(what, r_info_flags7[i]))
2017 r_ptr->flags7 |= (1L << i);
2023 for (i = 0; i < 32; i++)
2025 if (streq(what, r_info_flags8[i]))
2027 r_ptr->flags8 |= (1L << i);
2033 for (i = 0; i < 32; i++)
2035 if (streq(what, r_info_flags9[i]))
2037 r_ptr->flags9 |= (1L << i);
2044 msg_format("̤ÃΤΥâ¥ó¥¹¥¿¡¼¡¦¥Õ¥é¥° '%s'¡£", what);
2046 msg_format("Unknown monster flag '%s'.", what);
2056 * Grab one (spell) flag in a monster_race from a textual string
2058 static errr grab_one_spell_flag(monster_race *r_ptr, cptr what)
2063 for (i = 0; i < 32; i++)
2065 if (streq(what, r_info_flags4[i]))
2067 r_ptr->flags4 |= (1L << i);
2073 for (i = 0; i < 32; i++)
2075 if (streq(what, r_info_flags5[i]))
2077 r_ptr->flags5 |= (1L << i);
2083 for (i = 0; i < 32; i++)
2085 if (streq(what, r_info_flags6[i]))
2087 r_ptr->flags6 |= (1L << i);
2094 msg_format("̤ÃΤΥâ¥ó¥¹¥¿¡¼¡¦¥Õ¥é¥° '%s'¡£", what);
2096 msg_format("Unknown monster flag '%s'.", what);
2108 * Initialize the "r_info" array, by parsing an ascii "template" file
2110 errr parse_r_info(char *buf, header *head)
2117 static monster_race *r_ptr = NULL;
2120 /* Process 'N' for "New/Number/Name" */
2123 /* Find the colon before the name */
2124 s = strchr(buf+2, ':');
2126 /* Verify that colon */
2129 /* Nuke the colon, advance to the name */
2132 /* Paranoia -- require a name */
2133 if (!*s) return (1);
2138 /* Verify information */
2139 if (i < error_idx) return (4);
2141 /* Verify information */
2142 if (i >= head->info_num) return (2);
2144 /* Save the index */
2147 /* Point at the "info" */
2150 /* Store the name */
2151 if (!add_name(&r_ptr->name, head, s)) return (7);
2155 /* There better be a current r_ptr */
2156 else if (!r_ptr) return (3);
2160 /* ±Ñ¸ì̾¤òÆɤà¥ë¡¼¥Á¥ó¤òÄɲà */
2161 /* 'E' ¤«¤é»Ï¤Þ¤ë¹Ô¤Ï±Ñ¸ì̾ */
2162 else if (buf[0] == 'E')
2164 /* Acquire the Text */
2167 /* Store the name */
2168 if (!add_name(&r_ptr->E_name, head, s)) return (7);
2171 else if (buf[0] == 'E')
2173 /* Acquire the Text */
2176 /* Store the name */
2177 if (!add_name(&r_ptr->name, head, s)) return (7);
2180 /* Process 'D' for "Description" */
2181 else if (buf[0] == 'D')
2186 /* Acquire the text */
2191 /* Acquire the text */
2195 /* Store the text */
2196 if (!add_text(&r_ptr->text, head, s)) return (7);
2199 /* Process 'G' for "Graphics" (one line only) */
2200 else if (buf[0] == 'G')
2206 if (!buf[2]) return (1);
2207 if (!buf[3]) return (1);
2208 if (!buf[4]) return (1);
2210 /* Extract the char */
2213 /* Extract the attr */
2214 tmp = color_char_to_attr(buf[4]);
2217 if (tmp > 127) return (1);
2219 /* Save the values */
2220 r_ptr->d_char = sym;
2221 r_ptr->d_attr = tmp;
2224 /* Process 'I' for "Info" (one line only) */
2225 else if (buf[0] == 'I')
2227 int spd, hp1, hp2, aaf, ac, slp;
2229 /* Scan for the other values */
2230 if (6 != sscanf(buf+2, "%d:%dd%d:%d:%d:%d",
2231 &spd, &hp1, &hp2, &aaf, &ac, &slp)) return (1);
2233 /* Save the values */
2242 /* Process 'W' for "More Info" (one line only) */
2243 else if (buf[0] == 'W')
2250 /* Scan for the values */
2251 if (6 != sscanf(buf+2, "%d:%d:%d:%ld:%ld:%d",
2252 &lev, &rar, &pad, &exp, &nextexp, &nextmon)) return (1);
2254 /* Save the values */
2256 r_ptr->rarity = rar;
2259 r_ptr->next_exp = nextexp;
2260 r_ptr->next_r_idx = nextmon;
2263 /* Process 'B' for "Blows" (up to four lines) */
2264 else if (buf[0] == 'B')
2268 /* Find the next empty blow slot (if any) */
2269 for (i = 0; i < 4; i++) if (!r_ptr->blow[i].method) break;
2271 /* Oops, no more slots */
2272 if (i == 4) return (1);
2274 /* Analyze the first field */
2275 for (s = t = buf+2; *t && (*t != ':'); t++) /* loop */;
2277 /* Terminate the field (if necessary) */
2278 if (*t == ':') *t++ = '\0';
2280 /* Analyze the method */
2281 for (n1 = 0; r_info_blow_method[n1]; n1++)
2283 if (streq(s, r_info_blow_method[n1])) break;
2286 /* Invalid method */
2287 if (!r_info_blow_method[n1]) return (1);
2289 /* Analyze the second field */
2290 for (s = t; *t && (*t != ':'); t++) /* loop */;
2292 /* Terminate the field (if necessary) */
2293 if (*t == ':') *t++ = '\0';
2295 /* Analyze effect */
2296 for (n2 = 0; r_info_blow_effect[n2]; n2++)
2298 if (streq(s, r_info_blow_effect[n2])) break;
2301 /* Invalid effect */
2302 if (!r_info_blow_effect[n2]) return (1);
2304 /* Analyze the third field */
2305 for (s = t; *t && (*t != 'd'); t++) /* loop */;
2307 /* Terminate the field (if necessary) */
2308 if (*t == 'd') *t++ = '\0';
2310 /* Save the method */
2311 r_ptr->blow[i].method = n1;
2313 /* Save the effect */
2314 r_ptr->blow[i].effect = n2;
2316 /* Extract the damage dice and sides */
2317 r_ptr->blow[i].d_dice = atoi(s);
2318 r_ptr->blow[i].d_side = atoi(t);
2321 /* Process 'F' for "Basic Flags" (multiple lines) */
2322 else if (buf[0] == 'F')
2324 /* Parse every entry */
2325 for (s = buf + 2; *s; )
2327 /* Find the end of this entry */
2328 for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
2330 /* Nuke and skip any dividers */
2334 while (*t == ' ' || *t == '|') t++;
2337 /* Parse this entry */
2338 if (0 != grab_one_basic_flag(r_ptr, s)) return (5);
2340 /* Start the next entry */
2345 /* Process 'S' for "Spell Flags" (multiple lines) */
2346 else if (buf[0] == 'S')
2348 /* Parse every entry */
2349 for (s = buf + 2; *s; )
2351 /* Find the end of this entry */
2352 for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
2354 /* Nuke and skip any dividers */
2358 while ((*t == ' ') || (*t == '|')) t++;
2361 /* XXX XXX XXX Hack -- Read spell frequency */
2362 if (1 == sscanf(s, "1_IN_%d", &i))
2364 /* Extract a "frequency" */
2365 r_ptr->freq_spell = 100 / i;
2367 /* Start at next entry */
2374 /* Parse this entry */
2375 if (0 != grab_one_spell_flag(r_ptr, s)) return (5);
2377 /* Start the next entry */
2392 * Grab one flag for a dungeon type from a textual string
2394 static errr grab_one_dungeon_flag(dungeon_info_type *d_ptr, cptr what)
2399 for (i = 0; i < 32; i++)
2401 if (streq(what, d_info_flags1[i]))
2403 d_ptr->flags1 |= (1L << i);
2410 msg_format("̤ÃΤΥÀ¥ó¥¸¥ç¥ó¡¦¥Õ¥é¥° '%s'¡£", what);
2412 msg_format("Unknown dungeon type flag '%s'.", what);
2420 * Grab one (basic) flag in a monster_race from a textual string
2422 static errr grab_one_basic_monster_flag(dungeon_info_type *d_ptr, cptr what)
2427 for (i = 0; i < 32; i++)
2429 if (streq(what, r_info_flags1[i]))
2431 d_ptr->mflags1 |= (1L << i);
2437 for (i = 0; i < 32; i++)
2439 if (streq(what, r_info_flags2[i]))
2441 d_ptr->mflags2 |= (1L << i);
2447 for (i = 0; i < 32; i++)
2449 if (streq(what, r_info_flags3[i]))
2451 d_ptr->mflags3 |= (1L << i);
2457 for (i = 0; i < 32; i++)
2459 if (streq(what, r_info_flags7[i]))
2461 d_ptr->mflags7 |= (1L << i);
2467 for (i = 0; i < 32; i++)
2469 if (streq(what, r_info_flags8[i]))
2471 d_ptr->mflags8 |= (1L << i);
2477 for (i = 0; i < 32; i++)
2479 if (streq(what, r_info_flags9[i]))
2481 d_ptr->mflags9 |= (1L << i);
2488 msg_format("̤ÃΤΥâ¥ó¥¹¥¿¡¼¡¦¥Õ¥é¥° '%s'¡£", what);
2490 msg_format("Unknown monster flag '%s'.", what);
2498 * Grab one (spell) flag in a monster_race from a textual string
2500 static errr grab_one_spell_monster_flag(dungeon_info_type *d_ptr, cptr what)
2505 for (i = 0; i < 32; i++)
2507 if (streq(what, r_info_flags4[i]))
2509 d_ptr->mflags4 |= (1L << i);
2515 for (i = 0; i < 32; i++)
2517 if (streq(what, r_info_flags5[i]))
2519 d_ptr->mflags5 |= (1L << i);
2525 for (i = 0; i < 32; i++)
2527 if (streq(what, r_info_flags6[i]))
2529 d_ptr->mflags6 |= (1L << i);
2536 msg_format("̤ÃΤΥâ¥ó¥¹¥¿¡¼¡¦¥Õ¥é¥° '%s'¡£", what);
2538 msg_format("Unknown monster flag '%s'.", what);
2546 * Initialize the "d_info" array, by parsing an ascii "template" file
2548 errr parse_d_info(char *buf, header *head)
2555 static dungeon_info_type *d_ptr = NULL;
2558 /* Process 'N' for "New/Number/Name" */
2561 /* Find the colon before the name */
2562 s = strchr(buf+2, ':');
2564 /* Verify that colon */
2567 /* Nuke the colon, advance to the name */
2570 /* Paranoia -- require a name */
2571 if (!*s) return (1);
2576 /* Verify information */
2577 if (i < error_idx) return (4);
2579 /* Verify information */
2580 if (i >= head->info_num) return (2);
2582 /* Save the index */
2585 /* Point at the "info" */
2588 /* Store the name */
2589 if (!add_name(&d_ptr->name, head, s)) return (7);
2594 else if (buf[0] == 'E') return (0);
2596 else if (buf[0] == 'E')
2598 /* Acquire the Text */
2601 /* Store the name */
2602 if (!add_name(&d_ptr->name, head, s)) return (7);
2606 /* Process 'D' for "Description */
2607 else if (buf[0] == 'D')
2612 /* Acquire the text */
2617 /* Acquire the text */
2621 /* Store the text */
2622 if (!add_text(&d_ptr->text, head, s)) return (7);
2625 /* Process 'W' for "More Info" (one line only) */
2626 else if (buf[0] == 'W')
2628 int min_lev, max_lev;
2630 int min_alloc, max_chance;
2631 int obj_good, obj_great;
2634 /* Scan for the values */
2635 if (10 != sscanf(buf+2, "%d:%d:%d:%d:%d:%d:%d:%d:%x:%x",
2636 &min_lev, &max_lev, &min_plev, &mode, &min_alloc, &max_chance, &obj_good, &obj_great, (unsigned int *)&pit, (unsigned int *)&nest)) return (1);
2638 /* Save the values */
2639 d_ptr->mindepth = min_lev;
2640 d_ptr->maxdepth = max_lev;
2641 d_ptr->min_plev = min_plev;
2643 d_ptr->min_m_alloc_level = min_alloc;
2644 d_ptr->max_m_alloc_chance = max_chance;
2645 d_ptr->obj_good = obj_good;
2646 d_ptr->obj_great = obj_great;
2651 /* Process 'P' for "Place Info" */
2652 else if (buf[0] == 'P')
2656 /* Scan for the values */
2657 if (2 != sscanf(buf+2, "%d:%d", &dy, &dx)) return (1);
2659 /* Save the values */
2664 /* Process 'L' for "fLoor type" (one line only) */
2665 else if (buf[0] == 'L')
2671 /* Scan for the values */
2672 if (7 != sscanf(buf+2, "%d:%d:%d:%d:%d:%d:%d",
2673 &f1, &p1, &f2, &p2, &f3, &p3, &tunnel)) return (1);
2675 /* Save the values */
2677 d_ptr->floor_percent1 = p1;
2679 d_ptr->floor_percent2 = p2;
2681 d_ptr->floor_percent3 = p3;
2682 d_ptr->tunnel_percent = tunnel;
2685 /* Process 'A' for "wAll type" (one line only) */
2686 else if (buf[0] == 'A')
2688 int w1, w2, w3, outer, inner, stream1, stream2;
2691 /* Scan for the values */
2692 if (10 != sscanf(buf+2, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
2693 &w1, &p1, &w2, &p2, &w3, &p3, &outer, &inner, &stream1, &stream2)) return (1);
2695 /* Save the values */
2696 d_ptr->fill_type1 = w1;
2697 d_ptr->fill_percent1 = p1;
2698 d_ptr->fill_type2 = w2;
2699 d_ptr->fill_percent2 = p2;
2700 d_ptr->fill_type3 = w3;
2701 d_ptr->fill_percent3 = p3;
2702 d_ptr->outer_wall = outer;
2703 d_ptr->inner_wall = inner;
2704 d_ptr->stream1 = stream1;
2705 d_ptr->stream2 = stream2;
2708 /* Process 'F' for "Dungeon Flags" (multiple lines) */
2709 else if (buf[0] == 'F')
2711 int artif = 0, monst = 0;
2713 /* Parse every entry */
2714 for (s = buf + 2; *s; )
2716 /* Find the end of this entry */
2717 for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
2719 /* Nuke and skip any dividers */
2723 while (*t == ' ' || *t == '|') t++;
2726 /* XXX XXX XXX Hack -- Read Final Artifact */
2727 if (1 == sscanf(s, "FINAL_ARTIFACT_%d", &artif))
2729 /* Extract a "Final Artifact" */
2730 d_ptr->final_artifact = artif;
2732 /* Start at next entry */
2739 /* XXX XXX XXX Hack -- Read Final Object */
2740 if (1 == sscanf(s, "FINAL_OBJECT_%d", &artif))
2742 /* Extract a "Final Artifact" */
2743 d_ptr->final_object = artif;
2745 /* Start at next entry */
2752 /* XXX XXX XXX Hack -- Read Artifact Guardian */
2753 if (1 == sscanf(s, "FINAL_GUARDIAN_%d", &monst))
2755 /* Extract a "Artifact Guardian" */
2756 d_ptr->final_guardian = monst;
2758 /* Start at next entry */
2765 /* XXX XXX XXX Hack -- Read Special Percentage */
2766 if (1 == sscanf(s, "MONSTER_DIV_%d", &monst))
2768 /* Extract a "Special %" */
2769 d_ptr->special_div = monst;
2771 /* Start at next entry */
2778 /* Parse this entry */
2779 if (0 != grab_one_dungeon_flag(d_ptr, s)) return (5);
2781 /* Start the next entry */
2786 /* Process 'M' for "Basic Flags" (multiple lines) */
2787 else if (buf[0] == 'M')
2789 /* Parse every entry */
2790 for (s = buf + 2; *s; )
2792 /* Find the end of this entry */
2793 for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
2795 /* Nuke and skip any dividers */
2799 while (*t == ' ' || *t == '|') t++;
2802 /* Hack -- Read monster symbols */
2803 if (!strncmp(s, "R_CHAR_", 7))
2805 /* Skip "R_CHAR_" */
2809 strncpy(d_ptr->r_char, s, sizeof(d_ptr->r_char));
2811 /* Start at next entry */
2818 /* Parse this entry */
2819 if (0 != grab_one_basic_monster_flag(d_ptr, s)) return (5);
2821 /* Start the next entry */
2826 /* Process 'S' for "Spell Flags" (multiple lines) */
2827 else if (buf[0] == 'S')
2829 /* Parse every entry */
2830 for (s = buf + 2; *s; )
2832 /* Find the end of this entry */
2833 for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
2835 /* Nuke and skip any dividers */
2839 while ((*t == ' ') || (*t == '|')) t++;
2842 /* XXX XXX XXX Hack -- Read spell frequency */
2843 if (1 == sscanf(s, "1_IN_%d", &i))
2845 /* Start at next entry */
2852 /* Parse this entry */
2853 if (0 != grab_one_spell_monster_flag(d_ptr, s)) return (5);
2855 /* Start the next entry */
2868 #else /* ALLOW_TEMPLATES */
2874 #endif /* ALLOW_TEMPLATES */
2877 /* Random dungeon grid effects */
2878 #define RANDOM_NONE 0x00
2879 #define RANDOM_FEATURE 0x01
2880 #define RANDOM_MONSTER 0x02
2881 #define RANDOM_OBJECT 0x04
2882 #define RANDOM_EGO 0x08
2883 #define RANDOM_ARTIFACT 0x10
2884 #define RANDOM_TRAP 0x20
2887 typedef struct dungeon_grid dungeon_grid;
2891 int feature; /* Terrain feature */
2892 int monster; /* Monster */
2893 int object; /* Object */
2894 int ego; /* Ego-Item */
2895 int artifact; /* Artifact */
2896 int trap; /* Trap */
2897 int cave_info; /* Flags for CAVE_MARK, CAVE_GLOW, CAVE_ICKY, CAVE_ROOM */
2898 int special; /* Reserved for special terrain info */
2899 int random; /* Number of the random effect */
2903 static dungeon_grid letter[255];
2907 * Process "F:<letter>:<terrain>:<cave_info>:<monster>:<object>:<ego>:<artifact>:<trap>:<special>" -- info for dungeon grid
2909 static errr parse_line_feature(char *buf)
2915 if (init_flags & INIT_ONLY_BUILDINGS) return (0);
2917 /* Tokenize the line */
2918 if ((num = tokenize(buf+2, 9, zz, 0)) > 1)
2920 /* Letter to assign */
2921 int index = zz[0][0];
2923 /* Reset the info for the letter */
2924 letter[index].feature = 0;
2925 letter[index].monster = 0;
2926 letter[index].object = 0;
2927 letter[index].ego = 0;
2928 letter[index].artifact = 0;
2929 letter[index].trap = 0;
2930 letter[index].cave_info = 0;
2931 letter[index].special = 0;
2932 letter[index].random = 0;
2938 letter[index].special = atoi(zz[8]);
2942 if (zz[7][0] == '*')
2944 letter[index].random |= RANDOM_TRAP;
2949 letter[index].trap = atoi(zz[7]);
2954 letter[index].trap = atoi(zz[7]);
2959 if (zz[6][0] == '*')
2961 letter[index].random |= RANDOM_ARTIFACT;
2966 letter[index].artifact = atoi(zz[6]);
2971 letter[index].artifact = atoi(zz[6]);
2976 if (zz[5][0] == '*')
2978 letter[index].random |= RANDOM_EGO;
2983 letter[index].ego = atoi(zz[5]);
2988 letter[index].ego = atoi(zz[5]);
2993 if (zz[4][0] == '*')
2995 letter[index].random |= RANDOM_OBJECT;
3000 letter[index].object = atoi(zz[4]);
3005 letter[index].object = atoi(zz[4]);
3010 if (zz[3][0] == '*')
3012 letter[index].random |= RANDOM_MONSTER;
3016 letter[index].monster = atoi(zz[3]);
3019 else if (zz[3][0] == 'c')
3021 letter[index].monster = - atoi(zz[3]+1);
3025 letter[index].monster = atoi(zz[3]);
3030 letter[index].cave_info = atoi(zz[2]);
3034 if (zz[1][0] == '*')
3036 letter[index].random |= RANDOM_FEATURE;
3040 letter[index].feature = atoi(zz[1]);
3045 letter[index].feature = atoi(zz[1]);
3058 * Process "F:<letter>:<terrain>:<cave_info>:<monster>:<object>:<ego>:<artifact>:<trap>:<special>" -- info for dungeon grid
3060 static errr parse_line_building(char *buf)
3076 /* Get the building number */
3079 /* Find the colon after the building number */
3082 /* Verify that colon */
3085 /* Nuke the colon, advance to the sub-index */
3088 /* Paranoia -- require a sub-index */
3089 if (!*s) return (1);
3091 /* Building definition sub-index */
3094 /* Building name, owner, race */
3097 if (tokenize(s + 2, 3, zz, 0) == 3)
3099 /* Name of the building */
3100 strcpy(building[index].name, zz[0]);
3102 /* Name of the owner */
3103 strcpy(building[index].owner_name, zz[1]);
3105 /* Race of the owner */
3106 strcpy(building[index].owner_race, zz[2]);
3111 return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3114 /* Building Action */
3117 if (tokenize(s + 2, 8, zz, 0) >= 7)
3119 /* Index of the action */
3120 int action_index = atoi(zz[0]);
3122 /* Name of the action */
3123 strcpy(building[index].act_names[action_index], zz[1]);
3125 /* Cost of the action for members */
3126 building[index].member_costs[action_index] = atoi(zz[2]);
3128 /* Cost of the action for non-members */
3129 building[index].other_costs[action_index] = atoi(zz[3]);
3131 /* Letter assigned to the action */
3132 building[index].letters[action_index] = zz[4][0];
3135 building[index].actions[action_index] = atoi(zz[5]);
3137 /* Action restriction */
3138 building[index].action_restr[action_index] = atoi(zz[6]);
3143 return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3146 /* Building Classes */
3149 if (tokenize(s + 2, MAX_CLASS, zz, 0) == MAX_CLASS)
3151 for (i = 0; i < MAX_CLASS; i++)
3153 building[index].member_class[i] = atoi(zz[i]);
3159 return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3162 /* Building Races */
3165 if (tokenize(s+2, MAX_RACES, zz, 0) == MAX_RACES)
3167 for (i = 0; i < MAX_RACES; i++)
3169 building[index].member_race[i] = atoi(zz[i]);
3175 return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3178 /* Building Realms */
3181 if (tokenize(s+2, MAX_MAGIC, zz, 0) == MAX_MAGIC)
3183 for (i = 0; i < MAX_MAGIC; i++)
3185 building[index].member_realm[i+1] = atoi(zz[i]);
3191 return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3196 /* Ignore scripts */
3202 return (PARSE_ERROR_UNDEFINED_DIRECTIVE);
3211 * Parse a sub-file of the "extra info"
3213 static errr process_dungeon_file_aux(char *buf, int ymin, int xmin, int ymax, int xmax, int *y, int *x)
3220 /* Skip "empty" lines */
3221 if (!buf[0]) return (0);
3223 /* Skip "blank" lines */
3224 if (isspace(buf[0])) return (0);
3227 if (buf[0] == '#') return (0);
3229 /* Require "?:*" format */
3230 if (buf[1] != ':') return (1);
3233 /* Process "%:<fname>" */
3236 /* Attempt to Process the given file */
3237 return (process_dungeon_file(buf + 2, ymin, xmin, ymax, xmax));
3240 /* Process "F:<letter>:<terrain>:<cave_info>:<monster>:<object>:<ego>:<artifact>:<trap>:<special>" -- info for dungeon grid */
3243 return parse_line_feature(buf);
3246 /* Process "D:<dungeon>" -- info for the cave grids */
3247 else if (buf[0] == 'D')
3249 object_type object_type_body;
3251 /* Acquire the text */
3254 /* Length of the text */
3255 int len = strlen(s);
3257 if (init_flags & INIT_ONLY_BUILDINGS) return (0);
3259 for (*x = xmin, i = 0; ((*x < xmax) && (i < len)); (*x)++, s++, i++)
3261 /* Access the grid */
3262 cave_type *c_ptr = &cave[*y][*x];
3266 int object_index = letter[idx].object;
3267 int monster_index = letter[idx].monster;
3268 int random = letter[idx].random;
3269 int artifact_index = letter[idx].artifact;
3271 /* Lay down a floor */
3272 c_ptr->feat = letter[idx].feature;
3274 /* Only the features */
3275 if (init_flags & INIT_ONLY_FEATURES) continue;
3278 c_ptr->info = letter[idx].cave_info;
3280 /* Create a monster */
3281 if (random & RANDOM_MONSTER)
3283 monster_level = base_level + monster_index;
3285 place_monster(*y, *x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
3287 monster_level = base_level;
3289 else if (monster_index)
3291 int old_cur_num, old_max_num;
3294 if (monster_index < 0)
3296 monster_index = -monster_index;
3299 old_cur_num = r_info[monster_index].cur_num;
3300 old_max_num = r_info[monster_index].max_num;
3302 /* Make alive again */
3303 if (r_info[monster_index].flags1 & RF1_UNIQUE)
3305 r_info[monster_index].cur_num = 0;
3306 r_info[monster_index].max_num = 1;
3309 /* Make alive again */
3310 if (r_info[monster_index].flags7 & RF7_UNIQUE_7)
3312 if (r_info[monster_index].cur_num == r_info[monster_index].max_num)
3314 r_info[monster_index].max_num++;
3319 place_monster_aux(0, *y, *x, monster_index, (PM_ALLOW_SLEEP | PM_NO_KAGE));
3323 m_list[hack_m_idx_ii].smart |= SM_CLONED;
3325 /* Make alive again for real unique monster */
3326 r_info[monster_index].cur_num = old_cur_num;
3327 r_info[monster_index].max_num = old_max_num;
3331 /* Object (and possible trap) */
3332 if ((random & RANDOM_OBJECT) && (random & RANDOM_TRAP))
3334 object_level = base_level + object_index;
3337 * Random trap and random treasure defined
3338 * 25% chance for trap and 75% chance for object
3340 if (randint0(100) < 75)
3342 place_object(*y, *x, FALSE, FALSE);
3349 object_level = base_level;
3351 else if (random & RANDOM_OBJECT)
3353 object_level = base_level + object_index;
3355 /* Create an out of deep object */
3356 if (randint0(100) < 75)
3357 place_object(*y, *x, FALSE, FALSE);
3358 else if (randint0(100) < 80)
3359 place_object(*y, *x, TRUE, FALSE);
3361 place_object(*y, *x, TRUE, TRUE);
3363 object_level = base_level;
3366 else if (random & RANDOM_TRAP)
3370 /* Hidden trap (or door) */
3371 else if (letter[idx].trap)
3373 c_ptr->mimic = c_ptr->feat;
3374 c_ptr->feat = letter[idx].trap;
3376 else if (object_index)
3378 /* Get local object */
3379 object_type *o_ptr = &object_type_body;
3381 /* Create the item */
3382 object_prep(o_ptr, object_index);
3384 if (o_ptr->tval == TV_GOLD)
3386 coin_type = object_index - OBJ_GOLD_LIST;
3391 /* Apply magic (no messages, no artifacts) */
3392 apply_magic(o_ptr, base_level, FALSE, TRUE, FALSE, FALSE);
3394 (void)drop_near(o_ptr, -1, *y, *x);
3400 if (a_info[artifact_index].cur_num)
3404 object_type *q_ptr = &forge;
3406 object_prep(q_ptr, k_idx);
3408 /* Drop it in the dungeon */
3409 (void)drop_near(q_ptr, -1, *y, *x);
3413 /* Create the artifact */
3414 create_named_art(artifact_index, *y, *x);
3416 a_info[artifact_index].cur_num = 1;
3420 /* Terrain special */
3421 c_ptr->special = letter[idx].special;
3429 /* Process "Q:<number>:<command>:... -- quest info */
3430 else if (buf[0] == 'Q')
3437 num = tokenize(buf + 2, 33, zz, 0);
3441 num = tokenize(buf + 3, 33, zz, 0);
3444 /* Have we enough parameters? */
3445 if (num < 3) return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3448 q_ptr = &(quest[atoi(zz[0])]);
3450 /* Process "Q:<q_index>:Q:<type>:<num_mon>:<cur_num>:<max_num>:<level>:<r_idx>:<k_idx>:<flags>" -- quest info */
3451 if (zz[1][0] == 'Q')
3453 if (init_flags & INIT_ASSIGN)
3455 monster_race *r_ptr;
3456 artifact_type *a_ptr;
3458 if (num < 9) return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3460 q_ptr->type = atoi(zz[2]);
3461 q_ptr->num_mon = atoi(zz[3]);
3462 q_ptr->cur_num = atoi(zz[4]);
3463 q_ptr->max_num = atoi(zz[5]);
3464 q_ptr->level = atoi(zz[6]);
3465 q_ptr->r_idx = atoi(zz[7]);
3466 q_ptr->k_idx = atoi(zz[8]);
3467 q_ptr->dungeon = atoi(zz[9]);
3470 q_ptr->flags = atoi(zz[10]);
3472 r_ptr = &r_info[q_ptr->r_idx];
3473 if (r_ptr->flags1 & RF1_UNIQUE)
3474 r_ptr->flags1 |= RF1_QUESTOR;
3476 a_ptr = &a_info[q_ptr->k_idx];
3477 a_ptr->gen_flags |= TRG_QUESTITEM;
3482 /* Process "Q:<q_index>:N:<name>" -- quest name */
3483 else if (zz[1][0] == 'N')
3485 if (init_flags & (INIT_ASSIGN | INIT_SHOW_TEXT))
3487 strcpy(q_ptr->name, zz[2]);
3493 /* Process "Q:<q_index>:T:<text>" -- quest description line */
3494 else if (zz[1][0] == 'T')
3496 if (init_flags & INIT_SHOW_TEXT)
3498 strcpy(quest_text[quest_text_line], zz[2]);
3506 /* Process "W:<command>: ..." -- info for the wilderness */
3507 else if (buf[0] == 'W')
3509 return parse_line_wilderness(buf, ymin, xmin, ymax, xmax, y, x);
3512 /* Process "P:<y>:<x>" -- player position */
3513 else if (buf[0] == 'P')
3515 if (init_flags & INIT_CREATE_DUNGEON)
3517 if (tokenize(buf + 2, 2, zz, 0) == 2)
3519 int panels_x, panels_y;
3521 /* Hack - Set the dungeon size */
3522 panels_y = (*y / SCREEN_HGT);
3523 if (*y % SCREEN_HGT) panels_y++;
3524 cur_hgt = panels_y * SCREEN_HGT;
3526 panels_x = (*x / SCREEN_WID);
3527 if (*x % SCREEN_WID) panels_x++;
3528 cur_wid = panels_x * SCREEN_WID;
3530 /* Assume illegal panel */
3531 panel_row_min = cur_hgt;
3532 panel_col_min = cur_wid;
3534 /* Place player in a quest level */
3535 if (p_ptr->inside_quest)
3539 /* Delete the monster (if any) */
3540 delete_monster(py, px);
3548 /* Place player in the town */
3549 else if (!p_ptr->oldpx && !p_ptr->oldpy)
3551 p_ptr->oldpy = atoi(zz[0]);
3552 p_ptr->oldpx = atoi(zz[1]);
3560 /* Process "B:<Index>:<Command>:..." -- Building definition */
3561 else if (buf[0] == 'B')
3563 return parse_line_building(buf);
3566 /* Process "M:<type>:<maximum>" -- set maximum values */
3567 else if (buf[0] == 'M')
3569 if (tokenize(buf+2, 2, zz, 0) == 2)
3572 if (zz[0][0] == 'T')
3574 max_towns = atoi(zz[1]);
3577 /* Maximum quests */
3578 else if (zz[0][0] == 'Q')
3580 max_quests = atoi(zz[1]);
3584 else if (zz[0][0] == 'R')
3586 max_r_idx = atoi(zz[1]);
3590 else if (zz[0][0] == 'K')
3592 max_k_idx = atoi(zz[1]);
3596 else if (zz[0][0] == 'V')
3598 max_v_idx = atoi(zz[1]);
3602 else if (zz[0][0] == 'F')
3604 max_f_idx = atoi(zz[1]);
3608 else if (zz[0][0] == 'A')
3610 max_a_idx = atoi(zz[1]);
3614 else if (zz[0][0] == 'E')
3616 max_e_idx = atoi(zz[1]);
3620 else if (zz[0][0] == 'D')
3622 max_d_idx = atoi(zz[1]);
3626 else if (zz[0][0] == 'O')
3628 max_o_idx = atoi(zz[1]);
3632 else if (zz[0][0] == 'M')
3634 max_m_idx = atoi(zz[1]);
3637 /* Wilderness size */
3638 else if (zz[0][0] == 'W')
3640 /* Maximum wild_x_size */
3641 if (zz[0][1] == 'X')
3642 max_wild_x = atoi(zz[1]);
3643 /* Maximum wild_y_size */
3644 if (zz[0][1] == 'Y')
3645 max_wild_y = atoi(zz[1]);
3659 static cptr variant = "ZANGBAND";
3663 * Helper function for "process_dungeon_file()"
3665 static cptr process_dungeon_file_expr(char **sp, char *fp)
3681 while (isspace(*s)) s++;
3699 t = process_dungeon_file_expr(&s, &f);
3708 else if (streq(t, "IOR"))
3711 while (*s && (f != b2))
3713 t = process_dungeon_file_expr(&s, &f);
3714 if (*t && !streq(t, "0")) v = "1";
3719 else if (streq(t, "AND"))
3722 while (*s && (f != b2))
3724 t = process_dungeon_file_expr(&s, &f);
3725 if (*t && streq(t, "0")) v = "0";
3730 else if (streq(t, "NOT"))
3733 while (*s && (f != b2))
3735 t = process_dungeon_file_expr(&s, &f);
3736 if (*t && streq(t, "1")) v = "0";
3741 else if (streq(t, "EQU"))
3744 if (*s && (f != b2))
3746 t = process_dungeon_file_expr(&s, &f);
3748 while (*s && (f != b2))
3751 t = process_dungeon_file_expr(&s, &f);
3752 if (*t && !streq(p, t)) v = "0";
3757 else if (streq(t, "LEQ"))
3760 if (*s && (f != b2))
3762 t = process_dungeon_file_expr(&s, &f);
3764 while (*s && (f != b2))
3767 t = process_dungeon_file_expr(&s, &f);
3768 if (*t && (strcmp(p, t) > 0)) v = "0";
3773 else if (streq(t, "GEQ"))
3776 if (*s && (f != b2))
3778 t = process_dungeon_file_expr(&s, &f);
3780 while (*s && (f != b2))
3783 t = process_dungeon_file_expr(&s, &f);
3784 if (*t && (strcmp(p, t) < 0)) v = "0";
3791 while (*s && (f != b2))
3793 t = process_dungeon_file_expr(&s, &f);
3798 if (f != b2) v = "?x?x?";
3800 /* Extract final and Terminate */
3801 if ((f = *s) != '\0') *s++ = '\0';
3807 /* Accept all printables except spaces and brackets */
3808 while (isprint(*s) && !strchr(" []", *s)) ++s;
3810 /* Extract final and Terminate */
3811 if ((f = *s) != '\0') *s++ = '\0';
3817 if (streq(b+1, "SYS"))
3823 else if (streq(b+1, "GRAF"))
3828 else if (streq(b+1, "MONOCHROME"))
3837 else if (streq(b+1, "RACE"))
3840 v = rp_ptr->E_title;
3847 else if (streq(b+1, "CLASS"))
3850 v = cp_ptr->E_title;
3857 else if (streq(b+1, "REALM1"))
3860 v = E_realm_names[p_ptr->realm1];
3862 v = realm_names[p_ptr->realm1];
3867 else if (streq(b+1, "REALM2"))
3870 v = E_realm_names[p_ptr->realm2];
3872 v = realm_names[p_ptr->realm2];
3877 else if (streq(b+1, "PLAYER"))
3883 else if (streq(b+1, "TOWN"))
3885 sprintf(tmp, "%d", p_ptr->town_num);
3890 else if (streq(b+1, "LEVEL"))
3892 sprintf(tmp, "%d", p_ptr->lev);
3896 /* Current quest number */
3897 else if (streq(b+1, "QUEST_NUMBER"))
3899 sprintf(tmp, "%d", p_ptr->inside_quest);
3903 /* Number of last quest */
3904 else if (streq(b+1, "LEAVING_QUEST"))
3906 sprintf(tmp, "%d", leaving_quest);
3911 else if (prefix(b+1, "QUEST"))
3913 /* "QUEST" uses a special parameter to determine the number of the quest */
3914 sprintf(tmp, "%d", quest[atoi(b+6)].status);
3919 else if (prefix(b+1, "RANDOM"))
3921 /* "RANDOM" uses a special parameter to determine the number of the quest */
3922 sprintf(tmp, "%d", (int)(seed_town%atoi(b+7)));
3927 else if (streq(b+1, "VARIANT"))
3933 else if (streq(b+1, "WILDERNESS"))
3936 sprintf(tmp, "NONE");
3938 sprintf(tmp, "LITE");
3940 sprintf(tmp, "NORMAL");
3963 errr process_dungeon_file(cptr name, int ymin, int xmin, int ymax, int xmax)
3973 bool bypass = FALSE;
3975 int x = xmin, y = ymin;
3978 /* Build the filename */
3979 path_build(buf, sizeof(buf), ANGBAND_DIR_EDIT, name);
3982 fp = my_fopen(buf, "r");
3985 if (!fp) return (-1);
3988 /* Process the file */
3989 while (0 == my_fgets(fp, buf, sizeof(buf)))
3995 /* Skip "empty" lines */
3996 if (!buf[0]) continue;
3998 /* Skip "blank" lines */
3999 if (isspace(buf[0])) continue;
4002 if (buf[0] == '#') continue;
4005 /* Process "?:<expr>" */
4006 if ((buf[0] == '?') && (buf[1] == ':'))
4015 /* Parse the expr */
4016 v = process_dungeon_file_expr(&s, &f);
4019 bypass = (streq(v, "0") ? TRUE : FALSE);
4025 /* Apply conditionals */
4026 if (bypass) continue;
4028 /* Process the line */
4029 err = process_dungeon_file_aux(buf, ymin, xmin, ymax, xmax, &y, &x);
4041 oops = (((err > 0) && (err < PARSE_ERROR_MAX)) ? err_str[err] : "unknown");
4044 msg_format("Error %d (%s) at line %d of '%s'.", err, oops, num, name);
4046 msg_format("'%s'¤ò²òÀÏÃæ¡£", buf);
4048 msg_format("Parsing '%s'.", buf);
4055 /* Close the file */
4065 void write_r_info_txt(void)
4067 int i, j, z, fc, bc;
4075 monster_race *r_ptr;
4077 monster_blow *b_ptr;
4079 FILE *fff = fopen("output.txt", "wt");
4087 fprintf(fff, "# File: r_info.txt (autogenerated)\n\n");
4089 fprintf(fff, "# Version stamp (required)\n\n");
4092 fprintf(fff, "V:%d.%d.%d\n\n\n", r_head->v_major, r_head->v_minor, r_head->v_patch);
4095 fprintf(fff, "##### The Player #####\n\n");
4097 for (z = -1; z < alloc_race_size; z++)
4099 /* Output the monsters in order */
4100 i = (z >= 0) ? alloc_race_table[z].index : 0;
4102 /* Acquire the monster */
4105 /* Ignore empty monsters */
4106 if (!strlen(r_name + r_ptr->name)) continue;
4108 /* Ignore useless monsters */
4109 if (i && !r_ptr->speed) continue;
4111 /* Write a note if necessary */
4112 if (i && (!r_ptr->level != !mode))
4117 fprintf(fff, "\n##### Town monsters #####\n\n");
4119 /* Note the dungeon */
4122 fprintf(fff, "\n##### Normal monsters #####\n\n");
4125 /* Record the change */
4126 mode = r_ptr->level;
4129 /* Acquire the flags */
4130 f_ptr[0] = r_ptr->flags1; n_ptr[0] = r_info_flags1;
4131 f_ptr[1] = r_ptr->flags2; n_ptr[1] = r_info_flags2;
4132 f_ptr[2] = r_ptr->flags3; n_ptr[2] = r_info_flags3;
4133 f_ptr[3] = r_ptr->flags4; n_ptr[3] = r_info_flags4;
4134 f_ptr[4] = r_ptr->flags5; n_ptr[4] = r_info_flags5;
4135 f_ptr[5] = r_ptr->flags6; n_ptr[5] = r_info_flags6;
4136 f_ptr[6] = r_ptr->flags7; n_ptr[6] = r_info_flags7;
4137 f_ptr[7] = r_ptr->flags8; n_ptr[7] = r_info_flags8;
4138 f_ptr[8] = r_ptr->flags9; n_ptr[8] = r_info_flags9;
4140 /* Write New/Number/Name */
4141 fprintf(fff, "N:%d:%s\n", z + 1, r_name + r_ptr->name);
4144 fprintf(fff, "G:%c:%c\n", r_ptr->d_char, color_char[r_ptr->d_attr]);
4146 /* Write Information */
4147 fprintf(fff, "I:%d:%dd%d:%d:%d:%d\n", r_ptr->speed, r_ptr->hdice, r_ptr->hside,
4148 r_ptr->aaf, r_ptr->ac, r_ptr->sleep);
4150 /* Write more information */
4151 fprintf(fff, "W:%d:%d:%d:%ld\n", r_ptr->level, r_ptr->rarity, r_ptr->extra, r_ptr->mexp);
4154 for(j = 0; j < 4; j++)
4156 b_ptr = &(r_ptr->blow[j]);
4158 /* Stop when done */
4159 if (!b_ptr->method) break;
4161 /* Write the blows */
4162 fprintf(fff, "B:%s:%s:%dd%d\n", r_info_blow_method[b_ptr->method],
4163 r_info_blow_effect[b_ptr->effect],
4164 b_ptr->d_dice, b_ptr->d_side);
4167 /* Extract the flags */
4168 for (fc = 0, j = 0; j < 96; j++)
4170 /* Check this flag */
4171 if (f_ptr[j / 32] & (1L << (j % 32))) flags[fc++] = n_ptr[j / 32][j % 32];
4174 /* Extract the extra flags */
4175 for (j = 192; j < 288; j++)
4177 /* Check this flag */
4178 if (f_ptr[j / 32] & (1L << (j % 32))) flags[fc++] = n_ptr[j / 32][j % 32];
4181 /* Write the flags */
4182 for (j = 0; j < fc;)
4186 /* Start the line */
4189 for (bc = 0; (bc < 60) && (j < fc); j++)
4193 /* Format the flag */
4194 sprintf(t, "%s%s", flags[j], (j < fc - 1) ? " | " : "");
4196 /* Add it to the buffer */
4199 /* Note the length */
4203 /* Done with this line; write it */
4204 fprintf(fff, "%s\n", buf);
4207 /* Write Spells if applicable */
4208 if (r_ptr->freq_spell)
4210 /* Write the frequency */
4211 fprintf(fff, "S:1_IN_%d | \n", 100 / r_ptr->freq_spell);
4213 /* Extract the spell flags */
4214 for (fc = 0, j = 96; j < 192; j++)
4216 /* Check this flag */
4217 if (f_ptr[j / 32] & (1L << (j % 32))) flags[fc++] = n_ptr[j / 32][j % 32];
4220 /* Write the flags */
4221 for (j = 0; j < fc;)
4225 /* Start the line */
4228 for (bc = 0, t = buf + 2; (bc < 60) && (j < fc); j++)
4232 /* Format the flag */
4233 sprintf(t, "%s%s", flags[j], (j < fc - 1) ? " | " : "");
4237 /* Note the length */
4244 /* Done with this line; write it */
4245 fprintf(fff, "%s\n", buf);
4249 /* Acquire the description */
4250 desc = r_text + r_ptr->text;
4251 dlen = strlen(desc);
4253 /* Write Description */
4254 for (j = 0; j < dlen;)
4258 /* Start the line */
4261 for (bc = 0, t = buf + 2; ((bc < 60) || !isspace(desc[j])) && (j < dlen); j++, bc++, t++)
4269 /* Done with this line; write it */
4270 fprintf(fff, "%s\n", buf);
4273 /* Space between entries */