/*
....[@@@..[@@@..............[@.................. MUD++ is a written from
....[@..[@..[@..[@..[@..[@@@@@....[@......[@.... scratch multi-user swords and
....[@..[@..[@..[@..[@..[@..[@..[@@@@@..[@@@@@.. sorcery game written in C++.
....[@......[@..[@..[@..[@..[@....[@......[@.... This server is an ongoing
....[@......[@..[@@@@@..[@@@@@.................. development project.  All 
................................................ contributions are welcome. 
....Copyright(C).1995.Melvin.Smith.............. Enjoy. 
------------------------------------------------------------------------------
Melvin Smith (aka Fusion)         msmith@falcon.mercer.peachnet.edu 
MUD++ development mailing list    mudpp-list@spice.com
------------------------------------------------------------------------------
pc_act.cc
*/

#include "string.h"
#include "llist.h"
#include "indexable.h"
#include "server.h"
#include "room.h"
#include "bit.h"
#include "spell.h"
#include "pc.h"

#include "global.h"

void PC::do_cast( String & arg )
{
	char targetbuf[ 256 ];

// Kludge until String is completely integrated
//	const Spell * spell = lookupSpell( arg, targetbuf );
	const Spell * spell = lookupSpell( arg.chars(), targetbuf );

	if( !spell )
	{
		out( "You know of no such spell.\n\r" );
		return;
	}

	out( "You utter some mystical words.\n\r" );
	spell->cast( this, this );
}


void PC::do_open( String & arg )
{
	Exit * door;
	int dir;

	if( !arg )
	{
		out( "Open what?\n\r" );
		return;
	}

	dir = getDir( arg[0] );
	if( dir == DIR_UNDEFINED )
	{
		out( "Nothing to open in that direction.\n\r" );
		return;
	}

	door = in_room->getExit( dir );
	if( !door )
		return;
	else if( door->isOpen() )
	{
		out( "It's already open.\n\r" );
		return;
	}

	open( door );
	out( "You open the door.\n\r" );
}


void PC::do_close( String & arg )
{
	Exit * door;
	int dir;

	if( !arg )
	{
		out( "Close what?\n\r" );
		return;
	}

	dir = getDir( arg[0] );
	if( dir == DIR_UNDEFINED )
	{
		out( "Nothing to close in that direction.\n\r" );
		return;
	}

	door = in_room->getExit( dir );
	if( !door )
		return;
	else if( door->isClosed() )
	{
		out( "It's already closed.\n\r" );
		return;
	}

	close( door );
	out( "You close the door.\n\r" );
}


void PC::do_quaff( String & arg )
{
//	Char::quaff( arg );
// Another String kludge
	Char::quaff( arg.chars() );
	return;

	if( !arg )
	{
		out( "Quaff what?\n\r" );
		return;
	}

	Object *obj = getObjInv( arg.chars() );
	if( !obj )
	{
		out( "You don't have that.\n\r" );
		return;
	}

	if( !obj->isPotion() )
	{
		out( "That is not a potion.\n\r" );
		return;
	}

	out( "You work the seal off " );
	out( obj->getShort() );
	out( "\n\rYou quaff " );
	out( obj->getShort() );
	out( "\n\r" );

	obj->cast( this );
	
	rmObjInv( obj );
	obj->fromWorld();
	delete obj;
}


void PC::do_drop( String & arg )
{
	String str;
	Object *obj;
	String arg1;
	String arg2;
	int num = -1;

	arg.startArgs();

	arg1	= arg.getArg();
	arg2	= arg.getArg();

	if( arg1.isNumber() )
	{
		if( !arg2 )
		{
			out( "Drop what?\n\r" );
			return;
		}

		num = arg1.asInt();
	}

	if( num > 1 )
	{
		if( !arg2 )
		{
			out( "Drop what?\n\r" );
			return;
		}

		if( arg2 == "coins" || arg2 == "gold" )
		{
			if( gold <= 0 )
			{
				out( "Forget it, you are broke!\n\r" );
				return;
			}

			if( gold < num )
			{
				out( "Very generous of you, but you aren't that wealthy.\n\r" );
				return;
			}

			gold -= num;

			obj = new Object(	ITEM_GOLD,
								"gold pieces coins", "a pile of gold",
								"a pile of gold is here."	);

			obj->setCost( num );
			out( "You drop some gold.\n\r" );
			str << shortdesc << " drops some gold pieces.\n\r";
			in_room->outAllCharExcept( str, this, 0 );
			obj->toWorld();
			in_room->addObjInv( obj );
			return;
		}
	}

	if( num == 1 )
	{
		if( arg2 == "coin" || arg2 == "gold" )
		{
			if( gold <= 0 )
			{
				out( "Forget it, you are broke!\n\r" );
				return;
			}

			obj = new Object(	ITEM_GOLD,
								"gold piece coin",
								"a gold piece",
								"a gold piece lies here in the dust."	);

			obj->setCost( 1 );
			obj->toWorld();
			in_room->addObjInv( obj );
			out( "You drop a piece of gold.\n\r" );
			str << shortdesc << " drops a piece of gold.\n\r";
			in_room->outAllCharExcept( str, this, 0 );
			gold--;
			return;
		}
		else
			arg1 = arg2;
	}

	obj = getObjInv( arg1 );

	if( obj )
	{
		drop( obj );
		str << "\n\rYou drop " << obj->getShort() << ".\n\r";
		out( str );
		str.clr();
		str << "\n\r" << name << " drops " << obj->getShort() << ".\n\r";
		in_room->outAllCharExcept( str, this, 0 );
		return;
	}

	out( "You don't have that.\n\r" ); 
}


