Skip to content

Commit

Permalink
Builder AI Updates (#11167)
Browse files Browse the repository at this point in the history
Add improvement evaluation scores for golden age points, local culture and tourism.

Tweak values of existing yields.

Builder AI will now prechop features for future planned improvements.

Builder AI should now be better at planning improvements with SameAdjacent and SameTwoAdjacent properties.

Builder AI should no longer build non-town GP improvements on city connections.

Skip some unnecessary computations in CP version, should make it a bit more efficient.

When canBuild is called with bTestEra set to true, also take this in consideration when checking if a feature is blocking the build.

Fix bug where improvements with large negative scores would be valued very highly (mostly affecting GP improvements).

Simplify improvement resource monopoly calculation and make it consistent (should solve rare issue of improvement indecision from the AI).

Ignore luxury value if the luxury is banned.

Add a small static value to existing improvements.

Remove an unused function.
  • Loading branch information
KungCheops authored Jul 21, 2024
1 parent ceb0cdc commit 1da77b4
Show file tree
Hide file tree
Showing 9 changed files with 406 additions and 230 deletions.
9 changes: 6 additions & 3 deletions (1) Community Patch/Core Files/Core Values/CoreDefines.sql
Original file line number Diff line number Diff line change
Expand Up @@ -213,10 +213,13 @@ UPDATE Defines SET Value = 750 WHERE Name = 'BUILDER_TASKING_BASELINE_BUILD_ROUT
UPDATE Defines SET Value = 300 WHERE Name = 'BUILDER_TASKING_BASELINE_BUILD_RESOURCE_IMPROVEMENTS';
UPDATE Defines SET Value = 100 WHERE Name = 'BUILDER_TASKING_BASELINE_BUILD_IMPROVEMENTS';
INSERT INTO Defines (Name, Value) SELECT 'BUILDER_TASKING_BASELINE_ADDS_FOOD', 180;
INSERT INTO Defines (Name, Value) SELECT 'BUILDER_TASKING_BASELINE_ADDS_GOLD', 40;
INSERT INTO Defines (Name, Value) SELECT 'BUILDER_TASKING_BASELINE_ADDS_FAITH', 150;
INSERT INTO Defines (Name, Value) SELECT 'BUILDER_TASKING_BASELINE_ADDS_PRODUCTION', 200;
INSERT INTO Defines (Name, Value) SELECT 'BUILDER_TASKING_BASELINE_ADDS_GOLD', 80;
INSERT INTO Defines (Name, Value) SELECT 'BUILDER_TASKING_BASELINE_ADDS_FAITH', 200;
INSERT INTO Defines (Name, Value) SELECT 'BUILDER_TASKING_BASELINE_ADDS_PRODUCTION', 180;
INSERT INTO Defines (Name, Value) SELECT 'BUILDER_TASKING_BASELINE_ADDS_SCIENCE', 200;
INSERT INTO Defines (Name, Value) SELECT 'BUILDER_TASKING_BASELINE_ADDS_TOURISM', 200;
INSERT INTO Defines (Name, Value) SELECT 'BUILDER_TASKING_BASELINE_ADDS_CULTURE_LOCAL', 100;
INSERT INTO Defines (Name, Value) SELECT 'BUILDER_TASKING_BASELINE_ADDS_GOLDEN_AGE_POINTS', 200;
UPDATE Defines SET Value = 200 WHERE Name = 'BUILDER_TASKING_BASELINE_ADDS_CULTURE';

-- Scouts
Expand Down
508 changes: 312 additions & 196 deletions CvGameCoreDLL_Expansion2/CvBuilderTaskingAI.cpp

Large diffs are not rendered by default.

19 changes: 13 additions & 6 deletions CvGameCoreDLL_Expansion2/CvBuilderTaskingAI.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ struct BuilderDirective
NUM_DIRECTIVES ENUM_META_VALUE
};

BuilderDirective() : m_eDirectiveType(NUM_DIRECTIVES), m_eBuild(NO_BUILD), m_eResource(NO_RESOURCE), m_bIsGreatPerson(false), m_sX(-1), m_sY(-1), m_iScore(-1), m_iScorePenalty(-1) {}
BuilderDirective(BuilderDirectiveType eDirective, BuildTypes eBuild, ResourceTypes eResource, bool bIsGreatPerson, short sX, short sY, int iScore)
BuilderDirective() : m_eDirectiveType(NUM_DIRECTIVES), m_eBuild(NO_BUILD), m_eResource(NO_RESOURCE), m_bIsGreatPerson(false), m_sX(-1), m_sY(-1), m_iScore(-1), m_iPotentialBonusScore(-1), m_iScorePenalty(-1) {}
BuilderDirective(BuilderDirectiveType eDirective, BuildTypes eBuild, ResourceTypes eResource, bool bIsGreatPerson, short sX, short sY, int iScore, int iPotentialScore)
{
m_eDirectiveType = eDirective;
m_eBuild = eBuild;
Expand All @@ -40,6 +40,7 @@ struct BuilderDirective
m_sX = sX;
m_sY = sY;
m_iScore = iScore;
m_iPotentialBonusScore = iPotentialScore;
m_iScorePenalty = 0;
}

Expand All @@ -52,8 +53,8 @@ struct BuilderDirective
short m_sY;
int m_iScore;
int m_iScorePenalty;
//int m_iGoldCost;
//short m_sMoveTurnsAway;
int m_iPotentialBonusScore;

bool operator==(const BuilderDirective& rhs) const
{
return m_eDirectiveType == rhs.m_eDirectiveType && m_eBuild == rhs.m_eBuild && m_eResource == rhs.m_eResource && m_sX == rhs.m_sX && m_sY == rhs.m_sY && m_bIsGreatPerson == rhs.m_bIsGreatPerson;
Expand All @@ -67,10 +68,16 @@ struct BuilderDirective
if (m_sY != rhs.m_sY) return m_sY < rhs.m_sY;
return m_bIsGreatPerson < rhs.m_bIsGreatPerson;
}

int GetScore() const
{
return m_iScore - m_iScorePenalty;
}

int GetPotentialScore() const
{
return m_iScore + m_iPotentialBonusScore - m_iScorePenalty;
}
};
FDataStream& operator<<(FDataStream&, const BuilderDirective&);
FDataStream& operator>>(FDataStream&, BuilderDirective&);
Expand Down Expand Up @@ -118,7 +125,7 @@ class CvBuilderTaskingAI
bool ShouldAnyBuilderConsiderPlot(const CvPlot* pPlot) const; // general checks for whether the plot should be considered
bool ShouldBuilderConsiderPlot(CvUnit* pUnit, CvPlot* pPlot); // specific checks for this particular worker

int GetResourceWeight(ResourceTypes eResource, int iQuantity, int iAdditionalOwned=0);
int GetResourceWeight(ResourceTypes eResource, int iQuantity);

bool DoesBuildHelpRush(CvPlot* pPlot, BuildTypes eBuild);
pair<RouteTypes, int> GetBestRouteTypeAndValue(const CvPlot* pPlot) const;
Expand All @@ -127,7 +134,7 @@ class CvBuilderTaskingAI
bool WillNeverBuildVillageOnPlot(CvPlot* pPlot, RouteTypes eRoute, bool bIgnoreUnowned) const;
ImprovementTypes SavePlotForUniqueImprovement(const CvPlot* pPlot) const;

int ScorePlotBuild(CvPlot* pPlot, ImprovementTypes eImprovement, BuildTypes eBuild, const SBuilderState& sState = SBuilderState::DefaultInstance());
pair<int, int> ScorePlotBuild(CvPlot* pPlot, ImprovementTypes eImprovement, BuildTypes eBuild, const SBuilderState& sState = SBuilderState::DefaultInstance());
int GetTotalRouteBuildTime(const CvUnit* pUnit, const CvPlot* pPlot) const;

BuildTypes GetRepairBuild(void);
Expand Down
12 changes: 9 additions & 3 deletions CvGameCoreDLL_Expansion2/CvGlobals.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -179,10 +179,13 @@ CvGlobals::CvGlobals() :
GD_INT_INIT(BUILDER_TASKING_BASELINE_REPAIR, 1000),
GD_INT_INIT(BUILDER_TASKING_BASELINE_SCRUB_FALLOUT, 20000),
GD_INT_INIT(BUILDER_TASKING_BASELINE_ADDS_FOOD, 180),
GD_INT_INIT(BUILDER_TASKING_BASELINE_ADDS_GOLD, 40),
GD_INT_INIT(BUILDER_TASKING_BASELINE_ADDS_FAITH, 150),
GD_INT_INIT(BUILDER_TASKING_BASELINE_ADDS_PRODUCTION, 200),
GD_INT_INIT(BUILDER_TASKING_BASELINE_ADDS_GOLD, 80),
GD_INT_INIT(BUILDER_TASKING_BASELINE_ADDS_FAITH, 200),
GD_INT_INIT(BUILDER_TASKING_BASELINE_ADDS_PRODUCTION, 180),
GD_INT_INIT(BUILDER_TASKING_BASELINE_ADDS_SCIENCE, 200),
GD_INT_INIT(BUILDER_TASKING_BASELINE_ADDS_TOURISM, 200),
GD_INT_INIT(BUILDER_TASKING_BASELINE_ADDS_CULTURE_LOCAL, 100),
GD_INT_INIT(BUILDER_TASKING_BASELINE_ADDS_GOLDEN_AGE_POINTS, 200),
GD_INT_INIT(BUILDER_TASKING_BASELINE_ADDS_CULTURE, 200),
GD_INT_INIT(AI_STRATEGY_DEFEND_MY_LANDS_BASE_UNITS, 3),
GD_INT_INIT(AI_MILITARY_CITY_THREAT_WEIGHT_CAPITAL, 125),
Expand Down Expand Up @@ -5026,6 +5029,9 @@ void CvGlobals::cacheGlobals()
GD_INT_CACHE(BUILDER_TASKING_BASELINE_ADDS_FAITH);
GD_INT_CACHE(BUILDER_TASKING_BASELINE_ADDS_PRODUCTION);
GD_INT_CACHE(BUILDER_TASKING_BASELINE_ADDS_SCIENCE);
GD_INT_CACHE(BUILDER_TASKING_BASELINE_ADDS_TOURISM);
GD_INT_CACHE(BUILDER_TASKING_BASELINE_ADDS_CULTURE_LOCAL);
GD_INT_CACHE(BUILDER_TASKING_BASELINE_ADDS_GOLDEN_AGE_POINTS);
GD_INT_CACHE(BUILDER_TASKING_BASELINE_ADDS_CULTURE);
GD_INT_CACHE(AI_STRATEGY_DEFEND_MY_LANDS_BASE_UNITS);
GD_INT_CACHE(AI_MILITARY_CITY_THREAT_WEIGHT_CAPITAL);
Expand Down
3 changes: 3 additions & 0 deletions CvGameCoreDLL_Expansion2/CvGlobals.h
Original file line number Diff line number Diff line change
Expand Up @@ -774,6 +774,9 @@ class CvGlobals
GD_INT_MEMBER(BUILDER_TASKING_BASELINE_ADDS_FAITH); // VP
GD_INT_MEMBER(BUILDER_TASKING_BASELINE_ADDS_PRODUCTION); // VP
GD_INT_MEMBER(BUILDER_TASKING_BASELINE_ADDS_SCIENCE); // VP
GD_INT_MEMBER(BUILDER_TASKING_BASELINE_ADDS_TOURISM); // VP
GD_INT_MEMBER(BUILDER_TASKING_BASELINE_ADDS_CULTURE_LOCAL); // VP
GD_INT_MEMBER(BUILDER_TASKING_BASELINE_ADDS_GOLDEN_AGE_POINTS); // VP
GD_INT_MEMBER(BUILDER_TASKING_BASELINE_ADDS_CULTURE);
GD_INT_MEMBER(AI_STRATEGY_DEFEND_MY_LANDS_BASE_UNITS);
GD_INT_MEMBER(AI_MILITARY_CITY_THREAT_WEIGHT_CAPITAL);
Expand Down
72 changes: 54 additions & 18 deletions CvGameCoreDLL_Expansion2/CvHomelandAI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2516,7 +2516,9 @@ bool CvHomelandAI::ExecuteExplorerMoves(CvUnit* pUnit)
// Higher weight means better directive
static int GetDirectiveWeight(BuilderDirective eDirective, int iBuildTurns, int iMoveTurns)
{
int iScore = eDirective.GetScore() / 10;
int iScore = (eDirective.GetScore() + (eDirective.m_iPotentialBonusScore / 3)) / 10;

int iSign = iScore >= 0 ? 1 : -1;

// Try to avoid moving around too much with workers
if (!eDirective.m_bIsGreatPerson)
Expand All @@ -2533,7 +2535,7 @@ static int GetDirectiveWeight(BuilderDirective eDirective, int iBuildTurns, int
const int iScoreWeightSquared = 1;
int iBuildTimeWeightSquared = 25;

return (iScore * iScore) * iScoreWeightSquared - (iBuildTime * iBuildTime) * iBuildTimeWeightSquared;
return iSign * (iScore * iScore) * iScoreWeightSquared - (iBuildTime * iBuildTime) * iBuildTimeWeightSquared;
}

static bool IsBestDirectiveForBuilderAndPlot(BuilderDirective eDirective, CvUnit* pUnit, const CvPlayer* pPlayer, vector<BuilderDirective> aDirectives)
Expand Down Expand Up @@ -2565,10 +2567,10 @@ static bool IsBestDirectiveForBuilderAndPlot(BuilderDirective eDirective, CvUnit
if ((eRoute != NO_ROUTE && eOtherRoute == NO_ROUTE) || (eRoute == NO_ROUTE && eOtherRoute != NO_ROUTE))
continue;

if (eOtherDirective.GetScore() < eDirective.GetScore())
if (eOtherDirective.GetPotentialScore() < eDirective.GetPotentialScore())
continue;

if (eOtherDirective.GetScore() == eDirective.GetScore())
if (eOtherDirective.GetPotentialScore() == eDirective.GetPotentialScore())
if (eOtherDirective.m_eBuild > eDirective.m_eBuild)
continue;

Expand Down Expand Up @@ -2853,6 +2855,15 @@ void CvHomelandAI::ExecuteWorkerMoves()
ignoredDirectives.insert(eDirective);
m_workedPlots.insert(GC.getMap().plot(eDirective.m_sX, eDirective.m_sY)->GetPlotIndex());
}
if (GC.getLogging() && GC.getAILogging())
{
CvString strLogString;
CvBuildInfo* pkBuild = GC.getBuildInfo(eDirective.m_eBuild);
CvString strTemp = pkBuild->GetDescription();
strLogString.Format("Player %d wants to %s at (%d, %d), value=%d, potential value=%d, weighted value=%d", m_pPlayer->GetID(), strTemp.GetCString(),
eDirective.m_sX, eDirective.m_sY, eDirective.GetScore(), eDirective.GetPotentialScore(), pUnitAndDirectiveWithScore.score);
LogHomelandMessage(strLogString);
}
}
else
{
Expand All @@ -2874,7 +2885,7 @@ void CvHomelandAI::ExecuteWorkerMoves()
ImprovementTypes eOldImprovement = !pDirectivePlot->IsImprovementPillaged() ? pDirectivePlot->getImprovementType() : NO_IMPROVEMENT;
ImprovementTypes eImprovement = (ImprovementTypes)pkBuildInfo->getImprovement();

if (eImprovement == NO_IMPROVEMENT && pkBuildInfo->isRepair() && pDirectivePlot->IsImprovementPillaged())
if (eImprovement == NO_IMPROVEMENT && (pkBuildInfo->isRepair() || !pDirectivePlot->IsImprovementPillaged()))
eImprovement = pDirectivePlot->getImprovementType();

CvImprovementEntry* pkImprovementInfo = GC.getImprovementInfo(eImprovement);
Expand Down Expand Up @@ -2931,12 +2942,12 @@ void CvHomelandAI::ExecuteWorkerMoves()

// Feature considerations
bool bFeatureStateChanged = false;
FeatureTypes eFeatureFromImprovement = pkImprovementInfo ? pkImprovementInfo->GetCreatedFeature() : NO_FEATURE;
FeatureTypes eFeature = pkBuildInfo->isFeatureRemove(pDirectivePlot->getFeatureType()) ? NO_FEATURE : pDirectivePlot->getFeatureType();
eFeature = eFeatureFromImprovement != NO_FEATURE ? eFeatureFromImprovement : eFeature;

if (bCanBuild)
{
FeatureTypes eFeatureFromImprovement = pkImprovementInfo ? pkImprovementInfo->GetCreatedFeature() : NO_FEATURE;
FeatureTypes eFeature = pkBuildInfo->isFeatureRemove(pDirectivePlot->getFeatureType()) ? NO_FEATURE : pDirectivePlot->getFeatureType();
eFeature = eFeatureFromImprovement != NO_FEATURE ? eFeatureFromImprovement : eFeature;

if (!MOD_BALANCE_VP && eFeature != pDirectivePlot->getFeatureType())
{
sState.mChangedPlotFeatures[pDirectivePlot->GetPlotIndex()] = eFeature;
Expand Down Expand Up @@ -3002,7 +3013,8 @@ void CvHomelandAI::ExecuteWorkerMoves()

CvPlot* pOtherPlot = GC.getMap().plot(eOtherDirective.m_sX, eOtherDirective.m_sY);
CvBuildInfo* pkOtherBuildInfo = GC.getBuildInfo(eOtherDirective.m_eBuild);
ImprovementTypes eOtherImprovement = pkOtherBuildInfo ? (ImprovementTypes)pkOtherBuildInfo->getImprovement() : eOldImprovement;
ImprovementTypes eOtherOldImprovement = !pOtherPlot->IsImprovementPillaged() ? pOtherPlot->getImprovementType() : NO_IMPROVEMENT;
ImprovementTypes eOtherImprovement = pkOtherBuildInfo ? (ImprovementTypes)pkOtherBuildInfo->getImprovement() : eOtherOldImprovement;

if (eOtherImprovement == NO_IMPROVEMENT && pkOtherBuildInfo && pkOtherBuildInfo->isRepair() && pOtherPlot->IsImprovementPillaged())
eOtherImprovement = pOtherPlot->getImprovementType();
Expand All @@ -3019,14 +3031,22 @@ void CvHomelandAI::ExecuteWorkerMoves()
}
else
{
if (eOtherImprovement != NO_IMPROVEMENT)
// Don't remove features that are needed for future better improvements
if (eFeature != NO_FEATURE && pkOtherBuildInfo && pkOtherBuildInfo->isFeatureRemove(eFeature) && pkImprovementInfo && pkImprovementInfo->GetFeatureMakesValid(eFeature))
continue;

if (eOtherImprovement != NO_IMPROVEMENT && eOtherImprovement != eOtherOldImprovement)
{
int iScore = pBuilderTaskingAI->ScorePlotBuild(pDirectivePlot, eOtherImprovement, eOtherDirective.m_eBuild, sState);
pair<int,int> pScore = pBuilderTaskingAI->ScorePlotBuild(pDirectivePlot, eOtherImprovement, eOtherDirective.m_eBuild, sState);

int iScore = pScore.first;
int iPotentialScore = pScore.second;

// If we are planning to build something else here in the future, downscale the priority of this by 1/3
eOtherDirective.m_iScore = iScore;
eOtherDirective.m_iPotentialBonusScore = iPotentialScore;
eOtherDirective.m_iScorePenalty += iScore / 3;
if (eOtherDirective.m_iScorePenalty >= eOtherDirective.m_iScore)
if (eOtherDirective.m_iScorePenalty >= eOtherDirective.m_iScore + eOtherDirective.m_iPotentialBonusScore)
continue;
bDirectiveUpdated = true;
}
Expand All @@ -3045,13 +3065,17 @@ void CvHomelandAI::ExecuteWorkerMoves()
if (eOtherImprovement != NO_IMPROVEMENT && bResourceStateChanged && !bDirectiveUpdated)
{
// Connecting a resource may reduce or increase the value of connecting more instances of the same resource
if ((pOtherPlot->getResourceType(m_pPlayer->getTeam()) == eResource && pkOtherImprovementInfo && pkOtherImprovementInfo->IsConnectsResource(eResource)) || (pkOtherImprovementInfo && pkOtherImprovementInfo->GetResourceFromImprovement() == eResource))
if (pOtherPlot->getResourceType(m_pPlayer->getTeam()) == eResource || (pkOtherImprovementInfo && pkOtherImprovementInfo->GetResourceFromImprovement() == eResource))
{
int iScore = pBuilderTaskingAI->ScorePlotBuild(pOtherPlot, eOtherImprovement, eOtherDirective.m_eBuild, sState);
pair<int, int> pScore = pBuilderTaskingAI->ScorePlotBuild(pOtherPlot, eOtherImprovement, eOtherDirective.m_eBuild, sState);

int iScore = pScore.first;
int iPotentialScore = pScore.second;

if (iScore != eOtherDirective.m_iScore)
{
eOtherDirective.m_iScore = iScore;
eOtherDirective.m_iPotentialBonusScore = iPotentialScore;
bDirectiveUpdated = true;
}
}
Expand All @@ -3070,11 +3094,15 @@ void CvHomelandAI::ExecuteWorkerMoves()

if (eOtherFeature != pOtherPlot->getFeatureType())
{
int iScore = pBuilderTaskingAI->ScorePlotBuild(pOtherPlot, eOtherImprovement, eOtherDirective.m_eBuild, sState);
pair<int, int> pScore = pBuilderTaskingAI->ScorePlotBuild(pOtherPlot, eOtherImprovement, eOtherDirective.m_eBuild, sState);

int iScore = pScore.first;
int iPotentialScore = pScore.second;

if (iScore != eOtherDirective.m_iScore)
{
eOtherDirective.m_iScore = iScore;
eOtherDirective.m_iPotentialBonusScore = iPotentialScore;
bDirectiveUpdated = true;
}
}
Expand All @@ -3098,11 +3126,15 @@ void CvHomelandAI::ExecuteWorkerMoves()

if (eOtherOldImprovement != eOtherImprovement && (iOtherNewDefenseModifier != 0 || iOtherOldDefenseModifier != 0 || iOtherNewImprovementDamage != 0 || iOtherOldImprovementDamage != 0))
{
int iScore = pBuilderTaskingAI->ScorePlotBuild(pOtherPlot, eOtherImprovement, eOtherDirective.m_eBuild, sState);
pair<int, int> pScore = pBuilderTaskingAI->ScorePlotBuild(pOtherPlot, eOtherImprovement, eOtherDirective.m_eBuild, sState);

int iScore = pScore.first;
int iPotentialScore = pScore.second;

if (iScore != eOtherDirective.m_iScore)
{
eOtherDirective.m_iScore = iScore;
eOtherDirective.m_iPotentialBonusScore = iPotentialScore;
bDirectiveUpdated = true;
}
}
Expand All @@ -3115,11 +3147,15 @@ void CvHomelandAI::ExecuteWorkerMoves()
// TODO check if we will actually change the yield value before we call ScorePlotBuild
if (plotDistance(eOtherDirective.m_sX, eOtherDirective.m_sY, eDirective.m_sX, eDirective.m_sY) == 1)
{
int iScore = pBuilderTaskingAI->ScorePlotBuild(pOtherPlot, eOtherImprovement, eOtherDirective.m_eBuild, sState);
pair<int, int> pScore = pBuilderTaskingAI->ScorePlotBuild(pOtherPlot, eOtherImprovement, eOtherDirective.m_eBuild, sState);

int iScore = pScore.first;
int iPotentialScore = pScore.second;

if (iScore != eOtherDirective.m_iScore)
{
eOtherDirective.m_iScore = iScore;
eOtherDirective.m_iPotentialBonusScore = iPotentialScore;
bDirectiveUpdated = true;
}
}
Expand Down
9 changes: 7 additions & 2 deletions CvGameCoreDLL_Expansion2/CvPlayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15973,7 +15973,7 @@ bool CvPlayer::canBuild(const CvPlot* pPlot, BuildTypes eBuild, bool bTestEra, b

if(pPlot && !bTestVisible)
{
if(IsBuildBlockedByFeature(eBuild, pPlot->getFeatureType()))
if(IsBuildBlockedByFeature(eBuild, pPlot->getFeatureType(), bTestEra))
{
return false;
}
Expand All @@ -15991,7 +15991,7 @@ bool CvPlayer::canBuild(const CvPlot* pPlot, BuildTypes eBuild, bool bTestEra, b
}

/// Are we prevented from eBuild-ing because of a Feature on this plot?
bool CvPlayer::IsBuildBlockedByFeature(BuildTypes eBuild, FeatureTypes eFeature) const
bool CvPlayer::IsBuildBlockedByFeature(BuildTypes eBuild, FeatureTypes eFeature, bool bTestEra) const
{
// No Feature here to block us
if(eFeature == NO_FEATURE)
Expand Down Expand Up @@ -16019,6 +16019,11 @@ bool CvPlayer::IsBuildBlockedByFeature(BuildTypes eBuild, FeatureTypes eFeature)
return false;
}

if (bTestEra && ((GetCurrentEra() + 1) >= GC.getTechInfo((TechTypes)GC.getBuildInfo(eBuild)->getTechPrereq())->GetEra()))
{
return false;
}

// Feature is blocking us!
return true;
}
Expand Down
2 changes: 1 addition & 1 deletion CvGameCoreDLL_Expansion2/CvPlayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,7 @@ class CvPlayer
int GetWorldWonderYieldChange(int iYield);

bool canBuild(const CvPlot* pPlot, BuildTypes eBuild, bool bTestEra = false, bool bTestVisible = false, bool bTestGold = true, bool bTestPlotOwner = true, const CvUnit* pUnit = NULL) const;
bool IsBuildBlockedByFeature(BuildTypes eBuild, FeatureTypes eFeature) const;
bool IsBuildBlockedByFeature(BuildTypes eBuild, FeatureTypes eFeature, bool bTestEra = false) const;
int getBuildCost(const CvPlot* pPlot, BuildTypes eBuild) const;
int getImprovementUpgradeRate() const;

Expand Down
2 changes: 1 addition & 1 deletion CvGameCoreDLL_Expansion2/CvPlayerAI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3099,7 +3099,7 @@ std::priority_queue<SPlotWithScore> CvPlayerAI::GetBestCultureBombPlots(BuildTyp
ResourceTypes eResource = pAdjacentPlot->getResourceType(getTeam());
if (eResource != NO_RESOURCE)
{
iScore += (GetBuilderTaskingAI()->GetResourceWeight(eResource, NO_IMPROVEMENT, pAdjacentPlot->getNumResource()) * iWeightFactor);
iScore += (GetBuilderTaskingAI()->GetResourceWeight(eResource, pAdjacentPlot->getNumResource()) * iWeightFactor);
}

// score yield
Expand Down

0 comments on commit 1da77b4

Please sign in to comment.