All pastes #28942 Raw Edit

Pathfinding - Works

public text v1 · immutable
#28942 ·published 2005-11-16 18:53 UTC
rendered paste body
View.Set ("graphics:1280:768")

% Pathfinding

type node :
    record
        x, y, parentX, parentY : int
    end record

var nodeFirst, nodeLast, nodeNextLast, numNodes : int := 1
var nodeX, nodeY : int
var endNode : node
var retVal, pathVal : int
var reachEnd : boolean := false
var start, goal, parent : node
var atNode : array 1 .. 625 of node
var numTiles : int := 25
var map : array 1 .. numTiles, 1 .. numTiles of int
var mapVals : array 1 .. numTiles, 1 .. numTiles of int
var expandedNode : array 1 .. numTiles, 1 .. numTiles of boolean
var val, pathMinVal : int
var nodeNbr : int := 1
var pathToFollow : array 1 .. 401 of node
var foundPath : boolean := false
var moveCost := 2

var font := Font.New ("verdana:8")

for i : 1 .. upper (atNode)
    atNode (i).x := 0
    atNode (i).y := 0
end for

for i : 1 .. numTiles
    for j : 1 .. numTiles
        map (i, j) := 2
        mapVals (i, j) := 1
        expandedNode (i, j) := false
    end for
end for

function findCombinations (point : node, var arrayStart : int) : int
    if point.x - 1 = 0 or point.x + 1 = (numTiles + 1) or point.y - 1 = 0 or point.y + 1 = (numTiles + 1) then
        result 0
    end if
    if (point.x - 1 >= 1) and expandedNode (point.x - 1, point.y) = false then
        atNode (nodeNbr).x := point.x - 1
        atNode (nodeNbr).y := point.y
        nodeNbr += 1
        expandedNode (point.x - 1, point.y) := true
        atNode (nodeNbr).parentX := point.x
        atNode (nodeNbr).parentY := point.y
    end if
    if (point.y - 1 >= 1) and expandedNode (point.x, point.y - 1) = false then
        atNode (nodeNbr).x := point.x
        atNode (nodeNbr).y := point.y - 1
        expandedNode (point.x, point.y - 1) := true
        nodeNbr += 1
        atNode (nodeNbr).parentX := point.x
        atNode (nodeNbr).parentY := point.y
    end if
    if (point.x + 1 <= numTiles) and expandedNode (point.x + 1, point.y) = false then
        atNode (nodeNbr).x := point.x + 1
        atNode (nodeNbr).y := point.y
        expandedNode (point.x + 1, point.y) := true
        nodeNbr += 1
        atNode (nodeNbr).parentX := point.x
        atNode (nodeNbr).parentY := point.y
    end if
    if (point.y + 1 <= numTiles) and expandedNode (point.x, point.y + 1) = false then
        atNode (nodeNbr).x := point.x
        atNode (nodeNbr).y := point.y + 1
        expandedNode (point.x, point.y + 1) := true
        nodeNbr += 1
        atNode (nodeNbr).parentX := point.x
        atNode (nodeNbr).parentY := point.y
    end if
    result nodeNbr - arrayStart
end findCombinations

function isValid (num : int) : boolean
    if num >= 1 then
        result true
    end if
    result false
end isValid

function getNodeValue (x, y : int) : int
    pathMinVal := 500
    % Check if it is an impossible tile...
    if x = 0 or y = 0 then
        result - 2
    end if
    if map (x, y) = -1 then
        result - 1
    end if

    if (x - 1) >= 1 then
        val := mapVals (x - 1, y)
        if isValid (val) then
            if val <= pathMinVal or pathMinVal = 0 then
                pathMinVal := val
            end if
        end if
    end if
    if (x + 1) <= numTiles then
        val := mapVals (x + 1, y)
        if isValid (val) then
            if val <= pathMinVal or pathMinVal = 0 then
                pathMinVal := val
            end if
        end if
    end if
    if (y - 1) >= 1 then
        val := mapVals (x, y - 1)
        if isValid (val) then
            if val <= pathMinVal or pathMinVal = 0 then
                pathMinVal := val
            end if
        end if
    end if
    if (y + 1) <= numTiles then
        val := mapVals (x, y + 1)
        if isValid (val) then
            if val <= pathMinVal or pathMinVal = 0 then
                pathMinVal := val
            end if
        end if
    end if
    result pathMinVal
end getNodeValue

