mirror of
https://github.com/yairm210/Unciv.git
synced 2025-07-13 17:28:57 +07:00
Un-hardcoded some settler checks
This commit is contained in:
@ -67,8 +67,6 @@ object Constants {
|
|||||||
const val disabled = "disabled"
|
const val disabled = "disabled"
|
||||||
const val enabled = "enabled"
|
const val enabled = "enabled"
|
||||||
|
|
||||||
const val scienceConversionEffect = "Production to science conversion in cities increased by 33%"
|
|
||||||
|
|
||||||
const val ancientEra = "Ancient era"
|
const val ancientEra = "Ancient era"
|
||||||
const val classicalEra = "Classical era"
|
const val classicalEra = "Classical era"
|
||||||
const val medievalEra = "Medieval 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.
|
//Player can choose not to auto-build roads & railroads.
|
||||||
if (unit.civInfo.isPlayerCivilization() && !UncivGame.Current.settings.autoBuildingRoads)
|
if (unit.civInfo.isPlayerCivilization() && !UncivGame.Current.settings.autoBuildingRoads)
|
||||||
return false
|
return false
|
||||||
@ -68,15 +68,17 @@ class WorkerAutomation(val unit: MapUnit) {
|
|||||||
val targetRoad = unit.civInfo.tech.getBestRoadAvailable()
|
val targetRoad = unit.civInfo.tech.getBestRoadAvailable()
|
||||||
|
|
||||||
val citiesThatNeedConnecting = unit.civInfo.cities.asSequence()
|
val citiesThatNeedConnecting = unit.civInfo.cities.asSequence()
|
||||||
.filter { it.population.population>3 && !it.isCapital() && !it.isBeingRazed //City being razed should not be connected.
|
.filter {
|
||||||
|
it.population.population > 3 && !it.isCapital() && !it.isBeingRazed //City being razed should not be connected.
|
||||||
&& !it.cityStats.isConnectedToCapital(targetRoad)
|
&& !it.cityStats.isConnectedToCapital(targetRoad)
|
||||||
// Cities that are too far away make the caReach() calculations devastatingly long
|
// Cities that are too far away make the caReach() calculations devastatingly long
|
||||||
&& it.getCenterTile().aerialDistanceTo(unit.getTile()) < 20 }
|
&& it.getCenterTile().aerialDistanceTo(unit.getTile()) < 20
|
||||||
if(citiesThatNeedConnecting.none()) return false // do nothing.
|
}
|
||||||
|
if (citiesThatNeedConnecting.none()) return false // do nothing.
|
||||||
|
|
||||||
val citiesThatNeedConnectingBfs = citiesThatNeedConnecting
|
val citiesThatNeedConnectingBfs = citiesThatNeedConnecting
|
||||||
.sortedBy { it.getCenterTile().aerialDistanceTo(unit.civInfo.getCapital().getCenterTile()) }
|
.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
|
val connectedCities = unit.civInfo.cities
|
||||||
.filter { it.isCapital() || it.cityStats.isConnectedToCapital(targetRoad) }.map { it.getCenterTile() }
|
.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,
|
// 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
|
// 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.
|
// it can take to an existing connected city.
|
||||||
for(bfs in citiesThatNeedConnectingBfs) {
|
for (bfs in citiesThatNeedConnectingBfs) {
|
||||||
while (bfs.tilesToCheck.isNotEmpty()) {
|
while (bfs.tilesToCheck.isNotEmpty()) {
|
||||||
bfs.nextStep()
|
bfs.nextStep()
|
||||||
for (city in connectedCities)
|
for (city in connectedCities)
|
||||||
@ -177,7 +179,7 @@ class WorkerAutomation(val unit: MapUnit) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun chooseImprovement(tile: TileInfo, civInfo: CivilizationInfo): TileImprovement? {
|
private fun chooseImprovement(tile: TileInfo, civInfo: CivilizationInfo): TileImprovement? {
|
||||||
val improvementStringForResource : String ?= when {
|
val improvementStringForResource: String? = when {
|
||||||
tile.resource == null || !tile.hasViewableResource(civInfo) -> null
|
tile.resource == null || !tile.hasViewableResource(civInfo) -> null
|
||||||
tile.terrainFeature == Constants.marsh && !isImprovementOnFeatureAllowed(tile, civInfo) -> "Remove Marsh"
|
tile.terrainFeature == Constants.marsh && !isImprovementOnFeatureAllowed(tile, civInfo) -> "Remove Marsh"
|
||||||
tile.terrainFeature == "Fallout" && !isImprovementOnFeatureAllowed(tile, civInfo) -> "Remove Fallout" // for really mad modders
|
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 tileImprovements = civInfo.gameInfo.ruleSet.tileImprovements
|
||||||
val uniqueImprovement = tileImprovements.values
|
val uniqueImprovement = tileImprovements.values
|
||||||
.firstOrNull { it.uniqueTo==civInfo.civName}
|
.firstOrNull { it.uniqueTo == civInfo.civName }
|
||||||
|
|
||||||
val improvementString = when {
|
val improvementString = when {
|
||||||
tile.improvementInProgress != null -> tile.improvementInProgress
|
tile.improvementInProgress != null -> tile.improvementInProgress
|
||||||
improvementStringForResource != null && tileImprovements.containsKey(improvementStringForResource)
|
improvementStringForResource != null && tileImprovements.containsKey(improvementStringForResource)
|
||||||
&& tileImprovements[improvementStringForResource]!!.turnsToBuild!=0 -> improvementStringForResource
|
&& tileImprovements[improvementStringForResource]!!.turnsToBuild != 0 -> improvementStringForResource
|
||||||
tile.containsGreatImprovement() -> null
|
tile.containsGreatImprovement() -> null
|
||||||
tile.containsUnfinishedGreatImprovement() -> null
|
tile.containsUnfinishedGreatImprovement() -> null
|
||||||
|
|
||||||
// Defence is more important that civilian improvements
|
// Defence is more important that civilian improvements
|
||||||
// While AI sucks in strategical placement of forts, allow a human does it manually
|
// 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
|
// 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 == "Fallout" -> "Remove Fallout"
|
||||||
tile.terrainFeature == Constants.marsh -> "Remove Marsh"
|
tile.terrainFeature == Constants.marsh -> "Remove Marsh"
|
||||||
@ -209,7 +211,7 @@ class WorkerAutomation(val unit: MapUnit) {
|
|||||||
tile.terrainFeature == "Oasis" -> null
|
tile.terrainFeature == "Oasis" -> null
|
||||||
tile.terrainFeature == Constants.forest -> "Lumber mill"
|
tile.terrainFeature == Constants.forest -> "Lumber mill"
|
||||||
tile.isHill() -> "Mine"
|
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.isAdjacentToFreshwater -> "Farm"
|
||||||
tile.baseTerrain in listOf(Constants.tundra, Constants.snow) -> Constants.tradingPost
|
tile.baseTerrain in listOf(Constants.tundra, Constants.snow) -> Constants.tradingPost
|
||||||
else -> null
|
else -> null
|
||||||
@ -217,6 +219,7 @@ class WorkerAutomation(val unit: MapUnit) {
|
|||||||
if (improvementString == null) return null
|
if (improvementString == null) return null
|
||||||
return unit.civInfo.gameInfo.ruleSet.tileImprovements[improvementString] // For mods, the tile improvement may not exist, so don't assume.
|
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 {
|
private fun isImprovementOnFeatureAllowed(tile: TileInfo, civInfo: CivilizationInfo): Boolean {
|
||||||
// routine assumes the caller ensured that terrainFeature and resource are both present
|
// routine assumes the caller ensured that terrainFeature and resource are both present
|
||||||
val resourceImprovementName = tile.getTileResource().improvement
|
val resourceImprovementName = tile.getTileResource().improvement
|
||||||
@ -226,8 +229,7 @@ class WorkerAutomation(val unit: MapUnit) {
|
|||||||
return resourceImprovement.resourceTerrainAllow.contains(tile.terrainFeature!!)
|
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
|
if (tile.isCityCenter() // don't build fort in the city
|
||||||
|| !tile.isLand // don't build fort in the water
|
|| !tile.isLand // don't build fort in the water
|
||||||
|| tile.improvement == Constants.fort // don't build fort if it is already here
|
|| 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
|
!isAcceptableTileForFort(tile, civInfo)) return false
|
||||||
|
|
||||||
// if this place is not perfect, let's see if there is a better one
|
// 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) {
|
for (closeTile in nearestTiles) {
|
||||||
// don't build forts too close to the cities
|
// don't build forts too close to the cities
|
||||||
if (closeTile.isCityCenter()) return false
|
if (closeTile.isCityCenter()) return false
|
||||||
// don't build forts too close to other forts
|
// don't build forts too close to other forts
|
||||||
if (closeTile.improvement == Constants.fort || closeTile.improvement == Constants.citadel
|
if (closeTile.improvement != null
|
||||||
|| closeTile.improvementInProgress == Constants.fort) return false
|
&& 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
|
// there is another better tile for the fort
|
||||||
if (!tile.isHill() && closeTile.isHill() &&
|
if (!tile.isHill() && closeTile.isHill() &&
|
||||||
isAcceptableTileForFort(closeTile, civInfo)) return false
|
isAcceptableTileForFort(closeTile, civInfo)) return false
|
||||||
@ -263,7 +266,7 @@ class WorkerAutomation(val unit: MapUnit) {
|
|||||||
// no potential enemies
|
// no potential enemies
|
||||||
if (enemyCivs.isEmpty()) return false
|
if (enemyCivs.isEmpty()) return false
|
||||||
|
|
||||||
val threatMapping : (CivilizationInfo) -> Int = {
|
val threatMapping: (CivilizationInfo) -> Int = {
|
||||||
// the war is already a good nudge to build forts
|
// the war is already a good nudge to build forts
|
||||||
(if (civInfo.isAtWarWith(it)) 20 else 0) +
|
(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
|
||||||
@ -273,14 +276,15 @@ class WorkerAutomation(val unit: MapUnit) {
|
|||||||
ThreatLevel.Medium -> 10
|
ThreatLevel.Medium -> 10
|
||||||
ThreatLevel.High -> 15 // they are strong, let's built until they reach us
|
ThreatLevel.High -> 15 // they are strong, let's built until they reach us
|
||||||
ThreatLevel.VeryHigh -> 20
|
ThreatLevel.VeryHigh -> 20
|
||||||
} }
|
}
|
||||||
|
}
|
||||||
val enemyCivsIsCloseEnough = enemyCivs.filter { NextTurnAutomation.getMinDistanceBetweenCities(civInfo, it) <= threatMapping(it) }
|
val enemyCivsIsCloseEnough = enemyCivs.filter { NextTurnAutomation.getMinDistanceBetweenCities(civInfo, it) <= threatMapping(it) }
|
||||||
// no threat, let's not build fort
|
// no threat, let's not build fort
|
||||||
if (enemyCivsIsCloseEnough.isEmpty()) return false
|
if (enemyCivsIsCloseEnough.isEmpty()) return false
|
||||||
|
|
||||||
// make list of enemy cities as sources of threat
|
// make list of enemy cities as sources of threat
|
||||||
val enemyCities = mutableListOf<TileInfo>()
|
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
|
// find closest enemy city
|
||||||
val closestEnemyCity = enemyCities.minBy { it.aerialDistanceTo(tile) }!!
|
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
|
// Buildings, techs and policies can have 'triggered' effects
|
||||||
object UniqueTriggerActivation {
|
object UniqueTriggerActivation {
|
||||||
fun triggerCivwideUnique(unique: Unique, civInfo: CivilizationInfo, cityInfo:CityInfo?=null) {
|
fun triggerCivwideUnique(unique: Unique, civInfo: CivilizationInfo, cityInfo: CityInfo? = null) {
|
||||||
val chosenCity = if(cityInfo!=null) cityInfo else civInfo.cities.firstOrNull { it.isCapital() }
|
val chosenCity = if (cityInfo != null) cityInfo else civInfo.cities.firstOrNull { it.isCapital() }
|
||||||
when (unique.placeholderText) {
|
when (unique.placeholderText) {
|
||||||
"Free [] appears" -> {
|
"Free [] appears" -> {
|
||||||
val unitName = unique.params[0]
|
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)
|
civInfo.addUnit(unitName, chosenCity)
|
||||||
}
|
}
|
||||||
"[] free [] units appear" -> {
|
"[] free [] units appear" -> {
|
||||||
val unitName = unique.params[1]
|
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())
|
for (i in 1..unique.params[0].toInt())
|
||||||
civInfo.addUnit(unitName, chosenCity)
|
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
|
// 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" ->
|
"Empire enters golden age" ->
|
||||||
civInfo.goldenAges.enterGoldenAge()
|
civInfo.goldenAges.enterGoldenAge()
|
||||||
"Free Great Person" -> {
|
"Free Great Person" -> {
|
||||||
@ -84,9 +86,11 @@ object UniqueTriggerActivation {
|
|||||||
val promotion = unique.params[1]
|
val promotion = unique.params[1]
|
||||||
for (unit in civInfo.getCivUnits())
|
for (unit in civInfo.getCivUnits())
|
||||||
if (unit.matchesFilter(filter)
|
if (unit.matchesFilter(filter)
|
||||||
|| (civInfo.gameInfo.ruleSet.unitPromotions.values.any { it.name == promotion
|
|| (civInfo.gameInfo.ruleSet.unitPromotions.values.any {
|
||||||
&& unit.type.name in it.unitTypes }))
|
it.name == promotion && unit.type.name in it.unitTypes
|
||||||
unit.promotions.addPromotion(promotion, isFree = true)}
|
}))
|
||||||
|
unit.promotions.addPromotion(promotion, isFree = true)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,11 +18,11 @@ class CityStatsTable(val cityScreen: CityScreen): Table() {
|
|||||||
|
|
||||||
init {
|
init {
|
||||||
pad(2f)
|
pad(2f)
|
||||||
background = ImageGetter.getBackground(colorFromRGB(194,180,131))
|
background = ImageGetter.getBackground(colorFromRGB(194, 180, 131))
|
||||||
|
|
||||||
innerTable.pad(5f)
|
innerTable.pad(5f)
|
||||||
innerTable.defaults().pad(2f)
|
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()
|
add(innerTable).fill()
|
||||||
}
|
}
|
||||||
@ -31,8 +31,8 @@ class CityStatsTable(val cityScreen: CityScreen): Table() {
|
|||||||
innerTable.clear()
|
innerTable.clear()
|
||||||
|
|
||||||
val ministatsTable = Table()
|
val ministatsTable = Table()
|
||||||
for(stat in cityInfo.cityStats.currentCityStats.toHashMap()) {
|
for (stat in cityInfo.cityStats.currentCityStats.toHashMap()) {
|
||||||
if(stat.key == Stat.Happiness || stat.key == Stat.Faith) continue
|
if (stat.key == Stat.Happiness || stat.key == Stat.Faith) continue
|
||||||
ministatsTable.add(ImageGetter.getStatIcon(stat.key.name)).size(20f).padRight(5f)
|
ministatsTable.add(ImageGetter.getStatIcon(stat.key.name)).size(20f).padRight(5f)
|
||||||
ministatsTable.add(round(stat.value).toInt().toString().toLabel()).padRight(10f)
|
ministatsTable.add(round(stat.value).toInt().toString().toLabel()).padRight(10f)
|
||||||
}
|
}
|
||||||
@ -59,7 +59,7 @@ class CityStatsTable(val cityScreen: CityScreen): Table() {
|
|||||||
} else {
|
} else {
|
||||||
"Stopped expansion".tr()
|
"Stopped expansion".tr()
|
||||||
}
|
}
|
||||||
if (cityInfo.expansion.chooseNewTileToOwn()!=null)
|
if (cityInfo.expansion.chooseNewTileToOwn() != null)
|
||||||
turnsToExpansionString += " (" + cityInfo.expansion.cultureStored + "/" +
|
turnsToExpansionString += " (" + cityInfo.expansion.cultureStored + "/" +
|
||||||
cityInfo.expansion.getCultureToNextTile() + ")"
|
cityInfo.expansion.getCultureToNextTile() + ")"
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user