OTEP - OpenTafl Engine Protocol The OpenTafl Engine Protocol is a bidirectional communications protocol used by OpenTafl to communicate with external tafl engines. For simplicity, it uses piped text input and output, with human-readable commands. OpenTafl sends all commands using the US-ASCII character set, and expects to receive responses in the same. Commands will be separated by the newline character \n. Anywhere an ordering of commands is specified in this document, that ordering is guaranteed. To avoid complicated bookkeeping, commands are unacknowledged. 1. External engine .ini file OpenTafl requires that external engines provide an .ini file containing basic configuration information. The file must contain a section with the [engine] heading, and entries with the names 'directory', 'filename', and 'command'. It may optionally contain an entry named 'arguments' and an entry named 'name'. 'directory' must contain the path to the directory in which your engine is installed, relative to /engines. It is recommended to install your engine in a subdirectory of /engines. 'filename' must contain the name of your engine's executable file inside the directory specified in 'directory'. This entry is used to verify that your engine file exists and can be accessed by OpenTafl. 'command' must contain the command used to run your engine. OpenTafl will execute it, using the directory specified in 'directory' as the working directory. 'arguments' need not be present. If it is, its contents will be treated as command-line arguments to your engine. 'name' need not be present. If it is, its contents will be displayed as your AI's human-readable name. See the opentafl.ini file in any distribution of OpenTafl for an example. 2. Simple Algebraic Tafl Notation Since both OpenTafl and the external engines maintain game state, detailed notation is unnecessary. Therefore, OpenTafl by default uses a very simple move notation: the starting space, a dash, and the finishing space: 'a4-a1'. OpenTafl can be configured to use full OpenTafl move notation, if desired. 3. Analysis vs. play If a player is playing against an external AI engine, and has configured that same AI engine to provide game analysis, by convention, OpenTafl will run two instances of that engine. One will be solely dedicated to gameplay, and the other will be solely dedicated to analysis. If your engine receives a 'play' command, you may assume that it will not be used for analysis. If your engine receives an 'analysis' command, it will not be used for play. Engines used for analysis may receive multiple 'rules' commands, and, when a player requests a position analysis, will receive a 'position' command and a 'side' command to set up the correct game state. If a player has configured an external AI engine as an opponent, or for analysis, and is viewing a replay, OpenTafl will initialize the AI engine at the start of the replay, and send 'position' and 'side' commands as the player moves through the replay, so that attached AI engines are always aware of the current game state. 4. hello Direction: Engine <-> OpenTafl Command: 'hello' Alerts OpenTafl that the engine is active. Send 'hello' once your engine has started. If your engine has not sent a 'hello' command after five seconds, OpenTafl will assume that your engine failed to start, and will stop any game in progress and alert the user. 5. simple-moves Direction: Engine -> OpenTafl Command: 'simple-moves ' Default: on When set to on, OpenTafl provides the external engine with simple move records. When set to off, OpenTafl provides full OpenTafl Algebraic Tafl Notation. 6. rules Direction: OpenTafl <-> Engine Command: 'rules [rules-string]' OpenTafl provides the engine with an OpenTafl Notation Rules string, as defined in the OpenTafl Notation specification. See the OpenTafl Notation spec for defaults and other required implementation details. When receiving a 'rules' command, the engine should initialize to the starting board position. If the engine sends a 'rules' command, OpenTafl will reply with a 'rules' command; in this case, initialize to the starting board position only if the game has not yet begun. (You may assume that the game has begun if your engine has received a 'play' command or an 'opponent-move' command.) 7. position Direction: OpenTafl <-> Engine Command: 'position [position-record]' OpenTafl provides the engine with an OpenTafl Notation Position string, as defined in the OpenTafl Notation specification, representing the current game state. OpenTafl will not send unsolicited position commands unless the engine is being used for game analysis, or during replay viewing. Engines playing as opponents must send a 'position' command to receive a 'position' command. 8. side Direction: OpenTafl <-> Engine Command: 'side [attackers|defenders]' OpenTafl informs the engine which side it is to play for. OpenTafl will send side commands to engines in analysis mode and during replays only. Engines being used for gameplay will be given the side to play in the 'play' command. 9. clock Direction: OpenTafl <-> Engine Command: 'clock [[*] [*] ]' OpenTafl provides the engine with the time left for both players in milliseconds. If overtime timing is enabled, also provides the length of each overtime period in seconds, and how many overtime periods the attacker and defender have left. If main time has expired, [attacker-millis] or [defender-millis] will list the amount of time remaining in the current overtime period, followed by an asterisk. OpenTafl will send clock commands at four times: 1. At the start of every turn, immediately following the 'play' command. 2. When main time expires. 3. When an overtime period expires. 4. Immediately before asking an engine used for analysis to analyze a position. 10. analyze Direction: OpenTafl -> Engine Command: 'analyze ' OpenTafl instructs the engine to analyze the current position, returning the given number of possible moves with evaluations (see 'analysis') and taking up to the given amount of time. Engines are not required to return exactly [number] moves, provided they return at least one move. At their discretion, engines may use less than the given limiting time. 11. analysis Direction: Engine -> OpenTafl Command: 'analysis [ ]...' The engine should provide [number] move-list and evaluation pairs. A move-list is a list of moves in simple algebraic tafl notation or OpenTafl algebraic tafl notation (see OpenTafl Notation specification for details), which leads from the current game state to the deepest state searched, separated by the pipe character: '|'. The move-list should include no spaces. The evaluation is the engine's overall evaluation of the move which starts the move-list. Engines are not required to return a full move list, and may elect to simply provide the first move in the list (the move which exits the current game state). 12. play Direction: OpenTafl -> Engine Command: 'play ' OpenTafl instructs the engine to play for the given side from the current board state. The game clock runs from the moment the OpenTafl sends the 'play' command to the moment that OpenTafl receives the 'move' command. 13. move Direction: Engine -> OpenTafl Command: 'move ' The engine submits the given move to OpenTafl. If the move is made successfully, OpenTafl returns a 'move' command. If the move is not successful, OpenTafl returns an 'error' command. See 'error' and 'opponent-move' below. 14. move Direction: OpenTafl -> Engine Command: 'move ' The move the engine last submitted to OpenTafl completed successfully. The position record provided is the board state following your move. 15. error Direction: OpenTafl <-> Engine Command: 'error [message]' OpenTafl will send errors for incorrectly-proposed moves. OpenTafl can receive two kinds of error messages from the engine. A non-critical error will be presented to the user, and the game will continue. A critical error will be presented to the user, and the game will end. Errors initiated from OpenTafl will never include a message. Errors initiated from the engine should include a message, which will be displayed to the user. Error code can be one of the following: Engine -> OpenTafl: -1: critical error 0: non-critical error OpenTafl -> Engine: 1: wrong side 2: illegal move (blocked or off the board) 3: berserk mode wrong side (side from last turn moves again: berserk mode) 4: berserk mode illegal move (attempted to move a non-berserking taflman) 16. opponent-move Direction: OpenTafl -> Engine Command: 'opponent-move ' OpenTafl informs the engine that the other side has made a move, given as [move-list] in whichever algebraic tafl notation the engine is configured to use. [position-record] gives the current state of the board. [move-list] is a string of move records separated by the pipe character '|', and will only be more than one move in the case of berserk tafl and berserk moves. Moves are listed from oldest to newest. [position-record] is always the state of the board at the end of the move list. OpenTafl will always send an 'opponent-move' command immediately before a 'play' command, even if the 'play' command is a repeat after an 'error' command. Note that, in case of an erroneous move, OpenTafl will send three commands: 'error', 'opponent-move' (containing the prior move, and the correct board position), and 'play'. 17. finish Direction: OpenTafl -> Engine Command: 'finish ' OpenTafl informs the engine that the game has ended. Result codes: 0: exit before victory 1: draw 2: attackers win 3: defenders win 18. goodbye Direction: OpenTafl -> Engine Command: 'goodbye' OpenTafl informs the engine that it may safely shut down. 19. status Direction: Engine -> OpenTafl Command: 'status [text]' All text between the end of 'status' and the next newline character will be output to the OpenTafl status display.