ruby-poker 0.2.4 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,24 +1,45 @@
1
- 2008-01-10 (0.1.0)
2
- * Initial version
3
- 2008-01-12 (0.1.1)
4
- * Ranks are now a class.
5
- * Extracted card, rank, and arrays methods to individual files
6
- * Added gem packaging
7
- 2008-01-12 (0.1.2)
8
- * Fixed critical bug that was stopping the whole program to not work
9
- * Added some test cases as a result
10
- * More test cases coming soon
1
+ 2008-05-17 (0.3.0)
2
+ * Changed Card#== to compare based on card suit and face value. Before it only compared the face value of two cards. Warning: This change may potentially break your program if you were comparing Card objects directly.
3
+ * Replaced `PokerHand#arranged_hand` with `PokerHand#sort_using_rank` which is more descriptive. This loosely corresponds to bug #20194.
4
+ * Bug [#20196] 'rank' goes into an infinite loop.
5
+ * Bug [#20195] Allows the same card to be entered into the hand.
6
+ * Bug [#20344] sort_using_rank does not return expected results
7
+
8
+ 2008-04-20 (0.2.4)
9
+ * Modernized the Rakefile
10
+ * Updated to be compatible with Ruby 1.9
11
+
12
+ 2008-04-06 (0.2.2)
13
+ * Fixed bug where two hands that had the same values but different suits returned not equal
14
+
15
+ 2008-02-08 (0.2.1)
16
+ * Cards can be added to a hand after it is created by using (<<) on a PokerHand
17
+ * Cards can be deleted from a hand with PokerHand.delete()
18
+
11
19
  2008-01-21 (0.2.0)
12
20
  * Merged Patrick Hurley's poker solver
13
21
  * Added support for hands with >5 cards
14
22
  * Straights with a low Ace count now
15
23
  * to_s on a PokerHand now includes the rank after the card list
16
- * Finally wrote the Unit Tests suite
17
- 2008-02-08 (0.2.1)
18
- * Cards can be added to a hand after it is created by using (<<) on a PokerHand
19
- * Cards can be deleted from a hand with PokerHand.delete()
20
- 2008-04-06 (0.2.2)
21
- * Fixed bug where two hands that had the same values but different suits returned not equal
22
- 2008-04-20 (0.2.4)
23
- * Modernized the Rakefile
24
- * Updated to be compatible with Ruby 1.9
24
+ * Finally wrote the Unit Tests suite
25
+
26
+ 2008-01-12 (0.1.2)
27
+ * Fixed critical bug that was stopping the whole program to not work
28
+ * Added some test cases as a result
29
+ * More test cases coming soon
30
+
31
+ 2008-01-12 (0.1.1)
32
+ * Ranks are now a class.
33
+ * Extracted card, rank, and arrays methods to individual files
34
+ * Added gem packaging
35
+
36
+ 2008-01-10 (0.1.0)
37
+ * Initial version
38
+
39
+
40
+
41
+
42
+
43
+
44
+
45
+
data/README CHANGED
@@ -41,6 +41,21 @@ In this section some examples show what can be done with this class.
41
41
  puts hand2.rank => Three of a kind
42
42
  puts hand1 > hand2 => true
43
43
 
44
+ == Duplicates
45
+
46
+ By default ruby-poker will not raise an exception if you add the same card to a hand
47
+ twice. You can tell ruby-poker to not allow duplicates by doing the following
48
+
49
+ PokerHand.allow_duplicates = false
50
+
51
+ Place that line near the beginning of your program. The change is program wide so
52
+ once allow_duplicates is set to false, _all_ poker hands will raise an exception
53
+ if a duplicate card is added to the hand.
54
+
55
+ == Compatibility
56
+
57
+ Ruby-Poker is compatible with Ruby 1.8 and Ruby 1.9.
58
+
44
59
  == Background
45
60
 
46
61
  The original version of ruby-poker was written entirely by myself (Robert Olson).
data/Rakefile CHANGED
@@ -11,7 +11,7 @@ rescue LoadError
11
11
  nil
12
12
  end
13
13
 
14
- RUBYPOKER_VERSION = "0.2.4"
14
+ RUBYPOKER_VERSION = "0.3.0"
15
15
 
16
16
  task :default => [:test]
17
17
 
@@ -41,6 +41,7 @@ end
41
41
 
42
42
  Rake::GemPackageTask.new(spec) do |pkg|
43
43
  pkg.need_tar = true
44
+ pkg.need_zip = true
44
45
  end
45
46
 
46
47
  Rake::TestTask.new do |test|
@@ -54,16 +55,10 @@ task :autotest do
54
55
  ruby "-I lib -w /usr/bin/autotest"
55
56
  end
56
57
 
57
- desc "Create Zentest tests"
58
- task :zentest do
59
- `zentest card.rb test_card.rb > test_card_2.rb`
60
- `zentest ruby-poker.rb test_poker_hand.rb > test_poker_hand_2.rb`
61
- end
62
-
63
58
  Rake::RDocTask.new(:rdoc) do |rdoc|
64
59
  rdoc.rdoc_files.include('README', 'CHANGELOG', 'LICENSE', 'lib/')
65
60
  rdoc.main = 'README'
66
61
  rdoc.rdoc_dir = 'doc/html'
67
62
  rdoc.title = 'Ruby Poker Documentation'
68
- rdoc.options << '--all' << '--inline-source'
63
+ rdoc.options << '--inline-source'
69
64
  end
@@ -1,3 +1,4 @@
1
+ # This is a sample Deck implementation.
1
2
  class Deck
2
3
  def shuffle
3
4
  deck_size = @cards.size
@@ -109,4 +109,10 @@ class Card
109
109
  def <=> card2
110
110
  @face <=> card2.face
111
111
  end
112
+
113
+ # Returns true if the cards are the same card. Meaning they
114
+ # have the same suit and the same face value.
115
+ def == card2
116
+ @value == card2.value
117
+ end
112
118
  end
@@ -4,6 +4,10 @@ class PokerHand
4
4
  include Comparable
5
5
  attr_reader :hand
6
6
 
7
+ @@allow_duplicates = true # true by default
8
+ def self.allow_duplicates; @@allow_duplicates; end
9
+ def self.allow_duplicates=(v); @@allow_duplicates = v; end
10
+
7
11
  # Returns a new PokerHand object. Accepts the cards represented
8
12
  # in a string or an array
9
13
  #
@@ -47,6 +51,7 @@ class PokerHand
47
51
  def just_cards
48
52
  @hand.join(" ")
49
53
  end
54
+ alias :cards :just_cards
50
55
 
51
56
  # Returns an array of the card values in the hand.
52
57
  # The values returned are 1 less than the value on the card.
@@ -57,6 +62,12 @@ class PokerHand
57
62
  @hand.map { |c| c.face }
58
63
  end
59
64
 
65
+ # The =~ method does a regular expression match on the cards in this hand.
66
+ # This can be useful for many purposes. A common use is the check if a card
67
+ # exists in a hand.
68
+ #
69
+ # PokerHand.new("3d 4d 5d") =~ /8h/ # => nil
70
+ # PokerHand.new("3d 4d 5d") =~ /4d/ # => #<MatchData:0x615e18>
60
71
  def =~ (re)
61
72
  re.match(just_cards)
62
73
  end
@@ -134,13 +145,16 @@ class PokerHand
134
145
  transform = delta_transform
135
146
  # note we can have more than one delta 0 that we
136
147
  # need to shuffle to the back of the hand
137
- until transform.match(/^\S{3}( [1-9x]\S\S)+( 0\S\S)*$/) do
138
- transform.gsub!(/(\s0\S\S)(.*)/, "\\2\\1")
148
+ i = 0
149
+ until transform.match(/^\S{3}( [1-9x]\S\S)+( 0\S\S)*$/) or i >= hand.size do
150
+ # only do this once per card in the hand to avoid entering an
151
+ # infinite loop if all of the cards in the hand are the same
152
+ transform.gsub!(/(\s0\S\S)(.*)/, "\\2\\1") # moves the front card to the back of the string
153
+ i += 1
139
154
  end
140
155
  if (md = (/.(.). 1.. 1.. 1.. 1../.match(transform)))
141
156
  high_card = Card::face_value(md[1])
142
- arranged_hand = fix_low_ace_display(md[0] + ' ' +
143
- md.pre_match + ' ' + md.post_match)
157
+ arranged_hand = fix_low_ace_display(md[0] + ' ' + md.pre_match + ' ' + md.post_match)
144
158
  result = [[5, high_card], arranged_hand]
145
159
  end
146
160
  end
@@ -166,17 +180,24 @@ class PokerHand
166
180
  end
167
181
 
168
182
  def two_pair?
183
+ # \1 is the face value of the first pair
184
+ # \2 is the card in between the first pair and the second pair
185
+ # \3 is the face value of the second pair
169
186
  if (md = (by_face =~ /(.). \1.(.*) (.). \3./))
170
- # get kicker
171
- arranged_hand = arrange_hand(md[0] + ' ' +
187
+ # to get the kicker this does the following
188
+ # md[0] is the regex matched above which includes the first pair and
189
+ # the second pair but also some cards in the middle so we sub them out
190
+ # then we add on the cards that came before the first pair, the cards that
191
+ # we in between, and the cards that came after.
192
+ arranged_hand = arrange_hand(md[0].sub(md[2], '') + ' ' +
172
193
  md.pre_match + ' ' + md[2] + ' ' + md.post_match)
173
194
  arranged_hand.match(/(?:\S\S ){4}(\S)/)
174
195
  [
175
196
  [
176
197
  3,
177
- Card::face_value(md[1]),
178
- Card::face_value(md[3]),
179
- Card::face_value($1)
198
+ Card::face_value(md[1]), # face value of the first pair
199
+ Card::face_value(md[3]), # face value of the second pair
200
+ Card::face_value($1) # face value of the kicker
180
201
  ],
181
202
  arranged_hand
182
203
  ]
@@ -240,8 +261,14 @@ class PokerHand
240
261
  }.find([0]) { |score| score }
241
262
  end
242
263
 
243
- def arranged_hand
244
- score[1] + " (#{hand_rating})"
264
+ # Returns a string of the hand arranged based on its rank. Usually this will be the
265
+ # same as `by_face` but there are some cases where it makes a difference.
266
+ #
267
+ # ph = PokerHand.new("AS 3S 5S 2S 4S")
268
+ # ph.sort_using_rank # => "5s 4s 3s 2s As"
269
+ # ph.by_face.just_cards # => "As 5s 4s 3s 2s"
270
+ def sort_using_rank
271
+ score[1]
245
272
  end
246
273
 
247
274
  # Returns string with a listing of the cards in the hand followed by the hand's rank.
@@ -274,6 +301,10 @@ class PokerHand
274
301
  end
275
302
 
276
303
  new_cards.each do |nc|
304
+ unless @@allow_duplicates
305
+ raise "A card with the value #{nc} already exists in this hand. Set PokerHand.allow_duplicates to true if you want to be able to add a card more than once." if self =~ /#{nc}/
306
+ end
307
+
277
308
  @hand << Card.new(nc)
278
309
  end
279
310
  end
@@ -296,16 +327,18 @@ class PokerHand
296
327
  }
297
328
  end
298
329
 
299
- protected
330
+ # protected
300
331
 
332
+ # if md is a string, arrange_hand will remove extra white space
333
+ # if md is a MatchData, arrange_hand returns the matched segment
334
+ # followed by the pre_match and the post_match
301
335
  def arrange_hand(md)
302
336
  hand = if (md.respond_to?(:to_str))
303
337
  md
304
338
  else
305
339
  md[0] + ' ' + md.pre_match + md.post_match
306
340
  end
307
- hand.gsub!(/\s+/, ' ')
308
- hand.gsub(/\s+$/,'')
341
+ hand.strip.squeeze(" ") # remove extra whitespace
309
342
  end
310
343
 
311
344
  def delta_transform(use_suit = false)
@@ -1,8 +1,4 @@
1
- # Code Generated by ZenTest v. 3.8.0
2
- # classname: asrt / meth = ratio%
3
- # Card: 0 / 4 = 0.00%
4
-
5
- require 'test/unit' unless defined? $ZENTEST and $ZENTEST
1
+ require 'test/unit'
6
2
  require 'card.rb'
7
3
 
8
4
  class TestCard < Test::Unit::TestCase
@@ -45,6 +41,15 @@ class TestCard < Test::Unit::TestCase
45
41
  assert_equal(37, @c3.value)
46
42
  assert_equal(52, @c4.value)
47
43
  end
48
- end
49
-
50
- # Number of errors detected: 9
44
+
45
+ def test_comparison
46
+ assert(@c1 < @c2)
47
+ assert(@c3 > @c2)
48
+ end
49
+
50
+ def test_equals
51
+ c = Card.new("9h")
52
+ assert_not_equal(@c1, c)
53
+ assert_equal(@c1, @c1)
54
+ end
55
+ end
@@ -1,8 +1,4 @@
1
- # Code Generated by ZenTest v. 3.8.0
2
- # classname: asrt / meth = ratio%
3
- # PokerHand: 0 / 24 = 0.00%
4
-
5
- require 'test/unit' unless defined? $ZENTEST and $ZENTEST
1
+ require 'test/unit'
6
2
  require 'ruby-poker.rb'
7
3
 
8
4
  class TestPokerHand < Test::Unit::TestCase
@@ -13,8 +9,16 @@ class TestPokerHand < Test::Unit::TestCase
13
9
  @straight = PokerHand.new("8H 9D TS JH QC AS")
14
10
  end
15
11
 
16
- def test_arranged_hand
17
- assert_equal("As Ah Ac 9c 2d (Three of a kind)", @trips.arranged_hand)
12
+ # there are a lot of combinations that should be tested here. I will add more
13
+ # troublesome cases as I think of them.
14
+ def test_sort_using_rank
15
+ assert_equal("As Ah Ac 9c 2d", @trips.sort_using_rank)
16
+ assert_equal("4s 4d 4c 2h 2d", @full_boat.sort_using_rank)
17
+ assert_equal("Qd Td 7d 6d 3d 2s 5h", @flush.sort_using_rank)
18
+ assert_equal("Qc Jh Ts 9d 8h As", @straight.sort_using_rank)
19
+
20
+ assert_equal("As Ah 3d 3c Kd", PokerHand.new("AS AH KD 3D 3C").sort_using_rank)
21
+ assert_equal("As Ah 3d 3c 2d", PokerHand.new("2D AS AH 3D 3C").sort_using_rank)
18
22
  end
19
23
 
20
24
  def test_by_face
@@ -29,17 +33,17 @@ class TestPokerHand < Test::Unit::TestCase
29
33
  assert_equal([1, 8, 13, 13, 13], @trips.face_values)
30
34
  end
31
35
 
32
- def test_flush_eh
36
+ def test_flush
33
37
  assert @flush.flush?
34
38
  assert !@trips.flush?
35
39
  end
36
40
 
37
- def test_four_of_a_kind_eh
41
+ def test_four_of_a_kind
38
42
  assert !@trips.four_of_a_kind?
39
43
  assert PokerHand.new("AD 9C AS AH AC")
40
44
  end
41
45
 
42
- def test_full_house_eh
46
+ def test_full_house
43
47
  assert !@trips.full_house?
44
48
  assert @full_boat.full_house?
45
49
  end
@@ -59,7 +63,7 @@ class TestPokerHand < Test::Unit::TestCase
59
63
  assert_not_nil @trips.rank
60
64
  end
61
65
 
62
- def test_highest_card_eh
66
+ def test_highest_card
63
67
  # hard to test, make sure it does not return null
64
68
  assert PokerHand.new("2D 4S 6C 8C TH").highest_card?
65
69
  end
@@ -68,12 +72,12 @@ class TestPokerHand < Test::Unit::TestCase
68
72
  assert_equal("2d 9c As Ah Ac", @trips.just_cards)
69
73
  end
70
74
 
71
- def test_pair_eh
75
+ def test_pair
72
76
  assert !PokerHand.new("5C JC 2H 7S 3D").pair?
73
77
  assert PokerHand.new("6D 7C 5D 5H 3S").pair?
74
78
  end
75
79
 
76
- def test_royal_flush_eh
80
+ def test_royal_flush
77
81
  assert !@flush.royal_flush?
78
82
  assert PokerHand.new("AD KD QD JD TD").royal_flush?
79
83
  end
@@ -82,22 +86,22 @@ class TestPokerHand < Test::Unit::TestCase
82
86
  assert_equal([4, 13, 8, 1], @trips.score[0])
83
87
  end
84
88
 
85
- def test_straight_eh
89
+ def test_straight
86
90
  assert @straight.straight?
87
91
  assert PokerHand.new("AH 2S 3D 4H 5D").straight?
88
92
  end
89
93
 
90
- def test_straight_flush_eh
94
+ def test_straight_flush
91
95
  assert !@flush.straight_flush?
92
96
  assert !@straight.straight_flush?
93
97
  assert PokerHand.new("8H 9H TH JH QH AS").straight_flush?
94
98
  end
95
99
 
96
- def test_three_of_a_kind_eh
100
+ def test_three_of_a_kind
97
101
  assert @trips.three_of_a_kind?
98
102
  end
99
103
 
100
- def test_two_pair_eh
104
+ def test_two_pair
101
105
  assert PokerHand.new("2S 2D TH TD 4S").two_pair?
102
106
  assert !PokerHand.new("6D 7C 5D 5H 3S").two_pair?
103
107
  end
@@ -138,5 +142,24 @@ class TestPokerHand < Test::Unit::TestCase
138
142
  ph.delete("Ac")
139
143
  assert_equal(Array.new, ph.hand)
140
144
  end
145
+
146
+ def test_five_of_a_kind
147
+ # there is no five of a kind. This just tests to make sure
148
+ # that ruby-poker doesn't crash if given 5 of the same card
149
+ ph = PokerHand.new("KS KS KS KS KS")
150
+ assert_equal("Four of a kind", ph.rank)
151
+ end
152
+
153
+ def test_duplicates
154
+ ph = PokerHand.new("2d")
155
+ PokerHand.allow_duplicates = true
156
+ ph << "2d"
157
+ assert_equal("2d 2d", ph.just_cards)
158
+
159
+ PokerHand.allow_duplicates = false
160
+ assert_raise RuntimeError do
161
+ ph << "2d"
162
+ end
163
+ end
141
164
  end
142
165
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-poker
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.4
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robert Olson
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-04-20 00:00:00 -07:00
12
+ date: 2008-05-26 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies: []
15
15