mirror of
https://github.com/yairm210/Unciv.git
synced 2025-07-12 16:59:11 +07:00
Un-hardcoded some settler checks
This commit is contained in:
@ -67,8 +67,6 @@ object Constants {
|
||||
const val disabled = "disabled"
|
||||
const val enabled = "enabled"
|
||||
|
||||
const val scienceConversionEffect = "Production to science conversion in cities increased by 33%"
|
||||
|
||||
const val ancientEra = "Ancient era"
|
||||
const val classicalEra = "Classical era"
|
||||
const val medievalEra = "Medieval era"
|
||||
|
@ -60,7 +60,7 @@ class WorkerAutomation(val unit: MapUnit) {
|
||||
}
|
||||
|
||||
|
||||
private fun tryConnectingCities(unit: MapUnit):Boolean { // returns whether we actually did anything
|
||||
private fun tryConnectingCities(unit: MapUnit): Boolean { // returns whether we actually did anything
|
||||
//Player can choose not to auto-build roads & railroads.
|
||||
if (unit.civInfo.isPlayerCivilization() && !UncivGame.Current.settings.autoBuildingRoads)
|
||||
return false
|
||||
@ -68,15 +68,17 @@ class WorkerAutomation(val unit: MapUnit) {
|
||||
val targetRoad = unit.civInfo.tech.getBestRoadAvailable()
|
||||
|
||||
val citiesThatNeedConnecting = unit.civInfo.cities.asSequence()
|
||||
.filter { it.population.population>3 && !it.isCapital() && !it.isBeingRazed //City being razed should not be connected.
|
||||
&& !it.cityStats.isConnectedToCapital(targetRoad)
|
||||
// Cities that are too far away make the caReach() calculations devastatingly long
|
||||
&& it.getCenterTile().aerialDistanceTo(unit.getTile()) < 20 }
|
||||
if(citiesThatNeedConnecting.none()) return false // do nothing.
|
||||
.filter {
|
||||
it.population.population > 3 && !it.isCapital() && !it.isBeingRazed //City being razed should not be connected.
|
||||
&& !it.cityStats.isConnectedToCapital(targetRoad)
|
||||
// Cities that are too far away make the caReach() calculations devastatingly long
|
||||
&& it.getCenterTile().aerialDistanceTo(unit.getTile()) < 20
|
||||
}
|
||||
if (citiesThatNeedConnecting.none()) return false // do nothing.
|
||||
|
||||
val citiesThatNeedConnectingBfs = citiesThatNeedConnecting
|
||||
.sortedBy { it.getCenterTile().aerialDistanceTo(unit.civInfo.getCapital().getCenterTile()) }
|
||||
.map { city -> BFS(city.getCenterTile()){it.isLand && unit.movement.canPassThrough(it)} }
|
||||
.map { city -> BFS(city.getCenterTile()) { it.isLand && unit.movement.canPassThrough(it) } }
|
||||
|
||||
val connectedCities = unit.civInfo.cities
|
||||
.filter { it.isCapital() || it.cityStats.isConnectedToCapital(targetRoad) }.map { it.getCenterTile() }
|
||||
@ -84,7 +86,7 @@ class WorkerAutomation(val unit: MapUnit) {
|
||||
// Since further away cities take longer to get to and - most importantly - the canReach() to them is very long,
|
||||
// we order cities by their closeness to the worker first, and then check for each one whether there's a viable path
|
||||
// it can take to an existing connected city.
|
||||
for(bfs in citiesThatNeedConnectingBfs) {
|
||||
for (bfs in citiesThatNeedConnectingBfs) {
|
||||
while (bfs.tilesToCheck.isNotEmpty()) {
|
||||
bfs.nextStep()
|
||||
for (city in connectedCities)
|
||||
@ -124,7 +126,7 @@ class WorkerAutomation(val unit: MapUnit) {
|
||||
(it.civilianUnit == null || it == currentTile)
|
||||
&& tileCanBeImproved(it, unit.civInfo)
|
||||
&& it.getTilesInDistance(2)
|
||||
.none { it.isCityCenter() && it.getCity()!!.civInfo.isAtWarWith(unit.civInfo) }
|
||||
.none { it.isCityCenter() && it.getCity()!!.civInfo.isAtWarWith(unit.civInfo) }
|
||||
}
|
||||
.sortedByDescending { getPriority(it, unit.civInfo) }
|
||||
|
||||
@ -177,7 +179,7 @@ class WorkerAutomation(val unit: MapUnit) {
|
||||
}
|
||||
|
||||
private fun chooseImprovement(tile: TileInfo, civInfo: CivilizationInfo): TileImprovement? {
|
||||
val improvementStringForResource : String ?= when {
|
||||
val improvementStringForResource: String? = when {
|
||||
tile.resource == null || !tile.hasViewableResource(civInfo) -> null
|
||||
tile.terrainFeature == Constants.marsh && !isImprovementOnFeatureAllowed(tile, civInfo) -> "Remove Marsh"
|
||||
tile.terrainFeature == "Fallout" && !isImprovementOnFeatureAllowed(tile, civInfo) -> "Remove Fallout" // for really mad modders
|
||||
@ -188,20 +190,20 @@ class WorkerAutomation(val unit: MapUnit) {
|
||||
|
||||
val tileImprovements = civInfo.gameInfo.ruleSet.tileImprovements
|
||||
val uniqueImprovement = tileImprovements.values
|
||||
.firstOrNull { it.uniqueTo==civInfo.civName}
|
||||
.firstOrNull { it.uniqueTo == civInfo.civName }
|
||||
|
||||
val improvementString = when {
|
||||
tile.improvementInProgress != null -> tile.improvementInProgress
|
||||
improvementStringForResource != null && tileImprovements.containsKey(improvementStringForResource)
|
||||
&& tileImprovements[improvementStringForResource]!!.turnsToBuild!=0 -> improvementStringForResource
|
||||
&& tileImprovements[improvementStringForResource]!!.turnsToBuild != 0 -> improvementStringForResource
|
||||
tile.containsGreatImprovement() -> null
|
||||
tile.containsUnfinishedGreatImprovement() -> null
|
||||
|
||||
// Defence is more important that civilian improvements
|
||||
// While AI sucks in strategical placement of forts, allow a human does it manually
|
||||
!civInfo.isPlayerCivilization() && evaluateFortPlacement(tile,civInfo,false) -> Constants.fort
|
||||
!civInfo.isPlayerCivilization() && evaluateFortPlacement(tile, civInfo, false) -> Constants.fort
|
||||
// I think we can assume that the unique improvement is better
|
||||
uniqueImprovement!=null && tile.canBuildImprovement(uniqueImprovement,civInfo) -> uniqueImprovement.name
|
||||
uniqueImprovement != null && tile.canBuildImprovement(uniqueImprovement, civInfo) -> uniqueImprovement.name
|
||||
|
||||
tile.terrainFeature == "Fallout" -> "Remove Fallout"
|
||||
tile.terrainFeature == Constants.marsh -> "Remove Marsh"
|
||||
@ -209,7 +211,7 @@ class WorkerAutomation(val unit: MapUnit) {
|
||||
tile.terrainFeature == "Oasis" -> null
|
||||
tile.terrainFeature == Constants.forest -> "Lumber mill"
|
||||
tile.isHill() -> "Mine"
|
||||
tile.baseTerrain in listOf(Constants.grassland,Constants.desert,Constants.plains) -> "Farm"
|
||||
tile.baseTerrain in listOf(Constants.grassland, Constants.desert, Constants.plains) -> "Farm"
|
||||
tile.isAdjacentToFreshwater -> "Farm"
|
||||
tile.baseTerrain in listOf(Constants.tundra, Constants.snow) -> Constants.tradingPost
|
||||
else -> null
|
||||
@ -217,6 +219,7 @@ class WorkerAutomation(val unit: MapUnit) {
|
||||
if (improvementString == null) return null
|
||||
return unit.civInfo.gameInfo.ruleSet.tileImprovements[improvementString] // For mods, the tile improvement may not exist, so don't assume.
|
||||
}
|
||||
|
||||
private fun isImprovementOnFeatureAllowed(tile: TileInfo, civInfo: CivilizationInfo): Boolean {
|
||||
// routine assumes the caller ensured that terrainFeature and resource are both present
|
||||
val resourceImprovementName = tile.getTileResource().improvement
|
||||
@ -226,8 +229,7 @@ class WorkerAutomation(val unit: MapUnit) {
|
||||
return resourceImprovement.resourceTerrainAllow.contains(tile.terrainFeature!!)
|
||||
}
|
||||
|
||||
private fun isAcceptableTileForFort(tile: TileInfo, civInfo: CivilizationInfo): Boolean
|
||||
{
|
||||
private fun isAcceptableTileForFort(tile: TileInfo, civInfo: CivilizationInfo): Boolean {
|
||||
if (tile.isCityCenter() // don't build fort in the city
|
||||
|| !tile.isLand // don't build fort in the water
|
||||
|| tile.improvement == Constants.fort // don't build fort if it is already here
|
||||
@ -246,13 +248,14 @@ class WorkerAutomation(val unit: MapUnit) {
|
||||
!isAcceptableTileForFort(tile, civInfo)) return false
|
||||
|
||||
// if this place is not perfect, let's see if there is a better one
|
||||
val nearestTiles = tile.getTilesInDistance(2).filter{it.owningCity?.civInfo == civInfo}.toList()
|
||||
val nearestTiles = tile.getTilesInDistance(2).filter { it.owningCity?.civInfo == civInfo }.toList()
|
||||
for (closeTile in nearestTiles) {
|
||||
// don't build forts too close to the cities
|
||||
if (closeTile.isCityCenter()) return false
|
||||
// don't build forts too close to other forts
|
||||
if (closeTile.improvement == Constants.fort || closeTile.improvement == Constants.citadel
|
||||
|| closeTile.improvementInProgress == Constants.fort) return false
|
||||
if (closeTile.improvement != null
|
||||
&& closeTile.getTileImprovement()!!.uniqueObjects.any { it.placeholderText == "Gives a defensive bonus of []%" }
|
||||
|| closeTile.improvementInProgress != Constants.fort) return false
|
||||
// there is another better tile for the fort
|
||||
if (!tile.isHill() && closeTile.isHill() &&
|
||||
isAcceptableTileForFort(closeTile, civInfo)) return false
|
||||
@ -263,24 +266,25 @@ class WorkerAutomation(val unit: MapUnit) {
|
||||
// no potential enemies
|
||||
if (enemyCivs.isEmpty()) return false
|
||||
|
||||
val threatMapping : (CivilizationInfo) -> Int = {
|
||||
val threatMapping: (CivilizationInfo) -> Int = {
|
||||
// the war is already a good nudge to build forts
|
||||
(if (civInfo.isAtWarWith(it)) 20 else 0) +
|
||||
// let's check also the force of the enemy
|
||||
// let's check also the force of the enemy
|
||||
when (Automation.threatAssessment(civInfo, it)) {
|
||||
ThreatLevel.VeryLow -> 1 // do not build forts
|
||||
ThreatLevel.Low -> 6 // too close, let's build until it is late
|
||||
ThreatLevel.Medium -> 10
|
||||
ThreatLevel.High -> 15 // they are strong, let's built until they reach us
|
||||
ThreatLevel.VeryHigh -> 20
|
||||
} }
|
||||
ThreatLevel.VeryLow -> 1 // do not build forts
|
||||
ThreatLevel.Low -> 6 // too close, let's build until it is late
|
||||
ThreatLevel.Medium -> 10
|
||||
ThreatLevel.High -> 15 // they are strong, let's built until they reach us
|
||||
ThreatLevel.VeryHigh -> 20
|
||||
}
|
||||
}
|
||||
val enemyCivsIsCloseEnough = enemyCivs.filter { NextTurnAutomation.getMinDistanceBetweenCities(civInfo, it) <= threatMapping(it) }
|
||||
// no threat, let's not build fort
|
||||
if (enemyCivsIsCloseEnough.isEmpty()) return false
|
||||
|
||||
// make list of enemy cities as sources of threat
|
||||
val enemyCities = mutableListOf<TileInfo>()
|
||||
enemyCivsIsCloseEnough.forEach { enemyCities.addAll(it.cities.map { city -> city.getCenterTile() } ) }
|
||||
enemyCivsIsCloseEnough.forEach { enemyCities.addAll(it.cities.map { city -> city.getCenterTile() }) }
|
||||
|
||||
// find closest enemy city
|
||||
val closestEnemyCity = enemyCities.minBy { it.aerialDistanceTo(tile) }!!
|
||||
|
@ -36,22 +36,24 @@ class UniqueMap:HashMap<String, ArrayList<Unique>>() {
|
||||
|
||||
// Buildings, techs and policies can have 'triggered' effects
|
||||
object UniqueTriggerActivation {
|
||||
fun triggerCivwideUnique(unique: Unique, civInfo: CivilizationInfo, cityInfo:CityInfo?=null) {
|
||||
val chosenCity = if(cityInfo!=null) cityInfo else civInfo.cities.firstOrNull { it.isCapital() }
|
||||
fun triggerCivwideUnique(unique: Unique, civInfo: CivilizationInfo, cityInfo: CityInfo? = null) {
|
||||
val chosenCity = if (cityInfo != null) cityInfo else civInfo.cities.firstOrNull { it.isCapital() }
|
||||
when (unique.placeholderText) {
|
||||
"Free [] appears" -> {
|
||||
val unitName = unique.params[0]
|
||||
if (chosenCity != null && (unitName != Constants.settler || !civInfo.isOneCityChallenger()))
|
||||
val unit = civInfo.gameInfo.ruleSet.units[unitName]
|
||||
if (chosenCity != null && unit != null && (!unit.uniques.contains("Founds a new city") || !civInfo.isOneCityChallenger()))
|
||||
civInfo.addUnit(unitName, chosenCity)
|
||||
}
|
||||
"[] free [] units appear" -> {
|
||||
val unitName = unique.params[1]
|
||||
if (chosenCity!=null && (unitName != Constants.settler || !civInfo.isOneCityChallenger()))
|
||||
val unit = civInfo.gameInfo.ruleSet.units[unitName]
|
||||
if (chosenCity != null && unit != null && (!unit.uniques.contains("Founds a new city") || !civInfo.isOneCityChallenger()))
|
||||
for (i in 1..unique.params[0].toInt())
|
||||
civInfo.addUnit(unitName, chosenCity)
|
||||
}
|
||||
// spectators get all techs at start of game, and if (in a mod) a tech gives a free policy, the game stucks on the policy picker screen
|
||||
"Free Social Policy" -> if(!civInfo.isSpectator()) civInfo.policies.freePolicies++
|
||||
"Free Social Policy" -> if (!civInfo.isSpectator()) civInfo.policies.freePolicies++
|
||||
"Empire enters golden age" ->
|
||||
civInfo.goldenAges.enterGoldenAge()
|
||||
"Free Great Person" -> {
|
||||
@ -84,9 +86,11 @@ object UniqueTriggerActivation {
|
||||
val promotion = unique.params[1]
|
||||
for (unit in civInfo.getCivUnits())
|
||||
if (unit.matchesFilter(filter)
|
||||
|| (civInfo.gameInfo.ruleSet.unitPromotions.values.any { it.name == promotion
|
||||
&& unit.type.name in it.unitTypes }))
|
||||
unit.promotions.addPromotion(promotion, isFree = true)}
|
||||
|| (civInfo.gameInfo.ruleSet.unitPromotions.values.any {
|
||||
it.name == promotion && unit.type.name in it.unitTypes
|
||||
}))
|
||||
unit.promotions.addPromotion(promotion, isFree = true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -18,11 +18,11 @@ class CityStatsTable(val cityScreen: CityScreen): Table() {
|
||||
|
||||
init {
|
||||
pad(2f)
|
||||
background = ImageGetter.getBackground(colorFromRGB(194,180,131))
|
||||
background = ImageGetter.getBackground(colorFromRGB(194, 180, 131))
|
||||
|
||||
innerTable.pad(5f)
|
||||
innerTable.defaults().pad(2f)
|
||||
innerTable.background = ImageGetter.getBackground(Color.BLACK.cpy().apply { a=0.8f })
|
||||
innerTable.background = ImageGetter.getBackground(Color.BLACK.cpy().apply { a = 0.8f })
|
||||
|
||||
add(innerTable).fill()
|
||||
}
|
||||
@ -31,8 +31,8 @@ class CityStatsTable(val cityScreen: CityScreen): Table() {
|
||||
innerTable.clear()
|
||||
|
||||
val ministatsTable = Table()
|
||||
for(stat in cityInfo.cityStats.currentCityStats.toHashMap()) {
|
||||
if(stat.key == Stat.Happiness || stat.key == Stat.Faith) continue
|
||||
for (stat in cityInfo.cityStats.currentCityStats.toHashMap()) {
|
||||
if (stat.key == Stat.Happiness || stat.key == Stat.Faith) continue
|
||||
ministatsTable.add(ImageGetter.getStatIcon(stat.key.name)).size(20f).padRight(5f)
|
||||
ministatsTable.add(round(stat.value).toInt().toString().toLabel()).padRight(10f)
|
||||
}
|
||||
@ -59,9 +59,9 @@ class CityStatsTable(val cityScreen: CityScreen): Table() {
|
||||
} else {
|
||||
"Stopped expansion".tr()
|
||||
}
|
||||
if (cityInfo.expansion.chooseNewTileToOwn()!=null)
|
||||
if (cityInfo.expansion.chooseNewTileToOwn() != null)
|
||||
turnsToExpansionString += " (" + cityInfo.expansion.cultureStored + "/" +
|
||||
cityInfo.expansion.getCultureToNextTile() + ")"
|
||||
cityInfo.expansion.getCultureToNextTile() + ")"
|
||||
|
||||
var turnsToPopString =
|
||||
when {
|
||||
|
Reference in New Issue
Block a user