Mazes 2 NetLogo Model

Produced for the book series "Exercises for Artificial Intelligence";

Author: W. J. Teahan; Publisher: Ventus Publishing Aps, Denmark.

powered by NetLogo

view/download model file: Mazes-2.nlogo

WHAT IS IT?

This model shows how to get a simple reactive turtle agent to move around a maze. The model comes with four mazes: the empty maze (just outside walls); two mazes that are schematic representations of real life mazes in the United Kingdom - the Hampton Court Palace maze, and the Chevening House Maze; and a maze that is in the shape of a butterfly, created by Jamie Hughes, a student at Bangor University in North Wales.

This model is a variant of the Mazes model, but with the Butterfly Maze added as a fourth maze. The setup procedure has been changed to add the fourth maze. The setup-butterfly-maze procedure has also been added and the wall? reporter has been changed to cope with different coloured walls.

The model has also added fifth and sixth turtle behaviours - "Random Forward 3" and "Random Forward 4". These behaviours are defined by the sliders move-forward-behaviour, move-forward-behaviour-after-turning and move-forward-step-amount, and are the same as the behaviours used for the Searching Mazes model. This is where the turtle can perform one of three base behaviours - forward, left then forward or right then forward. The forward movement is defined by the sliders. For the "Random Forward 3" behaviour, the turtle chooses at random one of the three base behaviours, where the move forward action is defined by the sliders (as in the Searching Mazes model). For the "Random Forward 4" behaviour, the turtle chooses at random one of the three base behaviours, but ignores the slider values (except for the move-forward-step-amount slider) and chooses one of the four possible move forward behaviours at random (see The Interface section below to see how these are defined).


THE INTERFACE

The buttons in the Interface are defined as follows:
- setup: This will clear the environment and redraw the maze selected by the maze-being-searched chooser.

- go-once: This will get a single turtle agent to walk around the maze according to the behaviour selected in the turtle-behaviour chooser. This button will execute the walk turtle procedure once, not continuously

- go-forever: This will get a single turtle agent to continusously walk around the maze according to the behaviour selected in the turtle-behaviour chooser.

The choosers, sliders and switch are defined as follows:

- maze-being-searched: This specifies the maze that is being searched. This is either the empty maze, the Hampton Court Palace maze, the Chevening House maze or the Butterfly maze.

- turtle-behaviour: This specifies the type of reactive behaviour the walker turtle agent exhibits. The types of behaviour is as follows:
"hand-on-the-wall": This is the classic maze wall following behaviour of keeping a specific hand, either left or right, on a wall at all times. The model randomly decides itself whether the left hand or right hand is chosen.
"Random Forward 0": In this behaviour, the walker turtle agent moves forward unless there is a wall ahead, then tries to turn left unless there is a wall to the left, then tries to turn right unless there is a wall to the right, then randomly turns left or right as a last resort.
"Random Forward 1": In this behaviour, the walker turtle agent moves around mostly in straight lines in random directions for a random distance, but if it encounters a wall, it will bang against it for a short while (much like a woodpecker banging against a tree or a fly against a window) before backing off a random distance and continuing on with its random wanderings.
"Random Forward 2": In this behaviour, the walker turtle agent wanders around in random directions using small steps.
"Random Forward 3": In this behaviour, the walker turtle agent wanders around in random directions as defined by the sliders move-forward-behaviour, move-forward-behaviour-after-turning and move-forward-step-amount, and are the same as the behaviours used for the Searching-Mazes model. This is where the turtle can perform one of three behaviours - forward, left then forward or right then forward.
"Random Forward 4": This behaviour is similar to the Random Forward 3 behaviour except that instead of the move forward behaviour being defined by the sliders, it is chosen at random.

- move-forward-behaviour, move-forward-after-turning-behaviour: These choosers control how the turtle moves forward (i.e. not turning for the first chooser, or what happens after it has turned either left or right for the second chooser) when the turtle-behaviour slider is set to "Random Forward 3" or "Random Forward 4". The options for the type of move forward behaviour used by both these choosers are as follows:
"Move forward n steps unless hit wall": The turtle moves forward a number of steps determined by the move-forward-step amount slider.
"Move forward until hit wall": The turtle will move forward indefinitely until it hits a wall.
"Move forward until any open space": The turtle will move forward until it has found open space (i.e. until there is a wall in the way or there is open space on both sides).
"Move forward until open space after side wall": The turtle will move forward until it has found open space (i.e. until there is a wall in the way or there is open space on both sides but will only stop if it has previously been following a wall on either side).

- move-forward-step-amount: This is the amount of steps forward the turtle makes when it moves forward when the turtle-behaviour slider is set to "Random Forward 3" or "Random Forward 4" (either directly ahead of itself on its current heading, or after it has made a right or left turn).

- set-pen-down?: If set to On, this will draw the path of the walker turtle agent.

- left-cols, right-cols, above-rows, below-rows, entrance-cols: This sets the length and widths of the empty maze's side walls and entrance.

- col-patches-width, row-patches-width: This sets he width in patches for the columns and rows of the Hampton Court maze and Chevening House maze (i.e. the width between horizontal and vertical walls in these mazes).


HOW IT WORKS

It uses one ask patches command to set the patches blue that define the walls, and to set the remaining patches white. The code uses two procedures that are similar, setup-row and setup-col, to draw the walls in a horizontal row or vertical column respectively. These procedures take the row or column number as the first parameter, the colour that the walls are to be drawn with, and a list containing two-numbered range lists that define the segments where the walls are to be drawn in the row or column.

One turtle agent is created as the walker agent. It uses a simple proximity detector method (see the wall? reporter) to sense if there is a wall ahead at a specific angle and distance.


HOW TO USE IT

First select the maze using the maze-being-searched chooser, then select the behaviour of the turtle using the turtle-behaviour chooser. Then press the setup button, followed by either the go-once or go-forever buttons.

To get the turtle to draw its path, set the set-pen-down? switch to On.


WHAT IS ITS PURPOSE?

Its purpose is to show how a simple reactive agent can be effective (or not) at exploring a maze. The turtle has no cognitive abilities to recognize the situation it is in. e.g. that it is in a maze, that there is a goal it should try to reach, that it gets stuck at times, that there are alternative paths it can take at various points, or that it has travelled over the same point multiple times. The turtle agent simply reacts to the immediate situation it finds itself in using a simple proximity detector to sense a wall nearby.

The model also uses two virtual mazes that have a corresponding maze in real-life to demonstrate how virtual environments can mirror real-life environments but where the reflection can often be distorted in the process.


THINGS TO TRY

Try out the different behaviours on the different mazes by changing the values of the maze-being-searched and turtle-behaviour choosers.

See what happens when you change the value of the sliders.

Try changing the Settings of the environment such as the Patch Size and the maximum and minimum x and y co-ordinates.

Try to find out what happens in the Butterfly Maze when different turtle behaviours are chosen. Find out what happens to the way the maze is traversed when the value of the col-patches-width and the row-patches-width sliders are altered to change the dimensions of the maze. Why does the turtle agent end up going different ways with different slider values?


THINGS TO NOTICE

The turtle agent in the Butterfly Maze often ends up running around the outside of the maze, unlike the other three mazes. i.e. It can get to the exit at the top right by cheating. The reason it does this is that there are further ways of exiting the maze in the middle that are not the final exit at the top right that constitutes the goal. This is another illustration of how an environment has an important role in determining the behaviour of an agent, since this behaviour of the turtle agent in the Butterfly Maze does not arise in the other three mazes.

Notice also that there are many "islands" in the Butterfly Maze. You can get the turtle agent executing the hand on the wall behaviour to leap from one island to another by temporarily switching the behaviour to one of the other three behaviours using the turtle-behaviour slider, and then switching back. How many islands are there?


EXTENDING THE MODEL

Try adding your own behaviours to get the turtle agent to move around the maze.


NETLOGO FEATURES

The model uses the path-right-and-ahead reporter to allow the turtle agent to sense if there is a wall nearby.


RELATED MODELS

See the Mazes, Empty Maze, Hampton Court Maze and Chevening House Maze models.


CREDITS AND REFERENCES

To refer to this model in publications, please use:

