ruby_holdem 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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