Merge pull request #432 from ninjatao/ai_exchange_tech

Ai exchange tech
This commit is contained in:
Yair Morgenstern 2019-01-23 11:28:48 +02:00 committed by GitHub
commit 0e5c1843fe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 92 additions and 15 deletions

View File

@ -58,11 +58,11 @@ class GameInfo {
while(thisPlayer.playerType==PlayerType.AI){
NextTurnAutomation().automateCivMoves(thisPlayer)
if (thisPlayer.tech.techsToResearch.isEmpty()) { // should belong in automation? yes/no?
val researchableTechs = GameBasics.Technologies.values
.filter { !thisPlayer.tech.isResearched(it.name) && thisPlayer.tech.canBeResearched(it.name) }
thisPlayer.tech.techsToResearch.add(researchableTechs.minBy { it.cost }!!.name)
}
// if (thisPlayer.tech.techsToResearch.isEmpty()) { // should belong in automation? yes/no?
// val researchableTechs = GameBasics.Technologies.values
// .filter { !thisPlayer.tech.isResearched(it.name) && thisPlayer.tech.canBeResearched(it.name) }
// thisPlayer.tech.techsToResearch.add(researchableTechs.minBy { it.cost }!!.name)
// }
switchTurn()
}

View File

@ -2,31 +2,99 @@ package com.unciv.logic.automation
import com.unciv.logic.city.CityInfo
import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.logic.civilization.PlayerType
import com.unciv.logic.map.MapUnit
import com.unciv.logic.trade.TradeLogic
import com.unciv.logic.trade.TradeOffer
import com.unciv.logic.trade.TradeType
import com.unciv.models.gamebasics.GameBasics
import com.unciv.models.gamebasics.tech.Technology
import com.unciv.models.gamebasics.tr
import com.unciv.ui.utils.getRandom
import kotlin.math.min
class NextTurnAutomation{
fun automateCivMoves(civInfo: CivilizationInfo) {
exchangeTechs(civInfo)
chooseTechToResearch(civInfo)
adoptPolicy(civInfo)
exchangeLuxuries(civInfo)
declareWar(civInfo)
automateCityBombardment(civInfo)
buyBuildingOrUnit(civInfo)
automateUnits(civInfo)
reassignWorkedTiles(civInfo)
trainSettler(civInfo)
}
private fun buyBuildingOrUnit(civInfo: CivilizationInfo) {
//allow ai spending money to purchase building & unit. Buying staff has slightly lower priority than buying tech.
for (city in civInfo.cities.sortedByDescending{ it.population.population }) {
val construction = city.cityConstructions.getCurrentConstruction()
if (construction.canBePurchased()
&& city.civInfo.gold / 3 >= construction.getGoldCost(civInfo.policies.getAdoptedPolicies()) ) {
city.cityConstructions.purchaseBuilding(construction.name)
}
}
}
private fun exchangeTechs(civInfo: CivilizationInfo) {
val otherCivList = civInfo.diplomacy.values.map { it.otherCiv() }.
filter { it.playerType == PlayerType.AI && !it.isBarbarianCivilization() }.
sortedBy { it.tech.techsResearched.size }
for (otherCiv in otherCivList) {
val tradeLogic = TradeLogic(civInfo, otherCiv)
var ourGold = tradeLogic.ourAvailableOffers.first { it.type == TradeType.Gold }.amount
val ourTradableTechs = tradeLogic.ourAvailableOffers
.filter { it.type == TradeType.Technology }
val theirTradableTechs = tradeLogic.theirAvailableOffers
.filter { it.type == TradeType.Technology }
for (theirOffer in theirTradableTechs) {
val theirValue = tradeLogic.evaluateOffer(theirOffer, false)
val ourOfferList = ourTradableTechs.filter{
tradeLogic.evaluateOffer(it, false) == theirValue
&& !tradeLogic.currentTrade.ourOffers.contains(it) }
if (ourOfferList.isNotEmpty()) {
tradeLogic.currentTrade.ourOffers.add(ourOfferList.getRandom())
tradeLogic.currentTrade.theirOffers.add(theirOffer)
} else {
//try to buy tech with money, not spending more than 1/3 of treasury
if (ourGold / 2 >= theirValue)
{
tradeLogic.currentTrade.ourOffers.add(TradeOffer("Gold".tr(), TradeType.Gold, 0, theirValue))
tradeLogic.currentTrade.theirOffers.add(theirOffer)
ourGold -= theirValue
}
}
}
if (tradeLogic.currentTrade.theirOffers.isNotEmpty()) {
tradeLogic.acceptTrade()
}
}
}
private fun chooseTechToResearch(civInfo: CivilizationInfo) {
if (civInfo.tech.techsToResearch.isEmpty()) {
val researchableTechs = GameBasics.Technologies.values.filter { civInfo.tech.canBeResearched(it.name) }
val techToResearch = researchableTechs.groupBy { it.cost }.minBy { it.key }!!.value.getRandom()
civInfo.tech.techsResearched.add(techToResearch.name)
val researchableTechs = GameBasics.Technologies.values.filter { !civInfo.tech.isResearched(it.name) && civInfo.tech.canBeResearched(it.name) }
val techsGroups = researchableTechs.groupBy { it.cost }
val costs = techsGroups.keys.sorted()
val tech: Technology
val techsCheapest = techsGroups[costs[0]]!!
//Do not consider advanced techs if only one tech left in cheapest groupe
if (techsCheapest.size == 1 || costs.size == 1) {
tech = techsCheapest.getRandom()
} else {
//Choose randomly between cheapest and second cheapest groupe
val techsAdvanced = techsGroups[costs[1]]!!
tech = (techsCheapest + techsAdvanced).getRandom()
}
civInfo.tech.techsToResearch.add(tech.name)
}
}
@ -147,4 +215,4 @@ class NextTurnAutomation{
}
}
}
}

