The ray filter

The ray filter is a fundamental building block of CQL matching. The ray filter is most commonly used to find pins, but it can be used for more complex configurations as well.

The syntax of the ray filter is as follows:

ray optional_range '(' setfilters ')'
ray optional_range direction_keyword '(' setfilters ')'
ray optional_range attack '(' setfilters ')'

Here, optional_range is a range that is optionally present. The setfilters are a whitespace separated list of at least two set filters. For example:

ray (A a )
ray up (A a P)
ray vertical (A A A a k)
ray attack (A a k)
A ray on the chessboard is all the squares in a straight line with a start-point and an endpoint that is in one of the eight basic directions. For example, there is an up ray from the start point e2 to the endpoint e8 in the up direction. That ray has seven squares e2-8.

Each ray orders the set of its squares. The ordering is determined by the direction of the ray. If squares s and t are on the ray, then s is earlier than square t if t can be reached from s by moving along the ray's basic direction.

For example, in the up ray from e2 to e8, the square e3 is earlier than e7. But in the down ray from e8 to e2, the square e7 is earlier than e2.

A ray R is said to match a list of n distinct squares in the current position, s1, s2, ...,sn if

  1. Each s1, ..., sn is on the ray
    • s1 is earlier than s2
    • s2 is earlier than s3
    • ...
    • sn-1 is earlier than sn.
  2. If a square t is on the ray then either
    • t is one of s1,...,sn or
    • t is empty (or both)

The basic directions of a ray

Each ray filter has a set of allowed basic directions depending on its direction parameter and its argument setfilters.

If the direction parameter is omitted, then the basic directions allowed are the eight basic directions.

If a direction_keyword is specified, then the basic directions are the elements of the directions given by that keyword.

ray attack (s1 s2 ... )
is shorthand for
  ray orthogonal ({[QqRr] on s1} s2 ...)
  or ray diagonal ({[QqBb] on s1} s2 ...)

ray filter matching a position

A ray filter with arguments s1, s2, ..., sn matches the current position if:
  1. there is some basic direction D that is one of the basic directions of the ray
  2. there is a ray R in the direction D
  3. there are squares t_1, t_2, ... such that t_1 is in the set represented by s1; t_2 is in the set represented by s2; and so on,
  4. R matches s1, s2, ...
  5. s1 is the startpoint of R and sn is the endpoint of R

Examples of rays

This filter is true whenever a black knight is pinned:
ray attack (A n k)
To match a position with any pinned black piece, use
ray attack (A a k)
To match any pinned piece, use
flipcolor ray attack (A a k)
Suppose the current position is the position after 1e4 e5 Nf3 Nc6. Then some rays that would match the position are:
ray diagonal (c6 e4 f3)
ray diagonal (n P N)
ray (n P N)
ray up (K P p k)
ray up (K _ P p _ k)
ray right (r b q k)
ray northeast (R P p p r)
ray attack (B P h6)
ray (Q c2)
ray orthogonal (K P)
However, the following ray filters would not match the position:
ray (K p)
ray (K p k)
ray diagonal (K p)
ray attack (N a-h1-8)

counting rays

If the ray keyword is followed by a range, then the ray matches the position only if the number of distinct rays matching the arguments lies within the range. For example,
ray 2 4 attack (A a k)
matches a position only if two, three, or four Black pieces are pinned

ray as a set filter

(New since version 5.2) As a set filter, a ray is the set of squares in the last filter in its list of filters that terminates a matching ray.