mirror of
https://github.com/vcmi/vcmi.git
synced 2025-03-19 21:10:12 +02:00
Further changes for programming challenge.
* setting obstacles and creature params in duel config file * handling arguments for Odpalarka * handling runner + runner + runner + client scenario (memory measura AND visualziation)
This commit is contained in:
parent
51ace689c4
commit
92e508fe1f
@ -204,6 +204,16 @@ void CStupidAI::battleStart(const CCreatureSet *army1, const CCreatureSet *army2
|
||||
{
|
||||
print("battleStart called");
|
||||
side = Side;
|
||||
TStacks myStacks = cb->battleGetStacks(CBattleCallback::ONLY_MINE);
|
||||
std::cout << "My side: " << side << std::endl
|
||||
<< "I have " << myStacks.size() << " stacks. They are:\n";
|
||||
|
||||
for(int i = 0; i < myStacks.size(); i++)
|
||||
{
|
||||
const CStack *s = myStacks.at(i);
|
||||
tlog5 << format("%2d) Stack of %4d %s.\n\tAttack:\t%4d, \n\tDefense:\t%4d, \n\tHP:\t%4d\n\tDamage:\t%4d-%d\n")
|
||||
% i % s->count % s->getCreature()->namePl % s->Attack() % s->Defense() % s->MaxHealth() % s->getMinDamage() % s->getMaxDamage();
|
||||
}
|
||||
}
|
||||
|
||||
void CStupidAI::battleStacksHealedRes(const std::vector<std::pair<ui32, ui32> > & healedStacks, bool lifeDrain, bool tentHeal, si32 lifeDrainFrom)
|
||||
|
@ -1,3 +1,8 @@
|
||||
#pragma once
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include "../../AI_Base.h"
|
||||
#include <boost/format.hpp>
|
||||
#include "../../AI_Base.h"
|
||||
|
||||
using boost::format;
|
||||
using boost::str;
|
||||
using boost::lexical_cast;
|
@ -1,9 +1,60 @@
|
||||
#include "../global.h"
|
||||
#include <boost/thread.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/program_options.hpp>
|
||||
namespace po = boost::program_options;
|
||||
|
||||
void prog_help()
|
||||
{
|
||||
throw std::exception("The method or operation is not implemented.");
|
||||
}
|
||||
|
||||
int main(int argc, const char **argv)
|
||||
{
|
||||
std::cout << "VCMI Odpalarka\nMy path: " << argv[0] << std::endl;
|
||||
|
||||
po::options_description opts("Allowed options");
|
||||
opts.add_options()
|
||||
("help,h", "display help and exit")
|
||||
("aiLeft,l", po::value<std::string>(), "Left AI path")
|
||||
("aiRight,r", po::value<std::string>(), "Right AI path")
|
||||
("battle,b", po::value<std::string>(), "Duel file path")
|
||||
("visualization,v", "Runs a client to display a visualization of battle");
|
||||
|
||||
std::string leftAI = "StupidAI",
|
||||
rightAI = "StupidAI",
|
||||
battle = "b1.json";
|
||||
|
||||
po::variables_map vm;
|
||||
if(argc > 1)
|
||||
{
|
||||
try
|
||||
{
|
||||
po::store(po::parse_command_line(argc, argv, opts), vm);
|
||||
po::notify(vm);
|
||||
leftAI = vm["aiLeft"].as<std::string>();
|
||||
rightAI = vm["aiRight"].as<std::string>();
|
||||
battle = vm["battle"].as<std::string>();
|
||||
}
|
||||
catch(std::exception &e)
|
||||
{
|
||||
std::cerr << "Failure during parsing command-line options:\n" << e.what() << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Default AIs will be used." << std::endl;
|
||||
}
|
||||
|
||||
if(vm.count("help"))
|
||||
{
|
||||
prog_help();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::string runnername =
|
||||
#ifdef _WIN32
|
||||
"VCMI_BattleAiHost.exe"
|
||||
@ -19,17 +70,18 @@ int main(int argc, const char **argv)
|
||||
#endif
|
||||
;
|
||||
|
||||
std::string serverCommand = servername + " b1.json StupidAI MadAI"; // StupidAI MadAI
|
||||
bool withVisualization = vm.count("visualization");
|
||||
std::string serverCommand = servername + " " + battle + " " + leftAI + " " + rightAI + (withVisualization ? " v" : "");
|
||||
std::string runnerCommand = runnername;
|
||||
boost::thread t(boost::bind(std::system, serverCommand.c_str()));
|
||||
boost::thread tt(boost::bind(std::system, runnername.c_str()));
|
||||
boost::thread ttt(boost::bind(std::system, runnername.c_str()));
|
||||
if(argc == 2)
|
||||
boost::thread tt(boost::bind(std::system, runnerCommand.c_str()));
|
||||
boost::thread ttt(boost::bind(std::system, runnerCommand.c_str()));
|
||||
boost::thread tttt(boost::bind(std::system, runnername.c_str()));
|
||||
if(withVisualization)
|
||||
{
|
||||
boost::this_thread::sleep(boost::posix_time::millisec(500)); //FIXME
|
||||
//boost::this_thread::sleep(boost::posix_time::millisec(500)); //FIXME
|
||||
boost::thread tttt(boost::bind(std::system, "VCMI_Client.exe -battle"));
|
||||
}
|
||||
else if(argc == 1)
|
||||
boost::thread tttt(boost::bind(std::system, runnername.c_str()));
|
||||
|
||||
//boost::this_thread::sleep(boost::posix_time::seconds(5));
|
||||
|
||||
|
@ -61,6 +61,7 @@ const int PROCESS_INFO_TIME = 5;
|
||||
const int MAKE_DECIDION_TIME = 75;
|
||||
const int MEASURE_MARGIN = 1;
|
||||
const int HANGUP_TIME = 50;
|
||||
const int STARTUP_TIME = 100;
|
||||
|
||||
void postInfoCall(int timeUsed);
|
||||
void postDecisionCall(int timeUsed);
|
||||
|
@ -12,12 +12,12 @@
|
||||
#include "CheckTime.h"
|
||||
|
||||
|
||||
void postInfoCall(int timeUsed)
|
||||
void postInfoCall(int timeUsed, int limit)
|
||||
{
|
||||
tlog0 << "AI was processing info for " << timeUsed << " ms.\n";
|
||||
if(timeUsed > PROCESS_INFO_TIME + MEASURE_MARGIN)
|
||||
if(timeUsed > limit + MEASURE_MARGIN)
|
||||
{
|
||||
tlog1 << "That's too long! AI is disqualified!\n";
|
||||
tlog1 << "That's too long (limit=" << limit << "+" << MEASURE_MARGIN << ")! AI is disqualified!\n";
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
@ -34,20 +34,25 @@ void postDecisionCall(int timeUsed)
|
||||
|
||||
//macros to avoid code duplication - calls given method with given arguments if interface for specific player is present
|
||||
//awaiting variadic templates...
|
||||
#define BATTLE_INTERFACE_CALL_IF_PRESENT(function,...) \
|
||||
//
|
||||
|
||||
#define BATTLE_INTERFACE_CALL_IF_PRESENT_WITH_TIME_LIMIT(TIME_LIMIT, function, ...) \
|
||||
do \
|
||||
{ \
|
||||
int timeUsed = 0; \
|
||||
if(cl->ai) \
|
||||
{ \
|
||||
Bomb *b = new Bomb(PROCESS_INFO_TIME + HANGUP_TIME);\
|
||||
Bomb *b = new Bomb(TIME_LIMIT + HANGUP_TIME); \
|
||||
CheckTime pr; \
|
||||
cl->ai->function(__VA_ARGS__); \
|
||||
postInfoCall(pr.timeSinceStart()); \
|
||||
postInfoCall(pr.timeSinceStart(), TIME_LIMIT); \
|
||||
b->disarm(); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define BATTLE_INTERFACE_CALL_IF_PRESENT(function,...) \
|
||||
BATTLE_INTERFACE_CALL_IF_PRESENT_WITH_TIME_LIMIT(PROCESS_INFO_TIME, function, __VA_ARGS__)
|
||||
|
||||
#define UNEXPECTED_PACK assert(0)
|
||||
|
||||
void SetResources::applyCl( CClient *cl )
|
||||
@ -277,8 +282,7 @@ void GarrisonDialog::applyCl(CClient *cl)
|
||||
|
||||
void BattleStart::applyCl( CClient *cl )
|
||||
{
|
||||
//TODO!!!!
|
||||
BATTLE_INTERFACE_CALL_IF_PRESENT(battleStart, info->belligerents[0], info->belligerents[1], info->tile, info->heroes[0], info->heroes[1], cl->color);
|
||||
BATTLE_INTERFACE_CALL_IF_PRESENT_WITH_TIME_LIMIT(STARTUP_TIME, battleStart, info->belligerents[0], info->belligerents[1], info->tile, info->heroes[0], info->heroes[1], cl->color);
|
||||
}
|
||||
|
||||
void BattleNextRound::applyFirstCl(CClient *cl)
|
||||
|
@ -17,6 +17,8 @@
|
||||
#include <boost/format.hpp>
|
||||
#include "Client.h"
|
||||
#include "../lib/VCMI_Lib.h"
|
||||
#include "../lib/BattleState.h"
|
||||
#include "../lib/NetPacks.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace boost;
|
||||
@ -51,7 +53,7 @@ int main(int argc, char** argv)
|
||||
try
|
||||
{
|
||||
tlog0 << "Establishing connection...\n";
|
||||
serv = new CConnection(host, port, "DLL host");
|
||||
serv = new CConnection(host, port, NAME);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
@ -87,6 +89,11 @@ int main(int argc, char** argv)
|
||||
cl.color = color;
|
||||
tlog0 << "AI created\n";
|
||||
cl.ai->init(cbc);
|
||||
|
||||
BattleStart bs;
|
||||
bs.info = gs->curB;
|
||||
bs.applyFirstCl(&cl);
|
||||
bs.applyCl(&cl);
|
||||
}
|
||||
else
|
||||
tlog0 << "Not loading AI, only simulation will be run\n";
|
||||
|
11
b1.json
11
b1.json
@ -1,6 +1,7 @@
|
||||
{
|
||||
"terType" : 1,
|
||||
"bfieldType" : 0,
|
||||
"obstacles" : [77, 94, 111, [28, 7]], //vector of positions or vectored pairs [type, pos]
|
||||
|
||||
"sides" :
|
||||
[
|
||||
@ -9,10 +10,18 @@
|
||||
"army" : [[10, 40]],
|
||||
"heroid" : 0,
|
||||
"spells" : [1,2,3,4]
|
||||
}
|
||||
},
|
||||
{
|
||||
"side" : 1,
|
||||
"army" : [[11, 41]]
|
||||
}
|
||||
],
|
||||
|
||||
"creatures" :
|
||||
[
|
||||
{
|
||||
"id" : 10,
|
||||
"attack" : 50
|
||||
}
|
||||
]
|
||||
}
|
@ -1577,6 +1577,7 @@ void CBattleInterface::activate()
|
||||
|
||||
void CBattleInterface::deactivate()
|
||||
{
|
||||
if(!active) return;
|
||||
deactivateKeys();
|
||||
deactivateMouseMove();
|
||||
deactivateRClick();
|
||||
@ -4502,7 +4503,7 @@ CBattleResultWindow::CBattleResultWindow(const BattleResult &br, const SDL_Rect
|
||||
|
||||
CCS->musich->playMusic(musicBase::winBattle);
|
||||
CCS->videoh->open(VIDEO_WIN);
|
||||
std::string str = CGI->generaltexth->allTexts[text];
|
||||
std::string str = text >= 0 ? CGI->generaltexth->allTexts[text] : std::string("AI has been disqualified!");
|
||||
|
||||
const CGHeroInstance * ourHero = weAreAttacker? owner->attackingHeroInstance : owner->defendingHeroInstance;
|
||||
if (ourHero)
|
||||
|
@ -433,7 +433,7 @@ void CClient::newDuel(CConnection *con, StartInfo *si)
|
||||
try
|
||||
{
|
||||
tlog0 << "Establishing connection...\n";
|
||||
serv = new CConnection(host, port, "DLL host");
|
||||
serv = new CConnection(host, port, NAME);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
|
@ -13,5 +13,5 @@ clientSettings
|
||||
defaultPlayerAI=GeniusAI;
|
||||
neutralBattleAI=StupidAI;
|
||||
showFPS=0;
|
||||
classicCreatureWindow=0;
|
||||
classicCreatureWindow=1;
|
||||
}
|
@ -989,9 +989,30 @@ void CGameState::init( StartInfo * si, ui32 checksum, int Seed )
|
||||
if(count || obj->hasStackAtSlot(j))
|
||||
obj->setCreature(j, cre, count);
|
||||
}
|
||||
|
||||
BOOST_FOREACH(const DuelParameters::CusomCreature &cc, dp.creatures)
|
||||
{
|
||||
CCreature *c = VLC->creh->creatures[cc.id];
|
||||
if(cc.attack >= 0)
|
||||
c->getBonus(Selector::typeSubtype(Bonus::PRIMARY_SKILL, PrimarySkill::ATTACK))->val = cc.attack;
|
||||
if(cc.defense >= 0)
|
||||
c->getBonus(Selector::typeSubtype(Bonus::PRIMARY_SKILL, PrimarySkill::DEFENSE))->val = cc.defense;
|
||||
if(cc.speed >= 0)
|
||||
c->getBonus(Selector::type(Bonus::STACKS_SPEED))->val = cc.speed;
|
||||
if(cc.HP >= 0)
|
||||
c->getBonus(Selector::type(Bonus::STACK_HEALTH))->val = cc.HP;
|
||||
if(cc.dmg >= 0)
|
||||
{
|
||||
c->getBonus(Selector::typeSubtype(Bonus::CREATURE_DAMAGE, 1))->val = cc.dmg;
|
||||
c->getBonus(Selector::typeSubtype(Bonus::CREATURE_DAMAGE, 2))->val = cc.dmg;
|
||||
}
|
||||
if(cc.shoots >= 0)
|
||||
c->getBonus(Selector::type(Bonus::SHOTS))->val = cc.shoots;
|
||||
}
|
||||
}
|
||||
|
||||
curB = BattleInfo::setupBattle(int3(), dp.bfieldType, dp.terType, armies, heroes, false, town);
|
||||
curB->obstacles = dp.obstacles;
|
||||
curB->localInit();
|
||||
return;
|
||||
}
|
||||
@ -2798,6 +2819,45 @@ DuelParameters DuelParameters::fromJSON(const std::string &fname)
|
||||
|
||||
}
|
||||
|
||||
BOOST_FOREACH(const JsonNode &n, duelData["obstacles"].Vector())
|
||||
{
|
||||
CObstacleInstance oi;
|
||||
if(n.getType() == JsonNode::DATA_VECTOR)
|
||||
{
|
||||
oi.ID = n.Vector()[0].Float();
|
||||
oi.pos = n.Vector()[1].Float();
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(n.getType() == JsonNode::DATA_FLOAT);
|
||||
oi.ID = 21;
|
||||
oi.pos = n.Float();
|
||||
}
|
||||
oi.uniqueID = ret.obstacles.size();
|
||||
ret.obstacles.push_back(oi);
|
||||
}
|
||||
|
||||
BOOST_FOREACH(const JsonNode &n, duelData["creatures"].Vector())
|
||||
{
|
||||
CusomCreature cc;
|
||||
cc.id = n["id"].Float();
|
||||
|
||||
#define retreive(name) \
|
||||
if(n[ #name ].getType() == JsonNode::DATA_FLOAT)\
|
||||
cc.name = n[ #name ].Float(); \
|
||||
else \
|
||||
cc.name = -1;
|
||||
|
||||
retreive(attack);
|
||||
retreive(defense);
|
||||
retreive(HP);
|
||||
retreive(dmg);
|
||||
retreive(shoots);
|
||||
retreive(speed);
|
||||
ret.creatures.push_back(cc);
|
||||
}
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -306,12 +306,31 @@ struct DLL_EXPORT DuelParameters
|
||||
}
|
||||
} sides[2];
|
||||
|
||||
std::vector<CObstacleInstance> obstacles;
|
||||
|
||||
static DuelParameters fromJSON(const std::string &fname);
|
||||
|
||||
struct CusomCreature
|
||||
{
|
||||
int id;
|
||||
int attack, defense, dmg, HP, speed, shoots;
|
||||
|
||||
CusomCreature()
|
||||
{
|
||||
id = attack = defense = dmg = HP = speed = shoots = -1;
|
||||
}
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & id & attack & defense & dmg & HP & speed & shoots;
|
||||
}
|
||||
};
|
||||
|
||||
std::vector<CusomCreature> creatures;
|
||||
|
||||
DuelParameters();
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & terType & bfieldType & sides;
|
||||
h & terType & bfieldType & sides & obstacles & creatures;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -75,6 +75,7 @@ void CConnection::init()
|
||||
wmx = new boost::mutex;
|
||||
rmx = new boost::mutex;
|
||||
|
||||
contactName = pom;
|
||||
handler = NULL;
|
||||
receivedStop = sendStop = false;
|
||||
static int cid = 1;
|
||||
|
@ -902,6 +902,7 @@ public:
|
||||
bool myEndianess, contactEndianess; //true if little endian, if endianess is different we'll have to revert received multi-byte vars
|
||||
boost::asio::io_service *io_service;
|
||||
std::string name; //who uses this connection
|
||||
std::string contactName;
|
||||
|
||||
int connectionID;
|
||||
CConnection *c;
|
||||
|
@ -498,13 +498,14 @@ void CVCMIServer::loadGame()
|
||||
gh.run(true);
|
||||
}
|
||||
|
||||
void CVCMIServer::startDuel(const std::string &battle, const std::string &leftAI, const std::string &rightAI)
|
||||
void CVCMIServer::startDuel(const std::string &battle, const std::string &leftAI, const std::string &rightAI, int howManyClients)
|
||||
{
|
||||
|
||||
//we need three connections
|
||||
boost::thread* threads[3] = {0};
|
||||
CConnection *conns[3] = {0};
|
||||
for (int i = 0; i < 3 ; i++)
|
||||
std::vector<boost::thread*> threads(howManyClients, NULL);
|
||||
std::vector<CConnection*> conns(howManyClients, NULL);
|
||||
|
||||
for (int i = 0; i < howManyClients ; i++)
|
||||
{
|
||||
boost::system::error_code error;
|
||||
|
||||
@ -554,9 +555,32 @@ void CVCMIServer::startDuel(const std::string &battle, const std::string &leftAI
|
||||
}
|
||||
|
||||
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);
|
||||
int aisSoFar = 0;
|
||||
for (int i = 0; i < howManyClients ; i++)
|
||||
{
|
||||
tlog0 << "Connection nr " << i;
|
||||
CConnection *c = conns[i];
|
||||
|
||||
if(c->contactName.find("client") != std::string::npos)
|
||||
{
|
||||
tlog0 << " is a visualization client!\n";
|
||||
*c << std::string() << ui8(254);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(aisSoFar < 2)
|
||||
{
|
||||
tlog0 << " will run " << (aisSoFar ? "right" : "left") << " AI " << std::endl;
|
||||
*c << gh->ais[aisSoFar] << ui8(aisSoFar);
|
||||
aisSoFar++;
|
||||
}
|
||||
else
|
||||
{
|
||||
tlog0 << " will serve as a memory reference.\n";
|
||||
*c << std::string() << ui8(254);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string logFName = "duel_log.vdat";
|
||||
tlog0 << "Logging battle activities (for replay possibility) in " << logFName << std::endl;
|
||||
@ -598,10 +622,10 @@ int main(int argc, char** argv)
|
||||
{
|
||||
io_service io_service;
|
||||
CVCMIServer server;
|
||||
if(argc == 4)
|
||||
server.startDuel(argv[1], argv[2], argv[3]);
|
||||
if(argc == 4 || argc == 5)
|
||||
server.startDuel(argv[1], argv[2], argv[3], argc-1);
|
||||
else
|
||||
server.startDuel("b1.json", "StupidAI", "StupidAI");
|
||||
server.startDuel("b1.json", "StupidAI", "StupidAI", 2);
|
||||
|
||||
while(!end2)
|
||||
{
|
||||
|
@ -54,7 +54,7 @@ public:
|
||||
~CVCMIServer(); //d-tor
|
||||
|
||||
void start();
|
||||
void startDuel(const std::string &battle, const std::string &leftAI, const std::string &rightAI);
|
||||
void startDuel(const std::string &battle, const std::string &leftAI, const std::string &rightAI, int howManyClients);
|
||||
CGameHandler *initGhFromHostingConnection(CConnection &c);
|
||||
|
||||
void newGame();
|
||||
|
Loading…
x
Reference in New Issue
Block a user