package controller_test

import (
	"slices"
	"testing"

	e "galaxy/error"

	"galaxy/game/internal/controller"
	"galaxy/game/internal/model/game"

	"github.com/stretchr/testify/assert"
)

func TestPlanetRouteSet(t *testing.T) {
	c, g := newCache()

	assert.NotContains(t, c.MustPlanet(0).Route, game.RouteMaterial)
	assert.NotContains(t, c.MustPlanet(0).Route, game.RouteCapital)
	assert.NotContains(t, c.MustPlanet(0).Route, game.RouteColonist)
	assert.NotContains(t, c.MustPlanet(0).Route, game.RouteEmpty)

	assert.NoError(t, g.PlanetRouteSet(Race_0.Name, "COL", 0, 2))
	assert.NotContains(t, c.MustPlanet(0).Route, game.RouteMaterial)
	assert.NotContains(t, c.MustPlanet(0).Route, game.RouteCapital)
	assert.Contains(t, c.MustPlanet(0).Route, game.RouteColonist)
	assert.NotContains(t, c.MustPlanet(0).Route, game.RouteEmpty)

	assert.NoError(t, g.PlanetRouteSet(Race_0.Name, "MAT", 0, 2))
	assert.Contains(t, c.MustPlanet(0).Route, game.RouteMaterial)
	assert.NotContains(t, c.MustPlanet(0).Route, game.RouteCapital)
	assert.Contains(t, c.MustPlanet(0).Route, game.RouteColonist)
	assert.NotContains(t, c.MustPlanet(0).Route, game.RouteEmpty)

	assert.NoError(t, g.PlanetRouteSet(Race_0.Name, "CAP", 0, 2))
	assert.Contains(t, c.MustPlanet(0).Route, game.RouteMaterial)
	assert.Contains(t, c.MustPlanet(0).Route, game.RouteCapital)
	assert.Contains(t, c.MustPlanet(0).Route, game.RouteColonist)
	assert.NotContains(t, c.MustPlanet(0).Route, game.RouteEmpty)

	assert.NoError(t, g.PlanetRouteSet(Race_0.Name, "EMP", 0, 2))
	assert.Contains(t, c.MustPlanet(0).Route, game.RouteMaterial)
	assert.Contains(t, c.MustPlanet(0).Route, game.RouteCapital)
	assert.Contains(t, c.MustPlanet(0).Route, game.RouteColonist)
	assert.Contains(t, c.MustPlanet(0).Route, game.RouteEmpty)

	assert.ErrorContains(t,
		g.PlanetRouteSet(UnknownRace, "COL", 0, 2),
		e.GenericErrorText(e.ErrInputUnknownRace))
	assert.ErrorContains(t,
		g.PlanetRouteSet(Race_Extinct.Name, "COL", 0, 2),
		e.GenericErrorText(e.ErrRaceExinct))
	assert.ErrorContains(t,
		g.PlanetRouteSet(Race_0.Name, "IND", 0, 2),
		e.GenericErrorText(e.ErrInputCargoTypeInvalid))
	assert.ErrorContains(t,
		g.PlanetRouteSet(Race_0.Name, "COL", 500, 2),
		e.GenericErrorText(e.ErrInputEntityNotExists))
	assert.ErrorContains(t,
		g.PlanetRouteSet(Race_0.Name, "COL", 1, 2),
		e.GenericErrorText(e.ErrInputEntityNotOwned))
	assert.ErrorContains(t,
		g.PlanetRouteSet(Race_0.Name, "COL", 0, 3),
		e.GenericErrorText(e.ErrSendUnreachableDestination))
}

