import { randInt } from "@/utils/alea";
export class ColorboundRules extends ChessRules {
+
static get PawnSpecs() {
return Object.assign(
{},
'k': 'k'
};
- let pieces = { w: new Array(8), b: new Array(8) };
- let flags = "";
- // Shuffle pieces on first (and last rank if randomness == 2)
- for (let c of ["w", "b"]) {
- if (c == 'b' && randomness == 1) {
- pieces['b'] = pieces['w'].map(p => piecesMap[p]);
- flags += flags;
- break;
- }
-
- // TODO: same code as in base_rules. Should extract and factorize?
-
- let positions = ArrayFun.range(8);
-
- let randIndex = 2 * randInt(4);
- const bishop1Pos = positions[randIndex];
- let randIndex_tmp = 2 * randInt(4) + 1;
- const bishop2Pos = positions[randIndex_tmp];
- positions.splice(Math.max(randIndex, randIndex_tmp), 1);
- positions.splice(Math.min(randIndex, randIndex_tmp), 1);
-
- randIndex = randInt(6);
- const knight1Pos = positions[randIndex];
- positions.splice(randIndex, 1);
- randIndex = randInt(5);
- const knight2Pos = positions[randIndex];
- positions.splice(randIndex, 1);
-
- randIndex = randInt(4);
- const queenPos = positions[randIndex];
- positions.splice(randIndex, 1);
-
- const rook1Pos = positions[0];
- const kingPos = positions[1];
- const rook2Pos = positions[2];
-
- pieces[c][rook1Pos] = "r";
- pieces[c][knight1Pos] = "n";
- pieces[c][bishop1Pos] = "b";
- pieces[c][queenPos] = "q";
- pieces[c][kingPos] = "k";
- pieces[c][bishop2Pos] = "b";
- pieces[c][knight2Pos] = "n";
- pieces[c][rook2Pos] = "r";
- if (c == 'b') pieces[c] = pieces[c].map(p => piecesMap[p]);
- flags += V.CoordToColumn(rook1Pos) + V.CoordToColumn(rook2Pos);
- }
- // Add turn + flags + enpassant
+ const baseFen = ChessRules.GenRandInitFen(randomness);
return (
- pieces["b"].join("") +
- "/pppppppp/8/8/8/8/PPPPPPPP/" +
- pieces["w"].join("").toUpperCase() +
- " w 0 " + flags + " -"
+ baseFen.substr(0, 8).split('').map(p => piecesMap[p]).join('') +
+ baseFen.substr(8)
);
}
getPotentialMovesFrom([x, y]) {
switch (this.getPiece(x, y)) {
- case V.C_ROOK:
- return this.getPotentialC_rookMoves([x, y]);
- case V.C_KNIGHT:
- return this.getPotentialC_knightMoves([x, y]);
- case V.C_BISHOP:
- return this.getPotentialC_bishopMoves([x, y]);
- case V.C_QUEEN:
- return this.getPotentialC_queenMoves([x, y]);
- default:
- return super.getPotentialMovesFrom([x, y]);
+ case V.C_ROOK: return this.getPotentialC_rookMoves([x, y]);
+ case V.C_KNIGHT: return this.getPotentialC_knightMoves([x, y]);
+ case V.C_BISHOP: return this.getPotentialC_bishopMoves([x, y]);
+ case V.C_QUEEN: return this.getPotentialC_queenMoves([x, y]);
+ default: return super.getPotentialMovesFrom([x, y]);
}
return [];
}
);
}
- // TODO: really find a way to avoid duolicating most of the castling code
- // each time: here just the queenside castling squares change for black.
getCastleMoves([x, y]) {
- const c = this.getColor(x, y);
- if (x != (c == "w" ? V.size.x - 1 : 0) || y != this.INIT_COL_KING[c])
- return [];
-
- const oppCol = V.GetOppCol(c);
- let moves = [];
- let i = 0;
- // King, then rook:
+ const color = this.getColor(x, y);
const finalSquares = [
// Black castle long in an unusual way:
- (c == 'w' ? [2, 3] : [1, 2]),
+ (color == 'w' ? [2, 3] : [1, 2]),
[V.size.y - 2, V.size.y - 3]
];
- castlingCheck: for (
- let castleSide = 0;
- castleSide < 2;
- castleSide++ //large, then small
- ) {
- if (this.castleFlags[c][castleSide] >= V.size.y) continue;
-
- const rookPos = this.castleFlags[c][castleSide];
- const castlingPiece = this.getPiece(x, rookPos);
- const finDist = finalSquares[castleSide][0] - y;
- let step = finDist / Math.max(1, Math.abs(finDist));
- i = y;
- do {
- if (
- this.isAttacked([x, i], oppCol) ||
- (this.board[x][i] != V.EMPTY &&
- (this.getColor(x, i) != c ||
- ![V.KING, castlingPiece].includes(this.getPiece(x, i))))
- ) {
- continue castlingCheck;
- }
- i += step;
- } while (i != finalSquares[castleSide][0]);
-
- step = castleSide == 0 ? -1 : 1;
- for (i = y + step; i != rookPos; i += step) {
- if (this.board[x][i] != V.EMPTY) continue castlingCheck;
- }
-
- for (i = 0; i < 2; i++) {
- if (
- finalSquares[castleSide][i] != rookPos &&
- this.board[x][finalSquares[castleSide][i]] != V.EMPTY &&
- (
- this.getPiece(x, finalSquares[castleSide][i]) != V.KING ||
- this.getColor(x, finalSquares[castleSide][i]) != c
- )
- ) {
- continue castlingCheck;
- }
- }
-
- moves.push(
- new Move({
- appear: [
- new PiPo({
- x: x,
- y: finalSquares[castleSide][0],
- p: V.KING,
- c: c
- }),
- new PiPo({
- x: x,
- y: finalSquares[castleSide][1],
- p: castlingPiece,
- c: c
- })
- ],
- vanish: [
- new PiPo({ x: x, y: y, p: V.KING, c: c }),
- new PiPo({ x: x, y: rookPos, p: castlingPiece, c: c })
- ],
- end:
- Math.abs(y - rookPos) <= 2
- ? { x: x, y: rookPos }
- : { x: x, y: y + 2 * (castleSide == 0 ? -1 : 1) }
- })
- );
- }
-
- return moves;
+ return super.getCastleMoves([x, y], finalSquares);
}
isAttacked(sq, color) {
return (
this.isAttackedBySlideNJump(sq, color, V.C_QUEEN, V.steps[V.BISHOP]) ||
this.isAttackedBySlideNJump(
- sq, color, V.C_ROOK, V.steps[V.KNIGHT], "oneStep")
+ sq, color, V.C_QUEEN, V.steps[V.KNIGHT], "oneStep")
);
}
}
);
}
+
+ static get SEARCH_DEPTH() {
+ return 2;
+ }
+
};