roh/conf/area/
roh/game/talk/
roh/help/
roh/monsters/ocean/
roh/objects/ocean/
roh/player/
roh/rooms/area/1/
roh/rooms/misc/
roh/rooms/ocean/
roh/src-2.44b/
/* 
 * pythonHandler.h
 *   Class for handling Python <--> mud interactions
 *   ____            _               
 *  |  _ \ ___  __ _| |_ __ ___  ___ 
 *  | |_) / _ \/ _` | | '_ ` _ \/ __|
 *  |  _ <  __/ (_| | | | | | | \__ \
 *  |_| \_\___|\__,_|_|_| |_| |_|___/
 *
 * Permission to use, modify and distribute is granted via the
 *  Creative Commons - Attribution - Non Commercial - Share Alike 3.0 License
 *    http://creativecommons.org/licenses/by-nc-sa/3.0/
 *  
 * 	Copyright (C) 2007-2009 Jason Mitchell, Randi Mitchell
 * 	   Contributions by Tim Callahan, Jonathan Hseu
 *  Based on Mordor (C) Brooke Paul, Brett J. Vickers, John P. Freeman
 *
 */

// Mud Includes
#include "mud.h"
#include "pythonHandler.h"

namespace bp = boost::python;

struct BaseRoom_wrapper : BaseRoom, bp::wrapper< BaseRoom > {

    BaseRoom_wrapper( )
    : BaseRoom( )
      , bp::wrapper< BaseRoom >(){
        // null constructor

    }

    void BaseDestroy(  ){
        BaseRoom::BaseDestroy(  );
    }

    virtual bool flagIsSet( int flag ) const {
        bp::override func_flagIsSet = this->get_override( "flagIsSet" );
        return func_flagIsSet( flag );
    }

    virtual ::Fishing const * getFishing(  ) const {
        bp::override func_getFishing = this->get_override( "getFishing" );
        return func_getFishing(  );
    }

};



BOOST_PYTHON_MODULE(mud) {
	class_<Config>("Config", no_init)
		.def("getVersion",&Config::getVersion);
	
	class_<Server>("Server", no_init)
		.def("findPlayer",&Server::findPlayer,
			return_value_policy<reference_existing_object>())
	;

	class_<MudObject>("MudObject", no_init)
		.def("getName", &MudObject::getName)
	;

	
	def("dice", &::dice);
	
//	class_<Player, bases<Creature> >("Player", no_init)
//	;
}

