A lecture on counting and probability made me curious about the relative strengths of monopoly board positions, and before the end of the lecture I had sketched an outline of this program. The `monopoly`

function returns the probability that a piece will be at each position of the board at the end of the given number of dice-rolls.

The strategy that I chose to solve this problem is to calculate the probability of each individual location *j + k* by summing the probabilities of being at each space *j* times the probability of rolling a *k*. This is only a general strategy; many complications appear because of chance cards and other special squares. Each possibility is carefully accounted for so that the probabilities always add to exactly 1.0, so the process can be iterated to produce probabilities after an arbitrary number of moves.

This code is written in Python, which I had never used before and looked
interesting. Check out the
monopoly board
image below; the saturation
values of the colors are generated by `monopoly`

and `color_map`

.

```
def monopoly(moves):
"""Return a list of the probabilities (0-1) of a monopoly piece
being at each board position after the given number of moves.
The probabilities are guaranteed to sum to 1."""
#Pre-fill old with the previous move (the piece must be on Go)
old = [0,] * 40
old[0] = 1
for i in range(moves):
board = [0,] * 40
#The probability that the piece ends up at j+k is the probability
#that the piece was at j times the probability of rolling k to
#the position j+k. These can be accumulated by trying each possible
#dice roll on each possible starting position.
for j in range(40):
for k in range(2,13):
cur = (j + k) % 40
multiplier = old[j] * roll_probability(k)
#We're handling a Chance card draw. There are sixteen chance cards.
if cur == 7 or cur == 22 or cur == 36:
board[0] += (1.0/16) * multiplier #Advance to Go
board[5] += (1.0/16) * multiplier #Ride on the Reading Railroad
board[10] += (1.0/16) * multiplier #Go directly to Jail
board[11] += (1.0/16) * multiplier #Advance to St. Charles Place
board[24] += (1.0/16) * multiplier #Advance to Illinois Avenue
board[39] += (1.0/16) * multiplier #Advance to Boardwalk
board[cur-3] += (1.0/16) * multiplier #Go back 3 spaces
if cur == 7:
board[12] += (1.0/16) * multiplier #Nearest utility
board[15] += (2.0/16) * multiplier #Nearest railroad (2x)
elif cur == 22:
board[28] += (1.0/16) * multiplier #Nearest utility
board[25] += (2.0/16) * multiplier #Nearest railroad (2x)
elif cur == 36:
board[12] += (1.0/16) * multiplier #Nearest utility
board[5] += (2.0/16) * multiplier #Nearest railroad (2x)
#Account for leaving this space due to "teleport" cards.
#Ten out of the sixteen chance cards divert the piece somewhere else.
board[cur] += multiplier * (6.0/16)
#We're handling a Community Chest draw. There are sixteen CC cards.
elif cur == 2 or cur == 17 or cur == 33:
board[0] += (1.0/16) * multiplier #Advance to Go
board[10] += (1.0/16) * multiplier #Directly to Jail
#Account for leaving this space due to "teleport" cards.
#Two out of the sixteen CC cards divert the piece somewhere else.
board[cur] += multiplier * (14.0/16)
#We're handling the Go To Jail square
elif cur == 30:
board[10] += (1.0) * multiplier
#Account for leaving this space due to "teleport" cards.
#The piece is always diverted somewhere else
board[cur] = 0
#We're handling a regular square with no chance of teleportation
else:
board[cur] += (1.0) * multiplier
old = board
return board
def roll_probability(sum):
"""Return the probability of getting a particular sum when rolling
two die. Valid values for sum are 2-12."""
return [1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1][sum-2] / 36.0;
def color_map(list):
"""Map a list of numbers to discrete values in the range 0-100.
This is useful for colorizing the relative magnitudes of each element."""
#Scale the maximum up to 100 but preserve the zero point
scale_factor = 100.0 / max(list);
return map(lambda x: round(x * scale_factor), list)
```

*Image: The saturation of the colors represents the relative probability of a
piece being found on each square after 10 turns. The board is oriented so that Go is the
bottom-right square.*