diff --git a/AI/CMakeLists.txt b/AI/CMakeLists.txt index 6e9786950..9b9381d5c 100644 --- a/AI/CMakeLists.txt +++ b/AI/CMakeLists.txt @@ -29,3 +29,4 @@ add_subdirectory(BattleAI) add_subdirectory(StupidAI) add_subdirectory(EmptyAI) add_subdirectory(VCAI) +add_subdirectory(Nullkiller) diff --git a/AI/Nullkiller/VCAI.cpp b/AI/Nullkiller/AIGateway.cpp similarity index 83% rename from AI/Nullkiller/VCAI.cpp rename to AI/Nullkiller/AIGateway.cpp index 5b2e6798f..23cb0c313 100644 --- a/AI/Nullkiller/VCAI.cpp +++ b/AI/Nullkiller/AIGateway.cpp @@ -1,5 +1,5 @@ /* - * VCAI.cpp, part of VCMI engine + * AIGateway.cpp, part of VCMI engine * * Authors: listed in file AUTHORS in main folder * @@ -20,7 +20,7 @@ #include "../../lib/serializer/BinarySerializer.h" #include "../../lib/serializer/BinaryDeserializer.h" -#include "VCAI.h" +#include "AIGateway.h" #include "Goals/Goals.h" class CGVisitableOPW; @@ -29,12 +29,12 @@ const float SAFE_ATTACK_CONSTANT = 1.2; //one thread may be turn of AI and another will be handling a side effect for AI2 boost::thread_specific_ptr cb; -boost::thread_specific_ptr ai; +boost::thread_specific_ptr ai; //helper RAII to manage global ai/cb ptrs struct SetGlobalState { - SetGlobalState(VCAI * AI) + SetGlobalState(AIGateway * AI) { assert(!ai.get()); assert(!cb.get()); @@ -57,7 +57,7 @@ struct SetGlobalState #define NET_EVENT_HANDLER SET_GLOBAL_STATE(this) #define MAKING_TURN SET_GLOBAL_STATE(this) -VCAI::VCAI() +AIGateway::AIGateway() { LOG_TRACE(logAi); makingTurn = nullptr; @@ -66,20 +66,20 @@ VCAI::VCAI() nullkiller.reset(new Nullkiller()); } -VCAI::~VCAI() +AIGateway::~AIGateway() { LOG_TRACE(logAi); finish(); nullkiller.reset(); } -void VCAI::availableCreaturesChanged(const CGDwelling * town) +void AIGateway::availableCreaturesChanged(const CGDwelling * town) { LOG_TRACE(logAi); NET_EVENT_HANDLER; } -void VCAI::heroMoved(const TryMoveHero & details) +void AIGateway::heroMoved(const TryMoveHero & details) { LOG_TRACE(logAi); NET_EVENT_HANDLER; @@ -120,43 +120,43 @@ void VCAI::heroMoved(const TryMoveHero & details) } } -void VCAI::heroInGarrisonChange(const CGTownInstance * town) +void AIGateway::heroInGarrisonChange(const CGTownInstance * town) { LOG_TRACE(logAi); NET_EVENT_HANDLER; } -void VCAI::centerView(int3 pos, int focusTime) +void AIGateway::centerView(int3 pos, int focusTime) { LOG_TRACE_PARAMS(logAi, "focusTime '%i'", focusTime); NET_EVENT_HANDLER; } -void VCAI::artifactMoved(const ArtifactLocation & src, const ArtifactLocation & dst) +void AIGateway::artifactMoved(const ArtifactLocation & src, const ArtifactLocation & dst) { LOG_TRACE(logAi); NET_EVENT_HANDLER; } -void VCAI::artifactAssembled(const ArtifactLocation & al) +void AIGateway::artifactAssembled(const ArtifactLocation & al) { LOG_TRACE(logAi); NET_EVENT_HANDLER; } -void VCAI::showTavernWindow(const CGObjectInstance * townOrTavern) +void AIGateway::showTavernWindow(const CGObjectInstance * townOrTavern) { LOG_TRACE(logAi); NET_EVENT_HANDLER; } -void VCAI::showThievesGuildWindow(const CGObjectInstance * obj) +void AIGateway::showThievesGuildWindow(const CGObjectInstance * obj) { LOG_TRACE(logAi); NET_EVENT_HANDLER; } -void VCAI::playerBlocked(int reason, bool start) +void AIGateway::playerBlocked(int reason, bool start) { LOG_TRACE_PARAMS(logAi, "reason '%i', start '%i'", reason % start); NET_EVENT_HANDLER; @@ -167,19 +167,19 @@ void VCAI::playerBlocked(int reason, bool start) status.setMove(start); } -void VCAI::showPuzzleMap() +void AIGateway::showPuzzleMap() { LOG_TRACE(logAi); NET_EVENT_HANDLER; } -void VCAI::showShipyardDialog(const IShipyard * obj) +void AIGateway::showShipyardDialog(const IShipyard * obj) { LOG_TRACE(logAi); NET_EVENT_HANDLER; } -void VCAI::gameOver(PlayerColor player, const EVictoryLossCheckResult & victoryLossCheckResult) +void AIGateway::gameOver(PlayerColor player, const EVictoryLossCheckResult & victoryLossCheckResult) { LOG_TRACE_PARAMS(logAi, "victoryLossCheckResult '%s'", victoryLossCheckResult.messageToSelf); NET_EVENT_HANDLER; @@ -192,37 +192,37 @@ void VCAI::gameOver(PlayerColor player, const EVictoryLossCheckResult & victoryL { if(victoryLossCheckResult.victory()) { - logAi->debug("VCAI: Player %d (%s) won. I won! Incredible!", player, player.getStr()); + logAi->debug("AIGateway: Player %d (%s) won. I won! Incredible!", player, player.getStr()); logAi->debug("Turn nr %d", myCb->getDate()); } else { - logAi->debug("VCAI: Player %d (%s) lost. It's me. What a disappointment! :(", player, player.getStr()); + logAi->debug("AIGateway: Player %d (%s) lost. It's me. What a disappointment! :(", player, player.getStr()); } finish(); } } -void VCAI::artifactPut(const ArtifactLocation & al) +void AIGateway::artifactPut(const ArtifactLocation & al) { LOG_TRACE(logAi); NET_EVENT_HANDLER; } -void VCAI::artifactRemoved(const ArtifactLocation & al) +void AIGateway::artifactRemoved(const ArtifactLocation & al) { LOG_TRACE(logAi); NET_EVENT_HANDLER; } -void VCAI::artifactDisassembled(const ArtifactLocation & al) +void AIGateway::artifactDisassembled(const ArtifactLocation & al) { LOG_TRACE(logAi); NET_EVENT_HANDLER; } -void VCAI::heroVisit(const CGHeroInstance * visitor, const CGObjectInstance * visitedObj, bool start) +void AIGateway::heroVisit(const CGHeroInstance * visitor, const CGObjectInstance * visitedObj, bool start) { LOG_TRACE_PARAMS(logAi, "start '%i'; obj '%s'", start % (visitedObj ? visitedObj->getObjectName() : std::string("n/a"))); NET_EVENT_HANDLER; @@ -235,28 +235,27 @@ void VCAI::heroVisit(const CGHeroInstance * visitor, const CGObjectInstance * vi status.heroVisit(visitedObj, start); } -void VCAI::availableArtifactsChanged(const CGBlackMarket * bm) +void AIGateway::availableArtifactsChanged(const CGBlackMarket * bm) { LOG_TRACE(logAi); NET_EVENT_HANDLER; } -void VCAI::heroVisitsTown(const CGHeroInstance * hero, const CGTownInstance * town) +void AIGateway::heroVisitsTown(const CGHeroInstance * hero, const CGTownInstance * town) { LOG_TRACE(logAi); NET_EVENT_HANDLER; } -void VCAI::tileHidden(const std::unordered_set & pos) +void AIGateway::tileHidden(const std::unordered_set & pos) { LOG_TRACE(logAi); NET_EVENT_HANDLER; nullkiller->memory->removeInvisibleObjects(myCb.get()); - clearPathsInfo(); } -void VCAI::tileRevealed(const std::unordered_set & pos) +void AIGateway::tileRevealed(const std::unordered_set & pos) { LOG_TRACE(logAi); NET_EVENT_HANDLER; @@ -265,11 +264,9 @@ void VCAI::tileRevealed(const std::unordered_set & pos) for(const CGObjectInstance * obj : myCb->getVisitableObjs(tile)) addVisitableObj(obj); } - - clearPathsInfo(); } -void VCAI::heroExchangeStarted(ObjectInstanceID hero1, ObjectInstanceID hero2, QueryID query) +void AIGateway::heroExchangeStarted(ObjectInstanceID hero1, ObjectInstanceID hero2, QueryID query) { LOG_TRACE(logAi); NET_EVENT_HANDLER; @@ -305,31 +302,31 @@ void VCAI::heroExchangeStarted(ObjectInstanceID hero1, ObjectInstanceID hero2, Q }); } -void VCAI::heroPrimarySkillChanged(const CGHeroInstance * hero, int which, si64 val) +void AIGateway::heroPrimarySkillChanged(const CGHeroInstance * hero, int which, si64 val) { LOG_TRACE_PARAMS(logAi, "which '%i', val '%i'", which % val); NET_EVENT_HANDLER; } -void VCAI::showRecruitmentDialog(const CGDwelling * dwelling, const CArmedInstance * dst, int level) +void AIGateway::showRecruitmentDialog(const CGDwelling * dwelling, const CArmedInstance * dst, int level) { LOG_TRACE_PARAMS(logAi, "level '%i'", level); NET_EVENT_HANDLER; } -void VCAI::heroMovePointsChanged(const CGHeroInstance * hero) +void AIGateway::heroMovePointsChanged(const CGHeroInstance * hero) { LOG_TRACE(logAi); NET_EVENT_HANDLER; } -void VCAI::garrisonsChanged(ObjectInstanceID id1, ObjectInstanceID id2) +void AIGateway::garrisonsChanged(ObjectInstanceID id1, ObjectInstanceID id2) { LOG_TRACE(logAi); NET_EVENT_HANDLER; } -void VCAI::newObject(const CGObjectInstance * obj) +void AIGateway::newObject(const CGObjectInstance * obj) { LOG_TRACE(logAi); NET_EVENT_HANDLER; @@ -339,7 +336,7 @@ void VCAI::newObject(const CGObjectInstance * obj) //to prevent AI from accessing objects that got deleted while they became invisible (Cover of Darkness, enemy hero moved etc.) below code allows AI to know deletion of objects out of sight //see: RemoveObject::applyFirstCl, to keep AI "not cheating" do not use advantage of this and use this function just to prevent crashes -void VCAI::objectRemoved(const CGObjectInstance * obj) +void AIGateway::objectRemoved(const CGObjectInstance * obj) { LOG_TRACE(logAi); NET_EVENT_HANDLER; @@ -355,37 +352,37 @@ void VCAI::objectRemoved(const CGObjectInstance * obj) } } -void VCAI::showHillFortWindow(const CGObjectInstance * object, const CGHeroInstance * visitor) +void AIGateway::showHillFortWindow(const CGObjectInstance * object, const CGHeroInstance * visitor) { LOG_TRACE(logAi); NET_EVENT_HANDLER; } -void VCAI::playerBonusChanged(const Bonus & bonus, bool gain) +void AIGateway::playerBonusChanged(const Bonus & bonus, bool gain) { LOG_TRACE_PARAMS(logAi, "gain '%i'", gain); NET_EVENT_HANDLER; } -void VCAI::heroCreated(const CGHeroInstance * h) +void AIGateway::heroCreated(const CGHeroInstance * h) { LOG_TRACE(logAi); NET_EVENT_HANDLER; } -void VCAI::advmapSpellCast(const CGHeroInstance * caster, int spellID) +void AIGateway::advmapSpellCast(const CGHeroInstance * caster, int spellID) { LOG_TRACE_PARAMS(logAi, "spellID '%i", spellID); NET_EVENT_HANDLER; } -void VCAI::showInfoDialog(const std::string & text, const std::vector & components, int soundID) +void AIGateway::showInfoDialog(const std::string & text, const std::vector & components, int soundID) { LOG_TRACE_PARAMS(logAi, "soundID '%i'", soundID); NET_EVENT_HANDLER; } -void VCAI::requestRealized(PackageApplied * pa) +void AIGateway::requestRealized(PackageApplied * pa) { LOG_TRACE(logAi); NET_EVENT_HANDLER; @@ -404,31 +401,31 @@ void VCAI::requestRealized(PackageApplied * pa) } } -void VCAI::receivedResource() +void AIGateway::receivedResource() { LOG_TRACE(logAi); NET_EVENT_HANDLER; } -void VCAI::showUniversityWindow(const IMarket * market, const CGHeroInstance * visitor) +void AIGateway::showUniversityWindow(const IMarket * market, const CGHeroInstance * visitor) { LOG_TRACE(logAi); NET_EVENT_HANDLER; } -void VCAI::heroManaPointsChanged(const CGHeroInstance * hero) +void AIGateway::heroManaPointsChanged(const CGHeroInstance * hero) { LOG_TRACE(logAi); NET_EVENT_HANDLER; } -void VCAI::heroSecondarySkillChanged(const CGHeroInstance * hero, int which, int val) +void AIGateway::heroSecondarySkillChanged(const CGHeroInstance * hero, int which, int val) { LOG_TRACE_PARAMS(logAi, "which '%d', val '%d'", which % val); NET_EVENT_HANDLER; } -void VCAI::battleResultsApplied() +void AIGateway::battleResultsApplied() { LOG_TRACE(logAi); NET_EVENT_HANDLER; @@ -436,7 +433,7 @@ void VCAI::battleResultsApplied() status.setBattle(NO_BATTLE); } -void VCAI::objectPropertyChanged(const SetObjectProperty * sop) +void AIGateway::objectPropertyChanged(const SetObjectProperty * sop) { LOG_TRACE(logAi); NET_EVENT_HANDLER; @@ -465,32 +462,32 @@ void VCAI::objectPropertyChanged(const SetObjectProperty * sop) } } -void VCAI::buildChanged(const CGTownInstance * town, BuildingID buildingID, int what) +void AIGateway::buildChanged(const CGTownInstance * town, BuildingID buildingID, int what) { LOG_TRACE_PARAMS(logAi, "what '%i'", what); NET_EVENT_HANDLER; } -void VCAI::heroBonusChanged(const CGHeroInstance * hero, const Bonus & bonus, bool gain) +void AIGateway::heroBonusChanged(const CGHeroInstance * hero, const Bonus & bonus, bool gain) { LOG_TRACE_PARAMS(logAi, "gain '%i'", gain); NET_EVENT_HANDLER; } -void VCAI::showMarketWindow(const IMarket * market, const CGHeroInstance * visitor) +void AIGateway::showMarketWindow(const IMarket * market, const CGHeroInstance * visitor) { LOG_TRACE(logAi); NET_EVENT_HANDLER; } -void VCAI::showWorldViewEx(const std::vector & objectPositions) +void AIGateway::showWorldViewEx(const std::vector & objectPositions) { //TODO: AI support for ViewXXX spell LOG_TRACE(logAi); NET_EVENT_HANDLER; } -void VCAI::init(std::shared_ptr CB) +void AIGateway::init(std::shared_ptr CB) { LOG_TRACE(logAi); myCb = CB; @@ -506,15 +503,15 @@ void VCAI::init(std::shared_ptr CB) retrieveVisitableObjs(); } -void VCAI::yourTurn() +void AIGateway::yourTurn() { LOG_TRACE(logAi); NET_EVENT_HANDLER; status.startedTurn(); - makingTurn = make_unique(&VCAI::makeTurn, this); + makingTurn = make_unique(&AIGateway::makeTurn, this); } -void VCAI::heroGotLevel(const CGHeroInstance * hero, PrimarySkill::PrimarySkill pskill, std::vector & skills, QueryID queryID) +void AIGateway::heroGotLevel(const CGHeroInstance * hero, PrimarySkill::PrimarySkill pskill, std::vector & skills, QueryID queryID) { LOG_TRACE_PARAMS(logAi, "queryID '%i'", queryID); NET_EVENT_HANDLER; @@ -532,7 +529,7 @@ void VCAI::heroGotLevel(const CGHeroInstance * hero, PrimarySkill::PrimarySkill }); } -void VCAI::commanderGotLevel(const CCommanderInstance * commander, std::vector skills, QueryID queryID) +void AIGateway::commanderGotLevel(const CCommanderInstance * commander, std::vector skills, QueryID queryID) { LOG_TRACE_PARAMS(logAi, "queryID '%i'", queryID); NET_EVENT_HANDLER; @@ -540,7 +537,7 @@ void VCAI::commanderGotLevel(const CCommanderInstance * commander, std::vector & components, QueryID askID, const int soundID, bool selection, bool cancel) +void AIGateway::showBlockingDialog(const std::string & text, const std::vector & components, QueryID askID, const int soundID, bool selection, bool cancel) { LOG_TRACE_PARAMS(logAi, "text '%s', askID '%i', soundID '%i', selection '%i', cancel '%i'", text % askID % soundID % selection % cancel); NET_EVENT_HANDLER; @@ -592,7 +589,8 @@ void VCAI::showBlockingDialog(const std::string & text, const std::vectorheroManager->getHeroRole(hero) != HeroRole::MAIN) + && (nullkiller->heroManager->getHeroRole(hero) != HeroRole::MAIN + || nullkiller->buildAnalyzer->getGoldPreasure() > MAX_GOLD_PEASURE)) { sel = 1; // for now lets pick gold from a chest. } @@ -601,7 +599,7 @@ void VCAI::showBlockingDialog(const std::string & text, const std::vector & objects) +void AIGateway::showMapObjectSelectDialog(QueryID askID, const Component & icon, const MetaString & title, const MetaString & description, const std::vector & objects) { NET_EVENT_HANDLER; status.addQuery(askID, "Map object select query"); requestActionASAP([=](){ answerQuery(askID, selectedObject.getNum()); }); } -void VCAI::saveGame(BinarySerializer & h, const int version) +void AIGateway::saveGame(BinarySerializer & h, const int version) { LOG_TRACE_PARAMS(logAi, "version '%i'", version); NET_EVENT_HANDLER; @@ -681,7 +679,7 @@ void VCAI::saveGame(BinarySerializer & h, const int version) serializeInternal(h, version); } -void VCAI::loadGame(BinaryDeserializer & h, const int version) +void AIGateway::loadGame(BinaryDeserializer & h, const int version) { LOG_TRACE_PARAMS(logAi, "version '%i'", version); //NET_EVENT_HANDLER; @@ -694,7 +692,7 @@ void VCAI::loadGame(BinaryDeserializer & h, const int version) serializeInternal(h, version); } -bool VCAI::makePossibleUpgrades(const CArmedInstance * obj) +bool AIGateway::makePossibleUpgrades(const CArmedInstance * obj) { if(!obj) return false; @@ -707,7 +705,7 @@ bool VCAI::makePossibleUpgrades(const CArmedInstance * obj) { UpgradeInfo ui; myCb->getUpgradeInfo(obj, SlotID(i), ui); - if(ui.oldID >= 0 && myCb->getResourceAmount().canAfford(ui.cost[0] * s->count)) + if(ui.oldID >= 0 && nullkiller->getFreeResources().canAfford(ui.cost[0] * s->count)) { myCb->upgradeCreature(obj, SlotID(i), ui.newID[0]); upgraded = true; @@ -719,7 +717,7 @@ bool VCAI::makePossibleUpgrades(const CArmedInstance * obj) return upgraded; } -void VCAI::makeTurn() +void AIGateway::makeTurn() { MAKING_TURN; @@ -727,7 +725,7 @@ void VCAI::makeTurn() logAi->info("Player %d (%s) starting turn, day %d", playerID, playerID.getStr(), day); boost::shared_lock gsLock(CGameState::mutex); - setThreadName("VCAI::makeTurn"); + setThreadName("AIGateway::makeTurn"); if(cb->getDate(Date::DAY_OF_WEEK) == 1) { @@ -776,7 +774,7 @@ void VCAI::makeTurn() endTurn(); } -void VCAI::performObjectInteraction(const CGObjectInstance * obj, HeroPtr h) +void AIGateway::performObjectInteraction(const CGObjectInstance * obj, HeroPtr h) { LOG_TRACE_PARAMS(logAi, "Hero %s and object %s at %s", h->name % obj->getObjectName() % obj->pos.toString()); switch(obj->ID) @@ -789,11 +787,11 @@ void VCAI::performObjectInteraction(const CGObjectInstance * obj, HeroPtr h) { makePossibleUpgrades(h.get()); - if(!nullkiller || !h->visitedTown->garrisonHero || !nullkiller->isHeroLocked(h->visitedTown->garrisonHero)) + if(!h->visitedTown->garrisonHero || !nullkiller->isHeroLocked(h->visitedTown->garrisonHero)) moveCreaturesToHero(h->visitedTown); - if(ai->nullkiller->heroManager->getHeroRole(h) == HeroRole::MAIN && !h->hasSpellbook() - && cb->getResourceAmount(Res::GOLD) >= GameConstants::SPELLBOOK_GOLD_COST) + if(nullkiller->heroManager->getHeroRole(h) == HeroRole::MAIN && !h->hasSpellbook() + && nullkiller->getFreeGold() >= GameConstants::SPELLBOOK_GOLD_COST) { if(h->visitedTown->hasBuilt(BuildingID::MAGES_GUILD_1)) cb->buyArtifact(h.get(), ArtifactID::SPELLBOOK); @@ -806,7 +804,7 @@ void VCAI::performObjectInteraction(const CGObjectInstance * obj, HeroPtr h) } } -void VCAI::moveCreaturesToHero(const CGTownInstance * t) +void AIGateway::moveCreaturesToHero(const CGTownInstance * t) { if(t->visitingHero && t->armedGarrison() && t->visitingHero->tempOwner == t->tempOwner) { @@ -814,7 +812,7 @@ void VCAI::moveCreaturesToHero(const CGTownInstance * t) } } -void VCAI::pickBestCreatures(const CArmedInstance * destinationArmy, const CArmedInstance * source) +void AIGateway::pickBestCreatures(const CArmedInstance * destinationArmy, const CArmedInstance * source) { const CArmedInstance * armies[] = {destinationArmy, source}; @@ -897,7 +895,7 @@ void VCAI::pickBestCreatures(const CArmedInstance * destinationArmy, const CArme //TODO - having now strongest possible army, we may want to think about arranging stacks } -void VCAI::pickBestArtifacts(const CGHeroInstance * h, const CGHeroInstance * other) +void AIGateway::pickBestArtifacts(const CGHeroInstance * h, const CGHeroInstance * other) { auto equipBest = [](const CGHeroInstance * h, const CGHeroInstance * otherh, bool giveStuffToFirstHero) -> void { @@ -996,7 +994,7 @@ void VCAI::pickBestArtifacts(const CGHeroInstance * h, const CGHeroInstance * ot equipBest(h, other, false); } -void VCAI::recruitCreatures(const CGDwelling * d, const CArmedInstance * recruiter) +void AIGateway::recruitCreatures(const CGDwelling * d, const CArmedInstance * recruiter) { //now used only for visited dwellings / towns, not BuyArmy goal for(int i = 0; i < d->creatures.size(); i++) @@ -1013,25 +1011,7 @@ void VCAI::recruitCreatures(const CGDwelling * d, const CArmedInstance * recruit } } -bool VCAI::isTileNotReserved(const CGHeroInstance * h, int3 t) const -{ - if(t.valid()) - { - auto obj = cb->getTopObj(t); - if(obj && vstd::contains(ai->reservedObjs, obj) - && vstd::contains(reservedHeroesMap, h) - && !vstd::contains(reservedHeroesMap.at(h), obj)) - return false; //do not capture object reserved by another hero - else - return true; - } - else - { - return false; - } -} - -bool VCAI::canRecruitAnyHero(const CGTownInstance * t) const +bool AIGateway::canRecruitAnyHero(const CGTownInstance * t) const { //TODO: make gathering gold, building tavern or conquering town (?) possible subgoals if(!t) @@ -1048,7 +1028,7 @@ bool VCAI::canRecruitAnyHero(const CGTownInstance * t) const return true; } -void VCAI::battleStart(const CCreatureSet * army1, const CCreatureSet * army2, int3 tile, const CGHeroInstance * hero1, const CGHeroInstance * hero2, bool side) +void AIGateway::battleStart(const CCreatureSet * army1, const CCreatureSet * army2, int3 tile, const CGHeroInstance * hero1, const CGHeroInstance * hero2, bool side) { NET_EVENT_HANDLER; assert(playerID > PlayerColor::PLAYER_LIMIT || status.getBattle() == UPCOMING_BATTLE); @@ -1058,7 +1038,7 @@ void VCAI::battleStart(const CCreatureSet * army1, const CCreatureSet * army2, i CAdventureAI::battleStart(army1, army2, tile, hero1, hero2, side); } -void VCAI::battleEnd(const BattleResult * br) +void AIGateway::battleEnd(const BattleResult * br) { NET_EVENT_HANDLER; assert(status.getBattle() == ONGOING_BATTLE); @@ -1069,30 +1049,13 @@ void VCAI::battleEnd(const BattleResult * br) CAdventureAI::battleEnd(br); } -void VCAI::waitTillFree() +void AIGateway::waitTillFree() { auto unlock = vstd::makeUnlockSharedGuard(CGameState::mutex); status.waitTillFree(); } -void VCAI::markHeroUnableToExplore(HeroPtr h) -{ - heroesUnableToExplore.insert(h); -} -void VCAI::markHeroAbleToExplore(HeroPtr h) -{ - vstd::erase_if_present(heroesUnableToExplore, h); -} -bool VCAI::isAbleToExplore(HeroPtr h) -{ - return !vstd::contains(heroesUnableToExplore, h); -} -void VCAI::clearPathsInfo() -{ - heroesUnableToExplore.clear(); -} - -void VCAI::retrieveVisitableObjs(std::vector & out, bool includeOwned) const +void AIGateway::retrieveVisitableObjs(std::vector & out, bool includeOwned) const { foreach_tile_pos([&](const int3 & pos) { @@ -1104,7 +1067,7 @@ void VCAI::retrieveVisitableObjs(std::vector & out, bo }); } -void VCAI::retrieveVisitableObjs() +void AIGateway::retrieveVisitableObjs() { foreach_tile_pos([&](const int3 & pos) { @@ -1116,7 +1079,7 @@ void VCAI::retrieveVisitableObjs() }); } -std::vector VCAI::getFlaggedObjects() const +std::vector AIGateway::getFlaggedObjects() const { std::vector ret; for(const CGObjectInstance * obj : nullkiller->memory->visitableObjs) @@ -1127,7 +1090,7 @@ std::vector VCAI::getFlaggedObjects() const return ret; } -void VCAI::addVisitableObj(const CGObjectInstance * obj) +void AIGateway::addVisitableObj(const CGObjectInstance * obj) { if(obj->ID == Obj::EVENT) return; @@ -1140,7 +1103,7 @@ void VCAI::addVisitableObj(const CGObjectInstance * obj) } } -HeroPtr VCAI::getHeroWithGrail() const +HeroPtr AIGateway::getHeroWithGrail() const { for(const CGHeroInstance * h : cb->getHeroesInfo()) { @@ -1150,7 +1113,7 @@ HeroPtr VCAI::getHeroWithGrail() const return nullptr; } -bool VCAI::moveHeroToTile(int3 dst, HeroPtr h) +bool AIGateway::moveHeroToTile(int3 dst, HeroPtr h) { if(h->inTownGarrison && h->visitedTown) { @@ -1342,8 +1305,6 @@ bool VCAI::moveHeroToTile(int3 dst, HeroPtr h) if(startHpos == h->visitablePos() && !ret) //we didn't move and didn't reach the target { - vstd::erase_if_present(lockedHeroes, h); //hero seemingly is confused or has only 95mp which is not enough to move - invalidPathHeroes.insert(h); throw cannotFulfillGoalException("Invalid path found!"); } @@ -1352,14 +1313,14 @@ bool VCAI::moveHeroToTile(int3 dst, HeroPtr h) return ret; } -void VCAI::buildStructure(const CGTownInstance * t, BuildingID building) +void AIGateway::buildStructure(const CGTownInstance * t, BuildingID building) { auto name = t->town->buildings.at(building)->Name(); logAi->debug("Player %d will build %s in town of %s at %s", ai->playerID, name, t->name, t->pos.toString()); cb->buildBuilding(t, building); //just do this; } -void VCAI::tryRealize(Goals::DigAtTile & g) +void AIGateway::tryRealize(Goals::DigAtTile & g) { assert(g.hero->visitablePos() == g.tile); //surely we want to crash here? if(g.hero->diggingStatus() == EDiggingStatus::CAN_DIG) @@ -1368,12 +1329,11 @@ void VCAI::tryRealize(Goals::DigAtTile & g) } else { - ai->lockedHeroes[g.hero] = sptr(g); //hero who tries to dig shouldn't do anything else throw cannotFulfillGoalException("A hero can't dig!\n"); } } -void VCAI::tryRealize(Goals::Trade & g) //trade +void AIGateway::tryRealize(Goals::Trade & g) //trade { if(cb->getResourceAmount((Res::ERes)g.resID) >= g.value) //goal is already fulfilled. Why we need this check, anyway? throw goalFulfilledException(sptr(g)); @@ -1417,7 +1377,7 @@ void VCAI::tryRealize(Goals::Trade & g) //trade } } -const CGTownInstance * VCAI::findTownWithTavern() const +const CGTownInstance * AIGateway::findTownWithTavern() const { for(const CGTownInstance * t : cb->getTownsInfo()) if(t->hasBuilt(BuildingID::TAVERN) && !t->visitingHero) @@ -1426,7 +1386,7 @@ const CGTownInstance * VCAI::findTownWithTavern() const return nullptr; } -void VCAI::endTurn() +void AIGateway::endTurn() { logAi->info("Player %d (%s) ends turn", playerID, playerID.getStr()); if(!status.haveTurn()) @@ -1443,7 +1403,7 @@ void VCAI::endTurn() logGlobal->info("Player %d (%s) ended turn", playerID, playerID.getStr()); } -void VCAI::buildArmyIn(const CGTownInstance * t) +void AIGateway::buildArmyIn(const CGTownInstance * t) { makePossibleUpgrades(t->visitingHero); makePossibleUpgrades(t); @@ -1451,7 +1411,7 @@ void VCAI::buildArmyIn(const CGTownInstance * t) moveCreaturesToHero(t); } -void VCAI::recruitHero(const CGTownInstance * t, bool throwing) +void AIGateway::recruitHero(const CGTownInstance * t, bool throwing) { logAi->debug("Trying to recruit a hero in %s at %s", t->name, t->visitablePos().toString()); @@ -1479,7 +1439,7 @@ void VCAI::recruitHero(const CGTownInstance * t, bool throwing) } } -void VCAI::finish() +void AIGateway::finish() { //we want to lock to avoid multiple threads from calling makingTurn->join() at same time boost::lock_guard multipleCleanupGuard(turnInterruptionMutex); @@ -1492,29 +1452,23 @@ void VCAI::finish() } } -void VCAI::requestActionASAP(std::function whatToDo) +void AIGateway::requestActionASAP(std::function whatToDo) { boost::thread newThread([this, whatToDo]() { - setThreadName("VCAI::requestActionASAP::whatToDo"); + setThreadName("AIGateway::requestActionASAP::whatToDo"); SET_GLOBAL_STATE(this); boost::shared_lock gsLock(CGameState::mutex); whatToDo(); }); } -void VCAI::lostHero(HeroPtr h) +void AIGateway::lostHero(HeroPtr h) { logAi->debug("I lost my hero %s. It's best to forget and move on.", h.name); - - vstd::erase_if_present(visitedHeroes, h); - for (auto heroVec : visitedHeroes) - { - vstd::erase_if_present(heroVec.second, h); - } } -void VCAI::answerQuery(QueryID queryID, int selection) +void AIGateway::answerQuery(QueryID queryID, int selection) { logAi->debug("I'll answer the query %d giving the choice %d", queryID, selection); if(queryID != QueryID(-1)) @@ -1528,7 +1482,7 @@ void VCAI::answerQuery(QueryID queryID, int selection) } } -void VCAI::requestSent(const CPackForServer * pack, int requestID) +void AIGateway::requestSent(const CPackForServer * pack, int requestID) { //BNLOG("I have sent request of type %s", typeid(*pack).name()); if(auto reply = dynamic_cast(pack)) @@ -1537,7 +1491,7 @@ void VCAI::requestSent(const CPackForServer * pack, int requestID) } } -std::string VCAI::getBattleAIName() const +std::string AIGateway::getBattleAIName() const { if(settings["server"]["enemyAI"].getType() == JsonNode::JsonType::DATA_STRING) return settings["server"]["enemyAI"].String(); @@ -1545,12 +1499,12 @@ std::string VCAI::getBattleAIName() const return "BattleAI"; } -void VCAI::validateObject(const CGObjectInstance * obj) +void AIGateway::validateObject(const CGObjectInstance * obj) { validateObject(obj->id); } -void VCAI::validateObject(ObjectIdRef obj) +void AIGateway::validateObject(ObjectIdRef obj) { if(!obj) { diff --git a/AI/Nullkiller/VCAI.h b/AI/Nullkiller/AIGateway.h similarity index 73% rename from AI/Nullkiller/VCAI.h rename to AI/Nullkiller/AIGateway.h index 24cd421d5..d56b79182 100644 --- a/AI/Nullkiller/VCAI.h +++ b/AI/Nullkiller/AIGateway.h @@ -1,5 +1,5 @@ /* - * VCAI.h, part of VCMI engine + * AIGateway.h, part of VCMI engine * * Authors: listed in file AUTHORS in main folder * @@ -70,7 +70,9 @@ public: } }; -class DLL_EXPORT VCAI : public CAdventureAI +// The gateway is responsible for AI events handling. Copied from VCAI.h and refined a bit +// Probably we can use concept of hooks to handle event in their related goals +class DLL_EXPORT AIGateway : public CAdventureAI { public: ObjectInstanceID destinationTeleport; @@ -78,20 +80,18 @@ public: std::vector teleportChannelProbingList; //list of teleport channel exits that not visible and need to be (re-)explored //std::vector visitedThisWeek; //only OPWs - std::set invalidPathHeroes; //FIXME, just a workaround - std::map lockedHeroes; //TODO: allow non-elementar objectives - std::map> reservedHeroesMap; //objects reserved by specific heroes - std::set heroesUnableToExplore; //these heroes will not be polled for exploration in current state of game + //std::set invalidPathHeroes; //FIXME, just a workaround + //std::map lockedHeroes; //TODO: allow non-elementar objectives + //std::map> reservedHeroesMap; //objects reserved by specific heroes + //std::set heroesUnableToExplore; //these heroes will not be polled for exploration in current state of game //sets are faster to search, also do not contain duplicates - std::set reservedObjs; //to be visited by specific hero - std::map> visitedHeroes; //visited this turn //FIXME: this is just bug workaround + //std::set reservedObjs; //to be visited by specific hero + //std::map> visitedHeroes; //visited this turn //FIXME: this is just bug workaround AIStatus status; std::string battlename; - std::shared_ptr myCb; - std::unique_ptr makingTurn; private: boost::mutex turnInterruptionMutex; @@ -100,15 +100,13 @@ public: std::unique_ptr nullkiller; - VCAI(); - virtual ~VCAI(); + AIGateway(); + virtual ~AIGateway(); - //TODO: use only smart pointers? + //TODO: extract to apropriate goals void tryRealize(Goals::DigAtTile & g); void tryRealize(Goals::Trade & g); - bool isTileNotReserved(const CGHeroInstance * h, int3 t) const; //the tile is not occupied by allied hero and the object is not reserved - std::string getBattleAIName() const override; void init(std::shared_ptr CB) override; @@ -176,8 +174,8 @@ public: void buildArmyIn(const CGTownInstance * t); void endTurn(); + // TODO: all the routines like recruiting hero or building army should be removed from here and extracted to elementar goals or whatever void recruitHero(const CGTownInstance * t, bool throwing = false); - //void recruitCreatures(const CGTownInstance * t); void recruitCreatures(const CGDwelling * d, const CArmedInstance * recruiter); void pickBestCreatures(const CArmedInstance * army, const CArmedInstance * source); //called when we can't find a slot for new stack void pickBestArtifacts(const CGHeroInstance * h, const CGHeroInstance * other = nullptr); @@ -186,18 +184,13 @@ public: bool makePossibleUpgrades(const CArmedInstance * obj); bool moveHeroToTile(int3 dst, HeroPtr h); - void buildStructure(const CGTownInstance * t, BuildingID building); //TODO: move to BuildingManager + void buildStructure(const CGTownInstance * t, BuildingID building); void lostHero(HeroPtr h); //should remove all references to hero (assigned tasks and so on) void waitTillFree(); void addVisitableObj(const CGObjectInstance * obj); - void markHeroUnableToExplore(HeroPtr h); - void markHeroAbleToExplore(HeroPtr h); - bool isAbleToExplore(HeroPtr h); - void clearPathsInfo(); - void validateObject(const CGObjectInstance * obj); //checks if object is still visible and if not, removes references to it void validateObject(ObjectIdRef obj); //checks if object is still visible and if not, removes references to it void retrieveVisitableObjs(std::vector & out, bool includeOwned = false) const; @@ -214,96 +207,14 @@ public: //special function that can be called ONLY from game events handling thread and will send request ASAP void requestActionASAP(std::function whatToDo); - #if 0 - //disabled due to issue 2890 - template void registerGoals(Handler & h) - { - //h.template registerType(); - h.template registerType(); - h.template registerType(); - //h.template registerType(); - h.template registerType(); - h.template registerType(); - h.template registerType(); - h.template registerType(); - h.template registerType(); - h.template registerType(); - h.template registerType(); - h.template registerType(); - h.template registerType(); - h.template registerType(); - h.template registerType(); - //h.template registerType(); - h.template registerType(); - h.template registerType(); - h.template registerType(); - h.template registerType(); - } - #endif - template void serializeInternal(Handler & h, const int version) { - std::map> ignore; - h & nullkiller->memory->knownTeleportChannels; h & nullkiller->memory->knownSubterraneanGates; h & destinationTeleport; - h & ignore; - - #if 0 - //disabled due to issue 2890 - h & lockedHeroes; - #else - { - ui32 length = 0; - h & length; - if(!h.saving) - { - std::set loadedPointers; - lockedHeroes.clear(); - for(ui32 index = 0; index < length; index++) - { - HeroPtr ignored1; - h & ignored1; - - ui8 flag = 0; - h & flag; - - if(flag) - { - ui32 pid = 0xffffffff; - h & pid; - - if(!vstd::contains(loadedPointers, pid)) - { - loadedPointers.insert(pid); - - ui16 typeId = 0; - //this is the problem requires such hack - //we have to explicitly ignore invalid goal class type id - h & typeId; - Goals::AbstractGoal ignored2; - ignored2.serialize(h, version); - } - } - } - } - } - #endif - - h & reservedHeroesMap; //FIXME: cannot instantiate abstract class h & nullkiller->memory->visitableObjs; h & nullkiller->memory->alreadyVisited; - h & reservedObjs; - if (version < 788 && !h.saving) - { - TResources saving; - h & saving; //mind the ambiguity - } h & status; h & battlename; - h & heroesUnableToExplore; - - //myCB is restored after load by init call } }; diff --git a/AI/Nullkiller/AIUtility.cpp b/AI/Nullkiller/AIUtility.cpp index 2a4bcef68..1af1f7cc9 100644 --- a/AI/Nullkiller/AIUtility.cpp +++ b/AI/Nullkiller/AIUtility.cpp @@ -9,7 +9,7 @@ */ #include "StdInc.h" #include "AIUtility.h" -#include "VCAI.h" +#include "AIGateway.h" #include "Goals/Goals.h" #include "../../lib/UnlockGuard.h" @@ -21,7 +21,7 @@ #include "../../lib/CModHandler.h" extern boost::thread_specific_ptr cb; -extern boost::thread_specific_ptr ai; +extern boost::thread_specific_ptr ai; //extern static const int3 dirs[8]; @@ -460,7 +460,7 @@ bool shouldVisit(const Nullkiller * ai, const CGHeroInstance * h, const CGObject case Obj::SCHOOL_OF_MAGIC: case Obj::SCHOOL_OF_WAR: { - if(ai->cb->getResourceAmount(Res::GOLD) < 1000) + if(ai->getFreeGold() < 1000) return false; break; } @@ -473,7 +473,7 @@ bool shouldVisit(const Nullkiller * ai, const CGHeroInstance * h, const CGObject if(ai->heroManager->getHeroRole(h) == HeroRole::SCOUT) return false; - TResources myRes = ai->cb->getResourceAmount(); + TResources myRes = ai->getFreeResources(); if(myRes[Res::GOLD] < 2000 || myRes[Res::GEMS] < 10) return false; break; @@ -483,20 +483,10 @@ bool shouldVisit(const Nullkiller * ai, const CGHeroInstance * h, const CGObject case Obj::PRISON: return ai->cb->getHeroesInfo().size() < VLC->modh->settings.MAX_HEROES_ON_MAP_PER_PLAYER; case Obj::TAVERN: - { - //TODO: make AI actually recruit heroes - //TODO: only on request - if(ai->cb->getHeroesInfo().size() >= VLC->modh->settings.MAX_HEROES_ON_MAP_PER_PLAYER) - return false; - else if(ai->cb->getResourceAmount(Res::GOLD) < GameConstants::HERO_GOLD_COST) - return false; - break; - } - case Obj::BOAT: - return false; - //Boats are handled by pathfinder case Obj::EYE_OF_MAGI: - return false; //this object is useless to visit, but could be visited indefinitely + case Obj::BOAT: + case Obj::SIGN: + return false; } if(obj->wasVisited(h)) //it must pointer to hero instance, heroPtr calls function wasVisited(ui8 player); diff --git a/AI/Nullkiller/Analyzers/ArmyManager.cpp b/AI/Nullkiller/Analyzers/ArmyManager.cpp index 3da29237f..877acb130 100644 --- a/AI/Nullkiller/Analyzers/ArmyManager.cpp +++ b/AI/Nullkiller/Analyzers/ArmyManager.cpp @@ -189,16 +189,48 @@ std::vector ArmyManager::getBestArmy(const IBonusBearer * armyCarrier, ui64 ArmyManager::howManyReinforcementsCanBuy(const CCreatureSet * h, const CGDwelling * t) const { - return howManyReinforcementsCanBuy(h, t, cb->getResourceAmount()); + return howManyReinforcementsCanBuy(h, t, ai->getFreeResources()); +} + +std::shared_ptr ArmyManager::getArmyAvailableToBuyAsCCreatureSet( + const CGDwelling * dwelling, + TResources availableRes) const +{ + std::vector creaturesInDwellings; + int freeHeroSlots = GameConstants::ARMY_SIZE; + auto army = std::make_shared(); + + for(int i = dwelling->creatures.size() - 1; i >= 0; i--) + { + auto ci = infoFromDC(dwelling->creatures[i]); + + if(!ci.count || ci.creID == -1) + continue; + + vstd::amin(ci.count, availableRes / ci.cre->cost); //max count we can afford + + if(!ci.count) + continue; + + SlotID dst = army->getFreeSlot(); + + if(!dst.validSlot()) + break; + + army->setCreature(dst, ci.creID, ci.count); + availableRes -= ci.cre->cost * ci.count; + } + + return army; } ui64 ArmyManager::howManyReinforcementsCanBuy( - const CCreatureSet * h, - const CGDwelling * t, + const CCreatureSet * targetArmy, + const CGDwelling * dwelling, const TResources & availableResources) const { ui64 aivalue = 0; - auto army = getArmyAvailableToBuy(h, t, availableResources); + auto army = getArmyAvailableToBuy(targetArmy, dwelling, availableResources); for(const creInfo & ci : army) { @@ -210,10 +242,13 @@ ui64 ArmyManager::howManyReinforcementsCanBuy( std::vector ArmyManager::getArmyAvailableToBuy(const CCreatureSet * hero, const CGDwelling * dwelling) const { - return getArmyAvailableToBuy(hero, dwelling, cb->getResourceAmount()); + return getArmyAvailableToBuy(hero, dwelling, ai->getFreeResources()); } -std::vector ArmyManager::getArmyAvailableToBuy(const CCreatureSet * hero, const CGDwelling * dwelling, TResources availableRes) const +std::vector ArmyManager::getArmyAvailableToBuy( + const CCreatureSet * hero, + const CGDwelling * dwelling, + TResources availableRes) const { std::vector creaturesInDwellings; int freeHeroSlots = GameConstants::ARMY_SIZE - hero->stacksCount(); diff --git a/AI/Nullkiller/Analyzers/ArmyManager.h b/AI/Nullkiller/Analyzers/ArmyManager.h index 568cdd90a..0078bc0d5 100644 --- a/AI/Nullkiller/Analyzers/ArmyManager.h +++ b/AI/Nullkiller/Analyzers/ArmyManager.h @@ -44,8 +44,8 @@ public: virtual void update() = 0; virtual ui64 howManyReinforcementsCanBuy(const CCreatureSet * target, const CGDwelling * source) const = 0; virtual ui64 howManyReinforcementsCanBuy( - const CCreatureSet * h, - const CGDwelling * t, + const CCreatureSet * targetArmy, + const CGDwelling * dwelling, const TResources & availableResources) const = 0; virtual ui64 howManyReinforcementsCanGet(const CGHeroInstance * hero, const CCreatureSet * source) const = 0; virtual ui64 howManyReinforcementsCanGet(const IBonusBearer * armyCarrier, const CCreatureSet * target, const CCreatureSet * source) const = 0; @@ -60,6 +60,7 @@ public: const CGObjectInstance * upgrader, const TResources & availableResources) const = 0; virtual std::vector getArmyAvailableToBuy(const CCreatureSet * hero, const CGDwelling * dwelling) const = 0; + virtual std::shared_ptr getArmyAvailableToBuyAsCCreatureSet(const CGDwelling * dwelling, TResources availableRes) const = 0; }; struct StackUpgradeInfo; @@ -76,8 +77,8 @@ public: void update() override; ui64 howManyReinforcementsCanBuy(const CCreatureSet * target, const CGDwelling * source) const override; ui64 howManyReinforcementsCanBuy( - const CCreatureSet * h, - const CGDwelling * t, + const CCreatureSet * targetArmy, + const CGDwelling * dwelling, const TResources & availableResources) const override; ui64 howManyReinforcementsCanGet(const CGHeroInstance * hero, const CCreatureSet * source) const override; ui64 howManyReinforcementsCanGet(const IBonusBearer * armyCarrier, const CCreatureSet * target, const CCreatureSet * source) const override; @@ -86,6 +87,7 @@ public: std::vector getSortedSlots(const CCreatureSet * target, const CCreatureSet * source) const override; std::vector getArmyAvailableToBuy(const CCreatureSet * hero, const CGDwelling * dwelling, TResources availableRes) const override; std::vector getArmyAvailableToBuy(const CCreatureSet * hero, const CGDwelling * dwelling) const override; + std::shared_ptr getArmyAvailableToBuyAsCCreatureSet(const CGDwelling * dwelling, TResources availableRes) const override; uint64_t evaluateStackPower(const CCreature * creature, int count) const override; SlotInfo getTotalCreaturesAvailable(CreatureID creatureID) const override; ArmyUpgradeInfo calculateCreateresUpgrade( diff --git a/AI/Nullkiller/Analyzers/BuildAnalyzer.cpp b/AI/Nullkiller/Analyzers/BuildAnalyzer.cpp index 14105a48f..396a773f2 100644 --- a/AI/Nullkiller/Analyzers/BuildAnalyzer.cpp +++ b/AI/Nullkiller/Analyzers/BuildAnalyzer.cpp @@ -97,7 +97,7 @@ int32_t convertToGold(const TResources & res) TResources BuildAnalyzer::getResourcesRequiredNow() const { - auto resourcesAvailable = ai->cb->getResourceAmount(); + auto resourcesAvailable = ai->getFreeResources(); auto result = requiredResources - resourcesAvailable; result.positive(); @@ -107,7 +107,7 @@ TResources BuildAnalyzer::getResourcesRequiredNow() const TResources BuildAnalyzer::getTotalResourcesRequired() const { - auto resourcesAvailable = ai->cb->getResourceAmount(); + auto resourcesAvailable = ai->getFreeResources(); auto result = totalDevelopmentCost - resourcesAvailable; result.positive(); @@ -157,7 +157,15 @@ void BuildAnalyzer::update() updateDailyIncome(); - goldPreasure = (float)armyCost[Res::GOLD] / (1 + ai->cb->getResourceAmount(Res::GOLD) + (float)dailyIncome[Res::GOLD] * 7.0f); + if(ai->cb->getDate(Date::EDateType::DAY) == 1) + { + goldPreasure = 1; + } + else + { + goldPreasure = ai->getLockedResources()[Res::GOLD] / 10000.0f + + (float)armyCost[Res::GOLD] / (1 + ai->getFreeGold() + (float)dailyIncome[Res::GOLD] * 7.0f); + } logAi->trace("Gold preasure: %f", goldPreasure); } @@ -194,7 +202,7 @@ BuildingInfo BuildAnalyzer::getBuildingOrPrerequisite( auto info = BuildingInfo(buildPtr, creature, baseCreatureID, town, ai); - logAi->trace("checking %s", buildPtr->Name()); + logAi->trace("checking %s", info.name); logAi->trace("buildInfo %s", info.toString()); buildPtr = nullptr; @@ -244,6 +252,8 @@ BuildingInfo BuildAnalyzer::getBuildingOrPrerequisite( prerequisite.creatureID = info.creatureID; prerequisite.baseCreatureID = info.baseCreatureID; prerequisite.prerequisitesCount++; + prerequisite.armyCost = info.armyCost; + prerequisite.dailyIncome = info.dailyIncome; return prerequisite; } @@ -296,7 +306,7 @@ void TownDevelopmentInfo::addExistingDwelling(const BuildingInfo & existingDwell { existingDwellings.push_back(existingDwelling); - armyCost += existingDwelling.creatureCost * existingDwelling.creatureGrows; + armyCost += existingDwelling.armyCost; armyStrength += existingDwelling.armyStrength; } @@ -306,13 +316,14 @@ void TownDevelopmentInfo::addBuildingToBuild(const BuildingInfo & nextToBuild) if(nextToBuild.canBuild) { - toBuild.push_back(nextToBuild); hasSomethingToBuild = true; + toBuild.push_back(nextToBuild); } else if(nextToBuild.notEnoughRes) { requiredResources += nextToBuild.buildCost; hasSomethingToBuild = true; + toBuild.push_back(nextToBuild); } } @@ -341,6 +352,7 @@ BuildingInfo::BuildingInfo( dailyIncome = building->produce; exists = town->hasBuilt(id); prerequisitesCount = 1; + name = building->Name(); if(creature) { @@ -352,7 +364,7 @@ BuildingInfo::BuildingInfo( if(exists) { - creatureGrows = town->creatureGrowth(creatureID); + creatureGrows = town->creatureGrowth(creatureLevel - 1); } else { diff --git a/AI/Nullkiller/Analyzers/HeroManager.cpp b/AI/Nullkiller/Analyzers/HeroManager.cpp index bf3d1591d..7b546f70c 100644 --- a/AI/Nullkiller/Analyzers/HeroManager.cpp +++ b/AI/Nullkiller/Analyzers/HeroManager.cpp @@ -102,7 +102,7 @@ std::vector> clusterizeHeroes(CCallback * cb { auto hero = std::find_if(cluster->begin(), cluster->end(), [&](const CGHeroInstance * h) -> bool { - return paths->getNode(h->visitablePos())->turns <= SCOUT_TURN_DISTANCE_LIMIT; + return paths->getNode(h->visitablePos())->turns < SCOUT_TURN_DISTANCE_LIMIT; }); if(hero != cluster->end()) diff --git a/AI/Nullkiller/Analyzers/ObjectClusterizer.cpp b/AI/Nullkiller/Analyzers/ObjectClusterizer.cpp index 8f7a3e3c4..96f25e9c6 100644 --- a/AI/Nullkiller/Analyzers/ObjectClusterizer.cpp +++ b/AI/Nullkiller/Analyzers/ObjectClusterizer.cpp @@ -10,7 +10,7 @@ #include "StdInc.h" #include "ObjectClusterizer.h" #include "../Goals/ExecuteHeroChain.h" -#include "../VCAI.h" +#include "../AIGateway.h" #include "../Engine/Nullkiller.h" #include "lib/mapping/CMap.h" //for victory conditions diff --git a/AI/Nullkiller/Behaviors/Behavior.h b/AI/Nullkiller/Behaviors/Behavior.h index 3e50a94a5..e9e36197e 100644 --- a/AI/Nullkiller/Behaviors/Behavior.h +++ b/AI/Nullkiller/Behaviors/Behavior.h @@ -9,7 +9,7 @@ */ #pragma once -#include "../VCAI.h" +#include "../AIGateway.h" #error REMOVE THIS FILE class Behavior : public Goals::AbstractGoal diff --git a/AI/Nullkiller/Behaviors/BuildingBehavior.cpp b/AI/Nullkiller/Behaviors/BuildingBehavior.cpp index 0a4afb019..22386683e 100644 --- a/AI/Nullkiller/Behaviors/BuildingBehavior.cpp +++ b/AI/Nullkiller/Behaviors/BuildingBehavior.cpp @@ -9,16 +9,18 @@ */ #include "StdInc.h" #include "BuildingBehavior.h" -#include "../VCAI.h" +#include "../AIGateway.h" #include "../AIUtility.h" #include "../Goals/BuyArmy.h" +#include "../Goals/Composition.h" #include "../Goals/BuildThis.h" +#include "../Goals/SaveResources.h" #include "lib/mapping/CMap.h" //for victory conditions #include "lib/CPathfinder.h" #include "../Engine/Nullkiller.h" extern boost::thread_specific_ptr cb; -extern boost::thread_specific_ptr ai; +extern boost::thread_specific_ptr ai; using namespace Goals; @@ -33,10 +35,10 @@ Goals::TGoalVec BuildingBehavior::decompose() const TResources resourcesRequired = ai->nullkiller->buildAnalyzer->getResourcesRequiredNow(); TResources totalDevelopmentCost = ai->nullkiller->buildAnalyzer->getTotalResourcesRequired(); - TResources availableResources = cb->getResourceAmount(); + TResources availableResources = ai->nullkiller->getFreeResources(); TResources dailyIncome = ai->nullkiller->buildAnalyzer->getDailyIncome(); - logAi->trace("Resources amount: %s", availableResources.toString()); + logAi->trace("Free resources amount: %s", availableResources.toString()); resourcesRequired -= availableResources; resourcesRequired.positive(); @@ -56,7 +58,22 @@ Goals::TGoalVec BuildingBehavior::decompose() const for(auto & buildingInfo : developmentInfo.toBuild) { if(goldPreasure < MAX_GOLD_PEASURE || buildingInfo.dailyIncome[Res::GOLD] > 0) - tasks.push_back(sptr(BuildThis(buildingInfo, developmentInfo))); + { + if(buildingInfo.notEnoughRes) + { + if(ai->nullkiller->getLockedResources().canAfford(buildingInfo.buildCost)) + continue; + + Composition composition; + + composition.addNext(BuildThis(buildingInfo, developmentInfo)); + composition.addNext(SaveResources(buildingInfo.buildCost)); + + tasks.push_back(sptr(composition)); + } + else + tasks.push_back(sptr(BuildThis(buildingInfo, developmentInfo))); + } } } diff --git a/AI/Nullkiller/Behaviors/BuyArmyBehavior.cpp b/AI/Nullkiller/Behaviors/BuyArmyBehavior.cpp index 36abe1bea..d7fbea89b 100644 --- a/AI/Nullkiller/Behaviors/BuyArmyBehavior.cpp +++ b/AI/Nullkiller/Behaviors/BuyArmyBehavior.cpp @@ -9,7 +9,7 @@ */ #include "StdInc.h" #include "BuyArmyBehavior.h" -#include "../VCAI.h" +#include "../AIGateway.h" #include "../AIUtility.h" #include "../Goals/BuyArmy.h" #include "../Engine/Nullkiller.h" @@ -17,7 +17,7 @@ #include "lib/CPathfinder.h" extern boost::thread_specific_ptr cb; -extern boost::thread_specific_ptr ai; +extern boost::thread_specific_ptr ai; using namespace Goals; @@ -32,43 +32,43 @@ Goals::TGoalVec BuyArmyBehavior::decompose() const if(cb->getDate(Date::DAY) == 1) return tasks; - - if(ai->nullkiller->buildAnalyzer->getGoldPreasure() > MAX_GOLD_PEASURE) - return tasks; auto heroes = cb->getHeroesInfo(); - if(heroes.size()) + if(heroes.empty()) { - auto mainArmy = vstd::maxElementByFun(heroes, [](const CGHeroInstance * hero) -> uint64_t - { - return hero->getTotalStrength(); - }); + return tasks; + } - for(auto town : cb->getTownsInfo()) - { - const CGHeroInstance * targetHero = *mainArmy; + for(auto town : cb->getTownsInfo()) + { + auto townArmyAvailableToBuy = ai->nullkiller->armyManager->getArmyAvailableToBuyAsCCreatureSet( + town, + ai->nullkiller->getFreeResources()); - /*if(town->visitingHero) + for(const CGHeroInstance * targetHero : heroes) + { + if(ai->nullkiller->buildAnalyzer->getGoldPreasure() > MAX_GOLD_PEASURE + && !town->hasBuilt(BuildingID::CITY_HALL)) { - targetHero = town->visitingHero.get(); + continue; + } - if(ai->nullkiller->armyManager->howManyReinforcementsCanGet(targetHero, town->getUpperArmy())) + if(ai->nullkiller->heroManager->getHeroRole(targetHero) == HeroRole::MAIN + && targetHero->getArmyStrength() >= 300) + { + auto reinforcement = ai->nullkiller->armyManager->howManyReinforcementsCanGet( + targetHero, + targetHero, + &*townArmyAvailableToBuy); + + if(reinforcement) + vstd::amin(reinforcement, ai->nullkiller->armyManager->howManyReinforcementsCanBuy(town->getUpperArmy(), town)); + + if(reinforcement) { - tasks.push_back(sptr(VisitTile(town->visitablePos()).sethero(targetHero).setpriority(5))); - - continue; + tasks.push_back(Goals::sptr(Goals::BuyArmy(town, reinforcement).setpriority(5))); } - }*/ - - auto reinforcement = ai->nullkiller->armyManager->howManyReinforcementsCanBuy(targetHero, town); - - if(reinforcement) - reinforcement = ai->nullkiller->armyManager->howManyReinforcementsCanBuy(town->getUpperArmy(), town); - - if(reinforcement) - { - tasks.push_back(Goals::sptr(Goals::BuyArmy(town, reinforcement).setpriority(5))); } } } diff --git a/AI/Nullkiller/Behaviors/CaptureObjectsBehavior.cpp b/AI/Nullkiller/Behaviors/CaptureObjectsBehavior.cpp index d4e26ab00..daea0c741 100644 --- a/AI/Nullkiller/Behaviors/CaptureObjectsBehavior.cpp +++ b/AI/Nullkiller/Behaviors/CaptureObjectsBehavior.cpp @@ -8,7 +8,7 @@ * */ #include "StdInc.h" -#include "../VCAI.h" +#include "../AIGateway.h" #include "../Engine/Nullkiller.h" #include "../Goals/Composition.h" #include "../Goals/ExecuteHeroChain.h" @@ -16,7 +16,7 @@ #include "../AIUtility.h" extern boost::thread_specific_ptr cb; -extern boost::thread_specific_ptr ai; +extern boost::thread_specific_ptr ai; using namespace Goals; diff --git a/AI/Nullkiller/Behaviors/ClusterBehavior.cpp b/AI/Nullkiller/Behaviors/ClusterBehavior.cpp index ef9a80692..79ed91def 100644 --- a/AI/Nullkiller/Behaviors/ClusterBehavior.cpp +++ b/AI/Nullkiller/Behaviors/ClusterBehavior.cpp @@ -9,7 +9,7 @@ */ #include "StdInc.h" #include "ClusterBehavior.h" -#include "../VCAI.h" +#include "../AIGateway.h" #include "../Engine/Nullkiller.h" #include "../AIUtility.h" #include "../Markers/UnlockCluster.h" @@ -17,7 +17,7 @@ #include "../Behaviors/CaptureObjectsBehavior.h" extern boost::thread_specific_ptr cb; -extern boost::thread_specific_ptr ai; +extern boost::thread_specific_ptr ai; using namespace Goals; @@ -74,16 +74,21 @@ Goals::TGoalVec ClusterBehavior::decomposeCluster(std::shared_ptr blockerPaths.push_back(*path); - blockerPaths.back().nodes.clear(); + AIPath & clonedPath = blockerPaths.back(); + + clonedPath.nodes.clear(); for(auto node = path->nodes.rbegin(); node != path->nodes.rend(); node++) { - blockerPaths.back().nodes.insert(blockerPaths.back().nodes.begin(), *node); + clonedPath.nodes.insert(clonedPath.nodes.begin(), *node); if(node->coord == blockerPos || cb->getGuardingCreaturePosition(node->coord) == blockerPos) break; } + for(auto & node : clonedPath.nodes) + node.parentIndex -= path->nodes.size() - clonedPath.nodes.size(); + #if AI_TRACE_LEVEL >= 2 logAi->trace("Unlock path found %s", blockerPaths.back().toString()); #endif diff --git a/AI/Nullkiller/Behaviors/DefenceBehavior.cpp b/AI/Nullkiller/Behaviors/DefenceBehavior.cpp index b4b0922aa..2c95d1b5c 100644 --- a/AI/Nullkiller/Behaviors/DefenceBehavior.cpp +++ b/AI/Nullkiller/Behaviors/DefenceBehavior.cpp @@ -9,7 +9,7 @@ */ #include "StdInc.h" #include "DefenceBehavior.h" -#include "../VCAI.h" +#include "../AIGateway.h" #include "../Engine/Nullkiller.h" #include "../AIUtility.h" #include "../Goals/BuyArmy.h" @@ -24,7 +24,7 @@ #include "lib/CPathfinder.h" extern boost::thread_specific_ptr cb; -extern boost::thread_specific_ptr ai; +extern boost::thread_specific_ptr ai; using namespace Goals; diff --git a/AI/Nullkiller/Behaviors/GatherArmyBehavior.cpp b/AI/Nullkiller/Behaviors/GatherArmyBehavior.cpp index 61b3afe73..9397d2ed7 100644 --- a/AI/Nullkiller/Behaviors/GatherArmyBehavior.cpp +++ b/AI/Nullkiller/Behaviors/GatherArmyBehavior.cpp @@ -8,7 +8,7 @@ * */ #include "StdInc.h" -#include "../VCAI.h" +#include "../AIGateway.h" #include "../Engine/Nullkiller.h" #include "../Goals/ExecuteHeroChain.h" #include "../Goals/Composition.h" @@ -20,7 +20,7 @@ #include "lib/CPathfinder.h" extern boost::thread_specific_ptr cb; -extern boost::thread_specific_ptr ai; +extern boost::thread_specific_ptr ai; using namespace Goals; @@ -173,7 +173,7 @@ Goals::TGoalVec GatherArmyBehavior::upgradeArmy(const CGTownInstance * upgrader) { Goals::TGoalVec tasks; const int3 pos = upgrader->visitablePos(); - TResources availableResources = cb->getResourceAmount(); + TResources availableResources = ai->nullkiller->getFreeResources(); #if AI_TRACE_LEVEL >= 1 logAi->trace("Checking ways to upgrade army in town %s, %s", upgrader->getObjectName(), pos.toString()); diff --git a/AI/Nullkiller/Behaviors/RecruitHeroBehavior.cpp b/AI/Nullkiller/Behaviors/RecruitHeroBehavior.cpp index 1cb1fc4b6..f90323bfa 100644 --- a/AI/Nullkiller/Behaviors/RecruitHeroBehavior.cpp +++ b/AI/Nullkiller/Behaviors/RecruitHeroBehavior.cpp @@ -9,7 +9,7 @@ */ #include "StdInc.h" #include "RecruitHeroBehavior.h" -#include "../VCAI.h" +#include "../AIGateway.h" #include "../AIUtility.h" #include "../Goals/RecruitHero.h" #include "../Goals/ExecuteHeroChain.h" @@ -17,7 +17,7 @@ #include "lib/CPathfinder.h" extern boost::thread_specific_ptr cb; -extern boost::thread_specific_ptr ai; +extern boost::thread_specific_ptr ai; using namespace Goals; @@ -36,7 +36,8 @@ Goals::TGoalVec RecruitHeroBehavior::decompose() const if(!town->garrisonHero && !town->visitingHero && ai->canRecruitAnyHero(town)) { if(cb->getHeroesInfo().size() < cb->getTownsInfo().size() + 1 - || cb->getResourceAmount(Res::GOLD) > 10000) + || (ai->nullkiller->getFreeResources()[Res::GOLD] > 10000 + && ai->nullkiller->buildAnalyzer->getGoldPreasure() < MAX_GOLD_PEASURE)) { tasks.push_back(Goals::sptr(Goals::RecruitHero(town).setpriority(3))); } diff --git a/AI/Nullkiller/Behaviors/StartupBehavior.cpp b/AI/Nullkiller/Behaviors/StartupBehavior.cpp index a03af4b0a..4a1788c67 100644 --- a/AI/Nullkiller/Behaviors/StartupBehavior.cpp +++ b/AI/Nullkiller/Behaviors/StartupBehavior.cpp @@ -9,7 +9,7 @@ */ #include "StdInc.h" #include "StartupBehavior.h" -#include "../VCAI.h" +#include "../AIGateway.h" #include "../AIUtility.h" #include "../Goals/BuildThis.h" #include "../Goals/RecruitHero.h" @@ -21,7 +21,7 @@ #include "../Engine/Nullkiller.h" extern boost::thread_specific_ptr cb; -extern boost::thread_specific_ptr ai; +extern boost::thread_specific_ptr ai; using namespace Goals; diff --git a/AI/Nullkiller/CMakeLists.txt b/AI/Nullkiller/CMakeLists.txt index 7b4546997..460f30a05 100644 --- a/AI/Nullkiller/CMakeLists.txt +++ b/AI/Nullkiller/CMakeLists.txt @@ -1,4 +1,4 @@ -set(VCAI_SRCS +set(Nullkiller_SRCS StdInc.cpp Pathfinding/AIPathfinderConfig.cpp @@ -23,6 +23,7 @@ set(VCAI_SRCS Engine/AIMemory.cpp Goals/AbstractGoal.cpp Goals/Composition.cpp + Goals/SaveResources.cpp Goals/BuildBoat.cpp Goals/BuildThis.cpp Goals/DismissHero.cpp @@ -54,10 +55,10 @@ set(VCAI_SRCS Behaviors/GatherArmyBehavior.cpp Behaviors/ClusterBehavior.cpp main.cpp - VCAI.cpp + AIGateway.cpp ) -set(VCAI_HEADERS +set(Nullkiller_HEADERS StdInc.h Pathfinding/AIPathfinderConfig.h @@ -85,6 +86,7 @@ set(VCAI_HEADERS Goals/Composition.h Goals/Invalid.h Goals/BuildBoat.h + Goals/SaveResources.h Goals/BuildThis.h Goals/DismissHero.h Goals/BuyArmy.h @@ -115,39 +117,39 @@ set(VCAI_HEADERS Behaviors/BuildingBehavior.h Behaviors/GatherArmyBehavior.h Behaviors/ClusterBehavior.h - VCAI.h + AIGateway.h ) -assign_source_group(${VCAI_SRCS} ${VCAI_HEADERS}) +assign_source_group(${Nullkiller_SRCS} ${Nullkiller_HEADERS}) if(ANDROID) # android compiles ai libs into main lib directly, so we skip this library and just reuse sources list return() endif() -add_library(VCAI SHARED ${VCAI_SRCS} ${VCAI_HEADERS}) +add_library(Nullkiller SHARED ${Nullkiller_SRCS} ${Nullkiller_HEADERS}) if(FL_FOUND) - target_include_directories(VCAI PUBLIC ${FL_INCLUDE_DIRS}) + target_include_directories(Nullkiller PUBLIC ${FL_INCLUDE_DIRS}) else() - target_include_directories(VCAI PUBLIC ${CMAKE_HOME_DIRECTORY}/AI/FuzzyLite/fuzzylite) + target_include_directories(Nullkiller PUBLIC ${CMAKE_HOME_DIRECTORY}/AI/FuzzyLite/fuzzylite) endif() -target_include_directories(VCAI PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) +target_include_directories(Nullkiller PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) if(FL_FOUND) - target_link_libraries(VCAI PRIVATE ${FL_LIBRARIES} vcmi) + target_link_libraries(Nullkiller PRIVATE ${FL_LIBRARIES} vcmi) else() - target_link_libraries(VCAI PRIVATE fl-static vcmi) + target_link_libraries(Nullkiller PRIVATE fl-static vcmi) endif() if(TBB_FOUND) - target_link_libraries(VCAI PRIVATE ${TBB_LIBRARIES}) + target_link_libraries(Nullkiller PRIVATE ${TBB_LIBRARIES}) else() - target_link_libraries(VCAI PRIVATE tbb) + target_link_libraries(Nullkiller PRIVATE tbb) endif() -vcmi_set_output_dir(VCAI "AI") +vcmi_set_output_dir(Nullkiller "AI") -set_target_properties(VCAI PROPERTIES ${PCH_PROPERTIES}) -cotire(VCAI) +set_target_properties(Nullkiller PROPERTIES ${PCH_PROPERTIES}) +cotire(Nullkiller) -install(TARGETS VCAI RUNTIME DESTINATION ${AI_LIB_DIR} LIBRARY DESTINATION ${AI_LIB_DIR}) +install(TARGETS Nullkiller RUNTIME DESTINATION ${AI_LIB_DIR} LIBRARY DESTINATION ${AI_LIB_DIR}) diff --git a/AI/Nullkiller/Engine/DeepDecomposer.cpp b/AI/Nullkiller/Engine/DeepDecomposer.cpp index 6dae5a7ee..565aa7dfc 100644 --- a/AI/Nullkiller/Engine/DeepDecomposer.cpp +++ b/AI/Nullkiller/Engine/DeepDecomposer.cpp @@ -9,7 +9,7 @@ */ #include "StdInc.h" #include "DeepDecomposer.h" -#include "../VCAI.h" +#include "../AIGateway.h" #include "../Behaviors/CaptureObjectsBehavior.h" #include "../Behaviors/RecruitHeroBehavior.h" #include "../Behaviors/BuyArmyBehavior.h" @@ -22,7 +22,7 @@ #include "../Goals/Composition.h" extern boost::thread_specific_ptr cb; -extern boost::thread_specific_ptr ai; +extern boost::thread_specific_ptr ai; using namespace Goals; diff --git a/AI/Nullkiller/Engine/FuzzyEngines.cpp b/AI/Nullkiller/Engine/FuzzyEngines.cpp index cd757cc45..ab449e666 100644 --- a/AI/Nullkiller/Engine/FuzzyEngines.cpp +++ b/AI/Nullkiller/Engine/FuzzyEngines.cpp @@ -12,12 +12,12 @@ #include "../Goals/Goals.h" #include "../../../lib/mapObjects/MapObjects.h" -#include "../VCAI.h" +#include "../AIGateway.h" #define MIN_AI_STRENGTH (0.5f) //lower when combat AI gets smarter #define UNGUARDED_OBJECT (100.0f) //we consider unguarded objects 100 times weaker than us -extern boost::thread_specific_ptr ai; +extern boost::thread_specific_ptr ai; engineBase::engineBase() { diff --git a/AI/Nullkiller/Engine/Nullkiller.cpp b/AI/Nullkiller/Engine/Nullkiller.cpp index 622a256bc..d3f9e81cc 100644 --- a/AI/Nullkiller/Engine/Nullkiller.cpp +++ b/AI/Nullkiller/Engine/Nullkiller.cpp @@ -9,7 +9,7 @@ */ #include "StdInc.h" #include "Nullkiller.h" -#include "../VCAI.h" +#include "../AIGateway.h" #include "../Behaviors/CaptureObjectsBehavior.h" #include "../Behaviors/RecruitHeroBehavior.h" #include "../Behaviors/BuyArmyBehavior.h" @@ -22,7 +22,7 @@ #include "../Goals/Composition.h" extern boost::thread_specific_ptr cb; -extern boost::thread_specific_ptr ai; +extern boost::thread_specific_ptr ai; using namespace Goals; @@ -111,6 +111,7 @@ Goals::TTask Nullkiller::choseBestTask(Goals::TSubgoal behavior, int decompositi void Nullkiller::resetAiState() { + lockedResources = TResources(); scanDepth = ScanDepth::SMALL; playerID = ai->playerID; lockedHeroes.clear(); @@ -238,7 +239,7 @@ void Nullkiller::makeTurn() if(hero.validAndSet()) heroRole = heroManager->getHeroRole(hero); - if(heroRole == HeroRole::MAIN) + if(heroRole == HeroRole::MAIN || bestTask->priority < MIN_PRIORITY) { logAi->trace( "Goal %s has too low priority %f so increasing scan depth", @@ -278,4 +279,18 @@ void Nullkiller::makeTurn() return; } } +} + +TResources Nullkiller::getFreeResources() const +{ + auto freeRes = cb->getResourceAmount() - lockedResources; + + freeRes.positive(); + + return freeRes; +} + +void Nullkiller::lockResources(const TResources & res) +{ + lockedResources += res; } \ No newline at end of file diff --git a/AI/Nullkiller/Engine/Nullkiller.h b/AI/Nullkiller/Engine/Nullkiller.h index 7d3997a5b..6f95ba17f 100644 --- a/AI/Nullkiller/Engine/Nullkiller.h +++ b/AI/Nullkiller/Engine/Nullkiller.h @@ -50,6 +50,7 @@ private: int3 targetTile; std::map lockedHeroes; ScanDepth scanDepth; + TResources lockedResources; public: std::unique_ptr dangerHitMap; @@ -78,6 +79,10 @@ public: void lockHero(const CGHeroInstance * hero, HeroLockedReason lockReason) { lockedHeroes[hero] = lockReason; } void unlockHero(const CGHeroInstance * hero) { lockedHeroes.erase(hero); } bool arePathHeroesLocked(const AIPath & path) const; + TResources getFreeResources() const; + int32_t getFreeGold() const { return getFreeResources()[Res::GOLD]; } + void lockResources(const TResources & res); + const TResources & getLockedResources() const { return lockedResources; } private: void resetAiState(); diff --git a/AI/Nullkiller/Engine/PriorityEvaluator.cpp b/AI/Nullkiller/Engine/PriorityEvaluator.cpp index 47b8ab2ba..de5789e3e 100644 --- a/AI/Nullkiller/Engine/PriorityEvaluator.cpp +++ b/AI/Nullkiller/Engine/PriorityEvaluator.cpp @@ -686,8 +686,9 @@ public: } else { - evaluationContext.strategicalValue += 0.05f * bi.creatureLevel / (float)bi.prerequisitesCount; - evaluationContext.armyReward += evaluationContext.evaluator.getUpgradeArmyReward(buildThis.town, bi); + auto potentialUpgradeValue = evaluationContext.evaluator.getUpgradeArmyReward(buildThis.town, bi); + //evaluationContext.strategicalValue += 0.05f * bi.creatureLevel / (float)bi.prerequisitesCount; + evaluationContext.armyReward += 0.3f * potentialUpgradeValue / (float)bi.prerequisitesCount; } } else if(bi.id == BuildingID::CITADEL || bi.id == BuildingID::CASTLE) @@ -777,7 +778,7 @@ float PriorityEvaluator::evaluate(Goals::TSubgoal task) closestHeroRatioVariable->setValue(evaluationContext.closestWayRatio); strategicalValueVariable->setValue(evaluationContext.strategicalValue); goldPreasureVariable->setValue(ai->buildAnalyzer->getGoldPreasure()); - goldCostVariable->setValue(evaluationContext.goldCost / ((float)ai->cb->getResourceAmount(Res::GOLD) + (float)ai->buildAnalyzer->getDailyIncome()[Res::GOLD] + 1.0f)); + goldCostVariable->setValue(evaluationContext.goldCost / ((float)ai->getFreeResources()[Res::GOLD] + (float)ai->buildAnalyzer->getDailyIncome()[Res::GOLD] + 1.0f)); turnVariable->setValue(evaluationContext.turn); fearVariable->setValue(evaluationContext.enemyHeroDangerRatio); diff --git a/AI/Nullkiller/Goals/AbstractGoal.cpp b/AI/Nullkiller/Goals/AbstractGoal.cpp index 4dbebb01b..fb51ac0a9 100644 --- a/AI/Nullkiller/Goals/AbstractGoal.cpp +++ b/AI/Nullkiller/Goals/AbstractGoal.cpp @@ -9,13 +9,13 @@ */ #include "StdInc.h" #include "AbstractGoal.h" -#include "../VCAI.h" +#include "../AIGateway.h" #include "../../../lib/mapping/CMap.h" //for victory conditions #include "../../../lib/CPathfinder.h" #include "../../../lib/StringConstants.h" extern boost::thread_specific_ptr cb; -extern boost::thread_specific_ptr ai; +extern boost::thread_specific_ptr ai; using namespace Goals; diff --git a/AI/Nullkiller/Goals/AbstractGoal.h b/AI/Nullkiller/Goals/AbstractGoal.h index 1e966aa14..64bcd6b8d 100644 --- a/AI/Nullkiller/Goals/AbstractGoal.h +++ b/AI/Nullkiller/Goals/AbstractGoal.h @@ -16,7 +16,7 @@ #include "../AIUtility.h" struct HeroPtr; -class VCAI; +class AIGateway; class FuzzyHelper; namespace Goals @@ -67,7 +67,8 @@ namespace Goals HERO_EXCHANGE, ARMY_UPGRADE, DEFEND_TOWN, - CAPTURE_OBJECT + CAPTURE_OBJECT, + SAVE_RESOURCES }; class DLL_EXPORT TSubgoal : public std::shared_ptr @@ -84,10 +85,6 @@ namespace Goals //method chaining + clone pattern #define SETTER(type, field) AbstractGoal & set ## field(const type &rhs) {field = rhs; return *this;}; -#if 0 -#define SETTER -#endif // _DEBUG - enum { LOW_PR = -1 }; DLL_EXPORT TSubgoal sptr(const AbstractGoal & tmp); @@ -150,25 +147,6 @@ namespace Goals { return !(*this == g); } - - template void serialize(Handler & h, const int version) - { - float priority; - bool isElementar; - - h & goalType; - h & isElementar; - h & isAbstract; - h & priority; - h & value; - h & resID; - h & objid; - h & aid; - h & tile; - h & hero; - h & town; - h & bid; - } }; class DLL_EXPORT ITask @@ -180,7 +158,7 @@ namespace Goals ///Visitor pattern //TODO: make accept work for std::shared_ptr... somehow - virtual void accept(VCAI * ai) = 0; //unhandled goal will report standard error + virtual void accept(AIGateway * ai) = 0; //unhandled goal will report standard error virtual std::string toString() const = 0; virtual HeroPtr getHero() const = 0; virtual ~ITask() {} diff --git a/AI/Nullkiller/Goals/AdventureSpellCast.cpp b/AI/Nullkiller/Goals/AdventureSpellCast.cpp index 91abbd1db..4d00cc937 100644 --- a/AI/Nullkiller/Goals/AdventureSpellCast.cpp +++ b/AI/Nullkiller/Goals/AdventureSpellCast.cpp @@ -9,12 +9,12 @@ */ #include "StdInc.h" #include "AdventureSpellCast.h" -#include "../VCAI.h" +#include "../AIGateway.h" #include "../../../lib/mapping/CMap.h" //for victory conditions #include "../../../lib/CPathfinder.h" extern boost::thread_specific_ptr cb; -extern boost::thread_specific_ptr ai; +extern boost::thread_specific_ptr ai; using namespace Goals; @@ -23,7 +23,7 @@ bool AdventureSpellCast::operator==(const AdventureSpellCast & other) const return hero.h == other.hero.h; } -void AdventureSpellCast::accept(VCAI * ai) +void AdventureSpellCast::accept(AIGateway * ai) { if(!hero.validAndSet()) throw cannotFulfillGoalException("Invalid hero!"); diff --git a/AI/Nullkiller/Goals/AdventureSpellCast.h b/AI/Nullkiller/Goals/AdventureSpellCast.h index 377a9ee20..063848521 100644 --- a/AI/Nullkiller/Goals/AdventureSpellCast.h +++ b/AI/Nullkiller/Goals/AdventureSpellCast.h @@ -30,7 +30,7 @@ namespace Goals return spellID.toSpell(); } - void accept(VCAI * ai) override; + void accept(AIGateway * ai) override; std::string toString() const override; virtual bool operator==(const AdventureSpellCast & other) const override; }; diff --git a/AI/Nullkiller/Goals/Build.cpp b/AI/Nullkiller/Goals/Build.cpp index 140f7e99f..3497706ba 100644 --- a/AI/Nullkiller/Goals/Build.cpp +++ b/AI/Nullkiller/Goals/Build.cpp @@ -10,7 +10,7 @@ #include "StdInc.h" #include "Build.h" #include "BuildThis.h" -#include "../VCAI.h" +#include "../AIGateway.h" #include "../AIUtility.h" #include "../AIhelper.h" #include "../FuzzyHelper.h" @@ -22,7 +22,7 @@ extern boost::thread_specific_ptr cb; -extern boost::thread_specific_ptr ai; +extern boost::thread_specific_ptr ai; extern FuzzyHelper * fh; using namespace Goals; diff --git a/AI/Nullkiller/Goals/Build.h b/AI/Nullkiller/Goals/Build.h index c6d972d9f..df2311e2e 100644 --- a/AI/Nullkiller/Goals/Build.h +++ b/AI/Nullkiller/Goals/Build.h @@ -12,7 +12,7 @@ #include "CGoal.h" struct HeroPtr; -class VCAI; +class AIGateway; class FuzzyHelper; namespace Goals diff --git a/AI/Nullkiller/Goals/BuildBoat.cpp b/AI/Nullkiller/Goals/BuildBoat.cpp index 83207d75c..0b934ffbf 100644 --- a/AI/Nullkiller/Goals/BuildBoat.cpp +++ b/AI/Nullkiller/Goals/BuildBoat.cpp @@ -9,13 +9,13 @@ */ #include "StdInc.h" #include "BuildBoat.h" -#include "../VCAI.h" +#include "../AIGateway.h" #include "../../../lib/mapping/CMap.h" //for victory conditions #include "../../../lib/CPathfinder.h" #include "../Behaviors/CaptureObjectsBehavior.h" extern boost::thread_specific_ptr cb; -extern boost::thread_specific_ptr ai; +extern boost::thread_specific_ptr ai; using namespace Goals; @@ -42,7 +42,7 @@ bool BuildBoat::operator==(const BuildBoat & other) const // return iAmElementar(); //} -void BuildBoat::accept(VCAI * ai) +void BuildBoat::accept(AIGateway * ai) { TResources boatCost; shipyard->getBoatCost(boatCost); diff --git a/AI/Nullkiller/Goals/BuildBoat.h b/AI/Nullkiller/Goals/BuildBoat.h index c13e1ac1a..858e6810f 100644 --- a/AI/Nullkiller/Goals/BuildBoat.h +++ b/AI/Nullkiller/Goals/BuildBoat.h @@ -24,7 +24,7 @@ namespace Goals { } - void accept(VCAI * ai) override; + void accept(AIGateway * ai) override; std::string toString() const override; virtual bool operator==(const BuildBoat & other) const override; }; diff --git a/AI/Nullkiller/Goals/BuildThis.cpp b/AI/Nullkiller/Goals/BuildThis.cpp index cd80454f5..c43a26796 100644 --- a/AI/Nullkiller/Goals/BuildThis.cpp +++ b/AI/Nullkiller/Goals/BuildThis.cpp @@ -9,7 +9,7 @@ */ #include "StdInc.h" #include "BuildThis.h" -#include "../VCAI.h" +#include "../AIGateway.h" #include "../AIUtility.h" #include "../../../lib/mapping/CMap.h" //for victory conditions #include "../../../lib/CPathfinder.h" @@ -17,10 +17,25 @@ extern boost::thread_specific_ptr cb; -extern boost::thread_specific_ptr ai; +extern boost::thread_specific_ptr ai; using namespace Goals; + +BuildThis::BuildThis(BuildingID Bid, const CGTownInstance * tid) + : ElementarGoal(Goals::BUILD_STRUCTURE) +{ + buildingInfo = BuildingInfo( + tid->town->buildings.at(Bid), + nullptr, + CreatureID::NONE, + tid, + nullptr); + + bid = Bid; + town = tid; +} + bool BuildThis::operator==(const BuildThis & other) const { return town == other.town && bid == other.bid; @@ -28,10 +43,10 @@ bool BuildThis::operator==(const BuildThis & other) const std::string BuildThis::toString() const { - return "Build " + buildingInfo.name + "(" + std::to_string(bid) + ") in " + town->name; + return "Build " + buildingInfo.name + " in " + town->name; } -void BuildThis::accept(VCAI * ai) +void BuildThis::accept(AIGateway * ai) { auto b = BuildingID(bid); diff --git a/AI/Nullkiller/Goals/BuildThis.h b/AI/Nullkiller/Goals/BuildThis.h index 6248530d4..a8a273ac9 100644 --- a/AI/Nullkiller/Goals/BuildThis.h +++ b/AI/Nullkiller/Goals/BuildThis.h @@ -13,7 +13,7 @@ #include "../Analyzers/BuildAnalyzer.h" struct HeroPtr; -class VCAI; +class AIGateway; class FuzzyHelper; namespace Goals @@ -34,21 +34,10 @@ namespace Goals bid = buildingInfo.id; town = townInfo.town; } - BuildThis(BuildingID Bid, const CGTownInstance * tid) - : ElementarGoal(Goals::BUILD_STRUCTURE) - { - bid = Bid; - town = tid; - priority = 1; - } - BuildThis(BuildingID Bid) - : ElementarGoal(Goals::BUILD_STRUCTURE) - { - bid = Bid; - priority = 1; - } + BuildThis(BuildingID Bid, const CGTownInstance * tid); + virtual bool operator==(const BuildThis & other) const override; virtual std::string toString() const override; - void accept(VCAI * ai) override; + void accept(AIGateway * ai) override; }; } diff --git a/AI/Nullkiller/Goals/BuyArmy.cpp b/AI/Nullkiller/Goals/BuyArmy.cpp index e4519093d..c4d6f7151 100644 --- a/AI/Nullkiller/Goals/BuyArmy.cpp +++ b/AI/Nullkiller/Goals/BuyArmy.cpp @@ -10,12 +10,12 @@ #include "../StdInc.h" #include "BuyArmy.h" #include "../../../lib/mapObjects/CGTownInstance.h" -#include "../VCAI.h" +#include "../AIGateway.h" #include "../Engine/Nullkiller.h" extern boost::thread_specific_ptr cb; -extern boost::thread_specific_ptr ai; +extern boost::thread_specific_ptr ai; using namespace Goals; @@ -29,7 +29,7 @@ std::string BuyArmy::toString() const return "Buy army at " + town->name; } -void BuyArmy::accept(VCAI * ai) +void BuyArmy::accept(AIGateway * ai) { ui64 valueBought = 0; //buy the stacks with largest AI value diff --git a/AI/Nullkiller/Goals/BuyArmy.h b/AI/Nullkiller/Goals/BuyArmy.h index 8b478fe32..79b6ef99d 100644 --- a/AI/Nullkiller/Goals/BuyArmy.h +++ b/AI/Nullkiller/Goals/BuyArmy.h @@ -12,7 +12,7 @@ #include "CGoal.h" struct HeroPtr; -class VCAI; +class AIGateway; class FuzzyHelper; namespace Goals @@ -37,6 +37,6 @@ namespace Goals virtual std::string toString() const override; - virtual void accept(VCAI * ai) override; + virtual void accept(AIGateway * ai) override; }; } diff --git a/AI/Nullkiller/Goals/CGoal.h b/AI/Nullkiller/Goals/CGoal.h index 0b2e7d322..5e0d341c8 100644 --- a/AI/Nullkiller/Goals/CGoal.h +++ b/AI/Nullkiller/Goals/CGoal.h @@ -12,7 +12,7 @@ #include "AbstractGoal.h" struct HeroPtr; -class VCAI; +class AIGateway; namespace Goals { @@ -115,7 +115,7 @@ namespace Goals return "Invalid"; } - virtual void accept(VCAI * ai) override + virtual void accept(AIGateway * ai) override { throw cannotFulfillGoalException("Can not fulfill Invalid goal!"); } diff --git a/AI/Nullkiller/Goals/CaptureObject.cpp b/AI/Nullkiller/Goals/CaptureObject.cpp index 574c562d1..1950e249f 100644 --- a/AI/Nullkiller/Goals/CaptureObject.cpp +++ b/AI/Nullkiller/Goals/CaptureObject.cpp @@ -10,7 +10,7 @@ #include "../StdInc.h" #include "CaptureObject.h" #include "../../../lib/mapObjects/CGTownInstance.h" -#include "../VCAI.h" +#include "../AIGateway.h" #include "../Engine/Nullkiller.h" #include "../Behaviors/CaptureObjectsBehavior.h" diff --git a/AI/Nullkiller/Goals/CaptureObject.h b/AI/Nullkiller/Goals/CaptureObject.h index 02de78cdc..a53a78ff0 100644 --- a/AI/Nullkiller/Goals/CaptureObject.h +++ b/AI/Nullkiller/Goals/CaptureObject.h @@ -12,7 +12,7 @@ #include "CGoal.h" struct HeroPtr; -class VCAI; +class AIGateway; class FuzzyHelper; namespace Goals diff --git a/AI/Nullkiller/Goals/CompleteQuest.cpp b/AI/Nullkiller/Goals/CompleteQuest.cpp index 60cac70a4..501d1237c 100644 --- a/AI/Nullkiller/Goals/CompleteQuest.cpp +++ b/AI/Nullkiller/Goals/CompleteQuest.cpp @@ -10,14 +10,14 @@ #include "StdInc.h" #include "CompleteQuest.h" #include "../Behaviors/CaptureObjectsBehavior.h" -#include "../VCAI.h" +#include "../AIGateway.h" #include "../../../lib/mapping/CMap.h" //for victory conditions #include "../../../lib/CPathfinder.h" #include "../../../lib/VCMI_Lib.h" #include "../../../lib/CGeneralTextHandler.h" extern boost::thread_specific_ptr cb; -extern boost::thread_specific_ptr ai; +extern boost::thread_specific_ptr ai; using namespace Goals; diff --git a/AI/Nullkiller/Goals/Composition.cpp b/AI/Nullkiller/Goals/Composition.cpp index 3b7e649e1..61151f388 100644 --- a/AI/Nullkiller/Goals/Composition.cpp +++ b/AI/Nullkiller/Goals/Composition.cpp @@ -9,7 +9,7 @@ */ #include "StdInc.h" #include "Composition.h" -#include "../VCAI.h" +#include "../AIGateway.h" #include "../AIUtility.h" #include "../../../lib/mapping/CMap.h" //for victory conditions #include "../../../lib/CPathfinder.h" @@ -17,7 +17,7 @@ extern boost::thread_specific_ptr cb; -extern boost::thread_specific_ptr ai; +extern boost::thread_specific_ptr ai; using namespace Goals; @@ -38,7 +38,7 @@ std::string Composition::toString() const return result; } -void Composition::accept(VCAI * ai) +void Composition::accept(AIGateway * ai) { taskptr(*subtasks.back())->accept(ai); } diff --git a/AI/Nullkiller/Goals/Composition.h b/AI/Nullkiller/Goals/Composition.h index ae4569ef3..7906b4841 100644 --- a/AI/Nullkiller/Goals/Composition.h +++ b/AI/Nullkiller/Goals/Composition.h @@ -31,7 +31,7 @@ namespace Goals virtual bool operator==(const Composition & other) const override; virtual std::string toString() const override; - void accept(VCAI * ai) override; + void accept(AIGateway * ai) override; Composition & addNext(const AbstractGoal & goal); Composition & addNext(TSubgoal goal); virtual TGoalVec decompose() const override; diff --git a/AI/Nullkiller/Goals/DigAtTile.cpp b/AI/Nullkiller/Goals/DigAtTile.cpp index e079b511c..9236a3788 100644 --- a/AI/Nullkiller/Goals/DigAtTile.cpp +++ b/AI/Nullkiller/Goals/DigAtTile.cpp @@ -9,12 +9,12 @@ */ #include "StdInc.h" #include "DigAtTile.h" -#include "../VCAI.h" +#include "../AIGateway.h" #include "../AIUtility.h" extern boost::thread_specific_ptr cb; -extern boost::thread_specific_ptr ai; +extern boost::thread_specific_ptr ai; using namespace Goals; diff --git a/AI/Nullkiller/Goals/DigAtTile.h b/AI/Nullkiller/Goals/DigAtTile.h index 79f4b1bf1..21af09404 100644 --- a/AI/Nullkiller/Goals/DigAtTile.h +++ b/AI/Nullkiller/Goals/DigAtTile.h @@ -12,7 +12,7 @@ #include "CGoal.h" struct HeroPtr; -class VCAI; +class AIGateway; class FuzzyHelper; namespace Goals diff --git a/AI/Nullkiller/Goals/DismissHero.cpp b/AI/Nullkiller/Goals/DismissHero.cpp index 967f0e65f..d84e79ca5 100644 --- a/AI/Nullkiller/Goals/DismissHero.cpp +++ b/AI/Nullkiller/Goals/DismissHero.cpp @@ -9,12 +9,12 @@ */ #include "StdInc.h" #include "DismissHero.h" -#include "../VCAI.h" +#include "../AIGateway.h" #include "../../../lib/mapping/CMap.h" //for victory conditions #include "../../../lib/CPathfinder.h" extern boost::thread_specific_ptr cb; -extern boost::thread_specific_ptr ai; +extern boost::thread_specific_ptr ai; using namespace Goals; @@ -23,7 +23,7 @@ bool DismissHero::operator==(const DismissHero & other) const return hero.h == other.hero.h; } -void DismissHero::accept(VCAI * ai) +void DismissHero::accept(AIGateway * ai) { if(!hero.validAndSet()) throw cannotFulfillGoalException("Invalid hero!"); diff --git a/AI/Nullkiller/Goals/DismissHero.h b/AI/Nullkiller/Goals/DismissHero.h index 2b1de0806..7437875e8 100644 --- a/AI/Nullkiller/Goals/DismissHero.h +++ b/AI/Nullkiller/Goals/DismissHero.h @@ -22,7 +22,7 @@ namespace Goals sethero(hero); } - void accept(VCAI * ai) override; + void accept(AIGateway * ai) override; std::string toString() const override; virtual bool operator==(const DismissHero & other) const override; }; diff --git a/AI/Nullkiller/Goals/ExchangeSwapTownHeroes.cpp b/AI/Nullkiller/Goals/ExchangeSwapTownHeroes.cpp index fd0848f38..f35213a37 100644 --- a/AI/Nullkiller/Goals/ExchangeSwapTownHeroes.cpp +++ b/AI/Nullkiller/Goals/ExchangeSwapTownHeroes.cpp @@ -10,13 +10,13 @@ #include "StdInc.h" #include "ExchangeSwapTownHeroes.h" #include "ExecuteHeroChain.h" -#include "../VCAI.h" +#include "../AIGateway.h" #include "../../../lib/mapping/CMap.h" //for victory conditions #include "../../../lib/CPathfinder.h" #include "../Engine/Nullkiller.h" extern boost::thread_specific_ptr cb; -extern boost::thread_specific_ptr ai; +extern boost::thread_specific_ptr ai; using namespace Goals; @@ -38,7 +38,7 @@ bool ExchangeSwapTownHeroes::operator==(const ExchangeSwapTownHeroes & other) co return town == other.town; } -void ExchangeSwapTownHeroes::accept(VCAI * ai) +void ExchangeSwapTownHeroes::accept(AIGateway * ai) { if(!garrisonHero) { diff --git a/AI/Nullkiller/Goals/ExchangeSwapTownHeroes.h b/AI/Nullkiller/Goals/ExchangeSwapTownHeroes.h index 9c632b281..00e4e1f83 100644 --- a/AI/Nullkiller/Goals/ExchangeSwapTownHeroes.h +++ b/AI/Nullkiller/Goals/ExchangeSwapTownHeroes.h @@ -27,7 +27,7 @@ namespace Goals const CGHeroInstance * garrisonHero = nullptr, HeroLockedReason lockingReason = HeroLockedReason::NOT_LOCKED); - void accept(VCAI * ai) override; + void accept(AIGateway * ai) override; std::string toString() const override; virtual bool operator==(const ExchangeSwapTownHeroes & other) const override; }; diff --git a/AI/Nullkiller/Goals/ExecuteHeroChain.cpp b/AI/Nullkiller/Goals/ExecuteHeroChain.cpp index f941dcaee..dcfde92f1 100644 --- a/AI/Nullkiller/Goals/ExecuteHeroChain.cpp +++ b/AI/Nullkiller/Goals/ExecuteHeroChain.cpp @@ -9,13 +9,13 @@ */ #include "StdInc.h" #include "ExecuteHeroChain.h" -#include "../VCAI.h" +#include "../AIGateway.h" #include "../../../lib/mapping/CMap.h" //for victory conditions #include "../../../lib/CPathfinder.h" #include "../Engine/Nullkiller.h" extern boost::thread_specific_ptr cb; -extern boost::thread_specific_ptr ai; +extern boost::thread_specific_ptr ai; using namespace Goals; @@ -44,7 +44,7 @@ bool ExecuteHeroChain::operator==(const ExecuteHeroChain & other) const && chainPath.chainMask == other.chainPath.chainMask; } -void ExecuteHeroChain::accept(VCAI * ai) +void ExecuteHeroChain::accept(AIGateway * ai) { logAi->debug("Executing hero chain towards %s. Path %s", targetName, chainPath.toString()); @@ -59,6 +59,11 @@ void ExecuteHeroChain::accept(VCAI * ai) const CGHeroInstance * hero = node.targetHero; HeroPtr heroPtr = hero; + if(node.parentIndex >= i) + { + logAi->error("Invalid parentIndex while executing node " + node.coord.toString()); + } + if(vstd::contains(blockedIndexes, i)) { blockedIndexes.insert(node.parentIndex); diff --git a/AI/Nullkiller/Goals/ExecuteHeroChain.h b/AI/Nullkiller/Goals/ExecuteHeroChain.h index 9fb71d60f..8e3b4085b 100644 --- a/AI/Nullkiller/Goals/ExecuteHeroChain.h +++ b/AI/Nullkiller/Goals/ExecuteHeroChain.h @@ -26,7 +26,7 @@ namespace Goals ExecuteHeroChain(const AIPath & path, const CGObjectInstance * obj = nullptr); - void accept(VCAI * ai) override; + void accept(AIGateway * ai) override; std::string toString() const override; virtual bool operator==(const ExecuteHeroChain & other) const override; const AIPath & getPath() const { return chainPath; } diff --git a/AI/Nullkiller/Goals/GatherArmy.cpp b/AI/Nullkiller/Goals/GatherArmy.cpp index df6620a81..82e9f361a 100644 --- a/AI/Nullkiller/Goals/GatherArmy.cpp +++ b/AI/Nullkiller/Goals/GatherArmy.cpp @@ -9,7 +9,7 @@ */ #include "StdInc.h" #include "Goals.h" -#include "../VCAI.h" +#include "../AIGateway.h" #include "../AIUtility.h" #include "../AIhelper.h" #include "../FuzzyHelper.h" @@ -21,7 +21,7 @@ extern boost::thread_specific_ptr cb; -extern boost::thread_specific_ptr ai; +extern boost::thread_specific_ptr ai; extern FuzzyHelper * fh; using namespace Goals; diff --git a/AI/Nullkiller/Goals/GatherArmy.h b/AI/Nullkiller/Goals/GatherArmy.h index 97108df76..d48e03e87 100644 --- a/AI/Nullkiller/Goals/GatherArmy.h +++ b/AI/Nullkiller/Goals/GatherArmy.h @@ -12,7 +12,7 @@ #include "CGoal.h" struct HeroPtr; -class VCAI; +class AIGateway; class FuzzyHelper; namespace Goals diff --git a/AI/Nullkiller/Goals/Invalid.h b/AI/Nullkiller/Goals/Invalid.h index a67d80ed5..62326d387 100644 --- a/AI/Nullkiller/Goals/Invalid.h +++ b/AI/Nullkiller/Goals/Invalid.h @@ -12,7 +12,7 @@ #include "CGoal.h" struct HeroPtr; -class VCAI; +class AIGateway; namespace Goals { diff --git a/AI/Nullkiller/Goals/RecruitHero.cpp b/AI/Nullkiller/Goals/RecruitHero.cpp index 6969eab70..d6b2450aa 100644 --- a/AI/Nullkiller/Goals/RecruitHero.cpp +++ b/AI/Nullkiller/Goals/RecruitHero.cpp @@ -9,7 +9,7 @@ */ #include "StdInc.h" #include "Goals.h" -#include "../VCAI.h" +#include "../AIGateway.h" #include "../AIUtility.h" #include "../../../lib/mapping/CMap.h" //for victory conditions #include "../../../lib/CPathfinder.h" @@ -17,7 +17,7 @@ extern boost::thread_specific_ptr cb; -extern boost::thread_specific_ptr ai; +extern boost::thread_specific_ptr ai; using namespace Goals; @@ -26,7 +26,7 @@ std::string RecruitHero::toString() const return "Recruit hero at " + town->name; } -void RecruitHero::accept(VCAI * ai) +void RecruitHero::accept(AIGateway * ai) { auto t = town; diff --git a/AI/Nullkiller/Goals/RecruitHero.h b/AI/Nullkiller/Goals/RecruitHero.h index 06d5212e6..5f8b98fd7 100644 --- a/AI/Nullkiller/Goals/RecruitHero.h +++ b/AI/Nullkiller/Goals/RecruitHero.h @@ -12,7 +12,7 @@ #include "CGoal.h" struct HeroPtr; -class VCAI; +class AIGateway; class FuzzyHelper; namespace Goals @@ -39,6 +39,6 @@ namespace Goals } virtual std::string toString() const override; - void accept(VCAI * ai) override; + void accept(AIGateway * ai) override; }; } diff --git a/AI/Nullkiller/Goals/SaveResources.cpp b/AI/Nullkiller/Goals/SaveResources.cpp new file mode 100644 index 000000000..d3f216898 --- /dev/null +++ b/AI/Nullkiller/Goals/SaveResources.cpp @@ -0,0 +1,39 @@ +/* +* SaveResources.cpp, part of VCMI engine +* +* Authors: listed in file AUTHORS in main folder +* +* License: GNU General Public License v2.0 or later +* Full text of license available in license.txt file, in main folder +* +*/ +#include "StdInc.h" +#include "SaveResources.h" +#include "../AIGateway.h" +#include "../../../lib/mapping/CMap.h" //for victory conditions +#include "../../../lib/CPathfinder.h" +#include "../Behaviors/CaptureObjectsBehavior.h" + +extern boost::thread_specific_ptr cb; +extern boost::thread_specific_ptr ai; + +using namespace Goals; + +bool SaveResources::operator==(const SaveResources & other) const +{ + return true; +} + +void SaveResources::accept(AIGateway * ai) +{ + ai->nullkiller->lockResources(resources); + + logAi->debug("Locked %s resources", resources.toString()); + + throw goalFulfilledException(sptr(*this)); +} + +std::string SaveResources::toString() const +{ + return "SaveResources " + resources.toString(); +} diff --git a/AI/Nullkiller/Goals/SaveResources.h b/AI/Nullkiller/Goals/SaveResources.h new file mode 100644 index 000000000..26bb9a005 --- /dev/null +++ b/AI/Nullkiller/Goals/SaveResources.h @@ -0,0 +1,31 @@ +/* +* SaveResources.h, part of VCMI engine +* +* Authors: listed in file AUTHORS in main folder +* +* License: GNU General Public License v2.0 or later +* Full text of license available in license.txt file, in main folder +* +*/ +#pragma once + +#include "CGoal.h" + +namespace Goals +{ + class DLL_EXPORT SaveResources : public ElementarGoal + { + private: + TResources resources; + + public: + SaveResources(TResources resources) + : ElementarGoal(Goals::SAVE_RESOURCES), resources(resources) + { + } + + void accept(AIGateway * ai) override; + std::string toString() const override; + virtual bool operator==(const SaveResources & other) const override; + }; +} diff --git a/AI/Nullkiller/Goals/Trade.h b/AI/Nullkiller/Goals/Trade.h index d9b41ed1b..6109e517f 100644 --- a/AI/Nullkiller/Goals/Trade.h +++ b/AI/Nullkiller/Goals/Trade.h @@ -12,7 +12,7 @@ #include "CGoal.h" struct HeroPtr; -class VCAI; +class AIGateway; class FuzzyHelper; namespace Goals diff --git a/AI/Nullkiller/Goals/Win.cpp b/AI/Nullkiller/Goals/Win.cpp index a0c96135d..82fc11776 100644 --- a/AI/Nullkiller/Goals/Win.cpp +++ b/AI/Nullkiller/Goals/Win.cpp @@ -9,7 +9,7 @@ */ #include "StdInc.h" #include "Goals.h" -#include "../VCAI.h" +#include "../AIGateway.h" #include "../AIUtility.h" #include "../AIhelper.h" #include "../FuzzyHelper.h" @@ -19,7 +19,7 @@ extern boost::thread_specific_ptr cb; -extern boost::thread_specific_ptr ai; +extern boost::thread_specific_ptr ai; extern FuzzyHelper * fh; using namespace Goals; diff --git a/AI/Nullkiller/Goals/Win.h b/AI/Nullkiller/Goals/Win.h index 07dfcdee5..df24b7fd4 100644 --- a/AI/Nullkiller/Goals/Win.h +++ b/AI/Nullkiller/Goals/Win.h @@ -12,7 +12,7 @@ #include "CGoal.h" struct HeroPtr; -class VCAI; +class AIGateway; class FuzzyHelper; namespace Goals diff --git a/AI/Nullkiller/Markers/ArmyUpgrade.cpp b/AI/Nullkiller/Markers/ArmyUpgrade.cpp index c5341d672..8720139e9 100644 --- a/AI/Nullkiller/Markers/ArmyUpgrade.cpp +++ b/AI/Nullkiller/Markers/ArmyUpgrade.cpp @@ -9,12 +9,12 @@ */ #include "StdInc.h" #include "ArmyUpgrade.h" -#include "../VCAI.h" +#include "../AIGateway.h" #include "../Engine/Nullkiller.h" #include "../AIUtility.h" extern boost::thread_specific_ptr cb; -extern boost::thread_specific_ptr ai; +extern boost::thread_specific_ptr ai; using namespace Goals; diff --git a/AI/Nullkiller/Markers/DefendTown.cpp b/AI/Nullkiller/Markers/DefendTown.cpp index 06dfabfdd..62e50585e 100644 --- a/AI/Nullkiller/Markers/DefendTown.cpp +++ b/AI/Nullkiller/Markers/DefendTown.cpp @@ -9,7 +9,7 @@ */ #include "StdInc.h" #include "DefendTown.h" -#include "../VCAI.h" +#include "../AIGateway.h" #include "../Engine/Nullkiller.h" #include "../AIUtility.h" diff --git a/AI/Nullkiller/Markers/HeroExchange.cpp b/AI/Nullkiller/Markers/HeroExchange.cpp index d58b6838e..e673ce0b4 100644 --- a/AI/Nullkiller/Markers/HeroExchange.cpp +++ b/AI/Nullkiller/Markers/HeroExchange.cpp @@ -9,13 +9,13 @@ */ #include "StdInc.h" #include "HeroExchange.h" -#include "../VCAI.h" +#include "../AIGateway.h" #include "../Engine/Nullkiller.h" #include "../AIUtility.h" #include "../Analyzers/ArmyManager.h" extern boost::thread_specific_ptr cb; -extern boost::thread_specific_ptr ai; +extern boost::thread_specific_ptr ai; using namespace Goals; diff --git a/AI/Nullkiller/Markers/UnlockCluster.cpp b/AI/Nullkiller/Markers/UnlockCluster.cpp index 66ddb89f1..ef24095f3 100644 --- a/AI/Nullkiller/Markers/UnlockCluster.cpp +++ b/AI/Nullkiller/Markers/UnlockCluster.cpp @@ -9,12 +9,12 @@ */ #include "StdInc.h" #include "UnlockCluster.h" -#include "../VCAI.h" +#include "../AIGateway.h" #include "../Engine/Nullkiller.h" #include "../AIUtility.h" extern boost::thread_specific_ptr cb; -extern boost::thread_specific_ptr ai; +extern boost::thread_specific_ptr ai; using namespace Goals; diff --git a/AI/Nullkiller/Markers/UnlockCluster.h b/AI/Nullkiller/Markers/UnlockCluster.h index b55195087..3e40ab850 100644 --- a/AI/Nullkiller/Markers/UnlockCluster.h +++ b/AI/Nullkiller/Markers/UnlockCluster.h @@ -14,7 +14,7 @@ struct HeroPtr; -class VCAI; +class AIGateway; class FuzzyHelper; namespace Goals diff --git a/AI/Nullkiller/Pathfinding/AINodeStorage.cpp b/AI/Nullkiller/Pathfinding/AINodeStorage.cpp index a98da1d23..138add1c1 100644 --- a/AI/Nullkiller/Pathfinding/AINodeStorage.cpp +++ b/AI/Nullkiller/Pathfinding/AINodeStorage.cpp @@ -11,7 +11,7 @@ #include "AINodeStorage.h" #include "Actions/TownPortalAction.h" #include "../Goals/Goals.h" -#include "../VCAI.h" +#include "../AIGateway.h" #include "../Engine/Nullkiller.h" #include "../../../CCallback.h" #include "../../../lib/mapping/CMap.h" diff --git a/AI/Nullkiller/Pathfinding/AINodeStorage.h b/AI/Nullkiller/Pathfinding/AINodeStorage.h index cf9e910cc..368e6681a 100644 --- a/AI/Nullkiller/Pathfinding/AINodeStorage.h +++ b/AI/Nullkiller/Pathfinding/AINodeStorage.h @@ -11,7 +11,7 @@ #pragma once #define PATHFINDER_TRACE_LEVEL 0 -#define AI_TRACE_LEVEL 0 +#define AI_TRACE_LEVEL 1 #define SCOUT_TURN_DISTANCE_LIMIT 3 #define MAIN_TURN_DISTANCE_LIMIT 5 diff --git a/AI/Nullkiller/Pathfinding/Actions/BattleAction.cpp b/AI/Nullkiller/Pathfinding/Actions/BattleAction.cpp index d395c7349..fcfc0fac2 100644 --- a/AI/Nullkiller/Pathfinding/Actions/BattleAction.cpp +++ b/AI/Nullkiller/Pathfinding/Actions/BattleAction.cpp @@ -10,12 +10,12 @@ #include "StdInc.h" #include "BattleAction.h" -#include "../../VCAI.h" +#include "../../AIGateway.h" #include "../../Goals/CompleteQuest.h" #include "../../../../lib/mapping/CMap.h" //for victory conditions extern boost::thread_specific_ptr cb; -extern boost::thread_specific_ptr ai; +extern boost::thread_specific_ptr ai; namespace AIPathfinding { diff --git a/AI/Nullkiller/Pathfinding/Actions/BoatActions.cpp b/AI/Nullkiller/Pathfinding/Actions/BoatActions.cpp index d9f2be544..39aec27a2 100644 --- a/AI/Nullkiller/Pathfinding/Actions/BoatActions.cpp +++ b/AI/Nullkiller/Pathfinding/Actions/BoatActions.cpp @@ -9,7 +9,7 @@ */ #include "StdInc.h" -#include "../../VCAI.h" +#include "../../AIGateway.h" #include "../../Goals/AdventureSpellCast.h" #include "../../Goals/CaptureObject.h" #include "../../Goals/BuildBoat.h" @@ -18,7 +18,7 @@ #include "BoatActions.h" extern boost::thread_specific_ptr cb; -extern boost::thread_specific_ptr ai; +extern boost::thread_specific_ptr ai; namespace AIPathfinding { diff --git a/AI/Nullkiller/Pathfinding/Actions/BuyArmyAction.cpp b/AI/Nullkiller/Pathfinding/Actions/BuyArmyAction.cpp index 48ddf0277..338a8b918 100644 --- a/AI/Nullkiller/Pathfinding/Actions/BuyArmyAction.cpp +++ b/AI/Nullkiller/Pathfinding/Actions/BuyArmyAction.cpp @@ -10,12 +10,12 @@ #include "StdInc.h" #include "BuyArmyAction.h" -#include "../../VCAI.h" +#include "../../AIGateway.h" #include "../../Goals/CompleteQuest.h" #include "../../../../lib/mapping/CMap.h" //for victory conditions extern boost::thread_specific_ptr cb; -extern boost::thread_specific_ptr ai; +extern boost::thread_specific_ptr ai; namespace AIPathfinding { diff --git a/AI/Nullkiller/Pathfinding/Actions/QuestAction.cpp b/AI/Nullkiller/Pathfinding/Actions/QuestAction.cpp index 7b35a2915..5249d6396 100644 --- a/AI/Nullkiller/Pathfinding/Actions/QuestAction.cpp +++ b/AI/Nullkiller/Pathfinding/Actions/QuestAction.cpp @@ -10,12 +10,12 @@ #include "StdInc.h" #include "QuestAction.h" -#include "../../VCAI.h" +#include "../../AIGateway.h" #include "../../Goals/CompleteQuest.h" #include "../../../../lib/mapping/CMap.h" //for victory conditions extern boost::thread_specific_ptr cb; -extern boost::thread_specific_ptr ai; +extern boost::thread_specific_ptr ai; namespace AIPathfinding { diff --git a/AI/Nullkiller/Pathfinding/Actions/SpecialAction.cpp b/AI/Nullkiller/Pathfinding/Actions/SpecialAction.cpp index 4a8de524e..75222ac9e 100644 --- a/AI/Nullkiller/Pathfinding/Actions/SpecialAction.cpp +++ b/AI/Nullkiller/Pathfinding/Actions/SpecialAction.cpp @@ -10,7 +10,7 @@ #include "StdInc.h" #include "SpecialAction.h" -#include "../../VCAI.h" +#include "../../AIGateway.h" #include "../../Goals/CGoal.h" Goals::TSubgoal SpecialAction::decompose(const CGHeroInstance * hero) const diff --git a/AI/Nullkiller/Pathfinding/Actions/TownPortalAction.cpp b/AI/Nullkiller/Pathfinding/Actions/TownPortalAction.cpp index b7bbfab0e..889ec1245 100644 --- a/AI/Nullkiller/Pathfinding/Actions/TownPortalAction.cpp +++ b/AI/Nullkiller/Pathfinding/Actions/TownPortalAction.cpp @@ -17,7 +17,7 @@ using namespace AIPathfinding; extern boost::thread_specific_ptr cb; -extern boost::thread_specific_ptr ai; +extern boost::thread_specific_ptr ai; void TownPortalAction::execute(const CGHeroInstance * hero) const { diff --git a/AI/Nullkiller/Pathfinding/Actors.cpp b/AI/Nullkiller/Pathfinding/Actors.cpp index 0c277b2f3..5178606e3 100644 --- a/AI/Nullkiller/Pathfinding/Actors.cpp +++ b/AI/Nullkiller/Pathfinding/Actors.cpp @@ -9,7 +9,7 @@ */ #include "StdInc.h" #include "Actors.h" -#include "../VCAI.h" +#include "../AIGateway.h" #include "../Engine/Nullkiller.h" #include "../../../CCallback.h" #include "../../../lib/mapping/CMap.h" diff --git a/AI/Nullkiller/Pathfinding/PathfindingManager.cpp b/AI/Nullkiller/Pathfinding/PathfindingManager.cpp deleted file mode 100644 index 9b658708d..000000000 --- a/AI/Nullkiller/Pathfinding/PathfindingManager.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/* -* PathfindingManager.cpp, part of VCMI engine -* -* Authors: listed in file AUTHORS in main folder -* -* License: GNU General Public License v2.0 or later -* Full text of license available in license.txt file, in main folder -* -*/ -#include "StdInc.h" -#include "PathfindingManager.h" -#include "AIPathfinder.h" -#include "AIPathfinderConfig.h" -#include "../Goals/Goals.h" -#include "../../../lib/CGameInfoCallback.h" -#include "../../../lib/mapping/CMap.h" - -PathfindingManager::PathfindingManager(CPlayerSpecificInfoCallback * CB, VCAI * AI) - : ai(AI), cb(CB) -{ -} - -void PathfindingManager::init(CPlayerSpecificInfoCallback * CB) -{ - cb = CB; - pathfinder.reset(new AIPathfinder(cb, ai)); - pathfinder->init(); -} - -void PathfindingManager::setAI(VCAI * AI) -{ - ai = AI; -} - -std::vector PathfindingManager::getPathsToTile(const HeroPtr & hero, const int3 & tile) const -{ - auto paths = pathfinder->getPathInfo(tile); - - vstd::erase_if(paths, [&](AIPath & path) -> bool{ - return path.targetHero != hero.h; - }); - - return paths; -} - -std::vector PathfindingManager::getPathsToTile(const int3 & tile) const -{ - return pathfinder->getPathInfo(tile); -} - -void PathfindingManager::updatePaths(std::vector heroes, bool useHeroChain) -{ - logAi->debug("AIPathfinder has been reseted."); - pathfinder->updatePaths(heroes, useHeroChain); -} diff --git a/AI/Nullkiller/Pathfinding/Rules/AILayerTransitionRule.h b/AI/Nullkiller/Pathfinding/Rules/AILayerTransitionRule.h index 722ab6421..b18da7f7b 100644 --- a/AI/Nullkiller/Pathfinding/Rules/AILayerTransitionRule.h +++ b/AI/Nullkiller/Pathfinding/Rules/AILayerTransitionRule.h @@ -11,7 +11,7 @@ #pragma once #include "../AINodeStorage.h" -#include "../../VCAI.h" +#include "../../AIGateway.h" #include "../Actions/BoatActions.h" #include "../../../../CCallback.h" #include "../../../../lib/mapping/CMap.h" diff --git a/AI/Nullkiller/Pathfinding/Rules/AIMovementAfterDestinationRule.h b/AI/Nullkiller/Pathfinding/Rules/AIMovementAfterDestinationRule.h index fd1193889..c118bdc40 100644 --- a/AI/Nullkiller/Pathfinding/Rules/AIMovementAfterDestinationRule.h +++ b/AI/Nullkiller/Pathfinding/Rules/AIMovementAfterDestinationRule.h @@ -11,7 +11,7 @@ #pragma once #include "../AINodeStorage.h" -#include "../../VCAI.h" +#include "../../AIGateway.h" #include "../../../../CCallback.h" #include "../../../../lib/mapping/CMap.h" #include "../../../../lib/mapObjects/MapObjects.h" diff --git a/AI/Nullkiller/Pathfinding/Rules/AIMovementToDestinationRule.h b/AI/Nullkiller/Pathfinding/Rules/AIMovementToDestinationRule.h index 6f0e8ac01..4d0da1b49 100644 --- a/AI/Nullkiller/Pathfinding/Rules/AIMovementToDestinationRule.h +++ b/AI/Nullkiller/Pathfinding/Rules/AIMovementToDestinationRule.h @@ -11,7 +11,7 @@ #pragma once #include "../AINodeStorage.h" -#include "../../VCAI.h" +#include "../../AIGateway.h" #include "../../../../CCallback.h" #include "../../../../lib/mapping/CMap.h" #include "../../../../lib/mapObjects/MapObjects.h" diff --git a/AI/Nullkiller/Pathfinding/Rules/AIPreviousNodeRule.h b/AI/Nullkiller/Pathfinding/Rules/AIPreviousNodeRule.h index d97aa53b5..d3847c862 100644 --- a/AI/Nullkiller/Pathfinding/Rules/AIPreviousNodeRule.h +++ b/AI/Nullkiller/Pathfinding/Rules/AIPreviousNodeRule.h @@ -11,7 +11,7 @@ #pragma once #include "../AINodeStorage.h" -#include "../../VCAI.h" +#include "../../AIGateway.h" #include "../../../../CCallback.h" #include "../../../../lib/mapping/CMap.h" #include "../../../../lib/mapObjects/MapObjects.h" diff --git a/AI/Nullkiller/VCAI.cbp b/AI/Nullkiller/VCAI.cbp deleted file mode 100644 index f63dbc85e..000000000 --- a/AI/Nullkiller/VCAI.cbp +++ /dev/null @@ -1,194 +0,0 @@ - - - - - - diff --git a/AI/Nullkiller/VCAI.vcxproj b/AI/Nullkiller/VCAI.vcxproj deleted file mode 100644 index 4160f8f59..000000000 --- a/AI/Nullkiller/VCAI.vcxproj +++ /dev/null @@ -1,246 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - RD - Win32 - - - RD - x64 - - - - {276C3DB0-7A6B-4417-8E5C-322B08633AAC} - StupidAI - 10.0 - - - - DynamicLibrary - true - MultiByte - v140_xp - - - DynamicLibrary - true - MultiByte - v140_xp - - - DynamicLibrary - false - true - MultiByte - v142 - - - DynamicLibrary - false - true - MultiByte - v140_xp - - - - - - - - - - - - - - - - - - - - - - - - - - - $(VCMI_Out)\AI\ - - - $(VCMI_Out)\AI\ - - - $(VCMI_Out)/AI - - - $(VCMI_Out)\AI\ - - - - $(FUZZYLITEDIR) - Use - StdInc.h - /Zm210 %(AdditionalOptions) - - - VCMI_lib.lib;FuzzyLite.lib;%(AdditionalDependencies) - ..\..\..\libs;..\..;.. - - - - - - - Use - StdInc.h - /Zm150 %(AdditionalOptions) - - - VCMI_lib.lib;FuzzyLite.lib;%(AdditionalDependencies) - $(VCMI_Out);$(OutDir);%(AdditionalLibraryDirectories) - - - - - ..\FuzzyLite\fuzzylite - Use - StdInc.h - true - Disabled - - - VCMI_lib.lib;FuzzyLite.lib;%(AdditionalDependencies) - $(VCMI_Out);$(SolutionDir)\AI - /d2:-notypeopt %(AdditionalOptions) - - - - - - - Use - StdInc.h - /Zm150 %(AdditionalOptions) - - - VCMI_lib.lib;FuzzyLite.lib;%(AdditionalDependencies) - $(VCMI_Out);$(OutDir);%(AdditionalLibraryDirectories) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Create - Create - Create - Create - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/AI/Nullkiller/VCAI.vcxproj.filters b/AI/Nullkiller/VCAI.vcxproj.filters deleted file mode 100644 index ca64f2922..000000000 --- a/AI/Nullkiller/VCAI.vcxproj.filters +++ /dev/null @@ -1,254 +0,0 @@ - - - - - - - - - - - - - - - - Pathfinding - - - Pathfinding - - - Pathfinding - - - Pathfinding - - - Goals - - - Goals - - - Goals - - - Goals - - - Goals - - - Goals - - - Goals - - - Goals - - - Goals - - - Goals - - - Goals - - - Goals - - - Goals - - - Goals - - - Goals - - - Goals - - - Goals - - - Goals - - - Goals - - - Goals - - - Goals - - - Goals - - - Pathfinding\Actions - - - Pathfinding\Actions - - - Pathfinding\Actions - - - Pathfinding\Rules - - - Pathfinding\Rules - - - Pathfinding\Rules - - - Pathfinding\Rules - - - - - - - - - - - - - - - - Pathfinding - - - Pathfinding - - - Pathfinding - - - Pathfinding - - - Goals - - - Goals - - - Goals - - - Goals - - - Goals - - - Goals - - - Goals - - - Goals - - - Goals - - - Goals - - - Goals - - - Goals - - - Goals - - - Goals - - - Goals - - - Goals - - - Goals - - - Goals - - - Goals - - - Goals - - - Goals - - - Goals - - - Goals - - - Goals - - - Goals - - - Pathfinding\Actions - - - Pathfinding\Actions - - - Pathfinding\Actions - - - Pathfinding\Actions - - - Pathfinding\Rules - - - Pathfinding\Rules - - - Pathfinding\Rules - - - Pathfinding\Rules - - - - - - {f0ef4866-37a3-4a10-a6bf-34460fcefab5} - - - {f97140a0-eee3-456f-b586-4b13265c01da} - - - {beabfdb9-2e76-4daa-8d1a-81086387f319} - - - {3ebb4852-a986-447a-b5cc-20992df76f0c} - - - \ No newline at end of file diff --git a/AI/Nullkiller/main.cpp b/AI/Nullkiller/main.cpp index 3a88b2716..a6a95ef24 100644 --- a/AI/Nullkiller/main.cpp +++ b/AI/Nullkiller/main.cpp @@ -8,13 +8,13 @@ * */ #include "StdInc.h" -#include "VCAI.h" +#include "AIGateway.h" #ifdef __GNUC__ #define strcpy_s(a, b, c) strncpy(a, c, b) #endif -static const char * g_cszAiName = "VCAI"; +static const char * g_cszAiName = "Nullkiller"; extern "C" DLL_EXPORT int GetGlobalAiVersion() { @@ -28,5 +28,5 @@ extern "C" DLL_EXPORT void GetAiName(char * name) extern "C" DLL_EXPORT void GetNewAI(std::shared_ptr & out) { - out = std::make_shared(); + out = std::make_shared(); } diff --git a/AUTHORS b/AUTHORS index f6e78f8f4..3204092bb 100644 --- a/AUTHORS +++ b/AUTHORS @@ -74,7 +74,7 @@ Andrzej Żak aka godric3 * minor bug fixes and modding features Andrii Danylchenko - * VCAI improvements + * Nullkiller AI, VCAI improvements Dmitry Orlov, * special buildings support in fan towns, new features and bug fixes diff --git a/CI/msvc/install.sh b/CI/msvc/install.sh index c912378af..3e5c71f66 100644 --- a/CI/msvc/install.sh +++ b/CI/msvc/install.sh @@ -4,9 +4,12 @@ git submodule update --init --recursive cd .. curl -LfsS -o "vcpkg-export-${VCMI_BUILD_PLATFORM}-windows-v140.7z" \ - "https://github.com/vcmi/vcmi-deps-windows/releases/download/v1.2/vcpkg-export-${VCMI_BUILD_PLATFORM}-windows-v140.7z" + "https://github.com/nullkiller/vcmi-deps-windows/releases/download/v1.3/vcpkg-export-${VCMI_BUILD_PLATFORM}-windows-v140.7z" 7z x "vcpkg-export-${VCMI_BUILD_PLATFORM}-windows-v140.7z" +rmdir vcpkg\installed\${VCMI_BUILD_PLATFORM}-windows\debug /S/Q +xcopy vcpkg\installed\${VCMI_BUILD_PLATFORM}-windows\bin vcpkg\installed\${VCMI_BUILD_PLATFORM}-windows\debug\bin /S/I/Q + cd $APPVEYOR_BUILD_FOLDER mkdir build_$VCMI_BUILD_PLATFORM cd build_$VCMI_BUILD_PLATFORM diff --git a/CI/mxe/before_install.sh b/CI/mxe/before_install.sh index 0794f1817..dbef4671d 100644 --- a/CI/mxe/before_install.sh +++ b/CI/mxe/before_install.sh @@ -14,28 +14,28 @@ sudo dpkg -i mxe-*.deb sudo apt-get install -f --yes if false; then -# Add MXE repository and key -echo "deb http://pkg.mxe.cc/repos/apt trusty main" \ - | sudo tee /etc/apt/sources.list.d/mxeapt.list + # Add MXE repository and key + echo "deb http://pkg.mxe.cc/repos/apt trusty main" \ + | sudo tee /etc/apt/sources.list.d/mxeapt.list -sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 86B72ED9 + sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys D43A795B73B16ABE9643FE1AFD8FFF16DB45C6AB -# Install needed packages -sudo apt-get update -qq + # Install needed packages + sudo apt-get update -qq -sudo apt-get install -q --yes \ -mxe-$MXE_TARGET-gcc \ -mxe-$MXE_TARGET-boost \ -mxe-$MXE_TARGET-zlib \ -mxe-$MXE_TARGET-sdl2 \ -mxe-$MXE_TARGET-sdl2-gfx \ -mxe-$MXE_TARGET-sdl2-image \ -mxe-$MXE_TARGET-sdl2-mixer \ -mxe-$MXE_TARGET-sdl2-ttf \ -mxe-$MXE_TARGET-ffmpeg \ -mxe-$MXE_TARGET-qt \ -mxe-$MXE_TARGET-qtbase \ -mxe-i686-w64-mingw32.static-luajit + sudo apt-get install -q --yes \ + mxe-$MXE_TARGET-gcc \ + mxe-$MXE_TARGET-boost \ + mxe-$MXE_TARGET-zlib \ + mxe-$MXE_TARGET-sdl2 \ + mxe-$MXE_TARGET-sdl2-gfx \ + mxe-$MXE_TARGET-sdl2-image \ + mxe-$MXE_TARGET-sdl2-mixer \ + mxe-$MXE_TARGET-sdl2-ttf \ + mxe-$MXE_TARGET-ffmpeg \ + mxe-$MXE_TARGET-qt \ + mxe-$MXE_TARGET-qtbase \ + mxe-i686-w64-mingw32.static-luajit fi # Disable diff --git a/CMakeLists.txt b/CMakeLists.txt index 6995eef89..1b06c6ca0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -224,6 +224,7 @@ find_package(SDL2 REQUIRED) find_package(SDL2_image REQUIRED) find_package(SDL2_mixer REQUIRED) find_package(SDL2_ttf REQUIRED) +find_package(TBB REQUIRED) if(ENABLE_LAUNCHER) # Widgets finds its own dependencies (QtGui and QtCore). diff --git a/client/CMT.cpp b/client/CMT.cpp index 2fd21064e..eec7874f6 100644 --- a/client/CMT.cpp +++ b/client/CMT.cpp @@ -1397,25 +1397,31 @@ void handleQuit(bool ask) { auto quitApplication = []() { - if(CSH->client) - CSH->endGameplay(); + if(!settings["session"]["headless"].Bool()) + { + if(CSH->client) + CSH->endGameplay(); + } GH.listInt.clear(); GH.objsToBlit.clear(); CMM.reset(); - // cleanup, mostly to remove false leaks from analyzer - if(CCS) + if(!settings["session"]["headless"].Bool()) { - CCS->musich->release(); - CCS->soundh->release(); + // cleanup, mostly to remove false leaks from analyzer + if(CCS) + { + CCS->musich->release(); + CCS->soundh->release(); - vstd::clear_pointer(CCS); + vstd::clear_pointer(CCS); + } + CMessage::dispose(); + + vstd::clear_pointer(graphics); } - CMessage::dispose(); - - vstd::clear_pointer(graphics); vstd::clear_pointer(VLC); diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index 2ba5d8f36..40729791d 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -175,7 +175,7 @@ endif() target_link_libraries(vcmiclient PRIVATE vcmi ${SDL2_LIBRARY} ${SDL2_IMAGE_LIBRARY} ${SDL2_MIXER_LIBRARY} ${SDL2_TTF_LIBRARY} - ${FFMPEG_LIBRARIES} ${FFMPEG_EXTRA_LINKING_OPTIONS} + ${FFMPEG_LIBRARIES} ${FFMPEG_EXTRA_LINKING_OPTIONS} ${TBB_LIBRARIES} ) target_include_directories(vcmi diff --git a/client/CServerHandler.cpp b/client/CServerHandler.cpp index 8a010a629..d9ce48f46 100644 --- a/client/CServerHandler.cpp +++ b/client/CServerHandler.cpp @@ -579,6 +579,8 @@ void CServerHandler::debugStartTest(std::string filename, bool save) else startLocalServerAndConnect(); + boost::this_thread::sleep(boost::posix_time::milliseconds(100)); + while(!settings["session"]["headless"].Bool() && !dynamic_cast(GH.topInt().get())) boost::this_thread::sleep(boost::posix_time::milliseconds(50)); while(!mi || mapInfo->fileURI != CSH->mi->fileURI) diff --git a/cmake_modules/FindTBB.cmake b/cmake_modules/FindTBB.cmake new file mode 100644 index 000000000..eb98caf18 --- /dev/null +++ b/cmake_modules/FindTBB.cmake @@ -0,0 +1,534 @@ +#.rst: +# FindTBB +# ------- +# +# Find Intel's Threading Building Blocks (TBB) include path and libraries. +# +# This module reads hints about search locations from variables: +# +# :: +# +# TBB_ROOT - Root directory of pre-built TBB package. +# Can be an environment variable instead. It is +# derived from the found TBB_INCLUDE_DIR if unset. +# TBB_ARCH_PLATFORM - Environment variable which can be used to specify +# architecture and platform specific library path +# suffix (excluding "/lib/" suffix or prefix). +# For MSVC, the appropriate link library path of the +# official pre-built download package from the TBB +# web site is chosen by this module. The path suffix +# derived from this variable takes precedence. +# +# This module considers the following CMake variables set by find_package: +# +# :: +# +# TBB_FIND_COMPONENTS - Case-insensitive names of requested libraries: +# tbb, [tbb]malloc, [tbb]malloc_proxy +# TBB_FIND_REQUIRED_ - Whether TBB library component is required. +# TBB is considered to be not found when at least +# one required library or its include path is missing. +# When no TBB_FIND_COMPONENTS are specified, only the +# threading library "tbb" is required. +# TBB_FIND_REQUIRED - Raise FATAL_ERROR when required components not found. +# TBB_FIND_QUIETLY - Suppress all other (status) messages. +# +# The TBB_DEBUG variable can be set to TRUE before find_package(TBB) to +# enable verbose output which helps to debug the processing of this module: +# +# :: +# +# set(TBB_DEBUG TRUE) +# find_package(TBB) +# +# This module defines the following variables: +# +# :: +# +# TBB_FOUND - Whether TBB libraries were found. +# TBB_INCLUDE_DIR - TBB library include path where tbb/tbb_stddef.h is located. +# Used as HINTS for find_path of TBB__INCLUDE_DIR. +# TBB_INCLUDE_DIRS - Include paths of found TBB libraries. +# TBB_LIBRARIES - File paths of found TBB libraries. +# TBB_VERSION - Version for use in VERSION_LESS et al. comparisons. +# TBB_VERSION_MAJOR - Major library version number. +# TBB_VERSION_MINOR - Minor library version number. +# TBB_VERSION_STRING - Version string for output messages. +# TBB_INTERFACE_VERSION - API version number. +# TBB_COMPATIBLE_INTERFACE_VERSION - The oldest major version still supported. +# +# Additionally, for each requested component, this module defines the following variables: +# +# :: +# +# TBB_TBB_FOUND - Whether TBB threading library was found. +# TBB_TBB_INCLUDE_DIR - Include path of TBB threading library. +# TBB_TBB_INCLUDE_DIRS - Include paths for use of TBB library. +# TBB_TBB_LIBRARIES - TBB threading library and transitive link dependencies. +# TBB_TBB_LIBRARY_RELEASE - File path of optimized TBB link library. +# TBB_TBB_LIBRARY_DEBUG - File path of TBB link library with debug symbols. +# TBB_TBB_LIBRARY - File paths of both "optimized" and "debug" TBB threading link libraries. +# When only one of these is found, this variable is set to either +# TBB_TBB_LIBRARY_RELEASE or TBB_TBB_LIBRARY_DEBUG. +# +# TBB_MALLOC_FOUND - Whether TBB malloc library was found. +# TBB_MALLOC_INCLUDE_DIR - Include path of TBB malloc library. +# TBB_MALLOC_INCLUDE_DIRS - Include paths for use of TBB malloc library. +# TBB_MALLOC_LIBRARIES - TBB malloc library and transitive link dependencies. +# TBB_MALLOC_LIBRARY_RELEASE - File path of optimized TBB malloc link library. +# TBB_MALLOC_LIBRARY_DEBUG - File path of TBB malloc link library with debug symbols. +# TBB_MALLOC_LIBRARY - File paths of both "optimized" and "debug" TBB malloc link libraries. +# When only one of these is found, this variable is set to either +# TBB_MALLOC_LIBRARY_RELEASE or TBB_MALLOC_LIBRARY_DEBUG. +# +# TBB_MALLOC_PROXY_FOUND - Whether TBB malloc proxy library was found. +# TBB_MALLOC_PROXY_INCLUDE_DIR - Include path of TBB malloc proxy library. +# TBB_MALLOC_PROXY_INCLUDE_DIRS - Include paths for use of TBB malloc proxy library. +# TBB_MALLOC_PROXY_LIBRARIES - TBB malloc proxy library and transitive link dependencies. +# TBB_MALLOC_PROXY_LIBRARY_RELEASE - File path of optimized TBB malloc proxy link library. +# TBB_MALLOC_PROXY_LIBRARY_DEBUG - File path of TBB malloc proxy link library with debug symbols. +# TBB_MALLOC_PROXY_LIBRARY - File paths of both "optimized" and "debug" TBB malloc proxy link libraries. +# When only one of these is found, this variable is set to either +# TBB_MALLOC_PROXY_LIBRARY_RELEASE or TBB_MALLOC_PROXY_LIBRARY_DEBUG. +# +# of these, the following variables are added as advanced cache entries: +# +# :: +# +# TBB_INCLUDE_DIR +# TBB__INCLUDE_DIR +# TBB__LIBRARY_RELEASE +# TBB__LIBRARY_DEBUG +# +# This module further defines the following import targets with the IMPORTED and INTERFACE +# properties set appropriately such that only a target_link_libraries command is required +# to declare the dependency of another target on the respective TBB library component. +# The use of these import targets instead of above defined variables is recommended. +# +# :: +# +# TBB::tbb - TBB threading library. +# TBB::malloc - TBB malloc library. +# TBB::malloc_proxy - TBB malloc proxy library. +# +# Example usage: +# +# :: +# +# find_package(TBB REQUIRED COMPONENTS tbb OPTIONAL_COMPONENTS malloc) +# +# add_executable(foo foo.cc) +# target_link_libraries(foo TBB::tbb) +# if (TARGET TBB::malloc) +# # or if (TBB_MALLOC_FOUND) +# target_link_libraries(foo TBB::malloc) +# endif () +# +# This module was written by Andreas Schuh for CMake BASIS with inspiration +# from the FindTBB module which was originally part of the Object-oriented +# Graphics Rendering Engine (OGRE) project with modifications by Robert Maynard. + +#============================================================================= +# Copyright 2016 Andreas Schuh +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# (To distribute this file outside of CMake, substitute the full +# License text for the above reference.) + +if (NOT TBB_FIND_QUIETLY) + set(_TBB_FIND_STATUS "Looking for TBB") + if (TBB_FIND_COMPONENTS) + set(_TBB_FIND_STATUS "${_TBB_FIND_STATUS} [${TBB_FIND_COMPONENTS}]") + endif () + if (NOT TBB_FIND_REQUIRED) + set(_TBB_FIND_STATUS "${_TBB_FIND_STATUS} (optional)") + endif () + message(STATUS "${_TBB_FIND_STATUS}...") +endif () + +# ------------------------------------------------------------------------------ +# Default required/optional components +if (NOT TBB_FIND_COMPONENTS) + set(TBB_FIND_COMPONENTS tbb malloc malloc_proxy) + set(TBB_FIND_REQUIRED_tbb TRUE) + set(TBB_FIND_REQUIRED_malloc FALSE) + set(TBB_FIND_REQUIRED_malloc_proxy FALSE) +endif () + +# ------------------------------------------------------------------------------ +# Normalize component names +set(_TBB_FIND_COMPONENTS) +foreach (__TBB_COMPONENT IN LISTS TBB_FIND_COMPONENTS) + string(TOUPPER "${__TBB_COMPONENT}" _TBB_COMPONENT) + string(REGEX REPLACE "^TBB_?([A-Z_]+)$" "\\1" _TBB_COMPONENT "${_TBB_COMPONENT}") + if (_TBB_COMPONENT MATCHES "^(TBB|MALLOC|MALLOC_PROXY)$") + set(_TBB_${_TBB_COMPONENT}_NAME ${__TBB_COMPONENT}) + list(APPEND _TBB_FIND_COMPONENTS ${_TBB_COMPONENT}) + if (TBB_FIND_REQUIRED_${__TBB_COMPONENT}) + set(_TBB_FIND_REQUIRED_${_TBB_COMPONENT} TRUE) + else () + set(_TBB_FIND_REQUIRED_${_TBB_COMPONENT} FALSE) + endif () + else () + message(FATAL_ERROR "Unknown TBB library component: ${__TBB_COMPONENT}\n" + "Valid component names are: tbb, [tbb]malloc, [tbb]malloc_proxy") + endif () +endforeach () +unset(__TBB_COMPONENT) + +if (TBB_DEBUG) + message("** FindTBB: Components = [${_TBB_FIND_COMPONENTS}]") +endif () + +# ------------------------------------------------------------------------------ +# Names of headers and libraries for each component +set(_TBB_TBB_LIB_NAMES_RELEASE tbb) +set(_TBB_TBB_LIB_NAMES_DEBUG tbb_debug) +set(_TBB_TBB_INC_NAMES tbb/tbb.h) + +set(_TBB_MALLOC_LIB_NAMES_RELEASE tbbmalloc) +set(_TBB_MALLOC_LIB_NAMES_DEBUG tbbmalloc_debug) +set(_TBB_MALLOC_INC_NAMES tbb/tbb.h) + +set(_TBB_MALLOC_PROXY_LIB_NAMES_RELEASE tbbmalloc_proxy) +set(_TBB_MALLOC_PROXY_LIB_NAMES_DEBUG tbbmalloc_proxy_debug) +set(_TBB_MALLOC_PROXY_INC_NAMES tbb/tbbmalloc_proxy.h) + +# ------------------------------------------------------------------------------ +# Transitive link dependencies +set(_TBB_TBB_LIB_LINK_DEPENDS) +set(_TBB_MALLOC_LIB_LINK_DEPENDS) +set(_TBB_MALLOC_PROXY_LIB_LINK_DEPENDS) + +if (UNIX AND NOT APPLE) + # On Linux, the TBB threading library requires librt.so + list(APPEND _TBB_TBB_LIB_LINK_DEPENDS rt) +endif () + +# ------------------------------------------------------------------------------ +# Construct a set of search paths +set(_TBB_ARCH_PLATFORM $ENV{TBB_ARCH_PLATFORM}) + +if (NOT TBB_ROOT) + file(TO_CMAKE_PATH "$ENV{TBB_ROOT}" TBB_ROOT) +endif () + +set(_TBB_INC_PATH_SUFFIXES include) + +set(_TBB_LIB_PATH_SUFFIXES) +if (_TBB_ARCH_PLATFORM) + list(APPEND _TBB_LIB_PATH_SUFFIXES lib/${_TBB_ARCH_PLATFORM}) + list(APPEND _TBB_LIB_PATH_SUFFIXES ${_TBB_ARCH_PLATFORM}/lib) +endif () +list(APPEND _TBB_LIB_PATH_SUFFIXES lib) + +if (WIN32 AND MSVC AND CMAKE_GENERATOR MATCHES "Visual Studio ([0-9]+)") + set(_TBB_MSVS_VERSION ${CMAKE_MATCH_1}) + if (CMAKE_CL_64) + list(APPEND _TBB_LIB_PATH_SUFFIXES lib/intel64/vc${_TBB_MSVS_VERSION}) + list(APPEND _TBB_LIB_PATH_SUFFIXES intel64/vc${_TBB_MSVS_VERSION}/lib) + list(APPEND _TBB_LIB_PATH_SUFFIXES lib/ia64/vc${_TBB_MSVS_VERSION}) + list(APPEND _TBB_LIB_PATH_SUFFIXES ia64/vc${_TBB_MSVS_VERSION}/lib) + else () + list(APPEND _TBB_LIB_PATH_SUFFIXES lib/ia32/vc${_TBB_MSVS_VERSION}) + list(APPEND _TBB_LIB_PATH_SUFFIXES ia32/vc${_TBB_MSVS_VERSION}/lib) + endif () + unset(_TBB_MSVS_VERSION) +endif () + +if (TBB_DEBUG) + message("** FindTBB: Initial search paths:") + message("** FindTBB: - Root directory hints = [${TBB_ROOT}]") + message("** FindTBB: - Include path suffixes = [${_TBB_INC_PATH_SUFFIXES}]") + message("** FindTBB: - Library path suffixes = [${_TBB_LIB_PATH_SUFFIXES}]") +endif () + +# ------------------------------------------------------------------------------ +# Find common include directory +# +# Looking for tbb/tbb_stddef.h because we use this path later to read this file +# in order to extract the version information. The tbb.h header should be in the +# same directory and is searched for separately as part of the "tbb" and "malloc" +# component search. The TBB_INCLUDE_DIR is then used as HINTS. +find_path(TBB_INCLUDE_DIR + NAMES tbb/tbb_stddef.h + HINTS ${TBB_ROOT} + PATH_SUFFIXES ${_TBB_INC_PATH_SUFFIXES} +) + +mark_as_advanced(TBB_INCLUDE_DIR) + +# ------------------------------------------------------------------------------ +# Derive TBB_ROOT from TBB_INCLUDE_DIR if unset +if (TBB_INCLUDE_DIR AND NOT TBB_ROOT) + if (_TBB_INC_PATH_SUFFIXES MATCHES "[^/;]/[^/;]") + string(LENGTH "${TBB_INCLUDE_DIR}" _TBB_INCLUDE_DIR_LENGTH) + foreach (_TBB_INC_PATH_SUFFIX IN LISTS _TBB_INC_PATH_SUFFIXES) + string(LENGTH "${_TBB_INC_PATH_SUFFIX}" _TBB_INC_PATH_SUFFIX_LENGTH) + if (_TBB_INC_PATH_SUFFIX_LENGTH GREATER 0) + math(EXPR _TBB_SUBSTRING_START "${_TBB_INCLUDE_DIR_LENGTH} - ${_TBB_INC_PATH_SUFFIX_LENGTH}") + string(SUBSTRING "${TBB_INCLUDE_DIR}" _TBB_SUBSTRING_START -1 _TBB_SUBSTRING) + if (_TBB_SUBSTRING STREQUAL _TBB_INC_PATH_SUFFIX) + if (_TBB_SUBSTRING_START GREATER 0) + string(SUBSTRING "${TBB_INCLUDE_DIR}" 0 _TBB_SUBSTRING_START TBB_ROOT) + string(REGEX REPLACE "/+$" "" TBB_ROOT "${TBB_ROOT}") + else () + set(TBB_ROOT "/") + endif () + break() + endif () + endif () + endforeach () + unset(_TBB_SUBSTRING) + unset(_TBB_SUBSTRING_START) + unset(_TBB_INCLUDE_DIR_LENGTH) + unset(_TBB_INC_PATH_SUFFIX_LENGTH) + else () + get_filename_component(TBB_ROOT "${TBB_INCLUDE_DIR}" DIRECTORY) + endif () +endif () + +if (TBB_DEBUG) + message("** FindTBB: After initial search of TBB include path") + message("** FindTBB: - TBB_INCLUDE_DIR = ${TBB_INCLUDE_DIR}") + message("** FindTBB: - TBB_ROOT = [${TBB_ROOT}]") +endif () + +# ------------------------------------------------------------------------------ +# Find library components +set(TBB_INCLUDE_DIRS) +set(TBB_LIBRARIES) + +foreach (_TBB_COMPONENT IN LISTS _TBB_FIND_COMPONENTS) + if (TBB_DEBUG) + message("** FindTBB: Looking for component ${_TBB_COMPONENT}...") + endif () + + # Find include path and library files of this component + find_path(TBB_${_TBB_COMPONENT}_INCLUDE_DIR + NAMES ${_TBB_${_TBB_COMPONENT}_INC_NAMES} + HINTS ${TBB_INCLUDE_DIR} ${TBB_ROOT} + PATH_SUFFIXES ${_TBB_INC_PATH_SUFFIXES} + ) + + find_library(TBB_${_TBB_COMPONENT}_LIBRARY_RELEASE + NAMES ${_TBB_${_TBB_COMPONENT}_LIB_NAMES_RELEASE} + HINTS ${TBB_ROOT} + PATH_SUFFIXES ${_TBB_LIB_PATH_SUFFIXES} + ) + + find_library(TBB_${_TBB_COMPONENT}_LIBRARY_DEBUG + NAMES ${_TBB_${_TBB_COMPONENT}_LIB_NAMES_DEBUG} + HINTS ${TBB_ROOT} + PATH_SUFFIXES ${_TBB_LIB_PATH_SUFFIXES} + ) + + if (TBB_DEBUG) + message("** FindTBB: - TBB_${_TBB_COMPONENT}_INCLUDE_DIR = ${TBB_${_TBB_COMPONENT}_INCLUDE_DIR}") + message("** FindTBB: - TBB_${_TBB_COMPONENT}_LIBRARY_RELEASE = ${TBB_${_TBB_COMPONENT}_LIBRARY_RELEASE}") + message("** FindTBB: - TBB_${_TBB_COMPONENT}_LIBRARY_DEBUG = ${TBB_${_TBB_COMPONENT}_LIBRARY_DEBUG}") + endif () + + # Mark cache entries as advanced + mark_as_advanced(TBB_${_TBB_COMPONENT}_INCLUDE_DIR) + mark_as_advanced(TBB_${_TBB_COMPONENT}_LIBRARY_RELEASE) + mark_as_advanced(TBB_${_TBB_COMPONENT}_LIBRARY_DEBUG) + + # Set TBB__LIBRARY + if (TBB_${_TBB_COMPONENT}_LIBRARY_RELEASE AND TBB_${_TBB_COMPONENT}_LIBRARY_DEBUG) + set(TBB_${_TBB_COMPONENT}_LIBRARY + optimized ${TBB_${_TBB_COMPONENT}_LIBRARY_RELEASE} + debug ${TBB_${_TBB_COMPONENT}_LIBRARY_DEBUG} + ) + elseif (TBB_${_TBB_COMPONENT}_LIBRARY_RELEASE) + set(TBB_${_TBB_COMPONENT}_LIBRARY ${TBB_${_TBB_COMPONENT}_LIBRARY_RELEASE}) + elseif (TBB_${_TBB_COMPONENT}_LIBRARY_DEBUG) + set(TBB_${_TBB_COMPONENT}_LIBRARY ${TBB_${_TBB_COMPONENT}_LIBRARY_DEBUG}) + else () + set(TBB_${_TBB_COMPONENT}_LIBRARY TBB_${_TBB_COMPONENT}_LIBRARY-NOTFOUND) + endif () + + # Set TBB__FOUND + if (TBB_${_TBB_COMPONENT}_INCLUDE_DIR AND TBB_${_TBB_COMPONENT}_LIBRARY) + set(TBB_${_TBB_COMPONENT}_FOUND TRUE) + else () + set(TBB_${_TBB_COMPONENT}_FOUND FALSE) + endif () + set(TBB_${_TBB_${_TBB_COMPONENT}_NAME}_FOUND ${TBB_${_TBB_COMPONENT}_FOUND}) + + if (TBB_${_TBB_COMPONENT}_FOUND) + + # Add transitive dependencies + set(TBB_${_TBB_COMPONENT}_INCLUDE_DIRS ${TBB_${_TBB_COMPONENT}_INCLUDE_DIR}) + set(TBB_${_TBB_COMPONENT}_LIBRARIES ${TBB_${_TBB_COMPONENT}_LIBRARY}) + if (_TBB_${_TBB_COMPONENT}_LIB_LINK_DEPENDS) + list(APPEND TBB_${_TBB_COMPONENT}_LIBRARIES "${_TBB_${_TBB_COMPONENT}_LIB_LINK_DEPENDS}") + endif () + + if (TBB_DEBUG) + message("** FindTBB: - TBB_${_TBB_COMPONENT}_INCLUDE_DIRS = [${TBB_${_TBB_COMPONENT}_INCLUDE_DIRS}]") + message("** FindTBB: - TBB_${_TBB_COMPONENT}_LIBRARIES = [${TBB_${_TBB_COMPONENT}_LIBRARIES}]") + endif () + + # Add to TBB_INCLUDE_DIRS and TBB_LIBRARIES + list(APPEND TBB_INCLUDE_DIRS ${TBB_${_TBB_COMPONENT}_INCLUDE_DIRS}) + list(APPEND TBB_LIBRARIES ${TBB_${_TBB_COMPONENT}_LIBRARIES}) + + # Add TBB:: import target + string(TOLOWER ${_TBB_COMPONENT} _TBB_TARGET_NAME) + set(_TBB_TARGET_NAME "TBB::${_TBB_TARGET_NAME}") + add_library(${_TBB_TARGET_NAME} SHARED IMPORTED) + + set_target_properties(${_TBB_TARGET_NAME} PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${TBB_${_TBB_COMPONENT}_INCLUDE_DIRS}" + IMPORTED_LINK_INTERFACE_LANGUAGES CXX + IMPORTED_NO_SONAME TRUE + ) + if (_TBB_${_TBB_COMPONENT}_LIB_LINK_DEPENDS) + set_target_properties(${_TBB_TARGET_NAME} PROPERTIES + INTERFACE_LINK_LIBRARIES "${_TBB_${_TBB_COMPONENT}_LIB_LINK_DEPENDS}" + ) + endif () + + foreach (_TBB_CONFIGURATION IN ITEMS DEBUG RELEASE) + if (TBB_${_TBB_COMPONENT}_LIBRARY_${_TBB_CONFIGURATION}) + set_property(TARGET ${_TBB_TARGET_NAME} APPEND PROPERTY IMPORTED_CONFIGURATIONS ${_TBB_CONFIGURATION}) + if (WIN32) + set_target_properties(${_TBB_TARGET_NAME} PROPERTIES + IMPORTED_IMPLIB_${_TBB_CONFIGURATION} "${TBB_${_TBB_COMPONENT}_LIBRARY_${_TBB_CONFIGURATION}}" + ) + string(REPLACE "/lib/" "/bin/" _TBB_LIB_PATH_DLL "${TBB_${_TBB_COMPONENT}_LIBRARY_${_TBB_CONFIGURATION}}") + string(REGEX REPLACE "\\.lib$" ".dll" _TBB_LIB_PATH_DLL "${_TBB_LIB_PATH_DLL}") + if (EXISTS "${_TBB_LIB_PATH_DLL}") + set_target_properties(${_TBB_TARGET_NAME} PROPERTIES + IMPORTED_LOCATION_${_TBB_CONFIGURATION} "${_TBB_LIB_PATH_DLL}" + ) + if (TBB_DEBUG) + message("** FindTBB: - IMPORTED_LOCATION_${_TBB_CONFIGURATION} = ${_TBB_LIB_PATH_DLL}") + endif () + elseif (TBB_DEBUG) + message("** FindTBB: Could not determine ${_TBB_CONFIGURATION} DLL path from import library, tried: " + "\n\t${_TBB_LIB_PATH_DLL}") + endif () + else () + set_target_properties(${_TBB_TARGET_NAME} PROPERTIES + IMPORTED_LOCATION_${_TBB_CONFIGURATION} "${TBB_${_TBB_COMPONENT}_LIBRARY_${_TBB_CONFIGURATION}}" + ) + endif () + endif () + endforeach () + + if (TBB_DEBUG) + message("** FindTBB: Looking for component ${_TBB_COMPONENT}... - found") + endif () + + else () + + if (TBB_DEBUG) + message("** FindTBB: Looking for component ${_TBB_COMPONENT}... - not found") + endif () + unset(TBB_${_TBB_COMPONENT}_INCLUDE_DIRS) + unset(TBB_${_TBB_COMPONENT}_LIBRARIES) + + endif () +endforeach () + +if (TBB_INCLUDE_DIRS) + list(REMOVE_DUPLICATES TBB_INCLUDE_DIRS) +endif () + +if (TBB_DEBUG) + message("** FindTBB: Include paths and libraries of all found components:") + message("** FindTBB: - TBB_INCLUDE_DIRS = [${TBB_INCLUDE_DIRS}]") + message("** FindTBB: - TBB_LIBRARIES = [${TBB_LIBRARIES}]") +endif () + +# ------------------------------------------------------------------------------ +# Extract library version from start of tbb_stddef.h +if (TBB_INCLUDE_DIR) + if (NOT DEFINED TBB_VERSION_MAJOR OR + NOT DEFINED TBB_VERSION_MINOR OR + NOT DEFINED TBB_INTERFACE_VERSION OR + NOT DEFINED TBB_COMPATIBLE_INTERFACE_VERSION) + file(READ "${TBB_INCLUDE_DIR}/tbb/tbb_stddef.h" _TBB_VERSION_CONTENTS LIMIT 2048) + string(REGEX REPLACE + ".*#define TBB_VERSION_MAJOR ([0-9]+).*" "\\1" + TBB_VERSION_MAJOR "${_TBB_VERSION_CONTENTS}" + ) + string(REGEX REPLACE + ".*#define TBB_VERSION_MINOR ([0-9]+).*" "\\1" + TBB_VERSION_MINOR "${_TBB_VERSION_CONTENTS}" + ) + string(REGEX REPLACE + ".*#define TBB_INTERFACE_VERSION ([0-9]+).*" "\\1" + TBB_INTERFACE_VERSION "${_TBB_VERSION_CONTENTS}" + ) + string(REGEX REPLACE + ".*#define TBB_COMPATIBLE_INTERFACE_VERSION ([0-9]+).*" "\\1" + TBB_COMPATIBLE_INTERFACE_VERSION "${_TBB_VERSION_CONTENTS}" + ) + unset(_TBB_VERSION_CONTENTS) + endif () + set(TBB_VERSION "${TBB_VERSION_MAJOR}.${TBB_VERSION_MINOR}") + set(TBB_VERSION_STRING "${TBB_VERSION}") +else () + unset(TBB_VERSION) + unset(TBB_VERSION_MAJOR) + unset(TBB_VERSION_MINOR) + unset(TBB_VERSION_STRING) + unset(TBB_INTERFACE_VERSION) + unset(TBB_COMPATIBLE_INTERFACE_VERSION) +endif () + +if (TBB_DEBUG) + message("** FindTBB: Version information from ${TBB_INCLUDE_DIR}/tbb/tbb_stddef.h") + message("** FindTBB: - TBB_VERSION_STRING = ${TBB_VERSION_STRING}") + message("** FindTBB: - TBB_VERSION_MAJOR = ${TBB_VERSION_MAJOR}") + message("** FindTBB: - TBB_VERSION_MINOR = ${TBB_VERSION_MINOR}") + message("** FindTBB: - TBB_INTERFACE_VERSION = ${TBB_INTERFACE_VERSION}") + message("** FindTBB: - TBB_COMPATIBLE_INTERFACE_VERSION = ${TBB_COMPATIBLE_INTERFACE_VERSION}") +endif () + +# ------------------------------------------------------------------------------ +# Handle QUIET, REQUIRED, and [EXACT] VERSION arguments and set TBB_FOUND +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(TBB + REQUIRED_VARS TBB_INCLUDE_DIR + VERSION_VAR TBB_VERSION + HANDLE_COMPONENTS +) + +if (NOT TBB_FIND_QUIETLY) + if (TBB_FOUND) + message(STATUS "${_TBB_FIND_STATUS}... - found v${TBB_VERSION_STRING}") + else () + message(STATUS "${_TBB_FIND_STATUS}... - not found") + endif () +endif () + +# ------------------------------------------------------------------------------ +# Unset local auxiliary variables +foreach (_TBB_COMPONENT IN ITEMS TBB MALLOC MALLOC_PROXY) + unset(_TBB_FIND_REQUIRED_${_TBB_COMPONENT}) + unset(_TBB_${_TBB_COMPONENT}_LIB_NAMES_RELEASE) + unset(_TBB_${_TBB_COMPONENT}_LIB_NAMES_DEBUG) + unset(_TBB_${_TBB_COMPONENT}_LIB_LINK_DEPENDS) + unset(_TBB_${_TBB_COMPONENT}_INC_NAMES) + unset(_TBB_${_TBB_COMPONENT}_NAME) +endforeach () + +unset(_TBB_COMPONENT) +unset(_TBB_TARGET_NAME) +unset(_TBB_FIND_COMPONENTS) +unset(_TBB_FIND_STATUS) +unset(_TBB_INC_PATH_SUFFIXES) +unset(_TBB_LIB_PATH_SUFFIXES) +unset(_TBB_LIB_PATH_DLL) +unset(_TBB_LIB_NAME) +unset(_TBB_ARCH_PLATFORM) \ No newline at end of file diff --git a/config/ai/object-priorities.txt b/config/ai/object-priorities.txt new file mode 100644 index 000000000..be5b52efc --- /dev/null +++ b/config/ai/object-priorities.txt @@ -0,0 +1,219 @@ +Engine: visit tile +description: visit tile priority +InputVariable: mainTurnDistance + description: distance to tile in turns + enabled: true + range: 0.000 10.000 + lock-range: true + term: LOWEST Ramp 0.250 0.000 + term: LOW Discrete 0.000 1.000 0.500 0.800 1.000 0.000 + term: MEDIUM Discrete 0.000 0.000 0.500 0.200 1.000 1.000 3.000 0.000 + term: LONG Discrete 1.000 0.000 1.500 0.200 3.000 0.800 10.000 1.000 +InputVariable: scoutTurnDistance + description: distance to tile in turns + enabled: true + range: 0.000 10.000 + lock-range: true + term: LOWEST Ramp 0.250 0.000 + term: LOW Discrete 0.000 1.000 0.500 0.800 1.000 0.000 + term: MEDIUM Discrete 0.000 0.000 0.500 0.200 1.000 1.000 2.500 0.300 4.000 0.000 + term: LONG Discrete 1.000 0.000 1.500 0.200 3.000 0.800 10.000 1.000 +InputVariable: goldReward + description: estimated amount of gold received + enabled: true + range: 0.000 5000.000 + lock-range: true + term: LOW Triangle 10.000 500.000 2000.000 + term: MEDIUM Triangle 500.000 2000.000 5000.000 + term: HIGH Ramp 2000.000 5000.000 + term: NONE Ramp 100.000 0.000 + term: LOWEST Triangle 0.000 100.000 500.000 +InputVariable: armyReward + enabled: true + range: 0.000 10000.000 + lock-range: false + term: NONE Ramp 100.000 0.000 + term: LOW Triangle 0.000 700.000 3000.000 + term: HIGH Ramp 3000.000 10000.000 + term: MEDIUM Triangle 700.000 3000.000 8000.000 +InputVariable: armyLoss + enabled: true + range: 0.000 1.000 + lock-range: false + term: LOW Ramp 0.200 0.000 + term: MEDIUM Triangle 0.000 0.200 0.500 + term: HIGH Ramp 0.200 0.500 +InputVariable: heroRole + enabled: true + range: -0.100 1.100 + lock-range: false + term: SCOUT Rectangle -0.500 0.500 + term: MAIN Rectangle 0.500 1.500 +InputVariable: danger + enabled: true + range: 0.000 10000.000 + lock-range: false + term: NONE Ramp 20.000 0.000 + term: LOW Triangle 50.000 1000.000 2000.000 + term: HIGH Ramp 2000.000 5000.000 + term: MEDIUM Triangle 1000.000 2000.000 5000.000 +InputVariable: skillReward + enabled: true + range: 0.000 10.000 + lock-range: false + term: NONE Ramp 1.000 0.000 + term: LOW Triangle 0.000 1.000 3.000 + term: MEDIUM Triangle 1.000 3.000 5.000 + term: HIGH Discrete 3.000 0.000 5.000 0.800 10.000 1.000 +InputVariable: rewardType + enabled: true + range: 0.000 3.000 + lock-range: false + term: SINGLE Rectangle 0.500 1.500 + term: MIXED Rectangle 1.500 2.500 + term: NONE Rectangle 0.000 0.500 +InputVariable: closestHeroRatio + enabled: true + range: 0.000 1.000 + lock-range: false + term: LOW Discrete 0.000 1.000 0.500 0.800 0.700 0.200 1.000 0.000 + term: HIGH Discrete 0.500 0.000 0.700 0.600 1.000 1.000 + term: LOWEST Discrete 0.000 1.000 0.400 0.200 0.900 0.000 +InputVariable: strategicalValue + description: Some abstract long term benefit non gold or army or skill + enabled: true + range: 0.000 1.000 + lock-range: false + term: NONE Ramp 0.200 0.000 + term: LOWEST Triangle 0.000 0.010 0.250 + term: LOW Triangle 0.000 0.400 0.700 + term: MEDIUM Triangle 0.400 0.700 1.000 + term: HIGH Ramp 0.700 1.000 +InputVariable: goldPreasure + description: Ratio between weekly army cost and gold income + enabled: true + range: 0.000 1.000 + lock-range: false + term: LOW Ramp 0.300 0.000 + term: HIGH Discrete 0.100 0.000 0.250 0.100 0.300 0.200 0.400 0.700 1.000 1.000 +InputVariable: goldCost + description: Action cost in gold + enabled: true + range: 0.000 1.000 + lock-range: false + term: NONE Ramp 0.050 0.000 + term: MEDIUM Triangle 0.100 0.200 0.500 + term: LOW Triangle 0.000 0.100 0.200 + term: HIGH Discrete 0.200 0.000 0.300 0.600 0.500 0.900 1.000 1.000 +InputVariable: turn + description: Turn of goal completion. Discrete variable to sharpen boundaries between turns. Turn distances does not care about turn boundaries and just count total movement points + enabled: true + range: 0.000 5.000 + lock-range: false + term: NOW Ramp 1.000 0.999 + term: NEXT Trapezoid 1.000 1.000 1.990 2.000 + term: FUTURE Discrete 1.990 0.000 2.000 0.500 2.999 0.500 3.000 1.000 +InputVariable: fear + description: Fear strength of enemy heroes + enabled: true + range: 0.000 2.000 + lock-range: false + term: LOW Triangle 0.000 0.500 1.000 + term: MEDIUM Triangle 0.500 1.000 1.500 + term: HIGH Ramp 1.000 1.800 +OutputVariable: Value + enabled: true + range: -0.500 1.500 + lock-range: false + aggregation: AlgebraicSum + defuzzifier: Centroid 100 + default: 0.500 + lock-previous: false + term: LOWEST Discrete -0.500 0.000 -0.500 1.000 -0.200 1.000 -0.200 0.000 0.200 0.000 0.200 1.000 0.500 1.000 0.500 0.000 0.500 + term: BITLOW Rectangle -0.010 0.010 0.500 + term: LOW Discrete -0.150 0.000 -0.150 1.000 -0.050 1.000 -0.050 0.000 0.050 0.000 0.050 1.000 0.150 1.000 0.150 0.000 0.500 + term: MEDIUM Triangle 0.450 0.500 0.550 0.050 + term: HIGH Discrete 0.850 0.000 0.850 1.000 0.950 1.000 0.950 0.000 1.050 0.000 1.050 1.000 1.150 1.000 1.150 0.000 0.500 + term: HIGHEST Discrete 0.500 0.000 0.500 1.000 0.800 1.000 0.800 0.000 1.200 0.000 1.200 1.000 1.500 1.000 1.500 0.000 0.500 + term: BITHIGH Rectangle 0.990 1.010 0.500 +RuleBlock: gold reward + enabled: true + conjunction: AlgebraicProduct + disjunction: AlgebraicSum + implication: AlgebraicProduct + activation: General + rule: if turn is NOW and mainTurnDistance is very LONG and heroRole is SCOUT then Value is LOW with 0.5 + rule: if turn is NOW and mainTurnDistance is LONG and heroRole is SCOUT then Value is LOW with 0.3 + rule: if turn is NOW and scoutTurnDistance is LONG and heroRole is SCOUT then Value is LOW with 0.3 + rule: if turn is NOW and mainTurnDistance is LONG and heroRole is MAIN then Value is LOW with 0.3 + rule: if turn is NEXT and mainTurnDistance is very LONG and heroRole is SCOUT then Value is LOW with 0.8 + rule: if turn is NEXT and scoutTurnDistance is LONG and heroRole is SCOUT then Value is BITLOW + rule: if turn is NEXT and mainTurnDistance is LONG and heroRole is MAIN then Value is LOW with 0.3 + rule: if turn is NEXT and mainTurnDistance is LONG and heroRole is SCOUT then Value is BITLOW with 0.3 + rule: if turn is FUTURE and scoutTurnDistance is very LONG and heroRole is SCOUT then Value is LOWEST with 0.3 + rule: if turn is FUTURE and mainTurnDistance is very LONG and heroRole is SCOUT then Value is LOWEST with 0.5 + rule: if turn is FUTURE and mainTurnDistance is very LONG and heroRole is MAIN and strategicalValue is NONE then Value is LOWEST with 0.5 + rule: if turn is FUTURE and mainTurnDistance is very LONG and heroRole is MAIN and strategicalValue is LOW then Value is LOWEST with 0.3 + rule: if turn is FUTURE and mainTurnDistance is very LONG and heroRole is MAIN and strategicalValue is MEDIUM then Value is LOW with 0.5 + rule: if turn is FUTURE and mainTurnDistance is very LONG and heroRole is MAIN and strategicalValue is HIGH then Value is BITLOW + rule: if turn is FUTURE and scoutTurnDistance is LONG and heroRole is SCOUT then Value is LOW + rule: if turn is FUTURE and mainTurnDistance is LONG and heroRole is MAIN then Value is LOW + rule: if turn is FUTURE and mainTurnDistance is LONG and heroRole is SCOUT then Value is LOW + rule: if scoutTurnDistance is MEDIUM and heroRole is SCOUT then Value is BITLOW + rule: if mainTurnDistance is MEDIUM then Value is BITLOW + rule: if scoutTurnDistance is LOW and heroRole is SCOUT then Value is MEDIUM + rule: if mainTurnDistance is LOW then Value is MEDIUM + rule: if goldReward is HIGH and goldPreasure is HIGH and heroRole is SCOUT and danger is not NONE and armyLoss is LOW then Value is BITHIGH + rule: if goldReward is HIGH and goldPreasure is HIGH and heroRole is SCOUT and danger is NONE then Value is HIGH with 0.7 + rule: if goldReward is HIGH and goldPreasure is HIGH and heroRole is MAIN and danger is not NONE and armyLoss is LOW and fear is not HIGH then Value is HIGHEST + rule: if goldReward is HIGH and goldPreasure is HIGH and heroRole is MAIN and danger is NONE then Value is BITHIGH + rule: if goldReward is MEDIUM and goldPreasure is HIGH and heroRole is SCOUT and danger is NONE then Value is HIGH + rule: if goldReward is MEDIUM and goldPreasure is HIGH and armyLoss is LOW and heroRole is SCOUT and danger is not NONE then Value is MEDIUM + rule: if goldReward is MEDIUM and heroRole is MAIN and danger is NONE and rewardType is SINGLE then Value is BITLOW + rule: if goldReward is MEDIUM and goldPreasure is HIGH and armyLoss is LOW and heroRole is MAIN and danger is not NONE then Value is BITHIGH + rule: if goldReward is LOW and goldPreasure is HIGH and heroRole is SCOUT and armyLoss is LOW then Value is BITHIGH + rule: if goldReward is LOW and heroRole is MAIN and danger is not NONE and rewardType is SINGLE and armyLoss is LOW then Value is BITLOW + rule: if goldReward is LOW and heroRole is MAIN and danger is NONE and rewardType is SINGLE then Value is LOW + rule: if goldReward is LOWEST and heroRole is MAIN and danger is NONE and rewardType is SINGLE then Value is LOWEST + rule: if armyReward is HIGH and heroRole is SCOUT and danger is not NONE and armyLoss is LOW then Value is HIGH with 0.5 + rule: if armyReward is HIGH and heroRole is SCOUT and danger is NONE then Value is HIGHEST + rule: if armyReward is HIGH and heroRole is MAIN and rewardType is MIXED and armyLoss is LOW and fear is not HIGH then Value is HIGHEST + rule: if armyReward is HIGH and heroRole is MAIN and rewardType is SINGLE and mainTurnDistance is LOWEST then Value is HIGHEST + rule: if armyReward is HIGH and heroRole is MAIN and rewardType is SINGLE and danger is NONE and fear is not HIGH then Value is HIGH + rule: if armyReward is HIGH and heroRole is MAIN and rewardType is SINGLE and danger is not NONE and armyLoss is LOW and fear is not HIGH then Value is HIGHEST + rule: if armyReward is MEDIUM and heroRole is MAIN and danger is not NONE and armyLoss is LOW and fear is not HIGH then Value is HIGHEST with 0.5 + rule: if armyReward is MEDIUM and heroRole is MAIN and danger is NONE then Value is BITHIGH + rule: if armyReward is MEDIUM and heroRole is MAIN and danger is NONE and mainTurnDistance is LOWEST then Value is HIGH with 0.2 + rule: if armyReward is MEDIUM and heroRole is SCOUT and danger is NONE then Value is HIGHEST with 0.5 + rule: if armyReward is LOW and heroRole is SCOUT and danger is NONE then Value is HIGH + rule: if armyReward is LOW and heroRole is MAIN and danger is not NONE and armyLoss is LOW then Value is HIGH + rule: if armyReward is LOW and heroRole is MAIN and danger is NONE then Value is BITLOW with 0.5 + rule: if armyReward is LOW and heroRole is MAIN and danger is NONE and mainTurnDistance is LOWEST then Value is HIGH + rule: if skillReward is LOW and heroRole is MAIN and armyLoss is LOW then Value is BITHIGH with 0.5 + rule: if skillReward is MEDIUM and heroRole is MAIN and armyLoss is LOW and fear is not HIGH then Value is HIGH with 0.5 + rule: if skillReward is HIGH and heroRole is MAIN and armyLoss is LOW and fear is not HIGH then Value is HIGH + rule: if strategicalValue is LOW and heroRole is MAIN and armyLoss is LOW then Value is BITLOW + rule: if strategicalValue is LOWEST and heroRole is MAIN and armyLoss is LOW then Value is LOW + rule: if strategicalValue is LOW and heroRole is SCOUT and armyLoss is LOW and fear is not HIGH then Value is HIGH with 0.5 + rule: if strategicalValue is MEDIUM and heroRole is SCOUT and danger is NONE and fear is not HIGH then Value is HIGH + rule: if strategicalValue is HIGH and heroRole is SCOUT and danger is NONE and fear is not HIGH then Value is HIGHEST with 0.5 + rule: if strategicalValue is HIGH and heroRole is MAIN and armyLoss is LOW and fear is not HIGH then Value is HIGHEST + rule: if strategicalValue is HIGH and heroRole is MAIN and armyLoss is MEDIUM and fear is not HIGH then Value is HIGH + rule: if strategicalValue is MEDIUM and heroRole is MAIN and armyLoss is LOW and fear is not HIGH then Value is HIGH + rule: if rewardType is NONE then Value is LOWEST + rule: if armyLoss is HIGH and strategicalValue is not HIGH and heroRole is MAIN then Value is LOWEST + rule: if armyLoss is HIGH and strategicalValue is HIGH and heroRole is MAIN then Value is LOW + rule: if armyLoss is HIGH and heroRole is SCOUT then Value is LOWEST + rule: if heroRole is SCOUT and closestHeroRatio is LOW then Value is LOW + rule: if heroRole is SCOUT and closestHeroRatio is LOWEST then Value is LOWEST + rule: if heroRole is MAIN and danger is NONE and skillReward is NONE and rewardType is SINGLE and closestHeroRatio is LOW then Value is LOW + rule: if heroRole is MAIN and danger is NONE and skillReward is NONE and rewardType is SINGLE and closestHeroRatio is LOWEST then Value is LOWEST + rule: if heroRole is MAIN and danger is not NONE and armyLoss is LOW then Value is BITHIGH with 0.2 + rule: if heroRole is SCOUT then Value is BITLOW + rule: if goldCost is not NONE and goldReward is NONE and goldPreasure is HIGH then Value is LOWEST + rule: if turn is NOW then Value is BITHIGH with 0.2 + rule: if goldPreasure is HIGH and goldReward is HIGH and armyLoss is LOW and fear is not HIGH then Value is HIGHEST + rule: if goldPreasure is HIGH and goldReward is MEDIUM and armyLoss is LOW and fear is not HIGH then Value is HIGH + rule: if goldPreasure is HIGH and goldReward is LOW and armyLoss is LOW then Value is BITHIGH + rule: if fear is MEDIUM then Value is LOW + rule: if fear is HIGH then Value is LOWEST \ No newline at end of file diff --git a/launcher/settingsView/csettingsview_moc.ui b/launcher/settingsView/csettingsview_moc.ui index 9c624a765..cdde691da 100644 --- a/launcher/settingsView/csettingsview_moc.ui +++ b/launcher/settingsView/csettingsview_moc.ui @@ -184,6 +184,11 @@ VCAI + + + Nullkiller + + diff --git a/lib/int3.h b/lib/int3.h index 0b5ed9613..3c066e056 100644 --- a/lib/int3.h +++ b/lib/int3.h @@ -40,6 +40,16 @@ public: //returns int3 with coordinates decreased by given number int3 operator-(const si32 i) const { return int3(x - i, y - i, z - i); } + //returns int3 with coordinates multiplied by given number + int3 operator*(const double i) const { return int3((int)(x * i), (int)(y * i), (int)(z * i)); } + //returns int3 with coordinates divided by given number + int3 operator/(const double i) const { return int3((int)(x / i), (int)(y / i), (int)(z / i)); } + + //returns int3 with coordinates multiplied by given number + int3 operator*(const si32 i) const { return int3(x * i, y * i, z * i); } + //returns int3 with coordinates divided by given number + int3 operator/(const si32 i) const { return int3(x / i, y / i, z / i); } + int3 & operator+=(const int3 & i) { x += i.x;