CQL FAQ

Be sure you read manual.txt and the examples before checking this FAQ.

Why is the manual so difficult to understand

We've rewritten the manual! It's now difficult to understand in full-blown HTML, not just .txt. However, if there are still questions, we are happy to help answer them and to help with CQL files. Just email rbnn@rbnn.com .

What is the latest version

Version 3.02

This version supportstagging, which keeps track of piece identity.

Why am I getting anomalous results when I use :shift and a piece is on the edge of the board?

When a piece designator refers to a square on the left edge of the board, for example, and a right shift is performed on the position, the new designator continues to include the original square on the left edge.

For example,

(position 
  Pa4 Nd4 :shifthorizontal)

will match any position in which White has a knight on d4, e4, f4, g4, or h4 and in which White has a pawn on the fourth rank at least three squares to the left of that knight.

If, conversely, one wanted to search for positions in which White has a knight on d4, e4, f4, g4, or h4 and in which White has pawn on the fourth rank exactly three squares to the left of the knight, then the following fragment would be used:

(position 
  Pb4 Ne4 :shifthorizontal)

Similar rules apply for shifts in other directions: pieces are always "shifted in" to the edge of the board.

It is worth noting that this feature does give pattern matching power that would be difficult to obtain using other features. For example, consider the following fragment:

(position
  Pa4 Pa5 Nd4 Nd5 :shifthorizontal)

This fragment would match positions with a pair of pawns, one behind the other, on the fourth and fifth ranks, at least three files to the left of a similarly arranged pair of knights. This pattern could not be readily expressed using other primitives without this "shift-in" feature.

How does :moveto work?

:moveto takes a piece designator, not a square. Thus,

:moveto d4

will not work. You would have to use

:moveto ?d4

See manual.txt for other examples.

How can I check for an unguarded guard?

Unguarded guard is a theme in which

  • White is in check
  • White moves a piece to an empty square to stop the check
  • After moving the piece, that piece is unguarded

Use this form (use :flipcolor to search for black avoiding check and so on, of course).

;;Find positions with white to move such that white 
;;is in check from a sliding piece and
;;on white's next move interposes a piece that is unguarded

(match
 :pgn heijden.pgn
 :output out.pgn

 (position
  :wtm
  :moveto .d4
  :check
  :or
  ((position   :rayorthogonal ([qr] .d4 K))
   (position   :raydiagonal ([qb] .d4 K))
   )
	       
  :sequence
  ((position)
   (position :attackcount A Ad4 0)
   )
  :shift :markall)
 )

In fact Tim Krabbé observes the :ray specifiers are superfluous here, since a white move to an empty square when in check must stop a ray check.

How about an unguarded guard in which black then captures the interposing white piece and another piece interposes afterward to stop the check?

That is, we are looking for a position such that:

  • White is in check
  • White moves a piece to an empty square to stop the check
  • After moving the piece, that piece is unguarded
  • That piece is then captured by Black with check
  • White is still in check, and interposes another piece to an empty square to stop this second check.

Note the use of a "dummy square" d4, in conjunction with a :shift.

;;Find positions with white to move such that white is in check from a sliding piece and
;;on white's next move interposes a piece that is unguarded. 
;;Then black captures that piece in such a way that white remains
;;in check and white subsequently interposes another piece to stop the check

(match
 :pgn heijden.pgn
 :output out.pgn
 (position
  :wtm
  :moveto .d4
  :check
  :or
  ((position   :rayorthogonal ([qr] .d4 K))
   (position   :raydiagonal ([qb] .d4 K))
   )
	       
  :sequence
  ((position)
   (position :attackcount A Ad4 0
	     :movefrom [rqb] ; this might pick up some extra captures from the wrong piece
	     :moveto Ad4)		
   (position :check :moveto . :movefrom [QRBNP])
   )
  :shift :markall)
 )

In the Dobrescu example, dobrescu.cql, should :originalsamecount 0 be :originalsamecount 0 1 ?

This position filter was:

  (position
  Ke6 be7 be4 nd5
  :shift
  :flip
   :markall ; find each occurrence
  :relation (:pattern  ; only pay attention to the pieces we found
	     :shift ; allow shift
	     :flip ; allow flip
	     :originalsamecount 0 ; disregard identity matches
	     :samesidetomove ; same side to move
	     :variations ; look in variations
	     )
  )

It depends what you are looking for.

:originalsamecount 0
will find the Dobrescu study, for which this CQL file was written. It will not find positions that it is not designed to find. In particular, it will not find positions in which any of the pieces in the target overlap any of the pieces in the pattern. It is reasonable to use
:originalsamecount 0 1
as well, however. It all depends on what you are trying to find.

Try it both ways and see what new positions you get!

How can I look for a passed pawn on the b file?

Use this position filter

 (position Pb2 :piececount p[a-c3-7] 0 :shiftvertical :flipcolor)

Does :flipcolor affect :result?

No. Because CQL was originally designed to search for studies, and there are no 0-1 studies, this feature was not implemented.

How does one represent light-squared or dark-squared bishops?

The following can be cut-and-pasted into a CQL file, and is the piece designator for a light-squared white bishop:

B[a1,a3,a5,a7,b2,b4,b6,b8,c1,c3,c5,c7,d2,d4,d6,d8,e1,e3,e5,e7,f2,f4,f6,f8,g1,g3,g5,g7,h2,h4,h6,h8]

A dark-squared bishop is:

B[a2,a4,a6,a8,b1,b3,b5,b7,c2,c4,c6,c8,d1,d3,d5,d7,e2,e4,e6,e8,f1,f3,f5,f7,g2,g4,g6,g8,h1,h3,h5,h7]

See samecolorbishops for an example.

Why does CQL crash on a simple .cql file?

The only known cause of CQL crashing is due to a malformed PGN file. Some large chessbase databases do contain invalid games which, when converted to CQL, cause the crash. You can use the output of CQL to pinpoint the approximate location of the bad game and delete it manually.

The easiest way to do this is to view the output of the console, which prints a dot every 100 games. Suppose you have narrowed the crash so you know it occurss somewhere between game 650500 and 650700.

Then create a new .cql file like this:

(match :pgn baddatabase.pgn :output out.pgn
 :gamenumber 650499 650701
 (position)
)

Because CQL prints a message with the game number at every matched game, this will print the number of the last correct game matched; the number one higher than that is the invalid game. This game should then be deleted either from the PGN database or the Chessbase database (if you are using chessbase to generate the PGN) that has the corrupt game. If the latter you must then regenerate the PGN database.


ChessQuery Language Manual: http://www.rbnn.com/cql