package game import ( "encoding/json" "github.com/google/uuid" e "github.com/iliadenisov/galaxy/pkg/error" ) type Game struct { ID uuid.UUID `json:"id"` Age uint `json:"turn"` // Game's turn number Map Map `json:"map"` Race []Race `json:"races"` } func (g Game) Votes(raceID uuid.UUID) float64 { // XXX: calculate [Race]Population once when loading Game from Storage? var pop float64 for i := range g.Map.Planet { if g.Map.Planet[i].Owner == raceID { pop += g.Map.Planet[i].Population } } return pop / 1000. } func (g Game) hostRaceID(name string) (uuid.UUID, error) { if v, ok := g.raceID(name); ok { return v, nil } return uuid.Nil, e.NewHostRaceUnknownError(name) } func (g Game) opponentRaceID(name string) (uuid.UUID, error) { if v, ok := g.raceID(name); ok { return v, nil } return uuid.Nil, e.NewOpponentRaceUnknownError(name) } func (g Game) raceID(raceName string) (uuid.UUID, bool) { for i := range g.Race { if g.Race[i].Name == raceName { return g.Race[i].ID, true } } return uuid.Nil, false } func (g Game) UpdateRelation(hostRace, opponentRace string, rel Relation) error { hostID, err := g.hostRaceID(hostRace) if err != nil { return err } var opponentID uuid.UUID if hostRace == opponentRace { opponentID = hostID } else if opponentID, err = g.opponentRaceID(opponentRace); err != nil { return err } return g.updateRelationInternal(hostID, opponentID, rel) } func (g Game) updateRelationInternal(hostID, opponentID uuid.UUID, rel Relation) error { for r := range g.Race { if g.Race[r].ID == hostID { for o := range g.Race[r].Relations { switch { case hostID == opponentID: g.Race[r].Relations[o].Relation = rel case g.Race[r].Relations[o].RaceID == opponentID: g.Race[r].Relations[o].Relation = rel return nil } } if hostID != opponentID { return e.NewGameStateError("UpdateRelation: opponent not found") } } } if hostID != opponentID { return e.NewGameStateError("UpdateRelation: host %v not found", hostID) } return nil } func (g Game) Relation(hostRace, opponentRace string) (RaceRelation, error) { hostID, err := g.hostRaceID(hostRace) if err != nil { return RaceRelation{}, err } opponentID, err := g.opponentRaceID(opponentRace) if err != nil { return RaceRelation{}, err } return g.relationInternal(hostID, opponentID) } func (g Game) relationInternal(hostID, opponentID uuid.UUID) (RaceRelation, error) { for r := range g.Race { if g.Race[r].ID == hostID { for o := range g.Race[r].Relations { if g.Race[r].Relations[o].RaceID == opponentID { return g.Race[r].Relations[o], nil } } return RaceRelation{}, e.NewGameStateError("Relation: opponent not found") } } return RaceRelation{}, e.NewGameStateError("Relation: host %v not found", hostID) } func (g Game) MarshalBinary() (data []byte, err error) { return json.Marshal(&g) } func (g *Game) UnmarshalBinary(data []byte) error { return json.Unmarshal(data, g) }