From 2cd7e5dc880de571359c8fcc0d1bfc42848ce0f3 Mon Sep 17 00:00:00 2001 From: Yair Morgenstern Date: Tue, 27 Nov 2018 19:10:27 +0200 Subject: [PATCH] Added "declare war on X" to available trades Organized trades by type --- .../com/unciv/logic/automation/Automation.kt | 19 +++++ core/src/com/unciv/logic/trade/TradeLogic.kt | 72 ++++++++++++---- core/src/com/unciv/logic/trade/TradeType.kt | 1 + .../com/unciv/ui/cityscreen/BuildingsTable.kt | 31 ++++--- core/src/com/unciv/ui/trade/OffersList.kt | 82 +++++++++++++------ 5 files changed, 156 insertions(+), 49 deletions(-) diff --git a/core/src/com/unciv/logic/automation/Automation.kt b/core/src/com/unciv/logic/automation/Automation.kt index cde7b34cee..5da866a8bc 100644 --- a/core/src/com/unciv/logic/automation/Automation.kt +++ b/core/src/com/unciv/logic/automation/Automation.kt @@ -100,5 +100,24 @@ class Automation { return (sqrt(unitStrength.toDouble()) /*+ sqrt(cityStrength.toDouble())*/).toInt() } + fun threatAssessment(assessor:CivilizationInfo, assessed: CivilizationInfo): ThreatLevel { + val powerLevelComparison = evaluteCombatStrength(assessed)/evaluteCombatStrength(assessor).toFloat() + when{ + powerLevelComparison>2 -> return ThreatLevel.VeryHigh + powerLevelComparison>1.5f -> return ThreatLevel.High + powerLevelComparison<(1/1.5f) -> return ThreatLevel.Low + powerLevelComparison<0.5f -> return ThreatLevel.VeryLow + else -> return ThreatLevel.Medium + } + } + +} + +enum class ThreatLevel{ + VeryLow, + Low, + Medium, + High, + VeryHigh } diff --git a/core/src/com/unciv/logic/trade/TradeLogic.kt b/core/src/com/unciv/logic/trade/TradeLogic.kt index 00166d4e12..d43afe2aba 100644 --- a/core/src/com/unciv/logic/trade/TradeLogic.kt +++ b/core/src/com/unciv/logic/trade/TradeLogic.kt @@ -1,6 +1,7 @@ package com.unciv.logic.trade import com.unciv.logic.automation.Automation +import com.unciv.logic.automation.ThreatLevel import com.unciv.logic.civilization.CivilizationInfo import com.unciv.logic.civilization.DiplomaticStatus import com.unciv.models.gamebasics.GameBasics @@ -34,17 +35,25 @@ class TradeLogic(val ourCivilization:CivilizationInfo, val otherCivilization: Ci for(city in civInfo.cities.filterNot { it.isCapital() }) offers.add(TradeOffer(city.name, TradeType.City, 0)) - val civsWeKnowAndTheyDont = civInfo.diplomacy.values.map { it.otherCiv() } - .filter { !otherCivilization.diplomacy.containsKey(it.civName) - && it != otherCivilization && !it.isBarbarianCivilization() } + val otherCivsWeKnow = civInfo.diplomacy.values.map { it.otherCiv() } + .filter { it != otherCivilization && !it.isBarbarianCivilization() } + val civsWeKnowAndTheyDont = otherCivsWeKnow + .filter { !otherCivilization.diplomacy.containsKey(it.civName) } for(thirdCiv in civsWeKnowAndTheyDont){ offers.add(TradeOffer("Introduction to " + thirdCiv.civName, TradeType.Introduction, 0)) } + val civsWeBothKnow = otherCivsWeKnow + .filter { otherCivilization.diplomacy.containsKey(it.civName) } + val civsWeArentAtWarWith = civsWeBothKnow + .filter { civInfo.diplomacy[it.civName]!!.diplomaticStatus==DiplomaticStatus.Peace } + for(thirdCiv in civsWeArentAtWarWith){ + offers.add(TradeOffer("Declare war on "+thirdCiv.civName,TradeType.WarDeclaration,0)) + } + return offers } - fun isTradeAcceptable(): Boolean { val sumOfTheirOffers = currentTrade.theirOffers.asSequence() .filter { it.type!= TradeType.Treaty } // since treaties should only be evaluated once for 2 sides @@ -109,12 +118,39 @@ class TradeLogic(val ourCivilization:CivilizationInfo, val otherCivilization: Ci else return 1000 } TradeType.Introduction -> return 250 + TradeType.WarDeclaration -> { + val nameOfCivToDeclareWarOn = offer.name.split(' ').last() + val civToDeclareWarOn = ourCivilization.gameInfo.civilizations.first { it.civName==nameOfCivToDeclareWarOn } + val threatToThem = Automation().threatAssessment(otherCivilization,civToDeclareWarOn) + + if(!otherCivIsRecieving) { // we're getting this from them, that is, they're declaring war + when (threatToThem) { + ThreatLevel.VeryLow -> return 100 + ThreatLevel.Low -> return 250 + ThreatLevel.Medium -> return 500 + ThreatLevel.High -> return 1000 + ThreatLevel.VeryHigh -> return 10000 // no way + } + } + else{ + if(otherCivilization.diplomacy[nameOfCivToDeclareWarOn]!!.diplomaticStatus==DiplomaticStatus.War){ + when (threatToThem) { + ThreatLevel.VeryLow -> return 0 + ThreatLevel.Low -> return 0 + ThreatLevel.Medium -> return 100 + ThreatLevel.High -> return 500 + ThreatLevel.VeryHigh -> return 1000 + } + } + else return 0 // why should we pay you to go fight someone...? + } + + } // Dunno what this is? else -> return 1000 } } - fun evaluatePeaceCostForThem(): Int { val ourCombatStrength = Automation().evaluteCombatStrength(ourCivilization) val theirCombatStrength = Automation().evaluteCombatStrength(otherCivilization) @@ -139,34 +175,38 @@ class TradeLogic(val ourCivilization:CivilizationInfo, val otherCivilization: Ci otherCivilization.diplomacy[ourCivilization.civName]!!.trades.add(currentTrade.reverse()) // instant transfers - fun transfer(us: CivilizationInfo, them: CivilizationInfo, trade: Trade) { + fun transferTrade(to: CivilizationInfo, from: CivilizationInfo, trade: Trade) { for (offer in trade.theirOffers) { if (offer.type == TradeType.Gold) { - us.gold += offer.amount - them.gold -= offer.amount + to.gold += offer.amount + from.gold -= offer.amount } if (offer.type == TradeType.Technology) { - us.tech.techsResearched.add(offer.name) + to.tech.techsResearched.add(offer.name) } if(offer.type== TradeType.City){ - val city = them.cities.first { it.name==offer.name } - city.moveToCiv(us) + val city = from.cities.first { it.name==offer.name } + city.moveToCiv(to) city.getCenterTile().getUnits().forEach { it.movementAlgs().teleportToClosestMoveableTile() } } if(offer.type== TradeType.Treaty){ if(offer.name=="Peace Treaty"){ - us.diplomacy[them.civName]!!.diplomaticStatus= DiplomaticStatus.Peace - for(unit in us.getCivUnits().filter { it.getTile().getOwner()==them }) + to.diplomacy[from.civName]!!.diplomaticStatus= DiplomaticStatus.Peace + for(unit in to.getCivUnits().filter { it.getTile().getOwner()==from }) unit.movementAlgs().teleportToClosestMoveableTile() } } if(offer.type==TradeType.Introduction) - us.meetCivilization(us.gameInfo.civilizations + to.meetCivilization(to.gameInfo.civilizations .first { it.civName==offer.name.split(" ")[2] }) + if(offer.type==TradeType.WarDeclaration){ + val nameOfCivToDeclareWarOn = offer.name.split(' ').last() + from.diplomacy[nameOfCivToDeclareWarOn]!!.declareWar() + } } } - transfer(ourCivilization,otherCivilization,currentTrade) - transfer(otherCivilization,ourCivilization,currentTrade.reverse()) + transferTrade(ourCivilization,otherCivilization,currentTrade) + transferTrade(otherCivilization,ourCivilization,currentTrade.reverse()) } } \ No newline at end of file diff --git a/core/src/com/unciv/logic/trade/TradeType.kt b/core/src/com/unciv/logic/trade/TradeType.kt index 4b01b7d62a..185ecbed3d 100644 --- a/core/src/com/unciv/logic/trade/TradeType.kt +++ b/core/src/com/unciv/logic/trade/TradeType.kt @@ -8,5 +8,6 @@ enum class TradeType{ Strategic_Resource, Technology, Introduction, + WarDeclaration, City } \ No newline at end of file diff --git a/core/src/com/unciv/ui/cityscreen/BuildingsTable.kt b/core/src/com/unciv/ui/cityscreen/BuildingsTable.kt index b8a19192ee..48d3678d66 100644 --- a/core/src/com/unciv/ui/cityscreen/BuildingsTable.kt +++ b/core/src/com/unciv/ui/cityscreen/BuildingsTable.kt @@ -1,6 +1,7 @@ package com.unciv.ui.cityscreen import com.badlogic.gdx.graphics.Color +import com.badlogic.gdx.scenes.scene2d.Touchable import com.badlogic.gdx.scenes.scene2d.ui.* import com.badlogic.gdx.utils.Align import com.unciv.logic.city.CityInfo @@ -13,27 +14,37 @@ class ExpanderTab(private val title:String,skin: Skin):Table(skin){ private val toggle = Table(skin) // the show/hide toggler private val tab = Table() // what holds the information to be shown/hidden val innerTable=Table() // the information itself + var isOpen=true init{ toggle.defaults().pad(10f) + toggle.touchable=Touchable.enabled toggle.background(ImageGetter.getBackground(ImageGetter.getBlue())) toggle.add("+ $title").apply { actor.setFontSize(24) } toggle.onClick { - toggle.clearChildren() - if(tab.isVisible) { - toggle.add("- $title").apply { actor.setFontSize(24) } - tab.clear() - } - else { - toggle.add("+ $title").apply { actor.setFontSize(24) } - tab.add(innerTable) - } - tab.isVisible=!tab.isVisible + if(isOpen) close() + else open() } add(toggle).row() tab.add(innerTable).pad(10f) add(tab) } + + fun close(){ + if(!isOpen) return + toggle.clearChildren() + toggle.add("- $title").apply { actor.setFontSize(24) } + tab.clear() + isOpen=false + } + + fun open(){ + if(isOpen) return + toggle.clearChildren() + toggle.add("+ $title").apply { actor.setFontSize(24) } + tab.add(innerTable) + isOpen=true + } } class BuildingsTable(private val cityScreen: CityScreen) : Table() { diff --git a/core/src/com/unciv/ui/trade/OffersList.kt b/core/src/com/unciv/ui/trade/OffersList.kt index 3ca2c7ff90..fcd6a335ad 100644 --- a/core/src/com/unciv/ui/trade/OffersList.kt +++ b/core/src/com/unciv/ui/trade/OffersList.kt @@ -5,6 +5,8 @@ import com.badlogic.gdx.scenes.scene2d.ui.Table import com.badlogic.gdx.scenes.scene2d.ui.TextButton import com.unciv.logic.trade.TradeOffersList import com.unciv.logic.trade.TradeType +import com.unciv.logic.trade.TradeType.* +import com.unciv.ui.cityscreen.ExpanderTab import com.unciv.ui.utils.CameraStageBaseScreen import com.unciv.ui.utils.disable import com.unciv.ui.utils.onClick @@ -14,37 +16,71 @@ import kotlin.math.min class OffersList(val offers: TradeOffersList, val correspondingOffers: TradeOffersList, val otherCivOffers: TradeOffersList, val otherCivCorrespondingOffers: TradeOffersList, val onChange: () -> Unit) : ScrollPane(null) { - val table= Table(CameraStageBaseScreen.skin).apply { defaults().pad(5f) } + val table = Table(CameraStageBaseScreen.skin).apply { defaults().pad(5f) } + val tradesToNotHaveNumbers = listOf(Technology, City, + Introduction, Treaty, WarDeclaration) + + val expanderTabs = HashMap() + init { + for (offertype in values()) { + val labelName = when(offertype){ + Gold, Gold_Per_Turn, Treaty,Introduction -> "" + Luxury_Resource -> "Luxury resources" + Strategic_Resource -> "Luxury resources" + Technology -> "Technologies" + WarDeclaration -> "Declarations of war" + City -> "Cities" + } + val offersOfType = offers.filter { it.type == offertype } + if (labelName!="" && offersOfType.any()) { + expanderTabs[offertype] = ExpanderTab(labelName, CameraStageBaseScreen.skin) + expanderTabs[offertype]!!.close() + expanderTabs[offertype]!!.innerTable.defaults().pad(5f) + } + } update() } fun update() { table.clear() - for(offer in offers.sortedBy { it.type }) { - var buttonText = offer.name.tr() - if(offer.type !in listOf(TradeType.Technology, TradeType.City, TradeType.Introduction, TradeType.Treaty)) buttonText+=" ("+offer.amount+")" - if(offer.duration>1) buttonText+="\n"+offer.duration+" {turns}".tr() - val tb = TextButton(buttonText, CameraStageBaseScreen.skin) - val amountPerClick = - if(offer.type== TradeType.Gold) 50 - else 1 - if(offer.amount>0) - tb.onClick { - val amountTransferred = min(amountPerClick, offer.amount) - offers += offer.copy(amount = -amountTransferred) - correspondingOffers += offer.copy(amount = amountTransferred) - if(offer.type== TradeType.Treaty) { // this goes both ways, so it doesn't matter which side you click - otherCivOffers += offer.copy(amount = -amountTransferred) - otherCivCorrespondingOffers += offer.copy(amount = amountTransferred) - } + for (offertype in values()) { + val offersOfType = offers.filter { it.type == offertype } - onChange() - update() - } - else tb.disable() // for instance we have negative gold - table.add(tb).row() + if (expanderTabs.containsKey(offertype)) { + expanderTabs[offertype]!!.innerTable.clear() + table.add(expanderTabs[offertype]!!).row() + } + + for (offer in offersOfType) { + var buttonText = offer.name.tr() + if (offer.type !in tradesToNotHaveNumbers) buttonText += " (" + offer.amount + ")" + if (offer.duration > 1) buttonText += "\n" + offer.duration + " {turns}".tr() + val tradeButton = TextButton(buttonText, CameraStageBaseScreen.skin) + val amountPerClick = + if (offer.type == Gold) 50 + else 1 + if (offer.amount > 0) + tradeButton.onClick { + val amountTransferred = min(amountPerClick, offer.amount) + offers += offer.copy(amount = -amountTransferred) + correspondingOffers += offer.copy(amount = amountTransferred) + if (offer.type == Treaty) { // this goes both ways, so it doesn't matter which side you click + otherCivOffers += offer.copy(amount = -amountTransferred) + otherCivCorrespondingOffers += offer.copy(amount = amountTransferred) + } + + onChange() + update() + } + else tradeButton.disable() // for instance we have negative gold + + + if (expanderTabs.containsKey(offertype)) + expanderTabs[offertype]!!.innerTable.add(tradeButton).row() + else table.add(tradeButton).row() + } } widget = table }