cdirt/ascii/
cdirt/data/BULL/
cdirt/data/ZONES/PENDING/
cdirt/pending/
cdirt/src/utils/
cdirt/utils/
#include "kernel.h"
#include "pflags.h"
#include "lflags.h"
#include "aflags.h"
#include "oflags.h"
#include "mflags.h"
#include "sflags.h"
#include "nflags.h"
#include "eflags.h"
#include "quests.h"
#include "flags.h"
#include "verbs.h"
#include "objsys.h"
#include "flagindex.h"

extern char *Oflags[];

char *TF[3] = {"False", "True", TABLE_END};
char *OO[3] = {"Off", "On", TABLE_END};

/* rather redundant... */

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;
  }
}


/* stores the current flags to a player file */

void store_flags(FILE *outfp, PERSONA *p) {
  int i, j, len;

  fprintf(outfp, "<flags>");

  for (i = 0 ; i < MAX_MOB_FLAGS ; i++) {
    len = mindex[i+1] - mindex[i];

    if (!strstr(Mobflags[i], "Reset")) {
      fprintf(outfp, "\n%s      ", Mobflags[i]);
      for (j = 0 ; j < len ; j++)
        fprintf(outfp, "%lx ", p->ublock.bits[mindex[i] + j]);
    }
  }
}

/* stores an objects flags to a file */

void store_obj_flags(FILE *outfp, int obj) {
  int i;
  char buff[256];
  char *p;

  for (i = 0 ; i < MAX_OBJ_FLAGS ; i++) {
    if (strstr(Objflags[i], "Reset")) {
      p = dump_bits(obits(obj), oindex, oflagsindex[i], i);
      if (*p) {
        strcpy(buff, Objflags[i]);
        *strstr(buff, "Reset") = 0;
        fprintf(outfp, "%s { %s}\n", buff, p);
      }
    }
  }
}

/* stores a location's flags to a file */

void store_loc_flags(FILE *outfp, int loc) {
  int i;
  Boolean set = False;
  char buff[256];
  char *p;

  for (i = 0 ; i < MAX_LOC_FLAGS ; i++) {
    if (strstr(Locflags[i], "Reset")) {
      p = dump_bits(lbits(loc), lindex, lflagsindex[i], i);
      if (*p) {
        strcpy(buff, Locflags[i]);
        *strstr(buff, "Reset") = 0;
        fprintf(outfp, "%s { %s}\n", buff, p);
        set = True;
      }
    }
  }
  if (!set)
    fprintf(outfp, "lflags { }\n");
}

/* stores a mobile's flags to a file */

void store_mob_flags(FILE *outfp, int mob) {
  int i;
  char buff[256];
  char *p;

  for (i = 0 ; i < MAX_MOB_FLAGS ; i++) {
    if (strstr(Mobflags[i], "Reset")) {
      p = dump_bits(mbits(mob), mindex, mobflagsindex[i], i);
      if (*p) {
        strcpy(buff, Mobflags[i]);
        *strstr(buff, "Reset") = 0;
        fprintf(outfp, "%s { %s}\n", buff, p);
      }
    }
  }
}

