Can now trade Peace Treaty! Which leads to actual fukken peace!
This commit is contained in:
parent
fa8e8a148d
commit
d8bb0eb9e5
12 changed files with 130 additions and 57 deletions
|
@ -21,8 +21,8 @@ android {
|
|||
applicationId "com.unciv.game"
|
||||
minSdkVersion 14
|
||||
targetSdkVersion 26
|
||||
versionCode 107
|
||||
versionName "2.6.9"
|
||||
versionCode 108
|
||||
versionName "2.6.10"
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
|
|
|
@ -38,7 +38,7 @@ class UnitAutomation{
|
|||
fun containsAttackableEnemy(tile: TileInfo, civInfo: CivilizationInfo): Boolean {
|
||||
val tileCombatant = Battle().getMapCombatantOfTile(tile)
|
||||
if(tileCombatant==null) return false
|
||||
return tileCombatant.getCivilization()!=civInfo// && civInfo.isAtWarWith(tileCombatant.getCivilization())
|
||||
return tileCombatant.getCivilization()!=civInfo && civInfo.isAtWarWith(tileCombatant.getCivilization())
|
||||
}
|
||||
|
||||
class AttackableTile(val tileToAttackFrom:TileInfo, val tileToAttack:TileInfo)
|
||||
|
|
|
@ -103,22 +103,13 @@ class Battle(val gameInfo:GameInfo=UnCivGame.Current.gameInfo) {
|
|||
private fun conquerCity(city: CityInfo, attacker: ICombatant) {
|
||||
val enemyCiv = city.civInfo
|
||||
attacker.getCivilization().addNotification("We have conquered the city of [${city.name}]!",city.location, Color.RED)
|
||||
enemyCiv.cities.remove(city)
|
||||
attacker.getCivilization().cities.add(city)
|
||||
city.civInfo = attacker.getCivilization()
|
||||
city.moveToCiv(attacker.getCivilization())
|
||||
city.health = city.getMaxHealth() / 2 // I think that cities recover to half health when conquered?
|
||||
city.getCenterTile().apply {
|
||||
militaryUnit = null
|
||||
if(civilianUnit!=null) captureCivilianUnit(attacker,MapUnitCombatant(civilianUnit!!))
|
||||
}
|
||||
|
||||
city.expansion.cultureStored = 0
|
||||
city.expansion.reset()
|
||||
|
||||
// now that the tiles have changed, we need to reassign population
|
||||
city.workedTiles.filterNot { city.tiles.contains(it) }
|
||||
.forEach { city.workedTiles.remove(it); city.population.autoAssignPopulation() }
|
||||
|
||||
if(city.cityConstructions.isBuilt("Palace")){
|
||||
city.cityConstructions.builtBuildings.remove("Palace")
|
||||
if(enemyCiv.isDefeated()) {
|
||||
|
@ -131,12 +122,7 @@ class Battle(val gameInfo:GameInfo=UnCivGame.Current.gameInfo) {
|
|||
}
|
||||
}
|
||||
|
||||
// Remove all national wonders when conquering a city
|
||||
for(building in city.cityConstructions.getBuiltBuildings().filter { it.requiredBuildingInAllCities!=null })
|
||||
city.cityConstructions.builtBuildings.remove(building.name)
|
||||
|
||||
(attacker as MapUnitCombatant).unit.moveToTile(city.getCenterTile())
|
||||
city.civInfo.gameInfo.updateTilesToCities()
|
||||
}
|
||||
|
||||
fun getMapCombatantOfTile(tile:TileInfo): ICombatant? {
|
||||
|
|
|
@ -25,7 +25,7 @@ class CityCombatant(val city: CityInfo) : ICombatant {
|
|||
return getCityStrength()
|
||||
}
|
||||
|
||||
private fun getCityStrength(): Int { // Civ fanatics forum, from a modder who went through the original code
|
||||
fun getCityStrength(): Int { // Civ fanatics forum, from a modder who went through the original code
|
||||
var strength = 8f
|
||||
if(city.isCapital()) strength+=2.5f
|
||||
strength += (city.population.population/5) * 2 // Each 5 pop gives 2 defence
|
||||
|
|
|
@ -149,6 +149,25 @@ class CityInfo {
|
|||
|
||||
fun isCapital() = cityConstructions.isBuilt("Palace")
|
||||
|
||||
fun moveToCiv(newCivInfo: CivilizationInfo){
|
||||
civInfo.cities.remove(this)
|
||||
newCivInfo.cities.add(this)
|
||||
civInfo = newCivInfo
|
||||
|
||||
expansion.cultureStored = 0
|
||||
expansion.reset()
|
||||
|
||||
// now that the tiles have changed, we need to reassign population
|
||||
workedTiles.filterNot { tiles.contains(it) }
|
||||
.forEach { workedTiles.remove(it); population.autoAssignPopulation() }
|
||||
|
||||
// Remove all national wonders
|
||||
for(building in cityConstructions.getBuiltBuildings().filter { it.requiredBuildingInAllCities!=null })
|
||||
cityConstructions.builtBuildings.remove(building.name)
|
||||
|
||||
civInfo.gameInfo.updateTilesToCities()
|
||||
}
|
||||
|
||||
internal fun getMaxHealth(): Int {
|
||||
return 200 + cityConstructions.getBuiltBuildings().sumBy { it.cityHealth }
|
||||
}
|
||||
|
|
|
@ -289,12 +289,17 @@ class CivilizationInfo {
|
|||
else return TechEra.Ancient
|
||||
}
|
||||
|
||||
// fun isAtWarWith(otherCiv:CivilizationInfo): Boolean {
|
||||
// if(otherCiv.isBarbarianCivilization() || isBarbarianCivilization()) return true
|
||||
// if(!diplomacy.containsKey(otherCiv.civName)) // not encountered yet
|
||||
// return false
|
||||
// return diplomacy[otherCiv.civName]!!.diplomaticStatus == DiplomaticStatus.War
|
||||
// }
|
||||
fun isAtWarWith(otherCiv:CivilizationInfo): Boolean {
|
||||
if(otherCiv.isBarbarianCivilization() || isBarbarianCivilization()) return true
|
||||
if(!diplomacy.containsKey(otherCiv.civName)) // not encountered yet
|
||||
return false
|
||||
return diplomacy[otherCiv.civName]!!.diplomaticStatus == DiplomaticStatus.War
|
||||
}
|
||||
|
||||
fun canEnterTiles(otherCiv: CivilizationInfo): Boolean {
|
||||
if(isAtWarWith(otherCiv)) return true
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -22,7 +22,6 @@ class DiplomacyManager() {
|
|||
otherCivName=OtherCivName
|
||||
}
|
||||
|
||||
// var status:DiplomaticStatus = DiplomaticStatus.War
|
||||
var trades = ArrayList<Trade>()
|
||||
|
||||
fun goldPerTurn():Int{
|
||||
|
@ -80,9 +79,9 @@ class DiplomacyManager() {
|
|||
|
||||
fun otherCiv() = civInfo.gameInfo.civilizations.first{it.civName==otherCivName}
|
||||
|
||||
//var diplomaticStatus = DiplomaticStatus.War
|
||||
// fun declareWar(){
|
||||
// diplomaticStatus = DiplomaticStatus.War
|
||||
// otherCiv().diplomacy[civInfo.civName]!!.diplomaticStatus = DiplomaticStatus.War
|
||||
// }
|
||||
var diplomaticStatus = DiplomaticStatus.War
|
||||
fun declareWar(){
|
||||
diplomaticStatus = DiplomaticStatus.War
|
||||
otherCiv().diplomacy[civInfo.civName]!!.diplomaticStatus = DiplomaticStatus.War
|
||||
}
|
||||
}
|
|
@ -189,7 +189,10 @@ class MapUnit {
|
|||
* Designates whether we can walk to the tile - without attacking
|
||||
*/
|
||||
fun canMoveTo(tile: TileInfo): Boolean {
|
||||
if(tile.isCityCenter() && tile.getOwner()!!.civName!=owner) return false
|
||||
val tileOwner = tile.getOwner()
|
||||
if(tileOwner!=null && tileOwner.civName!=owner) {
|
||||
if (tile.isCityCenter() || !civInfo.canEnterTiles(tileOwner)) return false
|
||||
}
|
||||
if (getBaseUnit().unitType== UnitType.Civilian)
|
||||
return tile.civilianUnit==null && (tile.militaryUnit==null || tile.militaryUnit!!.owner==owner)
|
||||
else return tile.militaryUnit==null && (tile.civilianUnit==null || tile.civilianUnit!!.owner==owner)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package com.unciv.logic.map
|
||||
|
||||
import com.badlogic.gdx.math.Vector2
|
||||
import com.unciv.models.gamebasics.unit.UnitType
|
||||
|
||||
class UnitMovementAlgorithms(val unit:MapUnit) {
|
||||
val tileMap = unit.getTile().tileMap
|
||||
|
@ -167,14 +168,19 @@ class UnitMovementAlgorithms(val unit:MapUnit) {
|
|||
throw Exception("We couldn't get the path between the two tiles")
|
||||
}
|
||||
|
||||
// fun moveToClosestMoveableTile(){
|
||||
// val unitCurrentTile = unit.getTile()
|
||||
// var allowedTile:TileInfo? = null
|
||||
// var distance=0
|
||||
// while(allowedTile==null){
|
||||
// distance++
|
||||
// allowedTile = tileMap.tilesat
|
||||
// }
|
||||
// }
|
||||
fun teleportToClosestMoveableTile(){
|
||||
val unitCurrentTilePosition = unit.getTile().position
|
||||
var allowedTile:TileInfo? = null
|
||||
var distance=0
|
||||
while(allowedTile==null){
|
||||
distance++
|
||||
allowedTile = tileMap.getTilesAtDistance(unitCurrentTilePosition,distance)
|
||||
.firstOrNull{unit.canMoveTo(it)}
|
||||
}
|
||||
unit.removeFromTile() // we "teleport" them away
|
||||
if(unit.getBaseUnit().unitType==UnitType.Civilian)
|
||||
allowedTile.civilianUnit=unit
|
||||
else allowedTile.militaryUnit=unit
|
||||
}
|
||||
|
||||
}
|
|
@ -10,6 +10,7 @@ import com.unciv.ui.utils.tr
|
|||
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) }
|
||||
init {
|
||||
|
@ -32,6 +33,11 @@ class OffersList(val offers: TradeOffersList, val correspondingOffers: TradeOffe
|
|||
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()
|
||||
update()
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
package com.unciv.logic.trade
|
||||
|
||||
enum class TradeType{
|
||||
Luxury_Resource,
|
||||
Strategic_Resource,
|
||||
Gold,
|
||||
Gold_Per_Turn,
|
||||
City,
|
||||
Treaty,
|
||||
Luxury_Resource,
|
||||
Strategic_Resource,
|
||||
Technology,
|
||||
Treaty
|
||||
City
|
||||
}
|
|
@ -4,7 +4,9 @@ import com.badlogic.gdx.scenes.scene2d.ui.Label
|
|||
import com.badlogic.gdx.scenes.scene2d.ui.Table
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.TextButton
|
||||
import com.unciv.UnCivGame
|
||||
import com.unciv.logic.battle.CityCombatant
|
||||
import com.unciv.logic.civilization.CivilizationInfo
|
||||
import com.unciv.logic.civilization.DiplomaticStatus
|
||||
import com.unciv.logic.trade.OffersList
|
||||
import com.unciv.logic.trade.Trade
|
||||
import com.unciv.logic.trade.TradeOffersList
|
||||
|
@ -12,6 +14,7 @@ import com.unciv.logic.trade.TradeType
|
|||
import com.unciv.models.gamebasics.GameBasics
|
||||
import com.unciv.models.gamebasics.tile.ResourceType
|
||||
import com.unciv.ui.utils.*
|
||||
import kotlin.math.max
|
||||
import kotlin.math.sqrt
|
||||
|
||||
|
||||
|
@ -45,12 +48,18 @@ class TradeScreen(val otherCivilization: CivilizationInfo) : CameraStageBaseScre
|
|||
tradeText.setText("What do you have in mind?".tr())
|
||||
}
|
||||
|
||||
val ourAvailableOffersTable = OffersList(ourAvailableOffers, currentTrade.ourOffers) { onChange() }
|
||||
val ourOffersTable = OffersList(currentTrade.ourOffers, ourAvailableOffers) { onChange() }
|
||||
val theirOffersTable = OffersList(currentTrade.theirOffers, theirAvailableOffers) { onChange() }
|
||||
val theirAvailableOffersTable = OffersList(theirAvailableOffers, currentTrade.theirOffers) { onChange() }
|
||||
val ourAvailableOffersTable = OffersList(ourAvailableOffers, currentTrade.ourOffers,
|
||||
theirAvailableOffers, currentTrade.theirOffers) { onChange() }
|
||||
val ourOffersTable = OffersList(currentTrade.ourOffers, ourAvailableOffers,
|
||||
currentTrade.theirOffers, theirAvailableOffers) { onChange() }
|
||||
val theirOffersTable = OffersList(currentTrade.theirOffers, theirAvailableOffers,
|
||||
currentTrade.ourOffers, ourAvailableOffers) { onChange() }
|
||||
val theirAvailableOffersTable = OffersList(theirAvailableOffers, currentTrade.theirOffers,
|
||||
ourAvailableOffers, currentTrade.ourOffers) { onChange() }
|
||||
|
||||
init {
|
||||
val peaceCost = evaluatePeaceCostForThem()
|
||||
|
||||
val closeButton = TextButton("Close".tr(), skin)
|
||||
closeButton.addClickListener { UnCivGame.Current.setWorldScreen() }
|
||||
closeButton.y = stage.height - closeButton.height - 5
|
||||
|
@ -90,9 +99,15 @@ class TradeScreen(val otherCivilization: CivilizationInfo) : CameraStageBaseScre
|
|||
}
|
||||
if(offer.type==TradeType.City){
|
||||
val city = them.cities.first { it.name==offer.name }
|
||||
us.cities.add(city)
|
||||
them.cities.remove(city)
|
||||
|
||||
city.moveToCiv(us)
|
||||
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 })
|
||||
unit.movementAlgs().teleportToClosestMoveableTile()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -138,6 +153,8 @@ class TradeScreen(val otherCivilization: CivilizationInfo) : CameraStageBaseScre
|
|||
|
||||
fun getAvailableOffers(civInfo: CivilizationInfo, otherCivilization: CivilizationInfo): TradeOffersList {
|
||||
val offers = TradeOffersList()
|
||||
if(civInfo.isAtWarWith(otherCivilization))
|
||||
offers.add(TradeOffer("Peace Treaty",TradeType.Treaty,20,1))
|
||||
for(entry in civInfo.getCivResources().filterNot { it.key.resourceType == ResourceType.Bonus }) {
|
||||
val resourceTradeType = if(entry.key.resourceType==ResourceType.Luxury) TradeType.Luxury_Resource
|
||||
else TradeType.Strategic_Resource
|
||||
|
@ -150,13 +167,14 @@ class TradeScreen(val otherCivilization: CivilizationInfo) : CameraStageBaseScre
|
|||
}
|
||||
offers.add(TradeOffer("Gold".tr(), TradeType.Gold,0,civInfo.gold))
|
||||
offers.add(TradeOffer("Gold per turn".tr(), TradeType.Gold_Per_Turn,30,civInfo.getStatsForNextTurn().gold.toInt()))
|
||||
// for(city in civInfo.cities.filterNot { it.isCapital() })
|
||||
// offers.add(TradeOffer(city.name,TradeType.City,0,1))
|
||||
for(city in civInfo.cities.filterNot { it.isCapital() })
|
||||
offers.add(TradeOffer(city.name,TradeType.City,0,1))
|
||||
return offers
|
||||
}
|
||||
|
||||
fun isTradeAcceptable(trade: Trade): Boolean {
|
||||
val sumOfTheirOffers = trade.theirOffers.map { evaluateOffer(it,false) }.sum()
|
||||
val sumOfTheirOffers = trade.theirOffers.filter { it.type!=TradeType.Treaty } // since treaties should only be evaluated once for 2 sides
|
||||
.map { evaluateOffer(it,false) }.sum()
|
||||
val sumOfOurOffers = trade.ourOffers.map { evaluateOffer(it,true)}.sum()
|
||||
return sumOfOurOffers >= sumOfTheirOffers
|
||||
}
|
||||
|
@ -180,18 +198,49 @@ class TradeScreen(val otherCivilization: CivilizationInfo) : CameraStageBaseScre
|
|||
}
|
||||
|
||||
}
|
||||
TradeType.Technology -> return sqrt(GameBasics.Technologies[offer.name]!!.cost.toDouble()).toInt()*10 // gold cost is science cost
|
||||
TradeType.Technology -> return sqrt(GameBasics.Technologies[offer.name]!!.cost.toDouble()).toInt()*10
|
||||
TradeType.Strategic_Resource -> return 50 * offer.amount
|
||||
TradeType.City -> {
|
||||
val civ = if(otherCivIsRecieving) civInfo else otherCivilization
|
||||
val city = civ.cities.first { it.name==offer.name }
|
||||
val stats = city.cityStats.currentCityStats
|
||||
val sumOfStats = stats.culture+stats.gold+stats.science+stats.production+stats.happiness+stats.food
|
||||
return sumOfStats.toInt() * 10
|
||||
return sumOfStats.toInt() * 100
|
||||
}
|
||||
TradeType.Treaty -> {
|
||||
if(offer.name=="Peace Treaty")
|
||||
return evaluatePeaceCostForThem() // Since it will be evaluated twice, once when they evaluate our offer and once when they evaluate theirs
|
||||
else return 1000
|
||||
}
|
||||
// Dunno what this is?
|
||||
else -> return 1000
|
||||
}
|
||||
}
|
||||
|
||||
fun evaluteCombatStrength(civInfo: CivilizationInfo): Int {
|
||||
// Since units become exponentially stronger per combat strength increase, we square em all
|
||||
fun square(x:Int) = x*x
|
||||
val unitStrength = civInfo.getCivUnits().map { square(max(it.getBaseUnit().strength,it.getBaseUnit().rangedStrength)) }.sum()
|
||||
val cityStrength = civInfo.cities.map { square(CityCombatant(it).getCityStrength()) }.sum()
|
||||
return (sqrt(unitStrength.toDouble()) /*+ sqrt(cityStrength.toDouble())*/).toInt()
|
||||
}
|
||||
|
||||
fun evaluatePeaceCostForThem(): Int {
|
||||
val ourCombatStrength = evaluteCombatStrength(civInfo)
|
||||
val theirCombatStrength = evaluteCombatStrength(otherCivilization)
|
||||
if(ourCombatStrength==theirCombatStrength) return 0
|
||||
if(ourCombatStrength==0) return 1000
|
||||
if(theirCombatStrength==0) return -1000 // Chumps got no cities or units
|
||||
if(ourCombatStrength>theirCombatStrength){
|
||||
val absoluteAdvantage = ourCombatStrength-theirCombatStrength
|
||||
val percentageAdvantage = absoluteAdvantage / theirCombatStrength.toFloat()
|
||||
return (absoluteAdvantage*percentageAdvantage).toInt() * 10
|
||||
}
|
||||
else{
|
||||
val absoluteAdvantage = theirCombatStrength-ourCombatStrength
|
||||
val percentageAdvantage = absoluteAdvantage / ourCombatStrength.toFloat()
|
||||
return -(absoluteAdvantage*percentageAdvantage).toInt() * 10
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue