refactor: float64 types for storage and report

This commit is contained in:
Ilia Denisov
2026-02-02 13:14:57 +02:00
parent 4c14234afb
commit a567229f8a
24 changed files with 264 additions and 253 deletions
+2 -2
View File
@@ -65,9 +65,9 @@ func FilterBattleOpponents(c *Cache, attIdx, defIdx int, cacheProbability map[in
p := DestructionProbability(
c.ShipGroupShipClass(attIdx).Weapons,
c.ShipGroup(attIdx).TechLevel(game.TechWeapons),
c.ShipGroup(attIdx).TechLevel(game.TechWeapons).F(),
c.ShipGroupShipClass(defIdx).Shields,
c.ShipGroup(defIdx).TechLevel(game.TechShields),
c.ShipGroup(defIdx).TechLevel(game.TechShields).F(),
c.ShipGroup(defIdx).FullMass(c.ShipGroupShipClass(defIdx)),
)
// Exclude opponent's group which cannot be probably destroyed
+5 -5
View File
@@ -30,11 +30,11 @@ func TransformBattle(c *Cache, b *Battle) *report.BattleReport {
NumberLeft: sg.Number,
ClassName: shipClass.Name,
LoadType: sg.CargoString(),
LoadQuantity: sg.Load,
Drive: sg.TechLevel(game.TechDrive),
Weapons: sg.TechLevel(game.TechWeapons),
Shields: sg.TechLevel(game.TechShields),
Cargo: sg.TechLevel(game.TechCargo),
LoadQuantity: sg.Load.RF(),
Drive: sg.TechLevel(game.TechDrive).RF(),
Weapons: sg.TechLevel(game.TechWeapons).RF(),
Shields: sg.TechLevel(game.TechShields).RF(),
Cargo: sg.TechLevel(game.TechCargo).RF(),
}
cacheShipClass[shipClass.ID] = itemNumber
return itemNumber
+17 -17
View File
@@ -20,12 +20,12 @@ func (c *Cache) bombingReport(p *game.Planet, ri int, groups []int) report.Bombi
Owner: c.g.Race[c.RaceIndex(p.Owner)].Name,
Attacker: c.g.Race[ri].Name,
Production: c.PlanetProductionDisplayName(p.Number),
Industry: p.Industry,
Population: p.Population,
Colonists: p.Colonists,
Capital: p.Capital,
Material: p.Material,
AttackPower: attackPower,
Industry: p.Industry.RF(),
Population: p.Population.RF(),
Colonists: p.Colonists.RF(),
Capital: p.Capital.RF(),
Material: p.Material.RF(),
AttackPower: game.RF(attackPower),
}
bombPlanet(p, attackPower)
r.Wiped = p.Population == 0
@@ -61,23 +61,23 @@ func (c *Cache) ProduceBombings() []report.BombingPlanetReport {
func bombPlanet(p *game.Planet, power float64) {
// Уничтожается население и колонисты в количестве равном [суммарной] мощности бомбардировки
if power > p.Population {
p.Population = 0
if power > p.Population.F() {
p.Pop(0)
} else {
p.Population -= power
p.Pop(p.Population.F() - power)
}
if power > p.Colonists {
p.Colonists = 0
if power > p.Colonists.F() {
p.Col(0)
} else {
p.Colonists -= power
p.Col(p.Colonists.F() - power)
}
// Такое же количество промышленности превращается в сырье
if power > p.Industry {
p.Material += p.Industry
p.Industry = 0
if power > p.Industry.F() {
p.Mat(p.Material.F() + p.Industry.F())
p.Ind(0)
} else {
p.Material += power
p.Industry -= power
p.Mat(p.Material.F() + power)
p.Ind(p.Industry.F() - power)
}
}
+17 -17
View File
@@ -12,25 +12,25 @@ import (
func TestBombPlanet(t *testing.T) {
p := controller.NewPlanet(0, "Planet_0", uuid.New(), 1, 1, 1000, 300, 200, 10, game.ResearchDrive.AsType(uuid.Nil))
(&p).Colonists = 100.
assert.Equal(t, 0., p.Material)
assert.Equal(t, 0., p.Material.F())
controller.BombPlanet(&p, 55.)
assert.Equal(t, 245., p.Population)
assert.Equal(t, 45., p.Colonists)
assert.Equal(t, 145., p.Industry)
assert.Equal(t, 55., p.Material)
assert.Equal(t, 245., p.Population.F())
assert.Equal(t, 45., p.Colonists.F())
assert.Equal(t, 145., p.Industry.F())
assert.Equal(t, 55., p.Material.F())
controller.BombPlanet(&p, 56.)
assert.Equal(t, 189., p.Population)
assert.Equal(t, 0., p.Colonists)
assert.Equal(t, 89., p.Industry)
assert.Equal(t, 111., p.Material)
assert.Equal(t, 189., p.Population.F())
assert.Equal(t, 0., p.Colonists.F())
assert.Equal(t, 89., p.Industry.F())
assert.Equal(t, 111., p.Material.F())
controller.BombPlanet(&p, 200.)
assert.Equal(t, 0., p.Population)
assert.Equal(t, 0., p.Colonists)
assert.Equal(t, 0., p.Industry)
assert.Equal(t, 200., p.Material)
assert.Equal(t, 0., p.Population.F())
assert.Equal(t, 0., p.Colonists.F())
assert.Equal(t, 0., p.Industry.F())
assert.Equal(t, 200., p.Material.F())
}
func TestCollectBombingGroups(t *testing.T) {
@@ -126,19 +126,19 @@ func TestProduceBombings(t *testing.T) {
case R1_Planet_1_num:
assert.Equal(t, Race_1.Name, r.Owner)
assert.Equal(t, Race_0.Name, r.Attacker)
assert.InDelta(t, 697.857, r.AttackPower, 0.0003)
assert.InDelta(t, 697.857, r.AttackPower.F(), 0.0003)
assert.True(t, r.Wiped)
assert.Equal(t, uuid.Nil, c.MustPlanet(pn).Owner)
assert.Empty(t, c.MustPlanet(pn).Route)
assert.Equal(t, 0., c.MustPlanet(pn).Population)
assert.Equal(t, 0., c.MustPlanet(pn).Population.F())
case R0_Planet_2_num:
assert.Equal(t, Race_0.Name, r.Owner)
assert.Equal(t, Race_1.Name, r.Attacker)
assert.InDelta(t, 358.85596, r.AttackPower, 0.000001)
assert.Equal(t, 358.856, r.AttackPower.F())
assert.False(t, r.Wiped)
assert.Equal(t, Race_0_ID, c.MustPlanet(pn).Owner)
assert.NotEmpty(t, c.MustPlanet(pn).Route)
assert.InDelta(t, 500.-358.85596, c.MustPlanet(pn).Population, 0.000001)
assert.InDelta(t, 500.-358.85596, c.MustPlanet(pn).Population.F(), 0.000001)
}
}
}
+1 -1
View File
@@ -34,7 +34,7 @@ func (c *Cache) SendFleet(ri, fi int, planetNumber uint) error {
if !ok {
return e.NewEntityNotExistsError("destination planet #%d", planetNumber)
}
rangeToDestination := util.ShortDistance(c.g.Map.Width, c.g.Map.Height, p1.X, p1.Y, p2.X, p2.Y)
rangeToDestination := util.ShortDistance(c.g.Map.Width, c.g.Map.Height, p1.X.F(), p1.Y.F(), p2.X.F(), p2.Y.F())
if rangeToDestination > c.g.Race[ri].FlightDistance() {
return e.NewSendUnreachableDestinationError("range=%.03f", rangeToDestination)
}
+6 -6
View File
@@ -134,16 +134,16 @@ func NewPlanet(num uint, name string, owner uuid.UUID, x, y, size, pop, ind, res
PlanetReport: game.PlanetReport{
UninhabitedPlanet: game.UninhabitedPlanet{
UnidentifiedPlanet: game.UnidentifiedPlanet{
X: x,
Y: y,
X: game.F(x),
Y: game.F(y),
Number: num,
},
Size: size,
Size: game.F(size),
Name: name,
Resources: res,
Resources: game.F(res),
},
Population: pop,
Industry: ind,
Population: game.F(pop),
Industry: game.F(ind),
Production: prod,
},
}
+7 -7
View File
@@ -108,7 +108,7 @@ func (c *Cache) PlanetProduction(ri int, number int, prod game.ProductionType, s
if p.Production.Type == game.ProductionShip && (prod != game.ProductionShip || *subjectID != *p.Production.SubjectID) {
mat, _ := c.MustShipType(ri, *p.Production.SubjectID).ProductionCost()
p.Material += mat * (*p.Production.Progress)
p.Mat(p.Material.F() + mat*(*p.Production.Progress))
*p.Production.Progress = 0.
} else if prod == game.ProductionShip {
// new ship class to produce; otherwise we must have been returned from the func earlier
@@ -265,15 +265,15 @@ func (c *Cache) listProducingPlanets() iter.Seq[uint] {
// Internal funcs
func (c *Cache) putPopulation(pn uint, v float64) {
c.MustPlanet(pn).Population = v
c.MustPlanet(pn).Pop(v)
}
func (c *Cache) putColonists(pn uint, v float64) {
c.MustPlanet(pn).Colonists = v
c.MustPlanet(pn).Col(v)
}
func (c *Cache) putMaterial(pn uint, v float64) {
c.MustPlanet(pn).Material = v
c.MustPlanet(pn).Mat(v)
}
func ProduceShip(p *game.Planet, shipMass float64) uint {
@@ -281,20 +281,20 @@ func ProduceShip(p *game.Planet, shipMass float64) uint {
if productionAvailable <= 0 {
return 0
}
CAP_perShip := shipMass / p.Resources
CAP_perShip := shipMass / p.Resources.F()
productionForMass := shipMass * 10.
ships := uint(0)
flZero := 0.
p.Production.Progress = &flZero
for productionAvailable > 0 {
var productionExtraCAP float64
if CAP_deficit := p.Capital - CAP_perShip; CAP_deficit < 0 {
if CAP_deficit := p.Capital.F() - CAP_perShip; CAP_deficit < 0 {
productionExtraCAP = -CAP_deficit
}
productionCost := productionExtraCAP + productionForMass
if productionAvailable >= productionCost {
productionAvailable -= productionCost
p.Capital = p.Capital - (CAP_perShip - productionExtraCAP)
p.Cap(p.Capital.F() - (CAP_perShip - productionExtraCAP))
ships++
} else {
progress := productionAvailable / productionCost
+9 -9
View File
@@ -152,7 +152,7 @@ func TestProduceShips(t *testing.T) {
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 1)
assert.Equal(t, uint(7), c.ShipGroup(0).Number)
assert.NoError(t, g.PlanetProduction(Race_0.Name, pn, "SHIP", "Drone"))
assert.InDelta(t, shipMass*progress, c.MustPlanet(R0_Planet_0_num).Material, 0.00001) // 99.(0099) material build
assert.InDelta(t, shipMass*progress, c.MustPlanet(R0_Planet_0_num).Material.F(), 0.00001) // 99.(0099) material build
c.MustPlanet(R0_Planet_0_num).Material = 0
c.MustPlanet(R0_Planet_0_num).Colonists = 0
@@ -197,7 +197,7 @@ func TestProduceShip(t *testing.T) {
r = controller.ProduceShip(&p, Drone.EmptyMass())
assert.Equal(t, uint(100), r)
assert.Equal(t, 0., *p.Production.Progress)
assert.Equal(t, 0., number.Fixed3(p.Capital)) // TODO: zero CAP is not actual '0.0' after series of decrements
assert.Equal(t, 0., number.Fixed3(p.Capital.F())) // TODO: zero CAP is not actual '0.0' after series of decrements
(&p).Production = game.ProductionShip.AsType(uuid.Nil)
(&p).Capital = 0.
@@ -242,17 +242,17 @@ func TestTurnPlanetProductions(t *testing.T) {
pn := int(R0_Planet_0_num)
assert.NoError(t, g.PlanetProduction(Race_0.Name, pn, "CAP", ""))
assert.Equal(t, 0.0, c.MustPlanet(R0_Planet_0_num).Capital)
assert.Equal(t, 0.0, c.MustPlanet(R0_Planet_0_num).Colonists)
assert.Equal(t, 0.0, c.MustPlanet(R0_Planet_0_num).Capital.F())
assert.Equal(t, 0.0, c.MustPlanet(R0_Planet_0_num).Colonists.F())
c.TurnPlanetProductions()
assert.InDelta(t, 196., c.MustPlanet(R0_Planet_0_num).Capital, 0.1)
assert.InDelta(t, 10.0, c.MustPlanet(R0_Planet_0_num).Colonists, 0.000001) // FIXME: should store more exact value
assert.InDelta(t, 196., c.MustPlanet(R0_Planet_0_num).Capital.F(), 0.1)
assert.InDelta(t, 10.0, c.MustPlanet(R0_Planet_0_num).Colonists.F(), 0.000001) // FIXME: should store more exact value
assert.NoError(t, g.PlanetProduction(Race_0.Name, pn, "MAT", ""))
assert.Equal(t, 0.0, c.MustPlanet(R0_Planet_0_num).Material)
assert.Equal(t, 0.0, c.MustPlanet(R0_Planet_0_num).Material.F())
c.TurnPlanetProductions()
assert.Equal(t, 10000., c.MustPlanet(R0_Planet_0_num).Material)
assert.InDelta(t, 20.0, c.MustPlanet(R0_Planet_0_num).Colonists, 0.000001)
assert.Equal(t, 10000., c.MustPlanet(R0_Planet_0_num).Material.F())
assert.InDelta(t, 20.0, c.MustPlanet(R0_Planet_0_num).Colonists.F(), 0.000001)
assert.NoError(t, g.PlanetProduction(Race_0.Name, pn, "DRIVE", ""))
assert.Equal(t, 1.1, c.Race(Race_0_idx).TechLevel(game.TechDrive))
+8 -8
View File
@@ -39,7 +39,7 @@ func (c *Cache) SetRoute(ri int, rt game.RouteType, origin, destination uint) er
if !ok {
return e.NewEntityNotExistsError("destination planet #%d", destination)
}
rangeToDestination := util.ShortDistance(c.g.Map.Width, c.g.Map.Height, p1.X, p1.Y, p2.X, p2.Y)
rangeToDestination := util.ShortDistance(c.g.Map.Width, c.g.Map.Height, p1.X.F(), p1.Y.F(), p2.X.F(), p2.Y.F())
if rangeToDestination > c.g.Race[ri].FlightDistance() {
return e.NewSendUnreachableDestinationError("range=%.03f max=%.03f", rangeToDestination, c.g.Race[ri].FlightDistance())
}
@@ -127,7 +127,7 @@ func (c *Cache) SendRoutedGroups() {
if !ok {
continue
}
var res *float64
var res *game.Float
var ct game.CargoType
switch rt {
case game.RouteColonist:
@@ -152,7 +152,7 @@ func (c *Cache) SendRoutedGroups() {
st := c.ShipGroupShipClass(sgi)
ships := sg.Number
sgCapacity := sg.CargoCapacity(st)
toLoad := *res
toLoad := (*res).F()
if toLoad > sgCapacity {
toLoad = sgCapacity
} else if maxShips := uint(math.Ceil(toLoad / (sgCapacity / float64(ships)))); maxShips < ships {
@@ -160,9 +160,9 @@ func (c *Cache) SendRoutedGroups() {
sg = c.ShipGroup(newGroupIdx)
}
// decrease planet resource
*res = *res - toLoad
*res = (*res).Add(-toLoad)
// load group
sg.Load += toLoad
sg.Load = sg.Load.Add(toLoad)
sg.CargoType = &ct
c.LaunchShips(sg, dest)
groups = reorderGroups(groups)
@@ -214,7 +214,7 @@ func (c *Cache) RemoveUnreachableRoutes() {
ri := c.RaceIndex(p1.Owner)
for rt, destination := range p1.Route {
p2 := c.MustPlanet(destination)
rangeToDestination := util.ShortDistance(c.g.Map.Width, c.g.Map.Height, p1.X, p1.Y, p2.X, p2.Y)
rangeToDestination := util.ShortDistance(c.g.Map.Width, c.g.Map.Height, p1.X.F(), p1.Y.F(), p2.X.F(), p2.Y.F())
if rangeToDestination > c.g.Race[ri].FlightDistance() {
delete(p1.Route, rt)
}
@@ -224,7 +224,7 @@ func (c *Cache) RemoveUnreachableRoutes() {
func (c *Cache) doUnload(groups iter.Seq[int]) {
for sgi := range groups {
c.unsafeUnloadCargo(sgi, c.ShipGroup(sgi).Load)
c.unsafeUnloadCargo(sgi, c.ShipGroup(sgi).Load.F())
}
}
@@ -255,7 +255,7 @@ func (c *Cache) selectColUnloadGroup(groups []int) (result iter.Seq[int]) {
sg := c.ShipGroup(i)
ri := c.RaceIndex(sg.OwnerID)
groupByRace[ri] = append(groupByRace[ri], i)
loadByRace[ri] += sg.Load
loadByRace[ri] += sg.Load.F()
}
if len(loadByRace) < 2 {
// only one race has to unload cargo
+18 -18
View File
@@ -129,7 +129,7 @@ func TestListRoutedSendGroupIds(t *testing.T) {
assert.Equal(t, Race_0_ID, sg.OwnerID)
assert.Greater(t, sg.CargoCapacity(st), 0.)
assert.Equal(t, game.StateInOrbit, sg.State())
assert.Equal(t, 0., sg.Load)
assert.Equal(t, 0., sg.Load.F())
assert.Nil(t, sg.FleetID)
}
}
@@ -149,11 +149,11 @@ func TestEnrouteGroups_SplitGroup(t *testing.T) {
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 2)
assert.Equal(t, game.StateInOrbit, c.ShipGroup(0).State())
assert.Equal(t, uint(1), c.ShipGroup(0).Number)
assert.Equal(t, 0., c.ShipGroup(0).Load)
assert.Equal(t, 0., c.ShipGroup(0).Load.F())
assert.Equal(t, game.StateLaunched, c.ShipGroup(1).State())
assert.Equal(t, uint(4), c.ShipGroup(1).Number)
assert.Equal(t, 65., c.ShipGroup(1).Load)
assert.Equal(t, 0., c.MustPlanet(R0_Planet_0_num).Colonists)
assert.Equal(t, 65., c.ShipGroup(1).Load.F())
assert.Equal(t, 0., c.MustPlanet(R0_Planet_0_num).Colonists.F())
}
func TestEnrouteGroups_GroupSorting(t *testing.T) {
@@ -177,8 +177,8 @@ func TestEnrouteGroups_GroupSorting(t *testing.T) {
assert.Equal(t, game.StateInOrbit, c.ShipGroup(0).State())
assert.Equal(t, game.StateLaunched, c.ShipGroup(1).State())
assert.Equal(t, 100., c.ShipGroup(1).Load)
assert.Equal(t, 0., c.MustPlanet(R0_Planet_0_num).Colonists)
assert.Equal(t, 100., c.ShipGroup(1).Load.F())
assert.Equal(t, 0., c.MustPlanet(R0_Planet_0_num).Colonists.F())
}
func TestEnrouteGroups_LaunchOrder(t *testing.T) {
@@ -215,7 +215,7 @@ func TestEnrouteGroups_LaunchOrder(t *testing.T) {
sgi := 0
assert.Equal(t, game.StateLaunched, c.ShipGroup(sgi).State())
assert.Equal(t, R0_Planet_2_num, c.ShipGroup(sgi).Destination)
assert.Equal(t, 105., c.ShipGroup(sgi).Load)
assert.Equal(t, 105., c.ShipGroup(sgi).Load.F())
assert.NotNil(t, c.ShipGroup(sgi).CargoType)
assert.Equal(t, game.CargoColonist, *c.ShipGroup(sgi).CargoType)
assert.Equal(t, uint(5), c.ShipGroup(sgi).Number)
@@ -224,7 +224,7 @@ func TestEnrouteGroups_LaunchOrder(t *testing.T) {
sgi = 3
assert.Equal(t, game.StateLaunched, c.ShipGroup(sgi).State())
assert.Equal(t, R0_Planet_2_num, c.ShipGroup(sgi).Destination)
assert.Equal(t, 45., c.ShipGroup(sgi).Load)
assert.Equal(t, 45., c.ShipGroup(sgi).Load.F())
assert.NotNil(t, c.ShipGroup(sgi).CargoType)
assert.Equal(t, game.CargoColonist, *c.ShipGroup(sgi).CargoType)
assert.Equal(t, uint(3), c.ShipGroup(sgi).Number)
@@ -233,7 +233,7 @@ func TestEnrouteGroups_LaunchOrder(t *testing.T) {
sgi = 2
assert.Equal(t, game.StateLaunched, c.ShipGroup(sgi).State())
assert.Equal(t, R0_Planet_2_num, c.ShipGroup(sgi).Destination)
assert.Equal(t, 100., c.ShipGroup(sgi).Load)
assert.Equal(t, 100., c.ShipGroup(sgi).Load.F())
assert.NotNil(t, c.ShipGroup(sgi).CargoType)
assert.Equal(t, game.CargoCapital, *c.ShipGroup(sgi).CargoType)
assert.Equal(t, uint(5), c.ShipGroup(sgi).Number)
@@ -242,7 +242,7 @@ func TestEnrouteGroups_LaunchOrder(t *testing.T) {
sgi = 4
assert.Equal(t, game.StateLaunched, c.ShipGroup(sgi).State())
assert.Equal(t, R0_Planet_2_num, c.ShipGroup(sgi).Destination)
assert.Equal(t, 20., c.ShipGroup(sgi).Load)
assert.Equal(t, 20., c.ShipGroup(sgi).Load.F())
assert.NotNil(t, c.ShipGroup(sgi).CargoType)
assert.Equal(t, game.CargoMaterial, *c.ShipGroup(sgi).CargoType)
assert.Equal(t, uint(1), c.ShipGroup(sgi).Number)
@@ -251,7 +251,7 @@ func TestEnrouteGroups_LaunchOrder(t *testing.T) {
sgi = 1
assert.Equal(t, game.StateLaunched, c.ShipGroup(sgi).State())
assert.Equal(t, R1_Planet_1_num, c.ShipGroup(sgi).Destination)
assert.Equal(t, 0., c.ShipGroup(sgi).Load)
assert.Equal(t, 0., c.ShipGroup(sgi).Load.F())
assert.Nil(t, c.ShipGroup(sgi).CargoType)
assert.Equal(t, uint(1), c.ShipGroup(sgi).Number)
}
@@ -406,15 +406,15 @@ func TestTurnUnloadEnroutedGroups(t *testing.T) {
c.TurnUnloadEnroutedGroups()
assert.Equal(t, 0., c.ShipGroup(0).Load)
assert.Equal(t, 222., c.MustPlanet(R0_Planet_0_num).Material)
assert.Equal(t, 0., c.ShipGroup(1).Load)
assert.Equal(t, 11., c.MustPlanet(R0_Planet_0_num).Capital)
assert.Equal(t, 0., c.ShipGroup(2).Load)
assert.Equal(t, 96.8, c.MustPlanet(Uninhabited_Planet_4_num).Population)
assert.Equal(t, 0., c.ShipGroup(0).Load.F())
assert.Equal(t, 222., c.MustPlanet(R0_Planet_0_num).Material.F())
assert.Equal(t, 0., c.ShipGroup(1).Load.F())
assert.Equal(t, 11., c.MustPlanet(R0_Planet_0_num).Capital.F())
assert.Equal(t, 0., c.ShipGroup(2).Load.F())
assert.Equal(t, 96.8, c.MustPlanet(Uninhabited_Planet_4_num).Population.F())
assert.Equal(t, Race_1_ID, c.MustPlanet(Uninhabited_Planet_4_num).Owner)
assert.Equal(t, game.ProductionCapital, c.MustPlanet(Uninhabited_Planet_4_num).Production.Type)
assert.Equal(t, 17.3, c.ShipGroup(3).Load)
assert.Equal(t, 17.3, c.ShipGroup(3).Load.F())
}
func TestRemoveUnreachableRoutes(t *testing.T) {
+17 -17
View File
@@ -61,7 +61,7 @@ func (c *Cache) ShipGroupJoinFleet(groupIndex int, fID *uuid.UUID) {
func (c *Cache) ShipGroupShipsNumber(groupIndex int, number uint) {
c.validateShipGroupIndex(groupIndex)
if c.g.ShipGroups[groupIndex].Number > 0 {
c.g.ShipGroups[groupIndex].Load = c.g.ShipGroups[groupIndex].Load / float64(c.g.ShipGroups[groupIndex].Number) * float64(number)
c.g.ShipGroups[groupIndex].Load = game.F(c.g.ShipGroups[groupIndex].Load.F() / float64(c.g.ShipGroups[groupIndex].Number) * float64(number))
}
c.g.ShipGroups[groupIndex].Number = number
}
@@ -228,20 +228,20 @@ func (c *Cache) DisassembleGroup(ri int, groupIndex, quantity uint) error {
if c.ShipGroup(sgi).CargoType != nil {
ct := *c.ShipGroup(sgi).CargoType
load := c.ShipGroup(sgi).Load
load := c.ShipGroup(sgi).Load.F()
switch ct {
case game.CargoColonist:
if p.Owner == c.g.Race[ri].ID {
p = game.UnloadColonists(p, load)
}
case game.CargoMaterial:
p.Material += load
p.Material = p.Material.Add(load)
case game.CargoCapital:
p.Capital += load
p.Capital = p.Capital.Add(load)
}
}
p.Material += c.ShipGroup(sgi).EmptyMass(st)
p.Material = p.Material.Add(c.ShipGroup(sgi).EmptyMass(st))
c.unsafeDeleteShipGroup(sgi)
@@ -300,11 +300,11 @@ func (c *Cache) LoadCargo(ri int, groupIndex uint, ct game.CargoType, ships uint
sgi = nsgi
}
capacity := c.ShipGroup(sgi).CargoCapacity(st)
freeShipGroupCargoLoad := capacity - c.ShipGroup(sgi).Load
freeShipGroupCargoLoad := capacity - c.ShipGroup(sgi).Load.F()
if freeShipGroupCargoLoad == 0 {
return e.NewCargoLoadNoSpaceLeftError()
}
var availableOnPlanet *float64
var availableOnPlanet *game.Float
switch ct {
case game.CargoMaterial:
availableOnPlanet = &p.Material
@@ -315,18 +315,18 @@ func (c *Cache) LoadCargo(ri int, groupIndex uint, ct game.CargoType, ships uint
default:
return e.NewGameStateError("CargoType not accepted: %v", ct)
}
if quantity > *availableOnPlanet || *availableOnPlanet == 0 {
if quantity > float64(*availableOnPlanet) || *availableOnPlanet == 0 {
return e.NewCargoLoadNotEnoughError("planet: #%d, %s=%.03f", p.Number, ct, *availableOnPlanet)
}
toBeLoaded := quantity
if quantity == 0 {
toBeLoaded = *availableOnPlanet
toBeLoaded = float64(*availableOnPlanet)
}
if toBeLoaded > freeShipGroupCargoLoad {
toBeLoaded = freeShipGroupCargoLoad
}
*availableOnPlanet = *availableOnPlanet - toBeLoaded
c.ShipGroup(sgi).Load += toBeLoaded
*availableOnPlanet = (*availableOnPlanet).Add(-toBeLoaded)
c.ShipGroup(sgi).Load = c.ShipGroup(sgi).Load.Add(toBeLoaded)
if c.ShipGroup(sgi).Load > 0 {
c.ShipGroup(sgi).CargoType = &ct
}
@@ -379,9 +379,9 @@ func (c *Cache) UnloadCargo(ri int, groupIndex uint, ships uint, quantity float6
toBeUnloaded := quantity
if quantity == 0 {
toBeUnloaded = c.ShipGroup(sgi).Load
toBeUnloaded = c.ShipGroup(sgi).Load.F()
}
if toBeUnloaded > c.ShipGroup(sgi).Load {
if toBeUnloaded > c.ShipGroup(sgi).Load.F() {
return e.NewCargoUnoadNotEnoughError("load: %.03f", c.ShipGroup(sgi).Load)
}
@@ -401,7 +401,7 @@ func (c *Cache) unsafeUnloadCargo(sgi int, q float64) {
p := c.MustPlanet(c.ShipGroup(sgi).Destination)
ct := *c.ShipGroup(sgi).CargoType
var availableOnPlanet *float64
var availableOnPlanet *game.Float
switch ct {
case game.CargoColonist:
availableOnPlanet = &p.Colonists
@@ -414,9 +414,9 @@ func (c *Cache) unsafeUnloadCargo(sgi int, q float64) {
case game.CargoCapital:
availableOnPlanet = &p.Capital
}
*availableOnPlanet += q
*availableOnPlanet = (*availableOnPlanet).Add(q)
c.ShipGroup(sgi).Load -= q // TODO: apply rounding for Load property?
c.ShipGroup(sgi).Load = c.ShipGroup(sgi).Load.Add(-q) // TODO: apply rounding for Load property?
if c.ShipGroup(sgi).Load == 0 {
c.ShipGroup(sgi).CargoType = nil
}
@@ -532,7 +532,7 @@ func (c *Cache) breakGroupSafe(ri int, groupIndex uint, newGroupShips uint) (int
func (c *Cache) breakGroupUnsafe(ri, sgi int, newGroupShips uint) int {
newGroup := *c.ShipGroup(sgi)
if c.ShipGroup(sgi).CargoType != nil {
newGroup.Load = c.ShipGroup(sgi).Load / float64(c.ShipGroup(sgi).Number) * float64(newGroupShips)
newGroup.Load = game.F(c.ShipGroup(sgi).Load.F() / float64(c.ShipGroup(sgi).Number) * float64(newGroupShips))
}
newGroup.Number = newGroupShips
c.ShipGroupShipsNumber(sgi, c.ShipGroup(sgi).Number-newGroup.Number)
+1 -1
View File
@@ -40,7 +40,7 @@ func (c *Cache) moveShipGroup(i int, delta float64) {
destPlanet := c.MustPlanet(sg.Destination)
arrived := false
sg.StateInSpace.X, sg.StateInSpace.Y, arrived =
util.NextTravelCoord(c.g.Map.Width, c.g.Map.Height, originX, originY, destPlanet.X, destPlanet.Y, delta)
util.NextTravelCoord(c.g.Map.Width, c.g.Map.Height, originX, originY, destPlanet.X.F(), destPlanet.Y.F(), delta)
if arrived {
sg.StateInSpace = nil
}
+2 -2
View File
@@ -44,7 +44,7 @@ func (c *Cache) SendGroup(ri int, groupIndex, planetNumber, quantity uint) error
if !ok {
return e.NewEntityNotExistsError("destination planet #%d", planetNumber)
}
rangeToDestination := util.ShortDistance(c.g.Map.Width, c.g.Map.Height, p1.X, p1.Y, p2.X, p2.Y)
rangeToDestination := util.ShortDistance(c.g.Map.Width, c.g.Map.Height, p1.X.F(), p1.Y.F(), p2.X.F(), p2.Y.F())
if rangeToDestination > c.g.Race[ri].FlightDistance() {
return e.NewSendUnreachableDestinationError("range=%.03f", rangeToDestination)
}
@@ -81,7 +81,7 @@ func (c *Cache) LaunchShips(sg *game.ShipGroup, destination uint) *game.ShipGrou
default:
panic("state invalid")
}
c.g.ShipGroups[i] = LaunchShips(*sg, destination, p.X, p.Y)
c.g.ShipGroups[i] = LaunchShips(*sg, destination, p.X.F(), p.Y.F())
return &c.g.ShipGroups[i]
}
}
+4 -4
View File
@@ -51,8 +51,8 @@ func TestSendGroup(t *testing.T) {
assert.Equal(t, uint(3), c.ShipGroup(3).Number)
assert.Equal(t, game.StateLaunched, c.ShipGroup(3).State())
assert.NotNil(t, c.ShipGroup(3).StateInSpace)
assert.Equal(t, c.MustPlanet(R0_Planet_0_num).X, c.ShipGroup(3).StateInSpace.X)
assert.Equal(t, c.MustPlanet(R0_Planet_0_num).Y, c.ShipGroup(3).StateInSpace.Y)
assert.Equal(t, c.MustPlanet(R0_Planet_0_num).X.F(), c.ShipGroup(3).StateInSpace.X)
assert.Equal(t, c.MustPlanet(R0_Planet_0_num).Y.F(), c.ShipGroup(3).StateInSpace.Y)
assert.NoError(t, g.SendGroup(Race_0.Name, 4, R0_Planet_0_num, 2)) // un-send 2 of 3
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 4)
@@ -61,8 +61,8 @@ func TestSendGroup(t *testing.T) {
assert.Equal(t, uint(1), c.MustShipGroup(Race_0_idx, 4).Number)
assert.Equal(t, game.StateLaunched, c.MustShipGroup(Race_0_idx, 4).State())
assert.NotNil(t, c.MustShipGroup(Race_0_idx, 4).StateInSpace)
assert.Equal(t, c.MustPlanet(R0_Planet_0_num).X, c.MustShipGroup(Race_0_idx, 4).StateInSpace.X)
assert.Equal(t, c.MustPlanet(R0_Planet_0_num).Y, c.MustShipGroup(Race_0_idx, 4).StateInSpace.Y)
assert.Equal(t, c.MustPlanet(R0_Planet_0_num).X.F(), c.MustShipGroup(Race_0_idx, 4).StateInSpace.X)
assert.Equal(t, c.MustPlanet(R0_Planet_0_num).Y.F(), c.MustShipGroup(Race_0_idx, 4).StateInSpace.Y)
assert.NoError(t, g.SendGroup(Race_0.Name, 4, R0_Planet_0_num, 0)) // un-send the rest 1
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 3)
+38 -38
View File
@@ -142,9 +142,9 @@ func TestBreakGroup(t *testing.T) {
assert.NotNil(t, c.ShipGroup(3).FleetID)
assert.Equal(t, game.CargoColonist.Ref(), c.ShipGroup(0).CargoType)
assert.Equal(t, 24.6, number.Fixed3(c.ShipGroup(0).Load))
assert.Equal(t, 24.6, number.Fixed3(c.ShipGroup(0).Load.F()))
assert.Equal(t, game.CargoColonist.Ref(), c.ShipGroup(3).CargoType)
assert.Equal(t, 8.2, number.Fixed3(c.ShipGroup(3).Load))
assert.Equal(t, 8.2, number.Fixed3(c.ShipGroup(3).Load.F()))
// group #1 -> MAX 6 off the fleet
assert.NoError(t, g.BreakGroup(Race_0.Name, 1, 6)) // group #1 (0)
@@ -295,48 +295,48 @@ func TestLoadCargo(t *testing.T) {
// break group and load maximum
assert.NoError(t, g.LoadCargo(Race_0.Name, 1, game.CargoMaterial.String(), 2, 0))
assert.Equal(t, 58.0, c.MustPlanet(R0_Planet_0_num).Material)
assert.Equal(t, 58.0, c.MustPlanet(R0_Planet_0_num).Material.F())
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 6)
assert.Nil(t, c.ShipGroup(0).CargoType)
assert.Equal(t, game.CargoMaterial.Ref(), c.ShipGroup(5).CargoType)
assert.Equal(t, uint(9), c.ShipGroup(0).Number)
assert.Equal(t, 0.0, c.ShipGroup(0).Load)
assert.Equal(t, 0.0, c.ShipGroup(0).Load.F())
assert.Equal(t, uint(2), c.ShipGroup(5).Number)
assert.Equal(t, 42.0, c.ShipGroup(5).Load)
assert.Equal(t, 42.0, c.ShipGroup(5).Load.F())
// break group and load limited
assert.NoError(t, g.LoadCargo(Race_0.Name, 1, game.CargoMaterial.String(), 2, 18))
assert.Equal(t, 40.0, c.MustPlanet(R0_Planet_0_num).Material)
assert.Equal(t, 40.0, c.MustPlanet(R0_Planet_0_num).Material.F())
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 7)
assert.Nil(t, c.ShipGroup(0).CargoType)
assert.Equal(t, game.CargoMaterial.Ref(), c.ShipGroup(6).CargoType)
assert.Equal(t, uint(7), c.ShipGroup(0).Number)
assert.Equal(t, 0.0, c.ShipGroup(0).Load)
assert.Equal(t, 0.0, c.ShipGroup(0).Load.F())
assert.Equal(t, uint(2), c.ShipGroup(6).Number)
assert.Equal(t, 18.0, c.ShipGroup(6).Load)
assert.Equal(t, 18.0, c.ShipGroup(6).Load.F())
// add cargo to planet
c.PutMaterial(R0_Planet_0_num, 100)
// loading all available cargo
assert.NoError(t, g.LoadCargo(Race_0.Name, 1, game.CargoMaterial.String(), 0, 0))
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 7)
assert.Equal(t, 0.0, c.MustPlanet(R0_Planet_0_num).Material)
assert.Equal(t, 100.0, c.ShipGroup(0).Load) // free: 131.0
assert.Equal(t, 0.0, c.MustPlanet(R0_Planet_0_num).Material.F())
assert.Equal(t, 100.0, c.ShipGroup(0).Load.F()) // free: 131.0
assert.Equal(t, game.CargoMaterial.Ref(), c.ShipGroup(0).CargoType)
// add cargo to planet
c.PutMaterial(R0_Planet_0_num, 200)
assert.NoError(t, g.LoadCargo(Race_0.Name, 1, game.CargoMaterial.String(), 11, 31))
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 7)
assert.Equal(t, 169.0, c.MustPlanet(R0_Planet_0_num).Material)
assert.Equal(t, 131.0, c.ShipGroup(0).Load) // free: 100.0
assert.Equal(t, 169.0, c.MustPlanet(R0_Planet_0_num).Material.F())
assert.Equal(t, 131.0, c.ShipGroup(0).Load.F()) // free: 100.0
assert.Equal(t, game.CargoMaterial.Ref(), c.ShipGroup(0).CargoType)
// load to maximum cargo space left
assert.NoError(t, g.LoadCargo(Race_0.Name, 1, game.CargoMaterial.String(), 11, 0))
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 7)
assert.Equal(t, 153.0, c.MustPlanet(R0_Planet_0_num).Material)
assert.Equal(t, 147.0, c.ShipGroup(0).Load) // free: 0.0
assert.Equal(t, 153.0, c.MustPlanet(R0_Planet_0_num).Material.F())
assert.Equal(t, 147.0, c.ShipGroup(0).Load.F()) // free: 0.0
assert.Equal(t, game.CargoMaterial.Ref(), c.ShipGroup(0).CargoType)
// ship group is full
@@ -413,33 +413,33 @@ func TestUnloadCargo(t *testing.T) {
// unload MAT on foreign planet / break group
assert.NoError(t, g.UnloadCargo(Race_0.Name, 6, 3, 0))
assert.Equal(t, 27.273, number.Fixed3(c.MustPlanet(R1_Planet_1_num).Material))
assert.Equal(t, 27.273, number.Fixed3(c.MustPlanet(R1_Planet_1_num).Material.F()))
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 7)
assert.Equal(t, uint(3), c.ShipGroup(6).Number)
assert.Nil(t, c.ShipGroup(6).CargoType)
assert.Equal(t, 0.0, c.ShipGroup(6).Load)
assert.Equal(t, 0.0, c.ShipGroup(6).Load.F())
assert.Equal(t, game.CargoMaterial.Ref(), c.ShipGroup(5).CargoType)
assert.Equal(t, uint(8), c.ShipGroup(5).Number)
assert.Equal(t, 72.727, number.Fixed3(c.ShipGroup(5).Load))
assert.Equal(t, 72.727, number.Fixed3(c.ShipGroup(5).Load.F()))
// unload MAT on foreign planet / break group / limited MAT
assert.NoError(t, g.UnloadCargo(Race_0.Name, 6, 3, 20.0))
assert.Equal(t, 47.273, number.Fixed3(c.MustPlanet(R1_Planet_1_num).Material))
assert.Equal(t, 47.273, number.Fixed3(c.MustPlanet(R1_Planet_1_num).Material.F()))
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 8)
assert.Equal(t, uint(3), c.ShipGroup(7).Number)
assert.Equal(t, game.CargoMaterial.Ref(), c.ShipGroup(7).CargoType)
assert.Equal(t, 7.273, number.Fixed3(c.ShipGroup(7).Load))
assert.Equal(t, 7.273, number.Fixed3(c.ShipGroup(7).Load.F()))
assert.Equal(t, game.CargoMaterial.Ref(), c.ShipGroup(5).CargoType)
assert.Equal(t, uint(5), c.ShipGroup(5).Number)
assert.Equal(t, 45.455, number.Fixed3(c.ShipGroup(5).Load))
assert.Equal(t, 45.455, number.Fixed3(c.ShipGroup(5).Load.F()))
// unload ALL
assert.NoError(t, g.UnloadCargo(Race_0.Name, 1, 0, 0))
assert.Equal(t, 100.0, number.Fixed3(c.MustPlanet(R0_Planet_0_num).Colonists))
assert.Equal(t, 100.0, number.Fixed3(c.MustPlanet(R0_Planet_0_num).Colonists.F()))
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 8)
assert.Equal(t, uint(10), c.ShipGroup(0).Number)
assert.Nil(t, c.ShipGroup(0).CargoType)
assert.Equal(t, 0.0, number.Fixed3(c.ShipGroup(0).Load))
assert.Equal(t, 0.0, number.Fixed3(c.ShipGroup(0).Load.F()))
}
func TestDisassembleGroup(t *testing.T) {
@@ -489,40 +489,40 @@ func TestDisassembleGroup(t *testing.T) {
e.GenericErrorText(e.ErrBeakGroupNumberNotEnough))
groupEmptyMass := c.ShipGroup(4).EmptyMass(c.MustShipClass(Race_0_idx, Race_0_Freighter))
planetMAT := c.MustPlanet(R1_Planet_1_num).Material
planetCOL := c.MustPlanet(R1_Planet_1_num).Colonists
planetMAT := c.MustPlanet(R1_Planet_1_num).Material.F()
planetCOL := c.MustPlanet(R1_Planet_1_num).Colonists.F()
assert.NoError(t, g.DisassembleGroup(Race_0.Name, 5, 0))
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 4)
assert.Equal(t, planetMAT+groupEmptyMass, c.MustPlanet(R1_Planet_1_num).Material)
assert.Equal(t, planetCOL, c.MustPlanet(R1_Planet_1_num).Colonists)
assert.Equal(t, planetMAT+groupEmptyMass, c.MustPlanet(R1_Planet_1_num).Material.F())
assert.Equal(t, planetCOL, c.MustPlanet(R1_Planet_1_num).Colonists.F())
groupEmptyMass = c.ShipGroup(3).EmptyMass(c.MustShipClass(Race_0_idx, Race_0_Freighter))
groupLoadMAT := c.ShipGroup(3).Load
planetMAT = c.MustPlanet(R1_Planet_1_num).Material
groupLoadMAT := c.ShipGroup(3).Load.F()
planetMAT = c.MustPlanet(R1_Planet_1_num).Material.F()
assert.NoError(t, g.DisassembleGroup(Race_0.Name, 4, 0))
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 3)
assert.Equal(t, planetMAT+groupEmptyMass+groupLoadMAT, c.MustPlanet(R1_Planet_1_num).Material)
assert.Equal(t, planetMAT+groupEmptyMass+groupLoadMAT, c.MustPlanet(R1_Planet_1_num).Material.F())
groupEmptyMass = c.ShipGroup(2).EmptyMass(c.MustShipClass(Race_0_idx, Race_0_Freighter))
planetMAT = c.MustPlanet(R0_Planet_0_num).Material
planetCOL = c.MustPlanet(R0_Planet_0_num).Colonists
planetMAT = c.MustPlanet(R0_Planet_0_num).Material.F()
planetCOL = c.MustPlanet(R0_Planet_0_num).Colonists.F()
planetPOP := 90.0
c.PutPopulation(R0_Planet_0_num, planetPOP)
assert.Equal(t, planetPOP, c.MustPlanet(R0_Planet_0_num).Population)
assert.Equal(t, planetPOP, c.MustPlanet(R0_Planet_0_num).Population.F())
var quantity uint = 3
groupEmptyMass = groupEmptyMass / float64(c.ShipGroup(2).Number) * float64(quantity)
newGroupUnloadedCOL := c.ShipGroup(2).Load / float64(c.ShipGroup(2).Number) * float64(quantity)
newGroupUnloadedCOL := c.ShipGroup(2).Load.F() / float64(c.ShipGroup(2).Number) * float64(quantity)
expectPOPIncrease := newGroupUnloadedCOL * 8
freePOPLeft := c.MustPlanet(R0_Planet_0_num).Size - c.MustPlanet(R0_Planet_0_num).Population
freePOPLeft := c.MustPlanet(R0_Planet_0_num).Size.F() - c.MustPlanet(R0_Planet_0_num).Population.F()
expectAddedCOL := (expectPOPIncrease - freePOPLeft) / 8
expectAddedPOP := freePOPLeft
assert.NoError(t, g.DisassembleGroup(Race_0.Name, 3, quantity))
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 3)
assert.Equal(t, planetCOL+expectAddedCOL, c.MustPlanet(R0_Planet_0_num).Colonists)
assert.Equal(t, planetPOP+expectAddedPOP, c.MustPlanet(R0_Planet_0_num).Population)
assert.Equal(t, planetMAT+groupEmptyMass, c.MustPlanet(R0_Planet_0_num).Material)
assert.Equal(t, planetCOL+expectAddedCOL, c.MustPlanet(R0_Planet_0_num).Colonists.F())
assert.Equal(t, planetPOP+expectAddedPOP, c.MustPlanet(R0_Planet_0_num).Population.F())
assert.Equal(t, planetMAT+groupEmptyMass, c.MustPlanet(R0_Planet_0_num).Material.F())
assert.Equal(t, uint(7), c.ShipGroup(2).Number)
assert.Equal(t, 56.0, c.ShipGroup(2).Load)
assert.Equal(t, 56.0, c.ShipGroup(2).Load.F())
}
+1 -1
View File
@@ -65,7 +65,7 @@ func (c *Cache) UpgradeGroup(ri int, groupIndex uint, techInput string, limitShi
if c.g.Race[ri].TechLevel(tech) < limitLevel {
return e.NewUpgradeTechLevelInsufficientError("%s=%.03f < %.03f", tech.String(), c.g.Race[ri].TechLevel(tech), limitLevel)
}
targetLevel[tech] = game.FutureUpgradeLevel(c.g.Race[ri].TechLevel(tech), c.ShipGroup(sgi).TechLevel(tech), limitLevel)
targetLevel[tech] = game.FutureUpgradeLevel(c.g.Race[ri].TechLevel(tech), c.ShipGroup(sgi).TechLevel(tech).F(), limitLevel)
} else {
targetLevel[tech] = game.CurrentUpgradingLevel(c.g.ShipGroups[sgi], tech)
}