129 lines
4.1 KiB
Go
129 lines
4.1 KiB
Go
package game
|
|
|
|
import (
|
|
"slices"
|
|
|
|
"github.com/google/uuid"
|
|
e "github.com/iliadenisov/galaxy/pkg/error"
|
|
)
|
|
|
|
type PlanetProduction string
|
|
|
|
const (
|
|
ProductionNone PlanetProduction = "-"
|
|
ProductionMaterial PlanetProduction = "MAT" // Сырьё
|
|
ProductionCapital PlanetProduction = "CAP" // Промышленность
|
|
|
|
ResearchDrive PlanetProduction = "DRIVE"
|
|
ResearchWeapons PlanetProduction = "WEAPONS"
|
|
ResearchShields PlanetProduction = "SHIELDS"
|
|
ResearchCargo PlanetProduction = "CARGO"
|
|
|
|
ResearchScience PlanetProduction = "SCIENCE"
|
|
ProductionShip PlanetProduction = "SHIP"
|
|
)
|
|
|
|
type ProductionType struct {
|
|
Production PlanetProduction `json:"type"`
|
|
SubjectID *uuid.UUID `json:"subjectId"`
|
|
Progress *float64 `json:"progress"`
|
|
}
|
|
|
|
func (p PlanetProduction) AsType(subject uuid.UUID) ProductionType {
|
|
switch p {
|
|
case ResearchScience, ProductionShip:
|
|
return ProductionType{Production: p, SubjectID: &subject}
|
|
default:
|
|
return ProductionType{Production: p, SubjectID: nil}
|
|
}
|
|
}
|
|
|
|
func (g Game) PlanetProduction(raceName string, planetNumber int, prodType, subject string) error {
|
|
ri, err := g.raceIndex(raceName)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
var prod PlanetProduction
|
|
switch PlanetProduction(prodType) {
|
|
case ProductionMaterial:
|
|
prod = ProductionMaterial
|
|
case ProductionCapital:
|
|
prod = ProductionCapital
|
|
case ResearchDrive:
|
|
prod = ResearchDrive
|
|
case ResearchWeapons:
|
|
prod = ResearchWeapons
|
|
case ResearchShields:
|
|
prod = ResearchShields
|
|
case ResearchCargo:
|
|
prod = ResearchCargo
|
|
case ResearchScience:
|
|
prod = ResearchScience
|
|
case ProductionShip:
|
|
prod = ProductionShip
|
|
default:
|
|
return e.NewProductionInvalidError(prodType)
|
|
}
|
|
return g.planetProductionInternal(ri, planetNumber, prod, subject)
|
|
}
|
|
|
|
func (g Game) planetProductionInternal(ri int, number int, prod PlanetProduction, subj string) error {
|
|
if number < 0 {
|
|
return e.NewPlanetNumberError(number)
|
|
}
|
|
i := slices.IndexFunc(g.Map.Planet, func(p Planet) bool { return p.Number == uint(number) })
|
|
if i < 0 {
|
|
return e.NewEntityNotExistsError("planet #%d", number)
|
|
}
|
|
if g.Map.Planet[i].Owner != g.Race[ri].ID {
|
|
return e.NewEntityNotOwnedError("planet %#d", number)
|
|
}
|
|
g.Map.Planet[i].Production.Progress = nil
|
|
var subjectID *uuid.UUID
|
|
if (prod == ResearchScience || prod == ProductionShip) && subj == "" {
|
|
return e.NewEntityTypeNameValidationError("%s=%q", prod, subj)
|
|
}
|
|
if prod == ResearchScience {
|
|
i := slices.IndexFunc(g.Race[ri].Sciences, func(s Science) bool { return s.Name == subj })
|
|
if i < 0 {
|
|
return e.NewEntityNotExistsError("science %w", subj)
|
|
}
|
|
subjectID = &g.Race[ri].Sciences[i].ID
|
|
}
|
|
if prod == ProductionShip {
|
|
i := slices.IndexFunc(g.Race[ri].ShipTypes, func(st ShipType) bool { return st.Name == subj })
|
|
if i < 0 {
|
|
return e.NewEntityNotExistsError("ship type %w", subj)
|
|
}
|
|
if g.Map.Planet[i].Production.Production == ProductionShip &&
|
|
g.Map.Planet[i].Production.SubjectID != nil &&
|
|
*g.Map.Planet[i].Production.SubjectID == g.Race[ri].ShipTypes[i].ID {
|
|
// Planet already produces this ship type, keeping progress intact
|
|
return nil
|
|
}
|
|
subjectID = &g.Race[ri].ShipTypes[i].ID
|
|
var progress float64 = 0.
|
|
g.Map.Planet[i].Production.Progress = &progress
|
|
}
|
|
if g.Map.Planet[i].Production.Production == ProductionShip {
|
|
if g.Map.Planet[i].Production.SubjectID == nil {
|
|
return e.NewGameStateError("planet #%d produces ship but SubjectID is empty", g.Map.Planet[i].Number)
|
|
}
|
|
s := *g.Map.Planet[i].Production.SubjectID
|
|
if g.Map.Planet[i].Production.Progress == nil {
|
|
return e.NewGameStateError("planet #%d produces ship but Progress is empty", g.Map.Planet[i].Number)
|
|
}
|
|
progress := *g.Map.Planet[i].Production.Progress
|
|
i := slices.IndexFunc(g.Race[ri].ShipTypes, func(st ShipType) bool { return st.ID == s })
|
|
if i < 0 {
|
|
return e.NewGameStateError("planet #%d produces ship but ShipType was not found for race %s", g.Map.Planet[i].Number, g.Race[ri].Name)
|
|
}
|
|
mat, _ := g.Race[ri].ShipTypes[i].ProductionCost()
|
|
extra := mat * progress
|
|
g.Map.Planet[i].Material += extra
|
|
}
|
|
g.Map.Planet[i].Production.Production = prod
|
|
g.Map.Planet[i].Production.SubjectID = subjectID
|
|
return nil
|
|
}
|