1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

[programming challenge, SSN] today's changes

This commit is contained in:
mateuszb 2012-05-12 17:59:32 +00:00
parent d853bea6f4
commit 2f74224a34
12 changed files with 188 additions and 49 deletions

View File

@ -68,6 +68,7 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<OutDir>$(SolutionDir)</OutDir>
<IntDir>$(Configuration)\</IntDir>
<LibraryPath>$(SolutionDir);$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<OutDir>$(SolutionDir)</OutDir>
@ -76,6 +77,7 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RD|Win32'">
<OutDir>$(SolutionDir)$(Configuration)\bin\</OutDir>
<IntDir>$(Configuration)\</IntDir>
<LibraryPath>$(SolutionDir)$(SolutionDir)..\libs;\$(PlatformShortName);$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RD|x64'">
<OutDir>$(SolutionDir)$(Configuration)\bin\</OutDir>
@ -85,18 +87,24 @@
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>StdInc.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>VCMI_lib.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>StdInc.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>VCMI_lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='RD|Win32'">
@ -105,11 +113,14 @@
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>StdInc.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>VCMI_lib.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='RD|x64'">
@ -118,15 +129,27 @@
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>StdInc.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>VCMI_lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="main.cpp" />
<ClCompile Include="StdInc.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='RD|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='RD|x64'">Create</PrecompiledHeader>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="StdInc.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">

View File

