Rolling dice
Posted: Wed May 27, 2020 10:07 am
Some chess variants use dice or cards to introduce a random element. E.g. in medieval chess one sometimes used a die to determine which piece type had to be moved. Contemporary chess variants that use dice (and are popular amongst AI researchers) are Dice (mini-)Shogi (where a dice roll determines what file your move has to end in), and Einstein Würfelt Nicht. (Although one can argue whether the latter really is a chess variant.) Other variants involve randomization that is more like drawing cards: in Dark Chines Chess all piece (which are flat disks) start shuffled face down, and are only flipped open when you first move them. Which would be equivalent to determining their type by drawing a card at that time. The commercial variant Raindrop Chess starts with an empty board, and instead of moving a piece you can draw a card to determine which piece you must drop on the board. (But you cannot capture before your King is placed.)
GUIs so far only offered the possibility to either let the engine simulate a virtual dice roll, or have it ask for the human opponent to roll a physical die, and enter the result. The latter is slow and not automated, and both methods offer the possibility for cheating, either by the engine or by the user. So it would be better to outsorce a virtual dice roll to a trusted referee, the GUI.
To make this possible I extended CECP ('WB protocol') with a few commands. (See http://hgm.nubati.net/CECP.html for a tentative new specs document.) An engine can send "dice N" to the GUI to request the roll of an N-sided die, to which the GUI will then reply with 'pips K/N', where K = 1...N the outcome of the virtual roll. In engine-engine mode this 'pips' command would go to both engines, so that the opponent can verify whether the followng move complies with the outcome K, and whether there was no cheating with regard to N. The commands can also be used to request rolling several dice at once (e.g. "dice 6 8 4" could be replied to with "pips 1/6 5/8 4/4").
Only engines that printed "feature dice=1" at startup will get the 'pips' command when their opponent rolls the dice. Engines should not send the 'dice' command to GUIs that have not accepted this feature first. In engine-engine mode the 'dice' command of the engine not on move will be ignored, so that engines can always ask for dice roll on behalf of their opponent (which is convenient when the opponent is human).
In engine-human games it is important that (of course) the user can see what the GUI rolled on his behalf. In the implementation I made in XBoard this is shown in the title bar of the board window. But it accumulates the info from all 'pips' commands sent during that turn, to prevent cheating of the form where an engine would keep requesting dice rolls until it gets an outcome that is favorable, giving the user no time to notice the earlier outcomes. Also, during the user's turn, the accumulated outcomes of the previous engine turn remain in view, to prevent an engine could mask what it has done by moving instantly and requesting a dice roll for the human opponent. I tested the implementation with my Einsten Würfelt Nicht engine Pips.
The new specs also propose commands for drawing cards, similar in spirit to the dice/pips protocol. I have not implemented that yet. The situation here is a bit complex, because card draws are not independent events. So you cannot alternate draws of decks of different size like you can switch rolling dice of different size; once a deck of a certain size is used, its new state must be remembered for the rest of the game. There also is the issue of whether both players draw from the same deck, or each have their own. And finally, it makes sens to allow the players to put cards back into the deck. A first XBoard implementation will probably allow each player to use only a single deck; the engine has to specify the size of it when he draws a card, and stick to the same size for the duration of the game. By specifying negative size you can draw from the deck that formally belongs to the opponent.
GUIs so far only offered the possibility to either let the engine simulate a virtual dice roll, or have it ask for the human opponent to roll a physical die, and enter the result. The latter is slow and not automated, and both methods offer the possibility for cheating, either by the engine or by the user. So it would be better to outsorce a virtual dice roll to a trusted referee, the GUI.
To make this possible I extended CECP ('WB protocol') with a few commands. (See http://hgm.nubati.net/CECP.html for a tentative new specs document.) An engine can send "dice N" to the GUI to request the roll of an N-sided die, to which the GUI will then reply with 'pips K/N', where K = 1...N the outcome of the virtual roll. In engine-engine mode this 'pips' command would go to both engines, so that the opponent can verify whether the followng move complies with the outcome K, and whether there was no cheating with regard to N. The commands can also be used to request rolling several dice at once (e.g. "dice 6 8 4" could be replied to with "pips 1/6 5/8 4/4").
Only engines that printed "feature dice=1" at startup will get the 'pips' command when their opponent rolls the dice. Engines should not send the 'dice' command to GUIs that have not accepted this feature first. In engine-engine mode the 'dice' command of the engine not on move will be ignored, so that engines can always ask for dice roll on behalf of their opponent (which is convenient when the opponent is human).
In engine-human games it is important that (of course) the user can see what the GUI rolled on his behalf. In the implementation I made in XBoard this is shown in the title bar of the board window. But it accumulates the info from all 'pips' commands sent during that turn, to prevent cheating of the form where an engine would keep requesting dice rolls until it gets an outcome that is favorable, giving the user no time to notice the earlier outcomes. Also, during the user's turn, the accumulated outcomes of the previous engine turn remain in view, to prevent an engine could mask what it has done by moving instantly and requesting a dice roll for the human opponent. I tested the implementation with my Einsten Würfelt Nicht engine Pips.
The new specs also propose commands for drawing cards, similar in spirit to the dice/pips protocol. I have not implemented that yet. The situation here is a bit complex, because card draws are not independent events. So you cannot alternate draws of decks of different size like you can switch rolling dice of different size; once a deck of a certain size is used, its new state must be remembered for the rest of the game. There also is the issue of whether both players draw from the same deck, or each have their own. And finally, it makes sens to allow the players to put cards back into the deck. A first XBoard implementation will probably allow each player to use only a single deck; the engine has to specify the size of it when he draws a card, and stick to the same size for the duration of the game. By specifying negative size you can draw from the deck that formally belongs to the opponent.