func TestPlanetRouteRemove(t *testing.T) {
	c, g := newCache()

	assert.NoError(t, g.PlanetRouteSet(Race_0.Name, "COL", 0, 2))
	assert.NoError(t, g.PlanetRouteSet(Race_0.Name, "CAP", 0, 2))
	assert.NoError(t, g.PlanetRouteSet(Race_0.Name, "EMP", 2, 0))

	assert.Contains(t, c.MustPlanet(0).Route, game.RouteColonist)
	assert.Contains(t, c.MustPlanet(0).Route, game.RouteCapital)
	assert.Contains(t, c.MustPlanet(2).Route, game.RouteEmpty)

	assert.NoError(t, g.PlanetRouteRemove(Race_0.Name, "COL", 0))
	assert.NotContains(t, c.MustPlanet(0).Route, game.RouteColonist)
	assert.Contains(t, c.MustPlanet(0).Route, game.RouteCapital)

	assert.NoError(t, g.PlanetRouteRemove(Race_0.Name, "EMP", 2))
	assert.NotContains(t, c.MustPlanet(2).Route, game.RouteEmpty)

	assert.ErrorContains(t,
		g.PlanetRouteRemove(UnknownRace, "COL", 0),
		e.GenericErrorText(e.ErrInputUnknownRace))
	assert.ErrorContains(t,
		g.PlanetRouteRemove(Race_Extinct.Name, "COL", 0),
		e.GenericErrorText(e.ErrRaceExinct))
	assert.ErrorContains(t,
		g.PlanetRouteRemove(Race_0.Name, "IND", 0),
		e.GenericErrorText(e.ErrInputCargoTypeInvalid))
	assert.ErrorContains(t,
		g.PlanetRouteRemove(Race_0.Name, "COL", 500),
		e.GenericErrorText(e.ErrInputEntityNotExists))
	assert.ErrorContains(t,
		g.PlanetRouteRemove(Race_0.Name, "COL", 1),
		e.GenericErrorText(e.ErrInputEntityNotOwned))
}

func TestListRoutedSendGroupIds(t *testing.T) {
	c, g := newCache()

	// 1: idx = 0 / Ready to load
	assert.NoError(t, c.CreateShips(Race_0_idx, Race_0_Freighter, R0_Planet_0_num, 10))

	// 2: idx = 1 / Has no cargo bay
	assert.NoError(t, c.CreateShips(Race_0_idx, Race_0_Gunship, R0_Planet_0_num, 1))

	// 3: idx = 2 / In_Space
	assert.NoError(t, c.CreateShips(Race_0_idx, Race_0_Freighter, R0_Planet_0_num, 7))
	c.ShipGroup(2).StateInSpace = &InSpace

	// 4: idx = 3 / loaded with COL
	assert.NoError(t, c.CreateShips(Race_0_idx, Race_0_Freighter, R0_Planet_0_num, 11))
	c.ShipGroup(3).CargoType = game.CargoColonist.Ref()
	c.ShipGroup(3).Load = 1.234

	// Foreign group -> idx 1
	assert.NoError(t, c.CreateShips(Race_0_idx, Race_0_Freighter, R0_Planet_0_num, 10))
	assert.NoError(t, g.ShipGroupTransfer(Race_0.Name, Race_1.Name, c.ShipGroup(4).ID))

	// 5: idx = 4 / Part of the Fleet
	assert.NoError(t, c.CreateShips(Race_0_idx, Race_0_Freighter, R0_Planet_0_num, 10))
	assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, "Fleet", c.ShipGroup(5).ID))

	planet_0_groups := slices.Collect(c.ListRoutedSendGroupIds(0))
	assert.Len(t, planet_0_groups, 1)
	for _, i := range planet_0_groups {
		sg := c.ShipGroup(i)
		st := c.ShipGroupShipClass(i)
		assert.Equal(t, Race_0_ID, sg.OwnerID)
		assert.Greater(t, sg.CargoCapacity(st), 0.)
		assert.Equal(t, game.StateInOrbit, sg.State())
		assert.Equal(t, 0., sg.Load.F())
		assert.Nil(t, sg.FleetID)
	}
}

func TestEnrouteGroups_SplitGroup(t *testing.T) {
	c, g := newCache()

	assert.NoError(t, g.PlanetRouteSet(Race_0.Name, "COL", R0_Planet_0_num, R0_Planet_2_num))

	c.MustPlanet(R0_Planet_0_num).Colonists = 65

	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.SendRoutedGroups()

	assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 2)

	assert.Equal(t, game.StateInOrbit, c.ShipGroup(0).State())
	assert.Equal(t, uint(1), c.ShipGroup(0).Number)
	assert.Equal(t, 0., c.ShipGroup(0).Load.F())

	assert.Equal(t, game.StateLaunched, c.ShipGroup(1).State())
	assert.Equal(t, uint(4), c.ShipGroup(1).Number)
	assert.Equal(t, 65., c.ShipGroup(1).Load.F())
	assert.Equal(t, 0., c.MustPlanet(R0_Planet_0_num).Colonists.F())
}

func TestEnrouteGroups_GroupSorting(t *testing.T) {
	c, g := newCache()

	assert.NoError(t, g.PlanetRouteSet(Race_0.Name, "COL", R0_Planet_0_num, R0_Planet_2_num))

	c.MustPlanet(R0_Planet_0_num).Colonists = 100

	// 0: idx = 1
	assert.NoError(t, c.CreateShips(Race_0_idx, Race_0_Freighter, R0_Planet_0_num, 4)) // 21.0 per Ship
	assert.Equal(t, 84., c.ShipGroup(0).CargoCapacity(c.ShipGroupShipClass(0)))

	// 1: idx = 2
	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.SendRoutedGroups()

	assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 2)
	assert.Equal(t, game.StateInOrbit, c.ShipGroup(0).State())
	assert.Equal(t, game.StateLaunched, c.ShipGroup(1).State())

	assert.Equal(t, 100., c.ShipGroup(1).Load.F())
	assert.Equal(t, 0., c.MustPlanet(R0_Planet_0_num).Colonists.F())
}

func TestEnrouteGroups_LaunchOrder(t *testing.T) {
	c, g := newCache()

	assert.NoError(t, g.PlanetRouteSet(Race_0.Name, "COL", R0_Planet_0_num, R0_Planet_2_num))
	assert.NoError(t, g.PlanetRouteSet(Race_0.Name, "CAP", R0_Planet_0_num, R0_Planet_2_num))
	assert.NoError(t, g.PlanetRouteSet(Race_0.Name, "MAT", R0_Planet_0_num, R0_Planet_2_num))
	assert.NoError(t, g.PlanetRouteSet(Race_0.Name, "EMP", R0_Planet_0_num, R1_Planet_1_num))

	c.MustPlanet(R0_Planet_0_num).Colonists = 150
	c.MustPlanet(R0_Planet_0_num).Capital = 100
	c.MustPlanet(R0_Planet_0_num).Material = 20

	// 0: idx = 1 (105 COL) ->
	// 3: idx = 4 ( 45 COL)
	assert.NoError(t, c.CreateShips(Race_0_idx, Race_0_Freighter, R0_Planet_0_num, 5))
	assert.Equal(t, 105., c.ShipGroup(0).CargoCapacity(c.ShipGroupShipClass(0)))

	// 1: idx = 2 (In_Orbit) ->
	// 4: idx = 5 (20 MAT)
	assert.NoError(t, c.CreateShips(Race_0_idx, Race_0_Freighter, R0_Planet_0_num, 5))
	assert.Equal(t, 105., c.ShipGroup(1).CargoCapacity(c.ShipGroupShipClass(1)))

	// 2: idx = 3 (100 CAP)
	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.SendRoutedGroups()

	assert.Len(t, slices.Collect(c.RaceShipGroups(Race_0_idx)), 5)

	// full load of COL
	sgi := 0
	assert.Equal(t, game.StateLaunched, c.ShipGroup(sgi).State())
	assert.Equal(t, R0_Planet_2_num, c.ShipGroup(sgi).Destination)
	assert.Equal(t, 105., c.ShipGroup(sgi).Load.F())
	assert.NotNil(t, c.ShipGroup(sgi).CargoType)
	assert.Equal(t, game.CargoColonist, *c.ShipGroup(sgi).CargoType)
	assert.Equal(t, uint(5), c.ShipGroup(sgi).Number)

	// rest of COL
	sgi = 3
	assert.Equal(t, game.StateLaunched, c.ShipGroup(sgi).State())
	assert.Equal(t, R0_Planet_2_num, c.ShipGroup(sgi).Destination)
	assert.Equal(t, 45., c.ShipGroup(sgi).Load.F())
	assert.NotNil(t, c.ShipGroup(sgi).CargoType)
	assert.Equal(t, game.CargoColonist, *c.ShipGroup(sgi).CargoType)
	assert.Equal(t, uint(3), c.ShipGroup(sgi).Number)

	// full load of CAP
	sgi = 2
	assert.Equal(t, game.StateLaunched, c.ShipGroup(sgi).State())
	assert.Equal(t, R0_Planet_2_num, c.ShipGroup(sgi).Destination)
	assert.Equal(t, 100., c.ShipGroup(sgi).Load.F())
	assert.NotNil(t, c.ShipGroup(sgi).CargoType)
	assert.Equal(t, game.CargoCapital, *c.ShipGroup(sgi).CargoType)
	assert.Equal(t, uint(5), c.ShipGroup(sgi).Number)

	// partial load of MAT
	sgi = 4
	assert.Equal(t, game.StateLaunched, c.ShipGroup(sgi).State())
	assert.Equal(t, R0_Planet_2_num, c.ShipGroup(sgi).Destination)
	assert.Equal(t, 20., c.ShipGroup(sgi).Load.F())
	assert.NotNil(t, c.ShipGroup(sgi).CargoType)
	assert.Equal(t, game.CargoMaterial, *c.ShipGroup(sgi).CargoType)
	assert.Equal(t, uint(1), c.ShipGroup(sgi).Number)

	// empty / on_planet
	sgi = 1
	assert.Equal(t, game.StateLaunched, c.ShipGroup(sgi).State())
	assert.Equal(t, R1_Planet_1_num, c.ShipGroup(sgi).Destination)
	assert.Equal(t, 0., c.ShipGroup(sgi).Load.F())
	assert.Nil(t, c.ShipGroup(sgi).CargoType)
	assert.Equal(t, uint(1), c.ShipGroup(sgi).Number)
}

