lima-1.0b5/
lima-1.0b5/driver/
lima-1.0b5/driver/ChangeLog.old/
lima-1.0b5/driver/Win32/
lima-1.0b5/driver/compat/
lima-1.0b5/driver/include/
lima-1.0b5/driver/testsuite/
lima-1.0b5/driver/testsuite/clone/
lima-1.0b5/driver/testsuite/command/
lima-1.0b5/driver/testsuite/data/
lima-1.0b5/driver/testsuite/etc/
lima-1.0b5/driver/testsuite/include/
lima-1.0b5/driver/testsuite/inherit/
lima-1.0b5/driver/testsuite/inherit/master/
lima-1.0b5/driver/testsuite/log/
lima-1.0b5/driver/testsuite/single/
lima-1.0b5/driver/testsuite/single/tests/compiler/
lima-1.0b5/driver/testsuite/single/tests/efuns/
lima-1.0b5/driver/testsuite/single/tests/operators/
lima-1.0b5/driver/testsuite/u/
lima-1.0b5/driver/tmp/
lima-1.0b5/etc/
lima-1.0b5/lib/WWW/help/
lima-1.0b5/lib/cmds/
lima-1.0b5/lib/cmds/create/
lima-1.0b5/lib/cmds/player/attic/
lima-1.0b5/lib/contrib/bboard/
lima-1.0b5/lib/contrib/boards/
lima-1.0b5/lib/contrib/marriage/
lima-1.0b5/lib/contrib/roommaker/
lima-1.0b5/lib/contrib/transient_effect/
lima-1.0b5/lib/daemons/channel/
lima-1.0b5/lib/daemons/imud/
lima-1.0b5/lib/data/
lima-1.0b5/lib/data/config/
lima-1.0b5/lib/data/links/
lima-1.0b5/lib/data/news/
lima-1.0b5/lib/data/players/
lima-1.0b5/lib/data/secure/
lima-1.0b5/lib/domains/
lima-1.0b5/lib/domains/std/2.4.5/maze1/
lima-1.0b5/lib/domains/std/2.4.5/npc/
lima-1.0b5/lib/domains/std/2.4.5/post_dir/
lima-1.0b5/lib/domains/std/2.4.5/sub/
lima-1.0b5/lib/domains/std/camera/
lima-1.0b5/lib/domains/std/config/
lima-1.0b5/lib/domains/std/cult/
lima-1.0b5/lib/domains/std/effects/
lima-1.0b5/lib/domains/std/misc/
lima-1.0b5/lib/domains/std/monsters/
lima-1.0b5/lib/domains/std/recorder/
lima-1.0b5/lib/domains/std/rooms/
lima-1.0b5/lib/domains/std/rooms/beach/
lima-1.0b5/lib/domains/std/rooms/labyrinth/
lima-1.0b5/lib/domains/std/school/
lima-1.0b5/lib/domains/std/school/O/
lima-1.0b5/lib/domains/std/spells/
lima-1.0b5/lib/domains/std/spells/stock-mage/
lima-1.0b5/lib/domains/std/spells/stock-priest/
lima-1.0b5/lib/help/
lima-1.0b5/lib/help/admin/
lima-1.0b5/lib/help/hints/General_Questions/
lima-1.0b5/lib/help/hints/Pirate_Quest/
lima-1.0b5/lib/help/player/
lima-1.0b5/lib/help/player/bin/
lima-1.0b5/lib/help/player/quests/
lima-1.0b5/lib/help/wizard/
lima-1.0b5/lib/help/wizard/coding/guilds/
lima-1.0b5/lib/help/wizard/coding/rooms/
lima-1.0b5/lib/help/wizard/lib/daemons/
lima-1.0b5/lib/help/wizard/lib/lfun/
lima-1.0b5/lib/help/wizard/lib/std/
lima-1.0b5/lib/help/wizard/mudos_doc/
lima-1.0b5/lib/help/wizard/mudos_doc/applies/
lima-1.0b5/lib/help/wizard/mudos_doc/applies/interactive/
lima-1.0b5/lib/help/wizard/mudos_doc/applies/parsing/
lima-1.0b5/lib/help/wizard/mudos_doc/concepts/
lima-1.0b5/lib/help/wizard/mudos_doc/driver/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/arrays/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/buffers/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/compile/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/filesystem/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/floats/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/functions/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/general/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/mappings/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/mixed/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/numbers/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/parsing/
lima-1.0b5/lib/help/wizard/mudos_doc/lpc/constructs/
lima-1.0b5/lib/help/wizard/mudos_doc/lpc/types/
lima-1.0b5/lib/include/driver/
lima-1.0b5/lib/log/
lima-1.0b5/lib/obj/admtool/
lima-1.0b5/lib/obj/admtool/internal/
lima-1.0b5/lib/obj/admtool/mudinfo/
lima-1.0b5/lib/obj/admtool/secure/
lima-1.0b5/lib/obj/secure/
lima-1.0b5/lib/obj/secure/cmd/
lima-1.0b5/lib/obj/secure/mailers/
lima-1.0b5/lib/obj/secure/shell/
lima-1.0b5/lib/obj/secure/shell/classes/
lima-1.0b5/lib/obj/tasktool/
lima-1.0b5/lib/obj/tasktool/internal/
lima-1.0b5/lib/open/
lima-1.0b5/lib/secure/
lima-1.0b5/lib/secure/cgi/
lima-1.0b5/lib/secure/modules/
lima-1.0b5/lib/secure/simul_efun/
lima-1.0b5/lib/std/adversary/
lima-1.0b5/lib/std/adversary/advancement/
lima-1.0b5/lib/std/adversary/armor/
lima-1.0b5/lib/std/adversary/blows/
lima-1.0b5/lib/std/adversary/death/
lima-1.0b5/lib/std/adversary/formula/
lima-1.0b5/lib/std/adversary/health/
lima-1.0b5/lib/std/adversary/pulse/
lima-1.0b5/lib/std/adversary/wield/
lima-1.0b5/lib/std/classes/event_info/
lima-1.0b5/lib/std/container/
lima-1.0b5/lib/std/living/
lima-1.0b5/lib/std/modules/contrib/
lima-1.0b5/lib/std/patterns/
lima-1.0b5/lib/std/race/
lima-1.0b5/lib/std/race/restricted/
lima-1.0b5/lib/std/room/
lima-1.0b5/lib/tmp/
lima-1.0b5/lib/trans/
lima-1.0b5/lib/trans/admincmds/
lima-1.0b5/lib/trans/obj/
lima-1.0b5/lib/wiz/
/* Do not remove the headers from this file! see /USAGE for more info. */

/* For keeping track of sets of numbers.  See also the set_bit()/test_bit()
 * series of efuns.  The major advantage of this package is that the
 * storage requirements are much lower for sets with many consecutive
 * numbers, or for numbers which are sparsely distributed over a large
 * range.  It isn't particularly efficient speedwise, but it is compact.
 *
 * The format is: x-x,y-z ...
 */

/* This function ensures that the sets aren't currupted.  It returns 1 
 * if the set is valid and 0 on failure.
 * There may need to be more work done here -- Tigran */
int valid_set(string set)
{
  int part1, part2;
  string rest;
  string array parts=explode(set,",");
  if(set="") return 1;
  foreach(string part in parts)
    {
      if(sscanf("%d-%d%s",part1,part2,rest)!=2)
	return 0;
    }
  return 1;
} 

string set_add(string set, int number) {
    int idx, nextidx;
    int lastidx, lastfirst, lastlast = -10;
    
    if(!valid_set(set))
      error(sprintf("Invalid set in set_add: %s\n",set));
    if (set == "") return number + "-" + number;

    /* The cases we have to consider:
     1-2 -> 1-2,4-4
     1-2,4-5 -> 1-2,4-6
     1-3,5-7 -> 1-7
    */

    idx = 0;
    do {
        string part;
        int first, last;

        nextidx = member_array(',', set, idx) + 1;

        if (!nextidx)
            part = set[idx..];
        else
            part = set[idx..nextidx-2];
        sscanf(part, "%d-%d", first, last);
        if (number < first) {
            string res;
            
            if (number == lastlast + 1) {
	      if (number == first - 1) {
		res = set[0..lastidx-1] + lastfirst + "-" + last;
		if (nextidx) res += set[nextidx-1..];
		return res;
	      }
	      return set[0..lastidx-1] + lastfirst + "-" + number + set[idx-1..];
            }
            if (number == first - 1) {
                res = set[0..idx-1] + number + "-" + last;
                if (nextidx) res += set[nextidx-1..];
                return res;
            }
            return set[0..idx-1] + number + "-" + number + "," + set[idx..];
        }
        if (number <= last)
            return set;
        
        lastidx = idx;
        lastfirst = first;
        lastlast = last;
        idx = nextidx;
    } while (idx);

    if (number == lastlast + 1)
        return set[0..lastidx-1] + lastfirst + "-" + number;
    else
        return set + "," + number + "-" + number;
}

