feat: produce on planets, unload on routes
This commit is contained in:
@@ -3,9 +3,12 @@ package controller
|
||||
import (
|
||||
"cmp"
|
||||
"iter"
|
||||
"maps"
|
||||
"math"
|
||||
"math/rand/v2"
|
||||
"slices"
|
||||
|
||||
"github.com/google/uuid"
|
||||
e "github.com/iliadenisov/galaxy/internal/error"
|
||||
"github.com/iliadenisov/galaxy/internal/model/game"
|
||||
"github.com/iliadenisov/galaxy/internal/util"
|
||||
@@ -88,7 +91,7 @@ func (c *Cache) RemovePlanetRoute(rt game.RouteType, origin uint) {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: NOT IN THIS FUNC: remove routes if planet became uninhabited
|
||||
// TODO: NOT IN THIS FUNC: remove routes if planet became uninhabited (bombing, quit game, etc)
|
||||
func (c *Cache) EnrouteGroups() {
|
||||
for pi := range c.g.Map.Planet {
|
||||
if len(c.g.Map.Planet[pi].Route) == 0 {
|
||||
@@ -188,3 +191,81 @@ func (c *Cache) listRouteEligibleGroupIds(pn uint) iter.Seq[int] {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Невозможно лишь выгрузить колонистов на чужой планете.
|
||||
func (c *Cache) TurnUnloadEnroutedGroups() {
|
||||
for pi := range c.g.Map.Planet {
|
||||
p := &c.g.Map.Planet[pi]
|
||||
colGroups := c.listUnloadEligibleShipGroupIds(p.Number, game.RouteColonist)
|
||||
if p.Owner == uuid.Nil {
|
||||
c.selectColUnloadGroup(colGroups)
|
||||
} else {
|
||||
for sgi := range colGroups {
|
||||
sg := c.ShipGroup(sgi)
|
||||
if sg.OwnerID != p.Owner {
|
||||
continue
|
||||
}
|
||||
c.unloadCargoUnsafe(sgi, sg.Load)
|
||||
}
|
||||
}
|
||||
for _, rt := range []game.RouteType{game.RouteMaterial, game.RouteCapital} {
|
||||
for sgi := range c.listUnloadEligibleShipGroupIds(p.Number, rt) {
|
||||
c.unloadCargoUnsafe(sgi, c.ShipGroup(sgi).Load)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Cache) selectColUnloadGroup(seq iter.Seq[int]) {
|
||||
groupByRace := make(map[int][]int)
|
||||
loadByRace := make(map[int]float64)
|
||||
for i := range seq {
|
||||
sg := c.ShipGroup(i)
|
||||
ri := c.RaceIndex(sg.OwnerID)
|
||||
groupByRace[ri] = append(groupByRace[ri], i)
|
||||
loadByRace[ri] += sg.Load
|
||||
}
|
||||
if len(loadByRace) < 2 {
|
||||
for _, gr := range groupByRace {
|
||||
for _, sgi := range gr {
|
||||
c.unloadCargoUnsafe(sgi, c.ShipGroup(sgi).Load)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// select winner to unload
|
||||
|
||||
raceIdx := slices.Collect(maps.Keys(loadByRace))
|
||||
slices.SortFunc(raceIdx, func(ri1, ri2 int) int { return cmp.Compare(loadByRace[ri2], loadByRace[ri1]) })
|
||||
if loadByRace[raceIdx[0]] == loadByRace[raceIdx[1]] {
|
||||
// no single winner with highest load
|
||||
raceIdx = slices.DeleteFunc(raceIdx, func(v int) bool { return loadByRace[v] < loadByRace[raceIdx[0]] })
|
||||
rand.Shuffle(len(raceIdx), func(i, j int) { raceIdx[i], raceIdx[j] = raceIdx[j], raceIdx[i] })
|
||||
// now raceIdx[0] has a random race index
|
||||
}
|
||||
for _, sgi := range groupByRace[raceIdx[0]] {
|
||||
c.unloadCargoUnsafe(sgi, c.ShipGroup(sgi).Load)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Cache) listUnloadEligibleShipGroupIds(pn uint, routeType game.RouteType) iter.Seq[int] {
|
||||
return func(yield func(int) bool) {
|
||||
for i := range c.g.Map.Planet {
|
||||
for rt, dest := range c.g.Map.Planet[i].Route {
|
||||
if dest != pn || rt != routeType {
|
||||
continue
|
||||
}
|
||||
for i := range c.ShipGroupsIndex() {
|
||||
sg := c.ShipGroup(i)
|
||||
if sg.FleetID != nil || sg.State() != game.StateInOrbit || sg.CargoType == nil {
|
||||
continue
|
||||
}
|
||||
if !yield(i) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user