Forts and citadels (with AI) (#2325)

* Enabled Forts & Citadels

* Friendly territory checks

* Citadel damage & notifications

* Sprites, Icons, Translation & Atlas

* Obsolete tests are removed

* NullReferenceException code is fixed

* Refactoring: using the static object

* AI for the forts and citadels

* Display defence stats

* Exclude enemies tiles as candidates

Co-authored-by: r3versi <fluo392@gmail.com>
This commit is contained in:
Jack Rainy 2020-04-03 11:22:27 +03:00 committed by GitHub
parent 10762a3873
commit 29a077a803
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 197 additions and 111 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 951 B

View file

@ -79,7 +79,16 @@
"improvingTech": "Compass", "improvingTech": "Compass",
"improvingTechStats": {"gold": 1} "improvingTechStats": {"gold": 1}
}, },
// Military improvement
{
name: "Fort",
terrainsCanBeBuiltOn: ["Plains","Grassland","Desert","Hill","Tundra","Snow"],
turnsToBuild: 6,
techRequired: "Engineering",
uniques: ["Gives a defensive bonus of 50%"]
},
// Transportation // Transportation
{ {
"name": "Road", "name": "Road",
@ -151,7 +160,12 @@
"improvingTech": "Economics", "improvingTech": "Economics",
"improvingTechStats": {"gold": 1} "improvingTechStats": {"gold": 1}
}, },
{
name: "Citadel",
uniques: ["Gives a defensive bonus of 100%", "Deal 30 damage to adjacent enemy units"]
// TODO (G&K): adds every tile around it to your territory
},
//Civilization unique improvements //Civilization unique improvements
{ {
"name": "Moai", "name": "Moai",

View file

@ -1324,8 +1324,7 @@
"name": "Great General", "name": "Great General",
"unbuildable": true, "unbuildable": true,
"unitType": "Civilian", "unitType": "Civilian",
"uniques": ["Can start an 8-turn golden age","Bonus for units in 2 tile radius 15%"], "uniques": ["Can start an 8-turn golden age","Bonus for units in 2 tile radius 15%", "Can build improvement: Citadel"],
//todo : should be able to build mega-fort
"movement": 2 "movement": 2
}, },
{ {
@ -1334,8 +1333,7 @@
"unitType": "Civilian", "unitType": "Civilian",
"uniqueTo": "Mongolia", "uniqueTo": "Mongolia",
"replaces": "Great General", "replaces": "Great General",
"uniques": ["Can start an 8-turn golden age","Bonus for units in 2 tile radius 15%", "Heal adjacent units for an additional 15 HP per turn"], "uniques": ["Can start an 8-turn golden age","Bonus for units in 2 tile radius 15%", "Heal adjacent units for an additional 15 HP per turn", "Can build improvement: Citadel"],
//todo : should be able to build mega-fort
"movement": 5 "movement": 5
} }
] ]

View file

@ -1,4 +1,4 @@

# Tutorial tasks # Tutorial tasks
Move a unit!\nClick on a unit > Click on a destination > Click the arrow popup = Sposta un'unità!\nClicca su un'unità > Clicca su una destinazione > Clicca sul popup con la freccia Move a unit!\nClick on a unit > Click on a destination > Click the arrow popup = Sposta un'unità!\nClicca su un'unità > Clicca su una destinazione > Clicca sul popup con la freccia

View file

