summaryrefslogtreecommitdiffstats
path: root/kjumpingcube/kcubeboxwidget.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kjumpingcube/kcubeboxwidget.cpp')
-rw-r--r--kjumpingcube/kcubeboxwidget.cpp711
1 files changed, 711 insertions, 0 deletions
diff --git a/kjumpingcube/kcubeboxwidget.cpp b/kjumpingcube/kcubeboxwidget.cpp
new file mode 100644
index 00000000..98f305d9
--- /dev/null
+++ b/kjumpingcube/kcubeboxwidget.cpp
@@ -0,0 +1,711 @@
+/* ****************************************************************************
+ This file is part of the game 'KJumpingCube'
+
+ Copyright (C) 1998-2000 by Matthias Kiefer
+ <matthias.kiefer@gmx.de>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+**************************************************************************** */
+#include "kcubeboxwidget.h"
+
+#include <kapplication.h>
+#include <kconfig.h>
+#include <qlayout.h>
+#include <qtimer.h>
+#include <assert.h>
+#include <kcursor.h>
+
+#include "prefs.h"
+
+KCubeBoxWidget::KCubeBoxWidget(const int d,QWidget *parent,const char *name)
+ : QWidget(parent,name),
+ CubeBoxBase<KCubeWidget>(d)
+{
+ init();
+}
+
+
+
+KCubeBoxWidget::KCubeBoxWidget(CubeBox& box,QWidget *parent,const char *name)
+ :QWidget(parent,name),
+ CubeBoxBase<KCubeWidget>(box.dim())
+{
+ init();
+
+ int i,j;
+ for(i=0;i<dim();i++)
+ for(j=0;j<dim();j++)
+ {
+ *cubes[i][j]=*box[i][j];
+ }
+
+ currentPlayer=(KCubeBoxWidget::Player)box.player();
+}
+
+
+
+KCubeBoxWidget::KCubeBoxWidget(const KCubeBoxWidget& box,QWidget *parent,const char *name)
+ :QWidget(parent,name),
+ CubeBoxBase<KCubeWidget>(box.dim())
+{
+ init();
+
+ int i,j;
+ for(i=0;i<dim();i++)
+ for(j=0;j<dim();j++)
+ {
+ *cubes[i][j]=*box.cubes[i][j];
+ }
+
+
+ currentPlayer=box.currentPlayer;
+}
+
+
+
+KCubeBoxWidget::~KCubeBoxWidget()
+{
+ if(isActive())
+ stopActivities();
+ if(cubes)
+ deleteCubes();
+ if(undoBox)
+ delete undoBox;
+}
+
+void KCubeBoxWidget::loadSettings(){
+ setColor(KCubeBoxWidget::One, Prefs::color1());
+ setColor(KCubeBoxWidget::Two, Prefs::color2());
+
+ setDim(Prefs::cubeDim());
+ brain.setSkill( Prefs::skill() );
+
+ setComputerplayer(KCubeBoxWidget::One, Prefs::computerPlayer1());
+ setComputerplayer(KCubeBoxWidget::Two, Prefs::computerPlayer2());
+ checkComputerplayer(currentPlayer);
+}
+
+KCubeBoxWidget& KCubeBoxWidget::operator=(const KCubeBoxWidget& box)
+{
+ if(this!=&box)
+ {
+ if(dim()!=box.dim())
+ {
+ setDim(box.dim());
+ }
+
+
+ for(int i=0;i<dim();i++)
+ for(int j=0;j<dim();j++)
+ {
+ *cubes[i][j]=*box.cubes[i][j];
+ }
+
+ currentPlayer=box.currentPlayer;
+ }
+ return *this;
+}
+
+KCubeBoxWidget& KCubeBoxWidget::operator=(CubeBox& box)
+{
+ if(dim()!=box.dim())
+ {
+ setDim(box.dim());
+ }
+
+ for(int i=0;i<dim();i++)
+ for(int j=0;j<dim();j++)
+ {
+ *cubes[i][j]=*box[i][j];
+ }
+
+ currentPlayer=(KCubeBoxWidget::Player)box.player();
+
+ return *this;
+}
+
+void KCubeBoxWidget::reset()
+{
+ stopActivities();
+
+ int i,j;
+ for(i=0;i<dim();i++)
+ for(j=0;j<dim();j++)
+ {
+ cubes[i][j]->reset();
+ }
+
+ KCubeWidget::enableClicks(true);
+
+ currentPlayer=One;
+
+ emit playerChanged(One);
+ checkComputerplayer(One);
+}
+
+void KCubeBoxWidget::undo()
+{
+ if(isActive())
+ return;
+
+ Player oldPlayer=currentPlayer;
+
+ *this=*undoBox;
+
+ if(oldPlayer!=currentPlayer)
+ emit playerChanged(currentPlayer);
+
+ checkComputerplayer(currentPlayer);
+
+}
+
+void KCubeBoxWidget::getHint()
+{
+ if(isActive())
+ return;
+
+ int d=dim();
+ for(int i=0;i<d;i++)
+ for(int j=0;j<d;j++)
+ {
+ cubes[i][j]->stopHint();
+ }
+
+ int row=0,column=0;
+ CubeBox field=*this;
+
+ emit startedThinking();
+ bool canceled=!brain.getHint(row,column,(CubeBox::Player)currentPlayer,field);
+ emit stoppedThinking();
+
+ if(canceled)
+ {
+ return; // return if thinking was stopped
+ }
+ cubes[row][column]->showHint();
+}
+
+void KCubeBoxWidget::setColor(Player player,QPalette color)
+{
+ KCubeWidget::setColor((Cube::Owner)player,color);
+
+ for(int row=0;row<dim();row++)
+ for(int col=0;col<dim();col++)
+ {
+ cubes[row][col]->updateColors();
+ }
+}
+
+void KCubeBoxWidget::setDim(int d)
+{
+ if(d != dim())
+ {
+ undoBox->setDim(d);
+ CubeBoxBase<KCubeWidget>::setDim(d);
+ }
+}
+
+void KCubeBoxWidget::setComputerplayer(Player player,bool flag)
+{
+ if(player==One)
+ computerPlOne=flag;
+ else if(player==Two)
+ computerPlTwo=flag;
+}
+
+
+void KCubeBoxWidget::stopActivities()
+{
+ if(moveTimer->isActive())
+ {
+ stopLoop();
+ emit stoppedMoving();
+ }
+ if(brain.isActive())
+ {
+ brain.stop();
+ emit stoppedThinking();
+ }
+
+}
+
+void KCubeBoxWidget::saveProperties(KConfigBase* config)
+{
+ if(isMoving())
+ {
+ stopActivities();
+ undo();
+ }
+ else if(brain.isActive())
+ stopActivities();
+
+ // save current player
+ config->writeEntry("onTurn",(int)currentPlayer);
+
+ QStrList list;
+ list.setAutoDelete(true);
+ QString owner, value, key;
+ int cubeDim=dim();
+
+ for(int row=0; row < cubeDim ; row++)
+ for(int column=0; column < cubeDim ; column++)
+ {
+ key.sprintf("%u,%u",row,column);
+ owner.sprintf("%u",cubes[row][column]->owner());
+ value.sprintf("%u",cubes[row][column]->value());
+ list.append(owner.ascii());
+ list.append(value.ascii());
+ config->writeEntry(key , list);
+
+ list.clear();
+ }
+ config->writeEntry("CubeDim",dim());
+}
+
+void KCubeBoxWidget::readProperties(KConfigBase* config)
+{
+ QStrList list;
+ list.setAutoDelete(true);
+ QString owner, value, key;
+ setDim(config->readNumEntry("CubeDim",5));
+ int cubeDim=dim();
+
+ for(int row=0; row < cubeDim ; row++)
+ for(int column=0; column < cubeDim ; column++)
+ {
+ key.sprintf("%u,%u",row,column);
+ config->readListEntry(key, list);
+ owner=list.first();
+ value=list.next();
+ cubes[row][column]->setOwner((KCubeWidget::Owner)owner.toInt());
+ cubes[row][column]->setValue(value.toInt());
+
+ list.clear();
+ }
+
+
+ // set current player
+ int onTurn=config->readNumEntry("onTurn",1);
+ currentPlayer=(Player)onTurn;
+ emit playerChanged(onTurn);
+ checkComputerplayer((Player)onTurn);
+}
+
+/* ***************************************************************** **
+** slots **
+** ***************************************************************** */
+void KCubeBoxWidget::setWaitCursor()
+{
+ setCursor(KCursor::waitCursor());
+}
+
+
+
+void KCubeBoxWidget::setNormalCursor()
+{
+ setCursor(KCursor::handCursor());
+}
+
+void KCubeBoxWidget::stopHint()
+{
+
+ int d=dim();
+ for(int i=0;i<d;i++)
+ for(int j=0;j<d;j++)
+ {
+ cubes[i][j]->stopHint();
+ }
+
+}
+
+bool KCubeBoxWidget::checkClick(int row,int column, bool isClick)
+{
+ if(isActive())
+ return false;
+
+ // make the game start when computer player is player one and user clicks
+ if(isClick && currentPlayer == One && computerPlOne)
+ {
+ checkComputerplayer(currentPlayer);
+ return false;
+ }
+ else if((Cube::Owner)currentPlayer==cubes[row][column]->owner() ||
+ cubes[row][column]->owner()==Cube::Nobody)
+ {
+ doMove(row,column);
+ return true;
+ }
+ else
+ return false;
+}
+
+void KCubeBoxWidget::checkComputerplayer(Player player)
+{
+ // checking if a process is running or the Widget isn't shown yet
+ if(isActive() || !isVisibleToTLW())
+ return;
+ if((player==One && computerPlOne && currentPlayer==One)
+ || (player==Two && computerPlTwo && currentPlayer==Two))
+ {
+ KCubeWidget::enableClicks(false);
+
+ CubeBox field(*this);
+ int row=0,column=0;
+ emit startedThinking();
+ bool canceled=!brain.getHint(row,column,(CubeBoxBase<Cube>::Player)player,field);
+ emit stoppedThinking();
+
+ if(!canceled)
+ {
+ cubes[row][column]->showHint(500,2);
+
+ bool result=checkClick(row,column,false);
+ assert(result);
+ }
+ }
+
+}
+
+/* ***************************************************************** **
+** status functions **
+** ***************************************************************** */
+
+bool KCubeBoxWidget::isActive() const
+{
+ bool flag=false;
+ if(moveTimer->isActive())
+ flag=true;
+ else if(brain.isActive())
+ flag=true;
+
+ return flag;
+}
+
+bool KCubeBoxWidget::isMoving() const
+{
+ return moveTimer->isActive();
+}
+
+bool KCubeBoxWidget::isComputer(Player player) const
+{
+ if(player==One)
+ return computerPlOne;
+ else
+ return computerPlTwo;
+}
+
+
+int KCubeBoxWidget::skill() const
+{
+ return brain.skill();
+}
+
+QPalette KCubeBoxWidget::color(Player forWhom)
+{
+ return KCubeWidget::color((KCubeWidget::Owner)forWhom);
+}
+
+/* ***************************************************************** **
+** initializing functions **
+** ***************************************************************** */
+void KCubeBoxWidget::init()
+{
+ initCubes();
+
+ undoBox=new CubeBox(dim());
+
+ currentPlayer=One;
+ moveDelay=100;
+ moveTimer=new QTimer(this);
+ computerPlOne=false;
+ computerPlTwo=false;
+ KCubeWidget::enableClicks(true);
+ loadSettings();
+
+ connect(moveTimer,SIGNAL(timeout()),SLOT(nextLoopStep()));
+ connect(this,SIGNAL(startedThinking()),SLOT(setWaitCursor()));
+ connect(this,SIGNAL(stoppedThinking()),SLOT(setNormalCursor()));
+ connect(this,SIGNAL(startedMoving()),SLOT(setWaitCursor()));
+ connect(this,SIGNAL(stoppedMoving()),SLOT(setNormalCursor()));
+ connect(this,SIGNAL(playerWon(int)),SLOT(stopActivities()));
+
+ setNormalCursor();
+
+ emit playerChanged(One);
+}
+
+void KCubeBoxWidget::initCubes()
+{
+ const int s=dim();
+ int i,j;
+
+ // create Layout
+ layout=new QGridLayout(this,s,s);
+
+
+ for(i=0;i<s;i++)
+ {
+ layout->setRowStretch(i,1);
+ layout->setColStretch(i,1);
+ }
+
+
+ // create new cubes
+ cubes = new KCubeWidget**[s];
+ for(i=0;i<s;i++)
+ {
+ cubes[i]=new KCubeWidget*[s];
+ }
+ for(i=0;i<s;i++)
+ for(j=0;j<s;j++)
+ {
+ cubes[i][j]=new KCubeWidget(this);
+ cubes[i][j]->setCoordinates(i,j);
+ layout->addWidget(cubes[i][j],i,j);
+ cubes[i][j]->show();
+ connect(cubes[i][j],SIGNAL(clicked(int,int,bool)),SLOT(stopHint()));
+ connect(cubes[i][j],SIGNAL(clicked(int,int,bool)),SLOT(checkClick(int,int,bool)));
+ }
+
+ // initialize cubes
+ int max=dim()-1;
+
+ cubes[0][0]->setMax(2);
+ cubes[0][max]->setMax(2);
+ cubes[max][0]->setMax(2);
+ cubes[max][max]->setMax(2);
+
+ for(i=1;i<max;i++)
+ {
+ cubes[i][0]->setMax(3);
+ cubes[i][max]->setMax(3);
+ cubes[0][i]->setMax(3);
+ cubes[max][i]->setMax(3);
+ }
+
+ for(i=1;i<max;i++)
+ for(j=1;j<max;j++)
+ {
+ cubes[i][j]->setMax(4);
+ }
+
+}
+
+QSize KCubeBoxWidget::sizeHint() const
+{
+ return QSize(400,400);
+}
+
+void KCubeBoxWidget::deleteCubes()
+{
+ if(layout)
+ delete layout;
+
+ CubeBoxBase<KCubeWidget>::deleteCubes();
+}
+
+
+/* ***************************************************************** **
+** other private functions **
+** ***************************************************************** */
+
+void KCubeBoxWidget::doMove(int row,int column)
+{
+ // if a move hasn't finished yet don't do another move
+ if(isActive())
+ return;
+
+ // for undo-function copy field
+ *undoBox=*this;
+
+ cubes[row][column]->increase((Cube::Owner)currentPlayer);
+
+ if(cubes[row][column]->overMax())
+ {
+ KCubeWidget::enableClicks(false);
+ startLoop();
+ }
+ else
+ changePlayer();
+}
+
+void KCubeBoxWidget::startLoop()
+{
+ emit startedMoving();
+
+ KCubeWidget::enableClicks(false);
+
+ loop.row=0;
+ loop.column=0;
+ loop.finished=true;
+
+ moveTimer->start(moveDelay);
+}
+
+void KCubeBoxWidget::stopLoop()
+{
+ moveTimer->stop();
+ emit stoppedMoving();
+ KCubeWidget::enableClicks(true);
+}
+
+void KCubeBoxWidget::nextLoopStep()
+{
+ // search cube with to many points
+ while(!cubes[loop.row][loop.column]->overMax())
+ {
+ loop.column++;
+ if(loop.column==dim())
+ {
+ if(loop.row==dim()-1)
+ {
+ if(!loop.finished)
+ {
+ loop.row=0;
+ loop.column=0;
+ loop.finished=true;
+ return;
+ }
+ else // loop finished
+ {
+ stopLoop();
+ changePlayer();
+
+ return;
+ }
+ }
+ else
+ {
+ loop.row++;
+ loop.column=0;
+ }
+ }
+ }
+
+
+ increaseNeighbours(currentPlayer,loop.row,loop.column);
+ cubes[loop.row][loop.column]->decrease();
+ loop.finished=false;
+
+ if(hasPlayerWon(currentPlayer))
+ {
+ emit playerWon((int)currentPlayer);
+ stopLoop();
+ return;
+ }
+}
+
+bool KCubeBoxWidget::hasPlayerWon(Player player)
+{
+ for(int i=0;i<dim();i++)
+ for(int j=0;j<dim();j++)
+ {
+ if(cubes[i][j]->owner()!=(Cube::Owner)player)
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+KCubeBoxWidget::Player KCubeBoxWidget::changePlayer()
+{
+ currentPlayer=(currentPlayer==One)? Two : One;
+
+ emit playerChanged(currentPlayer);
+ checkComputerplayer(currentPlayer);
+ KCubeWidget::enableClicks(true);
+ return currentPlayer;
+}
+
+
+void KCubeBoxWidget::increaseNeighbours(KCubeBoxWidget::Player forWhom,int row,int column)
+{
+ KCubeWidget::Owner _player = (KCubeWidget::Owner)(forWhom);
+
+ if(row==0)
+ {
+ if(column==0) // top left corner
+ {
+ cubes[0][1]->increase(_player);
+ cubes[1][0]->increase(_player);
+ return;
+ }
+ else if(column==dim()-1) // top right corner
+ {
+ cubes[0][dim()-2]->increase(_player);
+ cubes[1][dim()-1]->increase(_player);
+ return;
+ }
+ else // top edge
+ {
+ cubes[0][column-1]->increase(_player);
+ cubes[0][column+1]->increase(_player);
+ cubes[1][column]->increase(_player);
+ return;
+ }
+ }
+ else if(row==dim()-1)
+ {
+ if(column==0) // left bottom corner
+ {
+ cubes[dim()-2][0]->increase(_player);
+ cubes[dim()-1][1]->increase(_player);
+ return;
+ }
+
+ else if(column==dim()-1) // right bottom corner
+ {
+ cubes[dim()-2][dim()-1]->increase(_player);
+ cubes[dim()-1][dim()-2]->increase(_player);
+ return;
+ }
+ else // bottom edge
+ {
+ cubes[dim()-1][column-1]->increase(_player);
+ cubes[dim()-1][column+1]->increase(_player);
+ cubes[dim()-2][column]->increase(_player);
+ return;
+ }
+ }
+ else if(column==0) // left edge
+ {
+ cubes[row-1][0]->increase(_player);
+ cubes[row+1][0]->increase(_player);
+ cubes[row][1]->increase(_player);
+ return;
+ }
+ else if(column==dim()-1) // right edge
+ {
+ cubes[row-1][dim()-1]->increase(_player);
+ cubes[row+1][dim()-1]->increase(_player);
+ cubes[row][dim()-2]->increase(_player);
+ return;
+ }
+ else
+ {
+ cubes[row][column-1]->increase(_player);
+ cubes[row][column+1]->increase(_player);
+ cubes[row-1][column]->increase(_player);
+ cubes[row+1][column]->increase(_player);
+ return;
+ }
+
+
+}
+
+#include "kcubeboxwidget.moc"
+