import type { Color, EnemyColor, FriendlyPiece, Graph, Index, Indices, MaybePiece, ParsedGame, ParsedMove, Piece, PieceColor, Position, PositionIndex, Positions, Unoccupied } from './base'; import type { ParseFen, ParseSan, ParseSans, ToPositions, ToSans } from './notation'; import type { Increment } from './utils'; import type { BishopMoves } from './pieces/bishop'; import type { KingMoves } from './pieces/king'; import type { KnightMoves } from './pieces/knight'; import type { PawnMoves } from './pieces/pawn'; import type { QueenMoves } from './pieces/queen'; import type { RookMoves } from './pieces/rook'; /** * Apply moves to a game, regardless of turn or legality */ export type ApplyMoveUnsafe = _ApplyMoveUnsafe>; export type _ApplyMoveUnsafe = _ApplyMovePiece extends infer P extends Piece ? { board: _UpdateBoard; turn: EnemyColor>; halfmove: _CountHalfmove; fullmove: _CountFullmove; castling: _UpdateCastling; ep: _UpdateEnPassant; } : never; type _ApplyMovePiece = Move['castle'] extends 'K' ? 'K' : Move['castle'] extends 'k' ? 'k' : Move['castle'] extends 'Q' ? 'Q' : Move['castle'] extends 'q' ? 'q' : Game['board'][Move['from']] extends infer P extends Piece ? P : false; type _CountHalfmove = P extends 'p' | 'P' ? 0 : Move['castle'] extends false ? Game['board'][Move['to']] extends Piece ? 0 : Increment : Increment; type _CountFullmove = P extends Piece ? PieceColor

extends 'b' ? Increment : Game['fullmove'] : Game['fullmove']; type _UpdateBoard = Move['castle'] extends 'K' ? _ReplaceValues : Move['castle'] extends 'Q' ? _ReplaceValues : Move['castle'] extends 'k' ? _ReplaceValues : Move['castle'] extends 'q' ? _ReplaceValues : Game['ep'] extends Move['to'] ? P extends 'p' ? Graph[Move['to']][1] extends Index ? _ReplaceValues : never : P extends 'P' ? Graph[Move['to']][7] extends Index ? _ReplaceValues : never : _ReplaceValues : _ReplaceValues; type _UpdateCastling = { K: Move['castle'] extends 'K' | 'Q' ? false : Game['castling']['K']; Q: Move['castle'] extends 'K' | 'Q' ? false : Game['castling']['Q']; k: Move['castle'] extends 'k' | 'q' ? false : Game['castling']['k']; q: Move['castle'] extends 'k' | 'q' ? false : Game['castling']['q']; }; type _UpdateEnPassant

