acpc_dealer 0.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.
- data/README.md +33 -0
- data/Rakefile +20 -0
- data/acpc_dealer.gemspec +29 -0
- data/bin/acpc_dealer +168 -0
- data/ext/hand_evaluator/extconf.rb +5 -0
- data/ext/hand_evaluator/hand_evaluator.c +38 -0
- data/lib/acpc_dealer/2p.limit.h5.r0.logs/2p.limit.h5.r0.actions.log +5 -0
- data/lib/acpc_dealer/2p.limit.h5.r0.logs/2p.limit.h5.r0.log +0 -0
- data/lib/acpc_dealer/dealer_runner.rb +72 -0
- data/lib/acpc_dealer/version.rb +3 -0
- data/lib/acpc_dealer.rb +33 -0
- data/lib/hand_evaluator.so +0 -0
- data/spec/coverage/assets/0.5.3/app.js +88 -0
- data/spec/coverage/assets/0.5.3/fancybox/blank.gif +0 -0
- data/spec/coverage/assets/0.5.3/fancybox/fancy_close.png +0 -0
- data/spec/coverage/assets/0.5.3/fancybox/fancy_loading.png +0 -0
- data/spec/coverage/assets/0.5.3/fancybox/fancy_nav_left.png +0 -0
- data/spec/coverage/assets/0.5.3/fancybox/fancy_nav_right.png +0 -0
- data/spec/coverage/assets/0.5.3/fancybox/fancy_shadow_e.png +0 -0
- data/spec/coverage/assets/0.5.3/fancybox/fancy_shadow_n.png +0 -0
- data/spec/coverage/assets/0.5.3/fancybox/fancy_shadow_ne.png +0 -0
- data/spec/coverage/assets/0.5.3/fancybox/fancy_shadow_nw.png +0 -0
- data/spec/coverage/assets/0.5.3/fancybox/fancy_shadow_s.png +0 -0
- data/spec/coverage/assets/0.5.3/fancybox/fancy_shadow_se.png +0 -0
- data/spec/coverage/assets/0.5.3/fancybox/fancy_shadow_sw.png +0 -0
- data/spec/coverage/assets/0.5.3/fancybox/fancy_shadow_w.png +0 -0
- data/spec/coverage/assets/0.5.3/fancybox/fancy_title_left.png +0 -0
- data/spec/coverage/assets/0.5.3/fancybox/fancy_title_main.png +0 -0
- data/spec/coverage/assets/0.5.3/fancybox/fancy_title_over.png +0 -0
- data/spec/coverage/assets/0.5.3/fancybox/fancy_title_right.png +0 -0
- data/spec/coverage/assets/0.5.3/fancybox/fancybox-x.png +0 -0
- data/spec/coverage/assets/0.5.3/fancybox/fancybox-y.png +0 -0
- data/spec/coverage/assets/0.5.3/fancybox/fancybox.png +0 -0
- data/spec/coverage/assets/0.5.3/fancybox/jquery.fancybox-1.3.1.css +363 -0
- data/spec/coverage/assets/0.5.3/fancybox/jquery.fancybox-1.3.1.pack.js +44 -0
- data/spec/coverage/assets/0.5.3/favicon_green.png +0 -0
- data/spec/coverage/assets/0.5.3/favicon_red.png +0 -0
- data/spec/coverage/assets/0.5.3/favicon_yellow.png +0 -0
- data/spec/coverage/assets/0.5.3/highlight.css +129 -0
- data/spec/coverage/assets/0.5.3/highlight.pack.js +1 -0
- data/spec/coverage/assets/0.5.3/jquery-1.6.2.min.js +18 -0
- data/spec/coverage/assets/0.5.3/jquery.dataTables.min.js +152 -0
- data/spec/coverage/assets/0.5.3/jquery.timeago.js +141 -0
- data/spec/coverage/assets/0.5.3/jquery.url.js +174 -0
- data/spec/coverage/assets/0.5.3/loading.gif +0 -0
- data/spec/coverage/assets/0.5.3/magnify.png +0 -0
- data/spec/coverage/assets/0.5.3/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
- data/spec/coverage/assets/0.5.3/smoothness/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
- data/spec/coverage/assets/0.5.3/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
- data/spec/coverage/assets/0.5.3/smoothness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
- data/spec/coverage/assets/0.5.3/smoothness/images/ui-bg_glass_75_dadada_1x400.png +0 -0
- data/spec/coverage/assets/0.5.3/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
- data/spec/coverage/assets/0.5.3/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
- data/spec/coverage/assets/0.5.3/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
- data/spec/coverage/assets/0.5.3/smoothness/images/ui-icons_222222_256x240.png +0 -0
- data/spec/coverage/assets/0.5.3/smoothness/images/ui-icons_2e83ff_256x240.png +0 -0
- data/spec/coverage/assets/0.5.3/smoothness/images/ui-icons_454545_256x240.png +0 -0
- data/spec/coverage/assets/0.5.3/smoothness/images/ui-icons_888888_256x240.png +0 -0
- data/spec/coverage/assets/0.5.3/smoothness/images/ui-icons_cd0a0a_256x240.png +0 -0
- data/spec/coverage/assets/0.5.3/smoothness/jquery-ui-1.8.4.custom.css +295 -0
- data/spec/coverage/assets/0.5.3/stylesheet.css +383 -0
- data/spec/coverage/index.html +81 -0
- data/spec/dealer_runner_spec.rb +83 -0
- data/spec/support/spec_helper.rb +33 -0
- data/vendor/project_acpc_server/LICENCE +23 -0
- data/vendor/project_acpc_server/Makefile +22 -0
- data/vendor/project_acpc_server/README +113 -0
- data/vendor/project_acpc_server/README.submission +42 -0
- data/vendor/project_acpc_server/acpc_play_match.pl +101 -0
- data/vendor/project_acpc_server/bm_server +0 -0
- data/vendor/project_acpc_server/bm_server.c +1557 -0
- data/vendor/project_acpc_server/bm_server.config +78 -0
- data/vendor/project_acpc_server/bm_widget +0 -0
- data/vendor/project_acpc_server/bm_widget.c +186 -0
- data/vendor/project_acpc_server/dealer +0 -0
- data/vendor/project_acpc_server/dealer.c +1278 -0
- data/vendor/project_acpc_server/evalHandTables +4269 -0
- data/vendor/project_acpc_server/example_player +0 -0
- data/vendor/project_acpc_server/example_player.c +204 -0
- data/vendor/project_acpc_server/example_player.limit.2p.sh +2 -0
- data/vendor/project_acpc_server/example_player.limit.3p.sh +2 -0
- data/vendor/project_acpc_server/example_player.nolimit.2p.sh +2 -0
- data/vendor/project_acpc_server/example_player.nolimit.3p.sh +2 -0
- data/vendor/project_acpc_server/game.c +1793 -0
- data/vendor/project_acpc_server/game.h +253 -0
- data/vendor/project_acpc_server/holdem.limit.2p.reverse_blinds.game +13 -0
- data/vendor/project_acpc_server/holdem.limit.3p.game +13 -0
- data/vendor/project_acpc_server/holdem.nolimit.2p.reverse_blinds.game +12 -0
- data/vendor/project_acpc_server/holdem.nolimit.3p.game +12 -0
- data/vendor/project_acpc_server/net.c +218 -0
- data/vendor/project_acpc_server/net.h +61 -0
- data/vendor/project_acpc_server/play_match.pl +99 -0
- data/vendor/project_acpc_server/protocol.odt +0 -0
- data/vendor/project_acpc_server/protocol.pdf +0 -0
- data/vendor/project_acpc_server/rng.c +138 -0
- data/vendor/project_acpc_server/rng.h +63 -0
- data/vendor/project_acpc_server/test.log +11 -0
- data/vendor/project_acpc_server/validate_submission.pl +546 -0
- metadata +315 -0
data/README.md
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# AcpcDealer
|
|
2
|
+
|
|
3
|
+
TODO: Write a gem description
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
Add this line to your application's Gemfile:
|
|
8
|
+
|
|
9
|
+
gem 'acpc_dealer'
|
|
10
|
+
|
|
11
|
+
And then execute:
|
|
12
|
+
|
|
13
|
+
$ bundle
|
|
14
|
+
|
|
15
|
+
Or install it yourself as:
|
|
16
|
+
|
|
17
|
+
$ gem install acpc_dealer
|
|
18
|
+
|
|
19
|
+
## Usage
|
|
20
|
+
|
|
21
|
+
TODO: Write usage instructions here
|
|
22
|
+
|
|
23
|
+
## Logging
|
|
24
|
+
|
|
25
|
+
For every match, two files will be logged: `<match name>.log` containing the match results and `<match name>.actions.log` containing the sequence of messages to and from the dealer over the course of the match. The location of these files can be customized with the :log_directory option. By default, they will be populated in the working directory of the calling process.
|
|
26
|
+
|
|
27
|
+
## Contributing
|
|
28
|
+
|
|
29
|
+
1. Fork it
|
|
30
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
|
31
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
|
32
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
|
33
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
require "bundler/gem_tasks"
|
|
2
|
+
require 'rake'
|
|
3
|
+
require 'rake/extensiontask'
|
|
4
|
+
require 'rake/testtask'
|
|
5
|
+
|
|
6
|
+
require File.expand_path('../lib/acpc_dealer/version', __FILE__)
|
|
7
|
+
|
|
8
|
+
Rake::ExtensionTask.new('hand_evaluator')
|
|
9
|
+
|
|
10
|
+
desc 'Build gem'
|
|
11
|
+
task :default => :build
|
|
12
|
+
|
|
13
|
+
task :build => :compile
|
|
14
|
+
|
|
15
|
+
Rake::TestTask.new do |t|
|
|
16
|
+
t.libs << "lib" << 'spec/support'
|
|
17
|
+
t.test_files = FileList['spec/**/*_spec.rb']
|
|
18
|
+
t.verbose = true
|
|
19
|
+
t.warning = true
|
|
20
|
+
end
|
data/acpc_dealer.gemspec
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
require File.expand_path('../lib/acpc_dealer/version', __FILE__)
|
|
3
|
+
|
|
4
|
+
Gem::Specification.new do |gem|
|
|
5
|
+
gem.name = "acpc_dealer"
|
|
6
|
+
gem.version = AcpcDealer::VERSION
|
|
7
|
+
gem.authors = ["Dustin Morrill"]
|
|
8
|
+
gem.email = ["morrill@ualberta.ca"]
|
|
9
|
+
gem.description = %q{Annual Computer Poker Competition Dealer}
|
|
10
|
+
gem.summary = %q{Ruby interface to the Annual Computer Poker Competition's dealer program.}
|
|
11
|
+
gem.homepage = "https://github.com/dmorrill10/acpc_dealer"
|
|
12
|
+
|
|
13
|
+
gem.add_dependency 'clive'
|
|
14
|
+
gem.add_dependency 'dmorrill10-utils', '~>1.0.0'
|
|
15
|
+
gem.add_dependency 'rake-compiler'
|
|
16
|
+
|
|
17
|
+
gem.add_development_dependency 'piston'
|
|
18
|
+
|
|
19
|
+
gem.add_development_dependency 'mocha'
|
|
20
|
+
gem.add_development_dependency 'simplecov'
|
|
21
|
+
gem.add_development_dependency 'turn'
|
|
22
|
+
|
|
23
|
+
gem.files = Dir.glob("lib/**/*") + Dir.glob("ext/**/*") + Dir.glob('*.gemspec') +
|
|
24
|
+
%w(Rakefile README.md) + Dir.glob('spec/**/*') + Dir.glob("vendor/**/*")
|
|
25
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
|
26
|
+
gem.extensions = Dir.glob("ext/**/extconf.rb")
|
|
27
|
+
gem.require_paths = ["lib"]
|
|
28
|
+
gem.executables << 'acpc_dealer'
|
|
29
|
+
end
|
data/bin/acpc_dealer
ADDED
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
require 'dmorrill10-utils/process_runner'
|
|
4
|
+
|
|
5
|
+
require 'fileutils'
|
|
6
|
+
|
|
7
|
+
require 'clive'
|
|
8
|
+
|
|
9
|
+
require File.expand_path('../../lib/acpc_dealer', __FILE__)
|
|
10
|
+
|
|
11
|
+
class AcpcDealerCli < Clive
|
|
12
|
+
|
|
13
|
+
def self.print_usage(command_symbol)
|
|
14
|
+
puts AcpcDealerCli.find_command(command_symbol).help
|
|
15
|
+
exit
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def self.game_def_from_components(number_of_players, betting_type)
|
|
19
|
+
begin
|
|
20
|
+
game_def = AcpcDealer::GAME_DEFINITION_FILE_PATHS[number_of_players][betting_type]
|
|
21
|
+
raise unless game_def
|
|
22
|
+
rescue
|
|
23
|
+
puts "Unable to find game definition for #{number_of_players} players with betting type '#{betting_type}'"
|
|
24
|
+
puts "Available game definitions:"
|
|
25
|
+
AcpcDealer::GAME_DEFINITION_FILE_PATHS.each do |num_players, game_defs|
|
|
26
|
+
game_defs.each do |type, path|
|
|
27
|
+
puts " #{num_players} #{type}"
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
exit
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
game_def
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
command :compile, 'Compiles the ACPC Dealer program' do
|
|
37
|
+
opt :c, :clean, 'Do a clean and full recompile' do
|
|
38
|
+
print 'Cleaning...'
|
|
39
|
+
FileUtils.cd AcpcDealer::DEALER_DIRECTORY do
|
|
40
|
+
system "make clean"
|
|
41
|
+
end
|
|
42
|
+
puts 'Done'
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
action do
|
|
46
|
+
print 'Compiling...'
|
|
47
|
+
FileUtils.cd AcpcDealer::DEALER_DIRECTORY do
|
|
48
|
+
system "make"
|
|
49
|
+
end
|
|
50
|
+
puts 'Done'
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
command :dealer, 'Runs the ACPC Dealer' do
|
|
55
|
+
desc 'The name of the match, defaults to <number_of_players>p.<betting_type>.h<hands>.r<random_seed>'
|
|
56
|
+
opt :m, :name, arg: '<name>', as: String
|
|
57
|
+
|
|
58
|
+
desc 'Parameters that determine which game definition to use'
|
|
59
|
+
opt :g, :game_def, args: '<number_of_players> <betting_type>', as: [Integer, Symbol]
|
|
60
|
+
|
|
61
|
+
opt :n, :hands, 'The number of hands to play', arg: '<hands>', as: Integer
|
|
62
|
+
|
|
63
|
+
desc 'The random seed to determine how the cards are dealt, defaults to a random random seed'
|
|
64
|
+
opt :r, :random_seed, arg: '<random_seed>', as: Integer
|
|
65
|
+
|
|
66
|
+
desc 'The names of the players participating in the match, defaults to "p1", "p2", ...'
|
|
67
|
+
opt :p, :player_names, args: '<p1_name>...', as: [String]
|
|
68
|
+
|
|
69
|
+
opt :l, :log_directory, 'Directory where logs will be placed', arg: '<log_directory>', as: String
|
|
70
|
+
|
|
71
|
+
opt :t_response, 'Maximum time per response', arg: '<t_response_milliseconds>', as: Integer
|
|
72
|
+
|
|
73
|
+
opt :t_hand, 'Maximum player time per hand', arg: '<t_hand_milliseconds>', as: Integer
|
|
74
|
+
|
|
75
|
+
opt :t_per_hand, 'Maximum average player time for match', arg: '<t_per_hand_milliseconds>', as: Integer
|
|
76
|
+
|
|
77
|
+
desc 'Maximum time to wait for players to connect, defaults to no timeout'
|
|
78
|
+
opt :start_timeout, arg: '<start_timeout_milliseconds>', as: Integer
|
|
79
|
+
|
|
80
|
+
action do
|
|
81
|
+
AcpcDealerCli.print_usage(:dealer) unless get(:game_def)
|
|
82
|
+
AcpcDealerCli.print_usage(:dealer) unless get(:hands)
|
|
83
|
+
|
|
84
|
+
(number_of_players, betting_type) = get(:game_def)
|
|
85
|
+
game_def = AcpcDealerCli.game_def_from_components(number_of_players, betting_type)
|
|
86
|
+
|
|
87
|
+
random_seed = if get(:random_seed)
|
|
88
|
+
get(:random_seed)
|
|
89
|
+
else
|
|
90
|
+
random_float = rand
|
|
91
|
+
(random_float * 10**random_float.to_s.length).to_i
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
name = if get(:name)
|
|
95
|
+
get(:name)
|
|
96
|
+
else
|
|
97
|
+
"#{number_of_players}p.#{betting_type}.h#{get(:hands)}.r#{random_seed}"
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
player_names = if get(:player_names)
|
|
101
|
+
get(:player_names)
|
|
102
|
+
else
|
|
103
|
+
[]
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
while player_names.length < get(:game_def).first
|
|
107
|
+
player_names << "p#{player_names.length+1}"
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
arguments = {
|
|
111
|
+
match_name: name,
|
|
112
|
+
game_def_file_name: game_def,
|
|
113
|
+
hands: get(:hands).to_s,
|
|
114
|
+
random_seed: random_seed.to_s,
|
|
115
|
+
player_names: player_names.join(' ')
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
# Append to produce behavior of previous dealer version
|
|
119
|
+
options = ['-a']
|
|
120
|
+
options << "--t_response #{get(:t_response_milliseconds)}" if get(:t_response_milliseconds)
|
|
121
|
+
options << "--t_hand #{get(:t_hand_milliseconds)}" if get(:t_hand_milliseconds)
|
|
122
|
+
options << "--t_per_hand #{get(:t_per_hand_milliseconds)}" if get(:t_per_hand_milliseconds)
|
|
123
|
+
options << "--start_timeout #{get(:start_timeout_milliseconds)}" if get(:start_timeout_milliseconds)
|
|
124
|
+
|
|
125
|
+
arguments[:options] = options
|
|
126
|
+
|
|
127
|
+
AcpcDealerCli.run(['compile']) unless File.exists? AcpcDealer::DEALER_PATH
|
|
128
|
+
|
|
129
|
+
dealer_result = DealerRunner.start(arguments, get(:log_directory))
|
|
130
|
+
puts "Dealer pid: #{dealer_result[:pid]}, ports: #{dealer_result[:port_numbers].join(' ')}, log directory: #{dealer_result[:log_directory]}"
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
command :example_player, 'Starts an example player' do
|
|
135
|
+
desc 'Parameters that determine which type of player to use, same format as that for the dealer command'
|
|
136
|
+
opt :g, :game_def, args: '<number_of_players> <betting_type>', as: [Integer, Symbol]
|
|
137
|
+
|
|
138
|
+
desc 'The host name of the running dealer, defaults to "localhost"'
|
|
139
|
+
opt :o, :host_name, arg: '<host_name>', as: String
|
|
140
|
+
|
|
141
|
+
desc 'The port on which this player will try to connect to the dealer'
|
|
142
|
+
opt :p, :port, arg: '<port>', as: String
|
|
143
|
+
|
|
144
|
+
action do
|
|
145
|
+
AcpcDealerCli.print_usage(:example_player) unless get(:game_def)
|
|
146
|
+
AcpcDealerCli.print_usage(:example_player) unless get(:port)
|
|
147
|
+
|
|
148
|
+
(number_of_players, betting_type) = get(:game_def)
|
|
149
|
+
# Check that a game def for the specified parameters exists
|
|
150
|
+
AcpcDealerCli.game_def_from_components(number_of_players, betting_type)
|
|
151
|
+
|
|
152
|
+
host_name = if get(:host_name) then get(:host_name) else 'localhost' end
|
|
153
|
+
|
|
154
|
+
player = AcpcDealer::EXAMPLE_PLAYERS[number_of_players][betting_type]
|
|
155
|
+
players_directory = File.dirname(player)
|
|
156
|
+
FileUtils.cd players_directory
|
|
157
|
+
ProcessRunner.go [player, host_name, get(:port)]
|
|
158
|
+
|
|
159
|
+
puts "Example player for #{number_of_players} player #{betting_type}, connected to dealer on #{host_name}:#{get(:port)}"
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
if ARGV.empty?
|
|
165
|
+
puts AcpcDealerCli.help
|
|
166
|
+
else
|
|
167
|
+
AcpcDealerCli.run
|
|
168
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// Ruby includes
|
|
2
|
+
#include <ruby.h>
|
|
3
|
+
#include <ruby/io.h>
|
|
4
|
+
|
|
5
|
+
// ACPC includes
|
|
6
|
+
#include "../../vendor/project_acpc_server/game.h"
|
|
7
|
+
#include "../../vendor/project_acpc_server/evalHandTables"
|
|
8
|
+
|
|
9
|
+
static VALUE cHandEvaluator;
|
|
10
|
+
|
|
11
|
+
/*
|
|
12
|
+
* @param [VALUE] self The class from which this method was called. This is
|
|
13
|
+
* an implicit argument.
|
|
14
|
+
* @param [VALUE] ruby_card_list The list of numeric ACPC represented cards in
|
|
15
|
+
* a Ruby array.
|
|
16
|
+
* @return [int] The rank of the hand.
|
|
17
|
+
*/
|
|
18
|
+
static VALUE rank_hand(VALUE self, VALUE ruby_card_list) {
|
|
19
|
+
VALUE* card_list = RARRAY_PTR(ruby_card_list);
|
|
20
|
+
int card_list_length = RARRAY_LEN(ruby_card_list);
|
|
21
|
+
|
|
22
|
+
int card;
|
|
23
|
+
Cardset card_set = emptyCardset();
|
|
24
|
+
|
|
25
|
+
int i;
|
|
26
|
+
for(i = 0; i < card_list_length; ++i) {
|
|
27
|
+
card = NUM2INT(card_list[i]);
|
|
28
|
+
addCardToCardset(&card_set, suitOfCard(card),
|
|
29
|
+
rankOfCard(card));
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return INT2NUM(rankCardset(card_set));
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
void Init_hand_evaluator() {
|
|
36
|
+
cHandEvaluator = rb_define_module("HandEvaluator");
|
|
37
|
+
rb_define_module_function(cHandEvaluator, "rank_hand", rank_hand, 1);
|
|
38
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
|
|
2
|
+
require 'socket'
|
|
3
|
+
|
|
4
|
+
require 'dmorrill10-utils/process_runner'
|
|
5
|
+
|
|
6
|
+
class DealerRunner
|
|
7
|
+
|
|
8
|
+
# @return [Array<Symbol>] The format of the dealer command. The symbols in this
|
|
9
|
+
# => array should correspond to those in the +dealer_arguments+ of ::start.
|
|
10
|
+
# => (see ::start)
|
|
11
|
+
DEALER_COMMAND_FORMAT = [
|
|
12
|
+
# @note The name of the match to start.
|
|
13
|
+
:match_name,
|
|
14
|
+
# @note The path of the game definition to use.
|
|
15
|
+
:game_def_file_name,
|
|
16
|
+
# @note The number of hands to play.
|
|
17
|
+
:hands,
|
|
18
|
+
# @note The random seed to use.
|
|
19
|
+
:random_seed,
|
|
20
|
+
# @note The names of the players in the game. Should be specified as a space delimited string of names.
|
|
21
|
+
:player_names,
|
|
22
|
+
# @note Should be specified as an option string that the dealer will understand.
|
|
23
|
+
:options
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
# @param [Array] dealer_arguments Arguments to the new dealer instance.
|
|
27
|
+
# @param [String] log_directory The directory in which logs will be placed.
|
|
28
|
+
# => Defaults to +<dealer_arguments[:match_name]>.logs+.
|
|
29
|
+
# @param [Array] port_numbers The port numbers to which each player will connect.
|
|
30
|
+
# => Defaults to random.
|
|
31
|
+
# @return [Hash] The process ID of the started dealer (key +:pid+) and the array of ports that players may
|
|
32
|
+
# => use to connect to the new dealer instance (key +:port_numbers+).
|
|
33
|
+
# @raise (see ProcessRunner::go)
|
|
34
|
+
# @raise (see FileUtils::mkdir_p)
|
|
35
|
+
def self.start(dealer_arguments, log_directory=nil, port_numbers=nil)
|
|
36
|
+
dealer_start_command = DEALER_COMMAND_FORMAT.inject([AcpcDealer::DEALER_PATH]) do |command, parameter|
|
|
37
|
+
command << dealer_arguments[parameter].to_s
|
|
38
|
+
end
|
|
39
|
+
dealer_start_command << "-p #{port_numbers.join(',')}" if port_numbers
|
|
40
|
+
|
|
41
|
+
unless log_directory
|
|
42
|
+
log_directory = File.expand_path("../#{dealer_arguments[:match_name]}.logs", __FILE__)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
FileUtils.mkdir_p log_directory
|
|
46
|
+
|
|
47
|
+
IO.pipe do |read_io, write_io|
|
|
48
|
+
pid = ProcessRunner.go(
|
|
49
|
+
dealer_start_command,
|
|
50
|
+
err: [
|
|
51
|
+
"#{dealer_arguments[:match_name]}.actions.log",
|
|
52
|
+
File::CREAT|File::WRONLY
|
|
53
|
+
],
|
|
54
|
+
out: write_io,
|
|
55
|
+
chdir: log_directory
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
{pid: pid, port_numbers: read_io.gets.split, log_directory: log_directory}
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# @todo How could ports be reserved without starting a server? Would +::ports_for_players+ even want to do that?
|
|
63
|
+
|
|
64
|
+
# @return [Array<Integer>] List of random open ports. Does NOT reserve the ports though,
|
|
65
|
+
# => so it's possible that the ports will come into use between calling this method and
|
|
66
|
+
# => using them.
|
|
67
|
+
def self.ports_for_players(number_of_players)
|
|
68
|
+
number_of_players.times.inject([]) do |ports, i|
|
|
69
|
+
ports << TCPServer.open('localhost', 0) { |s| s.addr[1] }
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
data/lib/acpc_dealer.rb
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
require File.expand_path('../hand_evaluator', __FILE__)
|
|
2
|
+
require File.expand_path("../acpc_dealer/dealer_runner", __FILE__)
|
|
3
|
+
|
|
4
|
+
module AcpcDealer
|
|
5
|
+
DEALER_DIRECTORY = File.expand_path('../../vendor/project_acpc_server', __FILE__)
|
|
6
|
+
GAME_DEFINITION_FILE_PATHS =
|
|
7
|
+
{
|
|
8
|
+
2 =>
|
|
9
|
+
{
|
|
10
|
+
limit: "#{DEALER_DIRECTORY}/holdem.limit.2p.reverse_blinds.game",
|
|
11
|
+
nolimit: "#{DEALER_DIRECTORY}/holdem.nolimit.2p.reverse_blinds.game"
|
|
12
|
+
},
|
|
13
|
+
3 =>
|
|
14
|
+
{
|
|
15
|
+
limit: "#{DEALER_DIRECTORY}/holdem.limit.3p.game",
|
|
16
|
+
nolimit: "#{DEALER_DIRECTORY}/holdem.nolimit.3p.game"
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
DEALER_PATH = "#{DEALER_DIRECTORY}/dealer"
|
|
20
|
+
EXAMPLE_PLAYERS =
|
|
21
|
+
{
|
|
22
|
+
2 =>
|
|
23
|
+
{
|
|
24
|
+
limit: "#{DEALER_DIRECTORY}/example_player.limit.2p.sh",
|
|
25
|
+
nolimit: "#{DEALER_DIRECTORY}/example_player.nolimit.2p.sh"
|
|
26
|
+
},
|
|
27
|
+
3 =>
|
|
28
|
+
{
|
|
29
|
+
limit: "#{DEALER_DIRECTORY}/example_player.limit.3p.sh",
|
|
30
|
+
nolimit: "#{DEALER_DIRECTORY}/example_player.nolimit.3p.sh"
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
end
|
|
Binary file
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
$(document).ready(function() {
|
|
2
|
+
// Configuration for fancy sortable tables for source file groups
|
|
3
|
+
$('.file_list').dataTable({
|
|
4
|
+
"aaSorting": [[ 1, "asc" ]],
|
|
5
|
+
"bPaginate": false,
|
|
6
|
+
"bJQueryUI": true,
|
|
7
|
+
"aoColumns": [
|
|
8
|
+
null,
|
|
9
|
+
{ "sType": "percent" },
|
|
10
|
+
null,
|
|
11
|
+
null,
|
|
12
|
+
null,
|
|
13
|
+
null,
|
|
14
|
+
null
|
|
15
|
+
]
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
// Syntax highlight all files up front - deactivated
|
|
19
|
+
// $('.source_table pre code').each(function(i, e) {hljs.highlightBlock(e, ' ')});
|
|
20
|
+
|
|
21
|
+
// Syntax highlight source files on first toggle of the file view popup
|
|
22
|
+
$("a.src_link").click(function() {
|
|
23
|
+
// Get the source file element that corresponds to the clicked element
|
|
24
|
+
var source_table = $($(this).attr('href'));
|
|
25
|
+
|
|
26
|
+
// If not highlighted yet, do it!
|
|
27
|
+
if (!source_table.hasClass('highlighted')) {
|
|
28
|
+
source_table.find('pre code').each(function(i, e) {hljs.highlightBlock(e, ' ')});
|
|
29
|
+
source_table.addClass('highlighted');
|
|
30
|
+
};
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
// Set-up of popup for source file views
|
|
34
|
+
$("a.src_link").fancybox({
|
|
35
|
+
'hideOnContentClick': true,
|
|
36
|
+
'centerOnScroll': true,
|
|
37
|
+
'width': '90%',
|
|
38
|
+
'padding': 0,
|
|
39
|
+
'transitionIn': 'elastic'
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
// Hide src files and file list container after load
|
|
43
|
+
$('.source_files').hide();
|
|
44
|
+
$('.file_list_container').hide();
|
|
45
|
+
|
|
46
|
+
// Add tabs based upon existing file_list_containers
|
|
47
|
+
$('.file_list_container h2').each(function(){
|
|
48
|
+
var container_id = $(this).parent().attr('id');
|
|
49
|
+
var group_name = $(this).find('.group_name').first().html();
|
|
50
|
+
var covered_percent = $(this).find('.covered_percent').first().html();
|
|
51
|
+
|
|
52
|
+
$('.group_tabs').append('<li><a href="#' + container_id + '">' + group_name + ' ('+ covered_percent +')</a></li>');
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
$('.group_tabs a').each( function() {
|
|
56
|
+
$(this).addClass($(this).attr('href').replace('#', ''));
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
// Make sure tabs don't get ugly focus borders when active
|
|
60
|
+
$('.group_tabs a').live('focus', function() { $(this).blur(); });
|
|
61
|
+
|
|
62
|
+
var favicon_path = $('link[rel="shortcut icon"]').attr('href');
|
|
63
|
+
$('.group_tabs a').live('click', function(){
|
|
64
|
+
if (!$(this).parent().hasClass('active')) {
|
|
65
|
+
$('.group_tabs a').parent().removeClass('active');
|
|
66
|
+
$(this).parent().addClass('active');
|
|
67
|
+
$('.file_list_container').hide();
|
|
68
|
+
$(".file_list_container" + $(this).attr('href')).show();
|
|
69
|
+
window.location.href = window.location.href.split('#')[0] + $(this).attr('href').replace('#', '#_');
|
|
70
|
+
|
|
71
|
+
// Force favicon reload - otherwise the location change containing anchor would drop the favicon...
|
|
72
|
+
// Works only on firefox, but still... - Anyone know a better solution to force favicon on local file?
|
|
73
|
+
$('link[rel="shortcut icon"]').remove();
|
|
74
|
+
$('head').append('<link rel="shortcut icon" type="image/png" href="'+ favicon_path +'" />');
|
|
75
|
+
};
|
|
76
|
+
return false;
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
if (jQuery.url.attr('anchor')) {
|
|
80
|
+
$('.group_tabs a.'+jQuery.url.attr('anchor').replace('_', '')).click();
|
|
81
|
+
} else {
|
|
82
|
+
$('.group_tabs a:first').click();
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
$("abbr.timeago").timeago();
|
|
86
|
+
$('#loading').fadeOut();
|
|
87
|
+
$('#wrapper').show();
|
|
88
|
+
});
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|