Logo Search packages:      
Sourcecode: qgo version File versions  Download package

qgo_interface.cpp

/*
 *   qgo_interface.cpp - qGoClient's interface to qGo
 */

#include "qgo.h"
#include "mainwindow.h"
#include "qgo_interface.h"
#include "tables.h"
#include "defines.h"
#include "globals.h"
#include "gs_globals.h"
#include "misc.h"
#include "config.h"
#include "interfacehandler.h"
#include "normaltools_gui.h"
#include "move.h"
#include "qnewgamedlg.h"
#include <qlabel.h>
//#include <qmultilineedit.h>
#include <qobject.h>
#include <qstring.h>
#include <qtimer.h>
#include <qpushbutton.h>
#include <qmessagebox.h>
#include <qtooltip.h>
#include <qcombobox.h>
#include <qslider.h>
#include <qtoolbar.h>
#include <qptrlist.h>


/*
 *    Playing or Observing
 */

qGoIF::qGoIF(QWidget *p) : QObject()
{
      qgo = new qGo();

      ASSERT(qgo);

      setting->qgo = qgo;
      parent = p;
      qgobrd = 0;
      gsName = GS_UNKNOWN;
      boardlist = new QPtrList<qGoBoard>;
      boardlist->setAutoDelete(false);
      localBoardCounter = 10000;

      // init sound (all sounds!)
      qgo->loadSound();
}

qGoIF::~qGoIF()
{
      delete boardlist;
      delete qgo;
}