@ -1,9 +1,14 @@
//#include "../global.h"
#include <boost/thread.hpp>
#include <boost/bind.hpp>
#include <boost/program_options.hpp>
#include "StdInc.h"
#include "../lib/VCMI_Lib.h"
namespace po = boost::program_options;
std::string leftAI, rightAI, battle, results, logsDir;
bool withVisualization = false;
std::string servername;
std::string runnername;
extern DLL_EXPORT LibClasses * VLC;
std::string addQuotesIfNeeded(const std::string &s)
{
if(s.find_first_of(' ') != std::string::npos)
@ -33,6 +38,84 @@ void runCommand(const std::string &command, const std::string &name, const std::
boost::thread tt(boost::bind(std::system, cmd.c_str()));
}
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;
}
void SSNRun()
{
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));
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);
}
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();
}
//lewa strona z art 0.9
//bez artefaktow -0.41
//prawa strona z art. -0.926
dp.sides[0].artifacts[Arts::LEFT_HAND] = artinst;
auto battleOutcome = playBattle(dp);
int g = 4;
}
int main(int argc, char **argv)
{
std::cout << "VCMI Odpalarka\nMy path: " << argv[0] << std::endl;
@ -42,13 +125,11 @@ int main(int argc, char **argv)
("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")
("battle,b", po::value<std::string>()->default_value("b1.json"), "Duel file path")
("battle,b", po::value<std::string>()->default_value("pliczek.ssnb"), "Duel file path")
("resultsOut,o", po::value<std::string>()->default_value("./results.txt"), "Output file when results will be appended")
("logsDir,d", po::value<std::string>()->default_value("."), "Directory where log files will be created")
("visualization,v", "Runs a client to display a visualization of battle");
std::string leftAI, rightAI, battle, results, logsDir;
bool withVisualization = false;
try
{
@ -86,14 +167,14 @@ int main(int argc, char **argv)
std::string runnername =
runnername =
#ifdef _WIN32
"VCMI_BattleAiHost.exe"
#else
"./vcmirunner"
#endif
;
std::string servername =
servername =
#ifdef _WIN32
"VCMI_server.exe"
#else
@ -101,22 +182,11 @@ int main(int argc, char **argv)
#endif
;
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;
VLC = new LibClasses();
VLC->init();
boost::thread t(boost::bind(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"));
}
SSNRun();
//boost::this_thread::sleep(boost::posix_time::seconds(5));
t.join();
return EXIT_SUCCESS;
}

View File

@ -59,7 +59,7 @@ struct CheckTime
//all ms
const int PROCESS_INFO_TIME = 5;
const int MAKE_DECIDION_TIME = 150;
const int MEASURE_MARGIN = 3;
const int MEASURE_MARGIN = 3000000;
const int HANGUP_TIME = 250;
const int CONSTRUCT_TIME = 50;
const int STARTUP_TIME = 100;

View File

@ -23,9 +23,8 @@ struct ArtifactLocation;
class DLL_EXPORT CArtifact : public CBonusSystemNode //container for artifacts
{
protected:
std::string name, description; //set if custom
public:
std::string name, description; //set if custom
enum EartClass {ART_SPECIAL=1, ART_TREASURE=2, ART_MINOR=4, ART_MAJOR=8, ART_RELIC=16}; //artifact classes
const std::string &Name() const; //getter
const std::string &Description() const; //getter
@ -56,10 +55,9 @@ public:
class DLL_EXPORT CArtifactInstance : public CBonusSystemNode
{
protected:
public:
void init();
CArtifactInstance(CArtifact *Art);
public:
CArtifactInstance();
ConstTransitivePtr<CArtifact> artType;

View File

@ -983,6 +983,11 @@ void CGameState::init( StartInfo * si, ui32 checksum, int Seed )
h->spells.insert(spell);
}
BOOST_FOREACH(auto &parka, ss.artifacts)
{
h->putArtifact(parka.first, parka.second);
}
typedef const std::pair<si32, si8> &TSecSKill;
BOOST_FOREACH(TSecSKill secSkill, ss.heroSecSkills)
h->setSecSkillLevel((CGHeroInstance::SecondarySkill)secSkill.first, secSkill.second, 1);

View File

@ -281,9 +281,9 @@ struct DLL_EXPORT CPathsInfo
struct DLL_EXPORT DuelParameters
{
si32 terType, bfieldType;
struct SideSettings
struct DLL_EXPORT SideSettings
{
struct StackSettings
struct DLL_EXPORT StackSettings
{
si32 type;
si32 count;
@ -298,13 +298,14 @@ struct DLL_EXPORT DuelParameters
si32 heroId; //-1 if none
std::vector<si32> heroPrimSkills; //may be empty
std::map<int, CArtifactInstance*> artifacts;
std::vector<std::pair<si32, si8> > heroSecSkills; //may be empty; pairs <id, level>, level [0-3]
std::set<si32> spells;
SideSettings();
template <typename Handler> void serialize(Handler &h, const int version)
{
h & stacks & heroId & heroPrimSkills & spells;
h & stacks & heroId & heroPrimSkills & artifacts & heroSecSkills & spells;
}
} sides[2];

View File

@ -28,6 +28,17 @@
int CBonusSystemNode::treeChanged = 1;
const bool CBonusSystemNode::cachingEnabled = false;
DLL_EXPORT std::string bonusTypeToString(int type)
{
BOOST_FOREACH(auto &p, bonusNameMap)
{
if(p.second == type)
return p.first;
}
return "UNKNOWN BONUS";
}
BonusList::BonusList(bool BelongsToTree /* =false */) : belongsToTree(BelongsToTree)
{

View File

@ -833,6 +833,7 @@ namespace Selector
}
extern DLL_EXPORT const std::map<std::string, int> bonusNameMap;
DLL_EXPORT std::string bonusTypeToString(int type);
// BonusList template that requires full interface of CBonusSystemNode
template <class InputIterator>
@ -859,3 +860,5 @@ namespace boost
typedef std::vector<Bonus*>::const_iterator type;
};
}

View File

@ -332,7 +332,7 @@ void CGameHandler::startBattle( const CArmedInstance *armies[2], int3 tile, cons
runBattle();
}
void CGameHandler::endBattle(int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2)
int CGameHandler::endBattle( int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2 )
{
bool duel = gs->initialOpts->mode == StartInfo::DUEL;
BattleResultsApplied resultsApplied;
@ -381,8 +381,20 @@ void CGameHandler::endBattle(int3 tile, const CGHeroInstance *hero1, const CGHer
}
}
const CArmedInstance *armed = gs->curB->belligerents[battleResult.data->winner];
int winnerArmyAfterBattle = 0;
int winnerArmyBeforeBattle = 0;
BOOST_FOREACH(auto &slot, armed->Slots())
{
winnerArmyBeforeBattle += slot.second->type->AIValue * slot.second->count;
assert(winnerArmyBeforeBattle >= 0);
}
sendAndApply(battleResult.data);
//Eagle Eye secondary skill handling
if(cs.spells.size())
{
@ -459,12 +471,12 @@ void CGameHandler::endBattle(int3 tile, const CGHeroInstance *hero1, const CGHer
addToSlot(StackLocation(winnerHero, necroSlot), raisedStack.type, raisedStack.count);
}
int casualtiesPoints = 0;
if(duel)
{
CSaveFile resultFile(LOGS_DIR + "/result.vdrst");
resultFile << *battleResult.data;
int casualtiesPoints = 0;
tlog0 << boost::format("Winner side %d\nWinner casualties:\n") % (int)battleResult.data->winner;
for(std::map<ui32,si32>::const_iterator i = battleResult.data->casualties[battleResult.data->winner].begin(); i != battleResult.data->casualties[battleResult.data->winner].end(); i++)
{
@ -487,8 +499,18 @@ void CGameHandler::endBattle(int3 tile, const CGHeroInstance *hero1, const CGHer
sendAndApply(&resultsApplied);
winnerArmyAfterBattle = winnerArmyBeforeBattle - casualtiesPoints;
if(duel)
return;
{
double ratioKept = (double)winnerArmyAfterBattle / (double)winnerArmyBeforeBattle;
int ret = ratioKept * 1000000;
if(battleResult.data->winner)
ret *= -1;
return ret;
}
if(visitObjectAfterVictory && winnerHero == hero1)
{
@ -517,6 +539,8 @@ void CGameHandler::endBattle(int3 tile, const CGHeroInstance *hero1, const CGHer
sendAndApply(&sah);
}
return 0;
}
void CGameHandler::afterBattleCallback() //object interaction after leveling up is done
@ -4984,7 +5008,7 @@ bool CGameHandler::swapStacks(const StackLocation &sl1, const StackLocation &sl2
}
}
void CGameHandler::runBattle()
int CGameHandler::runBattle()
{
assert(gs->curB);
//TODO: pre-tactic stuff, call scripts etc.
@ -5203,7 +5227,7 @@ void CGameHandler::runBattle()
}
}
endBattle(gs->curB->tile, gs->curB->heroes[0], gs->curB->heroes[1]);
return endBattle(gs->curB->tile, gs->curB->heroes[0], gs->curB->heroes[1]);
}
void CGameHandler::giveHeroArtifact(const CGHeroInstance *h, const CArtifactInstance *a, int pos)

View File

@ -113,7 +113,7 @@ public:
void giveSpells(const CGTownInstance *t, const CGHeroInstance *h);
int moveStack(int stack, THex dest); //returned value - travelled distance
void startBattle(const CArmedInstance *armies[2], int3 tile, const CGHeroInstance *heroes[2], bool creatureBank, boost::function<void(BattleResult*)> cb, const CGTownInstance *town = NULL); //use hero=NULL for no hero
void runBattle();
int runBattle();
void checkLossVictory(ui8 player);
void winLoseHandle(ui8 players=255); //players: bit field - colours of players to be checked; default: all
void getLossVicMessage(ui8 player, ui8 standard, bool victory, InfoWindow &out) const;
@ -125,7 +125,7 @@ public:
//
void disqualifyPlayer(int side);
void endBattle(int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2); //ends battle
int endBattle(int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2); //ends battle
void prepareAttack(BattleAttack &bat, const CStack *att, const CStack *def, int distance, int targetHex); //distance - number of hexes travelled before attacking
void applyBattleEffects(BattleAttack &bat, const CStack *att, const CStack *def, int distance, bool secondary); //damage, drain life & fire shield
void checkForBattleEnd( std::vector<CStack*> &stacks );

View File

@ -668,7 +668,7 @@ void CVCMIServer::startDuel(const std::string &battle, const std::string &leftAI
*gh->gameLog << battle << leftAI << rightAI << ui8('$');
tlog0 << "Starting battle!\n";
gh->runBattle();
auto battleOut = gh->runBattle();
tlog0 << "Battle over!\n";
tlog0 << "Waiting for connections to close\n";
@ -687,7 +687,8 @@ void CVCMIServer::startDuel(const std::string &battle, const std::string &leftAI
tlog0 << "Removed gh!\n";
tlog0 << "Dying...\n";
exit(0);
exit(battleOut);
}
#ifndef __GNUC__
@ -711,15 +712,18 @@ int main(int argc, char** argv)
{
io_service io_service;
CVCMIServer server;
if(argc == 6 || argc == 7)
if(argc != 2)
{
RESULTS_PATH = argv[4];
tlog1 << "Results path: " << RESULTS_PATH << std::endl;
tlog1 << "Logs path: " << RESULTS_PATH << std::endl;
server.startDuel(argv[1], argv[2], argv[3], argc-3);
if(argc == 6 || argc == 7)
{
RESULTS_PATH = argv[4];
tlog1 << "Results path: " << RESULTS_PATH << std::endl;
tlog1 << "Logs path: " << RESULTS_PATH << std::endl;
server.startDuel(argv[1], argv[2], argv[3], argc-3);
}
else
server.startDuel("b1.json", "StupidAI", "StupidAI", 2);
}
else
server.startDuel("b1.json", "StupidAI", "StupidAI", 2);
while(!end2)
{

View File

@ -243,8 +243,8 @@ bool MakeAction::applyGh( CGameHandler *gh )
if(gh->connections[b->sides[b->tacticsSide]] != c)
ERROR_AND_RETURN;
}
else if(gh->connections[b->getStack(b->activeStack)->owner] != c)
ERROR_AND_RETURN;
// else if(gh->connections[b->getStack(b->activeStack)->owner] != c)
// ERROR_AND_RETURN;
return gh->makeBattleAction(ba);
}