func TestListRoutedUnloadShipGroupIds(t *testing.T) {
	c, g := newCache()

	// 1: idx = 0 / Empty cargo
	assert.NoError(t, c.CreateShips(Race_0_idx, Race_0_Freighter, R0_Planet_0_num, 10))
	c.ShipGroup(0).CargoType = game.CargoColonist.Ref()
	c.ShipGroup(0).Load = 0.

	// 2: idx = 1 / Has no cargo bay
	assert.NoError(t, c.CreateShips(Race_0_idx, Race_0_Gunship, R0_Planet_0_num, 1))

	// 3: idx = 2 / In_Space
	assert.NoError(t, c.CreateShips(Race_0_idx, Race_0_Freighter, R0_Planet_0_num, 7))
	c.ShipGroup(2).StateInSpace = &InSpace

	// 4: idx = 3 / loaded with COL
	assert.NoError(t, c.CreateShips(Race_0_idx, Race_0_Freighter, R0_Planet_0_num, 11))
	c.ShipGroup(3).CargoType = game.CargoColonist.Ref()
	c.ShipGroup(3).Load = 1.234

	// 5: idx = 4 / Part of the Fleet
	assert.NoError(t, c.CreateShips(Race_0_idx, Race_0_Freighter, R0_Planet_0_num, 10))
	assert.NoError(t, g.ShipGroupJoinFleet(Race_0.Name, "Fleet", c.ShipGroup(4).ID))

	assert.NoError(t, g.PlanetRouteSet(Race_0.Name, "COL", R0_Planet_0_num, R0_Planet_2_num))
	for _, rt := range game.RouteTypeSet {
		groups := slices.Collect(c.ListRoutedUnloadShipGroupIds(R0_Planet_2_num, rt))
		assert.Len(t, groups, 0, "route: %v", rt)
		groups = slices.Collect(c.ListRoutedUnloadShipGroupIds(R0_Planet_0_num, rt))
		assert.Len(t, groups, 0, "route: %v", rt)
	}

	// double route from different planets - must not double group ids
	assert.NoError(t, g.PlanetRouteSet(Race_0.Name, "COL", R0_Planet_2_num, R0_Planet_0_num))
	assert.NoError(t, g.PlanetRouteSet(Race_1.Name, "COL", R1_Planet_1_num, R0_Planet_0_num))

	// 6: idx = 5 / loaded with CAP
	assert.NoError(t, c.CreateShips(Race_0_idx, Race_0_Freighter, R0_Planet_0_num, 11))
	c.ShipGroup(5).CargoType = game.CargoCapital.Ref()
	c.ShipGroup(5).Load = 1.234

	groups := slices.Collect(c.ListRoutedUnloadShipGroupIds(R0_Planet_0_num, game.RouteColonist))
	assert.Len(t, groups, 1)
	for _, sgi := range groups {
		assert.Greater(t, c.ShipGroup(sgi).Load, 0.)
		assert.Equal(t, game.StateInOrbit, c.ShipGroup(sgi).State())
		assert.Equal(t, R0_Planet_0_num, c.ShipGroup(sgi).Destination)
	}

	groups = slices.Collect(c.ListRoutedUnloadShipGroupIds(R0_Planet_0_num, game.RouteMaterial))
	assert.Len(t, groups, 0)

	groups = slices.Collect(c.ListRoutedUnloadShipGroupIds(R0_Planet_0_num, game.RouteCapital))
	assert.Len(t, groups, 0)
}

