Mazes #155
@@ -2,7 +2,6 @@ package StevenDimDoors.experimental;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.Queue;
|
import java.util.Queue;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
@@ -362,13 +361,23 @@ public class MazeDesigner
|
|||||||
// the nodes in the graph being in a random order. We assume
|
// the nodes in the graph being in a random order. We assume
|
||||||
// that was handled in a previous step!
|
// that was handled in a previous step!
|
||||||
|
|
||||||
|
// We split the maze into sections by choosing core rooms and removing
|
||||||
|
// rooms that are a certain number of doorways away. However, for a section
|
||||||
|
// to be valid, it must also have enough space for at least two doors in
|
||||||
|
// rooms without floor holes. If a section can't fit two doors, more
|
||||||
|
// neighboring rooms are added until the necessary space is found or the
|
||||||
|
// search space is exhausted.
|
||||||
|
|
||||||
final int MAX_DISTANCE = 2;
|
final int MAX_DISTANCE = 2;
|
||||||
final int MIN_SECTION_ROOMS = 5;
|
final int MIN_SECTION_ROOMS = 5;
|
||||||
|
final int MIN_SECTION_CAPACITY = 2;
|
||||||
|
|
||||||
int distance;
|
int distance;
|
||||||
|
int capacity;
|
||||||
RoomData room;
|
RoomData room;
|
||||||
RoomData neighbor;
|
RoomData neighbor;
|
||||||
IGraphNode<RoomData, DoorwayData> current;
|
boolean hasHoles;
|
||||||
|
IGraphNode<RoomData, DoorwayData> roomNode;
|
||||||
|
|
||||||
ArrayList<RoomData> cores = new ArrayList<RoomData>();
|
ArrayList<RoomData> cores = new ArrayList<RoomData>();
|
||||||
ArrayList<RoomData> removals = new ArrayList<RoomData>();
|
ArrayList<RoomData> removals = new ArrayList<RoomData>();
|
||||||
@@ -385,23 +394,23 @@ public class MazeDesigner
|
|||||||
if (room.getDistance() < 0)
|
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
|
||||||
room.setDistance(0);
|
|
||||||
ordering.add(room);
|
ordering.add(room);
|
||||||
|
room.setDistance(0);
|
||||||
section.clear();
|
section.clear();
|
||||||
|
capacity = 0;
|
||||||
|
|
||||||
while (!ordering.isEmpty())
|
while (room != null && (room.getDistance() <= MAX_DISTANCE || capacity < 2))
|
||||||
{
|
|
||||||
room = ordering.remove();
|
|
||||||
distance = room.getDistance() + 1;
|
|
||||||
|
|
||||||
if (distance <= MAX_DISTANCE + 1)
|
|
||||||
{
|
{
|
||||||
|
ordering.remove();
|
||||||
section.add(room);
|
section.add(room);
|
||||||
current = room.getLayoutNode();
|
roomNode = room.getLayoutNode();
|
||||||
|
distance = room.getDistance() + 1;
|
||||||
|
hasHoles = false;
|
||||||
|
|
||||||
// Visit neighboring rooms and assign them distances, if they don't
|
// Visit neighboring rooms and assign them distances,
|
||||||
// have a proper distance assigned already
|
// if they don't have a proper distance assigned already.
|
||||||
for (IEdge<RoomData, DoorwayData> edge : current.inbound())
|
// Also check for floor holes.
|
||||||
|
for (IEdge<RoomData, DoorwayData> edge : roomNode.inbound())
|
||||||
{
|
{
|
||||||
neighbor = edge.head().data();
|
neighbor = edge.head().data();
|
||||||
if (neighbor.getDistance() < 0)
|
if (neighbor.getDistance() < 0)
|
||||||
@@ -409,8 +418,12 @@ public class MazeDesigner
|
|||||||
neighbor.setDistance(distance);
|
neighbor.setDistance(distance);
|
||||||
ordering.add(neighbor);
|
ordering.add(neighbor);
|
||||||
}
|
}
|
||||||
|
if (edge.data().axis() == DoorwayData.Y_AXIS)
|
||||||
|
{
|
||||||
|
hasHoles = true;
|
||||||
}
|
}
|
||||||
for (IEdge<RoomData, DoorwayData> edge : current.outbound())
|
}
|
||||||
|
for (IEdge<RoomData, DoorwayData> edge : roomNode.outbound())
|
||||||
{
|
{
|
||||||
neighbor = edge.tail().data();
|
neighbor = edge.tail().data();
|
||||||
if (neighbor.getDistance() < 0)
|
if (neighbor.getDistance() < 0)
|
||||||
@@ -419,25 +432,29 @@ public class MazeDesigner
|
|||||||
ordering.add(neighbor);
|
ordering.add(neighbor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
// Count this room's door capacity if it has no floor holes
|
||||||
|
if (!hasHoles)
|
||||||
{
|
{
|
||||||
removals.add(room);
|
capacity += room.estimateDoorCapacity();
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// List rooms that have a distance of exactly MAX_DISTANCE + 1
|
room = ordering.peek();
|
||||||
// Those are precisely the nodes that remain in the queue
|
|
||||||
// We can't remove them immediately because that could break
|
|
||||||
// the iterator for the graph.
|
|
||||||
while (!ordering.isEmpty())
|
|
||||||
{
|
|
||||||
removals.add(ordering.remove());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if this section contains enough rooms
|
// The remaining rooms in the ordering are those that are at the
|
||||||
if (section.size() >= MIN_SECTION_ROOMS)
|
// frontier of structure. They must be removed to create a gap
|
||||||
|
// between this section and other sections. But we can't remove
|
||||||
|
// the rooms immediately because that could break the iterator
|
||||||
|
// for the graph.
|
||||||
|
if (!ordering.isEmpty())
|
||||||
|
{
|
||||||
|
removals.addAll(ordering);
|
||||||
|
ordering.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if this section contains enough rooms and capacity for doors
|
||||||
|
if (section.size() >= MIN_SECTION_ROOMS && capacity >= MIN_SECTION_CAPACITY)
|
||||||
{
|
{
|
||||||
cores.add(node.data());
|
cores.add(node.data());
|
||||||
}
|
}
|
||||||
@@ -449,7 +466,6 @@ public class MazeDesigner
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Remove all the rooms that were listed for removal
|
// Remove all the rooms that were listed for removal
|
||||||
// Also remove unused partitions from the partition tree
|
|
||||||
for (RoomData target : removals)
|
for (RoomData target : removals)
|
||||||
{
|
{
|
||||||
removeRoom(target, layout);
|
removeRoom(target, layout);
|
||||||
@@ -508,9 +524,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 based on
|
||||||
// We only have to look at outbound edges since inbound edges mirror them
|
// being connected by X_AXIS or Z_AXIS doorways. We only have to look
|
||||||
// Also list any Y_AXIS doorways we come across
|
// at outbound edges since inbound edges mirror them. List any Y_AXIS
|
||||||
|
// doorways we come across to consider removing them later, depending
|
||||||
|
// on their impact on connectedness.
|
||||||
|
// doorways.
|
||||||
ArrayList<IEdge<RoomData, DoorwayData>> targets =
|
ArrayList<IEdge<RoomData, DoorwayData>> targets =
|
||||||
new ArrayList<IEdge<RoomData, DoorwayData>>();
|
new ArrayList<IEdge<RoomData, DoorwayData>>();
|
||||||
|
|
||||||
|
|||||||
@@ -72,4 +72,11 @@ public class RoomData
|
|||||||
partitionNode = null;
|
partitionNode = null;
|
||||||
layoutNode = null;
|
layoutNode = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int estimateDoorCapacity()
|
||||||
|
{
|
||||||
|
int cellsX = (partitionNode.width() - 3) / 2;
|
||||||
|
int cellsZ = (partitionNode.length() - 3) / 2;
|
||||||
|
return Math.min(cellsX * cellsZ, 3);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user