One could make some educated guesses. But a surer way of predicting the answer is to build a cheap and cheerful computational model.

I thought I'd blog about what I did for two reasons: first, to demonstrate how building small computational experiments with Mathematica is easy; and second, to point to the fact that the generation of income inequality in games with transferable money might be ubiquitous, a point that my interlocutor is keen to stress.

These days I use Mathematica to do almost all my computational explorations. Why? Because it's a powerful language well suited to quick prototyping and has an unmatched arsenal of fully integrated mathematical tools, including some fantastic and easy-to-use data visualization capabilities.

We can create a "monopoly-like" board by imagining, say, 50 squares, each of which contains two pieces of information: the value of the property that may be bought, and a flag indicating the player who has bought the property.

In Monopoly there is cheap and expensive property. So let's create the board like this:

land = Table[{i^1.5, 0}, {i, 50}]which generates a list like so:

{1, 0}, {2.82843, 0}, {5.19615, 0}, {8., 0}, {11.1803, 0},<<40>>, {311.987, 0}, {322.216, 0}, {332.554, 0}, {343., 0}, {353.553, 0}}For example, square 3 has a property value of 5.19615, which is currently not owned.

Next we need to create the players. Each player also has two pieces of associated information: their current endowment of cash and the square they are currently on. So let's create the players like this:

players = Table[{initialMoney, 1}, {numPlayers}]But what about the initial money that each player has? Let's do something simple. First, calculate the total cost of the property on the board:

totalCost = Total[Map[#[[1]] &, land]]Mathematica is more like functional than procedural programming. This statement is a nice, simple example. The inner call to "Map" applies the implicit function "#[[1]]" to each element of the list "land". "#" refers to an element of the list. "#[[1]]" refers to the first element of the element of the list, which in this case is the property value of the square. Hence "Map[#[[1]] &, land]" returns a new list, which is simply the list of the property values. Finally, we pass this list to "Total" which adds it all up and returns the total.

I'm sure that any expert Mathematica coders out there will be able to suggest a better way of doing this.

Now we simply make the initial money endowments for each player equal such that they add up to the total property value on the board. Since money will be conserved this entails that in principle all the property on the board can be purchased.

numPlayers = 50;The list of players is therefore:

initialMoney = totalCost/numPlayers

{{144.974, 1}, <<48>>, {144.974, 1}}In other words, every player starts at square 1 with cash reserves of 144.974.

Now that we've got the basic state of the Monopoly-like game we simply need to write some code that updates that state. Here's a function that processes one player's move. It does a number of things: (i) it rolls the die, (ii) it moves the player to the new square (wrapping at square 50), (iii) if the property is not bought and the player has sufficient money then buy it -- the purchase money is transferred to the whole community since we abstract from the existence of a "bank", (iv) if the property is already bought then pay rent to the player who owns it at a rate of 10%. I wrote this function very quickly with no effort to make it nice -- that's the point of quick computational explorations, after all. The code is intended to be "throwaway".

Move[players_List, land_List, playerIndex_Integer] :=Now we just need to repeatedly apply this "Move" function to each player lots of times, until the game reaches a fixed point.

Module[{nextPlayers = players, nextLand = land, die, playerSquare,

communityYield, rentDue},

die = RandomInteger[{1, 6}];

nextPlayers[[playerIndex, 2]] += die;

nextPlayers[[playerIndex, 2]] = Mod[nextPlayers[[playerIndex]][[2]], Length[nextLand]];

If[nextPlayers[[playerIndex]][[2]] == 0,

nextPlayers[[playerIndex, 2]] = Length[nextLand];

];

(* Buy if available *)

playerSquare = nextPlayers[[playerIndex]][[2]];

If[nextLand[[playerSquare]][[2]] == 0,

(* Buy land *)

If[nextPlayers[[playerIndex]][[1]] >= nextLand[[playerSquare]][[1]],

(* Spend money *)

nextPlayers[[playerIndex, 1]] -= nextLand[[playerSquare]][[1]];

(* Record ownership *)

nextLand[[playerSquare, 2]] = playerIndex;

(* Allocate spent money to whole community *)

communityYield = nextLand[[playerSquare]][[1]]/numPlayers;

nextPlayers = Map[{#[[1]] + communityYield, #[[2]]} &, nextPlayers];

];,

(* else pay rent at 10% *)

rentDue = Min[nextLand[[playerSquare]][[1]]*0.1, nextPlayers[[playerIndex]][[1]]];

nextPlayers[[playerIndex, 1]] -= rentDue;

nextPlayers[[nextLand[[playerSquare]][[2]], 1]] += rentDue;

];

{nextPlayers, nextLand}

]

wealthHist = {};The "wealthHist" records the money holdings of every player after everyone has a turn (the inner for loop). We let everyone have 100 turns.

For[j = 1, j <= 100, j++ For[i = 1, i <= Length[players], i++,

{players, land} = Move[players, land, i]; ];

wealth = Map[#[[1]] &, players];

wealthHist = Append[wealthHist, wealth];

];

("For loops" are generally considered bad practice in Mathematica. So this could be written much more elegantly. It's hard to break procedural habits.)

So what's the payoff for all this? We can use Mathematica's "ListAnimate" and "Histogram" functions to take the "wealthHist" and plot it as an animated histogram over time.

ListAnimate[Map[Histogram[#] &, wealthHist]]Here's the money distribution just after the start of the game:

Pretty much everyone is very close to the money they started with. Here's the money distribution after all players had 10 turns:

The initial equitable distribution of money is disappearing. The population of players splits into two segments: those that are losing money and those that are gaining it. This snapshot resembles a normal distribution: the majority of players are losing money at similar rates, although their is some variance (mode at about 130). But a much smaller population is "splitting off" to the right: they are beginning to gain money (e.g., a single individual with >275 cash).

And at the end of the game:

Almost all players are bankrupt leaving a tiny number of monopolists who control all the property and cash.

This final state is independent of initial conditions. Small changes to the board and rules make no difference.

If you played Monopoly as a child you may remember that there comes a point when one player enters a "positive feedback" phase in which their property generates more income to buy more property that generates more income etc. They become runaway winners. There is almost zero probability of ever catching up with them.

Monopoly has a Gambler's Ruin dynamic at its heart.

Monopoly was originally designed to communicate Henry George's critique of capitalist property relations to the working class, especially his call for a single tax on land. That subversive message has almost certainly been lost. If anything Monopoly now functions as a small, fun, fairly innocuous celebration of the process of accumulation.

In Monopoly, everyone starts out equal, and everyone is subject to the same rules: it's a "fair" game in this sense. But regardless of the individual capacities and talents of the players it is always the case that the final money distribution is highly unequal. In reality, players differ in their capacities and talents and clever players should on average come out on top. But Monopoly is not a meritocracy, since if all players were equally clever they could not be equally rewarded.

For example, in this abstract simulation of Monopoly all players are identical in their capacities and talents. It is therefore quite simply luck that controls which player eventually wins.

My interlocutor asked: "What is the source of income inequality in this game"?

Another question worth thinking about is: "What can this simple game tell us about income inequality in human societies"?