예제 #1
0
        public Map GenerateMap(Random Random, Environment Environment, IdGenerator IdGenerator)
        {
            var map = new Map(Width, Height, Environment, IdGenerator);

            var cache = new Dictionary <FunctionFactory, Func <double, double, double> >();
            var elevationGenerator =
                Setting.MapGenerator.TerrainGenerator.ElevationGenerator.GetFeatureGenerator(Random, cache);
            var waterGenerator =
                Setting.MapGenerator.TerrainGenerator.WaterGenerator.GetFeatureGenerator(Random, cache);
            var swampGenerator =
                Setting.MapGenerator.TerrainGenerator.SwampGenerator.GetFeatureGenerator(Random, cache);
            var forestGenerator =
                Setting.MapGenerator.TerrainGenerator.ForestGenerator.GetFeatureGenerator(Random, cache);
            var townGenerator =
                Setting.MapGenerator.TerrainGenerator.TownGenerator.GetFeatureGenerator(Random, cache);

            foreach (Tile t in map.TilesEnumerable)
            {
                if (elevationGenerator(t.Center.X, t.Center.Y) && t.OnEdge(Direction.NONE))
                {
                    t.Configuration.SetElevation(1);
                }
                else if (waterGenerator(t.Center.X, t.Center.Y))
                {
                    for (int i = 0; i < 6; ++i)
                    {
                        t.SetEdge(i, TileEdge.WATER);
                    }
                }
                if (t.Configuration.Elevation == 0 && swampGenerator(t.Center.X, t.Center.Y))
                {
                    t.Configuration.SetTileBase(TileBase.SWAMP);
                }
            }
            foreach (Tile t in map.TilesEnumerable)
            {
                if (t.NeighborTiles.Any(i => i != null && i.Configuration.Elevation > t.Configuration.Elevation))
                {
                    t.Configuration.SetTileBase(TileBase.SLOPE);
                    for (int i = 0; i < 6; ++i)
                    {
                        t.SetEdge(i, TileEdge.NONE);
                    }
                }
            }
            foreach (Tile t in map.TilesEnumerable)
            {
                if (t.Configuration.TileBase == TileBase.SWAMP)
                {
                    continue;
                }

                var slopes = GetSlopeDirections(t).ToArray();
                for (int i = 0; i < 6; ++i)
                {
                    if (t.Configuration.GetEdge(i) == TileEdge.WATER)
                    {
                        continue;
                    }

                    Tile neighbor = t.NeighborTiles[i];
                    if (neighbor == null)
                    {
                        continue;
                    }

                    if (t.Configuration.TileBase == TileBase.SLOPE)
                    {
                        if (neighbor.Configuration.TileBase == TileBase.SLOPE)
                        {
                            var nSlopes = GetSlopeDirections(neighbor).ToArray();
                            if (!slopes.All(v => nSlopes.Any(w => DoublesEqual(v, w))))
                            {
                                t.SetEdge(i, TileEdge.SLOPE);
                            }
                        }
                        continue;
                    }

                    if (neighbor.Configuration.TileBase != TileBase.SLOPE &&
                        neighbor.Configuration.TileBase != TileBase.SWAMP)
                    {
                        Vector2f v = .5f * (t.Bounds[i].Point + t.Bounds[i].End);
                        if (forestGenerator(v.X, v.Y))
                        {
                            t.SetEdge(i, TileEdge.FOREST);
                        }
                        if (townGenerator(t.Bounds[i].Point.X, t.Bounds[i].Point.Y) ||
                            townGenerator(t.Bounds[i].End.X, t.Bounds[i].End.Y))
                        {
                            t.SetEdge(i, TileEdge.TOWN);
                        }
                    }
                }
            }

            // Rivers
            var riverNodes = new HashSet <Tile>();

            for (int i = 0; i < Math.Max(1, Width * Height / 160); ++i)
            {
                var t = GetRandomTile(Random, map);
                if (!IsElevated(t))
                {
                    riverNodes.Add(t);
                }
            }
            for (int i = 0; i < Math.Max(2, (Width + Height - 2) / 8); ++i)
            {
                var t = GetRandomEdgeTile(Random, map);
                if (!IsElevated(t))
                {
                    EdgePathOverlay(t, TilePathOverlay.STREAM);
                    riverNodes.Add(t);
                }
            }
            var mst   = new MinimalSpanning <Tile>(riverNodes, i => riverNodes, (i, j) => i.HeuristicDistanceTo(j));
            var edges = mst.GetEdges().ToList();

            for (int i = 0; i < edges.Count / 4; ++i)
            {
                edges.RemoveAt(Random.Next(0, edges.Count));
            }
            foreach (Tuple <Tile, Tile> edge in edges)
            {
                MakePath(edge.Item1, edge.Item2, TilePathOverlay.STREAM, RiverDistanceFunction(Random));
            }

            // Roads and Towns
            var towns     = new Partitioning <Tile>(map.TilesEnumerable, (i, j) => i.GetEdge(j) == TileEdge.TOWN);
            var roadNodes = new HashSet <Tile>();

            foreach (ISet <Tile> town in towns.GetPartitions())
            {
                var name =
                    new string(Setting.MapGenerator.NameGenerator.Generate(Random).ToArray());
                name = ObjectDescriber.Namify(name);
                map.Regions.Add(new MapRegion(name, town));
                var tiles = town.ToList();
                for (int i = 0; i < Math.Max(1, tiles.Count / 4); ++i)
                {
                    roadNodes.Add(tiles[Random.Next(0, tiles.Count)]);
                }
            }
            for (int i = 0; i < Math.Max(1, Width * Height / 160); ++i)
            {
                roadNodes.Add(GetRandomTile(Random, map));
            }
            for (int i = 0; i < Math.Max(2, (Width + Height - 2) / 8); ++i)
            {
                var t = GetRandomEdgeTile(Random, map);
                EdgePathOverlay(t, TilePathOverlay.ROAD);
                roadNodes.Add(t);
            }

            mst   = new MinimalSpanning <Tile>(roadNodes, i => roadNodes, (i, j) => i.HeuristicDistanceTo(j));
            edges = mst.GetEdges().ToList();
            var nodes = roadNodes.ToList();

            for (int i = 0; i < edges.Count / 4; ++i)
            {
                edges.Add(
                    new Tuple <Tile, Tile>(nodes[Random.Next(0, nodes.Count)], nodes[Random.Next(0, nodes.Count)]));
            }
            foreach (Tuple <Tile, Tile> edge in edges)
            {
                MakePath(edge.Item1, edge.Item2, TilePathOverlay.ROAD, (i, j) => RoadDistanceFunction(Random, i, j, 6));
            }

            map.Ready();
            return(map);
        }