/* This is used when the player is moving one of her pieces that is * already on the board to a new space. * * Return true iff the current player can place the piece in board * position (x,y). * * We can move the old piece here if * 0) Target space is empty, * AND * 1a) Moving to an unoccupied neighboring space, OR * 1b) Moving to an unoccupied space that is one jump over a neighbor * AND * 2) The move does not result in disconnected board * AND * 3) Target space is still adjacent to an existing piece (could be our own * piece or an enemy piece, doesn't matter) * * Hint: you may want to use checkNbrs, isNeighboringSpace, * isJumpSpace, and isConnected as subroutines here. */ bool canPlaceOldPiece(int x, int y){ //TODO int target = 20*y+x; if ((board[target]->type == 0) && (isNeighboringSpace(x,y) || isJumpSpace(x,y))) if(stillConnected(x,y)) return true; return false; }
//***************************************************************************** // // Method: me_write // // Purpose: // // This method writes a number of bytes to the communications channel. // // Returns: // // > 0 - write succeeded // -1 - write failed // // Arguments: // // I const char *buffer - buffer to write // I int length - number of bytes to write // // History: // // Date Author Reason // ==== ====== ====== // // 27/11/97 Geoff Glasson Original version // //***************************************************************************** int TcpSocket::write ( const char * pBuffer, // Buffer to write const int pLength ) // Number of bytes to write { // // Write the buffer to the socket. // try { // // If the socket is not connected then we can't really write to // it. // if( false == stillConnected() ) { //throw exception std::ostringstream streamErrInfo; std::string strErrorInfo; streamErrInfo << "Not connected"; strErrorInfo = streamErrInfo.str(); throw std::exception(strErrorInfo.c_str()); } _LOG(SourceFLInfo, DebugDebug, "Attempting to write %d bytes to socket", pLength ); // // Write the data to the stream. Under UNIX we will retry if there is a // write already in progream. // const char * lvPacket; const int lvMaxPacketLength = 1024; int lvPacketLength; int lvProgressing = 1; int lvTransferredBytes = 0; lvPacket = pBuffer; int lvNumberOfBytesWritten = 0; do { // // Determine the amount of data to be transferred. The maximum packet // size is defined by lv_max_packet_length. // lvPacketLength = ( pBuffer + pLength) - lvPacket; if ( lvMaxPacketLength < lvPacketLength ) { lvPacketLength = lvMaxPacketLength; } #if !defined( WIN32 ) LOG (SourceInfo, TA_Base_Core::DebugUtil::GenericLog, TA_Base_Core::DebugUtil::DebugDebug, "About to write %d bytes to socket", lvPacketLength ); lvNumberOfBytesWritten = ::write( socketId, lvPacket, lvPacketLength ); int lvErrno = errno; if ( -1 == lvNumberOfBytesWritten ) { LOG (SourceInfo, TA_Base_Core::DebugUtil::GenericLog, TA_Base_Core::DebugUtil::DebugWarn, "Failed to write to socket: %s", strerror( lvErrno ) ); // // If a write is in progress, sleep for 0.1 second2. // struct timespec lvSleepTime = { 0, #if defined( SOLARIS ) ( unsigned long )( 0.1 * NANOSEC ) #else // !defined( SOLARIS ) ( unsigned long )( 0.1 * 1000000000 ) #endif // !defined( SOLARIS ); }; nanosleep( & lvSleepTime, NULL ); } #else // defined( WIN32 ) //lvNumberOfBytesWritten = ::send( socketId, pBuffer, pLength, 0 ); lvNumberOfBytesWritten = ::send( socketId, lvPacket, lvPacketLength, 0 ); int lvErrno = 0; if ( SOCKET_ERROR == lvNumberOfBytesWritten ) { lvErrno = WSAGetLastError(); if ( WSAEALREADY == lvErrno ) { _LOG(SourceFLInfo, DebugDebug, "Write in progress => waiting 1 millisecond before trying again"); // // If a write is in progress, sleep for one millisecond then // try again. // Sleep( 1 ); } } #endif // WIN32 else { if ( 0 != lvNumberOfBytesWritten ) { lvTransferredBytes += lvNumberOfBytesWritten; } else { _LOG(SourceFLInfo, DebugDebug, "Wrote %d bytes to the socket", lvNumberOfBytesWritten); } if ( lvPacketLength == lvNumberOfBytesWritten ) { lvPacket += lvMaxPacketLength; } } // // Determine if the transfer is progressing. // lvProgressing = 1; if ( ( EBADF == lvErrno ) || ( ENXIO == lvErrno ) || ( EPIPE == lvErrno ) || ( lvPacket > & pBuffer[ pLength - 1 ] ) ) { lvProgressing = 0; } #ifndef WIN32 if ( ( ECONNRESET == lvErrno ) || ( ENOTCONN == lvErrno ) || ( ECONNABORTED == lvErrno ) ) #else // !WIN32 if ( ( WSAECONNRESET == lvErrno ) || ( WSAENOTCONN == lvErrno ) || ( WSAECONNABORTED == lvErrno ) ) #endif // WIN32 { m_isDisconnected = true; lvProgressing = 0; } } while ( 0 != lvProgressing ); return lvTransferredBytes; } // // Deal with MS Visual C++ exceptions. // catch ( const unsigned int ) { //throw exception std::ostringstream streamErrInfo; std::string strErrorInfo; streamErrInfo << "Unknown Microsoft exception caught"; strErrorInfo = streamErrInfo.str(); throw std::exception(strErrorInfo.c_str()); } }
//***************************************************************************** // // Method: me_read // // Purpose: // // This method reads a number of bytes from the channel. It returns the // number of bytes read from the channel. The method determines if the // client is still connected, and throws an exception if it is not. The // checking works as follows: // // If there is a socket ready for reading and there is no data to be read, // then the socket may not be connected. After COMMS_CHECK_TIME seconds, // the client is "pinged" and if there is no response, the client is // assumed to have disconnected. In this case, an exception is thrown. If // a response is received, the method waits for another COMMS_CHECK_TIME // seconds before checking the connection status again. // // Returns: // // 0 - read succeeded // non-0 - read failed // // Arguments: // // O char *buffer - buffer to read into // O unsigned int *length - number of bytes read // I unsigned int max_length - maximum length of the buffer // // History: // // Date Author Reason // ==== ====== ====== // // 19/08/98 Geoff Glasson Channel now detects when the remote connection // is closed unexpectedly and throws an // CHANNEL_EX_COMMS_LOST exception. // // 12/01/97 Geoff Glasson Added code to determine if the connection to the // client is down. It throws an exception so that // higher level routines can figure out what to do. // // 27/11/97 Geoff Glasson Original version // //***************************************************************************** int TcpSocket::read ( char *pBuffer, // Buffer to read into unsigned int *pLength, // Number of bytes read const unsigned int pMaxLength) // Maximum length of the buffer { // // Do some validation. // //TA_DEBUG_ASSERT( 0 != pBuffer, "NULL pointer passed for read buffer" ); //TA_DEBUG_ASSERT( 0 != pLength , "Zero length read requested" ); //TA_DEBUG_ASSERT( 0 < pMaxLength , "Buffer length is zero or less" ); try { // // If the socket is not connected then we can't really read from // it. // if( false == stillConnected() ) { pBuffer[ 0 ] = '\0'; *pLength = 0; std::ostringstream streamErrInfo; std::string strErrorInfo; streamErrInfo << "Not connected"; strErrorInfo = streamErrInfo.str(); throw std::exception(strErrorInfo.c_str()); } // // Read max_length bytes from the socket. // *pLength = 0; fd_set lvIdset; FD_ZERO( & lvIdset); FD_SET( socketId, & lvIdset ); #if !defined( WIN32 ) const int lvNumReady = select( FD_SETSIZE, & lvIdset, ( fd_set * )0, ( fd_set * )0, & m_readingTimeout ); #else //xinsong ++ //it seems that the timeout does not work properly when running in win32 const int lvNumReady = select( FD_SETSIZE, & lvIdset, ( fd_set * )0, ( fd_set * )0, NULL ); #endif _LOG(SourceFLInfo, DebugInfo, "Number of ready sockets: %d", lvNumReady ); // For Blocking sockets, select is in error if <=0 // For NonBlocking sockets, select is in error if <0 if ( (isBlocking && lvNumReady <= 0) || (!isBlocking && lvNumReady < 0) ) { #if !defined( WIN32 ) const int lvErrno = errno; #else // defined( WIN32 ) const int lvErrno = WSAGetLastError(); #endif // defined( WIN32 ) if ( EINTR == lvErrno ) { _LOG(SourceFLInfo, DebugInfo, "Interrupted system call" ); return 0; } std::string lvMessage = "Unable to read from socket - "; #if !defined( WIN32 ) lvMessage.append( strerror( errno ) ); #else // defined( WIN32 ) LPVOID lpMsgBuf; FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, WSAGetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPTSTR) &lpMsgBuf, 0, NULL ); lvMessage.append( ( char * )lpMsgBuf ); LocalFree( lpMsgBuf ); #endif // defined( WIN32 ) m_isDisconnected = true; //throw exception std::ostringstream streamErrInfo; std::string strErrorInfo; streamErrInfo << lvMessage; strErrorInfo = streamErrInfo.str(); throw std::exception(strErrorInfo.c_str()); } if ( lvNumReady != 0 ) { if ( false == FD_ISSET( socketId, & lvIdset ) ) { #if !defined( WIN32 ) if ( ECONNRESET == errno || ENOTCONN == errno ) #else // defined( WIN32 ) if ( WSAECONNRESET == WSAGetLastError() || WSAENOTCONN == WSAGetLastError() ) #endif // defined( WIN32 ) { m_isDisconnected = true; //throw exception std::ostringstream streamErrInfo; std::string strErrorInfo; streamErrInfo << "Connection closed unexpectedly"; strErrorInfo = streamErrInfo.str(); throw std::exception(strErrorInfo.c_str()); } else { #if !defined( WIN32 ) return errno; #else // defined( WIN32 ) return WSAGetLastError(); #endif // defined( WIN32 ) } } #if !defined( WIN32 ) const int lvStatus = ::read( socketId, ( void * )pBuffer, pMaxLength ); #else // defined( WIN32 ) const int lvStatus = recv( socketId, pBuffer, pMaxLength, 0 ); #endif // defined( WIN32 ) if( 0 <= lvStatus ) { * pLength = lvStatus; pBuffer[ * pLength ] = '\0'; _LOG(SourceFLInfo, DebugDebug, "Read %d bytes from socket", lvStatus ); } else { _LOG(SourceFLInfo, DebugDebug, "No data returned from socket" ); } } } // // Handle Windows exceptions. // catch ( const unsigned int ) { //throw exception std::ostringstream streamErrInfo; std::string strErrorInfo; streamErrInfo << "Unexpected Microsoft exception caught"; strErrorInfo = streamErrInfo.str(); throw std::exception(strErrorInfo.c_str()); } // // Done. // return (0); }