require_relative "./card_kind.rb" module Model class Hand HAND_STATE_PLAYING = :hand_playing HAND_STATE_BUSTED = :hand_busted HAND_STATE_STAND = :hand_stand HAND_STATE_DOUBLED_DOWN = :hand_doubled_down def initialize(bet, cards, is_split_hand: false) @state = HAND_STATE_PLAYING @bet = bet @cards = cards @total = nil @is_split_hand = is_split_hand end attr_reader :bet, :cards, :is_split_hand def is_playing? @state == HAND_STATE_PLAYING end def is_busted? @state == HAND_STATE_BUSTED end def is_standing? @state == HAND_STATE_STAND end def is_blackjack? total == 21 && @cards.length == 2 end def total(is_dealer: false) return @total unless @total.nil? @total = @cards.reduce(0) {|sum, card| sum + card.value} if @total > 21 aces_count = @cards.count {|c| c == CardKind::ACE} while ((!is_dealer && @total > 21) || (is_dealer && @total < 16)) && aces_count > 0 do @total -= 10 aces_count -= 1 end end @total end ## Hand actions def can_split? not @is_split_hand and @cards.length == 2 && @cards[0].same_value?(cards[1]) end def split throw "can't split" unless can_split? [ Hand.new(@bet, @cards[0...1], is_split_hand: true), Hand.new(@bet, @cards[1..1], is_split_hand: true) ] end def hit(card) throw "can't hit" unless is_playing? @cards.push(card) @total = nil check_busted end def double_down(card) throw "can't double down" unless is_playing? @bet *= 2 hit card @state = HAND_STATE_DOUBLED_DOWN end def stand throw "can't stand" unless is_playing? @state = HAND_STATE_STAND end private def check_busted @state = HAND_STATE_BUSTED if total > 21 end end end