// handle move info and distribute to different boards
bool qGoIF::parse_move(int src, GameInfo* gi, Game* g, QString txt)
{
#ifdef SHOW_MOVES_DLG
      static Talk *dlg;
#endif

      int         game_id = 0;
      StoneColor  sc = stoneNone;
      QString     pt;
      QString     mv_nr;

      switch (src)
      {
            // regular move info (parser)
            case 0:
                  game_id = gi->nr.toInt();
                  if (gi->mv_col == QString("B"))
                        sc = stoneBlack;
                  else if (gi->mv_col == QString("W"))
                        sc = stoneWhite;
                  else
                        sc = stoneNone;
                  mv_nr = gi->mv_nr;
                  pt = gi->mv_pt;
                  break;

            // adjourn/end/resume of a game (parser)
            case 1:
                  // check if g->nr is a number
                  if (g->nr == QString("@"))
                  {
                        qGoBoard *qb = boardlist->first();
                        while (qb != NULL && qb->get_bplayer() != myName && qb->get_wplayer() != myName)
                        {
                              qb = boardlist->next();
                        }

                        if (qb)
                              game_id = qb->get_id();
                        else
                        {
                              qWarning("*** You are not playing a game to be adjourned!");
                              return false;
                        }
                  }
                  else
                        game_id = g->nr.toInt();

                  if (g->Sz == QString("@") || g->Sz == QString("@@"))
                  {
                        // look for adjourned games
                        qGoBoard *qb = boardlist->first();
                        while (qb != NULL)
                        {
                              if (qb->get_adj() && qb->get_id() == 10000 &&
                                  qb->get_bplayer() == g->bname &&
                                  qb->get_wplayer() == g->wname)
                              {
                                    qDebug("ok, adjourned game found ...");
                                    if (g->bname != myName && g->wname != myName)
                                          // observe if I'm not playing
                                          emit signal_sendcommand("observe " + g->nr, false);
                                    else
                                          // ensure that my game is correct stated
                                          emit signal_sendcommand("games " + g->nr, false);
                                    qb->set_sentmovescmd(true);
                                    qb->set_id(g->nr.toInt());
                                    qb->setGameData();
                                    qb->setMode();
                                    qb->set_adj(false);
                                    qb->get_win()->getInterfaceHandler()->toggleMode();
                                    qb->set_runTimer();
                                    qb->set_sentmovescmd(true);
                                    emit signal_sendcommand("moves " + g->nr, false);
                                    emit signal_sendcommand("all " + g->nr, false);

                                    qb->send_kibitz(tr("Game continued as Game number %1").arg(g->nr));
                                    // show new game number;
                                    qb->get_win()->getBoard()->updateCaption();

                                    // renew refresh button
                                    qb->get_win()->getInterfaceHandler()->refreshButton->setText(QObject::tr("Refresh", "button label"));

                                    // increase number of observed games
                                    emit signal_addToObservationList(-2);

                                    return true;
                              }

                              qb = boardlist->next();
                        }
                  }

                  // special case: your own game
                  if (g->Sz == QString("@@"))// || g->bname == myName || g->wname == myName)
                  {
                        // set up new game
                        if (g->bname == g->wname)
                              // teaching game
                              src = 14;
                        else
                              // match
                              src = 13;
                  }
                  break;

            // game to observe
            case 2:
                  game_id = txt.toInt();
                  break;

            // match
            case 3:
                  game_id = txt.toInt();
                  break;

            // teaching game
            case 4: game_id = txt.toInt();
                  break;

            // computer game
            case 6: game_id = ++localBoardCounter; //txt.toInt();
                  qDebug(QString("computer game no. %1").arg(game_id));
                  break;      

            // remove all boards! -> if connection is closed
            // but: set options for local actions
            case -1:
                  qgobrd = boardlist->first();
                  while (qgobrd)
                  {
                        // modeNormal;
                        qgobrd->set_stopTimer();
                        // enable Menus
//                      qgobrd->get_win()->setOnlineMenu(false);

                        // set board editable...
                        qgobrd->set_Mode(1);
                        // toggle score 2x
                        qgobrd->get_win()->getInterfaceHandler()->toggleMode();
                        qgobrd->get_win()->getInterfaceHandler()->toggleMode();

                        boardlist->remove();
                        qgobrd = boardlist->current();
                  }

                  // set number of observed games to 0
                  emit signal_addToObservationList(0);
                  return false;
                  break;

            default:
                  qWarning("*** qGoIF::parse_move(): unknown case !!! ***");
                  return false;
                  break;
      }

#ifdef SHOW_MOVES_DLG
      // dialog recently used?
      if (!dlg)
      {
            dlg = new Talk("SPIEL", parent, true);
            connect(dlg->get_dialog(), SIGNAL(signal_talkto(QString&, QString&)), parent, SLOT(slot_talkto(QString&, QString&)));

            CHECK_PTR(dlg);
            dlg->write("New Dialog created\n");
      }
#endif

      // board recently used?
      if (!qgobrd || qgobrd->get_id() != game_id)
      {
            // seek dialog
            qgobrd = boardlist->first();
            while (qgobrd != NULL && qgobrd->get_id() != game_id)
                  qgobrd = boardlist->next();
            
            // not found -> create new dialog
            if (!qgobrd)
            {
                  // setup only with mouseclick or automatic in case of matching !!!!
                  // added case 0: 'observe' cmd
                  if (src < 2) //(src == 1) //
                  {
                        return false;
                  }

                  boardlist->append(new qGoBoard(this, qgo));
                  qgobrd = boardlist->current();
//                qgobrd->get_win()->setOnlineMenu(true);

                  CHECK_PTR(qgobrd);

                  // connect with board (MainWindow::CloseEvent())
                  connect(qgobrd->get_win(),
                        SIGNAL(signal_closeevent()),
                        qgobrd,
                        SLOT(slot_closeevent()));
                  // connect with board (qGoBoard)
/*                connect(qgobrd,
                        SIGNAL(signal_closeevent(int)),
                        this,
                        SLOT(slot_closeevent(int)));
*/
                  //  board -> to kibitz or say
                  connect(qgobrd->get_win()->getBoard(),
                        SIGNAL(signal_sendcomment(const QString&)),
                        qgobrd,
                        SLOT(slot_sendcomment(const QString&)));
                  // board -> stones
                  connect(qgobrd->get_win()->getBoard(),
                        SIGNAL(signal_addStone(enum StoneColor, int, int)),
                        qgobrd,
                        SLOT(slot_addStone(enum StoneColor, int, int)));
                  // board-> stones (computer game)
                  connect(qgobrd->get_win()->getBoard(),
                        SIGNAL(signal_Stone_Computer(enum StoneColor, int, int)),
                        qgobrd,
                        SLOT(slot_stoneComputer(enum StoneColor, int, int)));

                  connect(qgobrd,
                        SIGNAL(signal_2passes(const QString&,const QString& )),
                        this,
                        SLOT(slot_removestones(const QString&, const QString&)));
            
                  connect(qgobrd,
                        SIGNAL(signal_sendcommand(const QString&, bool)),
                        this,
                        SLOT(slot_sendcommand(const QString&, bool)));
                  // board -> commands
                  connect(qgobrd->get_win()->getBoard(),
                        SIGNAL(signal_pass()),
                        qgobrd,
                        SLOT(slot_doPass()));
/*                connect(qgobrd->get_win()->get_fileClose(),
                        SIGNAL(activated()),
                        qgobrd,
                        SLOT(slot_doAdjourn()));
                  connect(qgobrd->get_win()->get_fileQuit(),
                        SIGNAL(activated()),
                        qgobrd,
                        SLOT(slot_doAdjourn())); */
                  connect(qgobrd->get_win()->getBoard(),
                        SIGNAL(signal_adjourn()),
                        qgobrd,
                        SLOT(slot_doAdjourn()));
                  connect(qgobrd->get_win()->getBoard(),
                        SIGNAL(signal_undo()),
                        qgobrd,
                        SLOT(slot_doUndo()));
                  connect(qgobrd->get_win()->getBoard(),
                        SIGNAL(signal_resign()),
                        qgobrd,
                        SLOT(slot_doResign()));
                  connect(qgobrd->get_win()->getBoard(),
                        SIGNAL(signal_done()),
                        qgobrd,
                        SLOT(slot_doDone()));
                  connect(qgobrd->get_win()->getBoard(),
                        SIGNAL(signal_refresh()),
                        qgobrd,
                        SLOT(slot_doRefresh()));
                  connect(qgobrd->get_win()->getBoard(),
                        SIGNAL(signal_editBoardInNewWindow()),
                        qgobrd->get_win(),
                        SLOT(slot_editBoardInNewWindow()));
                  // teach tools
                  connect(qgobrd->get_win()->getMainWidget()->cb_opponent,
                        SIGNAL(activated(const QString&)),
                        qgobrd,
                        SLOT(slot_ttOpponentSelected(const QString&)));
                  connect(qgobrd->get_win()->getMainWidget()->pb_controls,
                        SIGNAL(toggled(bool)),
                        qgobrd,
                        SLOT(slot_ttControls(bool)));
                  connect(qgobrd->get_win()->getMainWidget()->pb_mark,
                        SIGNAL(toggled(bool)),
                        qgobrd,
                        SLOT(slot_ttMark(bool)));

                  // for own games send "games" cmd to get full info
                  if (src == 3 || src == 4 || src == 13 || src == 14)
                  {
                        connect(qgobrd->get_win()->getInterfaceHandler()->normalTools->pb_timeBlack,
                              SIGNAL(clicked()),
                              qgobrd,
                              SLOT(slot_addtimePauseB()));
                        connect(qgobrd->get_win()->getInterfaceHandler()->normalTools->pb_timeWhite,
                              SIGNAL(clicked()),
                              qgobrd,
                              SLOT(slot_addtimePauseW()));

                        if (src == 13 || src == 14)// || src== 0)
                        {
                              // src changed from 1 to 3/4
                              qgobrd->set_sentmovescmd(true);
                              emit signal_sendcommand("games " + g->nr, false);
                              emit signal_sendcommand("moves " + g->nr, false);
                              emit signal_sendcommand("all " + g->nr, false);

                              if (src == 13)
                                    src = 3;
                              else
                                    src = 4;
                        }
                        else
                              emit signal_sendcommand("games " + txt, false);

                        if (src == 4)
                        {
                              // make teaching features visible
                              qgobrd->get_win()->getMainWidget()->cb_opponent->setEnabled(true);
                              qgobrd->get_win()->getMainWidget()->pb_controls->setDisabled(true);
                              qgobrd->get_win()->getMainWidget()->pb_mark->setEnabled(true);
                              qgobrd->ExtendedTeachingGame = true;
                              qgobrd->IamTeacher = true;
                              qgobrd->havePupil = false;
                              qgobrd->mark_set = false;
                        }
                  }

                  // set correct mode in qGo
                  qgobrd->set_id(game_id);
                  qgobrd->set_gsName(gsName);
                  qgobrd->set_myName(myName);
                  if ((game_id == 0) && (src != 6)) //SL added eb 12
                        // set local board
                        qgobrd->set_Mode(5);
                  //else if (src==0)
                  //    qgobrd->set_Mode(2); // special case when not triggered by the 'observe' command (trail, for instance)
                  else
                        qgobrd->set_Mode(src);

                  // increase number of observed games
                  emit signal_addToObservationList(-2);

                  return true;
            }
      }

      switch (src)
      {
            // regular move info (parser)
            case 0:
#ifdef SHOW_MOVES_DLG
                  dlg->write("Spiel " + gi->nr + gi->type + "\n");
#endif

                  if (gi->mv_col == "T")
                  {
#ifdef SHOW_MOVES_DLG
                        dlg->write("W: " + gi->wname + " " + gi->wprisoners + " " + gi->wtime + " " + gi->wstones + "\n");
                        dlg->write("B: " + gi->bname + " " + gi->bprisoners + " " + gi->btime + " " + gi->bstones + "\n");
#endif

                        // set times
                        qgobrd->setTimerInfo(gi->btime, gi->bstones, gi->wtime, gi->wstones);
                  }
                  else if (gi->mv_col == "B" || gi->mv_col == "W")
                  {
#ifdef SHOW_MOVES_DLG
                        dlg->write(gi->mv_col + " " + gi->mv_nr + " " + gi->mv_pt + "\n");
#endif

                        // set move if game is initialized
                        if (qgobrd->get_havegd())
                        {
                              // get all moves till now one times if kibitzing
                              if (qgobrd->get_Mode() == modeObserve && !qgobrd->get_sentmovescmd())
                              {
                                    qgobrd->set_sentmovescmd(true);
                                    emit signal_sendcommand("moves " + gi->nr, false);
                                    emit signal_sendcommand("all " + gi->nr, false);
                              }
                              else
                              {
                                    // do normal move
                                    qgobrd->set_move(sc, pt, mv_nr);
                              }
                        }
                  }

                  break;
                        
            // adjourn/end/resume of a game (parser)
            case 1:
#ifdef SHOW_MOVES_DLG
                  dlg->write("Spiel " + g->nr + (g->running ? " running\n" : " STOPPED\n"));
                  dlg->write(g->Sz + "\n");
#endif

                  if (!g->running)
                  {
                        // stopped game do not need a timer
                        qgobrd->set_stopTimer();

                        ASSERT(g->Sz);

                        if (g->Sz == "-")
                        {
                              return false;
                        }
                        
                        /*
                        if (g->Sz.contains("adjourned"))
                              qgobrd->send_kibitz(tr("Game has adjourned"));
                        else if (g->Sz.contains("White forfeits"))
                              qgobrd->send_kibitz(tr("White forfeits on time"));
                        else if (g->Sz.contains("Black forfeits"))
                              qgobrd->send_kibitz(tr("Black forfeits on time"));
                        else if (g->Sz.contains("White resigns"))
                              qgobrd->send_kibitz(tr("White resigns"));
                        else if (g->Sz.contains("Black resigns"))
                              qgobrd->send_kibitz(tr("Black resigns"));
                        else */
                              qgobrd->send_kibitz(g->Sz);

                        // set correct result entry
                        QString rs = QString();
                        if (g->Sz.contains("White forfeits"))
                              rs = "B+T";
                        else if (g->Sz.contains("Black forfeits"))
                              rs = "W+T";
                        else if (g->Sz.contains("has run out of time"))
                               rs = ((( g->Sz.contains(myName) && qgobrd->get_myColorIsBlack() ) ||
                                    ( !g->Sz.contains(myName) && !qgobrd->get_myColorIsBlack() )) ?
                                    "W+T" : "B+T");

                        else if (g->Sz.contains("W ", true) && g->Sz.contains("B ", true))
                        {
                              // NNGS: White resigns. W 59.5 B 66.0
                              // IGS: W 62.5 B 93.0
                              // calculate result first
                              int posw, posb;
                              float re1, re2;
                              posw = g->Sz.find("W ");
                              posb = g->Sz.find("B ");
                              bool wfirst = posw < posb;

                              if (!wfirst)
                              {
                                    int h = posw;
                                    posw = posb;
                                    posb = h;
                              }

                              QString t1 = g->Sz.mid(posw+1, posb-posw-2);
                              QString t2 = g->Sz.right(g->Sz.length()-posb-1);
                              re1 = t1.toFloat();
                              re2 = t2.toFloat();

                              re1 = re2-re1;
                              if (re1 < 0)
                              {
                                    re1 = -re1;
                                    wfirst = !wfirst;
                              }
                              
                              if (re1 < 0.2)
                                    rs = "Jigo";
                              else if (wfirst)
                                    rs = "B+" + QString::number(re1);
                              else
                                    rs = "W+" + QString::number(re1);
                        }
                        else if (g->Sz.contains("White resigns"))
                              rs = "B+R";
                        else if (g->Sz.contains("Black resigns"))
                              rs = "W+R";
                        else if (g->Sz.contains("has resigned the game"))
                               rs = ((( g->Sz.contains(myName) && qgobrd->get_myColorIsBlack() ) ||
                                    ( !g->Sz.contains(myName) && !qgobrd->get_myColorIsBlack() )) ?
                                    "W+R" : "B+R");
                        if (rs)
                        {
                              qgobrd->get_win()->getBoard()->getGameData()->result = rs;
                              qgobrd->send_kibitz(rs);
                              qDebug("Result: " + rs);
                        }

                        if (g->Sz.contains("adjourned") && qgobrd->get_bplayer() && qgobrd->get_wplayer())
                        {
                              if (qgobrd->get_bplayer() == myName || qgobrd->get_wplayer() == myName)
                                    // can only reload own games
                                    qgobrd->get_win()->getInterfaceHandler()->refreshButton->setText(tr("LOAD"));
                              qDebug("game adjourned... #" + QString::number(qgobrd->get_id()));
                              qgobrd->set_adj(true);
                              qgobrd->set_id(10000);
                              qgobrd->clearObserverList();
                              qgo->playGameEndSound();
                        }
                        else
                        {
                              // case: error -> game has not correctly been removed from list
                              GameMode owngame = qgobrd->get_Mode();
                              // game ended - if new game started with same number -> prohibit access
                              qgobrd->set_id(-qgobrd->get_id());

                              // enable Menus
//                            qgobrd->get_win()->setOnlineMenu(false);

                              // set board editable...
                              qgobrd->set_Mode(1);
                              // toggle score 2x
                              qgobrd->get_win()->getInterfaceHandler()->toggleMode();
                              qgobrd->get_win()->getInterfaceHandler()->toggleMode();

                              //autosave ?
                              //if ((setting->readBoolEntry("AUTOSAVE")) && (owngame == modeObserve)) 
                              //{
                              //    qgobrd->get_win()->doSave(qgobrd->get_win()->getBoard()->getCandidateFileName(),true);
                              //    qDebug("Game saved");
                              //}

                              // but allow to use "say" cmd if it was an own game
                              //if (owngame == modeMatch)
                              bool doSave = ((setting->readBoolEntry("AUTOSAVE")) && (owngame == modeObserve)) ||
                                          ((setting->readBoolEntry("AUTOSAVE_PLAYED")) && (owngame == modeMatch)); 
                              wrapupMatchGame(qgobrd, doSave);
                              //else
                              //    qgo->playGameEndSound();

                              /*{
                                          // allow 'say' command
                                    qgobrd->get_win()->getInterfaceHandler()->commentEdit2->setReadOnly(false);
                                    qgobrd->get_win()->getInterfaceHandler()->commentEdit2->setDisabled(false);
                              }*/
                        }

                        // decrease number of observed games
                        emit signal_addToObservationList(-1);
                  }
                  else if (!qgobrd->get_havegd())
                  {
                        // check if it's my own game
                        if (g->bname == myName || g->wname == myName)
                        {
                              // case: trying to observe own game: this is the way to get back to match if
                              // board has been closed by mistake
                              if (g->bname == g->wname)
                                    // teach
                                    qgobrd->set_Mode(4);
                              else
                                    // match
                                    qgobrd->set_Mode(3);
                        }
                        else if (g->bname == g->wname && !g->bname.contains('*'))
                        {
                              // case: observing a teaching game
                              // make teaching features visible while observing
                              qgobrd->get_win()->getMainWidget()->cb_opponent->setDisabled(true);
                              qgobrd->get_win()->getMainWidget()->pb_controls->setDisabled(true);
                              qgobrd->get_win()->getMainWidget()->pb_mark->setDisabled(true);
                              qgobrd->ExtendedTeachingGame = true;
                              qgobrd->IamTeacher = false;
                              qgobrd->IamPupil = false;
                              qgobrd->havePupil = false;
                        }
                        qgobrd->set_game(g);

                        if (qgobrd->get_Mode() == modeMatch)
                        {
                              if (g->bname == myName)
                              {
                                    qgobrd->get_win()->getBoard()->set_myColorIsBlack(true);
                                    qgobrd->set_myColorIsBlack(true);

                                    // I'm black, so check before the first move if komi, handi, free is correct
                                    if (qgobrd->get_requests_set())
                                    {
                                          qDebug("qGoIF::parse_move() : check_requests");
                                          qgobrd->check_requests();
                                    }
                              }
                              else if (g->wname == myName)
                              {
                                    qgobrd->get_win()->getBoard()->set_myColorIsBlack(false);
                                    qgobrd->set_myColorIsBlack(false);
                              }
                              else
                                    qWarning("*** Wanted to set up game without knowing my color ***");
                        }
                  }
                  break;

#ifdef SHOW_MOVES_DLG
            // game to observe (mouse click)
            case 2:
                  dlg->write("Observe: " + txt + "\n");
                  break;

            // game to play (mouse click and match prompt)
            case 3:
                  dlg->write("Play(MATCH): " + txt + "\n");
                  break;

            // game to play (mouse click and match prompt)
            case 4:
                  dlg->write("Teach: " + txt + "\n");
                  break;

      
#endif
            default:
                  //qDebug("qGoInterface::parse_move() - illegal parameter");
                  break;
      }

      // assume no new window
      return false;
}


