Home / Psets / Problem Set 4: Blackjack Game Simulation

Problem Set 4: Blackjack Game Simulation

The questions below are due on Monday April 27, 2020; 11:00:00 PM.
 
You are not logged in.

If you are a current student, please Log In for full access to the web site.
Note that this link will take you to an external site (https://shimmer.csail.mit.edu) to authenticate, and then you will be redirected back to this page.
Download Files

In this PSET, you will finish the implementation of a Blackjack game system, and then use simulation to analyze the performance (how much money can be made) from a few different strategies of how one could play the game. For anyone not familiar with Blackjack yet, don’t worry; the rules are explained throughout this document as well as within the docstrings of the Python code.

MIT Trivia aside: the movie “21” was based on MIT Blackjack players!


What is Blackjack?

Blackjack, also known as Twenty-One, is a card game usually played with one or more standard decks of cards. A standard deck of cards contains 52 cards, 13 each of 4 suits: clubs, diamonds, hearts, and spades. There are 13 cards for every suit with the following ranks: A (ace), 2, 3, 4, 5, 6, 7, 8, 9, 10, J (Jack), Q (Queen), and K (King). Cards have different point values based on their rank.

Point values of the cards:

  • Face cards (Jack, Queen, King): 10 points
  • Ace: either 1 point or 11 points
  • All others: numerical value on card

The objective of the game is to get the sum of your card point values as close to 21 without exceeding it. The player (or the dealer) busts if their points go over 21.

Here is a simplified progression of the game:

  1. Player wagers an initial bet for the hand ​before the cards are dealt.
  2. One card is dealt face up to the player, and then one card is dealt face up to the dealer. Another card is dealt face up to the player, and then another card is dealt face down to the dealer. The face-down card is the hole-card, ​and it is hidden from the player.
  3. The player (or the dealer) has a blackjack if the point values of the 2 cards initially dealt to them add up to exactly 21 (an Ace and a card with value 10).
    • If the dealer gets a blackjack, and the player does not, the dealer automatically wins the hand.
    • If the player gets a blackjack, and the dealer does not, then they win the hand.
    • If both the dealer and player get blackjack, neither party wins, and the hand ends.
    • Otherwise, game play continues with the next step.
  4. The player has fewer than 21 points, so they have two options:
    • Hit: ​Request another card. The player can do this as many times as they want in a single turn.
    • Stand: ​​Indication to keep the current cards. Player stays at the current best value of their cards.
    • Double-Down: The player doubles their bet and hits one more time, but then must stand (they do not have the option to keep hitting).
  5. The dealer will always employ the same basic strategy. If the dealer does not have 21, they hit until they get to a value of 17 or above. This is also known as “stand on soft 17.” For one of the gameplay strategies under consideration, you will analyze the performance of when the player “mimics” the dealer’s strategy and plays this way too (later in the PSET).

End game scenarios

Based on the best value of their cards at the end of the hand, either the player wins the hand, the dealer wins the hand, or they tie (otherwise known as a BlackJack “push”).

If either the player or dealer’s best value of their cards is over 21, they let their value become too large, so we say they went “bust,” or are “busted.”

If the player loses the hand (by either being beat by the dealer’s best value, or from the player going “bust”) they lose the amount currently bet on the hand (in other words, they receive 0 back).

The amounts the player receives at the end of the hand is calculated as follows:

  • 2.5 times the bet of the hand if the player's first two cards equal 21, and the dealer's first two cards do not equal 21 (player has BlackJack).
  • 2 times the bet of the hand if the player wins by having a higher best value than the dealer after the dealer's turn concludes
  • 2 times the bet of the hand if the dealer busts
  • The exact bet amount of the hand if the game ends in a tie. If the player and dealer both get blackjack from their first two cards this is also a tie.
  • 0 if the dealer wins with a higher best value, or the player busts.

Getting Started - The Code

  • blackjack.py – implement the functions in this file to complete the pset. Turn this in when you are done.
  • ps4_classes.py – contains class definitions that will be helpful for the pset. Do not modify.
  • Do not rename files, change function/method names, or delete/edit given docstrings.
  • Please review the Style Guide on Stellar. Points will be deducted if there are violations.

1) Problem 1: Implementing Strategies

We will be representing a hand of Blackjack using the BlackJackHand class, which keeps track of the deck and the cards dealt to the player and the dealer. You will be implementing 5 different playing strategies as part of this problem:

  • Dealer-Copy Strategy: The player will mimic the strategy used by the dealer to determine their next move. In other words, the player will hit until the best value of their cards (i.e. best sum of their cards) is greater or equal to 17.
  • Cheating strategy: The player “peeks” to check the best value of the dealer’s cards, and decides whether to hit or stand based on how their best card value compares. The player will hit until the best value of their cards is greater or equal to the best value of the dealer’s cards.
  • Simple strategy: The player will hit until either of these two cases is true: (1) the player’s best value is greater than or equal to 17 or (2) the player’s best value is between 12 and 16 (inclusive) AND the dealer’s face up card is between 2 and 6 (inclusive).
  • DD (Doubledown) Strategy: This is an augmented version of simple strategy, where the moves of the player are the same as using the simple strategy, except when the best_value of the player's hand is 11. When this scenario is encountered, the strategy indicates the player should "doubledown," or double the current bet of the hand and request one final hit before standing.
  • Random Strategy: This strategy reflects how most of us (TAs included) actually play the game. If the best value is low, we hit, if it’s high, we stand, if it’s in the middle between low and high, we just randomly choose whether to hit or stand. Hence in this strategy, a player will stand if the best value of his/her cards is above or equal to 16; a player will hit if the best value is below or equal to 12; and a player will toss a coin and choose to hit if the coin toss results in a head, and stand otherwise.