= P extends 'p' ? Move['from'] extends 8 ? Move['to'] extends 24 ? 16 : null : Move['from'] extends 9 ? Move['to'] extends 25 ? 17 : null : Move['from'] extends 10 ? Move['to'] extends 26 ? 18 : null : Move['from'] extends 11 ? Move['to'] extends 27 ? 19 : null : Move['from'] extends 12 ? Move['to'] extends 28 ? 20 : null : Move['from'] extends 13 ? Move['to'] extends 29 ? 21 : null : Move['from'] extends 14 ? Move['to'] extends 30 ? 22 : null : Move['from'] extends 15 ? Move['to'] extends 31 ? 23 : null : null : P extends 'P' ? Move['from'] extends 48 ? Move['to'] extends 32 ? 40 : null : Move['from'] extends 49 ? Move['to'] extends 33 ? 41 : null : Move['from'] extends 50 ? Move['to'] extends 34 ? 42 : null : Move['from'] extends 51 ? Move['to'] extends 35 ? 43 : null : Move['from'] extends 52 ? Move['to'] extends 36 ? 44 : null : Move['from'] extends 53 ? Move['to'] extends 37 ? 45 : null : Move['from'] extends 54 ? Move['to'] extends 38 ? 46 : null : Move['from'] extends 55 ? Move['to'] extends 39 ? 47 : null : null : null; export type _ReplaceValues = U extends [infer Head extends [Index, MaybePiece], ...infer Tail extends [Index, MaybePiece][]] ? _ReplaceValues<_ReplaceAt, Tail> : T; export type _ReplaceAt = [ U extends 0 ? V : T[0], U extends 1 ? V : T[1], U extends 2 ? V : T[2], U extends 3 ? V : T[3], U extends 4 ? V : T[4], U extends 5 ? V : T[5], U extends 6 ? V : T[6], U extends 7 ? V : T[7], U extends 8 ? V : T[8], U extends 9 ? V : T[9], U extends 10 ? V : T[10], U extends 11 ? V : T[11], U extends 12 ? V : T[12], U extends 13 ? V : T[13], U extends 14 ? V : T[14], U extends 15 ? V : T[15], U extends 16 ? V : T[16], U extends 17 ? V : T[17], U extends 18 ? V : T[18], U extends 19 ? V : T[19], U extends 20 ? V : T[20], U extends 21 ? V : T[21], U extends 22 ? V : T[22], U extends 23 ? V : T[23], U extends 24 ? V : T[24], U extends 25 ? V : T[25], U extends 26 ? V : T[26], U extends 27 ? V : T[27], U extends 28 ? V : T[28], U extends 29 ? V : T[29], U extends 30 ? V : T[30], U extends 31 ? V : T[31], U extends 32 ? V : T[32], U extends 33 ? V : T[33], U extends 34 ? V : T[34], U extends 35 ? V : T[35], U extends 36 ? V : T[36], U extends 37 ? V : T[37], U extends 38 ? V : T[38], U extends 39 ? V : T[39], U extends 40 ? V : T[40], U extends 41 ? V : T[41], U extends 42 ? V : T[42], U extends 43 ? V : T[43], U extends 44 ? V : T[44], U extends 45 ? V : T[45], U extends 46 ? V : T[46], U extends 47 ? V : T[47], U extends 48 ? V : T[48], U extends 49 ? V : T[49], U extends 50 ? V : T[50], U extends 51 ? V : T[51], U extends 52 ? V : T[52], U extends 53 ? V : T[53], U extends 54 ? V : T[54], U extends 55 ? V : T[55], U extends 56 ? V : T[56], U extends 57 ? V : T[57], U extends 58 ? V : T[58], U extends 59 ? V : T[59], U extends 60 ? V : T[60], U extends 61 ? V : T[61], U extends 62 ? V : T[62], U extends 63 ? V : T[63] ]; /** * Get current legal moves */ export type CurrentMoves = ToSans<_CurrentMoves>; export type _CurrentMoves = _CurrentMovesUnsafe extends infer UnsafeMoves extends ParsedMove[] ? _FilterIllegalMoves : []; type _FilterIllegalMoves = Moves extends [infer Head extends ParsedMove, ...infer Tail extends ParsedMove[]] ? _IsLegal extends true ? _FilterIllegalMoves : _FilterIllegalMoves : Acc; /** * Get all possible moves, even ones that result in self-check **/ export type CurrentMovesUnsafe, Acc extends ParsedMove[] = []> = _CurrentMovesUnsafe extends infer M extends ParsedMove[] ? ToSans : never; type _CurrentMovesUnsafe, Acc extends ParsedMove[] = []> = From extends [infer Head extends Index, ...infer Tail extends Index[]] ? Game['board'][Head] extends infer CurrentPiece extends Piece ? CurrentPiece extends 'p' | 'P' ? _CurrentMovesUnsafe, Head>]> : CurrentPiece extends 'n' | 'N' ? _CurrentMovesUnsafe, Head>]> : CurrentPiece extends 'b' | 'B' ? _CurrentMovesUnsafe, Head>]> : CurrentPiece extends 'r' | 'R' ? _CurrentMovesUnsafe, Head>]> : CurrentPiece extends 'q' | 'Q' ? _CurrentMovesUnsafe, Head>]> : CurrentPiece extends 'k' | 'K' ? _CurrentMovesUnsafe, Head>]> : never : never : Acc; /** * Create a hover-display of the chessboard **/ export type Chessboard = Flipped extends true ? { 1: ` ${_Square} ${_Square} ${_Square} ${_Square} ${_Square} ${_Square} ${_Square} ${_Square} `; 2: ` ${_Square} ${_Square} ${_Square} ${_Square} ${_Square} ${_Square} ${_Square} ${_Square} `; 3: ` ${_Square} ${_Square} ${_Square} ${_Square} ${_Square} ${_Square} ${_Square} ${_Square} `; 4: ` ${_Square} ${_Square} ${_Square} ${_Square} ${_Square} ${_Square} ${_Square} ${_Square} `; 5: ` ${_Square} ${_Square} ${_Square} ${_Square} ${_Square} ${_Square} ${_Square} ${_Square} `; 6: ` ${_Square} ${_Square} ${_Square} ${_Square} ${_Square} ${_Square} ${_Square} ${_Square} `; 7: ` ${_Square} ${_Square} ${_Square} ${_Square} ${_Square} ${_Square} ${_Square} ${_Square} `; 8: ` ${_Square} ${_Square} ${_Square} ${_Square} ${_Square} ${_Square} ${_Square} ${_Square} `; } : { 8: ` ${_Square} ${_Square} ${_Square} ${_Square} ${_Square} ${_Square} ${_Square} ${_Square} `; 7: ` ${_Square} ${_Square} ${_Square} ${_Square} ${_Square} ${_Square} ${_Square} ${_Square} `; 6: ` ${_Square} ${_Square} ${_Square} ${_Square} ${_Square} ${_Square} ${_Square} ${_Square} `; 5: ` ${_Square} ${_Square} ${_Square} ${_Square} ${_Square} ${_Square} ${_Square} ${_Square} `; 4: ` ${_Square} ${_Square} ${_Square} ${_Square} ${_Square} ${_Square} ${_Square} ${_Square} `; 3: ` ${_Square} ${_Square} ${_Square} ${_Square} ${_Square} ${_Square} ${_Square} ${_Square} `; 2: ` ${_Square} ${_Square} ${_Square} ${_Square} ${_Square} ${_Square} ${_Square} ${_Square} `; 1: ` ${_Square} ${_Square} ${_Square} ${_Square} ${_Square} ${_Square} ${_Square} ${_Square} `; }; type _B = '*'; type _W = '-'; type _Square = Game['board'][I] extends infer P extends Piece ? P : Char; /** * Find king by color */ export type FindKing = _FindKing extends infer K extends Index ? Positions[K] : false; type _FindKing = Remaining extends [infer Head extends Index, ...infer Tail extends Index[]] ? Game['board'][Head] extends King ? Head : _FindKing : false; /** * Test if a king is threatened **/ export type IsCheck = _FindKing extends infer KingIndex extends Index ? _IsThreatened> : false; /** * Test if a move is legal */ export type IsLegal = _IsLegal>; type _IsLegal = Move['castle'] extends 'K' ? _HasBoardValues extends true ? Game['castling']['K'] extends true ? _CurrentMovesUnsafe extends infer UnsafeMoves extends ParsedMove[] ? _ContainsReachable extends false ? true : false : never : false : false : Move['castle'] extends 'Q' ? _HasBoardValues extends true ? Game['castling']['Q'] extends true ? _CurrentMovesUnsafe extends infer UnsafeMoves extends ParsedMove[] ? _ContainsReachable extends false ? true : false : never : false : false : Move['castle'] extends 'k' ? _HasBoardValues extends true ? Game['castling']['k'] extends true ? _CurrentMovesUnsafe extends infer UnsafeMoves extends ParsedMove[] ? _ContainsReachable extends false ? true : false : never : false : false : Move['castle'] extends 'q' ? _HasBoardValues extends true ? Game['castling']['q'] extends true ? _CurrentMovesUnsafe extends infer UnsafeMoves extends ParsedMove[] ? _ContainsReachable extends false ? true : false : never : false : false : Game['board'][Move['from']] extends infer P extends Piece ? PieceColor

