Coding hex board game Introduction
Hex is a strategy board game played on a hexagonal grid, theoretically of any size and several possible shapes, but traditionally as an 11×11 rhombus. Other popular dimensions are 13×13 and 19×19 as a result of the game's relationship to the older game of Go. According to the book A Beautiful Mind, John Nash (one of the game's inventors) advocated 14×14 as the optimal size.

Game Rules
Each player has an allocated color, conventionally Red and Blue or White and Black. Players take turns placing a stone of their color on a single cell within the overall playing board. The goal for each player is to form a connected path of their own stones linking the opposing sides of the board marked by their colors, before their opponent connects his or her sides in a similar fashion. The first player to complete his or her connection wins the game. The four corner hexagons each belong to both adjacent sides.
Coding Rules

You may use any program or language. Do not use any third party libraries or modules (full or in part) that implements the same game. The rest are fine.
Players are computer and user.
You may choose the size of the grid.
You may use either CLI or GUI for output (see points).
Your code should not exceed 5120 bytes.

Points

+(5120 - bytes) / 100 golfing points
+50 points for making GUI
+50 for two player mode
+75 for best-move-prediction#
+50 for undo-move

# Tell the user, if they wish, their next best move.
Super bot challenge

+150 points if your bot is undefeatable. Add this points ONLY IF you are absolutely certain of your bot's 100% winning capability. If any user defeats your bot and reports it all your points will be taken away (zero points). The person reporting this must either post a screenshot or input sequences based on the implementation of game. They will be awarded +150 points, if they have posted an answer.
HTML5 and JavaScript, 12.72 + 50 + 50 + 50 = 162.72 points

