From bb5392db4a5a01239144aa99a98d798c6d26d811 Mon Sep 17 00:00:00 2001 From: Interdice <67503847+Interdice@users.noreply.github.com> Date: Wed, 4 Aug 2021 02:53:46 +1000 Subject: [PATCH] Ai now cares about city distances (#4680) * Ai now cares about distance from it's cities * Ai now cares about distance from it's cities * Ai now cares about distance from it's cities * Ai will pay extra pay extra for bordering cities or surrounding cities * Ai will pay extra pay extra for bordering cities or surrounding cities * Ai will pay extra for cities that are closer to their territory * The code is cleaner * The code is cleaner * The code is cleaner * Ai now values distance * Ai now values distance * Ai now values distance * Ai now values distance * Ai now values distance * Ai now values distance * Ai now values distance * Ai now values distance * Ai now values distance * Ai now values distance * Ai now values distance * Ai now values distance * Ai now values distance * Ai now values distance * Ai now values distance * Ai now values distance --- core/src/com/unciv/logic/city/CityInfo.kt | 18 ++++++++++++++ .../com/unciv/logic/trade/TradeEvaluation.kt | 24 +++++++++++++++++-- 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/core/src/com/unciv/logic/city/CityInfo.kt b/core/src/com/unciv/logic/city/CityInfo.kt index 13509a0d13..f2a417a3e6 100644 --- a/core/src/com/unciv/logic/city/CityInfo.kt +++ b/core/src/com/unciv/logic/city/CityInfo.kt @@ -13,6 +13,7 @@ import com.unciv.models.ruleset.tile.ResourceSupplyList import com.unciv.models.ruleset.tile.ResourceType import com.unciv.models.ruleset.unit.BaseUnit import java.util.* +import kotlin.collections.ArrayList import kotlin.collections.HashMap import kotlin.collections.HashSet import kotlin.math.ceil @@ -231,6 +232,7 @@ class CityInfo { fun isConnectedToCapital(connectionTypePredicate: (Set) -> Boolean = { true }): Boolean { val mediumTypes = civInfo.citiesConnectedToCapitalToMediums[this] ?: return false return connectionTypePredicate(mediumTypes) + } fun isInResistance() = resistanceCounter > 0 @@ -629,5 +631,21 @@ class CityInfo { return !isOriginalCapital && !isCapital() && !isHolyCity() } + + fun getNeighbouringCivs(): List { + val tilesList: HashSet = getTiles().toHashSet() + val cityPositionList: ArrayList = arrayListOf() + + for (tiles in tilesList) + for (tile in tiles.neighbors) + if (!tilesList.contains(tile)) + cityPositionList.add(tile) + + return cityPositionList.asSequence() + .map { it.getOwner()?.civName }.filterNotNull().toSet() + .distinct().toList() + } + + //endregion } diff --git a/core/src/com/unciv/logic/trade/TradeEvaluation.kt b/core/src/com/unciv/logic/trade/TradeEvaluation.kt index f0dbd2f87d..402f779bb9 100644 --- a/core/src/com/unciv/logic/trade/TradeEvaluation.kt +++ b/core/src/com/unciv/logic/trade/TradeEvaluation.kt @@ -3,6 +3,7 @@ package com.unciv.logic.trade import com.unciv.Constants import com.unciv.logic.automation.Automation import com.unciv.logic.automation.ThreatLevel +import com.unciv.logic.city.CityInfo import com.unciv.logic.civilization.CivilizationInfo import com.unciv.logic.civilization.diplomacy.RelationshipLevel import com.unciv.models.ruleset.tile.ResourceType @@ -147,9 +148,10 @@ class TradeEvaluation { TradeType.City -> { val city = tradePartner.cities.first { it.id == offer.name } val stats = city.cityStats.currentCityStats + val surrounded: Int = surroundedByOurCities(city, civInfo) if (civInfo.getHappiness() + city.cityStats.happinessList.values.sum() < 0) return 0 // we can't really afford to go into negative happiness because of buying a city - val sumOfStats = stats.culture + stats.gold + stats.science + stats.production + stats.happiness + stats.food + val sumOfStats = stats.culture + stats.gold + stats.science + stats.production + stats.happiness + stats.food + surrounded return sumOfStats.toInt() * 100 } TradeType.Agreement -> { @@ -158,6 +160,16 @@ class TradeEvaluation { } } } + fun surroundedByOurCities(city: CityInfo, civInfo: CivilizationInfo): Int{ + val borderingCivs: List = city.getNeighbouringCivs() + if (borderingCivs.size == 1 && borderingCivs.contains(civInfo.civName)){ + return 10*civInfo.getEraNumber() // if the city is surrounded only by trading civ + } + if (borderingCivs.contains(civInfo.civName)) + return 2*civInfo.getEraNumber() // if the city has a border with trading civ + return 0 + + } fun evaluateSellCost(offer: TradeOffer, civInfo: CivilizationInfo, tradePartner: CivilizationInfo): Int { when (offer.type) { @@ -217,8 +229,10 @@ class TradeEvaluation { TradeType.City -> { val city = civInfo.cities.first { it.id == offer.name } + val capitalcity = civInfo.getCapital() + val distanceCost = distanceCityTradeModifier(civInfo, capitalcity, city) val stats = city.cityStats.currentCityStats - val sumOfStats = stats.culture + stats.gold + stats.science + stats.production + stats.happiness + stats.food + val sumOfStats = stats.culture + stats.gold + stats.science + stats.production + stats.happiness + stats.food - distanceCost return sumOfStats.toInt() * 100 } TradeType.Agreement -> { @@ -235,6 +249,12 @@ class TradeEvaluation { } } } + fun distanceCityTradeModifier(civInfo: CivilizationInfo, capitalcity: CityInfo, city: CityInfo): Int{ + val distanceBetweenCities = capitalcity.getCenterTile().aerialDistanceTo(city.getCenterTile()) + + if (distanceBetweenCities < 500) return 0 + return min(50, (500 - distanceBetweenCities) * civInfo.getEraNumber()) + } fun evaluatePeaceCostForThem(ourCivilization: CivilizationInfo, otherCivilization: CivilizationInfo): Int { val ourCombatStrength = Automation.evaluateCombatStrength(ourCivilization)