From 1aa81530cb3832d3445747a2e0337b3ea211c5a0 Mon Sep 17 00:00:00 2001 From: Andrii Danylchenko Date: Sun, 16 May 2021 15:09:44 +0300 Subject: [PATCH] Nullkiller: cancel heavy decomposition on shipyards --- AI/Nullkiller/Analyzers/ArmyManager.cpp | 2 +- .../Behaviors/CaptureObjectsBehavior.cpp | 3 +- AI/Nullkiller/CMakeLists.txt | 2 + AI/Nullkiller/Engine/DeepDecomposer.cpp | 17 +++++++- AI/Nullkiller/Goals/AbstractGoal.h | 3 +- AI/Nullkiller/Goals/CaptureObject.cpp | 40 +++++++++++++++++++ AI/Nullkiller/Goals/CaptureObject.h | 40 +++++++++++++++++++ AI/Nullkiller/Pathfinding/AINodeStorage.h | 2 +- .../Pathfinding/Actions/BoatActions.cpp | 4 +- 9 files changed, 106 insertions(+), 7 deletions(-) create mode 100644 AI/Nullkiller/Goals/CaptureObject.cpp create mode 100644 AI/Nullkiller/Goals/CaptureObject.h diff --git a/AI/Nullkiller/Analyzers/ArmyManager.cpp b/AI/Nullkiller/Analyzers/ArmyManager.cpp index b4381e4a7..3da29237f 100644 --- a/AI/Nullkiller/Analyzers/ArmyManager.cpp +++ b/AI/Nullkiller/Analyzers/ArmyManager.cpp @@ -108,7 +108,7 @@ std::vector ArmyManager::getBestArmy(const IBonusBearer * armyCarrier, // army bonuses will change and object bonuses are temporary if(bonus->source != Bonus::ARMY || bonus->source != Bonus::OBJECT) { - newArmyInstance.addNewBonus(bonus); + newArmyInstance.addNewBonus(std::make_shared(*bonus)); } } diff --git a/AI/Nullkiller/Behaviors/CaptureObjectsBehavior.cpp b/AI/Nullkiller/Behaviors/CaptureObjectsBehavior.cpp index 05c8b1c9f..d4e26ab00 100644 --- a/AI/Nullkiller/Behaviors/CaptureObjectsBehavior.cpp +++ b/AI/Nullkiller/Behaviors/CaptureObjectsBehavior.cpp @@ -146,7 +146,8 @@ Goals::TGoalVec CaptureObjectsBehavior::decompose() const { Goals::TGoalVec tasks; - auto captureObjects = [&](const std::vector & objs) -> void{ + auto captureObjects = [&](const std::vector & objs) -> void + { if(objs.empty()) { return; diff --git a/AI/Nullkiller/CMakeLists.txt b/AI/Nullkiller/CMakeLists.txt index 0a3fb5348..cc21d8c95 100644 --- a/AI/Nullkiller/CMakeLists.txt +++ b/AI/Nullkiller/CMakeLists.txt @@ -29,6 +29,7 @@ set(VCAI_SRCS Goals/BuyArmy.cpp Goals/AdventureSpellCast.cpp Goals/Trade.cpp + Goals/CaptureObject.cpp Goals/RecruitHero.cpp Goals/DigAtTile.cpp Goals/ExecuteHeroChain.cpp @@ -89,6 +90,7 @@ set(VCAI_HEADERS Goals/BuyArmy.h Goals/AdventureSpellCast.h Goals/Trade.h + Goals/CaptureObject.h Goals/RecruitHero.h Goals/DigAtTile.h Goals/ExecuteHeroChain.h diff --git a/AI/Nullkiller/Engine/DeepDecomposer.cpp b/AI/Nullkiller/Engine/DeepDecomposer.cpp index 9c9649cee..6dae5a7ee 100644 --- a/AI/Nullkiller/Engine/DeepDecomposer.cpp +++ b/AI/Nullkiller/Engine/DeepDecomposer.cpp @@ -139,6 +139,21 @@ Goals::TSubgoal DeepDecomposer::unwrapComposition(Goals::TSubgoal goal) return goal->goalType == Goals::COMPOSITION ? goal->decompose().back() : goal; } +bool isEquivalentGoals(TSubgoal goal1, TSubgoal goal2) +{ + if(goal1 == goal2) return true; + + if(goal1->goalType == Goals::CAPTURE_OBJECT && goal2->goalType == Goals::CAPTURE_OBJECT) + { + auto o1 = cb->getObj(ObjectInstanceID(goal1->objid)); + auto o2 = cb->getObj(ObjectInstanceID(goal2->objid)); + + return o1->ID == Obj::SHIPYARD && o1->ID == o2->ID; + } + + return false; +} + bool DeepDecomposer::isCompositionLoop(TSubgoal goal) { auto goalsToTest = goal->goalType == Goals::COMPOSITION ? goal->decompose() : TGoalVec{goal}; @@ -149,7 +164,7 @@ bool DeepDecomposer::isCompositionLoop(TSubgoal goal) { auto parent = unwrapComposition(goals[i].back()); - if(parent == goalToTest) + if(isEquivalentGoals(parent, goalToTest)) { return true; } diff --git a/AI/Nullkiller/Goals/AbstractGoal.h b/AI/Nullkiller/Goals/AbstractGoal.h index 2c66adb09..32b7496e0 100644 --- a/AI/Nullkiller/Goals/AbstractGoal.h +++ b/AI/Nullkiller/Goals/AbstractGoal.h @@ -66,7 +66,8 @@ namespace Goals UNLOCK_CLUSTER, HERO_EXCHANGE, ARMY_UPGRADE, - DEFEND_TOWN + DEFEND_TOWN, + CAPTURE_OBJECT }; class DLL_EXPORT TSubgoal : public std::shared_ptr diff --git a/AI/Nullkiller/Goals/CaptureObject.cpp b/AI/Nullkiller/Goals/CaptureObject.cpp new file mode 100644 index 000000000..574c562d1 --- /dev/null +++ b/AI/Nullkiller/Goals/CaptureObject.cpp @@ -0,0 +1,40 @@ +/* +* CaptureObject.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 "CaptureObject.h" +#include "../../../lib/mapObjects/CGTownInstance.h" +#include "../VCAI.h" +#include "../Engine/Nullkiller.h" +#include "../Behaviors/CaptureObjectsBehavior.h" + + +extern boost::thread_specific_ptr cb; + +using namespace Goals; + +bool CaptureObject::operator==(const CaptureObject & other) const +{ + return objid == other.objid; +} + +uint64_t CaptureObject::getHash() const +{ + return objid; +} + +std::string CaptureObject::toString() const +{ + return "Capture " + name + " at " + tile.toString(); +} + +TGoalVec CaptureObject::decompose() const +{ + return CaptureObjectsBehavior(cb->getObj(ObjectInstanceID(objid))).decompose(); +} \ No newline at end of file diff --git a/AI/Nullkiller/Goals/CaptureObject.h b/AI/Nullkiller/Goals/CaptureObject.h new file mode 100644 index 000000000..02de78cdc --- /dev/null +++ b/AI/Nullkiller/Goals/CaptureObject.h @@ -0,0 +1,40 @@ +/* +* CaptureObject.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" + +struct HeroPtr; +class VCAI; +class FuzzyHelper; + +namespace Goals +{ + class DLL_EXPORT CaptureObject : public CGoal + { + private: + std::string name; + + public: + CaptureObject(const CGObjectInstance * obj) + : CGoal(Goals::CAPTURE_OBJECT) + { + objid = obj->id.getNum(); + tile = obj->visitablePos(); + name = obj->getObjectName(); + } + + virtual bool operator==(const CaptureObject & other) const override; + virtual Goals::TGoalVec decompose() const override; + virtual std::string toString() const override; + virtual bool hasHash() const override { return true; } + virtual uint64_t getHash() const override; + }; +} 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/BoatActions.cpp b/AI/Nullkiller/Pathfinding/Actions/BoatActions.cpp index b09c93c95..d9f2be544 100644 --- a/AI/Nullkiller/Pathfinding/Actions/BoatActions.cpp +++ b/AI/Nullkiller/Pathfinding/Actions/BoatActions.cpp @@ -11,7 +11,7 @@ #include "StdInc.h" #include "../../VCAI.h" #include "../../Goals/AdventureSpellCast.h" -#include "../../Behaviors/CaptureObjectsBehavior.h" +#include "../../Goals/CaptureObject.h" #include "../../Goals/BuildBoat.h" #include "../../../../lib/mapping/CMap.h" #include "../../../../lib/mapObjects/MapObjects.h" @@ -31,7 +31,7 @@ namespace AIPathfinding { if(cb->getPlayerRelations(ai->playerID, shipyard->o->tempOwner) == PlayerRelations::ENEMIES) { - return Goals::sptr(Goals::CaptureObjectsBehavior(shipyard->o)); + return Goals::sptr(Goals::CaptureObject(shipyard->o)); } return sptr(Goals::Invalid());