The Computer Player
This is the user’s opponent object. This other child of player has to decide by itself of its best actions. There are plenty of things to improve for sure, but we’ll get a basic AI able to play against our user.
function Computer(i, base, limit) {
'use strict';
this.name = 'Computer';
// Call the parent constructor
Player.call(this, i, base, limit);
}
// Inherit Player
Computer.prototype = Object.create(Player.prototype);
The opponent
First of all, we need to decide which player is our main opponent. This is mostly for the four players game configuration.
Computer.prototype.getOpponent = function () {
'use strict';
var i, opponent = false, path, oppPath;
for (i = 0; i < game.players.length; i += 1) {
path = game.players[i].getPath();
// Is the path of that player the shortest ? Or randomly if equal :
if ((this.i !== i) && (!opponent || (path < oppPath) || ((path === oppPath) && (Math.random() > 0.5)))) {
opponent = game.players[i];
oppPath = path;
}
}
// Return the opponent with the shortest way to his goal line
return opponent;
};
Determining the advantage
The difference we get with this function is this computer‘s path length minus its opponent one : the lower it is, the closer it gets to win. So for a negative result, we have the advantage, and for a positive one, our opponent has it.
Computer.prototype.getDifference = function (opponent) {
'use strict';
// Return the difference between this Player's path and the given opponent's path
return (this.getPath() - opponent.getPath());
};
Get a smart fence
What we’re basically doing here is to try every possible fence, and return the one that gets us the lowest difference.
It is only planning one action forward, but for a smarter AI we could extend this method to compute several moves ahead.
Computer.prototype.getFence = function () {
'use strict';
var a, b, opponent = this.getOpponent(), difference = this.getDifference(opponent), newDif, fence = false, span;
// If we cannot put any other fence, no need to continue
if ((this.limit === 0) || (difference < 0)) { return false; }
// For each position on board
for (a = 0; a < game.size; a += 1) {
for (b = 0; b < game.size; b += 1) {
// We set a fence object.
span = {a: a, b: b, horizontal: true};
// Get the difference of path length for a valid potential object
newDif = game.validFence(span, 1, opponent);
if ((newDif !== false) && (newDif < difference)) {
// That fence is valid and giving us the advantage
difference = newDif;
fence = jQuery.extend({}, span);
}
// Let's rotate and try again on the vertical axis.
span.horizontal = false;
newDif = game.validFence(span, 1, opponent);
if ((newDif !== false) && (newDif < difference)) {
difference = newDif;
fence = jQuery.extend({}, span);
}
}
}
// Return the more advantageous fence, or false if we didn't set any
return fence;
};
Now be smart
This function plays a smart fence if we found any. Otherwise, it moves the computer’s pawn to the accessible square with the shortest path to its goal line.
Computer.prototype.play = function () {
'use strict';
var action = this.getFence();
if (action) {
// We found a fence to put.
this.putUp(action);
} else {
action = this.getAccess();
// Let's move to the next position
this.move(action);
}
};