UNPKG

chlss

Version:

Open-Source Chess Engine in TypeScript.

206 lines (205 loc) 7.18 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.FEN = void 0; const boardPosition_1 = require("./boardPosition"); const stringBuilder_1 = require("./stringBuilder"); const piece_1 = require("./piece"); const pieces_1 = __importDefault(require("./pieces")); const colour_1 = require("./colour"); const boardNotation_1 = require("./boardNotation"); function writeFENPosition(boardPosition) { const stringBuilder = new stringBuilder_1.StringBuilder(); function writeSeparator() { stringBuilder.append("/"); } function writeEmpty() { stringBuilder.append("1"); } function pieceToFenValue(piece) { switch (piece) { case pieces_1.default.WhiteKnight: return "N"; case pieces_1.default.BlackKnight: return 'n'; case pieces_1.default.WhiteKing: return 'K'; case pieces_1.default.BlackKing: return 'k'; case pieces_1.default.WhiteBishop: return 'B'; case pieces_1.default.BlackBishop: return 'b'; case pieces_1.default.BlackPawn: return 'p'; case pieces_1.default.WhitePawn: return 'P'; case pieces_1.default.WhiteRook: return 'R'; case pieces_1.default.BlackRook: return 'r'; case pieces_1.default.BlackQueen: return 'q'; case pieces_1.default.WhiteQueen: return 'Q'; } throw new Error(`unknown piece: '${piece}'`); } for (let index = 0; index < 64; index++) { const piece = boardPosition_1.BoardPosition.getPiece(boardPosition, index); if ((index) % 8 == 0 && index != 0 && index != 63) { writeSeparator(); } if (piece_1.Piece.isEmpty(piece)) { writeEmpty(); } else stringBuilder.append(pieceToFenValue(piece)); } return stringBuilder.build().replace(/1+/g, (m) => (m.length).toString()); } function writeSpace(stringBuilder) { stringBuilder.append(" "); } function writeText(stringBuilder, text) { stringBuilder.append(text); } function writeCastling(stringBuilder, castling) { if (!castling.white.kingSide && !castling.white.queenSide && !castling.black.kingSide && !castling.black.queenSide) { stringBuilder.append("-"); return; } if (castling.white.kingSide) stringBuilder.append("K"); if (castling.white.queenSide) stringBuilder.append("Q"); if (castling.black.kingSide) stringBuilder.append("k"); if (castling.black.queenSide) stringBuilder.append("q"); } function writeColour(stringBuilder, colour) { stringBuilder.append(colour == colour_1.Colours.white ? "w" : "b"); } function writeEnPassant(stringBuilder, enPassant) { stringBuilder.append(enPassant == null ? "-" : boardNotation_1.BoardNotation.toBoardNotation(enPassant)); } function writeNumber(stringBuilder, i) { stringBuilder.append(i.toString()); } function parseCastlingData(castling) { return { black: { queenSide: castling.includes("q"), kingSide: castling.includes("k") }, white: { queenSide: castling.includes("Q"), kingSide: castling.includes("K") } }; } function parseEnPassant(enPassant) { return enPassant == "-" ? null : boardNotation_1.BoardNotation.fromBoardNotation(enPassant); } function parseFullMoveCounter(fullMoveCounter) { return parseInt(fullMoveCounter); } function parseHalfMoveCounter(halfMoveCounter) { return parseInt(halfMoveCounter); } function isDigit(str) { const number = parseInt(str); return isNaN(number) ? null : number; } function parseFENPosition(position, boardPosition) { let index = 0; function fenValueToPiece(fenValue) { switch (fenValue) { case 'N': return pieces_1.default.WhiteKnight; case 'n': return pieces_1.default.BlackKnight; case 'K': return pieces_1.default.WhiteKing; case 'k': return pieces_1.default.BlackKing; case 'B': return pieces_1.default.WhiteBishop; case 'b': return pieces_1.default.BlackBishop; case 'p': return pieces_1.default.BlackPawn; case 'P': return pieces_1.default.WhitePawn; case 'R': return pieces_1.default.WhiteRook; case 'r': return pieces_1.default.BlackRook; case 'q': return pieces_1.default.BlackQueen; case 'Q': return pieces_1.default.WhiteQueen; default: throw new Error(`unknown FEN value: '${fenValue}'`); } } for (let char of position) { if (char == "/") continue; const digit = isDigit(char); if (digit != null) { for (let eX = 0; eX < digit; eX++) { const square = index + eX; boardPosition_1.BoardPosition.setEmpty(boardPosition, square); } index += digit; } else { let piece = fenValueToPiece(char); boardPosition_1.BoardPosition.setPiece(boardPosition, index, piece); index += 1; } } } function parseColourToMove(colourStr) { switch (colourStr) { case "w": return colour_1.Colours.white; case "b": return colour_1.Colours.black; default: throw new Error("invalid fen"); } } exports.FEN = { writeFEN(board) { const stringBuilder = new stringBuilder_1.StringBuilder(); writeText(stringBuilder, writeFENPosition(board.position)); writeSpace(stringBuilder); writeColour(stringBuilder, board.toMove); writeSpace(stringBuilder); writeCastling(stringBuilder, board.castling); writeSpace(stringBuilder); writeEnPassant(stringBuilder, board.enPassant); writeSpace(stringBuilder); writeNumber(stringBuilder, board.halfMoveNumber); writeSpace(stringBuilder); writeNumber(stringBuilder, board.fullMoveCounter); return stringBuilder.build(); }, regExp: new RegExp(/([rnbqkRQNBKPp12345678/]+) ([wb]) ([KQkq-]+) (.+) (\d+) (\d+)/), loadFEN(fen, board) { const match = this.regExp.exec(fen); if (match == null) throw new Error("invalid fen"); parseFENPosition(match[1], board.position); board.toMove = parseColourToMove(match[2]); board.castling = parseCastlingData(match[3]); board.enPassant = parseEnPassant(match[4]); board.halfMoveNumber = parseHalfMoveCounter(match[5]); board.fullMoveCounter = parseFullMoveCounter(match[6]); } };