function tracePath (point, start, goal : node) : node
    var xFactor, yFactor, absVal, absTestVal, lowestAbsVal : int := 0
    pathMinVal := 500
    lowestAbsVal := 500
    var resultPt : node
    resultPt.x := point.x
    resultPt.y := point.y
    % X VALUES
    % Is it in the bounds?
    if point.x - 1 = goal.x and point.y = goal.y then
        result goal
    elsif (point.x - 1) >= 1 and expandedNode (point.x - 1, point.y) = true then
        % Find value
        val := mapVals (point.x - 1, point.y)
        locate (3, maxcol - 2)
        if isValid (val) and val > 1 then
            put val
            absTestVal := abs ((start.x - (point.x - 1)) ** 2) + abs ((start.y - point.y) ** 2)
            if val < pathMinVal or pathMinVal = 0 then
                pathMinVal := val
                xFactor := -1
                yFactor := 0
                lowestAbsVal := absTestVal
            elsif val = pathMinVal and absTestVal <= lowestAbsVal then
                pathMinVal := val
                xFactor := -1
                yFactor := 0
                lowestAbsVal := absTestVal
            end if
        end if
    end if

    if point.x + 1 = goal.x and point.y = goal.y then
        result goal
    elsif (point.x + 1) <= numTiles and expandedNode (point.x + 1, point.y) = true then
        % Find value
        val := mapVals (point.x + 1, point.y)
        if isValid (val) and val > 1 then
            absTestVal := abs ((start.x - (point.x + 1)) ** 2) + abs ((start.y - point.y) ** 2)
            if val < pathMinVal or pathMinVal = 0 then
                pathMinVal := val
                xFactor := 1
                yFactor := 0
            elsif val = pathMinVal and absTestVal <= lowestAbsVal then
                pathMinVal := val
                xFactor := 1
                yFactor := 0
                lowestAbsVal := absTestVal
            end if
        end if
    end if
    if point.x = goal.x and point.y - 1 = goal.y then
        result goal
    elsif (point.y - 1) >= 1 and expandedNode (point.x, point.y - 1) = true then
        % Find value
        val := mapVals (point.x, point.y - 1)
        if isValid (val) and val > 1 then
            absTestVal := abs ((start.x - point.x) ** 2) + abs ((start.y - (point.y - 1)) ** 2)
            if val < pathMinVal or pathMinVal = 0 then
                pathMinVal := val
                xFactor := 0
                yFactor := -1
            elsif val = pathMinVal and absTestVal <= lowestAbsVal then
                pathMinVal := val
                xFactor := 1
                yFactor := 0
                lowestAbsVal := absTestVal
            end if
        end if
    end if
    if point.x = goal.x and point.y + 1 = goal.y then
        result goal
    elsif (point.y + 1) <= numTiles and expandedNode (point.x, point.y + 1) = true then
        % Find value
        val := mapVals (point.x, point.y + 1)
        if isValid (val) and val < 1 then
            absTestVal := abs ((start.x - point.x) ** 2) + abs ((start.y - (point.y + 1)) ** 2)
            if val < pathMinVal or pathMinVal = 0 then
                pathMinVal := val
                xFactor := 0
                yFactor := 1
            elsif val = pathMinVal and absTestVal <= lowestAbsVal then
                pathMinVal := val
                xFactor := 1
                yFactor := 0
                lowestAbsVal := absTestVal
            end if
        end if
    end if
    if pathMinVal not= 0 then
        resultPt.x += xFactor
        resultPt.y += yFactor
    end if
    result resultPt
end tracePath

proc choosePath (start, goal : node, points : array 1 .. * of node)
    var currentPoint : node
    var count := 1
    currentPoint := start

    loop
        if foundPath = false then
            locate (1, maxcol)
            drawfillbox (1 + currentPoint.x * 16, 1 + currentPoint.y * 16, 15 + currentPoint.x * 16, 15 + currentPoint.y * 16, blue)
            drawfillbox (goal.x * 16, goal.y * 16, 16 + goal.x * 16, 16 + goal.y * 16, red)
            currentPoint := tracePath (currentPoint, start, goal)
            drawfillbox (1 + currentPoint.x * 16, 1 + currentPoint.y * 16, 15 + currentPoint.x * 16, 15 + currentPoint.y * 16, green)
            exit when currentPoint.x = goal.x and currentPoint.y = goal.y
        end if
    end loop
end choosePath

proc pathSearch (start, goal : node)
    % Prepare
    endNode.x := goal.x
    endNode.y := goal.y

    % Initialize first node (starting location)
    atNode (1).x := start.x
    atNode (1).y := start.y
    atNode (1).parentX := start.x
    atNode (1).parentY := start.y
    nodeFirst := 1
    nodeLast := findCombinations (start, numNodes)
    mapVals (start.x, start.y) := map (start.x, start.y)
    parent := atNode (1)
    loop
        nodeNextLast := nodeLast
        for a : nodeFirst .. nodeLast
            % Store the x and y values for speed
            nodeX := atNode (a).x
            nodeY := atNode (a).y

            pathVal := getNodeValue (nodeX, nodeY)
            if pathVal = -1 then
                mapVals (nodeX, nodeY) := -1
            elsif pathVal > 0 then
                % Adds the lowest value of closest tile to the current value of my tile
                mapVals (nodeX, nodeY) := mapVals (atNode (a).parentX, atNode (a).parentY) + pathVal

                % Draw it in
                Font.Draw (intstr (mapVals (nodeX, nodeY)), nodeX * 16 + 2, nodeY * 16 + 2, font, black)

                % Find the next 4 nodes
                retVal := findCombinations (atNode (a), nodeNextLast)
                nodeNextLast := nodeNextLast + retVal

                % Destination reached?
                if nodeX = endNode.x and nodeY = endNode.y then
                    reachEnd := true
                end if
            end if
        end for
        nodeFirst := nodeLast + 1
        nodeLast := nodeNextLast
        exit when reachEnd = true
        exit when nodeFirst > nodeLast
    end loop
    if reachEnd = true then
        choosePath (goal, start, atNode)
    end if
end pathSearch

var temp, mx, my, mb : int

start.x := 15
start.y := 2
goal.x := 7
goal.y := 8
for i : 1 .. numTiles
    for j : 1 .. numTiles
        drawbox (i * 16, j * 16, 16 + i * 16, 16 + j * 16, black)
    end for
end for

buttonchoose ("multibutton")

loop
    mousewhere (mx, my, mb)
    if mx < (16 * numTiles) and my < (16 * numTiles) and mb = 1 then
        map (mx div 16, my div 16) := -1
        drawfillbox ((mx div 16) * 16, (my div 16) * 16, 16 + (mx div 16) * 16, 16 + (my div 16) * 16, red)
    end if
    exit when mb = 100
end loop

pathSearch (start, goal)
% for i : 1 .. 10
%     put pathToFollow (i).x, " ", pathToFollow (i).y
% end for