feat: remove instant group breaking

This commit is contained in:
Ilia Denisov
2026-02-11 09:35:33 +02:00
parent 1515bc8599
commit 6e84cc3c51
17 changed files with 223 additions and 403 deletions
+16 -16
View File
@@ -78,7 +78,7 @@ func (c *Controller) ShipClassRemove(actor, typeName string) error {
return c.Cache.shipClassRemove(ri, typeName)
}
func (c *Controller) ShipGroupLoad(actor string, groupID uuid.UUID, cargoType string, ships uint, quantity float64) error {
func (c *Controller) ShipGroupLoad(actor string, groupID uuid.UUID, cargoType string, quantity float64) error {
ri, err := c.Cache.validActor(actor)
if err != nil {
return err
@@ -87,31 +87,31 @@ func (c *Controller) ShipGroupLoad(actor string, groupID uuid.UUID, cargoType st
if !ok {
return e.NewCargoTypeInvalidError(cargoType)
}
return c.Cache.shipGroupLoad(ri, groupID, ct, ships, quantity)
return c.Cache.shipGroupLoad(ri, groupID, ct, quantity)
}
func (c *Controller) ShipGroupUnload(actor string, groupID uuid.UUID, ships uint, quantity float64) error {
func (c *Controller) ShipGroupUnload(actor string, groupID uuid.UUID, quantity float64) error {
ri, err := c.Cache.validActor(actor)
if err != nil {
return err
}
return c.Cache.shipGroupUnload(ri, groupID, ships, quantity)
return c.Cache.shipGroupUnload(ri, groupID, quantity)
}
func (c *Controller) ShipGroupSend(actor string, groupID uuid.UUID, planetNumber, quantity uint) error {
func (c *Controller) ShipGroupSend(actor string, groupID uuid.UUID, planetNumber uint) error {
ri, err := c.Cache.validActor(actor)
if err != nil {
return err
}
return c.Cache.shipGroupSend(ri, groupID, planetNumber, quantity)
return c.Cache.shipGroupSend(ri, groupID, planetNumber)
}
func (c *Controller) ShipGroupUpgrade(actor string, groupID uuid.UUID, techInput string, limitShips uint, limitLevel float64) error {
func (c *Controller) ShipGroupUpgrade(actor string, groupID uuid.UUID, techInput string, limitLevel float64) error {
ri, err := c.Cache.validActor(actor)
if err != nil {
return err
}
return c.Cache.shipGroupUpgrade(ri, groupID, techInput, limitShips, limitLevel)
return c.Cache.shipGroupUpgrade(ri, groupID, techInput, limitLevel)
}
func (c *Controller) ShipGroupMerge(actor string) error {
@@ -123,23 +123,23 @@ func (c *Controller) ShipGroupMerge(actor string) error {
return nil
}
func (c *Controller) ShipGroupBreak(actor string, groupID uuid.UUID, quantity uint) error {
func (c *Controller) ShipGroupBreak(actor string, groupID, newID uuid.UUID, quantity uint) error {
ri, err := c.Cache.validActor(actor)
if err != nil {
return err
}
return c.Cache.ShipGroupBreak(ri, groupID, quantity)
return c.Cache.ShipGroupBreak(ri, groupID, newID, quantity)
}
func (c *Controller) ShipGroupDismantle(actor string, groupID uuid.UUID, quantity uint) error {
func (c *Controller) ShipGroupDismantle(actor string, groupID uuid.UUID) error {
ri, err := c.Cache.validActor(actor)
if err != nil {
return err
}
return c.Cache.shipGroupDismantle(ri, groupID, quantity)
return c.Cache.shipGroupDismantle(ri, groupID)
}
func (c *Controller) ShipGroupTransfer(actor, acceptor string, groupID uuid.UUID, quantity uint) error {
func (c *Controller) ShipGroupTransfer(actor, acceptor string, groupID uuid.UUID) error {
ri, err := c.Cache.validActor(actor)
if err != nil {
return err
@@ -148,15 +148,15 @@ func (c *Controller) ShipGroupTransfer(actor, acceptor string, groupID uuid.UUID
if err != nil {
return err
}
return c.Cache.shipGroupTransfer(ri, riAccept, groupID, quantity)
return c.Cache.shipGroupTransfer(ri, riAccept, groupID)
}
func (c *Controller) ShipGroupJoinFleet(actor, fleetName string, groupID uuid.UUID, quantity uint) error {
func (c *Controller) ShipGroupJoinFleet(actor, fleetName string, groupID uuid.UUID) error {
ri, err := c.Cache.validActor(actor)
if err != nil {
return err
}
return c.Cache.ShipGroupJoinFleet(ri, fleetName, groupID, quantity)
return c.Cache.ShipGroupJoinFleet(ri, fleetName, groupID)
}
func (c *Controller) FleetMerge(actor, fleetSourceName, fleetTargetName string) error {
+8 -8
View File
@@ -51,15 +51,15 @@ type Ctrl interface {
ShipClassCreate(actor, typeName string, drive float64, ammo int, weapons, shileds, cargo float64) error
ShipClassMerge(actor, name, targetName string) error
ShipClassRemove(actor, typeName string) error
ShipGroupLoad(actor string, groupID uuid.UUID, cargoType string, ships uint, quantity float64) error
ShipGroupUnload(actor string, groupID uuid.UUID, ships uint, quantity float64) error
ShipGroupSend(actor string, groupID uuid.UUID, planetNumber, quantity uint) error
ShipGroupUpgrade(actor string, groupID uuid.UUID, techInput string, limitShips uint, limitLevel float64) error
ShipGroupBreak(actor string, groupID uuid.UUID, quantity uint) error
ShipGroupLoad(actor string, groupID uuid.UUID, cargoType string, quantity float64) error
ShipGroupUnload(actor string, groupID uuid.UUID, quantity float64) error
ShipGroupSend(actor string, groupID uuid.UUID, planetNumber uint) error
ShipGroupUpgrade(actor string, groupID uuid.UUID, techInput string, limitLevel float64) error
ShipGroupBreak(actor string, groupID, newID uuid.UUID, quantity uint) error
ShipGroupMerge(actor string) error
ShipGroupDismantle(actor string, groupID uuid.UUID, quantity uint) error
ShipGroupTransfer(actor, acceptor string, groupID uuid.UUID, quantity uint) error
ShipGroupJoinFleet(actor, fleetName string, groupID uuid.UUID, count uint) error
ShipGroupDismantle(actor string, groupID uuid.UUID) error
ShipGroupTransfer(actor, acceptor string, groupID uuid.UUID) error
ShipGroupJoinFleet(actor, fleetName string, groupID uuid.UUID) error
FleetMerge(actor, fleetSourceName, fleetTargetName string) error
FleetSend(actor, fleetName string, planetNumber uint) error
ScienceCreate(actor, typeName string, drive, weapons, shields, cargo float64) error
+1 -13
View File
@@ -101,7 +101,7 @@ func (c *Cache) FleetSpeedAndMass(fi int) (float64, float64) {
return speed, mass
}
func (c *Cache) ShipGroupJoinFleet(ri int, fleetName string, groupID uuid.UUID, quantity uint) (err error) {
func (c *Cache) ShipGroupJoinFleet(ri int, fleetName string, groupID uuid.UUID) (err error) {
c.validateRaceIndex(ri)
name, ok := util.ValidateTypeName(fleetName)
if !ok {
@@ -116,10 +116,6 @@ func (c *Cache) ShipGroupJoinFleet(ri int, fleetName string, groupID uuid.UUID,
return e.NewShipsBusyError("state: %s", state)
}
if c.ShipGroup(sgi).Number < quantity {
return e.NewJoinFleetGroupNumberNotEnoughError("%d<%d", c.ShipGroup(sgi).Number, quantity)
}
var oldFleetID *uuid.UUID
if c.ShipGroup(sgi).FleetID != nil {
fID := *c.ShipGroup(sgi).FleetID
@@ -139,14 +135,6 @@ func (c *Cache) ShipGroupJoinFleet(ri int, fleetName string, groupID uuid.UUID,
}
}
if quantity > 0 && quantity < c.ShipGroup(sgi).Number {
nsgi, err := c.breakGroup(ri, groupID, quantity)
if err != nil {
return err
}
sgi = nsgi
}
c.internalShipGroupJoinFleet(sgi, &c.g.Fleets[fi].ID)
if oldFleetID != nil {
+6 -6
View File
@@ -29,22 +29,22 @@ func TestFleetSend(t *testing.T) {
fleetUnmovable := "R0_Fleet_unmovable"
fleetUnmovable2 := "R0_Fleet_unmovable2"
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, fleetSending, c.ShipGroup(0).ID, 0))
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, fleetSending, c.ShipGroup(0).ID))
assert.Len(t, slices.Collect(c.ListFleets(Race_0_idx)), 1)
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, fleetSending, c.ShipGroup(2).ID, 0))
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, fleetSending, c.ShipGroup(2).ID))
assert.Len(t, slices.Collect(c.ListFleets(Race_0_idx)), 1)
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, fleetInSpace, c.ShipGroup(1).ID, 0))
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, fleetInSpace, c.ShipGroup(1).ID))
assert.Len(t, slices.Collect(c.ListFleets(Race_0_idx)), 2)
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, fleetUnmovable, c.ShipGroup(2).ID, 0))
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, fleetUnmovable, c.ShipGroup(2).ID))
assert.Len(t, slices.Collect(c.ListFleets(Race_0_idx)), 3)
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, fleetUnmovable2, c.ShipGroup(3).ID, 0))
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, fleetUnmovable2, c.ShipGroup(3).ID))
assert.Len(t, slices.Collect(c.ListFleets(Race_0_idx)), 4)
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, fleetUnmovable, c.ShipGroup(3).ID, 0))
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, fleetUnmovable, c.ShipGroup(3).ID))
assert.Len(t, slices.Collect(c.ListFleets(Race_0_idx)), 3)
// group #2 - in_space
+25 -33
View File
@@ -19,11 +19,11 @@ func TestShipGroupJoinFleet(t *testing.T) {
fleetTwo := "R0_Fleet_two"
assert.ErrorContains(t,
g.ShipGroupJoinFleet(Race_0.Name, BadEntityName, groupIndex, 0),
g.ShipGroupJoinFleet(Race_0.Name, BadEntityName, groupIndex),
e.GenericErrorText(e.ErrInputEntityTypeNameInvalid))
assert.ErrorContains(t,
g.ShipGroupJoinFleet(Race_0.Name, "Unnamed", groupIndex, 0),
g.ShipGroupJoinFleet(Race_0.Name, "Unnamed", groupIndex),
e.GenericErrorText(e.ErrInputEntityNotExists))
// creating ShipGroup
@@ -31,20 +31,16 @@ func TestShipGroupJoinFleet(t *testing.T) {
groupIndex = c.ShipGroup(0).ID
assert.ErrorContains(t,
g.ShipGroupJoinFleet(UnknownRace, fleetOne, groupIndex, 0),
g.ShipGroupJoinFleet(UnknownRace, fleetOne, groupIndex),
e.GenericErrorText(e.ErrInputUnknownRace))
assert.ErrorContains(t,
g.ShipGroupJoinFleet(Race_Extinct.Name, fleetOne, groupIndex, 0),
g.ShipGroupJoinFleet(Race_Extinct.Name, fleetOne, groupIndex),
e.GenericErrorText(e.ErrRaceExinct))
assert.ErrorContains(t,
g.ShipGroupJoinFleet(Race_0.Name, "Unnamed", groupIndex, 6),
e.GenericErrorText(e.ErrJoinFleetGroupNumberNotEnough))
// ensure race has no Fleets
assert.Len(t, slices.Collect(c.ListFleets(Race_0_idx)), 0)
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, fleetOne, groupIndex, 0))
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, fleetOne, groupIndex))
fleets := slices.Collect(c.ListFleets(Race_0_idx))
groups := slices.Collect(c.RaceShipGroups(Race_0_idx))
assert.Len(t, groups, 1)
@@ -60,29 +56,25 @@ func TestShipGroupJoinFleet(t *testing.T) {
// create another ShipGroup
assert.NoError(t, c.CreateShips(Race_0_idx, Race_0_Gunship, R0_Planet_0_num, 3))
groupIndex = c.ShipGroup(1).ID
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, fleetTwo, groupIndex, 2))
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, fleetTwo, groupIndex))
fleets = slices.Collect(c.ListFleets(Race_0_idx))
groups = slices.Collect(c.RaceShipGroups(Race_0_idx))
assert.Len(t, groups, 3)
assert.Len(t, groups, 2)
assert.Len(t, fleets, 2)
assert.Equal(t, fleets[1].Name, fleetTwo)
fleetState = c.FleetState(fleets[1].ID)
assert.Equal(t, game.StateInOrbit, fleetState.State)
gi = 2
assert.Len(t, groups, 3)
gi = 1
assert.Len(t, groups, 2)
assert.NotNil(t, groups[gi].FleetID)
assert.Equal(t, fleets[1].ID, *groups[gi].FleetID)
assert.Equal(t, uint(2), groups[gi].Number)
gi = 1
assert.Nil(t, groups[gi].FleetID)
assert.Equal(t, uint(1), groups[gi].Number)
assert.Equal(t, uint(3), groups[gi].Number)
groupIndex = groups[gi].ID
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, fleetOne, groupIndex, 0))
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, fleetOne, groupIndex))
fleets = slices.Collect(c.ListFleets(Race_0_idx))
assert.Len(t, fleets, 2)
assert.Len(t, fleets, 1)
groups = slices.Collect(c.RaceShipGroups(Race_0_idx))
assert.NotNil(t, groups[gi].FleetID)
assert.Equal(t, fleets[0].ID, *groups[gi].FleetID)
@@ -91,10 +83,10 @@ func TestShipGroupJoinFleet(t *testing.T) {
// group not In_Orbit
assert.NoError(t, c.CreateShips(Race_0_idx, Race_0_Gunship, R0_Planet_0_num, 7))
gi = 3
gi = 2
c.ShipGroup(gi).StateInSpace = &InSpace
assert.ErrorContains(t,
g.ShipGroupJoinFleet(Race_0.Name, fleetOne, c.ShipGroup(gi).ID, 0),
g.ShipGroupJoinFleet(Race_0.Name, fleetOne, c.ShipGroup(gi).ID),
e.GenericErrorText(e.ErrShipsBusy))
c.ShipGroup(gi).StateInSpace = nil
@@ -102,7 +94,7 @@ func TestShipGroupJoinFleet(t *testing.T) {
c.ShipGroup(0).StateInSpace = &InSpace
c.ShipGroup(1).StateInSpace = c.ShipGroup(0).StateInSpace
assert.ErrorContains(t,
g.ShipGroupJoinFleet(Race_0.Name, fleetOne, c.ShipGroup(gi).ID, 0),
g.ShipGroupJoinFleet(Race_0.Name, fleetOne, c.ShipGroup(gi).ID),
e.GenericErrorText(e.ErrShipsNotOnSamePlanet))
}
@@ -133,21 +125,21 @@ func TestFleetMerge(t *testing.T) {
e.GenericErrorText(e.ErrRaceExinct))
assert.ErrorContains(t,
g.ShipGroupJoinFleet(UnknownRace, fleetSourceOne, c.ShipGroup(0).ID, 0),
g.ShipGroupJoinFleet(UnknownRace, fleetSourceOne, c.ShipGroup(0).ID),
e.GenericErrorText(e.ErrInputUnknownRace))
assert.ErrorContains(t,
g.ShipGroupJoinFleet(Race_Extinct.Name, fleetSourceOne, c.ShipGroup(0).ID, 0),
g.ShipGroupJoinFleet(Race_Extinct.Name, fleetSourceOne, c.ShipGroup(0).ID),
e.GenericErrorText(e.ErrRaceExinct))
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, fleetSourceOne, c.ShipGroup(0).ID, 0))
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, fleetSourceOne, c.ShipGroup(0).ID))
assert.ErrorContains(t,
g.FleetMerge(Race_0.Name, fleetSourceOne, fleetTargetTwo),
e.GenericErrorText(e.ErrInputEntityNotExists))
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, fleetTargetTwo, c.ShipGroup(2).ID, 0))
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, fleetTargetTwo, c.ShipGroup(2).ID))
assert.NoError(t, g.FleetMerge(Race_0.Name, fleetSourceOne, fleetTargetTwo))
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, fleetOnPlanet2, c.ShipGroup(1).ID, 0))
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, fleetOnPlanet2, c.ShipGroup(1).ID))
assert.ErrorContains(t,
g.FleetMerge(Race_0.Name, fleetOnPlanet2, fleetTargetTwo),
@@ -168,12 +160,12 @@ func TestFleetSpeedAndMass(t *testing.T) {
m := c.ShipGroup(0).FullMass(c.MustShipClass(Race_0_idx, Race_0_Gunship))
assert.NoError(t, c.CreateShips(Race_0_idx, Race_0_Freighter, R0_Planet_0_num, 5)) // 2
assert.NoError(t, g.ShipGroupLoad(Race_0.Name, c.ShipGroup(1).ID, "MAT", 10., 0))
assert.NoError(t, g.ShipGroupLoad(Race_0.Name, c.ShipGroup(1).ID, "MAT", 10.))
assert.NoError(t, c.CreateShips(Race_0_idx, Race_0_Freighter, R0_Planet_0_num, 7)) // 3
assert.NoError(t, g.ShipGroupLoad(Race_0.Name, c.ShipGroup(2).ID, "CAP", 10., 0))
assert.NoError(t, g.ShipGroupLoad(Race_0.Name, c.ShipGroup(2).ID, "CAP", 10.))
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, fleet, c.ShipGroup(0).ID, 0))
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, fleet, c.ShipGroup(0).ID))
fleetIndex := 0
speed, mass = c.FleetSpeedAndMass(fleetIndex)
assert.Equal(t, s, speed)
@@ -182,7 +174,7 @@ func TestFleetSpeedAndMass(t *testing.T) {
s = math.Min(s, c.ShipGroup(1).Speed(c.MustShipClass(Race_0_idx, Race_0_Freighter)))
m += c.ShipGroup(1).FullMass(c.MustShipClass(Race_0_idx, Race_0_Freighter))
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, fleet, c.ShipGroup(1).ID, 0))
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, fleet, c.ShipGroup(1).ID))
speed, mass = c.FleetSpeedAndMass(fleetIndex)
assert.Equal(t, s, speed)
assert.Equal(t, m, mass)
@@ -190,7 +182,7 @@ func TestFleetSpeedAndMass(t *testing.T) {
s = math.Min(s, c.ShipGroup(2).Speed(c.MustShipClass(Race_0_idx, Race_0_Freighter)))
m += c.ShipGroup(2).FullMass(c.MustShipClass(Race_0_idx, Race_0_Freighter))
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, fleet, c.ShipGroup(2).ID, 0))
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, fleet, c.ShipGroup(2).ID))
speed, mass = c.FleetSpeedAndMass(fleetIndex)
assert.Equal(t, s, speed)
assert.Equal(t, m, mass)
+2 -2
View File
@@ -191,8 +191,8 @@ func TestProduceShips(t *testing.T) {
c.MustPlanet(R0_Planet_2_num).Population = 100
c.MustPlanet(R0_Planet_2_num).Industry = 100
c.RaceTechLevel(Race_0_idx, game.TechDrive, 1.5)
assert.NoError(t, g.ShipGroupUpgrade(Race_0.Name, c.ShipGroup(1).ID, "Drive", 0, 0))
assert.NoError(t, g.ShipGroupUpgrade(Race_0.Name, c.ShipGroup(0).ID, "Drive", 0, 0))
assert.NoError(t, g.ShipGroupUpgrade(Race_0.Name, c.ShipGroup(1).ID, "Drive", 0))
assert.NoError(t, g.ShipGroupUpgrade(Race_0.Name, c.ShipGroup(0).ID, "Drive", 0))
assert.Equal(t, game.StateUpgrade, c.ShipGroup(0).State())
assert.Equal(t, game.StateUpgrade, c.ShipGroup(1).State())
+3 -3
View File
@@ -118,11 +118,11 @@ func TestListRoutedSendGroupIds(t *testing.T) {
// Foreign group -> idx 1
assert.NoError(t, c.CreateShips(Race_0_idx, Race_0_Freighter, R0_Planet_0_num, 10))
assert.NoError(t, g.ShipGroupTransfer(Race_0.Name, Race_1.Name, c.ShipGroup(4).ID, 0))
assert.NoError(t, g.ShipGroupTransfer(Race_0.Name, Race_1.Name, c.ShipGroup(4).ID))
// 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.ShipGroupJoinFleet(Race_0.Name, "Fleet", c.ShipGroup(5).ID, 0))
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, "Fleet", c.ShipGroup(5).ID))
planet_0_groups := slices.Collect(c.ListRoutedSendGroupIds(0))
assert.Len(t, planet_0_groups, 1)
@@ -283,7 +283,7 @@ func TestListRoutedUnloadShipGroupIds(t *testing.T) {
// 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.ShipGroupJoinFleet(Race_0.Name, "Fleet", c.ShipGroup(4).ID, 0))
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, "Fleet", c.ShipGroup(4).ID))
assert.NoError(t, g.PlanetRouteSet(Race_0.Name, "COL", R0_Planet_0_num, R0_Planet_2_num))
for _, rt := range game.RouteTypeSet {
+11 -48
View File
@@ -96,6 +96,7 @@ func (c *Cache) TurnMergeEqualShipGroups() {
}
func (c *Cache) transferPendingGroups(ri int) {
c.validateRaceIndex(ri)
for sg := range c.listShipGroups(ri) {
if sg.State() == game.StateTransfer {
sg.StateTransfer = false
@@ -146,7 +147,8 @@ func (c *Cache) shipGroupMerge(ri int) {
}
}
func (c *Cache) shipGroupDismantle(ri int, groupIndex uuid.UUID, quantity uint) error {
func (c *Cache) shipGroupDismantle(ri int, groupIndex uuid.UUID) error {
c.validateRaceIndex(ri)
sgi, ok := c.raceShipGroupIndex(ri, groupIndex)
if !ok {
return e.NewEntityNotExistsError("group #%d", groupIndex)
@@ -156,10 +158,6 @@ func (c *Cache) shipGroupDismantle(ri int, groupIndex uuid.UUID, quantity uint)
return e.NewShipsBusyError("state: %s", state)
}
if c.ShipGroup(sgi).Number < quantity {
return e.NewBeakGroupNumberNotEnoughError("%d<%d", c.ShipGroup(sgi).Number, quantity)
}
pl, ok := c.Planet(c.ShipGroup(sgi).Destination)
if !ok {
return e.NewGameStateError("planet #%d", c.ShipGroup(sgi).Destination)
@@ -168,15 +166,6 @@ func (c *Cache) shipGroupDismantle(ri int, groupIndex uuid.UUID, quantity uint)
st := c.ShipGroupShipClass(sgi)
if quantity > 0 && quantity < c.ShipGroup(sgi).Number {
// make new group for disassembly
nsgi, err := c.breakGroup(ri, groupIndex, quantity)
if err != nil {
return err
}
sgi = nsgi
}
if c.ShipGroup(sgi).CargoType != nil {
ct := *c.ShipGroup(sgi).CargoType
load := c.ShipGroup(sgi).Load.F()
@@ -204,10 +193,8 @@ func (c *Cache) shipGroupDismantle(ri int, groupIndex uuid.UUID, quantity uint)
// Корабль может нести только один тип груза одновременно.
// Возможные типы груза - это колонисты, сырье и промышленность.
// Груз может быть доставлен на борт корабля с Вашей или не занятой планеты, на которой он имеется.
func (c *Cache) shipGroupLoad(ri int, groupID uuid.UUID, ct game.CargoType, ships uint, quantity float64) error {
if ships == 0 && quantity > 0 {
return e.NewCargoQuantityWithoutGroupBreakError()
}
func (c *Cache) shipGroupLoad(ri int, groupID uuid.UUID, ct game.CargoType, quantity float64) error {
c.validateRaceIndex(ri)
sgi, ok := c.raceShipGroupIndex(ri, groupID)
if !ok {
return e.NewEntityNotExistsError("group %s", groupID)
@@ -231,13 +218,7 @@ func (c *Cache) shipGroupLoad(ri int, groupID uuid.UUID, ct game.CargoType, ship
if c.ShipGroup(sgi).CargoType != nil && *c.ShipGroup(sgi).CargoType != ct {
return e.NewCargoLoadNotEqualError("cargo: %v", *c.ShipGroup(sgi).CargoType)
}
if ships > 0 && ships < c.ShipGroup(sgi).Number {
nsgi, err := c.breakGroup(ri, groupID, ships)
if err != nil {
return err
}
sgi = nsgi
}
capacity := c.ShipGroup(sgi).CargoCapacity(st)
freeShipGroupCargoLoad := capacity - float64(c.ShipGroup(sgi).Load)
if freeShipGroupCargoLoad == 0 {
@@ -274,11 +255,8 @@ func (c *Cache) shipGroupLoad(ri int, groupID uuid.UUID, ct game.CargoType, ship
// Промышленность и Сырье могут быть выгружены на любой планете.
// Колонисты могут быть высажены только на планеты, принадлежащие Вам или на необитаемые планеты.
func (c *Cache) shipGroupUnload(ri int, groupID uuid.UUID, ships uint, quantity float64) error {
func (c *Cache) shipGroupUnload(ri int, groupID uuid.UUID, quantity float64) error {
c.validateRaceIndex(ri)
if ships == 0 && quantity > 0 {
return e.NewCargoQuantityWithoutGroupBreakError()
}
sgi, ok := c.raceShipGroupIndex(ri, groupID)
if !ok {
return e.NewEntityNotExistsError("group %s", groupID)
@@ -300,13 +278,6 @@ func (c *Cache) shipGroupUnload(ri int, groupID uuid.UUID, ships uint, quantity
if ct == game.CargoColonist && p.Owned() && !p.OwnedBy(c.g.Race[ri].ID) {
return e.NewEntityNotOwnedError("planet #%d unload %v", p.Number, ct)
}
if ships > 0 && ships < c.ShipGroup(sgi).Number {
nsgi, err := c.breakGroup(ri, groupID, ships)
if err != nil {
return err
}
sgi = nsgi
}
toBeUnloaded := quantity
if quantity == 0 {
@@ -356,7 +327,8 @@ func (c *Cache) unsafeUnloadCargo(sgi int, q float64) {
p.UnpackCapital()
}
func (c *Cache) shipGroupTransfer(ri, riAccept int, groupID uuid.UUID, quantity uint) (err error) {
func (c *Cache) shipGroupTransfer(ri, riAccept int, groupID uuid.UUID) (err error) {
c.validateRaceIndex(ri)
if ri == riAccept {
return e.NewSameRaceError(c.g.Race[riAccept].Name)
}
@@ -369,9 +341,6 @@ func (c *Cache) shipGroupTransfer(ri, riAccept int, groupID uuid.UUID, quantity
if state == game.StateTransfer {
return e.NewShipsBusyError("state: %s", state)
}
if sg.Number < quantity {
return e.NewBeakGroupNumberNotEnoughError("%d<%d", sg.Number, quantity)
}
st := c.ShipGroupShipClass(sgi)
@@ -402,19 +371,13 @@ func (c *Cache) shipGroupTransfer(ri, riAccept int, groupID uuid.UUID, quantity
newGroup.StateTransfer = true
}
if quantity == 0 || quantity == sg.Number {
c.unsafeDeleteShipGroup(sgi)
} else {
newGroup.Number = quantity
sg.Number -= quantity
}
c.appendShipGroup(riAccept, &newGroup)
c.unsafeDeleteShipGroup(sgi)
return nil
}
func (c *Cache) ShipGroupBreak(ri int, groupID uuid.UUID, quantity uint) error {
func (c *Cache) ShipGroupBreak(ri int, groupID, newID uuid.UUID, quantity uint) error {
c.validateRaceIndex(ri)
sgi, ok := c.raceShipGroupIndex(ri, groupID)
if !ok {
+3 -3
View File
@@ -19,8 +19,8 @@ func TestListMoveableGroupIds(t *testing.T) {
// 3: idx = 2 / [v] In-Fleet group
assert.NoError(t, c.CreateShips(Race_0_idx, Race_0_Freighter, R0_Planet_0_num, 10))
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, "Fleet", c.ShipGroup(1).ID, 0))
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, "Fleet", c.ShipGroup(2).ID, 0))
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, "Fleet", c.ShipGroup(1).ID))
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, "Fleet", c.ShipGroup(2).ID))
// 4: idx = 3 / [v] In_Space
assert.NoError(t, c.CreateShips(Race_0_idx, Race_0_Freighter, R0_Planet_0_num, 7))
@@ -34,7 +34,7 @@ func TestListMoveableGroupIds(t *testing.T) {
// 6: idx = 5 / [v] Just launched group
assert.NoError(t, c.CreateShips(Race_0_idx, Race_0_Freighter, R0_Planet_0_num, 10))
assert.NoError(t, g.ShipGroupSend(Race_0.Name, c.ShipGroup(5).ID, R0_Planet_2_num, 0))
assert.NoError(t, g.ShipGroupSend(Race_0.Name, c.ShipGroup(5).ID, R0_Planet_2_num))
movableGroups := slices.Collect(c.ListMoveableGroupIds())
assert.Len(t, movableGroups, 5)
+1 -13
View File
@@ -7,7 +7,7 @@ import (
"github.com/iliadenisov/galaxy/internal/util"
)
func (c *Cache) shipGroupSend(ri int, groupID uuid.UUID, planetNumber, quantity uint) error {
func (c *Cache) shipGroupSend(ri int, groupID uuid.UUID, planetNumber uint) error {
c.validateRaceIndex(ri)
sgi, ok := c.raceShipGroupIndex(ri, groupID)
@@ -25,10 +25,6 @@ func (c *Cache) shipGroupSend(ri int, groupID uuid.UUID, planetNumber, quantity
return e.NewShipsBusyError("state: %s", c.ShipGroup(sgi).State())
}
if c.ShipGroup(sgi).Number < quantity {
return e.NewBeakGroupNumberNotEnoughError("%d<%d", c.ShipGroup(sgi).Number, quantity)
}
p1, ok := c.Planet(sourcePlanet)
if !ok {
return e.NewGameStateError("source planet #%d does not exists", sourcePlanet)
@@ -42,14 +38,6 @@ func (c *Cache) shipGroupSend(ri int, groupID uuid.UUID, planetNumber, quantity
return e.NewSendUnreachableDestinationError("range=%.03f", rangeToDestination)
}
if quantity > 0 && quantity < c.ShipGroup(sgi).Number {
nsgi, err := c.breakGroup(ri, groupID, quantity)
if err != nil {
return err
}
sgi = nsgi
}
if p1.Number == p2.Number {
c.UnsendShips(sgi)
c.shipGroupMerge(ri)
+14 -42
View File
@@ -1,7 +1,6 @@
package controller_test
import (
"slices"
"testing"
"github.com/google/uuid"
@@ -17,66 +16,39 @@ func TestShipGroupSend(t *testing.T) {
assert.NoError(t, c.CreateShips(Race_0_idx, ShipType_Cruiser, R0_Planet_0_num, 10))
// group #2 - in_space
assert.NoError(t, c.CreateShips(Race_0_idx, ShipType_Cruiser, R0_Planet_0_num, 1))
// g.ShipGroups[1].StateInSpace = &game.InSpace{Origin: 2, Range: 1.23}
c.ShipGroup(1).StateInSpace = &InSpace
// group #3 - in_orbit, unmovable
g.ShipClassCreate(Race_0.Name, "Fortress", 0, 50, 30, 100, 0)
assert.NoError(t, c.CreateShips(Race_0_idx, "Fortress", R0_Planet_0_num, 1))
assert.ErrorContains(t,
g.ShipGroupSend(UnknownRace, c.ShipGroup(0).ID, 2, 0),
g.ShipGroupSend(UnknownRace, c.ShipGroup(0).ID, 2),
e.GenericErrorText(e.ErrInputUnknownRace))
assert.ErrorContains(t,
g.ShipGroupSend(Race_Extinct.Name, c.ShipGroup(0).ID, 2, 0),
g.ShipGroupSend(Race_Extinct.Name, c.ShipGroup(0).ID, 2),
e.GenericErrorText(e.ErrRaceExinct))
assert.ErrorContains(t,
g.ShipGroupSend(Race_0.Name, uuid.New(), 2, 0),
g.ShipGroupSend(Race_0.Name, uuid.New(), 2),
e.GenericErrorText(e.ErrInputEntityNotExists))
assert.ErrorContains(t,
g.ShipGroupSend(Race_0.Name, c.ShipGroup(0).ID, 222, 0),
g.ShipGroupSend(Race_0.Name, c.ShipGroup(0).ID, 222),
e.GenericErrorText(e.ErrInputEntityNotExists))
assert.ErrorContains(t,
g.ShipGroupSend(Race_0.Name, c.ShipGroup(1).ID, 1, 0),
g.ShipGroupSend(Race_0.Name, c.ShipGroup(1).ID, 1),
e.GenericErrorText(e.ErrShipsBusy))
assert.ErrorContains(t,
g.ShipGroupSend(Race_0.Name, c.ShipGroup(2).ID, 2, 0),
g.ShipGroupSend(Race_0.Name, c.ShipGroup(2).ID, 2),
e.GenericErrorText(e.ErrSendShipHasNoDrives))
assert.ErrorContains(t,
g.ShipGroupSend(Race_0.Name, c.ShipGroup(0).ID, 2, 100),
e.GenericErrorText(e.ErrBeakGroupNumberNotEnough))
assert.ErrorContains(t,
g.ShipGroupSend(Race_0.Name, c.ShipGroup(0).ID, 3, 0),
g.ShipGroupSend(Race_0.Name, c.ShipGroup(0).ID, 3),
e.GenericErrorText(e.ErrSendUnreachableDestination))
assert.NoError(t, g.ShipGroupSend(Race_0.Name, c.ShipGroup(0).ID, R0_Planet_2_num, 3)) // send 3 of 10
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 4)
assert.Equal(t, uint(7), c.ShipGroup(0).Number)
assert.Equal(t, game.StateInOrbit, c.ShipGroup(0).State())
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.Nil(t, c.ShipGroup(3).StateInSpace.X)
assert.Nil(t, c.ShipGroup(3).StateInSpace.Y)
assert.NoError(t, g.ShipGroupSend(Race_0.Name, c.ShipGroup(3).ID, R0_Planet_0_num, 2)) // un-send 2 of 3
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 4)
assert.Equal(t, uint(9), c.ShipGroup(0).Number)
assert.Equal(t, game.StateInOrbit, c.ShipGroup(0).State())
assert.Equal(t, uint(1), c.ShipGroup(3).Number)
assert.Equal(t, game.StateLaunched, c.ShipGroup(3).State())
assert.NotNil(t, c.ShipGroup(3).StateInSpace)
assert.Nil(t, c.ShipGroup(3).StateInSpace.X)
assert.Nil(t, c.ShipGroup(3).StateInSpace.Y)
assert.NoError(t, g.ShipGroupSend(Race_0.Name, c.ShipGroup(3).ID, R0_Planet_0_num, 0)) // un-send the rest 1
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 3)
assert.Equal(t, uint(10), c.ShipGroup(0).Number)
assert.Equal(t, game.StateInOrbit, c.ShipGroup(0).State())
assert.NoError(t, g.ShipGroupSend(Race_0.Name, c.ShipGroup(0).ID, R0_Planet_2_num, 0))
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 3)
assert.Equal(t, uint(10), c.ShipGroup(0).Number)
assert.NoError(t, g.ShipGroupSend(Race_0.Name, c.ShipGroup(0).ID, R0_Planet_2_num)) // send #0
assert.Equal(t, game.StateLaunched, c.ShipGroup(0).State())
assert.NotNil(t, c.ShipGroup(0).StateInSpace)
assert.Nil(t, c.ShipGroup(0).StateInSpace.X)
assert.Nil(t, c.ShipGroup(0).StateInSpace.Y)
assert.NoError(t, g.ShipGroupSend(Race_0.Name, c.ShipGroup(0).ID, R0_Planet_0_num)) // un-send #0
assert.Equal(t, game.StateInOrbit, c.ShipGroup(0).State())
}
+107 -165
View File
@@ -105,29 +105,29 @@ func TestShipGroupBreak(t *testing.T) {
c.ShipGroup(1).StateInSpace = &InSpace
fleet := "R0_Fleet"
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, fleet, c.ShipGroup(0).ID, 0))
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, fleet, c.ShipGroup(0).ID))
assert.ErrorContains(t,
g.ShipGroupBreak(UnknownRace, c.ShipGroup(0).ID, 0),
g.ShipGroupBreak(UnknownRace, c.ShipGroup(0).ID, uuid.New(), 1),
e.GenericErrorText(e.ErrInputUnknownRace))
assert.ErrorContains(t,
g.ShipGroupBreak(Race_Extinct.Name, c.ShipGroup(0).ID, 0),
g.ShipGroupBreak(Race_Extinct.Name, c.ShipGroup(0).ID, uuid.New(), 1),
e.GenericErrorText(e.ErrRaceExinct))
assert.ErrorContains(t,
g.ShipGroupBreak(Race_0.Name, uuid.New(), 0),
g.ShipGroupBreak(Race_0.Name, uuid.New(), uuid.New(), 1),
e.GenericErrorText(e.ErrInputEntityNotExists))
assert.ErrorContains(t,
g.ShipGroupBreak(Race_0.Name, c.ShipGroup(0).ID, 17),
g.ShipGroupBreak(Race_0.Name, c.ShipGroup(0).ID, uuid.New(), 17),
e.GenericErrorText(e.ErrBeakGroupNumberNotEnough))
assert.ErrorContains(t,
g.ShipGroupBreak(Race_0.Name, c.ShipGroup(1).ID, 0),
g.ShipGroupBreak(Race_0.Name, c.ShipGroup(1).ID, uuid.New(), 1),
e.GenericErrorText(e.ErrShipsBusy))
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 2)
assert.Len(t, slices.Collect(c.ListFleets(Race_0_idx)), 1)
// group #1 -> group #3 (5 new, 8 left)
assert.NoError(t, c.ShipGroupBreak(Race_0_idx, c.ShipGroup(0).ID, 5)) // group #3 (2)
assert.NoError(t, c.ShipGroupBreak(Race_0_idx, c.ShipGroup(0).ID, uuid.New(), 5)) // group #3 (2)
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 3)
assert.Equal(t, uint(8), c.ShipGroup(0).Number)
assert.NotNil(t, c.ShipGroup(0).FleetID)
@@ -139,14 +139,14 @@ func TestShipGroupBreak(t *testing.T) {
// group #1 -> group #4 (2 new, 6 left)
c.ShipGroup(0).CargoType = game.CargoColonist.Ref()
c.ShipGroup(0).Load = 32.8 // 8 ships
assert.NoError(t, c.ShipGroupBreak(Race_0_idx, c.ShipGroup(0).ID, 2)) // group #4 (3)
assert.NoError(t, c.ShipGroupBreak(Race_0_idx, c.ShipGroup(0).ID, uuid.New(), 2)) // group #4 (3)
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 4)
assert.Equal(t, uint(6), c.ShipGroup(0).Number)
assert.NotNil(t, c.ShipGroup(0).FleetID)
assert.Equal(t, uint(2), c.ShipGroup(3).Number)
// assert.Equal(t, uint(4), c.ShipGroup(3).Index)
assert.Nil(t, c.ShipGroup(3).FleetID)
assert.NoError(t, c.ShipGroupJoinFleet(Race_0_idx, fleet, c.ShipGroup(3).ID, 0))
assert.NoError(t, c.ShipGroupJoinFleet(Race_0_idx, fleet, c.ShipGroup(3).ID))
assert.NotNil(t, c.ShipGroup(3).FleetID)
assert.Equal(t, game.CargoColonist.Ref(), c.ShipGroup(0).CargoType)
@@ -155,13 +155,13 @@ func TestShipGroupBreak(t *testing.T) {
assert.Equal(t, 8.2, number.Fixed3(c.ShipGroup(3).Load.F()))
// group #1 -> MAX 6 off the fleet
assert.NoError(t, g.ShipGroupBreak(Race_0.Name, c.ShipGroup(0).ID, 6)) // group #1 (0)
assert.NoError(t, g.ShipGroupBreak(Race_0.Name, c.ShipGroup(0).ID, uuid.New(), 6)) // group #1 (0)
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 4)
assert.Equal(t, uint(6), c.ShipGroup(0).Number)
assert.Nil(t, c.ShipGroup(0).FleetID)
// group #4 -> ALL off the fleet
assert.NoError(t, g.ShipGroupBreak(Race_0.Name, c.ShipGroup(3).ID, 0)) // group #1 (0)
assert.NoError(t, g.ShipGroupBreak(Race_0.Name, c.ShipGroup(3).ID, uuid.New(), 0)) // group #1 (0)
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 4)
assert.Equal(t, uint(2), c.ShipGroup(3).Number)
assert.Nil(t, c.ShipGroup(3).FleetID)
@@ -173,7 +173,7 @@ func TestShipGroupTransfer(t *testing.T) {
assert.NoError(t, c.CreateShips(Race_1_idx, ShipType_Cruiser, R1_Planet_1_num, 23)) // group #2 (1)
assert.NoError(t, c.CreateShips(Race_0_idx, Race_0_Gunship, R0_Planet_0_num, 17)) // group #3 (2) - In_Space
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, "R0_Fleet", c.ShipGroup(2).ID, 0))
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, "R0_Fleet", c.ShipGroup(2).ID))
assert.NotNil(t, c.ShipGroup(2).FleetID)
c.ShipGroup(2).StateInSpace = &InSpace
c.ShipGroup(2).CargoType = game.CargoMaterial.Ref()
@@ -183,74 +183,71 @@ func TestShipGroupTransfer(t *testing.T) {
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_1_idx)), 1)
assert.ErrorContains(t,
g.ShipGroupTransfer(UnknownRace, Race_1.Name, c.ShipGroup(1).ID, 0),
g.ShipGroupTransfer(UnknownRace, Race_1.Name, c.ShipGroup(1).ID),
e.GenericErrorText(e.ErrInputUnknownRace))
assert.ErrorContains(t,
g.ShipGroupTransfer(Race_0.Name, UnknownRace, c.ShipGroup(1).ID, 0),
g.ShipGroupTransfer(Race_0.Name, UnknownRace, c.ShipGroup(1).ID),
e.GenericErrorText(e.ErrInputUnknownRace))
assert.ErrorContains(t,
g.ShipGroupTransfer(Race_0.Name, Race_Extinct.Name, c.ShipGroup(1).ID, 0),
g.ShipGroupTransfer(Race_0.Name, Race_Extinct.Name, c.ShipGroup(1).ID),
e.GenericErrorText(e.ErrRaceExinct))
assert.ErrorContains(t,
g.ShipGroupTransfer(Race_Extinct.Name, Race_1.Name, c.ShipGroup(1).ID, 0),
g.ShipGroupTransfer(Race_Extinct.Name, Race_1.Name, c.ShipGroup(1).ID),
e.GenericErrorText(e.ErrRaceExinct))
assert.ErrorContains(t,
g.ShipGroupTransfer(Race_0.Name, Race_0.Name, c.ShipGroup(1).ID, 0),
g.ShipGroupTransfer(Race_0.Name, Race_0.Name, c.ShipGroup(1).ID),
e.GenericErrorText(e.ErrInputSameRace))
assert.ErrorContains(t,
g.ShipGroupTransfer(Race_0.Name, Race_1.Name, uuid.New(), 0),
g.ShipGroupTransfer(Race_0.Name, Race_1.Name, uuid.New()),
e.GenericErrorText(e.ErrInputEntityNotExists))
assert.ErrorContains(t,
g.ShipGroupTransfer(Race_0.Name, Race_1.Name, c.ShipGroup(2).ID, 18),
e.GenericErrorText(e.ErrBeakGroupNumberNotEnough))
assert.ErrorContains(t,
g.ShipGroupTransfer(Race_0.Name, Race_1.Name, c.ShipGroup(0).ID, 0),
g.ShipGroupTransfer(Race_0.Name, Race_1.Name, c.ShipGroup(0).ID),
e.GenericErrorText(e.ErrGiveawayGroupShipsTypeNotEqual))
assert.NoError(t, g.ShipGroupTransfer(Race_0.Name, Race_1.Name, c.ShipGroup(2).ID, 11)) // group #2 (3)
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 2)
orig := *c.ShipGroup(2)
assert.NoError(t, g.ShipGroupTransfer(Race_0.Name, Race_1.Name, c.ShipGroup(2).ID)) // group #2 (3)
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 1)
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_1_idx)), 2)
newSg := c.ShipGroup(2)
assert.Equal(t, c.MustShipClass(Race_1_idx, Race_0_Gunship).Name, c.MustShipClass(Race_0_idx, Race_0_Gunship).Name)
assert.Equal(t, c.MustShipClass(Race_1_idx, Race_0_Gunship).Drive, c.MustShipClass(Race_0_idx, Race_0_Gunship).Drive)
assert.Equal(t, c.MustShipClass(Race_1_idx, Race_0_Gunship).Weapons, c.MustShipClass(Race_0_idx, Race_0_Gunship).Weapons)
assert.Equal(t, c.MustShipClass(Race_1_idx, Race_0_Gunship).Shields, c.MustShipClass(Race_0_idx, Race_0_Gunship).Shields)
assert.Equal(t, c.MustShipClass(Race_1_idx, Race_0_Gunship).Cargo, c.MustShipClass(Race_0_idx, Race_0_Gunship).Cargo)
assert.Equal(t, c.MustShipClass(Race_1_idx, Race_0_Gunship).Armament, c.MustShipClass(Race_0_idx, Race_0_Gunship).Armament)
assert.Equal(t, c.ShipGroup(2).State(), c.ShipGroup(3).State())
assert.Equal(t, c.ShipGroup(2).CargoType, c.ShipGroup(3).CargoType)
assert.Equal(t, c.ShipGroup(2).Load, c.ShipGroup(3).Load)
assert.Equal(t, c.ShipGroup(2).TechLevel(game.TechDrive), c.ShipGroup(3).TechLevel(game.TechDrive))
assert.Equal(t, c.ShipGroup(2).TechLevel(game.TechWeapons), c.ShipGroup(3).TechLevel(game.TechWeapons))
assert.Equal(t, c.ShipGroup(2).TechLevel(game.TechShields), c.ShipGroup(3).TechLevel(game.TechShields))
assert.Equal(t, c.ShipGroup(2).TechLevel(game.TechCargo), c.ShipGroup(3).TechLevel(game.TechCargo))
assert.Equal(t, c.ShipGroup(2).Destination, c.ShipGroup(3).Destination)
assert.Equal(t, c.ShipGroup(2).StateInSpace, c.ShipGroup(3).StateInSpace)
assert.Equal(t, c.ShipGroup(2).StateUpgrade, c.ShipGroup(3).StateUpgrade)
assert.Equal(t, c.ShipGroup(2).StateTransfer, c.ShipGroup(3).StateTransfer)
assert.Equal(t, c.ShipGroup(3).OwnerID, Race_1_ID)
assert.Equal(t, c.ShipGroup(3).TypeID, c.MustShipClass(Race_1_idx, Race_0_Gunship).ID)
assert.Equal(t, c.ShipGroup(3).Number, uint(11))
assert.Nil(t, c.ShipGroup(3).FleetID)
assert.NoError(t, g.ShipGroupTransfer(Race_1.Name, Race_0.Name, c.ShipGroup(3).ID, 11))
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 3)
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_1_idx)), 1)
assert.Equal(t, orig.State(), newSg.State())
assert.Equal(t, orig.CargoType, newSg.CargoType)
assert.Equal(t, orig.Load, newSg.Load)
assert.Equal(t, orig.TechLevel(game.TechDrive), newSg.TechLevel(game.TechDrive))
assert.Equal(t, orig.TechLevel(game.TechWeapons), newSg.TechLevel(game.TechWeapons))
assert.Equal(t, orig.TechLevel(game.TechShields), newSg.TechLevel(game.TechShields))
assert.Equal(t, orig.TechLevel(game.TechCargo), newSg.TechLevel(game.TechCargo))
assert.Equal(t, orig.Destination, newSg.Destination)
assert.Equal(t, orig.StateInSpace, newSg.StateInSpace)
assert.Equal(t, orig.StateUpgrade, newSg.StateUpgrade)
assert.Equal(t, orig.StateTransfer, newSg.StateTransfer)
assert.Equal(t, newSg.TypeID, c.MustShipClass(Race_1_idx, Race_0_Gunship).ID)
assert.Equal(t, orig.Number, newSg.Number)
assert.Equal(t, Race_1_ID, newSg.OwnerID)
assert.Nil(t, newSg.FleetID)
assert.NoError(t, c.CreateShips(Race_0_idx, Race_0_Gunship, R0_Planet_0_num, 1))
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 4)
assert.Equal(t, game.StateInOrbit, c.ShipGroup(4).State())
assert.NoError(t, g.ShipGroupSend(Race_0.Name, c.ShipGroup(4).ID, R0_Planet_2_num, 0))
assert.Equal(t, game.StateLaunched, c.ShipGroup(4).State())
assert.Equal(t, c.ShipGroup(4).OwnerID, Race_0_ID)
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 2)
sg := c.ShipGroup(3)
assert.Equal(t, game.StateInOrbit, sg.State())
assert.NoError(t, g.ShipGroupSend(Race_0.Name, sg.ID, R0_Planet_2_num))
assert.Equal(t, game.StateLaunched, sg.State())
assert.Equal(t, sg.OwnerID, Race_0_ID)
assert.NoError(t, g.ShipGroupTransfer(Race_0.Name, Race_1.Name, c.ShipGroup(4).ID, 0))
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 3)
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_1_idx)), 2)
assert.Equal(t, game.StateTransfer, c.ShipGroup(4).State())
assert.Equal(t, c.ShipGroup(4).OwnerID, Race_1_ID)
assert.NoError(t, g.ShipGroupTransfer(Race_0.Name, Race_1.Name, sg.ID))
sg = c.ShipGroup(3)
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 1)
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_1_idx)), 3)
assert.Equal(t, game.StateTransfer, sg.State())
assert.Equal(t, sg.OwnerID, Race_1_ID)
assert.ErrorContains(t,
g.ShipGroupTransfer(Race_1.Name, Race_0.Name, c.ShipGroup(4).ID, 0),
g.ShipGroupTransfer(Race_1.Name, Race_0.Name, sg.ID),
e.GenericErrorText(e.ErrShipsBusy))
}
@@ -280,98 +277,84 @@ func TestShipGroupLoad(t *testing.T) {
// tests
assert.ErrorContains(t,
g.ShipGroupLoad(UnknownRace, c.ShipGroup(0).ID, game.CargoMaterial.String(), 0, 0),
g.ShipGroupLoad(UnknownRace, c.ShipGroup(0).ID, game.CargoMaterial.String(), 0),
e.GenericErrorText(e.ErrInputUnknownRace))
assert.ErrorContains(t,
g.ShipGroupLoad(Race_Extinct.Name, c.ShipGroup(0).ID, game.CargoMaterial.String(), 0, 0),
g.ShipGroupLoad(Race_Extinct.Name, c.ShipGroup(0).ID, game.CargoMaterial.String(), 0),
e.GenericErrorText(e.ErrRaceExinct))
assert.ErrorContains(t,
g.ShipGroupLoad(Race_0.Name, c.ShipGroup(0).ID, "GOLD", 0, 0),
g.ShipGroupLoad(Race_0.Name, c.ShipGroup(0).ID, "GOLD", 0),
e.GenericErrorText(e.ErrInputCargoTypeInvalid))
assert.ErrorContains(t,
g.ShipGroupLoad(Race_0.Name, uuid.New(), game.CargoMaterial.String(), 0, 0),
g.ShipGroupLoad(Race_0.Name, uuid.New(), game.CargoMaterial.String(), 0),
e.GenericErrorText(e.ErrInputEntityNotExists))
assert.ErrorContains(t,
g.ShipGroupLoad(Race_0.Name, c.ShipGroup(2).ID, game.CargoMaterial.String(), 0, 0),
g.ShipGroupLoad(Race_0.Name, c.ShipGroup(2).ID, game.CargoMaterial.String(), 0),
e.GenericErrorText(e.ErrShipsBusy))
assert.ErrorContains(t,
g.ShipGroupLoad(Race_0.Name, c.ShipGroup(4).ID, game.CargoMaterial.String(), 0, 0),
g.ShipGroupLoad(Race_0.Name, c.ShipGroup(4).ID, game.CargoMaterial.String(), 0),
e.GenericErrorText(e.ErrInputEntityNotOwned))
assert.ErrorContains(t,
g.ShipGroupLoad(Race_0.Name, c.ShipGroup(1).ID, game.CargoMaterial.String(), 0, 0),
g.ShipGroupLoad(Race_0.Name, c.ShipGroup(1).ID, game.CargoMaterial.String(), 0),
e.GenericErrorText(e.ErrInputNoCargoBay))
assert.ErrorContains(t,
g.ShipGroupLoad(Race_0.Name, c.ShipGroup(3).ID, game.CargoMaterial.String(), 0, 0),
g.ShipGroupLoad(Race_0.Name, c.ShipGroup(3).ID, game.CargoMaterial.String(), 0),
e.GenericErrorText(e.ErrInputCargoLoadNotEqual))
// initial planet is empty
assert.ErrorContains(t,
g.ShipGroupLoad(Race_0.Name, c.ShipGroup(0).ID, game.CargoMaterial.String(), 0, 0),
g.ShipGroupLoad(Race_0.Name, c.ShipGroup(0).ID, game.CargoMaterial.String(), 0),
e.GenericErrorText(e.ErrInputCargoLoadNotEnough))
// add cargo to planet
c.PutMaterial(R0_Planet_0_num, 100)
// not enough on the planet
assert.ErrorContains(t,
g.ShipGroupLoad(Race_0.Name, c.ShipGroup(0).ID, game.CargoMaterial.String(), 11, 101),
g.ShipGroupLoad(Race_0.Name, c.ShipGroup(0).ID, game.CargoMaterial.String(), 101),
e.GenericErrorText(e.ErrInputCargoLoadNotEnough))
// quantity > ships
assert.ErrorContains(t,
g.ShipGroupLoad(Race_0.Name, c.ShipGroup(0).ID, game.CargoMaterial.String(), 0, 1),
e.GenericErrorText(e.ErrInputCargoQuantityWithoutGroupBreak))
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 5)
// break group and load maximum
assert.NoError(t, g.ShipGroupLoad(Race_0.Name, c.ShipGroup(0).ID, game.CargoMaterial.String(), 2, 0))
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.F())
assert.Equal(t, uint(2), c.ShipGroup(5).Number)
assert.Equal(t, 42.0, c.ShipGroup(5).Load.F())
// load maximum
assert.NoError(t, g.ShipGroupLoad(Race_0.Name, c.ShipGroup(0).ID, game.CargoMaterial.String(), 0))
assert.Equal(t, 0.0, c.MustPlanet(R0_Planet_0_num).Material.F())
assert.Equal(t, game.CargoMaterial.Ref(), c.ShipGroup(0).CargoType)
assert.Equal(t, 100.0, c.ShipGroup(0).Load.F())
// break group and load limited
assert.NoError(t, g.ShipGroupLoad(Race_0.Name, c.ShipGroup(0).ID, game.CargoMaterial.String(), 2, 18))
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.F())
assert.Equal(t, uint(2), c.ShipGroup(6).Number)
assert.Equal(t, 18.0, c.ShipGroup(6).Load.F())
assert.NoError(t, g.ShipGroupUnload(Race_0.Name, c.ShipGroup(0).ID, 0))
// load limited
assert.NoError(t, g.ShipGroupLoad(Race_0.Name, c.ShipGroup(0).ID, game.CargoMaterial.String(), 18))
assert.Equal(t, 82.0, c.MustPlanet(R0_Planet_0_num).Material.F())
assert.Equal(t, game.CargoMaterial.Ref(), c.ShipGroup(0).CargoType)
assert.Equal(t, 18.0, c.ShipGroup(0).Load.F())
assert.NoError(t, g.ShipGroupUnload(Race_0.Name, c.ShipGroup(0).ID, 0))
// add cargo to planet
c.PutMaterial(R0_Planet_0_num, 100)
// loading all available cargo
assert.NoError(t, g.ShipGroupLoad(Race_0.Name, c.ShipGroup(0).ID, game.CargoMaterial.String(), 0, 0))
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 7)
assert.NoError(t, g.ShipGroupLoad(Race_0.Name, c.ShipGroup(0).ID, game.CargoMaterial.String(), 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.ShipGroupLoad(Race_0.Name, c.ShipGroup(0).ID, game.CargoMaterial.String(), 11, 31))
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 7)
assert.NoError(t, g.ShipGroupLoad(Race_0.Name, c.ShipGroup(0).ID, game.CargoMaterial.String(), 31))
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.ShipGroupLoad(Race_0.Name, c.ShipGroup(0).ID, 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.F())
assert.Equal(t, 147.0, c.ShipGroup(0).Load.F()) // free: 0.0
assert.NoError(t, g.ShipGroupLoad(Race_0.Name, c.ShipGroup(0).ID, game.CargoMaterial.String(), 0))
assert.Equal(t, 69.0, c.MustPlanet(R0_Planet_0_num).Material.F())
assert.Equal(t, 231.0, c.ShipGroup(0).Load.F()) // free: 0.0
assert.Equal(t, game.CargoMaterial.Ref(), c.ShipGroup(0).CargoType)
// ship group is full
assert.ErrorContains(t,
g.ShipGroupLoad(Race_0.Name, c.ShipGroup(0).ID, game.CargoMaterial.String(), 0, 0),
g.ShipGroupLoad(Race_0.Name, c.ShipGroup(0).ID, game.CargoMaterial.String(), 0),
e.GenericErrorText(e.ErrInputCargoLoadNoSpaceLeft))
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 7)
}
func TestShipGroupUnload(t *testing.T) {
@@ -408,67 +391,51 @@ func TestShipGroupUnload(t *testing.T) {
// tests
assert.ErrorContains(t,
g.ShipGroupUnload(UnknownRace, c.ShipGroup(0).ID, 0, 0),
g.ShipGroupUnload(UnknownRace, c.ShipGroup(0).ID, 0),
e.GenericErrorText(e.ErrInputUnknownRace))
assert.ErrorContains(t,
g.ShipGroupUnload(Race_Extinct.Name, c.ShipGroup(0).ID, 0, 0),
g.ShipGroupUnload(Race_Extinct.Name, c.ShipGroup(0).ID, 0),
e.GenericErrorText(e.ErrRaceExinct))
assert.ErrorContains(t,
g.ShipGroupUnload(Race_0.Name, uuid.New(), 0, 0),
g.ShipGroupUnload(Race_0.Name, uuid.New(), 0),
e.GenericErrorText(e.ErrInputEntityNotExists))
assert.ErrorContains(t,
g.ShipGroupUnload(Race_0.Name, c.ShipGroup(2).ID, 0, 0),
g.ShipGroupUnload(Race_0.Name, c.ShipGroup(2).ID, 0),
e.GenericErrorText(e.ErrShipsBusy))
assert.ErrorContains(t,
g.ShipGroupUnload(Race_0.Name, c.ShipGroup(1).ID, 0, 0),
g.ShipGroupUnload(Race_0.Name, c.ShipGroup(1).ID, 0),
e.GenericErrorText(e.ErrInputNoCargoBay))
assert.ErrorContains(t,
g.ShipGroupUnload(Race_0.Name, c.ShipGroup(0).ID, 0, 0),
g.ShipGroupUnload(Race_0.Name, c.ShipGroup(0).ID, 0),
e.GenericErrorText(e.ErrInputCargoUnloadEmpty))
assert.ErrorContains(t,
g.ShipGroupUnload(Race_0.Name, c.ShipGroup(4).ID, 0, 0),
g.ShipGroupUnload(Race_0.Name, c.ShipGroup(4).ID, 0),
e.GenericErrorText(e.ErrInputEntityNotOwned))
c.ShipGroup(0).CargoType = game.CargoColonist.Ref()
c.ShipGroup(0).Load = 100
assert.ErrorContains(t,
g.ShipGroupUnload(Race_0.Name, c.ShipGroup(0).ID, 11, 101),
g.ShipGroupUnload(Race_0.Name, c.ShipGroup(0).ID, 101),
e.GenericErrorText(e.ErrInputCargoUnoadNotEnough))
assert.ErrorContains(t,
g.ShipGroupUnload(Race_0.Name, c.ShipGroup(0).ID, 0, 1),
e.GenericErrorText(e.ErrInputCargoQuantityWithoutGroupBreak))
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 6)
// unload MAT on foreign planet / break group
assert.NoError(t, g.ShipGroupUnload(Race_0.Name, c.ShipGroup(5).ID, 3, 0))
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.Equal(t, 0., c.ShipGroup(6).Load.F())
assert.Nil(t, c.ShipGroup(6).CargoType)
assert.Equal(t, 0.0, c.ShipGroup(6).Load.F())
// unload MAT on foreign planet / limited
assert.NoError(t, g.ShipGroupUnload(Race_0.Name, c.ShipGroup(5).ID, 20.1))
assert.Equal(t, 20.1, number.Fixed3(c.MustPlanet(R1_Planet_1_num).Material.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.F()))
assert.Equal(t, 79.9, number.Fixed3(c.ShipGroup(5).Load.F()))
// unload MAT on foreign planet / break group / limited MAT
assert.NoError(t, g.ShipGroupUnload(Race_0.Name, c.ShipGroup(5).ID, 3, 20.0))
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.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.F()))
// unload MAT on foreign planet / ALL
assert.NoError(t, g.ShipGroupUnload(Race_0.Name, c.ShipGroup(5).ID, 0))
assert.Equal(t, 100.0, number.Fixed3(c.MustPlanet(R1_Planet_1_num).Material.F()))
assert.Equal(t, 0.0, number.Fixed3(c.ShipGroup(5).Load.F()))
assert.Nil(t, c.ShipGroup(5).CargoType)
// unload ALL
assert.NoError(t, g.ShipGroupUnload(Race_0.Name, c.ShipGroup(0).ID, 0, 0))
assert.NoError(t, g.ShipGroupUnload(Race_0.Name, c.ShipGroup(0).ID, 0))
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.F()))
assert.Nil(t, c.ShipGroup(0).CargoType)
}
func TestShipGroupDismantle(t *testing.T) {
@@ -502,26 +469,23 @@ func TestShipGroupDismantle(t *testing.T) {
// tests
assert.ErrorContains(t,
g.ShipGroupDismantle(UnknownRace, c.ShipGroup(0).ID, 0),
g.ShipGroupDismantle(UnknownRace, c.ShipGroup(0).ID),
e.GenericErrorText(e.ErrInputUnknownRace))
assert.ErrorContains(t,
g.ShipGroupDismantle(Race_Extinct.Name, c.ShipGroup(0).ID, 0),
g.ShipGroupDismantle(Race_Extinct.Name, c.ShipGroup(0).ID),
e.GenericErrorText(e.ErrRaceExinct))
assert.ErrorContains(t,
g.ShipGroupDismantle(Race_0.Name, uuid.New(), 0),
g.ShipGroupDismantle(Race_0.Name, uuid.New()),
e.GenericErrorText(e.ErrInputEntityNotExists))
assert.ErrorContains(t,
g.ShipGroupDismantle(Race_0.Name, c.ShipGroup(1).ID, 0),
g.ShipGroupDismantle(Race_0.Name, c.ShipGroup(1).ID),
e.GenericErrorText(e.ErrShipsBusy))
assert.ErrorContains(t,
g.ShipGroupDismantle(Race_0.Name, c.ShipGroup(2).ID, 12),
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.F()
planetCOL := c.MustPlanet(R1_Planet_1_num).Colonists.F()
assert.NoError(t, g.ShipGroupDismantle(Race_0.Name, c.ShipGroup(4).ID, 0))
assert.NoError(t, g.ShipGroupDismantle(Race_0.Name, c.ShipGroup(4).ID))
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 4)
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())
@@ -529,31 +493,9 @@ func TestShipGroupDismantle(t *testing.T) {
groupEmptyMass = c.ShipGroup(3).EmptyMass(c.MustShipClass(Race_0_idx, Race_0_Freighter))
groupLoadMAT := c.ShipGroup(3).Load.F()
planetMAT = c.MustPlanet(R1_Planet_1_num).Material.F()
assert.NoError(t, g.ShipGroupDismantle(Race_0.Name, c.ShipGroup(3).ID, 0))
assert.NoError(t, g.ShipGroupDismantle(Race_0.Name, c.ShipGroup(3).ID))
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 3)
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.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.F())
var quantity uint = 3
groupEmptyMass = groupEmptyMass / 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.F() - c.MustPlanet(R0_Planet_0_num).Population.F()
expectAddedCOL := (expectPOPIncrease - freePOPLeft) / 8
expectAddedPOP := freePOPLeft
assert.NoError(t, g.ShipGroupDismantle(Race_0.Name, c.ShipGroup(2).ID, quantity))
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 3)
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.F())
}
func TestShipGroupDestroyItem(t *testing.T) {
@@ -578,7 +520,7 @@ func TestUnsafeDeleteShipGroup(t *testing.T) {
assert.NoError(t, c.CreateShips(Race_0_idx, Race_0_Gunship, R0_Planet_0_num, 3)) // 0
assert.NoError(t, c.CreateShips(Race_0_idx, Race_0_Gunship, R0_Planet_2_num, 5)) // 1
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, "Fleet", c.ShipGroup(0).ID, 0))
assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, "Fleet", c.ShipGroup(0).ID))
assert.NoError(t, c.CreateShips(Race_0_idx, Race_0_Freighter, R0_Planet_2_num, 7)) // 2
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 3)
+1 -6
View File
@@ -10,7 +10,7 @@ import (
"github.com/iliadenisov/galaxy/internal/model/game"
)
func (c *Cache) shipGroupUpgrade(ri int, groupID uuid.UUID, techInput string, limitShips uint, limitLevel float64) error {
func (c *Cache) shipGroupUpgrade(ri int, groupID uuid.UUID, techInput string, limitLevel float64) error {
c.validateRaceIndex(ri)
sgi, ok := c.raceShipGroupIndex(ri, groupID)
if !ok {
@@ -77,11 +77,6 @@ func (c *Cache) shipGroupUpgrade(ri int, groupID uuid.UUID, techInput string, li
}
shipsToUpgrade := sg.Number
// НЕ БОЛЕЕ УКАЗАННОГО
if limitShips > 0 && shipsToUpgrade > limitShips {
shipsToUpgrade = limitShips
}
maxUpgradableShips := uc.UpgradeMaxShips(productionCapacity)
/*
+18 -17
View File
@@ -1,7 +1,6 @@
package controller_test
import (
"slices"
"testing"
"github.com/google/uuid"
@@ -126,50 +125,52 @@ func TestShipGroupUpgrade(t *testing.T) {
c.ShipGroup(2).Destination = R1_Planet_1_num
assert.ErrorContains(t,
g.ShipGroupUpgrade(UnknownRace, c.ShipGroup(0).ID, "DRIVE", 0, 0),
g.ShipGroupUpgrade(UnknownRace, c.ShipGroup(0).ID, "DRIVE", 0),
e.GenericErrorText(e.ErrInputUnknownRace))
assert.ErrorContains(t,
g.ShipGroupUpgrade(Race_Extinct.Name, c.ShipGroup(0).ID, "DRIVE", 0, 0),
g.ShipGroupUpgrade(Race_Extinct.Name, c.ShipGroup(0).ID, "DRIVE", 0),
e.GenericErrorText(e.ErrRaceExinct))
assert.ErrorContains(t,
g.ShipGroupUpgrade(Race_0.Name, uuid.New(), "DRIVE", 0, 0),
g.ShipGroupUpgrade(Race_0.Name, uuid.New(), "DRIVE", 0),
e.GenericErrorText(e.ErrInputEntityNotExists))
assert.ErrorContains(t,
g.ShipGroupUpgrade(Race_0.Name, c.ShipGroup(1).ID, "DRIVE", 0, 0),
g.ShipGroupUpgrade(Race_0.Name, c.ShipGroup(1).ID, "DRIVE", 0),
e.GenericErrorText(e.ErrShipsBusy))
assert.ErrorContains(t,
g.ShipGroupUpgrade(Race_0.Name, c.ShipGroup(2).ID, "DRIVE", 0, 0),
g.ShipGroupUpgrade(Race_0.Name, c.ShipGroup(2).ID, "DRIVE", 0),
e.GenericErrorText(e.ErrInputEntityNotOwned))
assert.ErrorContains(t,
g.ShipGroupUpgrade(Race_0.Name, c.ShipGroup(0).ID, "GUN", 0, 0),
g.ShipGroupUpgrade(Race_0.Name, c.ShipGroup(0).ID, "GUN", 0),
e.GenericErrorText(e.ErrInputTechUnknown))
assert.ErrorContains(t,
g.ShipGroupUpgrade(Race_0.Name, c.ShipGroup(0).ID, "CARGO", 0, 0),
g.ShipGroupUpgrade(Race_0.Name, c.ShipGroup(0).ID, "CARGO", 0),
e.GenericErrorText(e.ErrInputUpgradeShipTechNotUsed))
assert.ErrorContains(t,
g.ShipGroupUpgrade(Race_0.Name, c.ShipGroup(0).ID, "ALL", 0, 2.0),
g.ShipGroupUpgrade(Race_0.Name, c.ShipGroup(0).ID, "ALL", 2.0),
e.GenericErrorText(e.ErrInputUpgradeParameterNotAllowed))
assert.ErrorContains(t,
g.ShipGroupUpgrade(Race_0.Name, c.ShipGroup(0).ID, "DRIVE", 0, 2.0),
g.ShipGroupUpgrade(Race_0.Name, c.ShipGroup(0).ID, "DRIVE", 2.0),
e.GenericErrorText(e.ErrInputUpgradeTechLevelInsufficient))
assert.ErrorContains(t,
g.ShipGroupUpgrade(Race_0.Name, c.ShipGroup(0).ID, "DRIVE", 0, 1.1),
g.ShipGroupUpgrade(Race_0.Name, c.ShipGroup(0).ID, "DRIVE", 1.1),
e.GenericErrorText(e.ErrInputUpgradeShipsAlreadyUpToDate))
c.RaceTechLevel(Race_0_idx, game.TechDrive, 10.0)
assert.Equal(t, 10.0, c.Race(Race_0_idx).TechLevel(game.TechDrive))
assert.ErrorContains(t,
g.ShipGroupUpgrade(Race_0.Name, c.ShipGroup(0).ID, "DRIVE", 0, 10.0),
g.ShipGroupUpgrade(Race_0.Name, c.ShipGroup(0).ID, "DRIVE", 10.0),
e.GenericErrorText(e.ErrUpgradeInsufficientResources))
assert.NoError(t, g.ShipGroupUpgrade(Race_0.Name, c.ShipGroup(0).ID, "DRIVE", 2, 1.2))
assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 4)
assert.Equal(t, uint(8), c.ShipGroup(0).Number)
assert.Equal(t, uint(2), c.ShipGroup(3).Number)
assert.NoError(t, g.ShipGroupUpgrade(Race_0.Name, c.ShipGroup(0).ID, "DRIVE", 1.3))
assert.Equal(t, game.StateInOrbit, c.ShipGroup(0).State())
assert.Equal(t, uint(6), c.ShipGroup(0).Number)
assert.Equal(t, game.StateUpgrade, c.ShipGroup(3).State())
assert.Equal(t, uint(4), c.ShipGroup(3).Number)
assert.NotNil(t, c.ShipGroup(3).StateUpgrade)
assert.Equal(t, 1.3, c.ShipGroup(3).StateUpgrade.UpgradeTech[0].Level.F())
assert.Equal(t, "DRIVE", c.ShipGroup(3).StateUpgrade.UpgradeTech[0].Tech.String())
assert.ErrorContains(t,
g.ShipGroupUpgrade(Race_0.Name, c.ShipGroup(3).ID, "DRIVE", 1, 1.3),
g.ShipGroupUpgrade(Race_0.Name, c.ShipGroup(3).ID, "DRIVE", 1.3),
e.GenericErrorText(e.ErrShipsBusy))
}
-6
View File
@@ -18,7 +18,6 @@ const (
ErrDeleteShipTypePlanetProduction = 5001
ErrDeleteSciencePlanetProduction = 5002
ErrMergeShipTypeNotEqual = 5003
ErrJoinFleetGroupNumberNotEnough = 5004
ErrBeakGroupNumberNotEnough = 5005
ErrEntityInUse = 5006
ErrShipsBusy = 5007
@@ -51,7 +50,6 @@ const (
ErrInputScienceSumValues
ErrInputProductionInvalid
ErrInputCargoTypeInvalid
ErrInputCargoQuantityWithoutGroupBreak
ErrInputCargoLoadNotEnough
ErrInputCargoLoadNotEqual
ErrInputNoCargoBay
@@ -123,8 +121,6 @@ func GenericErrorText(code int) string {
return "Invalid Production type"
case ErrInputCargoTypeInvalid:
return "Invalid cargo type"
case ErrInputCargoQuantityWithoutGroupBreak:
return "Cargo quantity should be specified only for a new group number of ships"
case ErrInputCargoLoadNotEnough:
return "Not enough cargo to load"
case ErrInputCargoLoadNotEqual:
@@ -141,8 +137,6 @@ func GenericErrorText(code int) string {
return "Illegal ships number to make new group"
case ErrMergeShipTypeNotEqual:
return "Source and target ship types are not the same"
case ErrJoinFleetGroupNumberNotEnough:
return "Not enough ships in the group to join a fleet"
case ErrBeakGroupNumberNotEnough:
return "Not enough ships in the group to make a separate group"
case ErrShipsBusy:
-8
View File
@@ -80,10 +80,6 @@ func NewCargoTypeInvalidError(arg ...any) error {
return newGenericError(ErrInputCargoTypeInvalid, arg...)
}
func NewCargoQuantityWithoutGroupBreakError(arg ...any) error {
return newGenericError(ErrInputCargoQuantityWithoutGroupBreak, arg...)
}
func NewCargoLoadNotEnoughError(arg ...any) error {
return newGenericError(ErrInputCargoLoadNotEnough, arg...)
}
@@ -116,10 +112,6 @@ func NewMergeShipTypeNotEqualError(arg ...any) error {
return newGenericError(ErrMergeShipTypeNotEqual, arg...)
}
func NewJoinFleetGroupNumberNotEnoughError(arg ...any) error {
return newGenericError(ErrJoinFleetGroupNumberNotEnough, arg...)
}
func NewBeakGroupNumberNotEnoughError(arg ...any) error {
return newGenericError(ErrBeakGroupNumberNotEnough, arg...)
}
-7
View File
@@ -87,14 +87,12 @@ type CommandShipGroupLoad struct {
CommandMeta
ID string `json:"id" binding:"required,uuid_rfc4122"`
Cargo string `json:"cargo" binding:"required,notblank,oneof=COL MAT CAP"`
Ships int `json:"ships" binding:"gte=0"`
Quantity float64 `json:"quantity" binding:"gte=0"`
}
type CommandShipGroupUnload struct {
CommandMeta
ID string `json:"id" binding:"required,uuid_rfc4122"`
Ships int `json:"ships" binding:"gte=0"`
Quantity float64 `json:"quantity" binding:"gte=0"`
}
@@ -102,14 +100,12 @@ type CommandShipGroupSend struct {
CommandMeta
ID string `json:"id" binding:"required,uuid_rfc4122"`
Destination int `json:"planetNumber" binding:"gte=0"`
Quantity int `json:"quantity" binding:"gte=0"`
}
type CommandShipGroupUpgrade struct {
CommandMeta
ID string `json:"id" binding:"required,uuid_rfc4122"`
Tech string `json:"tech" binding:"oneof=ALL DRIVE WEAPONS SHIELDS CARGO"`
MaxShips int `json:"maxShips" binding:"gte=0"`
Level int `json:"level" binding:"gte=1"`
}
@@ -126,21 +122,18 @@ type CommandShipGroupBreak struct {
type CommandShipGroupDismantle struct {
CommandMeta
ID string `json:"id" binding:"required,uuid_rfc4122"`
Quantity int `json:"quantity" binding:"gte=0"`
}
type CommandShipGroupTransfer struct {
CommandMeta
ID string `json:"id" binding:"required,uuid_rfc4122"`
Acceptor string `json:"acceptor" binding:"required,notblank"`
Quantity int `json:"quantity" binding:"gte=0"`
}
type CommandShipGroupJoinFleet struct {
CommandMeta
ID string `json:"id" binding:"required,uuid_rfc4122"`
Name string `json:"name" binding:"required,notblank,entity"`
Quantity int `json:"quantity" binding:"gte=0"`
}
type CommandFleetMerge struct {