Specifying chess variants in Sjaak

Sjaak comes with a number of build-in variants, but it's also possible to create your own without having to modify the program. Since revision 367, Sjaak comes with a "variants.txt" file, which contains a detailed description of how to define a variant as well as a number of examples.

To make the variants work in XBoard/WinBoard, all you have to do is specify the name of the file after the engine command:

./xsjaak variants.txt

You may need to enclose the entire command in quotes, and you may need to specify the full path to the file in order for Sjaak to find it. If the file is found succesfully, the variants listed in it will appear in Sjaak's option dialog box as variants that can be played as variant "fairy".

Format of the "variants.txt" file

Empty lines and anything following a # character are ignored.

To define a variant, begin a line with "Variant: gt;", then follow on subsequent lines with descriptions of the board, the pieces used and their movement, and other rules used in the variant.

The board and zones

The board size is specified by (files)x(ranks), for instance

Board: 8x8

defines a standard chess board. There are some limits on the size of a board: the number of files and ranks needs to be smaller than 16 and the total size of the board needs to be less than 128 squares. It is currently not possible to define boards that are smaller than 8x8 (this will be added eventually). For some of the rules, it's necessary to identify a part of the board. This is done by defining a "zone", which lists the squares on the board that are part of that zone.

For instance:

Zone: rank2 = a2,b2,c2,d2,e2,f2,g2,h2
Zone: rank8 = a8,b8,c8,d8,e8,f8,g8,h8

defines the 8th rank (rank8) of the board. Files are identified by letters, "a" being the first. Ranks are labelled by numbers, starting at "1". The square "a1" is in the lower-left hand side of the board. Two special zones, "empty" and "all", are pre-defined. As the names indicate, "empty" corresponds to an empty board while "all" corresponds to the entire board.

It's possible to exclude certain regions of the board. Moves are never generated from or to these squares:

Exclude: g1,h1,g2,h2,g3,h3,g4,h4,g5,h5,g6,h6,a7,b7,c7,d7,e7,f7,g7,h7,a8,b8,c8,d8,e8,f8,g8,h8

excludes the last two rows and the rightmost files on the board, effectively reducing the board to 6x6.

For some games, the victory (or drawing!) condition can be to occupy a specific region of the board. This is referred to here as "capture the flag". To enable this, a special zone has to be defined for each player, WhiteFlag for white and BlackFlag for black:

WhiteFlag: e1
BlackFlag: e8

The game ends when white captures and holds all black flags and vice versa.

Pieces

Piece descriptions start with a "Piece:" line. On following lines the piece move and special properties can be defined.

Movement types

In order to define new variants, it is important to know how to specify the movement of the pieces. Sjaak distinguishes three types of moves:

  • Sliders - move along a ray direction until they encounter another piece or the edge of the board
  • Leapers - perform single steps to specified target squares
  • Steppers - perform single (repeated) steps in a particular board direction

Each of these moves treats the board in a slightly different way, and so the description of moves for each is different:

Sliders move along a ray, either horizontal (H), vertical (V), diagonal (D) or anti-diaginal (A).

Examples:

slide (H,V) - describes a chess rook slide (A,D) - describes a bishop slide (H,V,A,D) - describes a queen

Leaper moves can become complicated, but in their simplest form they just specify the step-vector, which is then mirrored to give a total of up to 8 target squares.

Examples:

 leap (2,1)          # describes a knight
 leap (1,2)          # alternative description of a knight
 leap (1,1)          # describes a ferz
 leap (2,2)          # an elephant
 leap (1,0)          # a wazir
 leap (2,0)          # a dabbabah

The complications begin when a piece is a compound leaper, meaning it can choose between different leaper moves. For instance, a king can move as a ferz, or as a wazir:

 leap (1,0)|(1,1)    # a king

However, a leaper can also be a two-step leaper, which first moves as one type of leaper and then again as another type of leaper:

 leap (1,0)+(1,1)    # move as a wazir first and then as a ferz

Typically, this is useful to define lame leapers by also specifying a mask:

 leap ((1,0)+(1,1)) & (1,2)

describes a piece that moves first as a wazir (only to empty squares) and then again as a ferz. However, the final destination must be a square that could have been reached by a knight. In other words, this describes a piece that moves like a knight, but can be blocked. A Xiangqi horse.

For steppers, board directions are indicated by compass points, so "north" (the side of the board where black starts out), "south" (where white starts), "east" (the king-side, the direction of the H-file) and "west" (towards the A-file). Steppers are intended to be asymmetric (the move description is for white and mirrored for black),

 step N              # describes a piece that moves one square "north", a white pawn
 step S              # describes a piece that moves one square "south", a black pawn

Optionally, the direction can be prefixed with a number (1-7):

 step 2N             # the initial double step of a white pawn.

Steppers are normally used to define pawns, and a number of pawn-specific evaluation terms are only activated for pieces that are defined as stepper moves. Steppers also have their moves generated in bulk, one direction at a time (as opposed to one piece at a time), which impacts performance.

Finally, there are two variations to the three above movement types: hoppers and asymmetric leapers.

Hoppers are sliders that need to jump over another piece before they can move.

 hop (H,V)           # describes the capture move of a cannon in Xiangqi

Currently, capture is replacement only. It is not possible (yet) to define a piece that captures by leaping over its victim.

Asymmetric leapers are leapers that, as the name implies, move differently for white and black. Their syntax is similar to that of normal leapers, but instead of specifying the movement vector, it's necessary to specify each step:

 aleap (0,1)         # a piece that moves one square north for white and one square south for black (like a pawn)
 aleap (1,1)|(1,-1)|(-1,-1)|(-1,1)|(0,1) # a Makruk elephant or silver general
 aleap (1,1)|(-1,1)|(1,0)|(-1,0)|(0,1)|(0,-1) # a gold general
 

Moves and captures

A piece can have more than one movement type defined for it, simply by specifying them one after the other on separate lines:

 Move: slide (H,V,A,D)
 Move: leap (1,2)

defines the move for an Amazon. The move types must be different on each line, or the result will be undefined. If a capture move is not specified, it is assumed to be the same as the normal move. To disable captures for a particular piece type, specify "none":

 Capture: none     # Piece cannot capture
 

Special moves (double pushes)

For pieces that can perform special moves, it's necessary to specify both the move and the location on the board where they can make the special move. This is done by defining a zone and then referencing it from the piece description:

 Special: rank2, rank7, step 2N

defines the initial double step for a white pawn (on rank 2) and a black pawn (on rank 7). Special moves currently cannot be captures, and do not depend on whether the piece has moved or not.

Special moves (castling)

Castling is a special move where two friendly pieces move. It is only possible if neither of the two pieces has moved already. All squares between the initial and final positions of the two pieces must be empty (apart from the two pieces themselves). If the primary castling piece is royal, then all squares between the king's initial and final position must be "safe". To define a castling move, specify the (default) starting position of the king, the king's destination square and the secondary's (default) starting position. The secondary's destination square is derived from the king's move: if the king moves to the king-side (east side) of the board, the secondary moves to the left of the king. If the king moves to the queen-side (west side) of the board the secondary moves to the right of the king.

Example:

 Castle: white e1-g1 with h1     # Canonical king-side castling
 Castle: white e1-c1 with a1     # Canonical queen-side castling

To define FRC-style castling, simply define the "standard" castling rule (which provide the destination square for the king and the default location of the rook). The FRC rule will be based on this and the actual specified position of the king and rook in the startup FEN. Behaviour is undefined if all squares are not on one rank.

Restricting movement

It is possible to restrict the movement options of a piece by specifying the locations it is allowed to move to:

 Zone: white_palace = d1,e1,f1, d2,e2,f2, d3,e3,f3
 Zone: black_palace = d8,e8,f8, d9,e9,f9, d10,e10,f10

 Piece: King
 Move: leap (0,1)
 Symbol: "K", "K,k"
 Flags: royal
 Prison: white_palace, black_palace

Defines the XiangQi king, which is only allowed to move inside the palace.

Drops

For variants that include drops, the default rule is that pieces in-hand may be dropped anywhere on the board, as long as pieces are allowed to move from their new location. You can override this:

 Drop zone: all, all

allows pieces to be dropped everywhere, while

 Zone: rank1 = a1,b1,c1,d1,e1,f1,g1,h1
 Zone: rank8 = a8,b8,c8,d8,e8,f8,g8,h8

 Drop zone: rank1, rank8
restricts drops to the (own) back rank.

Specifying the drop zone in this way implicitly sets the "drop_dead" piece property (see below).

Promotions

Pieces promote as soon as they reach their promotion zone, to one of the possible promotion choices:

 Promotion: rank8, rank1, "QRBN"

defines the promotion for a white pawn on rank 8 and for a black pawn on rank 1. A promotion choice of "+" is treated in a special way: if the piece symbol is "P" and it has promotion choice "+", then the piece will be promoted to a piece with symbol "+P". It is your responsibility to make sure that this piece is defined in the game!

If capture/drop rules are used, pieces that have a symbol that starts with "+" will be demoted when captured.

Example:

 Piece: Queen
 Move: slide (D,A,H,V)
 Symbol: "+P", "+P,+p"

 Piece: Pawn
 Move: step N
 Capture: step NE,NW
 Special: rank2, rank7, step 2N
 Symbol: " ", "P,p"
 Flags: set_ep,take_ep
 Promotion: rank8, rank1, "+"

This example defines a Queen that will demote to Pawn when captured, and a Pawn whose only promotion choice is the Queen (+P)

By default, promotion is mandatory if the piece has no legal moves from a given square, otherwise it is optional. You can override this rule by specifying the optional promotion zone explicitly:

 Optional promotion: empty, empty

makes all promotions for this piece type mandatory.

Piece properties

Pieces can have a number of special properties, listed on a "Flags:" line. Multiple properties can be specified in one line, separated by a comma. The following properties can be specified:

royal this is a royal piece: the game is lost if a side were to lose all royal pieces.
set_ep this piece sets the "en-passant" capture square when it makes a special move.
take_ep this piece type can capture on the "en-passant" square.
drop_no_check this piece may not be dropped to give check.
drop_no_mate this piece may not be dropped to give mate (it may give check).
drop_one_file this piece may not be dropped on a file that already contains a friendly piece of the same type.
drop_dead This piece may be dropped even where it cannot move.
no_mate this piece may not deliver mate. It may deliver check.
shak this piece delivers a special "shak" check.

Limit the number of pieces

It is possible to limit the number of pieces of a particular type (by promotion) by specifying that number in a "Max: number" or "Max: white,black" line:

Max: 2

allows only two of this piece type for white and for black. You can set a different number for white and for black. Pass 0 to leave this at the default (whch is 1 for royal pieces and unlimited for all other piece types).

Extra rules and victory conditions

It's possible to specify a number of extra rule options or game-ending conditions. End-of-game scores can be any of "win", "loss", "draw" or "illegal".

The following game-ending conditions can be defined:

checkmate The enemy royal piece is under attack and cannot avoid being captured (win, loss or draw, normally win)
stalemate The enemy cannot make any legal moves (win, loss or draw, normally draw)
repeatN The game is declared a draw if a position occurs for the Nth time (win, loss or draw, normally draw and N = 3)
Set N=0 to disable any special treatment for repetitions.
perpetual As repeatN, but refers to in-check positions. If not specified defaults to "repeat" (win, loss, draw or repeat).
loneking Triggered if a side has a lone king remaining and baring rules are in effect (win, loss or draw, normally loss)
nopieces Triggered if the side-to-move has no pieces left (win, loss or draw, normally loss).
captureanyflag Triggered when capturing any flag (win, loss or draw, normally win).
captureallflags Triggered when capturing all flags (win, loss or draw, normally win).

Examples (these are the defaults):

 Rule: checkmate = win
 Rule: stalemate = draw
 Rule: repeat3 = draw
The following special rules can be defined:

taboo The kings may not share a ray with no pieces between them
keep capture Captured pieces are held in your hand (rather than just disappearing)
return capture Captured pieces are returned to their owner's hand
duplecheck If a side has more than one king, he is assumed to be in check if all of them are attacked. Without this rule a side with more than one king can never be in check.
allow pickup As a move you can take one of your non-royal pieces from the board into your hand.
allow drops As a move you may place a piece from your hand on the board.
force drops If you have a piece in-hand you must place one on the board.
gate drops You may "gate" pieces from your hand when first moving a back-rank piece.
promote here A piece that is in the promomotion zone may promote without making a move.
special init Special moves are only allowed if the piece has not moved before.
bare rule If you have a bare king, you have one turn to bare your opponent's king in turn.
chase rule Xiangqi-style chases are not allowed.
shak rule Checkmate can only be given if a chain of checks leading to it contains at least one "shak" check.