string set_add_range(string set, int nfirst, int nlast) {
    int idx, nextidx;
    int lastidx, lastfirst, lastlast = -10;
    
    if(!valid_set(set))
      error(sprintf("Invalid set in set_add_range: %s\n",set));
    if (set == "") return nfirst + "-" + nlast;

    idx = 0;
    do {
        string part;
        int first, last;

        nextidx = member_array(',', set, idx) + 1;

        if (!nextidx)
            part = set[idx..];
        else
            part = set[idx..nextidx-2];
        sscanf(part, "%d-%d", first, last);
        if (nfirst < first) {
            string res;
	    int sidx;

	    sidx = idx;
	    while (nextidx && nlast > last) {
		idx = nextidx;
		nextidx = member_array(',', set, idx) + 1;

		if (!nextidx)
		    part = set[idx..];
		else
		    part = set[idx..nextidx-2];
		sscanf(part, "%d-%d", first, last);
	    }
            
            if (nfirst <= lastlast + 1) {
                if (nlast >= first - 1) {
                    res = set[0..lastidx-1] + lastfirst + "-" + last;
                    if (nextidx) res += set[nextidx-1..];
                    return res;
                }
                return set[0..lastidx-1] + lastfirst + "-" + nlast + set[idx-1..];
            }
            if (nlast >= first - 1) {
                res = set[0..sidx-1] + nfirst + "-" + last;
                if (nextidx) res += set[nextidx-1..];
                return res;
            }
            return set[0..sidx-1] + nfirst + "-" + nlast + set[idx-1..];
        }
        if (nlast <= last)
            return set;
        
        lastidx = idx;
        lastfirst = first;
        lastlast = last;
        idx = nextidx;
    } while (idx);

    if (nfirst <= lastlast + 1)
        return set[0..lastidx-1] + lastfirst + "-" + nlast;
    else
        return set + "," + nfirst + "-" + nlast;
}

string set_remove(string set, int number) {
    int idx, nextidx;

    if(!valid_set(set))
      error(sprintf("Invalid set in set_remove: %s\n",set));
    if (set == "") return set;

    idx = 0;
    do {
        string part;
        int first, last;

        nextidx = member_array(',', set, idx) + 1;

        if (!nextidx)
            part = set[idx..];
        else
            part = set[idx..nextidx-2];
        sscanf(part, "%d-%d", first, last);
        if (number <= last) {
            string res;

            if (number < first)
                return set;
            
            if (number == last) {
                if (number == first) {
                    if (idx) {
                        res = set[0..idx-1];
                        if (nextidx) res += set[nextidx-1..];
                    } else {
                        res = (nextidx ? set[nextidx..] : "");
                    }
                    return res;
                }
                res = set[0..idx-1] + first + "-" + (last - 1);
                if (nextidx) res += set[nextidx-1..];
                return res;
            }
            if (number == first) {
                res = set[0..idx-1] + (first + 1) + "-" + last;
                if (nextidx) res += set[nextidx-1..];
                return res;
            }
            res = set[0..idx-1] + first + "-" + (number - 1) + "," + (number + 1) + "-" + last;
            if (nextidx) res += set[nextidx-1..];
            return res;
        }
        
        idx = nextidx;
    } while (idx);

    return set;
}

