private void RepairMesh(RoadNetwork network) { network.SetVisited(false); int num_unknown = network.VertexCount; LinkedList<Vertex> to_check = new LinkedList<Vertex>(); to_check.AddLast( network.Start ); while( num_unknown > 0 ) { Vertex v = null; // While there's still unchecked nodes in this group while(to_check.Count > 0) { v = to_check.First.Value; to_check.RemoveFirst(); v.Visited = true; num_unknown --; for( int i = 0; i < v.EdgeCount; i ++ ) { Vertex next = v.GetEdge(i).End; if (next.Visited) continue; to_check.AddLast(next); } } // If there are still unreached verticies, pick the first and connect if( num_unknown > 0 ) { Vertex end = null; // Find the first non-visited vertex for (int i = 0; i < network.VertexCount; i++) { if (!network.GetVertex(i).Visited) { end = network.GetVertex(i); break; } } // Make an edge from this vertex to the last checked network.AddEdge(v, end); to_check.AddLast(end); } } }
/// <summary> /// Randomly alter a RoadNetwork to Produce a slightly different RoadNetwork /// </summary> /// <param name="source">The RoadNetwork to mutate</param> /// <returns>The mutated RoadNetwork</returns> public static RoadNetwork Mutate(RoadNetwork source) { Map map = source.Map; int mapWidth = map.Width; int mapHeight = map.Height; int maxXChange = 1 + mapWidth / 10; int maxYChange = 1 + mapHeight / 10; source.ClearCopies(); source.SetVisited(false); source.SetBroken(true); RoadNetwork destination = new RoadNetwork(map); int endVertexIndex = -1; LinkedList<Vertex> vertexStack = new LinkedList<Vertex>(); source.Start.Visited = true; vertexStack.AddFirst(source.Start); while (vertexStack.Count > 0) { Vertex vertex = vertexStack.First(); vertexStack.RemoveFirst(); List<Vertex> nextVertices = new List<Vertex>(); for (int i = 0; i < vertex.EdgeCount; i++) { Edge edge = vertex.GetEdge(i); Vertex nextVertex = edge.End; if (!nextVertex.Visited) { edge.Broken = false; nextVertex.Visited = true; nextVertices.Add(nextVertex); } } //If this vertex is a leaf of the tree and not the end vertex it has a 25% chance of //begin removed. if (nextVertices.Count > 0 || vertex == source.End || random.Next(4) > 0) { Coordinates coordinates = vertex.Coordinates; if (vertex != source.Start && vertex != source.End && random.Next(4) == 0) { coordinates = RandomAdjacentPoint(vertex.Coordinates); } int index = destination.AddVertexUnique(vertex.Coordinates); vertex.Copy = destination.GetVertex(index); if (vertex == source.End) { endVertexIndex = index; } } //Shuffle Vertices for (int n = nextVertices.Count - 1; n > 0; n--) { int m = random.Next(n + 1); Vertex temp = nextVertices[m]; nextVertices[m] = nextVertices[n]; nextVertices[n] = temp; } //Push vertices onto stack in shiffled order. foreach (Vertex nextVertex in nextVertices) { vertexStack.AddFirst(nextVertex); } } for (int i = 0; i < source.EdgeCount; i++) { Edge edge = source.GetEdge(i); if ((!edge.Broken || random.Next(4) > 0) && edge.Start.Copy != null && edge.End.Copy != null) { StepPath(destination, edge.Start.Copy, edge.End.Copy); } } int newVertices = random.Next(20); for (int i = 0; i < newVertices; i++) { Vertex startVertex = destination.GetVertex(random.Next(destination.VertexCount)); int index = destination.AddVertexUnique(RandomAdjacentPoint(startVertex.Coordinates)); Vertex endVertex = destination.GetVertex(index); destination.AddEdge(startVertex, endVertex); } if (endVertexIndex == -1) { throw new Exception("End vertex not found."); } else { destination.SetEnd(endVertexIndex); } return destination; }
/// <summary> /// Randomly alter a RoadNetwork to Produce a slightly different RoadNetwork /// </summary> /// <param name="source">The RoadNetwork to mutate</param> /// <returns>The mutated RoadNetwork</returns> public static RoadNetwork Mutate(RoadNetwork source) { Map map = source.Map; int mapWidth = map.Width; int mapHeight = map.Height; int maxXChange = 1 + mapWidth / 10; int maxYChange = 1 + mapHeight / 10; source.ClearCopies(); source.SetVisited(false); source.SetBroken(true); RoadNetwork destination = new RoadNetwork(map); int endVertexIndex = -1; LinkedList<Vertex> vertexStack = new LinkedList<Vertex>(); source.Start.Visited = true; vertexStack.AddFirst(source.Start); while (vertexStack.Count > 0) { Vertex vertex = vertexStack.First(); vertexStack.RemoveFirst(); List<Vertex> nextVertices = new List<Vertex>(); for (int i = 0; i < vertex.EdgeCount; i++) { Edge edge = vertex.GetEdge(i); Vertex nextVertex = edge.End; if (!nextVertex.Visited) { edge.Broken = false; nextVertex.Visited = true; nextVertices.Add(nextVertex); } } //If this vertex is a leaf of the tree and not the end vertex it has a 25% chance of //begin removed. if (nextVertices.Count > 0 || vertex == source.End || random.Next(4) > 0) { if (vertex == source.End) { endVertexIndex = destination.VertexCount; } if (vertex == source.Start || vertex == source.End || random.Next(10) > 0) { destination.CopyVertex(vertex); } else { int x = vertex.Coordinates.X + random.Next(2 * maxXChange+1) - maxXChange; int y = vertex.Coordinates.Y + random.Next(2 * maxYChange + 1) - maxYChange; x = Math.Max(0, Math.Min(x, map.Width - 1)); y = Math.Max(0, Math.Min(y, map.Height - 1)); vertex.Copy = destination.AddVertex(x, y); } } //Shuffle Vertices for (int n = nextVertices.Count - 1; n > 0; n--) { int m = random.Next(n + 1); Vertex temp = nextVertices[m]; nextVertices[m] = nextVertices[n]; nextVertices[n] = temp; } //Push vertices onto stack in shiffled order. foreach (Vertex nextVertex in nextVertices) { vertexStack.AddFirst(nextVertex); } } for (int i = 0; i < source.EdgeCount; i++) { Edge edge = source.GetEdge(i); if ((!edge.Broken || random.Next(4) > 0) && edge.Start.Copy != null && edge.End.Copy != null) { destination.CopyEdge(edge); } } int verticesToAdd = random.Next(10); for (int i = 0; i < verticesToAdd; i++) { Vertex startVertex = destination.GetVertex(random.Next(destination.VertexCount)); Vertex endVertex = destination.AddVertex(random.Next(mapWidth), random.Next(mapHeight)); destination.AddEdge(startVertex, endVertex); } int edgesToAdd = random.Next(destination.VertexCount/2); for (int i = 0; i < edgesToAdd; i++) { Vertex startVertex = destination.GetVertex(random.Next(destination.VertexCount)); Vertex endVertex = destination.GetVertex(random.Next(destination.VertexCount)); if (startVertex != endVertex) { destination.AddEdge(startVertex, endVertex); } } if (endVertexIndex == -1) { throw new Exception("End vertex not found."); } else { destination.SetEnd(endVertexIndex); } return destination; }