1. package Directions is 
  2.  
  3.     pragma Pure; 
  4.  
  5.     subtype Axis_Direction is Integer range -1..1; 
  6.  
  7.     -- A record capable of expressing eight directions with x, y axis. It is 
  8.     -- useful because direction arithmetic can be performed on a Direction_Type. 
  9.     type Direction_Type is 
  10.         record 
  11.             x, y : Axis_Direction; 
  12.         end record; 
  13.  
  14.     -- Enumeration of the four cardinal directions. 
  15.     type Cardinal_Direction is (Left, Right, Up, Down); 
  16.  
  17.     -- Enumeration of eight directions at 45 degree angles. 
  18.     type Direction_8 is (D8_Left,    D8_Right,    D8_Up,        D8_Down, 
  19.                          D8_Up_Left, D8_Up_Right, D8_Down_Left, D8_Down_Right); 
  20.  
  21.     -- An array of Booleans indexed by cardinal direction. 
  22.     type Direction_Booleans is array (Cardinal_Direction) of Boolean; 
  23.  
  24.     ---------------------------------------------------------------------------- 
  25.  
  26.     -- Returns a combined direction. If the direction of 'r' is directly 
  27.     -- opposite the matching component of the 'l' direction, then 'r' will 
  28.     -- override the matching component of 'l' in the resultant direction. 
  29.     -- (ex: Dir_Left + Right = Dir_Right) 
  30.     function "+"( l : Direction_Type; r : Cardinal_Direction ) return Direction_Type; 
  31.  
  32.     -- Zeros the component of direction 'l' that matches 'r'. Note that the 
  33.     -- returned direction will have at least one non-zero component because a 
  34.     -- direction with no components is illegal. 
  35.     function "-"( l : Direction_Type; r : Cardinal_Direction ) return Direction_Type; 
  36.  
  37.     -- Returns true if cardinal direction 'r' is a component of direction 'l'. 
  38.     -- Example: "<Up+Right> and Up = True", "<Down+Right> and Up = False" 
  39.     function "and"( l : Direction_Type; r : Cardinal_Direction ) return Boolean; 
  40.  
  41.     -- Converts dir to a Direction_8 type. If dir doesn't have a component in 
  42.     -- any axis then a Constraint_Error is raised. 
  43.     function To_D8( dir : Direction_Type ) return Direction_8; 
  44.     pragma Precondition( dir.x /= 0 or else dir.y /= 0 ); 
  45.  
  46.     -- Converts dir to a Direction_8 type. 
  47.     function To_D8( dir : Cardinal_Direction ) return Direction_8; 
  48.  
  49.     -- Returns only the X component of dir as a Direction_8. If dir doesn't have 
  50.     -- an X component then Left is returned as a default. 
  51.     function To_X( dir : Direction_Type ) return Direction_8; 
  52.  
  53.     -- Returns only the Y component of dir as a Direction_8. If dir doesn't have 
  54.     -- any Y component then Up is returned as a default. 
  55.     function To_Y( dir : Direction_Type ) return Direction_8; 
  56.  
  57.     -- Returns only the Y component of dir as a cardinal direction. If dir 
  58.     -- doesn't have any Y component then Up is returned as a default. 
  59.     function To_Y( dir : Direction_Type ) return Cardinal_Direction; 
  60.  
  61.     -- Returns true if all of the Booleans in the array are False. 
  62.     function "not"( db : Direction_Booleans ) return Boolean; 
  63.  
  64.     -- Returns the opposite of the given direction. 
  65.     function Opposite( dir : Cardinal_Direction ) return Cardinal_Direction; 
  66.  
  67.     -- Converts a Cardinal_Direction to a general Direction_Type. 
  68.     function To_Direction( dir : Cardinal_Direction ) return Direction_Type; 
  69.  
  70.     -- Converts a Direction_8 to a general Direction_Type. 
  71.     function To_Direction( dir : Direction_8 ) return Direction_Type; 
  72.  
  73.     function To_String( dir : Direction_Type ) return String; 
  74.  
  75.     ---------------------------------------------------------------------------- 
  76.  
  77.     Dir_Left       : constant Direction_Type; 
  78.     Dir_Right      : constant Direction_Type; 
  79.     Dir_Up         : constant Direction_Type; 
  80.     Dir_Down       : constant Direction_Type; 
  81.     Dir_Up_Left    : constant Direction_Type; 
  82.     Dir_Up_Right   : constant Direction_Type; 
  83.     Dir_Down_Left  : constant Direction_Type; 
  84.     Dir_Down_Right : constant Direction_Type; 
  85.  
  86. private 
  87.  
  88.     Dir_Left       : constant Direction_Type := (x => -1, y =>  0); 
  89.     Dir_Right      : constant Direction_Type := (x =>  1, y =>  0); 
  90.     Dir_Up         : constant Direction_Type := (x =>  0, y => -1); 
  91.     Dir_Down       : constant Direction_Type := (x =>  0, y =>  1); 
  92.     Dir_Up_Left    : constant Direction_Type := (x => -1, y => -1); 
  93.     Dir_Up_Right   : constant Direction_Type := (x =>  1, y => -1); 
  94.     Dir_Down_Left  : constant Direction_Type := (x => -1, y =>  1); 
  95.     Dir_Down_Right : constant Direction_Type := (x =>  1, y =>  1); 
  96.  
  97. end Directions;