Variables

Variables are sometimes useful for expressing certain complex ideas in a clearer or more succinct manner.

A user-defined variable, like x, $foo, or Pawn has a name and a value.

Variable names

A variable name is a sequence of allowed characters. An allowed character is an alphabetic character a-z or A-Z, a digit, or the characters $ or _. Variable names are case-sensitive: yes is different from Yes.

A (user-defined) variable name cannot be the same as a CQL keyword. The CQL keywords are listed in the index. In addition, a user-defined variable name cannot by the name of a piece specifier, like R, _ , Ba3, ab3, _c1 and so on.

Examples of legal variable names are:

  rook Rook bishop Bishop ...
  x y z // but not a or b
  $R $foo RR foo Foo
  this_is_a_legal_variable_name
Variable names beginning with the characters
__CQL
are reserved by CQL.

Variable values

There are four types of variables: numeric variables, set variables, piece variables and position variables. Once assigned, a variable cannot change its type.

In addition, numeric variables can be either persistent or normal: persistent values retain their value between games.

A variable must have been assigned a value before the variable is used, and (except for persistent variables) the value of a variable is unassigned before CQL begins parsing of a new game.

A variable is assigned using the = filter:

  x = 3 //numeric assignment
  y = find check  //position assignment
  z = . attackedby k //set assignment
  piece zz = N       // piece assignment

Numeric variables

A numeric variable holds an integer. The absolute value of this integer may not exceed a billion.

A numeric variable is defined by assigning it to a numeric filter using "=":

  x = #R

The variable x will hold the integer number of squares that have a white rook on them, that is, the number of white rooks in the current position.

A numeric variable is a numeric filter. Numeric variable can be compared using standard expressions.

    x+y<power R
    2*NumberRooks == NumberPawns
  

A numeric variable can be modified by using the operator assignments: +=, -=, /=, *=, and %=.

These modify the variable on the left according to the operator. For example,

x += 1

Is the same as

x = x+1

The other operators work the same way (the '%' operator is the modulus operator).

If var is a numeric variable and value is a countable filter, then the assignmet

    var = value
matches the current position only if value matches the current position. If the value matches the current position, then the value of var is set to the value of value. Otherwise, var is not modified.

Similar rules apply to operator assignments, which match the current position, and which modify the variable on their left hand side, only when their right hand side matches the current position.

A numeric variable always matches the current position, but CQL will signal an error if a numeric is used in a context where it is being tested only for whether it matches:

    x=3
    if x then y=4 // error: no reason to test if x matches 

Set variables

A set variable holds a set of squares and is a set filter. A set variable can be introduced in one of two ways:
  • Using the square filter, or
  • Using =.
A set variable introduced by the square filter is just an ordinary set variable which happens to hold a set of cardinality 1:

    square x in A
      x attacks k
  

In the above, x at any time holds a single square on which there is a white piece (and loops through all possible such squares).

If S is a set filter, then x = S assigns the set of squares represented by S in the current position to the variable x. For example:

    x= . attackedby R 
    y= move to _ legal 
    z=x | y 
    z=x&y 
  

When var is a set variable, then

    var = value
always matches the current position and always assigns to var the value of value, even if that value is empty. However,
    var =? value
will only match the current position (and will only change the value of the set variable var) when value is nonempty. This is how numeric and position assignments work, and is sometimes convenient.

Position variables

Position variables hold the identity of a particular position, which is a location in the game tree. Position variables are created by an assignment statement in which the right side is a position filter, of which the most common is currentposition:
z=currentposition
As with the other variable assignment statements, if the right side of the assignment expression does not match the current position, then neither does the assignment, and the variable is unchanged.

Piece variables

The most complex of the variable types is the piece variable. A piece variable holds the identity of a particular piece. Each individual piece on the chessboard is given a unique integer at the start of the game, called its piece id. The piece id of a piece does not change as the piece moves or promotes.

A piece variable however is a set filter. The piece variable is associated with a particular set of squares in any position as follows. Suppose the piece variable var holds a piece id of id. Then:

  • If the piece with piece id of id exists in the current position, then the value of var is the square on which that piece stands.
  • Otherwise, the value of var is the empty set.

Piece variables are introduced in one of two ways:

  • using the piece filter, like piece x in A ...;
  • using the piece assignment filter.

The piece assignment filter consists of the word piece, followed by the name of a variable, then an = sign, then a set filter, e.g.:

      piece x=N
      piece y=move from R
or in general
piece var = value
If value consists of exactly square, and that square is occupied by a piece, then var is set to hold the piece id of the piece occupying that square. Otherwise, var is unchanged and the piece assignment expression does not match the current position.

Piece variables are normally converted to their values as sets when they appear. For example, if x is a piece variable, then

N==x
matches the current position only if either there are no white knights in the position and the piece represented by x is not in the position; or if the piece represented by x in the current position is the only white knight in the position.

Piece variables can appear in two other contexts (other then in a piece filter or a piece assignment filter) and not be converted into their corresponding sets.

First, if a piece variable is passed to a comment filter, then the comment outputs its color and type, in addition to the square its on:

      piece x=K
      comment ("The king is " x)
will output the comment The king is Kd4 (assuming the king is on d4). by contrast, the code
      x=K // x is a set variable, not a piece variable
      comment ("The king is " x)
would output the comment The king is d4.

Second, like all variables, when a piece variable is an argument to a user-defined function, it is not converted to a set.

Persistent variables

If the first use (and only the first use) of a numeric variable in a CQL file is preceded by the keyword persistent, then the variable is persistent. A persistent variable is initialized to 0 and retains its value between games. After all the games are read, the values of all persistent values are output to standard output.

Persistent variables cannot be used when multithreading is enabled. (This is because the value of a persistent variable depends upon the value of that variable in previously parsed games, and in multithreaded mode CQL parses different games simultaneously.) CQL automatically runs in single-threaded mode if any persistent variables are used in the CQL file).

An example of using persistent variables is in the example file persistent.cql.

Scoping

The value of a variable cannot be accessed before it is defined. Once defined, the variable retains its type, but not necessarily its value, as the program progresses.