A presentation based on the concepts and ideas from this article was delivered to the VegasPy Python User Group in December 2020. Video of the presentation can be viewed on YouTube.

Earlier in 2020, just before COVID-19 became a pandemic in the United States, HBO aired the documentary McMillion$, about a cheating scandal surrounding the McDonald’s Monopoly promotional game in the 1990s.

For those unfamiliar, McDonald’s ran this promotion nearly every year starting in 1987 in the U.S. and later in other countries as well. The promotion was based on a game board similar to a Monopoly board, with groups of squares associated by color, each of which corresponds to a prize. McDonald’s customers received game pieces with their food items, and by collecting all the pieces in a color group, the customer won the designated prize. There were also instant-win prize pieces which didn’t need to be matched up with any other pieces. The top prize in the U.S. game most (all?) years was $1 million.

Although McDonald’s doesn’t provide details, the fact they’ve run the game so many times and expanded it across the globe is a clear indication the game is popular and boosts visitation. The genius of the game is the need to collect all the pieces in a group, necessitating multiple visits.

As it turned out, someone was stealing the extremely rare game pieces representing the $1 million, other large cash prizes, as well as cars and more, then either selling them or distributing to friends, family and associates. After many years, the FBI was notified of the fraud via an anonymous tip, and started an investigation to find the perpetrator. The documentary was nominated for 5 Primetime Emmys, the characters in the story were generally quite entertaining.

Why am I writing about any of this? The attention on the Monopoly promotion reminded me of a fascinating project I previously worked on, when a casino's marketing team wanted to run a very similar promotion. Like the McDonald’s game, they imagined a game with color groups (instead of streets, squares would be named after the casino’s bars and restaurants), each of which was associated with a cash prize. Also like the McDonald's game, they wanted the game to run for an extended period, about 3 weeks. Guests would be awarded a limited number of game pieces per day, although instead of food items, pieces would be earned based on gambling activity, specifically, meeting certain tier credit thresholds. And they planned a $50,000 grand prize.

My role was to figure out all the math behind the game, to determine the correct prize amounts and more importantly, the frequency of pieces so that the total value of all prizes awarded aligned with the team's marketing budget. The team made one important change, which was to award the grand prize to the first customer to collect at least one of every piece, rather than just having a single, extremely rare game piece representing the grand prize. This was a great idea for a number of reasons, but it also added the the complexity of the game math, because we wanted to be near-certain that somebody would eventually complete the board and collect the grand prize, but also wanted it to remain unclaimed until the last possible moment, in order to keep the anticipation building as long as possible. We also didn’t know how many total game pieces we would need to print. Without solving for all of these unknowns, we couldn’t be confident the game would be a success.

It was quickly clear that the best way to approach this problem was via a Monte-Carlo method, which entails building a game simulation and executing it thousands of times to hone in on the expected values for the questions we needed to answer. But before we'd be able to simulate the game, we needed to make an educated guess regarding how many players would participate, and how many pieces each of them would likely earn.

I started by collecting and reviewing historical data on guest counts at various earning levels and visit frequency, to estimate the number of individual players who would earn various numbers of tier credits, and also how many players might visit once, twice, and all the way up to every day of the promotion. We had to assume that some players would earn the maximum number of game pieces every day of the promotion, and wanted to set the odds so that even those players would be unlikely to complete the entire board until very close to the end of the promotional period.

example of player count forecasts:

# a possible distribution for a 7-day game with max. 3 pieces earned per day

# example: we expect 1000 players to earn 1 piece, expect 600 players to earn 2 pieces, etc. up to a max of 21 pieces

expected_players = {
     1 : 1000 ,  2 : 600 ,  3 : 400 ,  4 : 300 ,  5 : 250 , 
     6 : 200 ,   7 : 180 ,  8 : 160 ,  9 : 140 , 10 : 120 , 
    11 : 100 ,  12 : 90 ,  13 : 80 ,  14 : 70 ,  15 : 60 , 
    16 : 50 ,   17 : 40 ,  18 : 30 ,  19 : 15 ,  20 : 25 , 21 : 40 
}

The next step was to build the game simulation -- in other words, write a script or program to emulate an individual picking game pieces from a random bucket, then calculate all the groups completed, convert those groups to prize dollars, add on additional prizes (the marketing team also added a small prize for collecting 3-of-a-kind, which we implemented to reduce frustration among the customers who were collecting lots of pieces), and repeat for every player at every number of pieces, and total up the individual results. A complete game simulation written in Python, which you can tweak to build your own game, is available here.

