diff --git a/__tests__/validate_fen.test.ts b/__tests__/validate_fen.test.ts index 102592e..4c11e1d 100644 --- a/__tests__/validate_fen.test.ts +++ b/__tests__/validate_fen.test.ts @@ -524,13 +524,26 @@ test.each([ expect(validateFen(fen)).toMatchObject({ ok }) }) -test('test non-strict fen validation', () => { +test('non-strict fen validation parameter (FEN with no kings)', () => { const noKingFen = '8/8/8/8/4R3/8/8/8 w - - 0 1' - // chess: Chess(fen, strict) -> Chess - // strict is false will by bypass - // the 4th to 11th checks in validateFen - // most of them are about 8x8 board constraints - // king presence, and en passant rule matching - const chess = new Chess(noKingFen, false) + // chess: Chess(fen, config: {bypass: number[]}) -> Chess + // strict is false will by bypass the 4th to 11th checks in validateFen + + // 1st criterion: 6 space-seperated fields? + // 2nd criterion: move number field is a integer value > 0? + // 3rd criterion: half move counter is an integer >= 0? + // 4th criterion: 4th field is a valid e.p.-string? + // 5th criterion: 3th field is a valid castle-string? + // 6th criterion: 2nd field is "w" (white) or "b" (black)? + // 7th criterion: 1st field contains 8 rows? + // 8th criterion: every row is valid? + // 9th criterion: is en-passant square legal? + // 10th criterion: does chess position contain exact two kings? + // 11th criterion: are any pawns on the first or eighth rows? + + const chess = new Chess(noKingFen, { + // if not strict, we don't need to check the remaining criterions + bypass: [4, 5, 6, 7, 8, 9, 10, 11], + }) expect(chess.fen()).toBe(noKingFen) }) diff --git a/src/chess.ts b/src/chess.ts index 15d3ecc..233beee 100644 --- a/src/chess.ts +++ b/src/chess.ts @@ -52,7 +52,7 @@ export type Square = export const DEFAULT_POSITION = 'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1' -export const DEFAULT_STRICT_FEN = true +export const DEFAULT_STRICT_FEN: number[] = [] export type Piece = { color: Color @@ -293,7 +293,7 @@ function swapColor(color: Color): Color { return color === WHITE ? BLACK : WHITE } -export function validateFen(fen: string, strict?: boolean) { +export function validateFen(fen: string, bypass?: number[]) { let validations = [] const tokens = fen.split(/\s+/) @@ -453,12 +453,8 @@ export function validateFen(fen: string, strict?: boolean) { return { ok: true } }) - if (!strict) { - // if not strict, we don't need to check the remaining criterions - const notStrictCriterions = [4, 5, 6, 7, 8, 9, 10, 11] - validations = validations.filter( - (_, index) => !notStrictCriterions.includes(index + 1) - ) + if (bypass?.length) { + validations = validations.filter((_, index) => !bypass.includes(index + 1)) } for (let i = 0; i < validations.length; i++) { @@ -581,6 +577,10 @@ function strippedSan(move: string) { return move.replace(/=/, '').replace(/[+#]?[?!]*$/, '') } +type Config = { + bypass: number[] +} + export class Chess { private _board = new Array(128) private _turn: Color = WHITE @@ -592,11 +592,15 @@ export class Chess { private _history: History[] = [] private _comments: Record = {} private _castling: Record = { w: 0, b: 0 } - private _strict: boolean + private _bypass: number[] - constructor(fen = DEFAULT_POSITION, strict = DEFAULT_STRICT_FEN) { - this._strict = strict - this.load(fen, false, strict) + constructor( + fen = DEFAULT_POSITION, + config: Config = { bypass: DEFAULT_STRICT_FEN } + ) { + const { bypass } = config + this._bypass = bypass + this.load(fen, false, bypass) } clear(keepHeaders = false) { @@ -610,6 +614,7 @@ export class Chess { this._history = [] this._comments = {} this._header = keepHeaders ? this._header : {} + this._bypass = [] this._updateSetup(this.fen()) } @@ -619,7 +624,7 @@ export class Chess { } } - load(fen: string, keepHeaders = false, strict = true) { + load(fen: string, keepHeaders = false, bypass = DEFAULT_STRICT_FEN) { let tokens = fen.split(/\s+/) // append commonly omitted fen tokens @@ -630,7 +635,7 @@ export class Chess { tokens = fen.split(/\s+/) - const { ok, error } = validateFen(fen, strict) + const { ok, error } = validateFen(fen, bypass) if (!ok) { throw new Error(error) } @@ -799,7 +804,7 @@ export class Chess { } reset() { - this.load(DEFAULT_POSITION, false, this._strict) + this.load(DEFAULT_POSITION, false, this._bypass) } get(square: Square) {