lpc4/lib/
lpc4/lib/doc/efun/
lpc4/lib/doc/lfun/
lpc4/lib/doc/operators/
lpc4/lib/doc/simul_efuns/
lpc4/lib/doc/types/
lpc4/lib/etc/
lpc4/lib/include/
lpc4/lib/include/arpa/
lpc4/lib/obj/d/
lpc4/lib/save/
lpc4/lib/secure/
lpc4/lib/std/
lpc4/lib/std/living/
/* This file contains functions that will appear as efuns when compiling
 * other objects. Note that this is not done automatically as in the old
 * days, instead the old behaviour is simulated by master.c with the use
 * of add_simul_efun.
 */

varargs string implode_nicely(string *dum,string sep)
{
  int s;
  if(!sep) sep="and";
  s=sizeof(dum);
  switch(s)
  {
  default:
    return implode(dum[0..s-2],", ")+" "+sep+" "+dum[s-1];

  case 2:
    return dum[0]+" "+sep+" "+dum[1];

  case 1:
    return dum[0];
  
  case 0:
    return "";
  }
}


static mapping living_names=([]);
static mapping livings=([]);

void set_living_name(string n,object o)
{
  if(living_names[n])
  {
    living_names[n]=({o})+living_names[n];
  }else{
    living_names[n]=({o});
  }
  livings[o]=n;
}

mixed find_living(string n,int all)
{
  object *tmp;
  if(tmp=living_names[n])
  {
    tmp-=({0}); /* remove destructed objects */
    if(!sizeof(tmp))
      m_delete(living_names,n);
  }else{
    tmp=({});
  }
  if(all) return tmp;
  if(sizeof(tmp)) return tmp[0];
  return 0;
}

string living(object o) { return livings[o]; }
int query_number_of_livings() { return m_sizeof(livings); }

object *users()
{
  return "/secure/ip"->users();
}

mapping find_player_cache=([]);
object find_player(string name)
{
  object ret;
  string tmp;
  if(ret=find_player_cache[name]) return ret;

  foreach(users(),ret)
  {
    tmp=ret->query_real_name();
    find_player_cache[tmp]=ret;
    if(tmp==name) return ret;
  }
  return 0;
}

void tell_object(object o,string msg) { o->catch_tell(msg); }
void notify_fail(string n) { this_player()->set_notify_fail(n); }

int abs(int x) { return x<0?-x:x; }
int atoi(string a) { return (int)a; }
mixed max(mixed x,mixed y) { return x>y?x:y; }
mixed min(mixed x,mixed y) { return x<y?x:y; }

int transfer(object o,object to)
{
  object from;
  int w;
  if(!o->query_get(to)) return 1;

  from=environment(o);
  if(!to->query_room())
  {
    if(!to->can_put_and_get(o)) return 2;
    if(!from->can_put_and_get(o)) return 3;
    if(!o->query_drop(0)) return 4;

    if(w=o->query_weight())
    {
      if(!to->add_weight(w)) return 5;
      from->add_weight(-w);
    }
  }else{
    if(w=o->query_weight())
      from->add_weight(-w);
  }
  if(living(from))
    if(!from->silent_unwield(o,1))
      return 7;
  o->move(to);

  if(environment(o)!=to) return 6;
  return 0;
}

/* this _used_ to be an efun:
NAME
	pluralize - attempt to pluralize a noun

SYNTAX
	string pluralize(string noun);

DESCRIPTION
	Try to return the plural form of a given noun. Doesn't always
	work, but makes an acceptable 'default' for when no plural form
	is given.

NOTA BENE
	Might not work very well with most languages except english.
*/

string pluralize(string p)
{
  while(sscanf(p,"%s %s",p,p));
  p=lower_case(p);
  switch(p)
  {
    case "moose":
    case "fish":
    case "deer":
    case "sheep": return p;
    case "child": return "children";
    case "tooth": return "teeth";
    case "ox":
    case "vax": return p+"en";
    case "bus": return "busses";
    case "chef": return "chefs";
    case "foot": return "feet";
  }
  
  if(p[-1]=='x' || p[-1]=='s' || (p[-1]=='h' && (p[-2]=='c' || p[-2]=='s')))
    return p+"es";

  if(sscanf(p,"%sff",p) || sscanf(p,"%sfe",p)) return p+"ves";
/*  if(sscanf(p,"%sef",p)) return p+"efs"; */
  if(sscanf(p,"%sf",p)) return p+"ves";
  if(sscanf(p,"%sy",p)) return p+"ies";
  if(sscanf(p,"%sus",p)) return p+"i";
  if(sscanf(p,"%sman",p)) return p+"men";
  if(sscanf(p,"%sis",p)) return p+"es";
  if(sscanf(p,"%so",p)) return p+"s";
  return p+"s";
}


string tail(string file)
{
  string f;
  int s;
  f=master()->valid_read(file,geteuid(previous_object()),"tail");
  if(!f) return;
  if(stringp(f)) file=f;
  s=file_size(file);
  s-=54*20;
  if(s<0) s=0;
  f=read_bytes(file,s);
  sscanf(f,"%*s\n%s",f);
  return f;
}

string cat(string file)
{
  string f;
  f=master()->valid_read(file,geteuid(previous_object()),"cat");
  if(!f) return;
  if(stringp(f)) file=f;
  return read_file(file,1,20);
}

void log_file(string file,string entry)
{
  if(file[0]!='/') file="/log/"+file;
  string f;
  f=master()->valid_read(file,geteuid(previous_object()),"log_file");
  if(!f) return;
  if(stringp(f)) file=f;
  write_file(file,entry);
  if(file_size(file)>50000) /* MAX_LOG_SIZE */
    rename(file,file+".old");
}

object present(string s,object o)
{
  int num;
  string s2;
  if(s[-1]>='0' && s[-1]<='9')
  {
    num=strlen(s)-2;
    while(s[num]>='0' && s[num]<='9') num--;
    if(s[num]==' ')
    {
      s2=s[0..num-1];
      num=(int)s[num+1..strlen(s)-1];
      foreach(all_inventory(o),o)
	if(o->id(s) && !--num)
	  return o;
      return 0;
    }
  }
  foreach(all_inventory(o),o)
    if(o->id(s))
      return o;
  return 0;
}

varargs void tell_room(object o,string s,object *avoid)
{
  if(avoid)
    map_array(all_inventory(o)-avoid,"catch_tell",s);
  else
    map_array(all_inventory(o),"catch_tell",s);
}