acpc_dealer 2.4.1 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Brickfile +6 -0
- data/README.md +7 -6
- data/Rakefile +30 -14
- data/acpc_dealer.gemspec +2 -1
- data/bin/acpc_dealer +4 -0
- data/ext/hand_evaluator/extconf.rb +10 -0
- data/lib/acpc_dealer/version.rb +1 -1
- data/lib/hand_evaluator.bundle +0 -0
- data/spec/dealer_runner_spec.rb +76 -72
- metadata +19 -82
- data/vendor/project_acpc_server/LICENCE +0 -23
- data/vendor/project_acpc_server/Makefile +0 -35
- data/vendor/project_acpc_server/README +0 -113
- data/vendor/project_acpc_server/README.submission +0 -42
- data/vendor/project_acpc_server/acpc_play_match.pl +0 -101
- data/vendor/project_acpc_server/bm_run_matches.c +0 -238
- data/vendor/project_acpc_server/bm_server.c +0 -1604
- data/vendor/project_acpc_server/bm_server.config +0 -78
- data/vendor/project_acpc_server/bm_widget.c +0 -230
- data/vendor/project_acpc_server/dealer.c +0 -1293
- data/vendor/project_acpc_server/evalHandTables +0 -4269
- data/vendor/project_acpc_server/example_player.c +0 -204
- data/vendor/project_acpc_server/example_player.limit.2p.sh +0 -3
- data/vendor/project_acpc_server/example_player.limit.3p.sh +0 -3
- data/vendor/project_acpc_server/example_player.nolimit.2p.sh +0 -3
- data/vendor/project_acpc_server/example_player.nolimit.3p.sh +0 -3
- data/vendor/project_acpc_server/game.c +0 -1792
- data/vendor/project_acpc_server/game.h +0 -253
- data/vendor/project_acpc_server/holdem.limit.2p.reverse_blinds.game +0 -13
- data/vendor/project_acpc_server/holdem.limit.3p.game +0 -13
- data/vendor/project_acpc_server/holdem.nolimit.2p.reverse_blinds.game +0 -12
- data/vendor/project_acpc_server/holdem.nolimit.3p.game +0 -12
- data/vendor/project_acpc_server/kuhn.limit.3p.game +0 -14
- data/vendor/project_acpc_server/kuhn_3p_equilibrium_player.sf1.sh +0 -3
- data/vendor/project_acpc_server/kuhn_3p_equilibrium_player.sf2.sh +0 -3
- data/vendor/project_acpc_server/kuhn_3p_equilibrium_player.sf3.sh +0 -3
- data/vendor/project_acpc_server/kuhn_3p_equilibrium_player/LICENCE +0 -23
- data/vendor/project_acpc_server/kuhn_3p_equilibrium_player/Makefile +0 -127
- data/vendor/project_acpc_server/kuhn_3p_equilibrium_player/README.md +0 -35
- data/vendor/project_acpc_server/kuhn_3p_equilibrium_player/src/CExceptionConfig.h +0 -12
- data/vendor/project_acpc_server/kuhn_3p_equilibrium_player/src/dealer_connection.c +0 -49
- data/vendor/project_acpc_server/kuhn_3p_equilibrium_player/src/dealer_connection.h +0 -22
- data/vendor/project_acpc_server/kuhn_3p_equilibrium_player/src/kuhn_3p_equilibrium_player.c +0 -483
- data/vendor/project_acpc_server/kuhn_3p_equilibrium_player/src/kuhn_3p_equilibrium_player.h +0 -108
- data/vendor/project_acpc_server/kuhn_3p_equilibrium_player/src/main.c +0 -84
- data/vendor/project_acpc_server/kuhn_3p_equilibrium_player/src/player_config.c +0 -253
- data/vendor/project_acpc_server/kuhn_3p_equilibrium_player/src/player_config.h +0 -21
- data/vendor/project_acpc_server/kuhn_3p_equilibrium_player/test/support/test_helper.c +0 -45
- data/vendor/project_acpc_server/kuhn_3p_equilibrium_player/test/support/test_helper.h +0 -27
- data/vendor/project_acpc_server/kuhn_3p_equilibrium_player/test/test_kuhn_3p_equilibrium_player.c +0 -698
- data/vendor/project_acpc_server/kuhn_3p_equilibrium_player/test/test_kuhn_3p_equilibrium_player_sub_family_1.c +0 -324
- data/vendor/project_acpc_server/kuhn_3p_equilibrium_player/test/test_kuhn_3p_equilibrium_player_sub_family_2.c +0 -262
- data/vendor/project_acpc_server/kuhn_3p_equilibrium_player/test/test_kuhn_3p_equilibrium_player_sub_family_3.c +0 -177
- data/vendor/project_acpc_server/kuhn_3p_equilibrium_player/vendor/cexception/docs/license.txt +0 -30
- data/vendor/project_acpc_server/kuhn_3p_equilibrium_player/vendor/cexception/docs/readme.txt +0 -242
- data/vendor/project_acpc_server/kuhn_3p_equilibrium_player/vendor/cexception/lib/CException.c +0 -43
- data/vendor/project_acpc_server/kuhn_3p_equilibrium_player/vendor/cexception/lib/CException.h +0 -86
- data/vendor/project_acpc_server/kuhn_3p_equilibrium_player/vendor/cexception/release/build.info +0 -2
- data/vendor/project_acpc_server/kuhn_3p_equilibrium_player/vendor/cexception/release/version.info +0 -2
- data/vendor/project_acpc_server/kuhn_3p_equilibrium_player/vendor/commander.c/History.md +0 -27
- data/vendor/project_acpc_server/kuhn_3p_equilibrium_player/vendor/commander.c/Makefile +0 -8
- data/vendor/project_acpc_server/kuhn_3p_equilibrium_player/vendor/commander.c/Readme.md +0 -103
- data/vendor/project_acpc_server/kuhn_3p_equilibrium_player/vendor/commander.c/package.json +0 -9
- data/vendor/project_acpc_server/kuhn_3p_equilibrium_player/vendor/commander.c/src/commander.c +0 -250
- data/vendor/project_acpc_server/kuhn_3p_equilibrium_player/vendor/commander.c/src/commander.h +0 -88
- data/vendor/project_acpc_server/kuhn_3p_equilibrium_player/vendor/commander.c/test.c +0 -34
- data/vendor/project_acpc_server/kuhn_3p_equilibrium_player/vendor/unity/auto/colour_prompt.rb +0 -94
- data/vendor/project_acpc_server/kuhn_3p_equilibrium_player/vendor/unity/auto/colour_reporter.rb +0 -39
- data/vendor/project_acpc_server/kuhn_3p_equilibrium_player/vendor/unity/auto/generate_config.yml +0 -36
- data/vendor/project_acpc_server/kuhn_3p_equilibrium_player/vendor/unity/auto/generate_module.rb +0 -202
- data/vendor/project_acpc_server/kuhn_3p_equilibrium_player/vendor/unity/auto/generate_test_runner.rb +0 -316
- data/vendor/project_acpc_server/kuhn_3p_equilibrium_player/vendor/unity/auto/test_file_filter.rb +0 -23
- data/vendor/project_acpc_server/kuhn_3p_equilibrium_player/vendor/unity/auto/unity_test_summary.rb +0 -139
- data/vendor/project_acpc_server/kuhn_3p_equilibrium_player/vendor/unity/docs/Unity Summary.txt +0 -216
- data/vendor/project_acpc_server/kuhn_3p_equilibrium_player/vendor/unity/docs/license.txt +0 -31
- data/vendor/project_acpc_server/kuhn_3p_equilibrium_player/vendor/unity/release/build.info +0 -2
- data/vendor/project_acpc_server/kuhn_3p_equilibrium_player/vendor/unity/release/version.info +0 -2
- data/vendor/project_acpc_server/kuhn_3p_equilibrium_player/vendor/unity/src/unity.c +0 -1146
- data/vendor/project_acpc_server/kuhn_3p_equilibrium_player/vendor/unity/src/unity.h +0 -245
- data/vendor/project_acpc_server/kuhn_3p_equilibrium_player/vendor/unity/src/unity_internals.h +0 -546
- data/vendor/project_acpc_server/net.c +0 -218
- data/vendor/project_acpc_server/net.h +0 -62
- data/vendor/project_acpc_server/play_match.pl +0 -99
- data/vendor/project_acpc_server/protocol.md +0 -239
- 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 +0 -139
- data/vendor/project_acpc_server/rng.h +0 -63
- data/vendor/project_acpc_server/validate_submission.pl +0 -546
@@ -1,218 +0,0 @@
|
|
1
|
-
/*
|
2
|
-
Copyright (C) 2011 by the Computer Poker Research Group, University of Alberta
|
3
|
-
*/
|
4
|
-
|
5
|
-
#include <unistd.h>
|
6
|
-
#include <netdb.h>
|
7
|
-
#include <string.h>
|
8
|
-
#include <sys/socket.h>
|
9
|
-
#include <sys/time.h>
|
10
|
-
#include <netinet/in.h>
|
11
|
-
#include <netinet/tcp.h>
|
12
|
-
#include "net.h"
|
13
|
-
|
14
|
-
|
15
|
-
ReadBuf *createReadBuf( int fd )
|
16
|
-
{
|
17
|
-
ReadBuf *readBuf = (ReadBuf*)malloc( sizeof( ReadBuf ) );
|
18
|
-
if( readBuf == 0 ) {
|
19
|
-
|
20
|
-
return readBuf;
|
21
|
-
}
|
22
|
-
|
23
|
-
readBuf->fd = fd;
|
24
|
-
readBuf->bufStart = 0;
|
25
|
-
readBuf->bufEnd = 0;
|
26
|
-
|
27
|
-
return readBuf;
|
28
|
-
}
|
29
|
-
|
30
|
-
void destroyReadBuf( ReadBuf *readBuf )
|
31
|
-
{
|
32
|
-
close( readBuf->fd );
|
33
|
-
free( readBuf );
|
34
|
-
}
|
35
|
-
|
36
|
-
/* get a newline terminated line and place it as a string in 'line'
|
37
|
-
terminates the string with a 0 character
|
38
|
-
if timeoutMicros is non-negative, do not spend more than
|
39
|
-
that number of microseconds waiting to read data
|
40
|
-
return number of characters read (including newline, excluding 0)
|
41
|
-
0 on end of file, or -1 on error or timeout */
|
42
|
-
ssize_t getLine( ReadBuf *readBuf,
|
43
|
-
size_t maxLen,
|
44
|
-
char *line,
|
45
|
-
int64_t timeoutMicros )
|
46
|
-
{
|
47
|
-
int haveStartTime, c;
|
48
|
-
ssize_t len;
|
49
|
-
fd_set fds;
|
50
|
-
struct timeval start, tv;
|
51
|
-
|
52
|
-
/* reserve space for string terminator */
|
53
|
-
--maxLen;
|
54
|
-
if( maxLen < 0 ) {
|
55
|
-
return -1;
|
56
|
-
}
|
57
|
-
|
58
|
-
/* read the line */
|
59
|
-
haveStartTime = 0;
|
60
|
-
len = 0;
|
61
|
-
while( len < maxLen ) {
|
62
|
-
|
63
|
-
if( readBuf->bufStart >= readBuf->bufEnd ) {
|
64
|
-
/* buffer is empty */
|
65
|
-
|
66
|
-
if( timeoutMicros >= 0 ) {
|
67
|
-
/* figure out how much time is left for reading */
|
68
|
-
uint64_t timeLeft;
|
69
|
-
|
70
|
-
timeLeft = timeoutMicros;
|
71
|
-
if( haveStartTime ) {
|
72
|
-
|
73
|
-
gettimeofday( &tv, NULL );
|
74
|
-
timeLeft -= (uint64_t)( tv.tv_sec - start.tv_sec ) * 1000000
|
75
|
-
+ ( tv.tv_usec - start.tv_usec );
|
76
|
-
if( timeLeft < 0 ) {
|
77
|
-
|
78
|
-
timeLeft = 0;
|
79
|
-
}
|
80
|
-
} else {
|
81
|
-
|
82
|
-
haveStartTime = 1;
|
83
|
-
gettimeofday( &start, NULL );
|
84
|
-
}
|
85
|
-
tv.tv_sec = timeLeft / 1000000;
|
86
|
-
tv.tv_usec = timeLeft % 1000000;
|
87
|
-
|
88
|
-
/* wait for file descriptor to be ready */
|
89
|
-
FD_ZERO( &fds );
|
90
|
-
FD_SET( readBuf->fd, &fds );
|
91
|
-
if( select( readBuf->fd + 1, &fds, NULL, NULL, &tv ) < 1 ) {
|
92
|
-
/* no input ready within time, or an actual error */
|
93
|
-
|
94
|
-
return -1;
|
95
|
-
}
|
96
|
-
}
|
97
|
-
|
98
|
-
/* try reading a buffer full of data */
|
99
|
-
readBuf->bufStart = 0;
|
100
|
-
readBuf->bufEnd = read( readBuf->fd, readBuf->buf, READBUF_LEN );
|
101
|
-
if( readBuf->bufEnd == 0 ) {
|
102
|
-
/* end of input */
|
103
|
-
|
104
|
-
break;
|
105
|
-
} else if( readBuf->bufEnd < 0 ) {
|
106
|
-
/* error condition */
|
107
|
-
|
108
|
-
readBuf->bufEnd = 0;
|
109
|
-
return -1;
|
110
|
-
}
|
111
|
-
}
|
112
|
-
|
113
|
-
/* keep adding to the string until we see a newline */
|
114
|
-
c = readBuf->buf[ readBuf->bufStart ];
|
115
|
-
++readBuf->bufStart;
|
116
|
-
line[ len ] = c;
|
117
|
-
++len;
|
118
|
-
if( c == '\n' ) {
|
119
|
-
|
120
|
-
break;
|
121
|
-
}
|
122
|
-
}
|
123
|
-
|
124
|
-
/* terminate the string */
|
125
|
-
line[ len ] = 0;
|
126
|
-
return len;
|
127
|
-
}
|
128
|
-
|
129
|
-
|
130
|
-
int connectTo( char *hostname, uint16_t port )
|
131
|
-
{
|
132
|
-
int sock;
|
133
|
-
struct hostent *hostent;
|
134
|
-
struct sockaddr_in addr;
|
135
|
-
|
136
|
-
hostent = gethostbyname( hostname );
|
137
|
-
if( hostent == NULL ) {
|
138
|
-
|
139
|
-
fprintf( stderr, "ERROR: could not look up address for %s\n", hostname );
|
140
|
-
return -1;
|
141
|
-
}
|
142
|
-
|
143
|
-
if( ( sock = socket( AF_INET, SOCK_STREAM, 0 ) ) < 0 ) {
|
144
|
-
|
145
|
-
fprintf( stderr, "ERROR: could not open socket\n" );
|
146
|
-
return -1;
|
147
|
-
}
|
148
|
-
|
149
|
-
addr.sin_family = AF_INET;
|
150
|
-
addr.sin_port = htons( port );
|
151
|
-
memcpy( &addr.sin_addr, hostent->h_addr_list[ 0 ], hostent->h_length );
|
152
|
-
|
153
|
-
if( connect( sock, (struct sockaddr *)&addr, sizeof( addr ) ) < 0 ) {
|
154
|
-
|
155
|
-
fprintf( stderr, "ERROR: could not connect to %s:%"PRIu16"\n",
|
156
|
-
hostname, port );
|
157
|
-
return -1;
|
158
|
-
}
|
159
|
-
|
160
|
-
return sock;
|
161
|
-
}
|
162
|
-
|
163
|
-
int getListenSocket( uint16_t *desiredPort )
|
164
|
-
{
|
165
|
-
int sock, t;
|
166
|
-
struct sockaddr_in addr;
|
167
|
-
|
168
|
-
if( ( sock = socket( AF_INET, SOCK_STREAM, 0 ) ) < 0 ) {
|
169
|
-
|
170
|
-
return -1;
|
171
|
-
}
|
172
|
-
|
173
|
-
/* allow fast socket reuse - ignore failure */
|
174
|
-
t = 1;
|
175
|
-
setsockopt( sock, SOL_SOCKET, SO_REUSEADDR, &t, sizeof( int ) );
|
176
|
-
|
177
|
-
/* bind the socket to the port */
|
178
|
-
if( *desiredPort != 0 ) {
|
179
|
-
|
180
|
-
addr.sin_family = AF_INET;
|
181
|
-
addr.sin_port = htons( *desiredPort );
|
182
|
-
addr.sin_addr.s_addr = htonl( INADDR_ANY );
|
183
|
-
if( bind( sock, (struct sockaddr *)&addr, sizeof( addr ) ) < 0 ) {
|
184
|
-
|
185
|
-
return -1;
|
186
|
-
}
|
187
|
-
} else {
|
188
|
-
|
189
|
-
t = 0;
|
190
|
-
while( 1 ) {
|
191
|
-
addr.sin_family = AF_INET;
|
192
|
-
*desiredPort = ( random() % 64512 ) + 1024;
|
193
|
-
addr.sin_port = htons( *desiredPort );
|
194
|
-
addr.sin_addr.s_addr = htonl( INADDR_ANY );
|
195
|
-
if( bind( sock, (struct sockaddr *)&addr, sizeof( addr ) ) < 0 ) {
|
196
|
-
|
197
|
-
if( t < NUM_PORT_CREATION_ATTEMPTS ) {
|
198
|
-
|
199
|
-
++t;
|
200
|
-
continue;
|
201
|
-
} else {
|
202
|
-
|
203
|
-
return -1;
|
204
|
-
}
|
205
|
-
}
|
206
|
-
|
207
|
-
break;
|
208
|
-
}
|
209
|
-
}
|
210
|
-
|
211
|
-
/* listen on the socket */
|
212
|
-
if( listen( sock, 8 ) < 0 ) {
|
213
|
-
|
214
|
-
return -1;
|
215
|
-
}
|
216
|
-
|
217
|
-
return sock;
|
218
|
-
}
|
@@ -1,62 +0,0 @@
|
|
1
|
-
/*
|
2
|
-
Copyright (C) 2011 by the Computer Poker Research Group, University of Alberta
|
3
|
-
*/
|
4
|
-
|
5
|
-
#ifndef _NET_H
|
6
|
-
#define _NET_H
|
7
|
-
|
8
|
-
#include <stdlib.h>
|
9
|
-
#include <stdio.h>
|
10
|
-
#include <sys/types.h>
|
11
|
-
#define __STDC_FORMAT_MACROS
|
12
|
-
#include <inttypes.h>
|
13
|
-
|
14
|
-
|
15
|
-
#define READBUF_LEN 4096
|
16
|
-
#define NUM_PORT_CREATION_ATTEMPTS 10
|
17
|
-
|
18
|
-
|
19
|
-
/* buffered I/O on file descriptors
|
20
|
-
|
21
|
-
Yes... this is basically re-implementing bits of a standard FILE.
|
22
|
-
Unfortunately, trying to mix timeouts and FILE streams either
|
23
|
-
a) doesn't work, or b) is fairly system specific */
|
24
|
-
typedef struct {
|
25
|
-
int fd;
|
26
|
-
int bufStart;
|
27
|
-
int bufEnd;
|
28
|
-
char buf[ READBUF_LEN ];
|
29
|
-
} ReadBuf;
|
30
|
-
|
31
|
-
|
32
|
-
/* open a socket to hostname/port
|
33
|
-
returns file descriptor on success, <0 on failure */
|
34
|
-
int connectTo( char *hostname, uint16_t port );
|
35
|
-
|
36
|
-
/* try opening a socket suitable for connecting to
|
37
|
-
if *desiredPort>0, uses specified port, otherwise use a random port
|
38
|
-
returns actual port in *desiredPort
|
39
|
-
returns file descriptor for socket, or -1 on failure */
|
40
|
-
int getListenSocket( uint16_t *desiredPort );
|
41
|
-
|
42
|
-
|
43
|
-
/* create a read buffer structure
|
44
|
-
returns 0 on failure */
|
45
|
-
ReadBuf *createReadBuf( int fd );
|
46
|
-
|
47
|
-
/* destroy a read buffer - like fdopen, it will close the file descriptor */
|
48
|
-
void destroyReadBuf( ReadBuf *readBuf );
|
49
|
-
|
50
|
-
/* get a newline terminated line and place it as a string in 'line'
|
51
|
-
terminates the string with a 0 character
|
52
|
-
if timeoutMicros is non-negative, do not spend more than
|
53
|
-
that number of microseconds waiting to read data
|
54
|
-
return number of characters read (including newline, excluding 0)
|
55
|
-
0 on end of file, or -1 on error or timeout */
|
56
|
-
ssize_t getLine( ReadBuf *readBuf,
|
57
|
-
size_t maxLen,
|
58
|
-
char *line,
|
59
|
-
int64_t timeoutMicros );
|
60
|
-
|
61
|
-
|
62
|
-
#endif
|
@@ -1,99 +0,0 @@
|
|
1
|
-
#!/usr/bin/perl
|
2
|
-
|
3
|
-
# Copyright (C) 2011 by the Computer Poker Research Group, University of Alberta
|
4
|
-
|
5
|
-
use Socket;
|
6
|
-
|
7
|
-
$hostname = `hostname` or die "could not get hostname";
|
8
|
-
chomp $hostname;
|
9
|
-
@hostent = gethostbyname( $hostname );
|
10
|
-
$#hostent >= 4 or die "could not look up $hostname";
|
11
|
-
$hostip = inet_ntoa( $hostent[ 4 ] );
|
12
|
-
|
13
|
-
$#ARGV >= 3 or die "usage: play_match.pl matchName gameDefFile #Hands rngSeed player1name player1exe player2name player2exe ... [options]";
|
14
|
-
|
15
|
-
$numPlayers = -1;
|
16
|
-
open FILE, '<', $ARGV[ 1 ] or die "couldn't open game definition $ARGV[ 1 ]";
|
17
|
-
while( $_ = <FILE> ) {
|
18
|
-
|
19
|
-
@_ = split;
|
20
|
-
|
21
|
-
if( uc( $_[ 0 ] ) eq 'NUMPLAYERS' ) {
|
22
|
-
$numPlayers = $_[ $#_ ];
|
23
|
-
}
|
24
|
-
}
|
25
|
-
close FILE;
|
26
|
-
|
27
|
-
$numPlayers > 1 or die "couldn't get number of players from $ARGV[ 1 ]";
|
28
|
-
|
29
|
-
|
30
|
-
$#ARGV >= 3 + $numPlayers * 2 or die "too few players on command line";
|
31
|
-
|
32
|
-
pipe STDINREADPIPE, STDINWRITEPIPE or die "couldn't create stdin pipe";
|
33
|
-
pipe STDOUTREADPIPE, STDOUTWRITEPIPE or die "couldn't create stdout pipe";
|
34
|
-
|
35
|
-
$dealerPID = fork();
|
36
|
-
if( $dealerPID == 0 ) {
|
37
|
-
# we're the child
|
38
|
-
|
39
|
-
# replace standard in and standard out with pipe
|
40
|
-
close STDINWRITEPIPE;
|
41
|
-
close STDOUTREADPIPE;
|
42
|
-
open STDIN, '<&STDINREADPIPE' or die "can't dup STDIN";
|
43
|
-
open STDOUT, '>&STDOUTWRITEPIPE' or die "can't dup STDOUT";
|
44
|
-
open STDERR, ">>$ARGV[ 0 ].err" or die "can't open log file $ARGV[ 0 ].err";
|
45
|
-
|
46
|
-
@args = ( "dealer", $ARGV[ 0 ], $ARGV[ 1 ],
|
47
|
-
$ARGV[ 2 ], $ARGV[ 3 ] );
|
48
|
-
|
49
|
-
# add names to the arguments
|
50
|
-
for( $p = 0; $p < $numPlayers; ++$p ) {
|
51
|
-
push @args, $ARGV[ 4 + $p * 2 ];
|
52
|
-
}
|
53
|
-
|
54
|
-
# add any extra arguments (options?) to the arguments
|
55
|
-
for( $i = 4 + $numPlayers * 2; $i <= $#ARGV; ++$i ) {
|
56
|
-
push @args, $ARGV[ $i ];
|
57
|
-
}
|
58
|
-
exec { "./dealer" } @args or die "Couldn't run dealer";
|
59
|
-
}
|
60
|
-
|
61
|
-
close STDINREADPIPE;
|
62
|
-
close STDOUTWRITEPIPE;
|
63
|
-
|
64
|
-
$_ = <STDOUTREADPIPE> or die "couldn't read port description from dealer";
|
65
|
-
@_ = split;
|
66
|
-
$#_ + 1 >= $numPlayers or die "couldn't get enough ports from $_";
|
67
|
-
|
68
|
-
for( $p = 0; $p < $numPlayers; ++$p ) {
|
69
|
-
|
70
|
-
$playerPID[ $p ] = fork();
|
71
|
-
|
72
|
-
if( $playerPID[ $p ] == 0 ) {
|
73
|
-
# we're the child
|
74
|
-
|
75
|
-
# log standard out and standard error
|
76
|
-
open STDOUT, ">$ARGV[ 0 ].player$p.std"
|
77
|
-
or die "can't dup player $p STDOUT";
|
78
|
-
open STDERR, ">$ARGV[ 0 ].player$p.err"
|
79
|
-
or die "can't dup player $p STDERR";
|
80
|
-
|
81
|
-
exec { $ARGV[ 4 + $p * 2 + 1 ] } ( $ARGV[ 4 + $p * 2 + 1 ],
|
82
|
-
$hostip, $_[ $p ] )
|
83
|
-
or die "couldn't run $ARGV[ 4 + $p * 2 + 1 ] for player $p";
|
84
|
-
}
|
85
|
-
}
|
86
|
-
|
87
|
-
$_ = <STDOUTREADPIPE>;
|
88
|
-
|
89
|
-
for( $p = 0; $p < $numPlayers; ++$p ) {
|
90
|
-
waitpid( $playerPID[ $p ], 0 );
|
91
|
-
}
|
92
|
-
|
93
|
-
waitpid( $dealerPID, 0 );
|
94
|
-
|
95
|
-
$_ or die "couldn't get values from dealer";
|
96
|
-
|
97
|
-
print $_;
|
98
|
-
|
99
|
-
exit( 0 );
|
@@ -1,239 +0,0 @@
|
|
1
|
-
ACPC Protocol Specification, version 2.0.0, October 2010
|
2
|
-
=======================================
|
3
|
-
|
4
|
-
This document describes the format of messages between the ACPC `dealer` program and a player. Communication is over *TCP*, where players connect to `dealer` with a port number that `dealer` will print to `STDOUT` upon starting. All messages are terminated by a
|
5
|
-
carriage return and a new line (`\r\n` or *ASCII* characters 13 and 10, respectively).
|
6
|
-
<!-- @todo Does the dealer still ever send comments or GUI commands?/do we still want users to be aware of this? Why would we waste the bandwidth to send players comments? -->
|
7
|
-
Any message from the server which starts with '#' or ';' is a comment or GUI command, and may be safely ignored.
|
8
|
-
The first message from a player must be a version string
|
9
|
-
|
10
|
-
VERSION:2.0.0\r\n
|
11
|
-
|
12
|
-
After this, the server will repeatedly send *match state* strings to players describing their view of the match after every event,including an initial state, states where the player is not acting, and the final state when the game is over.
|
13
|
-
|
14
|
-
Match States
|
15
|
-
--------------
|
16
|
-
<!-- @todo -->
|
17
|
-
|
18
|
-
ACPC Representation of Actions
|
19
|
-
---------------------------------
|
20
|
-
|
21
|
-
Action ACPC Representation
|
22
|
-
------ -------------------
|
23
|
-
check or call `c`
|
24
|
-
fold `f`
|
25
|
-
bet or raise (limit) `r`
|
26
|
-
bet or raise **to** 100 (no-limit) `r100`
|
27
|
-
|
28
|
-
Sending Actions
|
29
|
-
-----------------
|
30
|
-
If the player is acting, it must respond by returning a message with the same state, with their action, in ACPC format, appended. For example, had the player received the match state <!-- @todo -->
|
31
|
-
|
32
|
-
|
33
|
-
<serverMessage> := <matchState> '\r\n'
|
34
|
-
<matchState> := 'MATCHSTATE:' <position> <handNumber> <betting> <cards>
|
35
|
-
<position> := <unsigned integer> ':'
|
36
|
-
<handNumber>:= <unsigned integer> ':'
|
37
|
-
<betting> := { <limitBetting> } { <nolimitBetting> } ':'
|
38
|
-
<limitBetting> := ( <round1LimitBetting>
|
39
|
-
{ | <round1LimitBetting> '/' <round2LimitBetting> … } )
|
40
|
-
<roundXLimitBetting> = <limitAction>*
|
41
|
-
<limitAction> := <fold> | <call> | <limitRaise>
|
42
|
-
<fold> := 'f'
|
43
|
-
<call> := 'c'
|
44
|
-
<limitRaise> := 'r'
|
45
|
-
<nolimitBetting> := ( <round1NolimitBetting>
|
46
|
-
{ | <round1NolimitBetting> '/' <round2NolimitBetting> … } )
|
47
|
-
<roundXNolimitBetting> := <noLimitAction>*
|
48
|
-
<noLimitAction> := <fold> | <call> | <nolimitRaise>
|
49
|
-
<nolmitRaise> := 'r' <nolimitRaiseSize>
|
50
|
-
<nolimitRaiseSize> := <unsigned integer>
|
51
|
-
<cards> := <holeCards> <boardCards>
|
52
|
-
<holeCards> := <player1Cards> '|' <player2Cards> { '|' <player3Cards> … }
|
53
|
-
<boardCards> := <round1BoardCards> { '/' <round2BoardCards> … }
|
54
|
-
<playerXCards> := '' | <card> { <card> … }
|
55
|
-
<roundXBoardCards> := { <card> … }
|
56
|
-
<card> := <rank> <suit>
|
57
|
-
<rank> := '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | 'T' | 'J' | 'Q' | 'K' | 'A'
|
58
|
-
<suit> := 's' | 'h' | 'd' | 'c'
|
59
|
-
<clientResponse> := <matchState> ':' { <limitAction> } { <noLimitAction> } '\r\n'
|
60
|
-
Parts of the specification in brackets indicate game specific definitions. For example, in Texas
|
61
|
-
Hold'em, there are four rounds with zero, three, one, and one board cards on the rounds respectively, so
|
62
|
-
the actual definition would be
|
63
|
-
<round1BoardCards> := ''
|
64
|
-
<round2BoardCards> := <card> <card> <card>
|
65
|
-
<round3BoardCards> := <card>
|
66
|
-
<round4BoardCards> := <card>
|
67
|
-
The <position> field tells the client their position relative to the dealer button. A value of 0 indicates
|
68
|
-
that for the current hand, the client is the first player after the button (the small blind in ring games, or
|
69
|
-
the big blind in reverse-blind heads-up games.)
|
70
|
-
The <handNumber> is simply an identifier for the current hand. Clients should make no assumption
|
71
|
-
about these values, other than that it will be unique across hands within a match, and that it will not
|
72
|
-
change within a single hand.
|
73
|
-
<betting> is a list of actions taken by all players. There is no distinction made between calling and
|
74
|
-
checking, or betting and raising. In no-limit betting strings, the raise action includes a size, which
|
75
|
-
indicates the total number of chips the player will have put into the pot after raising (ie the value they
|
76
|
-
are raising to, not the value they are raising by.) Valid betting strings will be described in a later
|
77
|
-
section.
|
78
|
-
<cards> is the complete set of cards visible to the player, given their <position>. <holecards>
|
79
|
-
describes the view of the private cards, and the number of <playerCards> sections is determined by the
|
80
|
-
game being player. For example, heads-up games will have two sections, 3 player ring games will have
|
81
|
-
3 sections, and so on. Each <playerCard> section will either be an empty string, indicating that the
|
82
|
-
player does not know what those cards are, or a number of <card> strings determined by the game. A
|
83
|
-
<card> is simply two characters, one for the rank and one for the suit. The <boardCards> description
|
84
|
-
will also have a number of sections, one for each round, up to the current round as indicated by the
|
85
|
-
<betting>. The number of <cards> in each section is fixed, and determined by the game. Note that if it
|
86
|
-
ever becomes desirable to play a game with board cards in the first round, the protocol should probably
|
87
|
-
be changed again to add a separator between the hole cards and board cards.
|
88
|
-
A valid <betting> string consists of a sequence of valid actions for successive acting players. Calling is
|
89
|
-
always valid. Folding is only valid if the acting player would need to add money to the pot to call. To
|
90
|
-
describe raises, it is worth making a distinction between raising by and raising to. Unless this
|
91
|
-
document specifically mention otherwise, when it speaks of a raise size, it is talking about a raise to a
|
92
|
-
value, using the term to mean the total number of chips the player will have put into the pot, including
|
93
|
-
chips added in previous rounds. In contrast, raising by a value is adding that number of chips to the pot
|
94
|
-
after calling the current bet.
|
95
|
-
A raise is valid if a) it raises by at least one chip, b) the player has sufficient money in their stack to
|
96
|
-
raise to the value, and c) the raise would put the player all-in (they have spent all their chips) or the
|
97
|
-
amount they are raising by is at least as large as the big blind and the raise-by amount for any other
|
98
|
-
raise in the round. This description properly handles some odd cases where some players may be all-
|
99
|
-
in. Informally, at the beginning of a round a player may bet as low as the big blind, and each
|
100
|
-
subsequent raise must increase the bet by at least as much as the last raise. In limit betting games, there
|
101
|
-
may also be a limit on the number of raises in a round, and any raise action over this limit is not valid.
|
102
|
-
An active player is one that has not folded, and is not all-in. Label the players from 0 to N-1, where N
|
103
|
-
is the number of players in the game. After an action by player p, the next acting player is p' for the
|
104
|
-
minimum d>0 such that p' is active and p' =(p+d) modulo N. That is, the next player around the table
|
105
|
-
who has at least two valid actions. The first player in a round is specified by the game.
|
106
|
-
A betting round ends when all active players remaining have either called, or were the player which
|
107
|
-
initiated the current bet. The game is over if the all betting rounds have finished, or if there are not at
|
108
|
-
least two active players left in the game. If all players but one have folded, the remaining player wins
|
109
|
-
the entire pot, and does not show other players their cards. Otherwise, the game has ended in a
|
110
|
-
showdown and all non-folding players show everyone their cards.
|
111
|
-
Values in a showdown are determined by the rank of a players best hand, constructed from their hole
|
112
|
-
cards and the public board cards. Folding players have a lower rank than any non-folding player.
|
113
|
-
Every pot of money is split evenly between all participating players with the highest rank. There is a
|
114
|
-
separate pot for every distinct amount j of money spent by a player (whether they fold or not), and a
|
115
|
-
player is participating in the pot if they spent at least that much money (again, whether they fold or
|
116
|
-
not.) The size of the pot is equal to the number of participating players multiplied by (j - the size of the
|
117
|
-
next smallest amount spent by a player).
|
118
|
-
Changes from Version 1
|
119
|
-
There a number of changes from the first version of the protocol. Ring games are now documented.
|
120
|
-
No-limit games no longer give a value for a call, and there are no blinds in the string. The question of
|
121
|
-
whether all-in players got to act was previously left unspecified, and different implementations had
|
122
|
-
different behaviour. Folding is no longer allowed if the player could have called for free. Finally, this
|
123
|
-
updated description also covers the protocol for no-limit ring games, in the event that this game is
|
124
|
-
added to the competition.
|
125
|
-
It is also strongly suggested to the chair that on a failed responses from a client, whether the message
|
126
|
-
was malformed, the action was invalid, or the player did not respond in time, the entire match should
|
127
|
-
be ended. If the problem can not be fixed easily by a very short interaction with the team, the program
|
128
|
-
should be disqualified. The previous choice of having the player call in some cases, or fold all
|
129
|
-
remaining hands led to some situations where the results of the competition depended on the chair's
|
130
|
-
decision on exactly how to handle incorrect behaviour. Teams with buggy programs also took up large
|
131
|
-
amounts of the chair's time. As long as players are given sufficient time for testing, using the exact
|
132
|
-
same code used for the competition, it is not unreasonable to expect players to be able to run without
|
133
|
-
producing error messages or warnings.
|
134
|
-
Examples
|
135
|
-
The rest of this document is examples of messages to and from a client in various games. Messages
|
136
|
-
from the server are prefaced with S->. Responses from the client are prefaced with <-C.
|
137
|
-
Two player limit Texas Hold'em
|
138
|
-
S-> MATCHSTATE:0:0::TdAs|
|
139
|
-
S-> MATCHSTATE:0:0:r:TdAs|
|
140
|
-
<-C MATCHSTATE:0:0:r:TdAs|:r
|
141
|
-
S-> MATCHSTATE:0:0:rr:TdAs|
|
142
|
-
S-> MATCHSTATE:0:0:rrc/:TdAs|/2c8c3h
|
143
|
-
<-C MATCHSTATE:0:0:rrc/:TdAs|/2c8c3h:r
|
144
|
-
S-> MATCHSTATE:0:0:rrc/r:TdAs|/2c8c3h
|
145
|
-
S-> MATCHSTATE:0:0:rrc/rc/:TdAs|/2c8c3h/9c
|
146
|
-
<-C MATCHSTATE:0:0:rrc/rc/:TdAs|/2c8c3h/9c:c
|
147
|
-
S-> MATCHSTATE:0:0:rrc/rc/c:TdAs|/2c8c3h/9c
|
148
|
-
S-> MATCHSTATE:0:0:rrc/rc/cr:TdAs|/2c8c3h/9c
|
149
|
-
<-C MATCHSTATE:0:0:rrc/rc/cr:TdAs|/2c8c3h/9c:c
|
150
|
-
S-> MATCHSTATE:0:0:rrc/rc/crc/:TdAs|/2c8c3h/9c/Kh
|
151
|
-
<-C MATCHSTATE:0:0:rrc/rc/crc/:TdAs|/2c8c3h/9c/Kh:c
|
152
|
-
S-> MATCHSTATE:0:0:rrc/rc/crc/c:TdAs|/2c8c3h/9c/Kh
|
153
|
-
S-> MATCHSTATE:0:0:rrc/rc/crc/cr:TdAs|/2c8c3h/9c/Kh
|
154
|
-
<-C MATCHSTATE:0:0:rrc/rc/crc/cr:TdAs|/2c8c3h/9c/Kh:c
|
155
|
-
S-> MATCHSTATE:0:0:rrc/rc/crc/crc:TdAs|8hTc/2c8c3h/9c/Kh
|
156
|
-
S-> MATCHSTATE:1:1::|Qd7c
|
157
|
-
<-C MATCHSTATE:1:1::|Qd7c:r
|
158
|
-
S-> MATCHSTATE:1:1:r:|Qd7c
|
159
|
-
S-> MATCHSTATE:1:1:rr:|Qd7c
|
160
|
-
<-C MATCHSTATE:1:1:rr:|Qd7c:c
|
161
|
-
S-> MATCHSTATE:1:1:rrc/:|Qd7c/2h8h5c
|
162
|
-
S-> MATCHSTATE:1:1:rrc/r:|Qd7c/2h8h5c
|
163
|
-
<-C MATCHSTATE:1:1:rrc/r:|Qd7c/2h8h5c:c
|
164
|
-
S-> MATCHSTATE:1:1:rrc/rc/:|Qd7c/2h8h5c/Th
|
165
|
-
S-> MATCHSTATE:1:1:rrc/rc/r:|Qd7c/2h8h5c/Th
|
166
|
-
<-C MATCHSTATE:1:1:rrc/rc/r:|Qd7c/2h8h5c/Th:f
|
167
|
-
S-> MATCHSTATE:1:1:rrc/rc/rf:|Qd7c/2h8h5c/Th
|
168
|
-
S-> MATCHSTATE:0:2::9d7s|
|
169
|
-
S-> MATCHSTATE:0:2:r:9d7s|
|
170
|
-
<-C MATCHSTATE:0:2:r:9d7s|:c
|
171
|
-
S-> MATCHSTATE:0:2:rc/:9d7s|/5d2cJc
|
172
|
-
<-C MATCHSTATE:0:2:rc/:9d7s|/5d2cJc:c
|
173
|
-
S-> MATCHSTATE:0:2:rc/c:9d7s|/5d2cJc
|
174
|
-
S-> MATCHSTATE:0:2:rc/cc/:9d7s|/5d2cJc/3d
|
175
|
-
<-C MATCHSTATE:0:2:rc/cc/:9d7s|/5d2cJc/3d:c
|
176
|
-
S-> MATCHSTATE:0:2:rc/cc/c:9d7s|/5d2cJc/3d
|
177
|
-
S-> MATCHSTATE:0:2:rc/cc/cr:9d7s|/5d2cJc/3d
|
178
|
-
<-C MATCHSTATE:0:2:rc/cc/cr:9d7s|/5d2cJc/3d:f
|
179
|
-
S-> MATCHSTATE:0:2:rc/cc/crf:9d7s|/5d2cJc/3d
|
180
|
-
Two player no-limit Texas Hold'em
|
181
|
-
S-> MATCHSTATE:0:30::9s8h|
|
182
|
-
S-> MATCHSTATE:0:30:c:9s8h|
|
183
|
-
<-C MATCHSTATE:0:30:c:9s8h|:c
|
184
|
-
S-> MATCHSTATE:0:30:cc/:9s8h|/8c8d5c
|
185
|
-
<-C MATCHSTATE:0:30:cc/:9s8h|/8c8d5c:r250
|
186
|
-
S-> MATCHSTATE:0:30:cc/r250:9s8h|/8c8d5c
|
187
|
-
S-> MATCHSTATE:0:30:cc/r250c/:9s8h|/8c8d5c/6s
|
188
|
-
<-C MATCHSTATE:0:30:cc/r250c/:9s8h|/8c8d5c/6s:r500
|
189
|
-
S-> MATCHSTATE:0:30:cc/r250c/r500:9s8h|/8c8d5c/6s
|
190
|
-
S-> MATCHSTATE:0:30:cc/r250c/r500c/:9s8h|/8c8d5c/6s/2d
|
191
|
-
<-C MATCHSTATE:0:30:cc/r250c/r500c/:9s8h|/8c8d5c/6s/2d:r1250
|
192
|
-
S-> MATCHSTATE:0:30:cc/r250c/r500c/r1250:9s8h|/8c8d5c/6s/2d
|
193
|
-
S-> MATCHSTATE:0:30:cc/r250c/r500c/r1250c:9s8h|9c6h/8c8d5c/6s/2d
|
194
|
-
S-> MATCHSTATE:1:31::|JdTc
|
195
|
-
<-C MATCHSTATE:1:31::|JdTc:r300
|
196
|
-
S-> MATCHSTATE:1:31:r300:|JdTc
|
197
|
-
S-> MATCHSTATE:1:31:r300r900:|JdTc
|
198
|
-
<-C MATCHSTATE:1:31:r300r900:|JdTc:c
|
199
|
-
S-> MATCHSTATE:1:31:r300r900c/:|JdTc/6dJc9c
|
200
|
-
S-> MATCHSTATE:1:31:r300r900c/r1800:|JdTc/6dJc9c
|
201
|
-
<-C MATCHSTATE:1:31:r300r900c/r1800:|JdTc/6dJc9c:r3600
|
202
|
-
S-> MATCHSTATE:1:31:r300r900c/r1800r3600:|JdTc/6dJc9c
|
203
|
-
S-> MATCHSTATE:1:31:r300r900c/r1800r3600r9000:|JdTc/6dJc9c
|
204
|
-
<-C MATCHSTATE:1:31:r300r900c/r1800r3600r9000:|JdTc/6dJc9c:c
|
205
|
-
S-> MATCHSTATE:1:31:r300r900c/r1800r3600r9000c/:|JdTc/6dJc9c/Kh
|
206
|
-
S-> MATCHSTATE:1:31:r300r900c/r1800r3600r9000c/r20000:|JdTc/6dJc9c/Kh
|
207
|
-
<-C MATCHSTATE:1:31:r300r900c/r1800r3600r9000c/r20000:|JdTc/6dJc9c/Kh:c
|
208
|
-
S-> MATCHSTATE:1:31:r300r900c/r1800r3600r9000c/r20000c/:KsJs|JdTc/6dJc9c/Kh/Qc
|
209
|
-
Three player limit Texas Hold'em
|
210
|
-
S-> MATCHSTATE:2:55::||AsTs
|
211
|
-
<-C MATCHSTATE:2:55::||AsTs:r
|
212
|
-
S-> MATCHSTATE:2:55:r:||AsTs
|
213
|
-
S-> MATCHSTATE:2:55:rc:||AsTs
|
214
|
-
S-> MATCHSTATE:2:55:rcc/:||AsTs/4cJh8h
|
215
|
-
S-> MATCHSTATE:2:55:rcc/r:||AsTs/4cJh8h
|
216
|
-
S-> MATCHSTATE:2:55:rcc/rf:||AsTs/4cJh8h
|
217
|
-
<-C MATCHSTATE:2:55:rcc/rf:||AsTs/4cJh8h:c
|
218
|
-
S-> MATCHSTATE:2:55:rcc/rfc/:||AsTs/4cJh8h/Kd
|
219
|
-
S-> MATCHSTATE:2:55:rcc/rfc/r:||AsTs/4cJh8h/Kd
|
220
|
-
<-C MATCHSTATE:2:55:rcc/rfc/r:||AsTs/4cJh8h/Kd:c
|
221
|
-
S-> MATCHSTATE:2:55:rcc/rfc/rc/:||AsTs/4cJh8h/Kd/8c
|
222
|
-
S-> MATCHSTATE:2:55:rcc/rfc/rc/r:||AsTs/4cJh8h/Kd/8c
|
223
|
-
<-C MATCHSTATE:2:55:rcc/rfc/rc/r:||AsTs/4cJh8h/Kd/8c:f
|
224
|
-
S-> MATCHSTATE:2:55:rcc/rfc/rc/rf:||AsTs/4cJh8h/Kd/8c
|
225
|
-
S-> MATCHSTATE:0:90::Ad6h||
|
226
|
-
S-> MATCHSTATE:0:90:c:Ad6h||
|
227
|
-
<-C MATCHSTATE:0:90:c:Ad6h||:r
|
228
|
-
S-> MATCHSTATE:0:90:cr:Ad6h||
|
229
|
-
S-> MATCHSTATE:0:90:crf:Ad6h||
|
230
|
-
S-> MATCHSTATE:0:90:crfc/:Ad6h||/TsKd7h
|
231
|
-
<-C MATCHSTATE:0:90:crfc/:Ad6h||/TsKd7h:r
|
232
|
-
S-> MATCHSTATE:0:90:crfc/r:Ad6h||/TsKd7h
|
233
|
-
S-> MATCHSTATE:0:90:crfc/rc/:Ad6h||/TsKd7h/Kh
|
234
|
-
<-C MATCHSTATE:0:90:crfc/rc/:Ad6h||/TsKd7h/Kh:r
|
235
|
-
S-> MATCHSTATE:0:90:crfc/rc/r:Ad6h||/TsKd7h/Kh
|
236
|
-
S-> MATCHSTATE:0:90:crfc/rc/rc/:Ad6h||/TsKd7h/Kh/6d
|
237
|
-
<-C MATCHSTATE:0:90:crfc/rc/rc/:Ad6h||/TsKd7h/Kh/6d:r
|
238
|
-
S-> MATCHSTATE:0:90:crfc/rc/rc/r:Ad6h||/TsKd7h/Kh/6d
|
239
|
-
S-> MATCHSTATE:0:90:crfc/rc/rc/rc:Ad6h||Td2h/TsKd7h/Kh/6d
|