/*
 * kpuzzleapp.cpp
 *
 * Copyright (C) 1999 Michael Wand <mwand@gmx.de>
 */
#include "main.h"

#include <qpixmap.h>
#include <qpaintdevice.h> 
#include <qpainter.h>
#include <qcolor.h>
#include <qsize.h>
#include <qwmatrix.h>
#include <qbitmap.h>
#include <qmessagebox.h>
#include <qfiledialog.h>
#include <qdialog.h>

#include <kapp.h>

#include "kpuzzleapp.h"

#include "kpuzzle.h"
#include "kpuzzlewidget.h"
#include "gamewidget.h"
#include "piecewidget.h"
#include "picview.h"
#include "gamedialog.h"
#include "highscore.h"

#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include <stdlib.h>

// Why to change a score
#define SC_PIECE_RIGHT 1
#define SC_PIECE_WRONG 2
#define SC_COUNT_TIME 3
#define SC_BONUS 4

KPuzzleApp::KPuzzleApp(KPuzzleWidget* view)
{
	_mainWidget = view;

	_status = GS_NOT_STARTED;

	connect(this,SIGNAL(sigTerm(int)),this,SLOT(slotTerm(int)));

	connect(&_timer,SIGNAL(timeout()),this,SLOT(slotTimer()));
}

bool KPuzzleApp::initialize()
{
	_picview = mainWidget()->picview();
	_fullview = mainWidget()->fullview();
	_mainPixmap = new QPixmap(_filename);
	if (_mainPixmap->isNull()) {
		return false;
	}
	_gamePixmap = new QPixmap(pixmapSize());
	QPainter pt;
	pt.begin(_gamePixmap);
	pt.setBackgroundColor(QColor(0,0,0));
	pt.eraseRect(QRect(QPoint(0,0),pixmapSize()));
	pt.end();	

	calcPiecesCount();
	_maskCache = new QCache<QBitmap>;

	ASSERT(_piecesCount.width() >= 3);
	ASSERT(_piecesCount.height() >= 3);

	_pieceSize = QSize(pixmapSize().width() / _piecesCount.width(),
			  pixmapSize().height() / _piecesCount.height());
	
	_pieceList = new QList<PieceState>;
	_pieceList->setAutoDelete(true);
	minglePieces();

	_currentPieceNr = 0;
	_currentPiece = new QPixmap(pieceSizeDisp());
	getPiece();

	_gameStatus = (char*) malloc(piecesTotal());
	memset(_gameStatus,0,piecesTotal());

	_picview->updatePixmap(_gamePixmap,_gamePixmap->rect());
	_fullview->updatePixmap(_mainPixmap,_mainPixmap->rect());

	setScore(0);

	_elapsed = 0;

	initGameData();

	mainWidget()->updateButtons(false,false,
		pixmapSize().width() > mainWidget()->gameWidget()->width(),
		pixmapSize().height() > mainWidget()->gameWidget()->height());
	mainWidget()->gameWidget()->initialize(pixmapSize());

	char timeStr[6];
	snprintf(timeStr,5,"%i:%i",_scoreData.maxTime / 60,_scoreData.maxTime % 60);
	mainWidget()->time()->display(timeStr);

	startTimer();
	setStatus(GS_RUNNING);
	
	return true;
}

void KPuzzleApp::done()
{
	_picview = NULL;
	_fullview = NULL;

	ASSERT(_pieceList != NULL);
	while (!_pieceList->isEmpty()) _pieceList->removeFirst(); // deleted automatically
	delete _pieceList;

	if (_maskCache) delete _maskCache;

	if (_currentPiece) delete _currentPiece;

	delete _mainPixmap;

	delete _gamePixmap;

	free(_gameStatus);
}

KPuzzleApp::~KPuzzleApp()
{
	if (status() != GS_NOT_STARTED) done();
}

void KPuzzleApp::slotNewGame()
{
	if (status() != GS_NOT_STARTED) {
		if (QMessageBox::warning(0,"Start new game","A game is already running. Start a new one?",
				     "Yes","No",NULL,0,1) == 1) return;
	}
	_filename = QFileDialog::getOpenFileName(PUZZLE_DIR + "levels/","*.bmp",mainWidget(),"Open Image");
	if (_filename.isNull()) return;
	CGameDialog gd(mainWidget());
	if (gd.exec() != QDialog::Accepted) return;

	if (status() != GS_NOT_STARTED) emit sigTerm(TM_FORCE);

	_dialog_pieceSize = gd.pieceSize();
	_gameType = gd.gameType();
	_difficulty = gd.difficulty();
	_scale = true;
	_useMask = gd.useMask();
	
	mainWidget()->createPlayground(_gameType == UNBEARABLE_GAME);
	initialize();
}

