Allow auto assign population to specialists.

This commit is contained in:
Duan Tao 2018-12-07 00:39:15 +08:00
parent 7cacff0a37
commit 173a773271
2 changed files with 68 additions and 16 deletions

View File

@ -4,18 +4,36 @@ import com.badlogic.gdx.graphics.Color
import com.unciv.logic.battle.CityCombatant import com.unciv.logic.battle.CityCombatant
import com.unciv.logic.city.CityConstructions import com.unciv.logic.city.CityConstructions
import com.unciv.logic.city.CityInfo import com.unciv.logic.city.CityInfo
import com.unciv.logic.city.CityStats
import com.unciv.logic.civilization.CivilizationInfo import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.logic.map.TileInfo import com.unciv.logic.map.TileInfo
import com.unciv.models.gamebasics.unit.BaseUnit import com.unciv.models.gamebasics.unit.BaseUnit
import com.unciv.models.gamebasics.unit.UnitType import com.unciv.models.gamebasics.unit.UnitType
import com.unciv.models.stats.Stat
import com.unciv.models.stats.Stats
import com.unciv.ui.utils.getRandom import com.unciv.ui.utils.getRandom
import kotlin.math.max import kotlin.math.max
import kotlin.math.sqrt import kotlin.math.sqrt
class Automation { class Automation {
internal fun rankTile(tile: TileInfo, civInfo: CivilizationInfo): Float { internal fun rankTile(tile: TileInfo?, civInfo: CivilizationInfo): Float {
if (tile == null) return 0.0f
val stats = tile.getTileStats(null, civInfo) val stats = tile.getTileStats(null, civInfo)
var rank = rankStatsValue(stats, civInfo)
if (tile.improvement == null) rank += 0.5f // improvement potential!
if (tile.hasViewableResource(civInfo)) rank += 1.0f
return rank
}
internal fun rankSpecialist(stats: Stats?, civInfo: CivilizationInfo): Float {
if (stats == null) return 0.0f
var rank = rankStatsValue(stats, civInfo)
rank += 0.3f //GPP bonus
return rank
}
fun rankStatsValue(stats: Stats, civInfo: CivilizationInfo): Float {
var rank = 0.0f var rank = 0.0f
if (stats.food <= 2) rank += stats.food if (stats.food <= 2) rank += stats.food
else rank += (2 + (stats.food - 2) / 2) // 1 point for each food up to 2, from there on half a point else rank += (2 + (stats.food - 2) / 2) // 1 point for each food up to 2, from there on half a point
@ -26,8 +44,6 @@ class Automation {
rank += stats.production rank += stats.production
rank += stats.science rank += stats.science
rank += stats.culture rank += stats.culture
if (tile.improvement == null) rank += 0.5f // improvement potential!
if (tile.hasViewableResource(civInfo)) rank += 1.0f
return rank return rank
} }

View File

@ -3,6 +3,7 @@ package com.unciv.logic.city
import com.badlogic.gdx.graphics.Color import com.badlogic.gdx.graphics.Color
import com.unciv.logic.automation.Automation import com.unciv.logic.automation.Automation
import com.unciv.logic.map.TileInfo import com.unciv.logic.map.TileInfo
import com.unciv.models.stats.Stat
import com.unciv.models.stats.Stats import com.unciv.models.stats.Stats
import com.unciv.ui.utils.getRandom import com.unciv.ui.utils.getRandom
import kotlin.math.roundToInt import kotlin.math.roundToInt
@ -70,12 +71,34 @@ class PopulationManager {
internal fun autoAssignPopulation() { internal fun autoAssignPopulation() {
if(getFreePopulation()==0) return if(getFreePopulation()==0) return
val toWork: TileInfo? = cityInfo.getTiles()
//evaluate tiles
val bestTile: TileInfo? = cityInfo.getTiles()
.filter { it.arialDistanceTo(cityInfo.getCenterTile()) <= 3 } .filter { it.arialDistanceTo(cityInfo.getCenterTile()) <= 3 }
.filterNot { cityInfo.workedTiles.contains(it.position) || cityInfo.location==it.position} .filterNot { cityInfo.workedTiles.contains(it.position) || cityInfo.location==it.position}
.maxBy { Automation().rankTile(it,cityInfo.civInfo) } .maxBy { Automation().rankTile(it,cityInfo.civInfo) }
if (toWork != null) // This is when we've run out of tiles! val valueBestTile = Automation().rankTile(bestTile, cityInfo.civInfo)
cityInfo.workedTiles.add(toWork.position)
//evaluate specialists
val maxSpecialistsMap = getMaxSpecialists().toHashMap()
val policies = cityInfo.civInfo.policies.adoptedPolicies
val bestJob: Stat? = specialists.toHashMap()
.filter {maxSpecialistsMap.containsKey(it.key) && it.value < maxSpecialistsMap[it.key]!!}
.maxBy { Automation().rankSpecialist(cityInfo.cityStats.getStatsOfSpecialist(it.key, policies), cityInfo.civInfo) }
?.key
var valueBestSpecialist = 0f
if (bestJob != null)
valueBestSpecialist = Automation().rankSpecialist(cityInfo.cityStats.getStatsOfSpecialist(bestJob, policies), cityInfo.civInfo)
//assign population
if (valueBestTile > valueBestSpecialist) {
if (bestTile != null)
cityInfo.workedTiles.add(bestTile.position)
} else {
if (bestJob != null) {
specialists.add(bestJob, 1f)
}
}
} }
fun unassignExtraPopulation() { fun unassignExtraPopulation() {
@ -87,16 +110,29 @@ class PopulationManager {
} }
while (getFreePopulation()<0) { while (getFreePopulation()<0) {
if(getNumberOfSpecialists()>0){ //evaluate tiles
val specialistTypeToUnassign = specialists.toHashMap().filter { it.value>0 }.map { it.key }.getRandom() val worstWorkedTile: TileInfo? = cityInfo.workedTiles
specialists.add(specialistTypeToUnassign,-1f) .asSequence()
} .map { cityInfo.tileMap[it] }
else { .minBy { Automation().rankTile(it, cityInfo.civInfo) }!!
val lowestRankedWorkedTile = cityInfo.workedTiles val valueWorstTile = Automation().rankTile(worstWorkedTile, cityInfo.civInfo)
.asSequence()
.map { cityInfo.tileMap[it] } //evaluate specialists
.minBy { Automation().rankTile(it, cityInfo.civInfo) }!! val policies = cityInfo.civInfo.policies.adoptedPolicies
cityInfo.workedTiles.remove(lowestRankedWorkedTile.position) val worstJob: Stat? = specialists.toHashMap()
.filter { it.value > 0 }
.minBy { Automation().rankSpecialist(cityInfo.cityStats.getStatsOfSpecialist(it.key, policies), cityInfo.civInfo) }
?.key
var valueWorstSpecialist = 0f
if (worstJob != null)
valueWorstSpecialist = Automation().rankSpecialist(cityInfo.cityStats.getStatsOfSpecialist(worstJob, policies), cityInfo.civInfo)
//un-assign population
if ((valueWorstTile < valueWorstSpecialist && worstWorkedTile != null)
|| (getNumberOfSpecialists() == 0)) {
cityInfo.workedTiles.remove(worstWorkedTile!!.position)
} else {
specialists.add(worstJob!!, -1f)
} }
} }