Mazes #119
@@ -126,4 +126,9 @@ public class DisjointSet<T>
|
|||||||
return (firstRoot == secondRoot);
|
return (firstRoot == secondRoot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void clear()
|
||||||
|
{
|
||||||
|
mapping.clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,10 +39,10 @@ public class MazeDesigner
|
|||||||
// Cut out random subgraphs from the adjacency graph
|
// Cut out random subgraphs from the adjacency graph
|
||||||
ArrayList<IGraphNode<PartitionNode, DoorwayData>> cores = createMazeSections(rooms, random);
|
ArrayList<IGraphNode<PartitionNode, DoorwayData>> cores = createMazeSections(rooms, random);
|
||||||
|
|
||||||
// Remove unnecessary passages through floors/ceilings
|
// Remove unnecessary passages through floors/ceilings and some from the walls
|
||||||
for (IGraphNode<PartitionNode, DoorwayData> core : cores)
|
for (IGraphNode<PartitionNode, DoorwayData> core : cores)
|
||||||
{
|
{
|
||||||
minimizeVerticalPassages(core, rooms, random);
|
pruneDoorways(core, rooms, random);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new MazeDesign(root, rooms, cores);
|
return new MazeDesign(root, rooms, cores);
|
||||||
@@ -459,7 +459,7 @@ public class MazeDesigner
|
|||||||
return cores;
|
return cores;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void minimizeVerticalPassages(IGraphNode<PartitionNode, DoorwayData> core,
|
private static void pruneDoorways(IGraphNode<PartitionNode, DoorwayData> core,
|
||||||
DirectedGraph<PartitionNode, DoorwayData> rooms, Random random)
|
DirectedGraph<PartitionNode, DoorwayData> rooms, Random random)
|
||||||
{
|
{
|
||||||
// We receive a node for one of the rooms in a section of the maze
|
// We receive a node for one of the rooms in a section of the maze
|
||||||
@@ -467,13 +467,15 @@ public class MazeDesigner
|
|||||||
// still allowing any room to be reachable from any other room.
|
// still allowing any room to be reachable from any other room.
|
||||||
// In technical terms, we receive a node from a connected subgraph
|
// In technical terms, we receive a node from a connected subgraph
|
||||||
// and we need to remove as many Y_AXIS-type edges as possible while
|
// and we need to remove as many Y_AXIS-type edges as possible while
|
||||||
// preserving connectedness.
|
// preserving connectedness. We also want to randomly remove some of
|
||||||
|
// the other doorways without breaking connectedness.
|
||||||
|
|
||||||
// An efficient solution is to assign nodes to disjoint sets based
|
// An efficient solution is to assign nodes to disjoint sets based
|
||||||
// on their components, ignoring all Y_AXIS edges, then iterate over
|
// on their components, ignoring all Y_AXIS edges, then iterate over
|
||||||
// a list of those edges and remove them if they connect two nodes
|
// a list of those edges and remove them if they connect two nodes
|
||||||
// in the same set. Otherwise, merge their sets and keep the edge.
|
// in the same set. Otherwise, merge their sets and keep the edge.
|
||||||
// This is similar to algorithms for spanning trees.
|
// This is similar to algorithms for spanning trees. The same
|
||||||
|
// idea applies for the other doorways with some chance added.
|
||||||
|
|
||||||
// First, list all nodes in the subgraph
|
// First, list all nodes in the subgraph
|
||||||
IGraphNode<PartitionNode, DoorwayData> current;
|
IGraphNode<PartitionNode, DoorwayData> current;
|
||||||
@@ -540,6 +542,38 @@ public class MazeDesigner
|
|||||||
rooms.removeEdge(passage);
|
rooms.removeEdge(passage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Repeat the pruning process with X_AXIS and Z_AXIS doorways
|
||||||
|
// In this case, unnecessary edges might be kept at random
|
||||||
|
components.clear();
|
||||||
|
targets.clear();
|
||||||
|
|
||||||
|
for (IGraphNode<PartitionNode, DoorwayData> room : subgraph)
|
||||||
|
{
|
||||||
|
components.makeSet(room);
|
||||||
|
}
|
||||||
|
for (IGraphNode<PartitionNode, DoorwayData> room : subgraph)
|
||||||
|
{
|
||||||
|
for (IEdge<PartitionNode, DoorwayData> passage : room.outbound())
|
||||||
|
{
|
||||||
|
if (passage.data().axis() == DoorwayData.Y_AXIS)
|
||||||
|
{
|
||||||
|
components.mergeSets(passage.head(), passage.tail());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
targets.add(passage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Collections.shuffle(targets, random);
|
||||||
|
for (IEdge<PartitionNode, DoorwayData> passage : targets)
|
||||||
|
{
|
||||||
|
if (!components.mergeSets(passage.head(), passage.tail()) && random.nextBoolean())
|
||||||
|
{
|
||||||
|
rooms.removeEdge(passage);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user