acpc_poker_types 6.1.2 → 6.2.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1bceefd96ab22bcbccd8ed8f9ddee93eb1808462
4
- data.tar.gz: c0811aafbf5f500fffa97e431c51a30240e04a80
3
+ metadata.gz: fbed7f982f75101fa5ea0655986ed7e2d39ea77e
4
+ data.tar.gz: bdc7f86c7351298a819751e1cb9cda56ad9746ff
5
5
  SHA512:
6
- metadata.gz: 4009749b1e934b1c4d8d9248e1fe0f495bb8a52378c1c9d8f04e213cab0c244f0d8b37298e9e612ae24ad7180ff1ae3013406573ef16f25f8111d1ca271091a5
7
- data.tar.gz: bb713825016560c9cbd079b2f2290154d741250e4e02bdb47747a48fa53b1532fb8c5050321f28aefdb6e3692ebd740a94f605e04abe005756dbeabd036fc1b2
6
+ metadata.gz: b8feecf734cd9636bed880b3a8be93bbbb6c8e21c4b77212c127d80f130098287691b326343b7b3ce2e6d3afc5cf0fef6edd4f414e4a9c103e5a4b39caf11600
7
+ data.tar.gz: aad719143fe546905d0ff49207f2ae4f284c7c83f3a38a50c49a8caf1f71ab54ca4033f4231553f079106a8d3dd73584332c2fcb7ce205af5c5566f804325d5d
@@ -87,17 +87,13 @@ class HandPlayer
87
87
  l_actions
88
88
  end
89
89
 
90
- # @param round [Integer] The round in which the largest wager by size is desired.
91
- # defaults to +nil+.
92
- # @return [ChipStack] The largest wager by size this player has made.
93
- # Checks only in the specified +round+ or over the entire hand if round is +nil+.
94
- # def largest_wager_by(round=nil)
95
- # @todo
96
- # end
97
-
98
90
  def append_action!(action, round_num = round)
99
91
  raise Inactive if inactive?
100
92
 
93
+ while @actions.length <= round_num
94
+ @actions << []
95
+ end
96
+
101
97
  @actions[round_num] ||= []
102
98
  @actions[round_num] << action
103
99
 
@@ -51,12 +51,8 @@ class MatchState
51
51
  # @return [String] The ACPC string created by the given betting sequence.
52
52
  attr_reader :betting_sequence_string
53
53
 
54
- # @todo Move this @return [Array<Hand>] The list of visible hole card sets for each player.
55
-
56
54
  attr_reader :hands_string
57
55
 
58
- # @todo Move this @return [BoardCards] All visible community cards on the board.
59
-
60
56
  attr_reader :community_cards_string
61
57
 
62
58
  # @return [String] Label for match state strings.
@@ -107,6 +103,7 @@ class MatchState
107
103
  @hands_string = $4
108
104
  @community_cards_string = $5
109
105
  end
106
+ @min_wager_by = nil
110
107
  end
111
108
 
112
109
  # @return [String] The MatchState in raw text form.
@@ -129,6 +126,7 @@ class MatchState
129
126
  another_match_state.to_s == to_s
130
127
  end
131
128
 
129
+ # @return [Array<Hand>] The list of hole card hands for each player.
132
130
  def all_hands
133
131
  @all_hands ||= -> do
134
132
  lcl_hole_card_hands = all_string_hands(@hands_string).map do |string_hand|
@@ -160,6 +158,7 @@ class MatchState
160
158
  end
161
159
  end
162
160
 
161
+ # @return [BoardCards] All visible community cards on the board.
163
162
  def community_cards
164
163
  @community_cards ||= -> do
