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')
1120 else if (buf[0] == 'E')
1122 /* Acquire the Text */
1125 /* Hack -- Verify space */
1126 if (head->name_size + strlen(s) + 8 > fake_name_size) return (7);
1128 /* Advance and Save the name index */
1129 if (!f_ptr->name) f_ptr->name = ++head->name_size;
1131 /* Append chars to the name */
1132 strcpy(head->name_ptr + head->name_size, s);
1134 /* Advance the index */
1135 head->name_size += strlen(s);
1141 /* Process 'D' for "Description" */
1142 else if (buf[0] == 'D')
1144 /* Acquire the text */
1147 /* Hack -- Verify space */
1148 if (f_head->text_size + strlen(s) + 8 > fake_text_size) return (7);
1150 /* Advance and Save the text index */
1151 if (!f_ptr->text) f_ptr->text = ++f_head->text_size;
1153 /* Append chars to the name */
1154 strcpy(f_text + f_head->text_size, s);
1156 /* Advance the index */
1157 f_head->text_size += strlen(s);
1164 /* Process 'M' for "Mimic" (one line only) */
1165 else if (buf[0] == 'M')
1169 /* Scan for the values */
1170 if (1 != sscanf(buf+2, "%d",
1171 &mimic)) return (1);
1173 /* Save the values */
1174 f_ptr->mimic = mimic;
1179 /* Process 'G' for "Graphics" (one line only) */
1180 else if (buf[0] == 'G')
1185 if (!buf[2]) return (1);
1186 if (!buf[3]) return (1);
1187 if (!buf[4]) return (1);
1189 /* Extract the color */
1190 tmp = color_char_to_attr(buf[4]);
1193 if (tmp < 0) return (1);
1195 /* Save the values */
1196 f_ptr->d_attr = tmp;
1197 f_ptr->d_char = buf[2];
1210 * Grab one flag in an object_kind from a textual string
1212 static errr grab_one_kind_flag(object_kind *k_ptr, cptr what)
1217 for (i = 0; i < 32; i++)
1219 if (streq(what, k_info_flags1[i]))
1221 k_ptr->flags1 |= (1L << i);
1227 for (i = 0; i < 32; i++)
1229 if (streq(what, k_info_flags2[i]))
1231 k_ptr->flags2 |= (1L << i);
1237 for (i = 0; i < 32; i++)
1239 if (streq(what, k_info_flags3[i]))
1241 k_ptr->flags3 |= (1L << i);
1248 msg_format("̤ÃΤΥ¢¥¤¥Æ¥à¡¦¥Õ¥é¥° '%s'¡£", what);
1250 msg_format("Unknown object flag '%s'.", what);
1260 * Initialize the "k_info" array, by parsing an ascii "template" file
1262 errr parse_k_info(char *buf, header *head)
1269 static object_kind *k_ptr = NULL;
1272 /* Process 'N' for "New/Number/Name" */
1275 /* Find the colon before the name */
1276 s = strchr(buf+2, ':');
1278 /* Verify that colon */
1281 /* Nuke the colon, advance to the name */
1285 /* Paranoia -- require a name */
1286 if (!*s) return (1);
1291 /* Verify information */
1292 if (i <= error_idx) return (4);
1294 /* Verify information */
1295 if (i >= head->info_num) return (2);
1297 /* Save the index */
1300 /* Point at the "info" */
1304 /* Hack -- Verify space */
1305 if (head->name_size + strlen(s) + 8 > fake_name_size) return (7);
1307 /* Advance and Save the name index */
1308 if (!k_ptr->name) k_ptr->name = ++head->name_size;
1310 /* Append chars to the name */
1311 strcpy(head->name_ptr + head->name_size, s);
1313 /* Advance the index */
1314 head->name_size += strlen(s);
1318 /* There better be a current k_ptr */
1319 else if (!k_ptr) return (3);
1323 /* ±Ñ¸ì̾¤òÆɤà¥ë¡¼¥Á¥ó¤òÄɲà */
1324 /* 'E' ¤«¤é»Ï¤Þ¤ë¹Ô¤Ï±Ñ¸ì̾¤È¤·¤Æ¤¤¤ë */
1325 else if (buf[0] == 'E')
1330 else if (buf[0] == 'E')
1332 /* Acquire the Text */
1335 /* Hack -- Verify space */
1336 if (head->name_size + strlen(s) + 8 > fake_name_size) return (7);
1338 /* Advance and Save the name index */
1339 if (!k_ptr->name) k_ptr->name = ++head->name_size;
1341 /* Append chars to the name */
1342 strcpy(head->name_ptr + head->name_size, s);
1344 /* Advance the index */
1345 head->name_size += strlen(s);
1350 /* Process 'D' for "Description" */
1351 else if (buf[0] == 'D')
1353 /* Acquire the text */
1356 /* Hack -- Verify space */
1357 if (k_head->text_size + strlen(s) + 8 > fake_text_size) return (7);
1359 /* Advance and Save the text index */
1360 if (!k_ptr->text) k_ptr->text = ++k_head->text_size;
1362 /* Append chars to the name */
1363 strcpy(k_text + k_head->text_size, s);
1365 /* Advance the index */
1366 k_head->text_size += strlen(s);
1372 /* Process 'G' for "Graphics" (one line only) */
1373 else if (buf[0] == 'G')
1379 if (!buf[2]) return (1);
1380 if (!buf[3]) return (1);
1381 if (!buf[4]) return (1);
1383 /* Extract the char */
1386 /* Extract the attr */
1387 tmp = color_char_to_attr(buf[4]);
1390 if (tmp < 0) return (1);
1392 /* Save the values */
1393 k_ptr->d_attr = tmp;
1394 k_ptr->d_char = sym;
1397 /* Process 'I' for "Info" (one line only) */
1398 else if (buf[0] == 'I')
1400 int tval, sval, pval;
1402 /* Scan for the values */
1403 if (3 != sscanf(buf+2, "%d:%d:%d",
1404 &tval, &sval, &pval)) return (1);
1406 /* Save the values */
1412 /* Process 'W' for "More Info" (one line only) */
1413 else if (buf[0] == 'W')
1415 int level, extra, wgt;
1418 /* Scan for the values */
1419 if (4 != sscanf(buf+2, "%d:%d:%d:%ld",
1420 &level, &extra, &wgt, &cost)) return (1);
1422 /* Save the values */
1423 k_ptr->level = level;
1424 k_ptr->extra = extra;
1425 k_ptr->weight = wgt;
1429 /* Process 'A' for "Allocation" (one line only) */
1430 else if (buf[0] == 'A')
1434 /* XXX XXX XXX Simply read each number following a colon */
1435 for (i = 0, s = buf+1; s && (s[0] == ':') && s[1]; ++i)
1437 /* Default chance */
1438 k_ptr->chance[i] = 1;
1440 /* Store the attack damage index */
1441 k_ptr->locale[i] = atoi(s+1);
1443 /* Find the slash */
1444 t = strchr(s+1, '/');
1446 /* Find the next colon */
1447 s = strchr(s+1, ':');
1449 /* If the slash is "nearby", use it */
1450 if (t && (!s || t < s))
1452 int chance = atoi(t+1);
1453 if (chance > 0) k_ptr->chance[i] = chance;
1458 /* Hack -- Process 'P' for "power" and such */
1459 else if (buf[0] == 'P')
1461 int ac, hd1, hd2, th, td, ta;
1463 /* Scan for the values */
1464 if (6 != sscanf(buf+2, "%d:%dd%d:%d:%d:%d",
1465 &ac, &hd1, &hd2, &th, &td, &ta)) return (1);
1475 /* Hack -- Process 'F' for flags */
1476 else if (buf[0] == 'F')
1478 /* Parse every entry textually */
1479 for (s = buf + 2; *s; )
1481 /* Find the end of this entry */
1482 for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
1484 /* Nuke and skip any dividers */
1488 while (*t == ' ' || *t == '|') t++;
1491 /* Parse this entry */
1492 if (0 != grab_one_kind_flag(k_ptr, s)) return (5);
1494 /* Start the next entry */
1510 * Grab one flag in an artifact_type from a textual string
1512 static errr grab_one_artifact_flag(artifact_type *a_ptr, cptr what)
1517 for (i = 0; i < 32; i++)
1519 if (streq(what, k_info_flags1[i]))
1521 a_ptr->flags1 |= (1L << i);
1527 for (i = 0; i < 32; i++)
1529 if (streq(what, k_info_flags2[i]))
1531 a_ptr->flags2 |= (1L << i);
1537 for (i = 0; i < 32; i++)
1539 if (streq(what, k_info_flags3[i]))
1541 a_ptr->flags3 |= (1L << i);
1548 msg_format("̤ÃΤÎÅÁÀâ¤Î¥¢¥¤¥Æ¥à¡¦¥Õ¥é¥° '%s'¡£", what);
1550 msg_format("Unknown artifact flag '%s'.", what);
1562 * Initialize the "a_info" array, by parsing an ascii "template" file
1564 errr parse_a_info(char *buf, header *head)
1571 static artifact_type *a_ptr = NULL;
1574 /* Process 'N' for "New/Number/Name" */
1577 /* Find the colon before the name */
1578 s = strchr(buf+2, ':');
1580 /* Verify that colon */
1583 /* Nuke the colon, advance to the name */
1586 /* Paranoia -- require a name */
1587 if (!*s) return (1);
1592 /* Verify information */
1593 if (i < error_idx) return (4);
1595 /* Verify information */
1596 if (i >= head->info_num) return (2);
1598 /* Save the index */
1601 /* Point at the "info" */
1604 /* Ignore everything */
1605 a_ptr->flags3 |= (TR3_IGNORE_ACID);
1606 a_ptr->flags3 |= (TR3_IGNORE_ELEC);
1607 a_ptr->flags3 |= (TR3_IGNORE_FIRE);
1608 a_ptr->flags3 |= (TR3_IGNORE_COLD);
1610 /* Hack -- Verify space */
1611 if (head->name_size + strlen(s) + 8 > fake_name_size) return (7);
1613 /* Advance and Save the name index */
1614 if (!a_ptr->name) a_ptr->name = ++head->name_size;
1616 /* Append chars to the name */
1617 strcpy(head->name_ptr + head->name_size, s);
1619 /* Advance the index */
1620 head->name_size += strlen(s);
1624 /* There better be a current a_ptr */
1625 else if (!a_ptr) return (3);
1629 /* ±Ñ¸ì̾¤òÆɤà¥ë¡¼¥Á¥ó¤òÄɲà */
1630 /* 'E' ¤«¤é»Ï¤Þ¤ë¹Ô¤Ï±Ñ¸ì̾¤È¤·¤Æ¤¤¤ë */
1631 else if (buf[0] == 'E')
1636 else if (buf[0] == 'E')
1638 /* Acquire the Text */
1641 /* Hack -- Verify space */
1642 if (head->name_size + strlen(s) + 8 > fake_name_size) return (7);
1644 /* Advance and Save the name index */
1645 if (!a_ptr->name) a_ptr->name = ++head->name_size;
1647 /* Append chars to the name */
1648 strcpy(head->name_ptr + head->name_size, s);
1650 /* Advance the index */
1651 head->name_size += strlen(s);
1655 /* Process 'D' for "Description" */
1656 else if (buf[0] == 'D')
1661 /* Acquire the text */
1666 /* Acquire the text */
1670 /* Hack -- Verify space */
1671 if (head->text_size + strlen(s) + 8 > fake_text_size) return (7);
1673 /* Advance and Save the text index */
1674 if (!a_ptr->text) a_ptr->text = ++head->text_size;
1676 /* Append chars to the name */
1677 strcpy(head->text_ptr + head->text_size, s);
1679 /* Advance the index */
1680 head->text_size += strlen(s);
1684 /* Process 'I' for "Info" (one line only) */
1685 else if (buf[0] == 'I')
1687 int tval, sval, pval;
1689 /* Scan for the values */
1690 if (3 != sscanf(buf+2, "%d:%d:%d",
1691 &tval, &sval, &pval)) return (1);
1693 /* Save the values */
1699 /* Process 'W' for "More Info" (one line only) */
1700 else if (buf[0] == 'W')
1702 int level, rarity, wgt;
1705 /* Scan for the values */
1706 if (4 != sscanf(buf+2, "%d:%d:%d:%ld",
1707 &level, &rarity, &wgt, &cost)) return (1);
1709 /* Save the values */
1710 a_ptr->level = level;
1711 a_ptr->rarity = rarity;
1712 a_ptr->weight = wgt;
1716 /* Hack -- Process 'P' for "power" and such */
1717 else if (buf[0] == 'P')
1719 int ac, hd1, hd2, th, td, ta;
1721 /* Scan for the values */
1722 if (6 != sscanf(buf+2, "%d:%dd%d:%d:%d:%d",
1723 &ac, &hd1, &hd2, &th, &td, &ta)) return (1);
1733 /* Hack -- Process 'F' for flags */
1734 else if (buf[0] == 'F')
1736 /* Parse every entry textually */
1737 for (s = buf + 2; *s; )
1739 /* Find the end of this entry */
1740 for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
1742 /* Nuke and skip any dividers */
1746 while ((*t == ' ') || (*t == '|')) t++;
1749 /* Parse this entry */
1750 if (0 != grab_one_artifact_flag(a_ptr, s)) return (5);
1752 /* Start the next entry */
1768 * Grab one flag in a ego-item_type from a textual string
1770 static bool grab_one_ego_item_flag(ego_item_type *e_ptr, cptr what)
1775 for (i = 0; i < 32; i++)
1777 if (streq(what, k_info_flags1[i]))
1779 e_ptr->flags1 |= (1L << i);
1785 for (i = 0; i < 32; i++)
1787 if (streq(what, k_info_flags2[i]))
1789 e_ptr->flags2 |= (1L << i);
1795 for (i = 0; i < 32; i++)
1797 if (streq(what, k_info_flags3[i]))
1799 e_ptr->flags3 |= (1L << i);
1806 msg_format("̤ÃΤÎ̾¤Î¤¢¤ë¥¢¥¤¥Æ¥à¡¦¥Õ¥é¥° '%s'¡£", what);
1808 msg_format("Unknown ego-item flag '%s'.", what);
1820 * Initialize the "e_info" array, by parsing an ascii "template" file
1822 errr parse_e_info(char *buf, header *head)
1829 static ego_item_type *e_ptr = NULL;
1832 /* Just before the first record */
1835 /* Just before the first line */
1839 /* Process 'N' for "New/Number/Name" */
1842 /* Find the colon before the name */
1843 s = strchr(buf+2, ':');
1845 /* Verify that colon */
1848 /* Nuke the colon, advance to the name */
1851 /* Paranoia -- require a name */
1852 if (!*s) return (1);
1857 /* Verify information */
1858 if (i < error_idx) return (4);
1860 /* Verify information */
1861 if (i >= head->info_num) return (2);
1863 /* Save the index */
1866 /* Point at the "info" */
1869 /* Hack -- Verify space */
1870 if (head->name_size + strlen(s) + 8 > fake_name_size) return (7);
1872 /* Advance and Save the name index */
1873 if (!e_ptr->name) e_ptr->name = ++head->name_size;
1875 /* Append chars to the name */
1876 strcpy(head->name_ptr + head->name_size, s);
1878 /* Advance the index */
1879 head->name_size += strlen(s);
1883 /* There better be a current e_ptr */
1884 else if (!e_ptr) return (3);
1888 /* ±Ñ¸ì̾¤òÆɤà¥ë¡¼¥Á¥ó¤òÄɲà */
1889 /* 'E' ¤«¤é»Ï¤Þ¤ë¹Ô¤Ï±Ñ¸ì̾ */
1890 else if (buf[0] == 'E')
1895 else if (buf[0] == 'E')
1897 /* Acquire the Text */
1900 /* Hack -- Verify space */
1901 if (head->name_size + strlen(s) + 8 > fake_name_size) return (7);
1903 /* Advance and Save the name index */
1904 if (!e_ptr->name) e_ptr->name = ++head->name_size;
1906 /* Append chars to the name */
1907 strcpy(head->name_ptr + head->name_size, s);
1909 /* Advance the index */
1910 head->name_size += strlen(s);
1915 /* Process 'D' for "Description" */
1916 else if (buf[0] == 'D')
1918 /* Acquire the text */
1921 /* Hack -- Verify space */
1922 if (e_head->text_size + strlen(s) + 8 > fake_text_size) return (7);
1924 /* Advance and Save the text index */
1925 if (!e_ptr->text) e_ptr->text = ++e_head->text_size;
1927 /* Append chars to the name */
1928 strcpy(e_text + e_head->text_size, s);
1930 /* Advance the index */
1931 e_head->text_size += strlen(s);
1936 /* Process 'X' for "Xtra" (one line only) */
1937 else if (buf[0] == 'X')
1941 /* Scan for the values */
1942 if (2 != sscanf(buf+2, "%d:%d",
1943 &slot, &rating)) return (1);
1945 /* Save the values */
1947 e_ptr->rating = rating;
1950 /* Process 'W' for "More Info" (one line only) */
1951 else if (buf[0] == 'W')
1953 int level, rarity, pad2;
1956 /* Scan for the values */
1957 if (4 != sscanf(buf+2, "%d:%d:%d:%ld",
1958 &level, &rarity, &pad2, &cost)) return (1);
1960 /* Save the values */
1961 e_ptr->level = level;
1962 e_ptr->rarity = rarity;
1963 /* e_ptr->weight = wgt; */
1967 /* Hack -- Process 'C' for "creation" */
1968 else if (buf[0] == 'C')
1972 /* Scan for the values */
1973 if (4 != sscanf(buf+2, "%d:%d:%d:%d",
1974 &th, &td, &ta, &pv)) return (1);
1976 e_ptr->max_to_h = th;
1977 e_ptr->max_to_d = td;
1978 e_ptr->max_to_a = ta;
1979 e_ptr->max_pval = pv;
1982 /* Hack -- Process 'F' for flags */
1983 else if (buf[0] == 'F')
1985 /* Parse every entry textually */
1986 for (s = buf + 2; *s; )
1988 /* Find the end of this entry */
1989 for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
1991 /* Nuke and skip any dividers */
1995 while ((*t == ' ') || (*t == '|')) t++;
1998 /* Parse this entry */
1999 if (0 != grab_one_ego_item_flag(e_ptr, s)) return (5);
2001 /* Start the next entry */
2015 * Grab one (basic) flag in a monster_race from a textual string
2017 static errr grab_one_basic_flag(monster_race *r_ptr, cptr what)
2022 for (i = 0; i < 32; i++)
2024 if (streq(what, r_info_flags1[i]))
2026 r_ptr->flags1 |= (1L << i);
2032 for (i = 0; i < 32; i++)
2034 if (streq(what, r_info_flags2[i]))
2036 r_ptr->flags2 |= (1L << i);
2042 for (i = 0; i < 32; i++)
2044 if (streq(what, r_info_flags3[i]))
2046 r_ptr->flags3 |= (1L << i);
2052 for (i = 0; i < 32; i++)
2054 if (streq(what, r_info_flags7[i]))
2056 r_ptr->flags7 |= (1L << i);
2062 for (i = 0; i < 32; i++)
2064 if (streq(what, r_info_flags8[i]))
2066 r_ptr->flags8 |= (1L << i);
2072 for (i = 0; i < 32; i++)
2074 if (streq(what, r_info_flags9[i]))
2076 r_ptr->flags9 |= (1L << i);
2083 msg_format("̤ÃΤΥâ¥ó¥¹¥¿¡¼¡¦¥Õ¥é¥° '%s'¡£", what);
2085 msg_format("Unknown monster flag '%s'.", what);
2095 * Grab one (spell) flag in a monster_race from a textual string
2097 static errr grab_one_spell_flag(monster_race *r_ptr, cptr what)
2102 for (i = 0; i < 32; i++)
2104 if (streq(what, r_info_flags4[i]))
2106 r_ptr->flags4 |= (1L << i);
2112 for (i = 0; i < 32; i++)
2114 if (streq(what, r_info_flags5[i]))
2116 r_ptr->flags5 |= (1L << i);
2122 for (i = 0; i < 32; i++)
2124 if (streq(what, r_info_flags6[i]))
2126 r_ptr->flags6 |= (1L << i);
2133 msg_format("̤ÃΤΥâ¥ó¥¹¥¿¡¼¡¦¥Õ¥é¥° '%s'¡£", what);
2135 msg_format("Unknown monster flag '%s'.", what);
2147 * Initialize the "r_info" array, by parsing an ascii "template" file
2149 errr parse_r_info(char *buf, header *head)
2156 static monster_race *r_ptr = NULL;
2159 /* Process 'N' for "New/Number/Name" */
2162 /* Find the colon before the name */
2163 s = strchr(buf+2, ':');
2165 /* Verify that colon */
2168 /* Nuke the colon, advance to the name */
2171 /* Paranoia -- require a name */
2172 if (!*s) return (1);
2177 /* Verify information */
2178 if (i < error_idx) return (4);
2180 /* Verify information */
2181 if (i >= head->info_num) return (2);
2183 /* Save the index */
2186 /* Point at the "info" */
2189 /* Hack -- Verify space */
2190 if (head->name_size + strlen(s) + 8 > fake_name_size) return (7);
2192 /* Advance and Save the name index */
2193 if (!r_ptr->name) r_ptr->name = ++head->name_size;
2195 /* Append chars to the name */
2196 strcpy(head->name_ptr + head->name_size, s);
2198 /* Advance the index */
2199 head->name_size += strlen(s);
2203 /* There better be a current r_ptr */
2204 else if (!r_ptr) return (3);
2208 /* ±Ñ¸ì̾¤òÆɤà¥ë¡¼¥Á¥ó¤òÄɲà */
2209 /* 'E' ¤«¤é»Ï¤Þ¤ë¹Ô¤Ï±Ñ¸ì̾ */
2210 else if (buf[0] == 'E')
2212 /* Acquire the Text */
2215 /* Hack -- Verify space */
2216 if (head->name_size + strlen(s) + 8 > fake_name_size) return (7);
2218 /* Advance and Save the name index */
2219 if (!r_ptr->E_name) r_ptr->E_name = ++head->name_size;
2221 /* Append chars to the name */
2222 strcpy(head->name_ptr + head->name_size, s);
2224 /* Advance the index */
2225 head->name_size += strlen(s);
2228 else if (buf[0] == 'E')
2230 /* Acquire the Text */
2233 /* Hack -- Verify space */
2234 if (head->name_size + strlen(s) + 8 > fake_name_size) return (7);
2236 /* Advance and Save the name index */
2237 if (!r_ptr->name) r_ptr->name = ++head->name_size;
2239 /* Append chars to the name */
2240 strcpy(head->name_ptr + head->name_size, s);
2242 /* Advance the index */
2243 head->name_size += strlen(s);
2246 /* Process 'D' for "Description" */
2247 else if (buf[0] == 'D')
2252 /* Acquire the text */
2257 /* Acquire the text */
2261 /* Hack -- Verify space */
2262 if (head->text_size + strlen(s) + 8 > fake_text_size) return (7);
2264 /* Advance and Save the text index */
2265 if (!r_ptr->text) r_ptr->text = ++head->text_size;
2267 /* Append chars to the name */
2268 strcpy(head->text_ptr + head->text_size, s);
2270 /* Advance the index */
2271 head->text_size += strlen(s);
2274 /* Process 'G' for "Graphics" (one line only) */
2275 else if (buf[0] == 'G')
2281 if (!buf[2]) return (1);
2282 if (!buf[3]) return (1);
2283 if (!buf[4]) return (1);
2285 /* Extract the char */
2288 /* Extract the attr */
2289 tmp = color_char_to_attr(buf[4]);
2292 if (tmp < 0) return (1);
2294 /* Save the values */
2295 r_ptr->d_char = sym;
2296 r_ptr->d_attr = tmp;
2299 /* Process 'I' for "Info" (one line only) */
2300 else if (buf[0] == 'I')
2302 int spd, hp1, hp2, aaf, ac, slp;
2304 /* Scan for the other values */
2305 if (6 != sscanf(buf+2, "%d:%dd%d:%d:%d:%d",
2306 &spd, &hp1, &hp2, &aaf, &ac, &slp)) return (1);
2308 /* Save the values */
2317 /* Process 'W' for "More Info" (one line only) */
2318 else if (buf[0] == 'W')
2325 /* Scan for the values */
2326 if (6 != sscanf(buf+2, "%d:%d:%d:%ld:%ld:%d",
2327 &lev, &rar, &pad, &exp, &nextexp, &nextmon)) return (1);
2329 /* Save the values */
2331 r_ptr->rarity = rar;
2334 r_ptr->next_exp = nextexp;
2335 r_ptr->next_r_idx = nextmon;
2338 /* Process 'B' for "Blows" (up to four lines) */
2339 else if (buf[0] == 'B')
2343 /* Find the next empty blow slot (if any) */
2344 for (i = 0; i < 4; i++) if (!r_ptr->blow[i].method) break;
2346 /* Oops, no more slots */
2347 if (i == 4) return (1);
2349 /* Analyze the first field */
2350 for (s = t = buf+2; *t && (*t != ':'); t++) /* loop */;
2352 /* Terminate the field (if necessary) */
2353 if (*t == ':') *t++ = '\0';
2355 /* Analyze the method */
2356 for (n1 = 0; r_info_blow_method[n1]; n1++)
2358 if (streq(s, r_info_blow_method[n1])) break;
2361 /* Invalid method */
2362 if (!r_info_blow_method[n1]) return (1);
2364 /* Analyze the second field */
2365 for (s = t; *t && (*t != ':'); t++) /* loop */;
2367 /* Terminate the field (if necessary) */
2368 if (*t == ':') *t++ = '\0';
2370 /* Analyze effect */
2371 for (n2 = 0; r_info_blow_effect[n2]; n2++)
2373 if (streq(s, r_info_blow_effect[n2])) break;
2376 /* Invalid effect */
2377 if (!r_info_blow_effect[n2]) return (1);
2379 /* Analyze the third field */
2380 for (s = t; *t && (*t != 'd'); t++) /* loop */;
2382 /* Terminate the field (if necessary) */
2383 if (*t == 'd') *t++ = '\0';
2385 /* Save the method */
2386 r_ptr->blow[i].method = n1;
2388 /* Save the effect */
2389 r_ptr->blow[i].effect = n2;
2391 /* Extract the damage dice and sides */
2392 r_ptr->blow[i].d_dice = atoi(s);
2393 r_ptr->blow[i].d_side = atoi(t);
2396 /* Process 'F' for "Basic Flags" (multiple lines) */
2397 else if (buf[0] == 'F')
2399 /* Parse every entry */
2400 for (s = buf + 2; *s; )
2402 /* Find the end of this entry */
2403 for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
2405 /* Nuke and skip any dividers */
2409 while (*t == ' ' || *t == '|') t++;
2412 /* Parse this entry */
2413 if (0 != grab_one_basic_flag(r_ptr, s)) return (5);
2415 /* Start the next entry */
2420 /* Process 'S' for "Spell Flags" (multiple lines) */
2421 else if (buf[0] == 'S')
2423 /* Parse every entry */
2424 for (s = buf + 2; *s; )
2426 /* Find the end of this entry */
2427 for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
2429 /* Nuke and skip any dividers */
2433 while ((*t == ' ') || (*t == '|')) t++;
2436 /* XXX XXX XXX Hack -- Read spell frequency */
2437 if (1 == sscanf(s, "1_IN_%d", &i))
2439 /* Extract a "frequency" */
2440 r_ptr->freq_spell = r_ptr->freq_inate = 100 / i;
2442 /* Start at next entry */
2449 /* Parse this entry */
2450 if (0 != grab_one_spell_flag(r_ptr, s)) return (5);
2452 /* Start the next entry */
2467 * Grab one flag for a dungeon type from a textual string
2469 static errr grab_one_dungeon_flag(dungeon_info_type *d_ptr, cptr what)
2474 for (i = 0; i < 32; i++)
2476 if (streq(what, d_info_flags1[i]))
2478 d_ptr->flags1 |= (1L << i);
2485 msg_format("̤ÃΤΥÀ¥ó¥¸¥ç¥ó¡¦¥Õ¥é¥° '%s'¡£", what);
2487 msg_format("Unknown dungeon type flag '%s'.", what);
2495 * Grab one (basic) flag in a monster_race from a textual string
2497 static errr grab_one_basic_monster_flag(dungeon_info_type *d_ptr, cptr what)
2502 for (i = 0; i < 32; i++)
2504 if (streq(what, r_info_flags1[i]))
2506 d_ptr->mflags1 |= (1L << i);
2512 for (i = 0; i < 32; i++)
2514 if (streq(what, r_info_flags2[i]))
2516 d_ptr->mflags2 |= (1L << i);
2522 for (i = 0; i < 32; i++)
2524 if (streq(what, r_info_flags3[i]))
2526 d_ptr->mflags3 |= (1L << i);
2532 for (i = 0; i < 32; i++)
2534 if (streq(what, r_info_flags7[i]))
2536 d_ptr->mflags7 |= (1L << i);
2542 for (i = 0; i < 32; i++)
2544 if (streq(what, r_info_flags8[i]))
2546 d_ptr->mflags8 |= (1L << i);
2552 for (i = 0; i < 32; i++)
2554 if (streq(what, r_info_flags9[i]))
2556 d_ptr->mflags9 |= (1L << i);
2563 msg_format("̤ÃΤΥâ¥ó¥¹¥¿¡¼¡¦¥Õ¥é¥° '%s'¡£", what);
2565 msg_format("Unknown monster flag '%s'.", what);
2573 * Grab one (spell) flag in a monster_race from a textual string
2575 static errr grab_one_spell_monster_flag(dungeon_info_type *d_ptr, cptr what)
2580 for (i = 0; i < 32; i++)
2582 if (streq(what, r_info_flags4[i]))
2584 d_ptr->mflags4 |= (1L << i);
2590 for (i = 0; i < 32; i++)
2592 if (streq(what, r_info_flags5[i]))
2594 d_ptr->mflags5 |= (1L << i);
2600 for (i = 0; i < 32; i++)
2602 if (streq(what, r_info_flags6[i]))
2604 d_ptr->mflags6 |= (1L << i);
2611 msg_format("̤ÃΤΥâ¥ó¥¹¥¿¡¼¡¦¥Õ¥é¥° '%s'¡£", what);
2613 msg_format("Unknown monster flag '%s'.", what);
2621 * Initialize the "d_info" array, by parsing an ascii "template" file
2623 errr parse_d_info(char *buf, header *head)
2630 static dungeon_info_type *d_ptr = NULL;
2633 /* Process 'N' for "New/Number/Name" */
2636 /* Find the colon before the name */
2637 s = strchr(buf+2, ':');
2639 /* Verify that colon */
2642 /* Nuke the colon, advance to the name */
2645 /* Paranoia -- require a name */
2646 if (!*s) return (1);
2651 /* Verify information */
2652 if (i < error_idx) return (4);
2654 /* Verify information */
2655 if (i >= head->info_num) return (2);
2657 /* Save the index */
2660 /* Point at the "info" */
2663 /* Hack -- Verify space */
2664 if (head->name_size + strlen(s) + 8 > fake_name_size) return (7);
2666 /* Advance and Save the name index */
2667 if (!d_ptr->name) d_ptr->name = ++head->name_size;
2669 /* Append chars to the name */
2670 strcpy(head->name_ptr + head->name_size, s);
2672 /* Advance the index */
2673 head->name_size += strlen(s);
2678 else if (buf[0] == 'E') return (0);
2680 else if (buf[0] == 'E')
2682 /* Acquire the Text */
2685 /* Hack -- Verify space */
2686 if (head->name_size + strlen(s) + 8 > fake_name_size) return (7);
2688 /* Advance and Save the name index */
2689 if (!d_ptr->name) d_ptr->name = ++head->name_size;
2691 /* Append chars to the name */
2692 strcpy(head->name_ptr + head->name_size, s);
2694 /* Advance the index */
2695 head->name_size += strlen(s);
2699 /* Process 'D' for "Description */
2700 else if (buf[0] == 'D')
2705 /* Acquire the text */
2710 /* Acquire the text */
2714 /* Hack -- Verify space */
2715 if (head->text_size + strlen(s) + 8 > fake_text_size) return (7);
2717 /* Advance and Save the text index */
2718 if (!d_ptr->text) d_ptr->text = ++head->text_size;
2720 /* Append chars to the name */
2721 strcpy(d_text + head->text_size, s);
2723 /* Advance the index */
2724 head->text_size += strlen(s);
2727 /* Process 'W' for "More Info" (one line only) */
2728 else if (buf[0] == 'W')
2730 int min_lev, max_lev;
2732 int min_alloc, max_chance;
2733 int obj_good, obj_great;
2736 /* Scan for the values */
2737 if (10 != sscanf(buf+2, "%d:%d:%d:%d:%d:%d:%d:%d:%x:%x",
2738 &min_lev, &max_lev, &min_plev, &mode, &min_alloc, &max_chance, &obj_good, &obj_great, (unsigned int *)&pit, (unsigned int *)&nest)) return (1);
2740 /* Save the values */
2741 d_ptr->mindepth = min_lev;
2742 d_ptr->maxdepth = max_lev;
2743 d_ptr->min_plev = min_plev;
2745 d_ptr->min_m_alloc_level = min_alloc;
2746 d_ptr->max_m_alloc_chance = max_chance;
2747 d_ptr->obj_good = obj_good;
2748 d_ptr->obj_great = obj_great;
2753 /* Process 'P' for "Place Info" */
2754 else if (buf[0] == 'P')
2758 /* Scan for the values */
2759 if (2 != sscanf(buf+2, "%d:%d", &dy, &dx)) return (1);
2761 /* Save the values */
2766 /* Process 'L' for "fLoor type" (one line only) */
2767 else if (buf[0] == 'L')
2773 /* Scan for the values */
2774 if (7 != sscanf(buf+2, "%d:%d:%d:%d:%d:%d:%d",
2775 &f1, &p1, &f2, &p2, &f3, &p3, &tunnel)) return (1);
2777 /* Save the values */
2779 d_ptr->floor_percent1 = p1;
2781 d_ptr->floor_percent2 = p2;
2783 d_ptr->floor_percent3 = p3;
2784 d_ptr->tunnel_percent = tunnel;
2787 /* Process 'A' for "wAll type" (one line only) */
2788 else if (buf[0] == 'A')
2790 int w1, w2, w3, outer, inner, stream1, stream2;
2793 /* Scan for the values */
2794 if (10 != sscanf(buf+2, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
2795 &w1, &p1, &w2, &p2, &w3, &p3, &outer, &inner, &stream1, &stream2)) return (1);
2797 /* Save the values */
2798 d_ptr->fill_type1 = w1;
2799 d_ptr->fill_percent1 = p1;
2800 d_ptr->fill_type2 = w2;
2801 d_ptr->fill_percent2 = p2;
2802 d_ptr->fill_type3 = w3;
2803 d_ptr->fill_percent3 = p3;
2804 d_ptr->outer_wall = outer;
2805 d_ptr->inner_wall = inner;
2806 d_ptr->stream1 = stream1;
2807 d_ptr->stream2 = stream2;
2810 /* Process 'F' for "Dungeon Flags" (multiple lines) */
2811 else if (buf[0] == 'F')
2813 int artif = 0, monst = 0;
2815 /* Parse every entry */
2816 for (s = buf + 2; *s; )
2818 /* Find the end of this entry */
2819 for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
2821 /* Nuke and skip any dividers */
2825 while (*t == ' ' || *t == '|') t++;
2828 /* XXX XXX XXX Hack -- Read Final Artifact */
2829 if (1 == sscanf(s, "FINAL_ARTIFACT_%d", &artif))
2831 /* Extract a "Final Artifact" */
2832 d_ptr->final_artifact = artif;
2834 /* Start at next entry */
2841 /* XXX XXX XXX Hack -- Read Final Object */
2842 if (1 == sscanf(s, "FINAL_OBJECT_%d", &artif))
2844 /* Extract a "Final Artifact" */
2845 d_ptr->final_object = artif;
2847 /* Start at next entry */
2854 /* XXX XXX XXX Hack -- Read Artifact Guardian */
2855 if (1 == sscanf(s, "FINAL_GUARDIAN_%d", &monst))
2857 /* Extract a "Artifact Guardian" */
2858 d_ptr->final_guardian = monst;
2860 /* Start at next entry */
2867 /* XXX XXX XXX Hack -- Read Special Percentage */
2868 if (1 == sscanf(s, "MONSTER_DIV_%d", &monst))
2870 /* Extract a "Special %" */
2871 d_ptr->special_div = monst;
2873 /* Start at next entry */
2880 /* Parse this entry */
2881 if (0 != grab_one_dungeon_flag(d_ptr, s)) return (5);
2883 /* Start the next entry */
2888 /* Process 'M' for "Basic Flags" (multiple lines) */
2889 else if (buf[0] == 'M')
2891 byte r_char_number = 0, r_char;
2893 /* Parse every entry */
2894 for (s = buf + 2; *s; )
2896 /* Find the end of this entry */
2897 for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
2899 /* Nuke and skip any dividers */
2903 while (*t == ' ' || *t == '|') t++;
2906 /* XXX XXX XXX Hack -- Read monster symbols */
2907 if (1 == sscanf(s, "R_CHAR_%c", &r_char))
2909 /* Limited to 5 races */
2910 if(r_char_number >= 5) continue;
2912 /* Extract a "frequency" */
2913 d_ptr->r_char[r_char_number++] = r_char;
2915 /* Start at next entry */
2922 /* Parse this entry */
2923 if (0 != grab_one_basic_monster_flag(d_ptr, s)) return (5);
2925 /* Start the next entry */
2930 /* Process 'S' for "Spell Flags" (multiple lines) */
2931 else if (buf[0] == 'S')
2933 /* Parse every entry */
2934 for (s = buf + 2; *s; )
2936 /* Find the end of this entry */
2937 for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
2939 /* Nuke and skip any dividers */
2943 while ((*t == ' ') || (*t == '|')) t++;
2946 /* XXX XXX XXX Hack -- Read spell frequency */
2947 if (1 == sscanf(s, "1_IN_%d", &i))
2949 /* Start at next entry */
2956 /* Parse this entry */
2957 if (0 != grab_one_spell_monster_flag(d_ptr, s)) return (5);
2959 /* Start the next entry */
2972 #else /* ALLOW_TEMPLATES */
2978 #endif /* ALLOW_TEMPLATES */
2981 /* Random dungeon grid effects */
2982 #define RANDOM_NONE 0x00
2983 #define RANDOM_FEATURE 0x01
2984 #define RANDOM_MONSTER 0x02
2985 #define RANDOM_OBJECT 0x04
2986 #define RANDOM_EGO 0x08
2987 #define RANDOM_ARTIFACT 0x10
2988 #define RANDOM_TRAP 0x20
2991 typedef struct dungeon_grid dungeon_grid;
2995 int feature; /* Terrain feature */
2996 int monster; /* Monster */
2997 int object; /* Object */
2998 int ego; /* Ego-Item */
2999 int artifact; /* Artifact */
3000 int trap; /* Trap */
3001 int cave_info; /* Flags for CAVE_MARK, CAVE_GLOW, CAVE_ICKY, CAVE_ROOM */
3002 int special; /* Reserved for special terrain info */
3003 int random; /* Number of the random effect */
3007 static dungeon_grid letter[255];
3011 * Process "F:<letter>:<terrain>:<cave_info>:<monster>:<object>:<ego>:<artifact>:<trap>:<special>" -- info for dungeon grid
3013 static errr parse_line_feature(char *buf)
3019 if (init_flags & INIT_ONLY_BUILDINGS) return (0);
3021 /* Tokenize the line */
3022 if ((num = tokenize(buf+2, 9, zz, 0)) > 1)
3024 /* Letter to assign */
3025 int index = zz[0][0];
3027 /* Reset the info for the letter */
3028 letter[index].feature = 0;
3029 letter[index].monster = 0;
3030 letter[index].object = 0;
3031 letter[index].ego = 0;
3032 letter[index].artifact = 0;
3033 letter[index].trap = 0;
3034 letter[index].cave_info = 0;
3035 letter[index].special = 0;
3036 letter[index].random = 0;
3042 letter[index].special = atoi(zz[8]);
3046 if (zz[7][0] == '*')
3048 letter[index].random |= RANDOM_TRAP;
3053 letter[index].trap = atoi(zz[7]);
3058 letter[index].trap = atoi(zz[7]);
3063 if (zz[6][0] == '*')
3065 letter[index].random |= RANDOM_ARTIFACT;
3070 letter[index].artifact = atoi(zz[6]);
3075 letter[index].artifact = atoi(zz[6]);
3080 if (zz[5][0] == '*')
3082 letter[index].random |= RANDOM_EGO;
3087 letter[index].ego = atoi(zz[5]);
3092 letter[index].ego = atoi(zz[5]);
3097 if (zz[4][0] == '*')
3099 letter[index].random |= RANDOM_OBJECT;
3104 letter[index].object = atoi(zz[4]);
3109 letter[index].object = atoi(zz[4]);
3114 if (zz[3][0] == '*')
3116 letter[index].random |= RANDOM_MONSTER;
3120 letter[index].monster = atoi(zz[3]);
3125 letter[index].monster = atoi(zz[3]);
3130 letter[index].cave_info = atoi(zz[2]);
3134 if (zz[1][0] == '*')
3136 letter[index].random |= RANDOM_FEATURE;
3140 letter[index].feature = atoi(zz[1]);
3145 letter[index].feature = atoi(zz[1]);
3158 * Process "F:<letter>:<terrain>:<cave_info>:<monster>:<object>:<ego>:<artifact>:<trap>:<special>" -- info for dungeon grid
3160 static errr parse_line_building(char *buf)
3176 /* Get the building number */
3179 /* Find the colon after the building number */
3182 /* Verify that colon */
3185 /* Nuke the colon, advance to the sub-index */
3188 /* Paranoia -- require a sub-index */
3189 if (!*s) return (1);
3191 /* Building definition sub-index */
3194 /* Building name, owner, race */
3197 if (tokenize(s + 2, 3, zz, 0) == 3)
3199 /* Name of the building */
3200 strcpy(building[index].name, zz[0]);
3202 /* Name of the owner */
3203 strcpy(building[index].owner_name, zz[1]);
3205 /* Race of the owner */
3206 strcpy(building[index].owner_race, zz[2]);
3211 return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3214 /* Building Action */
3217 if (tokenize(s + 2, 8, zz, 0) >= 7)
3219 /* Index of the action */
3220 int action_index = atoi(zz[0]);
3222 /* Name of the action */
3223 strcpy(building[index].act_names[action_index], zz[1]);
3225 /* Cost of the action for members */
3226 building[index].member_costs[action_index] = atoi(zz[2]);
3228 /* Cost of the action for non-members */
3229 building[index].other_costs[action_index] = atoi(zz[3]);
3231 /* Letter assigned to the action */
3232 building[index].letters[action_index] = zz[4][0];
3235 building[index].actions[action_index] = atoi(zz[5]);
3237 /* Action restriction */
3238 building[index].action_restr[action_index] = atoi(zz[6]);
3243 return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3246 /* Building Classes */
3249 if (tokenize(s + 2, MAX_CLASS, zz, 0) == MAX_CLASS)
3251 for (i = 0; i < MAX_CLASS; i++)
3253 building[index].member_class[i] = atoi(zz[i]);
3259 return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3262 /* Building Races */
3265 if (tokenize(s+2, MAX_RACES, zz, 0) == MAX_RACES)
3267 for (i = 0; i < MAX_RACES; i++)
3269 building[index].member_race[i] = atoi(zz[i]);
3275 return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3278 /* Building Realms */
3281 if (tokenize(s+2, MAX_MAGIC, zz, 0) == MAX_MAGIC)
3283 for (i = 0; i < MAX_MAGIC; i++)
3285 building[index].member_realm[i+1] = atoi(zz[i]);
3291 return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3297 if (tokenize(s+2, 2, zz, 0) == 2)
3299 /* Index of the action */
3300 int action_index = atoi(zz[0]);
3302 /* Name of the action */
3303 strcpy(building[index].act_script[action_index], zz[1]);
3308 #else /* USE_SCRIPT */
3309 /* Ignore scripts */
3311 #endif /* USE_SCRIPT */
3316 return (PARSE_ERROR_UNDEFINED_DIRECTIVE);
3325 * Parse a sub-file of the "extra info"
3327 static errr process_dungeon_file_aux(char *buf, int ymin, int xmin, int ymax, int xmax, int *y, int *x)
3334 /* Skip "empty" lines */
3335 if (!buf[0]) return (0);
3337 /* Skip "blank" lines */
3338 if (isspace(buf[0])) return (0);
3341 if (buf[0] == '#') return (0);
3343 /* Require "?:*" format */
3344 if (buf[1] != ':') return (1);
3347 /* Process "%:<fname>" */
3350 /* Attempt to Process the given file */
3351 return (process_dungeon_file(buf + 2, ymin, xmin, ymax, xmax));
3354 /* Process "F:<letter>:<terrain>:<cave_info>:<monster>:<object>:<ego>:<artifact>:<trap>:<special>" -- info for dungeon grid */
3357 return parse_line_feature(buf);
3360 /* Process "D:<dungeon>" -- info for the cave grids */
3361 else if (buf[0] == 'D')
3363 object_type object_type_body;
3365 /* Acquire the text */
3368 /* Length of the text */
3369 int len = strlen(s);
3371 if (init_flags & INIT_ONLY_BUILDINGS) return (0);
3373 for (*x = xmin, i = 0; ((*x < xmax) && (i < len)); (*x)++, s++, i++)
3375 /* Access the grid */
3376 cave_type *c_ptr = &cave[*y][*x];
3380 int object_index = letter[idx].object;
3381 int monster_index = letter[idx].monster;
3382 int random = letter[idx].random;
3383 int artifact_index = letter[idx].artifact;
3385 /* Lay down a floor */
3386 c_ptr->feat = letter[idx].feature;
3388 /* Only the features */
3389 if (init_flags & INIT_ONLY_FEATURES) continue;
3392 c_ptr->info = letter[idx].cave_info;
3394 /* Create a monster */
3395 if (random & RANDOM_MONSTER)
3397 monster_level = base_level + monster_index;
3399 place_monster(*y, *x, TRUE, TRUE);
3401 monster_level = base_level;
3403 else if (monster_index)
3405 /* Make alive again */
3406 if (r_info[monster_index].flags1 & RF1_UNIQUE)
3408 r_info[monster_index].cur_num = 0;
3409 r_info[monster_index].max_num = 1;
3412 /* Make alive again */
3413 if (r_info[monster_index].flags7 & RF7_UNIQUE_7)
3415 if (r_info[monster_index].cur_num == r_info[monster_index].max_num)
3417 r_info[monster_index].max_num++;
3422 place_monster_aux(*y, *x, monster_index, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE);
3425 /* Object (and possible trap) */
3426 if ((random & RANDOM_OBJECT) && (random & RANDOM_TRAP))
3428 object_level = base_level + object_index;
3431 * Random trap and random treasure defined
3432 * 25% chance for trap and 75% chance for object
3434 if (rand_int(100) < 75)
3436 place_object(*y, *x, FALSE, FALSE);
3443 object_level = base_level;
3445 else if (random & RANDOM_OBJECT)
3447 object_level = base_level + object_index;
3449 /* Create an out of deep object */
3450 if (rand_int(100) < 75)
3451 place_object(*y, *x, FALSE, FALSE);
3452 else if (rand_int(100) < 80)
3453 place_object(*y, *x, TRUE, FALSE);
3455 place_object(*y, *x, TRUE, TRUE);
3457 object_level = base_level;
3460 else if (random & RANDOM_TRAP)
3464 else if (object_index)
3466 /* Get local object */
3467 object_type *o_ptr = &object_type_body;
3469 /* Create the item */
3470 object_prep(o_ptr, object_index);
3472 if (o_ptr->tval == TV_GOLD)
3474 coin_type = object_index - OBJ_GOLD_LIST;
3479 /* Apply magic (no messages, no artifacts) */
3480 apply_magic(o_ptr, base_level, FALSE, TRUE, FALSE, FALSE);
3483 o_ptr->python = object_create_callback(o_ptr);
3484 #endif /* USE_SCRIPT */
3486 (void)drop_near(o_ptr, -1, *y, *x);
3492 if (a_info[artifact_index].cur_num)
3496 object_type *q_ptr = &forge;
3498 object_prep(q_ptr, k_idx);
3500 q_ptr->python = object_create_callback(q_ptr);
3501 #endif /* USE_SCRIPT */
3503 /* Drop it in the dungeon */
3504 (void)drop_near(q_ptr, -1, *y, *x);
3508 /* Create the artifact */
3509 create_named_art(artifact_index, *y, *x);
3511 a_info[artifact_index].cur_num = 1;
3515 /* Terrain special */
3516 c_ptr->special = letter[idx].special;
3524 /* Process "Q:<number>:<command>:... -- quest info */
3525 else if (buf[0] == 'Q')
3532 num = tokenize(buf + 2, 33, zz, 0);
3536 num = tokenize(buf + 3, 33, zz, 0);
3539 /* Have we enough parameters? */
3540 if (num < 3) return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3543 q_ptr = &(quest[atoi(zz[0])]);
3545 /* Process "Q:<q_index>:Q:<type>:<num_mon>:<cur_num>:<max_num>:<level>:<r_idx>:<k_idx>:<flags>" -- quest info */
3546 if (zz[1][0] == 'Q')
3548 if (init_flags & INIT_ASSIGN)
3550 monster_race *r_ptr;
3551 artifact_type *a_ptr;
3553 if (num < 9) return (PARSE_ERROR_TOO_FEW_ARGUMENTS);
3555 q_ptr->type = atoi(zz[2]);
3556 q_ptr->num_mon = atoi(zz[3]);
3557 q_ptr->cur_num = atoi(zz[4]);
3558 q_ptr->max_num = atoi(zz[5]);
3559 q_ptr->level = atoi(zz[6]);
3560 q_ptr->r_idx = atoi(zz[7]);
3561 q_ptr->k_idx = atoi(zz[8]);
3562 q_ptr->dungeon = atoi(zz[9]);
3565 q_ptr->flags = atoi(zz[10]);
3567 r_ptr = &r_info[q_ptr->r_idx];
3568 if (r_ptr->flags1 & RF1_UNIQUE)
3569 r_ptr->flags1 |= RF1_QUESTOR;
3571 a_ptr = &a_info[q_ptr->k_idx];
3572 a_ptr->flags3 |= TR3_QUESTITEM;
3577 /* Process "Q:<q_index>:N:<name>" -- quest name */
3578 else if (zz[1][0] == 'N')
3580 if (init_flags & (INIT_ASSIGN | INIT_SHOW_TEXT))
3582 strcpy(q_ptr->name, zz[2]);
3588 /* Process "Q:<q_index>:T:<text>" -- quest description line */
3589 else if (zz[1][0] == 'T')
3591 if (init_flags & INIT_SHOW_TEXT)
3593 strcpy(quest_text[quest_text_line], zz[2]);
3601 /* Process "W:<command>: ..." -- info for the wilderness */
3602 else if (buf[0] == 'W')
3604 return parse_line_wilderness(buf, ymin, xmin, ymax, xmax, y, x);
3607 /* Process "P:<y>:<x>" -- player position */
3608 else if (buf[0] == 'P')
3610 if (init_flags & INIT_CREATE_DUNGEON)
3612 if (tokenize(buf + 2, 2, zz, 0) == 2)
3614 int panels_x, panels_y;
3616 /* Hack - Set the dungeon size */
3617 panels_y = (*y / SCREEN_HGT);
3618 if (*y % SCREEN_HGT) panels_y++;
3619 cur_hgt = panels_y * SCREEN_HGT;
3621 panels_x = (*x / SCREEN_WID);
3622 if (*x % SCREEN_WID) panels_x++;
3623 cur_wid = panels_x * SCREEN_WID;
3625 /* Choose a panel row */
3626 max_panel_rows = (cur_hgt / SCREEN_HGT) * 2 - 2;
3627 if (max_panel_rows < 0) max_panel_rows = 0;
3629 /* Choose a panel col */
3630 max_panel_cols = (cur_wid / SCREEN_WID) * 2 - 2;
3631 if (max_panel_cols < 0) max_panel_cols = 0;
3633 /* Assume illegal panel */
3634 panel_row = max_panel_rows;
3635 panel_col = max_panel_cols;
3637 /* Place player in a quest level */
3638 if (p_ptr->inside_quest)
3642 /* Delete the monster (if any) */
3643 delete_monster(py, px);
3651 /* Place player in the town */
3652 else if (!p_ptr->oldpx && !p_ptr->oldpy)
3654 p_ptr->oldpy = atoi(zz[0]);
3655 p_ptr->oldpx = atoi(zz[1]);
3663 /* Process "B:<Index>:<Command>:..." -- Building definition */
3664 else if (buf[0] == 'B')
3666 return parse_line_building(buf);
3669 /* Process "M:<type>:<maximum>" -- set maximum values */
3670 else if (buf[0] == 'M')
3672 if (tokenize(buf+2, 2, zz, 0) == 2)
3675 if (zz[0][0] == 'T')
3677 max_towns = atoi(zz[1]);
3680 /* Maximum quests */
3681 else if (zz[0][0] == 'Q')
3683 max_quests = atoi(zz[1]);
3687 else if (zz[0][0] == 'R')
3689 max_r_idx = atoi(zz[1]);
3693 else if (zz[0][0] == 'K')
3695 max_k_idx = atoi(zz[1]);
3699 else if (zz[0][0] == 'V')
3701 max_v_idx = atoi(zz[1]);
3705 else if (zz[0][0] == 'F')
3707 max_f_idx = atoi(zz[1]);
3711 else if (zz[0][0] == 'A')
3713 max_a_idx = atoi(zz[1]);
3717 else if (zz[0][0] == 'E')
3719 max_e_idx = atoi(zz[1]);
3723 else if (zz[0][0] == 'D')
3725 max_d_idx = atoi(zz[1]);
3729 else if (zz[0][0] == 'O')
3731 max_o_idx = atoi(zz[1]);
3735 else if (zz[0][0] == 'M')
3737 max_m_idx = atoi(zz[1]);
3740 /* Wilderness size */
3741 else if (zz[0][0] == 'W')
3743 /* Maximum wild_x_size */
3744 if (zz[0][1] == 'X')
3745 max_wild_x = atoi(zz[1]);
3746 /* Maximum wild_y_size */
3747 if (zz[0][1] == 'Y')
3748 max_wild_y = atoi(zz[1]);
3762 static cptr variant = "ZANGBAND";
3766 * Helper function for "process_dungeon_file()"
3768 static cptr process_dungeon_file_expr(char **sp, char *fp)
3784 while (isspace(*s)) s++;
3802 t = process_dungeon_file_expr(&s, &f);
3811 else if (streq(t, "IOR"))
3814 while (*s && (f != b2))
3816 t = process_dungeon_file_expr(&s, &f);
3817 if (*t && !streq(t, "0")) v = "1";
3822 else if (streq(t, "AND"))
3825 while (*s && (f != b2))
3827 t = process_dungeon_file_expr(&s, &f);
3828 if (*t && streq(t, "0")) v = "0";
3833 else if (streq(t, "NOT"))
3836 while (*s && (f != b2))
3838 t = process_dungeon_file_expr(&s, &f);
3839 if (*t && streq(t, "1")) v = "0";
3844 else if (streq(t, "EQU"))
3847 if (*s && (f != b2))
3849 t = process_dungeon_file_expr(&s, &f);
3851 while (*s && (f != b2))
3854 t = process_dungeon_file_expr(&s, &f);
3855 if (*t && !streq(p, t)) v = "0";
3860 else if (streq(t, "LEQ"))
3863 if (*s && (f != b2))
3865 t = process_dungeon_file_expr(&s, &f);
3867 while (*s && (f != b2))
3870 t = process_dungeon_file_expr(&s, &f);
3871 if (*t && (strcmp(p, t) > 0)) v = "0";
3876 else if (streq(t, "GEQ"))
3879 if (*s && (f != b2))
3881 t = process_dungeon_file_expr(&s, &f);
3883 while (*s && (f != b2))
3886 t = process_dungeon_file_expr(&s, &f);
3887 if (*t && (strcmp(p, t) < 0)) v = "0";
3894 while (*s && (f != b2))
3896 t = process_dungeon_file_expr(&s, &f);
3901 if (f != b2) v = "?x?x?";
3903 /* Extract final and Terminate */
3904 if ((f = *s) != '\0') *s++ = '\0';
3910 /* Accept all printables except spaces and brackets */
3911 while (isprint(*s) && !strchr(" []", *s)) ++s;
3913 /* Extract final and Terminate */
3914 if ((f = *s) != '\0') *s++ = '\0';
3920 if (streq(b+1, "SYS"))
3926 else if (streq(b+1, "GRAF"))
3931 else if (streq(b+1, "MONOCHROME"))
3940 else if (streq(b+1, "RACE"))
3943 v = rp_ptr->E_title;
3950 else if (streq(b+1, "CLASS"))
3953 v = cp_ptr->E_title;
3960 else if (streq(b+1, "REALM1"))
3963 v = E_realm_names[p_ptr->realm1];
3965 v = realm_names[p_ptr->realm1];
3970 else if (streq(b+1, "REALM2"))
3973 v = E_realm_names[p_ptr->realm2];
3975 v = realm_names[p_ptr->realm2];
3980 else if (streq(b+1, "PLAYER"))
3986 else if (streq(b+1, "TOWN"))
3988 sprintf(tmp, "%d", p_ptr->town_num);
3993 else if (streq(b+1, "LEVEL"))
3995 sprintf(tmp, "%d", p_ptr->lev);
3999 /* Current quest number */
4000 else if (streq(b+1, "QUEST_NUMBER"))
4002 sprintf(tmp, "%d", p_ptr->inside_quest);
4006 /* Number of last quest */
4007 else if (streq(b+1, "LEAVING_QUEST"))
4009 sprintf(tmp, "%d", leaving_quest);
4014 else if (prefix(b+1, "QUEST"))
4016 /* "QUEST" uses a special parameter to determine the number of the quest */
4017 sprintf(tmp, "%d", quest[atoi(b+6)].status);
4022 else if (prefix(b+1, "RANDOM"))
4024 /* "RANDOM" uses a special parameter to determine the number of the quest */
4025 sprintf(tmp, "%d", (int)(seed_town%atoi(b+7)));
4030 else if (streq(b+1, "VARIANT"))
4036 else if (streq(b+1, "WILDERNESS"))
4039 sprintf(tmp, "NONE");
4041 sprintf(tmp, "LITE");
4043 sprintf(tmp, "NORMAL");
4066 errr process_dungeon_file(cptr name, int ymin, int xmin, int ymax, int xmax)
4076 bool bypass = FALSE;
4078 int x = xmin, y = ymin;
4081 /* Build the filename */
4082 path_build(buf, 1024, ANGBAND_DIR_EDIT, name);
4085 fp = my_fopen(buf, "r");
4088 if (!fp) return (-1);
4091 /* Process the file */
4092 while (0 == my_fgets(fp, buf, 1024))
4098 /* Skip "empty" lines */
4099 if (!buf[0]) continue;
4101 /* Skip "blank" lines */
4102 if (isspace(buf[0])) continue;
4105 if (buf[0] == '#') continue;
4108 /* Process "?:<expr>" */
4109 if ((buf[0] == '?') && (buf[1] == ':'))
4118 /* Parse the expr */
4119 v = process_dungeon_file_expr(&s, &f);
4122 bypass = (streq(v, "0") ? TRUE : FALSE);
4128 /* Apply conditionals */
4129 if (bypass) continue;
4132 /* Process "%:<file>" */
4135 /* Process that file if allowed */
4136 (void)process_dungeon_file(buf + 2, ymin, xmin, ymax, xmax);
4143 /* Process the line */
4144 err = process_dungeon_file_aux(buf, ymin, xmin, ymax, xmax, &y, &x);
4156 oops = (((err > 0) && (err < PARSE_ERROR_MAX)) ? err_str[err] : "unknown");
4159 msg_format("Error %d (%s) at line %d of '%s'.", err, oops, num, name);
4161 msg_format("'%s'¤ò²òÀÏÃæ¡£", buf);
4163 msg_format("Parsing '%s'.", buf);
4170 /* Close the file */
4180 void write_r_info_txt(void)
4182 int i, j, z, fc, bc;
4190 monster_race *r_ptr;
4192 monster_blow *b_ptr;
4194 FILE *fff = fopen("output.txt", "wt");
4202 fprintf(fff, "# File: r_info.txt (autogenerated)\n\n");
4204 fprintf(fff, "# Version stamp (required)\n\n");
4207 fprintf(fff, "V:%d.%d.%d\n\n\n", r_head->v_major, r_head->v_minor, r_head->v_patch);
4210 fprintf(fff, "##### The Player #####\n\n");
4212 for (z = -1; z < alloc_race_size; z++)
4214 /* Output the monsters in order */
4215 i = (z >= 0) ? alloc_race_table[z].index : 0;
4217 /* Acquire the monster */
4220 /* Ignore empty monsters */
4221 if (!strlen(r_name + r_ptr->name)) continue;
4223 /* Ignore useless monsters */
4224 if (i && !r_ptr->speed) continue;
4226 /* Write a note if necessary */
4227 if (i && (!r_ptr->level != !mode))
4232 fprintf(fff, "\n##### Town monsters #####\n\n");
4234 /* Note the dungeon */
4237 fprintf(fff, "\n##### Normal monsters #####\n\n");
4240 /* Record the change */
4241 mode = r_ptr->level;
4244 /* Acquire the flags */
4245 f_ptr[0] = r_ptr->flags1; n_ptr[0] = r_info_flags1;
4246 f_ptr[1] = r_ptr->flags2; n_ptr[1] = r_info_flags2;
4247 f_ptr[2] = r_ptr->flags3; n_ptr[2] = r_info_flags3;
4248 f_ptr[3] = r_ptr->flags4; n_ptr[3] = r_info_flags4;
4249 f_ptr[4] = r_ptr->flags5; n_ptr[4] = r_info_flags5;
4250 f_ptr[5] = r_ptr->flags6; n_ptr[5] = r_info_flags6;
4251 f_ptr[6] = r_ptr->flags7; n_ptr[6] = r_info_flags7;
4252 f_ptr[7] = r_ptr->flags8; n_ptr[7] = r_info_flags8;
4253 f_ptr[8] = r_ptr->flags9; n_ptr[8] = r_info_flags9;
4255 /* Write New/Number/Name */
4256 fprintf(fff, "N:%d:%s\n", z + 1, r_name + r_ptr->name);
4259 fprintf(fff, "G:%c:%c\n", r_ptr->d_char, color_char[r_ptr->d_attr]);
4261 /* Write Information */
4262 fprintf(fff, "I:%d:%dd%d:%d:%d:%d\n", r_ptr->speed, r_ptr->hdice, r_ptr->hside,
4263 r_ptr->aaf, r_ptr->ac, r_ptr->sleep);
4265 /* Write more information */
4266 fprintf(fff, "W:%d:%d:%d:%ld\n", r_ptr->level, r_ptr->rarity, r_ptr->extra, r_ptr->mexp);
4269 for(j = 0; j < 4; j++)
4271 b_ptr = &(r_ptr->blow[j]);
4273 /* Stop when done */
4274 if (!b_ptr->method) break;
4276 /* Write the blows */
4277 fprintf(fff, "B:%s:%s:%dd%d\n", r_info_blow_method[b_ptr->method],
4278 r_info_blow_effect[b_ptr->effect],
4279 b_ptr->d_dice, b_ptr->d_side);
4282 /* Extract the flags */
4283 for (fc = 0, j = 0; j < 96; j++)
4285 /* Check this flag */
4286 if (f_ptr[j / 32] & (1L << (j % 32))) flags[fc++] = n_ptr[j / 32][j % 32];
4289 /* Extract the extra flags */
4290 for (j = 192; j < 288; j++)
4292 /* Check this flag */
4293 if (f_ptr[j / 32] & (1L << (j % 32))) flags[fc++] = n_ptr[j / 32][j % 32];
4296 /* Write the flags */
4297 for (j = 0; j < fc;)
4301 /* Start the line */
4304 for (bc = 0; (bc < 60) && (j < fc); j++)
4308 /* Format the flag */
4309 sprintf(t, "%s%s", flags[j], (j < fc - 1) ? " | " : "");
4311 /* Add it to the buffer */
4314 /* Note the length */
4318 /* Done with this line; write it */
4319 fprintf(fff, "%s\n", buf);
4322 /* Write Spells if applicable */
4323 if (r_ptr->freq_spell)
4325 /* Write the frequency */
4326 fprintf(fff, "S:1_IN_%d | \n", 100 / r_ptr->freq_spell);
4328 /* Extract the spell flags */
4329 for (fc = 0, j = 96; j < 192; j++)
4331 /* Check this flag */
4332 if (f_ptr[j / 32] & (1L << (j % 32))) flags[fc++] = n_ptr[j / 32][j % 32];
4335 /* Write the flags */
4336 for (j = 0; j < fc;)
4340 /* Start the line */
4343 for (bc = 0, t = buf + 2; (bc < 60) && (j < fc); j++)
4347 /* Format the flag */
4348 sprintf(t, "%s%s", flags[j], (j < fc - 1) ? " | " : "");
4352 /* Note the length */
4359 /* Done with this line; write it */
4360 fprintf(fff, "%s\n", buf);
4364 /* Acquire the description */
4365 desc = r_text + r_ptr->text;
4366 dlen = strlen(desc);
4368 /* Write Description */
4369 for (j = 0; j < dlen;)
4373 /* Start the line */
4376 for (bc = 0, t = buf + 2; ((bc < 60) || !isspace(desc[j])) && (j < dlen); j++, bc++, t++)
4384 /* Done with this line; write it */
4385 fprintf(fff, "%s\n", buf);
4388 /* Space between entries */