//BaseRoom *getRoom() const;
BOOST_PYTHON_MODULE(MudObjects) {
//	boost::python::implicitly_convertible<int32_t, int64_t>();
//	boost::python::implicitly_convertible<int64_t, int32_t>();

	bp::class_< Stat, boost::noncopyable >( "Stat", bp::init< >() )
        .def(
            "addCur"
            , (void ( ::Stat::* )( short int ) )( &::Stat::addCur )
            , ( bp::arg("a") ) )
        .def(
            "addMax"
            , (void ( ::Stat::* )( short int ) )( &::Stat::addMax )
            , ( bp::arg("a") ) )
        .def(
            "adjust"
            , (int ( ::Stat::* )( int,bool ) )( &::Stat::adjust )
            , ( bp::arg("amt"), bp::arg("overMaxOk")=(bool)(false) ) )
        .def(
            "adjustMax"
            , (int ( ::Stat::* )( int ) )( &::Stat::adjustMax )
            , ( bp::arg("amt") ) )
        .def(
            "decrease"
            , (int ( ::Stat::* )( int ) )( &::Stat::decrease )
            , ( bp::arg("amt") ) )
        .def(
            "decreaseMax"
            , (int ( ::Stat::* )( int ) )( &::Stat::decreaseMax )
            , ( bp::arg("amt") ) )
        .def(
            "getCur"
            , (short int ( ::Stat::* )(  ) const)( &::Stat::getCur ) )
        .def(
            "getInitial"
            , (short int ( ::Stat::* )(  ) const)( &::Stat::getInitial ) )
        .def(
            "getMax"
            , (short int ( ::Stat::* )(  ) const)( &::Stat::getMax ) )
        .def(
            "increase"
            , (int ( ::Stat::* )( int,bool ) )( &::Stat::increase )
            , ( bp::arg("amt"), bp::arg("overMaxOk")=(bool)(false) ) )
        .def(
            "increaseMax"
            , (int ( ::Stat::* )( int ) )( &::Stat::increaseMax )
            , ( bp::arg("amt") ) )
        .def(
            "load"
            , (bool ( ::Stat::* )( ::xmlNodePtr ) )( &::Stat::load )
            , ( bp::arg("curNode") ) )
        .def(
            "restore"
            , (int ( ::Stat::* )(  ) )( &::Stat::restore ) )
        .def(
            "save"
            , (void ( ::Stat::* )( ::xmlNodePtr,char const * ) const)( &::Stat::save )
            , ( bp::arg("parentNode"), bp::arg("statName") ) )
        .def(
            "setCur"
            , (int ( ::Stat::* )( short int ) )( &::Stat::setCur )
            , ( bp::arg("newCur") ) )
        .def(
            "setInitial"
            , (void ( ::Stat::* )( short int ) )( &::Stat::setInitial )
            , ( bp::arg("i") ) )
        .def(
            "setMax"
            , (int ( ::Stat::* )( short int,bool ) )( &::Stat::setMax )
            , ( bp::arg("newMax"), bp::arg("allowZero")=(bool)(false) ) );


	{ //::BaseRoom
        typedef bp::class_< BaseRoom_wrapper, bp::bases< MudObject >, boost::noncopyable > BaseRoom_exposer_t;
        BaseRoom_exposer_t BaseRoom_exposer = BaseRoom_exposer_t( "BaseRoom", bp::no_init );
        bp::scope BaseRoom_scope( BaseRoom_exposer );
        BaseRoom_exposer.def( bp::init< >() );
        { //::BaseRoom::BaseDestroy

            typedef void ( BaseRoom_wrapper::*BaseDestroy_function_type )(  ) ;

            BaseRoom_exposer.def(
                "BaseDestroy"
                , BaseDestroy_function_type( &BaseRoom_wrapper::BaseDestroy ) );

        }
		{ //::BaseRoom::findCreature

            typedef ::Creature * ( ::BaseRoom::*findCreature_function_type )( ::Creature *,::bstring const &,bool,bool,bool ) ;

            BaseRoom_exposer.def(
                "findCreature"
                , findCreature_function_type( &::BaseRoom::findCreaturePython )
                , ( bp::arg("searcher"), bp::arg("name"), bp::arg("monFirst")=(bool)(true), bp::arg("firstAggro")=(bool)(false), bp::arg("exactMatch")=(bool)(false) )
                    ,return_value_policy<reference_existing_object>());

        }
	 }

	class_<Creature, boost::noncopyable, bases<MudObject> >("Creature", no_init)
		.def("send", &Creature::bPrint)

		.def("getRoom", &Creature::getRoom, return_value_policy<reference_existing_object>())
		.def("getName", &Creature::getName)
		.def("getClass", &Creature::getClass)
		.def("getLevel", &Creature::getLevel)
		.def("getAlignment", &Creature::getAlignment)
		.def("getArmor", &Creature::getArmor)
		.def("getExperience", &Creature::getExperience)
		.def("getClan", &Creature::getClan)
		//.def("getType", &Creature::getType)
		.def("getRace", &Creature::getRace)
		.def("getSize", &Creature::getSize)
		.def("getAttackPower", &Creature::getAttackPower)
		.def("getDescription", &Creature::getDescription)
		.def("checkMp", &Creature::checkMp)
		.def("subMp", &Creature::subMp)
		.def("smashInvis", &Creature::smashInvis)
		.def("unhide", &Creature::unhide)
		.def("unmist", &Creature::unmist)
		
		
		.def("flagIsSet", &Creature::flagIsSet)		
		.def("setFlag", &Creature::setFlag)
		.def("clearFlag", &Creature::clearFlag)
		.def("toggleFlag", &Creature::toggleFlag)

		.def("learnSpell", &Creature::setFlag)
		.def("forgetSpell", &Creature::clearFlag)
		.def("spellIsKnown", &Creature::spellIsKnown)
		
		.def("learnLanguage", &Creature::learnLanguage)
		.def("forgetLanguage", &Creature::forgetLanguage)
		.def("languageIsKnown", &Creature::languageIsKnown)
		
		.def("isEffected", &Creature::isEffected)
		.def("hasPermEffect", &Creature::hasPermEffect)
		// TODO: More effects stuff
			
		.def("knowsSkill", &Creature::knowsSkill)
		.def("getSkillLevel", &Creature::getSkillLevel)
		.def("getSkillGained", &Creature::getSkillGained)
		.def("addSkill", &Creature::addSkill)
		.def("remSkill", &Creature::remSkill)
		.def("setSkill", &Creature::setSkill)
		
		.def("addExperience", &Creature::addExperience)
		.def("subExperience", &Creature::subExperience)
		.def("subAlignment", &Creature::subAlignment)
		
		.def("setClass", &Creature::setClass)
		.def("setClan", &Creature::setClan)
		.def("setRace", &Creature::setRace)
		.def("setLevel", &Creature::setLevel)
		

		.def("subAlignment", &Creature::subAlignment)
		.def("setSize", &Creature::setSize)
		.def("getWeight", &Creature::getWeight)
		.def("maxWeight", &Creature::maxWeight)
		
		.def("isVampire", &Creature::isNewVampire)
		.def("isWerewolf", &Creature::isNewWerewolf)
		.def("isUndead", &Creature::isUndead)
		.def("immuneCriticals", &Creature::immuneCriticals)
		.def("immuneToPoison", &Creature::immuneToPoison)
		.def("immuneToDisease", &Creature::immuneToDisease)

		.def("isRace", &Creature::isRace)
		.def("getSex", &Creature::getSex)

		.def("isBrittle", &Creature::isBrittle)
		.def("isBlind", &Creature::isBlind)
		.def("isUnconscious", &Creature::isUnconscious)
		.def("isBraindead", &Creature::isBraindead)

		.def("isHidden", &Creature::isHidden)
		.def("isInvisible", &Creature::isInvisible)

		.def("isWatcher", &Creature::isWatcher)
		.def("isStaff", &Creature::isStaff)
		.def("isCt", &Creature::isCt)
		.def("isDm", &Creature::isDm)
		.def("isAdm", &Creature::isAdm)
		.def("isPet", &Creature::isPet)
		.def_readonly( "hp", &Creature::hp )
	    .def_readonly( "mp", &Creature::mp )
	;
//		.def("checkDie", &Creature::checkDie)
//		.def("checkDieRobJail", &Creature::checkDieRobJail)
//		.def("die", &Creature::die)
//		.def("", &Creature::)
		
	;


	class_<Player, bases<Creature> >("Player", no_init)
	;


	class_<Object, bases<MudObject> >("Object", no_init)
		.def("getType", &Object::getType)
		.def("getWearflag", &Object::getWearflag)
		.def("getShotsmax", &Object::getShotsmax)
		.def("getShotscur", &Object::getShotscur)

		.def("flagIsSet", &Object::flagIsSet)		
		.def("setFlag", &Object::setFlag)
		.def("clearFlag", &Object::clearFlag)
		.def("toggleFlag", &Object::toggleFlag)
	;



//	class_<BaseRoom, boost::noncopyable, bases<MudObject> >("BaseRoom", no_init)
//		.def("findCreature", &BaseRoom::findCreature, return_value_policy<reference_existing_object>())
//	;
}

