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); }