فهرست منبع

AI-adjustments

AI no longer rushes towns that don't have a citadel or better when there is a scary enemy hero around.

AI will no longer try to maximize defenses by using the strongest possible defender. Instead it will try to use the most appropriate defender. The most appropriate is considered to have roughly 75% power of the threat and the score will be lower but still above zero the bigger the deviation is.
Xilmi 9 ماه پیش
والد
کامیت
cf3eee5d8a
1فایلهای تغییر یافته به همراه22 افزوده شده و 1 حذف شده
  1. 22 1
      AI/Nullkiller/Engine/PriorityEvaluator.cpp

+ 22 - 1
AI/Nullkiller/Engine/PriorityEvaluator.cpp

@@ -1077,6 +1077,8 @@ public:
 				evaluationContext.isHero = true;
 				evaluationContext.isHero = true;
 			if (target->getOwner().isValidPlayer() && ai->cb->getPlayerRelations(ai->playerID, target->getOwner()) == PlayerRelations::ENEMIES)
 			if (target->getOwner().isValidPlayer() && ai->cb->getPlayerRelations(ai->playerID, target->getOwner()) == PlayerRelations::ENEMIES)
 				evaluationContext.isEnemy = true;
 				evaluationContext.isEnemy = true;
+			if (target->ID == Obj::TOWN)
+				evaluationContext.defenseValue = dynamic_cast<const CGTownInstance*>(target)->fortLevel();
 			evaluationContext.goldCost += evaluationContext.evaluator.getGoldCost(target, hero, army);
 			evaluationContext.goldCost += evaluationContext.evaluator.getGoldCost(target, hero, army);
 			if(evaluationContext.danger > 0)
 			if(evaluationContext.danger > 0)
 				evaluationContext.skillReward += (float)evaluationContext.danger / (float)hero->getArmyStrength();
 				evaluationContext.skillReward += (float)evaluationContext.danger / (float)hero->getArmyStrength();
@@ -1465,6 +1467,8 @@ float PriorityEvaluator::evaluate(Goals::TSubgoal task, int priorityTier)
 					return 0;
 					return 0;
 				if (evaluationContext.movementCost >= 1)
 				if (evaluationContext.movementCost >= 1)
 					return 0;
 					return 0;
+				if (evaluationContext.defenseValue < 2 && evaluationContext.enemyHeroDangerRatio > dangerThreshold)
+					return 0;
 				if(evaluationContext.conquestValue > 0)
 				if(evaluationContext.conquestValue > 0)
 					score = evaluationContext.armyInvolvement;
 					score = evaluationContext.armyInvolvement;
 				if (vstd::isAlmostZero(score) || (evaluationContext.enemyHeroDangerRatio > dangerThreshold && (evaluationContext.turn > 0 || evaluationContext.isExchange) && !ai->cb->getTownsInfo().empty()))
 				if (vstd::isAlmostZero(score) || (evaluationContext.enemyHeroDangerRatio > dangerThreshold && (evaluationContext.turn > 0 || evaluationContext.isExchange) && !ai->cb->getTownsInfo().empty()))
@@ -1487,13 +1491,30 @@ float PriorityEvaluator::evaluate(Goals::TSubgoal task, int priorityTier)
 				if (evaluationContext.isEnemy && evaluationContext.turn > 0)
 				if (evaluationContext.isEnemy && evaluationContext.turn > 0)
 					return 0;
 					return 0;
 				if (evaluationContext.isDefend && evaluationContext.threatTurns <= evaluationContext.turn)
 				if (evaluationContext.isDefend && evaluationContext.threatTurns <= evaluationContext.turn)
-					score = evaluationContext.armyInvolvement / (evaluationContext.turn + 1);
+				{
+					const float OPTIMAL_PERCENTAGE = 0.75f; // We want army to be 75% of the threat
+					float optimalStrength = evaluationContext.threat * OPTIMAL_PERCENTAGE;
+
+					// Calculate how far the army is from optimal strength
+					float deviation = std::abs(evaluationContext.armyInvolvement - optimalStrength);
+
+					// Convert deviation to a percentage of the threat to normalize it
+					float deviationPercentage = deviation / evaluationContext.threat;
+
+					// Calculate score: 1.0 is perfect, decreasing as deviation increases
+					score = 1.0f / (1.0f + deviationPercentage);
+
+					// Apply turn penalty to still prefer earlier moves when scores are close
+					score = score / (evaluationContext.turn + 1);
+				}
 				break;
 				break;
 			}
 			}
 			case PriorityTier::KILL: //Take towns / kill heroes that are further away
 			case PriorityTier::KILL: //Take towns / kill heroes that are further away
 				//FALL_THROUGH
 				//FALL_THROUGH
 			case PriorityTier::FAR_KILL:
 			case PriorityTier::FAR_KILL:
 			{
 			{
+				if (evaluationContext.defenseValue < 2 && evaluationContext.enemyHeroDangerRatio > dangerThreshold)
+					return 0;
 				if (evaluationContext.turn > 0 && evaluationContext.isHero)
 				if (evaluationContext.turn > 0 && evaluationContext.isHero)
 					return 0;
 					return 0;
 				if (arriveNextWeek && evaluationContext.isEnemy)
 				if (arriveNextWeek && evaluationContext.isEnemy)