private void DoMapping() { var graph = levelDescription.GetGraph(); var stageOneGraph = levelDescription.GetGraphWithoutCorridors(); foreach (var vertex in graph.Vertices) { var roomNode = CreateRoomNode(vertex); // Create vertices mapping mappedGraph.AddVertex(roomNode); // Store room description roomDescriptions[roomNode.Id] = levelDescription.GetRoomDescription(vertex); } // Handle main graph edges foreach (var edge in graph.Edges) { mappedGraph.AddEdge(GetRoomNode(edge.From), GetRoomNode(edge.To)); } // Handle stage one graph vertices foreach (var vertex in stageOneGraph.Vertices) { mappedStageOneGraph.AddVertex(GetRoomNode(vertex)); } // Handle stage one graph edges foreach (var edge in stageOneGraph.Edges) { mappedStageOneGraph.AddEdge(GetRoomNode(edge.From), GetRoomNode(edge.To)); } }
/// <inheritdoc /> public bool ComputeEnergyData(ILayout <TNode, TConfiguration> layout, TNode node, TConfiguration configuration, ref TEnergyData energyData) { // TODO: why this? if (mapDescription.GetRoomDescription(node).IsCorridor) { return(true); } var wrongDistanceCount = 0; foreach (var vertex in layout.Graph.Vertices) { if (vertex.Equals(node)) { continue; } if (!layout.GetConfiguration(vertex, out var c)) { continue; } if (mapDescription.GetRoomDescription(vertex).IsCorridor) { continue; } if (AreNeighbours(node, vertex)) { continue; } if (!HaveMinimumDistance(configuration, c)) { wrongDistanceCount++; } } var constraintData = new MinimumDistanceConstraintData() { WrongDistanceCount = wrongDistanceCount }; energyData.MinimumDistanceConstraintData = constraintData; return(wrongDistanceCount == 0); }
public bool ComputeEnergyData(ILayout <TNode, TConfiguration> layout, TNode node, TConfiguration configuration, ref TEnergyData energyData) { var isCorridor = optimizeCorridors && mapDescription.GetRoomDescription(node).IsCorridor; var overlap = 0; var distance = 0; var neighbors = layout.Graph.GetNeighbours(node).ToList(); foreach (var vertex in layout.Graph.Vertices) { if (vertex.Equals(node)) { continue; } if (!layout.GetConfiguration(vertex, out var c)) { continue; } var area = ComputeOverlap(configuration, c); if (area != 0) { overlap += area; } else if (!isCorridor && neighbors.Contains(vertex)) { if (!configurationSpaces.HaveValidPosition(configuration, c)) { // TODO: this is not really accurate when there are more sophisticated door positions (as smaller distance is not always better) distance += ComputeDistance(configuration, c); } } } var constraintData = new BasicConstraintData { Overlap = overlap, MoveDistance = distance }; energyData.BasicConstraintData = constraintData; return(overlap == 0 && distance == 0); }
/// <inheritdoc /> public bool ComputeEnergyData(ILayout <TNode, TConfiguration> layout, TNode node, TConfiguration configuration, ref TEnergyData energyData) { if (mapDescription.GetRoomDescription(node).IsCorridor) { return(true); } var distance = 0; var neighbours = graphWithoutCorridors.GetNeighbours(node).ToList(); foreach (var vertex in neighbours) { if (vertex.Equals(node)) { continue; } if (!layout.GetConfiguration(vertex, out var c)) { continue; } // TODO: why wasn't this here? if (!AreNeighboursWithoutCorridors(vertex, node)) { continue; } if (!configurationSpaces.HaveValidPosition(configuration, c)) { distance += ComputeDistance(configuration, c); } } var constraintData = new CorridorConstraintData { CorridorDistance = distance }; energyData.CorridorConstraintData = constraintData; return(distance == 0); }
/// <inheritdoc /> public virtual void PerturbPosition(TLayout layout, IList <TNode> chain, bool updateLayout) { // TODO: check what would happen if only invalid nodes could be perturbed var canBePerturbed = chain .Where(x => !LevelDescription.GetRoomDescription(x).IsCorridor) // TODO: handle .ToList(); if (canBePerturbed.Count == 0) { return; } PerturbPosition(layout, canBePerturbed.GetRandom(Random), updateLayout); }
// TODO: remove when possible public Dictionary <Tuple <TNode, TNode>, IRoomDescription> GetNodesToCorridorMapping <TNode>(ILevelDescription <TNode> mapDescription) { var mapping = new Dictionary <Tuple <TNode, TNode>, IRoomDescription>(); var graph = mapDescription.GetGraph(); foreach (var room in graph.Vertices) { var roomDescription = mapDescription.GetRoomDescription(room); if (roomDescription.IsCorridor) { var neighbors = graph.GetNeighbours(room).ToList(); mapping.Add(new Tuple <TNode, TNode>(neighbors[0], neighbors[1]), roomDescription); mapping.Add(new Tuple <TNode, TNode>(neighbors[1], neighbors[0]), roomDescription); } } return(mapping); }
/// <inheritdoc /> public List <Chain <TNode> > GetChains(IGraph <TNode> graph) { // Get all the faces from the stage one graph var stageOneGraph = mapDescription.GetGraphWithoutCorridors(); var faces = decomposition.GetChains(stageOneGraph); var usedVertices = new HashSet <TNode>(); var notUsedStageTwoRooms = graph.Vertices.Where(x => mapDescription.GetRoomDescription(x).IsCorridor).ToList(); // Iterate through all the faces, marking all the seen vertices // As soon as all the neighbors of a stage two room are used, add the stage two room to the current face foreach (var face in faces) { // TODO: weird ForEach face.Nodes.ToList().ForEach(x => usedVertices.Add(x)); foreach (var stageTwoRoom in notUsedStageTwoRooms.ToList()) { var neighbors = graph.GetNeighbours(stageTwoRoom).ToList(); if (neighbors.TrueForAll(x => usedVertices.Contains(x))) { notUsedStageTwoRooms.Remove(stageTwoRoom); face.Nodes.Add(stageTwoRoom); } } } // It must not happen that a stage two room is not in the decomposition if (notUsedStageTwoRooms.Count != 0) { throw new ArgumentException(); } return(faces); }