console-blackjack 1.0.0 → 1.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 +4 -4
- data/README.md +10 -14
- data/bj.txt +1 -1
- data/console-blackjack-1.0.0.gem +0 -0
- data/console-blackjack.gemspec +2 -2
- data/lib/blackjack.rb +26 -195
- data/lib/blackjack/card.rb +6 -0
- data/lib/blackjack/dealer_hand.rb +11 -9
- data/lib/blackjack/format.rb +8 -0
- data/lib/blackjack/menus.rb +73 -0
- data/lib/blackjack/player_hand.rb +57 -114
- data/lib/blackjack/player_hand_actions.rb +50 -0
- data/lib/blackjack/player_hand_draw.rb +50 -0
- data/lib/blackjack/shoe.rb +9 -0
- data/lib/blackjack/split_hand.rb +40 -0
- data/lib/blackjack/utils.rb +59 -0
- data/spec/lib/blackjack/format_spec.rb +10 -0
- data/spec/lib/blackjack/hand_spec.rb +2 -2
- data/spec/lib/blackjack/player_hand_spec.rb +29 -30
- data/spec/lib/blackjack_spec.rb +0 -7
- metadata +10 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6d8e2845da3cf406f528ed2658a6ca3746a734ba539c83cdc705b971d3100836
|
4
|
+
data.tar.gz: a3850be940cb68425bab3c72b449316675bfeadaf48393115662c326f906353b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 40a8d8db918d89a6e357c0966cce82e0bf9b9aa8c74c74ad6c90424a5b669717935340bc4274f64d3937f40468c419725895161fd2df7c7ca065bfc2400e768b
|
7
|
+
data.tar.gz: 1936e836e9f98afd78f76da330f1c14f45eb8350db5b178ce99804b20f941ebc1f79a082a9b68110ee91693bdfb63fb3b01cbcec0d500da50e2b0223b17b4966
|
data/README.md
CHANGED
@@ -1,28 +1,24 @@
|
|
1
|
-
# blackjack-ruby
|
1
|
+
# console-blackjack-ruby
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-

|
3
|
+

