mirror of
https://github.com/coding-horror/basic-computer-games.git
synced 2025-12-22 23:26:40 -08:00
98 lines
1.8 KiB
Ruby
98 lines
1.8 KiB
Ruby
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
|