I am trying to make an A* algorithm, but I have a problem. The way script is intended to work, is to get neighbors of current node, and then add the neighbors (that are not in closed list/occupied) to the openList
, in which the best part to move at is determined. However, I think I have an issue with this part of code:
local function UpdateNeighbors(Center, Neighbors) -- Detect if neighbors are occupied or already in openList
for i, neighbor in pairs(Neighbors) do
if table.find(closedList, neighbor) then continue end
if table.find(openList, neighbor) then
if neighbor:GetAttribute("MoveCost") == not 0 and neighbor:GetAttribute("MoveCost") < Center:GetAttribute("MoveCost") + 1 then
continue
end
end
local mCost = Center:GetAttribute("MoveCost") + 1
neighbor:SetAttribute("MoveCost", mCost)
local hCost = math.abs(finish.Position.X / 8 - neighbor.Position.X / 8) + math.abs(finish.Position.Z / 8 - neighbor.Position.Z / 8)
neighbor:SetAttribute("TotalCost", mCost + hCost)
neighbor:SetAttribute("CameFrom", Center.CFrame)
table.insert(openList, neighbor)
table.remove(openList, table.find(openList, Center))
table.insert(closedList, Center)
end
end
The result of this function always puts only 1 part in the list, and not 3 or 4, like it is intended.
If need more context, this is the whole code:
local active = false
local finish = workspace.Nodes.Finish
local start = workspace.Nodes.Start
local upComing
local Nodes = workspace.Nodes:GetChildren()
local openList = {}
local closedList = {}
local function GetNeighbors(Center) -- Get neighbors of current node, AKA upcoming
local neighbors = {}
for i, node in pairs(Nodes) do
if math.abs(node.Position.X / 8) == math.abs(Center.Position.X / 8) and math.abs(node.Position.Z / 8) == math.abs(Center.Position.Z / 8) + 1 then
table.insert(neighbors, node)
elseif math.abs(node.Position.X / 8) == math.abs(Center.Position.X / 8) and math.abs(node.Position.Z / 8) == math.abs(Center.Position.Z / 8) - 1 then
table.insert(neighbors, node)
elseif math.abs(node.Position.X / 8) == math.abs(Center.Position.X / 8) + 1 and math.abs(node.Position.Z / 8) == math.abs(Center.Position.Z / 8) then
table.insert(neighbors, node)
elseif math.abs(node.Position.X / 8) == math.abs(Center.Position.X / 8) - 1 and math.abs(node.Position.Z / 8) == math.abs(Center.Position.Z / 8) then
table.insert(neighbors, node)
end
end
print(neighbors)
return neighbors
end
local function UpdateNeighbors(Center, Neighbors) -- Detect if neighbors are occupied or already in openList
for i, neighbor in pairs(Neighbors) do
if table.find(closedList, neighbor) then continue end
if table.find(openList, neighbor) then
if neighbor:GetAttribute("MoveCost") == not 0 and neighbor:GetAttribute("MoveCost") < Center:GetAttribute("MoveCost") + 1 then
continue
end
end
local mCost = Center:GetAttribute("MoveCost") + 1
neighbor:SetAttribute("MoveCost", mCost)
local hCost = math.abs(finish.Position.X / 8 - neighbor.Position.X / 8) + math.abs(finish.Position.Z / 8 - neighbor.Position.Z / 8)
neighbor:SetAttribute("TotalCost", mCost + hCost)
neighbor:SetAttribute("CameFrom", Center.CFrame)
table.insert(openList, neighbor)
table.remove(openList, table.find(openList, Center))
table.insert(closedList, Center)
end
end
local function UpdateNodes() -- Update nodes: Their color and list references
for i, node in pairs(Nodes) do
if node:GetAttribute("Occupied") == true and table.find(closedList, node) then
continue
elseif node:GetAttribute("Occupied") == true and not table.find(closedList, node) then
table.insert(closedList, node)
end
if table.find(closedList, node) and node:GetAttribute("Occupied") == true then
node.Color = Color3.fromRGB(60, 0, 0)
elseif table.find(closedList, node) and node:GetAttribute("Occupied") == false then
node.Color = Color3.fromRGB(60, 60, 60)
elseif table.find(openList, node) then
node.Color = Color3.fromRGB(0, 180, 240)
end
end
end
local function GetUpcoming() -- Get best part for the next iteration
local Costs = {}
for i, node in pairs(openList) do
local tCost = node:GetAttribute("TotalCost")
table.insert(Costs, tCost)
end
local bestCost = math.min(unpack(Costs))
for i, node in pairs(openList) do
if node:GetAttribute("TotalCost") == bestCost then
upComing = node
break
else
continue
end
end
return upComing
end
local function Cycle()
repeat
UpdateNodes()
task.wait(1)
UpdateNeighbors(upComing, GetNeighbors(upComing))
task.wait(1)
GetUpcoming()
print(GetUpcoming())
until table.find(openList, finish)
end
script.Parent.MouseClick:Connect(function()
table.insert(openList, start)
upComing = start
Cycle()
end)