@ -44,7 +44,7 @@ object Constants {
const val researchAgreement = "Research Agreement" const val researchAgreement = "Research Agreement"
const val openBorders = "Open Borders" const val openBorders = "Open Borders"
const val random = "Random" const val random = "Random"
val greatImprovements = listOf("Academy", "Landmark", "Manufactory", "Customs house") val greatImprovements = listOf("Academy", "Landmark", "Manufactory", "Customs house", "Citadel")
val unitActionSetUp = "Set Up" val unitActionSetUp = "Set Up"
val unitActionSleep = "Sleep" val unitActionSleep = "Sleep"

View file

@ -212,7 +212,7 @@ class ConstructionAutomation(val cityConstructions: CityConstructions){
// If this city is the closest city to another civ, that makes it a likely candidate for attack // If this city is the closest city to another civ, that makes it a likely candidate for attack
if (civInfo.getKnownCivs().filter { it.cities.isNotEmpty() } if (civInfo.getKnownCivs().filter { it.cities.isNotEmpty() }
.any { NextTurnAutomation().getClosestCities(civInfo, it).city1 == cityInfo }) .any { NextTurnAutomation.getClosestCities(civInfo, it).city1 == cityInfo })
modifier *= 1.5f modifier *= 1.5f
addChoice(relativeCostEffectiveness, defensiveBuilding.name, modifier) addChoice(relativeCostEffectiveness, defensiveBuilding.name, modifier)

View file

@ -282,21 +282,6 @@ class NextTurnAutomation{
} }
} }
fun getMinDistanceBetweenCities(civ1: CivilizationInfo, civ2: CivilizationInfo): Int {
return getClosestCities(civ1,civ2).aerialDistance
}
data class CityDistance(val city1:CityInfo, val city2:CityInfo, val aerialDistance: Int)
fun getClosestCities(civ1: CivilizationInfo, civ2: CivilizationInfo): CityDistance {
val cityDistances = arrayListOf<CityDistance>()
for (civ1city in civ1.cities)
for (civ2city in civ2.cities)
cityDistances.add(CityDistance(civ1city, civ2city,
civ1city.getCenterTile().aerialDistanceTo(civ2city.getCenterTile())))
return cityDistances.minBy { it.aerialDistance }!!
}
private fun offerDeclarationOfFriendship(civInfo: CivilizationInfo) { private fun offerDeclarationOfFriendship(civInfo: CivilizationInfo) {
val civsThatWeCanDeclareFriendshipWith = civInfo.getKnownCivs() val civsThatWeCanDeclareFriendshipWith = civInfo.getKnownCivs()
.asSequence() .asSequence()
@ -509,4 +494,22 @@ class NextTurnAutomation{
diplomacyManager.removeFlag(DiplomacyFlags.SettledCitiesNearUs) diplomacyManager.removeFlag(DiplomacyFlags.SettledCitiesNearUs)
} }
companion object
{
fun getMinDistanceBetweenCities(civ1: CivilizationInfo, civ2: CivilizationInfo): Int {
return getClosestCities(civ1,civ2).aerialDistance
}
data class CityDistance(val city1:CityInfo, val city2:CityInfo, val aerialDistance: Int)
fun getClosestCities(civ1: CivilizationInfo, civ2: CivilizationInfo): CityDistance {
val cityDistances = arrayListOf<CityDistance>()
for (civ1city in civ1.cities)
for (civ2city in civ2.cities)
cityDistances.add(CityDistance(civ1city, civ2city,
civ1city.getCenterTile().aerialDistanceTo(civ2city.getCenterTile())))
return cityDistances.minBy { it.aerialDistance }!!
}
}
} }

View file

@ -61,16 +61,27 @@ class SpecificUnitAutomation {
return return
} }
//if no unit to follow, take refuge in city. // try to build a citadel
if (WorkerAutomation(unit).evaluateFortPlacement(unit.currentTile, unit.civInfo))
UnitActions.getGreatPersonBuildImprovementAction(unit)?.action?.invoke()
//if no unit to follow, take refuge in city or build citadel there.
val reachableTest : (TileInfo) -> Boolean = {it.civilianUnit == null &&
unit.movement.canMoveTo(it)
&& unit.movement.canReach(it)}
val cityToGarrison = unit.civInfo.cities.asSequence().map { it.getCenterTile() } val cityToGarrison = unit.civInfo.cities.asSequence().map { it.getCenterTile() }
.sortedBy { it.aerialDistanceTo(unit.currentTile) } .sortedBy { it.aerialDistanceTo(unit.currentTile) }
.firstOrNull { .firstOrNull { reachableTest(it) }
it.civilianUnit == null && unit.movement.canMoveTo(it)
&& unit.movement.canReach(it)
}
if (cityToGarrison != null) { if (cityToGarrison != null) {
unit.movement.headTowards(cityToGarrison) // try to find a good place for citadel nearby
val potentialTilesNearCity = cityToGarrison.getTilesInDistanceRange(3..4)
val tileForCitadel = potentialTilesNearCity.firstOrNull { reachableTest(it) &&
WorkerAutomation(unit).evaluateFortPlacement(it, unit.civInfo) }
if (tileForCitadel != null)
unit.movement.headTowards(tileForCitadel)
else
unit.movement.headTowards(cityToGarrison)
return return
} }
} }

