Monopoly and Prosperity

In which a set of rules for the game of Monopoly are provided that can be played on a modern game board, but with the moralistic Georgist Land Tax values of when the game was first created over 100 years ago. It may make you think of ‘Go to Jail’, ‘Free Parking’, ‘Community Chest’ and other features of the game in a different light in the future. Unlike other writings that just tell the history of the game, this includes a Python program to simulate Monopoly games in order to see the effect of rule changes – on social justice!

Here is some festive fun for all the family. On Christmas Day, after the turkey, get the Monopoly set down from the loft and play throughout the afternoon. Someone will have the good fortune to get some orange sites and 2 or 3 stations early on and go on to end up with hotels on the expensive (green and dark blue) sites and win handsomely. The degree of gloating at their own mastery of the game will depend on the person but, at some point, a junior member of the family is sure to end up crying. I know of no other game that manages this so successfully. The inequity of the game thus serves as preparation for the inequity of life.

The Landlord’s Game

There is an extensive history of the game of Monopoly on Wikipedia. But in short, the invention of the game is commonly attributed to Charles Darrow, around 1933, who became a millionaire from it. Yet the game has its origins in ‘The Landlord’s Game’ by Elizabeth Magie, around 1904, who only benefitted to the tune of $500. She was a Georgist, believing that income derived from land (as opposed to one’s own labour, including labour upon that land) should be shared among everyone in society. She created the game as a practical way to demonstrate the problem of rents enriching some and impoverishing others. Georgists generally advocate a land value tax as a solution (but see ‘The Land Windfall Tax’ about an alternative).

Her game had two phases: ‘Landlord’s Game’ and ‘Prosperity’. Players all start with a set amount of money and play the rules of the Landlord’s Game. Inequities grow until enough players elect to switch to Prosperity rules. With minimal rule changes, the objective of the game is to then get the poorest player to a level of wealth twice that at which everyone originally started. It thus serves to show the benefit of running an economy according to the Land Value Tax principles behind Prosperity rather than the ‘unearned income’ and monopolistic effects of Monopoly. The game was developed by various people but the invention of Monopoly has commonly be attributed to Charles Darrow who it was that sold the game to Parker Brothers in 1935. It immediately became very successful. But by this stage, the Prosperity phase of the game had disappeared, along with the game’s didactic purpose. The origins of the game, and Lizzie Magie were forgotten.

A Game for 2019?

As early (1932) rules of the game said:

Do you want to be wealthy? Play the Landlord’s Game and learn how.
Do you want prosperity? Play Prosperity Game and find out.
Easily learned and enjoyed at the first sitting. But repeated playing develops the highest skill and foresight.
No dull moments.
Full of novel situations and swift surprises.
Lots of fun, and you learn without painful effort.
A study in economics.
Brings out the points which the man in the street wants explained.
A thorough understanding of the mysteries of “political economy” comes with playing The Landlord’s Game and Prosperity.
The Landlord’s Game and Prosperity presents familiar every-day problems in a most entertaining way.
The players solve the problems by following their own self-interest.
The Landlord’s Game shows why our national housekeeping has gone wrong and Prosperity Game shows how to start it right and keep it going right.

The bold emphasis is mine. Perhaps this game has some lessons for us now, in 2019?

Monopolies

Most people have probably not given much thought about the significance of specific aspects of the game and even why it is called Monopoly.
Suppliers of particular goods or service can charge higher when they are the only supplier. Hence the modern Monopoly rules:

  • “… doubled”: When all sites of a particular colour are owned by a single player, that player has a monopoly on the supply of rental properties in that neighbourhood and so the rent is increased.
  • “When two stations are owned…” – I suppose ownership of a ‘station’ really means ownership of the train services (if not the railway infrastructure); the station is just the terminus square to land on. The fee payable is for the fares for journeys (perhaps for commuting in from outside the city). A player can gain a monopoly through owning more of the railways out of the city.
  • “When both Utility franchises are owned … 10 times the throw of the dice …”: the owner has a monopoly on utilities.

Everybody Works but the Vacant Lot

Generally, landing on a coloured site is analogous to renting a property in that street.
Plots are originally sold as vacant i.e. without any buildings on them. Houses can be built on the site and these can then be rented out. A site in the game that could have houses built on it but does have any is referred to as ‘unimproved’. But there is a problem here:

Why do you pay anything when you land on an unimproved site?

One interpretation of this might be:

  • The ‘site’ is just one of many plots on the street in question.
  • Other plots have other owners (these are outside of the game).
  • Whoever lands on the square is paying to rent a property – but not necessarily the one owned by another player.
  • If a site in the game is unimproved, whoever has landed on the game square is clearly not renting from the player-owner of the unimproved site.
  • But: the player-owner has benefitted from “the presence in this community and enterprise of its [other] people” who have built houses for other to rent, through an increase in the value of the site (“without earning it”).

Or perhaps there is some very basic accommodation to rent out through just buying the site and ‘improvements’ are not necessarily new houses – a model house is just a convenient marker in the game.
Either way, there is an underlying principle here in the original game: to highlight the problem on ‘unearned income’. As a billboard in Rockford, Illinois said:

“Everybody Works but the Vacant Lot: I paid $3600 for this lot and will hold till I get $6000. The profit is unearned increment made possible by the presence of this community and enterprise of its people. I take the profit without earning it. For the remedy read Henry George. Yours truly Fay Lewis”

https://www.humanjourney.us/wp-content/uploads/2017/08/vacantLot.jpg
(credit: The Human Journey)

The Board

Here is the 1906 version of Lizzie Magie’s board, thanks to landlordsgame.info (as is much subsequent information):

landlordsgame.info
A very early game board (credit landlordsgame.info)

Magie’s Georgism is apparent from the board and the rules, particularly in the contrast between the ‘Landlord’s Game’ rules and ‘Prosperity’ rules.

  • What is now ‘Go’ is labelled ‘Labor upon Mother Earth produces wages’: a clear Georgist distinction between earned income from labour and unearned income from benefitting from common land (and its resources).
  • The order to “Go to Jail” is a consequence of trespassing on the land of ‘Lord Blueblood’s Estate’. In Prosperity, there are no absentee landlords of large estates and the land is now a public park, free to visit.
  • The modern Monopoly’s “Just Visiting” the Jail is instead a $10 tax for ‘Absolute necessity: Shelter’, highlighting the plight of those that do not own property. Under Prosperity rules, there is no trespassing and therefore no jail is needed.
  • Taxes – e.g. ‘Super Tax’ – are undesirable in the modern game of Monopoly. The original board has some squares that highlights what those taxes were being used for: food, clothing and fuel (as well as shelter), these being ‘Absolute necessities’, in contrast to luxuries (for which there is a ‘Luxury Tax’).
  • The modern Monopoly’s “Free Parking” was nothing so desirable in the original context. Yes it was rent-free, but that was because it was the Workhouse! Under Prosperity rules, everyone prospers so there is no need for a Workhouse and the square becomes a free open park space.

