Oshuma-gambler 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +5 -0
- data/Manifest.txt +4 -0
- data/README.txt +3 -0
- data/Rakefile +11 -9
- data/bin/gambler_client +1 -207
- data/gambler.gemspec +22 -0
- data/lib/gambler.rb +2 -1
- data/lib/gambler/deck.rb +1 -1
- data/lib/gambler/exceptions.rb +5 -0
- data/lib/gambler/game/basic_game.rb +68 -0
- data/lib/gambler/game/blackjack.rb +102 -2
- data/lib/gambler/player.rb +21 -0
- data/tasks/docs.rake +1 -0
- data/tasks/site.rake +1 -0
- data/test/client/test_client.rb +8 -0
- data/test/client/test_client_helper.rb +8 -0
- data/test/game/test_blackjack.rb +84 -2
- data/test/test_gambler.rb +1 -1
- data/test/test_player.rb +17 -0
- metadata +16 -3
data/History.txt
CHANGED
data/Manifest.txt
CHANGED
@@ -8,6 +8,8 @@ bin/gambler_client
|
|
8
8
|
gambler.gemspec
|
9
9
|
lib/gambler.rb
|
10
10
|
lib/gambler/card.rb
|
11
|
+
lib/gambler/client.rb
|
12
|
+
lib/gambler/client/client_helper.rb
|
11
13
|
lib/gambler/deck.rb
|
12
14
|
lib/gambler/exceptions.rb
|
13
15
|
lib/gambler/game.rb
|
@@ -21,6 +23,8 @@ tasks/override_rake_task.rb
|
|
21
23
|
tasks/rcov.rake
|
22
24
|
tasks/site.rake
|
23
25
|
tasks/util.rb
|
26
|
+
test/client/test_client.rb
|
27
|
+
test/client/test_client_helper.rb
|
24
28
|
test/game/test_basic_game.rb
|
25
29
|
test/game/test_blackjack.rb
|
26
30
|
test/helper.rb
|
data/README.txt
CHANGED
@@ -27,6 +27,9 @@ Pure Ruby, so far.
|
|
27
27
|
$ gem sources -a http://gems.github.com/ (You only need to do this once.)
|
28
28
|
$ gem install Oshuma-gambler
|
29
29
|
|
30
|
+
== USAGE:
|
31
|
+
See http://gambler.rubyforge.org/api/ for usage documentation.
|
32
|
+
|
30
33
|
== LICENSE:
|
31
34
|
|
32
35
|
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
data/Rakefile
CHANGED
@@ -29,15 +29,17 @@ Dir["#{GAMBLER_ROOT}/tasks/**/*.rake"].sort.each { |task| load task }
|
|
29
29
|
|
30
30
|
task :default => [ :test, :rcov ]
|
31
31
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
32
|
+
namespace :gambler do
|
33
|
+
desc 'Clean up dynamically generated files'
|
34
|
+
task :cleanup do
|
35
|
+
%w{
|
36
|
+
docs:clear
|
37
|
+
issues:report:clear
|
38
|
+
rcov:clear
|
39
|
+
site:clear_local
|
40
|
+
}.each do |clean|
|
41
|
+
Rake::Task[clean].invoke
|
42
|
+
end
|
41
43
|
end
|
42
44
|
end
|
43
45
|
|
data/bin/gambler_client
CHANGED
@@ -4,211 +4,5 @@ GAMBLER_ROOT = File.join(File.dirname(__FILE__), '..')
|
|
4
4
|
$LOAD_PATH.unshift File.join(GAMBLER_ROOT, 'lib')
|
5
5
|
require 'gambler'
|
6
6
|
|
7
|
-
|
8
|
-
# A simple Client which allows you to play around with Gambler.
|
9
|
-
# Most of this class can be ignored, as it just sets up the gaming
|
10
|
-
# environment. The method to pay attention to is +play_blackjack+.
|
11
|
-
# This is the method that actually creates and deals a Blackjack game.
|
12
|
-
class Client
|
13
|
-
WIDTH = 50
|
14
|
-
|
15
|
-
$player_quits = false
|
16
|
-
|
17
|
-
attr_accessor :bots
|
18
|
-
attr_accessor :player
|
19
|
-
|
20
|
-
def initialize
|
21
|
-
@player = setup_player
|
22
|
-
@bots = Array.new
|
23
|
-
end
|
24
|
-
|
25
|
-
# This is the main client menu.
|
26
|
-
def menu
|
27
|
-
display_header
|
28
|
-
until $player_quits do
|
29
|
-
display_player_stats
|
30
|
-
display_game_menu
|
31
|
-
choice = STDIN.gets.chomp
|
32
|
-
|
33
|
-
case choice
|
34
|
-
when '1':
|
35
|
-
play_blackjack
|
36
|
-
when '2':
|
37
|
-
puts 'This game is not implemented yet.'
|
38
|
-
when '3':
|
39
|
-
puts 'This game is not implemented yet.'
|
40
|
-
when /a/i:
|
41
|
-
add_ai_player
|
42
|
-
when /p/i:
|
43
|
-
setup_player
|
44
|
-
when /d/i:
|
45
|
-
debug_console
|
46
|
-
when /q/i:
|
47
|
-
$player_quits = true
|
48
|
-
exit
|
49
|
-
else
|
50
|
-
puts 'Invalid choice, dumbass.'
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end # of menu
|
54
|
-
|
55
|
-
private
|
56
|
-
|
57
|
-
# Add an AI Player as an opponent.
|
58
|
-
def add_ai_player
|
59
|
-
@bots << setup_player(:bot => true)
|
60
|
-
end
|
61
|
-
|
62
|
-
# Simple debugging console.
|
63
|
-
def debug_console
|
64
|
-
stop_debug = false
|
65
|
-
code = Array.new
|
66
|
-
|
67
|
-
puts # spacer
|
68
|
-
puts '== DEBUG CONSOLE =='
|
69
|
-
puts 'Commands:'
|
70
|
-
puts ' /run - Quit debugger and run the code.'
|
71
|
-
puts ' /show - Show the code currently in the buffer.'
|
72
|
-
puts ' /quit - Quit debugger without running the code.'
|
73
|
-
|
74
|
-
until stop_debug do
|
75
|
-
print "eval:#{code.size + 1}> "
|
76
|
-
line = STDIN.gets.chomp
|
77
|
-
|
78
|
-
case line
|
79
|
-
when '/run':
|
80
|
-
run_code(code)
|
81
|
-
stop_debug = true
|
82
|
-
when '/show':
|
83
|
-
show_code_buffer(code)
|
84
|
-
when '/quit':
|
85
|
-
stop_debug = true
|
86
|
-
else # not a command, must be some Ruby code.
|
87
|
-
code << line
|
88
|
-
end
|
89
|
-
end
|
90
|
-
end # of debug_console
|
91
|
-
|
92
|
-
# Client header.
|
93
|
-
def display_header
|
94
|
-
puts # spacer
|
95
|
-
puts ''.center(WIDTH, '=')
|
96
|
-
puts " Gambler v#{Gambler::VERSION} ".center(WIDTH, '=')
|
97
|
-
puts ''.center(WIDTH, '=')
|
98
|
-
puts '----------------------------------------'.center(WIDTH)
|
99
|
-
puts '| Feeding yet another human addiction. |'.center(WIDTH)
|
100
|
-
puts '----------------------------------------'.center(WIDTH)
|
101
|
-
end # of display_header
|
102
|
-
|
103
|
-
# Pretty print the player's stats.
|
104
|
-
def display_player_stats
|
105
|
-
puts '- Players -'.center(WIDTH)
|
106
|
-
seperator = "\t"
|
107
|
-
stat_width = WIDTH - 5
|
108
|
-
stats = String.new
|
109
|
-
bot_stats = String.new
|
110
|
-
|
111
|
-
stats << "Player: #{@player.name}".ljust(WIDTH/2)
|
112
|
-
stats << seperator
|
113
|
-
stats << "Chips: #{@player.chips}"
|
114
|
-
puts stats.center(stat_width)
|
115
|
-
|
116
|
-
if @bots.empty?
|
117
|
-
puts 'No AI opponents.'.center(WIDTH)
|
118
|
-
else
|
119
|
-
@bots.each do |bot|
|
120
|
-
bot_stats = "AI: #{bot.name}".ljust(WIDTH/2)
|
121
|
-
bot_stats << seperator
|
122
|
-
bot_stats << "Chips: #{bot.chips}"
|
123
|
-
puts bot_stats.center(stat_width)
|
124
|
-
end
|
125
|
-
end
|
126
|
-
end # of display_player_stats
|
127
|
-
|
128
|
-
# Client game menu.
|
129
|
-
def display_game_menu
|
130
|
-
puts '-----------------------'.center(WIDTH)
|
131
|
-
puts '| 1) Blackjack |'.center(WIDTH)
|
132
|
-
puts '| 2) Stud Poker |'.center(WIDTH)
|
133
|
-
puts "| 3) Texas Hold 'em |".center(WIDTH)
|
134
|
-
puts '| A) Add AI Player |'.center(WIDTH)
|
135
|
-
puts '| D) Debug Console |'.center(WIDTH)
|
136
|
-
puts '| P) Setup Player |'.center(WIDTH)
|
137
|
-
puts '| Q) Quit |'.center(WIDTH)
|
138
|
-
puts '-----------------------'.center(WIDTH)
|
139
|
-
puts
|
140
|
-
print 'Game: '
|
141
|
-
end # of display_menu
|
142
|
-
|
143
|
-
# Play a quick 1vs1 game of Blackjack.
|
144
|
-
def play_blackjack
|
145
|
-
begin
|
146
|
-
# Create an array and add the player and bots.
|
147
|
-
players = Array.new
|
148
|
-
players << @player
|
149
|
-
players << @bots
|
150
|
-
players.flatten!
|
151
|
-
|
152
|
-
@game = Gambler::Game::Blackjack.new(:players => players)
|
153
|
-
rescue Gambler::Exceptions::InvalidPlayerSize
|
154
|
-
puts 'Need at least 2 players for blackjack.'
|
155
|
-
until @bots.size >= 1
|
156
|
-
@bots << setup_player(:bot => true)
|
157
|
-
end
|
158
|
-
retry
|
159
|
-
end # of begin ZOMG!!1
|
160
|
-
end # of play_blackjack
|
161
|
-
|
162
|
-
# Takes an array of +code+ lines and <tt>eval</tt>'s them.
|
163
|
-
def run_code(code)
|
164
|
-
puts # spacer
|
165
|
-
begin
|
166
|
-
puts " BEGIN DEBUG ".center(WIDTH, '=')
|
167
|
-
eval(code.join("\n")) # Need to join, since +code+ is an Array.
|
168
|
-
puts " END DEBUG ".center(WIDTH, '=')
|
169
|
-
rescue Exception => error
|
170
|
-
puts " DEBUG FAILED ".center(WIDTH, '=')
|
171
|
-
puts error
|
172
|
-
end
|
173
|
-
puts # spacer
|
174
|
-
end
|
175
|
-
|
176
|
-
# Setup a new Player instance.
|
177
|
-
def setup_player(options = {})
|
178
|
-
default_chips = 100
|
179
|
-
if options[:bot]
|
180
|
-
who = 'AI player'
|
181
|
-
default_name = 'Kenny'
|
182
|
-
else
|
183
|
-
who = 'your player'
|
184
|
-
default_name = 'Human'
|
185
|
-
end
|
186
|
-
|
187
|
-
puts "Setting up #{who}."
|
188
|
-
print "Name [#{default_name}]: "
|
189
|
-
name = STDIN.gets.chomp
|
190
|
-
name = default_name if name.empty?
|
191
|
-
|
192
|
-
print "Chips [#{default_chips}]: "
|
193
|
-
chips = STDIN.gets.chomp.to_i
|
194
|
-
chips = default_chips if chips.zero?
|
195
|
-
|
196
|
-
return Gambler::Player.new(name, :chips => chips)
|
197
|
-
end # of setup_player
|
198
|
-
|
199
|
-
# Takes an array of +code+ lines and prints them.
|
200
|
-
def show_code_buffer(code)
|
201
|
-
return (puts "Buffer empty.") if code.size.zero?
|
202
|
-
puts "== BUFFER ==\n"
|
203
|
-
code.each_with_index do |buf, line_num|
|
204
|
-
print "#{line_num + 1}: ".rjust(5)
|
205
|
-
puts buf
|
206
|
-
end
|
207
|
-
end
|
208
|
-
|
209
|
-
end # of Client
|
210
|
-
|
211
|
-
end # of Gambler
|
212
|
-
|
213
|
-
# Let's do this!
|
7
|
+
# See lib/gambler/client.rb
|
214
8
|
Gambler::Client.new.menu
|
data/gambler.gemspec
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = 'gambler'
|
3
|
+
s.version = '0.0.3'
|
4
|
+
s.date = '2008-06-09'
|
5
|
+
|
6
|
+
s.authors = ['Dale Campbell']
|
7
|
+
s.email = ['dale@save-state.net']
|
8
|
+
s.homepage = 'http://gambler.rubyforge.org/'
|
9
|
+
|
10
|
+
s.summary = 'Ruby library to satisfy yet another human addiction.'
|
11
|
+
s.description = "Gambler is a Ruby library which can be included into other classes/modules. It provides an object oriented interface for common gambling games such as Blackjack, Poker, etc."
|
12
|
+
|
13
|
+
s.require_paths = ['lib']
|
14
|
+
s.files = ['History.txt', 'Manifest.txt', 'README', 'README.rdoc', 'README.txt', 'Rakefile', 'bin/gambler_client', 'gambler.gemspec', 'lib/gambler.rb', 'lib/gambler/card.rb', 'lib/gambler/deck.rb', 'lib/gambler/exceptions.rb', 'lib/gambler/game.rb', 'lib/gambler/game/basic_game.rb', 'lib/gambler/game/blackjack.rb', 'lib/gambler/player.rb', 'tasks/ditz.rake', 'tasks/docs.rake', 'tasks/git.rake', 'tasks/override_rake_task.rb', 'tasks/rcov.rake', 'tasks/site.rake', 'tasks/util.rb', 'test/game/test_basic_game.rb', 'test/game/test_blackjack.rb', 'test/helper.rb', 'test/suite.rb', 'test/test_card.rb', 'test/test_deck.rb', 'test/test_gambler.rb', 'test/test_player.rb', 'test/client/test_client.rb', 'test/client/test_client_helper.rb']
|
15
|
+
s.test_files = ['test/client/test_client.rb', 'test/client/test_client_helper.rb', 'test/game/test_basic_game.rb', 'test/game/test_blackjack.rb', 'test/test_card.rb', 'test/test_deck.rb', 'test/test_gambler.rb', 'test/test_player.rb']
|
16
|
+
|
17
|
+
s.has_rdoc = true
|
18
|
+
s.rdoc_options = ['--main', 'README.txt']
|
19
|
+
s.extra_rdoc_files = ['History.txt', 'Manifest.txt', 'README.txt']
|
20
|
+
|
21
|
+
s.add_dependency('hoe', '>= 1.5.3')
|
22
|
+
end
|
data/lib/gambler.rb
CHANGED
@@ -6,6 +6,7 @@ require 'rubygems'
|
|
6
6
|
|
7
7
|
# Gambler libraries.
|
8
8
|
require 'gambler/card'
|
9
|
+
require 'gambler/client'
|
9
10
|
require 'gambler/deck'
|
10
11
|
require 'gambler/exceptions'
|
11
12
|
require 'gambler/game'
|
@@ -20,5 +21,5 @@ module Gambler
|
|
20
21
|
|
21
22
|
self.debug = false
|
22
23
|
|
23
|
-
VERSION = '0.0.
|
24
|
+
VERSION = '0.0.3'
|
24
25
|
end
|
data/lib/gambler/deck.rb
CHANGED
data/lib/gambler/exceptions.rb
CHANGED
@@ -5,8 +5,12 @@ module Gambler
|
|
5
5
|
# Gambler
|
6
6
|
class MustOverrideMethod < Exception; end
|
7
7
|
|
8
|
+
# Blackjack
|
9
|
+
class PlayerBust < Exception; end
|
10
|
+
|
8
11
|
# Card
|
9
12
|
class InvalidCardType < Exception; end
|
13
|
+
class NoWinner < Exception; end
|
10
14
|
|
11
15
|
# Deck
|
12
16
|
class DeckEmpty < Exception; end
|
@@ -15,6 +19,7 @@ module Gambler
|
|
15
19
|
# Game
|
16
20
|
class InvalidPlayers < Exception; end
|
17
21
|
class InvalidPlayerSize < Exception; end
|
22
|
+
class NotEnoughChips < Exception; end
|
18
23
|
class NoPlayers < Exception; end
|
19
24
|
|
20
25
|
# Player
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module Gambler
|
2
|
+
|
3
|
+
module Game
|
4
|
+
|
5
|
+
# The basic game class in which all others can inherit.
|
6
|
+
# Feel free to create your own game class which does not inherit
|
7
|
+
# from BasicGame, but uses Player, Deck, etc. directly.
|
8
|
+
#
|
9
|
+
# BasicGame gives some free functionality to it's children:
|
10
|
+
# * <tt>players</tt>: Instance reader for the game's Player(s).
|
11
|
+
# * <tt>ante</tt>: Instance accessor for the game's current ante.
|
12
|
+
# * <tt>deck</tt>: Brand new, fully shuffled Deck to play with.
|
13
|
+
# * <tt>pot</tt>: Instance accessor for the game's current pot.
|
14
|
+
#
|
15
|
+
# The +options+ hash only requires one element, +players+, which must
|
16
|
+
# be an array of Gambler::Player object(s).
|
17
|
+
#
|
18
|
+
# Example:
|
19
|
+
# class Poker < Gambler::Game::BasicGame
|
20
|
+
# def initialize(options = {})
|
21
|
+
# # .. do custom shit (if needed) ..
|
22
|
+
# super(options) # Required to recieve free functionality.
|
23
|
+
# # .. more custom shit (if needed) ..
|
24
|
+
# end
|
25
|
+
#
|
26
|
+
# def poker_stuff
|
27
|
+
# !cheat
|
28
|
+
# end
|
29
|
+
# end
|
30
|
+
#
|
31
|
+
# # Create some players.
|
32
|
+
# @dale = Gambler::Player.new('Dale')
|
33
|
+
# @kenny = Gambler::Player.new('Kenny')
|
34
|
+
#
|
35
|
+
# # This will be passed to Poker.new.
|
36
|
+
# options = {
|
37
|
+
# :players => [@dale, @kenny], # The only required option.
|
38
|
+
# :ante => 50,
|
39
|
+
# :pot => 1_000
|
40
|
+
# }
|
41
|
+
#
|
42
|
+
# @game = Poker.new(options)
|
43
|
+
# @game.poker_stuff
|
44
|
+
class BasicGame
|
45
|
+
INITIAL_ANTE = 10
|
46
|
+
INITIAL_POT = 0
|
47
|
+
|
48
|
+
attr_reader :players
|
49
|
+
attr_accessor :ante, :deck, :pot
|
50
|
+
|
51
|
+
def initialize(options = {})
|
52
|
+
raise Exceptions::NoPlayers unless options[:players].size > 0
|
53
|
+
options[:players].each do |player|
|
54
|
+
raise Exceptions::InvalidPlayers unless player.is_a? Player
|
55
|
+
end
|
56
|
+
@players = options[:players]
|
57
|
+
|
58
|
+
@deck = Deck.new
|
59
|
+
3.times { @deck.shuffle! }
|
60
|
+
|
61
|
+
@ante = options[:ante] || INITIAL_ANTE
|
62
|
+
@pot = options[:pot] || INITIAL_POT
|
63
|
+
end
|
64
|
+
end # of BasicGame
|
65
|
+
|
66
|
+
end # of Game
|
67
|
+
|
68
|
+
end # of Gambler
|
@@ -4,25 +4,125 @@ module Gambler
|
|
4
4
|
|
5
5
|
# The Game of Blackjack.
|
6
6
|
class Blackjack < Gambler::Game::BasicGame
|
7
|
+
BUST = 21 # The hand_value in which the Player busts.
|
7
8
|
INITIAL_CARDS = 2
|
8
9
|
|
10
|
+
# These are used instead of Card::FACE_VALUES to accommodate Blackjack.
|
11
|
+
FACE_VALUES = {
|
12
|
+
'A' => 11,
|
13
|
+
'K' => 10,
|
14
|
+
'Q' => 10,
|
15
|
+
'J' => 10,
|
16
|
+
'T' => 10,
|
17
|
+
'9' => 9,
|
18
|
+
'8' => 8,
|
19
|
+
'7' => 7,
|
20
|
+
'6' => 6,
|
21
|
+
'5' => 5,
|
22
|
+
'4' => 4,
|
23
|
+
'3' => 3,
|
24
|
+
'2' => 2,
|
25
|
+
'L' => 1 # Magic low Ace.
|
26
|
+
}
|
27
|
+
|
28
|
+
attr_reader :players_in_round
|
29
|
+
attr_reader :round_winner
|
30
|
+
|
9
31
|
def initialize(options = {})
|
10
32
|
raise Exceptions::InvalidPlayerSize unless options[:players].size >= 2
|
11
33
|
super(options)
|
12
34
|
@players.each { |player| player.empty_hand! }
|
35
|
+
@players_in_round = Array.new
|
36
|
+
@players_in_round.replace(@players)
|
37
|
+
@round_winner = nil
|
38
|
+
end
|
39
|
+
|
40
|
+
# Forces each Player to put ante in the pot.
|
41
|
+
def ante_up!
|
42
|
+
@players_in_round.each { |player| place_bet(player, @ante) }
|
43
|
+
end
|
44
|
+
|
45
|
+
# Calculates the integer value for a Blackjack +hand+.
|
46
|
+
# Aces are converted to their lower value if the total hand value
|
47
|
+
# will bust the Player (and there are aces in the +hand+, of course).
|
48
|
+
def hand_value(hand)
|
49
|
+
return 0 if hand.empty?
|
50
|
+
value = 0
|
51
|
+
|
52
|
+
# Add up the face values
|
53
|
+
hand.each do |card|
|
54
|
+
value += FACE_VALUES[card.face]
|
55
|
+
end
|
56
|
+
|
57
|
+
# Handle any needed Ace changes.
|
58
|
+
while value > BUST
|
59
|
+
hand.each do |card|
|
60
|
+
if card.face == 'A'
|
61
|
+
# Subtract the difference between high and low ace (10).
|
62
|
+
value -= (FACE_VALUES['A'] - FACE_VALUES['L'])
|
63
|
+
end
|
64
|
+
end
|
65
|
+
break # no aces to change, bail
|
66
|
+
end
|
67
|
+
|
68
|
+
return value
|
69
|
+
end # of hand_value
|
70
|
+
|
71
|
+
# Give +player+ a Card.
|
72
|
+
def hit(player)
|
73
|
+
@deck.deal_to player
|
74
|
+
if player_bust?(player)
|
75
|
+
@players_in_round.delete(player)
|
76
|
+
raise Exceptions::PlayerBust
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# Allows +player+ to place a bet for +amount+ which will be added to
|
81
|
+
# the current hand's pot.
|
82
|
+
def place_bet(player, amount)
|
83
|
+
raise Exceptions::NotEnoughChips if player.chips < amount
|
84
|
+
@pot += amount
|
85
|
+
player.chips -= amount
|
86
|
+
end
|
87
|
+
|
88
|
+
# Returns true of the Player's hand has a value above BUST.
|
89
|
+
def player_bust?(player)
|
90
|
+
hand_value(player.hand) > BUST
|
91
|
+
end
|
92
|
+
|
93
|
+
# This should be called at the beginning of every round (not game),
|
94
|
+
# and sets up things like the ante and dealing initial hands.
|
95
|
+
def start_round!
|
96
|
+
@players.each { |player| player.empty_hand! }
|
97
|
+
@players_in_round.replace(@players)
|
98
|
+
@round_winner = nil
|
99
|
+
ante_up!
|
13
100
|
deal_initial_hands
|
14
101
|
end
|
15
102
|
|
103
|
+
# This should be called after all players bust or stay. Sets the
|
104
|
+
# <tt>@round_winner</tt> variable to the Player object who won and
|
105
|
+
# gives them the pot.
|
106
|
+
def finish_round!
|
107
|
+
raise Exceptions::NoWinner if @players_in_round.nil?
|
108
|
+
# The winner is the Player with the highest hand_value.
|
109
|
+
@round_winner = @players_in_round.sort_by do |player|
|
110
|
+
hand_value(player.hand)
|
111
|
+
end.reverse.first
|
112
|
+
@round_winner.chips += @pot
|
113
|
+
@pot = INITIAL_POT
|
114
|
+
end
|
115
|
+
|
16
116
|
private
|
17
117
|
|
18
118
|
# Deal out the initial cards to each Player.
|
19
119
|
def deal_initial_hands
|
20
120
|
INITIAL_CARDS.times do
|
21
|
-
@
|
121
|
+
@players_in_round.each do |player|
|
22
122
|
@deck.deal_to player
|
23
123
|
end
|
24
124
|
end
|
25
|
-
end
|
125
|
+
end # of deal_initial_hands
|
26
126
|
|
27
127
|
end # of Blackjack
|
28
128
|
|
data/lib/gambler/player.rb
CHANGED
@@ -37,12 +37,33 @@ module Gambler
|
|
37
37
|
%Q{#<Gambler::Player '#{@name}'>}
|
38
38
|
end
|
39
39
|
|
40
|
+
# Return true/false depending on if the Player has chips.
|
41
|
+
def is_broke?
|
42
|
+
@chips <= 0
|
43
|
+
end
|
44
|
+
|
40
45
|
# Pretty printing of a Player.
|
41
46
|
def to_s
|
42
47
|
"#{@name} ($#{@chips})"
|
43
48
|
end
|
44
49
|
|
45
50
|
# Allows a Player to view their +hand+ in various formats.
|
51
|
+
# Examples:
|
52
|
+
# @player = Player.new('Dale', :hand => [Card.new('Ad'), Card.new('Kd')])
|
53
|
+
#
|
54
|
+
# # :format => :array (the default)
|
55
|
+
# @player.view_hand
|
56
|
+
# => ['Ad', 'Kd']
|
57
|
+
# @player.view_hand(:pretty => true)
|
58
|
+
# => ['Ace of Diamonds', 'King of Diamonds']
|
59
|
+
#
|
60
|
+
# # :format => :string
|
61
|
+
# @player.view_hand(:format => :string)
|
62
|
+
# => 'Ad Kd'
|
63
|
+
# @player.view_hand(:format => :string, :pretty => true)
|
64
|
+
# => 'Ace of Diamonds, King of Diamonds'
|
65
|
+
# @player.view_hand(:format => :string, :pretty => true, :seperator => ' | ')
|
66
|
+
# => 'Ace of Diamonds | King of Diamonds'
|
46
67
|
def view_hand(options = {})
|
47
68
|
format = options[:format] || :array
|
48
69
|
pretty = options[:pretty] || false
|
data/tasks/docs.rake
CHANGED
data/tasks/site.rake
CHANGED
data/test/game/test_blackjack.rb
CHANGED
@@ -6,15 +6,17 @@ class TestBlackjack < Test::Unit::TestCase
|
|
6
6
|
|
7
7
|
def setup
|
8
8
|
@dale = Player.new('Dale')
|
9
|
-
@kenny = Player.new('
|
9
|
+
@kenny = Player.new('The Gambler')
|
10
10
|
@game = Blackjack.new(:players => [@dale, @kenny])
|
11
|
+
@game.start_round!
|
11
12
|
end
|
12
13
|
|
13
14
|
def test_new_blackjack_game
|
14
15
|
assert_kind_of(Blackjack, @game)
|
15
16
|
assert_equal(10, @game.ante)
|
16
|
-
assert_equal(
|
17
|
+
assert_equal(20, @game.pot)
|
17
18
|
assert_kind_of(Deck, @game.deck)
|
19
|
+
assert(@game.deck.shuffled, "#{@game.deck} not shuffled")
|
18
20
|
end
|
19
21
|
|
20
22
|
def test_invalid_player_size
|
@@ -23,4 +25,84 @@ class TestBlackjack < Test::Unit::TestCase
|
|
23
25
|
Blackjack.new(:players => [@dale])
|
24
26
|
end
|
25
27
|
end
|
28
|
+
|
29
|
+
def test_ante_up!
|
30
|
+
@game.ante_up!
|
31
|
+
assert_equal(40, @game.pot)
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_hand_value
|
35
|
+
@player = Player.new('Newb', :hand => [ Card.new('2s'), Card.new('3s') ])
|
36
|
+
assert_equal(5, @game.hand_value(@player.hand))
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_hand_value_with_aces
|
40
|
+
@player = Player.new('Newb', :hand => [
|
41
|
+
Card.new('As'), Card.new('2s'), Card.new('3s') ])
|
42
|
+
assert_equal(16, @game.hand_value(@player.hand))
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_hand_value_treating_ace_as_one
|
46
|
+
@player = Player.new('Newb', :hand => [
|
47
|
+
Card.new('As'), Card.new('2s'), Card.new('Ks') ])
|
48
|
+
assert_equal(13, @game.hand_value(@player.hand))
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_hit # shouldn't bust
|
52
|
+
@dale.hand = [ Card.new('2d'), Card.new('3d') ]
|
53
|
+
@game.hit(@dale)
|
54
|
+
assert_equal(3, @dale.hand.size)
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_place_bet
|
58
|
+
@game.place_bet(@dale, 10)
|
59
|
+
assert_equal(30, @game.pot)
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_player_bust?
|
63
|
+
@dale.hand = [ Card.new('Kd'), Card.new('Qd') ]
|
64
|
+
assert_raise(Exceptions::PlayerBust) do
|
65
|
+
@game.hit @dale
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def test_start_round!
|
70
|
+
@game = Blackjack.new(:players => [@dale, @kenny])
|
71
|
+
assert(@dale.hand.empty?, "#{@dale}'s hand is not empty")
|
72
|
+
assert(@kenny.hand.empty?, "#{@kenny}'s hand is not empty")
|
73
|
+
assert_equal(0, @game.pot)
|
74
|
+
@game.start_round!
|
75
|
+
assert_equal(2, @dale.hand.size)
|
76
|
+
assert_equal(2, @kenny.hand.size)
|
77
|
+
assert_equal(20, @game.pot)
|
78
|
+
end
|
79
|
+
|
80
|
+
def test_finish_round!
|
81
|
+
@winner = Player.new('Winner')
|
82
|
+
@middle = Player.new('Middle')
|
83
|
+
@loser = Player.new('Loser')
|
84
|
+
|
85
|
+
# Randomize the order.
|
86
|
+
players = [@winner, @middle, @loser].sort_by { rand }
|
87
|
+
@game = Blackjack.new(:players => players)
|
88
|
+
@game.start_round!
|
89
|
+
|
90
|
+
# Used in the asserts below.
|
91
|
+
winner_chips = @winner.chips
|
92
|
+
middle_chips = @middle.chips
|
93
|
+
loser_chips = @loser.chips
|
94
|
+
pot = @game.pot
|
95
|
+
|
96
|
+
# Craft a round with a known outcome.
|
97
|
+
@winner.hand = [Card.new('Kd'), Card.new('Ks')] # => 20
|
98
|
+
@middle.hand = [Card.new('5h'), Card.new('5c')] # => 10
|
99
|
+
@loser.hand = [Card.new('2d'), Card.new('2s')] # => 4
|
100
|
+
@game.finish_round!
|
101
|
+
|
102
|
+
assert_equal(@winner, @game.round_winner)
|
103
|
+
assert_equal((winner_chips + pot), @winner.chips)
|
104
|
+
assert_equal(middle_chips, @middle.chips)
|
105
|
+
assert_equal(loser_chips, @loser.chips)
|
106
|
+
assert_equal(0, @game.pot)
|
107
|
+
end
|
26
108
|
end
|
data/test/test_gambler.rb
CHANGED
data/test/test_player.rb
CHANGED
@@ -72,6 +72,13 @@ class TestPlayer < Test::Unit::TestCase
|
|
72
72
|
assert_equal(pretty_hand, @player.view_hand(:format => :string, :pretty => true))
|
73
73
|
end
|
74
74
|
|
75
|
+
def test_view_hand_as_pretty_string_with_seperator
|
76
|
+
@player = Player.new('Dale', :hand => [Card.new('Ad'), Card.new('Kd')])
|
77
|
+
pretty_hand = 'Ace of Diamonds | King of Diamonds'
|
78
|
+
assert_equal(pretty_hand,
|
79
|
+
@player.view_hand(:format => :string, :pretty => true, :seperator => ' | '))
|
80
|
+
end
|
81
|
+
|
75
82
|
def test_default_chip_stack
|
76
83
|
assert_equal(100, @player.chips)
|
77
84
|
end
|
@@ -93,4 +100,14 @@ class TestPlayer < Test::Unit::TestCase
|
|
93
100
|
@player.chips += pot # You win!
|
94
101
|
assert_equal(pot + chips, @player.chips)
|
95
102
|
end
|
103
|
+
|
104
|
+
def test_is_broke?
|
105
|
+
@player.chips = 0
|
106
|
+
assert(@player.is_broke?, "#{@player} isn't broke")
|
107
|
+
end
|
108
|
+
|
109
|
+
def test_is_not_broke
|
110
|
+
assert_equal(100, @player.chips)
|
111
|
+
assert_equal(false, @player.is_broke?)
|
112
|
+
end
|
96
113
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: Oshuma-gambler
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dale Campbell
|
@@ -11,8 +11,16 @@ cert_chain: []
|
|
11
11
|
|
12
12
|
date: 2008-06-09 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
|
-
dependencies:
|
15
|
-
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: hoe
|
17
|
+
version_requirement:
|
18
|
+
version_requirements: !ruby/object:Gem::Requirement
|
19
|
+
requirements:
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 1.5.3
|
23
|
+
version:
|
16
24
|
description: Gambler is a Ruby library which can be included into other classes/modules. It provides an object oriented interface for common gambling games such as Blackjack, Poker, etc.
|
17
25
|
email:
|
18
26
|
- dale@save-state.net
|
@@ -32,6 +40,7 @@ files:
|
|
32
40
|
- README.txt
|
33
41
|
- Rakefile
|
34
42
|
- bin/gambler_client
|
43
|
+
- gambler.gemspec
|
35
44
|
- lib/gambler.rb
|
36
45
|
- lib/gambler/card.rb
|
37
46
|
- lib/gambler/deck.rb
|
@@ -55,6 +64,8 @@ files:
|
|
55
64
|
- test/test_deck.rb
|
56
65
|
- test/test_gambler.rb
|
57
66
|
- test/test_player.rb
|
67
|
+
- test/client/test_client.rb
|
68
|
+
- test/client/test_client_helper.rb
|
58
69
|
has_rdoc: true
|
59
70
|
homepage: http://gambler.rubyforge.org/
|
60
71
|
post_install_message:
|
@@ -83,6 +94,8 @@ signing_key:
|
|
83
94
|
specification_version: 2
|
84
95
|
summary: Ruby library to satisfy yet another human addiction.
|
85
96
|
test_files:
|
97
|
+
- test/client/test_client.rb
|
98
|
+
- test/client/test_client_helper.rb
|
86
99
|
- test/game/test_basic_game.rb
|
87
100
|
- test/game/test_blackjack.rb
|
88
101
|
- test/test_card.rb
|