Royal Ur library¶
Core functionality for classical ROGOUR¶
The player are named Green (to move) and Red. Each board square is assigned a character.
D C B A Z Y
1 2 3 4 5 6 7 8
d c b a z y
Green pieces move through abcd12345678yz, while Red pieces move ABCD12345678YZ. Internally the board is represented as an array of length 22, indexed thus,
18 17 16 15 [21] 20 19
4 5 6 7 8 9 10 11
3 2 1 0 [14] 13 12
Positions 14 and 21 respectively store the number of Green/Red pieces out of play (born-off). The number of pieces at home is implicit (total must sum to 7). You may find it easier to picture the game and internal representation like that:
Red 15 16 17 18+ 19 20+ 21
4 5 6 7& 8 9 10 11
Green 0 1 2 3+ 12 13+ 14
The plus sign indicates the square bestows an extra roll. The ampersand provide protection from hits as well.
The board can be encoded as either a code or an index. Codes are printable strings (of length 5) intended for “human interaction” and light usage, i.e. copy/paste for sharing or when the number of boards is relativly small. The index is tighter representation mapping the board to an unique integer in the range [0,137913936), the total number of Ur positions. Indices are computationally slower than codes, but enable storing per-board values in one contiguous memory block, indexed by the board index, for the full game space. Given the ridiculous overhead of Python lists, and even the supposedly efficient arrays, the only viable option is to work with low-level bytearrays indexed by the board index.
-
royalur.urcore.
startPosition
()¶ Staring position.
-
royalur.urcore.
allActualMoves
(board, pips, froms=None)¶ Return a list of all actual moves by Green given the dice.
actual here means omitting the cases where Green can’t move. Each returned move is a
(b,e)
pair, wheree
is True when Green has an extra turn (and thus the board has not been flipped), or False and thus this is Red turn and the board is flipped.
-
royalur.urcore.
allMoves
(board, pips, froms=None)¶ Return a list of all moves by Green given the dice.
Same format as
allActualMoves()
, but including the “no-move” board from 0 pips.
-
royalur.urcore.
getPips
()¶ Get a “dice” roll.
-
royalur.urcore.
reverseBoard
(board)¶ Reverse roles of Red and Green.
-
royalur.urcore.
homes
(board)¶ Helper returning a (numberOfGreenMenAtHome, numberOfRedMenAtHome) pair.
-
royalur.urcore.
gameOver
(board)¶ True if game on board is over, False otherwise.
-
royalur.urcore.
typeBearOff
(board)¶ True if board is in bear-off mode. (i.e. no more contact possible).
-
royalur.urcore.
getIndex
(board)¶ Get board index from either a board, code, or index (convenience)
-
royalur.urcore.
getBoard
(key)¶ Get internal representation of board from either a board, code, or index (convenience)
-
royalur.urcore.
getCode
(board)¶ Get board code from either a board, code, or index (convenience)
-
royalur.urcore.
boardAsString
(board)¶ Board as a printable string (debug).
-
royalur.urcore.
positionsIterator
(gOff=0, rOff=0)¶ Iterate over all positions with gOff/rOff Green/Red pieces (respectively) off.
-
royalur.urcore.
validBoard
(b)¶ A valid ROGOUR board (debug)
Play and rollout functions¶
Functions to play ROGOUR games and positions, using different strategies for X and O.
-
royalur.play.
rollout
(board, nTrials, playerX=None, playerO=None, evaluator=None)¶ Play
board
nTrials
times. Report percentage of wins.Use playerX/playerO to determine X/O moves. If unspecified, use the best human-like player. If
evaluator
is given, truncate the rollout at the first position with a valid probability.
-
royalur.play.
getDBplayer
(db)¶ Return a player using probabilities from
db
.Fall back to default human player if position has no DB entry.
-
royalur.play.
ply1
(board, db)¶ Win probability of
board
at 1-ply.
-
royalur.play.
prob
(board, ply, db)¶ Win probability of
board
atply
-ply.
Human-like Players for ROGOUR¶
Human-like players are built upon the basic core principles of ROGOUR: hitting,
not getting hit, extra moves and bearing off. Such core principles (or
strategies) are captured in a move filter. A move filter takes a set of
positions (all possible moves for some position and dice in our case), and
filters out undesirable positions. It may filter none at all or all but one. For
example hitAny()
keeps the positions with the highest number of pieces
in the opponents home, and so effectively prefers positions with hits over
positions without hits.
More advanced players are built on top of those core principles by creating a compound filter, which is a list of core filters which are executed in order, from first to last.
Probabilities Database¶
Per-Position win probabilities for the full game space.
-
class
royalur.probsdb.
PositionsWinProbs
(fname=None)¶ Win probability for Green (on play) for each ROGOUR position.
-
aget
(board)¶ Get the win probability associated with board.
-
aset
(board, pr)¶ Set the win probability associated with board to
pr
.
-
board2key
(board)¶ Return the db internal ‘position’. This happens to be the offset into one humongus byte array.
-
get
(bpos)¶ Get the win probability associated with position
bpos
.
-
key2board
(key)¶ Return the key of the board associated with this position.
-
keys
()¶ Return the set of valid board positions (will be very slow the first time).
-
set
(bpos, pr)¶ Set the win probability associated with position
bpos
topr
.
-