Files
galaxy-game/internal/model/game/planet.go
T
2026-01-04 19:22:06 +02:00

131 lines
3.7 KiB
Go

package game
import (
"math"
"slices"
"github.com/google/uuid"
e "github.com/iliadenisov/galaxy/internal/error"
)
type UnidentifiedPlanet struct {
X float64 `json:"x"`
Y float64 `json:"y"`
Number uint `json:"number"`
}
type UninhabitedPlanet struct {
UnidentifiedPlanet
Size float64 `json:"size"`
Name string `json:"name"`
Resources float64 `json:"resources"` // R - Ресурсы
Capital float64 `json:"capital"` // CAP $ - Запасы промышленности
Material float64 `json:"material"` // MAT M - Запасы ресурсов / сырья
}
type PlanetReport struct {
UninhabitedPlanet
Industry float64 `json:"industry"` // I - Промышленность
Population float64 `json:"population"` // P - Население
Colonists float64 `json:"colonists"` // COL C - Количество колонистов
Production Production `json:"production"` // TODO: internal/report format
// Параметр "L" - Свободный производственный потенциал
}
type Planet struct {
Owner uuid.UUID `json:"owner"` // FIXME: nil value when no owner
PlanetReport
}
type PlanetReportForeign struct {
RaceName string
PlanetReport
}
// TODO: delete func
func (p Planet) ProductionCapacity() float64 {
return p.Industry*0.75 + p.Population*0.25
}
// Свободный производственный потенциал (L)
// промышленность * 0.75 + население * 0.25
// за вычетом затрат, расходуемых в течение хода на модернизацию кораблей
func PlanetProductionCapacity(g *Game, planetNumber uint) float64 {
p, err := g.PlanetByNumber(planetNumber)
if err != nil {
panic(err)
}
var busyResources float64
for sg := range g.ShipsInUpgrade(p.Number) {
busyResources += sg.StateUpgrade.Cost()
}
return PlanetProduction(p.Industry, p.Population) - busyResources
}
func PlanetProduction(industry, population float64) float64 {
return industry*0.75 + population*0.25
}
// Производство промышленности
// TODO: test on real values
func (p *Planet) IncreaseIndustry() {
prod := p.ProductionCapacity() / 5
industryIncrement := math.Min(prod, p.Material)
p.Industry += industryIncrement
if p.Industry > p.Population {
p.Industry = p.Population
p.Capital += p.Population - p.Industry
}
}
// Производство материалов
// TODO: test on real values
func (p *Planet) IncreaseMaterial() {
p.Material += p.ProductionCapacity() * p.Industry
}
// Автоматическое увеличение населения на каждом ходу
func (p *Planet) IncreasePopulation() {
p.Population *= 1.08
if p.Population > p.Size {
p.Colonists += (p.Population - p.Size) / 8
p.Population = p.Size
}
}
func UnloadColonists(p Planet, v float64) Planet {
p.Population += v * 8
if p.Population > p.Size {
p.Colonists += (p.Population - p.Size) / 8
p.Population = p.Size
}
return p
}
func (g Game) RenamePlanet(raceName string, planetNumber int, typeName string) error {
ri, err := g.raceIndex(raceName)
if err != nil {
return err
}
return g.renamePlanetInternal(ri, planetNumber, typeName)
}
func (g Game) renamePlanetInternal(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)
}
pl := slices.IndexFunc(g.Map.Planet, func(p Planet) bool { return p.Number == uint(number) })
if pl < 0 {
return e.NewEntityNotExistsError("planet #%d", number)
}
if g.Map.Planet[pl].Owner != g.Race[ri].ID {
return e.NewEntityNotOwnedError("planet #%d", number)
}
g.Map.Planet[pl].Name = n
return nil
}