1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-04-11 11:31:52 +02:00

Programming challenge - further preparations.

This commit is contained in:
mateuszb 2011-09-28 17:58:06 +00:00
parent ca2709e274
commit 96a5bdaa5b
15 changed files with 244 additions and 176 deletions

View File

@ -177,33 +177,6 @@ bool CCallback::buildBuilding(const CGTownInstance *town, si32 buildingID)
return true;
}
int CBattleCallback::battleMakeAction(BattleAction* action)
{
assert(action->actionType == BattleAction::HERO_SPELL);
MakeCustomAction mca(*action);
sendRequest(&mca);
return 0;
}
void CBattleCallback::sendRequest(const CPack* request)
{
//TODO should be part of CClient (client owns connection, not CB)
//but it would have to be very tricky cause template/serialization issues
if(waitTillRealize)
cl->waitingRequest.set(typeList.getTypeID(request));
cl->serv->sendPack(*request);
if(waitTillRealize)
{
if(unlockGsWhenWaiting)
getGsMutex().unlock_shared();
cl->waitingRequest.waitWhileTrue();
if(unlockGsWhenWaiting)
getGsMutex().lock_shared();
}
}
void CCallback::swapGarrisonHero( const CGTownInstance *town )
{
@ -355,19 +328,3 @@ void CCallback::unregisterMyInterface()
cl->battleints.erase(player);
//TODO? should callback be disabled as well?
}
CBattleCallback::CBattleCallback(CGameState *GS, int Player, CClient *C )
{
gs = GS;
player = Player;
cl = C;
}
bool CBattleCallback::battleMakeTacticAction( BattleAction * action )
{
assert(cl->gs->curB->tacticDistance);
MakeAction ma;
ma.ba = *action;
sendRequest(&ma);
return true;
}

View File

@ -87,16 +87,13 @@ struct CPack;
class CBattleCallback : public IBattleCallback, public CBattleInfoCallback
{
private:
CBattleCallback(CGameState *GS, int Player, CClient *C);
protected:
void sendRequest(const CPack *request);
CClient *cl;
//virtual bool hasAccess(int playerId) const;
public:
CBattleCallback(CGameState *GS, int Player, CClient *C);
int battleMakeAction(BattleAction* action) OVERRIDE;//for casting spells by hero - DO NOT use it for moving active stack
bool battleMakeTacticAction(BattleAction * action) OVERRIDE; // performs tactic phase actions

View File

@ -8,7 +8,8 @@ int main()
boost::thread tt(boost::bind(std::system, "VCMI_BattleAiHost.exe"));
boost::thread ttt(boost::bind(std::system, "VCMI_BattleAiHost.exe"));
boost::thread tttt(boost::bind(std::system, "VCMI_BattleAiHost.exe"));
boost::this_thread::sleep(boost::posix_time::seconds(5));
//boost::this_thread::sleep(boost::posix_time::seconds(5));
t.join();
return EXIT_SUCCESS;
}

View File

@ -0,0 +1,50 @@
#include "BattleCallback.h"
#include "Client.h"
#include "../lib/CGameState.h"
#include "../lib/BattleState.h"
#include "../lib/NetPacks.h"
#include "../lib/Connection.h"
CBattleCallback::CBattleCallback(CGameState *GS, int Player, CClient *C )
{
gs = GS;
player = Player;
cl = C;
}
bool CBattleCallback::battleMakeTacticAction( BattleAction * action )
{
assert(cl->gs->curB->tacticDistance);
MakeAction ma;
ma.ba = *action;
sendRequest(&ma);
return true;
}
int CBattleCallback::battleMakeAction(BattleAction* action)
{
assert(action->actionType == BattleAction::HERO_SPELL);
MakeCustomAction mca(*action);
sendRequest(&mca);
return 0;
}
void CBattleCallback::sendRequest(const CPack* request)
{
//TODO should be part of CClient (client owns connection, not CB)
//but it would have to be very tricky cause template/serialization issues
// if(waitTillRealize)
// cl->waitingRequest.set(typeList.getTypeID(request));
cl->serv->sendPack(*request);
// if(waitTillRealize)
// {
// if(unlockGsWhenWaiting)
// getGsMutex().unlock_shared();
// cl->waitingRequest.waitWhileTrue();
// if(unlockGsWhenWaiting)
// getGsMutex().lock_shared();
// }
}

