Kaynağa Gözat

NKAI: improve neutral town priority handling, reduce priority of objects like star axis

Andrii Danylchenko 2 yıl önce
ebeveyn
işleme
4bf570763a

+ 2 - 2
AI/Nullkiller/Analyzers/ArmyManager.cpp

@@ -58,7 +58,7 @@ std::vector<SlotInfo> ArmyManager::getSortedSlots(const CCreatureSet * target, c
 		}
 	}
 
-	for(auto pair : creToPower)
+	for(auto & pair : creToPower)
 		resultingArmy.push_back(pair.second);
 
 	boost::sort(resultingArmy, [](const SlotInfo & left, const SlotInfo & right) -> bool
@@ -112,7 +112,7 @@ std::vector<SlotInfo> ArmyManager::getBestArmy(const IBonusBearer * armyCarrier,
 	for(auto bonus : *bonusModifiers)
 	{
 		// army bonuses will change and object bonuses are temporary
-		if(bonus->source != Bonus::ARMY || bonus->source != Bonus::OBJECT)
+		if(bonus->source != Bonus::ARMY && bonus->source != Bonus::OBJECT)
 		{
 			newArmyInstance.addNewBonus(std::make_shared<Bonus>(*bonus));
 		}

+ 1 - 1
AI/Nullkiller/Analyzers/BuildAnalyzer.cpp

@@ -158,7 +158,7 @@ void BuildAnalyzer::update()
 
 	updateDailyIncome();
 
-	if(ai->cb->getDate(Date::EDateType::DAY) == 1 && dailyIncome[Res::GOLD] <= 500)
+	if(ai->cb->getDate(Date::EDateType::DAY) == 1)
 	{
 		goldPreasure = 1;
 	}

+ 6 - 0
AI/Nullkiller/Analyzers/HeroManager.cpp

@@ -111,6 +111,12 @@ void HeroManager::update()
 
 	int globalMainCount = std::min(((int)myHeroes.size() + 2) / 3, cb->getMapSize().x / 50 + 1);
 
+	//vstd::amin(globalMainCount, 1 + (cb->getTownsInfo().size() / 3));
+	if(cb->getTownsInfo().size() < 4 && globalMainCount > 2)
+	{
+		globalMainCount = 2;
+	}
+
 	std::sort(myHeroes.begin(), myHeroes.end(), scoreSort);
 
 	for(auto hero : myHeroes)

+ 6 - 11
AI/Nullkiller/Behaviors/StartupBehavior.cpp

@@ -70,10 +70,7 @@ bool needToRecruitHero(const CGTownInstance * startupTown)
 		return false;
 
 	if(!startupTown->garrisonHero && !startupTown->visitingHero)
-		return false;
-
-	auto heroToCheck = startupTown->garrisonHero ? startupTown->garrisonHero.get() : startupTown->visitingHero.get();
-	auto paths = cb->getPathsInfo(heroToCheck);
+		return true;
 
 	int treasureSourcesCount = 0;
 
@@ -84,18 +81,16 @@ bool needToRecruitHero(const CGTownInstance * startupTown)
 			|| obj->ID == Obj::CAMPFIRE
 			|| obj->ID == Obj::WATER_WHEEL)
 		{
-			auto path = paths->getPathInfo(obj->visitablePos());
-			if((path->accessible == CGPathNode::BLOCKVIS || path->accessible == CGPathNode::VISITABLE) 
-				&& path->reachable())
-			{
-				treasureSourcesCount++;
-			}
+			treasureSourcesCount++;
 		}
 	}
 
 	auto basicCount = cb->getTownsInfo().size() + 2;
-	auto boost = (int)std::floor(std::pow(treasureSourcesCount / 2.0, 2));
+	auto boost = std::min(
+		(int)std::floor(std::pow(1 + (cb->getMapSize().x / 50), 2)),
+		treasureSourcesCount / 2);
 
+	logAi->trace("Treasure sources found %d", treasureSourcesCount);
 	logAi->trace("Startup allows %d+%d heroes", basicCount, boost);
 
 	return cb->getHeroCount(ai->playerID, true) < basicCount + boost;

+ 3 - 0
AI/Nullkiller/Engine/FuzzyHelper.cpp

@@ -130,6 +130,9 @@ ui64 FuzzyHelper::evaluateDanger(const CGObjectInstance * obj)
 
 		return danger;
 	}
