PageRenderTime 54ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 1ms

/src/init1.c

https://bitbucket.org/ekolis/jackband
C | 4460 lines | 2504 code | 908 blank | 1048 comment | 1277 complexity | f86b0fd1a926979ee1ee65e5a39c5449 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. * File: init1.c
  3. * Purpose: Parsing the lib/edit/ files into data structures.
  4. *
  5. * Copyright (c) 1997 Ben Harrison
  6. *
  7. * This work is free software; you can redistribute it and/or modify it
  8. * under the terms of either:
  9. *
  10. * a) the GNU General Public License as published by the Free Software
  11. * Foundation, version 2, or
  12. *
  13. * b) the "Angband licence":
  14. * This software may be copied and distributed for educational, research,
  15. * and not for profit purposes provided that this copyright and statement
  16. * are included in all such copies. Other copyrights may also apply.
  17. */
  18. #include "angband.h"
  19. #include "object/tvalsval.h"
  20. /*
  21. * This file is used to initialize various variables and arrays for the
  22. * Angband game. Note the use of "fd_read()" and "fd_write()" to bypass
  23. * the common limitation of "read()" and "write()" to only 32767 bytes
  24. * at a time.
  25. *
  26. * Several of the arrays for Angband are built from "template" files in
  27. * the "lib/file" directory, from which quick-load binary "image" files
  28. * are constructed whenever they are not present in the "lib/data"
  29. * directory, or if those files become obsolete, if we are allowed.
  30. *
  31. * Warning -- the "ascii" file parsers use a minor hack to collect the
  32. * name and text information in a single pass. Thus, the game will not
  33. * be able to load any template file with more than 20K of names or 60K
  34. * of text, even though technically, up to 64K should be legal.
  35. *
  36. * The code could actually be removed and placed into a "stand-alone"
  37. * program, but that feels a little silly, especially considering some
  38. * of the platforms that we currently support.
  39. */
  40. #include "effects.h"
  41. #include "monster/constants.h"
  42. #include "init.h"
  43. /*** Helper arrays for parsing ascii template files ***/
  44. /* Use a slightly unusual include method to create effect_list[] */
  45. static const char *effect_list[] =
  46. {
  47. #define EFFECT(x, y, r, z) #x,
  48. #include "list-effects.h"
  49. #undef EFFECT
  50. };
  51. /*
  52. * Monster blow methods
  53. */
  54. static const char *r_info_blow_method[] =
  55. {
  56. #define RBM(a, b) #a,
  57. #include "list-blow-methods.h"
  58. #undef RBM
  59. NULL
  60. };
  61. /*
  62. * Monster blow effects
  63. */
  64. static const char *r_info_blow_effect[] =
  65. {
  66. #define RBE(a, b) #a,
  67. #include "list-blow-effects.h"
  68. #undef RBE
  69. NULL
  70. };
  71. /*
  72. * Monster race flags
  73. */
  74. static const char *r_info_flags[] =
  75. {
  76. #define RF(a, b) #a,
  77. #include "list-mon-flags.h"
  78. #undef RF
  79. NULL
  80. };
  81. /*
  82. * Monster (race) spell flags
  83. */
  84. static const char *r_info_spell_flags[] =
  85. {
  86. #define RSF(a, b) #a,
  87. #include "list-mon-spells.h"
  88. #undef RSF
  89. NULL
  90. };
  91. /*
  92. * Object (kind) flags
  93. */
  94. static const char *k_info_flags[] =
  95. {
  96. #define OF(a, b) #a,
  97. #include "list-object-flags.h"
  98. #undef OF
  99. NULL
  100. };
  101. /*
  102. * Player race and class flags
  103. */
  104. static const char *player_info_flags[] =
  105. {
  106. #define PF(a, b) #a,
  107. #include "list-player-flags.h"
  108. #undef PF
  109. NULL
  110. };
  111. /*
  112. * Terrain feature flags
  113. */
  114. static const char *f_info_flags[] =
  115. {
  116. "PWALK",
  117. "PPASS",
  118. "MWALK",
  119. "MPASS",
  120. "LOOK",
  121. "DIG",
  122. "DOOR",
  123. "EXIT_UP",
  124. "EXIT_DOWN",
  125. "PERM",
  126. "TRAP",
  127. "SHOP",
  128. "HIDDEN",
  129. "BORING",
  130. NULL
  131. };
  132. /*** Initialize from ascii template files ***/
  133. /*
  134. * Initialize an "*_info" array, by parsing an ascii "template" file
  135. */
  136. errr init_info_txt(ang_file *fp, char *buf, header *head,
  137. parse_info_txt_func parse_info_txt_line)
  138. {
  139. errr err;
  140. /* Not ready yet */
  141. bool okay = FALSE;
  142. /* Just before the first record */
  143. error_idx = -1;
  144. /* Just before the first line */
  145. error_line = 0;
  146. /* Prepare the "fake" stuff */
  147. head->name_size = 0;
  148. head->text_size = 0;
  149. /* Parse */
  150. while (file_getl(fp, buf, 1024))
  151. {
  152. /* Advance the line number */
  153. error_line++;
  154. /* Skip comments and blank lines */
  155. if (!buf[0] || (buf[0] == '#')) continue;
  156. /* Verify correct "colon" format */
  157. if (buf[1] != ':') return (PARSE_ERROR_MISSING_COLON);
  158. /* Hack -- Process 'V' for "Version" */
  159. if (buf[0] == 'V')
  160. {
  161. int v1, v2, v3;
  162. /* Scan for the values */
  163. if ((3 != sscanf(buf+2, "%d.%d.%d", &v1, &v2, &v3)) ||
  164. (v1 != head->v_major) ||
  165. (v2 != head->v_minor) ||
  166. (v3 != head->v_patch))
  167. {
  168. #if 0
  169. return (PARSE_ERROR_OBSOLETE_FILE);
  170. #endif
  171. }
  172. /* Okay to proceed */
  173. okay = TRUE;
  174. /* Continue */
  175. continue;
  176. }
  177. /* No version yet */
  178. if (!okay) return (PARSE_ERROR_OBSOLETE_FILE);
  179. /* Parse the line */
  180. if ((err = (*parse_info_txt_line)(buf, head)) != 0)
  181. return (err);
  182. }
  183. /* Complete the "name" and "text" sizes */
  184. if (head->name_size) head->name_size++;
  185. if (head->text_size) head->text_size++;
  186. /* No version yet */
  187. if (!okay) return (PARSE_ERROR_OBSOLETE_FILE);
  188. /* Success */
  189. return (0);
  190. }
  191. /*
  192. * Add a text to the text-storage and store offset to it.
  193. *
  194. * Returns FALSE when there isn't enough space available to store
  195. * the text.
  196. */
  197. static bool add_text(u32b *offset, header *head, cptr buf)
  198. {
  199. size_t len = strlen(buf);
  200. /* Hack -- Verify space */
  201. if (head->text_size + len + 8 > z_info->fake_text_size)
  202. return (FALSE);
  203. /* New text? */
  204. if (*offset == 0)
  205. {
  206. /* Advance and save the text index */
  207. *offset = ++head->text_size;
  208. }
  209. /* Append chars to the text */
  210. my_strcpy(head->text_ptr + head->text_size, buf, len + 1);
  211. /* Advance the index */
  212. head->text_size += len;
  213. /* Success */
  214. return (TRUE);
  215. }
  216. /*
  217. * Add a name to the name-storage and return an offset to it.
  218. *
  219. * Returns 0 when there isn't enough space available to store
  220. * the name.
  221. */
  222. static u32b add_name(header *head, cptr buf)
  223. {
  224. u32b index;
  225. size_t len = strlen(buf);
  226. /* Hack -- Verify space */
  227. if (head->name_size + len + 8 > z_info->fake_name_size)
  228. return (0);
  229. /* Advance and save the name index */
  230. index = ++head->name_size;
  231. /* Append chars to the names */
  232. my_strcpy(head->name_ptr + head->name_size, buf, len + 1);
  233. /* Advance the index */
  234. head->name_size += len;
  235. /* Return the name index */
  236. return (index);
  237. }
  238. /*
  239. * Grab one flag from a textual string
  240. */
  241. static errr grab_one_flag(u32b *flags, cptr names[], cptr what)
  242. {
  243. int i;
  244. /* Check flags */
  245. for (i = 0; i < 32 && names[i]; i++)
  246. {
  247. if (streq(what, names[i]))
  248. {
  249. *flags |= (1L << i);
  250. return (0);
  251. }
  252. }
  253. return (-1);
  254. }
  255. /*
  256. * This function reads a value of the form "1+2d3M4"
  257. *
  258. * - The 1 is a constant base value.
  259. * - The 2d3 is a dice roll, to be applied with damroll(). The number of dice
  260. * is optional, and if not present, is assumed to be 1.
  261. * - The M4 is a magic bonus, to be applied with m_bonus().
  262. *
  263. * All parts of the random value are optional. The value is read into a
  264. * "random_value" struct and may be used with the randcalc() function to
  265. * determine the minimum, maximum, average, or randomised result of the roll.
  266. */
  267. static bool parse_random_value(const char *str, random_value *bonus)
  268. {
  269. bool negative = FALSE;
  270. char buffer[50];
  271. int i = 0, b, dn, ds, mb;
  272. const char end_chr = '|';
  273. char eov;
  274. /* Entire value may be negated */
  275. if (str[0] == '-')
  276. {
  277. negative = TRUE;
  278. i++;
  279. }
  280. /* Make a working copy of the string */
  281. my_strcpy(buffer, &str[i], N_ELEMENTS(buffer) - 2);
  282. /* Check for invalid negative numbers */
  283. if (NULL != strstr(buffer, "-")) return FALSE;
  284. /*
  285. * Add a sentinal value at the end of the string.
  286. * Used by scanf to make sure there's no text after the final conversion.
  287. */
  288. buffer[strlen(buffer) + 1] = '\0';
  289. buffer[strlen(buffer)] = end_chr;
  290. /* Scan the value, apply defaults for unspecified components */
  291. if (5 == sscanf(buffer, "%d+%dd%dM%d%c", &b, &dn, &ds, &mb, &eov) && eov == end_chr)
  292. {
  293. /* No defaults */
  294. }
  295. else if (4 == sscanf(buffer, "%d+d%dM%d%c", &b, &ds, &mb, &eov) && eov == end_chr)
  296. {
  297. dn = 1;
  298. }
  299. else if (3 == sscanf(buffer, "%d+M%d%c", &b, &mb, &eov) && eov == end_chr)
  300. {
  301. dn = 0; ds = 0;
  302. }
  303. else if (4 == sscanf(buffer, "%d+%dd%d%c", &b, &dn, &ds, &eov) && eov == end_chr)
  304. {
  305. mb = 0;
  306. }
  307. else if (3 == sscanf(buffer, "%d+d%d%c", &b, &ds, &eov) && eov == end_chr)
  308. {
  309. dn = 1; mb = 0;
  310. }
  311. else if (4 == sscanf(buffer, "%dd%dM%d%c", &dn, &ds, &mb, &eov) && eov == end_chr)
  312. {
  313. b = 0;
  314. }
  315. else if (3 == sscanf(buffer, "d%dM%d%c", &ds, &mb, &eov) && eov == end_chr)
  316. {
  317. b = 0; dn = 1;
  318. }
  319. else if (2 == sscanf(buffer, "M%d%c", &mb, &eov) && eov == end_chr)
  320. {
  321. b = 0; dn = 0; ds = 0;
  322. }
  323. else if (3 == sscanf(buffer, "%dd%d%c", &dn, &ds, &eov) && eov == end_chr)
  324. {
  325. b = 0; mb = 0;
  326. }
  327. else if (2 == sscanf(buffer, "d%d%c", &ds, &eov) && eov == end_chr)
  328. {
  329. b = 0; dn = 1; mb = 0;
  330. }
  331. else if (2 == sscanf(buffer, "%d%c", &b, &eov) && eov == end_chr)
  332. {
  333. dn = 0; ds = 0; mb = 0;
  334. }
  335. else
  336. {
  337. return FALSE;
  338. }
  339. /* Assign the values */
  340. bonus->base = b;
  341. bonus->dice = dn;
  342. bonus->sides = ds;
  343. bonus->m_bonus = mb;
  344. /*
  345. * Handle negation (the random components are always positive, so the base
  346. * must be adjusted as necessary).
  347. */
  348. if (negative)
  349. {
  350. bonus->base *= -1;
  351. bonus->base -= bonus->m_bonus;
  352. bonus->base -= bonus->dice * (bonus->sides + 1);
  353. }
  354. return TRUE;
  355. }
  356. /*
  357. * Figure out what index an activation should have
  358. */
  359. static u32b grab_one_effect(const char *what)
  360. {
  361. size_t i;
  362. /* Scan activations */
  363. for (i = 0; i < N_ELEMENTS(effect_list); i++)
  364. {
  365. if (streq(what, effect_list[i]))
  366. return i;
  367. }
  368. /* Oops */
  369. msg_format("Unknown effect '%s'.", what);
  370. /* Error */
  371. return 0;
  372. }
  373. /**
  374. * Initialise the store stocking lists.
  375. */
  376. errr init_store_txt(ang_file *fp, char *buf)
  377. {
  378. int i;
  379. int store_num = -1;
  380. store_type *st_ptr;
  381. error_idx = -1;
  382. error_line = 0;
  383. /* Allocate the stores */
  384. store = C_ZNEW(MAX_STORES, store_type);
  385. for (i = 0; i < MAX_STORES; i++)
  386. {
  387. st_ptr = &store[i];
  388. /* Assume stock */
  389. st_ptr->stock_size = STORE_INVEN_MAX;
  390. st_ptr->stock = C_ZNEW(st_ptr->stock_size, object_type);
  391. }
  392. st_ptr = NULL;
  393. while (file_getl(fp, buf, 1024))
  394. {
  395. error_line++;
  396. if (!buf[0] || buf[0] == '#')
  397. continue;
  398. else if (buf[0] == 'S')
  399. {
  400. int num, slots;
  401. /* Make sure all the previous slots have been filled */
  402. if (st_ptr)
  403. {
  404. if (st_ptr->table_num != st_ptr->table_size)
  405. {
  406. msg_format("Store %d has too few entries (read %d, expected %d).", error_idx, st_ptr->table_num, st_ptr->table_size);
  407. return PARSE_ERROR_TOO_FEW_ENTRIES;
  408. }
  409. }
  410. if (2 != sscanf(buf, "S:%d:%d", &num, &slots))
  411. return PARSE_ERROR_GENERIC;
  412. if (num < 2 || num > 6)
  413. return PARSE_ERROR_GENERIC;
  414. error_idx = num;
  415. /* Account for 0-based indexing */
  416. num--;
  417. store_num = num;
  418. /* Set up this store */
  419. st_ptr = &store[num];
  420. st_ptr->table_size = slots;
  421. st_ptr->table = C_ZNEW(st_ptr->table_size, s16b);
  422. }
  423. else if (buf[0] == 'I')
  424. {
  425. int slots, tval;
  426. int k_idx;
  427. char *tval_s;
  428. char *sval_s;
  429. if (store_num == -1 || !st_ptr)
  430. return PARSE_ERROR_GENERIC;
  431. if (1 != sscanf(buf, "I:%d:", &slots))
  432. return PARSE_ERROR_GENERIC;
  433. if (st_ptr->table_num + slots > st_ptr->table_size)
  434. return PARSE_ERROR_TOO_MANY_ENTRIES;
  435. /* Find the beginning of the tval field */
  436. tval_s = strchr(buf+2, ':');
  437. if (!tval_s) return PARSE_ERROR_MISSING_COLON;
  438. *tval_s++ = '\0';
  439. if (!*tval_s) return PARSE_ERROR_MISSING_FIELD;
  440. /* Now find the beginning of the sval field */
  441. sval_s = strchr(tval_s, ':');
  442. if (!sval_s) return PARSE_ERROR_MISSING_COLON;
  443. *sval_s++ = '\0';
  444. if (!*sval_s) return PARSE_ERROR_MISSING_FIELD;
  445. /* Now convert the tval into its numeric equivalent */
  446. tval = tval_find_idx(tval_s);
  447. if (tval == -1) return PARSE_ERROR_UNRECOGNISED_TVAL;
  448. k_idx = lookup_name(tval, sval_s);
  449. if (!k_idx) return PARSE_ERROR_UNRECOGNISED_SVAL;
  450. while (slots--)
  451. st_ptr->table[st_ptr->table_num++] = k_idx;
  452. }
  453. else
  454. {
  455. return PARSE_ERROR_UNDEFINED_DIRECTIVE;
  456. }
  457. }
  458. /* No errors */
  459. return 0;
  460. }
  461. /**
  462. * Initialise the random name fragments
  463. */
  464. errr init_names_txt(ang_file *fp, char *buf)
  465. {
  466. int i, name_section;
  467. u32b num_names[RANDNAME_NUM_TYPES];
  468. char temp[1024];
  469. int counter = 0;
  470. error_line = 0;
  471. memset(num_names, 0, RANDNAME_NUM_TYPES * sizeof(u32b));
  472. /*
  473. * Go through the file and count the total number of names in each name
  474. * section
  475. */
  476. while (file_getl(fp, buf, 1024))
  477. {
  478. error_line++;
  479. if (!buf[0] || '#' == buf[0])
  480. continue;
  481. else if ('N' == buf[0])
  482. {
  483. if (1 != sscanf(buf, "N:%d", &name_section))
  484. return PARSE_ERROR_GENERIC;
  485. if (name_section > RANDNAME_NUM_TYPES)
  486. return PARSE_ERROR_GENERIC;
  487. }
  488. else if ('D' == buf[0])
  489. {
  490. num_names[name_section]++;
  491. }
  492. else
  493. {
  494. return PARSE_ERROR_UNDEFINED_DIRECTIVE;
  495. }
  496. }
  497. /* Go back to the start of the file */
  498. file_seek(fp, 0);
  499. /* Allocate some memory for pointers to sections */
  500. name_sections = C_ZNEW(RANDNAME_NUM_TYPES, cptr*);
  501. /* Allocate more memory for pointers to names */
  502. /* Add a null element at the end of each array (see randname.c) */
  503. for (i = 0; i < RANDNAME_NUM_TYPES; i++)
  504. {
  505. if (num_names[i])
  506. {
  507. name_sections[i] = C_ZNEW(num_names[i] + 1, cptr);
  508. }
  509. }
  510. /*
  511. * Go through the file again and read each name into the relevant array
  512. */
  513. while (file_getl(fp, buf, 1024))
  514. {
  515. error_line++;
  516. if (!buf[0] || '#' == buf[0])
  517. continue;
  518. else if ('N' == buf[0])
  519. {
  520. if (1 != sscanf(buf, "N:%d", &name_section))
  521. return PARSE_ERROR_GENERIC;
  522. if (name_section > RANDNAME_NUM_TYPES)
  523. return PARSE_ERROR_GENERIC;
  524. counter = 0;
  525. }
  526. else if ('D' == buf[0])
  527. {
  528. if (1 != sscanf(buf, "D:%s", temp))
  529. return PARSE_ERROR_GENERIC;
  530. name_sections[name_section][counter++] = string_make(temp);
  531. }
  532. else
  533. {
  534. return PARSE_ERROR_UNDEFINED_DIRECTIVE;
  535. }
  536. }
  537. /* No errors */
  538. return 0;
  539. }
  540. /*
  541. * Initialize the "z_info" structure, by parsing an ascii "template" file
  542. */
  543. errr parse_z_info(char *buf, header *head)
  544. {
  545. maxima *z_info = head->info_ptr;
  546. /* Hack - Verify 'M:x:' format */
  547. if (buf[0] != 'M') return (PARSE_ERROR_UNDEFINED_DIRECTIVE);
  548. if (!buf[2]) return (PARSE_ERROR_UNDEFINED_DIRECTIVE);
  549. if (buf[3] != ':') return (PARSE_ERROR_UNDEFINED_DIRECTIVE);
  550. /* Process 'F' for "Maximum f_info[] index" */
  551. if (buf[2] == 'F')
  552. {
  553. int max;
  554. /* Scan for the value */
  555. if (1 != sscanf(buf+4, "%d", &max)) return (PARSE_ERROR_NOT_NUMBER);
  556. /* Save the value */
  557. z_info->f_max = max;
  558. }
  559. /* Process 'K' for "Maximum k_info[] index" */
  560. else if (buf[2] == 'K')
  561. {
  562. int max;
  563. /* Scan for the value */
  564. if (1 != sscanf(buf+4, "%d", &max)) return (PARSE_ERROR_NOT_NUMBER);
  565. /* Save the value */
  566. z_info->k_max = max;
  567. }
  568. /* Process 'A' for "Maximum a_info[] index" */
  569. else if (buf[2] == 'A')
  570. {
  571. int max;
  572. /* Scan for the value */
  573. if (1 != sscanf(buf+4, "%d", &max)) return (PARSE_ERROR_NOT_NUMBER);
  574. /* Save the value */
  575. z_info->a_max = max;
  576. }
  577. /* Process 'E' for "Maximum e_info[] index" */
  578. else if (buf[2] == 'E')
  579. {
  580. int max;
  581. /* Scan for the value */
  582. if (1 != sscanf(buf+4, "%d", &max)) return (PARSE_ERROR_NOT_NUMBER);
  583. /* Save the value */
  584. z_info->e_max = max;
  585. }
  586. /* Process 'R' for "Maximum r_info[] index" */
  587. else if (buf[2] == 'R')
  588. {
  589. int max;
  590. /* Scan for the value */
  591. if (1 != sscanf(buf+4, "%d", &max)) return (PARSE_ERROR_NOT_NUMBER);
  592. /* Save the value */
  593. z_info->r_max = max;
  594. }
  595. /* Process 'V' for "Maximum v_info[] index" */
  596. else if (buf[2] == 'V')
  597. {
  598. int max;
  599. /* Scan for the value */
  600. if (1 != sscanf(buf+4, "%d", &max)) return (PARSE_ERROR_NOT_NUMBER);
  601. /* Save the value */
  602. z_info->v_max = max;
  603. }
  604. /* Process 'P' for "Maximum p_info[] index" */
  605. else if (buf[2] == 'P')
  606. {
  607. int max;
  608. /* Scan for the value */
  609. if (1 != sscanf(buf+4, "%d", &max)) return (PARSE_ERROR_NOT_NUMBER);
  610. /* Save the value */
  611. z_info->p_max = max;
  612. }
  613. /* Process 'C' for "Maximum c_info[] index" */
  614. else if (buf[2] == 'C')
  615. {
  616. int max;
  617. /* Scan for the value */
  618. if (1 != sscanf(buf+4, "%d", &max)) return (PARSE_ERROR_NOT_NUMBER);
  619. /* Save the value */
  620. z_info->c_max = max;
  621. }
  622. /* Process 'H' for "Maximum h_info[] index" */
  623. else if (buf[2] == 'H')
  624. {
  625. int max;
  626. /* Scan for the value */
  627. if (1 != sscanf(buf+4, "%d", &max)) return (PARSE_ERROR_NOT_NUMBER);
  628. /* Save the value */
  629. z_info->h_max = max;
  630. }
  631. /* Process 'B' for "Maximum b_info[] subindex" */
  632. else if (buf[2] == 'B')
  633. {
  634. int max;
  635. /* Scan for the value */
  636. if (1 != sscanf(buf+4, "%d", &max)) return (PARSE_ERROR_NOT_NUMBER);
  637. /* Save the value */
  638. z_info->b_max = max;
  639. }
  640. /* Process 'L' for "Maximum flavor_info[] subindex" */
  641. else if (buf[2] == 'L')
  642. {
  643. int max;
  644. /* Scan for the value */
  645. if (1 != sscanf(buf+4, "%d", &max)) return (PARSE_ERROR_NOT_NUMBER);
  646. /* Save the value */
  647. z_info->flavor_max = max;
  648. }
  649. /* Process 'S' for "Maximum s_info[] subindex" */
  650. else if (buf[2] == 'S')
  651. {
  652. int max;
  653. /* Scan for the value */
  654. if (1 != sscanf(buf+4, "%d", &max)) return (PARSE_ERROR_NOT_NUMBER);
  655. /* Save the value */
  656. z_info->s_max = max;
  657. }
  658. /* Process 'O' for "Maximum o_list[] index" */
  659. else if (buf[2] == 'O')
  660. {
  661. int max;
  662. /* Scan for the value */
  663. if (1 != sscanf(buf+4, "%d", &max)) return (PARSE_ERROR_NOT_NUMBER);
  664. /* Save the value */
  665. z_info->o_max = max;
  666. }
  667. /* Process 'M' for "Maximum mon_list[] index" */
  668. else if (buf[2] == 'M')
  669. {
  670. int max;
  671. /* Scan for the value */
  672. if (1 != sscanf(buf+4, "%d", &max)) return (PARSE_ERROR_NOT_NUMBER);
  673. /* Save the value */
  674. z_info->m_max = max;
  675. }
  676. /* Process 'N' for "Fake name size" */
  677. else if (buf[2] == 'N')
  678. {
  679. long max;
  680. /* Scan for the value */
  681. if (1 != sscanf(buf+4, "%ld", &max)) return (PARSE_ERROR_NOT_NUMBER);
  682. /* Save the value */
  683. z_info->fake_name_size = max;
  684. }
  685. /* Process 'T' for "Fake text size" */
  686. else if (buf[2] == 'T')
  687. {
  688. long max;
  689. /* Scan for the value */
  690. if (1 != sscanf(buf+4, "%ld", &max)) return (PARSE_ERROR_NOT_NUMBER);
  691. /* Save the value */
  692. z_info->fake_text_size = max;
  693. }
  694. else
  695. {
  696. /* Oops */
  697. return (PARSE_ERROR_UNDEFINED_DIRECTIVE);
  698. }
  699. /* Success */
  700. return (0);
  701. }
  702. /*
  703. * Initialize the "v_info" array, by parsing an ascii "template" file
  704. */
  705. errr parse_v_info(char *buf, header *head)
  706. {
  707. int i;
  708. char *s;
  709. /* Current entry */
  710. static vault_type *v_ptr = NULL;
  711. /* Process 'N' for "New/Number/Name" */
  712. if (buf[0] == 'N')
  713. {
  714. /* Find the colon before the name */
  715. s = strchr(buf+2, ':');
  716. /* Verify that colon */
  717. if (!s) return (PARSE_ERROR_MISSING_COLON);
  718. /* Nuke the colon, advance to the name */
  719. *s++ = '\0';
  720. /* Paranoia -- require a name */
  721. if (!*s) return (PARSE_ERROR_GENERIC);
  722. /* Get the index */
  723. i = atoi(buf+2);
  724. /* Verify information */
  725. if (i <= error_idx) return (PARSE_ERROR_NON_SEQUENTIAL_RECORDS);
  726. /* Verify information */
  727. if (i >= head->info_num) return (PARSE_ERROR_TOO_MANY_ENTRIES);
  728. /* Save the index */
  729. error_idx = i;
  730. /* Point at the "info" */
  731. v_ptr = (vault_type*)head->info_ptr + i;
  732. /* Store the name */
  733. if ((v_ptr->name = add_name(head, s)) == 0)
  734. return (PARSE_ERROR_OUT_OF_MEMORY);
  735. }
  736. /* Process 'D' for "Description" */
  737. else if (buf[0] == 'D')
  738. {
  739. /* There better be a current v_ptr */
  740. if (!v_ptr) return (PARSE_ERROR_MISSING_RECORD_HEADER);
  741. /* Get the text */
  742. s = buf+2;
  743. /* Store the text */
  744. if (!add_text(&v_ptr->text, head, s))
  745. return (PARSE_ERROR_OUT_OF_MEMORY);
  746. }
  747. /* Process 'X' for "Extra info" (one line only) */
  748. else if (buf[0] == 'X')
  749. {
  750. int typ, rat, hgt, wid;
  751. /* There better be a current v_ptr */
  752. if (!v_ptr) return (PARSE_ERROR_MISSING_RECORD_HEADER);
  753. /* Scan for the values */
  754. if (4 != sscanf(buf+2, "%d:%d:%d:%d",
  755. &typ, &rat, &hgt, &wid)) return (PARSE_ERROR_GENERIC);
  756. /* Save the values */
  757. v_ptr->typ = typ;
  758. v_ptr->rat = rat;
  759. v_ptr->hgt = hgt;
  760. v_ptr->wid = wid;
  761. /* Check for maximum vault sizes */
  762. if ((v_ptr->typ == 6) && ((v_ptr->wid > 33) || (v_ptr->hgt > 22)))
  763. return (PARSE_ERROR_VAULT_TOO_BIG);
  764. if ((v_ptr->typ == 7) && ((v_ptr->wid > 66) || (v_ptr->hgt > 44)))
  765. return (PARSE_ERROR_VAULT_TOO_BIG);
  766. }
  767. else
  768. {
  769. /* Oops */
  770. return (PARSE_ERROR_UNDEFINED_DIRECTIVE);
  771. }
  772. /* Success */
  773. return (0);
  774. }
  775. /*
  776. * Initialize the "f_info" array, by parsing an ascii "template" file
  777. */
  778. errr parse_f_info(char *buf, header *head)
  779. {
  780. int i;
  781. char *s;
  782. char *t;
  783. /* Current entry */
  784. static feature_type *f_ptr = NULL;
  785. /* Process 'N' for "New/Number/Name" */
  786. if (buf[0] == 'N')
  787. {
  788. /* Find the colon before the name */
  789. s = strchr(buf+2, ':');
  790. /* Verify that colon */
  791. if (!s) return (PARSE_ERROR_MISSING_COLON);
  792. /* Nuke the colon, advance to the name */
  793. *s++ = '\0';
  794. /* Paranoia -- require a name */
  795. if (!*s) return (PARSE_ERROR_GENERIC);
  796. /* Get the index */
  797. i = atoi(buf+2);
  798. /* Verify information */
  799. if (i <= error_idx) return (PARSE_ERROR_NON_SEQUENTIAL_RECORDS);
  800. /* Verify information */
  801. if (i >= head->info_num) return (PARSE_ERROR_TOO_MANY_ENTRIES);
  802. /* Save the index */
  803. error_idx = i;
  804. /* Point at the "info" */
  805. f_ptr = (feature_type*)head->info_ptr + i;
  806. /* Store the name */
  807. if ((f_ptr->name = add_name(head, s)) == 0)
  808. return (PARSE_ERROR_OUT_OF_MEMORY);
  809. /* Default "mimic" */
  810. f_ptr->mimic = i;
  811. }
  812. /* Process 'M' for "Mimic" (one line only) */
  813. else if (buf[0] == 'M')
  814. {
  815. int mimic;
  816. /* There better be a current f_ptr */
  817. if (!f_ptr) return (PARSE_ERROR_MISSING_RECORD_HEADER);
  818. /* Scan for the values */
  819. if (1 != sscanf(buf+2, "%d", &mimic))
  820. return (PARSE_ERROR_NOT_NUMBER);
  821. /* Save the values */
  822. f_ptr->mimic = mimic;
  823. }
  824. /* Process 'P' for "Priority" */
  825. else if (buf[0] == 'P')
  826. {
  827. int priority;
  828. /* There better be a current f_ptr */
  829. if (!f_ptr) return (PARSE_ERROR_MISSING_RECORD_HEADER);
  830. /* Scan for the values */
  831. if (1 != sscanf(buf+2, "%d", &priority))
  832. return (PARSE_ERROR_NOT_NUMBER);
  833. /* Save the values */
  834. f_ptr->priority = priority;
  835. }
  836. /* Process 'G' for "Graphics" (one line only) */
  837. else if (buf[0] == 'G')
  838. {
  839. char d_char;
  840. int d_attr;
  841. /* There better be a current f_ptr */
  842. if (!f_ptr) return (PARSE_ERROR_MISSING_RECORD_HEADER);
  843. /* Paranoia */
  844. if (!buf[2]) return (PARSE_ERROR_GENERIC);
  845. if (!buf[3]) return (PARSE_ERROR_GENERIC);
  846. if (!buf[4]) return (PARSE_ERROR_GENERIC);
  847. /* Extract d_char */
  848. d_char = buf[2];
  849. /* If we have a longer string than expected ... */
  850. if (buf[5])
  851. {
  852. /* Advance "buf" on by 4 */
  853. buf += 4;
  854. /* Extract the colour */
  855. d_attr = color_text_to_attr(buf);
  856. }
  857. else
  858. {
  859. /* Extract the attr */
  860. d_attr = color_char_to_attr(buf[4]);
  861. }
  862. /* Paranoia */
  863. if (d_attr < 0) return (PARSE_ERROR_GENERIC);
  864. /* Save the values */
  865. f_ptr->d_attr = d_attr;
  866. f_ptr->d_char = d_char;
  867. }
  868. /* Process 'F' for flags */
  869. else if (buf[0] == 'F')
  870. {
  871. /* Parse every entry textually */
  872. for (s = buf + 2; *s; )
  873. {
  874. /* Find the end of this entry */
  875. for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
  876. /* Nuke and skip any dividers */
  877. if (*t)
  878. {
  879. *t++ = '\0';
  880. while ((*t == ' ') || (*t == '|')) t++;
  881. }
  882. /* Parse this entry */
  883. if (0 != grab_one_flag(&f_ptr->flags, f_info_flags, s))
  884. return (PARSE_ERROR_INVALID_FLAG);
  885. /* Start the next entry */
  886. s = t;
  887. }
  888. }
  889. /* Process 'E' for effect */
  890. else if (buf[0] == 'E')
  891. {
  892. f_ptr->effect = grab_one_effect(buf + 2);
  893. if (!f_ptr->effect)
  894. return PARSE_ERROR_GENERIC;
  895. }
  896. /* Process 'X' for extra */
  897. else if (buf[0] == 'X')
  898. {
  899. int locked, jammed, shopnum, dig;
  900. if (4 != sscanf(buf + 2, "%d:%d:%d:%d",
  901. &locked, &jammed, &shopnum, &dig))
  902. return PARSE_ERROR_NOT_NUMBER;
  903. f_ptr->locked = locked;
  904. f_ptr->jammed = jammed;
  905. f_ptr->shopnum = shopnum;
  906. f_ptr->dig = dig;
  907. }
  908. else
  909. {
  910. /* Oops */
  911. return (PARSE_ERROR_UNDEFINED_DIRECTIVE);
  912. }
  913. /* Success */
  914. return (0);
  915. }
  916. /*
  917. * Find a flag's index from a textual string.
  918. */
  919. static int lookup_flag(const char **flag_table, const char *flag_name)
  920. {
  921. int i = FLAG_START;
  922. while (flag_table[i] && !streq(flag_table[i], flag_name))
  923. i++;
  924. /* End of table reached without match */
  925. if (!flag_table[i]) i = FLAG_END;
  926. return i;
  927. }
  928. /*
  929. * Grab one flag from a string, and set that flag in a bit field
  930. */
  931. static errr grab_flag(bitflag *flags, const size_t size, const char **flag_table, const char *flag_name)
  932. {
  933. int flag = lookup_flag(flag_table, flag_name);
  934. if (flag == FLAG_END) return PARSE_ERROR_INVALID_FLAG;
  935. flag_on(flags, size, flag);
  936. return 0;
  937. }
  938. /*
  939. * Initialize the "k_info" array, by parsing an ascii "template" file
  940. */
  941. errr parse_k_info(char *buf, header *head)
  942. {
  943. int i;
  944. char *s = NULL, *t;
  945. /* Current entry */
  946. static object_kind *k_ptr = NULL;
  947. /* Process 'N' for "New/Number/Name" */
  948. if (buf[0] == 'N')
  949. {
  950. /* Find the colon before the name */
  951. s = strchr(buf+2, ':');
  952. /* Verify that colon */
  953. if (!s) return (PARSE_ERROR_MISSING_COLON);
  954. /* Nuke the colon, advance to the name */
  955. *s++ = '\0';
  956. /* Paranoia -- require a name */
  957. if (!*s) return (PARSE_ERROR_GENERIC);
  958. /* Get the index */
  959. i = atoi(buf+2);
  960. /* Verify information */
  961. if (i <= error_idx) return (PARSE_ERROR_NON_SEQUENTIAL_RECORDS);
  962. /* Verify information */
  963. if (i >= head->info_num) return (PARSE_ERROR_TOO_MANY_ENTRIES);
  964. /* Save the index */
  965. error_idx = i;
  966. /* Point at the "info" */
  967. k_ptr = (object_kind*)head->info_ptr + i;
  968. /* Store the name */
  969. if ((k_ptr->name = add_name(head, s)) == 0)
  970. return (PARSE_ERROR_OUT_OF_MEMORY);
  971. /* Success (return early) */
  972. return (0);
  973. }
  974. /* There better be a current k_ptr */
  975. if (!k_ptr) return (PARSE_ERROR_MISSING_RECORD_HEADER);
  976. /* Process 'G' for "Graphics" (one line only) */
  977. if (buf[0] == 'G')
  978. {
  979. char d_char;
  980. int d_attr;
  981. /* Paranoia */
  982. if (!buf[2]) return (PARSE_ERROR_GENERIC);
  983. if (!buf[3]) return (PARSE_ERROR_GENERIC);
  984. if (!buf[4]) return (PARSE_ERROR_GENERIC);
  985. /* Extract d_char */
  986. d_char = buf[2];
  987. /* If we have a longer string than expected ... */
  988. if (buf[5])
  989. {
  990. /* Advance "buf" on by 4 */
  991. buf += 4;
  992. /* Extract the colour */
  993. d_attr = color_text_to_attr(buf);
  994. }
  995. else
  996. {
  997. /* Extract the attr */
  998. d_attr = color_char_to_attr(buf[4]);
  999. }
  1000. /* Paranoia */
  1001. if (d_attr < 0) return (PARSE_ERROR_GENERIC);
  1002. /* Save the values */
  1003. k_ptr->d_attr = d_attr;
  1004. k_ptr->d_char = d_char;
  1005. }
  1006. /* Process 'I' for "Info" (one line only) */
  1007. else if (buf[0] == 'I')
  1008. {
  1009. int tval, sval;
  1010. char pval[50];
  1011. /* Scan for the values */
  1012. if (3 != sscanf(buf+2, "%d:%d:%s",
  1013. &tval, &sval, pval)) return (PARSE_ERROR_GENERIC);
  1014. /* Save the values */
  1015. k_ptr->tval = tval;
  1016. k_ptr->sval = sval;
  1017. if (!parse_random_value(pval, &k_ptr->pval)) return PARSE_ERROR_INVALID_VALUE;
  1018. }
  1019. /* Process 'W' for "More Info" (one line only) */
  1020. else if (buf[0] == 'W')
  1021. {
  1022. int level, extra, wgt;
  1023. long cost;
  1024. /* Scan for the values */
  1025. if (4 != sscanf(buf+2, "%d:%d:%d:%ld",
  1026. &level, &extra, &wgt, &cost)) return (PARSE_ERROR_GENERIC);
  1027. /* Save the values */
  1028. k_ptr->level = level;
  1029. k_ptr->weight = wgt;
  1030. k_ptr->cost = cost;
  1031. }
  1032. /* Process 'A' for "Allocation" (one line only) */
  1033. else if (buf[0] == 'A')
  1034. {
  1035. int common, min, max;
  1036. /* Format is "A:<common>:<min> to <max>" */
  1037. if (3 != sscanf(buf+2, "%d:%d to %d", &common, &min, &max))
  1038. return (PARSE_ERROR_GENERIC);
  1039. /* Limit to size a byte */
  1040. if (common < 0 || common > 255) return (PARSE_ERROR_GENERIC);
  1041. if (min < 0 || min > 255) return (PARSE_ERROR_GENERIC);
  1042. if (max < 0 || max > 255) return (PARSE_ERROR_GENERIC);
  1043. /* Set up data */
  1044. k_ptr->alloc_prob = common;
  1045. k_ptr->alloc_min = min;
  1046. k_ptr->alloc_max = max;
  1047. }
  1048. /* Hack -- Process 'P' for "power" and such */
  1049. else if (buf[0] == 'P')
  1050. {
  1051. int ac, hd1, hd2;
  1052. char *th, *td, *ta;
  1053. char fields[150];
  1054. /* Scan for the values "P:0:0d0:0:0:0" */
  1055. if (4 != sscanf(buf+2, "%d:%dd%d:%s",
  1056. &ac, &hd1, &hd2, fields)) return (PARSE_ERROR_GENERIC);
  1057. /* Tokenize the last three fields */
  1058. if(!(th = strtok(fields, ":"))) return PARSE_ERROR_GENERIC;
  1059. if(!(td = strtok(NULL, ":"))) return PARSE_ERROR_GENERIC;
  1060. if(!(ta = strtok(NULL, ":"))) return PARSE_ERROR_GENERIC;
  1061. k_ptr->ac = ac;
  1062. k_ptr->dd = hd1;
  1063. k_ptr->ds = hd2;
  1064. if (!parse_random_value(th, &k_ptr->to_h)) return PARSE_ERROR_INVALID_VALUE;
  1065. if (!parse_random_value(td, &k_ptr->to_d)) return PARSE_ERROR_INVALID_VALUE;
  1066. if (!parse_random_value(ta, &k_ptr->to_a)) return PARSE_ERROR_INVALID_VALUE;
  1067. }
  1068. /* Hack -- Process 'C' for "charges" */
  1069. else if (buf[0] == 'C')
  1070. {
  1071. if(!parse_random_value(buf+2, &k_ptr->charge)) return PARSE_ERROR_INVALID_VALUE;
  1072. }
  1073. /* Process 'M' for "Multiple quantity" (one line only) */
  1074. else if (buf[0] == 'M')
  1075. {
  1076. int prob;
  1077. char stack[50];
  1078. /* Scan for the values */
  1079. if (2 != sscanf(buf+2, "%d:%s", &prob, stack))
  1080. return (PARSE_ERROR_GENERIC);
  1081. /* Save the values */
  1082. k_ptr->gen_mult_prob = prob;
  1083. if (!parse_random_value(stack, &k_ptr->stack_size)) return PARSE_ERROR_INVALID_VALUE;
  1084. }
  1085. /* Hack -- Process 'F' for flags */
  1086. else if (buf[0] == 'F')
  1087. {
  1088. /* Parse every entry textually */
  1089. for (s = buf + 2; *s; )
  1090. {
  1091. /* Find the end of this entry */
  1092. for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
  1093. /* Nuke and skip any dividers */
  1094. if (*t)
  1095. {
  1096. *t++ = '\0';
  1097. while (*t == ' ' || *t == '|') t++;
  1098. }
  1099. /* Parse this entry */
  1100. if (0 != grab_flag(k_ptr->flags, OF_SIZE, k_info_flags, s))
  1101. return (PARSE_ERROR_INVALID_FLAG);
  1102. /* Start the next entry */
  1103. s = t;
  1104. }
  1105. }
  1106. /* Process 'E' for effect */
  1107. else if (buf[0] == 'E')
  1108. {
  1109. /* Find the colon after the name, nuke it and advance */
  1110. s = strchr(buf + 2, ':');
  1111. if (s) *s++ = '\0';
  1112. /* Get the activation */
  1113. k_ptr->effect = grab_one_effect(buf + 2);
  1114. if (!k_ptr->effect) return (PARSE_ERROR_GENERIC);
  1115. /* Get the timeout, if supplied */
  1116. if (s && !parse_random_value(s, &k_ptr->time))
  1117. return (PARSE_ERROR_INVALID_VALUE);
  1118. }
  1119. /* Process 'D' for "Description" */
  1120. else if (buf[0] == 'D')
  1121. {
  1122. /* Store the text */
  1123. if (!add_text(&(k_ptr->text), head, buf + 2))
  1124. return (PARSE_ERROR_OUT_OF_MEMORY);
  1125. }
  1126. else
  1127. {
  1128. /* Oops */
  1129. return (PARSE_ERROR_UNDEFINED_DIRECTIVE);
  1130. }
  1131. /* Success */
  1132. return (0);
  1133. }
  1134. /*
  1135. * Initialize the "a_info" array, by parsing an ascii "template" file
  1136. */
  1137. errr parse_a_info(char *buf, header *head)
  1138. {
  1139. int i;
  1140. char *s, *t;
  1141. /* Current entry */
  1142. static artifact_type *a_ptr = NULL;
  1143. /* Process 'N' for "New/Number/Name" */
  1144. if (buf[0] == 'N')
  1145. {
  1146. /* Find the colon before the name */
  1147. s = strchr(buf+2, ':');
  1148. /* Verify that colon */
  1149. if (!s) return (PARSE_ERROR_MISSING_COLON);
  1150. /* Nuke the colon, advance to the name */
  1151. *s++ = '\0';
  1152. /* Paranoia -- require a name */
  1153. if (!*s) return (PARSE_ERROR_GENERIC);
  1154. /* Get the index */
  1155. i = atoi(buf+2);
  1156. /* Verify information */
  1157. if (i <= error_idx) return (PARSE_ERROR_NON_SEQUENTIAL_RECORDS);
  1158. /* Verify information */
  1159. if (i >= head->info_num) return (PARSE_ERROR_TOO_MANY_ENTRIES);
  1160. /* Save the index */
  1161. error_idx = i;
  1162. /* Point at the "info" */
  1163. a_ptr = (artifact_type*)head->info_ptr + i;
  1164. /* Store the name */
  1165. if ((a_ptr->name = add_name(head, s)) == 0)
  1166. return (PARSE_ERROR_OUT_OF_MEMORY);
  1167. /* Ignore everything */
  1168. flags_set(a_ptr->flags, OF_SIZE, OF_IGNORE_MASK, FLAG_END);
  1169. /* Return early */
  1170. return (0);
  1171. }
  1172. /* There better be a current a_ptr */
  1173. if (!a_ptr) return (PARSE_ERROR_MISSING_RECORD_HEADER);
  1174. /* Process 'I' for "Info" (one line only) */
  1175. else if (buf[0] == 'I')
  1176. {
  1177. char *tval_s, *sval_s, *pval_s;
  1178. int tval, sval, pval;
  1179. /* Find the beginning of the tval field */
  1180. tval_s = strchr(buf, ':');
  1181. if (!tval_s) return PARSE_ERROR_MISSING_COLON;
  1182. *tval_s++ = '\0';
  1183. if (!*tval_s) return PARSE_ERROR_MISSING_FIELD;
  1184. /* Now find the beginning of the sval field */
  1185. sval_s = strchr(tval_s, ':');
  1186. if (!sval_s) return PARSE_ERROR_MISSING_COLON;
  1187. *sval_s++ = '\0';
  1188. if (!*sval_s) return PARSE_ERROR_MISSING_FIELD;
  1189. /* Now find the beginning of the pval field */
  1190. pval_s = strchr(sval_s, ':');
  1191. if (!pval_s) return PARSE_ERROR_MISSING_COLON;
  1192. *pval_s++ = '\0';
  1193. if (!*pval_s) return PARSE_ERROR_MISSING_FIELD;
  1194. /* Now convert the tval into its numeric equivalent */
  1195. if (1 != sscanf(tval_s, "%d", &tval))
  1196. {
  1197. tval = tval_find_idx(tval_s);
  1198. if (tval == -1) return PARSE_ERROR_UNRECOGNISED_TVAL;
  1199. }
  1200. /* Now find the sval */
  1201. if (1 != sscanf(sval_s, "%d", &sval))
  1202. {
  1203. sval = lookup_sval(tval, sval_s);
  1204. if (sval == -1) return PARSE_ERROR_UNRECOGNISED_SVAL;
  1205. }
  1206. /* Now extract the pval */
  1207. if (1 != sscanf(pval_s, "%d", &pval))
  1208. return PARSE_ERROR_NOT_NUMBER;
  1209. /* Save the values */
  1210. a_ptr->tval = tval;
  1211. a_ptr->sval = sval;
  1212. a_ptr->pval = pval;
  1213. }
  1214. /* Process 'W' for "More Info" (one line only) */
  1215. else if (buf[0] == 'W')
  1216. {
  1217. int level, rarity, wgt;
  1218. long cost;
  1219. /* Scan for the values */
  1220. if (4 != sscanf(buf+2, "%d:%d:%d:%ld",
  1221. &level, &rarity, &wgt, &cost)) return (PARSE_ERROR_GENERIC);
  1222. /* Save the values */
  1223. a_ptr->level = level;
  1224. a_ptr->rarity = rarity;
  1225. a_ptr->weight = wgt;
  1226. a_ptr->cost = cost;
  1227. }
  1228. /* Process 'A' for "Allocation" (one line only) */
  1229. else if (buf[0] == 'A')
  1230. {
  1231. int common, min, max;
  1232. /* Format is "A:<common>:<min> to <max>" */
  1233. if (3 != sscanf(buf+2, "%d:%d to %d", &common, &min, &max))
  1234. return (PARSE_ERROR_GENERIC);
  1235. /* Limit to size a byte */
  1236. if (common < 0 || common > 255) return (PARSE_ERROR_GENERIC);
  1237. if (min < 0 || min > 255) return (PARSE_ERROR_GENERIC);
  1238. if (max < 0 || max > 255) return (PARSE_ERROR_GENERIC);
  1239. /* Set up data */
  1240. a_ptr->alloc_prob = common;
  1241. a_ptr->alloc_min = min;
  1242. a_ptr->alloc_max = max;
  1243. }
  1244. /* Process 'P' for "power" and such */
  1245. else if (buf[0] == 'P')
  1246. {
  1247. int ac, hd1, hd2, th, td, ta;
  1248. /* Scan for the values */
  1249. if (6 != sscanf(buf+2, "%d:%dd%d:%d:%d:%d",
  1250. &ac, &hd1, &hd2, &th, &td, &ta)) return (PARSE_ERROR_GENERIC);
  1251. a_ptr->ac = ac;
  1252. a_ptr->dd = hd1;
  1253. a_ptr->ds = hd2;
  1254. a_ptr->to_h = th;
  1255. a_ptr->to_d = td;
  1256. a_ptr->to_a = ta;
  1257. }
  1258. /* Process 'F' for flags */
  1259. else if (buf[0] == 'F')
  1260. {
  1261. /* Parse every entry textually */
  1262. for (s = buf + 2; *s; )
  1263. {
  1264. /* Find the end of this entry */
  1265. for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
  1266. /* Nuke and skip any dividers */
  1267. if (*t)
  1268. {
  1269. *t++ = '\0';
  1270. while ((*t == ' ') || (*t == '|')) t++;
  1271. }
  1272. /* Parse this entry */
  1273. if (0 != grab_flag(a_ptr->flags, OF_SIZE, k_info_flags, s))
  1274. return (PARSE_ERROR_INVALID_FLAG);
  1275. /* Start the next entry */
  1276. s = t;
  1277. }
  1278. }
  1279. /* Process 'E' for Effect (Activation) & time */
  1280. else if (buf[0] == 'E')
  1281. {
  1282. /* Find the colon after the name */
  1283. s = strchr(buf + 2, ':');
  1284. if (!s) return (PARSE_ERROR_MISSING_COLON);
  1285. /* Nuke the colon, advance to the name */
  1286. *s++ = '\0';
  1287. if (!*s) return (PARSE_ERROR_GENERIC);
  1288. /* Get the activation */
  1289. a_ptr->effect = grab_one_effect(buf + 2);
  1290. if (!a_ptr->effect) return (PARSE_ERROR_GENERIC);
  1291. /* Scan for the values */
  1292. if (!parse_random_value(s, &a_ptr->time))
  1293. return (PARSE_ERROR_INVALID_VALUE);
  1294. }
  1295. /* Process 'M' for "Effect message" */
  1296. else if (buf[0] == 'M')
  1297. {
  1298. /* Store the text */
  1299. if (!add_text(&a_ptr->effect_msg, head, buf+2))
  1300. return (PARSE_ERROR_OUT_OF_MEMORY);
  1301. }
  1302. /* Process 'D' for "Description" */
  1303. else if (buf[0] == 'D')
  1304. {
  1305. /* Store the text */
  1306. if (!add_text(&a_ptr->text, head, buf+2))
  1307. return (PARSE_ERROR_OUT_OF_MEMORY);
  1308. }
  1309. else
  1310. {
  1311. /* Oops */
  1312. return (PARSE_ERROR_UNDEFINED_DIRECTIVE);
  1313. }
  1314. /* Success */
  1315. return (0);
  1316. }
  1317. /*
  1318. * Initialize the "e_info" array, by parsing an ascii "template" file
  1319. */
  1320. errr parse_e_info(char *buf, header *head)
  1321. {
  1322. int i;
  1323. char *s, *t;
  1324. /* Current entry */
  1325. static ego_item_type *e_ptr = NULL;
  1326. static int cur_t = 0;
  1327. /* Process 'N' for "New/Number/Name" */
  1328. if (buf[0] == 'N')
  1329. {
  1330. /* Find the colon before the name */
  1331. s = strchr(buf+2, ':');
  1332. /* Verify that colon */
  1333. if (!s) return (PARSE_ERROR_MISSING_COLON);
  1334. /* Nuke the colon, advance to the name */
  1335. *s++ = '\0';
  1336. /* Paranoia -- require a name */
  1337. if (!*s) return (PARSE_ERROR_GENERIC);
  1338. /* Get the index */
  1339. i = atoi(buf+2);
  1340. /* Verify information */
  1341. if (i <= error_idx) return (PARSE_ERROR_NON_SEQUENTIAL_RECORDS);
  1342. /* Verify information */
  1343. if (i >= head->info_num) return (PARSE_ERROR_TOO_MANY_ENTRIES);
  1344. /* Save the index */
  1345. error_idx = i;
  1346. /* Point at the "info" */
  1347. e_ptr = (ego_item_type*)head->info_ptr + i;
  1348. /* Store the name */
  1349. if ((e_ptr->name = add_name(head, s)) == 0)
  1350. return (PARSE_ERROR_OUT_OF_MEMORY);
  1351. /* Start with the first of the tval indices */
  1352. cur_t = 0;
  1353. }
  1354. /* Process 'W' for "More Info" (one line only) */
  1355. else if (buf[0] == 'W')
  1356. {
  1357. int level, rarity, pad2;
  1358. long cost;
  1359. /* There better be a current e_ptr */
  1360. if (!e_ptr) return (PARSE_ERROR_MISSING_RECORD_HEADER);
  1361. /* Scan for the values */
  1362. if (4 != sscanf(buf+2, "%d:%d:%d:%ld",
  1363. &level, &rarity, &pad2, &cost)) return (PARSE_ERROR_GENERIC);
  1364. /* Save the values */
  1365. e_ptr->level = level;
  1366. e_ptr->rarity = rarity;
  1367. /* e_ptr->weight = wgt; */
  1368. e_ptr->cost = cost;
  1369. }
  1370. /* Process 'X' for "Xtra" (one line only) */
  1371. else if (buf[0] == 'X')
  1372. {
  1373. int rating, xtra;
  1374. /* There better be a current e_ptr */
  1375. if (!e_ptr) return (PARSE_ERROR_MISSING_RECORD_HEADER);
  1376. /* Scan for the values */
  1377. if (2 != sscanf(buf+2, "%d:%d", &rating, &xtra))
  1378. return (PARSE_ERROR_GENERIC);
  1379. /* Save the values */
  1380. e_ptr->rating = rating;
  1381. e_ptr->xtra = xtra;
  1382. }
  1383. /* Process 'T' for "Types allowed" (up to three lines) */
  1384. else if (buf[0] == 'T')
  1385. {
  1386. int tval, sval1, sval2;
  1387. /* There better be a current e_ptr */
  1388. if (!e_ptr) return (PARSE_ERROR_MISSING_RECORD_HEADER);
  1389. /* Scan for the values */
  1390. if (3 != sscanf(buf+2, "%d:%d:%d",
  1391. &tval, &sval1, &sval2)) return (PARSE_ERROR_GENERIC);
  1392. /* Save the values */
  1393. e_ptr->tval[cur_t] = (byte)tval;
  1394. e_ptr->min_sval[cur_t] = (byte)sval1;
  1395. e_ptr->max_sval[cur_t] = (byte)sval2;
  1396. /* Increase counter for 'possible tval' index */
  1397. cur_t++;
  1398. /* Allow only a limited number of T: lines */
  1399. if (cur_t > EGO_TVALS_MAX) return (PARSE_ERROR_GENERIC);
  1400. }
  1401. /* Hack -- Process 'C' for "creation" */
  1402. else if (buf[0] == 'C')
  1403. {
  1404. char *th, *td, *ta, *pv;
  1405. char fields[200];
  1406. /* There better be a current e_ptr */
  1407. if (!e_ptr) return (PARSE_ERROR_MISSING_RECORD_HEADER);
  1408. /* Scan for the values */
  1409. if (1 != sscanf(buf+2, "%s", fields)) return (PARSE_ERROR_GENERIC);
  1410. if(!(th = strtok(fields, ":"))) return PARSE_ERROR_GENERIC;
  1411. if(!(td = strtok(NULL, ":"))) return PARSE_ERROR_GENERIC;
  1412. if(!(ta = strtok(NULL, ":"))) return PARSE_ERROR_GENERIC;
  1413. if(!(pv = strtok(NULL, ":"))) return PARSE_ERROR_GENERIC;
  1414. if(!parse_random_value(th, &e_ptr->to_h)) return PARSE_ERROR_INVALID_VALUE;
  1415. if(!parse_random_value(td, &e_ptr->to_d)) return PARSE_ERROR_INVALID_VALUE;
  1416. if(!parse_random_value(ta, &e_ptr->to_a)) return PARSE_ERROR_INVALID_VALUE;
  1417. if(!parse_random_value(pv, &e_ptr->pval)) return PARSE_ERROR_INVALID_VALUE;
  1418. }
  1419. /* Process 'M' for "minimum values" */
  1420. else if (buf[0] == 'M')
  1421. {
  1422. int th, td, ta, pv;
  1423. /* There better be a current e_ptr */
  1424. if (!e_ptr) return (PARSE_ERROR_MISSING_RECORD_HEADER);
  1425. /* Scan for the values */
  1426. if (4 != sscanf(buf+2, "%d:%d:%d:%d",
  1427. &th, &td, &ta, &pv)) return (PARSE_ERROR_GENERIC);
  1428. e_ptr->min_to_h = th;
  1429. e_ptr->min_to_d = td;
  1430. e_ptr->min_to_a = ta;
  1431. e_ptr->min_pval = pv;
  1432. }
  1433. /* Hack -- Process 'F' for flags */
  1434. else if (buf[0] == 'F')
  1435. {
  1436. /* There better be a current e_ptr */
  1437. if (!e_ptr) return (PARSE_ERROR_MISSING_RECORD_HEADER);
  1438. /* Parse every entry textually */
  1439. for (s = buf + 2; *s; )
  1440. {
  1441. /* Find the end of this entry */
  1442. for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
  1443. /* Nuke and skip any dividers */
  1444. if (*t)
  1445. {
  1446. *t++ = '\0';
  1447. while ((*t == ' ') || (*t == '|')) t++;
  1448. }
  1449. /* Parse this entry */
  1450. if (0 != grab_flag(e_ptr->flags, OF_SIZE, k_info_flags, s))
  1451. return (PARSE_ERROR_INVALID_FLAG);
  1452. /* Start the next entry */
  1453. s = t;
  1454. }
  1455. }
  1456. /* Process 'D' for "Description" */
  1457. else if (buf[0] == 'D')
  1458. {
  1459. /* There better be a current e_ptr */
  1460. if (!e_ptr) return (PARSE_ERROR_MISSING_RECORD_HEADER);
  1461. /* Get the text */
  1462. s = buf+2;
  1463. /* Store the text */
  1464. if (!add_text(&e_ptr->text, head, s))
  1465. return (PARSE_ERROR_OUT_OF_MEMORY);
  1466. }
  1467. else
  1468. {
  1469. /* Oops */
  1470. return (PARSE_ERROR_UNDEFINED_DIRECTIVE);
  1471. }
  1472. /* Success */
  1473. return (0);
  1474. }
  1475. /*
  1476. * Initialize the "r_info" array, by parsing an ascii "template" file
  1477. */
  1478. errr parse_r_info(char *buf, header *head)
  1479. {
  1480. int i;
  1481. char *s, *t;
  1482. /* Current entry */
  1483. static monster_race *r_ptr = NULL;
  1484. /* Process 'N' for "New/Number/Name" */
  1485. if (buf[0] == 'N')
  1486. {
  1487. /* Find the colon before the name */
  1488. s = strchr(buf+2, ':');
  1489. /* Verify that colon */
  1490. if (!s) return (PARSE_ERROR_MISSING_COLON);
  1491. /* Nuke the colon, advance to the name */
  1492. *s++ = '\0';
  1493. /* Paranoia -- require a name */
  1494. if (!*s) return (PARSE_ERROR_GENERIC);
  1495. /* Get the index */
  1496. i = atoi(buf+2);
  1497. /* Verify information */
  1498. if (i <= error_idx) return (PARSE_ERROR_NON_SEQUENTIAL_RECORDS);
  1499. /* Verify information */
  1500. if (i >= head->info_num) return (PARSE_ERROR_TOO_MANY_ENTRIES);
  1501. /* Save the index */
  1502. error_idx = i;
  1503. /* Point at the "info" */
  1504. r_ptr = (monster_race*)head->info_ptr + i;
  1505. /* Store the name */
  1506. if ((r_ptr->name = add_name(head, s)) == 0)
  1507. return (PARSE_ERROR_OUT_OF_MEMORY);
  1508. return 0;
  1509. }
  1510. /* There better be a current r_ptr */
  1511. if (!r_ptr) return (PARSE_ERROR_MISSING_RECORD_HEADER);
  1512. /* Process 'D' for "Description" */
  1513. if (buf[0] == 'D')
  1514. {
  1515. /* Store the text */
  1516. if (!add_text(&(r_ptr->text), head, buf+2))
  1517. return (PARSE_ERROR_OUT_OF_MEMORY);
  1518. }
  1519. /* Process 'G' for "Graphics" (one line only) */
  1520. else if (buf[0] == 'G')
  1521. {
  1522. char d_char;
  1523. int d_attr;
  1524. /* Paranoia */
  1525. if (!buf[2]) return (PARSE_ERROR_GENERIC);
  1526. if (!buf[3]) return (PARSE_ERROR_GENERIC);
  1527. if (!buf[4]) return (PARSE_ERROR_GENERIC);
  1528. /* Extract d_char */
  1529. d_char = buf[2];
  1530. /* If we have a longer string than expected ... */
  1531. if (buf[5])
  1532. {
  1533. /* Advance "buf" on by 4 */
  1534. buf += 4;
  1535. /* Extract the colour */
  1536. d_attr = color_text_to_attr(buf);
  1537. }
  1538. else
  1539. {
  1540. /* Extract the attr */
  1541. d_attr = color_char_to_attr(buf[4]);
  1542. }
  1543. /* Paranoia */
  1544. if (d_attr < 0) return (PARSE_ERROR_GENERIC);
  1545. /* Save the values */
  1546. r_ptr->d_attr = d_attr;
  1547. r_ptr->d_char = d_char;
  1548. }
  1549. /* Process 'I' for "Info" (one line only) */
  1550. else if (buf[0] == 'I')
  1551. {
  1552. int spd, lif, aaf, ac, slp;
  1553. /* Scan for the other values */
  1554. if (5 != sscanf(buf+2, "%d:%d:%d:%d:%d",
  1555. &spd, &lif, &aaf, &ac, &slp)) return (PARSE_ERROR_GENERIC);
  1556. /* Save the values */
  1557. r_ptr->speed = spd;
  1558. r_ptr->avg_hp = lif;
  1559. r_ptr->aaf = aaf;
  1560. r_ptr->ac = ac;
  1561. r_ptr->sleep = slp;
  1562. }
  1563. /* Process 'W' for "More Info" (one line only) */
  1564. else if (buf[0] == 'W')
  1565. {
  1566. int lev, rar, pad;
  1567. long exp;
  1568. /* Scan for the values */
  1569. if (4 != sscanf(buf+2, "%d:%d:%d:%ld",
  1570. &lev, &rar, &pad, &exp)) return (PARSE_ERROR_GENERIC);
  1571. /* Save the values */
  1572. r_ptr->level = lev;
  1573. r_ptr->rarity = rar;
  1574. r_ptr->power = pad;
  1575. r_ptr->mexp = exp;
  1576. }
  1577. /* Process 'B' for "Blows" */
  1578. else if (buf[0] == 'B')
  1579. {
  1580. int n1, n2;
  1581. /* Find the next empty blow slot (if any) */
  1582. for (i = 0; i < MONSTER_BLOW_MAX; i++) if (!r_ptr->blow[i].method) break;
  1583. /* Oops, no more slots */
  1584. if (i == MONSTER_BLOW_MAX)
  1585. return (PARSE_ERROR_TOO_MANY_ENTRIES);
  1586. /* Analyze the first field */
  1587. for (s = t = buf+2; *t && (*t != ':'); t++) /* loop */;
  1588. /* Terminate the field (if necessary) */
  1589. if (*t == ':') *t++ = '\0';
  1590. /* Analyze the method */
  1591. for (n1 = 0; r_info_blow_method[n1]; n1++)
  1592. {
  1593. if (streq(s, r_info_blow_method[n1])) break;
  1594. }
  1595. /* Invalid method */
  1596. if (!r_info_blow_method[n1]) return (PARSE_ERROR_UNRECOGNISED_BLOW);
  1597. /* Analyze the second field */
  1598. for (s = t; *t && (*t != ':'); t++) /* loop */;
  1599. /* Terminate the field (if necessary) */
  1600. if (*t == ':') *t++ = '\0';
  1601. /* Analyze effect */
  1602. for (n2 = 0; r_info_blow_effect[n2]; n2++)
  1603. {
  1604. if (streq(s, "")) break;
  1605. if (streq(s, r_info_blow_effect[n2])) break;
  1606. }
  1607. /* Invalid effect */
  1608. if (!r_info_blow_effect[n2]) return (PARSE_ERROR_UNRECOGNISED_BLOW);
  1609. /* Analyze the third field */
  1610. for (s = t; *t && (*t != 'd'); t++) /* loop */;
  1611. /* Terminate the field (if necessary) */
  1612. if (*t == 'd') *t++ = '\0';
  1613. /* Save the method */
  1614. r_ptr->blow[i].method = n1;
  1615. /* Save the effect */
  1616. r_ptr->blow[i].effect = n2;
  1617. /* Extract the damage dice and sides */
  1618. r_ptr->blow[i].d_dice = atoi(s);
  1619. r_ptr->blow[i].d_side = atoi(t);
  1620. }
  1621. /* Process 'F' for "Basic Flags" (multiple lines) */
  1622. else if (buf[0] == 'F')
  1623. {
  1624. /* Parse every entry */
  1625. for (s = buf + 2; *s; )
  1626. {
  1627. /* Find the end of this entry */
  1628. for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
  1629. /* Nuke and skip any dividers */
  1630. if (*t)
  1631. {
  1632. *t++ = '\0';
  1633. while (*t == ' ' || *t == '|') t++;
  1634. }
  1635. /* Parse this entry */
  1636. if (0 != grab_flag(r_ptr->flags, RF_SIZE, r_info_flags, s))
  1637. return (PARSE_ERROR_INVALID_FLAG);
  1638. /* Start the next entry */
  1639. s = t;
  1640. }
  1641. }
  1642. /* Process 'S' for "Spell Flags" (multiple lines) */
  1643. else if (buf[0] == 'S')
  1644. {
  1645. /* Parse every entry */
  1646. for (s = buf + 2; *s; )
  1647. {
  1648. /* Find the end of this entry */
  1649. for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
  1650. /* Nuke and skip any dividers */
  1651. if (*t)
  1652. {
  1653. *t++ = '\0';
  1654. while ((*t == ' ') || (*t == '|')) t++;
  1655. }
  1656. /* XXX Hack -- Read spell frequency */
  1657. if (1 == sscanf(s, "1_IN_%d", &i))
  1658. {
  1659. /* Sanity check */
  1660. if ((i < 1) || (i > 100))
  1661. return (PARSE_ERROR_INVALID_SPELL_FREQ);
  1662. /* Extract a "frequency" */
  1663. r_ptr->freq_spell = r_ptr->freq_innate = 100 / i;
  1664. /* Start at next entry */
  1665. s = t;
  1666. /* Continue */
  1667. continue;
  1668. }
  1669. /* Parse this entry */
  1670. if (0 != grab_flag(r_ptr->spell_flags, RSF_SIZE, r_info_spell_flags, s))
  1671. return (PARSE_ERROR_INVALID_FLAG);
  1672. /* Start the next entry */
  1673. s = t;
  1674. }
  1675. }
  1676. else
  1677. {
  1678. /* Oops */
  1679. return (PARSE_ERROR_UNDEFINED_DIRECTIVE);
  1680. }
  1681. /* Success */
  1682. return (0);
  1683. }
  1684. /*
  1685. * Helper function for reading a list of skills
  1686. */
  1687. static bool parse_skills(s16b *skills_array, const char *buf)
  1688. {
  1689. int dis, dev, sav, stl, srh, fos, thn, thb, throw, dig;
  1690. /* Scan for the values */
  1691. if (SKILL_MAX != sscanf(buf, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
  1692. &dis, &dev, &sav, &stl, &srh,
  1693. &fos, &thn, &thb, &throw, &dig))
  1694. return FALSE;
  1695. /* Save the values */
  1696. skills_array[SKILL_DISARM] = dis;
  1697. skills_array[SKILL_DEVICE] = dev;
  1698. skills_array[SKILL_SAVE] = sav;
  1699. skills_array[SKILL_STEALTH] = stl;
  1700. skills_array[SKILL_SEARCH] = srh;
  1701. skills_array[SKILL_SEARCH_FREQUENCY] = fos;
  1702. skills_array[SKILL_TO_HIT_MELEE] = thn;
  1703. skills_array[SKILL_TO_HIT_BOW] = thb;
  1704. skills_array[SKILL_TO_HIT_THROW] = throw;
  1705. skills_array[SKILL_DIGGING] = dig;
  1706. return TRUE;
  1707. }
  1708. /*
  1709. * Initialize the "p_info" array, by parsing an ascii "template" file
  1710. */
  1711. errr parse_p_info(char *buf, header *head)
  1712. {
  1713. int i, j;
  1714. char *s, *t;
  1715. /* Current entry */
  1716. static player_race *pr_ptr = NULL;
  1717. /* Process 'N' for "New/Number/Name" */
  1718. if (buf[0] == 'N')
  1719. {
  1720. /* Find the colon before the name */
  1721. s = strchr(buf+2, ':');
  1722. /* Verify that colon */
  1723. if (!s) return (PARSE_ERROR_MISSING_COLON);
  1724. /* Nuke the colon, advance to the name */
  1725. *s++ = '\0';
  1726. /* Paranoia -- require a name */
  1727. if (!*s) return (PARSE_ERROR_MISSING_FIELD);
  1728. /* Get the index */
  1729. i = atoi(buf+2);
  1730. /* Verify information */
  1731. if (i <= error_idx) return (PARSE_ERROR_NON_SEQUENTIAL_RECORDS);
  1732. /* Verify information */
  1733. if (i >= head->info_num) return (PARSE_ERROR_TOO_MANY_ENTRIES);
  1734. /* Save the index */
  1735. error_idx = i;
  1736. /* Point at the "info" */
  1737. pr_ptr = (player_race*)h

Large files files are truncated, but you can click here to view the full file