from constants import SUITS, RANKS import random def deal_card(): """Simulates drawing a card. Returns a card name (e.g., 'card_clubs_02', 'card_clubs_K').""" return f"card_{random.choice(SUITS)}_{random.choice(RANKS)}" def calculate_hand_total(hand): """Calculates the total value of a hand, adjusting for Aces if necessary.""" numerical_values = [] for card in hand: # Extract the rank from the card name (e.g., 'card_clubs_02' -> '02') rank = card.split('_')[-1] # Convert rank to numerical value if rank in ['J', 'Q', 'K']: numerical_values.append(10) elif rank == 'A': numerical_values.append(11) else: numerical_values.append(int(rank)) total = sum(numerical_values) aces = numerical_values.count(11) # Adjust for Aces if the total exceeds 21 while total > 21 and aces: total -= 10 # Change an Ace from 11 to 1 aces -= 1 return total def has_blackjack(hand): """Check if the hand is a Blackjack (Ace + 10-value card).""" return len(hand) == 2 and calculate_hand_total(hand) == 21 def can_split(player_hand): """Checks if the player can split their hand.""" if len(player_hand) != 2: return False # Get ranks of both cards rank1 = player_hand[0].split('_')[-1] rank2 = player_hand[1].split('_')[-1] # Consider all 10-value cards as splittable with each other ten_value_cards = ['10', 'J', 'Q', 'K'] # Case 1: Exact same rank if rank1 == rank2: return True # Case 2: Both are 10-value cards elif rank1 in ten_value_cards and rank2 in ten_value_cards: return True return False def get_split_decision(player_hand, dealer_card): """Returns the correct decision for splitting based on the player's pair and the dealer's card.""" pair_card = player_hand[0].split('_')[-1] # Define splitting rules if pair_card == "05": # 5s return "Double", "Never split 5s; double down instead." elif pair_card == "08": # 8s return "Split", "Always split 8s." elif pair_card in ['10', 'J', 'Q', 'K']: # 10s return "Stand", "Never split 10s; stand instead." elif pair_card == "A": # Aces return "Split", "Always split Aces." elif pair_card in ["02", "03", "04", "06", "07", "09"]: # Other pairs if pair_card == "02" or pair_card == "03": if dealer_card in ["02", "03", "04", "05", "06", "07"]: return "Split", f"Split {pair_card}s vs dealer's 2–7. Note: This assumes doubling after splitting (DAS) is allowed. If DAS is not allowed, do not split {pair_card}s vs dealer's 2–3." else: return "Hit", f"Do not split {pair_card}s vs dealer's 8–Ace; hit instead." elif pair_card == "04": # 4s if dealer_card in ["05", "06"]: return "Split", f"Split {pair_card}s vs dealer's 5–6. Note: This assumes doubling after splitting (DAS) is allowed. If DAS is not allowed, do not split {pair_card}s." else: return "Hit", f"Do not split {pair_card}s vs dealer's 2–4 or 7–Ace; hit instead." elif pair_card == "06": # 6s if dealer_card in ["02", "03", "04", "05", "06"]: return "Split", f"Split {pair_card}s vs dealer's 2–6. Note: This assumes doubling after splitting (DAS) is allowed. If DAS is not allowed, do not split {pair_card}s vs dealer's 2." else: return "Hit", f"Do not split {pair_card}s vs dealer's 7–Ace; hit instead." elif pair_card == "07": if dealer_card in ["02", "03", "04", "05", "06", "07"]: return "Split", f"Split {pair_card}s vs dealer's 2–7." else: return "Hit", f"Do not split {pair_card}s vs dealer's 8–Ace; hit instead." elif pair_card == "09": if dealer_card in ["02", "03", "04", "05", "06", "08", "09"]: return "Split", f"Split {pair_card}s vs dealer's 2–6, 8, or 9." else: return "Stand", f"Do not split {pair_card}s vs dealer's 7, 10, or Ace; stand instead." return "No rule defined", "No rule defined for this pair." def get_correct_decision(player_hand, player_total, dealer_card): """Returns the correct decision based on the player's hand and the dealer's card.""" # Check if the hand is a soft total (contains an Ace counted as 11) is_soft = 'A' in [card.split('_')[-1] for card in player_hand] and player_total <= 21 # Soft totals (Ace + 2 to Ace + 9) if is_soft: if player_total == 13: # Ace + 2 if dealer_card.split('_')[-1] in ['05', '06']: return "Double", "Double when you have A,2 vs dealer's 5–6." else: return "Hit", "Hit when you have A,2 vs dealer's 2–4 or 7–Ace." elif player_total == 14: # Ace + 3 if dealer_card.split('_')[-1] in ['05', '06']: return "Double", "Double when you have A,3 vs dealer's 5–6." else: return "Hit", "Hit when you have A,3 vs dealer's 2–4 or 7–Ace." elif player_total == 15: # Ace + 4 if dealer_card.split('_')[-1] in ['04', '05', '06']: return "Double", "Double when you have A,4 vs dealer's 4–6." else: return "Hit", "Hit when you have A,4 vs dealer's 2–3 or 7–Ace." elif player_total == 16: # Ace + 5 if dealer_card.split('_')[-1] in ['04', '05', '06']: return "Double", "Double when you have A,5 vs dealer's 4–6." else: return "Hit", "Hit when you have A,5 vs dealer's 2–3 or 7–Ace." elif player_total == 17: # Ace + 6 if dealer_card.split('_')[-1] in ['03', '04', '05', '06']: return "Double", "Double when you have A,6 vs dealer's 3–6." else: return "Hit", "Hit when you have A,6 vs dealer's 2 or 7–Ace." elif player_total == 18: # Ace + 7 if dealer_card.split('_')[-1] in ['03', '04', '05', '06']: # Double vs. 3–6 return "Double", "Double when you have A,7 vs dealer's 3–6. Note: Some casinos may restrict doubling on certain hands, so check the rules." elif dealer_card.split('_')[-1] in ['02', '07', '08']: # Stand vs. 2, 7, 8 if dealer_card.split('_')[-1] == '02': return "Stand", "Stand on A,7 vs dealer's 2. However, some players choose to Double in this situation as a risky option. Note: Some casinos may restrict doubling on certain hands, so check the rules." else: return "Stand", "Stand on A,7 vs dealer's 7 or 8." else: # Hit vs. 9, 10, Ace return "Hit", "Hit on A,7 vs dealer's 9, 10, or Ace, as the dealer has a strong chance of making a good hand." elif player_total == 19: # Ace + 8 if dealer_card.split('_')[-1] == '06': return "Stand", "Stand on A,8 vs dealer's 6. However, some players choose to Double in this situation as a risky option. Note: This depends on casino rules." else: return "Stand", "Stand on A,8 vs dealer's 2–5 or 7–Ace." elif player_total == 20: # Ace + 9 return "Stand", "Stand on A,9 (soft 20)." elif player_total == 21: # Ace + 10 return "Stand", "Stand on A,10 (Blackjack)." # Hard totals (no Ace or Ace counted as 1) if player_total < 9: return "Hit", "Always Hit when your total is less than 9." if player_total == 9: if dealer_card.split('_')[-1] in ['03', '04', '05', '06']: return "Double", "Double on 9 vs dealer's 3–6." else: return "Hit", "Hit on 9 vs dealer's 2, 7–Ace." elif player_total == 10: if dealer_card.split('_')[-1] in ['02', '03', '04', '05', '06', '07', '08', '09']: return "Double", "Double on 10 vs dealer's 2–9." else: return "Hit", "Hit on 10 vs dealer's 10 or Ace." elif player_total == 11: return "Double", "Always Double on 11." elif player_total == 12: if dealer_card.split('_')[-1] in ['04', '05', '06']: return "Stand", "Stand on 12 vs dealer's 4–6." else: return "Hit", "Hit on 12 vs dealer's 2–3 or 7–Ace." elif 13 <= player_total <= 16: if dealer_card.split('_')[-1] in ['02', '03', '04', '05', '06']: return "Stand", "Stand on 13–16 vs dealer's 2–6." else: return "Hit", "Hit on 13–16 vs dealer's 7–Ace." elif player_total >= 17: return "Stand", "Always Stand on 17 or higher." return "No rule defined", "No rule defined for this scenario."