View File

@ -2,6 +2,7 @@ package com.unciv.logic.city
import com.badlogic.gdx.graphics.Color
import com.unciv.logic.automation.Automation
import com.unciv.logic.civilization.PlayerType
import com.unciv.models.gamebasics.Building
import com.unciv.models.gamebasics.GameBasics
import com.unciv.models.gamebasics.tr
@ -145,7 +146,6 @@ class CityConstructions {
if (inProgressConstructions[currentConstruction]!! >= productionCost) {
constructionComplete(construction)
}
}
fun constructionComplete(construction: IConstruction) {

View File

@ -8,6 +8,7 @@ interface IConstruction : INamed, ICivilopedia {
fun getGoldCost(adoptedPolicies: HashSet<String>): Int
fun isBuildable(construction: CityConstructions): Boolean
fun postBuildEvent(construction: CityConstructions) // Yes I'm hilarious.
fun canBePurchased(): Boolean
}
@ -35,6 +36,9 @@ open class SpecialConstruction(override var name: String, override val descripti
}
}
override fun canBePurchased(): Boolean {
return false
}
override fun getProductionCost(adoptedPolicies: HashSet<String>): Int {
throw Exception("Impossible!")

View File

@ -91,7 +91,7 @@ class TradeLogic(val ourCivilization:CivilizationInfo, val otherCivilization: Ci
return value
}
}
TradeType.Technology -> return sqrt(GameBasics.Technologies[offer.name]!!.cost.toDouble()).toInt()*10
TradeType.Technology -> return sqrt(GameBasics.Technologies[offer.name]!!.cost.toDouble()).toInt()*20
TradeType.Strategic_Resource -> {
if(otherCivIsRecieving) {
val resources = ourCivilization.getCivResourcesByName()
@ -211,4 +211,4 @@ class TradeLogic(val ourCivilization:CivilizationInfo, val otherCivilization: Ci
transferTrade(ourCivilization,otherCivilization,currentTrade)
transferTrade(otherCivilization,ourCivilization,currentTrade.reverse())
}
}
}

View File

@ -149,6 +149,9 @@ class Building : NamedStats(), IConstruction{
return stats
}
override fun canBePurchased(): Boolean {
return !isWonder
}
override fun getProductionCost(adoptedPolicies: HashSet<String>): Int {
return if (!isWonder && culture != 0f && adoptedPolicies.contains("Piety")) (cost * 0.85).toInt()

View File

@ -81,6 +81,10 @@ class BaseUnit : INamed, IConstruction, ICivilopedia {
return unit
}
override fun canBePurchased(): Boolean {
return true
}
override fun getProductionCost(adoptedPolicies: HashSet<String>): Int = cost
override fun getGoldCost(adoptedPolicies: HashSet<String>): Int {

View File

@ -123,9 +123,7 @@ class ConstructionsTable(val cityScreen: CityScreen) : Table(CameraStageBaseScre
row()
val purchaseConstructionButton: TextButton
if (construction !is SpecialConstruction &&
!(construction is Building && construction.isWonder)) {
if (construction.canBePurchased()) {
val buildingGoldCost = construction.getGoldCost(city.civInfo.policies.getAdoptedPolicies())
purchaseConstructionButton = TextButton("Buy for [$buildingGoldCost] gold".tr(), CameraStageBaseScreen.skin)
purchaseConstructionButton.onClick("coin") {