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);
1218 /* Process 'D' for "Description" */
1219 else if (buf[0] == 'D')
1221 /* Acquire the text */
1224 /* Store the text */
1225 if (!add_text(&f_ptr->text, 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 = r_ptr->freq_inate = 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 byte r_char_number = 0, r_char;
2791 /* Parse every entry */
2792 for (s = buf + 2; *s; )
2794 /* Find the end of this entry */
2795 for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
2797 /* Nuke and skip any dividers */
2801 while (*t == ' ' || *t == '|') t++;
2804 /* XXX XXX XXX Hack -- Read monster symbols */
2805 if (1 == sscanf(s, "R_CHAR_%c", &r_char))
2807 /* Limited to 5 races */
2808 if(r_char_number >= 5) continue;
2810 /* Extract a "frequency" */
2811 d_ptr->r_char[r_char_number++] = r_char;
2813 /* Start at next entry */
2820 /* Parse this entry */
2821 if (0 != grab_one_basic_monster_flag(d_ptr, s)) return (5);
2823 /* Start the next entry */
2828 /* Process 'S' for "Spell Flags" (multiple lines) */
2829 else if (buf[0] == 'S')
2831 /* Parse every entry */
2832 for (s = buf + 2; *s; )
2834 /* Find the end of this entry */
2835 for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
2837 /* Nuke and skip any dividers */
2841 while ((*t == ' ') || (*t == '|')) t++;
2844 /* XXX XXX XXX Hack -- Read spell frequency */
2845 if (1 == sscanf(s, "1_IN_%d", &i))
2847 /* Start at next entry */
2854 /* Parse this entry */
2855 if (0 != grab_one_spell_monster_flag(d_ptr, s)) return (5);
2857 /* Start the next entry */
2870 #else /* ALLOW_TEMPLATES */
2876 #endif /* ALLOW_TEMPLATES */
2879 /* Random dungeon grid effects */
2880 #define RANDOM_NONE 0x00
2881 #define RANDOM_FEATURE 0x01
2882 #define RANDOM_MONSTER 0x02
2883 #define RANDOM_OBJECT 0x04
2884 #define RANDOM_EGO 0x08
2885 #define RANDOM_ARTIFACT 0x10
2886 #define RANDOM_TRAP 0x20
2887 #define RANDOM_HIDDEN_DOOR 0x40
2890 typedef struct dungeon_grid dungeon_grid;
2894 int feature; /* Terrain feature */
2895 int monster; /* Monster */
2896 int object; /* Object */
2897 int ego; /* Ego-Item */
2898 int artifact; /* Artifact */
2899 int trap; /* Trap */
2900 int cave_info; /* Flags for CAVE_MARK, CAVE_GLOW, CAVE_ICKY, CAVE_ROOM */
2901 int special; /* Reserved for special terrain info */
2902 int random; /* Number of the random effect */
2906 static dungeon_grid letter[255];
2910 * Process "F:<letter>:<terrain>:<cave_info>:<monster>:<object>:<ego>:<artifact>:<trap>:<special>" -- info for dungeon grid
2912 static errr parse_line_feature(char *buf)
2918 if (init_flags & INIT_ONLY_BUILDINGS) return (0);
2920 /* Tokenize the line */
2921 if ((num = tokenize(buf+2, 9, zz, 0)) > 1)
2923 /* Letter to assign */
2924 int index = zz[0][0];
2926 /* Reset the info for the letter */
2927 letter[index].feature = 0;
2928 letter[index].monster = 0;
2929 letter[index].object = 0;
2930 letter[index].ego = 0;
2931 letter[index].artifact = 0;
2932 letter[index].trap = 0;
2933 letter[index].cave_info = 0;
2934 letter[index].special = 0;
2935 letter[index].random = 0;
2941 letter[index].special = atoi(zz[8]);
2945 if (zz[7][0] == '*')
2947 letter[index].random |= RANDOM_TRAP;
2952 letter[index].trap = atoi(zz[7]);
2957 letter[index].trap = atoi(zz[7]);
2962 if (zz[6][0] == '*')
2964 letter[index].random |= RANDOM_ARTIFACT;
2969 letter[index].artifact = atoi(zz[6]);
2974 letter[index].artifact = atoi(zz[6]);
2979 if (zz[5][0] == '*')
2981 letter[index].random |= RANDOM_EGO;
2986 letter[index].ego = atoi(zz[5]);
2991 letter[index].ego = atoi(zz[5]);
2996 if (zz[4][0] == '*')
2998 letter[index].random |= RANDOM_OBJECT;
3003 letter[index].object = atoi(zz[4]);
3008 letter[index].object = atoi(zz[4]);
3013 if (zz[3][0] == '*')
3015 letter[index].random |= RANDOM_MONSTER;
3019 letter[index].monster = atoi(zz[3]);
3022 else if (zz[3][0] == 'c')
3024 letter[index].monster = - atoi(zz[3]+1);
3028 letter[index].monster = atoi(zz[3]);
3033 letter[index].cave_info = atoi(zz[2]);
3037 if (zz[1][0] == '*')
3039 letter[index].random |= RANDOM_FEATURE;
3043 letter[index].feature = atoi(zz[1]);
3046 else if (zz[1][0] == '+')
3048 letter[index].random |= RANDOM_HIDDEN_DOOR;
3052 letter[index].feature = atoi(zz[1]);
3057 letter[index].feature = atoi(zz[1]);
3070 * Process "F:<letter>:<terrain>:<cave_info>:<monster>:<object>:<ego>:<artifact>:<trap>:<special>" -- info for dungeon grid
3072 static errr parse_line_building(char *buf)
3088 /* Get the building number */
3091 /* Find the colon after the building number */
3094 /* Verify that colon */
3097 /* Nuke the colon, advance to the sub-index */
3100 /* Paranoia -- require a sub-index */
3101 if (!*s) return (1);
3103 /* Building definition sub-index */
3106 /* Building name, owner, race */
3109 if (tokenize(s + 2, 3, zz, 0) == 3)
3111 /* Name of the building */
3112 strcpy(building[index].name, zz[0]);
3114 /* Name of the owner */
3115 strcpy(building[index].owner_name, zz[1]);
3117 /* Race of the owner */
3118 strcpy(building[index].owner_race, zz[2]);
3123 return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3126 /* Building Action */
3129 if (tokenize(s + 2, 8, zz, 0) >= 7)
3131 /* Index of the action */
3132 int action_index = atoi(zz[0]);
3134 /* Name of the action */
3135 strcpy(building[index].act_names[action_index], zz[1]);
3137 /* Cost of the action for members */
3138 building[index].member_costs[action_index] = atoi(zz[2]);
3140 /* Cost of the action for non-members */
3141 building[index].other_costs[action_index] = atoi(zz[3]);
3143 /* Letter assigned to the action */
3144 building[index].letters[action_index] = zz[4][0];
3147 building[index].actions[action_index] = atoi(zz[5]);
3149 /* Action restriction */
3150 building[index].action_restr[action_index] = atoi(zz[6]);
3155 return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3158 /* Building Classes */
3161 if (tokenize(s + 2, MAX_CLASS, zz, 0) == MAX_CLASS)
3163 for (i = 0; i < MAX_CLASS; i++)
3165 building[index].member_class[i] = atoi(zz[i]);
3171 return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3174 /* Building Races */
3177 if (tokenize(s+2, MAX_RACES, zz, 0) == MAX_RACES)
3179 for (i = 0; i < MAX_RACES; i++)
3181 building[index].member_race[i] = atoi(zz[i]);
3187 return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3190 /* Building Realms */
3193 if (tokenize(s+2, MAX_MAGIC, zz, 0) == MAX_MAGIC)
3195 for (i = 0; i < MAX_MAGIC; i++)
3197 building[index].member_realm[i+1] = atoi(zz[i]);
3203 return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3208 /* Ignore scripts */
3214 return (PARSE_ERROR_UNDEFINED_DIRECTIVE);
3223 * Parse a sub-file of the "extra info"
3225 static errr process_dungeon_file_aux(char *buf, int ymin, int xmin, int ymax, int xmax, int *y, int *x)
3232 /* Skip "empty" lines */
3233 if (!buf[0]) return (0);
3235 /* Skip "blank" lines */
3236 if (isspace(buf[0])) return (0);
3239 if (buf[0] == '#') return (0);
3241 /* Require "?:*" format */
3242 if (buf[1] != ':') return (1);
3245 /* Process "%:<fname>" */
3248 /* Attempt to Process the given file */
3249 return (process_dungeon_file(buf + 2, ymin, xmin, ymax, xmax));
3252 /* Process "F:<letter>:<terrain>:<cave_info>:<monster>:<object>:<ego>:<artifact>:<trap>:<special>" -- info for dungeon grid */
3255 return parse_line_feature(buf);
3258 /* Process "D:<dungeon>" -- info for the cave grids */
3259 else if (buf[0] == 'D')
3261 object_type object_type_body;
3263 /* Acquire the text */
3266 /* Length of the text */
3267 int len = strlen(s);
3269 if (init_flags & INIT_ONLY_BUILDINGS) return (0);
3271 for (*x = xmin, i = 0; ((*x < xmax) && (i < len)); (*x)++, s++, i++)
3273 /* Access the grid */
3274 cave_type *c_ptr = &cave[*y][*x];
3278 int object_index = letter[idx].object;
3279 int monster_index = letter[idx].monster;
3280 int random = letter[idx].random;
3281 int artifact_index = letter[idx].artifact;
3283 /* Lay down a floor */
3284 c_ptr->feat = letter[idx].feature;
3286 /* Create hidden door */
3287 if (random & RANDOM_HIDDEN_DOOR)
3289 c_ptr->mimic = c_ptr->feat;
3290 c_ptr->feat = FEAT_DOOR_HEAD;
3293 /* Only the features */
3294 if (init_flags & INIT_ONLY_FEATURES) continue;
3297 c_ptr->info = letter[idx].cave_info;
3299 /* Create a monster */
3300 if (random & RANDOM_MONSTER)
3302 monster_level = base_level + monster_index;
3304 place_monster(*y, *x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
3306 monster_level = base_level;
3308 else if (monster_index)
3310 int old_cur_num, old_max_num;
3313 if (monster_index < 0)
3315 monster_index = -monster_index;
3318 old_cur_num = r_info[monster_index].cur_num;
3319 old_max_num = r_info[monster_index].max_num;
3321 /* Make alive again */
3322 if (r_info[monster_index].flags1 & RF1_UNIQUE)
3324 r_info[monster_index].cur_num = 0;
3325 r_info[monster_index].max_num = 1;
3328 /* Make alive again */
3329 if (r_info[monster_index].flags7 & RF7_UNIQUE_7)
3331 if (r_info[monster_index].cur_num == r_info[monster_index].max_num)
3333 r_info[monster_index].max_num++;
3338 place_monster_aux(0, *y, *x, monster_index, (PM_ALLOW_SLEEP | PM_NO_KAGE));
3342 m_list[hack_m_idx_ii].smart |= SM_CLONED;
3344 /* Make alive again for real unique monster */
3345 r_info[monster_index].cur_num = old_cur_num;
3346 r_info[monster_index].max_num = old_max_num;
3350 /* Object (and possible trap) */
3351 if ((random & RANDOM_OBJECT) && (random & RANDOM_TRAP))
3353 object_level = base_level + object_index;
3356 * Random trap and random treasure defined
3357 * 25% chance for trap and 75% chance for object
3359 if (randint0(100) < 75)
3361 place_object(*y, *x, FALSE, FALSE);
3368 object_level = base_level;
3370 else if (random & RANDOM_OBJECT)
3372 object_level = base_level + object_index;
3374 /* Create an out of deep object */
3375 if (randint0(100) < 75)
3376 place_object(*y, *x, FALSE, FALSE);
3377 else if (randint0(100) < 80)
3378 place_object(*y, *x, TRUE, FALSE);
3380 place_object(*y, *x, TRUE, TRUE);
3382 object_level = base_level;
3385 else if (random & RANDOM_TRAP)
3389 else if (object_index)
3391 /* Get local object */
3392 object_type *o_ptr = &object_type_body;
3394 /* Create the item */
3395 object_prep(o_ptr, object_index);
3397 if (o_ptr->tval == TV_GOLD)
3399 coin_type = object_index - OBJ_GOLD_LIST;
3404 /* Apply magic (no messages, no artifacts) */
3405 apply_magic(o_ptr, base_level, FALSE, TRUE, FALSE, FALSE);
3407 (void)drop_near(o_ptr, -1, *y, *x);
3413 if (a_info[artifact_index].cur_num)
3417 object_type *q_ptr = &forge;
3419 object_prep(q_ptr, k_idx);
3421 /* Drop it in the dungeon */
3422 (void)drop_near(q_ptr, -1, *y, *x);
3426 /* Create the artifact */
3427 create_named_art(artifact_index, *y, *x);
3429 a_info[artifact_index].cur_num = 1;
3433 /* Terrain special */
3434 c_ptr->special = letter[idx].special;
3442 /* Process "Q:<number>:<command>:... -- quest info */
3443 else if (buf[0] == 'Q')
3450 num = tokenize(buf + 2, 33, zz, 0);
3454 num = tokenize(buf + 3, 33, zz, 0);
3457 /* Have we enough parameters? */
3458 if (num < 3) return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3461 q_ptr = &(quest[atoi(zz[0])]);
3463 /* Process "Q:<q_index>:Q:<type>:<num_mon>:<cur_num>:<max_num>:<level>:<r_idx>:<k_idx>:<flags>" -- quest info */
3464 if (zz[1][0] == 'Q')
3466 if (init_flags & INIT_ASSIGN)
3468 monster_race *r_ptr;
3469 artifact_type *a_ptr;
3471 if (num < 9) return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3473 q_ptr->type = atoi(zz[2]);
3474 q_ptr->num_mon = atoi(zz[3]);
3475 q_ptr->cur_num = atoi(zz[4]);
3476 q_ptr->max_num = atoi(zz[5]);
3477 q_ptr->level = atoi(zz[6]);
3478 q_ptr->r_idx = atoi(zz[7]);
3479 q_ptr->k_idx = atoi(zz[8]);
3480 q_ptr->dungeon = atoi(zz[9]);
3483 q_ptr->flags = atoi(zz[10]);
3485 r_ptr = &r_info[q_ptr->r_idx];
3486 if (r_ptr->flags1 & RF1_UNIQUE)
3487 r_ptr->flags1 |= RF1_QUESTOR;
3489 a_ptr = &a_info[q_ptr->k_idx];
3490 a_ptr->gen_flags |= TRG_QUESTITEM;
3495 /* Process "Q:<q_index>:N:<name>" -- quest name */
3496 else if (zz[1][0] == 'N')
3498 if (init_flags & (INIT_ASSIGN | INIT_SHOW_TEXT))
3500 strcpy(q_ptr->name, zz[2]);
3506 /* Process "Q:<q_index>:T:<text>" -- quest description line */
3507 else if (zz[1][0] == 'T')
3509 if (init_flags & INIT_SHOW_TEXT)
3511 strcpy(quest_text[quest_text_line], zz[2]);
3519 /* Process "W:<command>: ..." -- info for the wilderness */
3520 else if (buf[0] == 'W')
3522 return parse_line_wilderness(buf, ymin, xmin, ymax, xmax, y, x);
3525 /* Process "P:<y>:<x>" -- player position */
3526 else if (buf[0] == 'P')
3528 if (init_flags & INIT_CREATE_DUNGEON)
3530 if (tokenize(buf + 2, 2, zz, 0) == 2)
3532 int panels_x, panels_y;
3534 /* Hack - Set the dungeon size */
3535 panels_y = (*y / SCREEN_HGT);
3536 if (*y % SCREEN_HGT) panels_y++;
3537 cur_hgt = panels_y * SCREEN_HGT;
3539 panels_x = (*x / SCREEN_WID);
3540 if (*x % SCREEN_WID) panels_x++;
3541 cur_wid = panels_x * SCREEN_WID;
3543 /* Assume illegal panel */
3544 panel_row_min = cur_hgt;
3545 panel_col_min = cur_wid;
3547 /* Place player in a quest level */
3548 if (p_ptr->inside_quest)
3552 /* Delete the monster (if any) */
3553 delete_monster(py, px);
3561 /* Place player in the town */
3562 else if (!p_ptr->oldpx && !p_ptr->oldpy)
3564 p_ptr->oldpy = atoi(zz[0]);
3565 p_ptr->oldpx = atoi(zz[1]);
3573 /* Process "B:<Index>:<Command>:..." -- Building definition */
3574 else if (buf[0] == 'B')
3576 return parse_line_building(buf);
3579 /* Process "M:<type>:<maximum>" -- set maximum values */
3580 else if (buf[0] == 'M')
3582 if (tokenize(buf+2, 2, zz, 0) == 2)
3585 if (zz[0][0] == 'T')
3587 max_towns = atoi(zz[1]);
3590 /* Maximum quests */
3591 else if (zz[0][0] == 'Q')
3593 max_quests = atoi(zz[1]);
3597 else if (zz[0][0] == 'R')
3599 max_r_idx = atoi(zz[1]);
3603 else if (zz[0][0] == 'K')
3605 max_k_idx = atoi(zz[1]);
3609 else if (zz[0][0] == 'V')
3611 max_v_idx = atoi(zz[1]);
3615 else if (zz[0][0] == 'F')
3617 max_f_idx = atoi(zz[1]);
3621 else if (zz[0][0] == 'A')
3623 max_a_idx = atoi(zz[1]);
3627 else if (zz[0][0] == 'E')
3629 max_e_idx = atoi(zz[1]);
3633 else if (zz[0][0] == 'D')
3635 max_d_idx = atoi(zz[1]);
3639 else if (zz[0][0] == 'O')
3641 max_o_idx = atoi(zz[1]);
3645 else if (zz[0][0] == 'M')
3647 max_m_idx = atoi(zz[1]);
3650 /* Wilderness size */
3651 else if (zz[0][0] == 'W')
3653 /* Maximum wild_x_size */
3654 if (zz[0][1] == 'X')
3655 max_wild_x = atoi(zz[1]);
3656 /* Maximum wild_y_size */
3657 if (zz[0][1] == 'Y')
3658 max_wild_y = atoi(zz[1]);
3672 static cptr variant = "ZANGBAND";
3676 * Helper function for "process_dungeon_file()"
3678 static cptr process_dungeon_file_expr(char **sp, char *fp)
3694 while (isspace(*s)) s++;
3712 t = process_dungeon_file_expr(&s, &f);
3721 else if (streq(t, "IOR"))
3724 while (*s && (f != b2))
3726 t = process_dungeon_file_expr(&s, &f);
3727 if (*t && !streq(t, "0")) v = "1";
3732 else if (streq(t, "AND"))
3735 while (*s && (f != b2))
3737 t = process_dungeon_file_expr(&s, &f);
3738 if (*t && streq(t, "0")) v = "0";
3743 else if (streq(t, "NOT"))
3746 while (*s && (f != b2))
3748 t = process_dungeon_file_expr(&s, &f);
3749 if (*t && streq(t, "1")) v = "0";
3754 else if (streq(t, "EQU"))
3757 if (*s && (f != b2))
3759 t = process_dungeon_file_expr(&s, &f);
3761 while (*s && (f != b2))
3764 t = process_dungeon_file_expr(&s, &f);
3765 if (*t && !streq(p, t)) v = "0";
3770 else if (streq(t, "LEQ"))
3773 if (*s && (f != b2))
3775 t = process_dungeon_file_expr(&s, &f);
3777 while (*s && (f != b2))
3780 t = process_dungeon_file_expr(&s, &f);
3781 if (*t && (strcmp(p, t) > 0)) v = "0";
3786 else if (streq(t, "GEQ"))
3789 if (*s && (f != b2))
3791 t = process_dungeon_file_expr(&s, &f);
3793 while (*s && (f != b2))
3796 t = process_dungeon_file_expr(&s, &f);
3797 if (*t && (strcmp(p, t) < 0)) v = "0";
3804 while (*s && (f != b2))
3806 t = process_dungeon_file_expr(&s, &f);
3811 if (f != b2) v = "?x?x?";
3813 /* Extract final and Terminate */
3814 if ((f = *s) != '\0') *s++ = '\0';
3820 /* Accept all printables except spaces and brackets */
3821 while (isprint(*s) && !strchr(" []", *s)) ++s;
3823 /* Extract final and Terminate */
3824 if ((f = *s) != '\0') *s++ = '\0';
3830 if (streq(b+1, "SYS"))
3836 else if (streq(b+1, "GRAF"))
3841 else if (streq(b+1, "MONOCHROME"))
3850 else if (streq(b+1, "RACE"))
3853 v = rp_ptr->E_title;
3860 else if (streq(b+1, "CLASS"))
3863 v = cp_ptr->E_title;
3870 else if (streq(b+1, "REALM1"))
3873 v = E_realm_names[p_ptr->realm1];
3875 v = realm_names[p_ptr->realm1];
3880 else if (streq(b+1, "REALM2"))
3883 v = E_realm_names[p_ptr->realm2];
3885 v = realm_names[p_ptr->realm2];
3890 else if (streq(b+1, "PLAYER"))
3896 else if (streq(b+1, "TOWN"))
3898 sprintf(tmp, "%d", p_ptr->town_num);
3903 else if (streq(b+1, "LEVEL"))
3905 sprintf(tmp, "%d", p_ptr->lev);
3909 /* Current quest number */
3910 else if (streq(b+1, "QUEST_NUMBER"))
3912 sprintf(tmp, "%d", p_ptr->inside_quest);
3916 /* Number of last quest */
3917 else if (streq(b+1, "LEAVING_QUEST"))
3919 sprintf(tmp, "%d", leaving_quest);
3924 else if (prefix(b+1, "QUEST"))
3926 /* "QUEST" uses a special parameter to determine the number of the quest */
3927 sprintf(tmp, "%d", quest[atoi(b+6)].status);
3932 else if (prefix(b+1, "RANDOM"))
3934 /* "RANDOM" uses a special parameter to determine the number of the quest */
3935 sprintf(tmp, "%d", (int)(seed_town%atoi(b+7)));
3940 else if (streq(b+1, "VARIANT"))
3946 else if (streq(b+1, "WILDERNESS"))
3949 sprintf(tmp, "NONE");
3951 sprintf(tmp, "LITE");
3953 sprintf(tmp, "NORMAL");
3976 errr process_dungeon_file(cptr name, int ymin, int xmin, int ymax, int xmax)
3986 bool bypass = FALSE;
3988 int x = xmin, y = ymin;
3991 /* Build the filename */
3992 path_build(buf, sizeof(buf), ANGBAND_DIR_EDIT, name);
3995 fp = my_fopen(buf, "r");
3998 if (!fp) return (-1);
4001 /* Process the file */
4002 while (0 == my_fgets(fp, buf, sizeof(buf)))
4008 /* Skip "empty" lines */
4009 if (!buf[0]) continue;
4011 /* Skip "blank" lines */
4012 if (isspace(buf[0])) continue;
4015 if (buf[0] == '#') continue;
4018 /* Process "?:<expr>" */
4019 if ((buf[0] == '?') && (buf[1] == ':'))
4028 /* Parse the expr */
4029 v = process_dungeon_file_expr(&s, &f);
4032 bypass = (streq(v, "0") ? TRUE : FALSE);
4038 /* Apply conditionals */
4039 if (bypass) continue;
4042 /* Process "%:<file>" */
4045 /* Process that file if allowed */
4046 (void)process_dungeon_file(buf + 2, ymin, xmin, ymax, xmax);
4053 /* Process the line */
4054 err = process_dungeon_file_aux(buf, ymin, xmin, ymax, xmax, &y, &x);
4066 oops = (((err > 0) && (err < PARSE_ERROR_MAX)) ? err_str[err] : "unknown");
4069 msg_format("Error %d (%s) at line %d of '%s'.", err, oops, num, name);
4071 msg_format("'%s'¤ò²òÀÏÃæ¡£", buf);
4073 msg_format("Parsing '%s'.", buf);
4080 /* Close the file */
4090 void write_r_info_txt(void)
4092 int i, j, z, fc, bc;
4100 monster_race *r_ptr;
4102 monster_blow *b_ptr;
4104 FILE *fff = fopen("output.txt", "wt");
4112 fprintf(fff, "# File: r_info.txt (autogenerated)\n\n");
4114 fprintf(fff, "# Version stamp (required)\n\n");
4117 fprintf(fff, "V:%d.%d.%d\n\n\n", r_head->v_major, r_head->v_minor, r_head->v_patch);
4120 fprintf(fff, "##### The Player #####\n\n");
4122 for (z = -1; z < alloc_race_size; z++)
4124 /* Output the monsters in order */
4125 i = (z >= 0) ? alloc_race_table[z].index : 0;
4127 /* Acquire the monster */
4130 /* Ignore empty monsters */
4131 if (!strlen(r_name + r_ptr->name)) continue;
4133 /* Ignore useless monsters */
4134 if (i && !r_ptr->speed) continue;
4136 /* Write a note if necessary */
4137 if (i && (!r_ptr->level != !mode))
4142 fprintf(fff, "\n##### Town monsters #####\n\n");
4144 /* Note the dungeon */
4147 fprintf(fff, "\n##### Normal monsters #####\n\n");
4150 /* Record the change */
4151 mode = r_ptr->level;
4154 /* Acquire the flags */
4155 f_ptr[0] = r_ptr->flags1; n_ptr[0] = r_info_flags1;
4156 f_ptr[1] = r_ptr->flags2; n_ptr[1] = r_info_flags2;
4157 f_ptr[2] = r_ptr->flags3; n_ptr[2] = r_info_flags3;
4158 f_ptr[3] = r_ptr->flags4; n_ptr[3] = r_info_flags4;
4159 f_ptr[4] = r_ptr->flags5; n_ptr[4] = r_info_flags5;
4160 f_ptr[5] = r_ptr->flags6; n_ptr[5] = r_info_flags6;
4161 f_ptr[6] = r_ptr->flags7; n_ptr[6] = r_info_flags7;
4162 f_ptr[7] = r_ptr->flags8; n_ptr[7] = r_info_flags8;
4163 f_ptr[8] = r_ptr->flags9; n_ptr[8] = r_info_flags9;
4165 /* Write New/Number/Name */
4166 fprintf(fff, "N:%d:%s\n", z + 1, r_name + r_ptr->name);
4169 fprintf(fff, "G:%c:%c\n", r_ptr->d_char, color_char[r_ptr->d_attr]);
4171 /* Write Information */
4172 fprintf(fff, "I:%d:%dd%d:%d:%d:%d\n", r_ptr->speed, r_ptr->hdice, r_ptr->hside,
4173 r_ptr->aaf, r_ptr->ac, r_ptr->sleep);
4175 /* Write more information */
4176 fprintf(fff, "W:%d:%d:%d:%ld\n", r_ptr->level, r_ptr->rarity, r_ptr->extra, r_ptr->mexp);
4179 for(j = 0; j < 4; j++)
4181 b_ptr = &(r_ptr->blow[j]);
4183 /* Stop when done */
4184 if (!b_ptr->method) break;
4186 /* Write the blows */
4187 fprintf(fff, "B:%s:%s:%dd%d\n", r_info_blow_method[b_ptr->method],
4188 r_info_blow_effect[b_ptr->effect],
4189 b_ptr->d_dice, b_ptr->d_side);
4192 /* Extract the flags */
4193 for (fc = 0, j = 0; j < 96; j++)
4195 /* Check this flag */
4196 if (f_ptr[j / 32] & (1L << (j % 32))) flags[fc++] = n_ptr[j / 32][j % 32];
4199 /* Extract the extra flags */
4200 for (j = 192; j < 288; 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; (bc < 60) && (j < fc); j++)
4218 /* Format the flag */
4219 sprintf(t, "%s%s", flags[j], (j < fc - 1) ? " | " : "");
4221 /* Add it to the buffer */
4224 /* Note the length */
4228 /* Done with this line; write it */
4229 fprintf(fff, "%s\n", buf);
4232 /* Write Spells if applicable */
4233 if (r_ptr->freq_spell)
4235 /* Write the frequency */
4236 fprintf(fff, "S:1_IN_%d | \n", 100 / r_ptr->freq_spell);
4238 /* Extract the spell flags */
4239 for (fc = 0, j = 96; j < 192; j++)
4241 /* Check this flag */
4242 if (f_ptr[j / 32] & (1L << (j % 32))) flags[fc++] = n_ptr[j / 32][j % 32];
4245 /* Write the flags */
4246 for (j = 0; j < fc;)
4250 /* Start the line */
4253 for (bc = 0, t = buf + 2; (bc < 60) && (j < fc); j++)
4257 /* Format the flag */
4258 sprintf(t, "%s%s", flags[j], (j < fc - 1) ? " | " : "");
4262 /* Note the length */
4269 /* Done with this line; write it */
4270 fprintf(fff, "%s\n", buf);
4274 /* Acquire the description */
4275 desc = r_text + r_ptr->text;
4276 dlen = strlen(desc);
4278 /* Write Description */
4279 for (j = 0; j < dlen;)
4283 /* Start the line */
4286 for (bc = 0, t = buf + 2; ((bc < 60) || !isspace(desc[j])) && (j < dlen); j++, bc++, t++)
4294 /* Done with this line; write it */
4295 fprintf(fff, "%s\n", buf);
4298 /* Space between entries */