private void BuildCities() { if (Bot.Settings.CommerceGame == false || Bot.Settings.CommerceCityBaseCost.HasValue == false) { return; //can't build cities } var totalGold = Bot.Standing.NumResources(Bot.PlayerID, ResourceType.Gold); var spentGold = Bot.Settings.CostOfBuyingArmies(IncomeTracker.TotalArmiesDeployed); var maxPercent = !Bot.UseRandomness ? 0.5 : RandomUtility.BellRandom(0, 0.9); int goldLeftToSpendOnCities = Math.Min(totalGold - spentGold, SharedUtility.Round(totalGold * maxPercent)); //limit our cities to about half our gold to ensure we don't over-build AILog.Log("BuildCities", "totalGold=" + totalGold + " spentGold=" + spentGold + " goldToSpendOnCities=" + goldLeftToSpendOnCities + " maxPercent=" + maxPercent); if (goldLeftToSpendOnCities < Bot.Settings.CommerceCityBaseCost.Value) { return; //can't even afford one city } //randomize the safe range. This makes it int acceptableRangeFromOpponent = !Bot.UseRandomness ? 4 : SharedUtility.Round(RandomUtility.BellRandom(2, 6)); var eligibleTerritories = Bot.TerritoriesNotNearOpponent(acceptableRangeFromOpponent); eligibleTerritories.RemoveAll(Bot.AvoidTerritories); var numCitiesOn = eligibleTerritories.ToDictionary(o => o, o => Bot.Standing.Territories[o].NumStructures(StructureType.City)); //while we might be able to afford a city... while (goldLeftToSpendOnCities > Bot.Settings.CommerceCityBaseCost.Value) { var fewestCities = numCitiesOn.Values.Min(); var cheapestCityCost = fewestCities + Bot.Settings.CommerceCityBaseCost.Value; if (goldLeftToSpendOnCities < cheapestCityCost) { return; //can't afford any more, we must have one on every spot which increases the cost. } //We can afford it, let's build a city var buildCityOn = Bot.UseRandomness ? numCitiesOn.Where(o => o.Value == fewestCities).Random().Key : numCitiesOn.Where(o => o.Value == fewestCities).OrderBy(o => (int)o.Key).First().Key; goldLeftToSpendOnCities -= cheapestCityCost; //remember that we spent it for the loop above. AILog.Log("BuildCities", "Building a city on " + Bot.TerrString(buildCityOn) + " for " + cheapestCityCost + " unspentGold=" + goldLeftToSpendOnCities); Orders.PurchaseOrder.BuildCities.AddTo(buildCityOn, 1); numCitiesOn.AddTo(buildCityOn, 1); //Since we spent gold, adjust the remaining deployable armies so we don't overdeploy later this.UpdateEffectiveIncome(); } }