import { Board, Color, Move, Square } from './index'; import { PovScore } from './engine'; import { Arrow } from './svg'; /** * A minimal implementation of Python's `typing.TextIO` class interface. * Only the methods used internally by `pgn.ts` are implemented. */ export declare class StringIO { private buffer; constructor(s?: string); write(str: string): void; read(): string; readline(): string; } /** ========== Direct transpilation ========== */ export declare const LOGGER: { info: (message: string) => void; error: (message: string) => void; }; export declare const NAG_NULL = 0; /** A good move. Can also be indicated by ``!`` in PGN notation. */ export declare const NAG_GOOD_MOVE = 1; /** A mistake. Can also be indicated by ``?`` in PGN notation. */ export declare const NAG_MISTAKE = 2; /** A brilliant move. Can also be indicated by ``!!`` in PGN notation. */ export declare const NAG_BRILLIANT_MOVE = 3; /** A blunder. Can also be indicated by ``??`` in PGN notation. */ export declare const NAG_BLUNDER = 4; /** A speculative move. Can also be indicated by ``!?`` in PGN notation. */ export declare const NAG_SPECULATIVE_MOVE = 5; /** A dubious move. Can also be indicated by ``?!`` in PGN notation. */ export declare const NAG_DUBIOUS_MOVE = 6; export declare const NAG_FORCED_MOVE = 7; export declare const NAG_SINGULAR_MOVE = 8; export declare const NAG_WORST_MOVE = 9; export declare const NAG_DRAWISH_POSITION = 10; export declare const NAG_QUIET_POSITION = 11; export declare const NAG_ACTIVE_POSITION = 12; export declare const NAG_UNCLEAR_POSITION = 13; export declare const NAG_WHITE_SLIGHT_ADVANTAGE = 14; export declare const NAG_BLACK_SLIGHT_ADVANTAGE = 15; export declare const NAG_WHITE_MODERATE_ADVANTAGE = 16; export declare const NAG_BLACK_MODERATE_ADVANTAGE = 17; export declare const NAG_WHITE_DECISIVE_ADVANTAGE = 18; export declare const NAG_BLACK_DECISIVE_ADVANTAGE = 19; export declare const NAG_WHITE_ZUGZWANG = 22; export declare const NAG_BLACK_ZUGZWANG = 23; export declare const NAG_WHITE_MODERATE_COUNTERPLAY = 132; export declare const NAG_BLACK_MODERATE_COUNTERPLAY = 133; export declare const NAG_WHITE_DECISIVE_COUNTERPLAY = 134; export declare const NAG_BLACK_DECISIVE_COUNTERPLAY = 135; export declare const NAG_WHITE_MODERATE_TIME_PRESSURE = 136; export declare const NAG_BLACK_MODERATE_TIME_PRESSURE = 137; export declare const NAG_WHITE_SEVERE_TIME_PRESSURE = 138; export declare const NAG_BLACK_SEVERE_TIME_PRESSURE = 139; export declare const NAG_NOVELTY = 146; export declare const TAG_REGEX: RegExp; export declare const TAG_NAME_REGEX: RegExp; export declare const MOVETEXT_REGEX: RegExp; export declare const SKIP_MOVETEXT_REGEX: RegExp; export declare const CLOCK_REGEX: RegExp; export declare const EMT_REGEX: RegExp; export declare const EVAL_REGEX: RegExp; export declare const ARROWS_REGEX: RegExp; export declare const _condenseAffix: (infix: string) => (substring: string, ...args: any[]) => string; export declare const TAG_ROSTER: string[]; export declare enum SkipType { SKIP = 0 } export declare const SKIP: SkipType; export declare enum TimeControlType { UNKNOW = 0, UNLIMITED = 1, STANDARD = 2, RAPID = 3, BLITZ = 4, BULLET = 5 } export declare class TimeControlPart { moves: number; time: number; increment: number; delay: number; constructor(moves?: number, time?: number, increment?: number, delay?: number); } /** * PGN TimeControl Parser * Spec: http://www.saremba.de/chessgml/standards/pgn/pgn-complete.htm#c9.6 * * Not Yet Implemented: * - Hourglass/Sandclock ('*' prefix) * - Differentiating between Bronstein and Simple Delay (Not part of the PGN Spec) * - More Info: https://en.wikipedia.org/wiki/Chess_clock#Timing_methods */ export declare class TimeControl { parts: TimeControlPart[]; type: TimeControlType; constructor(parts?: TimeControlPart[], type?: TimeControlType); } export declare class _AcceptFrame { state: string; node: ChildNode; isVariation: boolean; variations: Iterator; inVariation: boolean; constructor(node: ChildNode, { isVariation, sidelines, }?: { isVariation?: boolean; sidelines?: boolean; }); } export declare abstract class GameNode { /** The parent node or `null` if this is the root node of the game. */ parent: GameNode | null; /** * The move leading to this node or `null` if this is the root node of the * game. */ move: Move | null; /** A list of child nodes. */ variations: ChildNode[]; /** * A comment that goes behind the move leading to this node. Comments * that occur before any moves are assigned to the root node. */ comment: string; startingComment: string; nags: Set; constructor({ comment }?: { comment?: string; }); /** * Gets a board with the position of the node. * * For the root node, this is the default starting position (for the * ``Variant``) unless the ``FEN`` header tag is set. * * It's a copy, so modifying the board will not alter the game. * * Complexity is `O(n)`. */ abstract board(): Board; /** * Returns the number of half-moves up to this node, as indicated by * fullmove number and turn of the position. * See :func:`Board.ply()`. * * Usually this is equal to the number of parent nodes, but it may be * more if the game was started from a custom position. * * Complexity is `O(n)`. */ abstract ply(): number; /** * Gets the color to move at this node. See :data:`Board.turn`. * * Complexity is `O(n)`. */ turn(): Color; root(): GameNode; /** * Gets the root node, i.e., the game. * * Complexity is `O(n)`. */ game(): Game; /** * Follows the main variation to the end and returns the last node. * * Complexity is `O(n)`. */ end(): GameNode; /** * Checks if this node is the last node in the current variation. * * Complexity is `O(1)`. */ isEnd(): boolean; /** * Checks if this node starts a variation (and can thus have a starting * comment). The root node does not start a variation and can have no * starting comment. * * For example, in ``1. e4 e5 (1... c5 2. Nf3) 2. Nf3``, the node holding * 1... c5 starts a variation. * * Complexity is `O(1)`. */ startsVariation(): boolean; /** * Checks if the node is in the mainline of the game. * * Complexity is `O(n)`. */ isMainline(): boolean; /** * Checks if this node is the first variation from the point of view of its * parent. The root node is also in the main variation. * * Complexity is `O(1)`. */ isMainVariation(): boolean; getitem(move: number | Move | GameNode): ChildNode; includes(move: number | Move | GameNode): boolean; /** * Gets a child node by either the move or the variation index. */ variation(move: number | Move | GameNode): ChildNode; /** Checks if this node has the given variation. */ hasVariation(move: number | Move | GameNode): boolean; /** Promotes the given *move* to the main variation. */ promoteToMain(move: number | Move | GameNode): void; /** Moves a variation one up in the list of variations. */ promote(move: number | Move | GameNode): void; /** * Moves a variation one down in the list of variations. */ demote(move: number | Move | GameNode): void; /** * Removes a variation. */ removeVariation(move: number | Move | GameNode): void; /** * Creates a child node with the given attributes. */ addVariation(move: Move, { comment, startingComment, nags, }?: { comment?: string; startingComment?: string; nags?: Iterable; }): ChildNode; /** * Creates a child node with the given attributes and promotes it to the * main variation. */ addMainVariation(move: Move, { comment, nags, }?: { comment?: string; nags?: Iterable; }): ChildNode; /** * Returns the first node of the mainline after this node, or ``null`` if * this node does not have any children. * * Complexity is `O(1)`. */ next(): ChildNode | null; /** * Returns an iterable over the mainline starting after this node. */ mainline(): Mainline; /** * Returns an iterable over the main moves after this node. */ mainlineMoves(): Mainline; /** * Creates a sequence of child nodes for the given list of moves. * Adds *comment* and *nags* to the last node of the line and returns it. */ addLine(moves: Iterable, { comment, startingComment, nags, }?: { comment?: string; startingComment?: string; nags?: Iterable; }): GameNode; /** * Parses the first valid ``[%eval ...]`` annotation in the comment of * this node, if any. * * Complexity is `O(n)`. */ eval(): PovScore | null; /** * Parses the first valid ``[%eval ...]`` annotation in the comment of * this node and returns the corresponding depth, if any. * * Complexity is `O(1)`. */ evalDepth(): number | null; /** * Replaces the first valid `[%eval ...]` annotation in the comment of * this node or adds a new one. */ setEval(score: PovScore | null, depth?: number | null): void; /** * Parses all ``[%csl ...]`` and ``[%cal ...]`` annotations in the comment * of this node. * * Returns a list of :class:`arrows `. */ arrows(): Arrow[]; /** * Replaces all valid ``[%csl ...]`` and ``[%cal ...]`` annotations in * the comment of this node or adds new ones. */ setArrows(arrows: Iterable): void; /** * Parses the first valid ``[%clk ...]`` annotation in the comment of * this node, if any. * * Returns the player's remaining time to the next time control after this * move, in seconds. */ clock(): number | null; /** * Replaces the first valid ``[%clk ...]`` annotation in the comment of * this node or adds a new one. */ setClock(seconds: number | null): void; /** * Parses the first valid ``[%emt ...]`` annotation in the comment of * this node, if any. * * Returns the player's elapsed move time use for the comment of this * move, in seconds. */ emt(): number | null; /** * Replaces the first valid ``[%emt ...]`` annotation in the comment of * this node or adds a new one. */ setEmt(seconds: number | null): void; /** * Traverses game nodes in PGN order using the given `visitor`. Starts with * the move leading to this node. Returns the `visitor` result. */ abstract accept(visitor: BaseVisitor): ResultT; /** * Traverses headers and game nodes in PGN order, as if the game was * starting after this node. Returns the *visitor* result. */ acceptSubgame(visitor: BaseVisitor): ResultT; toString(): string; } /** * A child node of a game, with the move leading to it. * Extends :class:`~pgn.GameNode`. */ export declare class ChildNode extends GameNode { /** The parent node. */ parent: GameNode; /** The move leading to this node. */ move: Move; /** * A comment for the start of a variation. Only nodes that * actually start a variation (:func:`~pgn.GameNode.startsVariation()` * checks this) can have a starting comment. The root node can not have * a starting comment. */ startingComment: string; /** * A set of NAGs as integers. NAGs always go behind a move, so the root * node of the game will never have NAGs. */ nags: Set; constructor(parent: GameNode, move: Move, { comment, startingComment, nags, }?: { comment?: string; startingComment?: string; nags?: Iterable; }); board(): Board; ply(): number; /** * Gets the standard algebraic notation of the move leading to this node. * See :func:`Board.san()`. * * Do not call this on the root node. * * Complexity is `O(n)`. */ san(): string; /** * Gets the UCI notation of the move leading to this node. * See :func:`Board.uci()`. * * Do not call this on the root node. * * Complexity is `O(n)`. */ uci({ chess960 }?: { chess960?: boolean | null; }): string; /** * Follows the main variation to the end and returns the last node. * * Complexity is `O(n)`. */ end(): ChildNode; _acceptNode(parentBoard: Board, visitor: BaseVisitor): void; _accept(parentBoard: Board, visitor: BaseVisitor, { sidelines }?: { sidelines?: boolean; }): void; accept(visitor: BaseVisitor): ResultT; toRepr(): string; } /** * The root node of a game with extra information such as headers and the * starting position. Extends :class:`~pgn.GameNode`. */ export declare class Game extends GameNode { /** * A mapping of headers. By default, the following 7 headers are provided * (Seven Tag Roster): * * >>> import pgn * >>> * >>> game = pgn.Game() * >>> game.headers * Headers(Event='?', Site='?', Date='????.??.??', Round='?', White='?', Black='?', Result='*') */ headers: Headers; /** * A list of errors (such as illegal or ambiguous moves) encountered while * parsing the game. */ errors: Error[]; constructor(headers?: Map | Iterable<[string, string]> | null); board(): Board; ply(): number; /** * Sets up a specific starting position. This sets (or resets) the * ``FEN``, ``SetUp``, and ``Variant`` header tags. */ setup(board: Board | string): void; /** * Traverses the game in PGN order using the given *visitor*. Returns * the *visitor* result. */ accept(visitor: BaseVisitor): ResultT; /** * Returns the time control of the game. If the game has no time control * information, the default time control ('UNKNOWN') is returned. */ timeControl(): TimeControl; /** * Creates a game from the move stack of a :class:`~Board()`. */ static fromBoard(this: T, board: Board): InstanceType; /** * Creates an empty game without the default Seven Tag Roster. */ static withoutTagRoster(this: T): InstanceType; static builder(this: GameT): GameBuilder; toRepr(): string; } export declare class Headers { _tagRoster: Map; _others: Map; constructor(data?: Map | Iterable<[string, string]> | null, { kwargs }?: { kwargs: Map; }); isChess960(): boolean; isWild(): boolean; variant(): typeof Board; board(): Board; set(key: string, value: string): void; get(key: string): string | undefined; delitem(key: string): boolean; iter(): IterableIterator; length(): number; copy(): this; toRepr(): string; toString(): string; static builder(this: HeadersT): HeadersBuilder; keys(): IterableIterator; values(): IterableIterator; items(): IterableIterator<[string, string]>; [Symbol.iterator](): IterableIterator; includes(key: string): boolean; pop(key: string): string | undefined; } export declare class Mainline { start: GameNode; f: (node: ChildNode) => MainlineMapT; constructor(start: GameNode, f: (node: ChildNode) => MainlineMapT); bool(): boolean; iter(): IterableIterator; [Symbol.iterator](): IterableIterator; reversed(): IterableIterator; accept(visitor: BaseVisitor): ResultT; toString(): string; toRepr(): string; } /** * Base class for visitors. * * Use with :func:`pgn.Game.accept()` or * :func:`pgn.GameNode.accept()` or :func:`pgn.readGame()`. * * The methods are called in PGN order. */ export declare abstract class BaseVisitor { /** * Called at the start of a game. */ beginGame(): SkipType | void; /** * Called before visiting game headers. */ beginHeaders(): Headers | void; /** * Called for each game header. */ visitHeader(tagname: string, tagvalue: string): void; /** * Called after visiting game headers. */ endHeaders(): SkipType | void; /** * When the visitor is used by a parser, this is called at the start of * each standard algebraic notation detailing a move. */ beginParseSan(board: Board, san: string): SkipType | void; /** * When the visitor is used by a parser, this is called to parse a move * in standard algebraic notation. * * You can override the default implementation to work around specific * quirks of your input format. * * .. deprecated:: 1.1 * This method is very limited, because it is only called on moves * that the parser recognizes in the first place. Instead of adding * workarounds here, please report common quirks so that * they can be handled for everyone. */ parseSan(board: Board, san: string): Move; /** * Called for each move. * * *board* is the board state before the move. The board state must be * restored before the traversal continues. */ visitMove(board: Board, move: Move): void; /** * Called for the starting position of the game and after each move. * * The board state must be restored before the traversal continues. */ visitBoard(board: Board): void; /** * Called for each comment. */ visitComment(comment: string): void; /** * Called for each NAG. */ visitNag(nag: number): void; /** * Called at the start of a new variation. It is not called for the * mainline of the game. */ beginVariation(): SkipType | void; /** * Concludes a variation. */ endVariation(): void; /** * Called at the end of a game with the value from the ``Result`` header. */ visitResult(result: string): void; /** * Called at the end of a game. */ endGame(): void; /** * Called to get the result of the visitor. */ abstract result(): ResultT; /** * Called for encountered errors. Defaults to raising an exception. */ handleError(error: Error): void; } /** * Creates a game model. Default visitor for :func:`~pgn.readGame()`. */ export declare class GameBuilder extends BaseVisitor { Game_: typeof Game; game: Game; variationStack: GameNode[]; startingComment: string; inVariation: boolean; constructor(); constructor({ Game_ }: { Game_: typeof Game; }); beginGame(): void; beginHeaders(): Headers; visitHeader(tagname: string, tagvalue: string): void; visitNag(nag: number): void; beginVariation(): void; endVariation(): void; visitResult(result: string): void; visitComment(comment: string): void; visitMove(board: Board, move: Move): void; /** * Populates :data:`pgn.Game.errors` with encountered errors and * logs them. * * You can silence the log and handle errors yourself after parsing: * * >>> import pgn * >>> import logging * >>> * >>> logging.getLogger("pgn").setLevel(logging.CRITICAL) * >>> * >>> pgn = open("data/pgn/kasparov-deep-blue-1997.pgn") * >>> * >>> game = pgn.readGame(pgn) * >>> game.errors // List of exceptions * [] * * You can also override this method to hook into error handling: * * >>> import pgn * >>> * >>> class MyGameBuilder(pgn.GameBuilder): * >>> def handleError(this, error: Exception) -> null: * >>> pass // Ignore error * >>> * >>> pgn = open("data/pgn/kasparov-deep-blue-1997.pgn") * >>> * >>> game = pgn.readGame(pgn, Visitor=MyGameBuilder) */ handleError(error: Error): void; /** * Returns the visited :class:`~pgn.Game()`. */ result(): Game; } /** * Collects headers into a dictionary. */ export declare class HeadersBuilder extends BaseVisitor { Headers_: typeof Headers; headers: Headers; constructor(); constructor({ Headers_ }: { Headers_: typeof Headers; }); beginHeaders(): Headers; visitHeader(tagname: string, tagvalue: string): void; endHeaders(): SkipType; result(): Headers; } /** * Returns the final position of the game. The mainline of the game is * on the move stack. */ export declare class BoardBuilder extends BaseVisitor { skipVariationDepth: number; board: Board; beginGame(): void; beginVariation(): SkipType; endVariation(): void; visitBoard(board: Board): void; result(): Board; } /** * Skips a game. */ export declare class SkipVisitor extends BaseVisitor { beginGame(): SkipType; endHeaders(): SkipType; beginVariation(): SkipType; result(): true; } export declare abstract class StringExporterMixin extends BaseVisitor { columns: number | null; headers: boolean; comments: boolean; variations: boolean; foundHeaders: boolean; forceMovenumber: boolean; lines: string[]; currentLine: string; variationDepth: number; constructor({ columns, headers, comments, variations, }?: { columns?: number | null; headers?: boolean; comments?: boolean; variations?: boolean; }); flushCurrentLine(): void; writeToken(token: string): void; writeLine(line?: string): void; endGame(): void; beginHeaders(): void; visitHeader(tagname: string, tagvalue: string): void; endHeaders(): void; beginVariation(): SkipType | void; endVariation(): void; visitComment(comment: string): void; visitNag(nag: number): void; visitMove(board: Board, move: Move): void; visitResult(result: string): void; } /** * Allows exporting a game as a string. * * >>> import pgn * >>> * >>> game = pgn.Game() * >>> * >>> exporter = pgn.StringExporter(headers=true, variations=true, comments=true) * >>> pgnString = game.accept(exporter) * * Only *columns* characters are written per line. If *columns* is ``null``, * then the entire movetext will be on a single line. This does not affect * header tags and comments. * * There will be no newline characters at the end of the string. */ export declare class StringExporter extends StringExporterMixin { constructor({ columns, headers, comments, variations, }?: { columns?: number | null; headers?: boolean; comments?: boolean; variations?: boolean; }); result(): string; toString(): string; } export declare function readGame(handle: StringIO): Game | null; export declare function readGame(handle: StringIO, { Visitor }: { Visitor?: typeof BaseVisitor; }): ResultT | null; /** * Reads game headers from a PGN file opened in text mode. Skips the rest of * the game. * * Since actually parsing many games from a big file is relatively expensive, * this is a better way to look only for specific games and then seek and * parse them later. * * This example scans for the first game with Kasparov as the white player. * * >>> import pgn * >>> * >>> pgn = open("data/pgn/kasparov-deep-blue-1997.pgn") * >>> * >>> kasparovOffsets = [] * >>> * >>> while true: * ... offset = pgn.tell() * ... * ... headers = pgn.readHeaders(pgn) * ... if headers is null: * ... break * ... * ... if "Kasparov" in headers.get("White", "?"): * ... kasparovOffsets.append(offset) * * Then it can later be seeked and parsed. * * >>> for offset in kasparovOffsets: * ... pgn.seek(offset) * ... pgn.readGame(pgn) // doctest: +ELLIPSIS * 0 * * 1436 * * 3067 * */ export declare const readHeaders: (handle: StringIO) => Headers | null; /** * Skips a game. Returns ``true`` if a game was found and skipped. */ export declare const skipGame: (handle: StringIO) => boolean; export declare const parseTimeControl: (timeControl: string) => TimeControl; declare const _default: { LOGGER: { info: (message: string) => void; error: (message: string) => void; }; NAG_NULL: number; NAG_GOOD_MOVE: number; NAG_MISTAKE: number; NAG_BRILLIANT_MOVE: number; NAG_BLUNDER: number; NAG_SPECULATIVE_MOVE: number; NAG_DUBIOUS_MOVE: number; NAG_FORCED_MOVE: number; NAG_SINGULAR_MOVE: number; NAG_WORST_MOVE: number; NAG_DRAWISH_POSITION: number; NAG_QUIET_POSITION: number; NAG_ACTIVE_POSITION: number; NAG_UNCLEAR_POSITION: number; NAG_WHITE_SLIGHT_ADVANTAGE: number; NAG_BLACK_SLIGHT_ADVANTAGE: number; NAG_WHITE_MODERATE_ADVANTAGE: number; NAG_BLACK_MODERATE_ADVANTAGE: number; NAG_WHITE_DECISIVE_ADVANTAGE: number; NAG_BLACK_DECISIVE_ADVANTAGE: number; NAG_WHITE_ZUGZWANG: number; NAG_BLACK_ZUGZWANG: number; NAG_WHITE_MODERATE_COUNTERPLAY: number; NAG_BLACK_MODERATE_COUNTERPLAY: number; NAG_WHITE_DECISIVE_COUNTERPLAY: number; NAG_BLACK_DECISIVE_COUNTERPLAY: number; NAG_WHITE_MODERATE_TIME_PRESSURE: number; NAG_BLACK_MODERATE_TIME_PRESSURE: number; NAG_WHITE_SEVERE_TIME_PRESSURE: number; NAG_BLACK_SEVERE_TIME_PRESSURE: number; NAG_NOVELTY: number; TAG_REGEX: RegExp; TAG_NAME_REGEX: RegExp; MOVETEXT_REGEX: RegExp; SKIP_MOVETEXT_REGEX: RegExp; CLOCK_REGEX: RegExp; EMT_REGEX: RegExp; EVAL_REGEX: RegExp; ARROWS_REGEX: RegExp; _condenseAffix: (infix: string) => (substring: string, ...args: any[]) => string; TAG_ROSTER: string[]; SkipType: typeof SkipType; SKIP: SkipType; TimeControlType: typeof TimeControlType; TimeControlPart: typeof TimeControlPart; TimeControl: typeof TimeControl; _AcceptFrame: typeof _AcceptFrame; GameNode: typeof GameNode; ChildNode: typeof ChildNode; Game: typeof Game; Headers: typeof Headers; Mainline: typeof Mainline; BaseVisitor: typeof BaseVisitor; GameBuilder: typeof GameBuilder; HeadersBuilder: typeof HeadersBuilder; BoardBuilder: typeof BoardBuilder; SkipVisitor: typeof SkipVisitor; StringExporterMixin: typeof StringExporterMixin; StringExporter: typeof StringExporter; readGame: typeof readGame; readHeaders: (handle: StringIO) => Headers | null; skipGame: (handle: StringIO) => boolean; parseTimeControl: (timeControl: string) => TimeControl; }; export default _default; //# sourceMappingURL=pgn.d.ts.map