int set_member(string set, int number) {
    string array set_parts;

    if(!valid_set(set))
      error(sprintf("Invalid set in set_member: %s\n",set));
    set_parts=explode(set,",");
    foreach(string element in set_parts)
      {
	int first;
	int last;
	sscanf(element,"%d-%d",first,last);
	if(number<first)
	  continue;
	if(number<=last)
	  return 1;
      }
}


/* More filter() friendly interface */
int member_set(int number,string set)
{
  return set_member(set,number);
}

string set_union(string set1, string set2)
{
    string res = "";
    int f1 = -1, f2 = -1, l1, l2, handled;

    if(!valid_set(set1))
      error(sprintf("Invalid first set in set_union: %s\n",set1));
    if(!valid_set(set2))
      error(sprintf("Invalid second set in set_union: %s\n",set2));
    sscanf(set1, "%d-%d%s", f1, l1, set1);
    if (set1[0] == ',') set1 = set1[1..];
    sscanf(set2, "%d-%d%s", f2, l2, set2);
    if (set2[0] == ',') set2 = set2[1..];
    handled = 0;
    
    while (f1 != -1 && f2 != -1) {
	if (l1 < f2) {
	    res += (res == "" ? "" : ",") + f1 + "-" + l1;
	    f1 = -1;
	    sscanf(set1, "%d-%d%s", f1, l1, set1);
	    if (set1[0] == ',') set1 = set1[1..];
	} else if (l2 < f1) {
	    res += (res == "" ? "" : ",") + f2 + "-" + l2;
	    f2 = -1;
	    sscanf(set2, "%d-%d%s", f2, l2, set2);
	    if (set2[0] == ',') set2 = set2[1..];
	} else {
	    int a = (f1 < f2 ? f1 : f2);
	    int b = (l1 > l2 ? l1 : l2);

	    while (1) {
		if (f1 != -1 && f1 <= b) {
		    f1 = -1;
		    sscanf(set1, "%d-%d%s", f1, l1, set1);
		    if (set1[0] == ',') set1 = set1[1..];
		    if (f1 <= b && l1 > b)
			b = l1;
		} else
		if (f2 != -1 && f2 <= b) {
		    f2 = -1;
		    sscanf(set2, "%d-%d%s", f2, l2, set2);
		    if (set2[0] == ',') set2 = set2[1..];
		    if (f2 <= b && l2 > b)
			b = l2;
		} else
		    break;
	    }

	    res += (res == "" ? "" : ",") + a + "-" + b;
	}
    }
    if (f1 != -1)
	res += (res == "" ? "" : ",") + f1 + "-" + l1;
    if (f2 != -1)
	res += (res == "" ? "" : ",") + f2 + "-" + l2;
    if (set1 != "")
	res += (res == "" ? "" : ",") + set1;
    if (set2 != "")
	res += (res == "" ? "" : ",") + set2;

    return res;
}

