X-Git-Url: https://git.auder.net/?a=blobdiff_plain;f=client%2Fsrc%2Fvariants%2FCopycat.js;fp=client%2Fsrc%2Fvariants%2FCopycat.js;h=089b92f86b98410014393d0e5602c89814e8962a;hb=b21e0e3a8f4af5c04b39c034d13bbb4e1e2abf18;hp=0000000000000000000000000000000000000000;hpb=8d15beb4880d40c89d893a3423fb1d0f0ffbc2c6;p=vchess.git diff --git a/client/src/variants/Copycat.js b/client/src/variants/Copycat.js new file mode 100644 index 00000000..089b92f8 --- /dev/null +++ b/client/src/variants/Copycat.js @@ -0,0 +1,144 @@ +import { ChessRules } from "@/base_rules"; + +export class CopycatRules extends ChessRules { + + getPotentialMovesFrom([x, y]) { + let moves = super.getPotentialMovesFrom([x, y]); + // Expand potential moves if attacking friendly pieces. + const piece = this.getPiece(x,y); + if ([V.PAWN, V.KING].includes(piece)) return moves; + const color = this.turn; + const oneStep = (piece == V.PAWN); + let movements = {}, + steps = []; + if (piece == V.QUEEN) steps = V.steps[V.ROOK].concat(V.steps[V.BISHOP]); + else steps = V.steps[piece]; + steps.forEach(s => { + let [i, j] = [x + s[0], y + s[1]]; + while ( + V.OnBoard(i, j) && + this.board[i][j] == V.EMPTY && + piece != V.KNIGHT + ) { + i += s[0]; + j += s[1]; + } + if (V.OnBoard(i, j) && this.getColor(i, j) == color) { + const attacked = this.getPiece(i, j); + if ([V.ROOK, V.BISHOP, V.KNIGHT].includes(attacked)) { + if (!movements[attacked]) movements[attacked] = true; + } + else if (attacked == V.QUEEN) { + if (!movements[V.ROOK]) movements[V.ROOK] = true; + if (!movements[V.BISHOP]) movements[V.BISHOP] = true; + } + } + }); + Object.keys(movements).forEach(type => { + if ( + (piece != V.QUEEN && type != piece) || + (piece == V.QUEEN && type == V.KNIGHT) + ) { + Array.prototype.push.apply(moves, + this.getSlideNJumpMoves([x, y], V.steps[type], type == V.KNIGHT)); + } + }); + return moves; + } + + // Detect indirect attacks: + isAttackedBy_aux( + [x, y], color, steps1, oneStep1, piece1, steps2, oneStep2, pieces2) + { + for (let s1 of steps1) { + let i = x + s1[0], + j = y + s1[1]; + while (V.OnBoard(i, j) && this.board[i][j] == V.EMPTY && !oneStep1) { + i += s1[0]; + j += s1[1]; + } + if ( + V.OnBoard(i, j) && + this.board[i][j] != V.EMPTY && + this.getPiece(i, j) == piece1 && + this.getColor(i, j) == color + ) { + // Continue to detect "copycat" attacks + for (let s2 of steps2) { + let ii = i + s2[0], + jj = j + s2[1]; + while ( + V.OnBoard(ii, jj) && + this.board[ii][jj] == V.EMPTY && + !oneStep2 + ) { + ii += s2[0]; + jj += s2[1]; + } + if ( + V.OnBoard(ii, jj) && + this.board[ii][jj] != V.EMPTY && + pieces2.includes(this.getPiece(ii, jj)) && + this.getColor(ii, jj) == color + ) { + return true; + } + } + } + } + return false; + } + + isAttackedByKnight(sq, color) { + if (super.isAttackedByKnight(sq, color)) return true; + return ( + this.isAttackedBy_aux(sq, color, + V.steps[V.ROOK], false, V.KNIGHT, + V.steps[V.KNIGHT], true, [V.ROOK, V.QUEEN] + ) || + this.isAttackedBy_aux(sq, color, + V.steps[V.BISHOP], false, V.KNIGHT, + V.steps[V.KNIGHT], true, [V.BISHOP, V.QUEEN] + ) + ); + } + + isAttackedByRook(sq, color) { + if (super.isAttackedByRook(sq, color)) return true; + return ( + this.isAttackedBy_aux(sq, color, + V.steps[V.KNIGHT], true, V.ROOK, + V.steps[V.ROOK], false, [V.KNIGHT] + ) || + this.isAttackedBy_aux(sq, color, + V.steps[V.BISHOP], false, V.ROOK, + V.steps[V.ROOK], false, [V.BISHOP, V.QUEEN] + ) + ); + } + + isAttackedByBishop(sq, color) { + if (super.isAttackedByBishop(sq, color)) return true; + return ( + this.isAttackedBy_aux(sq, color, + V.steps[V.KNIGHT], true, V.BISHOP, + V.steps[V.BISHOP], false, [V.KNIGHT] + ) || + this.isAttackedBy_aux(sq, color, + V.steps[V.ROOK], false, V.BISHOP, + V.steps[V.BISHOP], false, [V.ROOK, V.QUEEN] + ) + ); + } + + isAttackedByQueen(sq, color) { + if (super.isAttackedByQueen(sq, color)) return true; + return ( + this.isAttackedBy_aux(sq, color, + V.steps[V.KNIGHT], true, V.QUEEN, + V.steps[V.ROOK].concat(V.steps[V.BISHOP]), false, [V.KNIGHT] + ) + ); + } + +};