Instance problem

:kir:

http://files.herenbdy.com/Altercatio.swf

I’m using A* pathfinding in my tile-based game. The node class has the properties: xPos (xcoordinate on map), yPos (ycoordinate on map), tile (the movieclip on stage that the Node is referencing), and F (a numerical representation of how close the tile is to the end, lower = better). Whenever a new Node is made, it is automatically added to the open list. The Path class is used to calculate the path between two given nodes. The tiles go by the name: map.info.t_xPos_yPos (ie: map.info.t_2_16 would refer to the tile that’s x coordinate is 2, and y 16).

Play around with my game a a bit (ignore the other enemies on screen), using the mouse to select your next target. The code will always function correctly the first time, but each time thereafter you will eiether freeze (an infinite loop occurs), or get a path to the tile (a rather drunken one). The path that the object is following is printed to the log, as you can see the beggining of the path will usually begin with the same node for some reason…

Could anyone look at my code and see a reason why an infinite loop would occur? or why node 15_14 is constantly set as the start of the path… (I’ve double checked to make sure the correct variables are being passed into the function)

Pathfinding class:

http://files.herenbdy.com/Path.as (Can open it in a text editor)

class Path {
    public var path:Array; //where the final result will be stored
    public var nodes:Array = new Array(); //arbitrary array, it's function is to hold the new nodes we create
    public var open:Array = new Array(); //the list of nodes that have not been examined yet
    public var start:Node; //the start point
    public var end:Node; //the end point
    public var map:Map; //map object that will be defined in the constructor
    public var complete:Boolean = false;
    function nodeIsValid(name:String):Boolean{
        //Checks whether the specified node already exists in our nodes list, and if's walkable
        if(map.info[name].walkable == false){
            return false;
        } else {
            for(var r = 0; r < nodes.length; r++){
                if(nodes[r].tile == map.info[name]){
                    return false;
                }
            }
        }
        return true;
    }
    function nodeIsOpen(name:String):Number{
        for(var e = 0; e < open.length; e++){
            if(open[e].tile == map.info[name]){
                return e;
            }
        }
        return 0;
    }
    public function findAdjacentNodes(node:Node){
        //Finds all the nodes that are next to the selected node, and adds them to the open list
        open.splice(0, 1);//remove first element from open list
        var x = node.xPos;
        var y = node.yPos;
        var left = "t_"+(x-1)+"_"+y;
        var up = "t_"+x+"_"+(y-1);
        var right = "t_"+(x+1)+"_"+y;
        var down = "t_"+x+"_"+(y+1);
        var list:Array = new Array(left, up, right, down);
        for(var t = 0; t < list.length; t++){
            if(nodeIsValid(list[t])){
                nodes.push(new Node(this, node, map.info[list[t]]));
            }
        }
    }
    public function compareF(a:Node, b:Node):Number{
        //function called by the sort function
        // -1 means A comes before B, 0 means their equal, 1 means B come before A
        if(isNaN(a.F)){
            return 1;
        } else if(isNaN(b.F)){
            return -1;
        } else if(a.F < b.F){
            return -1;
        } else if(a.F == b.F){
            return -1;
        } else if(a.F > b.F){
            return 1;
        } else {
            return -1;
        }
    }
    public function sort(){
        //sorts the open list by lowest F score first
        open.sort(compareF, Array.NUMERIC);
    }
    public function printNode(node:Node){ 
        //debugging function
        trace("Node_" + node.xPos +"_"+node.yPos);
    }
    public function tracePathTo(n:Node){
        //Retrace our steps, and populate the path array
        path = new Array();
        var done:Boolean = false;
        var node:Node = n;
        var f = 0;
        while(!done){
            if(node.parent == null){
                done = true;
            } else {
                path.push(node);
                node = node.parent;
            }
            f++;
            if(f > 500){
                trace("ERROR IN TRACE FUNCTION");
                break;
            }
        }
        path.reverse();
    }
    public function Path(battle:Battle, unit:Unit, target:Tile){
        map = battle.map;
        var tName:String = "t_"+unit.xPos+"_"+unit.yPos;
        start = new Node(this, null, map.info[tName]);
        trace("Path is starting at....");
        printNode(start);
        end = new Node(this, null, target);
        while(!complete){
            if(open[0].tile == end.tile){
                trace("Path found.");
                end = open[0];
                tracePathTo(end);
                complete = true;
                trace("length of path is: "+path.length);
            } else {
                findAdjacentNodes(open[0]);
                sort();
            }
        };
    }
    public function getPath():Array{
        return path;
    }
}