View file

@ -191,6 +191,8 @@ class WorkerAutomation(val unit: MapUnit) {
tile.containsGreatImprovement() -> null tile.containsGreatImprovement() -> null
tile.containsUnfinishedGreatImprovement() -> null tile.containsUnfinishedGreatImprovement() -> null
// Defence is more important that civilian improvements
evaluateFortPlacement(tile,civInfo) -> "Fort"
// I think we can assume that the unique improvement is better // I think we can assume that the unique improvement is better
uniqueImprovement!=null && tile.canBuildImprovement(uniqueImprovement,civInfo) -> uniqueImprovement.name uniqueImprovement!=null && tile.canBuildImprovement(uniqueImprovement,civInfo) -> uniqueImprovement.name
@ -208,4 +210,73 @@ class WorkerAutomation(val unit: MapUnit) {
return unit.civInfo.gameInfo.ruleSet.tileImprovements[improvementString]!! return unit.civInfo.gameInfo.ruleSet.tileImprovements[improvementString]!!
} }
private fun isAcceptableTileForFort(tile: TileInfo, civInfo: CivilizationInfo): Boolean
{
// don't build fort in the city
if (tile.isCityCenter()) return false
// don't build fort if it is already here
if (tile.improvement == "Fort") return false
// don't build on resource tiles
if (tile.hasViewableResource(civInfo)) return false
// don't build on great improvements
if (tile.containsGreatImprovement() || tile.containsUnfinishedGreatImprovement()) return false
return true
}
fun evaluateFortPlacement(tile: TileInfo, civInfo: CivilizationInfo): Boolean {
// build on our land only
if ((tile.owningCity?.civInfo != civInfo) ||
!isAcceptableTileForFort(tile, civInfo)) return false
val isHills = tile.getBaseTerrain().name == Constants.hill
// if this place is not perfect, let's see if there is a better one
val nearestTiles = tile.getTilesInDistance(2).filter{it.owningCity?.civInfo == civInfo}.toList()
for (closeTile in nearestTiles) {
// don't build forts too close to the cities
if (closeTile.isCityCenter()) return false
// don't build forts too close to other forts
if (closeTile.improvement == "Fort" || closeTile.improvement == "Citadel"
|| closeTile.improvementInProgress == "Fort") return false
// there is another better tile for the fort
if (!isHills && tile.getBaseTerrain().name == Constants.hill &&
isAcceptableTileForFort(closeTile, civInfo)) return false
}
val enemyCivs = civInfo.getKnownCivs()
.filterNot { it == civInfo || it.cities.isEmpty() || !civInfo.getDiplomacyManager(it).canAttack() }
// no potential enemies
if (enemyCivs.isEmpty()) return false
val threatMapping : (CivilizationInfo) -> Int = {
// the war is already a good nudge to build forts
(if (civInfo.isAtWarWith(it)) 20 else 0) +
// let's check also the force of the enemy
when (Automation().threatAssessment(civInfo, it)) {
ThreatLevel.VeryLow -> 1 // do not build forts
ThreatLevel.Low -> 6 // too close, let's build until it is late
ThreatLevel.Medium -> 10
ThreatLevel.High -> 15 // they are strong, let's built until they reach us
ThreatLevel.VeryHigh -> 20
} }
val enemyCivsIsCloseEnough = enemyCivs.filter { NextTurnAutomation.getMinDistanceBetweenCities(civInfo, it) <= threatMapping(it) }
// no threat, let's not build fort
if (enemyCivsIsCloseEnough.isEmpty()) return false
// make list of enemy cities as sources of threat
val enemyCities = mutableListOf<TileInfo>()
enemyCivsIsCloseEnough.forEach { enemyCities.addAll(it.cities.map { city -> city.getCenterTile() } ) }
// find closest enemy city
val closestEnemyCity = enemyCities.minBy { it.aerialDistanceTo(tile) }!!
val distanceToEnemy = tile.aerialDistanceTo(closestEnemyCity)
// find closest our city to defend from this enemy city
val closestOurCity = tile.owningCity!!.getCenterTile()
val distanceBetweenCities = closestEnemyCity.aerialDistanceTo(closestOurCity)
// let's build fort on the front line, not behind the city
return distanceBetweenCities > distanceToEnemy
}
} }