We can recognize that the rules in the modern game of Monopoly have their origins in Magie’s rules but they have lost Magie’s moralist values. And so it just becomes a game of individualistic greed!

Playing the Landlord’s Game Again

If you want to a play a modern version of The Landlord’s Game, you can download (or buy) material from thelandlordgame.com:

“a game of cents and sensibility”

There are a number of other games that can be considered as ‘inverted Monopoly’, to varying degrees of similarity to The Landlord’s Game:

(and Marxist to varying degrees).

As an alternative to these, below I offer rules that can be played with an existing Monopoly set, with minimal re-interpretation of the board. The rules of modern monopoly are widely known and hence easier to play. Some changes help to emphasize the monopolizing nature of the game; they are strongly based on the original Landlord’s Game (thanks to landlordsgame.info for the info) which therefore gives a flavour of the original game.

Below is a board as it might ideally be, showing the squares taken from Magie’s board where the function or interpretation of the square has been changed.

Adapted from landlordsgame.info and http://tripsandtips.com.au/dest-london-monopoly.html
The Landlord’s Game: Past and Present

This is for the London edition of game. For interest only, it shows ‘up to date’ (or at least recent) monthly rental prices. We can see how the desirability or areas have changed in the last Century, with Bow Street and Pall Mall becoming so valuable and Mayfair sliding down the ranking from first place.

I have renamed ‘The Landlord’s Game” game phase to ‘Monopoly’ – because of it basically being the same as normal modern Monopoly. The overall two-phase game could be called ‘The Landlord’s Game’ (since there would still be landlords under Prosperity rules) or just ‘Monopoly and Prosperity’. I hope the result reflects the spirit and values of the original game.

Rules of the Game

Unlike modern Monopoly, the overall objective of the game is to just finish the game! The game starts by following normal Monopoly game rules, with just a few modifications. The game switches over to Prosperity rules when at least half of the players are in the Workhouse. The game continues until all players have twice as much wealth as they had when they started Monopoly.
It thus demonstrates the original objectives of Lizzie Magie:

  • How monopolies lead to inequality and poverty
  • How communities that collect Land Rents rather than taxes benefit everyone.

It shows:

“Why our national housekeeping has gone wrong and … how to start it right and keep it going right”!

One player will finish the game with more wealth that others. They are sure to go away thinking they are the winners. But no one can finish until everyone can finish. Everyone is a winner! Hopefully no one will end up crying.

The New Rules for ‘Monopoly’

The rules of the Monopoly phase of the game are basically the same as modern Monopoly but with some differences as described below, generally to emphasize the presence of monopolies and the benefitting from unearned incomes.
The differences are:

  1. Improving sites: The original game talks about ‘improvements’, standing for “any kind of work done on or in the ground” but multiples of whole houses are used in modern Monopoly. In the rules here, only one house can be built on any site. A house can be built on a site without needing to own the set of sites of the same colour.
  2. A distinction is made between Land Rent (payable on unimproved sites) and House Rent (payable when a site has been improved). When a site has been improved, both Land Rent and Housing Rent are payable. This distinction is important for the Prosperity rules (as part of the Georgist principle of separating ‘unearned income’ and ‘earned income’).
  3. The Land Rent payable is the ‘unimproved’ rent on the site, plus the ‘unimproved’ rent of every other site in the same color group that has been improved. Thus, if the other two sites in a group have been improved, Land Rent will tripled. This is an example of the “unearned increment made possible by the presence of this community and enterprise of its people. I take the profit without earning it” said by Fay Lewis.
  4. The number of properties counted for Housing Rent is the number owned by the player across the color group, not just the single site (where there is a maximum of one). For example, if the player owns two sites within a group that are both improved and the third site is also improved but owned by someone else, Housing Rent charged is ‘if 2 properties are owned’. Owning more sites increases the monopoly across the site, increasing prices.
  5. Going bankrupt: A player is sent directly to the Workhouse when broke. (The Workhouse is at ‘Free Parking’) This must be after selling all assets. The player will stay there, only advancing from that site when Prosperity rules have been invoked.

Note:

  1. ‘Go To Jail’: this is ‘Lord Blueblood’s estate’ in the original game: the reason for going to jail is for trespassing on private land.
  2. The ‘Go’ square is marked ‘Labor Upon Mother Earth Produces Wages’ in the original game. The significance of the money handed out is that it has been earned from work.

The Rules for ‘Prosperity’

The rules of Prosperity are the same as the Monopoly rules set out above except:

  1. Land Rent now goes to the ‘Community Chest’. When a player lands on a site owned by someone else, they pay Land Rent (and Housing Rent in addition, if applicable) as under Monopoly rules. But the owner of the site must pay Land Rent to the Community Chest. (In practicality, player landing on the site can just pay Land Rent into the Community Chest directly). The owner of an unimproved site will not benefit from the value imparted to the land as a result of the work and/or investment of others in the neighbourhood improving their sites. (Remember the problem whereby ‘Everybody Works but the Vacant Lot’.)
  2. The Community Chest cards are not used. In their place, the Community Chest revenue from Land Rent is stored. When anyone lands on one of the three Community Chest sites on the board, that revenue is distributed equally to all players.
  3. Landing on one’s own site also incurs a payment of Land Rent to the Community Chest. You own the improvement of the site but not the value of the land.
  4. Because owners do not benefit from players landing on unimproved sites, rents do not increase when an owner has more than one site of a particular colour. The total Land Rent payable is just based on that of the one site landed on. (There is no monopoly effect.)
  5. A monopoly exists where a player owns more than one site in any color group which is why higher rents were charged under Monopoly rules. In Prosperity, the owner must sell a site that is part of a monopoly when another player land on it. The owner sells both the site and its improvement value back to the Bank. The land is then not owned by anyone. The player who landed on that site is therefore not liable for any Land Rent and may choose to buy that site if it does not create a new monopoly (i.e. the player cannot already own any site within the same color group).
  6. When landing on one of the three Chance sites, $10 must be paid to the Community Chest to help those in society that need to be given an ‘Absolute Necessity’ to have a chance in life.
  7. No tax needs to be paid when landing on Income Tax or Super Tax. With Georgism, all distribution of wealth in managed through Land Rent.
  8. Trespassing on unimproved land no longer applies. Players no longer go to jail for landing on the absentee landlord’s land (‘Go to Jail’). ‘Lord Blueblood’s Estate’ becomes ‘Blueblood Park’.
  9. Players rolling 3 doubles will still go to jail but throwing a double is the only way out of jail, regardless of how many turns that takes. $50 bribery does not work.
  10. Players ending up in debt will still go to the Workhouse but there is a way out of the Workhouse because of receiving monies from the Community Chest. (The original debts are written off.)

The Gini Coefficient

The Gini Coefficient is a measure of inequality. A value of 0 indicates that everyone has the same wealth. A value of 1 indicates that one person has all the wealth. The coefficient is zero at the start
of Monopoly. By the end of playing using Monopoly rules, it is close to 1, with the majority of players having nothing. Playing Prosperity rules should bring the coefficient back down towards zero.

