/****************************************************************************
* The purpose of this file is to boot the mud, or generate the headers for *
* objects or mobiles in the game. The first stage is the prepass step. *
* That eliminates the need for using cpp (which slows things down). It *
* builds hash tables, z_* for zone names. n_* is for in-game Pnames. *
* Then it links all the locations (by freeing the text descriptions, and *
* casting an int to the pointers), and performs all the necessary *
* assignments to get the game up and running. *
****************************************************************************/
#include <stdio.h>
#include <sys/file.h>
#include <dirent.h>
#include <string.h>
#include <malloc.h>
#include <stdlib.h>
#include "bootstrap.h"
#include "global.h"
#include "wizlist.h"
#include "actions.h"
#include "zones.h"
#include "bprintf.h"
#include "mobile.h"
#include "fight.h"
#undef DEBUG
void add_tree(T_elemptr *, char *, int);
#ifdef GEN
#include "flagindex.h"
int make_verbs(void) {
FILE *In, *Out, *H;
char *p, *q;
int vcode, num_v;
XTABLE *first, *last, *v, *w;
char buff[128], verb[30];
if (!(In = fopen(DATA_DIR "/verbs.src", "r"))) {
printf("Unable to open %s for input\n", DATA_DIR "/verbs.src");
exit(1);
}
if (!(Out = fopen(DATA_DIR "/verbs", "w"))) {
printf("Unable to open %s for output.\n", DATA_DIR "/verbs");
exit(1);
}
if (!(H = fopen(H_DIR "/verbs.h", "w"))) {
printf("Unable to open %s for output\n", DATA_DIR "/verbs.h");
exit(1);
}
first = last = NULL;
vcode = num_v = 0;
while (fgets (buff, sizeof buff, In)) {
for (p = buff, q = verb; isalpha (*p);)
*q++ = *p++;
if (q == verb)
continue;
*q = 0;
lowercase (verb);
v = (XTABLE *) NEW(XTABLE, 1);
strcpy (v->name, verb);
++num_v;
if (*p != '=')
v->code = ++vcode;
else {
for (q = verb, ++p; isalpha (*p);)
*q++ = *p++;
*q = 0;
lowercase (verb);
for (w = first; w != NULL && strcmp (w->name, verb) != 0; w = w->next);
if (w == NULL)
v->code = ++vcode;
else
v->code = w->code;
}
v->next = NULL;
if (first == NULL)
first = last = v;
else
last = (last->next = v);
}
fclose (In);
fprintf (H, "\
/*\n\
**\tVerb file header generated from verbs.src\n\
**\tDON'T MAKE CHANGES HERE -- THEY WILL GO AWAY!\n\
*/\n\n\
#ifndef _VERBS_H\n\
#define _VERBS_H\n\n");
fprintf (Out, "%d\n", num_v);
for (w = first; w != NULL; w = w->next) {
strcpy (verb, w->name);
(void) fprintf (Out, "%s %d\n", verb, w->code);
uppercase (verb);
(void) fprintf (H, "#define\tVERB_%s\t%d\n", verb, w->code);
}
fclose (Out);
fprintf (H, "\n#endif\n");
fclose (H);
return(num_v);
}
int main(void) {
int verbs;
bootstrap();
verbs = make_verbs();
fprintf(stderr, "\nThe world: [%d Objects | %d Mobiles | %d Locations "
"| %d Verbs]\n", numobs, numchars, numloc, verbs);
return(0);
}
#endif
void set_flagpoints(void) {
int i, a, b, sum;
b = oindex[0];
oindex[0] = 0;
for (i = 1, sum = 1 ; i < MAX_OBJ_FLAGS + 1 ; i++) {
a = oindex[i];
oindex[i] = (b / 32) + sum;
b = a;
sum = oindex[i] + 1;
}
b = mindex[0];
mindex[0] = 0;
for (i = 1, sum = 1 ; i < MAX_MOB_FLAGS + 1 ; i++) {
a = mindex[i];
mindex[i] = (b / 32) + sum;
b = a;
sum = mindex[i] + 1;
}
b = lindex[0];
lindex[0] = 0;
for (i = 1, sum = 1 ; i < MAX_LOC_FLAGS + 1 ; i++) {
a = lindex[i];
lindex[i] = (b / 32) + sum;
b = a;
sum = lindex[i] + 1;
}
b = windex[0];
windex[0] = 0;
for (i = 1, sum = 1 ; i < MAX_WORLD_FLAGS + 1 ; i++) {
a = windex[i];
windex[i] = (b / 32) + sum;
b = a;
sum = windex[i] + 1;
}
b = pflindex[0];
pflindex[0] = 0;
for (i = 1, sum = 1 ; i < MAX_PFL_FLAGS + 1 ; i++) {
a = pflindex[i];
pflindex[i] = (b / 32) + sum;
b = a;
sum = pflindex[i] + 1;
}
}
int bootstrap(void) {
char buff[256];
struct dirent **namelist;
int n, x;
xzon = 0;
x = scandir(ZONE_DIR, &namelist, 0, NULL);
if (x < 0) {
perror("scandir");
return(-1);
}
set_flagpoints();
#ifndef GEN
numchars = max_players;
if (boot_verbs() == -1) {
fprintf(stderr, "\nVerb boot failed.\n");
return(1);
}
else if (boot_pflags() == -1) {
fprintf(stderr, "\nPflags boot failed.\n");
return(1);
}
else if (boot_wizlist() == -1) {
fprintf(stderr, "\nBoot wizlist failed.\n");
return(1);
}
else if (boot_actions() == -1) {
fprintf(stderr, "\nBoot actions failed.\n");
return(1);
}
#endif
boot_arrays(x);
for (n = x - 1 ; n > 0 ; n--) {
if (namelist[n]->d_name[0] == '.' || !valid_zone(namelist[n]->d_name))
continue;
else {
sprintf(buff, "%s/%s", ZONE_DIR, namelist[n]->d_name);
if (!old_proc_num && !(n % (x > 9 ? (x/10) : 1)))
fprintf(stderr, ".");
if (process_zone(buff, False, False) == -1) {
fprintf(stderr, "\nFailure at zone: %s\n", namelist[n]->d_name);
return(-1);
}
numzon = ++xzon;
resize_zones();
}
}
#ifdef GEN
if (link_zones() == -1) {
fprintf(stderr, "\nFailure linking zones.\n");
return(-2);
}
else if (store_headers() == -1) {
fprintf(stderr, "\nFailure storing headers.\n");
return(-3);
}
#else
if (link_zones() == -1) {
fprintf(stderr, "\nFailure linking zones.\n");
return(-2);
}
num_const_locs = numloc;
num_const_chars = numchars;
num_const_obs = numobs;
num_const_zon = numzon;
if (!old_proc_num)
fprintf(stderr, "Linked.\n");
#endif
return(0);
}
int boot_arrays(int bzones) {
#ifndef GEN
players = NEW (PLAYER_REC, max_players);
rplrs = NEW (RPLR_REC, max_players);
iplrs = NEW (IO_REC, max_players);
#endif
zones = NEW (ZONE, bzones * 2);
ublock = NEW (UBLOCK_REC, bzones * BASEMULT);
objs = NEW (OBJECT, bzones * BASEMULT);
room_data = NEW (Location, bzones * BASEMULT);
ublock_len = bzones * BASEMULT;
objects_len = bzones * BASEMULT;
locations_len = bzones * BASEMULT;
zones_len = bzones * 2;
return(0);
}
#ifndef GEN
int boot_verbs (void) {
int numverbs, i, verbnum;
FILE *fpr;
char verbstr[64];
if (!(fpr = fopen(DATA_DIR "/verbs", "r"))) {
fprintf(stderr, "\nUnable to load verbs file.\n");
return(-1);
}
verb_t = NULL;
fscanf (fpr, "%d", &numverbs);
for (i = 0; i < numverbs; i++) {
fscanf (fpr, "%s %d", verbstr, &verbnum);
add_tree(&verb_t, verbstr, verbnum);
}
return(0);
}
#endif
Boolean valid_zone(char *file) {
char *p;
if ((p = strstr(file, ".zone"))) {
if (strlen(p) == strlen(".zone"))
return(True);
}
return(False);
}
#ifndef GEN
void load_zone(char *player, Boolean silent) {
int numloc_p = numloc;
int numobs_p = numobs;
int numchars_p = numchars;
Boolean empty;
char buff[256];
sprintf(buff, "%s/%s", WIZ_ZONE_DIR, player);
xzon = get_wizzone_by_name(player);
empty = (!znumloc(xzon) && !znumchars(xzon) && !znumobs(xzon));
process_zone(buff, empty, silent);
link_zone(xzon);
reset_zone(xzon);
if (!(numloc - numloc_p) && !(numobs - numobs_p) && !(numchars-numchars_p)) {
if (!silent)
bprintf("Zone %s: No new objects, mobiles, or locations loaded.\n",
pname(mynum));
return;
}
else {
if (!silent)
bprintf("Zone %s loaded: [%d object%s | %d mobile%s, %d location%s]\n",
pname(mynum), zmaxobjs(xzon), zmaxobjs(xzon) != 1 ? "s" : "",
zmaxmobs(xzon), zmaxmobs(xzon) != 1 ? "s" : "",
zmaxlocs(xzon), zmaxlocs(xzon) != 1 ? "s" : "");
return;
}
}
#endif
int process_zone(char *file, Boolean empty, Boolean silent) {
FILE *fptr;
char *line;
char buff[BUFFLEN];
Boolean in_comment = False;
Boolean in_quote = False;
Boolean in_hat = False;
if (!(fptr = fopen(file, "r"))) {
#ifdef GEN
if (!silent)
fprintf(stderr, "\nError in fopen(): unable to open zone file.\n");
#else
if (!silent)
bprintf("Unable to load your wiz-zone, sorry.\n");
#endif
return(-1);
}
else {
setup_zone(empty, strrchr(file, '/') + 1);
while (!feof(fptr)) {
fgets(buff, BUFFLEN - 1, fptr);
if (!(line = prepass(&in_comment, &in_quote, &in_hat, buff)))
return(-1);
else if (in_quote || in_hat)
continue;
if (!EMPTY(line) && *line != '#' && *line != '\n') {
if (*line == '%') {
if (set_zone_global(line+1) == -1)
return(-1);
}
else {
switch (loading) {
case PROC_MOBILES:
if (proc_mobile(line) == -1)
return(-1);
break;
case PROC_LOCATIONS:
if (proc_location(line) == -1)
return(-1);
break;
case PROC_OBJECTS:
if (proc_object(line) == -1)
return(-1);
break;
default:
fprintf(stderr, "\nAll mobiles must be defined after a %%mobiles, etc."
"Line failed: %s\n", line);
return(-1);
break;
}
}
}
}
fclose(fptr);
}
return(0);
}
int get_key_value(char *buff, char **key, char **value) {
char *p;
for (p = buff ; *p ; p++) /* skip over leading whitespaces */
if (!isspace(*p) && *p != '\t')
break;
*key = p;
while (*p++) /* skip over keyword or whatever */
if (isspace(*p) || *p == '\t')
break;
*p = 0;
for (++p ; *p ; p++) /* skip over whitespace after keyword */
if (!isspace(*p) && *p != '=' && *p != '\t')
break;
*value = p;
if (!**key)
return(-1);
return(0);
}
int string2num(int *num, char *str) {
char *p;
for (p = str ; *p ; p++)
if (!isdigit(*p) && *p != '-')
break;
if (*p != 0)
return(-1);
*num = atoi(str);
return(0);
}
void resize_zones(void) {
if (numzon < zones_len)
return;
zones = (ZONE *) resize_array(zones, sizeof(ZONE), zones_len,
zones_len + BASE_INCR/10);
zones_len += BASE_INCR/10;
}
void resize_ublock(void) {
if (numchars < ublock_len)
return;
ublock = (UBLOCK_REC *) resize_array(ublock, sizeof(UBLOCK_REC),
ublock_len, ublock_len + BASE_INCR);
ublock_len += BASE_INCR;
}
void resize_objects(void) {
if (numobs < objects_len)
return;
objs = (OBJECT *) resize_array(objs, sizeof(OBJECT),
objects_len, objects_len + BASE_INCR);
objects_len += BASE_INCR;
}
void resize_locs(void) {
if (numloc < locations_len)
return;
room_data = (Location *) resize_array(room_data, sizeof(Location),
locations_len, locations_len + BASE_INCR);
locations_len += BASE_INCR;
}
/* resets all bits to zero, then loads alphanumeric flags */
int proc_flags(int flagset, long int *bits, int index[],
char *flsetname, char *flagnames[], char *buff) {
char *p, *q;
int rslt, i;
for (p = buff ; *p ; p++)
if (*p == '{') {
p++;
break;
}
if (!*p) {
fprintf(stderr, "\n%s: missing {\n", flsetname);
return(-1);
}
else {
for (q = p ; *q ; q++)
if (*q == '}')
break;
if (!*q) {
fprintf(stderr, "\n%s: missing }\n", flsetname);
return(-1);
}
else {
for (i = index[flagset] ; i < index[flagset+1] ; i++)
bits[i] = 0;
*q = 0;
while (*p) {
while(isspace(*p))
p++;
if ((q = strchr(p, ' ')))
*q++ = 0;
else
q = p + strlen(p);
if ((rslt = tlookup(p, flagnames)) != -1) {
#ifndef GEN
if (*p) {
if (index == lindex)
set_bit(bits, lindex, rslt, True, flagset);
else if (index == mindex)
set_bit(bits, mindex, rslt, True, flagset);
else if (index == oindex)
set_bit(bits, oindex, rslt, True, flagset);
}
#endif
}
else {
fprintf(stderr, "\nUnknown %s: %s\n", flsetname, p);
return(-1);
}
p = q;
}
return(0);
}
}
}
int proc_mobile(char *buff) {
int rslt, i;
static char name[MNAME_LEN] = "";
char *key, *value, flagsbuff[32];
if (get_key_value(buff, &key, &value) == -1) {
fprintf(stderr, "\nError: KEY = VALUE expected. Got %s\n", buff);
return(-1);
}
else {
i = tlookup(key, mobtab);
switch(i) {
case 0: /* Name */
if (strlen(value) > MNAME_LEN) {
fprintf(stderr, "\nMobile %s length exceeds %d.\n", value, MNAME_LEN);
return(-1);
}
else if (*name) {
fprintf(stderr, "\nMobile %s has no End statement.\n", name);
return(-1);
}
else {
strcpy(name, value);
if ((rslt = ht_lookup(ublock_z, name, 0, xzon, mob_search)) != -1) {
ht_remove(ublock_z, name, rslt);
ht_remove(ublock_n, pname(rslt), rslt);
xchar = rslt;
}
else { /* Mobile doesn't already exist */
zmaxmobs(xzon)++;
xchar = numchars++;
zadd_mob(xchar, xzon);
resize_ublock();
}
#ifndef GEN
memset(&ublock[xchar], 0, sizeof(UBLOCK_REC)); /* for clone */
#endif
setpname(xchar, value);
pname_reset(xchar) = value;
}
break;
case 1: /* Pname */
if (strlen(value) > MNAME_LEN) {
fprintf(stderr, "\n%s exceeds %d chars.\n", value, MNAME_LEN);
return(-1);
}
else {
setpname(xchar, value);
pname_reset(xchar) = value;
}
break;
case 2: /* Location */
ublock[xchar].ploc_reset = (int) COPY(value);
break;
case 3: /* Strength */
if (string2num(&rslt, value) == -1) {
fprintf(stderr, "\nError in mob %s: Strength expects num.\n", name);
return(-1);
}
else
ublock[xchar].pstr_reset = rslt;
break;
case 4: /* Damage */
if (string2num(&rslt, value) == -1) {
fprintf(stderr, "\nError in mob %s: Damage expects num.\n", name);
return(-1);
}
else
ublock[xchar].pdam_reset = rslt;
break;
case 5: /* Aggression */
if (string2num(&rslt, value) == -1) {
fprintf(stderr, "\nError in mob %s: Aggression expects num.\n", name);
return(-1);
}
else
ublock[xchar].pagg_reset = rslt;
break;
case 6: /* Armor */
if (string2num(&rslt, value) == -1) {
fprintf(stderr, "\nError in mob %s: Armor expects num.\n", name);
return(-1);
}
else
parmor_reset(xchar) = rslt;
break;
case 7: /* Speed */
if (string2num(&rslt, value) == -1) {
fprintf(stderr, "\nError in mob %s: Speed expects num.\n", name);
return(-1);
}
else
pspeed_reset(xchar) = rslt;
break;
case 8: /* Description */
pftxt(xchar) = COPY(value);
break;
case 9: /* End */
if (!*name) {
fprintf(stderr, "\nMobile %s has no Begin statement.\n", value);
return(-1);
}
else if (!EQ(value, name)) {
fprintf(stderr, "\nMobile %s has no End statement.\n", name);
return(-1);
}
else if (!ublock[xchar].ploc_reset) {
fprintf(stderr, "\nMobile %s has no Location.\n", name);
return(-1);
}
else if (!pftxt(xchar)) {
fprintf(stderr, "\nMobile %s has no Description.\n", name);
return(-1);
}
else {
ht_add(ublock_z, name, xchar);
pname(xchar)[0] = toupper(pname(xchar)[0]);
pzname(xchar) = COPY(name);
pname_reset(xchar) = COPY(pname(xchar));
plev_reset(xchar) = -1;
ublock[xchar].unlinked = True;
#ifndef GEN
ht_add(ublock_n, xname(pname(xchar)), xchar);
set_vital(xchar);
set_player_parts(xchar);
init_intset (pinv (xchar), 4);
#endif
pzone(xchar) = xzon;
*name = 0;
}
break;
case 10:
pexam(xchar) = COPY(value);
break;
default:
sprintf(flagsbuff, "%sReset", key);
if ((rslt = tlookup(flagsbuff, Mobflags)) == -1) {
if (*name)
fprintf(stderr, "\nUnknown key in mobile %s: ", name);
else
fprintf(stderr, "\nUnknown key: ");
fprintf(stderr, "\n%s\n", key);
return(-1);
}
else
return(proc_flags(rslt, ublock[xchar].bits, mindex, flagsbuff,
mobflagsindex[rslt], value));
break;
}
}
return(0);
}
int proc_object(char *buff) {
int rslt, i;
static char name[ONAME_LEN] = "";
char *key, *value, flagsbuff[32];
if (get_key_value(buff, &key, &value) == -1) {
fprintf(stderr, "\nError: KEY = VALUE expected. Got %s\n", buff);
return(-1);
}
else {
i = tlookup(key, objtab);
switch(i) {
case 0: /* Name */
if (strlen(value) > ONAME_LEN) {
fprintf(stderr, "\nObjects %s length exceeds %d.\n", value, ONAME_LEN);
return(-1);
}
else if (*name) {
fprintf(stderr, "\nObject %s missing End statement.\n", name);
return(-1);
}
else {
strcpy(name, value);
if ((rslt = ht_lookup(objects_z, name, 0, xzon, obj_search)) != -1) {
ht_remove(objects_z, name, rslt);
ht_remove(objects_n, oname(rslt), rslt);
if (oaltname(rslt))
ht_remove(oalts_n, oaltname(rslt), rslt);
xobj = rslt;
}
else { /* object doesn't already exist */
resize_objects();
xobj = numobs++;
zadd_obj(xobj, xzon);
zmaxobjs(xzon)++;
}
#ifndef GEN
memset(&objs[xobj], 0, sizeof(OBJECT));
#endif
oname(xobj) = COPY(value);
}
break;
case 1: /* Pname */
if (strlen(value) > ONAME_LEN) {
fprintf(stderr, "\n%s exceeds %d chars.\n", name, ONAME_LEN);
return(-1);
}
else
oname(xobj) = COPY(value);
break;
case 2: /* AltName */
if (strlen(value) > ONAME_LEN) {
fprintf(stderr, "\n%s exceeds %d chars.\n", name, ONAME_LEN);
return(-1);
}
else {
oaltname(xobj) = COPY(value);
ht_add(oalts_n, value, xobj);
}
break;
case 3: /* Location */
objs[xobj].oloc_reset = (int) COPY(value);
break;
case 4: /* Linked */
objs[xobj].linked = (int) COPY(value);
break;
case 5: /* State */
if (string2num(&rslt, value) == -1) {
fprintf(stderr, "\nError in obj %s: State expects num.\n", name);
return(-1);
}
else
state_reset(xobj) = rslt;
break;
case 6: /* MaxState */
if (string2num(&rslt, value) == -1) {
fprintf(stderr, "\nError in obj %s: MaxState expects num.\n", name);
return(-1);
}
else
omaxstate(xobj) = rslt;
break;
case 7: /* Desc[0] */
olongt(xobj, 0) = COPY(value);
break;
case 8: /* Desc[1] */
olongt(xobj, 1) = COPY(value);
break;
case 9: /* Desc[2] */
olongt(xobj, 2) = COPY(value);
break;
case 10: /* Desc[3] */
olongt(xobj, 3) = COPY(value);
break;
case 11: /* Armor */
if (string2num(&rslt, value) == -1) {
fprintf(stderr, "\nError in obj %s: Armor expects num.\n", name);
return(-1);
}
else
oarmor_reset(xobj) = rslt;
break;
case 12: /* BValue */
if (string2num(&rslt, value) == -1) {
fprintf(stderr, "\nError in obj %s: BValue expects num.\n", name);
return(-1);
}
else
ovalue_reset(xobj) = rslt;
break;
case 13: /* Size */
if (string2num(&rslt, value) == -1) {
fprintf(stderr, "\nError in obj %s: Size expects num.\n", name);
return(-1);
}
else
osize_reset(xobj) = rslt;
break;
case 14: /* Weight */
if (string2num(&rslt, value) == -1) {
fprintf(stderr, "\nError in obj %s: Weight expects num.\n", name);
return(-1);
}
else
oweight_reset(xobj) = rslt;
break;
case 15: /* Examine */
objs[xobj].oexam_text = COPY(value);
break;
case 16: /* Damage */
if (string2num(&rslt, value) == -1) {
fprintf(stderr, "\nError in obj %s: Damage expects num.\n", name);
return(-1);
}
else
odamage_reset(xobj) = rslt;
break;
case 17: /* End */
if (!*name) {
fprintf(stderr, "\nObject %s has no Begin statement.\n", value);
return(-1);
}
if (!EQ(value, name)) {
fprintf(stderr, "\nObject %s has no End statement.\n", name);
return(-1);
}
else { /* finish up */
objs[xobj].unlinked = True;
oname(xobj)[0] = toupper(oname(xobj)[0]);
ht_add(objects_z, name, xobj);
ht_add(objects_n, oname(xobj), xobj);
ozname(xobj) = COPY(name);
#ifndef GEN
if (otstbit(xobj, OFL_CONTAINER))
init_intset(oinv(xobj), 5);
#endif
ozone(xobj) = xzon;
*name = 0;
}
break;
default:
sprintf(flagsbuff, "%sReset", key);
if ((rslt = tlookup(flagsbuff, Objflags)) == -1) {
if (*name)
fprintf(stderr, "\nUnknown key in object %s: ", name);
else
fprintf(stderr, "\nUnknown key: ");
fprintf(stderr, "\n%s\n", key);
return(-1);
}
else
return(proc_flags(rslt, objs[xobj].bits, oindex, flagsbuff,
oflagsindex[rslt], value));
break;
}
}
return(0);
}
char *posp(char *p) {
char *q;
for (q = p ; *q ; q++) {
if (*q == ';') {
*q = 0;
return(q);
}
else if (isspace(*q) && !isspace(*(q+1))) {
*q = 0;
return(q+1);
}
}
return(q);
}
int proc_location(char *buff) {
static int i = 0;
char *key, *value;
int rslt;
char *p, *q;
if (!strncasecmp(buff, "Altitude", strlen("Altitude"))) {
if (get_key_value(buff, &key, &value) == -1) {
fprintf(stderr, "\nError: KEY = VALUE expected. Got %s\n", buff);
return(-1);
}
else if (string2num(&rslt, value) == -1) {
fprintf(stderr, "\nAltitude expects a number.\n");
return(-1);
}
else
room_data[xloc].r_altitude_reset = rslt;
return(0);
}
if (i == 0) { /* first line in location */
i++;
for (p = buff ; *p ; p++) {
if (*p == ';') {
*p = 0;
if ((rslt = ht_lookup(locations_z, buff, 0, xzon, room_search)) != -1){
xloc = rslt;
ht_remove(locations_z, buff, rslt);
}
else { /* loc doesn't already exist */
xloc = numloc++;
zadd_loc (xloc, xzon);
zmaxlocs(xzon)++;
}
resize_locs();
#ifndef GEN
memset(&room_data[xloc], 0, sizeof(Location));
#endif
room_data[xloc].r_name = COPY(buff);
ht_add(locations_z, buff, xloc);
return(0);
}
else if (isspace(*p)) {
*p = 0;
if ((rslt = ht_lookup(locations_z, buff, 0, xzon, room_search)) != -1){
xloc = rslt;
ht_remove(locations_z, buff, rslt);
}
else {
xloc = numloc++;
zadd_loc (xloc, xzon);
zmaxlocs(xzon)++;
}
resize_locs();
room_data[xloc].r_name = COPY(buff);
ht_add(locations_z, buff, xloc);
break;
}
}
for (++p ; *p ; p++)
if (!isspace(*p))
break;
while (*p) {
if (*p == ';')
break;
else if (*(p+1) != ':' && *(p+2)) {
fprintf(stderr, "\nWas expecting <dir>:<room> Got: %s\n", p);
return(-1);
}
else if ((rslt = llookup(p, Exits)) == -1) {
fprintf(stderr, "\nUnknown exit in loc: %s\n", p);
return(-1);
}
else {
q = posp(p);
room_data[xloc].r_exit_reset[rslt] = (int) COPY(p+2);
if ((p = strchr((char *) room_data[xloc].r_exit_reset[rslt], ' ')))
*p = 0;
p = q;
}
}
}
else if (i == 1) { /* lflags line */
i++;
return(proc_flags(LFLAGS_RESET, room_data[xloc].bits, lindex,
"LflagsReset", Lflags, buff));
}
else { /* description */
i = 0;
for (p = buff ; *p ; p++) {
if (*p == '\n')
break;
}
*p++ = 0; /* finish up */
room_data[xloc].r_short = COPY(buff);
room_data[xloc].r_long = COPY(p);
room_data[xloc].zone = xzon;
room_data[xloc].unlinked = True;
init_intset(&room_data[xloc].objects, 5);
init_intset(&room_data[xloc].mobiles, 3);
init_intset(&room_data[xloc].exits_to_me, 3);
}
return(0);
}
void setup_zone(Boolean new, char *str) {
char *p;
loading = -1;
if ((p = strstr(str, ".zone"))) /* setup_zone called with filename */
*p = 0;
#ifdef DEBUG
fprintf(stderr, "\nProcessing zone %d:%s\n", xzon, str);
#endif
#ifndef GEN
if (new) {
init_intset (zlocs (xzon), 15);
init_intset (zmobs (xzon), 5);
init_intset (zobjs (xzon), 10);
}
#endif
zones[xzon].z_name = COPY(str);
}
int set_zone_global(char *str) {
char *p;
if (EQ(str, "objects"))
loading = PROC_OBJECTS;
else if (EQ(str, "locations"))
loading = PROC_LOCATIONS;
else if (EQ(str, "mobiles"))
loading = PROC_MOBILES;
else if (!strncasecmp(str, "rainfall", strlen("rainfall"))) {
if (!(p = strchr(str, ':'))) {
fprintf(stderr, "\nInvalid usage of %%rainfall. Must use "
"%%rainfall:<integer>\n");
return(-1);
}
else {
for (++p ; *p && isspace(*p) ; p++);
zones[xzon].rainfall = atoi(p);
}
}
else if (!strncasecmp(str, "latitude", strlen("latitude"))) {
if (!(p = strchr(str, ':'))) {
fprintf(stderr, "\nInvalid usage of %%latitude. Must use "
"%%latitutde:<integer>\n");
return(-1);
}
else {
for (++p ; *p && isspace(*p) ; p++);
zones[xzon].latitude = atoi(p);
}
}
else if (!strncasecmp(str, "zone", strlen("zone"))) {
if (!(p = strchr(str, ':'))) {
fprintf(stderr, "\nInvalid usage of %%zone. Must use "
"%%zone:<zonename>\n");
return(-1);
}
else {
for (++p ; *p && isspace(*p) ; p++);
if (!EQ(zones[xzon].z_name, p)) { /* new zone, not same as fname */
numzon = ++xzon;
resize_zones();
setup_zone(True, p);
}
}
}
else {
fprintf(stderr, "\nUnknown %% sequence: %s\n", str);
return(-1);
}
return(0);
}
char *prepass(Boolean *in_comment, Boolean *in_quote,
Boolean *in_hat, char *inp) {
static char newbuff[PAGELEN];
char *p, *q;
if (*in_quote || *in_hat) {
strcat(newbuff, "\n");
if (*inp == '\n')
return(newbuff);
q = newbuff + strlen(newbuff);
if (q - newbuff > PAGELEN) {
fprintf(stderr, "\nQuote page length exceeded in zone %s", zname(xzon));
exit(0);
}
}
else {
q = newbuff;
*newbuff = 0;
}
for (p = inp ; *p ; p++) {
switch (*p) {
case '/':
if (*(p+1) == '*') {
if (*in_comment) {
fprintf(stderr, "\nComment (/*) not allowed within comment (/*).\n");
return(NULL);
}
*in_comment = True;
p += 2;
}
break;
case '*':
if (*(p+1) == '/') {
if (!*in_comment) {
fprintf(stderr, "\nEnd comment (*/) must follow comment (/*).\n");
return(NULL);
}
*in_comment = False;
p += 2;
}
else
*p = '*';
break;
case '"':
if (!*in_hat)
*in_quote = !*in_quote;
else
*q++ = *p;
break;
case '^':
if (*(p-1) != ':')
*in_hat = !*in_hat;
else
*q++ = '^';
break;
default:
if (!*in_comment)
*q++ = *p;
break;
}
}
*q = 0;
if (*(q - 1) == '\n') /* remove newline */
*(--q) = 0;
if (!*in_quote)
for (--q ; q >= newbuff ; q--) { /* remove trailing whitespaces */
if (isspace(*q))
*q = 0;
else
break;
}
return(newbuff);
}
void ucase(char *dest, char *src) {
char *p, *q;
if ((p = strstr(src, "The ")))
p = src + 4;
else
p = src;
for (q = dest ; *p && !isspace(*p) ; p++, q++)
*q = toupper(*p);
*q = 0;
}
int link_zones(void) {
int i, rslt;
rslt = -1;
for (i = 0 ; i < numzon ; i++)
if ((rslt = link_zone(i)) == -1)
return(-1);
return(rslt);
}
/* could use some optimization. -1 = fail, 0 = succeed, 1 = warn */
int link_zone(int zn) {
char *p, *z;
int i, j, rslt, zone, ct;
char buff[BUFFLEN];
for (ct = 0 ; ct < znumobs(zn) ; ct++) {
i = zobj_nr(ct, zn);
if (!objs[i].unlinked)
continue;
else
objs[i].unlinked = False;
strcpy(buff, (char *) objs[i].oloc_reset);
free((char *) objs[i].oloc_reset);
if (!(p = strchr(buff, ':'))) {
fprintf(stderr, "\nError in zone %s: Location keyword expects "
"FLAG:location\nGot: %s\n", zname(ozone(i)), buff);
return(-1);
}
*p = 0;
p++;
if ((z = strchr(p, '@'))) {
*z++ = 0;
for (zone = 0 ; zone < numzon ; zone++)
if (EQ(zones[zone].z_name, z))
break;
if (zone == numzon) {
fprintf(stderr, "\nUnknown link to zone: %s\n", z);
return(-1);
}
}
else
zone = ozone(i);
switch (tlookup(buff, loctypes)) {
case 0: /* IN_CONTAINER */
rslt = ht_lookup(objects_z, p, 0, zone, obj_search);
if (rslt == -1) {
fprintf(stderr, "\nUnknown container in zone %s: %s\n",
zname(ozone(i)), p);
return(-1);
}
oloc_reset(i) = rslt;
ocarrf_reset(i) = IN_CONTAINER;
ozone(i) = ozone(rslt);
break;
case 1: /* IN_ROOM */
rslt = ht_lookup(locations_z, p, 0, zone, room_search);
if (rslt == -1) {
fprintf(stderr, "\nUnknown location in zone %s: %s\n",
zname(ozone(i)), p);
return(-1);
}
oloc_reset(i) = rslt;
ocarrf_reset(i) = IN_ROOM;
break;
case 2: /* CARRIED_BY */
rslt = ht_lookup(ublock_z, p, 0, zone, mob_search);
if (rslt == -1) {
fprintf(stderr, "\nUnknown mobile in zone %s: %s\n",
zname(ozone(i)), p);
return(-1);
}
oloc_reset(i) = rslt;
ocarrf_reset(i) = CARRIED_BY;
ozone(i) = pzone(rslt);
break;
case 3: /* WIELDED_BY */
rslt = ht_lookup(ublock_z, p, 0, zone, mob_search);
if (rslt == -1) {
fprintf(stderr, "\nUnknown mobile in zone %s: %s\n",
zname(ozone(i)), p);
return(-1);
}
oloc_reset(i) = rslt;
ocarrf_reset(i) = WIELDED_BY;
ozone(i) = pzone(rslt);
break;
case 4: /* WORN_BY */
rslt = ht_lookup(ublock_z, p, 0, zone, mob_search);
if (rslt == -1) {
fprintf(stderr, "\nUnknown mobile in zone %s: %s\n", zname(ozone(i)), p);
return(-1);
}
oloc_reset(i) = rslt;
ocarrf_reset(i) = WORN_BY;
ozone(i) = pzone(rslt);
break;
case 5: /* BOTH_BY */
rslt = ht_lookup(ublock_z, p, 0, zone, mob_search);
if (rslt == -1) {
fprintf(stderr, "\nUnknown mobile in zone %s: %s\n", zname(ozone(i)), p);
return(-1);
}
oloc_reset(i) = rslt;
ocarrf_reset(i) = BOTH_BY;
ozone(i) = pzone(rslt);
break;
default:
fprintf(stderr, "\nUnknown location tag in zone %s: %s\n", zname(ozone(i)), buff);
return(-1);
break;
}
if (olinked(i)) {
if ((z = strchr((char *) objs[i].linked, '@'))) { /* sets the zone */
*z++ = 0;
for (zone = 0 ; zone < numzon ; zone++)
if (EQ(zones[zone].z_name, z))
break;
if (zone == numzon) {
fprintf(stderr, "\nUnknown link to zone: %s\n", z);
return(-1);
}
}
else
zone = ozone(i);
if ((rslt = ht_lookup(objects_z, (char *) objs[i].linked, 0, zone,
obj_search)) == -1) {
fprintf(stderr, "\nObject %s linked to nonexistant %s.\n", oname(i),
(char *) objs[i].linked);
fprintf(stderr, "\nFailed at zone %s\n", zname(zone));
return(-1);
}
else {
free((char *) objs[i].linked);
olinked(i) = rslt;
}
}
else
olinked(i) = -1;
}
for (ct = 0 ; ct < znumchars(zn) ; ct++) {
i = zmob_nr(ct, zn);
if (!ublock[i].unlinked)
continue;
else
ublock[i].unlinked = False;
strcpy(buff, (char *) ublock[i].ploc_reset);
free((char *) ublock[i].ploc_reset);
if ((z = strchr(buff, '@'))) {
*z++ = 0;
for (zone = 0 ; zone < numzon ; zone++)
if (EQ(zones[zone].z_name, z))
break;
if (zone == numzon) {
fprintf(stderr, "\nUnknown link to zone: %s\n", z);
return(-1);
}
}
else
zone = ublock[i].zone;
if ((rslt = ht_lookup(locations_z, buff, 0, zone, room_search)) != -1)
ublock[i].ploc_reset = rslt;
else {
fprintf(stderr, "\nMobile \"%s\" in zone %s linked to %s (invalid loc)\n",
pname(i), zones[pzone(i)].z_name, buff);
return(-1);
}
}
for (ct = 0 ; ct < znumloc(zn) ; ct++) {
i = zloc_nr(ct, zn);
if (!room_data[i].unlinked)
continue;
else
room_data[i].unlinked = False;
for (j = 0 ; j < NEXITS ; j++) {
if (!lexit_reset(i, j))
lexit_reset(i, j) = -1;
else {
strcpy(buff, (char *) lexit_reset(i, j));
free((char *) lexit_reset(i, j));
if (*buff == '^')
p = buff + 1;
else
p = buff;
if ((z = strchr(p, '@'))) {
*z++ = 0;
for (zone = 0 ; zone < numzon ; zone++)
if (EQ(zname(zone), z))
break;
if (zone == numzon) {
lexit_reset(i, j) = -1;
#ifdef GEN
fprintf(stderr, "\nWARNING: Unknown link to zone %s in zone %s.",
z, zname(lzone(i)));
#endif
continue;
}
}
else
zone = lzone(i);
if (*buff == '^') {
if ((rslt = ht_lookup(objects_z, p, 0, zone, obj_search)) != -1)
lexit_reset(i, j) = DOOR + rslt;
else {
fprintf(stderr, "\nLocation \"%s\" in zone %s linked to %s "
"(invalid obj)\n", lname(i), zname(lzone(i)), p);
return(-1);
}
}
else {
if ((rslt = ht_lookup(locations_z, p, 0, zone, room_search)) != -1)
lexit_reset(i, j) = rslt;
else {
fprintf(stderr, "\nLocation \"%s\" in zone %s linked to %s "
"(invalid loc)\n", lname(i), zname(lzone(i)), p);
return(-1);
}
}
}
}
}
return(0);
}
int store_headers(void) {
int i;
FILE *fptr;
char buff1[256], buff2[256];
if (!(fptr = fopen(LOCATIONS_H, "w"))) {
fprintf(stderr, "\nUnable to open %s for writing.\n", LOCATIONS_H);
return(-1);
}
else {
fprintf(fptr, "/*\n"
"**\tLocations file header generated from %s\n"
"**\tDON'T MAKE CHANGES HERE -- THEY WILL GO AWAY!\n"
"*/\n\n"
"#ifndef _LOCATIONS_H\n"
"#define _LOCATIONS_H\n\n", ZONE_DIR);
for (i = 0 ; i < numloc ; i++) {
if (i == 0 || room_data[i].zone != room_data[i-1].zone) {
ucase(buff1, zname(room_data[i].zone));
fprintf(fptr, "#define LOCMIN_%s\t%d\n", buff1, i);
fprintf(fptr, "#define LOCMAX_%s\t%d\n", buff1,
i + zmaxlocs(room_data[i].zone));
}
ucase(buff1, zones[room_data[i].zone].z_name);
ucase(buff2, room_data[i].r_name);
fprintf(fptr, "#define LOC_%s_%s\t%d\n", buff1, buff2, i);
}
fprintf(fptr, "#endif\n");
fclose(fptr);
}
if (!(fptr = fopen(OBJECTS_H, "w"))) {
fprintf(stderr, "\nUnable to open %s for writing.\n", OBJECTS_H);
return(-1);
}
else {
fprintf(fptr, "/*\n"
"**\tObjects file header generated from %s\n"
"**\tDON'T MAKE CHANGES HERE -- THEY WILL GO AWAY!\n"
"*/\n\n"
"#ifndef _OBJECTS_H\n"
"#define _OBJECTS_H\n\n", ZONE_DIR);
for (i = 0 ; i < numobs ; i++) {
ucase(buff1, zname(ozone(i)));
ucase(buff2, ozname(i));
fprintf(fptr, "#define OBJ_%s_%s\t%d\n", buff1, buff2, i);
}
fprintf(fptr, "#endif\n");
fclose(fptr);
}
if (!(fptr = fopen(MOBILES_H, "w"))) {
fprintf(stderr, "\nUnable to open %s for writing.\n", MOBILES_H);
return(-1);
}
else {
fprintf(fptr, "/*\n"
"**\tMobiles file header generated from %s\n"
"**\tDON'T MAKE CHANGES HERE -- THEY WILL GO AWAY!\n"
"*/\n\n"
"#ifndef _MOBILES_H\n"
"#define _MOBILES_H\n\n", ZONE_DIR);
for (i = 0 ; i < numchars ; i++) {
ucase(buff1, zname(pzone(i)));
ucase(buff2, pzname(i));
fprintf(fptr, "#define MOB_%s_%s\t%d\n", buff1, buff2, i);
}
fprintf(fptr, "#endif\n");
fclose(fptr);
}
return(0);
}
int obj_search(int a, int b) {
if (objs[a].zone == b)
return(1);
return(0);
}
int room_search(int a, int b) {
if (room_data[a].zone == b)
return(1);
return(0);
}
int mob_search(int a, int b) {
if (ublock[a].zone == b)
return(1);
return(0);
}
int llookup (char *elem, char **table) {
return(glookup(elem, 1, table, strncasecmp));
}