//A Dijkstra Search implementation focused on finding the most efficent way to move to a target tile given the environemental cost to get there. INodeSearchable DijkstraSearch(INodeSearchable startNode, INodeSearchable targetNode, List <INodeSearchable> searchSet, ECostType costType) { INodeSearchable currentNode; currentNode = startNode; foreach (var node in searchSet) { node.DijkstraCost = null; } //Ensures we don't check our starting node twice, and that our starting node is at the front of our "queue" searchSet.Remove(currentNode); searchSet.Insert(0, currentNode); currentNode.DijkstraCost = 0; while (searchSet.Count > 0) { currentNode = searchSet[0]; searchSet.RemoveAt(0); searchSet.TrimExcess(); if (currentNode == targetNode) { return(targetNode); } else if (currentNode.DijkstraCost == null) { //Remaining nodes are assumed unreachable, no path to target, return null as a fail state return(null); } else { foreach (var child in currentNode.children) { if (child == null) { continue; } bool reassigned = CalculateDijkstra(currentNode, child, costType); if (reassigned) { child.parent = currentNode; } child.TotalCost = child.DijkstraCost; } } IComparer <INodeSearchable> nullback = new SortNullToBackByTotalCost(); searchSet.Sort(nullback); } return(null); }
//@Param startNode: The INodeSearchable object the search should start from. //@Param targetNode: The INodeSearchable object the search should be attempting to reach. //@Param searchSet: A list containing all nodes to be searched/in the search range. public INodeSearchable AStarBasic(INodeSearchable startNode, INodeSearchable targetNode, List <INodeSearchable> searchSet, ECostType costType, EHeuristic heuristic, float dijkstraWeight, float heuristicWeight) { //A* selects the path that minimizes: //f(x) = g(x) + h(x) //Where g(x) is the cost of the node, and h(x) is the cost of heursitic INodeSearchable currentNode; currentNode = startNode; foreach (var node in searchSet) { node.DijkstraCost = null; node.HeuristicCost = null; node.TotalCost = null; } //Ensures we don't check our starting node twice, and that our starting node is at the front of our "queue" searchSet.Remove(currentNode); searchSet.Insert(0, currentNode); currentNode.DijkstraCost = 0; currentNode.TotalCost = 0; while (searchSet.Count > 0) { currentNode = searchSet[0]; searchSet.RemoveAt(0); searchSet.TrimExcess(); if (currentNode == targetNode) { return(targetNode); } else if (currentNode.DijkstraCost == null) { //Remaining nodes are assumed unreachable, no path to target, return null as a fail state return(null); } else { foreach (var child in currentNode.children) { if (child == null) { continue; } //Calc the heuristic cost of chosen heuristic measure: h(x) CalculateHeuristic(targetNode, child, heuristic); //Calc the Dijkstra cost of chosen cost measure g(x) CalculateDijkstra(currentNode, child, costType); //Calc the total cost: f(x) = g(x) + h(x) float?total = child.DijkstraCost * dijkstraWeight + child.HeuristicCost * heuristicWeight; if (total < child.TotalCost || child.TotalCost == null) { child.TotalCost = total; child.parent = currentNode; if (!searchSet.Contains(child)) { searchSet.Add(child); } } } } IComparer <INodeSearchable> nullback = new SortNullToBackByTotalCost(); searchSet.Sort(nullback); } return(null); }