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

#ifndef _PC_H
#define _PC_H

#include "bit.h"
#include "socket.h"
#include "server.h"
#include "char.h"
#include "edit.h"


#define PLAYER_DIR		"../player"

extern const bitType	priv_bit_list[];
extern const int		exp_table[];


const int SUPERUSER			= 1;
const int DIRECTOR			= 2;
const int ADMIN				= 3;
const int OPERATOR			= 4;
const int MASTERBUILDER		= 5;
const int BUILDER			= 6;
const int QUESTER			= 7;
const int WIZARD			= 8;

const int MAX_CLASS			= 7;
const int CLASS_IMM			= 0;
const int MAX_SKILL			= 256;
const int MAX_PC_LEVEL		= 31;
const int MAX_PRIV_BIT_FIELDS = 1;
const int MAX_INBUF_SIZE	= 2048;

const int STATE_BOOT				= 0;
const int STATE_INIT				= 1;
const int STATE_GET_NAME			= 2;
const int STATE_CONFIRM_NAME		= 3;
const int STATE_GET_OLD_PASSWORD	= 4;
const int STATE_GET_NEW_PASSWORD	= 5;
const int STATE_CONFIRM_PASSWORD	= 6;
const int STATE_GET_CLASS			= 7;
const int STATE_GET_RACE			= 8;
const int STATE_MAIN_MENU			= 9;
const int STATE_DELETE_CHAR			= 10;
const int STATE_CHANGE_PASSWD		= 11;
const int STATE_READ_WIZ_LIST		= 12;
const int STATE_PLAYING				= 14;
const int STATE_EMAIL				= 15;
const int STATE_EDIT				= 17; 
const int STATE_EDIT_AREA			= 18; 
const int STATE_EDIT_NPC			= 19; 
const int STATE_EDIT_OBJ			= 20; 
const int STATE_EDIT_RESET			= 21; 
const int STATE_EDIT_SHOP			= 22; 
const int STATE_EDIT_ROOM			= 23; 
const int STATE_EDIT_TEXT			= 24; 

const int TASK_EDIT_APPEND			= 1;
const int TASK_EMAIL_SEND			= 20;
const int TASK_EMAIL_QUIT			= 21;

// PC bits

const int PC_UNDEFINED	= 0;	// dont use
const int PC_UNUSED1	= 1;	// reserved
const int PC_UNUSED2	= 2;	// reserved
const int PC_AFK		= 3;
const int PC_COLOR		= 4;
const int PC_ANSI		= 5;
const int PC_VT100		= 6;
const int PC_UNUSED3	= 7;
const int PC_BANNED		= 8;
const int PC_UNUSED4	= 9;
const int PC_NO_HASSLE	= 10;
const int PC_SILENCE	= 11;
const int PC_AUTOEXIT	= 12;
const int PC_AUTOLOOT	= 13;
const int PC_AUTOGOLD	= 14;
const int PC_BRIEF		= 15;
const int PC_NO_EMOTE	= 16;
const int PC_NO_TELL	= 17;
const int PC_LOG		= 18;
const int PC_NO_SUMMON	= 19; // This goes away, need resist summon as a skill
const int PC_SPIRIT		= 20; // For death quest setup
const int PC_QUEST		= 21;
const int PC_GOD_PROOF	= 22; // Lower gods cant snoop


struct command_type
{
	char *commd;
	void (PC::*fun)( String & );
	//int level;
	//int position;
};

struct immcmd_type
{
	char *commd;
	void (PC::*fun)( String & );
	int level;
	int bit;
};

class Editor;

class PC : public Char
{
	protected:
		static const command_type cmdlist[27][32];
		static const immcmd_type immcmdlist[27][10];
		Server *server;
		Socket *socket;
		short state;
		short state_last;
		short task;
		char *prompt;
		String password;
		String incommd;
		String args;
		String inlast;
		char inbuf[MAX_INBUF_SIZE];
		char *inptr;
		char *intop;
		char *inceiling;
		char *outbuf;
		char *outptr; 
		short outsize;
		char *pagebuf;
		char *pageptr;
		char *pagelast;
		unsigned long plr_flags;
		unsigned long priv [ MAX_PRIV_BIT_FIELDS ];
   
		Editor *editor;
		Editor *text;
		//EMail **email;
		short messages;
		short levels[ MAX_CLASS ];
		short learned[ MAX_SKILL ];
		long exp;
		short age;
		short energy;
		short luck;
		short security;

	public:
		PC()
		:	server(0), socket(0),
			state(STATE_INIT),task(0),prompt(new char('\0')),
			incommd(256),args(256),inptr(inbuf),intop(inbuf),
			inceiling(inbuf+MAX_INBUF_SIZE-1),
			outbuf(0),outptr(0),outsize(0),
			pagebuf(0),pageptr(0),pagelast(0),
			plr_flags(0),editor(0),
			messages(0),exp(0),
			energy(100),security(0)
		{
			*inbuf = '\0';
			memset( levels, 0, sizeof( levels[0] ) * MAX_CLASS );
			memset( learned, 0, sizeof( learned[0] ) * MAX_SKILL );
		}