Implement the methods in the BlackJackHand class, as per the docstrings. You may find the classes defined in ps4_classes.py helpful when implementing BlackJackHand.

You should now pass the following tests in test_ps4_student.py:

test_#_best_value_no_aces_*,
test_#_best_value_one_ace_*,
test_#_best_value_multiple_aces_*,
test_#_dealer_copy_strategy_*,
test_#_cheating_strategy_*,
test_#_simple_strategy_*,
test_#_doubledown_strategy_*,
test_#_random_strategy_*,
test_#_play_player_turn_*,
test_#_play_dealer_turn_*

2) Problem 2: Play Hand (One 'round' of BlackJack)

Now that you have implemented the strategies and rules for playing a hand of Blackjack in BlackJackHand, let’s implement the logic required to play one round of Blackjack and to determine how much money the player receives at the end of the game.

Note: One hand involves a player going until they bust or stand followed by the dealer going until they bust or stand. The player and dealer do NOT alternate turns; the player plays their turn first, and then the dealer plays their turn.

At the end of the game the player will receive:

  • 2.5 times the bet of the hand if the player's first two cards equal 21 and the dealer's first two cards do not equal 21.
  • 2 times the bet of the hand if the player wins by having a higher best value than the dealer after the dealer's turn concludes
  • 2 times the bet of the hand if the dealer busts
  • the exact bet amount of the hand if the game ends in a tie. If the player and dealer both get blackjack from their first two cards, this is also a tie.
  • 0 if the dealer wins with a higher best value, or the player busts.

Implement this logic in the function play_hand in blackjack.py. This function should return a tuple (float, float) of the current bet of the hand, along with the total amount of money the player gets back (0 if they lost the hand). Remember, the amount they win includes the amount they initially bet; use the current bet of the hand.

You should now pass the following tests in test_ps4_student.py:

test_#_play_hand_copy_*,
test_#_play_hand_cheating_*,
test_#_play_hand_simple_*,
test_#_play_hand_doubledown_strategy_*,
test_#_play_hand_random_strategy_*

3) Problem 3: Blackjack Simulation

This step will implement functionality to analyze the overall performance – or how much money one might make on average – when playing with the 4 different strategies by simulating gameplay over many iterations (trials).

Create a simple simulation that determines the average and standard deviation for the rate of return associated with a given playing strategy. Your simulation should be able to run many trials. Each trial may have multiple hands of Blackjack, but the same deck of cards should be used across all trials. For each trial, calculate the rate of return after playing all the hands. If the player lost money, then the total amount of money earned—and thus the rate of return—will be negative.

*rate of return* (%) $= 100*$ $\frac{total \: money \: received - total \: money \: bet}{total \: money \: bet}$

Once you have determined the rate of return for each trial, find the mean and standard deviation across all the trials. You should then plot the distribution of rates of return using a normal distribution.

Normal Distributions
Normal Distributions are a useful way of visualizing simple probability distributions because of their nice properties. Normal Distributions...

  1. are defined by their mean (μ) and standard deviation (σ)
  2. are symmetric around their mean
  3. have 68% of the area under the curve within one standard deviation of the mean
  4. have 95% of the area under the curve within two standard deviations of the mean
Here are 3 examples of a Normal Distribution. The green one has a very small standard deviation, which means that most samples from this distribution will be very close to each other. The **black** one has a very large standard deviation, which means that you are less likely to correctly predict where any one sample may fall. The red distribution is in between the other two.

You may find matplotlib.pyplot and scipy.stats.norm.pdf helpful in generating the required plots. Remember to include the title, x_axis, corresponding labels, and underlying histogram in your final plot.

Here is an example:

Implement the function run_simulation. This function takes in a boolean parameter show_plot, which determines whether or not to display the plot (when true), or (when false) to just calculate and return the rates_of_return, average, and standard deviation.

Checklist for run_simulation plot:

  • Title with…
    • Strategy
    • Mean ROI
    • Standard deviation of ROI
  • X-axis label
  • Histogram of ROIs
  • Gaussian curve on top of histogram

Finally, we want a way to visually compare the four strategies we implemented in problem 1.

Implement the function run_all_simulations. The function runs the simulations for each strategy and displays a single graph with one normal distribution for each of the strategies. Notice the legend. It is what is differentiating one graph from the other.

Here is an example:

Checklist for run_all_simulation plot:

  • Title
  • X-axis label
  • 3 Gaussian curves
  • Legend

You should now pass these tests in test_ps4_student.py:

test_#_run_simulation_copy,
test_#_run_simulation_cheating,
test_#_run_simulation_simple,
test_#_run_simulation_doubledown

Congratulations! You are ready for the casino!

Hand-In Procedure

1. Save

Save your solution as blackjack.py

2. Time and Collaboration Info

At the start of ps1.py, in a comment, write down the number of hours (roughly) you spent on the problems in that part, and the names of the people you collaborated with. For example:

  # Problem Set 4
  # Name: Jane Lee
  # Collaborators: John Doe
  # Time: 8 hours

3. Sanity checks

After you are done with the problem set, run your files and make sure they run without errors.

Note: Passing all of the tests in the local tester does not necessarily mean you will receive a perfect score. The staff will run additional tests on your code to check for correctness.

4) Submission

The tester file contains a subset of the tests that will be run to determine the problem set grade.

You may upload new versions of each file until the 9PM deadline, but anything uploaded after that time will be counted towards your late days, if you have any remaining. If you have no remaining late days, you will receive no credit for a late submission.

When you upload a new file with the same name, your old one will be overwritten.

 No file selected