int boot_pflags(void) {
  char buff[256], *p, *q;
  int lev, oldlev, bitnum, i, type, len, j;
  long int *from, *to;
  FILE *fptr;

  oldlev = type = -1;

  if (!(fptr = fopen(DATA_DIR "/pflags", "r"))) {
    printf("Unable to open pflags file.\n");
    return(-1);
  }
  else 
    while (!feof(fptr)) {
      fgets(buff, 255, fptr);

      if ((p = strchr(buff, '\n')))
	*p = 0;

      if (*buff == '#' || allspaces(buff) || feof(fptr))
	continue;
      else {
      	if (!strncasecmp(buff, "Pflag", 5))
	  type = PFLAGS;
	else if (!strncasecmp(buff, "Mask", 4))
	  type = MASKS;
	else {
	  if (type == -1) {
	    printf("Boot Pflags: first line not PflagsLevel: or MaskLevel:\n");
	    return(-1);
	  }
	  else {               /* a line with names of flags on it */
	    q = buff;
	    
	    while (*q) {
	      for (p = q ; *p ; p++)
		if (!isspace(*p))
		  break;
	      
	      for (q = p ; *q ; q++)
		if (isspace(*q)) {
		  *q++ = 0;
		  break;
		}
	      
	      bitnum = tlookup(p, Pflags);
	      
	      if (bitnum == -1) {
		printf("Boot Pflags: Invalid flag (%s)\n", p);
		return(-1);
	      }
	      else
		set_bit(pbits(lev), pflindex, bitnum, True, type);

	      p = q;
	    }
	    continue;
	  }
	}
	
	if ((q = strchr(buff, ':')))   /* fall through here */
	  *q = 0;
	else {
	  printf("Boot Pflags: Invalid line (%s) - missing \":\"\n", buff);
	  return(-1);
	}
	
	if ((q = strchr(buff, ' ')))
	  *q = 0;
	if ((q = strchr(buff, '\n')))
	  *q = 0;

	if (type == PFLAGS)
	  p = buff + 5;
	else
	  p = buff + 4;
	
        if (EQ(p, "Novice"))
	  lev = 0;
	else if ((lev = tlookup(p, MWizLevels)) == -1) {
	  printf("Boot Pflags: Invalid level %s\n", p); 
	  return(-1);
	}
	else if (lev < oldlev) {
	  printf("Boot Pflags: Levels must come in order\n");
	  return(-1);
	}
	else {
	  if (oldlev != -1) {                     /* copy over older bits */
	    for (i = oldlev ; i < lev ; i++) {
	      from = &the_world->pbits[i][pflindex[MASKS]];
	      to = &the_world->pbits[i+1][pflindex[MASKS]];
	      len = pflindex[MASKS+1] - pflindex[MASKS];
	      
	      for (j = 0 ; j < len ; j++)
		to[j] = from[j];

	      from = &the_world->pbits[i][pflindex[PFLAGS]];
	      to = &the_world->pbits[i+1][pflindex[PFLAGS]];
	      len = pflindex[PFLAGS+1] - pflindex[PFLAGS];
	      
	      for (j = 0 ; j < len ; j++)
		to[j] = from[j];
	    }
	  }
	  oldlev = lev;
	}
      }
    }
  fclose(fptr);
  return(0);
}

void set_xpflags(long int bits[], int l) {
  long int *from, *to, len, i;

  from = &the_world->pbits[wlevel(l) - 1][pflindex[PFLAGS]];
  to = &bits[mindex[PFLAGS]];
  len = mindex[PFLAGS+1] - mindex[PFLAGS];

  for (i = 0 ; i < len ; i++)
    to[i] = from[i];

  from = &the_world->pbits[wlevel(l) - 1][pflindex[MASKS]];
  to = &bits[mindex[PMASK]];
  len = mindex[PMASK+1] - mindex[PMASK];

  for (i = 0 ; i < len ; i++)
    to[i] = from[i];  
}

/* loads the current flags from the player file */

void load_flags(char *flags, PERSONA *pers) {
  char *p, *q;
  int i, j;
  long int rslt;

  if (!*flags)
    return;
  else if ((p = strchr(flags, ' ')))
    *p = 0;
  else {
    mudlog("Invalid flags line: %s", flags);
    return;
  }

  while (isspace(*++p));

  if ((i = tlookup(flags, Mobflags)) == -1) {
    mudlog("Invalid flags type: %s", flags);
    return;
  }
  else {
    for (j = 0, q = p ; *q ; j++) {
      if (q = strchr(p, ' '))
        *q++ = 0;
      else
        q = p + strlen(p);
      sscanf(p, "%lx", &rslt);
      pers->ublock.bits[mindex[i] + j] = rslt;
      p = q;
    }
  }
}