// regular move info (parser)
void qGoIF::slot_move(GameInfo *gi)
{
      parse_move(0, gi);
}

// start/adjourn/end/resume of a game (parser)
void qGoIF::slot_move(Game *g)
{
      parse_move(1, 0, g);
}

void qGoIF::slot_computer_game(QNewGameDlg * dlg)
{
      Game  g;

      //    g.nr = lv_popupGames->text(0);

      g.wname = dlg->getPlayerWhiteName();
      //    g.wrank = lv_popupGames->text(2);
      g.bname = dlg->getPlayerBlackName();
      //    g.brank = lv_popupGames->text(4);
      g.mv = "0";
      g.Sz.setNum(dlg->getSize()); 
      g.H.setNum(dlg->getHandicap());
      g.K.setNum(dlg->getKomi());
      //g.By = lv_popupGames->text(9);
      //g.FR = lv_popupGames->text(10);
      //g.ob = lv_popupGames->text(11);
      g.running = true;
      g.oneColorGo = dlg->getOneColorGo();


      if ((dlg->getPlayerWhiteType()==HUMAN)&&
            (dlg->getPlayerBlackType()==HUMAN))
      {
            QMessageBox::warning(this->get_parent(), PACKAGE, tr("*** Both players are Human ! ***"));
            return ;
      }

      parse_move(6, 0, &g);
      qgobrd->set_game(&g);
      qgobrd->set_stopTimer();
      
      /*
      * This is creepy ...
      * for some reason, the function 2 lines below zeroes the 'qgobrd' pointer
      * This happens when connected to IGS. Hours of trace did not deliver a clue
      * So we make it dirty : we store the pointer
      */
      
      qGoBoard *qb = qgobrd;
      
      if (!qgobrd->get_win()->startComputerPlay(dlg,dlg->fileName, qgobrd->get_win()->getFileExtension(dlg->fileName),setting->readEntry("COMPUTER_PATH")))
      {
            // computer program failed -> end game
            slot_closeevent();
            return ;
      }

      /*************************************************** 
      *     OK, we reset the pointer
      ****************************************************/
      qgobrd=qb;
      
      // if we have loaded a game, we have to overwrite the game settings
      if (!(dlg->fileName.isNull() || dlg->fileName.isEmpty()))
      {
            qgobrd->gd.size = qgobrd->get_win()->getBoard()->getGameData()->size;
            qgobrd->gd.handicap = qgobrd->get_win()->getBoard()->getGameData()->handicap;
            qgobrd->gd.playerWhite =qgobrd->get_win()->getBoard()->getGameData()->playerWhite;
            qgobrd->gd.playerBlack =qgobrd->get_win()->getBoard()->getGameData()->playerBlack;
      }
      //qgobrd->set_game(&g);
      
            
      qgobrd->get_win()->getBoard()->set_myColorIsBlack((qgobrd->get_win()->blackPlayerType==HUMAN));
      qgobrd->set_myColorIsBlack((qgobrd->get_win()->blackPlayerType==HUMAN));

      if (qgobrd->get_win()->getBoard()->get_myColorIsBlack() != qgobrd->get_win()->getBoard()->getBoardHandler()->getBlackTurn())
            qgobrd->playComputer(qgobrd->get_win()->getBoard()->getBoardHandler()->getBlackTurn() ? stoneWhite : stoneBlack);
}

// game to observe (mouse click)
bool qGoIF::set_observe(QString gameno)
{
      return parse_move(2, 0, 0, gameno);
}

// remove all boards
void qGoIF::set_initIF()
{
      parse_move(-1);
}

// a match is created
void qGoIF::slot_matchcreate(const QString &gameno, const QString &opponent)
{
      if (opponent == myName)
            // teaching game
            parse_move(4, 0, 0, gameno);
      else
            parse_move(3, 0, 0, gameno);
}

void qGoIF::slot_matchsettings(const QString &id, const QString &handicap, const QString &komi, assessType kt)
{
      // seek board
      qGoBoard *qb = boardlist->first();
      while (qb && qb->get_id() != id.toInt())
            qb = boardlist->next();

      if (!qb)
      {
            qWarning("BOARD CORRESPONDING TO GAME SETTINGS NOT FOUND !!!");
            return;
      }

      qb->set_requests(handicap, komi, kt);
      qDebug(QString("qGoIF::slot_matchsettings: h=%1, k=%2, kt=%3").arg(handicap).arg(komi).arg(kt));
}

void qGoIF::slot_title(const QString &title)
{
      // title message follows to move message -> not reliable
      // only teaching games can have a title

      // seek board
      int found = 0;
      qGoBoard *qb_save = 0;
      qGoBoard *qb = boardlist->first();
      while (qb)
      {
            if (//!qb->get_haveTitle() &&
                  (qb->get_wplayer() == qb->get_bplayer() ||
                   qb->get_gameData().freegame == TEACHING))
            {
                  qb_save = qb;
                  found++;
            }
            qb = boardlist->next();
      }

      // set title if only one teaching game (with or without title) found
      if (found == 1 && qb_save)
            qb_save->set_title(title);
}

// komi set or requested
void qGoIF::slot_komi(const QString &nr, const QString &komi, bool isrequest)
{
      qGoBoard *qb;
      static int move_number_memo = -1;
      static QString komi_memo = NULL;

      // correctness:
      if (!komi)
            return;

      if (isrequest)
      {
            // check if opponent is me
            if (!nr || nr == myName)
                  return;

            // 'nr' is opponent (IGS/NNGS)
            qb = boardlist->first();
            while (qb != NULL && qb->get_wplayer() != nr && qb->get_bplayer() != nr)
                  qb = boardlist->next();

            if (qb)
            {
                  // check if same opponent twice (IGS problem...)
                  if (move_number_memo == qb->get_mv_counter() && komi_memo  && komi_memo == komi)
                  {
                        qDebug(QString("...request skipped: opponent %1 wants komi %2").arg(nr).arg(komi));
                        return;
                  }

                  // remember of actual values
                  move_number_memo = qb->get_mv_counter();
                  komi_memo = komi;

                  if (qb->get_reqKomi() == komi  && setting->readBoolEntry("DEFAULT_AUTONEGO"))
                  {
                        if (qb->get_currentKomi() != komi)
                        {
                              qDebug("GoIF::slot_komi() : emit komi");
                              emit signal_sendcommand("komi " + komi, true);
                        }
                  }
                  else
                  {
                        slot_requestDialog(tr("komi ") + komi, tr("decline"), QString::number(qb->get_id()), nr);
                  }
            }

            return;
      }
      // own game if nr == NULL
      else if (!nr)
      {
            if (!myName)
            {
                  // own name not set -> should never happen!
                  qWarning("*** Wrong komi because don't know which online name I have ***");
                  return;
            }

            qb = boardlist->first();
            while (qb != NULL && qb->get_wplayer() != myName && qb->get_bplayer() != myName)
                  qb = boardlist->next();
      }
      else
      {
            // title message follows to move message
            qb = boardlist->first();
            while (qb != NULL && qb->get_id() != nr.toInt())
                  qb = boardlist->next();
      }

      if (qb)
            qb->set_komi(komi);
}

// game free/unfree message received
void qGoIF::slot_freegame(bool freegame)
{
      qGoBoard *qb;

      qb = boardlist->first();
      // what if 2 games (IGS) and mv_counter < 3 in each game? -> problem
      while (qb != NULL && qb->get_wplayer() != myName && qb->get_bplayer() != myName && qb->get_mvcount() < 3)
            qb = boardlist->next();

      if (qb)
            qb->set_freegame(freegame);
}

// board window closed...
void qGoIF::slot_closeevent()
{
      int id = 0;
      qGoBoard *qb;

      // erase actual pointer to prevent error
      qgobrd = 0;

      // seek board
      qb = boardlist->first();
      while (qb && (id = qb->get_id()) > 0)
            qb = boardlist->next();

      if (!qb)
      {
            qWarning("CLOSED BOARD NOT FOUND IN LIST !!!");
            return;
      }

      qDebug(QString("qGoIF::slot_closeevent() -> game %1").arg(qb->get_id()));

      // destroy timers
      qb->set_stopTimer();

      if (id < 0 && id > -10000)
      {
            switch (qb->get_Mode())
            {
                  case modeObserve:
                        // unobserve
                        emit signal_sendcommand("observe " + QString::number(-id), false);

                        // decrease number of observed games
                        emit signal_addToObservationList(-1);
                        break;

                  case modeMatch:

                        // decrease number of observed games
                        emit signal_addToObservationList(-1);
                        break;

                  case modeTeach:
                        emit signal_sendcommand("adjourn", false);

                        // decrease number of observed games
                        emit signal_addToObservationList(-1);
                        break;

                  default:
                        break;
            }
      }

//    MainWindow *win = qb->get_win();
//    qgo->removeBoardWindow(win);
      boardlist->remove();

      delete qb;
//    delete win;
}

