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. */

//### lots of functions in here need to be autodoc'd

// /std/player.c  Written after login.c 1-12-94
// Rust@ZorkMUD
// with mods by alot of us:
// including:   Nevyn@ZorkMUD (GUE)
//              Peregrin @ZorkMUD (GUE)
// Beek ... Deathblade ... The rest of the Zorkmud staff ...
//
#include <security.h>
#include <setbit.h>
#include <playerflags.h>
#include <commands.h>
#include <move.h>
#include <hooks.h>
#include <size.h>
#include <clean_up.h>

// Files we need to inherit --
inherit ADVERSARY;
inherit M_ACCESS;
inherit M_SMARTMOVE;
inherit M_FOLLOW;
inherit M_ACTIONS;

#ifndef EVERYTHING_SAVES
private inherit M_SAVE; // don't want people calling load_from_string()
// externally
#endif

inherit __DIR__ "body/quests";
inherit __DIR__ "body/cmd";
inherit __DIR__ "body/help";
inherit __DIR__ "body/wizfuncs";
inherit __DIR__ "body/money";
inherit __DIR__ "body/start";
inherit __DIR__ "body/time";
inherit __DIR__ "body/naming";

#ifndef SAY_HISTORY_IN_ROOMS
inherit __DIR__ "body/history";
#endif

#ifdef USE_STATUS_LINE
inherit __DIR__ "body/status_line";
#endif
#ifdef USE_SKILLS
inherit __DIR__ "body/skills";
#endif
#ifdef USE_TITLES
inherit __DIR__ "body/title";
#endif
#ifdef USE_WIZ_POSITION
inherit __DIR__ "body/wiz_position";
#endif
#ifdef USE_GUILDS
inherit __DIR__ "body/guilds";
#endif
#ifdef USE_STATS
inherit M_BODY_STATS;
#endif

void heal_all();
varargs void stop_fight(object);
void reinstate_effects();

// Global variables --
private string plan;
private nosave object link;
private mixed saved_items;

// interfaces for other objects to manipulate our global variables

//:FUNCTION is_body
//Is this a body object? 
int is_body() { return 1; }

//:FUNCTION query_link
//Return our link object
nomask object query_link()
{
    return link;
}

void mudlib_setup(mixed args...)
{
   adversary::mudlib_setup(args...);
   m_follow::mudlib_setup(args...);
}

#ifdef EVERYONE_HAS_A_PLAN

//:FUNCTION query_plan
//Returns our plan
nomask string query_plan()
{
    return plan;
}

//:FUNCTION set_plan
//Sets our plan
nomask void set_plan(string new_plan)
{
    if ( this_body() != this_object() )
	error("illegal attempt to set plan\n");

    plan = new_plan;
    save_me();
}

#endif /* EVERYONE_HAS_A_PLAN */

protected void update_for_new_body(mapping tmp) {
    /* nothing for now; can be overloaded for races that need it */
}
//:FUNCTION update_containers
// Update containers on loading - fix relationships
private nomask void update_container(object ob)
{
  foreach(object inv in all_inventory(ob))
  {
    if(inv->is_container())
      update_container(inv);
    ob->receive_object(inv);
  }
}

// Added to complete initialisation of stuff loaded
private nomask void init_stuff()
{
  foreach(object inv in all_inventory())
  {
#ifdef WIELD_SINGLE
    if(inv->test_flag(F_WIELDED))
      do_wield(inv);
#else
    if( inv->query_wielding() && sizeof(inv->query_wielding()) )
       this_object()->wield(inv, inv->query_wielding()[0]);
#endif
    if(inv->test_flag(F_WORN))
      inv->do_wear();
  }
  update_container(this_object());
  reinstate_effects();
}

