How to play:

Click on the arrows to select them; then click on the board to place them. You can place arrows on any empty square, including the red square. When you're done, click on the button that says "click here when ready" to start the red square moving. You can't start moving until you've placed an arrow on the red square to give it an initial direction.

Every time you click on the button, the square takes a step in the current direction. When it enters a space with an arrow, its current direction will change to that of the arrow, and the arrow will rotate clockwise. If it hits a wall (#), it dies. If it enters a square containing an unlocked door ( "X" ), you win the game. If it enters a square containing a locked door ( "*" ), it unlocks it as it goes past.

[Click to play]

0 - Test puzzle
1 - AC's first
2 - Left, Right, Left, Right
3 - Loopdeloop (2 solutions)
4 - Failed Combination Lock (Try to find a combination that doesn't work!)
5 - Back and Forth
6 - Misdirection

To do:
• Use cutesy images instead of a red square and ascii art
• Ability to put arrows back from board into palette - probably won't do this; - I want to be able to put arrows on the board in predetermined locations, as it would make for more interesting puzzles. I'll add an undo button instead. - MoonShadow
You could do a 'fixed' bit on arrows if you wanted to. --K
I thought about that, but I think the changes for undo would be simpler and more readable (due to being localised).. - MoonShadow
• Make the red square move automatically using every{} once started; animate?
• There seems to be something wrong with the row count, at least for LRLR.  Setting it to 9 means the count is off and the following puzzle(s) won't load, but it renders correctly.  Setting it to 10 renders 11 rows, adding an extra row of walls at the bottom. --K
OK, got it - a previous fix was overzealous.. - MoonShadow

• (PeterTaylor) I find a very strange bug. The "click here when done" button doesn't work on level 0, but it does on level 5. Debian stable version of Firefox. Will try other levels later.
Can you post the link at the time the bug occurs? Bear in mind the button won't work until you've placed an arrow on the red square to give it an initial direction.. - MoonShadow
(PeterTaylor) Yes, I just realised that was the problem. Could the button text be altered and change to "Click here..." when an arrow is placed on the red square?

Solutions:
/ArrowMazeSolution5 discusses game 5: there are at least 3 ways to solve it with 3 arrows left over. Further discussion on that subpage.

Puzzle array contains all available puzzles in the form:
board size, width, number of initial pieces, the list of initial pieces, the board layout

Squares are integers, coded as follows:
0 - empty
1, 2, 3, 4 - left, right, up, down
5 - wall
6 - open door
7 - locked door
8+(one of the above) - player starts on this square

```logic
{
const array puzzles
{
6*6, 6, 4, 1, 2, 2, 3,
5, 5, 5, 5, 5, 5,
5, 8, 0, 0, 0, 5,
5, 0, 0, 0, 0, 5,
5, 0, 0, 7, 0, 5,
5, 0, 0, 0, 0, 5,
5, 5, 5, 5, 5, 5,

7*7, 7, 5, 1, 3, 3, 4, 4,
5, 5, 5, 5, 5, 5, 5,
5, 0, 5, 0, 0, 0, 5,
5, 0, 0, 0,11, 0, 5,
5, 0, 0, 5, 0, 0, 5,
5, 0, 7, 5, 0, 0, 5,
5, 0, 0, 5, 0, 0, 5,
5, 5, 5, 5, 5, 5, 5,

11*10, 11, 12, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 4, 0, 0, 5, 0, 5, 0, 0, 4, 5,
5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5,
5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5,
5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5,
5, 0, 5, 5, 0, 5, 0, 5, 5, 0, 5,
5, 7, 5, 0, 0, 8, 0, 0, 5, 7, 5,
5, 0, 5, 0, 0, 0, 0, 0, 5, 0, 5,
0, 0, 0, 5, 0, 0, 0, 5, 0, 0, 0,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,

7*7, 7, 4, 4, 1, 1, 1,
5, 5, 5, 5, 5, 5, 5,
0, 0, 5, 0, 0, 0, 0,
0, 0, 8, 7, 5, 0, 0,
5, 5, 5, 0, 5, 5, 5,
2, 0, 0, 2, 0, 0, 2,
0, 0, 0, 0, 0, 0, 0,
5, 5, 5, 5, 5, 5, 5,

9*9, 9, 4, 1, 2, 3, 4,
5, 5, 5, 5, 5, 5, 5, 5, 5,
5,12, 0, 2, 0, 4, 0, 1, 5,
5, 0, 5, 0, 5, 0, 5, 0, 5,
5, 2, 0, 0, 0, 0, 0, 4, 5,
5, 0, 5, 0, 5, 0, 5, 0, 5,
5, 2, 0, 0, 0, 0, 0, 1, 5,
5, 0, 5, 0, 5, 0, 5, 0, 5,
5, 2, 0, 3, 0, 3, 0, 6, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5,

11*10, 11, 9, 2, 2, 2, 3, 3, 3, 4, 4, 4,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 0, 0, 0, 5, 0, 0, 5,
5, 5, 0, 0, 0, 0, 0, 0, 1, 0, 5,
5, 5, 0, 5, 5, 0, 5, 5, 0, 5, 5,
5, 0,10, 0, 0, 1, 0, 7, 0, 0, 5,
5, 0, 0, 1, 5, 0, 5, 5, 0, 5, 5,
5, 0, 0, 0, 5, 0, 5, 5, 0, 5, 5,
5, 0, 5, 5, 5, 0, 0, 0, 1, 5, 5,
5, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,

7*7, 7, 4, 1, 2, 3, 4,
5, 5, 5, 5, 5, 5, 5,
5, 4, 4, 4, 4, 1, 5,
5, 2, 0, 4, 0, 1, 5,
5, 2, 2, 9, 1, 1, 6,
5, 2, 0, 3, 0, 1, 5,
5, 2, 3, 3, 3, 3, 5,
5, 5, 5, 5, 5, 5, 5,
}

const int numpuzzles { 7 }
const int numlabels { 7 }

array board
{ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
}
const int maxboardwidth { 11 }
const int maxboardheight { 11 }

array pieces
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}
const int maxpieces { 13 }

const array nextboard { 0, 3, 4, 2, 1, 5, 6, 6 }
const array nextstate { 2, 2, 2, 2, 2, 4, 3, 2 }
local int selected { -1 }
local int scratch  { 0 }

int boardsize { 0 }
int boardwidth { 0 }
int numpieces { 0 }
array nextdirection { 0, -1, 1, 0, 0, 0, 0, 0 }

int gamestate { 0 }
int direction { 0 }
int location { 0 }

for i ( 0 .. (numpuzzles - 1) )
{
when
{
gamestate == 0
}
allow
{
scratch = 0;
for j ( 0 .. (i-1) )
{
scratch = scratch + 3 + puzzles[scratch] + puzzles[scratch+2];
}
boardsize = puzzles[scratch];
boardwidth = puzzles[scratch+1];
numpieces = puzzles[scratch+2];
scratch += 3;
for j ( 0 .. (numpieces-1) )
{
pieces[j] = puzzles[scratch+j];
}
scratch += numpieces;
location = boardwidth + 1;
for j ( 0 .. (boardsize-1) )
{
board[j] = puzzles[scratch+j];
if( board[j] & 8 )
{
location = j;
}
}
nextdirection[3] = 0 - boardwidth;
nextdirection[4] = boardwidth;
direction = 0;
selected = -1;
gamestate = 1;
}
label { "puzzle " i }
}

when
{
( gamestate == 1 ) and ( (board[location]&7) != 0 )
}
allow
{
selected = -1;
gamestate = 2;
direction = nextdirection[(board[location]&7)];
}
label { "act" }

when
{
( gamestate == 5 ) and ( (board[location]&7) < 5  )
}
allow
{
selected = -1;
gamestate = 2;
direction = nextdirection[(board[location]&7)];
}
label { "playtest" }

for i ( 0 .. (boardsize-1) )
{
when
{
( gamestate == 1 ) and (selected > -1) and ( (board[i]&7) == 0 )
}
allow
{
board[i] += pieces[selected];
pieces[selected] = 0;
selected = -1;
}
label
{
"place " i
}

when
{
( gamestate == 5 ) and (selected > -1)
}
allow
{
if( pieces[selected] == 8 )
{
board[location] = board[location] & 7;
board[i] = (board[i] ^ 8);
location = i;
}
if( pieces[selected] != 8 )
{
board[i] = pieces[selected] | ( board[i] & 8 );
}
}
label
{
"place " i
}
}

for i ( 0 .. (numpieces-1) )
{
when
{
(( gamestate == 1 ) or ( gamestate == 5 ))
}
allow
{
scratch = -1;
if( selected != i )
{
scratch = i;
}
selected = scratch;
}
label { "select " i }
}

when
{
gamestate == 2

}
allow
{
board[location] = nextboard[(board[location] & 7)];
location += direction;
if( nextdirection[board[location]] != 0 )
{
direction = nextdirection[board[location]];
}
gamestate = nextstate[board[location]];
board[location] += 8;
}
label { "act" }

when
{
gamestate == 0
}
allow
{
boardsize = maxboardwidth*maxboardheight;
boardwidth = maxboardwidth;
numpieces = 9;
for i ( 0..(boardsize-1) )
{
board[i] = 5;
}
for i ( 0..(numpieces-1) )
{
pieces[i] = i;
}
location = 0;
nextdirection[3] = 0 - boardwidth;
nextdirection[4] = boardwidth;
direction = 0;
selected = -1;
gamestate = 5;
}
label { "playtest mode" }

when
{
gamestate > 2
}
allow
{
boardsize = 0;
boardwidth = 0;
numpieces = 0;
location = 0;
nextdirection[3] = 0;
nextdirection[4] = 0;
direction = 0;
selected = -1;
gamestate = 0;
}
label { "act" }
}

display
{
stringtable griditems
{
" ",  "←", "→", "↑", "↓",  "#", "X", "*", "player start location"
}

stringtable statenames
{
}

stringtable labels
{
"Test puzzle",
"AC's first",
"Left, Right, Left, Right",
"Loopdeloop",
"Failed Combination Lock",
"Back and Forth",
"Misdirection"
}

for y ( 0 .. (maxboardheight-1) )
{
for x ( 0 .. (maxboardwidth-1) )
{
box
{
if( (x < boardwidth) and (y < (boardsize / boardwidth) ) )
{
width { 2em }
height { 2em }
border { 1px solid black }
content { griditems[ board[x+boardwidth*y] & 7 ] }
if( board[x+boardwidth*y] & 8 )
{
background { red }
}
bind_action { "place " x+boardwidth*y }
}
}
}
newline
}

newline

for j ( 0 .. (maxpieces-1) )
{
box
{
if( ( ( gamestate == 1 ) or ( gamestate == 5) ) and ( j < numpieces ) )
{
width { 2em }
height { 2em }
border { 1px solid black }
if( selected == j )
{
background { yellow }
}
content { griditems[ pieces[j] ] }
bind_action { "select " j }
}
}
}

newline
newline

box
{
border { 1px solid black }
content { statenames[gamestate] }
bind_action { "act" }
}
box
{
bind_action { "playtest" }
while_active
{
border { 1px solid black }
content { "Playtest (NB. destructive right now - copy the link)" }
}
}

newline

for j ( 0 .. (numpuzzles-1) )
{
newline
box
{
if( gamestate == 0 )
{
border { 1px solid black }
if( j < numlabels )
{
content { "puzzle " j ": " labels[j] }
}
if( j >= numlabels )
{
content { "puzzle " j }
}
bind_action { "puzzle " j }
}
}
}
newline
newline
box
{
if( gamestate == 0 )
{
border { 1px solid black }
content { "Edit/playtest mode" }
bind_action { "playtest mode" }
}
}

}
```