Skip to content

Instantly share code, notes, and snippets.

@joelgrus
Last active October 4, 2015 15:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save joelgrus/ea1fdb4341afe14d52ca to your computer and use it in GitHub Desktop.
Save joelgrus/ea1fdb4341afe14d52ca to your computer and use it in GitHub Desktop.
semi-functional rewrite of Norvig monopoly simulator to avoid global state
# Rewrite of Norvig's monopoly simulator to avoid global state
# except for `board`, which is used immutably.
# http://nbviewer.ipython.org/url/norvig.com/ipython/Probability.ipynb
import random
split = str.split
# The board: a list of the names of the 40 squares
board = split("""GO A1 CC1 A2 T1 R1 B1 CH1 B2 B3
JAIL C1 U1 C2 C3 R2 D1 CC2 D2 D3
FP E1 CH2 E2 E3 R3 F1 F2 U2 F3
G2J G1 G2 CC3 G3 R4 CH3 H1 T2 H2""")
# The deck of 16 community chest cards. See do_card.
def get_cc_deck():
deck = split('GO JAIL' + 14 * ' ?')
random.shuffle(deck)
return deck
# The deck of 16 chance cards. See do_card.
def get_ch_deck():
deck = split('GO JAIL C1 E3 H2 R1 R R U -3' + 6 * ' ?')
random.shuffle(deck)
return deck
def monopoly(steps):
"""Simulate given number of steps of monopoly game, yielding the name of the
current square after each step."""
here = 0
CC = get_cc_deck()
CH = get_ch_deck()
doubles = 0
for _ in range(steps):
d1, d2 = random.randint(1, 6), random.randint(1, 6)
here = goto(here + d1 + d2)
doubles = (doubles + 1) if (d1 == d2) else 0
if doubles == 3 or board[here] == 'G2J':
here = goto('JAIL')
elif board[here].startswith('CC'):
here = do_card(CC, here)
elif board[here].startswith('CH'):
here = do_card(CH, here)
yield board[here]
def goto(square):
"""Go to destination square, which can be either a square number or a square
name. Return the index of the resulting square."""
if isinstance(square, int):
return square % len(board)
else:
return board.index(square)
def do_card(deck, square):
"""Take the top card from deck and do what it says. Return the index of the
resulting square."""
card = deck.pop() # Remove card from deck
deck[0:0] = [card] # Put card back on bottom of deck
if card == 'R' or card == 'U':
while not board[square].startswith(card):
# Advance to next railroad or utility
square = goto(square + 1)
return square
elif card == '-3':
# Go back 3 spaces
return goto(square - 3)
elif card == '?':
# Card is about money, not about movement
return square
else:
# Go to destination named on card
return goto(card)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment