/
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

/*
 *  Master File for HEAVEN7 mudlib 
 */

#include "/include/config.h"         
#include "/include/mudlib.h"
#include "/include/cfg/levels.h"
#include "/include/cfg/master.cfg"

#ifdef AMYLAAR321
#include "/include/cfg/driver_hook.h"
#endif

status debug_mode;


/*
 * There are several occasions when the game driver wants to check if
 * a player has permission to specific things.
 *
 * These types are implemented so far:
 *
 * "error messages": player is allowed to see runtime error messages.
 * "trace":          player is allowed to use tracing.
 * "wizard":         player considered at least a "minimal" wizard 
 * "create domain":  player is allowed to create new domains
 * "snoop":          player is allowed to snoop
 */

int query_player_level(string what) {
  int security_level;

  if(!this_player()) return 0;
  security_level = (int)this_player()->query_security_level();
  switch(what) {
    case "wizard":
      return (security_level >= SEC1);
    case "error messages":
      return (security_level >= SEC1);
    case "trace":
      return (security_level >= SEC4);
    case "create domain":
      return (security_level >= SEC8);
    case "snoop":
      return (security_level >= SEC5);
  }
  return 0;
}

/*
 * Strip '/' from native mode file_name()
 */
 
#ifdef NATIVE_MODE

string master_file_name(object ob) {
  string file;

  file = file_name(ob);
  if(file[0] == '/') file = file[1..(strlen(file)-1)];
  return file;
}

#define file_name master_file_name

#endif /* NATIVE */


/*
 *  start-up flags
 */

void flag(string str) {
    string file, arg;

    if(sscanf(str, "echo %s", arg) == 1) {
       write(arg + "\n");
       return;
    }
    if(sscanf(str, "call %s %s", file, arg) == 2) {
       arg = (string)call_other(file, arg);
       write("Call Flag: "+ arg +"\n");
       return;
    }
    write("Master: Unknown flag " + str + "\n");
}


/***************************************************************************/
/* object player is connected */

/*
 * This function is called every time a player connects.
 * input_to() can't be called from here.
 */

object connect() {
  write("\n");
#ifdef USE_DEBUG
  return clone_object(DEBUG);
#endif /* force usuage of DEBUG-player */

#ifdef DEBUG
/* attempt to load WIZARD,
 * loads "secure/security"
 *       "inherit/base/base_obj",
 *       "inherit/base/living",
 *       "obj/player",
 *       "obj/wizard"
 */
  
  if(catch(call_other(SECURITY_FILE,"??")) || catch(call_other(WIZARD,"??"))) {
    write("FATAL: Switching to DEBUG Object!!\n");
    debug_mode = 1;
    return clone_object(DEBUG);
  }
  else {
    debug_mode = 0;
    return clone_object(PLAYER);
  }   
#else
  return clone_object(PLAYER);
#endif
}

/****************************************************************************/
/* where are error logs written */

/*
 * Get the owner of a file. This is called from the game driver, so as
 * to be able to know which wizard should have the error.
 */

string get_wiz_name(string file) {
    string name, domain, rest;

    if(file[0] != '/') file = "/"+ file;
    if(sscanf(file, WIZARD_DIR +"%s/%s", name, rest) == 2
    || sscanf(file, DOMAIN_DIR +"%s/w/%s/%s", domain, name, rest) == 3) {
      return name;
    }
    return 0;
}


/*
 * Write an error message into a log file. The error occured in the object
 * 'file', giving the error message 'message'.
 */

void log_error(string file, string message) {
    string name;

    name = get_wiz_name(file);
    if(!name)  name = "log";
    write_file("/log/"+ name, message);
}


/****************************************************************************/
/* edit setup save */

/*
 * The wizard object 'who' wants to save his ed setup. It is saved in the
 * file /players/wiz_name/.edrc . A test should be added to make sure it is
 * a call from a wizard.
 *
 * Don't care to prevent unauthorized access of this file. Only make sure
 * that a number is given as argument.
 */

int save_ed_setup(object who, int code) {
    string file;

    if(!intp(code)) return 0;
    file = WIZARD_DIR+(string)who->query_name(1)+"/"+ ED_SAVE;
    rm(file);
    return write_file(file,code+"");
}


/*
 * Retrieve the ed setup. No meaning to defend this file read from
 * unauthorized access.
 */

