Converted all logic/map files to Kotlin
This commit is contained in:
parent
18be9e37b2
commit
113f3965fc
19 changed files with 561 additions and 603 deletions
|
@ -111,7 +111,7 @@ public class CivilizationInfo {
|
|||
statsForTurn.happiness=0;
|
||||
|
||||
int transportationUpkeep = 0;
|
||||
for(TileInfo tile : gameInfo.tileMap.values()) {
|
||||
for(TileInfo tile : gameInfo.tileMap.getValues()) {
|
||||
if(tile.isCityCenter()) continue;
|
||||
if (tile.roadStatus == RoadStatus.Road) transportationUpkeep+=1;
|
||||
else if(tile.roadStatus == RoadStatus.Railroad) transportationUpkeep+=2;
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
package com.unciv.logic.civilization;
|
||||
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
|
||||
public class Notification{
|
||||
public String text;
|
||||
public Vector2 location;
|
||||
|
||||
Notification(){}
|
||||
|
||||
public Notification(String text, Vector2 location) {
|
||||
this.text = text;
|
||||
this.location = location;
|
||||
}
|
||||
}
|
15
core/src/com/unciv/logic/civilization/Notification.kt
Normal file
15
core/src/com/unciv/logic/civilization/Notification.kt
Normal file
|
@ -0,0 +1,15 @@
|
|||
package com.unciv.logic.civilization
|
||||
|
||||
import com.badlogic.gdx.math.Vector2
|
||||
|
||||
class Notification {
|
||||
@JvmField var text: String = ""
|
||||
@JvmField var location: Vector2? = null
|
||||
|
||||
internal constructor() {}
|
||||
|
||||
constructor(text: String, location: Vector2?) {
|
||||
this.text = text
|
||||
this.location = location
|
||||
}
|
||||
}
|
|
@ -63,7 +63,7 @@ public class TechManager {
|
|||
});
|
||||
|
||||
if (revealedResource != null)
|
||||
for (TileInfo tileInfo : civInfo.gameInfo.tileMap.values())
|
||||
for (TileInfo tileInfo : civInfo.gameInfo.tileMap.getValues())
|
||||
if (revealedResource.name.equals(tileInfo.resource) && civInfo.civName.equals(tileInfo.owner)) {
|
||||
for (int i = 0; ; i++) {
|
||||
TileInfo cityTile = civInfo.gameInfo.tileMap.getTilesAtDistance(tileInfo.position, i)
|
||||
|
|
|
@ -1,130 +0,0 @@
|
|||
package com.unciv.logic.map;
|
||||
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
import com.badlogic.gdx.utils.Predicate;
|
||||
import com.unciv.logic.civilization.CivilizationInfo;
|
||||
import com.unciv.models.gamebasics.GameBasics;
|
||||
import com.unciv.models.gamebasics.TileImprovement;
|
||||
import com.unciv.models.linq.Linq;
|
||||
|
||||
public class MapUnit{
|
||||
public transient CivilizationInfo civInfo;
|
||||
|
||||
public String owner;
|
||||
public String name;
|
||||
public int maxMovement;
|
||||
public float currentMovement;
|
||||
public String action; // work, automation, fortifying, I dunno what.
|
||||
|
||||
public void doPreTurnAction(TileInfo tile){
|
||||
if(currentMovement==0) return; // We've already done stuff this turn, and can't do any more stuff
|
||||
if(action!=null && action.startsWith("moveTo")){
|
||||
String[] destination = action.replace("moveTo ","").split(",");
|
||||
Vector2 destinationVector = new Vector2(Integer.parseInt(destination[0]), Integer.parseInt(destination[1]));
|
||||
TileInfo gotTo = headTowards(tile.position,destinationVector);
|
||||
if(gotTo==null) // we couldn't move there because another unit was in the way!
|
||||
return;
|
||||
if(gotTo.position.equals(destinationVector)) action=null;
|
||||
if(currentMovement!=0) doPreTurnAction(gotTo);
|
||||
return;
|
||||
}
|
||||
|
||||
if ("automation".equals(action)) doAutomatedAction(tile);
|
||||
}
|
||||
|
||||
public void doPostTurnAction(TileInfo tile){
|
||||
if(name.equals("Worker") && tile.improvementInProgress!=null) workOnImprovement(tile);
|
||||
}
|
||||
|
||||
private void workOnImprovement(TileInfo tile){
|
||||
tile.turnsToImprovement -= 1;
|
||||
if(tile.turnsToImprovement == 0)
|
||||
{
|
||||
if (tile.improvementInProgress.startsWith("Remove")) tile.terrainFeature = null;
|
||||
else if(tile.improvementInProgress.equals("Road")) tile.roadStatus = RoadStatus.Road;
|
||||
else if(tile.improvementInProgress.equals("Railroad")) tile.roadStatus = RoadStatus.Railroad;
|
||||
else tile.improvement = tile.improvementInProgress;
|
||||
tile.improvementInProgress = null;
|
||||
}
|
||||
}
|
||||
|
||||
private int getPriority(TileInfo tileInfo){
|
||||
int priority =0;
|
||||
if(tileInfo.workingCity!=null) priority+=2;
|
||||
if(tileInfo.hasViewableResource(civInfo)) priority+=1;
|
||||
if(tileInfo.owner!=null) priority+=2;
|
||||
else if(tileInfo.getNeighbors().any(new Predicate<TileInfo>() {
|
||||
@Override
|
||||
public boolean evaluate(TileInfo arg0) {
|
||||
return arg0.owner!=null;
|
||||
}
|
||||
})) priority+=1;
|
||||
return priority;
|
||||
}
|
||||
|
||||
public TileInfo findTileToWork(TileInfo currentTile){
|
||||
TileInfo selectedTile = currentTile;
|
||||
int tilePriority = currentTile.improvement==null
|
||||
&& currentTile.canBuildImprovement(chooseImprovement(currentTile), civInfo)
|
||||
? getPriority(currentTile) : 1; // min rank to get selected is 2
|
||||
for (int i = 1; i < 5; i++)
|
||||
for (TileInfo tile : civInfo.gameInfo.tileMap.getTilesAtDistance(currentTile.position,i))
|
||||
if(tile.unit==null && tile.improvement==null && getPriority(tile)>tilePriority
|
||||
&& tile.canBuildImprovement(chooseImprovement(tile),civInfo)){
|
||||
selectedTile = tile;
|
||||
tilePriority = getPriority(tile);
|
||||
}
|
||||
|
||||
return selectedTile;
|
||||
}
|
||||
|
||||
public void doAutomatedAction(TileInfo tile){
|
||||
TileInfo toWork = findTileToWork(tile);
|
||||
if(toWork!=tile) {
|
||||
tile = headTowards(tile.position, toWork.position);
|
||||
doPreTurnAction(tile);
|
||||
return;
|
||||
}
|
||||
if(tile.improvementInProgress == null){
|
||||
TileImprovement 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 TileImprovement chooseImprovement(final TileInfo tile){
|
||||
return GameBasics.TileImprovements.get(chooseImprovementString(tile));
|
||||
}
|
||||
|
||||
private String chooseImprovementString(final TileInfo tile){
|
||||
if(tile.improvementInProgress!=null) return tile.improvementInProgress;
|
||||
if("Forest".equals(tile.terrainFeature)) return "Lumber mill";
|
||||
if("Jungle".equals(tile.terrainFeature)) return "Trading post";
|
||||
if("Marsh".equals(tile.terrainFeature)) return "Remove Marsh";
|
||||
|
||||
if(tile.resource!=null) return tile.getTileResource().improvement;
|
||||
if(tile.baseTerrain.equals("Hill")) return "Mine";
|
||||
if(tile.baseTerrain.equals("Grassland") || tile.baseTerrain.equals("Desert") || tile.baseTerrain.equals("Plains"))
|
||||
return "Farm";
|
||||
if(tile.baseTerrain.equals("Tundra")) return "Trading post";
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param origin
|
||||
* @param destination
|
||||
* @return The tile that we reached this turn
|
||||
*/
|
||||
public TileInfo headTowards(Vector2 origin, Vector2 destination){
|
||||
TileMap tileMap = civInfo.gameInfo.tileMap;
|
||||
boolean isMachieneryResearched = civInfo.tech.isResearched("Machinery");
|
||||
Linq<TileInfo> path = tileMap.getShortestPath(origin,destination,currentMovement,maxMovement, isMachieneryResearched);
|
||||
|
||||
TileInfo destinationThisTurn = path.get(0);
|
||||
if(destinationThisTurn.unit!=null) return null;
|
||||
float distanceToTile = tileMap.getDistanceToTilesWithinTurn(origin,currentMovement,isMachieneryResearched).get(destinationThisTurn);
|
||||
tileMap.get(origin).moveUnitToTile(destinationThisTurn, distanceToTile);
|
||||
return destinationThisTurn;
|
||||
}
|
||||
}
|
141
core/src/com/unciv/logic/map/MapUnit.kt
Normal file
141
core/src/com/unciv/logic/map/MapUnit.kt
Normal file
|
@ -0,0 +1,141 @@
|
|||
package com.unciv.logic.map
|
||||
|
||||
import com.badlogic.gdx.math.Vector2
|
||||
import com.unciv.logic.civilization.CivilizationInfo
|
||||
import com.unciv.models.gamebasics.GameBasics
|
||||
import com.unciv.models.gamebasics.TileImprovement
|
||||
|
||||
import java.text.DecimalFormat
|
||||
|
||||
class MapUnit {
|
||||
@Transient
|
||||
@JvmField var civInfo: CivilizationInfo? = null
|
||||
|
||||
@JvmField var owner: String? = null
|
||||
@JvmField var name: String? = null
|
||||
@JvmField var maxMovement: Int = 0
|
||||
@JvmField var currentMovement: Float = 0.toFloat()
|
||||
@JvmField var action: String? = null // work, automation, fortifying, I dunno what.
|
||||
|
||||
val movementString: String
|
||||
get() = DecimalFormat("0.#").format(currentMovement.toDouble()) + "/" + maxMovement
|
||||
|
||||
fun doPreTurnAction(tile: TileInfo) {
|
||||
if (currentMovement == 0f) return // We've already done stuff this turn, and can't do any more stuff
|
||||
if (action != null && action!!.startsWith("moveTo")) {
|
||||
val destination = action!!.replace("moveTo ", "").split(",").dropLastWhile { it.isEmpty() }.toTypedArray()
|
||||
val destinationVector = Vector2(Integer.parseInt(destination[0]).toFloat(), Integer.parseInt(destination[1]).toFloat())
|
||||
val gotTo = headTowards(tile.position, destinationVector)
|
||||
if(gotTo==tile) // We didn't move at all
|
||||
return
|
||||
if (gotTo.position == destinationVector) action = null
|
||||
if (currentMovement != 0f) doPreTurnAction(gotTo)
|
||||
return
|
||||
}
|
||||
|
||||
if ("automation" == action) doAutomatedAction(tile)
|
||||
}
|
||||
|
||||
private fun doPostTurnAction(tile: TileInfo) {
|
||||
if (name == "Worker" && tile.improvementInProgress != null) workOnImprovement(tile)
|
||||
}
|
||||
|
||||
private fun workOnImprovement(tile: TileInfo) {
|
||||
tile.turnsToImprovement -= 1
|
||||
if (tile.turnsToImprovement != 0) return
|
||||
when {
|
||||
tile.improvementInProgress!!.startsWith("Remove") -> tile.terrainFeature = null
|
||||
tile.improvementInProgress == "Road" -> tile.roadStatus = RoadStatus.Road
|
||||
tile.improvementInProgress == "Railroad" -> tile.roadStatus = RoadStatus.Railroad
|
||||
else -> tile.improvement = tile.improvementInProgress
|
||||
}
|
||||
tile.improvementInProgress = null
|
||||
}
|
||||
|
||||
private fun getPriority(tileInfo: TileInfo): Int {
|
||||
var priority = 0
|
||||
if (tileInfo.workingCity != null) priority += 2
|
||||
if (tileInfo.hasViewableResource(civInfo!!)) priority += 1
|
||||
if (tileInfo.owner == owner) priority += 2
|
||||
else if (tileInfo.neighbors.any { it.owner != null }) priority += 1
|
||||
return priority
|
||||
}
|
||||
|
||||
private fun findTileToWork(currentTile: TileInfo): TileInfo {
|
||||
var selectedTile = currentTile
|
||||
var selectedTilePriority =
|
||||
if (currentTile.improvement == null && currentTile.canBuildImprovement(chooseImprovement(currentTile), civInfo!!))
|
||||
getPriority(currentTile)
|
||||
else
|
||||
1 // min rank to get selected is 2
|
||||
|
||||
for (i in 1..4)
|
||||
for (tile in civInfo!!.gameInfo.tileMap.getTilesAtDistance(currentTile.position, i))
|
||||
if (tile.unit == null && tile.improvement == null && getPriority(tile) > selectedTilePriority
|
||||
&& tile.canBuildImprovement(chooseImprovement(tile), civInfo!!)) {
|
||||
selectedTile = tile
|
||||
selectedTilePriority = getPriority(tile)
|
||||
}
|
||||
|
||||
return selectedTile
|
||||
}
|
||||
|
||||
fun doAutomatedAction(tile: TileInfo) {
|
||||
var tile = tile
|
||||
val toWork = findTileToWork(tile)
|
||||
if (toWork != tile) {
|
||||
tile = headTowards(tile.position, toWork.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
|
||||
* @param destination
|
||||
* @return The tile that we reached this turn
|
||||
*/
|
||||
private fun headTowards(origin: Vector2, destination: Vector2): TileInfo {
|
||||
val tileMap = civInfo!!.gameInfo.tileMap
|
||||
val isMachineryResearched = civInfo!!.tech.isResearched("Machinery")
|
||||
val path = tileMap.getShortestPath(origin, destination, currentMovement, maxMovement, isMachineryResearched)
|
||||
|
||||
val destinationThisTurn = path[0]
|
||||
if (destinationThisTurn.unit != null) return tileMap[origin] // Someone is blocking tohe path to the final tile...
|
||||
val distanceToTile = tileMap.getDistanceToTilesWithinTurn(origin, currentMovement, isMachineryResearched)[destinationThisTurn]!!
|
||||
tileMap[origin].moveUnitToTile(destinationThisTurn, distanceToTile)
|
||||
return destinationThisTurn
|
||||
}
|
||||
|
||||
fun nextTurn(tileInfo: TileInfo) {
|
||||
doPostTurnAction(tileInfo)
|
||||
currentMovement = maxMovement.toFloat()
|
||||
doPreTurnAction(tileInfo)
|
||||
}
|
||||
}
|
|
@ -1,85 +0,0 @@
|
|||
package com.unciv.logic.map;
|
||||
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
import com.badlogic.gdx.utils.Predicate;
|
||||
import com.unciv.models.gamebasics.GameBasics;
|
||||
import com.unciv.models.gamebasics.ResourceType;
|
||||
import com.unciv.models.gamebasics.Terrain;
|
||||
import com.unciv.models.gamebasics.TerrainType;
|
||||
import com.unciv.models.gamebasics.TileResource;
|
||||
import com.unciv.models.linq.Linq;
|
||||
import com.unciv.models.linq.LinqHashMap;
|
||||
import com.unciv.ui.utils.HexMath;
|
||||
|
||||
public class RandomMapGenerator{
|
||||
|
||||
private TileInfo addRandomTile(Vector2 position) {
|
||||
final TileInfo tileInfo = new TileInfo();
|
||||
tileInfo.position = position;
|
||||
Linq<Terrain> Terrains = GameBasics.Terrains.linqValues();
|
||||
|
||||
final Terrain baseTerrain = Terrains.where(new Predicate<Terrain>() {
|
||||
@Override
|
||||
public boolean evaluate(Terrain arg0) {
|
||||
return arg0.type == TerrainType.BaseTerrain && !arg0.name.equals("Lakes");
|
||||
}
|
||||
}).getRandom();
|
||||
tileInfo.baseTerrain = baseTerrain.name;
|
||||
|
||||
if (baseTerrain.canHaveOverlay) {
|
||||
if (Math.random() > 0.7f) {
|
||||
Terrain SecondaryTerrain = Terrains.where(new Predicate<Terrain>() {
|
||||
@Override
|
||||
public boolean evaluate(Terrain arg0) {
|
||||
return arg0.type == TerrainType.TerrainFeature && arg0.occursOn.contains(baseTerrain.name);
|
||||
}
|
||||
}).getRandom();
|
||||
if (SecondaryTerrain != null) tileInfo.terrainFeature = SecondaryTerrain.name;
|
||||
}
|
||||
}
|
||||
|
||||
addRandomResourceToTile(tileInfo);
|
||||
|
||||
return tileInfo;
|
||||
}
|
||||
|
||||
void addRandomResourceToTile(final TileInfo tileInfo){
|
||||
|
||||
Linq<TileResource> TileResources = GameBasics.TileResources.linqValues();
|
||||
|
||||
// Resources are placed according to TerrainFeature, if exists, otherwise according to BaseLayer.
|
||||
TileResources = TileResources.where(new Predicate<TileResource>() {
|
||||
@Override
|
||||
public boolean evaluate(TileResource arg0) {
|
||||
return arg0.terrainsCanBeFoundOn.contains(tileInfo.getLastTerrain().name);
|
||||
}
|
||||
});
|
||||
|
||||
TileResource resource = null;
|
||||
if (Math.random() < 1 / 5f) {
|
||||
resource = GetRandomResource(TileResources, ResourceType.Bonus);
|
||||
} else if (Math.random() < 1 / 7f) {
|
||||
resource = GetRandomResource(TileResources, ResourceType.Strategic);
|
||||
} else if (Math.random() < 1 / 15f) {
|
||||
resource = GetRandomResource(TileResources, ResourceType.Luxury);
|
||||
}
|
||||
if (resource != null) tileInfo.resource = resource.name;
|
||||
}
|
||||
|
||||
TileResource GetRandomResource(Linq<TileResource> resources, final ResourceType resourceType) {
|
||||
return resources.where(new Predicate<TileResource>() {
|
||||
@Override
|
||||
public boolean evaluate(TileResource arg0) {
|
||||
return arg0.resourceType.equals(resourceType);
|
||||
}
|
||||
}).getRandom();
|
||||
}
|
||||
|
||||
|
||||
public LinqHashMap<String,TileInfo> generateMap(int distance) {
|
||||
LinqHashMap<String,TileInfo> map = new LinqHashMap<String, TileInfo>();
|
||||
for(Vector2 vector : HexMath.GetVectorsInDistance(Vector2.Zero,distance))
|
||||
map.put(vector.toString(),addRandomTile(vector));
|
||||
return map;
|
||||
}
|
||||
}
|
63
core/src/com/unciv/logic/map/RandomMapGenerator.kt
Normal file
63
core/src/com/unciv/logic/map/RandomMapGenerator.kt
Normal file
|
@ -0,0 +1,63 @@
|
|||
package com.unciv.logic.map
|
||||
|
||||
import com.badlogic.gdx.math.Vector2
|
||||
import com.unciv.models.gamebasics.GameBasics
|
||||
import com.unciv.models.gamebasics.ResourceType
|
||||
import com.unciv.models.gamebasics.TerrainType
|
||||
import com.unciv.models.gamebasics.TileResource
|
||||
import com.unciv.models.linq.Linq
|
||||
import com.unciv.models.linq.LinqHashMap
|
||||
import com.unciv.ui.utils.HexMath
|
||||
|
||||
class RandomMapGenerator {
|
||||
|
||||
private fun addRandomTile(position: Vector2): TileInfo {
|
||||
val tileInfo = TileInfo()
|
||||
tileInfo.position = position
|
||||
val terrains = GameBasics.Terrains.linqValues()
|
||||
|
||||
val baseTerrain = terrains.where { it.type === TerrainType.BaseTerrain && it.name != "Lakes" }.random
|
||||
tileInfo.baseTerrain = baseTerrain!!.name
|
||||
|
||||
if (baseTerrain.canHaveOverlay) {
|
||||
if (Math.random() > 0.7f) {
|
||||
val SecondaryTerrain = terrains.where { it.type === TerrainType.TerrainFeature && it.occursOn!!.contains(baseTerrain.name) }.random
|
||||
if (SecondaryTerrain != null) tileInfo.terrainFeature = SecondaryTerrain.name
|
||||
}
|
||||
}
|
||||
|
||||
addRandomResourceToTile(tileInfo)
|
||||
|
||||
return tileInfo
|
||||
}
|
||||
|
||||
internal fun addRandomResourceToTile(tileInfo: TileInfo) {
|
||||
|
||||
var TileResources = GameBasics.TileResources.linqValues()
|
||||
|
||||
// Resources are placed according to TerrainFeature, if exists, otherwise according to BaseLayer.
|
||||
TileResources = TileResources.where { it.terrainsCanBeFoundOn.contains(tileInfo.lastTerrain!!.name) }
|
||||
|
||||
var resource: TileResource? = null
|
||||
if (Math.random() < 1 / 5f) {
|
||||
resource = GetRandomResource(TileResources, ResourceType.Bonus)
|
||||
} else if (Math.random() < 1 / 7f) {
|
||||
resource = GetRandomResource(TileResources, ResourceType.Strategic)
|
||||
} else if (Math.random() < 1 / 15f) {
|
||||
resource = GetRandomResource(TileResources, ResourceType.Luxury)
|
||||
}
|
||||
if (resource != null) tileInfo.resource = resource.name
|
||||
}
|
||||
|
||||
internal fun GetRandomResource(resources: Linq<TileResource>, resourceType: ResourceType): TileResource? {
|
||||
return resources.where { it.resourceType == resourceType }.random
|
||||
}
|
||||
|
||||
|
||||
fun generateMap(distance: Int): LinqHashMap<String, TileInfo> {
|
||||
val map = LinqHashMap<String, TileInfo>()
|
||||
for (vector in HexMath.GetVectorsInDistance(Vector2.Zero, distance))
|
||||
map[vector.toString()] = addRandomTile(vector)
|
||||
return map
|
||||
}
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
package com.unciv.logic.map;
|
||||
|
||||
public enum RoadStatus{
|
||||
None,
|
||||
Road,
|
||||
Railroad
|
||||
}
|
7
core/src/com/unciv/logic/map/RoadStatus.kt
Normal file
7
core/src/com/unciv/logic/map/RoadStatus.kt
Normal file
|
@ -0,0 +1,7 @@
|
|||
package com.unciv.logic.map
|
||||
|
||||
enum class RoadStatus {
|
||||
None,
|
||||
Road,
|
||||
Railroad
|
||||
}
|
|
@ -1,193 +0,0 @@
|
|||
package com.unciv.logic.map;
|
||||
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
import com.badlogic.gdx.utils.Predicate;
|
||||
import com.unciv.logic.city.CityInfo;
|
||||
import com.unciv.logic.civilization.CivilizationInfo;
|
||||
import com.unciv.models.linq.Linq;
|
||||
import com.unciv.models.gamebasics.GameBasics;
|
||||
import com.unciv.models.gamebasics.Terrain;
|
||||
import com.unciv.models.gamebasics.TileImprovement;
|
||||
import com.unciv.models.gamebasics.TileResource;
|
||||
import com.unciv.models.stats.FullStats;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
|
||||
public class TileInfo
|
||||
{
|
||||
public transient TileMap tileMap;
|
||||
|
||||
public MapUnit unit;
|
||||
public Vector2 position;
|
||||
public String baseTerrain;
|
||||
public String terrainFeature;
|
||||
public String resource;
|
||||
public String improvement;
|
||||
public String improvementInProgress;
|
||||
public String owner; // owning civ name
|
||||
public String workingCity; // Working City name
|
||||
public RoadStatus roadStatus = RoadStatus.None;
|
||||
public boolean explored=false;
|
||||
public int turnsToImprovement;
|
||||
|
||||
public Terrain getBaseTerrain(){return GameBasics.Terrains.get(baseTerrain);}
|
||||
|
||||
public CivilizationInfo getOwner(){
|
||||
if(owner==null) return null;
|
||||
return tileMap.gameInfo.civilizations.first(new Predicate<CivilizationInfo>() {
|
||||
@Override
|
||||
public boolean evaluate(CivilizationInfo arg0) {
|
||||
return arg0.civName.equals(owner);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public CityInfo getCity(){
|
||||
if(workingCity == null) return null;
|
||||
return getOwner().cities.first(new Predicate<CityInfo>() {
|
||||
@Override
|
||||
public boolean evaluate(CityInfo arg0) {
|
||||
return arg0.name.equals(workingCity);
|
||||
}
|
||||
});}
|
||||
|
||||
public Terrain getTerrainFeature(){return terrainFeature ==null ? null : GameBasics.Terrains.get(terrainFeature);}
|
||||
|
||||
public Terrain getLastTerrain() {
|
||||
return terrainFeature == null ? getBaseTerrain() : getTerrainFeature();
|
||||
}
|
||||
|
||||
public TileResource getTileResource(){return resource ==null ? null : GameBasics.TileResources.get(resource);}
|
||||
|
||||
public boolean isCityCenter(){return getCity()!=null && position.equals(getCity().cityLocation);}
|
||||
|
||||
public TileImprovement getTileImprovement(){return improvement ==null ? null : GameBasics.TileImprovements.get(improvement);}
|
||||
|
||||
|
||||
public FullStats getTileStats(CivilizationInfo observingCiv){return getTileStats(getCity(),observingCiv);}
|
||||
|
||||
public FullStats getTileStats(CityInfo city, CivilizationInfo observingCiv)
|
||||
{
|
||||
FullStats stats = getBaseTerrain().clone();
|
||||
|
||||
if(terrainFeature !=null){
|
||||
Terrain terrainFeature = getTerrainFeature();
|
||||
if(terrainFeature.overrideStats) stats = terrainFeature.clone();
|
||||
else stats.add(terrainFeature);
|
||||
}
|
||||
|
||||
TileResource resource = getTileResource();
|
||||
if (hasViewableResource(observingCiv))
|
||||
{
|
||||
stats.add(resource); // resource base
|
||||
if(resource.building !=null && city!=null && city.cityConstructions.isBuilt(resource.building))
|
||||
{
|
||||
stats.add(resource.GetBuilding().resourceBonusStats); // resource-specific building (eg forge, stable) bonus
|
||||
}
|
||||
}
|
||||
|
||||
TileImprovement improvement = getTileImprovement();
|
||||
if (improvement != null)
|
||||
{
|
||||
if (resource != null && resource.improvement.equals(improvement.name))
|
||||
stats.add(resource.improvementStats); // resource-specifc improvement
|
||||
else stats.add(improvement); // basic improvement
|
||||
|
||||
if (observingCiv.tech.isResearched(improvement.improvingTech)) stats.add(improvement.improvingTechStats); // eg Chemistry for mines
|
||||
if(improvement.name.equals("Trading post") && city!=null && city.civInfo.policies.isAdopted("Free Thought"))
|
||||
stats.science+=1;
|
||||
if(new Linq<String>("Academy","Landmark","Manufactory","Customs House").contains(improvement.name)
|
||||
&& observingCiv.policies.isAdopted("Freedom Complete"))
|
||||
stats.add(improvement); // again, for the double effect
|
||||
}
|
||||
|
||||
if (isCityCenter()) {
|
||||
if (stats.food < 2) stats.food = 2;
|
||||
if (stats.production < 1) stats.production = 1;
|
||||
}
|
||||
|
||||
if (stats.production < 0) stats.production = 0;
|
||||
|
||||
if("Jungle".equals(terrainFeature) && city!=null
|
||||
&& city.getBuildingUniques().contains("JunglesProvideScience")) stats.science+=2;
|
||||
if(stats.gold!=0 && observingCiv.goldenAges.isGoldenAge())
|
||||
stats.gold++;
|
||||
|
||||
return stats;
|
||||
}
|
||||
|
||||
public boolean canBuildImprovement(TileImprovement improvement, CivilizationInfo civInfo)
|
||||
{
|
||||
if(isCityCenter() || improvement.name.equals(this.improvement)) return false;
|
||||
Terrain topTerrain = terrainFeature ==null ? getBaseTerrain() : getTerrainFeature();
|
||||
if (improvement.techRequired != null && !civInfo.tech.isResearched(improvement.techRequired)) return false;
|
||||
if (improvement.terrainsCanBeBuiltOn.contains(topTerrain.name)) return true;
|
||||
if(improvement.name.equals("Road") && this.roadStatus== RoadStatus.None) return true;
|
||||
if(improvement.name.equals("Railroad") && this.roadStatus != RoadStatus.Railroad) return true;
|
||||
if (topTerrain.unbuildable) return false;
|
||||
|
||||
return hasViewableResource(civInfo) && getTileResource().improvement.equals(improvement.name);
|
||||
}
|
||||
|
||||
public void startWorkingOnImprovement(TileImprovement improvement, CivilizationInfo civInfo)
|
||||
{
|
||||
improvementInProgress = improvement.name;
|
||||
turnsToImprovement = improvement.getTurnsToBuild(civInfo);
|
||||
}
|
||||
|
||||
public void stopWorkingOnImprovement()
|
||||
{
|
||||
improvementInProgress = null;
|
||||
}
|
||||
|
||||
public void nextTurn()
|
||||
{
|
||||
if(unit !=null) {
|
||||
unit.doPostTurnAction(this);
|
||||
unit.currentMovement = unit.maxMovement;
|
||||
unit.doPreTurnAction(this);
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuilder SB = new StringBuilder();
|
||||
if (isCityCenter()){SB.append(workingCity+",\r\n"+getCity().cityConstructions.getProductionForTileInfo());}
|
||||
SB.append(this.baseTerrain);
|
||||
if (terrainFeature != null) SB.append(",\r\n" + terrainFeature);
|
||||
if (hasViewableResource(tileMap.gameInfo.getPlayerCivilization())) SB.append(",\r\n" + resource);
|
||||
if (roadStatus!= RoadStatus.None && !isCityCenter()) SB.append(",\r\n" + roadStatus);
|
||||
if (improvement != null) SB.append(",\r\n" + improvement);
|
||||
if (improvementInProgress != null) SB.append(",\r\n" + improvementInProgress +" in "+this.turnsToImprovement +" turns");
|
||||
if (unit !=null) SB.append(",\r\n" + unit.name + "("+ new DecimalFormat("0.#").format(unit.currentMovement)+"/"+ unit.maxMovement+")");
|
||||
return SB.toString();
|
||||
}
|
||||
|
||||
public boolean hasViewableResource(CivilizationInfo civInfo) {
|
||||
return resource != null && (getTileResource().revealedBy ==null || civInfo.tech.isResearched(getTileResource().revealedBy));
|
||||
}
|
||||
|
||||
public boolean hasIdleUnit() {
|
||||
if (unit == null) return false;
|
||||
if (unit.currentMovement == 0) return false;
|
||||
return !(unit.name.equals("Worker") && improvementInProgress != null);
|
||||
}
|
||||
|
||||
public void moveUnitToTile(TileInfo otherTile, float movementDistance){
|
||||
if(otherTile.unit!=null) return; // Fail.
|
||||
unit.currentMovement -= movementDistance;
|
||||
if(unit.currentMovement < 0.1) unit.currentMovement =0; // silly floats which are "almost zero"
|
||||
otherTile.unit = unit;
|
||||
unit = null;
|
||||
}
|
||||
|
||||
public Linq<TileInfo> getNeighbors(){
|
||||
return tileMap.getTilesAtDistance(position,1);
|
||||
}
|
||||
|
||||
public int getHeight(){
|
||||
int height=0;
|
||||
if(new Linq<String>("Forest","Jungle").contains(terrainFeature)) height+=1;
|
||||
if("Hill".equals(baseTerrain)) height+=2;
|
||||
return height;
|
||||
}
|
||||
}
|
180
core/src/com/unciv/logic/map/TileInfo.kt
Normal file
180
core/src/com/unciv/logic/map/TileInfo.kt
Normal file
|
@ -0,0 +1,180 @@
|
|||
package com.unciv.logic.map
|
||||
|
||||
import com.badlogic.gdx.math.Vector2
|
||||
import com.unciv.logic.city.CityInfo
|
||||
import com.unciv.logic.civilization.CivilizationInfo
|
||||
import com.unciv.models.linq.Linq
|
||||
import com.unciv.models.gamebasics.GameBasics
|
||||
import com.unciv.models.gamebasics.Terrain
|
||||
import com.unciv.models.gamebasics.TileImprovement
|
||||
import com.unciv.models.gamebasics.TileResource
|
||||
import com.unciv.models.stats.FullStats
|
||||
|
||||
class TileInfo {
|
||||
@Transient @JvmField var tileMap: TileMap? = null
|
||||
|
||||
@JvmField var unit: MapUnit? = null
|
||||
@JvmField var position: Vector2 = Vector2.Zero
|
||||
@JvmField var baseTerrain: String? = null
|
||||
@JvmField var terrainFeature: String? = null
|
||||
@JvmField var resource: String? = null
|
||||
@JvmField var improvement: String? = null
|
||||
@JvmField var improvementInProgress: String? = null
|
||||
@JvmField var owner: String? = null // owning civ name
|
||||
@JvmField var workingCity: String? = null // Working City name
|
||||
@JvmField var roadStatus = RoadStatus.None
|
||||
@JvmField var explored = false
|
||||
@JvmField var turnsToImprovement: Int = 0
|
||||
|
||||
val city: CityInfo?
|
||||
get() = if (workingCity == null) null else getOwner()!!.cities.first { it.name == workingCity }
|
||||
|
||||
val lastTerrain: Terrain
|
||||
get() = if (terrainFeature == null) getBaseTerrain() else getTerrainFeature()!!
|
||||
|
||||
val tileResource: TileResource?
|
||||
get() = if (resource == null) null else GameBasics.TileResources[resource]
|
||||
|
||||
val isCityCenter: Boolean
|
||||
get() = city != null && position == city!!.cityLocation
|
||||
|
||||
val tileImprovement: TileImprovement?
|
||||
get() = if (improvement == null) null else GameBasics.TileImprovements[improvement]
|
||||
|
||||
val neighbors: Linq<TileInfo>
|
||||
get() = tileMap!!.getTilesAtDistance(position, 1)
|
||||
|
||||
val height: Int
|
||||
get() {
|
||||
var height = 0
|
||||
if (Linq("Forest", "Jungle").contains(terrainFeature)) height += 1
|
||||
if ("Hill" == baseTerrain) height += 2
|
||||
return height
|
||||
}
|
||||
|
||||
fun getBaseTerrain(): Terrain {
|
||||
return GameBasics.Terrains[baseTerrain]!!
|
||||
}
|
||||
|
||||
fun getOwner(): CivilizationInfo? {
|
||||
return if (owner == null) null
|
||||
else tileMap!!.gameInfo!!.civilizations.first { it.civName == owner }
|
||||
}
|
||||
|
||||
fun getTerrainFeature(): Terrain? {
|
||||
return if (terrainFeature == null) null else GameBasics.Terrains[terrainFeature]
|
||||
}
|
||||
|
||||
|
||||
fun getTileStats(observingCiv: CivilizationInfo): FullStats {
|
||||
return getTileStats(city, observingCiv)
|
||||
}
|
||||
|
||||
fun getTileStats(city: CityInfo?, observingCiv: CivilizationInfo): FullStats {
|
||||
var stats = getBaseTerrain().clone()
|
||||
|
||||
if (terrainFeature != null) {
|
||||
val terrainFeature = getTerrainFeature()
|
||||
if (terrainFeature!!.overrideStats)
|
||||
stats = terrainFeature.clone()
|
||||
else
|
||||
stats.add(terrainFeature)
|
||||
}
|
||||
|
||||
val resource = tileResource
|
||||
if (hasViewableResource(observingCiv)) {
|
||||
stats.add(resource!!) // resource base
|
||||
if (resource.building != null && city != null && city.cityConstructions.isBuilt(resource.building)) {
|
||||
stats.add(resource.GetBuilding()!!.resourceBonusStats!!) // resource-specific building (eg forge, stable) bonus
|
||||
}
|
||||
}
|
||||
|
||||
val improvement = tileImprovement
|
||||
if (improvement != null) {
|
||||
if (resource != null && resource.improvement == improvement.name)
|
||||
stats.add(resource.improvementStats!!) // resource-specifc improvement
|
||||
else
|
||||
stats.add(improvement) // basic improvement
|
||||
|
||||
if (observingCiv.tech.isResearched(improvement.improvingTech)) stats.add(improvement.improvingTechStats!!) // eg Chemistry for mines
|
||||
if (improvement.name == "Trading post" && city != null && city.civInfo.policies.isAdopted("Free Thought"))
|
||||
stats.science += 1f
|
||||
if (Linq("Academy", "Landmark", "Manufactory", "Customs House").contains(improvement.name) && observingCiv.policies.isAdopted("Freedom Complete"))
|
||||
stats.add(improvement) // again, for the double effect
|
||||
}
|
||||
|
||||
if (isCityCenter) {
|
||||
if (stats.food < 2) stats.food = 2f
|
||||
if (stats.production < 1) stats.production = 1f
|
||||
}
|
||||
|
||||
if (stats.production < 0) stats.production = 0f
|
||||
|
||||
if ("Jungle" == terrainFeature && city != null
|
||||
&& city.buildingUniques.contains("JunglesProvideScience"))
|
||||
stats.science += 2f
|
||||
if (stats.gold != 0f && observingCiv.goldenAges.isGoldenAge)
|
||||
stats.gold++
|
||||
|
||||
return stats
|
||||
}
|
||||
|
||||
fun canBuildImprovement(improvement: TileImprovement, civInfo: CivilizationInfo): Boolean {
|
||||
if (isCityCenter || improvement.name == this.improvement) return false
|
||||
val topTerrain = if (terrainFeature == null) getBaseTerrain() else getTerrainFeature()
|
||||
if (improvement.techRequired != null && !civInfo.tech.isResearched(improvement.techRequired)) return false
|
||||
if (improvement.terrainsCanBeBuiltOn.contains(topTerrain!!.name)) return true
|
||||
if (improvement.name == "Road" && this.roadStatus === RoadStatus.None) return true
|
||||
if (improvement.name == "Railroad" && this.roadStatus !== RoadStatus.Railroad) return true
|
||||
if (topTerrain.unbuildable) return false
|
||||
return hasViewableResource(civInfo) && tileResource!!.improvement == improvement.name
|
||||
|
||||
}
|
||||
|
||||
fun startWorkingOnImprovement(improvement: TileImprovement, civInfo: CivilizationInfo) {
|
||||
improvementInProgress = improvement.name
|
||||
turnsToImprovement = improvement.getTurnsToBuild(civInfo)
|
||||
}
|
||||
|
||||
fun stopWorkingOnImprovement() {
|
||||
improvementInProgress = null
|
||||
}
|
||||
|
||||
fun nextTurn() {
|
||||
if (unit != null) unit!!.nextTurn(this)
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
val SB = StringBuilder()
|
||||
if (isCityCenter) {
|
||||
SB.appendln(workingCity + ",\r\n" + city!!.cityConstructions.productionForTileInfo)
|
||||
}
|
||||
SB.appendln(this.baseTerrain)
|
||||
if (terrainFeature != null) SB.appendln(terrainFeature!!)
|
||||
if (hasViewableResource(tileMap!!.gameInfo!!.playerCivilization)) SB.appendln(resource!!)
|
||||
if (roadStatus !== RoadStatus.None && !isCityCenter) SB.appendln(roadStatus)
|
||||
if (improvement != null) SB.appendln(improvement!!)
|
||||
if (improvementInProgress != null) SB.appendln("$improvementInProgress in ${this.turnsToImprovement} turns")
|
||||
if (unit != null) SB.appendln(unit!!.name + "(" + unit!!.movementString + ")")
|
||||
return SB.toString()
|
||||
}
|
||||
|
||||
fun hasViewableResource(civInfo: CivilizationInfo): Boolean {
|
||||
return resource != null && (tileResource!!.revealedBy == null || civInfo.tech.isResearched(tileResource!!.revealedBy))
|
||||
}
|
||||
|
||||
fun hasIdleUnit(): Boolean {
|
||||
if (unit == null) return false
|
||||
if (unit!!.currentMovement == 0f) return false
|
||||
if (unit!!.name == "Worker" && improvementInProgress != null) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
fun moveUnitToTile(otherTile: TileInfo, movementDistance: Float) {
|
||||
if (otherTile.unit != null) return // Fail.
|
||||
unit!!.currentMovement -= movementDistance
|
||||
if (unit!!.currentMovement < 0.1) unit!!.currentMovement = 0f // silly floats which are "almost zero"
|
||||
otherTile.unit = unit
|
||||
unit = null
|
||||
}
|
||||
}
|
|
@ -1,149 +0,0 @@
|
|||
package com.unciv.logic.map;
|
||||
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
import com.badlogic.gdx.utils.Predicate;
|
||||
import com.unciv.logic.civilization.CivilizationInfo;
|
||||
import com.unciv.models.gamebasics.GameBasics;
|
||||
import com.unciv.models.linq.Linq;
|
||||
import com.unciv.models.linq.LinqHashMap;
|
||||
import com.unciv.ui.GameInfo;
|
||||
import com.unciv.ui.utils.HexMath;
|
||||
|
||||
public class TileMap{
|
||||
|
||||
public transient GameInfo gameInfo;
|
||||
|
||||
|
||||
private Linq<MapUnit> units;
|
||||
private LinqHashMap<String, TileInfo> tiles = new LinqHashMap<String, TileInfo>();
|
||||
|
||||
public TileMap(){} // for json parsing, we need to have a default constructor
|
||||
public Linq<TileInfo> values(){return tiles.linqValues();}
|
||||
|
||||
|
||||
public TileMap(int distance) {
|
||||
tiles = new RandomMapGenerator().generateMap(distance);
|
||||
setTransients();
|
||||
}
|
||||
|
||||
public boolean contains(Vector2 vector){ return tiles.containsKey(vector.toString());}
|
||||
|
||||
public TileInfo get(Vector2 vector){return tiles.get(vector.toString());}
|
||||
|
||||
public Linq<TileInfo> getTilesInDistance(Vector2 origin, int distance){
|
||||
Linq<TileInfo> tiles = new Linq<TileInfo>();
|
||||
|
||||
for(Vector2 vector : HexMath.GetVectorsInDistance(origin, distance))
|
||||
if(contains(vector))
|
||||
tiles.add(get(vector));
|
||||
|
||||
return tiles;
|
||||
}
|
||||
|
||||
public Linq<TileInfo> getTilesAtDistance(Vector2 origin, int distance){
|
||||
Linq<TileInfo> tiles = new Linq<TileInfo>();
|
||||
|
||||
for(Vector2 vector : HexMath.GetVectorsAtDistance(origin, distance))
|
||||
if(contains(vector))
|
||||
tiles.add(get(vector));
|
||||
|
||||
return tiles;
|
||||
}
|
||||
|
||||
public LinqHashMap<TileInfo,Float> getDistanceToTilesWithinTurn(Vector2 origin, float currentUnitMovement, boolean machineryIsResearched){
|
||||
LinqHashMap<TileInfo,Float> distanceToTiles = new LinqHashMap<TileInfo, Float>();
|
||||
distanceToTiles.put(get(origin), 0f);
|
||||
Linq<TileInfo> tilesToCheck = new Linq<TileInfo>();
|
||||
tilesToCheck.add(get(origin));
|
||||
while(!tilesToCheck.isEmpty()){
|
||||
Linq<TileInfo> updatedTiles = new Linq<TileInfo>();
|
||||
for(TileInfo tileToCheck : tilesToCheck)
|
||||
for (TileInfo maybeUpdatedTile : getTilesInDistance(tileToCheck.position,1)) {
|
||||
float distanceBetweenTiles = maybeUpdatedTile.getLastTerrain().movementCost;
|
||||
if(tileToCheck.roadStatus!=RoadStatus.None && maybeUpdatedTile.roadStatus!=RoadStatus.None) {
|
||||
if(machineryIsResearched) distanceBetweenTiles = 1 / 3f;
|
||||
else distanceBetweenTiles = 1/2f;
|
||||
}
|
||||
if(tileToCheck.roadStatus==RoadStatus.Railroad && maybeUpdatedTile.roadStatus==RoadStatus.Railroad) distanceBetweenTiles = 1/10f;
|
||||
float totalDistanceToTile = distanceToTiles.get(tileToCheck)+ distanceBetweenTiles;
|
||||
if (!distanceToTiles.containsKey(maybeUpdatedTile) || distanceToTiles.get(maybeUpdatedTile) > totalDistanceToTile) {
|
||||
|
||||
if(totalDistanceToTile<currentUnitMovement) updatedTiles.add(maybeUpdatedTile);
|
||||
else totalDistanceToTile = currentUnitMovement;
|
||||
distanceToTiles.put(maybeUpdatedTile,totalDistanceToTile);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
tilesToCheck = updatedTiles;
|
||||
}
|
||||
return distanceToTiles;
|
||||
}
|
||||
|
||||
public Linq<TileInfo> getShortestPath(Vector2 origin, Vector2 destination, float currentMovement, int maxMovement, boolean isMachieneryResearched){
|
||||
Linq<TileInfo> toCheck = new Linq<TileInfo>(get(origin));
|
||||
LinqHashMap<TileInfo,TileInfo> parents = new LinqHashMap<TileInfo, TileInfo>();
|
||||
parents.put(get(origin),null);
|
||||
|
||||
for (int distance = 1; ; distance++) {
|
||||
Linq<TileInfo> newToCheck = new Linq<TileInfo>();
|
||||
for (TileInfo ti : toCheck){
|
||||
for (TileInfo otherTile : getDistanceToTilesWithinTurn(ti.position, distance == 1 ? currentMovement : maxMovement, isMachieneryResearched).keySet()){
|
||||
if(parents.containsKey(otherTile)) continue; // We cannot be faster than anything existing...
|
||||
if(!otherTile.position.equals(destination) && otherTile.unit!=null) continue; // go to
|
||||
parents.put(otherTile,ti);
|
||||
if(otherTile.position.equals(destination)){
|
||||
Linq<TileInfo> path = new Linq<TileInfo>();
|
||||
TileInfo current = otherTile;
|
||||
while(parents.get(current)!=null){
|
||||
path.add(current);
|
||||
current = parents.get(current);
|
||||
}
|
||||
return path.reverse();
|
||||
}
|
||||
newToCheck.add(otherTile);
|
||||
}
|
||||
}
|
||||
toCheck = newToCheck;
|
||||
}
|
||||
}
|
||||
|
||||
public void placeUnitNearTile(Vector2 position, final String unitName, final CivilizationInfo civInfo){
|
||||
MapUnit unit = GameBasics.Units.get(unitName).getMapUnit();
|
||||
unit.owner = civInfo.civName;
|
||||
unit.civInfo = civInfo;
|
||||
getTilesInDistance(position,2).first(new Predicate<TileInfo>() {
|
||||
@Override
|
||||
public boolean evaluate(TileInfo arg0) {
|
||||
return arg0.unit==null;
|
||||
}
|
||||
}).unit = unit; // And if there's none, then kill me.
|
||||
}
|
||||
|
||||
public Linq<TileInfo> getViewableTiles(Vector2 position, int sightDistance){
|
||||
final Linq<TileInfo> tiles = getTilesInDistance(position,1);
|
||||
if(get(position).baseTerrain.equals("Hill")) sightDistance+=1;
|
||||
for (int i = 0; i <= sightDistance; i++) {
|
||||
Linq<TileInfo> tilesForLayer = new Linq<TileInfo>();
|
||||
for (final TileInfo tile : getTilesAtDistance(position, i))
|
||||
if (tile.getNeighbors().any(new Predicate<TileInfo>() {
|
||||
@Override
|
||||
public boolean evaluate(TileInfo neighbor) {
|
||||
if (!tiles.contains(neighbor))
|
||||
return false; // Basically, if there's a viewable neighbor which is either flatlands, or I'm taller than him
|
||||
int tileHeight = neighbor.getHeight();
|
||||
return tileHeight == 0 || tile.getHeight() > tileHeight;
|
||||
}
|
||||
})) tilesForLayer.add(tile);
|
||||
tiles.addAll(tilesForLayer);
|
||||
}
|
||||
|
||||
return tiles;
|
||||
}
|
||||
|
||||
public void setTransients(){
|
||||
for(TileInfo tileInfo: values()) tileInfo.tileMap=this;
|
||||
}
|
||||
|
||||
}
|
||||
|
131
core/src/com/unciv/logic/map/TileMap.kt
Normal file
131
core/src/com/unciv/logic/map/TileMap.kt
Normal file
|
@ -0,0 +1,131 @@
|
|||
package com.unciv.logic.map
|
||||
|
||||
import com.badlogic.gdx.math.Vector2
|
||||
import com.unciv.logic.civilization.CivilizationInfo
|
||||
import com.unciv.models.gamebasics.GameBasics
|
||||
import com.unciv.models.linq.Linq
|
||||
import com.unciv.models.linq.LinqHashMap
|
||||
import com.unciv.ui.GameInfo
|
||||
import com.unciv.ui.utils.HexMath
|
||||
|
||||
class TileMap {
|
||||
|
||||
@Transient
|
||||
@JvmField var gameInfo: GameInfo? = null
|
||||
|
||||
private var tiles = LinqHashMap<String, TileInfo>()
|
||||
|
||||
constructor() {} // for json parsing, we need to have a default constructor
|
||||
|
||||
val values: Linq<TileInfo>
|
||||
get() = tiles.linqValues()
|
||||
|
||||
|
||||
constructor(distance: Int) {
|
||||
tiles = RandomMapGenerator().generateMap(distance)
|
||||
setTransients()
|
||||
}
|
||||
|
||||
operator fun contains(vector: Vector2): Boolean {
|
||||
return tiles.containsKey(vector.toString())
|
||||
}
|
||||
|
||||
operator fun get(vector: Vector2): TileInfo {
|
||||
return tiles[vector.toString()]!!
|
||||
}
|
||||
|
||||
fun getTilesInDistance(origin: Vector2?, distance: Int): Linq<TileInfo> {
|
||||
return HexMath.GetVectorsInDistance(origin, distance).where{contains(it)}.select { get(it) }
|
||||
}
|
||||
|
||||
fun getTilesAtDistance(origin: Vector2, distance: Int): Linq<TileInfo> {
|
||||
return HexMath.GetVectorsAtDistance(origin, distance).where{contains(it)}.select { get(it) }
|
||||
|
||||
}
|
||||
|
||||
fun getDistanceToTilesWithinTurn(origin: Vector2, currentUnitMovement: Float, machineryIsResearched: Boolean): LinqHashMap<TileInfo, Float> {
|
||||
val distanceToTiles = LinqHashMap<TileInfo, Float>()
|
||||
distanceToTiles[get(origin)] = 0f
|
||||
var tilesToCheck = Linq<TileInfo>(get(origin))
|
||||
while (!tilesToCheck.isEmpty()) {
|
||||
val updatedTiles = Linq<TileInfo>()
|
||||
for (tileToCheck in tilesToCheck)
|
||||
for (maybeUpdatedTile in getTilesInDistance(tileToCheck.position, 1)) {
|
||||
var distanceBetweenTiles = maybeUpdatedTile.lastTerrain.movementCost.toFloat() // no road
|
||||
if (tileToCheck.roadStatus !== RoadStatus.None && maybeUpdatedTile.roadStatus !== RoadStatus.None) //Road
|
||||
distanceBetweenTiles = if (machineryIsResearched) 1 / 3f else 1 / 2f
|
||||
|
||||
if (tileToCheck.roadStatus === RoadStatus.Railroad && maybeUpdatedTile.roadStatus === RoadStatus.Railroad) // Railroad
|
||||
distanceBetweenTiles = 1 / 10f
|
||||
|
||||
var totalDistanceToTile = distanceToTiles[tileToCheck]!! + distanceBetweenTiles
|
||||
if (!distanceToTiles.containsKey(maybeUpdatedTile) || distanceToTiles[maybeUpdatedTile]!! > totalDistanceToTile) {
|
||||
if (totalDistanceToTile < currentUnitMovement)
|
||||
updatedTiles += maybeUpdatedTile
|
||||
else
|
||||
totalDistanceToTile = currentUnitMovement
|
||||
distanceToTiles[maybeUpdatedTile] = totalDistanceToTile
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
tilesToCheck = updatedTiles
|
||||
}
|
||||
return distanceToTiles
|
||||
}
|
||||
|
||||
fun getShortestPath(origin: Vector2, destination: Vector2, currentMovement: Float, maxMovement: Int, isMachineryResearched: Boolean): Linq<TileInfo> {
|
||||
var tilesToCheck: Linq<TileInfo> = Linq(get(origin))
|
||||
val movementTreeParents = LinqHashMap<TileInfo, TileInfo>() // contains a map of "you can get from X to Y in that turn"
|
||||
movementTreeParents[get(origin)] = null
|
||||
|
||||
var distance = 1
|
||||
while (true) {
|
||||
val newTilesToCheck = Linq<TileInfo>()
|
||||
for (tileToCheck in tilesToCheck) {
|
||||
val movementThisTurn = if (distance == 1) currentMovement else maxMovement.toFloat()
|
||||
for (reachableTile in getDistanceToTilesWithinTurn(tileToCheck.position, movementThisTurn, isMachineryResearched).keys) {
|
||||
if (movementTreeParents.containsKey(reachableTile)) continue // We cannot be faster than anything existing...
|
||||
if (reachableTile.position != destination && reachableTile.unit != null) continue // This is an intermediary tile that contains a unit - we can't go there!
|
||||
movementTreeParents[reachableTile] = tileToCheck
|
||||
if (reachableTile.position == destination) {
|
||||
val path = Linq<TileInfo>() // Traverse the tree upwards to get the list of tiles leading to the destination,
|
||||
var current = reachableTile
|
||||
while (movementTreeParents[current] != null) {
|
||||
path.add(current)
|
||||
current = movementTreeParents[current]
|
||||
}
|
||||
return path.reverse() // and reverse in order to get the list in chronological order
|
||||
}
|
||||
newTilesToCheck.add(reachableTile)
|
||||
}
|
||||
}
|
||||
tilesToCheck = newTilesToCheck
|
||||
distance++
|
||||
}
|
||||
}
|
||||
|
||||
fun placeUnitNearTile(position: Vector2, unitName: String, civInfo: CivilizationInfo) {
|
||||
val unit = GameBasics.Units[unitName]!!.mapUnit
|
||||
unit.owner = civInfo.civName
|
||||
unit.civInfo = civInfo
|
||||
getTilesInDistance(position, 2).first { it.unit == null }!!.unit = unit // And if there's none, then kill me.
|
||||
}
|
||||
|
||||
fun getViewableTiles(position: Vector2, sightDistance: Int): Linq<TileInfo> {
|
||||
var sightDistance = sightDistance
|
||||
val viewableTiles = getTilesInDistance(position, 1)
|
||||
if (get(position).baseTerrain == "Hill") sightDistance += 1
|
||||
for (i in 1..sightDistance) { // in each layer,
|
||||
getTilesAtDistance(position, i).filterTo(viewableTiles) // take only tiles which have a visible neighbor, which is lower than the tile
|
||||
{ tile -> tile.neighbors.any{viewableTiles.contains(it) && (it.height==0 || it.height < tile.height)} }
|
||||
}
|
||||
|
||||
return viewableTiles
|
||||
}
|
||||
|
||||
fun setTransients() {
|
||||
for (tileInfo in values) tileInfo.tileMap = this
|
||||
}
|
||||
|
||||
}
|
|
@ -15,9 +15,9 @@ open class FullStats : CivStats()
|
|||
}
|
||||
|
||||
fun clone():FullStats {
|
||||
val FS = FullStats()
|
||||
FS.add(this)
|
||||
return FS
|
||||
val stats = FullStats()
|
||||
stats.add(this)
|
||||
return stats
|
||||
}
|
||||
|
||||
fun getMinus(): FullStats {
|
||||
|
@ -28,22 +28,22 @@ open class FullStats : CivStats()
|
|||
stats.science = -science
|
||||
stats.culture = -culture
|
||||
stats.happiness = -happiness
|
||||
return stats;
|
||||
return stats
|
||||
}
|
||||
|
||||
operator fun times(number: Float): FullStats{
|
||||
val FS = FullStats()
|
||||
FS.production = production * number
|
||||
FS.food = food*number
|
||||
FS.gold = gold*number
|
||||
FS.science = science*number
|
||||
FS.culture = culture*number
|
||||
FS.happiness = happiness*number
|
||||
return FS
|
||||
val stats = FullStats()
|
||||
stats.production = production * number
|
||||
stats.food = food*number
|
||||
stats.gold = gold*number
|
||||
stats.science = science*number
|
||||
stats.culture = culture*number
|
||||
stats.happiness = happiness*number
|
||||
return stats
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return toDict().filter{it.value!=0}.map{it.key+": "+it.value}.joinToString(",")
|
||||
return toDict().filter{it.value!=0}.map{it.key+": "+it.value}.joinToString()
|
||||
}
|
||||
|
||||
fun toDict(): HashMap<String, Int> {
|
||||
|
|
|
@ -26,7 +26,7 @@ public class GameInfo{
|
|||
|
||||
for(CivilizationInfo civInfo : civilizations) civInfo.nextTurn();
|
||||
|
||||
for(TileInfo tile : tileMap.values().where(new Predicate<TileInfo>() {
|
||||
for(TileInfo tile : tileMap.getValues().where(new Predicate<TileInfo>() {
|
||||
@Override
|
||||
public boolean evaluate(TileInfo arg0) {
|
||||
return arg0.unit!=null;
|
||||
|
@ -52,7 +52,7 @@ public class GameInfo{
|
|||
civInfo.setTransients();
|
||||
}
|
||||
|
||||
for(final TileInfo tile : tileMap.values())
|
||||
for(final TileInfo tile : tileMap.getValues())
|
||||
if(tile.unit!=null) tile.unit.civInfo=civilizations.first(new Predicate<CivilizationInfo>() {
|
||||
@Override
|
||||
public boolean evaluate(CivilizationInfo arg0) {
|
||||
|
|
|
@ -45,8 +45,8 @@ public class HexMath
|
|||
return vectors;
|
||||
}
|
||||
|
||||
public static ArrayList<Vector2> GetVectorsAtDistance(Vector2 origin, int distance){
|
||||
ArrayList<Vector2> vectors = new ArrayList<Vector2>();
|
||||
public static Linq<Vector2> GetVectorsAtDistance(Vector2 origin, int distance){
|
||||
Linq<Vector2> vectors = new Linq<Vector2>();
|
||||
if(distance==0){vectors.add(origin.cpy()); return vectors;}
|
||||
Vector2 Current = origin.cpy().sub(distance,distance); // start at 6 o clock
|
||||
for (int i = 0; i < distance; i++) { // From 6 to 8
|
||||
|
|
|
@ -20,7 +20,7 @@ public class IdleUnitButton extends TextButton {
|
|||
addListener(new ClickListener() {
|
||||
@Override
|
||||
public void clicked(InputEvent event, float x, float y) {
|
||||
Linq<TileInfo> tilesWithIdleUnits = worldScreen.civInfo.gameInfo.tileMap.values().where(new Predicate<TileInfo>() {
|
||||
Linq<TileInfo> tilesWithIdleUnits = worldScreen.civInfo.gameInfo.tileMap.getValues().where(new Predicate<TileInfo>() {
|
||||
@Override
|
||||
public boolean evaluate(TileInfo arg0) {
|
||||
return arg0.hasIdleUnit();
|
||||
|
@ -43,7 +43,7 @@ public class IdleUnitButton extends TextButton {
|
|||
}
|
||||
|
||||
void update() {
|
||||
if (worldScreen.civInfo.gameInfo.tileMap.values().any(new Predicate<TileInfo>() {
|
||||
if (worldScreen.civInfo.gameInfo.tileMap.getValues().any(new Predicate<TileInfo>() {
|
||||
@Override
|
||||
public boolean evaluate(TileInfo arg0) {
|
||||
return arg0.hasIdleUnit();
|
||||
|
|
|
@ -42,7 +42,7 @@ public class TileMapHolder extends ScrollPane {
|
|||
float bottomX = 0;
|
||||
float bottomY = 0;
|
||||
|
||||
for (final TileInfo tileInfo : tileMap.values()) {
|
||||
for (final TileInfo tileInfo : tileMap.getValues()) {
|
||||
final WorldTileGroup group = new WorldTileGroup(tileInfo);
|
||||
|
||||
group.addListener(new ClickListener() {
|
||||
|
@ -130,13 +130,13 @@ public class TileMapHolder extends ScrollPane {
|
|||
HashSet<String> ViewableVectorStrings = new HashSet<String>();
|
||||
|
||||
// tiles adjacent to city tiles
|
||||
for (TileInfo tileInfo : tileMap.values())
|
||||
for (TileInfo tileInfo : tileMap.getValues())
|
||||
if (civInfo.civName.equals(tileInfo.owner))
|
||||
for (Vector2 adjacentLocation : HexMath.GetAdjacentVectors(tileInfo.position))
|
||||
ViewableVectorStrings.add(adjacentLocation.toString());
|
||||
|
||||
// Tiles within 2 tiles of units
|
||||
for (TileInfo tile : tileMap.values()
|
||||
for (TileInfo tile : tileMap.getValues()
|
||||
.where(new Predicate<TileInfo>() {
|
||||
@Override
|
||||
public boolean evaluate(TileInfo arg0) {
|
||||
|
|
Loading…
Reference in a new issue