// kibitz strings
void qGoIF::slot_kibitz(int num, const QString& who, const QString& msg)
{
      qGoBoard *qb;
      QString name;

      // own game if num == NULL
      if (!num)
      {
            if (!myName)
            {
                  // own name not set -> should never happen!
                  qWarning("*** qGoIF::slot_kibitz(): Don't know my online name ***");
                  return;
            }

            qb = boardlist->first();
            while (qb != NULL && qb->get_wplayer() != myName && qb->get_bplayer() != myName)
                  qb = boardlist->next();

            if (qb && qb->get_wplayer() == myName)
                  name = qb->get_bplayer();
            else if (qb)
                  name = qb->get_wplayer();

            if (qb)
                  // sound for "say" command
                  qgo->playSaySound();
      }
      else
      {
            // seek board to send kibitz
            qb = boardlist->first();
            while (qb && qb->get_id() != num)
                  qb = boardlist->next();

            name = who;
      }

      if (!qb)
            qDebug("Board to send kibitz string not in list...");
      else if (!num && who)
      {
            // special case: opponent has resigned - interesting in quiet mode
            qb->send_kibitz(msg);
            //qgo->playGameEndSound();
            wrapupMatchGame(qb, true);
      }
      else
            qb->send_kibitz(name + ": " + msg);
}

void qGoIF::slot_requestDialog(const QString &yes, const QString &no, const QString & /*id*/, const QString &opponent)
{
      QString opp;
      if (opponent)
            opp = opponent;
      else
            opp = tr("Opponent");

      if (!no)
      {
            QMessageBox mb(tr("Request of Opponent"),
                  QString(tr("%1 wants to %2\nYES = %3\nCANCEL = %4")).arg(opp).arg(yes).arg(yes).arg(tr("ignore request")),
                  QMessageBox::NoIcon,
                  QMessageBox::Yes | QMessageBox::Default,
                  QMessageBox::Cancel | QMessageBox::Escape,
                  QMessageBox::NoButton);
            mb.setActiveWindow();
            mb.raise();
            qgo->playPassSound();

            if (mb.exec() == QMessageBox::Yes)
            {
                  qDebug(QString(QString("qGoIF::slot_requestDialog(): emit %1").arg(yes)));
                  emit signal_sendcommand(yes, false);
            }
      }
      else
      {
            QMessageBox mb(tr("Request of Opponent"),
                  QString(tr("%1 wants to %2\nYES = %3\nCANCEL = %4")).arg(opp).arg(yes).arg(yes).arg(no),
                  QMessageBox::NoIcon,
                  QMessageBox::Yes | QMessageBox::Default,
                  QMessageBox::No | QMessageBox::Escape,
                  QMessageBox::NoButton);
            mb.setActiveWindow();
            mb.raise();
            qgo->playPassSound();

            if (mb.exec() == QMessageBox::Yes)
            {
                  qDebug(QString(QString("qGoIF::slot_requestDialog(): emit %1").arg(yes)));
                  emit signal_sendcommand(yes, false);
            }
            else
            {
                  qDebug(QString(QString("qGoIF::slot_requestDialog(): emit %1").arg(no)));
                  emit signal_sendcommand(no, false);
            }
      }
}

void qGoIF::slot_sendcommand(const QString &text, bool show)
{
      emit signal_sendcommand(text, show);
}

void qGoIF::slot_removestones(const QString &pt, const QString &game_id)
{
      qGoBoard *qb = boardlist->first();

      if (!pt && !game_id)
      {
qDebug("slot_removestones(): !pt !game_id");
            // search game
            qb = boardlist->first();
            while (qb && (qb->get_Mode() != modeMatch) && (qb->get_Mode() != modeComputer))
                  qb = boardlist->next();
            
            if (!qb)
            {
                  qWarning("*** No Match found !!! ***");
                  return;
            }

            switch (gsName)
            {
                  case IGS:
                        // no parameter -> restore counting
                        if (qb->get_win()->getInterfaceHandler()->passButton->text() == QString(tr("Done")))
                        {
qDebug("slot_removestones(): IGS restore counting");
                              // undo has done -> reset counting
                              qb->get_win()->doRealScore(false);
                              qb->get_win()->getBoard()->setMode(modeMatch);
                              qb->get_win()->getBoard()->previousMove();
                              qb->dec_mv_counter();
                              qb->get_win()->doRealScore(true);
                              qb->send_kibitz(tr("SCORE MODE: RESET - click on a stone to mark as dead..."));
                        }
                        else if (qb->get_Mode() == modeMatch)
                        {
qDebug("slot_removestones(): IGS score mode");
                              // set to count mode
                              qb->get_win()->doRealScore(true);
                              qb->send_kibitz(tr("SCORE MODE: click on a stone to mark as dead..."));
                        }
                        break;

                  default:
                        if ((qb->get_Mode() == modeMatch) || (qb->get_Mode() == modeComputer))
                        {
qDebug("slot_removestones(): NON IGS counting");
                              // set to count mode
                              qb->get_win()->doRealScore(true);
                              qb->send_kibitz(tr("SCORE MODE: click on a stone to mark as dead..."));
                        }
                        else
                        {
qWarning("slot_removestones(): NON IGS no match");
                              // back to matchMode
                              qb->get_win()->doRealScore(false);
                              qb->get_win()->getBoard()->setMode(modeMatch);
                              qb->get_win()->getBoard()->previousMove();
                              qb->dec_mv_counter();
                              qb->send_kibitz(tr("GAME MODE: place stones..."));
                        }
                        break;
            }

            return;
      }

      if (pt && !game_id)
      {
qDebug("slot_removestones(): pt !game_id");
            // stone coords but no game number:
            // single match mode, e.g. NNGS
            while (qb && qb->get_Mode() != modeMatch && qb->get_Mode() != modeTeach)
                  qb = boardlist->next();
      }
      else
      {
qDebug("slot_removestones(): game_id");
            // multi match mode, e.g. IGS
            while (qb && qb->get_id() != game_id.toInt())
                  qb = boardlist->next();

            if (qb && qb->get_win()->getInterfaceHandler()->passButton->text() != QString(tr("Done")))
            {
                  // set to count mode
                  qb->get_win()->doRealScore(true);
                  qb->send_kibitz(tr("SCORE MODE: click on a stone to mark as dead..."));
            }
      }
            
      if (!qb)
      {
            qWarning("*** No Match found !!! ***");
            return;
      }

      int i = (QChar) pt[0] - 'A' + 1;
      // skip j
      if (i > 8)
            i--;
      
      int j;
      if (pt[2] >= '0' && pt[2] <= '9')
            j = qb->get_boardsize() + 1 - pt.mid(1,2).toInt();
      else
            j = qb->get_boardsize() + 1 - pt[1].digitValue();

      // mark dead stone
      qb->get_win()->getBoard()->getBoardHandler()->markDeadStone(i, j);
      qb->send_kibitz("removing @ " + pt);
}

// game status received
void qGoIF::slot_result(const QString &txt, const QString &line, bool isplayer, 
const QString &komi)
{
      static qGoBoard *qb;
      static float wcount, bcount;
      static int column;

      if (isplayer)
      {
            qb = boardlist->first();
            // find right board - slow, but just once a game
            while (qb != NULL && qb->get_wplayer() != txt && qb->get_bplayer() != txt)
                  qb = boardlist->next();

            if (qb && qb->get_wplayer() == txt)
            {
                  // prisoners white + komi
                  wcount = line.toFloat() + komi.toFloat();
            }
            else if (qb && qb->get_bplayer() == txt)
            {
                  // prisoners black
                  bcount = line.toFloat();
                  // ok, start counting column
                  column = 0;
            }
      }
      else if (qb)
      {
            // ok, now mark territory points only
            // 0 .. black
            // 1 .. white
            // 2 .. free
            // 3 .. neutral
            // 4 .. white territory
            // 5 .. black territory

            // one line at a time
            column++;
            int i;
            for (i = 0; i < (int) line.length(); i++)
            {
                  switch(line[i].digitValue())
                  {
                        case 4:
                              // add white territory
                              wcount++;
                              qb->get_win()->getBoard()->setMark(column, i+1, markTerrWhite, true);
                              break;

                        case 5:
                              // add black territory
                              bcount++;
                              qb->get_win()->getBoard()->setMark(column, i+1, markTerrBlack, true);
                              break;

                        default:
                              break;
                  }
            }
            // send kibitz string after counting
            if (txt.toInt() == (int) line.length() - 1)
                  /*send_kibitz*/ qDebug(tr("Game Status: W:") + QString::number(wcount) + " " + tr("B:") + QString::number(bcount));

            // show territory
            qb->get_win()->getBoard()->updateCanvas();
      }
}

// undo a move
void qGoIF::slot_undo(const QString &player, const QString &move)
{
      qDebug("qGoIF::slot_undo()");
      qGoBoard *qb = boardlist->first();

      // check if game number given
      bool ok;
      int nr = player.toInt(&ok);
      if (ok)
            while (qb != NULL && qb->get_id() != nr)
                  qb = boardlist->next();
      else
            while (qb != NULL && qb->get_wplayer() != player && qb->get_bplayer() != player)
                  qb = boardlist->next();

      if (!qb)
      {
            qWarning("*** board for undo not found!");
            return;
      }

      if (move != "Pass")
      {
            // only the last '0' is necessary
            qb->set_move(stoneNone, 0, 0);
            return;
      }

      // back to matchMode
      qb->get_win()->doRealScore(false);
      qb->get_win()->getBoard()->setMode(modeMatch);
      qb->get_win()->getBoard()->previousMove();
      qb->dec_mv_counter();
      qb->send_kibitz(tr("GAME MODE: place stones..."));
}

// set independent local board
void qGoIF::set_localboard(QString file)
{
      qGoBoard *qb = new qGoBoard(this, qgo);
      qb->set_id(0);
      // normal mode
      qb->set_Mode(1);
      if (file == "/19/")
      {
            qb->set_komi("5.5");
            // special case - set up 19x19 board without any questions
      }
      else if (file)
            qb->get_win()->doOpen(file, 0, false);
      else
            qb->get_win()->slotFileNewGame();
//    qb->get_win()->setOnlineMenu(false);
      qb->get_win()->getInterfaceHandler()->toggleMode();
      qb->get_win()->getInterfaceHandler()->toggleMode();

      boardlist->append(qb);
      qb->set_id(++localBoardCounter);

      // connect with board (MainWindow::CloseEvent())
      connect(qb->get_win(),
            SIGNAL(signal_closeevent()),
            qb,
            SLOT(slot_closeevent()));
      // connect with board (qGoBoard)
/*    connect(qb,
            SIGNAL(signal_closeevent(int)),
            this,
            SLOT(slot_closeevent(int)));*/
}

