Add blind eight random AI.
authorOleksandr Gavenko <gavenkoa@gmail.com>
Wed, 10 Sep 2014 14:49:28 +0300
changeset 36 a18fc2601ce8
parent 35 3d56325d7002
child 37 fe75d168a605
Add blind eight random AI.
2048.html
ai.js
--- a/2048.html	Wed Sep 10 13:26:10 2014 +0300
+++ b/2048.html	Wed Sep 10 14:49:28 2014 +0300
@@ -73,6 +73,14 @@
       display: inline-block;
       float: left;
       margin: 1px 4px;
+      padding: 2px;
+      border: 1px solid tan;
+      border-radius: 4px;
+    }
+    div.ai > div.option > input.int {
+      text-align: right;
+      max-width: 4em;
+      margin-rght: 2px;
     }
     .clearfix {
       clear: both;
@@ -148,6 +156,23 @@
         <button class="ai">enable</button>
         <h5>bling random</h5>
       </div>
+      <div class="ai" id="ai-blind-weight-random">
+        <button class="ai">enable</button>
+        <h5>bling weight random</h5>
+        <div class="option">
+          <input type="text" name="left" class="int" pattern="[0-9]*" value="1"/> left weight
+        </div>
+        <div class="option">
+          <input type="text" name="right" class="int" pattern="[0-9]*" value="1"/> right weight
+        </div>
+        <div class="option">
+          <input type="text" name="up" class="int" pattern="[0-9]*" value="1"/> up weight
+        </div>
+        <div class="option">
+          <input type="text" name="down" class="int" pattern="[0-9]*" value="1"/> down weight
+        </div>
+        <div class="clearfix"></div>
+      </div>
       <div class="ai" id="ai-blind-cycle">
         <button class="ai">enable</button>
         <h5>blind cycle</h5>
@@ -481,6 +506,14 @@
       "ai-blind-random": function() {
         return new ai.blindRandom(ui.brdEngine);
       },
+      "ai-blind-weight-random": function(aiDom) {
+        var cfg = {};
+        cfg.left = aiDom.querySelectorAll("input[name='left']")[0].value;
+        cfg.right = aiDom.querySelectorAll("input[name='right']")[0].value;
+        cfg.up = aiDom.querySelectorAll("input[name='up']")[0].value;
+        cfg.down = aiDom.querySelectorAll("input[name='down']")[0].value;
+        return new ai.blindWeightRandom(ui.brdEngine);
+      },
       "ai-blind-cycle": function(aiDom) {
         var cfg = {};
         cfg.clockwise = aiDom.querySelectorAll("input[name='clockwise']")[0].checked;
--- a/ai.js	Wed Sep 10 13:26:10 2014 +0300
+++ b/ai.js	Wed Sep 10 14:49:28 2014 +0300
@@ -1,8 +1,8 @@
 "use strict";
 
 var ai = {};
-ai.dirs = ["up", "down", "left", "right"];
-ai.canDirs = ["canUp", "canDown", "canLeft", "canRight"];
+ai.dirs = ["up", "right", "down", "left"];
+ai.canDirs = ["canUp", "canRight", "canDown", "canLeft"];
 
 // 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.
@@ -10,7 +10,7 @@
 
 
 ////////////////////////////////////////////////////////////////
-// Random AI.
+// Blind random AI.
 ////////////////////////////////////////////////////////////////
 
 ai.blindRandom = function(brdEngine) {
@@ -20,8 +20,8 @@
     var origBrd = new this.brdEngine(brd);
     while (true) {
         var rnd = Math.floor(Math.random()*4);
-        if (origBrd[["canUp", "canDown", "canLeft", "canRight"][rnd]]())
-            return ["up", "down", "left", "right"][rnd];
+        if (origBrd[ai.canDirs[rnd]]())
+            return ai.dirs[rnd];
     }
 }
 /* Mark that next board will be unrelated to previous, so any stored precompution can be cleared. */
@@ -30,6 +30,49 @@
 
 
 ////////////////////////////////////////////////////////////////
+// Blind weight random AI.
+////////////////////////////////////////////////////////////////
+
+ai.blindWeightRandom = function(brdEngine, cfg) {
+    this.brdEngine = brdEngine;
+    this.cfg = this.cfg || {};
+    var left = ai.blindWeightRandom.fixWeight(this.cfg.left);
+    var right = ai.blindWeightRandom.fixWeight(this.cfg.right);
+    var up = ai.blindWeightRandom.fixWeight(this.cfg.up);
+    var down = ai.blindWeightRandom.fixWeight(this.cfg.down);
+    var total = left + right + up + down;
+    this.threshold1 = left/total;
+    this.threshold2 = (left+down)/total;
+    this.threshold3 = (left+down+right)/total;
+}
+ai.blindWeightRandom.fixWeight = function(val) {
+    val = val && parseFloat(v) || 1;
+    if (val <= 0)
+        val = 1;
+    return val;
+}
+ai.blindWeightRandom.prototype.analyse = function(brd) {
+    var origBrd = new this.brdEngine(brd);
+    while (true) {
+        var rnd = Math.random();
+        if (rnd < this.threshold1)
+            var dir = 0;
+        else if (rnd < this.threshold2)
+            var dir = 1;
+        else if (rnd < this.threshold3)
+            var dir = 2;
+        else
+            var dir = 3;
+        if (origBrd[ai.canDirs[dir]]())
+            return ai.dirs[dir];
+    }
+}
+/* Mark that next board will be unrelated to previous, so any stored precompution can be cleared. */
+ai.blindWeightRandom.prototype.cleanup = function() { }
+
+
+
+////////////////////////////////////////////////////////////////
 // Blind cycle AI.
 ////////////////////////////////////////////////////////////////