180 lines
8.9 KiB
Python
Executable File
180 lines
8.9 KiB
Python
Executable File
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." |