int retrieve_ed_setup(object who) {
    string file;
    int code;

    file = WIZARD_DIR+(string)who->query_name(1)+"/"+ ED_SAVE;
    if (file_size(file) <= 0) return 0;
    sscanf(read_file(file), "%d", code);
    return code;
}


/***************************************************************************/
/* a number of fn() in master will accept calls only from specific objects */
/* they form the basis of the security of the mud                          */


nomask status valid_master_call(object ob) {
  return (debug_mode || (status)SECURITY_FILE->valid_master_object(ob));
}

nomask status valid_player_call(object ob) {
  if(valid_master_call(ob)) return 1;
  return (debug_mode || (status)SECURITY_FILE->restricted_path_object(ob));
}
 

/****************************************************************************/

/*
 * When an object is destructed, this function is called with every
 * item in that room. We get the chance to save players !
 */

void destruct_environment_of(object ob) {
  if(!interactive(ob)) return;
  tell_object(ob,
  "Everything you see is disolved.\n"+
  "Luckily, you are transported somewhere...\n");
  ob->move_player("is transfered#"+ VOID,0,1); /* domain safe move */
}


#ifndef MUDOS_DR   /* mudos loads these at startup in config */

/**********************************************************************/
/* include directories */

/*
 * Define where the '#include' statement is supposed to search for files.
 * "." will automatically be searched first, followed in order as given
 * below. The path should contain a '%s', which will be replaced by the file
 * searched for.
 */

string *define_include_dirs() {
  return ({
    "/include/%s", "/include/fn_specs/%s","/include/cfg/%s",
    "/include/fn/%s","/include/skills/%s",
  });
}

#endif /* !MUDOS_DR */

/**********************************************************************/

/*
 * The master object is asked if it is ok to shadow object ob. Use
 * previous_object() to find out who is asking.
 *
 * In this example, we allow shadowing as long as the victim object
 * hasn't denied it with a query_prevent_shadow() returning 1.
 */

#ifdef MUSOS_DR 
int valid_shadow(object ob) {
#else
int query_allow_shadow(object ob) {
#endif /* MUDOS_DR */
    string file;

#ifdef SHADOW_DIR
    file = file_name(previous_object());
    if(file[0] != '/') file = "/"+ file;
    if(sscanf(file,SHADOW_DIR,file) != 1) {
      return 0; /* only shadows that have been inspected can be used */
    }
#endif
    /* do not allow shadows with our security fns in them */
    if(function_exists("valid_read",previous_object())
    || function_exists("valid_write",previous_object())) {
      return 0;
    }
    return !ob->query_prevent_shadow(previous_object());
}


/************************************************************************/
/* where is file written if wizard goes net-dead during edit *
 *
 * Give a file name for edit preferences to be saved in.
 */

string get_ed_buffer_save_file_name(string file) {
  string *file_ar;

  if(!debug_mode && file && file != "") {
    SECURITY_FILE->remove_current_edit(((file[0] != '/') ? "/" : "")+ file); 
  }
  file_ar = explode(file,"/");
  file = file_ar[sizeof(file_ar)-1];
  return WIZARD_DIR+(string)this_player()->query_name(1)+"/"+DEAD_ED+"/"+file;
}


#ifndef MUDOS_DR /* mudos loads simul efun before master */
/***************************************************************************/

/*
 * Give a path to a simul_efun file. Observe that it is a string returned,
 * not an object. But the object has to be loaded here. Return 0 if this
 * feature isn't wanted.
 */

static string get_simul_efun_file() {
  if(catch(call_other(SIMUL_EFUN, "??"))) {
    write("Failed to load " + SIMUL_EFUN + "\n");
    if(catch(call_other(SPARE_SIMUL_EFUN_FILE, "??"))) {
      write("Failed to load spare " + SPARE_SIMUL_EFUN_FILE + "\n");
      shutdown();
      return 0;
    }
    return SPARE_SIMUL_EFUN_FILE;
  }  
  return SIMUL_EFUN;
}

string get_simul_efun() {
#ifdef AMYLAAR321
  return "/"+ get_simul_efun_file();
#else
  return get_simul_efun_file();
#endif /* AMYLAAR321 */
}

#endif /* !MUDOS_DR */

/****************************************************************************/
/* file_size that can be used by all objects */

int master_file_size(string file) {
  return file_size(file);
}


/**************************************************************************/
/* exec() is called in player.c */

/*
 * Function name:   valid_exec
 * Description:     Checks if a certain 'program' has the right to use exec()
 * Arguments:       name: Name of the 'program' that attempts to use exec()
 *                        Note that this is different from file_name(),
 *                        Programname is what 'function_exists' returns.
 *                  NOTE, the absence of a leading slash in the name.
 * Returns:         True if exec() is allowed.
 */

int valid_exec(string name) {
  if(name && name != "" && name[0] == '/') { 
    name = name[1..(strlen(name)-1)];
  }
  switch(name) {
    case  PLAYER +".c":
    case  WIZARD +".c":
      return 1;
    break;
  }
  write("Invalid Exec() call by object: "+ name +"\n");
  return 0;
}


#ifdef AMYLAAR

void runtime_error(string error,
                   string program,
                   string current_object,
                   int line) {
  if(!this_player() || !query_ip_number(this_player())) return;
  if(!query_player_level("error messages") || !error) {
#ifdef ADMIN_NAME
    write(ADMIN_NAME +" exclaims: You have found a Space-Time Anomaly.\n");
#else
    write("Driver says: You have found a Space-Time Anomaly.\n");
#endif /* ADMIN_NAME */
  }
  else {
    write(error +"\n");
    write(((current_object) 
     ? "program: "+ program +", object: "+ current_object +" line "+ line +"\n"
     : ""));
  }
}


int heart_beat_error(object heart_beat,
                     string error,
                     string program,
                     string current_object,
                     int line) {
  string wiz_name;

  if(!heart_beat || !query_ip_number(heart_beat)) return 0;
#ifdef ADMIN_NAME
  tell_object(heart_beat,ADMIN_NAME +" tells you: You have no heart beat !\n");
#else
  tell_object(heart_beat,"Driver tells you: You have no heart beat !\n");
#endif /* ADMIN_NAME */
  if(query_player_level("error messages")) {
    tell_object(heart_beat, error +"\n");
    tell_object(heart_beat, ((current_object)
    ? "program: "+program+", object: "+current_object+" line "+line+"\n"
    : ""));
  }

#ifdef LOG_HB_ERROR
  if(environment(this_player())) {
    write_file(LOG_HB_ERROR,"Room: "+ file_name(environment(this_player())) +
               "\nError: "+ error +
               "Program: "+ program +
               "\nObject: "+ current_object + 
               "\nLine: "+ line +"\n\n");
    if(!(wiz_name = get_wiz_name(file_name(environment(this_player()))))) {
      if(!(wiz_name = get_wiz_name(current_object))) {
        return 0;
      }
    }
    write_file(WIZARD_DIR+ wiz_name +"/HB_ERRORS",
      "Room: "+ file_name(environment(this_player())) +"\n"+
      "Error: "+ error +
      "Program: "+ program +"\n"+
      "Object: "+ current_object +"\n"+
      "Line: "+ line +"\n\n");
  }
#endif
    
  return 0; /* Don't restart */
}

#endif /* AMYLAAR */



/*************************************************************************/
/* validates whether an object can be loaded  */
/* in native it gives object its uid          */

static mixed master_creator_file(string object_name) {
  string wiz_name, domain, trailer;

  if(sscanf("/"+object_name,WIZARD_DIR+"%s/%s",wiz_name,trailer)) {
    return wiz_name;
  }
  if(sscanf("/"+object_name,DOMAIN_DIR+"%s/w/%s/%s",domain,wiz_name,trailer)) {
    return wiz_name;
  } 

  /* directories that should not have objects in them */
  if(sscanf(object_name,"usr/%s", trailer))                       return 0; 
  if(sscanf(object_name,"doc/%s", trailer))                       return 0;
  if(sscanf(object_name,"info/%s", trailer))                      return 0;
  if(sscanf(object_name,"help/%s", trailer))                      return 0;
  if(sscanf(object_name,"manuals/%s", trailer))                   return 0;
  if(sscanf("/"+object_name,WIZARD_DIR+"%s",trailer))             return 0;
  if(sscanf("/"+object_name,DOMAIN_DIR+"%s/w/%s",domain,trailer)) return 0;
  if(sscanf(object_name,"open/%s", trailer))                      return 0;      
  if(sscanf(object_name,"log/%s", trailer))                       return 0;
  return 1;  /* else legal */
}


mixed creator_file(string object_name) {
  mixed creator_status;

  if((creator_status = master_creator_file(object_name))) {
#ifdef NATIVE_MODE
    return UID_ROOT;
#else
    return creator_status;
#endif
  }
  return 0;
}



void move_or_destruct(object what, object to)
/* An error in this function can be very nasty. Note that unlimited recursion
 * is likely to cause errors when environments are deeply nested
 */
{
#ifdef COMPAT_FLAG
    do {
     int res;
     if (catch( res = transfer(what, to) )) res = 5;
     if ( !(res && what) ) return;
    } while( (res == 1 || res == 4 || res == 5) && (to = environment(to)) );
#else /* !COMPAT_FLAG */
    if ( !catch( what->move(to, 1) ) ) return;
#endif /*COMPAT_FLAG */
    
    /*
     * Failed to move the object. Then, it is destroyed.
     */
    destruct(what);
}


/******************************************************************/
/* snoops must routed via simul_efun */

int valid_snoop(object snooper, object snoopee) {
#ifndef MUDOS_DR
   if(file_name(previous_object()) == get_simul_efun()) return 1;
#else
   if(file_name(previous_object()) == SIMUL_EFUN) return 1;
#endif /* MUDOS_DR */
}


/****************************************************************/
/* snoops are usable by priviledged people */

int valid_query_snoop(object wiz) {
  return query_player_level("snoop");
}


#ifdef AMYLAAR

#ifdef COMPAT_FLAG

mixed *prepare_destruct1(object ob) {
    object super;

    super = environment(ob);
    if (super) {
     mixed error, *errors;
     mixed weight;
     object me;
     me = this_object();
     set_this_object(ob);
     errors = ({});
     if ( living(ob) ) {
      if (error = catch(super->exit(ob),0))
       errors = ({"exit"+": "+error});
     }
     if ( error = catch((weight = (mixed)ob->query_weight()),0) ) {
      set_this_object(me);
      return ({"query_weight"+": "+error}) + errors;
     }
     if (weight && intp(weight)) {
      if (error = catch(super->add_weight(-weight),0)) {
       set_this_object(me);
       return ({"add_weight"+": "+error}) + errors;
      }
     }
     set_this_object(me);
    }
    return ({});
}
#endif /* COMPAT_FLAG */


mixed prepare_destruct(object ob) {
  object super;
  mixed *errors;
  int i;

#if 6 * 7 != 42 || 6 * 9 == 42
  return "Preprocessor error";
#endif

#ifdef COMPAT_FLAG
  errors = prepare_destruct1(ob);
  for(i = sizeof(errors); i--; ) {
    write(errors[i]);
  }
#endif /* COMPAT_FLAG */
  super = environment(ob);
  if (!super) {
    object item;

    while ( item = first_inventory(ob) ) {
      destruct_environment_of(item);
      if (item && environment(item) == ob) destruct(item);
    }
  } 
  else {
    while (first_inventory(ob)) move_or_destruct(first_inventory(ob), super);
  }
  return 0; /* success */
}

/* privilege_violation is called when objects try to do illegal things,
 * or files being compiled request a privileged efun.
 *
 * return values: 
 *   1: The caller/file is allowed to use the privilege.
 *   0: The caller was probably misleaded; try to fix the error.
 *  -1: A real privilege violation. Handle it as error.
 */

int privilege_violation(string what, mixed who, mixed arg) {
  switch(what) {
     case "call_out_info":
       return (valid_player_call(who)) ? 1 : -1;

#ifdef INTERMUD
     case "send_imp":
     case "wizlist_info":
       return (valid_player_call(who) || file_name(who) == INETD) ? 1 : -1;
#else
     case "wizlist_info":
       return (valid_player_call(who)) ? 1 : -1;
#endif /* INTERMUD */ 

     case "shutdown":
       return (valid_player_call(who) || file_name(who) == SHUTD) ? 1 : -1;
     
     case "nomask simul_efun":
     case "set_auto_include_string":
     case "add_worth":
     case "bind_lambda":
     case "get_extra_wizinfo":
     case "rename_object":
     case "set_extra_wizinfo":
     case "set_extra_wizinfo_size":
     case "set_this_object":
     case "shadow_add_action":
       return (valid_master_call(who)) ? 1 : -1;

     default:
       return -1;
    }
    return -1;
}



#ifdef INTERMUD

void receive_imp(string sender,string msg) {
    INETD->receive_udp(sender,msg);
}

#endif  /* INTERMUD */


void dangling_lfun_closure() {
  raise_error("dangling lfun closure\n");
}

#endif  /* AMYLAAR */


void slow_shut_down(int minutes) {
  shout("Game driver shouts: The memory is getting low !\n");
  SHUTD->shut(minutes);
}


void remove_player(object victim) {
  catch(victim->quit());
  if(victim) destruct(victim);
}


#ifndef 312MASTER

/************************************************************************/
/* I don't know anyone who uses it?
 * Parse_command() is a heavy load */

/*
 * Default language functions used by parse_command() in non -o mode
 */

string *parse_command_id_list()
{
    return ({ "one", "thing" });
}

string *parse_command_plural_id_list()
{
    return ({ "ones", "things", "them" });
}

string *parse_command_adjectiv_id_list()
{
    return ({ "iffish" });
}

string *parse_command_prepos_list()
{
    return ({ "in", "on", "under", "behind", "beside" });
}

string parse_command_all_word()
{
    return "all";
}

#endif /* 312MASTER */



UID_TYPE get_root_uid() { return UID_ROOT; }


#ifdef NATIVE_MODE /* mudos/native master fns */

string get_bb_uid()   { return UID_BACKBONE; }

string domain_file(string str) {
    string nom, tmp;

    if(str[0] != '/') str = "/"+str;
    if(sscanf(str, DOMAIN_DIR+"%s/%s", nom, tmp) == 2) return nom;
    return 0;
}

string author_file(string str) {  return get_wiz_name(str);  }

int valid_seteuid(object ob, string id) {
    return 1;
}

int valid_override(string file, string efun_call) { return 1; }


#endif /* mudos */






/*********************************************/
/* file security */


static mixed valid_file_access(string path, 
                               object caller,
                               string call_fun,
                               string access) {
  mixed file;
  object ob;
 


  if(path[0] != '/') path = "/"+ path;
  ob = (debug_mode) ? this_player() : (object)SECURITY_FILE;
  file = (mixed)call_other(ob,"valid_"+ access, path, caller, call_fun);
  if(!file) {
#if 1
    if(query_player_level("error messages")) {
      write("Invalid "+ access +" Access:\t "+ path
           +"\n\t\tCaller:\t "+ file_name(caller) 
           +"\n\t\tEfun:\t "+ call_fun +"\n"); 
    }
    else {
      write("Bad file name.\n");
    }
#else
      write("Invalid "+ access +" Access:\t "+ path
           +"\n\t\tCaller:\t "+ file_name(caller) 
           +"\n\t\tEfun:\t "+ call_fun +"\n"); 
#endif
  }
  return file;
}


#ifndef MUDOS_DR

mixed valid_write(string path, 
                  string eff_user,
                  string call_fun,
                  object caller) {
  if(!objectp(caller)) caller = previous_object();
  return valid_file_access(path, caller, call_fun, "write");
}

mixed valid_read(string path, 
                 string eff_user, 
                 string call_fun, 
                 object caller) {
  if(!objectp(caller)) caller = previous_object();
  return valid_file_access(path, caller, call_fun, "read");
}

/************************************************************************/
/* used by ed() to resolve a full path name */

mixed make_path_absolute(string path) { 
  return (string)this_player()->valid_read(path); 
}


#else


mixed valid_write(string path, 
                  mixed caller,
                  string call_fun) {
  if(!objectp(caller)) caller = previous_object();
  return valid_file_access(path, caller, call_fun, "write");
}


mixed valid_read(string path, 
                 mixed caller,
                 string call_fun) {
  if(!objectp(caller)) caller = previous_object();
  return valid_file_access(path, caller, call_fun, "read");
}

#endif /* mudos */



/**************************************************************************/
/* wizlist */

#if defined(AMYLAAR)

#if HAVE_WIZLIST == 0

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


static void wiz_decay() {
    mixed *wl;
    int i;

    wl = wizlist_info();
    for (i=sizeof(wl); i--; ) {
     set_extra_wizinfo(wl[i][WL_NAME], wl[i][WL_EXTRA] * 99 / 100);
    }
    call_out("wiz_decay", 3600);
}


void save_wiz_file() {
    rm("/WIZLIST");
    write_file(
      "/WIZLIST",
      implode(
     map_array(wizlist_info(),
       lambda(({'a}),
         ({#'sprintf, "%s %d %d\n",
           ({#'[, 'a, WL_NAME}),
           ({#'[, 'a, WL_COMMANDS}),
           ({#'[, 'a, WL_EXTRA})
         })
       )
     ), ""
      )
    );
}

void notify_shutdown() {
  if(previous_object() && valid_master_call(previous_object())) return;
  save_wiz_file();
}

#endif /* WIZLIST */


void inaugurate_master(int arg)
{

#if HAVE_WIZLIST == 0
    if (!arg)
        set_extra_wizinfo(0, allocate(BACKBONE_WIZINFO_SIZE));
    if (find_call_out("wiz_decay") < 0)
        call_out("wiz_decay", 3600);
#endif /* HAVE_WIZLIST */

#if defined(AMYLAAR321)
    set_driver_hook(
      H_MOVE_OBJECT0,
      unbound_lambda( ({'item, 'dest}), ({#',,
#ifdef NATIVE_MODE
     ({#'?, ({#'!=, 'item, ({#'this_object})}),
       ({#'raise_error,
         "Illegal to move other object than this_object()\n"}) }),
#endif
#ifdef COMPAT_FLAG
     ({#'&&, ({#'living, 'item}), ({#'environment, 'item}), ({#',,
       ({#'efun::set_this_player, 'item}),
       ({#'call_other, ({#'environment, 'item}), "exit", 'item}),
     }) }),
#endif
     ({#'efun::efun308, 'item, 'dest}),
     ({#'?, ({#'living, 'item}), ({#',,
       ({#'efun::set_this_player, 'item}),
       ({#'call_other, 'dest, "init"}),
       ({#'?, ({#'!=, ({#'environment, 'item}), 'dest}), ({#'return})}),
     }) }),
     ({#'=, 'others, ({#'all_inventory, 'dest}) }),
     ({#'=, ({#'[, 'others, ({#'member, 'others, 'item}) }), 0}),
     ({#'filter_array, 'others,
       ({#'bind_lambda,
         unbound_lambda( ({'ob, 'item}),
           ({#'?, ({#'living, 'ob}), ({#',,
          ({#'efun::set_this_player, 'ob}),
          ({#'call_other, 'item, "init"}),
           }) })
         )
       }),
       'item,
     }),
     ({#'?, ({#'living, 'item}), ({#',,
       ({#'efun::set_this_player, 'item}),
       ({#'filter_objects, 'others, "init"}),
     }) }),
     ({#'?, ({#'living, 'dest}), ({#',,
       ({#'efun::set_this_player, 'dest}),
       ({#'call_other, 'item, "init"}),
     }) }),
      }) )
    );
#ifdef COMPAT_FLAG
    set_driver_hook(
      H_LOAD_UIDS,
      unbound_lambda( ({'object_name}),
     ({#'?,
       ({#'==,
         ({#'sscanf, 'object_name, "players/%s", 'wiz_name}),
         1,
       }),
       ({#'?,
         ({#'==,
           ({#'sscanf, 'wiz_name, "%s/%s", 'start, 'trailer}),
           2,
         }),
         ({#'&&, ({#'strlen, 'start}), 'start}),
         'wiz_name
       }),
       ({#'&&,
         ({#'!=, ({#'[..], 'object_name, 0, 3}), "ftp/"}),
         ({#'!=, ({#'[..], 'object_name, 0, 4}), "open/"}),
       })
     })
      )
    );
    set_driver_hook(
      H_CLONE_UIDS,
      unbound_lambda( ({'blueprint, 'new_name}), ({
     #'||,
       ({#'creator, 'blueprint}),
       ({#'creator, ({#'previous_object})}),
       1
      }) )
    );
    set_driver_hook(H_CREATE_SUPER, "reset");
    set_driver_hook(H_CREATE_OB,    "reset");
    set_driver_hook(H_CREATE_CLONE, "reset");
#else
    /* the following closures illustrate how the 3.1.2 driver used to
     * set (e)uids. It should be usable for tests, but to get better
     * performance, you are encouraged to replace the function
     * calls to get_bb_uid() and creator_file() by the equivalent code,
     * even if you are satisfied with the current behaviour.
     */
    set_driver_hook(
      H_LOAD_UIDS,
      unbound_lambda( ({'object_name}), ({
     #'?,
     ({#'==,
       ({#'=, 'creator_name, ({#'creator_file, 'object_name})}),
       ({#'getuid, ({#'previous_object})}),
     }),
      ({#'geteuid, ({#'previous_object})}),
     ({#'==, 'creator_name, ({#'get_bb_uid})}),
      ({#'geteuid, ({#'previous_object})}),
      ({#'({, 'creator_name, 1}),
      }) )
    );
    set_driver_hook(
      H_CLONE_UIDS,
      unbound_lambda( ({ /* object */ 'blueprint, 'new_name}), ({
     #'?,
     ({#'==,
       ({#'=, 'creator_name, ({#'creator_file, 'new_name})}),
       ({#'getuid, ({#'previous_object})}),
     }),
      ({#'geteuid, ({#'previous_object})}),
     ({#'==, 'creator_name, ({#'get_bb_uid})}),
      ({#'geteuid, ({#'previous_object})}),
      ({#'({, 'creator_name, 1}),
      }) )
    );
#ifdef NATIVE_MODE
    set_driver_hook(H_CREATE_OB,    "create");
    set_driver_hook(H_CREATE_CLONE, "create");
#else
    set_driver_hook(H_CREATE_SUPER,
      unbound_lambda(0, ({#',,
       ({#'call_other, ({#'this_object}), "create"}),
       ({#'call_other, ({#'this_object}), "reset"})
     })
      )
    );
    set_driver_hook(H_CREATE_OB,
      unbound_lambda(0, ({#',,
       ({#'call_other, ({#'this_object}), "create"}),
       ({#'call_other, ({#'this_object}), "reset"})
     })
      )
    );
    set_driver_hook(H_CREATE_CLONE,
      unbound_lambda(0, ({#',,
       ({#'call_other, ({#'this_object}), "create"}),
       ({#'call_other, ({#'this_object}), "reset"})
     })
      )
    );
#endif
#endif
    set_driver_hook(H_RESET,        "reset");
    set_driver_hook(H_CLEAN_UP,     "clean_up");

#endif /* AMYLAAR321 */
}


#if defined(AMYLAAR321)

mixed current_time;

string *epilog(int eflag) {
    if (eflag) return ({});
    debug_message(sprintf("Loading init file %s\n", INIT_FILE));
    current_time = rusage();
    current_time = current_time[0] + current_time[1];
    return explode(read_file(INIT_FILE), "\n");
}

void preload(string file) {
    int last_time;

    if (strlen(file) && file[0] != '#') {
        last_time = current_time;
        debug_message(sprintf("Preloading: %s", file));
        call_other(file, "");
        current_time = rusage();
        current_time = current_time[0] + current_time[1];
        debug_message(sprintf(" %.2f\n", (current_time - last_time)/1000.));
    }
}

#endif /* AMYLAAR321 */
#endif /* AMYLAAR */


/***********************************************************************/
/* promote new wizards and domain wizards */


string master_create_wizard(string owner,string domain,object caller) {
  string txt, tmp1, tmp2;
  object access;
  int tmp;

  if(!owner) return 0;
  
  if(!valid_player_call(caller)) return 0;
  write_file("/log/WIZ",
    "Name: "+ owner +", By: "+ (string)this_player()->query_name(1)
   +" Time: "+ ctime(time()) +"\n");

  /* promote wizard */
  
  if(!domain) {
    if(file_size(WIZARD_DIR+ owner) != -2) {
      tell_object(caller,"Adding Wizard Directory...\n");
      mkdir(WIZARD_DIR+ owner); 
    }
    if(file_size(WIZARD_DIR+ owner +"/open") != -2) {
      tell_object(caller,"Adding Open directory, ~/open\n");
      mkdir(WIZARD_DIR+ owner +"/open"); 
    }
    if(file_size(WIZARD_DIR+ owner +"/private") != -2) {
      tell_object(caller,"Adding Private directory, ~/private\n");
      mkdir(WIZARD_DIR+ owner +"/private");
    }
    if(file_size(WIZARD_DIR+ owner +"/"+ DEAD_ED) != -2) {
      tell_object(caller,"Adding dead edit directory, ~/"+ DEAD_ED +"\n");
      mkdir(WIZARD_DIR+ owner +"/"+ DEAD_ED);
    }
    if(file_size(INIT_ACCESS) > 0 
    && file_size(WIZARD_DIR+ owner +"/access.c") < 0) {  
      tell_object(caller,"Adding Configurable Access Object...\n");
      txt = "#define NAME \""+ owner +"\"\n";
      write_file(WIZARD_DIR+ owner +"/access.c",txt);
      txt = read_file(INIT_ACCESS); 
      write_file(WIZARD_DIR+ owner +"/access.c",txt);
    }
    if(file_size(INIT_WORKROOM) > 0
    && file_size(WIZARD_DIR+ owner +"/workroom.c") < 0) {  
      tell_object(caller,"Adding Workroom...\n");
      txt = "#include <mudlib.h>\ninherit ROOM;\n\n";
      write_file(WIZARD_DIR+ owner +"/workroom.c",txt);
      txt = read_file(INIT_WORKROOM); 
      write_file(WIZARD_DIR+ owner +"/workroom.c",txt);
    }
  }
  else { /* Add wizard to domain */
    if(file_size(DOMAIN_DIR+ domain) != -2) {
      if(catch(call_other(DOMAIN_DIR +"access","??"))) {
        write("Error In Loading Head Domain Access Object!\n");
      }
    
      if(query_player_level("create domain")) { 
        write("Adding New Domain...\nMaking "+ owner +" the High Lord.\n");
        if(this_player() != caller) {
          tell_object(caller,"Adding New Domain...\n"+
            "You are now High Lord over "+ domain +".\n"); 
        }
        mkdir(DOMAIN_DIR+ domain);
 
 
        txt = read_bytes(DOMAIN_DIR +"access.c",
                         0, file_size(DOMAIN_DIR +"access.c"));
       
        rm(DOMAIN_DIR +"access.bak");
        write_file(DOMAIN_DIR +"access.bak",txt);                 
 
        sscanf(txt, "%s});%s", tmp1, tmp2);
        txt = "\""+owner+"\",                     ";
        txt = extract(txt,0,15);
        txt += "\""+ domain +"\",\n";
        txt = tmp1+txt +"    });"+ tmp2;
        rm(DOMAIN_DIR +"access.c");
        write_file(DOMAIN_DIR +"access.c",txt);
        if((access = find_object(DOMAIN_DIR +"access"))) {
          destruct(access);
        }
        if(catch(call_other(DOMAIN_DIR +"access","??"))) {
          write("Error In Reloading Head Domain Access Object!\n");
        }
      }
      else {
        write("You cannot add a New Domain.\n");
        return 0;
      }
    }
    if(file_size(DOMAIN_DIR+ domain +"/access.c") < 0) {
      txt = read_bytes(DOMAIN_ACCESS,0,file_size(DOMAIN_ACCESS));
      write_file(DOMAIN_DIR+domain+"/access.c",txt);
      if(catch(call_other(DOMAIN_DIR+ domain +"/access","??"))) {
        write("Error In Reloading Domain Access Object!\n");
      }
    }           
    if(file_size(DOMAIN_DIR+ domain +"/w") != -2) {
      mkdir(DOMAIN_DIR+ domain +"/w");
    }
    if(file_size(DOMAIN_DIR+ domain +"/w/"+ owner) != -2) {
      tell_object(caller,"Adding Domain directory...\n");
      mkdir(DOMAIN_DIR+ domain +"/w/"+ owner);
    }
    if(file_size(DOMAIN_DIR+ domain +"/w/"+ owner +"/access.c") < 0) {  
      tell_object(caller,"Adding Configurable Access Object...\n");
      txt = read_bytes(PLAYER_DOMAIN_ACCESS,0,file_size(PLAYER_DOMAIN_ACCESS));
      write_file(DOMAIN_DIR+ domain +"/w/"+ owner +"/access.c",txt);
      if(catch(call_other(DOMAIN_DIR+domain+"/w/"+owner+"/access","??"))) {
        write("Error In Reloading Domain Creator Access Object!\n");
      }
    }
  }
}