fix(game): fight before departure and reorder the turn sequence #77
@@ -181,8 +181,13 @@ func (c *Cache) TurnPlanetProductions() {
|
||||
ri := c.RaceIndex(*p.Owner)
|
||||
r := &c.g.Race[ri]
|
||||
|
||||
// upgrade groups and return to in_orbit state
|
||||
productionAvailable := c.PlanetProductionCapacity(pn)
|
||||
// Upgrade groups (most expensive first) and return them to the
|
||||
// in-orbit state, paying for each upgrade once out of the planet's
|
||||
// full production potential; whatever remains feeds this turn's
|
||||
// production below. Starting from PlanetProductionCapacity here would
|
||||
// have charged every applied upgrade twice, since that helper already
|
||||
// nets out the reserved upgrade cost for the report.
|
||||
productionAvailable := p.ProductionCapacity()
|
||||
for sg := range c.shipGroupsInUpgrade(p.Number) {
|
||||
cost := c.upgradeCostNow(sg)
|
||||
if productionAvailable >= cost {
|
||||
|
||||
@@ -208,11 +208,40 @@ func TestProduceShips(t *testing.T) {
|
||||
assert.Equal(t, game.StateInOrbit, c.ShipGroup(0).State())
|
||||
assert.Equal(t, 1.5, c.ShipGroup(0).TechLevel(game.TechDrive).F())
|
||||
|
||||
// Upgrade cost is now recomputed from the group's current ship count
|
||||
// (calc raw float) rather than read from the Fixed12-rounded stored value,
|
||||
// which shifts Material at the 12th decimal — far below the 3-decimal
|
||||
// report precision, so an InDelta check is the robust expectation here.
|
||||
assert.InDelta(t, 4346.6766, c.MustPlanet(R0_Planet_0_num).Material.F(), 0.001)
|
||||
// The pending upgrade is now charged once (not twice) against the planet's
|
||||
// production potential, so MAT production keeps the budget it previously
|
||||
// lost to the double charge (the pre-fix value here was ~4346.68).
|
||||
assert.InDelta(t, 7173.3432, c.MustPlanet(R0_Planet_0_num).Material.F(), 0.001)
|
||||
}
|
||||
|
||||
// TestUpgradeDoesNotDoubleChargeProduction guards that a pending upgrade is
|
||||
// paid for once out of the planet's production potential, leaving the rest for
|
||||
// the turn's production. The pre-fix code subtracted the upgrade cost twice
|
||||
// (PlanetProductionCapacity already nets it out for the report, and the apply
|
||||
// loop netted it again), which both starved production and could skip
|
||||
// affordable upgrades.
|
||||
func TestUpgradeDoesNotDoubleChargeProduction(t *testing.T) {
|
||||
c, _ := newCache()
|
||||
p := c.MustPlanet(R0_Planet_0_num)
|
||||
p.Population = 1000
|
||||
p.Industry = 1000 // ProductionCapacity = 1000*0.75 + 1000*0.25 = 1000
|
||||
p.Resources = 1 // material produced == leftover production budget
|
||||
p.Colonists = 0
|
||||
p.Material = 0
|
||||
assert.NoError(t, c.PlanetProduce(Race_0_idx, int(R0_Planet_0_num), game.ProductionMaterial, ""))
|
||||
|
||||
// One Cruiser with a pending drive upgrade 1.1 -> 2.0:
|
||||
// block cost = (1 - 1.1/2.0) * 10 * 15 = 67.5 for the single ship.
|
||||
assert.NoError(t, c.CreateShips(Race_0_idx, ShipType_Cruiser, R0_Planet_0_num, 1))
|
||||
c.ShipGroup(0).StateUpgrade = &game.InUpgrade{
|
||||
UpgradeTech: []game.UpgradePreference{{Tech: game.TechDrive, Level: 2.0}},
|
||||
}
|
||||
|
||||
c.TurnPlanetProductions()
|
||||
|
||||
assert.InDelta(t, 2.0, c.ShipGroup(0).TechLevel(game.TechDrive).F(), 0.0001)
|
||||
// 1000 - 67.5 = 932.5; the pre-fix double charge would have left 865.
|
||||
assert.InDelta(t, 932.5, c.MustPlanet(R0_Planet_0_num).Material.F(), 0.01)
|
||||
}
|
||||
|
||||
func TestProduceShip(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user