Teahan, W. J. (2010). Mazes-2 NetLogo model.
Exercises for Artificial Intelligence. Ventus Publishing Aps.


PROCEDURES

; Mazes model.
; 
; Gets turtles with simple reactive behaviours to search various mazes.
;
; Copyright 2009 William John Teahan. All Rights Reserved.

turtles-own [direction]  ;;  1 follows right-hand wall,
                         ;; -1 follows left-hand wall

breed [mazes maze]
mazes-own
[ start-x start-y start-width; co-ordinates where the search starts
  entrance-x entrance-y entrance-width
  goal-type goal-x goal-y goal-width] ; specifies where the exit or goal is
          
to setup
  ca ;; clear everything

      if (maze-being-searched = "Empty Maze")
        [ setup-empty-maze
          create-mazes 1
          [  
            set start-x 0
            set start-y (- below-rows - 5)
            set start-width 6
            set entrance-x (- entrance-cols) + 1
            set entrance-y (- below-rows)
            set entrance-width 2 * entrance-cols - 2
            set goal-type "Exit"
            set goal-x entrance-x
            set goal-y above-rows
            set goal-width entrance-width
          ]
        ]
      if (maze-being-searched = "Hampton Court Maze")
        [ setup-hampton-court-maze
          create-mazes 1
          [
            set start-x (col-patches-width / 2)
            set start-y (- row-patches-width * 7 - 1)
            set start-width row-patches-width + 2
            set entrance-x 0
            set entrance-y (- row-patches-width * 6)
            set entrance-width col-patches-width
            set goal-type "Centre"
            set goal-x 0
            set goal-y (- 2 * row-patches-width)
            set goal-width col-patches-width
          ]
        ]
      if (maze-being-searched = "Chevening House Maze")
        [ setup-chevening-house-maze
          create-mazes 1
          [
            set start-x (col-patches-width / 2)
            set start-y (- row-patches-width * 12)
            set start-width row-patches-width + 2
            set entrance-x 1
            set entrance-y (- row-patches-width * 11)
            set entrance-width col-patches-width - 2
            set goal-type "Centre"
            set goal-x 1
            set goal-y (- row-patches-width)
            set goal-width entrance-width
          ]
        ]
      if (maze-being-searched = "Butterfly Maze")
        [ setup-butterfly-maze
          create-mazes 1
          [
            set start-x -16 * col-patches-width
            set start-y 13 * row-patches-width
            set start-width row-patches-width + 2
            set entrance-x -17 * col-patches-width
            set entrance-y 12 * row-patches-width
            set entrance-width col-patches-width * 2
            set goal-type "Exit"
            set goal-x 17 * col-patches-width - entrance-width
            set goal-y 12 * row-patches-width
            set goal-width entrance-width
          ]
        ]

  create-turtles 1 [
      ifelse (maze-being-searched = "Butterfly Maze")
        [ set shape "butterfly" ]
        [ set shape "mouse top" ]
      set size 5              ;; bigger turtles are easier to see
      set pen-size 2          ;; thicker lines are easier to see
      set color magenta
      
      ; move the turtle slowly to the entrance
      setxy [start-x] of maze 0 [start-y] of maze 0

      if set-pen-down
          [ pen-down ]

      ifelse (maze-being-searched = "Butterfly Maze")
        [ set heading 180 ] ; head south
        [ set heading 0 ]   ; head north
      repeat ([start-width] of maze 0) [forward 1 wait 0.2]

      set direction 1
      if not (maze-being-searched = "Chevening House Maze")
        [ ; randomly turn left or right
          ifelse random 2 = 0
          [ set heading 90
            set direction 1 ]   ;; follow right hand wall
          [ set heading 270
            set direction -1]   ;; follow left hand wall
          forward 2
        ]
  ]
  
  ; close "door" once they are in
  ask patches
    [ let xpos ([entrance-x] of maze 0)
      if pxcor >= xpos and pxcor <= xpos + ([entrance-width] of maze 0) and
        pycor = ([entrance-y] of maze 0)
      [ set pcolor sky ]]
end

