mirror of
https://github.com/yairm210/Unciv.git
synced 2025-01-20 09:17:47 +07:00
AI now accompanies settlers with military units
AI now picks promotions for promotable units
This commit is contained in:
parent
3f87cfa3db
commit
05b37dc660
@ -12,6 +12,14 @@ class UnCivGame : Game() {
|
|||||||
var gameInfo: GameInfo = GameInfo()
|
var gameInfo: GameInfo = GameInfo()
|
||||||
lateinit var settings : GameSettings
|
lateinit var settings : GameSettings
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This exists so that when debugging we can see the entire map.
|
||||||
|
* Remember to turn this to false before commit and upload!
|
||||||
|
*/
|
||||||
|
val viewEntireMapForDebug = false
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
lateinit var worldScreen: WorldScreen
|
lateinit var worldScreen: WorldScreen
|
||||||
|
|
||||||
override fun create() {
|
override fun create() {
|
||||||
|
@ -81,14 +81,6 @@ class GameInfo {
|
|||||||
civInfo.setTransients()
|
civInfo.setTransients()
|
||||||
}
|
}
|
||||||
|
|
||||||
val civNameToCiv = civilizations.associateBy ({ it.civName},{it})
|
|
||||||
|
|
||||||
for (tile in tileMap.values) {
|
|
||||||
if (tile.militaryUnit != null) tile.militaryUnit!!.civInfo = civNameToCiv[tile.militaryUnit!!.owner]!!
|
|
||||||
if (tile.civilianUnit!= null) tile.civilianUnit!!.civInfo = civNameToCiv[tile.civilianUnit!!.owner]!!
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
for (civInfo in civilizations)
|
for (civInfo in civilizations)
|
||||||
for (cityInfo in civInfo.cities)
|
for (cityInfo in civInfo.cities)
|
||||||
cityInfo.cityStats.update()
|
cityInfo.cityStats.update()
|
||||||
|
@ -47,19 +47,25 @@ class Automation {
|
|||||||
val civilianUnits = mutableListOf<MapUnit>()
|
val civilianUnits = mutableListOf<MapUnit>()
|
||||||
|
|
||||||
for (unit in civInfo.getCivUnits()) {
|
for (unit in civInfo.getCivUnits()) {
|
||||||
|
if(unit.promotions.canBePromoted()){
|
||||||
|
val availablePromotions = unit.promotions.getAvailablePromotions()
|
||||||
|
if(availablePromotions.isNotEmpty())
|
||||||
|
unit.promotions.addPromotion(availablePromotions.getRandom().name)
|
||||||
|
}
|
||||||
|
|
||||||
val unitType = unit.getBaseUnit().unitType
|
val unitType = unit.getBaseUnit().unitType
|
||||||
if(unitType.isRanged()) rangedUnits.add(unit)
|
if(unitType.isRanged()) rangedUnits.add(unit)
|
||||||
else if(unitType.isMelee()) meleeUnits.add(unit)
|
else if(unitType.isMelee()) meleeUnits.add(unit)
|
||||||
else civilianUnits.add(unit)
|
else civilianUnits.add(unit)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (unit in civilianUnits) UnitAutomation().automateUnitMoves(unit) // They move first so that combat units can accompany a settler
|
||||||
for (unit in rangedUnits) UnitAutomation().automateUnitMoves(unit)
|
for (unit in rangedUnits) UnitAutomation().automateUnitMoves(unit)
|
||||||
for (unit in meleeUnits) UnitAutomation().automateUnitMoves(unit)
|
for (unit in meleeUnits) UnitAutomation().automateUnitMoves(unit)
|
||||||
for (unit in civilianUnits) UnitAutomation().automateUnitMoves(unit)
|
|
||||||
|
|
||||||
// train settler?
|
// train settler?
|
||||||
if (civInfo.cities.any()
|
if (civInfo.cities.any()
|
||||||
&& civInfo.happiness > 2*civInfo.cities.size +5
|
&& civInfo.happiness > civInfo.cities.size +5
|
||||||
&& civInfo.getCivUnits().none { it.name == "Settler" }
|
&& civInfo.getCivUnits().none { it.name == "Settler" }
|
||||||
&& civInfo.cities.none { it.cityConstructions.currentConstruction == "Settler" }) {
|
&& civInfo.cities.none { it.cityConstructions.currentConstruction == "Settler" }) {
|
||||||
|
|
||||||
|
@ -76,7 +76,16 @@ class UnitAutomation{
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if(unit.name.startsWith("Great")) return // DON'T MOVE A MUSCLE
|
if(unit.name.startsWith("Great")) return // I don't know what to do with you yet.
|
||||||
|
|
||||||
|
|
||||||
|
// Accompany settlers
|
||||||
|
val closeTileWithSettler = unit.getDistanceToTiles().keys.firstOrNull{
|
||||||
|
it.civilianUnit!=null && it.civilianUnit!!.name=="Settler"}
|
||||||
|
if(closeTileWithSettler != null && unit.canMoveTo(closeTileWithSettler)){
|
||||||
|
unit.movementAlgs().headTowards(closeTileWithSettler)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if (unit.health < 50) {
|
if (unit.health < 50) {
|
||||||
healUnit(unit)
|
healUnit(unit)
|
||||||
@ -87,7 +96,7 @@ class UnitAutomation{
|
|||||||
val enemyTileToAttack = getAttackableEnemies(unit).firstOrNull()
|
val enemyTileToAttack = getAttackableEnemies(unit).firstOrNull()
|
||||||
|
|
||||||
if (enemyTileToAttack != null) {
|
if (enemyTileToAttack != null) {
|
||||||
val setupAction = UnitActions().getUnitActions(unit, UnCivGame.Current.worldScreen!!).firstOrNull{ it.name == "Set up" }
|
val setupAction = UnitActions().getUnitActions(unit, UnCivGame.Current.worldScreen).firstOrNull{ it.name == "Set up" }
|
||||||
if(setupAction!=null) setupAction.action()
|
if(setupAction!=null) setupAction.action()
|
||||||
|
|
||||||
val enemy = Battle().getMapCombatantOfTile(enemyTileToAttack)!!
|
val enemy = Battle().getMapCombatantOfTile(enemyTileToAttack)!!
|
||||||
@ -160,6 +169,8 @@ class UnitAutomation{
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun automateSettlerActions(unit: MapUnit) {
|
private fun automateSettlerActions(unit: MapUnit) {
|
||||||
|
if(unit.getTile().militaryUnit==null) return // Don;t move until you're accompanied by a military unit
|
||||||
|
|
||||||
// find best city location within 5 tiles
|
// find best city location within 5 tiles
|
||||||
val tilesNearCities = unit.civInfo.gameInfo.civilizations.flatMap { it.cities }
|
val tilesNearCities = unit.civInfo.gameInfo.civilizations.flatMap { it.cities }
|
||||||
.flatMap { it.getCenterTile().getTilesInDistance(2) }
|
.flatMap { it.getCenterTile().getTilesInDistance(2) }
|
||||||
|
@ -127,6 +127,12 @@ class CivilizationInfo {
|
|||||||
policies.civInfo = this
|
policies.civInfo = this
|
||||||
tech.civInfo = this
|
tech.civInfo = this
|
||||||
|
|
||||||
|
for (unit in getCivUnits()) {
|
||||||
|
unit.civInfo=this
|
||||||
|
unit.setTransients()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
for (cityInfo in cities) {
|
for (cityInfo in cities) {
|
||||||
cityInfo.setTransients()
|
cityInfo.setTransients()
|
||||||
cityInfo.civInfo = this
|
cityInfo.civInfo = this
|
||||||
@ -180,7 +186,7 @@ class CivilizationInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun getCivUnits(): List<MapUnit> {
|
fun getCivUnits(): List<MapUnit> {
|
||||||
return gameInfo.tileMap.values.flatMap { it.getUnits() }.filter { it.civInfo==this }
|
return gameInfo.tileMap.values.flatMap { it.getUnits() }.filter { it.owner==civName }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getViewableTiles(): List<TileInfo> {
|
fun getViewableTiles(): List<TileInfo> {
|
||||||
|
@ -21,6 +21,10 @@ class MapUnit {
|
|||||||
var attacksThisTurn = 0
|
var attacksThisTurn = 0
|
||||||
var promotions = UnitPromotions()
|
var promotions = UnitPromotions()
|
||||||
|
|
||||||
|
init{
|
||||||
|
promotions.unit=this
|
||||||
|
}
|
||||||
|
|
||||||
fun getBaseUnit(): Unit = GameBasics.Units[name]!!
|
fun getBaseUnit(): Unit = GameBasics.Units[name]!!
|
||||||
fun getMovementString(): String = DecimalFormat("0.#").format(currentMovement.toDouble()) + "/" + maxMovement
|
fun getMovementString(): String = DecimalFormat("0.#").format(currentMovement.toDouble()) + "/" + maxMovement
|
||||||
fun getTile(): TileInfo {
|
fun getTile(): TileInfo {
|
||||||
@ -190,4 +194,8 @@ class MapUnit {
|
|||||||
if(hasUnique("Must set up to ranged attack") && action != "Set Up") return false
|
if(hasUnique("Must set up to ranged attack") && action != "Set Up") return false
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun setTransients(){
|
||||||
|
promotions.unit=this
|
||||||
|
}
|
||||||
}
|
}
|
@ -67,7 +67,7 @@ class TileMap {
|
|||||||
fun setTransients() {
|
fun setTransients() {
|
||||||
for (tileInfo in values){
|
for (tileInfo in values){
|
||||||
tileInfo.tileMap = this
|
tileInfo.tileMap = this
|
||||||
if(tileInfo.unit!=null){
|
if(tileInfo.unit!=null){ // thi is for the old "unit" field which has been replaced.
|
||||||
tileInfo.unit!!.putInTile(tileInfo)
|
tileInfo.unit!!.putInTile(tileInfo)
|
||||||
tileInfo.unit=null
|
tileInfo.unit=null
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
package com.unciv.logic.map
|
package com.unciv.logic.map
|
||||||
|
|
||||||
|
import com.unciv.models.gamebasics.GameBasics
|
||||||
|
import com.unciv.models.gamebasics.unit.Promotion
|
||||||
|
|
||||||
class UnitPromotions{
|
class UnitPromotions{
|
||||||
|
@Transient lateinit var unit:MapUnit
|
||||||
var XP=0
|
var XP=0
|
||||||
var promotions = HashSet<String>()
|
var promotions = HashSet<String>()
|
||||||
var numberOfPromotions = 0 // The number of times this unit has been promoted - some promotions don't come from being promoted but from other things!
|
var numberOfPromotions = 0 // The number of times this unit has been promoted - some promotions don't come from being promoted but from other things!
|
||||||
@ -13,4 +17,10 @@ class UnitPromotions{
|
|||||||
promotions.add(promotionName)
|
promotions.add(promotionName)
|
||||||
numberOfPromotions++
|
numberOfPromotions++
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getAvailablePromotions(): List<Promotion> {
|
||||||
|
return GameBasics.UnitPromotions.values
|
||||||
|
.filter { unit.getBaseUnit().unitType.toString() in it.unitTypes && it.name !in promotions }
|
||||||
|
.filter { it.prerequisites.isEmpty() || it.prerequisites.all { p->p in promotions } }
|
||||||
|
}
|
||||||
}
|
}
|
@ -21,13 +21,13 @@ class PromotionPickerScreen(mapUnit: MapUnit) : PickerScreen() {
|
|||||||
dispose()
|
dispose()
|
||||||
}
|
}
|
||||||
|
|
||||||
val availablePromotions = VerticalGroup()
|
val availablePromotionsGroup = VerticalGroup()
|
||||||
availablePromotions.space(10f)
|
availablePromotionsGroup.space(10f)
|
||||||
val unitType = mapUnit.getBaseUnit().unitType
|
val unitType = mapUnit.getBaseUnit().unitType
|
||||||
val promotionsForUnitType = GameBasics.UnitPromotions.values.filter { it.unitTypes.contains(unitType.toString()) }
|
val promotionsForUnitType = GameBasics.UnitPromotions.values.filter { it.unitTypes.contains(unitType.toString()) }
|
||||||
|
val unitAvailablePromotions = mapUnit.promotions.getAvailablePromotions()
|
||||||
for (promotion in promotionsForUnitType) {
|
for (promotion in promotionsForUnitType) {
|
||||||
val isPromotionAvailable = promotion.prerequisites.isEmpty()
|
val isPromotionAvailable = promotion in unitAvailablePromotions
|
||||||
|| promotion.prerequisites.any { mapUnit.promotions.promotions.contains(it) }
|
|
||||||
val unitHasPromotion = mapUnit.promotions.promotions.contains(promotion.name)
|
val unitHasPromotion = mapUnit.promotions.promotions.contains(promotion.name)
|
||||||
val promotionButton = Button(skin)
|
val promotionButton = Button(skin)
|
||||||
|
|
||||||
@ -48,8 +48,8 @@ class PromotionPickerScreen(mapUnit: MapUnit) : PickerScreen() {
|
|||||||
.joinToString(" OR ")
|
.joinToString(" OR ")
|
||||||
descriptionLabel.setText(descriptionText)
|
descriptionLabel.setText(descriptionText)
|
||||||
}
|
}
|
||||||
availablePromotions.addActor(promotionButton)
|
availablePromotionsGroup.addActor(promotionButton)
|
||||||
}
|
}
|
||||||
topTable.add(availablePromotions)
|
topTable.add(availablePromotionsGroup)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -15,13 +15,6 @@ import com.unciv.ui.utils.center
|
|||||||
import com.unciv.ui.utils.colorFromRGB
|
import com.unciv.ui.utils.colorFromRGB
|
||||||
|
|
||||||
open class TileGroup(var tileInfo: TileInfo) : Group() {
|
open class TileGroup(var tileInfo: TileInfo) : Group() {
|
||||||
/**
|
|
||||||
* This exists so that when debugging we can see the entire map.
|
|
||||||
* Remember to turn this to false before commit and upload!
|
|
||||||
*/
|
|
||||||
protected val viewEntireMapForDebug = false
|
|
||||||
|
|
||||||
|
|
||||||
protected val hexagon = ImageGetter.getImage("TerrainIcons/Hexagon.png")
|
protected val hexagon = ImageGetter.getImage("TerrainIcons/Hexagon.png")
|
||||||
protected var terrainFeatureImage:Image?=null
|
protected var terrainFeatureImage:Image?=null
|
||||||
|
|
||||||
@ -90,7 +83,7 @@ open class TileGroup(var tileInfo: TileInfo) : Group() {
|
|||||||
open fun update(isViewable: Boolean) {
|
open fun update(isViewable: Boolean) {
|
||||||
hideCircle()
|
hideCircle()
|
||||||
if (!tileInfo.tileMap.gameInfo.getPlayerCivilization().exploredTiles.contains(tileInfo.position)
|
if (!tileInfo.tileMap.gameInfo.getPlayerCivilization().exploredTiles.contains(tileInfo.position)
|
||||||
&& !viewEntireMapForDebug) {
|
&& !UnCivGame.Current.viewEntireMapForDebug) {
|
||||||
hexagon.color = Color.BLACK
|
hexagon.color = Color.BLACK
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -109,7 +102,7 @@ open class TileGroup(var tileInfo: TileInfo) : Group() {
|
|||||||
updateBorderImages()
|
updateBorderImages()
|
||||||
|
|
||||||
fogImage.toFront()
|
fogImage.toFront()
|
||||||
fogImage.isVisible=!isViewable
|
fogImage.isVisible=!(isViewable || UnCivGame.Current.viewEntireMapForDebug)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateBorderImages() {
|
private fun updateBorderImages() {
|
||||||
@ -256,7 +249,7 @@ open class TileGroup(var tileInfo: TileInfo) : Group() {
|
|||||||
currentImage.remove()
|
currentImage.remove()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unit != null && (isViewable || viewEntireMapForDebug)) { // Tile is visible
|
if (unit != null && isViewable) { // Tile is visible
|
||||||
newImage = getUnitImage(unit, unit.civInfo.getCivilization().getColor(), 25f)
|
newImage = getUnitImage(unit, unit.civInfo.getCivilization().getColor(), 25f)
|
||||||
addActor(newImage)
|
addActor(newImage)
|
||||||
newImage.center(this)
|
newImage.center(this)
|
||||||
|
@ -44,9 +44,9 @@ class WorldTileGroup(tileInfo: TileInfo) : TileGroup(tileInfo) {
|
|||||||
addPopulationIcon()
|
addPopulationIcon()
|
||||||
|
|
||||||
if (tileInfo.tileMap.gameInfo.getPlayerCivilization().exploredTiles.contains(tileInfo.position)
|
if (tileInfo.tileMap.gameInfo.getPlayerCivilization().exploredTiles.contains(tileInfo.position)
|
||||||
|| viewEntireMapForDebug) updateCityButton(city, isViewable) // needs to be before the update so the units will be above the city button
|
|| UnCivGame.Current.viewEntireMapForDebug) updateCityButton(city, isViewable) // needs to be before the update so the units will be above the city button
|
||||||
|
|
||||||
super.update(isViewable)
|
super.update(isViewable || UnCivGame.Current.viewEntireMapForDebug)
|
||||||
|
|
||||||
yieldGroup.isVisible = !UnCivGame.Current.settings.showResourcesAndImprovements
|
yieldGroup.isVisible = !UnCivGame.Current.settings.showResourcesAndImprovements
|
||||||
if(yieldGroup.isVisible)
|
if(yieldGroup.isVisible)
|
||||||
|
@ -6,6 +6,7 @@ import com.badlogic.gdx.scenes.scene2d.Group
|
|||||||
import com.badlogic.gdx.scenes.scene2d.InputListener
|
import com.badlogic.gdx.scenes.scene2d.InputListener
|
||||||
import com.badlogic.gdx.scenes.scene2d.ui.Image
|
import com.badlogic.gdx.scenes.scene2d.ui.Image
|
||||||
import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane
|
import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane
|
||||||
|
import com.unciv.UnCivGame
|
||||||
import com.unciv.logic.HexMath
|
import com.unciv.logic.HexMath
|
||||||
import com.unciv.logic.map.TileInfo
|
import com.unciv.logic.map.TileInfo
|
||||||
import com.unciv.ui.utils.ImageGetter
|
import com.unciv.ui.utils.ImageGetter
|
||||||
@ -74,7 +75,7 @@ class Minimap(val tileMapHolder: TileMapHolder) : ScrollPane(null){
|
|||||||
for(tileInfo in tileMapHolder.tileMap.values) {
|
for(tileInfo in tileMapHolder.tileMap.values) {
|
||||||
val RGB = tileInfo.getBaseTerrain().RGB!!
|
val RGB = tileInfo.getBaseTerrain().RGB!!
|
||||||
val hex = tileImages[tileInfo]!!
|
val hex = tileImages[tileInfo]!!
|
||||||
if (!exploredTiles.contains(tileInfo.position)) hex.color = Color.BLACK
|
if (!(exploredTiles.contains(tileInfo.position) || UnCivGame.Current.viewEntireMapForDebug)) hex.color = Color.BLACK
|
||||||
else if (tileInfo.isCityCenter()) hex.color = Color.WHITE
|
else if (tileInfo.isCityCenter()) hex.color = Color.WHITE
|
||||||
else if (tileInfo.getCity() != null) hex.color = tileInfo.getOwner()!!.getCivilization().getColor()
|
else if (tileInfo.getCity() != null) hex.color = tileInfo.getOwner()!!.getCivilization().getColor()
|
||||||
else hex.color = colorFromRGB(RGB[0], RGB[1], RGB[2]).lerp(Color.GRAY, 0.5f) // Todo add to baseterrain as function
|
else hex.color = colorFromRGB(RGB[0], RGB[1], RGB[2]).lerp(Color.GRAY, 0.5f) // Todo add to baseterrain as function
|
||||||
|
@ -3,6 +3,7 @@ package com.unciv.ui.worldscreen.bottombar
|
|||||||
import com.badlogic.gdx.scenes.scene2d.ui.Label
|
import com.badlogic.gdx.scenes.scene2d.ui.Label
|
||||||
import com.badlogic.gdx.scenes.scene2d.ui.Table
|
import com.badlogic.gdx.scenes.scene2d.ui.Table
|
||||||
import com.badlogic.gdx.utils.Align
|
import com.badlogic.gdx.utils.Align
|
||||||
|
import com.unciv.UnCivGame
|
||||||
import com.unciv.logic.map.TileInfo
|
import com.unciv.logic.map.TileInfo
|
||||||
import com.unciv.ui.utils.CameraStageBaseScreen
|
import com.unciv.ui.utils.CameraStageBaseScreen
|
||||||
import com.unciv.ui.utils.ImageGetter
|
import com.unciv.ui.utils.ImageGetter
|
||||||
@ -18,7 +19,7 @@ class TileInfoTable(private val worldScreen: WorldScreen) : Table() {
|
|||||||
val civInfo = worldScreen.civInfo
|
val civInfo = worldScreen.civInfo
|
||||||
columnDefaults(0).padRight(10f)
|
columnDefaults(0).padRight(10f)
|
||||||
|
|
||||||
if (civInfo.exploredTiles.contains(tile.position)) {
|
if (civInfo.exploredTiles.contains(tile.position) || UnCivGame.Current.viewEntireMapForDebug) {
|
||||||
add(getStatsTable(tile)).pad(10f)
|
add(getStatsTable(tile)).pad(10f)
|
||||||
add(Label(tile.toString(), skin)).colspan(2)
|
add(Label(tile.toString(), skin)).colspan(2)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user