/* This is used for copying reset bits to use bits */

void copy_bits(int bits[], int fpoints[], int flagsto, int flagsfrom) {
  int stop = fpoints[flagsfrom + 1];
  int i, j;

  for (i = fpoints[flagsfrom], j = fpoints[flagsto] ; i < stop ; i++, j++)
    bits[j] = bits[i];
}

/* Primitive for setting a bit in a flagset, use the macro instead */

void set_bit(long int bits[], int fpoints[], int bitnum, Boolean val, 
             int flagset) {
  int len = fpoints[flagset + 1] - fpoints[flagset];
  int intpos, bitpos;

  if (len * 32 <= bitnum || bitnum < 0)
    mudlog("Attempt to set bit %d of flagset %d", bitnum, flagset);
  else {
    intpos = fpoints[flagset] + (bitnum / 32);
    bitpos = bitnum % 32;

    if (val)
      xsetbit(bits[intpos], bitpos);
    else
      xclrbit(bits[intpos], bitpos);
  }
}

/* Primitive for testing a bit in a flagset, use the macro instead */

Boolean test_bit(long int bits[], int fpoints[], int bitnum, int flagset) {
  int len = fpoints[flagset + 1] - fpoints[flagset];
  int intpos, bitpos;

  if (len * 32 <= bitnum || bitnum < 0) {
    mudlog("Attempt to test bit %d of flagset %d", bitnum, flagset);
    return(False);
  }
  else {
    intpos = fpoints[flagset] + (bitnum / 32);
    bitpos = bitnum % 32;
   
    return(xtstbit(bits[intpos], bitpos));
  }
}

void obj_flags(int flagset, int viewflag, int edtflg, char *f_names[]) {
  int o, b, c;

  if (!ptstflg(mynum, viewflag) && plev(mynum) < LVL_GOD)
    bprintf("Pardon?\n");
  else if ((o = ob1) == -1)
    bprintf("What's that?\n");
  else {
    if (!*item2) {
      bprintf ("Object: %s\nFlags:\t", oname(o));
      show_bits(obits(o), oindex, f_names, flagset, False);
    }
    else if (!*item3) {
      if ((b = tlookup(item2, f_names)) == -1)
	bprintf("%s: No such flag.\n", item2);
      else {
	c = test_bit(obits(o), oindex, b, flagset);
	bprintf("Value of %s is %s\n", f_names[b], TF[c]);
      }
    }
    else {
      if ((b = tlookup(item2, f_names)) == -1)
	bprintf("%s: No such flag.\n", item2);
      else if ((c = tlookup(item3, TF)) == -1)
	bprintf("Value must be True or False.\n");
      else {
	if (!c)
	  set_bit(obits(o), oindex, b, False, flagset);
	else
          set_bit(obits(o), oindex, b, True, flagset);
      }
    }
  }
}

void loc_flags(int flagset, int viewflag, int edtflg, char *f_names[]) {
  int l, b, c;

  if (!ptstflg(mynum, viewflag) && plev(mynum) < LVL_GOD)
    bprintf("Pardon?\n");
  else if (!(l = find_loc_by_name(item1)))
    bprintf("Where's that?\n");
  else {
    if (!*item2) {
      bprintf ("Location: %s\nFlags:\t", lname(l));
      show_bits(lbits(l), lindex, f_names, flagset, False);
    }
    else if (!*item3) {
      if ((b = tlookup(item2, f_names)) == -1)
	bprintf("%s: No such flag.\n", item2);
      else {
	c = test_bit(lbits(l), lindex, b, flagset);
	bprintf("Value of %s is %s\n", f_names[b], TF[c]);
      }
    }
    else {
      if ((b = tlookup(item2, f_names)) == -1)
	bprintf("%s: No such flag.\n", item2);
      else if ((c = tlookup(item3, TF)) == -1)
	bprintf("Value must be True or False.\n");
      else {
	if (!c)
	  set_bit(lbits(l), lindex, b, False, flagset);
	else
          set_bit(lbits(l), lindex, b, True, flagset);
      }
    }
  }
}

