public Node(Point GridPosition, int DistanceFromStartPoint, int DistanceToEndPoint)
 {
     this.Parent = null;
     this.GridPosition = GridPosition;
     this.DistanceFromStartPoint = DistanceFromStartPoint;
     this.DistanceToEndPoint = DistanceToEndPoint;
     this.Score = DistanceFromStartPoint + DistanceToEndPoint;
 }
 public void SetParent(Node Parent)
 {
     this.Parent = Parent;
 }
 public void AddChild(Node Child)
 {
     ChildList.Add(Child);
 }
        /// <summary>
        /// Score = DistanceFromStartPoint (CostFromStart) + DistanceToEndPoint (Heuristic)
        /// </summary>
        public static List<Point> FindPath(Map GameMap, Point StartPoint, Point EndPoint)
        {
            if (StartPoint == EndPoint)
            {
                return new List<Point>();
            }

            List<Point> ExploredPoints = new List<Point>();

            List<Node> ClosedList = new List<Node>();
            List<Node> OpenList = new List<Node>();

            List<Node> ConclusionNodeList = new List<Node>();

            // Initialize StartPoint to be first Node
            int DistanceFromStartPoint = GameMap.DistanceOfPoints(StartPoint, StartPoint);
            int DistanceToEndPoint = GameMap.DistanceOfPoints(StartPoint, EndPoint);
            Node CurrentNode = new Node(StartPoint, DistanceFromStartPoint, DistanceToEndPoint);
            ExploredPoints.Add(CurrentNode.GridPosition);

            int RunTime = 0;

            do
            {
                List<Point> AdjacentGridPositions = GetAdjacentGridPositions(CurrentNode);
                List<Node> AdjacentNodes = ConvertPointListToNodeList(AdjacentGridPositions, GameMap, StartPoint, EndPoint);

                // Add Unexplored and Walkable Nodes into OpenList
                // Also set non-Walkable Nodes to Explored to prevent re-exploring
                foreach (Node AdjacentNode in AdjacentNodes)
                {
                    if (!ExploredPoints.Contains(AdjacentNode.GridPosition))
                    {
                        ExploredPoints.Add(AdjacentNode.GridPosition);

                        AdjacentNode.SetParent(CurrentNode);

                        if (GameMap.CheckTileWalkable(AdjacentNode.GridPosition))
                        {
                            OpenList.Add(AdjacentNode);
                        }
                    }
                }

                // Sort by Node Score and Heuristic (Lowest first)
                OpenList = OpenList.OrderBy(Obj => Obj.Score).ThenBy(Obj => Obj.Heuristic).ToList();
                OpenList = RandomizeSameScoreNodes(OpenList);

                // Debug
                if (false)
                {
                    Console.WriteLine();
                    Console.WriteLine("----- " + RunTime);
                    Console.WriteLine("CurrentNode: " + CurrentNode.GridPosition + " S" + CurrentNode.Score + " H" + CurrentNode.Heuristic);
                    Console.Write("ClosedList:  ");
                    foreach (Node node in ClosedList)
                    {
                        Console.Write(node.GridPosition + " S" + node.Score + " H" + node.Heuristic + " - ");
                    }
                    Console.Write("\n");
                    Console.Write("OpenList:    ");
                    foreach (Node node in OpenList)
                    {
                        Console.Write(node.GridPosition + " S" + node.Score + " H" + node.Heuristic + " - ");
                    }
                    Console.Write("\n");
                    Console.Write("Conclusion:  ");
                    foreach (Node node in ConclusionNodeList)
                    {
                        Console.Write(node.GridPosition + " S" + node.Score + " H" + node.Heuristic + " - ");
                    }
                    Console.WriteLine();
                }

                // Add element to ClosedList
                // Take first lowest element from sorted OpenList
                // Remove element from OpenList
                ClosedList.Add(CurrentNode);
                CurrentNode = OpenList[0];
                OpenList.RemoveAt(0);

            } while (CurrentNode.Heuristic > 0);

            // Get resulting path
            // Cycle from end node to first node
            while (CurrentNode.CostFromStart > 0)
            {
                ConclusionNodeList.Add(CurrentNode);
                CurrentNode = CurrentNode.Parent;
            }

            // Tile Coloring Debug
            if (false)
            {
                GameMap.Reset();
                foreach (Node node in OpenList)
                {
                    GameMap.UpdateTileType(node.GridPosition, GameSetting.TileType.Brown);
                }
                foreach (Node node in ClosedList)
                {
                    GameMap.UpdateTileType(node.GridPosition, GameSetting.TileType.Purple);
                }
                foreach (Node node in ConclusionNodeList)
                {
                    GameMap.UpdateTileType(node.GridPosition, GameSetting.TileType.Yellow);
                }
            }

            List<Point> ConclusionPointList = new List<Point>();
            foreach (Node ConclusionNode in ConclusionNodeList)
            {
                ConclusionPointList.Insert(0, ConclusionNode.GridPosition);
            }

            return ConclusionPointList;
        }
 private static List<Point> GetAdjacentGridPositions(Node CurrentNode)
 {
     Point GridPosition = CurrentNode.GridPosition;
     List<Point> AdjacentGridPositions = new List<Point>();
     AdjacentGridPositions.Add(new Point(GridPosition.X - 1, GridPosition.Y - 1));
     AdjacentGridPositions.Add(new Point(GridPosition.X + 0, GridPosition.Y - 1));
     AdjacentGridPositions.Add(new Point(GridPosition.X + 1, GridPosition.Y - 1));
     AdjacentGridPositions.Add(new Point(GridPosition.X - 1, GridPosition.Y + 0));
     AdjacentGridPositions.Add(new Point(GridPosition.X + 1, GridPosition.Y + 0));
     AdjacentGridPositions.Add(new Point(GridPosition.X + 1, GridPosition.Y + 1));
     AdjacentGridPositions.Add(new Point(GridPosition.X + 0, GridPosition.Y + 1));
     AdjacentGridPositions.Add(new Point(GridPosition.X - 1, GridPosition.Y + 1));
     return AdjacentGridPositions;
 }