Selaa lähdekoodia

Fixes for AI town building logic

- Fixes AI not considering non-built dwellings
- AI will now skip evaluation of towns in which construction today is no
longer possible
Ivan Savenko 9 kuukautta sitten
vanhempi
sitoutus
8468469976

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

@@ -11,6 +11,7 @@
 #include "../Engine/Nullkiller.h"
 #include "../Engine/Nullkiller.h"
 #include "../../../lib/entities/building/CBuilding.h"
+#include "../../../lib/IGameSettings.h"
 
 namespace NKAI
 {
@@ -30,30 +31,22 @@ void BuildAnalyzer::updateTownDwellings(TownDevelopmentInfo & developmentInfo)
 	for(int level = 0; level < developmentInfo.town->getTown()->creatures.size(); level++)
 	{
 		logAi->trace("Checking dwelling level %d", level);
-		BuildingInfo nextToBuild = BuildingInfo();
-
-		BuildingID buildID = BuildingID(BuildingID::getDwellingFromLevel(level, 0));
-
-		for(; developmentInfo.town->getBuildings().count(buildID); BuildingID::advanceDwelling(buildID))
+		for(BuildingID buildID = BuildingID::getDwellingFromLevel(level, 0); buildID.hasValue(); BuildingID::advanceDwelling(buildID))
 		{
-			if(!developmentInfo.town->hasBuilt(buildID))
+			if(developmentInfo.town->getTown()->buildings.count(buildID) == 0)
 				continue; // no such building in town
 
 			auto info = getBuildingOrPrerequisite(developmentInfo.town, buildID);
 
+			if (!info.exists && !info.canBuild && !info.notEnoughRes)
+				continue;
+
 			if(info.exists)
-			{
 				developmentInfo.addExistingDwelling(info);
+			else
+				developmentInfo.addBuildingToBuild(info);
 
-				break;
-			}
-
-			nextToBuild = info;
-		}
-
-		if(nextToBuild.id != BuildingID::NONE)
-		{
-			developmentInfo.addBuildingToBuild(nextToBuild);
+			break;
 		}
 	}
 }
@@ -148,6 +141,9 @@ void BuildAnalyzer::update()
 
 	for(const CGTownInstance* town : towns)
 	{
+		if(town->built >= cb->getSettings().getInteger(EGameSettings::TOWNS_BUILDINGS_PER_TURN_CAP))
+			continue; // Not much point in trying anything - can't built in this town anymore today
+
 		logAi->trace("Checking town %s", town->getNameTranslated());
 
 		developmentInfos.push_back(TownDevelopmentInfo(town));
@@ -272,11 +268,11 @@ BuildingInfo BuildAnalyzer::getBuildingOrPrerequisite(
 
 			if(vstd::contains_if(missingBuildings, otherDwelling))
 			{
-				logAi->trace("cant build. Need other dwelling");
+				logAi->trace("cant build %d. Need other dwelling %d", toBuild.getNum(), missingBuildings.front().getNum());
 			}
 			else if(missingBuildings[0] != toBuild)
 			{
-				logAi->trace("cant build. Need %d", missingBuildings[0].num);
+				logAi->trace("cant build %d. Need %d", toBuild.getNum(), missingBuildings[0].num);
 
 				BuildingInfo prerequisite = getBuildingOrPrerequisite(town, missingBuildings[0], excludeDwellingDependencies);
 
@@ -307,10 +303,14 @@ BuildingInfo BuildAnalyzer::getBuildingOrPrerequisite(
 				return info;
 			}
 		}
+		else
+		{
+			logAi->trace("Cant build. Reason: %d", static_cast<int>(canBuild));
+		}
 	}
 	else
 	{
-		logAi->trace("exists");
+		logAi->trace("Dwelling %d exists", toBuild.getNum());
 		info.exists = true;
 	}
 

+ 5 - 3
AI/Nullkiller/Behaviors/BuildingBehavior.cpp

@@ -59,17 +59,19 @@ Goals::TGoalVec BuildingBehavior::decompose(const Nullkiller * ai) const
 		{
 			closestThreat = std::min(closestThreat, threat.turn);
 		}
-		for (auto& buildingInfo : developmentInfo.toBuild)
+
+		if (closestThreat <= 1 && developmentInfo.town->fortLevel() < CGTownInstance::EFortLevel::CASTLE)
 		{
-			if (closestThreat <= 1 && developmentInfo.town->fortLevel() < CGTownInstance::EFortLevel::CASTLE && !buildingInfo.notEnoughRes)
+			for (auto& buildingInfo : developmentInfo.toBuild)
 			{
-				if (buildingInfo.id == BuildingID::CITADEL || buildingInfo.id == BuildingID::CASTLE)
+				if ( !buildingInfo.notEnoughRes && (buildingInfo.id == BuildingID::CITADEL || buildingInfo.id == BuildingID::CASTLE))
 				{
 					tasks.push_back(sptr(BuildThis(buildingInfo, developmentInfo)));
 					emergencyDefense = true;
 				}
 			}
 		}
+
 		if (!emergencyDefense)
 		{
 			for (auto& buildingInfo : developmentInfo.toBuild)

+ 8 - 1
lib/constants/EntityIdentifiers.h

@@ -325,7 +325,14 @@ private:
 public:
 	static Type getDwellingFromLevel(int level, int upgradeIndex)
 	{
-		return getDwellings()[upgradeIndex][level];
+		try
+		{
+			return getDwellings().at(upgradeIndex).at(level);
+		}
+		catch (const std::out_of_range & e)
+		{
+			return Type::NONE;
+		}
 	}
 
 	static int getLevelFromDwelling(BuildingIDBase dwelling)