View file

@ -160,6 +160,7 @@ class BattleDamage{
fun getDefenceModifiers(attacker: ICombatant, defender: MapUnitCombatant): HashMap<String, Float> { fun getDefenceModifiers(attacker: ICombatant, defender: MapUnitCombatant): HashMap<String, Float> {
val modifiers = HashMap<String, Float>() val modifiers = HashMap<String, Float>()
val tile = defender.getTile()
if (defender.unit.isEmbarked()) { if (defender.unit.isEmbarked()) {
// embarked units get no defensive modifiers apart from this unique // embarked units get no defensive modifiers apart from this unique
@ -172,11 +173,17 @@ class BattleDamage{
modifiers.putAll(getGeneralModifiers(defender, attacker)) modifiers.putAll(getGeneralModifiers(defender, attacker))
modifiers.putAll(getTileSpecificModifiers(defender, defender.getTile())) modifiers.putAll(getTileSpecificModifiers(defender, tile))
if (!defender.unit.hasUnique("No defensive terrain bonus")) { if (!defender.unit.hasUnique("No defensive terrain bonus")) {
val tileDefenceBonus = defender.getTile().getDefensiveBonus() val tileDefenceBonus = tile.getDefensiveBonus()
if (tileDefenceBonus > 0) modifiers["Terrain"] = tileDefenceBonus if (tileDefenceBonus > 0)
modifiers["Terrain"] = tileDefenceBonus
val improvement = tile.getTileImprovement()
if (improvement != null && tile.isFriendlyTerritory(defender.getCivInfo()))
if (improvement.hasUnique("Gives a defensive bonus of 50%")) modifiers[improvement.name] = 0.50f
else if (improvement.hasUnique("Gives a defensive bonus of 100%")) modifiers[improvement.name] = 1.0f
} }
if(attacker.isRanged()) { if(attacker.isRanged()) {
@ -196,10 +203,9 @@ class BattleDamage{
private fun getTileSpecificModifiers(unit: MapUnitCombatant, tile: TileInfo): HashMap<String,Float> { private fun getTileSpecificModifiers(unit: MapUnitCombatant, tile: TileInfo): HashMap<String,Float> {
val modifiers = HashMap<String,Float>() val modifiers = HashMap<String,Float>()
val isFriendlyTerritory = tile.getOwner()!=null && !unit.getCivInfo().isAtWarWith(tile.getOwner()!!) if(tile.isFriendlyTerritory(unit.getCivInfo()) && unit.getCivInfo().containsBuildingUnique("+15% combat strength for units fighting in friendly territory"))
if(isFriendlyTerritory && unit.getCivInfo().containsBuildingUnique("+15% combat strength for units fighting in friendly territory"))
modifiers["Himeji Castle"] = 0.15f modifiers["Himeji Castle"] = 0.15f
if(!isFriendlyTerritory && unit.unit.hasUnique("+20% bonus outside friendly territory")) if(!tile.isFriendlyTerritory(unit.getCivInfo()) && unit.unit.hasUnique("+20% bonus outside friendly territory"))
modifiers["Foreign Land"] = 0.2f modifiers["Foreign Land"] = 0.2f

View file

@ -527,7 +527,7 @@ class CivilizationInfo {
} }
fun giftMilitaryUnitTo(otherCiv: CivilizationInfo) { fun giftMilitaryUnitTo(otherCiv: CivilizationInfo) {
val city = NextTurnAutomation().getClosestCities(this, otherCiv).city1 val city = NextTurnAutomation.getClosestCities(this, otherCiv).city1
val militaryUnit = city.cityConstructions.getConstructableUnits() val militaryUnit = city.cityConstructions.getConstructableUnits()
.filter { !it.unitType.isCivilian() && it.unitType.isLandUnit() } .filter { !it.unitType.isCivilian() && it.unitType.isLandUnit() }
.toList().random() .toList().random()

View file

@ -235,7 +235,7 @@ class DiplomacyManager() {
* *
* This includes friendly and allied city-states and the open border treaties. * This includes friendly and allied city-states and the open border treaties.
*/ */
fun isConsideredAllyTerritory(): Boolean { fun isConsideredFriendlyTerritory(): Boolean {
if(civInfo.isCityState() && relationshipLevel() >= RelationshipLevel.Friend) if(civInfo.isCityState() && relationshipLevel() >= RelationshipLevel.Friend)
return true return true
return hasOpenBorders return hasOpenBorders

View file

@ -411,25 +411,19 @@ class MapUnit {
/** Returns the health points [MapUnit] will receive if healing on [tileInfo] */ /** Returns the health points [MapUnit] will receive if healing on [tileInfo] */
fun rankTileForHealing(tileInfo: TileInfo): Int { fun rankTileForHealing(tileInfo: TileInfo): Int {
val tileOwner = tileInfo.getOwner() val isFriendlyTerritory = tileInfo.isFriendlyTerritory(civInfo)
val isAlliedTerritory = when {
tileOwner == null -> false
tileOwner == civInfo -> true
!civInfo.knows(tileOwner) -> false
else -> tileOwner.getDiplomacyManager(civInfo).isConsideredAllyTerritory()
}
var healing = when { var healing = when {
tileInfo.isCityCenter() -> 20 tileInfo.isCityCenter() -> 20
tileInfo.isWater && isAlliedTerritory && type.isWaterUnit() -> 15 // Water unit on friendly water tileInfo.isWater && isFriendlyTerritory && type.isWaterUnit() -> 15 // Water unit on friendly water
tileInfo.isWater -> 0 // All other water cases tileInfo.isWater -> 0 // All other water cases
tileOwner == null -> 10 // Neutral territory tileInfo.getOwner() == null -> 10 // Neutral territory
isAlliedTerritory -> 15 // Allied territory isFriendlyTerritory -> 15 // Allied territory
else -> 5 // Enemy territory else -> 5 // Enemy territory
} }
if (hasUnique("This unit and all others in adjacent tiles heal 5 additional HP. This unit heals 5 additional HP outside of friendly territory.") if (hasUnique("This unit and all others in adjacent tiles heal 5 additional HP. This unit heals 5 additional HP outside of friendly territory.")
&& !isAlliedTerritory && !isFriendlyTerritory
// Additional healing from medic is only applied when the unit is able to heal // Additional healing from medic is only applied when the unit is able to heal
&& healing > 0) && healing > 0)
healing += 5 healing += 5
@ -439,7 +433,7 @@ class MapUnit {
fun endTurn() { fun endTurn() {
doPostTurnAction() doPostTurnAction()
if(currentMovement== getMaxMovement().toFloat() // didn't move this turn if (currentMovement == getMaxMovement().toFloat() // didn't move this turn
|| getUniques().contains("Unit will heal every turn, even if it performs an action")){ || getUniques().contains("Unit will heal every turn, even if it performs an action")){
heal() heal()
} }
@ -447,6 +441,8 @@ class MapUnit {
if (action!!.endsWith(" until healed")) { if (action!!.endsWith(" until healed")) {
action = null // wake up when healed action = null // wake up when healed
} }
getCitadelDamage()
} }
fun startTurn() { fun startTurn() {
@ -662,5 +658,25 @@ class MapUnit {
return sum return sum
} }
private fun getCitadelDamage() {
// Check for Citadel damage
val applyCitadelDamage = currentTile.neighbors
.filter{ it.getOwner() != null && civInfo.isAtWarWith(it.getOwner()!!) }
.map{ it.getTileImprovement() }
.filter{ it != null && it.hasUnique("Deal 30 damage to adjacent enemy units") }
.any()
if (applyCitadelDamage) {
health -= 30
if (health <= 0) {
civInfo.addNotification("An enemy [Citadel] has destroyed our [$name]", currentTile.position, Color.RED)
destroy()
} else {
civInfo.addNotification("An enemy [Citadel] has attacked our [$name]", currentTile.position, Color.RED)
}
}
}
//endregion //endregion
} }

View file

@ -1,4 +1,4 @@
package com.unciv.logic.map package com.unciv.logic.map
import com.badlogic.gdx.math.Vector2 import com.badlogic.gdx.math.Vector2
import com.unciv.Constants import com.unciv.Constants
@ -132,9 +132,20 @@ open class TileInfo {
return containingCity.civInfo return containingCity.civInfo
} }
fun isFriendlyTerritory(civInfo: CivilizationInfo): Boolean {
val tileOwner = getOwner()
return when {
tileOwner == null -> false
tileOwner == civInfo -> true
!civInfo.knows(tileOwner) -> false
else -> tileOwner.getDiplomacyManager(civInfo).isConsideredFriendlyTerritory()
}
}
fun getTerrainFeature(): Terrain? = fun getTerrainFeature(): Terrain? =
if (terrainFeature == null) null else ruleset.terrains[terrainFeature!!] if (terrainFeature == null) null else ruleset.terrains[terrainFeature!!]
fun isWorked(): Boolean { fun isWorked(): Boolean {
val city = getCity() val city = getCity()
return city!=null && city.workedTiles.contains(position) return city!=null && city.workedTiles.contains(position)
@ -337,8 +348,17 @@ open class TileInfo {
milUnitString += " - "+militaryUnit!!.civInfo.civName.tr() milUnitString += " - "+militaryUnit!!.civInfo.civName.tr()
lineList += milUnitString lineList += milUnitString
} }
if(getDefensiveBonus()!=0f){ var defenceBonus = getDefensiveBonus()
var defencePercentString = (getDefensiveBonus()*100).toInt().toString()+"%" val tileImprovement = getTileImprovement()
if (tileImprovement != null) {
defenceBonus += when {
tileImprovement.hasUnique("Gives a defensive bonus of 50%") -> 0.5f
tileImprovement.hasUnique("Gives a defensive bonus of 100%") -> 1.0f
else -> 0.0f
}
}
if(defenceBonus != 0.0f){
var defencePercentString = (defenceBonus*100).toInt().toString()+"%"
if(!defencePercentString.startsWith("-")) defencePercentString = "+$defencePercentString" if(!defencePercentString.startsWith("-")) defencePercentString = "+$defencePercentString"
lineList += "[$defencePercentString] to unit defence".tr() lineList += "[$defencePercentString] to unit defence".tr()
} }

View file

@ -64,5 +64,7 @@ class TileImprovement : NamedStats() {
return stringBuilder.toString() return stringBuilder.toString()
} }
fun hasUnique(unique: String) = uniques.contains(unique)
} }

View file

@ -40,6 +40,7 @@ class UnitActionsTable(val worldScreen: WorldScreen) : Table(){
"Construct Academy" -> return ImageGetter.getImprovementIcon("Academy") "Construct Academy" -> return ImageGetter.getImprovementIcon("Academy")
"Start Golden Age" -> return ImageGetter.getUnitIcon("Great Artist") "Start Golden Age" -> return ImageGetter.getUnitIcon("Great Artist")
"Construct Landmark" -> return ImageGetter.getImprovementIcon("Landmark") "Construct Landmark" -> return ImageGetter.getImprovementIcon("Landmark")
"Construct Citadel" -> return ImageGetter.getImprovementIcon("Citadel")
"Hurry Wonder" -> return ImageGetter.getUnitIcon("Great Engineer") "Hurry Wonder" -> return ImageGetter.getUnitIcon("Great Engineer")
"Construct Manufactory" -> return ImageGetter.getImprovementIcon("Manufactory") "Construct Manufactory" -> return ImageGetter.getImprovementIcon("Manufactory")
"Conduct Trade Mission" -> return ImageGetter.getUnitIcon("Great Merchant") "Conduct Trade Mission" -> return ImageGetter.getUnitIcon("Great Merchant")

View file

@ -153,6 +153,8 @@ Unless otherwise specified, all the following are from [the Noun Project](https:
* [Ruins](https://thenounproject.com/term/ruins/3849/) By Paulo Volkova for City ruins * [Ruins](https://thenounproject.com/term/ruins/3849/) By Paulo Volkova for City ruins
* [Fishing Net](https://thenounproject.com/term/fishing-net/1073133/) By Made for Fishing Boats * [Fishing Net](https://thenounproject.com/term/fishing-net/1073133/) By Made for Fishing Boats
* [Moai](https://thenounproject.com/search/?q=moai&i=2878111) By Template * [Moai](https://thenounproject.com/search/?q=moai&i=2878111) By Template
* [Fort](https://thenounproject.com/term/fort/1697645/) By Adrien Coquet
* [Citadel](https://thenounproject.com/term/fort/1697646/) By Adrien Coquet
## Buildings ## Buildings

View file

@ -45,64 +45,6 @@ class TranslationTests {
allUnitActionsHaveTranslation) allUnitActionsHaveTranslation)
} }
@Test
fun allTerrainsHaveTranslation() {
val strings: Set<String> = ruleset.terrains.keys
val allStringsHaveTranslation = allStringAreTranslated(strings)
Assert.assertTrue("This test will only pass when there is a translation for all buildings",
allStringsHaveTranslation)
}
@Test
fun allTerrainUniquesHaveTranslation() {
val strings: MutableSet<String> = HashSet()
for (terrain in ruleset.terrains.values) {
strings.addAll(terrain.uniques)
}
val allStringsHaveTranslation = allStringAreTranslated(strings)
Assert.assertTrue("This test will only pass when there is a translation for all terrain uniques",
allStringsHaveTranslation)
}
@Test
fun allImprovementsHaveTranslation() {
val strings: Set<String> = ruleset.tileImprovements.keys
val allStringsHaveTranslation = allStringAreTranslated(strings)
Assert.assertTrue("This test will only pass when there is a translation for all improvements",
allStringsHaveTranslation)
}
@Test
fun allImprovementUniquesHaveTranslation() {
val strings: MutableSet<String> = HashSet()
for (improvement in ruleset.tileImprovements.values) {
strings.addAll(improvement.uniques)
}
val allStringsHaveTranslation = allStringAreTranslated(strings)
Assert.assertTrue("This test will only pass when there is a translation for all improvements uniques",
allStringsHaveTranslation)
}
@Test
fun allTechnologiesHaveTranslation() {
val strings: Set<String> = ruleset.technologies.keys
val allStringsHaveTranslation = allStringAreTranslated(strings)
Assert.assertTrue("This test will only pass when there is a translation for all technologies",
allStringsHaveTranslation)
}
@Test
fun allTechnologiesQuotesHaveTranslation() {
val strings: MutableSet<String> = HashSet()
for (tech in ruleset.technologies.values) {
strings.add(tech.quote)
}
val allStringsHaveTranslation = allStringAreTranslated(strings)
Assert.assertTrue("This test will only pass when there is a translation for all technologies quotes",
allStringsHaveTranslation)
}
private fun allStringAreTranslated(strings: Set<String>): Boolean { private fun allStringAreTranslated(strings: Set<String>): Boolean {
var allStringsHaveTranslation = true var allStringsHaveTranslation = true
for (key in strings) { for (key in strings) {