|
6
4
|
|
7
5
|
## Getting Started
|
8
6
|
|
9
|
-
Install
|
10
|
-
|
11
|
-
bundle install
|
12
|
-
|
13
|
-
Run tests:
|
7
|
+
Install:
|
14
8
|
|
15
|
-
|
9
|
+
gem install console-blackjack
|
16
10
|
|
17
11
|
Run:
|
18
12
|
|
19
|
-
|
13
|
+
console-blackjack
|
20
14
|
|
21
15
|
## Status
|
22
16
|
|
23
|
-
[](https://travis-ci.org/gdonald/blackjack-ruby)
|
24
|
-
[](https://coveralls.io/github/gdonald/blackjack-ruby?branch=master)
|
17
|
+
[](https://travis-ci.org/gdonald/console-blackjack-ruby)
|
18
|
+
[](https://coveralls.io/github/gdonald/console-blackjack-ruby?branch=master)
|
19
|
+
[](https://codeclimate.com/github/gdonald/console-blackjack-ruby/maintainability)
|
20
|
+
[](https://rubygems.org/gems/console-blackjack)
|
25
21
|
|
26
22
|
## License
|
27
23
|
|
28
|
-
blackjack-ruby
|
24
|
+
[](https://github.com/gdonald/console-blackjack-ruby/blob/master/LICENSE)
|
data/bj.txt
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
1|10500|500
|
Binary file
|
data/console-blackjack.gemspec
CHANGED
@@ -4,8 +4,8 @@ require 'rake'
|
|
4
4
|
|
5
5
|
Gem::Specification.new do |spec|
|
6
6
|
spec.name = 'console-blackjack'
|
7
|
-
spec.version = '1.0.
|
8
|
-
spec.date = '2019-11-
|
7
|
+
spec.version = '1.0.1'
|
8
|
+
spec.date = '2019-11-10'
|
9
9
|
spec.summary = 'Console Blackjack'
|
10
10
|
spec.description = 'Blackjack for your console, full version.'
|
11
11
|
spec.author = 'Greg Donald'
|
data/lib/blackjack.rb
CHANGED
@@ -1,14 +1,22 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative 'blackjack/shoe'
|
4
3
|
require_relative 'blackjack/dealer_hand'
|
4
|
+
require_relative 'blackjack/format'
|
5
|
+
require_relative 'blackjack/menus'
|
5
6
|
require_relative 'blackjack/player_hand'
|
7
|
+
require_relative 'blackjack/shoe'
|
8
|
+
require_relative 'blackjack/split_hand'
|
9
|
+
require_relative 'blackjack/utils'
|
6
10
|
|
7
11
|
SAVE_FILE = 'bj.txt'
|
8
12
|
MIN_BET = 500
|
9
13
|
MAX_BET = 10_000_000
|
10
14
|
|
11
15
|
class Blackjack
|
16
|
+
include Menus
|
17
|
+
include SplitHand
|
18
|
+
include Utils
|
19
|
+
|
12
20
|
attr_accessor :shoe, :money, :player_hands, :dealer_hand, :num_decks, :current_bet, :current_hand
|
13
21
|
|
14
22
|
def initialize
|
@@ -72,8 +80,7 @@ class Blackjack
|
|
72
80
|
if current_player_hand.done?
|
73
81
|
current_player_hand.process
|
74
82
|
else
|
75
|
-
|
76
|
-
current_player_hand.action?
|
83
|
+
draw_hands_current_hand_action
|
77
84
|
end
|
78
85
|
end
|
79
86
|
|
@@ -84,16 +91,6 @@ class Blackjack
|
|
84
91
|
false
|
85
92
|
end
|
86
93
|
|
87
|
-
def normalize_current_bet
|
88
|
-
if current_bet < MIN_BET
|
89
|
-
self.current_bet = MIN_BET
|
90
|
-
elsif current_bet > MAX_BET
|
91
|
-
self.current_bet = MAX_BET
|
92
|
-
end
|
93
|
-
|
94
|
-
self.current_bet = money if current_bet > money
|
95
|
-
end
|
96
|
-
|
97
94
|
def pay_hands
|
98
95
|
dealer_hand_value = dealer_hand.value(SOFT)
|
99
96
|
dealer_busted = dealer_hand.busted?
|
@@ -116,76 +113,41 @@ class Blackjack
|
|
116
113
|
clear
|
117
114
|
out = String.new
|
118
115
|
out << "\n Dealer:\n#{dealer_hand.draw}\n"
|
119
|
-
|
120
116
|
out << "\n Player $"
|
121
|
-
out <<
|
117
|
+
out << Format.money(money / 100.0)
|
122
118
|
out << ":\n"
|
119
|
+
out << draw_player_hands
|
120
|
+
puts out
|
121
|
+
end
|
123
122
|
|
123
|
+
def draw_player_hands
|
124
|
+
out = String.new('')
|
124
125
|
player_hands.each_with_index do |player_hand, index|
|
125
126
|
out << player_hand.draw(index)
|
126
127
|
end
|
127
|
-
|
128
|
-
puts out
|
128
|
+
out
|
129
129
|
end
|
130
130
|
|
131
131
|
def new_bet
|
132
132
|
clear
|
133
133
|
draw_hands
|
134
134
|
|
135
|
-
puts " Current Bet: $#{
|
135
|
+
puts " Current Bet: $#{Format.money(current_bet / 100)}\n"
|
136
136
|
print ' Enter New Bet: $'
|
137
137
|
|
138
|
-
|
139
|
-
self.current_bet = tmp * 100
|
138
|
+
self.current_bet = STDIN.gets.to_i * 100
|
140
139
|
|
141
140
|
normalize_current_bet
|
142
141
|
deal_new_hand
|
143
142
|
end
|
144
143
|
|
145
|
-
def draw_game_options
|
146
|
-
puts ' (N) Number of Decks (T) Deck Type (B) Back'
|
147
|
-
|
148
|
-
loop do
|
149
|
-
br = false
|
150
|
-
case Blackjack.getc
|
151
|
-
when 'n'
|
152
|
-
br = true
|
153
|
-
clear
|
154
|
-
draw_hands
|
155
|
-
new_num_decks
|
156
|
-
when 't'
|
157
|
-
br = true
|
158
|
-
clear
|
159
|
-
draw_hands
|
160
|
-
new_deck_type
|
161
|
-
clear
|
162
|
-
draw_hands
|
163
|
-
draw_bet_options
|
164
|
-
when 'b'
|
165
|
-
br = true
|
166
|
-
clear
|
167
|
-
draw_hands
|
168
|
-
draw_bet_options
|
169
|
-
else
|
170
|
-
clear
|
171
|
-
draw_hands
|
172
|
-
draw_game_options
|
173
|
-
end
|
174
|
-
|
175
|
-
break if br
|
176
|
-
end
|
177
|
-
end
|
178
|
-
|
179
144
|
def new_num_decks
|
180
145
|
puts " Number Of Decks: #{num_decks}"
|
181
146
|
print ' New Number Of Decks (1-8): '
|
182
147
|
self.num_decks = STDIN.gets.to_i
|
183
148
|
|
184
149
|
normalize_num_decks
|
185
|
-
|
186
|
-
clear
|
187
|
-
draw_hands
|
188
|
-
draw_game_options
|
150
|
+
clear_draw_hands_game_options
|
189
151
|
end
|
190
152
|
|
191
153
|
def normalize_num_decks
|
@@ -193,62 +155,6 @@ class Blackjack
|
|
193
155
|
self.num_decks = 8 if num_decks > 8
|
194
156
|
end
|
195
157
|
|
196
|
-
def new_deck_type
|
197
|
-
puts ' (1) Regular (2) Aces (3) Jacks (4) Aces & Jacks (5) Sevens (6) Eights'
|
198
|
-
|
199
|
-
loop do
|
200
|
-
br = false
|
201
|
-
case Blackjack.getc
|
202
|
-
when '1'
|
203
|
-
br = true
|
204
|
-
shoe.new_regular
|
205
|
-
when '2'
|
206
|
-
br = true
|
207
|
-
shoe.new_aces
|
208
|
-
when '3'
|
209
|
-
br = true
|
210
|
-
shoe.new_jacks
|
211
|
-
when '4'
|
212
|
-
br = true
|
213
|
-
shoe.new_aces_jacks
|
214
|
-
when '5'
|
215
|
-
br = true
|
216
|
-
shoe.new_sevens
|
217
|
-
when '6'
|
218
|
-
br = true
|
219
|
-
shoe.new_eights
|
220
|
-
else
|
221
|
-
clear
|
222
|
-
draw_hands
|
223
|
-
new_deck_type
|
224
|
-
end
|
225
|
-
|
226
|
-
break if br
|
227
|
-
end
|
228
|
-
end
|
229
|
-
|
230
|
-
def ask_insurance
|
231
|
-
puts ' Insurance? (Y) Yes (N) No'
|
232
|
-
|
233
|
-
loop do
|
234
|
-
br = false
|
235
|
-
case Blackjack.getc
|
236
|
-
when 'y'
|
237
|
-
br = true
|
238
|
-
insure_hand
|
239
|
-
when 'n'
|
240
|
-
br = true
|
241
|
-
no_insurance
|
242
|
-
else
|
243
|
-
clear
|
244
|
-
draw_hands
|
245
|
-
ask_insurance
|
246
|
-
end
|
247
|
-
|
248
|
-
break if br
|
249
|
-
end
|
250
|
-
end
|
251
|
-
|
252
158
|
def insure_hand
|
253
159
|
player_hand = current_player_hand
|
254
160
|
player_hand.bet /= 2
|
@@ -281,89 +187,18 @@ class Blackjack
|
|
281
187
|
end
|
282
188
|
end
|
283
189
|
|
284
|
-
def play_dealer_hand
|
285
|
-
dealer_hand.play
|
286
|
-
draw_hands
|
287
|
-
draw_bet_options
|
288
|
-
end
|
289
|
-
|
290
|
-
def split_current_hand
|
291
|
-
if current_player_hand.can_split?
|
292
|
-
player_hands << PlayerHand.new(self, current_bet)
|
293
|
-
|
294
|
-
x = player_hands.size - 1
|
295
|
-
while x > current_hand
|
296
|
-
player_hands[x] = player_hands[x - 1].clone
|
297
|
-
x -= 1
|
298
|
-
end
|
299
|
-
|
300
|
-
this_hand = player_hands[current_hand]
|
301
|
-
split_hand = player_hands[current_hand + 1]
|
302
|
-
|
303
|
-
split_hand.cards = []
|
304
|
-
split_hand.cards << this_hand.cards.last
|
305
|
-
this_hand.cards.pop
|
306
|
-
|
307
|
-
this_hand.cards << shoe.next_card
|
308
|
-
if this_hand.done?
|
309
|
-
this_hand.process
|
310
|
-
else
|
311
|
-
draw_hands
|
312
|
-
current_player_hand.action?
|
313
|
-
end
|
314
|
-
else
|
315
|
-
draw_hands
|
316
|
-
current_player_hand.action?
|
317
|
-
end
|
318
|
-
end
|
319
|
-
|
320
|
-
def draw_bet_options
|
321
|
-
puts ' (D) Deal Hand (B) Change Bet (O) Options (Q) Quit'
|
322
|
-
|
323
|
-
loop do
|
324
|
-
br = false
|
325
|
-
case Blackjack.getc
|
326
|
-
when 'd'
|
327
|
-
br = true
|
328
|
-
deal_new_hand
|
329
|
-
when 'b'
|
330
|
-
br = true
|
331
|
-
new_bet
|
332
|
-
when 'o'
|
333
|
-
br = true
|
334
|
-
clear
|
335
|
-
draw_hands
|
336
|
-
draw_game_options
|
337
|
-
when 'q'
|
338
|
-
clear
|
339
|
-
exit
|
340
|
-
else
|
341
|
-
clear
|
342
|
-
draw_hands
|
343
|
-
draw_bet_options
|
344
|
-
end
|
345
|
-
|
346
|
-
break if br
|
347
|
-
end
|
348
|
-
end
|
349
|
-
|
350
190
|
def all_bets
|
351
191
|
player_hands.inject(0) { |sum, player_hand| sum + player_hand.bet }
|
352
192
|
end
|
353
193
|
|
354
|
-
def
|
355
|
-
|
356
|
-
|
194
|
+
def normalize_current_bet
|
195
|
+
if current_bet < MIN_BET
|
196
|
+
self.current_bet = MIN_BET
|
197
|
+
elsif current_bet > MAX_BET
|
198
|
+
self.current_bet = MAX_BET
|
357
199
|
end
|
358
|
-
end
|
359
|
-
|
360
|
-
def load_game
|
361
|
-
return unless File.readable?(SAVE_FILE)
|
362
200
|
|
363
|
-
|
364
|
-
self.num_decks = a[0].to_i
|
365
|
-
self.money = a[1].to_i
|
366
|
-
self.current_bet = a[2].to_i
|
201
|
+
self.current_bet = money if current_bet > money
|
367
202
|
end
|
368
203
|
|
369
204
|
def self.getc
|
@@ -375,8 +210,4 @@ class Blackjack
|
|
375
210
|
end
|
376
211
|
c.chr
|
377
212
|
end
|
378
|
-
|
379
|
-
def self.format_money(value)
|
380
|
-
format('%.2f', value)
|
381
|
-
end
|
382
213
|
end
|
data/lib/blackjack/card.rb
CHANGED
@@ -20,6 +20,12 @@ class Card
|
|
20
20
|
value > 8
|
21
21
|
end
|
22
22
|
|
23
|
+
def self.value(card, count_method, total)
|
24
|
+
value = card.value + 1
|
25
|
+
v = value > 9 ? 10 : value
|
26
|
+
count_method == SOFT && v == 1 && total < 11 ? 11 : v
|
27
|
+
end
|
28
|
+
|
23
29
|
def self.faces
|
24
30
|
[%w[🂡 🂱 🃁 🃑], %w[🂢 🂲 🃂 🃒], %w[🂣 🂳 🃃 🃓], %w[🂤 🂴 🃄 🃔],
|
25
31
|
%w[🂥 🂵 🃅 🃕], %w[🂦 🂶 🃆 🃖], %w[🂧 🂷 🃇 🃗], %w[🂨 🂸 🃈 🃘],
|
@@ -11,15 +11,7 @@ class DealerHand < Hand
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def value(count_method)
|
14
|
-
total =
|
15
|
-
cards.each_with_index do |card, index|
|
16
|
-
next if index == 1 && hide_down_card
|
17
|
-
|
18
|
-
value = card.value + 1
|
19
|
-
v = value > 9 ? 10 : value
|
20
|
-
v = 11 if count_method == SOFT && v == 1 && total < 11
|
21
|
-
total += v
|
22
|
-
end
|
14
|
+
total = total_card_value(count_method)
|
23
15
|
|
24
16
|
if count_method == SOFT && total > 21
|
25
17
|
value(HARD)
|
@@ -28,6 +20,16 @@ class DealerHand < Hand
|
|
28
20
|
end
|
29
21
|
end
|
30
22
|
|
23
|
+
def total_card_value(count_method)
|
24
|
+
total = 0
|
25
|
+
cards.each_with_index do |card, index|
|
26
|
+
next if index == 1 && hide_down_card
|
27
|
+
|
28
|
+
total += Card.value(card, count_method, total)
|
29
|
+
end
|
30
|
+
total
|
31
|
+
end
|
32
|
+
|
31
33
|
def upcard_is_ace?
|
32
34
|
cards.first.ace?
|
33
35
|
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Menus
|
4
|
+
def draw_game_options
|
5
|
+
puts ' (N) Number of Decks (T) Deck Type (B) Back'
|
6
|
+
loop do
|
7
|
+
c = Blackjack.getc
|
8
|
+
case c
|
9
|
+
when 'n'
|
10
|
+
clear_draw_hands_new_num_decks
|
11
|
+
when 't'
|
12
|
+
clear_draw_hands_new_deck_type
|
13
|
+
clear_draw_hands_bet_options
|
14
|
+
when 'b'
|
15
|
+
clear_draw_hands_bet_options
|
16
|
+
else
|
17
|
+
clear_draw_hands_game_options
|
18
|
+
end
|
19
|
+
break if %w[n t b].include?(c)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def new_deck_type
|
24
|
+
puts ' (1) Regular (2) Aces (3) Jacks (4) Aces & Jacks (5) Sevens (6) Eights'
|
25
|
+
loop do
|
26
|
+
c = Blackjack.getc.to_i
|
27
|
+
case c
|
28
|
+
when (1..6)
|
29
|
+
shoe.send("new_#{SHOES[c]}")
|
30
|
+
else
|
31
|
+
clear_draw_hands_new_deck_type
|
32
|
+
end
|
33
|
+
break if (1..6).include?(c)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def ask_insurance
|
38
|
+
puts ' Insurance? (Y) Yes (N) No'
|
39
|
+
loop do
|
40
|
+
c = Blackjack.getc
|
41
|
+
case c
|
42
|
+
when 'y'
|
43
|
+
insure_hand
|
44
|
+
when 'n'
|
45
|
+
no_insurance
|
46
|
+
else
|
47
|
+
clear_draw_hands_ask_insurance
|
48
|
+
end
|
49
|
+
break if %w[y n].include?(c)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def draw_bet_options
|
54
|
+
puts ' (D) Deal Hand (B) Change Bet (O) Options (Q) Quit'
|
55
|
+
loop do
|
56
|
+
c = Blackjack.getc
|
57
|
+
case c
|
58
|
+
when 'd'
|
59
|
+
deal_new_hand
|
60
|
+
when 'b'
|
61
|
+
new_bet
|
62
|
+
when 'o'
|
63
|
+
clear_draw_hands_game_options
|
64
|
+
when 'q'
|
65
|
+
clear
|
66
|
+
exit
|
67
|
+
else
|
68
|
+
clear_draw_hands_bet_options
|
69
|
+
end
|
70
|
+
break if %w[d b o].include?(c)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -1,8 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative 'hand'
|
4
|
+
require_relative 'player_hand_actions'
|
5
|
+
require_relative 'player_hand_draw'
|
4
6
|
|
5
7
|
class PlayerHand < Hand
|
8
|
+
include PlayerHandDraw
|
9
|
+
include PlayerHandActions
|
10
|
+
|
6
11
|
MAX_PLAYER_HANDS = 7
|
7
12
|
|
8
13
|
attr_accessor :blackjack, :bet, :status, :payed, :cards, :stood
|
@@ -21,94 +26,60 @@ class PlayerHand < Hand
|
|
21
26
|
self.payed = true
|
22
27
|
player_hand_value = value(SOFT)
|
23
28
|
|
24
|
-
if dealer_busted
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
elsif player_hand_value < dealer_hand_value
|
29
|
-
blackjack.money -= bet
|
30
|
-
self.status = LOST
|
29
|
+
if player_hand_won?(dealer_busted, dealer_hand_value, player_hand_value)
|
30
|
+
pay_won_hand
|
31
|
+
elsif player_hand_lost?(dealer_hand_value, player_hand_value)
|
32
|
+
collect_lost_hand
|
31
33
|
else
|
32
34
|
self.status = PUSH
|
33
35
|
end
|
34
36
|
end
|
35
37
|
|
36
|
-
def
|
37
|
-
|
38
|
-
cards.each do |card|
|
39
|
-
value = card.value + 1
|
40
|
-
v = value > 9 ? 10 : value
|
41
|
-
v = 11 if count_method == SOFT && v == 1 && total < 11
|
42
|
-
total += v
|
43
|
-
end
|
44
|
-
|
45
|
-
return value(HARD) if count_method == SOFT && total > 21
|
46
|
-
|
47
|
-
total
|
48
|
-
end
|
49
|
-
|
50
|
-
def done?
|
51
|
-
if played || stood || blackjack? || busted? ||
|
52
|
-
value(SOFT) == 21 ||
|
53
|
-
value(HARD) == 21
|
54
|
-
self.played = true
|
55
|
-
|
56
|
-
if !payed && busted?
|
57
|
-
self.payed = true
|
58
|
-
self.status = LOST
|
59
|
-
blackjack.money -= bet
|
60
|
-
end
|
61
|
-
return true
|
62
|
-
end
|
63
|
-
|
64
|
-
false
|
65
|
-
end
|
66
|
-
|
67
|
-
def can_split?
|
68
|
-
return false if stood || blackjack.player_hands.size >= MAX_PLAYER_HANDS
|
69
|
-
|
70
|
-
return false if blackjack.money < blackjack.all_bets + bet
|
71
|
-
|
72
|
-
cards.size == 2 && cards.first.value == cards.last.value
|
38
|
+
def player_hand_lost?(dealer_hand_value, player_hand_value)
|
39
|
+
player_hand_value < dealer_hand_value
|
73
40
|
end
|
74
41
|
|
75
|
-
def
|
76
|
-
|
77
|
-
|
78
|
-
!(stood || cards.size != 2 || blackjack?)
|
42
|
+
def player_hand_won?(dealer_busted, dealer_hand_value, player_hand_value)
|
43
|
+
dealer_busted || player_hand_value > dealer_hand_value
|
79
44
|
end
|
80
45
|
|
81
|
-
def
|
82
|
-
|
46
|
+
def collect_lost_hand
|
47
|
+
blackjack.money -= bet
|
48
|
+
self.status = LOST
|
83
49
|
end
|
84
50
|
|
85
|
-
def
|
86
|
-
|
51
|
+
def pay_won_hand
|
52
|
+
self.bet *= 1.5 if blackjack?
|
53
|
+
blackjack.money += bet
|
54
|
+
self.status = WON
|
87
55
|
end
|
88
56
|
|
89
|
-
def
|
90
|
-
|
57
|
+
def value(count_method)
|
58
|
+
total = cards.inject(0) { |sum, card| sum + Card.value(card, count_method, sum) }
|
91
59
|
|
92
|
-
if
|
93
|
-
|
60
|
+
if count_method == SOFT && total > 21
|
61
|
+
value(HARD)
|
94
62
|
else
|
95
|
-
|
96
|
-
blackjack.current_player_hand.action?
|
63
|
+
total
|
97
64
|
end
|
98
65
|
end
|
99
66
|
|
100
|
-
def
|
101
|
-
|
67
|
+
def done?
|
68
|
+
return false unless no_more_actions?
|
102
69
|
|
103
70
|
self.played = true
|
104
|
-
|
105
|
-
|
71
|
+
collect_busted_hand if !payed && busted?
|
72
|
+
true
|
106
73
|
end
|
107
74
|
|
108
|
-
def
|
109
|
-
self.
|
110
|
-
self.
|
111
|
-
|
75
|
+
def collect_busted_hand
|
76
|
+
self.payed = true
|
77
|
+
self.status = LOST
|
78
|
+
blackjack.money -= bet
|
79
|
+
end
|
80
|
+
|
81
|
+
def no_more_actions?
|
82
|
+
played || stood || blackjack? || busted? || value(SOFT) == 21 || value(HARD) == 21
|
112
83
|
end
|
113
84
|
|
114
85
|
def process
|
@@ -119,66 +90,38 @@ class PlayerHand < Hand
|
|
119
90
|
end
|
120
91
|
end
|
121
92
|
|
122
|
-
def draw(index)
|
123
|
-
out = String.new(' ')
|
124
|
-
cards.each do |card|
|
125
|
-
out << "#{card} "
|
126
|
-
end
|
127
|
-
|
128
|
-
out << ' ⇒ ' << value(SOFT).to_s << ' '
|
129
|
-
|
130
|
-
if status == LOST
|
131
|
-
out << '-'
|
132
|
-
elsif status == WON
|
133
|
-
out << '+'
|
134
|
-
end
|
135
|
-
|
136
|
-
out << '$' << Blackjack.format_money(bet / 100.0)
|
137
|
-
out << ' ⇐' if !played && index == blackjack.current_hand
|
138
|
-
out << ' '
|
139
|
-
|
140
|
-
if status == LOST
|
141
|
-
out << (busted? ? 'Busted!' : 'Lose!')
|
142
|
-
elsif status == WON
|
143
|
-
out << (blackjack? ? 'Blackjack!' : 'Won!')
|
144
|
-
elsif status == PUSH
|
145
|
-
out << 'Push'
|
146
|
-
end
|
147
|
-
|
148
|
-
out << "\n\n"
|
149
|
-
out
|
150
|
-
end
|
151
|
-
|
152
93
|
def action?
|
153
|
-
|
154
|
-
out << '(H) Hit ' if can_hit?
|
155
|
-
out << '(S) Stand ' if can_stand?
|
156
|
-
out << '(P) Split ' if can_split?
|
157
|
-
out << '(D) Double ' if can_dbl?
|
158
|
-
puts out
|
159
|
-
|
94
|
+
draw_actions
|
160
95
|
loop do
|
161
|
-
|
162
|
-
case
|
96
|
+
c = Blackjack.getc
|
97
|
+
case c
|
163
98
|
when 'h'
|
164
|
-
br = true
|
165
99
|
hit
|
166
100
|
when 's'
|
167
|
-
br = true
|
168
101
|
stand
|
169
102
|
when 'p'
|
170
|
-
br = true
|
171
103
|
blackjack.split_current_hand
|
172
104
|
when 'd'
|
173
|
-
br = true
|
174
105
|
dbl
|
175
106
|
else
|
176
|
-
|
177
|
-
blackjack.draw_hands
|
178
|
-
action?
|
107
|
+
clear_draw_hands_action
|
179
108
|
end
|
180
|
-
|
181
|
-
break if br
|
109
|
+
break if %w[h s p d].include?(c)
|
182
110
|
end
|
183
111
|
end
|
112
|
+
|
113
|
+
def clear_draw_hands_action
|
114
|
+
blackjack.clear
|
115
|
+
blackjack.draw_hands
|
116
|
+
action?
|
117
|
+
end
|
118
|
+
|
119
|
+
def draw_actions
|
120
|
+
out = String.new(' ')
|
121
|
+
out << '(H) Hit ' if can_hit?
|
122
|
+
out << '(S) Stand ' if can_stand?
|
123
|
+
out << '(P) Split ' if can_split?
|
124
|
+
out << '(D) Double ' if can_dbl?
|
125
|
+
puts out
|
126
|
+
end
|
184
127
|
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PlayerHandActions
|
4
|
+
def can_split?
|
5
|
+
return false if stood || blackjack.player_hands.size >= PlayerHand::MAX_PLAYER_HANDS
|
6
|
+
|
7
|
+
return false if blackjack.money < blackjack.all_bets + bet
|
8
|
+
|
9
|
+
cards.size == 2 && cards.first.value == cards.last.value
|
10
|
+
end
|
11
|
+
|
12
|
+
def can_dbl?
|
13
|
+
return false if blackjack.money < blackjack.all_bets + bet
|
14
|
+
|
15
|
+
!(stood || cards.size != 2 || blackjack?)
|
16
|
+
end
|
17
|
+
|
18
|
+
def can_stand?
|
19
|
+
!(stood || busted? || blackjack?)
|
20
|
+
end
|
21
|
+
|
22
|
+
def can_hit?
|
23
|
+
!(played || stood || value(HARD) == 21 || blackjack? || busted?)
|
24
|
+
end
|
25
|
+
|
26
|
+
def hit
|
27
|
+
deal_card
|
28
|
+
|
29
|
+
if done?
|
30
|
+
process
|
31
|
+
else
|
32
|
+
blackjack.draw_hands
|
33
|
+
blackjack.current_player_hand.action?
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def dbl
|
38
|
+
deal_card
|
39
|
+
|
40
|
+
self.played = true
|
41
|
+
self.bet *= 2
|
42
|
+
process if done?
|
43
|
+
end
|
44
|
+
|
45
|
+
def stand
|
46
|
+
self.stood = true
|
47
|
+
self.played = true
|
48
|
+
process
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PlayerHandDraw
|
4
|
+
def draw(index)
|
5
|
+
out = String.new(' ')
|
6
|
+
out << draw_cards
|
7
|
+
out << draw_money(index)
|
8
|
+
out << draw_status
|
9
|
+
out << "\n\n"
|
10
|
+
out
|
11
|
+
end
|
12
|
+
|
13
|
+
def draw_status
|
14
|
+
case status
|
15
|
+
when LOST
|
16
|
+
draw_lost_str
|
17
|
+
when WON
|
18
|
+
draw_won_str
|
19
|
+
when PUSH
|
20
|
+
'Push'
|
21
|
+
else
|
22
|
+
''
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def draw_lost_str
|
27
|
+
busted? ? 'Busted!' : 'Lose!'
|
28
|
+
end
|
29
|
+
|
30
|
+
def draw_won_str
|
31
|
+
blackjack? ? 'Blackjack!' : 'Won!'
|
32
|
+
end
|
33
|
+
|
34
|
+
def draw_money(index)
|
35
|
+
out = String.new('')
|
36
|
+
out << '-' if status == LOST
|
37
|
+
out << '+' if status == WON
|
38
|
+
out << '$' << Format.money(bet / 100.0)
|
39
|
+
out << ' ⇐' if !played && index == blackjack.current_hand
|
40
|
+
out << ' '
|
41
|
+
out
|
42
|
+
end
|
43
|
+
|
44
|
+
def draw_cards
|
45
|
+
out = String.new('')
|
46
|
+
out << cards.map { |card| "#{card} " }.join
|
47
|
+
out << ' ⇒ ' << value(SOFT).to_s << ' '
|
48
|
+
out
|
49
|
+
end
|
50
|
+
end
|
data/lib/blackjack/shoe.rb
CHANGED
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SplitHand
|
4
|
+
def split_current_hand
|
5
|
+
if current_player_hand.can_split?
|
6
|
+
expand_split_hands
|
7
|
+
this_hand = split_hand
|
8
|
+
|
9
|
+
if this_hand.done?
|
10
|
+
this_hand.process
|
11
|
+
else
|
12
|
+
draw_hands_current_hand_action
|
13
|
+
end
|
14
|
+
else
|
15
|
+
draw_hands_current_hand_action
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def split_hand
|
20
|
+
this_hand = player_hands[current_hand]
|
21
|
+
split_hand = player_hands[current_hand + 1]
|
22
|
+
|
23
|
+
split_hand.cards = []
|
24
|
+
split_hand.cards << this_hand.cards.last
|
25
|
+
this_hand.cards.pop
|
26
|
+
|
27
|
+
this_hand.cards << shoe.next_card
|
28
|
+
this_hand
|
29
|
+
end
|
30
|
+
|
31
|
+
def expand_split_hands
|
32
|
+
player_hands << PlayerHand.new(self, current_bet)
|
33
|
+
|
34
|
+
x = player_hands.size - 1
|
35
|
+
while x > current_hand
|
36
|
+
player_hands[x] = player_hands[x - 1].clone
|
37
|
+
x -= 1
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Utils
|
4
|
+
def save_game
|
5
|
+
File.open(SAVE_FILE, 'w') do |file|
|
6
|
+
file.puts "#{num_decks}|#{money}|#{current_bet}"
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def load_game
|
11
|
+
return unless File.readable?(SAVE_FILE)
|
12
|
+
|
13
|
+
a = File.read(SAVE_FILE).split('|')
|
14
|
+
self.num_decks = a[0].to_i
|
15
|
+
self.money = a[1].to_i
|
16
|
+
self.current_bet = a[2].to_i
|
17
|
+
end
|
18
|
+
|
19
|
+
def clear_draw_hands
|
20
|
+
clear
|
21
|
+
draw_hands
|
22
|
+
end
|
23
|
+
|
24
|
+
def clear_draw_hands_new_num_decks
|
25
|
+
clear_draw_hands
|
26
|
+
new_num_decks
|
27
|
+
end
|
28
|
+
|
29
|
+
def clear_draw_hands_new_deck_type
|
30
|
+
clear_draw_hands
|
31
|
+
new_deck_type
|
32
|
+
end
|
33
|
+
|
34
|
+
def clear_draw_hands_ask_insurance
|
35
|
+
clear_draw_hands
|
36
|
+
ask_insurance
|
37
|
+
end
|
38
|
+
|
39
|
+
def clear_draw_hands_bet_options
|
40
|
+
clear_draw_hands
|
41
|
+
draw_bet_options
|
42
|
+
end
|
43
|
+
|
44
|
+
def clear_draw_hands_game_options
|
45
|
+
clear_draw_hands
|
46
|
+
draw_game_options
|
47
|
+
end
|
48
|
+
|
49
|
+
def draw_hands_current_hand_action
|
50
|
+
draw_hands
|
51
|
+
current_player_hand.action?
|
52
|
+
end
|
53
|
+
|
54
|
+
def play_dealer_hand
|
55
|
+
dealer_hand.play
|
56
|
+
draw_hands
|
57
|
+
draw_bet_options
|
58
|
+
end
|
59
|
+
end
|
@@ -1,4 +1,3 @@
|
|
1
|
-
# coding: utf-8
|
2
1
|
# frozen_string_literal: true
|
3
2
|
|
4
3
|
RSpec.describe PlayerHand do
|
@@ -35,6 +34,35 @@ RSpec.describe PlayerHand do
|
|
35
34
|
end
|
36
35
|
end
|
37
36
|
|
37
|
+
describe '#draw' do
|
38
|
+
it 'draws the hand' do
|
39
|
+
player_hand.cards << ace << ten
|
40
|
+
expected = " 🂡 🂪 ⇒ 21 $5.00 \n\n"
|
41
|
+
expect(player_hand.draw(1)).to eq(expected)
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'draws a lost hand' do
|
45
|
+
player_hand.cards << ace << ace
|
46
|
+
player_hand.status = LOST
|
47
|
+
expected = " 🂡 🂡 ⇒ 12 -$5.00 Lose!\n\n"
|
48
|
+
expect(player_hand.draw(1)).to eq(expected)
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'draws a won hand' do
|
52
|
+
player_hand.cards << ace << ace
|
53
|
+
player_hand.status = WON
|
54
|
+
expected = " 🂡 🂡 ⇒ 12 +$5.00 Won!\n\n"
|
55
|
+
expect(player_hand.draw(1)).to eq(expected)
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'draws a push hand' do
|
59
|
+
player_hand.cards << ace << ace
|
60
|
+
player_hand.status = PUSH
|
61
|
+
expected = " 🂡 🂡 ⇒ 12 $5.00 Push\n\n"
|
62
|
+
expect(player_hand.draw(1)).to eq(expected)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
38
66
|
describe '#busted?' do
|
39
67
|
it 'returns false' do
|
40
68
|
expect(player_hand).to_not be_busted
|
@@ -273,35 +301,6 @@ RSpec.describe PlayerHand do
|
|
273
301
|
end
|
274
302
|
end
|
275
303
|
|
276
|
-
describe '#draw' do
|
277
|
-
it 'draws the hand' do
|
278
|
-
player_hand.cards << ace << ten
|
279
|
-
expected = " 🂡 🂪 ⇒ 21 $5.00 \n\n"
|
280
|
-
expect(player_hand.draw(1)).to eq(expected)
|
281
|
-
end
|
282
|
-
|
283
|
-
it 'draws a lost hand' do
|
284
|
-
player_hand.cards << ace << ace
|
285
|
-
player_hand.status = LOST
|
286
|
-
expected = " 🂡 🂡 ⇒ 12 -$5.00 Lose!\n\n"
|
287
|
-
expect(player_hand.draw(1)).to eq(expected)
|
288
|
-
end
|
289
|
-
|
290
|
-
it 'draws a won hand' do
|
291
|
-
player_hand.cards << ace << ace
|
292
|
-
player_hand.status = WON
|
293
|
-
expected = " 🂡 🂡 ⇒ 12 +$5.00 Won!\n\n"
|
294
|
-
expect(player_hand.draw(1)).to eq(expected)
|
295
|
-
end
|
296
|
-
|
297
|
-
it 'draws a push hand' do
|
298
|
-
player_hand.cards << ace << ace
|
299
|
-
player_hand.status = PUSH
|
300
|
-
expected = " 🂡 🂡 ⇒ 12 $5.00 Push\n\n"
|
301
|
-
expect(player_hand.draw(1)).to eq(expected)
|
302
|
-
end
|
303
|
-
end
|
304
|
-
|
305
304
|
describe '#process' do
|
306
305
|
context 'with more hands to play' do
|
307
306
|
before do
|
data/spec/lib/blackjack_spec.rb
CHANGED
@@ -36,13 +36,6 @@ RSpec.describe Blackjack do
|
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
39
|
-
describe '#format_money' do
|
40
|
-
it 'returns a formatted string' do
|
41
|
-
str = described_class.format_money(1)
|
42
|
-
expect(str).to eq('1.00')
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
39
|
describe '.all_bets?' do
|
47
40
|
it 'returns 10' do
|
48
41
|
blackjack.player_hands << player_hand << player_hand
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: console-blackjack
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Greg Donald
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-11-
|
11
|
+
date: 2019-11-10 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Blackjack for your console, full version.
|
14
14
|
email: gdonald@gmail.com
|
@@ -25,13 +25,20 @@ files:
|
|
25
25
|
- bin/console-blackjack
|
26
26
|
- bj.png
|
27
27
|
- bj.txt
|
28
|
+
- console-blackjack-1.0.0.gem
|
28
29
|
- console-blackjack.gemspec
|
29
30
|
- lib/blackjack.rb
|
30
31
|
- lib/blackjack/card.rb
|
31
32
|
- lib/blackjack/dealer_hand.rb
|
33
|
+
- lib/blackjack/format.rb
|
32
34
|
- lib/blackjack/hand.rb
|
35
|
+
- lib/blackjack/menus.rb
|
33
36
|
- lib/blackjack/player_hand.rb
|
37
|
+
- lib/blackjack/player_hand_actions.rb
|
38
|
+
- lib/blackjack/player_hand_draw.rb
|
34
39
|
- lib/blackjack/shoe.rb
|
40
|
+
- lib/blackjack/split_hand.rb
|
41
|
+
- lib/blackjack/utils.rb
|
35
42
|
- spec/factories/blackjack_factory.rb
|
36
43
|
- spec/factories/card_factory.rb
|
37
44
|
- spec/factories/dealer_hand_factory.rb
|
@@ -40,6 +47,7 @@ files:
|
|
40
47
|
- spec/factories/shoe_factory.rb
|
41
48
|
- spec/lib/blackjack/card_spec.rb
|
42
49
|
- spec/lib/blackjack/dealer_hand_spec.rb
|
50
|
+
- spec/lib/blackjack/format_spec.rb
|
43
51
|
- spec/lib/blackjack/hand_spec.rb
|
44
52
|
- spec/lib/blackjack/player_hand_spec.rb
|
45
53
|
- spec/lib/blackjack/shoe_spec.rb
|