Added "declare war on X" to available trades

Organized trades by type
This commit is contained in:
Yair Morgenstern 2018-11-27 19:10:27 +02:00
parent 24ccd630da
commit 2cd7e5dc88
5 changed files with 156 additions and 49 deletions

View File

@ -100,5 +100,24 @@ class Automation {
return (sqrt(unitStrength.toDouble()) /*+ sqrt(cityStrength.toDouble())*/).toInt() 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
} }

View File

@ -1,6 +1,7 @@
package com.unciv.logic.trade package com.unciv.logic.trade
import com.unciv.logic.automation.Automation import com.unciv.logic.automation.Automation
import com.unciv.logic.automation.ThreatLevel
import com.unciv.logic.civilization.CivilizationInfo import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.logic.civilization.DiplomaticStatus import com.unciv.logic.civilization.DiplomaticStatus
import com.unciv.models.gamebasics.GameBasics 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() }) for(city in civInfo.cities.filterNot { it.isCapital() })
offers.add(TradeOffer(city.name, TradeType.City, 0)) offers.add(TradeOffer(city.name, TradeType.City, 0))
val civsWeKnowAndTheyDont = civInfo.diplomacy.values.map { it.otherCiv() } val otherCivsWeKnow = civInfo.diplomacy.values.map { it.otherCiv() }
.filter { !otherCivilization.diplomacy.containsKey(it.civName) .filter { it != otherCivilization && !it.isBarbarianCivilization() }
&& it != otherCivilization && !it.isBarbarianCivilization() } val civsWeKnowAndTheyDont = otherCivsWeKnow
.filter { !otherCivilization.diplomacy.containsKey(it.civName) }
for(thirdCiv in civsWeKnowAndTheyDont){ for(thirdCiv in civsWeKnowAndTheyDont){
offers.add(TradeOffer("Introduction to " + thirdCiv.civName, TradeType.Introduction, 0)) 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 return offers
} }
fun isTradeAcceptable(): Boolean { fun isTradeAcceptable(): Boolean {
val sumOfTheirOffers = currentTrade.theirOffers.asSequence() val sumOfTheirOffers = currentTrade.theirOffers.asSequence()
.filter { it.type!= TradeType.Treaty } // since treaties should only be evaluated once for 2 sides .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 else return 1000
} }
TradeType.Introduction -> return 250 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? // Dunno what this is?
else -> return 1000 else -> return 1000
} }
} }
fun evaluatePeaceCostForThem(): Int { fun evaluatePeaceCostForThem(): Int {
val ourCombatStrength = Automation().evaluteCombatStrength(ourCivilization) val ourCombatStrength = Automation().evaluteCombatStrength(ourCivilization)
val theirCombatStrength = Automation().evaluteCombatStrength(otherCivilization) 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()) otherCivilization.diplomacy[ourCivilization.civName]!!.trades.add(currentTrade.reverse())
// instant transfers // instant transfers
fun transfer(us: CivilizationInfo, them: CivilizationInfo, trade: Trade) { fun transferTrade(to: CivilizationInfo, from: CivilizationInfo, trade: Trade) {
for (offer in trade.theirOffers) { for (offer in trade.theirOffers) {
if (offer.type == TradeType.Gold) { if (offer.type == TradeType.Gold) {
us.gold += offer.amount to.gold += offer.amount
them.gold -= offer.amount from.gold -= offer.amount
} }
if (offer.type == TradeType.Technology) { if (offer.type == TradeType.Technology) {
us.tech.techsResearched.add(offer.name) to.tech.techsResearched.add(offer.name)
} }
if(offer.type== TradeType.City){ if(offer.type== TradeType.City){
val city = them.cities.first { it.name==offer.name } val city = from.cities.first { it.name==offer.name }
city.moveToCiv(us) city.moveToCiv(to)
city.getCenterTile().getUnits().forEach { it.movementAlgs().teleportToClosestMoveableTile() } city.getCenterTile().getUnits().forEach { it.movementAlgs().teleportToClosestMoveableTile() }
} }
if(offer.type== TradeType.Treaty){ if(offer.type== TradeType.Treaty){
if(offer.name=="Peace Treaty"){ if(offer.name=="Peace Treaty"){
us.diplomacy[them.civName]!!.diplomaticStatus= DiplomaticStatus.Peace to.diplomacy[from.civName]!!.diplomaticStatus= DiplomaticStatus.Peace
for(unit in us.getCivUnits().filter { it.getTile().getOwner()==them }) for(unit in to.getCivUnits().filter { it.getTile().getOwner()==from })
unit.movementAlgs().teleportToClosestMoveableTile() unit.movementAlgs().teleportToClosestMoveableTile()
} }
} }
if(offer.type==TradeType.Introduction) if(offer.type==TradeType.Introduction)
us.meetCivilization(us.gameInfo.civilizations to.meetCivilization(to.gameInfo.civilizations
.first { it.civName==offer.name.split(" ")[2] }) .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) transferTrade(ourCivilization,otherCivilization,currentTrade)
transfer(otherCivilization,ourCivilization,currentTrade.reverse()) transferTrade(otherCivilization,ourCivilization,currentTrade.reverse())
} }
} }

View File

@ -8,5 +8,6 @@ enum class TradeType{
Strategic_Resource, Strategic_Resource,
Technology, Technology,
Introduction, Introduction,
WarDeclaration,
City City
} }