void KPuzzleApp::slotShowLarge()
{
	if (status() != GS_RUNNING) return;
	pause(true);
	mainWidget()->setLargePxm(new QPixmap(getLargePixmap(mainWidget()->size())));
	setStatus(GS_SHOW_LARGE);
	mainWidget()->update();
}

void KPuzzleApp::slotPause()
{
	switch (status()) {
	case GS_RUNNING: 
		pause(true);
		break;
	case GS_PAUSED: 
		pause(false);
		break;
	}
}

void KPuzzleApp::slotPauseToggle(bool on)
{
	if ((status() == GS_PAUSED && on) || (status() == GS_RUNNING && !on)) return;
	slotPause();
}	

void KPuzzleApp::initGameData()
{
	int tt = piecesTotal();
	int r; // score for placing a piece correctly

	_scoreData.maxFaults = -1;
	_scoreData.maxPieceTime = -1;
	_scoreData.maxRounds = -1;
		
	switch (_difficulty) {
	case 0: // easy
		r = 50;
		_scoreData.maxTime = tt * 60; 
		_scoreData.score1Time = tt * 10;
		_scoreData.score2Time = tt * 20;
		_scoreData.score3Time = tt * 30;
		_scoreData.timeScore1 = tt * r / 10;
		_scoreData.timeScore2 = tt * r / 15;
		_scoreData.timeScore3 = tt * r / 20;
		_scoreData.rightPieceScore = r;
		_scoreData.wrongPieceScore = 0;
		
		switch (_gameType) {
		case STD_GAME:
			_scoreData.bonus = 0;
			break;
		case PIECE_TIME_GAME:
			_scoreData.bonus = tt * r / 15;
			_scoreData.maxPieceTime = 60;
			break;
		case PIECE_FAULTS_GAME:
			_scoreData.bonus = tt * r / 20;
			_scoreData.maxFaults = 10;
			break;
		case FAULTS_SUM_GAME:
			_scoreData.bonus = tt * r / 20;
			_scoreData.maxFaults = 9 * tt;
			_faults = 0;
			break;
		case UNBEARABLE_GAME:
			_scoreData.bonus = tt * r / 10;
			_scoreData.maxPieceTime = 15;
			_scoreData.maxRounds = 5;
			_rounds = 0;
			break;	
		}
		break;

	case 1: // medium
		r = 70;
		_scoreData.maxTime = tt * 50; 
		_scoreData.score1Time = tt * 15;
		_scoreData.score2Time = tt * 25;
		_scoreData.score3Time = tt * 35;
		_scoreData.timeScore1 = tt * r / 10;
		_scoreData.timeScore2 = tt * r / 15;
		_scoreData.timeScore3 = tt * r / 20;
		_scoreData.rightPieceScore = r;
		_scoreData.wrongPieceScore = 10;
		
		switch (_gameType) {
		case STD_GAME:
			_scoreData.bonus = tt * r / 20;
			break;
		case PIECE_TIME_GAME:
			_scoreData.bonus = tt * r / 12;
			_scoreData.maxPieceTime = 50;
			break;
		case PIECE_FAULTS_GAME:
			_scoreData.bonus = tt * r / 16;
			_scoreData.maxFaults = 8;
			break;
		case FAULTS_SUM_GAME:
			_scoreData.bonus = tt * r / 16;
			_scoreData.maxFaults = 7 * tt;
			_faults = 0;
			break;
		case UNBEARABLE_GAME:
			_scoreData.bonus = tt * r / 6;
			_scoreData.maxPieceTime = 12;
			_scoreData.maxRounds = 4;
			_rounds = 0;
			break;	
		}
		break;

	case 2: // hard
		r = 90;
		_scoreData.maxTime = tt * 40;
		_scoreData.score1Time = tt * 20;
		_scoreData.score2Time = tt * 30;
		_scoreData.score3Time = tt * 40;
		_scoreData.timeScore1 = tt * r / 5;
		_scoreData.timeScore2 = tt * r / 10;
		_scoreData.timeScore3 = tt * r / 15;
		_scoreData.rightPieceScore = r;
		_scoreData.wrongPieceScore = 20;
		
		switch (_gameType) {
		case STD_GAME:
			_scoreData.bonus = tt * r / 15;
			break;
		case PIECE_TIME_GAME:
			_scoreData.bonus = tt * r / 10;
			_scoreData.maxPieceTime = 40;
			break;
		case PIECE_FAULTS_GAME:
			_scoreData.bonus = tt * r / 12;
			_scoreData.maxFaults = 6;
			break;
		case FAULTS_SUM_GAME:
			_scoreData.bonus = tt * r / 12;
			_scoreData.maxFaults = 5 * tt;
			_faults = 0;
			break;
		case UNBEARABLE_GAME:
			_scoreData.bonus = tt * r / 3;
			_scoreData.maxPieceTime = 10;
			_scoreData.maxRounds = 3;
			_rounds = 0;
			break;	
		}
		break;
	}

}