to setup-empty-maze
  ca ;; clear everything
  
  ask patches
  [
    set pcolor white ;; make background full of white patches
          
    if (pxcor >= (- left-cols - entrance-cols) and pxcor <= (- entrance-cols) and
        pycor = (- below-rows))
      [set pcolor blue] ;; draws bottom left horizontal wall in blue

    if (pxcor >= (entrance-cols) and pxcor <= (right-cols + entrance-cols) and
        pycor = (- below-rows))
      [set pcolor blue] ;; draws bottom right horizontal wall in blue

    if (pxcor >= (- left-cols - entrance-cols) and pxcor <= (- entrance-cols) and
        pycor = (above-rows))
      [set pcolor blue] ;; draws top left horizontal wall in blue

    if (pxcor >= (entrance-cols) and pxcor <= (right-cols + entrance-cols) and
        pycor = (above-rows))         
      [set pcolor blue] ;; draws top left horizontal wall in blue

    if (pxcor = (- left-cols - entrance-cols) and
        pycor >= (- below-rows) and pycor <= (above-rows))
      [set pcolor blue] ;; draws left vertical wall in blue
      
    if (pxcor = (right-cols + entrance-cols) and
        pycor >= (- below-rows) and pycor <= (above-rows))
      [set pcolor blue] ;; draws right vertical wall in blue
  ]
end

to setup-row [row colour segments]
  foreach segments
  [
      if pycor = row * row-patches-width and
        (pxcor >= col-patches-width * (item 0 ?)) and (pxcor <= col-patches-width * (item 1 ?))
          [set pcolor colour]
  ]
end

to setup-col [col colour segments]
  foreach segments
  [
      if pxcor = col * col-patches-width and
        (pycor >= row-patches-width * (item 0 ?)) and (pycor <= row-patches-width * (item 1 ?))
          [set pcolor colour]
  ]
end

to setup-hampton-court-maze
  ca ;; clear everything
  
  ask patches
  [
      if (pxcor >= min-pxcor and pxcor <= max-pxcor and
        pycor >= min-pycor and pycor <= max-pycor)
          [set pcolor white] ;; make background full of white patches
      
      setup-row  5 blue [[-9 10]]
      setup-row  4 blue [[-8 -5] [-3 -1] [0 3] [5 9]]
      setup-row  3 blue [[-7 -4] [-2 2] [4 8]]
      setup-row  2 blue [[-6 -1] [1 4] [5 7]]
      setup-row  1 blue [[-3 3] [8 9]]
      setup-row  0 blue [[-8 -7] [9 10]]
      setup-row -1 blue [[-9 -8]]
      setup-row -2 blue [[-8 -7] [-3 0] [1 3]]
      setup-row -3 blue [[-4 -1] [2 4] [6 8]]
      setup-row -4 blue [[-7 -1] [1 9]]
      setup-row -5 blue [[-8 10]]
      setup-row -6 blue [[-9 0] [1 10]]

      setup-col 10 blue [[-6 5]]
      setup-col  9 blue [[-4 -1] [1 4]]
      setup-col  8 blue [[-3 1] [2 3]]
      setup-col  7 blue [[-2 2]]
      setup-col  6 blue [[-4 1]]
      setup-col  5 blue [[-3 2]]
      setup-col  4 blue [[-3 2] [3 5]]
      setup-col  3 blue [[-2 1] [2 4]]
      setup-col  1 blue [[-4 -2]]
      setup-col  0 blue [[-5 -2] [1 3]]
      setup-col -1 blue [[-4 -3] [4 5]]                  
      setup-col -3 blue [[-2 1] [2 4]]
      setup-col -4 blue [[-3 2] [3 5]]
      setup-col -5 blue [[-4 1]]
      setup-col -6 blue [[-3 2]]
      setup-col -7 blue [[-4 -3] [-2 0] [1 3]]
      setup-col -8 blue [[-5 -2] [0 4]]
      setup-col -9 blue [[-6 5]]
  ]
end

to setup-chevening-house-maze
  ca ;; clear everything
  
  ask patches
  [
      if (pxcor >= min-pxcor and pxcor <= max-pxcor and
        pycor >= min-pycor and pycor <= max-pycor)
          [set pcolor white] ;; make background full of white patches
      
      setup-row  12 blue [[-11 12]]
      setup-row  11 blue [[-10 11]]
      setup-row  10 blue [[-9 10]]
      setup-row   9 blue [[-8 0] [1 9]]
      setup-row   8 blue [[-7 -1] [2 8]]
      setup-row   7 blue [[-6 0] [1 7]]
      setup-row   6 blue [[-5 0] [1 6]]
      setup-row   5 blue [[-4 -1] [2 5]]
      setup-row   4 blue [[-3 0] [1 4]]
      setup-row   3 blue [[-2 3]]
      setup-row   2 blue [[-1 2]]
      setup-row   1 blue [[-9 -5] [-4 -2] [3 5] [6 8] [10 11]]
      setup-row  -0 blue [[-9 -7] [3 5] [6 10]]
      setup-row  -1 blue [[-1 0] [1 2] [7 9]]
      setup-row  -2 blue [[-2 0] [1 3]]
      setup-row  -3 blue [[-3 -1] [1 4]]
      setup-row  -4 blue [[-4 -2] [2 5]]
      setup-row  -5 blue [[-5 -3] [2 6]]
      setup-row  -6 blue [[-6 -3] [1 7]]
      setup-row  -7 blue [[-7 -2] [0 8]]
      setup-row  -8 blue [[-8 1] [3 9]]
      setup-row  -9 blue [[-9 0] [3 10]]
      setup-row -10 blue [[-10 -1] [2 11]]
      setup-row -11 blue [[-11 0] [1 12]]

      setup-col  12 blue [[-11 12]]
      setup-col  11 blue [[-10 1] [2 11]]
      setup-col  10 blue [[-9 0] [1 10]]
      setup-col   9 blue [[-8 -1] [0 9]]
      setup-col   8 blue [[-7 -2] [1 8]]
      setup-col   7 blue [[-6 -1] [2 7]]
      setup-col   6 blue [[-5 0] [1 6]]
      setup-col   5 blue [[-4 0] [1 5]]
      setup-col   4 blue [[-3 -1] [2 4]]
      setup-col   3 blue [[-2 0] [1 3]]
      setup-col   2 blue [[-10 -7] [-1 2]]
      setup-col   1 blue [[-11 -8] [-6 -1] [4 6] [7 9]]
      setup-col   0 blue [[-11 -9] [-7 -1] [4 6] [7 9]]
      setup-col  -1 blue [[-8 -3] [-1 2]]
      setup-col  -2 blue [[-7 -4] [-2 0] [1 3]]
      setup-col  -3 blue [[-3 1] [2 4]]
      setup-col  -4 blue [[-4 0] [1 5]]
      setup-col  -5 blue [[-5 6]]
      setup-col  -6 blue [[-6 0] [2 7]]
      setup-col  -7 blue [[-7 0] [1 8]]
      setup-col  -8 blue [[-8 -1] [2 9]]
      setup-col  -9 blue [[-9 0] [1 10]]
      setup-col -10 blue [[-10 11]]
      setup-col -11 blue [[-11 12]]
  ]
end

