Code viewer for Mind: Skrt
function Mind() 
{
    var invalid_spaces = [];
    var prev_x;
    var prev_y;
    var prev_move;
    
    this.compareArrays = function (a, b)
    {
        if (a === undefined || b === undefined)
            return false;
        else if (a.length !== b.length)
            return false;
        
        for (var i = 0; i < a.length; i++)
            if (a[i] !== b[i])
                return false;
                
        return true;
    };
    
    this.contains = function (list, element)
    {
        for (var i = 0; i < list.length; i++)
            if (this.compareArrays(element, list[i]))
                return true;
        
        return false;
    };
    
    this.getDistance = function (x1, y1, x2, y2)
    {
        return Math.abs(x1 - x2) + Math.abs(y1 - y2);
    };
    
    this.spaceFree = function (x, y)
    {
        return !(x === 0 || y === 0 || x === gridsize - 1 || y === gridsize - 1 || this.contains(invalid_spaces,[x, y]));  
    };
    
    this.availableMoves = function(x, y)
    {
        var count = 0;
        
        if (this.spaceFree(x + 1, y))
            count++;
        if (this.spaceFree(x - 1, y))
            count++;
        if (this.spaceFree(x, y + 1))
            count++;
        if (this.spaceFree(x, y - 1))
            count++;
            
        return count;
    };
    
    this.getScore = function (x, y, depth)
    {
        if (!this.spaceFree(x, y))
            return 0;
        else if (depth === 3)
            return this.availableMoves(x, y);
        else
            return this.getScore(x + 1, y, depth + 1) + this.getScore(x - 1, y, depth + 1) + this.getScore(x, y + 1, depth + 1) + this.getScore(x, y - 1, depth + 1);
    };
    
    this.bestMove = function (moves)
    {
        var best = moves[0];
        
        for (var i = 1; i < moves.length; i++)
            if (this.getScore(moves[i][0], moves[i][1], 0) > this.getScore(best[0], best[1], 0))
                best = moves[i];
                
        return best;
    };
    
    this.updateInvalidSpaces = function ()
    {
        if (prev_move === ACTION_LEFT)
            invalid_spaces.push([prev_x - 1, prev_y]);
        else if (prev_move === ACTION_RIGHT)
            invalid_spaces.push([prev_x + 1, prev_y]);
        else if (prev_move === ACTION_UP)
            invalid_spaces.push([prev_x, prev_y + 1]);
        else
            invalid_spaces.push([prev_x, prev_y - 1]);
    };
    
    this.getAction = function (state)
    { 
        var ax = state[0];
        var ay = state[1];
        var ex = state[2];
        var ey = state[3];
        var current_distance = this.getDistance(ax, ay, ex, ey);
        
        if (ax === prev_x && ay === prev_y && current_distance > 2) // The last turn resulted in us not moving, meaning that we have hit a block.
            this.updateInvalidSpaces();
        
        prev_x = ax;
        prev_y = ay;
        
        var moves = [[ax - 1, ay], [ax + 1, ay], [ax, ay - 1], [ax, ay + 1]]; // [left, right, up, down]
        var desirable_moves = [];

        for (var i = 0; i < moves.length; i++)
            if (this.spaceFree(moves[i][0], moves[i][1]) && this.getDistance(moves[i][0], moves[i][1], ex, ey) > current_distance)
                desirable_moves.push(moves[i]);
        
        var best;
        if (desirable_moves.length >= 1)
            best = this.bestMove(desirable_moves);
        else
            best = this.bestMove(moves);
        
        if (best[0] === ax - 1)
        {
            prev_move = ACTION_LEFT;
            return ACTION_LEFT;
        }
        else if (best[0] === ax + 1)
        {
            prev_move = ACTION_RIGHT;
            return ACTION_RIGHT;
        }
        else if (best[1] === ay + 1)
        {
            prev_move = ACTION_UP;
            return ACTION_UP;
        }
        else if (best[1] === ay - 1)
        {
            prev_move = ACTION_DOWN;
            return ACTION_DOWN;
        }
    };
}