Class: CribbageGame::Game

Inherits:
Object
  • Object
show all
Defined in:
lib/cribbage_game/game.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(args = {}) ⇒ Game



19
20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/cribbage_game/game.rb', line 19

def initialize args = {}
  @points_to_win = args[:points_to_win] || 121
  @auto_score = args[:is_auto_score] || true
  @game_over_cb = args[:game_over_cb] || lambda {}
  @players = 2.times.map { |id| Player.new self, id.to_s }
  @score_client = Score.new self
  @fsm = Fsm.new
  @deck = self.class.get_cards_hash CardDeck::Deck.new.cards
  @round = 0
  @winner = nil

  reset_cards
end

Instance Attribute Details

#auto_scoreObject (readonly)

Returns the value of attribute auto_score.



17
18
19
# File 'lib/cribbage_game/game.rb', line 17

def auto_score
  @auto_score
end

#cribObject

Returns the value of attribute crib.



16
17
18
# File 'lib/cribbage_game/game.rb', line 16

def crib
  @crib
end

#cut_cardObject

Returns the value of attribute cut_card.



16
17
18
# File 'lib/cribbage_game/game.rb', line 16

def cut_card
  @cut_card
end

#dealerObject

Returns the value of attribute dealer.



16
17
18
# File 'lib/cribbage_game/game.rb', line 16

def dealer
  @dealer
end

#deckObject

Returns the value of attribute deck.



16
17
18
# File 'lib/cribbage_game/game.rb', line 16

def deck
  @deck
end

#fsmObject

Returns the value of attribute fsm.



16
17
18
# File 'lib/cribbage_game/game.rb', line 16

def fsm
  @fsm
end

#pileObject

Returns the value of attribute pile.



16
17
18
# File 'lib/cribbage_game/game.rb', line 16

def pile
  @pile
end

#playersObject

Returns the value of attribute players.



16
17
18
# File 'lib/cribbage_game/game.rb', line 16

def players
  @players
end

#points_to_winObject

Returns the value of attribute points_to_win.



16
17
18
# File 'lib/cribbage_game/game.rb', line 16

def points_to_win
  @points_to_win
end

#roundObject

Returns the value of attribute round.



16
17
18
# File 'lib/cribbage_game/game.rb', line 16

def round
  @round
end

#whose_turnObject

Returns the value of attribute whose_turn.



16
17
18
# File 'lib/cribbage_game/game.rb', line 16

def whose_turn
  @whose_turn
end

#winnerObject

Returns the value of attribute winner.



16
17
18
# File 'lib/cribbage_game/game.rb', line 16

def winner
  @winner
end

Class Method Details

.get_cards_hash(cards) ⇒ Object



33
34
35
36
37
# File 'lib/cribbage_game/game.rb', line 33

def self.get_cards_hash cards
  cards.each_with_object({}) do |card, card_map|
    card_map[card.id] = card
  end
end

.get_hand_hash(card_ids) ⇒ Object



39
40
41
# File 'lib/cribbage_game/game.rb', line 39

def self.get_hand_hash card_ids
  card_ids.to_h { |id| [id, true] }
end

Instance Method Details

#all_cards_discarded?Boolean



84
85
86
# File 'lib/cribbage_game/game.rb', line 84

def all_cards_discarded?
  @players.all? { |player| player.hand.keys.size == 4 }
end

#auto_score_hands_and_cribObject



176
177
178
179
# File 'lib/cribbage_game/game.rb', line 176

def auto_score_hands_and_crib
  @score_client.score_hands
  @score_client.score_crib
end

#can_either_player_play?Boolean



76
77
78
# File 'lib/cribbage_game/game.rb', line 76

def can_either_player_play?
  can_whose_turn_play? || can_not_whose_turn_play?
end

#can_not_whose_turn_play?Boolean



72
73
74
# File 'lib/cribbage_game/game.rb', line 72

def can_not_whose_turn_play?
  has_playable_card? not_whose_turn.hand
end

#can_play_card?(card_id) ⇒ Boolean



55
56
57
# File 'lib/cribbage_game/game.rb', line 55

def can_play_card? card_id
  pile_score + @deck[card_id].value <= 31
end

#can_whose_turn_play?Boolean



68
69
70
# File 'lib/cribbage_game/game.rb', line 68

def can_whose_turn_play?
  has_playable_card? @whose_turn.hand
end

#cut_for_dealObject

Raises:



104
105
106
107
108
109
110
# File 'lib/cribbage_game/game.rb', line 104

def cut_for_deal
  raise WrongStateError if !@fsm.cutting_for_deal?

  @dealer = @players.sample
  @whose_turn = opponent
  @fsm.deal
end

#dealObject

Raises:



112
113
114
115
116
117
118
119
120
# File 'lib/cribbage_game/game.rb', line 112

