/***************************************************************************** ** BOOTSTRAP ******************************************************************************/ #define BOOTSTRAP_C #include <malloc.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <unistd.h> #include <limits.h> #include "kernel.h" #include "config.h" #include "mudtypes.h" #include "oflags.h" #include "bootstrap.h" #include "board.h" #include "misc.h" #include "log.h" #include "actions.h" #include "wizlist.h" #include "timing.h" #include "parse.h" #include "special.h" #include "levels.h" #include "utils.h" #ifdef INTERMUD #include "InterMud/intermud.h" #endif #ifdef ABERCHAT #include "AberChat/client.h" #endif #define get_newline(f) while (getc(f) != '\n') #define ID_CNT_START 200000L EXTERN int errno; EXTERN char *Pflags[]; EXTERN char *WizLevels[]; PRIVATE void boot_world (void); PRIVATE int boot_players (void); PRIVATE int boot_mobiles (FILE * f, char *fname); PRIVATE int boot_levels (FILE * f, char *fname); PRIVATE int boot_locations (FILE * f, char *fname); PRIVATE int boot_objects (FILE * f, char *fname); PRIVATE int boot_pflags (FILE * f, char *fname); PRIVATE int boot_verbs (FILE * f, char *fname); PRIVATE int boot_zones (FILE * f, char *fname); PRIVATE int boot_id_counter (void); PRIVATE Boolean read_pflags (FILE * f, PFLAGS p[]); PRIVATE char *get_string (FILE * f); char *PFT[] = { "PflagApprentice", "MaskApprentice", "PflagEmeriti", "MaskEmeriti", "PflagWizard", "MaskWizard", "PflagSenior", "MaskSenior", "PflagCounsel", "MaskCounsel", "PflagArchwizard", "MaskArchwizard", "PflagHighArch", "MaskHighArch", "PflagAdvisor", "MaskAdvisor", "PflagDemigod", "MaskDemigod", "PflagHighDemi", "MaskHighDemi", "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]; boot_world (); boot_bboards (); mem_used = boot_id_counter (); printf (" o P:Players : %d bytes.\n", tot_used = boot_players ()); if ((bootf = (FILE *) bopen (BOOTSTRAP)) == NULL) { mudlog ("bopen: Bootstrap failed for \"" BOOTSTRAP "\".\n"); mudlog ("bopen: %s.\n", strerror(errno)); return -1; } while (fgets (x, sizeof x, bootf)) { if ((y = strchr (x, '\n'))) *y = '\0'; printf (" o %-13s:", x); if ((y = strchr (x, ':')) == NULL) { printf ("\nInvalid bootstrap declaration\n"); return -1; } if ((f = (FILE *) bopen (++y)) == NULL) { printf (" (Can't open file %s)", y); } switch (x[0]) { case 'A': mem_used = boot_extern (f, y); break; case 'M': 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; #ifdef ABERCHAT case 'C': mem_used = boot_aberchat(f,y); break; #endif #ifdef INTERMUD case 'I': mem_used = boot_intermud(f, y); break; #endif 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) bclose (f); if (mem_used < 0) { printf(" Failed.\n"); fclose (bootf); return mem_used; } printf (" %d bytes.\n", mem_used); tot_used += mem_used; } fclose (bootf); printf ("\n Startup completed: %d bytes used. \n\n", tot_used); return tot_used; } PRIVATE void boot_world (void) { WORLD_REC *w = &the_world_rec; w->w_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; w->w_start_loc = 0; last_healall = 0; } PRIVATE 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; p->linkdead = False; } return sizeof (PLAYER_REC) * max_players; } PRIVATE 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). */ PUBLIC 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) { mudlog("Invalid number of mobiles in file."); return -1; } if (numchars + num_infile > char_array_len) { int oldlen = char_array_len; if (numchars + num_infile > GLOBAL_MAX_MOBS) { mudlog("Total number of mobiles exceeds mobile table limit."); 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) { mudlog("Format of mobiles file is not correct."); mudlog("Last correct read mobile: %d",ct-1-max_players); 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:0x%lx", &sflags_reset (ct).b3, &sflags_reset (ct).b2, &sflags_reset (ct).b1, &pflags_reset (ct).b3, &pflags_reset (ct).b2, &pflags_reset (ct).b1); get_newline (f); fscanf (f, "0x%8lx:0x%8lx", &mflags_reset (ct).h, &mflags_reset (ct).l); 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); #ifdef LEAVE_CORPSES pftxt_reset(ct) = pftxt(ct); pexam_reset(ct) = pexam(ct); #endif 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; } PRIVATE 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_APPREN) { printf ("Number of levels in levels file (%d) doesn't match LVL_APPREN " "(%d).\n", ct, LVL_APPREN); return -1; } for (i = 1; i <= ct; i++) { fscanf (f, "%d", &v); get_newline (f); levels[i] = v; } return sizeof(levels); } PRIVATE 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. */ PUBLIC 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 %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], &r->r_exit_reset[6], &r->r_exit_reset[7], &r->r_exit_reset[8], &r->r_exit_reset[9]) != 12) return -1; get_newline (f); fscanf (f, "0x%8lx:0x%8lx:0x%8lx",&r->r_flags_reset.b3, &r->r_flags_reset.b2, &r->r_flags_reset.b1); 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; } PRIVATE 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). */ PUBLIC 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) { mudlog ("BOOTSTRAP ERROR: o.1"); 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 %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), &omaxstate (ct), &ovalue_reset (ct), &osize_reset (ct)) != 15) { mudlog ("BOOTSTRAP ERROR: o.2 [%s %s]", name, altname); return -1; } get_newline (f); fscanf(f,"0x%08lx:0x%08lx:0x%08lx",&obits_reset(ct).b3, &obits_reset(ct).b2, &obits_reset(ct).b1); get_newline(f); /* If it allready 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), tst_doublebit(&obits_reset(ct),OFL_CONTAINER) ? 10 : 0); /* xtstbit (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; } PRIVATE int boot_pflags (FILE * f, char *fname) { WORLD_REC *w = &the_world_rec; PFLAGS p[2*MAX_LEV_IMM]; 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 < MAX_LEV_IMM; ++x) { w->w_pflags[x] = p[y++]; w->w_mask[x] = p[y++]; } return sizeof(PFLAGS) * 2; } PRIVATE int boot_verbs (FILE * f, char *fname) { return Read_Verbs(f); } PRIVATE int boot_zones (FILE * f, char *fname) { int ct, mem_used, loc; 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,&loc); zname (ct) = COPY (x); init_intset (zlocs (ct), 15); init_intset (zmobs (ct), 5); init_intset (zobjs (ct), 10); ztemporary (ct) = False; zstartloc(ct) = convroom(loc); mem_used += strlen (x) + 1; /* add the space for the intsets later */ } return mem_used; } PRIVATE char * id_counter_file () { return ID_COUNTER; } /* Boot ID counter and initialize ID table. */ PRIVATE int boot_id_counter (void) { int mem_used = 0; FILE *f = fopen (id_counter_file (), "r"); printf (" o I: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 ("%d bytes.\n", mem_used = get_table_mem_usage (&id_table)); return mem_used; } PUBLIC 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 ? */ PRIVATE Boolean islegal (int c) { return isalpha (c) || c == '/'; } /* * ** Read pflags. */ PRIVATE 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[2048]; f.b3 = f.b2 = f.b1 = 0; w = -1; for (i = 0; i < 2*MAX_LEV_IMM; i++) { p[i].b3 = p[i].b2 = p[i].b1 = 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 >= 2*MAX_LEV_IMM) { 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) { k = 1 << (v-64); if (y>0) { p[w].b3 |= k; } else if (y<0) { p[w].b3 &= ~k; } else { for (i=w; i <2*MAX_LEV_IMM; i += 2) { p[i].b3 |= k; } } } else if (v >= 32) { k = 1 << (v - 32); if (y>0) { p[w].b2 |= k; } else if (y < 0) { p[w].b2 &= ~k; } else { for (i=w; i < 2*MAX_LEV_IMM; i += 2) { p[i].b2 |= k; } } } else { k = 1 << v; if (y > 0) { p[w].b1 |= ~k; } else if (y < 0) { p[w].b1 &= ~k; } else { for (i = w; i < 2*MAX_LEV_IMM; i += 2) { p[i].b1 |= k; } } } y = 0; } } return (w >= 0); } PRIVATE char * get_string (FILE * f) { char *y; char x[2048]; for (y = x; (*y = fgetc (f)) != '^'; y++); *y = 0; get_newline (f); return COPY (x); }