Exemple #1
0
bool InternetChessPlayer::receive (
    ChessBoard &board,
    Move &move )
{
    char tempString [256];
    for(;;)
    {
        UINT32 packetSize = 0;
        int result = ::recv ( connectInfo.commSocket, (char *)&packetSize, 4, 0 );
        if ( result != 4 )
        {
            sprintf ( tempString, "recv psize: %d", WSAGetLastError() );
            userInterface.ReportSpecial (tempString);
            return false;
        }

        char inMessageType [16];
        memset ( inMessageType, 0, sizeof(inMessageType) );
        result = ::recv ( connectInfo.commSocket, inMessageType, 8, 0 );
        if ( result != 8 )
        {
            sprintf ( tempString, "recv(message): %d", WSAGetLastError() );
            userInterface.ReportSpecial (tempString);
            return false;
        }

        if ( strcmp ( inMessageType, "history " ) == 0 )
        {
            // Receive the number of plies from the other side...

            int numPlies = 0;
            result = ::recv ( connectInfo.commSocket, (char *)&numPlies, sizeof(int), 0 );
            if ( result != sizeof(int) )
            {
                sprintf ( tempString, "recv(numPlies): size=%d err=%d", result, WSAGetLastError() );
                userInterface.ReportSpecial (tempString);
                return false;
            }

            if ( numPlies > 0 )
            {
                if ( numPlies > 1024 )
                {
                    sprintf ( tempString, "numPlies = %d", numPlies );
                    userInterface.ReportSpecial (tempString);
                    return false;
                }

                Move *history = new Move [numPlies];
                if ( !history )
                {
                    userInterface.ReportSpecial ( "out of memory!" );
                    return false;
                }

                int plyBytes = numPlies * sizeof(Move);
                result = ::recv ( connectInfo.commSocket, (char *)history, plyBytes, 0 );
                if ( result != plyBytes )
                {
                    sprintf ( tempString, "recv: size=%d err=%d", result, WSAGetLastError() );
                    userInterface.ReportSpecial (tempString);
                    return false;
                }

                // Now that we safely have the game history from the opponent,
                // we can reset the board and apply all but the final ply to the board.
                // The final ply is returned as the move made by the InternetChessPlayer
                // so that it can be animated on the board display.

                UnmoveInfo unmove;
                board.Init();
                for ( int ply = 0; ply < numPlies-1; ++ply )
                {
                    Move hm = history[ply];
                    if ( (hm.dest & SPECIAL_MOVE_MASK) == SPECIAL_MOVE_EDIT )
                    {
                        board.EditCommand ( hm );
                        board.SaveSpecialMove ( hm );
                    }
                    else
                        board.MakeMove ( hm, unmove );
                }

                move = history [numPlies - 1];
                delete[] history;
            }

            break;
        }
        else if ( strcmp ( inMessageType, "resign  " ) == 0 )
        {
            SetQuitReason(qgr_resign);
            return false;   // remote player has resigned
        }
        else  // unknown message, perhaps from a later version of Chenard
        {
            // eat all the bytes in the message and ignore them

            int bytesLeft = int(packetSize) - 8;
            char trash;
            while ( bytesLeft-- > 0 )
                ::recv ( connectInfo.commSocket, &trash, 1, 0 );
        }
    }

    return true;
}