/* * Copyright (c) 1989 James E. Wilson, Robert A. Koeneke * * 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. */ #include "files.hpp" #include "files.h" #include "cave.hpp" #include "cave_type.hpp" #include "corrupt.hpp" #include "cmd3.hpp" #include "dungeon_info_type.hpp" #include "feature_type.hpp" #include "hiscore.hpp" #include "hook_chardump_in.hpp" #include "hooks.hpp" #include "init1.hpp" #include "levels.hpp" #include "loadsave.h" #include "loadsave.hpp" #include "mimic.hpp" #include "monoid.hpp" #include "monster2.hpp" #include "monster3.hpp" #include "monster_ego.hpp" #include "monster_race.hpp" #include "monster_race_flag.hpp" #include "monster_type.hpp" #include "notes.hpp" #include "object1.hpp" #include "object2.hpp" #include "object_flag.hpp" #include "object_flag_meta.hpp" #include "object_kind.hpp" #include "options.hpp" #include "player_class.hpp" #include "player_race.hpp" #include "player_race_flag.hpp" #include "player_race_mod.hpp" #include "player_spec.hpp" #include "player_type.hpp" #include "skills.hpp" #include "spells2.hpp" #include "store_info_type.hpp" #include "store_type.hpp" #include "tables.hpp" #include "town_type.hpp" #include "trap_type.hpp" #include "util.hpp" #include "util.h" #include "variable.h" #include "variable.hpp" #include "wilderness_map.hpp" #include "wilderness_type_info.hpp" #include "xtra1.hpp" #include "z-rand.hpp" #include #include #include #include #include #include /* * Extract the first few "tokens" from a buffer * * This function uses "colon" and "slash" and delim arg as the delimeter characters. * * We never extract more than "num" tokens. The "last" token may include * "delimeter" characters, allowing the buffer to include a "string" token. * * We save pointers to the tokens in "tokens", and return the number found. * * Hack -- Attempt to handle the 'c' character formalism * * Hack -- An empty buffer, or a final delimeter, yields an "empty" token. * * Hack -- We will always extract at least one token */ s16b tokenize(char *buf, s16b num, char **tokens, char delim1, char delim2) { int i = 0; char *s = buf; /* Process */ while (i < num - 1) { char *t; /* Scan the string */ for (t = s; *t; t++) { /* Found a delimiter */ if ((*t == delim1) || (*t == delim2)) break; /* Handle single quotes */ if (*t == '\'') { /* Advance */ t++; /* Handle backslash */ if (*t == '\\') t++; /* Require a character */ if (!*t) break; /* Advance */ t++; /* Hack -- Require a close quote */ if (*t != '\'') *t = '\''; } /* Handle back-slash */ if (*t == '\\') t++; } /* Nothing left */ if (!*t) break; /* Nuke and advance */ *t++ = '\0'; /* Save the token */ tokens[i++] = s; /* Advance */ s = t; } /* Save the token */ tokens[i++] = s; /* Number found */ return (i); } /* * Parse a sub-file of the "extra info" (format shown below) * * Each "action" line has an "action symbol" in the first column, * followed by a colon, followed by some command specific info, * usually in the form of "tokens" separated by colons or slashes. * * Blank lines, lines starting with white space, and lines starting * with pound signs ("#") are ignored (as comments). * * Note the use of "tokenize()" to allow the use of both colons and * slashes as delimeters, while still allowing final tokens which * may contain any characters including "delimiters". * * Note the use of "strtol()" to allow all "integers" to be encoded * in decimal, hexidecimal, or octal form. * * Note that "monster zero" is used for the "player" attr/char, "object * zero" will be used for the "stack" attr/char, and "feature zero" is * used for the "nothing" attr/char. * * Parse another file recursively, see below for details * %: * * Specify the attr/char values for "monsters" by race index * R::: * * Specify the attr/char values for "objects" by kind index * K::: * * Specify the attr/char values for "features" by feature index * F::: * * Specify the attr/char values for "stores" by store index * B::: * * Specify the attr/char values for unaware "objects" by kind tval * U::: * * Specify the attr/char values for inventory "objects" by kind tval * E::: * * Define a macro action, given an encoded macro action * A: * * Create a normal macro, given an encoded macro trigger * P: * * Create a command macro, given an encoded macro trigger * C: * * Create a keyset mapping * S::: * * Turn an option off, given its name * X: * * Turn an option on, given its name * Y: * * Specify visual information, given an index, and some data * V::::: * * Specify squelch settings * Q:: */ errr process_pref_file_aux(char *buf) { int i, j, n1, n2; char *zz[16]; /* Skip "empty" lines */ if (!buf[0]) return (0); /* Skip "blank" lines */ if (isspace(buf[0])) return (0); /* Skip comments */ if (buf[0] == '#') return (0); /* Require "?:*" format */ if (buf[1] != ':') return (1); /* Process "%:" */ if (buf[0] == '%') { /* Attempt to Process the given file */ return (process_pref_file(buf + 2)); } /* Process "R::/" -- attr/char for monster races */ if (buf[0] == 'R') { if (tokenize(buf + 2, 3, zz, ':', '/') == 3) { monster_race *r_ptr; i = (huge)strtol(zz[0], NULL, 0); n1 = strtol(zz[1], NULL, 0); n2 = strtol(zz[2], NULL, 0); if (i >= max_r_idx) return (1); r_ptr = &r_info[i]; if (n1) r_ptr->x_attr = n1; if (n2) { r_ptr->x_char = n2; } return (0); } } /* Process "G:::/" -- attr/char for overlay graphics */ if (buf[0] == 'G') { /* Process "G:M::/" -- attr/char for ego monsters */ if (buf[2] == 'M') { if (tokenize(buf + 4, 3, zz, ':', '/') == 3) { monster_ego *re_ptr; i = (huge)strtol(zz[0], NULL, 0); n1 = strtol(zz[1], NULL, 0); n2 = strtol(zz[2], NULL, 0); if (i >= max_re_idx) return (1); re_ptr = &re_info[i]; if (n1) re_ptr->g_attr = n1; if (n2) { re_ptr->g_char = n2; } return (0); } } /* Process "G:P::/" -- attr/char for race modifiers */ if (buf[2] == 'P') { if (tokenize(buf + 4, 3, zz, ':', '/') == 3) { player_race_mod *rmp_ptr; i = (huge)strtol(zz[0], NULL, 0); n1 = strtol(zz[1], NULL, 0); n2 = strtol(zz[2], NULL, 0); if (i >= max_rmp_idx) return (1); rmp_ptr = &race_mod_info[i]; if (n1) rmp_ptr->g_attr = n1; if (n2) { rmp_ptr->g_char = n2; } return (0); } } /* Process "G:T::/" -- attr/char for traps */ if (buf[2] == 'T') { if (tokenize(buf + 4, 3, zz, ':', '/') == 3) { trap_type *t_ptr; i = (huge)strtol(zz[0], NULL, 0); n1 = strtol(zz[1], NULL, 0); n2 = strtol(zz[2], NULL, 0); if (i >= max_t_idx) return (1); t_ptr = &t_info[i]; if (n1) t_ptr->g_attr = n1; if (n2) { t_ptr->g_char = n2; } return (0); } } } /* Process "K::/" -- attr/char for object kinds */ else if (buf[0] == 'K') { if (tokenize(buf + 2, 3, zz, ':', '/') == 3) { object_kind *k_ptr; i = (huge)strtol(zz[0], NULL, 0); n1 = strtol(zz[1], NULL, 0); n2 = strtol(zz[2], NULL, 0); if (i >= max_k_idx) return (1); k_ptr = &k_info[i]; if (n1) k_ptr->x_attr = n1; if (n2) { k_ptr->x_char = n2; } return (0); } } /* Process "F::/" -- attr/char for terrain features */ else if (buf[0] == 'F') { if (tokenize(buf + 2, 3, zz, ':', '/') == 3) { feature_type *f_ptr; i = (huge)strtol(zz[0], NULL, 0); n1 = strtol(zz[1], NULL, 0); n2 = strtol(zz[2], NULL, 0); if (i >= max_f_idx) return (1); f_ptr = &f_info[i]; if (n1) f_ptr->x_attr = n1; if (n2) { f_ptr->x_char = n2; } return (0); } } /* Process "B::/" -- attr/char for stores */ else if (buf[0] == 'B') { if (tokenize(buf + 2, 3, zz, ':', '/') == 3) { store_info_type *st_ptr; i = (huge)strtol(zz[0], NULL, 0); n1 = strtol(zz[1], NULL, 0); n2 = strtol(zz[2], NULL, 0); if (i >= max_st_idx) return (1); st_ptr = &st_info[i]; if (n1) st_ptr->x_attr = n1; if (n2) st_ptr->x_char = n2; return (0); } } /* Process "S::/" -- attr/char for special things */ else if (buf[0] == 'S') { if (tokenize(buf + 2, 3, zz, ':', '/') == 3) { j = (byte)strtol(zz[0], NULL, 0); n1 = strtol(zz[1], NULL, 0); n2 = strtol(zz[2], NULL, 0); misc_to_attr[j] = n1; misc_to_char[j] = n2; return (0); } } /* Process "U::/" -- attr/char for unaware items */ else if (buf[0] == 'U') { if (tokenize(buf + 2, 3, zz, ':', '/') == 3) { j = (huge)strtol(zz[0], NULL, 0); n1 = strtol(zz[1], NULL, 0); n2 = strtol(zz[2], NULL, 0); for (i = 1; i < max_k_idx; i++) { object_kind *k_ptr = &k_info[i]; if (k_ptr->tval == j) { if (n1) k_ptr->d_attr = n1; if (n2) k_ptr->d_char = n2; } } return (0); } } /* Process "E::" -- attribute for inventory objects */ else if (buf[0] == 'E') { if (tokenize(buf + 2, 2, zz, ':', '/') == 2) { j = (byte)strtol(zz[0], NULL, 0) % 128; n1 = strtol(zz[1], NULL, 0); if (n1) tval_to_attr[j] = n1; return (0); } } /* Process "A:" -- save an "action" for later */ else if (buf[0] == 'A') { text_to_ascii(macro__buf, buf + 2); return (0); } /* Process "P:" -- normal macro */ else if (buf[0] == 'P') { char tmp[1024]; text_to_ascii(tmp, buf + 2); macro_add(tmp, macro__buf); return (0); } /* Process "L::: -- extended command macro */ else if (buf[0] == 'L') { switch (tokenize(buf + 2, 3, zz, ':', 0)) { case 3: cli_add(zz[0], zz[1], zz[2]); return 0; case 2: cli_add(zz[0], zz[1], 0); return 0; default: return 1; } } /* Process "C:" -- create keymap */ else if (buf[0] == 'C') { int mode; char tmp[1024]; if (tokenize(buf + 2, 2, zz, ':', '/') != 2) return (1); mode = strtol(zz[0], NULL, 0); if ((mode < 0) || (mode >= KEYMAP_MODES)) return (1); text_to_ascii(tmp, zz[1]); if (!tmp[0] || tmp[1]) return (1); i = (byte)(tmp[0]); free(keymap_act[mode][i]); keymap_act[mode][i] = strdup(macro__buf); return (0); } /* Process "V:::::" -- visual info */ else if (buf[0] == 'V') { if (tokenize(buf + 2, 5, zz, ':', '/') == 5) { i = (byte)strtol(zz[0], NULL, 0); angband_color_table[i][0] = (byte)strtol(zz[1], NULL, 0); angband_color_table[i][1] = (byte)strtol(zz[2], NULL, 0); angband_color_table[i][2] = (byte)strtol(zz[3], NULL, 0); angband_color_table[i][3] = (byte)strtol(zz[4], NULL, 0); return (0); } } /* set macro trigger names and a template */ /* Process "T:::" */ /* Process "T: