dsI/bin/
dsI/extra/creremote/
dsI/extra/mingw/
dsI/extra/wolfpaw/
dsI/fluffos-2.7-ds2.018/
dsI/fluffos-2.7-ds2.018/ChangeLog.old/
dsI/fluffos-2.7-ds2.018/Win32/
dsI/fluffos-2.7-ds2.018/compat/
dsI/fluffos-2.7-ds2.018/compat/simuls/
dsI/fluffos-2.7-ds2.018/testsuite/
dsI/fluffos-2.7-ds2.018/testsuite/clone/
dsI/fluffos-2.7-ds2.018/testsuite/command/
dsI/fluffos-2.7-ds2.018/testsuite/data/
dsI/fluffos-2.7-ds2.018/testsuite/etc/
dsI/fluffos-2.7-ds2.018/testsuite/include/
dsI/fluffos-2.7-ds2.018/testsuite/inherit/
dsI/fluffos-2.7-ds2.018/testsuite/inherit/master/
dsI/fluffos-2.7-ds2.018/testsuite/log/
dsI/fluffos-2.7-ds2.018/testsuite/single/
dsI/fluffos-2.7-ds2.018/testsuite/single/tests/compiler/
dsI/fluffos-2.7-ds2.018/testsuite/single/tests/efuns/
dsI/fluffos-2.7-ds2.018/testsuite/single/tests/operators/
dsI/fluffos-2.7-ds2.018/testsuite/u/
dsI/fluffos-2.7-ds2.018/tmp/
dsI/lib/cfg/
dsI/lib/cmds/common/
dsI/lib/cmds/creators/include/
dsI/lib/cmds/creators/include/SCCS/
dsI/lib/daemon/services/
dsI/lib/doc/
dsI/lib/domains/Ylsrim/
dsI/lib/domains/Ylsrim/adm/
dsI/lib/domains/Ylsrim/armour/
dsI/lib/domains/Ylsrim/broken/
dsI/lib/domains/Ylsrim/fish/
dsI/lib/domains/Ylsrim/meal/
dsI/lib/domains/Ylsrim/npc/
dsI/lib/domains/Ylsrim/virtual/
dsI/lib/domains/Ylsrim/weapon/
dsI/lib/domains/default/creator/
dsI/lib/domains/default/etc/
dsI/lib/domains/default/room/
dsI/lib/lib/comp/
dsI/lib/lib/lvs/
dsI/lib/lib/user/
dsI/lib/lib/virtual/
dsI/lib/obj/
dsI/lib/obj/include/
dsI/lib/realms/
dsI/lib/save/kills/a/
dsI/lib/save/kills/b/
dsI/lib/save/kills/f/
dsI/lib/save/kills/m/
dsI/lib/save/kills/q/
dsI/lib/save/kills/r/
dsI/lib/secure/cfg/
dsI/lib/secure/cfg/classes/
dsI/lib/secure/cfg/races/SCCS/
dsI/lib/secure/cmds/creators/include/
dsI/lib/secure/cmds/players/
dsI/lib/secure/cmds/players/include/
dsI/lib/secure/daemon/include/
dsI/lib/secure/lib/
dsI/lib/secure/lib/include/
dsI/lib/secure/lib/net/
dsI/lib/secure/lib/net/include/
dsI/lib/secure/lib/std/
dsI/lib/secure/obj/
dsI/lib/secure/obj/include/
dsI/lib/secure/save/
dsI/lib/spells/
dsI/lib/verbs/admins/include/
dsI/lib/verbs/common/
dsI/lib/verbs/common/include/
dsI/lib/verbs/creators/
dsI/lib/verbs/creators/include/
dsI/lib/verbs/players/include/SCCS/
dsI/lib/verbs/rooms/
dsI/lib/verbs/rooms/include/
dsI/lib/www/
dsI/v22.2b14/
dsI/win32/
/*    /lib/interactive.c
 *    from the Dead Soulsr1 Object Library
 *    an interactive object
 *    created by Descartes of Borg 941001 for the Idea Exchange
 *    Version: @(#) interactive.c 1.17@(#)
 *    Last modified: 97/01/03
 */

#include <lib.h>
#include <clock.h>
#include <privs.h>
#include <daemons.h>
#include <objects.h>
#include <rooms.h>
#include <marriage.h>
#include <medium.h>
#include <position.h>
#include <message_class.h>
#include <vision.h>
#include <voting.h>
#include "include/interactive.h"

inherit LIB_CONTAINER;
inherit LIB_OBJECT;
inherit LIB_AUTOSAVE;
inherit LIB_FILES;
inherit LIB_MOVE;
inherit LIB_PAGER;
inherit LIB_MESSAGES;
inherit LIB_INTERFACE;

private int Age, WhereBlock, Brief, LoginTime, BirthTime;
private string Password, Email, RealName, Rank, LoginSite, HostSite, WebPage;
private mapping News;
private class marriage *Marriages;
private static int LastAge, Setup;
private static object NetDiedHere;
private static mapping LastError;
private static string *UserId;

static void create() {
    object::create();
    messages::create();
    interface::create();
    SetOpacity(0);
    Marriages = ({});
    HostSite = "";
    Brief = 0;
    Password = 0;
    Email = 0;
    RealName = 0;
    Rank = "citizen";
    LoginSite = ROOM_START;
    BirthTime = time();
    LastAge = time();
    News = ([]);
    SetShort("$N the unaccomplished");
    SetLong("$N is nondescript.");
}

/* ***************  /lib/interactive.c modal functions  *************** */

mixed CanDivorce(object who) {
    class marriage m;
    
    if( !Marriages || !sizeof(Marriages) )
      return GetName() + " is not married!";
    m = Marriages[0];
    if( m->DivorceDate ) return GetName() + " is not married!";
    return 1;
}
    
mixed CanGet(object ob) {
    return GetName() + " is a living being!";
}

mixed CanMarry(object who, object to_whom) {
    if( !Marriages ) Marriages = ({});
    if( GetSpouse() ) return GetName() + " is currently married!";
    return 1;
}

/* ***************  /lib/interactive.c lfuns  *************** */
int Setup() {
    mapping mp;
    string tmp;

    if(Setup) return 0;
    else Setup = 1;
    set_living_name(GetKeyName());
    interface::Setup();
    add_action((: cmdQuit :), "quit");
    HostSite = query_ip_name(this_object());
    LoginTime = time();
    SetId(({}));
    autosave::Setup();
    call_out("save_player", 2, GetKeyName());
    log_file("enter", GetCapName()+" (enter): "+ctime(time())+
      " : "+query_ip_name(this_object())+"\n");
    if( VOTING_D->GetStatus() == VOTE_RUNNING ) {
        if( VOTING_D->GetMode() == VOTE_MODE_CANDIDATES )
            eventPrint("%^YELLOW%^Class Elections are in progress!  "
              "Go nominate candidates!%^RESET%^");
        if( VOTING_D->GetMode() == VOTE_MODE_VOTING )
            eventPrint("%^YELLOW%^Class Elections are in progress!  "
              "Go vote for the candidates!%^RESET%^");
    } 

    if( VOTING_D->GetVoteStatus( this_object() ) != VOTE_ALREADY_VOTED ) {
        eventPrint("%^YELLOW%^You have not yet voted!  "
          "Please vote now.%^RESET%^");
        eventMove( VOTING_D->GetVoteRoom() );
    } else {
	object room;
	
	catch(room = load_object(LoginSite));
	if( room && room->GetMedium() == MEDIUM_AIR ) {
	}
        if( !eventMove(LoginSite) ) {
	    eventMove(LoginSite = ROOM_START);
	}
    }
    environment()->eventPrint(tmp, MSG_ENV, this_object());
    if( !(tmp = GetMessage("login")) )
      tmp = GetName() + " enters " + mud_name() + ".";
    filter(users(), (: archp :))->eventPrint("[" + GetCapName() + " logs in]",
                                             MSG_SYSTEM);
    if(!catch(mp = (mapping)FOLDERS_D->mail_status(GetKeyName()))) {
        if(mp["unread"]) {
            eventPrint("\n>>> " + mp["unread"] + " of your " +
                       (mp["total"] == 1 ? mp["total"] + " letter is" :
                        mp["total"] + " letters remain") + " unread. <<<\n",
                       MSG_SYSTEM);
        }
    }
    NEWS_D->GeneralNews();
    return 1;
}

static void net_dead() {
    interface::net_dead();
    Age += time() - LastAge;
    LastAge = time();
    NetDiedHere = environment(this_object());
    save_player(GetKeyName());
    log_file("enter", GetCapName() + " (net-dead): " + ctime(time()) + "\n");
    environment()->eventPrint(GetName() + " suddenly disappears into "
                              "a sea of irreality.", MSG_ENV, this_object());
    filter(users(), (: archp :))->eventPrint("[" + GetCapName() +
                                             " goes net-dead]", MSG_SYSTEM);
    eventMove(ROOM_FREEZER);
    if(query_snoop(this_object()))
      query_snoop(this_object())->eventPrint(GetCapName() + " has gone "
                                             "net-dead.", MSG_SYSTEM);
}

void eventReconnect() {
    string dead_ed;

    interface::eventReconnect();
    LastAge = time();
    HostSite = query_ip_name(this_object());
    eventPrint("Reconnected.", MSG_SYSTEM);
    filter(users(), (: archp :))->eventPrint("[" + GetCapName() + " has "
                                             "rejoined " + mud_name() + "]",
                                             MSG_SYSTEM);
    if( NetDiedHere ) eventMove(NetDiedHere);
    else eventMove(ROOM_START);
    environment()->eventPrint(GetCapName() + " has rejoined this reality.",
                              MSG_ENV, this_object());
    NetDiedHere = 0;
}

void eventDescribeEnvironment(int brief) {
    object env;
    mixed tmp;
    string *shorts;
    string desc, smell, sound, touch;
    int i, maxi;

    if(!(env = environment(this_object()))) {
        eventPrint("You are nowhere.", MSG_ROOMDESC);
        return;
    }
    switch( i = GetEffectiveVision() ) {
    case VISION_BLIND:
	eventPrint("You are blind and can see nothing.");
	break;
    case VISION_TOO_DARK:
        eventPrint("It is much too dark to see.");
	break;
    case VISION_DARK:
	eventPrint("It is too dark to see.");
        break;
    case VISION_TOO_BRIGHT:
        eventPrint("It is much too %^YELLOW%^bright%^RESET%^ to see.");
	break;
    case VISION_BRIGHT:
        eventPrint("It is too %^YELLOW%^bright%^RESET%^ to see.");
        break;
    }
    if( !brief ) {
	if( i == VISION_CLEAR ) {
	    desc = (string)env->GetObviousExits() || "";
	    desc = capitalize((string)env->GetShort() || "")
		+ " [" + desc + "]\n";
	}
	else desc = "";
	if( i == VISION_CLEAR || i == VISION_LIGHT || i == VISION_DIM )
	  desc += (string)env->GetLong();
        if(functionp(tmp = (mixed)env->GetSmell("default")))
	    tmp = (string)(*tmp)("default");
        smell = tmp;
        if(functionp(tmp = (mixed)env->GetListen("default")))
          tmp = (string)(*tmp)("default");
        sound = tmp;
        if( functionp(tmp = (mixed)env->GetTouch("default")) )
          tmp = evaluate(tmp, "default");
        touch = tmp;
    }
    else {
	if( i == VISION_CLEAR || i == VISION_LIGHT || i == VISION_DIM ) {
	    desc = (string)env->GetShort();
	    if( (tmp = (string)env->GetObviousExits()) && tmp != "" )
		desc += " [" + tmp + "]";
	}
	else desc = "";
    }
    if( desc ) eventPrint(desc, MSG_ROOMDESC);
    if( smell ) eventPrint("%^GREEN%^" + smell, MSG_ROOMDESC);
    if( sound ) eventPrint("%^CYAN%^" + sound, MSG_ROOMDESC);
    if( touch ) eventPrint("%^YELLOW%^" + touch, MSG_ROOMDESC);
    desc = "";
    if( i == VISION_CLEAR ) {
	mapping lying = ([]);
	shorts = map(filter(all_inventory(env),
			    function(object ob) {
	                        if( living(ob) ) return 0;
				if( (int)ob->GetInvis(this_object()) )
				  return 0;
				if( (int)ob->isFreshCorpse() ) return 0;
				return 1;
	                    }), (: (string)$1->GetShort() :));
	foreach(string s in shorts) {
	    if( s ) {
		lying[s]++;
	    }
	}
	for(i=0, desc = 0, maxi = sizeof(shorts = keys(lying)); i<maxi; i++) {
	    string key = shorts[i];
	    int val = lying[shorts[i]];

	    if( val < 2 ) {
		if( !desc ) desc = "%^MAGENTA%^" +
				capitalize(key) + "%^RESET%^MAGENTA%^";
		else desc += key + "%^RESET%^MAGENTA%^";
	    }
	    else {
		if( !desc ) desc = "%^MAGENTA%^" +
				capitalize(consolidate(val, key)) +
		    "%^RESET%^MAGENTA%^";
		else desc += consolidate(val, key) +
		    "%^RESET%^MAGENTA%^";
	    }
	    if( i == maxi - 1 ) {
		if( maxi > 1 || val >1 )
		    desc += " are here.%^RESET%^\n";
		else desc += " is here.%^RESET%^\n";
	    }
	    else if( i == maxi - 2 ) {
		if( maxi == 2 ) {
		    desc += " and ";
		}
		else {
		    desc += ", and ";
		}
	    }
	    else desc += ", ";
	}
    }
    i = GetEffectiveVision();
    if( i == VISION_CLEAR || i == VISION_LIGHT || i == VISION_DIM ) {
	mapping lying = ([]), sitting = ([]), standing = ([]);
	object *obs;
	string key;
	int val;
	
	obs = filter(all_inventory(env), function(object ob) {
	                                   if( (int)ob->GetInvis(this_object()) ) return 0;
					   if( living(ob) ) return 1;
					   if( (int)ob->isFreshCorpse() )
					     return 1;
	                                 }) - ({ this_object() });
	maxi = sizeof(shorts = map(obs, (: (string)$1->GetHealthShort() :)));
	foreach(object liv in obs) {
	    string s = (string)liv->GetHealthShort();
	    int pos = (int)liv->GetPosition();
	    
	    if( !s ) continue;
	    if( creatorp(liv) || pos == POSITION_STANDING) standing[s]++;
	    else if( pos == POSITION_LYING || (int)liv->isFreshCorpse() )
	      lying[s]++;
	    else if( pos == POSITION_SITTING ) sitting[s]++;
	    else lying[s]++;
	}
        if( !desc ) {
            tmp = "";
        }
        else {
            tmp = desc;
        }
	desc = "";
	foreach(key, val in lying) {
	    if( val<2 ) desc += capitalize(key) + "%^RESET%^ is lying down.";
	    else desc += capitalize(consolidate(val, key)) +
		"%^RESET%^ are lying down.";
	    desc += "\n";
	}
	foreach(key, val in sitting) {
	    if( val<2 )
	      desc += capitalize(key) + "%^RESET%^ is sitting down.";
	    else desc += capitalize(consolidate(val, key)) +
		"%^RESET%^ are sitting down.";
	    desc += "\n";
	}
	foreach(key, val in standing) {
	    if( val<2 )
	      desc += capitalize(key) + "%^RESET%^ is standing here.";
	    else desc += capitalize(consolidate(val, key)) +
		"%^RESET%^ are standing here.";
	    desc += "\n";
	}
    }
    if( tmp ) {
	desc = tmp + desc;
    }
    if( sizeof(desc) ) {
	eventPrint(desc + "\n", MSG_ROOMDESC);
    }
}

