/*
....[@@@..[@@@..............[@.................. 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
------------------------------------------------------------------------------
char.h
*/

#ifndef _CHAR_H
#define _CHAR_H

#include "thing.h"
#include "streamable.h"
#include "object.h"
#include "combat.h"

const int POS_DEAD		= 0;
const int POS_MORTAL	= 1;
const int POS_STUNNED	= 2;
const int POS_SLEEPING	= 3;
const int POS_RESTING	= 4;
const int POS_SITTING	= POS_RESTING;
const int POS_STANDING	= 5;
const int POS_FLOATING	= 6;
const int POS_FLYING	= 7;
const int POS_SWIMMING	= 8;

// Char base class flags ( common to NPC, PC, etc. )
// Char::char_bits

const int CHAR_UNDEFINED	= 0;
const int CHAR_FROZEN		= 1;
const int CHAR_SNEAKING		= 2;

class Affect;
class Modifier;
class Object;
class Exit;

const int CLASS_WIZARD		= 0;
const int MAX_CHAR_BIT_FIELDS	= 1;
const int MAX_LANG_BIT_FIELDS	= 1;
const int MAX_EQ_BIT_FIELDS	= 1;

class Char : public Thing, public Streamable
{
	protected:
		unsigned long char_bits[ MAX_CHAR_BIT_FIELDS ];
		unsigned long language_bits[ MAX_LANG_BIT_FIELDS ];
		unsigned long eq_bits[ MAX_EQ_BIT_FIELDS ];
		short level;
		short classnow;
		long exp;
		short race;
		long copper;
		long silver;
		long gold;
		short damroll;
		short hitroll;
		short armor;
		short max_hp;
		short hp;
		short max_mana;
		short mana;
		short anger;
		short frustration;
		short adrenaline;
		short strength;
		short intel;
		short wis;
		short charisma;
		short con;
		short dex;
		short speed;
		short position;
		short carried_weight;
		short carried_count;
		short magic_resistance;

		Char * fighting;

	public:
		LList <Affect> affects;
		LList <Attack> attacks;
		LList <Object> inv;
		LList <Object> wearlist;

		Char()
		:	level(1), classnow(4), exp(0), race(0),
			copper(0), silver(0), gold(0),
			damroll(0), hitroll(0), armor(0),
			max_hp(12), hp(12), max_mana(12), mana(12),
			anger(0), frustration(0), adrenaline(0),
			position(POS_STANDING), carried_weight(0), carried_count(0),
			magic_resistance(0),
			fighting(0)
		{
			memset( char_bits, 0,
					sizeof( char_bits[0] ) * MAX_CHAR_BIT_FIELDS );
			memset( language_bits, 0,
					sizeof( language_bits[0] ) * MAX_LANG_BIT_FIELDS );
			memset( eq_bits, 0,
					sizeof( eq_bits[0] ) * MAX_EQ_BIT_FIELDS );
		}

		Char( const Char & x )
		:	Thing( x ), // propagate up the hierarchy
			level( x.level ), classnow( x.classnow ), exp( x.exp ),
			race( x.race ),
			copper( x.copper ), silver( x.silver ), gold( x.gold ),
			damroll( x.damroll ), hitroll( x.hitroll ),
			armor( x.armor ), max_hp( x.max_hp ), hp( x.hp ),
			max_mana( x.max_mana ), mana( x.mana ),
			anger( x.anger ), frustration( x.frustration ),
			adrenaline( x.adrenaline ), position( x.position ),
			carried_weight( x.carried_weight ), carried_count( x.carried_count ),
			fighting( 0 ),
			// for now only copy affects list, never copy inv and wear
			affects( x.affects )
		{
			memcpy( (void *)char_bits, (void *)x.char_bits,
					sizeof( char_bits[0] ) * MAX_CHAR_BIT_FIELDS );
			memcpy( (void *)language_bits, (void *)x.language_bits,
					sizeof( language_bits[0] ) * MAX_LANG_BIT_FIELDS );
			memset( eq_bits, 0,
					sizeof( eq_bits[0] ) * MAX_EQ_BIT_FIELDS );
		}
		
		virtual ~Char();

		//
		// Interface
		// 

		virtual Char * asChar() { return this; }

		virtual void out( const char * ) = 0;
		virtual void out( const String & ) = 0;

		virtual void pulse();

		// convert all actions to return bool on success
		bool open( Exit * );
		bool close( Exit * );

		void wear( Object *, int );
		void equip( Object *, int );
		void wield( Object *, int );	 // int param for left/right
		void remove( Object * );
		int canWear( Object *, int );
		void addObjInv( Object * obj );
		virtual Object * getObjInv( const String & );
		virtual Object * getSecondObjInv( const String & );
		virtual void rmObjInv( Object * );
		Object * getObjWear( const String & );
		Object * getObjWear( int pos );
		virtual void addAffect( Affect * );
		virtual void rmAffect( int );
		virtual void modify( Modifier *, bool );
		virtual void addAttack();
		virtual void rmAttack();
		bool isFighting() const { return (bool)fighting; }
		Char * getFighting() const { return fighting; }
		void setFighting( Char * x ) { fighting = x; }
		void stopFighting() { fighting = 0; }
		void attack( Char *, int );
		int hit( Char *, Attack * );
		int damage( int, int );
		void damMessg( Char *, int, int ); // Preliminary only
		void cast( const Spell *, Thing * );
		virtual int gainExp( int );
		virtual int getExp() const { return exp; }
		void setMaxHp( int x ) { max_hp = x; }
		void setHp( int x ) { hp = x; }
		int getMaxHp() const { return max_hp; }
		int getHp() const { return hp; }
		int getMaxMana() const { return max_mana; }
		int getMana() const { return mana; }
		virtual int getLevel() const { return level; }
		virtual int getStr() const;
		virtual int getInt() const;
		virtual int getWis() const;
		virtual int getDex() const;
		virtual int getCon() const;
		int getSpd() const;
		int getCopper() const { return copper; }
		void setCopper( int coins ) { copper = coins; }
		int getSilver() const { return silver; }
		void setSilver( int coins ) { silver = coins; }
		int getGold() const { return gold; }
		void setGold( int coins ) { gold = coins; }
		int getArmor() const { return armor; }
		int getDamRoll() const { return damroll; }
		int getHitRoll() const { return hitroll; }
		int getCarriedWeight() const { return carried_weight; }
		int getCarriedCount() const { return carried_count; }

		virtual void look( Object * ) = 0;
		virtual void look( Char * ) = 0;
		virtual void get( Object * );
		virtual void drop( Object * );
		virtual void put( Object *, Object * ); 
		virtual void quaff( Object * );
		virtual void quaff( const char * );
		virtual void fromWorld() {}
		virtual void toWorld() {}
		virtual void toRoom( Room * );
		virtual void fromRoom();
		virtual bool moveDir( int dir );
		
		virtual bool isNPC() const { return false; }
		virtual bool isPC() const { return false; }
		virtual bool isShopKeeper() const { return false; }

};
#endif