void KPuzzleApp::calcPiecesCount()
{
	int tcx;
	int tcy;
	switch(_dialog_pieceSize) {
	case 0: tcx = 88; tcy = 66; _displace = maskedPieces() ? 19 : 0; break;
	case 1: tcx = 100; tcy = 75; _displace = maskedPieces() ? 21 : 0; break;
	case 2: tcx = 112; tcy = 84; _displace = maskedPieces() ? 24 : 0; break;
	case 3: tcx = 132; tcy = 99; _displace = maskedPieces() ? 28 : 0; break;
	case 4: tcx = 140; tcy = 105; _displace = maskedPieces() ? 30 : 0; break;
	}
	if (pixmapSize().width() % tcx) { //TODO
		QWMatrix m;
		float scaleVal = (float) ((pixmapSize().width() / tcx + 1) * 
                        tcx) / pixmapSize().width();
		m.scale(scaleVal,scaleVal);
		QPixmap* pxm = new QPixmap(_mainPixmap->xForm(m));
		delete _mainPixmap;
		_mainPixmap = pxm;

		pxm = new QPixmap(_gamePixmap->xForm(m));
		delete _gamePixmap;
		_gamePixmap = pxm;
	}
	
	_piecesCount = QSize(pixmapSize().width() / tcx,pixmapSize().height() / tcy);
}

bool KPuzzleApp::setNextPiece(bool currentInvalid,bool forceUpdate)
	// currentInvalid means that the current piece does no longer exist
	// this function must also be improved
{
	int newNr = _currentPieceNr;
	int maxNr = availablePiecesCount() - 1;
	int startNr = newNr;

	if (maxNr == -1) {
		emit sigTerm(TM_WON);
		return false; 
	}
	if (maxNr == 0) {
		if (currentInvalid) {
			if (!pieceAvailable(0)) {
				emit sigTerm(TM_LOST);
				return false;
			}
			_currentPieceNr = 0;
			getPiece();
			return true;
		} 
		if (forceUpdate) {
			emit sigTerm(TM_LOST);
			return false;
		}
		return false; // No change
		
	}

	if (!currentInvalid) newNr++;
	if (newNr > maxNr) newNr = 0;
	if (startNr > maxNr) startNr = 0;

	while (!pieceAvailable(newNr)) {
		newNr++;
		if (newNr > maxNr) newNr = 0;
		if (newNr == startNr && (forceUpdate || currentInvalid)) {
			emit sigTerm(TM_LOST);
			return false;
		} 
	}	

	
	_currentPieceNr = newNr;
	getPiece();
 	return true; // redraw


}

bool KPuzzleApp::setPrevPiece(bool currentInvalid)
{
 	int newNr = _currentPieceNr;
 	int maxNr = availablePiecesCount() - 1;

	if (maxNr == -1) {
		emit sigTerm(TM_WON);
		return false; 
	}
	if (maxNr == 0) return false; // No change

	do {
		newNr--;
		if (newNr < 0) newNr = maxNr;
		if (newNr == _currentPieceNr) {
			emit sigTerm(TM_LOST);
			return false;
		}
	} while (!pieceAvailable(newNr));
	
	_currentPieceNr = newNr;
	getPiece();
 	return true; // redraw
}

