diff --git a/.idea/workspace.xml b/.idea/workspace.xml
index 64da3ec..72aa50a 100644
--- a/.idea/workspace.xml
+++ b/.idea/workspace.xml
@@ -4,10 +4,13 @@
-
-
+
+
+
+
+
@@ -33,6 +36,9 @@
+
+
+ {
"associatedIndex": 2
}
@@ -174,7 +180,15 @@
1729358883715
-
+
+
+ 1729362135731
+
+
+
+ 1729362135731
+
+
@@ -219,6 +233,8 @@
-
+
+
+
\ No newline at end of file
diff --git a/src/main/kotlin/Mazefinder.kt b/src/main/kotlin/Mazefinder.kt
index 2e8b910..928c2d9 100644
--- a/src/main/kotlin/Mazefinder.kt
+++ b/src/main/kotlin/Mazefinder.kt
@@ -1,5 +1,8 @@
package technology.zim
+import technology.zim.data.Directions
+import technology.zim.data.Tile
+
//Build the maze
//Options:
@@ -8,13 +11,69 @@ package technology.zim
//Wall-builder?
//https://emmilco.github.io/path_finder/
-//Needs https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/PriorityQueue.html
-//and https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/Comparator.html
-
//http://weblog.jamisbuck.org/2011/1/10/maze-generation-prim-s-algorithm
//http://weblog.jamisbuck.org/2011/1/3/maze-generation-kruskal-s-algorithm
-class Mazefinder {
+class MazeFinder {
+ val visited = ArrayList>(World.tiles.data.size).apply {
+ this.forEach() { element -> element.fill(false) }
+ }
+ val frontier = mutableSetOf()
+
+ fun primsAlgorithm() {
+ //Choose an arbitrary vertex from G (the graph), and add it to some (initially empty) set V.
+ frontier.add(World.getRandomLocation())
+
+ //Choose a random edge from G, that connects a vertex in V with another vertex not in V.
+ var current: Tile
+ var prospect: Pair
+ var possibleTiles: Set>
+ while(frontier.isNotEmpty()) {
+ //Grab a random tile from the frontier, mark it as visited
+ current = frontier.random()
+ frontier.remove(current)
+ visited[current.value.first][current.value.second] = true
+
+ //Find all adjacent tiles to that tile
+ possibleTiles = getUnexploredAdjacent(current)
+
+ //It's possible that this frontier tile has no unexplored neighbors, in which case removing it from the frontier is enough
+ if(possibleTiles.isNotEmpty()) {
+ //Grab a random tile from the possible set
+ prospect = possibleTiles.random()
+
+ //Connect it to the current tile
+ current.connect(prospect.second)
+
+ //Add its adjacent unexplored tiles to frontier
+ frontier.addAll(getUnexploredAdjacentWithoutDirection(prospect.first))
+ }
+ }
+ }
+
+ fun getUnexploredAdjacentWithoutDirection(tile: Tile): Set {
+ val result = mutableSetOf()
+ getUnexploredAdjacent(tile).forEach { pair -> result.add(pair.first)}
+ return result
+ }
+
+ fun getUnexploredAdjacent(tile: Tile): Set> {
+ val adj = mutableSetOf>()
+ val dirs = Directions.NORTH.all()
+
+ dirs.forEach { dir ->
+ val candidateTile = tile + dir
+ //Ensure that the tile is within bounds
+ if(candidateTile.isInBounds() && !visited[candidateTile.value.first][candidateTile.value.second])
+ {
+ adj.add(Pair(candidateTile, dir))
+ }
+ }
+ return adj
+ }
+ //Todo: Consider growing World with null values, then use Mazefinder to instantiate as the maze is developed
+ //Consequence: World becomes nullable, requiring null checks to be added in order to avoid... issues
+ //It's probable that this will only be needed at large scales
}
\ No newline at end of file
diff --git a/src/main/kotlin/World.kt b/src/main/kotlin/World.kt
index 5f4ff48..066edee 100644
--- a/src/main/kotlin/World.kt
+++ b/src/main/kotlin/World.kt
@@ -1,11 +1,13 @@
package technology.zim
-import technology.zim.data.Directions
import technology.zim.data.Tile
import technology.zim.data.TileProperties
import technology.zim.data.WorldData
import java.util.*
+//Singleton object containing a set of tiles
+//Has helper functions included
+
//For now, keep it small with uncompresed tile representation
//In the future, this could be stored in a gzipped file and memory mapped
@@ -15,37 +17,22 @@ import java.util.*
// Which currently only contains the edges of the "graph", stored as directions
object World {
- val tiles = WorldData(ArrayList>())
+ //Default size should be 20
+ val tiles = WorldData(ArrayList>(20))
//Returns a coordinate pair
fun getRandomLocation(): Tile {
return Tile(Pair((0..tiles.data.size).random(), (0..tiles.data[0].size).random()))
}
- //Get the properties of the tile at the given coordinates
- fun getProperties(tile: Tile): TileProperties {
- return tiles.data.elementAt(tile.loc.first).elementAt(tile.loc.second)
+ fun setSize(x: Int, y: Int) {
+ tiles.setSize(x, y)
}
-
- //fun addConnection(at: Pair, dir: Directions)
-
- //Sort out what cells are connected. Induces some CPU overhead compared to storing a simple list
- //Benefit is smaller memory footprint by using references to singleton enums
- fun getConnections(at: Tile): Set {
- val listTiles = ArrayList()
- for (dir: Directions in getProperties(at).connections) {
- //Use the ghost of linear algebra to identify potential neighbor tiles
- val candidateTile = Tile(Pair(at.loc.first + dir.dif.first, at.loc.second + dir.dif.second))
-
- //Ensure that the tile is within bounds
- if(candidateTile.loc.first > 0 &&
- candidateTile.loc.second > 0 &&
- candidateTile.loc.first < tiles.data.size &&
- candidateTile.loc.second < tiles.data[candidateTile.loc.first].size) {
- listTiles.add(candidateTile)
- }
- }
- return listTiles.toSet()
- }
+ //TODO: toString method
+ //Reads array left to right, top to bottom
+ //Only looks at SOUTH and EAST connections
+ //Either connection exists or it does not, whitespace character for exists, some block-appearing char for not
+ //Needs one monowidth char space between each column of array
+ //Needs one line between each row, line containing vertical connections
}
\ No newline at end of file
diff --git a/src/main/kotlin/data/Directions.kt b/src/main/kotlin/data/Directions.kt
index 2cee81a..a6866ab 100644
--- a/src/main/kotlin/data/Directions.kt
+++ b/src/main/kotlin/data/Directions.kt
@@ -1,5 +1,32 @@
package technology.zim.data
-enum class Directions(val dif: Pair) {
- NORTH(Pair(0, 1)), SOUTH(Pair(0, -1)), EAST(Pair(1, 0)), WEST(Pair(-1, 0))
+enum class Directions(val value: Pair) {
+ NORTH(Pair(0, 1)) {
+ override fun opposite(): Directions {
+ return SOUTH
+ }
+ },
+ SOUTH(Pair(0, -1)) {
+ override fun opposite(): Directions {
+ return NORTH
+ }
+ },
+ EAST(Pair(1, 0)) {
+ override fun opposite(): Directions {
+ return WEST
+ }
+ },
+ WEST(Pair(-1, 0)) {
+ override fun opposite(): Directions {
+ return EAST
+ }
+ };
+
+ //Return the opposite direction
+ abstract fun opposite(): Directions
+
+ fun all(): MutableSet {
+ return mutableSetOf(NORTH, SOUTH, EAST, WEST)
+ }
+
}
\ No newline at end of file
diff --git a/src/main/kotlin/data/Tile.kt b/src/main/kotlin/data/Tile.kt
index b47fb32..2873009 100644
--- a/src/main/kotlin/data/Tile.kt
+++ b/src/main/kotlin/data/Tile.kt
@@ -1,7 +1,63 @@
package technology.zim.data
+import technology.zim.World
+
@JvmInline
-value class Tile(val loc: Pair) {
- //Todo: Function for cell to add a connection
- //Todo: Refactor so Tiles know how to get their connections, not the world
+value class Tile(val value: Pair) {
+
+ constructor(x: Int, y: Int): this(Pair(x, y))
+
+ //Connect two tiles together.
+ //Calls utility function on the connected cell
+ fun connect(dir: Directions) {
+ val candidateTile = this+dir
+
+ //Ensure that the tile is within bounds
+ if(candidateTile.isInBounds())
+ {
+ this.getProperties().add(dir)
+ (this + dir).getProperties().add(dir.opposite())
+ }
+ else {
+ //TODO: Consider just silently not connecting out-of-bounds values
+ println("Attempted to connect to outside bounds: <" +
+ candidateTile.value.first + ", " + candidateTile.value.second
+ + "> From Tile: <" + this.value.first + ", " +
+ this.value.second + ">")
+ return
+ }
+ }
+
+ //Gets Tile objects for all connected directions
+ //Used for finding a path through the maze
+ fun getConnections(): MutableSet {
+ val listTiles = mutableSetOf()
+ for (dir: Directions in getProperties().connections) {
+ //Use the ghost of linear algebra to identify potential neighbor tiles
+ listTiles.add(this+dir)
+ }
+ return listTiles
+ }
+
+ fun isInBounds(): Boolean {
+ return value.first > 0 &&
+ value.second > 0 &&
+ value.first < World.tiles.data.size &&
+ value.second < World.tiles.data[value.second].size
+ }
+
+ //Get the properties of the tile at the given coordinates
+ fun getProperties(): TileProperties {
+ return World.tiles.data.elementAt(value.first).elementAt(value.second)
+ }
+
+ //Get tile at given direction
+ operator fun plus(dir: Directions): Tile {
+ return Tile(value.first + dir.value.first, value.second + dir.value.second)
+ }
+
+ //Get tile at direction opposite of given direction
+ operator fun minus(dir: Directions): Tile {
+ return Tile(value.first - dir.value.first, value.second - dir.value.second)
+ }
}
\ No newline at end of file
diff --git a/src/main/kotlin/data/TileProperties.kt b/src/main/kotlin/data/TileProperties.kt
index f910a81..8f40e16 100644
--- a/src/main/kotlin/data/TileProperties.kt
+++ b/src/main/kotlin/data/TileProperties.kt
@@ -1,11 +1,28 @@
package technology.zim.data
+import technology.zim.World
+import technology.zim.World.tiles
+
//Data holder for a Tile
//Should contain a mutable set of connected directions
//Later, can hold jumps to other locations other such fancy features
//For now, a simple inline class to mitigate memory usage
+
+
@JvmInline
value class TileProperties(val connections:MutableSet = mutableSetOf()) {
+
+ //Remove a direction from the list of connections
+ fun remove(dir: Directions) {
+ connections.remove(dir)
+ }
+
+ //Add a direction to the list of connections
+ //Should only be accessed by the Tile class
+ fun add(dir: Directions) {
+ connections.add(dir)
+ }
+
}
diff --git a/src/main/kotlin/data/WorldData.kt b/src/main/kotlin/data/WorldData.kt
index 1e31c35..e709069 100644
--- a/src/main/kotlin/data/WorldData.kt
+++ b/src/main/kotlin/data/WorldData.kt
@@ -1,16 +1,18 @@
package technology.zim.data
-//Data structure wrapper for more easily readable code
+//Data structure wrapper for a set of tiles
@JvmInline
-value class WorldData constructor(val data: ArrayList>) {
+value class WorldData(val data: ArrayList>) {
fun setSize(xmin : Int, ymin : Int) {
+ //Fill every column with an ArrayList of TileProperties
with(data) {
this.ensureCapacity(xmin)
this.fill(ArrayList())
}
+ //Fill every row with TileProperties
for(y in data) {
with(y) {
this.ensureCapacity((ymin))