/src/init1.c
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
- /*
- * File: init1.c
- * Purpose: Parsing the lib/edit/ files into data structures.
- *
- * Copyright (c) 1997 Ben Harrison
- *
- * This work is free software; you can redistribute it and/or modify it
- * under the terms of either:
- *
- * a) the GNU General Public License as published by the Free Software
- * Foundation, version 2, or
- *
- * b) the "Angband licence":
- * This software may be copied and distributed for educational, research,
- * and not for profit purposes provided that this copyright and statement
- * are included in all such copies. Other copyrights may also apply.
- */
- #include "angband.h"
- #include "object/tvalsval.h"
-
-
- /*
- * This file is used to initialize various variables and arrays for the
- * Angband game. Note the use of "fd_read()" and "fd_write()" to bypass
- * the common limitation of "read()" and "write()" to only 32767 bytes
- * at a time.
- *
- * Several of the arrays for Angband are built from "template" files in
- * the "lib/file" directory, from which quick-load binary "image" files
- * are constructed whenever they are not present in the "lib/data"
- * directory, or if those files become obsolete, if we are allowed.
- *
- * Warning -- the "ascii" file parsers use a minor hack to collect the
- * name and text information in a single pass. Thus, the game will not
- * be able to load any template file with more than 20K of names or 60K
- * of text, even though technically, up to 64K should be legal.
- *
- * The code could actually be removed and placed into a "stand-alone"
- * program, but that feels a little silly, especially considering some
- * of the platforms that we currently support.
- */
-
- #include "effects.h"
- #include "monster/constants.h"
- #include "init.h"
-
-
- /*** Helper arrays for parsing ascii template files ***/
-
- /* Use a slightly unusual include method to create effect_list[] */
- static const char *effect_list[] =
- {
- #define EFFECT(x, y, r, z) #x,
- #include "list-effects.h"
- #undef EFFECT
- };
-
-
- /*
- * Monster blow methods
- */
- static const char *r_info_blow_method[] =
- {
- #define RBM(a, b) #a,
- #include "list-blow-methods.h"
- #undef RBM
- NULL
- };
-
-
- /*
- * Monster blow effects
- */
- static const char *r_info_blow_effect[] =
- {
- #define RBE(a, b) #a,
- #include "list-blow-effects.h"
- #undef RBE
- NULL
- };
-
-
- /*
- * Monster race flags
- */
-
- static const char *r_info_flags[] =
- {
- #define RF(a, b) #a,
- #include "list-mon-flags.h"
- #undef RF
- NULL
- };
-
-
- /*
- * Monster (race) spell flags
- */
- static const char *r_info_spell_flags[] =
- {
- #define RSF(a, b) #a,
- #include "list-mon-spells.h"
- #undef RSF
- NULL
- };
-
-
- /*
- * Object (kind) flags
- */
-
- static const char *k_info_flags[] =
- {
- #define OF(a, b) #a,
- #include "list-object-flags.h"
- #undef OF
- NULL
- };
-
- /*
- * Player race and class flags
- */
-
- static const char *player_info_flags[] =
- {
- #define PF(a, b) #a,
- #include "list-player-flags.h"
- #undef PF
- NULL
- };
-
- /*
- * Terrain feature flags
- */
- static const char *f_info_flags[] =
- {
- "PWALK",
- "PPASS",
- "MWALK",
- "MPASS",
- "LOOK",
- "DIG",
- "DOOR",
- "EXIT_UP",
- "EXIT_DOWN",
- "PERM",
- "TRAP",
- "SHOP",
- "HIDDEN",
- "BORING",
- NULL
- };
-
-
-
- /*** Initialize from ascii template files ***/
-
-
- /*
- * Initialize an "*_info" array, by parsing an ascii "template" file
- */
- errr init_info_txt(ang_file *fp, char *buf, header *head,
- parse_info_txt_func parse_info_txt_line)
- {
- errr err;
-
- /* Not ready yet */
- bool okay = FALSE;
-
- /* Just before the first record */
- error_idx = -1;
-
- /* Just before the first line */
- error_line = 0;
-
-
- /* Prepare the "fake" stuff */
- head->name_size = 0;
- head->text_size = 0;
-
- /* Parse */
- while (file_getl(fp, buf, 1024))
- {
- /* Advance the line number */
- error_line++;
-
- /* Skip comments and blank lines */
- if (!buf[0] || (buf[0] == '#')) continue;
-
- /* Verify correct "colon" format */
- if (buf[1] != ':') return (PARSE_ERROR_MISSING_COLON);
-
-
- /* Hack -- Process 'V' for "Version" */
- if (buf[0] == 'V')
- {
- int v1, v2, v3;
-
- /* Scan for the values */
- if ((3 != sscanf(buf+2, "%d.%d.%d", &v1, &v2, &v3)) ||
- (v1 != head->v_major) ||
- (v2 != head->v_minor) ||
- (v3 != head->v_patch))
- {
- #if 0
- return (PARSE_ERROR_OBSOLETE_FILE);
- #endif
- }
-
- /* Okay to proceed */
- okay = TRUE;
-
- /* Continue */
- continue;
- }
-
- /* No version yet */
- if (!okay) return (PARSE_ERROR_OBSOLETE_FILE);
-
- /* Parse the line */
- if ((err = (*parse_info_txt_line)(buf, head)) != 0)
- return (err);
- }
-
-
- /* Complete the "name" and "text" sizes */
- if (head->name_size) head->name_size++;
- if (head->text_size) head->text_size++;
-
-
- /* No version yet */
- if (!okay) return (PARSE_ERROR_OBSOLETE_FILE);
-
-
- /* Success */
- return (0);
- }
-
-
- /*
- * Add a text to the text-storage and store offset to it.
- *
- * Returns FALSE when there isn't enough space available to store
- * the text.
- */
- static bool add_text(u32b *offset, header *head, cptr buf)
- {
- size_t len = strlen(buf);
-
- /* Hack -- Verify space */
- if (head->text_size + len + 8 > z_info->fake_text_size)
- return (FALSE);
-
- /* New text? */
- if (*offset == 0)
- {
- /* Advance and save the text index */
- *offset = ++head->text_size;
- }
-
- /* Append chars to the text */
- my_strcpy(head->text_ptr + head->text_size, buf, len + 1);
-
- /* Advance the index */
- head->text_size += len;
-
- /* Success */
- return (TRUE);
- }
-
-
- /*
- * Add a name to the name-storage and return an offset to it.
- *
- * Returns 0 when there isn't enough space available to store
- * the name.
- */
- static u32b add_name(header *head, cptr buf)
- {
- u32b index;
- size_t len = strlen(buf);
-
- /* Hack -- Verify space */
- if (head->name_size + len + 8 > z_info->fake_name_size)
- return (0);
-
- /* Advance and save the name index */
- index = ++head->name_size;
-
- /* Append chars to the names */
- my_strcpy(head->name_ptr + head->name_size, buf, len + 1);
-
- /* Advance the index */
- head->name_size += len;
-
- /* Return the name index */
- return (index);
- }
-
-
- /*
- * Grab one flag from a textual string
- */
- static errr grab_one_flag(u32b *flags, cptr names[], cptr what)
- {
- int i;
-
- /* Check flags */
- for (i = 0; i < 32 && names[i]; i++)
- {
- if (streq(what, names[i]))
- {
- *flags |= (1L << i);
- return (0);
- }
- }
-
- return (-1);
- }
-
-
- /*
- * This function reads a value of the form "1+2d3M4"
- *
- * - The 1 is a constant base value.
- * - The 2d3 is a dice roll, to be applied with damroll(). The number of dice
- * is optional, and if not present, is assumed to be 1.
- * - The M4 is a magic bonus, to be applied with m_bonus().
- *
- * All parts of the random value are optional. The value is read into a
- * "random_value" struct and may be used with the randcalc() function to
- * determine the minimum, maximum, average, or randomised result of the roll.
- */
- static bool parse_random_value(const char *str, random_value *bonus)
- {
- bool negative = FALSE;
-
- char buffer[50];
- int i = 0, b, dn, ds, mb;
-
- const char end_chr = '|';
- char eov;
-
- /* Entire value may be negated */
- if (str[0] == '-')
- {
- negative = TRUE;
- i++;
- }
-
- /* Make a working copy of the string */
- my_strcpy(buffer, &str[i], N_ELEMENTS(buffer) - 2);
-
- /* Check for invalid negative numbers */
- if (NULL != strstr(buffer, "-")) return FALSE;
-
- /*
- * Add a sentinal value at the end of the string.
- * Used by scanf to make sure there's no text after the final conversion.
- */
- buffer[strlen(buffer) + 1] = '\0';
- buffer[strlen(buffer)] = end_chr;
-
- /* Scan the value, apply defaults for unspecified components */
- if (5 == sscanf(buffer, "%d+%dd%dM%d%c", &b, &dn, &ds, &mb, &eov) && eov == end_chr)
- {
- /* No defaults */
- }
- else if (4 == sscanf(buffer, "%d+d%dM%d%c", &b, &ds, &mb, &eov) && eov == end_chr)
- {
- dn = 1;
- }
- else if (3 == sscanf(buffer, "%d+M%d%c", &b, &mb, &eov) && eov == end_chr)
- {
- dn = 0; ds = 0;
- }
- else if (4 == sscanf(buffer, "%d+%dd%d%c", &b, &dn, &ds, &eov) && eov == end_chr)
- {
- mb = 0;
- }
- else if (3 == sscanf(buffer, "%d+d%d%c", &b, &ds, &eov) && eov == end_chr)
- {
- dn = 1; mb = 0;
- }
- else if (4 == sscanf(buffer, "%dd%dM%d%c", &dn, &ds, &mb, &eov) && eov == end_chr)
- {
- b = 0;
- }
- else if (3 == sscanf(buffer, "d%dM%d%c", &ds, &mb, &eov) && eov == end_chr)
- {
- b = 0; dn = 1;
- }
- else if (2 == sscanf(buffer, "M%d%c", &mb, &eov) && eov == end_chr)
- {
- b = 0; dn = 0; ds = 0;
- }
- else if (3 == sscanf(buffer, "%dd%d%c", &dn, &ds, &eov) && eov == end_chr)
- {
- b = 0; mb = 0;
- }
- else if (2 == sscanf(buffer, "d%d%c", &ds, &eov) && eov == end_chr)
- {
- b = 0; dn = 1; mb = 0;
- }
- else if (2 == sscanf(buffer, "%d%c", &b, &eov) && eov == end_chr)
- {
- dn = 0; ds = 0; mb = 0;
- }
- else
- {
- return FALSE;
- }
-
- /* Assign the values */
- bonus->base = b;
- bonus->dice = dn;
- bonus->sides = ds;
- bonus->m_bonus = mb;
-
- /*
- * Handle negation (the random components are always positive, so the base
- * must be adjusted as necessary).
- */
- if (negative)
- {
- bonus->base *= -1;
- bonus->base -= bonus->m_bonus;
- bonus->base -= bonus->dice * (bonus->sides + 1);
- }
-
- return TRUE;
- }
-
-
- /*
- * Figure out what index an activation should have
- */
- static u32b grab_one_effect(const char *what)
- {
- size_t i;
-
- /* Scan activations */
- for (i = 0; i < N_ELEMENTS(effect_list); i++)
- {
- if (streq(what, effect_list[i]))
- return i;
- }
-
- /* Oops */
- msg_format("Unknown effect '%s'.", what);
-
- /* Error */
- return 0;
- }
-
-
- /**
- * Initialise the store stocking lists.
- */
- errr init_store_txt(ang_file *fp, char *buf)
- {
- int i;
-
- int store_num = -1;
- store_type *st_ptr;
-
- error_idx = -1;
- error_line = 0;
-
-
- /* Allocate the stores */
- store = C_ZNEW(MAX_STORES, store_type);
- for (i = 0; i < MAX_STORES; i++)
- {
- st_ptr = &store[i];
-
- /* Assume stock */
- st_ptr->stock_size = STORE_INVEN_MAX;
- st_ptr->stock = C_ZNEW(st_ptr->stock_size, object_type);
- }
-
- st_ptr = NULL;
-
-
- while (file_getl(fp, buf, 1024))
- {
- error_line++;
-
- if (!buf[0] || buf[0] == '#')
- continue;
-
- else if (buf[0] == 'S')
- {
- int num, slots;
-
- /* Make sure all the previous slots have been filled */
- if (st_ptr)
- {
- if (st_ptr->table_num != st_ptr->table_size)
- {
- msg_format("Store %d has too few entries (read %d, expected %d).", error_idx, st_ptr->table_num, st_ptr->table_size);
- return PARSE_ERROR_TOO_FEW_ENTRIES;
- }
- }
-
-
- if (2 != sscanf(buf, "S:%d:%d", &num, &slots))
- return PARSE_ERROR_GENERIC;
-
- if (num < 2 || num > 6)
- return PARSE_ERROR_GENERIC;
-
- error_idx = num;
-
- /* Account for 0-based indexing */
- num--;
- store_num = num;
-
- /* Set up this store */
- st_ptr = &store[num];
- st_ptr->table_size = slots;
- st_ptr->table = C_ZNEW(st_ptr->table_size, s16b);
- }
-
- else if (buf[0] == 'I')
- {
- int slots, tval;
- int k_idx;
-
- char *tval_s;
- char *sval_s;
-
- if (store_num == -1 || !st_ptr)
- return PARSE_ERROR_GENERIC;
-
- if (1 != sscanf(buf, "I:%d:", &slots))
- return PARSE_ERROR_GENERIC;
-
- if (st_ptr->table_num + slots > st_ptr->table_size)
- return PARSE_ERROR_TOO_MANY_ENTRIES;
-
- /* Find the beginning of the tval field */
- tval_s = strchr(buf+2, ':');
- if (!tval_s) return PARSE_ERROR_MISSING_COLON;
- *tval_s++ = '\0';
- if (!*tval_s) return PARSE_ERROR_MISSING_FIELD;
-
- /* Now find the beginning of the sval field */
- sval_s = strchr(tval_s, ':');
- if (!sval_s) return PARSE_ERROR_MISSING_COLON;
- *sval_s++ = '\0';
- if (!*sval_s) return PARSE_ERROR_MISSING_FIELD;
-
- /* Now convert the tval into its numeric equivalent */
- tval = tval_find_idx(tval_s);
- if (tval == -1) return PARSE_ERROR_UNRECOGNISED_TVAL;
-
- k_idx = lookup_name(tval, sval_s);
- if (!k_idx) return PARSE_ERROR_UNRECOGNISED_SVAL;
-
- while (slots--)
- st_ptr->table[st_ptr->table_num++] = k_idx;
- }
-
- else
- {
- return PARSE_ERROR_UNDEFINED_DIRECTIVE;
- }
- }
-
- /* No errors */
- return 0;
- }
-
-
- /**
- * Initialise the random name fragments
- */
- errr init_names_txt(ang_file *fp, char *buf)
- {
- int i, name_section;
- u32b num_names[RANDNAME_NUM_TYPES];
- char temp[1024];
- int counter = 0;
- error_line = 0;
- memset(num_names, 0, RANDNAME_NUM_TYPES * sizeof(u32b));
-
- /*
- * Go through the file and count the total number of names in each name
- * section
- */
- while (file_getl(fp, buf, 1024))
- {
- error_line++;
-
- if (!buf[0] || '#' == buf[0])
- continue;
-
- else if ('N' == buf[0])
- {
- if (1 != sscanf(buf, "N:%d", &name_section))
- return PARSE_ERROR_GENERIC;
-
- if (name_section > RANDNAME_NUM_TYPES)
- return PARSE_ERROR_GENERIC;
- }
-
- else if ('D' == buf[0])
- {
- num_names[name_section]++;
- }
-
- else
- {
- return PARSE_ERROR_UNDEFINED_DIRECTIVE;
- }
- }
-
- /* Go back to the start of the file */
- file_seek(fp, 0);
-
- /* Allocate some memory for pointers to sections */
- name_sections = C_ZNEW(RANDNAME_NUM_TYPES, cptr*);
-
- /* Allocate more memory for pointers to names */
- /* Add a null element at the end of each array (see randname.c) */
- for (i = 0; i < RANDNAME_NUM_TYPES; i++)
- {
- if (num_names[i])
- {
- name_sections[i] = C_ZNEW(num_names[i] + 1, cptr);
- }
- }
-
- /*
- * Go through the file again and read each name into the relevant array
- */
- while (file_getl(fp, buf, 1024))
- {
- error_line++;
-
- if (!buf[0] || '#' == buf[0])
- continue;
-
- else if ('N' == buf[0])
- {
- if (1 != sscanf(buf, "N:%d", &name_section))
- return PARSE_ERROR_GENERIC;
-
- if (name_section > RANDNAME_NUM_TYPES)
- return PARSE_ERROR_GENERIC;
-
- counter = 0;
- }
-
- else if ('D' == buf[0])
- {
- if (1 != sscanf(buf, "D:%s", temp))
- return PARSE_ERROR_GENERIC;
-
- name_sections[name_section][counter++] = string_make(temp);
- }
-
- else
- {
- return PARSE_ERROR_UNDEFINED_DIRECTIVE;
- }
- }
-
- /* No errors */
- return 0;
- }
-
-
- /*
- * Initialize the "z_info" structure, by parsing an ascii "template" file
- */
- errr parse_z_info(char *buf, header *head)
- {
- maxima *z_info = head->info_ptr;
-
- /* Hack - Verify 'M:x:' format */
- if (buf[0] != 'M') return (PARSE_ERROR_UNDEFINED_DIRECTIVE);
- if (!buf[2]) return (PARSE_ERROR_UNDEFINED_DIRECTIVE);
- if (buf[3] != ':') return (PARSE_ERROR_UNDEFINED_DIRECTIVE);
-
-
- /* Process 'F' for "Maximum f_info[] index" */
- if (buf[2] == 'F')
- {
- int max;
-
- /* Scan for the value */
- if (1 != sscanf(buf+4, "%d", &max)) return (PARSE_ERROR_NOT_NUMBER);
-
- /* Save the value */
- z_info->f_max = max;
- }
-
- /* Process 'K' for "Maximum k_info[] index" */
- else if (buf[2] == 'K')
- {
- int max;
-
- /* Scan for the value */
- if (1 != sscanf(buf+4, "%d", &max)) return (PARSE_ERROR_NOT_NUMBER);
-
- /* Save the value */
- z_info->k_max = max;
- }
-
- /* Process 'A' for "Maximum a_info[] index" */
- else if (buf[2] == 'A')
- {
- int max;
-
- /* Scan for the value */
- if (1 != sscanf(buf+4, "%d", &max)) return (PARSE_ERROR_NOT_NUMBER);
-
- /* Save the value */
- z_info->a_max = max;
- }
-
- /* Process 'E' for "Maximum e_info[] index" */
- else if (buf[2] == 'E')
- {
- int max;
-
- /* Scan for the value */
- if (1 != sscanf(buf+4, "%d", &max)) return (PARSE_ERROR_NOT_NUMBER);
-
- /* Save the value */
- z_info->e_max = max;
- }
-
- /* Process 'R' for "Maximum r_info[] index" */
- else if (buf[2] == 'R')
- {
- int max;
-
- /* Scan for the value */
- if (1 != sscanf(buf+4, "%d", &max)) return (PARSE_ERROR_NOT_NUMBER);
-
- /* Save the value */
- z_info->r_max = max;
- }
-
-
- /* Process 'V' for "Maximum v_info[] index" */
- else if (buf[2] == 'V')
- {
- int max;
-
- /* Scan for the value */
- if (1 != sscanf(buf+4, "%d", &max)) return (PARSE_ERROR_NOT_NUMBER);
-
- /* Save the value */
- z_info->v_max = max;
- }
-
-
- /* Process 'P' for "Maximum p_info[] index" */
- else if (buf[2] == 'P')
- {
- int max;
-
- /* Scan for the value */
- if (1 != sscanf(buf+4, "%d", &max)) return (PARSE_ERROR_NOT_NUMBER);
-
- /* Save the value */
- z_info->p_max = max;
- }
-
- /* Process 'C' for "Maximum c_info[] index" */
- else if (buf[2] == 'C')
- {
- int max;
-
- /* Scan for the value */
- if (1 != sscanf(buf+4, "%d", &max)) return (PARSE_ERROR_NOT_NUMBER);
-
- /* Save the value */
- z_info->c_max = max;
- }
-
- /* Process 'H' for "Maximum h_info[] index" */
- else if (buf[2] == 'H')
- {
- int max;
-
- /* Scan for the value */
- if (1 != sscanf(buf+4, "%d", &max)) return (PARSE_ERROR_NOT_NUMBER);
-
- /* Save the value */
- z_info->h_max = max;
- }
-
- /* Process 'B' for "Maximum b_info[] subindex" */
- else if (buf[2] == 'B')
- {
- int max;
-
- /* Scan for the value */
- if (1 != sscanf(buf+4, "%d", &max)) return (PARSE_ERROR_NOT_NUMBER);
-
- /* Save the value */
- z_info->b_max = max;
- }
-
- /* Process 'L' for "Maximum flavor_info[] subindex" */
- else if (buf[2] == 'L')
- {
- int max;
-
- /* Scan for the value */
- if (1 != sscanf(buf+4, "%d", &max)) return (PARSE_ERROR_NOT_NUMBER);
-
- /* Save the value */
- z_info->flavor_max = max;
- }
-
- /* Process 'S' for "Maximum s_info[] subindex" */
- else if (buf[2] == 'S')
- {
- int max;
-
- /* Scan for the value */
- if (1 != sscanf(buf+4, "%d", &max)) return (PARSE_ERROR_NOT_NUMBER);
-
- /* Save the value */
- z_info->s_max = max;
- }
-
- /* Process 'O' for "Maximum o_list[] index" */
- else if (buf[2] == 'O')
- {
- int max;
-
- /* Scan for the value */
- if (1 != sscanf(buf+4, "%d", &max)) return (PARSE_ERROR_NOT_NUMBER);
-
- /* Save the value */
- z_info->o_max = max;
- }
-
- /* Process 'M' for "Maximum mon_list[] index" */
- else if (buf[2] == 'M')
- {
- int max;
-
- /* Scan for the value */
- if (1 != sscanf(buf+4, "%d", &max)) return (PARSE_ERROR_NOT_NUMBER);
-
- /* Save the value */
- z_info->m_max = max;
- }
-
- /* Process 'N' for "Fake name size" */
- else if (buf[2] == 'N')
- {
- long max;
-
- /* Scan for the value */
- if (1 != sscanf(buf+4, "%ld", &max)) return (PARSE_ERROR_NOT_NUMBER);
-
- /* Save the value */
- z_info->fake_name_size = max;
- }
-
- /* Process 'T' for "Fake text size" */
- else if (buf[2] == 'T')
- {
- long max;
-
- /* Scan for the value */
- if (1 != sscanf(buf+4, "%ld", &max)) return (PARSE_ERROR_NOT_NUMBER);
-
- /* Save the value */
- z_info->fake_text_size = max;
- }
- else
- {
- /* Oops */
- return (PARSE_ERROR_UNDEFINED_DIRECTIVE);
- }
-
- /* Success */
- return (0);
- }
-
-
- /*
- * Initialize the "v_info" array, by parsing an ascii "template" file
- */
- errr parse_v_info(char *buf, header *head)
- {
- int i;
-
- char *s;
-
- /* Current entry */
- static vault_type *v_ptr = NULL;
-
-
- /* Process 'N' for "New/Number/Name" */
- if (buf[0] == 'N')
- {
- /* Find the colon before the name */
- s = strchr(buf+2, ':');
-
- /* Verify that colon */
- if (!s) return (PARSE_ERROR_MISSING_COLON);
-
- /* Nuke the colon, advance to the name */
- *s++ = '\0';
-
- /* Paranoia -- require a name */
- if (!*s) return (PARSE_ERROR_GENERIC);
-
- /* Get the index */
- i = atoi(buf+2);
-
- /* Verify information */
- if (i <= error_idx) return (PARSE_ERROR_NON_SEQUENTIAL_RECORDS);
-
- /* Verify information */
- if (i >= head->info_num) return (PARSE_ERROR_TOO_MANY_ENTRIES);
-
- /* Save the index */
- error_idx = i;
-
- /* Point at the "info" */
- v_ptr = (vault_type*)head->info_ptr + i;
-
- /* Store the name */
- if ((v_ptr->name = add_name(head, s)) == 0)
- return (PARSE_ERROR_OUT_OF_MEMORY);
- }
-
- /* Process 'D' for "Description" */
- else if (buf[0] == 'D')
- {
- /* There better be a current v_ptr */
- if (!v_ptr) return (PARSE_ERROR_MISSING_RECORD_HEADER);
-
- /* Get the text */
- s = buf+2;
-
- /* Store the text */
- if (!add_text(&v_ptr->text, head, s))
- return (PARSE_ERROR_OUT_OF_MEMORY);
- }
-
- /* Process 'X' for "Extra info" (one line only) */
- else if (buf[0] == 'X')
- {
- int typ, rat, hgt, wid;
-
- /* There better be a current v_ptr */
- if (!v_ptr) return (PARSE_ERROR_MISSING_RECORD_HEADER);
-
- /* Scan for the values */
- if (4 != sscanf(buf+2, "%d:%d:%d:%d",
- &typ, &rat, &hgt, &wid)) return (PARSE_ERROR_GENERIC);
-
- /* Save the values */
- v_ptr->typ = typ;
- v_ptr->rat = rat;
- v_ptr->hgt = hgt;
- v_ptr->wid = wid;
-
- /* Check for maximum vault sizes */
- if ((v_ptr->typ == 6) && ((v_ptr->wid > 33) || (v_ptr->hgt > 22)))
- return (PARSE_ERROR_VAULT_TOO_BIG);
-
- if ((v_ptr->typ == 7) && ((v_ptr->wid > 66) || (v_ptr->hgt > 44)))
- return (PARSE_ERROR_VAULT_TOO_BIG);
- }
- else
- {
- /* Oops */
- return (PARSE_ERROR_UNDEFINED_DIRECTIVE);
- }
-
- /* Success */
- return (0);
- }
-
-
-
- /*
- * Initialize the "f_info" array, by parsing an ascii "template" file
- */
- errr parse_f_info(char *buf, header *head)
- {
- int i;
-
- char *s;
- char *t;
-
- /* Current entry */
- static feature_type *f_ptr = NULL;
-
-
- /* Process 'N' for "New/Number/Name" */
- if (buf[0] == 'N')
- {
- /* Find the colon before the name */
- s = strchr(buf+2, ':');
-
- /* Verify that colon */
- if (!s) return (PARSE_ERROR_MISSING_COLON);
-
- /* Nuke the colon, advance to the name */
- *s++ = '\0';
-
- /* Paranoia -- require a name */
- if (!*s) return (PARSE_ERROR_GENERIC);
-
- /* Get the index */
- i = atoi(buf+2);
-
- /* Verify information */
- if (i <= error_idx) return (PARSE_ERROR_NON_SEQUENTIAL_RECORDS);
-
- /* Verify information */
- if (i >= head->info_num) return (PARSE_ERROR_TOO_MANY_ENTRIES);
-
- /* Save the index */
- error_idx = i;
-
- /* Point at the "info" */
- f_ptr = (feature_type*)head->info_ptr + i;
-
- /* Store the name */
- if ((f_ptr->name = add_name(head, s)) == 0)
- return (PARSE_ERROR_OUT_OF_MEMORY);
-
- /* Default "mimic" */
- f_ptr->mimic = i;
- }
-
- /* Process 'M' for "Mimic" (one line only) */
- else if (buf[0] == 'M')
- {
- int mimic;
-
- /* There better be a current f_ptr */
- if (!f_ptr) return (PARSE_ERROR_MISSING_RECORD_HEADER);
-
- /* Scan for the values */
- if (1 != sscanf(buf+2, "%d", &mimic))
- return (PARSE_ERROR_NOT_NUMBER);
-
- /* Save the values */
- f_ptr->mimic = mimic;
- }
-
- /* Process 'P' for "Priority" */
- else if (buf[0] == 'P')
- {
- int priority;
-
- /* There better be a current f_ptr */
- if (!f_ptr) return (PARSE_ERROR_MISSING_RECORD_HEADER);
-
- /* Scan for the values */
- if (1 != sscanf(buf+2, "%d", &priority))
- return (PARSE_ERROR_NOT_NUMBER);
-
- /* Save the values */
- f_ptr->priority = priority;
- }
-
- /* Process 'G' for "Graphics" (one line only) */
- else if (buf[0] == 'G')
- {
- char d_char;
- int d_attr;
-
- /* There better be a current f_ptr */
- if (!f_ptr) return (PARSE_ERROR_MISSING_RECORD_HEADER);
-
- /* Paranoia */
- if (!buf[2]) return (PARSE_ERROR_GENERIC);
- if (!buf[3]) return (PARSE_ERROR_GENERIC);
- if (!buf[4]) return (PARSE_ERROR_GENERIC);
-
- /* Extract d_char */
- d_char = buf[2];
-
- /* If we have a longer string than expected ... */
- if (buf[5])
- {
- /* Advance "buf" on by 4 */
- buf += 4;
-
- /* Extract the colour */
- d_attr = color_text_to_attr(buf);
- }
- else
- {
- /* Extract the attr */
- d_attr = color_char_to_attr(buf[4]);
- }
-
- /* Paranoia */
- if (d_attr < 0) return (PARSE_ERROR_GENERIC);
-
- /* Save the values */
- f_ptr->d_attr = d_attr;
- f_ptr->d_char = d_char;
- }
-
- /* Process 'F' for flags */
- else if (buf[0] == 'F')
- {
- /* Parse every entry textually */
- for (s = buf + 2; *s; )
- {
- /* Find the end of this entry */
- for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
-
- /* Nuke and skip any dividers */
- if (*t)
- {
- *t++ = '\0';
- while ((*t == ' ') || (*t == '|')) t++;
- }
-
- /* Parse this entry */
- if (0 != grab_one_flag(&f_ptr->flags, f_info_flags, s))
- return (PARSE_ERROR_INVALID_FLAG);
-
- /* Start the next entry */
- s = t;
- }
- }
-
- /* Process 'E' for effect */
- else if (buf[0] == 'E')
- {
- f_ptr->effect = grab_one_effect(buf + 2);
- if (!f_ptr->effect)
- return PARSE_ERROR_GENERIC;
- }
-
- /* Process 'X' for extra */
- else if (buf[0] == 'X')
- {
- int locked, jammed, shopnum, dig;
-
- if (4 != sscanf(buf + 2, "%d:%d:%d:%d",
- &locked, &jammed, &shopnum, &dig))
- return PARSE_ERROR_NOT_NUMBER;
-
- f_ptr->locked = locked;
- f_ptr->jammed = jammed;
- f_ptr->shopnum = shopnum;
- f_ptr->dig = dig;
- }
-
- else
- {
- /* Oops */
- return (PARSE_ERROR_UNDEFINED_DIRECTIVE);
- }
-
- /* Success */
- return (0);
- }
-
-
- /*
- * Find a flag's index from a textual string.
- */
- static int lookup_flag(const char **flag_table, const char *flag_name)
- {
- int i = FLAG_START;
-
- while (flag_table[i] && !streq(flag_table[i], flag_name))
- i++;
-
- /* End of table reached without match */
- if (!flag_table[i]) i = FLAG_END;
-
- return i;
- }
-
-
- /*
- * Grab one flag from a string, and set that flag in a bit field
- */
- static errr grab_flag(bitflag *flags, const size_t size, const char **flag_table, const char *flag_name)
- {
- int flag = lookup_flag(flag_table, flag_name);
-
- if (flag == FLAG_END) return PARSE_ERROR_INVALID_FLAG;
-
- flag_on(flags, size, flag);
-
- return 0;
- }
-
-
-
- /*
- * Initialize the "k_info" array, by parsing an ascii "template" file
- */
- errr parse_k_info(char *buf, header *head)
- {
- int i;
-
- char *s = NULL, *t;
-
- /* Current entry */
- static object_kind *k_ptr = NULL;
-
-
- /* Process 'N' for "New/Number/Name" */
- if (buf[0] == 'N')
- {
- /* Find the colon before the name */
- s = strchr(buf+2, ':');
-
- /* Verify that colon */
- if (!s) return (PARSE_ERROR_MISSING_COLON);
-
- /* Nuke the colon, advance to the name */
- *s++ = '\0';
-
- /* Paranoia -- require a name */
- if (!*s) return (PARSE_ERROR_GENERIC);
-
- /* Get the index */
- i = atoi(buf+2);
-
- /* Verify information */
- if (i <= error_idx) return (PARSE_ERROR_NON_SEQUENTIAL_RECORDS);
-
- /* Verify information */
- if (i >= head->info_num) return (PARSE_ERROR_TOO_MANY_ENTRIES);
-
- /* Save the index */
- error_idx = i;
-
- /* Point at the "info" */
- k_ptr = (object_kind*)head->info_ptr + i;
-
- /* Store the name */
- if ((k_ptr->name = add_name(head, s)) == 0)
- return (PARSE_ERROR_OUT_OF_MEMORY);
-
- /* Success (return early) */
- return (0);
- }
-
- /* There better be a current k_ptr */
- if (!k_ptr) return (PARSE_ERROR_MISSING_RECORD_HEADER);
-
- /* Process 'G' for "Graphics" (one line only) */
- if (buf[0] == 'G')
- {
- char d_char;
- int d_attr;
-
- /* Paranoia */
- if (!buf[2]) return (PARSE_ERROR_GENERIC);
- if (!buf[3]) return (PARSE_ERROR_GENERIC);
- if (!buf[4]) return (PARSE_ERROR_GENERIC);
-
- /* Extract d_char */
- d_char = buf[2];
-
- /* If we have a longer string than expected ... */
- if (buf[5])
- {
- /* Advance "buf" on by 4 */
- buf += 4;
-
- /* Extract the colour */
- d_attr = color_text_to_attr(buf);
- }
- else
- {
- /* Extract the attr */
- d_attr = color_char_to_attr(buf[4]);
- }
-
- /* Paranoia */
- if (d_attr < 0) return (PARSE_ERROR_GENERIC);
-
- /* Save the values */
- k_ptr->d_attr = d_attr;
- k_ptr->d_char = d_char;
- }
-
- /* Process 'I' for "Info" (one line only) */
- else if (buf[0] == 'I')
- {
- int tval, sval;
- char pval[50];
-
- /* Scan for the values */
- if (3 != sscanf(buf+2, "%d:%d:%s",
- &tval, &sval, pval)) return (PARSE_ERROR_GENERIC);
-
- /* Save the values */
- k_ptr->tval = tval;
- k_ptr->sval = sval;
- if (!parse_random_value(pval, &k_ptr->pval)) return PARSE_ERROR_INVALID_VALUE;
- }
-
- /* Process 'W' for "More Info" (one line only) */
- else if (buf[0] == 'W')
- {
- int level, extra, wgt;
- long cost;
-
- /* Scan for the values */
- if (4 != sscanf(buf+2, "%d:%d:%d:%ld",
- &level, &extra, &wgt, &cost)) return (PARSE_ERROR_GENERIC);
-
- /* Save the values */
- k_ptr->level = level;
- k_ptr->weight = wgt;
- k_ptr->cost = cost;
- }
-
- /* Process 'A' for "Allocation" (one line only) */
- else if (buf[0] == 'A')
- {
- int common, min, max;
-
- /* Format is "A:<common>:<min> to <max>" */
- if (3 != sscanf(buf+2, "%d:%d to %d", &common, &min, &max))
- return (PARSE_ERROR_GENERIC);
-
-
- /* Limit to size a byte */
- if (common < 0 || common > 255) return (PARSE_ERROR_GENERIC);
- if (min < 0 || min > 255) return (PARSE_ERROR_GENERIC);
- if (max < 0 || max > 255) return (PARSE_ERROR_GENERIC);
-
-
- /* Set up data */
- k_ptr->alloc_prob = common;
- k_ptr->alloc_min = min;
- k_ptr->alloc_max = max;
- }
-
- /* Hack -- Process 'P' for "power" and such */
- else if (buf[0] == 'P')
- {
- int ac, hd1, hd2;
- char *th, *td, *ta;
- char fields[150];
-
- /* Scan for the values "P:0:0d0:0:0:0" */
- if (4 != sscanf(buf+2, "%d:%dd%d:%s",
- &ac, &hd1, &hd2, fields)) return (PARSE_ERROR_GENERIC);
-
- /* Tokenize the last three fields */
- if(!(th = strtok(fields, ":"))) return PARSE_ERROR_GENERIC;
- if(!(td = strtok(NULL, ":"))) return PARSE_ERROR_GENERIC;
- if(!(ta = strtok(NULL, ":"))) return PARSE_ERROR_GENERIC;
-
- k_ptr->ac = ac;
- k_ptr->dd = hd1;
- k_ptr->ds = hd2;
- if (!parse_random_value(th, &k_ptr->to_h)) return PARSE_ERROR_INVALID_VALUE;
- if (!parse_random_value(td, &k_ptr->to_d)) return PARSE_ERROR_INVALID_VALUE;
- if (!parse_random_value(ta, &k_ptr->to_a)) return PARSE_ERROR_INVALID_VALUE;
- }
-
- /* Hack -- Process 'C' for "charges" */
- else if (buf[0] == 'C')
- {
- if(!parse_random_value(buf+2, &k_ptr->charge)) return PARSE_ERROR_INVALID_VALUE;
- }
-
- /* Process 'M' for "Multiple quantity" (one line only) */
- else if (buf[0] == 'M')
- {
- int prob;
- char stack[50];
-
- /* Scan for the values */
- if (2 != sscanf(buf+2, "%d:%s", &prob, stack))
- return (PARSE_ERROR_GENERIC);
-
- /* Save the values */
- k_ptr->gen_mult_prob = prob;
- if (!parse_random_value(stack, &k_ptr->stack_size)) return PARSE_ERROR_INVALID_VALUE;
- }
-
- /* Hack -- Process 'F' for flags */
- else if (buf[0] == 'F')
- {
- /* Parse every entry textually */
- for (s = buf + 2; *s; )
- {
- /* Find the end of this entry */
- for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
-
- /* Nuke and skip any dividers */
- if (*t)
- {
- *t++ = '\0';
- while (*t == ' ' || *t == '|') t++;
- }
-
- /* Parse this entry */
- if (0 != grab_flag(k_ptr->flags, OF_SIZE, k_info_flags, s))
- return (PARSE_ERROR_INVALID_FLAG);
-
- /* Start the next entry */
- s = t;
- }
- }
-
- /* Process 'E' for effect */
- else if (buf[0] == 'E')
- {
- /* Find the colon after the name, nuke it and advance */
- s = strchr(buf + 2, ':');
- if (s) *s++ = '\0';
-
- /* Get the activation */
- k_ptr->effect = grab_one_effect(buf + 2);
- if (!k_ptr->effect) return (PARSE_ERROR_GENERIC);
-
- /* Get the timeout, if supplied */
- if (s && !parse_random_value(s, &k_ptr->time))
- return (PARSE_ERROR_INVALID_VALUE);
- }
-
- /* Process 'D' for "Description" */
- else if (buf[0] == 'D')
- {
- /* Store the text */
- if (!add_text(&(k_ptr->text), head, buf + 2))
- return (PARSE_ERROR_OUT_OF_MEMORY);
- }
-
- else
- {
- /* Oops */
- return (PARSE_ERROR_UNDEFINED_DIRECTIVE);
- }
-
- /* Success */
- return (0);
- }
-
-
-
- /*
- * Initialize the "a_info" array, by parsing an ascii "template" file
- */
- errr parse_a_info(char *buf, header *head)
- {
- int i;
-
- char *s, *t;
-
- /* Current entry */
- static artifact_type *a_ptr = NULL;
-
-
- /* Process 'N' for "New/Number/Name" */
- if (buf[0] == 'N')
- {
- /* Find the colon before the name */
- s = strchr(buf+2, ':');
-
- /* Verify that colon */
- if (!s) return (PARSE_ERROR_MISSING_COLON);
-
- /* Nuke the colon, advance to the name */
- *s++ = '\0';
-
- /* Paranoia -- require a name */
- if (!*s) return (PARSE_ERROR_GENERIC);
-
- /* Get the index */
- i = atoi(buf+2);
-
- /* Verify information */
- if (i <= error_idx) return (PARSE_ERROR_NON_SEQUENTIAL_RECORDS);
-
- /* Verify information */
- if (i >= head->info_num) return (PARSE_ERROR_TOO_MANY_ENTRIES);
-
- /* Save the index */
- error_idx = i;
-
- /* Point at the "info" */
- a_ptr = (artifact_type*)head->info_ptr + i;
-
- /* Store the name */
- if ((a_ptr->name = add_name(head, s)) == 0)
- return (PARSE_ERROR_OUT_OF_MEMORY);
-
- /* Ignore everything */
- flags_set(a_ptr->flags, OF_SIZE, OF_IGNORE_MASK, FLAG_END);
-
- /* Return early */
- return (0);
- }
-
- /* There better be a current a_ptr */
- if (!a_ptr) return (PARSE_ERROR_MISSING_RECORD_HEADER);
-
- /* Process 'I' for "Info" (one line only) */
- else if (buf[0] == 'I')
- {
- char *tval_s, *sval_s, *pval_s;
- int tval, sval, pval;
-
- /* Find the beginning of the tval field */
- tval_s = strchr(buf, ':');
- if (!tval_s) return PARSE_ERROR_MISSING_COLON;
- *tval_s++ = '\0';
- if (!*tval_s) return PARSE_ERROR_MISSING_FIELD;
-
- /* Now find the beginning of the sval field */
- sval_s = strchr(tval_s, ':');
- if (!sval_s) return PARSE_ERROR_MISSING_COLON;
- *sval_s++ = '\0';
- if (!*sval_s) return PARSE_ERROR_MISSING_FIELD;
-
- /* Now find the beginning of the pval field */
- pval_s = strchr(sval_s, ':');
- if (!pval_s) return PARSE_ERROR_MISSING_COLON;
- *pval_s++ = '\0';
- if (!*pval_s) return PARSE_ERROR_MISSING_FIELD;
-
- /* Now convert the tval into its numeric equivalent */
- if (1 != sscanf(tval_s, "%d", &tval))
- {
- tval = tval_find_idx(tval_s);
- if (tval == -1) return PARSE_ERROR_UNRECOGNISED_TVAL;
- }
-
- /* Now find the sval */
- if (1 != sscanf(sval_s, "%d", &sval))
- {
- sval = lookup_sval(tval, sval_s);
- if (sval == -1) return PARSE_ERROR_UNRECOGNISED_SVAL;
- }
-
- /* Now extract the pval */
- if (1 != sscanf(pval_s, "%d", &pval))
- return PARSE_ERROR_NOT_NUMBER;
-
- /* Save the values */
- a_ptr->tval = tval;
- a_ptr->sval = sval;
- a_ptr->pval = pval;
- }
-
- /* Process 'W' for "More Info" (one line only) */
- else if (buf[0] == 'W')
- {
- int level, rarity, wgt;
- long cost;
-
- /* Scan for the values */
- if (4 != sscanf(buf+2, "%d:%d:%d:%ld",
- &level, &rarity, &wgt, &cost)) return (PARSE_ERROR_GENERIC);
-
- /* Save the values */
- a_ptr->level = level;
- a_ptr->rarity = rarity;
- a_ptr->weight = wgt;
- a_ptr->cost = cost;
- }
-
- /* Process 'A' for "Allocation" (one line only) */
- else if (buf[0] == 'A')
- {
- int common, min, max;
-
- /* Format is "A:<common>:<min> to <max>" */
- if (3 != sscanf(buf+2, "%d:%d to %d", &common, &min, &max))
- return (PARSE_ERROR_GENERIC);
-
-
- /* Limit to size a byte */
- if (common < 0 || common > 255) return (PARSE_ERROR_GENERIC);
- if (min < 0 || min > 255) return (PARSE_ERROR_GENERIC);
- if (max < 0 || max > 255) return (PARSE_ERROR_GENERIC);
-
-
- /* Set up data */
- a_ptr->alloc_prob = common;
- a_ptr->alloc_min = min;
- a_ptr->alloc_max = max;
- }
-
- /* Process 'P' for "power" and such */
- else if (buf[0] == 'P')
- {
- int ac, hd1, hd2, th, td, ta;
-
- /* Scan for the values */
- if (6 != sscanf(buf+2, "%d:%dd%d:%d:%d:%d",
- &ac, &hd1, &hd2, &th, &td, &ta)) return (PARSE_ERROR_GENERIC);
-
- a_ptr->ac = ac;
- a_ptr->dd = hd1;
- a_ptr->ds = hd2;
- a_ptr->to_h = th;
- a_ptr->to_d = td;
- a_ptr->to_a = ta;
- }
-
- /* Process 'F' for flags */
- else if (buf[0] == 'F')
- {
- /* Parse every entry textually */
- for (s = buf + 2; *s; )
- {
- /* Find the end of this entry */
- for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
-
- /* Nuke and skip any dividers */
- if (*t)
- {
- *t++ = '\0';
- while ((*t == ' ') || (*t == '|')) t++;
- }
-
- /* Parse this entry */
- if (0 != grab_flag(a_ptr->flags, OF_SIZE, k_info_flags, s))
- return (PARSE_ERROR_INVALID_FLAG);
-
- /* Start the next entry */
- s = t;
- }
- }
-
- /* Process 'E' for Effect (Activation) & time */
- else if (buf[0] == 'E')
- {
- /* Find the colon after the name */
- s = strchr(buf + 2, ':');
- if (!s) return (PARSE_ERROR_MISSING_COLON);
-
- /* Nuke the colon, advance to the name */
- *s++ = '\0';
- if (!*s) return (PARSE_ERROR_GENERIC);
-
- /* Get the activation */
- a_ptr->effect = grab_one_effect(buf + 2);
- if (!a_ptr->effect) return (PARSE_ERROR_GENERIC);
-
- /* Scan for the values */
- if (!parse_random_value(s, &a_ptr->time))
- return (PARSE_ERROR_INVALID_VALUE);
- }
-
- /* Process 'M' for "Effect message" */
- else if (buf[0] == 'M')
- {
- /* Store the text */
- if (!add_text(&a_ptr->effect_msg, head, buf+2))
- return (PARSE_ERROR_OUT_OF_MEMORY);
- }
-
- /* Process 'D' for "Description" */
- else if (buf[0] == 'D')
- {
- /* Store the text */
- if (!add_text(&a_ptr->text, head, buf+2))
- return (PARSE_ERROR_OUT_OF_MEMORY);
- }
-
- else
- {
- /* Oops */
- return (PARSE_ERROR_UNDEFINED_DIRECTIVE);
- }
-
- /* Success */
- return (0);
- }
-
-
-
- /*
- * Initialize the "e_info" array, by parsing an ascii "template" file
- */
- errr parse_e_info(char *buf, header *head)
- {
- int i;
-
- char *s, *t;
-
- /* Current entry */
- static ego_item_type *e_ptr = NULL;
-
- static int cur_t = 0;
-
-
- /* Process 'N' for "New/Number/Name" */
- if (buf[0] == 'N')
- {
- /* Find the colon before the name */
- s = strchr(buf+2, ':');
-
- /* Verify that colon */
- if (!s) return (PARSE_ERROR_MISSING_COLON);
-
- /* Nuke the colon, advance to the name */
- *s++ = '\0';
-
- /* Paranoia -- require a name */
- if (!*s) return (PARSE_ERROR_GENERIC);
-
- /* Get the index */
- i = atoi(buf+2);
-
- /* Verify information */
- if (i <= error_idx) return (PARSE_ERROR_NON_SEQUENTIAL_RECORDS);
-
- /* Verify information */
- if (i >= head->info_num) return (PARSE_ERROR_TOO_MANY_ENTRIES);
-
- /* Save the index */
- error_idx = i;
-
- /* Point at the "info" */
- e_ptr = (ego_item_type*)head->info_ptr + i;
-
- /* Store the name */
- if ((e_ptr->name = add_name(head, s)) == 0)
- return (PARSE_ERROR_OUT_OF_MEMORY);
-
- /* Start with the first of the tval indices */
- cur_t = 0;
- }
-
- /* Process 'W' for "More Info" (one line only) */
- else if (buf[0] == 'W')
- {
- int level, rarity, pad2;
- long cost;
-
- /* There better be a current e_ptr */
- if (!e_ptr) return (PARSE_ERROR_MISSING_RECORD_HEADER);
-
- /* Scan for the values */
- if (4 != sscanf(buf+2, "%d:%d:%d:%ld",
- &level, &rarity, &pad2, &cost)) return (PARSE_ERROR_GENERIC);
-
- /* Save the values */
- e_ptr->level = level;
- e_ptr->rarity = rarity;
- /* e_ptr->weight = wgt; */
- e_ptr->cost = cost;
- }
-
- /* Process 'X' for "Xtra" (one line only) */
- else if (buf[0] == 'X')
- {
- int rating, xtra;
-
- /* There better be a current e_ptr */
- if (!e_ptr) return (PARSE_ERROR_MISSING_RECORD_HEADER);
-
- /* Scan for the values */
- if (2 != sscanf(buf+2, "%d:%d", &rating, &xtra))
- return (PARSE_ERROR_GENERIC);
-
- /* Save the values */
- e_ptr->rating = rating;
- e_ptr->xtra = xtra;
- }
-
- /* Process 'T' for "Types allowed" (up to three lines) */
- else if (buf[0] == 'T')
- {
- int tval, sval1, sval2;
-
- /* There better be a current e_ptr */
- if (!e_ptr) return (PARSE_ERROR_MISSING_RECORD_HEADER);
-
- /* Scan for the values */
- if (3 != sscanf(buf+2, "%d:%d:%d",
- &tval, &sval1, &sval2)) return (PARSE_ERROR_GENERIC);
-
- /* Save the values */
- e_ptr->tval[cur_t] = (byte)tval;
- e_ptr->min_sval[cur_t] = (byte)sval1;
- e_ptr->max_sval[cur_t] = (byte)sval2;
-
- /* Increase counter for 'possible tval' index */
- cur_t++;
-
- /* Allow only a limited number of T: lines */
- if (cur_t > EGO_TVALS_MAX) return (PARSE_ERROR_GENERIC);
- }
-
- /* Hack -- Process 'C' for "creation" */
- else if (buf[0] == 'C')
- {
- char *th, *td, *ta, *pv;
- char fields[200];
-
- /* There better be a current e_ptr */
- if (!e_ptr) return (PARSE_ERROR_MISSING_RECORD_HEADER);
-
- /* Scan for the values */
- if (1 != sscanf(buf+2, "%s", fields)) return (PARSE_ERROR_GENERIC);
-
- if(!(th = strtok(fields, ":"))) return PARSE_ERROR_GENERIC;
- if(!(td = strtok(NULL, ":"))) return PARSE_ERROR_GENERIC;
- if(!(ta = strtok(NULL, ":"))) return PARSE_ERROR_GENERIC;
- if(!(pv = strtok(NULL, ":"))) return PARSE_ERROR_GENERIC;
-
- if(!parse_random_value(th, &e_ptr->to_h)) return PARSE_ERROR_INVALID_VALUE;
- if(!parse_random_value(td, &e_ptr->to_d)) return PARSE_ERROR_INVALID_VALUE;
- if(!parse_random_value(ta, &e_ptr->to_a)) return PARSE_ERROR_INVALID_VALUE;
- if(!parse_random_value(pv, &e_ptr->pval)) return PARSE_ERROR_INVALID_VALUE;
- }
-
- /* Process 'M' for "minimum values" */
- else if (buf[0] == 'M')
- {
- int th, td, ta, pv;
-
- /* There better be a current e_ptr */
- if (!e_ptr) return (PARSE_ERROR_MISSING_RECORD_HEADER);
-
- /* Scan for the values */
- if (4 != sscanf(buf+2, "%d:%d:%d:%d",
- &th, &td, &ta, &pv)) return (PARSE_ERROR_GENERIC);
-
- e_ptr->min_to_h = th;
- e_ptr->min_to_d = td;
- e_ptr->min_to_a = ta;
- e_ptr->min_pval = pv;
- }
-
- /* Hack -- Process 'F' for flags */
- else if (buf[0] == 'F')
- {
- /* There better be a current e_ptr */
- if (!e_ptr) return (PARSE_ERROR_MISSING_RECORD_HEADER);
-
- /* Parse every entry textually */
- for (s = buf + 2; *s; )
- {
- /* Find the end of this entry */
- for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
-
- /* Nuke and skip any dividers */
- if (*t)
- {
- *t++ = '\0';
- while ((*t == ' ') || (*t == '|')) t++;
- }
-
- /* Parse this entry */
- if (0 != grab_flag(e_ptr->flags, OF_SIZE, k_info_flags, s))
- return (PARSE_ERROR_INVALID_FLAG);
-
- /* Start the next entry */
- s = t;
- }
- }
-
- /* Process 'D' for "Description" */
- else if (buf[0] == 'D')
- {
- /* There better be a current e_ptr */
- if (!e_ptr) return (PARSE_ERROR_MISSING_RECORD_HEADER);
-
- /* Get the text */
- s = buf+2;
-
- /* Store the text */
- if (!add_text(&e_ptr->text, head, s))
- return (PARSE_ERROR_OUT_OF_MEMORY);
- }
-
- else
- {
- /* Oops */
- return (PARSE_ERROR_UNDEFINED_DIRECTIVE);
- }
-
- /* Success */
- return (0);
- }
-
-
-
- /*
- * Initialize the "r_info" array, by parsing an ascii "template" file
- */
- errr parse_r_info(char *buf, header *head)
- {
- int i;
-
- char *s, *t;
-
- /* Current entry */
- static monster_race *r_ptr = NULL;
-
-
- /* Process 'N' for "New/Number/Name" */
- if (buf[0] == 'N')
- {
- /* Find the colon before the name */
- s = strchr(buf+2, ':');
-
- /* Verify that colon */
- if (!s) return (PARSE_ERROR_MISSING_COLON);
-
- /* Nuke the colon, advance to the name */
- *s++ = '\0';
-
- /* Paranoia -- require a name */
- if (!*s) return (PARSE_ERROR_GENERIC);
-
- /* Get the index */
- i = atoi(buf+2);
-
- /* Verify information */
- if (i <= error_idx) return (PARSE_ERROR_NON_SEQUENTIAL_RECORDS);
-
- /* Verify information */
- if (i >= head->info_num) return (PARSE_ERROR_TOO_MANY_ENTRIES);
-
- /* Save the index */
- error_idx = i;
-
- /* Point at the "info" */
- r_ptr = (monster_race*)head->info_ptr + i;
-
- /* Store the name */
- if ((r_ptr->name = add_name(head, s)) == 0)
- return (PARSE_ERROR_OUT_OF_MEMORY);
-
- return 0;
- }
-
- /* There better be a current r_ptr */
- if (!r_ptr) return (PARSE_ERROR_MISSING_RECORD_HEADER);
-
- /* Process 'D' for "Description" */
- if (buf[0] == 'D')
- {
- /* Store the text */
- if (!add_text(&(r_ptr->text), head, buf+2))
- return (PARSE_ERROR_OUT_OF_MEMORY);
- }
-
- /* Process 'G' for "Graphics" (one line only) */
- else if (buf[0] == 'G')
- {
- char d_char;
- int d_attr;
-
- /* Paranoia */
- if (!buf[2]) return (PARSE_ERROR_GENERIC);
- if (!buf[3]) return (PARSE_ERROR_GENERIC);
- if (!buf[4]) return (PARSE_ERROR_GENERIC);
-
- /* Extract d_char */
- d_char = buf[2];
-
- /* If we have a longer string than expected ... */
- if (buf[5])
- {
- /* Advance "buf" on by 4 */
- buf += 4;
-
- /* Extract the colour */
- d_attr = color_text_to_attr(buf);
- }
- else
- {
- /* Extract the attr */
- d_attr = color_char_to_attr(buf[4]);
- }
-
- /* Paranoia */
- if (d_attr < 0) return (PARSE_ERROR_GENERIC);
-
- /* Save the values */
- r_ptr->d_attr = d_attr;
- r_ptr->d_char = d_char;
- }
-
- /* Process 'I' for "Info" (one line only) */
- else if (buf[0] == 'I')
- {
- int spd, lif, aaf, ac, slp;
-
- /* Scan for the other values */
- if (5 != sscanf(buf+2, "%d:%d:%d:%d:%d",
- &spd, &lif, &aaf, &ac, &slp)) return (PARSE_ERROR_GENERIC);
-
- /* Save the values */
- r_ptr->speed = spd;
- r_ptr->avg_hp = lif;
- r_ptr->aaf = aaf;
- r_ptr->ac = ac;
- r_ptr->sleep = slp;
- }
-
- /* Process 'W' for "More Info" (one line only) */
- else if (buf[0] == 'W')
- {
- int lev, rar, pad;
- long exp;
-
- /* Scan for the values */
- if (4 != sscanf(buf+2, "%d:%d:%d:%ld",
- &lev, &rar, &pad, &exp)) return (PARSE_ERROR_GENERIC);
-
- /* Save the values */
- r_ptr->level = lev;
- r_ptr->rarity = rar;
- r_ptr->power = pad;
- r_ptr->mexp = exp;
- }
-
- /* Process 'B' for "Blows" */
- else if (buf[0] == 'B')
- {
- int n1, n2;
-
- /* Find the next empty blow slot (if any) */
- for (i = 0; i < MONSTER_BLOW_MAX; i++) if (!r_ptr->blow[i].method) break;
-
- /* Oops, no more slots */
- if (i == MONSTER_BLOW_MAX)
- return (PARSE_ERROR_TOO_MANY_ENTRIES);
-
- /* Analyze the first field */
- for (s = t = buf+2; *t && (*t != ':'); t++) /* loop */;
-
- /* Terminate the field (if necessary) */
- if (*t == ':') *t++ = '\0';
-
- /* Analyze the method */
- for (n1 = 0; r_info_blow_method[n1]; n1++)
- {
- if (streq(s, r_info_blow_method[n1])) break;
- }
-
- /* Invalid method */
- if (!r_info_blow_method[n1]) return (PARSE_ERROR_UNRECOGNISED_BLOW);
-
- /* Analyze the second field */
- for (s = t; *t && (*t != ':'); t++) /* loop */;
-
- /* Terminate the field (if necessary) */
- if (*t == ':') *t++ = '\0';
-
- /* Analyze effect */
- for (n2 = 0; r_info_blow_effect[n2]; n2++)
- {
- if (streq(s, "")) break;
- if (streq(s, r_info_blow_effect[n2])) break;
- }
-
- /* Invalid effect */
- if (!r_info_blow_effect[n2]) return (PARSE_ERROR_UNRECOGNISED_BLOW);
-
- /* Analyze the third field */
- for (s = t; *t && (*t != 'd'); t++) /* loop */;
-
- /* Terminate the field (if necessary) */
- if (*t == 'd') *t++ = '\0';
-
- /* Save the method */
- r_ptr->blow[i].method = n1;
-
- /* Save the effect */
- r_ptr->blow[i].effect = n2;
-
- /* Extract the damage dice and sides */
- r_ptr->blow[i].d_dice = atoi(s);
- r_ptr->blow[i].d_side = atoi(t);
- }
-
- /* Process 'F' for "Basic Flags" (multiple lines) */
- else if (buf[0] == 'F')
- {
- /* Parse every entry */
- for (s = buf + 2; *s; )
- {
- /* Find the end of this entry */
- for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
-
- /* Nuke and skip any dividers */
- if (*t)
- {
- *t++ = '\0';
- while (*t == ' ' || *t == '|') t++;
- }
-
- /* Parse this entry */
- if (0 != grab_flag(r_ptr->flags, RF_SIZE, r_info_flags, s))
- return (PARSE_ERROR_INVALID_FLAG);
-
- /* Start the next entry */
- s = t;
- }
- }
-
- /* Process 'S' for "Spell Flags" (multiple lines) */
- else if (buf[0] == 'S')
- {
- /* Parse every entry */
- for (s = buf + 2; *s; )
- {
- /* Find the end of this entry */
- for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
-
- /* Nuke and skip any dividers */
- if (*t)
- {
- *t++ = '\0';
- while ((*t == ' ') || (*t == '|')) t++;
- }
-
- /* XXX Hack -- Read spell frequency */
- if (1 == sscanf(s, "1_IN_%d", &i))
- {
- /* Sanity check */
- if ((i < 1) || (i > 100))
- return (PARSE_ERROR_INVALID_SPELL_FREQ);
-
- /* Extract a "frequency" */
- r_ptr->freq_spell = r_ptr->freq_innate = 100 / i;
-
- /* Start at next entry */
- s = t;
-
- /* Continue */
- continue;
- }
-
- /* Parse this entry */
- if (0 != grab_flag(r_ptr->spell_flags, RSF_SIZE, r_info_spell_flags, s))
- return (PARSE_ERROR_INVALID_FLAG);
-
- /* Start the next entry */
- s = t;
- }
- }
- else
- {
- /* Oops */
- return (PARSE_ERROR_UNDEFINED_DIRECTIVE);
- }
-
-
- /* Success */
- return (0);
- }
-
-
- /*
- * Helper function for reading a list of skills
- */
- static bool parse_skills(s16b *skills_array, const char *buf)
- {
- int dis, dev, sav, stl, srh, fos, thn, thb, throw, dig;
-
- /* Scan for the values */
- if (SKILL_MAX != sscanf(buf, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
- &dis, &dev, &sav, &stl, &srh,
- &fos, &thn, &thb, &throw, &dig))
- return FALSE;
-
- /* Save the values */
- skills_array[SKILL_DISARM] = dis;
- skills_array[SKILL_DEVICE] = dev;
- skills_array[SKILL_SAVE] = sav;
- skills_array[SKILL_STEALTH] = stl;
- skills_array[SKILL_SEARCH] = srh;
- skills_array[SKILL_SEARCH_FREQUENCY] = fos;
- skills_array[SKILL_TO_HIT_MELEE] = thn;
- skills_array[SKILL_TO_HIT_BOW] = thb;
- skills_array[SKILL_TO_HIT_THROW] = throw;
- skills_array[SKILL_DIGGING] = dig;
-
- return TRUE;
- }
-
-
- /*
- * Initialize the "p_info" array, by parsing an ascii "template" file
- */
- errr parse_p_info(char *buf, header *head)
- {
- int i, j;
-
- char *s, *t;
-
- /* Current entry */
- static player_race *pr_ptr = NULL;
-
-
- /* Process 'N' for "New/Number/Name" */
- if (buf[0] == 'N')
- {
- /* Find the colon before the name */
- s = strchr(buf+2, ':');
-
- /* Verify that colon */
- if (!s) return (PARSE_ERROR_MISSING_COLON);
-
- /* Nuke the colon, advance to the name */
- *s++ = '\0';
-
- /* Paranoia -- require a name */
- if (!*s) return (PARSE_ERROR_MISSING_FIELD);
-
- /* Get the index */
- i = atoi(buf+2);
-
- /* Verify information */
- if (i <= error_idx) return (PARSE_ERROR_NON_SEQUENTIAL_RECORDS);
-
- /* Verify information */
- if (i >= head->info_num) return (PARSE_ERROR_TOO_MANY_ENTRIES);
-
- /* Save the index */
- error_idx = i;
-
- /* Point at the "info" */
- pr_ptr = (player_race*)h…
Large files files are truncated, but you can click here to view the full file