/* * Alf Salte (Alf) June 1990 */ #include <stdio.h> #include <ctype.h> #include <stdlib.h> #include "kernel.h" #include <stdarg.h> #define get_oref(z,F) ((XOBJ *)get_ref('O',z,F)) #define get_lref(z,F) get_ref('L', z, F) #define get_mref(z,F) ((XMOB *)get_ref('M', z, F)) #include "cflags.h" #include "mflagnames.h" #include "pflagnames.h" #include "sflagnames.h" #include "lflagnames.h" #include "oflagnames.h" #include "aflagnames.h" #include "eflagnames.h" #include "exitnames.h" #include "lflags.h" #define UNKNOWN ((XOBJ *)(-1)) #define BAD ((XOBJ *)(-2)) #define GOOD ((XOBJ *)(-3)) #define REFERRED ((XOBJ *)(-4)) #define DEFINED ((XOBJ *)(-5)) #define IS_LINK 0 #define IS_CONTAINED 1 #define IS_CHECK 2 #undef DEBUG typedef struct _XZON { char *name; char *fname; int zone; /* This zone's number */ int latitude; int rainfall; int loc; /* The loc number of room ZONE0 */ int n_loc; /* Number of locations in this zone */ int mob; /* The mob number of first mobile in zone */ int n_mob; /* Number of mobiles in this zone */ struct _XLOC *locs; struct _XOBJ *objs; struct _XMOB *mobs; struct _XLOC *rlocs; struct _XMOB *rmobs; } XZON; typedef struct _XMOB { struct _XOBJ *aux; struct _XZON *zone; struct _XMOB *next; char *name; char *pname; int mob; struct _XLOC *loc; int str; int armor; int damage; int agg; int speed; int vis; int wimpy; PFLAGS pflags; SFLAGS sflags; MFLAGS mflags; EFLAGS eflags; int attitude; int att_param; char *desc; char *exam; } XMOB; typedef struct _XOBJ { struct _XOBJ *aux; struct _XZON *zone; struct _XOBJ *next; char *name; struct _XOBJ *the_next; struct _XOBJ *linked; char *pname; char *aname; int obj; int cflag; struct _XLOC *loc; unsigned char damage; unsigned char armor; OFLAGS oflags; AFLAGS aflags; int state; int mstate; int bvalue; int osize; int oweight; char *desc[4]; char *examine; int vis; } XOBJ; typedef struct _XLOC { struct _XOBJ *aux; struct _XZON *zone; struct _XLOC *next; char *name; char *pname; int loc; int altitude; LFLAGS lflags; char exit_types[NEXITS]; struct _XLOC *exits[NEXITS]; char *description; } XLOC; char *strchr (); char *main_file; char *log_file; char *zone_file; char *mobh_file; char *mob_file; char *objh_file; char *obj_file; char *reset_list; char *loch_file; char *loc_file; FILE *LogFile; int n_logs; char dir[512]; XZON zones[400]; XMOB mobs[10000]; XOBJ objs[10000]; XLOC locns[10000]; char texts[2000000]; char *textsp = texts; int num_z = 0; int num_m = 0; int num_o = 0; int num_l = 0; int num_linked = 0; int num_unlinked = 0; XOBJ *obj_list = NULL; XOBJ *obj_list_l = NULL; /* last */ #define T_NAME 0 #define T_PNAME 1 #define T_LOC 2 #define T_DESC 3 #define T_END 4 #define TMOB_STR 5 #define TMOB_DAM 6 #define TMOB_ARMOR 7 #define TMOB_AGG 8 #define TMOB_SFLAGS 9 #define TMOB_PFLAGS 10 #define TMOB_MFLAGS 11 #define TMOB_SPEED 12 #define TMOB_EXAM 13 #define TMOB_VIS 14 #define TMOB_WIMPY 15 #define TMOB_EFLAGS 16 #define TOBJ_ANAME 5 #define TOBJ_OFLAGS 6 #define TOBJ_ARMOR 7 #define TOBJ_DAMAGE 8 #define TOBJ_MAX_STATE 9 #define TOBJ_STATE 10 #define TOBJ_BVALUE 11 #define TOBJ_SIZE 12 #define TOBJ_WEIGHT 13 #define TOBJ_EXAM 14 #define TOBJ_LINKED 15 #define TOBJ_VIS 16 #define TOBJ_AFLAGS 17 char *Mob_tab[] = { "Name", "Pname", "Location", "Description", "End", "Strength", "Damage", "Armor", "Aggression", "SFlags", "PFlags", "MFlags", "Speed", "Examine", "Visibility", "Wimpy", "EFlags", TABLE_END }; char *Obj_tab[] = { "Name", "Pname", "Location", "Description", "End", "AltName", "Oflags", "Armor", "Damage", "MaxState", "State", "BValue", "Size", "Weight", "Examine", "Linked", "Visibility", "AFlags", TABLE_END }; char *Cflags[] = { "In room", "In container", "Carried by", "Worn by", "Wielded by", "Both worn and wielded by" }; void xexit (code) int code; { exit (code); } void log (char t, XOBJ * O, XZON * Z, char *f,...); /* * ** Open file for read/write or die trying */ static FILE * Do_fopen (char *name, char *mode) { char *m; FILE *file; Boolean b; b = False; if (*(m = mode) == 'p') { b = True; ++m; } if (*name == '-' && !name[1]) return *mode == 'w' ? stdout : stdin; file = (b ? popen (name, m) : fopen (name, m)); if (!file) { perror (name); (void) fprintf (stderr, "Unable to open file for %s(%s)\n", (*m == 'w' ? "write" : "read"), mode); xexit (1); } return file; } char * xfgets (char *b, int s, FILE * f) { int k; int c = 0; char *t; for (t = b, k = s; --k >= 0 && (c = fgetc (f)) != EOF && c != '\n';) *t++ = c; if (c == EOF && t == b) return NULL; *t = 0; return b; } char * alloc_text (int s) { char *p; textsp = (p = textsp) + s; return p; } char * save_text (char *t) { int s; char *u; s = strlen (t) + 1; u = alloc_text (s); bcopy (t, u, s); return u; } char * get_fname (FILE * a, char *d) { char *p; register char *q; int c, k; while ((c = getc (a)) == ' ' || c == '\t') ; q = (p = textsp); if (c != '/') { k = strlen (d); bcopy (d, q, k); q += k; } do { *q++ = c; c = getc (a); } while (!isspace (c)); while (c != '\n') c = getc (a); *q++ = 0; textsp = q; return p; } char * get_text (FILE * a) { char *p; register char *q; int c, d; q = (p = textsp); while ((c = getc (a)) == ' ' || c == '\t') ; if (ispunct (c)) { d = c; } else { d = 0; ungetc (c, a); } if ((c = getc (a)) != '\n') ungetc (c, a); while ((c = getc (a)) != d) { if (d == 0 && isspace (c)) break; *q++ = c; } if (d == 0) ungetc (c, a); *q++ = 0; textsp = q; return p; } char * get_exam (FILE * a) { char *p; register char *q; int c, d; q = (p = textsp); c = getc (a); while (isspace (c)) c = getc (a); d = c; if ((c = getc (a)) != '\n') ungetc (c, a); while ((c = getc (a)) != d && c != EOF) *q++ = c; if (q[-1] != '\n') *q++ = '\n'; *q++ = 0; textsp = q; return p; } char * get_description (FILE * a) { char *p; register char *q; int c; q = (p = textsp); while (True) { while ((c = getc (a)) != '^') { do { *q++ = c; } while ((c = getc (a)) != '\n'); *q++ = '\n'; } if ((c = getc (a)) == '\n') break; *q++ = '^'; *q++ = c; while ((*q++ = c = getc (a)) != '\n') ; } *q++ = 0; textsp = q; return p; } FILE * xopen (char *f, char *m) { FILE *x; if ((x = fopen (f, m)) == 0) { perror (f); xexit (1); } return x; } int read_main (char *mf) { char b[128]; char n[128]; FILE *f; XZON *p; int z; int k; char *s; char *t; char *u; f = xopen (mf, "r"); main_file = mf; for (s = dir, t = main_file, u = NULL; *t != 0; ++s, ++t) { if ((*s = *t) == '/') u = s; } if (u == NULL) *(u = s = dir) = 0; else *++u = 0; log_file = get_fname (f, dir); zone_file = get_fname (f, dir); mobh_file = get_fname (f, dir); mob_file = get_fname (f, dir); objh_file = get_fname (f, dir); obj_file = get_fname (f, dir); reset_list = get_fname (f, dir); loch_file = get_fname (f, dir); loc_file = get_fname (f, dir); if ((LogFile = fopen (log_file, "w")) == NULL) { perror (log_file); exit (1); } n_logs = 0; for (z = 0, p = zones; xfgets (b, sizeof (b), f) != NULL;) { for (s = b; isalpha (*s); ++s) ; if ((k = s - b) == 0) continue; t = alloc_text (k + 1); bcopy (b, t, k); t[k] = 0; p->name = t; while (*s == ' ' || *s == '\t') ++s; if (isalpha (*s) || *s == '/' || *s == '.') { for (t = s; isalpha (*s) || *s == '/' || *s == '.'; ++s) ; *s = 0; if (*t != '/') { sprintf (n, "%s%s", dir, t); t = n; } } else { sprintf (n, "%s%s.zone", dir, t); t = n; } k = strlen (t); s = alloc_text (k + 1); bcopy (t, s, k); s[k] = 0; p->fname = s; p->loc = 0; p->latitude = 0; p->rainfall = 0; p->locs = (XLOC *) 0; p->mobs = (XMOB *) 0; p->objs = (XOBJ *) 0; p->zone = z; ++z; ++p; } fclose (f); return num_z = z; } FILE * zopen (char *fn, char *zn, Boolean * m, char *b, int bs) { FILE *f; char *s; char *t; char buff[128]; sprintf (buff, "/lib/cpp -P -traditional -I../include %s", fn); f = popen (buff, "r"); if (f == NULL) { fprintf (stderr, "\nError when opening file %s for zone %s\n", fn, zn); perror (fn); xexit (1); } *m = False; do { if (xfgets (b, bs, f) == NULL) { pclose (f); return NULL; } } while (b[0] != '%'); if (strncasecmp (&b[1], "zone:", 5) == 0) { *m = True; for (;;) { for (s = &b[6]; *s == ' ' || *s == '\t'; ++s) ; for (t = s; isalpha (*t); ++t) ; *t = 0; if (strcasecmp (s, zn) == 0) { while (xfgets (b, bs, f)) { if (b[0] == '%') return f; } pclose (f); return NULL; } do { if (xfgets (b, bs, f) == NULL) { pclose (f); return NULL; } } while (strncasecmp (b, "%zone:", 6) != 0); } } return f; } int lookup (char *s, char **t) { char **u; int l; int x; l = strlen (s); for (u = t, x = 0; *u != TABLE_END; u++, x++) { if (*u == NULL) continue; if (strncasecmp (s, *u, l) == 0) return x; } return -1; } XMOB * find_mob (XZON * z, char *name) { XMOB *m, *q = NULL; char *s; for (m = z->mobs; m != NULL; m = m->next) { if (strcasecmp (m->name, name) == 0) return m; } for (m = z->rmobs; m != NULL; m = m->next) { if (strcasecmp (m->name, name) == 0) return m; q = m; } m = &mobs[num_m++]; bzero ((char *) m, sizeof (XMOB)); m->next = NULL; if (q == NULL) z->rmobs = m; else q->next = m; m->name = s = save_text (name); lowercase (s); *s = toupper (*s); if (strncmp (m->name, "The ", 4) == 0) { s += 4; *s = toupper (*s); } m->zone = z; m->mob = -1; m->aux = REFERRED; return m; } XOBJ * find_obj (XZON * z, char *name) { XOBJ *o, *q = NULL; char *s; for (o = z->objs; o != NULL; o = o->next) { if (strcasecmp (o->name, name) == 0) return o; q = o; } o = &objs[num_o++]; bzero ((char *) o, sizeof (XOBJ)); o->next = NULL; if (q == NULL) z->objs = o; else q->next = o; o->name = s = save_text (name); lowercase (s); o->zone = z; o->obj = -1; o->aux = REFERRED; return o; } XLOC * find_loc (XZON * z, char *name) { XLOC *l, *q = NULL; for (l = z->locs; l != NULL; l = l->next) { if (strcasecmp (l->name, name) == 0) return l; } for (l = z->rlocs; l != NULL; l = l->next) { if (strcasecmp (l->name, name) == 0) return l; q = l; } l = &locns[num_l++]; bzero ((char *) l, sizeof (XLOC)); l->next = NULL; if (q == NULL) z->rlocs = l; else q->next = l; l->name = save_text (name); l->zone = z; l->loc = -1; l->aux = REFERRED; return l; } XLOC * get_ref (char t, XZON * zo, FILE * F) { char n[128]; char zone[128]; char *s; XZON *z; int c; int x; for (s = n, c = getc (F); isalnum (c) || c == '_'; c = getc (F)) { *s++ = c; } *s = 0; z = zo; if (c == '@') { for (s = zone, c = getc (F); isalpha (c); c = getc (F)) { *s++ = c; } *s = 0; for (z = zones, x = 0; x < num_z; ++z, ++x) { if (strcasecmp (z->name, zone) == 0) break; } if (x == num_z) { ungetc (c, F); return 0; /* Couldn't find entry */ } } ungetc (c, F); switch (t) { case 'L': return (XLOC *) find_loc (z, n); break; case 'O': return (XLOC *) find_obj (z, n); break; case 'M': return (XLOC *) find_mob (z, n); break; } return 0; } int get_int (FILE * F) { int i; int c; Boolean neg; c = getc (F); while (c == ' ' || c == '\t') c = getc (F); i = 0; if ((neg = c == '-')) { c = getc (F); } while (isdigit (c)) { i = i * 10 + (c - '0'); c = getc (F); } ungetc (c, F); if (neg) i = -i; return i; } void get_flags (XZON * z, XMOB * m, char ty, int *f, int s, char **t, FILE * F) { char n[128]; int c; char *p; int k; c = getc (F); while (c != '{') c = getc (F); bzero (f, s); for (c = getc (F); c != '}'; c = getc (F)) { if (!isalpha (c)) { continue; } for (p = n; isalpha (c); c = getc (F)) { *p++ = c; } ungetc (c, F); *p = 0; if ((k = lookup (n, t)) == -1) { fprintf (stderr, "\nError in %s@%s, %cFLAGS: unknown flag %s.\n", m->name, z->name, ty, n); xexit (1); } f[s - k / 32 - 1] |= (1 << (k % 32)); } } void mkdef_mob (XZON * z, XMOB * m) { XMOB *p; if (m->aux != REFERRED) { fprintf (stderr, "\nMobile %s@%s is defined twice!\n", m->name, z->name); xexit (1); } if ((p = z->rmobs) == m) { z->rmobs = m->next; } else { while (p->next != m) p = p->next; p->next = m->next; } m->aux = DEFINED; m->mob = -1; m->pname = m->name; m->next = NULL; if ((p = z->mobs) == NULL) z->mobs = m; else { while (p->next != NULL) p = p->next; p->next = m; } } Boolean read_mob (FILE * F, XZON * z, char *b, int bs) { XMOB *m; char s[128]; char n[128]; int c; int d; char *t; char *v; int k; int i; m = NULL; for (;;) { do { c = getc (F); } while (isspace (c)); for (t = s; isalnum (c) || c == '_'; c = getc (F)) *t++ = c; *t = 0; if (t == s) { if (c == EOF) { return False; } if (c != '%') continue; ungetc (c, F); break; } i = -1; while (c == ' ' || c == '\t' || c == '=') c = getc (F); ungetc (c, F); k = lookup (s, Mob_tab); if (k != T_NAME && m == NULL) { fprintf (stderr, "\nError in zone mob:%s: Entry %s is out of sequence.\n", z->name, s); xexit (1); } switch (k) { case T_NAME: d = 0; c = getc (F); for (t = n; isalnum (c) || c == '_'; c = getc (F)) { *t++ = c; } *t = 0; ungetc (c, F); m = find_mob (z, n); mkdef_mob (z, m); m->mob = -1; m->pname = m->name; m->loc = 0; m->str = 0; m->armor = 0; m->damage = 10; m->vis = 0; m->agg = 0; m->speed = -1; m->wimpy = 0; m->pflags.u = 0; m->pflags.h = 0; m->pflags.l = 0; m->mflags.h = 0; m->mflags.l = 0; m->sflags.h = 0; m->sflags.l = 0; m->eflags.h = 0; m->eflags.l = 0; m->attitude = 0; m->att_param = 0; m->desc = NULL; m->exam = NULL; #ifdef DEBUG printf( "\rMobile %s@%s.%-30s", m->name, z->name, "" ); #endif break; case T_PNAME: m->pname = v = get_text (F); lowercase (v); *v = toupper (*v); if (strncmp (m->pname, "The ", 4) == 0) { v += 4; *v = toupper (*v); } break; case T_LOC: m->loc = get_lref (z, F); break; case T_DESC: m->desc = get_text (F); break; case T_END: d = 0; c = getc (F); for (t = n; isalnum (c) || c == '_'; c = getc (F)) { *t++ = c; } *t = 0; ungetc (c, F); if (strcasecmp (n, m->name) != 0) { log ('M', (XOBJ *) m, z, "Wrong arg to end: %s.", n); m->aux = BAD; } m = NULL; break; case TMOB_STR: m->str = get_int (F); break; case TMOB_ARMOR: m->armor = get_int (F); break; case TMOB_DAM: m->damage = get_int (F); break; case TMOB_WIMPY: m->wimpy = get_int (F); break; case TMOB_VIS: m->vis = get_int (F); break; case TMOB_AGG: m->agg = get_int (F); break; case TMOB_SPEED: m->speed = get_int (F); break; case TMOB_EXAM: m->exam = get_exam (F); break; case TMOB_SFLAGS: get_flags (z, m, 'S', (int *) &(m->sflags), sizeof (SFLAGS) / sizeof (int), Sflags, F); break; case TMOB_PFLAGS: get_flags (z, m, 'P', (int *) &(m->pflags), sizeof (PFLAGS) / sizeof (int), Pflags, F); break; case TMOB_MFLAGS: get_flags (z, m, 'M', (int *) &(m->mflags), sizeof (MFLAGS) / sizeof (int), Mflags, F); break; case TMOB_EFLAGS: get_flags (z, m, 'E', (int *) &(m->eflags), sizeof (EFLAGS) / sizeof (int), Eflags, F); break; case -1: fprintf (stderr, "\nError in zone mob:%s: %s is not a legal entry.\n", z->name, s); xexit (1); default: fprintf (stderr, "\nError in zone mob:%s: %s isn't implemented yet.\n", z->name, s); xexit (1); } while ((c = getc (F)) != '\n') { if (c == EOF) return False; } } xfgets (b, bs, F); return True; } Boolean read_obj (FILE * F, XZON * z, char *b, int bs) { XOBJ *o; char s[128]; char n[128]; int c; int d; char *t; int k; int i; int cf; char cft = 0; o = NULL; for (;;) { do { c = getc (F); } while (isspace (c)); for (t = s; isalnum (c) || c == '_'; c = getc (F)) *t++ = c; *t = 0; if (t == s) { if (c == EOF) { return False; } if (c != '%') continue; ungetc (c, F); break; } i = -1; if (c == '[') { c = getc (F); for (i = 0; isdigit (c); i = i * 10 + (c - '0'), c = getc (F)) ; if (c != ']') { fprintf (stderr, "\nError in zone obj:%s: not number in [..]\n", z->name); } c = getc (F); } while (c == ' ' || c == '\t' || c == '=') c = getc (F); ungetc (c, F); k = lookup (s, Obj_tab); if (k != T_NAME && o == NULL) { fprintf (stderr, "\nError in zone obj:%s: Entry %s is out of sequence.\n", z->name, s); xexit (1); } switch (k) { case T_NAME: d = 0; c = getc (F); for (t = n; isalnum (c) || c == '_'; c = getc (F)) { *t++ = c; } *t = 0; ungetc (c, F); o = find_obj (z, n); if (o->aux != REFERRED) { fprintf (stderr, "\nObject %s@%s is defined twice!\n", n, z->name); xexit (1); } o->aux = DEFINED; o->obj = -1; o->pname = o->name; o->linked = NULL; o->aname = NULL; o->cflag = -1; o->loc = 0; o->damage = 0; o->armor = 0; o->oflags.h = 0; o->oflags.l = 0; o->aflags = 0; o->state = -1; o->mstate = 0; o->bvalue = 0; o->osize = 0; o->oweight = 0; o->desc[0] = NULL; o->desc[1] = NULL; o->desc[2] = NULL; o->desc[3] = NULL; o->examine = NULL; o->vis = 0; break; case T_PNAME: o->pname = get_text (F); lowercase (o->pname); break; case T_LOC: fscanf (F, "%d\t:", &cf); switch (cf) { case IN_ROOM: cft = 'L'; break; case IN_CONTAINER: cft = 'O'; break; case CARRIED_BY: case WIELDED_BY: case WORN_BY: case BOTH_BY: cft = 'M'; break; default: fprintf (stderr, "\nError in obj:%s@%s: Illegal carry flag %d.\n", o->name, z->name, cf); xexit (1); } o->cflag = cf; o->loc = get_ref (cft, z, F); break; case T_DESC: if (i < 0 || i >= 4) { fprintf (stderr, "\nError in obj:%s@%s: Illegal index in Desc %d.\n", o->name, z->name, i); } o->desc[i] = get_text (F); break; case T_END: d = 0; c = getc (F); for (t = n; isalnum (c) || c == '_'; c = getc (F)) { *t++ = c; } *t = 0; ungetc (c, F); if (strcasecmp (n, o->name) != 0) { log ('O', o, z, "Wrong arg to end: %s.", n); o->aux = BAD; } o = NULL; break; case TOBJ_ANAME: o->aname = get_text (F); break; case TOBJ_OFLAGS: get_flags (z, (XMOB *) o, 'O', (int *) &(o->oflags), sizeof (OFLAGS) / sizeof (int), Oflags, F); break; case TOBJ_AFLAGS: get_flags (z, (XMOB *) o, 'A', (int *) &(o->aflags), sizeof (AFLAGS) / sizeof (int), Aflags, F); break; case TOBJ_ARMOR: o->armor = get_int (F); break; case TOBJ_DAMAGE: o->damage = get_int (F); break; case TOBJ_MAX_STATE: o->mstate = get_int (F); break; case TOBJ_STATE: o->state = get_int (F); break; case TOBJ_BVALUE: o->bvalue = get_int (F); break; case TOBJ_SIZE: o->osize = get_int (F); break; case TOBJ_WEIGHT: o->oweight = get_int (F); break; case TOBJ_LINKED: if ((o->linked = get_oref (z, F)) == NULL) o->linked = (XOBJ *) (-1); break; case TOBJ_EXAM: o->examine = get_exam (F); break; case TOBJ_VIS: o->vis = get_int (F); break; case -1: fprintf (stderr, "\nError in zone obj:%s: %s is not a legal entry.\n", z->name, s); xexit (1); default: fprintf (stderr, "\nError in zone obj:%s: %s isn't implemented yet.\n", z->name, s); xexit (1); } while ((c = getc (F)) != '\n') { if (c == EOF) return False; } } xfgets (b, bs, F); return True; } void mkdef_loc (XZON * z, XLOC * l) { XLOC *p; if (l->aux != REFERRED) { fprintf (stderr, "\nRoom %s@%s is defined twice!\n", l->name, z->name); xexit (1); } if ((p = z->rlocs) == l) { z->rlocs = l->next; } else { while (p->next != l) p = p->next; p->next = l->next; } l->aux = DEFINED; l->loc = 0; l->next = NULL; if ((p = z->locs) == NULL) z->locs = l; else { while (p->next != NULL) p = p->next; p->next = l; } } Boolean read_loc (FILE * F, XZON * z, char *b, int bs) { XLOC *l; char s[128]; char n[128]; int c; int g; char *t; int k; l = NULL; for (;;) { do { c = getc (F); } while (isspace (c)); for (t = s; isalnum (c) || c == '_'; c = getc (F)) *t++ = c; *t = 0; if (t == s) { if (c == EOF) { return False; } if (c == '%') { ungetc (c, F); break; } continue; } #ifdef DEBUG printf( "\rLocation %s@%s.%-30s", s, z->name, "" ); #endif l = find_loc (z, s); mkdef_loc (z, l); l->altitude = 0; while (c != ';') { while (isspace (c)) c = getc (F); for (t = n; isalpha (c) || isspace(c); c = getc (F)) { *t++ = c; } *t = 0; if (t == n) { if (c == ';') break; if (t == n && c != ';') { fprintf (stderr, "\n Expected ';' in room %s@%s.\n", s, z->name); xexit (1); } } if (c != ':') { fprintf (stderr, "\n Expected ':' in room %s@%s.\n", s, z->name); xexit (1); } if ((k = lookup (n, Exits)) == -1) { fprintf (stderr, "\n Illegal exit %s in room %s@%s.\n", n, s, z->name); xexit (1); } if (l->exit_types[k] != 0) { log ('L', (XOBJ *) l, z, "Multiple defineds of exit %s.", Exits[k]); } for (c = getc (F); isspace (c); c = getc (F)) ; switch (c) { case '#': l->exit_types[k] = '#'; l->exits[k] = (XLOC *) get_int (F); break; case '^': l->exit_types[k] = '^'; l->exits[k] = (XLOC *) get_oref (z, F); break; default: l->exit_types[k] = ' '; ungetc (c, F); l->exits[k] = get_lref (z, F); } c = getc (F); } while (getc (F) != '\n') ; c = getc (F); while (isspace (c)) c = getc (F); for (t = n; isalpha (c); c = getc (F)) { *t++ = c; } *t = 0; if ((g = t - n) == 0 || strncasecmp (n, "Lflags", g) != 0) { if(g != 0 && strncasecmp (n, "Altitude", g) == 0) { while (isspace (c)) c = getc (F); l->altitude = get_int(F); while (getc (F) != '\n') ; c = getc (F); while (isspace (c)) c = getc (F); for (t = n; isalpha (c); c = getc (F)) { *t++ = c; } *t = 0; if((g = t - n) == 0 || strncasecmp (n, "Lflags", g) != 0) { fprintf (stderr, "\nError in %s@%s, Lflags entry required.\n", s, z->name); xexit (1); } } else { fprintf (stderr, "\nError in %s@%s, Lflags entry required.\n", s, z->name); xexit (1); } } ungetc (c, F); get_flags (z, (XMOB *) l, 'L', (int *) &(l->lflags), sizeof (LFLAGS) / sizeof (int), Lflags, F); while (getc (F) != '\n') ; c = getc (F); t = n; while (c != '^') { *t++ = c; c = getc (F); } *t = 0; while (getc (F) != '\n') ; l->pname = save_text (n); l->description = get_description (F); } return True; } void read_zones (XZON * zo, int nz, Boolean silent) { int z; XZON *zon; FILE *F; Boolean multiple; char buff[128]; if (!silent) printf ("\n"); for (z = 0, zon = zo; z < nz; ++z, ++zon, pclose (F)) { if (!silent) printf("\r%d:%s from %s ", z, zon->name, zon->fname); fflush (stdout); if ((F = zopen (zon->fname, zon->name, &multiple, buff, sizeof (buff))) == NULL) { fprintf (stderr, "\nZone not found: %s in file %s.\n", zon->name, zon->fname); xexit (1); } if (!strncasecmp(buff, "%rainfall:", 10 )) { char c; zon->rainfall = atoi(&buff[10]); while ((c = getc (F)) != '\n') { if (c == EOF) continue; } xfgets(buff, sizeof(buff), F); } if (!strncasecmp(buff, "%latitude:", 10 )) { char c; zon->latitude = atoi( &buff[10] ); while ((c = getc (F)) != '\n') { if (c == EOF) continue; } xfgets( buff, sizeof(buff), F ); } if (!strncasecmp(buff, "%mobiles", 8)) { if (!read_mob (F, zon, buff, sizeof (buff))) continue; } if (!strncasecmp(buff, "%objects", 8)) { if (!read_obj (F, zon, buff, sizeof (buff))) continue; } if (!strncasecmp(buff, "%locations", 10)) { read_loc (F, zon, buff, sizeof (buff)); continue; } else if (!strncasecmp(buff, "%zone:", 6)) { if (!multiple) { fprintf (stderr, "\nError in zone file, %s unexpected.\n", buff); xexit (1); } continue; } else { fprintf (stderr, "\n Error in zone file: unknown sequence %s.", buff); xexit (1); } } } Boolean obj_ok (XOBJ * O, XOBJ * F, char t) { XOBJ *L; XOBJ *G; XLOC *R; if (O == 0 || O == (XOBJ *) (-1) || O->aux == BAD) { return False; } else if (O->aux == F && t == IS_LINK) { return True; } else if (O->aux == F) { log ('O', O, O->zone, "Recursive contents in object."); O->aux = BAD; return False; } else if (O->loc == NULL) { log ('O', O, O->zone, "Location does not exist."); O->aux = BAD; return False; } else if (O->obj != -1) { log ('O', O, O->zone, "O->obj == %d, should be -1"); O->aux = BAD; return False; } else if (O->aux != UNKNOWN) { return True; } O->aux = F; if (O->cflag == IN_CONTAINER && !obj_ok ((XOBJ *) (O->loc), F, IS_CONTAINED)) { G = (XOBJ *) (O->loc); log ('O', O, O->zone, "Container %s@%s[%s] is bad", G->name, G->zone->name, G->pname); O->aux = BAD; return False; } if ((L = O->linked) != NULL) { if (L == (XOBJ *) (-1)) { log ('O', O, O->zone, "Linked object doesn't exist."); O->aux = BAD; return False; } else if (L == O) { log ('O', O, O->zone, "Linked object to itself."); O->aux = BAD; return False; } else if (L->linked != O) { log ('O', O, O->zone, "Linked object %s@%s[%s] isn't linked back.", L->name, L->zone->name, L->pname); O->aux = BAD; return False; } else if (L->aux == BAD) { log ('O', O, O->zone, "Linked object %s@%s[%s] is bad.", L->name, L->zone->name, L->pname); O->aux = BAD; return False; } else if ((G = L->aux) != GOOD) { if (G == UNKNOWN) G = L; if (!obj_ok (L, G, IS_LINK)) { log ('O', O, O->zone, "Error with linked object %s@%s[%s].", L->name, L->zone->name, L->pname); L->aux = BAD; O->aux = BAD; return False; } } if (O->state == -1) { if ((O->state = L->state) == -1) { O->state = L->state = 0; } } else if (L->state == -1) { L->state = O->state; } else if (L->state != O->state) { log ('O', O, O->zone, "Initial states on linked objects %s@%s[%s] are not the same.", L->name, L->zone->name, L->pname); L->aux = BAD; O->aux = BAD; return False; } } else if (O->state == -1) { O->state = 0; } if ((R = O->loc) != NULL) { switch (O->cflag) { case IN_ROOM: if (((int) (R->loc)) <= 0 || R->aux != GOOD) R = NULL; break; case IN_CONTAINER: break; case CARRIED_BY: case WORN_BY: case WIELDED_BY: case BOTH_BY: if (((XMOB *) R)->mob < 0 || ((XMOB *) R)->aux != GOOD) R = NULL; break; default: R = NULL; } } if (R == NULL) { log ('O', O, O->zone, "Invalid location."); O->aux = BAD; return False; } /* * if (O->linked == NULL) { * if (not_linked_l == NULL) { * not_linked = not_linked_l = O; * } else { * not_linked_l->the_next = O; * not_linked_l = O; * } * ++num_unlinked; * } else if (O < O->linked) { * if (linked_objs_l == NULL) { * linked_objs = linked_objs_l = O; * } else { * linked_objs_l->the_next = O; * linked_objs_l = O; * } * ++num_linked; * } */ if (obj_list == NULL) { obj_list_l = obj_list = O; } else { obj_list_l->the_next = obj_list_l = O; } if (O->linked == NULL) ++num_unlinked; else if (O < O->linked) ++num_linked; O->aux = GOOD; return True; } void clean_up (XZON * zon, int nz, int *mm, int *oo, int *lo, int *ll) { XOBJ *O; XOBJ *F; XMOB *M; XLOC *L; XLOC *E; XZON *Z; int x; int k; int l; int m; int o; int z; for (M = mobs, x = 0; x < num_m; M++, x++) { if (M->aux == BAD) continue; if (M->aux != DEFINED) { M->aux = BAD; log ('M', (XOBJ *) M, M->zone, "Mobile isn't properly defined.."); } else { char *p = M->pname; M->aux = UNKNOWN; if (M->agg == -1) { M->agg = 10; /*((k = abs(M->lev)) <= 200 ? 0 : k%100); */ } if (M->speed == -1) { M->speed = 5; } while (isalpha (*p) || *p == ' ') p++; if (*p != '\0') log ('M', (XOBJ *) M, M->zone, "Mobile in-game name must consist of letters only."); } } for (L = locns, x = 0; x < num_l; L++, x++) { if (L->aux != DEFINED) { log ('L', (XOBJ *) L, L->zone, "Location isn't properly defined.."); L->aux = BAD; } else { L->aux = UNKNOWN; L->loc = -2; } } for (O = objs, x = 0; x < num_o; O++, x++) { if (O->aux == BAD) continue; if (O->aux != DEFINED) { log ('O', O, O->zone, "Object isn't properly defined.."); O->aux = BAD; } else { char *p = O->pname; O->obj = -2; O->the_next = NULL; O->aux = UNKNOWN; while (isalpha (*p) || *p == ' ') p++; if (*p != '\0') log ('O', O, O->zone, "Object in-game name must consist of letters only."); } } for (Z = zon, z = 0, o = 0; z < nz; ++z, ++Z) { Z->n_loc = 0; for (O = Z->objs; O != NULL; O = O->next) { if (O->aux == UNKNOWN) { O->obj = -1; O->zone = Z; } } for (L = Z->locs; L != NULL; L = L->next) { if (L->aux == UNKNOWN) { L->loc = -1; } } } for (Z = zon, z = 0, l = 0; z < nz; ++z, ++Z) { Z->loc = l; for (L = Z->locs; L != NULL; L = L->next) { if (L->aux == UNKNOWN && L->pname != NULL && L->description != NULL) { L->loc = ++l; L->aux = GOOD; Z->n_loc++; } } } for (Z = zon, z = 0, m = 0; z < nz; ++z, ++Z) { Z->mob = m; for (M = Z->mobs; M != NULL; M = M->next) { if (M->aux == UNKNOWN && M->loc != NULL && M->loc->aux == GOOD) { M->mob = m++; M->aux = GOOD; Z->n_mob++; } } } for (Z = zon, z = 0, o = 0; z < nz; ++z, ++Z) { for (O = Z->objs; O != NULL; O = O->next) { if ((F = O->aux) == BAD || F == GOOD) continue; if (F == REFERRED || F == DEFINED) { log ('O', O, O->zone, "Object isn't properly checked."); O->aux = BAD; continue; } if (F == UNKNOWN) F = O; if (!obj_ok (O, F, IS_CHECK)) { log ('O', O, O->zone, "General error with object."); O->aux = BAD; } else { O->aux = GOOD; } } } for (Z = zon, z = 0; z < nz; ++z, ++Z) { for (L = Z->locs; L != NULL; L = L->next) { if (L->aux != GOOD) continue; for (k = 0; k < NEXITS; k++) { E = L->exits[k]; switch (L->exit_types[k]) { case '^': O = (XOBJ *) E; if (O->cflag != IN_ROOM || O->loc != L || O->aux != GOOD || (F = O->linked) == NULL || F->cflag != IN_ROOM) { L->exits[k] = NULL; L->exit_types[k] = 0; } break; case '#': break; case ' ': if (E == NULL || E->aux != GOOD) { L->exits[k] = NULL; L->exit_types[k] = 0; } break; case 0: if (L->exits[k] != NULL) { log ('L', (XOBJ *) L, L->zone, "Garbage in exit %s, should be none.", Exits[k]); L->exits[k] = NULL; } break; default: log ('L', (XOBJ *) L, L->zone, "Garbage in exit %s, exit type = %c[%03o]", Exits[k], L->exit_types[k], L->exit_types[k]); L->exits[k] = NULL; L->exit_types[k] = 0; break; } } } } for (O = obj_list, o = *lo = 0; O != NULL; O = O->the_next) { if (O->aux != GOOD || (O->linked != NULL && O->linked->aux != GOOD)) { printf ("\nPanic Object %s@%s were supposed to be good!\n", O->name, O->zone->name); xexit (1); } O->obj = o++; if (O->linked != NULL) (*lo)++; } *mm = m; *oo = o; *ll = l; } void write_zone (XZON * ZON, int numz) { FILE *F; int z; XZON *Z; F = Do_fopen (zone_file, "w"); fprintf (F, "%d\n", numz); for (Z = ZON, z = 0; z < numz; ++z, ++Z) { fprintf (F, "%s %d %d\n", Z->name, Z->latitude, Z->rainfall); } fclose (F); } void write_mob (XZON * ZON, int numz, int m) { FILE *F; FILE *H; int z; int i = 0; XZON *Z; XMOB *M; char zn[32]; char n[64]; F = Do_fopen (mob_file, "w"); H = Do_fopen (mobh_file, "w"); fprintf (F, "%d\n", m); /* Print out header */ (void) fprintf (H, "\ /*\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", main_file); for (Z = ZON, z = 0; z < numz; ++z, ++Z) { strcpy (zn, Z->name); uppercase (zn); fprintf (H, "#define MOBMIN_%s\t%d\n", zn, Z->mob); fprintf (H, "#define MOBMAX_%s\t%d\n", zn, Z->mob + Z->n_mob); for (M = Z->mobs; M != NULL; M = M->next, i++) { if (M->aux != GOOD) { log ('M', (XOBJ *) M, Z, "Mobile not found good."); continue; } fprintf (F, "%s^\n", M->pname); fprintf (F, "%d %d %d %d %d %d %d %d %d %d %d\n", i, i, z, -(M->loc->loc), M->str, M->damage, M->agg, M->armor, M->speed, M->vis, M->wimpy); fprintf (F, "0x%08lx:0x%08lx 0x%08lx:0x%08lx:0x%08lx\n", M->sflags.h, M->sflags.l, M->pflags.u, M->pflags.h, M->pflags.l); fprintf (F, "0x%08lx:0x%08lx 0x%08lx:0x%08lx\n", M->mflags.h, M->mflags.l, M->eflags.l, M->eflags.h); fprintf (F, "%s^\n", M->desc); fprintf (F, "%s^\n\n", M->exam == NULL ? "" : M->exam); strcpy (n, M->name); uppercase (n); fprintf (H, "#define MOB_%s_%s\t%d\n", zn, n, M->mob); } } fprintf (H, "\n#endif\n"); fclose (F); fclose (H); } void write_xobj (FILE * F, FILE * H, FILE * X, XOBJ * O, int obj_num) { XLOC *L = NULL; XOBJ *C = NULL; XMOB *M = NULL; XZON *Z = NULL; int x; char *s; int obj_loc = 0; char n[64]; char z[32]; L = O->loc; switch (O->cflag) { case IN_ROOM: Z = L->zone; obj_loc = -(L->loc); break; case IN_CONTAINER: C = (XOBJ *) L; Z = C->zone; obj_loc = C->obj; break; case CARRIED_BY: case WIELDED_BY: case WORN_BY: case BOTH_BY: M = (XMOB *) L; Z = M->zone; obj_loc = M->mob; break; default: printf ("\nPanic carry flag is %d!\n", O->cflag); xexit (1); } fprintf (F, "%s %s %d %d %d %d %d %d %d %d %d %d %ld:%ld %ld %d %d %d %d\n", O->pname, O->aname ? O->aname : "<null>", O->zone->zone, obj_num, obj_num, O->linked ? O->linked->obj : -1, O->vis, O->cflag, obj_loc, O->state, O->damage, O->armor, O->oflags.l, O->oflags.h, O->aflags, O->mstate, O->bvalue, O->osize, O->oweight); for (x = 0; x < 4; ++x) { if ((s = O->desc[x]) == NULL) s = ""; fprintf (F, "%s^\n", s); } if ((s = O->examine) == NULL) s = ""; fprintf (F, "%s^\n\n", s); strcpy (n, O->name); uppercase (n); strcpy (z, O->zone->name); uppercase (z); fprintf (H, "#define OBJ_%s_%s\t%d\n", z, n, O->obj); } void write_obj (XZON * ZON, int numz, int o, int l) { FILE *F; FILE *H; FILE *X = NULL; int i; XOBJ *O; F = Do_fopen (obj_file, "w"); H = Do_fopen (objh_file, "w"); fprintf (F, "%d\n", o); /* Print out header */ (void) fprintf (H, "\ /*\n\ **\tObject 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", main_file); for (O = obj_list, i = 0; O != NULL; O = O->the_next, i++) write_xobj (F, H, X, O, i); fclose (F); fprintf (H, "\n#endif\n"); fclose (H); } static char * c_ex (char *s, int x, int *Ex, Boolean * ex, Boolean neg) { char c; if (ex[x]) { ex[x] = False; } else if ((Ex[x] == 0) == neg) { ex[x] = True; } else { c = s[-1]; while (*s != 0) { if (*s == '^' && s[1] == c) return s + 2; ++s; } } return s; } static char * c_zo (char *s, Boolean neg) { XZON *Z; char zname[64]; char *t, *q; int z; if (*s != '(') return s; for (t = zname, q = s; *++q != 0 && *q != ')';) *t++ = *q; if (*q == 0) return s; ++q; if (t == zname) return q; *t = 0; for (z = 0, Z = zones; z < num_z; ++z, ++Z) { if (strcasecmp (zname, Z->name) == 0) continue; neg = !neg; break; } if (neg) return q; while (*q != 0 && (*q != '^' || q[1] != 'z')) ++q; if (*q == 0) return q; q += 2; if (*q == '(' && q[1] == ')') q += 2; return q; } void write_loc (XZON * ZON, int numz, int l) { FILE *F; FILE *H; int z; int x; int y = 0; int i = -1; Boolean neg; Boolean ex[NEXITS]; /* True if in condition ^<exit> */ int Ex[NEXITS]; /* The calculated exit number.. */ XZON *Z; XLOC *L; XLOC *E; char *s; char c; char zn[32]; char n[64]; F = Do_fopen (loc_file, "w"); H = Do_fopen (loch_file, "w"); fprintf (F, "%d\n", l); /* Print out header */ (void) fprintf (H, "\ /*\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", main_file); for (Z = ZON, z = 0; z < numz; ++z, ++Z) { strcpy (zn, Z->name); uppercase (zn); fprintf (H, "#define LOCMIN_%s\t%d\n", zn, -(Z->loc)); fprintf (H, "#define LOCMAX_%s\t%d\n", zn, -(Z->loc + Z->n_loc)); for (L = Z->locs; L != NULL; L = L->next, i--) { if (L->aux != GOOD) { log ('L', (XOBJ *) L, Z, "Location not found good."); continue; } fprintf (F, "%d %d", /*L->loc, */ i, z); for (x = 0; x < NEXITS; x++) { E = L->exits[x]; ex[x] = False; switch (L->exit_types[x]) { case '^': y = DOOR + ((XOBJ *) L->exits[x])->obj; break; case '#': y = (int) (L->exits[x]); break; case ' ': y = -(L->exits[x]->loc); break; case 0: y = 0; break; default: printf ("\nPanic Room %d has illegal exit type %s: %c!\n", L->loc, Exits[x], L->exit_types[x]); xexit (1); } Ex[x] = y; fprintf (F, " %d", y); } fprintf (F, "\n0x%08lx:0x%08lx\n%d\n%s^\n%s^\n", L->lflags.h, L->lflags.l, L->altitude, L->name, L->pname); s = L->description; while (*s != 0) { if ((c = *s++) != '^') { putc (c, F); continue; } neg = False; if (*s == '!') { neg = True; ++s; } switch (c = *s++) { case 'n': s = c_ex (s, 0, Ex, ex, neg); continue; case 'e': s = c_ex (s, 1, Ex, ex, neg); continue; case 's': s = c_ex (s, 2, Ex, ex, neg); continue; case 'w': s = c_ex (s, 3, Ex, ex, neg); continue; case 'u': s = c_ex (s, 4, Ex, ex, neg); continue; case 'd': s = c_ex (s, 5, Ex, ex, neg); continue; case 'z': s = c_zo (s, neg); continue; default: putc (c, F); continue; } } fprintf (F, "^\n"); strcpy (n, L->name); uppercase (n); fprintf (H, "#define LOC_%s_%s\t%d\n", zn, n, -(L->loc)); } } fclose (F); fprintf (H, "\n#endif\n"); fclose (H); } void write_files (XZON * ZON, int numz, int l, int o, int lo, int m) { write_zone (ZON, numz); write_mob (ZON, numz, m); write_obj (ZON, numz, o, lo); write_loc (ZON, numz, l); } void make_data (char *file, Boolean silent) { int numz; int numl; int numo; int numm; int numlo; numz = read_main(file); read_zones (zones, numz, silent); clean_up (zones, numz, &numm, &numo, &numlo, &numl); write_files (zones, numz, numl, numo, numlo, numm); if (!silent) { printf("\nGenerate: text space is %d/%d\n", textsp - texts, sizeof(texts)); printf("Generate: %d zones, %d locs, %d objs (%d linked), %d mobs.\n", numz, numl, numo, numlo, numm); if (n_logs > 0) { printf("Generate errors: %d, logfile %s.\n\n", n_logs, log_file); fprintf(LogFile, "Total number of logs is %d.\n", n_logs); } else printf("\nNo errors, log file %s is empty.\n\n", log_file); } fclose (LogFile); } void log (char t, XOBJ * O, XZON * Z, char *f,...) { va_list pvar; char *n; char *z; char *p; char *q; char b[1024]; va_start (pvar, f); vsprintf (b, f, pvar); z = Z->name; ++n_logs; switch (t) { case 'L': n = ((XLOC *) O)->name; p = ((XLOC *) O)->pname; q = "Loc"; break; case 'M': n = ((XMOB *) O)->name; p = ((XMOB *) O)->pname; q = "Mob"; break; case 'O': n = O->name; p = O->pname; q = "Obj"; break; default: fprintf (stderr, "\nIllegal type %c.\n", t); exit (1); } fprintf (LogFile, "%s: %s@%s[%s] %s\n", q, n, z, p, b); }