ai.js
changeset 155 1f8df90bd338
parent 152 07814b979a8a
child 156 e6a4bc888b72
equal deleted inserted replaced
154:c6d9b84d9391 155:1f8df90bd338
   433 }
   433 }
   434 /* Mark that next board will be unrelated to previous, so any stored precompution can be cleared. */
   434 /* Mark that next board will be unrelated to previous, so any stored precompution can be cleared. */
   435 ai.expectimax.prototype.cleanup = function() {
   435 ai.expectimax.prototype.cleanup = function() {
   436 }
   436 }
   437 
   437 
       
   438 
       
   439 
       
   440 ////////////////////////////////////////////////////////////////
       
   441 // Survive as long as possible.
       
   442 ////////////////////////////////////////////////////////////////
       
   443 
       
   444 /**
       
   445  * Defines coefficient for linear resulted weight function.
       
   446  * @name ai.survive.cfg
       
   447  * @namespace
       
   448  * @property {number} scoreCoef    multiplicator for score
       
   449  * @property {number} maxValCoef   multiplicator for max value
       
   450  * @property {number} cornerBonus  bonus for max value at board corner
       
   451  * @property {number} edgeBonus    bonus for max value at board edge
       
   452  * @property {number} freeBonus    bonus for each free cell
       
   453  */
       
   454 
       
   455 /** N level deep with random simulation.
       
   456  * @param {Board} brdEngine  board engine from board.js
       
   457  * @param {ai.survive.cfg} cfg  configuration settings
       
   458  * @constructor */
       
   459 ai.survive = function(brdEngine, cfg) {
       
   460     this.brdEngine = brdEngine;
       
   461     this.cfg = ai.copyObj(ai.survive.bestCfg);
       
   462     ai.copyObj(cfg, this.cfg);
       
   463     if (this.cfg.freeCells <= 0)
       
   464         this.cfg.freeCells = ai.survive.bestCfg.freeCells;
       
   465     if (!this.cfg.maxDepth || this.cfg.maxDepth < 0 || 20 <= this.cfg.maxDepth)
       
   466         this.cfg.maxDepth = ai.survive.bestCfg.maxDepth;
       
   467     this.cfg.altAI = new ai.StaticDeepMerges(brdEngine, ai.survive.altAICfg);
       
   468 }
       
   469 ai.survive.bestCfg = {freeCells: 8, maxDepth: 5};
       
   470 ai.survive.altAICfg = {scoreCoef: 1, maxValCoef: 0, cornerBonus: 0, edgeBonus: 0, freeBonus: 0, weightThreshold: 0};
       
   471 /** Select best direction for next step. */
       
   472 ai.survive.prototype.analyse = function(brd2d) {
       
   473     var origBrd = new this.brdEngine(brd2d);
       
   474     var nextBrd = new this.brdEngine();
       
   475     var bestW = -1;
       
   476     var bestDir;
       
   477     var freeCnt = origBrd.freeCnt();
       
   478     if (freeCnt >= this.cfg.freeCells)
       
   479         return this.cfg.altAI.analyse(brd2d);
       
   480     for (var i = 0; i < ai.dirs.length; i++) {
       
   481         var dir = ai.dirs[i];
       
   482         if (origBrd[dir](nextBrd)) {
       
   483             var w = this.evalFn(nextBrd, 1);
       
   484             console.log("dir: %s, w: %d", dir, w);
       
   485             if (w > bestW) {
       
   486                 bestW = w;
       
   487                 bestDir = dir;
       
   488             }
       
   489         }
       
   490     }
       
   491     return bestDir;
       
   492 }
       
   493 ai.survive.prototype.evalFn = function(brd, depth) {
       
   494     if (brd.freeCnt() >= this.cfg.freeCells)
       
   495         return 1;
       
   496     if (depth >= this.cfg.maxDepth)
       
   497         return 0;
       
   498     var wMin = +Infinity;
       
   499     var randBoard = new this.brdEngine();
       
   500     var nextBrd = new this.brdEngine();
       
   501 exit:
       
   502     for (var i = 0; i < 3; i++) {
       
   503         for (var j = 0; j < 3; j++) {
       
   504             if (brd.get(i, j) !== 0)
       
   505                 continue;
       
   506             brd.copy(randBoard);
       
   507             randBoard.set(i, j, 1);
       
   508             var wMax = -1;
       
   509             for (var diri = 0; diri < ai.dirs.length; diri++) {
       
   510                 if (randBoard[ai.dirs[diri]](nextBrd)) {
       
   511                     var w = this.evalFn(nextBrd, depth+1);
       
   512                     if (w === 1) {
       
   513                         wMax = 1;
       
   514                         break;
       
   515                     }
       
   516                     wMax = Math.max(wMax, w);
       
   517                 }
       
   518             }
       
   519             if (wMax === -1) {
       
   520                 wMin = -1;
       
   521                 break exit;
       
   522             }
       
   523             wMin = Math.min(wMin, wMax);
       
   524         }
       
   525     }
       
   526     if (wMin === +Infinity)
       
   527         return -1;
       
   528     return wMin;
       
   529 }
       
   530 /* Mark that next board will be unrelated to previous, so any stored precompution can be cleared. */
       
   531 ai.survive.prototype.cleanup = function() {
       
   532 }
       
   533