UNPKG

chlss

Version:

Open-Source Chess Engine in TypeScript.

274 lines (273 loc) 11.7 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.MoveMaker = void 0; const boardPosition_1 = require("./boardPosition"); const pieces_1 = __importDefault(require("./pieces")); const piece_1 = require("./piece"); const coords_1 = require("./coords"); const colour_1 = require("./colour"); exports.MoveMaker = { undoEnPassantMove(boardPosition, move) { const fromY = coords_1.Coords.toY(move.from); const targetX = coords_1.Coords.toX(move.to); const colour = piece_1.Piece.getColour(move.piece); if (colour == null) throw new Error("Move.Piece can't be null."); function getEnemyPawnSquare() { return coords_1.Coords.toSquareIndex(targetX, fromY); } const pawnToAdd = piece_1.Piece.getPawn(colour_1.Colours.inverseColour(colour)); boardPosition_1.BoardPosition.setPiece(boardPosition, getEnemyPawnSquare(), pawnToAdd); boardPosition_1.BoardPosition.setPiece(boardPosition, move.from, move.piece); boardPosition_1.BoardPosition.setEmpty(boardPosition, move.to); }, undoNormalMove(boardPosition, move) { boardPosition_1.BoardPosition.setPiece(boardPosition, move.from, move.piece); boardPosition_1.BoardPosition.setPiece(boardPosition, move.to, move.targetPiece); }, makeMoveOnBoard(boardPosition, move) { if (this.isCastlingMove(move)) { this.makeCastle(boardPosition, move); return; } const fromX = coords_1.Coords.toX(move.from); const targetX = coords_1.Coords.toX(move.to); if (this.isEnPassant(move)) { this.makeEnPassant(boardPosition, move, fromX, targetX); return; } this.makeNormalMoveOnBoard(boardPosition, move); }, undoCastleMove(boardPosition, move) { function setEmptyAll(...n) { n.forEach(t => boardPosition_1.BoardPosition.setEmpty(boardPosition, t)); } function place(n, piece) { boardPosition_1.BoardPosition.setPiece(boardPosition, n, piece); } if (move.from == 60) { if (move.to == 63) { setEmptyAll(61, 62); place(60, pieces_1.default.WhiteKing); place(63, pieces_1.default.WhiteRook); } else if (move.to == 56) { setEmptyAll(58, 59); place(60, pieces_1.default.WhiteKing); place(56, pieces_1.default.WhiteRook); } } else if (move.from == 4) { if (move.to == 0) { setEmptyAll(5, 6); place(4, pieces_1.default.BlackKing); place(7, pieces_1.default.BlackRook); } else if (move.to == 7) { setEmptyAll(2, 3); place(4, pieces_1.default.BlackKing); place(0, pieces_1.default.BlackRook); } } }, undoMoveOnBoard(boardPosition, move) { if (this.isCastlingMove(move)) { this.undoCastleMove(boardPosition, move); return; } else if (this.isEnPassant(move)) { this.undoEnPassantMove(boardPosition, move); return; } this.undoNormalMove(boardPosition, move); }, updateColourToMove(board, move, colour) { board.toMove = colour_1.Colours.inverseColour(colour); }, isAttack(board, move, colour, isCastling, isEnPassant) { return move.targetPiece != pieces_1.default.Empty && !isCastling && !isEnPassant; }, modifyFullMoveNumber(board, move, colour) { if (colour == colour_1.Colours.black) { board.fullMoveCounter += 1; } }, modifyHalfMoveNumber(board, move, colour, isCastling, isEnPassant) { function reset() { board.halfMoveNumber = 0; } const inc = () => board.halfMoveNumber = board.halfMoveNumber + 1; if (piece_1.Piece.isPawn(move.piece) || this.isAttack(board, move, colour, isCastling, isEnPassant)) { reset(); return; } inc(); }, isCastlingMove(move) { return (move.piece == pieces_1.default.WhiteKing && move.targetPiece == pieces_1.default.WhiteRook) || (move.piece == pieces_1.default.BlackKing && move.targetPiece == pieces_1.default.BlackRook); }, makeCastle(boardPosition, move) { function setEmpty(n) { boardPosition_1.BoardPosition.setEmpty(boardPosition, n); } function setPiece(n, piece) { boardPosition_1.BoardPosition.setPiece(boardPosition, n, piece); } function setEmptyAll(...n) { n.forEach((x) => boardPosition_1.BoardPosition.setEmpty(boardPosition, x)); } if (move.from == 60 && move.to == 63) { setEmptyAll(60, 63); setPiece(61, pieces_1.default.WhiteRook); setPiece(62, pieces_1.default.WhiteKing); } else if (move.from == 4 && move.to == 7) { setEmptyAll(4, 7); setPiece(5, pieces_1.default.BlackRook); setPiece(6, pieces_1.default.BlackKing); } else if (move.from == 60 && move.to == 56) { setEmptyAll(56, 57, 60); setPiece(58, pieces_1.default.WhiteKing); setPiece(59, pieces_1.default.WhiteRook); } else if (move.from == 4 && move.to == 0) { setEmptyAll(0, 1, 4); setPiece(2, pieces_1.default.BlackKing); setPiece(3, pieces_1.default.BlackRook); } }, isEnPassant(move) { const fromX = coords_1.Coords.toX(move.from); const targetX = coords_1.Coords.toX(move.to); const fromY = coords_1.Coords.toY(move.from); const toY = coords_1.Coords.toY(move.to); const xValid = ((fromX + 1 == targetX) || (fromX - 1 == targetX)); function yValid() { const colour = piece_1.Piece.getColour(move.piece); if (colour == colour_1.Colours.white) { return toY == fromY - 1; } else if (colour == colour_1.Colours.black) { return toY == fromY + 1; } throw new Error("Colour can't be null. [moveMaker isEnPassant yValid]"); } return piece_1.Piece.isEmpty(move.targetPiece) && xValid && yValid() && piece_1.Piece.isPawn(move.piece) ? { fromX: fromX, targetX: targetX } : null; }, makeEnPassant(boardPosition, move, fromX, targetX) { const fromY = coords_1.Coords.toY(move.from); function getEnemyPawnSquare() { return coords_1.Coords.toSquareIndex(targetX, fromY); } boardPosition_1.BoardPosition.setEmpty(boardPosition, move.from); boardPosition_1.BoardPosition.setEmpty(boardPosition, getEnemyPawnSquare()); boardPosition_1.BoardPosition.setPiece(boardPosition, move.to, move.piece); }, tryDisableCastling(board, move, isCastling) { if (piece_1.Piece.isKing(move.piece)) { this.disableCastling(board, move); } else if (piece_1.Piece.isRook(move.piece)) { if (move.from == 0) board.castling.black.queenSide = false; if (move.from == 7) board.castling.black.kingSide = false; if (move.from == 56) board.castling.white.queenSide = false; if (move.from == 63) board.castling.white.kingSide = false; } /* When the rook is captured, we also need to disable castling related with this rook. */ else if (piece_1.Piece.isRook(move.targetPiece)) { if (move.to == 0) board.castling.black.queenSide = false; if (move.to == 7) board.castling.black.kingSide = false; if (move.to == 56) board.castling.white.queenSide = false; if (move.to == 63) board.castling.white.kingSide = false; } }, makeNormalMoveOnBoard(boardPosition, move) { boardPosition_1.BoardPosition.setPiece(boardPosition, move.to, move.piece); boardPosition_1.BoardPosition.setEmpty(boardPosition, move.from); }, makeNormalMove(board, boardPosition, move) { this.makeNormalMoveOnBoard(boardPosition, move); this.tryDisableCastling(board, move, false); }, disableCastling(board, move) { const colour = piece_1.Piece.getColour(move.piece); if (colour == null) throw new Error("Move.Piece can't be empty"); const castling = colour == colour_1.Colours.white ? board.castling.white : board.castling.black; castling.queenSide = false; castling.kingSide = false; }, clearEnPassant(board) { board.enPassant = null; }, makePromotionMove(boardPosition, move) { const colour = piece_1.Piece.getColour(move.piece); function createPieceToSet() { if (move.promotion == undefined) { throw new Error("Need to specify move.promotion when you're pushing the promotion move."); } if (move.promotion == "knight") { return colour == colour_1.Colours.white ? pieces_1.default.WhiteKnight : pieces_1.default.BlackKnight; } else if (move.promotion == "queen") { return colour == colour_1.Colours.white ? pieces_1.default.WhiteQueen : pieces_1.default.BlackQueen; } else if (move.promotion == "rook") { return colour == colour_1.Colours.white ? pieces_1.default.WhiteRook : pieces_1.default.BlackRook; } else if (move.promotion == "bishop") { return colour == colour_1.Colours.white ? pieces_1.default.WhiteBishop : pieces_1.default.BlackBishop; } throw new Error("MoveMaker->makePromotionMove->createPieceToSet"); } boardPosition_1.BoardPosition.setPiece(boardPosition, move.to, createPieceToSet()); boardPosition_1.BoardPosition.setEmpty(boardPosition, move.from); }, makeMove(board, move) { const boardPosition = board.position; // TODO: I'm getting an error move.piece is empty... [I don't know where] const colour = piece_1.Piece.getColour(move.piece); if (colour == null) throw new Error("Move.Piece can't be null."); const enPassant = this.isEnPassant(move); const isCastling = this.isCastlingMove(move); if (isCastling) { this.makeCastle(boardPosition, move); this.disableCastling(board, move); } else if (move.promotion != undefined) { this.makePromotionMove(boardPosition, move); } else if (enPassant != null) { this.makeEnPassant(boardPosition, move, enPassant.fromX, enPassant.targetX); } else this.makeNormalMove(board, boardPosition, move); this.clearEnPassant(board); this.modifyFullMoveNumber(board, move, colour); this.tryDisableCastling(board, move, isCastling); this.modifyHalfMoveNumber(board, move, colour, isCastling, enPassant != null); this.trySetEnPassant(board, move); this.updateColourToMove(board, move, colour); }, trySetEnPassant(board, move) { if (move.setEnPassant != null) board.enPassant = move.setEnPassant; } };