Make fast board cache.
authorOleksandr Gavenko <gavenkoa@gmail.com>
Thu, 25 Sep 2014 02:05:48 +0300
changeset 139 4dde63ac0bb4
parent 138 23cd36180bf9
child 140 438fd8c3c3ca
Make fast board cache.
ai.js
board.js
--- a/ai.js	Thu Sep 25 01:10:01 2014 +0300
+++ b/ai.js	Thu Sep 25 02:05:48 2014 +0300
@@ -22,6 +22,28 @@
     return to;
 }
 
+ai.brdCache = function() {
+    this.cache = [];
+}
+ai.brdCache.prototype.get = function(brd) {
+    var compr = brd.compress();
+    var subCache = this.cache[compr[0]];
+    if (subCache) {
+        return subCache[compr[1]];
+    }
+    return undefined;
+}
+ai.brdCache.prototype.put = function(brd, val) {
+    var compr = brd.compress();
+    var subCache = this.cache[compr[0]];
+    if (subCache) {
+        subCache[compr[1]] = val;
+    } else {
+        this.cache[compr[0]] = [];
+        this.cache[compr[0]][compr[1]] = val;
+    }
+}
+
 // Each strategy is a function that except current board position as 2d array and context from
 // previous call to share state/precomputed values between calls.
 
@@ -343,6 +365,7 @@
     return score;
 }
 ai.expectimax.prototype.analyse = function(brd) {
+    this.brdCache = new ai.brdCache();
     var origBrd = new this.brdEngine(brd);
     var nextBrd = new this.brdEngine();
     var maxW = -1;
@@ -368,15 +391,9 @@
 ai.expectimax.prototype.evalFn = function(brd, depth) {
     if (depth >= this.depthLimit)
         return this.weight(brd);
-    if (this.cache[depth]) {
-        var cache = this.cache[depth];
-        for (var i = cache.length-1; i >= 0; i--) {
-            if (brd.equals(cache[i].brd))
-                return cache[i].weight;
-        }
-    } else {
-        this.cache[depth] = [];
-    }
+    var wCached = this.brdCache.get(brd);
+    if (wCached)
+        return wCached;
     var wMin = +Infinity;
     for (var i = 0; i < 3; i++) {
         for (var j = 0; j < 3; j++) {
@@ -402,11 +419,10 @@
             }
         }
     }
-    this.cache[depth].push({brd: brd, weight: wMin});
+    this.brdCache.put(brd, wMin);
     return wMin;
 }
 /* Mark that next board will be unrelated to previous, so any stored precompution can be cleared. */
 ai.expectimax.prototype.cleanup = function() {
-    this.cache = [];
 }
 
--- a/board.js	Thu Sep 25 01:10:01 2014 +0300
+++ b/board.js	Thu Sep 25 02:05:48 2014 +0300
@@ -119,6 +119,26 @@
 }
 /** Compare boards. */
 BoardArr2d.prototype.equals = BoardArr2d.prototype.equals_unrolled;
+BoardArr2d.prototype.compress = function() {
+    var brd = this.brd;
+    var h1 = brd[0][0];
+    h1 = (h1 << 4) | brd[0][1];
+    h1 = (h1 << 4) | brd[0][2];
+    h1 = (h1 << 4) | brd[0][3];
+    h1 = (h1 << 4) | brd[1][0];
+    h1 = (h1 << 4) | brd[1][1];
+    h1 = (h1 << 4) | brd[1][2];
+    h1 = (h1 << 4) | brd[1][3];
+    var h2 = brd[2][0];
+    h2 = (h2 << 4) | brd[2][1];
+    h2 = (h2 << 4) | brd[2][2];
+    h2 = (h2 << 4) | brd[2][3];
+    h2 = (h2 << 4) | brd[3][0];
+    h2 = (h2 << 4) | brd[3][1];
+    h2 = (h2 << 4) | brd[3][2];
+    h2 = (h2 << 4) | brd[3][3];
+    return [h1, h2];
+}
 
 /* Return and optionally fill 2d board. */
 BoardArr2d.prototype.exportTo = function(brd) {
@@ -812,6 +832,26 @@
         && self.db == brd.db && self.dc == brd.dc
         && self.bb == brd.bb && self.bc == brd.bc && self.cb == brd.cb && self.cc == brd.cc;
 };
+BoardObj.prototype.compress = function() {
+    var brd = this.brd;
+    var h1 = brd.aa;
+    h1 = (h1 << 4) | brd.ab;
+    h1 = (h1 << 4) | brd.ac;
+    h1 = (h1 << 4) | brd.ad;
+    h1 = (h1 << 4) | brd.ba;
+    h1 = (h1 << 4) | brd.bb;
+    h1 = (h1 << 4) | brd.bc;
+    h1 = (h1 << 4) | brd.bd;
+    var h2 = brd.ca;
+    h2 = (h2 << 4) | brd.cb;
+    h2 = (h2 << 4) | brd.cc;
+    h2 = (h2 << 4) | brd.cd;
+    h2 = (h2 << 4) | brd.da;
+    h2 = (h2 << 4) | brd.db;
+    h2 = (h2 << 4) | brd.dc;
+    h2 = (h2 << 4) | brd.dd;
+    return [h1, h2];
+}
 BoardObj.prototype.copy = function(brd) {
     var self = this.brd;
     if ( ! brd) {