View File

@ -0,0 +1,23 @@
#pragma once
#include "../global.h"
#include "../CCallback.h"
/*class CBattleCallback : public IBattleCallback, public CBattleInfoCallback
{
private:
CBattleCallback(CGameState *GS, int Player, CClient *C);
protected:
void sendRequest(const CPack *request);
CClient *cl;
//virtual bool hasAccess(int playerId) const;
public:
int battleMakeAction(BattleAction* action) OVERRIDE;//for casting spells by hero - DO NOT use it for moving active stack
bool battleMakeTacticAction(BattleAction * action) OVERRIDE; // performs tactic phase actions
friend class CCallback;
friend class CClient;
};*/

View File

@ -0,0 +1,3 @@
#include "Client.h"

View File

@ -0,0 +1,17 @@
#pragma once
class CGameState;
class CConnection;
class CClient/* : public IGameCallback*/
{
public:
CGameState *gs;
CConnection *serv;
CClient()
{
}
//void commitPackage(CPackForClient *) OVERRIDE {};
};

View File

@ -132,8 +132,14 @@
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="BattleCallback.cpp" />
<ClCompile Include="Client.cpp" />
<ClCompile Include="main.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="BattleCallback.h" />
<ClInclude Include="Client.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>

View File

@ -10,16 +10,21 @@
#else
#include <unistd.h>
#endif
#include "../lib/CGameState.h"
#include "../CCallback.h"
#include "../lib/CGameInterface.h"
#include <boost/format.hpp>
#include "Client.h"
#include "../lib/VCMI_Lib.h"
using namespace std;
using namespace boost;
std::string NAME = NAME_VER + std::string(" DLL runner");
int main(int argc, char** argv)
{
int pid = -1;
@ -29,8 +34,9 @@ int main(int argc, char** argv)
#else
pid = getpid();
#endif
initDLL(console,logfile);
logfile = new std::ofstream(("VCMI_Server_log_" + boost::lexical_cast<std::string>(pid) + ".txt").c_str());
logfile = new std::ofstream(("VCMI_Runner_log_" + boost::lexical_cast<std::string>(pid) + ".txt").c_str());
try
{
@ -39,6 +45,7 @@ int main(int argc, char** argv)
string port = "3030";
CConnection *serv = NULL;
int i = 3;
while(!serv)
{
try
@ -50,6 +57,8 @@ int main(int argc, char** argv)
{
tlog1 << "\nCannot establish connection! Retrying within 2 seconds" << std::endl;
boost::this_thread::sleep(boost::posix_time::seconds(2));
if(!--i)
exit(0);
}
}
@ -58,17 +67,24 @@ int main(int argc, char** argv)
string battleAIName;
*serv >> si >> battleAIName >> color;
assert(si.mode == StartInfo::DUEL);
tlog0 << format("Server wants us to run %s in battle %s as side %d") % battleAIName % si.mapname % color;
tlog0 << format("Server wants us to run %s in battle %s as side %d") % battleAIName % si.mapname % (int)color;
CGameState *gs = new CGameState();
gs->init(&si, 0, 0);
tlog0 << "Gs inited\n";
CClient cl;
cl.serv = serv;
cl.gs = gs;
CBattleCallback * cbc = new CBattleCallback(gs, color, this);
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);
tlog0 << cbc->battleGetAllStacks().size() << std::endl;
}
catch(std::exception &e)
{

View File

@ -1,8 +1,6 @@

Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VCMI_client", "client\VCMI_client.vcxproj", "{8355EBA8-65C2-44A4-BC2D-78053E1BF2D6}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VCMI_lib", "lib\VCMI_lib.vcxproj", "{B952FFC5-3039-4DE1-9F08-90ACDA483D8F}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VCMI_server", "server\VCMI_server.vcxproj", "{8AF697C3-465E-4910-B31B-576A9ECDB309}"
@ -34,17 +32,6 @@ Global
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{8355EBA8-65C2-44A4-BC2D-78053E1BF2D6}.Debug|Win32.ActiveCfg = Debug|Win32
{8355EBA8-65C2-44A4-BC2D-78053E1BF2D6}.Debug|Win32.Build.0 = Debug|Win32
{8355EBA8-65C2-44A4-BC2D-78053E1BF2D6}.Debug|x64.ActiveCfg = Debug|x64
{8355EBA8-65C2-44A4-BC2D-78053E1BF2D6}.Debug|x64.Build.0 = Debug|x64
{8355EBA8-65C2-44A4-BC2D-78053E1BF2D6}.RD|Win32.ActiveCfg = RD|Win32
{8355EBA8-65C2-44A4-BC2D-78053E1BF2D6}.RD|Win32.Build.0 = RD|Win32
{8355EBA8-65C2-44A4-BC2D-78053E1BF2D6}.RD|x64.ActiveCfg = RD|x64
{8355EBA8-65C2-44A4-BC2D-78053E1BF2D6}.RD|x64.Build.0 = RD|x64
{8355EBA8-65C2-44A4-BC2D-78053E1BF2D6}.Release|Win32.ActiveCfg = RD|x64
{8355EBA8-65C2-44A4-BC2D-78053E1BF2D6}.Release|x64.ActiveCfg = RD|x64
{8355EBA8-65C2-44A4-BC2D-78053E1BF2D6}.Release|x64.Build.0 = RD|x64
{B952FFC5-3039-4DE1-9F08-90ACDA483D8F}.Debug|Win32.ActiveCfg = Debug|Win32
{B952FFC5-3039-4DE1-9F08-90ACDA483D8F}.Debug|Win32.Build.0 = Debug|Win32
{B952FFC5-3039-4DE1-9F08-90ACDA483D8F}.Debug|x64.ActiveCfg = Debug|x64

View File

@ -1,5 +1,5 @@
[
"terType" : 0,
{
"terType" : 1,
"bfieldType" : 0,
"sides" :
@ -13,4 +13,4 @@
"army" : [[11, 41]]
}
]
]
}

