Amazing program from BASIC Computer Games
The maze program is one of the games in the famous 101 BASIC Computer Games published in 1978. In the book it is called 'Amazing' and the code available in Vintage BASIC. I have rewritten it in Pascal. It relies on two external procedures to create random numbers as the standard library doesn't have that functionality. The code used non-standard bit-level operators: '!' for OR, '&' for AND, and '#' for XOR.
OS-9 Pascal edition
{ Generate a maze. The algoritm uses a two-dimensional matrix of cells, where the bottom or the right wall can be absent. Pascal does not have a 'continue' statement, therefore the goto 580. } PROGRAM maze(input); label 580,750; const MAXROWS = 25; MAXCOLS = 25; NO_FLOOR = 1; NO_RIGHT_WALL = 2; VISITED = 4; type direction = (Left, Right, Up, Down); var randstate: integer; rows,cols,c,r,dx,entry,x,cellinx,totcells: integer; bottom: boolean; d: array[1..10] of direction; cells: array[1..MAXROWS, 1..MAXCOLS] of integer; function random(VAR block:integer) : real; EXTERNAL; procedure randomize(VAR block:integer); EXTERNAL; { Provide a random integer } function rnd(maxval:integer):integer; begin rnd := trunc(random(randstate) * maxval); end; { Ask for dimensions. Sets the global variables: cols and rows } procedure AskDimensions; var goodsize : boolean; begin goodsize := false; repeat writeln('What are your length and width (e. g. 13 10)?'); readln(rows, cols); if (rows > 1) or (rows <= MAXROWS) or (cols > 1) or (cols <= MAXCOLS) then goodsize := true else writeln('Meaningless dimensions. Try again.'); until goodsize = true; end; procedure PrintMaze; var r, c : integer; begin { Print top of the maze with an opening. } writeln; for c := 1 to cols do if c = entry then write('. ') else write('.--'); writeln('.'); for r := 1 to rows do begin write('|'); for c := 1 to cols do begin if (cells[r, c] & NO_RIGHT_WALL) = 0 then write(' |') else write(' '); end; writeln; for c := 1 to cols do begin if (cells[r, c] & NO_FLOOR) = 0 then write(':--') else write(': '); end; writeln(':'); end end; { Find a cell that is already visited to continue from. Uses the global variables r, c, cols, rows and visited. } procedure FindVisited; begin repeat c := c + 1; if c > cols then begin r := r + 1; if r > rows then r := 1; c := 1 end; until (cells[r, c] & VISITED) <> 0; end; procedure InitMaze; var q,z : integer; begin for q := 1 to rows do for z := 1 to cols do begin cells[q,z] := 0; end; end; procedure AddPossibility(go:direction); begin dx := dx + 1; d[dx] := go; end; begin randstate := 0; randomize(randstate); AskDimensions; totcells := rows * cols; InitMaze; bottom := false; entry := rnd(cols) + 1; r := 1; c := entry; cellinx := 1; cells[r, c] := cells[r, c] ! VISITED; repeat dx := 0; if c <> 1 then begin if (cells[r, c - 1] & VISITED) = 0 then begin AddPossibility(Left) end; end; if c <> cols then begin if (cells[r, c + 1] & VISITED) = 0 then begin AddPossibility(Right) end else goto 750; end; if r > 1 then begin if (cells[r - 1, c] & VISITED) = 0 then begin AddPossibility(Up) end; end; 750: if r < rows then begin if (cells[r + 1, c] & VISITED) = 0 then AddPossibility(Down); end else begin if bottom = false then AddPossibility(Down); end; if dx = 0 then begin FindVisited; goto 580; end; x := rnd(dx) + 1; case d[x] of Down: begin cells[r, c] := cells[r, c] ! NO_FLOOR; r := r + 1; if r > rows then begin bottom := true; r := 1; c := 0; FindVisited; goto 580; end end; Up: begin r := r - 1; cells[r, c] := NO_FLOOR end; Right: begin cells[r, c] := cells[r, c] ! NO_RIGHT_WALL; c := c + 1 end; Left: begin c := c - 1; cells[r, c] := NO_RIGHT_WALL end; end; cellinx := cellinx + 1; cells[r, c] := cells[r, c] ! VISITED; 580: until cellinx >= totcells; PrintMaze; end.