/
lib/banish/
lib/d/coronos/
lib/d/coronos/w/alena/
lib/d/coronos/w/angel/
lib/d/coronos/w/angel/caves/
lib/d/coronos/w/angel/caves/monst/
lib/d/coronos/w/angel/city/chambers/
lib/d/coronos/w/angel/city/monst/
lib/d/coronos/w/angel/city/obj/
lib/d/coronos/w/angel/city/streets/
lib/d/coronos/w/angel/farms/plains/
lib/d/coronos/w/angel/monst/
lib/d/tempus/
lib/d/tempus/w/angel/
lib/d/tempus/w/kingbill/
lib/d/tempus/w/mirak/
lib/d/tempus/w/mirak/monst/
lib/d/tempus/w/mirak/obj/
lib/d/tempus/w/relgar/planes/baat/
lib/d/tempus/w/sarak/
lib/d/tempus/w/serepion/mon/
lib/d/tempus/w/valrejn/
lib/doc/
lib/doc/domains/
lib/doc/efun/
lib/include/fn_specs/
lib/info/
lib/inherit/base/
lib/log/
lib/log/mailbox/
lib/log/main/
lib/news/
lib/obj/party/
lib/objects/componen/
lib/open/
lib/open/party/
lib/open/paste/
lib/open/spells/
lib/open/valrejn/
lib/players/
lib/players/alena/
lib/players/alena/obj/
lib/players/alena/open/
lib/players/alena/private/
lib/players/angel/
lib/players/angel/obj/
lib/players/ash/
lib/players/biggs/
lib/players/biggs/food/
lib/players/biggs/gobkeep/
lib/players/biggs/mnstr/
lib/players/biggs/town/caves/
lib/players/biggs/town/tower/
lib/players/biggs/wpns/
lib/players/calris/
lib/players/deathurg/
lib/players/deathurg/open/
lib/players/deathurg/private/thief/
lib/players/dogberry/
lib/players/dogberry/library/
lib/players/dogberry/open/
lib/players/epsilon/
lib/players/epsilon/private/
lib/players/farewell/
lib/players/hippo/
lib/players/hippo/open/
lib/players/hippo/tools/
lib/players/jimpa/
lib/players/josh/
lib/players/josh/room/
lib/players/josh/room/mage/dungeon/
lib/players/josh/room/mage/dungeon/obj/
lib/players/josh/wep/
lib/players/kingbill/
lib/players/metatron/
lib/players/miette/
lib/players/mirak/
lib/players/mirak/open/
lib/players/parsilan/
lib/players/relgar/
lib/players/relgar/private/
lib/players/sarak/
lib/players/sarak/bugs/
lib/players/sarak/feelings/
lib/players/sarak/magical/
lib/players/sarak/minotaur/island/
lib/players/sarak/open/
lib/players/sarak/private/
lib/players/serepion/
lib/players/serepion/open/
lib/players/serepion/private/
lib/players/spike/
lib/players/spike/open/
lib/players/spike/private/
lib/players/spike/seaworld/
lib/players/valrejn/
lib/players/valrejn/open/
lib/players/valrejn/private/
lib/players/virus/
lib/players/wrath/
lib/players/wrath/arm/
lib/players/wrath/mon/
lib/players/wrath/room/
lib/players/wrath/room/entry/
lib/players/wrath/room/zolgath/
lib/players/wrath/weap/
lib/players/zil/
lib/room/
lib/room/city/arena/
lib/room/city/creator/
lib/room/city/garden/monst/
lib/room/city/library/
lib/room/city/library/open/books/
lib/room/city/shop/
lib/room/death/
lib/room/death/open/
lib/room/island/
lib/room/keeps/
lib/room/registry/
lib/room/ships/crew/
lib/room/ships/open/
lib/room/ships/open/types/bounty/
lib/room/ships/open/types/nebula/
lib/room/ships/open/types/phoenix/
lib/secure/udp_cmd_/
lib/skills/
lib/skills/fighter/
lib/skills/psionici/
lib/skills/thief/
lib/usr/
lib/usr/creators/
lib/usr/no_banis/
lib/usr/players/
#pragma strict_types
#pragma save_types


/* simul_ef.c

  This object simulates efuns for the HEAVEN7 mudlib.
 */

#include "/include/mudlib.h"
#include "/include/fn/shout.h"

#define VALID_READ(PATH,CALL_FUN) \
  MASTER->valid_read(PATH,0,CALL_FUN,previous_object())

