Ok, I am not the best at writing clean code though.
This is how I reach each node:
local function ColorModel(model , color) --Used for testing purposes
for i , v in pairs(model:GetDescendants()) do
if v:IsA("BasePart") then
if not color then
v.Color = Color3.new(0.0980392, 1, 0)
else
v.Color = color
end
end
end
end
local function WrapAround(num) --Wrap around function because the maze wraps around itself
if typeof(num) == "table" then
local nums = {}
for i , v in pairs(num) do
nums[i] = WrapAround(v)
end
return nums
end
if typeof(num) == "Vector2" then
return Vector2.new(WrapAround(num.X) , WrapAround(num.Y))
end
if num < 1 then
num += TilesLength
elseif num > TilesLength then
num -= TilesLength
end
return num
end
local function AbsoluteVector3(vector) --I used this to attempt to calculate the neearest tile taking the wrap around feature into account.
return Vector3.new(math.abs(vector.X),math.abs(vector.Y),math.abs(vector.Z))
end
local function ComputeTile(Tile)
local PathOptions = {}
local currentPosition = Vector2.new((Tile.Tile:GetPivot().Position.X + (tiles.Size / 2)) / 16 , (Tile.Tile:GetPivot().Position.Z + (tiles.Size / 2)) / 16)
local nodeReached = false
ColorModel(Tile.Tile)
for i , e in pairs(Tile.Entrances) do --For each neighboring tile
local targetTile = tileData[WrapAround(e.X)][WrapAround(e.Y)] --Check the tile in that entrance position
if table.find(WrapAround(targetTile.Entrances) , currentPosition) then -- if you can enter this tile from the selected entrance tile then
if game.CollectionService:HasTag(targetTile.Tile , "Node") then -- if the current tile is next to a node tile, that means it is a reachable node
nodeReached = true
ColorModel(targetTile.Tile)
game.CollectionService:RemoveTag(targetTile.Tile , "Node")
targetTile.Status = "Node"
ColorModel(targetTile.Tile.RoomValue.Value)
end
if targetTile.Status == "New" or targetTile.Status == "Wall"then --Mark the tile as an untestedPath if it was not approached previously or deemed impassable
ColorModel(targetTile.Tile , Color3.new(1, 0.415686, 0))
targetTile.Status = "UntestedPath"
table.insert(PathOptions , targetTile)
end
elseif targetTile.Status == "New" then --Wall status can only be granted if the tile hasn't been walked through before, it can be removed though
ColorModel(targetTile.Tile , Color3.new(1, 0, 0))
targetTile.Status = "Wall"
end
ColorModel(Tile.Tile , Color3.new(1, 1, 1)) --Mark the path as tested so it isn't in the nearby untested tiles list
Tile.Status = "TestedPath"
end
return PathOptions , nodeReached --return nearby accessible tiles and wether a node was reached
end
local starterTile = tileData[31][30]
local nearbyTiles = {}
local Nodes = game.CollectionService:GetTagged("Node")
table.sort(Nodes, function(NodeA , NodeB) --Sort nodes by the nearest to the center
return NodeA:GetPivot().Position.Magnitude < NodeB:GetPivot().Position.Magnitude
end)
for i , v in pairs(ComputeTile(starterTile)) do --Compute the starting tile to get the first nearby rooms in the array
table.insert(nearbyTiles , v)
end
repeat
local NewTiles, reachedNode = ComputeTile(nearbyTiles[1]) --Compute the first nearby tile
for i , v in pairs(NewTiles) do
if not table.find(nearbyTiles , v ) then
table.insert(nearbyTiles , v) --insert the tiles that weren't there previously
end
end
for i , v in pairs(nearbyTiles) do
if string.sub(v.Status,1,8) ~= "Untested" then
table.remove(nearbyTiles , i)
end
end
table.sort(nearbyTiles , function(tileA, tileB)
return (AbsoluteVector3(Nodes[1]:GetPivot().Position) - AbsoluteVector3(tileA.Tile:GetPivot().Position)).Magnitude > (AbsoluteVector3(Nodes[1]:GetPivot().Position) - AbsoluteVector3(tileB.Tile:GetPivot().Position)).Magnitude
end) --Sort the nearby tiles so that
if reachedNode == true then
table.remove(Nodes , 1) --Removed the reached node
workspace.Step.Value += 1
warn("Step " .. workspace.Step.Value)
end
wait()
until #Nodes == 0 or #nearbyTiles == 0
I put a wait after checking around each tile because otherwise I get a script timeout error.
Due to how I coded it, every node after the first just pathfinds from the UntestedTile closest to that node.