/**************************************************************************** * 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)); }