diff options
Diffstat (limited to 'knights/io_internet.cpp')
-rw-r--r-- | knights/io_internet.cpp | 1138 |
1 files changed, 1138 insertions, 0 deletions
diff --git a/knights/io_internet.cpp b/knights/io_internet.cpp new file mode 100644 index 0000000..e5325cd --- /dev/null +++ b/knights/io_internet.cpp @@ -0,0 +1,1138 @@ +/*************************************************************************** + io_internet.cpp - description + ------------------- + begin : Thu Aug 16 2001 + copyright : (C) 2003 by Troy Corbin Jr. + email : tcorbin@users.sourceforge.net + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +/* KDE */ +#include <ksock.h> +#include <kprocess.h> +#include <kmessagebox.h> + +/* Qt */ +#include <qobject.h> +#include <qwidget.h> +#include <qregexp.h> +#include <qdns.h> +#include <qsocket.h> +#include <qptrlist.h> + +/* Local */ +#include "io_internet.moc" +#include "resource.h" +#include "dlg_login.h" +#include "dlg_challenge.h" +#include "match.h" +#include "core.h" +#include "audio.h" +#include "../config.h" + +static const int TXT_Std = 0; +static const int TXT_Pvt = 1; +static const int TXT_Ch = 2; +static const int TXT_Sht = 3; +static const int TXT_Wsp = 4; +static const int TXT_Not = 5; + +io_internet::io_internet( QWidget *parent, resource *rsrc ) +{ + myResource = rsrc; + challenge = NULL; + myTimeseal = NULL; + socket = NULL; + loginStage = LOGIN_STAGE_NAME; + lineBuffer = ""; + Log = NULL; + + /* set type */ + this->myType = io_base::INTERNET; + + /* initialize various variables */ + this->waiting_for_move_list = false; + this->myParent = parent; + connected = false; /* we are not connected to a server */ + + /* create the login dialog and show it to the user */ + loginDlg = new dlg_login( myParent, "LoginDialog", myResource); + connect(loginDlg, SIGNAL( okClicked() ), this, SLOT( connectToServer() ) ); + connect(loginDlg, SIGNAL( cancelClicked() ), this, SLOT( selfDestruct() ) ); + connect(loginDlg, SIGNAL( login(QString, QString) ), this, SLOT( setUserInfo(QString, QString) ) ); +} + +/////////////////////////////////////////////////////////// +// Destructor +/////////////////////////////////////////////////////////// +io_internet::~io_internet() +{ + TabMap::Iterator i; + + /* Close and remove socket */ + if( socket != NULL ) + { + if(socket->socket() != -1) + { + send("quit"); + } + delete socket; + } + /* Close and remove logfile */ + if( Log ) + { + Log->close(); + delete Log; + Log = NULL; + } + /* Remove Timeseal */ + if( myTimeseal != NULL ) + { + myTimeseal->kill(); + delete myTimeseal; + } + /* Close and remove Tabs */ + + for(i = myTabList.begin(); i != myTabList.end(); i++) + { + if(myResource->tabManager->isTab(*i)) + { + myResource->tabManager->removeTab(*i); + } + } +} + +void io_internet::connectToServer() +{ + serverList::iterator i; + QWidget *tempTab; + QWidget *consoleTab; + QValueList<Command>::iterator j; + + qApp->mainWidget()->setCursor( myResource->CURSOR_Thinking ); + /* Get and parse server config from resource */ + myServer = NULL; + for( i = myResource->servers.begin(); i != myResource->servers.end(); i++ ) + { + if( (*i).CurrentRef ) + { + myServer = &(*i); + } + } + if(myServer == NULL) + { + /* No server configured. Notify User and die gracefully */ + qApp->mainWidget()->setCursor( myResource->CURSOR_Standard ); + kdError() << "internetio::internetio: Can not find server resource CurrentRef " << endl; + KMessageBox::sorry( (QWidget*)myParent, i18n( "There are no servers configured.\nPlease make sure you have at least one server configured." ), i18n( "Cannot find a server.")); + QApplication::postEvent( qApp->mainWidget(), new QCustomEvent( EVENT_Del_IO_Net ) ); + return; + } + + if(myServer->Port == 0) + { + myServer->Port = 5000; + } + + if(!myServer->Timeseal.isEmpty()) + { + myTimeseal = new KProcess(); + (*myTimeseal) << myServer->Timeseal << myServer->URL << QString().setNum( myServer->Port ) + << QString( "-p" ) << QString().setNum(myServer->Port + 1); + if(!myTimeseal->start()) + { + /* Couldn't start Timeseal. Notify User and die gracefully */ + qApp->mainWidget()->setCursor( myResource->CURSOR_Standard ); + KMessageBox::sorry( (QWidget*)myParent, i18n( "Knights can not start Timeseal.\nPlease make sure you have the correct path and filename configured." ), i18n( "Cannot find Timeseal.")); + QApplication::postEvent( qApp->mainWidget(), new QCustomEvent( EVENT_Del_IO_Net ) ); + return; + } + socket = new KSocket("127.0.0.1", myServer->Port + 1, 30); + if(socket->socket() == -1) + { + /* try again on a different port, somehow the port hasn't been freed yet */ + delete socket; + myTimeseal->kill(); + + myTimeseal = new KProcess(); + (*myTimeseal) << myServer->Timeseal << myServer->URL << QString().setNum( myServer->Port ) + << QString( "-p" ) << QString().setNum(myServer->Port + 2); + if(!myTimeseal->start()) + { + /* Couldn't start Timeseal. Notify User and die gracefully */ + qApp->mainWidget()->setCursor( myResource->CURSOR_Standard ); + KMessageBox::sorry( (QWidget*)myParent, i18n( "Knights can not start Timeseal.\nPlease make sure you have the correct path and filename configured." ), i18n( "Cannot find Timeseal.")); + QApplication::postEvent( qApp->mainWidget(), new QCustomEvent( EVENT_Del_IO_Net ) ); + return; + } + socket = new KSocket("127.0.0.1", myServer->Port + 2, 30); + if(socket->socket() == -1) + { + /* if we can't do it the second time, give up */ + /* Couldn't connect to server through Timeseal. Notify User and die gracefully */ + qApp->mainWidget()->setCursor( myResource->CURSOR_Standard ); + KMessageBox::sorry( (QWidget*)myParent, i18n( "Knights is unable to connect to the server.\n Please make sure your internet connection is working and try again."), i18n( "Cannot connect to server(timeseal).")); + QApplication::postEvent( qApp->mainWidget(), new QCustomEvent( EVENT_Del_IO_Net ) ); + return; + } + } + } + else + { + socket = new KSocket(myServer->URL, myServer->Port, 30); + if(socket->socket() == -1) + { + /* Couldn't connect to server. Notify User and die gracefully */ + qApp->mainWidget()->setCursor( myResource->CURSOR_Standard ); + KMessageBox::sorry( (QWidget*)myParent, i18n( "Knights is unable to connect to the server.\n Please make sure your internet connection is working and try again."), i18n( "Cannot connect to server.")); + QApplication::postEvent( qApp->mainWidget(), new QCustomEvent( EVENT_Del_IO_Net ) ); + return; + } + } + socket->enableRead(true); + socket->enableWrite(true); + + /* connect a signal to readReady */ + connect(socket, SIGNAL(readEvent(KSocket *)), this, SLOT(readCommand(KSocket *))); + + /* setup the seekTimer and turn it off by default */ + seekTimer = new QTimer(this); + connect(seekTimer, SIGNAL(timeout()), this, SLOT(processSeekTimer())); + + /* succesfully connected to the server, turn connected on and flush the command buffer */ + connected = true; + for(j = myCommandBuffer.begin(); j != myCommandBuffer.end(); j++) + { + recvCMD(*j); + } + + /* + Create ICS Related Tabs + + These will need to be moved into thier own functions because we want to be able to open + and close these tabs at will, or have multiple open at once. ALL communication to our tabs + needs to be done with SIGNALS & SLOTS to facilitate this. + */ + consoleTab = new Console( 0, myServer->Name, myResource ); + myTabList[consoleTab] = consoleTab; + myResource->tabManager->addTab( myTabList[consoleTab], i18n( "%1 Console" ).arg( myServer->Name ) ); + connect( myTabList[consoleTab], SIGNAL( sendCMD( const Command& ) ), this, SLOT( recvCMD( const Command& ) ) ); + connect( this, SIGNAL( sendCMD( const Command& ) ), myTabList[consoleTab], SLOT( recvCMD( const Command& ) ) ); + + tempTab = new tab_SeekList( 0, "seekList", myResource ); + myTabList[tempTab] = tempTab; + myResource->tabManager->addTab( myTabList[tempTab], i18n( "Sought Matches List" ) ); + connect( myTabList[tempTab], SIGNAL( sendCMD( const Command& ) ), this, SLOT( recvCMD( const Command& ) ) ); + connect( this, SIGNAL( sendCMD( const Command& ) ), myTabList[tempTab], SLOT( recvCMD( const Command& ) ) ); + + tempTab = new Challenge_Graph( 0, "seekGraph", myResource ); + myTabList[tempTab] = tempTab; + myResource->tabManager->addTab( myTabList[tempTab], i18n( "Sought Matches Graph" ) ); + connect( myTabList[tempTab], SIGNAL( sendCMD( const Command& ) ), this, SLOT( recvCMD( const Command& ) ) ); + connect( this, SIGNAL( sendCMD( const Command& ) ), myTabList[tempTab], SLOT( recvCMD( const Command& ) ) ); + + myResource->tabManager->showTab(consoleTab); + + /* ...log file */ + if( !myServer->LogFile.isEmpty() ) + { + Log = new QFile( myServer->LogFile ); + if( !Log->open( IO_WriteOnly | IO_Append ) ) + { + if( !Log->open( IO_WriteOnly ) ) + { + kdError() << "Can not open " << myServer->LogFile << " for writing." << endl; + } + } + } + qApp->mainWidget()->setCursor( myResource->CURSOR_Standard ); +} + +void io_internet::recvCMD(const Command& command) +{ + QString error_message; + + if(!connected) + { + myCommandBuffer.push_back(command); + return; + } + + switch(((Command)command).getCommand()) + { + case CMD_Move: + send(((Command)command).getMove().SAN); + break; + case CMD_Reset_Server: + sendUserSettings(); + break; + case CMD_Toggle_Seek: + if(seekTimer->isActive()) + { + /* timer running stop it */ + seekTimer->stop(); + emit sendCMD( Command( 0, CMD_Hide_Sought_List ) ); + } + else + { + /* timer not running start it */ + seekTimer->start(myResource->Seek_Timer * 100); + /* send a sought now */ + processSeekTimer(); + } + break; + case CMD_Player_Finger: + send("$finger " + ((Command)command).getData()); + break; + case CMD_Add_Friend: + send("$+notify " + ((Command)command).getData()); + break; + case CMD_Ignore_Player: + send("$+censor " + ((Command)command).getData()); + break; + case CMD_Player_History: + send("$history " + ((Command)command).getData()); + break; + case CMD_Start_Match: + send("$play " + ((Command)command).getData()); + break; + case CMD_Assess: + send("$assess " + ((Command)command).getData()); + break; + case CMD_Set_Input: + sendCMD( command ); + break; + case CMD_Send_To_ICS: + if(((Command)command).getData().contains(QRegExp("^(?:\\.|tell)"))) + { + writeToConsole(((Command)command).getData(), "K_PVT"); + } + send(((Command)command).getData()); + break; + case CMD_Examine_Forward: + send("$forward 1"); + break; + case CMD_Examine_Backward: + send("$backward 1"); + break; + case CMD_White_Resign: + case CMD_Black_Resign: + send("$resign"); + break; + case CMD_Offer_Draw: + send("$draw"); + break; + case CMD_Reject_Draw: + send("$decline t draw"); + break; + default: + /* do nothing unknown command */ + kdWarning() << "InternetIO::sendCMD received an unknown command: " << ((Command)command).getCommand() << endl; + } +} + +/////////////////////////////////////// +// +// io_internet::send +// +/////////////////////////////////////// +void io_internet::send(const QString& msg) +{ + QString tmp(msg); + ssize_t len; + + /* Attach events to specific outgoing text */ + if( ( tmp == "accept" ) || + ( tmp == "decline" ) || + ( tmp.left(6) == "match " ) ) + { + if( challenge != NULL ) + { + delete challenge; + nullifyChallenge(); + } + } + if( tmp.right(1) != "\n" ) + { + tmp += "\n"; + } + + len = write(socket->socket(), tmp.latin1(), tmp.length() ); + + if( Log ) + { + Log->writeBlock( QString("<< ").latin1(), 3 ); + Log->writeBlock( tmp.latin1(), tmp.length() ); + } + if( len < (signed)tmp.length() ) + { + kdWarning() << "io_internet::Send: Failed to write full block of data to socket." << endl; + } +} + +/////////////////////////////////////// +// +// io_internet::readCommand +// +/////////////////////////////////////// +void io_internet::readCommand(KSocket* socket) +{ + char buffer[READ_BUFFER_SIZE]; + QString tmp; + QStringList lines; + + memset(buffer, 0, READ_BUFFER_SIZE); + read(socket->socket(), buffer, READ_BUFFER_SIZE); + tmp = buffer; + + tmp = lineBuffer + tmp; + if( Log ) + { + Log->writeBlock( tmp.latin1(), tmp.length() ); + } + if(loginStage != LOGIN_STAGE_LOGGED_IN) + { + // route all the data to the login parser + parseLoginData(tmp); + this->parseMode = NORMAL_MODE; + } + else + { + lines = QStringList::split( QRegExp("\n\r?"), tmp, FALSE ); + if(!(tmp.endsWith("\n\r") || tmp.endsWith("\n"))) + { + lineBuffer = (*(--lines.end())); + } + else + { + lineBuffer = ""; + } + for(QStringList::iterator i = lines.begin(); i != lines.end(); i++) + { + if(lineBuffer == "" || i != --lines.end()) + { + (*i).replace( QRegExp( "\\a" ), "" ); + parseLine(*i); + } + } + } +} +/////////////////////////////////////// +// +// io_internet::sendUserName +// +/////////////////////////////////////// +void io_internet::sendUserName() +{ + loginStage = LOGIN_STAGE_PASSWORD; + send(userName); +} +/////////////////////////////////////// +// +// io_internet::sendPassword +// +/////////////////////////////////////// +void io_internet::sendPassword() +{ + send(passWord); +} + +/////////////////////////////////////// +// +// io_internet::parseLoginData +// +/////////////////////////////////////// +void io_internet::parseLoginData( QString data ) +{ + QStringList lines; + + if(loginStage == LOGIN_STAGE_NAME) + { + if(data.contains( "login:" )) + { + sendUserName(); + } + lines = QStringList::split( QRegExp("\n\r?"), data, FALSE ); + for(QStringList::iterator i = lines.begin(); i != lines.end(); i++) + { + writeToConsole((*i), "K_STD"); + } + } + else if(loginStage == LOGIN_STAGE_PASSWORD) + { + if(data.contains("**** Invalid password! ****") || + data.contains("Sorry, names can only consist of lower and upper case letters. Try again.") || + data.contains("If you are not a registered player, enter guest or a unique ID.")) + { + loginDlg = new dlg_login( myParent, "LoginDialog", myResource); + loginDlg->disableServerSelect(); + connect(loginDlg, SIGNAL( okClicked() ), this, SLOT( sendUserName() ) ); + connect(loginDlg, SIGNAL( cancelClicked() ), this, SLOT( selfDestruct() ) ); + connect(loginDlg, SIGNAL( login(QString, QString) ), this, SLOT( setUserInfo(QString, QString) ) ); + } + else if(data.contains("Press return to enter the server as")) + { + QRegExp guestName("Logging you in as \"(\\w*)\""); + int pos = guestName.search(data); + if(pos > -1) + { + userName = guestName.cap(1); + } + send("\n"); + } + else if(data.contains("password:")) + { + sendPassword(); + } + else + { + loginStage = LOGIN_STAGE_LOGGED_IN; + sendUserSettings(); + } + lines = QStringList::split( QRegExp("\n\r?"), data, FALSE ); + for(QStringList::iterator i = lines.begin(); i != lines.end(); i++) + { + writeToConsole((*i), "K_STD"); + } + } + else + { + lines = QStringList::split( QRegExp("\n\r?"), data, FALSE ); + for(QStringList::iterator i = lines.begin(); i != lines.end(); i++) + { + writeToConsole((*i), "K_STD"); + } + } +} + +/////////////////////////////////////// +// +// io_internet::ParseLine +// +/////////////////////////////////////// +void io_internet::parseLine( QString line ) +{ + int i, j; + QString tmp; + + switch(parseMode) + { + case NORMAL_MODE: /* determine which mode we should go into */ + if(line.contains(QRegExp("^\\s*\\d{1,3}\\s+(?:\\d{1,4}|\\+\\+\\+\\+|\\-\\-\\-\\-)\\s+\\w{3,17}(\\(C\\))?\\s+\\d{1,3}\\s+\\d{1,3}"))) + { + updateSoughtList(line); + parseMode = UPDATE_SOUGHT_MODE; + } + /* CHALLENGE */ + else if( line.contains(QRegExp("^\\s*Challenge: "))) + { + myResource->play( SND_CHALLENGE ); + if( challenge != NULL ) + { + delete challenge; + } + challenge = new dlg_challenge( 0, "Challenge", myResource ); + connect( challenge, SIGNAL( destroyed() ), this, SLOT( nullifyChallenge() ) ); + connect( challenge, SIGNAL( user1Clicked() ), this, SLOT( acceptChallenge() ) ); + connect( challenge, SIGNAL( user2Clicked() ), this, SLOT( declineChallenge() ) ); + line.replace(QRegExp("^\\s*Challenge: "), ""); + challenge->setValues( line, userName ); + parseMode = CHALLENGE_MODE; + } + else if( ( line.left(15) == "Challenge from " ) && ( line.right(9) == " removed." ) ) + { + if( challenge != NULL ) + { + delete challenge; + } + } + /* SOUGHT GAME */ + else if(line.contains("seeking")) + { + // writeToConsole("seeking", "K_CH"); + } + /* PRIVATE TELL */ + else if(line.contains(QRegExp(".+ tells you: .*"))) + { + /* First grab the user name so we can auto-respond later */ + emit sendCMD( Command( 0, CMD_Set_Src_Tell, line.section(' ', 0, 0) ) ); + myResource->play( SND_TELL ); + writeToConsole(line, "K_PVT"); + } + /* SAY */ + else if(line.contains( QRegExp(".+ says: .*"))) + { + myResource->play(SND_SAY); + writeToConsole(line, "K_PVT"); + return; + } + /* WHISPER & KIBITZ */ + else if(line.contains(QRegExp(".+ whispers: .*")) || line.contains(QRegExp(".+ kibitzes: .*"))) + { + writeToConsole(line, "K_WSP"); + } + /* Important System Messages: Use Whisper Color */ + else if(line.contains(QRegExp("declines the draw request\\.$" ))) + { + writeToConsole(line, "K_WSP"); + } + /* DRAW OFFER */ + else if(line.right(19) == " offers you a draw.") + { + writeToConsole(line, "K_WSP"); + } + else if( line.contains( QRegExp(".+rating adjustment:.+" ) ) ) + { + writeToConsole(line, "K_WSP"); + } + /* SHOUTS */ + else if( line.contains( QRegExp("^c?t?s?-?shouts: ") ) ) + { + writeToConsole(line, "K_SHT"); + } + /* NOTIFY */ + else if((line.contains(QRegExp("\\s*Notification:"))) || + (line.contains(QRegExp("\\s*Present company includes:"))) || + (line.contains(QRegExp("\\s*Your arrival was noted by:")))) + { + writeToConsole(line, "K_NOT"); + myResource->play( SND_NOTIFICATION ); + } + /* CHANNEL TELLS */ + else if(line.contains(QRegExp( ".\\(\\d+\\):" ))) + { + /* First grab the channel # so we can auto-respond later */ + j = line.find(QString("):")); + i = line.findRev(QString("("), j) + 1; + emit sendCMD( Command( 0, CMD_Set_Src_Channel, line.mid(i, j - i) ) ); + writeToConsole(line, "K_CH"); + } + else if(line.contains(QRegExp("^<12>\\s"))) + { + /* a game move */ + parseStyle12(line, PARSE12_MODE_MOVE); + } + else if(line.contains(QRegExp("^<b1>\\s"))) + { + /* a bughouse piece has been passed or a piece has been captured in crazyhouse */ + writeToConsole(line, "K_CH"); + } + else if(line.contains(QRegExp("^\\\\"))) + { + writeToConsole(line, lastTag); + } + else if(line.contains(QRegExp("^\\{?Game \\d+")) && line.contains("Creating", TRUE)) + { + parseMode = NEW_GAME_MODE; + } + else if(line.contains("You are now observing game")) + { + parseMode = OBSERVE_GAME_MODE; + } + else if(line.startsWith("Movelist for game")) + { + QRegExp gameNumber("\\d+"); + int pos = gameNumber.search(line); + if(pos > -1) + { + ficsMoveListNumber = gameNumber.cap(0).toInt(); + } + parseMode = PARSE_MOVE_LIST_MODE; + } + else if((line.contains(QRegExp("^\\{?Game \\d+")) || line.contains(QRegExp("Game \\d+"))) && + ( + line.contains(" forfeits by disconnection", TRUE) || + line.contains(" forfeits by disconnection}", TRUE) || + line.contains(" forfeits on time} ", TRUE) || + line.contains(" forfeits on time ", TRUE) || + line.contains(" resigns} ", TRUE) || + line.contains(" resigns ", TRUE) || + line.contains(" Game drawn by mutual agreement ", TRUE) || + line.contains(" Game drawn by mutual agreement} ", TRUE) || + line.contains(", has lost contact or quit.", TRUE) || + line.contains(" checkmated ", TRUE) || + line.contains(" checkmated} ", TRUE) || + line.contains("lost connection", TRUE) || + line.contains("has no material to mate", TRUE) + ) + ) + { + sendEndOfGameCommand(line); + } + else + { + /* don't know what to do with it, just send it to the console */ + /* don't write the prompt to the console */ + if( line.contains( QRegExp( "^a?d?f?g?s?z?ics% " ) ) || + line.contains( QRegExp( "^cex% " ) ) || + line.contains( QRegExp( "^chess% " ) ) ) + break; + writeToConsole(line, "K_STD"); + } + break; + case UPDATE_SOUGHT_MODE: + if(line.contains(QRegExp("\\d+\\s+ads? displayed."))) + { + updateSoughtList(line); + parseMode = NORMAL_MODE; + } + else + { + updateSoughtList(line); + } + break; + case NEW_GAME_MODE: + if(line.contains(QRegExp("<12>\\s"))) + { + /* a game move */ + parseStyle12(line, PARSE12_MODE_NEW); + } + else if((line.startsWith("fics%") && line.length() == 6)) + { + parseMode = NORMAL_MODE; + } + break; + case OBSERVE_GAME_MODE: + if(line.contains(QRegExp("<12>\\s"))) + { + /* a game move */ + parseStyle12(line, PARSE12_MODE_NEW); + send("moves"); + parseMode = NORMAL_MODE; + } + break; + case CHALLENGE_MODE: + if(line.startsWith("You can \"accept\" or \"decline\", or propose")) + { + parseMode = NORMAL_MODE; + } + break; + case PARSE_MOVE_LIST_MODE: + if(!line.contains("{Still in progress}")) + { + if(line.contains(QRegExp("\\d\\."))) + { + parseMoveList(line); + } + } + else + { + parseMode = NORMAL_MODE; + } + break; + default: /* do nothing */ + break; + }; +} + +/////////////////////////////////////// +// +// io_internet::ParseStyle12 +// +/////////////////////////////////////// +void io_internet::parseStyle12(QString line, const unsigned int Mode) +{ +// kdWarning() << line << endl; + + struct ChessMove move; + QStringList fields; + QString position_line = ""; + match_param *param = NULL; + Command::clearMove(&move); + switch(Mode) + { + case PARSE12_MODE_NEW: + { + /* a new game that we are playing, or observing */ + param = new match_param(this->myResource); + fields = QStringList::split( QChar(' '), line, FALSE ); + + /* set white time control */ + TCPList tmpListWhite(param->time(WHITE)); + TCP tmpTCPWhite = tmpListWhite[0]; + tmpTCPWhite.Seconds = fields[20].toInt() * 60; + tmpTCPWhite.Increment = fields[21].toInt(); + tmpListWhite[0] = tmpTCPWhite; + param->setTime(WHITE, tmpListWhite); + + /* set black time control */ + TCPList tmpListBlack(param->time(BLACK)); + TCP tmpTCPBlack = tmpListBlack[0]; + tmpTCPBlack.Seconds = fields[20].toInt() * 60; + tmpTCPBlack.Increment = fields[21].toInt(); + tmpListBlack[0] = tmpTCPBlack; + param->setTime(BLACK, tmpListBlack); + + if((userName.upper() == fields[17].upper()) && + ((fields[19].toInt() == -1) || (fields[19].toInt() == 1))) + { + /* I am playing white */ + param->setType(WHITE, PLAYERLOCAL); + } + else if(fields[19].toInt() != 2) + { + /* I am not playing white */ + param->setType(WHITE, PLAYERTCP); + } + + if((userName.upper() == fields[18].upper()) && + ((fields[19].toInt() == -1) || (fields[19].toInt() == 1))) + { + /* I am playing black */ + param->setType(BLACK, PLAYERLOCAL); + } + else if(fields[19].toInt() != 2) + { + /* I am not playing black */ + param->setType(BLACK, PLAYERTCP); + } + + if(fields[19].toInt() == 2) + { + param->setType(WHITE, PLAYEREXAMINE); + param->setType(BLACK, PLAYEREXAMINE); + } + //param->setVariation(something); figure out how to get the variation + param->setName(WHITE, fields[17]); + param->setName(BLACK, fields[18]); + /* tell core to connect us to a new match */ + fics_to_knights[fields[16].toInt()] = ((core*)myParent)->newMatch(param)->getID(); + } + case PARSE12_MODE_MOVE: + { + fields = QStringList::split( QChar(' '), line, FALSE ); + + /* various ICS stuff for ChessMove */ + move.ICS_ClockTicking = fields[31].toInt(); + move.ICS_PawnPushFile = fields[10].toShort(); + move.ICS_MoveCounter = fields[15].toInt(); + if(fields[9] == "W") + { + move.ICS_OnMove = BLACK; + } + else if( fields[9] == "B" ) + { + move.ICS_OnMove = WHITE; + } + + switch( fields[19].toInt() ) + { + /* Examining a game */ + case 2: + move.ICS_Mode = ICS_Examine; + if(fics_to_knights[fields[16].toInt()] == 0) + { + /* no new game started yet, call parsestyle 12 with a different mode */ + parseStyle12(line, PARSE12_MODE_NEW); + return; + } + break; + /* Observing a game */ + case -2: + case 0: + move.ICS_Mode = ICS_Observe; + break; + /* Playing a game */ + default: + move.ICS_Mode = ICS_Normal; + break; + } + + /* Verbose Coordinate Notation of previous move ( USE AS CAN ) */ + strcpy(move.CAN, fields[27].right(fields[27].length() - 2).replace(QRegExp("-"), "")); + /* SAN */ + strcpy(move.SAN, fields[29].replace(QRegExp("\\+"), "").replace(QRegExp("#"), "")); + + /* fill the line for the command */ + position_line += fields[1]; /* Internal Rank #7 */ + position_line += fields[2]; /* Internal Rank #6 */ + position_line += fields[3]; /* Internal Rank #5 */ + position_line += fields[4]; /* Internal Rank #4 */ + position_line += fields[5]; /* Internal Rank #3 */ + position_line += fields[6]; /* Internal Rank #2 */ + position_line += fields[7]; /* Internal Rank #1 */ + position_line += fields[8]; /* Internal Rank #0 */ + /* Can White Castle Short (boolean) */ + position_line += fields[11]; + /* Can White Castle Long (boolean) */ + position_line += fields[12]; + /* Can Black Castle Short (boolean) */ + position_line += fields[13]; + /* Can Black Castle Long (boolean) */ + position_line += fields[14]; + + Command command(fics_to_knights[fields[16].toInt()], CMD_Move, fields[24].toInt() * 100, + fields[25].toInt() * 100, move); + command.setData(position_line); + emit sendCMD(command); + break; + } + default: + break; + } +} + +/////////////////////////////////////// +// +// io_internet::ParsePlayer +// +/////////////////////////////////////// +//void io_internet::ParsePlayer( QString Handle ) +//{ +// player.Raw = Handle; + /* SysAdmin */ +// if( Handle.contains( QRegExp("\\(\\*\\)") ) ) +// { +// player.SysAdmin = TRUE; +// Handle.replace( QRegExp("\\(\\*\\)"), QString("") ); +// } +// else player.SysAdmin = FALSE; + /* ServiceRep */ +// if( Handle.contains( QRegExp("\\(SR\\)") ) ) +// { +// player.ServiceRep = TRUE; +// Handle.replace( QRegExp("\\(SR\\)"), QString("") ); +// } +// else player.ServiceRep = FALSE; + /* Computer */ +// if( Handle.contains( QRegExp("\\(C\\)") ) ) +// { +// player.Computer = TRUE; +// Handle.replace( QRegExp("\\(C\\)"), QString("") ); +// } +// else player.Computer = FALSE; + /* Unregistered */ +// if( Handle.contains( QRegExp("\\(U\\)") ) ) +// { +// player.Unregistered = TRUE; +// Handle.replace( QRegExp("\\(U\\)"), QString("") ); +// } +// else player.Unregistered = FALSE; +// return; +//} +/////////////////////////////////////// +// +// io_internet::nullifyChallenge +// +/////////////////////////////////////// +void io_internet::nullifyChallenge( void ) +{ + challenge = NULL; +} + +/////////////////////////////////////// +// +// io_internet::declineChallenge +// +/////////////////////////////////////// +void io_internet::declineChallenge( void ) +{ + send( "decline" ); + delete challenge; + challenge = NULL; +} +/////////////////////////////////////// +// +// io_internet::acceptChallenge +// +/////////////////////////////////////// +void io_internet::acceptChallenge( void ) +{ + send( challenge->values() ); + delete challenge; + challenge = NULL; +} + +/////////////////////////////////////// +// +// io_internet::writeToConsole +// +/////////////////////////////////////// +void io_internet::writeToConsole(QString text, QString tag) +{ + lastTag = tag; + /* Remove Bells */ + text.replace( QRegExp("\\x0007") , "" ); + /* Replace misc characters with rich-text friendly counterparts */ + text.replace( QRegExp("\\x003c"), "<" ); + text.replace( QRegExp("\\x007c"), "|" ); + text.replace( QRegExp( "\\f"), ""); + text.replace( QRegExp( "\\n"), ""); + text.replace( QRegExp( "\\r*" ), "" ); + emit sendCMD( Command( 0, CMD_Append_To_Console, "<" + tag + ">" + text + "</" + tag + ">" ) ); +} + +/////////////////////////////////////// +// +// io_internet::updateSoughtList +// +/////////////////////////////////////// +void io_internet::updateSoughtList(QString soughtLine) +{ + /* "ADS DISPLAYED" MESSAGE */ + if(soughtLine.contains(QRegExp("\\d+\\s+ads? displayed."))) + { + emit sendCMD( Command( 0, CMD_Show_Sought_List ) ); + } + else + { + emit sendCMD( Command( 0, CMD_Add_Sought_Match, soughtLine ) ); + } +} + +/////////////////////////////////////// +// +// io_internet::sendUserSettings() +// +/////////////////////////////////////// +void io_internet::sendUserSettings() +{ + send("set style 12"); + send(QString("set interface Knights %1").arg(_VERSION_)); + send(QString("set private %1").arg(myResource->OPTION_Private)); + send(QString("set kibitz %1").arg(myResource->OPTION_Kibitz)); + send(QString("set tell %1").arg(myResource->OPTION_Tell)); + send(QString("set shout %1").arg(myResource->OPTION_Shout)); + send(QString("set seek %1").arg(myResource->OPTION_Seek)); + send(QString("set tolerance %1").arg(myResource->OPTION_Profanity)); +} + +/////////////////////////////////////// +// +// io_internet::parseMoveList(QString data) +// +/////////////////////////////////////// +void io_internet::parseMoveList(QString line) +{ + QStringList two_plys; + struct ChessMove move; + Command command; + int move_counter = 0; + + /* white */ + two_plys = QStringList::split(QRegExp("\\s+"), line, FALSE); + Command::clearMove(&move); + move_counter = two_plys[0].left(two_plys[0].length() - 1).length(); /* remove the . */ + move.ICS_MoveCounter = move_counter; + move.ICS_Mode = ICS_Movelist; + move.ICS_OnMove = WHITE; + strcpy(move.SAN, two_plys[1]); + command.setCommand((int&)CMD_Move); + command.setID(fics_to_knights[ficsMoveListNumber]); + command.setMove(move); + emit sendCMD(command); + + /* black */ + if(two_plys.size() > 3) + { + Command::clearMove(&move); + move.ICS_MoveCounter = move_counter; + move.ICS_Mode = ICS_Movelist; + move.ICS_OnMove = BLACK; + strcpy(move.SAN, two_plys[3]); + command.setCommand((int&)CMD_Move); + command.setID(fics_to_knights[ficsMoveListNumber]); + command.setMove(move); + emit sendCMD(command); + } +} + +/////////////////////////////////////// +// +// io_internet::sendEndOfGameCommand(QString line) +// +/////////////////////////////////////// +void io_internet::sendEndOfGameCommand(QString line) +{ + QStringList fields; + Command command; + + fields = QStringList::split( QChar(' '), line, FALSE ); + if(fields[1].endsWith(":")) + { + fields[1] = fields[1].left(fields[1].length() - 1); + } + command.setID(fics_to_knights[fields[1].toInt()]); + fields[fields.count() - 1] = fields[fields.count() - 1].stripWhiteSpace(); + if(fields[fields.count() - 1] == "1-0" ) + { + if(fields[fields.count() - 2].contains("resigns")) + { + command.setCommand((int&)CMD_Black_Resign); + } + else if(fields[fields.count() - 2].contains("time")) + { + command.setCommand((int&)CMD_White_Called_Flag); + } + else + { + command.setCommand((int&)CMD_Result_White); + } + } + else if(fields[fields.count() - 1] == "0-1") + { + if(fields[fields.count() - 2].contains("resigns")) + { + command.setCommand((int&)CMD_White_Resign); + } + else if(fields[fields.count() - 2].contains("time")) + { + command.setCommand((int&)CMD_Black_Called_Flag); + } + else + { + command.setCommand((int&)CMD_Result_Black); + } + } + else if(fields[fields.count() - 1] == "1/2-1/2") + { + command.setCommand((int&)CMD_Result_Draw); + } + else + { + command.setCommand((int&)CMD_Lost_Contact); + } + emit sendCMD(command); +} + +/////////////////////////////////////// +// +// io_internet::processSeekTimer() +// +/////////////////////////////////////// +void io_internet::processSeekTimer() +{ + /* timer timed out, send out a sought */ + send("sought"); +} + +/////////////////////////////////////// +// +// io_internet::selfDestruct() +// +/////////////////////////////////////// +void io_internet::selfDestruct() +{ + /* cause the io_internet to delete itself */ + QApplication::postEvent( qApp->mainWidget(), new QCustomEvent( EVENT_Del_IO_Net ) ); +} + +/////////////////////////////////////// +// +// io_internet::setUserInfo() +// +/////////////////////////////////////// +void io_internet::setUserInfo(QString userName, QString passWord) +{ + this->userName = userName; + this->passWord = passWord; +} + |