civ units are now cached and not calculated every time

This commit is contained in:
Yair Morgenstern 2018-08-17 14:45:48 +03:00
parent 1957c4ca80
commit 06091d640d
6 changed files with 123 additions and 113 deletions

View file

@ -120,7 +120,7 @@ class Battle(val gameInfo:GameInfo=UnCivGame.Current.gameInfo) {
if(enemyCiv.isDefeated()) {
gameInfo.getPlayerCivilization()
.addNotification("The civilization of [${enemyCiv.civName}] has been destroyed!", null, Color.RED)
enemyCiv.getCivUnits().forEach { it.removeFromTile() }
enemyCiv.getCivUnits().forEach { it.destroy() }
}
else if(enemyCiv.cities.isNotEmpty()){
enemyCiv.cities.first().cityConstructions.builtBuildings.add("Palace") // relocate palace
@ -145,7 +145,8 @@ class Battle(val gameInfo:GameInfo=UnCivGame.Current.gameInfo) {
val capturedUnit = (defender as MapUnitCombatant).unit
capturedUnit.civInfo.addNotification("An enemy ["+attacker.getName()+"] has captured our ["+defender.getName()+"]",
defender.getTile().position, Color.RED)
capturedUnit.civInfo = attacker.getCivilization()
capturedUnit.owner = capturedUnit.civInfo.civName
capturedUnit.civInfo.units.remove(capturedUnit)
capturedUnit.assignOwner(attacker.getCivilization())
}
}

View file

@ -14,7 +14,7 @@ class MapUnitCombatant(val unit: MapUnit) : ICombatant {
override fun takeDamage(damage: Int) {
unit.health -= damage
if(isDefeated()) unit.removeFromTile()
if(isDefeated()) unit.destroy()
}
override fun getAttackingStrength(defender: ICombatant): Int { // todo remove defender

View file

@ -23,6 +23,7 @@ import kotlin.math.roundToInt
class CivilizationInfo {
@Transient lateinit var gameInfo: GameInfo
@Transient var units=ArrayList<MapUnit>()
var gold = 0
var happiness = 15
@ -174,7 +175,7 @@ class CivilizationInfo {
fun getBuildingUniques(): List<String> = cities.flatMap { it.cityConstructions.getBuiltBuildings().map { it.unique }.filterNotNull() }.distinct()
fun getCivUnits(): List<MapUnit> {
return gameInfo.tileMap.values.flatMap { it.getUnits() }.filter { it.owner==civName }
return units
}
fun getViewableTiles(): List<TileInfo> {
@ -232,12 +233,11 @@ class CivilizationInfo {
tech.civInfo = this
diplomacy.values.forEach { it.civInfo=this}
for (unit in getCivUnits()) {
unit.civInfo=this
for (unit in gameInfo.tileMap.values.flatMap { it.getUnits() }.filter { it.owner==civName }) {
unit.assignOwner(this)
unit.setTransients()
}
for (cityInfo in cities) {
cityInfo.setTransients()
cityInfo.civInfo = this
@ -255,7 +255,7 @@ class CivilizationInfo {
var civMilitaryUnits = getCivUnits().filter { it.baseUnit().unitType != UnitType.Civilian }
if (civMilitaryUnits.isNotEmpty()) {
val unitToDisband = civMilitaryUnits.first()
unitToDisband.removeFromTile()
unitToDisband.destroy()
civMilitaryUnits -= unitToDisband
addNotification("Cannot provide unit upkeep for " + unitToDisband.name + " - unit has been disbanded!".tr(), null, Color.RED)
}

View file

@ -9,8 +9,9 @@ import com.unciv.models.gamebasics.unit.UnitType
import java.text.DecimalFormat
class MapUnit {
@Transient
lateinit var civInfo: CivilizationInfo
@Transient lateinit var civInfo: CivilizationInfo
@Transient lateinit var baseUnit: BaseUnit
@Transient internal lateinit var currentTile :TileInfo
lateinit var owner: String
lateinit var name: String
@ -20,12 +21,21 @@ class MapUnit {
var attacksThisTurn = 0
var promotions = UnitPromotions()
@Transient lateinit var baseUnit: BaseUnit
//region pure functions
fun clone(): MapUnit {
val toReturn = MapUnit()
toReturn.action=action
toReturn.currentMovement=currentMovement
toReturn.name=name
toReturn.promotions=promotions.clone()
toReturn.health=health
toReturn.attacksThisTurn=attacksThisTurn
toReturn.owner=owner
return toReturn
}
fun baseUnit(): BaseUnit = baseUnit
fun getMovementString(): String = DecimalFormat("0.#").format(currentMovement.toDouble()) + "/" + getMaxMovement()
@Transient
internal lateinit var currentTile :TileInfo
fun getTile(): TileInfo = currentTile
fun getMaxMovement() = baseUnit.movement
@ -34,6 +44,83 @@ class MapUnit {
return movementAlgs().getDistanceToTilesWithinTurn(tile.position,currentMovement)
}
fun getSpecialAbilities(): MutableList<String> {
val abilities = mutableListOf<String>()
val baseUnit = baseUnit()
if(baseUnit.uniques!=null) abilities.addAll(baseUnit.uniques!!)
abilities.addAll(promotions.promotions.map { GameBasics.UnitPromotions[it]!!.effect })
return abilities
}
fun hasUnique(unique:String): Boolean {
return getSpecialAbilities().contains(unique)
}
fun getViewableTiles(): MutableList<TileInfo> {
var visibilityRange = 2
visibilityRange += getSpecialAbilities().count{it=="+1 Visibility Range"}
if(hasUnique("Limited Visibility")) visibilityRange-=1
val tile = getTile()
if (tile.baseTerrain == "Hill") visibilityRange += 1
return tile.getViewableTiles(visibilityRange)
}
fun isFortified(): Boolean {
return action!=null && action!!.startsWith("Fortify")
}
fun getFortificationTurns(): Int {
if(!isFortified()) return 0
return action!!.split(" ")[1].toInt()
}
fun movementAlgs() = UnitMovementAlgorithms(this)
override fun toString(): String {
return "$name - $owner"
}
/**
* Designates whether we can walk to the tile - without attacking
*/
fun canMoveTo(tile: TileInfo): Boolean {
val tileOwner = tile.getOwner()
if(tileOwner!=null && tileOwner.civName!=owner
&& (tile.isCityCenter() || !civInfo.canEnterTiles(tileOwner))) return false
if (baseUnit().unitType== UnitType.Civilian)
return tile.civilianUnit==null && (tile.militaryUnit==null || tile.militaryUnit!!.owner==owner)
else return tile.militaryUnit==null && (tile.civilianUnit==null || tile.civilianUnit!!.owner==owner)
}
fun isIdle(): Boolean {
if (currentMovement == 0f) return false
if (name == "Worker" && getTile().improvementInProgress != null) return false
if (isFortified()) return false
return true
}
fun canAttack(): Boolean {
if(currentMovement==0f) return false
if(attacksThisTurn>0) return false
if(hasUnique("Must set up to ranged attack") && action != "Set Up") return false
return true
}
fun getRange(): Int {
if(baseUnit().unitType.isMelee()) return 1
var range = baseUnit().range
if(hasUnique("+1 Range")) range++
return range
}
//endregion
//region state-changing functions
fun setTransients(){
promotions.unit=this
baseUnit=GameBasics.Units[name]!!
}
fun doPreTurnAction() {
val currentTile = getTile()
if (currentMovement == 0f) return // We've already done stuff this turn, and can't do any more stuff
@ -92,10 +179,6 @@ class MapUnit {
tile.improvementInProgress = null
}
/**
* @return The tile that we reached this turn
*/
private fun heal(){
val tile = getTile()
health += when{
@ -107,6 +190,9 @@ class MapUnit {
if(health>100) health=100
}
/**
* @return The tile that we reached this turn
*/
fun moveToTile(otherTile: TileInfo) {
if(otherTile==getTile()) return // already here!
val distanceToTiles = getDistanceToTiles()
@ -139,40 +225,9 @@ class MapUnit {
doPreTurnAction()
}
fun getSpecialAbilities(): MutableList<String> {
val abilities = mutableListOf<String>()
val baseUnit = baseUnit()
if(baseUnit.uniques!=null) abilities.addAll(baseUnit.uniques!!)
abilities.addAll(promotions.promotions.map { GameBasics.UnitPromotions[it]!!.effect })
return abilities
}
fun hasUnique(unique:String): Boolean {
return getSpecialAbilities().contains(unique)
}
fun movementAlgs() = UnitMovementAlgorithms(this)
override fun toString(): String {
return "$name - $owner"
}
fun getViewableTiles(): MutableList<TileInfo> {
var visibilityRange = 2
visibilityRange += getSpecialAbilities().count{it=="+1 Visibility Range"}
if(hasUnique("Limited Visibility")) visibilityRange-=1
val tile = getTile()
if (tile.baseTerrain == "Hill") visibilityRange += 1
return tile.getViewableTiles(visibilityRange)
}
fun isFortified(): Boolean {
return action!=null && action!!.startsWith("Fortify")
}
fun getFortificationTurns(): Int {
if(!isFortified()) return 0
return action!!.split(" ")[1].toInt()
fun destroy(){
removeFromTile()
civInfo.units.remove(this)
}
fun removeFromTile(){
@ -188,54 +243,10 @@ class MapUnit {
currentTile = tile
}
/**
* Designates whether we can walk to the tile - without attacking
*/
fun canMoveTo(tile: TileInfo): Boolean {
val tileOwner = tile.getOwner()
if(tileOwner!=null && tileOwner.civName!=owner
&& (tile.isCityCenter() || !civInfo.canEnterTiles(tileOwner))) return false
if (baseUnit().unitType== UnitType.Civilian)
return tile.civilianUnit==null && (tile.militaryUnit==null || tile.militaryUnit!!.owner==owner)
else return tile.militaryUnit==null && (tile.civilianUnit==null || tile.civilianUnit!!.owner==owner)
}
fun isIdle(): Boolean {
if (currentMovement == 0f) return false
if (name == "Worker" && getTile().improvementInProgress != null) return false
if (isFortified()) return false
return true
}
fun canAttack(): Boolean {
if(currentMovement==0f) return false
if(attacksThisTurn>0) return false
if(hasUnique("Must set up to ranged attack") && action != "Set Up") return false
return true
}
fun setTransients(){
promotions.unit=this
baseUnit=GameBasics.Units[name]!!
}
fun getRange(): Int {
if(baseUnit().unitType.isMelee()) return 1
var range = baseUnit().range
if(hasUnique("+1 Range")) range++
return range
}
fun clone(): MapUnit {
val toReturn = MapUnit()
toReturn.action=action
toReturn.currentMovement=currentMovement
toReturn.name=name
toReturn.promotions=promotions.clone()
toReturn.health=health
toReturn.attacksThisTurn=attacksThisTurn
toReturn.owner=owner
return toReturn
fun assignOwner(civInfo:CivilizationInfo){
owner=civInfo.civName
this.civInfo=civInfo
civInfo.units.add(this)
}
//endregion
}

View file

@ -41,11 +41,9 @@ class TileMap {
}
fun placeUnitNearTile(position: Vector2, unitName: String, civInfo: CivilizationInfo): MapUnit {
val unit = GameBasics.Units[unitName]!!.getMapUnit()
unit.owner = civInfo.civName
unit.civInfo = civInfo
unit.assignOwner(civInfo)
val tilesInDistance = getTilesInDistance(position, 2)
val unitToPlaceTile = tilesInDistance.firstOrNull { unit.canMoveTo(it) }
if(unitToPlaceTile!=null) unit.putInTile(unitToPlaceTile)

View file

@ -22,7 +22,7 @@ class UnitActions {
private fun constructImprovementAndDestroyUnit(unit:MapUnit, improvementName: String): () -> Unit {
return {
unit.getTile().improvement = improvementName
unit.removeFromTile()
unit.destroy()
}
}
@ -71,7 +71,7 @@ class UnitActions {
{
unit.civInfo.gold -= goldCostOfUpgrade
val unitTile = unit.getTile()
unit.removeFromTile()
unit.destroy()
val newunit = unit.civInfo.placeUnitNearTile(unitTile.position, upgradedUnit.name)
newunit.health = unit.health
newunit.promotions = unit.promotions
@ -95,7 +95,7 @@ class UnitActions {
unit.civInfo.addCity(tile.position)
tile.improvement=null
unitTable.currentlyExecutingAction = null // In case the settler was in the middle of doing something and we then founded a city with it
unit.removeFromTile()
unit.destroy()
},
unit.currentMovement != 0f &&
!tile.getTilesInDistance(2).any { it.isCityCenter() })
@ -126,7 +126,7 @@ class UnitActions {
actionList += UnitAction( "Discover Technology",
{
unit.civInfo.tech.freeTechs += 1
unit.removeFromTile()
unit.destroy()
worldScreen.game.screen = TechPickerScreen(true, unit.civInfo)
},unit.currentMovement != 0f)
@ -139,7 +139,7 @@ class UnitActions {
actionList += UnitAction( "Start Golden Age",
{
unit.civInfo.goldenAges.enterGoldenAge()
unit.removeFromTile()
unit.destroy()
},unit.currentMovement != 0f
)
actionList += UnitAction("Construct Landmark",
@ -151,7 +151,7 @@ class UnitActions {
actionList += UnitAction( "Hurry Wonder",
{
tile.getCity()!!.cityConstructions.addConstruction(300 + 30 * tile.getCity()!!.population.population) //http://civilization.wikia.com/wiki/Great_engineer_(Civ5)
unit.removeFromTile()
unit.destroy()
},
unit.currentMovement != 0f &&
tile.isCityCenter() &&
@ -167,7 +167,7 @@ class UnitActions {
actionList += UnitAction("Conduct Trade Mission",
{
unit.civInfo.gold += 350 // + 50 * era_number - todo!
unit.removeFromTile()
unit.destroy()
},unit.currentMovement != 0f)
actionList += UnitAction( "Construct Customs House",
constructImprovementAndDestroyUnit(unit, "Customs house"),
@ -177,7 +177,7 @@ class UnitActions {
actionList += UnitAction("Disband unit",
{
YesNoPopupTable("Do you really want to disband this unit?".tr(),
{unit.removeFromTile(); worldScreen.update()} )
{unit.destroy(); worldScreen.update()} )
},unit.currentMovement != 0f)
return actionList