/
LIB3/
LIB3/D/ADMIN/
LIB3/D/ADMIN/OBJ/
LIB3/D/ADMIN/ROOM/W/
LIB3/D/HOME/
LIB3/D/HOME/CITY/ARENA/
LIB3/D/HOME/CITY/ITEMS/
LIB3/D/HOME/CITY/POSTOFFI/
LIB3/DOC/
LIB3/GLOBAL/SPECIAL/
LIB3/GLOBAL/VIRTUAL/
LIB3/NET/
LIB3/NET/CONFIG/
LIB3/NET/DAEMON/CHARS/
LIB3/NET/GOPHER/
LIB3/NET/INHERIT/
LIB3/NET/OBJ/
LIB3/NET/SAVE/
LIB3/NET/VIRTUAL/
LIB3/OBJ/B_DAY/
LIB3/OBJ/HANDLERS/TERM_TYP/
LIB3/PLAYERS/B/
LIB3/PLAYERS/N/
LIB3/ROOM/
LIB3/SAVE/
LIB3/SAVE/BOARDS/
LIB3/SAVE/ENVIRON/
LIB3/SAVE/POST/
LIB3/STD/COMMANDS/SHADOWS/
LIB3/STD/CREATOR/
LIB3/STD/DOM/
LIB3/STD/EFFECTS/
LIB3/STD/EFFECTS/HEALING/
LIB3/STD/EFFECTS/OTHER/
LIB3/STD/EFFECTS/POISONS/
LIB3/STD/ENVIRON/
LIB3/STD/GUILDS/
LIB3/STD/LIQUIDS/
LIB3/STD/ROOM/
LIB3/STD/TRIGGER/SHADOW/
LIB3/W/
LIB3/W/BANNOR/
LIB3/W/NEWSTYLE/
/*
   ** Optimised, Newstyle, 08/12/93
 */

#include "player.h"

inherit "global/alias";
inherit "/global/nickname";

#define SOUL_OBJECT "/obj/handlers/soul"
#undef SOUL_ERROR_CHECK

static int time_left, *queue_depth, doing_it, last_command;
static string *queued_commands, *in_command;
static mixed *interupt;

void    create()
{
    time_left = ROUND_TIME;
    queued_commands = in_command = ({ });
    queue_depth = ({ 0 });
}

void    no_time_left()
{
    time_left = -ROUND_TIME;
}

void    soul_commands()
{
    add_action( "nosoul", "nosoul", 1 );
    add_action( "soul_com", "*", -1 );
    add_action( "lower_check", "*", -10000 );
    add_action( "drunk_check", "*", 10000 );
    add_action( "soul_force_thingy", "SOUL_FORCE", 20000 );
    alias_commands();
    nickname_commands();
    history_commands();
}

int     nosoul( string str )
{
    if( str == "on" )
	this_object()->add_property( "nosoul", 1 );
    else
	if( str == "off" )
	    this_object()->remove_property( "nosoul" );
	else
	    if( this_object()->query_property( "nosoul" ) )
		this_object()->remove_property( "nosoul" );
	    else
		this_object()->add_property( "nosoul", 1 );
    if( this_object()->query_property( "nosoul" ) )
	write( "Soul turned off.\n" );
    else
	write( "Soul turned on.\n" );
    return 1;
}

#ifdef SOUL_ERROR_CHECK
int     soul_error_check()
{
    if( !find_object( SOUL_OBJECT ) )
	if( catch( call_other( SOUL_OBJECT, "??" ) ) )
	{
	    write( "Soul errors!  Notify a wiz at once.\n" +
		   "Use nosoul to turn the soul back on when it is fixed.\n" );
	    this_object()->add_property( "nosoul", 1 );
	    return 1;
	}
    return 0;
}
#endif

int     soul_force_thingy( string str )
{
    string  str2;

    sscanf( str, "%s %s", str, str2 );
    if( !this_object()->query_property( "nosoul" ) )
    {

#ifdef SOUL_ERROR_CHECK
	if( soul_error_check() )
	    return 0;
#endif

	SOUL_OBJECT->soul_command( str, str2 );
    }
    return 1;
}

int     do_soul_force( string str )
{
    return command( "SOUL_FORCE " + str );
}

int     soul_com( string str )
{
    string  str2;

    sscanf( str, "%s %s", str, str2 );
    if( exec_alias( str, str2 ) )
	return 2;
    if( !this_object()->query_property( "nosoul" ) )
    {

#ifdef SOUL_ERROR_CHECK
	if( soul_error_check() )
	    return 0;
#endif

	if( SOUL_OBJECT->soul_command( str, str2 ) )
	    return 1;
    }
    return 0;
}

