tests: produce on planets, unload on routes
This commit is contained in:
@@ -71,8 +71,8 @@ func (c *Cache) ProduceBombings() []BombingPlanetReport {
|
||||
} else {
|
||||
// Если на планете остались также и колонисты, то они превращаются в население,
|
||||
// а накопленная промышленность возмещает потери производства.
|
||||
p.UnpackCOLtoPOP()
|
||||
p.UnpackCAPtoIND()
|
||||
p.UnpackColonists()
|
||||
p.UnpackCapital()
|
||||
}
|
||||
}
|
||||
return report
|
||||
|
||||
@@ -67,8 +67,16 @@ func (c *Cache) RaceTechLevel(ri int, t game.Tech, v float64) {
|
||||
c.raceTechLevel(ri, t, v)
|
||||
}
|
||||
|
||||
func (c *Cache) ListRouteEligibleGroupIds(pn uint) iter.Seq[int] {
|
||||
return c.listRouteEligibleGroupIds(pn)
|
||||
func (c *Cache) ListRoutedSendGroupIds(pn uint) iter.Seq[int] {
|
||||
return c.listRoutedSendGroupIds(pn)
|
||||
}
|
||||
|
||||
func (c *Cache) ListRoutedUnloadShipGroupIds(pn uint, rt game.RouteType) iter.Seq[int] {
|
||||
return c.listRoutedUnloadShipGroupIds(pn, rt)
|
||||
}
|
||||
|
||||
func (c *Cache) SelectColUnloadGroup(groups []int) (result iter.Seq[int]) {
|
||||
return c.selectColUnloadGroup(groups)
|
||||
}
|
||||
|
||||
func (c *Cache) ListMoveableGroupIds() iter.Seq[int] {
|
||||
|
||||
@@ -57,6 +57,7 @@ var (
|
||||
Race_1_Cruiser_idx = 2
|
||||
|
||||
Uninhabited_Planet_3_num uint = 3
|
||||
Uninhabited_Planet_4_num uint = 4
|
||||
|
||||
ShipType_Cruiser = "Cruiser"
|
||||
|
||||
@@ -100,6 +101,7 @@ func newGame() *game.Game {
|
||||
controller.NewPlanet(R1_Planet_1_num, "Planet_1", Race_1.ID, 2, 2, 100, 0, 0, 0, game.ProductionNone.AsType(uuid.Nil)),
|
||||
controller.NewPlanet(R0_Planet_2_num, "Planet_2", Race_0.ID, 3, 3, 100, 0, 0, 0, game.ProductionNone.AsType(uuid.Nil)),
|
||||
controller.NewPlanet(Uninhabited_Planet_3_num, "Planet_3", uuid.Nil, 500, 500, 100, 0, 0, 0, game.ProductionNone.AsType(uuid.Nil)),
|
||||
controller.NewPlanet(Uninhabited_Planet_4_num, "Planet_4", uuid.Nil, 10, 10, 500, 0, 0, 10, game.ProductionNone.AsType(uuid.Nil)),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -34,11 +34,9 @@ func MakeTurn(c *Controller, r Repo, g *game.Game) error {
|
||||
// 09. Корабли, где это возможно, объединяются в группы.
|
||||
// 10. На планетах производится промышленность, добывается сырье, разрабатываются новые технологии.
|
||||
// 11. Увеличивается население планет.
|
||||
// TODO: tests
|
||||
c.Cache.TurnPlanetProductions()
|
||||
|
||||
// 12. Товары выгружаются в конце грузовых маршрутов.
|
||||
// TODO: tests
|
||||
c.Cache.TurnUnloadEnroutedGroups()
|
||||
|
||||
/*** Last steps ***/
|
||||
|
||||
@@ -211,29 +211,30 @@ func (c *Cache) TurnPlanetProductions() {
|
||||
}
|
||||
case game.ResearchScience:
|
||||
sc := c.mustScience(ri, *p.Production.SubjectID)
|
||||
IncreaseTech(r, p, sc.Drive, sc.Weapons, sc.Shields, sc.Cargo)
|
||||
ResearchTech(r, p.ProductionCapacity(), sc.Drive, sc.Weapons, sc.Shields, sc.Cargo)
|
||||
case game.ResearchDrive:
|
||||
IncreaseTech(r, p, 1., 0, 0, 0)
|
||||
ResearchTech(r, p.ProductionCapacity(), 1., 0, 0, 0)
|
||||
case game.ResearchWeapons:
|
||||
IncreaseTech(r, p, 0, 1., 0, 0)
|
||||
ResearchTech(r, p.ProductionCapacity(), 0, 1., 0, 0)
|
||||
case game.ResearchShields:
|
||||
IncreaseTech(r, p, 0, 0, 1., 0)
|
||||
ResearchTech(r, p.ProductionCapacity(), 0, 0, 1., 0)
|
||||
case game.ResearchCargo:
|
||||
IncreaseTech(r, p, 0, 0, 0, 1.)
|
||||
ResearchTech(r, p.ProductionCapacity(), 0, 0, 0, 1.)
|
||||
case game.ProductionMaterial:
|
||||
p.IncreaseMaterial()
|
||||
p.ProduceMaterial()
|
||||
case game.ProductionCapital:
|
||||
p.IncreaseIndustry()
|
||||
p.ProduceIndustry()
|
||||
default:
|
||||
panic(fmt.Sprintf("unprocessed production type: %v", pt))
|
||||
}
|
||||
|
||||
p.IncreasePopulation()
|
||||
// last step: increase population / colonists
|
||||
p.ProducePopulation()
|
||||
}
|
||||
c.TurnMergeEqualShipGroups()
|
||||
}
|
||||
|
||||
// listProducingPlanets iterates over all inhabited planet numbers with production not set to None.
|
||||
// listProducingPlanets iterates over all inhabited planet numbers with defined production type.
|
||||
// Planets producing ships guaranteed to be iterated first for correct turn actions order.
|
||||
func (c *Cache) listProducingPlanets() iter.Seq[uint] {
|
||||
ordered := make([]int, 0)
|
||||
@@ -261,14 +262,6 @@ func (c *Cache) listProducingPlanets() iter.Seq[uint] {
|
||||
}
|
||||
}
|
||||
|
||||
func IncreaseTech(r *game.Race, p *game.Planet, d, w, s, c float64) {
|
||||
increment := 5000. / p.ProductionCapacity()
|
||||
r.Tech.Set(game.TechDrive, r.Tech.Value(game.TechDrive)+increment*d)
|
||||
r.Tech.Set(game.TechWeapons, r.Tech.Value(game.TechWeapons)+increment*w)
|
||||
r.Tech.Set(game.TechShields, r.Tech.Value(game.TechShields)+increment*s)
|
||||
r.Tech.Set(game.TechCargo, r.Tech.Value(game.TechCargo)+increment*c)
|
||||
}
|
||||
|
||||
// Internal funcs
|
||||
|
||||
func (c *Cache) putPopulation(pn uint, v float64) {
|
||||
|
||||
@@ -229,3 +229,61 @@ func TestListProducingPlanets(t *testing.T) {
|
||||
assert.Equal(t, R0_Planet_2_num, c.MustPlanet(planets[0]).Number)
|
||||
assert.Equal(t, R0_Planet_0_num, c.MustPlanet(planets[1]).Number)
|
||||
}
|
||||
|
||||
func TestTurnPlanetProductions(t *testing.T) {
|
||||
c, g := newCache()
|
||||
assert.NoError(t, c.CreateShipType(Race_0_idx, "Drone", 1, 0, 0, 0, 0))
|
||||
assert.NoError(t, g.CreateScience(Race_0.Name, "Equality", 0.25, 0.25, 0.25, 0.25))
|
||||
c.MustPlanet(R0_Planet_0_num).Resources = 10.
|
||||
c.MustPlanet(R0_Planet_0_num).Size = 1000.
|
||||
c.MustPlanet(R0_Planet_0_num).Population = 1000.
|
||||
c.MustPlanet(R0_Planet_0_num).Industry = 1000.
|
||||
|
||||
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)
|
||||
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.NoError(t, g.PlanetProduction(Race_0.Name, pn, "MAT", ""))
|
||||
assert.Equal(t, 0.0, c.MustPlanet(R0_Planet_0_num).Material)
|
||||
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.NoError(t, g.PlanetProduction(Race_0.Name, pn, "DRIVE", ""))
|
||||
assert.Equal(t, 1.1, c.Race(Race_0_idx).TechLevel(game.TechDrive))
|
||||
c.TurnPlanetProductions()
|
||||
assert.Equal(t, 1.3, c.Race(Race_0_idx).TechLevel(game.TechDrive))
|
||||
|
||||
assert.NoError(t, g.PlanetProduction(Race_0.Name, pn, "WEAPONS", ""))
|
||||
assert.Equal(t, 1.2, c.Race(Race_0_idx).TechLevel(game.TechWeapons))
|
||||
c.TurnPlanetProductions()
|
||||
assert.Equal(t, 1.4, c.Race(Race_0_idx).TechLevel(game.TechWeapons))
|
||||
|
||||
assert.NoError(t, g.PlanetProduction(Race_0.Name, pn, "SHIELDS", ""))
|
||||
assert.Equal(t, 1.3, c.Race(Race_0_idx).TechLevel(game.TechShields))
|
||||
c.TurnPlanetProductions()
|
||||
assert.Equal(t, 1.5, c.Race(Race_0_idx).TechLevel(game.TechShields))
|
||||
|
||||
assert.NoError(t, g.PlanetProduction(Race_0.Name, pn, "CARGO", ""))
|
||||
assert.Equal(t, 1.4, c.Race(Race_0_idx).TechLevel(game.TechCargo))
|
||||
c.TurnPlanetProductions()
|
||||
assert.InDelta(t, 1.6, c.Race(Race_0_idx).TechLevel(game.TechCargo), 0.1) // FIXME: 1.5999999999999999 -> 1.6
|
||||
|
||||
assert.NoError(t, g.PlanetProduction(Race_0.Name, pn, "SCIENCE", "Equality"))
|
||||
c.TurnPlanetProductions()
|
||||
assert.Equal(t, 1.35, c.Race(Race_0_idx).TechLevel(game.TechDrive))
|
||||
assert.Equal(t, 1.45, c.Race(Race_0_idx).TechLevel(game.TechWeapons))
|
||||
assert.Equal(t, 1.55, c.Race(Race_0_idx).TechLevel(game.TechShields))
|
||||
assert.Equal(t, 1.65, c.Race(Race_0_idx).TechLevel(game.TechCargo))
|
||||
|
||||
assert.NoError(t, g.PlanetProduction(Race_0.Name, pn, "SHIP", "Drone"))
|
||||
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 0)
|
||||
c.TurnPlanetProductions()
|
||||
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 1)
|
||||
assert.Equal(t, uint(100), c.ShipGroup(0).Number)
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ func (c *Cache) SetRoute(ri int, rt game.RouteType, origin, destination uint) er
|
||||
}
|
||||
rangeToDestination := util.ShortDistance(c.g.Map.Width, c.g.Map.Height, p1.X, p1.Y, p2.X, p2.Y)
|
||||
if rangeToDestination > c.g.Race[ri].FlightDistance() {
|
||||
return e.NewSendUnreachableDestinationError("range=%.03f", rangeToDestination)
|
||||
return e.NewSendUnreachableDestinationError("range=%.03f max=%.03f", rangeToDestination, c.g.Race[ri].FlightDistance())
|
||||
}
|
||||
|
||||
c.SetPlanetRoute(rt, origin, destination)
|
||||
@@ -97,7 +97,7 @@ func (c *Cache) EnrouteGroups() {
|
||||
if len(c.g.Map.Planet[pi].Route) == 0 {
|
||||
continue
|
||||
}
|
||||
groups := slices.Collect(c.listRouteEligibleGroupIds(c.g.Map.Planet[pi].Number))
|
||||
groups := slices.Collect(c.listRoutedSendGroupIds(c.g.Map.Planet[pi].Number))
|
||||
if len(groups) == 0 {
|
||||
continue
|
||||
}
|
||||
@@ -171,7 +171,7 @@ func (c *Cache) EnrouteGroups() {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Cache) listRouteEligibleGroupIds(pn uint) iter.Seq[int] {
|
||||
func (c *Cache) listRoutedSendGroupIds(pn uint) iter.Seq[int] {
|
||||
return func(yield func(int) bool) {
|
||||
p := c.MustPlanet(pn)
|
||||
for i := range c.ShipGroupsIndex() {
|
||||
@@ -194,63 +194,83 @@ func (c *Cache) listRouteEligibleGroupIds(pn uint) iter.Seq[int] {
|
||||
|
||||
// Невозможно лишь выгрузить колонистов на чужой планете.
|
||||
func (c *Cache) TurnUnloadEnroutedGroups() {
|
||||
for pi := range c.g.Map.Planet {
|
||||
p := &c.g.Map.Planet[pi]
|
||||
colGroups := c.listUnloadEligibleShipGroupIds(p.Number, game.RouteColonist)
|
||||
if p.Owner == uuid.Nil {
|
||||
c.selectColUnloadGroup(colGroups)
|
||||
} else {
|
||||
for sgi := range colGroups {
|
||||
sg := c.ShipGroup(sgi)
|
||||
if sg.OwnerID != p.Owner {
|
||||
continue
|
||||
}
|
||||
c.unloadCargoUnsafe(sgi, sg.Load)
|
||||
}
|
||||
}
|
||||
for i := range c.g.Map.Planet {
|
||||
p := &c.g.Map.Planet[i]
|
||||
c.doUnload(c.unloadRoutedColonists(p.Number, c.listRoutedUnloadShipGroupIds(p.Number, game.RouteColonist)))
|
||||
for _, rt := range []game.RouteType{game.RouteMaterial, game.RouteCapital} {
|
||||
for sgi := range c.listUnloadEligibleShipGroupIds(p.Number, rt) {
|
||||
c.unloadCargoUnsafe(sgi, c.ShipGroup(sgi).Load)
|
||||
}
|
||||
c.doUnload(c.listRoutedUnloadShipGroupIds(p.Number, rt))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Cache) selectColUnloadGroup(seq iter.Seq[int]) {
|
||||
func (c *Cache) doUnload(groups iter.Seq[int]) {
|
||||
for sgi := range groups {
|
||||
c.unsafeUnloadCargo(sgi, c.ShipGroup(sgi).Load)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Cache) unloadRoutedColonists(pn uint, groups iter.Seq[int]) iter.Seq[int] {
|
||||
p := c.MustPlanet(pn)
|
||||
gr := slices.Collect(groups)
|
||||
if p.Owner == uuid.Nil {
|
||||
return c.selectColUnloadGroup(gr)
|
||||
}
|
||||
return func(yield func(int) bool) {
|
||||
for _, sgi := range gr {
|
||||
sg := c.ShipGroup(sgi)
|
||||
if p.Owner != sg.OwnerID {
|
||||
continue
|
||||
}
|
||||
if !yield(sgi) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (c *Cache) selectColUnloadGroup(groups []int) (result iter.Seq[int]) {
|
||||
groupByRace := make(map[int][]int)
|
||||
loadByRace := make(map[int]float64)
|
||||
for i := range seq {
|
||||
for _, i := range groups {
|
||||
sg := c.ShipGroup(i)
|
||||
ri := c.RaceIndex(sg.OwnerID)
|
||||
groupByRace[ri] = append(groupByRace[ri], i)
|
||||
loadByRace[ri] += sg.Load
|
||||
}
|
||||
if len(loadByRace) < 2 {
|
||||
for _, gr := range groupByRace {
|
||||
for _, sgi := range gr {
|
||||
c.unloadCargoUnsafe(sgi, c.ShipGroup(sgi).Load)
|
||||
}
|
||||
}
|
||||
// only one race has to unload cargo
|
||||
result = slices.Values(groups)
|
||||
return
|
||||
}
|
||||
|
||||
// select winner to unload
|
||||
// select winner to unload cargo
|
||||
id := MaxOrRandomLoadId(loadByRace)
|
||||
result = slices.Values(groupByRace[id])
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func MaxOrRandomLoadId(IDtoLoad map[int]float64) int {
|
||||
if len(IDtoLoad) < 2 {
|
||||
panic("IDtoLoad must contain at least 2 keys")
|
||||
}
|
||||
IDs := slices.Collect(maps.Keys(IDtoLoad))
|
||||
slices.SortFunc(IDs, func(id1, id2 int) int { return cmp.Compare(IDtoLoad[id2], IDtoLoad[id1]) })
|
||||
|
||||
raceIdx := slices.Collect(maps.Keys(loadByRace))
|
||||
slices.SortFunc(raceIdx, func(ri1, ri2 int) int { return cmp.Compare(loadByRace[ri2], loadByRace[ri1]) })
|
||||
if loadByRace[raceIdx[0]] == loadByRace[raceIdx[1]] {
|
||||
// no single winner with highest load
|
||||
raceIdx = slices.DeleteFunc(raceIdx, func(v int) bool { return loadByRace[v] < loadByRace[raceIdx[0]] })
|
||||
rand.Shuffle(len(raceIdx), func(i, j int) { raceIdx[i], raceIdx[j] = raceIdx[j], raceIdx[i] })
|
||||
// now raceIdx[0] has a random race index
|
||||
}
|
||||
for _, sgi := range groupByRace[raceIdx[0]] {
|
||||
c.unloadCargoUnsafe(sgi, c.ShipGroup(sgi).Load)
|
||||
if IDtoLoad[IDs[0]] == IDtoLoad[IDs[1]] {
|
||||
// remove IDs which load less than maximum
|
||||
IDs = slices.DeleteFunc(IDs, func(v int) bool { return IDtoLoad[v] < IDtoLoad[IDs[0]] })
|
||||
// IDs[0] will have random index
|
||||
rand.Shuffle(len(IDs), func(i, j int) { IDs[i], IDs[j] = IDs[j], IDs[i] })
|
||||
}
|
||||
return IDs[0]
|
||||
}
|
||||
|
||||
func (c *Cache) listUnloadEligibleShipGroupIds(pn uint, routeType game.RouteType) iter.Seq[int] {
|
||||
func (c *Cache) listRoutedUnloadShipGroupIds(pn uint, routeType game.RouteType) iter.Seq[int] {
|
||||
return func(yield func(int) bool) {
|
||||
yielded := make(map[int]bool)
|
||||
for i := range c.g.Map.Planet {
|
||||
for rt, dest := range c.g.Map.Planet[i].Route {
|
||||
if dest != pn || rt != routeType {
|
||||
@@ -258,12 +278,16 @@ func (c *Cache) listUnloadEligibleShipGroupIds(pn uint, routeType game.RouteType
|
||||
}
|
||||
for i := range c.ShipGroupsIndex() {
|
||||
sg := c.ShipGroup(i)
|
||||
if sg.FleetID != nil || sg.State() != game.StateInOrbit || sg.CargoType == nil {
|
||||
if _, ok := yielded[i]; ok || sg.FleetID != nil || sg.CargoType == nil || sg.Load == 0. || sg.State() != game.StateInOrbit || sg.Destination != dest {
|
||||
continue
|
||||
}
|
||||
if v, ok := game.RouteToCargo[rt]; !ok || v != *sg.CargoType {
|
||||
continue
|
||||
}
|
||||
if !yield(i) {
|
||||
return
|
||||
}
|
||||
yielded[i] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"slices"
|
||||
"testing"
|
||||
|
||||
"github.com/iliadenisov/galaxy/internal/controller"
|
||||
e "github.com/iliadenisov/galaxy/internal/error"
|
||||
"github.com/iliadenisov/galaxy/internal/model/game"
|
||||
|
||||
@@ -91,7 +92,7 @@ func TestRemoveRoute(t *testing.T) {
|
||||
e.GenericErrorText(e.ErrInputEntityNotOwned))
|
||||
}
|
||||
|
||||
func TestListRouteEligibleGroupIds(t *testing.T) {
|
||||
func TestListRoutedSendGroupIds(t *testing.T) {
|
||||
c, g := newCache()
|
||||
|
||||
// 1: idx = 0 / Ready to load
|
||||
@@ -120,7 +121,7 @@ func TestListRouteEligibleGroupIds(t *testing.T) {
|
||||
assert.NoError(t, c.CreateShips(Race_0_idx, Race_0_Freighter, R0_Planet_0_num, 10))
|
||||
assert.NoError(t, g.JoinShipGroupToFleet(Race_0.Name, "Fleet", 5, 0))
|
||||
|
||||
planet_0_groups := slices.Collect(c.ListRouteEligibleGroupIds(0))
|
||||
planet_0_groups := slices.Collect(c.ListRoutedSendGroupIds(0))
|
||||
assert.Len(t, planet_0_groups, 1)
|
||||
for _, i := range planet_0_groups {
|
||||
sg := c.ShipGroup(i)
|
||||
@@ -254,3 +255,164 @@ func TestEnrouteGroups_LaunchOrder(t *testing.T) {
|
||||
assert.Nil(t, c.ShipGroup(sgi).CargoType)
|
||||
assert.Equal(t, uint(1), c.ShipGroup(sgi).Number)
|
||||
}
|
||||
|
||||
func TestListRoutedUnloadShipGroupIds(t *testing.T) {
|
||||
c, g := newCache()
|
||||
|
||||
// 1: idx = 0 / Empty cargo
|
||||
assert.NoError(t, c.CreateShips(Race_0_idx, Race_0_Freighter, R0_Planet_0_num, 10))
|
||||
c.ShipGroup(0).CargoType = game.CargoColonist.Ref()
|
||||
c.ShipGroup(0).Load = 0.
|
||||
|
||||
// 2: idx = 1 / Has no cargo bay
|
||||
assert.NoError(t, c.CreateShips(Race_0_idx, Race_0_Gunship, R0_Planet_0_num, 1))
|
||||
|
||||
// 3: idx = 2 / In_Space
|
||||
assert.NoError(t, c.CreateShips(Race_0_idx, Race_0_Freighter, R0_Planet_0_num, 7))
|
||||
c.ShipGroup(2).StateInSpace = &game.InSpace{
|
||||
Origin: 2,
|
||||
Range: 31.337,
|
||||
}
|
||||
|
||||
// 4: idx = 3 / loaded with COL
|
||||
assert.NoError(t, c.CreateShips(Race_0_idx, Race_0_Freighter, R0_Planet_0_num, 11))
|
||||
c.ShipGroup(3).CargoType = game.CargoColonist.Ref()
|
||||
c.ShipGroup(3).Load = 1.234
|
||||
|
||||
// 5: idx = 4 / Part of the Fleet
|
||||
assert.NoError(t, c.CreateShips(Race_0_idx, Race_0_Freighter, R0_Planet_0_num, 10))
|
||||
assert.NoError(t, g.JoinShipGroupToFleet(Race_0.Name, "Fleet", 5, 0))
|
||||
|
||||
assert.NoError(t, g.SetRoute(Race_0.Name, "COL", R0_Planet_0_num, R0_Planet_2_num))
|
||||
for _, rt := range game.RouteTypeSet {
|
||||
groups := slices.Collect(c.ListRoutedUnloadShipGroupIds(R0_Planet_2_num, rt))
|
||||
assert.Len(t, groups, 0, "route: %v", rt)
|
||||
groups = slices.Collect(c.ListRoutedUnloadShipGroupIds(R0_Planet_0_num, rt))
|
||||
assert.Len(t, groups, 0, "route: %v", rt)
|
||||
}
|
||||
|
||||
// double route from different planets - must not double group ids
|
||||
assert.NoError(t, g.SetRoute(Race_0.Name, "COL", R0_Planet_2_num, R0_Planet_0_num))
|
||||
assert.NoError(t, g.SetRoute(Race_1.Name, "COL", R1_Planet_1_num, R0_Planet_0_num))
|
||||
|
||||
// 6: idx = 5 / loaded with CAP
|
||||
assert.NoError(t, c.CreateShips(Race_0_idx, Race_0_Freighter, R0_Planet_0_num, 11))
|
||||
c.ShipGroup(5).CargoType = game.CargoCapital.Ref()
|
||||
c.ShipGroup(5).Load = 1.234
|
||||
|
||||
groups := slices.Collect(c.ListRoutedUnloadShipGroupIds(R0_Planet_0_num, game.RouteColonist))
|
||||
assert.Len(t, groups, 1)
|
||||
for _, sgi := range groups {
|
||||
assert.Greater(t, c.ShipGroup(sgi).Load, 0.)
|
||||
assert.Equal(t, game.StateInOrbit, c.ShipGroup(sgi).State())
|
||||
assert.Equal(t, R0_Planet_0_num, c.ShipGroup(sgi).Destination)
|
||||
}
|
||||
|
||||
groups = slices.Collect(c.ListRoutedUnloadShipGroupIds(R0_Planet_0_num, game.RouteMaterial))
|
||||
assert.Len(t, groups, 0)
|
||||
|
||||
groups = slices.Collect(c.ListRoutedUnloadShipGroupIds(R0_Planet_0_num, game.RouteCapital))
|
||||
assert.Len(t, groups, 0)
|
||||
}
|
||||
|
||||
func TestMaxOrRandomLoadId(t *testing.T) {
|
||||
IDtoLoad := make(map[int]float64)
|
||||
|
||||
assert.Panics(t, func() { controller.MaxOrRandomLoadId(IDtoLoad) })
|
||||
IDtoLoad[1] = 100.
|
||||
assert.Panics(t, func() { controller.MaxOrRandomLoadId(IDtoLoad) })
|
||||
|
||||
IDtoLoad[5] = 100.001
|
||||
assert.Equal(t, 5, controller.MaxOrRandomLoadId(IDtoLoad))
|
||||
|
||||
IDtoLoad[3] = 100.
|
||||
assert.NotContains(t, []int{1, 3}, controller.MaxOrRandomLoadId(IDtoLoad))
|
||||
|
||||
IDtoLoad[7] = 100.001
|
||||
rndCount := make(map[int]int)
|
||||
for range 100 {
|
||||
id := controller.MaxOrRandomLoadId(IDtoLoad)
|
||||
assert.NotContains(t, []int{1, 3}, id)
|
||||
assert.Contains(t, []int{5, 7}, id)
|
||||
rndCount[id]++
|
||||
}
|
||||
assert.Greater(t, rndCount[5], 10)
|
||||
assert.Greater(t, rndCount[7], 10)
|
||||
}
|
||||
|
||||
func TestSelectColUnloadGroup(t *testing.T) {
|
||||
c, g := newCache()
|
||||
|
||||
assert.NoError(t, g.SetRoute(Race_0.Name, "COL", R0_Planet_2_num, R0_Planet_0_num))
|
||||
assert.NoError(t, g.SetRoute(Race_1.Name, "COL", R1_Planet_1_num, R0_Planet_0_num))
|
||||
|
||||
// 1: idx = 0 / Loaded COL
|
||||
assert.NoError(t, c.CreateShips(Race_0_idx, Race_0_Freighter, R0_Planet_0_num, 10))
|
||||
c.ShipGroup(0).CargoType = game.CargoColonist.Ref()
|
||||
c.ShipGroup(0).Load = 7.
|
||||
|
||||
// 2: idx = 1 / Loaded COL
|
||||
assert.NoError(t, c.CreateShips(Race_0_idx, Race_0_Freighter, R0_Planet_0_num, 5))
|
||||
c.ShipGroup(1).CargoType = game.CargoColonist.Ref()
|
||||
c.ShipGroup(1).Load = 5.
|
||||
|
||||
groups := slices.Collect(c.ListRoutedUnloadShipGroupIds(R0_Planet_0_num, game.RouteColonist))
|
||||
assert.Len(t, groups, 2)
|
||||
unloadGroups := slices.Collect(c.SelectColUnloadGroup(groups))
|
||||
assert.ElementsMatch(t, groups, unloadGroups)
|
||||
|
||||
// 3: idx = 2 / Loaded COL - another race, winner
|
||||
assert.NoError(t, c.CreateShips(Race_1_idx, Race_1_Freighter, R1_Planet_1_num, 10))
|
||||
c.ShipGroup(2).Destination = R0_Planet_0_num
|
||||
c.ShipGroup(2).CargoType = game.CargoColonist.Ref()
|
||||
c.ShipGroup(2).Load = 12.1
|
||||
|
||||
groups = slices.Collect(c.ListRoutedUnloadShipGroupIds(R0_Planet_0_num, game.RouteColonist))
|
||||
assert.Len(t, groups, 3)
|
||||
unloadGroups = slices.Collect(c.SelectColUnloadGroup(groups))
|
||||
assert.Equal(t, 2, unloadGroups[0])
|
||||
}
|
||||
|
||||
func TestTurnUnloadEnroutedGroups(t *testing.T) {
|
||||
c, g := newCache()
|
||||
|
||||
assert.NoError(t, g.SetRoute(Race_0.Name, "MAT", R0_Planet_2_num, R0_Planet_0_num))
|
||||
assert.NoError(t, g.SetRoute(Race_0.Name, "CAP", R0_Planet_2_num, R0_Planet_0_num))
|
||||
|
||||
assert.NoError(t, g.SetRoute(Race_1.Name, "COL", R1_Planet_1_num, R0_Planet_0_num))
|
||||
assert.NoError(t, g.SetRoute(Race_1.Name, "COL", R1_Planet_1_num, Uninhabited_Planet_4_num))
|
||||
|
||||
// 1: idx = 0 / Loaded MAT
|
||||
assert.NoError(t, c.CreateShips(Race_0_idx, Race_0_Freighter, R0_Planet_0_num, 10))
|
||||
c.ShipGroup(0).CargoType = game.CargoMaterial.Ref()
|
||||
c.ShipGroup(0).Load = 222.
|
||||
|
||||
// 2: idx = 1 / Loaded CAP
|
||||
assert.NoError(t, c.CreateShips(Race_0_idx, Race_0_Freighter, R0_Planet_0_num, 10))
|
||||
c.ShipGroup(1).CargoType = game.CargoCapital.Ref()
|
||||
c.ShipGroup(1).Load = 11.
|
||||
|
||||
// 3: idx = 2 / Loaded COL - on empty planet
|
||||
assert.NoError(t, c.CreateShips(Race_1_idx, Race_1_Freighter, R1_Planet_1_num, 10))
|
||||
c.ShipGroup(2).Destination = Uninhabited_Planet_4_num
|
||||
c.ShipGroup(2).CargoType = game.CargoColonist.Ref()
|
||||
c.ShipGroup(2).Load = 12.1
|
||||
|
||||
// 4: idx = 3 / Loaded COL - on inhabited planet
|
||||
assert.NoError(t, c.CreateShips(Race_1_idx, Race_1_Freighter, R1_Planet_1_num, 10))
|
||||
c.ShipGroup(3).Destination = R0_Planet_0_num
|
||||
c.ShipGroup(3).CargoType = game.CargoColonist.Ref()
|
||||
c.ShipGroup(3).Load = 17.3
|
||||
|
||||
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, 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)
|
||||
}
|
||||
|
||||
@@ -81,6 +81,22 @@ func (c *Cache) DeleteScience(ri int, name string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func ResearchTech(r *game.Race, indCapacity float64, drive, weapons, shields, cargo float64) {
|
||||
increment := indCapacity / 5000.
|
||||
if drive > 0 {
|
||||
r.Tech = r.Tech.Set(game.TechDrive, r.Tech.Value(game.TechDrive)+increment*drive)
|
||||
}
|
||||
if weapons > 0 {
|
||||
r.Tech = r.Tech.Set(game.TechWeapons, r.Tech.Value(game.TechWeapons)+increment*weapons)
|
||||
}
|
||||
if shields > 0 {
|
||||
r.Tech = r.Tech.Set(game.TechShields, r.Tech.Value(game.TechShields)+increment*shields)
|
||||
}
|
||||
if cargo > 0 {
|
||||
r.Tech = r.Tech.Set(game.TechCargo, r.Tech.Value(game.TechCargo)+increment*cargo)
|
||||
}
|
||||
}
|
||||
|
||||
// Internal func
|
||||
|
||||
func (c *Cache) raceScience(ri int) []game.Science {
|
||||
@@ -96,5 +112,4 @@ func (c *Cache) mustScience(ri int, id uuid.UUID) *game.Science {
|
||||
panic(fmt.Sprintf("science not found for race=%q id=%v", r.Name, id))
|
||||
}
|
||||
return &c.g.Race[ri].Sciences[i]
|
||||
|
||||
}
|
||||
|
||||
@@ -4,7 +4,9 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/iliadenisov/galaxy/internal/controller"
|
||||
e "github.com/iliadenisov/galaxy/internal/error"
|
||||
"github.com/iliadenisov/galaxy/internal/model/game"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
@@ -97,3 +99,36 @@ func TestDeleteScience(t *testing.T) {
|
||||
g.DeleteScience(Race_0.Name, second),
|
||||
e.GenericErrorText(e.ErrDeleteSciencePlanetProduction))
|
||||
}
|
||||
|
||||
func TestResearchTech(t *testing.T) {
|
||||
r := Race_0
|
||||
rr := &r
|
||||
assert.Equal(t, 1.1, rr.Tech.Value(game.TechDrive))
|
||||
assert.Equal(t, 1.2, rr.Tech.Value(game.TechWeapons))
|
||||
assert.Equal(t, 1.3, rr.Tech.Value(game.TechShields))
|
||||
assert.Equal(t, 1.4, rr.Tech.Value(game.TechCargo))
|
||||
|
||||
controller.ResearchTech(rr, 500, 1.0, 0.0, 0.0, 0.0)
|
||||
assert.InDelta(t, 1.2, rr.Tech.Value(game.TechDrive), 0.000001)
|
||||
assert.Equal(t, 1.2, rr.Tech.Value(game.TechWeapons))
|
||||
assert.Equal(t, 1.3, rr.Tech.Value(game.TechShields))
|
||||
assert.Equal(t, 1.4, rr.Tech.Value(game.TechCargo))
|
||||
|
||||
controller.ResearchTech(rr, 500, 0.0, 0.5, 0.0, 0.5)
|
||||
assert.InDelta(t, 1.2, rr.Tech.Value(game.TechDrive), 0.000001)
|
||||
assert.Equal(t, 1.25, rr.Tech.Value(game.TechWeapons))
|
||||
assert.Equal(t, 1.3, rr.Tech.Value(game.TechShields))
|
||||
assert.Equal(t, 1.45, rr.Tech.Value(game.TechCargo))
|
||||
|
||||
controller.ResearchTech(rr, 500, 0.5, 0.0, 0.5, 0.0)
|
||||
assert.InDelta(t, 1.25, rr.Tech.Value(game.TechDrive), 0.000001)
|
||||
assert.Equal(t, 1.25, rr.Tech.Value(game.TechWeapons))
|
||||
assert.Equal(t, 1.35, rr.Tech.Value(game.TechShields))
|
||||
assert.Equal(t, 1.45, rr.Tech.Value(game.TechCargo))
|
||||
|
||||
controller.ResearchTech(rr, 1000, 0.0, 1.0, 0.0, 0.0)
|
||||
assert.InDelta(t, 1.25, rr.Tech.Value(game.TechDrive), 0.000001)
|
||||
assert.Equal(t, 1.45, rr.Tech.Value(game.TechWeapons))
|
||||
assert.Equal(t, 1.35, rr.Tech.Value(game.TechShields))
|
||||
assert.Equal(t, 1.45, rr.Tech.Value(game.TechCargo))
|
||||
}
|
||||
|
||||
@@ -383,15 +383,18 @@ func (c *Cache) UnloadCargo(ri int, groupIndex uint, ships uint, quantity float6
|
||||
return e.NewCargoUnoadNotEnoughError("load: %.03f", c.ShipGroup(sgi).Load)
|
||||
}
|
||||
|
||||
c.unloadCargoUnsafe(sgi, toBeUnloaded)
|
||||
c.unsafeUnloadCargo(sgi, toBeUnloaded)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Cache) unloadCargoUnsafe(sgi int, q float64) {
|
||||
func (c *Cache) unsafeUnloadCargo(sgi int, q float64) {
|
||||
if q <= 0 {
|
||||
return
|
||||
}
|
||||
if st := c.ShipGroup(sgi).State(); st != game.StateInOrbit {
|
||||
panic(fmt.Sprintf("invalid group state: %v", st))
|
||||
}
|
||||
c.validateShipGroupIndex(sgi)
|
||||
p := c.MustPlanet(c.ShipGroup(sgi).Destination)
|
||||
ct := *c.ShipGroup(sgi).CargoType
|
||||
@@ -411,12 +414,13 @@ func (c *Cache) unloadCargoUnsafe(sgi int, q float64) {
|
||||
}
|
||||
*availableOnPlanet += q
|
||||
|
||||
// FIXME: unpack COL / CAP
|
||||
|
||||
c.ShipGroup(sgi).Load -= q
|
||||
c.ShipGroup(sgi).Load -= q // TODO: apply rounding for Load property?
|
||||
if c.ShipGroup(sgi).Load == 0 {
|
||||
c.ShipGroup(sgi).CargoType = nil
|
||||
}
|
||||
|
||||
p.UnpackColonists()
|
||||
p.UnpackCapital()
|
||||
}
|
||||
|
||||
func (c *Controller) GiveawayGroup(raceName, raceAcceptor string, groupIndex, quantity uint) error {
|
||||
|
||||
@@ -200,7 +200,7 @@ func newGenericError(code int, arg ...any) error {
|
||||
e.err = arg[i].(error)
|
||||
i += 1
|
||||
}
|
||||
if len(arg) == i+2 {
|
||||
if len(arg) >= i+2 {
|
||||
e.subject = fmt.Sprintf(asString(arg[i]), arg[i+1:]...)
|
||||
} else if len(arg) == i+1 {
|
||||
e.subject = asString(arg[i])
|
||||
|
||||
@@ -56,7 +56,7 @@ func PlanetProduction(industry, population float64) float64 {
|
||||
// [x] ind = (res * prod) / (5 * res + 1)
|
||||
// ind = 10 * 1000 / (5 * 10 + 1) = 10000 / 55 = 181.(81)
|
||||
// int = 10 * 500 / 55 = 5000 / 55
|
||||
func (p *Planet) IncreaseIndustry() {
|
||||
func (p *Planet) ProduceIndustry() {
|
||||
production := p.ProductionCapacity()
|
||||
var ind float64
|
||||
if p.Material > 0 {
|
||||
@@ -72,27 +72,13 @@ func (p *Planet) IncreaseIndustry() {
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Planet) UnpackCAPtoIND() {
|
||||
if p.Capital == 0 {
|
||||
return
|
||||
}
|
||||
cap := p.Population - p.Industry
|
||||
if cap > p.Capital {
|
||||
cap = p.Capital
|
||||
}
|
||||
p.Capital -= cap
|
||||
p.Industry += cap
|
||||
}
|
||||
|
||||
// Производство материалов
|
||||
// TODO: test on real values
|
||||
func (p *Planet) IncreaseMaterial() {
|
||||
func (p *Planet) ProduceMaterial() {
|
||||
p.Material += p.ProductionCapacity() * p.Resources
|
||||
}
|
||||
|
||||
// Автоматическое увеличение населения на каждом ходу
|
||||
// TODO: test - whether POP is busy on production or not?
|
||||
func (p *Planet) IncreasePopulation() {
|
||||
func (p *Planet) ProducePopulation() {
|
||||
p.Population *= 1.08
|
||||
if p.Population > p.Size {
|
||||
p.Colonists += (p.Population - p.Size) / 8.
|
||||
@@ -100,17 +86,28 @@ func (p *Planet) IncreasePopulation() {
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Planet) UnpackCOLtoPOP() {
|
||||
if p.Colonists < 1 {
|
||||
func (p *Planet) UnpackCapital() {
|
||||
if p.Capital == 0 {
|
||||
return
|
||||
}
|
||||
maxCOL := uint((p.Size - p.Population) / 8.)
|
||||
if float64(maxCOL) > p.Colonists {
|
||||
maxCOL = uint(p.Colonists)
|
||||
deficit := p.Population - p.Industry
|
||||
if deficit > p.Capital {
|
||||
deficit = p.Capital
|
||||
}
|
||||
maxCOL = uint(float64(maxCOL) - math.Mod(float64(maxCOL), 8.))
|
||||
p.Colonists -= float64(maxCOL)
|
||||
p.Population += float64(maxCOL) * 8
|
||||
p.Capital -= deficit
|
||||
p.Industry += deficit
|
||||
}
|
||||
|
||||
func (p *Planet) UnpackColonists() {
|
||||
if p.Colonists == 0 {
|
||||
return
|
||||
}
|
||||
deficit := (p.Size - p.Population) / 8
|
||||
if deficit > p.Colonists {
|
||||
deficit = p.Colonists
|
||||
}
|
||||
p.Colonists -= deficit
|
||||
p.Population += deficit * 8
|
||||
}
|
||||
|
||||
func UnloadColonists(p Planet, v float64) Planet {
|
||||
|
||||
@@ -14,7 +14,7 @@ func TestPlanetProduction(t *testing.T) {
|
||||
assert.Equal(t, 250., game.PlanetProduction(0., 1000.))
|
||||
}
|
||||
|
||||
func TestIncreaseIndustry(t *testing.T) {
|
||||
func TestProduceIndustry(t *testing.T) {
|
||||
HW := &game.Planet{
|
||||
PlanetReport: game.PlanetReport{
|
||||
UninhabitedPlanet: game.UninhabitedPlanet{
|
||||
@@ -35,23 +35,141 @@ func TestIncreaseIndustry(t *testing.T) {
|
||||
Industry: 500,
|
||||
},
|
||||
}
|
||||
HW.IncreaseIndustry()
|
||||
HW.ProduceIndustry()
|
||||
assert.InDelta(t, 196.078, HW.Capital, 0.0005)
|
||||
|
||||
HW.Capital = 0
|
||||
HW.Material = 200
|
||||
|
||||
HW.IncreaseIndustry()
|
||||
HW.ProduceIndustry()
|
||||
assert.Equal(t, 200., HW.Capital)
|
||||
assert.Equal(t, 0., HW.Material)
|
||||
|
||||
DW.IncreaseIndustry()
|
||||
DW.ProduceIndustry()
|
||||
assert.InDelta(t, 98.039, DW.Capital, 0.0003)
|
||||
|
||||
DW.Capital = 0
|
||||
DW.Material = 100
|
||||
|
||||
DW.IncreaseIndustry()
|
||||
DW.ProduceIndustry()
|
||||
assert.Equal(t, 100., DW.Capital)
|
||||
assert.Equal(t, 0., DW.Material)
|
||||
}
|
||||
|
||||
func TestProduceMaterial(t *testing.T) {
|
||||
HW := &game.Planet{
|
||||
PlanetReport: game.PlanetReport{
|
||||
UninhabitedPlanet: game.UninhabitedPlanet{
|
||||
Size: 1000,
|
||||
Resources: 10,
|
||||
},
|
||||
Population: 1000,
|
||||
Industry: 1000,
|
||||
},
|
||||
}
|
||||
assert.Equal(t, 0., HW.Material)
|
||||
|
||||
HW.ProduceMaterial()
|
||||
assert.Equal(t, 10000., HW.Material)
|
||||
|
||||
HW.Industry = 500
|
||||
HW.Population = 500
|
||||
HW.ProduceMaterial()
|
||||
assert.Equal(t, 15000., HW.Material)
|
||||
|
||||
HW.Population = 1000
|
||||
HW.ProduceMaterial()
|
||||
assert.Equal(t, 21250., HW.Material)
|
||||
}
|
||||
|
||||
func TestUnpackCapital(t *testing.T) {
|
||||
HW := &game.Planet{
|
||||
PlanetReport: game.PlanetReport{
|
||||
UninhabitedPlanet: game.UninhabitedPlanet{
|
||||
Size: 1000,
|
||||
Resources: 10,
|
||||
},
|
||||
Population: 1000,
|
||||
Industry: 1000,
|
||||
},
|
||||
}
|
||||
assert.Equal(t, 0., HW.Capital)
|
||||
|
||||
HW.UnpackCapital()
|
||||
assert.Equal(t, 1000., HW.Industry)
|
||||
assert.Equal(t, 0., HW.Capital)
|
||||
|
||||
HW.Capital = 123.
|
||||
HW.UnpackCapital()
|
||||
assert.Equal(t, 1000., HW.Industry)
|
||||
assert.Equal(t, 123., HW.Capital)
|
||||
|
||||
HW.Industry = 987.
|
||||
HW.UnpackCapital()
|
||||
assert.Equal(t, 1000., HW.Industry)
|
||||
assert.Equal(t, 110., HW.Capital)
|
||||
|
||||
HW.Population = 876.
|
||||
HW.Industry = 800.
|
||||
HW.UnpackCapital()
|
||||
assert.Equal(t, 876., HW.Population)
|
||||
assert.Equal(t, 876., HW.Industry)
|
||||
assert.Equal(t, 34., HW.Capital)
|
||||
}
|
||||
|
||||
func TestUnpackColonists(t *testing.T) {
|
||||
HW := &game.Planet{
|
||||
PlanetReport: game.PlanetReport{
|
||||
UninhabitedPlanet: game.UninhabitedPlanet{
|
||||
Size: 1000,
|
||||
Resources: 10,
|
||||
},
|
||||
Population: 1000,
|
||||
Industry: 1000,
|
||||
},
|
||||
}
|
||||
assert.Equal(t, 0., HW.Colonists)
|
||||
|
||||
HW.UnpackColonists()
|
||||
assert.Equal(t, 1000., HW.Population)
|
||||
assert.Equal(t, 0., HW.Colonists)
|
||||
|
||||
HW.Colonists = 1.05
|
||||
HW.UnpackColonists()
|
||||
assert.Equal(t, 1000., HW.Population)
|
||||
assert.Equal(t, 1.05, HW.Colonists)
|
||||
|
||||
HW.Population = 996.0
|
||||
HW.UnpackColonists()
|
||||
assert.Equal(t, 1000., HW.Population)
|
||||
assert.Equal(t, 0.55, HW.Colonists)
|
||||
|
||||
HW.Population = 0.0
|
||||
HW.UnpackColonists()
|
||||
assert.Equal(t, 4.4, HW.Population)
|
||||
assert.Equal(t, 0., HW.Colonists)
|
||||
}
|
||||
|
||||
func TestProducePopulation(t *testing.T) {
|
||||
HW := &game.Planet{
|
||||
PlanetReport: game.PlanetReport{
|
||||
UninhabitedPlanet: game.UninhabitedPlanet{
|
||||
Size: 1000,
|
||||
Resources: 10,
|
||||
},
|
||||
Population: 500,
|
||||
Industry: 1000,
|
||||
},
|
||||
}
|
||||
assert.Equal(t, 500., HW.Population)
|
||||
assert.Equal(t, 0., HW.Colonists)
|
||||
|
||||
HW.ProducePopulation()
|
||||
assert.Equal(t, 540., HW.Population)
|
||||
assert.Equal(t, 0., HW.Colonists)
|
||||
|
||||
HW.Population = 1000.
|
||||
HW.ProducePopulation()
|
||||
assert.Equal(t, 1000., HW.Population)
|
||||
assert.Equal(t, 10., HW.Colonists)
|
||||
}
|
||||
|
||||
@@ -16,6 +16,11 @@ var (
|
||||
RouteColonist.String(): RouteColonist,
|
||||
RouteEmpty.String(): RouteEmpty,
|
||||
}
|
||||
RouteToCargo map[RouteType]CargoType = map[RouteType]CargoType{
|
||||
RouteColonist: CargoColonist,
|
||||
RouteCapital: CargoCapital,
|
||||
RouteMaterial: CargoMaterial,
|
||||
}
|
||||
)
|
||||
|
||||
func (rt RouteType) Ref() *RouteType {
|
||||
|
||||
Reference in New Issue
Block a user