package game import ( "slices" e "github.com/iliadenisov/galaxy/internal/error" "github.com/iliadenisov/galaxy/internal/util" ) func (g *Game) SendGroup(raceName string, groupIndex, planetNumber, quantity uint) error { ri, err := g.raceIndex(raceName) if err != nil { return err } return g.sendGroupInternal(ri, groupIndex, planetNumber, quantity) } func (g *Game) sendGroupInternal(ri int, groupIndex, planetNumber, quantity uint) error { 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 := g.ShipGroups[sgi].OnPlanet() if !ok { return e.NewShipsBusyError() } if g.ShipGroups[sgi].Number < quantity { return e.NewBeakGroupNumberNotEnoughError("%d<%d", g.ShipGroups[sgi].Number, quantity) } p1, ok := PlanetByNum(g, sourcePlanet) if !ok { return e.NewGameStateError("source planet #%d does not exists", g.ShipGroups[sgi].Destination) } p2, ok := PlanetByNum(g, planetNumber) if !ok { return e.NewEntityNotExistsError("destination planet #%d", planetNumber) } rangeToDestination := util.ShortDistance(g.Map.Width, g.Map.Height, p1.X, p1.Y, p2.X, p2.Y) if rangeToDestination > g.Race[ri].FlightDistance() { return e.NewSendUnreachableDestinationError("range=%.03f", rangeToDestination) } if quantity > 0 && quantity < g.ShipGroups[sgi].Number { nsgi, err := g.breakGroupSafe(ri, groupIndex, quantity) if err != nil { return err } sgi = nsgi } if sourcePlanet == planetNumber { g.ShipGroups[sgi] = UnsendShips(g.ShipGroups[sgi]) g.joinEqualGroupsInternal(ri) return nil } g.ShipGroups[sgi] = LaunchShips(g.ShipGroups[sgi], planetNumber) return nil } func LaunchShips(sg ShipGroup, destination uint) ShipGroup { sg.StateInSpace = &InSpace{ Origin: sg.Destination, } sg.Destination = destination return sg } func UnsendShips(sg ShipGroup) ShipGroup { sg.Destination = sg.StateInSpace.Origin sg.StateInSpace = nil return sg }