View File

@ -1,6 +1,7 @@
package com.unciv.ui.cityscreen package com.unciv.ui.cityscreen
import com.badlogic.gdx.graphics.Color import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.scenes.scene2d.Touchable
import com.badlogic.gdx.scenes.scene2d.ui.* import com.badlogic.gdx.scenes.scene2d.ui.*
import com.badlogic.gdx.utils.Align import com.badlogic.gdx.utils.Align
import com.unciv.logic.city.CityInfo 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 toggle = Table(skin) // the show/hide toggler
private val tab = Table() // what holds the information to be shown/hidden private val tab = Table() // what holds the information to be shown/hidden
val innerTable=Table() // the information itself val innerTable=Table() // the information itself
var isOpen=true
init{ init{
toggle.defaults().pad(10f) toggle.defaults().pad(10f)
toggle.touchable=Touchable.enabled
toggle.background(ImageGetter.getBackground(ImageGetter.getBlue())) toggle.background(ImageGetter.getBackground(ImageGetter.getBlue()))
toggle.add("+ $title").apply { actor.setFontSize(24) } toggle.add("+ $title").apply { actor.setFontSize(24) }
toggle.onClick { toggle.onClick {
toggle.clearChildren() if(isOpen) close()
if(tab.isVisible) { else open()
toggle.add("- $title").apply { actor.setFontSize(24) }
tab.clear()
}
else {
toggle.add("+ $title").apply { actor.setFontSize(24) }
tab.add(innerTable)
}
tab.isVisible=!tab.isVisible
} }
add(toggle).row() add(toggle).row()
tab.add(innerTable).pad(10f) tab.add(innerTable).pad(10f)
add(tab) 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() { class BuildingsTable(private val cityScreen: CityScreen) : Table() {

View File

@ -5,6 +5,8 @@ import com.badlogic.gdx.scenes.scene2d.ui.Table
import com.badlogic.gdx.scenes.scene2d.ui.TextButton import com.badlogic.gdx.scenes.scene2d.ui.TextButton
import com.unciv.logic.trade.TradeOffersList import com.unciv.logic.trade.TradeOffersList
import com.unciv.logic.trade.TradeType 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.CameraStageBaseScreen
import com.unciv.ui.utils.disable import com.unciv.ui.utils.disable
import com.unciv.ui.utils.onClick import com.unciv.ui.utils.onClick
@ -14,37 +16,71 @@ import kotlin.math.min
class OffersList(val offers: TradeOffersList, val correspondingOffers: TradeOffersList, class OffersList(val offers: TradeOffersList, val correspondingOffers: TradeOffersList,
val otherCivOffers: TradeOffersList, val otherCivCorrespondingOffers: TradeOffersList, val otherCivOffers: TradeOffersList, val otherCivCorrespondingOffers: TradeOffersList,
val onChange: () -> Unit) : ScrollPane(null) { 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<TradeType, ExpanderTab>()
init { 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() update()
} }
fun update() { fun update() {
table.clear() table.clear()
for(offer in offers.sortedBy { it.type }) { for (offertype in values()) {
var buttonText = offer.name.tr() val offersOfType = offers.filter { it.type == offertype }
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)
}
onChange() if (expanderTabs.containsKey(offertype)) {
update() expanderTabs[offertype]!!.innerTable.clear()
} table.add(expanderTabs[offertype]!!).row()
else tb.disable() // for instance we have negative gold }
table.add(tb).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 widget = table
} }