Added chariot archer - includes adding requiredTech, requiredResource, and uniques to units

This commit is contained in:
Yair Morgenstern 2018-05-07 23:42:58 +03:00
parent 8350d000b1
commit 8b748384af
11 changed files with 78 additions and 41 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@ -21,6 +21,7 @@
unbuildable:true,
unitType:"Melee",
strength:5,
uniques:["Ignores terrain cost"]
movement:2
},
{
@ -42,6 +43,22 @@
cost: 40,
hurryCostModifier:20
},
{
name:"Chariot Archer",
baseDescription: "",
unitType:"Ranged",
movement:4,
strength:6,
rangedStrength:10,
cost: 56,
requiredTech:"The Wheel",
requiredResource:"Horses",
uniques:["No Defensive Terrain Bonus","Rough Terrain Penalty"],
hurryCostModifier:20
},
{
name:"Great Artist",
baseDescription: "Can start an 8-turn golden age or construct a Landmark (+6 culture)",

View File

@ -21,8 +21,8 @@ android {
applicationId "com.unciv.game"
minSdkVersion 14
targetSdkVersion 26
versionCode 46
versionName "2.0.3"
versionCode 47
versionName "2.0.4"
}
buildTypes {
release {

View File

@ -7,11 +7,11 @@ import com.unciv.logic.map.UnitMovementAlgorithms
import com.unciv.models.gamebasics.GameBasics
import com.unciv.models.gamebasics.TileImprovement
public class WorkerAutomation(){
class WorkerAutomation {
fun automateWorkerAction(unit: MapUnit) {
var tile = unit.getTile()
val tileToWork = findTileToWork(tile, unit.civInfo)
val tileToWork = findTileToWork(unit)
if (tileToWork != tile) {
tile = unit.headTowards(tileToWork.position)
unit.doPreTurnAction(tile)
@ -25,27 +25,28 @@ public class WorkerAutomation(){
}
}
private fun findTileToWork(currentTile: TileInfo, civInfo: CivilizationInfo): TileInfo {
private fun findTileToWork(worker:MapUnit): TileInfo {
val currentTile=worker.getTile()
val workableTiles = currentTile.getTilesInDistance(4)
.filter {
(it.unit == null || it == currentTile)
&& it.improvement == null
&& it.canBuildImprovement(chooseImprovement(it), civInfo)
&& {val city=it.getCity(); city==null || it.getCity()?.civInfo == civInfo}() // don't work tiles belonging to another civ
}.sortedByDescending { getPriority(it, civInfo) }.toMutableList()
&& it.canBuildImprovement(chooseImprovement(it), worker.civInfo)
&& {val city=it.getCity(); city==null || it.getCity()?.civInfo == worker.civInfo}() // don't work tiles belonging to another civ
}.sortedByDescending { getPriority(it, worker.civInfo) }.toMutableList()
// the tile needs to be actually reachable - more difficult than it seems,
// which is why we DON'T calculate this for every possible tile in the radius,
// but only for the tile that's about to be chosen.
val selectedTile = workableTiles.firstOrNull{
UnitMovementAlgorithms(currentTile.tileMap)
.getShortestPath(currentTile.position, workableTiles.first().position,2f, 2, civInfo)
.getShortestPath(currentTile.position, workableTiles.first().position,worker)
.isNotEmpty()}
if (selectedTile != null
&& getPriority(selectedTile, civInfo)>1
&& getPriority(selectedTile, worker.civInfo)>1
&& (!workableTiles.contains(currentTile)
|| getPriority(selectedTile, civInfo) > getPriority(currentTile,civInfo)))
|| getPriority(selectedTile, worker.civInfo) > getPriority(currentTile,worker.civInfo)))
return selectedTile
else return currentTile
}

View File

@ -25,8 +25,10 @@ class Battle(val gameInfo:GameInfo) {
fun getDefenceModifiers(attacker: ICombatant, defender: ICombatant): HashMap<String, Float> {
val modifiers = HashMap<String,Float>()
if(!(defender is MapUnitCombatant && defender.unit.getBaseUnit().hasUnique("No Defensive Terrain Bonus"))){
val tileDefenceBonus = defender.getTile().getDefensiveBonus()
if (tileDefenceBonus > 0) modifiers["Terrain"] = tileDefenceBonus
}
return modifiers
}

View File

@ -19,6 +19,9 @@ class CityConstructions {
internal fun getBuildableBuildings(): List<String> = GameBasics.Buildings.values
.filter { it.isBuildable(this) }.map { it.name }
fun getConstructableUnits() = GameBasics.Units.values
.filter { it.isBuildable(this) }.map { it.name }
// Library and public school unique (not actualy unique, though...hmm)
fun getStats(): Stats {
val stats = Stats()

View File

@ -34,7 +34,7 @@ class MapUnit {
fun getDistanceToTiles(): HashMap<TileInfo, Float> {
val tile = getTile()
return UnitMovementAlgorithms(tile.tileMap).getDistanceToTilesWithinTurn(tile.position,currentMovement,
civInfo)
this)
}
fun doPreTurnAction(tile: TileInfo) {
@ -102,7 +102,7 @@ class MapUnit {
else { // If the tile is far away, we need to build a path how to get there, and then take the first step
val path = UnitMovementAlgorithms(tileMap)
.getShortestPath(currentTile.position, destination, currentMovement, maxMovement, civInfo)
.getShortestPath(currentTile.position, destination, this)
destinationTileThisTurn = path.first()
}

View File

@ -1,38 +1,49 @@
package com.unciv.logic.map
import com.badlogic.gdx.math.Vector2
import com.unciv.logic.civilization.CivilizationInfo
class UnitMovementAlgorithms(val tileMap: TileMap){
private fun getMovementCostBetweenAdjacentTiles(from:TileInfo, to:TileInfo, unit:MapUnit): Float {
if (from.roadStatus === RoadStatus.Railroad && to.roadStatus === RoadStatus.Railroad)
return 1 / 10f
fun getDistanceToTilesWithinTurn(origin: Vector2, unitMovement:Float, civInfo:CivilizationInfo): HashMap<TileInfo, Float> {
if (from.roadStatus !== RoadStatus.None && to.roadStatus !== RoadStatus.None) //Road
{
if(unit.civInfo.tech.isResearched("Machinery")) return 1/3f
else return 1/2f
}
if(unit.getBaseUnit().hasUnique("Ignores terrain cost")) return 1f;
if(unit.getBaseUnit().hasUnique("Rough Terrain Penalty")
&& (to.baseTerrain=="Hill" || to.terrainFeature=="Forest" || to.terrainFeature=="Jungle"))
return 4f
return to.lastTerrain.movementCost.toFloat() // no road
}
fun getDistanceToTilesWithinTurn(origin: Vector2, unitMovement:Float, unit: MapUnit): HashMap<TileInfo, Float> {
val distanceToTiles = HashMap<TileInfo, Float>()
val unitTile = tileMap[origin]
distanceToTiles[unitTile] = 0f
var tilesToCheck = listOf(unitTile)
val isMachineryResearched = civInfo.tech.isResearched("Machinery")
while (!tilesToCheck.isEmpty()) {
val updatedTiles = ArrayList<TileInfo>()
for (tileToCheck in tilesToCheck)
for (maybeUpdatedTile in tileToCheck.neighbors) {
if(maybeUpdatedTile.getOwner() != null && maybeUpdatedTile.getOwner() != civInfo && maybeUpdatedTile.isCityCenter())
for (neighbor in tileToCheck.neighbors) {
if(neighbor.getOwner() != null && neighbor.getOwner() != unit.civInfo
&& neighbor.isCityCenter())
continue // Enemy city, can't move through it!
var distanceBetweenTiles = maybeUpdatedTile.lastTerrain.movementCost.toFloat() // no road
if (tileToCheck.roadStatus !== RoadStatus.None && maybeUpdatedTile.roadStatus !== RoadStatus.None) //Road
distanceBetweenTiles = if (isMachineryResearched) 1 / 3f else 1 / 2f
if (tileToCheck.roadStatus === RoadStatus.Railroad && maybeUpdatedTile.roadStatus === RoadStatus.Railroad) // Railroad
distanceBetweenTiles = 1 / 10f
var distanceBetweenTiles = getMovementCostBetweenAdjacentTiles(tileToCheck,neighbor,unit)
var totalDistanceToTile = distanceToTiles[tileToCheck]!! + distanceBetweenTiles
if (!distanceToTiles.containsKey(maybeUpdatedTile) || distanceToTiles[maybeUpdatedTile]!! > totalDistanceToTile) {
if (!distanceToTiles.containsKey(neighbor) || distanceToTiles[neighbor]!! > totalDistanceToTile) {
if (totalDistanceToTile < unitMovement)
updatedTiles += maybeUpdatedTile
updatedTiles += neighbor
else
totalDistanceToTile = unitMovement
distanceToTiles[maybeUpdatedTile] = totalDistanceToTile
distanceToTiles[neighbor] = totalDistanceToTile
}
}
@ -42,8 +53,7 @@ class UnitMovementAlgorithms(val tileMap: TileMap){
return distanceToTiles
}
fun getShortestPath(origin: Vector2, destination: Vector2, currentMovement: Float, maxMovement: Int, civInfo: CivilizationInfo): List<TileInfo> {
fun getShortestPath(origin: Vector2, destination: Vector2, unit:MapUnit): List<TileInfo> {
if(origin.equals(destination)) return listOf(tileMap[origin]) // edge case that's needed, so that workers will know that they can reach their own tile. *sig
var tilesToCheck: List<TileInfo> = listOf(tileMap[origin])
@ -54,9 +64,9 @@ class UnitMovementAlgorithms(val tileMap: TileMap){
while (true) {
val newTilesToCheck = ArrayList<TileInfo>()
val distanceToDestination = HashMap<TileInfo, Float>()
val movementThisTurn = if (distance == 1) currentMovement else maxMovement.toFloat()
val movementThisTurn = if (distance == 1) unit.currentMovement else unit.maxMovement.toFloat()
for (tileToCheck in tilesToCheck) {
val distanceToTilesThisTurn = getDistanceToTilesWithinTurn(tileToCheck.position, movementThisTurn, civInfo)
val distanceToTilesThisTurn = getDistanceToTilesWithinTurn(tileToCheck.position, movementThisTurn, unit)
for (reachableTile in distanceToTilesThisTurn.keys) {
if(reachableTile.position == destination)
distanceToDestination[tileToCheck] = distanceToTilesThisTurn[reachableTile]!!

View File

@ -28,6 +28,8 @@ class Unit : INamed, IConstruction, ICivilopedia {
lateinit var unitType: UnitType
internal var unbuildable: Boolean = false // for special units like great people
var requiredTech:String? = null
var requiredResource:String? = null
var uniques:HashSet<String>?=null
fun getMapUnit(): MapUnit {
val unit = MapUnit()
@ -37,6 +39,7 @@ class Unit : INamed, IConstruction, ICivilopedia {
return unit
}
fun hasUnique(unique:String) = uniques!=null && uniques!!.contains(unique)
override fun getProductionCost(adoptedPolicies: HashSet<String>): Int = cost
@ -45,7 +48,11 @@ class Unit : INamed, IConstruction, ICivilopedia {
}
override fun isBuildable(construction: CityConstructions): Boolean {
return !unbuildable
val civInfo = construction.cityInfo.civInfo
if (unbuildable) return false
if (requiredTech!=null && !civInfo.tech.isResearched(requiredTech!!)) return false
if (requiredResource!=null && !civInfo.getCivResources().keys.any { it.name == requiredResource }) return false
return true
}
override fun postBuildEvent(construction: CityConstructions) {

View File

@ -18,6 +18,7 @@ class BattleTable(val worldScreen: WorldScreen): Table() {
private val battle = Battle(worldScreen.civInfo.gameInfo)
init{
skin = CameraStageBaseScreen.skin
pad(10f)
}
fun hide(){
@ -157,7 +158,7 @@ class BattleTable(val worldScreen: WorldScreen): Table() {
pack()
val tileTableBackground = ImageGetter.getDrawable("skin/tileTableBackground.png")
.tint(Color(0x004085bf))
.tint(Color(0x004085ff))
tileTableBackground.minHeight = 0f
tileTableBackground.minWidth = 0f
background = tileTableBackground

View File

@ -31,12 +31,8 @@ class UnitActions {
}
fun getUnitActions(unit:MapUnit,worldScreen: WorldScreen): List<UnitAction> {
val tile = unit.getTile()
val tileMapHolder = worldScreen.tileMapHolder
val unitTable = worldScreen.unitTable
val actionList = ArrayList<UnitAction>()
if (unitTable.currentlyExecutingAction != "moveTo"
@ -51,7 +47,7 @@ class UnitActions {
UnitAction("Stop movement", {
unitTable.currentlyExecutingAction = null
unit.action=null
},unit.currentMovement != 0f)
},true)
}
if (unit.name == "Settler") {
@ -78,7 +74,7 @@ class UnitActions {
if("automation" == unit.action){
actionList += UnitAction("Stop automation",
{unit.action = null},unit.currentMovement != 0f)
{unit.action = null},true)
}
else {
actionList += UnitAction("Automate",