int     soul_com_force( string str )
{
    if( file_name( previous_object() ) != SOUL_OBJECT )
	return 0;
    command( str );
    return 1;
}

void    do_soul( string str, mixed bing )
{
    say( str, bing );
}
int     query_time_left()
{
    return time_left;
}
int     adjust_time_left( int i )
{
    return time_left += i;
}

void    do_flush( int first )
{
    int     i, *temp_qd;
    string  com, *temp_ic;

    if( time_left < 0 || !sizeof( queued_commands ) )
	return;
    if( !first )
    {
	temp_ic = in_command;
	temp_qd = queue_depth;
	com = queued_commands[ 0 ];

/* Would delete be quicker here? */
	queued_commands = queued_commands[ 1..1000 ];
	queue_depth = ({ 0 });
	in_command = ({ });
	doing_it = 1;
	command( com );
	doing_it = 0;
	in_command = temp_ic;
	queue_depth = temp_qd;
	return;
    }
/* Does this \/ prevent more than 2 commands firing per round? */
    for( i = 0; i < 2 && i < sizeof( queued_commands ); i++ )
	call_out( "do_flush", 0, 0 );
    call_out( "do_flush", 1, 1 );
}

/* Called each heart_beat */
static void flush_queue()
{
    if( time_left < 0 )
	time_left += ROUND_TIME;
    else
	time_left = ROUND_TIME;
    remove_call_out( "do_flush" );
    do_flush( 1 );
    if( !sizeof( queued_commands ) )
    {
	if( interupt && time_left > 0 )
	{
	    call_other( interupt[ 1 ], interupt[ 0 ], 0, interupt[ 2 ] );
	    interupt = 0;
	}
	doing_alias = ([ ]);
	in_alias_command = 0;
	in_command = ({ });
	queue_depth = ({ 0 });
    }
}

void    set_interupt_command( string func, mixed ob, mixed arg )
{
    interupt = ({ func, ob, arg });
}

int     drunk_check( string str )
{
    last_command = time();
    if( sizeof( in_command ) && in_command[ 0 ] == str )
	return 0;
    if( this_object()->query_property( PASSED_OUT_PROP ) )
    {
	if( str == "quit" )
	    return 0;
	write( "You have passed out, you cant do anything.\n" );
	return 1;
    }
    if( str == "stop" || str == "restart" )
    {
	queued_commands = ({ });
	if( interupt && time_left < 0 )
	    call_other( interupt[ 1 ], interupt[ 0 ], -time_left, interupt[ 2 ] );
	write( "Removed queue.\n" );
	time_left = 0;
	return 0;
    }
    if( time_left < 0 || (!doing_it && sizeof( queued_commands )) )
    {
	if( str[ 0..8 ] != "END_ALIAS" )
        {
            str = replace( str, "@@", "@ @ " );
	    write( "Queued command " + str + ".\n" );
        }
	if( str == "quit" )
	{
	    write( "If you are trying to quit and it is queueing things, use " +
		   "'stop' to stop your commands, and or restart to start " +
		   "your heartbeat.\n" );
	}
/* Is there not a nice insert function? */
	queued_commands = queued_commands[ 0..queue_depth[ 0 ] - 1 ] + ({ str }) +
	    queued_commands[ queue_depth[ 0 ]..255 ];
	queue_depth[ 0 ]++;
	return 1;
    }
    if( interupt )
    {
	call_other( interupt[ 1 ], interupt[ 0 ], 0, interupt[ 2 ] );
	interupt = 0;
    }
    time_left -= DEFAULT_TIME;
    str = replace( str, "@@", "@ @ " );
    add_history( str );
    in_command = ({ str }) +in_command;
    if( !sizeof( queue_depth ) )
	queue_depth = ({ 0, 0 });
    else
	queue_depth = ({ queue_depth[ 0 ] }) +queue_depth;
    command( str );
    in_command = in_command[ 1..1000 ];
    queue_depth[ 1 ] = queue_depth[ 0 ];
    queue_depth = queue_depth[ 1..1000 ];
    if( interupt && time_left >= 0 )
    {
	call_other( interupt[ 1 ], interupt[ 0 ], 0, interupt[ 2 ] );
	interupt = 0;
    }
    return 1;
}

int     lower_check( string str )
{
    time_left += DEFAULT_TIME;
    return( str == "stop" );
}