focus) is a parameter to ⊢ that lets the user focus on the movements of a selected set of pieces and ignore other pieces.
◎ parameter to
⊢ is followed by a set filter. When the
⊢ filter is evaluated at a position, this set filter is evaluated to get a set of squares. The pieces that are on those squares at the start of the
⊢ evaluation are called the focused pieces.
A move is said to be in focus if it is a move by a focused piece. If the move is castling, the move is in focus if either the moving rook or the moving king is in focus.
A move that is not in focus is out of focus
For example, consider the following game:
1. d4 d5 2. ♘f3 ♞f6 3. g3 g6 4. ♗g2 ♝g7
Suppose the following
⊢ filter is evaluated at the initial position of that game:
⊢◎♙ ―― ―― ///"fianchetto"
◎ parameter has argument
♙, the focused pieces are the eight white pawns.
The first constituent of the
――, which will match the first move of the game,
d4. That move is in focus because it is by a white pawn.
⊢ filter sets the current position to the result of executing the first move (so it is now Black's move) and evaluates the second constituent:
――. This constituent would ordinarily match the game's second move (Black's first move,
d5), but that move is out of focus because it is by a White piece. The next out-of-focus moves are all skipped by the
⊢ filter, until the move
g3 is reached. Since that move is in focus, it is matched. The filter
///"fianchetto"would now be evaluated and would have the effect of the commenting the move
g3with the annotation
fianchettoin the output PGN file.
Because two focused moves (
g3) were matched, the numeric value of this
pathu filter would be two.
Allowing captures of focused piecesOrdinarily, a capture of a focused piece would not considered to be in focus (unless it were performed by another focused piece of course). That is because a capture of a focused piece is not a move by that focused piece, so it would not be a focused move.
Sometimes however we want to include captures of focused pieces as being in-focus moves. If the keyword
focus (or the symbol
◎) is immediately followed by the keyword
capture, then captures of focused pieces (as well as moves by focused pieces) are considered to be in focus. An example of this feature is in the CQL file clearance-delayed.cql .
Special handling of focus for the first move of a pathThere is one special case we have not mentioned. The first move of the game from the start position must be in focus. Thus, from the initial position of the above game, the filter
⊢◎♞ ――would not match at all, because the first move
1.e4is not in focus. The reason this rule is chosen is that, if this
⊢filter were in a CQL file, the CQL file would later try to match the filter starting from the position where the move in question would be in focus.
Focusing on just the white to move, just the black to move, or bothOlder versions of cql had a
singlecolorparameter which only considered moves by a single side. To just get moves by white pieces, use
⊢◎△....Likewise, to only get moves by black pieces, use
If we want to consider only moves by whichever side is originally to move without using
This is exactly equivalent to the older
◎if wtm △ else ▲...
singlecolor. This technique is used in forced-moves-either-side.cql and consecutive-checks-by-one-color.cql .
Counting moves with
Counting moves can be complex when using
◎because sometimes we are interested in the count of the focused moves, sometimes the unfocused moves, sometimes both combined.
The following filters are used for counting moves inside of a
pathcount, which gives the total number of focused moves seen so far from the start position of the
⊢filter to the current position.
pathcountunfocused, whcih gives the total number of unfocused moves seen so far from the start position
pathcountunfocused is exactly the same as
ply-pathstart:ply-pathcountand in fact that is how this filter is implemented internally. That is because
plyis the ply of the current position and
pathstart:plyis the ply of the start move of the
⊢filter. Therefore, their difference is the total number of ply traversed by the
⊢filter, which is the total number of moves (in the path from the start position to the current position). Since each move is either focused or unfocused, but not both, subtracting the number of focused moves gives the number of unfocused moves.
pathcountunfocused filter can be used with the
max parameter of
⊢, which indicates what value the
⊢ filter is trying to maximize in its choice of path. This use of
pathcountunfocused is illustrated in clearance-delayed.cql where we are interested in the number of unfocused moves because they tell us how much "delay" is involved in the theme.
piecepath parameter with
⊢filter has a
piecepathparameter, the motion of each focused piece is output to the PGN in a concise way. This gives an easy-to-read bird's eye view of the path taken by a focused piece. For example, in staircase-sort-annotated.cql , the
⊢◎♕ piecepath...The output in the PGN file might include a particular staircase taken by the queen, e.g.
The piecepath parameter to
⊢ can also be used when there are multiple pieces in focus. Each such piece's path is individually commented.
Clarity of expression and
One of the goals of the
⊢is to help to express the central ideas of the theme clearly than in previous versions. That is,
◎can facilitate the expression of thematic ideas.
We will give three examples below.
Rook traversing the cornersSuppose we want to search for a rook appearing on all four corners in just three moves (see rookleapcorners.cql . With
◎, we can write
✵⊢◎ T //T is a ♖ a1――h1 ――h8 ――a8
Writing this in the old version would be longer and would require repeated explicit ignoring of moves we do not want to see:
flip //A CQL 6.1 version line --> move from (T&a1) to h1 --> move from ~T * --> move from T to h8 --> move from ~T * --> move from T to a8
It is true that the second version is more familiar to long-time CQL users. However, abstractly, the semantics of the first version are much closer to that of chess notation.
Turton themeThe Turton involves the movement of two pieces,
U, as well as a critical square
C. The body of the theme is expressed in three moves:
⊢◎T|U T―― not xray(T C U) ///"T crosses critical square " C U――C ///"U to critical square" U―― xray (T C U) ///"U moves supported by T"
Note that the
insert comments into the PGN file. The xray filter,
xray(T C U) in case it is unfamiliar, asserts that the piece at
T attacks the square
U and that the square
C is between
This requires three moves, exactly the thematic moves.
The old version of Turton requires 7 arrows and more boilerplate:
line --> move from T comment ("T moves to " T " crossing critical square " C) --> not xray (T C U) --> not move from (T | U) * --> move from U to C comment ("U moves to the critical square: " C) --> not move from (T | U) * --> move from U comment ("U moves supported by T") --> xray (T C U)
Because of the greater number of arrows and all the regular expressions required to skip moves, we find this expression obscures the essence of the Turton theme in comparison to the
Snake exampleThe snake theme involves a piece moving along a zigzag path like
a1-b2-a3-b4-a5-b6-a7. The new version of snake looks for snakes of size at least 5, and sorts the output by length (T is the piece that is supposed to participate in the snake).
✵ 5≤sort "snake length" ⊢◎T nestban piecepath (――northeast 1 T ――southeast 1 T)+ ――northeast 1 T ?
This version is very similar to the code for a simple staircase sort.
By contrast, the snake-old.cql version is too long to show here. It runs to 62 lines (versus 10 for the new version) and is much more complex, has worse comments output to the PGN file (because
piecepath is missing), and runs single-threaded.
The older version also required a separate dictionary to implement a less precise version of
nestban, and had to keep track of counting the focused moves in the itself, which complicated the
focus is not a panacea. In some cases, like clearance-delayed.cql, the improvement is much smaller compared to the older version clearance-delayed.cql.
In some cases it is difficult to use or inapplicable. But in our experience, it often leads to shorter, clearer CQL files with better PGN annotations as well compared to earlier versions of CQL.