Hi, this is my very first code golf, but I think, the following code works quite well (it's a full HTML page, 3848 bytes).



&lt;html&gt;&lt;head&gt;&lt;meta charset="utf-8"&gt;&lt;title&gt;Hex&lt;/title&gt;&lt;script type="text/javascript"&gt;var r=20;var w=r*2*(Math.sqrt(3)/2);var ctx;var s=[-1,-1];var b=new Array(14);var h=[];var p=0;var m=false;var t=true;function H(c,x,y,r){c.beginPath();c.moveTo(x,y-r);for(var i=0;i&lt;6;i++)c.lineTo(x+r*Math.cos(Math.PI*(1.5+1/3*i)),y+r*Math.sin(Math.PI*(1.5+1/3*i)));c.closePath();c.fill();c.stroke();}function P(c,p){c.lineWidth=10;c.beginPath();c.moveTo((p[0][0]+p[0][1])*w-(p[0][1]-4)*(w/2),(p[0][1]+2)*1.5*r);for(var i=1;i&lt;p.length;i++)c.lineTo((p[i][0]+p[i][1])*w-(p[i][1]-4)*(w/2),(p[i][1]+2)*1.5*r);c.stroke();}function S(e){var l=ctx.getImageData(e.clientX-20,e.clientY,1,1).data;l[0]-=l[2]==38||l[2]==178 ? 241 : 0;l[1]-=l[2]==178 ? 220 : (l[2]==38 ? 0 : 140);if(l[0]&gt;=0&amp;&amp;l[0]&lt;=13&amp;&amp;l[1]&gt;=0&amp;&amp;l[1]&lt;=13&amp;&amp;(l[2]==38||l[2]==171||l[2]==178))s=[l[0],l[1]];else s=[-1,-1];}function Ai(){var pos;do pos=[Math.floor(Math.random()*14),Math.floor(Math.random()*14)];while(b[pos[0]][pos[1]]!=-1);h.push([pos[0],pos[1],1]);b[pos[0]][pos[1]]=1;}function Fa(a,d){for(var i=0;i&lt;a.length;i++)if(JSON.stringify(a[i])==JSON.stringify(d))return i;return -1;}function C(x,y,c,o,s){var a=[-1,0,1,0,0,-1,0,1,1,-1,-1,1];var r=[];for(var i=0;i&lt;6;i++)if(x+a[i*2]&gt;=0&amp;&amp;x+a[i*2]&lt;14&amp;&amp;y+a[i*2+1]&gt;=0&amp;&amp;y+a[i*2+1]&lt;14)if(b[x+a[i*2]][y+a[i*2+1]]==c&amp;&amp;Fa(o,[x+a[i*2],y+a[i*2+1]])==-1&amp;&amp;Fa(s,[x+a[i*2],y+a[i*2+1]])==-1)r.push([x+a[i*2],y+a[i*2+1]]);return r;}function W(c){var o=[],op=[],s=[],sp=[];for(var a=0;a&lt;14;a++){if(b[c==0?a:0][c==0?0:a]==c){o.length=op.length=s.length=sp.length=0;var pf=false;o.push([c==0?a:0,c==0?0:a]);op.push(-1);while(o.length&gt;0){var u=o[0];o.splice(0,1);var uI=op.splice(0,1);s.push(u);sp.push(uI);if(u[c==0?1:0]==13){pf=true;break;}var n=C(u[0],u[1],c,o,s);for(var i=0;i&lt;n.length;i++){o.push(n[i]);op.push(s.length-1);}}if(pf){var p=[];var u=s.length-1;while(sp[u]!=-1){p.push(s[u]);u=sp[u];}p.push([c==0?a:0,c==0?0:a]);p.reverse();t=false;return p;}}}return false;}function Md(e){S(e);if(t){if(s[0]!=-1&amp;&amp;s[1]!=-1){h.push([s[0],s[1],p]);b[s[0]][s[1]]=p;if(m)p=p==0 ? 1 : 0;else Ai();D();var p0=W(0),p1=W(1);if(p0!=false){P(ctx,p0);alert((m?"The red player":"You")+" won!");}else if(p1!=false){P(ctx,p1);alert((m?"The blue player":"The computer")+" won!");}}}}function Mm(e){S(e);if(t)D();}function D(){ctx.clearRect(0,0,850,600);ctx.lineWidth=1;ctx.fillStyle="rgb(0,154,172)";ctx.beginPath();ctx.moveTo(w*15.65,r);ctx.lineTo(w*23.5,24.5*r);ctx.lineTo(0,r);ctx.lineTo(w*7.85,24.5*r);ctx.closePath();ctx.fill();ctx.fillStyle="rgb(255,0,39)";ctx.beginPath();ctx.moveTo(0,r);ctx.lineTo(w*15.65,r);ctx.lineTo(w*7.85,24.5*r);ctx.lineTo(w*23.5,24.5*r);ctx.closePath();ctx.fill();var num=0;ctx.strokeStyle="white";for(var y=0;y&lt;14;y++){for(var x=0;x&lt;14;x++){if(b[x][y]==0)ctx.fillStyle="rgb(255,0,39)";else if(b[x][y]==1)ctx.fillStyle="rgb(0,154,172)";else if(x==s[0]&amp;&amp;y==s[1])ctx.fillStyle="rgb("+(x+(p==0?241:0))+","+(y+(p==0?0:140))+","+(p==0?38:171)+")";else ctx.fillStyle="rgb("+(x+241)+","+(y+220)+",178)";H(ctx,(x+y)*w-(y-4)*(w/2),(y+2)*1.5*r,r);num++;}}}function Mp(){m=!m;p=0;I();}function U(){if(t){var a;if(h.length&gt;0){a=h[h.length-1];b[a[0]][a[1]]=-1;h.pop();}if(!m){a=h[h.length-1];b[a[0]][a[1]]=-1;h.pop();}p=a[2];D();}}function I(){for(var i=0;i&lt;14;i++){b[i]=new Array(14);for(var j=0;j&lt;14;j++)b[i][j]=-1;}history.length=0;t=true;D();}function L(){var a=document.getElementById("o");ctx=a.getContext("2d");document.getElementById("mp").checked=false;a.onmousedown=Md;a.onmousemove=Mm;I();}&lt;/script&gt;&lt;/head&gt;&lt;body onload="L()"&gt;&lt;canvas style="position:absolute;top:0px;left:20px" width="850" height="600" id="o"&gt;&lt;/canvas&gt;&lt;div style="position:absolute;top:250px;left:20px"&gt;&lt;input type="button" onClick="I()" value="New game"&gt;&lt;br&gt;&lt;br&gt;Multiplayer: &lt;input id="mp" type="checkbox" onClick="Mp()"&gt;&lt;br&gt;&lt;input type="button" onClick="U()" value="Undo"&gt;&lt;/div&gt;&lt;/body&gt;&lt;/html&gt;




Expanded

&lt;html&gt;
&lt;head&gt;
    &lt;meta charset="utf-8"&gt;
    &lt;title&gt;Hex&lt;/title&gt;
    &lt;script type="text/javascript"&gt;
        var r = 20;
        var w = r*2*(Math.sqrt(3)/2);
        var ctx;
        var sel = [-1, -1];
        var board = new Array(14);
        var hist = [];
        var player = 0;
        var multiplayer = false;
        var active = true;

        function drawHexagon(c, x, y, r)
        {
            c.beginPath();
            c.moveTo(x, y-r);
            for(var i=0; i&lt;6; i++)
                c.lineTo(x+r*Math.cos(Math.PI*(1.5+1/3*i)), y+r*Math.sin(Math.PI*(1.5+1/3*i)));
            c.closePath();
            c.fill();
            c.stroke();
        }

        function drawPath(c, p)
        {
            c.lineWidth = 10;
            c.beginPath();
            c.moveTo((p[0][0]+p[0][1])*w - (p[0][1]-4)*(w/2), (p[0][1]+2)*1.5*r);
            for(var i=1; i&lt;p.length; i++)
                c.lineTo((p[i][0]+p[i][1])*w - (p[i][1]-4)*(w/2), (p[i][1]+2)*1.5*r);
            c.stroke();
        }

        function getSel(e)
        {
            var color = ctx.getImageData(e.clientX-20, e.clientY, 1, 1).data;
            color[0] -= color[2]==38||color[2]==178 ? 241 : 0;
            color[1] -= color[2]==178 ? 220 : (color[2]==38 ? 0 : 140);
            if(color[0] &gt;= 0  &amp;&amp;  color[0] &lt;= 13  &amp;&amp;  color[1] &gt;= 0  &amp;&amp;  color[1] &lt;= 13  &amp;&amp;  (color[2] == 38  ||  color[2] == 171  ||  color[2] == 178))
                sel = [color[0], color[1]];
            else
                sel = [-1, -1];
        }

        function aiMove()
        {
            var pos;
            do
                pos = [Math.floor(Math.random()*14), Math.floor(Math.random()*14)];
            while(board[pos[0]][pos[1]] != -1);
            hist.push([pos[0],pos[1],1]);
            board[pos[0]][pos[1]] = 1;
        }

        function findArr(a, b)
        {
            for(var i=0; i&lt;a.length; i++)
                if(JSON.stringify(a[i]) == JSON.stringify(b))
                    return i;
            return -1;
        }

        function getConnections(x, y, c, open, closed)
        {
            var a = [-1, 0, 1, 0, 0, -1, 0, 1, 1, -1, -1, 1];
            var ret = [];
            for(var i=0; i&lt;6; i++)
                if(x+a[i*2] &gt;= 0  &amp;&amp;  x+a[i*2] &lt; 14  &amp;&amp;  y+a[i*2+1] &gt;= 0  &amp;&amp;  y+a[i*2+1] &lt; 14)
                    if(board[x+a[i*2]][y+a[i*2+1]] == c  &amp;&amp;  findArr(open, [x+a[i*2],y+a[i*2+1]]) == -1  &amp;&amp;  findArr(closed, [x+a[i*2],y+a[i*2+1]]) == -1)
                        ret.push([x+a[i*2],y+a[i*2+1]]);
            return ret;
        }

        function checkWin(c)
        {
            var open = [], openPrev = [], closed = [], closedPrev = [];
            for(var a=0; a&lt;14; a++)
            {
                if(board[c==0?a:0][c==0?0:a] == c)
                {
                    open.length = openPrev.length = closed.length = closedPrev.length = 0;
                    var pathFound = false;
                    open.push([c==0?a:0, c==0?0:a]);
                    openPrev.push(-1);
                    while(open.length &gt; 0)
                    {
                        var u = open[0];
                        open.splice(0, 1);
                        var uI = openPrev.splice(0, 1);
                        closed.push(u);
                        closedPrev.push(uI);
                        if(u[c==0?1:0] == 13)
                        {
                            pathFound = true;
                            break;
                        }
                        var connections = getConnections(u[0], u[1], c, open, closed);
                        for(var i=0; i&lt;connections.length; i++)
                        {
                            open.push(connections[i]);
                            openPrev.push(closed.length-1);
                        }
                    }
                    if(pathFound)
                    {
                        var path = [];
                        var u = closed.length-1;
                        while(closedPrev[u] != -1)
                        {
                            path.push(closed[u]);
                            u = closedPrev[u];
                        }
                        path.push([c==0?a:0, c==0?0:a]);
                        path.reverse();
                        active = false;
                        return path;
                    }
                }
            }
            return false;
        }

        function mouseDown(e)
        {
            getSel(e);
            if(active)
            {
                if(sel[0] != -1  &amp;&amp;  sel[1] != -1)
                {
                    hist.push([sel[0],sel[1],player]);
                    board[sel[0]][sel[1]] = player;
                    if(multiplayer)
                        player = player==0 ? 1 : 0;
                    else
                        aiMove();
                    draw();
                    var p0 = checkWin(0), p1 = checkWin(1);
                    if(p0 != false)
                        { drawPath(ctx, p0); alert((multiplayer?"The red player":"You") + " won!"); }
                    else if(p1 != false)
                        { drawPath(ctx, p1); alert((multiplayer?"The blue player":"The computer") + " won!"); }
                }
            }
        }

        function mouseMove(e)
        {
            getSel(e);
            if(active)
                draw();
        }

        function draw()
        {
            ctx.clearRect(0, 0, 850, 600);
            ctx.lineWidth = 1;

            ctx.fillStyle = "rgb(0,154,172)";
            ctx.beginPath();
            ctx.moveTo(w*15.65, r);
            ctx.lineTo(w*23.5, 24.5*r);
            ctx.lineTo(0, r);
            ctx.lineTo(w*7.85, 24.5*r);
            ctx.closePath();
            ctx.fill();

            ctx.fillStyle = "rgb(255,0,39)";
            ctx.beginPath();
            ctx.moveTo(0, r);
            ctx.lineTo(w*15.65, r);
            ctx.lineTo(w*7.85, 24.5*r);
            ctx.lineTo(w*23.5, 24.5*r);
            ctx.closePath();
            ctx.fill();

            var num = 0;
            ctx.strokeStyle = "white";
            for(var y=0; y&lt;14; y++)
            {
                for(var x=0; x&lt;14; x++)
                {
                    if(board[x][y] == 0)
                        ctx.fillStyle = "rgb(255,0,39)";
                    else if(board[x][y] == 1)
                        ctx.fillStyle = "rgb(0,154,172)";
                    else if(x == sel[0]  &amp;&amp;  y == sel[1])
                        ctx.fillStyle = "rgb(" + (x+(player==0?241:0)) + "," + (y+(player==0?0:140)) + "," + (player==0?38:171) + ")";
                    else
                        ctx.fillStyle = "rgb(" + (x+241) + "," + (y+220) + ",178)";
                    drawHexagon(ctx, (x+y)*w - (y-4)*(w/2), (y+2)*1.5*r, r);
                    num++;
                }
            }
        }

        function chgMP()
        {
            multiplayer = !multiplayer;
            player = 0;
            init();
        }

        function undo()
        {
            if(active)
            {
                var a;
                if(hist.length &gt; 0)
                {
                    a = hist[hist.length-1];
                    board[a[0]][a[1]] = -1;
                    hist.pop();
                }
                if(!multiplayer)
                {
                    a = hist[hist.length-1];
                    board[a[0]][a[1]] = -1;
                    hist.pop();
                }
                player = a[2];
                draw();
            }
        }

        function init()
        {
            for(var i=0; i&lt;14; i++)
            {
                board[i] = new Array(14);
                for(var j=0; j&lt;14; j++)
                    board[i][j] = -1;
            }
            hist.length = 0;
            active = true;
            draw();
        }

        function load()
        {
            var canvas = document.getElementById("output");
            ctx = canvas.getContext("2d");
            document.getElementById("mp").checked = false;
            canvas.onmousedown = mouseDown;
            canvas.onmousemove = mouseMove;
            init();
        }
    &lt;/script&gt;
&lt;/head&gt;
&lt;body onload="load()"&gt;
    &lt;canvas style="position:absolute; top:0px; left:20px" width="850" height="600" id="output"&gt;Canvas not supported...&lt;/canvas&gt;
    &lt;div style="position:absolute; top:250px; left:20px"&gt;&lt;input type="button" onClick="init()" value="New game"&gt;&lt;br&gt;&lt;br&gt;Multiplayer: &lt;input id="mp" type="checkbox" onClick="chgMP()"&gt;&lt;br&gt;&lt;input type="button" onClick="undo()" value="Undo"&gt;&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;


Explanation

The code uses the HTML5's canvas-tag to display the game (14x14 board). You can undo the last step and play against another player (enable Multiplayer) or the computer, but its AI is still very weak (it just uses a random position to place the next field). The entire graphical design is based on your screenshot.