bowlero 0.1.3 → 0.1.5
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/bowlero-0.1.3.gem +0 -0
- data/lib/bowlero/cli.rb +393 -0
- data/lib/bowlero/version.rb +1 -1
- metadata +3 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4866b12e70993cfa04847186591671976562d28996a975b01d8171d6bc534577
|
|
4
|
+
data.tar.gz: 9115b09508a42b9d18054f434b6486a56f68a216e2de31b50619ac93f0152045
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2f5b78cec0d2c5843d3dc685d92c8265cc562d08b9698e12370c6ed80f5c9b115a85856cbdcd9e52885c6d0bba5f5ebe659c1766ea65f0b4a00d614ec0eb9aca
|
|
7
|
+
data.tar.gz: 657462265218e270f2f37211a755aeab67bdb61f570357b141249e70014a08df681427bcc8daf99eaacee72aa6385e4a27b9a94402044903eaf23d956fb444a4
|
data/bowlero-0.1.3.gem
ADDED
|
Binary file
|
data/lib/bowlero/cli.rb
ADDED
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
module Bowlero
|
|
2
|
+
class CLI
|
|
3
|
+
PUN_NAMES = [
|
|
4
|
+
'Pin Diesel', 'Bowl Job', "Livin' on a Spare", 'Alley McBowl',
|
|
5
|
+
'Split Happens', 'Gutterball Guru', 'The Pincredible Hulk',
|
|
6
|
+
'Strike Tyson', 'Bowliver Twist', 'Rolling Thunder'
|
|
7
|
+
]
|
|
8
|
+
|
|
9
|
+
def self.start
|
|
10
|
+
def clear_screen
|
|
11
|
+
system('clear') || system('cls')
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def prompt(message)
|
|
15
|
+
print "#{message} "
|
|
16
|
+
gets.chomp
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def main_menu
|
|
20
|
+
loop do
|
|
21
|
+
clear_screen
|
|
22
|
+
puts '🎳 Welcome to Bowlero! 🎳'
|
|
23
|
+
puts '1. Start Game'
|
|
24
|
+
puts '2. Exit'
|
|
25
|
+
print 'Choose an option: '
|
|
26
|
+
choice = gets.chomp.strip
|
|
27
|
+
case choice
|
|
28
|
+
when '1'
|
|
29
|
+
start_game
|
|
30
|
+
when '2'
|
|
31
|
+
puts 'Thanks for playing Bowlero!'
|
|
32
|
+
exit(0)
|
|
33
|
+
else
|
|
34
|
+
puts 'Invalid option. Press Enter to try again.'
|
|
35
|
+
gets
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def start_game
|
|
41
|
+
clear_screen
|
|
42
|
+
default_name = PUN_NAMES.sample
|
|
43
|
+
name = prompt("Enter your player name [#{default_name}]:")
|
|
44
|
+
name = default_name if name.strip.empty?
|
|
45
|
+
puts "\nWelcome, #{name}! Let's bowl a full game."
|
|
46
|
+
|
|
47
|
+
frames = []
|
|
48
|
+
10.times do |frame_num|
|
|
49
|
+
puts "\n--- Frame #{frame_num + 1} ---"
|
|
50
|
+
frame = Bowlero::Frame.new(frame_number: frame_num + 1)
|
|
51
|
+
if frame_num < 9
|
|
52
|
+
# Regular frames (1-9)
|
|
53
|
+
strike_die = Bowlero::Dice.roll_strike_die
|
|
54
|
+
split_die = Bowlero::Dice.roll_split_die
|
|
55
|
+
if strike_die == :strike
|
|
56
|
+
puts "🎳 STRIKE! You knocked down all 10 pins on the first roll!"
|
|
57
|
+
frame.result = :strike
|
|
58
|
+
frame.first_roll = 10
|
|
59
|
+
frame.second_roll = 0
|
|
60
|
+
frame.pins = 10
|
|
61
|
+
frames << frame
|
|
62
|
+
next
|
|
63
|
+
end
|
|
64
|
+
# Not a strike, so sum pins
|
|
65
|
+
if split_die == :split
|
|
66
|
+
split_value = 6
|
|
67
|
+
total_pins = strike_die + split_value
|
|
68
|
+
frame.split = true
|
|
69
|
+
puts "You knocked down #{strike_die} pins and left a SPLIT! (Split worth 6, Total: #{total_pins} pins)"
|
|
70
|
+
else
|
|
71
|
+
split_value = split_die
|
|
72
|
+
total_pins = strike_die + split_value
|
|
73
|
+
frame.split = false
|
|
74
|
+
puts "You knocked down #{strike_die} and #{split_die} pins (Total: #{total_pins})"
|
|
75
|
+
end
|
|
76
|
+
frame.first_roll = total_pins > 10 ? 10 : total_pins
|
|
77
|
+
if total_pins >= 10
|
|
78
|
+
puts "That's a STRIKE by pin count!"
|
|
79
|
+
frame.result = :strike
|
|
80
|
+
frame.second_roll = 0
|
|
81
|
+
frame.pins = 10
|
|
82
|
+
else
|
|
83
|
+
# Second roll
|
|
84
|
+
if split_die == :split
|
|
85
|
+
split_res = Bowlero::Dice.roll_split_resolution_die
|
|
86
|
+
frame.split_converted = (split_res == :spare)
|
|
87
|
+
if split_res == :spare
|
|
88
|
+
puts "You converted the split for a SPARE!"
|
|
89
|
+
frame.result = :spare
|
|
90
|
+
frame.second_roll = 10 - frame.first_roll
|
|
91
|
+
frame.pins = 10
|
|
92
|
+
else
|
|
93
|
+
puts "Open frame. Some pins left standing."
|
|
94
|
+
frame.result = :open
|
|
95
|
+
frame.second_roll = 0
|
|
96
|
+
frame.pins = frame.first_roll
|
|
97
|
+
end
|
|
98
|
+
else
|
|
99
|
+
spare_res = Bowlero::Dice.roll_spare_resolution_die
|
|
100
|
+
if spare_res == :spare
|
|
101
|
+
puts "You picked up the spare!"
|
|
102
|
+
frame.result = :spare
|
|
103
|
+
frame.second_roll = 10 - frame.first_roll
|
|
104
|
+
frame.pins = 10
|
|
105
|
+
else
|
|
106
|
+
puts "Open frame. Some pins left standing."
|
|
107
|
+
frame.result = :open
|
|
108
|
+
frame.second_roll = 0
|
|
109
|
+
frame.pins = frame.first_roll
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
frames << frame
|
|
114
|
+
else
|
|
115
|
+
# 10th frame special logic
|
|
116
|
+
puts "10th frame! You can get up to 3 rolls if you strike or spare."
|
|
117
|
+
# First roll
|
|
118
|
+
strike_die = Bowlero::Dice.roll_strike_die
|
|
119
|
+
split_die = Bowlero::Dice.roll_split_die
|
|
120
|
+
if strike_die == :strike
|
|
121
|
+
puts "🎳 STRIKE! You knocked down all 10 pins on the first roll!"
|
|
122
|
+
frame.first_roll = 10
|
|
123
|
+
frame.result = :strike
|
|
124
|
+
# Second roll (bonus)
|
|
125
|
+
strike_die2 = Bowlero::Dice.roll_strike_die
|
|
126
|
+
split_die2 = Bowlero::Dice.roll_split_die
|
|
127
|
+
if strike_die2 == :strike
|
|
128
|
+
puts "🎳 STRIKE! Second roll in 10th frame is a strike!"
|
|
129
|
+
frame.second_roll = 10
|
|
130
|
+
else
|
|
131
|
+
if split_die2 == :split
|
|
132
|
+
split_value2 = 6
|
|
133
|
+
total_pins2 = strike_die2 + split_value2
|
|
134
|
+
puts "You knocked down #{strike_die2} pins and left a SPLIT! (Split worth 6, Total: #{total_pins2} pins)"
|
|
135
|
+
frame.second_roll = total_pins2 > 10 ? 10 : total_pins2
|
|
136
|
+
else
|
|
137
|
+
split_value2 = split_die2
|
|
138
|
+
total_pins2 = strike_die2 + split_value2
|
|
139
|
+
puts "You knocked down #{strike_die2} and #{split_die2} pins (Total: #{total_pins2})"
|
|
140
|
+
frame.second_roll = total_pins2 > 10 ? 10 : total_pins2
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
# Third roll (bonus)
|
|
144
|
+
strike_die3 = Bowlero::Dice.roll_strike_die
|
|
145
|
+
split_die3 = Bowlero::Dice.roll_split_die
|
|
146
|
+
if strike_die3 == :strike
|
|
147
|
+
puts "🎳 STRIKE! Third roll in 10th frame is a strike!"
|
|
148
|
+
frame.third_roll = 10
|
|
149
|
+
else
|
|
150
|
+
if split_die3 == :split
|
|
151
|
+
split_value3 = 6
|
|
152
|
+
total_pins3 = strike_die3 + split_value3
|
|
153
|
+
puts "You knocked down #{strike_die3} pins and left a SPLIT! (Split worth 6, Total: #{total_pins3} pins)"
|
|
154
|
+
frame.third_roll = total_pins3 > 10 ? 10 : total_pins3
|
|
155
|
+
else
|
|
156
|
+
split_value3 = split_die3
|
|
157
|
+
total_pins3 = strike_die3 + split_value3
|
|
158
|
+
puts "You knocked down #{strike_die3} and #{split_die3} pins (Total: #{total_pins3})"
|
|
159
|
+
frame.third_roll = total_pins3 > 10 ? 10 : total_pins3
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
else
|
|
163
|
+
# Not a strike on first roll
|
|
164
|
+
if split_die == :split
|
|
165
|
+
split_value = 6
|
|
166
|
+
total_pins = strike_die + split_value
|
|
167
|
+
puts "You knocked down #{strike_die} pins and left a SPLIT! (Split worth 6, Total: #{total_pins} pins)"
|
|
168
|
+
frame.split = true
|
|
169
|
+
else
|
|
170
|
+
split_value = split_die
|
|
171
|
+
total_pins = strike_die + split_value
|
|
172
|
+
puts "You knocked down #{strike_die} and #{split_die} pins (Total: #{total_pins})"
|
|
173
|
+
frame.split = false
|
|
174
|
+
end
|
|
175
|
+
frame.first_roll = total_pins > 10 ? 10 : total_pins
|
|
176
|
+
# Second roll
|
|
177
|
+
if total_pins >= 10
|
|
178
|
+
puts "That's a STRIKE by pin count!"
|
|
179
|
+
frame.result = :strike
|
|
180
|
+
# Two more rolls
|
|
181
|
+
strike_die2 = Bowlero::Dice.roll_strike_die
|
|
182
|
+
split_die2 = Bowlero::Dice.roll_split_die
|
|
183
|
+
if strike_die2 == :strike
|
|
184
|
+
puts "🎳 STRIKE! Second roll in 10th frame is a strike!"
|
|
185
|
+
frame.second_roll = 10
|
|
186
|
+
else
|
|
187
|
+
if split_die2 == :split
|
|
188
|
+
split_value2 = 6
|
|
189
|
+
total_pins2 = strike_die2 + split_value2
|
|
190
|
+
puts "You knocked down #{strike_die2} pins and left a SPLIT! (Split worth 6, Total: #{total_pins2} pins)"
|
|
191
|
+
frame.second_roll = total_pins2 > 10 ? 10 : total_pins2
|
|
192
|
+
else
|
|
193
|
+
split_value2 = split_die2
|
|
194
|
+
total_pins2 = strike_die2 + split_value2
|
|
195
|
+
puts "You knocked down #{strike_die2} and #{split_die2} pins (Total: #{total_pins2})"
|
|
196
|
+
frame.second_roll = total_pins2 > 10 ? 10 : total_pins2
|
|
197
|
+
end
|
|
198
|
+
end
|
|
199
|
+
# Third roll
|
|
200
|
+
strike_die3 = Bowlero::Dice.roll_strike_die
|
|
201
|
+
split_die3 = Bowlero::Dice.roll_split_die
|
|
202
|
+
if strike_die3 == :strike
|
|
203
|
+
puts "🎳 STRIKE! Third roll in 10th frame is a strike!"
|
|
204
|
+
frame.third_roll = 10
|
|
205
|
+
else
|
|
206
|
+
if split_die3 == :split
|
|
207
|
+
split_value3 = 6
|
|
208
|
+
total_pins3 = strike_die3 + split_value3
|
|
209
|
+
puts "You knocked down #{strike_die3} pins and left a SPLIT! (Split worth 6, Total: #{total_pins3} pins)"
|
|
210
|
+
frame.third_roll = total_pins3 > 10 ? 10 : total_pins3
|
|
211
|
+
else
|
|
212
|
+
split_value3 = split_die3
|
|
213
|
+
total_pins3 = strike_die3 + split_value3
|
|
214
|
+
puts "You knocked down #{strike_die3} and #{split_die3} pins (Total: #{total_pins3})"
|
|
215
|
+
frame.third_roll = total_pins3 > 10 ? 10 : total_pins3
|
|
216
|
+
end
|
|
217
|
+
end
|
|
218
|
+
else
|
|
219
|
+
# Not a strike by pin count, so check for split or spare
|
|
220
|
+
if split_die == :split
|
|
221
|
+
split_res = Bowlero::Dice.roll_split_resolution_die
|
|
222
|
+
if split_res == :spare
|
|
223
|
+
puts "You converted the split for a SPARE!"
|
|
224
|
+
frame.result = :spare
|
|
225
|
+
frame.second_roll = 10 - frame.first_roll
|
|
226
|
+
# Third roll (bonus)
|
|
227
|
+
strike_die3 = Bowlero::Dice.roll_strike_die
|
|
228
|
+
split_die3 = Bowlero::Dice.roll_split_die
|
|
229
|
+
if strike_die3 == :strike
|
|
230
|
+
puts "🎳 STRIKE! Third roll in 10th frame is a strike!"
|
|
231
|
+
frame.third_roll = 10
|
|
232
|
+
else
|
|
233
|
+
if split_die3 == :split
|
|
234
|
+
split_value3 = 6
|
|
235
|
+
total_pins3 = strike_die3 + split_value3
|
|
236
|
+
puts "You knocked down #{strike_die3} pins and left a SPLIT! (Split worth 6, Total: #{total_pins3} pins)"
|
|
237
|
+
frame.third_roll = total_pins3 > 10 ? 10 : total_pins3
|
|
238
|
+
else
|
|
239
|
+
split_value3 = split_die3
|
|
240
|
+
total_pins3 = strike_die3 + split_value3
|
|
241
|
+
puts "You knocked down #{strike_die3} and #{split_die3} pins (Total: #{total_pins3})"
|
|
242
|
+
frame.third_roll = total_pins3 > 10 ? 10 : total_pins3
|
|
243
|
+
end
|
|
244
|
+
end
|
|
245
|
+
else
|
|
246
|
+
puts "Open frame. Some pins left standing."
|
|
247
|
+
frame.result = :open
|
|
248
|
+
frame.second_roll = 0
|
|
249
|
+
frame.third_roll = 0
|
|
250
|
+
end
|
|
251
|
+
else
|
|
252
|
+
spare_res = Bowlero::Dice.roll_spare_resolution_die
|
|
253
|
+
if spare_res == :spare
|
|
254
|
+
puts "You picked up the spare!"
|
|
255
|
+
frame.result = :spare
|
|
256
|
+
frame.second_roll = 10 - frame.first_roll
|
|
257
|
+
# Third roll (bonus)
|
|
258
|
+
strike_die3 = Bowlero::Dice.roll_strike_die
|
|
259
|
+
split_die3 = Bowlero::Dice.roll_split_die
|
|
260
|
+
if strike_die3 == :strike
|
|
261
|
+
puts "🎳 STRIKE! Third roll in 10th frame is a strike!"
|
|
262
|
+
frame.third_roll = 10
|
|
263
|
+
else
|
|
264
|
+
if split_die3 == :split
|
|
265
|
+
split_value3 = 6
|
|
266
|
+
total_pins3 = strike_die3 + split_value3
|
|
267
|
+
puts "You knocked down #{strike_die3} pins and left a SPLIT! (Split worth 6, Total: #{total_pins3} pins)"
|
|
268
|
+
frame.third_roll = total_pins3 > 10 ? 10 : total_pins3
|
|
269
|
+
else
|
|
270
|
+
split_value3 = split_die3
|
|
271
|
+
total_pins3 = strike_die3 + split_value3
|
|
272
|
+
puts "You knocked down #{strike_die3} and #{split_die3} pins (Total: #{total_pins3})"
|
|
273
|
+
frame.third_roll = total_pins3 > 10 ? 10 : total_pins3
|
|
274
|
+
end
|
|
275
|
+
end
|
|
276
|
+
else
|
|
277
|
+
puts "Open frame. Some pins left standing."
|
|
278
|
+
frame.result = :open
|
|
279
|
+
frame.second_roll = 0
|
|
280
|
+
frame.third_roll = 0
|
|
281
|
+
end
|
|
282
|
+
end
|
|
283
|
+
end
|
|
284
|
+
end
|
|
285
|
+
# For 10th frame, pins = sum of all rolls
|
|
286
|
+
frame.pins = (frame.first_roll || 0) + (frame.second_roll || 0) + (frame.third_roll || 0)
|
|
287
|
+
frames << frame
|
|
288
|
+
end
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
# --- Scoring pass ---
|
|
292
|
+
def next_rolls(frames, idx, count)
|
|
293
|
+
rolls = []
|
|
294
|
+
i = idx + 1
|
|
295
|
+
while rolls.size < count && i < frames.size
|
|
296
|
+
f = frames[i]
|
|
297
|
+
rolls << f.first_roll if rolls.size < count
|
|
298
|
+
rolls << f.second_roll if rolls.size < count
|
|
299
|
+
i += 1
|
|
300
|
+
end
|
|
301
|
+
rolls[0, count]
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
total_score = 0
|
|
305
|
+
frames.each_with_index do |f, i|
|
|
306
|
+
if i == 9
|
|
307
|
+
# 10th frame: just sum the rolls
|
|
308
|
+
f.score = (f.first_roll || 0) + (f.second_roll || 0) + (f.third_roll || 0)
|
|
309
|
+
total_score += f.score
|
|
310
|
+
f.score = total_score
|
|
311
|
+
elsif f.result == :strike
|
|
312
|
+
bonus_rolls = next_rolls(frames, i, 2)
|
|
313
|
+
f.score = 10 + bonus_rolls.sum
|
|
314
|
+
total_score += f.score
|
|
315
|
+
f.score = total_score
|
|
316
|
+
elsif f.result == :spare
|
|
317
|
+
bonus_rolls = next_rolls(frames, i, 1)
|
|
318
|
+
f.score = 10 + bonus_rolls.sum
|
|
319
|
+
total_score += f.score
|
|
320
|
+
f.score = total_score
|
|
321
|
+
else
|
|
322
|
+
f.score = f.first_roll + f.second_roll
|
|
323
|
+
total_score += f.score
|
|
324
|
+
f.score = total_score
|
|
325
|
+
end
|
|
326
|
+
end
|
|
327
|
+
|
|
328
|
+
def print_scorecard(frames)
|
|
329
|
+
# Frame header
|
|
330
|
+
puts '+---' * 10 + '+'
|
|
331
|
+
print '|'
|
|
332
|
+
(1..10).each { |n| print "%2s |" % n }
|
|
333
|
+
puts
|
|
334
|
+
puts '+-+-' * 10 + '+'
|
|
335
|
+
|
|
336
|
+
# Rolls row
|
|
337
|
+
print '|'
|
|
338
|
+
frames.each_with_index do |f, i|
|
|
339
|
+
if i == 9
|
|
340
|
+
# 10th frame: show up to 3 rolls
|
|
341
|
+
r1 = f.first_roll == 10 ? 'X' : f.first_roll.to_s
|
|
342
|
+
r2 = f.second_roll == 10 ? 'X' : (f.result == :spare ? '/' : f.second_roll.to_s)
|
|
343
|
+
r3 = f.third_roll == 10 ? 'X' : (f.third_roll.nil? ? ' ' : f.third_roll.to_s)
|
|
344
|
+
print "%s|%s|%s|" % [r1, r2, r3]
|
|
345
|
+
else
|
|
346
|
+
r1 = r2 = ' '
|
|
347
|
+
if f.result == :strike
|
|
348
|
+
r1 = 'X'
|
|
349
|
+
r2 = ' '
|
|
350
|
+
elsif f.result == :spare
|
|
351
|
+
r1 = f.first_roll == 0 ? '-' : f.first_roll.to_s
|
|
352
|
+
r2 = '/'
|
|
353
|
+
elsif f.split
|
|
354
|
+
r1 = f.first_roll == 0 ? '-' : f.first_roll.to_s
|
|
355
|
+
r2 = 'S'
|
|
356
|
+
else
|
|
357
|
+
r1 = f.first_roll == 0 ? '-' : f.first_roll.to_s
|
|
358
|
+
r2 = f.second_roll == 0 ? '-' : f.second_roll.to_s
|
|
359
|
+
end
|
|
360
|
+
print "%s|%s|" % [r1, r2]
|
|
361
|
+
end
|
|
362
|
+
end
|
|
363
|
+
puts
|
|
364
|
+
puts '+---' * 10 + '+'
|
|
365
|
+
|
|
366
|
+
# Scores row
|
|
367
|
+
print '|'
|
|
368
|
+
frames.each { |f| print "%3s|" % f.score }
|
|
369
|
+
puts
|
|
370
|
+
puts '+---' * 10 + '+'
|
|
371
|
+
end
|
|
372
|
+
|
|
373
|
+
puts "\n--- Game Summary for #{name} ---"
|
|
374
|
+
print_scorecard(frames)
|
|
375
|
+
frames.each do |f|
|
|
376
|
+
case f.result
|
|
377
|
+
when :strike
|
|
378
|
+
puts "Frame #{f.frame_number}: STRIKE! (10 pins) | Running Score: #{f.score}"
|
|
379
|
+
when :spare
|
|
380
|
+
puts "Frame #{f.frame_number}: SPARE! (#{f.pins} pins) | Running Score: #{f.score}"
|
|
381
|
+
else
|
|
382
|
+
puts "Frame #{f.frame_number}: Open frame (#{f.pins} pins) | Running Score: #{f.score}"
|
|
383
|
+
end
|
|
384
|
+
end
|
|
385
|
+
puts "\nFinal Score: #{frames.last.score}"
|
|
386
|
+
puts "\n[Press Enter to return to menu]"
|
|
387
|
+
gets
|
|
388
|
+
end
|
|
389
|
+
|
|
390
|
+
main_menu
|
|
391
|
+
end
|
|
392
|
+
end
|
|
393
|
+
end
|
data/lib/bowlero/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: bowlero
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.5
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Mike Benner
|
|
@@ -26,8 +26,10 @@ files:
|
|
|
26
26
|
- README.md
|
|
27
27
|
- Rakefile
|
|
28
28
|
- bowlero-0.1.0.gem
|
|
29
|
+
- bowlero-0.1.3.gem
|
|
29
30
|
- exe/bowlero
|
|
30
31
|
- lib/bowlero.rb
|
|
32
|
+
- lib/bowlero/cli.rb
|
|
31
33
|
- lib/bowlero/dice.rb
|
|
32
34
|
- lib/bowlero/frame.rb
|
|
33
35
|
- lib/bowlero/version.rb
|