#define VALID_WRITE(PATH,CALL_FUN) \
  MASTER->valid_write(PATH,0,CALL_FUN,previous_object())
  
  

/* have 'earmuffs on shout */

void shout(string str) {
  check_shout(str,0);
}



#ifdef MUDOS_DR

#ifdef MSDOS

/* This is a fix for ok09193c mudos read_file() */

#ifndef MAX_BYTE_READ
#define MAX_BYTE_READ 8192
#endif /* MAX_BYTE_READ */

varargs string read_file(string file, int line, int block) {
  string *txt_lines, txt;
  int lines, current_byte, f_size, byte_size;
  int  lines_in_last_block, total_lines;
  
  /* from more.c */

  if(!MASTER->valid_read(file, previous_object(), "read_file")
  && !MASTER->valid_read(file, this_player(), "read_file")) {
    return 0;
  }
  f_size = file_size(file);
  while(current_byte < f_size) {
    if(current_byte + MAX_BYTE_READ >= f_size) {
      byte_size = f_size - current_byte;
    }
    else {
      byte_size = MAX_BYTE_READ;
    }
    txt = read_bytes(file, current_byte, byte_size);         
    if(txt) {
#ifdef OLD_EXPLODE
      lines_in_last_block = sizeof(explode(txt + "\n","\n")) - 1;
#else
      lines_in_last_block = sizeof(explode(txt,"\n")) - 1;
#endif /* OLD_EXPLODE */
      total_lines += lines_in_last_block;
    }
    current_byte += byte_size;

#ifdef MSDOS   /* hack to account for CR-LF in Olav's msdos compilation */
    current_byte += lines_in_last_block;
#endif
    if(total_lines > line) break; /* ok to read_file() */
  }
  if(line > total_lines) return 0; /* not ok to read_file() */

  if(block && txt = efun::read_file(file, line, block+1)) {
    lines = sizeof((txt_lines = explode(txt,"\n")))-1;
    if(block > lines) block = lines;
    return implode(txt_lines[0..(block-1)],"\n") +"\n";
  }
  return efun::read_file(file, line);
}

#endif /* MSDOS */

varargs string extract(string arg, int start, int end) {
  if(start < 0) start += strlen(arg);
  if(start < 0) start = 0;
  if(start > end || end > strlen(arg)-1) end = strlen(arg) - 1;
  return arg[start..end];
}

void localcmd() {
  write("Function Disabled.\n");
}

varargs string cat(string file, int start, int block) {
  string str;

  if(!file) return 0;
  if(!block) block = 45;
  if(!(str = read_file(file,start,block))) {
    str = read_file(file,start);
  }
  if(str) write(str);
  return str;
}

/* last time file was edited */

int file_time(string path) {
  mixed *v;

  if(!VALID_READ(path,"file_time")) return 0;
  if(sizeof(v=stat(path))) return v[1];
}


/* when was it last loaded */

int load_time(string path) {
  mixed *v;


  if(!VALID_READ(path,"load_time")) return 0;
  if(sizeof(v=stat(path))) return v[2];
}

#endif /* mudos */



#if defined(NATIVE_MODE)

varargs string creator(object ob) {
  if(!ob) ob = previous_object();
  return (string)MASTER->get_wiz_name(file_name(ob));
}


varargs mixed create_wizard(string owner, string domain) {
    mixed result;

    result =
      (mixed)MASTER->master_create_wizard(owner, domain, previous_object());
    if(stringp(result)) return result;
    return 0;
}


string file_name(object ob) {
  string file;

  file = efun::file_name(ob);
  return file[1..(strlen(file)-1)];
}


#endif /* NATIVE_MODE */



#if defined(AMYLAAR) || defined(MUDOS_DR) /* amylaar driver */

#define MAX_LOG_SIZE 1000000


void log_file(string file, string str) {
    string file_name;

    file_name = "/log/" + file;
#ifdef AMYLAAR
    if(file_size(file_name) > MAX_LOG_SIZE) {
       catch(rename(file_name, file_name +".old")); 
    }
#endif /* AMYLAAAR */
    write_file(file_name, str);
}



#ifndef NATIVE_MODE

varargs mixed create_wizard(string owner, string domain) {
    mixed result;

    result =
      (mixed)MASTER->master_create_wizard(owner, domain, previous_object());
    if(stringp(result)) return result;
    return 0;
}

