◎
(focus)
◎
(or focus
) is a parameter to ⊢ that lets the user focus on the movements of a selected set of pieces and ignore other pieces.
The ◎
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"
Because the ◎
parameter has argument ♙
, the focused pieces are the eight white pawns.
The first constituent of the ⊢
is ――
, which will match the first move of the game, d4
. That move is in focus because it is by a white pawn.
The ⊢
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
g3
with the annotation fianchetto
in the output PGN file.
Because two focused moves (d4
and g3
) were matched, the numeric value of this pathu
filter would be two.
Allowing captures of focused pieces
Ordinarily, 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 path
There 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.e4
is 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 both
Older versions of cql had asinglecolor
parameter 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
⊢◎▲...
This is used, for example in staircase-sort.cql , where only moves by white pieces are considered (moves by black moves are also considered implicitly because the ⊢
occurs inside the scope of ⬓ ).
If we want to consider only moves by whichever side is originally to move without using ⬓
, use
◎
if wtm △ else ▲...
This is exactly equivalent to the older 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 ⊢
filter:
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
Note that pathcountunfocused
is exactly the same as
ply-pathstart:ply-pathcountand in fact that is how this filter is implemented internally. That is because
ply
is the ply of the current position and pathstart:ply
is 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.
The 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 max
with 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.
Using the piecepath
parameter with ◎
When a ⊢
filter has a piecepath
parameter, 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 ⊢
parameters include:
⊢◎♕ piecepath...The output in the PGN file might include a particular staircase taken by the queen, e.g.
Qa1-a2-b2-b3-c3-c4
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 ◎
parameter to ⊢
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 corners
Suppose 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 theme
The Turton involves the movement of two pieces,T
and 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 ///
filters
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 T
and U
.
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 ◎
version.
Snake example
The snake theme involves a piece moving along a zigzag path likea1-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 line
.
Of course, 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.