# HG changeset patch # User Oleksandr Gavenko # Date 1410187390 -10800 # Node ID ab294e8db00cdd106a29d229994443dd866e8cff # Parent 94a4201d27a391fcffd4c3f1968dd4c3a21bbf8b Add detecting value at edge or corner, free cell count. Added AI that count max value at edges or corner and free cell count. diff -r 94a4201d27a3 -r ab294e8db00c 2048.html --- a/2048.html Mon Sep 08 02:04:16 2014 +0300 +++ b/2048.html Mon Sep 08 17:43:10 2014 +0300 @@ -88,6 +88,7 @@ + @@ -354,6 +355,9 @@ document.getElementById("ai-deep-max-score").addEventListener("click", function() { ui.ai = new ai.deepMaxScore(ui.brdEngine); }); + document.getElementById("ai-deep-max-score-corner").addEventListener("click", function() { + ui.ai = new ai.deepMaxScoreCorner(ui.brdEngine); + }); diff -r 94a4201d27a3 -r ab294e8db00c ai.js --- a/ai.js Mon Sep 08 02:04:16 2014 +0300 +++ b/ai.js Mon Sep 08 17:43:10 2014 +0300 @@ -137,3 +137,81 @@ /* Mark that next board will be unrelated to previous, so any stored precompution can be cleared. */ ai.deepMaxScore.prototype.cleanup = function() { } + +//////////////////////////////////////////////////////////////// +// N level deep on score value + max value prefer corner, +// without random simulation. +//////////////////////////////////////////////////////////////// + +/* cfg.cornerBonus - value to add if max value at corner. */ +/* cfg.edgeBonus - value to add if max value at edge. */ +ai.deepMaxScoreCorner = function(brdEngine, cfg) { + this.brdEngine = brdEngine; + this.cfg = cfg || {}; + this.cfg.cornerBonus = this.cfg.cornerBonus || 20000; + this.cfg.edgeBonus = this.cfg.edgeBonus || 100; + this.cfg.freeBonus = this.cfg.edgeBonus || 100; +} +ai.deepMaxScoreCorner.prototype.scoreCorner = function(brd) { + var score = brd.score(); + var max = brd.max(); + if (brd.atCorner(max)) + score += this.cfg.cornerBonus; + else if (brd.atEdge(max)) + score += this.cfg.edgeBonus; + score += brd.free() * this.cfg.freeBonus; + return score; +} +ai.deepMaxScoreCorner.prototype.scoreEdge = function(brd) { + var score = brd.score(); + var max = brd.max(); + if (brd.atEdge(max)) + score += this.cfg.edgeBonus; + score += brd.free() * this.cfg.freeBonus; + return score; +} +ai.deepMaxScoreCorner.prototype.analyse = function(brd) { + var origBrd = new this.brdEngine(brd); + var nextBrd = new this.brdEngine(); + var prevScore = -1, nextScore = -1; + var maxScore = -1; + var bestDir; + for (var i = 0; i < ai.dirs.length; i++) { + var dir = ai.dirs[i]; + if (origBrd[dir](nextBrd)) { + nextScore = this.scoreCorner(nextBrd); + var score = this.bestScore(nextBrd); + // console.log("dir: %o, prevScore: %o, nextScore: %o, maxScore: %o, score: %o", dir, prevScore, nextScore, maxScore, score); + if (maxScore < score || (maxScore === score && prevScore < nextScore)) { + prevScore = nextScore; + maxScore = score; + bestDir = dir; + } + } + } + return bestDir; +} +ai.deepMaxScoreCorner.prototype.bestScore = function(brd, seenBrds) { + if (seenBrds) { + for (var i = 0; i < seenBrds.length; i++) + if (brd.equals(seenBrds[i])) + return 0; + } else { + seenBrds = []; + } + seenBrds.push(brd); + var currScore = this.scoreEdge(brd); + var maxScore = currScore; + var nextBrd = new this.brdEngine(); + for (var i = 0; i < ai.dirs.length; i++) { + if (brd[ai.dirs[i]](nextBrd)) { + var score = this.scoreEdge(nextBrd); + if (score > currScore) + maxScore = Math.max(maxScore, this.bestScore(nextBrd, seenBrds)); + } + } + return maxScore; +} +/* Mark that next board will be unrelated to previous, so any stored precompution can be cleared. */ +ai.deepMaxScoreCorner.prototype.cleanup = function() { } + diff -r 94a4201d27a3 -r ab294e8db00c board.js --- a/board.js Mon Sep 08 02:04:16 2014 +0300 +++ b/board.js Mon Sep 08 17:43:10 2014 +0300 @@ -81,6 +81,14 @@ brd.brd[i][j] = this.brd[i][j]; return brd; } +BoardArr2d.prototype.free = function() { + var cnt = 0; + for (var i = 0; i < 4; i++) + for (var j = 0; j < 4; j++) + if (this.brd[i][j] === 0) + cnt++; + return cnt; +} BoardArr2d.prototype.score = function() { var score = 0; for (var i = 0; i < 4; i++) { @@ -101,6 +109,27 @@ } return max; } +BoardArr2d.prototype.find = function(val) { + var xy = []; + for (var i = 0; i < 4; i++) { + for (var j = 0; j < 4; j++) { + if (this.brd[i][j] === val) + xy.push([i,j]); + } + } + return xy; +} +BoardArr2d.prototype.atEdge = function(val) { + var brd = this.brd; + return (brd[0][0] === val) || (brd[0][1] === val) || (brd[0][2] === val) || (brd[0][3] === val) + || (brd[1][0] === val) || (brd[1][3] === val) + || (brd[2][0] === val) || (brd[2][3] === val) + || (brd[3][0] === val) || (brd[3][1] === val) || (brd[3][2] === val) || (brd[3][3] === val); +} +BoardArr2d.prototype.atCorner = function(val) { + var brd = this.brd; + return (brd[0][0] === val) || (brd[0][3] === val) || (brd[3][0] === val) || (brd[3][3] === val); +} BoardArr2d.prototype.canRight = function() { for (var i = 0; i < 4; i++) {