refactor: game funcs moved to controller

This commit is contained in:
Ilia Denisov
2026-01-15 14:42:04 +02:00
parent fe8a8d4150
commit 16aba8435d
47 changed files with 1023 additions and 3093 deletions
+140 -22
View File
@@ -2,29 +2,160 @@ package controller
import (
"fmt"
"slices"
"strings"
"github.com/google/uuid"
e "github.com/iliadenisov/galaxy/internal/error"
"github.com/iliadenisov/galaxy/internal/model/game"
)
func (c *Controller) RenamePlanet(raceName string, planetNumber int, typeName string) error {
ri, err := c.Cache.raceIndex(raceName)
if err != nil {
return err
}
return c.Cache.RenamePlanet(ri, planetNumber, typeName)
}
func (c *Cache) RenamePlanet(ri int, number int, name string) error {
n, ok := validateTypeName(name)
if !ok {
return e.NewEntityTypeNameValidationError("%q", n)
}
if number < 0 {
return e.NewPlanetNumberError(number)
}
p, ok := c.Planet(uint(number))
if !ok {
return e.NewEntityNotExistsError("planet #%d", number)
}
if p.Owner != c.g.Race[ri].ID {
return e.NewEntityNotOwnedError("planet #%d", number)
}
c.g.Map.Planet[c.MustPlanetIndex(p.Number)].Name = n
return nil
}
func (c *Controller) PlanetProduction(raceName string, planetNumber int, prodType, subject string) error {
ri, err := c.Cache.raceIndex(raceName)
if err != nil {
return err
}
var prod game.ProductionType
switch game.ProductionType(strings.ToUpper(prodType)) {
case game.ProductionMaterial:
prod = game.ProductionMaterial
case game.ProductionCapital:
prod = game.ProductionCapital
case game.ResearchDrive:
prod = game.ResearchDrive
case game.ResearchWeapons:
prod = game.ResearchWeapons
case game.ResearchShields:
prod = game.ResearchShields
case game.ResearchCargo:
prod = game.ResearchCargo
case game.ResearchScience:
prod = game.ResearchScience
case game.ProductionShip:
prod = game.ProductionShip
default:
return e.NewProductionInvalidError(prodType)
}
return c.Cache.PlanetProduction(ri, planetNumber, prod, subject)
}
func (c *Cache) PlanetProduction(ri int, number int, prod game.ProductionType, subj string) error {
c.validateRaceIndex(ri)
if number < 0 {
return e.NewPlanetNumberError(number)
}
p, ok := c.Planet(uint(number))
if !ok {
return e.NewEntityNotExistsError("planet #%d", number)
}
if p.Owner != c.g.Race[ri].ID {
return e.NewEntityNotOwnedError("planet #%d", number)
}
i := c.MustPlanetIndex(p.Number)
var subjectID *uuid.UUID
if (prod == game.ResearchScience || prod == game.ProductionShip) && subj == "" {
return e.NewEntityTypeNameValidationError("%s=%q", prod, subj)
}
if prod == game.ResearchScience {
i := slices.IndexFunc(c.g.Race[ri].Sciences, func(s game.Science) bool { return s.Name == subj })
if i < 0 {
return e.NewEntityNotExistsError("science %q", subj)
}
subjectID = &c.g.Race[ri].Sciences[i].ID
}
if prod == game.ProductionShip {
st, _, ok := c.ShipClass(ri, subj)
if !ok {
return e.NewEntityNotExistsError("ship type %q", subj)
}
if p.Production.Type == game.ProductionShip &&
p.Production.SubjectID != nil &&
*p.Production.SubjectID == st.ID {
// Planet already produces this ship type, keeping progress intact
return nil
}
subjectID = &st.ID
var progress float64 = 0.
c.g.Map.Planet[i].Production.Progress = &progress
} else {
c.g.Map.Planet[i].Production.Progress = nil
}
if p.Production.Type == game.ProductionShip && prod != game.ProductionShip {
if p.Production.SubjectID == nil {
return e.NewGameStateError("planet #%d produces ship but SubjectID is empty", p.Number)
}
s := *p.Production.SubjectID
if p.Production.Progress == nil {
return e.NewGameStateError("planet #%d produces ship but Progress is empty", p.Number)
}
progress := *p.Production.Progress
st, ok := c.ShipType(ri, s)
if !ok {
return e.NewGameStateError("planet #%d produces ship but ShipType was not found for race %s", p.Number, c.g.Race[ri].Name)
}
mat, _ := st.ProductionCost()
extra := mat * progress
c.g.Map.Planet[i].Material += extra
}
c.g.Map.Planet[i].Production.Type = prod
c.g.Map.Planet[i].Production.SubjectID = subjectID
return nil
}
func (c *Cache) Planet(planetNumber uint) (*game.Planet, bool) {
if c.planetByPlanetNumber == nil {
c.planetByPlanetNumber = make(map[uint]*game.Planet)
if c.cachePlanetByPlanetNumber == nil {
c.cachePlanetByPlanetNumber = make(map[uint]*game.Planet)
for p := range c.g.Map.Planet {
c.planetByPlanetNumber[c.g.Map.Planet[p].Number] = &c.g.Map.Planet[p]
c.cachePlanetByPlanetNumber[c.g.Map.Planet[p].Number] = &c.g.Map.Planet[p]
}
}
if v, ok := c.planetByPlanetNumber[planetNumber]; ok {
if v, ok := c.cachePlanetByPlanetNumber[planetNumber]; ok {
return v, true
} else {
return nil, false
}
}
func (c *Cache) MustPlanet(planetNumber uint) *game.Planet {
if v, ok := c.Planet(planetNumber); ok {
func (c *Cache) MustPlanet(pn uint) *game.Planet {
if v, ok := c.Planet(pn); ok {
return v
} else {
panic(fmt.Sprintf("Planet: not found by number=%d", planetNumber))
panic(fmt.Sprintf("planet not found by number=%d", pn))
}
}
func (c *Cache) MustPlanetIndex(pn uint) int {
if idx := slices.IndexFunc(c.g.Map.Planet, func(p game.Planet) bool { return p.Number == pn }); idx < 0 {
panic(fmt.Sprintf("planet not found by number=%d", pn))
} else {
return idx
}
}
@@ -33,18 +164,14 @@ func (c *Cache) MustPlanet(planetNumber uint) *game.Planet {
// за вычетом затрат, расходуемых в течение хода на модернизацию кораблей
func (c *Cache) PlanetProductionCapacity(planetNumber uint) float64 {
p := c.MustPlanet(planetNumber)
// p, err := g.PlanetByNumber(planetNumber)
// if err != nil {
// panic(err)
// }
var busyResources float64
for sg := range c.g.ShipsInUpgrade(p.Number) {
for sg := range c.shipGroupsInUpgrade(p.Number) {
busyResources += sg.StateUpgrade.Cost()
}
return game.PlanetProduction(p.Industry, p.Population) - busyResources
}
// Internal fincs
// Internal funcs
func (c *Cache) putPopulation(pn uint, v float64) {
c.MustPlanet(pn).Population = v
@@ -57,12 +184,3 @@ func (c *Cache) putColonists(pn uint, v float64) {
func (c *Cache) putMaterial(pn uint, v float64) {
c.MustPlanet(pn).Material = v
}
func UnloadColonists(p game.Planet, v float64) game.Planet {
p.Population += v * 8
if p.Population > p.Size {
p.Colonists += (p.Population - p.Size) / 8
p.Population = p.Size
}
return p
}