Documentation

Metadata Filters

Query and edit PGN metadata with filters for tags, ratings, results, game numbers, and metadata-driven workflows.

The filters described in this section allow access to PGN game metadata including tag values, ordinal position of the game within the PGN file, and the recorded game result.

The tag, settag, and removetag filters support querying, modifying, and removing PGN tags.

Convenience filters provided for extracting information from standard PGN tags include elo, event, player, result, site, and year.

The gamenumber filter yields the index of the current game within the PGN file and the result filter supports querying of the recorded game result.

The result Filter

The result filter takes a single argument representing a game disposition and yields a Boolean value indicating whether the game terminated with the specified disposition. The valid arguments for the result filter are: 1-0 or "1-0" indicating a win for White, 0-1 or "0-1" indicating a win for Black, 1/2-1/2 or "1/2-1/2" indicating a draw, and * or "*" indicating an incomplete game. The result filter yields true if the specified disposition matches the disposition of the current game and false otherwise.

The game termination token, not the value of the Result PGN tag, is used to determine the game’s disposition. To obtain the value of the Result PGN tag (which should match the game termination token), use tag "Result".

The following query will detect and report conflicts between a game’s termination token (via the result filter) and either the result recorded in the Result tag or the game’s actual disposition (checkmate, stalemate, variant-specific win, etc).

cql()
mainline
terminal

$result_str = "*"
if result 1-0 then $result_str = "1-0"
else if result 0-1 then $result_str = "0-1"
else if result 1/2-1/2 then $result_str = "1/2-1/2"

if ($result_tag = tag "Result") and $result_tag != $result_str {
    message("Value of Result tag ('" $result_tag
        "') is inconsistent with game termination token '"
        $result_str "'")
}

$cur_side = if wtm then "white" else "black"
$off_side = if wtm then "black" else "white"

if variantwin {
    if flipcolor { wtm not result 1-0 }
        message("Game termination token '" $result_str
        "' inconsistent with result of variant win by " $cur_side)
}
else if variantloss {
    if flipcolor { wtm not result 0-1 }
        message("Game termination token '" $result_str
        "' inconsistent with result of variant loss by " $off_side)
}
else if variantdraw {
    if flipcolor { wtm not result 1/2-1/2 }
        message("Game termination token '" $result_str
        "' inconsistent with result of variant draw")
}
else if stalemate {
    if not result 1/2-1/2
        message("Game termination token '" $result_str
        "' inconsistent with result of stalemate")
}
else if mate {
    if flipcolor { wtm not result 0-1 }
        message("Game termination token '" $result_str
        "' inconsistent with result of checkmate by " $off_side)
}

false

Tag Filters

Tag filters operate on the tag pairs appearing before the move text section of a PGN file.

The Standard Tag Filters

The standard tag filters are date, eco, event, eventdate, site, and player.
When not immediately followed by a string literal, these filters yield a String whose value is the value of the current game’s corresponding tag, as shown in the below table.

Filter Tag
date Date or UTCDate
eco ECO
event Event
eventdate EventDate
site Site
player White and Black

If the corresponding tag does not appear in the current game, the filter does not match the position. The date filter will yield the value of either the Date or UTCDate tag, preferring Date if present. The player filter may optionally be followed by the white or black keyword. The filter player white will yield the value of the White tag and player black the value of the Black tag. If player is not followed by black or white, the result is equivalent to:

notransform { player white + \n + player black }

Any of the standard tag filters may be immediately followed by a string literal in which case the filter yields a Boolean value indicating whether the value of the string literal appears within the value of the corresponding tag. E.g. site "X" is equivalent to "X" in site.

The year Filter

The year filter yields a Numeric result that corresponds to the year provided in either the Date or UTCDate PGN tag for the current game. If neither of these tags is present or a valid year could not be extracted from the tag, the year filter will not match the position. For example, to limit games to those played between 2000 and 2005 use:

2000 <= year <= 2005

The elo Filter

The elo filter exposes information from supplemental tags in the tag pair section of the PGN game related to player ratings. If the token following elo is black or white, the filter evaluates to the numeric rating of the corresponding player. If the rating for the requested player is not available, the filter does not match. If elo is not followed by black or white, the filter yields the rating of the higher-rated player if the ratings for both players are present and does not match the position otherwise.

Ratings are traditionally supplied via the WhiteElo and BlackElo tags but this is not universal and several other tags are commonly used to provide this information. When parsing a PGN game, the rating of each player is taken from the first tag in the below table that contains a numeric value. If no matching tag is encountered, the rating for that player is considered to be unavailable.

White Black
WhiteElo BlackElo
WhiteRating BlackRating
WhiteRapid BlackRapid
WhiteICCF BlackICCF
WhiteUSCF BlackUSCF
WhiteDWZ BlackDWZ
WhiteBCF BlackBCF

The tag Filter

The tag filter accepts a single string argument which specifies the name of the PGN tag to inspect, and yields a string value corresponding to the value of the specified tag in the current game. If the specified tag is not present for the current game, the filter yields None.

The tag filter operates on the tags present in the PGN file, changes to tags via the settag or removetag filters are not reflected in the evaluation of tag as these changes are not realized until after the game has been processed.

The settag Filter

The settag filter accepts a parenthesized argument list consisting of two string filters. The first string filter argument is the tag name and the second string argument is the tag value. This filter sets the value of the specified tag, creating the tag if it was not originally present in the PGN file. The new tag value is included in the output PGN written by CQLi.

The PGN format requires that tag names consist exclusively of letter, digit, and underscore characters. If the name specified by the settag filter consists of characters besides A-Z, a-z, 0-9, or _, the filter yields false without making any changes. Existing tags with such invalid names may be queried with the tag filter and removed with the removetag filter but may not be created or modified via settag.

Caution should be exercised when using settag to set the value of standard tag names as this may cause problems when read by other PGN-processing software. In particular, setting the value of the standard tag FEN is likely to elicit errors from chess software if the value of this field does not correctly portray the initial position of the game.

The PGN standard forbids the use of non-printing characters in tag values. CQLi will replace carriage return and linefeed characters appearing in the second argument to settag with spaces but will not prevent other non-printing characters from being used in a tag value. The PGN specification also limits tag values to “255 characters of data”, as a result some chess software may have difficulty reading tag values that exceed 255 bytes.

Note that settag does not employ smart-comment-like semantics. The effects of a previously evaluated settag filter will be realized even if the same position later fails to match.

If the –nosettag option is specified, the settag filter behaves as described above except that the change is not represented in the corresponding output PGN file.

Examples

The following query will set the tag PlyCount to the number of plies in the mainline:

cql(quiet)
mainline
terminal
settag("PlyCount" str ply)

The query below will set the tag TotalPlyCount to the total number of plies across all variations, i.e. the total number of moves or the total number of positions not counting the initial position.

cql(variations quiet)
initial
settag("TotalPlyCount" str find all true - 1)

The next query will set the tag MaxPly to the largest ply of any position across all variations. The echo filter will evaluate its target filter at every position. When the target of an echo filter is a Numeric filter, the result is the value of the largest evaluation at any of the processed positions. The target filter yields the ply of all terminal positions and the result of the enclosing echo filter is the largest of these values. The in all parameter is used to include the initial position in set of positions evaluated by echo so that a game without any moves will have a MaxPly value of 0 instead of <None>.

cql(variations quiet)
initial
settag("MaxPly" str echo(x y) in all { terminal ply })

The removetag Filter

The removetag filter accepts a single string argument representing a tag name. The specified tag will be removed from the current game when written to the output PGN file unless a later evaluation of a settag filter specifies a value for the same tag name. If there is no tag of the specified name to remove (either appearing in the original PGN content or previously added with settag), the removetag filter has no effect. The removetag filter always yields true.

Caution should be exercised when using removetag with standard tag names as this may cause problems when read by other PGN-processing software. In particular, removing the value of the standard FEN or SetUp tags is likely to elicit errors from chess software if the game does not start from the expected starting position.

Note that removetag does not employ smart-comment-like semantics. The effects of a previously evaluated removetag filter will be realized even if the same position later fails to match.

If the –noremovetag option specified, the effects of the removetag filter are not honored.

The gamenumber Filter

Every game is assigned a game number by CQLi which is a one-based index representing the physical order of the game within the PGN file. The first game in the PGN file has a game number of 1, the second a game number of 2, etc. The gamenumber filter yields the game number of the current game.

The proper ordering of game numbers is maintained even when using multiple threads where one thread may process several games in the time it takes another thread to process one game. When using the –gamenumber option to skip games, the indices of the skipped games are not reused, e.g. the option --gamenumber 10 20 specifies that only games 10 through 20 (inclusive) should be processed and the gamenumber filter will yield values between 10 and 20 for these games.