Not every part added to the list

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)
2 Likes

replace == not 0 with ~= 0. character limit

1 Like
if neighbor:GetAttribute("MoveCost") ~= 0 and neighbor:GetAttribute("MoveCost") < Center:GetAttribute("MoveCost") + 1 then
    continue
end

this should fix it

1 Like

Neither of 2 answers fixed it, sadly.

I kind of fixed it myself. The nodes at the start always have a move cost and total cost of 0, so I had to add additional “if” statement. Got another problem, though, which I will also try to fix, but if I fail, ill ask for help here once again.

what’s the point of this clusterbomb of if statements if the nodes end up in the same table anyway?

there’s no such thing as == not 0, you do ~= 0

They get the neighbors in 4 directions, and because they are in different places, the statements are slightly different. I could have gotten 1 simple statement that would get the magnitude between the center and all other nodes, and if the magnitude is equal or less than 8 then add to the list, but I am planning on doing diagonal movement too, and due to diagonal neighbors having more distance from center, I can’t do that. And yeah, i just forgot that there is ~= existing.

1 Like

image
Made some edit and now it works.