ruby-poker 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG ADDED
@@ -0,0 +1,5 @@
1
+ 2008-01-10 (0.1.0)
2
+ * Initial version
3
+ 2008-01-11 (0.1.1)
4
+ * Ranks are now a class.
5
+ * Added gem packaging
data/LICENSE ADDED
@@ -0,0 +1,27 @@
1
+ Copyright (c) 2008, Robert Olson
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without
5
+ modification, are permitted provided that the following conditions
6
+ are met:
7
+
8
+ * Redistributions of source code must retain the above copyright
9
+ notice, this list of conditions and the following disclaimer.
10
+ * Redistributions in binary form must reproduce the above copyright
11
+ notice, this list of conditions and the following disclaimer in
12
+ the documentation and/or other materials provided with the distribution.
13
+ * Neither the name of the author nor the names of its
14
+ contributors may be used to endorse or promote products derived
15
+ from this software without specific prior written permission.
16
+
17
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
+ POSSIBILITY OF SUCH DAMAGE.
data/README ADDED
@@ -0,0 +1,40 @@
1
+ = Poker hand evaluator for Ruby
2
+
3
+ == Author
4
+
5
+ Robert Olson mailto:rko618@gmail.com
6
+
7
+ == License
8
+
9
+ This is free software; you can redistribute it and/or modify it under the
10
+ terms of the BSD license. See LICENSE for more details.
11
+
12
+ == Download
13
+
14
+ The latest version of <b>ruby poker</b> can be found at
15
+
16
+ * http://rubyforge.org/frs/?group_id=5257
17
+
18
+ The homepage of this project is located at
19
+
20
+ * http://rubyforge.org/projects/rubypoker
21
+
22
+ == Description
23
+
24
+ This class handles poker logic for 5 card poker hands.
25
+
26
+ Card representations can be passed to the PokerHand constructor as a string or an array.
27
+ Face cards (cards ten, jack, queen, king, and ace) can be created using their
28
+ value (10, 11, 12, 13, 14) or letter representation (T, J, Q, K, A)
29
+
30
+ == Examples
31
+
32
+ In this section some examples show what can be done with this class.
33
+
34
+ hand1 = PokerHand.new("8H 9C TC JD QH")
35
+ hand2 = PokerHand.new(["3D", "3C", "3S", "13D", "14H"])
36
+ puts hand1 => 8H 9C 10C 11D 12H
37
+ puts hand1.rank => Straight
38
+ puts hand2 => 3D 3C 3S 13D 14H
39
+ puts hand2.rank => Three of a Kind
40
+ puts hand1 > hand2 => true
@@ -0,0 +1,25 @@
1
+ module ArrayHelper
2
+ class Array < ::Array
3
+ # Returns array of elements that only occur once
4
+ # [1, 1, 2, 3] => [2, 3]
5
+ def singles
6
+ counts = Hash.new(0)
7
+ self.each do |value|
8
+ counts[value] += 1
9
+ end
10
+
11
+ return counts.collect {|key,value| value == 1 ? key : nil }.compact.sort
12
+ end
13
+
14
+ # Returns an array containing values that we duplicated in the original array
15
+ # [1, 2, 3, 1] => [1]
16
+ def duplicates
17
+ counts = Hash.new(0)
18
+ self.each do |value|
19
+ counts[value] += 1
20
+ end
21
+
22
+ return counts.collect {|key,value| value > 1 ? key : nil }.compact.sort
23
+ end
24
+ end # class Array
25
+ end # module ArrayHelper
data/lib/card.rb ADDED
@@ -0,0 +1,22 @@
1
+ class PokerHand
2
+
3
+ class Card
4
+ include Comparable
5
+ attr_reader :suit, :value
6
+
7
+ def initialize card_str
8
+ card_str = card_str.gsub("T","10").gsub("J","11").gsub("Q","12").gsub("K","13").gsub("A","14")
9
+ @value = card_str[0, card_str.length-1].to_i
10
+ @suit = card_str[-1,1]
11
+ end
12
+
13
+ def <=> card2
14
+ @value <=> card2.value
15
+ end
16
+
17
+ def to_s
18
+ @value.to_s + @suit
19
+ end
20
+ end # class Card
21
+
22
+ end # class PokerHand
data/lib/poker_hand.rb ADDED
@@ -0,0 +1,161 @@
1
+ # poker_hand.rb
2
+
3
+ require 'array_helper.rb'
4
+ require 'rank.rb'
5
+ require 'card.rb'
6
+
7
+ class PokerHand
8
+
9
+ include ArrayHelper
10
+ include Comparable
11
+ attr_reader :cards, :values_hash
12
+
13
+ def initialize cards
14
+ @cards = Array.new
15
+ @values_hash = Hash.new(0)
16
+
17
+ begin
18
+ if cards.class == String
19
+ cards = cards.split
20
+ end
21
+
22
+ cards.each {|c| @cards << Card.new(c)}
23
+
24
+ @cards.each {|c| @values_hash[c.value] += 1}
25
+ rescue
26
+ raise "Unable to process cards input. Please check the documentation for acceptable input formats"
27
+ end
28
+ end
29
+
30
+ def rank
31
+ @rank ||= self.determine_rank
32
+ end
33
+
34
+ # Returns an array of all the values in the hand. Does not
35
+ # sort the values before returning them so Array#sort should
36
+ # be called on the return value if sorting is desired.
37
+ def values
38
+ @cards.collect {|c| c.value}
39
+ end
40
+
41
+ # Flush if the cards are all the same suit.
42
+ def flush?
43
+ @cards.collect {|c| c.suit}.uniq.size == 1
44
+ end
45
+
46
+ # Straight if all cards are consecutive values.
47
+ def straight?
48
+ straight = true # innocent until proven guilty
49
+ c_values = self.values.sort
50
+ i = c_values.first
51
+ c_values.each do |v|
52
+ straight &&= (v == i)
53
+ i += 1
54
+ end
55
+ return straight
56
+ end
57
+
58
+ # Royal Flush: Ten, Jack, Queen, King, Ace, in same suit.
59
+ def royal_flush?
60
+ self.flush? and self.values.sort == [10,11,12,13,14]
61
+ end
62
+
63
+ # Straight Flush: All cards are consecutive values of same suit.
64
+ def straight_flush?
65
+ self.flush? and self.straight?
66
+ end
67
+
68
+ # Full House: Three of a kind and a pair.
69
+ def full_house?
70
+ @values_hash.has_value?(3) and @values_hash.has_value?(2)
71
+ end
72
+
73
+ # Three of a Kind: Three cards of the same value.
74
+ def three_of_a_kind?
75
+ @values_hash.has_value?(3) and not full_house?
76
+ end
77
+
78
+ # Four of a Kind: Four cards of the same value.
79
+ def four_of_a_kind?
80
+ @values_hash.has_value?(4)
81
+ end
82
+
83
+ # Two Pair: Two different pairs.
84
+ def two_pair?
85
+ @values_hash.select {|k, v| v == 2}.size == 2 # check if two seperate values have two occurances
86
+ end
87
+
88
+ # One Pair: Two cards of the same value.
89
+ def one_pair?
90
+ @values_hash.select {|k, v| v == 2}.size == 1
91
+ end
92
+
93
+ def <=> hand2
94
+ if self.rank != hand2.rank
95
+ self.rank <=> hand2.rank
96
+ else # we have a tie... do a tie breaker
97
+ case self.rank.value # both hands have the same rank
98
+ when 0, 4, 5, 8 # highest card, straight, flush, straight flush
99
+ # check who has the highest card, if same move to the next card, etc
100
+ self.values.sort.reverse <=> hand2.values.sort.reverse
101
+ when 1 # two people with one pair
102
+ # check which pair is higher, if the pairs are the same then remove the pairs and check
103
+ # for highest card
104
+ hand1_pair = @values_hash.index(2) # get key(card value) of the duplicate pair
105
+ hand2_pair = hand2.values_hash.index(2)
106
+ if hand1_pair == hand2_pair
107
+ return self.values.singles.reverse <=> hand2.values.singles.reverse
108
+ else
109
+ return hand1_pair <=> hand2_pair
110
+ end
111
+ when 2 # two people with two pairs
112
+ # check who has the higher pair, if the pairs are the same
113
+ # then remove the pairs and check for highest card
114
+ hand1_pairs = self.values.duplicates.reverse
115
+ hand2_pairs = hand2.values.duplicates.reverse
116
+ if hand1_pairs == hand2_pairs
117
+ return self.values.singles <=> hand2.values.singles # there will be only one card remaining
118
+ else
119
+ return hand1_pairs <=> hand2_pairs
120
+ end
121
+ when 3, 6 # three_of_a_kind, full house
122
+ @values_hash.index(3) <=> hand2.values_hash.index(3)
123
+ when 7 # four of a kind
124
+ @values_hash.index(4) <=> hand2.values_hash.index(4)
125
+ when 9 # royal flush
126
+ return 0 # royal flushes always tie
127
+ end
128
+ end
129
+ end
130
+
131
+ def to_s
132
+ @cards.inject("") {|str, c| str << "#{c.to_s} "}.rstrip
133
+ end
134
+
135
+ protected
136
+
137
+ def determine_rank
138
+ if royal_flush?
139
+ r = Rank::ROYAL_FLUSH
140
+ elsif straight_flush?
141
+ r = Rank::STRAIGHT_FLUSH
142
+ elsif four_of_a_kind?
143
+ r = Rank::FOUR_OF_A_KIND
144
+ elsif full_house?
145
+ r = Rank::FULL_HOUSE
146
+ elsif flush?
147
+ r = Rank::FLUSH
148
+ elsif straight?
149
+ r = Rank::STRAIGHT
150
+ elsif three_of_a_kind?
151
+ r = Rank::THREE_OF_A_KIND
152
+ elsif two_pair?
153
+ r = Rank::TWO_PAIR
154
+ elsif one_pair?
155
+ r = Rank::PAIR
156
+ else
157
+ r = Rank::HIGH_CARD
158
+ end
159
+ return Rank.new(r)
160
+ end
161
+ end # class PokerHand
data/lib/rank.rb ADDED
@@ -0,0 +1,48 @@
1
+ class PokerHand
2
+
3
+ # Rank objects maintain the poker value of the hand. Ex. Full House
4
+ class Rank
5
+ include Comparable
6
+ attr_accessor :value
7
+
8
+ HIGH_CARD = 0
9
+ PAIR = 1
10
+ TWO_PAIR = 2
11
+ THREE_OF_A_KIND = 3
12
+ STRAIGHT = 4
13
+ FLUSH = 5
14
+ FULL_HOUSE = 6
15
+ FOUR_OF_A_KIND = 7
16
+ STRAIGHT_FLUSH = 8
17
+ ROYAL_FLUSH = 9
18
+
19
+ # Creates a new Rank instance of <code>value</code>
20
+ # Values can be 0-9. Consider using the Rank constants
21
+ # for the hand values.
22
+ def initialize value
23
+ @value = value
24
+ end
25
+
26
+ # Returns the text representation of the poker rank. Ex. "Two Pair"
27
+ def to_s
28
+ case @value
29
+ when 0: "High Card"
30
+ when 1: "Pair"
31
+ when 2: "Two Pair"
32
+ when 3: "Three of a Kind"
33
+ when 4: "Straight"
34
+ when 5: "Flush"
35
+ when 6: "Full House"
36
+ when 7: "Four of a Kind"
37
+ when 8: "Straight Flush"
38
+ when 9: "Royal Flush"
39
+ else "Unknown"
40
+ end
41
+ end
42
+
43
+ def <=> other
44
+ @value <=> other.value
45
+ end
46
+ end # class Rank
47
+
48
+ end
data/lib/ruby-poker.rb ADDED
@@ -0,0 +1 @@
1
+ require 'poker_hand'
metadata ADDED
@@ -0,0 +1,62 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ruby-poker
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Robert Olson
8
+ autorequire: ruby-poker
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-01-12 00:00:00 -08:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description:
17
+ email: rko618@gmail.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - README
24
+ - CHANGELOG
25
+ - LICENSE
26
+ files:
27
+ - lib/array_helper.rb
28
+ - lib/card.rb
29
+ - lib/poker_hand.rb
30
+ - lib/rank.rb
31
+ - lib/ruby-poker.rb
32
+ - README
33
+ - CHANGELOG
34
+ - LICENSE
35
+ has_rdoc: true
36
+ homepage: http://rubyforge.org/projects/rubypoker/
37
+ post_install_message:
38
+ rdoc_options: []
39
+
40
+ require_paths:
41
+ - lib
42
+ required_ruby_version: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: "0"
47
+ version:
48
+ required_rubygems_version: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: "0"
53
+ version:
54
+ requirements: []
55
+
56
+ rubyforge_project: rubypoker
57
+ rubygems_version: 1.0.1
58
+ signing_key:
59
+ specification_version: 2
60
+ summary: Ruby library for determining the winner in a game of poker.
61
+ test_files: []
62
+