Fix Sweden not being able to gift great people to city states (#6690)

This commit is contained in:
Timo T 2022-05-05 08:09:15 +02:00 committed by GitHub
parent 342367c72c
commit cf6543bc29
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 228 additions and 161 deletions

View File

@ -817,7 +817,7 @@ object UnitActions {
if (getGiftAction != null) actionList += getGiftAction
}
private fun getGiftAction(unit: MapUnit, tile: TileInfo): UnitAction? {
fun getGiftAction(unit: MapUnit, tile: TileInfo): UnitAction? {
val recipient = tile.getOwner()
// We need to be in another civs territory.
if (recipient == null || recipient.isCurrentPlayer()) return null
@ -825,7 +825,7 @@ object UnitActions {
// City States only take military units (and units specifically allowed by uniques)
if (recipient.isCityState()) {
if (!unit.matchesFilter("Military")
&& unit.getMatchingUniques("Gain [] Influence with a [] gift to a City-State")
&& unit.getMatchingUniques(UniqueType.GainInfluenceWithUnitGiftToCityState, checkCivInfoUniques = true)
.none { unit.matchesFilter(it.params[1]) }
) return null
}
@ -837,7 +837,7 @@ object UnitActions {
val giftAction = {
if (recipient.isCityState()) {
for (unique in unit.civInfo.getMatchingUniques(UniqueType.GainInfluenceWithUnitGiftToCityState)) {
for (unique in unit.getMatchingUniques(UniqueType.GainInfluenceWithUnitGiftToCityState, checkCivInfoUniques = true)) {
if (unit.matchesFilter(unique.params[1])) {
recipient.getDiplomacyManager(unit.civInfo)
.addInfluence(unique.params[0].toFloat() - 5f)

View File

@ -6,8 +6,8 @@ plugins {
}
java {
sourceCompatibility = JavaVersion.VERSION_1_7
targetCompatibility = JavaVersion.VERSION_1_7
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
tasks {

View File

@ -3,15 +3,6 @@ package com.unciv.uniques
import com.badlogic.gdx.math.Vector2
import com.unciv.Constants
import com.unciv.UncivGame
import com.unciv.logic.GameInfo
import com.unciv.logic.city.CityInfo
import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.logic.map.MapUnit
import com.unciv.logic.map.TileInfo
import com.unciv.logic.map.TileMap
import com.unciv.models.metadata.GameSettings
import com.unciv.models.ruleset.*
import com.unciv.models.ruleset.unique.UniqueType
import com.unciv.models.stats.Stats
import com.unciv.testing.GdxTestRunner
@ -24,115 +15,21 @@ import org.junit.runner.RunWith
@RunWith(GdxTestRunner::class)
class GlobalUniquesTests {
private var ruleSet = Ruleset()
private var gameInfo = GameInfo()
private var tileMap = TileMap()
private lateinit var game: TestGame
companion object {
var objectsCreated = 0
}
@Before
fun initTheWorld() {
// Set UncivGame.Current so that debug variables are initialized
UncivGame.Current = UncivGame("Test")
// And the settings can be reached for the locale used in .tr()
UncivGame.Current.settings = GameSettings()
// Create a new ruleset we can easily edit, and set the important variables of gameInfo
RulesetCache.loadRulesets()
ruleSet = RulesetCache.getVanillaRuleset()
gameInfo.ruleSet = ruleSet
gameInfo.difficultyObject = ruleSet.difficulties["Prince"]!!
// Create a tilemap, needed for city centers
gameInfo.tileMap = tileMap
game = TestGame()
}
private fun addTile(terrain: String, position: Vector2 = Vector2.Zero, features: List<String> = listOf()): TileInfo {
val tile = TileInfo()
tile.ruleset = ruleSet
tile.baseTerrain = terrain
for (feature in features) {
tile.addTerrainFeature(feature)
}
tile.tileMap = tileMap
tile.position = position
tile.setTransients()
while (tileMap.tileMatrix.size < position.x + 1)
tileMap.tileMatrix.add(ArrayList())
while (tileMap.tileMatrix[position.x.toInt()].size < position.y + 1)
tileMap.tileMatrix[position.x.toInt()].add(null)
tileMap.tileMatrix[position.x.toInt()][position.y.toInt()] = tile
return tile
}
private fun addCiv(): CivilizationInfo {
val nationName = "Nation-$objectsCreated"
objectsCreated++
ruleSet.nations[nationName] = Nation().apply {
name = nationName
cities = arrayListOf("The Capital")
}
val civInfo = CivilizationInfo()
civInfo.nation = ruleSet.nations[nationName]!!
civInfo.gameInfo = gameInfo
civInfo.civName = nationName
civInfo.setTransients()
gameInfo.civilizations.add(civInfo)
return civInfo
}
private fun addCity(civInfo: CivilizationInfo, tile: TileInfo, replacePalace: Boolean = false): CityInfo {
val cityInfo = CityInfo(civInfo, tile.position)
cityInfo.population.addPopulation(-1) // Remove population
if (replacePalace && civInfo.cities.size == 1) {
// Add a capital indicator without any other stats
val palaceWithoutStats = createBuildingWithUnique(UniqueType.IndicatesCapital.text)
cityInfo.cityConstructions.removeBuilding("Palace")
cityInfo.cityConstructions.addBuilding(palaceWithoutStats.name)
}
return cityInfo
}
private fun addUnit(name: String, civInfo: CivilizationInfo, tile: TileInfo): MapUnit {
val baseUnit = ruleSet.units[name]!!
baseUnit.ruleset = ruleSet
val mapUnit = baseUnit.getMapUnit(civInfo)
mapUnit.putInTile(tile)
return mapUnit
}
private fun addEmptySpecialist(): String {
val name = "specialist-${objectsCreated}"
objectsCreated++
ruleSet.specialists[name] = Specialist()
return name
}
private fun createBuildingWithUnique(unique: String): Building {
return createBuildingWithUniques(arrayListOf(unique))
}
private fun createBuildingWithUniques(uniques: ArrayList<String> = arrayListOf()): Building {
val building = Building()
building.uniques = uniques
building.name = "Building-${objectsCreated}"
objectsCreated++
ruleSet.buildings[building.name] = building
return building
}
@Test
/** tests [UniqueType.Stats] */
fun stats() {
val civInfo = addCiv()
val tile = addTile(Constants.desert)
val cityInfo = addCity(civInfo, tile, true)
val buildingName = createBuildingWithUnique("[+1 Food]").name
val civInfo = game.addCiv()
val tile = game.addTile(Constants.desert)
val cityInfo = game.addCity(civInfo, tile, true)
val buildingName = game.createBuildingWithUnique("[+1 Food]").name
cityInfo.cityConstructions.addBuilding(buildingName)
cityInfo.cityStats.update()
@ -141,10 +38,10 @@ class GlobalUniquesTests {
@Test
fun statsPerCity() {
val civInfo = addCiv()
val tile = addTile(Constants.desert)
val cityInfo = addCity(civInfo, tile, true)
val buildingName = createBuildingWithUnique("[+1 Production] [in this city]").name
val civInfo = game.addCiv()
val tile = game.addTile(Constants.desert)
val cityInfo = game.addCity(civInfo, tile, true)
val buildingName = game.createBuildingWithUnique("[+1 Production] [in this city]").name
cityInfo.cityConstructions.addBuilding(buildingName)
cityInfo.cityStats.update()
@ -153,11 +50,11 @@ class GlobalUniquesTests {
@Test
fun statsPerSpecialist() {
val civInfo = addCiv()
val tile = addTile(Constants.desert)
val cityInfo = addCity(civInfo, tile, true)
val building = createBuildingWithUnique("[+3 Gold] from every specialist [in this city]")
val specialistName = addEmptySpecialist()
val civInfo = game.addCiv()
val tile = game.addTile(Constants.desert)
val cityInfo = game.addCity(civInfo, tile, true)
val building = game.createBuildingWithUnique("[+3 Gold] from every specialist [in this city]")
val specialistName = game.addEmptySpecialist()
building.specialistSlots.add(specialistName,2)
cityInfo.population.addPopulation(2)
cityInfo.population.specialistAllocations[specialistName] = 2
@ -169,10 +66,10 @@ class GlobalUniquesTests {
@Test
fun statsPerPopulation() {
val civInfo = addCiv()
val tile = addTile(Constants.desert)
val cityInfo = addCity(civInfo, tile, true)
val building = createBuildingWithUnique("[+3 Gold] per [2] population [in this city]")
val civInfo = game.addCiv()
val tile = game.addTile(Constants.desert)
val cityInfo = game.addCity(civInfo, tile, true)
val building = game.createBuildingWithUnique("[+3 Gold] per [2] population [in this city]")
cityInfo.population.addPopulation(4)
cityInfo.cityConstructions.addBuilding(building.name)
@ -182,10 +79,10 @@ class GlobalUniquesTests {
@Test
fun statsPerXPopulation() {
val civInfo = addCiv()
val tile = addTile(Constants.desert)
val cityInfo = addCity(civInfo, tile, true)
val building = createBuildingWithUnique("[+3 Gold] in cities with [3] or more population")
val civInfo = game.addCiv()
val tile = game.addTile(Constants.desert)
val cityInfo = game.addCity(civInfo, tile, true)
val building = game.createBuildingWithUnique("[+3 Gold] in cities with [3] or more population")
cityInfo.population.addPopulation(2)
cityInfo.cityConstructions.addBuilding(building.name)
@ -199,10 +96,10 @@ class GlobalUniquesTests {
@Test
fun statsFromCitiesOnSpecificTiles() {
val civInfo = addCiv()
val tile = addTile(Constants.desert)
val cityInfo = addCity(civInfo, tile, true)
val building = createBuildingWithUnique("[+3 Gold] in cities on [${Constants.desert}] tiles")
val civInfo = game.addCiv()
val tile = game.addTile(Constants.desert)
val cityInfo = game.addCity(civInfo, tile, true)
val building = game.createBuildingWithUnique("[+3 Gold] in cities on [${Constants.desert}] tiles")
cityInfo.cityConstructions.addBuilding(building.name)
cityInfo.cityStats.update()
@ -214,11 +111,11 @@ class GlobalUniquesTests {
@Test
fun statsSpendingGreatPeople() {
val civInfo = addCiv()
val tile = addTile(Constants.desert)
val cityInfo = addCity(civInfo, tile, true)
val unit = addUnit("Great Prophet", civInfo, tile)
val building = createBuildingWithUnique("[+250 Gold] whenever a Great Person is expended")
val civInfo = game.addCiv()
val tile = game.addTile(Constants.desert)
val cityInfo = game.addCity(civInfo, tile, true)
val unit = game.addUnit("Great Prophet", civInfo, tile)
val building = game.createBuildingWithUnique("[+250 Gold] whenever a Great Person is expended")
cityInfo.cityConstructions.addBuilding(building.name)
civInfo.addGold(-civInfo.gold)
@ -228,38 +125,38 @@ class GlobalUniquesTests {
@Test
fun statsFromTiles() {
val civInfo = addCiv()
val tile = addTile(Constants.desert)
val cityInfo = addCity(civInfo, tile, true)
val building = createBuildingWithUnique("[+4 Gold] from [${Constants.grassland}] tiles [in all cities]")
val civInfo = game.addCiv()
val tile = game.addTile(Constants.desert)
val cityInfo = game.addCity(civInfo, tile, true)
val building = game.createBuildingWithUnique("[+4 Gold] from [${Constants.grassland}] tiles [in all cities]")
cityInfo.cityConstructions.addBuilding(building.name)
val tile2 = addTile(Constants.grassland, Vector2(0f,1f))
val tile2 = game.addTile(Constants.grassland, Vector2(0f,1f))
Assert.assertTrue(tile2.getTileStats(cityInfo, civInfo).gold == 4f)
}
@Test
fun statsFromTilesWithout() {
val civInfo = addCiv()
val tile = addTile(Constants.desert)
val cityInfo = addCity(civInfo, tile, true)
val building = createBuildingWithUnique("[+4 Gold] from [${Constants.grassland}] tiles without [${Constants.forest}] [in all cities]")
val civInfo = game.addCiv()
val tile = game.addTile(Constants.desert)
val cityInfo = game.addCity(civInfo, tile, true)
val building = game.createBuildingWithUnique("[+4 Gold] from [${Constants.grassland}] tiles without [${Constants.forest}] [in all cities]")
cityInfo.cityConstructions.addBuilding(building.name)
val tile2 = addTile(Constants.grassland, Vector2(0f,1f))
val tile2 = game.addTile(Constants.grassland, Vector2(0f,1f))
Assert.assertTrue(tile2.getTileStats(cityInfo, civInfo).gold == 4f)
val tile3 = addTile(Constants.grassland, Vector2(0f, 2f), listOf(Constants.forest))
val tile3 = game.addTile(Constants.grassland, Vector2(0f, 2f), listOf(Constants.forest))
Assert.assertFalse(tile3.getTileStats(cityInfo, civInfo).gold == 4f)
}
@Test
fun statsFromObject() {
val civInfo = addCiv()
val tile = addTile(Constants.desert)
val cityInfo = addCity(civInfo, tile, true)
val specialist = addEmptySpecialist()
val building = createBuildingWithUnique("[+3 Faith] from every [${specialist}]")
val civInfo = game.addCiv()
val tile = game.addTile(Constants.desert)
val cityInfo = game.addCity(civInfo, tile, true)
val specialist = game.addEmptySpecialist()
val building = game.createBuildingWithUnique("[+3 Faith] from every [${specialist}]")
cityInfo.cityConstructions.addBuilding(building.name)
cityInfo.population.addPopulation(2)
@ -269,17 +166,17 @@ class GlobalUniquesTests {
Assert.assertTrue(cityInfo.cityStats.finalStatList["Specialists"]!!.faith == 6f)
cityInfo.cityConstructions.removeBuilding(building.name)
val building2 = createBuildingWithUnique("[+3 Faith] from every [${Constants.grassland}]")
val building2 = game.createBuildingWithUnique("[+3 Faith] from every [${Constants.grassland}]")
cityInfo.cityConstructions.addBuilding(building2.name)
val tile2 = addTile(Constants.grassland, Vector2(1f, 0f))
val tile2 = game.addTile(Constants.grassland, Vector2(1f, 0f))
Assert.assertTrue(tile2.getTileStats(cityInfo, civInfo).faith == 3f)
cityInfo.cityConstructions.removeBuilding(building2.name)
val emptyBuilding = createBuildingWithUniques()
val emptyBuilding = game.createBuildingWithUniques()
val building3 = createBuildingWithUnique("[+3 Faith] from every [${emptyBuilding.name}]")
val building3 = game.createBuildingWithUnique("[+3 Faith] from every [${emptyBuilding.name}]")
cityInfo.cityConstructions.addBuilding(emptyBuilding.name)
cityInfo.cityConstructions.addBuilding(building3.name)
cityInfo.cityStats.update()

View File

@ -0,0 +1,122 @@
package com.unciv.uniques
import com.badlogic.gdx.math.Vector2
import com.unciv.UncivGame
import com.unciv.logic.GameInfo
import com.unciv.logic.city.CityInfo
import com.unciv.logic.civilization.CityStateType
import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.logic.civilization.PlayerType
import com.unciv.logic.map.MapUnit
import com.unciv.logic.map.TileInfo
import com.unciv.logic.map.TileMap
import com.unciv.models.metadata.BaseRuleset
import com.unciv.models.metadata.GameSettings
import com.unciv.models.ruleset.*
import com.unciv.models.ruleset.unique.UniqueType
class TestGame {
private var objectsCreated = 0
val ruleset: Ruleset
val gameInfo = GameInfo()
val tileMap = TileMap()
init {
// Set UncivGame.Current so that debug variables are initialized
UncivGame.Current = UncivGame("Test")
// And the settings can be reached for the locale used in .tr()
UncivGame.Current.settings = GameSettings()
// Create a new ruleset we can easily edit, and set the important variables of gameInfo
RulesetCache.loadRulesets()
ruleset = RulesetCache[BaseRuleset.Civ_V_GnK.fullName]!!
gameInfo.ruleSet = ruleset
gameInfo.difficultyObject = ruleset.difficulties["Prince"]!!
// Create a tilemap, needed for city centers
gameInfo.tileMap = tileMap
}
fun addTile(terrain: String, position: Vector2 = Vector2.Zero, features: List<String> = listOf()): TileInfo {
val tile = TileInfo()
tile.ruleset = ruleset
tile.baseTerrain = terrain
for (feature in features) {
tile.addTerrainFeature(feature)
}
tile.tileMap = tileMap
tile.position = position
tile.setTransients()
while (tileMap.tileMatrix.size < position.x + 1)
tileMap.tileMatrix.add(ArrayList())
while (tileMap.tileMatrix[position.x.toInt()].size < position.y + 1)
tileMap.tileMatrix[position.x.toInt()].add(null)
tileMap.tileMatrix[position.x.toInt()][position.y.toInt()] = tile
return tile
}
fun addCiv(uniques: List<String> = emptyList(), isPlayer: Boolean = false, cityState: CityStateType? = null): CivilizationInfo {
val nationName = "Nation-${objectsCreated++}"
ruleset.nations[nationName] = Nation().apply {
name = nationName
cities = arrayListOf("The Capital")
if (cityState != null) {
cityStateType = cityState
}
this.uniques = ArrayList(uniques)
}
val civInfo = CivilizationInfo()
civInfo.nation = ruleset.nations[nationName]!!
civInfo.gameInfo = gameInfo
civInfo.civName = nationName
if (isPlayer) civInfo.playerType = PlayerType.Human
civInfo.setTransients()
if (cityState != null) {
civInfo.cityStateFunctions.initCityState(ruleset, "Ancient era", emptyList())
}
gameInfo.civilizations.add(civInfo)
return civInfo
}
fun addCity(civInfo: CivilizationInfo, tile: TileInfo, replacePalace: Boolean = false): CityInfo {
val cityInfo = CityInfo(civInfo, tile.position)
cityInfo.population.addPopulation(-1) // Remove population
if (replacePalace && civInfo.cities.size == 1) {
// Add a capital indicator without any other stats
val palaceWithoutStats = createBuildingWithUnique(UniqueType.IndicatesCapital.text)
cityInfo.cityConstructions.removeBuilding("Palace")
cityInfo.cityConstructions.addBuilding(palaceWithoutStats.name)
}
return cityInfo
}
fun addUnit(name: String, civInfo: CivilizationInfo, tile: TileInfo): MapUnit {
val baseUnit = ruleset.units[name]!!
baseUnit.ruleset = ruleset
val mapUnit = baseUnit.getMapUnit(civInfo)
mapUnit.putInTile(tile)
return mapUnit
}
fun addEmptySpecialist(): String {
val name = "specialist-${objectsCreated++}"
ruleset.specialists[name] = Specialist()
return name
}
fun createBuildingWithUnique(unique: String): Building {
return createBuildingWithUniques(arrayListOf(unique))
}
fun createBuildingWithUniques(uniques: ArrayList<String> = arrayListOf()): Building {
val building = Building()
building.uniques = uniques
building.name = "Building-${objectsCreated++}"
ruleset.buildings[building.name] = building
return building
}
}

View File

@ -0,0 +1,48 @@
package com.unciv.uniques
import com.badlogic.gdx.math.Vector2
import com.unciv.Constants
import com.unciv.logic.civilization.CityStateType
import com.unciv.testing.GdxTestRunner
import com.unciv.ui.worldscreen.unit.UnitActions
import org.hamcrest.CoreMatchers
import org.hamcrest.MatcherAssert.assertThat
import org.junit.Assert
import org.junit.Assert.assertNotNull
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(GdxTestRunner::class)
class UnitUniquesTests {
private lateinit var game: TestGame
@Before
fun initTheWorld() {
game = TestGame()
}
@Test
fun `Sweden can gift Great Persons to City States`() {
// when
val cityState = game.addCiv(cityState = CityStateType.Cultured)
val cityStateCapitalTile = game.addTile(Constants.grassland, Vector2(0f, 0f))
val cityStateCapital = game.addCity(cityState, cityStateCapitalTile)
val mainCiv = game.addCiv(
uniques = listOf("Gain [90] Influence with a [Great Person] gift to a City-State"),
isPlayer = true
)
game.gameInfo.currentPlayerCiv = mainCiv
val unitTile = game.addTile(Constants.grassland, Vector2(1f, 0f))
cityStateCapital.expansion.takeOwnership(unitTile)
val greatPerson = game.addUnit("Great Scientist", mainCiv, unitTile)
// then
val giftAction = UnitActions.getGiftAction(greatPerson, unitTile)
assertNotNull("Great Person should have a gift action", giftAction)
}
}