Bot: Outsnake the game! So, I wrote a simple Javascript game (as yet unnamed) and naturally I wanted to write an API so I could write a bot to play it for me, and naturally I wanted to let the PPCG community have a go for themselves.

It's a 'snake' game with the simple goal of collecting as many blue squares as possible while avoiding red squares or the edge of the board. It was initially controlled with a mouse. 



Find the API edition of the game here: https://ajfaraday.github.io/game_name_here/api.html

Gameplay:


Type the code for your bot in the field under 'Your function': This will repeat automatically when you tell it to run.


Only in Javascript, sorry.
See restrictions, below.

You can try it step-wise by clicking 'step'.
I suggest you 'Run (fast)' once you have a workable function. 
Click 'Reset' to try a fresh game.
Every 10 points will increase the points per blue square by 1.
Every 10 points will increase the red squares spawned by 1.
You can lose lives by:


Gobbling up a red square (Be aware that, while you lose a life, it also breaks down the wall. Sacrificing lives to break through walls is a legitimate tactic).
Attempting to leave the game board.
Running down the 'Timeout' clock of 20 seconds between blue squares.

You will not lose a life by 'stepping on your tail' in this version.
Every 100 points will earn an additional life.
Be aware that all coordinates are x, y starting in the top left corner. 0 indexed.


Restrictions:


There is no security in this code. Please do not hack the game!


Only use standard JS and the API methods described.
PLEASE! Don't change API.coord
You may not interact directly with Sketch, Cell or other entities defined within the game.



The competition


Please give your entry title a short name for your snake.
Include your JS code and any explanation you'd like to include.
The OP will copy/paste the code into the game, and run it 5 times (using 'Run (fast)').
The highest score achieved in those attempts is your score. 
The OP will add your score to the answer, and to a leader board in the question.
You may submit more than one function.




Leader Board

+--------------------------+---------------------------------+----------+
| Username                 | Snake Name                      | Score    |
+--------------------------+---------------------------------+----------+
| orlp                     | Simple A*                       | 595      |
+--------------------------+---------------------------------+----------+


Rendering Issue

This rendering issue has now been fixed and deployed.


Please be aware that if you call more than one of the direction methods during your function, the snake will visit all of the squares and collect points or lose lives accordingly. However, due to a rendering issue, it will only display the ending position of your snake.
 

Be aware that the snake can not travel diagonally between walls without losing a life.



Responsible disclosure: This is written in pure Javascript, it contains no logging, analytics or other data gathering processes. It's hosted on github pages, typically a trusted home of code.

If you want to confirm this, or would prefer to develop your answer on a locally hosted instance, the code is available here:
https://github.com/ajfaraday/game_name_here



This is my first attempt at a competitive non-golf challenge, so I'm open to suggestions about how I could make it more suitable for this kind of situation.

Happy snaking!
Simple A* - Official score: 595

This solution uses simple A* pathfinding, with no long-term strategy - it always finds the optimal route towards just the next blue square.

var h = function(p, q) {
    // Manhattan distance.
    return Math.abs(p[0] - q[0]) + Math.abs(p[1] - q[1]);
};

var s = JSON.stringify;
var p = JSON.parse;
var walls = API.walls.map(s);
var start = API.coord;
var goal = API.goal;

var is_closed = {};
is_closed[s(start)] = 0;
var open = [s(start)];

var came_from = {};
var gs = {};
gs[s(start)] = 0;
var fs = {};
fs[s(start)] = h(start, goal);

var cur;
while (open.length) {
    var best;
    var bestf = Infinity;
    for (var i = 0; i &lt; open.length; ++i) {
        if (fs[open[i]] &lt; bestf) {
            bestf = fs[open[i]];
            best = i;
        }
    }

    cur = p(open.splice(best, 1)[0]);
    is_closed[s(cur)] = 1;

    if (s(cur) == s(goal)) break;

    for (var d of [[0, 1], [0, -1], [1, 0], [-1, 0]]) {
        var next = [cur[0] + d[0], cur[1] + d[1]];
        if (next[0] &lt; 0 || next[0] &gt;= API.width ||
            next[1] &lt; 0 || next[1] &gt;= API.height) {
            continue;
        }

        if (is_closed[s(next)]) continue;
        if (open.indexOf(s(next)) == -1) open.push(s(next));
        var is_wall = walls.indexOf(s(next)) &gt; -1;
        var g = gs[s(cur)] + 1 + 10000 * is_wall;
        if (gs[s(next)] != undefined &amp;&amp; g &gt; gs[s(next)]) continue;

        came_from[s(next)] = cur;
        gs[s(next)] = g;
        fs[s(next)] = g + h(next, goal);
    }
}

var path = [cur];
while (came_from[s(cur)] != undefined) {
    cur = came_from[s(cur)];
    path.push(cur);
}

var c = path[path.length - 1];
var n = path[path.length - 2];
if (n[0] &lt; c[0]) {
    API.left();
} else if (n[0] &gt; c[0]) {
    API.right();
} else if (n[1] &lt; c[1]) {
    API.up();
} else {
    API.down();
}