/* returns >= 0 if action/size has been set to a valid action returns -1 for failure (disconnect, timeout, too many bad actions, etc) */ static int readPlayerResponse( const Game *game, const MatchState *state, const int quiet, const uint8_t seat, const struct timeval *sendTime, ErrorInfo *errorInfo, ReadBuf *readBuf, Action *action, struct timeval *recvTime ) { int c, r; MatchState tempState; char line[ MAX_LINE_LEN ]; while( 1 ) { /* read a line of input from player */ struct timeval start; gettimeofday( &start, NULL ); if( getLine( readBuf, MAX_LINE_LEN, line, errorInfo->maxResponseMicros ) <= 0 ) { /* couldn't get any input from player */ struct timeval after; gettimeofday( &after, NULL ); uint64_t micros_spent = (uint64_t)( after.tv_sec - start.tv_sec ) * 1000000 + ( after.tv_usec - start.tv_usec ); fprintf( stderr, "ERROR: could not get action from seat %"PRIu8"\n", seat + 1 ); // Print out how much time has passed so we can see if this was a // timeout as opposed to some other sort of failure (e.g., socket // closing). fprintf( stderr, "%.1f seconds spent waiting; timeout %.1f\n", micros_spent / 1000000.0, errorInfo->maxResponseMicros / 1000000.0); return -1; } /* note when the message arrived */ gettimeofday( recvTime, NULL ); /* log the response */ if( !quiet ) { fprintf( stderr, "FROM %d at %zu.%06zu %s", seat + 1, recvTime->tv_sec, recvTime->tv_usec, line ); } /* ignore comments */ if( line[ 0 ] == '#' || line[ 0 ] == ';' ) { continue; } /* check for any timeout issues */ if( checkErrorTimes( seat, sendTime, recvTime, errorInfo ) < 0 ) { fprintf( stderr, "ERROR: seat %"PRIu8" ran out of time\n", seat + 1 ); return -1; } /* parse out the state */ c = readMatchState( line, game, &tempState ); if( c < 0 ) { /* couldn't get an intelligible state */ fprintf( stderr, "WARNING: bad state format in response\n" ); continue; } /* ignore responses that don't match the current state */ if( !matchStatesEqual( game, state, &tempState ) ) { fprintf( stderr, "WARNING: ignoring un-requested response\n" ); continue; } /* get the action */ if( line[ c++ ] != ':' || ( r = readAction( &line[ c ], game, action ) ) < 0 ) { if( checkErrorInvalidAction( seat, errorInfo ) < 0 ) { fprintf( stderr, "ERROR: bad action format in response\n" ); } fprintf( stderr, "WARNING: bad action format in response, changed to call\n" ); action->type = a_call; action->size = 0; goto doneRead; } c += r; /* make sure the action is valid */ if( !isValidAction( game, &state->state, 1, action ) ) { if( checkErrorInvalidAction( seat, errorInfo ) < 0 ) { fprintf( stderr, "ERROR: invalid action\n" ); return -1; } fprintf( stderr, "WARNING: invalid action, changed to call\n" ); action->type = a_call; action->size = 0; } goto doneRead; } doneRead: return 0; }
int main( int argc, char **argv ) { int sock, len, r; int32_t min, max; uint16_t port; Game *game; MatchState state; Action action; struct sockaddr_in addr; struct hostent *hostent; FILE *file, *toServer, *fromServer; char line[ MAX_LINE_LEN ]; if( argc < 4 ) { fprintf( stderr, "usage: player game server port\n" ); exit( EXIT_FAILURE ); } file = fopen( argv[ 1 ], "r" ); if( file == NULL ) { fprintf( stderr, "ERROR: could not open game %s\n", argv[ 1 ] ); exit( EXIT_FAILURE ); } game = readGame( file ); if( game == NULL ) { fprintf( stderr, "ERROR: could not read game %s\n", argv[ 1 ] ); exit( EXIT_FAILURE ); } fclose( file ); hostent = gethostbyname( argv[ 2 ] ); if( hostent == NULL ) { fprintf( stderr, "ERROR: could not look up address for %s\n", argv[ 2 ] ); exit( EXIT_FAILURE ); } if( sscanf( argv[ 3 ], "%"SCNu16, &port ) < 1 ) { fprintf( stderr, "ERROR: invalid port %s\n", argv[ 3 ] ); exit( EXIT_FAILURE ); } if( ( sock = socket( AF_INET, SOCK_STREAM, 0 ) ) < 0 ) { fprintf( stderr, "ERROR: could not open socket\n" ); exit( EXIT_FAILURE ); } addr.sin_family = AF_INET; addr.sin_port = htons( port ); memcpy( &addr.sin_addr, hostent->h_addr_list[ 0 ], hostent->h_length ); if( connect( sock, (struct sockaddr *)&addr, sizeof( addr ) ) < 0 ) { fprintf( stderr, "ERROR: could not open connect to %s:%"PRIu16"\n", argv[ 2 ], port ); exit( EXIT_FAILURE ); } toServer = fdopen( sock, "w" ); fromServer = fdopen( sock, "r" ); if( toServer == NULL || fromServer == NULL ) { fprintf( stderr, "ERROR: could not get socket streams\n" ); exit( EXIT_FAILURE ); } if( fprintf( toServer, "VERSION:%"PRIu32".%"PRIu32".%"PRIu32"\n", VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION ) != 14 ) { fprintf( stderr, "ERROR: could not get send version to server\n" ); exit( EXIT_FAILURE ); } fflush( toServer ); while( fgets( line, MAX_LINE_LEN, fromServer ) ) { /* ignore comments */ if( line[ 0 ] == '#' || line[ 0 ] == ';' ) { continue; } len = readMatchState( line, game, &state ); if( len < 0 ) { fprintf( stderr, "ERROR: could not read state %s", line ); exit( EXIT_FAILURE ); } if( stateFinished( &state.state ) ) { /* ignore the game over message */ continue; } if( currentPlayer( game, &state.state ) != state.viewingPlayer ) { /* we're not acting */ continue; } int bucket = computeHandValue(game,&state.state,state.viewingPlayer,min,max); /* add a colon (guaranteed to fit because we read a new-line in fgets) */ line[ len ] = ':'; ++len; //if( ( random() % 2 ) && raiseIsValid( game, &state.state, &min, &max ) ) { /* raise */ if ((bucket >= 3) && raiseIsValid(game, &state.state, &min, &max)) { action.type = raise; action.size = min + random() % ( max - min + 1 ); } else if (bucket >=2) { /* call */ action.type = call; action.size = 0; } else{ action.type = fold; action.size = 0; } if( !isValidAction( game, &state.state, 0, &action ) ) { fprintf( stderr, "ERROR: chose an invalid action\n" ); exit( EXIT_FAILURE ); } r = printAction( game, &action, MAX_LINE_LEN - len - 1, &line[ len ] ); if( r < 0 ) { fprintf( stderr, "ERROR: line too long after printing action\n" ); exit( EXIT_FAILURE ); } len += r; line[ len ] = '\n'; ++len; if( fwrite( line, 1, len, toServer ) != len ) { fprintf( stderr, "ERROR: could not get send response to server\n" ); exit( EXIT_FAILURE ); } fflush( toServer ); } return EXIT_SUCCESS; }
/* returns >= 0 if action/size has been set to a valid action returns -1 for failure (disconnect, timeout, too many bad actions, etc) */ static int readPlayerResponse( const Game *game, const MatchState *state, const int quiet, const uint8_t seat, const struct timeval *sendTime, ErrorInfo *errorInfo, int seatFD, ReadBuf *readBuf, Action *action, struct timeval *recvTime ) { int c, r; MatchState tempState; char line[ MAX_LINE_LEN ]; while( 1 ) { /* read a line of input from player */ if( getLine( seatFD, readBuf, MAX_LINE_LEN, line, errorInfo->maxResponseMicros ) <= 0 ) { /* couldn't get any input from player */ fprintf( stderr, "ERROR: could not get action from seat %"PRIu8"\n", seat + 1 ); return -1; } /* note when the message arrived */ gettimeofday( recvTime, NULL ); /* log the response */ if( !quiet ) { fprintf( stderr, "FROM %d at %zu.%06zu %s", seat + 1, recvTime->tv_sec, recvTime->tv_usec, line ); } /* ignore comments */ if( line[ 0 ] == '#' || line[ 0 ] == ';' ) { continue; } /* check for any timeout issues */ if( checkErrorTimes( seat, sendTime, recvTime, errorInfo ) < 0 ) { fprintf( stderr, "ERROR: seat %"PRIu8" ran out of time\n", seat + 1 ); return -1; } /* parse out the state */ c = readMatchState( line, game, &tempState ); if( c < 0 ) { /* couldn't get an intelligible state */ fprintf( stderr, "WARNING: bad state format in response\n" ); continue; } /* ignore responses that don't match the current state */ if( !matchStatesEqual( game, state, &tempState ) ) { fprintf( stderr, "WARNING: ignoring un-requested response\n" ); continue; } /* get the action */ if( line[ c++ ] != ':' || ( r = readAction( &line[ c ], game, action ) ) < 0 ) { if( checkErrorInvalidAction( seat, errorInfo ) < 0 ) { fprintf( stderr, "ERROR: bad action format in response\n" ); } fprintf( stderr, "WARNING: bad action format in response, changed to call\n" ); action->type = call; action->size = 0; goto doneRead; } c += r; /* make sure the action is valid */ if( !isValidAction( game, &state->state, 1, action ) ) { if( checkErrorInvalidAction( seat, errorInfo ) < 0 ) { fprintf( stderr, "ERROR: invalid action\n" ); return -1; } fprintf( stderr, "WARNING: invalid action, changed to call\n" ); action->type = call; action->size = 0; } goto doneRead; } doneRead: return 0; }