+	case Obj::PANDORAS_BOX:
+		return 10000; //Who knows what awaits us there
+
 	case Obj::ARTIFACT:
 	case Obj::RESOURCE:
 	{

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

@@ -236,7 +236,6 @@ void Nullkiller::makeTurn()
 		{
 			Goals::TTaskVec fastTasks = {
 				choseBestTask(sptr(BuyArmyBehavior()), 1),
-				choseBestTask(sptr(RecruitHeroBehavior()), 1),
 				choseBestTask(sptr(BuildingBehavior()), 1)
 			};
 
@@ -251,6 +250,7 @@ void Nullkiller::makeTurn()
 
 		Goals::TTaskVec bestTasks = {
 			bestTask,
+			choseBestTask(sptr(RecruitHeroBehavior()), 1),
 			choseBestTask(sptr(CaptureObjectsBehavior()), 1),
 			choseBestTask(sptr(ClusterBehavior()), MAX_DEPTH),
 			choseBestTask(sptr(DefenceBehavior()), MAX_DEPTH),

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

@@ -549,7 +549,7 @@ int32_t RewardEvaluator::getGoldReward(const CGObjectInstance * target, const CG
 	case Obj::SEA_CHEST:
 		return 1500;
 	case Obj::PANDORAS_BOX:
-		return 5000;
+		return 2500;
 	case Obj::PRISON:
 		//Objectively saves us 2500 to hire hero
 		return GameConstants::HERO_GOLD_COST;

+ 4 - 0
AI/Nullkiller/Pathfinding/AINodeStorage.cpp

@@ -855,6 +855,10 @@ void AINodeStorage::setHeroes(std::map<const CGHeroInstance *, HeroRole> heroes)
 
 	for(auto & hero : heroes)
 	{
+		// do not allow our own heroes in garrison to act on map
+		if(hero.first->getOwner() == ai->playerID && hero.first->inTownGarrison)
+			continue;
+
 		uint64_t mask = FirstActorMask << actors.size();
 		auto actor = std::make_shared<HeroActor>(hero.first, hero.second, mask, ai);
 

+ 13 - 9
config/ai/object-priorities.txt

@@ -86,8 +86,8 @@ InputVariable: strategicalValue
   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: LOW Triangle 0.000 0.250 0.700
+  term: MEDIUM Triangle 0.250 0.700 1.000
   term: HIGH Ramp 0.700 1.000
 InputVariable: goldPreasure
   description: Ratio between weekly army cost and gold income
@@ -189,10 +189,10 @@ RuleBlock: gold reward
   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 LOW and heroRole is MAIN and armyLoss is LOW then Value is BITHIGH
+  rule: if skillReward is MEDIUM and heroRole is MAIN and armyLoss is LOW and fear is not HIGH then Value is BITHIGH
   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 LOW and heroRole is MAIN and armyLoss is LOW then Value is BITHIGH
   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
@@ -211,9 +211,13 @@ RuleBlock: gold reward
   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 turn is NOW then Value is LOW with 0.3
+  rule: if turn is not NOW then Value is LOW with 0.4
+  rule: if goldPreasure is HIGH and goldReward 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 goldPreasure is HIGH and goldReward is MEDIUM and heroRole is MAIN and danger is not NONE and armyLoss is LOW and fear is not HIGH then Value is HIGH
+  rule: if goldPreasure is HIGH and goldReward is HIGH and heroRole is SCOUT and danger is NONE and armyLoss is LOW and fear is not HIGH then Value is HIGHEST
+  rule: if goldPreasure is HIGH and goldReward is MEDIUM and heroRole is SCOUT and danger is NONE and armyLoss is LOW and fear is not HIGH then Value is HIGH
+  rule: if goldPreasure is HIGH and goldReward is LOW and heroRole is SCOUT and armyLoss is LOW then Value is BITHIGH
+  rule: if goldPreasure is HIGH and goldReward is LOW and heroRole is SCOUT and scoutTurnDistance is LOW and armyLoss is LOW then Value is HIGH with 0.5
   rule: if fear is MEDIUM then Value is LOW
   rule: if fear is HIGH then Value is LOWEST