Beispiel #1
0
 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();
 }
Beispiel #2
0
        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;
            }));
        }