acpc_poker_types 2.0.0 → 3.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/acpc_poker_types.gemspec +2 -2
  3. data/lib/acpc_poker_types/acpc_dealer_data/action_messages.rb +1 -3
  4. data/lib/acpc_poker_types/acpc_dealer_data/poker_match_data.rb +1 -1
  5. data/lib/acpc_poker_types/board_cards.rb +38 -37
  6. data/lib/acpc_poker_types/card.rb +40 -54
  7. data/lib/acpc_poker_types/chip_stack.rb +25 -25
  8. data/lib/acpc_poker_types/game_definition.rb +286 -284
  9. data/lib/acpc_poker_types/hand.rb +19 -17
  10. data/lib/acpc_poker_types/match_state.rb +208 -235
  11. data/lib/acpc_poker_types/pile_of_cards.rb +6 -4
  12. data/lib/acpc_poker_types/player.rb +138 -133
  13. data/lib/acpc_poker_types/poker_action.rb +80 -90
  14. data/lib/acpc_poker_types/rank.rb +51 -49
  15. data/lib/acpc_poker_types/suit.rb +45 -43
  16. data/lib/acpc_poker_types/version.rb +1 -1
  17. data/spec/card_spec.rb +0 -5
  18. data/spec/coverage/index.html +1 -1
  19. data/spec/match_state_spec.rb +8 -10
  20. data/spec/player_spec.rb +12 -19
  21. data/spec/poker_action_spec.rb +105 -171
  22. data/spec/support/spec_helper.rb +0 -1
  23. metadata +121 -219
  24. data/spec/coverage/assets/0.5.3/app.js +0 -88
  25. data/spec/coverage/assets/0.5.3/fancybox/blank.gif +0 -0
  26. data/spec/coverage/assets/0.5.3/fancybox/fancy_close.png +0 -0
  27. data/spec/coverage/assets/0.5.3/fancybox/fancy_loading.png +0 -0
  28. data/spec/coverage/assets/0.5.3/fancybox/fancy_nav_left.png +0 -0
  29. data/spec/coverage/assets/0.5.3/fancybox/fancy_nav_right.png +0 -0
  30. data/spec/coverage/assets/0.5.3/fancybox/fancy_shadow_e.png +0 -0
  31. data/spec/coverage/assets/0.5.3/fancybox/fancy_shadow_n.png +0 -0
  32. data/spec/coverage/assets/0.5.3/fancybox/fancy_shadow_ne.png +0 -0
  33. data/spec/coverage/assets/0.5.3/fancybox/fancy_shadow_nw.png +0 -0
  34. data/spec/coverage/assets/0.5.3/fancybox/fancy_shadow_s.png +0 -0
  35. data/spec/coverage/assets/0.5.3/fancybox/fancy_shadow_se.png +0 -0
  36. data/spec/coverage/assets/0.5.3/fancybox/fancy_shadow_sw.png +0 -0
  37. data/spec/coverage/assets/0.5.3/fancybox/fancy_shadow_w.png +0 -0
  38. data/spec/coverage/assets/0.5.3/fancybox/fancy_title_left.png +0 -0
  39. data/spec/coverage/assets/0.5.3/fancybox/fancy_title_main.png +0 -0
  40. data/spec/coverage/assets/0.5.3/fancybox/fancy_title_over.png +0 -0
  41. data/spec/coverage/assets/0.5.3/fancybox/fancy_title_right.png +0 -0
  42. data/spec/coverage/assets/0.5.3/fancybox/fancybox-x.png +0 -0
  43. data/spec/coverage/assets/0.5.3/fancybox/fancybox-y.png +0 -0
  44. data/spec/coverage/assets/0.5.3/fancybox/fancybox.png +0 -0
  45. data/spec/coverage/assets/0.5.3/fancybox/jquery.fancybox-1.3.1.css +0 -363
  46. data/spec/coverage/assets/0.5.3/fancybox/jquery.fancybox-1.3.1.pack.js +0 -44
  47. data/spec/coverage/assets/0.5.3/favicon_green.png +0 -0
  48. data/spec/coverage/assets/0.5.3/favicon_red.png +0 -0
  49. data/spec/coverage/assets/0.5.3/favicon_yellow.png +0 -0
  50. data/spec/coverage/assets/0.5.3/highlight.css +0 -129
  51. data/spec/coverage/assets/0.5.3/highlight.pack.js +0 -1
  52. data/spec/coverage/assets/0.5.3/jquery-1.6.2.min.js +0 -18
  53. data/spec/coverage/assets/0.5.3/jquery.dataTables.min.js +0 -152
  54. data/spec/coverage/assets/0.5.3/jquery.timeago.js +0 -141
  55. data/spec/coverage/assets/0.5.3/jquery.url.js +0 -174
  56. data/spec/coverage/assets/0.5.3/loading.gif +0 -0
  57. data/spec/coverage/assets/0.5.3/magnify.png +0 -0
  58. data/spec/coverage/assets/0.5.3/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  59. data/spec/coverage/assets/0.5.3/smoothness/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  60. data/spec/coverage/assets/0.5.3/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  61. data/spec/coverage/assets/0.5.3/smoothness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  62. data/spec/coverage/assets/0.5.3/smoothness/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  63. data/spec/coverage/assets/0.5.3/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  64. data/spec/coverage/assets/0.5.3/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  65. data/spec/coverage/assets/0.5.3/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  66. data/spec/coverage/assets/0.5.3/smoothness/images/ui-icons_222222_256x240.png +0 -0
  67. data/spec/coverage/assets/0.5.3/smoothness/images/ui-icons_2e83ff_256x240.png +0 -0
  68. data/spec/coverage/assets/0.5.3/smoothness/images/ui-icons_454545_256x240.png +0 -0
  69. data/spec/coverage/assets/0.5.3/smoothness/images/ui-icons_888888_256x240.png +0 -0
  70. data/spec/coverage/assets/0.5.3/smoothness/images/ui-icons_cd0a0a_256x240.png +0 -0
  71. data/spec/coverage/assets/0.5.3/smoothness/jquery-ui-1.8.4.custom.css +0 -295
  72. data/spec/coverage/assets/0.5.3/stylesheet.css +0 -383
@@ -2,25 +2,27 @@
2
2
  require 'acpc_poker_types/pile_of_cards'
3
3
  require 'acpc_poker_types/card'
4
4
 
5
- class AcpcPokerTypes::Hand < AcpcPokerTypes::PileOfCards
6
- # @return [Hand]
7
- def self.draw_cards(*cards)
8
- AcpcPokerTypes::Hand.new cards
9
- end
5
+ module AcpcPokerTypes
6
+ class Hand < AcpcPokerTypes::PileOfCards
7
+ # @return [Hand]
8
+ def self.draw_cards(*cards)
9
+ AcpcPokerTypes::Hand.new cards
10
+ end
10
11
 
11
- # @param [String] acpc_string_hand ACPC string description of a hand.
12
- # @return [Hand]
13
- def self.from_acpc(acpc_string_hand)
14
- AcpcPokerTypes::Hand.new AcpcPokerTypes::Card.cards(acpc_string_hand)
15
- end
12
+ # @param [String] acpc_string_hand ACPC string description of a hand.
13
+ # @return [Hand]
14
+ def self.from_acpc(acpc_string_hand)
15
+ AcpcPokerTypes::Hand.new AcpcPokerTypes::Card.cards(acpc_string_hand)
16
+ end
16
17
 
17
- def to_s
18
- join
19
- end
18
+ def to_s
19
+ join
20
+ end
20
21
 
21
- alias_method :to_str, :to_s
22
+ alias_method :to_str, :to_s
22
23
 
23
- def to_acpc
24
- (map { |card| card.to_acpc }).join
24
+ def to_acpc
25
+ (map { |card| card.to_acpc }).join
26
+ end
25
27
  end
