From abf72c16b46368e1f62f2a610558be824b2b0215 Mon Sep 17 00:00:00 2001 From: Ilia Denisov Date: Fri, 23 Jan 2026 00:43:21 +0200 Subject: [PATCH] feat: remove unreachable routes --- internal/controller/generate_turn.go | 7 ++++++- internal/controller/route.go | 21 ++++++++++++++++++++- internal/controller/route_test.go | 27 ++++++++++++++++++++++++--- 3 files changed, 50 insertions(+), 5 deletions(-) diff --git a/internal/controller/generate_turn.go b/internal/controller/generate_turn.go index 907c79f..7430ded 100644 --- a/internal/controller/generate_turn.go +++ b/internal/controller/generate_turn.go @@ -16,7 +16,7 @@ func MakeTurn(c *Controller, r Repo, g *game.Game) error { battles := ProduceBattles(c.Cache) // 03. Товары загружаются на корабли, находящиеся в начале грузовых маршрутов, и корабли входят в гиперпространство (но ещё не полетели) - c.Cache.EnrouteGroups() + c.Cache.SendRoutedGroups() // 04. Корабли пролетают сквозь гиперпространство. c.Cache.MoveShipGroups() @@ -37,8 +37,13 @@ func MakeTurn(c *Controller, r Repo, g *game.Game) error { c.Cache.TurnPlanetProductions() // 12. Товары выгружаются в конце грузовых маршрутов. + // 13. Выгруженные колонисты увеличивают население планеты (если население планеты ниже её размера). + // 14. Накопленная и выгруженная промышленность увеличивает производственный уровень планеты (если производственный уровень планеты ниже уровня населения). c.Cache.TurnUnloadEnroutedGroups() + // 15. Происходит отмена маршрутов, выходящих за зону полета кораблей. + c.Cache.RemoveUnreachableRoutes() + /*** Last steps ***/ // Store battles diff --git a/internal/controller/route.go b/internal/controller/route.go index 9468080..898d69b 100644 --- a/internal/controller/route.go +++ b/internal/controller/route.go @@ -92,7 +92,7 @@ func (c *Cache) RemovePlanetRoute(rt game.RouteType, origin uint) { } // TODO: NOT IN THIS FUNC: remove routes if planet became uninhabited (bombing, quit game, etc) -func (c *Cache) EnrouteGroups() { +func (c *Cache) SendRoutedGroups() { for pi := range c.g.Map.Planet { if len(c.g.Map.Planet[pi].Route) == 0 { continue @@ -200,6 +200,25 @@ func (c *Cache) TurnUnloadEnroutedGroups() { for _, rt := range []game.RouteType{game.RouteMaterial, game.RouteCapital} { c.doUnload(c.listRoutedUnloadShipGroupIds(p.Number, rt)) } + p.UnpackColonists() + p.UnpackCapital() + } +} + +func (c *Cache) RemoveUnreachableRoutes() { + for i := range c.g.Map.Planet { + p1 := &c.g.Map.Planet[i] + if p1.Owner == uuid.Nil { + continue + } + ri := c.RaceIndex(p1.Owner) + for rt, destination := range p1.Route { + p2 := c.MustPlanet(destination) + 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() { + delete(p1.Route, rt) + } + } } } diff --git a/internal/controller/route_test.go b/internal/controller/route_test.go index e1ff61b..cf35cb3 100644 --- a/internal/controller/route_test.go +++ b/internal/controller/route_test.go @@ -144,7 +144,7 @@ func TestEnrouteGroups_SplitGroup(t *testing.T) { assert.NoError(t, c.CreateShips(Race_0_idx, Race_0_Freighter, R0_Planet_0_num, 5)) // 21.0 per Ship assert.Equal(t, 105., c.ShipGroup(0).CargoCapacity(c.ShipGroupShipClass(0))) - c.EnrouteGroups() + c.SendRoutedGroups() assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 2) assert.Equal(t, game.StateInOrbit, c.ShipGroup(0).State()) @@ -171,7 +171,7 @@ func TestEnrouteGroups_GroupSorting(t *testing.T) { assert.NoError(t, c.CreateShips(Race_0_idx, Race_0_Freighter, R0_Planet_0_num, 5)) // 21.0 per Ship assert.Equal(t, 105., c.ShipGroup(1).CargoCapacity(c.ShipGroupShipClass(1))) - c.EnrouteGroups() + c.SendRoutedGroups() assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 2) assert.Equal(t, game.StateInOrbit, c.ShipGroup(0).State()) @@ -207,7 +207,7 @@ func TestEnrouteGroups_LaunchOrder(t *testing.T) { assert.NoError(t, c.CreateShips(Race_0_idx, Race_0_Freighter, R0_Planet_0_num, 5)) assert.Equal(t, 105., c.ShipGroup(2).CargoCapacity(c.ShipGroupShipClass(2))) - c.EnrouteGroups() + c.SendRoutedGroups() assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 5) @@ -416,3 +416,24 @@ func TestTurnUnloadEnroutedGroups(t *testing.T) { assert.Equal(t, game.ProductionCapital, c.MustPlanet(Uninhabited_Planet_4_num).Production.Type) assert.Equal(t, 17.3, c.ShipGroup(3).Load) } + +func TestRemoveUnreachableRoutes(t *testing.T) { + c, g := newCache() + + assert.NoError(t, g.SetRoute(Race_0.Name, "MAT", R0_Planet_2_num, R0_Planet_0_num)) + assert.NoError(t, g.SetRoute(Race_0.Name, "CAP", R0_Planet_2_num, R0_Planet_0_num)) + + assert.NoError(t, g.SetRoute(Race_1.Name, "COL", R1_Planet_1_num, R0_Planet_0_num)) + assert.NoError(t, g.SetRoute(Race_1.Name, "CAP", R1_Planet_1_num, Uninhabited_Planet_4_num)) + + assert.Error(t, g.SetRoute(Race_0.Name, "COL", R0_Planet_2_num, Uninhabited_Planet_3_num)) + c.MustPlanet(R0_Planet_2_num).Route[game.RouteColonist] = Uninhabited_Planet_3_num + + c.RemoveUnreachableRoutes() + + assert.NotContains(t, c.MustPlanet(R0_Planet_2_num).Route, game.RouteColonist) + assert.Contains(t, c.MustPlanet(R0_Planet_2_num).Route, game.RouteMaterial) + assert.Contains(t, c.MustPlanet(R0_Planet_2_num).Route, game.RouteCapital) + assert.Contains(t, c.MustPlanet(R1_Planet_1_num).Route, game.RouteColonist) + assert.Contains(t, c.MustPlanet(R1_Planet_1_num).Route, game.RouteCapital) +}