Commit 04df3a41 authored by Dmitry Suzdalev's avatar Dmitry Suzdalev

Postpone deleting game object until animation slot gets called

(if animation or thiking is in progress)
This should fix crahses that appear if you hit "New Game" when computer is thiking or
playing animation

BUG: 154946

svn path=/trunk/KDE/kdegames/kreversi/; revision=757648
parent 7b0c3759
......@@ -219,6 +219,7 @@ public:
~Engine();
KReversiPos computeMove(const KReversiGame& game, bool competitive);
bool isThinking() const { return m_computingMove; }
void setInterrupt(bool intr) { m_interrupt = intr; }
bool interrupted() const { return m_interrupt; }
......
......@@ -508,6 +508,14 @@ bool KReversiGame::hasChunk( Direction dir, const KReversiPos& move ) const
return false;
}
bool KReversiGame::isThinking() const
{
if( !m_engine )
return false;
return m_engine->isThinking();
}
bool KReversiGame::isGameOver() const
{
// trivial fast-check
......
......@@ -99,6 +99,10 @@ public:
* Sets the computer skill level. From 1 to 7
*/
void setComputerSkill(int skill);
/**
* @return whether the game is currently computing turn
*/
bool isThinking() const;
/**
* @return whether the game is already over
*/
......
......@@ -34,7 +34,7 @@
#include <KGamePopupItem>
KReversiScene::KReversiScene( KReversiGame* game , const QString& chipsPath )
: m_game(0), m_frameSet(0), m_hintChip(0), m_lastMoveChip(0), m_timerDelay(25),
: m_game(0), m_pendingNewGame(0), m_frameSet(0), m_hintChip(0), m_lastMoveChip(0), m_timerDelay(25),
m_showingHint(false), m_demoMode(false), m_showLastMove(false), m_showPossibleMoves(false),
m_showLabels(false)
{
......@@ -147,7 +147,43 @@ void KReversiScene::setShowBoardLabels( bool show )
void KReversiScene::setGame( KReversiGame* game )
{
// if animation is running or we are thinking save this game in pending var.
// It will be made current animation slot will get called
// @see setNewGameObject and @see slotAnimationStep
//
// NOTE: all this magic is needed for game not to crash while pressing new game:
// if we'd simply set the new object right away and deleted an old one, slotAnimationStep
// might got called *after* this, trying to do smth with already deleted object.
// For example see BUG #154946
// So we postpone the setting && deletion...
if( m_animTimer->isActive() || ( m_game && m_game->isThinking() ) )
m_pendingNewGame = game;
else
setNewGameObject( game );
}
void KReversiScene::setNewGameObject( KReversiGame* game )
{
m_animTimer->stop();
// disconnect signals from previous game if it exists,
// we are not interested in them anymore
if( m_game )
{
disconnect( m_game, SIGNAL(boardChanged()), this, SLOT(updateBoard()) );
disconnect( m_game, SIGNAL(moveFinished()), this, SLOT(slotGameMoveFinished()) );
disconnect( m_game, SIGNAL(gameOver()), this, SLOT(slotGameOver()) );
disconnect( m_game, SIGNAL(computerCantMove()), this, SLOT(slotComputerCantMove()) );
disconnect( m_game, SIGNAL(playerCantMove()), this, SLOT(slotPlayerCantMove()) );
}
// delete old object
delete m_game;
m_game = game;
m_pendingNewGame = 0; // it's made official now ;)
connect( m_game, SIGNAL(boardChanged()), SLOT(updateBoard()) );
connect( m_game, SIGNAL(moveFinished()), SLOT(slotGameMoveFinished()) );
connect( m_game, SIGNAL(gameOver()), SLOT(slotGameOver()) );
......@@ -169,7 +205,6 @@ void KReversiScene::setGame( KReversiGame* game )
m_possibleMovesItems.clear();
m_animTimer->stop();
m_hintChip = 0; // it was deleted above if it was shown
m_showingHint = false;
m_lastMoveChip = 0;
......@@ -296,6 +331,14 @@ void KReversiScene::slotGameMoveFinished()
void KReversiScene::slotAnimationStep()
{
if( m_pendingNewGame != 0 )
{
// aha! we have new game waiting for us
m_animTimer->stop();
setNewGameObject( m_pendingNewGame );
return;
}
if(m_changedChips.count() == 0 && !m_showingHint)
{
// FIXME: GGZ only - doesn't yet report flipped chips
......
......@@ -56,7 +56,8 @@ public:
~KReversiScene();
/**
* Sets the game object which this scene will visualize/use
* Sets the game object which this scene will visualize/use.
* KReversiScene takes ownership of this object and will delete it when appropriate
*/
void setGame( KReversiGame* game );
/**
......@@ -144,6 +145,11 @@ private:
* Mouse presses event handler
*/
virtual void mousePressEvent( QGraphicsSceneMouseEvent* );
/**
* Makes pending new game object a current one.
* @see m_pendingNewGame @see setGame
*/
void setNewGameObject( KReversiGame* game );
/**
* Visually displays last move and possible moves
* (if the scene is set up to show them)
......@@ -169,6 +175,11 @@ private:
* The Game object
*/
KReversiGame *m_game;
/**
* This pointer is meant for temporal storage of new game object being set.
* New game object is *actually* set after animation slot gets called by timer
*/
KReversiGame *m_pendingNewGame;
/**
* This will hold pixmap which is rendered by m_possMovesRenderer.
* It will be rerendered on resizes
......
......@@ -248,11 +248,6 @@ void KReversiMainWindow::slotToggleDemoMode()
void KReversiMainWindow::slotNewGame()
{
delete m_game;
m_game = new KReversiGame;
m_game->setComputerSkill( Preferences::skill() );
connect( m_game, SIGNAL(gameOver()), SLOT(slotGameOver()) );
if(KGGZMod::Module::isGGZ())
{
setCaption(i18n("Online game"));
......@@ -274,6 +269,10 @@ void KReversiMainWindow::slotNewGame()
if(m_historyView)
m_historyView->clear();
m_game = new KReversiGame;
m_game->setComputerSkill( Preferences::skill() );
connect( m_game, SIGNAL(gameOver()), SLOT(slotGameOver()) );
if(m_scene == 0) // if called first time
{
QString chipsPrefix = Preferences::useColoredChips() ? "chip_color_%1" : "chip_bw_%1";
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment