--
-- Copyright (c) 2012 Kevin Wellwood
-- All rights reserved.
--
-- This source code is distributed under the Modified BSD License. For terms and
-- conditions, see license.txt.
--
package Directions is
pragma Pure;
subtype Axis_Direction is Integer range -1..1;
-- A record capable of expressing eight directions with x, y axis. It is
-- useful because direction arithmetic can be performed on a Direction_Type.
type Direction_Type is
record
x, y : Axis_Direction;
end record;
-- Enumeration of the four cardinal directions.
type Cardinal_Direction is (Left, Right, Up, Down);
-- Enumeration of eight directions at 45 degree angles.
type Direction_8 is (D8_Left, D8_Right, D8_Up, D8_Down,
D8_Up_Left, D8_Up_Right, D8_Down_Left, D8_Down_Right);
-- An array of Booleans indexed by cardinal direction.
type Direction_Booleans is array (Cardinal_Direction) of Boolean;
----------------------------------------------------------------------------
-- Returns a combined direction. If the direction of 'r' is directly
-- opposite the matching component of the 'l' direction, then 'r' will
-- override the matching component of 'l' in the resultant direction.
-- (ex: Dir_Left + Right = Dir_Right)
function "+"( l : Direction_Type; r : Cardinal_Direction ) return Direction_Type;
-- Zeros the component of direction 'l' that matches 'r'. Note that the
-- returned direction will have at least one non-zero component because a
-- direction with no components is illegal.
function "-"( l : Direction_Type; r : Cardinal_Direction ) return Direction_Type;
-- Returns true if cardinal direction 'r' is a component of direction 'l'.
-- Example: "<Up+Right> and Up = True", "<Down+Right> and Up = False"
function "and"( l : Direction_Type; r : Cardinal_Direction ) return Boolean;
-- Converts dir to a Direction_8 type. If dir doesn't have a component in
-- any axis then a Constraint_Error is raised.
function To_D8( dir : Direction_Type ) return Direction_8;
pragma Precondition( dir.x /= 0 or else dir.y /= 0 );
-- Converts dir to a Direction_8 type.
function To_D8( dir : Cardinal_Direction ) return Direction_8;
-- Returns only the X component of dir as a Direction_8. If dir doesn't have
-- an X component then Left is returned as a default.
function To_X( dir : Direction_Type ) return Direction_8;
-- Returns only the Y component of dir as a Direction_8. If dir doesn't have
-- any Y component then Up is returned as a default.
function To_Y( dir : Direction_Type ) return Direction_8;
-- Returns only the Y component of dir as a cardinal direction. If dir
-- doesn't have any Y component then Up is returned as a default.
function To_Y( dir : Direction_Type ) return Cardinal_Direction;
-- Returns true if all of the Booleans in the array are False.
function "not"( db : Direction_Booleans ) return Boolean;
-- Returns the opposite of the given direction.
function Opposite( dir : Cardinal_Direction ) return Cardinal_Direction;
-- Converts a Cardinal_Direction to a general Direction_Type.
function To_Direction( dir : Cardinal_Direction ) return Direction_Type;
-- Converts a Direction_8 to a general Direction_Type.
function To_Direction( dir : Direction_8 ) return Direction_Type;
function To_String( dir : Direction_Type ) return String;
----------------------------------------------------------------------------
Dir_Left : constant Direction_Type;
Dir_Right : constant Direction_Type;
Dir_Up : constant Direction_Type;
Dir_Down : constant Direction_Type;
Dir_Up_Left : constant Direction_Type;
Dir_Up_Right : constant Direction_Type;
Dir_Down_Left : constant Direction_Type;
Dir_Down_Right : constant Direction_Type;
private
Dir_Left : constant Direction_Type := (x => -1, y => 0);
Dir_Right : constant Direction_Type := (x => 1, y => 0);
Dir_Up : constant Direction_Type := (x => 0, y => -1);
Dir_Down : constant Direction_Type := (x => 0, y => 1);
Dir_Up_Left : constant Direction_Type := (x => -1, y => -1);
Dir_Up_Right : constant Direction_Type := (x => 1, y => -1);
Dir_Down_Left : constant Direction_Type := (x => -1, y => 1);
Dir_Down_Right : constant Direction_Type := (x => 1, y => 1);
end Directions;