AI construction choices now better and change between peacetime and wartime.

AIs now declare war on each other if they think they can defeat the other side
(Returned movement alg. to the way it was because the new way didn't allow ais to find enemy units, added comment)
This commit is contained in:
Yair Morgenstern
2018-08-05 23:08:50 +03:00
parent c4a761efdf
commit 2be6a5c15c
10 changed files with 30 additions and 17 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

View File

@ -21,8 +21,8 @@ android {
applicationId "com.unciv.game"
minSdkVersion 14
targetSdkVersion 26
versionCode 112
versionName "2.7.1"
versionCode 114
versionName "2.7.3"
}
buildTypes {
release {

View File

@ -6,7 +6,6 @@ import com.badlogic.gdx.utils.Json
import com.unciv.logic.GameInfo
import com.unciv.logic.GameSaver
import com.unciv.models.gamebasics.GameBasics
import com.unciv.ui.LanguagePickerScreen
import com.unciv.ui.worldscreen.WorldScreen
class UnCivGame : Game() {
@ -18,7 +17,7 @@ class UnCivGame : Game() {
* 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
val viewEntireMapForDebug = true
lateinit var worldScreen: WorldScreen
@ -34,7 +33,7 @@ class UnCivGame : Game() {
startNewGame()
}
}
else screen=LanguagePickerScreen() //startNewGame()
else startNewGame() // screen=LanguagePickerScreen() disabled because of people's negative reviews =(
}
fun loadGame(gameInfo:GameInfo){

View File

@ -5,7 +5,6 @@ import com.unciv.logic.battle.CityCombatant
import com.unciv.logic.city.CityConstructions
import com.unciv.logic.city.CityInfo
import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.logic.civilization.DiplomaticStatus
import com.unciv.logic.map.MapUnit
import com.unciv.logic.map.TileInfo
import com.unciv.logic.trade.TradeLogic
@ -77,7 +76,7 @@ class Automation {
// Declare war?
if(civInfo.cities.isNotEmpty() && civInfo.diplomacy.isNotEmpty()
&& civInfo.diplomacy.values.none { it.diplomaticStatus==DiplomaticStatus.War }) {
&& !civInfo.isAtWar()) {
val enemyCivsByDistanceToOurs = civInfo.diplomacy.values.map { it.otherCiv() }
.filterNot { it == civInfo || it.cities.isEmpty() || !civInfo.diplomacy[it.civName]!!.canDeclareWar() }
@ -94,6 +93,7 @@ class Automation {
}
}
val rangedUnits = mutableListOf<MapUnit>()
val meleeUnits = mutableListOf<MapUnit>()
val civilianUnits = mutableListOf<MapUnit>()
@ -142,11 +142,11 @@ class Automation {
private fun trainCombatUnit(city: CityInfo) {
val combatUnits = city.cityConstructions.getConstructableUnits().filter { it.unitType != UnitType.Civilian }
val chosenUnit: BaseUnit
if(city.civInfo.cities.any { it.getCenterTile().militaryUnit==null}
if(!city.civInfo.isAtWar() && city.civInfo.cities.any { it.getCenterTile().militaryUnit==null}
&& combatUnits.any { it.unitType== UnitType.Ranged }) // this is for city defence so get an archery unit if we can
chosenUnit = combatUnits.filter { it.unitType== UnitType.Ranged }.maxBy { it.cost }!!
else{ // randomize type of unit and takee the most expensive of its kind
else{ // randomize type of unit and take the most expensive of its kind
val chosenUnitType = combatUnits.map { it.unitType }.distinct().filterNot{it==UnitType.Scout}.getRandom()
chosenUnit = combatUnits.filter { it.unitType==chosenUnitType }.maxBy { it.cost }!!
}
@ -157,7 +157,7 @@ class Automation {
fun chooseNextConstruction(cityConstructions: CityConstructions) {
cityConstructions.run {
currentConstruction="" // This is so that if we're currently in the middle of building a wonder,
//currentConstruction="" // This is so that if we're currently in the middle of building a wonder,
// buildableWonders will still contain it
val buildableNotWonders = getBuildableBuildings().filterNot { it.isWonder }
@ -169,13 +169,16 @@ class Automation {
val cities = cityInfo.civInfo.cities.size
val goldBuildings = buildableNotWonders.filter { it.gold>0 }
val zeroMaintainanceBuildings = buildableNotWonders.filter { it.maintenance == 0 }
val wartimeBuildings = buildableNotWonders.filter { it.xpForNewUnits>0 || it.cityStrength>0 }.sortedBy { it.maintenance }
val zeroMaintainanceBuildings = buildableNotWonders.filter { it.maintenance == 0 && it !in wartimeBuildings }
val isAtWar = cityInfo.civInfo.isAtWar()
when {
buildableNotWonders.isNotEmpty() // if the civ is in the gold red-zone, build markets or somesuch
&& cityInfo.civInfo.getStatsForNextTurn().gold <0
&& goldBuildings.isNotEmpty()
-> currentConstruction = goldBuildings.first().name
currentConstruction!="" -> return
buildableNotWonders.any { it.name=="Monument"} -> currentConstruction = "Monument"
buildableNotWonders.any { it.name=="Granary"} -> currentConstruction = "Granary"
buildableNotWonders.any { it.name=="Library"} -> currentConstruction = "Library"
@ -183,10 +186,12 @@ class Automation {
militaryUnits==0 -> trainCombatUnit(cityInfo)
workers==0 -> currentConstruction = CityConstructions.Worker
zeroMaintainanceBuildings.isNotEmpty() -> currentConstruction = zeroMaintainanceBuildings.getRandom().name
buildableWonders.isNotEmpty() -> currentConstruction = buildableWonders.getRandom().name
buildableNotWonders.isNotEmpty() -> currentConstruction = buildableNotWonders.minBy { it.maintenance }!!.name
militaryUnits<cities -> trainCombatUnit(cityInfo)
isAtWar && militaryUnits<cities -> trainCombatUnit(cityInfo)
isAtWar && wartimeBuildings.isNotEmpty() -> currentConstruction = wartimeBuildings.getRandom().name
workers<cities/2 -> currentConstruction = CityConstructions.Worker
militaryUnits<cities -> trainCombatUnit(cityInfo)
buildableNotWonders.isNotEmpty() -> currentConstruction = buildableNotWonders.minBy { it.maintenance }!!.name
buildableWonders.isNotEmpty() -> currentConstruction = buildableWonders.getRandom().name
else -> trainCombatUnit(cityInfo)
}

View File

@ -96,6 +96,7 @@ class CityConstructions {
currentConstruction = "lie"
if (!construction.isBuildable(this)) {
// We can't build this building anymore! (Wonder has been built / resource is gone / etc.)
currentConstruction=""
cityInfo.civInfo.addNotification("Cannot continue work on [$saveCurrentConstruction]", cityInfo.location, Color.BROWN)
Automation().chooseNextConstruction(this)
construction = getConstruction(currentConstruction)
@ -119,6 +120,7 @@ class CityConstructions {
else
cityInfo.civInfo.addNotification("{$currentConstruction} {has been built in} " + cityInfo.name, cityInfo.location, Color.BROWN)
currentConstruction=""
Automation().chooseNextConstruction(this)
}

View File

@ -298,6 +298,8 @@ class CivilizationInfo {
return diplomacy[otherCiv.civName]!!.diplomaticStatus == DiplomaticStatus.War
}
fun isAtWar() = diplomacy.values.any { it.diplomaticStatus==DiplomaticStatus.War }
fun canEnterTiles(otherCiv: CivilizationInfo): Boolean {
if(otherCiv==this) return true
if(isAtWarWith(otherCiv)) return true

View File

@ -42,7 +42,10 @@ class UnitMovementAlgorithms(val unit:MapUnit) {
|| (neighbor.getUnits().isNotEmpty() && neighbor.getUnits().first().civInfo!=unit.civInfo) // Enemy unit
|| (isOwnedByEnemy && !unit.civInfo.canEnterTiles(neighborOwner!!))
)
continue // Can't go here!
totalDistanceToTile = unitMovement // Can't go here.
// The reason that we don't just "return" is so that when calculating how to reach an enemy,
// You need to assume his tile is reachable, otherwise all movement algs on reaching enemy
// cities and units goes kaput.
else {
val distanceBetweenTiles = getMovementCostBetweenAdjacentTiles(tileToCheck, neighbor)

View File

@ -53,6 +53,7 @@ class LanguagePickerScreen: PickerScreen(){
topTable.add(Label(
"Please note that translations are a " +
"community-based work in progress and are INCOMPLETE! \n" +
"The percentage shown is how much of the language is translated in-game.\n" +
"If you want to help translating the game " +
"into your language, contact me!",skin)).pad(10f).row()

View File

@ -45,7 +45,7 @@ class NewGameScreen: PickerScreen(){
table.add("{Difficulty}:".tr())
val difficultySelectBox = TranslatedSelectBox(GameBasics.Difficulties.keys, "Chieftain", skin)
val difficultySelectBox = TranslatedSelectBox(GameBasics.Difficulties.keys, "Prince", skin)
table.add(difficultySelectBox).pad(10f).row()

View File

@ -103,7 +103,8 @@ class TileMapHolder(internal val worldScreen: WorldScreen, internal val tileMap:
tileGroups[unit.getTile()]!!.addWhiteHaloAroundUnit(unit)
for(tile: TileInfo in unit.getDistanceToTiles().keys)
tileGroups[tile]!!.showCircle(colorFromRGB(0, 120, 215))
if(unit.canMoveTo(tile))
tileGroups[tile]!!.showCircle(colorFromRGB(0, 120, 215))
val unitType = unit.getBaseUnit().unitType
val attackableTiles: List<TileInfo> = when{