26
- end
28
+ end
@@ -8,280 +8,253 @@ require 'acpc_poker_types/suit'
8
8
  require 'acpc_poker_types/poker_action'
9
9
 
10
10
  # Model to parse and manage information from a given match state string.
11
- class AcpcPokerTypes::MatchState
12
- exceptions :incomplete_match_state
13
-
14
- # @return [Integer] The position relative to the dealer of the player that
15
- # received the match state string, indexed from 0, modulo the
16
- # number of players.
17
- # @example The player immediately to the left of the dealer has
18
- # +position_relative_to_dealer+ == 0
19
- # @example The dealer has
20
- # +position_relative_to_dealer+ == <number of players> - 1
21
- attr_reader :position_relative_to_dealer
22
-
23
- # @return [Integer] The hand number.
24
- attr_reader :hand_number
25
-
26
- # @return [Array<Array<AcpcPokerTypes::PokerAction>>] The sequence of betting actions.
27
- attr_reader :betting_sequence
28
-
29
- # @return [Array<AcpcPokerTypes::Hand>] The list of visible hole card sets for each player.
30
- attr_reader :list_of_hole_card_hands
31
-
32
- # @return [AcpcPokerTypes::BoardCards] All visible community cards on the board.
33
- attr_reader :board_cards
34
-
35
- # @return [Array<Integer>] The list of first seats for each round.
36
- attr_reader :first_seat_in_each_round
37
-
38
- # @return [String] Label for match state strings.
39
- LABEL = 'MATCHSTATE'
40
-
41
- alias_new :parse
42
-
43
- # Builds a match state string from its given component parts.
44
- #
45
- # @param [#to_s] position_relative_to_dealer The position relative to the dealer.
46
- # @param [#to_s] hand_number The hand number.
47
- # @param [#to_s] betting_sequence The betting sequence.
48
- # @param [#to_s] all_hole_cards All the hole cards visible.
49
- # @param [#to_acpc, #empty?] board_cards All the community cards on the board.
50
- # @return [String] The constructed match state string.
51
- def self.build_match_state_string(
52
- position_relative_to_dealer,
53
- hand_number,
54
- betting_sequence,
55
- all_hole_cards,
56
- board_cards
57
- )
58
- string = LABEL +
59
- ":#{position_relative_to_dealer}:#{hand_number}:#{betting_sequence}:#{all_hole_cards}"
60
-
61
- string += board_cards.to_acpc if board_cards && !board_cards.empty?
62
- string
63
- end
11
+ module AcpcPokerTypes
12
+ class MatchState
13
+ exceptions :incomplete_match_state
14
+
15
+ # @return [Integer] The position relative to the dealer of the player that
16
+ # received the match state string, indexed from 0, modulo the
17
+ # number of players.
18
+ # @example The player immediately to the left of the dealer has
19
+ # +position_relative_to_dealer+ == 0
20
+ # @example The dealer has
21
+ # +position_relative_to_dealer+ == <number of players> - 1
22
+ attr_reader :position_relative_to_dealer
23
+
24
+ # @return [Integer] The hand number.
25
+ attr_reader :hand_number
26
+
27
+ # @return [Array<Array<AcpcPokerTypes::PokerAction>>] The sequence of betting actions.
28
+ attr_reader :betting_sequence
29
+
30
+ # @return [Array<AcpcPokerTypes::Hand>] The list of visible hole card sets for each player.
31
+ attr_reader :list_of_hole_card_hands
32
+
33
+ # @return [AcpcPokerTypes::BoardCards] All visible community cards on the board.
34
+ attr_reader :board_cards
35
+
36
+ # @return [Array<Integer>] The list of first seats for each round.
37
+ attr_reader :first_seat_in_each_round
38
+
39
+ # @return [String] Label for match state strings.
40
+ LABEL = 'MATCHSTATE'
41
+
42
+ alias_new :parse
43
+
44
+ # Builds a match state string from its given component parts.
45
+ #
46
+ # @param [#to_s] position_relative_to_dealer The position relative to the dealer.
47
+ # @param [#to_s] hand_number The hand number.
48
+ # @param [#to_s] betting_sequence The betting sequence.
49
+ # @param [#to_s] all_hole_cards All the hole cards visible.
50
+ # @param [#to_acpc, #empty?] board_cards All the community cards on the board.
51
+ # @return [String] The constructed match state string.
52
+ def self.build_match_state_string(
53
+ position_relative_to_dealer,
54
+ hand_number,
55
+ betting_sequence,
56
+ all_hole_cards,
57
+ board_cards
58
+ )
59
+ string = LABEL +
60
+ ":#{position_relative_to_dealer}:#{hand_number}:#{betting_sequence}:#{all_hole_cards}"
64
61
 
