/*************************************************************************** proto_xboard.cpp - description ------------------- begin : Sat Oct 26 2002 copyright : (C) 2003 by Troy Corbin Jr. email : tcorbin@users.sf.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. * * * ***************************************************************************/ #include #include #include #include #include "proto_xboard.moc" #include "definitions.h" proto_xboard::proto_xboard( const int ID ) : proto_base( ID ) { FEATURE_Analyze = TRUE; FEATURE_Colors = TRUE; FEATURE_Draw = TRUE; FEATURE_ICS = FALSE; FEATURE_Name = TRUE; FEATURE_Pause = FALSE; FEATURE_Ping = FALSE; FEATURE_PlayOther = FALSE; FEATURE_Reuse = TRUE; FEATURE_SetBoard = FALSE; FEATURE_SAN = FALSE; FEATURE_SIGINT = TRUE; FEATURE_SIGTERM = TRUE; FEATURE_Time = TRUE; FEATURE_UserMove = FALSE; FEATURE_Variants = 0; FEATURE_Level = 1; FEATURE_BookEngine = 0; CMDList = new CommandList; InitTimer = new TQTimer( this ); connect( InitTimer, TQ_SIGNAL( timeout() ), this, TQ_SLOT( releaseBuffer() ) ); Check = TRUE; Team = FALSE; JustMoved = FALSE; AcceptIllegal = FALSE; DelayedGo = FALSE; Forced = TRUE; Turn = WHITE; } proto_xboard::~proto_xboard() { delete InitTimer; delete CMDList; } /////////////////////////////////////// // // proto_xboard::parse( const Command &command ) // /////////////////////////////////////// void proto_xboard::parse( const Command &command ) { TQString temp; Command cmd = command; if( InitTimer->isActive() ) { /* Store Command for later use.. we're still waiting for the engine to finish */ CMDList->append( command ); return; } switch( cmd.getCommand() ) { /* Command: Init */ case CMD_Init: emit output( "xboard\nprotover 3" ); InitTimer->start( 2000, TRUE ); break; /* Command: New Game */ case CMD_NewGame: emit output( "new\nrandom" ); break; /* Command: Exit */ case CMD_Exit: emit output( "quit" ); if( FEATURE_SIGTERM ) emit output( Command( myID, CMD_Send_SIGTERM ) ); break; /* Command: Move Now */ case CMD_MoveNow: emit output( "?" ); break; /* Command: Move */ case CMD_Move: if( JustMoved ) { JustMoved = FALSE; break; } AcceptIllegal = TRUE; myMove = cmd.getMove(); /* Send Time */ if( FEATURE_Time ) { if( Army == WHITE ) { emit output( TQString( "time %1" ).arg( cmd.getWhiteTime() ) ); emit output( TQString( "otim %1" ).arg( cmd.getBlackTime() ) ); } else { emit output( TQString( "time %1" ).arg( cmd.getBlackTime() ) ); emit output( TQString( "otim %1" ).arg( cmd.getWhiteTime() ) ); } } if( FEATURE_UserMove ) temp = "usermove "; if( FEATURE_SAN ) temp += myMove.SAN; else temp += myMove.CAN; if( DelayedGo ) { DelayedGo = FALSE; temp += "\ngo"; Forced = FALSE; } emit output( temp ); break; /* Command: Pause */ case CMD_Pause: if( FEATURE_Pause ) emit output( "pause" ); else { emit output( "force" ); Forced = TRUE; } break; /* Command: Resume */ case CMD_Resume: if( FEATURE_Pause ) emit output( "resume" ); else { if( Turn == Army ) { emit output( "go" ); Forced = FALSE; } else DelayedGo = TRUE; } break; /* Command: Play White */ case CMD_Play_White: Army = WHITE; if( Turn == BLACK ) { if( FEATURE_PlayOther ) { emit output( "playother" ); } else if( FEATURE_Colors ) { emit output( "black" ); } else { emit output( "force" ); Forced = TRUE; DelayedGo = TRUE; } break; } else { temp = "force"; if( FEATURE_Colors ) temp += "\nwhite"; temp += "\ngo"; emit output( temp ); break; } break; /* Command: Play Black */ case CMD_Play_Black: Army = BLACK; if( Turn == WHITE ) { if( FEATURE_PlayOther ) { emit output( "playother" ); } else if( FEATURE_Colors ) { emit output( "white" ); } else { emit output( "force" ); Forced = TRUE; DelayedGo = TRUE; } break; } else { temp = "force"; if( FEATURE_Colors ) temp += "\nblack"; temp += "\ngo"; emit output( temp ); break; } break; /* Command: Result White */ case CMD_Result_White: emit output( "result 1-0 {White Mates}" ); AcceptIllegal = FALSE; // if( Army == WHITE ) // (*IT).Wins++; // else // (*IT).Losses++; break; /* Command: Result Black */ case CMD_Result_Black: emit output( "result 0-1 {Black Mates}" ); AcceptIllegal = FALSE; // if( Army == BLACK ) // (*IT).Wins++; // else // (*IT).Losses++; break; /* Command: Result Draw */ case CMD_Result_Draw: emit output( "result 1/2-1/2 {Draw Game}" ); AcceptIllegal = FALSE; // (*IT).Draws++; break; /* Command: Your Time */ case CMD_Your_Time: if( FEATURE_Time ) { if( Army == WHITE ) emit output( TQString( "time %1" ).arg( cmd.getWhiteTime() ) ); else emit output( TQString( "time %1" ).arg( cmd.getBlackTime() ) ); } break; /* Command: Enemy Time */ case CMD_Enemy_Time: if( FEATURE_Time ) { if( Army == WHITE ) emit output( TQString( "otim %1" ).arg( cmd.getBlackTime() ) ); else emit output( TQString( "otim %1" ).arg( cmd.getWhiteTime() ) ); } break; /* Command: Offer Draw */ case CMD_Offer_Draw: if( FEATURE_Draw ) emit output( "draw" ); break; /* Command: Book Mode */ case CMD_Book_Mode: if( FEATURE_BookEngine != 0 ) emit output( "bookengine" ); break; /* Command: Check Book */ case CMD_Check_Book: emit output( "go" ); Forced = FALSE; break; /* Command: Ponder */ case CMD_Ponder: emit output( "hard" ); break; /* Command: No Pondering */ case CMD_No_Pondering: emit output( "hard\neasy" ); break; /* Command: Retract Move */ case CMD_Retract_Move: emit output( "remove" ); break; /* Command: Hint */ case CMD_Hint: emit output( "hint" ); break; /* Command: Listen */ case CMD_Listen: emit output( "force" ); Forced = TRUE; DelayedGo = FALSE; break; /* Command: Play */ case CMD_Play: if( Army == Turn ) { emit output( "go" ); Forced = FALSE; } else DelayedGo = TRUE; break; /* Command: White Resign */ case CMD_White_Resign: parse( Command( 0, CMD_Result_White ) ); break; /* Command: Black Resign */ case CMD_Black_Resign: parse( Command( 0, CMD_Result_Black ) ); break; /* Command: Set Board */ case CMD_Set_Board: if( FEATURE_SetBoard == TRUE ) { emit output( TQString( "setboard %1" ).arg( cmd.getData() ) ); } else { // Convert FEN to edit commands here and feed them to engine } break; /* Command: Set Difficulty */ case CMD_Set_Difficulty: emit output( "sd " + cmd.getData() ); // emit output( "st " + TQString::number( cmd.getData().toInt() >> 1 ) ); break; /* Command: Set Name */ case CMD_Set_Name: FEATURE_MyName = cmd.getData(); break; default: break; } } /////////////////////////////////////// // // proto_xboard::parse( const TQString &string ) // /////////////////////////////////////// void proto_xboard::parse( const TQString &string ) { TQString strIn = string; TQStringList strList( TQStringList::split( ' ', strIn ) ); if( ( FEATURE_SIGINT ) && ( !Forced ) ) emit output( Command( myID, CMD_Send_SIGINT ) ); /* Illegal */ if( strList[0].contains( "illegal", FALSE ) ) { if( AcceptIllegal ) { if( strIn.contains("(no matching move)board") ) return; if( strIn.contains("(no matching move)protover") ) return; if( strIn.contains("(no matching move)sd") ) return; AcceptIllegal = FALSE; emit output( Command( myID, CMD_Illegal ) ); } return; } /* A Move */ if( strList[0] == "move" ) { if( strList.count() < 2 ) { kdWarning() << "proto_xboard::parse: Incomplete Move command" << endl; return; } Command::clearMove( &myMove ); strcpy( myMove.SAN, strList[1].latin1() ); strcpy( myMove.CAN, strList[1].latin1() ); if( Team ) { emit output( "force" ); Forced = TRUE; } JustMoved = TRUE; emit output( Command( myID, CMD_Move, 0, 0, myMove ) ); return; } /* A Move ( Old Variation ) */ if( ( strList[0].contains( TQRegExp("\\d+\\.") ) ) && ( strList[1] == "..." ) ) { Command::clearMove( &myMove ); strcpy( myMove.SAN, strList[2].latin1() ); strcpy( myMove.CAN, strList[2].latin1() ); if( Team ) { emit output( "force" ); Forced = TRUE; } JustMoved = TRUE; emit output( Command( myID, CMD_Move, 0, 0, myMove ) ); return; } /* Hint */ if( strList[0] == "Hint:" ) { emit output( Command( myID, CMD_Hint, i18n( "%1 suggests this move:\n%2" ).arg( FEATURE_MyName ).arg( strList[1] ) ) ); return; } /* Offer Draw */ if( ( strList[0] == "offer" ) && ( strList[1] == "draw" ) ) { emit output( Command( myID, CMD_Offer_Draw ) ); } /* Out of Book */ if( strList[0] == "outofbook" ) { emit output( "force" ); Forced = TRUE; emit output( Command( myID, CMD_Out_Of_Book ) ); return; } /* Tell User */ if( strList[0] == "telluser" ) { emit output( Command( myID, CMD_Tell_User, i18n( "%1 tells you:\n%2" ).arg( FEATURE_MyName ).arg( strIn.right( strIn.length() - 9 ) ) ) ); return; } /* Tell User Error */ if( strList[0] == "tellusererror" ) { emit output( Command( myID, CMD_Tell_User_Error, i18n( "%1 tells you:\n%2" ).arg( FEATURE_MyName ).arg( strIn.right( strIn.length() - 14 ) ) ) ); return; } /* Error */ if( strList[0] == "Error" ) { emit output( Command( myID, CMD_Tell_User_Error, i18n( "%1 tells you:\n%2" ).arg( FEATURE_MyName ).arg( strIn.right( strIn.length() ) ) ) ); return; } /* Tell Opponent */ if( strList[0] == "tellopponent" ) { emit output( Command( myID, CMD_Tell_Opponent, TQString( "%1" ).arg( strIn.right( strIn.length() - 13 ) ) ) ); return; } /* Tell Others */ if( strList[0] == "tellothers" ) { emit output( Command( myID, CMD_Tell_Others, TQString( "%1" ).arg( strIn.right( strIn.length() - 11 ) ) ) ); return; } /* Tell All */ if( strList[0] == "tellall" ) { emit output( Command( myID, CMD_Tell_All, TQString( "%1" ).arg( strIn.right( strIn.length() - 8 ) ) ) ); return; } /* Tell ICS */ if( strList[0] == "tellics" ) { emit output( Command( myID, CMD_Tell_ICS, TQString( "%1" ).arg( strIn.right( strIn.length() - 8 ) ) ) ); return; } /* Tell ICS No Alias */ if( strList[0] == "tellicsnoalias" ) { emit output( Command( myID, CMD_Tell_ICS, TQString( "%1" ).arg( strIn.right( strIn.length() - 15 ) ) ) ); return; } /* Resign */ if( strIn.contains( "resign", FALSE ) ) { if( Army == WHITE ) emit output( Command( myID, CMD_White_Resign ) ); else emit output( Command( myID, CMD_Black_Resign ) ); return; } /* Parse Features */ if( !InitTimer->isActive() ) return; for( unsigned int loop = 0; loop < strList.count(); loop++ ) { if( strList[loop] == "done=1" ) { InitTimer->stop(); releaseBuffer(); continue; } /* This buys you 10 minutes */ if( strList[loop] == "done=0" ) { InitTimer->changeInterval( 600000 ); continue; } if( strList[loop] == "feature" ) { continue; } if( strList[loop].left(3) == "ics" ) { FEATURE_ICS = TQString( strList[loop].right(1) ).toInt(); emit output( "accepted ics" ); continue; } if( strList[loop].left(3) == "san" ) { FEATURE_SAN = TQString( strList[loop].right(1) ).toInt(); emit output( "accepted san" ); continue; } if( strList[loop].left(4) == "draw" ) { FEATURE_Draw = TQString( strList[loop].right(1) ).toInt(); emit output( "accepted draw" ); continue; } if( strList[loop].left(4) == "name" ) { FEATURE_Name = TQString( strList[loop].right(1) ).toInt(); emit output( "accepted name" ); continue; } if( strList[loop].left(4) == "ping" ) { FEATURE_Ping = TQString( strList[loop].right(1) ).toInt(); emit output( "accepted ping" ); continue; } if( strList[loop].left(4) == "time" ) { FEATURE_Time = TQString( strList[loop].right(1) ).toInt(); emit output( "accepted time" ); continue; } if( strList[loop].left(5) == "level" ) { FEATURE_Level = TQString( strList[loop].right( strList[loop].length() - 6 ) ).toInt(); emit output( "accepted level" ); continue; } if( strList[loop].left(5) == "pause" ) { FEATURE_Pause = TQString( strList[loop].right(1) ).toInt(); emit output( "accepted pause" ); continue; } if( strList[loop].left(5) == "reuse" ) { FEATURE_Reuse = TQString( strList[loop].right(1) ).toInt(); emit output( "accepted reuse" ); continue; } if( strList[loop].left(6) == "colors" ) { FEATURE_Colors = TQString( strList[loop].right(1) ).toInt(); emit output( "accepted colors" ); continue; } if( strList[loop].left(6) == "myname" ) { FEATURE_MyName = TQString( strList[loop].right( strList[loop].length() - 8 ) ); emit output( "accepted myname" ); continue; } if( strList[loop].left(6) == "sigint" ) { FEATURE_SIGINT = TQString( strList[loop].right(1) ).toInt(); emit output( "accepted sigint" ); continue; } if( strList[loop].left(7) == "analyze" ) { FEATURE_Analyze = TQString( strList[loop].right(1) ).toInt(); emit output( "accepted analyze" ); continue; } if( strList[loop].left(7) == "sigterm" ) { FEATURE_SIGTERM = TQString( strList[loop].right(1) ).toInt(); emit output( "accepted sigterm" ); continue; } if( strList[loop].left(8) == "setboard" ) { FEATURE_SetBoard = TQString( strList[loop].right(1) ).toInt(); emit output( "accepted setboard" ); continue; } if( strList[loop].left(8) == "usermove" ) { FEATURE_UserMove = TQString( strList[loop].right(1) ).toInt(); emit output( "accepted usermove" ); continue; } if( strList[loop].left(8) == "variants" ) { // FIFO_Tmp = strList[loop].right( strList[loop].length() - 10 ); // This must be finished emit output( "accepted variants" ); continue; } if( strList[loop].left(9) == "playother" ) { FEATURE_PlayOther = TQString( strList[loop].right(1) ).toInt(); emit output( "accepted playother" ); continue; } if( strList[loop].left(10) == "bookengine" ) { FEATURE_BookEngine = TQString( strList[loop].right( strList[loop].length() - 11 ) ).toInt(); emit output( "accepted bookengine" ); continue; } } } /////////////////////////////////////// // // proto_xboard::releaseBuffer // /////////////////////////////////////// void proto_xboard::releaseBuffer( void ) { CommandList::Iterator it; for( it = CMDList->begin(); it != CMDList->end(); it++ ) { parse( *it ); } CMDList->clear(); }