// set independent local board + open game
void qGoIF::set_localgame()
{
      qGoBoard *qb = new qGoBoard(this, qgo);
      qb->set_id(0);
      // normal mode
      qb->set_Mode(1);
      qb->get_win()->slotFileOpen();
//    qb->get_win()->setOnlineMenu(false);
      qb->get_win()->getInterfaceHandler()->toggleMode();
      qb->get_win()->getInterfaceHandler()->toggleMode();

      boardlist->append(qb);
      qb->set_id(++localBoardCounter);

      // connect with board (MainWindow::CloseEvent())
      connect(qb->get_win(),
            SIGNAL(signal_closeevent()),
            qb,
            SLOT(slot_closeevent()));
      // connect with board (qGoBoard)
/*    connect(qb,
            SIGNAL(signal_closeevent(int)),
            this,
            SLOT(slot_closeevent(int)));*/
}

// direct access to preferences dialog
void qGoIF::openPreferences(int tab)
{
      MainWindow *win = new MainWindow(0, PACKAGE);

      win->setParent(this);
      win->dlgSetPreferences(tab);

      delete win;
}

// time has been added
void qGoIF::slot_timeAdded(int time, bool toMe)
{
      qGoBoard *qb = boardlist->first();
      while (qb != NULL && qb->get_Mode() != modeMatch)
            qb = boardlist->next();

      if (!qb)
      {
            qWarning("*** board for undo not found!");
            return;
      }

      // use time == -1 to pause the game
      if (time == -1)
      {
            qb->set_gamePaused(toMe);
            return;
      }

      if (toMe && qb->get_myColorIsBlack() || !toMe && !qb->get_myColorIsBlack())
            qb->addtime_b(time);
      else
            qb->addtime_w(time);
}


void qGoIF::wrapupMatchGame(qGoBoard * qgobrd, bool doSave)
{
      qgo->playGameEndSound();                        
      qgobrd->get_win()->getInterfaceHandler()->commentEdit2->setReadOnly(false);
      qgobrd->get_win()->getInterfaceHandler()->commentEdit2->setDisabled(false);
      
      //autosave ?
      if (doSave) 
      {
            qgobrd->get_win()->doSave(qgobrd->get_win()->getBoard()->getCandidateFileName(),true);
            qDebug("Game saved");
      }


}


/*
 *    qGo Board
 */



// add new board window
qGoBoard::qGoBoard(qGoIF *parent, qGo *qgo_) : QObject(), Misc<QString>()
{
      qDebug("::qGoBoard()");
      have_gameData = false;
      sent_movescmd = false;
      adjourned = false;
      gd = GameData();
      mv_counter = -1;
      requests_set = false;
      haveTitle = false;
      win = new MainWindow(0, PACKAGE);
      win->setParent(parent);

      ExtendedTeachingGame = false;
      IamTeacher = false;
      IamPupil = false;
      havePupil = false;
      haveControls = false;
      mark_set = false;

      // set timer to 1 second
      startTimer(1000);
      timer_running = true;
      game_paused = false;
      req_handicap = -1;
      req_komi = -1;
      bt_i = -1;
      wt_i = -1;
      stated_mv_count =0 ;
  BY_timer = setting->readIntEntry("BY_TIMER");

#ifdef SHOW_INTERNAL_TIME
      chk_b = -2;
      chk_w = -2;
#endif
      qgo = qgo_;
      qgo->addBoardWindow(win);

      // disable some Menu items
//    win->setOnlineMenu(true);
}

qGoBoard::~qGoBoard()
{
qDebug("~qGoBoard()");
      qgo->removeBoardWindow(win);
      // do NOT delete *win, cause MainWindow does it first!
      delete win;
}

// set game info to one board
void qGoBoard::set_game(Game *g)
{
      gd.playerBlack = g->bname;
      gd.playerWhite = g->wname;
      gd.rankBlack = g->brank;
      gd.rankWhite = g->wrank;
//    QString status = g->Sz.simplifyWhiteSpace();
      gd.size = g->Sz.toInt();
      gd.handicap = g->H.toInt();
      gd.komi = g->K.toFloat();
      gd.gameNumber = id;
      if (g->FR.contains("F"))
            gd.freegame = FREE;
      else if (g->FR.contains("T"))
            gd.freegame = TEACHING;
      else
            gd.freegame = RATED;
      if (gd.freegame != TEACHING)
      {
            gd.timeSystem = canadian;
            gd.byoTime = g->By.toInt()*60;
            gd.byoStones = 25;
            if (wt_i > 0)
                  gd.timelimit = (((wt_i > bt_i ? wt_i : bt_i) / 60) + 1) * 60;
            else
                  gd.timelimit = 60;

            if (gd.byoTime == 0)
                  // change to absolute
                  gd.timeSystem = absolute;
            else
                  gd.overtime = "25/" + QString::number(gd.byoTime) + " Canadian";
      }
      
      else
      {
            gd.timeSystem = none;
            gd.byoTime = 0;
            gd.byoStones = 0;
            gd.timelimit = 0;
      }
      gd.style = 1;
      gd.oneColorGo = g->oneColorGo ;
      
      switch (gsName)
      {
            case IGS :
                  gd.place = "IGS";
                  break ;
            case LGS :
                  gd.place = "LGS";
                  break ;
            case WING :
                  gd.place = "WING";
                  break ;
            case CWS :
                  gd.place = "CWS";
                  break;
            default :
                  ;
      }

      gd.date = QDate::currentDate().toString("dd MM yyyy") ;
      
      setMode();
      initGame();
      setMode();
      win->getInterfaceHandler()->toggleMode();
      have_gameData = true;

      // needed for correct sound
      stated_mv_count = g->mv.toInt();
      sound = false;
}

void qGoBoard::set_title(const QString &t)
{
      gd = win->getBoard()->getGameData();
      gd.gameName = t;
      win->getBoard()->setGameData(&gd);
      win->getBoard()->updateCaption();

      haveTitle = true;
}

void qGoBoard::set_komi(const QString &k)
{
      QString k_;
      // check whether the string contains two commas
      if (k.contains('.') > 1)
            k_ = k.left(k.length()-1);
      else
            k_ = k;

      qDebug(QString("set komi to %1").arg(k_));

      gd.komi = k_.toFloat();
      win->getBoard()->setGameData(&gd);
      win->getInterfaceHandler()->normalTools->komi->setText(k_);
}

void qGoBoard::set_freegame(bool f)
{
      if (f)
      {
            win->getBoard()->getInterfaceHandler()->normalTools->TextLabel_free->setText(tr("free"));
            gd.freegame = FREE;
      }
      else
      {
            win->getBoard()->getInterfaceHandler()->normalTools->TextLabel_free->setText(tr("rated"));
            gd.freegame = RATED;
      }
      win->getBoard()->setGameData(&gd);
}

// convert seconds to time string
QString qGoBoard::secToTime(int seconds)
{
      bool neg = seconds < 0;
      if (neg)
            seconds = -seconds;

      int h = seconds / 3600;
      seconds -= h*3600;
      int m = seconds / 60;
      int s = seconds - m*60;

      QString sec;

      // prevailling 0 for seconds
      if ((h || m) && s < 10)
            sec = "0" + QString::number(s);
      else
            sec = QString::number(s);

      if (h)
      {
            QString min;

            // prevailling 0 for minutes
            if (h && m < 10)
                  min = "0" + QString::number(m);
            else
                  min = QString::number(m);

            return (neg ? "-" : "") + QString::number(h) + ":" + min + ":" + sec;
      }
      else
            return (neg ? "-" : "") + QString::number(m) + ":" + sec;
}

// send regular time Info
void qGoBoard::timerEvent(QTimerEvent*)
{
      // wait until first move
      if (mv_counter < 0 || id < 0 || game_paused)
            return;

      if (mv_counter % 2)
      {
            // B's turn
            bt_i--;

#ifdef SHOW_INTERNAL_TIME
            chk_b--;
            if (chk_b < bt_i + 20)
                  chk_b = bt_i;
            win->getInterfaceHandler()->setTimes("(" + secToTime(chk_b) + ") " + secToTime(bt_i), b_stones, "(" + secToTime(chk_w) + ") " + wt, w_stones);
#else
            win->getInterfaceHandler()->setTimes(secToTime(bt_i), b_stones, wt, w_stones);
#endif
      }
      else
      {
            // W's turn
            wt_i--;

#ifdef SHOW_INTERNAL_TIME
            chk_w--;
            if (chk_w < bt_i + 20)
                  chk_w = wt_i;
            win->getInterfaceHandler()->setTimes("(" + secToTime(chk_b) + ") " + bt, b_stones, "(" + secToTime(chk_w) + ") " + secToTime(wt_i), w_stones);
#else
            win->getInterfaceHandler()->setTimes(bt, b_stones, secToTime(wt_i), w_stones);
#endif
      }

      // warn if I am within the last 10 seconds
      if (gameMode == modeMatch)
      {
            if (myColorIsBlack && bt_i <= BY_timer && bt_i > -1 && mv_counter % 2) // ||
            {
                  // each second we alternate button background color
                  if (bt_i %2)
                        win->getInterfaceHandler()->normalTools->pb_timeBlack->setPaletteBackgroundColor(Qt::red);
                  else 
                        win->getInterfaceHandler()->normalTools->pb_timeBlack->setPaletteBackgroundColor(win->getInterfaceHandler()->normalTools->palette().color(QPalette::Active,QColorGroup::Button)) ;//setPaletteBackgroundColor(Qt::PaletteBase);
                  qgo->playTimeSound();
            }           
      
            else if ( !myColorIsBlack && wt_i <= BY_timer && wt_i > -1 && (mv_counter % 2) == 0)
            {
                  if (wt_i %2)
                        win->getInterfaceHandler()->normalTools->pb_timeWhite->setPaletteBackgroundColor(Qt::red);
                  else 
                        win->getInterfaceHandler()->normalTools->pb_timeWhite->setPaletteBackgroundColor(win->getInterfaceHandler()->normalTools->palette().color(QPalette::Active,QColorGroup::Button)) ;//setPaletteBackgroundColor(Qt::PaletteBase);
                  qgo->playTimeSound();
            }
            
            //we have to reset the color when not anymore in warning period)
            else if (win->getInterfaceHandler()->normalTools->pb_timeBlack->paletteBackgroundColor() == Qt::red)
                  win->getInterfaceHandler()->normalTools->pb_timeBlack->setPaletteBackgroundColor(win->getInterfaceHandler()->normalTools->palette().color(QPalette::Active,QColorGroup::Button)) ;

            
            else if (win->getInterfaceHandler()->normalTools->pb_timeWhite->paletteBackgroundColor() == Qt::red)
                  win->getInterfaceHandler()->normalTools->pb_timeWhite->setPaletteBackgroundColor(win->getInterfaceHandler()->normalTools->palette().color(QPalette::Active,QColorGroup::Button)) ;

            

      }
}

