Fix typo.
"use strict";
var ai = {};
// 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.
////////////////////////////////////////////////////////////////
// Random AI.
////////////////////////////////////////////////////////////////
ai.random = function(brdEngine) {
this.brdEngine = brdEngine;
}
ai.random.prototype.analyse = function(brd) {
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];
}
}
/* Mark that next board will be unrelated to previous, so any stored precompution can be cleared. */
ai.random.prototype.cleanup = function() { }
////////////////////////////////////////////////////////////////
// 1 level deep on max scores.
////////////////////////////////////////////////////////////////
ai.nextMaxScore = function(brdEngine) {
this.brdEngine = brdEngine;
}
ai.nextMaxScore.prototype.analyse = function(brd) {
var origBrd = new this.brdEngine(brd);
var nextBrd = new this.brdEngine();
var maxScore = -1;
var action;
if (origBrd.up(nextBrd)) {
maxScore = nextBrd.score();
action = "up";
}
if (origBrd.left(nextBrd)) {
var score = nextBrd.score();
if (maxScore < score) {
action = "left";
maxScore = score;
}
}
if (origBrd.down(nextBrd)) {
var score = nextBrd.score();
if (maxScore < score) {
action = "down";
maxScore = score;
}
}
if (origBrd.right(nextBrd)) {
var score = nextBrd.score();
if (maxScore < score) {
action = "right";
maxScore = score;
}
}
return action;
}
/* Mark that next board will be unrelated to previous, so any stored precompution can be cleared. */
ai.nextMaxScore.prototype.cleanup = function() { }
////////////////////////////////////////////////////////////////
// 1 level deep on max value.
////////////////////////////////////////////////////////////////
ai.nextMaxValue = function(brdEngine) {
this.brdEngine = brdEngine;
}
ai.nextMaxValue.prototype.analyse = function(brd) {
var origBrd = new this.brdEngine(brd);
var nextBrd = new this.brdEngine();
var maxMax = -1;
var action;
if (origBrd.up(nextBrd)) {
maxMax = nextBrd.max();
action = "up";
}
if (origBrd.left(nextBrd)) {
var max = nextBrd.score();
if (maxMax < max) {
action = "left";
maxMax = max;
}
}
if (origBrd.down(nextBrd)) {
var max = nextBrd.max();
if (maxMax < max) {
action = "down";
maxMax = max;
}
}
if (origBrd.right(nextBrd)) {
var max = nextBrd.max();
if (maxMax < max) {
action = "right";
maxMax = max;
}
}
return action;
}
/* Mark that next board will be unrelated to previous, so any stored precompution can be cleared. */
ai.nextMaxScore.prototype.cleanup = function() { }
////////////////////////////////////////////////////////////////
// N level deep on score value without random.
////////////////////////////////////////////////////////////////
ai.deepMaxScore = function(brdEngine) {
this.brdEngine = brdEngine;
}
ai.deepMaxScore.prototype.analyse = function(brd) {
var origBrd = new this.brdEngine(brd);
var nextBrd = new this.brdEngine();
var maxScore = -1;
var action;
if (origBrd.up(nextBrd)) {
maxScore = this.bestScore(nextBrd);
action = "up";
}
if (origBrd.left(nextBrd)) {
var score = this.bestScore(nextBrd);
if (maxScore < score) {
action = "left";
maxScore = score;
}
}
if (origBrd.down(nextBrd)) {
var score = this.bestScore(nextBrd);
if (maxScore < score) {
action = "down";
maxScore = score;
}
}
if (origBrd.right(nextBrd)) {
var score = this.bestScore(nextBrd);
if (maxScore < score) {
action = "right";
maxScore = score;
}
}
return action;
}
ai.deepMaxScore.prototype.bestScore = function(brd, seenBrds) {
if (seenBrds) {
for (var i = 0; i < seenBrds.length; i++)
if (brd.equals(seenBrds[i]))
return 0;
} else {
seenBrds = [];
}
seenBrds.push(brd);
var maxScore = brd.score();
var nextBrd = new this.brdEngine();
if (brd.up(nextBrd))
maxScore = Math.max(maxScore, this.bestScore(nextBrd, seenBrds) - 1);
if (brd.down(nextBrd))
maxScore = Math.max(maxScore, this.bestScore(nextBrd, seenBrds) - 1);
if (brd.left(nextBrd))
maxScore = Math.max(maxScore, this.bestScore(nextBrd, seenBrds) - 1);
if (brd.right(nextBrd))
maxScore = Math.max(maxScore, this.bestScore(nextBrd, seenBrds) - 1);
return maxScore;
}