165
164
  lcl_community_cards = BoardCards.new(
@@ -264,20 +263,23 @@ class MatchState
264
263
  @players = players_at_hand_start game_def.chip_stacks, game_def.blinds
265
264
 
266
265
  last_round = -1
267
- acting_player_position = nil
266
+ @next_to_act = nil
268
267
  @player_acting_sequence = []
268
+ @min_wager_by = game_def.min_wagers.first
269
269
  every_action_token do |action, round|
270
270
  if round != last_round
271
- acting_player_position = game_def.first_player_positions[round]
271
+ @min_wager_by = game_def.min_wagers[round]
272
+ @next_to_act = @players.position_of_first_active_player(
273
+ game_def.first_player_positions[round]
274
+ )
272
275
  @player_acting_sequence << []
273
276
  last_round = round
274
277
  end
275
278
 
276
- acting_player_position = @players.position_of_first_active_player(
277
- acting_player_position
278
- )
279
+ @player_acting_sequence.last << @next_to_act
280
+ acting_player_position = @player_acting_sequence.last.last
279
281
 
280
- @player_acting_sequence.last << acting_player_position
282
+ @next_to_act = @players.next_to_act(@next_to_act)
281
283
 
282
284
  cost = @players.action_cost(
283
285
  acting_player_position,
@@ -285,20 +287,13 @@ class MatchState
285
287
  game_def.min_wagers[round]
286
288
  )
287
289
 
288
- @players[acting_player_position].append_action!(
289
- if cost > 0
290
- action = PokerAction.new(action.to_s, cost: cost)
291
- else
292
- action
293
- end,
294
- round
295
- )
290
+ action = PokerAction.new(action.to_s, cost: cost) if cost > 0
296
291
 
297
- yield action, round, acting_player_position, @players if block_given?
292
+ adjust_min_wager!(action, acting_player_position)
298
293
 
299
- acting_player_position = @players.next_player_position(
300
- acting_player_position
301
- )
294
+ @players[acting_player_position].append_action!(action, round)
295
+
296
+ yield action, round, acting_player_position, @players if block_given?
302
297
  end
303
298
 
304
299
  distribute_chips!(game_def) if hand_ended?(game_def)
@@ -306,6 +301,12 @@ class MatchState
306
301
  @players
307
302
  end
308
303
 
304
+ def next_to_act(game_def)
305
+ every_action(game_def) unless @next_to_act
306
+
307
+ @next_to_act
308
+ end
309
+
309
310
  def players(game_def)
310
311
  @players ||= every_action(game_def)
311
312
  end
@@ -337,6 +338,13 @@ class MatchState
337
338
  @pot ||= players(game_def).map { |player| player.contributions }.flatten.inject(:+)
338
339
  end
339
340
 
341
+ # @return [ChipStack] Minimum wager by.
342
+ def min_wager_by(game_def)
343
+ every_action(game_def) unless @min_wager_by
344
+
345
+ @min_wager_by
346
+ end
347
+
340
348
  private
341
349
 
342
350
  # Distribute chips to all winning players
@@ -388,5 +396,19 @@ class MatchState
388
396
  def actions_from_acpc_characters(action_sequence)
389
397
  action_sequence.scan(/[^#{BETTING_SEQUENCE_SEPARATOR}\d]\d*/)
390
398
  end
399
+
400
+ def adjust_min_wager!(action, acting_player_position)
401
+ return self unless PokerAction::MODIFIABLE_ACTIONS.include?(action.action)
402
+
403
+ wager_size = ChipStack.new(
404
+ action.cost.to_f - @players.amount_to_call(acting_player_position)
405
+ )
406
+
407
+ return self unless wager_size > @min_wager_by
408
+
409
+ @min_wager_by = wager_size
410
+
411
+ self
412
+ end
391
413
  end
392
414
  end
@@ -58,5 +58,11 @@ class PlayerGroup < DelegateClass(Array)
58
58
  ].min
59
59
  )
60
60
  end
61
+
62
+ def next_to_act(acting_player_position=-1)
63
+ position_of_first_active_player(
64
+ next_player_position(acting_player_position)
65
+ )
66
+ end
61
67
  end
62
68
  end
@@ -1,42 +1,46 @@
1
1
  require 'delegate'
2
2
 
3
3
  module AcpcPokerTypes
4
- class Seat < DelegateClass(Integer)
5
- attr_reader :seat, :table_size
6
4
 
7
- # @return [Bool] Reports whether or not +seat+ represents an out of
8
- # bounds seat for the number of seats, +num_seats+.
9
- def self.in_bounds?(seat, num_seats)
10
- seat < num_seats && seat >= 0
11
- end
5
+ class Seat < DelegateClass(Integer)
6
+ attr_reader :seat, :table_size
12
7
 
13
- def initialize(seat, num_seats_at_table)
14
- @seat = seat.to_i
15
- @table_size = num_seats_at_table.to_i
8
+ # @return [Bool] Reports whether or not +seat+ represents an out of
9
+ # bounds seat for the number of seats, +num_seats+.
10
+ def self.in_bounds?(seat, num_seats)
11
+ seat < num_seats && seat >= 0
12
+ end
16
13
 
17
- unless in_bounds?
18
- raise "Seat #{@seat} out of bounds for #{num_seats_at_table} players"
19
- end
14
+ def initialize(seat, num_seats_at_table)
15
+ @seat = (seat_number(seat) % num_seats_at_table).to_i
16
+ @table_size = num_seats_at_table
20
17
 
21
- super @seat
22
- end
23
- def seats_to(other_seat_number)
24
- other_seat = self.class.new(other_seat_number, @table_size)
25
-
26
- if @seat > other_seat
27
- other_seat + @table_size
28
- else
29
- other_seat
30
- end - @seat
31
- end
32
- def seats_from(other_seat_number)
33
- Seat.new(other_seat_number, @table_size).seats_to(@seat)
34
- end
35
- def n_seats_away(n)
36
- Seat.new((n + @seat) % @table_size, @table_size)
37
- end
38
- def in_bounds?
39
- self.class.in_bounds?(@seat, @table_size)
18
+ super @seat
19
+ end
20
+ def seats_to(other_player)
21
+ other_seat = self.class.new(other_player, @table_size)
22
+
23
+ if @seat > other_seat
24
+ other_seat + @table_size
25
+ else
26
+ other_seat
27
+ end - @seat
28
+ end
29
+ def seats_from(other_player)
30
+ self.class.new(other_player, @table_size).seats_to(@seat)
31
+ end
32
+ def n_seats_away(n)
33
+ Seat.new((n + @seat) % @table_size, @table_size)
34
+ end
35
+
36
+ private
37
+
38
+ def seat_number(player_or_seat)
39
+ if player_or_seat.respond_to?(:seat)
40
+ player_or_seat.seat
41
+ else
42
+ player_or_seat
40
43
  end
41
44
  end
45
+ end
42
46
  end
@@ -1,3 +1,3 @@
1
1
  module AcpcPokerTypes
2
- VERSION = '6.1.2'
2
+ VERSION = '6.2.0'
3
3
  end
@@ -9,6 +9,7 @@ require_relative "../lib/acpc_poker_types/suit"
9
9
  require_relative "../lib/acpc_poker_types/hand"
10
10
  require_relative "../lib/acpc_poker_types/card"
11
11
  require_relative "../lib/acpc_poker_types/game_definition"
12
+ require_relative "../lib/acpc_poker_types/acpc_dealer_data/poker_match_data"
12
13
 
13
14
  module MapWithIndex
14
15
  refine Array do
@@ -269,7 +270,7 @@ describe MatchState do
269
270
  end[0..-2]
270
271
 
271
272
  match_state =
272
- "#{MatchState::LABEL}:#{position}:0:crcc/ccc/rrfc:#{hand_string}"
273
+ "#{MatchState::LABEL}:#{position}:0:crcc/ccc/rrfc:#{hand_string}"
273
274
 
274
275
  MatchState.new(
275
276
  match_state
@@ -377,7 +378,7 @@ describe MatchState do
377
378
  end[0..-2]
378
379
 
379
380
  match_state =
380
- "#{MatchState::LABEL}:#{position}:0:crcc/ccc/rrfc/crc:#{hand_string}"
381
+ "#{MatchState::LABEL}:#{position}:0:crcc/ccc/rrfc/crc:#{hand_string}"
381
382
 
382
383
  MatchState.new(match_state).every_action(x_game_def) do |action, round, acting_player_position|
383
384
  x_yields = x_actions.shift
@@ -390,7 +391,7 @@ describe MatchState do
390
391
  end
391
392
  end
392
393
  describe '#players' do
393
- it 'return proper player states' do
394
+ it 'returns proper player states' do
394
395
  wager_size = 10
395
396
  x_game_def = GameDefinition.new(
396
397
  first_player_positions: [3, 2, 2],
@@ -574,37 +575,37 @@ describe MatchState do
574
575
  end
575
576
  end
576
577
  end
577
- describe '#pot' do
578
- it 'works without side pots' do
579
- wager_size = 10
580
- x_game_def = GameDefinition.new(
581
- first_player_positions: [3, 2, 2, 2],
582
- chip_stacks: [100, 200, 150],
583
- blinds: [0, 10, 5],
584
- raise_sizes: [wager_size]*4,
585
- number_of_ranks: 3
586
- )
587
- x_total_contributions = [2 * 10, 5 * 10, 5 * 10]
578
+ end
579
+ describe '#pot' do
580
+ it 'works without side pots' do
581
+ wager_size = 10
582
+ x_game_def = GameDefinition.new(
583
+ first_player_positions: [3, 2, 2, 2],
584
+ chip_stacks: [100, 200, 150],
585
+ blinds: [0, 10, 5],
586
+ raise_sizes: [wager_size]*4,
587
+ number_of_ranks: 3
588
+ )
589
+ x_total_contributions = [2 * 10, 5 * 10, 5 * 10]
588
590
 
589
- (0..x_game_def.number_of_players-1).each do |position|
590
- hands = x_game_def.number_of_players.times.map do |i|
591
- Hand.from_acpc "Ac2#{['s', 'h', 'd', 'c'][i%4]}"
592
- end
591
+ (0..x_game_def.number_of_players-1).each do |position|
592
+ hands = x_game_def.number_of_players.times.map do |i|
593
+ Hand.from_acpc "Ac2#{['s', 'h', 'd', 'c'][i%4]}"
594
+ end
593
595
 
594
- hand_string = hands.inject('') do |hand_string, hand|
595
- hand_string << "#{hand}#{MatchState::HAND_SEPARATOR}"
596
- end[0..-2]
596
+ hand_string = hands.inject('') do |hand_string, hand|
597
+ hand_string << "#{hand}#{MatchState::HAND_SEPARATOR}"
598
+ end[0..-2]
597
599
 
598
- match_state =
599
- "#{MatchState::LABEL}:#{position}:0:crcc/ccc/rrfc/crc:#{hand_string}"
600
+ match_state =
601
+ "#{MatchState::LABEL}:#{position}:0:crcc/ccc/rrfc/crc:#{hand_string}"
600
602
 
601
- MatchState.new(match_state).pot(x_game_def).must_equal x_total_contributions.inject(:+)
602
- end
603
+ MatchState.new(match_state).pot(x_game_def).must_equal x_total_contributions.inject(:+)
603
604
  end
604
605
  end
605
606
  end
606
- describe '#every_action' do
607
- it 'yields every action, plus the round number, and the acting player position relative to the dealer' do
607
+ describe '#player_acting_sequence' do
608
+ it 'works' do
608
609
  wager_size = 10
609
610
  x_game_def = GameDefinition.new(
610
611
  first_player_positions: [3, 2, 2, 2],
@@ -704,7 +705,7 @@ describe MatchState do
704
705
  end
705
706
  end
706
707
  end
707
- describe 'hand_ended?' do
708
+ describe '#hand_ended?' do
708
709
  it 'works when there is a showdown' do
709
710
  wager_size = 10
710
711
  x_game_def = GameDefinition.new(
@@ -781,6 +782,40 @@ describe MatchState do
781
782
  end
782
783
  end
783
784
  end
785
+ describe '#min_wager_by' do
786
+ it 'return proper player states' do
787
+ wager_size = 10
788
+ x_game_def = GameDefinition.new(
789
+ first_player_positions: [0, 0, 0],
790
+ chip_stacks: [100, 200, 150],
791
+ blinds: [0, 10, 5],
792
+ raise_sizes: [wager_size]*3,
793
+ number_of_ranks: 3
794
+ )
795
+
796
+ x_min_wagers = [[wager_size], [wager_size, 20, 70, 70, 70], [wager_size, wager_size, wager_size], [wager_size, wager_size, 20, 30, 30]]
797
+
798
+ (0..x_game_def.number_of_players-1).each do |position|
799
+ actions = ''
800
+ [[''], ['c', 'r30', 'r100', 'c', 'c'], ['c', 'c', 'c'], ['c', 'r110', 'r130', 'r160', 'c']].each_with_index do |actions_per_round, i|
801
+ actions_per_round.each_with_index do |action, j|
802
+ actions << action
803
+
804
+ hands = x_game_def.number_of_players.times.map { |i| "Ac#{i+2}h" }
805
+
806
+ hand_string = hands.inject('') do |string, hand|
807
+ string << "#{hand}#{MatchState::HAND_SEPARATOR}"
808
+ end[0..-2]
809
+
810
+ match_state = "#{MatchState::LABEL}:#{position}:0:#{actions}:#{hand_string}"
811
+
812
+ MatchState.new(match_state).min_wager_by(x_game_def).must_equal x_min_wagers[i][j]
813
+ end
814
+ actions << '/' unless actions_per_round.first.empty?
815
+ end
816
+ end
817
+ end
818
+ end
784
819
  end
785
820
 
786
821
  def for_every_card
@@ -797,9 +832,6 @@ def for_every_hand
797
832
  end
798
833
  end
799
834
  end
800
- def test_match_state_initialization_error(incomplete_match_state)
801
- ->{MatchState.parse incomplete_match_state}.must_raise(MatchState::IncompleteMatchState)
802
- end
803
835
  def test_match_state_success(match_state)
804
836
  patient = MatchState.parse match_state
805
837
  patient.to_s.must_equal match_state
@@ -828,14 +860,6 @@ def arbitrary_roll_out(rounds)
828
860
  community_cards
829
861
  end
830
862
 
831
- # Construct an arbitrary hole card hand.
832
- #
833
- # @return [Hand] An arbitrary hole card hand.
834
863
  def arbitrary_hole_card_hand
835
- Hand.from_acpc(
836
- Rank::DOMAIN[:two][:acpc_character] +
837
- Suit::DOMAIN[:spades][:acpc_character] +
838
- Rank::DOMAIN[:three][:acpc_character] +
839
- Suit::DOMAIN[:hearts][:acpc_character]
840
- )
864
+ Hand.from_acpc('2s3h')
841
865
  end
data/spec/seat_spec.rb ADDED
@@ -0,0 +1,59 @@
1
+ require_relative 'support/spec_helper'
2
+
3
+ require 'acpc_poker_types/seat'
4
+
5
+ include AcpcPokerTypes
6
+
7
+ describe Seat do
8
+ it 'acts like an integer' do
9
+ x_int = 2
10
+ patient = Seat.new x_int, 4
11
+
12
+ patient.must_equal x_int
13
+ (patient + x_int).must_equal x_int * 2
14
+ end
15
+ it 'accepts players as well as seats' do
16
+ Struct.new 'Player', :seat
17
+
18
+ x_player = Struct::Player.new(1)
19
+ Seat.new(x_player, 4).must_equal x_player.seat
20
+ end
21
+ it 'accepts seats that are larger than the table size by wrapping' do
22
+ x_seat = 2
23
+
24
+ Seat.new(5, 3).must_equal x_seat
25
+ end
26
+ describe '#seats_to' do
27
+ it 'works for seats on the left' do
28
+ Seat.new(2, 5).seats_to(4).must_equal 2
29
+ end
30
+ it 'works for seats on the right' do
31
+ Seat.new(2, 5).seats_to(0).must_equal 3
32
+ end
33
+ it 'works for its own seat' do
34
+ Seat.new(1, 2).seats_to(1).must_equal 0
35
+ end
36
+ end
37
+ describe '#seats_from' do
38
+ it 'works for seats on the left' do
39
+ Seat.new(2, 5).seats_from(4).must_equal 3
40
+ end
41
+ it 'works for seats on the right' do
42
+ Seat.new(2, 5).seats_from(0).must_equal 2
43
+ end
44
+ it 'works for its own seat' do
45
+ Seat.new(1, 2).seats_from(1).must_equal 0
46
+ end
47
+ end
48
+ describe '#n_seats_away' do
49
+ it 'works for positive n' do
50
+ Seat.new(2, 5).n_seats_away(2).must_equal 4
51
+ end
52
+ it 'works for negative n' do
53
+ Seat.new(2, 5).n_seats_away(-2).must_equal 0
54
+ end
55
+ it 'works for n larger than the size of the table' do
56
+ Seat.new(1, 5).n_seats_away(8).must_equal 4
57
+ end
58
+ end
59
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: acpc_poker_types
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.1.2
4
+ version: 6.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dustin Morrill
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-08-02 00:00:00.000000000 Z
11
+ date: 2013-08-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: process_runner
@@ -206,6 +206,7 @@ files:
206
206
  - spec/suit_spec.rb
207
207
  - spec/hand_results_spec.rb
208
208
  - spec/hand_spec.rb
209
+ - spec/seat_spec.rb
209
210
  - spec/poker_match_data_spec.rb
210
211
  - spec/coverage/index.html
211
212
  - spec/coverage/assets/0.7.1/application.js
@@ -298,6 +299,7 @@ test_files:
298
299
  - spec/suit_spec.rb
299
300
  - spec/hand_results_spec.rb
300
301
  - spec/hand_spec.rb
302
+ - spec/seat_spec.rb
301
303
  - spec/poker_match_data_spec.rb
302
304
  - spec/coverage/index.html
303
305
  - spec/coverage/assets/0.7.1/application.js