(*   This maze game program first prompts the user to enter a seven-by-seven
maze, where a '.' indicates a path and a 'W' represents a wall.  The program
then determines whether or not there is a way out by beginning in the upper
left-hand corner and trying to exit at the lower right-hand corner.  The
program marks with 'X's the trail which actually leads out, if any.  If there
is no way out of the maze, the program displays an appropriate message.  Other-
wise it displays the final maze and prompts the user to enter another maze. *)

program AMazeGame(Input,Output);

const  Top = 1;         (* constant to mark the smallest row number *)
       Bottom = 7;      (* constant to mark the largest row number *)
       Left = 1;        (* constant to mark the smallest column number *)
       Right = 7;       (* constant to mark the largest column number *)
       Path = '.';      (* constant to mark a path input by user *)
       Trail = '^';     (* constant to mark the trail the program took *)
       Mark = 'x';      (* constant to mark the path which was travelled *)
       Size = 7;        (* number of columns or rows in the maze *)

var    Maze : array[1..Size,1..Size] of char;   (* array to hold maze *)
       WayOut : boolean;                 (* flag to indicate a way out *)
       InputChar : char;                 (* prompt user to play again *)

(*----------------------------------------------*)
  procedure ReadMaze;       (* procedure to input the user's maze *)
  var I, J  : 1..Size;   
  begin
      writeln('INPUT A MAZE:'); writeln;
      for I := 1 to Size do begin
          for J := 1 to Size do read(Maze[I,J]);  
          readln      
          end (* for *)
  end;(* ReadMaze *)

(*---------------------------------------------*)
  procedure WriteMaze;         (* procedure to output the maze *)
  var I, J : 1..Size;  
  begin
      writeln('PATH THROUGH MAZE IS:'); writeln;
      for I:= 1 to Size do begin
          for J := 1 to Size do write(Maze[I,J] : 2); 
          writeln    
          end (* for *)
  end; (* WriteMaze *)

(*---------------------------------------------*)
(*  Recursive procedure to find a path through the maze.  This procedure
continues to call itself until either the way out has been found or it has
determined there is no way out.  The algorithm begins at the upper right-hand 
corner of the maze and tries to move to the lower left-hand corner, marking
the path it has traveled with an X.  The algorithm first tries to move
right, then down, then left, then up.  If there is a way out, the procedure
marks the trail with up-arrow symbols as the recursion levels decrease.

      Row -  parameter to indicate row number
      Column - parameter to indicate column number    *)

  procedure FindPath(Row, Column : integer); 
  begin
      if (Row = Bottom) and (Column = Right) 
          then WayOut := true          
      else begin
          Maze[Row,Column] := Mark;     
          if Column <> Right then
              if Maze[Row,Column + 1] = Path then 
                  FindPath(Row,Column + 1);        (* move right if possible *)
          if (not WayOut) and (Row <> Bottom) then 
              if Maze[Row + 1,Column] = Path then
                  FindPath(Row + 1,Column);        (* move down if possible *)
          if (not WayOut) and (Column <> Left) then
              if Maze[Row,Column - 1] = Path then
                  FindPath(Row,Column - 1);        (* move left if possible *)
          if (not WayOut) and (Row <> Top) then 
              if Maze[Row - 1,Column] = Path then
                  FindPath(Row - 1,Column)         (* move up if possible *)
          end; (* else *)
      if WayOut then Maze[Row,Column] := Trail
  end; (* FindPath *)

(*---------------------------------------------*)
(* The main program inputs a maze, initially assumes there is no way out, then
calls the recursive procedure FindPath to find a way out if there is one.  If
there is no way out, the program prints a message; otherwise, it prints the
final maze. *)

begin  (* AMazeGame *)
    repeat                  
        ReadMaze;    
        WayOut := false; 
        FindPath(Top,Left); 
        if WayOut then WriteMaze   
        else begin     (* if no way out, print message *)
            writeln; writeln('NO PATH THROUGH MAZE FOUND.');
            writeln
            end; (* else *)
        writeln; writeln('ANOTHER MAZE? (Y or N)');
        readln(InputChar)
    until not (InputChar in ['y','Y'])
end. (* AMazeGame *)
