summaryrefslogtreecommitdiffstats
path: root/kenolaba/AbTop.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kenolaba/AbTop.cpp')
-rw-r--r--kenolaba/AbTop.cpp988
1 files changed, 988 insertions, 0 deletions
diff --git a/kenolaba/AbTop.cpp b/kenolaba/AbTop.cpp
new file mode 100644
index 00000000..a2283f16
--- /dev/null
+++ b/kenolaba/AbTop.cpp
@@ -0,0 +1,988 @@
+/* Class AbTop */
+
+#include <qpopupmenu.h>
+#include <qtimer.h>
+#include <qclipboard.h>
+
+#include <kaction.h>
+#include <kapplication.h>
+#include <kconfig.h>
+#include <kdialogbase.h>
+#include <kiconloader.h>
+#include <klocale.h>
+#include <kmenubar.h>
+#include <kstdaccel.h>
+#include <kglobal.h>
+#include <kstatusbar.h>
+#include <kstdaction.h>
+#include <kstdgameaction.h>
+#include <kdebug.h>
+
+#include "AbTop.h"
+#include "Board.h"
+#include "BoardWidget.h"
+#include "EvalDlgImpl.h"
+#include "EvalScheme.h"
+#include "Network.h"
+#include "Spy.h"
+#include "version.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+// #define MYTRACE 1
+
+const AbTop::Data AbTop::LEVEL[Nb_Levels] = {
+ { "Easy", I18N_NOOP("&Easy") },
+ { "Normal", I18N_NOOP("&Normal") },
+ { "Hard", I18N_NOOP("&Hard") },
+ { "Challange", I18N_NOOP("&Challenge") }
+};
+
+const AbTop::Data AbTop::IPLAY[Nb_IPlays] = {
+ { "Red", I18N_NOOP("&Red") },
+ { "Yellow", I18N_NOOP("&Yellow") },
+ { "Both", I18N_NOOP("&Both") },
+ { "None", I18N_NOOP("&None") }
+};
+
+AbTop::AbTop()
+ :KMainWindow(0)
+{
+ timerState = noGame;
+
+ myPort = Network::defaultPort;
+ currentEvalScheme = 0;
+ net = 0;
+
+ actValue = 0;
+ stop = false;
+ editMode = false;
+ spyLevel = 0;
+ pastePossible = true;
+
+
+ timer = new QTimer;
+ connect( timer, SIGNAL(timeout()), this, SLOT(timerDone()) );
+
+ board = new Board();
+ setMoveNo(0);
+
+ connect( board, SIGNAL(searchBreak()), this, SLOT(searchBreak()) );
+ Q_CHECK_PTR(board);
+ boardWidget = new BoardWidget(*board,this);
+
+#ifdef SPION
+ spy = new Spy(*board);
+#endif
+
+ connect( boardWidget, SIGNAL(updateSpy(QString)),
+ this, SLOT(updateSpy(QString)) );
+
+ setCentralWidget(boardWidget);
+ boardWidget->show();
+
+ // this creates the GUI
+ setupActions();
+ setupStatusBar();
+ setMinimumSize(200,300);
+
+ // RMB context menu
+ connect( boardWidget, SIGNAL(rightButtonPressed(int,const QPoint&)),
+ this, SLOT(rightButtonPressed(int,const QPoint&)) );
+
+ connect( boardWidget, SIGNAL(edited(int)),
+ this, SLOT(edited(int)) );
+
+ connect( board, SIGNAL(updateBestMove(Move&,int)),
+ this, SLOT(updateBestMove(Move&,int)) );
+
+ connect( boardWidget, SIGNAL(moveChoosen(Move&)),
+ this, SLOT(moveChoosen(Move&)) );
+
+ /* default */
+ setLevel(Easy);
+ setIPlay(Red);
+ showMoveLong = true;
+ showSpy = false;
+ renderBalls = true;
+
+ updateStatus();
+ updateActions();
+ setupGUI();
+}
+
+AbTop::~AbTop()
+{
+ /* Unregister from other abalone processes */
+ delete net;
+ delete timer;
+#ifdef SPION
+ delete spy;
+#endif
+}
+
+
+/**
+ * Create all the actions...
+ *
+ * The GUI will be built in createGUI using a XML file
+ *
+ */
+
+void AbTop::setupActions()
+{
+ newAction = KStdGameAction::gameNew( this, SLOT(newGame()), actionCollection() );
+ KStdGameAction::quit( this, SLOT(close()), actionCollection() );
+
+ stopAction = new KAction( i18n("&Stop Search"), "stop", Key_S, this,
+ SLOT(stopSearch()), actionCollection(), "move_stop");
+
+ backAction = new KAction( i18n("Take &Back"), "back",
+ KStdAccel::shortcut(KStdAccel::Prior), this,
+ SLOT(back()), actionCollection(), "move_back");
+
+ forwardAction = new KAction( i18n("&Forward"), "forward",
+ KStdAccel::shortcut(KStdAccel::Next), this,
+ SLOT(forward()), actionCollection(), "move_forward");
+
+ hintAction = KStdGameAction::hint(this, SLOT(suggestion()), actionCollection());
+
+ KStdAction::copy( this, SLOT(copy()), actionCollection());
+ pasteAction = KStdAction::paste( this, SLOT(paste()), actionCollection());
+
+ (void) new KAction( i18n("&Restore Position"),
+ KStdAccel::shortcut(KStdAccel::Open),
+ this, SLOT(restorePosition()),
+ actionCollection(), "edit_restore" );
+
+ (void) new KAction( i18n("&Save Position"),
+ KStdAccel::shortcut(KStdAccel::Save),
+ this, SLOT(savePosition()),
+ actionCollection(), "edit_save" );
+
+ KToggleAction *ta;
+
+ ta = new KToggleAction( i18n("&Network Play"), "network", Key_N,
+ actionCollection(), "game_net");
+ connect(ta, SIGNAL(toggled(bool)), this, SLOT(gameNetwork(bool)));
+
+ editAction = new KToggleAction( i18n("&Modify"), "edit",
+ CTRL+Key_Insert, actionCollection(), "edit_modify");
+ connect(editAction, SIGNAL(toggled(bool)), this, SLOT( editModify(bool)));
+
+ showMenubar = KStdAction::showMenubar(this, SLOT(toggleMenubar()), actionCollection());
+ KStdAction::saveOptions( this, SLOT(writeConfig()), actionCollection());
+
+ KStdAction::preferences( this, SLOT(configure()), actionCollection());
+
+ moveSlowAction = new KToggleAction( i18n("&Move Slow"), 0,
+ actionCollection(), "options_moveSlow");
+ connect(moveSlowAction, SIGNAL(toggled(bool)), this, SLOT(optionMoveSlow(bool)));
+
+ renderBallsAction = new KToggleAction( i18n("&Render Balls"), 0,
+ actionCollection(), "options_renderBalls");
+ connect(renderBallsAction, SIGNAL(toggled(bool)), this, SLOT(optionRenderBalls(bool)));
+
+ showSpyAction = new KToggleAction( i18n("&Spy"), 0,
+ actionCollection(), "options_showSpy");
+ connect(showSpyAction, SIGNAL(toggled(bool)), this, SLOT(optionShowSpy(bool)));
+
+
+ levelAction = KStdGameAction::chooseGameType(0, 0, actionCollection());
+ QStringList list;
+ for (uint i=0; i<Nb_Levels; i++)
+ list.append( i18n(LEVEL[i].label) );
+ levelAction->setItems(list);
+ connect(levelAction, SIGNAL(activated(int)), SLOT(setLevel(int)));
+
+ iplayAction = new KSelectAction(i18n("&Computer Play"), 0, actionCollection(), "options_iplay");
+ list.clear();
+ for (uint i=0; i<Nb_IPlays; i++)
+ list.append( i18n(IPLAY[i].label) );
+ iplayAction->setItems(list);
+ connect(iplayAction, SIGNAL(activated(int)), SLOT(setIPlay(int)));
+}
+
+void AbTop::toggleMenubar()
+{
+ if (menuBar()->isVisible())
+ menuBar()->hide();
+ else
+ menuBar()->show();
+}
+
+void AbTop::configure()
+{
+ KDialogBase *dlg = new KDialogBase( 0, "ConfigureEvaluation", true,
+ i18n("Configure Evaluation"),
+ KDialogBase::Ok | KDialogBase::Cancel,
+ KDialogBase::Ok, true);
+
+ EvalDlgImpl *edlg = new EvalDlgImpl(dlg,board);
+ dlg->setMainWidget(edlg);
+ if (dlg->exec()) {
+ *currentEvalScheme = *(edlg->evalScheme());
+ board->setEvalScheme(currentEvalScheme);
+ }
+ delete edlg;
+}
+
+/* Right Mouse button pressed in BoardWidget area */
+void AbTop::rightButtonPressed(int /* field */, const QPoint& pos)
+{
+ QPopupMenu* rmbMenu = static_cast<QPopupMenu*> (factory()->container("rmbPopup",this));
+ if (rmbMenu)
+ rmbMenu->popup( pos );
+}
+
+/* Read config options
+ *
+ * menu must already be created!
+ */
+void AbTop::readConfig()
+{
+ kdDebug(12011) << "Reading config..." << endl;
+
+ KConfig* config = kapp->config();
+ config->setGroup("Options");
+
+ readOptions(config);
+
+ applyMainWindowSettings( config, "Appearance" );
+
+ showMenubar->setChecked( !menuBar()->isHidden() );
+
+ currentEvalScheme = new EvalScheme("Current");
+ currentEvalScheme->read(config);
+ board->setEvalScheme( currentEvalScheme );
+}
+
+void AbTop::readOptions(KConfig* config)
+{
+ QString entry = config->readEntry("Level");
+ for (uint i=0; i<Nb_Levels; i++)
+ if ( entry==LEVEL[i].key ) setLevel(i);
+
+ entry = config->readEntry("Computer");
+ for (uint i=0; i<Nb_IPlays; i++)
+ if ( entry==IPLAY[i].key ) setIPlay(i);
+
+ showMoveLong = config->readBoolEntry("MoveSlow", false);
+ moveSlowAction->setChecked( showMoveLong );
+
+ renderBalls = config->readBoolEntry("RenderBalls", true);
+ boardWidget->renderBalls(renderBalls);
+ renderBallsAction->setChecked( renderBalls );
+
+ showSpy = config->readBoolEntry("ShowSpy", true);
+ board->updateSpy(showSpy);
+ showSpyAction->setChecked( showSpy );
+}
+
+void AbTop::readProperties(KConfig *config)
+{
+ QString entry;
+
+ readOptions(config);
+
+ currentEvalScheme = new EvalScheme("Current");
+ currentEvalScheme->read(config);
+ board->setEvalScheme( currentEvalScheme );
+
+
+ if (!(entry = config->readEntry("TimerState")).isNull())
+ timerState = entry.toInt();
+ if (timerState == noGame) return;
+
+ stop = config->readBoolEntry("GameStopped", false);
+
+ int mNo = 0;
+ if (!(entry = config->readEntry("Position")).isNull()) {
+ mNo = board->setState(entry);
+ boardWidget->updatePosition(true);
+ }
+ setMoveNo(mNo, true);
+
+ show();
+ playGame();
+}
+
+void AbTop::writeConfig()
+{
+ kdDebug(12011) << "Writing config..." << endl;
+
+ KConfig* config = kapp->config();
+ config->setGroup("Options");
+
+ writeOptions(config);
+
+ saveMainWindowSettings( config, "Appearance" );
+
+ if (currentEvalScheme)
+ currentEvalScheme->save(config);
+ config->sync();
+}
+
+
+void AbTop::writeOptions(KConfig *config)
+{
+ config->writeEntry("Level", LEVEL[levelAction->currentItem()].key);
+ config->writeEntry("Computer", IPLAY[iplayAction->currentItem()].key);
+
+ config->writeEntry("MoveSlow", showMoveLong);
+ config->writeEntry("RenderBalls", renderBalls);
+ config->writeEntry("ShowSpy", showSpy);
+}
+
+void AbTop::saveProperties(KConfig *config)
+{
+ writeOptions(config);
+ if (currentEvalScheme)
+ currentEvalScheme->save(config);
+
+ config->writeEntry("TimerState", timerState);
+
+ if (timerState == noGame) return;
+
+ config->writeEntry("GameStopped", stop);
+ config->writeEntry("Position", board->getState(moveNo));
+ config->sync();
+}
+
+void AbTop::savePosition()
+{
+ KConfig* config = kapp->config();
+ config->setGroup("SavedPosition");
+ config->writeEntry("Position", board->getState(moveNo));
+}
+
+void AbTop::restorePosition()
+{
+ KConfig* config = kapp->config();
+ config->setGroup("SavedPosition");
+ QString entry = config->readEntry("Position");
+
+ timerState = notStarted;
+ timer->stop();
+ board->begin(Board::color1);
+ stop = false;
+ setMoveNo( board->setState(entry), true );
+
+ if (net)
+ net->broadcast( board->getASCIIState( moveNo ).ascii() );
+
+ boardWidget->updatePosition(true);
+
+ playGame();
+}
+
+void AbTop::setupStatusBar()
+{
+ QString tmp;
+
+ QString t = i18n("Press %1 for a new game").arg( newAction->shortcut().toString());
+ statusLabel = new QLabel( t, statusBar(), "statusLabel" );
+ statusBar()->addWidget(statusLabel,1,false);
+
+ // PERMANENT: Moving side + move No.
+
+ // validPixmap, only visible in Modify mode: is position valid ?
+ warningPix = BarIcon( "warning" );
+ okPix = BarIcon( "ok" );
+ validLabel = new QLabel( "", statusBar(), "validLabel" );
+ validLabel->setFixedSize( 18, statusLabel->sizeHint().height() );
+ validLabel->setAlignment( AlignCenter );
+ validLabel->hide();
+ validShown = false;
+
+ redBall = BarIcon( "redball" );
+ yellowBall = BarIcon( "yellowball" );
+ noBall = BarIcon( "noball" );
+ ballLabel = new QLabel( "", statusBar(), "ballLabel" );
+ ballLabel->setPixmap(noBall);
+ ballLabel->setFixedSize( 18, statusLabel->sizeHint().height() );
+ ballLabel->setAlignment( AlignCenter );
+ statusBar()->addWidget(ballLabel, 0, true);
+
+ moveLabel = new QLabel( i18n("Move %1").arg("--"), statusBar(), "moveLabel" );
+ statusBar()->addWidget(moveLabel, 0, true);
+
+#ifdef MYTRACE
+ /* Create a toolbar menu for debugging output level */
+ KToolBar *tb = toolBar("mainToolBar");
+ if (tb) {
+ QPopupMenu* spyPopup = new QPopupMenu;
+ spy0 = BarIcon( "spy0" );
+ spy1 = BarIcon( "spy1" );
+ spy2 = BarIcon( "spy2" );
+ spy3 = BarIcon( "spy3" );
+ spyPopup->insertItem(spy0, 0);
+ spyPopup->insertItem(spy1, 1);
+ spyPopup->insertItem(spy2, 2);
+ spyPopup->insertItem(spy3, 3);
+ connect( spyPopup, SIGNAL(activated(int)),
+ this, SLOT(setSpy(int)) );
+ tb->insertButton(spy0, 30, spyPopup,
+ TRUE, i18n("Spy"));
+ }
+#endif
+
+}
+
+
+
+void AbTop::updateSpy(QString s)
+{
+ if (showSpy) {
+ if (s.isEmpty()) {
+ updateStatus();
+ // statusBar()->clear();
+ }
+ else
+ statusLabel->setText(s);
+ }
+}
+
+void AbTop::updateBestMove(Move& m, int value)
+{
+ if (showSpy) {
+ boardWidget->showMove(m,3);
+ boardWidget->showMove(m,0,false);
+
+ QString tmp;
+ tmp.sprintf("%s : %+d", (const char*) m.name().utf8(), value-actValue);
+ updateSpy(tmp);
+ kapp->processEvents();
+ }
+}
+
+
+void AbTop::updateStatus()
+{
+ QString tmp;
+ bool showValid = false;
+
+ if (!editMode && timerState == noGame) {
+ tmp = i18n("Move %1").arg("--");
+ ballLabel->setPixmap(noBall);
+ }
+ else {
+ tmp = i18n("Move %1").arg(moveNo/2 + 1);
+ ballLabel->setPixmap( (board->actColor() == Board::color1)
+ ? redBall : yellowBall);
+ }
+ moveLabel->setText(tmp);
+
+ if (editMode) {
+ tmp = QString("%1: %2 %3 - %4 %5")
+ .arg( i18n("Edit") )
+ .arg( i18n("Red") ).arg(boardWidget->getColor1Count())
+ .arg( i18n("Yellow") ).arg(boardWidget->getColor2Count());
+ validLabel->setPixmap( (board->validState() == Board::invalid)
+ ? warningPix:okPix );
+ showValid = true;
+ }
+ else if (timerState == noGame) {
+ tmp = i18n("Press %1 for a new game").arg( newAction->shortcut().toString());
+ }
+ else {
+ if (timerState == gameOver) {
+ tmp = (board->actColor() == Board::color2) ?
+ i18n("Red won"):i18n("Yellow won");
+ validLabel->setPixmap( warningPix );
+ showValid = true;
+ }
+ else {
+ tmp = QString("%1 - %2")
+ .arg( (board->actColor() == Board::color1) ?
+ i18n("Red"):i18n("Yellow") )
+ .arg( iPlayNow() ?
+ i18n("I am thinking...") : i18n("It is your turn!") );
+ }
+ }
+ statusLabel->setText(tmp);
+ if (validShown != showValid) {
+ if (showValid) {
+ statusBar()->addWidget(validLabel);
+ validLabel->show();
+ }
+ else {
+ statusBar()->removeWidget(validLabel);
+ validLabel->hide();
+ }
+ validShown = showValid;
+ }
+ statusBar()->clear();
+ statusBar()->repaint();
+}
+
+void AbTop::edited(int vState)
+{
+ if (vState == Board::empty)
+ timerState = noGame;
+
+ updateStatus();
+}
+
+/* only <stop search>, <hint>, <take back> have to be updated */
+void AbTop::updateActions()
+{
+ bool iPlay = iPlayNow();
+
+ /* New && Copy always on */
+
+ /* Paste */
+ pastePossible = !iPlay;
+ pasteAction->setEnabled(!iPlay);
+
+ /* Edit */
+ editAction->setEnabled(!iPlay);
+
+ /* Stop search */
+ stopAction->setEnabled(iPlay);
+
+ /* Back */
+ bool bBack = (editMode && moveNo>0) ||
+ (board->movesStored() >=1 && !iPlay);
+ backAction->setEnabled(bBack);
+
+ /* Forward */
+ bool bForward = editMode && moveNo<999;
+ forwardAction->setEnabled(bForward);
+
+ /* Hint */
+ bool bHint = !editMode && !iPlay && (haveHint().type != Move::none);
+ hintAction->setEnabled(bHint);
+}
+
+/* let the program be responsive even in a long search... */
+void AbTop::searchBreak()
+{
+ kapp->processEvents();
+}
+
+
+void AbTop::setSpy(int id )
+{
+ toolBar("mainToolBar")->setButtonPixmap(30, (id==0)?spy0:(id==1)?spy1:(id==2)?spy2:spy3 );
+ spyLevel = id;
+ board->setSpyLevel(spyLevel);
+}
+
+void AbTop::timerDone()
+{
+ int interval = 400;
+
+ switch(timerState) {
+ case noGame:
+ case notStarted:
+ return;
+ case showMove:
+ case showMove+2:
+ case showSugg:
+ case showSugg+2:
+ case showSugg+4:
+ boardWidget->showMove(actMove, 2);
+ interval = 200;
+ break;
+ case showMove+1:
+ case showMove+3:
+ case showSugg+1:
+ case showSugg+3:
+ boardWidget->showMove(actMove, 3);
+ break;
+ case showSugg+5:
+ interval = 800;
+ case showMove+4:
+ boardWidget->showMove(actMove, 4);
+ break;
+ case showMove+5:
+ boardWidget->showMove(actMove, 0);
+ timerState = moveShown;
+ playGame();
+ return;
+ case showSugg+6:
+ boardWidget->showMove(actMove, 0);
+ timerState = notStarted;
+ return;
+ }
+ timerState++;
+ timer->start(interval,TRUE);
+}
+
+void AbTop::userMove()
+{
+ /* User has to move */
+ static MoveList list;
+
+ list.clear();
+ board->generateMoves(list);
+
+ if (list.getLength() == 0) {
+ stop = true;
+ timerState = gameOver;
+ playGame();
+ }
+ else
+ boardWidget->choseMove(&list);
+}
+
+bool AbTop::iPlayNow()
+{
+ if (editMode ||
+ (board->validState() != Board::valid) ||
+ timerState == gameOver)
+ return false;
+
+ int c = board->actColor();
+
+ /* color1 is red */
+ return ((iplay == Both) ||
+ ((c == Board::color1) && (iplay == Red) ) ||
+ ((c == Board::color2) && (iplay == Yellow) ));
+}
+
+void AbTop::playGame()
+{
+ if (timerState == moveShown) {
+ if (actMove.type != Move::none) {
+ board->playMove(actMove);
+ moveNo++; // actColor in board is changed in playMove
+
+ if (net)
+ net->broadcast( board->getASCIIState( moveNo ).ascii() );
+ }
+ actValue = - board->calcEvaluation();
+ boardWidget->updatePosition(true);
+ timerState = notStarted;
+ }
+ if (!board->isValid()) {
+ stop = true;
+ timerState = gameOver;
+ }
+
+ updateStatus();
+ updateActions();
+ boardWidget->setCursor(crossCursor);
+ if (stop) return;
+
+
+ if (!iPlayNow()) {
+ userMove();
+ return;
+ }
+ boardWidget->setCursor(waitCursor);
+ kapp->processEvents();
+
+ if (moveNo <4) {
+ /* Chose a random move making the position better for actual color */
+
+ /* If comparing ratings among color1/2 on move, we have to negate one */
+ int v = -board->calcEvaluation(), vv;
+ do {
+ actMove = board->randomMove();
+ board->playMove(actMove);
+ vv = board->calcEvaluation();
+ board->takeBack();
+ } while( (board->actColor() == Board::color1) ? (vv<v) : (vv>v) );
+ }
+ else {
+ actMove = (board->bestMove());
+
+ if (actMove.type == Move::none) {
+ stop = true;
+ timerState = gameOver;
+ playGame();
+ return;
+ }
+ }
+
+ timerState = showMoveLong ? showMove : showMove+3;
+ timerDone();
+}
+
+void AbTop::moveChoosen(Move& m)
+{
+ actMove = m;
+ timerState = moveShown;
+ playGame();
+}
+
+void AbTop::newGame()
+{
+ /* stop a running animation */
+ timerState = notStarted;
+ timer->stop();
+
+ /* reset board */
+ board->begin(Board::color1);
+ boardWidget->updatePosition(true);
+ setMoveNo(0, true);
+
+ if (net)
+ net->broadcast( board->getASCIIState( moveNo ).ascii() );
+
+ /* if not in EditMode, start Game immediately */
+ if (!editMode) {
+ stop = false;
+ playGame();
+ }
+}
+
+/* Copy ASCII representation into Clipboard */
+void AbTop::copy()
+{
+ QClipboard *cb = QApplication::clipboard();
+ cb->setText( board->getASCIIState( moveNo ).ascii() );
+}
+
+void AbTop::paste()
+{
+ if (!pastePossible) return;
+
+ QClipboard *cb = QApplication::clipboard();
+ pastePosition( cb->text().ascii() );
+ /* don't do this in pastePosition: RECURSION !! */
+
+ if (net)
+ net->broadcast( board->getASCIIState( moveNo ).ascii() );
+}
+
+void AbTop::pastePosition(const char * text)
+{
+ if (!pastePossible) return;
+ if ( text ) {
+ timerState = notStarted;
+ timer->stop();
+ board->begin(Board::color1);
+ stop = false;
+
+ int mNo = board->setASCIIState(text);
+ if (mNo<0) mNo=0;
+ setMoveNo( mNo, true);
+
+ boardWidget->updatePosition(true);
+
+ if ( (board->validState()==Board::invalid) && !editMode) {
+ editAction->setChecked(true);
+ return;
+ }
+
+ playGame();
+ }
+}
+
+
+void AbTop::gameNetwork(bool on)
+{
+ if (!on) {
+ if (net != 0) {
+ delete net;
+ net = 0;
+ }
+ return;
+ }
+
+ if (myPort == 0) myPort = Network::defaultPort;
+ net = new Network(myPort);
+ char *h, h2[100];
+ int p, i;
+ for(h = hosts.first(); h!=0; h=hosts.next()) {
+ for(i=0;h[i]!=0 && h[i]!=':';i++);
+ if (h[i]==':')
+ p = atoi(h+i+1);
+ else
+ p = 0;
+
+ if (p == 0) p = Network::defaultPort;
+ strncpy(h2,h,i);
+ h2[i]=0;
+ net->addListener(h2, p);
+ }
+ QObject::connect(net, SIGNAL(gotPosition(const char *)),
+ this, SLOT(pastePosition(const char *)) );
+}
+
+
+void AbTop::editModify(bool on)
+{
+ int vState = board->validState();
+
+ editMode = boardWidget->setEditMode( on );
+ if (vState != Board::valid)
+ timerState = noGame;
+
+ updateActions();
+ updateStatus();
+ if (!editMode && vState == Board::valid) {
+ actMove.type = Move::none;
+ timerState = moveShown;
+ playGame();
+ }
+}
+
+void AbTop::stopGame()
+{
+ stop = true;
+ board->stopSearch();
+}
+
+void AbTop::stopSearch()
+{
+ // When computer plays both, switch back to human for next color
+ if (iplay == Both) {
+ if (board->actColor() == Board::color1) setIPlay(Red);
+ else setIPlay(Yellow);
+ }
+ board->stopSearch();
+}
+
+bool AbTop::queryClose()
+{
+ board->stopSearch();
+ return true;
+}
+
+void AbTop::continueGame()
+{
+ if (timerState != noGame && timerState != gameOver) {
+ stop = false;
+ if (timerState == notStarted)
+ playGame();
+ }
+}
+
+/**
+ * Reset the Move number of the actual game to <m>
+ * If <update> is true, update GUI actions and redraw statusbar
+ */
+void AbTop::setMoveNo(int m, bool updateGUI)
+{
+ moveNo = m;
+
+ board->setActColor( ((moveNo%2)==0) ? Board::color1 : Board::color2 );
+
+ if (updateGUI) {
+ updateStatus();
+ updateActions();
+ }
+}
+
+
+/* "Back" action activated
+ *
+ * If in edit mode, simple go 1 back
+ * If in a game, go back 2 if possible
+ */
+void AbTop::back()
+{
+ if (editMode) {
+ if (moveNo > 0)
+ setMoveNo(moveNo-1, true);
+ return;
+ }
+
+ if (moveNo < 1) return;
+
+ if (timerState == gameOver)
+ timerState = notStarted;
+ if (timerState != notStarted) return;
+
+ /* If possible, go 2 steps back */
+ if (moveNo>0 && board->takeBack()) moveNo--;
+ if (moveNo>0 && board->takeBack()) moveNo--;
+ setMoveNo( moveNo, true );
+
+ boardWidget->updatePosition(true);
+
+ userMove();
+}
+
+/* Only for edit Mode */
+void AbTop::forward()
+{
+ if (editMode) {
+ if (moveNo < 999)
+ setMoveNo(moveNo+1, true);
+ return;
+ }
+}
+
+Move AbTop::haveHint()
+{
+ static Move m;
+ static int oldMoveNo = 0;
+
+ if (timerState != notStarted) {
+ m.type = Move::none;
+ }
+ else if (moveNo != oldMoveNo) {
+ MoveList list;
+
+ oldMoveNo = moveNo;
+ m = board->nextMove();
+ board->generateMoves(list);
+ if (!list.isElement(m,0))
+ m.type = Move::none;
+ }
+ return m;
+}
+
+
+void AbTop::suggestion()
+{
+ if (timerState != notStarted) return;
+ Move m = haveHint();
+ if (m.type == Move::none) return;
+
+ actMove = m;
+
+ timerState = showSugg;
+ timerDone();
+}
+
+void AbTop::setLevel(int l)
+{
+ levelAction->setCurrentItem(l);
+ depth = l+2;
+ board->setDepth(depth);
+ // kdDebug(12011) << "Level set to " << d << endl;
+}
+
+void AbTop::setIPlay(int i)
+{
+ iplayAction->setCurrentItem(i);
+ iplay = (IPlay)i;
+ continueGame();
+}
+
+void AbTop::optionMoveSlow(bool on)
+{
+ showMoveLong = on;
+}
+
+void AbTop::optionRenderBalls(bool on)
+{
+ renderBalls = on;
+ boardWidget->renderBalls(renderBalls);
+}
+
+void AbTop::optionShowSpy(bool on)
+{
+ showSpy = on;
+ board->updateSpy(showSpy);
+
+#ifdef SPION
+ if (showSpy)
+ spy->show();
+ else {
+ spy->nextStep();
+ spy->hide();
+ }
+#endif
+
+}
+
+
+#include "AbTop.moc"