From ec6c84b0e04c2755bbf6d313c6d0980b8d6724e5 Mon Sep 17 00:00:00 2001 From: Andrii Danylchenko Date: Tue, 17 Sep 2024 15:24:59 +0300 Subject: [PATCH 1/3] NKAI: pandora as blocker object --- AI/Nullkiller/Analyzers/ObjectClusterizer.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/AI/Nullkiller/Analyzers/ObjectClusterizer.cpp b/AI/Nullkiller/Analyzers/ObjectClusterizer.cpp index 7b9607390..630be2ce5 100644 --- a/AI/Nullkiller/Analyzers/ObjectClusterizer.cpp +++ b/AI/Nullkiller/Analyzers/ObjectClusterizer.cpp @@ -141,6 +141,7 @@ std::optional ObjectClusterizer::getBlocker(const AIPa || blocker->ID == Obj::BORDERGUARD || blocker->ID == Obj::BORDER_GATE || blocker->ID == Obj::SHIPYARD + || blocker->ID == Obj::PANDORAS_BOX || (blocker->ID == Obj::QUEST_GUARD && node.actionIsBlocked)) { return blocker; From ce0f51672a8e1589e2ec6ff5e23bfef3b51ce336 Mon Sep 17 00:00:00 2001 From: Andrii Danylchenko Date: Fri, 20 Sep 2024 15:57:02 +0300 Subject: [PATCH 2/3] NKAI: replace hardcoded pandora with more flexible solution --- AI/Nullkiller/AIGateway.cpp | 9 ++++++++- AI/Nullkiller/Analyzers/ObjectClusterizer.cpp | 8 +++++++- AI/Nullkiller/Goals/ExploreNeighbourTile.cpp | 2 +- AI/Nullkiller/Pathfinding/AINodeStorage.cpp | 4 +--- AI/Nullkiller/Pathfinding/AINodeStorage.h | 6 ------ AI/Nullkiller/Pathfinding/GraphPaths.cpp | 4 ++-- AI/Nullkiller/Pathfinding/ObjectGraphCalculator.cpp | 4 ++-- .../Pathfinding/Rules/AIMovementAfterDestinationRule.cpp | 4 ++-- 8 files changed, 23 insertions(+), 18 deletions(-) diff --git a/AI/Nullkiller/AIGateway.cpp b/AI/Nullkiller/AIGateway.cpp index da6144e74..3609182df 100644 --- a/AI/Nullkiller/AIGateway.cpp +++ b/AI/Nullkiller/AIGateway.cpp @@ -649,7 +649,14 @@ void AIGateway::showBlockingDialog(const std::string & text, const std::vectordangerEvaluator->evaluateDanger(target, hero.get()); auto ratio = static_cast(danger) / hero->getTotalStrength(); - answer = topObj->id == goalObjectID; // no if we do not aim to visit this object + answer = 1; + + if(topObj->id != goalObjectID && nullkiller->dangerEvaluator->evaluateDanger(topObj) > 0) + { + // no if we do not aim to visit this object + answer = 0; + } + logAi->trace("Query hook: %s(%s) by %s danger ratio %f", target.toString(), topObj->getObjectName(), hero.name(), ratio); if(cb->getObj(goalObjectID, false)) diff --git a/AI/Nullkiller/Analyzers/ObjectClusterizer.cpp b/AI/Nullkiller/Analyzers/ObjectClusterizer.cpp index 630be2ce5..5c628f288 100644 --- a/AI/Nullkiller/Analyzers/ObjectClusterizer.cpp +++ b/AI/Nullkiller/Analyzers/ObjectClusterizer.cpp @@ -141,12 +141,18 @@ std::optional ObjectClusterizer::getBlocker(const AIPa || blocker->ID == Obj::BORDERGUARD || blocker->ID == Obj::BORDER_GATE || blocker->ID == Obj::SHIPYARD - || blocker->ID == Obj::PANDORAS_BOX || (blocker->ID == Obj::QUEST_GUARD && node.actionIsBlocked)) { return blocker; } + auto danger = ai->dangerEvaluator->evaluateDanger(blocker); + + if(danger > 0 && blocker->isBlockedVisitable() && isObjectRemovable(blocker)) + { + return blocker; + } + return std::optional< const CGObjectInstance *>(); } diff --git a/AI/Nullkiller/Goals/ExploreNeighbourTile.cpp b/AI/Nullkiller/Goals/ExploreNeighbourTile.cpp index 4f6a4903e..6efa0e0b4 100644 --- a/AI/Nullkiller/Goals/ExploreNeighbourTile.cpp +++ b/AI/Nullkiller/Goals/ExploreNeighbourTile.cpp @@ -59,7 +59,7 @@ void ExploreNeighbourTile::accept(AIGateway * ai) return; } - auto danger = ai->nullkiller->pathfinder->getStorage()->evaluateDanger(target, hero, true); + auto danger = ai->nullkiller->dangerEvaluator->evaluateDanger(target, hero, true); if(danger > 0 || !ai->moveHeroToTile(target, hero)) { diff --git a/AI/Nullkiller/Pathfinding/AINodeStorage.cpp b/AI/Nullkiller/Pathfinding/AINodeStorage.cpp index 326eda3d1..c7c318c95 100644 --- a/AI/Nullkiller/Pathfinding/AINodeStorage.cpp +++ b/AI/Nullkiller/Pathfinding/AINodeStorage.cpp @@ -97,8 +97,6 @@ AINodeStorage::AINodeStorage(const Nullkiller * ai, const int3 & Sizes) { accessibility = std::make_unique>( boost::extents[sizes.z][sizes.x][sizes.y][EPathfindingLayer::NUM_LAYERS]); - - dangerEvaluator.reset(new FuzzyHelper(ai)); } AINodeStorage::~AINodeStorage() = default; @@ -1419,7 +1417,7 @@ void AINodeStorage::calculateChainInfo(std::vector & paths, const int3 & path.targetHero = node.actor->hero; path.heroArmy = node.actor->creatureSet; path.armyLoss = node.armyLoss; - path.targetObjectDanger = evaluateDanger(pos, path.targetHero, !node.actor->allowBattle); + path.targetObjectDanger = ai->dangerEvaluator->evaluateDanger(pos, path.targetHero, !node.actor->allowBattle); if(path.targetObjectDanger > 0) { diff --git a/AI/Nullkiller/Pathfinding/AINodeStorage.h b/AI/Nullkiller/Pathfinding/AINodeStorage.h index 9e18bd7bd..a7352acdb 100644 --- a/AI/Nullkiller/Pathfinding/AINodeStorage.h +++ b/AI/Nullkiller/Pathfinding/AINodeStorage.h @@ -176,7 +176,6 @@ private: const CPlayerSpecificInfoCallback * cb; const Nullkiller * ai; - std::unique_ptr dangerEvaluator; AISharedStorage nodes; std::vector> actors; std::vector heroChain; @@ -285,11 +284,6 @@ public: bool calculateHeroChain(); bool calculateHeroChainFinal(); - inline uint64_t evaluateDanger(const int3 & tile, const CGHeroInstance * hero, bool checkGuards) const - { - return dangerEvaluator->evaluateDanger(tile, hero, checkGuards); - } - uint64_t evaluateArmyLoss(const CGHeroInstance * hero, uint64_t armyValue, uint64_t danger) const; inline EPathAccessibility getAccessibility(const int3 & tile, EPathfindingLayer layer) const diff --git a/AI/Nullkiller/Pathfinding/GraphPaths.cpp b/AI/Nullkiller/Pathfinding/GraphPaths.cpp index a3dba0696..136e8491c 100644 --- a/AI/Nullkiller/Pathfinding/GraphPaths.cpp +++ b/AI/Nullkiller/Pathfinding/GraphPaths.cpp @@ -291,7 +291,7 @@ void GraphPaths::addChainInfo(std::vector & paths, int3 tile, const CGHe } path.armyLoss += loss; - path.targetObjectDanger = ai->pathfinder->getStorage()->evaluateDanger(tile, path.targetHero, !allowBattle); + path.targetObjectDanger = ai->dangerEvaluator->evaluateDanger(tile, path.targetHero, !allowBattle); path.targetObjectArmyLoss = ai->pathfinder->getStorage()->evaluateArmyLoss(path.targetHero, path.heroArmy->getArmyStrength(), path.targetObjectDanger); paths.push_back(path); @@ -356,7 +356,7 @@ void GraphPaths::quickAddChainInfoWithBlocker(std::vector & paths, int3 path.heroArmy = entryPath.heroArmy; path.exchangeCount = entryPath.exchangeCount; path.armyLoss = entryPath.armyLoss + ai->pathfinder->getStorage()->evaluateArmyLoss(path.targetHero, path.heroArmy->getArmyStrength(), danger); - path.targetObjectDanger = ai->pathfinder->getStorage()->evaluateDanger(tile, path.targetHero, !allowBattle); + path.targetObjectDanger = ai->dangerEvaluator->evaluateDanger(tile, path.targetHero, !allowBattle); path.targetObjectArmyLoss = ai->pathfinder->getStorage()->evaluateArmyLoss(path.targetHero, path.heroArmy->getArmyStrength(), path.targetObjectDanger); AIPathNodeInfo n; diff --git a/AI/Nullkiller/Pathfinding/ObjectGraphCalculator.cpp b/AI/Nullkiller/Pathfinding/ObjectGraphCalculator.cpp index de20fb439..8905572c9 100644 --- a/AI/Nullkiller/Pathfinding/ObjectGraphCalculator.cpp +++ b/AI/Nullkiller/Pathfinding/ObjectGraphCalculator.cpp @@ -164,7 +164,7 @@ void ObjectGraphCalculator::calculateConnections(const int3 & pos, std::vectorvisitablePos(); auto fromObj = actorObjectMap[path.targetHero]; - auto danger = ai->pathfinder->getStorage()->evaluateDanger(pos, path.targetHero, true); + auto danger = ai->dangerEvaluator->evaluateDanger(pos, path.targetHero, true); auto updated = target->tryAddConnection( from, pos, @@ -220,7 +220,7 @@ void ObjectGraphCalculator::calculateConnections(const int3 & pos, std::vectorpathfinder->getStorage()->evaluateDanger(pos2, path1.targetHero, true); + auto danger = ai->dangerEvaluator->evaluateDanger(pos2, path1.targetHero, true); auto updated = target->tryAddConnection( pos1, diff --git a/AI/Nullkiller/Pathfinding/Rules/AIMovementAfterDestinationRule.cpp b/AI/Nullkiller/Pathfinding/Rules/AIMovementAfterDestinationRule.cpp index 88d61372c..ebb482a1a 100644 --- a/AI/Nullkiller/Pathfinding/Rules/AIMovementAfterDestinationRule.cpp +++ b/AI/Nullkiller/Pathfinding/Rules/AIMovementAfterDestinationRule.cpp @@ -227,7 +227,7 @@ namespace AIPathfinding return false; } - auto danger = nodeStorage->evaluateDanger(destination.coord, nodeStorage->getHero(destination.node), true); + auto danger = ai->dangerEvaluator->evaluateDanger(destination.coord, nodeStorage->getHero(destination.node), true); if(danger) { @@ -313,7 +313,7 @@ namespace AIPathfinding } auto hero = nodeStorage->getHero(source.node); - uint64_t danger = nodeStorage->evaluateDanger(destination.coord, hero, true); + uint64_t danger = ai->dangerEvaluator->evaluateDanger(destination.coord, hero, true); uint64_t actualArmyValue = srcNode->actor->armyValue - srcNode->armyLoss; uint64_t loss = nodeStorage->evaluateArmyLoss(hero, actualArmyValue, danger); From d6e69b9586f613f0af88a5ec853a01da6cc8f384 Mon Sep 17 00:00:00 2001 From: kdmcser Date: Sun, 22 Sep 2024 14:22:56 +0800 Subject: [PATCH 3/3] not report warning in factory-town --- config/schemas/faction.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/schemas/faction.json b/config/schemas/faction.json index 841c03240..e25c286e4 100644 --- a/config/schemas/faction.json +++ b/config/schemas/faction.json @@ -96,7 +96,7 @@ "creatures" : { "type" : "array", "minItems" : 7, - "maxItems" : 7, + "maxItems" : 8, "description" : "List of creatures available for recruitment on each level", "items" : { "type" : "array",