// stop timer
void qGoBoard::set_stopTimer()
{
      if (timer_running)
      {
            killTimers();
            timer_running = false;
      }
}

// stop timer
void qGoBoard::set_runTimer()
{
      if (!timer_running)
      {
            startTimer(1000);
            timer_running = true;
      }
}

// send regular time info
void qGoBoard::setTimerInfo(const QString &btime, const QString &bstones, const QString &wtime, const QString &wstones)
{
      bt_i = btime.toInt();
      wt_i = wtime.toInt();
      b_stones = bstones;
      w_stones = wstones;

#ifdef SHOW_INTERNAL_TIME
      if (chk_b < 0)
      {
            chk_b = bt_i;
            chk_w = wt_i;
      }
#endif

      // set string in any case
      bt = secToTime(bt_i);
      wt = secToTime(wt_i);

      // set initial timer until game is initialized
      if (!have_gameData)
            win->getInterfaceHandler()->setTimes(bt, bstones, wt, wstones);

      // if time info available, sound can be played
      // cause no moves cmd in execution
      sound = true;
}

// addtime function
void qGoBoard::addtime_b(int m)
{
      bt_i += m*60;
      bt = secToTime(bt_i);
      win->getInterfaceHandler()->setTimes(secToTime(bt_i), b_stones, wt, w_stones);
}

void qGoBoard::addtime_w(int m)
{
      wt_i += m*60;
      wt = secToTime(wt_i);
      win->getInterfaceHandler()->setTimes(bt, b_stones, secToTime(wt_i), w_stones);
}

void qGoBoard::set_Mode(int src)
{
      switch (src)
      {
            case 0:
                  break;
            case 1:
                  gameMode = modeNormal;
                  win->getBoard()->set_isLocalGame(true);
                  break;
            case 2:
                  gameMode = modeObserve;
                  win->getBoard()->set_isLocalGame(false);
                  break;
            case 3:
                  gameMode = modeMatch;
                  win->getBoard()->set_isLocalGame(false);
                  break;

            case 4:
                  gameMode = modeTeach;
                  win->getBoard()->set_isLocalGame(false);
                  break;

            case 5:
                  // for game 0; local game
                  gameMode = modeNormal;
                  // correct button states
                  win->getBoard()->setMode(gameMode);
                  win->getInterfaceHandler()->toggleMode();
                  win->getInterfaceHandler()->toggleMode();
                  win->getBoard()->set_isLocalGame(true);
                  return;

            case 6:                                       //added eb 12
                  gameMode = modeComputer;
                  win->getBoard()->set_isLocalGame(true);
                  break;                                      //end add eb 12
      }

      win->getBoard()->setMode(gameMode);
}

void qGoBoard::set_move(StoneColor sc, QString pt, QString mv_nr)
{
      int mv_nr_int;

      // IGS: case undo with 'mark': no following command
      // -> from qgoIF::slot_undo(): set_move(stoneNone, 0, 0)
      if (!mv_nr)
            // undo one move
            mv_nr_int = mv_counter - 1;
      else
            mv_nr_int = mv_nr.toInt();

      if (mv_nr_int > mv_counter)
      {
            if (mv_nr_int != mv_counter + 1 && mv_counter != -1)
                  // case: move has done but "moves" cmd not executed yet
                  qWarning("**** LOST MOVE !!!! ****");
            else if (mv_counter == -1 && mv_nr_int != 0)
            {
                  qDebug("move skipped");
                  // skip moves until "moves" cmd executed
                  return;
            }
            else
                  mv_counter++;
      }
      else if (mv_nr_int + 1 == mv_counter)
      {
            // scoring mode? (NNGS)
            if (gameMode == modeScore)
            {
                  // back to matchMode
                  win->doRealScore(false);
                  win->getBoard()->setMode(modeMatch);
            }

            // special case: undo handicap
            if (mv_counter <= 0 && gd.handicap)
            {
                  gd.handicap = 0;
                  win->getBoard()->getBoardHandler()->setHandicap(0);
                  qDebug("set Handicap to 0");
            }

            if (!pt)
            {
                  // case: undo
                  qDebug("set_move(): UNDO in game " + QString::number(id));
                  qDebug("...mv_nr = " + mv_nr);

                                                                                         //added eb 9
                  Move *m=win->getBoard()->getBoardHandler()->getTree()->getCurrent();
                  Move *last=win->getBoard()->getBoardHandler()->lastValidMove ; //win->getBoard()->getBoardHandler()->getTree()->findLastMoveInMainBranch();

                  if (m!=last)                          // equivalent to display_incoming_move = false
                        win->getBoard()->getBoardHandler()->getTree()->setCurrent(last) ;
                  else
                        m = m->parent ;                   //we are going to delete the node. We will bactrack to m

                  win->getBoard()->deleteNode();
                  win->getBoard()->getBoardHandler()->lastValidMove = win->getBoard()->getBoardHandler()->getTree()->getCurrent();
                  win->getBoard()->getBoardHandler()->getTree()->getCurrent()->marker = NULL ; //(just in case)
                  win->getBoard()->getBoardHandler()->getStoneHandler()->checkAllPositions();
                             
                  win->getBoard()->getBoardHandler()->getTree()->setCurrent(m) ;   //we return where we were observing the game
                  // this is not very nice, but it ensures things stay clean
                  win->getBoard()->getBoardHandler()->updateMove(m);                      // end add eb 9

                  mv_counter--;

                  // ok for sound - no moves cmd in execution
                  sound = true;
            }

            return;
      }
      else
            // move already done...
            return;

      if (pt.contains("Handicap"))
      {
            QString handi = pt.simplifyWhiteSpace();
            int h = element(handi, 1, " ").toInt();

            // check if handicap is set with initGame() - game data from server do not
            // contain correct handicap in early stage, because handicap is first move!
            if (gd.handicap != h)
            {
                  gd.handicap = h;
                  win->getBoard()->getBoardHandler()->setHandicap(h);
                  qDebug("corrected Handicap");
            }
      }
      else if (pt.contains("Pass",false))
      {
            win->getBoard()->doSinglePass();
            qgo->playPassSound();
      }
      else
      {
            if ((gameMode == modeMatch) && (mv_counter < 2) && !(myColorIsBlack))
            {
                  // if black has not already done - maybe too late here???
                  if (requests_set)
                  {
                        qDebug(QString("qGoBoard::set_move() : check_requests at move %1").arg(mv_counter));
                        check_requests();
                  }
            }

            int i = (QChar) pt[0] - 'A' + 1;
            // skip j
            if (i > 8)
                  i--;

            int j;

            if (pt[2] >= '0' && pt[2] <= '9')
                  j = gd.size + 1 - pt.mid(1,2).toInt();
            else
                  j = gd.size + 1 - pt[1].digitValue();

            // avoid sound problem during execution of "moves" cmd
            if (stated_mv_count > mv_counter)
            {
                  sound = false;
/*
                  win->getBoard()->getBoardHandler()->createMoveSGF();
                  win->getBoard()->getBoardHandler()->setModeSGF(modeNormal);
                  win->getBoard()->getBoardHandler()->addStone(sc, i, j, sound);
                  //win->getBoard()->getBoardHandler()->getTree()->getCurrent()->setX(i);
                  //win->getBoard()->getBoardHandler()->getTree()->getCurrent()->setY(j);
                  //win->getBoard()->getBoardHandler()->getTree()->getCurrent()->setColor(sc);
                  //win->getBoard()->getBoardHandler()->updateMove(win->getBoard()->getBoardHandler()->getTree()->getCurrent());

                  if (stated_mv_count <= mv_counter + 1)
                  {
                        //win->getBoard()->getBoardHandler()->prepareBoard();
                        win->slotNavLast();
                  }

                  //setMode();
                  //win->getBoard()->updateCanvas();
//*/
            }
            else if (gameMode == modeComputer)
                  sound = true;

            win->getBoard()->addStone(sc, i, j, sound);
            Move *m = win->getBoard()->getBoardHandler()->getTree()->getCurrent();
            if (stated_mv_count > mv_counter ||
                  //gameMode == modeTeach ||
                  //ExtendedTeachingGame ||
                  wt_i < 0 || bt_i < 0)
            {
                  m->setTimeinfo(false);
            }
            else
            {
                  m->setTimeLeft(sc == stoneBlack ? bt_i : wt_i);
                  int stones = -1;
                  if (sc == stoneBlack)
                        stones = b_stones.toInt();
                  else
                        stones = w_stones.toInt();
                  m->setOpenMoves(stones);
                  m->setTimeinfo(true);

                  // check for a common error -> times and open moves identical
                  if (m->parent &&
                        m->parent->parent &&
                        m->parent->parent->getTimeinfo() &&
                        m->parent->parent->getTimeLeft() == m->getTimeLeft() &&
                        m->parent->parent->getOpenMoves() == m->getOpenMoves())
                  {
                        m->parent->parent->setTimeinfo(false);
                  }
            }
      }
}

// board window closed
void qGoBoard::slot_closeevent()
{
      if (id > 0)
      {
            id = -id;
//          emit signal_closeevent(id);
      }
      else
            qWarning("id < 0 ******************");
}

