ruby_holdem 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 29fbffb1efbe129bc60cc9b38ef8f048c2e18ab9
4
+ data.tar.gz: 0b99f0a5ebf3996ae2fe11b169647cf1dd74384b
5
+ SHA512:
6
+ metadata.gz: c4b072056f11a740fe63f29deceb02a692114c152b6532ccb83364757b83728f7cb4425f063f8baeee3373672a31eaf6944a748b42dc9ee35a3c155b8b4bd172
7
+ data.tar.gz: 409610a9e35b4ec60cfb4730edea0ca4d7958f53682e20b039a502d2d2e3264f89c4d8e26327f577f023324facf3112340c77b4fa922d4bc046068cb76036e8e
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --require spec_helper
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in poker_game.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,48 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ ruby_holdem (0.0.1)
5
+ ruby-poker
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ coderay (1.1.0)
11
+ diff-lcs (1.2.5)
12
+ method_source (0.8.2)
13
+ pry (0.10.1)
14
+ coderay (~> 1.1.0)
15
+ method_source (~> 0.8.1)
16
+ slop (~> 3.4)
17
+ rake (10.4.0)
18
+ rspec (3.1.0)
19
+ rspec-core (~> 3.1.0)
20
+ rspec-expectations (~> 3.1.0)
21
+ rspec-mocks (~> 3.1.0)
22
+ rspec-core (3.1.7)
23
+ rspec-support (~> 3.1.0)
24
+ rspec-expectations (3.1.2)
25
+ diff-lcs (>= 1.2.0, < 2.0)
26
+ rspec-support (~> 3.1.0)
27
+ rspec-its (1.1.0)
28
+ rspec-core (>= 3.0.0)
29
+ rspec-expectations (>= 3.0.0)
30
+ rspec-mocks (3.1.3)
31
+ rspec-support (~> 3.1.0)
32
+ rspec-support (3.1.2)
33
+ ruby-poker (1.0.1)
34
+ slop (3.6.0)
35
+
36
+ PLATFORMS
37
+ ruby
38
+
39
+ DEPENDENCIES
40
+ bundler (~> 1.7)
41
+ pry
42
+ rake (~> 10.0)
43
+ rspec
44
+ rspec-its
45
+ ruby_holdem!
46
+
47
+ BUNDLED WITH
48
+ 1.12.5
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2016, Evan Rolfe
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,40 @@
1
+ # RubyHoldem
2
+ RubyHoldem is a set of classes which track the game state of a texas holdem poker game.
3
+
4
+ ### Installation
5
+ ```
6
+ git clone git@github.com:evanrolfe/ruby-holdem.git
7
+ cd ruby-holdem/
8
+ gem install ruby_holdem
9
+ ```
10
+
11
+ ### Usage
12
+ ```ruby
13
+ require 'ruby_holdem'
14
+
15
+ players = ["Jack", "Joe", "Jil"]
16
+ poker_round = RubyHoldem::Round.new(players, 2, 4)
17
+
18
+ poker_round.make_move('bet', 2) # Jack bets small blinds
19
+ poker_round.make_move('bet', 4) # Joe bets big blinds
20
+ poker_round.make_move('fold') # Jil folds
21
+ poker_round.make_move('call') # Jack calls
22
+ poker_round.make_move('call') # Joe calls
23
+ poker_round.next_stage
24
+
25
+ puts poker_round.community_cards.join(' ')
26
+ # => i.e. 3s Js Qd
27
+
28
+ puts poker_round.pot_amount
29
+ # => 8
30
+
31
+ poker_round.make_move('bet', 3) # Jack bets 3
32
+ poker_round.make_move('fold') # Joe folds
33
+
34
+ puts poker_round.winner
35
+ # => Jack
36
+ ```
37
+
38
+ ### License
39
+
40
+ RubyHoldem uses the MIT license. Please check the [LICENSE](https://github.com/evanrolfe/ruby-holdem/blob/master/LICENSE) file for more details.
data/Rakefile.rb ADDED
@@ -0,0 +1,6 @@
1
+ require 'rspec/core/rake_task'
2
+
3
+ RSpec::Core::RakeTask.new('spec')
4
+
5
+ # If you want to make this the default task
6
+ task :default => :spec
data/example_game.rb ADDED
@@ -0,0 +1,44 @@
1
+ require 'ruby_holdem'
2
+ require 'ostruct'
3
+
4
+ line_break = "\n----------------------\n"
5
+
6
+ player1 = OpenStruct.new(name: "Player #1")
7
+ player2 = OpenStruct.new(name: "Player #2")
8
+ player3 = OpenStruct.new(name: "Player #3")
9
+ players = [player1, player2, player3]
10
+
11
+ poker_round = RubyHoldem::Round.new(players, 2, 4)
12
+
13
+ puts "Game started"
14
+
15
+ until poker_round.has_winner?
16
+ puts "#{line_break}#{poker_round.current_stage} , pot: $#{poker_round.pot_amount}"
17
+ if poker_round.community_cards.any?
18
+ puts "Community cards: #{poker_round.community_cards.join(' ')}#{line_break}"
19
+ end
20
+
21
+ until poker_round.ready_for_next_stage?
22
+ next_move_args = [
23
+ ['bet', 4],
24
+ ['call'],
25
+ ['fold']
26
+ ].sample
27
+
28
+ poker_round.make_move(*next_move_args)
29
+
30
+ if poker_round.last_move[:move] == 'bet'
31
+ puts "Player #{poker_round.last_move[:player].name} raised by #{poker_round.last_move[:amount]}"
32
+ elsif poker_round.last_move[:move] == 'call'
33
+ puts "Player #{poker_round.last_move[:player].name} called by #{poker_round.last_move[:amount]}"
34
+ else
35
+ puts "Player #{poker_round.last_move[:player].name} folded"
36
+ end
37
+
38
+ sleep 0.3
39
+ end
40
+
41
+ poker_round.next_stage
42
+ end
43
+
44
+ puts "The winner is #{poker_round.winner.name}!"
@@ -0,0 +1,28 @@
1
+ module RubyHoldem
2
+ class Dealer
3
+ attr_reader :community_cards
4
+
5
+ def initialize
6
+ @deck = Deck.new
7
+ @deck.shuffle
8
+ @community_cards = []
9
+ end
10
+
11
+ def deal_hole_cards(players)
12
+ raise ArgumentError unless players.map { |player| player.hole_cards.count == 0 }.all?
13
+ players.each do |player|
14
+ 2.times { player.hole_cards << @deck.deal }
15
+ end
16
+ end
17
+
18
+ def deal_community_cards(stage)
19
+ raise ArgumentError unless %w(pre_flop flop turn river show_down).include?(stage)
20
+
21
+ if stage == 'flop'
22
+ 3.times { community_cards << @deck.deal }
23
+ elsif %w(turn river).include?(stage)
24
+ community_cards << @deck.deal
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,51 @@
1
+ # Code taken from: https://github.com/robolson/ruby-poker/blob/master/examples/deck.rb
2
+
3
+ module RubyHoldem
4
+ class Deck
5
+ def initialize
6
+ @cards = []
7
+ Card::SUITS.each_byte do |suit|
8
+ # careful not to double include the aces...
9
+ Card::FACES[1..-1].each_byte do |face|
10
+ @cards.push(Card.new(face.chr, suit.chr))
11
+ end
12
+ end
13
+ shuffle
14
+ end
15
+
16
+ def shuffle
17
+ @cards = @cards.sort_by { rand }
18
+ return self
19
+ end
20
+
21
+ # removes a single card from the top of the deck and returns it
22
+ # synonymous to poping off a stack
23
+ def deal
24
+ @cards.pop
25
+ end
26
+
27
+ # delete an array or a single card from the deck
28
+ # converts a string to a new card, if a string is given
29
+ def burn(burn_cards)
30
+ return false if burn_cards.is_a?(Integer)
31
+ if burn_cards.is_a?(Card) || burn_cards.is_a?(String)
32
+ burn_cards = [burn_cards]
33
+ end
34
+
35
+ burn_cards.map! do |c|
36
+ c = Card.new(c) unless c.class == Card
37
+ @cards.delete(c)
38
+ end
39
+ true
40
+ end
41
+
42
+ # return count of the remaining cards
43
+ def size
44
+ @cards.size
45
+ end
46
+
47
+ def empty?
48
+ @cards.empty?
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,7 @@
1
+ module RubyHoldem
2
+ class MinBetNotMeet < StandardError
3
+ end
4
+
5
+ class NotEnoughMoney < StandardError
6
+ end
7
+ end
@@ -0,0 +1,5 @@
1
+ module RubyHoldem
2
+ class Game
3
+ # TODO: Keep track of an entire poker game consisting of multiple rounds
4
+ end
5
+ end
@@ -0,0 +1,154 @@
1
+ require 'forwardable'
2
+
3
+ module RubyHoldem
4
+ class Round
5
+ extend Forwardable
6
+
7
+ attr_reader :players,
8
+ :small_blinds,
9
+ :big_blinds,
10
+ :pot_amount,
11
+ :current_stage,
12
+ :action_history,
13
+ :dealer,
14
+ :turns_played
15
+
16
+ def_delegator :@dealer, :community_cards
17
+
18
+ STAGES = %w(pre_flop flop turn river show_down)
19
+
20
+ def initialize(players, small_blinds, big_blinds)
21
+ @small_blinds, @big_blinds = small_blinds, big_blinds
22
+ @current_stage = STAGES[0]
23
+ @pot_amount = 0
24
+ @action_history = []
25
+
26
+ @players = players.map { |player| RoundPlayer.new(player) }
27
+ @dealer = Dealer.new
28
+ @dealer.deal_hole_cards(@players)
29
+ end
30
+
31
+ # TODO: Extract the code relating to making a move into its own class to separate the logic
32
+ # behind making a move and the game state methods
33
+ def make_move(move, amount=nil)
34
+ if turns_played == 0
35
+ apply_bet(small_blinds)
36
+ elsif turns_played == 1
37
+ apply_bet(big_blinds)
38
+ elsif move == 'bet'
39
+ apply_bet(amount)
40
+ elsif move == 'call'
41
+ apply_call
42
+ elsif move == 'fold'
43
+ apply_fold
44
+ end
45
+ end
46
+
47
+ def next_stage
48
+ raise StandardError unless ready_for_next_stage? && @current_stage != 'show_down'
49
+
50
+ @current_stage = STAGES[STAGES.index(@current_stage)+1]
51
+ @dealer.deal_community_cards(@current_stage)
52
+ end
53
+
54
+ def ready_for_next_stage?
55
+ return false unless every_player_has_called? && turns_played_in_stage > 0
56
+
57
+ players_still_in_round.map { |player| (player.current_bet_amount == highest_bet_placed) }.all?
58
+ end
59
+
60
+ def has_winner?
61
+ (current_stage == 'show_down' || players_still_in_round.count == 1)
62
+ end
63
+
64
+ def winner
65
+ return players_still_in_round[0] if players_still_in_round.count == 1
66
+ return players_still_in_round[2]
67
+ end
68
+
69
+ # TODO: Refactor this method to make it more readable
70
+ def player_in_turn #The player whose turn it is to make a move
71
+ return players[0] if action_history.length == 0
72
+
73
+ last_player_index = players.index(action_history.last[:player])
74
+ player_found = false
75
+ increment=1
76
+
77
+ until player_found
78
+ next_player = players[(last_player_index + increment) % players.length] #Wrap around the array once end reached
79
+ player_found = true if players_still_in_round.include?(next_player)
80
+ increment += 1
81
+ end
82
+
83
+ next_player
84
+ end
85
+
86
+ def players_still_in_round
87
+ players.select do |round_player|
88
+ folds = action_history.select { |action| action[:move] == 'fold' && action[:player] == round_player }
89
+ (folds.length == 0)
90
+ end
91
+ end
92
+
93
+ def highest_bet_placed
94
+ players_still_in_round.max_by(&:current_bet_amount).current_bet_amount
95
+ end
96
+
97
+ def last_move
98
+ action_history.last
99
+ end
100
+
101
+ private
102
+
103
+ def turns_played
104
+ action_history.length
105
+ end
106
+
107
+ def turns_played_in_stage
108
+ action_history.select { |action| action[:stage] == @current_stage }.length
109
+ end
110
+
111
+ def every_player_has_called?
112
+ players_num_calls = players_still_in_round.map do |round_player|
113
+ calls = action_history.select { |action| action[:stage] == @current_stage && action[:move] == 'call' && action[:player] == round_player }
114
+ calls.length
115
+ end
116
+
117
+ players_num_calls.map { |num_calls| num_calls >= 1 }.all?
118
+ end
119
+
120
+ def apply_bet(amount)
121
+ raise MinBetNotMeet if amount < min_bet_amount_for_player(player_in_turn)
122
+
123
+ #TODO: Go all in instead of raising an error
124
+ raise NotEnoughMoney unless player_can_afford_bet?(player_in_turn, amount)
125
+
126
+ @pot_amount += amount
127
+ player_in_turn.current_bet_amount += amount
128
+ action_history << { player: player_in_turn, stage: current_stage, move: 'bet', amount: amount}
129
+ end
130
+
131
+ def apply_call
132
+ amount = min_bet_amount_for_player(player_in_turn)
133
+ raise NotEnoughMoney unless player_can_afford_bet?(player_in_turn, amount)
134
+
135
+ @pot_amount += amount
136
+ player_in_turn.current_bet_amount += amount
137
+
138
+ action_history << { player: player_in_turn, stage: current_stage, move: 'call', amount: amount}
139
+ end
140
+
141
+ def apply_fold
142
+ action_history << { player: player_in_turn, stage: current_stage, move: 'fold', amount: 0}
143
+ end
144
+
145
+ def min_bet_amount_for_player(player)
146
+ highest_bet_placed - player.current_bet_amount
147
+ end
148
+
149
+ # TODO:
150
+ def player_can_afford_bet?(player, bet_amount)
151
+ true
152
+ end
153
+ end
154
+ end
@@ -0,0 +1,11 @@
1
+ module RubyHoldem
2
+ class RoundPlayer < SimpleDelegator
3
+ attr_accessor :hole_cards, :current_bet_amount
4
+
5
+ def initialize(player)
6
+ @hole_cards = []
7
+ @current_bet_amount = 0
8
+ super(player)
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,3 @@
1
+ module RubyHoldem
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,7 @@
1
+ require 'ruby-poker'
2
+ require 'ruby_holdem/deck'
3
+ require 'ruby_holdem/errors'
4
+
5
+ require 'ruby_holdem/dealer'
6
+ require 'ruby_holdem/round'
7
+ require 'ruby_holdem/round_player'
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ require 'ruby_holdem/version'
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = 'ruby_holdem'
9
+ spec.version = RubyHoldem::VERSION
10
+ spec.authors = ['Evan Rolfe']
11
+ spec.email = ['evanrolfe@gmail.com']
12
+ spec.summary = 'A gem for playing texas-holdem poker'
13
+ spec.homepage = 'https://github.com/evanrolfe/ruby-holdem'
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = []
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ['lib']
20
+
21
+ spec.add_runtime_dependency 'ruby-poker'
22
+
23
+ spec.add_development_dependency 'bundler', '~> 1.7'
24
+ spec.add_development_dependency 'rake', '~> 10.0'
25
+ spec.add_development_dependency 'rspec'
26
+ spec.add_development_dependency 'pry'
27
+ spec.add_development_dependency 'rspec-its'
28
+ end
@@ -0,0 +1,5 @@
1
+ require 'spec_helper'
2
+
3
+ describe RubyHoldem::Dealer do
4
+ pending
5
+ end
@@ -0,0 +1,249 @@
1
+ require 'spec_helper'
2
+ require 'ostruct'
3
+
4
+ describe RubyHoldem::Round do
5
+ let(:player1) { OpenStruct.new(name: "Player #1") }
6
+ let(:player2) { OpenStruct.new(name: "Player #2") }
7
+ let(:player3) { OpenStruct.new(name: "Player #3") }
8
+ let(:players) { [player1, player2, player3] }
9
+
10
+ let(:round) { RubyHoldem::Round.new(players, 1, 2) }
11
+
12
+ describe '#initialize' do
13
+ subject { round }
14
+
15
+ # TODO: Convert all instances of "should" to "is_expected"
16
+ its(:small_blinds) { should eq(1) }
17
+ its(:big_blinds) { should eq(2) }
18
+ its(:current_stage) { should eq('pre_flop') }
19
+ its(:action_history) { should eq([]) }
20
+ end
21
+
22
+ describe '#next_stage' do
23
+ before do
24
+ allow(round).to receive(:action_history).and_return(action_history)
25
+ end
26
+
27
+ context 'on the pre_flop' do
28
+ # TODO: Convert the stubbing of the action_history to a sequence of make_move calls in a
29
+ # before block
30
+ let(:action_history) do
31
+ [
32
+ { stage: 'pre_flop', player: round.players[0], amount: 1, move: 'bet' },
33
+ { stage: 'pre_flop', player: round.players[1], amount: 0, move: 'fold' },
34
+ { stage: 'pre_flop', player: round.players[2], amount: 1, move: 'call' },
35
+ { stage: 'pre_flop', player: round.players[0], amount: 0, move: 'call' }
36
+ ]
37
+ end
38
+
39
+ before do
40
+ round.next_stage
41
+ end
42
+
43
+ it { expect(round.current_stage).to eq('flop') }
44
+ end
45
+ end
46
+
47
+ describe '#ready_for_next_stage?' do
48
+ before do
49
+ allow(round).to receive(:action_history).and_return(action_history)
50
+ end
51
+
52
+ subject { round.ready_for_next_stage? }
53
+
54
+ context 'on game start' do
55
+ let(:action_history) { [] }
56
+
57
+ it { should eq(false) }
58
+ end
59
+
60
+ context 'on the pre_flop' do
61
+
62
+ context 'situation 1' do
63
+ let(:action_history) do
64
+ [
65
+ { stage: 'pre_flop', player: round.players[0], amount: 1, move: 'bet' },
66
+ { stage: 'pre_flop', player: round.players[1], amount: 0, move: 'fold' }
67
+ ]
68
+ end
69
+ it { should eq(false) }
70
+ end
71
+
72
+ context 'situation 2' do
73
+ let(:action_history) do
74
+ [
75
+ { stage: 'pre_flop', player: round.players[0], amount: 1, move: 'bet' },
76
+ { stage: 'pre_flop', player: round.players[1], amount: 0, move: 'fold' },
77
+ { stage: 'pre_flop', player: round.players[2], amount: 1, move: 'call' },
78
+ { stage: 'pre_flop', player: round.players[0], amount: 0, move: 'call' }
79
+ ]
80
+ end
81
+
82
+ it { should eq(true) }
83
+ end
84
+
85
+ end
86
+
87
+ context 'on the flop' do
88
+
89
+ context 'situation 1' do
90
+ let(:action_history) do
91
+ [
92
+ { stage: 'pre_flop', player: round.players[0], amount: 1, move: 'bet' },
93
+ { stage: 'pre_flop', player: round.players[1], amount: 0, move: 'fold' },
94
+ { stage: 'pre_flop', player: round.players[2], amount: 1, move: 'call' },
95
+ { stage: 'flop', player: round.players[0], amount: 1, move: 'bet' }
96
+ ]
97
+ end
98
+
99
+ before do
100
+ allow(round).to receive(:current_stage).and_return('flop')
101
+ end
102
+
103
+ it { should eq(false) }
104
+ end
105
+
106
+ context 'situation 2' do
107
+ let(:action_history) do
108
+ [
109
+ { stage: 'pre_flop', player: round.players[0], amount: 1, move: 'bet' },
110
+ { stage: 'pre_flop', player: round.players[1], amount: 0, move: 'fold' },
111
+ { stage: 'pre_flop', player: round.players[2], amount: 1, move: 'call' },
112
+ { stage: 'pre_flop', player: round.players[0], amount: 0, move: 'call' },
113
+ { stage: 'flop', player: round.players[0], amount: 3, move: 'bet' },
114
+ { stage: 'flop', player: round.players[2], amount: 3, move: 'call' },
115
+ { stage: 'flop', player: round.players[0], amount: 0, move: 'call' }
116
+ ]
117
+ end
118
+
119
+ before do
120
+ allow(round).to receive(:current_stage).and_return('flop')
121
+ end
122
+
123
+ it { should eq(true) }
124
+ end
125
+
126
+ end
127
+ end
128
+
129
+ describe '#player_in_turn' do
130
+ let(:action_history) do
131
+ [
132
+ { stage: 'pre_flop', player: round.players[0], amount: 1, move: 'bet' },
133
+ { stage: 'pre_flop', player: round.players[1], amount: 0, move: 'fold' }
134
+ ]
135
+ end
136
+
137
+ before do
138
+ allow(round).to receive(:action_history).and_return(action_history)
139
+ end
140
+
141
+ subject { round.send(:player_in_turn) }
142
+
143
+ it { should == round.players[2] }
144
+ end
145
+
146
+ describe '#players_still_in_round' do
147
+ let(:action_history) do
148
+ [
149
+ { stage: 'pre_flop', player: round.players[0], amount: 1, move: 'bet' },
150
+ { stage: 'pre_flop', player: round.players[1], amount: 0, move: 'fold' }
151
+ ]
152
+ end
153
+
154
+ before do
155
+ allow(round).to receive(:action_history).and_return(action_history)
156
+ end
157
+
158
+ subject { round.send(:players_still_in_round) }
159
+
160
+ its([0]) { should eq(round.players[0]) }
161
+ its([1]) { should eq(round.players[2]) }
162
+ end
163
+
164
+ describe '#highest_bet_placed' do
165
+ before do
166
+ round.make_move('call')
167
+ round.make_move('call')
168
+ round.make_move('bet', 4)
169
+ end
170
+
171
+ subject { round.send(:highest_bet_placed) }
172
+
173
+ it { should eq(4) }
174
+ end
175
+
176
+ describe '#has_winner?' do
177
+ subject { round.has_winner? }
178
+
179
+ context 'round won after folds' do
180
+ let(:action_history) do
181
+ [
182
+ { stage: 'pre_flop', player: round.players[0], amount: 1, move: 'bet' },
183
+ { stage: 'pre_flop', player: round.players[1], amount: 4, move: 'bet' },
184
+ { stage: 'pre_flop', player: round.players[2], amount: 0, move: 'fold'},
185
+ { stage: 'pre_flop', player: round.players[0], amount: 3, move: 'call' },
186
+ { stage: 'flop', player: round.players[1], amount: 0, move: 'call' },
187
+ { stage: 'flop', player: round.players[0], amount: 0, move: 'fold' }
188
+ ]
189
+ end
190
+
191
+ before do
192
+ allow(round).to receive(:action_history).and_return(action_history)
193
+ end
194
+
195
+ it { should eq(true) }
196
+ end
197
+
198
+ context 'showdown between remaining players' do
199
+ before do
200
+ allow(round).to receive(:current_stage).and_return('show_down')
201
+ end
202
+
203
+ it { should eq(true) }
204
+ end
205
+ end
206
+
207
+ describe '#winner' do
208
+
209
+ end
210
+
211
+ describe '#apply_bet' do
212
+ context 'at the start of the round' do
213
+ before do
214
+ round.send(:apply_bet, 1)
215
+ end
216
+
217
+ subject { round }
218
+
219
+ its(:action_history) { should eq([{ player: round.players[0], stage: 'pre_flop', move: 'bet', amount: 1 }]) }
220
+ its(:pot_amount) { should eq(1) }
221
+ end
222
+ end
223
+
224
+ describe '#apply_call' do
225
+ context 'at the start of the round' do
226
+ before do
227
+ round.send(:apply_call)
228
+ end
229
+
230
+ subject { round }
231
+
232
+ its(:action_history) { should eq([{ player: round.players[0], stage: 'pre_flop', move: 'call', amount: 0 }]) }
233
+ its(:pot_amount) { should eq(0) }
234
+ end
235
+ end
236
+
237
+ describe '#apply_fold' do
238
+ context 'at the start of the round' do
239
+ before do
240
+ round.send(:apply_fold)
241
+ end
242
+
243
+ subject { round }
244
+
245
+ its(:action_history) { should eq([{ player: round.players[0], stage: 'pre_flop', move: 'fold', amount: 0 }]) }
246
+ its(:pot_amount) { should eq(0) }
247
+ end
248
+ end
249
+ end
@@ -0,0 +1,10 @@
1
+ require 'rspec'
2
+ require 'rspec/its'
3
+ require 'pry'
4
+ require 'ruby_holdem'
5
+
6
+ RSpec.configure do |config|
7
+ config.color = true
8
+ config.filter_run focus: true
9
+ config.run_all_when_everything_filtered = true
10
+ end
metadata ADDED
@@ -0,0 +1,150 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ruby_holdem
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Evan Rolfe
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-08-28 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: ruby-poker
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.7'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.7'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '10.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '10.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: pry
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec-its
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ description:
98
+ email:
99
+ - evanrolfe@gmail.com
100
+ executables: []
101
+ extensions: []
102
+ extra_rdoc_files: []
103
+ files:
104
+ - ".rspec"
105
+ - Gemfile
106
+ - Gemfile.lock
107
+ - LICENSE
108
+ - README.md
109
+ - Rakefile.rb
110
+ - example_game.rb
111
+ - lib/ruby_holdem.rb
112
+ - lib/ruby_holdem/dealer.rb
113
+ - lib/ruby_holdem/deck.rb
114
+ - lib/ruby_holdem/errors.rb
115
+ - lib/ruby_holdem/game.rb
116
+ - lib/ruby_holdem/round.rb
117
+ - lib/ruby_holdem/round_player.rb
118
+ - lib/ruby_holdem/version.rb
119
+ - ruby_holdem.gemspec
120
+ - spec/dealer_spec.rb
121
+ - spec/round_spec.rb
122
+ - spec/spec_helper.rb
123
+ homepage: https://github.com/evanrolfe/ruby-holdem
124
+ licenses:
125
+ - MIT
126
+ metadata: {}
127
+ post_install_message:
128
+ rdoc_options: []
129
+ require_paths:
130
+ - lib
131
+ required_ruby_version: !ruby/object:Gem::Requirement
132
+ requirements:
133
+ - - ">="
134
+ - !ruby/object:Gem::Version
135
+ version: '0'
136
+ required_rubygems_version: !ruby/object:Gem::Requirement
137
+ requirements:
138
+ - - ">="
139
+ - !ruby/object:Gem::Version
140
+ version: '0'
141
+ requirements: []
142
+ rubyforge_project:
143
+ rubygems_version: 2.5.1
144
+ signing_key:
145
+ specification_version: 4
146
+ summary: A gem for playing texas-holdem poker
147
+ test_files:
148
+ - spec/dealer_spec.rb
149
+ - spec/round_spec.rb
150
+ - spec/spec_helper.rb