2011-11-10 09:21:27 +00:00
|
|
|
//#include "../global.h"
|
2012-05-12 17:59:32 +00:00
|
|
|
#include "StdInc.h"
|
|
|
|
#include "../lib/VCMI_Lib.h"
|
2011-10-20 23:29:32 +00:00
|
|
|
namespace po = boost::program_options;
|
|
|
|
|
2012-05-13 14:51:13 +00:00
|
|
|
|
|
|
|
//FANN
|
|
|
|
#include <floatfann.h>
|
|
|
|
#include <fann_cpp.h>
|
|
|
|
|
2012-05-12 17:59:32 +00:00
|
|
|
std::string leftAI, rightAI, battle, results, logsDir;
|
|
|
|
bool withVisualization = false;
|
|
|
|
std::string servername;
|
|
|
|
std::string runnername;
|
|
|
|
extern DLL_EXPORT LibClasses * VLC;
|
|
|
|
|
2011-12-09 21:37:32 +00:00
|
|
|
std::string addQuotesIfNeeded(const std::string &s)
|
|
|
|
{
|
|
|
|
if(s.find_first_of(' ') != std::string::npos)
|
|
|
|
return "\"" + s + "\"";
|
|
|
|
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
2011-10-20 23:29:32 +00:00
|
|
|
void prog_help()
|
|
|
|
{
|
2011-11-10 09:21:27 +00:00
|
|
|
std::cout << "If run without args, then StupidAI will be run on b1.json.\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
void runCommand(const std::string &command, const std::string &name, const std::string &logsDir = "")
|
|
|
|
{
|
|
|
|
static std::string commands[100];
|
|
|
|
static int i = 0;
|
|
|
|
std::string &cmd = commands[i++];
|
|
|
|
if(logsDir.size() && name.size())
|
2011-12-09 21:37:32 +00:00
|
|
|
{
|
|
|
|
std::string directionLogs = logsDir + "/" + name + ".txt";
|
|
|
|
cmd = command + " > " + addQuotesIfNeeded(directionLogs);
|
|
|
|
}
|
2011-11-10 09:21:27 +00:00
|
|
|
else
|
|
|
|
cmd = command;
|
|
|
|
|
|
|
|
boost::thread tt(boost::bind(std::system, cmd.c_str()));
|
2011-10-20 23:29:32 +00:00
|
|
|
}
|
2011-09-27 21:54:40 +00:00
|
|
|
|
2012-05-12 17:59:32 +00:00
|
|
|
double playBattle(const DuelParameters &dp)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
CSaveFile out("pliczek.ssnb");
|
|
|
|
out << dp;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
std::string serverCommand = servername + " " + addQuotesIfNeeded(battle) + " " + addQuotesIfNeeded(leftAI) + " " + addQuotesIfNeeded(rightAI) + " " + addQuotesIfNeeded(results) + " " + addQuotesIfNeeded(logsDir) + " " + (withVisualization ? " v" : "");
|
|
|
|
std::string runnerCommand = runnername + " " + addQuotesIfNeeded(logsDir);
|
|
|
|
std::cout <<"Server command: " << serverCommand << std::endl << "Runner command: " << runnerCommand << std::endl;
|
|
|
|
|
|
|
|
int code = 0;
|
|
|
|
boost::thread t([&]
|
|
|
|
{
|
|
|
|
code = std::system(serverCommand.c_str());
|
|
|
|
});
|
|
|
|
|
|
|
|
runCommand(runnerCommand, "first_runner", logsDir);
|
|
|
|
runCommand(runnerCommand, "second_runner", logsDir);
|
|
|
|
runCommand(runnerCommand, "third_runner", logsDir);
|
|
|
|
if(withVisualization)
|
|
|
|
{
|
|
|
|
//boost::this_thread::sleep(boost::posix_time::millisec(500)); //FIXME
|
|
|
|
boost::thread tttt(boost::bind(std::system, "VCMI_Client.exe -battle"));
|
|
|
|
}
|
|
|
|
|
|
|
|
//boost::this_thread::sleep(boost::posix_time::seconds(5));
|
|
|
|
t.join();
|
|
|
|
return code / 1000000.0;
|
|
|
|
}
|
|
|
|
|
2012-05-13 14:51:13 +00:00
|
|
|
typedef std::map<int, CArtifactInstance*> TArtSet;
|
|
|
|
|
|
|
|
double cmpArtSets(TArtSet setL, TArtSet setR)
|
|
|
|
{
|
|
|
|
DuelParameters dp;
|
|
|
|
dp.bfieldType = 1;
|
|
|
|
dp.terType = 1;
|
|
|
|
|
|
|
|
for(int i = 0; i < 2 ; i++)
|
|
|
|
{
|
|
|
|
auto &side = dp.sides[i];
|
|
|
|
side.heroId = i;
|
|
|
|
side.heroPrimSkills.resize(4,0);
|
|
|
|
side.stacks[0] = DuelParameters::SideSettings::StackSettings(10+i, 40+i);
|
|
|
|
}
|
|
|
|
|
|
|
|
//lewa strona z art 0.9
|
|
|
|
//bez artefaktow -0.41
|
|
|
|
//prawa strona z art. -0.926
|
|
|
|
|
|
|
|
dp.sides[0].artifacts = setL;
|
|
|
|
dp.sides[1].artifacts = setR;
|
|
|
|
|
|
|
|
auto battleOutcome = playBattle(dp);
|
|
|
|
return battleOutcome;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<CArtifactInstance*> genArts()
|
2012-05-12 17:59:32 +00:00
|
|
|
{
|
2012-05-13 14:51:13 +00:00
|
|
|
std::vector<CArtifactInstance*> ret;
|
|
|
|
|
2012-05-12 17:59:32 +00:00
|
|
|
CArtifact *nowy = new CArtifact();
|
|
|
|
nowy->description = "Cudowny miecz Towa gwarantuje zwyciestwo";
|
|
|
|
nowy->name = "Cudowny miecz";
|
|
|
|
nowy->constituentOf = nowy->constituents = NULL;
|
|
|
|
nowy->possibleSlots.push_back(Arts::LEFT_HAND);
|
|
|
|
|
|
|
|
CArtifactInstance *artinst = new CArtifactInstance(nowy);
|
|
|
|
auto &arts = VLC->arth->artifacts;
|
|
|
|
CArtifactInstance *inny = new CArtifactInstance(VLC->arth->artifacts[15]);
|
|
|
|
|
|
|
|
artinst->addNewBonus(new Bonus(Bonus::PERMANENT, Bonus::PRIMARY_SKILL, Bonus::ARTIFACT_INSTANCE, +25, nowy->id, PrimarySkill::ATTACK));
|
|
|
|
artinst->addNewBonus(new Bonus(Bonus::PERMANENT, Bonus::PRIMARY_SKILL, Bonus::ARTIFACT_INSTANCE, +25, nowy->id, PrimarySkill::DEFENSE));
|
|
|
|
|
|
|
|
auto bonuses = artinst->getBonuses([](const Bonus *){ return true; });
|
|
|
|
BOOST_FOREACH(Bonus *b, *bonuses)
|
|
|
|
{
|
|
|
|
std::cout << format("%s (%d) value:%d, description: %s\n") % bonusTypeToString(b->type) % b->subtype % b->val % b->Description();
|
|
|
|
}
|
|
|
|
|
2012-05-13 14:51:13 +00:00
|
|
|
return ret;
|
|
|
|
}
|
2012-05-12 17:59:32 +00:00
|
|
|
|
|
|
|
|
2012-05-13 14:51:13 +00:00
|
|
|
//returns how good the artifact is for the neural network
|
|
|
|
double runSSN(FANN::neural_net & net, CArtifactInstance * inst)
|
|
|
|
{
|
2012-05-12 17:59:32 +00:00
|
|
|
|
2012-05-13 14:51:13 +00:00
|
|
|
return 0.0;
|
|
|
|
}
|
2012-05-12 17:59:32 +00:00
|
|
|
|
2012-05-13 14:51:13 +00:00
|
|
|
void initNet(FANN::neural_net & ret)
|
|
|
|
{
|
|
|
|
const float learning_rate = 0.7f;
|
|
|
|
const unsigned int num_layers = 3;
|
|
|
|
const unsigned int num_input = 2;
|
|
|
|
const unsigned int num_hidden = 3;
|
|
|
|
const unsigned int num_output = 1;
|
|
|
|
const float desired_error = 0.001f;
|
|
|
|
const unsigned int max_iterations = 300000;
|
|
|
|
const unsigned int iterations_between_reports = 1000;
|
|
|
|
|
|
|
|
ret.create_standard(num_layers, num_input, num_hidden, num_output);
|
|
|
|
|
|
|
|
ret.set_learning_rate(learning_rate);
|
|
|
|
|
|
|
|
ret.set_activation_steepness_hidden(1.0);
|
|
|
|
ret.set_activation_steepness_output(1.0);
|
|
|
|
|
|
|
|
ret.set_activation_function_hidden(FANN::SIGMOID_SYMMETRIC_STEPWISE);
|
|
|
|
ret.set_activation_function_output(FANN::SIGMOID_SYMMETRIC_STEPWISE);
|
|
|
|
|
|
|
|
ret.randomize_weights(0.0, 1.0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SSNRun()
|
|
|
|
{
|
|
|
|
auto availableArts = genArts();
|
|
|
|
std::vector<std::pair<CArtifactInstance *, double> > artNotes;
|
|
|
|
|
|
|
|
TArtSet setL, setR;
|
|
|
|
|
|
|
|
FANN::neural_net network;
|
|
|
|
initNet(network);
|
|
|
|
|
|
|
|
for(int i=0; i<availableArts.size(); ++i)
|
|
|
|
{
|
|
|
|
artNotes.push_back(std::make_pair(availableArts[i], runSSN(network, availableArts[i])));
|
|
|
|
}
|
|
|
|
boost::range::sort(artNotes,
|
|
|
|
[](const std::pair<CArtifactInstance *, double> & a1, const std::pair<CArtifactInstance *, double> & a2)
|
|
|
|
{return a1.second > a2.second;});
|
|
|
|
|
|
|
|
//pick best arts into setL
|
|
|
|
BOOST_FOREACH(auto & ap, artNotes)
|
|
|
|
{
|
|
|
|
auto art = ap.first;
|
|
|
|
BOOST_FOREACH(auto slot, art->artType->possibleSlots)
|
|
|
|
{
|
|
|
|
if(setL.find(slot) != setL.end())
|
|
|
|
{
|
|
|
|
setL[slot] = art;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//evaluate
|
|
|
|
double result = cmpArtSets(setL, setR);
|
2012-05-12 17:59:32 +00:00
|
|
|
}
|
|
|
|
|
2011-10-23 13:53:37 +00:00
|
|
|
int main(int argc, char **argv)
|
2011-09-27 21:54:40 +00:00
|
|
|
{
|
2011-10-20 23:29:32 +00:00
|
|
|
std::cout << "VCMI Odpalarka\nMy path: " << argv[0] << std::endl;
|
|
|
|
|
|
|
|
po::options_description opts("Allowed options");
|
|
|
|
opts.add_options()
|
2011-11-10 09:21:27 +00:00
|
|
|
("help,h", "Display help and exit")
|
|
|
|
("aiLeft,l", po::value<std::string>()->default_value("StupidAI"), "Left AI path")
|
|
|
|
("aiRight,r", po::value<std::string>()->default_value("StupidAI"), "Right AI path")
|
2012-05-12 17:59:32 +00:00
|
|
|
("battle,b", po::value<std::string>()->default_value("pliczek.ssnb"), "Duel file path")
|
2011-11-14 17:52:09 +00:00
|
|
|
("resultsOut,o", po::value<std::string>()->default_value("./results.txt"), "Output file when results will be appended")
|
2011-11-10 09:21:27 +00:00
|
|
|
("logsDir,d", po::value<std::string>()->default_value("."), "Directory where log files will be created")
|
2011-10-20 23:29:32 +00:00
|
|
|
("visualization,v", "Runs a client to display a visualization of battle");
|
|
|
|
|
|
|
|
|
2011-11-10 09:21:27 +00:00
|
|
|
try
|
2011-10-20 23:29:32 +00:00
|
|
|
{
|
2011-11-10 09:21:27 +00:00
|
|
|
po::variables_map vm;
|
|
|
|
po::store(po::parse_command_line(argc, argv, opts), vm);
|
|
|
|
po::notify(vm);
|
|
|
|
|
|
|
|
if(vm.count("help"))
|
2011-10-20 23:29:32 +00:00
|
|
|
{
|
2011-11-10 09:21:27 +00:00
|
|
|
opts.print(std::cout);
|
|
|
|
prog_help();
|
|
|
|
return 0;
|
2011-10-20 23:29:32 +00:00
|
|
|
}
|
2011-11-10 09:21:27 +00:00
|
|
|
|
|
|
|
leftAI = vm["aiLeft"].as<std::string>();
|
|
|
|
rightAI = vm["aiRight"].as<std::string>();
|
|
|
|
battle = vm["battle"].as<std::string>();
|
|
|
|
results = vm["resultsOut"].as<std::string>();
|
|
|
|
logsDir = vm["logsDir"].as<std::string>();
|
|
|
|
withVisualization = vm.count("visualization");
|
2011-10-20 23:29:32 +00:00
|
|
|
}
|
2011-11-10 09:21:27 +00:00
|
|
|
catch(std::exception &e)
|
2011-10-20 23:29:32 +00:00
|
|
|
{
|
2011-11-10 09:21:27 +00:00
|
|
|
std::cerr << "Failure during parsing command-line options:\n" << e.what() << std::endl;
|
|
|
|
exit(1);
|
2011-10-20 23:29:32 +00:00
|
|
|
}
|
|
|
|
|
2011-11-10 09:21:27 +00:00
|
|
|
std::cout << "Config:\n" << leftAI << " vs " << rightAI << " on " << battle << std::endl;
|
|
|
|
|
|
|
|
if(leftAI.empty() || rightAI.empty() || battle.empty())
|
2011-10-20 23:29:32 +00:00
|
|
|
{
|
2011-11-10 09:21:27 +00:00
|
|
|
std::cerr << "I wasn't able to retreive names of AI or battles. Ending.\n";
|
|
|
|
return 1;
|
2011-10-20 23:29:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-05-12 17:59:32 +00:00
|
|
|
runnername =
|
2011-10-01 15:07:07 +00:00
|
|
|
#ifdef _WIN32
|
|
|
|
"VCMI_BattleAiHost.exe"
|
|
|
|
#else
|
|
|
|
"./vcmirunner"
|
|
|
|
#endif
|
|
|
|
;
|
2012-05-12 17:59:32 +00:00
|
|
|
servername =
|
2011-10-01 15:07:07 +00:00
|
|
|
#ifdef _WIN32
|
|
|
|
"VCMI_server.exe"
|
|
|
|
#else
|
|
|
|
"./vcmiserver"
|
|
|
|
#endif
|
2011-10-06 20:55:19 +00:00
|
|
|
;
|
|
|
|
|
2012-05-12 17:59:32 +00:00
|
|
|
|
|
|
|
VLC = new LibClasses();
|
|
|
|
VLC->init();
|
2011-11-10 09:21:27 +00:00
|
|
|
|
2012-05-12 17:59:32 +00:00
|
|
|
SSNRun();
|
2011-09-29 21:53:39 +00:00
|
|
|
|
2011-09-27 21:54:40 +00:00
|
|
|
return EXIT_SUCCESS;
|
|
|
|
}
|