to setup-butterfly-maze
  ca ;; clear everything
  
  ask patches
  [
      set pcolor white ;; make background full of white patches
    
      setup-row  12 pink   [[-19 -17] [-15 -12] [12 15] [17 19]]
      setup-row  11 pink   [[-21 -19] [-17 -14] [-12 -10] [10 12] [14 17] [19 21]]
      setup-row  10 pink   [[-23 -21] [-19 -16] [-14 -10] [10 14] [16 19] [21 23 ]]
      setup-row   9 yellow [[-21 -12] [-10 -3] [3 10] [12 21]]
      setup-row   8 pink   [[-21 -5] [5 21]]
      setup-row   8 orange [[-2 2]]
      setup-row   7 pink   [[-21 -17] [-15 -5] [5 15] [17 21]]
      setup-row   6 pink   [[-19 -7] [7 19]]
      setup-row   5 yellow [[-21 -5] [5 21]]
      setup-row   5 red    [[-1 1]]
      setup-row   4 violet [[-3 2] [2 3]]
      setup-row   4 orange [[-2 2]]
      setup-row   4 pink   [[-23 -18] [-16 -3] [3 16] [18 23]]
      setup-row   3 pink   [[-19 -5] [-1 -1] [1 1] [5 19]]
      setup-row   2 yellow [[-8 -3] [3 8]]
      setup-row   1 pink   [[-15 -4] [4 15]]
      setup-row   1 red    [[-2 -1] [1 2]]
      setup-row   0 red    [[-1 1]]
      setup-row   0 violet [[-6 -4] [4 6]]
      setup-row  -1 red    [[0 0]]
      setup-row  -2 violet [[-6 -3] [3 6]]
      setup-row  -3 pink   [[-18 -3] [3 18]]
      setup-row  -4 violet [[-3 -2] [2 3]]
      setup-row  -4 yellow [[-21 -18] [-16 -5] [5 16] [18 21]]
      setup-row  -5 yellow [[-19 -3] [3 19]]
      setup-row  -5 pink   [[-1 -1] [1 1]]
      setup-row  -6 violet [[-1 -1] [1 1]]
      setup-row  -6 yellow [[-19 -5] [5 19]]
      setup-row  -7 violet [[-3 -2] [2 3]]
      setup-row  -7 yellow [[-21 -17] [-15 -3] [3 15] [17 21]]
      setup-row  -8 yellow [[-23 -7] [7 23]]
      setup-row  -9 orange [[-2 2]]
      setup-row  -9 yellow [[-21 -12] [-10 -5] [5 10] [12 21]]
      setup-row -10 pink   [[-23 -16] [-14 -8] [8 14] [16 23]]
      setup-row -11 pink   [[-21 -14] [-12 -10] [10 12] [14 21]]
      setup-row -12 pink   [[-19 -12] [12 19]]

      setup-col  23 black  [[-10 -8] [4 10]]
      setup-col  22 black  []
      setup-col  21 black  [[-11 -10] [-8 -4] [5 6] [10 11]]
      setup-col  20 black  []
      setup-col  19 black  [[-12 -11] [3 4] [6 7] [9 10] [11 12]]
      setup-col  18 black  [[-4 -3]]
      setup-col  17 black  [[5 6]]
      setup-col  16 black  [[-10 -9] [10 11]]
      setup-col  15 black  [[-7 -6] [1 3] [8 9]]
      setup-col  14 black  [[7 8]]
      setup-col  13 black  []
      setup-col  12 black  [[-12 -11] [11 12]]
      setup-col  11 black  []
      setup-col  10 black  [[-11 -10] [9 11]]
      setup-col   9 black  []
      setup-col   8 black  [[-10 -9]]
      setup-col   7 black  []
      setup-col   6 black  []
      setup-col   5 black  [[-9 -7] [5 7]]
      setup-col   4 black  [[-3 -2] [0 1]]
      setup-col   3 black  [[-7 -4] [2 9]]
      setup-col   2 black  [[-9 -7] [4 8]]
      setup-col   1 black  [[6 7]]
      setup-col   1 pink   [[10 11]]
      setup-col   1 black  [[8 10]]
      setup-col   0 blue   []
      setup-col  -1 blue   [[8 10]]
      setup-col  -1 pink   [[10 11]]
      setup-col  -1 blue   [[6 7]]
      setup-col  -2 orange  [[-9 -7] [4 8]]
      setup-col  -3 blue   [[-7 -4] [2 9]]
      setup-col  -4 blue   [[-3 -2] [0 1]]
      setup-col  -5 blue   [[-9 -7] [5 7]]
      setup-col  -6 blue   []
      setup-col  -7 blue   []
      setup-col  -8 blue   [[-10 -9]]
      setup-col  -9 blue   []
      setup-col -10 blue   [[-11 -10] [9 11]]
      setup-col -11 blue   []
      setup-col -12 blue   [[-12 -11] [11 12]]
      setup-col -13 blue   []
      setup-col -14 blue   [[7 8]]
      setup-col -15 blue   [[-7 -6] [1 3] [8 9]]
      setup-col -16 blue   [[-10 -9] [10 11]]
      setup-col -17 blue   [[5 6]]
      setup-col -18 blue   [[-4 -3]]
      setup-col -19 blue   [[-12 -11] [3 4] [6 7] [9 10] [11 12]]
      setup-col -20 blue   []
      setup-col -21 blue   [[-11 -10] [-8 -4] [5 6] [10 11]]
      setup-col -22 blue   []
      setup-col -23 blue   [[-10 -8] [4 10]]
  ]

