package controller import ( e "github.com/iliadenisov/galaxy/internal/error" "github.com/iliadenisov/galaxy/internal/model/game" "github.com/iliadenisov/galaxy/internal/util" ) func (c *Cache) SendGroup(ri int, groupIndex, planetNumber, quantity uint) error { c.validateRaceIndex(ri) sgi, ok := c.raceShipGroupIndex(ri, groupIndex) if !ok { return e.NewEntityNotExistsError("group #%d", groupIndex) } st := c.ShipGroupShipClass(sgi) if st.DriveBlockMass() == 0 { return e.NewSendShipHasNoDrivesError() } sourcePlanet, ok := c.ShipGroup(sgi).AtPlanet() if !ok { 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) } p2, ok := c.Planet(planetNumber) if !ok { return e.NewEntityNotExistsError("destination planet #%d", planetNumber) } rangeToDestination := util.ShortDistance(c.g.Map.Width, c.g.Map.Height, p1.X.F(), p1.Y.F(), p2.X.F(), p2.Y.F()) if rangeToDestination > c.g.Race[ri].FlightDistance() { return e.NewSendUnreachableDestinationError("range=%.03f", rangeToDestination) } if quantity > 0 && quantity < c.ShipGroup(sgi).Number { nsgi, err := c.breakGroupSafe(ri, groupIndex, quantity) if err != nil { return err } sgi = nsgi } if p1.Number == p2.Number { c.UnsendShips(c.ShipGroup(sgi)) c.JoinEqualGroups(ri) return nil } c.LaunchShips(c.ShipGroup(sgi), planetNumber) return nil } func (c *Cache) LaunchShips(sg *game.ShipGroup, destination uint) *game.ShipGroup { for i := range c.ShipGroupsIndex() { if c.ShipGroup(i).OwnerID == sg.OwnerID && c.ShipGroup(i).Index == sg.Index { state := c.ShipGroup(i).State() var p *game.Planet switch state { case game.StateInOrbit: p = c.MustPlanet(sg.Destination) case game.StateLaunched: p = c.MustPlanet(sg.StateInSpace.Origin) default: panic("state invalid") } c.g.ShipGroups[i] = LaunchShips(*sg, destination, p.X.F(), p.Y.F()) return &c.g.ShipGroups[i] } } panic("ship group not found") } func (c *Cache) UnsendShips(sg *game.ShipGroup) *game.ShipGroup { for i := range c.ShipGroupsIndex() { if c.ShipGroup(i).OwnerID == sg.OwnerID && c.ShipGroup(i).Index == sg.Index { state := c.ShipGroup(i).State() if state != game.StateLaunched { panic("state invalid") } c.g.ShipGroups[i] = UnsendShips(*sg) return &c.g.ShipGroups[i] } } panic("ship group not found") } func LaunchShips(sg game.ShipGroup, destination uint, originX, originY float64) game.ShipGroup { sg.StateInSpace = &game.InSpace{ Origin: sg.Destination, X: game.F(originX), Y: game.F(originY), } sg.Destination = destination return sg } func UnsendShips(sg game.ShipGroup) game.ShipGroup { sg.Destination = sg.StateInSpace.Origin sg.StateInSpace = nil return sg }