/* initialize various internal things */
//### needs a new name
private nomask void init_cmd_hook()
{
    link = previous_object();
    naming_init_ids();

#ifdef USE_MASS
    set_mass(100);
#endif
#ifdef USE_SIZE
    set_size(VERY_LARGE);
#endif
    set_max_capacity(VERY_LARGE);

    if (saved_items) {
	string e;

	if (e = catch(load_from_string(saved_items, 1))) {
	    mapping tmp = restore_variable(saved_items);

	    if (tmp["#base_name#"] != base_name(this_object())) {
		update_for_new_body(tmp);
		tmp["#base_name#"] = base_name(this_object());
		load_from_string(save_variable(tmp), 1);
	    } else
		error("Rethrown: " + e);
	}
	saved_items = 0;
    }
  init_stuff();
}

nomask void su_enter_game(object where)
{
    init_cmd_hook();
    move(where);
}

void enter_game(int state)
{
    switch (state) {
    case 1:

	/* FALLTHROUGH */   
    case 0:
	/* existing user */
	init_cmd_hook();
	CHANNEL_D->deliver_emote("announce", query_name(),
	  sprintf("enters %s.", mud_name()));
	/* move the body.  make sure this comes before the simple_action */
	if ( !move_to_start() ) {
	    write("Uh-oh, you have no environment.\n");
	} else {
	    /* we don't want other people to get the extra newlines */
	    write("\n");
	    if(is_visible())
		simple_action("$N $venter "+mud_name()+".");
	    write("\n");
	}
	/* FALLTHROUGH */
    case 2:
	do_game_command("look");
	update_health();
    }
}

//:FUNCTION save_me
//Saves us :-)
void save_me()
{
    object shell_ob = link && link->query_shell_ob();
    string userid = query_userid();

    /* save the shell information */
    if ( shell_ob )
	shell_ob->save_me();

    //### This check is bogus.  What should it be?
    // This check also doesn't work for su's -- John
    //    if (previous_object()==this_object())
    saved_items = save_to_string(1); // 1 meaning it is recursive.

    unguarded( 1, (: save_object , USER_PATH(userid) :) );
    saved_items = 0;
}

//:FUNCTION remove
//Handle mailboxes and the last login daemon, as well as the normal stuff
void remove()
{
    object ob;

    if ( !clonep() )
    {
	::remove();
	return;
    }

#ifdef PLAYERS_START_WHERE_THEY_QUIT
    if (environment() && !wizardp(link))
	set_start_location(file_name(environment()));
#endif

    save_me();

    LAST_LOGIN_D->register_last(query_userid());
    SNOOP_D->bye();
    ::remove();
}

//### This should be protected.
//:FUNCTION quit
//Quit the game.
void quit()
{
    if ( !clonep() )
    {
	::remove();
	return;
    }

    if (is_visible())
	simple_action("$N $vhave left "+mud_name()+".");

    CHANNEL_D->deliver_emote("announce", query_name(),
      sprintf("has left %s.", mud_name()));


    remove();
}

void do_receive(string msg, int msg_type) {
    if ( link )
	link->do_receive(msg, msg_type);
}


//:FUNCTION net_dead
//This function is called when we lose our link
void net_dead()
{
    //### add security here?

    if ( is_visible() )
	simple_action("$N $vhave gone link-dead.");

    CHANNEL_D->deliver_emote("announce", query_name(),
      sprintf("has gone link-dead.", mud_name()));
    SNOOP_D->bye(this_object());
}

//:FUNCTION reconnect
//This function is called when we get our link back
void reconnect(object new_link)
{
    //### add security here?

    link = new_link;
    if(is_visible())
	simple_action("$N $vhave reconnected.");

    CHANNEL_D->deliver_emote("announce", query_name(),
      sprintf("has reconnected.", mud_name()));
}

