/*
....[@@@..[@@@..............[@.................. 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 << " ";
}
}