# HG changeset patch # User Oleksandr Gavenko # Date 1435980718 18000 # Node ID 5a17638f0dca96f11b885102fee9799f8cfefdd7 # Parent cde69b258e85a4626f3557565691e3bb82ccb4ea# Parent df8e645c3f366c787f345fdacfd78210c9b362c3 merged diff -r cde69b258e85 -r 5a17638f0dca 2048.html --- a/2048.html Fri Jul 03 22:21:05 2015 -0500 +++ b/2048.html Fri Jul 03 22:31:58 2015 -0500 @@ -253,7 +253,7 @@ free cell coefficient
- score threshold + score threshold
diff -r cde69b258e85 -r 5a17638f0dca ai.js --- a/ai.js Fri Jul 03 22:21:05 2015 -0500 +++ b/ai.js Fri Jul 03 22:31:58 2015 -0500 @@ -184,13 +184,13 @@ //////////////////////////////////////////////////////////////// -// 1 step deep with linear weight function on score, max value, +// 1 step deep with linear utility function on score, max value, // bonuses for max value stay at corner or edge and bonuses // for each free field. //////////////////////////////////////////////////////////////// /** - * Defines coefficient for linear resulted weight function. + * Defines coefficient for linear resulted utility function. * @name ai.OneStepAhead.cfg * @namespace * @property {number} scoreCoef multiplicator for score @@ -210,34 +210,34 @@ ai.copyObj(cfg, this.cfg); } ai.OneStepAhead.bestCfg = {scoreCoef: 1, maxValCoef: 0, cornerBonus: 0, edgeBonus: 0, freeBonus: 0}; -ai.OneStepAhead.prototype.weight = function(brd) { - var weight = 0; +ai.OneStepAhead.prototype.utility = function(brd) { + var utility = 0; if (this.cfg.scoreCoef > 0) - weight += this.cfg.scoreCoef * brd.score(); + utility += this.cfg.scoreCoef * brd.score(); var max = brd.maxVal(); if (this.cfg.maxValCoef > 0) - weight += this.cfg.maxValCoef * max; + utility += this.cfg.maxValCoef * max; if (this.cfg.cornerBonus > 0 && brd.atCorner(max)) - weight += this.cfg.cornerBonus; + utility += this.cfg.cornerBonus; if (this.cfg.edgeBonus > 0 && brd.atEdge(max)) - weight += this.cfg.edgeBonus; + utility += this.cfg.edgeBonus; if (this.cfg.freeBonus > 0) - weight += this.cfg.freeBonus * brd.freeCnt(); - return weight; + utility += this.cfg.freeBonus * brd.freeCnt(); + return utility; } /** Select best direction for next step. */ ai.OneStepAhead.prototype.analyse = function(brd2d) { var origBrd = new this.brd(brd2d); var nextBrd = new this.brd(); - var maxWeight = -1; + var maxUtility = -1; var bestDir; for (var i = 0; i < ai.dirs.length; i++) { var dir = ai.dirs[i]; if (origBrd[dir](nextBrd)) { - var weight = this.weight(nextBrd); - if (maxWeight < weight) { + var utility = this.utility(nextBrd); + if (maxUtility < utility) { bestDir = dir; - maxWeight = weight; + maxUtility = utility; } } } @@ -253,7 +253,7 @@ //////////////////////////////////////////////////////////////// /** - * Defines coefficient for linear resulted weight function. + * Defines coefficient for linear resulted utility function. * @name ai.StaticDeepMerges.cfg * @namespace * @property {number} scoreCoef multiplicator for score @@ -272,41 +272,41 @@ this.cfg = ai.copyObj(ai.OneStepAhead.bestCfg); ai.copyObj(cfg, this.cfg); } -ai.StaticDeepMerges.bestCfg = {scoreCoef: 1, maxValCoef: 0, cornerBonus: 0, edgeBonus: 0, freeBonus: 0, weightThreshold: 10}; -ai.StaticDeepMerges.prototype.weight = function(brd) { - var weight = 0; +ai.StaticDeepMerges.bestCfg = {scoreCoef: 1, maxValCoef: 0, cornerBonus: 0, edgeBonus: 0, freeBonus: 0, utilityThreshold: 10}; +ai.StaticDeepMerges.prototype.utility = function(brd) { + var utility = 0; if (this.cfg.scoreCoef > 0) - weight += this.cfg.scoreCoef * brd.score(); + utility += this.cfg.scoreCoef * brd.score(); var max = brd.maxVal(); if (this.cfg.maxValCoef > 0) - weight += this.cfg.maxValCoef * max; + utility += this.cfg.maxValCoef * max; if (this.cfg.cornerBonus > 0 && brd.atCorner(max)) - weight += this.cfg.cornerBonus; + utility += this.cfg.cornerBonus; if (this.cfg.edgeBonus > 0 && brd.atEdge(max)) - weight += this.cfg.edgeBonus; + utility += this.cfg.edgeBonus; if (this.cfg.freeBonus > 0) - weight += this.cfg.freeBonus * brd.freeCnt(); - return weight; + utility += this.cfg.freeBonus * brd.freeCnt(); + return utility; } /** Select best direction for next step. */ ai.StaticDeepMerges.prototype.analyse = function(brd2d) { var origBrd = new this.brd(brd2d); var nextBrd = new this.brd(); var prevScore = -1, nextScore = -1; - var maxWeight = -1; + var maxUtility = -1; var bestDir; for (var i = 0; i < ai.dirs.length; i++) { var dir = ai.dirs[i]; if (origBrd[dir](nextBrd)) { - var weight = this.evalFn(nextBrd); - var ok = (weight - maxWeight) > this.cfg.weightThreshold; - if ( ! ok && maxWeight <= weight) { - nextScore = this.weight(nextBrd); + var utility = this.evalFn(nextBrd); + var ok = (utility - maxUtility) > this.cfg.utilityThreshold; + if ( ! ok && maxUtility <= utility) { + nextScore = this.utility(nextBrd); ok = prevScore < nextScore; } if (ok) { prevScore = nextScore; - maxWeight = weight; + maxUtility = utility; bestDir = dir; } } @@ -315,16 +315,16 @@ } ai.StaticDeepMerges.prototype.evalFn = function(brd) { var currScore = brd.score(); - var maxWeight = currScore; + var maxUtility = currScore; var nextBrd = new this.brd(); for (var i = 0; i < ai.dirs.length; i++) { if (brd[ai.dirs[i]](nextBrd)) { var score = nextBrd.score(); if (score > currScore) - maxWeight = Math.max(maxWeight, this.evalFn(nextBrd)); + maxUtility = Math.max(maxUtility, this.evalFn(nextBrd)); } } - return maxWeight; + return maxUtility; } /* Mark that next board will be unrelated to previous, so any stored precompution can be cleared. */ ai.StaticDeepMerges.prototype.cleanup = function() { } @@ -336,7 +336,7 @@ //////////////////////////////////////////////////////////////// /** - * Defines coefficient for linear resulted weight function. + * Defines coefficient for linear resulted utility function. * @name ai.expectimax.cfg * @namespace * @property {number} scoreCoef multiplicator for score @@ -362,7 +362,7 @@ this.cfg.depth = ai.expectimax.bestCfg.depth; } ai.expectimax.bestCfg = {balance: .9, depth: 5, scoreCoef: 1, maxValCoef: 0, cornerBonus: 0, edgeBonus: 0, freeBonus: 0}; -ai.expectimax.prototype.weight = function(brd) { +ai.expectimax.prototype.utility = function(brd) { var score = 0; var cfg = this.cfg; if (cfg.scoreCoef > 0) @@ -409,7 +409,7 @@ } ai.expectimax.prototype.evalFn = function(brd, depth) { if (depth >= this.depthLimit) - return this.weight(brd); + return this.utility(brd); var wCached = this.brdCache.get(brd); if (wCached) return wCached; @@ -453,7 +453,7 @@ //////////////////////////////////////////////////////////////// /** - * Defines coefficient for linear resulted weight function. + * Defines coefficient for linear resulted utility function. * @name ai.survive.cfg * @namespace * @property {number} scoreCoef multiplicator for score @@ -478,7 +478,7 @@ this.cfg.altAI = new ai.StaticDeepMerges(brd, ai.survive.altAICfg); } ai.survive.bestCfg = {freeCells: 8, maxDepth: 5}; -ai.survive.altAICfg = {scoreCoef: 1, maxValCoef: 0, cornerBonus: 0, edgeBonus: 0, freeBonus: 0, weightThreshold: 0}; +ai.survive.altAICfg = {scoreCoef: 1, maxValCoef: 0, cornerBonus: 0, edgeBonus: 0, freeBonus: 0, utilityThreshold: 0}; /** Select best direction for next step. */ ai.survive.prototype.analyse = function(brd2d) { var origBrd = new this.brd(brd2d); @@ -573,19 +573,19 @@ ai.MonteCarlo.prototype.analyse = function(brd2d) { var origBrd = new this.brd(brd2d); var nextBrd = new this.brd(); - var bestW = - this.cfg.simulations; + var bestUtility = - this.cfg.simulations; var bestDir; var freeCnt = origBrd.freeCnt(); for (var i = 0; i < ai.dirs.length; i++) { var dir = ai.dirs[i]; if (origBrd[dir](nextBrd)) { - var w = 0; + var utility = 0; for (var gameCnt = this.cfg.simulations; gameCnt > 0; gameCnt--) { var tmpBrd = nextBrd.copy(); - w += this.play(tmpBrd, this.cfg.maxDepth); + utility += this.play(tmpBrd, this.cfg.maxDepth); } - if (w > bestW) { - bestW = w; + if (utility > bestUtility) { + bestUtility = utility; bestDir = dir; } } @@ -608,17 +608,17 @@ return -1; } ai.MonteCarlo.prototype.evalFn = function(brd) { - var w = 0; + var utility = 0; if (this.cfg.freeBonus > 0) - w += this.cfg.freeBonus * brd.freeCnt(); + utility += this.cfg.freeBonus * brd.freeCnt(); var max = brd.maxVal(); if (max > 7) { if (this.cfg.cornerBonus > 0 && brd.atCorner(max)) - w += this.cfg.cornerBonus; + utility += this.cfg.cornerBonus; if (this.cfg.edgeBonus > 0 && brd.atEdge(max)) - w += this.cfg.edgeBonus; + utility += this.cfg.edgeBonus; } - return w; + return utility; } /* Mark that next board will be unrelated to previous, so any stored precompution can be cleared. */ ai.MonteCarlo.prototype.cleanup = function() {