Refactored Maze Generation to use RoomData

Rewrote portions of our maze generation code to use RoomData. This
provides an object that unifies all room data instead of having it
spread across various data structures and linked loosely by hash maps.
We'll need this to implement the remaining generation features.
This commit is contained in:
SenseiKiwi
2014-04-07 09:25:20 -04:00
parent 71fccfc1e4
commit d5e5e12cf9
6 changed files with 206 additions and 131 deletions

View File

@@ -18,8 +18,8 @@ public class MazeBuilder
Point3D offset = new Point3D(x - design.width() / 2, y - design.height() - 1, z - design.length() / 2); Point3D offset = new Point3D(x - design.width() / 2, y - design.height() - 1, z - design.length() / 2);
SphereDecayOperation decay = new SphereDecayOperation(random, 0, 0, Block.stoneBrick.blockID, 2); SphereDecayOperation decay = new SphereDecayOperation(random, 0, 0, Block.stoneBrick.blockID, 2);
buildRooms(design.getRoomGraph(), world, offset); buildRooms(design.getLayout(), world, offset);
carveDoorways(design.getRoomGraph(), world, offset, decay, random); carveDoorways(design.getLayout(), world, offset, decay, random);
//placeDoors(design, world, offset); //placeDoors(design, world, offset);
@@ -32,25 +32,25 @@ public class MazeBuilder
//final int DECAY_BOX_SIZE = 8 //final int DECAY_BOX_SIZE = 8
} }
private static void buildRooms(DirectedGraph<PartitionNode, DoorwayData> roomGraph, World world, Point3D offset) private static void buildRooms(DirectedGraph<RoomData, DoorwayData> layout, World world, Point3D offset)
{ {
for (IGraphNode<PartitionNode, DoorwayData> node : roomGraph.nodes()) for (IGraphNode<RoomData, DoorwayData> node : layout.nodes())
{ {
PartitionNode room = node.data(); PartitionNode room = node.data().getPartitionNode();
buildBox(world, offset, room.minCorner(), room.maxCorner(), Block.stoneBrick.blockID, 0); buildBox(world, offset, room.minCorner(), room.maxCorner(), Block.stoneBrick.blockID, 0);
} }
} }
private static void carveDoorways(DirectedGraph<PartitionNode, DoorwayData> roomGraph, World world, private static void carveDoorways(DirectedGraph<RoomData, DoorwayData> layout, World world,
Point3D offset, SphereDecayOperation decay, Random random) Point3D offset, SphereDecayOperation decay, Random random)
{ {
char axis; char axis;
Point3D lower; Point3D lower;
DoorwayData doorway; DoorwayData doorway;
for (IGraphNode<PartitionNode, DoorwayData> node : roomGraph.nodes()) for (IGraphNode<RoomData, DoorwayData> node : layout.nodes())
{ {
for (IEdge<PartitionNode, DoorwayData> passage : node.outbound()) for (IEdge<RoomData, DoorwayData> passage : node.outbound())
{ {
doorway = passage.data(); doorway = passage.data();
axis = doorway.axis(); axis = doorway.axis();
@@ -166,7 +166,6 @@ public class MazeBuilder
setBlockDirectly(world, x, y + 1, z, 0, 0); setBlockDirectly(world, x, y + 1, z, 0, 0);
} }
private static void buildBox(World world, Point3D offset, Point3D minCorner, Point3D maxCorner, int blockID, int metadata) private static void buildBox(World world, Point3D offset, Point3D minCorner, Point3D maxCorner, int blockID, int metadata)
{ {
int minX = minCorner.getX() + offset.getX(); int minX = minCorner.getX() + offset.getX();

View File

@@ -5,16 +5,12 @@ import java.util.ArrayList;
public class MazeDesign public class MazeDesign
{ {
private PartitionNode root; private PartitionNode root;
private DirectedGraph<PartitionNode, DoorwayData> rooms; private DirectedGraph<RoomData, DoorwayData> layout;
private ArrayList<IGraphNode<PartitionNode, DoorwayData>> cores;
private ArrayList<BoundingBox> protectedAreas;
public MazeDesign(PartitionNode root, DirectedGraph<PartitionNode, DoorwayData> rooms, public MazeDesign(PartitionNode root, DirectedGraph<RoomData, DoorwayData> layout)
ArrayList<IGraphNode<PartitionNode, DoorwayData>> cores)
{ {
this.root = root; this.root = root;
this.rooms = rooms; this.layout = layout;
this.cores = cores;
} }
public PartitionNode getRootPartition() public PartitionNode getRootPartition()
@@ -22,19 +18,9 @@ public class MazeDesign
return root; return root;
} }
public DirectedGraph<PartitionNode, DoorwayData> getRoomGraph() public DirectedGraph<RoomData, DoorwayData> getLayout()
{ {
return rooms; return layout;
}
public ArrayList<IGraphNode<PartitionNode, DoorwayData>> getCoreNodes()
{
return cores;
}
public ArrayList<BoundingBox> getProtectedAreas()
{
return protectedAreas;
} }
public int width() public int width()

View File

@@ -25,55 +25,66 @@ public class MazeDesigner
public static MazeDesign generate(Random random) public static MazeDesign generate(Random random)
{ {
// Construct a random binary space partitioning of our maze volume // Construct a random binary space partitioning of our maze volume
PartitionNode root = partitionRooms(MAZE_WIDTH, MAZE_HEIGHT, MAZE_LENGTH, SPLIT_COUNT, random); PartitionNode<RoomData> root = partitionRooms(MAZE_WIDTH, MAZE_HEIGHT, MAZE_LENGTH, SPLIT_COUNT, random);
// List all the leaf nodes of the partition tree, which denote individual rooms // Attach rooms to all the leaf nodes of the partition tree
ArrayList<PartitionNode> partitions = new ArrayList<PartitionNode>(1 << SPLIT_COUNT); ArrayList<RoomData> rooms = new ArrayList<RoomData>(1 << SPLIT_COUNT);
listRoomPartitions(root, partitions); attachRooms(root, rooms);
// Shuffle the list of rooms so that they're not listed in any ordered way in the room graph
// This is the only convenient way of randomizing the maze sections generated later
Collections.shuffle(rooms, random);
// Construct an adjacency graph of the rooms we've carved out. Two rooms are // Construct an adjacency graph of the rooms we've carved out. Two rooms are
// considered adjacent if and only if a doorway could connect them. Their // considered adjacent if and only if a doorway could connect them. Their
// common boundary must be large enough for a doorway. // common boundary must be large enough for a doorway.
DirectedGraph<PartitionNode, DoorwayData> rooms = createRoomGraph(root, partitions, random); DirectedGraph<RoomData, DoorwayData> layout = createRoomGraph(root, rooms, random);
// 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<RoomData> cores = createMazeSections(layout, random);
// Remove unnecessary passages through floors/ceilings and some from the walls // Remove unnecessary passages through floors/ceilings and some from the walls
for (IGraphNode<PartitionNode, DoorwayData> core : cores) for (RoomData core : cores)
{ {
pruneDoorways(core, rooms, random); pruneDoorways(core.getLayoutNode(), layout, random);
} }
return new MazeDesign(root, rooms, cores); return new MazeDesign(root, layout);
} }
private static void listRoomPartitions(PartitionNode node, ArrayList<PartitionNode> partitions) private static void attachRooms(PartitionNode<RoomData> node, ArrayList<RoomData> partitions)
{ {
if (node.isLeaf()) if (node.isLeaf())
{ {
partitions.add(node); partitions.add(new RoomData(node));
} }
else else
{ {
listRoomPartitions(node.leftChild(), partitions); attachRooms(node.leftChild(), partitions);
listRoomPartitions(node.rightChild(), partitions); attachRooms(node.rightChild(), partitions);
} }
} }
private static void removeRoomPartitions(PartitionNode node) private static void removeRoom(RoomData room, DirectedGraph<RoomData, DoorwayData> layout)
{ {
// Remove a node and any of its ancestors that become leaf nodes // Remove the room from the partition tree and from the layout graph.
// Also remove any ancestors that become leaf nodes.
PartitionNode parent; PartitionNode parent;
PartitionNode current; PartitionNode current;
current = node; current = room.getPartitionNode();
while (current != null && current.isLeaf()) while (current != null && current.isLeaf())
{ {
parent = current.parent(); parent = current.parent();
current.remove(); current.remove();
current = parent; current = parent;
} }
// Remove the room from the layout graph
layout.removeNode(room.getLayoutNode());
// Wipe the room's data, as a precaution.
room.clear();
} }
private static PartitionNode partitionRooms(int width, int height, int length, int maxLevels, Random random) private static PartitionNode partitionRooms(int width, int height, int length, int maxLevels, Random random)
@@ -140,35 +151,25 @@ public class MazeDesigner
} }
} }
private static DirectedGraph<PartitionNode, DoorwayData> createRoomGraph(PartitionNode root, ArrayList<PartitionNode> partitions, Random random) private static DirectedGraph<RoomData, DoorwayData> createRoomGraph(PartitionNode<RoomData> root, ArrayList<RoomData> rooms, Random random)
{ {
DirectedGraph<PartitionNode, DoorwayData> roomGraph = new DirectedGraph<PartitionNode, DoorwayData>(); DirectedGraph<RoomData, DoorwayData> layout = new DirectedGraph<RoomData, DoorwayData>();
HashMap<PartitionNode, IGraphNode<PartitionNode, DoorwayData>> roomsToGraph = new HashMap<PartitionNode, IGraphNode<PartitionNode, DoorwayData>>(2 * partitions.size());
// Shuffle the list of rooms so that they're not listed in any ordered way in the room graph
// This is the only convenient way of randomizing the maze sections generated later
Collections.shuffle(partitions, random);
// Add all rooms to a graph // Add all rooms to a graph
// Also add them to a map so we can associate rooms with their graph nodes for (RoomData room : rooms)
// The map is needed for linking graph nodes based on adjacent partitions
for (PartitionNode partition : partitions)
{ {
roomsToGraph.put(partition, roomGraph.addNode(partition)); room.addToLayout(layout);
} }
// Add edges for each room // Add edges for each room
for (IGraphNode<PartitionNode, DoorwayData> node : roomGraph.nodes()) for (IGraphNode<RoomData, DoorwayData> node : layout.nodes())
{ {
findDoorways(node, root, roomsToGraph, roomGraph); findDoorways(node.data(), root, layout);
} }
return layout;
return roomGraph;
} }
private static void findDoorways(IGraphNode<PartitionNode, DoorwayData> roomNode, PartitionNode root, private static void findDoorways(RoomData room, PartitionNode<RoomData> root,
HashMap<PartitionNode, IGraphNode<PartitionNode, DoorwayData>> roomsToGraph, DirectedGraph<RoomData, DoorwayData> layout)
DirectedGraph<PartitionNode, DoorwayData> roomGraph)
{ {
// This function finds rooms adjacent to a specified room that could be connected // This function finds rooms adjacent to a specified room that could be connected
// to it through a doorway. Edges are added to the room graph to denote rooms that // to it through a doorway. Edges are added to the room graph to denote rooms that
@@ -186,7 +187,7 @@ public class MazeDesigner
// there will always be a way to walk from any room to any other room. // there will always be a way to walk from any room to any other room.
boolean[][] detected; boolean[][] detected;
PartitionNode adjacent; PartitionNode<RoomData> adjacent;
int a, b, c; int a, b, c;
int p, q, r; int p, q, r;
@@ -195,11 +196,10 @@ public class MazeDesigner
Point3D otherMin; Point3D otherMin;
Point3D otherMax; Point3D otherMax;
DoorwayData doorway; DoorwayData doorway;
IGraphNode<PartitionNode, DoorwayData> adjacentNode;
PartitionNode room = roomNode.data(); PartitionNode partition = room.getPartitionNode();
Point3D minCorner = room.minCorner(); Point3D minCorner = partition.minCorner();
Point3D maxCorner = room.maxCorner(); Point3D maxCorner = partition.maxCorner();
int minX = minCorner.getX(); int minX = minCorner.getX();
int minY = minCorner.getY(); int minY = minCorner.getY();
@@ -209,9 +209,9 @@ public class MazeDesigner
int maxY = maxCorner.getY(); int maxY = maxCorner.getY();
int maxZ = maxCorner.getZ(); int maxZ = maxCorner.getZ();
int width = room.width(); int width = partition.width();
int height = room.height(); int height = partition.height();
int length = room.length(); int length = partition.length();
if (maxZ < root.maxCorner().getZ()) if (maxZ < root.maxCorner().getZ())
{ {
@@ -247,8 +247,7 @@ public class MazeDesigner
otherMin = new Point3D(minXI, minYI, maxZ); otherMin = new Point3D(minXI, minYI, maxZ);
otherMax = new Point3D(maxXI, maxYI, maxZ + 1); otherMax = new Point3D(maxXI, maxYI, maxZ + 1);
doorway = new DoorwayData(otherMin, otherMax, DoorwayData.Z_AXIS); doorway = new DoorwayData(otherMin, otherMax, DoorwayData.Z_AXIS);
adjacentNode = roomsToGraph.get(adjacent); layout.addEdge(room.getLayoutNode(), adjacent.getData().getLayoutNode(), doorway);
roomGraph.addEdge(roomNode, adjacentNode, doorway);
} }
} }
else else
@@ -295,8 +294,7 @@ public class MazeDesigner
otherMin = new Point3D(maxX, minYI, minZI); otherMin = new Point3D(maxX, minYI, minZI);
otherMax = new Point3D(maxX + 1, maxYI, maxZI); otherMax = new Point3D(maxX + 1, maxYI, maxZI);
doorway = new DoorwayData(otherMin, otherMax, DoorwayData.X_AXIS); doorway = new DoorwayData(otherMin, otherMax, DoorwayData.X_AXIS);
adjacentNode = roomsToGraph.get(adjacent); layout.addEdge(room.getLayoutNode(), adjacent.getData().getLayoutNode(), doorway);
roomGraph.addEdge(roomNode, adjacentNode, doorway);
} }
} }
else else
@@ -343,8 +341,7 @@ public class MazeDesigner
otherMin = new Point3D(minXI, maxY, minZI); otherMin = new Point3D(minXI, maxY, minZI);
otherMax = new Point3D(maxXI, maxY + 1, maxZI); otherMax = new Point3D(maxXI, maxY + 1, maxZI);
doorway = new DoorwayData(otherMin, otherMax, DoorwayData.Y_AXIS); doorway = new DoorwayData(otherMin, otherMax, DoorwayData.Y_AXIS);
adjacentNode = roomsToGraph.get(adjacent); layout.addEdge(room.getLayoutNode(), adjacent.getData().getLayoutNode(), doorway);
roomGraph.addEdge(roomNode, adjacentNode, doorway);
} }
} }
else else
@@ -359,7 +356,7 @@ public class MazeDesigner
//Done! //Done!
} }
private static ArrayList<IGraphNode<PartitionNode, DoorwayData>> createMazeSections(DirectedGraph<PartitionNode, DoorwayData> roomGraph, Random random) private static ArrayList<RoomData> createMazeSections(DirectedGraph<RoomData, DoorwayData> layout, Random random)
{ {
// The randomness of the sections generated here hinges on // The randomness of the sections generated here hinges on
// the nodes in the graph being in a random order. We assume // the nodes in the graph being in a random order. We assume
@@ -369,66 +366,68 @@ public class MazeDesigner
final int MIN_SECTION_ROOMS = 5; final int MIN_SECTION_ROOMS = 5;
int distance; int distance;
IGraphNode<PartitionNode, DoorwayData> current; RoomData room;
IGraphNode<PartitionNode, DoorwayData> neighbor; RoomData neighbor;
IGraphNode<RoomData, DoorwayData> current;
ArrayList<IGraphNode<PartitionNode, DoorwayData>> cores = new ArrayList<IGraphNode<PartitionNode, DoorwayData>>(); ArrayList<RoomData> cores = new ArrayList<RoomData>();
ArrayList<IGraphNode<PartitionNode, DoorwayData>> removals = new ArrayList<IGraphNode<PartitionNode, DoorwayData>>(); ArrayList<RoomData> removals = new ArrayList<RoomData>();
ArrayList<IGraphNode<PartitionNode, DoorwayData>> section = new ArrayList<IGraphNode<PartitionNode, DoorwayData>>(); ArrayList<RoomData> section = new ArrayList<RoomData>();
Queue<IGraphNode<PartitionNode, DoorwayData>> ordering = new LinkedList<IGraphNode<PartitionNode, DoorwayData>>(); Queue<RoomData> ordering = new LinkedList<RoomData>();
HashMap<IGraphNode<PartitionNode, DoorwayData>, Integer> distances = new HashMap<IGraphNode<PartitionNode, DoorwayData>, Integer>();
// Repeatedly generate sections until all nodes have been visited // Repeatedly generate sections until all nodes have been visited
for (IGraphNode<PartitionNode, DoorwayData> node : roomGraph.nodes()) for (IGraphNode<RoomData, DoorwayData> node : layout.nodes())
{ {
// If this node hasn't been visited, then use it as the core of a new section // If this room hasn't been visited (distance = -1), then use it as the core of a new section
// Otherwise, ignore it, since it was already processed // Otherwise, ignore it, since it was already processed
if (!distances.containsKey(node)) room = node.data();
if (room.getDistance() < 0)
{ {
// Perform a breadth-first search to tag surrounding nodes with distances // Perform a breadth-first search to tag surrounding nodes with distances
distances.put(node, 0); room.setDistance(0);
ordering.add(node); ordering.add(room);
section.clear(); section.clear();
while (!ordering.isEmpty()) while (!ordering.isEmpty())
{ {
current = ordering.remove(); room = ordering.remove();
distance = distances.get(current) + 1; distance = room.getDistance() + 1;
if (distance <= MAX_DISTANCE + 1) if (distance <= MAX_DISTANCE + 1)
{ {
section.add(current); section.add(room);
current = room.getLayoutNode();
// Visit neighboring nodes and assign them distances, if they don't // Visit neighboring rooms and assign them distances, if they don't
// have a distance assigned already // have a proper distance assigned already
for (IEdge<PartitionNode, DoorwayData> edge : current.inbound()) for (IEdge<RoomData, DoorwayData> edge : current.inbound())
{ {
neighbor = edge.head(); neighbor = edge.head().data();
if (!distances.containsKey(neighbor)) if (neighbor.getDistance() < 0)
{ {
distances.put(neighbor, distance); neighbor.setDistance(distance);
ordering.add(neighbor); ordering.add(neighbor);
} }
} }
for (IEdge<PartitionNode, DoorwayData> edge : current.outbound()) for (IEdge<RoomData, DoorwayData> edge : current.outbound())
{ {
neighbor = edge.tail(); neighbor = edge.tail().data();
if (!distances.containsKey(neighbor)) if (neighbor.getDistance() < 0)
{ {
distances.put(neighbor, distance); neighbor.setDistance(distance);
ordering.add(neighbor); ordering.add(neighbor);
} }
} }
} }
else else
{ {
removals.add(current); removals.add(room);
break; break;
} }
} }
// List nodes that have a distance of exactly MAX_DISTANCE + 1 // List rooms that have a distance of exactly MAX_DISTANCE + 1
// Those are precisely the nodes that remain in the queue // Those are precisely the nodes that remain in the queue
// We can't remove them immediately because that could break // We can't remove them immediately because that could break
// the iterator for the graph. // the iterator for the graph.
@@ -440,7 +439,7 @@ public class MazeDesigner
// Check if this section contains enough rooms // Check if this section contains enough rooms
if (section.size() >= MIN_SECTION_ROOMS) if (section.size() >= MIN_SECTION_ROOMS)
{ {
cores.add(node); cores.add(node.data());
} }
else else
{ {
@@ -449,18 +448,17 @@ public class MazeDesigner
} }
} }
// Remove all the nodes that were listed for removal // Remove all the rooms that were listed for removal
// Also remove unused partitions from the partition tree // Also remove unused partitions from the partition tree
for (IGraphNode<PartitionNode, DoorwayData> node : removals) for (RoomData target : removals)
{ {
removeRoomPartitions(node.data()); removeRoom(target, layout);
roomGraph.removeNode(node);
} }
return cores; return cores;
} }
private static void pruneDoorways(IGraphNode<PartitionNode, DoorwayData> core, private static void pruneDoorways(IGraphNode<RoomData, DoorwayData> core,
DirectedGraph<PartitionNode, DoorwayData> rooms, Random random) DirectedGraph<RoomData, DoorwayData> layout, 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
// and we need to remove as many floor doorways as possible while // and we need to remove as many floor doorways as possible while
@@ -478,12 +476,12 @@ public class MazeDesigner
// idea applies for the other doorways, plus some randomness. // idea applies for the other doorways, plus some randomness.
// First, list all nodes in the subgraph // First, list all nodes in the subgraph
IGraphNode<PartitionNode, DoorwayData> current; IGraphNode<RoomData, DoorwayData> current;
IGraphNode<PartitionNode, DoorwayData> neighbor; IGraphNode<RoomData, DoorwayData> neighbor;
Stack<IGraphNode<PartitionNode, DoorwayData>> ordering = new Stack<IGraphNode<PartitionNode, DoorwayData>>(); Stack<IGraphNode<RoomData, DoorwayData>> ordering = new Stack<IGraphNode<RoomData, DoorwayData>>();
ArrayList<IGraphNode<PartitionNode, DoorwayData>> subgraph = new ArrayList<IGraphNode<PartitionNode, DoorwayData>>(64); ArrayList<IGraphNode<RoomData, DoorwayData>> subgraph = new ArrayList<IGraphNode<RoomData, DoorwayData>>(64);
DisjointSet<IGraphNode<PartitionNode, DoorwayData>> components = new DisjointSet<IGraphNode<PartitionNode, DoorwayData>>(128); DisjointSet<IGraphNode<RoomData, DoorwayData>> components = new DisjointSet<IGraphNode<RoomData, DoorwayData>>(128);
ordering.add(core); ordering.add(core);
components.makeSet(core); components.makeSet(core);
@@ -492,7 +490,7 @@ public class MazeDesigner
current = ordering.pop(); current = ordering.pop();
subgraph.add(current); subgraph.add(current);
for (IEdge<PartitionNode, DoorwayData> edge : current.inbound()) for (IEdge<RoomData, DoorwayData> edge : current.inbound())
{ {
neighbor = edge.head(); neighbor = edge.head();
if (components.makeSet(neighbor)) if (components.makeSet(neighbor))
@@ -500,7 +498,7 @@ public class MazeDesigner
ordering.add(neighbor); ordering.add(neighbor);
} }
} }
for (IEdge<PartitionNode, DoorwayData> edge : current.outbound()) for (IEdge<RoomData, DoorwayData> edge : current.outbound())
{ {
neighbor = edge.tail(); neighbor = edge.tail();
if (components.makeSet(neighbor)) if (components.makeSet(neighbor))
@@ -513,12 +511,12 @@ public class MazeDesigner
// Now iterate over the list of nodes and merge their sets // Now iterate over the list of nodes and merge their sets
// We only have to look at outbound edges since inbound edges mirror them // We only have to look at outbound edges since inbound edges mirror them
// Also list any Y_AXIS doorways we come across // Also list any Y_AXIS doorways we come across
ArrayList<IEdge<PartitionNode, DoorwayData>> targets = ArrayList<IEdge<RoomData, DoorwayData>> targets =
new ArrayList<IEdge<PartitionNode, DoorwayData>>(); new ArrayList<IEdge<RoomData, DoorwayData>>();
for (IGraphNode<PartitionNode, DoorwayData> room : subgraph) for (IGraphNode<RoomData, DoorwayData> room : subgraph)
{ {
for (IEdge<PartitionNode, DoorwayData> passage : room.outbound()) for (IEdge<RoomData, DoorwayData> passage : room.outbound())
{ {
if (passage.data().axis() != DoorwayData.Y_AXIS) if (passage.data().axis() != DoorwayData.Y_AXIS)
{ {
@@ -535,11 +533,11 @@ public class MazeDesigner
Collections.shuffle(targets, random); Collections.shuffle(targets, random);
// Merge sets together and remove unnecessary doorways // Merge sets together and remove unnecessary doorways
for (IEdge<PartitionNode, DoorwayData> passage : targets) for (IEdge<RoomData, DoorwayData> passage : targets)
{ {
if (!components.mergeSets(passage.head(), passage.tail())) if (!components.mergeSets(passage.head(), passage.tail()))
{ {
rooms.removeEdge(passage); layout.removeEdge(passage);
} }
} }
@@ -548,13 +546,13 @@ public class MazeDesigner
components.clear(); components.clear();
targets.clear(); targets.clear();
for (IGraphNode<PartitionNode, DoorwayData> room : subgraph) for (IGraphNode<RoomData, DoorwayData> room : subgraph)
{ {
components.makeSet(room); components.makeSet(room);
} }
for (IGraphNode<PartitionNode, DoorwayData> room : subgraph) for (IGraphNode<RoomData, DoorwayData> room : subgraph)
{ {
for (IEdge<PartitionNode, DoorwayData> passage : room.outbound()) for (IEdge<RoomData, DoorwayData> passage : room.outbound())
{ {
if (passage.data().axis() == DoorwayData.Y_AXIS) if (passage.data().axis() == DoorwayData.Y_AXIS)
{ {
@@ -567,11 +565,11 @@ public class MazeDesigner
} }
} }
Collections.shuffle(targets, random); Collections.shuffle(targets, random);
for (IEdge<PartitionNode, DoorwayData> passage : targets) for (IEdge<RoomData, DoorwayData> passage : targets)
{ {
if (!components.mergeSets(passage.head(), passage.tail()) && random.nextBoolean()) if (!components.mergeSets(passage.head(), passage.tail()) && random.nextBoolean())
{ {
rooms.removeEdge(passage); layout.removeEdge(passage);
} }
} }
} }

View File

@@ -0,0 +1,6 @@
package StevenDimDoors.experimental;
public class MazeLinkData
{
}

View File

@@ -2,11 +2,12 @@ package StevenDimDoors.experimental;
import StevenDimDoors.mod_pocketDim.Point3D; import StevenDimDoors.mod_pocketDim.Point3D;
public class PartitionNode extends BoundingBox public class PartitionNode<T> extends BoundingBox
{ {
private PartitionNode parent; private PartitionNode parent;
private PartitionNode leftChild = null; private PartitionNode leftChild = null;
private PartitionNode rightChild = null; private PartitionNode rightChild = null;
private T data = null;
public PartitionNode(int width, int height, int length) public PartitionNode(int width, int height, int length)
{ {
@@ -122,4 +123,14 @@ public class PartitionNode extends BoundingBox
return this; return this;
} }
} }
public void setData(T value)
{
this.data = value;
}
public T getData()
{
return data;
}
} }

View File

@@ -0,0 +1,75 @@
package StevenDimDoors.experimental;
import java.util.ArrayList;
public class RoomData
{
private int distance;
private boolean decayed;
private PartitionNode partitionNode;
private ArrayList<MazeLinkData> inboundLinks;
private ArrayList<MazeLinkData> outboundLinks;
private IGraphNode<RoomData, DoorwayData> layoutNode;
public RoomData(PartitionNode partitionNode)
{
this.partitionNode = partitionNode;
this.inboundLinks = new ArrayList<MazeLinkData>();
this.outboundLinks = new ArrayList<MazeLinkData>();
this.layoutNode = null;
this.distance = -1;
this.decayed = false;
partitionNode.setData(this);
}
public PartitionNode getPartitionNode()
{
return this.partitionNode;
}
public IGraphNode<RoomData, DoorwayData> getLayoutNode()
{
return this.layoutNode;
}
public void addToLayout(DirectedGraph<RoomData, DoorwayData> layout)
{
this.layoutNode = layout.addNode(this);
}
public boolean isDecayed()
{
return decayed;
}
public void setDecayed(boolean value)
{
this.decayed = value;
}
public ArrayList<MazeLinkData> getInboundLinks()
{
return this.inboundLinks;
}
public ArrayList<MazeLinkData> getOutboundLinks()
{
return this.outboundLinks;
}
public int getDistance()
{
return distance;
}
public void setDistance(int value)
{
distance = value;
}
public void clear()
{
partitionNode = null;
layoutNode = null;
}
}