chlss
Version:
Open-Source Chess Engine in TypeScript.
206 lines (205 loc) • 7.18 kB
JavaScript
;
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]);
}
};