1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-01-12 02:28:11 +02:00
vcmi/VCMI_BattleAiHost/Client.cpp
2011-12-11 12:16:12 +00:00

182 lines
4.2 KiB
C++

#include "Client.h"
#include "../lib/Connection.h"
#include "../lib/CThreadHelper.h"
#include "../lib/CGameState.h"
#include "../lib/BattleAction.h"
#include "../lib/CGameInterface.h"
#include "CheckTime.h"
#include "../lib/BattleState.h"
//#define NOT_LIB
#include "../lib/RegisterTypes.cpp"
template <typename T> class CApplyOnCL;
class CBaseForCLApply
{
public:
virtual void applyOnClAfter(CClient *cl, void *pack) const =0;
virtual void applyOnClBefore(CClient *cl, void *pack) const =0;
virtual ~CBaseForCLApply(){}
template<typename U> static CBaseForCLApply *getApplier(const U * t=NULL)
{
return new CApplyOnCL<U>;
}
};
template <typename T> class CApplyOnCL : public CBaseForCLApply
{
public:
void applyOnClAfter(CClient *cl, void *pack) const
{
T *ptr = static_cast<T*>(pack);
ptr->applyCl(cl);
}
void applyOnClBefore(CClient *cl, void *pack) const
{
T *ptr = static_cast<T*>(pack);
ptr->applyFirstCl(cl);
}
};
static CApplier<CBaseForCLApply> *applier = NULL;
void CClient::run()
{
setThreadName(-1, "CClient::run");
try
{
CPack *pack = NULL;
while(!terminate)
{
pack = serv->retreivePack(); //get the package from the server
if (terminate)
{
delete pack;
pack = NULL;
break;
}
handlePack(pack);
pack = NULL;
}
}
catch (const std::exception& e)
{
tlog3 << "Lost connection to server, ending listening thread!\n";
tlog1 << e.what() << std::endl;
if(!terminate) //rethrow (-> boom!) only if closing connection was unexpected
{
tlog1 << "Something wrong, lost connection while game is still ongoing...\n";
throw;
}
}
}
void CClient::handlePack( CPack * pack )
{
CBaseForCLApply *apply = applier->apps[typeList.getTypeID(pack)]; //find the applier
if(apply)
{
apply->applyOnClBefore(this,pack);
tlog5 << "\tMade first apply on cl\n";
gs->apply(pack);
tlog5 << "\tApplied on gs\n";
apply->applyOnClAfter(this,pack);
tlog5 << "\tMade second apply on cl\n";
}
else
{
tlog1 << "Message cannot be applied, cannot find applier! TypeID " << typeList.getTypeID(pack) << std::endl;
}
delete pack;
}
void CClient::requestMoveFromAI(const CStack *s)
{
boost::thread(&CClient::requestMoveFromAIWorker, this, s);
}
void CClient::requestMoveFromAIWorker(const CStack *s)
{
BattleAction ba;
try
{
boost::shared_lock<boost::shared_mutex> shl(*gs->mx);
Bomb *b = new Bomb(MAKE_DECIDION_TIME + HANGUP_TIME, "activeStack timer");
CheckTime timer;
ba = ai->activeStack(s);
postDecisionCall(timer.timeSinceStart());
b->disarm();
}
catch(...)
{
tlog0 << "AI thrown an exception!\n";
//TODO: disqualify?
ba = BattleAction::makeDefend(s);
}
try
{
MakeAction temp_action(ba);
tlog0 << "Checking if action looks valid... ";
bool valid = gs->isValidAction(temp_action, true);
if(gs->curB->sides[temp_action.ba.side] != color)
{
tlog1 << "Wrong side set!\n";
valid = false;
}
if(!valid)
{
tlog1 << "Warning: action seems to be invalid! Stack will defend\n";
temp_action.ba = BattleAction::makeDefend(s);
}
else
tlog1 << "Doesn't look suspicious.\n";
*serv << &temp_action;
}
catch(...)
{
tlog1 << "Failed sending action!\n";
}
}
CClient::CClient()
{
gs = NULL;
serv = NULL;
ai = NULL;
curbaction = NULL;
terminate = false;
color = 250;
applier = new CApplier<CBaseForCLApply>;
registerTypes2(*applier);
}
void CClient::commenceTacticPhaseForInt(CBattleGameInterface *battleInt)
{
setThreadName(-1, "CClient::commenceTacticPhaseForInt");
try
{
boost::shared_lock<boost::shared_mutex> shl(*gs->mx);
Bomb *b = new Bomb(TACTICS_TIME + HANGUP_TIME, "yourTacticPhase timer");
CheckTime timer;
battleInt->yourTacticPhase(gs->curB->tacticDistance);
postDecisionCall(timer.timeSinceStart(), "AI was using tactics ordering", TACTICS_TIME);
b->disarm();
if(gs && !!gs->curB && gs->curB->tacticDistance) //while awaiting for end of tactics phase, many things can happen (end of battle... or game)
{
MakeAction ma(BattleAction::makeEndOFTacticPhase(battleInt->playerID));
serv->sendPack(ma);
}
} HANDLE_EXCEPTION
}