GNU Backgammon works with many different kinds of equities. The equity is defined as the expected value of the position. However, this value can be expressed in several different metrics and may be calculated with or without taking the effect of the cube into consideration. In the following section we will describe the equities used and calculated by GNU Backgammon.
This is the value of the position in money game, e.g., if your equity is +0.4 an you are playing money game with a $1 stake, you will win $0.40 on average. The money equity can be calculated with or without taking the effect of the doubling cube into consideration, or cubeful or cubeless. The cubeless equity can be calculated from the basic formulae: 2*p(w)-1+2(p(wg)-p(lg))+3(p(wbg)-p(lbg)). Evaluating the cubeful equity is much more difficult; it can either be estimated from the cubeless equitity by using transformations as outlined by Rick Janowski or by constructing a neural net that directly outputs cubeful equities. GNU Backgammon uses the former approach.
In match play we’re generally not particular interested in the outcome of the individual games as much as the outcome of the entire match, so the interesting quantity for match play is match winning chance (MWC). As for the money equity the MWC can be calculated with and without the effect of the doubling cube. The MWCs are generally calculated with the use of a match equity table, which contains the chance of winning the match before a game starts, e.g., if the score is 0-0 in a 1pt match each player has 50% chance of winning the match before the game starts assuming they’re of equal skill.
The cubeless MWC is calculated as: MWC(cubeless) = p(w) * MWC(w) + p(l) * MWC(l) + p(wg) * MWC(wg) + p(lg) * MWC(lg) + p(wbg) * MWC(wbg) * p(lbg) * MWC(lbg).
For example, if the w/g/bg distribution is 0 30 60 - 40 10 0 and the match score is 1-3 to 5 with the cube on 2 the cubeless MWC is:
MWC(cubeless)= 30% * 50% + 30% * 0% + 30% * 100% + 10% * 0% + 0% * 100% + 0% * 0% = 45%,
so the cubeless MWC is 45%.
Evaluating the cubeful MWC is more difficult, and as for the cubeful money equity it’s possible to estimate cubeful MWCs from transformation on the w/g/bg distribution or directly calculate it from neural nets. GNU Backgammon uses the former approach, but the formulae are currently not published.
It’s generally very difficult to compare MWCs. For example, it’s hardly worth mentioning a 0.5% MWC error at DMP where as it’s a huge error at 0-0 to 7. It is therefore of interesting to normalise the MWCs to some common scale. The most often used normalisation is Normalised Money Game Equity (NEMG) where the MWC for any game is transformed into the same interval as money game, i.e., -3 to +3 (due to anomalies at certain match scores the NEMG can go below -3 and above +3). The transformation is linear:
NEMG = 2 * (MWC-MWC(l))/(MWC(w)-MWC(l)) - 1
In other words, extrapolation with the following two extrapolation points: (MWC(w),+1) and (MWC(l),-1).
For example, suppose the score is 3-1 to 5 with the cube on 2: MWC(l)=0% and MWC(w)=50%:
MWC | NEMG |
---|---|
0% | -1 |
25% | 0 |
50% | +1 |
75% | +2 |
100% | +3 |
Note that a w/g/bg distribution of 0 100 100 - 0 0 0 gives a NEMG of +3 whereas the corresponding money equity is only +2. This is because the gammon price is high for that particular score. When both players are far from winning the match, e.g., 0-0 to 17 or 1-0 to 17, NEMG is very close to the ususal money equity.
NEMG can be calculated from both cubeless and cubeful MWCs.
A word of caution: A cubeless NEMG calculated from a cubeless MWC could be named “cubeless equity”, but in most backgammon litterature this term seems to be reserved for the cubeless money equity.
This chapter is a brief description of how GNU Backgammon calculates cubeful equities. The formulae build directly on the work by Rick Janowski Take-Points in Money Games from 1993.
The basic formulae for cubeful equities as derived by Janowski is
E(cubeful) = E(dead) * (1-x) + E(live) * x,
where E(dead) is the dead cube equity (cubeless equity) calculated from the standard formulae. E(live) is the cubeful equity assuming a fully live cube. We’ll return to that in the next section. x is the cube efficiency. x=0 gives E(cubeful)=E(dead) as one extreme and x=1 gives E(cubeful)=E(live) as the other extreme. In reality x is somewhere in between, which typical values around 0.6 - 0.8.
Janowski’s article doesn’t mention cubeful equities, so we use the straightforward generalisation
MWC(cubeful) = MWC(dead) * (1-x) + MWC(live) * x.
as MWC is the entity that is used for match play evaluations.
The live cube equity is the equity assuming that the equity changes continuously, so that doubles and takes occurs exactly at the double point and take point. For gammonless play this is the well-known take point of 20%. Janowski derives the more general formula
TP = (L-0.5)/(W+L+0.5)
where W is the average cubeless value of games ultimately won, and L is the average cubeless value of games ultimately lost. For example, for the following position
GNU Backgammon evaluates
Win | W(g) | W(bg) | L(g) | L(bg) | |
---|---|---|---|---|---|
static: | 0.454 | 0.103 | 0.001 | 0.106 | 0.003 |
and hence W=(0.454 + 0.103 + 0.001)/0.454=1.229 and L=(0.556+0.106+0.003)/0.556) = 1.196. For gammonless positions, e.g., a race, W=1 and L=1.
The live cube equity is now based on piecewise linear interpolation between the points (0%,-L), (TP,-1), (CP,+1), and (100%,+W): if my winning chance is 0 I lose L points, at my take point I lose 1 point, at my cash point I cash 1 point, and when I have a certain win I win W points:
For match play there is no simple formula, since redoubles can only occur a limited number of times.
The live cube take point is generally calculated as
TP(live, n Cube)=TP(dead, n cube) * (1 - TP(live, 2n cube)
So to calculate the live cube take points for a 1-cube at 3-0 to 7 we need the live cube take points for the 4-cube and the 2-cube. For the position above and using Woolsey’s match equity table the live cube take point are:
Cube value | TP for Black | TP for White |
---|---|---|
4 | 0% | 41% |
2 | 15% | 38.5% |
1 | 24.5% | 27.3% |
The calculation of these are left as an exercise to the reader.
Ignoring backgammons, the gammon rates for White and Black are 0.106/54.6=19% and 0.103/0.454=22%, respectively. If White wins the game his MWC will be
81% * MWC(-3,-7) + 19% * MWC(-2,-7) = 78%
and if Black wins his MWC will be
78% * MWC(-4,-6) + 22% * MWC(-4,-5) = 41%.
If White cashes 1 point he has MWC(-3,-7)=76% and if Black cashes he has MWC(-4,-6)=36%. Analogous to money game the live cube MWC is calculated as piecewise linear interpolation between (0%,22%), (24.5%,24%), (72.7%,36%), and (100%,41%) (from Black’s point of view):
Figure: Fully live cubeful MWC
Having established the live cube equities and MWCs we’re now in position to calculate the 0-ply cubeful equities.
Let’s start with money game: the cubeless equity is -0.097 and the live cube equity can be determined from the figure above as -0.157. Thus, the cubeful equity is -0.138.
For the match play example at the score 3-0 the cubeless MWC is 29.1% and from the figure Black using wins=45.4% we can determine the live cube MWC to be 29.2%. Using a value of x=0.68 we arrive at a cubeful MWC of 29.17%.
The previous section concerned the calculation of 0-ply cubeful equities, so how so GNU Backgammon calculate cubeful 2-ply equities? The answer is: by simple recursion:
Equity=0 Loop over 21 dice rolls Find best move for given roll Equity = Equity + Evaluate n-1 ply equity for resulting position End Loop Equity = Equity/36
Note that evaluating the n-1 ply equity involves a cube decision, since the opponent may double, so GNU Backgammon will actually calculate the two n-1 ply equities: (a) assuming no double, and (b) assuming double, take. These two equities are combined with the equity for a pass, and the optimum of these three is added to the resulting equity. For a cubeful 2-ply evaluation GNU Backgammon will end up calculating the following cubeful 0-ply equities: centred 1-cube, opponent owns 2-cube, owned 4-cube, and opponent owns 8-cube.
Note that the 2-ply level does not use the cube efficiency, it’s not used until at the 0-ply level, but it’s possible to calculate an effective one by isolating x in the basic cube formulae:
x(eff) = (E(2-ply cubeful) - E(2-ply dead))/(E(2-ply live)-E(2-ply dead)).
The cube efficiency is obviously an important parameter, unfortunately there haven’t been much investigation carried out, so GNU Backgammon basically uses the values 0.6-0.7 originally suggested by Rick Janowski:
Position Class | x (Cube efficiency) |
---|---|
Two-sided (exact) bearoff | n/a |
One-sided bearoff | 0.6 |
Crashed | 0.68 |
Contact | 0.68 |
Race | linear interpolation between 0.6 and 0.7 |
For race GNU Backgammon uses linear interpolation based on pip count for the player on roll. A pip count of 40 gives x=0.6 and 120 gives x=0.7. If the pip count is below 40 or above 120 values of x=0.6 and x=0.7 are used, respectively.
For the two sided bearoff positions the cubeful money equity is already available from the database, so for money game there is no need to calculate cubeful equities via Janowski’s formulae. However, the cubeful equities for money game cannot be used for match play. Instead of using a fixed value of x, say, 0.6, GNU Backgammon will calculate an effective value based on the cubeful money equity. The cubeful MWC is calculated as usual, but with the calculated x.
There is obviously room for improvements. For example, holding games should intuitively have a lower cube efficiency, since it’s very difficult to double effectively: either it’s not good enough or you’ve lost the market by a mile after rolling a high double or hitting a single shot. Similarly, backgames will often have a low cube efficiency, whereas blitzes have may have a higher cube efficiency.
GNU Backgammon’s cube decisions are simple based on calculations of cubeful equities. For a double decision GNU Backgammon calculates the cubeful equity for “no double” and the cubeful equity for “double, take”. Combined with the equity for “double, pass”, it’s possible to determine the correct cube action.
The figure below shows the relevant cubeful equities for White and Black’s cube decisions in sample position from earlier.
Figure: Cubeful equities
On 0-ply Black will double when the green curve (White owns 2-cube) is above the red curve (centered cube), and White will take as long as the green curve is below 1. Similarly, White will double when the blue curve (Black owns 2-cube) is below the red curve (centered cube), and Black takes as long as the blue curve is above -1.
Note that GNU Backgammon doesn’t calculate the take point or double point explicitly. The cube decision is simply made by comparing equities from the figure.
Janowski has developed two other models for cubeful equities. The first is a generalisation of the one used by GNU Backgammon; it introduces two cube efficiencies instead of one. Often you may see that the cube efficiencies are different for the two players, and the refined general model as it is named by Janowski, tries to take this into consideration by using different cube efficiency parameters for the two players. For example, the blitzer may have another cube efficiency that the blitzee.
The second model is not published, but redefines the cube efficiency into a value that can be understood more intuitively and calculate easily from rollouts.
This section describes a method for compactly recording a backgammon position. It demonstrates how to encode a position into 10 binary bytes, which is useful for minimising the space used when recording large numbers of positions in memory or on disk. There is also an ASCII representation in 14 characters, which is convenient for output to the screen, for copying and pasting to transfer positions between programs which support the format, and for communicating positions via Usenet news or e-mail. The 10 byte binary format is called the key, and the 14 character ASCII format is the ID.
The key is essentially a bit string (imagine you start with an empty sequence of bits, and continue adding either “0” or “1” to the end). The way to build up a sequence that corresponds to a given position is:
The worst-case representation will require 80 bits: you can see that there are always 50 0 bits even if there are no chequers at all. Each player has a maximum of 15 chequers in play (not yet borne off) which require a 1 bit wherever they are positioned. That’s 30 bits to take of all chequers, plus the 50 bits of overhead for a total of 80 bits (the last bit is always 0 and isn’t strictly necessary, but it makes the code slightly easier). This bit string should be stored in little-endian order when packed into bytes (ie. the first bits in the string are stored in the least significant bits of the first byte).
As an example, here’s what the starting position looks like in the key format:
0 0 0 0 0 | player on roll has no chequers on ace to 5 points |
11111 0 | 5 chequers on the 6 point |
0 | none on the 7 point |
111 0 | 3 on the 8 |
0 0 0 0 | no others in our outfield |
11111 0 | 5 on the midpoint |
0 0 0 0 0 | none in the opponent’s outfield |
0 0 0 0 0 | or in opponent’s board, until… |
11 0 | two on the 24 point |
0 | none on the bar |
0 0 0 0 0 | opponent has no chequers on ace to 5 points |
11111 0 | 5 chequers on the 6 point |
0 | none on the 7 point |
111 0 | 3 on the 8 |
0 0 0 0 | no others in opponent’s outfield |
11111 0 | 5 on the midpoint |
0 0 0 0 0 | none in our outfield |
0 0 0 0 0 | or in our board, until… |
11 0 | two on the 24 point |
0 | none on the bar |
so altogether it’s:
00000111110011100000111110000000000011000000011111001110000011111000000000001100
In little endian bytes it looks like:
11100000 | 01110011 | 11110000 | 00000001 | 00110000 | 11100000 | 01110011 | 11110000 | 00000001 | 00110000 |
0xE0 | 0x73 | 0xF0 | 0x01 | 0x30 | 0xE0 | 0x73 | 0xF0 | 0x01 | 0x30 |
so the 10 byte key (in hex) is E0 73 F0 01 30 E0 73 F0 01 30.
The ID format is simply the Base64 encoding of the key. (Technically, a Base64 encoding of 80 binary bits should consist of 14 characters followed by two = padding characters, but this padding is omitted in the ID format.)
To continue the above example, splitting the 10 8-bit bytes into 14 6-bit groups gives:
111000 000111 001111 110000 000000 010011 000011 100000 011100 111111 000000 000001 001100 000000
In Base64 encoding, these groups are respectively represented as:
4 H P w A T D g c / A B M A
So, the position ID of the chequers at the start of the game is simply:
4HPwATDgc/ABMA
You can set the board in gnubg either by writing the position ID into the position text input field in the GUI or by executing the command
set board 4HPwATDgc/ABMA.
This section describes how the match ID is calculated. The match ID can be used for easy exchange of positions for gnubg users in conjuction with the position ID. The match key is a 9 byte representation of the match score, match length, value of cube, owner of cube, Crawford game flag, player on roll, player to make a decision, doubled flag, resigned flag, and the dice rolled. The match ID is the 12 character Base64 encoding of the match key. Match key
The match key is a bit string of length 66:
1 | 5 | 7 | 8 | 9 | 12 | 13 | 14 |
---|---|---|---|---|---|---|---|
Cube-Cube-Cube-Cube | CubeOwner-CubeOwner | DiceOwner | Crawford | GameState-GameState-GameState | TurnOwner | Double | Resign-Resign |
16 | 19 | 22 | 37 | 52 |
---|---|---|---|---|
Dice1-Dice1-Dice1 | Dice2-Dice2-Dice2 | MatchLen x 15 | Score1 x 15 | Score2 x 15 |
For example, assume the score is 2-4 in a 9 point match with player 0 holding a 2-cube, and player 1 has just rolled 52. The match key for this will be (note that the bit order is reversed below for readability)
1000 00 1 0 100 1 0 00 101 010 100100000000000 010000000000000 001000000000000
In little endian the bytes looks like:
01000001 10001001 00101010 00000001 00100000 00000000 00100000 00000000 00
0×41 0×89 0×2A 0×01 0×20 0×00 0×20 0×00 0×00
Analogous to the position ID from the previous section the match ID format is simply the Base64 encoding of the key.
To continue the example above, the 9 8-bit bytes are grouped into 12 6-bits groups:
010000 011000 100100 101010 000000 010010 000000 000000 001000 000000 000000 000000
In Base64 encoding, the groups are represented as:
Q Y k q A S A A I A A A
So, the match id is simply:
QYkqASAAIAAA
If someone post a match ID you can set up the position in gnubg by writing or pasting it into the Match ID text input field on the main window, or by executing the command
set matchid QYkqASAAIAAA.