// write kibitz strings to comment window
void qGoBoard::send_kibitz(const QString msg)
{
      // observer info
      if (msg[0] == '0')
      {
            if (msg[1] == '0')
            {
                  // finish
                  win->updateObserverCnt();
            }
            else if (msg.length() < 5)
            {
                  //init
                  win->getMainWidget()->cb_opponent->clear();
                  win->getMainWidget()->TextLabel_opponent->setText(tr("opponent:"));
                  win->getMainWidget()->cb_opponent->insertItem(tr("-- none --"));
                  if (havePupil && ttOpponent != tr("-- none --"))
                  {
                        win->getMainWidget()->cb_opponent->insertItem(ttOpponent, 1);
                        win->getMainWidget()->cb_opponent->setCurrentItem(1);
                  }

                  win->clearObserver();
            }
            else
            {
                  win->getMainWidget()->cb_opponent->insertItem(msg.right(msg.length() - 3));
//                int cnt = win->getMainWidget()->cb_opponent->count();
//                win->getMainWidget()->TextLabel_opponent->setText(tr("opponent:") + " (" + QString::number(cnt-1) + ")");

                  win->addObserver(msg.right(msg.length() - 3));
            }

            return;
      }

      // if observing a teaching game
      if (ExtendedTeachingGame && !IamTeacher)
      {
            // get msgs from teacher
            if (msg.find("#OP:") != -1)
            {
                  // opponent has been selected
                  QString opp;
                  if (msg.contains('('))
                        opp = element(msg, 1, ":", "(").stripWhiteSpace();
                  else
                        opp = element(msg, 2, ":").stripWhiteSpace();

                  if (opp == "0")
                        slot_ttOpponentSelected(tr("-- none --"));
                  else
                        slot_ttOpponentSelected(opp);
            }
            else if (IamPupil)
            {
                  if (msg.find("#TC:ON") != -1)
                  {
                        // teacher gives controls to pupil
                        haveControls = true;
                        win->getMainWidget()->pb_controls->setEnabled(true);
                        win->getMainWidget()->pb_controls->setOn(true);
                  }
                  else if (msg.find("#TC:OFF") != -1)
                  {
                        // teacher takes controls back
                        haveControls = false;
                        win->getMainWidget()->pb_controls->setDisabled(true);
                        win->getMainWidget()->pb_controls->setOn(false);
                  }
            }
      }
      else if (ExtendedTeachingGame && IamTeacher)
      {
            // get msgs from pupil
            if (msg.find("#OC:OFF") != -1)
            {
                  // pupil gives controls back
                  haveControls = true;
                  win->getMainWidget()->pb_controls->setOn(false);
            }
            else if (havePupil && element(msg, 0, " ") == element(ttOpponent, 0, " ") &&
                    (myColorIsBlack && (mv_counter % 2) || !myColorIsBlack && ((mv_counter % 2 + 1) || mv_counter == -1) ||
                     !haveControls))
            {
                  // move from opponent - it's his turn (his color or he has controls)!
                  // xxx [rk]: B1 (7)
                  //   it's ensured that yyy [rk] didn't send forged message
                  //   e.g.: yyy [rk]: xxx[rk]: S1 (3)
                  QString s;
                  if (msg.contains('('))
                        s = element(msg, 0, ":", "(").stripWhiteSpace().upper();
                  else
                        s = element(msg, 1, ":").stripWhiteSpace().upper();

                  // check whether it's a position
                  // e.g. B1, A17, NOT: ok, yes
                  if (s.length() < 4 && s[0] >= 'A' && s[0] < 'U' && s[1] > '0' && s[1] <= '9')
                  {
                        // ok, could be a real pt
                        // now teacher has to send it: pupil -> teacher -> server
                        if (gsName == IGS)
                              emit signal_sendcommand(s + " " + QString::number(id), false);
                        else
                              emit signal_sendcommand(s, false);
                  }
            }
      }

      // skip my own messages
qDebug("msg.find(myName) = " + QString::number(msg.find(myName)));
//    if (msg.find(myName) == 0)
//          return;

      // normal stuff...
      if (msg.contains(QString::number(mv_counter + 1)))
      {
qDebug("qGoBoard::send_kibitz()");
//          win->getInterfaceHandler()->displayComment(msg);
            // update comment in SGF list
            win->getInterfaceHandler()->board->getBoardHandler()->updateComment(msg);
      }
      else
      {
//          win->getInterfaceHandler()->displayComment("(" + QString::number(mv_counter + 1) + ") " + msg);
            // update comment in SGF list
            win->getInterfaceHandler()->board->getBoardHandler()->updateComment("(" + QString::number(mv_counter + 1) + ") " + msg);
      }
}

void qGoBoard::slot_sendcomment(const QString &comment)
{
      // # has to be at the first position
      if (comment.find("#") == 0)
      {
            qDebug("detected (#) -> send command");
            QString testcmd = comment;
            testcmd = testcmd.remove(0, 1).stripWhiteSpace();
            emit signal_sendcommand(testcmd, true);
            return;
      }

      if (gameMode == modeObserve || gameMode == modeTeach || gameMode == modeMatch && ExtendedTeachingGame)
      {
            // kibitz
            emit signal_sendcommand("kibitz " + QString::number(id) + " " + comment, false);
            send_kibitz("-> " + comment);
      }
      else
      {
            // say
            emit signal_sendcommand("say " + comment, false);
            send_kibitz("-> " + comment);
      }
}

void qGoBoard::slot_addStone(StoneColor /*c*/, int x, int y)
{
      if (id < 0)
            return;

      if (x > 8)
            x++;
      QChar c1 = x - 1 + 'A';
      int c2 = gd.size + 1 - y;

      if (ExtendedTeachingGame && IamPupil)
            emit signal_sendcommand("kibitz " + QString::number(id) + " " + QString(c1) + QString::number(c2), false);
      else if (gsName == IGS)
            emit signal_sendcommand(QString(c1) + QString::number(c2) + " " + QString::number(id), false);
      else if (!win->getBoard()->getBoardHandler()->getGtp())
            emit signal_sendcommand(QString(c1) + QString::number(c2), false);
}

void qGoBoard::slot_stoneComputer(StoneColor c, int x, int y)
{
      if (id < 0)
            return;

      if (x > 8)
            x++;
      char c1 = x - 1 + 'A';
      //int c2 = gd.size + 1 - y;
      int c2 =win->getBoard()->getGameData()->size + 1 - y;
      
      
  mv_counter++;
  
      switch (c)
  {
    case stoneWhite :
      if (win->getBoard()->getBoardHandler()->getGtp()->playwhite(c1 ,c2))
        {
          QMessageBox::warning(win, PACKAGE, tr("Failed to play the stone within program \n") + win->getBoard()->getBoardHandler()->getGtp()->getLastMessage());
          return;
        }
      if (win->blackPlayerType==COMPUTER && (win->getBoard()->getBoardHandler()->getGtp()->getLastMessage() != "illegal move") )
           playComputer(c);  
        
       break;
        
    case stoneBlack :
      if (win->getBoard()->getBoardHandler()->getGtp()->playblack(c1 ,c2))
        {
          QMessageBox::warning(win, PACKAGE, tr("Failed to play the stone within program \n") + win->getBoard()->getBoardHandler()->getGtp()->getLastMessage());
          return;
        }

      if (win->whitePlayerType==COMPUTER && (win->getBoard()->getBoardHandler()->getGtp()->getLastMessage() != "illegal move"))
           playComputer(c);   
      break;  
     
    default :
      ;           
   }
}

void qGoBoard::slot_PassComputer(StoneColor c)
{
      if (id < 0)
            return;

  mv_counter++;

  //check if this is the second pass move.
   if ((win->getBoard()->getBoardHandler()->getTree()->getCurrent()->isPassMove())&&(win->getBoard()->getBoardHandler()->getTree()->getCurrent()->parent->isPassMove()))
      {
        emit signal_2passes(0,0);
        return;
      }
  
  // if simple pass, tell computer and move on
      switch (c)
  {
    case stoneWhite :
      if (win->getBoard()->getBoardHandler()->getGtp()->playwhitePass())
        {
          QMessageBox::warning(win, PACKAGE, tr("Failed to pass within program \n") + win->getBoard()->getBoardHandler()->getGtp()->getLastMessage());
          return;
        }
      if (win->blackPlayerType==COMPUTER)
           playComputer(c);

       break;

    case stoneBlack :
      if (win->getBoard()->getBoardHandler()->getGtp()->playblackPass())
        {
          QMessageBox::warning(win, PACKAGE, tr("Failed to pass within program \n") + win->getBoard()->getBoardHandler()->getGtp()->getLastMessage());
          return;
        }

      if (win->whitePlayerType==COMPUTER)
           playComputer(c);
      break;

    default :
      ;   
      
   }

}

void qGoBoard::slot_UndoComputer(StoneColor /*c*/)
{
      if (id < 0)
            return;

  mv_counter++;
  
  if (win->getBoard()->getBoardHandler()->getGtp()->undo())
        {
          QMessageBox::warning(win, PACKAGE, tr("Failed to undo within program \n") + win->getBoard()->getBoardHandler()->getGtp()->getLastMessage());
          return;
        }

  win->getBoard()->deleteNode();

  if (win->getBoard()->getBoardHandler()->getGtp()->undo())
        {
          QMessageBox::warning(win, PACKAGE, tr("Failed to undo within program \n") + win->getBoard()->getBoardHandler()->getGtp()->getLastMessage());
          return;
        }

  win->getBoard()->deleteNode();

}


void qGoBoard::playComputer(StoneColor c)
{

  // have the computer play a stone of color 'c'

  win->getBoard()->setCursor(WaitCursor);
  get_win()->getInterfaceHandler()->passButton->setEnabled(false);
  get_win()->getInterfaceHandler()->undoButton->setEnabled(false);
  
  switch (c)
  {
    case stoneWhite :

       if (win->getBoard()->getBoardHandler()->getGtp()->genmoveBlack())
        {
          QMessageBox::warning(win, PACKAGE, tr("Failed to have the program play its stone\n") + win->getBoard()->getBoardHandler()->getGtp()->getLastMessage());
          return;
        }
        break;

    case stoneBlack :
       if (win->getBoard()->getBoardHandler()->getGtp()->genmoveWhite())
        {
          QMessageBox::warning(win, PACKAGE, tr("Failed to have the program play its stone\n") + win->getBoard()->getBoardHandler()->getGtp()->getLastMessage());
          return;
        }
        break;

    default :
      ;     
      
   }

   QString computer_answer = win->getBoard()->getBoardHandler()->getGtp()->getLastMessage();

   /* Normal procedure would be
   GameInfo *gi

   gi ....
   emit signal || parse move(0,qi)
   */
   QString mv_nr;
   mv_nr.setNum(mv_counter+1);

   win->getBoard()->unsetCursor();
   get_win()->getInterfaceHandler()->passButton->setEnabled(true);
   get_win()->getInterfaceHandler()->undoButton->setEnabled(true);
   
   if (computer_answer == "resign")
      {
      win->getInterfaceHandler()->displayComment((myColorIsBlack ? "White resigned" : "Black resigned"));
      win->getBoard()->getBoardHandler()->getGameData()->result = (myColorIsBlack ? "B+R" : "W+R");
      slot_DoneComputer();
      return ;
      }     
   
   
   set_move(c==stoneBlack ? stoneWhite : stoneBlack , computer_answer, mv_nr);

   //the computer just played. Are we after 2 passes moves ?
 
   if ((win->getBoard()->getBoardHandler()->getTree()->getCurrent()->isPassMove())&&(win->getBoard()->getBoardHandler()->getTree()->getCurrent()->parent->isPassMove()))
      {
       emit signal_2passes(0,0);
       return;
       }

   // trick : if we have the computer play against himself, we recurse ...
   if (win->blackPlayerType ==   win->whitePlayerType)
      playComputer( c==stoneBlack ? stoneWhite : stoneBlack);
   
}

