Let’s Play Blackjack (with Python)

Coding Up our Simulator

You can find the code in its entirety on my GitHub hera. It probably would have been a effective idea to use object oriented scheduling. But at this point, I am not however used to writing code in that way. I will probably revise my code at some point in the future to be object oriented ; but that is a project for another day. To start, let ’ s get our input statements out of the way :

 meaning numpy as nurse practitioner 
consequence lesser panda as palladium
import random
import matplotlib.pyplot as plt
significance seaborn as tin

now let ’ s make a few functions to help us out. first, we need a function that creates a new deck of cards for us to play with. The make_decks function does fair that — it adds four of each menu character ( angiotensin converting enzyme, 2, 3, 4, etc. ) to the number new_deck, shuffles new_deck, and returns the newly created list ( pack of cards ) for us to play with. besides note that we can specify via num_decks how many decks we want the routine to create .

 # Make a deck 
def make_decks ( num_decks, card_types ) :
new_deck = [ ]
for one in range ( num_decks ) :
for j in crop ( 4 ) :
new_deck.extend ( card_types )
random.shuffle ( new_deck )
return new_deck

We besides need a affair that can add up the value of the cards in our pass. It is slenderly more complicate than simple summation because aces can be worth either 1 or 11, depending on whichever is most advantageous to its holder. so our function first gear tallies up the value of each non-ace calling card in the hand ( I represent all face cards with the count 10 as they are all functionally the same in blackmail ). then it counts up the number of aces. last, it determines how much each one should be worth depending on the value of the rest of your cards. Corrections: In my former version of the code below, there was an error. To fix it, I added the benefactor officiate ace_values which takes as remark the number of aces in your hand as an integer and outputs a list of alone values that your aces could be worth. Figuring out the permutations ( and their sums ) for a given issue of aces was more work than I thought and I needed to write the come 2 assistant functions to get it done ( fore more details, please refer to my comments in the following code jam ) :

 # This affair lists out all permutations of breeze through values in the 
# array sum_array.
# For example, if you have 2 aces, there are 4 permutations :
# [ [ 1,1 ], [ 1,11 ], [ 11,1 ], [ 11,11 ] ]
# These permutations lead to 3 singular sums : [ 2, 12, 22 ]
# Of these 3, lone 2 are < =21 so they are returned : [ 2, 12 ]
def get_ace_values ( temp_list ) :
sum_array = np.zeros ( ( 2**len ( temp_list ), len ( temp_list ) ) )
# This loop gets the permutations
for i in range ( len ( temp_list ) ) :
normality = len ( temp_list ) - i
half_len = int ( 2**n * 0.5 )
for rep in range ( int ( sum_array.shape [ 0 ] /half_len/2 ) ) :
sum_array [ rep*2**n : rep*2**n+half_len, one ] =1
sum_array [ rep*2**n+half_len : rep*2**n+half_len*2, one ] =11
# only return values that are valid ( < =21 )
refund list ( set ( [ int ( randomness ) for mho in np.sum ( sum_array, axis=1 ) \
if s < =21 ] ) ) # Convert num_aces, an int to a list of lists
# For case if num_aces=2, the output should be [ [ 1,11 ], [ 1,11 ] ]
# I require this format for the get_ace_values function
def ace_values ( num_aces ) :
temp_list = [ ]
for one in range ( num_aces ) :
temp_list.append ( [ 1,11 ] )
render get_ace_values ( temp_list )

The above two functions can now be used by the routine total_up, which like I mentioned above, calculates the value of the cards in our bridge player ( including the right handle of any aces ) :

 # Total up value of hand 
def total_up ( hand ) :
aces = 0
entire = 0

for card in hand :
if wag ! = 'A ' :
entire += batting order
else :
aces += 1

# Call function ace_values to produce list of potential values
# for aces in hand
ace_value_list = ace_values ( aces )
final_totals = [ i+total for i in ace_value_list if i+total < =21 ]

if final_totals == [ ] :
retort min ( ace_value_list ) + total
else :
retort soap ( final_totals )

now that our benefactor functions are out of the way, let ’ s move on to the chief loop. First, I define my key variables :

  • stacks is the number of card stacks (where each card stack can be one or more decks) we will simulate.
  • players is the number of players in each simulated game.
  • num_decks is the number of decks in each stack.
  • card_types is a list of all 13 card types.
 stacks = 50000 
players = 1
num_decks = 1 card_types = [ 'A',2,3,4,5,6,7,8,9,10,10,10,10 ]

now begins the main loops of our simulator. There are two :

  1. A for loop that iterates through the 50,000 stacks of cards that we want to simulate.
  2. A while loop, that for each stack of cards, plays blackjack until there are 20 or fewer cards in the stack. At that point it moves onto the next stack.

The numpy array, curr_player_results, is an crucial variable star where I store the bet on solution for each musician — 1 for a winnings, 0 for a marry, and -1 for a personnel casualty. Each component in this array corresponds to one player at the black flag table. Within the while loop, we deal a card to each player and then the principal ( where the Python comment says “ Deal FIRST circuit board ” ), and then we do it again so that everyone has 2 cards. In order to deal the cards, I take advantage of the pop serve with an input signal of 0 — this returns the first chemical element of a list while simultaneously removing it from that list ( perfective for dealing cards from a stack ). When the act of cards left in the dealer ’ s batch drops to 20 or below, a new stack of cards is used to replace the old one ( moves to the next iteration of our for coil ).

 for stack in image ( stacks ) : 
blackjack = set ( [ 'A',10 ] )
dealer_cards = make_decks ( num_decks, card_types )
while len ( dealer_cards ) > 20 :

curr_player_results = np.zeros ( ( 1, players ) )

dealer_hand = [ ]
player_hands = [ [ ] for player in range ( players ) ] # Deal FIRST card
for player, hand in enumerate ( player_hands ) :
player_hands [ player ] .append ( dealer_cards.pop ( 0 ) )
dealer_hand.append ( dealer_cards.pop ( 0 ) )
# Deal SECOND card
for player, hand in count ( player_hands ) :
player_hands [ player ] .append ( dealer_cards.pop ( 0 ) )
dealer_hand.append ( dealer_cards.pop ( 0 ) )

Next the dealer checks if he or she has a black flag ( an ace and a 10 ). Notice that in the previous code block, I defined blackjack as a set that includes an ace and a 10. If the trader has a blackjack, then the players lose ( and get assigned a -1 in curr_player_results ) unless they excessively have a blackjack oak ( in which case it is a marry ) .

 # Dealer checks for 21 
if set ( dealer_hand ) == blackmail :
for actor in image ( players ) :
if set ( player_hands [ musician ] ) ! = blackjack :
curr_player_results [ 0, actor ] = -1
else :
curr_player_results [ 0, musician ] = 0

If the principal does not have a black flag, then play continues. The players do their own blackmail checks — if they have one, they win ( in some casinos blackjack pays 1.5 to 1, in other words if your bet was $ 100 then you win $ 150 ). I record a win by setting the element corresponding to that actor in the array curr_player_results to 1. For the players without black flag, they immediately have the choice to hit, stay, etc. For this simulation, my objective was to capture all kinds of player decisions — smart ones, lucky ones, and stupid ones. So I based the decision for the player on a coin flip ( if random.random ( ) generates a value higher than 0.5 the player hits, otherwise the player stays ). Deciding via coin flip might sound punch-drunk, but by making the hit/stay decision uncorrelated to what is actually happening in the game, we can observe all types of situations and ultimately generate a deep dataset for analysis. I am not trying to figure out the optimum strategy good this exemplify. Rather, I want to use this simulator to generate train data, with which I can finally train a nervous network to play blackjack oak optimally ( in a future post ). For Python, the \ character denotes wrinkle sequel and can be used to format extra long lines of code for better legibility — you will see me use it in the follow code obstruct .

 else : 
for player in range ( players ) :
# Players check for 21
if set ( player_hands [ musician ] ) == blackjack :
curr_player_results [ 0, musician ] = 1
else :
# Hit randomly, check for busts
while ( random.random ( ) > = 0.5 ) and \
( total_up ( player_hands [ actor ] ) < = 11 ) :
player_hands [ player ] .append ]
( dealer_cards.pop ( 0 ) )
if total_up ( player_hands [ player ] ) > 21 :
curr_player_results [ 0, musician ] = -1
fracture

In the final segment of our loop ( about there ! ), it ’ s the dealer ’ mho turn. The trader must hit until either he or she busts or has a hand that sums to at least 17. So the while loop deals cards to the dealer until 17 is reached, then we check if our dealer busted. If a dealer break occurs, then every musician that has not already lost ( via busting ) wins and we record a 1 for them in curr_player_results .

 # Dealer hits based on the rules 
while total_up ( dealer_hand ) < 17 :
dealer_hand.append ( dealer_cards.pop ( 0 ) )
# Compare dealer hand to players hand
# but first check if dealer busted
if total_up ( dealer_hand ) > 21 :
for musician in range ( players ) :
if curr_player_results [ 0, player ] ! = -1 :
curr_player_results [ 0, player ] = 1

If the trader does not bust, then each actor compares his or her hand to the trader ’ randomness — the higher hand wins.

 else : 
for player in range ( players ) :
if total_up ( player_hands [ player ] ) > \
total_up ( dealer_hand ) :
if total_up ( player_hands [ player ] ) < = 21 :
curr_player_results [ 0, musician ] = 1
elif total_up ( player_hands [ player ] ) == \
total_up ( dealer_hand ) :
curr_player_results [ 0, actor ] = 0
else :
curr_player_results [ 0, musician ] = -1

last, at the decision of each blackjack oak game, we append the game results along with early variables that we care about to the lists that we will use to track our overall simulation results :

 # Track features 
dealer_card_feature.append ( dealer_hand [ 0 ] )
player_card_feature.append ( player_hands )
player_results.append ( tilt ( curr_player_results [ 0 ] ) )
beginning : https://kubet.io
Category : Casino Online Games

Leave a Reply

Your email address will not be published. Required fields are marked *

KUBET - KUBET.IO
© Copyright 2020 KUBET - KU CASINO. KUBET.IO - Nhà cái hàng đầu châu Á.