City's tiles and worked tiles are now saved in the CityInfo and not in the TileInfo

This commit is contained in:
Yair Morgenstern 2018-04-21 22:56:52 +03:00
parent 17307f16f9
commit 453e25ffe7
26 changed files with 274 additions and 265 deletions

View file

@ -40,7 +40,6 @@
strength:5,
rangedStrength:7,
cost: 40,
requiredTech:"Writing",
hurryCostModifier:20
},
{

View file

@ -28,7 +28,7 @@ class UnCivGame : Game() {
GameSaver.loadGame(this, "Autosave")
gameInfo.getPlayerCivilization().civName="Babylon"
gameInfo.tileMap.values.forEach {
if (it.owner == "Player") it.owner = "Babylon"
//if (it.getOwner() == "Player") it.getOwner() = "Babylon"
if (it.unit != null && it.unit!!.owner == "Player") it.unit!!.owner = "Babylon"
}
} catch (ex: Exception) { // silent fail if we can't read the autosave

View file

@ -0,0 +1,172 @@
package com.unciv.logic
import com.unciv.UnCivGame
import com.unciv.logic.battle.Battle
import com.unciv.logic.battle.MapUnitCombatant
import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.logic.map.MapUnit
import com.unciv.logic.map.TileInfo
import com.unciv.logic.map.UnitType
import com.unciv.models.gamebasics.GameBasics
import com.unciv.models.gamebasics.TileImprovement
import com.unciv.ui.utils.getRandom
import com.unciv.ui.worldscreen.unit.UnitActions
class Automation{
private fun findTileToWork(currentTile: TileInfo, civInfo: CivilizationInfo): TileInfo {
val selectedTile = currentTile.tileMap.getTilesInDistance(currentTile.position, 4)
.filter { (it.unit==null || it==currentTile )
&& it.improvement==null
&& it.canBuildImprovement(chooseImprovement(it),civInfo) }
.maxBy { getPriority(it,civInfo) }
if(selectedTile!=null && getPriority(selectedTile,civInfo) > 1) return selectedTile
else return currentTile
}
private fun getPriority(tileInfo: TileInfo, civInfo: CivilizationInfo): Int {
var priority = 0
if (tileInfo.isWorked()) priority += 3
if (tileInfo.getOwner() == civInfo) priority += 2
if (tileInfo.hasViewableResource(civInfo)) priority += 1
else if (tileInfo.neighbors.any { it.getOwner() != null }) priority += 1
return priority
}
private fun chooseImprovement(tile: TileInfo): TileImprovement {
return GameBasics.TileImprovements[chooseImprovementString(tile)]!!
}
private fun chooseImprovementString(tile: TileInfo): String? {
when {
tile.improvementInProgress != null -> return tile.improvementInProgress
tile.terrainFeature == "Forest" -> return "Lumber mill"
tile.terrainFeature == "Jungle" -> return "Trading post"
tile.terrainFeature == "Marsh" -> return "Remove Marsh"
tile.resource != null -> return tile.tileResource.improvement
tile.baseTerrain == "Hill" -> return "Mine"
tile.baseTerrain == "Grassland" || tile.baseTerrain == "Desert" || tile.baseTerrain == "Plains" -> return "Farm"
tile.baseTerrain == "Tundra" -> return "Trading post"
else -> return null
}
}
fun automateWorkerAction(unit: MapUnit) {
var tile = unit.getTile()
val tileToWork = findTileToWork(tile,unit.civInfo)
if (tileToWork != tile) {
tile = unit.headTowards(tileToWork.position)
unit.doPreTurnAction(tile)
return
}
if (tile.improvementInProgress == null) {
val improvement = chooseImprovement(tile)
if (tile.canBuildImprovement(improvement, unit.civInfo))
// What if we're stuck on this tile but can't build there?
tile.startWorkingOnImprovement(improvement, unit.civInfo)
}
}
fun automateCivMoves(civInfo: CivilizationInfo) {
if(civInfo.tech.techsToResearch.isEmpty()) {
val researchableTechs = GameBasics.Technologies.values.filter { civInfo.tech.canBeResearched(it.name) }
val techToResearch = researchableTechs.minBy { it.cost }
civInfo.tech.techsResearched.add(techToResearch!!.name)
}
for(unit in civInfo.getCivUnits()){
if(unit.name=="Settler") {
UnitActions().getUnitActions(unit, UnCivGame.Current.worldScreen!!).first { it.name == "Found city" }.action()
continue
}
if(unit.name=="Worker") {
Automation().automateWorkerAction(unit)
continue
}
fun healUnit(){
// If we're low on health then heal
// todo: go to a more defensible place if there is one
val tilesInDistance = unit.getDistanceToTiles().keys
val unitTile=unit.getTile()
// Go to friendly tile if within distance - better healing!
val friendlyTile = tilesInDistance.firstOrNull { it.getOwner()?.civName ==unit.owner && it.unit==null }
if(unitTile.getOwner()?.civName !=unit.owner && friendlyTile!=null){
unit.moveToTile(friendlyTile)
return
}
// Or at least get out of enemy territory yaknow
val neutralTile = tilesInDistance.firstOrNull { it.getOwner() ==null && it.unit==null }
if(unitTile.getOwner()?.civName !=unit.owner && unitTile.getOwner() !=null && neutralTile!=null){
unit.moveToTile(neutralTile)
return
}
}
if(unit.health < 50) {
healUnit()
continue
} // do nothing but heal
// if there is an attackable unit in the vicinity, attack!
val attackableTiles = civInfo.getViewableTiles()
.filter { it.unit != null && it.unit!!.owner != civInfo.civName && !it.isCityCenter }.toHashSet()
val distanceToTiles = unit.getDistanceToTiles()
val unitTileToAttack = distanceToTiles.keys.firstOrNull{ attackableTiles.contains(it)}
if(unitTileToAttack!=null){
val unitToAttack =unitTileToAttack.unit!!
if(unitToAttack.getBaseUnit().unitType == UnitType.Civilian){ // kill
unitToAttack.civInfo.addNotification("Our "+unitToAttack.name+" was destroyed by an enemy "+unit.name+"!", unitTileToAttack.position)
unitTileToAttack.unit=null
unit.headTowards(unitTileToAttack.position)
continue
}
val damageToAttacker = Battle(civInfo.gameInfo).calculateDamageToAttacker(MapUnitCombatant(unit), MapUnitCombatant(unitToAttack))
if(damageToAttacker < unit.health) { // don't attack if we'll die from the attack
unit.headTowards(unitTileToAttack.position)
Battle(civInfo.gameInfo).attack(MapUnitCombatant(unit), MapUnitCombatant(unitToAttack))
continue
}
}
if(unit.health < 80){
healUnit()
continue
} // do nothing but heal until 80 health
// else, if there is a reachable spot from which we can attack this turn
// (say we're an archer and there's a unit 3 tiles away), go there and attack
// todo
// else, find the closest enemy unit that we know of within 5 spaces and advance towards it
val closestUnit = civInfo.gameInfo.tileMap.getTilesInDistance(unit.getTile().position, 5)
.firstOrNull{ attackableTiles.contains(it) }
if(closestUnit!=null){
unit.headTowards(closestUnit.position)
continue
}
if(unit.health < 100){
healUnit()
continue
}
// else, go to a random space
unit.moveToTile(distanceToTiles.keys.filter { it.unit==null }.toList().getRandom())
}
}
}

View file

@ -1,15 +1,9 @@
package com.unciv.logic
import com.unciv.UnCivGame
import com.unciv.logic.battle.Battle
import com.unciv.logic.battle.MapUnitCombatant
import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.logic.civilization.Notification
import com.unciv.logic.map.TileMap
import com.unciv.logic.map.UnitType
import com.unciv.models.gamebasics.GameBasics
import com.unciv.ui.utils.getRandom
import com.unciv.ui.worldscreen.unit.UnitActions
class GameInfo {
@ -36,7 +30,7 @@ class GameInfo {
for (civInfo in civilizations){
if(!civInfo.isPlayerCivilization())
automateMoves(civInfo)
Automation().automateCivMoves(civInfo)
for (city in civInfo.cities)
city.cityStats.update()
civInfo.happiness = civInfo.getHappinessForNextTurn()
@ -74,105 +68,6 @@ class GameInfo {
}
private fun automateMoves(civInfo: CivilizationInfo) {
if(civInfo.tech.techsToResearch.isEmpty()) {
val researchableTechs = GameBasics.Technologies.values.filter { civInfo.tech.canBeResearched(it.name) }
val techToResearch = researchableTechs.minBy { it.cost }
civInfo.tech.techsResearched.add(techToResearch!!.name)
}
for(unit in civInfo.getCivUnits()){
if(unit.name=="Settler") {
UnitActions().getUnitActions(unit, UnCivGame.Current.worldScreen!!).first { it.name == "Found city" }.action()
continue
}
if(unit.name=="Worker") {
unit.doAutomatedAction()
continue
}
fun healUnit(){
// If we're low on health then heal
// todo: go to a more defensible place if there is one
val tilesInDistance = unit.getDistanceToTiles().keys
val unitTile=unit.getTile()
// Go to friendly tile if within distance - better healing!
val friendlyTile = tilesInDistance.firstOrNull { it.owner==unit.owner && it.unit==null }
if(unitTile.owner!=unit.owner && friendlyTile!=null){
unit.moveToTile(friendlyTile)
return
}
// Or at least get out of enemy territory yaknow
val neutralTile = tilesInDistance.firstOrNull { it.owner==null && it.unit==null }
if(unitTile.owner!=unit.owner && unitTile.owner!=null && neutralTile!=null){
unit.moveToTile(neutralTile)
return
}
}
if(unit.health < 50) {
healUnit()
continue
} // do nothing but heal
// if there is an attackable unit in the vicinity, attack!
val attackableTiles = civInfo.getViewableTiles()
.filter { it.unit != null && it.unit!!.owner != civInfo.civName && !it.isCityCenter }.toHashSet()
val distanceToTiles = unit.getDistanceToTiles()
val unitTileToAttack = distanceToTiles.keys.firstOrNull{ attackableTiles.contains(it)}
if(unitTileToAttack!=null){
val unitToAttack =unitTileToAttack.unit!!
if(unitToAttack.getBaseUnit().unitType == UnitType.Civilian){ // kill
if(unitToAttack.civInfo == getPlayerCivilization())
getPlayerCivilization().addNotification("Our "+unitToAttack.name+" was destroyed by an enemy "+unit.name+"!", unitTileToAttack.position)
unitTileToAttack.unit=null
unit.headTowards(unitTileToAttack.position)
continue
}
val damageToAttacker = Battle(this).calculateDamageToAttacker(MapUnitCombatant(unit), MapUnitCombatant(unitToAttack))
if(damageToAttacker < unit.health) { // don't attack if we'll die from the attack
unit.headTowards(unitTileToAttack.position)
Battle(this).attack(MapUnitCombatant(unit), MapUnitCombatant(unitToAttack))
continue
}
}
if(unit.health < 80){
healUnit()
continue
} // do nothing but heal until 80 health
// else, if there is a reachable spot from which we can attack this turn
// (say we're an archer and there's a unit 3 tiles away), go there and attack
// todo
// else, find the closest enemy unit that we know of within 5 spaces and advance towards it
val closestUnit = tileMap.getTilesInDistance(unit.getTile().position, 5)
.firstOrNull{ attackableTiles.contains(it) }
if(closestUnit!=null){
unit.headTowards(closestUnit.position)
continue
}
if(unit.health < 100){
healUnit()
continue
}
// else, go to a random space
unit.moveToTile(distanceToTiles.keys.filter { it.unit==null }.toList().getRandom())
}
}
}

View file

@ -108,33 +108,34 @@ class Battle(val gameInfo:GameInfo) {
gameInfo.getPlayerCivilization().addNotification(notificationString, attackedTile.position)
}
if (defender.isDefeated() && attacker.getCombatantType() == CombatantType.Melee)
(attacker as MapUnitCombatant).unit.moveToTile(attackedTile)
if(defender.isDefeated()
&& defender.getCombatantType() == CombatantType.City
&& attacker.getCombatantType() == CombatantType.Melee){
conquerCity((defender as CityCombatant).city, attacker)
}
if (defender.isDefeated() && attacker.getCombatantType() == CombatantType.Melee)
(attacker as MapUnitCombatant).unit.moveToTile(attackedTile)
if(attacker is MapUnitCombatant) attacker.unit.currentMovement = 0f
}
private fun conquerCity(city: CityInfo, attacker: ICombatant) {
val enemyCiv = city.civInfo
attacker.getCivilization().addNotification("We have conquered the city of ${city.name}!",city.cityLocation)
attacker.getCivilization().addNotification("We have conquered the city of ${city.name}!",city.location)
enemyCiv.cities.remove(city)
attacker.getCivilization().cities.add(city)
city.civInfo = attacker.getCivilization()
city.health = city.getMaxHealth() / 2 // I think that cities recover to half health?
city.getTile().unit = null
city.getCenterTile().unit = null
city.expansion.cultureStored = 0;
city.expansion.reset()
if(city.cityConstructions.isBuilt("Palace")){
city.cityConstructions.builtBuildings.remove("Palace")
if(enemyCiv.cities.isEmpty()) {
gameInfo.getPlayerCivilization()
.addNotification("The ${enemyCiv.civName} civilization has been destroyed!", null)
.addNotification("The civilization of ${enemyCiv.civName} has been destroyed!", null)
}
else{
enemyCiv.cities.first().cityConstructions.builtBuildings.add("Palace") // relocate palace

View file

@ -8,7 +8,7 @@ import com.unciv.models.gamebasics.GameBasics
class CityCombatant(val city: CityInfo) : ICombatant {
override fun getHealth(): Int = city.health
override fun getCivilization(): CivilizationInfo = city.civInfo
override fun getTile(): TileInfo = city.getTile()
override fun getTile(): TileInfo = city.getCenterTile()
override fun getName(): String = city.name
override fun isDefeated(): Boolean = city.health==1

View file

@ -86,7 +86,7 @@ class CityConstructions {
currentConstruction = "lie"
if (!construction.isBuildable(this)) {
// We can't build this building anymore! (Wonder has been built / resource is gone / etc.)
cityInfo.civInfo.addNotification("Cannot continue work on $saveCurrentConstruction", cityInfo.cityLocation)
cityInfo.civInfo.addNotification("Cannot continue work on $saveCurrentConstruction", cityInfo.location)
chooseNextConstruction()
construction = getConstruction(currentConstruction)
} else
@ -97,7 +97,7 @@ class CityConstructions {
if (inProgressConstructions[currentConstruction]!! >= productionCost) {
construction.postBuildEvent(this)
inProgressConstructions.remove(currentConstruction)
cityInfo.civInfo.addNotification(currentConstruction + " has been built in " + cityInfo.name, cityInfo.cityLocation)
cityInfo.civInfo.addNotification(currentConstruction + " has been built in " + cityInfo.name, cityInfo.location)
chooseNextConstruction()
}
@ -118,7 +118,7 @@ class CityConstructions {
}
}
if(cityInfo.civInfo == cityInfo.civInfo.gameInfo.getPlayerCivilization())
cityInfo.civInfo.addNotification("Work has started on $currentConstruction", cityInfo.cityLocation)
cityInfo.civInfo.addNotification("Work has started on $currentConstruction", cityInfo.location)
}
private fun workDone(constructionName: String): Int {

View file

@ -1,17 +1,14 @@
package com.unciv.logic.city
import com.badlogic.gdx.math.Vector2
class CityExpansionManager {
@Transient
lateinit var cityInfo: CityInfo
var cityTiles = ArrayList<Vector2>()
var cultureStored: Int = 0
fun reset(){
cityTiles = ArrayList(cityInfo.civInfo.gameInfo.tileMap
.getTilesInDistance(cityInfo.cityLocation, 1).map { it.position })
cityInfo.tiles = ArrayList(cityInfo.civInfo.gameInfo.tileMap
.getTilesInDistance(cityInfo.location, 1).map { it.position })
}
// This one has conflicting sources -
@ -21,7 +18,7 @@ class CityExpansionManager {
// The second seems to be more based, so I'll go with that
//Speciality of Angkor Wat
fun getCultureToNextTile(): Int {
val numTilesClaimed = cityTiles.size - 7
val numTilesClaimed = cityInfo.tiles.size - 7
var cultureToNextTile = 6 * Math.pow(numTilesClaimed + 1.4813, 1.3)
if (cityInfo.civInfo.buildingUniques.contains("NewTileCostReduction")) cultureToNextTile *= 0.75
if (cityInfo.civInfo.policies.isAdopted("Tradition")) cultureToNextTile *= 0.75
@ -32,11 +29,10 @@ class CityExpansionManager {
cultureStored -= getCultureToNextTile()
for (i in 2..3) {
val tiles = cityInfo.civInfo.gameInfo.tileMap.getTilesInDistance(cityInfo.cityLocation, i).filter { it.owner == null }
val tiles = cityInfo.civInfo.gameInfo.tileMap.getTilesInDistance(cityInfo.location, i).filter { it.getOwner() == null }
if (tiles.isEmpty()) continue
val chosenTile = tiles.maxBy { cityInfo.rankTile(it) }
cityTiles.add(chosenTile!!.position)
chosenTile.owner = cityInfo.civInfo.civName
cityInfo.tiles.add(chosenTile!!.position)
return
}
}
@ -45,7 +41,7 @@ class CityExpansionManager {
cultureStored += culture.toInt()
if (cultureStored >= getCultureToNextTile()) {
addNewTileWithCulture()
cityInfo.civInfo.addNotification(cityInfo.name + " has expanded its borders!", cityInfo.cityLocation)
cityInfo.civInfo.addNotification(cityInfo.name + " has expanded its borders!", cityInfo.location)
}
}

View file

@ -14,7 +14,7 @@ import kotlin.math.min
class CityInfo {
@Transient
lateinit var civInfo: CivilizationInfo
var cityLocation: Vector2 = Vector2.Zero
var location: Vector2 = Vector2.Zero
var name: String = ""
var health = 200
@ -23,14 +23,17 @@ class CityInfo {
var expansion = CityExpansionManager()
var cityStats = CityStats()
var tiles = ArrayList<Vector2>()
var workedTiles = ArrayList<Vector2>()
internal val tileMap: TileMap
get() = civInfo.gameInfo.tileMap
fun getTile(): TileInfo = tileMap[cityLocation]
fun getCenterTile(): TileInfo = tileMap[location]
fun getTiles(): List<TileInfo> = tiles.map { tileMap[it] }
fun getTilesInRange(): List<TileInfo> = tileMap.getTilesInDistance(cityLocation, 3).filter { civInfo.civName == it.owner }
fun getTilesInRange(): List<TileInfo> = tileMap.getTilesInDistance(location, 3).filter { civInfo == it.getOwner() }
// Remove resources required by buildings
@ -79,7 +82,7 @@ class CityInfo {
setTransients()
name = civInfo.getCivilization().cities[civInfo.cities.size]
this.cityLocation = cityLocation
this.location = cityLocation
civInfo.cities.add(this)
if(civInfo == civInfo.gameInfo.getPlayerCivilization())
civInfo.addNotification("$name has been founded!", cityLocation)
@ -92,8 +95,7 @@ class CityInfo {
expansion.reset()
val tile = getTile()
tile.workingCity = this.name
val tile = getCenterTile()
tile.roadStatus = RoadStatus.Railroad
if (listOf("Forest", "Jungle", "Marsh").contains(tile.terrainFeature))
tile.terrainFeature = null

View file

@ -17,7 +17,7 @@ class CityStats {
private fun getStatsFromTiles(): Stats {
val stats = Stats()
for (cell in cityInfo.getTilesInRange().filter { cityInfo.name == it.workingCity })
for (cell in cityInfo.getTilesInRange().filter { cityInfo.workedTiles.contains(it.position) || cityInfo.location==it.position})
stats.add(cell.getTileStats(cityInfo, cityInfo.civInfo))
return stats
}
@ -234,9 +234,9 @@ class CityStats {
private fun isConnectedToCapital(roadType: RoadStatus): Boolean {
if(cityInfo.civInfo.cities.count()<2) return false// first city!
val capitalTile = cityInfo.civInfo.capital.getTile()
val capitalTile = cityInfo.civInfo.capital.getCenterTile()
val tilesReached = HashSet<TileInfo>()
var tilesToCheck : List<TileInfo> = listOf(cityInfo.getTile())
var tilesToCheck : List<TileInfo> = listOf(cityInfo.getCenterTile())
while (tilesToCheck.isNotEmpty()) {
val newTiles = tilesToCheck
.flatMap { cityInfo.tileMap.getTilesInDistance(it.position, 1) }.distinct()

View file

@ -6,11 +6,11 @@ import com.unciv.models.stats.Stats
class PopulationManager {
@Transient
@JvmField var cityInfo: CityInfo? = null
@JvmField var population = 1
@JvmField var foodStored = 0
lateinit var cityInfo: CityInfo
var population = 1
var foodStored = 0
@JvmField var buildingsSpecialists = HashMap<String, Stats>()
var buildingsSpecialists = HashMap<String, Stats>()
fun getSpecialists(): Stats {
val allSpecialists = Stats()
@ -27,7 +27,7 @@ class PopulationManager {
// 1 is the city center
fun getFreePopulation(): Int {
val workingPopulation = cityInfo!!.getTilesInRange().count { cityInfo!!.name == it.workingCity } - 1
val workingPopulation = cityInfo.workedTiles.size
return population - workingPopulation - getNumberOfSpecialists()
}
@ -45,23 +45,25 @@ class PopulationManager {
{
population--
foodStored = 0
cityInfo!!.civInfo.addNotification(cityInfo!!.name + " is starving!", cityInfo!!.cityLocation)
cityInfo.civInfo.addNotification(cityInfo.name + " is starving!", cityInfo.location)
}
if (foodStored >= getFoodToNextPopulation())
// growth!
{
foodStored -= getFoodToNextPopulation()
if (cityInfo!!.buildingUniques.contains("FoodCarriesOver")) foodStored += (0.4f * getFoodToNextPopulation()).toInt() // Aqueduct special
if (cityInfo.buildingUniques.contains("FoodCarriesOver")) foodStored += (0.4f * getFoodToNextPopulation()).toInt() // Aqueduct special
population++
autoAssignWorker()
cityInfo!!.civInfo.addNotification(cityInfo!!.name + " has grown!", cityInfo!!.cityLocation)
cityInfo.civInfo.addNotification(cityInfo.name + " has grown!", cityInfo.location)
}
}
internal fun autoAssignWorker() {
val toWork: TileInfo? = cityInfo!!.getTilesInRange().filter { it.workingCity==null }.maxBy { cityInfo!!.rankTile(it) }
val toWork: TileInfo? = cityInfo.getTiles()
.filterNot { cityInfo.workedTiles.contains(it.position) || cityInfo.location==it.position}
.maxBy { cityInfo.rankTile(it) }
if (toWork != null) // This is when we've run out of tiles!
toWork.workingCity = cityInfo!!.name
cityInfo.workedTiles.add(toWork.position)
}
}

View file

@ -154,8 +154,8 @@ class CivilizationInfo {
fun addGreatPerson(greatPerson: String) {
val randomCity = cities.getRandom()
placeUnitNearTile(cities.getRandom().cityLocation, greatPerson)
addNotification("A $greatPerson has been born!", randomCity.cityLocation)
placeUnitNearTile(cities.getRandom().location, greatPerson)
addNotification("A $greatPerson has been born!", randomCity.location)
}
fun placeUnitNearTile(location: Vector2, unitName: String) {
@ -168,9 +168,10 @@ class CivilizationInfo {
fun getViewableTiles(): List<TileInfo> {
var viewablePositions = emptyList<TileInfo>()
viewablePositions += gameInfo.tileMap.values.filter { it.owner == civName }
.flatMap { it.neighbors } // tiles adjacent to city tiles
viewablePositions += gameInfo.tileMap.values.filter { it.unit != null && it.unit!!.owner == civName }
viewablePositions += cities.flatMap { it.getTiles() }
.flatMap { it.neighbors } // tiles adjacent to city tiles
viewablePositions += gameInfo.tileMap.values
.filter { it.unit != null && it.unit!!.owner == civName }
.flatMap { it.getViewableTiles(2)} // Tiles within 2 tiles of units
return viewablePositions
}

View file

@ -46,8 +46,8 @@ class PolicyManager {
}
when(policy.name ) {
"Collective Rule" -> civInfo.placeUnitNearTile(civInfo.capital.cityLocation, "Settler")
"Citizenship" -> civInfo.placeUnitNearTile(civInfo.capital.cityLocation, "Worker")
"Collective Rule" -> civInfo.placeUnitNearTile(civInfo.capital.location, "Settler")
"Citizenship" -> civInfo.placeUnitNearTile(civInfo.capital.location, "Worker")
"Representation", "Reformation" -> civInfo.goldenAges.enterGoldenAge()
"Scientific Revolution" -> civInfo.tech.freeTechs += 2
"Legalism" ->

View file

@ -59,13 +59,13 @@ class TechManager {
if (revealedResource == null) return
for (tileInfo in civInfo.gameInfo.tileMap.values
.filter { it.resource == revealedResource.name && civInfo.civName == it.owner }) {
.filter { it.resource == revealedResource.name && civInfo == it.getOwner() }) {
val closestCityTile = civInfo.gameInfo.tileMap.getTilesInDistance(tileInfo.position, 4)
.firstOrNull { it.isCityCenter }
if (closestCityTile != null) {
civInfo.addNotification(
revealedResource.name + " revealed near " + closestCityTile.city!!.name, tileInfo.position)
revealedResource.name + " revealed near " + closestCityTile.getCity()!!.name, tileInfo.position)
break
}
}

View file

@ -1,11 +1,10 @@
package com.unciv.logic.map
import com.badlogic.gdx.math.Vector2
import com.unciv.logic.Automation
import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.models.gamebasics.GameBasics
import com.unciv.models.gamebasics.TileImprovement
import com.unciv.models.gamebasics.Unit
import java.text.DecimalFormat
enum class UnitType{
@ -51,7 +50,7 @@ class MapUnit {
return
}
if ("automation" == action) doAutomatedAction()
if (action == "automation") Automation().automateWorkerAction(this)
}
private fun doPostTurnAction(tile: TileInfo) {
@ -70,59 +69,6 @@ class MapUnit {
tile.improvementInProgress = null
}
private fun getPriority(tileInfo: TileInfo): Int {
var priority = 0
if (tileInfo.workingCity != null) priority += 3
if (tileInfo.owner == owner) priority += 2
if (tileInfo.hasViewableResource(civInfo)) priority += 1
else if (tileInfo.neighbors.any { it.owner != null }) priority += 1
return priority
}
private fun findTileToWork(currentTile: TileInfo): TileInfo {
val selectedTile = civInfo.gameInfo.tileMap.getTilesInDistance(currentTile.position, 4)
.filter { (it.unit==null || it==currentTile )
&& it.improvement==null
&& it.canBuildImprovement(chooseImprovement(it),civInfo) }
.maxBy { getPriority(it) }
if(selectedTile!=null && getPriority(selectedTile) > 1) return selectedTile
else return currentTile
}
fun doAutomatedAction() {
var tile = getTile()
val tileToWork = findTileToWork(tile)
if (tileToWork != tile) {
tile = headTowards(tileToWork.position)
doPreTurnAction(tile)
return
}
if (tile.improvementInProgress == null) {
val improvement = chooseImprovement(tile)
if (tile.canBuildImprovement(improvement, civInfo))
// What if we're stuck on this tile but can't build there?
tile.startWorkingOnImprovement(improvement, civInfo)
}
}
private fun chooseImprovement(tile: TileInfo): TileImprovement {
return GameBasics.TileImprovements[chooseImprovementString(tile)]!!
}
private fun chooseImprovementString(tile: TileInfo): String? {
when {
tile.improvementInProgress != null -> return tile.improvementInProgress
tile.terrainFeature == "Forest" -> return "Lumber mill"
tile.terrainFeature == "Jungle" -> return "Trading post"
tile.terrainFeature == "Marsh" -> return "Remove Marsh"
tile.resource != null -> return tile.tileResource.improvement
tile.baseTerrain == "Hill" -> return "Mine"
tile.baseTerrain == "Grassland" || tile.baseTerrain == "Desert" || tile.baseTerrain == "Plains" -> return "Farm"
tile.baseTerrain == "Tundra" -> return "Trading post"
else -> return null
}
}
/**
* @param origin
@ -168,8 +114,8 @@ class MapUnit {
val tile = getTile()
health += when{
tile.isCityCenter -> 20
tile.owner == owner -> 15 // home territory
tile.owner == null -> 10 // no man's land (neutral)
tile.getOwner()?.civName == owner -> 15 // home territory
tile.getOwner() == null -> 10 // no man's land (neutral)
else -> 5 // enemy territory
}
if(health>100) health=100

View file

@ -20,19 +20,12 @@ class TileInfo {
var resource: String? = null
var improvement: String? = null
var improvementInProgress: String? = null
var owner: String? = null // owning civ name
get() {
val containingCity = tileMap.gameInfo.civilizations.flatMap { it.cities }.firstOrNull{it.expansion.cityTiles.contains(position)}
if(containingCity==null) return null
return containingCity.civInfo.civName
}
var workingCity: String? = null // Working City name
var roadStatus = RoadStatus.None
var explored = false
var turnsToImprovement: Int = 0
val city: CityInfo?
get() = if (workingCity == null) null else getOwner()!!.cities.first { it.name == workingCity }
fun getCity(): CityInfo? = tileMap.gameInfo.civilizations.flatMap { it.cities }.firstOrNull{it.tiles.contains(position)}
val lastTerrain: Terrain
get() = if (terrainFeature == null) getBaseTerrain() else getTerrainFeature()!!
@ -41,7 +34,7 @@ class TileInfo {
get() = if (resource == null) throw Exception("No resource exists for this tile!") else GameBasics.TileResources[resource!!]!!
val isCityCenter: Boolean
get() = city != null && position == city!!.cityLocation
get() = getCity() != null && position == getCity()!!.location
val tileImprovement: TileImprovement?
get() = if (improvement == null) null else GameBasics.TileImprovements[improvement!!]
@ -62,8 +55,9 @@ class TileInfo {
}
fun getOwner(): CivilizationInfo? {
return if (owner == null) null
else tileMap.gameInfo.civilizations.first { it.civName == owner }
val containingCity = getCity()
if(containingCity==null) return null
return containingCity.civInfo
}
fun getTerrainFeature(): Terrain? {
@ -72,7 +66,7 @@ class TileInfo {
fun getTileStats(observingCiv: CivilizationInfo): Stats {
return getTileStats(city, observingCiv)
return getTileStats(getCity(), observingCiv)
}
fun getTileStats(city: CityInfo?, observingCiv: CivilizationInfo): Stats {
@ -149,7 +143,8 @@ class TileInfo {
override fun toString(): String {
val SB = StringBuilder()
if (isCityCenter) {
SB.appendln(workingCity + ",\r\n" + city!!.cityConstructions.getProductionForTileInfo())
val city = getCity()!!
SB.appendln(city.name+ ",\r\n" + city.cityConstructions.getProductionForTileInfo())
}
SB.appendln(this.baseTerrain)
if (terrainFeature != null) SB.appendln(terrainFeature!!)
@ -190,4 +185,9 @@ class TileInfo {
return bonus
}
fun isWorked(): Boolean {
val city = getCity()
return city!=null && city.workedTiles.contains(position)
}
}

View file

@ -16,9 +16,8 @@ class UnitMovementAlgorithms(val tileMap: TileMap){
val updatedTiles = ArrayList<TileInfo>()
for (tileToCheck in tilesToCheck)
for (maybeUpdatedTile in tileToCheck.neighbors) {
if(maybeUpdatedTile.owner != null && maybeUpdatedTile.owner != civInfo.civName && maybeUpdatedTile.isCityCenter)
if(maybeUpdatedTile.getOwner() != null && maybeUpdatedTile.getOwner() != civInfo && maybeUpdatedTile.isCityCenter)
continue // Enemy city, can't move through it!
// if(maybeUpdatedTile.unit!=null && maybeUpdatedTile.unit!!.civInfo != civInfo) continue // Enemy unit!
var distanceBetweenTiles = maybeUpdatedTile.lastTerrain.movementCost.toFloat() // no road
if (tileToCheck.roadStatus !== RoadStatus.None && maybeUpdatedTile.roadStatus !== RoadStatus.None) //Road
@ -35,16 +34,11 @@ class UnitMovementAlgorithms(val tileMap: TileMap){
totalDistanceToTile = unitMovement
distanceToTiles[maybeUpdatedTile] = totalDistanceToTile
}
}
tilesToCheck = updatedTiles
}
// now that we've used the tiles that have friendly units to "pass through" them,
// we have to remove them from the final result since we can't actually get there.
// distanceToTiles.filterKeys { it.unit!=null }.forEach { distanceToTiles.remove(it.key) }
return distanceToTiles
}

View file

@ -142,7 +142,7 @@ class Building : NamedStats(), IConstruction, ICivilopedia {
if (requiredBuildingInAllCities != null && civInfo.cities.any { !it.cityConstructions.isBuilt(requiredBuildingInAllCities!!) })
return false
if (cannotBeBuiltWith != null && construction.isBuilt(cannotBeBuiltWith!!)) return false
if ("MustBeNextToDesert" == unique && !civInfo.gameInfo.tileMap.getTilesInDistance(construction.cityInfo.cityLocation, 1).any { it.baseTerrain == "Desert" })
if ("MustBeNextToDesert" == unique && !civInfo.gameInfo.tileMap.getTilesInDistance(construction.cityInfo.location, 1).any { it.baseTerrain == "Desert" })
return false
if (requiredResource != null && !civInfo.getCivResources().containsKey(GameBasics.TileResources[requiredResource!!]))
return false
@ -184,8 +184,8 @@ class Building : NamedStats(), IConstruction, ICivilopedia {
"EmpireEntersGoldenAge" -> civInfo.goldenAges.enterGoldenAge()
"FreeGreatArtistAppears" -> civInfo.addGreatPerson("Great Artist")
"WorkerConstruction" -> {
civInfo.placeUnitNearTile(construction.cityInfo.cityLocation, "Worker")
civInfo.placeUnitNearTile(construction.cityInfo.cityLocation, "Worker")
civInfo.placeUnitNearTile(construction.cityInfo.location, "Worker")
civInfo.placeUnitNearTile(construction.cityInfo.location, "Worker")
}
"FreeSocialPolicy" -> {
civInfo.policies.freePolicies++

View file

@ -40,6 +40,6 @@ class Unit : INamed, IConstruction {
}
override fun postBuildEvent(construction: CityConstructions) {
construction.cityInfo.civInfo.placeUnitNearTile(construction.cityInfo.cityLocation, name)
construction.cityInfo.civInfo.placeUnitNearTile(construction.cityInfo.location, name)
}
} // for json parsing, we need to have a default constructor

View file

@ -139,7 +139,7 @@ class CityScreen(internal val city: CityInfo) : CameraStageBaseScreen() {
goToWorldButton.clearListeners()
goToWorldButton.addClickListener {
game.setWorldScreen()
game.worldScreen!!.tileMapHolder.setCenterPosition(city.cityLocation)
game.worldScreen!!.tileMapHolder.setCenterPosition(city.location)
dispose()
}
@ -152,7 +152,7 @@ class CityScreen(internal val city: CityInfo) : CameraStageBaseScreen() {
val allTiles = Group()
for (tileInfo in game.gameInfo.tileMap.getTilesInDistance(cityInfo.cityLocation, 5)) {
for (tileInfo in game.gameInfo.tileMap.getTilesInDistance(cityInfo.location, 5)) {
if (!tileInfo.explored) continue // Don't even bother to display it.
val group = CityTileGroup(cityInfo, tileInfo)
group.addClickListener {
@ -160,21 +160,21 @@ class CityScreen(internal val city: CityInfo) : CameraStageBaseScreen() {
update()
}
if (!cityInfo.getTilesInRange().contains(tileInfo) || tileInfo.workingCity != null && tileInfo.workingCity != cityInfo.name) {
if (tileInfo.getCity()!=city) {
group.setColor(0f, 0f, 0f, 0.3f)
group.yieldGroup.isVisible = false
} else if (!tileInfo.isCityCenter) {
group.addPopulationIcon()
group.populationImage!!.addClickListener {
if (tileInfo.workingCity == null && cityInfo.population.getFreePopulation() > 0)
tileInfo.workingCity = cityInfo.name
else if (cityInfo.name == tileInfo.workingCity) tileInfo.workingCity = null
if (!tileInfo.isWorked() && cityInfo.population.getFreePopulation() > 0)
cityInfo.workedTiles.add(tileInfo.position)
else if (tileInfo.isWorked()) cityInfo.workedTiles.remove(tileInfo.position)
cityInfo.cityStats.update()
update()
}
}
val positionalVector = HexMath.Hex2WorldCoords(tileInfo.position.cpy().sub(cityInfo.cityLocation))
val positionalVector = HexMath.Hex2WorldCoords(tileInfo.position.cpy().sub(cityInfo.location))
val groupSize = 50
group.setPosition(stage.width / 2 + positionalVector.x * 0.8f * groupSize.toFloat(),
stage.height / 2 + positionalVector.y * 0.8f * groupSize.toFloat())

View file

@ -1,5 +1,6 @@
package com.unciv.ui.cityscreen
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.utils.Align
import com.unciv.logic.city.CityInfo
import com.unciv.logic.map.TileInfo
@ -13,7 +14,7 @@ class CityTileGroup(private val city: CityInfo, tileInfo: TileInfo) : TileGroup(
init {
this.yieldGroup = YieldGroup()
addActor(yieldGroup)
if (city.cityLocation == tileInfo.position) {
if (city.location == tileInfo.position) {
populationImage = ImageGetter.getImage("StatIcons/City_Center_(Civ6).png")
addActor(populationImage)
}
@ -26,8 +27,14 @@ class CityTileGroup(private val city: CityInfo, tileInfo: TileInfo) : TileGroup(
populationImage!!.setSize(30f, 30f)
populationImage!!.setPosition(width / 2 - populationImage!!.width / 2,
height * 0.85f - populationImage!!.height / 2)
if (tileInfo.isWorked())
populationImage!!.color = Color.WHITE
else populationImage!!.color = Color.GRAY
}
if (improvementImage != null) improvementImage!!.setColor(1f, 1f, 1f, 0.5f)
if (resourceImage != null) resourceImage!!.setColor(1f, 1f, 1f, 0.5f)

View file

@ -24,7 +24,7 @@ class GreatPersonPickerScreen : PickerScreen() {
}
rightSideButton.addClickListener {
civInfo!!.placeUnitNearTile(civInfo!!.cities[0].cityLocation, theChosenOne!!.name)
civInfo!!.placeUnitNearTile(civInfo!!.cities[0].location, theChosenOne!!.name)
}
}

View file

@ -62,13 +62,6 @@ open class TileGroup(var tileInfo: TileInfo) : Group() {
updateResourceImage()
updateImprovementImage()
if (populationImage != null) {
if (tileInfo.workingCity != null)
populationImage!!.color = Color.WHITE
else
populationImage!!.color = Color.GRAY
}
updateRoadImages()
updateBorderImages()
}
@ -77,8 +70,8 @@ open class TileGroup(var tileInfo: TileInfo) : Group() {
for (border in borderImages) border.remove() //clear
borderImages = arrayListOf()
if (tileInfo.owner != null) {
for (neighbor in tileInfo.neighbors.filter { it.owner != tileInfo.owner }) {
if (tileInfo.getOwner() != null) {
for (neighbor in tileInfo.neighbors.filter { it.getOwner() != tileInfo.getOwner() }) {
val image = ImageGetter.getImage(ImageGetter.WhiteDot)
val relativeHexPosition = tileInfo.position.cpy().sub(neighbor.position)

View file

@ -51,8 +51,8 @@ class WorldTileGroup(tileInfo: TileInfo) : TileGroup(tileInfo) {
if (populationImage != null) removePopulationIcon()
val city = tileInfo.city
if (city != null && city.civInfo.isPlayerCivilization() && !tileInfo.isCityCenter && populationImage == null)
val city = tileInfo.getCity()
if (tileInfo.isWorked() && city!!.civInfo.isPlayerCivilization() && populationImage == null)
addPopulationIcon()
if (city != null && tileInfo.isCityCenter) {

View file

@ -31,7 +31,7 @@ class BattleTable(val worldScreen: WorldScreen): Table() {
val selectedTile = worldScreen.tileMapHolder.selectedTile!!
val defender: ICombatant
if (selectedTile.explored && selectedTile.isCityCenter && selectedTile.getOwner() != worldScreen.civInfo)
defender = CityCombatant(selectedTile.city!!)
defender = CityCombatant(selectedTile.getCity()!!)
else if (selectedTile.unit != null
&& selectedTile.unit!!.owner != worldScreen.civInfo.civName // enemy unit on selected tile,
&& worldScreen.civInfo.getViewableTiles().contains(selectedTile))

View file

@ -2,6 +2,7 @@ package com.unciv.ui.worldscreen.unit
import com.badlogic.gdx.scenes.scene2d.ui.TextButton
import com.unciv.UnCivGame
import com.unciv.logic.Automation
import com.unciv.logic.map.MapUnit
import com.unciv.logic.map.TileInfo
import com.unciv.models.gamebasics.Building
@ -85,7 +86,7 @@ class UnitActions {
actionList += UnitAction("Automate",
{
tile.unit!!.action = "automation"
tile.unit!!.doAutomatedAction()
Automation().automateWorkerAction(tile.unit!!)
},unit.currentMovement != 0f
)
}
@ -118,13 +119,13 @@ class UnitActions {
if (unit.name == "Great Engineer") {
actionList += UnitAction( "Hurry Wonder",
{
tile.city!!.cityConstructions.addConstruction(300 + 30 * tile.city!!.population.population) //http://civilization.wikia.com/wiki/Great_engineer_(Civ5)
tile.getCity()!!.cityConstructions.addConstruction(300 + 30 * tile.getCity()!!.population.population) //http://civilization.wikia.com/wiki/Great_engineer_(Civ5)
tile.unit = null // destroy!
},
unit.currentMovement != 0f &&
tile.isCityCenter &&
tile.city!!.cityConstructions.getCurrentConstruction() is Building &&
(tile.city!!.cityConstructions.getCurrentConstruction() as Building).isWonder)
tile.getCity()!!.cityConstructions.getCurrentConstruction() is Building &&
(tile.getCity()!!.cityConstructions.getCurrentConstruction() as Building).isWonder)
actionList += UnitAction("Construct Manufactory",
constructImprovementAndDestroyUnit(tile, "Manufactory"),unit.currentMovement != 0f)