mirror of
https://github.com/RetroShare/RetroShare.git
synced 2025-05-02 22:25:04 -04:00
added game plugin solocards
git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@2346 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
parent
f2f23e7ece
commit
082d5732b0
92 changed files with 24978 additions and 0 deletions
434
plugins/qsolocards_plugin/GameBoard.cpp
Normal file
434
plugins/qsolocards_plugin/GameBoard.cpp
Normal file
|
@ -0,0 +1,434 @@
|
|||
/*
|
||||
QSoloCards is a collection of Solitaire card games written using Qt
|
||||
Copyright (C) 2009 Steve Moore
|
||||
|
||||
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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "GameBoard.h"
|
||||
#include <QtGui/QImage>
|
||||
#include "CardPixmaps.h"
|
||||
#include <QtGui/QResizeEvent>
|
||||
#include <QtGui/QCursor>
|
||||
#include <QtGui/QMessageBox>
|
||||
|
||||
#include "CardAnimationLock.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
GameBoard::GameBoard(QWidget * pParent,
|
||||
const QString & gameName,
|
||||
const QString & gameSettingsId)
|
||||
:QGraphicsView(pParent),
|
||||
m_scene(),
|
||||
m_sToSAniMove(),
|
||||
m_dealAni(),
|
||||
m_gameName(gameName),
|
||||
m_gameSettingsId(gameSettingsId),
|
||||
m_gamePixmap(":/images/sol32x32.png"),
|
||||
m_undoStack(),
|
||||
m_redoStack(),
|
||||
m_helpFile(""),
|
||||
m_numColsOrRows(1),
|
||||
m_resizeType(ResizeByWidth),
|
||||
m_demoRunning(false),
|
||||
m_pDemoSrcPrev(NULL),
|
||||
m_pDemoDstPrev(NULL),
|
||||
m_demoCardsPrev(),
|
||||
m_demoCardAniTime(GameBoard::DemoNormalCardAniTime),
|
||||
m_stacksCreated(false)
|
||||
{
|
||||
// set the background image
|
||||
this->setBackgroundBrush(QImage(":/images/greenfelt.png"));
|
||||
this->setCacheMode(QGraphicsView::CacheBackground);
|
||||
|
||||
// add the scene to the view.
|
||||
// and set it to rescale.
|
||||
this->setScene(&m_scene);
|
||||
|
||||
// turnoff the scroll bars on the view
|
||||
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
|
||||
|
||||
// hook up the animation signal for stack to stack moves. This will enable us
|
||||
// to update things just like it was a drag and drop move
|
||||
this->connect(&m_sToSAniMove,SIGNAL(cardsMoved(CardMoveRecord)),
|
||||
this,SLOT(slotCardsMoved(CardMoveRecord)));
|
||||
|
||||
this->connect(&m_dealAni,SIGNAL(cardsMoved(CardMoveRecord)),
|
||||
this,SLOT(slotCardsMoved(CardMoveRecord)));
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
GameBoard::~GameBoard()
|
||||
{
|
||||
CardAnimationLock::getInst().setDemoMode(false);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void GameBoard::setCardResizeAlg(unsigned int colsOrRows,CardResizeType resizeType)
|
||||
{
|
||||
if (colsOrRows<1)
|
||||
{
|
||||
colsOrRows=1;
|
||||
}
|
||||
|
||||
m_numColsOrRows=colsOrRows;
|
||||
|
||||
m_resizeType=resizeType;
|
||||
|
||||
this->updateCardSize(this->size());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void GameBoard::updateCardSize(const QSize & newSize)
|
||||
{
|
||||
if (GameBoard::ResizeByHeight==m_resizeType)
|
||||
{
|
||||
CardPixmaps::getInst().setCardHeight((newSize.height()-(LayoutSpacing*(m_numColsOrRows+1)))/m_numColsOrRows);
|
||||
}
|
||||
else
|
||||
{
|
||||
CardPixmaps::getInst().setCardWidth((newSize.width()-(LayoutSpacing*(m_numColsOrRows+1)))/m_numColsOrRows);
|
||||
}
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// ok go through and restore the last state of all stacks
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void GameBoard::undoMove()
|
||||
{
|
||||
if (!this->m_undoStack.empty())
|
||||
{
|
||||
CardMoveRecord moveRecord(m_undoStack.top());
|
||||
|
||||
CardStack::processCardMoveRecord(CardStack::UndoMove,m_undoStack.top());
|
||||
m_undoStack.pop();
|
||||
|
||||
// if we no longer have any undo info let users know.
|
||||
if (!this->canUndoMove())
|
||||
{
|
||||
emit undoAvail(false);
|
||||
}
|
||||
|
||||
bool canRedo=this->canRedoMove();
|
||||
|
||||
m_redoStack.push(moveRecord);
|
||||
|
||||
// if we didn't have a redo previously and now have one
|
||||
// emit a signal to tell listeners about it.
|
||||
if (!canRedo)
|
||||
{
|
||||
emit redoAvail(true);
|
||||
}
|
||||
|
||||
// calc the score with the changes
|
||||
this->calcScore();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// ok go through and redo the last state of all stacks
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void GameBoard::redoMove()
|
||||
{
|
||||
if (!this->m_redoStack.empty())
|
||||
{
|
||||
CardMoveRecord moveRecord(m_redoStack.top());
|
||||
|
||||
CardStack::processCardMoveRecord(CardStack::RedoMove,m_redoStack.top());
|
||||
m_redoStack.pop();
|
||||
|
||||
// emit a signal that we are out of redo info
|
||||
if (!this->canRedoMove())
|
||||
{
|
||||
emit redoAvail(false);
|
||||
}
|
||||
|
||||
bool canUndo=this->canUndoMove();
|
||||
m_undoStack.push(moveRecord);
|
||||
|
||||
// emit a signal that we now have undo info
|
||||
if (!canUndo)
|
||||
{
|
||||
emit undoAvail(true);
|
||||
}
|
||||
|
||||
// calc the score with the changes
|
||||
this->calcScore();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool GameBoard::canUndoMove() const
|
||||
{
|
||||
return !m_undoStack.empty();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool GameBoard::canRedoMove() const
|
||||
{
|
||||
return !m_redoStack.empty();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// adding some to the undo stack also means that the redo stack is cleared.
|
||||
// since
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void GameBoard::addUndoMove(const CardMoveRecord &moveRecord)
|
||||
{
|
||||
bool canUndo=this->canUndoMove();
|
||||
|
||||
m_undoStack.push(moveRecord);
|
||||
|
||||
// send a signal that we now have undo info
|
||||
if (!canUndo)
|
||||
{
|
||||
emit undoAvail(true);
|
||||
}
|
||||
|
||||
// clear the redo stack because we have made a move
|
||||
while(!m_redoStack.empty())
|
||||
{
|
||||
m_redoStack.pop();
|
||||
}
|
||||
|
||||
// since we have made a move the redo stack is now gone.
|
||||
emit redoAvail(false);
|
||||
|
||||
// calc the score with the changes
|
||||
this->calcScore();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void GameBoard::clearUndoRedoStacks()
|
||||
{
|
||||
while (!this->m_undoStack.empty())
|
||||
{
|
||||
m_undoStack.pop();
|
||||
}
|
||||
|
||||
while (!this->m_redoStack.empty())
|
||||
{
|
||||
m_redoStack.pop();
|
||||
}
|
||||
|
||||
emit undoAvail(false);
|
||||
emit redoAvail(false);
|
||||
|
||||
// calc the score with the changes
|
||||
this->calcScore();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void GameBoard::restartGame()
|
||||
{
|
||||
this->stopDemo();
|
||||
while (!this->m_undoStack.empty())
|
||||
{
|
||||
CardMoveRecord moveRecord(m_undoStack.top());
|
||||
|
||||
CardStack::processCardMoveRecord(CardStack::UndoMove,m_undoStack.top());
|
||||
m_undoStack.pop();
|
||||
}
|
||||
|
||||
this->clearUndoRedoStacks();
|
||||
|
||||
// update the screen for the new layout
|
||||
this->update();
|
||||
|
||||
// calc the score with the changes
|
||||
this->calcScore();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void GameBoard::showHint()
|
||||
{
|
||||
unsigned int index;
|
||||
CardStack * pFromStack=NULL;
|
||||
CardStack * pToStack=NULL;
|
||||
|
||||
// show hint if we found one.
|
||||
if (this->getHint(pFromStack,index,pToStack) && pToStack && pFromStack)
|
||||
{
|
||||
CardStack::showHint(pFromStack,index,pToStack);
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::critical(this,this->gameName(),
|
||||
tr("No move found involving full sets of movable cards. "
|
||||
"It might be possible to make a move not using the full set of movable cards.").trimmed());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void GameBoard::startDemo(GameBoard::DemoCardAniTime demoCardAniTime)
|
||||
{
|
||||
if (!m_demoRunning)
|
||||
{
|
||||
m_pDemoSrcPrev=NULL;
|
||||
m_pDemoDstPrev=NULL;
|
||||
m_demoCardsPrev.clear();
|
||||
|
||||
m_demoCardAniTime=demoCardAniTime;
|
||||
|
||||
m_demoRunning=true;
|
||||
CardAnimationLock::getInst().setDemoMode(true);
|
||||
emit demoStarted();
|
||||
runDemo();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void GameBoard::stopDemo()
|
||||
{
|
||||
if (m_demoRunning)
|
||||
{
|
||||
m_demoRunning=false;
|
||||
CardAnimationLock::getInst().setDemoMode(false);
|
||||
emit demoStopped();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void GameBoard::newGame()
|
||||
{
|
||||
m_dealAni.stopAni();
|
||||
m_sToSAniMove.stopAni();
|
||||
|
||||
stopDemo();
|
||||
|
||||
CardStack::clearAllStacks();
|
||||
CardStack::updateAllStacks();
|
||||
|
||||
// clear the undo and redo info
|
||||
this->clearUndoRedoStacks();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void GameBoard::slotCardsMoved(const CardMoveRecord & moveRecord)
|
||||
{
|
||||
// calc the score with the changes
|
||||
this->calcScore();
|
||||
|
||||
// if the move record is not empty add it.
|
||||
if (!moveRecord.empty())
|
||||
{
|
||||
this->addUndoMove(moveRecord);
|
||||
}
|
||||
|
||||
if (this->hasDemo()&& this->isDemoRunning())
|
||||
{
|
||||
runDemo();
|
||||
}
|
||||
// if all suits are sent home the game is over. Show a dialog stating that
|
||||
// and start the game over.
|
||||
if (this->isGameWon())
|
||||
{
|
||||
QMessageBox::information(this,this->gameName(),tr("Congratulations you won!").trimmed());
|
||||
this->newGame();
|
||||
}
|
||||
else if (CardAnimationLock::getInst().animationsEnabled() &&
|
||||
this->hasDemo() && !this->isDemoRunning() &&
|
||||
this->isGameWonNotComplete())
|
||||
{
|
||||
this->startDemo(DemoEndGameCardAniTime);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void GameBoard::resizeEvent (QResizeEvent * event)
|
||||
{
|
||||
QGraphicsView::resizeEvent(event);
|
||||
|
||||
this->updateCardSize(event->size());
|
||||
this->m_scene.setSceneRect(QRectF(QPointF(0,0),event->size()));
|
||||
|
||||
if (!m_stacksCreated)
|
||||
{
|
||||
m_stacksCreated=true;
|
||||
this->createStacks();
|
||||
}
|
||||
|
||||
CardStack::updateAllStacks();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool GameBoard::runDemo(bool stopWhenNoMore)
|
||||
{
|
||||
bool rc=false;
|
||||
unsigned int index;
|
||||
CardStack * pFromStack=NULL;
|
||||
CardStack * pToStack=NULL;
|
||||
PlayingCardVector moveCards;
|
||||
CardMoveRecord moveRecord;
|
||||
|
||||
// here we are looking to stop moving cards back and forth over and over
|
||||
// between two stacks
|
||||
if (this->getHint(pFromStack,index,pToStack) && pToStack && pFromStack)
|
||||
{
|
||||
rc=true;
|
||||
if (pFromStack->removeCardsStartingAt(index,moveCards,moveRecord,true))
|
||||
{
|
||||
if (m_pDemoSrcPrev==pToStack &&
|
||||
m_pDemoDstPrev==pFromStack &&
|
||||
m_demoCardsPrev==moveCards)
|
||||
{
|
||||
rc=false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if there is a hint perform the move
|
||||
if (rc)
|
||||
{
|
||||
pToStack->addCards(moveCards,moveRecord,true);
|
||||
|
||||
m_pDemoSrcPrev=pFromStack;
|
||||
m_pDemoDstPrev=pToStack;
|
||||
m_demoCardsPrev=moveCards;
|
||||
|
||||
this->m_sToSAniMove.moveCards(moveRecord,m_demoCardAniTime);
|
||||
}
|
||||
else if (stopWhenNoMore)
|
||||
{
|
||||
stopDemo();
|
||||
rc=false;
|
||||
}
|
||||
else
|
||||
{
|
||||
rc=false;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue