import random from FuzzyControlSystem import getStartDecision, getSplitDecision, getHardHandDecision, getSoftHandDecision def shoe(n_of_decks: int = 1) -> list: """Create shuffled shoe of n decks of cards Args: n_of_decks (int, optional): number of decks. Defaults to 1. Returns: list: shoe- shuffled decks of cards """ vals = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10] suits = ['spades', 'clubs', 'hearts', 'diamonds'] deck = [] for _ in range(n_of_decks): for _ in suits: deck.extend(vals) random.shuffle(deck) return deck def cards_eval(hand: list) -> list: """Evaluate hand value. Will return two values if there is an ace in the hand and both values are below 21. Args: hand (list): list of cards Returns: list: returns a list of values of the hand """ evaluation = [sum(hand), sum(hand)] for value in hand: if value == 1: evaluation[1] += 10 if evaluation[0] == evaluation[1]: return [evaluation[0]] elif evaluation[1] > 21: return [evaluation[0]] else: return evaluation # both values returned def dealer(hand: list, shoe: iter) -> int: """Dealer hand resolution Args: hand (list): dealer hand shoe (iter): iterator of shoe Returns: int: dealer hand value """ evaluation = cards_eval(hand) while max(evaluation) <= 17: #solve soft 17 hand.append(next(shoe)) evaluation = cards_eval(hand) return max(evaluation) def AI(hand: list, face_up: str) -> str: #TODO: add fuzzy logic """Fuzzy AI possible player decision: 'hit', 'double down', 'split', 'surrender', 'stand' Args: hand (list): player hand face_up (str): dealer face up card Returns: list: player decision """ ### temp # if face_up == 'ace': # return 'surrender' # else: evaluation = cards_eval(hand) if max(evaluation) == 11: return 'double down' if max(evaluation) <= 17: return 'hit' else: return 'stand' ### temp def show_game_state(player_hand: list, dealer_hand: list, decision: str='') -> None: """Print dealer and player card values and player decision Args: player_hand (list): List of cards in player hand dealer_hand (list): List of cards in dealer hand decision (str, optional): Player decision. Will not be printed if defaults to ''. """ if decision and cards_eval(player_hand)[0] > 21: print(f"dealer: {cards_eval(dealer_hand)} player: {cards_eval(player_hand)} fail") elif decision: print(f"dealer: {cards_eval(dealer_hand)} player: {cards_eval(player_hand)} decision: {decision}") elif not cards_eval(player_hand)[0] > 21: print(f"dealer: {cards_eval(dealer_hand)} player: {cards_eval(player_hand)}") def blackjack(shoe: iter, dealer_hand: list=[], player_hand: list=[], bet: int=10) -> str: """Single blackjack round Args: shoe (iter): shoe iterator dealer_hand (list, optional): dealer hand. Should be non empty only in SPLIT. player_hand (list, optional): player hand. Should be non empty only in SPLIT. Returns: str: game result """ if dealer_hand == [] and player_hand == []: dealer_hand = [next(shoe), next(shoe)] player_hand = [next(shoe), next(shoe)] face_up = dealer_hand[0] decision = '' while decision != 'stand' or decision != 'surrender': decision = AI(player_hand, face_up) show_game_state(player_hand, dealer_hand, decision) if decision == 'hit': player_hand.append(next(shoe)) elif decision == 'double down': bet *= 2 player_hand.append(next(shoe)) elif decision == 'split': #this wont work! #it will need to # dealer_value = dealer(dealer_hand, shoe) #be calculated before and passed to blackjack() #so both wager have the same dealer_value! ##this will work reccursevly player_hand = player_hand[0] blackjack(shoe, dealer_hand, player_hand, bet)#new wager start #old wager continue elif decision == 'surrender': break elif decision == 'stand': break #dealer turn dealer_value = dealer(dealer_hand, shoe) player_value = max(cards_eval(player_hand)) show_game_state(player_hand, dealer_hand) if player_value == 21 and 1 in player_hand: return 'player blackjack', bet elif player_value > 21: return 'dealer win', bet elif dealer_value > 21: return 'player win', bet elif player_value > dealer_value: return 'player win', bet elif player_value == dealer_value: return 'push', bet #keep money, no win no lose 0$ else: return 'dealer win', bet def game_loop(balance, bet) -> None: wins, losses, draws = 0, 0, 0 player_blackjack = 0 shoe_iter = iter(shoe(10)) notable_results = ['player win', 'dealer win', 'player blackjack'] while True: #round start try: balance -= bet result, game_bet = blackjack(shoe_iter, bet=bet) except StopIteration: break if result == 'player win': wins += 1 balance += (2*game_bet) elif result == 'player blackjack': wins += 1 # player_blackjack += 1 balance += (2*game_bet) + (game_bet/2) elif result == 'dealer win': losses += 1 elif result == 'push': balance += game_bet draws += 1 if result in notable_results: print(result) print("="*50) return wins, losses, draws, balance #player_blackjack def calculate_bet(wins, losses, hand): pass # if __name__ == '__main__': # print(game_loop()) if __name__ == '__main__': statistics = [0, 0, 0] money_sum = 0 import time #don't use time.time() for counting code execution time! start = time.perf_counter() for i in range(10): wins, loses, draws, money = game_loop(0, 10) statistics[0] += wins statistics[1] += loses statistics[2] += draws money_sum += money end = time.perf_counter() result = end - start print(f'time: {round(result, 3)} seconds') print(f'wins: {statistics[0]} | losses: {statistics[1]} | draws: {statistics[2]}') print(f'win {round((statistics[0]/sum(statistics)*100), 2)}%') print(f'balance: {money_sum}') # print(f'moeny return {round((money_sum)*100, 2)}%') # total_wins, total_losses, total_draws = 0, 0, 0 # total_p_blackjack = 0 # balance = 0 # bet = 10 # import time # #don't use time.time() for counting code execution time! # start = time.perf_counter() # for i in range(100): # wins, loses, draws, balance, p_blackjack = game_loop(balance, bet) # total_wins += wins # total_losses += loses # total_draws += draws # total_p_blackjack += p_blackjack # end = time.perf_counter() # result = end - start # print(result) # print(f"Wins: {total_wins}, Losses: {total_losses}, Draws: {total_draws}") # print(f"Wins/Losses ratio: {total_wins/sum([total_wins, total_losses])}") # print(f"Balance: {balance}") # print(f"Times player hit blackjack: {total_p_blackjack}")