Base province hero cap on infrastructure (#8757)

This commit is contained in:
2026-07-23 12:38:50 -07:00
committed by GitHub
parent 0766b63b9e
commit e07b077b7f
26 changed files with 109 additions and 38 deletions
@@ -235,7 +235,7 @@ minimumTrustToOfferTruce 0 Int
minimumTrustToInvite 20 Int
minimumTrustToOfferAlliance 30 Int
requiredPowerMultiplierForDismiss 1.5 Double
heroCapPerCastle 5 Int
heroCapDivisor 3.0 Double
overHeroCapLoyaltyDelta -1 Double
minimumAgilityForArchery 75 Double
minimumAgilityForStartFire 70 Double
1 actionVigorCost 15 Int
235 minimumTrustToInvite 20 Int
236 minimumTrustToOfferAlliance 30 Int
237 requiredPowerMultiplierForDismiss 1.5 Double
238 heroCapPerCastle heroCapDivisor 5 3.0 Int Double
239 overHeroCapLoyaltyDelta -1 Double
240 minimumAgilityForArchery 75 Double
241 minimumAgilityForStartFire 70 Double
@@ -24,6 +24,7 @@ scala_library(
"//src/main/scala/net/eagle0/eagle:eagle_pkg",
"//src/main/scala/net/eagle0/eagle/library/util:eagle_require",
"//src/main/scala/net/eagle0/eagle/library/util/hero:hero_utils",
"//src/main/scala/net/eagle0/eagle/library/util/province",
"//src/main/scala/net/eagle0/eagle/model/action_result/changed_province/concrete",
"//src/main/scala/net/eagle0/eagle/model/state:army",
"//src/main/scala/net/eagle0/eagle/model/state/game_state",
@@ -2,6 +2,7 @@ package net.eagle0.eagle.library.actions.applier
import net.eagle0.eagle.*
import net.eagle0.eagle.library.util.hero.HeroUtils
import net.eagle0.eagle.library.util.province.ProvinceUtils
import net.eagle0.eagle.library.util.EagleRequire.internalRequire
import net.eagle0.eagle.model.action_result.changed_province.concrete.{ChangedProvinceC, HostileArmyStatusChange}
import net.eagle0.eagle.model.state.{HostileArmyGroup, MovingArmy}
@@ -74,6 +75,13 @@ object ProvinceUpdateHelpers {
val newFood = p.food + cp.foodDelta.getOrElse(0)
internalRequire(newFood >= 0, s"Got a foodDelta of ${cp.foodDelta} but only ${p.food} available")
val newInfrastructure =
(p.infrastructure + cp.infrastructureDelta.getOrElse(0.0)).max(0.0).min(100.0)
val newInfrastructureDevastation =
(p.infrastructureDevastation + cp.infrastructureDevastationDelta.getOrElse(0.0))
.max(0.0)
.min(p.infrastructure)
p.copy(
incomingShipments = incomingShipments,
defendingArmy = defendingArmy,
@@ -82,12 +90,12 @@ object ProvinceUpdateHelpers {
priceIndex = cp.newPriceIndex.getOrElse(p.priceIndex),
economy = (p.economy + cp.economyDelta.getOrElse(0.0)).max(0.0).min(100.0),
agriculture = (p.agriculture + cp.agricultureDelta.getOrElse(0.0)).max(0.0).min(100.0),
infrastructure = (p.infrastructure + cp.infrastructureDelta.getOrElse(0.0)).max(0.0).min(100.0),
infrastructure = newInfrastructure,
economyDevastation = (p.economyDevastation + cp.economyDevastationDelta.getOrElse(0.0)).max(0.0).min(p.economy),
agricultureDevastation =
(p.agricultureDevastation + cp.agricultureDevastationDelta.getOrElse(0.0)).max(0.0).min(p.agriculture),
infrastructureDevastation =
(p.infrastructureDevastation + cp.infrastructureDevastationDelta.getOrElse(0.0)).max(0.0).min(p.infrastructure),
infrastructureDevastation = newInfrastructureDevastation,
heroCap = ProvinceUtils.heroCap(newInfrastructure - newInfrastructureDevastation),
support = (p.support + cp.supportDelta.getOrElse(0.0)).max(0.0).min(100.0)
)
}
@@ -3097,10 +3097,10 @@ scala_setting_library(
)
scala_setting_library(
name = "hero_cap_per_castle",
setting_name = "HeroCapPerCastle",
setting_type = "Int",
setting_value = "5",
name = "hero_cap_divisor",
setting_name = "HeroCapDivisor",
setting_type = "Double",
setting_value = "3.0",
visibility = [
"//src/main/scala/net/eagle0/eagle:__subpackages__",
"//src/main/scala/net/eagle0/util:__subpackages__",
@@ -124,7 +124,7 @@ scala_library(
"//src/main/scala/net/eagle0/eagle/library/settings:gold_cost_for_divine",
"//src/main/scala/net/eagle0/eagle/library/settings:gold_increase_per_economy",
"//src/main/scala/net/eagle0/eagle/library/settings:gold_per_hero_held_back",
"//src/main/scala/net/eagle0/eagle/library/settings:hero_cap_per_castle",
"//src/main/scala/net/eagle0/eagle/library/settings:hero_cap_divisor",
"//src/main/scala/net/eagle0/eagle/library/settings:history_backend",
"//src/main/scala/net/eagle0/eagle/library/settings:improvement_per_stat",
"//src/main/scala/net/eagle0/eagle/library/settings:improvement_reduction_max",
@@ -191,7 +191,6 @@ scala_library(
deps = [
"//src/main/scala/net/eagle0/common:tsv_utils",
"//src/main/scala/net/eagle0/eagle:eagle_pkg",
"//src/main/scala/net/eagle0/eagle/library/settings:hero_cap_per_castle",
"//src/main/scala/net/eagle0/eagle/library/util:eagle_require",
"//src/main/scala/net/eagle0/eagle/model/state/province",
"//src/main/scala/net/eagle0/eagle/model/state/province/concrete",
@@ -3,7 +3,6 @@ package net.eagle0.eagle.library.util
import java.net.URL
import net.eagle0.common.TsvUtils
import net.eagle0.eagle.library.settings.HeroCapPerCastle
import net.eagle0.eagle.library.util.EagleRequire.internalRequire
import net.eagle0.eagle.model.state.province.{Neighbor, ProvinceT}
import net.eagle0.eagle.model.state.province.concrete.ProvinceC
@@ -23,8 +22,7 @@ object MapGenerator {
name = map("name"),
neighbors = neighborsFromMap(map),
hexMapName = map("hexMapName"),
castleCount = map("castleCount").toInt,
heroCap = map("castleCount").toInt * HeroCapPerCastle.intValue
castleCount = map("castleCount").toInt
)
def neighborsFromMap(map: Map[String, String]): Vector[Neighbor] = {
@@ -17,6 +17,7 @@ scala_library(
"//src/main/scala/net/eagle0/eagle/library/settings:focus_province_storage_multiplier",
"//src/main/scala/net/eagle0/eagle/library/settings:food_increase_per_agriculture",
"//src/main/scala/net/eagle0/eagle/library/settings:gold_increase_per_economy",
"//src/main/scala/net/eagle0/eagle/library/settings:hero_cap_divisor",
"//src/main/scala/net/eagle0/eagle/library/settings:min_support_for_taxes",
"//src/main/scala/net/eagle0/eagle/library/settings:per_development_resource_limit",
"//src/main/scala/net/eagle0/eagle/library/util:battalion_utils",
@@ -6,6 +6,7 @@ import net.eagle0.eagle.library.settings.{
FocusProvinceStorageMultiplier,
FoodIncreasePerAgriculture,
GoldIncreasePerEconomy,
HeroCapDivisor,
MinSupportForTaxes,
PerDevelopmentResourceLimit
}
@@ -67,6 +68,15 @@ object ProvinceUtils {
def effectiveInfrastructure(province: ProvinceT): Double =
(province.infrastructure - province.infrastructureDevastation).max(0.0)
def heroCap(province: ProvinceT): Int =
heroCap(effectiveInfrastructure(province))
def heroCap(effectiveInfrastructure: Double): Int = {
val divisor = HeroCapDivisor.doubleValue
if !(divisor > 0.0) then throw new EagleInternalException(s"HeroCapDivisor must be positive, but was $divisor")
(effectiveInfrastructure.max(0.0) / divisor).floor.toInt.max(1)
}
def goldCap(province: ProvinceT, isFocusProvince: Boolean): Int =
resourceCap(effectiveEconomy(province), effectiveInfrastructure(province), isFocusProvince)
@@ -15,6 +15,7 @@ scala_library(
"//src/main/protobuf/net/eagle0/eagle/common:command_type_scala_proto",
"//src/main/protobuf/net/eagle0/eagle/internal:province_scala_proto",
"//src/main/scala/net/eagle0/eagle:eagle_pkg",
"//src/main/scala/net/eagle0/eagle/library/util/province",
"//src/main/scala/net/eagle0/eagle/model/proto_converters:army_converter",
"//src/main/scala/net/eagle0/eagle/model/proto_converters:battalion_type_id_converter",
"//src/main/scala/net/eagle0/eagle/model/proto_converters:battle_revelation_converter",
@@ -24,6 +24,7 @@ import net.eagle0.eagle.internal.unaffiliated_hero.{
CapturedHero as CapturedHeroProto,
UnaffiliatedHero as UnaffiliatedHeroProto
}
import net.eagle0.eagle.library.util.province.ProvinceUtils
import net.eagle0.eagle.model.proto_converters.{
ArmyConverter,
BattalionTypeIdConverter,
@@ -101,7 +102,7 @@ object ProvinceConverter {
pendingConquestInfo: Option[PendingConquestInfo],
hexMapName: String,
castleCount: Int,
heroCap: Int,
_ /* stored hero cap */,
lastCommand: Option[CommandType]
) =>
ProvinceProto(
@@ -148,7 +149,7 @@ object ProvinceConverter {
pendingConquestInfo = pendingConquestInfo.map(PendingConquestInfoConverter.toProto),
hexMapName = hexMapName,
castleCount = castleCount,
heroCap = heroCap
heroCap = ProvinceUtils.heroCap((infrastructure - infrastructureDevastation).max(0.0))
)
}
@@ -189,7 +190,7 @@ object ProvinceConverter {
lastRiotDate: Option[DateProto],
lastCommand: CommandTypeProto,
castleCount: Int,
heroCap: Int,
_ /* stored hero cap */,
deferredChanges: Seq[DeferredChangeProto],
battleRevelations: Seq[BattleRevelationProto],
pendingConquestInfoProto,
@@ -241,7 +242,7 @@ object ProvinceConverter {
pendingConquestInfo = pendingConquestInfoProto.map(PendingConquestInfoConverter.fromProto),
hexMapName = hexMapName,
castleCount = castleCount,
heroCap = heroCap
heroCap = ProvinceUtils.heroCap((infrastructure - infrastructureDevastation).max(0.0))
)
}
}
@@ -66,6 +66,7 @@ scala_library(
"//src/main/scala/net/eagle0/eagle/library/util:map_generator",
"//src/main/scala/net/eagle0/eagle/library/util:price_index_utils",
"//src/main/scala/net/eagle0/eagle/library/util/hero_generator/hero_with_name",
"//src/main/scala/net/eagle0/eagle/library/util/province",
"//src/main/scala/net/eagle0/eagle/model/proto_converters:battalion_type_id_converter",
"//src/main/scala/net/eagle0/eagle/model/proto_converters/province:order_type",
"//src/main/scala/net/eagle0/eagle/model/state/province",
@@ -181,6 +182,7 @@ scala_library(
"//src/main/scala/net/eagle0/eagle/library:engine",
"//src/main/scala/net/eagle0/eagle/library:engine_impl",
"//src/main/scala/net/eagle0/eagle/library/util/hero_generator",
"//src/main/scala/net/eagle0/eagle/library/util/province",
"//src/main/scala/net/eagle0/eagle/model/action_result/concrete:action_result_concrete",
"//src/main/scala/net/eagle0/eagle/model/action_result/types",
"//src/main/scala/net/eagle0/eagle/model/proto_converters:battalion_converter",
@@ -9,6 +9,7 @@ import net.eagle0.eagle.internal.hero.Hero
import net.eagle0.eagle.internal.province.Province
import net.eagle0.eagle.library.util.{MapGenerator, PriceIndexUtils}
import net.eagle0.eagle.library.util.hero_generator.hero_with_name.HeroWithName
import net.eagle0.eagle.library.util.province.ProvinceUtils
import net.eagle0.eagle.library.EagleInternalException
import net.eagle0.eagle.model.proto_converters.province.ProvinceOrderTypeConverter
import net.eagle0.eagle.model.proto_converters.BattalionTypeIdConverter
@@ -173,6 +174,7 @@ object GameParametersUtils {
_.economy := provinceOverrides.economy,
_.agriculture := provinceOverrides.agriculture,
_.infrastructure := provinceOverrides.infrastructure,
_.heroCap := ProvinceUtils.heroCap(provinceOverrides.infrastructure),
_.priceIndex := PriceIndexUtils.steadyState(
provinceOverrides.economy,
provinceOverrides.agriculture,
@@ -206,6 +208,7 @@ object GameParametersUtils {
economy = provinceOverrides.economy,
agriculture = provinceOverrides.agriculture,
infrastructure = provinceOverrides.infrastructure,
heroCap = ProvinceUtils.heroCap(provinceOverrides.infrastructure),
priceIndex = PriceIndexUtils.steadyState(
provinceOverrides.economy,
provinceOverrides.agriculture,
@@ -246,6 +249,7 @@ object GameParametersUtils {
economy = overrides.economy,
agriculture = overrides.agriculture,
infrastructure = overrides.infrastructure,
heroCap = ProvinceUtils.heroCap(overrides.infrastructure),
priceIndex = PriceIndexUtils.steadyState(
overrides.economy,
overrides.agriculture,
@@ -6,6 +6,7 @@ import net.eagle0.common.SeededRandom
import net.eagle0.eagle.internal.game_parameters.SetFaction.StartingTrust
import net.eagle0.eagle.library.{EngineAndResults, EngineAndResultsImpl, EngineImpl}
import net.eagle0.eagle.library.util.hero_generator.HeroGenerator
import net.eagle0.eagle.library.util.province.ProvinceUtils
import net.eagle0.eagle.model.action_result.concrete.ActionResultC
import net.eagle0.eagle.model.action_result.types.ActionResultType
import net.eagle0.eagle.model.proto_converters.faction.FactionConverter
@@ -299,6 +300,7 @@ object TutorialGameCreation {
)
)
val baseProvince = arWithBatts.provinceMap(po.provinceId)
val infrastructure = if po.infrastructure > 0 then po.infrastructure else baseProvince.infrastructure
arWithBatts.withProvince(
baseProvince
.updateWith(
@@ -312,7 +314,8 @@ object TutorialGameCreation {
support = po.support,
economy = if po.economy > 0 then po.economy else baseProvince.economy,
agriculture = if po.agriculture > 0 then po.agriculture else baseProvince.agriculture,
infrastructure = if po.infrastructure > 0 then po.infrastructure else baseProvince.infrastructure
infrastructure = infrastructure,
heroCap = ProvinceUtils.heroCap(infrastructure)
)
)
}
@@ -10,7 +10,6 @@ scala_test(
deps = [
"//src/main/protobuf/net/eagle0/shardok/common:hex_map_scala_proto",
"//src/main/scala/net/eagle0/eagle:eagle_pkg",
"//src/main/scala/net/eagle0/eagle/library/settings:hero_cap_per_castle",
"//src/main/scala/net/eagle0/eagle/library/util:map_generator",
"//src/main/scala/net/eagle0/eagle/model/state/province",
"//src/main/scala/net/eagle0/util:hex_map_utils",
@@ -1,20 +1,15 @@
package net.eagle0.eagle.shardok.maps
import net.eagle0.eagle.library.settings.HeroCapPerCastle
import net.eagle0.eagle.library.util.MapGenerator
import net.eagle0.eagle.model.state.province.{Neighbor, ProvinceT}
import net.eagle0.eagle.ProvinceId
import net.eagle0.shardok.common.hex_map.{HexMap, MonthlyWeather}
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers
import org.scalatest.BeforeAndAfterEach
class MapValidationTest extends AnyFlatSpec with BeforeAndAfterEach with Matchers {
class MapValidationTest extends AnyFlatSpec with Matchers {
import net.eagle0.util.HexMapUtils.hexMap
override def beforeEach(): Unit =
HeroCapPerCastle.setIntValue(3)
private def checkNeighbor(
provinceName: String,
neighbor: Neighbor,
@@ -1,6 +1,6 @@
package net.eagle0.eagle.library.actions.applier
import net.eagle0.eagle.library.settings.{ExtraXpForStatBumpOver100, XpForStatBump}
import net.eagle0.eagle.library.settings.{ExtraXpForStatBumpOver100, HeroCapDivisor, XpForStatBump}
import net.eagle0.eagle.model.action_result.{NotificationDetails, NotificationT}
import net.eagle0.eagle.model.action_result.changed_province.concrete.ChangedProvinceC
import net.eagle0.eagle.model.action_result.concrete.{
@@ -43,6 +43,7 @@ class ActionResultApplierImplTest extends AnyFlatSpec with Matchers with BeforeA
override def beforeEach(): Unit = {
XpForStatBump.setIntValue(100)
ExtraXpForStatBumpOver100.setIntValue(50)
HeroCapDivisor.setDoubleValue(3.0)
}
private val applier = ActionResultApplierImpl(None)
@@ -119,6 +120,33 @@ class ActionResultApplierImplTest extends AnyFlatSpec with Matchers with BeforeA
result.resultingState.actionResultCount shouldBe 8
}
it should "recalculate the hero cap after infrastructure devastation changes" in {
val provinceId = 13
val startingState = baseGameState.copy(
provinces = Map(
provinceId -> ProvinceC(
id = provinceId,
infrastructure = 45,
infrastructureDevastation = 12,
heroCap = 99
)
)
)
val actionResult = ActionResultC(
actionResultType = ActionResultType.UnknownActionUnspecified,
changedProvinces = Vector(
ChangedProvinceC(
provinceId = provinceId,
infrastructureDevastationDelta = Some(6)
)
)
)
val result = applier.applyActionResult(startingState, actionResult)
result.resultingState.provinces(provinceId).heroCap shouldBe 9
}
it should "not advance command tokens for automatic results with an acting faction" in {
val startingState = gameStateWithReturnCommand
val actionResult = ActionResultC(
@@ -7,6 +7,7 @@ scala_test(
"//src/main/scala/net/eagle0/eagle:eagle_pkg",
"//src/main/scala/net/eagle0/eagle/library/actions/applier:action_result_applier_impl",
"//src/main/scala/net/eagle0/eagle/library/settings:extra_xp_for_stat_bump_over100",
"//src/main/scala/net/eagle0/eagle/library/settings:hero_cap_divisor",
"//src/main/scala/net/eagle0/eagle/library/settings:xp_for_stat_bump",
"//src/main/scala/net/eagle0/eagle/model/action_result:notification_trait",
"//src/main/scala/net/eagle0/eagle/model/action_result/changed_province/concrete",
@@ -121,6 +121,7 @@ scala_test(
"//src/main/scala/net/eagle0/eagle/library/settings:base_resource_limit",
"//src/main/scala/net/eagle0/eagle/library/settings:focus_province_storage_multiplier",
"//src/main/scala/net/eagle0/eagle/library/settings:food_increase_per_agriculture",
"//src/main/scala/net/eagle0/eagle/library/settings:hero_cap_divisor",
"//src/main/scala/net/eagle0/eagle/library/settings:improvement_per_stat",
"//src/main/scala/net/eagle0/eagle/library/settings:improvement_reduction_max",
"//src/main/scala/net/eagle0/eagle/library/settings:improvement_support_gain",
@@ -168,7 +169,6 @@ scala_test(
srcs = ["ShardokMapInfoTest.scala"],
scalacopts = ["-deprecation"],
deps = [
"//src/main/scala/net/eagle0/eagle/library/settings:hero_cap_per_castle",
"//src/main/scala/net/eagle0/eagle/library/util:shardok_map_info",
],
)
@@ -6,6 +6,7 @@ import net.eagle0.eagle.library.settings.{
BaseResourceLimit,
FocusProvinceStorageMultiplier,
FoodIncreasePerAgriculture,
HeroCapDivisor,
ImprovementPerStat,
ImprovementReductionMax,
ImprovementSupportGain,
@@ -82,6 +83,7 @@ class ProvinceUtilsTest extends AnyFlatSpec with Matchers with BeforeAndAfterEac
BaseResourceLimit.setIntValue(5000)
PerDevelopmentResourceLimit.setIntValue(50)
FocusProvinceStorageMultiplier.setDoubleValue(1.5)
HeroCapDivisor.setDoubleValue(3.0)
}
"provinceLeader" should "return the faction head if present" in {
@@ -374,6 +376,22 @@ class ProvinceUtilsTest extends AnyFlatSpec with Matchers with BeforeAndAfterEac
ProvinceUtils.containsFactionLeader(province, Vector(actingFaction)) shouldBe false
}
"heroCap" should "use effective infrastructure divided by the configured divisor" in {
val province = ProvinceC(
id = 7,
infrastructure = 45,
infrastructureDevastation = 12
)
ProvinceUtils.heroCap(province) shouldBe 11
}
it should "floor fractional values and enforce a minimum cap of one" in {
ProvinceUtils.heroCap(effectiveInfrastructure = 100) shouldBe 33
ProvinceUtils.heroCap(effectiveInfrastructure = 8.99) shouldBe 2
ProvinceUtils.heroCap(effectiveInfrastructure = 0) shouldBe 1
}
"foodCap / goldCap" should "use the base resource cap when the province is not a focus province" in {
val province = ProvinceC(
id = 7,
@@ -1,14 +1,9 @@
package net.eagle0.eagle.library.util
import net.eagle0.eagle.library.settings.HeroCapPerCastle
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers
import org.scalatest.BeforeAndAfterEach
class ShardokMapInfoTest extends AnyFlatSpec with BeforeAndAfterEach with Matchers {
override def beforeEach(): Unit =
HeroCapPerCastle.setIntValue(3)
class ShardokMapInfoTest extends AnyFlatSpec with Matchers {
"mapInfos" should "have Shumal's info in position 1" in {
val mapInfos = ShardokMapInfo.shardokMapInfos
@@ -5,7 +5,6 @@ import net.eagle0.eagle.library.settings.{
AlmsSupportIncreasePerFood,
BaseFoodBuyPrice,
GoldPerHeroHeldBack,
HeroCapPerCastle,
MaxCombatUnitCountPerSide,
MinSupportForTaxes,
MinVigorForMarch,
@@ -71,7 +70,6 @@ class AttackCommandChooserTest extends AnyFlatSpec with Matchers with BeforeAndA
VassalMinimumGoldToSendSupplies.setIntValue(100)
MaxCombatUnitCountPerSide.setIntValue(10)
MinVigorForMarch.setDoubleValue(50)
HeroCapPerCastle.setIntValue(3)
RequiredRatioToAttack.setDoubleValue(1.5)
RequiredRatioToAttackWithoutTakingCastles.setDoubleValue(2.5)
}
@@ -54,7 +54,6 @@ scala_test(
"//src/main/scala/net/eagle0/eagle/library/settings:alms_support_increase_per_food",
"//src/main/scala/net/eagle0/eagle/library/settings:base_food_buy_price",
"//src/main/scala/net/eagle0/eagle/library/settings:gold_per_hero_held_back",
"//src/main/scala/net/eagle0/eagle/library/settings:hero_cap_per_castle",
"//src/main/scala/net/eagle0/eagle/library/settings:max_combat_unit_count_per_side",
"//src/main/scala/net/eagle0/eagle/library/settings:min_support_for_taxes",
"//src/main/scala/net/eagle0/eagle/library/settings:min_vigor_for_march",
@@ -1902,7 +1902,7 @@ class SqliteHistoryTest extends AnyFlatSpec with Matchers with BeforeAndAfterEac
// ---------------- newProvinces "new entity" decomposition (v11 — RED until implemented) ----------------
private def province(id: Int, name: String): ProvinceC =
ProvinceC(id = id, name = name, gold = 100, food = 50)
ProvinceC(id = id, name = name, gold = 100, food = 50, heroCap = 1)
"newProvinces v11 live write + reader" should "round-trip a new province via withNewResults" in {
// newProvinces holds full ProvinceT snapshots (no Changed* wrapper) — the deepest entity. Stored as one proto blob.
@@ -25,6 +25,7 @@ scala_test(
],
deps = [
"//src/main/scala/net/eagle0/eagle/library:engine",
"//src/main/scala/net/eagle0/eagle/library/settings:hero_cap_divisor",
"//src/main/scala/net/eagle0/eagle/library/settings:history_backend",
"//src/main/scala/net/eagle0/eagle/library/settings/loaders:battalion_type_loader",
"//src/main/scala/net/eagle0/eagle/service:in_memory_history",
@@ -2,8 +2,8 @@ package net.eagle0.eagle.service.new_game_creation
import java.nio.file.Files
import net.eagle0.eagle.library.settings.{HeroCapDivisor, HistoryBackend}
import net.eagle0.eagle.library.settings.loaders.BattalionTypeLoader
import net.eagle0.eagle.library.settings.HistoryBackend
import net.eagle0.eagle.service.{GameHistoryFactory, InMemoryHistory}
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers
@@ -104,6 +104,15 @@ class FixedNewGameCreationTest extends AnyFlatSpec with Matchers {
}
}
"GameParametersUtils.provincesWithoutPlayers" should "derive hero caps from generic province infrastructure" in {
HeroCapDivisor.setDoubleValue(3.0)
val provinces =
GameParametersUtils.provincesWithoutPlayers(GameParametersUtils.defaultExpandedGameParameters.gameParameters)
all(provinces.map(_.infrastructure)) shouldBe 20.0
all(provinces.map(_.heroCap)) shouldBe 6
}
"FixedNewGameCreation" should "create the warmup-sized default game" in {
val params = GameParametersUtils.defaultExpandedGameParameters