Skip to content

UniversalHiveProtocol

Jon Thysell edited this page Feb 24, 2021 · 27 revisions

Draft Proposal

Table of Contents

Introduction

The Universal Hive Protocol (UHP) is an open communication protocol for software versions of the board game Hive. The UHP is inspired by the Universal Chess Interface and Chess Engine Communication protocols used by chess software.

The goal of the UHP is to provide an easy method for developers to make their Hive-playing software inter-compatible with other Hive-playing software.

Engines vs Viewers

The UHP starts by distinguishing between two primary types of software: engines and viewers. Each has their own responsibilities and rely on the UHP to communicate with one another. Broadly speaking, an engine is the program that understands how to play a game of Hive, while a viewer is a program that makes it easy for humans to interact with an engine.

UHP Engines

A UHP-compliant engine is responsible for all of the logic necessary to play a complete game of Hive.

This means knowing the current state of the game, including:

  • What the hive currently looks like (what pieces are where)
  • Whose turn it is
  • What moves are valid
  • What is the history of moves already played
  • Whether or not the game is over

An engine must also be able to have actions taken upon it, including:

  • Starting a new game
  • Playing moves
  • Undoing moves

Lastly, a UHP-compliant engine must be able to recommend a "best" move to be played, given the current state of the game.

In total, a user should be able to play a complete game of Hive with nothing but a UHP-compliant engine. More specifically, an engine is UHP-compliant if it implements all of the responsibilities listed above (and a little bit more) by accepting specific textual Engine Commands as input and returning the correct textual output.

Typically (but not necessarily), a UHP-compliant engine is provided as simple command-line application that takes in the commands from the standard input and outputs the correct result to the standard output.

UHP Viewers

A UHP-compliant viewer is responsible for providing a human-friendly interface for players to interact with one or more UHP-compliant engines.

This means displaying the state of the game, including:

  • Displaying a graphical representation of the hive
  • Displaying each player's reserve pieces (in hand)
  • Displaying whose turn it is
  • Displaying the history of moves so far
  • Displaying whether or not the game is over

A viewer must also take input from the player, including:

  • Allowing players to start a new game
  • Allowing players to specify their next move
  • Allowing players to specify that they wish to undo a move

Lastly, a viewer should allow the user to specify that one or both players should be played automatically "by the computer".

In total, a viewer acts not only as a convenient interface for an engine, but should rely entirely on the engine for managing the state of the game. More specifically, a viewer is UHP-compliant if it implements all of the responsibilities listed above by taking user input and sending the specific textual Engine Commands to an engine, and using the engine's output to update the interface.

Typically (but not necessarily), a UHP-compliant viewer is provided as graphical application that, given a command-line UHP-compliant engine, takes user inputs (in the forms of mouse clicks, taps, or key presses) sends the correct commands to the standard input of the engine, then, reading the engine's standard output, makes the appropriate updates to the display.

Engine Commands

Engine commands are formatted as a single command keyword followed by zero or more command parameters. To be fully UHP-compliant, a engine must implement all of the commands as specified in this section.

Most commands output one or more lines of result text, but all must output ok on a new line after completion to signal that completion back to the viewer.

info

info

The info command asks the engine to return its identifier string, optionally followed by a list of capabilities that the engine supports. All engines are required to output the result of the info command automatically after starting, so that the viewer can immediately know: what engine is running, what capabilities it supports, and that the engine is ready for commands.

The identifier string is given with id followed by a space, followed by the name of the engine. For an engine with no capabilities to declare, the result of the info command might look like this:

info
id MzingaEngine v0.10
ok

If the engine does have capabilities to declare, they should be returned as a one-line, semi-colon separated list after the identifier string. Here is the current list of recognized capability flags:

Flag Description
Mosquito The engine supports games with the mosquito expansion piece.
Ladybug The engine supports games with the ladybug expansion piece.
Pillbug The engine supports games with the pillbug expansion piece.

Example (where the engine supports all expansion pieces):

info
id MzingaEngine v0.10
Mosquito;Ladybug;Pillbug
ok

newgame

newgame
newgame GameTypeString
newgame GameString

The newgame command asks the engine to start a new base game with no expansion pieces and should return a GameString. If a GameTypeString parameter is provided, the engine should start a new game of the type specified. If a GameString parameter is provided, the engine should load the exact game as specified.

Example without parameters:

newgame
Base;NotStarted;White[1]
ok

Example with GameTypeString:

newgame Base+MLP
Base+MLP;NotStarted;White[1]
ok

Example with GameString:

newgame Base;InProgress;White[3];wS1;bG1 -wS1;wA1 wS1/;bG2 /bG1
Base;InProgress;White[3];wS1;bG1 -wS1;wA1 wS1/;bG2 /bG1
ok

play

play MoveString

