More Maze Generation

Made some changes to maze generation to prune out random rooms from the
structure. This doesn't look as nice as I'd hoped, so I'm going to try
some other approaches.
This commit is contained in:
SenseiKiwi
2013-12-27 03:11:59 -04:00
parent 82da53b992
commit a9f0bc5069
2 changed files with 81 additions and 15 deletions

View File

@@ -1,5 +1,7 @@
package StevenDimDoors.experimental; package StevenDimDoors.experimental;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Random; import java.util.Random;
import net.minecraft.block.Block; import net.minecraft.block.Block;
@@ -13,18 +15,60 @@ public class MazeGenerator
{ {
public static final int ROOT_WIDTH = 40; public static final int ROOT_WIDTH = 40;
public static final int ROOT_LENGTH = 40; public static final int ROOT_LENGTH = 40;
public static final int ROOT_HEIGHT = 19; public static final int ROOT_HEIGHT = 20;
private static final int MIN_HEIGHT = 4; private static final int MIN_HEIGHT = 4;
private static final int MIN_SIDE = 3; private static final int MIN_SIDE = 3;
private static final int SPLIT_COUNT = 8; private static final int SPLIT_COUNT = 9;
private MazeGenerator() { } private MazeGenerator() { }
public static void generate(World world, int x, int y, int z, Random random) public static void generate(World world, int x, int y, int z, Random random)
{ {
SpatialNode root = partitionRooms(ROOT_WIDTH, ROOT_HEIGHT, ROOT_LENGTH, SPLIT_COUNT, random); SpatialNode root = partitionRooms(ROOT_WIDTH, ROOT_HEIGHT, ROOT_LENGTH, SPLIT_COUNT, random);
// Collect all the leaf nodes by performing a tree traversal
ArrayList<SpatialNode> rooms = new ArrayList<SpatialNode>(1 << SPLIT_COUNT);
listRooms(root, rooms);
removeRandomRooms(rooms, random);
buildRooms(root, world, new Point3D(x - ROOT_WIDTH / 2, y - ROOT_HEIGHT - 1, z - ROOT_WIDTH / 2)); buildRooms(root, world, new Point3D(x - ROOT_WIDTH / 2, y - ROOT_HEIGHT - 1, z - ROOT_WIDTH / 2));
}
private static void listRooms(SpatialNode node, ArrayList<SpatialNode> rooms)
{
if (node.isLeaf())
{
rooms.add(node);
}
else
{
listRooms(node.leftChild(), rooms);
listRooms(node.rightChild(), rooms);
}
}
private static void removeRandomRooms(ArrayList<SpatialNode> rooms, Random random)
{
// Randomly remove a fraction of the rooms
Collections.shuffle(rooms, random);
int remaining = rooms.size() / 2;
for (int k = rooms.size() - 1; k >= remaining; k--)
{
removeRoom(rooms.remove(k));
}
}
private static void removeRoom(SpatialNode node)
{
// Remove a node and any of its ancestors that become leaf nodes
SpatialNode parent;
SpatialNode current;
current = node;
while (current != null && current.isLeaf())
{
parent = current.parent();
current.remove();
current = parent;
}
} }
private static SpatialNode partitionRooms(int width, int height, int length, int maxLevels, Random random) private static SpatialNode partitionRooms(int width, int height, int length, int maxLevels, Random random)
@@ -99,8 +143,10 @@ public class MazeGenerator
} }
else else
{ {
buildRooms(node.leftChild(), world, offset); if (node.leftChild() != null)
buildRooms(node.rightChild(), world, offset); buildRooms(node.leftChild(), world, offset);
if (node.rightChild() != null)
buildRooms(node.rightChild(), world, offset);
} }
} }

View File