bool KPuzzleApp::setPiece(QPoint pos)
{
	if (pieceState()->pos != pos) { // Wrong place
		changeScore(SC_PIECE_WRONG);
		if (_gameType == PIECE_FAULTS_GAME) {
			pieceState()->faults++;
			if (pieceState()->faults > _scoreData.maxFaults) {
				setNextPiece(false,true);
				updateAll(); 
			}
			return true;
		}
		if (_gameType == FAULTS_SUM_GAME) {
			_faults++;
			if (_faults > _scoreData.maxFaults) 
				emit sigTerm(TM_LOST);
			return false;
		}
		return false;
	}
	if (_pieceList->at(_currentPieceNr)->turn != 0) { 
		// The piece is not turned correctly
		changeScore(SC_PIECE_WRONG);
		if (_gameType == PIECE_FAULTS_GAME) {
			pieceState()->faults++;
			if (pieceState()->faults > _scoreData.maxFaults) {
				setNextPiece(false,true);
				updateAll();
			}
			return true;
		}
		if (_gameType == FAULTS_SUM_GAME) {
			_faults++;
			if (_faults > _scoreData.maxFaults) 
				emit sigTerm(TM_LOST);
			return false;
		}
		return false;
	}
	QPoint tpos(pos.x() * pieceSize().width(),pos.y() * pieceSize().height());
	if (maskedPieces()) {
		tpos -= QPoint(_displace,_displace);
		bitBlt(_gamePixmap,tpos,_currentPiece,QRect(QPoint(0,0),pieceSizeDisp()));
	} else {
		bitBlt(_gamePixmap,tpos,_currentPiece,QRect(QPoint(0,0),pieceSize()));
	}
	_picview->addPiece(_currentPiece,_pieceList->at(_currentPieceNr)->pos);
	_pieceList->remove(_currentPieceNr);
	if (!setNextPiece(true)) return false; 
	// If false is returned, the game has been terminated
	updateAll();
	changeScore(SC_PIECE_RIGHT);
	return true;
}

bool KPuzzleApp::pieceAvailable(int nr)
{
	switch (_gameType) {
	case PIECE_FAULTS_GAME: 
		return _pieceList->at(nr)->faults <= _scoreData.maxFaults;
	case PIECE_TIME_GAME: 
		return _pieceList->at(nr)->time <= _scoreData.maxPieceTime;
	}
	return true;
}

void KPuzzleApp::minglePieces()
{
	ASSERT(_pieceList->isEmpty());
	for (int j = 0;j < _piecesCount.height();j++)
		for (int i = 0;i < _piecesCount.width();i++) {
			PieceState* ts = new PieceState;
			ts->pos = QPoint(i,j);
			ts->turn = rand() % 4;
			ts->time = 0;
			ts->faults = 0;
			_pieceList->insert(rand() % 
				(j * _piecesCount.width() + i + 1),ts);
		}
		     
}

//void KPuzzleApp::getPiece(QPixmap* dst,int nr)
void KPuzzleApp::getPiece()
{
	QPoint pos(_pieceList->at(_currentPieceNr)->pos);
	QPoint realPos;
	if (maskedPieces()) {
		// If we aren't at the left/top border, we copy _displace pixels more at the left/top side
		realPos = QPoint(pos.x() * pieceSize().width() - (pos.x() != 0 ? _displace : 0),
				 pos.y() * pieceSize().height() - (pos.y() != 0 ? _displace : 0));
		// If we aren't at a border at all, we need 2 * _displace
		QSize copySize(pieceSize().width() + _displace + 
			       ((pos.x() && pos.x() < piecesCount().width() - 1) ? _displace : 0),
			       pieceSize().height() + _displace +
			       ((pos.y() && pos.y() < piecesCount().height() - 1) ? _displace : 0));
		// If we copy less, the destination position must be adjusted
		QPoint copyTo(pos.x() ? 0 : _displace,pos.y() ? 0 : _displace);
 		bitBlt(_currentPiece,copyTo,mainPixmap(),QRect(realPos,copySize),CopyROP,false);
		_currentPiece->setMask(*getPieceMask(pos.x(),pos.y()));
	} else {
		realPos = QPoint(pos.x() * pieceSize().width(),pos.y() * pieceSize().height());
		bitBlt(_currentPiece,QPoint(0,0),mainPixmap(),QRect(realPos,pieceSize()),CopyROP,false);
	}
}