The play command asks to engine to play the specified MoveString and should return the updated GameString if successful.

Example:

newgame
Base;NotStarted;White[1]
ok
play wS1
Base;InProgress;Black[1];wS1
ok

pass

pass

The pass command asks the engine to play a pass move and should return the updated GameString if successful. It is the equivalent of play pass.

validmoves

validmoves

The validmoves command asks the engine for every valid move for the current board, returned as a semi-colon separated list of MoveStrings.

Example:

newgame
Base;NotStarted;White[1]
ok
validmoves
wS1;wB1;wG1;wA1
ok

bestmove

bestmove time MaxTime
bestmove depth MaxDepth

The bestmove command asks the engine's AI for the best move on the current board with the specified depth or time limit, and returns the MoveString for that move. The engine may optionally return moves incrementally as it thinks, as long as each MoveString is presented on its own line.

When using bestmove time, MaxTime is the engine's time limit to think, and it should be in the format hh:mm:ss.

Example with a 5 second time limit:

newgame
Base;NotStarted;White[1]
ok
bestmove time 00:00:05
wS1
ok

When using bestmove depth, MaxDepth is the number of plies (moves or turns) to look ahead, and should be a non-negative integer value.

Example with a two ply limit:

newgame
Base;NotStarted;White[1]
ok
bestmove depth 2
wS1
ok

undo

undo [MovesToUndo]

The undo command asks the engine to undo one or more previous moves and should return the updated GameString if successful.

Example without MovesToUndo:

newgame
Base;NotStarted;White[1]
ok
play wS1
Base;InProgress;Black[1];wS1
ok
undo
Base;NotStarted;White[1]
ok

Example with MovesToUndo:

newgame
Base;NotStarted;White[1]
ok
play wS1
Base;InProgress;Black[1];wS1
ok
undo 1
Base;NotStarted;White[1]
ok

options

options
options get OptionName
options set OptionName OptionValue

The options command asks the engine to list, get, or set options or settings for the engine. Note that the UHP does not prescribe any particular options that an engine must have - it is perfectly acceptable for an engine to not have any options that can be set by the user.

Using options without any parameters should return a list of options. If the engine has no options, it should simply return the standard ok line.

Example for an engine without any options:

options
ok

Otherwise, engines can expose options in any of the four following types:

OptionType Description
bool The option is boolean (either True or False).
int The option is an integer (whole) number within a specified range.
double The option is a floating-point (decimal) number within a specified range.
enum The option is a string from a list of specified strings.

Using options should then return each option on its own line in the following semi-colon separated format:

OptionType Format
bool OptionName;bool;OptionValue;DefaultValue
int OptionName;int;OptionValue;DefaultValue;MinValue;MaxValue
double OptionName;double;OptionValue;DefaultValue;MinValue;MaxValue
enum OptionName;enum;OptionValue;DefaultValue;PossibleValue1;PossibleValue2;PossibleValueN

As you can see, all of the lines start with OptionName;OptionType;OptionValue;DefaultValue. OptionName is the name of the option, OptionType is the type of the option, OptionValue represents the current value for that option, and DefaultValue represents the default value for the option. Note that OptionNames must not contain any spaces or semi-colons.

For the bool type, the only acceptable values are True or False. A viewer could choose to represent such options in the UI as check-boxes, toggle switches, etc.

For the int and double types, MinValue and MaxValue represent the (inclusive) minimum and maximum values that the option will accept. A viewer could choose to represent such options in the UI as numeric text boxes, sliders, etc.

For the enum type, you simply list each possible values separated by a semi-colon. There is no limit to the number of possible values you can specify. A viewer could choose to represent such options in the UI as a drop-down boxes, radio buttons, etc.

Example with multiple option types:

options
MaxBranchingFactor;int;500;500;1;500
MaxHelperThreads;enum;Auto;Auto;Auto;None;1;2;3;4;5
PonderDuringIdle;enum;SingleThreaded;SingleThreaded;Disabled;SingleThreaded;MultiThreaded
TranspositionTableSizeMB;int;32;32;1;1024
ReportIntermediateBestMoves;bool;False;False
ok

Using options get OptionName should return the same result, but only the line of the single OptionName specified.

Example:

options get MaxBranchingFactor
MaxBranchingFactor;int;500;500;1;500
ok

Using options set OptionName OptionValue should set the value of OptionName to OptionValue and then return the same single line result.

Example:

options set MaxBranchingFactor 25
MaxBranchingFactor;int;25;500;1;500
ok

Common String Definitions

The following string types are used by multiple engine commands, either taken as input parameters or returned as output results.

GameString

A GameString describes the complete state of the game. It is composed of various other strings joined by semi-colons, and is intended to include all of the information a viewer needs to display the game to the user. It should start as follows:

GameTypeString;GameStateString;TurnString

