chlss
Version:
Open-Source Chess Engine in TypeScript.
274 lines (273 loc) • 11.7 kB
JavaScript
;
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;
}
};