Refactor BattleDamage object and test it (#9992)

* 💡 add some comments providing examples

* ♻ refactor getGeneralModifiers to increase readability

* ♻ refactor getAttackModifiers to increase readability

* 🏗 move constants expressed as magic number to separated class to increase maintainability and expressivity

* ♻ invert condition to remove continue statement and simplify code

* 💚 add some tests for battle damage class
This commit is contained in:
Framonti
2023-08-30 22:37:10 +02:00
committed by GitHub
parent 96e96cf449
commit 7952366afb
3 changed files with 272 additions and 65 deletions

View File

@ -0,0 +1,158 @@
package com.unciv.logic.battle
import com.badlogic.gdx.math.Vector2
import com.unciv.logic.civilization.Civilization
import com.unciv.logic.civilization.managers.TurnManager
import com.unciv.logic.map.mapunit.MapUnit
import com.unciv.logic.map.tile.Tile
import com.unciv.testing.GdxTestRunner
import com.unciv.uniques.TestGame
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(GdxTestRunner::class)
class BattleDamageTest {
private lateinit var attackerCiv: Civilization
private lateinit var defenderCiv: Civilization
private lateinit var defaultAttackerTile: Tile
private lateinit var defaultDefenderTile: Tile
private lateinit var defaultAttackerUnit: MapUnit
private lateinit var defaultDefenderUnit: MapUnit
private val testGame = TestGame()
@Before
fun setUp() {
testGame.makeHexagonalMap(4)
attackerCiv = testGame.addCiv()
defenderCiv = testGame.addCiv()
defaultAttackerTile = testGame.getTile(Vector2(1f, 1f))
defaultAttackerUnit = testGame.addUnit("Warrior", attackerCiv, defaultAttackerTile)
defaultDefenderTile = testGame.getTile(Vector2(0f, 1f))
defaultDefenderUnit = testGame.addUnit("Warrior", defenderCiv, defaultDefenderTile)
}
@Test
fun `should retrieve modifiers from policies`() {
// given
val policy = testGame.createPolicy("[+25]% Strength <when attacking> <for [Military] units>")
attackerCiv.policies.adopt(policy, true)
// when
val attackModifiers = BattleDamage.getAttackModifiers(MapUnitCombatant(defaultAttackerUnit), MapUnitCombatant(defaultDefenderUnit), defaultAttackerTile)
// then
assertEquals(1, attackModifiers.size)
assertEquals(25, attackModifiers.sumValues())
}
@Test
fun `should retrieve modifiers from buldings`() {
// given
val building = testGame.createBuilding("[+15]% Strength <for [Military] units>")
val attackerCity = testGame.addCity(attackerCiv, testGame.getTile(Vector2.Zero))
attackerCity.cityConstructions.addBuilding(building.name)
// when
val attackModifiers = BattleDamage.getAttackModifiers(MapUnitCombatant(defaultAttackerUnit), MapUnitCombatant(defaultDefenderUnit), defaultAttackerTile)
// then
assertEquals(1, attackModifiers.size)
assertEquals(15, attackModifiers.sumValues())
}
@Test
fun `should retrieve modifiers from national abilities`() {
// given
val civ = testGame.addCiv("[+10]% Strength <for [All] units> <during a Golden Age>") // i.e., Persia national ability
civ.goldenAges.enterGoldenAge(2)
val attackerTile = testGame.getTile(Vector2.Zero)
val attackerUnit = testGame.addUnit("Warrior", civ, attackerTile)
// when
val attackModifiers = BattleDamage.getAttackModifiers(MapUnitCombatant(attackerUnit), MapUnitCombatant(defaultDefenderUnit), attackerTile)
// then
assertEquals(1, attackModifiers.size)
assertEquals(10, attackModifiers.sumValues())
}
@Test
fun `should retrieve modifiers from lack of strategic resource`() {
// given
defaultAttackerTile.militaryUnit = null // otherwise we'll also get a flanking bonus
val attackerTile = testGame.getTile(Vector2.Zero)
val attackerUnit = testGame.addUnit("Horseman", attackerCiv, attackerTile)
// when
val attackModifiers = BattleDamage.getAttackModifiers(MapUnitCombatant(attackerUnit), MapUnitCombatant(defaultDefenderUnit), attackerTile)
// then
assertEquals(1, attackModifiers.size)
assertEquals(BattleConstants.MISSING_RESOURCES_MALUS, attackModifiers.sumValues())
}
@Test
fun `should retrieve attacking flank bonus modifiers`() {
// given
val flankingAttackerTile = testGame.getTile(Vector2.Zero)
testGame.addUnit("Warrior", attackerCiv, flankingAttackerTile)
// when
val attackModifiers = BattleDamage.getAttackModifiers(MapUnitCombatant(defaultAttackerUnit), MapUnitCombatant(defaultDefenderUnit), defaultAttackerTile)
// then
assertEquals(1, attackModifiers.size)
assertEquals(BattleConstants.BASE_FLANKING_BONUS.toInt(), attackModifiers.sumValues())
}
@Test
fun `should retrieve defence fortification modifiers`() {
// given
defaultDefenderUnit.currentMovement = 2f // base warrior max movement points
defaultDefenderUnit.fortify()
TurnManager(defenderCiv).endTurn()
// when
val defenceModifiers = BattleDamage.getDefenceModifiers(MapUnitCombatant(defaultAttackerUnit), MapUnitCombatant(defaultDefenderUnit), defaultAttackerTile)
// then
assertEquals(1, defenceModifiers.size)
assertEquals(BattleConstants.FORTIFICATION_BONUS, defenceModifiers.sumValues())
}
@Test
fun `should retrieve defence terrain modifiers`() {
// given
testGame.setTileFeatures(defaultDefenderTile.position, "Hill")
// when
val defenceModifiers = BattleDamage.getDefenceModifiers(MapUnitCombatant(defaultAttackerUnit), MapUnitCombatant(defaultDefenderUnit), defaultAttackerTile)
// then
assertEquals(1, defenceModifiers.size)
assertEquals(25, defenceModifiers.sumValues())
}
@Test
fun `should not retrieve defence terrain modifiers when unit doesn't get them`() {
// given
val defenderTile = testGame.getTile(Vector2.Zero)
testGame.setTileFeatures(defenderTile.position, "Hill")
defenderCiv.resourceStockpiles.add("Horses", 1) // no resource penalty
val defenderUnit = testGame.addUnit("Horseman", defenderCiv, defenderTile)
// when
val defenceModifiers = BattleDamage.getDefenceModifiers(MapUnitCombatant(defaultAttackerUnit), MapUnitCombatant(defenderUnit), defaultAttackerTile)
// then
assertTrue(defenceModifiers.isEmpty())
assertEquals(0, defenceModifiers.sumValues())
}
}