int eventDestruct() {
    object ob;
    int i;

    interface::eventDestruct();
    foreach(ob in deep_inventory(this_object())) {
	if( ob ) catch(ob->eventDestruct());
    }
    return object::eventDestruct();
}

mixed eventDivorce(object who) {
    class marriage m;

    m = Marriages[0];
    m->DivorceDate = time();
    return 1;
}
    
mixed eventMarry(object who, object to_whom) {
    class marriage m;
    object env;

    if( (env = previous_object()) != environment() ) return 0;
    m = new(class marriage);
    m->Spouse = (string)to_whom->GetCapName();
    m->WeddingDate = time();
    m->DivorceDate = 0;
    m->Location = file_name(env);
    Marriages = ({ m }) + Marriages;
    return 1;
}

int eventMove(mixed dest) {
    string str;
    int x;

    x = move::eventMove(dest);
    if( x ) {
        if( !(str = (string)environment()->GetProperty("login")) )
          LoginSite = base_name(environment());
        else LoginSite = str;
    }
    return x;
}

int cmdQuit(string str) {
    string tmp;

    if( previous_object() && !
       ((int)master()->valid_apply( ({ GetKeyName() }) )) ) return 0;
    if( (int)environment(this_object())->GetProperty("no quit") &&
      ! sizeof(previous_object(-1)) ) {
        message("system", "You are unable to escape this reality!",
          this_object());
        return 1;
    }
    message("system", "Please come back another time!", this_object());
    save_player(GetKeyName());
    tmp = GetMessage("logout") || (GetName() + " is gone from this reality!");
    message("environment", tmp, environment(this_object()), ({this_object()}));
    log_file("enter", GetCapName()+" (quit): "+ctime(time())+"\n");
    message("announce", "["+GetCapName()+" quits]", filter(users(), (: archp :)));
    eventDestruct();
    return 1;
}

int GetAge() {
    int x;

    if(!interactive(this_object())) return Age;
    x = time() - LastAge;
    Age += x;
    LastAge = time();
    return Age;
}

int GetBirth() { return BirthTime - (YEAR * 18); }

string query_cwd() { return interface::query_cwd(); }

void SetEmail(string str) {
    if(!((int)master()->valid_apply(({ GetKeyName() })))) return;
    Email = str;
}

