acpc_dealer 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (99) hide show
  1. data/README.md +33 -0
  2. data/Rakefile +20 -0
  3. data/acpc_dealer.gemspec +29 -0
  4. data/bin/acpc_dealer +168 -0
  5. data/ext/hand_evaluator/extconf.rb +5 -0
  6. data/ext/hand_evaluator/hand_evaluator.c +38 -0
  7. data/lib/acpc_dealer/2p.limit.h5.r0.logs/2p.limit.h5.r0.actions.log +5 -0
  8. data/lib/acpc_dealer/2p.limit.h5.r0.logs/2p.limit.h5.r0.log +0 -0
  9. data/lib/acpc_dealer/dealer_runner.rb +72 -0
  10. data/lib/acpc_dealer/version.rb +3 -0
  11. data/lib/acpc_dealer.rb +33 -0
  12. data/lib/hand_evaluator.so +0 -0
  13. data/spec/coverage/assets/0.5.3/app.js +88 -0
  14. data/spec/coverage/assets/0.5.3/fancybox/blank.gif +0 -0
  15. data/spec/coverage/assets/0.5.3/fancybox/fancy_close.png +0 -0
  16. data/spec/coverage/assets/0.5.3/fancybox/fancy_loading.png +0 -0
  17. data/spec/coverage/assets/0.5.3/fancybox/fancy_nav_left.png +0 -0
  18. data/spec/coverage/assets/0.5.3/fancybox/fancy_nav_right.png +0 -0
  19. data/spec/coverage/assets/0.5.3/fancybox/fancy_shadow_e.png +0 -0
  20. data/spec/coverage/assets/0.5.3/fancybox/fancy_shadow_n.png +0 -0
  21. data/spec/coverage/assets/0.5.3/fancybox/fancy_shadow_ne.png +0 -0
  22. data/spec/coverage/assets/0.5.3/fancybox/fancy_shadow_nw.png +0 -0
  23. data/spec/coverage/assets/0.5.3/fancybox/fancy_shadow_s.png +0 -0
  24. data/spec/coverage/assets/0.5.3/fancybox/fancy_shadow_se.png +0 -0
  25. data/spec/coverage/assets/0.5.3/fancybox/fancy_shadow_sw.png +0 -0
  26. data/spec/coverage/assets/0.5.3/fancybox/fancy_shadow_w.png +0 -0
  27. data/spec/coverage/assets/0.5.3/fancybox/fancy_title_left.png +0 -0
  28. data/spec/coverage/assets/0.5.3/fancybox/fancy_title_main.png +0 -0
  29. data/spec/coverage/assets/0.5.3/fancybox/fancy_title_over.png +0 -0
  30. data/spec/coverage/assets/0.5.3/fancybox/fancy_title_right.png +0 -0
  31. data/spec/coverage/assets/0.5.3/fancybox/fancybox-x.png +0 -0
  32. data/spec/coverage/assets/0.5.3/fancybox/fancybox-y.png +0 -0
  33. data/spec/coverage/assets/0.5.3/fancybox/fancybox.png +0 -0
  34. data/spec/coverage/assets/0.5.3/fancybox/jquery.fancybox-1.3.1.css +363 -0
  35. data/spec/coverage/assets/0.5.3/fancybox/jquery.fancybox-1.3.1.pack.js +44 -0
  36. data/spec/coverage/assets/0.5.3/favicon_green.png +0 -0
  37. data/spec/coverage/assets/0.5.3/favicon_red.png +0 -0
  38. data/spec/coverage/assets/0.5.3/favicon_yellow.png +0 -0
  39. data/spec/coverage/assets/0.5.3/highlight.css +129 -0
  40. data/spec/coverage/assets/0.5.3/highlight.pack.js +1 -0
  41. data/spec/coverage/assets/0.5.3/jquery-1.6.2.min.js +18 -0
  42. data/spec/coverage/assets/0.5.3/jquery.dataTables.min.js +152 -0
  43. data/spec/coverage/assets/0.5.3/jquery.timeago.js +141 -0
  44. data/spec/coverage/assets/0.5.3/jquery.url.js +174 -0
  45. data/spec/coverage/assets/0.5.3/loading.gif +0 -0
  46. data/spec/coverage/assets/0.5.3/magnify.png +0 -0
  47. data/spec/coverage/assets/0.5.3/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  48. data/spec/coverage/assets/0.5.3/smoothness/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  49. data/spec/coverage/assets/0.5.3/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  50. data/spec/coverage/assets/0.5.3/smoothness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  51. data/spec/coverage/assets/0.5.3/smoothness/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  52. data/spec/coverage/assets/0.5.3/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  53. data/spec/coverage/assets/0.5.3/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  54. data/spec/coverage/assets/0.5.3/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  55. data/spec/coverage/assets/0.5.3/smoothness/images/ui-icons_222222_256x240.png +0 -0
  56. data/spec/coverage/assets/0.5.3/smoothness/images/ui-icons_2e83ff_256x240.png +0 -0
  57. data/spec/coverage/assets/0.5.3/smoothness/images/ui-icons_454545_256x240.png +0 -0
  58. data/spec/coverage/assets/0.5.3/smoothness/images/ui-icons_888888_256x240.png +0 -0
  59. data/spec/coverage/assets/0.5.3/smoothness/images/ui-icons_cd0a0a_256x240.png +0 -0
  60. data/spec/coverage/assets/0.5.3/smoothness/jquery-ui-1.8.4.custom.css +295 -0
  61. data/spec/coverage/assets/0.5.3/stylesheet.css +383 -0
  62. data/spec/coverage/index.html +81 -0
  63. data/spec/dealer_runner_spec.rb +83 -0
  64. data/spec/support/spec_helper.rb +33 -0
  65. data/vendor/project_acpc_server/LICENCE +23 -0
  66. data/vendor/project_acpc_server/Makefile +22 -0
  67. data/vendor/project_acpc_server/README +113 -0
  68. data/vendor/project_acpc_server/README.submission +42 -0
  69. data/vendor/project_acpc_server/acpc_play_match.pl +101 -0
  70. data/vendor/project_acpc_server/bm_server +0 -0
  71. data/vendor/project_acpc_server/bm_server.c +1557 -0
  72. data/vendor/project_acpc_server/bm_server.config +78 -0
  73. data/vendor/project_acpc_server/bm_widget +0 -0
  74. data/vendor/project_acpc_server/bm_widget.c +186 -0
  75. data/vendor/project_acpc_server/dealer +0 -0
  76. data/vendor/project_acpc_server/dealer.c +1278 -0
  77. data/vendor/project_acpc_server/evalHandTables +4269 -0
  78. data/vendor/project_acpc_server/example_player +0 -0
  79. data/vendor/project_acpc_server/example_player.c +204 -0
  80. data/vendor/project_acpc_server/example_player.limit.2p.sh +2 -0
  81. data/vendor/project_acpc_server/example_player.limit.3p.sh +2 -0
  82. data/vendor/project_acpc_server/example_player.nolimit.2p.sh +2 -0
  83. data/vendor/project_acpc_server/example_player.nolimit.3p.sh +2 -0
  84. data/vendor/project_acpc_server/game.c +1793 -0
  85. data/vendor/project_acpc_server/game.h +253 -0
  86. data/vendor/project_acpc_server/holdem.limit.2p.reverse_blinds.game +13 -0
  87. data/vendor/project_acpc_server/holdem.limit.3p.game +13 -0
  88. data/vendor/project_acpc_server/holdem.nolimit.2p.reverse_blinds.game +12 -0
  89. data/vendor/project_acpc_server/holdem.nolimit.3p.game +12 -0
  90. data/vendor/project_acpc_server/net.c +218 -0
  91. data/vendor/project_acpc_server/net.h +61 -0
  92. data/vendor/project_acpc_server/play_match.pl +99 -0
  93. data/vendor/project_acpc_server/protocol.odt +0 -0
  94. data/vendor/project_acpc_server/protocol.pdf +0 -0
  95. data/vendor/project_acpc_server/rng.c +138 -0
  96. data/vendor/project_acpc_server/rng.h +63 -0
  97. data/vendor/project_acpc_server/test.log +11 -0
  98. data/vendor/project_acpc_server/validate_submission.pl +546 -0
  99. metadata +315 -0