Piece names and symbols

Pieces can be assigned names and symbols. The piece name property is given on the "Piece:" line. It is an arbitrary string with no special meaning; SjaakII uses this when asked to list the rules and dump the internal board representation, but it is otherwise purely cosmetic.

The piece symbol is set using the "Symbol:" property:

 Symbol: "N", "N,n"

The first string ("N") is used for the output of moves in standard algebraic notation (SAN), for instance "Nf3". The second string ("N,n") identifies the symbol by which the piece is identified in a FEN string, first for white and then for black. Normally, the black character is just the lower case version of the white character, which is in upper case, but Sjaak doesn't require this. The SAN character is normally the same as the white symbol, but again this is not required.

There are two special symbols that have meaning when defining piece symbols:

If a piece symbol starts with "+", say "+P", then this piece will demote to "P" when captured, and a piece "P" will promote to this piece (if it has promotion choice "+").

If a piece symbol ends with "~", say "Q~", then this piece will demote to whichever piece type promotes to "Q~". Make sure that there is a piece type that lists "Q~" as a promotion option!

Piece visualisation (XBoard/WinBoard)

You can specify the piece graphic that is used by XBoard/WinBoard to represent the pieces in your variant. XBoard uses a string of 44 (2x22) characters in length. To use the N-th image you simply have to replace the N-th character in the string with the symbol you assigned to the piece. The first 22 characters are for white, the last 22 are for black.

The default value of the string is "PNBRQFEACWMOHIJGDVLSUKpnbrqfeacwmohijgdvlsuk", where the characters represent the following pieces:

 P=Pawn
 N=Knight
 B=Bishop
 R=Rook
 Q=Queen
 F=Ferz
 E=Alfil
 A=Archbishop
 C=Chancellor
 W=Wazir
 M=Man
 O=Cannon
 H=Nightrider
 I=Dragon Horse
 J=Dragon King
 G=Grasshopper
 D=Alternative Chancellor image
 V=Falcon
 L=Lance (or Amazon/Berolina pawn)
 S=Snake
 U=Unicorn
 K=King 

If you do not use a particular bitmap, simply put "." in its place. Example:

 XBoard pieces: "PNBRQFEACWMOHIJGDVLSUKpnbrqfeacwmohijgdvlsuk"

When specifying the string, you can write both "XBoard" and "WinBoard".

Example: FIDE chess

Variant: FIDE Chess (8x8)
Board: 8x8
FEN: "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq -"
XBoard pieces: "PNBRQKpnbrqk"
Zone: rank8 = a8,b8,c8,d8,e8,f8,g8,h8
Zone: rank7 = a7,b7,c7,d7,e7,f7,g7,h7
Zone: rank2 = a2,b2,c2,d2,e2,f2,g2,h2
Zone: rank1 = a1,b1,c1,d1,e1,f1,g1,h1

Piece: Knight
Move: leap (2,1)
Symbol: "N", "N,n"
Value: 320

Piece: Bishop
Move: slide (D,A)
Symbol: "B", "B,b"
Value: 325

Piece: Rook
Move: slide (H,V)
Symbol: "R", "R,r"
Value: 500

Piece: Queen
Move: slide (D,A,H,V)
Symbol: "Q", "Q,q"
Value: 950

Piece: King
Move: leap (0,1)|(1,1)
Symbol: "K", "K,k"
Flags: royal
Castle: white e1-g1 with h1
Castle: white e1-c1 with a1
Castle: black e8-g8 with h8
Castle: black e8-c8 with a8

Piece: Pawn
Move: step N
Capture: step NE,NW
Special: rank2, rank7, step 2N
Symbol: " ", "P,p"
Flags: set_ep,take_ep
Promotion: rank8, rank1, "QRBN"
Value: 100