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