program MAZE;
(* MAZEMAKE.PAS & MAZEPLAY.PAS CONCATENATED *)
(* separate them to run on Turbo Pascal compiler *)
(*written by Doug Cox on an Osborne 1, Mar '85, for use in the Public Domain*)

program MAZEMAKE;
label ORIG, FIN;
const ScreenTop: integer= $F000;
type
  Row= 1..24; Col= 1.. 128;
  PointerType= ^ScreenPointer;
  ScreenPointer= array[Row,Col] of byte;
var
  pointerVar: PointerType ABSOLUTE ScreenTop;
  screen: array[1..3072] of char ABSOLUTE $F000; (* 24 by 128 *)
  ch: char;
  x, y, key: byte;
  horiz: set of 1..80; vert: array[1..80] of set of 2..23;
  escape, ok: boolean;
  fileName: string[12];
  fv: Text;

begin
  ClrScr;
  GotoXY(1,12);
  writeln ('Name of maze data file, (or RETURN to make a new one)');
  write (' (don''t include the ".DTA"): '); read (fileName);
  FillChar (screen, SizeOf(screen), #127);
  horiz:= []; for x:= 1 to 80 do vert[x]:= [];
  if fileName= '' then Goto ORIG;
  fileName:= fileName+'.DTA';
  Assign (fv, fileName);
  {$I-} Reset (fv) {$I+};
  ok:= (IOresult= 0);
  if ok then
  begin
    while not Eof (fv) do
    begin
      readln(fv, y, x);
      pointerVar^[y,x]:= 32;
      horiz:= horiz+[x]; vert[x]:= vert[x]+[y];
    end;
    Close (fv);
  end;
ORIG:
  escape:= False;
  if fileName= '' then begin y:= 12; x:= 1; end;
  repeat
    if escape= False then
    begin
      pointerVar^[y,x]:= 13; (* ball *)
      Delay(50);
      pointerVar^[y,x]:= 32; (* space *)
      horiz:= horiz+[x]; vert[x]:= vert[x]+[y];
    end
    else
    begin
      pointerVar^[y,x]:= 42; (* asterisk *)
      Delay(50);
      pointerVar^[y,x]:= 127; (* dim block *)
      horiz:= horiz-[x]; vert[x]:= vert[x]-[y];
    end;
    key:= 0;
    key:= Bdos(6,$FF); (* KeyPressed *)
    if (key= Ord(^[)) and (escape= False) then escape:= True
    else if (key= Ord(^[)) and (escape= True) then escape:= False
    else if ((key= Ord(^D)) or (key= Ord(^L)))
      and (x < 80) then x:= x+1
    else if ((key= Ord(^S)) or (key= Ord(^H)))
      and (x > 1) then x:= x-1
    else if ((key= Ord(^E)) or (key= Ord(^K)))
      and (y > 2) then y:= y-1
    else if ((key= Ord(^X)) or (key= Ord(^J)))
      and (y < 23) then y:= y+1
    else if key= Ord(' ') then
      begin pointerVar^[y,x]:= 13; Delay(300); end;
  until key > Ord('@'); (* press any key to quit *)
  for x:= 1 to 53 do begin GotoXY(x,12); write (' '); end;
  for x:= 1 to 53 do begin GotoXY(x,13); write (' '); end;
  for x:= 1 to 53 do begin GotoXY(x,14); write (' '); end;
  GotoXY(1,12); writeln ('Name for maze data file (8 letters or less):');
  write (' (".DTA" will be automatically appended)');
  GotoXY(46,12); read (fileName); if fileName= '' then Goto FIN;
  fileName:= fileName+'.DTA';
  Assign (fv, fileName); Rewrite (fv);
  for x:= 1 to 80 do
    for y:= 2 to 23 do
      if y in vert[x] then writeln (fv, y,' ',x);
  Close (fv);
FIN:GotoXY(1,13);
end.

program MAZEPLAY;
label FIN;
const ScreenTop: integer= $F000;
type
  Row= 1..24; Col= 1.. 128;
  PointerType= ^ScreenPointer;
  ScreenPointer= array[Row,Col] of byte;
var
  pointerVar: PointerType ABSOLUTE ScreenTop;
  screen: array[1..3072] of char ABSOLUTE $F000; (* 24 by 128 *)
  ch: char;
  x, y: byte;
  horiz: set of 1..80; vert: array[1..80] of set of 2..23;
  ok: boolean;
  fileName: string[12];
  fv: Text;

procedure Return;
  begin pointerVar^[y,x]:= 127; y:= 12; x:= 1; end;

begin
  ClrScr;
  GotoXY(1,12); writeln ('Name of maze data file');
  write (' (don''t include the ".DTA"): ');
  repeat
    GotoXY(30,13); ClrEol;
    read (fileName); if fileName= '' then Goto FIN;
    fileName:= fileName+'.DTA'; GotoXY(1,12);
    Assign (fv, fileName);
    {$I-} Reset (fv) {$I+};
    ok:= (IOresult= 0);
    if not ok then
    begin
      GotoXY(1,11);
      write ('Sorry, I can''t find "',fileName,'", try again...');
    end;
  until ok;
  FillChar (screen, SizeOf(screen), #127);
  horiz:= []; for x:= 1 to 80 do vert[x]:= [];
  while not Eof (fv) do
    begin
      readln(fv, y, x);
      pointerVar^[y,x]:= 32;
      horiz:= horiz+[x]; vert[x]:= vert[x]+[y];
    end;
  Close (fv);
  y:= 12; x:= 1; ch:= ' ';
  repeat
    pointerVar^[y,x]:= 13;
    Delay (45);
    pointerVar^[y,x]:= 32;
    if Keypressed then
    begin
      read (Kbd, ch);
      case ch of
        ^D,^L: begin
                 x:= x+1;
                 if not ((x in horiz) and (y in vert[x]))
                     then x:= x-1;
               end;
        ^S,^H: begin
                 x:= x-1;
                 if not ((x in horiz) and (y in vert[x]))
                   then x:= x+1;
               end;
        ^E,^K: begin
                 y:= y-1;
                 if not ((y in vert[x]) and (x in horiz))
                   then y:= y+1;
               end;
        ^X,^J: begin
                 y:= y+1;
                 if not ((y in vert[x]) and (x in horiz))
                   then y:= y-1;
               end;
        end;
    end;
  until (ch > '@') or (x= 80); ClrScr;
  if x= 80 then begin GotoXY(35,12); writeln ('Way to go...'); end;
FIN:end.