with Console;

package body Traversal is

   ----------
   -- Mark --
   ----------

   procedure Mark
      (Point  : in     Maze.Position;
       On     : in out Trail;
       Within : in     Maze.Reference;
       Next   :    out Maze.Positions;
       Last   :    out Maze.Moves)
   is
      Candidates  : constant Maze.Positions := Maze.Next (Within, Point);
      Past        : Trail renames On;
      Count       : Maze.Moves := 0;
      Predecessor : Maze.Position;

      use type Maze.Moves, Maze.Position;
   begin
      if Past.Solutions /= null then
         Predecessor := Past.Solutions.Point; -- the one we just came from
         for K in Candidates'Range loop
            if Candidates (K) /= Predecessor and then
               not Visited (Candidates (K), Past.Intersections)
            then
               Count := Count + 1;
               Next (Count) := Candidates (K);
            end if;
         end loop;
         Last := Count;
      else -- at the entrance
         Next (Candidates'Range) := Candidates;
         Last := Candidates'Last;
      end if;

      Past.Solutions := new Node'(Point, Past.Solutions);

      if Candidates'Length > 2 then -- is an intersection
         --  Note that Candidates includes the position we just came from, which
         --  is why more than 2 indicates an intersection, rather than more than
         --  one.
         Past.Intersections := new Node'(Point, Past.Intersections);
      end if;
   end Mark;

   ----------
   -- Show --
   ----------

   procedure Show (Solution : in Trail) is
      Ptr : Link := Solution.Solutions;
      use Maze;
   begin
      while Ptr /= null loop
         Console.Plot_Solution_Point
            (Console.Instance.all,
             (Row (Ptr.Point), Column (Ptr.Point)));
         Ptr := Ptr.Pred;
      end loop;
   end Show;

   -------------
   -- Visited --
   -------------

   function Visited (Point : Maze.Position;  Within : Link) return Boolean is
      Ptr : Link := Within;
      use Maze; -- for "=" on Position
   begin
      while Ptr /= null and then Ptr.Point /= Point loop
         Ptr := Ptr.Pred;
      end loop;
      return Ptr /= null; -- ie, found it before getting to end of list
   end Visited;

end Traversal;

