mud++0.35/etc/
mud++0.35/etc/guilds/
mud++0.35/help/propert/
mud++0.35/mudC/
mud++0.35/player/
mud++0.35/src/interface/
mud++0.35/src/os/cygwin32/
mud++0.35/src/os/win32/
mud++0.35/src/os/win32/bcppbuilder/
mud++0.35/src/osaddon/
mud++0.35/src/util/
/*
....[@@@..[@@@..............[@.................. 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@hom.net 
MUD++ development mailing list    mudpp@van.ml.org
------------------------------------------------------------------------------
shop.cc
*/

#include "config.h"
#include "string.h"
#include "llist.h"
#include "object.h"
#include "shop.h"

#include "global.h"

LList<ShopKeeper> shops;

int ShopKeeper::readFrom_shopblock( StaticInput & in )
{
	char buf[BUF];
	String str;
	ShopTrade * st;
	Object * obj;

	in.getword( buf );
	if( strcmp( buf, "SHOP" ) )
	{
		Cout << "shopkeeper " << getShort() << " has no shop data.\n";
		return 0;
	}

	// Rewrite to allow ommision of certain parameters
	// I'm getting lazy! -Fusion

	in.getword( buf );	// '{'
	in.getword( buf );	shop = in.getword( buf );	// room index of shop
	in.getword( buf );	warehouse = in.getword( buf );	// room index of warehouse
	in.getword( buf );	shop_open = in.getnum();
	in.getword( buf );	shop_close = in.getnum();

	while( *in.getword( buf ) != '}' )
	{

		if ( !strcmp( buf, "Trade" ) )
		{
			in.getword(buf);	// {
			st = new ShopTrade( lookupObjType(in.getword(buf)),
			in.getnum(),in.getnum(), in.getnum(),in.getnum() );
			tradeList.reset();
			tradeList.add(st);
			in.getword(buf);	// }
		}
		else if ( !strcmp( buf, "Owners" ) )
		{
			owners = in.getstring(buf);
		}
		else if ( !strcmp( buf, "O" ) )
		{
			obj = Object::createObject(lookupObjType(in.getword(buf) ));
			obj->readFrom(in);
			addObjInv(obj);
		}
		else
			in.error("Unsupported data in SHOP block");

	}

	return 1;
}


int ShopKeeper::readFrom( StaticInput &in )
{
	char buf[ BUF ];
	if( *in.getword( buf ) != '{' )
		in.error("NPC::readFrom() - expected '{'" );

	readFrom_mainblock(in);
	readFrom_shopblock(in);
	if ( !readFrom_optionalblock(in) )
		in.error("NPC::readFrom() - expected '}'" );
	return 0;
}


void ShopKeeper::writeTo_shopblock( Output & outf ) const
{
	outf << "SHOP\n{" << endl;
	outf << "room " << shop << endl;
	outf << "warehouse " << warehouse << endl;
	outf << "open " << shop_open << endl;
	outf << "close " << shop_close << endl;
//	outf << "buy " << buy_profit << endl;
//	outf << "sell " << sell_profit << endl;

	ShopTrade * st;
	Object * obj;

	// Write trade types
	if ( (bool)owners )
	{
		outf << "Owners " << owners << "~" <<endl;
	}

	for_each(tradeList, st)
	{
		outf << "Trade{ " << lookupObjTypeName(st->getType()) << " " << 
		st->getBuyProfit() << 	" " << st->getSellProfit() << " " << 
		st->getMaxIdentical() << " " << st->getMaxType() << " }\n";
	}

	for_each(inv, obj )
	{
		outf << "O ";
		outf << obj->typeName() << endl;
		obj->writeTo(outf);
		outf << endl;
	}

	outf << '}' << endl;
}

int ShopKeeper::writeTo( Output & outf ) const
{
	outf << '{' << endl;
	
	writeTo_mainblock(outf);
	writeTo_shopblock(outf);
	writeTo_optionalblock(outf);
	outf << '}' << endl;
	return 1;
}


bool ShopKeeper::isTrading(int type )
{
	ShopTrade * st;

	for_each(tradeList, st)
		if ( st->getType() == type )
			return true;
	return false;
}

// How much he give for object
int ShopKeeper::buyValue(Object * obj)
{
	ShopTrade * st;
	int cost;
	Object * objMatch;
	int matchCount;
	int typeMatchCount;

	for_each(tradeList, st )
	{
		if ( obj->isType(st->getType()) )
		{

			cost = (obj->getCost() * st->getBuyProfit()) / 100;

			// Little fuzzy here, just comparing short desc
			// Since MUD++ doesn't use index/prototype pointers we don't match
			// objects exactly so there can be similar or identical objects
			// with different values or stats. The Implementor must handle
			// this and that's the way I like it. Would be nice to implement
			// a little supply/demand code but I'll save that for later. --Fusion

			matchCount = 0;
			typeMatchCount = 0;
			for_each( inv, objMatch )
			{
				if( objMatch->getShort() == obj->getShort() )
					matchCount++;	
//				if ( objMatch->getType() == obj->getType() )
//					typeMatchCount++;
			}

			if( matchCount && (matchCount > st->getMaxIdentical() ) )
			{
				return SHOPKEEPER_HAS_IDENTICAL;
			}

			if( typeMatchCount && (typeMatchCount > st->getMaxType() ) )
			{
				return SHOPKEEPER_HAS_TYPE;
			}

			// If keeper has 1 or more lower the offered value
			if( matchCount )
				cost /= ( matchCount + 1 );
			
			return cost;
		}
	}

	return SHOPKEEPER_NOT_TRADING;

}

// how much he demands for object
int ShopKeeper::sellValue(Object * obj)
{
	ShopTrade * st;
	for_each(tradeList, st )
	{
		if ( obj->isType(st->getType()) )
		{
			return ( (obj->getCost() * st->getSellProfit()) /100 );
		}
	}

	return SHOPKEEPER_NOT_TRADING;
}

bool ShopKeeper::isOwnedBy( Char * person)
{
	if ( strstr(owners.chars(), person->getName().chars() ) )
	return true;

	return false;
}

void ShopKeeper::addOwner( String & nomine )
{
	if ( strstr(owners.chars(), nomine.chars() ) )
		return;
	owners << " " << nomine;
}

void ShopKeeper::removeOwner( String & nomine )
{
	String arg;
	String new_owners;
	owners.startArgs();
	while ( (bool)(arg = owners.getArg() ) )
	{
		if ( arg != nomine )
			new_owners << arg << " ";
	}
}