public static void StartNew(Map[] maps, GameInitializationConfig config, IList <Civilization> civilizations, IPlayer localPlayer) { _instance = new Game(maps, config.Rules, civilizations, new Options(config), config.RuleSet.Paths, (DifficultyType)config.DifficultlyLevel, localPlayer); _instance.StartNextTurn(); }
public static Task <Map[]> GenerateMap(GameInitializationConfig config) { return(Task.Run(() => { var secondaryMaps = config.Rules.Maps; var area = config.WorldSize; var maps = new Map[secondaryMaps?.Length ?? 0 + 1]; var width = area[0]; var height = area[1]; var mainMap = new Map(config.FlatWorld, 0) { XDim = width, YDim = height, ResourceSeed = config.ResourceSeed ?? config.Random.Next(64), Tile = new Tile[width, height] }; var terrains = config.Rules.Terrains; var index = 0; var yMax = mainMap.Tile.GetLength(1) - 1; var land = new List <Tile>(); if (config.TerrainData != null) { for (int y = 0; y < mainMap.Tile.GetLength(1); y++) { var odd = y % 2; for (int x = 0; x < mainMap.Tile.GetLength(0); x++) { var terra = config.TerrainData[index++]; var tile = new Tile(2 * x + odd, y, terrains[0][terra & 0xF], mainMap.ResourceSeed, mainMap) { River = terra > 100, Visibility = new bool[config.NumberOfCivs + 1] }; if (tile.Type != TerrainType.Ocean) { land.Add(tile); } mainMap.Tile[x, y] = tile; } } if (!config.FlatWorld) { var ocean = terrains[0][(int)TerrainType.Ocean]; var arctic = terrains[0][(int)TerrainType.Glacier]; for (int x = 0; x < mainMap.Tile.GetLength(0); x++) { if (mainMap.Tile[x, 0].Terrain == ocean) { mainMap.Tile[x, 0].Terrain = arctic; } if (mainMap.Tile[x, yMax].Terrain == ocean) { mainMap.Tile[x, yMax].Terrain = arctic; } } } mainMap.NormalizeIslands(); } else { var remainingTiles = new HashSet <Tile>(); var ocean = terrains[0][(int)TerrainType.Ocean]; var arctic = terrains[0][(int)TerrainType.Glacier]; for (int y = 0; y < mainMap.Tile.GetLength(1); y++) { var odd = y % 2; var defaultTerrain = config.FlatWorld || (y > 0 && y < yMax) ? ocean : arctic; for (int x = 0; x < mainMap.Tile.GetLength(0); x++) { var tile = new Tile(2 * x + odd, y, defaultTerrain, mainMap.ResourceSeed, mainMap) { Island = -1, Visibility = new bool[config.NumberOfCivs + 1] }; remainingTiles.Add(tile); mainMap.Tile[x, y] = tile; } } var landRequired = config.PropLand switch { 0 => (area[0] * area[1]) / 6, 1 => (area[0] * area[1]) / 4, _ => (area[0] * area[1]) / 2 }; var landUsed = 0; var minIslandSize = 3; var maxIslandSize = 30; var grassland = terrains[0][(int)TerrainType.Grassland]; var continents = 0; var oceans = new List <Tile>(); var islands = new List <IslandDetails>(); while (landUsed < landRequired && remainingTiles.Count > 0) { var candidate = config.Random.ChooseFrom <Tile>(remainingTiles); remainingTiles.Remove(candidate); land.Add(candidate); var edgeSet = new HashSet <Tile>(); candidate.Terrain = grassland; var island = new IslandDetails { Tiles = { candidate } }; islands.Add(island); var size = config.Random.Next(minIslandSize, maxIslandSize); foreach (var tile in mainMap.DirectNeighbours(candidate)) { if (tile.Island != -1) { continue; } edgeSet.Add(tile); remainingTiles.Remove(tile); tile.Island = 0; } while (island.Tiles.Count < size && edgeSet.Count > 0) { var choice = config.Random.ChooseFrom(edgeSet); island.Tiles.Add(choice); land.Add(choice); choice.Island = candidate.Island; choice.Terrain = grassland; foreach (var tile in mainMap.DirectNeighbours(choice)) { if (tile.Island != -1 || !remainingTiles.Contains(tile)) { continue; } edgeSet.Add(tile); remainingTiles.Remove(tile); tile.Island = 0; } } if (edgeSet.Count > 0) { oceans.AddRange(edgeSet); foreach (var neighbour in edgeSet.SelectMany(tile => mainMap.DirectNeighbours(tile).Where(n => n.Island == -1 && mainMap.Neighbours(n).Any(t => t.Type != TerrainType.Ocean)))) { remainingTiles.Remove(neighbour); neighbour.Island = 0; oceans.Add(neighbour); } } landUsed += island.Tiles.Count; } oceans.AddRange(remainingTiles); mainMap.Islands = islands; mainMap.RenumberIslands(); mainMap.RenumberOceans(oceans); } mainMap.CalculateFertility(terrains[0], land); maps[0] = mainMap; return maps; })); }