// This handles bstring to PythonString conversions
struct bstringToPythonStr {
	static PyObject* convert(bstring const& s) {
		return boost::python::incref(boost::python::object((std::string)(s)).ptr());
	}
};

 struct bstringFromPythonStr {
    bstringFromPythonStr() {
      boost::python::converter::registry::push_back(
        &convertible,
        &construct,
        boost::python::type_id<bstring>());
    }

    static void* convertible(PyObject* objPtr)
    {
		if(!PyString_Check(objPtr)) 
			return 0;
		return objPtr;
    }

    static void construct( PyObject* objPtr, boost::python::converter::rvalue_from_python_stage1_data* data)
    {
      const char* value = PyString_AsString(objPtr);
      if (value == 0) 
		  boost::python::throw_error_already_set();
      void* storage = ((boost::python::converter::rvalue_from_python_storage<bstring>*)data)->storage.bytes;
      new (storage) bstring(value);
      data->convertible = storage;
    }
  };

// This will just test python for now
bool Server::initPython() {
	try {
		pythonHandler = new PythonHandler();
		
		// Setup the bstring --> pythonStr converter
		boost::python::to_python_converter<bstring, bstringToPythonStr>();
		
		// And the pythonStr --> bstring converter
		bstringFromPythonStr();
		
		// ********************************************************
		// * Module Initializations
		// *   Put any modules you would like available system wide
		// *   here, before Python is initialized below
		PyImport_AppendInittab( "mud", &initmud );
		PyImport_AppendInittab( "MudObjects", &initMudObjects );
		
		
		// Now that we've imported the modules we want, initalize python and setup the main module
		Py_Initialize();
		object main_module((handle<>(borrowed(PyImport_AddModule("__main__")))));
		pythonHandler->mainNamespace  = main_module.attr("__dict__");

		// Now import the modules we setup above
		object mudModule( (handle<>(PyImport_ImportModule("mud"))) );
		pythonHandler->mainNamespace["mud"] = mudModule;
		
		object mudObjectsModule( (handle<>(PyImport_ImportModule("MudObjects"))) );
		pythonHandler->mainNamespace["MudObjectsSystem"] = mudObjectsModule;
		
		// Add in any objects we want
		scope(mudModule).attr("gConfig") = ptr(gConfig); // Make the gConfig object available
		scope(mudModule).attr("gServer") = ptr(gServer); // Make the gServer object available
		
		
		// Run a python test command here
		runPython("import sys\nprint \"Python Initialized! Running Version \" + mud.gConfig.getVersion()");

	} catch( error_already_set) {
		PyErr_Print();
	}
	
	return(true);
}


