import type { Castling, Color, DirectionIndex, File, Index, ParsedGame, ParsedMove, Piece, Position, PositionIndex, Positions, PromotionPiece, Rank, Unoccupied } from './base'; import type { Includes, Int, IsLength } from './utils'; /** Format parsed game to fen notation */ export type FormatGame>> = `${Board} ${T['turn']} ${FormatCastling} ${T['ep'] extends Index ? Positions[T['ep']] extends infer E extends Position ? E : '-' : '-'} ${T['halfmove']} ${T['fullmove']}`; export type FormatBoard = IsLength extends false ? never : _FormatBoard; type _ImplodeBoard = T extends [infer Head extends string, ...infer Tail extends string[]] ? _ImplodeBoard : Acc; type _FormatBoard = Count extends 8 ? _FormatBoard> : Skip extends 8 ? never : T extends `${infer Head}${infer Tail}` ? Head extends Piece ? _FormatBoard, 0, Rank> : _FormatBoard, _Tick, Rank> : Acc; type _Tick = T extends 0 ? 1 : T extends 1 ? 2 : T extends 2 ? 3 : T extends 3 ? 4 : T extends 4 ? 5 : T extends 5 ? 6 : T extends 6 ? 7 : 8; /** stringify casting rights */ export type FormatCastling = U extends '' ? '-' : U; /** format san */ export type FormatSan = T['castle'] extends 'K' ? 'O-O' : T['castle'] extends 'Q' ? 'O-O-O' : T['castle'] extends 'k' ? 'o-o' : T['castle'] extends 'q' ? 'o-o-o' : `${Positions[T['from']]}${Positions[T['to']]}${T['promotion']}`; /** Normalize fen board string to a 64 character string */ export type ParseBoard = T extends `${infer Head}${infer Rest}` ? Head extends '/' ? ParseBoard : Head extends '1' ? ParseBoard : Head extends '2' ? ParseBoard : Head extends '3' ? ParseBoard : Head extends '4' ? ParseBoard : Head extends '5' ? ParseBoard : Head extends '6' ? ParseBoard : Head extends '7' ? ParseBoard : Head extends '8' ? ParseBoard : Head extends Piece ? ParseBoard : never : Acc['length'] extends 64 ? Acc : never; /** Parse castling rights */ export type ParseCastling = { K: Includes; Q: Includes; k: Includes; q: Includes; }; /** Parse fen string */ export type ParseFen> = U extends ParsedGame ? U['board'] extends never ? never : U['castling'] extends never ? never : U['ep'] extends never ? never : U['halfmove'] extends never ? never : U['fullmove'] extends never ? never : U['turn'] extends never ? never : U : never; export type _ParseFen = T extends `${infer _Board} ${infer _Turn} ${infer _Castling} ${infer _Ep} ${infer Halfmove} ${infer Fullmove}` ? { board: ParseBoard<_Board>; ep: _Ep extends 'a3' | 'b3' | 'c3' | 'd3' | 'e3' | 'f3' | 'g3' | 'h3' | 'a6' | 'b6' | 'c6' | 'd6' | 'e6' | 'f6' | 'g6' | 'h6' ? PositionIndex[_Ep] : _Ep extends '-' ? null : never; halfmove: Int; fullmove: Int; castling: ParseCastling<_Castling>; turn: _Turn extends Color ? _Turn : never; } : never; /** Parse move notation */ export type ParseSan = T extends 'O-O' ? { castle: 'K'; from: 0; to: 0; promotion: ''; } : T extends 'O-O-O' ? { castle: 'Q'; from: 0; to: 0; promotion: ''; } : T extends 'o-o' ? { castle: 'k'; from: 0; to: 0; promotion: ''; } : T extends 'o-o-o' ? { castle: 'q'; from: 0; to: 0; promotion: ''; } : T extends `${infer FromFile extends File}${infer FromRank extends Rank}${infer ToFile extends File}${infer ToRank extends Rank}${infer Promotion extends PromotionPiece | ''}` ? { castle: false; from: PositionIndex[`${FromFile}${FromRank}`]; to: PositionIndex[`${ToFile}${ToRank}`]; promotion: Promotion extends PromotionPiece ? Promotion : ''; } : never; /** * Parse a list of moves */ export type ParseSans = Moves extends [infer Head extends string, ...infer Tail extends string[]] ? ParseSans]> : Acc; /** format tuple of sans */ export type ToSans = T extends [infer U extends ParsedMove, ...infer V extends ParsedMove[]] ? ToSans]> : Acc; /** Map indices to their named position */ export type ToPositions = T extends [infer U extends Index, ...infer V extends Index[]] ? ToPositions : Acc; export {};