void PC::do_get( String & arg )
{
	String str;
	Object *obj;
	Object *container = 0;
	String arg1;
	String arg2;
	int num = -1;

	arg.startArgs();

	arg1 = arg.getArg();

	if( arg1 == "all" )
	{
	}

	if( arg1.isNumber() )
		num = arg1.asInt();

	// Add plural case
	//

	if( ( obj = in_room->getObj( arg1 ) ) )
	{
		if( obj->isGold() )
		{
			str << "You get " << obj->getValue() << " pieces of gold.\n\r";
			out( str );
			str.clr();
			str << "\n\r" << shortdesc << " gets " << obj->getShort() << ".\n\r";
			in_room->outAllCharExcept( str, this, 0 );
			gold += obj->getValue();
			obj->extract();
			delete obj;
			return;
		}
		else
			get( obj );

		str << "\n\rYou get " << obj->getShort() << ".\n\r";
 
		out( str );

		str.clr();
		str << "\n\r" << name << " gets " << obj->getShort() << ".\n\r";
 
		in_room->outAllCharExcept( str, this, 0 );
		return;
	}

	out( "You see no " ); 
	out( arg1 );
	out( " here.\n\r" );
}



void PC::do_put( String & arg )
{
	String arg1;
	String arg2;
	Object * obj;
	Object * container;

	arg.startArgs();

	arg1 = arg.getArg();
	arg2 = arg.getArg();

	if( !arg1 )
	{
		out( "Eh?\n\r" );
		return;
	}

	obj = getObjInv( arg1 );
	if( !obj )
	{
		out( "You don't have that.\n\r" );
		return;
	}

	if( !arg2 )
	{
		out( "Put it in what?\n\r" );
		return;
	}

	rmObjInv( obj );
	container = getObjInv( arg2 );
	addObjInv( obj );

	if( !container )
		container = in_room->getObj( arg2 );

	if( !container )
	{
		out( "Don't see that container.\n\r" );
		return;
	}

	out( "You put " );
	out( obj->getShort() );
	out( " in " );
	out( container->getShort() );
	out( "\n\r" );
	
	put( obj, container );	
}


void PC::do_up( String & )
{
	if( in_room->getExit( DIR_UP ) )
	{
		if( moveDir( DIR_UP ) )
			do_look( "" ); 
	}
	else
		out("You can't go that way.\n\r"); 
}


void PC::do_down( String & )
{
	if( in_room->getExit( DIR_DOWN ) )
	{
		if( moveDir( DIR_DOWN ) )
			do_look( "" ); 
	}
	else
		out("You can't go that way.\n\r"); 
}


void PC::do_north( String & )
{
	if( in_room->getExit( DIR_NORTH ) )
	{
		if( moveDir( DIR_NORTH ) )
			do_look( "" ); 
	}
	else
		out("You can't go that way.\n\r"); 
}


void PC::do_south( String & )
{
	if( in_room->getExit( DIR_SOUTH ) )
	{
		if( moveDir( DIR_SOUTH ) )
			do_look( "" ); 
	}
	else
		out("You can't go that way.\n\r"); 
}


void PC::do_east( String & )
{
	if( in_room->getExit( DIR_EAST ) )
	{
		if( moveDir( DIR_EAST ) )
			do_look( "" );
	}
	else
		out("You can't go that way.\n\r"); 
}


void PC::do_west( String & )
{
	if( in_room->getExit( DIR_WEST ) )
	{
		if( moveDir( DIR_WEST ) )
			do_look( "" ); 
	}
	else
		out("You can't go that way.\n\r"); 
}



void PC::do_wear( String & arg )
{
	if( !arg )
	{
		out( "\n\rWhat do you want to wear?\n\r" );
		return;
	}

	Object *obj = getObjInv( arg );
	if( !obj )
	{
		out( "\n\rYou dont have that.\n\r" );
		return;
	} 

	if( !obj->isWearable() )
	{
		out( "\n\rYou can't wear that.\n\r" );
		return;
	}

	int wear_pos = 1;
	while( wear_pos <= EQ_MAX ) 
	{
		if( canWear( obj, wear_pos ) )
		{ 
			if( IS_SET( eq_bits, wear_pos ) )
			{
				out( "\n\rYou already wear something there.\n\r" );
			}
			else
			{
				wear( obj, wear_pos );
				out( "Ok.\n\r" );
				return;
			}
		}

		wear_pos++; 
	}
}


void PC::do_remove( String & arg )
{
	if( !arg )
	{
		out( "\n\rWhat do you want to remove?\n\r" );
		return;
	}

	Object *obj = getObjWear( arg );

	if( !obj )
	{
		out( "\n\rYou aren't wearing that.\n\r" );
		return;
	}

	out( "\n\rOk.\n\r" );
	remove( obj );
}


void PC::do_hide( String & )
{
	out( "Feature not implemented yet. --Fusion\n\r" );
}

void PC::do_sneak( String & )
{
	out( "Feature not implemented yet. --Fusion\n\r" );
}

void PC::do_study( String & )
{
	out( "Feature not implemented yet. --Fusion\n\r" );
}

void PC::do_practice( String & )
{
	out( "Feature not implemented yet. --Fusion\n\r" );
}