https://voxeu.org/article/american-growth-and-inequality-1700
Gini coefficient of inequality (Credit: VoxEU.org)

Automating the Game

I am not sure how much learning would really be gained from actually playing ‘Monopoly and Prosperity’ beyond what I have said here. Board games are for enjoyment and I am not sure how much enjoyment would be gained from actually playing the Prosperity phase. So below, I present a computer simulation of the game; you can ‘play’ a game on your own in seconds that would take a group of people hours to play out physically on a game board.
The program is in Python3 code. If you don’t know how to install and run Python code, the simplest thing to do is copy and paste all the code into an online Python 3 interpreter, such as https://repl.it/@jef12345/python-361 (and click run).
You can play Monopoly followed by Prosperity, just Prosperity on its own. You can play around with parameters and see the effect. A major parameter is the Gini coefficient. Instead of playing Monopoly ‘until the majority of players choose to switch to Prosperity rules, Monopoly gets played until a particular Gini coefficient value is reached. Setting the threshold to 0.95 will generally mean that one or two players will end up in the Workhouse.
To automate the game, other human decisions have needed to be taken out. And I have also made some simplifications to reduce the amount of coding.

  • Buying sites at face value if landing on that site. There are no auctions.
  • Only getting out of jail by rolling a double, regardless of how many turns this takes.
  • Using an averaged value of the dice roll (value = 7) to determine the fee for landing on a utility.
  • Assuming Chance and Community Chest cards have net zero effect and therefor not including them in the game.

Understanding the Outputs

There are four imaginary players, Aaron, Brian, Calum and David, playing in that order.

Before clicking ‘run’ you can make minor changes:

  • Near the top: changing what events in the game get reported (‘report = …’)
  • Also near the top: changing the name of each site (‘site_name =’), and
  • At the bottom: changing what sort of game gets played (‘if True …’).

The output can be controlled by the various flags at the start of the code. Most are self-explanatory:

  • RPT_TURN: Reporting what square a player have landed on
  • RPT_BUY_SELL = Buying and selling sites
  • RPT_HOUSE: Making improvements on sites
  • RPT_RENT: Land Rent and Housing Rent payments
  • RPT_STATUS: Reporting a summary status at the end of each turn
  • RPT_CARD: Chance and Community Chest events
  • RPT_MONOPOLY = 128
  • RPT_DOUBLE: Throwing doubles
  • RPT_WEALTH: Total wealth (cash, sites and improvements)
  • RPT_EXPECT: Trend in wealth (getting richer or poorer)
  • RPT_UNAFFORDABLE: Inability to buy sites landed upon

