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.
knights/knights/core.cpp

893 lines
22 KiB

/***************************************************************************
core.cpp - description
-------------------
begin : Tue Oct 2 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 <tdefiledialog.h>
#include <tdemessagebox.h>
/* TQt */
#include <tqpushbutton.h>
/* Local */
#include "core.moc"
#include "match.h"
#include "list_pgn.h"
#include "thinbuttons.h"
#include "io_engine.h"
#include "io_internet.h"
#include "match_param.h"
/* Tabs */
#include "tabmanager.h"
///////////////////////////////////////
//
// core::core
//
///////////////////////////////////////
core::core(TQWidget *parent, const char *name, resource *Rsrc ) : TQWidget(parent,name)
{
myResource = Rsrc;
listPGN = NULL;
currentMatch = NULL;
myButtonGroup = new thinbuttons( this, "ButtonGroup", myResource );
myButtonGroup->show();
connect( myButtonGroup, TQT_SIGNAL( leftClick(int) ), this, TQT_SLOT( setMatch(int) ) );
connect( myButtonGroup, TQT_SIGNAL( menuItemSelected(int,int) ), this, TQT_SLOT( thinButtonMenu(int,int) ) );
myCoreClock.start( 100, FALSE );
resize();
}
///////////////////////////////////////
//
// core::~core
//
///////////////////////////////////////
core::~core()
{
myCoreClock.stop();
delete myButtonGroup;
}
///////////////////////////////////////
//
// core::createNewIO
//
///////////////////////////////////////
void core::createNewIO( int type, int ID, int side, int str )
{
io_internet *internetioPtr = NULL;
io_engine *engineioPtr = NULL;
// io_email *ioEmailPtr = NULL;
switch( type )
{
/* PLAYERTCP */
case PLAYERTCP:
if( ID == Null )
{
/* Create a NEW internetIO */
internetioPtr = new io_internet( this, myResource );
myIOMap.add( ID, internetioPtr );
internetioPtr->setID( ID );
connect( internetioPtr, TQT_SIGNAL( sendCMD( const Command& ) ), this, TQT_SLOT( command2Match( const Command& ) ) );
}
else
{
/* Use an existing internetIO */
internetioPtr = (io_internet*) myIOMap.find(Null);
if( internetioPtr == NULL )
{
kdWarning() << "core::createNewIO: Trying to connect a match to an internetIO that doesn't exsist." << endl;
}
else
{
myIOMap.add( ID, internetioPtr );
}
}
break;
/* PLAYEREXAMINE */
case PLAYEREXAMINE:
/* examine mode needs only 1 io mapped to it */
if( ID == Null )
{
/* Create a NEW internetIO */
internetioPtr = new io_internet( this, myResource );
myIOMap.add( ID, internetioPtr );
internetioPtr->setID( ID );
connect( internetioPtr, TQT_SIGNAL( sendCMD( const Command& ) ), this, TQT_SLOT( command2Match( const Command& ) ) );
}
else
{
internetioPtr = (io_internet*) myIOMap.find(ID);
if( internetioPtr == NULL )
{
/* no io mapped to the ID yet, use the internetio */
/* Use an existing internetIO */
internetioPtr = (io_internet*) myIOMap.find(Null);
if( internetioPtr == NULL )
{
kdWarning() << "core::createNewIO: Trying to connect a match to an internetIO that doesn't exsist." << endl;
}
else
{
myIOMap.add( ID, internetioPtr );
}
}
/* this ID is already mapped we don't need another one */
}
break;
/* PLAYERPC */
case PLAYERPC:
engineioPtr = new io_engine( this, myResource );
myIOMap.add( ID, engineioPtr );
engineioPtr->setID( ID );
connect( engineioPtr, TQT_SIGNAL( sendCMD( const Command& ) ), this, TQT_SLOT( command2Match( const Command& ) ) );
engineioPtr->Start( side );
engineioPtr->recvCMD( Command( ID, CMD_Set_Difficulty, TQString().setNum( 1 << str ) ) );
break;
/* PLAYEREMAIL */
case PLAYEREMAIL:
// ioEmailPtr = new io_email( this, myResource );
// myIOMap.add( ID, ioEmailPtr );
// ioEmailPtr->setID( ID );
// connect( ioEmailPtr, TQT_SIGNAL( sendCMD( const Command& ) ), this, TQT_SLOT( command2Match( const Command& ) ) );
break;
default:
/* No IO needed */
break;
}
}
///////////////////////////////////////
//
// core::newMatch(match_params* param);
//
///////////////////////////////////////
match* core::newMatch( match_param* param )
{
match *match_ptr = NULL;
int newID;
/* create a new ID for the match */
newID = myIDManager.getNewID();
/* Create the match navigation button */
myButtonGroup->create( newID );
/* Create the match */
match_ptr = new match(this, param, myResource);
match_ptr->setID( newID );
myMatchMap.add( newID, match_ptr );
/* Create IOs */
createNewIO( param->type(WHITE), newID, WHITE, param->strength(WHITE) );
createNewIO( param->type(BLACK), newID, BLACK, param->strength(BLACK) );
/* Connect Signals */
connect( match_ptr, TQT_SIGNAL( sendCMD( const Command& ) ), this, TQT_SLOT( command2IO( const Command& ) ) );
connect( &myCoreClock, TQT_SIGNAL( timeout() ), match_ptr, TQT_SLOT( tick() ) );
/* Set this new match as the current match */
setMatch( newID );
setActiveWindow();
/* Save our configuration settings */
myResource->ConfigWrite();
return match_ptr;
}
///////////////////////////////////////
//
// core::setMatch
//
///////////////////////////////////////
void core::setMatch( int ID )
{
/*
Disconnect the current match from the display
*/
if( currentMatch != NULL )
{
currentMatch->setCurrent( FALSE );
disconnect( currentMatch, TQT_SIGNAL( setClocks() ), this, TQT_SLOT( slot_setClocks() ) );
disconnect( currentMatch, TQT_SIGNAL( setStatusBar( const int&, const TQString& ) ), this, TQT_SLOT( slot_setStatusBar( const int&, const TQString& ) ) );
disconnect( currentMatch, TQT_SIGNAL( setNotation() ), this, TQT_SLOT( slot_setNotation() ) );
currentMatch->setVisibility( FALSE );
}
/*
Now display the new match, and connect it's signals to the GUI
*/
currentMatch = myMatchMap.find( ID );
currentMatch->setVisibility( TRUE );
myButtonGroup->setButton( ID );
connect( currentMatch, TQT_SIGNAL( setClocks() ), this, TQT_SLOT( slot_setClocks() ) );
connect( currentMatch, TQT_SIGNAL( setStatusBar( const int&, const TQString& ) ), this, TQT_SLOT( slot_setStatusBar( const int&, const TQString& ) ) );
connect( currentMatch, TQT_SIGNAL( setNotation() ), this, TQT_SLOT( slot_setNotation() ) );
currentMatch->setCurrent( TRUE );
emit requestResize();
emit initMatch();
currentMatch->resendStatusBar();
/* Give Ourselves Focus */
setActiveWindow();
topLevelWidget()->raise();
}
///////////////////////////////////////
//
// core::clearAll
//
///////////////////////////////////////
bool core::clearAll( void )
{
while( myMatchMap.count() )
{
if( clearMatch() != TRUE ) return FALSE;
}
return TRUE;
}
///////////////////////////////////////
//
// core::clearMatch
//
///////////////////////////////////////
bool core::clearMatch( int id )
{
match *departingMatch, *nextMatch;
io_base *ioPtr;
if( id == Null )
{
if( currentMatch != NULL )
{
id = currentMatch->getID();
}
else
{
return FALSE;
}
}
departingMatch = myMatchMap.find(id);
/* A bad ID was passed */
if( departingMatch == NULL )
{
kdError() << "core::clearMatch: Bad matchID " << id << " could not be cleared." << endl;
return FALSE;
}
/* Save if needed */
if( departingMatch->modified() )
{
if( save( id, TRUE, FALSE ) == FALSE )
{
return FALSE;
}
}
/* Get ID of another match so it can become the current match */
if( departingMatch == currentMatch )
{
/* Find another match in the map */
nextMatch = --myMatchMap;
if( nextMatch == NULL )
{
++myMatchMap;
nextMatch = ++myMatchMap;
}
/* Set the new current match */
if( nextMatch != NULL )
{
setMatch( nextMatch->getID() );
}
else
{
currentMatch = NULL;
emit initMatch();
}
}
/* Remove IOs in this match... */
ioPtr = myIOMap.find(id);
while( ioPtr != NULL )
{
myIOMap.remove( id );
if( ioPtr->getType() != io_base::INTERNET )
{
delete ioPtr;
}
ioPtr = myIOMap.find(id);
}
/* ...and remove the match */
myMatchMap.remove( id );
myButtonGroup->remove( id );
delete departingMatch;
resize();
return TRUE;
}
///////////////////////////////////////
//
// core::resize
//
///////////////////////////////////////
void core::resize( void )
{
int size = 8 + ( 1 * ( myResource->ThemeBorder == TRUE ) );
if( currentMatch != NULL )
{
currentMatch->resize();
myButtonGroup->resize( currentMatch->width() );
myButtonGroup->move( 0, currentMatch->height() );
setFixedSize( currentMatch->width(), currentMatch->height() + myButtonGroup->height() );
}
else
{
myButtonGroup->resize( myResource->ThemeSize * size );
myButtonGroup->move( 0, myResource->ThemeSize * size );
setFixedSize( myResource->ThemeSize * size, ( myResource->ThemeSize * size ) + myButtonGroup->height() );
}
}
///////////////////////////////////////
//
// core::command2IO
//
///////////////////////////////////////
void core::command2IO( const Command &command )
{
io_base *io;
int id = ((Command)command).getID();
io = myIOMap.find(id);
while( io != NULL )
{
io->recvCMD(command);
io = myIOMap.findNext();
}
}
///////////////////////////////////////
//
// core::command2Match
//
///////////////////////////////////////
void core::command2Match( const Command &command )
{
match_param *paramPtr;
match *matchPtr;
Command cmd = command;
matchPtr = myMatchMap.find( cmd.getID() );
while( matchPtr != NULL )
{
/* Catch Commands Meant for Core */
switch( cmd.getCommand() )
{
case CMD_Hint:
KMessageBox::information( this, cmd.getData(), i18n("Hint") );
break;
case CMD_Tell_User:
KMessageBox::information( this, cmd.getData(), i18n( "Tell User" ) );
break;
case CMD_Tell_User_Error:
KMessageBox::sorry( this, cmd.getData(), i18n( "Tell User Error" ) );
break;
case CMD_Tell_Opponent:
paramPtr = matchPtr->getParam();
if( ( paramPtr->type( WHITE ) == PLAYERLOCAL ) ||
( paramPtr->type( BLACK ) == PLAYERLOCAL ) )
KMessageBox::information( this, cmd.getData(), i18n( "Tell Opponent" ) );
else
command2IO( command );
break;
case CMD_Tell_Others:
command2IO( command );
break;
case CMD_Tell_ICS:
command2IO( command );
break;
case CMD_Tell_All:
paramPtr = matchPtr->getParam();
if( ( paramPtr->type( WHITE ) == PLAYERLOCAL ) ||
( paramPtr->type( BLACK ) == PLAYERLOCAL ) )
KMessageBox::information( this, cmd.getData(), i18n( "Tell All" ) );
command2IO( command );
break;
case CMD_Out_Of_Book:
// engine[enginePtr - 1]->sendCMD( CMD_Check_Book );
break;
default:
/* Just send it to the Match */
matchPtr->recvCMD( command );
break;
}
matchPtr = myMatchMap.findNext();
}
}
///////////////////////////////////////
//
// core::flag
//
///////////////////////////////////////
bool core::flag( const bool Army )
{
if( currentMatch == NULL ) return FALSE;
return currentMatch->flag( Army );
return false;
}
///////////////////////////////////////
//
// core::clock
//
///////////////////////////////////////
TQString core::clock( const bool Army )
{
if( currentMatch == NULL ) return TQString();
return currentMatch->clock( Army );
return "";
}
///////////////////////////////////////
//
// core::modified
//
///////////////////////////////////////
bool core::modified( void )
{
if( currentMatch == NULL ) return FALSE;
return currentMatch->modified();
return false;
}
///////////////////////////////////////
//
// core::paused
//
///////////////////////////////////////
bool core::paused( void )
{
if( currentMatch == NULL ) return FALSE;
return currentMatch->paused();
return false;
}
///////////////////////////////////////
//
// core::isOnline
//
///////////////////////////////////////
bool core::isOnline( void )
{
unsigned int index;
for( index=0; index < myIOMap.count(); index++ )
{
if( myIOMap[index]->getType() == io_base::INTERNET )
{
return TRUE;
}
}
return FALSE;
}
///////////////////////////////////////
//
// core::onMove
//
///////////////////////////////////////
char core::onMove( void )
{
if( currentMatch == NULL ) return Null;
return currentMatch->onMove();
}
///////////////////////////////////////
//
// core::caption
//
///////////////////////////////////////
TQString core::caption( void )
{
TQButton *Button;
if( currentMatch == NULL ) return TQString();
Button = myButtonGroup->find( currentMatch->getID() );
if( Button != NULL ) Button->setText( currentMatch->caption() );
return currentMatch->caption();
}
///////////////////////////////////////
//
// core::whiteInput
//
///////////////////////////////////////
char core::whiteInput(void)
{
if( currentMatch == NULL ) return Null;
return currentMatch->input(WHITE);
}
///////////////////////////////////////
//
// core::blackInput
//
///////////////////////////////////////
char core::blackInput(void)
{
if( currentMatch == NULL ) return Null;
return currentMatch->input(BLACK);
}
///////////////////////////////////////
//
// core::review
//
///////////////////////////////////////
void core::review( int Index )
{
if( currentMatch == NULL ) return;
currentMatch->review( Index );
}
///////////////////////////////////////
//
// core::inputOnMove
//
///////////////////////////////////////
char core::inputOnMove( bool reverse )
{
if( currentMatch == NULL ) return Null;
return currentMatch->inputOnMove( reverse );
}
///////////////////////////////////////
//
// core::notation
//
///////////////////////////////////////
TQStringList* core::notation( void )
{
if( currentMatch == NULL ) return NULL;
return currentMatch->notation();
}
///////////////////////////////////////
//
// core::slot_setNotation
//
///////////////////////////////////////
void core::slot_setNotation( void )
{
emit setNotation();
}
///////////////////////////////////////
//
// core::slot_setStatusBar
//
///////////////////////////////////////
void core::slot_setStatusBar( const int &ID, const TQString& MSG )
{
emit setStatusBar( ID, MSG );
}
///////////////////////////////////////
//
// core::slot_setClocks
//
///////////////////////////////////////
void core::slot_setClocks( void )
{
emit setClocks();
}
///////////////////////////////////////
//
// core::print
//
///////////////////////////////////////
void core::print( int ID )
{
match *m2p;
if( ID == Null )
{
m2p = currentMatch;
}
else
{
m2p = myMatchMap.find( ID );
}
if( m2p == NULL ) return;
m2p->print();
return;
}
///////////////////////////////////////
//
// core::load
//
///////////////////////////////////////
bool core::load( void )
{
const TQString fileFilter( "*.pgn *.Pgn *.PGN|Portable Game Notation (.pgn)\n*|All Files" );
TQString URL;
URL = KFileDialog::getOpenFileName( TQString(), TQString( fileFilter ), this, i18n( "Load PGN..." ) );
if( URL.isEmpty() ) return FALSE;
return load( URL );
}
bool core::load( const TQString &IncURL )
{
listPGN = new list_pgn( 0, "listPGN" );
myResource->tabManager->addTab( listPGN, IncURL.section( '/', -1 ) );
connect( listPGN, TQT_SIGNAL( selected( const TQString&, const int& ) ), this, TQT_SLOT( load( const TQString&, const int& ) ) );
listPGN->setURL( IncURL );
return TRUE;
}
bool core::load( const TQString &url, const int &pos )
{
newMatch( new match_param( myResource, PLAYERLOAD, PLAYERLOAD ) );
return currentMatch->load( url, pos );
}
///////////////////////////////////////
//
// core::save
//
///////////////////////////////////////
bool core::save( const int ID, const bool Prompt, const bool SaveAs )
{
const TQString fileFilter( "*.pgn *.Pgn *.PGN|Portable Game Notation (.pgn)\n*|All Files" );
match *match2bSaved;
int answer;
TQString URL;
if( ID == Null )
{
/* Use current match */
match2bSaved = currentMatch;
}
else
{
match2bSaved = myMatchMap.find( ID );
}
if( match2bSaved == NULL ) return FALSE;
if( Prompt )
{
/* Prompt for the save */
myResource->ConfigWrite();
answer = KMessageBox::warningYesNoCancel( this,
i18n("Would you like to save this match?"),
i18n("Save Match?"),
TQString(),
TQString(),
TQString("PromptForSaving") );
myResource->ConfigRead();
if( answer == KMessageBox::Cancel )
{
return FALSE;
}
if( answer == KMessageBox::No )
{
return TRUE;
}
}
/* Get the last URL we used */
URL = match2bSaved->url();
if( ( URL.isEmpty() ) || ( SaveAs ) )
{
/* Get a new URL */
URL = KFileDialog::getSaveFileName( TQString(), TQString( fileFilter ), this, i18n( "Save Match..." ) );
if( URL.isNull() )
{
return FALSE;
}
if( URL.findRev( ".pgn", -1, FALSE ) == -1 )
{
URL += ".pgn";
}
}
if( match2bSaved->save( URL ) == FALSE )
{
emit setStatusBar( SAVE_ERROR );
return FALSE;
}
emit setStatusBar( SAVE_OK );
match2bSaved->setModified( FALSE );
return TRUE;
}
///////////////////////////////////////
//
// core::matchMenu
//
///////////////////////////////////////
void core::matchMenu( int opt )
{
unsigned int index;
switch(opt)
{
/* Offer / Accept Draw */
case MENU_OFFER_DRAW: // Fall Through
case MENU_ACCEPT_DRAW:
if( whiteInput() == PLAYERLOCAL )
{
command2Match( Command( currentMatch->getID(), CMD_Offer_Draw, TQString("W") ) );
}
if( blackInput() == PLAYERLOCAL )
{
command2Match( Command( currentMatch->getID(), CMD_Offer_Draw, TQString("B") ) );
}
command2IO( Command( currentMatch->getID(), CMD_Offer_Draw ) );
break;
/* Reject Draw */
case MENU_REJECT_DRAW:
command2IO( Command( currentMatch->getID(), CMD_Reject_Draw ) );
break;
/* Resign */
case MENU_RESIGN:
if( ( whiteInput() == PLAYERLOCAL ) && ( currentMatch->onMove() == WHITE ) )
{
command2IO( Command( currentMatch->getID(), CMD_White_Resign ) );
currentMatch->recvCMD( Command( currentMatch->getID(), CMD_White_Resign ) );
}
if( ( blackInput() == PLAYERLOCAL ) && ( currentMatch->onMove() == BLACK ) )
{
command2IO( Command( currentMatch->getID(), CMD_Black_Resign ) );
currentMatch->recvCMD( Command( currentMatch->getID(), CMD_Black_Resign ) );
}
break;
/* Retract */
case MENU_RETRACT:
command2IO( Command( currentMatch->getID(), CMD_Retract_Move ) );
currentMatch->retract();
currentMatch->retract();
emit setNotation();
if( onMove() == WHITE )
emit setStatusBar( WHITE_TURN );
else
emit setStatusBar( BLACK_TURN );
break;
/* Move Now */
case MENU_MOVE_NOW:
command2IO( Command( currentMatch->getID(), CMD_MoveNow ) );
break;
/* Hint */
case MENU_HINT:
currentMatch->requestHint();
break;
/* Qt::Orientation */
case MENU_ORIENTATION:
currentMatch->flip();
break;
/* Ponder */
case MENU_PONDER:
if( myResource->OPTION_Ponder )
{
command2IO( Command( currentMatch->getID(), CMD_Ponder ) );
}
else
{
command2IO( Command( currentMatch->getID(), CMD_No_Pondering ) );
}
break;
/* Pause */
case MENU_PAUSE:
currentMatch->setPaused( !currentMatch->paused() );
if( currentMatch->paused() )
{
command2IO( Command( currentMatch->getID(), CMD_Pause ) );
}
else
{
command2IO( Command( currentMatch->getID(), CMD_Resume ) );
}
break;
/* Pause All */
case MENU_PAUSEALL:
if( myMatchMap.count() )
{
for( index = 0; index < myMatchMap.count(); index++ )
{
if( ( whiteInput() == PLAYERTCP ) || ( blackInput() == PLAYERTCP ) )
continue;
myMatchMap[index]->setPaused( !myMatchMap[index]->paused() );
if( myMatchMap[index]->paused() )
{
command2IO( Command( currentMatch->getID(), CMD_Pause ) );
}
else
{
command2IO( Command( currentMatch->getID(), CMD_Resume ) );
}
}
}
break;
/* Call Flag */
case MENU_CALL_FLAG:
if( whiteInput() == PLAYERLOCAL )
{
command2IO( Command( currentMatch->getID(), CMD_White_Called_Flag ) );
currentMatch->recvCMD( Command( currentMatch->getID(), CMD_White_Called_Flag ) );
}
if( blackInput() == PLAYERLOCAL )
{
command2IO( Command( currentMatch->getID(), CMD_Black_Called_Flag ) );
currentMatch->recvCMD( Command( currentMatch->getID(), CMD_Black_Called_Flag ) );
}
break;
default:
break;
}
}
///////////////////////////////////////
//
// core::thinButtonMenu
//
///////////////////////////////////////
void core::thinButtonMenu( int id, int item )
{
switch( item )
{
case MENU_SAVE:
save( id, FALSE, FALSE );
break;
case MENU_SAVEAS:
save( id, FALSE, TRUE );
break;
case MENU_PRINT:
print( id );
break;
case MENU_CLOSE:
clearMatch( id );
break;
default:
break;
}
}
///////////////////////////////////////
//
// core::resetServer
//
///////////////////////////////////////
void core::resetServer( void )
{
command2IO( Command( Null, CMD_Reset_Server ) );
}
///////////////////////////////////////
//
// core::goOffline()
//
///////////////////////////////////////
void core::goOffline(void)
{
unsigned int index(0);
io_base *ioPtr(NULL);
while( index < myIOMap.count() )
{
if( myIOMap[index]->getType() == io_base::INTERNET )
{
ioPtr = myIOMap[index];
if( myIOMap.keyAt(index) != Null )
{
clearMatch( myIOMap.keyAt(index) );
}
else
{
myIOMap.remove( Null );
}
index = 0;
continue;
}
index++;
}
if( ioPtr != NULL )
delete ioPtr;
}