}
}
- static GenRandInitFen(randomness) {
- if (randomness == 0)
+ static GenRandInitFen(options) {
+ if (options.randomness == 0)
return "rnbq1knbr/9/9/9/4a4/9/9/9/RNBQ1KNBR w 0";
let pieces = { w: new Array(8), b: new Array(8) };
for (let c of ["w", "b"]) {
- if (c == 'b' && randomness == 1) {
+ if (c == 'b' && options.randomness == 1) {
pieces['b'] = pieces['w'];
break;
}
V.OnBoard(i, j) &&
this.board[i][j] == V.EMPTY &&
(
- // In a corner? The, allow all ball moves
+ // In a corner? Then, allow all ball moves
([0, 8].includes(bp[0]) && [0, 8].includes(bp[1])) ||
// Do not end near the knight
(Math.abs(i - x) >= 2 || Math.abs(j - y) >= 2)
}
}
const kickedFrom = x + "-" + y;
- moves.forEach(m => m.by = kickedFrom)
+ moves.forEach(m => m.start.by = kickedFrom)
return moves;
}
const moves = super.getPotentialMovesFrom([x, y])
.filter(m => m.end.y != 4 || ![0, 8].includes(m.end.x));
// If bishop stuck in a corner: allow to jump over the next obstacle
- if (moves.length == 0 && piece == V.BISHOP) {
- if (
- x == 0 && y == 0 &&
- this.board[1][1] != V.EMPTY &&
- this.board[2][2] == V.EMPTY
- ) {
- return [super.getBasicMove([x, y], [2, 2])];
- }
- if (
- x == 0 && y == 8 &&
- this.board[1][7] != V.EMPTY &&
- this.board[2][6] == V.EMPTY
- ) {
- return [super.getBasicMove([x, y], [2, 6])];
- }
- if (
- x == 8 && y == 0 &&
- this.board[7][1] != V.EMPTY &&
- this.board[6][2] == V.EMPTY
- ) {
- return [super.getBasicMove([x, y], [6, 2])];
- }
+ if (
+ moves.length == 0 && piece == V.BISHOP &&
+ [0, 8].includes(x) && [0, 8].includes(y)
+ ) {
+ const indX = x == 0 ? [1, 2] : [7, 6];
+ const indY = y == 0 ? [1, 2] : [7, 6];
if (
- x == 8 && y == 8 &&
- this.board[7][7] != V.EMPTY &&
- this.board[6][6] == V.EMPTY
+ this.board[indX[0]][indY[0]] != V.EMPTY &&
+ this.board[indX[1]][indY[1]] == V.EMPTY
) {
- return [super.getBasicMove([x, y], [6, 6])];
+ return [super.getBasicMove([x, y], [indX[1], indY[1]])];
}
}
return moves;
const steps = V.steps[V.ROOK].concat(V.steps[V.BISHOP]);
const c = this.turn;
let moves = [];
+ let kicks = {};
+ let adjacentPieces = false;
for (let s of steps) {
const [i, j] = [x + s[0], y + s[1]];
if (
this.board[i][j] != V.EMPTY &&
this.getColor(i, j) == c
) {
- Array.prototype.push.apply(moves, this.tryKickFrom([i, j]));
+ const kmoves = this.tryKickFrom([i, j]);
+ kmoves.forEach(km => {
+ const key = V.CoordsToSquare(km.start) + V.CoordsToSquare(km.end);
+ if (!kicks[key]) {
+ moves.push(km);
+ kicks[key] = true;
+ }
+ });
+ if (!adjacentPieces) adjacentPieces = true;
}
}
- // And, always add the "end" move. For computer, keep only one
- outerLoop: for (let i=0; i < V.size.x; i++) {
- for (let j=0; j < V.size.y; j++) {
- if (this.board[i][j] != V.EMPTY && this.getColor(i, j) == c) {
- moves.push(super.getBasicMove([x, y], [i, j]));
- if (!!computer) break outerLoop;
+ if (adjacentPieces) {
+ // Add the "end" move (even if no valid kicks)
+ outerLoop: for (let i=0; i < V.size.x; i++) {
+ for (let j=0; j < V.size.y; j++) {
+ if (this.board[i][j] != V.EMPTY && this.getColor(i, j) == c) {
+ moves.push({
+ appear: [], vanish: [],
+ start: { x: x, y: y }, end: { x: i, y: j }
+ });
+ if (computer) break outerLoop; //no choice for computer
+ }
}
}
}
return moves;
}
- // No captures:
- getSlideNJumpMoves([x, y], steps, oneStep) {
- let moves = [];
- outerLoop: for (let step of steps) {
- let i = x + step[0];
- let j = y + step[1];
- let stepCount = 1;
- while (V.OnBoard(i, j) && this.board[i][j] == V.EMPTY) {
- moves.push(this.getBasicMove([x, y], [i, j]));
- if (!!oneStep) continue outerLoop;
- i += step[0];
- j += step[1];
- stepCount++;
- }
- }
- return moves;
+ canTake() {
+ return false;
}
// Extra arg "computer" to avoid trimming all redundant pass moves:
filterValid(moves) {
const L = this.kickedBy.length;
const kb = this.kickedBy[L-1];
- return moves.filter(m => !m.by || !kb[m.by]);
+ return moves.filter(m => !m.start.by || !kb[m.start.by]);
}
getCheckSquares() {
play(move) {
// Special message saying "passes are over"
- const passesOver = (move.vanish.length == 2);
+ const passesOver = (move.vanish.length == 0);
if (!passesOver) {
this.prePlay(move);
V.PlayOnBoard(this.board, move);
}
else {
this.subTurn++;
- if (!!move.by) {
+ if (!!move.start.by) {
const L = this.kickedBy.length;
- this.kickedBy[L-1][move.by] = true;
+ this.kickedBy[L-1][move.start.by] = true;
}
}
}
undo(move) {
- const passesOver = (move.vanish.length == 2);
+ const passesOver = (move.vanish.length == 0);
if (move.turn[0] != this.turn) {
[this.turn, this.subTurn] = move.turn;
this.movesCount--;
}
else {
this.subTurn--;
- if (!!move.by) {
+ if (!!move.start.by) {
const L = this.kickedBy.length;
- delete this.kickedBy[L-1][move.by];
+ delete this.kickedBy[L-1][move.start.by];
}
}
if (!passesOver) {
// NOTE: evalPosition() is wrong, but unused since bot plays at random
getNotation(move) {
- if (move.vanish.length == 2) return "pass";
+ if (move.vanish.length == 0) return "pass";
if (move.vanish[0].p != 'a') return super.getNotation(move);
// Kick: simple notation (TODO?)
return V.CoordsToSquare(move.end);