/* ========= PATHFINDING METHODS ========= */

        /// <summary>
        /// Return a list of possible moves for the player
        /// </summary>
        /// <param name="world">World the player is currently located in</param>
        /// <param name="location">Location the player is currently at</param>
        /// <param name="allowUnsafe">Allow possible but unsafe locations</param>
        /// <returns>A list of new locations the player can move to</returns>
        public static IEnumerable <Location> GetAvailableMoves(World world, Location location, bool allowUnsafe = false)
        {
            List <Location> availableMoves = new List <Location>();

            if (IsOnGround(world, location) || IsSwimming(world, location))
            {
                foreach (Direction dir in Enum.GetValues(typeof(Direction)))
                {
                    if (CanMove(world, location, dir) && (allowUnsafe || IsSafe(world, location.Move(dir))))
                    {
                        availableMoves.Add(location.Move(dir));
                    }
                }
            }
            else
            {
                foreach (Direction dir in new [] { Direction.East, Direction.West, Direction.North, Direction.South })
                {
                    if (CanMove(world, location, dir) && IsOnGround(world, location.Move(dir)) && (allowUnsafe || IsSafe(world, location.Move(dir))))
                    {
                        availableMoves.Add(location.Move(dir));
                    }
                }
                availableMoves.Add(location.Move(Direction.Down));
            }
            return(availableMoves);
        }
        /* ========= SIMPLE MOVEMENTS ========= */

        /// <summary>
        /// Check if the player can move in the specified direction
        /// </summary>
        /// <param name="world">World the player is currently located in</param>
        /// <param name="location">Location the player is currently at</param>
        /// <param name="direction">Direction the player is moving to</param>
        /// <returns>True if the player can move in the specified direction</returns>
        public static bool CanMove(World world, Location location, Direction direction)
        {
            switch (direction)
            {
            case Direction.Down:
                return(!IsOnGround(world, location));

            case Direction.Up:
                return((IsOnGround(world, location) || IsSwimming(world, location)) &&
                       !world.GetBlock(location.Move(Direction.Up, 2)).Type.IsSolid());

            case Direction.East:
            case Direction.West:
            case Direction.South:
            case Direction.North:
                return(!world.GetBlock(location.Move(direction)).Type.IsSolid() &&
                       !world.GetBlock(location.Move(direction).Move(Direction.Up)).Type.IsSolid());

            default:
                throw new ArgumentException("Unknown direction", "direction");
            }
        }
        /// <summary>
        /// Check if the specified location is safe
        /// </summary>
        /// <param name="world">World for performing check</param>
        /// <param name="location">Location to check</param>
        /// <returns>True if the destination location won't directly harm the player</returns>
        public static bool IsSafe(World world, Location location)
        {
            return
                //No block that can harm the player
                (!world.GetBlock(location).Type.CanHarmPlayers() &&
                 !world.GetBlock(location.Move(Direction.Up)).Type.CanHarmPlayers() &&
                 !world.GetBlock(location.Move(Direction.Down)).Type.CanHarmPlayers()

                 //No fall from a too high place
                 && (world.GetBlock(location.Move(Direction.Down)).Type.IsSolid() ||
                     world.GetBlock(location.Move(Direction.Down, 2)).Type.IsSolid() ||
                     world.GetBlock(location.Move(Direction.Down, 3)).Type.IsSolid())

                 //Not an underwater location
                 && !(world.GetBlock(location.Move(Direction.Up)).Type.IsLiquid()));
        }
        /* ========= LOCATION PROPERTIES ========= */

        /// <summary>
        /// Check if the specified location is on the ground
        /// </summary>
        /// <param name="world">World for performing check</param>
        /// <param name="location">Location to check</param>
        /// <returns>True if the specified location is on the ground</returns>
        public static bool IsOnGround(World world, Location location)
        {
            return(world.GetBlock(location.Move(Direction.Down)).Type.IsSolid() &&
                   (location.Y <= Math.Truncate(location.Y) + 0.0001));
        }