package controller import ( "maps" "slices" "galaxy/model/report" "galaxy/game/internal/model/game" "github.com/google/uuid" ) func (c *Controller) MakeTurn() error { if err := c.applyOrders(c.Cache.g.Turn); err != nil { return err } // Next turn c.Cache.g.Turn += 1 c.Cache.g.Stage = 0 // 01. Вышедшие расы удаляются из списка участвующих рас перед началом просчета очередного хода c.Cache.TurnWipeExtinctRaces() // 02. Товары загружаются на корабли, находящиеся в начале грузовых маршрутов, и корабли входят в гиперпространство (но ещё не полетели) c.Cache.SendRoutedGroups() // 03. Корабли, где это возможно, объединяются в группы. c.Cache.TurnMergeEqualShipGroups() // 04. Враждующие корабли вступают в схватку. battles := ProduceBattles(c.Cache) // 05. Корабли пролетают сквозь гиперпространство. c.Cache.MoveShipGroups() // 06. Корабли, где это возможно, объединяются в группы. c.Cache.TurnMergeEqualShipGroups() // 07. Враждующие корабли снова вступают в схватку (это происходит после выхода из гиперпространства). battles = append(battles, ProduceBattles(c.Cache)...) // 08. Корабли бомбят вражеские планеты. bombings := c.Cache.ProduceBombings() // 09. На планетах строятся корабли. // 10. Корабли, где это возможно, объединяются в группы. // 11. На планетах производится промышленность, добывается сырье, разрабатываются новые технологии. // 12. Увеличивается население планет. c.Cache.TurnPlanetProductions() // 13. Товары выгружаются в конце грузовых маршрутов. // 14. Выгруженные колонисты увеличивают население планеты (если население планеты ниже её размера). // 15. Накопленная и выгруженная промышленность увеличивает производственный уровень планеты (если производственный уровень планеты ниже уровня населения). c.Cache.TurnUnloadEnroutedGroups() // 16. Происходит отмена маршрутов, выходящих за зону полета кораблей. c.Cache.RemoveUnreachableRoutes() // 17. Происходит голосование. winners := c.Cache.TurnCalculateVotes() c.Cache.TurnAcceptWinners(winners) /*** Last steps ***/ // Store bombings bombingReport := make([]*report.Bombing, len(bombings)) if len(bombings) > 0 { if err := c.Repo.SaveBombings(c.Cache.g.Turn, bombings); err != nil { return err } for i := range bombings { bombingReport[i].Planet = bombings[i].Planet bombingReport[i].PlanetOwnedID = bombings[i].PlanetOwnedID bombingReport[i].Number = bombings[i].Number bombingReport[i].Owner = bombings[i].Owner bombingReport[i].Attacker = bombings[i].Attacker bombingReport[i].Production = bombings[i].Production bombingReport[i].Industry = report.F(bombings[i].Industry.F()) bombingReport[i].Population = report.F(bombings[i].Population.F()) bombingReport[i].Colonists = report.F(bombings[i].Colonists.F()) bombingReport[i].Capital = report.F(bombings[i].Capital.F()) bombingReport[i].Material = report.F(bombings[i].Material.F()) bombingReport[i].AttackPower = report.F(bombings[i].AttackPower.F()) bombingReport[i].Wiped = bombings[i].Wiped } } // Store battles battleReport := make([]*report.BattleReport, len(battles)) if len(battles) > 0 { battleMeta := make([]game.BattleMeta, len(battles)) for i := range battles { b := battles[i] observers := make(map[uuid.UUID]bool) for sgi := range b.ObserverGroups { observers[c.Cache.ShipGroup(sgi).OwnerID] = true } battleMeta[i] = game.BattleMeta{ Turn: c.Cache.g.Turn, Planet: b.Planet, BattleID: b.ID, ObserverIDs: slices.Collect(maps.Keys(observers)), } report := TransformBattle(c.Cache, b) if err := c.Repo.SaveBattle(c.Cache.g.Turn, report, &battleMeta[i]); err != nil { return err } battleReport[i] = report } } // Remove killed ship groups c.Cache.DeleteKilledShipGroups() // Store game state for the new turn and 'current' state as well if err := c.Repo.SaveNewTurn(c.Cache.g.Turn, c.Cache.g); err != nil { return err } for rep := range c.Cache.Report(c.Cache.g.Turn, battleReport, bombingReport) { if err := c.Repo.SaveReport(c.Cache.g.Turn, rep); err != nil { return err } } for i := range c.Cache.g.Race { if c.Cache.g.Race[i].Extinct { continue } c.Cache.g.Race[i].TTL -= 1 } // [ ] monitor memory consumption at this point? return nil }