Class: Holdem::Hand

Inherits:
Object
  • Object
show all
Defined in:
lib/hand.rb

Constant Summary collapse

RANKINGS =
[
  :straight_flush,
  :four_of_a_kind,
  :full_house,
  :flush,
  :straight,
  :three_of_a_kind,
  :two_pair,
  :pair,
  :high_card
]

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*cards) ⇒ Hand

Returns a new instance of Hand.



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/hand.rb', line 19

def initialize(*cards)
  @cards = []
  if(cards.length == 1 && cards[0].is_a?(String))
    # a string to split up, Card class takes care of raising errors.
    cards[0].split(' ').map { |c| @cards << Card.new(c) }
  else
    # an array of cards, need to verify class.
    cards = cards[0] if cards.length == 1 && cards[0].is_a?(Array)
    cards.map { |c| c.is_a?(Card) ? @cards << c : 
      raise("Cannot initialize Hand from #{c.class} objects") }
  end

  unless (2..7).include? @cards.length
    raise "#{@cards.length} cards given (2 to 7 cards required)"
  end

  @cards.sort!

  find_best(@cards)
  @high_card = @sorted_cards[@sorted_cards.length-1]
end

Instance Attribute Details

#cardsObject (readonly)

Returns the value of attribute cards.



17
18
19
# File 'lib/hand.rb', line 17

def cards
  @cards
end

#high_cardObject (readonly)

Returns the value of attribute high_card.



17
18
19
# File 'lib/hand.rb', line 17

def high_card
  @high_card
end

#rankingObject (readonly)

Returns the value of attribute ranking.



17
18
19
# File 'lib/hand.rb', line 17

def ranking
  @ranking
end

#sorted_cardsObject (readonly)

Returns the value of attribute sorted_cards.



17
18
19
# File 'lib/hand.rb', line 17

def sorted_cards
  @sorted_cards
end

Instance Method Details

#<(compare_to) ⇒ Object



46
47
48
49
# File 'lib/hand.rb', line 46

def <(compare_to)
  return true if (self <=> compare_to) == -1
  false
end

#<=>(compare_to) ⇒ Object



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/hand.rb', line 56

def <=>(compare_to)
  # must have 5 sorted cards or be same length.
  if(@sorted_cards.length != 5 && compare_to.sorted_cards.length != 5)
    unless @sorted_cards.length == compare_to.sorted_cards.length
      raise "Cannot compare mismatched, less then 5 card hand lengths"
    end
  end

  my_rank = RANKINGS.index(@ranking)
  comp_rank = RANKINGS.index(compare_to.ranking)

  return  1 if my_rank < comp_rank
  return -1 if my_rank > comp_rank

  # otherwise must compare by cards.
  i = @sorted_cards.length-1
  while(i >= 0)
    return  1 if @sorted_cards[i].higher?(compare_to.sorted_cards[i])
    return -1 if @sorted_cards[i].lower?(compare_to.sorted_cards[i])
    i -= 1
  end

  return 0
end

#==(compare_to) ⇒ Object



51
52
53
54
# File 'lib/hand.rb', line 51

def ==(compare_to)
  return true if (self <=> compare_to) == 0
  false
end

#>(compare_to) ⇒ Object



41
42
43
44
# File 'lib/hand.rb', line 41

def >(compare_to)
  return true if (self <=> compare_to) == 1
  false
end

#oddsObject



106
107
108
109
110
111
112
113
114
115
116
# File 'lib/hand.rb', line 106

def odds
  odds = outs
  return nil if odds.nil?
  
  unknown_cards = 52 - @cards.length
  odds.each_key do |key|
    odds[key] = (odds[key].to_f / unknown_cards.to_f)
  end
  
  odds
end

#on_board?(*hole_cards) ⇒ Boolean

Returns:

  • (Boolean)


118
119
120
121
122
123
124
125
126
127
# File 'lib/hand.rb', line 118

def on_board?(*hole_cards)
  hole_cards.flatten!
  raise "Need to receive 2 hole cards, got #{hole_cards.lenth}" if hole_cards.length != 2
  unless hole_cards[0].is_a?(Card) && hole_cards[0].is_a?(Card)
    raise "Need to receive Card objects, got #{hole_cards[0].class} and #{hole_cards[0].class}"
  end
  
  return false if @sorted_cards.include?(hole_cards[0]) || @sorted_cards.include?(hole_cards[1])
  true
end

#outsObject

Information Calculators



85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/hand.rb', line 85

def outs
  return nil if @cards.length >= 7
  
  deck = Deck.new(false)
  @cards.each { |c| deck.remove(c) }
  unknown_cards = deck.cards.length
  results = Hash.new
  
  deck.cards.length.times do
    card = deck.deal
    new_hand = Hand.new(@cards + [card])
    if(RANKINGS.index(new_hand.ranking) < RANKINGS.index(self.ranking))
      # an improved hand...  find ranking difference
      results[new_hand.ranking] ||= 0
      results[new_hand.ranking] += 1
    end
  end
  
  results
end