extends infer C extends Color ? _CurrentMovesUnsafe extends infer UnsafeMoves extends ParsedMove[] ? _ContainsMove extends true ? _ExposesKing extends false ? true : false : false : never : never : false; type _ContainsMove = Acc extends [infer Head extends ParsedMove, ...infer Tail extends ParsedMove[]] ? Head extends T ? true : _ContainsMove : false; type _ContainsReachable = T extends [infer Head extends Index, ...infer Tail extends Index[]] ? _IsReachable extends true ? true : _ContainsReachable : false; type _HasBoardValues = T extends [infer Head extends [Index, MaybePiece], ...infer Tail extends [Index, MaybePiece][]] ? Game['board'][Head[0]] extends Head[1] ? _HasBoardValues : false : true; type _ExposesKing = Game['board'][Move['from']] extends infer P extends Piece ? IsCheck<_ApplyMoveUnsafe, PieceColor

> : false; /** * Test if position is threatened by a hostile color **/ export type IsThreatened, Acc extends Index[] = _OccupiedBy> = _IsThreatened; type _IsThreatened, Acc extends Index[] = _OccupiedBy> = Acc extends [infer PositionHead extends Index, ...infer PositionTail extends Index[]] ? Game['board'][PositionHead] extends FriendlyPiece ? _CurrentMovesUnsafe extends infer PositionMoves extends ParsedMove[] ? _IsReachable extends true ? true : _IsThreatened : false : unknown : false; type _IsReachable = Moves extends [infer Head extends ParsedMove, ...infer Tail extends ParsedMove[]] ? Head['to'] extends Target ? true : _IsReachable : false; /** * Get all positions occupied by a color **/ export type OccupiedBy = ToPositions<_OccupiedBy>; type _OccupiedBy = Remaining extends [infer Head extends Index, ...infer Tail extends Index[]] ? Game['board'][Head] extends FriendlyPiece ? _OccupiedBy : _OccupiedBy : Acc; /** * Play a game */ export type NewGame = Play<'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1', Moves>; export type Play = Game extends infer G extends ParsedGame ? _Play> : Game extends string ? Play, Moves> : never; type _Play = Moves extends [infer Head extends ParsedMove, ...infer Tail extends ParsedMove[]] ? _Play<_ApplyMoveUnsafe, Tail> : Game; export {};