@@ -0,0 +1,253 @@
1
+ /*
2
+ Copyright (C) 2011 by the Computer Poker Research Group, University of Alberta
3
+ */
4
+
5
+ #ifndef _GAME_H
6
+ #define _GAME_H
7
+ #define __STDC_FORMAT_MACROS
8
+ #include <inttypes.h>
9
+ #include "rng.h"
10
+ #include "net.h"
11
+
12
+
13
+ #define VERSION_MAJOR 2
14
+ #define VERSION_MINOR 0
15
+ #define VERSION_REVISION 0
16
+
17
+
18
+ #define MAX_ROUNDS 4
19
+ #define MAX_PLAYERS 10
20
+ #define MAX_BOARD_CARDS 7
21
+ #define MAX_HOLE_CARDS 3
22
+ #define MAX_NUM_ACTIONS 64
23
+ #define MAX_SUITS 4
24
+ #define MAX_RANKS 13
25
+ #define MAX_LINE_LEN READBUF_LEN
26
+
27
+ #define NUM_ACTION_TYPES 3
28
+
29
+
30
+ enum BettingType { limitBetting, noLimitBetting };
31
+ enum ActionType { a_fold = 0, a_call = 1, a_raise = 2,
32
+ a_invalid = NUM_ACTION_TYPES };
33
+
34
+ typedef struct {
35
+ enum ActionType type; /* is action a fold, call, or raise? */
36
+ int32_t size; /* for no-limit raises, we need a size
37
+ MUST BE 0 IN ALL CASES WHERE IT IS NOT USED */
38
+ } Action;
39
+
40
+ typedef struct {
41
+
42
+ /* stack sizes for each player */
43
+ int32_t stack[ MAX_PLAYERS ];
44
+
45
+ /* entry fee for game, per player */
46
+ int32_t blind[ MAX_PLAYERS ];
47
+
48
+ /* size of fixed raises for limitBetting games */
49
+ int32_t raiseSize[ MAX_ROUNDS ];
50
+
51
+ /* general class of game */
52
+ enum BettingType bettingType;
53
+
54
+ /* number of players in the game */
55
+ uint8_t numPlayers;
56
+
57
+ /* number of betting rounds */
58
+ uint8_t numRounds;
59
+
60
+ /* first player to act in a round */
61
+ uint8_t firstPlayer[ MAX_ROUNDS ];
62
+
63
+ /* number of bets/raises that may be made in each round */
64
+ uint8_t maxRaises[ MAX_ROUNDS ];
65
+
66
+ /* number of suits and ranks in the deck of cards */
67
+ uint8_t numSuits;
68
+ uint8_t numRanks;
69
+
70
+ /* number of private player cards */
71
+ uint8_t numHoleCards;
72
+
73
+ /* number of shared public cards each round */
74
+ uint8_t numBoardCards[ MAX_ROUNDS ];
75
+ } Game;
76
+
77
+ typedef struct {
78
+ uint32_t handId;
79
+
80
+ /* largest bet so far, including all previous rounds */
81
+ int32_t maxSpent;
82
+
83
+ /* minimum number of chips a player must have spend in total to raise
84
+ only used for noLimitBetting games */
85
+ int32_t minNoLimitRaiseTo;
86
+
87
+ /* spent[ p ] gives the total amount put into the pot by player p */
88
+ int32_t spent[ MAX_PLAYERS ];
89
+
90
+ /* action[ r ][ i ] gives the i'th action in round r */
91
+ Action action[ MAX_ROUNDS ][ MAX_NUM_ACTIONS ];
92
+
93
+ /* actingPlayer[ r ][ i ] gives the player who made action i in round r
94
+ we can always figure this out from the actions taken, but it's
95
+ easier to just remember this in multiplayer (because of folds) */
96
+ uint8_t actingPlayer[ MAX_ROUNDS ][ MAX_NUM_ACTIONS ];
97
+
98
+ /* numActions[ r ] gives the number of actions made in round r */
99
+ uint8_t numActions[ MAX_ROUNDS ];
100
+
101
+ /* current round: a value between 0 and game.numRounds-1
102
+ a showdown is still in numRounds-1, not a separate round */
103
+ uint8_t round;
104
+
105
+ /* finished is non-zero if and only if the game is over */
106
+ uint8_t finished;
107
+
108
+ /* playerFolded[ p ] is non-zero if and only player p has folded */
109
+ uint8_t playerFolded[ MAX_PLAYERS ];
110
+
111
+ /* public cards (including cards which may not yet be visible to players) */
112
+ uint8_t boardCards[ MAX_BOARD_CARDS ];
113
+
114
+ /* private cards */
115
+ uint8_t holeCards[ MAX_PLAYERS ][ MAX_HOLE_CARDS ];
116
+ } State;
117
+
118
+ typedef struct {
119
+ State state;
120
+ uint8_t viewingPlayer;
121
+ } MatchState;
122
+
123
+
124
+ /* returns a game structure, or NULL on failure */
125
+ Game *readGame( FILE *file );
126
+
127
+ void printGame( FILE *file, const Game *game );
128
+
129
+ /* initialise a state so that it is at the beginning of a hand
130
+ DOES NOT DEAL OUT CARDS */
131
+ void initState( const Game *game, const uint32_t handId, State *state );
132
+
133
+ /* shuffle a deck of cards and deal them out, writing the results to state */
134
+ void dealCards( const Game *game, rng_state_t *rng, State *state );
135
+
136
+ int statesEqual( const Game *game, const State *a, const State *b );
137
+
138
+ int matchStatesEqual( const Game *game, const MatchState *a,
139
+ const MatchState *b );
140
+
141
+ /* check if a raise is possible, and the range of valid sizes
142
+ returns non-zero if raise is a valid action and sets *minSize
143
+ and maxSize, or zero if raise is not valid */
144
+ int raiseIsValid( const Game *game, const State *curState,
145
+ int32_t *minSize, int32_t *maxSize );
146
+
147
+ /* check if an action is valid
148
+
149
+ if tryFixing is non-zero, try modifying the given action to produce
150
+ a valid action, as in the AAAI rules. Currently this only means
151
+ that a no-limit raise will be modified to the nearest valid raise size
152
+
153
+ returns non-zero if final action/size is valid for state, 0 otherwise */
154
+ int isValidAction( const Game *game, const State *curState,
155
+ const int tryFixing, Action *action );
156
+
157
+ /* record the given action in state
158
+ does not check that action is valid */
159
+ void doAction( const Game *game, const Action *action, State *state );
160
+
161
+ /* returns non-zero if hand is finished, zero otherwise */
162
+ #define stateFinished( constStatePtr ) ((constStatePtr)->finished)
163
+
164
+ /* get the current player to act in the state */
165
+ uint8_t currentPlayer( const Game *game, const State *state );
166
+
167
+ /* number of raises in the current round */
168
+ uint8_t numRaises( const State *state );
169
+
170
+ /* number of players who have folded */
171
+ uint8_t numFolded( const Game *game, const State *state );
172
+
173
+ /* number of players who have called the current bet (or initiated it)
174
+ doesn't count non-acting players who are all-in */
175
+ uint8_t numCalled( const Game *game, const State *state );
176
+
177
+ /* number of players who are all-in */
178
+ uint8_t numAllIn( const Game *game, const State *state );
179
+
180
+ /* number of players who can still act (ie not all-in or folded) */
181
+ uint8_t numActingPlayers( const Game *game, const State *state );
182
+
183
+ /* get the index into array state.boardCards[] for the first board
184
+ card in round (where the first round is round 0) */
185
+ uint8_t bcStart( const Game *game, const uint8_t round );
186
+
187
+ /* get the total number of board cards dealt out after (zero based) round */
188
+ uint8_t sumBoardCards( const Game *game, const uint8_t round );
189
+
190
+ /* return the value of a finished hand for a player
191
+ returns a double because pots may be split when players tie
192
+ WILL HAVE UNDEFINED BEHAVIOUR IF HAND ISN'T FINISHED
193
+ (stateFinished(state)==0) */
194
+ double valueOfState( const Game *game, const State *state,
195
+ const uint8_t player );
196
+
197
+ /* returns number of characters consumed on success, -1 on failure
198
+ state will be modified even on a failure to read */
199
+ int readState( const char *string, const Game *game, State *state );
200
+
201
+ /* returns number of characters consumed on success, -1 on failure
202
+ state will be modified even on a failure to read */
203
+ int readMatchState( const char *string, const Game *game, MatchState *state );
204
+
205
+ /* print a state to a string, as viewed by viewingPlayer
206
+ returns the number of characters in string, or -1 on error
207
+ DOES NOT COUNT FINAL 0 TERMINATOR IN THIS COUNT!!! */
208
+ int printState( const Game *game, const State *state,
209
+ const int maxLen, char *string );
210
+
211
+ /* print a state to a string, as viewed by viewingPlayer
212
+ returns the number of characters in string, or -1 on error
213
+ DOES NOT COUNT FINAL 0 TERMINATOR IN THIS COUNT!!! */
214
+ int printMatchState( const Game *game, const MatchState *state,
215
+ const int maxLen, char *string );
216
+
217
+ /* read an action, returning the action in the passed pointer
218
+ action and size will be modified even on a failure to read
219
+ returns number of characters consumed on succes, -1 on failure */
220
+ int readAction( const char *string, const Game *game, Action *action );
221
+
222
+ /* print an action to a string
223
+ returns the number of characters in string, or -1 on error
224
+ DOES NOT COUNT FINAL 0 TERMINATOR IN THIS COUNT!!! */
225
+ int printAction( const Game *game, const Action *action,
226
+ const int maxLen, char *string );
227
+
228
+ /* returns number of characters consumed, or -1 on error
229
+ on success, returns the card in *card */
230
+ int readCard( const char *string, uint8_t *card );
231
+
232
+ /* read up to maxCards cards
233
+ returns number of cards successfully read
234
+ returns number of characters consumed in charsConsumed */
235
+ int readCards( const char *string, const int maxCards,
236
+ uint8_t *cards, int *charsConsumed );
237
+
238
+ /* print a card to a string
239
+ returns the number of characters in string, or -1 on error
240
+ DOES NOT COUNT FINAL 0 TERMINATOR IN THIS COUNT!!! */
241
+ int printCard( const uint8_t card, const int maxLen, char *string );
242
+
243
+ /* print out numCards cards to a string
244
+ returns the number of characters in string
245
+ DOES NOT COUNT FINAL 0 TERMINATOR IN THIS COUNT!!! */
246
+ int printCards( const int numCards, const uint8_t *cards,
247
+ const int maxLen, char *string );
248
+
249
+ #define rankOfCard( card ) ((card)/MAX_SUITS)
250
+ #define suitOfCard( card ) ((card)%MAX_SUITS)
251
+ #define makeCard( rank, suit ) ((rank)*MAX_SUITS+(suit))
252
+
253
+ #endif
@@ -0,0 +1,13 @@
1
+ GAMEDEF
2
+ limit
3
+ numPlayers = 2
4
+ numRounds = 4
5
+ blind = 10 5
6
+ raiseSize = 10 10 20 20
7
+ firstPlayer = 2 1 1 1
8
+ maxRaises = 3 4 4 4
9
+ numSuits = 4
10
+ numRanks = 13
11
+ numHoleCards = 2
12
+ numBoardCards = 0 3 1 1
13
+ END GAMEDEF
@@ -0,0 +1,13 @@
1
+ GAMEDEF
2
+ limit
3
+ numPlayers = 3
4
+ numRounds = 4
5
+ blind = 5 10 0
6
+ raiseSize = 10 10 20 20
7
+ firstPlayer = 3 1 1 1
8
+ maxRaises = 3 4 4 4
9
+ numSuits = 4
10
+ numRanks = 13
11
+ numHoleCards = 2
12
+ numBoardCards = 0 3 1 1
13
+ END GAMEDEF
@@ -0,0 +1,12 @@
1
+ GAMEDEF
2
+ nolimit
3
+ numPlayers = 2
4
+ numRounds = 4
5
+ stack = 20000 20000
6
+ blind = 100 50
7
+ firstPlayer = 2 1 1 1
8
+ numSuits = 4
9
+ numRanks = 13
10
+ numHoleCards = 2
11
+ numBoardCards = 0 3 1 1
12
+ END GAMEDEF
@@ -0,0 +1,12 @@
1
+ GAMEDEF
2
+ nolimit
3
+ numPlayers = 3
4
+ numRounds = 4
5
+ stack = 20000 20000 20000
6
+ blind = 50 100 0
7
+ firstPlayer = 3 1 1 1
8
+ numSuits = 4
9
+ numRanks = 13
10
+ numHoleCards = 2
11
+ numBoardCards = 0 3 1 1
12
+ END GAMEDEF
@@ -0,0 +1,218 @@
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
+ }
@@ -0,0 +1,61 @@
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
+ #define __STDC_FORMAT_MACROS
11
+ #include <inttypes.h>
12
+
13
+
14
+ #define READBUF_LEN 1024
15
+ #define NUM_PORT_CREATION_ATTEMPTS 10
16
+
17
+
18
+ /* buffered I/O on file descriptors
19
+
20
+ Yes... this is basically re-implementing bits of a standard FILE.
21
+ Unfortunately, trying to mix timeouts and FILE streams either
22
+ a) doesn't work, or b) is fairly system specific */
23
+ typedef struct {
24
+ int fd;
25
+ int bufStart;
26
+ int bufEnd;
27
+ char buf[ READBUF_LEN ];
28
+ } ReadBuf;
29
+
30
+
31
+ /* open a socket to hostname/port
32
+ returns file descriptor on success, <0 on failure */
33
+ int connectTo( char *hostname, uint16_t port );
34
+
35
+ /* try opening a socket suitable for connecting to
36
+ if *desiredPort>0, uses specified port, otherwise use a random port
37
+ returns actual port in *desiredPort
38
+ returns file descriptor for socket, or -1 on failure */
39
+ int getListenSocket( uint16_t *desiredPort );
40
+
41
+
42
+ /* create a read buffer structure
43
+ returns 0 on failure */
44
+ ReadBuf *createReadBuf( int fd );
45
+
46
+ /* destroy a read buffer - like fdopen, it will close the file descriptor */
47
+ void destroyReadBuf( ReadBuf *readBuf );
48
+
49
+ /* get a newline terminated line and place it as a string in 'line'
50
+ terminates the string with a 0 character
51
+ if timeoutMicros is non-negative, do not spend more than
52
+ that number of microseconds waiting to read data
53
+ return number of characters read (including newline, excluding 0)
54
+ 0 on end of file, or -1 on error or timeout */
55
+ ssize_t getLine( ReadBuf *readBuf,
56
+ size_t maxLen,
57
+ char *line,
58
+ int64_t timeoutMicros );
59
+
60
+
61
+ #endif
@@ -0,0 +1,99 @@
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 );