Prechádzať zdrojové kódy

Nullkiller: stabilisation

Andrii Danylchenko 4 rokov pred
rodič
commit
1fd838a5b9

+ 5 - 1
AI/Nullkiller/Behaviors/DefenceBehavior.cpp

@@ -88,7 +88,11 @@ void DefenceBehavior::evaluateDefence(Goals::TGoalVec & tasks, const CGTownInsta
 	{
 		if(!ai->nullkiller->isHeroLocked(town->garrisonHero.get()))
 		{
-			tasks.push_back(Goals::sptr(Goals::ExchangeSwapTownHeroes(town, nullptr).setpriority(5)));
+			if(!town->visitingHero)
+			{
+				tasks.push_back(Goals::sptr(Goals::ExchangeSwapTownHeroes(town, nullptr).setpriority(5)));
+			}
+
 			return;
 		}
 

+ 8 - 1
AI/Nullkiller/Behaviors/GatherArmyBehavior.cpp

@@ -159,7 +159,7 @@ Goals::TGoalVec GatherArmyBehavior::deliverArmyToHero(const CGHeroInstance * her
 	return tasks;
 }
 
-Goals::TGoalVec GatherArmyBehavior::upgradeArmy(const CGObjectInstance * upgrader) const
+Goals::TGoalVec GatherArmyBehavior::upgradeArmy(const CGTownInstance * upgrader) const
 {
 	Goals::TGoalVec tasks;
 	const int3 pos = upgrader->visitablePos();
@@ -181,6 +181,13 @@ Goals::TGoalVec GatherArmyBehavior::upgradeArmy(const CGObjectInstance * upgrade
 #ifdef AI_TRACE_LEVEL >= 2
 		logAi->trace("Path found %s", path.toString());
 #endif
+		if(upgrader->visitingHero != path.targetHero)
+		{
+#ifdef AI_TRACE_LEVEL >= 2
+			logAi->trace("Ignore path. Town has visiting hero.");
+#endif
+			continue;
+		}
 
 		if(path.getFirstBlockedAction())
 		{

+ 1 - 1
AI/Nullkiller/Behaviors/GatherArmyBehavior.h

@@ -31,6 +31,6 @@ public:
 
 private:
 	Goals::TGoalVec deliverArmyToHero(const CGHeroInstance * hero) const;
-	Goals::TGoalVec upgradeArmy(const CGObjectInstance * upgrader) const;
+	Goals::TGoalVec upgradeArmy(const CGTownInstance * upgrader) const;
 };
 

+ 6 - 3
AI/Nullkiller/Engine/Nullkiller.cpp

@@ -147,7 +147,10 @@ void Nullkiller::makeTurn()
 
 		try
 		{
-			activeHero = bestTask->hero.get();
+			if(bestTask->hero)
+			{
+				activeHero = bestTask->hero.get();
+			}
 
 			bestTask->accept(ai.get());
 		}
@@ -155,12 +158,12 @@ void Nullkiller::makeTurn()
 		{
 			logAi->trace(bestTask->completeMessage());
 		}
-		/*catch(std::exception & e)
+		catch(std::exception & e)
 		{
 			logAi->debug("Failed to realize subgoal of type %s, I will stop.", bestTask->name());
 			logAi->debug("The error message was: %s", e.what());
 
 			return;
-		}*/
+		}
 	}
 }

+ 1 - 1
AI/Nullkiller/Pathfinding/AINodeStorage.cpp

@@ -476,7 +476,7 @@ void AINodeStorage::calculateHeroChain(
 
 		if(other->actor->isMovable)
 		{
-			bool hasLessMp = carrier->turns > other->turns || carrier->moveRemains < other->moveRemains;
+			bool hasLessMp = carrier->turns > other->turns || (carrier->turns == other->turns && carrier->moveRemains < other->moveRemains);
 			bool hasLessExperience = carrier->actor->hero->exp < other->actor->hero->exp;
 
 			if(hasLessMp && hasLessExperience)

+ 37 - 1
AI/Nullkiller/Pathfinding/Rules/AIMovementAfterDestinationRule.cpp

@@ -58,7 +58,7 @@ namespace AIPathfinding
 			return;
 
 		auto destGuardians = cb->getGuardingCreatures(destination.coord);
-		bool allowBypass = true;
+		bool allowBypass = false;
 
 		switch(blocker)
 		{
@@ -74,12 +74,38 @@ namespace AIPathfinding
 				allowBypass = bypassDestinationGuards(destGuardians, source, destination, pathfinderConfig, pathfinderHelper);
 
 			break;
+
+		case BlockingReason::DESTINATION_VISIT:
+			allowBypass = true;
+
+			break;
+
+		case BlockingReason::DESTINATION_BLOCKED:
+			allowBypass = bypassBlocker(source, destination, pathfinderConfig, pathfinderHelper);
+
+			break;
 		}
 
 		destination.blocked = !allowBypass || nodeStorage->isDistanceLimitReached(source, destination);
 		destination.node->locked = !allowBypass;
 	}
 
+	bool AIMovementAfterDestinationRule::bypassBlocker(
+		const PathNodeInfo & source,
+		CDestinationNodeInfo & destination,
+		const PathfinderConfig * pathfinderConfig,
+		CPathfinderHelper * pathfinderHelper) const
+	{
+		auto enemyHero = destination.nodeHero && destination.heroRelations == PlayerRelations::ENEMIES;
+
+		if(enemyHero)
+		{
+			return bypassBattle(source, destination, pathfinderConfig, pathfinderHelper);
+		}
+
+		return false;
+	}
+
 	bool AIMovementAfterDestinationRule::bypassRemovableObject(
 		const PathNodeInfo & source,
 		CDestinationNodeInfo & destination,
@@ -151,6 +177,16 @@ namespace AIPathfinding
 			return true;
 		}
 
+		return bypassBattle(source, destination, pathfinderConfig, pathfinderHelper);
+	}
+
+	bool AIMovementAfterDestinationRule::bypassBattle(
+		const PathNodeInfo & source,
+		CDestinationNodeInfo & destination,
+		const PathfinderConfig * pathfinderConfig,
+		CPathfinderHelper * pathfinderHelper) const
+	{
+		const AIPathNode *  srcNode = nodeStorage->getAINode(source.node);
 		const AIPathNode * destNode = nodeStorage->getAINode(destination.node);
 		auto battleNodeOptional = nodeStorage->getOrCreateNode(
 			destination.coord,

+ 12 - 0
AI/Nullkiller/Pathfinding/Rules/AIMovementAfterDestinationRule.h

@@ -46,5 +46,17 @@ namespace AIPathfinding
 			CDestinationNodeInfo & destination,
 			const PathfinderConfig * pathfinderConfig,
 			CPathfinderHelper * pathfinderHelper) const;
+
+		bool bypassBlocker(
+			const PathNodeInfo & source,
+			CDestinationNodeInfo & destination,
+			const PathfinderConfig * pathfinderConfig,
+			CPathfinderHelper * pathfinderHelper) const;
+
+		bool bypassBattle(
+			const PathNodeInfo & source,
+			CDestinationNodeInfo & destination,
+			const PathfinderConfig * pathfinderConfig,
+			CPathfinderHelper * pathfinderHelper) const;
 	};
 }