string GetEmail() {
    if(!((int)master()->valid_apply(({ GetKeyName() })))) return 0;
    else return Email;
}

void SetId(string *bogus) {
    int i;

    if(UserId) return;
    if(!GetCapName()) {
        UserId = ({ GetKeyName() });
        return;
    }
    UserId = ({ GetKeyName(), lower_case(GetCapName()) });
    if((i=sizeof(bogus = explode(lower_case(GetCapName()), " "))) == 1)
        return;
    while(i--)
        if(!user_exists(bogus[i])) UserId += ({ bogus[i] });
}

string *GetId() { return UserId; }

int id(string str) {
    if(!str || !UserId) return 0;
    else return member_array(lower_case(str), UserId) != -1;
}

int GetLoginTime() { return LoginTime; }

string SetKeyName(string str) {
    if( previous_object() != master() ) return GetKeyName();
    return object::SetKeyName(str);
}

string GetKeyName() { return object::GetKeyName(); }

void SetNews(string type, int sz) { News[type] = sz; }

int GetNews(string type) { return News[type]; }

void SetPassword(string str) {
    if(!((int)master()->valid_apply(({ GetKeyName() })))) return;
    Password = str;
    save_player(GetKeyName());
}

string GetPassword() {
    if(!((int)master()->valid_apply(({ GetKeyName() })))) return 0;
    else return Password;
}

void SetRank(string str) { Rank = str; }

string GetRank() { return Rank; }

void SetRealName(string str) {
    if(!((int)master()->valid_apply(({ GetKeyName() })))) return;
    RealName = str;
}

string GetRealName() { return RealName; }

string GetShort() {
    string str;

    str = object::GetShort(str);
    if( !str ) str = "$N the unaccomplished";
    if( strsrch(str, "$N") == -1 ) str = "$N";
    str = replace_string(str, "$N", GetName());
    if( interactive(this_object()) ) return str;
    else return str + " (net-dead)";
}

varargs string GetLong() {
    string str;

    str = object::GetLong(str);
    if(!str || strsrch(str, "$N") == -1) str = "$N is nondescript.";
    str = replace_string(str, "$N", GetName());
    return str;
}

int SetBriefMode(int x) { return (Brief = x); }

int GetBriefMode() { return Brief; }

int SetWhereBlock() { return (WhereBlock = !WhereBlock); }

int GetWhereBlock() { return WhereBlock; }

string get_path() {
    log_file("get_path", identify(previous_object())+"\n");
    return query_cwd();
}

void SetLastError(mapping m) {
    if (previous_object() != master()) return;
    LastError = m;
}

mapping GetLastError() {
    string caller = file_name(previous_object());
    if( caller[0..24] == "/secure/cmds/creators/dbx" ||
      caller[0..23] == "/secure/cmds/players/bug" ) return LastError;
    error("Privilege Violation: " + caller);
}

void SetCapName(string str) {
    if( base_name(previous_object(0)) != LIB_CONNECT ) return;
    object::SetCapName(str);
}

void move_or_destruct() {
    (eventMove(ROOM_START) || eventMove(ROOM_VOID));
}

string SetShort(string str) {
    if( strsrch(str, "$N") == -1 ) return object::GetShort();
    else return object::SetShort(str);
}

string SetLong(string str) {
    if(strsrch(str, "$N") == -1) return object::GetLong();
    else return object::SetLong(str);
}

string GetName() { return object::GetName(); }

varargs int GetInvis(object ob) { return object::GetInvis(ob); }

mixed *GetCommands() {
    if( !((int)master()->valid_apply( ({ GetKeyName() }) )) ) return ({});
    else return commands();
}

string GetSpouse() {
    if( !Marriages || !sizeof(Marriages) ) return 0;
    if( ((class marriage)Marriages[0])->DivorceDate ) return 0;
    return ((class marriage)Marriages[0])->Spouse;
}

class marriage *GetMarriages() { return Marriages; }

string GetHostSite() {
    if( WhereBlock ) {
	if( !((int)master()->valid_access(({ PRIV_ASSIST }))) )
	  return "Confidential";
	else return HostSite;
    }
    return HostSite;
}

void eventLoadObject(mixed *value, int recurse) { }

int GetRadiantLight(int ambient) {
    return (object::GetRadiantLight(ambient) +
	    container::GetRadiantLight(ambient));
}

string GetWebPage() {
    return WebPage;
}

string SetWebPage(string page) {
    if( !master()->valid_apply(({ GetKeyName() })) ) {
	return WebPage;
    }
    return (WebPage = page);
}