View File

@ -51,98 +51,99 @@ void CGDefInfo::fetchInfoFromMSK()
void CDefObjInfoHandler::load()
{
VLC->dobjinfo = this;
std::istringstream inp(bitmaph->getTextFile("ZOBJCTS.TXT"));
int objNumber;
inp>>objNumber;
std::string mapStr;
for(int hh=0; hh<objNumber; ++hh)
{
CGDefInfo* nobj = new CGDefInfo();
std::string dump;
inp>>nobj->name;
std::transform(nobj->name.begin(), nobj->name.end(), nobj->name.begin(), (int(*)(int))toupper);
for(int o=0; o<6; ++o)
{
nobj->blockMap[o] = 0xff;
nobj->visitMap[o] = 0x00;
nobj->coverageMap[o] = 0x00;
nobj->shadowCoverage[o] = 0x00;
}
inp>>mapStr;
std::reverse(mapStr.begin(), mapStr.end());
for(int v=0; v<mapStr.size(); ++v)
{
if(mapStr[v]=='0')
{
nobj->blockMap[v/8] &= 255 - (128 >> (v%8));
}
}
inp>>mapStr;
std::reverse(mapStr.begin(), mapStr.end());
for(int v=0; v<mapStr.size(); ++v)
{
if(mapStr[v]=='1')
{
nobj->visitMap[v/8] |= (128 >> (v%8));
}
}
for(int yy=0; yy<2; ++yy) //first - on which types of terrain object can be placed;
inp>>dump; //second -in which terrains' menus object in the editor will be available (?)
inp>>nobj->id;
inp>>nobj->subid;
inp>>nobj->type;
nobj->visitDir = (8|16|32|64|128); //disabled visiting from the top
if(nobj->type == 2 || nobj->type == 3 || nobj->type == 4 || nobj->type == 5) //creature, hero, artifact, resource
{
nobj->visitDir = 0xff;
}
else
{
static int visitableFromTop[] = {29, 82, 86, 11, 59, 8, 111,33,81,12,9,212,215,22}; //sea chest, flotsam, shipwreck survivor, buoy, ocean bottle, boat, whirlpool, garrison, scholar, campfire, borderguard, bordergate, questguard, corpse
for(int i=0; i < ARRAY_COUNT(visitableFromTop); i++)
{
if(visitableFromTop[i] == nobj->id)
{
nobj->visitDir = 0xff;
break;
}
}
}
inp >> nobj->printPriority;
//coverageMap calculating
nobj->fetchInfoFromMSK();
gobjs[nobj->id][nobj->subid] = nobj;
if(nobj->id==TOWNI_TYPE)
castles[nobj->subid]=nobj;
}
if(vstd::contains(gobjs, 124))
{
for (int i = 0; i < 8 ; i++)
{
static const char *holeDefs[] = {"AVLHOLD0.DEF", "AVLHLDS0.DEF", "AVLHOLG0.DEF", "AVLHLSN0.DEF",
"AVLHOLS0.DEF", "AVLHOLR0.DEF", "AVLHOLX0.DEF", "AVLHOLL0.DEF"};
if(i)
{
gobjs[124][i] = new CGDefInfo(*gobjs[124][0]);
gobjs[124][i]->name = holeDefs[i];
}
}
}
else
{
tlog1 << "No def info for holes!\n";
}
return;
// std::istringstream inp(bitmaph->getTextFile("ZOBJCTS.TXT"));
// int objNumber;
// inp>>objNumber;
// std::string mapStr;
// for(int hh=0; hh<objNumber; ++hh)
// {
// CGDefInfo* nobj = new CGDefInfo();
// std::string dump;
// inp>>nobj->name;
//
// std::transform(nobj->name.begin(), nobj->name.end(), nobj->name.begin(), (int(*)(int))toupper);
//
// for(int o=0; o<6; ++o)
// {
// nobj->blockMap[o] = 0xff;
// nobj->visitMap[o] = 0x00;
// nobj->coverageMap[o] = 0x00;
// nobj->shadowCoverage[o] = 0x00;
// }
// inp>>mapStr;
// std::reverse(mapStr.begin(), mapStr.end());
// for(int v=0; v<mapStr.size(); ++v)
// {
// if(mapStr[v]=='0')
// {
// nobj->blockMap[v/8] &= 255 - (128 >> (v%8));
// }
// }
// inp>>mapStr;
// std::reverse(mapStr.begin(), mapStr.end());
// for(int v=0; v<mapStr.size(); ++v)
// {
// if(mapStr[v]=='1')
// {
// nobj->visitMap[v/8] |= (128 >> (v%8));
// }
// }
//
// for(int yy=0; yy<2; ++yy) //first - on which types of terrain object can be placed;
// inp>>dump; //second -in which terrains' menus object in the editor will be available (?)
// inp>>nobj->id;
// inp>>nobj->subid;
// inp>>nobj->type;
//
// nobj->visitDir = (8|16|32|64|128); //disabled visiting from the top
//
// if(nobj->type == 2 || nobj->type == 3 || nobj->type == 4 || nobj->type == 5) //creature, hero, artifact, resource
// {
// nobj->visitDir = 0xff;
// }
// else
// {
// static int visitableFromTop[] = {29, 82, 86, 11, 59, 8, 111,33,81,12,9,212,215,22}; //sea chest, flotsam, shipwreck survivor, buoy, ocean bottle, boat, whirlpool, garrison, scholar, campfire, borderguard, bordergate, questguard, corpse
// for(int i=0; i < ARRAY_COUNT(visitableFromTop); i++)
// {
// if(visitableFromTop[i] == nobj->id)
// {
// nobj->visitDir = 0xff;
// break;
// }
// }
// }
// inp >> nobj->printPriority;
//
// //coverageMap calculating
// nobj->fetchInfoFromMSK();
//
//
// gobjs[nobj->id][nobj->subid] = nobj;
// if(nobj->id==TOWNI_TYPE)
// castles[nobj->subid]=nobj;
// }
//
// if(vstd::contains(gobjs, 124))
// {
// for (int i = 0; i < 8 ; i++)
// {
//
// static const char *holeDefs[] = {"AVLHOLD0.DEF", "AVLHLDS0.DEF", "AVLHOLG0.DEF", "AVLHLSN0.DEF",
// "AVLHOLS0.DEF", "AVLHOLR0.DEF", "AVLHOLX0.DEF", "AVLHOLL0.DEF"};
//
// if(i)
// {
// gobjs[124][i] = new CGDefInfo(*gobjs[124][0]);
// gobjs[124][i]->name = holeDefs[i];
// }
// }
// }
// else
// {
// tlog1 << "No def info for holes!\n";
// }
}
CDefObjInfoHandler::~CDefObjInfoHandler()