Finally, it was just a matter of experimenting with various game configurations – the prize amounts, the relative rarity of specific pieces, the frequency of instant win prizes – and running each configuration through the simulation script. After each simulation, I’d tweak some of the initial configuration parameters to try to get closer to the optimal result. For example, if a simulation showed that the expected costs were lower than budgeted, I could increase a prize amount, or make a rare piece a little more common, thereby making it easier to complete that color group, then re-run the simulation to see the effect of the change.

example of a game configuration:

we define the groups, the prize for each group, and the relative frequency of each game piece

# here's where we define the piece names, the prizes for each set, and the probability (ratio) of picking each piece
# Monopoly uses street names in Atlantic City, we'll use street names from other cities
combosets = { 
    # define our combos -- piece names, prize amount, and piece ratio
    # ratios are universally relative... a piece with ratio 6 will be twice as common as a ratio of 3, 
    #     even across different groups
    # groups should be set up with one rare piece, the higher the value of the group, the rarer the final piece should be
  'New York' : {
    'prize' : 50,
    'pieces' : {
      'Wall Street' : {'ratio' : 6 } ,
      '5th Avenue' :  {'ratio' : 6 } ,
      'Broadway' :    {'ratio' : 3 }
    }
  } ,  
  'Las Vegas' : {
    'prize' : 100,
    'pieces' : {
      'Tropicana Ave' :  {'ratio' : 4 } ,
      'Fremont St' :     {'ratio' : 4 } ,
      'Las Vegas Blvd' : {'ratio' : 1 }
    }
  } ,      
  'Los Angeles' : {
    'prize' : 300,
    'pieces' : {
      'Pacific Coast Hwy' : {'ratio' : 6 } ,
      'Sunset Blvd' :        {'ratio' : 6 } ,
      'Rodeo Drive' :        {'ratio' : 1 }
    }
  } ,  
  # offer instant prizes for specific pieces that aren't part of a combo
  'InstantChicago' : {
    'prize' : 20,
    'pieces' : {
      'Michigan Ave' : {'ratio' : 4 } 
    }
  } , 
  'InstantNewOrleans' : {
    'prize' : 40,
    'pieces' : {
      'Bourbon Street' : {'ratio' : 2 } 
    }
  }  
}

# you can also offer a prize to avoid discouragement when players get multiples of the same piece
#   for example, 3 identical pieces = $25
duplicate_award = { 'duplicates' : 3 , 'prize' : 25 }

# entire board grand prize - to the first person to cover the entire board, i.e. collect at least 1 of every piece
#   this should be guaranteed, i.e. given away via drawing if not won - but, we will try to set p(at least 1 winner) > 95%
grand_prize = 50000

Once the full program has been built, it only takes a few seconds to run a new simulation, so it is easy to iterate through various ideas and settle upon a handful of configurations that yield near-optimal results.

total_expected_cost

268330.663

prob_at_least_one_winner

0.9424117886038211

# the total number of game pieces you need to print should be the total expected from all player counts, 
#   plus an extra safety margin if the game is more popular

game_pieces_needed = sum([ k * v for (k,v) in expected_players.items() ]) * 1.25
game_pieces_needed

25993.75

The simulation above yields a total expected prize expense of about $268,000. If the budget was $300,000, the prize amounts should be increased. For example, after some trial-and-error, setting Las Vegas to $150 and Los Angeles to $400 increases the expected cost to $297,000. Alternatively, upping the frequency ratio of the rare Las Vegas Blvd and Rodeo Drive game pieces (adjusting the ratio to 1.5, from 1) sets the total expected cost to about $298,000. With the simulation code we've built, we can expand the game to accommodate many more pieces and combinations, any prize amounts, and longer game periods (instead of 7 days as in the example, we could easily set up a 14-day, 21-day, or any number).

This simulation-based approach was relatively easy to build, was fast to run and iterate on, and allowed for thousands and thousands of individual simulation runs, providing confidence in the result output. I was able to present the marketing team with multiple game configurations that would meet the expense budget and produce an exciting promotion. When the casino actually ran the game, it played out almost exactly as anticipated, with the total prizes within about 3% of the total budget, and the grand prize claimed on the 20th day of a 21-day promotion. The excitement and the buzz among the top players vying for that grand prize in the final few days, with many of them just one piece missing, was extreme. Everybody – the marketing team, the front-line staff, and of course the players – were asking for constant updates every time a top player revealed a new piece, as we were all aware that multiple players were very close to finally winning the grand prize. The promotion was so successful, in fact, that the casino repeated the promotion at least 5 more times, most recently in September 2019!

One last note: unless you want to end up being investigated by the FBI, make sure to protect all your game pieces! Just ask McDonald's!

Interested in creating your own "McDonald's Monopoly"-style promotion? Customize the simulation code to configure your own game, or allow me to help you out!