#endif /* not native */


mixed snoop(mixed snoopee) {
    int result;

    if (snoopee && query_snoop(snoopee)) {
     write("Busy.\n");
     return 0;
    }
#if defined(NATIVE_MODE)
    result = efun::snoop(this_player(), snoopee);
#elif defined(COMPAT_FLAG)
    result = snoopee ? efun::snoop(this_player(), snoopee)
	       : efun::snoop(this_player());
#endif /* compat - native */
    switch (result) {
     case -1:
	 write("Busy.\n");
     case  0:
	 write("Failed.\n");
     case  1:
	 write("Ok.\n");
    }
    if (result > 0) return snoopee;
}

#endif /* amylaar or mudos */


#ifdef AMYLAAR

void localcmd() {
  write(implode(query_actions(this_player())," ") +"\n");
}

int file_time(string path) {
  mixed *v;

  if(!VALID_READ(path,"file_time")) return 0;
  if(sizeof(v=get_dir(path,4))) return v[0];
}

mixed *unique_array(mixed *arr,string func,mixed skipnum) {
    mixed *al, last;
    int i, j, k, *ordinals;

    if (sizeof(arr) < 32) return efun::unique_array(arr, func, skipnum);
    for (ordinals = allocate(i = sizeof(arr)); i--; )
     ordinals[i] = i;
    al = order_alist(map_objects(arr, func), ordinals, (ordinals=0,arr));
    arr = al[2];
    ordinals = al[1];
    al = al[0];
    if (k = i = sizeof(al)) {
     for (last = al[j = --i]; i--; ) {
	 if (al[i] != last) {
	  if (last != skipnum) {
	      arr[--k] = arr[i+1..j];
	      ordinals[k] = ordinals[j];
	  }
	  last = al[j = i];
	 }
     }
     if (last != skipnum) {
	 arr[--k] = arr[0..j];
	 ordinals[k] = ordinals[j];
     }
    }
    return order_alist(ordinals[k..], arr[k..])[1];
}

#ifndef NO_MAPPINGS
mapping m_delete(mapping m, mixed key) {
    return efun::m_delete(copy_mapping(m), key);
}
#endif



/*********************************************************************/
/* Force an object to become 'this_player()'. Only callable by       */
/* valid player objects                                              */