bool Server::cleanUpPython() {
	Py_Finalize();
	return(true);
}

// RunPython:
//    pyScript: The script to be run
//    actor: The actor of the script.
//    target: The target of the script

bool Server::runPython(bstring pyScript, bstring args, MudObject *actor, MudObject *target) {
    // TODO: Make sure python is initiliazed first
	


    // Setup the local name space
    object localNamespace( (handle<>(PyDict_New())));

	localNamespace["args"] = args;

    if(actor != NULL) {
		Monster *mActor;
		Player *pActor;
		Object *oActor;
		Room *rActor;

		if((mActor = actor->getMonster())) {
			localNamespace["actor"] = ptr(mActor);
		} else if((pActor = actor->getPlayer())) {
			localNamespace["actor"] = ptr(pActor);
		} else if((oActor = actor->getObject())) {
			localNamespace["actor"] = ptr(oActor);
		} else if((rActor = actor->getRoom())) {
			localNamespace["actor"] = ptr(rActor);
		} else {
			localNamespace["actor"] = ptr(actor);
		}
	}
    
    if(target != NULL) {
		Monster *mTarget;
		Player *pTarget;
		Object *oTarget;
		Room *rTarget;

		if((mTarget = target->getMonster())) {
			localNamespace["target"] = ptr(mTarget);
		} else if((pTarget = target->getPlayer())) {
			localNamespace["target"] = ptr(pTarget);
		} else if((oTarget = target->getObject())) {
			localNamespace["target"] = ptr(oTarget);
		} else if((rTarget = target->getRoom())) {
			localNamespace["target"] = ptr(rTarget);
		} else {
			localNamespace["target"] = ptr(target);
		}
	}
        

	try {
	// Run a python test command here
		handle<> ignored(( 
		
		PyRun_String( pyScript.c_str(),
		
			 Py_file_input,
			 pythonHandler->mainNamespace.ptr(),
			 localNamespace.ptr() ) ));

	}
	catch( error_already_set) {
		PyErr_Print();
		return(false);
	}
	return(true);
}