@@ -6,17 +6,20 @@ public class SpatialNode
{ {
private Point3D minCorner; private Point3D minCorner;
private Point3D maxCorner; private Point3D maxCorner;
private SpatialNode parent;
private SpatialNode leftChild = null; private SpatialNode leftChild = null;
private SpatialNode rightChild = null; private SpatialNode rightChild = null;
public SpatialNode(int width, int height, int length) public SpatialNode(int width, int height, int length)
{ {
parent = null;
minCorner = new Point3D(0, 0, 0); minCorner = new Point3D(0, 0, 0);
maxCorner = new Point3D(width - 1, height - 1, length - 1); maxCorner = new Point3D(width - 1, height - 1, length - 1);
} }
private SpatialNode(Point3D minCorner, Point3D maxCorner) private SpatialNode(SpatialNode parent, Point3D minCorner, Point3D maxCorner)
{ {
this.parent = parent;
this.minCorner = minCorner; this.minCorner = minCorner;
this.maxCorner = maxCorner; this.maxCorner = maxCorner;
} }
@@ -38,7 +41,7 @@ public class SpatialNode
public boolean isLeaf() public boolean isLeaf()
{ {
return (leftChild == null); return (leftChild == null && rightChild == null);
} }
public SpatialNode leftChild() public SpatialNode leftChild()
@@ -61,9 +64,14 @@ public class SpatialNode
return maxCorner; return maxCorner;
} }
public SpatialNode parent()
{
return parent;
}
public void splitByX(int rightStart) public void splitByX(int rightStart)
{ {
if (leftChild != null) if (!this.isLeaf())
{ {
throw new IllegalStateException("This node has already been split."); throw new IllegalStateException("This node has already been split.");
} }
@@ -71,13 +79,13 @@ public class SpatialNode
{ {
throw new IllegalArgumentException("The specified cutting plane is invalid."); throw new IllegalArgumentException("The specified cutting plane is invalid.");
} }
leftChild = new SpatialNode(minCorner, new Point3D(rightStart - 1, maxCorner.getY(), maxCorner.getZ())); leftChild = new SpatialNode(this, minCorner, new Point3D(rightStart - 1, maxCorner.getY(), maxCorner.getZ()));
rightChild = new SpatialNode(new Point3D(rightStart, minCorner.getY(), minCorner.getZ()), maxCorner); rightChild = new SpatialNode(this, new Point3D(rightStart, minCorner.getY(), minCorner.getZ()), maxCorner);
} }
public void splitByY(int rightStart) public void splitByY(int rightStart)
{ {
if (leftChild != null) if (!this.isLeaf())
{ {
throw new IllegalStateException("This node has already been split."); throw new IllegalStateException("This node has already been split.");
} }
@@ -85,13 +93,13 @@ public class SpatialNode
{ {
throw new IllegalArgumentException("The specified cutting plane is invalid."); throw new IllegalArgumentException("The specified cutting plane is invalid.");
} }
leftChild = new SpatialNode(minCorner, new Point3D(maxCorner.getX(), rightStart - 1, maxCorner.getZ())); leftChild = new SpatialNode(this, minCorner, new Point3D(maxCorner.getX(), rightStart - 1, maxCorner.getZ()));
rightChild = new SpatialNode(new Point3D(minCorner.getX(), rightStart, minCorner.getZ()), maxCorner); rightChild = new SpatialNode(this, new Point3D(minCorner.getX(), rightStart, minCorner.getZ()), maxCorner);
} }
public void splitByZ(int rightStart) public void splitByZ(int rightStart)
{ {
if (leftChild != null) if (!this.isLeaf())
{ {
throw new IllegalStateException("This node has already been split."); throw new IllegalStateException("This node has already been split.");
} }
@@ -99,7 +107,19 @@ public class SpatialNode
{ {
throw new IllegalArgumentException("The specified cutting plane is invalid."); throw new IllegalArgumentException("The specified cutting plane is invalid.");
} }
leftChild = new SpatialNode(minCorner, new Point3D(maxCorner.getX(), maxCorner.getY(), rightStart - 1)); leftChild = new SpatialNode(this, minCorner, new Point3D(maxCorner.getX(), maxCorner.getY(), rightStart - 1));
rightChild = new SpatialNode(new Point3D(minCorner.getX(), minCorner.getY(), rightStart), maxCorner); rightChild = new SpatialNode(this, new Point3D(minCorner.getX(), minCorner.getY(), rightStart), maxCorner);
}
public void remove()
{
if (parent != null)
{
if (parent.leftChild == this)
parent.leftChild = null;
else
parent.rightChild = null;
parent = null;
}
} }
} }