Moving the desired ‘site_name =’ statement to be last in the code listing (or deleting the other definitions) can control how the sites are named – either in full or a 4-character abbreviation (the latter makes it easier to see what’s going on from STATUS line outputs. For example, the last site on the circuit can be set to one of:

  • ‘Mayfair’
  • ‘Mayf’
  • ‘Boardwalk Ave’
  • ‘Bdwk’
  • ‘Blue2′

Normally, the status output is sufficient to see what is going on, and this does need some explanation. As an example, the output line:

#STATUS: 237 G=0.38 (W 1328 C 568 chnce)(W 1684 C 1024 Red2.)(W 2997 C 2237 Yelo2)(W 5041 C 2831 Jail.) $0

means:

  • Turn number 237
  • Gini coefficient 0.38
  • Aaron has a wealth of $1328, including $568 cash and is on a Chance.
  • Similarly, Brian, Calum and Davis are on the second Red site, second Yellow site and Jail (probably Just Visiting) respectively.
  • The amount of money in the Community Chest is $0. (This status is from the Monopoly phase, where there is no Community Chest fund.)

‘Sites’ output lines concisely indicate who owns what and whether sites have been improved.

# SITES: .A.D.db.A-.DdA-db.bD.d.DDbA-dD.DD.Da.D.D

The 40 characters, starting at ‘Go’ indicate as follows:

  • ‘.’ Dots indicate sites than cannot be bought.
  • ‘-‘ Dashes indicate purchasable sites that or not owned.
  • A letter indicates the owner e.g. ‘a’ = Aaron.
  • Upper-case letters indicate that the site has been improved.

Output such as

[[0 0 0 1 1 0 0 0 0 1]
[1 1 1 1 1 1 1 1 1 2]
[0 0 1 1 0 1 1 1 1 1]
[1 1 1 0 1 1 0 0 0 0]]

… shows the number of properties owned in each group for each player.

Running Monopoly then Prosperity

If we play Monopoly and Prosperity as originally intended, one after the other (using abbreviated London names),

if True: # Monopoly then Prosperity
    report = RPT_STATUS + RPT_BUY_SELL + RPT_HOUSE
    setup_game(play='fair')
    game_rules = 'monopoly'
    play_game(max_turns=1000, max_gini=0.95)
    game_rules = 'prosperity'
    play_game(max_turns=1000, max_gini=0.99)

it shows the Gini coefficient increasing throughout Monopoly and then recovering after the switch to Prosperity.

#####################
# Let's play Monopoly!
#####################
# STATUS: 1 G=0.00 (W 1500 C 1500 chnc)(W 1500 C 1500 Go..)(W 1500 C 1500 Go..)(W 1500 C 1500 Go..) $0
# STATUS: 2 G=0.02 (W 1500 C 1500 chnc)(W 1400 C 1400 InTx)(W 1500 C 1500 Go..)(W 1500 C 1500 Go..) $0
# INFO: Calum buys KxSt for $200
# INFO: Calum now has 1 properties
# STATUS: 3 G=0.02 (W 1500 C 1500 chnc)(W 1400 C 1400 InTx)(W 1500 C 1300 KxSt)(W 1500 C 1500 Go..) $0
# INFO: David buys Eust for $100
# INFO: David now has 1 properties
# STATUS: 4 G=0.02 (W 1500 C 1500 chnc)(W 1400 C 1400 InTx)(W 1500 C 1300 KxSt)(W 1500 C 1400 Eust) $0
# INFO: David buys Marl for $180
# INFO: David now has 2 properties
# STATUS: 4 G=0.02 (W 1500 C 1500 chnc)(W 1400 C 1400 InTx)(W 1500 C 1300 KxSt)(W 1500 C 1220 Marl) $0
# STATUS: 5 G=0.02 (W 1500 C 1500 Jail)(W 1400 C 1400 InTx)(W 1500 C 1300 KxSt)(W 1500 C 1220 Marl) $0
# INFO: Brian buys Pent for $120
# INFO: Brian now has 1 properties
# STATUS: 6 G=0.02 (W 1500 C 1500 Jail)(W 1400 C 1280 Pent)(W 1500 C 1300 KxSt)(W 1500 C 1220 Marl) $0

...

# STATUS: 420 G=0.91 (W 210 C 70 Flet)(W15059 C11759 Bond)(W 670 C 130 Jail)(W 444 C 444 Picc) $0
# INFO: Aaron is selling Pall for $140
# STATUS: 421 G=0.91 (W 0 C 0 Work)(W15111 C11811 Bond)(W 670 C 130 Jail)(W 834 C 834 Picc) $0
# STATUS: 422 G=0.91 (W 0 C 0 Work)(W15111 C11811 chnc)(W 670 C 130 Jail)(W 834 C 834 Picc) $0
# STATUS: 422 G=0.91 (W 0 C 0 Work)(W15311 C12011 cmch)(W 670 C 130 Jail)(W 834 C 834 Picc) $0
# STATUS: 423 G=0.91 (W 0 C 0 Work)(W15311 C12011 cmch)(W 670 C 130 Jail)(W 834 C 834 Picc) $0
# STATUS: 424 G=0.91 (W 0 C 0 Work)(W15310 C12010 cmch)(W 670 C 130 Jail)(W 835 C 835 LpSt) $0
# STATUS: 425 G=0.91 (W 0 C 0 Work)(W15310 C12010 cmch)(W 670 C 130 Jail)(W 835 C 835 LpSt) $0
# STATUS: 426 G=0.91 (W 0 C 0 Work)(W15311 C12011 KxSt)(W 669 C 129 Jail)(W 835 C 835 LpSt) $0
# STATUS: 427 G=0.91 (W 0 C 0 Work)(W15311 C12011 KxSt)(W 669 C 129 Jail)(W 835 C 835 LpSt) $0
# STATUS: 428 G=0.96 (W 0 C 0 Work)(W16011 C12711 KxSt)(W 669 C 129 Jail)(W 135 C 135 Mayf) $0
##################################################
# Game over!: Gini index 0.96 has exceeded 0.95
##################################################
# STATUS: 429 G=0.96 (W 0 C 0 Work)(W16011 C12711 KxSt)(W 669 C 129 Jail)(W 135 C 135 Mayf) $0
# SITES: .-.B.cB.-B.--c-bB.-c.B.-BbB-b-.B-.Bb.B.B
#####################
# Let's play Prosperity!
#####################
# STATUS: 1 G=0.96 (W 0 C 0 Work)(W16011 C12711 KxSt)(W 669 C 129 Jail)(W 135 C 135 Mayf) $0
# INFO: Brian buys Pall for $140
# INFO: Brian now has 16 properties
# STATUS: 2 G=0.96 (W 0 C 0 Work)(W16011 C12571 Pall)(W 669 C 129 Jail)(W 135 C 135 Mayf) $0
# STATUS: 3 G=0.96 (W 0 C 0 Work)(W16011 C12571 Pall)(W 669 C 129 Jail)(W 135 C 135 Mayf) $0
# STATUS: 4 G=0.95 (W 0 C 0 Work)(W16011 C12571 Pall)(W 669 C 129 Jail)(W 331 C 331 Wtpl) $4
# STATUS: 5 G=0.95 (W 0 C 0 Work)(W16011 C12571 Pall)(W 669 C 129 Jail)(W 331 C 331 Wtpl) $4
# INFO: Brian not allowed to buy Nrth
# STATUS: 6 G=0.95 (W 0 C 0 Work)(W15999 C12559 Nrth)(W 669 C 129 Jail)(W 331 C 331 Wtpl) $16
# STATUS: 7 G=0.95 (W 0 C 0 Work)(W15999 C12559 Nrth)(W 669 C 129 Jail)(W 331 C 331 Wtpl) $16
# STATUS: 8 G=0.95 (W 0 C 0 Work)(W15999 C12559 Nrth)(W 669 C 129 Jail)(W 321 C 321 Pall) $26
# STATUS: 9 G=0.95 (W 0 C 0 Work)(W15999 C12559 Nrth)(W 669 C 129 Jail)(W 321 C 321 Pall) $26

...

# STATUS: 335 G=0.59 (W 2860 C 2090 Elec)(W19703 C17673 Traf)(W 3505 C 2055 SpTx)(W 2853 C 2113 chnc) $344
# STATUS: 336 G=0.58 (W 2860 C 2090 Elec)(W19703 C17673 Traf)(W 3505 C 2055 SpTx)(W 3053 C 2313 InTx) $344
# STATUS: 337 G=0.58 (W 2860 C 2090 chnc)(W19703 C17673 Traf)(W 3505 C 2055 SpTx)(W 3053 C 2313 InTx) $344
# STATUS: 338 G=0.58 (W 2860 C 2090 chnc)(W19681 C17651 Cvty)(W 3505 C 2055 SpTx)(W 3053 C 2313 InTx) $366
# STATUS: 339 G=0.58 (W 2860 C 2090 chnc)(W19681 C17651 Cvty)(W 3701 C 2251 Wtpl)(W 3053 C 2313 InTx) $370
# STATUS: 340 G=0.58 (W 2860 C 2090 chnc)(W19681 C17651 Cvty)(W 3701 C 2251 Wtpl)(W 3043 C 2303 Whll) $380
# STATUS: 341 G=0.58 (W 2860 C 2090 GoTo)(W19681 C17651 Cvty)(W 3701 C 2251 Wtpl)(W 3043 C 2303 Whll) $380
# STATUS: 342 G=0.58 (W 2860 C 2090 GoTo)(W19646 C17616 PkLn)(W 3701 C 2251 Wtpl)(W 3043 C 2303 Whll) $415
# STATUS: 343 G=0.58 (W 2860 C 2090 GoTo)(W19646 C17616 PkLn)(W 3701 C 2251 Jail)(W 3043 C 2303 Whll) $415
# STATUS: 344 G=0.58 (W 2860 C 2090 GoTo)(W19646 C17616 PkLn)(W 3701 C 2251 Jail)(W 3043 C 2303 Flet) $415
# STATUS: 345 G=0.56 (W 3163 C 2393 cmch)(W19749 C17719 PkLn)(W 3804 C 2354 Jail)(W 3146 C 2406 Flet) $3
# STATUS: 345 G=0.56 (W 3157 C 2387 Eust)(W19749 C17719 PkLn)(W 3804 C 2354 Jail)(W 3146 C 2406 Flet) $9
##################################################
# Game over!: All players now have more than $3000
##################################################
# STATUS: 346 G=0.56 (W 3157 C 2387 Eust)(W19749 C17719 PkLn)(W 3804 C 2354 Jail)(W 3146 C 2406 Flet) $9
# SITES: .D.B.cB.DA.BaCDbB.-C.A.DBdBCbA.BC.--.C.B
[[0 1 0 0 1 1 0 0 1 0]
 [1 1 1 1 1 1 1 1 1 1]
 [0 0 1 1 0 1 1 1 0 1]
 [1 1 1 0 1 0 0 0 0 1]]
###################
# End of simulation
###################
>>>

Every player has had their wealth increased by a similar amount ($3000) but the ‘Big Landlord’ player at the end of Monopoly still has far more wealth than the other players at the end of Prosperity. The difference in wealth between the 3 players and the Big Landlord is roughly the same amount richer in value terms $16,000 but those 3 players have been able to gain wealth to move them out of subsistence. Over time, cash will increase as new properties cannot be bought because of monopoly rules. The Gini coefficient has decreased because of the reduction of inequality in relative terms.

Just Running Prosperity

In contrast, a game of Prosperity played from a normal Monopoly start (using full Atlantic City names):

if True: # Prosperity only
    report = RPT_STATUS + RPT_BUY_SELL + RPT_HOUSE
    setup_game(play='fair')
    game_rules = 'prosperity'
    play_game(max_turns=500, max_gini=0.40)

leads to all players gradually getting richer and virtually the same rate, with the Gini coefficient hovering around 0.

#####################
# Let's play Prosperity!
#####################
# STATUS: 1 G=0.00 (W 1500 C 1500 Chance)(W 1500 C 1500 Go)(W 1500 C 1500 Go)(W 1500 C 1500 Go) $0
# STATUS: 2 G=0.00 (W 1500 C 1500 Chance)(W 1500 C 1500 Income Tax)(W 1500 C 1500 Go)(W 1500 C 1500 Go) $0
# INFO: Calum buys Reading RR for $200
# INFO: Calum now has 1 properties
# STATUS: 3 G=0.00 (W 1500 C 1500 Chance)(W 1500 C 1500 Income Tax)(W 1500 C 1300 Reading RR)(W 1500 C 1500 Go) $0
# INFO: David buys Vermont Ave for $100
# INFO: David now has 1 properties
# STATUS: 4 G=0.00 (W 1500 C 1500 Chance)(W 1500 C 1500 Income Tax)(W 1500 C 1300 Reading RR)(W 1500 C 1400 Vermont Ave) $0
# INFO: David buys Tennessee Ave for $180

...

# STATUS: 227 G=0.03 (W 3140 C 2000 Poor House)(W 2839 C 1819 Pennsylvania Ave)(W 3001 C 1961 Virginia Ave)(W 3116 C 1976 Virginia Ave) $254
# STATUS: 228 G=0.03 (W 3140 C 2000 Poor House)(W 2839 C 1819 Pennsylvania Ave)(W 3001 C 1961 Virginia Ave)(W 3098 C 1958 Indiana Ave) $272
# STATUS: 229 G=0.03 (W 3140 C 2000 B&O RR)(W 2839 C 1819 Pennsylvania Ave)(W 3001 C 1961 Virginia Ave)(W 3098 C 1958 Indiana Ave) $272
# STATUS: 230 G=0.01 (W 3140 C 2000 B&O RR)(W 3039 C 2019 Mediterranean Ave)(W 3001 C 1961 Virginia Ave)(W 3098 C 1958 Indiana Ave) $272
##################################################
# Game over!: All players now have more than $3000
##################################################
# STATUS: 231 G=0.01 (W 3140 C 2000 B&O RR)(W 3039 C 2019 Mediterranean Ave)(W 3001 C 1961 Virginia Ave)(W 3098 C 1958 Indiana Ave) $272
# SITES: .B.D.cA.DB.A-CB-B.DC.-.CBaB-dC.DA.--.D.A
[[0 1 1 0 0 0 1 1 0 1]
 [1 1 1 1 1 1 0 0 0 0]
 [0 0 1 1 1 1 0 0 0 1]
 [1 1 0 1 0 0 1 1 1 0]]
###################
# End of simulation
###################
>>>

The Python3 Code

Below is the full code. As previously, all code is unpythonic – apologies to those who are concerned about this.

#############################################
# Monopoly and Prosperity
#############################################

import numpy as np
import random

#############################################
# The Game
#############################################

# Can play either game...
game_rules = 'monopoly'
game_rules = 'prosperity'
# Causes of finishing Monopoly...
turn = 0
gini_index = 0.0
# Causes of finishing Prosperity...
sufficient_wealth = 1500 * 2 # Twice the starting wealth (for all)

#############################################
# Output reporting control
#############################################

# Verbosity flags to aid debugging
RPT_TURN     = 1
RPT_BUY_SELL = 2
RPT_HOUSE    = 4
RPT_RENT     = 16
RPT_STATUS   = 32
RPT_CARD     = 64 # Chance / Community Chest
RPT_MONOPOLY = 128
RPT_DOUBLE   = 256
RPT_WEALTH   = 65536 # bit 17
RPT_EXPECT   = 65536*2
RPT_UNAFFORDABLE = 65536*4
# Edit to control what gets reported e.g.
report = RPT_TURN + RPT_BUY_SELL + RPT_HOUSE + RPT_RENT + RPT_STATUS + RPT_CARD + RPT_MONOPOLY + RPT_DOUBLE
report = RPT_STATUS # Concise normal information provided

#############################################
# Players in the Game
#############################################

# players and player number
NUM_PLAYERS = 4
p_name = ['Aaron', 'Brian', 'Calum', 'David'] # playing in that order

p_state = np.zeros(NUM_PLAYERS, dtype=int)
IS_FREE  = 0
IN_JAIL  = 1
IN_WORKHOUSE  = 2

p_locn    = np.zeros(NUM_PLAYERS, dtype=int)
p_cash    = np.zeros(NUM_PLAYERS, dtype=int)
p_wealth  = np.zeros(NUM_PLAYERS, dtype=int)

#############################################
# Sites on the board
#############################################

# Each site is of a particular type/group...
BROWN   = 0
CYAN    = 1
PINK    = 2
ORANGE  = 3
RED     = 4
YELLOW  = 5
GREEN   = 6
BLUE    = 7
UTILITY = 8
STATION = 9
GO      = 10
TAX     = 11
CHANCE  = 12
CHEST   = 13
GOTOJAIL    = 14
JAIL        = 15
WORKHOUSE   = 16 

NUM_SITES = 40

# All the squares clockwise around the board.
site_group = [ GO,       0, CHEST,    0, TAX, STATION, 1, CHANCE,       1, 1,
              JAIL,      2, UTILITY,  2,   2, STATION, 3,  CHEST,       3, 3,
              WORKHOUSE, 4, CHANCE,   4,   4, STATION, 5,      5, UTILITY, 5,
              GOTOJAIL,  6,    6, CHEST,   6, STATION, CHANCE, 7,     TAX, 7 ]

title_price  = [ 0,  60,   0,  60,   0, 200, 100,   0, 100, 120,
                0, 140, 150, 140, 160, 200, 180,   0, 180, 200,
                0, 220,   0, 220, 240, 200, 260, 260, 150, 280,
                0, 300, 300,   0, 320, 200,   0, 350,   0, 400 ]
NOT_FOR_SALE = 0

# Edit to choose between Atlantic City and London names and between full and abbreviated site names

#London sites
site_name = [       'Go',   'OldKent',    'Chest', 'Whitechapel', 'IncomeTax', 'KingsCross',  'TheAngel',   'Chance', 'EustonRd', 'Pentonville',
                  'Jail',  'PallMall', 'Electric',   'Whitehall',  'Northumb', 'Marylebone', 'BowStreet',    'Chest', 'Marlboro',      'VineSt',
             'WorkHouse', 'TheStrand',   'Chance',     'FleetSt', 'Trafalgar',  'Fenchurch', 'Leicester', 'Coventry',    'Water',  'Piccadilly',
              'GoToJail',  'RegentSt', 'OxfordSt',       'Chest',    'BondSt',  'Liverpool',    'Chance', 'ParkLane', 'SuperTax',     'Mayfair' ]

# Abbreviated makes reports shorter and easier to view
site_name = [     'Go..', 'OldK', 'cmch', 'Wtpl', 'InTx', 'KxSt', 'TheA', 'chnc', 'Eust', 'Pent',
                  'Jail', 'Pall', 'Elec', 'Whll', 'Nrth', 'MySt', 'BowS', 'cmch', 'Marl', 'Vine',
                  'Work', 'Strd', 'chnc', 'Flet', 'Traf', 'FnSt', 'Leic', 'Cvty', 'Wter', 'Picc',
                  'GoTo', 'Rege', 'Oxfd', 'cmch', 'Bond', 'LpSt', 'chnc', 'PkLn', 'SpTx', 'Mayf' ]

# Atlantic City
site_name = [         'Go', 'Mediterranean Ave', 'Community Chest', 'Baltic Ave',      'Income Tax',       'Reading RR',      'Oriental Ave',    'Chance',          'Vermont Ave',   'Connecticut Ave',
                    'Jail', 'St. Charles Place', 'Electric Co',     'States Ave',      'Virginia Ave',     'Pennsylvania RR', 'St. James Place', 'Community Chest', 'Tennessee Ave', 'New York Ave',
              'Poor House', 'Kentucky Ave',      'Chance',          'Indiana Ave',     'Illinois Ave',     'B&O RR',          'Atlantic Ave',    'Ventnor Ave',     'Water Works',   'Marven Gardens',
            'Blueblood\'s', 'Pacific Ave',       'S. Carolina Ave', 'Community Chest', 'Pennsylvania Ave', 'Short Line RR',   'Chance',          'Park Place',      'Super Tax',     'Boardwalk Ave' ]

# Note on South Carolina Ave: https://monopoly.fandom.com/wiki/North_Carolina_Avenue. Similarly on Marvin Gardens.
# Abbreviated makes reports shorter and easier to view
site_name = [ 'Go..', 'Medi',  'cmch', 'Balt', 'InTx', 'RdgR', 'Ornt', 'chnc', 'Verm', 'Conn',
              'Jail', 'StCh',  'Elec', 'Stat', 'Virg', 'PnnR', 'St.J', 'cmch', 'Tenn', 'N.Y.',
              'Poor', 'Kent',  'chnc', 'Indi', 'Illi', 'B&OR', 'Atln', 'Vent', 'Wter', 'Marv',
              'Blue', 'Pcif',  'Caro', 'cmch', 'Penn', 'ShtR', 'chnc', 'PkPl', 'SpTx', 'Bdwk' ]

# Descriptive of groups
site_name = [     'Go...', 'Bron1', 'cm.ch', 'Bron2', 'InTx.', 'Stat1', 'Cyan1', 'chnce', 'Cyan2', 'Cyan3',
                  'Jail.', 'Pink1', 'Util1', 'Pink2', 'Pink3', 'Stat2', 'Oran1', 'cm.ch', 'Oran2', 'Oran3',
                  'Work.', 'Red1.', 'chnce', 'Red2.', 'Red3.', 'Stat3', 'Yelo1', 'Yelo2', 'Util2', 'Yelo3',
                  'GoTo.', 'Gren1', 'Gren2', 'cm.ch', 'Gren3', 'Stat4', 'chnce', 'Blue1', 'SpTx.', 'Blue2' ]

site_name = [     'Go..', 'OldK', 'cmch', 'Wtpl', 'InTx', 'KxSt', 'TheA', 'chnc', 'Eust', 'Pent',
                  'Jail', 'Pall', 'Elec', 'Whll', 'Nrth', 'MySt', 'BowS', 'cmch', 'Marl', 'Vine',
                  'Work', 'Strd', 'chnc', 'Flet', 'Traf', 'FnSt', 'Leic', 'Cvty', 'Wter', 'Picc',
                  'GoTo', 'Rege', 'Oxfd', 'cmch', 'Bond', 'LpSt', 'chnc', 'PkLn', 'SpTx', 'Mayf' ]

group_name = [ 'BROWN', 'CYAN', 'PINK', 'ORANGE', 'RED', 'YELLOW', 'GREEN', 'BLUE', 'UTILITY', 'STATION', 'GO', 'TAX', 'CHANCE', 'CHEST', 'GOTOJAIL', 'JAIL', 'WORKHOUSE' ]

GO_LOCATION        = 0
JAIL_LOCATION      = 10
WORKHOUSE_LOCATION = 20 

#############################################
# Ownership
#############################################

NO_PRICE = -1
NO_OWNER = -1

# Ownership of property is handled by these arrays...
site_owner = np.zeros(NUM_SITES, dtype=int)
# Rather than counting the number of properties of each group every time it is required, we maintain a count...
site_count_ownership = np.zeros((NUM_PLAYERS, 10), dtype=int)

#############################################
# Money
#############################################

community_chest = 0

def credit(player, price, info):
    p_cash[player]  += price
    #if (player == 0): print('# %5d Credit(%d)+=%d (%s)' % (p_cash[player], player, price, info))

def debit(player, price, info):
    p_cash[player]  -= price
    if (p_cash[player] = BROWN) and (the_site_group  1)
            else:
                # Notify when a player owns all sites of the same group
                result = (num == num_sites_in_group[the_site_group])
        else:
            print('ERROR: No monopoly is possible on %s!' % (site_name[location]))
            exit()
    if (result == True) and (game_rules == 'prosperity'): print('DEBUG: There is a monopoly on %s owned by %s!' % (site_name[location], p_name[site_owner[location]]))
    return result

def land_rent(location, player):
    if game_rules == 'prosperity':
         # Monopolies are broken. No multiplier effect.
        return site_base_rent[location][UNIMPROVED]
    elif (player == site_owner[location]):
        # Don't pay Land rent on own property in Monopoly
        return 0
    elif site_group[location] == UTILITY:
        # Don't bother with calculating based on die roll; just use average value 7
        if site_count_ownership[player, UTILITY] == 2:
            return 7 * 10 # If both sites owned, 10 times the roll of the dice
        else:
            return 7 * 4  # If one site owned, 4 times the roll of the dice
    elif (site_group[location] >= BROWN) and (site_group[location] 0) and (player != site_owner[location]):
        if game_rules == 'monopoly':
            factor_to_be_applied = num_sites_in_group_with_the_same_owner_as(location)
            # (This should really be the number of *improved* sites.)
        else:
            factor_to_be_applied = 1 # Monopolies are broken
        if (report & RPT_EXPECT) != 0 and player==0: print('factor ', factor_to_be_applied)
        return site_base_rent[location][factor_to_be_applied]
    else: # No housing_rent chargeable
        return 0

#############################################
# Tracking divergence from equality
#############################################

def next_in_turn(player):
    return (player + 1)%NUM_PLAYERS

def report_wealth(player):
    global title_price
    running_total = p_cash[player]
    for locn in range(NUM_SITES):
        if site_owner[locn] == player:
            LP = title_price[locn]
            running_total += LP
    if (report & RPT_WEALTH) != 0: print('# report_wealth(%d): total = %d' % (player, running_total))
    return running_total

def total_outgoings(player):
    # The amount a player x would have to pay if they landed on every square
    running_total = 0
    for locn in range(NUM_SITES):
        if (site_owner[locn] != player):
            running_total += land_rent(locn, player) + housing_rent(locn, player)
            if (report & RPT_EXPECT) != 0 and player==0: print('#outgoings for %s at %12s = %d land & %d housing = %d so far' %(p_name[player], site_name[locn], land_rent(locn, player), housing_rent(locn, player), running_total))
        elif game_rules == 'prosperity':
            running_total += land_rent(locn, player) # Still have to pay land rent on your own site
            if (report & RPT_EXPECT) != 0 and player==0: print('#outgoings for %s at %12s = %d land = %d so far' %(p_name[player], site_name[locn], land_rent(locn, player), running_total))
    return running_total

# Calculate the Gini coefficient which is the ratio of
#   the area under the Lorenz curve (cumulative distribution)
# divided by
#   the area under a 'fair' Lorenz curve.
# Code is based on:
#   https://planspace.org/2013/06/21/how-to-calculate-gini-coefficient-from-raw-data-in-python/
# A more Pythonic alternative is at:
#   https://stackoverflow.com/questions/39512260/calculating-gini-coefficient-in-python-numpy
# Modification to work better with small sample size N:
#   I am multiplying by N/(N-1) so that 'completely unfair' e.g. (0, 0, 0, 1) produces gini(x)=1 rather than (N-1)/N.
def gini_coefficient(list_of_values):
    num_samples = len(list_of_values)
    height, area = 0, 0
    for value in sorted(list_of_values):
        height += value
        area += height - value / 2.
    fair_area = height * num_samples / 2.
    result = ((fair_area - area) / fair_area)*num_samples/(num_samples-1)
    return result

#############################################
# Game turn
#############################################

def setup_game(play='fair'):
    turn = 0
    community_chest = 0
    site_owner[0:]      = [NO_OWNER] * NUM_SITES
    p_locn[0:] = [GO_LOCATION] * NUM_PLAYERS
    if play == 'very_unfair':
        BIG_LANDLORD = 0 # Player #0
        p_cash[0:]    = [1500] * NUM_PLAYERS
        p_cash[BIG_LANDLORD] = 10000
        buy_everything(BIG_LANDLORD)
        improve_on_everything(BIG_LANDLORD)
    else:
        p_cash[0:]    = [1500] * NUM_PLAYERS

def report_status():
    global gini_index
    # shows player info: cash and location, plus the cash in the community chest.
    gini_index = gini_coefficient(p_wealth)
    print('# STATUS: %d G=%.2f ' % (turn, gini_index), end='')
    for plyr in range(NUM_PLAYERS):
        print('(W%5d ' % (p_wealth[plyr]), end='')
        print( 'C%5d ' % (p_cash[plyr]), end='')
        print(  '%s)' % (site_name[p_locn[plyr]]), end='')
    print(' $%d' % (community_chest))

def summarize_sites():
    print('# SITES: ', end='')
    for l in range(NUM_SITES):
        if (site_group[l]>STATION):
            print('.', end='') # Can't buy
        elif (site_owner[l] == NO_OWNER):
            print('-', end='') # Not bought
        elif (site_improvements[l] > 0): # Has a house on it
            name = p_name[site_owner[l]]
            print('%s' % (name[0].upper()), end='') # Upper case initial
        else: # No house
            name = p_name[site_owner[l]]
            print('%s' % (name[0].lower()), end='') # Lower case initial
    print('')

def i_can_afford_it(player, price): # Based on my cash being higher than that required in the next few rounds!
    return price  10):
                    if (report & RPT_CARD) != 0: print('# INFO: %s is paying $10 for an Absolute Necessity' % (p_name[player]))
                    debit(player, 10, 'chance')
                    community_chest      += 10
            else:
                # Local rules: have the option to take a Chance card.
                # In this automated game, always choose not to.
                print('# INFO: %s has decided not to take a chance' % (p_name[player]))
    elif site_group[p_locn[player]]== CHEST: # Community Chest
        if (game_rules == 'monopoly'):
            # Local rules: have the option to take a Community Chest card.
            # In this automated game, always choose not to.
            if (report & RPT_TURN) != 0: print('# INFO: %s does not get involved with the Community Chest' % (p_name[player]))
        else: # prosperity
            if community_chest > NUM_PLAYERS: # Sharing out: At least $1 to distribute!
                if (report & RPT_CARD) != 0: print('# Distributing the Community Chest')
                fee = community_chest // NUM_PLAYERS # (floor division)
                for plyr in range(NUM_PLAYERS):
                    if (report & RPT_CARD) != 0: print('# INFO: %s is receiving $%d from the Community Chest' % (p_name[plyr], fee))
                    credit(plyr, fee, 'payout')
                    community_chest      -= fee
    else: # A group site (housing color, station or utility)
        ###print('DEBUG_POINT3')
        #################################
        # Should there be a forced sale? (to break a monopoly)
        #################################
        ##if there_is_a_monopoly(p_locn[player]):
        #if (game_rules == 'prosperity'):
        #    #if num_sites_in_group_with_the_same_owner_as(p_locn[player]) > 1:
        #    if site_count_ownership[site_owner[p_locn[player]], site_group[p_locn[player]]] > 1:
        #        print('DEBUG_POINT3 AT %s' % (site_name[p_locn[player]]))
        #######        print(site_count_ownership)
        #if num_sites_in_group_with_the_same_owner_as(p_locn[player]) > 1:
        if site_count_ownership[site_owner[p_locn[player]], site_group[p_locn[player]]] > 1:
            if (game_rules == 'prosperity') and (player != site_owner[p_locn[player]]):
                # Monopoly only broken if the player landing on the site is not the monopoly owner!
                ######summarize_sites()
                if (report & RPT_BUY_SELL) != 0:
                    print('# INFO: %s is forced to sell %s to break monopoly' % (p_name[site_owner[p_locn[player]]], site_name[p_locn[player]]))
                    print(site_count_ownership)
                # Reimburse for any improvement:
                if site_improvements[p_locn[player]] == 1:
                    site_improvements[p_locn[player]] = 0
                    credit(site_owner[p_locn[player]], improvement_price[site_group[p_locn[player]]], 'reimbursement')
                sell_property(site_owner[p_locn[player]], p_locn[player], title_price[p_locn[player]])
        #################################
        # Will the site be bought?
        #################################
        ###print('DEBUG_POINT4')
        ###print(site_owner[p_locn[player]])
        ####print(title_price[p_locn[player]])
        if site_owner[p_locn[player]] == NO_OWNER:
            ###print('DEBUG_POINT3')
            price_to_buy = title_price[p_locn[player]]
            if i_can_afford_it(player, price_to_buy):
                ##########if (report & RPT_BUY_SELL) != 0: print('# INFO: %s is buying %s for $%d' % (p_name[player], site_name[p_locn[player]], price_to_buy))
                count = site_count_ownership[player, site_group[p_locn[player]]]
                #if (game_rules == 'prosperity') and there_is_a_monopoly(p_locn[player]):
                if (game_rules == 'prosperity') and (count > 0):
                    if (report & RPT_BUY_SELL) != 0: print('# INFO: %s not allowed to buy %s' % (p_name[player], site_name[p_locn[player]]))
                    ####print('DEBUG_POINT7')
                else:
                    ######summarize_sites() ##### DEBUG to see why players can buy towards a monopoly...
                    ######print(num_sites_in_group_with_the_same_owner_as(p_locn[player]))
                    #####print(there_is_a_monopoly(p_locn[player]))
                    buy_property(player, p_locn[player], price_to_buy)
                    #####print(site_count_ownership) ##### DEBUG to see why players can buy towards a monopoly...
            else:
                if (report & RPT_UNAFFORDABLE) != 0: print('# INFO: %s cannot afford to buy %s' % (p_name[player], site_name[p_locn[player]]))

        #################################
        # Will rent be paid?
        #################################
        if (player != site_owner[p_locn[player]]):
            if (report & RPT_TURN) != 0: print('# INFO: %s owns %s' % (p_name[site_owner[p_locn[player]]], site_name[p_locn[player]]))
            fee = land_rent(p_locn[player], player)
            if (game_rules == 'prosperity'):
                # Pay Land Rent to the Community Chest (including owners of the site)
                if (report & RPT_RENT) != 0: print('# INFO: %s is paying $%d Land Rent for %s' % (p_name[player], fee, site_name[p_locn[player]]))
                debit(player, fee, 'land rent')
                community_chest      += fee
            elif player != site_owner[p_locn[player]]: # monopoly rules
                # Pay Land Rent to the owner
                if (report & RPT_RENT) != 0: print('# INFO: %s is paying $%d Land Rent to %d for %s' % (p_name[player], fee, site_owner[p_locn[player]], site_name[p_locn[player]]))
                debit(player, fee, 'land rent')
                credit(site_owner[p_locn[player]], fee, 'let land')
                # Pay Housing Rent to the owner if applicable
                if player != site_owner[p_locn[player]]:
                    fee = housing_rent(p_locn[player], player)
                    if (report & RPT_RENT) != 0: print('# INFO: %s is paying $%d House Rent to %d for %s' % (p_name[player], fee, site_owner[p_locn[player]], site_name[p_locn[player]]))
                    debit(player, fee, 'house rent')
                    credit(site_owner[p_locn[player]], fee, 'let house')
        # (Code is not implementing the jump +/-8 rule on stations)

    for player2 in range(NUM_PLAYERS):
        p_wealth[player2] = report_wealth(player2)

    # Running status:
    # shows player info: cash, 'gain' and location, plus the cash in the community chest.
    # 'Gain' is an estimate of how quickly cash will increase or (if negative) decrease.
    if ((report & RPT_STATUS) != 0): report_status()
    ######if report_the_status: summarize_sites()

