/*
....[@@@..[@@@..............[@.................. 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
------------------------------------------------------------------------------
pc_act.cc
*/
#include "config.h"
#include "string.h"
#include "llist.h"
#include "hash.h"
#include "server.h"
#include "room.h"
#include "bit.h"
#include "spell.h"
#include "pc.h"
#include "mudobj.h"
#include "area.h"
#include "shop.h"
#include "global.h"
void PC::do_cast( const String & arg )
{
String str;
String extra_args;
char targetbuf[ 256 ];
MudObject * target = 0;
targetbuf[0] = 0;
const SpellType * stp = lookupSpell( arg.chars(), targetbuf );
if( !stp )
{
out( "You know of no such incantation.\n\r" );
return;
}
// Didnt specify a target: cast control weather worse, cast sanc
if ( !*targetbuf )
{
// Its a no target spell
if ( IS_SET( &stp->target_bits, TAR_NONE ) )
;
else if ( IS_SET( &stp->target_bits, TAR_SELF ) )
target = this;
else if ( IS_SET( &stp->target_bits, TAR_ROOM ) )
target = in_room;
else if ( IS_SET( &stp->target_bits, TAR_AREA ) )
target = in_room->getArea();
else
{
out( "What do you want to cast this spell on?\n\r" );
return;
}
}
else
{
str = targetbuf;
// If spell takes no target, just set the extra args
// to whatever the command line is (the target_buf is
// stuff after the spell name)
if ( IS_SET( &stp->target_bits, TAR_NONE ) )
{
extra_args = targetbuf;
}
else if ( str == "self" )
{
if ( !IS_SET( &stp->target_bits, TAR_SELF )
&& !IS_SET( &stp->target_bits, TAR_ANY ) )
{
out( "You can't cast this spell on yourself!\n\r" );
return;
}
else
target = this;
}
else if ( str == "room" )
{
if ( !IS_SET( &stp->target_bits, TAR_ROOM )
&& !IS_SET( &stp->target_bits, TAR_ANY ) )
{
out( "You can't cast this spell on the room!\n\r" );
return;
}
else
target = in_room;
}
else if ( str == "area" )
{
if ( !IS_SET( &stp->target_bits, TAR_AREA )
&& !IS_SET( &stp->target_bits, TAR_ANY ) )
{
out( "You can't cast this spell on the area!\n\r" );
return;
}
else
target = in_room->getArea();
}
else
{
// ok str is either an object or a char
target = inRoom()->getChar( str );
if ( target )
{
// its a char
if ( !IS_SET( &stp->target_bits, TAR_CHAR )
&& !IS_SET( &stp->target_bits, TAR_ANY ) )
{
out( "You can't cast this spell on that!\n\r" );
return;
}
if ( target == this
&& !IS_SET( &stp->target_bits, TAR_SELF ) )
{
out( "You can't cast that on yourself!\n\r" );
return;
}
}
else
{
// not a char so its probably an obj
target = inRoom()->getObj( str );
if ( target )
{
if ( !IS_SET( &stp->target_bits, TAR_OBJECT )
&& !IS_SET( &stp->target_bits, TAR_ANY ) )
{
out( "You can't cast this spell on that!\n\r" );
return;
}
}
else
{
// ack its nothing
out( "Your target is not here.\n\r" );
return;
}
}
}
}
out( "You concentrate deeply while uttering each word of the incantation.\n\r" );
// This doesn't cast right away; it launches an action.
cast( stp, target, extra_args );
}
void PC::do_use( const String & arg )
{
Object * obj;
if( ! arg )
{
out( "Use what?\n\r" );
return;
}
if( !( obj = getObjInv( arg ) ) )
{
out( "You don't have that.\n\r" );
return;
}
if( obj->isCompass() )
{
interp( "You pull out $o and look at it.\n\r", 0, 0, obj, 0 );
inRoom()->interp( "$n pulls out $o and looks at it for a moment.\n\r", this, 0, obj, 0 );
if( getOrientation() )
{
out( "You have a better sense of direction now.\n\r" );
inRoom()->interp( "$n turns and looks north.\n\r", this, 0, 0, 0 );
setOrientation(0);
return;
}
out( "The compass points north.\n\r" );
return;
}
// Add other use object types
out( "What do you want to use it for?\n\r" );
}
void PC::do_open( const String & arg )
{
Exit * door;
int dir;
if( !(bool)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( const String & arg )
{
Exit * door;
int dir;
if( !(bool)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( const String & arg )
{
if( !(bool)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() && !obj->isLiquidContainer() )
{
out( "You can't drink that.\n\r" );
return;
}
quaff( obj );
}
void PC::do_eat( const String & arg )
{
String str;
if( !(bool)arg )
{
out( "Eat what?\n\r" );
return;
}
Object *obj = getObjInv( arg.chars() );
if( !obj )
{
out( "You don't have that.\n\r" );
return;
}
if( !obj->isFood() )
{
// Wizards can eat anything
if( authorized( WIZARD ) )
{
rmObjInv( obj );
obj->extract();
str << getShort() << " eats " << obj->getShort() << ".\n\r";
inRoom()->outAllCharExcept( str, this, 0 );
str.clr();
str << "You eat " << obj->getShort() << ".\n\r";
out( str );
obj->fordelete();
return;
}
out( "You can't eat that.\n\r" );
return;
}
eat( obj );
}
void PC::do_drop( const String & arg )
{
String str;
Object *obj;
String arg1;
String arg2;
long num = -1;
arg.startArgs();
arg1 = arg.getArg();
arg2 = arg.getArg();
if( arg1.isNumber() )
{
if( !(bool)arg2 )
{
out( "Drop what?\n\r" );
return;
}
num = arg1.asInt();
}
if( num > 1 )
{
if( !(bool)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 < (unsigned long)num )
{
out( "Very generous of you, but you aren't that wealthy.\n\r" );
return;
}
gold -= num;
obj = new ObjGold();
obj->setName( "gold pieces coins" );
obj->setShort( "a pile of gold" );
obj->setLong( "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 ObjGold();
obj->setName( "gold piece coin" );
obj->setShort( "a gold piece" );
obj->setLong( "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 )
{
if (!drop( obj ))
return;
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( const String & arg )
{
String str;
Object *obj;
Object *container = 0;
String arg1;
String arg2;
int num = -1;
if( !(bool)arg )
{
out( "Get what?\n\r" );
return;
}
arg.startArgs();
arg1 = arg.getArg();
arg2 = arg.getArg();
if( arg1 == "all" )
{
if( !(bool)arg2 )
{
out( "Don't be so greedy.\n\r" );
return;
}
if( arg2 == "in" || arg2 == "from" )
arg2 = arg.getArg();
if( !(bool)arg2 )
{
out( "Get all from what?\n\r" );
return;
}
countedThing cI(arg2);
container = getObjInv( cI );
if ( container == NULL )
{
container = in_room->getObj( cI );
if ( container == NULL )
{
out( "You don't see the " );
out( arg2 + ".\n\r" );
return;
}
}
if( !container->isContainer() && !container->isCorpse() )
{
out( "Nothing there.\n\r" );
return;
}
container->inv.reset();
if( !container->inv.peek() )
{
out( "There is nothing in " );
out( container->getShort() );
out( ".\n\r" );
return;
}
while( ( obj = container->inv.remove() ) )
{
out( "You get " );
out( obj->getShort() );
out( " from " );
out( container->getShort() );
out( ".\n\r" );
addObjInv( obj );
}
return;
}
if( arg1.isNumber() )
num = arg1.asInt();
// Add plural case
//
if( !(bool)arg2 )
{
if( ( obj = in_room->getObj( arg1 ) ) )
{
if( obj->isGold() )
{
str << "You get " << obj->getCost() << " 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->getCost();
obj->extract();
obj->fordelete();
return;
}
else
{
if (!get( obj ))
return;
}
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 don't see the " );
out( arg1 );
out( ".\n\r" );
return;
}
// arg2 passed so get a container in room or inv
countedThing cI(arg2);
container = getObjInv( cI );
if ( container == NULL )
{
container = in_room->getObj( cI );
if ( container == NULL )
{
out( "You don't see the " );
out( arg2 + ".\n\r" );
return;
}
}
if( !container->isContainer() && !container->isCorpse() )
{
out( "Nothing there.\n\r" );
return;
}
if( !( obj = container->getObjInv( arg1 ) ) )
{
out( "It's not in the " );
out( container->getShort() );
out( ".\n\r" );
return;
}
if ( !get(obj, container) )
return;
str << "You get " << obj->getShort() << " from " << container->getShort()
<< ".\n\r";
out( str );
str.clr();
str << getShort() << " gets " << obj->getShort() << " from "
<< container->getShort() << ".\n\r";
inRoom()->outAllCharExcept( str, this, 0 );
}
void PC::do_put( const String & arg )
{
String arg1;
String arg2;
Object * obj;
Object * container;
arg.startArgs();
arg1 = arg.getArg();
arg2 = arg.getArg();
if( !(bool)arg1 )
{
out( "Eh?\n\r" );
return;
}
obj = getObjInv( arg1 );
if( !obj )
{
out( "You don't have that.\n\r" );
return;
}
if( !(bool)arg2 )
{
out( "Put it in what?\n\r" );
return;
}
countedThing cI(arg2);
if ( !(container = getObjInv(cI) ) )
{
if ( !(container = in_room->getObj(cI) ) )
{
out( "Don't see that container.\n\r" );
return;
}
}
if ( container == obj )
{
out( "You cannot put it into itself.\n\r");
return;
}
if ( !put( obj, container ) )
return;
out( "You put " );
out( obj->getShort() );
out( " in " );
out( container->getShort() );
out( ".\n\r" );
}
void PC::do_up( const String & )
{
if( fighting )
{
out( "You are in the middle of battle!\n\r" );
return;
}
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( const String & )
{
if( fighting )
{
out( "You are in the middle of battle!\n\r" );
return;
}
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( const String & )
{
if( fighting )
{
out( "You are in the middle of battle!\n\r" );
return;
}
int dir = ( DIR_NORTH + orientation ) % DIR_UP;
if( in_room->getExit( dir ) )
{
if( moveDir( dir ) )
do_look( "" );
}
else out("You can't go that way.\n\r");
}
void PC::do_south( const String & )
{
if( fighting )
{
out( "You are in the middle of battle!\n\r" );
return;
}
int dir = ( DIR_SOUTH + orientation ) % DIR_UP;
if( in_room->getExit( dir ) )
{
if( moveDir( dir ) )
do_look( "" );
}
else out("You can't go that way.\n\r");
}
void PC::do_east( const String & )
{
if( fighting )
{
out( "You are in the middle of battle!\n\r" );
return;
}
int dir = ( DIR_EAST + orientation ) % DIR_UP;
if( in_room->getExit( dir ) )
{
if( moveDir( dir ) )
do_look( "" );
}
else out("You can't go that way.\n\r");
}
void PC::do_west( const String & )
{
if( fighting )
{
out( "You are in the middle of battle!\n\r" );
return;
}
int dir = ( DIR_WEST + orientation ) % DIR_UP;
if( in_room->getExit( dir ) )
{
if( moveDir( dir ) )
do_look( "" );
}
else out("You can't go that way.\n\r");
}
void PC::do_wear( const String & arg )
{
if( !(bool)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
{
if ( !wear( obj, wear_pos ) )
return;
out( "Ok.\n\r" );
return;
}
}
wear_pos++;
}
}
void PC::do_remove( const String & arg )
{
if( !(bool)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;
}
if ( !remove( obj ) )
return;
out( "\n\rOk.\n\r" );
}
void PC::do_hide( const String & )
{
out( "Feature not implemented yet. --Fusion\n\r" );
}
void PC::do_sneak( const String & )
{
out( "Feature not implemented yet. --Fusion\n\r" );
}
void PC::do_study( const String & )
{
out( "Feature not implemented yet. --Fusion\n\r" );
}
void PC::do_practice( const String & )
{
out( "Feature not implemented yet. --Fusion\n\r" );
}
// Buy/sell code lacks item type discrepancy, alignment, charisma
// etc. but it is functional enough for you to code your own for now.
void PC::do_buy( const String & arg )
{
Object *obj;
String str;
Char *keeper;
int cost;
String arg1;
String arg2;
arg.startArgs();
arg1 = arg.getArg();
arg2 = arg.getArg();
if( !arg1 )
{
out( "Buy what?\n\r" );
return;
}
for_each( inRoom()->chars, keeper )
{
if( keeper->isShopKeeper() && (!arg2 || keeper->isName(arg2) ) )
break;
}
if( !keeper )
{
if ( !arg2 )
out( "There is no shopkeeper here.\n\r" );
else
out( "There is no shopkeeper here with that name.\n\r");
return;
}
if( !( obj = keeper->getObjInv( arg1 ) ) )
{
out( keeper->getShort() );
out( " tells you, \"I don't have that.\"\n\r" );
return;
}
cost = ((ShopKeeper *)keeper)->sellValue(obj);
if ( cost == SHOPKEEPER_NOT_TRADING )
{
out( keeper->getShort() );
out( " tells you, \"I have no such an item.\"\n\r" );
return;
}
if( getGold() < cost )
{
out( keeper->getShort() );
out( " tells you, \"You can't afford it. Go get a job.\"\n\r" );
return;
}
str << getShort() << " buys " << obj->getShort() << ".\n\r";
inRoom()->outAllCharExcept( str, this, keeper );
str.clr();
str << "You give " << keeper->getShort() << " " << cost
<< " gold pieces.\n\r";
str << keeper->getShort() << " gives you "
<< obj->getShort() << ".\n\r";
keeper->rmObjInv( obj );
addObjInv( obj );
keeper->setGold( keeper->getGold() + cost );
setGold( getGold() - cost );
out( str );
}
void PC::do_sell( const String & arg )
{
Object *obj;
String str;
Char *keeper;
int cost;
String arg1;
String arg2;
arg.startArgs();
arg1 = arg.getArg();
arg2 = arg.getArg();
if( !arg1 )
{
out( "Sell what?\n\r" );
return;
}
for_each( inRoom()->chars, keeper )
{
if( keeper->isShopKeeper() && (!arg2 || keeper->isName(arg2) ) )
break;
}
if( !keeper )
{
if ( !arg2 )
out( "There is no shopkeeper here.\n\r" );
else
out( "There is no shopkeeper here with that name.\n\r");
return;
}
if( !( obj = getObjInv( arg1 ) ) )
{
out( keeper->getShort() );
out( " tells you, \"You don't have that.\"\n\r" );
return;
}
cost = ((ShopKeeper *)keeper)->buyValue(obj);
if ( cost == SHOPKEEPER_NOT_TRADING )
{
str << keeper->getShort() << " tells you, \"I'm not interested at all.\"\n\r";
out(str);
return;
}
else if ( cost == SHOPKEEPER_HAS_IDENTICAL )
{
str << keeper->getShort() << " tells you \"I already have a few of those.\"\n\r";
out(str);
return;
}
else if ( cost == SHOPKEEPER_HAS_TYPE )
{
str << keeper->getShort() << " tells you \"I already have a few of this type.\"\n\r";
out(str);
return;
}
if( keeper->getGold() < cost )
{
out( keeper->getShort() );
out( " tells you \"For now I have run out of cold.\"\n\r" );
return;
}
str << getShort() << " sells " << obj->getShort() << ".\n\r";
inRoom()->outAllCharExcept( str, this, keeper );
str.clr();
str << keeper->getShort() << " gives you " << cost
<< " gold pieces.\n\r";
str << "You give " << keeper->getShort() << " "
<< obj->getShort() << ".\n\r";
rmObjInv( obj );
keeper->addObjInv( obj );
setGold( getGold() + cost );
keeper->setGold( keeper->getGold() - cost );
out( str );
}
void PC::do_trade( const String & )
{
}
void PC::do_price( const String & arg )
{
Object *obj;
String str;
Char *keeper;
int cost;
String arg1;
String arg2;
arg.startArgs();
arg1 = arg.getArg();
arg2 = arg.getArg();
if( !arg1 )
{
out( "Price what?\n\r" );
return;
}
for_each( inRoom()->chars, keeper )
{
if( keeper->isShopKeeper() && (!arg2 || keeper->isName(arg2) ) )
break;
}
if( !keeper )
{
if ( !arg2 )
out( "There is no shopkeeper here.\n\r" );
else
out( "There is no shopkeeper here with that name.\n\r");
return;
}
if( !( obj = getObjInv( arg1 ) ) )
{
out( "You don't have that.\n\r" );
return;
}
cost = ((ShopKeeper *)keeper)->buyValue(obj);
if ( cost == SHOPKEEPER_NOT_TRADING )
{
str << keeper->getShort() << " tells you, \"I'm not interested at all.\"\n\r";
}
else if ( cost == SHOPKEEPER_HAS_IDENTICAL )
{
str << keeper->getShort() << " tells you \"I already have a few of those.\"\n\r";
}
else if ( cost == SHOPKEEPER_HAS_TYPE )
{
str << keeper->getShort() << " tells you \"I already have a few of this type.\"\n\r";
}
else
{
str << keeper->getShort() << " tells you, \"I'll give you "
<< cost << " gold pieces for that.\"\n\r";
}
out( str );
if( keeper->getGold() < cost )
{
out( keeper->getShort() );
out( " tells you \"But for now I have run out of cash.\"\n\r" );
}
}
void PC::do_give ( const String & arg )
{
String str;
Object *obj;
Char * ch;
String arg1;
String arg2;
int num = -1;
if( !(bool)arg )
{
out( "Give what?\n\r" );
return;
}
arg.startArgs();
arg1 = arg.getArg();
if( arg1.isNumber() )
{
num = arg1.asInt();
arg1 = arg.getArg();
}
// Add plural case
//
arg2 = arg.getArg();
if ( !(bool)arg2 )
{
out("Give to whom ?\n\r");
return;
}
if( !( ch = in_room->getChar(arg2 ) ) )
{
out("You do not see " );
out(arg2);
out(" here.\n\r");
return;
}
if( !( obj = getObjInv( arg1 ) ) )
{
if ( (arg1 == "gold") || (arg1 == "coins") )
{
if ( num < 0 )
{
out("How many gold pieces do you want to give ?\n\r");
return;
}
if ( (unsigned)num > gold )
{
out("You do not have that much gold.\n\r");
return;
}
if ( ch->TgGivenGold(this, num) )
return;
gold -= num;
ch->setGold( ch->getGold() + num );
// comunicate
str << "You give " << num <<" pieces of gold to "
<< ch->getName() << ".\n\r";
out(str);
str.clr();
str << getName() << " gives some gold to " << ch->getName() << ".\n\r";
inRoom()->outAllCharExcept( str, this, ch );
str.clr();
str << getName() << " gives you " << num << " gold coins.\n\r";
ch->out(str);
return;
}
out("You do not have " );
out( arg1 );
out(" with you.\n\r" );
return;
}
// add checks for some lame non-drop bits
if ( !give( obj, ch ) )
return;
//comunicate
str << "You give " << obj->getName() <<" to "
<< ch->getName() << ".\n\r";
out(str);
str.clr();
str << getName() << " gives " << obj->getName() << " to "
<< ch->getName() << ".\n\r";
inRoom()->outAllCharExcept( str, this, ch );
str.clr();
str << getName() << " gives you " << obj->getName() << ".\n\r";
ch->out(str);
}
void PC::do_collect ( const String & arg )
{
Object *obj;
String str;
Char *keeper;
String arg1;
String arg2;
arg.startArgs();
arg1 = arg.getArg();
arg2 = arg.getArg();
for_each( inRoom()->chars, keeper )
if( keeper->isShopKeeper() && (!arg2 || keeper->isName(arg2) ) )
break;
if( !keeper )
{
if ( !arg2 )
out( "There is no shopkeeper here.\n\r" );
else
out( "There is no shopkeeper here with that name.\n\r");
return;
}
if ( !((ShopKeeper *)keeper)->isOwnedBy(this) )
{
out( keeper->getShort() );
out( "tells you, \"Sorry, I only obey my master\".\n\r");
return;
}
if( !( obj = keeper->getObjInv( arg1 ) ) )
{
out( keeper->getShort() );
out( " tells you, \"I don't have that.\"\n\r" );
return;
}
keeper->give(obj, this);
str << keeper->getShort() << " gives you " << obj->getShort() << ".\n\r";
out(str);
str.clr();
str << keeper->getShort() << " gives " << obj->getShort() << " to "
<< this->getShort() << ".\n\r";
inRoom()->outAllCharExcept(str, this, keeper );
return;
}