% A* Pathfinding Implementation % Finds a path, but it's inefficient (goes through unnecessary points. F-values f----- up?) View.Set ("graphics") randomize type Node : record x : int y : int f : int parentX, parentY : int end record function onClosedList (node : Node, closedList : array 1 .. * of Node, counter : int) : boolean for i : 1 .. counter if node.x = closedList (i).x and node.y = closedList (i).y then result true end if end for result false end onClosedList proc findPath (map : array 1 .. 20, 1 .. 20 of int, startNode, goalNode : Node) var currentNode, temp : Node var openList : array 1 .. 20 of Node var closedList : array 1 .. 20 of Node var path : array 1 .. 400 of Node var numOnOpenList, numOnClosedList, lowestFNum : int := 1 var lowestFVal : int := 100 var pathCount, tempNum, count : int := 0 var foundNode : boolean := false for i : 1 .. 20 openList (i).x := 0 openList (i).y := 0 openList (i).f := 0 openList (i).parentX := 0 openList (i).parentY := 0 closedList (i).x := 0 closedList (i).y := 0 closedList (i).f := 0 path (i).x := 0 path (i).y := 0 end for openList (1) := startNode openList (2).parentX := startNode.x openList (2).parentY := startNode.y currentNode := startNode numOnOpenList := 1 loop % Is the current node the goal node? if currentNode.x = goalNode.x and currentNode.y = goalNode.y then put "Target reached" exit end if % Find the possible successors to currentNode % LEFT if currentNode.x >= 2 and map (currentNode.x - 1, currentNode.y) not= 5 then currentNode.parentX := openList (numOnOpenList).x currentNode.parentY := openList (numOnOpenList).y numOnOpenList += 1 openList (numOnOpenList) := currentNode openList (numOnOpenList).x -= 1 openList (numOnOpenList).f := round (sqrt (intreal ((abs (goalNode.x - openList (numOnOpenList).x) ** 2 + abs (goalNode.y - openList (numOnOpenList).y) ** 2)))) end if % DOWN if currentNode.y >= 2 and map (currentNode.x, currentNode.y - 1) not= 5 then currentNode.parentX := openList (numOnOpenList).x currentNode.parentY := openList (numOnOpenList).y numOnOpenList += 1 openList (numOnOpenList) := currentNode openList (numOnOpenList).y -= 1 openList (numOnOpenList).f := round (sqrt (intreal ((abs (goalNode.x - openList (numOnOpenList).x) ** 2 + abs (goalNode.y - openList (numOnOpenList).y) ** 2)))) end if % RIGHT if currentNode.x <= 18 and map (currentNode.x + 1, currentNode.y) not= 5 then currentNode.parentX := openList (numOnOpenList).x currentNode.parentY := openList (numOnOpenList).y numOnOpenList += 1 openList (numOnOpenList) := currentNode openList (numOnOpenList).x += 1 openList (numOnOpenList).f := round (sqrt (intreal ((abs (goalNode.x - openList (numOnOpenList).x) ** 2 + abs (goalNode.y - openList (numOnOpenList).y) ** 2)))) end if % UP if currentNode.y <= 18 and map (currentNode.x, currentNode.y + 1) not= 5 then currentNode.parentX := openList (numOnOpenList).x currentNode.parentY := openList (numOnOpenList).y numOnOpenList += 1 openList (numOnOpenList) := currentNode openList (numOnOpenList).y += 1 openList (numOnOpenList).f := round (sqrt (intreal ((abs (goalNode.x - openList (numOnOpenList).x) ** 2 + abs (goalNode.y - openList (numOnOpenList).y) ** 2)))) end if % Sort the openList using F-costs for i : 1 .. numOnOpenList for j : i .. numOnOpenList if openList (i).f > openList (j).f then temp := openList (i) openList (i) := openList (j) openList (j) := temp end if end for end for % Assign a node to currentNode that is not on the Closed List if onClosedList (openList (1), closedList, numOnClosedList) = false then currentNode := openList (1) else for i : 2 .. numOnOpenList %if onClosedList (openList (i), closedList, numOnClosedList) = false and foundNode = false then if foundNode = false then foundNode := true currentNode := openList (i) tempNum := i pathCount += 1 path (pathCount) := currentNode end if end for end if % Remove the first node from the openList for i : 1 .. numOnOpenList - 1 openList (i) := openList (i + 1) end for % Add current node to the closed list numOnClosedList += 1 closedList (numOnClosedList) := currentNode if numOnClosedList > 15 then numOnClosedList := 0 end if if pathCount >= 400 then put "No path found" exit end if drawfillbox (currentNode.x * 8, currentNode.y * 8, currentNode.x * 8 + 7, currentNode.y * 8 + 7, blue) numOnOpenList := 1 lowestFNum := 1 lowestFVal := 100 foundNode := false end loop % Trace the path loop count := pathCount - 1 path (pathCount - count) := currentNode count -= 1 exit when count <= 1 end loop end findPath var map : array 1 .. 20, 1 .. 20 of int for i : 1 .. 20 for j : 1 .. 20 map (i, j) := 2 drawbox (i * 8, j * 8, 8 + i * 8, 8 + j * 8, black) end for end for var start, goal : Node var mx, my, mb : int buttonchoose ("multibutton") start.x := 14 start.y := 2 start.f := 2 randint (goal.x, 1, 20) randint (goal.y, 1, 20) drawfillbox (goal.x * 8, goal.y * 8, goal.x * 8 + 8, goal.y * 8 + 8, green) loop mousewhere (mx, my, mb) if mb = 1 then map (mx div 8, my div 8) := 5 drawfillbox ((mx div 8) * 8, (my div 8) * 8, (mx div 8) * 8 + 8, (my div 8) * 8 + 8, red) end if exit when mb = 100 end loop findPath (map, start, goal)