QBitmap* KPuzzleApp::getPieceMask(int x,int y)
{
	ASSERT(_maskCache);
	QBitmap* ret;
	QString resName;
	// Calculate variant (1,2) and type of the piece
	int variant = ((x + y) % 2 ? 2 : 1);
	resName.sprintf("piece%i",variant);
	if (!x) resName += "-l";
	if (x == piecesCount().width() - 1) resName += "-r";
	if (!y) resName += "-t";
	if (y == piecesCount().height() - 1) resName += "-b";
	if ((ret = _maskCache->find(resName))) return ret;
	QPixmap pxm(DATAFILE(resName + ".bmp"));
	ret = new QBitmap;
	*ret = pxm;
	if (ret->width() != pieceSizeDisp().width() || ret->height() != pieceSizeDisp().height()) {
		QBitmap* temp = new QBitmap;
		QWMatrix mx;
		mx.scale((float) pieceSizeDisp().width() / ret->width(),
			 (float) pieceSizeDisp().height() / ret->height());
		*temp = ret->xForm(mx);
		delete ret;
		ret = temp;
	}
	_maskCache->insert(resName,ret);
	return ret;
}

QPixmap* KPuzzleApp::currentPieceTurned()
{
	int turn = _pieceList->at(_currentPieceNr)->turn;
	QWMatrix trs((turn & TURN_LR ? -1 : 1),0,0,(turn & TURN_UD ? -1 : 1),0,0);
	QPixmap* ret = new QPixmap(currentPiece()->xForm(trs));
	return ret;
}

QPixmap KPuzzleApp::getLargePixmap(QSize size)
{
	float scaleX = (float) size.width() / gamePixmap()->width(); 
	// With this factor, the width of
	// the scaled picture is equal to the width of the window
	float scaleY = (float) size.height() / gamePixmap()->height(); 
	// same with height

	QWMatrix m;
	m.scale(min(scaleX,scaleY),min(scaleX,scaleY));
	QPixmap pxm = gamePixmap()->xForm(m);
	return pxm;
}

void KPuzzleApp::updateAll()
{
	mainWidget()->updateAll();
}

void KPuzzleApp::changeScore(char reason)
{
	int add = 0;
	switch(reason) {
	case SC_PIECE_RIGHT: setScore(score() + _scoreData.rightPieceScore);
		break;
	case SC_PIECE_WRONG: 
		if (score() > 0) 
			setScore(score() > _scoreData.wrongPieceScore ? 
				 score() - _scoreData.wrongPieceScore : 1);
		break;
	case SC_COUNT_TIME: 
		if (elapsed() < _scoreData.score3Time) 
			add = _scoreData.timeScore3;
		if (elapsed() < _scoreData.score2Time) 
			add = _scoreData.timeScore2;
		if (elapsed() < _scoreData.score1Time) 
			add = _scoreData.timeScore1;
		setScore(score() + add);
		break;
	case SC_BONUS: setScore(score() + _scoreData.bonus);
		break;
	}
	
}

void KPuzzleApp::showHighscoreDialog()
{
	CHighscoreDialog hs(mainWidget()->parentWidget(),score());
	hs.initializeDialog();
	hs.exec();
	
	
}