protected void die()
{
    if ( wizardp(link) )
    {
	if(is_visible())
	    simple_action("If $n $vwere mortal, $n would now no longer be mortal.");
        stop_fight();
        call_out((: reincarnate :), 1);
	heal_all();
	return;
    }

    stop_fight();
    if(is_visible())
	simple_action("$N $vhave kicked the bucket, and $vare now pushing up the daisies.");
    receive_private_msg("\n\n   ****  You have died  ****\n\n"
      "A pity, really.  Way too many people dying these days for me to just patch\n"
      "everyone up.  Oh well, you'll live.\n",0,0);
    rack_up_a_death();
    drop_corpse();

#ifdef DEATH_MESSAGES
    {
	// another option is to choose the message here based on player level
	// or something, instead of just letting action() pick at random.
	// something like: 
	//  action(({ this_object()}),
	//     (MESSAGES_D->get_messages("player_death"))[query_level()/5])[1];
	string msg = action(({this_object()}), 
	  MESSAGES_D->get_messages("player-death"))[1];
	tell( bodies() - ({ this_body() }), msg );
    }
#endif
}

int clean_up() {
    return NEVER_AGAIN;
}

//:FUNCTION id
//id(s) returns 1 if we respond to the name 's'
int id(string arg)
{
    if(!is_visible() && arg == lower_case(query_invis_name()))
	return 1;

    return ::id(arg);
}

string stat_me()
{
    string result = short() + "\n" +
    "Userid: " + query_userid() + "\n" +
    ::stat_me();

    if ( link )
	result += link->stat_me();

    return result;
}

void create(string userid)
{
    if ( !clonep() )
	return;

    if ( base_name(previous_object()) != USER_OB )
	error("security violation: illegal attempt to change name\n");

    messages = ([]);

    adversary::create();

    /*
    ** Make some of the flags non-persistent (they won't be saved).
    */
    configure_set(PLAYER_NP_FLAGS, 1);

    set_long( (: our_description :) );
    set_name(userid);

    unguarded(1, (: restore_object, USER_PATH(userid), 1 :));

    // up to the player
    set_attack_speed(0);
}

//### temp hack. be both user and body
nomask object query_body()
{
    return this_object();
}


/* verb interaction */
mixed indirect_give_obj_to_liv(object ob, object liv) {
    if( previous_object() == liv && ob->is_in( liv )) 
	return "You already have that.";
    return 1;
}

string inventory_header()
{
    return query_name() + " is carrying:\n";
}

int ob_state() 
{
    return -1;
}


void force_look(int force_long_desc)
{
    environment(this_object())->do_looking(force_long_desc, this_object());
}

// Called when our environment destructs.  If we don't move, we get dested too.
void move_or_destruct(object suggested_dest) {
    mixed err;
    object dested_env = environment();
    mixed destination;
    
    if ( !query_link() )
	return;
    
    // Might want to add another failsafe room on the end of this list
    // that doesn't inherit room.c and is guaranteed to load/accept people.
    foreach (destination in ({ suggested_dest, VOID_ROOM, this_body()->query_start_location(), START, WIZARD_START  })) {
	err = catch {
	    if (stringp(destination))
		destination = load_object(destination);
	    if (destination != dested_env) {
		err = move(destination);
		if (stringp(err))
		    throw(err);
	    } else
		throw("Being destructed.\n");
	};
	if (destination && !err) {
	    receive_private_msg(dested_env->short() + " being destructed: You have been moved to " + destination->short() + ".\n");
	    return;
	} else {
	    if (destination)
		receive_private_msg("Cannot move to " + destination->short() + ": " + err);
	}
    }
    receive_private_msg("Uh oh..., couldn't move you anywhere.  Goodbye.\n");
    (this_object()->query_link())->remove();
}


string living_query_name() {
    return ::query_name();
}

string query_name()
{
    return naming::adjust_name(::query_name());
}

/*
** These are overrides from our ancestor (MONSTER)
*/
string short() { return query_name(); }
string a_short() { return query_name(); }
string the_short() { return query_name(); }
string in_room_desc() { return base_in_room_desc() + query_idle_string(); }

/* end of naming overrides */

int allow(string what)
{
    if ( this_body() == this_object() )
    {
	return 1;
    }
    return 0;
}