string set_difference(string set1, string set2)
{
  string res = "";
  int f1 = -1, f2 = -1, l1, l2;
    if(!valid_set(set1))
      error(sprintf("Invalid first set in set_difference: %s\n",set1));
    if(!valid_set(set2))
      error(sprintf("Invalid second set in set_difference: %s\n",set2));
  sscanf(set1, "%d-%d%s", f1, l1, set1);
  sscanf(set2, "%d-%d%s", f2, l2, set2);  
  while (f1 != -1) 
    {
      if(set1[0]==',') set1=set1[1..];
      if(set2[0]==',') set2=set2[1..];
      if(f2==-1)
	{
	  /* This might want to be reconstructed as string addition to 
	   * conform with the rest of the function, but right now it
	   * works, and I can deal better w/ sprintf()S -- Tigran */
	  res+=sprintf("%s%i-%i%s%s",
		       (res==""?"":","),
		       f1,
		       l1,
		       set1==""?"":",",
		       set1);
	  f1=-1;
	  continue;
	}
      else if (l1 < f2) 
	{
	  res += (res == "" ? "" : ",") + f1 + "-" + l1;
	  f1 = -1;
	  sscanf(set1, "%d-%d%s", f1, l1, set1);
	  if (set1[0] == ',') set1 = set1[1..];
	}
      else if (l2 < f1) 
	{
	  f2 = -1;
	  sscanf(set2, "%d-%d%s", f2, l2, set2);
	  if (set2[0] == ',') set2 = set2[1..];
	} 
      else 
	{
	  if (f1 < f2)
	    {
	      res += (res == "" ? "" : ",") + f1 + "-" + (f2-1);
	      f1=-1;
	      sscanf(set1,"%d-%d%s",f1,l1,set1);
	    }
	  if (l2 < l1)
	    {
	      f1 = l2 + 1;
	      f2=-1;
	      sscanf(set2, "%d-%d%s", f2, l2, set2);
	    }
	  else if (l1 < l2)
	    {
	      f1 = -1;
	      sscanf(set1, "%d-%d%s", f1, l1, set1);
	      if (set1[0] == ',') set1 = set1[1..];
	    } 
	  else if ( f1==f2 ) 
	    {
	      if(l1==l2)
		{
		  f1=-1;
		  sscanf(set1,"%d-%d%s",f1,l1,set1);
		  f2=-1;
		  sscanf(set2,"%d-%d%s",f2,l2,set2);
		}
	    }
	  else 
	    {
	      f2 = -1;
	      sscanf(set2, "%d-%d%s", f2, l2, set2);
	      if (set2[0] == ',') set2 = set2[1..];
	    }
	}
    }
  return res;
}

string set_intersection(string set1, string set2) {
    string res = "";
    int f1 = -1, f2 = -1, l1, l2;
    if(!valid_set(set1))
      error(sprintf("Invalid first set in set_intersection: %s\n",set1));
    if(!valid_set(set2))
      error(sprintf("Invalid second set in set_intersection: %s\n",set2));
    sscanf(set1, "%d-%d%s", f1, l1, set1);
    if (set1[0] == ',') set1 = set1[1..];
    sscanf(set2, "%d-%d%s", f2, l2, set2);
    if (set2[0] == ',') set2 = set2[1..];
    
    while (f1 != -1 && f2 != -1) {
	if (l1 < f2) {
	    f1 = -1;
	    sscanf(set1, "%d-%d%s", f1, l1, set1);
	    if (set1[0] == ',') set1 = set1[1..];
	} else if (l2 < f1) {
	    f2 = -1;
	    sscanf(set2, "%d-%d%s", f2, l2, set2);
	    if (set2[0] == ',') set2 = set2[1..];
	} else {
	    res += (res == "" ? "" : ",") + 
		(f1 > f2 ? f1 : f2) + "-" + (l1 < l2 ? l1 : l2);
	    if (l1 < l2) {
		f1 = -1;
		sscanf(set1, "%d-%d%s", f1, l1, set1);
		if (set1[0] == ',') set1 = set1[1..];
	    } else {
		f2 = -1;
		sscanf(set2, "%d-%d%s", f2, l2, set2);
		if (set2[0] == ',') set2 = set2[1..];
	    }
	}
    }
    return res;
}

int set_min(string set) {
    int ret = 0;
    if(!valid_set(set))
      error(sprintf("Invalid set in set_min: %s\n",set));
    sscanf(set, "%d", ret);
    return ret;
}

int set_max(string set) {
    int idx = strsrch(set, ",", -1);
    int ret;
    if(!valid_set(set))
      error(sprintf("Invalid set in set_max: %s\n",set));
    sscanf(set[idx+1..], "%*d-%d", ret);
    
    return ret;
}

int set_count(string set) {
    int f, l;
    int ret = 0;
    
    if(!valid_set(set))
      error(sprintf("Invalid set in set_count: %s\n",set));
    while (strlen(set)) {
	sscanf(set, "%d-%d%s", f, l, set);
	if (set[0] == ',') set = set[1..];

	ret += l - f + 1;
    }

    return ret;
}