X-Git-Url: https://git.auder.net/?a=blobdiff_plain;f=client%2Fsrc%2Fvariants%2FTakenmake.js;fp=client%2Fsrc%2Fvariants%2FTakenmake.js;h=9a09b35afbe3d698f9ff23da3ae8ae368fd0318d;hb=6e47d367d4b1b4500bc46d65b44c5e55b52221bb;hp=0000000000000000000000000000000000000000;hpb=383bf350afc0c2600f2774ebf8572398c072a5af;p=vchess.git diff --git a/client/src/variants/Takenmake.js b/client/src/variants/Takenmake.js new file mode 100644 index 00000000..9a09b35a --- /dev/null +++ b/client/src/variants/Takenmake.js @@ -0,0 +1,147 @@ +import { ChessRules } from "@/base_rules"; + +export class TakenmakeRules extends ChessRules { + setOtherVariables(fen) { + super.setOtherVariables(fen); + // Stack of "last move" only for intermediate captures + this.lastMoveEnd = [null]; + } + + getPotentialMovesFrom([x, y], asA) { + const L = this.lastMoveEnd.length; + if (!asA && !!this.lastMoveEnd[L-1]) { + asA = this.lastMoveEnd[L-1].p; + if (x != this.lastMoveEnd[L-1].x || y != this.lastMoveEnd[L-1].y) { + // A capture was played: wrong square + return []; + } + } + let moves = []; + const piece = this.getPiece(x, y); + switch (asA || piece) { + case V.PAWN: + if (!asA || piece == V.PAWN) + moves = this.getPotentialPawnMoves([x, y]); + else { + // Special case: we don't want promotion, since just moving like + // a pawn, but I'm in fact not a pawn :) + const shiftX = (this.turn == 'w' ? -1 : 1); + if (this.board[x + shiftX][y] == V.EMPTY) + moves = [this.getBasicMove([x, y], [x + shiftX, y])]; + } + break; + case V.ROOK: + moves = this.getPotentialRookMoves([x, y]); + break; + case V.KNIGHT: + moves = this.getPotentialKnightMoves([x, y]); + break; + case V.BISHOP: + moves = this.getPotentialBishopMoves([x, y]); + break; + case V.KING: + moves = this.getPotentialKingMoves([x, y]); + break; + case V.QUEEN: + moves = this.getPotentialQueenMoves([x, y]); + break; + } + // Post-process: if capture, + // can a move "as-capturer" be achieved with the same piece? + if (!asA) { + const color = this.turn; + return moves.filter(m => { + if (m.vanish.length == 2 && m.appear.length == 1) { + this.play(m); + let moveOk = true; + const makeMoves = + this.getPotentialMovesFrom([m.end.x, m.end.y], m.vanish[1].p); + if ( + makeMoves.every(mm => { + // Cannot castle after a capturing move + // (with the capturing piece): + if (mm.vanish.length == 2) return true; + this.play(mm); + const res = this.underCheck(color); + this.undo(mm); + return res; + }) + ) { + moveOk = false; + } + this.undo(m); + return moveOk; + } + return true; + }); + } + // Moving "as a": filter out captures (no castles here) + return moves.filter(m => m.vanish.length == 1); + } + + getPossibleMovesFrom(sq) { + const L = this.lastMoveEnd.length; + let asA = undefined; + if (!!this.lastMoveEnd[L-1]) { + if ( + sq[0] != this.lastMoveEnd[L-1].x || + sq[1] != this.lastMoveEnd[L-1].y + ) { + return []; + } + asA = this.lastMoveEnd[L-1].p; + } + return this.filterValid(this.getPotentialMovesFrom(sq, asA)); + } + + filterValid(moves) { + let noCaptureMoves = []; + let captureMoves = []; + moves.forEach(m => { + if (m.vanish.length == 1 || m.appear.length == 2) noCaptureMoves.push(m); + else captureMoves.push(m); + }); + // Capturing moves were already checked in getPotentialMovesFrom() + return super.filterValid(noCaptureMoves).concat(captureMoves); + } + + play(move) { + move.flags = JSON.stringify(this.aggregateFlags()); + this.epSquares.push(this.getEpSquare(move)); + V.PlayOnBoard(this.board, move); + if (move.vanish.length == 1 || move.appear.length == 2) { + // Not a capture: change turn + this.turn = V.GetOppCol(this.turn); + this.movesCount++; + this.lastMoveEnd.push(null); + } + else { + this.lastMoveEnd.push( + Object.assign({}, move.end, { p: move.vanish[1].p }) + ); + } + this.postPlay(move); + } + + postPlay(move) { + const c = move.vanish[0].c; + const piece = move.vanish[0].p; + if (piece == V.KING && move.appear.length > 0) { + this.kingPos[c][0] = move.appear[0].x; + this.kingPos[c][1] = move.appear[0].y; + } + super.updateCastleFlags(move, piece); + } + + undo(move) { + this.disaggregateFlags(JSON.parse(move.flags)); + this.epSquares.pop(); + this.lastMoveEnd.pop(); + V.UndoOnBoard(this.board, move); + if (move.vanish.length == 1 || move.appear.length == 2) { + this.turn = V.GetOppCol(this.turn); + this.movesCount--; + } + super.postUndo(move); + } +};