void KPuzzleApp::setStatus(int s)
{
	int enable;
	_status = s;
	mainWidget()->hideStatusMsg();
	switch(s) {
	case GS_NOT_STARTED:
		enable = MI_NONE;

		done();

		break;

	case GS_RUNNING:
		enable = MI_STOP_GAME | MI_PAUSE | MI_SHOW_LARGE;

		mainWidget()->freeGamePixmap(GP_BIGLOGO);
		mainWidget()->freeGamePixmap(GP_PAUSE);
		
		break;

	case GS_WINNING:
		enable = MI_STOP_GAME;

		mainWidget()->showStatusMsg("Press mouse key to continue");
		mainWidget()->showAll(false);
		mainWidget()->useGamePixmap(GP_WIN);
		mainWidget()->setLargePxm(NULL);

		break;

	case GS_SHOW_LARGE:
		enable = MI_STOP_GAME;

		mainWidget()->showStatusMsg("Press mouse key to continue");

		break;

	case GS_SHOW_LARGE_WINNING:
		enable = MI_STOP_GAME;

		mainWidget()->showStatusMsg("Press mouse key to continue");
		mainWidget()->setLargePxm(new QPixmap(getLargePixmap(mainWidget()->size())));
		mainWidget()->freeGamePixmap(GP_WIN);

		break;

	case GS_LOSING:
		enable = MI_STOP_GAME;

		mainWidget()->showStatusMsg("Press mouse key to continue");
		mainWidget()->showAll(false);
		mainWidget()->useGamePixmap(GP_LOSE);
		mainWidget()->setLargePxm(NULL);

		break;

	case GS_SHOW_LARGE_LOSING:
		enable = MI_STOP_GAME;

		mainWidget()->showStatusMsg("Press mouse key to continue");
		mainWidget()->setLargePxm(new QPixmap(getLargePixmap(mainWidget()->size())));
		mainWidget()->freeGamePixmap(GP_LOSE);

		break;

	case GS_SHOW_HIGHSCORES:
		enable = MI_NONE;

		showHighscoreDialog();
		mainWidget()->destroyPlayground();
		setStatus(GS_NOT_STARTED);
		mainWidget()->update();

		break;

	case GS_PAUSED:
		enable = MI_STOP_GAME;

		mainWidget()->showStatusMsg("Press mouse key to continue");
		mainWidget()->useGamePixmap(GP_PAUSE);

		break;
	}
	TOPWIDGET->enableMenuItems(enable);
}

void KPuzzleApp::pause(bool p)
{
	if (p) {
		if (status() == GS_PAUSED) return;
		stopTimer();
		setStatus(GS_PAUSED);
		mainWidget()->showAll(false);
		mainWidget()->update();
	} else {
		if (status() == GS_RUNNING) return;
		startTimer();
		setStatus(GS_RUNNING);
		mainWidget()->showAll(true);
		mainWidget()->update();
	}

}

void KPuzzleApp::slotTimer()
{
	_elapsed++;
	int rest = _scoreData.maxTime - _elapsed;
	char s[10];
	snprintf(s,9,"%i:%2i",rest / 60,rest % 60);
	mainWidget()->time()->display(s);
	// Something has to be done, dependent on the game type
	PieceState* current = _pieceList->at(_currentPieceNr);
	switch (_gameType) {
	case PIECE_TIME_GAME: 
		current->time++;
		if (current->time > _scoreData.maxPieceTime) {
			if (availablePiecesCount() == 1) {
				emit sigTerm(TM_LOST);
				return;
			}
			if (setNextPiece(false,true)) {
				mainWidget()->pieceWidget()->update();
				mainWidget()->gameWidget()->update();
			}
		}
		break;
	case UNBEARABLE_GAME:
		current->time++;
		if (current->time > _scoreData.maxPieceTime) {
			current->time = 0;
			if (setNextPiece(false,true)) {
				mainWidget()->pieceWidget()->update();
				mainWidget()->gameWidget()->update(); //TODO
			}
			if (_currentPieceNr == 0) _rounds++;
			if (_rounds > _scoreData.maxRounds) {
				emit sigTerm(TM_LOST);
				return;
			}
		}
		break;
	}

} 

void KPuzzleApp::slotTerm(int reason)
{
	stopTimer();
	switch (reason) {
	case TM_WON:
		changeScore(SC_COUNT_TIME);
		changeScore(SC_BONUS);
		setStatus(GS_WINNING);
		mainWidget()->update();
		break;
	case TM_LOST:
		setStatus(GS_LOSING);
		mainWidget()->update();
		break;
	case TM_QUIT:
		setStatus(GS_LOSING);
		mainWidget()->update();
		break;

	// If reason is TM_FORCE, _status should be GS_NOT_STARTED when leaving, i.e.
	// the game should be in its initial state
	case TM_FORCE:
		switch (status()) {
		case GS_RUNNING:
		case GS_PAUSED:
		case GS_SHOW_LARGE:
		case GS_SHOW_LARGE_WINNING:
		case GS_SHOW_LARGE_LOSING:
			mainWidget()->destroyPlayground();
			setStatus(GS_NOT_STARTED);
			break;
		case GS_WINNING:
		case GS_LOSING:
			// Nothing more currently
			break;
		}

		setStatus(GS_NOT_STARTED);
		mainWidget()->update();
		return;
	}

}
