Mazes #117
@@ -1,5 +1,7 @@
|
||||
package StevenDimDoors.experimental;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Random;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
@@ -13,18 +15,60 @@ public class MazeGenerator
|
||||
{
|
||||
public static final int ROOT_WIDTH = 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_SIDE = 3;
|
||||
private static final int SPLIT_COUNT = 8;
|
||||
private static final int SPLIT_COUNT = 9;
|
||||
|
||||
private MazeGenerator() { }
|
||||
|
||||
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);
|
||||
// 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));
|
||||
}
|
||||
|
||||
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)
|
||||
@@ -99,8 +143,10 @@ public class MazeGenerator
|
||||
}
|
||||
else
|
||||
{
|
||||
buildRooms(node.leftChild(), world, offset);
|
||||
buildRooms(node.rightChild(), world, offset);
|
||||
if (node.leftChild() != null)
|
||||
buildRooms(node.leftChild(), world, offset);
|
||||
if (node.rightChild() != null)
|
||||
buildRooms(node.rightChild(), world, offset);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,17 +6,20 @@ public class SpatialNode
|
||||
{
|
||||
private Point3D minCorner;
|
||||
private Point3D maxCorner;
|
||||
private SpatialNode parent;
|
||||
private SpatialNode leftChild = null;
|
||||
private SpatialNode rightChild = null;
|
||||
|
||||
public SpatialNode(int width, int height, int length)
|
||||
{
|
||||
parent = null;
|
||||
minCorner = new Point3D(0, 0, 0);
|
||||
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.maxCorner = maxCorner;
|
||||
}
|
||||
@@ -38,7 +41,7 @@ public class SpatialNode
|
||||
|
||||
public boolean isLeaf()
|
||||
{
|
||||
return (leftChild == null);
|
||||
return (leftChild == null && rightChild == null);
|
||||
}
|
||||
|
||||
public SpatialNode leftChild()
|
||||
@@ -61,9 +64,14 @@ public class SpatialNode
|
||||
return maxCorner;
|
||||
}
|
||||
|
||||
public SpatialNode parent()
|
||||
{
|
||||
return parent;
|
||||
}
|
||||
|
||||
public void splitByX(int rightStart)
|
||||
{
|
||||
if (leftChild != null)
|
||||
if (!this.isLeaf())
|
||||
{
|
||||
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.");
|
||||
}
|
||||
leftChild = new SpatialNode(minCorner, new Point3D(rightStart - 1, maxCorner.getY(), maxCorner.getZ()));
|
||||
rightChild = new SpatialNode(new Point3D(rightStart, minCorner.getY(), minCorner.getZ()), maxCorner);
|
||||
leftChild = new SpatialNode(this, minCorner, new Point3D(rightStart - 1, maxCorner.getY(), maxCorner.getZ()));
|
||||
rightChild = new SpatialNode(this, new Point3D(rightStart, minCorner.getY(), minCorner.getZ()), maxCorner);
|
||||
}
|
||||
|
||||
public void splitByY(int rightStart)
|
||||
{
|
||||
if (leftChild != null)
|
||||
if (!this.isLeaf())
|
||||
{
|
||||
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.");
|
||||
}
|
||||
leftChild = new SpatialNode(minCorner, new Point3D(maxCorner.getX(), rightStart - 1, maxCorner.getZ()));
|
||||
rightChild = new SpatialNode(new Point3D(minCorner.getX(), rightStart, minCorner.getZ()), maxCorner);
|
||||
leftChild = new SpatialNode(this, minCorner, new Point3D(maxCorner.getX(), rightStart - 1, maxCorner.getZ()));
|
||||
rightChild = new SpatialNode(this, new Point3D(minCorner.getX(), rightStart, minCorner.getZ()), maxCorner);
|
||||
}
|
||||
|
||||
public void splitByZ(int rightStart)
|
||||
{
|
||||
if (leftChild != null)
|
||||
if (!this.isLeaf())
|
||||
{
|
||||
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.");
|
||||
}
|
||||
leftChild = new SpatialNode(minCorner, new Point3D(maxCorner.getX(), maxCorner.getY(), rightStart - 1));
|
||||
rightChild = new SpatialNode(new Point3D(minCorner.getX(), minCorner.getY(), rightStart), maxCorner);
|
||||
leftChild = new SpatialNode(this, minCorner, new Point3D(maxCorner.getX(), maxCorner.getY(), rightStart - 1));
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user