func TestMaxOrRandomLoadId(t *testing.T) {
	IDtoLoad := make(map[int]float64)

	pop := func(ri int) float64 {
		switch ri {
		case 1:
			return 0
		case 3:
			return 0
		case 5:
			return 9.99
		case 7:
			return 10
		case 11:
			return 10
		}
		return 0
	}

	assert.Panics(t, func() { controller.MaxOrRandomLoadId(IDtoLoad, pop) })
	IDtoLoad[1] = 100.
	assert.Panics(t, func() { controller.MaxOrRandomLoadId(IDtoLoad, pop) })

	IDtoLoad[5] = 100.001
	assert.Equal(t, 5, controller.MaxOrRandomLoadId(IDtoLoad, pop))

	IDtoLoad[3] = 100.
	assert.NotContains(t, []int{1, 3}, controller.MaxOrRandomLoadId(IDtoLoad, pop))

	IDtoLoad[7] = 100.001
	assert.Equal(t, 7, controller.MaxOrRandomLoadId(IDtoLoad, pop))

	IDtoLoad[11] = 100.001
	rndCount := make(map[int]int)
	for range 100 {
		id := controller.MaxOrRandomLoadId(IDtoLoad, pop)
		assert.NotContains(t, []int{1, 3, 5}, id)
		assert.Contains(t, []int{7, 11}, id)
		rndCount[id]++
	}
	assert.Greater(t, rndCount[7], 10)
	assert.Greater(t, rndCount[11], 10)
}

func TestSelectColUnloadGroup(t *testing.T) {
	c, g := newCache()

	assert.NoError(t, g.PlanetRouteSet(Race_0.Name, "COL", R0_Planet_2_num, R0_Planet_0_num))
	assert.NoError(t, g.PlanetRouteSet(Race_1.Name, "COL", R1_Planet_1_num, R0_Planet_0_num))

	// 1: idx = 0 / Loaded COL
	assert.NoError(t, c.CreateShips(Race_0_idx, Race_0_Freighter, R0_Planet_0_num, 10))
	c.ShipGroup(0).CargoType = game.CargoColonist.Ref()
	c.ShipGroup(0).Load = 7.

	// 2: idx = 1 / Loaded COL
	assert.NoError(t, c.CreateShips(Race_0_idx, Race_0_Freighter, R0_Planet_0_num, 5))
	c.ShipGroup(1).CargoType = game.CargoColonist.Ref()
	c.ShipGroup(1).Load = 5.

	groups := slices.Collect(c.ListRoutedUnloadShipGroupIds(R0_Planet_0_num, game.RouteColonist))
	assert.Len(t, groups, 2)
	unloadGroups := slices.Collect(c.SelectColUnloadGroup(groups))
	assert.ElementsMatch(t, groups, unloadGroups)

	// 3: idx = 2 / Loaded COL - another race, winner
	assert.NoError(t, c.CreateShips(Race_1_idx, Race_1_Freighter, R1_Planet_1_num, 10))
	c.ShipGroup(2).Destination = R0_Planet_0_num
	c.ShipGroup(2).CargoType = game.CargoColonist.Ref()
	c.ShipGroup(2).Load = 12.1

	groups = slices.Collect(c.ListRoutedUnloadShipGroupIds(R0_Planet_0_num, game.RouteColonist))
	assert.Len(t, groups, 3)
	unloadGroups = slices.Collect(c.SelectColUnloadGroup(groups))
	assert.Equal(t, 2, unloadGroups[0])
}

