{{{  description of the problem and its solution
{{{  the algorithm
; These macros 'solve' any maze produced by the a-maze-ing maze.c program.
;
; First, a bit of maze theory.
; If you were put into a maze, a guaranteed method of finding your way
; out of the maze is to put your left hand onto a wall and just keep walking,
; never taking your hand off the wall. This technique is only guaranteed to
; work if the maze does not have any 'islands', or if the 'exit' is on the
; same island as your starting point. These conditions hold for the mazes
; under consideration.
;
; Assuming that the maze is made up of horizontal and vertical walls spaced
; one step apart and that you can move either north, south, east or west,
; then you can automate this procedure by carrying out the following steps.
;
; 1. Put yourself somewhere in the maze near a wall.
; 2. Check if you have a wall on your left. If so, go to step 4.
; 3. There is no wall on your left, so turn on the spot to your left and step
;    forward by one step and repeat step 2.
; 4. Check what is directly in front of you. If it is a wall, turn on the
;    spot to your right by 90 degrees and repeat step 4.
; 5. There is no wall in front of you, so step forward one step and
;    go to step 2.
}}}
{{{  the used maze-format
; By examining a maze produced by the maze.c program you will see that
; each square of the maze is one character high and two characters wide.
; To go north or south, you move by a one character step, but to move east or
; west you move by a two character step. Also note that in any position
; there are four places where walls could be put - to the north, to the south,
; to the east and to the west.
; A wall exists to the north of you if the character to the north of
; you is a _ (otherwise it is a space).
; A wall exists to the east of you if the character to the east of you
; is a | (otherwise it is a .).
; A wall exists to the west of you if the character to the west of you
; is a | (otherwise it is a .).
; A wall exists to the south of you if the character where you are
; is a _ (otherwise it is a space).
}}}
{{{  implementation
; i implemented it with a couple of macros
;    maze-step - do one of the above mentioned steps of
;                the algorithm
;    set-destination -
;                check the current cursor-position to be a correct
;                destination-point. (Its a little bit simple, if you
;                are not in the maze, it will not work correct).
;    get-new-maze -
;                append at the end of ypur text a new maze.
;                the command 'maze' must be available.
;
; all other macros are help-functions
;
; used variables:
;   maze-dir: direction of movement
;             0 - up
;             1 - left
;             2 - down
;             3 - right
;   maze-state: state of the machine like above
;   maze-front: is set by front-wall, if there is a wall
}}}
{{{  how to do it
; 0. Put the command maze in your path. This is the same a for vi and the
;    used maze-format is the same too!
; 1. put the following macros in your OCL-file and make a new .origamirc .
; 2. Choose keybindings for the macros maze-step, get-new-maze, set-destination
; 3. get a maze with get-new-maze
; 4. go into the maze and set the destination with set-destination
; 5. do maze-stepo and it runs!!!
}}}
}}}
{{{  help-functions
{{{  turn-left
(deffun turn-left (
  if counter-0 maze-dir (
    set-counter maze-dir 3
  ) else (
    add-counter maze-dir -1
  )fi
 )
)
}}}
{{{  test-case
(deffun test-case (
  set-counter case-1 -1
  sum-counter case-1 case-0
  set-counter case-2 -1
  sum-counter case-2 case-1
  set-counter case-3 -1
  sum-counter case-3 case-2
  set-counter case-4 -1
  sum-counter case-4 case-3
  set-counter case-5 -1
  sum-counter case-5 case-4
))
}}}
{{{  front-wall
(deffun front-wall (
  set-counter maze-front 0
  set-counter case-0 0
  sum-counter case-0 maze-dir
  test-case
  case
    {{{  dir up
    (counter-0 case-0 (
      O_UP
      if test-char "_ (set-counter maze-front 1) fi
      O_DOWN
    ))
    }}}
    {{{  dir left
    (counter-0 case-1 (
       O_LEFT
       if test-char "| (set-counter maze-front 1) fi
       O_RIGHT
    ))
    }}}
    {{{  dir down
    (counter-0 case-2 (
      if test-char "_ (set-counter maze-front 1) fi
    ))
    }}}
    {{{  dir right
    (counter-0 case-3 (
      O_RIGHT
      if test-char "| (set-counter maze-front 1) fi
      O_LEFT
    ))
    }}}
    (not(counter-0 case-3) (message-exit "incorrect_dir_in_front))
  esac
))
}}}
{{{  go
(deffun go (
  set-counter case-0 0
  sum-counter case-0 maze-dir
  test-case
  case
    (counter-0 case-0 (O_UP))
    (counter-0 case-1 (O_LEFT O_LEFT))
    (counter-0 case-2 (O_DOWN))
    (counter-0 case-3 (O_RIGHT O_RIGHT))
    (not(counter-0 case-3) (message-exit "incorrect_dir_in_go))
  esac
))
}}}
{{{  m-delay
(defmac m-delay (
  set-counter delay-time 0
  while counter>0 delay-time (add-counter delay-time -1 O_REFRESH)
))
}}}
}}}
{{{  get new maze
(deffun get-new-maze (
  O_BOT_OF_FOLD
  O_START_OF_LINE
  store-line maze-begin-line
  shell-command
     "echo "  "Please_enter_size "  ";
     "maze "  ">maze.new
  O_RETURN
  O_RETURN
  O_CREATE_FOLD
  O_CREATE_FOLD
  "maze.new
  O_ATTACH_FILE
  O_FILE_FOLD
  O_REMOVE_FOLD
  O_START_OF_LINE
  message-exit "new_maze_read
))
}}}
{{{  set-destination
(deffun set-destination (
  if or(test-char "  ,test-char "_)
    (O_DEL_CHAR_RIGHT "X )
  else
    (message-exit "no_correct_position)
  fi
))
}}}
{{{  maze-step
(deffun maze-step (
  set-counter maze-state 1
  set-counter maze-dir 0
  while not(test-char "X) (
    set-counter case-0 0
    sum-counter case-0 maze-state
    test-case
    case
      {{{  state 1
      (counter-0 case-1 (
        goto-line-counter maze-begin-line
        O_FIND "X O_RETURN
        if not(test-char "X) (message-exit "no_destination-point) fi
        goto-line-counter maze-begin-line
        O_FIND "| O_RETURN
        O_RIGHT
        set-counter maze-state 2
      ))
      }}}
      {{{  state 2
      (counter-0 case-2 (
        turn-left
        front-wall
        repeat 3(turn-left)
        if counter-0 maze-front (
          set-counter maze-state 3
        ) else (
          set-counter maze-state 4
        ) fi
      ))
      }}}
      {{{  state 3
      (counter-0 case-3 (
        turn-left
        go
        set-counter maze-state 2
      ))
      }}}
      {{{  state 4
      (counter-0 case-4 (
        front-wall
        if counter-0 maze-front
          (set-counter maze-state 5)
        else
          (repeat 3 (turn-left))
        fi
      ))
      }}}
      {{{  state 5
      (counter-0 case-5 (
        go
        set-counter maze-state 2
      ))
      }}}
      (not(counter-0 case-5) (message-exit "incorrect_maze_state))
    esac
    m-delay
  )
  message-exit "faster_than_vi
))
}}}
