package game import ( "fmt" "math/rand/v2" "slices" "github.com/google/uuid" "github.com/iliadenisov/galaxy/pkg/generator" "github.com/iliadenisov/galaxy/pkg/model/game" ) func newGame(r Repo, races []string) (uuid.UUID, error) { m, err := generator.Generate(func(ms *generator.MapSetting) { ms.Players = uint32(len(races)) }) if err != nil { return uuid.Nil, fmt.Errorf("generate map: %s", err) } return newGameOnMap(r, races, m) } func newGameOnMap(r Repo, races []string, m generator.Map) (uuid.UUID, error) { g, err := buildGameOnMap(races, m) if err != nil { return uuid.Nil, err } if err := r.SaveTurn(0, *g); err != nil { return uuid.Nil, err } return g.ID, nil } func buildGameOnMap(races []string, m generator.Map) (*game.Game, error) { if len(races) != len(m.HomePlanets) { return nil, fmt.Errorf("generate map: wrong number of home planets: %d, expected: %d ", len(m.HomePlanets), len(races)) } gameID, err := uuid.NewRandom() if err != nil { return nil, fmt.Errorf("generate game uuid: %s", err) } g := &game.Game{ ID: gameID, Race: make([]game.Race, len(races)), } gameMap := &game.Map{ Width: m.Width, Height: m.Height, Planet: make([]game.Planet, 0), } var planetCount uint = 0 relations := make([]game.RaceRelation, len(races)) for i := range races { raceID, err := uuid.NewRandom() if err != nil { return nil, fmt.Errorf("generate race uuid: %s", err) } relations[i] = game.RaceRelation{RaceID: raceID, Relation: game.RelationWar} g.Race[i] = game.Race{ ID: raceID, Name: races[i], Vote: raceID, Drive: 1, Weapons: 1, Shields: 1, Cargo: 1, } gameMap.Planet = append(gameMap.Planet, NewPlanet( planetCount, m.HomePlanets[i].HW.RandomName(), raceID, m.HomePlanets[i].HW.Position.X, m.HomePlanets[i].HW.Position.Y, m.HomePlanets[i].HW.Size, m.HomePlanets[i].HW.Size, // HW's pop & ind = size m.HomePlanets[i].HW.Size, m.HomePlanets[i].HW.Resources, game.ResearchDrive.AsType(uuid.Nil), )) planetCount++ for dw := range m.HomePlanets[i].DW { gameMap.Planet = append(gameMap.Planet, NewPlanet( planetCount, m.HomePlanets[i].DW[dw].RandomName(), raceID, m.HomePlanets[i].DW[dw].Position.X, m.HomePlanets[i].DW[dw].Position.Y, m.HomePlanets[i].DW[dw].Size, m.HomePlanets[i].DW[dw].Size, // DW's pop & ind = size m.HomePlanets[i].DW[dw].Size, m.HomePlanets[i].DW[dw].Resources, game.ResearchDrive.AsType(uuid.Nil), )) planetCount++ } } for i := range g.Race { rel := slices.Clone(relations) ri := slices.IndexFunc(rel, func(a game.RaceRelation) bool { return a.RaceID == g.Race[i].ID }) g.Race[i].Relations = append(rel[:ri], rel[ri+1:]...) } for i := range m.FreePlanets { gameMap.Planet = append(gameMap.Planet, NewPlanet( planetCount, m.FreePlanets[i].RandomName(), uuid.Nil, m.FreePlanets[i].Position.X, m.FreePlanets[i].Position.Y, m.FreePlanets[i].Size, 0, 0, m.FreePlanets[i].Resources, game.ProductionNone.AsType(uuid.Nil), )) planetCount++ } rand.Shuffle(len(gameMap.Planet), func(i, j int) { gameMap.Planet[i].Number, gameMap.Planet[j].Number = gameMap.Planet[j].Number, gameMap.Planet[i].Number }) g.Map = *gameMap return g, nil } func NewPlanet(num uint, name string, owner uuid.UUID, x, y, size, pop, ind, res float64, prod game.ProductionType) game.Planet { return game.Planet{ Owner: owner, PlanetReport: game.PlanetReport{ UninhabitedPlanet: game.UninhabitedPlanet{ UnidentifiedPlanet: game.UnidentifiedPlanet{ X: x, Y: y, Number: num, }, Size: size, Name: name, Resources: res, }, Population: pop, Industry: ind, Production: prod, }, } }