void qGoBoard::slot_DoneComputer()
{
   win->getInterfaceHandler()->passButton->setEnabled(false);
   win->getInterfaceHandler()->commentEdit->append( win->getBoard()->getBoardHandler()->getGameData()->result); 
   win->getInterfaceHandler()->restoreToolbarButtons();
}


void qGoBoard::slot_doPass()
{
  if (gameMode == modeComputer)
    slot_PassComputer(myColorIsBlack ? stoneBlack : stoneWhite);

  else  if (id > 0)
    emit signal_sendcommand("pass", false);
}

void qGoBoard::slot_doResign()
{
      if (gameMode == modeComputer)
            {
            win->getInterfaceHandler()->displayComment((myColorIsBlack ? "Black resigned" : "White resigned"));
            win->getBoard()->getBoardHandler()->getGameData()->result = (myColorIsBlack ? "W+R" : "B+R");
            slot_DoneComputer();
            }     
      else if (id > 0)
            emit signal_sendcommand("resign", false);
}

void qGoBoard::slot_doUndo()
{
      if (gameMode == modeComputer)
            slot_UndoComputer(myColorIsBlack ? stoneBlack : stoneWhite);
    
      else if (id > 0)
            emit signal_sendcommand("undo", false); 
}

void qGoBoard::slot_doAdjourn()
{
      qDebug("button: adjourn");
      if (id > 0)
            emit signal_sendcommand("adjourn", false);
}

void qGoBoard::slot_doDone()
{
      if(win->getBoard()->getBoardHandler()->getGtp())   //we are now in score mode !
            slot_DoneComputer();
    
      else if (id > 0)
            emit signal_sendcommand("done", false);
}

void qGoBoard::slot_doRefresh()
{
      // no refresh for ended or adjourned games
      if (id > 0 && id != 10000)
      {
            if (!have_gameData)
                  emit signal_sendcommand("games " + QString::number(id), false);
            else
            {
                  set_sentmovescmd(true);
                  emit signal_sendcommand("moves " + QString::number(id), false);
//                emit signal_sendcommand("all " + QString::number(id), false);
            }

//          if (ExtendedTeachingGame)
                  // get observers
            emit signal_sendcommand("all " + QString::number(id), false);
      }
      else if (id == 10000 && (gd.playerBlack == myName || gd.playerWhite == myName))
      {
            // load stored game
            emit signal_sendcommand("load " + gd.playerWhite + "-" + gd.playerBlack, false);
      }
}

void qGoBoard::set_requests(const QString &handicap, const QString &komi, assessType kt)
{
qDebug("set req_handicap to " + handicap);
qDebug("set req_komi to " + komi);
      req_handicap = handicap;
      req_komi = komi;
      req_free = kt;
      requests_set = true;
}

// compare settings with requested values
void qGoBoard::check_requests()
{
      // check if handicap requested via negotiation (if activated!)
      // do not set any value while reloading a game
      if (req_handicap == -1 || gameMode == modeTeach || !setting->readBoolEntry("DEFAULT_AUTONEGO"))
            return;

      if (gd.handicap != req_handicap.toInt())
      {
            emit signal_sendcommand("handicap " + req_handicap, false);
            qDebug("Requested handicap: " + req_handicap);
      }
      else
            qDebug("Handicap settings ok...");

      if (gd.komi != req_komi.toFloat())
      {
            qDebug("qGoBoard::check_requests() : emit komi");
            emit signal_sendcommand("komi " + req_komi, false);
      }

      // if size != 19 don't care, it's a free game
      if (req_free != noREQ && gd.size == 19 && mv_counter < 1)
      {
            // check if requests are equal to settings or if teaching game
            if ((gd.freegame == FREE && req_free == FREE) ||
                (gd.freegame != FREE && req_free == RATED) ||
                req_free == TEACHING)
                return;

            switch (gsName)
            {
                  case NNGS:
                        if (gd.freegame == FREE)
                              emit signal_sendcommand("unfree", false);
                        else
                              emit signal_sendcommand("free", false);
                        break;

                  // default: toggle
                  default:
                        emit signal_sendcommand("free", false);
                        break;
            }
      }
else
qDebug("Rated game settings ok...");
}

// click on time field
void qGoBoard::slot_addtimePauseB()
{
      if (myColorIsBlack)
      {

            switch (gsName)
            {
                  case IGS:
                        break;

                  default:
                        if (game_paused)
                              emit signal_sendcommand("unpause", false);
                        else
                              emit signal_sendcommand("pause", false);
                        break;
            }
      }
      else
            emit signal_sendcommand("addtime 1", false);
}

// click on time field
void qGoBoard::slot_addtimePauseW()
{
      if (!myColorIsBlack)
      {
            switch (gsName)
            {
                  case IGS:
                        break;

                  default:
                        if (game_paused)
                              emit signal_sendcommand("unpause", false);
                        else
                              emit signal_sendcommand("pause", false);
                        break;
            }
      }
      else
            emit signal_sendcommand("addtime 1", false);
}

// for several reasons: let me know which is my color
void qGoBoard::set_myColorIsBlack(bool b)
{
      myColorIsBlack = b;

      // set correct tooltips
      QToolTip::remove(win->getInterfaceHandler()->normalTools->pb_timeBlack);
      QToolTip::remove(win->getInterfaceHandler()->normalTools->pb_timeWhite);

      if (b)
      {
            switch (gsName)
            {
                  case IGS:
                        QToolTip::add(win->getInterfaceHandler()->normalTools->pb_timeBlack, tr("remaining time / stones"));
                        break;

                  default:
                        QToolTip::add(win->getInterfaceHandler()->normalTools->pb_timeBlack, tr("click to pause/unpause the game"));
                        break;
            }

            QToolTip::add(win->getInterfaceHandler()->normalTools->pb_timeWhite, tr("click to add 1 minute to your opponent's clock"));
      }
      else
      {
            switch (gsName)
            {
                  case IGS:
                        QToolTip::add(win->getInterfaceHandler()->normalTools->pb_timeBlack, tr("remaining time / stones"));
                        break;

                  default:
                        QToolTip::add(win->getInterfaceHandler()->normalTools->pb_timeWhite, tr("click to pause/unpause the game"));
                        break;
            }

            QToolTip::add(win->getInterfaceHandler()->normalTools->pb_timeBlack, tr("click to add 1 minute to your opponent's clock"));
      }
}

// teachtools - teacher has selected an opponent
void qGoBoard::slot_ttOpponentSelected(const QString &opponent)
{
      if (opponent == tr("-- none --"))
      {
            havePupil = false;
      }
      else
      {
            ttOpponent = opponent;
            havePupil = true;
            // teacher has controls when opponent is selected
            haveControls = IamTeacher;
      }
      win->getMainWidget()->pb_controls->setEnabled(IamTeacher && havePupil);

      if (IamTeacher)
      {
            if (opponent == tr("-- none --"))
                  emit signal_sendcommand("kibitz " + QString::number(id) + " #OP:0", false);
            else
                  emit signal_sendcommand("kibitz " + QString::number(id) + " #OP:" + opponent, false);
            // set teacher's color -> but: teacher can play both colors anyway
            set_myColorIsBlack(mv_counter % 2 + 1);
      }
      else
      {
            bool found = false;
            // look for correct item
            QComboBox *cb = win->getMainWidget()->cb_opponent;
            int cnt = cb->count();
            for (int i = 0; i < cnt && !found; i++)
            {
                  cb->setCurrentItem(i);
                  if (cb->currentText() == opponent)
                  {
                        cb->setCurrentItem(i);
                        found = true;
                  }
            }

            if (!found)
            {
                  cb->insertItem(opponent, cnt);
                  cb->setCurrentItem(cnt);
            }

            // check if it's me
            QString opp = element(opponent, 0, " ");
            if (opp == myName)
            {
                  IamPupil = true;
                  // set up match
                  set_Mode(3);
                  win->getBoard()->set_myColorIsBlack(mv_counter % 2);
                  set_myColorIsBlack(mv_counter % 2);
            }
            else
            {
                  IamPupil = false;
                  // reset to observer
                  set_Mode(2);
            }
      }
}

// teachtools - controls button has toggled
void qGoBoard::slot_ttControls(bool on)
{
      // teacher: on -> give controls to pupil
      //          off -> take controls back
      //          teacher has controls if BUTTON RELEASED (!ON)
      // pupil: only off -> give controls back
      //          pupil has controls if BUTTON PRESSED (ON)
      if (IamTeacher)
      {
            // check whether controls key has been clicked or has been toggled by command
            if (haveControls && !on || !haveControls && on)
            {
                  // toggled by command
            }
            else
            {
                  if (on)
                        emit signal_sendcommand("kibitz " + QString::number(id) + " #TC:ON", false);
                  else
                        emit signal_sendcommand("kibitz " + QString::number(id) + " #TC:OFF", false);

                  haveControls = !on;
            }
      }
      else if (IamPupil)
      {
            // set game mode
            if (on)
            {
                  // pupil is able to play both colors
                  // set up teach
                  set_Mode(4);
            }
            else
            {
                  // pupil has only one color
                  // set up match
                  set_Mode(3);
            }

            // check whether controls key has been clicked or has been toggled by command
            if (!haveControls && !on || haveControls && on)
                  // toggled by command
                  return;

            emit signal_sendcommand("kibitz " + QString::number(id) + " #OC:OFF", false);
            win->getMainWidget()->pb_controls->setDisabled(true);
            haveControls = false;
      }
}

// teachtools - mark button has toggled
void qGoBoard::slot_ttMark(bool on)
{
      switch (gsName)
      {
            case IGS:
                  // simple 'mark' cmd
                  if (on)
                        emit signal_sendcommand("mark", false);
                  else
                        emit signal_sendcommand("undo", false);
                  break;

            case LGS:
            case CTN:
                  // use undo cmd
                  if (on)
                  {
                        mark_set = true;
                        mark_counter = mv_counter;
                  }
                  else
                  {
                        mark_set = false;
                        for (; mark_counter <= mv_counter; mark_counter++);
                              emit signal_sendcommand("undo", false);
                        mark_counter = 0;
                  }
                  break;

            default:
                  // use undo [n] cmd
                  if (on)
                  {
                        mark_set = true;
                        mark_counter = mv_counter;
                  }
                  else
                  {
                        mark_set = false;
                        emit signal_sendcommand("undo " + QString::number(mv_counter - mark_counter + 1), false);
                        mark_counter = 0;
                  }
                  break;
      }
}


Generated by  Doxygen 1.6.0   Back to index