#############################################
# Game play
#############################################

def threw_a_double(dice_throw):
    return dice_throw[0] == dice_throw[1]

def play_game(max_turns, max_gini):
    global p_locn
    global p_cash
    global site_owner
    global site_count_ownership
    global site_improvements
    global turn
    global game_rules
    global report

    print('#####################')
    if (game_rules == 'prosperity'):
        print('# Let\'s play Prosperity!')
    elif (game_rules == 'monopoly'):
        print('# Let\'s play Monopoly!')
    else:
        print('# ERROR: Bad game')
        exit()
    print('#####################')           

    turn = 1
    player = 0 # Player numbers are arbitrary. Fixed starting player (not rolling die and seeing who has the highest number)
    finish = False
    while (turn <= max_turns) and not finish:
        if (site_group[p_locn[player]]== WORKHOUSE) and (p_cash[player] = max_gini):
            finish = True
            print('##################################################')
            print('# Game over!: Gini index %.2f has exceeded %.2f' %(gini_index, max_gini))
            print('##################################################')
        elif (game_rules == 'prosperity'):
            # prosperity: continues until all players have sufficient wealth
            finish = True # until proven otherwise...
            for plyr in range(NUM_PLAYERS):
                if p_wealth[plyr] < sufficient_wealth:
                    finish = False
            if finish:
                print('##################################################')
                print('# Game over!: All players now have more than $%d' % (sufficient_wealth))
                print('##################################################')
        if (turn % 100 == 99) or finish:
            # Every so often, and at the very end, provide a snapshot of ownership
            #print('# Number of sites owned by each player, on each site group BROWN...BLUE + UTILITIES + STATION')
            #for p in range(NUM_PLAYERS):
            #####    print(site_count_ownership[p])
            #for l in range(NUM_SITES):
            #    if site_owner[l] != NO_OWNER:
            #        print('Site %s owned by %s with %d houses' % (site_name[l], p_name[site_owner[l]], site_improvements[l]))
            report_status()
            summarize_sites()
            #print(site_owner)

