// // Hand.swift // Blackjack // // Represents a Blackjack hand with value calculation. // import Foundation import CasinoKit /// A hand of cards in Blackjack. struct BlackjackHand: Identifiable, Equatable { let id = UUID() var cards: [Card] var bet: Int var isDoubledDown: Bool = false var isSplit: Bool = false var isStanding: Bool = false var result: HandResult? init(cards: [Card] = [], bet: Int = 0) { self.cards = cards self.bet = bet } /// The best possible value (highest without busting, or lowest if busted). var value: Int { let (hard, soft) = calculateValues() if soft <= 21 { return soft } return hard } /// Whether this hand has a soft value (usable ace). var isSoft: Bool { let (hard, soft) = calculateValues() return soft <= 21 && soft != hard } /// Whether the hand is over 21. var isBusted: Bool { value > 21 } /// Whether this is a natural blackjack (two cards totaling 21). var isBlackjack: Bool { cards.count == 2 && value == 21 && !isSplit } /// Whether this hand can be split (two cards of same rank). var canSplit: Bool { cards.count == 2 && cards[0].rank == cards[1].rank && !isSplit } /// Whether this hand can double down. var canDoubleDown: Bool { cards.count == 2 && !isDoubledDown && !isSplit } /// Whether this hand can hit. var canHit: Bool { !isBusted && !isStanding && !isBlackjack && cards.count < 5 } /// Calculates both hard and soft values. private func calculateValues() -> (hard: Int, soft: Int) { var hardValue = 0 var aceCount = 0 for card in cards { switch card.rank { case .ace: hardValue += 1 aceCount += 1 case .two: hardValue += 2 case .three: hardValue += 3 case .four: hardValue += 4 case .five: hardValue += 5 case .six: hardValue += 6 case .seven: hardValue += 7 case .eight: hardValue += 8 case .nine: hardValue += 9 case .ten, .jack, .queen, .king: hardValue += 10 } } // Calculate soft value (one ace as 11) var softValue = hardValue if aceCount > 0 && hardValue + 10 <= 21 { softValue = hardValue + 10 } return (hardValue, softValue) } /// Display string for the hand value. var valueDisplay: String { if isBlackjack { return "BJ" } let (hard, soft) = calculateValues() if isBusted { return "\(hard) 💥" } if isSoft && soft != hard { return "\(hard)/\(soft)" } return "\(value)" } } // MARK: - Card Value Extension extension Card { /// The blackjack value of this card (Ace = 1 or 11, face cards = 10). var blackjackValue: Int { switch rank { case .ace: return 1 // Or 11, handled by hand calculation case .two: return 2 case .three: return 3 case .four: return 4 case .five: return 5 case .six: return 6 case .seven: return 7 case .eight: return 8 case .nine: return 9 case .ten, .jack, .queen, .king: return 10 } } }