3 /* Purpose: Initialization (part 1) -BEN- */
10 char* _strchr(char* ptr, char ch)
14 for ( ; *ptr != '\0'; ++ptr)
25 #define strchr _strchr
28 * This file is used to initialize various variables and arrays for the
29 * Angband game. Note the use of "fd_read()" and "fd_write()" to bypass
30 * the common limitation of "read()" and "write()" to only 32767 bytes
33 * Several of the arrays for Angband are built from "template" files in
34 * the "lib/file" directory, from which quick-load binary "image" files
35 * are constructed whenever they are not present in the "lib/data"
36 * directory, or if those files become obsolete, if we are allowed.
38 * Warning -- the "ascii" file parsers use a minor hack to collect the
39 * name and text information in a single pass. Thus, the game will not
40 * be able to load any template file with more than 20K of names or 60K
41 * of text, even though technically, up to 64K should be legal.
43 * Note that if "ALLOW_TEMPLATES" is not defined, then a lot of the code
44 * in this file is compiled out, and the game will not run unless valid
45 * "binary template files" already exist in "lib/data". Thus, one can
46 * compile Angband with ALLOW_TEMPLATES defined, run once to create the
47 * "*.raw" files in "lib/data", and then quit, and recompile without
48 * defining ALLOW_TEMPLATES, which will both save 20K and prevent people
49 * from changing the ascii template files in potentially dangerous ways.
51 * The code could actually be removed and placed into a "stand-alone"
52 * program, but that feels a little silly, especially considering some
53 * of the platforms that we currently support.
56 #ifdef ALLOW_TEMPLATES
61 /*** Helper arrays for parsing ascii template files ***/
64 * Monster Blow Methods
66 static cptr r_info_blow_method[] =
98 * Monster Blow Effects
100 static cptr r_info_blow_effect[] =
143 static cptr r_info_flags1[] =
182 static cptr r_info_flags2[] =
221 static cptr r_info_flags3[] =
260 static cptr r_info_flags4[] =
299 static cptr r_info_flags5[] =
338 static cptr r_info_flags6[] =
355 "ANIM_DEAD", /* ToDo: Implement ANIM_DEAD */
378 static cptr r_info_flags7[] =
417 static cptr r_info_flags8[] =
449 "WILD_SWAMP", /* ToDo: Implement Swamp */
455 * Monster race flags - Drops
457 static cptr r_info_flags9[] =
498 static cptr k_info_flags1[] =
537 static cptr k_info_flags2[] =
576 static cptr k_info_flags3[] =
616 static cptr d_info_flags1[] =
654 * Convert a "color letter" into an "actual" color
655 * The colors are: dwsorgbuDWvyRGBU, as shown below
657 static int color_char_to_attr(char c)
661 case 'd': return (TERM_DARK);
662 case 'w': return (TERM_WHITE);
663 case 's': return (TERM_SLATE);
664 case 'o': return (TERM_ORANGE);
665 case 'r': return (TERM_RED);
666 case 'g': return (TERM_GREEN);
667 case 'b': return (TERM_BLUE);
668 case 'u': return (TERM_UMBER);
670 case 'D': return (TERM_L_DARK);
671 case 'W': return (TERM_L_WHITE);
672 case 'v': return (TERM_VIOLET);
673 case 'y': return (TERM_YELLOW);
674 case 'R': return (TERM_L_RED);
675 case 'G': return (TERM_L_GREEN);
676 case 'B': return (TERM_L_BLUE);
677 case 'U': return (TERM_L_UMBER);
685 /*** Initialize from ascii template files ***/
689 * Initialize an "*_info" array, by parsing an ascii "template" file
691 errr init_info_txt(FILE *fp, char *buf, header *head,
692 parse_info_txt_func parse_info_txt_line)
696 /* Just before the first record */
699 /* Just before the first line */
703 /* Prepare the "fake" stuff */
708 while (0 == my_fgets(fp, buf, 1024))
710 /* Advance the line number */
713 /* Skip comments and blank lines */
714 if (!buf[0] || (buf[0] == '#')) continue;
716 /* Verify correct "colon" format */
717 if (buf[1] != ':') return (PARSE_ERROR_GENERIC);
720 /* Hack -- Process 'V' for "Version" */
728 if ((err = (*parse_info_txt_line)(buf, head)) != 0)
733 /* Complete the "name" and "text" sizes */
734 if (head->name_size) head->name_size++;
735 if (head->text_size) head->text_size++;
743 * Initialize the "v_info" array, by parsing an ascii "template" file
745 errr parse_v_info(char *buf, header *head)
751 static vault_type *v_ptr = NULL;
753 /* Process 'N' for "New/Number/Name" */
756 /* Find the colon before the name */
757 s = strchr(buf+2, ':');
759 /* Verify that colon */
762 /* Nuke the colon, advance to the name */
765 /* Paranoia -- require a name */
771 /* Verify information */
772 if (i <= error_idx) return (4);
774 /* Verify information */
775 if (i >= head->info_num) return (2);
780 /* Point at the "info" */
783 /* Hack -- Verify space */
784 if (head->name_size + strlen(s) + 8 > fake_name_size) return (7);
786 /* Advance and Save the name index */
787 if (!v_ptr->name) v_ptr->name = ++head->name_size;
789 /* Append chars to the name */
790 strcpy(head->name_ptr + head->name_size, s);
792 /* Advance the index */
793 head->name_size += strlen(s);
796 /* There better be a current v_ptr */
797 else if (!v_ptr) return (3);
799 /* Process 'D' for "Description" */
800 else if (buf[0] == 'D')
802 /* Acquire the text */
805 /* Hack -- Verify space */
806 if (head->text_size + strlen(s) + 8 > fake_text_size) return (7);
808 /* Advance and Save the text index */
809 if (!v_ptr->text) v_ptr->text = ++head->text_size;
811 /* Append chars to the name */
812 strcpy(head->text_ptr + head->text_size, s);
814 /* Advance the index */
815 head->text_size += strlen(s);
819 /* Process 'X' for "Extra info" (one line only) */
820 else if (buf[0] == 'X')
822 int typ, rat, hgt, wid;
824 /* Scan for the values */
825 if (4 != sscanf(buf+2, "%d:%d:%d:%d",
826 &typ, &rat, &hgt, &wid)) return (1);
828 /* Save the values */
845 * Initialize the "s_info" array, by parsing an ascii "template" file
847 errr parse_s_info(char *buf, header *head)
852 static skill_table *s_ptr = NULL;
855 /* Process 'N' for "New/Number/Name" */
861 /* Verify information */
862 if (i <= error_idx) return (4);
864 /* Verify information */
865 if (i >= head->info_num) return (2);
870 /* Point at the "info" */
874 /* There better be a current s_ptr */
875 else if (!s_ptr) return (3);
877 /* Process 'W' for "Weapon exp" */
878 else if (buf[0] == 'W')
880 int tval, sval, start, max;
881 const s16b exp_conv_table[] = { 0, 4000, 6000, 7000, 8000 };
883 /* Scan for the values */
884 if (4 != sscanf(buf+2, "%d:%d:%d:%d",
885 &tval, &sval, &start, &max)) return (1);
887 if (start < 0 || start > 4 || max < 0 || max > 4) return (8);
889 /* Save the values */
890 s_ptr->w_start[tval][sval] = exp_conv_table[start];
891 s_ptr->w_max[tval][sval] = exp_conv_table[max];
894 /* Process 'S' for "Skill exp" */
895 else if (buf[0] == 'S')
899 /* Scan for the values */
900 if (3 != sscanf(buf+2, "%d:%d:%d",
901 &num, &start, &max)) return (1);
903 if (start < 0 || start > 8000 || max < 0 || max > 8000) return (8);
905 /* Save the values */
906 s_ptr->s_start[num] = start;
907 s_ptr->s_max[num] = max;
920 * Initialize the "m_info" array, by parsing an ascii "template" file
922 errr parse_m_info(char *buf, header *head)
929 static player_magic *m_ptr = NULL;
932 static int realm, magic_idx = 0, readable = 0;
935 /* Process 'N' for "New/Number/Name" */
941 /* Verify information */
942 if (i <= error_idx) return (4);
944 /* Verify information */
945 if (i >= head->info_num) return (2);
950 /* Point at the "info" */
954 /* There better be a current m_ptr */
955 else if (!m_ptr) return (3);
957 /* Process 'I' for "Info" (one line only) */
958 else if (buf[0] == 'I')
961 int xtra, type, first, weight;
963 /* Find the colon before the name */
964 s = strchr(buf+2, ':');
966 /* Verify that colon */
969 /* Nuke the colon, advance to the name */
974 if (streq(book, "SORCERY")) m_ptr->spell_book = TV_SORCERY_BOOK;
975 else if (streq(book, "LIFE")) m_ptr->spell_book = TV_LIFE_BOOK;
976 else if (streq(book, "MUSIC")) m_ptr->spell_book = TV_MUSIC_BOOK;
977 else if (streq(book, "HISSATSU")) m_ptr->spell_book = TV_HISSATSU_BOOK;
978 else if (streq(book, "NONE")) m_ptr->spell_book = 0;
983 /* Find the colon before the name */
986 /* Verify that colon */
989 /* Nuke the colon, advance to the name */
992 if (streq(stat, "STR")) m_ptr->spell_stat = A_STR;
993 else if (streq(stat, "INT")) m_ptr->spell_stat = A_INT;
994 else if (streq(stat, "WIS")) m_ptr->spell_stat = A_WIS;
995 else if (streq(stat, "DEX")) m_ptr->spell_stat = A_DEX;
996 else if (streq(stat, "CON")) m_ptr->spell_stat = A_CON;
997 else if (streq(stat, "CHR")) m_ptr->spell_stat = A_CHR;
1001 /* Scan for the values */
1002 if (4 != sscanf(s, "%x:%d:%d:%d",
1003 &xtra, &type, &first, &weight)) return (1);
1005 m_ptr->spell_xtra = xtra;
1006 m_ptr->spell_type = type;
1007 m_ptr->spell_first = first;
1008 m_ptr->spell_weight = weight;
1012 /* Process 'R' for "Realm" (one line only) */
1013 else if (buf[0] == 'R')
1015 /* Scan for the values */
1016 if (2 != sscanf(buf+2, "%d:%d",
1017 &realm, &readable)) return (1);
1022 else if (buf[0] == 'T')
1024 int level, mana, fail, exp;
1026 if (!readable) return (1);
1027 /* Scan for the values */
1028 if (4 != sscanf(buf+2, "%d:%d:%d:%d",
1029 &level, &mana, &fail, &exp)) return (1);
1031 m_ptr->info[realm][magic_idx].slevel = level;
1032 m_ptr->info[realm][magic_idx].smana = mana;
1033 m_ptr->info[realm][magic_idx].sfail = fail;
1034 m_ptr->info[realm][magic_idx].sexp = exp;
1048 * Initialize the "f_info" array, by parsing an ascii "template" file
1050 errr parse_f_info(char *buf, header *head)
1057 static feature_type *f_ptr = NULL;
1060 /* Process 'N' for "New/Number/Name" */
1063 /* Find the colon before the name */
1064 s = strchr(buf+2, ':');
1066 /* Verify that colon */
1069 /* Nuke the colon, advance to the name */
1073 /* Paranoia -- require a name */
1074 if (!*s) return (1);
1080 /* Verify information */
1081 if (i <= error_idx) return (4);
1083 /* Verify information */
1084 if (i >= head->info_num) return (2);
1086 /* Save the index */
1089 /* Point at the "info" */
1093 /* Hack -- Verify space */
1094 if (head->name_size + strlen(s) + 8 > fake_name_size) return (7);
1096 /* Advance and Save the name index */
1097 if (!f_ptr->name) f_ptr->name = ++head->name_size;
1099 /* Append chars to the name */
1100 strcpy(head->name_ptr + head->name_size, s);
1102 /* Advance the index */
1103 head->name_size += strlen(s);
1105 /* Default "mimic" */
1109 /* There better be a current f_ptr */
1110 else if (!f_ptr) return (3);
1113 /* ±Ñ¸ì̾¤òÆɤà¥ë¡¼¥Á¥ó¤òÄɲà */
1114 /* 'E' ¤«¤é»Ï¤Þ¤ë¹Ô¤Ï±Ñ¸ì̾¤È¤·¤Æ¤¤¤ë */
1115 else if (buf[0] == 'E')
1117 /* Acquire the Text */
1120 /* Hack -- Verify space */
1121 if (head->name_size + strlen(s) + 8 > fake_name_size) return (7);
1123 /* Advance and Save the name index */
1124 if (!f_ptr->E_name) f_ptr->E_name = ++head->name_size;
1126 /* Append chars to the name */
1127 strcpy(head->name_ptr + head->name_size, s);
1129 /* Advance the index */
1130 head->name_size += strlen(s);
1133 else if (buf[0] == 'E')
1135 /* Acquire the Text */
1138 /* Hack -- Verify space */
1139 if (head->name_size + strlen(s) + 8 > fake_name_size) return (7);
1141 /* Advance and Save the name index */
1142 if (!f_ptr->name) f_ptr->name = ++head->name_size;
1144 /* Append chars to the name */
1145 strcpy(head->name_ptr + head->name_size, s);
1147 /* Advance the index */
1148 head->name_size += strlen(s);
1154 /* Process 'D' for "Description" */
1155 else if (buf[0] == 'D')
1157 /* Acquire the text */
1160 /* Hack -- Verify space */
1161 if (f_head->text_size + strlen(s) + 8 > fake_text_size) return (7);
1163 /* Advance and Save the text index */
1164 if (!f_ptr->text) f_ptr->text = ++f_head->text_size;
1166 /* Append chars to the name */
1167 strcpy(f_text + f_head->text_size, s);
1169 /* Advance the index */
1170 f_head->text_size += strlen(s);
1177 /* Process 'M' for "Mimic" (one line only) */
1178 else if (buf[0] == 'M')
1182 /* Scan for the values */
1183 if (1 != sscanf(buf+2, "%d",
1184 &mimic)) return (1);
1186 /* Save the values */
1187 f_ptr->mimic = mimic;
1192 /* Process 'G' for "Graphics" (one line only) */
1193 else if (buf[0] == 'G')
1198 if (!buf[2]) return (1);
1199 if (!buf[3]) return (1);
1200 if (!buf[4]) return (1);
1202 /* Extract the color */
1203 tmp = color_char_to_attr(buf[4]);
1206 if (tmp < 0) return (1);
1208 /* Save the values */
1209 f_ptr->d_attr = tmp;
1210 f_ptr->d_char = buf[2];
1223 * Grab one flag in an object_kind from a textual string
1225 static errr grab_one_kind_flag(object_kind *k_ptr, cptr what)
1230 for (i = 0; i < 32; i++)
1232 if (streq(what, k_info_flags1[i]))
1234 k_ptr->flags1 |= (1L << i);
1240 for (i = 0; i < 32; i++)
1242 if (streq(what, k_info_flags2[i]))
1244 k_ptr->flags2 |= (1L << i);
1250 for (i = 0; i < 32; i++)
1252 if (streq(what, k_info_flags3[i]))
1254 k_ptr->flags3 |= (1L << i);
1261 msg_format("̤ÃΤΥ¢¥¤¥Æ¥à¡¦¥Õ¥é¥° '%s'¡£", what);
1263 msg_format("Unknown object flag '%s'.", what);
1273 * Initialize the "k_info" array, by parsing an ascii "template" file
1275 errr parse_k_info(char *buf, header *head)
1282 static object_kind *k_ptr = NULL;
1285 /* Process 'N' for "New/Number/Name" */
1288 /* Find the colon before the name */
1289 s = strchr(buf+2, ':');
1291 /* Verify that colon */
1294 /* Nuke the colon, advance to the name */
1298 /* Paranoia -- require a name */
1299 if (!*s) return (1);
1304 /* Verify information */
1305 if (i <= error_idx) return (4);
1307 /* Verify information */
1308 if (i >= head->info_num) return (2);
1310 /* Save the index */
1313 /* Point at the "info" */
1317 /* Hack -- Verify space */
1318 if (head->name_size + strlen(s) + 8 > fake_name_size) return (7);
1320 /* Advance and Save the name index */
1321 if (!k_ptr->name) k_ptr->name = ++head->name_size;
1323 /* Append chars to the name */
1324 strcpy(head->name_ptr + head->name_size, s);
1326 /* Advance the index */
1327 head->name_size += strlen(s);
1331 /* There better be a current k_ptr */
1332 else if (!k_ptr) return (3);
1336 /* ±Ñ¸ì̾¤òÆɤà¥ë¡¼¥Á¥ó¤òÄɲà */
1337 /* 'E' ¤«¤é»Ï¤Þ¤ë¹Ô¤Ï±Ñ¸ì̾¤È¤·¤Æ¤¤¤ë */
1338 else if (buf[0] == 'E')
1340 /* Acquire the Text */
1343 /* Hack -- Verify space */
1344 if (head->name_size + strlen(s) + 8 > fake_name_size) return (7);
1346 /* Advance and Save the name index */
1347 if (!k_ptr->E_name) k_ptr->E_name = ++head->name_size;
1349 /* Append chars to the name */
1350 strcpy(head->name_ptr + head->name_size, s);
1352 /* Advance the index */
1353 head->name_size += strlen(s);
1356 else if (buf[0] == 'E')
1358 /* Acquire the Text */
1361 /* Hack -- Verify space */
1362 if (head->name_size + strlen(s) + 8 > fake_name_size) return (7);
1364 /* Advance and Save the name index */
1365 if (!k_ptr->name) k_ptr->name = ++head->name_size;
1367 /* Append chars to the name */
1368 strcpy(head->name_ptr + head->name_size, s);
1370 /* Advance the index */
1371 head->name_size += strlen(s);
1376 /* Process 'D' for "Description" */
1377 else if (buf[0] == 'D')
1379 /* Acquire the text */
1382 /* Hack -- Verify space */
1383 if (k_head->text_size + strlen(s) + 8 > fake_text_size) return (7);
1385 /* Advance and Save the text index */
1386 if (!k_ptr->text) k_ptr->text = ++k_head->text_size;
1388 /* Append chars to the name */
1389 strcpy(k_text + k_head->text_size, s);
1391 /* Advance the index */
1392 k_head->text_size += strlen(s);
1398 /* Process 'G' for "Graphics" (one line only) */
1399 else if (buf[0] == 'G')
1405 if (!buf[2]) return (1);
1406 if (!buf[3]) return (1);
1407 if (!buf[4]) return (1);
1409 /* Extract the char */
1412 /* Extract the attr */
1413 tmp = color_char_to_attr(buf[4]);
1416 if (tmp < 0) return (1);
1418 /* Save the values */
1419 k_ptr->d_attr = tmp;
1420 k_ptr->d_char = sym;
1423 /* Process 'I' for "Info" (one line only) */
1424 else if (buf[0] == 'I')
1426 int tval, sval, pval;
1428 /* Scan for the values */
1429 if (3 != sscanf(buf+2, "%d:%d:%d",
1430 &tval, &sval, &pval)) return (1);
1432 /* Save the values */
1438 /* Process 'W' for "More Info" (one line only) */
1439 else if (buf[0] == 'W')
1441 int level, extra, wgt;
1444 /* Scan for the values */
1445 if (4 != sscanf(buf+2, "%d:%d:%d:%ld",
1446 &level, &extra, &wgt, &cost)) return (1);
1448 /* Save the values */
1449 k_ptr->level = level;
1450 k_ptr->extra = extra;
1451 k_ptr->weight = wgt;
1455 /* Process 'A' for "Allocation" (one line only) */
1456 else if (buf[0] == 'A')
1460 /* XXX XXX XXX Simply read each number following a colon */
1461 for (i = 0, s = buf+1; s && (s[0] == ':') && s[1]; ++i)
1463 /* Default chance */
1464 k_ptr->chance[i] = 1;
1466 /* Store the attack damage index */
1467 k_ptr->locale[i] = atoi(s+1);
1469 /* Find the slash */
1470 t = strchr(s+1, '/');
1472 /* Find the next colon */
1473 s = strchr(s+1, ':');
1475 /* If the slash is "nearby", use it */
1476 if (t && (!s || t < s))
1478 int chance = atoi(t+1);
1479 if (chance > 0) k_ptr->chance[i] = chance;
1484 /* Hack -- Process 'P' for "power" and such */
1485 else if (buf[0] == 'P')
1487 int ac, hd1, hd2, th, td, ta;
1489 /* Scan for the values */
1490 if (6 != sscanf(buf+2, "%d:%dd%d:%d:%d:%d",
1491 &ac, &hd1, &hd2, &th, &td, &ta)) return (1);
1501 /* Hack -- Process 'F' for flags */
1502 else if (buf[0] == 'F')
1504 /* Parse every entry textually */
1505 for (s = buf + 2; *s; )
1507 /* Find the end of this entry */
1508 for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
1510 /* Nuke and skip any dividers */
1514 while (*t == ' ' || *t == '|') t++;
1517 /* Parse this entry */
1518 if (0 != grab_one_kind_flag(k_ptr, s)) return (5);
1520 /* Start the next entry */
1536 * Grab one flag in an artifact_type from a textual string
1538 static errr grab_one_artifact_flag(artifact_type *a_ptr, cptr what)
1543 for (i = 0; i < 32; i++)
1545 if (streq(what, k_info_flags1[i]))
1547 a_ptr->flags1 |= (1L << i);
1553 for (i = 0; i < 32; i++)
1555 if (streq(what, k_info_flags2[i]))
1557 a_ptr->flags2 |= (1L << i);
1563 for (i = 0; i < 32; i++)
1565 if (streq(what, k_info_flags3[i]))
1567 a_ptr->flags3 |= (1L << i);
1574 msg_format("̤ÃΤÎÅÁÀâ¤Î¥¢¥¤¥Æ¥à¡¦¥Õ¥é¥° '%s'¡£", what);
1576 msg_format("Unknown artifact flag '%s'.", what);
1588 * Initialize the "a_info" array, by parsing an ascii "template" file
1590 errr parse_a_info(char *buf, header *head)
1597 static artifact_type *a_ptr = NULL;
1600 /* Process 'N' for "New/Number/Name" */
1603 /* Find the colon before the name */
1604 s = strchr(buf+2, ':');
1606 /* Verify that colon */
1609 /* Nuke the colon, advance to the name */
1612 /* Paranoia -- require a name */
1613 if (!*s) return (1);
1618 /* Verify information */
1619 if (i < error_idx) return (4);
1621 /* Verify information */
1622 if (i >= head->info_num) return (2);
1624 /* Save the index */
1627 /* Point at the "info" */
1630 /* Ignore everything */
1631 a_ptr->flags3 |= (TR3_IGNORE_ACID);
1632 a_ptr->flags3 |= (TR3_IGNORE_ELEC);
1633 a_ptr->flags3 |= (TR3_IGNORE_FIRE);
1634 a_ptr->flags3 |= (TR3_IGNORE_COLD);
1636 /* Hack -- Verify space */
1637 if (head->name_size + strlen(s) + 8 > fake_name_size) return (7);
1639 /* Advance and Save the name index */
1640 if (!a_ptr->name) a_ptr->name = ++head->name_size;
1642 /* Append chars to the name */
1643 strcpy(head->name_ptr + head->name_size, s);
1645 /* Advance the index */
1646 head->name_size += strlen(s);
1650 /* There better be a current a_ptr */
1651 else if (!a_ptr) return (3);
1655 /* ±Ñ¸ì̾¤òÆɤà¥ë¡¼¥Á¥ó¤òÄɲà */
1656 /* 'E' ¤«¤é»Ï¤Þ¤ë¹Ô¤Ï±Ñ¸ì̾¤È¤·¤Æ¤¤¤ë */
1657 else if (buf[0] == 'E')
1659 /* Acquire the Text */
1662 /* Hack -- Verify space */
1663 if (head->name_size + strlen(s) + 8 > fake_name_size) return (7);
1665 /* Advance and Save the name index */
1666 if (!a_ptr->E_name) a_ptr->name = ++head->name_size;
1668 /* Append chars to the name */
1669 strcpy(head->name_ptr + head->name_size, s);
1671 /* Advance the index */
1672 head->name_size += strlen(s);
1675 else if (buf[0] == 'E')
1677 /* Acquire the Text */
1680 /* Hack -- Verify space */
1681 if (head->name_size + strlen(s) + 8 > fake_name_size) return (7);
1683 /* Advance and Save the name index */
1684 if (!a_ptr->name) a_ptr->name = ++head->name_size;
1686 /* Append chars to the name */
1687 strcpy(head->name_ptr + head->name_size, s);
1689 /* Advance the index */
1690 head->name_size += strlen(s);
1694 /* Process 'D' for "Description" */
1695 else if (buf[0] == 'D')
1700 /* Acquire the text */
1705 /* Acquire the text */
1709 /* Hack -- Verify space */
1710 if (head->text_size + strlen(s) + 8 > fake_text_size) return (7);
1712 /* Advance and Save the text index */
1713 if (!a_ptr->text) a_ptr->text = ++head->text_size;
1715 /* Append chars to the name */
1716 strcpy(head->text_ptr + head->text_size, s);
1718 /* Advance the index */
1719 head->text_size += strlen(s);
1723 /* Process 'I' for "Info" (one line only) */
1724 else if (buf[0] == 'I')
1726 int tval, sval, pval;
1728 /* Scan for the values */
1729 if (3 != sscanf(buf+2, "%d:%d:%d",
1730 &tval, &sval, &pval)) return (1);
1732 /* Save the values */
1738 /* Process 'W' for "More Info" (one line only) */
1739 else if (buf[0] == 'W')
1741 int level, rarity, wgt;
1744 /* Scan for the values */
1745 if (4 != sscanf(buf+2, "%d:%d:%d:%ld",
1746 &level, &rarity, &wgt, &cost)) return (1);
1748 /* Save the values */
1749 a_ptr->level = level;
1750 a_ptr->rarity = rarity;
1751 a_ptr->weight = wgt;
1755 /* Hack -- Process 'P' for "power" and such */
1756 else if (buf[0] == 'P')
1758 int ac, hd1, hd2, th, td, ta;
1760 /* Scan for the values */
1761 if (6 != sscanf(buf+2, "%d:%dd%d:%d:%d:%d",
1762 &ac, &hd1, &hd2, &th, &td, &ta)) return (1);
1772 /* Hack -- Process 'F' for flags */
1773 else if (buf[0] == 'F')
1775 /* Parse every entry textually */
1776 for (s = buf + 2; *s; )
1778 /* Find the end of this entry */
1779 for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
1781 /* Nuke and skip any dividers */
1785 while ((*t == ' ') || (*t == '|')) t++;
1788 /* Parse this entry */
1789 if (0 != grab_one_artifact_flag(a_ptr, s)) return (5);
1791 /* Start the next entry */
1807 * Grab one flag in a ego-item_type from a textual string
1809 static bool grab_one_ego_item_flag(ego_item_type *e_ptr, cptr what)
1814 for (i = 0; i < 32; i++)
1816 if (streq(what, k_info_flags1[i]))
1818 e_ptr->flags1 |= (1L << i);
1824 for (i = 0; i < 32; i++)
1826 if (streq(what, k_info_flags2[i]))
1828 e_ptr->flags2 |= (1L << i);
1834 for (i = 0; i < 32; i++)
1836 if (streq(what, k_info_flags3[i]))
1838 e_ptr->flags3 |= (1L << i);
1845 msg_format("̤ÃΤÎ̾¤Î¤¢¤ë¥¢¥¤¥Æ¥à¡¦¥Õ¥é¥° '%s'¡£", what);
1847 msg_format("Unknown ego-item flag '%s'.", what);
1859 * Initialize the "e_info" array, by parsing an ascii "template" file
1861 errr parse_e_info(char *buf, header *head)
1868 static ego_item_type *e_ptr = NULL;
1871 /* Just before the first record */
1874 /* Just before the first line */
1878 /* Process 'N' for "New/Number/Name" */
1881 /* Find the colon before the name */
1882 s = strchr(buf+2, ':');
1884 /* Verify that colon */
1887 /* Nuke the colon, advance to the name */
1890 /* Paranoia -- require a name */
1891 if (!*s) return (1);
1896 /* Verify information */
1897 if (i < error_idx) return (4);
1899 /* Verify information */
1900 if (i >= head->info_num) return (2);
1902 /* Save the index */
1905 /* Point at the "info" */
1908 /* Hack -- Verify space */
1909 if (head->name_size + strlen(s) + 8 > fake_name_size) return (7);
1911 /* Advance and Save the name index */
1912 if (!e_ptr->name) e_ptr->name = ++head->name_size;
1914 /* Append chars to the name */
1915 strcpy(head->name_ptr + head->name_size, s);
1917 /* Advance the index */
1918 head->name_size += strlen(s);
1922 /* There better be a current e_ptr */
1923 else if (!e_ptr) return (3);
1927 /* ±Ñ¸ì̾¤òÆɤà¥ë¡¼¥Á¥ó¤òÄɲà */
1928 /* 'E' ¤«¤é»Ï¤Þ¤ë¹Ô¤Ï±Ñ¸ì̾ */
1929 else if (buf[0] == 'E')
1931 /* Acquire the Text */
1934 /* Hack -- Verify space */
1935 if (head->name_size + strlen(s) + 8 > fake_name_size) return (7);
1937 /* Advance and Save the name index */
1938 if (!e_ptr->E_name) e_ptr->E_name = ++head->name_size;
1940 /* Append chars to the name */
1941 strcpy(head->name_ptr+ head->name_size, s);
1943 /* Advance the index */
1944 head->name_size += strlen(s);
1947 else if (buf[0] == 'E')
1949 /* Acquire the Text */
1952 /* Hack -- Verify space */
1953 if (head->name_size + strlen(s) + 8 > fake_name_size) return (7);
1955 /* Advance and Save the name index */
1956 if (!e_ptr->name) e_ptr->name = ++head->name_size;
1958 /* Append chars to the name */
1959 strcpy(head->name_ptr + head->name_size, s);
1961 /* Advance the index */
1962 head->name_size += strlen(s);
1967 /* Process 'D' for "Description" */
1968 else if (buf[0] == 'D')
1970 /* Acquire the text */
1973 /* Hack -- Verify space */
1974 if (e_head->text_size + strlen(s) + 8 > fake_text_size) return (7);
1976 /* Advance and Save the text index */
1977 if (!e_ptr->text) e_ptr->text = ++e_head->text_size;
1979 /* Append chars to the name */
1980 strcpy(e_text + e_head->text_size, s);
1982 /* Advance the index */
1983 e_head->text_size += strlen(s);
1988 /* Process 'X' for "Xtra" (one line only) */
1989 else if (buf[0] == 'X')
1993 /* Scan for the values */
1994 if (2 != sscanf(buf+2, "%d:%d",
1995 &slot, &rating)) return (1);
1997 /* Save the values */
1999 e_ptr->rating = rating;
2002 /* Process 'W' for "More Info" (one line only) */
2003 else if (buf[0] == 'W')
2005 int level, rarity, pad2;
2008 /* Scan for the values */
2009 if (4 != sscanf(buf+2, "%d:%d:%d:%ld",
2010 &level, &rarity, &pad2, &cost)) return (1);
2012 /* Save the values */
2013 e_ptr->level = level;
2014 e_ptr->rarity = rarity;
2015 /* e_ptr->weight = wgt; */
2019 /* Hack -- Process 'C' for "creation" */
2020 else if (buf[0] == 'C')
2024 /* Scan for the values */
2025 if (4 != sscanf(buf+2, "%d:%d:%d:%d",
2026 &th, &td, &ta, &pv)) return (1);
2028 e_ptr->max_to_h = th;
2029 e_ptr->max_to_d = td;
2030 e_ptr->max_to_a = ta;
2031 e_ptr->max_pval = pv;
2034 /* Hack -- Process 'F' for flags */
2035 else if (buf[0] == 'F')
2037 /* Parse every entry textually */
2038 for (s = buf + 2; *s; )
2040 /* Find the end of this entry */
2041 for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
2043 /* Nuke and skip any dividers */
2047 while ((*t == ' ') || (*t == '|')) t++;
2050 /* Parse this entry */
2051 if (0 != grab_one_ego_item_flag(e_ptr, s)) return (5);
2053 /* Start the next entry */
2067 * Grab one (basic) flag in a monster_race from a textual string
2069 static errr grab_one_basic_flag(monster_race *r_ptr, cptr what)
2074 for (i = 0; i < 32; i++)
2076 if (streq(what, r_info_flags1[i]))
2078 r_ptr->flags1 |= (1L << i);
2084 for (i = 0; i < 32; i++)
2086 if (streq(what, r_info_flags2[i]))
2088 r_ptr->flags2 |= (1L << i);
2094 for (i = 0; i < 32; i++)
2096 if (streq(what, r_info_flags3[i]))
2098 r_ptr->flags3 |= (1L << i);
2104 for (i = 0; i < 32; i++)
2106 if (streq(what, r_info_flags7[i]))
2108 r_ptr->flags7 |= (1L << i);
2114 for (i = 0; i < 32; i++)
2116 if (streq(what, r_info_flags8[i]))
2118 r_ptr->flags8 |= (1L << i);
2124 for (i = 0; i < 32; i++)
2126 if (streq(what, r_info_flags9[i]))
2128 r_ptr->flags9 |= (1L << i);
2135 msg_format("̤ÃΤΥâ¥ó¥¹¥¿¡¼¡¦¥Õ¥é¥° '%s'¡£", what);
2137 msg_format("Unknown monster flag '%s'.", what);
2147 * Grab one (spell) flag in a monster_race from a textual string
2149 static errr grab_one_spell_flag(monster_race *r_ptr, cptr what)
2154 for (i = 0; i < 32; i++)
2156 if (streq(what, r_info_flags4[i]))
2158 r_ptr->flags4 |= (1L << i);
2164 for (i = 0; i < 32; i++)
2166 if (streq(what, r_info_flags5[i]))
2168 r_ptr->flags5 |= (1L << i);
2174 for (i = 0; i < 32; i++)
2176 if (streq(what, r_info_flags6[i]))
2178 r_ptr->flags6 |= (1L << i);
2185 msg_format("̤ÃΤΥâ¥ó¥¹¥¿¡¼¡¦¥Õ¥é¥° '%s'¡£", what);
2187 msg_format("Unknown monster flag '%s'.", what);
2199 * Initialize the "r_info" array, by parsing an ascii "template" file
2201 errr parse_r_info(char *buf, header *head)
2208 static monster_race *r_ptr = NULL;
2211 /* Process 'N' for "New/Number/Name" */
2214 /* Find the colon before the name */
2215 s = strchr(buf+2, ':');
2217 /* Verify that colon */
2220 /* Nuke the colon, advance to the name */
2223 /* Paranoia -- require a name */
2224 if (!*s) return (1);
2229 /* Verify information */
2230 if (i < error_idx) return (4);
2232 /* Verify information */
2233 if (i >= head->info_num) return (2);
2235 /* Save the index */
2238 /* Point at the "info" */
2241 /* Hack -- Verify space */
2242 if (head->name_size + strlen(s) + 8 > fake_name_size) return (7);
2244 /* Advance and Save the name index */
2245 if (!r_ptr->name) r_ptr->name = ++head->name_size;
2247 /* Append chars to the name */
2248 strcpy(head->name_ptr + head->name_size, s);
2250 /* Advance the index */
2251 head->name_size += strlen(s);
2255 /* There better be a current r_ptr */
2256 else if (!r_ptr) return (3);
2260 /* ±Ñ¸ì̾¤òÆɤà¥ë¡¼¥Á¥ó¤òÄɲà */
2261 /* 'E' ¤«¤é»Ï¤Þ¤ë¹Ô¤Ï±Ñ¸ì̾ */
2262 else if (buf[0] == 'E')
2264 /* Acquire the Text */
2267 /* Hack -- Verify space */
2268 if (head->name_size + strlen(s) + 8 > fake_name_size) return (7);
2270 /* Advance and Save the name index */
2271 if (!r_ptr->E_name) r_ptr->E_name = ++head->name_size;
2273 /* Append chars to the name */
2274 strcpy(head->name_ptr + head->name_size, s);
2276 /* Advance the index */
2277 head->name_size += strlen(s);
2280 else if (buf[0] == 'E')
2282 /* Acquire the Text */
2285 /* Hack -- Verify space */
2286 if (head->name_size + strlen(s) + 8 > fake_name_size) return (7);
2288 /* Advance and Save the name index */
2289 if (!r_ptr->name) r_ptr->name = ++head->name_size;
2291 /* Append chars to the name */
2292 strcpy(head->name_ptr + head->name_size, s);
2294 /* Advance the index */
2295 head->name_size += strlen(s);
2298 /* Process 'D' for "Description" */
2299 else if (buf[0] == 'D')
2304 /* Acquire the text */
2309 /* Acquire the text */
2313 /* Hack -- Verify space */
2314 if (head->text_size + strlen(s) + 8 > fake_text_size) return (7);
2316 /* Advance and Save the text index */
2317 if (!r_ptr->text) r_ptr->text = ++head->text_size;
2319 /* Append chars to the name */
2320 strcpy(head->text_ptr + head->text_size, s);
2322 /* Advance the index */
2323 head->text_size += strlen(s);
2326 /* Process 'G' for "Graphics" (one line only) */
2327 else if (buf[0] == 'G')
2333 if (!buf[2]) return (1);
2334 if (!buf[3]) return (1);
2335 if (!buf[4]) return (1);
2337 /* Extract the char */
2340 /* Extract the attr */
2341 tmp = color_char_to_attr(buf[4]);
2344 if (tmp < 0) return (1);
2346 /* Save the values */
2347 r_ptr->d_char = sym;
2348 r_ptr->d_attr = tmp;
2351 /* Process 'I' for "Info" (one line only) */
2352 else if (buf[0] == 'I')
2354 int spd, hp1, hp2, aaf, ac, slp;
2356 /* Scan for the other values */
2357 if (6 != sscanf(buf+2, "%d:%dd%d:%d:%d:%d",
2358 &spd, &hp1, &hp2, &aaf, &ac, &slp)) return (1);
2360 /* Save the values */
2369 /* Process 'W' for "More Info" (one line only) */
2370 else if (buf[0] == 'W')
2377 /* Scan for the values */
2378 if (6 != sscanf(buf+2, "%d:%d:%d:%ld:%ld:%d",
2379 &lev, &rar, &pad, &exp, &nextexp, &nextmon)) return (1);
2381 /* Save the values */
2383 r_ptr->rarity = rar;
2386 r_ptr->next_exp = nextexp;
2387 r_ptr->next_r_idx = nextmon;
2390 /* Process 'B' for "Blows" (up to four lines) */
2391 else if (buf[0] == 'B')
2395 /* Find the next empty blow slot (if any) */
2396 for (i = 0; i < 4; i++) if (!r_ptr->blow[i].method) break;
2398 /* Oops, no more slots */
2399 if (i == 4) return (1);
2401 /* Analyze the first field */
2402 for (s = t = buf+2; *t && (*t != ':'); t++) /* loop */;
2404 /* Terminate the field (if necessary) */
2405 if (*t == ':') *t++ = '\0';
2407 /* Analyze the method */
2408 for (n1 = 0; r_info_blow_method[n1]; n1++)
2410 if (streq(s, r_info_blow_method[n1])) break;
2413 /* Invalid method */
2414 if (!r_info_blow_method[n1]) return (1);
2416 /* Analyze the second field */
2417 for (s = t; *t && (*t != ':'); t++) /* loop */;
2419 /* Terminate the field (if necessary) */
2420 if (*t == ':') *t++ = '\0';
2422 /* Analyze effect */
2423 for (n2 = 0; r_info_blow_effect[n2]; n2++)
2425 if (streq(s, r_info_blow_effect[n2])) break;
2428 /* Invalid effect */
2429 if (!r_info_blow_effect[n2]) return (1);
2431 /* Analyze the third field */
2432 for (s = t; *t && (*t != 'd'); t++) /* loop */;
2434 /* Terminate the field (if necessary) */
2435 if (*t == 'd') *t++ = '\0';
2437 /* Save the method */
2438 r_ptr->blow[i].method = n1;
2440 /* Save the effect */
2441 r_ptr->blow[i].effect = n2;
2443 /* Extract the damage dice and sides */
2444 r_ptr->blow[i].d_dice = atoi(s);
2445 r_ptr->blow[i].d_side = atoi(t);
2448 /* Process 'F' for "Basic Flags" (multiple lines) */
2449 else if (buf[0] == 'F')
2451 /* Parse every entry */
2452 for (s = buf + 2; *s; )
2454 /* Find the end of this entry */
2455 for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
2457 /* Nuke and skip any dividers */
2461 while (*t == ' ' || *t == '|') t++;
2464 /* Parse this entry */
2465 if (0 != grab_one_basic_flag(r_ptr, s)) return (5);
2467 /* Start the next entry */
2472 /* Process 'S' for "Spell Flags" (multiple lines) */
2473 else if (buf[0] == 'S')
2475 /* Parse every entry */
2476 for (s = buf + 2; *s; )
2478 /* Find the end of this entry */
2479 for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
2481 /* Nuke and skip any dividers */
2485 while ((*t == ' ') || (*t == '|')) t++;
2488 /* XXX XXX XXX Hack -- Read spell frequency */
2489 if (1 == sscanf(s, "1_IN_%d", &i))
2491 /* Extract a "frequency" */
2492 r_ptr->freq_spell = r_ptr->freq_inate = 100 / i;
2494 /* Start at next entry */
2501 /* Parse this entry */
2502 if (0 != grab_one_spell_flag(r_ptr, s)) return (5);
2504 /* Start the next entry */
2519 * Grab one flag for a dungeon type from a textual string
2521 static errr grab_one_dungeon_flag(dungeon_info_type *d_ptr, cptr what)
2526 for (i = 0; i < 32; i++)
2528 if (streq(what, d_info_flags1[i]))
2530 d_ptr->flags1 |= (1L << i);
2537 msg_format("̤ÃΤΥÀ¥ó¥¸¥ç¥ó¡¦¥Õ¥é¥° '%s'¡£", what);
2539 msg_format("Unknown dungeon type flag '%s'.", what);
2547 * Grab one (basic) flag in a monster_race from a textual string
2549 static errr grab_one_basic_monster_flag(dungeon_info_type *d_ptr, cptr what)
2554 for (i = 0; i < 32; i++)
2556 if (streq(what, r_info_flags1[i]))
2558 d_ptr->mflags1 |= (1L << i);
2564 for (i = 0; i < 32; i++)
2566 if (streq(what, r_info_flags2[i]))
2568 d_ptr->mflags2 |= (1L << i);
2574 for (i = 0; i < 32; i++)
2576 if (streq(what, r_info_flags3[i]))
2578 d_ptr->mflags3 |= (1L << i);
2584 for (i = 0; i < 32; i++)
2586 if (streq(what, r_info_flags7[i]))
2588 d_ptr->mflags7 |= (1L << i);
2594 for (i = 0; i < 32; i++)
2596 if (streq(what, r_info_flags8[i]))
2598 d_ptr->mflags8 |= (1L << i);
2604 for (i = 0; i < 32; i++)
2606 if (streq(what, r_info_flags9[i]))
2608 d_ptr->mflags9 |= (1L << i);
2615 msg_format("̤ÃΤΥâ¥ó¥¹¥¿¡¼¡¦¥Õ¥é¥° '%s'¡£", what);
2617 msg_format("Unknown monster flag '%s'.", what);
2625 * Grab one (spell) flag in a monster_race from a textual string
2627 static errr grab_one_spell_monster_flag(dungeon_info_type *d_ptr, cptr what)
2632 for (i = 0; i < 32; i++)
2634 if (streq(what, r_info_flags4[i]))
2636 d_ptr->mflags4 |= (1L << i);
2642 for (i = 0; i < 32; i++)
2644 if (streq(what, r_info_flags5[i]))
2646 d_ptr->mflags5 |= (1L << i);
2652 for (i = 0; i < 32; i++)
2654 if (streq(what, r_info_flags6[i]))
2656 d_ptr->mflags6 |= (1L << i);
2663 msg_format("̤ÃΤΥâ¥ó¥¹¥¿¡¼¡¦¥Õ¥é¥° '%s'¡£", what);
2665 msg_format("Unknown monster flag '%s'.", what);
2673 * Initialize the "d_info" array, by parsing an ascii "template" file
2675 errr parse_d_info(char *buf, header *head)
2682 static dungeon_info_type *d_ptr = NULL;
2685 /* Process 'N' for "New/Number/Name" */
2688 /* Find the colon before the name */
2689 s = strchr(buf+2, ':');
2691 /* Verify that colon */
2694 /* Nuke the colon, advance to the name */
2697 /* Paranoia -- require a name */
2698 if (!*s) return (1);
2703 /* Verify information */
2704 if (i < error_idx) return (4);
2706 /* Verify information */
2707 if (i >= head->info_num) return (2);
2709 /* Save the index */
2712 /* Point at the "info" */
2715 /* Hack -- Verify space */
2716 if (head->name_size + strlen(s) + 8 > fake_name_size) return (7);
2718 /* Advance and Save the name index */
2719 if (!d_ptr->name) d_ptr->name = ++head->name_size;
2721 /* Append chars to the name */
2722 strcpy(head->name_ptr + head->name_size, s);
2724 /* Advance the index */
2725 head->name_size += strlen(s);
2730 else if (buf[0] == 'E') return (0);
2732 else if (buf[0] == 'E')
2734 /* Acquire the Text */
2737 /* Hack -- Verify space */
2738 if (head->name_size + strlen(s) + 8 > fake_name_size) return (7);
2740 /* Advance and Save the name index */
2741 if (!d_ptr->name) d_ptr->name = ++head->name_size;
2743 /* Append chars to the name */
2744 strcpy(head->name_ptr + head->name_size, s);
2746 /* Advance the index */
2747 head->name_size += strlen(s);
2751 /* Process 'D' for "Description */
2752 else if (buf[0] == 'D')
2757 /* Acquire the text */
2762 /* Acquire the text */
2766 /* Hack -- Verify space */
2767 if (head->text_size + strlen(s) + 8 > fake_text_size) return (7);
2769 /* Advance and Save the text index */
2770 if (!d_ptr->text) d_ptr->text = ++head->text_size;
2772 /* Append chars to the name */
2773 strcpy(d_text + head->text_size, s);
2775 /* Advance the index */
2776 head->text_size += strlen(s);
2779 /* Process 'W' for "More Info" (one line only) */
2780 else if (buf[0] == 'W')
2782 int min_lev, max_lev;
2784 int min_alloc, max_chance;
2785 int obj_good, obj_great;
2788 /* Scan for the values */
2789 if (10 != sscanf(buf+2, "%d:%d:%d:%d:%d:%d:%d:%d:%x:%x",
2790 &min_lev, &max_lev, &min_plev, &mode, &min_alloc, &max_chance, &obj_good, &obj_great, (unsigned int *)&pit, (unsigned int *)&nest)) return (1);
2792 /* Save the values */
2793 d_ptr->mindepth = min_lev;
2794 d_ptr->maxdepth = max_lev;
2795 d_ptr->min_plev = min_plev;
2797 d_ptr->min_m_alloc_level = min_alloc;
2798 d_ptr->max_m_alloc_chance = max_chance;
2799 d_ptr->obj_good = obj_good;
2800 d_ptr->obj_great = obj_great;
2805 /* Process 'P' for "Place Info" */
2806 else if (buf[0] == 'P')
2810 /* Scan for the values */
2811 if (2 != sscanf(buf+2, "%d:%d", &dy, &dx)) return (1);
2813 /* Save the values */
2818 /* Process 'L' for "fLoor type" (one line only) */
2819 else if (buf[0] == 'L')
2825 /* Scan for the values */
2826 if (7 != sscanf(buf+2, "%d:%d:%d:%d:%d:%d:%d",
2827 &f1, &p1, &f2, &p2, &f3, &p3, &tunnel)) return (1);
2829 /* Save the values */
2831 d_ptr->floor_percent1 = p1;
2833 d_ptr->floor_percent2 = p2;
2835 d_ptr->floor_percent3 = p3;
2836 d_ptr->tunnel_percent = tunnel;
2839 /* Process 'A' for "wAll type" (one line only) */
2840 else if (buf[0] == 'A')
2842 int w1, w2, w3, outer, inner, stream1, stream2;
2845 /* Scan for the values */
2846 if (10 != sscanf(buf+2, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
2847 &w1, &p1, &w2, &p2, &w3, &p3, &outer, &inner, &stream1, &stream2)) return (1);
2849 /* Save the values */
2850 d_ptr->fill_type1 = w1;
2851 d_ptr->fill_percent1 = p1;
2852 d_ptr->fill_type2 = w2;
2853 d_ptr->fill_percent2 = p2;
2854 d_ptr->fill_type3 = w3;
2855 d_ptr->fill_percent3 = p3;
2856 d_ptr->outer_wall = outer;
2857 d_ptr->inner_wall = inner;
2858 d_ptr->stream1 = stream1;
2859 d_ptr->stream2 = stream2;
2862 /* Process 'F' for "Dungeon Flags" (multiple lines) */
2863 else if (buf[0] == 'F')
2865 int artif = 0, monst = 0;
2867 /* Parse every entry */
2868 for (s = buf + 2; *s; )
2870 /* Find the end of this entry */
2871 for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
2873 /* Nuke and skip any dividers */
2877 while (*t == ' ' || *t == '|') t++;
2880 /* XXX XXX XXX Hack -- Read Final Artifact */
2881 if (1 == sscanf(s, "FINAL_ARTIFACT_%d", &artif))
2883 /* Extract a "Final Artifact" */
2884 d_ptr->final_artifact = artif;
2886 /* Start at next entry */
2893 /* XXX XXX XXX Hack -- Read Final Object */
2894 if (1 == sscanf(s, "FINAL_OBJECT_%d", &artif))
2896 /* Extract a "Final Artifact" */
2897 d_ptr->final_object = artif;
2899 /* Start at next entry */
2906 /* XXX XXX XXX Hack -- Read Artifact Guardian */
2907 if (1 == sscanf(s, "FINAL_GUARDIAN_%d", &monst))
2909 /* Extract a "Artifact Guardian" */
2910 d_ptr->final_guardian = monst;
2912 /* Start at next entry */
2919 /* XXX XXX XXX Hack -- Read Special Percentage */
2920 if (1 == sscanf(s, "MONSTER_DIV_%d", &monst))
2922 /* Extract a "Special %" */
2923 d_ptr->special_div = monst;
2925 /* Start at next entry */
2932 /* Parse this entry */
2933 if (0 != grab_one_dungeon_flag(d_ptr, s)) return (5);
2935 /* Start the next entry */
2940 /* Process 'M' for "Basic Flags" (multiple lines) */
2941 else if (buf[0] == 'M')
2943 byte r_char_number = 0, r_char;
2945 /* Parse every entry */
2946 for (s = buf + 2; *s; )
2948 /* Find the end of this entry */
2949 for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
2951 /* Nuke and skip any dividers */
2955 while (*t == ' ' || *t == '|') t++;
2958 /* XXX XXX XXX Hack -- Read monster symbols */
2959 if (1 == sscanf(s, "R_CHAR_%c", &r_char))
2961 /* Limited to 5 races */
2962 if(r_char_number >= 5) continue;
2964 /* Extract a "frequency" */
2965 d_ptr->r_char[r_char_number++] = r_char;
2967 /* Start at next entry */
2974 /* Parse this entry */
2975 if (0 != grab_one_basic_monster_flag(d_ptr, s)) return (5);
2977 /* Start the next entry */
2982 /* Process 'S' for "Spell Flags" (multiple lines) */
2983 else if (buf[0] == 'S')
2985 /* Parse every entry */
2986 for (s = buf + 2; *s; )
2988 /* Find the end of this entry */
2989 for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
2991 /* Nuke and skip any dividers */
2995 while ((*t == ' ') || (*t == '|')) t++;
2998 /* XXX XXX XXX Hack -- Read spell frequency */
2999 if (1 == sscanf(s, "1_IN_%d", &i))
3001 /* Start at next entry */
3008 /* Parse this entry */
3009 if (0 != grab_one_spell_monster_flag(d_ptr, s)) return (5);
3011 /* Start the next entry */
3024 #else /* ALLOW_TEMPLATES */
3030 #endif /* ALLOW_TEMPLATES */
3033 /* Random dungeon grid effects */
3034 #define RANDOM_NONE 0x00
3035 #define RANDOM_FEATURE 0x01
3036 #define RANDOM_MONSTER 0x02
3037 #define RANDOM_OBJECT 0x04
3038 #define RANDOM_EGO 0x08
3039 #define RANDOM_ARTIFACT 0x10
3040 #define RANDOM_TRAP 0x20
3043 typedef struct dungeon_grid dungeon_grid;
3047 int feature; /* Terrain feature */
3048 int monster; /* Monster */
3049 int object; /* Object */
3050 int ego; /* Ego-Item */
3051 int artifact; /* Artifact */
3052 int trap; /* Trap */
3053 int cave_info; /* Flags for CAVE_MARK, CAVE_GLOW, CAVE_ICKY, CAVE_ROOM */
3054 int special; /* Reserved for special terrain info */
3055 int random; /* Number of the random effect */
3059 static dungeon_grid letter[255];
3063 * Process "F:<letter>:<terrain>:<cave_info>:<monster>:<object>:<ego>:<artifact>:<trap>:<special>" -- info for dungeon grid
3065 static errr parse_line_feature(char *buf)
3071 if (init_flags & INIT_ONLY_BUILDINGS) return (0);
3073 /* Tokenize the line */
3074 if ((num = tokenize(buf+2, 9, zz, 0)) > 1)
3076 /* Letter to assign */
3077 int index = zz[0][0];
3079 /* Reset the info for the letter */
3080 letter[index].feature = 0;
3081 letter[index].monster = 0;
3082 letter[index].object = 0;
3083 letter[index].ego = 0;
3084 letter[index].artifact = 0;
3085 letter[index].trap = 0;
3086 letter[index].cave_info = 0;
3087 letter[index].special = 0;
3088 letter[index].random = 0;
3094 letter[index].special = atoi(zz[8]);
3098 if (zz[7][0] == '*')
3100 letter[index].random |= RANDOM_TRAP;
3105 letter[index].trap = atoi(zz[7]);
3110 letter[index].trap = atoi(zz[7]);
3115 if (zz[6][0] == '*')
3117 letter[index].random |= RANDOM_ARTIFACT;
3122 letter[index].artifact = atoi(zz[6]);
3127 letter[index].artifact = atoi(zz[6]);
3132 if (zz[5][0] == '*')
3134 letter[index].random |= RANDOM_EGO;
3139 letter[index].ego = atoi(zz[5]);
3144 letter[index].ego = atoi(zz[5]);
3149 if (zz[4][0] == '*')
3151 letter[index].random |= RANDOM_OBJECT;
3156 letter[index].object = atoi(zz[4]);
3161 letter[index].object = atoi(zz[4]);
3166 if (zz[3][0] == '*')
3168 letter[index].random |= RANDOM_MONSTER;
3172 letter[index].monster = atoi(zz[3]);
3177 letter[index].monster = atoi(zz[3]);
3182 letter[index].cave_info = atoi(zz[2]);
3186 if (zz[1][0] == '*')
3188 letter[index].random |= RANDOM_FEATURE;
3192 letter[index].feature = atoi(zz[1]);
3197 letter[index].feature = atoi(zz[1]);
3210 * Process "F:<letter>:<terrain>:<cave_info>:<monster>:<object>:<ego>:<artifact>:<trap>:<special>" -- info for dungeon grid
3212 static errr parse_line_building(char *buf)
3228 /* Get the building number */
3231 /* Find the colon after the building number */
3234 /* Verify that colon */
3237 /* Nuke the colon, advance to the sub-index */
3240 /* Paranoia -- require a sub-index */
3241 if (!*s) return (1);
3243 /* Building definition sub-index */
3246 /* Building name, owner, race */
3249 if (tokenize(s + 2, 3, zz, 0) == 3)
3251 /* Name of the building */
3252 strcpy(building[index].name, zz[0]);
3254 /* Name of the owner */
3255 strcpy(building[index].owner_name, zz[1]);
3257 /* Race of the owner */
3258 strcpy(building[index].owner_race, zz[2]);
3263 return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3266 /* Building Action */
3269 if (tokenize(s + 2, 8, zz, 0) >= 7)
3271 /* Index of the action */
3272 int action_index = atoi(zz[0]);
3274 /* Name of the action */
3275 strcpy(building[index].act_names[action_index], zz[1]);
3277 /* Cost of the action for members */
3278 building[index].member_costs[action_index] = atoi(zz[2]);
3280 /* Cost of the action for non-members */
3281 building[index].other_costs[action_index] = atoi(zz[3]);
3283 /* Letter assigned to the action */
3284 building[index].letters[action_index] = zz[4][0];
3287 building[index].actions[action_index] = atoi(zz[5]);
3289 /* Action restriction */
3290 building[index].action_restr[action_index] = atoi(zz[6]);
3295 return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3298 /* Building Classes */
3301 if (tokenize(s + 2, MAX_CLASS, zz, 0) == MAX_CLASS)
3303 for (i = 0; i < MAX_CLASS; i++)
3305 building[index].member_class[i] = atoi(zz[i]);
3311 return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3314 /* Building Races */
3317 if (tokenize(s+2, MAX_RACES, zz, 0) == MAX_RACES)
3319 for (i = 0; i < MAX_RACES; i++)
3321 building[index].member_race[i] = atoi(zz[i]);
3327 return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3330 /* Building Realms */
3333 if (tokenize(s+2, MAX_MAGIC, zz, 0) == MAX_MAGIC)
3335 for (i = 0; i < MAX_MAGIC; i++)
3337 building[index].member_realm[i+1] = atoi(zz[i]);
3343 return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3349 if (tokenize(s+2, 2, zz, 0) == 2)
3351 /* Index of the action */
3352 int action_index = atoi(zz[0]);
3354 /* Name of the action */
3355 strcpy(building[index].act_script[action_index], zz[1]);
3360 #else /* USE_SCRIPT */
3361 /* Ignore scripts */
3363 #endif /* USE_SCRIPT */
3368 return (PARSE_ERROR_UNDEFINED_DIRECTIVE);
3377 * Parse a sub-file of the "extra info"
3379 static errr process_dungeon_file_aux(char *buf, int ymin, int xmin, int ymax, int xmax, int *y, int *x)
3386 /* Skip "empty" lines */
3387 if (!buf[0]) return (0);
3389 /* Skip "blank" lines */
3390 if (isspace(buf[0])) return (0);
3393 if (buf[0] == '#') return (0);
3395 /* Require "?:*" format */
3396 if (buf[1] != ':') return (1);
3399 /* Process "%:<fname>" */
3402 /* Attempt to Process the given file */
3403 return (process_dungeon_file(buf + 2, ymin, xmin, ymax, xmax));
3406 /* Process "F:<letter>:<terrain>:<cave_info>:<monster>:<object>:<ego>:<artifact>:<trap>:<special>" -- info for dungeon grid */
3409 return parse_line_feature(buf);
3412 /* Process "D:<dungeon>" -- info for the cave grids */
3413 else if (buf[0] == 'D')
3415 object_type object_type_body;
3417 /* Acquire the text */
3420 /* Length of the text */
3421 int len = strlen(s);
3423 if (init_flags & INIT_ONLY_BUILDINGS) return (0);
3425 for (*x = xmin, i = 0; ((*x < xmax) && (i < len)); (*x)++, s++, i++)
3427 /* Access the grid */
3428 cave_type *c_ptr = &cave[*y][*x];
3432 int object_index = letter[idx].object;
3433 int monster_index = letter[idx].monster;
3434 int random = letter[idx].random;
3435 int artifact_index = letter[idx].artifact;
3437 /* Lay down a floor */
3438 c_ptr->feat = letter[idx].feature;
3440 /* Only the features */
3441 if (init_flags & INIT_ONLY_FEATURES) continue;
3444 c_ptr->info = letter[idx].cave_info;
3446 /* Create a monster */
3447 if (random & RANDOM_MONSTER)
3449 monster_level = base_level + monster_index;
3451 place_monster(*y, *x, TRUE, TRUE);
3453 monster_level = base_level;
3455 else if (monster_index)
3457 /* Make alive again */
3458 if (r_info[monster_index].flags1 & RF1_UNIQUE)
3460 r_info[monster_index].cur_num = 0;
3461 r_info[monster_index].max_num = 1;
3464 /* Make alive again */
3465 if (r_info[monster_index].flags7 & RF7_UNIQUE_7)
3467 if (r_info[monster_index].cur_num == r_info[monster_index].max_num)
3469 r_info[monster_index].max_num++;
3474 place_monster_aux(*y, *x, monster_index, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE);
3477 /* Object (and possible trap) */
3478 if ((random & RANDOM_OBJECT) && (random & RANDOM_TRAP))
3480 object_level = base_level + object_index;
3483 * Random trap and random treasure defined
3484 * 25% chance for trap and 75% chance for object
3486 if (rand_int(100) < 75)
3488 place_object(*y, *x, FALSE, FALSE);
3495 object_level = base_level;
3497 else if (random & RANDOM_OBJECT)
3499 object_level = base_level + object_index;
3501 /* Create an out of deep object */
3502 if (rand_int(100) < 75)
3503 place_object(*y, *x, FALSE, FALSE);
3504 else if (rand_int(100) < 80)
3505 place_object(*y, *x, TRUE, FALSE);
3507 place_object(*y, *x, TRUE, TRUE);
3509 object_level = base_level;
3512 else if (random & RANDOM_TRAP)
3516 else if (object_index)
3518 /* Get local object */
3519 object_type *o_ptr = &object_type_body;
3521 /* Create the item */
3522 object_prep(o_ptr, object_index);
3524 if (o_ptr->tval == TV_GOLD)
3526 coin_type = object_index - OBJ_GOLD_LIST;
3531 /* Apply magic (no messages, no artifacts) */
3532 apply_magic(o_ptr, base_level, FALSE, TRUE, FALSE, FALSE);
3535 o_ptr->python = object_create_callback(o_ptr);
3536 #endif /* USE_SCRIPT */
3538 (void)drop_near(o_ptr, -1, *y, *x);
3544 if (a_info[artifact_index].cur_num)
3548 object_type *q_ptr = &forge;
3550 object_prep(q_ptr, k_idx);
3552 q_ptr->python = object_create_callback(q_ptr);
3553 #endif /* USE_SCRIPT */
3555 /* Drop it in the dungeon */
3556 (void)drop_near(q_ptr, -1, *y, *x);
3560 /* Create the artifact */
3561 create_named_art(artifact_index, *y, *x);
3563 a_info[artifact_index].cur_num = 1;
3567 /* Terrain special */
3568 c_ptr->special = letter[idx].special;
3576 /* Process "Q:<number>:<command>:... -- quest info */
3577 else if (buf[0] == 'Q')
3584 num = tokenize(buf + 2, 33, zz, 0);
3588 num = tokenize(buf + 3, 33, zz, 0);
3591 /* Have we enough parameters? */
3592 if (num < 3) return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3595 q_ptr = &(quest[atoi(zz[0])]);
3597 /* Process "Q:<q_index>:Q:<type>:<num_mon>:<cur_num>:<max_num>:<level>:<r_idx>:<k_idx>:<flags>" -- quest info */
3598 if (zz[1][0] == 'Q')
3600 if (init_flags & INIT_ASSIGN)
3602 monster_race *r_ptr;
3603 artifact_type *a_ptr;
3605 if (num < 9) return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3607 q_ptr->type = atoi(zz[2]);
3608 q_ptr->num_mon = atoi(zz[3]);
3609 q_ptr->cur_num = atoi(zz[4]);
3610 q_ptr->max_num = atoi(zz[5]);
3611 q_ptr->level = atoi(zz[6]);
3612 q_ptr->r_idx = atoi(zz[7]);
3613 q_ptr->k_idx = atoi(zz[8]);
3614 q_ptr->dungeon = atoi(zz[9]);
3617 q_ptr->flags = atoi(zz[10]);
3619 r_ptr = &r_info[q_ptr->r_idx];
3620 if (r_ptr->flags1 & RF1_UNIQUE)
3621 r_ptr->flags1 |= RF1_QUESTOR;
3623 a_ptr = &a_info[q_ptr->k_idx];
3624 a_ptr->flags3 |= TR3_QUESTITEM;
3629 /* Process "Q:<q_index>:N:<name>" -- quest name */
3630 else if (zz[1][0] == 'N')
3632 if (init_flags & (INIT_ASSIGN | INIT_SHOW_TEXT))
3634 strcpy(q_ptr->name, zz[2]);
3640 /* Process "Q:<q_index>:T:<text>" -- quest description line */
3641 else if (zz[1][0] == 'T')
3643 if (init_flags & INIT_SHOW_TEXT)
3645 strcpy(quest_text[quest_text_line], zz[2]);
3653 /* Process "W:<command>: ..." -- info for the wilderness */
3654 else if (buf[0] == 'W')
3656 return parse_line_wilderness(buf, ymin, xmin, ymax, xmax, y, x);
3659 /* Process "P:<y>:<x>" -- player position */
3660 else if (buf[0] == 'P')
3662 if (init_flags & INIT_CREATE_DUNGEON)
3664 if (tokenize(buf + 2, 2, zz, 0) == 2)
3666 int panels_x, panels_y;
3668 /* Hack - Set the dungeon size */
3669 panels_y = (*y / SCREEN_HGT);
3670 if (*y % SCREEN_HGT) panels_y++;
3671 cur_hgt = panels_y * SCREEN_HGT;
3673 panels_x = (*x / SCREEN_WID);
3674 if (*x % SCREEN_WID) panels_x++;
3675 cur_wid = panels_x * SCREEN_WID;
3677 /* Choose a panel row */
3678 max_panel_rows = (cur_hgt / SCREEN_HGT) * 2 - 2;
3679 if (max_panel_rows < 0) max_panel_rows = 0;
3681 /* Choose a panel col */
3682 max_panel_cols = (cur_wid / SCREEN_WID) * 2 - 2;
3683 if (max_panel_cols < 0) max_panel_cols = 0;
3685 /* Assume illegal panel */
3686 panel_row = max_panel_rows;
3687 panel_col = max_panel_cols;
3689 /* Place player in a quest level */
3690 if (p_ptr->inside_quest)
3694 /* Delete the monster (if any) */
3695 delete_monster(py, px);
3703 /* Place player in the town */
3704 else if (!p_ptr->oldpx && !p_ptr->oldpy)
3706 p_ptr->oldpy = atoi(zz[0]);
3707 p_ptr->oldpx = atoi(zz[1]);
3715 /* Process "B:<Index>:<Command>:..." -- Building definition */
3716 else if (buf[0] == 'B')
3718 return parse_line_building(buf);
3721 /* Process "M:<type>:<maximum>" -- set maximum values */
3722 else if (buf[0] == 'M')
3724 if (tokenize(buf+2, 2, zz, 0) == 2)
3727 if (zz[0][0] == 'T')
3729 max_towns = atoi(zz[1]);
3732 /* Maximum quests */
3733 else if (zz[0][0] == 'Q')
3735 max_quests = atoi(zz[1]);
3739 else if (zz[0][0] == 'R')
3741 max_r_idx = atoi(zz[1]);
3745 else if (zz[0][0] == 'K')
3747 max_k_idx = atoi(zz[1]);
3751 else if (zz[0][0] == 'V')
3753 max_v_idx = atoi(zz[1]);
3757 else if (zz[0][0] == 'F')
3759 max_f_idx = atoi(zz[1]);
3763 else if (zz[0][0] == 'A')
3765 max_a_idx = atoi(zz[1]);
3769 else if (zz[0][0] == 'E')
3771 max_e_idx = atoi(zz[1]);
3775 else if (zz[0][0] == 'D')
3777 max_d_idx = atoi(zz[1]);
3781 else if (zz[0][0] == 'O')
3783 max_o_idx = atoi(zz[1]);
3787 else if (zz[0][0] == 'M')
3789 max_m_idx = atoi(zz[1]);
3792 /* Wilderness size */
3793 else if (zz[0][0] == 'W')
3795 /* Maximum wild_x_size */
3796 if (zz[0][1] == 'X')
3797 max_wild_x = atoi(zz[1]);
3798 /* Maximum wild_y_size */
3799 if (zz[0][1] == 'Y')
3800 max_wild_y = atoi(zz[1]);
3814 static cptr variant = "ZANGBAND";
3818 * Helper function for "process_dungeon_file()"
3820 static cptr process_dungeon_file_expr(char **sp, char *fp)
3836 while (isspace(*s)) s++;
3854 t = process_dungeon_file_expr(&s, &f);
3863 else if (streq(t, "IOR"))
3866 while (*s && (f != b2))
3868 t = process_dungeon_file_expr(&s, &f);
3869 if (*t && !streq(t, "0")) v = "1";
3874 else if (streq(t, "AND"))
3877 while (*s && (f != b2))
3879 t = process_dungeon_file_expr(&s, &f);
3880 if (*t && streq(t, "0")) v = "0";
3885 else if (streq(t, "NOT"))
3888 while (*s && (f != b2))
3890 t = process_dungeon_file_expr(&s, &f);
3891 if (*t && streq(t, "1")) v = "0";
3896 else if (streq(t, "EQU"))
3899 if (*s && (f != b2))
3901 t = process_dungeon_file_expr(&s, &f);
3903 while (*s && (f != b2))
3906 t = process_dungeon_file_expr(&s, &f);
3907 if (*t && !streq(p, t)) v = "0";
3912 else if (streq(t, "LEQ"))
3915 if (*s && (f != b2))
3917 t = process_dungeon_file_expr(&s, &f);
3919 while (*s && (f != b2))
3922 t = process_dungeon_file_expr(&s, &f);
3923 if (*t && (strcmp(p, t) > 0)) v = "0";
3928 else if (streq(t, "GEQ"))
3931 if (*s && (f != b2))
3933 t = process_dungeon_file_expr(&s, &f);
3935 while (*s && (f != b2))
3938 t = process_dungeon_file_expr(&s, &f);
3939 if (*t && (strcmp(p, t) < 0)) v = "0";
3946 while (*s && (f != b2))
3948 t = process_dungeon_file_expr(&s, &f);
3953 if (f != b2) v = "?x?x?";
3955 /* Extract final and Terminate */
3956 if ((f = *s) != '\0') *s++ = '\0';
3962 /* Accept all printables except spaces and brackets */
3963 while (isprint(*s) && !strchr(" []", *s)) ++s;
3965 /* Extract final and Terminate */
3966 if ((f = *s) != '\0') *s++ = '\0';
3972 if (streq(b+1, "SYS"))
3978 else if (streq(b+1, "GRAF"))
3983 else if (streq(b+1, "MONOCHROME"))
3992 else if (streq(b+1, "RACE"))
3995 v = rp_ptr->E_title;
4002 else if (streq(b+1, "CLASS"))
4005 v = cp_ptr->E_title;
4012 else if (streq(b+1, "REALM1"))
4015 v = E_realm_names[p_ptr->realm1];
4017 v = realm_names[p_ptr->realm1];
4022 else if (streq(b+1, "REALM2"))
4025 v = E_realm_names[p_ptr->realm2];
4027 v = realm_names[p_ptr->realm2];
4032 else if (streq(b+1, "PLAYER"))
4038 else if (streq(b+1, "TOWN"))
4040 sprintf(tmp, "%d", p_ptr->town_num);
4045 else if (streq(b+1, "LEVEL"))
4047 sprintf(tmp, "%d", p_ptr->lev);
4051 /* Current quest number */
4052 else if (streq(b+1, "QUEST_NUMBER"))
4054 sprintf(tmp, "%d", p_ptr->inside_quest);
4058 /* Number of last quest */
4059 else if (streq(b+1, "LEAVING_QUEST"))
4061 sprintf(tmp, "%d", leaving_quest);
4066 else if (prefix(b+1, "QUEST"))
4068 /* "QUEST" uses a special parameter to determine the number of the quest */
4069 sprintf(tmp, "%d", quest[atoi(b+6)].status);
4074 else if (prefix(b+1, "RANDOM"))
4076 /* "RANDOM" uses a special parameter to determine the number of the quest */
4077 sprintf(tmp, "%d", (int)(seed_town%atoi(b+7)));
4082 else if (streq(b+1, "VARIANT"))
4088 else if (streq(b+1, "WILDERNESS"))
4091 sprintf(tmp, "NONE");
4093 sprintf(tmp, "LITE");
4095 sprintf(tmp, "NORMAL");
4118 errr process_dungeon_file(cptr name, int ymin, int xmin, int ymax, int xmax)
4128 bool bypass = FALSE;
4130 int x = xmin, y = ymin;
4133 /* Build the filename */
4134 path_build(buf, 1024, ANGBAND_DIR_EDIT, name);
4137 fp = my_fopen(buf, "r");
4140 if (!fp) return (-1);
4143 /* Process the file */
4144 while (0 == my_fgets(fp, buf, 1024))
4150 /* Skip "empty" lines */
4151 if (!buf[0]) continue;
4153 /* Skip "blank" lines */
4154 if (isspace(buf[0])) continue;
4157 if (buf[0] == '#') continue;
4160 /* Process "?:<expr>" */
4161 if ((buf[0] == '?') && (buf[1] == ':'))
4170 /* Parse the expr */
4171 v = process_dungeon_file_expr(&s, &f);
4174 bypass = (streq(v, "0") ? TRUE : FALSE);
4180 /* Apply conditionals */
4181 if (bypass) continue;
4184 /* Process "%:<file>" */
4187 /* Process that file if allowed */
4188 (void)process_dungeon_file(buf + 2, ymin, xmin, ymax, xmax);
4195 /* Process the line */
4196 err = process_dungeon_file_aux(buf, ymin, xmin, ymax, xmax, &y, &x);
4208 oops = (((err > 0) && (err < PARSE_ERROR_MAX)) ? err_str[err] : "unknown");
4211 msg_format("Error %d (%s) at line %d of '%s'.", err, oops, num, name);
4213 msg_format("'%s'¤ò²òÀÏÃæ¡£", buf);
4215 msg_format("Parsing '%s'.", buf);
4222 /* Close the file */
4232 void write_r_info_txt(void)
4234 int i, j, z, fc, bc;
4242 monster_race *r_ptr;
4244 monster_blow *b_ptr;
4246 FILE *fff = fopen("output.txt", "wt");
4254 fprintf(fff, "# File: r_info.txt (autogenerated)\n\n");
4256 fprintf(fff, "# Version stamp (required)\n\n");
4259 fprintf(fff, "V:%d.%d.%d\n\n\n", r_head->v_major, r_head->v_minor, r_head->v_patch);
4262 fprintf(fff, "##### The Player #####\n\n");
4264 for (z = -1; z < alloc_race_size; z++)
4266 /* Output the monsters in order */
4267 i = (z >= 0) ? alloc_race_table[z].index : 0;
4269 /* Acquire the monster */
4272 /* Ignore empty monsters */
4273 if (!strlen(r_name + r_ptr->name)) continue;
4275 /* Ignore useless monsters */
4276 if (i && !r_ptr->speed) continue;
4278 /* Write a note if necessary */
4279 if (i && (!r_ptr->level != !mode))
4284 fprintf(fff, "\n##### Town monsters #####\n\n");
4286 /* Note the dungeon */
4289 fprintf(fff, "\n##### Normal monsters #####\n\n");
4292 /* Record the change */
4293 mode = r_ptr->level;
4296 /* Acquire the flags */
4297 f_ptr[0] = r_ptr->flags1; n_ptr[0] = r_info_flags1;
4298 f_ptr[1] = r_ptr->flags2; n_ptr[1] = r_info_flags2;
4299 f_ptr[2] = r_ptr->flags3; n_ptr[2] = r_info_flags3;
4300 f_ptr[3] = r_ptr->flags4; n_ptr[3] = r_info_flags4;
4301 f_ptr[4] = r_ptr->flags5; n_ptr[4] = r_info_flags5;
4302 f_ptr[5] = r_ptr->flags6; n_ptr[5] = r_info_flags6;
4303 f_ptr[6] = r_ptr->flags7; n_ptr[6] = r_info_flags7;
4304 f_ptr[7] = r_ptr->flags8; n_ptr[7] = r_info_flags8;
4305 f_ptr[8] = r_ptr->flags9; n_ptr[8] = r_info_flags9;
4307 /* Write New/Number/Name */
4308 fprintf(fff, "N:%d:%s\n", z + 1, r_name + r_ptr->name);
4311 fprintf(fff, "G:%c:%c\n", r_ptr->d_char, color_char[r_ptr->d_attr]);
4313 /* Write Information */
4314 fprintf(fff, "I:%d:%dd%d:%d:%d:%d\n", r_ptr->speed, r_ptr->hdice, r_ptr->hside,
4315 r_ptr->aaf, r_ptr->ac, r_ptr->sleep);
4317 /* Write more information */
4318 fprintf(fff, "W:%d:%d:%d:%ld\n", r_ptr->level, r_ptr->rarity, r_ptr->extra, r_ptr->mexp);
4321 for(j = 0; j < 4; j++)
4323 b_ptr = &(r_ptr->blow[j]);
4325 /* Stop when done */
4326 if (!b_ptr->method) break;
4328 /* Write the blows */
4329 fprintf(fff, "B:%s:%s:%dd%d\n", r_info_blow_method[b_ptr->method],
4330 r_info_blow_effect[b_ptr->effect],
4331 b_ptr->d_dice, b_ptr->d_side);
4334 /* Extract the flags */
4335 for (fc = 0, j = 0; j < 96; j++)
4337 /* Check this flag */
4338 if (f_ptr[j / 32] & (1L << (j % 32))) flags[fc++] = n_ptr[j / 32][j % 32];
4341 /* Extract the extra flags */
4342 for (j = 192; j < 288; j++)
4344 /* Check this flag */
4345 if (f_ptr[j / 32] & (1L << (j % 32))) flags[fc++] = n_ptr[j / 32][j % 32];
4348 /* Write the flags */
4349 for (j = 0; j < fc;)
4353 /* Start the line */
4356 for (bc = 0; (bc < 60) && (j < fc); j++)
4360 /* Format the flag */
4361 sprintf(t, "%s%s", flags[j], (j < fc - 1) ? " | " : "");
4363 /* Add it to the buffer */
4366 /* Note the length */
4370 /* Done with this line; write it */
4371 fprintf(fff, "%s\n", buf);
4374 /* Write Spells if applicable */
4375 if (r_ptr->freq_spell)
4377 /* Write the frequency */
4378 fprintf(fff, "S:1_IN_%d | \n", 100 / r_ptr->freq_spell);
4380 /* Extract the spell flags */
4381 for (fc = 0, j = 96; j < 192; j++)
4383 /* Check this flag */
4384 if (f_ptr[j / 32] & (1L << (j % 32))) flags[fc++] = n_ptr[j / 32][j % 32];
4387 /* Write the flags */
4388 for (j = 0; j < fc;)
4392 /* Start the line */
4395 for (bc = 0, t = buf + 2; (bc < 60) && (j < fc); j++)
4399 /* Format the flag */
4400 sprintf(t, "%s%s", flags[j], (j < fc - 1) ? " | " : "");
4404 /* Note the length */
4411 /* Done with this line; write it */
4412 fprintf(fff, "%s\n", buf);
4416 /* Acquire the description */
4417 desc = r_text + r_ptr->text;
4418 dlen = strlen(desc);
4420 /* Write Description */
4421 for (j = 0; j < dlen;)
4425 /* Start the line */
4428 for (bc = 0, t = buf + 2; ((bc < 60) || !isspace(desc[j])) && (j < dlen); j++, bc++, t++)
4436 /* Done with this line; write it */
4437 fprintf(fff, "%s\n", buf);
4440 /* Space between entries */