/// <summary>
        /// Initializes a discrete grid using the information provided.
        /// </summary>
        /// <param name="startPoint">The point to start the route at</param>
        /// <param name="endPoint">The point to end the route at</param>
        /// <param name="field">The field that needs to be discretised</param>
        /// <param name="gridSize">The size of the grid to be palced placed over <paramref name="field"/></param>
        /// <param name="movingObject">The object that will be moving.</param>
        /// <returns>A GridSquare array, initialized to represent <paramref name="field"/>.</returns>
        ///
        /// Produces a GridSquare array that is set up for use by <see cref="FindPath"/>.
        ///
        /// Uses the ObjectClearance and <paramref name="movingObject" />'s <see cref="IPositionedObject.Size"/> property to determine the
        /// apparent size of opponents, and marks the squares that contain them as <see cref="SquareType.Obstacle"/>.
        ///
        /// Marks the square that contains <paramref name="endPoint" /> as <see cref="SquareType.Destination"/>.
        ///
        /// Marks the square that contains <paramref name="startPoint" /> as <see cref="SquareType.Origin"/>.
        ///
        /// Works in parallel as far as possible, using the Microsoft Task Parallel Library (http://msdn.microsoft.com/en-us/library/dd460717.aspx).
        protected GridSquare[] InitGrid(PointF startPoint, PointF endPoint, Field field, Size gridSize, IPositionedObject movingObject)
        {
            var playersize = (movingObject.Size + new Size(ObjectClearance, ObjectClearance)).Scale(Resolution).Scale(2.0f).Ceiling();
            var clearance  = Math.Max(playersize.Width, playersize.Height); // The amount to increase an obstacle's size by to allow for the player's size

            var grid = new GridSquare[gridSize.Height * gridSize.Width];

            // Initialize the grid
            Parallel.For(0, grid.Length, i => {
                grid[i] = new GridSquare
                {
                    Location = PointExtensions.FromIndex(i, gridSize.Width)
                };
            });

            Parallel.ForEach(from p in field.Players where p.Team == Team.Opposition select p, player =>
            {
                var centerGridPoint = player.Position.Scale(Resolution).Floor();

                var minX = Math.Max(0, centerGridPoint.X - playersize.Width - clearance);
                var maxX = Math.Min(centerGridPoint.X + playersize.Width + clearance, gridSize.Width);
                var minY = Math.Max(0, centerGridPoint.Y - playersize.Height - clearance);
                var maxY = Math.Min(centerGridPoint.Y + playersize.Height + clearance, gridSize.Height);

                for (var i = minX; i < maxX; i++)
                {
                    for (var j = minY; j < maxY; j++)
                    {
                        if (i < 0 || j < 0)
                        {
                            continue;
                        }

                        var gridPoint = new Point(i, j);
                        grid[gridPoint.ToIndex(gridSize.Width)].Type = SquareType.Obstacle;
                    }
                }
            });

            var gridEndPoint = endPoint.Scale(Resolution).Floor();

            grid[gridEndPoint.ToIndex(gridSize.Width)].Type = SquareType.Destination;

            var gridStartPoint = startPoint.Scale(Resolution).Floor();

            grid[gridStartPoint.ToIndex(gridSize.Width)].Type = SquareType.Origin;

            return(grid);
        }
 /// <summary>
 /// Calculates the heuristic score for the given square.
 /// </summary>
 /// <param name="square">The square to calculate the heuristic for </param>
 /// <param name="endPoint">The current point to aim for </param>
 /// <returns>
 /// \f$+\infty\f$ if the square is an obstacle
 ///
 /// CalculateLength(square.Location, endPoint) otherwise
 /// </returns>
 protected float CalculateHeuristic(GridSquare square, PointF endPoint)
 {
     return(square.Type == SquareType.Obstacle ? float.PositiveInfinity : CalculateLength(square.Location, endPoint));
 }
 /// <summary>
 /// Reconstructs a path from the given cameFrom information.
 /// </summary>
 /// <param name="cameFrom">The list of 'came from' details produced by the A* algorithm</param>
 /// <param name="currentSquare">The current square to examine</param>
 /// <returns>The shortest Route to the destination</returns>
 ///
 /// A recursive algorithm that reconstructs the path that has been produced by the A* algorithm
 protected Route ReconstructPath(Dictionary <GridSquare, GridSquare> cameFrom, GridSquare currentSquare)
 {
     if (cameFrom.ContainsKey(currentSquare))
     {
         var path = ReconstructPath(cameFrom, cameFrom[currentSquare]);
         path.Path.Add(new LineSegment(cameFrom[currentSquare].Location, currentSquare.Location));
         return(path);
     }
     return(new Route());
 }