def deal
  raise WrongStateError if !@fsm.dealing?

  random_card_ids = @deck.keys.sample 12
  @dealer.hand = self.class.get_hand_hash random_card_ids.slice!(0, 6)
  opponent.hand = self.class.get_hand_hash random_card_ids.slice!(0, 6)

  @fsm.discard
end

#discard(player, card_id) ⇒ Object

Raises:



147
148
149
150
151
152
153
154
155
# File 'lib/cribbage_game/game.rb', line 147

def discard player, card_id
  raise WrongStateError if !@fsm.discarding?
  raise NotYourCardError if !player.hand[card_id]

  player.hand.delete(card_id)
  @crib << card_id

  @fsm.flip_top_card if all_cards_discarded?
end

#flip_top_card(top_card = nil) ⇒ Object

Raises:



137
138
139
140
141
142
143
144
145
# File 'lib/cribbage_game/game.rb', line 137

def flip_top_card top_card = nil
  raise WrongStateError if !@fsm.flipping_top_card?

  @cut_card = top_card || undealt_card_ids.sample
  @whose_turn = opponent
  @score_client.score_crib
  @score_client.score_hands
  @fsm.play
end

#has_playable_card?(hand) ⇒ Boolean



63
64
65
66
# File 'lib/cribbage_game/game.rb', line 63

def has_playable_card? hand
  card_ids = hand.keys.filter { |card_id| hand[card_id] } # false has been played
  card_ids.map { |card_id| can_play_card?(card_id) }.any?
end

#is_valid_play?(player, card_id) ⇒ Boolean

Raises:



88
89
90
91
92
93
94
# File 'lib/cribbage_game/game.rb', line 88

def is_valid_play? player, card_id
  raise WrongStateError if !@fsm.playing?
  raise NotYourTurnError if player != @whose_turn
  raise NotYourCardError if !player.hand[card_id]
  raise CardTooLargeError if !can_play_card? card_id
  true
end

#not_whose_turnObject



51
52
53
# File 'lib/cribbage_game/game.rb', line 51

def not_whose_turn
  @players.difference([@whose_turn]).first
end

#opponentObject



47
48
49
# File 'lib/cribbage_game/game.rb', line 47

def opponent
  @players.difference([@dealer]).first
end

#pile_scoreObject



80
81
82
# File 'lib/cribbage_game/game.rb', line 80

def pile_score
  @pile.map { |card_id| @deck[card_id].value }.sum
end

#play_card(player, card_id) ⇒ Object



122
123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/cribbage_game/game.rb', line 122

def play_card player, card_id
  is_valid_play?(player, card_id)

  player.hand[card_id] = false
  @pile << card_id
  is_last_card = !can_either_player_play?
  @score_client.score_play(@pile, is_last_card, player)
  @score_client.submit_play_score player
  return if we_have_a_winner?

  @pile = [] if is_last_card
  @whose_turn = not_whose_turn if can_not_whose_turn_play?
  @fsm.score if player_hands_empty?
end

#player_hands_empty?Boolean



59
60
61
# File 'lib/cribbage_game/game.rb', line 59

def player_hands_empty?
  @players.none? { |player| player.hand.values.any? }
end

#reset_cardsObject



96
97
98
99
100
101
102
# File 'lib/cribbage_game/game.rb', line 96

def reset_cards
  @round += 1
  @cut_card = nil
  @crib = []
  @pile = []
  @players.each { |player| player.hand = {} }
end

#submit_crib_scoresObject

Raises:



166
167
168
169
170
171
172
173
174
# File 'lib/cribbage_game/game.rb', line 166

def submit_crib_scores
  raise WrongStateError if !@fsm.scoring_dealer_crib?

  @score_client.submit_scores @dealer, :crib
  return if we_have_a_winner?
  reset_cards
  @dealer = opponent
  @fsm.deal
end

#submit_hand_scores(player) ⇒ Object

Raises:



157
158
159
160
161
162
163
164
# File 'lib/cribbage_game/game.rb', line 157

def submit_hand_scores player
  raise NotYourTurnError if player == @dealer && !@fsm.scoring_dealer_hand?
  raise NotYourTurnError if player == opponent && !@fsm.scoring_opponent_hand?

  @score_client.submit_scores player, :hand
  return if we_have_a_winner?
  @fsm.score
end

#undealt_card_idsObject



43
44
45
# File 'lib/cribbage_game/game.rb', line 43

def undealt_card_ids
  @deck.keys.difference(@dealer.hand.keys, opponent.hand.keys)
end

#we_have_a_winner?Boolean



181
182
183
184
185
186
187
188
189
190
# File 'lib/cribbage_game/game.rb', line 181

def we_have_a_winner?
  winner = @players.select { |player| player.total_score >= @points_to_win }
  return false if winner.empty?
  raise "You can only have one winner" if winner.size > 1

  @winner = winner.first
  @fsm.declare_winner
  @game_over_cb.call
  true
end