From 131b9d6e1a695634db7bbf96b6cec0f3ce57098f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20W=2E=20Urba=C5=84czyk?= Date: Thu, 29 Sep 2011 11:24:15 +0000 Subject: [PATCH] Battle is run and result is stored. --- VCMI_BattleAiHost/Client.cpp | 125 ++++++++++++++++++++ VCMI_BattleAiHost/Client.h | 18 ++- VCMI_BattleAiHost/VCMI_BattleAiHost.vcxproj | 2 + VCMI_BattleAiHost/main.cpp | 13 +- lib/Connection.cpp | 2 +- server/CGameHandler.cpp | 31 +++-- server/CVCMIServer.cpp | 36 +++--- server/Makefile.am | 23 +++- 8 files changed, 203 insertions(+), 47 deletions(-) diff --git a/VCMI_BattleAiHost/Client.cpp b/VCMI_BattleAiHost/Client.cpp index 826dc79d3..647f29fe5 100644 --- a/VCMI_BattleAiHost/Client.cpp +++ b/VCMI_BattleAiHost/Client.cpp @@ -1,3 +1,128 @@ #include "Client.h" +#include "../lib/Connection.h" +#include "../CThreadHelper.h" +#include "../lib/CGameState.h" +#include "../lib/BattleAction.h" +#include "../lib/CGameInterface.h" +#include "CheckTime.h" +#define NOT_LIB +#include "../lib/RegisterTypes.cpp" +template 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 static CBaseForCLApply *getApplier(const U * t=NULL) + { + return new CApplyOnCL; + } +}; + +template class CApplyOnCL : public CBaseForCLApply +{ +public: + void applyOnClAfter(CClient *cl, void *pack) const + { + T *ptr = static_cast(pack); + ptr->applyCl(cl); + } + void applyOnClBefore(CClient *cl, void *pack) const + { + T *ptr = static_cast(pack); + ptr->applyFirstCl(cl); + } +}; + +static CApplier *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 + { + CheckTime timer("AI was thinking for "); + ba = ai->activeStack(s); + MakeAction temp_action(ba); + *serv << &temp_action; + } + catch(...) + { + tlog0 << "AI thrown an exception!\n"; + } +} + +CClient::CClient() +{ + gs = NULL; + serv = NULL; + ai = NULL; + curbaction = NULL; + terminate = false; + + applier = new CApplier; + registerTypes2(*applier); +} \ No newline at end of file diff --git a/VCMI_BattleAiHost/Client.h b/VCMI_BattleAiHost/Client.h index f09856764..f359885dd 100644 --- a/VCMI_BattleAiHost/Client.h +++ b/VCMI_BattleAiHost/Client.h @@ -1,17 +1,25 @@ #pragma once - +#include "../global.h" class CGameState; class CConnection; +struct CPack; +class CBattleGameInterface; +struct BattleAction; +class CStack; class CClient/* : public IGameCallback*/ { public: + bool terminate; + BattleAction *curbaction; CGameState *gs; CConnection *serv; - CClient() - { + CBattleGameInterface *ai; - } + CClient(); - //void commitPackage(CPackForClient *) OVERRIDE {}; + void run(); + void handlePack( CPack * pack ); //applies the given pack and deletes it + void requestMoveFromAI(const CStack *s); + void requestMoveFromAIWorker(const CStack *s); }; \ No newline at end of file diff --git a/VCMI_BattleAiHost/VCMI_BattleAiHost.vcxproj b/VCMI_BattleAiHost/VCMI_BattleAiHost.vcxproj index 040d392ab..422d2be7d 100644 --- a/VCMI_BattleAiHost/VCMI_BattleAiHost.vcxproj +++ b/VCMI_BattleAiHost/VCMI_BattleAiHost.vcxproj @@ -135,9 +135,11 @@ + + diff --git a/VCMI_BattleAiHost/main.cpp b/VCMI_BattleAiHost/main.cpp index 6962ff65c..c0b327ab3 100644 --- a/VCMI_BattleAiHost/main.cpp +++ b/VCMI_BattleAiHost/main.cpp @@ -81,10 +81,17 @@ int main(int argc, char** argv) tlog0 << "Cl created\n"; CBattleCallback * cbc = new CBattleCallback(gs, color, &cl); tlog0 << "Cbc created\n"; - CBattleGameInterface *ai = CDynLibHandler::getNewBattleAI(battleAIName); - tlog0 << "AI created\n"; - ai->init(cbc); + if(battleAIName.size()) + { + cl.ai = CDynLibHandler::getNewBattleAI(battleAIName); + cl.ai->playerID = color; + tlog0 << "AI created\n"; + cl.ai->init(cbc); + } + else + tlog0 << "Not loading AI, only simulation will be run\n"; tlog0 << cbc->battleGetAllStacks().size() << std::endl; + cl.run(); } catch(std::exception &e) { diff --git a/lib/Connection.cpp b/lib/Connection.cpp index 9a51535a8..437724164 100644 --- a/lib/Connection.cpp +++ b/lib/Connection.cpp @@ -240,7 +240,7 @@ CPack * CConnection::retreivePack() boost::unique_lock lock(*rmx); tlog5 << "Listening... "; *this >> ret; - tlog5 << "\treceived server message of type " << typeid(*ret).name() << std::endl; + tlog5 << "\treceived message of type " << typeid(*ret).name() << std::endl; return ret; } diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index 1d548d572..177711f6b 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -462,6 +462,16 @@ void CGameHandler::endBattle(int3 tile, const CGHeroInstance *hero1, const CGHer { CSaveFile resultFile("result.vdrst"); resultFile << *battleResult.data; + + int casualtiesPoints = 0; + tlog0 << boost::format("Winner side %d\nWinner casualties:\n") % battleResult.data->winner; + for(std::map::const_iterator i = battleResult.data->casualties[battleResult.data->winner].begin(); i != battleResult.data->casualties[battleResult.data->winner].end(); i++) + { + const CCreature *c = VLC->creh->creatures[i->first]; + tlog0 << boost::format("\t* %d of %s\n") % i->second % c->namePl; + casualtiesPoints = c->AIValue * i->second; + } + tlog0 << boost::format("Total causalties points: %d\n") % casualtiesPoints; return; } @@ -626,17 +636,12 @@ void CGameHandler::handleConnection(std::set players, CConnection &c) { while(1)//server should never shut connection first //was: while(!end2) { - { - boost::unique_lock lock(*c.rmx); - c >> pack; //get the package - tlog5 << "Received client message of type " << typeid(*pack).name() << std::endl; - } - + pack = c.retreivePack(); int packType = typeList.getTypeID(pack); //get the id of type CBaseForGHApply *apply = applier->apps[packType]; //and appropriae applier object - if(packType != typeList.getTypeID() && - (packType != typeList.getTypeID() || !isAllowedArrangePack((ArrangeStacks*)pack)) && // for dialogs like garrison - states[getCurrentPlayer()].queries.size()) + if(packType != typeList.getTypeID() + &&(packType != typeList.getTypeID() || !isAllowedArrangePack((ArrangeStacks*)pack)) // for dialogs like garrison + && vstd::contains(states.players, getCurrentPlayer()) && states[getCurrentPlayer()].queries.size()) { complain("Answer the query before attempting any further actions!"); PackageApplied applied; @@ -1997,13 +2002,7 @@ void CGameHandler::save( const std::string &fname ) void CGameHandler::close() { - tlog0 << "We have been requested to close.\n"; - - if(gs->initialOpts->mode == StartInfo::DUEL) - { - exit(0); - } - + tlog0 << "We have been requested to close.\n"; //BOOST_FOREACH(CConnection *cc, conns) // if(cc && cc->socket && cc->socket->is_open()) // cc->socket->close(); diff --git a/server/CVCMIServer.cpp b/server/CVCMIServer.cpp index f548d21b8..1de5f02b2 100644 --- a/server/CVCMIServer.cpp +++ b/server/CVCMIServer.cpp @@ -501,23 +501,14 @@ void CVCMIServer::loadGame() void CVCMIServer::startDuel(const std::string &battle, const std::string &leftAI, const std::string &rightAI) { //we need three connections - CConnection *conns[1] = {0}; - for (int i = 0; i < 1 ; i++) + CConnection *conns[3] = {0}; + for (int i = 0; i < 3 ; i++) { boost::system::error_code error; - - //boost::system::error_code error; tlog0<<"Listening for connections at port " << acceptor->local_endpoint().port() << std::endl; tcp::socket * s = new tcp::socket(acceptor->get_io_service()); - boost::thread acc(boost::bind(vaccept,acceptor,s,&error)); -// sr->setToTrueAndNotify(); -// delete mr; - - acc.join(); - - //tcp::socket * s = new tcp::socket(acceptor->get_io_service()); - //acceptor->accept(*s, error); + acceptor->accept(*s, error); if (error) { @@ -537,26 +528,39 @@ void CVCMIServer::startDuel(const std::string &battle, const std::string &leftAI si.mode = StartInfo::DUEL; si.mapname = battle; + + tlog0 << "Preparing gh!\n"; CGameHandler *gh = new CGameHandler(); gh->init(&si,std::time(NULL)); BOOST_FOREACH(CConnection *c, conns) { + ui8 player = gh->conns.size(); + tlog0 << boost::format("Preparing connection %d!\n") % (int)player; c->addStdVecItems(gh->gs, VLC); - gh->connections[gh->conns.size()] = c; + gh->connections[player] = c; gh->conns.insert(c); + gh->states.addPlayer(player); *c << si; + + std::set pom; + pom.insert(player); + boost::thread(boost::bind(&CGameHandler::handleConnection,gh,pom,boost::ref(*c))); } + tlog0 << boost::format("Sending start info to connections!\n"); *gh->connections[0] << leftAI << ui8(0); - //*gh->connections[1] << rightAI << ui8(1); - //*gh->connections[2] << std::string() << ui8(254); + *gh->connections[1] << rightAI << ui8(1); + *gh->connections[2] << std::string() << ui8(254); + tlog0 << "Starting battle!\n"; gh->runBattle(); - + tlog0 << "Battle over!\n"; delNull(gh); + tlog0 << "Removed gh!\n"; boost::this_thread::sleep(boost::posix_time::milliseconds(1000)); + tlog0 << "Dying...\n"; exit(0); } diff --git a/server/Makefile.am b/server/Makefile.am index 7648f9531..f593da912 100644 --- a/server/Makefile.am +++ b/server/Makefile.am @@ -1,6 +1,17 @@ -bin_PROGRAMS = odpalarka - -odpalarka_LDADD = $(top_builddir)/lib/libvcmi.la -odpalarka_CXXFLAGS = @SDL_CXXFLAGS@ -odpalarka_LDFLAGS = -L$(top_builddir)/lib -odpalarka_SOURCES = main.cpp +bin_PROGRAMS = vcmiserver + +vcmiserver_LDADD = $(top_builddir)/lib/libvcmi.la +vcmiserver_CXXFLAGS = @SDL_CXXFLAGS@ +vcmiserver_LDFLAGS = -L$(top_builddir)/lib +vcmiserver_SOURCES = \ + ../CConsoleHandler.cpp \ + ../CConsoleHandler.h \ + ../CThreadHelper.cpp \ + ../CThreadHelper.h \ + CGameHandler.cpp \ + CGameHandler.h \ + CVCMIServer.cpp \ + CVCMIServer.h \ + NetPacksServer.cpp \ + stdafx.cpp \ + stdafx.h