void mob_flags(int flagset, int viewflag, int edtflag, char *f_names[]) {
  long int *bits;
  char *name;
  int lev, b, c;
  PERSONA d;
  Boolean file = False;
  int p = -1;

  if (!ptstflg(mynum, viewflag) && plev(mynum) < LVL_GOD)
    bprintf("Pardon?\n");
  else if ((p = fmbn(item1)) == -1 && !ptstflg(mynum, PFL_UAF) &&
    (plev(mynum) < LVL_GOD))
      bprintf("Who'se that?\n");
  else if (p == -1 && !getuaf(item1, &d))
    bprintf("No such persona in system.\n");
  else {
    if (pl1 == -1 || p != -1) {
      p = (pl1 == -1) ? mynum : p;
      name = pname(p);
      lev = plev(p);
      bits = mbits(p);
    }
    else {
      file = True;
      name = d.ublock.pname;
      lev = d.ublock.plev;
      bits = d.ublock.bits;
    }

    if (!EQ(name, pname(mynum)) && !ptstflg(mynum, edtflag))
      bprintf("You can only change your own, sorry.\n");
    else if (plev(mynum) < LVL_GOD &&
	     (!(EQ(name, pname(mynum))) && wlevel(plev(mynum)) <= wlevel(lev)))
      bprintf ("That is beyond your powers.\n");
    else if (!*item2) {
      bprintf ("Player/Mob: %s\nFlags:\n", name);
      show_bits(bits, mindex, f_names, flagset, False);
    }
    else if (!*item3) {
      if ((b = tlookup(item2, f_names)) == -1)
	bprintf("%s: No such flag.\n", item2);
      else {
	c = test_bit(bits, mindex, b, flagset);
	bprintf("Value of %s is %s\n", f_names[b], TF[c]);
      }
    }
    else {
      if ((b = tlookup(item2, f_names)) == -1)
	bprintf("%s: No such flag.\n", item2);
      else if ((c = tlookup(item3, TF)) == -1)
	bprintf("Value must be True or False.\n");
      else if (plev(mynum) < LVL_GOD && 
	       (flagset == PMASK || flagset == PFLAGS) && !ptstmsk(mynum, b))
	bprintf("You don't have that mask bit.\n");
      else {
	if (p != mynum)
	  mudlog("FLAG: %s by %s, %s = %s", name, pname(mynum), 
		 f_names[b], TF[c]);
	if (!c)
	  set_bit(bits, mindex, b, False, flagset);
	else
          set_bit(bits, mindex, b, True, flagset);

	if (file)
	  putuaf (&d);
      }
    }
  }
}

Boolean flags_parse(int verb) {
  switch (verb) {
  case VERB_AFLAGS:
    if (ob1 != -1 && !otstbit(ob1, OFL_WEARABLE)) {
      bprintf("That isn't wearable.\n");
      break;
    }  
    else 
      obj_flags(AFLAGS, PFL_AFLAGS, PFL_AFLAGEDIT, Aflags);
    break;
  case VERB_OFLAGS:
    obj_flags(OFLAGS, PFL_OFLAGS, PFL_OFLAGEDIT, Oflags);
    break;
  case VERB_MASK:
    mob_flags(PMASK, PFL_MASK, PFL_MASKEDIT, Pflags);
    break;
  case VERB_EFLAGS:
    mob_flags(EFLAGS, PFL_EFLAGS, PFL_EFLAGEDIT, Eflags);
    break;
  case VERB_LFLAGS:
    loc_flags(LFLAGS, PFL_LFLAGS, PFL_LFLAGEDIT, Lflags);
    break;
  case VERB_MFLAGS:
    mob_flags(MFLAGS, PFL_MFLAGS, PFL_MFLAGEDIT, Mflags);
    break;
  case VERB_NFLAGS:
    mob_flags(NFLAGS, PFL_NFLAGS, PFL_NFLAGEDIT, Nflags);
    break;
  case VERB_PFLAGS:
    mob_flags(PFLAGS, PFL_PFLAGS, PFL_PFLAGEDIT, Pflags);
    break;
  case VERB_SFLAGS:
    mob_flags(SFLAGS, PFL_SFLAGS, PFL_SFLAGEDIT, Sflags);
    break;
  default:
    return(False);
  }
  return(True);
}

