You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
688 lines
15 KiB
688 lines
15 KiB
/***************************************************************************
|
|
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 <klocale.h>
|
|
#include <qtimer.h>
|
|
#include <qstringlist.h>
|
|
#include <qregexp.h>
|
|
|
|
#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 QTimer( this );
|
|
connect( InitTimer, SIGNAL( timeout() ), this, 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 )
|
|
{
|
|
QString 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( QString( "time %1" ).arg( cmd.getWhiteTime() ) );
|
|
emit output( QString( "otim %1" ).arg( cmd.getBlackTime() ) );
|
|
}
|
|
else
|
|
{
|
|
emit output( QString( "time %1" ).arg( cmd.getBlackTime() ) );
|
|
emit output( QString( "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( QString( "time %1" ).arg( cmd.getWhiteTime() ) );
|
|
else
|
|
emit output( QString( "time %1" ).arg( cmd.getBlackTime() ) );
|
|
}
|
|
break;
|
|
|
|
/* Command: Enemy Time */
|
|
case CMD_Enemy_Time:
|
|
if( FEATURE_Time )
|
|
{
|
|
if( Army == WHITE )
|
|
emit output( QString( "otim %1" ).arg( cmd.getBlackTime() ) );
|
|
else
|
|
emit output( QString( "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( QString( "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 " + QString::number( cmd.getData().toInt() >> 1 ) );
|
|
break;
|
|
|
|
/* Command: Set Name */
|
|
case CMD_Set_Name:
|
|
FEATURE_MyName = cmd.getData();
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
///////////////////////////////////////
|
|
//
|
|
// proto_xboard::parse( const QString &string )
|
|
//
|
|
///////////////////////////////////////
|
|
void proto_xboard::parse( const QString &string )
|
|
{
|
|
QString strIn = string;
|
|
QStringList strList( QStringList::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( QRegExp("\\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, QString( "%1" ).arg( strIn.right( strIn.length() - 13 ) ) ) );
|
|
return;
|
|
}
|
|
|
|
/* Tell Others */
|
|
if( strList[0] == "tellothers" )
|
|
{
|
|
emit output( Command( myID, CMD_Tell_Others, QString( "%1" ).arg( strIn.right( strIn.length() - 11 ) ) ) );
|
|
return;
|
|
}
|
|
|
|
/* Tell All */
|
|
if( strList[0] == "tellall" )
|
|
{
|
|
emit output( Command( myID, CMD_Tell_All, QString( "%1" ).arg( strIn.right( strIn.length() - 8 ) ) ) );
|
|
return;
|
|
}
|
|
|
|
/* Tell ICS */
|
|
if( strList[0] == "tellics" )
|
|
{
|
|
emit output( Command( myID, CMD_Tell_ICS, QString( "%1" ).arg( strIn.right( strIn.length() - 8 ) ) ) );
|
|
return;
|
|
}
|
|
|
|
/* Tell ICS No Alias */
|
|
if( strList[0] == "tellicsnoalias" )
|
|
{
|
|
emit output( Command( myID, CMD_Tell_ICS, QString( "%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 = QString( strList[loop].right(1) ).toInt();
|
|
emit output( "accepted ics" );
|
|
continue;
|
|
}
|
|
if( strList[loop].left(3) == "san" )
|
|
{
|
|
FEATURE_SAN = QString( strList[loop].right(1) ).toInt();
|
|
emit output( "accepted san" );
|
|
continue;
|
|
}
|
|
if( strList[loop].left(4) == "draw" )
|
|
{
|
|
FEATURE_Draw = QString( strList[loop].right(1) ).toInt();
|
|
emit output( "accepted draw" );
|
|
continue;
|
|
}
|
|
if( strList[loop].left(4) == "name" )
|
|
{
|
|
FEATURE_Name = QString( strList[loop].right(1) ).toInt();
|
|
emit output( "accepted name" );
|
|
continue;
|
|
}
|
|
if( strList[loop].left(4) == "ping" )
|
|
{
|
|
FEATURE_Ping = QString( strList[loop].right(1) ).toInt();
|
|
emit output( "accepted ping" );
|
|
continue;
|
|
}
|
|
if( strList[loop].left(4) == "time" )
|
|
{
|
|
FEATURE_Time = QString( strList[loop].right(1) ).toInt();
|
|
emit output( "accepted time" );
|
|
continue;
|
|
}
|
|
if( strList[loop].left(5) == "level" )
|
|
{
|
|
FEATURE_Level = QString( strList[loop].right( strList[loop].length() - 6 ) ).toInt();
|
|
emit output( "accepted level" );
|
|
continue;
|
|
}
|
|
if( strList[loop].left(5) == "pause" )
|
|
{
|
|
FEATURE_Pause = QString( strList[loop].right(1) ).toInt();
|
|
emit output( "accepted pause" );
|
|
continue;
|
|
}
|
|
if( strList[loop].left(5) == "reuse" )
|
|
{
|
|
FEATURE_Reuse = QString( strList[loop].right(1) ).toInt();
|
|
emit output( "accepted reuse" );
|
|
continue;
|
|
}
|
|
if( strList[loop].left(6) == "colors" )
|
|
{
|
|
FEATURE_Colors = QString( strList[loop].right(1) ).toInt();
|
|
emit output( "accepted colors" );
|
|
continue;
|
|
}
|
|
if( strList[loop].left(6) == "myname" )
|
|
{
|
|
FEATURE_MyName = QString( strList[loop].right( strList[loop].length() - 8 ) );
|
|
emit output( "accepted myname" );
|
|
continue;
|
|
}
|
|
if( strList[loop].left(6) == "sigint" )
|
|
{
|
|
FEATURE_SIGINT = QString( strList[loop].right(1) ).toInt();
|
|
emit output( "accepted sigint" );
|
|
continue;
|
|
}
|
|
if( strList[loop].left(7) == "analyze" )
|
|
{
|
|
FEATURE_Analyze = QString( strList[loop].right(1) ).toInt();
|
|
emit output( "accepted analyze" );
|
|
continue;
|
|
}
|
|
if( strList[loop].left(7) == "sigterm" )
|
|
{
|
|
FEATURE_SIGTERM = QString( strList[loop].right(1) ).toInt();
|
|
emit output( "accepted sigterm" );
|
|
continue;
|
|
}
|
|
if( strList[loop].left(8) == "setboard" )
|
|
{
|
|
FEATURE_SetBoard = QString( strList[loop].right(1) ).toInt();
|
|
emit output( "accepted setboard" );
|
|
continue;
|
|
}
|
|
if( strList[loop].left(8) == "usermove" )
|
|
{
|
|
FEATURE_UserMove = QString( 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 = QString( strList[loop].right(1) ).toInt();
|
|
emit output( "accepted playother" );
|
|
continue;
|
|
}
|
|
if( strList[loop].left(10) == "bookengine" )
|
|
{
|
|
FEATURE_BookEngine = QString( 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();
|
|
}
|