app/pgn.h

a real PGN reader (broadcast-docs/PLAN.md §2, B1).

Until now the only PGN we read was Lichess’s puzzle payload, which is bare SAN and move numbers — so resolveFromPgn() got away with istringstream >> token and a digit check. A broadcast PGN does not resemble that at all:

  1. Nf3 { [eval -0.82] [clk 0:04:37] } 25… Ngxe3?! { Inaccuracy. e5 was best. }

which whitespace-splits into {, [eval, -0.82], … and puts { straight into sanToMove on move one. Hence a reader that actually understands the format: {} comments, ; line comments, () recursive variations (which, unlike comments, really do nest), $n NAGs, move numbers glued or spaced, and the result token.

SAN decorations are deliberately left on the token — sanToMove documents that it ignores + # ! ?, so stripping them here would be a second, drifting copy of a rule the engine already owns.

Pure: no engine, no network, no hardware. Turning SAN into moves needs a position and is the caller’s job.

namespace kirin
struct PgnGame
#include <pgn.h>

Public Functions

std::string tag(const std::string &name, const std::string &fallback = "") const

Public Members

std::vector<std::pair<std::string, std::string>> tags
std::vector<PgnMove> moves
std::string result
struct PgnMove
#include <pgn.h>

Public Members

std::string san
std::string clock