The move filter

The move filter tests whether a move occurs in the pgn file.

	move from K to _ ; White king moves to empty square
	move from k      ; Black king moves
	move previous from R ; Previous move was of a white Rook
	move previous null ;  Previous move was a null move
	move promote N     ;  Next move is a knight promotion
      

The formal syntax for a move filter:

	move_filter:=
	'move' move_parameters |
	'move previous' move_parameters

	move_parameters:= move_parameter*

	move_parameter:=
	'from' from_set
	'to' to_set
	'null'
	'primary'
	'secondary'
	'promote' piecedesignator
	'enpassantsquare' epset
	'enpassant'
In the move-parameters section: Omitting from means implicitly from a-h1-8
Omitting to means implicitly to a-h1-8

At most one of enpassantsquare or enpassant may be present.
enpassant is shorthand for enpassantsquare a-h1-8.

If promote is present, the piece designator must not list squares explicitly:

	move promote R ; legal syntax
	move promote [RN] ; legal syntax
	move promote Re8 ; illegal syntax
	move to e8 promote R ; legal syntax

move filter matching a position

To determine if a move filter matches a position, a two step process is used. Step 1 The candidate moves for the move filter are generated.

Step 2 The moves from the candidate moves that match the move parameters are generated.

A move filter matches the current position if step 2 succeeds: a move matching its parameters exists among its candidate moves.

The candidate moves for the move filter

The candidate moves for a move filter depend only on whether the move filter is of type move previous or not, and whether variations is set in the CQL header.

If the move filter is of type (that is, if it begins with the words) move previous, the the candidate move is just the previous move, if any. By "previous move" is meant the move that led to the current position. This move always exists except for the initial position of the game or study.

Otherwise, if the move filter is an ordinary move filter, then the candidate moves are:

  • If variations is set in the CQL header, then all the moves appearing in the PGN file from the current position.
  • Otherwise, only the mainline move from the current position, if any.

Matching the candidate moves

Once the candidate moves are matched, the matching candidate moves are generated. Whether a candidate move matches the move filter depends on the move_parameters: a candidate move matches a filter if and only if it matches each of the move parameters in the filter. The move filter itself matches a position if any of its candidate moves match.

If the move filter is of type move previous then the current position is set to the previous position (and restored afterwards of course).

Here are the rules for whether a move matches a move parameter:

  • A move matches its from parameter if the square from which the moving piece moves is a member of the set represented by from_square in the current position.
  • A move matches its to parameter if the square to which the moving piece moves is a member of the set represented by to_square in the current position (or previous position in the case of move previous).
  • A move matches its promote parameter if it is a promotion to the piece indicated by its piecedesignator.
  • A move matches its enpassantsquare parameter if the move is an en passant move that captures a pawn on a square that is a member of the set of squares corresponding to epset in the current position (or previous position in the case of move previous).
  • (since version 5.2) A move matches its primary parameter if it is a primary move. A primary move is either the first move of the game, or it is one which does not begin a new variation. Thus, in the PGN file, a primary move is the first move after a particular position.
  • (since version 5.2) A move matches its secondary parameter if it is a secondary move. A secondary move is a move is move that begins a new variation from the previous move. In the PGN file, a secondary move is always preceded by a left parenthesis:, e.g. in
     1. e4 (1. d4 d5) e5 
    the only secondary move is 1. d4. The other moves, 1.e4, 1...d5, and 1...e5 are all primary moves.
  • (since version 5.2) A move matches its null parameter if it is a null move. A null move is a move that changes only the side to move. It is represented in the PGN file by two adjacent hyphens: --. A null move is considered to be a move from the King of the side to move to the same square.

The move filter as a set filter

As a set, the move filter represents the set of squares S in to_set in the current position (for move previous, use the previous position, since version 5.2) for which there is a matching candidate move that is to a square in S.

Castling

Castling is represented as a move from the King's origin square to the King's destination square.

Examples

In the current position, a White knight moves
	move from N
In the current position, a White knight moves to the eighth rank:
	move from N to a-h8
A white minor piece captures the black Queen on the next move:
	move from [nb] to q
White underpromotes:
	move promote [RBN]
Black makes an enpassant move from the g file or the h file
	move from pg-h4 enpassant
White moves a rook to a square in the King's field:
	move from R to attack (K .)
This can also be written
	move from R to anydirection 1 K
The Black Queen has just moved to an unguarded square:
	attack 0 (.
        move previous q)
      
White en passant is possible:
	move previous from pa-h7 to horizontal 1 Pa-h5
This last might need some explanation:
	horizontal 1 Pa-h5
are all the squares on the 5th rank that are horizontally adjacent to a white Pawn. Thus,
move previous from pa-h7 to horizontal 1 Pa-h5
means that on the previous move, Black moved a pawn from the seventh rank to a square on the fifth rank adjacent to a white pawn.

En passant is possible (by either White or Black):

	flipcolor
	move previous from pa-h7 to horizontal 1 Pa-h5

Now consider the following sequence of moves from the start position:


	1. e4 e5
	2. Nf3 Nc6
	3. Bb5 (3. a3 h6)
	(3. Bc4 Bc5
        (3...Be7 4 o-o)
        4 d4)
      
The primary moves above are:
	1. e4 e5; 2. Nf3 Nc6; 3. Bb5;
	3...h6;
	3...Bc5;
	4. o-o;
	4. d4
      
The secondary moves are all the other moves.

Now consider the following cql file:

cql (input test.pgn variations)
        move secondary from P
      
The move filter here will match this game, because it will match the position that arises after 2. ... Nc6. When the current position is set to that position - just after the move 2...Nc6 is played - two steps are done.

First the list of candidate moves will be generated. This is all the moves from the position, namely: 3. Bb5; 3. a3; 3. Bc4 Of these three moves, only two are secondary moves: 3. a3; 3. Bc4 Of these two moves, only one matches the from P parameter, namely 3. a3

Therefore the move filter matches that single position.

Likewise, on the same PGN game, the filter

move previous primary from [Bb]
will match all the positions whose previous move was a bishop move that that does not descend into a new variation. These are the positions after 3. Bb5 and 3. ... Bc5. But this filter will not match the position after 3..Be7, because that move begins a new variation.

Using move inside of next

When move is used inside of a next filter when variations is set in the CQL header, see these special rules.