#############################################
# Start of program execution
#############################################

# Deterministic behaviour: The seed for random number generation is not based on time/date:
random.seed(1) # Arbitrary number

if False: # Monopoly only
    setup_game(play='fair')
    game_rules = 'monopoly'
    play_game(max_turns=5000, max_gini=0.99)

if False: # Prosperity only
    report = RPT_STATUS + RPT_BUY_SELL + RPT_HOUSE
    setup_game(play='fair')
    game_rules = 'prosperity'
    play_game(max_turns=500, max_gini=0.40)

if True: # Monopoly then Prosperity
    report = RPT_STATUS + RPT_BUY_SELL + RPT_HOUSE
    setup_game(play='fair')
    game_rules = 'monopoly'
    play_game(max_turns=1000, max_gini=0.95)
    game_rules = 'prosperity'
    play_game(max_turns=1000, max_gini=0.99)

if False: # Monopoly then Prosperity
    setup_game(play='fair')
    game_rules = 'monopoly'
    play_game(max_turns=5000, max_gini=0.95)
    game_rules = 'prosperity'
    sufficient_wealth = 1000000 # Never! Let 'max_turns' stop the sim
    play_game(max_turns=5000, max_gini=0.99)

print(site_count_ownership)        

print('###################')
print('# End of simulation')
print('###################')           

This entry was posted in Uncategorized and tagged , , , , . Bookmark the permalink.

3 Responses to Monopoly and Prosperity

  1. Paul Tengan says:

    Very interesting, despite complexity in figuring out rents. But that could be automated.

    How can the educational value be improved by a version that addresses “tragedy of the commons?”

    Modified with a self replenishing and growing commons, allowing for ever increasing productivity?

  2. Jude Lieber says:

    Thank you for this post! I just learned about the history of Monopoly, a game I always felt encouraged greed until I found out about the alternate rules. I’m looking forward to playing this with my wife and sons, ages 13 and 14, to teach them a little about equality and have some fun at the same time.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s