A Monte Carlo simulation that answers a simple question: on a Monopoly board, which squares do players actually land on most often?
Rather than deriving the distribution analytically, this notebook rolls the dice — 10,000 games, four players, 50 turns each, two million dice rolls in total — and counts where everybody ended up.
Landing frequency is not uniform across the 40 squares. Because every move is the sum of two dice, the step length is triangularly distributed around 7, and that structure propagates around the board instead of washing out. The notebook plots the outcome twice: once as raw landing counts, and once normalised to a percentage of all landings.
| Parameter | Value |
|---|---|
| Board size | 40 squares |
| Players | 4 |
| Turns per player, per game | 50 |
| Games simulated | 10,000 |
| Movement | (position + d1 + d2) mod 40, each die uniform on 1–6 |
Each player is a small Player class holding a name, a current position, and
the full list of squares they have visited. After every game, that list is
collapsed with collections.Counter and stored; at the end, all four players'
counters across all 10,000 games are merged into one distribution.
This models the dice, not the game. There is no:
- Jail, or the "go to jail" square
- Chance or Community Chest cards, which teleport players around the board
- Three-doubles rule
- Property ownership, rent, or bankruptcy
Those mechanics are what make the real distribution lopsided — Jail is by far the most-visited square in an actual game, and the orange properties are famously strong because they sit one good dice roll past it. Treat this notebook as the baseline that those effects distort, not as a model of real play.
pip install numpy matplotlib jupyter
jupyter notebook Monopoly.ipynbThen run the cells in order. simulate_games(10000) is the slow one; lower the
argument for a quicker pass.
Python 3 with numpy and matplotlib. Everything else — random, collections,
csv, functools, operator — is standard library.