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; }