varargs object set_this_player(object ob) {
  if(!ob) ob = previous_object();
  if(!MASTER->valid_player_call(previous_object())) {
    log_file("ILLEGAL","Call set_this_player() by "+
	       file_name(previous_object()) +"\n");
    return 0;
  }
  funcall(bind_lambda(#'enable_commands,ob));
  return ob;
}



/*********************************************************************/
/* returns an list of objects that can be found by find_living()
   Basically giving the contents of the living 'name' hash table.
   Used in wizard.c in 'FIND_OBJECT'  

  limitations:  evaluation limits to less then 30

*/


object *find_all_living(string name) {
  object ob, *all;
  closure live;
  int i;

  live = unbound_lambda(({'live_name}),({#'set_living_name,'live_name}));
  for(all = ({}),i = 0; (ob = find_living(name)) && i < 45; i++) {
    if(member_array(ob, all) != -1) break;
    all += ({ ob, });
    funcall(bind_lambda(live,ob),"DUMMY");
  }
  for(i = sizeof(all); i--; ) {
    funcall(bind_lambda(live,all[i]),name);
  }
  return all;
}

#endif



#if !defined(AMYLAAR)

/* fix for explode */

string *explode(string txt, string delimiter) {
  string *exploded_txt;
  string fix;

  if(!txt) return ({});
  if(!delimiter) return ({ txt, });
  if(delimiter != "" && sscanf(txt,delimiter +"%s", txt) == 1) {
    fix = (delimiter == "X") ? "Y" : "X";
    txt = fix + delimiter + txt;
  }
#ifndef OLD_EXPLODE
  exploded_txt = efun::explode(txt + delimiter, delimiter);
#else
  exploded_txt = efun::explode(txt, delimiter);
#endif 
  if(fix) {
    exploded_txt[0] = extract(exploded_txt[0],1);
  }
  return exploded_txt;
}


#endif /* 312MASTER || mudos */

#if defined(312MASTER) || defined(MUDOS_DR)
/************************************************************/
/* returns an list of objects that can be found by find_living()
   Basically giving the contents of the living 'name' hash table.
   Used in wizard.c in 'FIND_OBJECT'  

  limitations:  evaluation limits to less then 30,
	  works in conjunction with lfun set_living(name),
	  (it will stop evaluating if it doesn't have this
	  lfun)

example lfun (it has been put in base_obj.c):
	 void set_living(string str) {
	   if(file_name(previous_object()) == SIMUL_EFUN) {
	  set_living_name(str);
	   }
	 }
*/


object *find_all_living(string name) {
  object ob;
  object *all;
  int i;

  for(all = ({}); (ob = find_living(name)) && i < 45; i++) {
    if(member_array(ob, all) != -1) break;
    all += ({ ob, });
    ob->set_living("DUMMY");
  }
  for(i = sizeof(all); i--; ) all[i]->set_living(name);
  return all;
}
  

#endif /* 312MASTER */



/************************************************************************/
/* rtime -  convert a ctime() format time string back to time() int */
/*          returns -1 if input string has wrong clock format       */
/*          used by 'rm' action in wizard.c                         */


#define LEAP_YEAR      ((year%4) ? 0 : 1)

#define ZERO_YEAR      1970
#define ZERO_DAY       1
#define ZERO_HOUR      10
#define ZERO_MIN       0
#define ZERO_SEC       0
#define NEXT_LEAP_YEAR 1

#define YEAR   31536000
#define DAY    86400
#define HOUR   3600
#define MIN    60


int rtime(string str) {
  int i;
  string day, month;
  int date, year, hour, min, sec;
  string *month_names; 
  int month_index, *month_days;
  int rtime;

  if(sscanf(str,"%s %s %d %d:%d:%d %d", day,
			  month,
			   date,
			   hour,
			 min,
			 sec,
			 year) == 7
  || sscanf(str,"%s %s  %d %d:%d:%d %d", day,
			   month,
			 date,
			 hour,
			  min,
			  sec,
			  year) == 7) {
    month = capitalize(lower_case(month));
    month = extract(month,0,2);

    month_names = ({ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
	       "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", 
    });
    month_days = ({ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, });
    if((month_index = member_array(month, month_names)) == -1) return -1;

    rtime = (year-ZERO_YEAR)*YEAR;
    rtime += ((year-ZERO_YEAR+NEXT_LEAP_YEAR)/4) * DAY;
    for(i = 0; i < month_index; i++) {
      rtime += (month_days[i] + ((i == 1 && LEAP_YEAR) ? 1 : 0)) * DAY;
    } 
    rtime += (date-ZERO_DAY) * DAY;
    rtime += (hour-ZERO_HOUR) * HOUR;
    rtime += min * MIN;
    rtime += sec;
    return rtime;
  }
  return -1;
}



/*************************************************************************/
/* update actions, used in room2.c                                       */
/* limited to top 45 objects                                             */

varargs void update_actions(object ob) {
  int i;
  object *inv;

  if(!ob) ob = previous_object();
  inv = all_inventory(ob);
  for(i = 0; i < sizeof(inv) && i < 45; i++) {
    if(!inv[i] || !living(inv[i])) continue;
#ifdef NATIVE_MODE
    inv[i]->move(ob);
#else
    move_object(inv[i], ob);
#endif /* NATIVE_MODE */
  }
  if(environment(ob)) {
#ifdef NATIVE_MODE
    ob->move(environment(ob));
#else
    move_object(ob, environment(ob));
#endif /* NATIVE_MODE */
  }
}


#ifndef NATIVE_MODE

/**********************************************************************/
/* restrict command() usage                                           */

varargs status command(string str,object ob) {
  if(!ob) ob = previous_object();
  /*
   temporarily commented out so monsters can cast their spells
  if(ob != this_player() && this_player()) {
    if((int)this_player()->query_security_level() 
     < (int)ob->query_security_level()) {
      return 0;
    }
  }
  * end comment */
  return efun::command(str,ob);
}

#endif /* NATIVE_MODE */


#ifdef VERSION
string version() { return VERSION; }
#endif /* VERSION */

#if defined(AMYLAAR) && HAVE_WIZLIST == 0

#include "/include/cfg/wizlist.h"

void add_worth(int value, object ob) {
    mixed old;
#ifdef OLD_EXPLODE
    switch (explode(file_name(previous_object()) +"/", "/")[1]) {
#else
    switch (explode(file_name(previous_object()), "/")[1]) {
#endif
      default:
	raise_error("Illegal call of add_worth.\n");
      case "obj":
      case "room":
      case "secure":
    }
    if (!ob) {
	if ( !(ob = previous_object(1)) )
	    return;
    }
    if (intp(old = get_extra_wizinfo(ob)))
	set_extra_wizinfo(ob, old + value);
}


void wizlist(string name) {
    int i, pos, total_cmd;
    int *cmds;
    mixed *a;
    mixed *b;

    if (!name) {
	name = (string)this_player()->query_real_name();
	if (!name)
	    return;
    }
    a = transpose_array(wizlist_info());
    cmds = a[WL_COMMANDS];
    a[WL_COMMANDS] = a[0];
    a[0] = cmds;
    a = order_alist(a);
    cmds = a[0];
    a[0] = a[WL_COMMANDS];
    a[WL_COMMANDS] = cmds;
    if ((pos = member(a[WL_NAME], name)) < 0 && name != "ALL")
	return;
    b = allocate(sizeof(cmds));
    for (i = sizeof(cmds); i;) {
	b[<i] = i;
	total_cmd += cmds[--i];
    }
    a = transpose_array(a + ({b}) );
    if (name != "ALL") {
	if (pos + 18 < sizeof(cmds)) {
	    a = a[pos-2..pos+2]+a[<15..];
	} else if (pos < sizeof(cmds) - 13) {
	    a = a[pos-2..];
	} else {
	    a = a[<15..];
	}
    }
    write("\n\t   -=[ Top Creators of "+ MUD_NAME +" ]=-\n\n");
    if (total_cmd == 0)
	total_cmd = 1;
    for (i = sizeof(a); i; ) {
	b = a[<i--];
	printf("%-15s %5d %2d%% (%d)\t[%4dk,%5d] %6d %d\n",
	  b[WL_NAME], b[WL_COMMANDS], b[WL_COMMANDS] * 100 / total_cmd, b[<1],
	  b[WL_EVAL_COST] / 1000,
	  b[WL_HEART_BEATS], b[WL_EXTRA], b[WL_ARRAY_TOTAL]
	);
    }
    printf("\nTotal         %7d     (%d)\n\n", total_cmd, sizeof(cmds));
}

#endif /* WIZLIST */


#ifdef 312MASTER


/* limited file access thru efuns */

nomask int file_size(string path) {
  if(!VALID_READ(path,"file_size")) return 0;
  return efun::file_size(path);
}

nomask status tail(string path) {
  if(!VALID_READ(path,"tail")) return 0;
  efun::tail(path);
  return 1;
}

nomask varargs status cat(string path, int start, int lines) {
  if(!VALID_READ(path,"cat")) return 0;
  efun::cat(path,start,lines);
  return 1;
}

nomask varargs string read_bytes(string path, int start, int bytes) {
  if(!VALID_READ(path,"read_bytes")) return 0;
  return efun::read_bytes(path,start,bytes);
}

nomask varargs string read_file(string path, int start, int lines) {
  if(!VALID_READ(path,"read_file")) return 0;
  return efun::read_bytes(path,start,lines);
}

nomask string *get_dir(string path) {
  if(!VALID_READ(path,"get_dir")) return 0;
  return efun::get_dir(path);
}

nomask int mkdir(string path) {
  if(!VALID_WRITE(path,"mkdir")) return 0;
  return efun::mkdir(path);
}

nomask status rmdir(string path) {
  if(!VALID_WRITE(path,"rmdir")) return 0;
  efun::rmdir(path);
  return 1;
}

nomask int rm(string path) {
  if(!VALID_WRITE(path,"remove_file")) return 0;
  return efun::rm(path);
}

nomask int write_file(string path, string text) {
  if(!VALID_WRITE(path,"write_file")) return 0;
  return efun::write_file(path,text);
}

nomask int write_bytes(string path, int start, string text) {
  if(!VALID_WRITE(path,"write_bytes")) return 0;
  return efun::write_bytes(path,start,text);
}

#endif /* 312MASTER */

mixed *remove_duplicate_items(object ob) {
  mixed *arr1, *arr2;
  int i;

  if(!ob) ob = this_player();
  arr1 = all_inventory(ob);
  arr1 = unique_array(arr1, "short", 0);

  arr2 = ({ });
  for(i=0; i<sizeof(arr1); i++) {
    arr2 += ({ arr1[i][0], });
  }
  return arr2;
}