end
  
to go
  ask turtle 1 [ walk ]
  tick
end

to walk  ;; turtle procedure
  ;; turn right if necessary

  ifelse set-pen-down [ pen-down ] [ pen-up ]

  if count neighbors4 with [pcolor = blue] = 4
     [ user-message "Trapped!"
       stop ]
  let xpos [goal-x] of maze 0
  if xcor >= xpos and xcor <= xpos + [goal-width] of maze 0 and
     ycor = [goal-y] of maze 0 
     [ ifelse [goal-type] of maze 0 = "Exit"
       [ user-message "Found the exit!" ]
       [ user-message "Made it to the centre of the maze!" ]
       stop ]
     
  if (turtle-behaviour = "Hand On The Wall") [behaviour-wall-following]
  if (turtle-behaviour = "Random Forward 0") [behaviour-random-forward-0]
  if (turtle-behaviour = "Random Forward 1") [behaviour-random-forward-1]
  if (turtle-behaviour = "Random Forward 2") [behaviour-random-forward-2]
  if (turtle-behaviour = "Random Forward 3") [behaviour-random-forward-3]
  if (turtle-behaviour = "Random Forward 4") [behaviour-random-forward-4]
end

to-report wall? [angle dist]
  ;; note that angle may be positive or negative.  if angle is
  ;; positive, the turtle looks right.  if angle is negative,
  ;; the turtle looks left.
  let patch-color [pcolor] of patch-right-and-ahead angle dist
    
  report patch-color != white ; anything not the background (white) is deemed to be a wall
end

to-report wall-ahead? [dist]
  ;; reports whether there is a wall directly ahead at dist.
  let patch-color [pcolor] of patch-ahead dist
  
  report patch-color != white ; blue if it is a wall, sky if it is the closed entrance
end

to-report wall-anywhere-ahead? [dist]
  ;; reports whether there is a wall directly ahead anywhere up to dist.

  let d 1
  let wall false
  while [d <= dist and not wall]
  [ if wall-ahead? d
      [ set wall true ]
    set d d + 1 ]
  report wall
end

to behaviour-wall-following
; classic 'hand-on-the-wall' behaviour
  if not wall? (90 * direction) 1 and wall? (135 * direction) (sqrt 2)
     [ rt 90 * direction ]
  
  ;; wall straight ahead: turn left if necessary (sometimes more than once)
  while [wall? 0 1] [ lt 90 * direction]

  ;; move forward
  fd 1
end

to behaviour-random-forward-0
; moves forward unless there is a wall, then tries to turn left, then right
; then randomly turns as a last resort
  if wall? 0 1
    [ ifelse wall? 90 1
        [ lt 90 ]
        [ ifelse wall? 270 1
          [ rt 90 ]
          [ ifelse random 2 = 0 [lt 90] [rt 90] ]]]

  ;; move forward
  fd 1
end

to behaviour-random-forward-1
; moves around mostly in straight lines
  ifelse wall? 0 1
    [ bk 1 ]
 ;else
    [ let r random 20
      ifelse r = 0
        [ if not wall? 90 1 [rt 90 fd 1] ]
     ;else
        [ ifelse r = 1
            [ if not wall? 270 1 [lt 90 fd 1] ]
            [ let f random 5
              while [not wall? 0 1 and f > 0]
                [ fd 1
                  set f f - 1]]]]
end

to behaviour-random-forward-2
; moves around in random small steps
  let r random 3

  ifelse r = 0
    [ if not wall? 90 1 [rt 90 fd 1] ]
    [ ifelse r = 1
        [ if not wall? 270 1 [lt 90 fd 1] ]
        [ if not wall? 0 1 [fd 1] ]]
end