After that there should be a semi-colon followed by a semi-colon separated list of MoveStrings for every move that has occurred so far in the game.

GameTypeString;GameStateString;TurnString;MoveString1;MoveString2;MoveStringN

Note that there should be no trailing semi-colon at the end of the GameString.

Examples:

Base;NotStarted;White[1]
Base;InProgress;Black[1];wS1
Base;InProgress;White[2];wS1;bS1 wS1-

GameTypeString

A GameTypeString identifies the expansion pieces (if any) available in the current game. All GameTypeStrings start with Base, and if there are any expansion pieces, a single + and any combination of: M for Mosquito, L for Ladybug, P for Pillbug.

Examples:

Base
Base+M
Base+L
Base+P
Base+ML
Base+MP
Base+LP
Base+MLP

GameStateString

A GameStateString represents whether the game is in progress or not, and can be any of the following values:

GameStateString Description
NotStarted The game has not started, no moves have been made.
InProgress The game is in progress, at least one move has been made.
Draw The game is over, the result is a draw.
WhiteWins The game is over, the white side has won.
BlackWins The game is over, the black side has won.

TurnString

A TurnString represents which side's turn it is, as well as the turn number. The string starts with the color of the current side's turn, White or Black. After that is the turn number inside of square brackets [ and ].

Examples in order of moves:

White[1]
Black[1]
White[2]
Black[2]

Note that the turn number starts at 1, and that each side gets to play a move before the turn number increments.

MoveString

A MoveString represents a piece to be moved and the destination position on the board where the piece should be moved to. UHP uses the (de-facto) standard move notation developed by BoardSpace. The notation assumes you're looking down at the board and that the top of the pieces are pointed (not flat).

The string starts with the piece to move's short name, followed by a space, followed by a position relative to another piece on the board. The piece's short name is simply the piece's color w for white or b for black, followed by a single letter representation of the piece's bug type, and a number when a player has multiple bugs of that type, indicating the order in which the piece was initially played.

Short Name Description
wQ / bQ The white/black player's Queen Bee piece.
wS1 / bS1 The white/black player's first Spider piece played.
wS2 / bS2 The white/black player's second Spider piece played.
wB1 / bB1 The white/black player's first Beetle piece played.
wB2 / bB2 The white/black player's second Beetle piece played.
wG1 / bG1 The white/black player's first Grasshopper piece played.
wG2 / bG2 The white/black player's second Grasshopper piece played.
wG3 / bG3 The white/black player's third Grasshopper piece played.
wA1 / bA1 The white/black player's first Soldier Ant piece played.
wA2 / bA2 The white/black player's second Soldier Ant piece played.
wA3 / bA3 The white/black player's third Soldier Ant piece played.
wM / bM The white/black player's Mosquito expansion piece.
wL / bL The white/black player's Ladybug expansion piece.
wP / bP The white/black player's Pillbug expansion piece.

The relative position is given by listing the other piece's short name (near the destination), and (usually) prepending or appending one of three relative direction indicators: - / \

MoveString Description
bS1 wS1/ Place the first black spider on the top right edge first white spider.
bS1 wS1- Place the first black spider on the right-hand edge of the first white spider.
bS1 wS1\ Place the first black spider on the bottom right edge of the first white spider.
bS1 /wS1 Place the first black spider on the bottom left edge of the first white spider.
bS1 -wS1 Place the first black spider on the left-hand edge of the first white spider.
bS1 \wS1 Place the first black spider on the top left edge of the first white spider.

For the first move of the game, simply state the piece being played.

MoveString Description
wS1 White started the game by placing the first white spider.

For moving pieces on top of the hive (as the beetle, or the mosquito adopting the Beetle's movement), simply state the target piece that is about to be covered.

MoveString Description
wB1 wS1 Move the first white beetle on top of the first white spider.

A passing move (made because a side has no other moves) is simply pass. (Some users of this notation do not indicate when passes have occurred, but this protocol requires it).

MoveString Description
pass The player had no valid moves and passed their turn.

Note, because the positioning notation is relative in nature, it is possible that two different MoveStrings can describe the same actual move.

Error Handling

Occasionally a user may input bad command into the engine, and the engine may wish to message the user that an error has occurred. The engine should respond with err followed by a message string (typically a description of the error), and as with any command, the final line should be an ok.

Example:

hi
err Invalid command. Try 'help' to see a list of valid commands.
ok

In the special case that the user is trying to play an illegal move, the engine may use invalidmove instead of err.

Example:

newgame Base
Base;NotStarted;White[1]
ok
validmoves
wS1;wB1;wG1;wA1
ok
play wQ
invalidmove You can't play your Queen Bee on your first turn.
ok

In the event of an error, engines can return multiple output lines of text before the final ok. Viewers should display all message strings from the err and invalidmove output lines to the user.