CQL file: structure and operation
There are three parts to a CQL file:- The word
cql
- 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
The parameter, input heijden.pgn
specifies that the games are to be read from the file heijden.pgn
.
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:
1and
pin through a
The first of these, 1
is just the number 1. The second argument to the <
filter, 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 file
Here are the steps CQL takes when it is invoked on a.cql
file:
- CQL reads the CQL header and any command line arguments to determine where
it should read the PGN data from (the
input
file). - For each game in the
input
file, 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
matchcount
parameter). - If the game matches, it is output to the output file.
The input file
The 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. The PGN file should not contain any illegal moves, although null moves are allowed. (CQL sometimes halts with cryptic error messages if the PGN file is ill-formed.)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 file
The output file where the matched games are output to is by default the name of the CQL file, without any.cql
file extension, prepended to
-out.pgn
. For example, if the CQL file is foo.cql
then the output file will be foo-out.pgn
. You can specify the output explicitly,
either on the command line with -output
or in the CQL header
If the filename contains spaces, you should enclose the filename in quotes.
Which positions are visited
By default, CQL only visits the mainline positions in each CQL file. This can be changed by specifying the-variations
flag on the command line
or including the variations
parameter in the CQL header:
cql(input heijden.pgn variations) ...
CQL visits the positions in the order they occur in the PGN file.
Summary
Everything 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