mirror of
https://github.com/yairm210/Unciv.git
synced 2025-07-08 23:08:35 +07:00
Worker AI for mods, step 2 (#5998)
* Worker AI for mods, step 2 Support for removing terrain features, both when we need to get rid of them for a resource, and when they plain reduce the yield of a tile Note that the "Remove <improvement>" was implemented WAY before templating and uniques were a thing - the correct solution in these enlightened times would be to separate the improvement *name* from the *effect*, so we could have e.g. a "Deforestation" improvement which would contain botth ["Removes [Jungle]", "Removes [Forest]"] or whatnot. For now I Constant'D the "Remove " so we can at least follow where it's used. * Reverted some of the auto-formatting so the PR is cleaner * Caught 'nullify yields' unique for terrain removal
This commit is contained in:
@ -63,6 +63,7 @@ object Constants {
|
||||
|
||||
const val rising = "Rising"
|
||||
const val lowering = "Lowering"
|
||||
const val remove = "Remove "
|
||||
|
||||
const val minimumMovementEpsilon = 0.05
|
||||
}
|
||||
|
@ -11,7 +11,9 @@ import com.unciv.logic.map.BFS
|
||||
import com.unciv.logic.map.MapUnit
|
||||
import com.unciv.logic.map.RoadStatus
|
||||
import com.unciv.logic.map.TileInfo
|
||||
import com.unciv.models.ruleset.tile.Terrain
|
||||
import com.unciv.models.ruleset.tile.TileImprovement
|
||||
import com.unciv.models.ruleset.unique.UniqueType
|
||||
|
||||
private object WorkerAutomationConst {
|
||||
/** Controls detailed logging of decisions to the console -Turn off for release builds! */
|
||||
@ -329,14 +331,6 @@ class WorkerAutomation(
|
||||
* Determine the improvement appropriate to a given tile and worker
|
||||
*/
|
||||
private fun chooseImprovement(unit: MapUnit, tile: TileInfo): TileImprovement? {
|
||||
val improvementStringForResource: String? = when {
|
||||
tile.resource == null || !tile.hasViewableResource(civInfo) -> null
|
||||
tile.terrainFeatures.contains(Constants.marsh) && !isImprovementOnFeatureAllowed(tile) -> "Remove Marsh"
|
||||
tile.terrainFeatures.contains("Fallout") && !isImprovementOnFeatureAllowed(tile) -> "Remove Fallout" // for really mad modders
|
||||
tile.terrainFeatures.contains(Constants.jungle) && !isImprovementOnFeatureAllowed(tile) -> "Remove Jungle"
|
||||
tile.terrainFeatures.contains(Constants.forest) && !isImprovementOnFeatureAllowed(tile) -> "Remove Forest"
|
||||
else -> tile.tileResource.improvement
|
||||
}
|
||||
|
||||
// turnsToBuild is what defines them as buildable
|
||||
val tileImprovements = ruleSet.tileImprovements.filter {
|
||||
@ -349,6 +343,19 @@ class WorkerAutomation(
|
||||
.filter { it.second > 0f }
|
||||
.maxByOrNull { it.second }?.first
|
||||
|
||||
val lastTerrain = tile.getLastTerrain()
|
||||
|
||||
fun isUnbuildableAndRemovable(terrain: Terrain): Boolean = terrain.unbuildable
|
||||
&& ruleSet.tileImprovements.containsKey(Constants.remove + terrain.name)
|
||||
|
||||
val improvementStringForResource: String? = when {
|
||||
tile.resource == null || !tile.hasViewableResource(civInfo) -> null
|
||||
tile.terrainFeatures.isNotEmpty()
|
||||
&& isUnbuildableAndRemovable(lastTerrain)
|
||||
&& !isResourceImprovementAllowedOnFeature(tile) -> Constants.remove + lastTerrain.name
|
||||
else -> tile.tileResource.improvement
|
||||
}
|
||||
|
||||
val improvementString = when {
|
||||
tile.improvementInProgress != null -> tile.improvementInProgress!!
|
||||
improvementStringForResource != null && tileImprovements.containsKey(improvementStringForResource) -> improvementStringForResource
|
||||
@ -357,14 +364,16 @@ class WorkerAutomation(
|
||||
|
||||
// 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)
|
||||
&& unit.canBuildImprovement(uniqueImprovement, tile) ->
|
||||
uniqueImprovement.name
|
||||
|
||||
tile.terrainFeatures.contains("Fallout") -> "Remove Fallout"
|
||||
tile.terrainFeatures.contains(Constants.marsh) -> "Remove Marsh"
|
||||
lastTerrain.let {
|
||||
isUnbuildableAndRemovable(it) &&
|
||||
(Automation.rankStatsValue(it, civInfo) < 0 || it.hasUnique(UniqueType.NullifyYields) )
|
||||
} -> Constants.remove + lastTerrain.name
|
||||
tile.terrainFeatures.contains(Constants.jungle) -> Constants.tradingPost
|
||||
tile.terrainFeatures.contains("Oasis") -> return null
|
||||
tile.terrainFeatures.contains(Constants.forest) && tileImprovements.containsKey("Lumber mill") -> "Lumber mill"
|
||||
@ -372,10 +381,7 @@ class WorkerAutomation(
|
||||
tile.baseTerrain in listOf(Constants.grassland, Constants.desert, Constants.plains)
|
||||
&& tileImprovements.containsKey("Farm") -> "Farm"
|
||||
tile.isAdjacentToFreshwater && tileImprovements.containsKey("Farm") -> "Farm"
|
||||
tile.baseTerrain in listOf(Constants.tundra, Constants.snow) && tileImprovements.containsKey(Constants.tradingPost)
|
||||
-> Constants.tradingPost
|
||||
|
||||
// This is the ONLY thing that will catch modded non-unique improvements
|
||||
bestBuildableImprovement != null -> bestBuildableImprovement.name
|
||||
else -> return null
|
||||
}
|
||||
@ -387,7 +393,7 @@ class WorkerAutomation(
|
||||
*
|
||||
* Assumes the caller ensured that terrainFeature and resource are both present!
|
||||
*/
|
||||
private fun isImprovementOnFeatureAllowed(tile: TileInfo): Boolean {
|
||||
private fun isResourceImprovementAllowedOnFeature(tile: TileInfo): Boolean {
|
||||
val resourceImprovementName = tile.tileResource.improvement
|
||||
?: return false
|
||||
val resourceImprovement = ruleSet.tileImprovements[resourceImprovementName]
|
||||
|
@ -628,8 +628,8 @@ class MapUnit {
|
||||
UncivGame.Current.settings.addCompletedTutorialTask("Construct an improvement")
|
||||
|
||||
when {
|
||||
tile.improvementInProgress!!.startsWith("Remove ") -> {
|
||||
val removedFeatureName = tile.improvementInProgress!!.removePrefix("Remove ")
|
||||
tile.improvementInProgress!!.startsWith(Constants.remove) -> {
|
||||
val removedFeatureName = tile.improvementInProgress!!.removePrefix(Constants.remove)
|
||||
val tileImprovement = tile.getTileImprovement()
|
||||
if (tileImprovement != null
|
||||
&& tile.terrainFeatures.any {
|
||||
|
@ -487,7 +487,7 @@ open class TileInfo {
|
||||
&& getTileImprovement().let { it != null && it.hasUnique("Irremovable") } -> false
|
||||
|
||||
// Terrain blocks BUILDING improvements - removing things (such as fallout) is fine
|
||||
!improvement.name.startsWith("Remove ") &&
|
||||
!improvement.name.startsWith(Constants.remove) &&
|
||||
getAllTerrains().any { it.getMatchingUniques(UniqueType.RestrictedBuildableImprovements)
|
||||
.any { unique -> !improvement.matchesFilter(unique.params[0]) } } -> false
|
||||
|
||||
|
@ -131,7 +131,7 @@ class MapEditorOptionsTable(val mapEditorScreen: MapEditorScreen): Table(BaseScr
|
||||
}).row()
|
||||
|
||||
for (improvement in ruleset.tileImprovements.values) {
|
||||
if (improvement.name.startsWith("Remove")) continue
|
||||
if (improvement.name.startsWith(Constants.remove)) continue
|
||||
if (improvement.name == Constants.cancelImprovementOrder) continue
|
||||
val improvementImage = getHex(ImageGetter.getImprovementIcon(improvement.name, 40f))
|
||||
improvementImage.onClick {
|
||||
|
@ -84,7 +84,9 @@ class ImprovementPickerScreen(val tileInfo: TileInfo, unit: MapUnit, val onAccep
|
||||
val provideResource = tileInfo.hasViewableResource(currentPlayerCiv) && tileInfo.tileResource.improvement == improvement.name
|
||||
if (provideResource) labelText += "\n" + "Provides [${tileInfo.resource}]".tr()
|
||||
val removeImprovement = (improvement.name != RoadStatus.Road.name
|
||||
&& improvement.name != RoadStatus.Railroad.name && !improvement.name.startsWith("Remove") && improvement.name != Constants.cancelImprovementOrder)
|
||||
&& improvement.name != RoadStatus.Railroad.name
|
||||
&& !improvement.name.startsWith(Constants.remove)
|
||||
&& improvement.name != Constants.cancelImprovementOrder)
|
||||
if (tileInfo.improvement != null && removeImprovement) labelText += "\n" + "Replaces [${tileInfo.improvement}]".tr()
|
||||
|
||||
val pickNow = if (tileInfo.improvementInProgress != improvement.name)
|
||||
|
@ -261,7 +261,7 @@ object ImageGetter {
|
||||
|
||||
|
||||
fun getImprovementIcon(improvementName: String, size: Float = 20f): Actor {
|
||||
if (improvementName.startsWith("Remove") || improvementName == Constants.cancelImprovementOrder)
|
||||
if (improvementName.startsWith(Constants.remove) || improvementName == Constants.cancelImprovementOrder)
|
||||
return Table().apply { add(getImage("OtherIcons/Stop")).size(size) }
|
||||
|
||||
val iconGroup = getImage("ImprovementIcons/$improvementName").surroundWithCircle(size)
|
||||
|
Reference in New Issue
Block a user