		PC( Server *, Socket *, char * );

		virtual ~PC();

		// Take care of Thing base class pure virtuals
		void setRepop( Repop * ) {}

		Server *getServer() const { return server; }
		void setSock( Socket * x ) { socket = x; }
		Socket * getSock() const { return socket; }
 
		bool isPC() const { return true; }

		virtual void out( const char * );
		virtual void out( const String & x ) { PC::out( x.chars() ); }
		void readInput();
		bool getNextCommand();
		const String & getCommand();
		void command( String & );
		void command();

		virtual void pulse();
		virtual void fromWorld();
		virtual void toWorld();
		virtual void putPrompt();
		bool inBuf() const;
		bool outBuf() const;
		virtual int getState() const;
		virtual void setState( int s );
		int lastState() const;
		Editor * getEditor() const { if( text ) return text; return editor; }
		void quitEditor();
		bool isPlaying() const;
		char *pagePending() const;
		void page( char * arg="" );
		void flush(); /* not a real flush() */
		void view( const char *filename );
		void setWindow( int, int );
		void checkMail();
		//void newMail( EMail * );
		//void edit( char *str="" ); 
		void advance( int tolevel );
		virtual int setClass( int );
		virtual int getLevel() const { return levels[ classnow ]; }
		virtual int gainExp( int );
		virtual char *className() const;
//		int readFrom( const char * x ) { return Streamable::readFrom(x); }
		int readFrom( const String & x ) { return Streamable::readFrom(x); }
		int readFrom( InFile &in ); 
		int readProtoFrom( InFile &in ) {} // satisfy Thing interface
//		int writeTo( const char * x ) { return Streamable::writeTo(x); }
		int writeTo( const String & x ) { return Streamable::writeTo(x); }
		int writeTo( OutFile &out ) const;
		int writeProtoTo( OutFile &out ) const {} // satisfy Thing interface
		const String & getPasswd() const { return password; }
		void setPasswd( const String & str ) { password = str; }
		void setPrivBit( int );
		void rmPrivBit( int );
		int authorized( int ) const;
		void editText( String str );

		virtual void look( Char * );
		virtual void look( Object * );
 
		void do_debug( String & );
 
		// command member functions start here

		void do_up( String & );
		void do_down( String & );
		void do_north( String & );
		void do_south( String & );
		void do_east( String & );
		void do_west( String & );

		void do_close( String & );
		void do_open( String & );

		void do_kill( String & );

		void do_cast( String & );
		void do_advance( String & );
		void do_dbsave( String & );
		void do_goto( String & );
		void do_grant( String & );
		void do_revoke( String & );
		void do_echo( String & );
		void do_invis( String & );
		void do_immtalk( String & );
		void do_ls( String & );
		void do_cat( String & );
		void do_cp( String & );
        void do_cset( String & );
		void do_rm( String & );
		void do_memory( String & );
		void do_repops( String & );
		void do_mfind( String & );
		void do_ofind( String & );
		void do_owhere( String & );
		void do_reboot( String & );
		void do_rfind( String & );
		void do_page( String & );
		void do_purge( String & );
		void do_shutdown( String & );
		void do_slay( String & );
		void do_time( String & );
		void do_transfer( String & );
		void do_users( String & );
  		void do_ident( String & );
		void do_areas( String & );
		void do_chat( String & );
		void do_clear( String & );
		void do_commands( String & );
		void do_drop( String & );
		void do_equipment( String & );
		void do_exits( String & );
		void do_get( String & );
		void do_look( String & );
		void do_levels( String & );
		void do_help( String & );
		void do_hide( String & );
		void do_inventory( String & );
		void do_list( String & );
		//void do_mail( String & );
		void do_password( String & );
		void do_practice( String & );
		void do_prompt( String & );
		void do_put( String & );
		void do_quaff( String & );
		void do_quit( String & );
		void do_remove( String & );
		void do_save( String & );
		void do_say( String & );
		void do_score( String & );
		void do_sneak( String & );
		void do_study( String & );
		void do_tell( String & );
		void do_wear( String & );
		void do_weather( String & );
		void do_who( String & );
		void do_wield( String & );
		void do_wizhelp( String & );

		// Online Creation/Edit
		int getSecurity() { return security; }
		bool checkSecurity();
		void do_oset( String & );
		void do_ostat( String & );
		void do_mstat( String & );
		void do_aedit( String & );
		void do_medit( String & );
		void do_oedit( String & );
		void do_redit( String & );
		void do_mload( String & );
		void do_oload( String & );
};


inline const char * getPrivBitName( int val )
{
	return getBitName( priv_bit_list, val );
}

inline int getPrivBit( const char * name )
{
	return getBit( priv_bit_list, name );
}

#endif