There’s probably some hacky solution to this, but I’m looking for the most optimal solution to this issue.
I have a maze system which generates a maze by branching off of each hallways exit points by choosing a turn, straight hall, or junction (T Hall).
After the generation is complete, the system chooses the furthest hallway model from the spawn, and then sets it to the exit. (Evil, I know.)
I am trying to make this less evil by adding hints to where to go, however that is where my issue lies. I’m not sure how to add hints in the direction of the exit without having it preset, which I don’t want to do.
This probably has some easy solution for it, but I’m not perfect.
Anyways, I have already attempted to use pathfinding (Yes, I know, super hacky solution), and it barely functions 3% of the time. other 97% it just NoPaths. (Have already tried clearing the pathway to the best of my ability, to no avail.)
Any help appreciated, and will be credited during the end credits.
It will check all of these different positions if they’re further away than the last check.
Meaning if I try to generate while doing that it will add hints to random positions around the map and lead the player in circles, which I don’t want to do. By hints I mean subtle things that point the player in the correct direction, for example an arrow or some footprints on the floor, both would of course be facing towards the end of the maze.
Don’t you have something like a hitbox for a chunk of section you copy and paste? And why don’t you like store all the informations on a table and get the path for exit then place the hints?
No, well you do clone a model from somewhere and place it on workspace.
Just when you place your rooms you probs know if the room/hall has ended or if it continues and you also have defined the exit so you probs know the hall where the exit.
So what I am saying is when. Ever you place these halls why not store some infos in a table like ‘exit’, ‘ended’, ‘connected halls’ and seek for the path from that? Unless this is what u meant by making a huge tree.
I see what you are saying but the exit position is not predetermined. The exit is placed after the halls are generated. I see how you’re saying to link hallways to each other if they are connected, and I could try this, however it might become quite the large table due to the sheer size of the generation I am doing.
You can always shrink the table by eliminating ended hallways that you don’t need or some sort but also you should be able to just edit the table if it has an exit or not once you place the exit.
Keep in mind I am using junctions which have two separate possible links, However those are a lot rarer than the other variations due to there only being one variation, when the other halltypes have multiple variations.
Give me a moment to try this out.
Edit: Intellisense broke. This is going to take a bit longer than expected.
Pick random points where you will place your hints and put them in a table
Load your hints at around each point in the table
I haven’t scripted in a while and I’m not good at pathfinding whatsoever so I won’t be able to just give the code
I’ve been researching procedural generation for the better part of a year. It’s very challenging. But here’s what I’d do:
You have your nodes, so you can calculate how far away a node is from the exit. Then you can just decide, if a node is X nodes away from the exit, place a sign.
Uh, the issue right now is that I can’t get these nodes you speak of since my table layout’s loader for some reason stops working after a junction is hit.
If I manage to figure that out then I should be able to easily do the rest.
If you want I can DM you the functions used for generation
(So you can better understand what’s going on in the backend, I don’t want to send it here as I plan to use this system in a fully fledged game.)
So it’s a data problem. You’re using T-junctions. That means you can store your data as a ‘Binary Search Tree’. From there, it’s not so difficult to find things like distances.
Here’s some of my old code. Use at own risk
--[[
local TreeNode = require(game.ReplicatedStorage["N-ary tree"])
-- Example usage
local root = TreeNode.new("Root")
local child1 = TreeNode.new("Child 1")
local child2 = TreeNode.new("Child 2")
local child3 = TreeNode.new("Child 3")
local child4 = TreeNode.new("Child 4")
local child5 = TreeNode.new("Child 5")
root:addChild(child1)
root:addChild(child2)
child1:addChild(child3)
child3:addChild(child4)
child2:addChild(child5)
-- Perform tree traversal
print("Preorder Traversal:")
root:preorderTraversal()
print("Postorder Traversal:")
root:postorderTraversal()
root:levelOrderTraversal()
]]
-- Define a basic N-ary tree node structure
local TreeNode = {}
TreeNode.__index = TreeNode
function TreeNode.new(value)
local self = setmetatable({}, TreeNode)
self.value = value
self.children = {}
return self
end
function TreeNode:addChild(childNode)
table.insert(self.children, childNode)
end
-- Tree traversal functions with indentation
function TreeNode:preorderTraversal(indent)
indent = indent or 0
print(string.rep(" ", indent) .. self.value) -- Indent based on depth
for _, child in ipairs(self.children) do
child:preorderTraversal(indent + 1)
end
end
function TreeNode:postorderTraversal(indent)
indent = indent or 0
for _, child in ipairs(self.children) do
child:postorderTraversal(indent + 1)
end
print(string.rep(" ", indent) .. self.value) -- Indent based on depth
end
-- Method to count the number of children for a node
function TreeNode:getChildCount()
return #self.children
end
-- Method to check if a node is a leaf (has no children)
function TreeNode:isLeaf()
return #self.children == 0
end
-- Method to check if a node is the root of the tree
function TreeNode:isRoot()
return not self.parent
end
-- Method to get the depth of a node in the tree
function TreeNode:getDepth()
if not self.parent then
return 0
else
return 1 + self.parent:getDepth()
end
end
-- Method to find a node with a specific value in the tree
function TreeNode:findNode(targetValue)
if self.value == targetValue then
return self
else
for _, child in ipairs(self.children) do
local result = child:findNode(targetValue)
if result then
return result
end
end
return nil
end
end
-- Method to remove a child node from the current node
function TreeNode:removeChild(childNode)
for i, child in ipairs(self.children) do
if child == childNode then
table.remove(self.children, i)
childNode.parent = nil -- Clear the parent reference for the removed child
return true -- Child node removed successfully
end
end
return false -- Child node not found
end
-- Level order traversal with level information
function TreeNode:levelOrderTraversal()
local queue = {{self, 0}} -- Initialize the queue with the root node and its level
while #queue > 0 do
local currentEntry = table.remove(queue, 1)
local current = currentEntry[1]
local level = currentEntry[2]
print("Level " .. level .. ": " .. current.value) -- Print level and value
for _, child in ipairs(current.children) do
table.insert(queue, {child, level + 1}) -- Enqueue child nodes with increased level
end
end
end
return TreeNode