import { randInt } from "@/utils/alea";
import { ChessRules, PiPo, Move } from "@/base_rules";
-export const VariantRules = class EightpiecesRules extends ChessRules {
+export class EightpiecesRules extends ChessRules {
static get JAILER() {
return "j";
}
positions.splice(randIndex, 1);
// Rook, jailer and king positions are now almost fixed,
- // only the ordering rook-> jailer or jailer->rook must be decided.
+ // only the ordering rook->jailer or jailer->rook must be decided.
let rookPos = positions[0];
let jailerPos = positions[2];
const kingPos = positions[1];
// Because of the lancers, getPiece() could be wrong:
// use board[x][y][1] instead (always valid).
getBasicMove([sx, sy], [ex, ey], tr) {
+ const initColor = this.getColor(sx, sy);
+ const initPiece = this.board[sx][sy].charAt(1);
let mv = new Move({
appear: [
new PiPo({
x: ex,
y: ey,
- c: tr ? tr.c : this.getColor(sx, sy),
- p: tr ? tr.p : this.board[sx][sy].charAt(1)
+ c: tr ? tr.c : initColor,
+ p: tr ? tr.p : initPiece
})
],
vanish: [
new PiPo({
x: sx,
y: sy,
- c: this.getColor(sx, sy),
- p: this.board[sx][sy].charAt(1)
+ c: initColor,
+ p: initPiece
})
]
});
);
}
- // Adapted: castle with jailer possible
- getCastleMoves([x, y]) {
- const c = this.getColor(x, y);
- const firstRank = (c == "w" ? V.size.x - 1 : 0);
- if (x != firstRank || y != this.INIT_COL_KING[c])
- return [];
-
- const oppCol = V.GetOppCol(c);
- let moves = [];
- let i = 0;
- // King, then rook or jailer:
- const finalSquares = [
- [2, 3],
- [V.size.y - 2, V.size.y - 3]
- ];
- castlingCheck: for (
- let castleSide = 0;
- castleSide < 2;
- castleSide++
- ) {
- if (this.castleFlags[c][castleSide] >= 8) continue;
- // Rook (or jailer) and king are on initial position
- 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, V.ROOK, V.JAILER].includes(this.getPiece(x, i))))
- ) {
- continue castlingCheck;
- }
- i += step;
- } while (i != finalSquares[castleSide][0]);
- step = castleSide == 0 ? -1 : 1;
- const rookOrJailerPos = this.castleFlags[c][castleSide];
- for (i = y + step; i != rookOrJailerPos; i += step)
- if (this.board[x][i] != V.EMPTY) continue castlingCheck;
-
- // Nothing on final squares, except maybe king and castling rook or jailer?
- for (i = 0; i < 2; i++) {
- if (
- this.board[x][finalSquares[castleSide][i]] != V.EMPTY &&
- this.getPiece(x, finalSquares[castleSide][i]) != V.KING &&
- finalSquares[castleSide][i] != rookOrJailerPos
- ) {
- continue castlingCheck;
- }
- }
-
- // If this code is reached, castle is valid
- const castlingPiece = this.getPiece(firstRank, rookOrJailerPos);
- 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: rookOrJailerPos, p: castlingPiece, c: c })
- ],
- end:
- Math.abs(y - rookOrJailerPos) <= 2
- ? { x: x, y: rookOrJailerPos }
- : { x: x, y: y + 2 * (castleSide == 0 ? -1 : 1) }
- })
- );
- }
-
- return moves;
- }
-
atLeastOneMove() {
// If in second-half of a move, we already know that a move is possible
if (this.subTurn == 2) return true;
}
play(move) {
-// if (!this.states) this.states = [];
-// const stateFen = this.getFen();
-// this.states.push(stateFen);
-
this.prePlay(move);
move.flags = JSON.stringify(this.aggregateFlags());
this.epSquares.push(this.getEpSquare(move));
if (move.sentryPush) this.subTurn = 2;
}
this.postUndo(move);
-
-// const stateFen = this.getFen();
-// if (stateFen != this.states[this.states.length-1]) debugger;
-// this.states.pop();
}
postUndo(move) {
this.sentryPush.pop();
}
- isAttacked(sq, colors) {
+ isAttacked(sq, color) {
return (
- super.isAttacked(sq, colors) ||
- this.isAttackedByLancer(sq, colors) ||
- this.isAttackedBySentry(sq, colors)
+ super.isAttacked(sq, color) ||
+ this.isAttackedByLancer(sq, color) ||
+ this.isAttackedBySentry(sq, color)
);
}
- isAttackedBySlideNJump([x, y], colors, piece, steps, oneStep) {
+ isAttackedBySlideNJump([x, y], color, piece, steps, oneStep) {
for (let step of steps) {
let rx = x + step[0],
ry = y + step[1];
}
if (
V.OnBoard(rx, ry) &&
- this.getPiece(rx, ry) === piece &&
- colors.includes(this.getColor(rx, ry)) &&
+ this.getPiece(rx, ry) == piece &&
+ this.getColor(rx, ry) == color &&
!this.isImmobilized([rx, ry])
) {
return true;
return false;
}
- isAttackedByPawn([x, y], colors) {
- for (let c of colors) {
- const pawnShift = c == "w" ? 1 : -1;
- if (x + pawnShift >= 0 && x + pawnShift < V.size.x) {
- for (let i of [-1, 1]) {
- if (
- y + i >= 0 &&
- y + i < V.size.y &&
- this.getPiece(x + pawnShift, y + i) == V.PAWN &&
- this.getColor(x + pawnShift, y + i) == c &&
- !this.isImmobilized([x + pawnShift, y + i])
- ) {
- return true;
- }
+ isAttackedByPawn([x, y], color) {
+ const pawnShift = (color == "w" ? 1 : -1);
+ if (x + pawnShift >= 0 && x + pawnShift < V.size.x) {
+ for (let i of [-1, 1]) {
+ if (
+ y + i >= 0 &&
+ y + i < V.size.y &&
+ this.getPiece(x + pawnShift, y + i) == V.PAWN &&
+ this.getColor(x + pawnShift, y + i) == color &&
+ !this.isImmobilized([x + pawnShift, y + i])
+ ) {
+ return true;
}
}
}
return false;
}
- isAttackedByLancer([x, y], colors) {
+ isAttackedByLancer([x, y], color) {
for (let step of V.steps[V.ROOK].concat(V.steps[V.BISHOP])) {
// If in this direction there are only enemy pieces and empty squares,
// and we meet a lancer: can he reach us?
V.OnBoard(coord.x, coord.y) &&
(
this.board[coord.x][coord.y] == V.EMPTY ||
- colors.includes(this.getColor(coord.x, coord.y))
+ this.getColor(coord.x, coord.y) == color
)
) {
if (
return false;
}
- isAttackedBySentry([x, y], colors) {
+ isAttackedBySentry([x, y], color) {
// Attacked by sentry means it can self-take our king.
// Just check diagonals of enemy sentry(ies), and if it reaches
// one of our pieces: can I self-take?
- const color = V.GetOppCol(colors[0]);
+ const myColor = V.GetOppCol(color);
let candidates = [];
for (let i=0; i<V.size.x; i++) {
for (let j=0; j<V.size.y; j++) {
if (
this.getPiece(i,j) == V.SENTRY &&
- colors.includes(this.getColor(i,j)) &&
+ this.getColor(i,j) == color &&
!this.isImmobilized([i, j])
) {
for (let step of V.steps[V.BISHOP]) {
}
if (
V.OnBoard(sq[0], sq[1]) &&
- this.getColor(sq[0], sq[1]) == color
+ this.getColor(sq[0], sq[1]) == myColor
) {
candidates.push([ sq[0], sq[1] ]);
}