Add blind eight random AI.
--- 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.
////////////////////////////////////////////////////////////////