65
- # Checks if the given line is a comment beginning with '#' or ';', or empty.
66
- #
67
- # @param [String] line
68
- # @return [Boolean] True if +line+ is a comment or empty, false otherwise.
69
- def self.line_is_comment_or_empty?(line)
70
- line.nil? || line.match(/^\s*[#;]/) || line.empty?
71
- end
62
+ string += board_cards.to_acpc if board_cards && !board_cards.empty?
63
+ string
64
+ end
72
65
 
73
- # @param [String] raw_match_state A raw match state string to be parsed.
74
- # @raise IncompleteMatchState
75
- def initialize(raw_match_state)
76
- raise IncompleteMatchState, raw_match_state if AcpcPokerTypes::MatchState.line_is_comment_or_empty? raw_match_state
77
-
78
- all_actions = AcpcPokerTypes::PokerAction::LEGAL_ACPC_CHARACTERS.to_a.join
79
- all_ranks = (AcpcPokerTypes::Rank::DOMAIN.map { |rank, properties| properties[:acpc_character] }).join
80
- all_suits = (AcpcPokerTypes::Suit::DOMAIN.map { |suit, properties| properties[:acpc_character] }).join
81
- all_card_tokens = all_ranks + all_suits
82
- if raw_match_state.match(
83
- /#{LABEL}:(\d+):(\d+):([\d#{all_actions}\/]*):([|#{all_card_tokens}]+)\/*([\/#{all_card_tokens}]*)/)
84
- @position_relative_to_dealer = $1.to_i
85
- @hand_number = $2.to_i
86
- @betting_sequence = parse_betting_sequence $3
87
- @list_of_hole_card_hands = parse_list_of_hole_card_hands $4
88
- @board_cards = parse_board_cards $5
66
+ # Checks if the given line is a comment beginning with '#' or ';', or empty.
67
+ #
68
+ # @param [String] line
69
+ # @return [Boolean] True if +line+ is a comment or empty, false otherwise.
70
+ def self.line_is_comment_or_empty?(line)
71
+ line.nil? || line.match(/^\s*[#;]/) || line.empty?
89
72
  end
90
73
 
91
- raise IncompleteMatchState, raw_match_state if incomplete_match_state?
92
- end
74
+ # @param [String] raw_match_state A raw match state string to be parsed.
75
+ # @raise IncompleteMatchState
76
+ def initialize(raw_match_state)
77
+ raise IncompleteMatchState, raw_match_state if AcpcPokerTypes::MatchState.line_is_comment_or_empty? raw_match_state
78
+
79
+ if raw_match_state.match(
80
+ /#{LABEL}:(\d+):(\d+):([\d#{AcpcPokerTypes::PokerAction::CONCATONATED_ACTIONS}\/]*):([|#{AcpcPokerTypes::Card::CONCATONATED_CARDS}]+)\/*([\/#{AcpcPokerTypes::Card::CONCATONATED_CARDS}]*)/)
81
+ @position_relative_to_dealer = $1.to_i
82
+ @hand_number = $2.to_i
83
+ @betting_sequence = parse_betting_sequence $3
84
+ @list_of_hole_card_hands = parse_list_of_hole_card_hands $4
85
+ @board_cards = parse_board_cards $5
86
+ end
93
87
 
94
- # @return [String] The AcpcPokerTypes::MatchState in raw text form.
95
- def to_str
96
- AcpcPokerTypes::MatchState.build_match_state_string(
97
- @position_relative_to_dealer,
98
- @hand_number, betting_sequence_string,
99
- hole_card_strings,
100
- @board_cards
101
- )
102
- end
88
+ raise IncompleteMatchState, raw_match_state if incomplete_match_state?
89
+ end
103
90
 
104
- # @see to_str
105
- alias_method :to_s, :to_str
91
+ # @return [String] The AcpcPokerTypes::MatchState in raw text form.
92
+ def to_str
93
+ AcpcPokerTypes::MatchState.build_match_state_string(
94
+ @position_relative_to_dealer,
95
+ @hand_number, betting_sequence_string,
96
+ hole_card_strings,
97
+ @board_cards
98
+ )
99
+ end
106
100
 
107
- # @param [AcpcPokerTypes::MatchState] another_match_state A match state string to compare against this one.
108
- # @return [Boolean] +true+ if this match state string is equivalent to +another_match_state+, +false+ otherwise.
109
- def ==(another_match_state)
110
- another_match_state.to_s == to_s
111
- end
101
+ # @see to_str
102
+ alias_method :to_s, :to_str
112
103
 
113
- # @return [Integer] The number of players in this match.
114
- def number_of_players() @list_of_hole_card_hands.length end
115
-
116
- # @param [Array<Array<AcpcPokerTypes::PokerAction>>] betting_sequence The betting sequence from which the last action should be retrieved.
117
- # @return [AcpcPokerTypes::PokerAction] The last action taken.
118
- # @raise NoActionsHaveBeenTaken if no actions have been taken.
119
- def last_action(betting_sequence=@betting_sequence)
120
- if betting_sequence.nil? || betting_sequence.empty?
121
- nil
122
- elsif betting_sequence.last.last
123
- betting_sequence.last.last
124
- else
125
- last_action(betting_sequence.reject{ |elem| elem.equal?(betting_sequence.last) })
104
+ # @param [AcpcPokerTypes::MatchState] another_match_state A match state string to compare against this one.
105
+ # @return [Boolean] +true+ if this match state string is equivalent to +another_match_state+, +false+ otherwise.
106
+ def ==(another_match_state)
107
+ another_match_state.to_s == to_s
126
108
  end
127
- end
128
109
 
129
- # @return [AcpcPokerTypes::Hand] The user's hole cards.
130
- # @example An ace of diamonds and a 4 of clubs is represented as
131
- # 'Ad4c'
132
- def users_hole_cards
133
- @list_of_hole_card_hands[@position_relative_to_dealer]
134
- end
110
+ # @return [Integer] The number of players in this match.
111
+ def number_of_players() @list_of_hole_card_hands.length end
112
+
113
+ # @param [Array<Array<AcpcPokerTypes::PokerAction>>] betting_sequence The betting sequence from which the last action should be retrieved.
114
+ # @return [AcpcPokerTypes::PokerAction] The last action taken.
115
+ # @raise NoActionsHaveBeenTaken if no actions have been taken.
116
+ def last_action(betting_sequence=@betting_sequence)
117
+ if betting_sequence.nil? || betting_sequence.empty?
118
+ nil
119
+ elsif betting_sequence.last.last
120
+ betting_sequence.last.last
121
+ else
122
+ last_action(betting_sequence.reject{ |elem| elem.equal?(betting_sequence.last) })
123
+ end
124
+ end
135
125
 
136
- # @return [Array] The list of opponent hole cards that are visible.
137
- # @example If there are two opponents, one with AhKs and the other with QdJc, then
138
- # list_of_opponents_hole_cards == [AhKs:AcpcPokerTypes::Hand, QdJc:AcpcPokerTypes::Hand]
139
- def list_of_opponents_hole_cards
140
- local_list_of_hole_card_hands = @list_of_hole_card_hands.dup
141
- local_list_of_hole_card_hands.delete_at @position_relative_to_dealer
142
- local_list_of_hole_card_hands
143
- end
126
+ # @return [AcpcPokerTypes::Hand] The user's hole cards.
127
+ # @example An ace of diamonds and a 4 of clubs is represented as
128
+ # 'Ad4c'
129
+ def users_hole_cards
130
+ @list_of_hole_card_hands[@position_relative_to_dealer]
131
+ end
144
132
 
145
- # @return [Integer] The zero indexed current round number.
146
- def round
147
- @betting_sequence.length - 1
148
- end
133
+ # @return [Array] The list of opponent hole cards that are visible.
134
+ # @example If there are two opponents, one with AhKs and the other with QdJc, then
135
+ # list_of_opponents_hole_cards == [AhKs:AcpcPokerTypes::Hand, QdJc:AcpcPokerTypes::Hand]
136
+ def list_of_opponents_hole_cards
137
+ local_list_of_hole_card_hands = @list_of_hole_card_hands.dup
138
+ local_list_of_hole_card_hands.delete_at @position_relative_to_dealer
139
+ local_list_of_hole_card_hands
140
+ end
141
+
142
+ # @return [Integer] The zero indexed current round number.
143
+ def round
144
+ @betting_sequence.length - 1
145
+ end
149
146
 
150
- # @return [Integer] The number of actions in the current round.
151
- def number_of_actions_this_round() @betting_sequence[round].length end
147
+ # @return [Integer] The number of actions in the current round.
148
+ def number_of_actions_this_round() @betting_sequence[round].length end
152
149
 
153
- # @return [Integer] The number of actions in the current hand.
154
- def number_of_actions_this_hand
155
- @betting_sequence.inject(0) do |sum, sequence_per_round|
156
- sum += sequence_per_round.length
150
+ # @return [Integer] The number of actions in the current hand.
151
+ def number_of_actions_this_hand
152
+ @betting_sequence.inject(0) do |sum, sequence_per_round|
153
+ sum += sequence_per_round.length
154
+ end
157
155
  end
158
- end
159
156
 
160
- # @param [Array<Action>] betting_sequence=@betting_sequence The sequence of
161
- # actions to link into an ACPC string.
162
- # @return [String] The ACPC string created by the given betting sequence,
163
- # +betting_sequence+.
164
- def betting_sequence_string(betting_sequence=@betting_sequence)
165
- (round + 1).times.inject('') do |string, i|
166
- string += (betting_sequence[i].map { |action| action.to_acpc }).join('')
167
- string += '/' unless i == round
168
- string
157
+ # @param [Array<Action>] betting_sequence=@betting_sequence The sequence of
158
+ # actions to link into an ACPC string.
159
+ # @return [String] The ACPC string created by the given betting sequence,
160
+ # +betting_sequence+.
161
+ def betting_sequence_string(betting_sequence=@betting_sequence)
162
+ (round + 1).times.inject('') do |string, i|
163
+ string += (betting_sequence[i].map { |action| action.to_s }).join('')
164
+ string += '/' unless i == round
165
+ string
166
+ end
169
167
  end
170
- end
171
168
 
172
- # @return [Boolean] Reports whether or not it is the first state of the first round.
173
- def first_state_of_first_round?
174
- (0 == number_of_actions_this_hand)
175
- end
169
+ # @return [Boolean] Reports whether or not it is the first state of the first round.
170
+ def first_state_of_first_round?
171
+ (0 == number_of_actions_this_hand)
172
+ end
176
173
 
177
- def player_position_relative_to_self
178
- number_of_players - 1
179
- end
174
+ def player_position_relative_to_self
175
+ number_of_players - 1
176
+ end
180
177
 
181
- def round_in_which_last_action_taken
182
- unless number_of_actions_this_hand > 0
183
- nil
184
- else
185
- if number_of_actions_this_round < 1
186
- round - 1
178
+ def round_in_which_last_action_taken
179
+ unless number_of_actions_this_hand > 0
180
+ nil
187
181
  else
188
- round
182
+ if number_of_actions_this_round < 1
183
+ round - 1
184
+ else
185
+ round
186
+ end
189
187
  end
190
188
  end
191
- end
192
189
 
193
- private
194
-
195
- def validate_first_seats(list_of_first_seats)
196
- begin
197
- raise UnknownFirstSeat, round unless round < list_of_first_seats.length
198
- all_seats_are_occupied = ((problem_seat = list_of_first_seats.max) < number_of_players) && ((problem_seat = list_of_first_seats.min.abs)-1 < number_of_players)
199
- raise FirstSeatIsUnoccupied, problem_seat unless all_seats_are_occupied
200
- rescue UnknownFirstSeat => e
201
- raise e
202
- rescue FirstSeatIsUnoccupied => e
203
- raise e
204
- rescue => e
205
- raise UnknownFirstSeat, e.message
190
+ private
191
+
192
+ def validate_first_seats(list_of_first_seats)
193
+ begin
194
+ raise UnknownFirstSeat, round unless round < list_of_first_seats.length
195
+ all_seats_are_occupied = ((problem_seat = list_of_first_seats.max) < number_of_players) && ((problem_seat = list_of_first_seats.min.abs)-1 < number_of_players)
196
+ raise FirstSeatIsUnoccupied, problem_seat unless all_seats_are_occupied
197
+ rescue UnknownFirstSeat => e
198
+ raise e
199
+ rescue FirstSeatIsUnoccupied => e
200
+ raise e
201
+ rescue => e
202
+ raise UnknownFirstSeat, e.message
203
+ end
204
+ list_of_first_seats
206
205
  end
207
- list_of_first_seats
208
- end
209
-
210
- def list_of_actions_from_acpc_characters(betting_sequence)
211
- all_actions = AcpcPokerTypes::PokerAction::LEGAL_ACPC_CHARACTERS.to_a.join ''
212
- betting_sequence.scan(/[#{all_actions}]\d*/)
213
- end
214
206
 
215
- def incomplete_match_state?
216
- !(@position_relative_to_dealer and @hand_number and
217
- @list_of_hole_card_hands) || @list_of_hole_card_hands.empty?
218
- end
207
+ def list_of_actions_from_acpc_characters(betting_sequence)
208
+ betting_sequence.scan(/[#{AcpcPokerTypes::PokerAction::CONCATONATED_ACTIONS}]\d*/)
209
+ end
219
210
 
220
- def parse_list_of_hole_card_hands(string_of_hole_cards)
221
- list_of_hole_card_hands = []
222
- for_every_set_of_cards(string_of_hole_cards, '\|') do |string_hand|
223
- hand = AcpcPokerTypes::Hand.from_acpc string_hand
224
- list_of_hole_card_hands.push hand
211
+ def incomplete_match_state?
212
+ !(@position_relative_to_dealer and @hand_number and
213
+ @list_of_hole_card_hands) || @list_of_hole_card_hands.empty?
225
214
  end
226
- while list_of_hole_card_hands.length < (string_of_hole_cards.count('|') + 1)
227
- list_of_hole_card_hands.push AcpcPokerTypes::Hand.new
215
+
216
+ def parse_list_of_hole_card_hands(string_of_hole_cards)
217
+ list_of_hole_card_hands = every_set_of_cards(string_of_hole_cards, '\|').map do |string_hand|
218
+ AcpcPokerTypes::Hand.from_acpc string_hand
219
+ end
220
+ while list_of_hole_card_hands.length < (string_of_hole_cards.count('|') + 1)
221
+ list_of_hole_card_hands.push AcpcPokerTypes::Hand.new
222
+ end
223
+ list_of_hole_card_hands
228
224
  end
229
- list_of_hole_card_hands
230
- end
231
225
 
232
- def parse_betting_sequence(string_betting_sequence, acting_player_sees_wager=true)
233
- return [[]] if string_betting_sequence.empty?
226
+ def parse_betting_sequence(string_betting_sequence)
227
+ return [[]] if string_betting_sequence.empty?
234
228
 
235
- list_of_actions_by_round = string_betting_sequence.split(/\//)
236
- betting_sequence = list_of_actions_by_round.inject([]) do |list_of_actions, betting_string_in_a_particular_round|
237
- list_of_actions_in_a_particular_round = list_of_actions_from_acpc_characters(betting_string_in_a_particular_round).inject([]) do |list, action|
238
- list.push AcpcPokerTypes::PokerAction.new(action)
229
+ betting_sequence = string_betting_sequence.split(/\//).map do |betting_string_per_round|
230
+ list_of_actions_in_a_particular_round = list_of_actions_from_acpc_characters(
231
+ betting_string_per_round
232
+ ).map do |action|
233
+ AcpcPokerTypes::PokerAction.new(action)
234
+ end
239
235
  end
240
- list_of_actions.push list_of_actions_in_a_particular_round
241
- end
242
- # Increase the resolution of the last action
243
- # @todo I'm creating one too many AcpcPokerTypes::PokerActions, but I'm not going to worry about it for now.
244
- betting_sequence[-1][-1] = AcpcPokerTypes::PokerAction.new(
245
- last_action(betting_sequence).to_acpc_character,
246
- {
247
- amount_to_put_in_pot: last_action(betting_sequence).amount_to_put_in_pot,
248
- modifier: last_action(betting_sequence).modifier,
249
- acting_player_sees_wager: acting_player_sees_wager
250
- }
251
- )
252
236
 
253
- # Adjust the number of rounds if the last action was the last action in the round
254
- if string_betting_sequence.match(/\//)
255
- betting_sequence << [] if string_betting_sequence.count('/') > (betting_sequence.length - 1)
237
+ # Adjust the number of rounds if the last action was the last action in the round
238
+ betting_sequence << [] if string_betting_sequence.match(/\/$/)
239
+ betting_sequence
256
240
  end
257
- betting_sequence
258
- end
259
241
 
260
- def parse_board_cards(string_board_cards)
261
- board_cards = AcpcPokerTypes::BoardCards.new
262
- for_every_set_of_cards(string_board_cards, '\/') do |string_board_card_set|
263
- next if string_board_card_set.match(/^\s*$/)
264
- for_every_card(string_board_card_set) do |card|
265
- board_cards << card
266
- end
242
+ def parse_board_cards(string_board_cards)
243
+ board_cards = AcpcPokerTypes::BoardCards.new(
244
+ every_set_of_cards(string_board_cards, '\/').map do |cards_in_round|
245
+ AcpcPokerTypes::Card.cards(cards_in_round)
246
+ end
247
+ )
267
248
  board_cards.next_round! if board_cards.round < string_board_cards.count('/')
249
+ board_cards
268
250
  end
269
- board_cards
270
- end
271
251
 
272
- def for_every_set_of_cards(string_of_card_sets, divider)
273
- string_of_card_sets.split(/#{divider}/).each do |string_card_set|
274
- yield string_card_set
252
+ def every_set_of_cards(string_of_card_sets, divider)
253
+ string_of_card_sets.split(/#{divider}/)
275
254
  end
276
- end
277
255
 
278
- def for_every_card(string_of_cards)
279
- AcpcPokerTypes::Card.cards(string_of_cards).each do |card|
280
- yield card
256
+ def hole_card_strings
257
+ (@list_of_hole_card_hands.map { |hand| hand.to_acpc }).join '|'
281
258
  end
282
259
  end
283
-
284
- def hole_card_strings
285
- (@list_of_hole_card_hands.map { |hand| hand.to_acpc }).join '|'
286
- end
287
- end
260
+ end