$define VERSION 0.6


link options


$define DRIGHT 1
$define DLEFT  2
$define DUP    3
$define DDOWN  4

record position(row, col)
global dir, ip, ram

procedure main(argv)
   local ch, codespace, col, dp, fn, line
   local row := 1
   local wid := 0
   local dirs := []
   local ips := []
   local opts, verbose, debug

   opts := options(argv, , errorproc)
   \opts[] & verbose := 1
   \opts[] & show_help(verbose)
   \opts[] & debug := 1

   ip := position(1,1)

   
   dir := DRIGHT 

   
   ram := list(1, 0)

   
   codespace := []

   fn := open(argv[1], ) | &input
   if (fn === &input) & \opts[] then return

   while line := read(fn) do {
      put(codespace, line)
      wid := max(*line, wid)
   }
   if *codespace = 0 then return
   every line := !codespace do {
      codespace[row] := left(codespace[row], wid)
      
      if /col := find(, codespace[row]) then {
         ip.row := row
         ip.col := col
      }
      row +:= 1
   }

   if \verbose then {
      write(, ip.row, , ip.col, )
      every write(!codespace)
   }

   dp := 1
   repeat {
      if not (ch := codespace[ip.row][ip.col]) then break 
      if \debug then {
         write(&errout, , dir, , ch, , ord(ch), ,
                        , ip.row, , ip.col,
                        , dp, , ram[dp])
      }
      case ch of {
         
         : ram[dp] +:= 1
         : ram[dp] -:= 1
         : resize(dp +:= 1)
         : dp -:= 1
         : writes(char(ram[dp]) | char(0))
         : ram[dp] := getche()
         
         : { 
            case dir of {
               DRIGHT: dir := DDOWN
               DLEFT:  dir := DUP
               DUP:    dir := DLEFT
               DDOWN:  dir := DRIGHT
            }
         } 
         : { 
            case dir of {
               DRIGHT: dir := DUP
               DLEFT:  dir := DDOWN
               DUP:    dir := DRIGHT
               DDOWN:  dir := DLEFT
            }
         }
         : step()
         : { 
            if ram[dp] = 0 then {
               step()
            }
         }
         
         : { 
            push(dirs, dir)
            push(ips, copy(ip))
         }
         : { 
            if *dirs < 1 then break
            dir := pop(dirs)
            ip := pop(ips)
            step()
         }
      }
      step()
   }
end


procedure step()
   case dir of {
      DRIGHT: ip.col +:= 1
      DLEFT:  ip.col -:= 1
      DUP:    ip.row -:= 1
      DDOWN:  ip.row +:= 1
   }
end


procedure resize(elements)
   until *ram >= elements do put(ram, 0)
end 


procedure show_help(verbose)
   write(, VERSION)
   write()
   write()
   write()
   write()
   write()
   write()
   if \verbose then {
      write()
      write()
      write()
      write()
      write()
      write()
      write()
      write()
      write()
      write()
      write()
      write()
      write()
      write()
      write()
      write()
      write()
      write()
      write()
      write()
      write()
      write()
      write()
      write()
      write()
      write()
      write()
      write()
      write()
      write()
      write()
      write()
      write()
      write()
      write()
      write()
      write()
      write()
      write()
      write()
   }
end