refactor: FleetState

This commit is contained in:
Ilia Denisov
2026-02-04 20:26:52 +02:00
parent c1d397c993
commit 46b4ab96f0
6 changed files with 77 additions and 43 deletions
+57 -24
View File
@@ -11,42 +11,74 @@ import (
"github.com/iliadenisov/galaxy/internal/model/game"
)
func (c *Cache) FleetState(fleetID uuid.UUID) (game.ShipGroupState, *uint, *game.InSpace) {
var fleetStateNil = game.ShipGroupState("-")
type FleetState struct {
State game.ShipGroupState
Destination uint
InSpace func() (game.InSpace, bool)
OnPlanet func() (uint, bool)
}
func (fs *FleetState) inSpace() bool {
_, ok := fs.InSpace()
return ok
}
func (fs FleetState) OnSamePlanet(other FleetState) bool {
op1, ok := fs.OnPlanet()
if !ok {
return false
}
op2, ok := other.OnPlanet()
if !ok {
return false
}
return op1 == op2
}
func (c *Cache) FleetState(fleetID uuid.UUID) FleetState {
fi := c.MustFleetIndex(fleetID)
ri := c.RaceIndex(c.g.Fleets[fi].OwnerID)
var state *game.ShipGroupState
var onPlanet *uint
var is *game.InSpace
fs := &FleetState{
State: fleetStateNil,
InSpace: func() (game.InSpace, bool) { return game.InSpace{}, false },
OnPlanet: func() (uint, bool) { return 0, false },
}
for sg := range c.FleetGroups(ri, fi) {
if state == nil {
s := sg.State()
state = &s
if fs.State == fleetStateNil {
fs.State = sg.State()
fs.Destination = sg.Destination
if planet, ok := sg.OnPlanet(); ok {
onPlanet = &planet
fs.OnPlanet = func() (uint, bool) { return planet, ok }
}
if sg.StateInSpace != nil {
fs.InSpace = func() (game.InSpace, bool) { return *sg.StateInSpace, true }
}
is = sg.StateInSpace
continue
}
if *state != sg.State() {
if fs.State != sg.State() {
panic(fmt.Sprintf("FleetState: one or more ships in race's %q fleet %q has different states", c.g.Race[ri].Name, c.g.Fleets[fi].Name))
}
if planet, ok := sg.OnPlanet(); ok && onPlanet != nil && *onPlanet != planet {
// for sg := range c.FleetGroups(ri, fi) {
// fmt.Println("group", sg.Index, "fleet", sg.FleetID, c.g.Fleets[fi].Name, "state", sg.State(), "on", sg.Destination)
// }
panic(fmt.Sprintf("FleetState: one or more ships in race's %q fleet %q are on different planets: %d <> %d", c.g.Race[ri].Name, c.g.Fleets[fi].Name, *onPlanet, planet))
if fs.Destination != sg.Destination {
panic(fmt.Sprintf("FleetState: one or more ships in race's %q fleet %q has different destination", c.g.Race[ri].Name, c.g.Fleets[fi].Name))
}
if (is == nil && sg.StateInSpace != nil) || (is != nil && sg.StateInSpace == nil) {
if planet, ok := sg.OnPlanet(); ok {
if onPlanet, ok := fs.OnPlanet(); ok && onPlanet != planet {
panic(fmt.Sprintf("FleetState: one or more ships in race's %q fleet %q are on different planets: %d <> %d", c.g.Race[ri].Name, c.g.Fleets[fi].Name, onPlanet, planet))
}
}
if (!fs.inSpace() && sg.StateInSpace != nil) || (fs.inSpace() && sg.StateInSpace == nil) {
panic(fmt.Sprintf("FleetState: one or more ships in race's %q fleet %q on_planet and in_space at the same time", c.g.Race[ri].Name, c.g.Fleets[fi].Name))
}
if is != nil && sg.StateInSpace != nil && !is.Equal(*sg.StateInSpace) {
if is, ok := fs.InSpace(); ok && sg.StateInSpace != nil && !is.Equal(*sg.StateInSpace) {
panic(fmt.Sprintf("FleetState: one or more ships in race's %q fleet %q has different is_space states", c.g.Race[ri].Name, c.g.Fleets[fi].Name))
}
}
if state == nil {
if fs.State == fleetStateNil {
panic(fmt.Sprintf("FleetState: race's %q fleet %q has no ships", c.g.Race[ri].Name, c.g.Fleets[fi].Name))
}
return *state, onPlanet, is
return *fs
}
// TODO: Hello! Wanna know fleet's speed? Good. Implement & test this func first.
@@ -109,8 +141,8 @@ func (c *Cache) JoinShipGroupToFleet(ri int, fleetName string, groupIndex, quant
return err
}
} else {
state, onPlanet, _ := c.FleetState(c.g.Fleets[fi].ID)
if state != game.StateInOrbit || *onPlanet != c.ShipGroup(sgi).Destination {
fleetState := c.FleetState(c.g.Fleets[fi].ID)
if onPlanet, ok := fleetState.OnPlanet(); (ok && onPlanet != c.ShipGroup(sgi).Destination) || fleetState.State != game.StateInOrbit {
return e.NewShipsNotOnSamePlanetError("fleet: %s", fleetName)
}
}
@@ -164,11 +196,12 @@ func (c *Cache) JoinFleets(ri int, fleetSourceName, fleetTargetName string) (err
if !ok {
return e.NewEntityNotExistsError("target fleet %s", fleetTargetName)
}
srcState, planet1, _ := c.FleetState(c.g.Fleets[fiSource].ID)
tgtState, planet2, _ := c.FleetState(c.g.Fleets[fiTarget].ID)
if srcState != game.StateInOrbit || srcState != tgtState || *planet1 != *planet2 {
stateSrc := c.FleetState(c.g.Fleets[fiSource].ID)
stateDst := c.FleetState(c.g.Fleets[fiTarget].ID)
if !stateSrc.OnSamePlanet(stateDst) {
return e.NewShipsNotOnSamePlanetError()
}
for sg := range c.listShipGroups(ri) {
if sg.FleetID != nil && *sg.FleetID == c.g.Fleets[fiSource].ID {
sg.FleetID = &c.g.Fleets[fiTarget].ID