View File

@ -944,7 +944,7 @@ void CGameState::init( StartInfo * si, ui32 checksum, int Seed )
{
tlog0 << "Loading duel settings from JSON file: " << scenarioOps->mapname << std::endl;
dp = DuelParameters::fromJSON(scenarioOps->mapname);
tlog0 << "JSON file has been succesfully read!\n";
tlog0 << "JSON file has been successfully read!\n";
}
else
{
@ -971,16 +971,15 @@ void CGameState::init( StartInfo * si, ui32 checksum, int Seed )
obj = h;
h->subID = dp.sides[i].heroId;
h->initHero(h->subID);
obj->initObj();
}
else
{
CGCreature *c = new CGCreature();
armies[i] = obj = c;
c->subID = 34;
}
obj->initObj();
obj->setOwner(i);
for(int j = 0; j < ARRAY_COUNT(dp.sides[i].stacks); j++)

View File

@ -121,6 +121,7 @@ CConnection::CConnection(std::string host, std::string port, std::string Name)
else
{
tlog1 << "Problem with connecting: " << std::endl << error << std::endl;
tlog1 << error.message() << std::endl;
}
endpoint_iterator++;
}

View File

@ -501,12 +501,23 @@ void CVCMIServer::loadGame()
void CVCMIServer::startDuel(const std::string &battle, const std::string &leftAI, const std::string &rightAI)
{
//we need three connections
CConnection *conns[3] = {0};
for (int i = 0; i < 3 ; i++)
CConnection *conns[1] = {0};
for (int i = 0; i < 1 ; 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());
acceptor->accept(*s, error);
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);
if (error)
{
@ -534,8 +545,14 @@ void CVCMIServer::startDuel(const std::string &battle, const std::string &leftAI
c->addStdVecItems(gh->gs, VLC);
gh->connections[gh->conns.size()] = c;
gh->conns.insert(c);
*c << si;
}
*gh->connections[0] << leftAI << ui8(0);
//*gh->connections[1] << rightAI << ui8(1);
//*gh->connections[2] << std::string() << ui8(254);
gh->runBattle();
delNull(gh);
@ -552,15 +569,8 @@ int main(int argc, char** argv)
logfile = new std::ofstream("VCMI_Server_log.txt");
console = new CConsoleHandler;
//boost::thread t(boost::bind(&CConsoleHandler::run,::console));
if(argc > 1)
{
#ifdef _MSC_VER
port = _tstoi(argv[1]);
#else
port = _ttoi(argv[1]);
#endif
}
tlog0 << "Port " << port << " will be used." << std::endl;
initDLL(console,logfile);
srand ( (unsigned int)time(NULL) );
try