diff --git a/package.json b/package.json index cf2a6be..77ca1b1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "chessops", - "version": "0.8.1-pstrat3.1", + "version": "0.8.1-pstrat3.2", "description": "Chess and chess variant rules and operations", "keywords": [ "chess", diff --git a/src/compat.ts b/src/compat.ts index cda5808..1c98d85 100644 --- a/src/compat.ts +++ b/src/compat.ts @@ -57,6 +57,7 @@ export function lichessVariantRules( | 'fromPosition' | 'kingOfTheHill' | 'threeCheck' + | 'fiveCheck' | 'atomic' | 'horde' | 'racingKings' @@ -72,6 +73,8 @@ export function lichessVariantRules( return 'chess'; case 'threeCheck': return '3check'; + case 'fiveCheck': + return '5check'; case 'kingOfTheHill': return 'kingofthehill'; case 'racingKings': diff --git a/src/fen.ts b/src/fen.ts index 8711ebe..a4b2ff9 100644 --- a/src/fen.ts +++ b/src/fen.ts @@ -115,13 +115,13 @@ export function parseRemainingChecks(part: string): Result 3 || !defined(black) || black > 3) + if (!defined(white) || white > 5 || !defined(black) || black > 5) return Result.err(new FenError(InvalidFen.RemainingChecks)); - return Result.ok(new RemainingChecks(3 - white, 3 - black)); + return Result.ok(new RemainingChecks(5 - white, 5 - black)); //Old notation counting down, not used in games, therefore using highest check mode 5 } else if (parts.length === 2) { const white = parseSmallUint(parts[0]); const black = parseSmallUint(parts[1]); - if (!defined(white) || white > 3 || !defined(black) || black > 3) + if (!defined(white) || white > 5 || !defined(black) || black > 5) return Result.err(new FenError(InvalidFen.RemainingChecks)); return Result.ok(new RemainingChecks(white, black)); } else return Result.err(new FenError(InvalidFen.RemainingChecks)); diff --git a/src/setup.ts b/src/setup.ts index dabff85..5955aaa 100644 --- a/src/setup.ts +++ b/src/setup.ts @@ -174,6 +174,10 @@ export class RemainingChecks { return new RemainingChecks(3, 3); } + static fiveCheck(): RemainingChecks { + return new RemainingChecks(5, 5); + } + clone(): RemainingChecks { return new RemainingChecks(this.white, this.black); } diff --git a/src/types.ts b/src/types.ts index 63b94cd..4e53c1e 100644 --- a/src/types.ts +++ b/src/types.ts @@ -111,6 +111,7 @@ export const RULES = [ 'antichess', 'kingofthehill', '3check', + '5check', 'atomic', 'horde', 'racingkings', diff --git a/src/variant.ts b/src/variant.ts index 5d35ee5..555bec3 100644 --- a/src/variant.ts +++ b/src/variant.ts @@ -346,6 +346,46 @@ export class ThreeCheck extends Chess { } } +export class FiveCheck extends Chess { + protected constructor() { + super('5check'); + } + + static default(): FiveCheck { + const pos = super.default(); + pos.remainingChecks = RemainingChecks.fiveCheck(); + return pos; + } + + static fromSetup(setup: Setup): Result { + return super.fromSetup(setup).map(pos => { + pos.remainingChecks = setup.remainingChecks ? setup.remainingChecks.clone() : RemainingChecks.fiveCheck(); + return pos; + }); + } + + clone(): FiveCheck { + return super.clone() as FiveCheck; + } + + hasInsufficientMaterial(color: Color): boolean { + return this.board.pieces(color, 'k-piece').equals(this.board[color]); + } + + isVariantEnd(): boolean { + return !!this.remainingChecks && (this.remainingChecks.white <= 0 || this.remainingChecks.black <= 0); + } + + variantOutcome(_ctx?: Context): Outcome | undefined { + if (this.remainingChecks) { + for (const color of COLORS) { + if (this.remainingChecks[color] <= 0) return { winner: color }; + } + } + return; + } +} + class RacingKings extends Chess { protected constructor() { super('racingkings'); @@ -618,6 +658,8 @@ export function defaultPosition(rules: Rules): Position { return KingOfTheHill.default(); case '3check': return ThreeCheck.default(); + case '5check': + return FiveCheck.default(); case 'crazyhouse': return Crazyhouse.default(); case 'linesofaction': @@ -645,6 +687,8 @@ export function setupPosition(rules: Rules, setup: Setup): Result