declare class Bishop extends Piece {
    constructor(colour: Colour);
    get maximumMoves(): Moves;
}

declare type Board = Row[];

declare type CastlingRights = {
    w: PlayerCastlingRights;
    b: PlayerCastlingRights;
};

export declare class Chess {
    #private;
    history: ChessHistory;
    board: Chessboard;
    players: Players;
    activePlayer: Player;
    isGameInPlay: boolean;
    result?: Result;
    /**
     * @throws {TypeError} If invalid FEN given or PGN contains invalid move
     */
    constructor(startingState?: string, { isPGN }?: {
        isPGN: boolean;
    });
    get halfMoves(): number;
    get fullMoves(): number;
    get castlingRights(): CastlingRights;
    playMove(move: string | MoveCoordinates): [Error | null, string];
    toPreviousPosition(): Chess;
    toNextPosition(): Chess;
    toNthPosition(n: number): Chess;
    toPGN({ movesOnly }?: {
        movesOnly: boolean;
    }): string;
    toFEN(): string;
}

declare class Chessboard {
    #private;
    board: Board;
    enPassant: Coordinate | null;
    constructor(FENPosition: string, castlingRights?: CastlingRights, enPassantTarget?: Coordinate | null);
    getValidMoves({ rank, file, isCapture, isForFindingChecks, }: {
        rank: number;
        file: number;
        isCapture?: boolean;
        isForFindingChecks?: boolean;
    }): Move[] | null;
    isSquareInCheck(activeColour: Colour, targetRank: number, targetFile: number): boolean;
    isKingInCheck(colour: Colour): boolean;
    canPlayContinue(activeColour: Colour): [boolean, 'checkmate' | 'stalemate' | undefined];
    move({ from, to, promoteTo, }: {
        from: Move;
        to: Move;
        promoteTo?: PromotionPieceLetter;
    }): void;
    simulateMove(moveInfo: {
        from: Move;
        to: Move;
    }): Chessboard;
    flip(): void;
}

declare class ChessHistory {
    #private;
    constructor(FENState: string);
    get length(): number;
    get currentState(): HistoryState;
    get currentFEN(): string;
    getState(index: number): HistoryState;
    toNthState(n: number): HistoryState;
    toPreviousState(): HistoryState;
    toNextState(): HistoryState;
    record(move: string, toSerialise: HistorySegments, result?: Result): void;
    isThreefoldRepetition(): boolean;
    toPGN(movesOnly: boolean): string;
}

declare type Colour = 'w' | 'b';

declare type Coordinate = [number, number];

declare type FENSegmentsWithoutPosition = [
Colour,
CastlingRights,
enPassantTarget: Coordinate | null,
halfMoves: number,
fullMoves: number
];

declare type HistorySegments = [Board, ...FENSegmentsWithoutPosition];

declare type HistoryState = {
    board: Board;
    activeColour: Colour;
    castlingRights: CastlingRights;
    enPassantTarget: Coordinate | null;
    halfMoves: number;
    fullMoves: number;
};

declare class King extends Piece {
    hasMoved: boolean;
    constructor(colour: Colour);
    get maximumMoves(): Moves;
}

declare class Knight extends Piece {
    constructor(colour: Colour);
    get maximumMoves(): Moves;
}

declare type Move = [number, number];

declare type MoveCoordinates = {
    from: string;
    to: string;
};

declare type Moves = SameDirectionMoves[];

declare class Pawn extends Piece {
    #private;
    hasMoved: boolean;
    constructor(colour: Colour);
    get maximumMoves(): Moves;
}

/**
 * Abstract class instead of interface
 * `instanceof Piece` required in Board valid move checks
 */
declare abstract class Piece {
    letter: PieceLetter;
    colour: Colour;
    constructor(letter: PieceLetter, colour: Colour);
    abstract get maximumMoves(): Moves;
}

declare type PieceLetter = 'P' | 'N' | 'B' | 'R' | 'Q' | 'K' | 'p' | 'n' | 'b' | 'r' | 'q' | 'k';

declare class Player {
    #private;
    colour: Colour;
    castlingRights: PlayerCastlingRights;
    constructor(colour: Colour, castlingRights: PlayerCastlingRights, board: Chessboard);
    move(destination: string): [false] | [boolean, boolean, Coordinate | null, boolean];
}

declare type PlayerCastlingRights = {
    short: boolean;
    long: boolean;
};

declare type Players = {
    w: Player;
    b: Player;
};

declare type PromotionPieceLetter = Exclude<PieceLetter, 'P' | 'p' | 'K' | 'k'>;

declare class Queen extends Piece {
    constructor(colour: Colour);
    get maximumMoves(): Moves;
}

declare type Result = '1-0' | '0-1' | '1/2-1/2';

declare class Rook extends Piece {
    hasMoved: boolean;
    constructor(colour: Colour);
    get maximumMoves(): Moves;
}

declare type Row = Square[];

declare type SameDirectionMoves = Move[];

declare type Square = Pawn | Knight | Bishop | Rook | Queen | King | null;

export { }