func TestTurnUnloadEnroutedGroups(t *testing.T) {
	c, g := newCache()

	assert.NoError(t, g.PlanetRouteSet(Race_0.Name, "MAT", R0_Planet_2_num, R0_Planet_0_num))
	assert.NoError(t, g.PlanetRouteSet(Race_0.Name, "CAP", R0_Planet_2_num, R0_Planet_0_num))

	assert.NoError(t, g.PlanetRouteSet(Race_1.Name, "COL", R1_Planet_1_num, R0_Planet_0_num))
	assert.NoError(t, g.PlanetRouteSet(Race_1.Name, "COL", R1_Planet_1_num, Uninhabited_Planet_4_num))

	// 1: idx = 0 / Loaded MAT
	assert.NoError(t, c.CreateShips(Race_0_idx, Race_0_Freighter, R0_Planet_0_num, 10))
	c.ShipGroup(0).CargoType = game.CargoMaterial.Ref()
	c.ShipGroup(0).Load = 222.

	// 2: idx = 1 / Loaded CAP
	assert.NoError(t, c.CreateShips(Race_0_idx, Race_0_Freighter, R0_Planet_0_num, 10))
	c.ShipGroup(1).CargoType = game.CargoCapital.Ref()
	c.ShipGroup(1).Load = 11.

	// 3: idx = 2 / Loaded COL - on empty planet
	assert.NoError(t, c.CreateShips(Race_1_idx, Race_1_Freighter, R1_Planet_1_num, 10))
	c.ShipGroup(2).Destination = Uninhabited_Planet_4_num
	c.ShipGroup(2).CargoType = game.CargoColonist.Ref()
	c.ShipGroup(2).Load = 12.1

	// 4: idx = 3 / Loaded COL - on inhabited planet
	assert.NoError(t, c.CreateShips(Race_1_idx, Race_1_Freighter, R1_Planet_1_num, 10))
	c.ShipGroup(3).Destination = R0_Planet_0_num
	c.ShipGroup(3).CargoType = game.CargoColonist.Ref()
	c.ShipGroup(3).Load = 17.3

	c.TurnUnloadEnroutedGroups()

	assert.Equal(t, 0., c.ShipGroup(0).Load.F())
	assert.Equal(t, 222., c.MustPlanet(R0_Planet_0_num).Material.F())
	assert.Equal(t, 0., c.ShipGroup(1).Load.F())
	assert.Equal(t, 11., c.MustPlanet(R0_Planet_0_num).Capital.F())
	assert.Equal(t, 0., c.ShipGroup(2).Load.F())
	assert.Equal(t, 96.8, c.MustPlanet(Uninhabited_Planet_4_num).Population.F())
	assert.True(t, c.MustPlanet(Uninhabited_Planet_4_num).OwnedBy(Race_1_ID))
	assert.Equal(t, game.ProductionCapital, c.MustPlanet(Uninhabited_Planet_4_num).Production.Type)
	assert.Equal(t, 17.3, c.ShipGroup(3).Load.F())
}

func TestRemoveUnreachableRoutes(t *testing.T) {
	c, g := newCache()

	assert.NoError(t, g.PlanetRouteSet(Race_0.Name, "MAT", R0_Planet_2_num, R0_Planet_0_num))
	assert.NoError(t, g.PlanetRouteSet(Race_0.Name, "CAP", R0_Planet_2_num, R0_Planet_0_num))

	assert.NoError(t, g.PlanetRouteSet(Race_1.Name, "COL", R1_Planet_1_num, R0_Planet_0_num))
	assert.NoError(t, g.PlanetRouteSet(Race_1.Name, "CAP", R1_Planet_1_num, Uninhabited_Planet_4_num))

	assert.Error(t, g.PlanetRouteSet(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)
}