to behaviour-random-forward-3
; Moves around randomly, but by reacting to the maze.
; It uses the behaviours that were developed for the Searching-Mazes model.

  let b one-of [1 2 3] ; choose one of 3 sub-behaviours, at random
  
  if (b = 1) ; choose the move forward sub-behaviour
    [ behaviour-move-forward move-forward-behaviour ]
  if (b = 2) ; choose the left turn then move forward sub-behaviour
    [ behaviour-turn-left-then-forward move-forward-behaviour-after-turning ]
  if (b = 3) ; choose the right turn then move forward sub-behaviour
    [ behaviour-turn-right-then-forward move-forward-behaviour-after-turning ]
end

to behaviour-random-forward-4
; Moves around randomly, but by reacting to the maze.
; It uses the behaviours that were developed for the Searching-Mazes model.

  let b one-of [1 2 3] ; choose one of 3 sub-behaviours, at random
  let m one-of ; choose one of 4 sub-behaviours, at random
  [ "Move forward n steps unless hit wall"
    "Move forward until hit wall"
    "Move forward until any open space"
    "Move forward until open space after side wall" ]
  
  if (b = 1) ; choose the move forward sub-behaviour
    [ behaviour-move-forward m ]
  if (b = 2) ; choose the left turn then move forward sub-behaviour
    [ behaviour-turn-left-then-forward m ]
  if (b = 3) ; choose the right turn then move forward sub-behaviour
    [ behaviour-turn-right-then-forward m ]
end

to behaviour-move-forward [forward-behaviour]
; move forward behaviour defined by 

  if (forward-behaviour = "Move forward n steps unless hit wall")
    [ behaviour-move-forward1 move-forward-step-amount ]
  if (forward-behaviour = "Move forward until hit wall")
    [ behaviour-move-forward2 ]
  if (forward-behaviour = "Move forward until any open space")
    [ behaviour-move-forward3 ]
  if (forward-behaviour = "Move forward until open space after side wall")
    [ behaviour-move-forward4 ]  
end

to behaviour-move-forward1 [dist]
; move forward dist steps unless there is a wall in the way

  if (not wall-anywhere-ahead? dist)
    [ fd dist ]; move forward
end

to behaviour-move-forward2
; move forward until there is a wall in the way

  while [not wall-ahead? 1]
    [ ; move forward
      fd 1
    ]
end

to behaviour-move-forward3
; move forward until there is a wall in the way or there is open space on either side

  let open-space false
  
  while [not wall-ahead? 1 and not open-space]
    [ ; move forward
      fd 1
      if not (wall? -90 1) and not (wall? 90 1)
        [ set open-space true ] 
    ]
end

to behaviour-move-forward4
; move forward until there is a wall in the way or there is open space on either side
; but will only stop if there has been following a wall on either side

  let open-space false
  let by-wall false

  while [not wall-ahead? 1 and not open-space]
    [ ; move forward
      fd 1
      if (wall? -90 1) or (wall? 90 1)
        [ set by-wall true]
      if not (wall? -90 1) and not (wall? 90 1) and by-wall
        [ set open-space true ] 
    ]
end

to behaviour-turn-left
; turn left 90 degrees.
  lt 90
end

to behaviour-turn-right
; turn right 90 degrees.
  rt 90
end

to behaviour-turn-left-then-forward [forward-behaviour]
; turn left 90 degrees
  behaviour-turn-left
  behaviour-move-forward forward-behaviour
end

to behaviour-turn-right-then-forward [forward-behaviour]
; turn right 90 degrees.
  behaviour-turn-right
  behaviour-move-forward forward-behaviour
end
;
; Copyright 2009 by William John Teahan.  All rights reserved.
;
; Permission to use, modify or redistribute this model is hereby granted,
; provided that both of the following requirements are followed:
; a) this copyright notice is included.
; b) this model will not be redistributed for profit without permission
;    from William John Teahan.
; Contact William John Teahan for appropriate licenses for redistribution for
; profit.
;
; To refer to this model in publications, please use:
;
; Teahan, W. J. (2009).  Mazes NetLogo model.
;   Artificial Intelligence. Ventus Publishing Aps.
;