Mazes #117
@@ -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,7 +143,9 @@ public class MazeGenerator
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (node.leftChild() != null)
|
||||||
buildRooms(node.leftChild(), world, offset);
|
buildRooms(node.leftChild(), world, offset);
|
||||||
|
if (node.rightChild() != null)
|
||||||
buildRooms(node.rightChild(), world, offset);
|
buildRooms(node.rightChild(), world, offset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user