PGN, Notation & Events API Reference
This module covers PGN options, numeric annotation glyphs (NAGs), move metadata, and event-driven movetext streaming.
PgnOptions
libscid.PgnOptions
dataclass
PgnOptions(
symbolic_nags: bool = False,
supplemental_tags: bool = True,
comments: bool = True,
variations: bool = True,
line_width: int | None = None,
)
Configuration options controlling PGN formatting and export serialisation.
Pass an instance of PgnOptions to Game.to_pgn() to customise the output
representation of PGN tags, move annotations, commentary, variations, and
line wrapping.
Attributes:
| Name | Type | Description |
|---|---|---|
symbolic_nags |
bool
|
If |
supplemental_tags |
bool
|
If |
comments |
bool
|
If |
variations |
bool
|
If |
line_width |
int | None
|
Maximum column line width for movetext wrapping (default
|
Examples:
>>> import libscid
>>> pgn_text = (
... '[Event "World Championship"]\n'
... '[Site "London"]\n'
... '[Date "2018.11.09"]\n'
... '[Round "1"]\n'
... '[White "Carlsen, Magnus"]\n'
... '[Black "Caruana, Fabiano"]\n'
... '[Result "1/2-1/2"]\n'
... '[ECO "B31"]\n'
... '[Annotator "Expert"]\n\n'
... '1. e4 $1 {King Pawn} (1. d4) 1... c5 *'
... )
>>> game = libscid.Game.from_pgn(pgn_text)
>>> # Export with symbolic NAGs (! instead of $1) and no variations:
>>> options = libscid.PgnOptions(
... symbolic_nags=True,
... variations=False,
... supplemental_tags=False,
... )
>>> pgn_out = game.to_pgn(options)
>>> "1.e4 !" in pgn_out
True
>>> "(1.d4)" not in pgn_out
True
>>> '[Annotator "Expert"]' not in pgn_out
True
Nag
libscid.Nag
dataclass
Immutable Numeric Annotation Glyph (NAG) for chess move evaluation.
Encapsulates PGN standard annotation codes (0 to 255) representing move
qualities (e.g. ! for good move, ? for mistake, !! for brilliant)
and positional assessments (e.g. += for slight advantage).
Attributes:
| Name | Type | Description |
|---|---|---|
code |
int
|
Integer NAG code ranging from 0 to 255. A code of 0 denotes an absent or empty annotation. |
Examples:
>>> import libscid
>>> nag = libscid.Nag("!")
>>> nag.code
1
>>> nag.text
'$1'
>>> nag.symbol
'!'
>>> libscid.Nag("$14").symbol
'+='
>>> str(libscid.Nag(3))
'$3'
Initialises a Nag instance from an integer code, text, or glyph symbol.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
value
|
int | str | bytes
|
An integer code (0..255), dollar string/bytes (e.g. |
required |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
LibScidError
|
If an underlying native conversion error occurs. |
Source code in src/libscid/_nag.py
Attributes
text
property
Standard PGN dollar notation string for the NAG.
Returns:
| Type | Description |
|---|---|
str
|
The dollar-formatted string (e.g. |
MoveMetadata
libscid.MoveMetadata
Bases: Flag
Bitwise flag enumeration representing characteristics of a chess move.
Classifies structural, tactical, and rule-based properties of a move such
as check, checkmate, castling, and pawn promotion. Flags may be combined
using bitwise operators (|, &, ^, ~).
Attributes:
| Name | Type | Description |
|---|---|---|
NONE |
No special move characteristics present. |
|
CHECK |
Move delivers a check to the opponent's king (appends |
|
CHECKMATE |
Move delivers checkmate, concluding the game (appends |
|
CASTLING |
Move is a kingside ( |
|
PROMOTION |
Move is a pawn promotion to Queen, Rook, Bishop, or Knight. |
Examples:
>>> import libscid
>>> pos = libscid.Position.from_fen("4k3/1P6/8/8/8/8/8/4K3 w - - 0 1")
>>> meta = pos.get_move_metadata("b7b8q")
>>> libscid.MoveMetadata.PROMOTION in meta
True
>>> bool(meta & libscid.MoveMetadata.CHECK)
True
iter_movetext
libscid.iter_movetext
iter_movetext(
cursor: Cursor, *, variations: bool = True
) -> Iterator[MovetextEvent]
Iterate over movetext events starting from a given cursor position.
Recursively traverses the movetext tree from cursor, yielding structured
MovetextLineStart,
MovetextMove, and
MovetextLineEnd events. When variations is
True, sub-variation branches are explored in depth-first order immediately
after the parent move from which they branch.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cursor
|
Cursor
|
Starting |
required |
variations
|
bool
|
Whether to recursively traverse nested variation branches. Defaults to True. |
True
|
Yields:
| Type | Description |
|---|---|
MovetextEvent
|
Sequential |
Raises:
| Type | Description |
|---|---|
TypeError
|
If |
RuntimeError
|
If cursor navigation encounters an unexpected state. |
Examples:
>>> import libscid
>>> game = libscid.Game.from_pgn("1. e4 (1. d4 d5) e5 *")
>>> moves = [
... event.san for event in game.iter_movetext()
... if isinstance(event, libscid.MovetextMove)
... ]
>>> moves
['e4', 'd4', 'd5', 'e5']
Source code in src/libscid/_domain_support/_movetext_iteration.py
MovetextEvent
libscid.MovetextEvent
module-attribute
MovetextEvent = (
MovetextLineStart | MovetextMove | MovetextLineEnd
)
Union of all movetext iteration event types.
MovetextLineStart
libscid.MovetextLineStart
dataclass
MovetextLineStart(
cursor: Cursor,
preceding_comment: str | None,
variation_depth: int,
variation_index: int,
)
Event emitted at the beginning of a line or sub-variation branch.
Attributes:
| Name | Type | Description |
|---|---|---|
cursor |
Cursor
|
Cursor positioned at the start of this line or variation. |
preceding_comment |
str | None
|
Optional introductory commentary text preceding the first move of the line, or None if absent. |
variation_depth |
int
|
Variation nesting level (0 for the mainline, 1 for first-level sub-variations, etc.). |
variation_index |
int
|
Sibling index among variations branching at this fork point (0 for mainline or first alternative). |
Examples:
>>> import libscid
>>> game = libscid.Game.from_pgn("{Intro} 1. e4 e5 *")
>>> start_event = next(game.iter_movetext())
>>> isinstance(start_event, libscid.MovetextLineStart)
True
>>> start_event.preceding_comment
'Intro'
>>> start_event.variation_depth
0
MovetextMove
libscid.MovetextMove
dataclass
MovetextMove(
before: Cursor,
after: Cursor,
san: str,
uci: str,
nags: tuple[Nag, ...],
comment: str,
variation_depth: int,
variation_index: int,
position_before: Position,
position_after: Position,
)
Event emitted for each move transition in the movetext tree.
Encapsulates the move in both Standard Algebraic Notation (SAN) and Universal Chess Interface (UCI) formats, associated NAG annotations, trailing commentary, variation nesting hierarchy, and board position snapshots immediately before and after the move.
Attributes:
| Name | Type | Description |
|---|---|---|
before |
Cursor
|
Cursor positioned immediately prior to this move. |
after |
Cursor
|
Cursor positioned immediately following this move. |
san |
str
|
Standard Algebraic Notation string (e.g. "e4", "Nf3", "O-O"). |
uci |
str
|
Universal Chess Interface coordinate string (e.g. "e2e4", "g1f3"). |
nags |
tuple[Nag, ...]
|
Tuple of |
comment |
str
|
Commentary text attached to this move, or empty string. |
variation_depth |
int
|
Variation nesting level (0 for mainline). |
variation_index |
int
|
Sibling variation index at the parent fork. |
position_before |
Position
|
|
position_after |
Position
|
|
Examples:
>>> import libscid
>>> game = libscid.Game.from_pgn("1. e4 $1 {King pawn} e5 *")
>>> move = next(
... e for e in game.iter_movetext()
... if isinstance(e, libscid.MovetextMove)
... )
>>> move.san
'e4'
>>> move.uci
'e2e4'
>>> move.comment
'King pawn'
MovetextLineEnd
libscid.MovetextLineEnd
dataclass
MovetextLineEnd(
cursor: Cursor,
variation_depth: int,
variation_index: int,
)
Event emitted at the terminal end of a line or sub-variation branch.
Attributes:
| Name | Type | Description |
|---|---|---|
cursor |
Cursor
|
Cursor positioned at the end of this line or variation. |
variation_depth |
int
|
Variation nesting level (0 for mainline). |
variation_index |
int
|
Sibling variation index at the parent fork. |
Examples:
>>> import libscid
>>> game = libscid.Game.from_pgn("1. e4 e5 *")
>>> events = list(game.iter_movetext())
>>> end_event = events[-1]
>>> isinstance(end_event, libscid.MovetextLineEnd)
True
>>> end_event.cursor.is_line_end
True