CQL file: structure and operationThere are three parts to a CQL file:
- The word
- The CQL header: a sequence of cql parameters enclosed in parentheses
- The CQL body: a sequence of filters.
For example, here is a CQL file to find games where black is stalemated and is pinned at least twice:
cql (input heijden.pgn) btm stalemate 1< pin through a
In the above example, the CQL header consists of one cql parameter:
input heijden.pgn specifies that the games are to be read from the file
The CQL body in the above example is a sequence of three filters:
- A btm filter, which matches a position with black to move.
- A stalemate filter, which matches a position that is stalemate
- A < filter
1<pin through a
<filter has two arguments itself, each of which are also filters:
pin through a
The first of these,
1 is just the number 1. The second argument to the
pin through a,
represents the set of squares on which there is a black pinned piece. When a number is compared to a set using
the set is replaced by its
cardinality. Thus, the
< filter in the CQL file will match a position whenever there are multiple
pinned black pieces in the position.
This CQL file will output every game from
heijden.pgn in which there is a black stalemate with at least two pinned black pieces.
Operation of a CQL fileHere are the steps CQL takes when it is invoked on a
- CQL reads the CQL header and any command line arguments to determine where
it should read the PGN data from (the
- For each game in the
inputfile, CQL tries to match that game against its CQL body. It does this by visiting each position in the game being examined. Each time CQL visits a position, it does this:
- set the current position to the position being examined
- Evaluate each filter in the CQL body on the current position.
- If all the filters are true, the position matches
- Otherwise, the position fails to match.
- After all the positions in the game being examined were visited, CQL determines if the game matches. Normally,
the game matches if at least one of its positions matched the CQL body. (This can be changed by the
- If the game matches, it is output to the output file.
The input fileThe input file should be a standard PGN file. CQL works best with PGN files which are in so-called export format, which roughtly means they should not be hand-generated but should adhere to a strict format, such as should be produced by the output of a chess program or web site.
Over the decades, a number of commonly used programs have introduced non-compliant behavior into the PGN files they generate. Some PGN files have nested comments. CQL will try to eliminate the internal braces in nested comments. Others have Unicode non-ASCII characters, which CQL typically ignores.
If the filename contains spaces, you should enclose the filename in quotes:
cql (input "filename with spaces.pgn")
The output fileThe output file where the matched games are output to is by default the name of the CQL file, without any
.cqlfile extension, prepended to
-out.pgn. For example, if the CQL file is
foo.cqlthen the output file will be
foo-out.pgn. You can specify the output explicitly, either on the command line with
-outputor in the CQL header
If the filename contains spaces, you should enclose the filename in quotes.
Which positions are visitedBy default, CQL only visits the mainline positions in each CQL file. This can be changed by specifying the
-variationsflag on the command line or including the
variationsparameter in the CQL header:
cql(input heijden.pgn variations) ...
CQL visits the positions in the order they occur in the PGN file.
SummaryEverything in CQL depends on this order of operations. In brief,
- CQL reads parameters from the CQL header, and parses the CQL body into filters
- For each game, CQL determines whether any position from a game matches all the filters in its body
- Every time a game matches the CQL body, the game output to a pgn file