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.)