#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include "kernel.h" #include "bootstrap.h" #include "wizlist.h" #include "actions.h" #include "timing.h" #include "oflags.h" #include "nflags.h" #include "eflags.h" #include "log.h" #define get_newline(f) while (getc(f) != '\n') extern int errno; extern char *Pflags[]; extern char *WizLevels[]; static void boot_world (void); static int boot_players (void); static int boot_mobiles (FILE * f, char *fname); static int boot_levels (FILE * f, char *fname); static int boot_locations (FILE * f, char *fname); static int boot_objects (FILE * f, char *fname); static int boot_pflags (FILE * f, char *fname); static int boot_verbs (FILE * f, char *fname); static int boot_zones (FILE * f, char *fname); static int boot_id_counter (void); static Boolean read_pflags (FILE * f, PFLAGS p[]); static char *get_string (FILE * f); #define ID_CNT_START 200000L char *PFT[] = {"PflagApprentice", "MaskApprentice", "PflagWizard", "MaskWizard", "PflagProphet", "MaskProphet", "PflagArchwizard", "MaskArchwizard", "PflagAdvisor", "MaskAdvisor", "PflagAvatar", "MaskAvatar", "PflagGod", "MaskGod", "PflagMaster", "MaskMaster", "Comment", TABLE_END}; int bootstrap (void) { FILE *bootf, *f; int mem_used = 0; int tot_used = 0; char *y, x[128]; Boolean not_loaded = False; boot_world (); printf ("\niDiRT Bootstrap Loader\n"); mem_used = boot_id_counter (); printf (" players\t: Allocated %d Bytes.\n", tot_used = boot_players ()); if ((bootf = fopen (BOOTSTRAP, "r")) == NULL) { printf ("fopen: Bootstrap failed for \"" BOOTSTRAP "\".\n"); printf ("fopen: %s.\n", sys_errlist[errno]); return -1; } while (fgets (x, sizeof x, bootf)) { if ((y = strchr (x, '\n'))) *y = '\0'; printf (" %s", x); if ((y = strchr (x, ':')) == NULL) { printf ("\nInvalid bootstrap declaration\n"); return -1; } #ifdef USE_ZOPEN if ((f = zopen (++y)) == NULL) { not_loaded = True; } #else if ((f = fopen (++y, "r")) == NULL) { not_loaded = True; } #endif switch (x[0]) { case 'A': mem_used = boot_extern (f, y); break; case 'C': mem_used = boot_mobiles (f, y); break; case 'E': mem_used = boot_levels (f, y); break; case 'H': mem_used = boot_hours (f, y); break; case 'L': mem_used = boot_locations (f, y); break; case 'O': mem_used = boot_objects (f, y); break; case 'P': mem_used = boot_pflags (f, y); break; case 'V': mem_used = boot_verbs (f, y); break; case 'W': set_wizfile (y); mem_used = boot_wizlist (f, y); break; case 'Z': mem_used = boot_zones (f, y); break; } if (f != NULL) fclose (f); if (mem_used < 0) { fclose (bootf); return mem_used; } printf ("\t: Allocated %d Bytes.", mem_used); tot_used += mem_used; if (not_loaded) printf (" (Can't open %c file %s)\n", x[0], y); else printf ("\n"); not_loaded = False; } fclose (bootf); printf ("\n Total Memory Allocated : %d Bytes.\n", tot_used); return 0; } static void boot_world (void) { WORLD_REC *w = &the_world_rec; CLIMATE_REC *c = &the_climate_rec; c->weather = 0; w->w_lock = 0; w->w_mob_stop = 0; w->w_peace = 0; w->w_max_users = max_players; w->w_tournament = 0; } static int boot_players (void) { int i; PLAYER_REC *p = players = NEW (PLAYER_REC, max_players); for (i = 0; i < max_players; i++, p++) { p->inp_handler = NULL; p->iamon = False; } return sizeof (PLAYER_REC) * max_players; } static int boot_mobiles (FILE * f, char *fname) { int mem_used = 0; int new_mem; int i; int mobs_loaded; if (f == NULL) return -1; numchars = max_players; ublock = NEW (UBLOCK_REC, char_array_len = numchars + 150); mem_used += sizeof (UBLOCK_REC) * char_array_len; for (i = 0; i < max_players; i++) { setpname (i, ""); pnum (i) = -1; } if ((new_mem = load_mobiles (-1, f, &mobs_loaded, NULL)) < 0) return -1; num_const_chars = mobs_loaded + max_players; return mem_used + new_mem; } /* Read mobile spesifications from a file and load them into the game in the * zone specified. If it is -1, then use the zone specifications given in * the file for each mobile sepeartely. Return the number of mobiles actually * read, the total number of mobiles in the file, * and the amount of any extra memory allocated as the function value. * (-1 on error). */ int load_mobiles (int zone, FILE * f, int *loaded, int *infile) { int ct, c, i; int mem_used = 0; int num_ld, num_infile; char x[256]; char *p; fgets (x, sizeof x, f); if ((num_ld = num_infile = atoi (x)) <= 0) return -1; if (numchars + num_infile > char_array_len) { int oldlen = char_array_len; if (numchars + num_infile > GLOBAL_MAX_MOBS) return -1; char_array_len = numchars + 75 + num_infile; ublock = resize_array (ublock, sizeof (Mobile), oldlen, char_array_len); mem_used += sizeof (Mobile) * (char_array_len - oldlen); } for (ct = numchars; ct < numchars + num_ld; ct++) { ptemporary (ct) = False; for (p = pname (ct), i = 0; (c = getc (f)) != '^' && i < MNAME_LEN; *p++ = c, i++) ; *p = '\0'; get_newline (f); if (fscanf (f, "%ld %d %d %ld %d %d %d %d %d %d %d", &mob_id (ct), &pnum (ct), &pzone (ct), &ploc_reset (ct), &pstr_reset (ct), &pdam_reset (ct), &pagg_reset (ct), &parmor_reset (ct), &pspeed_reset (ct), &pvis_reset (ct), &pwimpy_reset (ct)) != 11) return -1; plev_reset (ct) = -1; /* Negative level for all mobiles. */ get_newline (f); /* If the mobile is allready in the game, skip that record */ if (mob_id (ct) >= ID_CNT_START && !insert_entry (mob_id (ct), ct, &id_table)) { get_newline (f); get_newline (f); for (i = 1; i <= 2; i++) { while (getc (f) != '^') ; } get_newline (f); get_newline (f); --ct; --num_ld; continue; } fscanf (f, "0x%8lx:0x%8lx 0x%8lx:0x%8lx:0x%8lx", &sflags_reset (ct).h, &sflags_reset (ct).l, &pflags_reset (ct).u, &pflags_reset (ct).h, &pflags_reset (ct).l); get_newline (f); fscanf (f, "0x%8lx:0x%8lx 0x%8lx 0x%8lx", &mflags_reset (ct).h, &mflags_reset (ct).l, &nflags_reset (ct), &eflags_reset (ct)); /* Quick Language Patch */ setplang (ct, NFL_ENGLISH); get_newline (f); pname_reset (ct) = COPY (pname (ct)); pftxt (ct) = get_string (f); mem_used += strlen (pftxt (ct)) + strlen (pname_reset (ct)) + 2; if (EMPTY (pexam (ct) = get_string (f))) { FREE (pexam (ct)); pexam (ct) = NULL; } else { mem_used += strlen (pexam (ct)); } get_newline (f); init_intset (pinv (ct), 4); mem_used += get_set_mem_usage (pinv (ct)); if (zone > -1) pzone (ct) = zone; zadd_mob (ct, pzone (ct)); } numchars += num_ld; if (loaded != NULL) *loaded = num_ld; if (infile != NULL) *infile = num_infile; return mem_used; } static int boot_levels (FILE * f, char *fname) { int i, v, ct; if (f == NULL) return -1; fscanf (f, "%d", &ct); get_newline (f); if (ct != LVL_WIZARD) { printf ("Number of levels in levels file (%d) doesn't match LVL_WIZARD" "(%d).\n", ct, LVL_WIZARD); return -1; } for (i = 1; i <= ct; i++) { fscanf (f, "%d", &v); get_newline (f); levels[i] = v; } return 0; } static int boot_locations (FILE * f, char *fname) { int mem_used = 0; int new_mem; if (f == NULL) return -1; numloc = 0; room_data = NEW (Location, loc_array_len = 800); mem_used += sizeof (Location) * loc_array_len; if ((new_mem = load_locations (-1, f, &num_const_locs, NULL)) < 0) return -1; return mem_used + new_mem; } /* Load locations from file into the game. Return the number of rooms the * file contained, and the number actually loaded. Return mem-used for value. */ int load_locations (int zone, FILE * f, int *loaded, int *infile) { int ct, mem_used = 0; int num_ld, num_infile; Location *r; char x[128]; int i; fgets (x, sizeof x, f); if ((num_ld = num_infile = atoi (x)) <= 0) return -1; if (numloc + num_infile > loc_array_len) { int oldlen = loc_array_len; if (numloc + num_infile > GLOBAL_MAX_LOCS) return -1; loc_array_len = 100 + numloc + num_infile; room_data = resize_array (room_data, sizeof (Location), oldlen, loc_array_len); mem_used += sizeof (Location) * (loc_array_len - oldlen); } for (r = room_data + numloc, ct = numloc; ct < numloc + num_ld; ct++, r++) { if (fscanf (f, "%ld %d %ld %ld %ld %ld %ld %ld", &r->id, &r->zone, &r->r_exit_reset[0], &r->r_exit_reset[1], &r->r_exit_reset[2], &r->r_exit_reset[3], &r->r_exit_reset[4], &r->r_exit_reset[5]) != 8) return -1; get_newline (f); fscanf (f, "0x%8lx:0x%8lx", &r->r_flags_reset.h, &r->r_flags_reset.l); get_newline (f); if (r->id >= ID_CNT_START && !insert_entry (r->id, convroom (ct), &id_table)) { for (i = 1; i <= 2; i++) { while (getc (f) != '^') ; } get_newline (f); --r; --ct; --num_ld; continue; } r->temporary = False; r->touched = True; r->r_short = get_string (f); r->r_long = get_string (f); mem_used += strlen (r->r_short) + strlen (r->r_long) + 2; init_intset (&r->objects, 5); init_intset (&r->mobiles, 3); init_intset (&r->exits_to_me, 3); if (zone > -1) r->zone = zone; zadd_loc (convroom (ct), r->zone); mem_used += get_set_mem_usage (&r->objects) + get_set_mem_usage (&r->mobiles) + get_set_mem_usage (&r->exits_to_me); } numloc += num_ld; if (loaded != NULL) *loaded = num_ld; if (infile != NULL) *infile = num_infile; return mem_used; } static int boot_objects (FILE * f, char *fname) { int mem_used = 0; int new_mem; if (f == NULL) return -1; numobs = 0; objects = NEW (Object, obj_array_len = 500); mem_used += sizeof (Object) * 500; if ((new_mem = load_objects (-1, f, &num_const_obs, NULL)) < 0) return -1; return mem_used + new_mem; } /* Read object spesifications from a file and load them into the game in the * zone specified. If it is -1, then use the zone specifications given in * the file for each object sepeartely. Return the number of objects actually * read, the total number of objects in the file, * and the amount of any extra memory allocated as the function value. * (-1 on error). */ int load_objects (int zone, FILE * f, int *loaded, int *infile) { int j, ct, mem_used = 0; int num_ld, num_infile; char name[64], altname[64]; long int link; j = fscanf (f, "%d", &num_infile); if (j != 1 || (num_ld = num_infile) <= 0) { return -1; } get_newline (f); if (numobs + num_infile > obj_array_len) { int oldlen = obj_array_len; if (numobs + num_infile > GLOBAL_MAX_OBJS) { return -1; } obj_array_len = 75 + numobs + num_infile; objects = resize_array (objects, sizeof (Object), oldlen, obj_array_len); mem_used += sizeof (Object) * (obj_array_len - oldlen); } for (ct = numobs; ct < numobs + num_ld; ct++) { if (fscanf (f, "%s %s %d %ld %d " "%ld %d %d %ld " "%d %d %d " "0x%8lx:0x%8lx:0x%8lx" "%d %d %d %*d", name, altname, &ozone (ct), &obj_id (ct), &onum (ct), &link, &ovis_reset (ct), &ocarrf_reset (ct), &oloc_reset (ct), &state_reset (ct), &odamage_reset (ct), &oarmor_reset (ct), &obits_reset (ct).u, &obits_reset (ct).h, &obits_reset (ct).l, &omaxstate (ct), &ovalue_reset (ct), &osize_reset (ct)) != 18) { mudlog ("BOOTSTRAP: load_objects; fscanf() failed"); return -1; } get_newline (f); /* If it already existed, skip it. */ if (obj_id (ct) >= ID_CNT_START && !insert_entry (obj_id (ct), ct, &id_table)) { for (j = 1; j <= 5; j++) { while (getc (f) != '^') ; } get_newline (f); get_newline (f); --ct, --num_ld; continue; } oname (ct) = COPY (name); oaltname (ct) = COPY (altname); if (link <= -1) olinked (ct) = -1; else if (link < numobs + num_infile) olinked (ct) = link; else if ((link = lookup_entry (link, &id_table)) != NOT_IN_TABLE) { olinked (ct) = link; olinked (link) = ct; } else olinked (ct) = -1; mem_used += strlen (name) + strlen (altname) + 2; for (j = 0; j < 4; j++) { olongt (ct, j) = get_string (f); mem_used += strlen (olongt (ct, j)) + 1; } if (zone == -1) { oexam_text (ct) = NULL; oexamine (ct) = ftell (f); for (j = 1; fgetc (f) != '^'; j++) ; if (j == 1) oexamine (ct) = 0; } else { oexam_text (ct) = get_string (f); oexamine (ct) = 0; } otemporary (ct) = False; init_intset (oinv (ct), dtst_bit (&obits_reset (ct), OFL_CONTAINER) ? 10 : 0); if (zone > -1) ozone (ct) = zone; zadd_obj (ct, ozone (ct)); mem_used += get_set_mem_usage (oinv (ct)); } numobs += num_ld; if (loaded != NULL) *loaded = num_ld; if (infile != NULL) *infile = num_infile; return mem_used; } static int boot_pflags (FILE * f, char *fname) { WORLD_REC *w = &the_world_rec; PFLAGS p[16]; int x, y; if (f == NULL) return -1; if (!read_pflags (f, p)) { printf ("\nIllegal syntax in %s.\n", fname); return -1; } for (x = y = 0; x < 8; ++x) { w->w_pflags[x] = p[y++]; w->w_mask[x] = p[y++]; } return 0; } static int boot_verbs (FILE * f, char *fname) { int v, ct, mem_used; char x[64]; if (f == NULL) return -1; fscanf (f, "%d", &v); mem_used = sizeof (char *) * (v + 1); mem_used = sizeof (int) * (v + 1); verbtxt = NEW (char *, v + 1); verbnum = NEW (int, v + 1); for (ct = 0; ct < v; ct++) { fscanf (f, "%s %d", x, &verbnum[ct]); verbtxt[ct] = COPY (x); mem_used += strlen (x) + 1; } verbtxt[ct] = NULL; return mem_used; } static int boot_zones (FILE * f, char *fname) { int ct, mem_used; char x[64]; if (f == NULL) return -1; fgets (x, sizeof x, f); numzon = num_const_zon = atoi (x); zon_array_len = num_const_zon + 20; zoname = NEW (ZONE, zon_array_len); mem_used = sizeof (ZONE) * zon_array_len; for (ct = 0; ct < num_const_zon; ct++) { fscanf (f, "%s %*d", x); zname (ct) = COPY (x); init_intset (zlocs (ct), 15); init_intset (zmobs (ct), 5); init_intset (zobjs (ct), 10); ztemporary (ct) = False; mem_used += strlen (x) + 1; /* add the space for the intsets later */ } return mem_used; } static char * id_counter_file () { return ID_COUNTER; } /* Boot ID counter and initialize ID table. */ static int boot_id_counter (void) { int mem_used = 0; FILE *f = fopen (id_counter_file (), "r"); printf (" ID-table & ID-counter "); if (f == NULL) { printf ("(Creating %s)", id_counter_file ()); if ((f = fopen (id_counter_file (), "w")) == NULL) { printf ("fopen: Bootstrap failed for \"%s\".\n", id_counter_file ()); perror ("fopen"); exit (1); } fprintf (f, "%ld", id_counter = ID_CNT_START); } else { int status = fscanf (f, "%ld", &id_counter); if (status != 1 || id_counter < ID_CNT_START) { printf ("Erroneous contents in %s\n", id_counter_file ()); exit (1); } } fclose (f); init_inttable (&id_table, 1024); printf ("used %d bytes.\n", mem_used = get_table_mem_usage (&id_table)); return mem_used; } Boolean save_id_counter (void) { FILE *f; int status; if ((f = fopen (id_counter_file (), "w")) == NULL) { progerror (id_counter_file ()); return False; } status = fprintf (f, "%ld\n", id_counter); fclose (f); if (status == EOF) { progerror (id_counter_file ()); return False; } return True; } /* Is this a character legal in a Pflag ? */ static Boolean islegal (int c) { return isalpha (c) || c == '/'; } /* * ** Read pflags. */ static Boolean read_pflags (FILE * F, PFLAGS p[]) { int x; /* 0 = PX, MX, PW, MW, PA, MA, PD, MD, PG, MG */ int y; char *s; PFLAGS f; int k, v; int c; int w; int i; char b[160]; f.u = f.l = f.h = 0; w = -1; for (i = 0; i < 16; i++) { p[i].u = p[i].h = p[i].l = 0; } for (k = getc (F); k != EOF; k = getc (F)) { if (!islegal (k)) continue; for (s = b; islegal (k); k = getc (F)) *s++ = k; *s = 0; if (k != ':' || (x = tlookup (b, PFT)) == -1) return False; if (x >= 16) { while ((k = getc (F)) != EOF && k != '\n') ; if (k == EOF) break; continue; } if (x < w) return False; y = 0; w = x; while ((c = getc (F)) != ';') { if (c == EOF) return False; if (c == '+') { y = 1; continue; } else if (c == '-') { y = -1; continue; } else if (!islegal (c)) { y = 0; continue; } for (s = b; islegal (c); c = getc (F)) { *s++ = c; } ungetc (c, F); *s = 0; if ((v = tlookup (b, Pflags)) == -1) { printf ("\nUnknown Pflag: %s.", b); return False; } if (v >= 64) { v -= 64; k = 1 << v; if (y > 0) { p[w].u |= k; } else if (y < 0) { p[w].u &= ~k; } else if ((w & 1) == 0) { for (i = w; i < 16; i++) { p[i].u |= k; } } else { for (i = w; i < 16; i += 2) { p[i].u |= k; } } } if (v >= 32) { v -= 32; k = 1 << v; if (y > 0) { p[w].h |= k; } else if (y < 0) { p[w].h &= ~k; } else if ((w & 1) == 0) { for (i = w; i < 16; i++) { p[i].h |= k; } } else { for (i = w; i < 16; i += 2) { p[i].h |= k; } } } else { k = 1 << v; if (y > 0) { p[w].l |= k; } else if (y < 0) { p[w].l &= ~k; } else if ((w & 1) == 0) { for (i = w; i < 16; i++) { p[i].l |= k; } } else { for (i = w; i < 16; i += 2) { p[i].l |= k; } } } y = 0; } } return (w >= 0); } static char * get_string (FILE * f) { char *y, x[4096]; for (y = x; (*y = fgetc (f)) != '^'; y++) ; *y = 0; get_newline (f); return COPY (x); }