/* formatted list of the names of bits */

void show_bits(long int bits[], int fpoints[], char *flnames[],
  int flagset, Boolean inverse) {

  int len = fpoints[flagset+1] - fpoints[flagset];
  int wordnum, bitnum, i, j, rslt;

  j = 1;

  for (i = 0 ; i < len ; i++) {
    for (bitnum = 0 ; bitnum < 32 ; bitnum++)
      if (((rslt = xtstbit(bits[fpoints[flagset] + i], bitnum)) &&
           !inverse) || (!rslt && inverse)) {
        if (flagset == QFLAGS)
  	  bprintf("%-16s%s", ((QUEST*) flnames)[i*32 + bitnum].name,
            !(j++ % 5) ? "\n" : "");
        else
	  bprintf("%-16s%s", flnames[i*32 + bitnum], !(j++ % 5) ? "\n" : "");
     }
  }
  bprintf("\n");
}

/* used to produce an unformatted string containing the names of bits */

char *dump_bits(long int bits[], int fpoints[], char *flnames[], int flagset) {
  static char buff[4096];
  int len = fpoints[flagset+1] - fpoints[flagset];
  int wordnum, bitnum, i, j;

  j = 1;
  *buff = 0;

  for (i = 0 ; i < len ; i++) {
    for (bitnum = 0 ; bitnum < 32 ; bitnum++)
      if (xtstbit(bits[fpoints[flagset] + i], bitnum)) {
	strcat(buff, flnames[i*32 + bitnum]);
        strcat(buff, " ");
      }
  }
  return(buff);
}

Boolean dump_pflags (void) {
  static char *t[] = { "Pflags", "Mask", TABLE_END };
  int k, k2;

  if (plev (mynum) < LVL_ARCHWIZARD || EMPTY(item1))
    return(False);
  else if (EMPTY(item2)) {
    bprintf("You need to give a level. Example: GLOBAL pflags Creator\n");
    return(True);
  }
  else if ((k = tlookup(item1, t)) < 0) {
    bprintf("You need to type: GLOBAL pflags <lev> or GLOBAL mask <lev>\n"); 
    return(True);
  }
  else if ((k2 = tlookup(item2, MWizLevels)) >= LEV_APPRENTICE)
    bprintf ("%s for %s:\n", t[k], MWizLevels[k2]);
  else if ((k2 = tlookup(item2, FWizLevels)) >= LEV_APPRENTICE)
    bprintf ("%s for %s:\n", t[k], FWizLevels[k2]);
  else if (EQ(item2, "Novice")) {
    bprintf ("%s for %s:\n", t[k], "Novice");
    k2 = 0;
  }
  else {
    bprintf("That isn't a level. Example: GLOBAL pflags Wizard\n");
    return(True);
  }

  if (k == 0)
    show_bits(pbits(k2), pflindex, Pflags, PFLAGS, False);
  else
    show_bits(pbits(k2), pflindex, Pflags, MASKS, False);

  return(True);
}

Boolean bitschanged(long int bits[], int idx[], char *flsetnames[], int len) {
  int a, b, i;

  for (i = 0 ; i < len ; i++) {
    if (strstr(flsetnames[i], "Reset")) {
      for (a = idx[i], b = idx[i-1] ; b != idx[i] ; a++ , b++)
        if (bits[a] != bits[b])
          return(True);
    }
  }  
  return(False);
}