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 *Controller) SendGroup(raceName string, groupIndex, planetNumber, quantity uint) error { ri, err := c.Cache.raceIndex(raceName) if err != nil { return err } return c.Cache.SendGroup(ri, groupIndex, planetNumber, quantity) } 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) // sgi := -1 // for i, sg := range g.listIndexShipGroups(ri) { // if sgi < 0 && sg.Index == groupIndex { // sgi = i // } // } // if sgi < 0 { // return e.NewEntityNotExistsError("group #%d", groupIndex) // } // var sti int // if sti = slices.IndexFunc(g.Race[ri].ShipTypes, func(st ShipType) bool { return st.ID == g.ShipGroups[sgi].TypeID }); sti < 0 { // // hard to test, need manual game data invalidation // return e.NewGameStateError("not found: ShipType ID=%v", g.ShipGroups[sgi].TypeID) // } // st := g.Race[ri].ShipTypes[sti] if st.DriveBlockMass() == 0 { return e.NewSendShipHasNoDrivesError() } sourcePlanet, ok := c.ShipGroup(sgi).OnPlanet() if !ok { return e.NewShipsBusyError() } if c.ShipGroup(sgi).Number < quantity { return e.NewBeakGroupNumberNotEnoughError("%d<%d", c.ShipGroup(sgi).Number, quantity) } p1 := c.MustPlanet(sourcePlanet) // p1, ok := PlanetByNum(g, sourcePlanet) // if !ok { // return e.NewGameStateError("source planet #%d does not exists", sourcePlanet) // } p2 := c.MustPlanet(planetNumber) // p2, ok := PlanetByNum(g, planetNumber) // if !ok { // return e.NewEntityNotExistsError("destination planet #%d", planetNumber) // } rangeToDestination := util.ShortDistance(c.g.Map.Width, c.g.Map.Height, p1.X, p1.Y, p2.X, p2.Y) 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 sourcePlanet == planetNumber { 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.g.ShipGroups[i].State() if state != game.StateInOrbit && state != game.StateLaunched { panic("state invalid") } c.g.ShipGroups[i] = LaunchShips(sg, destination) 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 { c.g.ShipGroups[i] = UnsendShips(sg) return &c.g.ShipGroups[i] } } panic("ship group not found") } func LaunchShips(sg game.ShipGroup, destination uint) game.ShipGroup { sg.StateInSpace = &game.InSpace{ Origin: sg.Destination, } sg.Destination = destination return sg } func UnsendShips(sg game.ShipGroup) game.ShipGroup { sg.Destination = sg.StateInSpace.Origin sg.StateInSpace = nil return sg }