Game file format

(The file format is still evolving -- there will be changes in the future. In case you need it, here's the old file format.)

I first give the generic part of the format, common to all games. Then I give the game-specific formats (Hex, Twixt, ...).

In the future, I plan to extend the format in at least two ways:


Generic (non-game-specific) format
----------------------------------

[Game file] =       [key-val list] [(root) node]

                    (Global game parameters (player names, board size, etc.), followed
                    by the game tree.)

[key-val list] =    [key-val pair] [key-val pair] ... [zero-byte]

                    (A list of key-value pairs.  List terminated by a zero byte.)

[key-val pair] =    [1 unsigned byte giving length of key string]
                    [key string (NOT zero-terminated)]
                    [4 byte integer in "network" order giving length of value]
                    [the value]
                    
                    (Examples: 'bdsize' => 10 would be encoded as the bytes
                    {\x06 'b' 'd' 's' 'i' 'z' 'e' \x00 \x00 \x00 \x01 \x0a}.
                    'player1' => 'vvvjv' would be {\x07 'p' 'l' 'a' 'y' 'e' 'r' '1'
                    \x00 \x00 \x00 \x05 'v' 'v' 'v' 'j' 'v'}.)

Note: The format of the value depends on the key.  Currently in use are:

    'gtv' - Game Tree (file format) Version; 4-byte integer (current
               value = 2); required
    'player1' - string; name of first player; optional
    'player2' - string; name of second player; optional
    'name' - string; name of game; optional
    'pov' - point of view for displaying 'good' and 'bad' moves (0 = alternate (default),
                1 = Player 1, 2 = Player 2); 1-byte integer; optional

In addition, there are game-specific keys (e.g. board size; see below).


[node] =            [node-key-val list]
                    [number of child nodes (2 byte network unsigned short integer)] 
                    [child node 1] [child node 2] ...

[node-key-val list] = [node-key-val pair] [node-key-val pair] ... [zero-byte]

                      (A list of key-value pairs.  List terminated by a zero byte.)

[node-key-val pair] = [1 unsigned byte giving length of key string]
                      [key string (NOT zero-terminated)]
                      [2 or 4 byte integer giving length of value]
                      [the value]
                    
                      (The third item (length of value field) is a 2-byte, network, 
                      unsigned, short integer, unless the key is 'c' (comment),
                      in which case it is a 4 byte integer.  (In other words, the
                      maximum length of a comment is 2-gigabytes (31 bits), not
                      64 kbytes (16 bits).))


For a node the keys are:

    'm' - the move; length and format depend on the specific game (see below)
    'r' - value of the position; signed 2-byte short integer in network order;
            current convention is that 10000 means player 1 wins, -10000 means
            that player 2 wins, 0 means an even position, 0 < x < 10000 means a
            favorable position for player 1, 12345 means undetermined; this key
            is optional
    'g' - 1 byte boolean; true means that this is the move is the main
            variation from its parent (typicially, the move played in an actual
            game); optional
    'c' - string, 4 byte length then the string itself without terminating 0 byte;
            the comment associated to this node; optional


Hex Specifics
-------------

For a Hex Game Tree File, there are the following additional header fields:

    'hgtv' - Hex Game Tree Version; 4-byte integer (current value = 1); required
    'bdsize' - board size; 4 byte integer; required
    'type' - string identifying type of file: 'hex1'

Hex moves are always 3 bytes long:

[Hex game move] =    [x-coordinate (1 unsigned byte); 0...bdsize-1]
                     [y-coordinate (1 unsigned byte); 0...bdsize-1]
                     [color (1 unsigned byte); 1 for player 1, 2 for player 2]


Twixt Specifics
---------------

For a Twixt Game Tree File, there are the following additional header fields:

    'tgtv' - Twixt Game Tree Version; 4-byte integer (current value = 1); required
    'bdsize' - board size; 4 byte integer; required
    'type' - string identifying type of file: 'twixt1'

There are 2 kinds of Twixt moves: "short" and "long".  Short moves are always
3 bytes long, while long moves are always more than 3 bytes long.  Thus one knows
what kind of move follows after reading the length field.

[Short twixt game move] =  [x-coordinate of peg (1 unsigned byte); 0...bdsize-1]
                           [y-coordinate of peg (1 unsigned byte); 0...bdsize-1]
                           [color (1 unsigned byte); 1 for player 1, 2 for player 2]

                           (For short moves, all available links to the new peg
                           are made.)

[Long twixt game move] =   [x-coordinate of peg (1 unsigned byte); 0...bdsize-1]
                           [y-coordinate of peg (1 unsigned byte); 0...bdsize-1]
                           [color (1 unsigned byte); 1 for player 1, 2 for player 2]
                           ['pbem_null'; 1 byte boolean; see below]
                           [number of removed links; 2 byte unsigned short integer]
                           [list of removed links]
                           [number of added links; 2 byte unsigned short integer]
                           [list of added links]

                           (Total length of a long move is
                           3 + 2 + 3*num_removed_links + 2 + 3*num_added_links.
                           
                           If pbem_null is false, then links on the remove list
                           are removed, links on the add list are added, and that's
                           it -- no implicit links are added.
                           
                           If pbem_null is true, then links on the remove list are
                           removed, and afterwards all available links to the new peg
                           are made.  The list of added links should be zero-length in
                           this case.  Whether or not it is zero-length, it is ignored.)
                           
[list of links] =          [link] [link] ...

[link] =                   [x-coordinate of bottom peg (1 unsigned byte)]
                           [y-coordinate of bottom peg (1 unsigned byte)]
                           [link direction; 1 byte: 1, 2, 3 or 4]
                           
                           (The bottom peg is the one closest to the bottom of the
                           board.  (The upper left corner of the board is at x=0, y=0.)
                           This is not necessarily the peg placed on this move.
                           Directions: 1 means x+2, y-1, 2 means x+1, y-2,
                           3 means x-1, y-2, 4 means x-2, y-1.  In other words,
                           direction 1 points to 2 O'clock from the bottom peg,
                           2 points to 1 O'clock, 3 points to 11 O'clock, and 4
                           points to 10 O'clock.)