fen support

FEN stands for Forsyth-Edwards Notation. It is a standard syntax for representing individual chess positions. CQL supports FEN via the fen filter inside a CQL file and as a command line argument.

A FEN record is a sequence of fields separated by spaces. Each field is just a sequence of alphanumeric characters.

For example the FEN record representing the start position is

rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1

CQL actually supports its own "extended" version of FEN in which the piece names in the first record (which agree with CQL's convention for piece naming) can be augmented by using any of the single-character piece designators: A, a, . or _. These have the obvious meanings. For example, if we replace the first four characters of the FEN record for the initial position above to get:

Aa._kbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR
then this represents any position with a white piece on a8, a black piece on b8, anything at all or an empty square on c8 and an empty square on d8. (This position can't actually occur, it's just an example).

fen filter

The fen filter consists of the keyword fen optionally followed by a quoted string. If the quoted string is present, is called the argument to the fen filter and represents a FEN record.

fen without arguments

(New in CQL 6.1) If fen is not followed by a quoted string, the value of the filter is a string representing the FEN associated with the current position. (The halfmove clock and fullmove number are treated as 0 and 1 respectively). This function is mainly used with writefile and dictionary to communicate with external programs or to check the occurrence of a FEN. In computing this FEN, the castling and en-passant privileges of any FEN mentioned in the PGN header as the FEN of the start position are disregarded:
  message ("Current Fen: " fen)
  writefile ("fenslist.cqo" fen)
  dictionary D
  D[fen]="seen"

Retrieving the halfmove clock and full move number

If you want to get a FEN that includes the halfmove clock and full move number, you can use the following CQL code:
function NHalfMovesSinceZ(){
distance(
  
  find <-- initial
            or currentmove ――
	    or currentmove ×
}	    
	   
  
function EditFen(F){
 assert F[-3:]="0 1" //make sure F comes from the fen filter
 F[-3:] = str(NHalfMovesSinceZ() " " movenumber)
 F
} 
 

Now, to use this, just write EditFen(fen) in your code instead of fen if you want that fen. However, for most purposes the default value of fen is more useful.

fen with argument

If the fen is followed by a quoted string, then the fen filter matches the current position if the board position (the placement of pieces and empty squares) in the current position is identical to the board position specified by the first field of the FEN record.

Thus, to find games with the board position discussed above, just use

      fen "Aa._kbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR"
Note how we left off the last five fields of the FEN record here, although this is optional.

Uses of the FEN filter with an argument

FEN is supported by most chess GUIs. Sometimes it is quicker to simply copy the position to a FEN in the GUI, then paste that FEN into CQL, rather than specifying the pieces individually. Of course, if you care about side to move and castling or en passant rights, you would have to specify those separately. (Side to move can be specified using wtm and btm . You can test for castling or en passant rights by move legal castle and move legal enpassant. However, CQL move legal disregards any FEN information regarding prior moves pertaining to castling or en passant rights in its assessment of the legality of castling or en passant. (This is because in our experience such information is frequently incorrect or inadvertently entered).

On the command line, you can specify a FEN using the --fen keyword directly, which lets you quickly search for a position without constructing a new CQL file. Thus,

      cql -input foo.pgn -fen "Aa._kbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR"
would match games with the specified position

The fen filter with argument can be flipped and rotated, but not shifted (if an attempt to shift a fen filter is made, CQL thinks the empty squares need to be shifted too, so nothing matches since some empty squares wind up off the board).

Parsing fens

When using fens in CQL, it is frequently necessary to parse a FEN string into its constituents. The following sample function, given a valid fen string as argument, sets the global variables: FenPieces, FenToMove, FenCastle, FenEnPassant, FenHalfmoveClock, FenFullmoveNumber:
function ParseFen(Fen){
   Fen ~~ 
     "^([^ ]+) ([bw]) ([KQkq]+|-) ([a-h][1-8]|-) (\d+) (\d+)"
   FenPieces=\1
   FenToMove = if \2=="b" black else white
   FenCastle = \3
   FenEnPassant = if \4=="-" [] else makesquare \4
   FenHalfmoveClock = int \5
   FenFullmoveNumber = int \6
}

To parse the current fen, use

	ParseFen (fen)
      

Note that the value of the enpassant record (FenEnPassant) taken from the FEN is not the same square as the value of the enpassantsquare parameter to move. The enpassantsquare parameter is the value of destination square of the captured pawn; the FEN en passant record is the the destination of the capturing pawn.