diff --git a/clock.cpp b/clock.cpp index c6f324e..f79236c 100644 --- a/clock.cpp +++ b/clock.cpp @@ -1,165 +1,165 @@ /* * Copyright (C) 2000-2009 Stephan Kulow * Copyright (C) 2010 Parker Coates * * License of original code: * ------------------------------------------------------------------------- * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, * provided that the above copyright notice appear in all copies and that * both that copyright notice and this permission notice appear in * supporting documentation. * * This file is provided AS IS with no warranties of any kind. The author * shall have no liability with respect to the infringement of copyrights, * trade secrets or any patents by this file or any part thereof. In no * event will the author be liable for any lost revenue or profits or * other special, indirect and consequential damages. * ------------------------------------------------------------------------- * * License of modifications/additions made after 2009-01-01: * ------------------------------------------------------------------------- * 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, see . * ------------------------------------------------------------------------- */ #include "clock.h" #include "dealerinfo.h" #include "patsolve/clocksolver.h" #include Clock::Clock( const DealerInfo * di ) : DealerScene( di ) { } void Clock::initialize() { setSceneAlignment( AlignHCenter | AlignVCenter ); setDeckContents(); const qreal dist_x = 1.11; const qreal ys[12] = { 0./96, 15./96, 52./96, 158./96, 264./96, 301./96, 316./96, 301./96, 264./96, 158./96, 52./96, 15./96}; const qreal xs[12] = { 200./72, 280./72, 360./72, 400./72, 360./72, 280./72, 200./72, 120./72, 40./72, 0./72, 40./72, 120./72}; for ( int i = 0; i < 12; ++i ) { target[i] = new PatPile( this, i + 1, QStringLiteral("target%1").arg(i) ); target[i]->setPileRole(PatPile::Foundation); target[i]->setLayoutPos(4 * dist_x + 0.4 + xs[i], 0.2 + ys[i]); target[i]->setSpread(0, 0); target[i]->setKeyboardSelectHint( KCardPile::NeverFocus ); target[i]->setKeyboardDropHint( KCardPile::ForceFocusTop ); } for ( int i = 0; i < 8; ++i ) { store[i] = new PatPile( this, 14 + i, QStringLiteral("store%1").arg(i) ); store[i]->setPileRole(PatPile::Tableau); store[i]->setLayoutPos(dist_x*(i%4), 2.5 * (i/4)); store[i]->setBottomPadding( 1.3 ); store[i]->setKeyboardSelectHint( KCardPile::AutoFocusTop ); store[i]->setKeyboardDropHint( KCardPile::AutoFocusTop ); } setActions(DealerScene::Hint | DealerScene::Demo); setSolver( new ClockSolver( this ) ); } void Clock::restart( const QList & cards ) { static const KCardDeck::Suit suits[12] = { KCardDeck::Diamonds, KCardDeck::Spades, KCardDeck::Hearts, KCardDeck::Clubs, KCardDeck::Diamonds, KCardDeck::Spades, KCardDeck::Hearts, KCardDeck::Clubs, KCardDeck::Diamonds, KCardDeck::Spades, KCardDeck::Hearts, KCardDeck::Clubs }; static const KCardDeck::Rank ranks[12] = { KCardDeck::Nine, KCardDeck::Ten, KCardDeck::Jack, KCardDeck::Queen, KCardDeck::King, KCardDeck::Two, KCardDeck::Three, KCardDeck::Four, KCardDeck::Five, KCardDeck::Six, KCardDeck::Seven, KCardDeck::Eight }; const QPointF center = ( target[0]->pos() + target[6]->pos() ) / 2; int j = 0; QList cardList = cards; while ( !cardList.isEmpty() ) { KCard * c = cardList.takeLast(); for ( int i = 0; i < 12; ++i ) { if ( c->rank() == ranks[i] && c->suit() == suits[i] ) { QPointF initPos = (2 * center + target[(i + 2) % 12]->pos()) / 3; addCardForDeal( target[i], c, true, initPos ); c = nullptr; break; } } if ( c ) { addCardForDeal( store[j], c, true, store[ j < 4 ? 0 : 4 ]->pos() ); j = (j + 1) % 8; } } startDealAnimation(); } bool Clock::drop() { return false; } bool Clock::checkAdd(const PatPile * pile, const QList & oldCards, const QList & newCards) const { if ( pile->pileRole() == PatPile::Tableau ) { return oldCards.isEmpty() || newCards.first()->rank() == oldCards.last()->rank() - 1; } else { return oldCards.last()->suit() == newCards.first()->suit() && ( newCards.first()->rank() == oldCards.last()->rank() + 1 || ( oldCards.last()->rank() == KCardDeck::King && newCards.first()->rank() == KCardDeck::Ace ) ); } } bool Clock::checkRemove(const PatPile* pile, const QList & cards) const { return pile->pileRole() == PatPile::Tableau && cards.first() == pile->topCard(); } static class ClockDealerInfo : public DealerInfo { public: ClockDealerInfo() : DealerInfo(I18N_NOOP("Grandfather's Clock"), GrandfathersClockId) {} - DealerScene *createGame() const Q_DECL_OVERRIDE + DealerScene *createGame() const override { return new Clock( this ); } } clockDealerInfo; diff --git a/clock.h b/clock.h index 1444c6e..0522772 100644 --- a/clock.h +++ b/clock.h @@ -1,65 +1,65 @@ /* * Copyright (C) 2000-2009 Stephan Kulow * * License of original code: * ------------------------------------------------------------------------- * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, * provided that the above copyright notice appear in all copies and that * both that copyright notice and this permission notice appear in * supporting documentation. * * This file is provided AS IS with no warranties of any kind. The author * shall have no liability with respect to the infringement of copyrights, * trade secrets or any patents by this file or any part thereof. In no * event will the author be liable for any lost revenue or profits or * other special, indirect and consequential damages. * ------------------------------------------------------------------------- * * License of modifications/additions made after 2009-01-01: * ------------------------------------------------------------------------- * 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, see . * ------------------------------------------------------------------------- */ #ifndef CLOCK_H #define CLOCK_H #include "dealer.h" class Clock : public DealerScene { Q_OBJECT public: explicit Clock( const DealerInfo * di ); - void initialize() Q_DECL_OVERRIDE; + void initialize() override; protected: - bool checkAdd(const PatPile * pile, const QList & oldCards, const QList & newCards) const Q_DECL_OVERRIDE; - bool checkRemove(const PatPile* pile, const QList & cards) const Q_DECL_OVERRIDE; - void restart( const QList & cards ) Q_DECL_OVERRIDE; + bool checkAdd(const PatPile * pile, const QList & oldCards, const QList & newCards) const override; + bool checkRemove(const PatPile* pile, const QList & cards) const override; + void restart( const QList & cards ) override; protected slots: - bool drop() Q_DECL_OVERRIDE; + bool drop() override; private: PatPile* store[8]; PatPile* target[12]; friend class ClockSolver; }; #endif diff --git a/dealer.cpp b/dealer.cpp index ead98ce..f55d620 100644 --- a/dealer.cpp +++ b/dealer.cpp @@ -1,2104 +1,2104 @@ /* * Copyright (C) 1995 Paul Olav Tvete * Copyright (C) 2000-2009 Stephan Kulow * Copyright (C) 2009-2010 Parker Coates * * License of original code: * ------------------------------------------------------------------------- * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, * provided that the above copyright notice appear in all copies and that * both that copyright notice and this permission notice appear in * supporting documentation. * * This file is provided AS IS with no warranties of any kind. The author * shall have no liability with respect to the infringement of copyrights, * trade secrets or any patents by this file or any part thereof. In no * event will the author be liable for any lost revenue or profits or * other special, indirect and consequential damages. * ------------------------------------------------------------------------- * * License of modifications/additions made after 2009-01-01: * ------------------------------------------------------------------------- * 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, see . * ------------------------------------------------------------------------- */ #include "dealer.h" #include "dealerinfo.h" #include "kpat_debug.h" #include "messagebox.h" #include "renderer.h" #include "shuffle.h" #include "speeds.h" #include "patsolve/solverinterface.h" #include "view.h" #include "KCardTheme" #include #include #include #include #include #include #include #include #include #include namespace { const qreal wonBoxToSceneSizeRatio = 0.7; QString solverStatusMessage( int status, bool everWinnable ) { switch ( status ) { case SolverInterface::SolutionExists: return i18n("Solver: This game is winnable."); case SolverInterface::NoSolutionExists: return everWinnable ? i18n("Solver: This game is no longer winnable.") : i18n("Solver: This game cannot be won."); case SolverInterface::UnableToDetermineSolvability: return i18n("Solver: Unable to determine if this game is winnable."); case SolverInterface::SearchAborted: case SolverInterface::MemoryLimitReached: default: return QString(); } } int readIntAttribute( const QXmlStreamReader & xml, const QString & key, bool * ok = nullptr ) { QStringRef value = xml.attributes().value( key ); return QString::fromRawData( value.data(), value.length() ).toInt( ok ); } QString suitToString( int suit ) { switch ( suit ) { case KCardDeck::Clubs: return QStringLiteral("clubs"); case KCardDeck::Diamonds: return QStringLiteral("diamonds"); case KCardDeck::Hearts: return QStringLiteral("hearts"); case KCardDeck::Spades: return QStringLiteral("spades"); default: return QString(); } } QString rankToString( int rank ) { switch ( rank ) { case KCardDeck::Ace: return QStringLiteral("ace"); case KCardDeck::Two: return QStringLiteral("two"); case KCardDeck::Three: return QStringLiteral("three"); case KCardDeck::Four: return QStringLiteral("four"); case KCardDeck::Five: return QStringLiteral("five"); case KCardDeck::Six: return QStringLiteral("six"); case KCardDeck::Seven: return QStringLiteral("seven"); case KCardDeck::Eight: return QStringLiteral("eight"); case KCardDeck::Nine: return QStringLiteral("nine"); case KCardDeck::Ten: return QStringLiteral("ten"); case KCardDeck::Jack: return QStringLiteral("jack"); case KCardDeck::Queen: return QStringLiteral("queen"); case KCardDeck::King: return QStringLiteral("king"); default: return QString(); } } } class SolverThread : public QThread { Q_OBJECT public: SolverThread( SolverInterface * solver ) : m_solver( solver ) { } - void run() Q_DECL_OVERRIDE + void run() override { SolverInterface::ExitStatus result = m_solver->patsolve(); emit finished( result ); } void abort() { m_solver->stopExecution(); wait(); } signals: void finished( int result ); private: SolverInterface * m_solver; }; int DealerScene::moveCount() const { return m_loadedMoveCount + m_undoStack.size(); } void DealerScene::saveLegacyFile( QIODevice * io ) { QXmlStreamWriter xml( io ); xml.setCodec( "UTF-8" ); xml.setAutoFormatting( true ); xml.setAutoFormattingIndent( -1 ); xml.writeStartDocument(); xml.writeDTD( QStringLiteral("") ); xml.writeStartElement( QStringLiteral("dealer") ); xml.writeAttribute( QStringLiteral("id"), QString::number( gameId() ) ); xml.writeAttribute( QStringLiteral("options"), getGameOptions() ); xml.writeAttribute( QStringLiteral("number"), QString::number( gameNumber() ) ); xml.writeAttribute( QStringLiteral("moves"), QString::number( moveCount() ) ); xml.writeAttribute( QStringLiteral("started"), QString::number( m_dealStarted ) ); xml.writeAttribute( QStringLiteral("data"), getGameState() ); foreach( const PatPile * p, patPiles() ) { xml.writeStartElement( QStringLiteral("pile") ); xml.writeAttribute( QStringLiteral("index"), QString::number( p->index() ) ); xml.writeAttribute( QStringLiteral("z"), QString::number( p->zValue() ) ); foreach( const KCard * c, p->cards() ) { xml.writeStartElement( QStringLiteral("card") ); xml.writeAttribute( QStringLiteral("suit"), QString::number( c->suit() ) ); xml.writeAttribute( QStringLiteral("value"), QString::number( c->rank() ) ); xml.writeAttribute( QStringLiteral("faceup"), QString::number( c->isFaceUp() ) ); xml.writeAttribute( QStringLiteral("z"), QString::number( c->zValue() ) ); xml.writeEndElement(); } xml.writeEndElement(); } xml.writeEndElement(); xml.writeEndDocument(); m_dealWasJustSaved = true; } bool DealerScene::loadLegacyFile( QIODevice * io ) { resetInternals(); QXmlStreamReader xml( io ); xml.readNextStartElement(); // Before KDE4.3, KPat didn't store game specific options in the save // file. This could cause crashes when loading a Spider game with a // different number of suits than the current setting. Similarly, in // Klondike the number of cards drawn from the deck was forgotten, but // this never caused crashes. Fortunately, in Spider we can count the // number of suits ourselves. For Klondike, there is no way to recover // that information. QString options = xml.attributes().value( QStringLiteral("options") ).toString(); if ( gameId() == 17 && options.isEmpty() ) { QSet suits; while ( !xml.atEnd() ) if ( xml.readNextStartElement() && xml.name() == "card" ) suits << readIntAttribute( xml, QStringLiteral("suit") ); options = QString::number( suits.size() ); // "Rewind" back to the tag. Yes, this is ugly. xml.clear(); io->reset(); xml.setDevice( io ); xml.readNextStartElement(); } setGameOptions( options ); m_dealNumber = readIntAttribute( xml, QStringLiteral("number") ); m_loadedMoveCount = readIntAttribute( xml, QStringLiteral("moves") ); m_dealStarted = readIntAttribute( xml, QStringLiteral("started") ); QString gameStateData = xml.attributes().value( QStringLiteral("data") ).toString(); QMultiHash cards; foreach ( KCard * c, deck()->cards() ) cards.insert( (c->id() & 0xffff), c ); QHash piles; foreach ( PatPile * p, patPiles() ) piles.insert( p->index(), p ); // Loop through s. while ( xml.readNextStartElement() ) { if ( xml.name() != "pile" ) { qCWarning(KPAT_LOG) << "Expected a \"pile\" tag. Found a" << xml.name() << "tag."; return false; } bool ok; int index = readIntAttribute( xml, QStringLiteral("index"), &ok ); QHash::const_iterator it = piles.constFind( index ); if ( !ok || it == piles.constEnd() ) { qCWarning(KPAT_LOG) << "Unrecognized pile index:" << xml.attributes().value( QStringLiteral("index") ); return false; } PatPile * p = it.value(); p->clear(); // Loop through s. while ( xml.readNextStartElement() ) { if ( xml.name() != "card" ) { qCWarning(KPAT_LOG) << "Expected a \"card\" tag. Found a" << xml.name() << "tag."; return false; } bool suitOk, rankOk, faceUpOk; int suit = readIntAttribute( xml, QStringLiteral("suit"), &suitOk ); int rank = readIntAttribute( xml, QStringLiteral("value"), &rankOk ); bool faceUp = readIntAttribute( xml, QStringLiteral("faceup"), &faceUpOk ); quint32 id = KCardDeck::getId( KCardDeck::Suit( suit ), KCardDeck::Rank( rank ), 0 ); KCard * card = cards.take( id ); if ( !suitOk || !rankOk || !faceUpOk || !card ) { qCWarning(KPAT_LOG) << "Unrecognized card: suit=" << xml.attributes().value(QStringLiteral("suit")) << " value=" << xml.attributes().value(QStringLiteral("value")) << " faceup=" << xml.attributes().value(QStringLiteral("faceup")); return false; } card->setFaceUp( faceUp ); p->add( card ); xml.skipCurrentElement(); } updatePileLayout( p, 0 ); } setGameState( gameStateData ); emit updateMoves( moveCount() ); takeState(); return true; } void DealerScene::saveFile( QIODevice * io ) { QXmlStreamWriter xml( io ); xml.setCodec( "UTF-8" ); xml.setAutoFormatting( true ); xml.setAutoFormattingIndent( -1 ); xml.writeStartDocument(); xml.writeStartElement( QStringLiteral("kpat-game") ); xml.writeAttribute( QStringLiteral("game-type"), m_di->baseIdString() ); if ( !getGameOptions().isEmpty() ) xml.writeAttribute( QStringLiteral("game-type-options"), getGameOptions() ); xml.writeAttribute( QStringLiteral("deal-number"), QString::number( gameNumber() ) ); if (!m_currentState) { deck()->stopAnimations(); takeState(); } QList allStates; for ( int i = 0; i < m_undoStack.size(); ++i ) allStates << m_undoStack.at( i ); allStates << m_currentState; for ( int i = m_redoStack.size() - 1; i >= 0; --i ) allStates << m_redoStack.at( i ); QString lastGameSpecificState; for ( int i = 0; i < allStates.size(); ++i ) { const GameState * state = allStates.at( i ); xml.writeStartElement( QStringLiteral("state") ); if ( state->stateData != lastGameSpecificState ) { xml.writeAttribute( QStringLiteral("game-specific-state"), state->stateData ); lastGameSpecificState = state->stateData; } if ( i == m_undoStack.size() ) xml.writeAttribute( QStringLiteral("current"), QStringLiteral("true") ); foreach ( const CardStateChange & change, state->changes ) { xml.writeStartElement( QStringLiteral("move") ); xml.writeAttribute( QStringLiteral("pile"), change.newState.pile->objectName() ); xml.writeAttribute( QStringLiteral("position"), QString::number( change.newState.index ) ); bool faceChanged = !change.oldState.pile || change.oldState.faceUp != change.newState.faceUp; foreach ( const KCard * card, change.cards ) { xml.writeStartElement( QStringLiteral("card") ); xml.writeAttribute( QStringLiteral("id"), QStringLiteral("%1").arg( card->id(), 7, 10, QChar('0') ) ); xml.writeAttribute( QStringLiteral("suit"), suitToString( card->suit() ) ); xml.writeAttribute( QStringLiteral("rank"), rankToString( card->rank() ) ); if ( faceChanged ) xml.writeAttribute( QStringLiteral("turn"), change.newState.faceUp ? "face-up" : "face-down" ); xml.writeEndElement(); } xml.writeEndElement(); } xml.writeEndElement(); } xml.writeEndElement(); xml.writeEndDocument(); m_dealWasJustSaved = true; } bool DealerScene::loadFile( QIODevice * io ) { resetInternals(); bool reenableAutoDrop = autoDropEnabled(); setAutoDropEnabled( false ); QXmlStreamReader xml( io ); xml.readNextStartElement(); if ( xml.name() != "kpat-game" ) { qCWarning(KPAT_LOG) << "First tag is not \"kpat-game\""; return false; } m_dealNumber = readIntAttribute( xml, QStringLiteral("deal-number") ); setGameOptions( xml.attributes().value( QStringLiteral("game-type-options") ).toString() ); QMultiHash cardHash; foreach ( KCard * c, deck()->cards() ) cardHash.insert( c->id(), c ); QHash pileHash; foreach ( KCardPile * p, piles() ) pileHash.insert( p->objectName(), p ); int undosToDo = -1; while( xml.readNextStartElement() ) { if ( xml.name() != "state" ) { qCWarning(KPAT_LOG) << "Expected a \"state\" tag. Found a" << xml.name() << "tag."; return false; } if ( xml.attributes().hasAttribute( QStringLiteral("game-specific-state") ) ) setGameState( xml.attributes().value( QStringLiteral("game-specific-state") ).toString() ); if ( undosToDo > -1 ) ++undosToDo; else if ( xml.attributes().value( QStringLiteral("current") ) == "true" ) undosToDo = 0; while( xml.readNextStartElement() ) { if ( xml.name() != "move" ) { qCWarning(KPAT_LOG) << "Expected a \"move\" tag. Found a" << xml.name() << "tag."; return false; } QString pileName = xml.attributes().value( QStringLiteral("pile") ).toString(); KCardPile * pile = pileHash.value( pileName ); bool indexOk; int index = readIntAttribute( xml, QStringLiteral("position"), &indexOk ); if ( !pile || !indexOk ) { qCWarning(KPAT_LOG) << "Unrecognized pile or index."; return false; } while ( xml.readNextStartElement() ) { if ( xml.name() != "card" ) { qCWarning(KPAT_LOG) << "Expected a \"card\" tag. Found a" << xml.name() << "tag."; return false; } KCard * card = cardHash.value( readIntAttribute( xml, QStringLiteral("id") ) ); if ( !card ) { qCWarning(KPAT_LOG) << "Unrecognized card."; return false; } if ( xml.attributes().value(QStringLiteral("turn")) == "face-up" ) card->setFaceUp( true ); else if ( xml.attributes().value(QStringLiteral("turn")) == "face-down" ) card->setFaceUp( false ); pile->insert( index, card ); ++index; xml.skipCurrentElement(); } } takeState(); } m_loadedMoveCount = 0; m_dealStarted = moveCount() > 0; emit updateMoves( moveCount() ); while ( undosToDo > 0 ) { undo(); --undosToDo; } foreach ( KCardPile * p, piles() ) updatePileLayout( p, 0 ); setAutoDropEnabled( reenableAutoDrop ); return true; } DealerScene::DealerScene( const DealerInfo * di ) : m_di( di ), m_solver( nullptr ), m_solverThread( nullptr ), m_peekedCard( nullptr ), m_dealNumber( 0 ), m_loadedMoveCount( 0 ), m_neededFutureMoves( 1 ), m_supportedActions( 0 ), m_autoDropEnabled( false ), m_solverEnabled( false ), m_dealStarted( false ), m_dealWasEverWinnable( false ), m_dealHasBeenWon( false ), m_dealWasJustSaved( false ), m_statisticsRecorded( false ), m_playerReceivedHelp( false ), m_toldAboutWonGame( false ), m_toldAboutLostGame( false ), m_dropSpeedFactor( 1 ), m_interruptAutoDrop( false ), m_dealInProgress( false ), m_hintInProgress( false ), m_demoInProgress( false ), m_dropInProgress( false ), m_hintQueued( false ), m_demoQueued( false ), m_dropQueued( false ), m_newCardsQueued( false ), m_takeStateQueued( false ), m_currentState( nullptr ) { setItemIndexMethod(QGraphicsScene::NoIndex); m_solverUpdateTimer.setInterval( 250 ); m_solverUpdateTimer.setSingleShot( true ); connect(&m_solverUpdateTimer, &QTimer::timeout, this, &DealerScene::stopAndRestartSolver); m_demoTimer.setSingleShot( true ); connect(&m_demoTimer, &QTimer::timeout, this, &DealerScene::demo); m_dropTimer.setSingleShot( true ); connect(&m_dropTimer, &QTimer::timeout, this, &DealerScene::drop); m_wonItem = new MessageBox(); m_wonItem->setZValue( 2000 ); m_wonItem->hide(); addItem( m_wonItem ); connect(this, &DealerScene::cardAnimationDone, this, &DealerScene::animationDone); connect(this, &DealerScene::cardDoubleClicked, this, &DealerScene::tryAutomaticMove); // Make rightClick == doubleClick. See bug #151921 connect(this, &DealerScene::cardRightClicked, this, &DealerScene::tryAutomaticMove); } DealerScene::~DealerScene() { stop(); disconnect(); if ( m_solverThread ) m_solverThread->abort(); delete m_solverThread; m_solverThread = nullptr; delete m_solver; m_solver = nullptr; qDeleteAll( m_undoStack ); delete m_currentState; qDeleteAll( m_redoStack ); delete m_wonItem; } void DealerScene::addPatPile( PatPile * pile ) { if ( !m_patPiles.contains( pile ) ) m_patPiles.append( pile ); } void DealerScene::removePatPile( PatPile * pile ) { m_patPiles.removeAll( pile ); } QList DealerScene::patPiles() const { return m_patPiles; } void DealerScene::cardsMoved( const QList & cards, KCardPile * oldPile, KCardPile * newPile ) { PatPile * newPatPile = dynamic_cast( newPile ); PatPile * oldPatPile = dynamic_cast( oldPile ); if ( oldPatPile && oldPatPile->isFoundation() && newPatPile && !newPatPile->isFoundation() ) { foreach ( KCard * c, cards ) m_cardsRemovedFromFoundations.insert( c ); } else { foreach ( KCard * c, cards ) m_cardsRemovedFromFoundations.remove( c ); } if ( !m_dropInProgress && !m_dealInProgress ) { m_dealStarted = true; takeState(); } } void DealerScene::startHint() { stopDemo(); stopDrop(); if ( isCardAnimationRunning() ) { m_hintQueued = true; return; } if ( isKeyboardModeActive() ) setKeyboardModeActive( false ); QList toHighlight; foreach ( const MoveHint & h, getHints() ) toHighlight << h.card(); if ( !m_winningMoves.isEmpty() ) { MOVE m = m_winningMoves.first(); MoveHint mh = solver()->translateMove( m ); if ( mh.isValid() ) toHighlight << mh.card(); } m_hintInProgress = !toHighlight.isEmpty(); setHighlightedItems( toHighlight ); emit hintActive( m_hintInProgress ); } void DealerScene::stopHint() { if ( m_hintInProgress ) { m_hintInProgress = false; clearHighlightedItems(); emit hintActive( false ); } } bool DealerScene::isHintActive() const { return m_hintInProgress; } QList DealerScene::getSolverHints() { QList hintList; if ( m_solverThread && m_solverThread->isRunning() ) m_solverThread->abort(); solver()->translate_layout(); solver()->patsolve( 1 ); foreach ( const MOVE & m, solver()->firstMoves() ) { MoveHint mh = solver()->translateMove( m ); hintList << mh; } return hintList; } QList DealerScene::getHints() { if ( solver() ) return getSolverHints(); QList hintList; foreach (PatPile * store, patPiles()) { if (store->isFoundation() || store->isEmpty()) continue; QList cards = store->cards(); while (cards.count() && !cards.first()->isFaceUp()) cards.erase(cards.begin()); QList::Iterator iti = cards.begin(); while (iti != cards.end()) { if (allowedToRemove(store, (*iti))) { foreach (PatPile * dest, patPiles()) { int cardIndex = store->indexOf(*iti); if (cardIndex == 0 && dest->isEmpty() && !dest->isFoundation()) continue; if (!checkAdd(dest, dest->cards(), cards)) continue; if (dest->isFoundation()) { hintList << MoveHint( *iti, dest, 127 ); } else { QList cardsBelow = cards.mid(0, cardIndex); // if it could be here as well, then it's no use if ((cardsBelow.isEmpty() && !dest->isEmpty()) || !checkAdd(store, cardsBelow, cards)) { hintList << MoveHint( *iti, dest, 0 ); } else if (checkPrefering(dest, dest->cards(), cards) && !checkPrefering(store, cardsBelow, cards)) { // if checkPrefers says so, we add it nonetheless hintList << MoveHint( *iti, dest, 10 ); } } } } cards.erase(iti); iti = cards.begin(); } } return hintList; } static bool prioSort(const MoveHint &c1, const MoveHint &c2) { return c1.priority() < c2.priority(); } MoveHint DealerScene::chooseHint() { if ( !m_winningMoves.isEmpty() ) { MOVE m = m_winningMoves.takeFirst(); MoveHint mh = solver()->translateMove( m ); #ifndef NDEBUG if ( m.totype == O_Type ) fprintf( stderr, "move from %d out (at %d) Prio: %d\n", m.from, m.turn_index, m.pri ); else fprintf( stderr, "move from %d to %d (%d) Prio: %d\n", m.from, m.to, m.turn_index, m.pri ); #endif return mh; } QList hintList = getHints(); if ( hintList.isEmpty() ) { return MoveHint(); } else { // Generate a random number with an exponentional distribution averaging 1/4. qreal randomExp = qMin( -log( 1 - qreal( KRandom::random() ) / RAND_MAX ) / 4, 1 ); int randomIndex = randomExp * ( hintList.size() - 1 ); std::sort(hintList.begin(), hintList.end(), prioSort); return hintList.at( randomIndex ); } } void DealerScene::startNew( int dealNumber ) { if ( dealNumber != -1 ) m_dealNumber = qBound( 1, dealNumber, INT_MAX ); // Only record the statistics and reset gameStarted if we're starting a // new game number or we're restarting a game we've already won. if ( dealNumber != -1 || m_dealHasBeenWon ) { recordGameStatistics(); m_statisticsRecorded = false; m_dealStarted = false; } if ( isCardAnimationRunning() ) { QTimer::singleShot( 100, this, SLOT(startNew()) ); return; } if ( m_solverThread && m_solverThread->isRunning() ) m_solverThread->abort(); resetInternals(); emit updateMoves( 0 ); foreach( KCardPile * p, piles() ) p->clear(); m_dealInProgress = true; restart( KpatShuffle::shuffled( deck()->cards(), m_dealNumber ) ); m_dealInProgress = false; takeState(); update(); } void DealerScene::resetInternals() { stop(); setKeyboardModeActive( false ); m_dealHasBeenWon = false; m_wonItem->hide(); qDeleteAll( m_undoStack ); m_undoStack.clear(); delete m_currentState; m_currentState = nullptr; qDeleteAll( m_redoStack ); m_redoStack.clear(); m_lastKnownCardStates.clear(); m_dealWasJustSaved = false; m_dealWasEverWinnable = false; m_toldAboutLostGame = false; m_toldAboutWonGame = false; m_loadedMoveCount = 0; m_playerReceivedHelp = false; m_dealInProgress = false; m_dropInProgress = false; m_dropSpeedFactor = 1; m_cardsRemovedFromFoundations.clear(); foreach (KCard * c, deck()->cards()) { c->disconnect( this ); c->stopAnimation(); } emit solverStateChanged( QString() ); emit gameInProgress( true ); } QPointF posAlongRect( qreal distOnRect, const QRectF & rect ) { if ( distOnRect < rect.width() ) return rect.topLeft() + QPointF( distOnRect, 0 ); distOnRect -= rect.width(); if ( distOnRect < rect.height() ) return rect.topRight() + QPointF( 0, distOnRect ); distOnRect -= rect.height(); if ( distOnRect < rect.width() ) return rect.bottomRight() + QPointF( -distOnRect, 0 ); distOnRect -= rect.width(); return rect.bottomLeft() + QPointF( 0, -distOnRect ); } void DealerScene::won() { if ( m_dealHasBeenWon ) return; m_dealHasBeenWon = true; m_toldAboutWonGame = true; stopDemo(); recordGameStatistics(); emit solverStateChanged( QString() ); emit newCardsPossible( false ); emit undoPossible( false ); emit redoPossible( false ); emit gameInProgress( false ); setKeyboardModeActive( false ); qreal speed = sqrt( width() * width() + height() * height() ) / ( DURATION_WON ); QRectF justOffScreen = sceneRect().adjusted( -deck()->cardWidth(), -deck()->cardHeight(), 0, 0 ); qreal spacing = 2 * ( justOffScreen.width() + justOffScreen.height() ) / deck()->cards().size(); qreal distOnRect = 0; foreach ( KCard *c, deck()->cards() ) { distOnRect += spacing; QPointF pos2 = posAlongRect( distOnRect, justOffScreen ); QPointF delta = c->pos() - pos2; qreal dist = sqrt( delta.x() * delta.x() + delta.y() * delta.y() ); c->setFaceUp( true ); c->animate( pos2, c->zValue(), 0, true, false, dist / speed ); } connect(deck(), &KAbstractCardDeck::cardAnimationDone, this, &DealerScene::showWonMessage); } void DealerScene::showWonMessage() { disconnect(deck(), &KAbstractCardDeck::cardAnimationDone, this, &DealerScene::showWonMessage); // It shouldn't be necessary to stop the demo yet again here, but we // get crashes if we don't. Will have to look into this further. stopDemo(); // Hide all cards to prevent them from showing up accidentally if the // window is resized. foreach ( KCard * c, deck()->cards() ) c->hide(); updateWonItem(); m_wonItem->show(); } void DealerScene::updateWonItem() { const qreal aspectRatio = Renderer::self()->aspectRatioOfElement(QStringLiteral("message_frame")); int boxWidth; int boxHeight; if ( width() < aspectRatio * height() ) { boxWidth = width() * wonBoxToSceneSizeRatio; boxHeight = boxWidth / aspectRatio; } else { boxHeight = height() * wonBoxToSceneSizeRatio; boxWidth = boxHeight * aspectRatio; } m_wonItem->setSize( QSize( boxWidth, boxHeight ) ); if ( m_playerReceivedHelp ) m_wonItem->setMessage( i18n( "Congratulations! We have won." ) ); else m_wonItem->setMessage( i18n( "Congratulations! You have won." ) ); m_wonItem->setPos( QPointF( (width() - boxWidth) / 2, (height() - boxHeight) / 2 ) + sceneRect().topLeft() ); } bool DealerScene::allowedToAdd( const KCardPile * pile, const QList & cards ) const { if ( !pile->isEmpty() && !pile->topCard()->isFaceUp() ) return false; const PatPile * p = dynamic_cast( pile ); return p && checkAdd( p, p->cards(), cards ); } bool DealerScene::allowedToRemove( const KCardPile * pile, const KCard * card ) const { const PatPile * p = dynamic_cast( pile ); QList cards = pile->topCardsDownTo( card ); return p && card->isFaceUp() && !cards.isEmpty() && checkRemove( p, cards ); } bool DealerScene::checkAdd( const PatPile * pile, const QList & oldCards, const QList & newCards ) const { Q_UNUSED( pile ) Q_UNUSED( oldCards ) Q_UNUSED( newCards ) return false; } bool DealerScene::checkRemove(const PatPile * pile, const QList & cards) const { Q_UNUSED( pile ) Q_UNUSED( cards ) return false; } bool DealerScene::checkPrefering( const PatPile * pile, const QList & oldCards, const QList & newCards ) const { Q_UNUSED( pile ) Q_UNUSED( oldCards ) Q_UNUSED( newCards ) return false; } void DealerScene::mousePressEvent( QGraphicsSceneMouseEvent * e ) { stop(); const QList itemsAtPoint = items( e->scenePos() ); KCard * card = qgraphicsitem_cast( itemsAtPoint.isEmpty() ? 0 : itemsAtPoint.first() ); if ( m_peekedCard ) { e->accept(); } else if ( e->button() == Qt::RightButton && card && card->pile() && card != card->pile()->topCard() && cardsBeingDragged().isEmpty() && !isCardAnimationRunning() ) { e->accept(); m_peekedCard = card; QPointF pos2( card->x() + deck()->cardWidth() / 3.0, card->y() - deck()->cardHeight() / 3.0 ); card->setZValue( card->zValue() + 0.1 ); card->animate( pos2, card->zValue(), 20, card->isFaceUp(), false, DURATION_FANCYSHOW ); } else { KCardScene::mousePressEvent( e ); if ( !cardsBeingDragged().isEmpty() ) emit cardsPickedUp(); } } void DealerScene::mouseReleaseEvent( QGraphicsSceneMouseEvent * e ) { stop(); if ( e->button() == Qt::RightButton && m_peekedCard && m_peekedCard->pile() ) { e->accept(); updatePileLayout( m_peekedCard->pile(), DURATION_FANCYSHOW ); m_peekedCard = nullptr; } else { bool hadCards = !cardsBeingDragged().isEmpty(); KCardScene::mouseReleaseEvent( e ); if ( hadCards && cardsBeingDragged().isEmpty() ) emit cardsPutDown(); } } void DealerScene::mouseDoubleClickEvent( QGraphicsSceneMouseEvent * e ) { stop(); KCardScene::mouseDoubleClickEvent( e ); } bool DealerScene::tryAutomaticMove( KCard * card ) { if ( !isCardAnimationRunning() && card && card->pile() && card == card->pile()->topCard() && card->isFaceUp() && allowedToRemove( card->pile(), card ) ) { QList cardList = QList() << card; foreach ( PatPile * p, patPiles() ) { if ( p->isFoundation() && allowedToAdd( p, cardList ) ) { moveCardToPile( card , p, DURATION_MOVE ); return true; } } } return false; } void DealerScene::undo() { undoOrRedo( true ); } void DealerScene::redo() { undoOrRedo( false ); } void DealerScene::undoOrRedo( bool undo ) { stop(); if ( isCardAnimationRunning() ) return; // The undo and redo actions are almost identical, except for where states // are pulled from and pushed to, so to keep things generic, we use // direction dependent const references throughout this code. QStack & fromStack = undo ? m_undoStack : m_redoStack; QStack & toStack = undo ? m_redoStack : m_undoStack; if ( !fromStack.isEmpty() && m_currentState ) { // If we're undoing, we use the oldStates of the changes of the current // state. If we're redoing, we use the newStates of the changes of the // nextState. const QList & changes = undo ? m_currentState->changes : fromStack.top()->changes; // Update the currentState pointer and undo/redo stacks. toStack.push( m_currentState ); m_currentState = fromStack.pop(); setGameState( m_currentState->stateData ); QSet pilesAffected; foreach ( const CardStateChange & change, changes ) { CardState sourceState = undo ? change.newState : change.oldState; CardState destState = undo ? change.oldState : change.newState; PatPile * sourcePile = dynamic_cast( sourceState.pile ); PatPile * destPile = dynamic_cast( destState.pile ); bool notDroppable = destState.takenDown || ((sourcePile && sourcePile->isFoundation()) && !(destPile && destPile->isFoundation())); pilesAffected << sourceState.pile << destState.pile; foreach ( KCard * c, change.cards ) { m_lastKnownCardStates.insert( c, destState ); c->setFaceUp( destState.faceUp ); destState.pile->insert( destState.index, c ); if ( notDroppable ) m_cardsRemovedFromFoundations.insert( c ); else m_cardsRemovedFromFoundations.remove( c ); ++sourceState.index; ++destState.index; } } // At this point all cards should be in the right piles, but not // necessarily at the right positions within those piles. So we // run through the piles involved and swap card positions until // everything is back in its place, then relayout the piles. foreach( KCardPile * p, pilesAffected ) { int i = 0; while ( i < p->count() ) { int index = m_lastKnownCardStates.value( p->at( i ) ).index; if ( i == index ) ++i; else p->swapCards( i, index ); } updatePileLayout( p, 0 ); } emit updateMoves( moveCount() ); emit undoPossible( !m_undoStack.isEmpty() ); emit redoPossible( !m_redoStack.isEmpty() ); if ( m_toldAboutLostGame ) // everything's possible again { gameInProgress( true ); m_toldAboutLostGame = false; m_toldAboutWonGame = false; } int solvability = m_currentState->solvability; m_winningMoves = m_currentState->winningMoves; emit solverStateChanged( solverStatusMessage( solvability, m_dealWasEverWinnable ) ); if ( m_solver && ( solvability == SolverInterface::SearchAborted || solvability == SolverInterface::MemoryLimitReached ) ) { startSolver(); } } } void DealerScene::takeState() { if ( isCardAnimationRunning() ) { m_takeStateQueued = true; return; } if ( !isDemoActive() ) m_winningMoves.clear(); QList changes; foreach ( KCardPile * p, piles() ) { QList currentRun; CardState oldRunState; CardState newRunState; for ( int i = 0; i < p->count(); ++i ) { KCard * c = p->at( i ); const CardState & oldState = m_lastKnownCardStates.value( c ); CardState newState( p, i, c->isFaceUp(), m_cardsRemovedFromFoundations.contains( c ) ); // The card has changed. if ( newState != oldState ) { // There's a run in progress, but this card isn't part of it. if ( !currentRun.isEmpty() && (oldState.pile != oldRunState.pile || (oldState.index != -1 && oldState.index != oldRunState.index + currentRun.size()) || oldState.faceUp != oldRunState.faceUp || newState.faceUp != newRunState.faceUp || oldState.takenDown != oldRunState.takenDown || newState.takenDown != newRunState.takenDown) ) { changes << CardStateChange( oldRunState, newRunState, currentRun ); currentRun.clear(); } // This card is the start of a new run. if ( currentRun.isEmpty() ) { oldRunState = oldState; newRunState = newState; } currentRun << c; m_lastKnownCardStates.insert( c, newState ); } } // Add the last run, if any. if ( !currentRun.isEmpty() ) { changes << CardStateChange( oldRunState, newRunState, currentRun ); } } // If nothing has changed, we're done. if ( changes.isEmpty() && m_currentState && m_currentState->stateData == getGameState() ) { return; } if ( m_currentState ) { m_undoStack.push( m_currentState ); qDeleteAll( m_redoStack ); m_redoStack.clear(); } m_currentState = new GameState( changes, getGameState() ); emit redoPossible( false ); emit undoPossible( !m_undoStack.isEmpty() ); emit updateMoves( moveCount() ); m_dealWasJustSaved = false; if ( isGameWon() ) { won(); return; } if ( !m_toldAboutWonGame && !m_toldAboutLostGame && isGameLost() ) { emit gameInProgress( false ); emit solverStateChanged( i18n( "Solver: This game is lost." ) ); m_toldAboutLostGame = true; stopDemo(); return; } if ( !isDemoActive() && !isCardAnimationRunning() && m_solver ) startSolver(); if ( autoDropEnabled() && !isDropActive() && !isDemoActive() && m_redoStack.isEmpty() ) { if ( m_interruptAutoDrop ) m_interruptAutoDrop = false; else startDrop(); } } void DealerScene::setSolverEnabled(bool a) { m_solverEnabled = a; } void DealerScene::setAutoDropEnabled( bool enabled ) { m_autoDropEnabled = enabled; } bool DealerScene::autoDropEnabled() const { return m_autoDropEnabled; } void DealerScene::startDrop() { stopHint(); stopDemo(); if ( isCardAnimationRunning() ) { m_dropQueued = true; return; } m_dropInProgress = true; m_interruptAutoDrop = false; m_dropSpeedFactor = 1; emit dropActive( true ); drop(); } void DealerScene::stopDrop() { if ( m_dropInProgress ) { m_dropTimer.stop(); m_dropInProgress = false; emit dropActive( false ); if ( autoDropEnabled() && m_takeStateQueued ) m_interruptAutoDrop = true; } } bool DealerScene::isDropActive() const { return m_dropInProgress; } bool DealerScene::drop() { foreach ( const MoveHint & mh, getHints() ) { if ( mh.pile() && mh.pile()->isFoundation() && mh.priority() > 120 && !m_cardsRemovedFromFoundations.contains( mh.card() ) ) { QList cards = mh.card()->pile()->topCardsDownTo( mh.card() ); QMap oldPositions; foreach ( KCard * c, cards ) oldPositions.insert( c, c->pos() ); moveCardsToPile( cards, mh.pile(), DURATION_MOVE ); int count = 0; foreach ( KCard * c, cards ) { c->completeAnimation(); QPointF destPos = c->pos(); c->setPos( oldPositions.value( c ) ); int duration = speedUpTime( DURATION_AUTODROP + count * DURATION_AUTODROP / 10 ); c->animate( destPos, c->zValue(), 0, c->isFaceUp(), true, duration ); ++count; } m_dropSpeedFactor *= AUTODROP_SPEEDUP_FACTOR; takeState(); return true; } } m_dropInProgress = false; emit dropActive( false ); return false; } int DealerScene::speedUpTime( int delay ) const { if ( delay < DURATION_AUTODROP_MINIMUM ) return delay; else return qMax( delay * m_dropSpeedFactor, DURATION_AUTODROP_MINIMUM ); } void DealerScene::stopAndRestartSolver() { if ( m_toldAboutLostGame || m_toldAboutWonGame ) // who cares? return; if ( m_solverThread && m_solverThread->isRunning() ) { m_solverThread->abort(); } if ( isCardAnimationRunning() ) { startSolver(); return; } slotSolverEnded(); } void DealerScene::slotSolverEnded() { if ( m_solverThread && m_solverThread->isRunning() ) return; m_solver->translate_layout(); m_winningMoves.clear(); emit solverStateChanged( i18n("Solver: Calculating...") ); if ( !m_solverThread ) { m_solverThread = new SolverThread( m_solver ); connect(m_solverThread, &SolverThread::finished, this, &DealerScene::slotSolverFinished); } m_solverThread->start( m_solverEnabled ? QThread::IdlePriority : QThread::NormalPriority ); } void DealerScene::slotSolverFinished( int result ) { if ( result == SolverInterface::SolutionExists ) { m_winningMoves = m_solver->winMoves(); m_dealWasEverWinnable = true; } emit solverStateChanged( solverStatusMessage( result, m_dealWasEverWinnable ) ); if ( m_currentState ) { m_currentState->solvability = static_cast( result ); m_currentState->winningMoves = m_winningMoves; } if ( result == SolverInterface::SearchAborted ) startSolver(); } int DealerScene::gameNumber() const { return m_dealNumber; } void DealerScene::stop() { stopHint(); stopDemo(); stopDrop(); } void DealerScene::animationDone() { Q_ASSERT( !isCardAnimationRunning() ); if ( !m_multiStepMoves.isEmpty() ) { continueMultiStepMove(); return; } if ( m_takeStateQueued ) { m_takeStateQueued = false; takeState(); } if ( m_demoInProgress ) { m_demoTimer.start( TIME_BETWEEN_MOVES ); } else if ( m_dropInProgress ) { m_dropTimer.start( speedUpTime( TIME_BETWEEN_MOVES ) ); } else if ( m_newCardsQueued ) { m_newCardsQueued = false; newCards(); } else if ( m_hintQueued ) { m_hintQueued = false; startHint(); } else if ( m_demoQueued ) { m_demoQueued = false; startDemo(); } else if ( m_dropQueued ) { m_dropQueued = false; startDrop(); } } void DealerScene::startDemo() { stopHint(); stopDrop(); if ( isCardAnimationRunning() ) { m_demoQueued = true; return; } m_demoInProgress = true; m_playerReceivedHelp = true; m_dealStarted = true; demo(); } void DealerScene::stopDemo() { if ( m_demoInProgress ) { m_demoTimer.stop(); m_demoInProgress = false; emit demoActive( false ); } } bool DealerScene::isDemoActive() const { return m_demoInProgress; } void DealerScene::demo() { if ( isCardAnimationRunning() ) { m_demoQueued = true; return; } m_demoInProgress = true; m_playerReceivedHelp = true; m_dealStarted = true; clearHighlightedItems(); m_demoTimer.stop(); MoveHint mh = chooseHint(); if ( mh.isValid() ) { KCard * card = mh.card(); Q_ASSERT( card ); KCardPile * sourcePile = mh.card()->pile(); Q_ASSERT( sourcePile ); Q_ASSERT( allowedToRemove( sourcePile, card ) ); PatPile * destPile = mh.pile(); Q_ASSERT( destPile ); Q_ASSERT( sourcePile != destPile ); QList cards = sourcePile->topCardsDownTo( card ); Q_ASSERT( allowedToAdd( destPile, cards ) ); if ( destPile->isEmpty() ) { qCDebug(KPAT_LOG) << "Moving" << card->objectName() << "from the" << sourcePile->objectName() << "pile to the" << destPile->objectName() << "pile, which is empty"; } else { qCDebug(KPAT_LOG) << "Moving" << card->objectName() << "from the" << sourcePile->objectName() << "pile to the" << destPile->objectName() << "pile, putting it on top of" << destPile->topCard()->objectName(); } moveCardsToPile( cards, destPile, DURATION_DEMO ); } else if ( !newCards() ) { if (isGameWon()) { won(); } else { stopDemo(); slotSolverEnded(); } return; } emit demoActive( true ); takeState(); } void DealerScene::drawDealRowOrRedeal() { stop(); if ( isCardAnimationRunning() ) { m_newCardsQueued = true; return; } m_newCardsQueued = false; newCards(); } bool DealerScene::newCards() { return false; } void DealerScene::setSolver( SolverInterface *s) { delete m_solver; delete m_solverThread; m_solver = s; m_solverThread = nullptr; } bool DealerScene::isGameWon() const { foreach (PatPile *p, patPiles()) { if (!p->isFoundation() && !p->isEmpty()) return false; } return true; } void DealerScene::startSolver() { if( m_solverEnabled ) m_solverUpdateTimer.start(); } bool DealerScene::isGameLost() const { if (! m_winningMoves.isEmpty()) { return false; } if ( solver() ) { if ( m_solverThread && m_solverThread->isRunning() ) m_solverThread->abort(); solver()->translate_layout(); return solver()->patsolve( neededFutureMoves() ) == SolverInterface::NoSolutionExists; } return false; } void DealerScene::recordGameStatistics() { // Don't record the game if it was never started, if it is unchanged since // it was last saved (allowing the user to close KPat after saving without // it recording a loss) or if it has already been recorded.// takeState(); // copying it again if ( m_dealStarted && !m_dealWasJustSaved && !m_statisticsRecorded ) { int id = oldId(); QString totalPlayedKey = QStringLiteral("total%1").arg( id ); QString wonKey = QStringLiteral("won%1").arg( id ); QString winStreakKey = QStringLiteral("winstreak%1").arg( id ); QString maxWinStreakKey = QStringLiteral("maxwinstreak%1").arg( id ); QString loseStreakKey = QStringLiteral("loosestreak%1").arg( id ); QString maxLoseStreakKey = QStringLiteral("maxloosestreak%1").arg( id ); KConfigGroup config(KSharedConfig::openConfig(), scores_group); int totalPlayed = config.readEntry( totalPlayedKey, 0 ); int won = config.readEntry( wonKey, 0 ); int winStreak = config.readEntry( winStreakKey, 0 ); int maxWinStreak = config.readEntry( maxWinStreakKey, 0 ); int loseStreak = config.readEntry( loseStreakKey, 0 ); int maxLoseStreak = config.readEntry( maxLoseStreakKey, 0 ); ++totalPlayed; if ( m_dealHasBeenWon ) { ++won; ++winStreak; maxWinStreak = qMax( winStreak, maxWinStreak ); loseStreak = 0; } else { ++loseStreak; maxLoseStreak = qMax( loseStreak, maxLoseStreak ); winStreak = 0; } config.writeEntry( totalPlayedKey, totalPlayed ); config.writeEntry( wonKey, won ); config.writeEntry( winStreakKey, winStreak ); config.writeEntry( maxWinStreakKey, maxWinStreak ); config.writeEntry( loseStreakKey, loseStreak ); config.writeEntry( maxLoseStreakKey, maxLoseStreak ); m_statisticsRecorded = true; } } void DealerScene::relayoutScene() { KCardScene::relayoutScene(); if ( m_wonItem->isVisible() ) updateWonItem(); } int DealerScene::gameId() const { return m_di->baseId(); } void DealerScene::setActions( int actions ) { m_supportedActions = actions; } int DealerScene::actions() const { return m_supportedActions; } QList DealerScene::configActions() const { return QList(); } SolverInterface * DealerScene::solver() const { return m_solver; } int DealerScene::neededFutureMoves() const { return m_neededFutureMoves; } void DealerScene::setNeededFutureMoves( int i ) { m_neededFutureMoves = i; } void DealerScene::setDeckContents( int copies, const QList & suits ) { Q_ASSERT( copies >= 1 ); Q_ASSERT( !suits.isEmpty() ); // Note that the order in which the cards are created can not be changed // without breaking the game numbering. For historical reasons, KPat // generates card by rank and then by suit, rather than the more common // suit then rank ordering. QList ids; unsigned int number = 0; for ( int i = 0; i < copies; ++i ) foreach ( const KCardDeck::Rank & r, KCardDeck::standardRanks() ) foreach ( const KCardDeck::Suit & s, suits ) ids << KCardDeck::getId( s, r, number++ ); deck()->setDeckContents( ids ); } QImage DealerScene::createDump() const { const QSize previewSize( 480, 320 ); foreach ( KCard * c, deck()->cards() ) c->completeAnimation(); QMultiMap itemsByZ; foreach ( QGraphicsItem * item, items() ) { Q_ASSERT( item->zValue() >= 0 ); itemsByZ.insert( item->zValue(), item ); } QImage img( contentArea().size().toSize(), QImage::Format_ARGB32 ); img.fill( Qt::transparent ); QPainter p( &img ); foreach ( QGraphicsItem * item, itemsByZ ) { if ( item->isVisible() ) { p.save(); p.setTransform( item->deviceTransform( p.worldTransform() ), false ); item->paint( &p, nullptr ); p.restore(); } } p.end(); img = img.scaled( previewSize, Qt::KeepAspectRatio, Qt::SmoothTransformation ); QImage img2( previewSize, QImage::Format_ARGB32 ); img2.fill( Qt::transparent ); QPainter p2( &img2 ); p2.drawImage( (img2.width() - img.width()) / 2, (img2.height() - img.height()) / 2, img ); p2.end(); return img2; } void DealerScene::mapOldId( int id ) { Q_UNUSED( id ); } int DealerScene::oldId() const { return gameId(); } QString DealerScene::getGameState() const { return QString(); } void DealerScene::setGameState( const QString & state ) { Q_UNUSED( state ); } QString DealerScene::getGameOptions() const { return QString(); } void DealerScene::setGameOptions( const QString & options ) { Q_UNUSED( options ); } bool DealerScene::allowedToStartNewGame() { // Check if the user is already running a game, and if she is, // then ask if she wants to abort it. return !m_dealStarted || m_dealWasJustSaved || m_toldAboutWonGame || m_toldAboutLostGame || KMessageBox::warningContinueCancel(nullptr, i18n("A new game has been requested, but there is already a game in progress.\n\n" "A loss will be recorded in the statistics if the current game is abandoned."), i18n("Abandon Current Game?"), KGuiItem(i18n("Abandon Current Game")), KStandardGuiItem::cancel(), QStringLiteral("careaboutstats") ) == KMessageBox::Continue; } void DealerScene::addCardForDeal( KCardPile * pile, KCard * card, bool faceUp, QPointF startPos ) { Q_ASSERT( card ); Q_ASSERT( pile ); card->setFaceUp( faceUp ); pile->add( card ); m_initDealPositions.insert( card, startPos ); } void DealerScene::startDealAnimation() { qreal speed = sqrt( width() * width() + height() * height() ) / ( DURATION_DEAL ); foreach ( PatPile * p, patPiles() ) { updatePileLayout( p, 0 ); foreach ( KCard * c, p->cards() ) { if ( !m_initDealPositions.contains( c ) ) continue; QPointF pos2 = c->pos(); c->setPos( m_initDealPositions.value( c ) ); QPointF delta = c->pos() - pos2; qreal dist = sqrt( delta.x() * delta.x() + delta.y() * delta.y() ); int duration = qRound( dist / speed ); c->animate( pos2, c->zValue(), 0, c->isFaceUp(), false, duration ); } } m_initDealPositions.clear(); } void DealerScene::multiStepMove( const QList & cards, KCardPile * pile, const QList & freePiles, const QList & freeCells, int duration ) { Q_ASSERT( cards.size() == 1 || !freePiles.isEmpty() || !freeCells.isEmpty() ); m_multiStepMoves.clear(); m_multiStepDuration = duration; multiStepSubMove( cards, pile, freePiles, freeCells ); continueMultiStepMove(); } void DealerScene::multiStepSubMove( QList cards, KCardPile * pile, QList freePiles, const QList & freeCells ) { // Note that cards and freePiles are passed by value, as we need to make a // local copy anyway. // Using n free cells, we can move a run of n+1 cards. If we want to move // more than that, we have to recursively move some of our cards to one of // the free piles temporarily. const int freeCellsPlusOne = freeCells.size() + 1; int cardsToSubMove = cards.size() - freeCellsPlusOne; QList > > tempMoves; while ( cardsToSubMove > 0 ) { int tempMoveSize; if ( cardsToSubMove <= freePiles.size() * freeCellsPlusOne ) { // If the cards that have to be submoved can be spread across the // the free piles without putting more than freeCellsPlusOne cards // on each one, we do so. This means that none of our submoves will // need further submoves, which keeps the total move count down. We // Just to a simple rounding up integer division. tempMoveSize = (cardsToSubMove + freePiles.size() - 1) / freePiles.size(); } else { // Otherwise, we use the space optimal method that gets the cards // moved using a minimal number of piles, but uses more submoves. tempMoveSize = freeCellsPlusOne; while ( tempMoveSize * 2 < cardsToSubMove ) tempMoveSize *= 2; } QList subCards; for ( int i = 0; i < tempMoveSize; ++i ) subCards.prepend( cards.takeLast() ); Q_ASSERT( !freePiles.isEmpty() ); KCardPile * nextPile = freePiles.takeFirst(); tempMoves << qMakePair( nextPile, subCards ); multiStepSubMove( subCards, nextPile, freePiles, freeCells ); cardsToSubMove -= tempMoveSize; } // Move cards to free cells. for ( int i = 0; i < cards.size() - 1; ++i ) { KCard * c = cards.at( cards.size() - 1 - i ); m_multiStepMoves << qMakePair( c, freeCells[i] ); } // Move bottom card to destination pile. m_multiStepMoves << qMakePair( cards.first(), pile ); // Move cards from free cells to destination pile. for ( int i = 1; i < cards.size(); ++i ) m_multiStepMoves << qMakePair( cards.at( i ), pile ); // If we just moved the bottomost card of the source pile, it must now be // empty and we won't need it any more. So we return it to the list of free // piles. KCardPile * sourcePile = cards.first()->pile(); if ( sourcePile->at( 0 ) == cards.first() ) freePiles << sourcePile; // If we had to do any submoves, we now move those cards from their // temporary pile to the destination pile and free up their temporary pile. while ( !tempMoves.isEmpty() ) { QPair > m = tempMoves.takeLast(); multiStepSubMove( m.second, pile, freePiles, freeCells ); freePiles << m.first; } } void DealerScene::continueMultiStepMove() { Q_ASSERT( !m_multiStepMoves.isEmpty() ); Q_ASSERT( !isCardAnimationRunning() ); QPair m = m_multiStepMoves.takeFirst(); KCard * card = m.first; KCardPile * dest = m.second; KCardPile * source = card->pile(); Q_ASSERT( card == source->topCard() ); Q_ASSERT( allowedToAdd( dest, QList() << card ) ); m_multiStepDuration = qMax( m_multiStepDuration * 0.9, 50 ); dest->add( card ); card->raise(); updatePileLayout( dest, m_multiStepDuration ); updatePileLayout( source, m_multiStepDuration ); if ( m_multiStepMoves.isEmpty() ) takeState(); } #include "dealer.moc" #include "moc_dealer.cpp" diff --git a/dealer.h b/dealer.h index 530b543..712c528 100644 --- a/dealer.h +++ b/dealer.h @@ -1,291 +1,291 @@ /* * Copyright (C) 1995 Paul Olav Tvete * Copyright (C) 2000-2009 Stephan Kulow * Copyright (C) 2009-2010 Parker Coates * * License of original code: * ------------------------------------------------------------------------- * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, * provided that the above copyright notice appear in all copies and that * both that copyright notice and this permission notice appear in * supporting documentation. * * This file is provided AS IS with no warranties of any kind. The author * shall have no liability with respect to the infringement of copyrights, * trade secrets or any patents by this file or any part thereof. In no * event will the author be liable for any lost revenue or profits or * other special, indirect and consequential damages. * ------------------------------------------------------------------------- * * License of modifications/additions made after 2009-01-01: * ------------------------------------------------------------------------- * 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, see . * ------------------------------------------------------------------------- */ #ifndef DEALER_H #define DEALER_H class DealerInfo; #include "gamestate.h" class MessageBox; class MoveHint; #include "patpile.h" class SolverInterface; class SolverThread; #include "speeds.h" #include "view.h" #include "KCardDeck" #include "KCardScene" class QAction; #include #include #include #include #define scores_group "Scores" class DealerScene : public KCardScene { Q_OBJECT public: enum { None = 0, Hint = 1, Demo = 2, Draw = 4, Deal = 8, Redeal = 16 } Actions; explicit DealerScene( const DealerInfo * di ); ~DealerScene(); virtual void initialize() = 0; - void relayoutScene() Q_DECL_OVERRIDE; + void relayoutScene() override; void updateWonItem(); void addPatPile( PatPile * pile ); void removePatPile( PatPile * pile ); QList patPiles() const; void setAutoDropEnabled( bool enabled ); bool autoDropEnabled() const; int gameNumber() const; int gameId() const; void setActions( int actions ); int actions() const; virtual QList configActions() const; void startHint(); void stopHint(); bool isHintActive() const; void startDrop(); void stopDrop(); bool isDropActive() const; void startDemo(); void stopDemo(); bool isDemoActive() const; void setSolverEnabled( bool enabled ); SolverInterface * solver() const; void startSolver(); virtual bool isGameLost() const; virtual bool isGameWon() const; bool allowedToStartNewGame(); int moveCount() const; void saveFile( QIODevice * io ); bool loadFile( QIODevice * io ); void saveLegacyFile( QIODevice * io ); bool loadLegacyFile( QIODevice * io ); virtual void mapOldId(int id); virtual int oldId() const; void recordGameStatistics(); QImage createDump() const; signals: void undoPossible(bool poss); void redoPossible(bool poss); void newCardsPossible(bool poss); void gameInProgress(bool inProgress); void demoActive(bool active); void hintActive(bool active); void dropActive(bool active); void updateMoves(int moves); void solverStateChanged(const QString &text); void cardsPickedUp(); void cardsPutDown(); public slots: void startNew( int dealNumber = -1 ); void undo(); void redo(); void stop(); void drawDealRowOrRedeal(); virtual bool tryAutomaticMove( KCard * card ); protected: - bool allowedToAdd(const KCardPile * pile, const QList & cards) const Q_DECL_OVERRIDE; - bool allowedToRemove(const KCardPile * pile, const KCard * card) const Q_DECL_OVERRIDE; + bool allowedToAdd(const KCardPile * pile, const QList & cards) const override; + bool allowedToRemove(const KCardPile * pile, const KCard * card) const override; virtual bool checkAdd( const PatPile * pile, const QList & oldCards, const QList & newCards ) const; virtual bool checkRemove( const PatPile * pile, const QList & cards ) const; virtual bool checkPrefering( const PatPile * pile, const QList & oldCards, const QList & newCards ) const; - void cardsMoved( const QList & cards, KCardPile * oldPile, KCardPile * newPile ) Q_DECL_OVERRIDE; + void cardsMoved( const QList & cards, KCardPile * oldPile, KCardPile * newPile ) override; - void mouseDoubleClickEvent( QGraphicsSceneMouseEvent * mouseEvent ) Q_DECL_OVERRIDE; - void mousePressEvent( QGraphicsSceneMouseEvent * mouseEvent ) Q_DECL_OVERRIDE; - void mouseReleaseEvent( QGraphicsSceneMouseEvent * mouseEvent ) Q_DECL_OVERRIDE; + void mouseDoubleClickEvent( QGraphicsSceneMouseEvent * mouseEvent ) override; + void mousePressEvent( QGraphicsSceneMouseEvent * mouseEvent ) override; + void mouseReleaseEvent( QGraphicsSceneMouseEvent * mouseEvent ) override; virtual void restart( const QList & cards ) = 0; void setSolver( SolverInterface * solver ); virtual QList getHints(); // reimplement these to store and load game-specific information in the state structure virtual QString getGameState() const; virtual void setGameState( const QString & state ); // reimplement these to store and load game-specific options in the saved game file virtual QString getGameOptions() const; virtual void setGameOptions( const QString & options ); void addCardForDeal( KCardPile * pile, KCard * card, bool faceUp, QPointF startPos ); void startDealAnimation(); void setNeededFutureMoves( int moves ); int neededFutureMoves() const; void setDeckContents( int copies = 1, const QList & suits = KCardDeck::standardSuits() ); void multiStepMove( const QList & cards, KCardPile * pile, const QList & freePiles, const QList & freeCells, int duration ); QList getSolverHints(); protected slots: void takeState(); virtual void animationDone(); virtual bool newCards(); virtual bool drop(); private slots: void stopAndRestartSolver(); void slotSolverEnded(); void slotSolverFinished( int result ); void demo(); void showWonMessage(); private: void undoOrRedo( bool undo ); void resetInternals(); MoveHint chooseHint(); void won(); int speedUpTime( int delay ) const; void multiStepSubMove( QList cards, KCardPile * pile, QList freePiles, const QList & freeCells ); void continueMultiStepMove(); const DealerInfo * const m_di; SolverInterface * m_solver; SolverThread * m_solverThread; QList m_winningMoves; KCard * m_peekedCard; MessageBox * m_wonItem; QTimer m_solverUpdateTimer; QTimer m_demoTimer; QTimer m_dropTimer; int m_dealNumber; int m_loadedMoveCount; int m_neededFutureMoves; int m_supportedActions; bool m_autoDropEnabled; bool m_solverEnabled; bool m_dealStarted; bool m_dealWasEverWinnable; bool m_dealHasBeenWon; bool m_dealWasJustSaved; bool m_statisticsRecorded; bool m_playerReceivedHelp; // We need a flag to avoid telling someone the game is lost // just because the winning animation moved the cards away bool m_toldAboutWonGame; bool m_toldAboutLostGame; QSet m_cardsRemovedFromFoundations; qreal m_dropSpeedFactor; bool m_interruptAutoDrop; bool m_dealInProgress; bool m_hintInProgress; bool m_demoInProgress; bool m_dropInProgress; bool m_hintQueued; bool m_demoQueued; bool m_dropQueued; bool m_newCardsQueued; bool m_takeStateQueued; QStack m_undoStack; GameState * m_currentState; QStack m_redoStack; QHash m_lastKnownCardStates; QList > m_multiStepMoves; int m_multiStepDuration; QList m_patPiles; QMap m_initDealPositions; }; #endif diff --git a/fortyeight.cpp b/fortyeight.cpp index 26c4168..328d9b0 100644 --- a/fortyeight.cpp +++ b/fortyeight.cpp @@ -1,262 +1,262 @@ /* * Copyright (C) 2000-2009 Stephan Kulow * Copyright (C) 2010 Parker Coates * * License of original code: * ------------------------------------------------------------------------- * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, * provided that the above copyright notice appear in all copies and that * both that copyright notice and this permission notice appear in * supporting documentation. * * This file is provided AS IS with no warranties of any kind. The author * shall have no liability with respect to the infringement of copyrights, * trade secrets or any patents by this file or any part thereof. In no * event will the author be liable for any lost revenue or profits or * other special, indirect and consequential damages. * ------------------------------------------------------------------------- * * License of modifications/additions made after 2009-01-01: * ------------------------------------------------------------------------- * 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, see . * ------------------------------------------------------------------------- */ #include "fortyeight.h" #include "dealerinfo.h" #include "pileutils.h" #include "speeds.h" #include "patsolve/fortyeightsolver.h" #include Fortyeight::Fortyeight( const DealerInfo* di ) : DealerScene( di ) { } void Fortyeight::initialize() { const qreal dist_x = 1.11; const qreal smallNeg = -1e-6; setDeckContents( 2 ); talon = new PatPile( this, 0, QStringLiteral("talon") ); talon->setPileRole(PatPile::Stock); talon->setLayoutPos( 7 * dist_x, smallNeg ); talon->setZValue(20); talon->setSpread(0, 0); talon->setKeyboardSelectHint( KCardPile::NeverFocus ); talon->setKeyboardDropHint( KCardPile::NeverFocus ); connect( talon, &KCardPile::clicked, this, &DealerScene::drawDealRowOrRedeal ); pile = new PatPile( this, 20, QStringLiteral("pile") ); pile->setPileRole(PatPile::Waste); pile->setLayoutPos( 6 * dist_x, smallNeg ); pile->setLeftPadding( 6 * dist_x ); pile->setWidthPolicy( KCardPile::GrowLeft ); pile->setSpread(-0.21, 0); pile->setKeyboardSelectHint( KCardPile::AutoFocusTop ); pile->setKeyboardDropHint( KCardPile::NeverFocus ); for ( int i = 0; i < 8; ++i ) { target[i] = new PatPile( this, 9 + i, QStringLiteral( "target%1" ).arg( i ) ); target[i]->setPileRole(PatPile::Foundation); target[i]->setLayoutPos(dist_x*i, 0); target[i]->setSpread(0, 0); target[i]->setKeyboardSelectHint( KCardPile::NeverFocus ); target[i]->setKeyboardDropHint( KCardPile::ForceFocusTop ); } for ( int i = 0; i < 8; ++i ) { stack[i] = new PatPile( this, 1 + i, QStringLiteral( "stack%1" ).arg( i ) ); stack[i]->setPileRole(PatPile::Tableau); stack[i]->setLayoutPos(dist_x*i, 1.1 ); stack[i]->setAutoTurnTop(true); stack[i]->setSpread(0, 0.25); stack[i]->setBottomPadding( 1.75 ); stack[i]->setHeightPolicy( KCardPile::GrowDown ); stack[i]->setKeyboardSelectHint( KCardPile::FreeFocus ); stack[i]->setKeyboardDropHint( KCardPile::AutoFocusTop ); } setActions(DealerScene::Hint | DealerScene::Demo | DealerScene::Draw); setSolver( new FortyeightSolver( this ) ); } void Fortyeight::restart( const QList & cards ) { lastdeal = false; QList cardList = cards; for ( int r = 0; r < 4; ++r ) { for ( int column = 0; column < 8; ++column ) { QPointF initPos = stack[column]->pos() - QPointF( 0, 2 * deck()->cardHeight() ); addCardForDeal( stack[column], cardList.takeLast(), true, initPos ); } } while ( !cardList.isEmpty() ) { KCard * c = cardList.takeFirst(); c->setPos( talon->pos() ); c->setFaceUp( false ); talon->add( c ); } startDealAnimation(); flipCardToPile( talon->topCard(), pile, DURATION_MOVE ); emit newCardsPossible( true ); } bool Fortyeight::newCards() { if ( talon->isEmpty() ) { if ( lastdeal ) { return false; } else { lastdeal = true; flipCardsToPile( pile->cards(), talon, DURATION_MOVE ); } } else { flipCardToPile( talon->topCard(), pile, DURATION_MOVE ); setKeyboardFocus( pile->topCard() ); } if ( talon->isEmpty() && lastdeal ) emit newCardsPossible( false ); return true; } void Fortyeight::cardsDroppedOnPile( const QList & cards, KCardPile * pile ) { if ( cards.size() <= 1 ) { DealerScene::moveCardsToPile( cards, pile, DURATION_MOVE ); return; } QList freePiles; for ( int i = 0; i < 8; ++i ) if ( stack[i]->isEmpty() && stack[i] != pile ) freePiles << stack[i]; multiStepMove( cards, pile, freePiles, QList(), DURATION_MOVE ); } bool Fortyeight::canPutStore( const KCardPile * pile, const QList &cards ) const { int frees = 0; for (int i = 0; i < 8; i++) if (stack[i]->isEmpty()) frees++; if ( pile->isEmpty()) // destination is empty frees--; if (int( cards.count()) > 1<isEmpty()) return true; KCard *c = cards.first(); // we assume there are only valid sequences return pile->topCard()->suit() == c->suit() && pile->topCard()->rank() == c->rank() + 1; } bool Fortyeight::checkAdd(const PatPile * pile, const QList & oldCards, const QList & newCards) const { switch ( pile->pileRole() ) { case PatPile::Foundation: return checkAddSameSuitAscendingFromAce(oldCards, newCards); case PatPile::Tableau: return canPutStore(pile, newCards); case PatPile::Stock: case PatPile::Waste: default: return false; } } bool Fortyeight::checkRemove( const PatPile * pile, const QList & cards) const { switch ( pile->pileRole() ) { case PatPile::Waste: return cards.first() == pile->topCard(); case PatPile::Tableau: return isSameSuitDescending(cards); case PatPile::Foundation: case PatPile::Stock: default: return false; } } QString Fortyeight::getGameState() const { return QString::number(lastdeal); } void Fortyeight::setGameState( const QString & state ) { lastdeal = state.toInt(); emit newCardsPossible( !lastdeal || !talon->isEmpty() ); } static class FortyEightDealerInfo : public DealerInfo { public: FortyEightDealerInfo() : DealerInfo(I18N_NOOP("Forty & Eight"), FortyAndEightId) {} - DealerScene *createGame() const Q_DECL_OVERRIDE + DealerScene *createGame() const override { return new Fortyeight( this ); } } fortyEightDealerInfo; diff --git a/fortyeight.h b/fortyeight.h index 4d73a8f..4d056e5 100644 --- a/fortyeight.h +++ b/fortyeight.h @@ -1,73 +1,73 @@ /* * Copyright (C) 2000-2009 Stephan Kulow * * License of original code: * ------------------------------------------------------------------------- * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, * provided that the above copyright notice appear in all copies and that * both that copyright notice and this permission notice appear in * supporting documentation. * * This file is provided AS IS with no warranties of any kind. The author * shall have no liability with respect to the infringement of copyrights, * trade secrets or any patents by this file or any part thereof. In no * event will the author be liable for any lost revenue or profits or * other special, indirect and consequential damages. * ------------------------------------------------------------------------- * * License of modifications/additions made after 2009-01-01: * ------------------------------------------------------------------------- * 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, see . * ------------------------------------------------------------------------- */ #ifndef FORTYEIGHT_H #define FORTYEIGHT_H #include "dealer.h" class Fortyeight : public DealerScene { Q_OBJECT public: explicit Fortyeight( const DealerInfo * di ); - void initialize() Q_DECL_OVERRIDE; + void initialize() override; protected: - void setGameState( const QString & state ) Q_DECL_OVERRIDE; - QString getGameState() const Q_DECL_OVERRIDE; - bool checkAdd(const PatPile * pile, const QList & oldCards, const QList & newCards) const Q_DECL_OVERRIDE; - bool checkRemove(const PatPile* pile, const QList & cards) const Q_DECL_OVERRIDE; - void cardsDroppedOnPile( const QList & cards, KCardPile * pile ) Q_DECL_OVERRIDE; - void restart( const QList & cards ) Q_DECL_OVERRIDE; + void setGameState( const QString & state ) override; + QString getGameState() const override; + bool checkAdd(const PatPile * pile, const QList & oldCards, const QList & newCards) const override; + bool checkRemove(const PatPile* pile, const QList & cards) const override; + void cardsDroppedOnPile( const QList & cards, KCardPile * pile ) override; + void restart( const QList & cards ) override; protected slots: - bool newCards() Q_DECL_OVERRIDE; + bool newCards() override; private: bool canPutStore( const KCardPile * pile, const QList &cards ) const; PatPile *talon; PatPile *stack[8]; PatPile *target[8]; PatPile *pile; bool lastdeal; friend class FortyeightSolver; }; #endif diff --git a/freecell.cpp b/freecell.cpp index 4c17864..ae3b956 100644 --- a/freecell.cpp +++ b/freecell.cpp @@ -1,307 +1,307 @@ /* * Copyright (C) 1997 Rodolfo Borges * Copyright (C) 1998-2009 Stephan Kulow * Copyright (C) 2010 Parker Coates * * License of original code: * ------------------------------------------------------------------------- * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, * provided that the above copyright notice appear in all copies and that * both that copyright notice and this permission notice appear in * supporting documentation. * * This file is provided AS IS with no warranties of any kind. The author * shall have no liability with respect to the infringement of copyrights, * trade secrets or any patents by this file or any part thereof. In no * event will the author be liable for any lost revenue or profits or * other special, indirect and consequential damages. * ------------------------------------------------------------------------- * * License of modifications/additions made after 2009-01-01: * ------------------------------------------------------------------------- * 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, see . * ------------------------------------------------------------------------- */ #include "freecell.h" #include "dealerinfo.h" #include "kpat_debug.h" #include "pileutils.h" #include "settings.h" #include "speeds.h" #include "patsolve/freecellsolver.h" #include Freecell::Freecell( const DealerInfo * di ) : DealerScene( di ) { } void Freecell::initialize() { setDeckContents(); const qreal topRowDist = 1.08; const qreal bottomRowDist = 1.13; const qreal targetOffsetDist = ( 7 * bottomRowDist + 1 ) - ( 3 * topRowDist + 1 ); for ( int i = 0; i < 4; ++i ) { freecell[i] = new PatPile ( this, 1 + 8 + i, QStringLiteral( "freecell%1" ).arg( i ) ); freecell[i]->setPileRole(PatPile::Cell); freecell[i]->setLayoutPos(topRowDist * i, 0); freecell[i]->setKeyboardSelectHint( KCardPile::AutoFocusTop ); freecell[i]->setKeyboardDropHint( KCardPile::AutoFocusTop ); } for ( int i = 0; i < 8; ++i ) { store[i] = new PatPile( this, 1 + i, QStringLiteral( "store%1" ).arg( i ) ); store[i]->setPileRole(PatPile::Tableau); store[i]->setLayoutPos( bottomRowDist * i, 1.3 ); store[i]->setBottomPadding( 2.5 ); store[i]->setHeightPolicy( KCardPile::GrowDown ); store[i]->setKeyboardSelectHint( KCardPile::AutoFocusDeepestRemovable ); store[i]->setKeyboardDropHint( KCardPile::AutoFocusTop ); } for ( int i = 0; i < 4; ++i ) { target[i] = new PatPile(this, 1 + 8 + 4 + i, QStringLiteral( "target%1" ).arg( i )); target[i]->setPileRole(PatPile::Foundation); target[i]->setLayoutPos(targetOffsetDist + topRowDist * i, 0); target[i]->setSpread(0, 0); target[i]->setKeyboardSelectHint( KCardPile::NeverFocus ); target[i]->setKeyboardDropHint( KCardPile::ForceFocusTop ); } setActions(DealerScene::Demo | DealerScene::Hint); auto solver = new FreecellSolver( this ); solver->default_max_positions = Settings::freecellSolverIterationsLimit(); setSolver( solver ); setNeededFutureMoves( 4 ); // reserve some } void Freecell::restart( const QList & cards ) { QList cardList = cards; int column = 0; while ( !cardList.isEmpty() ) { addCardForDeal( store[column], cardList.takeLast(), true, store[0]->pos() ); column = (column + 1) % 8; } startDealAnimation(); } QString Freecell::solverFormat() const { QString output; QString tmp; for (int i = 0; i < 4 ; i++) { if (target[i]->isEmpty()) continue; tmp += suitToString(target[i]->topCard()->suit()) + '-' + rankToString(target[i]->topCard()->rank()) + ' '; } if (!tmp.isEmpty()) output += QStringLiteral("Foundations: %1\n").arg(tmp); tmp.truncate(0); for (int i = 0; i < 4 ; i++) { const auto fc = freecell[i]; tmp += (fc->isEmpty() ? QStringLiteral("-") : cardToRankSuitString(fc->topCard())) + ' '; } if (!tmp.isEmpty()) { QString a = QStringLiteral("Freecells: %1\n"); output += a.arg(tmp); } for (int i = 0; i < 8 ; i++) cardsListToLine(output, store[i]->cards()); return output; } void Freecell::cardsDroppedOnPile( const QList & cards, KCardPile * pile ) { if ( cards.size() <= 1 ) { DealerScene::moveCardsToPile( cards, pile, DURATION_MOVE ); return; } QList freeCells; for ( int i = 0; i < 4; ++i ) if ( freecell[i]->isEmpty() ) freeCells << freecell[i]; QList freeStores; for ( int i = 0; i < 8; ++i ) if ( store[i]->isEmpty() && store[i] != pile ) freeStores << store[i]; multiStepMove( cards, pile, freeStores, freeCells, DURATION_MOVE ); } bool Freecell::tryAutomaticMove(KCard *c) { // target move if (DealerScene::tryAutomaticMove(c)) return true; if (c->isAnimated()) return false; if (allowedToRemove(c->pile(), c) && c == c->pile()->topCard()) { for (int i = 0; i < 4; i++) { if (allowedToAdd( freecell[i], {c} )) { moveCardToPile( c, freecell[i], DURATION_MOVE ); return true; } } } return false; } bool Freecell::canPutStore( const KCardPile * pile, const QList & cards ) const { int freeCells = 0; for ( int i = 0; i < 4; ++i ) if ( freecell[i]->isEmpty() ) ++freeCells; int freeStores = 0; for ( int i = 0; i < 8; ++i ) if ( store[i]->isEmpty() && store[i] != pile ) ++freeStores; return cards.size() <= (freeCells + 1) << freeStores && ( pile->isEmpty() || ( pile->topCard()->rank() == cards.first()->rank() + 1 && pile->topCard()->color() != cards.first()->color() ) ); } bool Freecell::checkAdd(const PatPile * pile, const QList & oldCards, const QList & newCards) const { switch (pile->pileRole()) { case PatPile::Tableau: return canPutStore(pile, newCards); case PatPile::Cell: return oldCards.isEmpty() && newCards.size() == 1; case PatPile::Foundation: return checkAddSameSuitAscendingFromAce(oldCards, newCards); default: return false; } } bool Freecell::checkRemove(const PatPile * pile, const QList & cards) const { switch (pile->pileRole()) { case PatPile::Tableau: return isAlternateColorDescending(cards); case PatPile::Cell: return cards.first() == pile->topCard(); case PatPile::Foundation: default: return false; } } QList Freecell::getHints() { QList hintList = getSolverHints(); if ( isDemoActive() ) return hintList; foreach (PatPile * store, patPiles()) { if (store->isEmpty()) continue; QList cards = store->cards(); while (cards.count() && !cards.first()->isFaceUp()) cards.erase(cards.begin()); QList::Iterator iti = cards.begin(); while (iti != cards.end()) { if (allowedToRemove(store, (*iti))) { foreach (PatPile * dest, patPiles()) { int cardIndex = store->indexOf(*iti); if (cardIndex == 0 && dest->isEmpty() && !dest->isFoundation()) continue; if (!checkAdd(dest, dest->cards(), cards)) continue; if ( dest->isFoundation() ) // taken care by solver continue; QList cardsBelow = cards.mid(0, cardIndex); // if it could be here as well, then it's no use if ((cardsBelow.isEmpty() && !dest->isEmpty()) || !checkAdd(store, cardsBelow, cards)) { hintList << MoveHint( *iti, dest, 0 ); } else if (checkPrefering( dest, dest->cards(), cards ) && !checkPrefering( store, cardsBelow, cards )) { // if checkPrefers says so, we add it nonetheless hintList << MoveHint( *iti, dest, 0 ); } } } cards.erase(iti); iti = cards.begin(); } } return hintList; } static class FreecellDealerInfo : public DealerInfo { public: FreecellDealerInfo() : DealerInfo(I18N_NOOP("Freecell"), FreecellId) {} - DealerScene *createGame() const Q_DECL_OVERRIDE + DealerScene *createGame() const override { return new Freecell( this ); } } freecellDealerInfo; diff --git a/freecell.h b/freecell.h index 9f7d84b..2e62c40 100644 --- a/freecell.h +++ b/freecell.h @@ -1,73 +1,73 @@ /* * Copyright (C) 1997 Rodolfo Borges * Copyright (C) 1998-2009 Stephan Kulow * * License of original code: * ------------------------------------------------------------------------- * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, * provided that the above copyright notice appear in all copies and that * both that copyright notice and this permission notice appear in * supporting documentation. * * This file is provided AS IS with no warranties of any kind. The author * shall have no liability with respect to the infringement of copyrights, * trade secrets or any patents by this file or any part thereof. In no * event will the author be liable for any lost revenue or profits or * other special, indirect and consequential damages. * ------------------------------------------------------------------------- * * License of modifications/additions made after 2009-01-01: * ------------------------------------------------------------------------- * 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, see . * ------------------------------------------------------------------------- */ #ifndef FREECELL_H #define FREECELL_H #include "dealer.h" #include "hint.h" class Freecell : public DealerScene { Q_OBJECT public: explicit Freecell( const DealerInfo * di ); - void initialize() Q_DECL_OVERRIDE; + void initialize() override; protected: - bool checkAdd(const PatPile * pile, const QList & oldCards, const QList & newCards) const Q_DECL_OVERRIDE; - bool checkRemove(const PatPile * pile, const QList & cards) const Q_DECL_OVERRIDE; - void cardsDroppedOnPile( const QList & cards, KCardPile * pile ) Q_DECL_OVERRIDE; - void restart( const QList & cards ) Q_DECL_OVERRIDE; - QList getHints() Q_DECL_OVERRIDE; + bool checkAdd(const PatPile * pile, const QList & oldCards, const QList & newCards) const override; + bool checkRemove(const PatPile * pile, const QList & cards) const override; + void cardsDroppedOnPile( const QList & cards, KCardPile * pile ) override; + void restart( const QList & cards ) override; + QList getHints() override; protected slots: - bool tryAutomaticMove( KCard * c ) Q_DECL_OVERRIDE; + bool tryAutomaticMove( KCard * c ) override; private: bool canPutStore( const KCardPile * pile, const QList & cards ) const; virtual QString solverFormat() const; PatPile* store[8]; PatPile* freecell[4]; PatPile* target[4]; friend class FreecellSolver; }; #endif diff --git a/gameselectionscene.cpp b/gameselectionscene.cpp index a508b9d..ce962be 100644 --- a/gameselectionscene.cpp +++ b/gameselectionscene.cpp @@ -1,392 +1,392 @@ /* * Copyright (C) 2008-2009 Stephan Kulow * Copyright (C) 2008-2009 Parker Coates * * 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, see . */ #include "gameselectionscene.h" #include "dealerinfo.h" #include "kpat_debug.h" #include "renderer.h" #include #include #include #include #include #include #include #include namespace { const qreal boxPaddingRatio = 0.037; const qreal spacingRatio = 0.10; const qreal textToBoxHeightRatio = 1 / 6.0; const qreal textToBoxWidthRatio = 0.57; const int hoverTransitionDuration = 300; const int minimumFontSize = 5; } class GameSelectionScene::GameSelectionBox : public QGraphicsObject { Q_OBJECT Q_PROPERTY( qreal fade READ hoverFadeAmount WRITE setHoverFadeAmount ) public: GameSelectionBox( const QString & name, int id ) : m_label( name ), m_gameId( id ), m_anim( new QPropertyAnimation( this, "fade", this ) ), m_highlightFadeAmount( 0 ), m_previewPath( QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral( "kpat/previews/%1.png" ).arg( id ) ) ) { setAcceptHoverEvents( true ); m_anim->setDuration( hoverTransitionDuration ); m_anim->setStartValue( qreal( 0.0 ) ); m_anim->setEndValue( qreal( 1.0 ) ); m_anim->setEasingCurve( QEasingCurve::InOutSine ); } void setSize( const QSize & size ) { if ( size != m_size ) { m_size = size; m_preview = QPixmap(); } } - QRectF boundingRect() const Q_DECL_OVERRIDE + QRectF boundingRect() const override { return QRectF( QPointF(), m_size ); } QString label() const { return m_label; } int id() const { return m_gameId; } void setHighlighted( bool highlighted ) { if ( highlighted ) { m_anim->setDirection( QAbstractAnimation::Forward ); if ( m_anim->state() != QAbstractAnimation::Running ) m_anim->start(); } else { m_anim->setDirection( QAbstractAnimation::Backward ); if ( m_anim->state() != QAbstractAnimation::Running ) m_anim->start(); } } static bool lessThan( const GameSelectionBox * a, const GameSelectionBox * b ) { return a->m_label < b->m_label; } signals: void selected( int gameId ); void hoverChanged( GameSelectionBox * box, bool hovered ); protected: - void mousePressEvent( QGraphicsSceneMouseEvent * event ) Q_DECL_OVERRIDE + void mousePressEvent( QGraphicsSceneMouseEvent * event ) override { Q_UNUSED( event ) emit selected( m_gameId ); } - void hoverEnterEvent( QGraphicsSceneHoverEvent * event ) Q_DECL_OVERRIDE + void hoverEnterEvent( QGraphicsSceneHoverEvent * event ) override { Q_UNUSED( event ) emit hoverChanged( this, true ); } - void hoverLeaveEvent( QGraphicsSceneHoverEvent * event ) Q_DECL_OVERRIDE + void hoverLeaveEvent( QGraphicsSceneHoverEvent * event ) override { Q_UNUSED( event ) emit hoverChanged( this, false ); } qreal hoverFadeAmount() const { return m_highlightFadeAmount; } void setHoverFadeAmount( qreal amount ) { m_highlightFadeAmount = amount; update(); } - void paint( QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget = nullptr ) Q_DECL_OVERRIDE + void paint( QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget = nullptr ) override { Q_UNUSED( option ) Q_UNUSED( widget ) Renderer * r = Renderer::self(); int textAreaHeight = m_size.height() * textToBoxHeightRatio; int padding = boxPaddingRatio * m_size.width(); QSize previewSize( m_size.height() - padding * 2, m_size.height() - padding * 2 - textAreaHeight ); QRect textRect( 0, 0, m_size.width(), textAreaHeight ); if ( m_highlightFadeAmount < 1 ) painter->drawPixmap( 0, 0, r->spritePixmap( QStringLiteral("bubble"), m_size ) ); if ( m_highlightFadeAmount > 0 ) { if ( m_highlightFadeAmount < 1 ) { // Using QPainter::setOpacity is currently very inefficient, so to // paint a semitransparent pixmap, we have to do some fiddling. QPixmap transPix( m_size ); transPix.fill( Qt::transparent ); QPainter p( &transPix ); p.drawPixmap( 0, 0, r->spritePixmap( QStringLiteral("bubble_hover"), m_size ) ); p.setCompositionMode( QPainter::CompositionMode_DestinationIn ); p.fillRect( transPix.rect(), QColor( 0, 0, 0, m_highlightFadeAmount * 255 ) ); painter->drawPixmap( 0, 0, transPix ); } else { painter->drawPixmap( 0, 0, r->spritePixmap( QStringLiteral("bubble_hover"), m_size ) ); } } // Draw game preview if ( m_preview.isNull() ) { QPixmap previewPix( m_previewPath ); m_preview = previewPix.scaled( previewSize, Qt::KeepAspectRatio, Qt::SmoothTransformation ); } painter->drawPixmap( ( m_size.width() - previewSize.width() ) / 2, padding + textAreaHeight, m_preview ); // Draw label painter->setFont( scene()->font() ); painter->setPen( KColorUtils::mix( r->colorOfElement( QStringLiteral("bubble_text_color") ), r->colorOfElement( QStringLiteral("bubble_hover_text_color") ), m_highlightFadeAmount ) ); painter->drawText( textRect, Qt::AlignCenter, m_label ); } private: QString m_label; int m_gameId; QSize m_size; QPropertyAnimation * m_anim; qreal m_highlightFadeAmount; QPixmap m_preview; QString m_previewPath; }; GameSelectionScene::GameSelectionScene( QObject * parent ) : QGraphicsScene( parent ), m_selectionIndex( -1 ) { foreach (const DealerInfo * i, DealerInfoList::self()->games()) { GameSelectionBox * box = new GameSelectionBox( i->baseName(), i->baseId() ); m_boxes.append( box ); addItem( box ); connect( box, &GameSelectionBox::selected, this, &GameSelectionScene::gameSelected ); connect( box, &GameSelectionBox::hoverChanged, this, &GameSelectionScene::boxHoverChanged ); } std::sort( m_boxes.begin(), m_boxes.end(), GameSelectionBox::lessThan ); } GameSelectionScene::~GameSelectionScene() { } void GameSelectionScene::resizeScene( const QSize & size ) { int numBoxes = m_boxes.size(); qreal boxAspect = Renderer::self()->aspectRatioOfElement( QStringLiteral("bubble") ); qreal sceneAspect = qreal( size.width() ) / size.height(); // Determine the optimal number of rows/columns for the grid m_columns = 1; int numRows = 1; int bestNumRows = 1; qreal lowestError = 10e10; for ( numRows = 1; numRows <= numBoxes; ++numRows ) { m_columns = ceil( qreal( numBoxes ) / numRows ); int numNonEmptyRows = ceil( qreal( numBoxes ) / m_columns ); qreal gridAspect = boxAspect * m_columns / numNonEmptyRows; qreal error = gridAspect > sceneAspect ? gridAspect / sceneAspect : sceneAspect / gridAspect; if ( error < lowestError ) { lowestError = error; bestNumRows = numRows; } } numRows = bestNumRows; m_columns = ceil( qreal( numBoxes ) / bestNumRows ); // Calculate the box and grid dimensions qreal gridAspect = boxAspect * ( m_columns + spacingRatio * ( m_columns + 1 ) ) / ( numRows + spacingRatio * ( numRows + 1 ) ); int boxWidth, boxHeight; if ( gridAspect > sceneAspect ) { boxWidth = size.width() / ( m_columns + spacingRatio * ( m_columns + 1 ) ); boxHeight = boxWidth / boxAspect; } else { boxHeight = size.height() / ( numRows + spacingRatio * ( numRows + 1 ) ); boxWidth = boxHeight * boxAspect; } int gridWidth = boxWidth * ( m_columns + spacingRatio * ( m_columns + 1 ) ); int gridHeight = boxHeight * ( numRows + spacingRatio * ( numRows + 1 ) ); int xOffset = (gridWidth - size.width()) / 2 - boxWidth * spacingRatio; int yOffset = (gridHeight - size.height()) / 2 - boxHeight * spacingRatio; // Set up the sceneRect so that the grid is centered setSceneRect( xOffset, yOffset, size.width(), size.height() ); QPixmap pix( 1, 1 ); QPainter p( &pix ); QFont f; // Initial font size estimate int pixelFontSize = boxHeight * (textToBoxHeightRatio - 1.5 * boxPaddingRatio); f.setPixelSize( pixelFontSize ); p.setFont( f ); qreal maxLabelWidth = boxWidth * textToBoxWidthRatio; int row = 0; int col = 0; foreach ( GameSelectionBox * box, m_boxes ) { // Reduce font size until the label fits while ( pixelFontSize > minimumFontSize && p.boundingRect( QRectF(), box->label() ).width() > maxLabelWidth ) { f.setPixelSize( --pixelFontSize ); p.setFont( f ); } // Position and size the boxes box->setPos( col * ( boxWidth * ( 1 + spacingRatio ) ), row * ( boxHeight * ( 1 + spacingRatio ) ) ); box->setSize( QSize( boxWidth, boxHeight ) ); // Increment column and row ++col; if ( col == m_columns ) { col = 0; ++row; } } setFont( f ); } void GameSelectionScene::keyReleaseEvent( QKeyEvent * event ) { if ( m_selectionIndex == -1 ) { m_selectionIndex = 0; m_boxes.at( m_selectionIndex )->setHighlighted( true ); } else if ( event->key() == Qt::Key_Up && m_selectionIndex / m_columns > 0 ) { m_boxes.at( m_selectionIndex )->setHighlighted( false ); m_selectionIndex -= m_columns; m_boxes.at( m_selectionIndex )->setHighlighted( true ); } else if ( event->key() == Qt::Key_Down && m_selectionIndex + m_columns < m_boxes.size() ) { m_boxes.at( m_selectionIndex )->setHighlighted( false ); m_selectionIndex += m_columns; m_boxes.at( m_selectionIndex )->setHighlighted( true ); } else if ( event->key() == Qt::Key_Left && m_selectionIndex % m_columns > 0 ) { m_boxes.at( m_selectionIndex )->setHighlighted( false ); --m_selectionIndex; m_boxes.at( m_selectionIndex )->setHighlighted( true ); } else if ( event->key() == Qt::Key_Right && m_selectionIndex % m_columns < m_columns - 1 && m_selectionIndex < m_boxes.size() - 1 ) { m_boxes.at( m_selectionIndex )->setHighlighted( false ); ++m_selectionIndex; m_boxes.at( m_selectionIndex )->setHighlighted( true ); } else if ( ( event->key() == Qt::Key_Return || event->key() ==Qt::Key_Enter || event->key() ==Qt::Key_Space ) && m_selectionIndex != -1 ) { emit gameSelected( m_boxes.at( m_selectionIndex )->id() ); } } void GameSelectionScene::boxHoverChanged( GameSelectionScene::GameSelectionBox * box, bool hovered ) { if ( hovered ) { if ( m_selectionIndex != -1 ) m_boxes.at( m_selectionIndex )->setHighlighted( false ); m_selectionIndex = m_boxes.indexOf( box ); box->setHighlighted( true ); } else { if ( m_boxes.indexOf( box ) == m_selectionIndex ) { m_selectionIndex = -1; box->setHighlighted( false ); } } } #include "gameselectionscene.moc" #include "moc_gameselectionscene.cpp" diff --git a/gameselectionscene.h b/gameselectionscene.h index cd53796..a19539a 100644 --- a/gameselectionscene.h +++ b/gameselectionscene.h @@ -1,52 +1,52 @@ /* * Copyright (C) 2008-2009 Stephan Kulow * Copyright (C) 2008-2009 Parker Coates * * 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, see . */ #ifndef GAMESELECTIONSCENE_H #define GAMESELECTIONSCENE_H #include class GameSelectionScene : public QGraphicsScene { Q_OBJECT class GameSelectionBox; public: explicit GameSelectionScene( QObject * parent ); ~GameSelectionScene(); void resizeScene( const QSize & size ); signals: void gameSelected( int i ); protected: - void keyReleaseEvent( QKeyEvent * event ) Q_DECL_OVERRIDE; + void keyReleaseEvent( QKeyEvent * event ) override; private slots: void boxHoverChanged( GameSelectionBox * box, bool hovered ); private: int m_columns; int m_selectionIndex; QList m_boxes; }; #endif diff --git a/golf.cpp b/golf.cpp index 8112688..a1d3d99 100644 --- a/golf.cpp +++ b/golf.cpp @@ -1,205 +1,205 @@ /* * Copyright (C) 2001-2009 Stephan Kulow * Copyright (C) 2010 Parker Coates * * License of original code: * ------------------------------------------------------------------------- * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, * provided that the above copyright notice appear in all copies and that * both that copyright notice and this permission notice appear in * supporting documentation. * * This file is provided AS IS with no warranties of any kind. The author * shall have no liability with respect to the infringement of copyrights, * trade secrets or any patents by this file or any part thereof. In no * event will the author be liable for any lost revenue or profits or * other special, indirect and consequential damages. * ------------------------------------------------------------------------- * * License of modifications/additions made after 2009-01-01: * ------------------------------------------------------------------------- * 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, see . * ------------------------------------------------------------------------- */ #include "golf.h" #include "dealerinfo.h" #include "speeds.h" #include "patsolve/golfsolver.h" #include "pileutils.h" #include "settings.h" #include Golf::Golf( const DealerInfo * di ) : DealerScene( di ) { } void Golf::initialize() { const qreal dist_x = 1.11; const qreal smallNeg = -1e-6; setDeckContents(); talon = new PatPile( this, 0, QStringLiteral("talon") ); talon->setPileRole(PatPile::Stock); talon->setLayoutPos(0, smallNeg); talon->setSpread(0, 0); talon->setKeyboardSelectHint( KCardPile::NeverFocus ); talon->setKeyboardDropHint( KCardPile::NeverFocus ); connect( talon, &KCardPile::clicked, this, &DealerScene::drawDealRowOrRedeal ); waste = new PatPile( this, 8, QStringLiteral("waste") ); waste->setPileRole(PatPile::Foundation); waste->setLayoutPos(1.1, smallNeg); waste->setSpread(0.12, 0); waste->setRightPadding( 5 * dist_x ); waste->setWidthPolicy( KCardPile::GrowRight ); waste->setKeyboardSelectHint( KCardPile::NeverFocus ); waste->setKeyboardDropHint( KCardPile::AutoFocusTop ); for( int r = 0; r < 7; ++r ) { stack[r] = new PatPile( this, 1 + r, QStringLiteral("stack%1").arg(r) ); stack[r]->setPileRole(PatPile::Tableau); stack[r]->setLayoutPos(r*dist_x,0); // Manual tweak of the pile z values to make some animations better. stack[r]->setZValue((7-r)/100.0); stack[r]->setBottomPadding( 1.3 ); stack[r]->setHeightPolicy( KCardPile::GrowDown ); stack[r]->setKeyboardSelectHint( KCardPile::AutoFocusTop ); stack[r]->setKeyboardDropHint( KCardPile::NeverFocus ); } setActions(DealerScene::Hint | DealerScene::Demo | DealerScene::Draw); auto solver = new GolfSolver( this ); solver->default_max_positions = Settings::golfSolverIterationsLimit(); setSolver( solver ); connect( this, &KCardScene::cardClicked, this, &DealerScene::tryAutomaticMove ); } bool Golf::checkAdd(const PatPile * pile, const QList & oldCards, const QList & newCards) const { return pile->pileRole() == PatPile::Foundation && ( newCards.first()->rank() == oldCards.last()->rank() + 1 || newCards.first()->rank() == oldCards.last()->rank() - 1 ); } bool Golf::checkRemove(const PatPile * pile, const QList & cards) const { return pile->pileRole() == PatPile::Tableau && cards.first() == pile->topCard(); } void Golf::restart( const QList & cards ) { QList cardList = cards; for ( int i = 0; i < 5; ++i ) for ( int r = 0; r < 7; ++r ) addCardForDeal( stack[r], cardList.takeLast(), true, stack[6]->pos() ); while ( !cardList.isEmpty() ) { KCard * c = cardList.takeFirst(); c->setPos( talon->pos() ); c->setFaceUp( false ); talon->add( c ); } startDealAnimation(); flipCardToPile(talon->topCard(), waste, DURATION_MOVE); emit newCardsPossible( true ); } bool Golf::newCards() { if ( talon->isEmpty() ) return false; flipCardToPile(talon->topCard(), waste, DURATION_MOVE); if ( talon->isEmpty() ) emit newCardsPossible( false ); return true; } bool Golf::drop() { for ( int i = 0; i < 7; ++i ) if ( !stack[i]->isEmpty() ) return false; if ( !talon->isEmpty() ) { flipCardToPile( talon->topCard(), waste, DURATION_MOVE ); takeState(); return true; } return false; } void Golf::setGameState( const QString & state ) { Q_UNUSED( state ); emit newCardsPossible( !talon->isEmpty() ); } QString Golf::solverFormat() const { QString output; output += QLatin1String("Foundations: ") + (waste->isEmpty() ? QLatin1String("-") : cardToRankSuitString(waste->topCard())) + '\n'; output += QLatin1String("Talon:"); for ( int i = talon->count()-1; i >= 0; --i ) { output += QLatin1Char(' ')+cardToRankSuitString(talon->at( i )); } output += QLatin1Char('\n'); for (int i = 0; i < 7 ; i++) cardsListToLine(output, stack[i]->cards()); return output; } static class GolfDealerInfo : public DealerInfo { public: GolfDealerInfo() : DealerInfo(I18N_NOOP("Golf"), GolfId) {} - DealerScene *createGame() const Q_DECL_OVERRIDE + DealerScene *createGame() const override { return new Golf( this ); } } golfDealerInfo; diff --git a/golf.h b/golf.h index dc89071..de5997a 100644 --- a/golf.h +++ b/golf.h @@ -1,69 +1,69 @@ /* * Copyright (C) 2001-2009 Stephan Kulow * * License of original code: * ------------------------------------------------------------------------- * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, * provided that the above copyright notice appear in all copies and that * both that copyright notice and this permission notice appear in * supporting documentation. * * This file is provided AS IS with no warranties of any kind. The author * shall have no liability with respect to the infringement of copyrights, * trade secrets or any patents by this file or any part thereof. In no * event will the author be liable for any lost revenue or profits or * other special, indirect and consequential damages. * ------------------------------------------------------------------------- * * License of modifications/additions made after 2009-01-01: * ------------------------------------------------------------------------- * 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, see . * ------------------------------------------------------------------------- */ #ifndef GOLF_H #define GOLF_H #include "dealer.h" class Golf : public DealerScene { Q_OBJECT public: explicit Golf( const DealerInfo * di ); - void initialize() Q_DECL_OVERRIDE; + void initialize() override; QString solverFormat() const; protected: - void setGameState( const QString & state ) Q_DECL_OVERRIDE; - bool checkAdd(const PatPile * pile, const QList & oldCards, const QList & newCards) const Q_DECL_OVERRIDE; - bool checkRemove(const PatPile * pile, const QList & cards) const Q_DECL_OVERRIDE; - void restart( const QList & cards ) Q_DECL_OVERRIDE; - bool drop() Q_DECL_OVERRIDE; + void setGameState( const QString & state ) override; + bool checkAdd(const PatPile * pile, const QList & oldCards, const QList & newCards) const override; + bool checkRemove(const PatPile * pile, const QList & cards) const override; + void restart( const QList & cards ) override; + bool drop() override; protected slots: - bool newCards() Q_DECL_OVERRIDE; + bool newCards() override; private: PatPile* talon; PatPile* stack[7]; PatPile* waste; friend class GolfSolver; }; #endif diff --git a/grandf.cpp b/grandf.cpp index 400f744..6010bd0 100644 --- a/grandf.cpp +++ b/grandf.cpp @@ -1,210 +1,210 @@ /* * Copyright (C) 1995 Paul Olav Tvete * Copyright (C) 2000-2009 Stephan Kulow * Copyright (C) 2010 Parker Coates * * License of original code: * ------------------------------------------------------------------------- * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, * provided that the above copyright notice appear in all copies and that * both that copyright notice and this permission notice appear in * supporting documentation. * * This file is provided AS IS with no warranties of any kind. The author * shall have no liability with respect to the infringement of copyrights, * trade secrets or any patents by this file or any part thereof. In no * event will the author be liable for any lost revenue or profits or * other special, indirect and consequential damages. * ------------------------------------------------------------------------- * * License of modifications/additions made after 2009-01-01: * ------------------------------------------------------------------------- * 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, see . * ------------------------------------------------------------------------- */ #include "grandf.h" #include "dealerinfo.h" #include "pileutils.h" #include "speeds.h" #include "patsolve/grandfsolver.h" #include Grandf::Grandf( const DealerInfo * di ) : DealerScene( di ) { } void Grandf::initialize() { setDeckContents(); const qreal distx = 1.4; const qreal targetOffset = 1.5 * distx; for ( int i = 0; i < 4; ++i ) { target[i] = new PatPile( this, i + 1, QStringLiteral("target%1").arg(i) ); target[i]->setPileRole(PatPile::Foundation); target[i]->setLayoutPos(targetOffset+i*distx, 0); target[i]->setSpread(0, 0); target[i]->setKeyboardSelectHint( KCardPile::NeverFocus ); target[i]->setKeyboardDropHint( KCardPile::ForceFocusTop ); } for ( int i = 0; i < 7; ++i ) { store[i] = new PatPile( this, 5 + i, QStringLiteral("store%1").arg(i) ); store[i]->setPileRole(PatPile::Tableau); store[i]->setLayoutPos(distx*i, 1.2); store[i]->setAutoTurnTop(true); store[i]->setBottomPadding( 2.5 ); store[i]->setHeightPolicy( KCardPile::GrowDown ); store[i]->setKeyboardSelectHint( KCardPile::FreeFocus ); store[i]->setKeyboardDropHint( KCardPile::AutoFocusTop ); } setActions(DealerScene::Hint | DealerScene::Demo | DealerScene::Redeal); setSolver( new GrandfSolver( this ) ); } void Grandf::restart( const QList & cards ) { deal( cards ); numberOfDeals = 1; emit newCardsPossible( true ); } bool Grandf::newCards() { if ( numberOfDeals >= 3 ) return false; // NOTE: This is not quite correct. The piles should be turned face down // (i.e. partially reversed) during collection. QList collectedCards; for ( int pos = 6; pos >= 0; --pos ) { collectedCards << store[pos]->cards(); store[pos]->clear(); } deal( collectedCards ); takeState(); numberOfDeals++; if (numberOfDeals == 3) emit newCardsPossible(false); return true; } void Grandf::deal( const QList & cardsToDeal ) { setKeyboardModeActive( false ); QList cards = cardsToDeal; QPointF initPos( 1.4 * 3 * deck()->cardWidth(), 1.2 * deck()->cardHeight() ); int start = 0; int stop = 7-1; int dir = 1; for (int round=0; round < 7; round++) { int i = start; do { if (!cards.isEmpty()) addCardForDeal( store[i], cards.takeLast(), (i == start), initPos ); i += dir; } while ( i != stop + dir); int t = start; start = stop; stop = t+dir; dir = -dir; } int i = 0; while (!cards.isEmpty()) { addCardForDeal( store[i+1], cards.takeLast(), true, initPos ); i = (i+1)%6; } for (int round=0; round < 7; round++) { KCard *c = store[round]->topCard(); if (c) c->setFaceUp(true); } startDealAnimation(); } bool Grandf::checkAdd(const PatPile * pile, const QList & oldCards, const QList & newCards) const { switch (pile->pileRole()) { case PatPile::Tableau: if (oldCards.isEmpty()) return newCards.first()->rank() == KCardDeck::King; else return newCards.first()->rank() == oldCards.last()->rank() - 1 && newCards.first()->suit() == oldCards.last()->suit(); case PatPile::Foundation: default: return checkAddSameSuitAscendingFromAce(oldCards, newCards); } } bool Grandf::checkRemove(const PatPile * pile, const QList & cards) const { return pile->pileRole() == PatPile::Tableau && cards.first()->isFaceUp(); } QString Grandf::getGameState() const { return QString::number(numberOfDeals); } void Grandf::setGameState( const QString & state ) { numberOfDeals = state.toInt(); emit newCardsPossible(numberOfDeals < 3); } static class GrandfDealerInfo : public DealerInfo { public: GrandfDealerInfo() : DealerInfo(I18N_NOOP("Grandfather"), GrandfatherId) {} - DealerScene *createGame() const Q_DECL_OVERRIDE + DealerScene *createGame() const override { return new Grandf( this ); } } grandfDealerInfo; diff --git a/grandf.h b/grandf.h index 68f7c7e..e45b0f5 100644 --- a/grandf.h +++ b/grandf.h @@ -1,72 +1,72 @@ /* * Copyright (C) 1995 Paul Olav Tvete * Copyright (C) 2000-2009 Stephan Kulow * * License of original code: * ------------------------------------------------------------------------- * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, * provided that the above copyright notice appear in all copies and that * both that copyright notice and this permission notice appear in * supporting documentation. * * This file is provided AS IS with no warranties of any kind. The author * shall have no liability with respect to the infringement of copyrights, * trade secrets or any patents by this file or any part thereof. In no * event will the author be liable for any lost revenue or profits or * other special, indirect and consequential damages. * ------------------------------------------------------------------------- * * License of modifications/additions made after 2009-01-01: * ------------------------------------------------------------------------- * 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, see . * ------------------------------------------------------------------------- */ #ifndef GRANDF_H #define GRANDF_H #include "dealer.h" class Grandf : public DealerScene { Q_OBJECT public: explicit Grandf( const DealerInfo * di ); - void initialize() Q_DECL_OVERRIDE; + void initialize() override; protected: - void setGameState( const QString & state ) Q_DECL_OVERRIDE; - QString getGameState() const Q_DECL_OVERRIDE; - bool checkAdd(const PatPile * pile, const QList & oldCards, const QList & newCards) const Q_DECL_OVERRIDE; - bool checkRemove(const PatPile * pile, const QList & cards) const Q_DECL_OVERRIDE; - void restart( const QList & cards ) Q_DECL_OVERRIDE; + void setGameState( const QString & state ) override; + QString getGameState() const override; + bool checkAdd(const PatPile * pile, const QList & oldCards, const QList & newCards) const override; + bool checkRemove(const PatPile * pile, const QList & cards) const override; + void restart( const QList & cards ) override; protected slots: - bool newCards() Q_DECL_OVERRIDE; + bool newCards() override; private: void deal( const QList & cardsToDeal ); PatPile* store[7]; PatPile* target[4]; int numberOfDeals; friend class GrandfSolver; }; #endif diff --git a/gypsy.cpp b/gypsy.cpp index 6b22094..ff2f547 100644 --- a/gypsy.cpp +++ b/gypsy.cpp @@ -1,187 +1,187 @@ /* * Copyright (C) 2000-2009 Stephan Kulow * Copyright (C) 2010 Parker Coates * * License of original code: * ------------------------------------------------------------------------- * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, * provided that the above copyright notice appear in all copies and that * both that copyright notice and this permission notice appear in * supporting documentation. * * This file is provided AS IS with no warranties of any kind. The author * shall have no liability with respect to the infringement of copyrights, * trade secrets or any patents by this file or any part thereof. In no * event will the author be liable for any lost revenue or profits or * other special, indirect and consequential damages. * ------------------------------------------------------------------------- * * License of modifications/additions made after 2009-01-01: * ------------------------------------------------------------------------- * 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, see . * ------------------------------------------------------------------------- */ #include "gypsy.h" #include "dealerinfo.h" #include "pileutils.h" #include "patsolve/gypsysolver.h" #include Gypsy::Gypsy( const DealerInfo * di ) : DealerScene( di ) { } void Gypsy::initialize() { const qreal dist_x = 1.11; const qreal dist_y = 1.11; setDeckContents( 2 ); talon = new PatPile( this, 0, QStringLiteral("talon") ); talon->setPileRole(PatPile::Stock); talon->setLayoutPos(8.5 * dist_x + 0.4, 4 * dist_y); talon->setKeyboardSelectHint( KCardPile::NeverFocus ); talon->setKeyboardDropHint( KCardPile::NeverFocus ); connect( talon, &KCardPile::clicked, this, &DealerScene::drawDealRowOrRedeal ); for ( int i = 0; i < 8; ++i ) { target[i] = new PatPile( this, i + 1, QStringLiteral("target%1").arg(i) ); target[i]->setPileRole(PatPile::Foundation); target[i]->setLayoutPos(dist_x*(8+(i/4)) + 0.4, (i%4)*dist_y); target[i]->setKeyboardSelectHint( KCardPile::NeverFocus ); target[i]->setKeyboardDropHint( KCardPile::ForceFocusTop ); } for ( int i = 0; i < 8; ++i ) { store[i] = new PatPile( this, 9 + i, QStringLiteral("store%1").arg(i) ); store[i]->setPileRole(PatPile::Tableau); store[i]->setLayoutPos(dist_x*i,0); store[i]->setAutoTurnTop(true); store[i]->setBottomPadding( 4 * dist_y ); store[i]->setHeightPolicy( KCardPile::GrowDown ); store[i]->setKeyboardSelectHint( KCardPile::AutoFocusDeepestRemovable ); store[i]->setKeyboardDropHint( KCardPile::AutoFocusTop ); } setActions(DealerScene::Hint | DealerScene::Demo | DealerScene::Deal); setSolver( new GypsySolver( this ) ); } void Gypsy::restart( const QList & cards ) { QList cardList = cards; for ( int round = 0; round < 8; ++round ) addCardForDeal(store[round], cardList.takeLast(), false, store[round]->pos() + QPointF(-2*deck()->cardWidth(),-1.1*deck()->cardHeight())); for ( int round = 0; round < 8; ++round ) addCardForDeal(store[round], cardList.takeLast(), true, store[round]->pos() + QPointF(-3*deck()->cardWidth(),-1.6*deck()->cardHeight())); for ( int round = 0; round < 8; ++round ) addCardForDeal(store[round], cardList.takeLast(), true, store[round]->pos() + QPointF(-4*deck()->cardWidth(),-2.1*deck()->cardHeight())); while ( !cardList.isEmpty() ) { KCard * c = cardList.takeFirst(); c->setPos( talon->pos() ); c->setFaceUp( false ); talon->add( c ); } startDealAnimation(); emit newCardsPossible(true); } bool Gypsy::checkAdd(const PatPile * pile, const QList & oldCards, const QList & newCards) const { switch (pile->pileRole()) { case PatPile::Tableau: return checkAddAlternateColorDescending(oldCards, newCards); case PatPile::Foundation: return checkAddSameSuitAscendingFromAce(oldCards, newCards); case PatPile::Stock: default: return false; } } bool Gypsy::checkRemove(const PatPile * pile, const QList & cards) const { switch (pile->pileRole()) { case PatPile::Tableau: return isAlternateColorDescending(cards); case PatPile::Foundation: return cards.first() == pile->topCard(); case PatPile::Stock: default: return false; } } bool Gypsy::newCards() { if ( talon->isEmpty() ) return false; for ( int round = 0; round < 8; ++round ) { KCard * c = talon->topCard(); flipCardToPileAtSpeed( c, store[round], DEAL_SPEED ); c->setZValue( c->zValue() + 8 - round ); } if (talon->isEmpty()) emit newCardsPossible(false); return true; } void Gypsy::setGameState( const QString & state ) { Q_UNUSED( state ) emit newCardsPossible(!talon->isEmpty()); } static class GypsyDealerInfo : public DealerInfo { public: GypsyDealerInfo() : DealerInfo(I18N_NOOP("Gypsy"), GypsyId) {} - DealerScene *createGame() const Q_DECL_OVERRIDE + DealerScene *createGame() const override { return new Gypsy( this ); } } gypsyDealerInfo; diff --git a/gypsy.h b/gypsy.h index 1502120..59efb5c 100644 --- a/gypsy.h +++ b/gypsy.h @@ -1,67 +1,67 @@ /* * Copyright (C) 2000-2009 Stephan Kulow * * License of original code: * ------------------------------------------------------------------------- * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, * provided that the above copyright notice appear in all copies and that * both that copyright notice and this permission notice appear in * supporting documentation. * * This file is provided AS IS with no warranties of any kind. The author * shall have no liability with respect to the infringement of copyrights, * trade secrets or any patents by this file or any part thereof. In no * event will the author be liable for any lost revenue or profits or * other special, indirect and consequential damages. * ------------------------------------------------------------------------- * * License of modifications/additions made after 2009-01-01: * ------------------------------------------------------------------------- * 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, see . * ------------------------------------------------------------------------- */ #ifndef GYPSY_H #define GYPSY_H #include "dealer.h" class Gypsy : public DealerScene { Q_OBJECT public: explicit Gypsy( const DealerInfo * di ); - void initialize() Q_DECL_OVERRIDE; + void initialize() override; protected: - void setGameState( const QString & state ) Q_DECL_OVERRIDE; - bool checkAdd(const PatPile * pile, const QList & oldCards, const QList & newCards) const Q_DECL_OVERRIDE; - bool checkRemove(const PatPile * pile, const QList & cards) const Q_DECL_OVERRIDE; - void restart( const QList & cards ) Q_DECL_OVERRIDE; + void setGameState( const QString & state ) override; + bool checkAdd(const PatPile * pile, const QList & oldCards, const QList & newCards) const override; + bool checkRemove(const PatPile * pile, const QList & cards) const override; + void restart( const QList & cards ) override; protected slots: - bool newCards() Q_DECL_OVERRIDE; + bool newCards() override; private: PatPile* talon; PatPile* store[8]; PatPile* target[8]; friend class GypsySolver; }; #endif diff --git a/idiot.cpp b/idiot.cpp index f68bb18..14679ae 100644 --- a/idiot.cpp +++ b/idiot.cpp @@ -1,269 +1,269 @@ /* * Copyright (C) 1995 Paul Olav Tvete * Copyright (C) 2000-2009 Stephan Kulow * Copyright (C) 2010 Parker Coates * * License of original code: * ------------------------------------------------------------------------- * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, * provided that the above copyright notice appear in all copies and that * both that copyright notice and this permission notice appear in * supporting documentation. * * This file is provided AS IS with no warranties of any kind. The author * shall have no liability with respect to the infringement of copyrights, * trade secrets or any patents by this file or any part thereof. In no * event will the author be liable for any lost revenue or profits or * other special, indirect and consequential damages. * ------------------------------------------------------------------------- * * License of modifications/additions made after 2009-01-01: * ------------------------------------------------------------------------- * 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, see . * ------------------------------------------------------------------------- */ #include "idiot.h" #include "dealerinfo.h" #include "patsolve/idiotsolver.h" #include Idiot::Idiot( const DealerInfo * di ) : DealerScene( di ) { } void Idiot::initialize() { setSceneAlignment( AlignHCenter | AlignVCenter ); setDeckContents(); // Create the talon to the left. talon = new PatPile( this, 0, QStringLiteral("talon") ); talon->setPileRole(PatPile::Stock); talon->setLayoutPos(0, 0); talon->setSpread(0, 0); talon->setKeyboardSelectHint( KCardPile::NeverFocus ); talon->setKeyboardDropHint( KCardPile::NeverFocus ); connect(talon, &PatPile::clicked, this, &Idiot::newCards); const qreal distx = 1.1; // Create 4 piles where the cards will be placed during the game. for( int i = 0; i < 4; ++i ) { m_play[i] = new PatPile( this, i + 1, QStringLiteral( "play%1" ).arg( i )); m_play[i]->setPileRole(PatPile::Tableau); m_play[i]->setLayoutPos(1.5 + distx * i, 0); m_play[i]->setBottomPadding( 2 ); m_play[i]->setHeightPolicy( KCardPile::GrowDown ); m_play[i]->setKeyboardSelectHint( KCardPile::AutoFocusTop ); m_play[i]->setKeyboardDropHint( KCardPile::AutoFocusTop ); } // Create the discard pile to the right m_away = new PatPile( this, 5, QStringLiteral("away") ); m_away->setPileRole(PatPile::Foundation); m_away->setLayoutPos(1.9 + distx * 4, 0); m_away->setSpread(0, 0); m_away->setKeyboardSelectHint(KCardPile::NeverFocus); m_away->setKeyboardDropHint(KCardPile::ForceFocusTop); connect(this, &Idiot::cardClicked, this, &Idiot::tryAutomaticMove); setActions(DealerScene::Hint | DealerScene::Demo | DealerScene::Deal); setSolver( new IdiotSolver(this ) ); } void Idiot::restart( const QList & cards ) { foreach ( KCard * c, cards ) { c->setPos( talon->pos() ); c->setFaceUp( false ); talon->add( c ); } dealRow(); emit newCardsPossible(true); } bool Idiot::drop() { return false; } bool Idiot::checkAdd(const PatPile * pile, const QList & oldCards, const QList & newCards) const { switch ( pile->pileRole() ) { case PatPile::Foundation: return newCards.size() == 1 && canMoveAway( newCards.first() ); case PatPile::Tableau: return oldCards.isEmpty() && newCards.size() == 1; case PatPile::Stock: default: return false; } } bool Idiot::checkRemove(const PatPile * pile, const QList & cards) const { return pile->pileRole() == PatPile::Tableau && cards.first() == pile->topCard() && ( canMoveAway( cards.first() ) || m_play[0]->isEmpty() || m_play[1]->isEmpty() || m_play[2]->isEmpty() || m_play[3]->isEmpty() ); } bool Idiot::canMoveAway(const KCard * card) const { Q_ASSERT( card->pile() != talon ); Q_ASSERT( card->pile() != m_away ); Q_ASSERT( card == card->pile()->topCard() ); for ( int i = 0; i < 4; ++i ) { KCard * c = m_play[i]->topCard(); if ( c && c != card && c->suit() == card->suit() && ( c->rank() == KCardDeck::Ace || ( card->rank() != KCardDeck::Ace && c->rank() > card->rank() ) ) ) return true; } return false; } bool Idiot::tryAutomaticMove( KCard * card ) { if ( !isCardAnimationRunning() && card && card->pile() && card == card->pile()->topCard() && card->pile() != talon && card->pile() != m_away ) { KCardPile * destination = nullptr; if ( canMoveAway( card ) ) destination = m_away; else if ( m_play[0]->isEmpty() ) destination = m_play[0]; else if ( m_play[1]->isEmpty() ) destination = m_play[1]; else if ( m_play[2]->isEmpty() ) destination = m_play[2]; else if ( m_play[3]->isEmpty() ) destination = m_play[3]; if ( destination ) { moveCardToPile( card, destination, DURATION_MOVE ); return true; } } return false; } // The game is won when: // 1. all cards are dealt. // 2. all piles contain exactly one ace. // 3. the rest of the cards are thrown away (follows automatically from 1, 2. // bool Idiot::isGameWon() const { // Criterium 1. if (!talon->isEmpty()) return false; // Criterium 2. for (int i = 0; i < 4; i++) { if (m_play[i]->count() != 1 || m_play[i]->topCard()->rank() != KCardDeck::Ace) return false; } return true; } // Deal 4 cards face up - one on each pile. bool Idiot::newCards() { if ( talon->isEmpty() ) return false; dealRow(); if ( talon->isEmpty() ) emit newCardsPossible( false ); return true; } void Idiot::dealRow() { Q_ASSERT(talon->count() >= 4); for ( int i = 0; i < 4; ++i ) { KCard * c = talon->topCard(); flipCardToPileAtSpeed( c, m_play[i], DEAL_SPEED ); // Fudge the z values so that cards don't appear to pop through one another. c->setZValue( c->zValue() + i ); } } void Idiot::setGameState( const QString & state ) { Q_UNUSED( state ); emit newCardsPossible( !talon->isEmpty() ); } static class IdiotDealerInfo : public DealerInfo { public: IdiotDealerInfo() : DealerInfo(I18N_NOOP("Aces Up"), AcesUpId) {} - DealerScene *createGame() const Q_DECL_OVERRIDE + DealerScene *createGame() const override { return new Idiot( this ); } } idiotDealerInfo; diff --git a/idiot.h b/idiot.h index e2d5ba1..b75918e 100644 --- a/idiot.h +++ b/idiot.h @@ -1,74 +1,74 @@ /* * Copyright (C) 1995 Paul Olav Tvete * Copyright (C) 2000-2009 Stephan Kulow * * License of original code: * ------------------------------------------------------------------------- * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, * provided that the above copyright notice appear in all copies and that * both that copyright notice and this permission notice appear in * supporting documentation. * * This file is provided AS IS with no warranties of any kind. The author * shall have no liability with respect to the infringement of copyrights, * trade secrets or any patents by this file or any part thereof. In no * event will the author be liable for any lost revenue or profits or * other special, indirect and consequential damages. * ------------------------------------------------------------------------- * * License of modifications/additions made after 2009-01-01: * ------------------------------------------------------------------------- * 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, see . * ------------------------------------------------------------------------- */ #ifndef IDIOT_H #define IDIOT_H #include "dealer.h" class Idiot: public DealerScene { Q_OBJECT public: explicit Idiot( const DealerInfo * di ); - void initialize() Q_DECL_OVERRIDE; - bool isGameWon() const Q_DECL_OVERRIDE; + void initialize() override; + bool isGameWon() const override; protected: - void setGameState( const QString & state ) Q_DECL_OVERRIDE; - bool checkAdd(const PatPile * pile, const QList & oldCards, const QList & newCards) const Q_DECL_OVERRIDE; - bool checkRemove(const PatPile * pile, const QList & cards) const Q_DECL_OVERRIDE; - void restart( const QList & cards ) Q_DECL_OVERRIDE; - bool drop() Q_DECL_OVERRIDE; + void setGameState( const QString & state ) override; + bool checkAdd(const PatPile * pile, const QList & oldCards, const QList & newCards) const override; + bool checkRemove(const PatPile * pile, const QList & cards) const override; + void restart( const QList & cards ) override; + bool drop() override; protected slots: - bool newCards() Q_DECL_OVERRIDE; - bool tryAutomaticMove( KCard * card ) Q_DECL_OVERRIDE; + bool newCards() override; + bool tryAutomaticMove( KCard * card ) override; private: void dealRow(); bool canMoveAway(const KCard * card) const; PatPile *talon; PatPile *m_play[ 4 ]; PatPile *m_away; friend class IdiotSolver; }; #endif diff --git a/klondike.cpp b/klondike.cpp index fdce6a3..35da630 100644 --- a/klondike.cpp +++ b/klondike.cpp @@ -1,358 +1,358 @@ /* * Copyright (C) 1995 Paul Olav Tvete * Copyright (C) 2000-2009 Stephan Kulow * Copyright (C) 2010 Parker Coates * * License of original code: * ------------------------------------------------------------------------- * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, * provided that the above copyright notice appear in all copies and that * both that copyright notice and this permission notice appear in * supporting documentation. * * This file is provided AS IS with no warranties of any kind. The author * shall have no liability with respect to the infringement of copyrights, * trade secrets or any patents by this file or any part thereof. In no * event will the author be liable for any lost revenue or profits or * other special, indirect and consequential damages. * ------------------------------------------------------------------------- * * License of modifications/additions made after 2009-01-01: * ------------------------------------------------------------------------- * 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, see . * ------------------------------------------------------------------------- */ #include "klondike.h" #include "dealerinfo.h" #include "pileutils.h" #include "settings.h" #include "speeds.h" #include "patsolve/klondikesolver.h" #include #include KlondikePile::KlondikePile( DealerScene * scene, int index, const QString & objectName ) : PatPile( scene, index, objectName ), m_cardsToShow( 1 ) { } void KlondikePile::setCardsToShow( int draw ) { m_cardsToShow = draw; } int KlondikePile::cardsToShow() const { return m_cardsToShow; } QList KlondikePile::cardPositions() const { QList positions; QPointF currentPos( 0, 0 ); for ( int i = 0; i < count(); ++i ) { positions << currentPos; if ( i >= count() - m_cardsToShow ) currentPos += spread(); } return positions; } Klondike::Klondike( const DealerInfo * di ) : DealerScene( di ) { } void Klondike::initialize() { // The units of the follwoing constants are pixels const qreal hspacing = 1.0 / 6 + 0.02; // horizontal spacing between card piles const qreal vspacing = 1.0 / 4; // vertical spacing between card piles setDeckContents(); easyRules = Settings::klondikeIsDrawOne(); talon = new PatPile( this, 0, QStringLiteral("talon") ); talon->setPileRole(PatPile::Stock); talon->setLayoutPos(0, 0); // Give the talon a low Z value to keep it out of the way during there // deal animation. talon->setZValue( -52 ); talon->setKeyboardSelectHint( KCardPile::NeverFocus ); talon->setKeyboardDropHint( KCardPile::NeverFocus ); connect( talon, &KCardPile::clicked, this, &DealerScene::drawDealRowOrRedeal ); pile = new KlondikePile( this, 13, QStringLiteral("pile") ); pile->setCardsToShow( easyRules ? 1 : 3 ); pile->setPileRole( PatPile::Waste ); pile->setRightPadding( 1.1 ); pile->setLayoutPos( 1 + hspacing, 0 ); pile->setSpread( 0.33, 0 ); pile->setKeyboardSelectHint( KCardPile::ForceFocusTop ); pile->setKeyboardDropHint( KCardPile::NeverFocus ); for( int i = 0; i < 7; ++i ) { play[i] = new PatPile( this, i + 5, QStringLiteral( "play%1" ).arg( i )); play[i]->setPileRole(PatPile::Tableau); play[i]->setLayoutPos((1.0 + hspacing) * i, 1.0 + vspacing); play[i]->setAutoTurnTop(true); play[i]->setBottomPadding( play[i]->spread().y() * 5 ); play[i]->setHeightPolicy( KCardPile::GrowDown ); play[i]->setKeyboardSelectHint( KCardPile::AutoFocusDeepestFaceUp ); play[i]->setKeyboardDropHint( KCardPile::AutoFocusTop ); } for( int i = 0; i < 4; ++i ) { target[i] = new PatPile( this, i + 1, QStringLiteral( "target%1" ).arg( i ) ); target[i]->setPileRole(PatPile::Foundation); target[i]->setLayoutPos((3 + i) * (1.0 + hspacing), 0); target[i]->setKeyboardSelectHint( KCardPile::ForceFocusTop ); target[i]->setKeyboardDropHint( KCardPile::ForceFocusTop ); } setActions(DealerScene::Hint | DealerScene::Demo | DealerScene::Draw); setSolver( new KlondikeSolver( this, pile->cardsToShow() ) ); options = new KSelectAction(i18n("Klondike &Options"), this ); options->addAction( i18n("Draw 1" )); options->addAction( i18n("Draw 3" )); options->setCurrentItem( easyRules ? 0 : 1 ); connect(options, static_cast(&KSelectAction::triggered), this, &Klondike::gameTypeChanged); } bool Klondike::checkAdd(const PatPile * pile, const QList & oldCards, const QList & newCards) const { switch (pile->pileRole()) { case PatPile::Tableau: return checkAddAlternateColorDescendingFromKing(oldCards, newCards); case PatPile::Foundation: return checkAddSameSuitAscendingFromAce(oldCards, newCards); case PatPile::Waste: case PatPile::Stock: default: return false; } } bool Klondike::checkRemove(const PatPile * pile, const QList & cards) const { switch (pile->pileRole()) { case PatPile::Tableau: return isAlternateColorDescending(cards); case PatPile::Foundation: return easyRules && cards.first() == pile->topCard(); case PatPile::Waste: return cards.first() == pile->topCard(); case PatPile::Stock: default: return false; } } void Klondike::cardsMoved( const QList & cards, KCardPile * oldPile, KCardPile * newPile ) { DealerScene::cardsMoved( cards, oldPile, newPile ); emit newCardsPossible( !talon->isEmpty() || pile->count() > 1 ); } QList Klondike::configActions() const { return QList() << options; } bool Klondike::newCards() { if ( talon->isEmpty() && pile->count() <= 1 ) return false; if ( talon->isEmpty() ) { // Move the cards from the pile back to the deck flipCardsToPile( pile->cards(), talon, DURATION_MOVE ); } else { QList cards = talon->topCards( pile->cardsToShow() ); flipCardsToPile( cards, pile, DURATION_MOVE ); setKeyboardFocus( pile->topCard() ); } if ( talon->isEmpty() && pile->count() <= 1 ) emit newCardsPossible( false ); // we need to look that many steps in the future to see if we can lose setNeededFutureMoves( talon->count() + pile->count() ); return true; } void Klondike::restart( const QList & cards ) { QList cardList = cards; for( int round = 0; round < 7; ++round ) for ( int i = round; i < 7; ++i ) addCardForDeal( play[i], cardList.takeLast(), (i == round), talon->pos()); while ( !cardList.isEmpty() ) { KCard * c = cardList.takeFirst(); c->setPos( talon->pos() ); c->setFaceUp( false ); talon->add( c ); } startDealAnimation(); } void Klondike::gameTypeChanged() { stopDemo(); if ( allowedToStartNewGame() ) { setEasy( options->currentItem() == 0 ); startNew( gameNumber() ); } else { // If we're not allowed, reset the option to // the current number of suits. options->setCurrentItem( easyRules ? 0 : 1 ); } } void Klondike::setGameState( const QString & state ) { Q_UNUSED( state ); emit newCardsPossible( !talon->isEmpty() || pile->count() > 1 ); } QString Klondike::getGameOptions() const { return QString::number( pile->cardsToShow() ); } void Klondike::setGameOptions( const QString & options ) { setEasy( options.toInt() == 1 ); } void Klondike::setEasy( bool _EasyRules ) { if ( _EasyRules != easyRules ) { easyRules = _EasyRules; options->setCurrentItem( easyRules ? 0 : 1 ); int drawNumber = easyRules ? 1 : 3; pile->setCardsToShow( drawNumber ); KCardPile::KeyboardFocusHint hint = easyRules ? KCardPile::ForceFocusTop : KCardPile::NeverFocus; for( int i = 0; i < 4; ++i ) target[i]->setKeyboardSelectHint( hint ); setSolver( new KlondikeSolver( this, drawNumber ) ); Settings::setKlondikeIsDrawOne( easyRules ); } } bool Klondike::drop() { bool pileempty = pile->isEmpty(); if (!DealerScene::drop()) return false; if (pile->isEmpty() && !pileempty) newCards(); return true; } void Klondike::mapOldId(int id) { switch ( id ) { case DealerInfo::KlondikeDrawOneId: setEasy( true ); break; case DealerInfo::KlondikeDrawThreeId: setEasy( false ); break; case DealerInfo::KlondikeGeneralId: default: // Do nothing. break; } } int Klondike::oldId() const { if ( easyRules ) return DealerInfo::KlondikeDrawOneId; else return DealerInfo::KlondikeDrawThreeId; } static class KlondikeDealerInfo : public DealerInfo { public: KlondikeDealerInfo() : DealerInfo(I18N_NOOP("Klondike"), DealerInfo::KlondikeGeneralId) { addSubtype( KlondikeDrawOneId, I18N_NOOP( "Klondike (Draw 1)" ) ); addSubtype( KlondikeDrawThreeId, I18N_NOOP( "Klondike (Draw 3)" ) ); } - DealerScene *createGame() const Q_DECL_OVERRIDE + DealerScene *createGame() const override { return new Klondike( this ); } } klondikeDealerInfo; diff --git a/klondike.h b/klondike.h index acfbf9b..7526e7a 100644 --- a/klondike.h +++ b/klondike.h @@ -1,101 +1,101 @@ /* * Copyright (C) 1995 Paul Olav Tvete * Copyright (C) 2000-2009 Stephan Kulow * * License of original code: * ------------------------------------------------------------------------- * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, * provided that the above copyright notice appear in all copies and that * both that copyright notice and this permission notice appear in * supporting documentation. * * This file is provided AS IS with no warranties of any kind. The author * shall have no liability with respect to the infringement of copyrights, * trade secrets or any patents by this file or any part thereof. In no * event will the author be liable for any lost revenue or profits or * other special, indirect and consequential damages. * ------------------------------------------------------------------------- * * License of modifications/additions made after 2009-01-01: * ------------------------------------------------------------------------- * 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, see . * ------------------------------------------------------------------------- */ #ifndef KLONDIKE_H #define KLONDIKE_H #include "dealer.h" class KlondikePile; class KSelectAction; class Klondike : public DealerScene { Q_OBJECT public: explicit Klondike( const DealerInfo * di ); - void initialize() Q_DECL_OVERRIDE; - void mapOldId(int id) Q_DECL_OVERRIDE; - int oldId() const Q_DECL_OVERRIDE; - QList configActions() const Q_DECL_OVERRIDE; + void initialize() override; + void mapOldId(int id) override; + int oldId() const override; + QList configActions() const override; protected: - void setGameState( const QString & state ) Q_DECL_OVERRIDE; - QString getGameOptions() const Q_DECL_OVERRIDE; - void setGameOptions( const QString & options ) Q_DECL_OVERRIDE; - bool checkAdd(const PatPile * pile, const QList & oldCards, const QList & newCards) const Q_DECL_OVERRIDE; - bool checkRemove(const PatPile * pile, const QList & cards) const Q_DECL_OVERRIDE; - void cardsMoved( const QList & cards, KCardPile * oldPile, KCardPile * newPile ) Q_DECL_OVERRIDE; - void restart( const QList & cards ) Q_DECL_OVERRIDE; + void setGameState( const QString & state ) override; + QString getGameOptions() const override; + void setGameOptions( const QString & options ) override; + bool checkAdd(const PatPile * pile, const QList & oldCards, const QList & newCards) const override; + bool checkRemove(const PatPile * pile, const QList & cards) const override; + void cardsMoved( const QList & cards, KCardPile * oldPile, KCardPile * newPile ) override; + void restart( const QList & cards ) override; protected slots: - bool drop() Q_DECL_OVERRIDE; - bool newCards() Q_DECL_OVERRIDE; + bool drop() override; + bool newCards() override; private slots: void gameTypeChanged(); private: void setEasy( bool easy ); bool easyRules; KSelectAction *options; PatPile* talon; PatPile* play[7]; PatPile* target[4]; KlondikePile *pile; friend class KlondikeSolver; }; class KlondikePile : public PatPile { public: KlondikePile( DealerScene * scene, int index, const QString & objectName = QString() ); void setCardsToShow( int numCards ); int cardsToShow() const; - QList cardPositions() const Q_DECL_OVERRIDE; + QList cardPositions() const override; private: int m_cardsToShow; }; #endif diff --git a/libkcardgame/kabstractcarddeck_p.h b/libkcardgame/kabstractcarddeck_p.h index ac8b493..00f80bc 100644 --- a/libkcardgame/kabstractcarddeck_p.h +++ b/libkcardgame/kabstractcarddeck_p.h @@ -1,108 +1,108 @@ /* * Copyright (C) 2009-2010 Parker Coates * * 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, see . * */ #ifndef KABSTRACTCARDDECK_P_H #define KABSTRACTCARDDECK_P_H #include "kabstractcarddeck.h" #include "kcardtheme.h" #include #include class QImage; #include #include #include #include #include #include class QSvgRenderer; class RenderingThread : public QThread { Q_OBJECT public: RenderingThread( KAbstractCardDeckPrivate * d, QSize size, const QStringList & elements ); - void run() Q_DECL_OVERRIDE; + void run() override; void halt(); Q_SIGNALS: void renderingDone( const QString & elementId, const QImage & image ); private: KAbstractCardDeckPrivate * const d; const QSize m_size; const QStringList m_elementsToRender; bool m_haltFlag; QMutex m_haltMutex; }; struct CardElementData { QPixmap cardPixmap; QList cardUsers; }; class KAbstractCardDeckPrivate : public QObject { Q_OBJECT public: explicit KAbstractCardDeckPrivate( KAbstractCardDeck * q ); ~KAbstractCardDeckPrivate(); QSvgRenderer * renderer(); QImage renderCard( const QString & element, const QSize & size ); QSizeF unscaledCardSize(); QPixmap requestPixmap( quint32 id, bool faceUp ); void updateCardSize( const QSize & size ); void deleteThread(); public Q_SLOTS: void submitRendering( const QString & elementId, const QImage & image ); void cardStartedAnimation( KCard * card ); void cardStoppedAnimation( KCard * card ); void checkIfAnimationIsDone(); public: KAbstractCardDeck * q; QSizeF originalCardSize; QSize currentCardSize; QList cards; QSet cardsWaitedFor; QTimer * animationCheckTimer; KCardTheme theme; KImageCache * cache; QSvgRenderer * svgRenderer; QMutex rendererMutex; RenderingThread * thread; QHash frontIndex; QHash backIndex; }; #endif diff --git a/libkcardgame/kcard.h b/libkcardgame/kcard.h index 2f148bf..5cc55a2 100644 --- a/libkcardgame/kcard.h +++ b/libkcardgame/kcard.h @@ -1,84 +1,84 @@ /* * Copyright (C) 2010 Parker Coates * * 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, see . * */ #ifndef KCARD_H #define KCARD_H class KAbstractCardDeck; class KCardPile; #include "libkcardgame_export.h" #include #include class LIBKCARDGAME_EXPORT KCard : public QObject, public QGraphicsPixmapItem { Q_OBJECT private: KCard( quint32 id, KAbstractCardDeck * deck ); virtual ~KCard(); public: enum { Type = QGraphicsItem::UserType + 1 }; - int type() const Q_DECL_OVERRIDE; + int type() const override; - void paint( QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget = nullptr ) Q_DECL_OVERRIDE; + void paint( QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget = nullptr ) override; quint32 id() const; int rank() const; int suit() const; int color() const; KCardPile * pile() const; void setFaceUp( bool faceUp ); bool isFaceUp() const; void animate( QPointF pos, qreal z, qreal rotation, bool faceUp, bool raised, int duration ); bool isAnimated() const; void raise(); void setHighlighted( bool highlighted ); bool isHighlighted() const; void setFrontPixmap( const QPixmap & pix ); void setBackPixmap( const QPixmap & pix ); Q_SIGNALS: void animationStarted( KCard * card ); void animationStopped( KCard * card ); public Q_SLOTS: void completeAnimation(); void stopAnimation(); private: void setPile( KCardPile * pile ); void setPixmap( const QPixmap & pix ); class KCardPrivate * const d; friend class KCardPrivate; friend class KAbstractCardDeck; friend class KCardPile; }; #endif diff --git a/libkcardgame/kcard_p.h b/libkcardgame/kcard_p.h index 97e7767..7eeebf0 100644 --- a/libkcardgame/kcard_p.h +++ b/libkcardgame/kcard_p.h @@ -1,92 +1,92 @@ /* * Copyright (C) 2010 Parker Coates * * 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, see . * */ #ifndef KCARD_P_H #define KCARD_P_H #include "kcard.h" class KAbstractCardDeck; class KCardPile; #include class QPropertyAnimation; class KCardAnimation : public QAbstractAnimation { public: KCardAnimation( KCardPrivate * d, int duration, QPointF pos, qreal rotation, bool faceUp ); - int duration() const Q_DECL_OVERRIDE; - void updateCurrentTime( int msec ) Q_DECL_OVERRIDE; + int duration() const override; + void updateCurrentTime( int msec ) override; private: KCardPrivate * d; int m_duration; qreal m_x0; qreal m_y0; qreal m_rotation0; qreal m_flippedness0; qreal m_xDelta; qreal m_yDelta; qreal m_rotationDelta; qreal m_flippednessDelta; qreal m_flipProgressFactor; }; class KCardPrivate : public QObject { Q_OBJECT Q_PROPERTY( qreal highlightedness READ highlightedness WRITE setHighlightedness ) public: explicit KCardPrivate( KCard * card ); void setFlippedness( qreal flippedness ); qreal flippedness() const; void setHighlightedness( qreal highlightedness ); qreal highlightedness() const; bool faceUp; bool highlighted; quint32 id; qreal destZ; qreal flipValue; qreal highlightValue; KCard * q; KAbstractCardDeck * deck; KCardPile * pile; QPixmap frontPixmap; QPixmap backPixmap; KCardAnimation * animation; QPropertyAnimation * fadeAnimation; }; #endif diff --git a/libkcardgame/kcarddeck.h b/libkcardgame/kcarddeck.h index 915cb8b..9d358c1 100644 --- a/libkcardgame/kcarddeck.h +++ b/libkcardgame/kcarddeck.h @@ -1,81 +1,81 @@ /* * Copyright (C) 2010 Parker Coates * * 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, see . * */ #ifndef KCARDDECK_H #define KCARDDECK_H #include "kabstractcarddeck.h" #include "libkcardgame_export.h" class LIBKCARDGAME_EXPORT KCardDeck : public KAbstractCardDeck { public: enum Color { Black = 0, Red }; enum Suit { Clubs = 0, Diamonds, Hearts, Spades }; enum Rank { Ace = 1, Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten, Jack, Queen, King }; static QList standardSuits(); static QList standardRanks(); static quint32 getId( Suit suit, Rank rank, int number ); static QList generateIdList( int copies = 1, const QList & suits = standardSuits(), const QList & ranks = standardRanks() ); explicit KCardDeck( const KCardTheme & theme = KCardTheme(), QObject * parent = nullptr ); virtual ~KCardDeck(); - int rankFromId( quint32 id ) const Q_DECL_OVERRIDE; - int suitFromId( quint32 id ) const Q_DECL_OVERRIDE; - int colorFromId( quint32 id ) const Q_DECL_OVERRIDE; + int rankFromId( quint32 id ) const override; + int suitFromId( quint32 id ) const override; + int colorFromId( quint32 id ) const override; protected: - QString elementName( quint32 id, bool faceUp = true ) const Q_DECL_OVERRIDE; + QString elementName( quint32 id, bool faceUp = true ) const override; private: class KStandardCardDeckPrivate * const d; }; #endif diff --git a/libkcardgame/kcardpile.h b/libkcardgame/kcardpile.h index 045e51a..3f80a24 100644 --- a/libkcardgame/kcardpile.h +++ b/libkcardgame/kcardpile.h @@ -1,155 +1,155 @@ /* * Copyright (C) 1995 Paul Olav Tvete * Copyright (C) 2000-2009 Stephan Kulow * Copyright (C) 2010 Parker Coates * * License of original code: * ------------------------------------------------------------------------- * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, * provided that the above copyright notice appear in all copies and that * both that copyright notice and this permission notice appear in * supporting documentation. * * This file is provided AS IS with no warranties of any kind. The author * shall have no liability with respect to the infringement of copyrights, * trade secrets or any patents by this file or any part thereof. In no * event will the author be liable for any lost revenue or profits or * other special, indirect and consequential damages. * ------------------------------------------------------------------------- * * License of modifications/additions made after 2009-01-01: * ------------------------------------------------------------------------- * 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, see . * ------------------------------------------------------------------------- */ #ifndef KCARDPILE_H #define KCARDPILE_H #include "kcard.h" class KCardScene; #include "libkcardgame_export.h" #include class LIBKCARDGAME_EXPORT KCardPile : public QGraphicsObject { Q_OBJECT public: explicit KCardPile( KCardScene * cardScene ); virtual ~KCardPile(); enum { Type = QGraphicsItem::UserType + 2 }; - int type() const Q_DECL_OVERRIDE; + int type() const override; - QRectF boundingRect() const Q_DECL_OVERRIDE; - void paint( QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget = nullptr ) Q_DECL_OVERRIDE; + QRectF boundingRect() const override; + void paint( QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget = nullptr ) override; QList cards() const; int count() const; bool isEmpty() const; int indexOf( const KCard * card ) const; KCard * at( int index ) const; KCard * topCard() const; QList topCards( int depth ) const; QList topCardsDownTo( const KCard * card ) const; void setLayoutPos( QPointF pos ); void setLayoutPos( qreal x, qreal y ); QPointF layoutPos() const; enum WidthPolicy { FixedWidth, GrowLeft, GrowRight }; void setWidthPolicy( WidthPolicy policy ); WidthPolicy widthPolicy() const; enum HeightPolicy { FixedHeight, GrowUp, GrowDown }; void setHeightPolicy( HeightPolicy policy ); HeightPolicy heightPolicy() const; void setPadding( qreal topPadding, qreal rightPadding, qreal bottomPadding, qreal leftPadding ); void setTopPadding( qreal padding ); qreal topPadding() const; void setRightPadding( qreal padding ); qreal rightPadding() const; void setBottomPadding( qreal padding ); qreal bottomPadding() const; void setLeftPadding( qreal padding ); qreal leftPadding() const; void setSpread( QPointF spread ); void setSpread( qreal width, qreal height ); QPointF spread() const; void setAutoTurnTop( bool autoTurnTop ); bool autoTurnTop() const; enum KeyboardFocusHint { FreeFocus, AutoFocusTop, AutoFocusDeepestRemovable, AutoFocusDeepestFaceUp, AutoFocusBottom, ForceFocusTop, NeverFocus }; void setKeyboardSelectHint( KeyboardFocusHint hint ); KeyboardFocusHint keyboardSelectHint() const; void setKeyboardDropHint( KeyboardFocusHint hint ); KeyboardFocusHint keyboardDropHint() const; virtual void setVisible(bool vis); void setHighlighted( bool highlighted ); bool isHighlighted() const; void add( KCard * card ); virtual void insert( int index, KCard * card ); virtual void remove( KCard * card ); void clear(); void swapCards( int index1, int index2 ); virtual QList cardPositions() const; Q_SIGNALS: void clicked( KCard * card ); void doubleClicked( KCard * card ); void rightClicked( KCard * card ); protected: virtual void paintGraphic( QPainter * painter, qreal highlightedness ); private: void setGraphicSize( QSize size ); class KCardPilePrivate * const d; friend class KCardPilePrivate; friend class KCardScene; }; #endif diff --git a/libkcardgame/kcardscene.h b/libkcardgame/kcardscene.h index f3df677..09a2634 100644 --- a/libkcardgame/kcardscene.h +++ b/libkcardgame/kcardscene.h @@ -1,153 +1,153 @@ /* * Copyright (C) 1995 Paul Olav Tvete * Copyright (C) 2000-2009 Stephan Kulow * Copyright (C) 2009-2010 Parker Coates * * License of original code: * ------------------------------------------------------------------------- * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, * provided that the above copyright notice appear in all copies and that * both that copyright notice and this permission notice appear in * supporting documentation. * * This file is provided AS IS with no warranties of any kind. The author * shall have no liability with respect to the infringement of copyrights, * trade secrets or any patents by this file or any part thereof. In no * event will the author be liable for any lost revenue or profits or * other special, indirect and consequential damages. * ------------------------------------------------------------------------- * * License of modifications/additions made after 2009-01-01: * ------------------------------------------------------------------------- * 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, see . * ------------------------------------------------------------------------- */ #ifndef KCARDSCENE_H #define KCARDSCENE_H class KCard; class KAbstractCardDeck; #include "libkcardgame_export.h" class KCardPile; #include class LIBKCARDGAME_EXPORT KCardScene : public QGraphicsScene { Q_OBJECT public: enum SceneAlignmentFlag { AlignLeft = 0x0001, AlignRight = 0x0002, AlignHCenter = 0x0004, AlignHSpread = 0x0008, AlignTop = 0x0010, AlignBottom = 0x0020, AlignVCenter = 0x0040, AlignVSpread = 0x0080 }; Q_DECLARE_FLAGS(SceneAlignment, SceneAlignmentFlag) explicit KCardScene( QObject * parent = nullptr ); ~KCardScene(); void setDeck( KAbstractCardDeck * deck ); KAbstractCardDeck * deck() const; QList cardsBeingDragged() const; void setSceneAlignment( SceneAlignment alignment ); SceneAlignment sceneAlignment() const; void setLayoutMargin( qreal margin ); qreal layoutMargin() const; void setLayoutSpacing( qreal spacing ); qreal layoutSpacing() const; QRectF contentArea() const; virtual void resizeScene( const QSize & size ); virtual void relayoutScene(); virtual void recalculatePileLayouts(); void addPile( KCardPile * pile ); void removePile( KCardPile * pile ); QList piles() const; void setHighlightedItems( const QList &items ); void clearHighlightedItems(); QList highlightedItems() const; void moveCardsToPile( const QList & cards, KCardPile * pile, int duration ); void moveCardToPile( KCard * card, KCardPile * pile, int duration ); void moveCardsToPileAtSpeed( const QList & cards, KCardPile * pile, qreal velocity ); void moveCardToPileAtSpeed( KCard * card, KCardPile * pile, qreal velocity ); void flipCardsToPile( const QList & cards, KCardPile * pile, int duration ); void flipCardToPile( KCard * card, KCardPile * pile, int duration ); void flipCardsToPileAtSpeed( const QList & cards, KCardPile * pile, qreal velocity ); void flipCardToPileAtSpeed( KCard * card, KCardPile * pile, qreal velocity ); void updatePileLayout( KCardPile * pile, int duration ); bool isCardAnimationRunning() const; public Q_SLOTS: void keyboardFocusLeft(); void keyboardFocusRight(); void keyboardFocusUp(); void keyboardFocusDown(); void keyboardFocusCancel(); void keyboardFocusSelect(); Q_SIGNALS: void cardClicked( KCard * card ); void cardDoubleClicked( KCard * card ); void cardRightClicked( KCard * card ); void pileClicked( KCardPile * pile ); void pileDoubleClicked( KCardPile * pile ); void pileRightClicked( KCardPile * pile ); void cardAnimationDone(); protected: void setKeyboardFocus( QGraphicsItem * item ); void setKeyboardModeActive( bool keyboardMode ); bool isKeyboardModeActive() const; virtual bool allowedToAdd( const KCardPile * pile, const QList & cards ) const; virtual bool allowedToRemove( const KCardPile * pile, const KCard * card ) const; virtual void cardsDroppedOnPile( const QList & cards, KCardPile * pile ); virtual void cardsMoved( const QList & cards, KCardPile * oldPile, KCardPile * newPile ); - void mouseDoubleClickEvent( QGraphicsSceneMouseEvent * e ) Q_DECL_OVERRIDE; - void mouseMoveEvent( QGraphicsSceneMouseEvent * e ) Q_DECL_OVERRIDE; - void mousePressEvent( QGraphicsSceneMouseEvent * e ) Q_DECL_OVERRIDE; - void mouseReleaseEvent( QGraphicsSceneMouseEvent * e ) Q_DECL_OVERRIDE; - void wheelEvent( QGraphicsSceneWheelEvent * e ) Q_DECL_OVERRIDE; + void mouseDoubleClickEvent( QGraphicsSceneMouseEvent * e ) override; + void mouseMoveEvent( QGraphicsSceneMouseEvent * e ) override; + void mousePressEvent( QGraphicsSceneMouseEvent * e ) override; + void mouseReleaseEvent( QGraphicsSceneMouseEvent * e ) override; + void wheelEvent( QGraphicsSceneWheelEvent * e ) override; - void drawForeground( QPainter * painter, const QRectF & rect ) Q_DECL_OVERRIDE; + void drawForeground( QPainter * painter, const QRectF & rect ) override; private: friend class KCardScenePrivate; class KCardScenePrivate * const d; }; Q_DECLARE_OPERATORS_FOR_FLAGS( KCardScene::SceneAlignment ) #endif diff --git a/libkcardgame/kcardthemewidget_p.h b/libkcardgame/kcardthemewidget_p.h index b576981..b55ab1f 100644 --- a/libkcardgame/kcardthemewidget_p.h +++ b/libkcardgame/kcardthemewidget_p.h @@ -1,129 +1,129 @@ /* * Portions Copyright (C) 2009 by Davide Bettio * Copyright (C) 2010 Parker Coates * * 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, see . * */ #ifndef KCARDTHEMEWIDGET_P_H #define KCARDTHEMEWIDGET_P_H #include "kcardthemewidget.h" #include "kcardtheme.h" #include class KLineEdit; class QPushButton; #include #include #include #include class QListView; class PreviewThread : public QThread { Q_OBJECT public: PreviewThread( const KCardThemeWidgetPrivate * d, const QList & themes ); - void run() Q_DECL_OVERRIDE; + void run() override; void halt(); Q_SIGNALS: void previewRendered( const KCardTheme & theme, const QImage & image ); private: const KCardThemeWidgetPrivate * const d; const QList m_themes; bool m_haltFlag; QMutex m_haltMutex; }; class CardThemeModel : public QAbstractListModel { Q_OBJECT public: explicit CardThemeModel( KCardThemeWidgetPrivate * d, QObject * parent = nullptr ); virtual ~CardThemeModel(); void reload(); QModelIndex indexOf( const QString & dirName ) const; - int rowCount( const QModelIndex & parent = QModelIndex() ) const Q_DECL_OVERRIDE; - QVariant data( const QModelIndex & index, int role = Qt::DisplayRole ) const Q_DECL_OVERRIDE; + int rowCount( const QModelIndex & parent = QModelIndex() ) const override; + QVariant data( const QModelIndex & index, int role = Qt::DisplayRole ) const override; private Q_SLOTS: void deleteThread(); void submitPreview( const KCardTheme & theme, const QImage & image ); private: const KCardThemeWidgetPrivate * const d; QMap m_themes; QMap m_previews; PreviewThread * m_thread; }; class CardThemeDelegate : public QAbstractItemDelegate { public: explicit CardThemeDelegate( KCardThemeWidgetPrivate * d, QObject * parent = nullptr ); - void paint( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const Q_DECL_OVERRIDE; - QSize sizeHint( const QStyleOptionViewItem & option, const QModelIndex & index ) const Q_DECL_OVERRIDE; + void paint( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const override; + QSize sizeHint( const QStyleOptionViewItem & option, const QModelIndex & index ) const override; private: const KCardThemeWidgetPrivate * const d; }; class KCardThemeWidgetPrivate : public QObject { Q_OBJECT public: explicit KCardThemeWidgetPrivate( KCardThemeWidget * parent ); public Q_SLOTS: void updateLineEdit( const QModelIndex & index ); void updateListView( const QString & dirName ); void getNewCardThemes(); public: KCardThemeWidget * q; KImageCache * cache; CardThemeModel * model; QListView * listView; KLineEdit * hiddenLineEdit; QPushButton * newDeckButton; int itemMargin; int textHeight; qreal abstractPreviewWidth; QSize baseCardSize; QSize previewSize; QSize itemSize; QString previewString; QList > previewLayout; QSet requiredFeatures; }; #endif diff --git a/mainwindow.h b/mainwindow.h index 5b5a63a..35752dc 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -1,166 +1,166 @@ /* * Copyright (C) 1995 Paul Olav Tvete * Copyright (C) 1997 Mario Weilguni * Copyright (C) 2000-2009 Stephan Kulow * Copyright (C) 2009 Parker Coates * * License of original code: * ------------------------------------------------------------------------- * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, * provided that the above copyright notice appear in all copies and that * both that copyright notice and this permission notice appear in * supporting documentation. * * This file is provided AS IS with no warranties of any kind. The author * shall have no liability with respect to the infringement of copyrights, * trade secrets or any patents by this file or any part thereof. In no * event will the author be liable for any lost revenue or profits or * other special, indirect and consequential damages. * ------------------------------------------------------------------------- * * License of modifications/additions made after 2009-01-01: * ------------------------------------------------------------------------- * 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, see . * ------------------------------------------------------------------------- */ #ifndef MAINWINDOW_H #define MAINWINDOW_H class DealerInfo; class DealerScene; class GameSelectionScene; class NumberedDealDialog; class PatienceView; class SoundEngine; class KCardDeck; class QAction; class KRecentFilesAction; class KToggleAction; class QUrl; #include #include class QLabel; #define saved_state_file "savedstate.xml" class MainWindow: public KXmlGuiWindow { Q_OBJECT public: MainWindow(); ~MainWindow(); public slots: bool loadGame( const QUrl & url, bool addToRecentFiles = true ); void slotShowGameSelectionScreen(); void slotGameSelected(int id); protected slots: void newGame(); void startRandom(); void loadGame(); void restart(); void newNumberedDeal(); void startNumbered( int gameId, int dealNumber ); void nextDeal(); void previousDeal(); void saveGame(); void showStats(); void undoMove(); void redoMove(); void toggleDrop(); void toggleHints(); void toggleDemo(); void toggleDemoAction(bool active); void toggleMenubar(); void setAutoDropEnabled( bool enabled ); void enableSolver(bool enable); void enableSounds(bool enable); void enableRememberState(bool enable); void slotPickRandom(); void configureAppearance(); void appearanceChanged(); void helpGame(); void updateSolverDescription(const QString & text); void slotUpdateMoves(int moves); protected: - void closeEvent(QCloseEvent * e) Q_DECL_OVERRIDE; - void saveNewToolbarConfig() Q_DECL_OVERRIDE; + void closeEvent(QCloseEvent * e) override; + void saveNewToolbarConfig() override; private slots: void slotSnapshot(); void slotSnapshot2(); void generateThemePreview(); private: void setupActions(); void setGameType( int id ); void setGameCaption(); void startNew(int gameNumber); void updateActions(); void updateGameActionList(); void updateSoundEngine(); // Members QAction * m_leftAction; QAction * m_rightAction; QAction * m_upAction; QAction * m_downAction; QAction * m_cancelAction; QAction * m_pickUpSetDownAction; KRecentFilesAction * m_recentFilesAction; QAction * m_saveAction; QAction * m_undoAction; QAction * m_redoAction; QAction * m_demoAction; QAction * m_hintAction; QAction * m_drawAction; QAction * m_dealAction; QAction * m_redealAction; QAction * m_dropAction; KToggleAction * m_autoDropEnabledAction; KToggleAction * m_solverEnabledAction; KToggleAction * m_rememberStateAction; KToggleAction * m_playSoundsAction; KToggleAction * m_showMenubarAction; QAction * m_gameHelpAction; QMap m_dealer_map; QMap::const_iterator m_dealer_it; PatienceView * m_view; DealerScene * m_dealer; GameSelectionScene * m_selector; KCardDeck * m_cardDeck; SoundEngine * m_soundEngine; NumberedDealDialog * m_dealDialog; QLabel * m_solverStatusLabel; QLabel * m_moveCountStatusLabel; }; #endif diff --git a/messagebox.h b/messagebox.h index 5aa2e1d..c3262d3 100644 --- a/messagebox.h +++ b/messagebox.h @@ -1,45 +1,45 @@ /* * Copyright (C) 2010 Parker Coates * * 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, see . */ #ifndef MESSAGEBOX_H #define MESSAGEBOX_H #include #include class MessageBox : public KGameRenderedItem { public: MessageBox(); void setMessage( const QString & message ); QString message() const; void setSize( const QSize & size ); QSize size() const; - void paint( QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget ) Q_DECL_OVERRIDE; + void paint( QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget ) override; private: QString m_message; QFont m_font; bool m_fontCached; }; #endif diff --git a/mod3.cpp b/mod3.cpp index a623cc4..8d442cd 100644 --- a/mod3.cpp +++ b/mod3.cpp @@ -1,248 +1,248 @@ /* * Copyright (C) 1997 Rodolfo Borges * Copyright (C) 1998-2009 Stephan Kulow * Copyright (C) 2010 Parker Coates * * License of original code: * ------------------------------------------------------------------------- * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, * provided that the above copyright notice appear in all copies and that * both that copyright notice and this permission notice appear in * supporting documentation. * * This file is provided AS IS with no warranties of any kind. The author * shall have no liability with respect to the infringement of copyrights, * trade secrets or any patents by this file or any part thereof. In no * event will the author be liable for any lost revenue or profits or * other special, indirect and consequential damages. * ------------------------------------------------------------------------- * * License of modifications/additions made after 2009-01-01: * ------------------------------------------------------------------------- * 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, see . * ------------------------------------------------------------------------- */ #include "mod3.h" #include "dealerinfo.h" #include "patsolve/mod3solver.h" #include Mod3::Mod3( const DealerInfo * di ) : DealerScene( di ) { } void Mod3::initialize() { // Piles are placed very close together. Set layoutSpacing to 0 to prevent // interference between them. setLayoutSpacing(0.0); const qreal dist_x = 1.114; const qreal dist_y = 1.31; const qreal bottomRowY = 3 * dist_y + 0.2; const qreal rightColumX = 8 * dist_x + 0.8; // This patience uses 2 deck of cards. setDeckContents( 2 ); talon = new PatPile( this, 0, QStringLiteral("talon") ); talon->setPileRole(PatPile::Stock); talon->setLayoutPos(rightColumX, bottomRowY); talon->setSpread(0, 0); talon->setKeyboardSelectHint( KCardPile::NeverFocus ); talon->setKeyboardDropHint( KCardPile::NeverFocus ); connect( talon, &KCardPile::clicked, this, &DealerScene::drawDealRowOrRedeal ); aces = new PatPile( this, 50, QStringLiteral("aces")); aces->setPileRole(PatPile::FoundationType1); aces->setLayoutPos(rightColumX, 0.5); aces->setBottomPadding( 2.5 ); aces->setKeyboardSelectHint( KCardPile::NeverFocus ); aces->setKeyboardDropHint( KCardPile::ForceFocusTop ); for ( int r = 0; r < 4; ++r ) { for ( int c = 0; c < 8; ++c ) { int pileIndex = r * 10 + c + 1; QString objectName = QStringLiteral( "stack%1_%2" ).arg( r ).arg( c ); stack[r][c] = new PatPile( this, pileIndex, objectName ); // The first 3 rows are the playing field, the fourth is the store. if ( r < 3 ) { stack[r][c]->setLayoutPos( dist_x * c, dist_y * r ); // Very tight spread makes it easy to quickly tell number of // cards in each pile and we don't care about the cards beneath. stack[r][c]->setSpread( 0, 0.08 ); stack[r][c]->setBottomPadding( 0.23 ); } else { stack[r][c]->setLayoutPos( dist_x * c, bottomRowY ); stack[r][c]->setBottomPadding( 0.8 ); } stack[r][c]->setPileRole( r == 0 ? PatPile::FoundationType2 : r == 1 ? PatPile::FoundationType3 : r == 2 ? PatPile::FoundationType4 : PatPile::Tableau ); stack[r][c]->setHeightPolicy( KCardPile::GrowDown ); stack[r][c]->setKeyboardSelectHint( KCardPile::AutoFocusTop ); stack[r][c]->setKeyboardDropHint( KCardPile::AutoFocusTop ); } } setActions(DealerScene::Hint | DealerScene::Demo | DealerScene::Deal); setSolver( new Mod3Solver( this ) ); } bool mod3CheckAdd(int baseRank, const QList & oldCards, const QList & newCards) { if (oldCards.isEmpty()) return newCards.first()->rank() == baseRank; else return oldCards.first()->rank() == baseRank && newCards.first()->suit() == oldCards.last()->suit() && newCards.first()->rank() == oldCards.last()->rank() + 3; } bool Mod3::checkAdd(const PatPile * pile, const QList & oldCards, const QList & newCards) const { switch (pile->pileRole()) { case PatPile::FoundationType1: return newCards.size() == 1 && newCards.first()->rank() == KCardDeck::Ace; case PatPile::FoundationType2: return mod3CheckAdd(KCardDeck::Two, oldCards, newCards); case PatPile::FoundationType3: return mod3CheckAdd(KCardDeck::Three, oldCards, newCards); case PatPile::FoundationType4: return mod3CheckAdd(KCardDeck::Four, oldCards, newCards); case PatPile::Tableau: return oldCards.isEmpty(); case PatPile::Stock: default: return false; } } bool Mod3::checkRemove(const PatPile * pile, const QList & cards) const { switch (pile->pileRole()) { case PatPile::FoundationType2: case PatPile::FoundationType3: case PatPile::FoundationType4: case PatPile::Tableau: return cards.first() == pile->topCard(); case PatPile::FoundationType1: case PatPile::Stock: default: return false; } } void Mod3::cardsMoved( const QList & cards, KCardPile * oldPile, KCardPile * newPile ) { if ( oldPile->isEmpty() && !talon->isEmpty() ) { PatPile * p = dynamic_cast( oldPile ); if ( p && p->pileRole() == PatPile::Tableau ) flipCardToPile( talon->topCard(), oldPile, DURATION_MOVE ); } DealerScene::cardsMoved( cards, oldPile, newPile ); } void Mod3::restart( const QList & cards ) { foreach ( KCard * c, cards ) { c->setPos( talon->pos() ); c->setFaceUp( false ); talon->add( c ); } for ( int r = 0; r < 4; r++ ) { for ( int c = 0; c < 8; ++c ) { KCard * card = talon->topCard(); card->setFaceUp( true ); // moveCardToPileAtSpeed( card, stack[r][c], DEAL_SPEED ); addCardForDeal( stack[r][c], card, true, talon->pos() ); // Fudge the z values to keep cards from popping through one another. card->setZValue( card->zValue() + ((4 - r) * (4 - r)) + ((8 - c) * (8 - c)) ); } } startDealAnimation(); emit newCardsPossible(true); } bool Mod3::newCards() { if ( talon->isEmpty() ) return false; for ( int c = 0; c < 8; ++c ) { if ( talon->isEmpty() ) break; flipCardToPileAtSpeed( talon->topCard(), stack[3][c], DEAL_SPEED * 2 ); } if (talon->isEmpty()) emit newCardsPossible(false); return true; } void Mod3::setGameState( const QString & state ) { Q_UNUSED( state ); emit newCardsPossible(!talon->isEmpty()); } static class Mod3DealerInfo : public DealerInfo { public: Mod3DealerInfo() : DealerInfo(I18N_NOOP("Mod3"), Mod3Id) {} - DealerScene *createGame() const Q_DECL_OVERRIDE + DealerScene *createGame() const override { return new Mod3( this ); } } mod3DealerInfo; diff --git a/mod3.h b/mod3.h index c5468ff..2b2dac6 100644 --- a/mod3.h +++ b/mod3.h @@ -1,69 +1,69 @@ /* * Copyright (C) 1997 Rodolfo Borges * Copyright (C) 1998-2009 Stephan Kulow * * License of original code: * ------------------------------------------------------------------------- * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, * provided that the above copyright notice appear in all copies and that * both that copyright notice and this permission notice appear in * supporting documentation. * * This file is provided AS IS with no warranties of any kind. The author * shall have no liability with respect to the infringement of copyrights, * trade secrets or any patents by this file or any part thereof. In no * event will the author be liable for any lost revenue or profits or * other special, indirect and consequential damages. * ------------------------------------------------------------------------- * * License of modifications/additions made after 2009-01-01: * ------------------------------------------------------------------------- * 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, see . * ------------------------------------------------------------------------- */ #ifndef MOD3_H #define MOD3_H #include "dealer.h" class Mod3 : public DealerScene { Q_OBJECT public: explicit Mod3( const DealerInfo * di ); - void initialize() Q_DECL_OVERRIDE; + void initialize() override; protected: - void setGameState( const QString & state ) Q_DECL_OVERRIDE; - bool checkAdd(const PatPile * pile, const QList & oldCards, const QList & newCards) const Q_DECL_OVERRIDE; - bool checkRemove(const PatPile * pile, const QList & cards) const Q_DECL_OVERRIDE; - void cardsMoved( const QList & cards, KCardPile * oldPile, KCardPile * newPile ) Q_DECL_OVERRIDE; - void restart( const QList & cards ) Q_DECL_OVERRIDE; + void setGameState( const QString & state ) override; + bool checkAdd(const PatPile * pile, const QList & oldCards, const QList & newCards) const override; + bool checkRemove(const PatPile * pile, const QList & cards) const override; + void cardsMoved( const QList & cards, KCardPile * oldPile, KCardPile * newPile ) override; + void restart( const QList & cards ) override; protected slots: - bool newCards() Q_DECL_OVERRIDE; + bool newCards() override; private: PatPile *talon; PatPile *stack[4][8]; PatPile *aces; friend class Mod3Solver; }; #endif diff --git a/numbereddealdialog.h b/numbereddealdialog.h index 6de1846..fb1fc03 100644 --- a/numbereddealdialog.h +++ b/numbereddealdialog.h @@ -1,53 +1,53 @@ /* * Copyright 2010 Parker Coates * * 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, see . * */ #ifndef NUMBEREDDEALDIALOG_H #define NUMBEREDDEALDIALOG_H class KComboBox; #include #include class QSpinBox; class NumberedDealDialog : public QDialog { Q_OBJECT public: explicit NumberedDealDialog( QWidget * parent ); void setGameType( int gameId ); void setDealNumber( int dealNumber ); public slots: - void setVisible( bool visible ) Q_DECL_OVERRIDE; + void setVisible( bool visible ) override; signals: void dealChosen( int gameId, int dealNumber ); private slots: void handleOkClicked(); private: KComboBox * m_gameType; QSpinBox * m_dealNumber; QMap m_indexToIdMap; }; #endif diff --git a/patpile.h b/patpile.h index af4d148..f847bb1 100644 --- a/patpile.h +++ b/patpile.h @@ -1,67 +1,67 @@ /* * Copyright (C) 2010 Parker Coates * * 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, see . * */ #ifndef PATPILE_H #define PATPILE_H class DealerScene; #include "KCardPile" class PatPile : public KCardPile { public: enum PileRole { NoRole, Stock, Waste, Tableau, TableauType1 = Tableau, TableauType2, TableauType3, TableauType4, Foundation, FoundationType1 = Foundation, FoundationType2, FoundationType3, FoundationType4, Cell }; PatPile( DealerScene * scene, int index, const QString & objectName = QString() ); virtual ~PatPile(); int index() const; void setPileRole( PileRole role ); PileRole pileRole() const; bool isFoundation() const; - QList cardPositions() const Q_DECL_OVERRIDE; + QList cardPositions() const override; protected: - void paintGraphic( QPainter * painter, qreal highlightedness ) Q_DECL_OVERRIDE; + void paintGraphic( QPainter * painter, qreal highlightedness ) override; private: int m_index; PileRole m_role; }; #endif diff --git a/patsolve/clocksolver.h b/patsolve/clocksolver.h index 59826df..366e24c 100644 --- a/patsolve/clocksolver.h +++ b/patsolve/clocksolver.h @@ -1,42 +1,42 @@ /* * Copyright (C) 2006-2009 Stephan Kulow * * 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, see . */ #ifndef CLOCKSOLVER_H #define CLOCKSOLVER_H class Clock; #include "patsolve.h" class ClockSolver : public Solver<9> { public: explicit ClockSolver(const Clock *dealer); - int get_possible_moves(int *a, int *numout) Q_DECL_OVERRIDE; - bool isWon() Q_DECL_OVERRIDE; - void make_move(MOVE *m) Q_DECL_OVERRIDE; - void undo_move(MOVE *m) Q_DECL_OVERRIDE; - int getOuts() Q_DECL_OVERRIDE; - void translate_layout() Q_DECL_OVERRIDE; - MoveHint translateMove(const MOVE &m) Q_DECL_OVERRIDE; + int get_possible_moves(int *a, int *numout) override; + bool isWon() override; + void make_move(MOVE *m) override; + void undo_move(MOVE *m) override; + int getOuts() override; + void translate_layout() override; + MoveHint translateMove(const MOVE &m) override; - void print_layout() Q_DECL_OVERRIDE; + void print_layout() override; const Clock *deal; }; #endif // CLOCKSOLVER_H diff --git a/patsolve/fortyeightsolver.h b/patsolve/fortyeightsolver.h index 08151b8..dd233b0 100644 --- a/patsolve/fortyeightsolver.h +++ b/patsolve/fortyeightsolver.h @@ -1,53 +1,53 @@ /* * Copyright (C) 2006-2009 Stephan Kulow * * 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, see . */ #ifndef FORTYEIGHTSOLVER_H #define FORTYEIGHTSOLVER_H class Fortyeight; #include "patsolve.h" class FortyeightSolverState; class FortyeightSolver : public Solver<10> { public: explicit FortyeightSolver(const Fortyeight *dealer); - int get_possible_moves(int *a, int *numout) Q_DECL_OVERRIDE; - bool isWon() Q_DECL_OVERRIDE; - void make_move(MOVE *m) Q_DECL_OVERRIDE; - void undo_move(MOVE *m) Q_DECL_OVERRIDE; - int getOuts() Q_DECL_OVERRIDE; - unsigned int getClusterNumber() Q_DECL_OVERRIDE; - void translate_layout() Q_DECL_OVERRIDE; - void unpack_cluster( unsigned int k ) Q_DECL_OVERRIDE; - MoveHint translateMove(const MOVE &m) Q_DECL_OVERRIDE; + int get_possible_moves(int *a, int *numout) override; + bool isWon() override; + void make_move(MOVE *m) override; + void undo_move(MOVE *m) override; + int getOuts() override; + unsigned int getClusterNumber() override; + void translate_layout() override; + void unpack_cluster( unsigned int k ) override; + MoveHint translateMove(const MOVE &m) override; bool checkMove( int from, int to, MOVE *mp ); bool checkMoveOut( int from, MOVE *mp, int *dropped ); void checkState(FortyeightSolverState &d); - void print_layout() Q_DECL_OVERRIDE; + void print_layout() override; const Fortyeight *deal; bool lastdeal; card_t O[8]; /* output piles store only the rank or NONE */ card_t Osuit[8]; }; #endif // FORTYEIGHTSOLVER_H diff --git a/patsolve/freecellsolver.h b/patsolve/freecellsolver.h index f3c66c0..a21a377 100644 --- a/patsolve/freecellsolver.h +++ b/patsolve/freecellsolver.h @@ -1,71 +1,71 @@ /* * Copyright (C) 1998-2002 Tom Holroyd * Copyright (C) 2006-2009 Stephan Kulow * * 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, see . */ #ifndef FREECELLSOLVER_H #define FREECELLSOLVER_H #include "abstract_fc_solve_solver.h" constexpr auto Nwpiles = 8; constexpr auto Ntpiles = 4; class Freecell; class FreecellSolver : public FcSolveSolver { public: explicit FreecellSolver(const Freecell *dealer); int good_automove(int o, int r); int get_possible_moves(int *a, int *numout) override; #if 0 - bool isWon() Q_DECL_OVERRIDE; - void make_move(MOVE *m) Q_DECL_OVERRIDE; - void undo_move(MOVE *m) Q_DECL_OVERRIDE; - void prioritize(MOVE *mp0, int n) Q_DECL_OVERRIDE; - int getOuts() Q_DECL_OVERRIDE; - unsigned int getClusterNumber() Q_DECL_OVERRIDE; - void translate_layout() Q_DECL_OVERRIDE; - void unpack_cluster( unsigned int k ) Q_DECL_OVERRIDE; - MoveHint translateMove(const MOVE &m) Q_DECL_OVERRIDE; + bool isWon() override; + void make_move(MOVE *m) override; + void undo_move(MOVE *m) override; + void prioritize(MOVE *mp0, int n) override; + int getOuts() override; + unsigned int getClusterNumber() override; + void translate_layout() override; + void unpack_cluster( unsigned int k ) override; + MoveHint translateMove(const MOVE &m) override; #endif void translate_layout() override; #if 0 virtual void unpack_cluster( unsigned int k ); #endif MoveHint translateMove(const MOVE &m) override; void setFcSolverGameParams() override; int get_cmd_line_arg_count() override; const char * * get_cmd_line_args() override; #if 0 virtual void print_layout(); int Nwpiles; /* the numbers we're actually using */ int Ntpiles; /* Names of the cards. The ordering is defined in pat.h. */ card_t Osuit[4]; static int Xparam[]; #endif card_t O[4]; /* output piles store only the rank or NONE */ const Freecell *deal; }; #endif // FREECELLSOLVER_H diff --git a/patsolve/golfsolver.h b/patsolve/golfsolver.h index bcc16d1..500d1a1 100644 --- a/patsolve/golfsolver.h +++ b/patsolve/golfsolver.h @@ -1,55 +1,55 @@ /* * Copyright (C) 2006-2009 Stephan Kulow * * 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, see . */ #ifndef GOLFSOLVER_H #define GOLFSOLVER_H class Golf; #include "patsolve.h" #ifdef WITH_BH_SOLVER #include #endif class GolfSolver : public Solver<9> { public: explicit GolfSolver(const Golf *dealer); int default_max_positions; #ifdef WITH_BH_SOLVER black_hole_solver_instance_t *solver_instance; int solver_ret; - SolverInterface::ExitStatus patsolve( int _max_positions ) Q_DECL_OVERRIDE; + SolverInterface::ExitStatus patsolve( int _max_positions ) override; // More than enough space for two decks. char board_as_string[4 * 13 * 2 * 4 * 3]; void free_solver_instance(); #endif - int get_possible_moves(int *a, int *numout) Q_DECL_OVERRIDE; - bool isWon() Q_DECL_OVERRIDE; - void make_move(MOVE *m) Q_DECL_OVERRIDE; - void undo_move(MOVE *m) Q_DECL_OVERRIDE; - int getOuts() Q_DECL_OVERRIDE; - void translate_layout() Q_DECL_OVERRIDE; - MoveHint translateMove(const MOVE &m) Q_DECL_OVERRIDE; - - void print_layout() Q_DECL_OVERRIDE; + int get_possible_moves(int *a, int *numout) override; + bool isWon() override; + void make_move(MOVE *m) override; + void undo_move(MOVE *m) override; + int getOuts() override; + void translate_layout() override; + MoveHint translateMove(const MOVE &m) override; + + void print_layout() override; const Golf *deal; }; #endif // GOLFSOLVER_H diff --git a/patsolve/grandfsolver.h b/patsolve/grandfsolver.h index d99572a..a7aeb20 100644 --- a/patsolve/grandfsolver.h +++ b/patsolve/grandfsolver.h @@ -1,49 +1,49 @@ /* * Copyright (C) 2006-2009 Stephan Kulow * * 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, see . */ #ifndef GRANDFSOLVER_H #define GRANDFSOLVER_H class Grandf; #include "patsolve.h" class GrandfSolver : public Solver<7*3+1> { public: explicit GrandfSolver(const Grandf *dealer); - int get_possible_moves(int *a, int *numout) Q_DECL_OVERRIDE; - bool isWon() Q_DECL_OVERRIDE; - void make_move(MOVE *m) Q_DECL_OVERRIDE; - void undo_move(MOVE *m) Q_DECL_OVERRIDE; - int getOuts() Q_DECL_OVERRIDE; - unsigned int getClusterNumber() Q_DECL_OVERRIDE; - void translate_layout() Q_DECL_OVERRIDE; - void unpack_cluster( unsigned int k ) Q_DECL_OVERRIDE; - MoveHint translateMove(const MOVE &m) Q_DECL_OVERRIDE; - - void print_layout() Q_DECL_OVERRIDE; + int get_possible_moves(int *a, int *numout) override; + bool isWon() override; + void make_move(MOVE *m) override; + void undo_move(MOVE *m) override; + int getOuts() override; + unsigned int getClusterNumber() override; + void translate_layout() override; + void unpack_cluster( unsigned int k ) override; + MoveHint translateMove(const MOVE &m) override; + + void print_layout() override; card_t Osuit[4]; const Grandf *deal; int m_redeal; int offs; }; #endif // GRANDFSOLVER_H diff --git a/patsolve/gypsysolver.h b/patsolve/gypsysolver.h index ed05ab4..3371c7f 100644 --- a/patsolve/gypsysolver.h +++ b/patsolve/gypsysolver.h @@ -1,48 +1,48 @@ /* * Copyright (C) 2006-2009 Stephan Kulow * * 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, see . */ #ifndef GYPSYSOLVER_H #define GYPSYSOLVER_H class Gypsy; #include "patsolve.h" class GypsySolver : public Solver<8 + 1 + 8> { public: explicit GypsySolver(const Gypsy *dealer); int good_automove(int o, int r); - int get_possible_moves(int *a, int *numout) Q_DECL_OVERRIDE; - bool isWon() Q_DECL_OVERRIDE; - void make_move(MOVE *m) Q_DECL_OVERRIDE; - void undo_move(MOVE *m) Q_DECL_OVERRIDE; - int getOuts() Q_DECL_OVERRIDE; - void translate_layout() Q_DECL_OVERRIDE; - MoveHint translateMove(const MOVE &m) Q_DECL_OVERRIDE; - - void print_layout() Q_DECL_OVERRIDE; + int get_possible_moves(int *a, int *numout) override; + bool isWon() override; + void make_move(MOVE *m) override; + void undo_move(MOVE *m) override; + int getOuts() override; + void translate_layout() override; + MoveHint translateMove(const MOVE &m) override; + + void print_layout() override; /* Names of the cards. The ordering is defined in pat.h. */ const Gypsy *deal; int deck, outs; int params[6]; }; #endif // GYPSYSOLVER_H diff --git a/patsolve/idiotsolver.h b/patsolve/idiotsolver.h index 5d7af7d..0493562 100644 --- a/patsolve/idiotsolver.h +++ b/patsolve/idiotsolver.h @@ -1,44 +1,44 @@ /* * Copyright (C) 2006-2009 Stephan Kulow * * 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, see . */ #ifndef IDIOTSOLVER_H #define IDIOTSOLVER_H class Idiot; #include "patsolve.h" class IdiotSolver : public Solver<6> { public: explicit IdiotSolver(const Idiot *dealer); - int get_possible_moves(int *a, int *numout) Q_DECL_OVERRIDE; - bool isWon() Q_DECL_OVERRIDE; - void make_move(MOVE *m) Q_DECL_OVERRIDE; - void undo_move(MOVE *m) Q_DECL_OVERRIDE; - int getOuts() Q_DECL_OVERRIDE; - void translate_layout() Q_DECL_OVERRIDE; - MoveHint translateMove(const MOVE &m) Q_DECL_OVERRIDE; - - void print_layout() Q_DECL_OVERRIDE; + int get_possible_moves(int *a, int *numout) override; + bool isWon() override; + void make_move(MOVE *m) override; + void undo_move(MOVE *m) override; + int getOuts() override; + void translate_layout() override; + MoveHint translateMove(const MOVE &m) override; + + void print_layout() override; bool canMoveAway( int pile ) const; const Idiot *deal; }; #endif // IDIOTSOLVER_H diff --git a/patsolve/klondikesolver.h b/patsolve/klondikesolver.h index 2e5757f..243f0b5 100644 --- a/patsolve/klondikesolver.h +++ b/patsolve/klondikesolver.h @@ -1,51 +1,51 @@ /* * Copyright (C) 2006-2009 Stephan Kulow * * 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, see . */ #ifndef KLONDIKESOLVER_H #define KLONDIKESOLVER_H class Klondike; #include "patsolve.h" class KlondikeSolver : public Solver<9> { public: KlondikeSolver(const Klondike *dealer, int draw); int good_automove(int o, int r); - int get_possible_moves(int *a, int *numout) Q_DECL_OVERRIDE; - bool isWon() Q_DECL_OVERRIDE; - void make_move(MOVE *m) Q_DECL_OVERRIDE; - void undo_move(MOVE *m) Q_DECL_OVERRIDE; - int getOuts() Q_DECL_OVERRIDE; - unsigned int getClusterNumber() Q_DECL_OVERRIDE; - void translate_layout() Q_DECL_OVERRIDE; - void unpack_cluster( unsigned int k ) Q_DECL_OVERRIDE; - MoveHint translateMove(const MOVE &m) Q_DECL_OVERRIDE; - - void print_layout() Q_DECL_OVERRIDE; + int get_possible_moves(int *a, int *numout) override; + bool isWon() override; + void make_move(MOVE *m) override; + void undo_move(MOVE *m) override; + int getOuts() override; + unsigned int getClusterNumber() override; + void translate_layout() override; + void unpack_cluster( unsigned int k ) override; + MoveHint translateMove(const MOVE &m) override; + + void print_layout() override; /* Names of the cards. The ordering is defined in pat.h. */ card_t O[4]; /* output piles store only the rank or NONE */ card_t Osuit[4]; const Klondike *deal; int m_draw; }; #endif // KLONDIKESOLVER_H diff --git a/patsolve/mod3solver.h b/patsolve/mod3solver.h index 1cb4431..916b48e 100644 --- a/patsolve/mod3solver.h +++ b/patsolve/mod3solver.h @@ -1,44 +1,44 @@ /* * Copyright (C) 2006-2009 Stephan Kulow * * 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, see . */ #ifndef MOD3SOLVER_H #define MOD3SOLVER_H class Mod3; #include "patsolve.h" class Mod3Solver : public Solver { public: explicit Mod3Solver(const Mod3 *dealer); - int get_possible_moves(int *a, int *numout) Q_DECL_OVERRIDE; - bool isWon() Q_DECL_OVERRIDE; - void make_move(MOVE *m) Q_DECL_OVERRIDE; - void undo_move(MOVE *m) Q_DECL_OVERRIDE; - int getOuts() Q_DECL_OVERRIDE; - void translate_layout() Q_DECL_OVERRIDE; - MoveHint translateMove(const MOVE &m) Q_DECL_OVERRIDE; + int get_possible_moves(int *a, int *numout) override; + bool isWon() override; + void make_move(MOVE *m) override; + void undo_move(MOVE *m) override; + int getOuts() override; + void translate_layout() override; + MoveHint translateMove(const MOVE &m) override; - void print_layout() Q_DECL_OVERRIDE; + void print_layout() override; const Mod3 *deal; int aces; int deck; }; #endif // MOD3SOLVER_H diff --git a/patsolve/patsolve.h b/patsolve/patsolve.h index 481e915..1abe0e1 100644 --- a/patsolve/patsolve.h +++ b/patsolve/patsolve.h @@ -1,160 +1,160 @@ /* * Copyright (C) 1998-2002 Tom Holroyd * Copyright (C) 2006-2009 Stephan Kulow * * 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, see . */ #ifndef PATSOLVE_H #define PATSOLVE_H #include "solverinterface.h" #include "../hint.h" #include "memory.h" #include "KCardPile" #include #include #include #include #include /* A card is represented as ( down << 6 ) + (suit << 4) + rank. */ typedef quint8 card_t; struct POSITION { POSITION *queue; /* next position in the queue */ POSITION *parent; /* point back up the move stack */ TREE *node; /* compact position rep.'s tree node */ MOVE move; /* move that got us here from the parent */ quint32 cluster; /* the cluster this node is in */ short depth; /* number of moves so far */ quint8 nchild; /* number of child nodes left */ }; class MemoryManager; template class Solver : public SolverInterface { public: Solver(); virtual ~Solver(); ExitStatus patsolve( int max_positions = -1) override; bool recursive(POSITION *pos = nullptr); void translate_layout() override = 0; MoveHint translateMove(const MOVE &m ) override = 0; - void stopExecution() final Q_DECL_OVERRIDE; - QList firstMoves() const final Q_DECL_OVERRIDE; - QList winMoves() const final Q_DECL_OVERRIDE; + void stopExecution() final override; + QList firstMoves() const final override; + QList winMoves() const final override; protected: MOVE *get_moves(int *nmoves); bool solve(POSITION *parent); void doit(); void win(POSITION *pos); virtual int get_possible_moves(int *a, int *numout) = 0; int translateSuit( int s ); void queue_position(POSITION *pos, int pri); void free_position(POSITION *pos, int); POSITION *dequeue_position(); void hashpile(int w); POSITION *new_position(POSITION *parent, MOVE *m); TREE *pack_position(void); void unpack_position(POSITION *pos); void init_buckets(void); int get_pilenum(int w); MemoryManager::inscode insert(unsigned int *cluster, int d, TREE **node); void free_buckets(void); void printcard(card_t card, FILE *outfile); int translate_pile(const KCardPile *pile, card_t *w, int size); virtual void print_layout(); void pilesort(void); void hash_layout( void ); virtual void make_move(MOVE *m) = 0; virtual void undo_move(MOVE *m) = 0; virtual void prioritize(MOVE *mp0, int n); virtual bool isWon() = 0; virtual int getOuts() = 0; virtual unsigned int getClusterNumber() { return 0; } virtual void unpack_cluster( unsigned int ) {} void init(); void free(); /* Work arrays. */ std::array W; /* the workspace */ std::array Wp; /* point to the top card of each work pile */ std::array Wlen; /* the number of cards in each pile */ /* Every different pile has a hash and a unique id. */ std::array Whash; std::array Wpilenum = {}; // = {} for zero initialization /* Position freelist. */ POSITION *Freepos = nullptr; static constexpr auto MAXMOVES = 64; /* > max # moves from any position */ MOVE Possible[MAXMOVES]; std::unique_ptr mm; ExitStatus Status; /* win, lose, or fail */ static constexpr auto NQUEUES = 127; POSITION *Qhead[NQUEUES]; /* separate queue for each priority */ int Maxq; unsigned long Total_generated, Total_positions; qreal depth_sum; POSITION *Stack = nullptr; QMap recu_pos; int max_positions; protected: QList m_firstMoves; QList m_winMoves; std::atomic_bool m_shouldEnd; }; /* Misc. */ constexpr card_t PS_DIAMOND = 0x00; /* red */ constexpr card_t PS_CLUB = 0x10; /* black */ constexpr card_t PS_HEART = 0x20; /* red */ constexpr card_t PS_SPADE = 0x30; /* black */ constexpr card_t PS_BLACK = 0x10; constexpr card_t PS_COLOR = 0x10; /* black if set */ constexpr card_t PS_SUIT = 0x30; /* mask both suit bits */ constexpr card_t NONE = 0; constexpr card_t PS_ACE = 1; constexpr card_t PS_KING = 13; constexpr card_t RANK(card_t card) {return card & 0xF;} constexpr card_t SUIT(card_t card) {return (card >> 4 ) & 3;} constexpr card_t COLOR(card_t card) {return card & PS_COLOR;} constexpr card_t DOWN(card_t card) {return (card) & ( 1 << 7 );} #endif // PATSOLVE_H diff --git a/patsolve/simonsolver.h b/patsolve/simonsolver.h index d8d63cd..4ea33fb 100644 --- a/patsolve/simonsolver.h +++ b/patsolve/simonsolver.h @@ -1,55 +1,55 @@ /* * Copyright (C) 2006-2009 Stephan Kulow * * 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, see . */ #ifndef SIMONSOLVER_H #define SIMONSOLVER_H #include "abstract_fc_solve_solver.h" #include "simon.h" class Simon; class SimonSolver : public FcSolveSolver { public: explicit SimonSolver(const Simon *dealer); - int get_possible_moves(int *a, int *numout) Q_DECL_OVERRIDE; + int get_possible_moves(int *a, int *numout) override; #if 0 - bool isWon() Q_DECL_OVERRIDE; - void make_move(MOVE *m) Q_DECL_OVERRIDE; - void undo_move(MOVE *m) Q_DECL_OVERRIDE; - int getOuts() Q_DECL_OVERRIDE; - unsigned int getClusterNumber() Q_DECL_OVERRIDE; + bool isWon() override; + void make_move(MOVE *m) override; + void undo_move(MOVE *m) override; + int getOuts() override; + unsigned int getClusterNumber() override; #endif void translate_layout() override; MoveHint translateMove(const MOVE &m) override; #if 0 - void unpack_cluster( unsigned int k ) Q_DECL_OVERRIDE; - void print_layout() Q_DECL_OVERRIDE; + void unpack_cluster( unsigned int k ) override; + void print_layout() override; #endif void setFcSolverGameParams() override; int get_cmd_line_arg_count() override; const char * * get_cmd_line_args() override; #if 0 /* Names of the cards. The ordering is defined in pat.h. */ int O[4]; #endif const Simon *deal; }; #endif // SIMONSOLVER_H diff --git a/patsolve/spidersolver.h b/patsolve/spidersolver.h index d85bbe4..1a534db 100644 --- a/patsolve/spidersolver.h +++ b/patsolve/spidersolver.h @@ -1,47 +1,47 @@ /* * Copyright (C) 2006-2009 Stephan Kulow * * 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, see . */ #ifndef SPIDERSOLVER_H #define SPIDERSOLVER_H #include "patsolve.h" class Spider; class SpiderSolver : public Solver { public: explicit SpiderSolver(const Spider *dealer); - int get_possible_moves(int *a, int *numout) Q_DECL_OVERRIDE; - bool isWon() Q_DECL_OVERRIDE; - void make_move(MOVE *m) Q_DECL_OVERRIDE; - void undo_move(MOVE *m) Q_DECL_OVERRIDE; - int getOuts() Q_DECL_OVERRIDE; - unsigned int getClusterNumber() Q_DECL_OVERRIDE; - void translate_layout() Q_DECL_OVERRIDE; - void unpack_cluster( unsigned int k ) Q_DECL_OVERRIDE; - MoveHint translateMove(const MOVE &m) Q_DECL_OVERRIDE; - - void print_layout() Q_DECL_OVERRIDE; + int get_possible_moves(int *a, int *numout) override; + bool isWon() override; + void make_move(MOVE *m) override; + void undo_move(MOVE *m) override; + int getOuts() override; + unsigned int getClusterNumber() override; + void translate_layout() override; + void unpack_cluster( unsigned int k ) override; + MoveHint translateMove(const MOVE &m) override; + + void print_layout() override; /* Names of the cards. The ordering is defined in pat.h. */ int O[8]; const Spider *deal; }; #endif // SPIDERSOLVER_H diff --git a/patsolve/yukonsolver.h b/patsolve/yukonsolver.h index 2e40820..2420e16 100644 --- a/patsolve/yukonsolver.h +++ b/patsolve/yukonsolver.h @@ -1,50 +1,50 @@ /* * Copyright (C) 2006-2009 Stephan Kulow * * 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, see . */ #ifndef YUKONSOLVER_H #define YUKONSOLVER_H #include "patsolve.h" class Yukon; class YukonSolver : public Solver<7> { public: explicit YukonSolver(const Yukon *dealer); int good_automove(int o, int r); - int get_possible_moves(int *a, int *numout) Q_DECL_OVERRIDE; - bool isWon() Q_DECL_OVERRIDE; - void make_move(MOVE *m) Q_DECL_OVERRIDE; - void undo_move(MOVE *m) Q_DECL_OVERRIDE; - int getOuts() Q_DECL_OVERRIDE; - unsigned int getClusterNumber() Q_DECL_OVERRIDE; - void translate_layout() Q_DECL_OVERRIDE; - void unpack_cluster( unsigned int k ) Q_DECL_OVERRIDE; - MoveHint translateMove(const MOVE &m) Q_DECL_OVERRIDE; - - void print_layout() Q_DECL_OVERRIDE; + int get_possible_moves(int *a, int *numout) override; + bool isWon() override; + void make_move(MOVE *m) override; + void undo_move(MOVE *m) override; + int getOuts() override; + unsigned int getClusterNumber() override; + void translate_layout() override; + void unpack_cluster( unsigned int k ) override; + MoveHint translateMove(const MOVE &m) override; + + void print_layout() override; /* Names of the cards. The ordering is defined in pat.h. */ card_t O[4]; /* output piles store only the rank or NONE */ card_t Osuit[4]; const Yukon *deal; }; #endif // YUKONSOLVER_H diff --git a/simon.cpp b/simon.cpp index 0316237..959396c 100644 --- a/simon.cpp +++ b/simon.cpp @@ -1,192 +1,192 @@ /* * Copyright (C) 2000-2009 Stephan Kulow * Copyright (C) 2010 Parker Coates * * License of original code: * ------------------------------------------------------------------------- * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, * provided that the above copyright notice appear in all copies and that * both that copyright notice and this permission notice appear in * supporting documentation. * * This file is provided AS IS with no warranties of any kind. The author * shall have no liability with respect to the infringement of copyrights, * trade secrets or any patents by this file or any part thereof. In no * event will the author be liable for any lost revenue or profits or * other special, indirect and consequential damages. * ------------------------------------------------------------------------- * * License of modifications/additions made after 2009-01-01: * ------------------------------------------------------------------------- * 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, see . * ------------------------------------------------------------------------- */ #include "simon.h" #include "dealerinfo.h" #include "pileutils.h" #include "patsolve/simonsolver.h" #include "settings.h" #include Simon::Simon( const DealerInfo * di ) : DealerScene( di ) { } void Simon::initialize() { setDeckContents(); const qreal dist_x = 1.11; for ( int i = 0; i < 4; ++i ) { target[i] = new PatPile( this, i + 1, QStringLiteral( "target%1" ).arg( i ) ); target[i]->setPileRole(PatPile::Foundation); target[i]->setLayoutPos((i+3)*dist_x, 0); target[i]->setSpread(0, 0); target[i]->setKeyboardSelectHint( KCardPile::NeverFocus ); target[i]->setKeyboardDropHint( KCardPile::AutoFocusTop ); } for ( int i = 0; i < 10; ++i ) { store[i] = new PatPile( this, 5 + i, QStringLiteral( "store%1" ).arg( i ) ); store[i]->setPileRole(PatPile::Tableau); store[i]->setLayoutPos(dist_x*i, 1.2); store[i]->setBottomPadding( 2.5 ); store[i]->setHeightPolicy( KCardPile::GrowDown ); store[i]->setZValue( 0.01 * i ); store[i]->setKeyboardSelectHint( KCardPile::AutoFocusDeepestRemovable ); store[i]->setKeyboardDropHint( KCardPile::AutoFocusTop ); } setActions(DealerScene::Hint | DealerScene::Demo); auto solver = new SimonSolver( this ); solver->default_max_positions = Settings::simpleSimonSolverIterationsLimit(); setSolver( solver ); //setNeededFutureMoves( 1 ); // could be some nonsense moves } void Simon::restart( const QList & cards ) { QList cardList = cards; QPointF initPos( 0, -deck()->cardHeight() ); for ( int piles = 9; piles >= 3; --piles ) for ( int j = 0; j < piles; ++j ) addCardForDeal( store[j], cardList.takeLast(), true, initPos ); for ( int j = 0; j < 10; ++j ) addCardForDeal( store[j], cardList.takeLast(), true, initPos ); Q_ASSERT( cardList.isEmpty() ); startDealAnimation(); } bool Simon::checkPrefering(const PatPile * pile, const QList & oldCards, const QList & newCards) const { return pile->pileRole() == PatPile::Tableau && !oldCards.isEmpty() && oldCards.last()->suit() == newCards.first()->suit(); } bool Simon::checkAdd(const PatPile * pile, const QList & oldCards, const QList & newCards) const { if (pile->pileRole() == PatPile::Tableau) { if (! (oldCards.isEmpty() || oldCards.last()->rank() == newCards.first()->rank() + 1 )) { return false; } int seqs_count = countSameSuitDescendingSequences(newCards); if (seqs_count < 0) return false; // This is similar to the supermoves of Freecell - we can use empty // columns to temporarily hold intermediate sub-sequences which are // not the same suit - only a "false" parent. // Shlomi Fish int empty_piles_count = 0; for (int i = 0; i < 10; ++i ) if (store[i]->isEmpty() && ( store[i]->index() != pile->index() )) empty_piles_count++; return (seqs_count <= (1 << empty_piles_count)); } else { return oldCards.isEmpty() && newCards.first()->rank() == KCardDeck::King && newCards.last()->rank() == KCardDeck::Ace && isSameSuitDescending(newCards); } } bool Simon::checkRemove(const PatPile * pile, const QList & cards) const { if (pile->pileRole() != PatPile::Tableau) return false; int seqs_count = countSameSuitDescendingSequences(cards); return (seqs_count >= 0); } QString Simon::solverFormat() const { QString output; QString tmp; for (int i = 0; i < 4 ; i++) { if (target[i]->isEmpty()) continue; tmp += suitToString(target[i]->topCard()->suit()) + "-K "; } if (!tmp.isEmpty()) output += QStringLiteral("Foundations: %1\n").arg(tmp); for (int i = 0; i < 10 ; i++) { cardsListToLine(output, store[i]->cards()); } return output; } static class SimonDealerInfo : public DealerInfo { public: SimonDealerInfo() : DealerInfo(I18N_NOOP("Simple Simon"), SimpleSimonId) {} - DealerScene *createGame() const Q_DECL_OVERRIDE + DealerScene *createGame() const override { return new Simon( this ); } } simonDealerInfo; diff --git a/simon.h b/simon.h index d816f27..24d4e32 100644 --- a/simon.h +++ b/simon.h @@ -1,64 +1,64 @@ /* * Copyright (C) 2000-2009 Stephan Kulow * * License of original code: * ------------------------------------------------------------------------- * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, * provided that the above copyright notice appear in all copies and that * both that copyright notice and this permission notice appear in * supporting documentation. * * This file is provided AS IS with no warranties of any kind. The author * shall have no liability with respect to the infringement of copyrights, * trade secrets or any patents by this file or any part thereof. In no * event will the author be liable for any lost revenue or profits or * other special, indirect and consequential damages. * ------------------------------------------------------------------------- * * License of modifications/additions made after 2009-01-01: * ------------------------------------------------------------------------- * 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, see . * ------------------------------------------------------------------------- */ #ifndef SIMON_H #define SIMON_H #include "dealer.h" class Simon : public DealerScene { Q_OBJECT public: explicit Simon( const DealerInfo * di ); - void initialize() Q_DECL_OVERRIDE; + void initialize() override; protected: - bool checkAdd(const PatPile * pile, const QList & oldCards, const QList & newCards) const Q_DECL_OVERRIDE; - bool checkPrefering(const PatPile * pile, const QList & oldCards, const QList & newCards) const Q_DECL_OVERRIDE; - bool checkRemove(const PatPile * pile, const QList & cards) const Q_DECL_OVERRIDE; - void restart( const QList & cards ) Q_DECL_OVERRIDE; + bool checkAdd(const PatPile * pile, const QList & oldCards, const QList & newCards) const override; + bool checkPrefering(const PatPile * pile, const QList & oldCards, const QList & newCards) const override; + bool checkRemove(const PatPile * pile, const QList & cards) const override; + void restart( const QList & cards ) override; private: PatPile* store[10]; PatPile* target[4]; virtual QString solverFormat() const; friend class SimonSolver; }; #endif diff --git a/spider.cpp b/spider.cpp index e6a254a..7baff0f 100644 --- a/spider.cpp +++ b/spider.cpp @@ -1,511 +1,511 @@ /* * Copyright (C) 2003 Josh Metzler * Copyright (C) 2000-2009 Stephan Kulow * Copyright (C) 2010 Parker Coates * * License of original code: * ------------------------------------------------------------------------- * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, * provided that the above copyright notice appear in all copies and that * both that copyright notice and this permission notice appear in * supporting documentation. * * This file is provided AS IS with no warranties of any kind. The author * shall have no liability with respect to the infringement of copyrights, * trade secrets or any patents by this file or any part thereof. In no * event will the author be liable for any lost revenue or profits or * other special, indirect and consequential damages. * ------------------------------------------------------------------------- * * License of modifications/additions made after 2009-01-01: * ------------------------------------------------------------------------- * 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, see . * ------------------------------------------------------------------------- */ #include "spider.h" #include "dealerinfo.h" #include "pileutils.h" #include "settings.h" #include "speeds.h" #include "patsolve/spidersolver.h" #include #include #include class InvisiblePile : public PatPile { public: InvisiblePile( DealerScene * scene, int index, const QString & objectName = QString() ) : PatPile( scene, index, objectName ) { }; protected: - void paintGraphic( QPainter * painter, qreal highlightedness ) Q_DECL_OVERRIDE + void paintGraphic( QPainter * painter, qreal highlightedness ) override { Q_UNUSED( painter ); Q_UNUSED( highlightedness ); }; }; Spider::Spider( const DealerInfo * di ) : DealerScene( di ) { } void Spider::initialize() { m_leg = 0; m_redeal = 0; const qreal dist_x = 1.12; const qreal smallNeg = -1e-6; m_suits = Settings::spiderSuitCount(); m_stackFaceup = Settings::spiderStackFaceup(); createDeck(); // Dealing the cards out into 5 piles so the user can see how many // sets of 10 cards are left to be dealt out for( int column = 0; column < 5; ++column ) { redeals[column] = new InvisiblePile( this, column + 1, QStringLiteral( "redeals%1" ).arg( column ) ); redeals[column]->setPileRole(PatPile::Stock); redeals[column]->setLayoutPos( dist_x * (9 - (4.0 - column) / 3), smallNeg ); redeals[column]->setZValue(12 * ( 5-column )); redeals[column]->setSpread(0, 0); redeals[column]->setKeyboardSelectHint( KCardPile::NeverFocus ); redeals[column]->setKeyboardDropHint( KCardPile::NeverFocus ); connect( redeals[column], &KCardPile::clicked, this, &DealerScene::drawDealRowOrRedeal ); } // The 10 playing piles for( int column = 0; column < 10; ++column ) { stack[column] = new PatPile( this, column + 6, QStringLiteral( "stack%1" ).arg( column ) ); stack[column]->setPileRole(PatPile::Tableau); stack[column]->setLayoutPos(dist_x * column, 0); stack[column]->setZValue(20); stack[column]->setAutoTurnTop(true); stack[column]->setBottomPadding( 1.5 ); stack[column]->setHeightPolicy( KCardPile::GrowDown ); stack[column]->setKeyboardSelectHint( KCardPile::AutoFocusDeepestRemovable ); stack[column]->setKeyboardDropHint( KCardPile::AutoFocusTop ); } // The 8 'legs' so named by me because spiders have 8 legs - why // else the name Spider? for( int column = 0; column < 8; ++column ) { legs[column] = new InvisiblePile( this, column + 16, QStringLiteral( "legs%1" ).arg( column ) ); legs[column]->setPileRole(PatPile::Foundation); legs[column]->setLayoutPos(dist_x / 3 * column, smallNeg); legs[column]->setZValue(column+1); legs[column]->setSpread(0, 0); legs[column]->setZValue(14 * column); legs[column]->setVisible( false ); legs[column]->setKeyboardSelectHint( KCardPile::NeverFocus ); legs[column]->setKeyboardDropHint( KCardPile::NeverFocus ); } // Moving an A-K run to a leg is not really an autoDrop - the // user should have no choice. setAutoDropEnabled(false); setActions(DealerScene::Hint | DealerScene::Demo | DealerScene::Deal); setSolver( new SpiderSolver( this ) ); options = new KSelectAction(i18n("Spider &Options"), this ); options->addAction( i18n("1 Suit (Easy)") ); options->addAction( i18n("2 Suits (Medium)") ); options->addAction( i18n("4 Suits (Hard)") ); if ( m_suits == 1 ) options->setCurrentItem( 0 ); else if ( m_suits == 2 ) options->setCurrentItem( 1 ); else options->setCurrentItem( 2 ); connect(options, static_cast(&KSelectAction::triggered), this, &Spider::gameTypeChanged); m_stackFaceupOption = new KSelectAction(i18n("S&tack Options"), this ); m_stackFaceupOption->addAction( i18n("Face &Down (harder)") ); m_stackFaceupOption->addAction( i18n("Face &Up (easier)") ); m_stackFaceupOption->setCurrentItem( m_stackFaceup ); connect(m_stackFaceupOption, static_cast(&KSelectAction::triggered), this, &Spider::gameTypeChanged); } QList Spider::configActions() const { return QList() << options << m_stackFaceupOption; } void Spider::gameTypeChanged() { stopDemo(); if ( allowedToStartNewGame() ) { if ( options->currentItem() == 0 ) setSuits( 1 ); else if ( options->currentItem() == 1 ) setSuits( 2 ); else setSuits( 4 ); if ( m_stackFaceup != m_stackFaceupOption->currentItem() ) { m_stackFaceup = m_stackFaceupOption->currentItem(); Settings::setSpiderStackFaceup( m_stackFaceup ); } startNew( gameNumber() ); } else { // If we're not allowed, reset the option to // the current number of suits. if ( m_suits == 1 ) options->setCurrentItem( 0 ); else if ( m_suits == 2 ) options->setCurrentItem( 1 ); else options->setCurrentItem( 2 ); m_stackFaceupOption->setCurrentItem( m_stackFaceup ); } } void Spider::setSuits(int suits) { if ( suits != m_suits ) { m_suits = suits; stopDemo(); clearHighlightedItems(); setKeyboardModeActive( false ); int cardWidth = deck()->cardWidth(); createDeck(); deck()->setCardWidth( cardWidth ); Settings::setSpiderSuitCount( m_suits ); if ( m_suits == 1 ) options->setCurrentItem( 0 ); else if ( m_suits == 2 ) options->setCurrentItem( 1 ); else options->setCurrentItem( 2 ); } } void Spider::createDeck() { // These look a bit weird, but are needed to keep the game numbering // from breaking. The original logic always created groupings of 4 // suits, while the new logic is more flexible. We maintain the card // ordering by always passing a list of 4 suits even if we really only // have one or two. QList suits; if ( m_suits == 1 ) suits << KCardDeck::Spades << KCardDeck::Spades << KCardDeck::Spades << KCardDeck::Spades; else if ( m_suits == 2 ) suits << KCardDeck::Hearts << KCardDeck::Spades << KCardDeck::Hearts << KCardDeck::Spades; else suits << KCardDeck::Clubs << KCardDeck::Diamonds << KCardDeck::Hearts << KCardDeck::Spades; setDeckContents( 2, suits ); } bool Spider::checkAdd(const PatPile * pile, const QList & oldCards, const QList & newCards) const { // assuming the cardlist is a valid unit, since I allowed // it to be removed - can drop any card on empty pile or // on any suit card of one higher rank return pile->pileRole() == PatPile::Tableau && ( oldCards.isEmpty() || oldCards.last()->rank() == newCards.first()->rank() + 1 ); } bool Spider::checkRemove(const PatPile * pile, const QList & cards) const { return pile->pileRole() == PatPile::Tableau && isSameSuitDescending(cards); } QString Spider::getGameState() const { return QString::number(m_leg*10 + m_redeal); } void Spider::setGameState( const QString & state ) { int n = state.toInt(); int numLegs = n / 10; int numRedeals = n % 10; if ( numRedeals != m_redeal || numLegs != m_leg ) { m_redeal = numRedeals; for ( int i = 0; i < 5; ++i ) redeals[i]->setVisible( i >= m_redeal ); m_leg = numLegs; for ( int i = 0; i < 8; ++i ) legs[i]->setVisible( i < m_leg ); recalculatePileLayouts(); foreach ( KCardPile * p, piles() ) updatePileLayout( p, 0 ); emit newCardsPossible(m_redeal <= 4); } } QString Spider::getGameOptions() const { return QString::number(m_suits); } void Spider::setGameOptions( const QString & options ) { setSuits(options.toInt()); } void Spider::restart( const QList & cards ) { m_pilesWithRuns.clear(); // make the redeal piles visible for (int i = 0; i < 5; ++i ) redeals[i]->setVisible( true ); // make the leg piles invisible for (int i = 0; i < 8; ++i ) legs[i]->setVisible( false ); recalculatePileLayouts(); m_leg = 0; m_redeal = 0; QList cardList = cards; int column = 0; // deal face down cards (5 to first 4 piles, 4 to last 6) for ( int i = 0; i < 44; ++i ) { addCardForDeal( stack[column], cardList.takeLast(), m_stackFaceup == 1, randomPos() ); column = (column + 1) % 10; } // deal face up cards, one to each pile for ( int i = 0; i < 10; ++i ) { addCardForDeal( stack[column], cardList.takeLast(), true, randomPos() ); column = (column + 1) % 10; } // deal the remaining cards into 5 'redeal' piles for ( int column = 0; column < 5; ++column ) for ( int i = 0; i < 10; ++i ) addCardForDeal( redeals[column], cardList.takeLast(), false, randomPos() ); startDealAnimation(); emit newCardsPossible(true); } void Spider::cardsMoved( const QList & cards, KCardPile * oldPile, KCardPile * newPile ) { PatPile * p = dynamic_cast( newPile ); // The solver treats the removal of complete runs from the table as a // separate move, so we don't do it automatically when the demo is active. if ( !isDemoActive() && p && p->pileRole() == PatPile::Tableau && pileHasFullRun( p ) ) { m_pilesWithRuns << p; } DealerScene::cardsMoved( cards, oldPile, newPile ); } bool Spider::pileHasFullRun( KCardPile * pile ) { QList potentialRun = pile->topCards( 13 ); return pile->count() >= 13 && potentialRun.first()->isFaceUp() && isSameSuitDescending( potentialRun ); } void Spider::moveFullRunToLeg( KCardPile * pile ) { QList run = pile->topCards( 13 ); PatPile * leg = legs[m_leg]; ++m_leg; leg->setVisible( true ); recalculatePileLayouts(); for ( int i = 0; i < 10; ++i ) if ( stack[i] != pile ) updatePileLayout( stack[i], DURATION_RELAYOUT ); for ( int i = 0; i < run.size(); ++i ) { KCard * c = run.at( i ); leg->add( c ); int duration = DURATION_AUTODROP * (0.7 + i / 10.0); c->animate( leg->pos(), leg->zValue() + i, 0, true, true, duration ); } updatePileLayout( pile, DURATION_RELAYOUT ); } QPointF Spider::randomPos() { QRectF rect = sceneRect(); qreal x = rect.left() + qreal(KRandom::random()) / RAND_MAX * (rect.width() - deck()->cardWidth()); qreal y = rect.top() + qreal(KRandom::random()) / RAND_MAX * (rect.height() - deck()->cardHeight()); return QPointF( x, y ); } bool Spider::newCards() { // The solver doesn't distinguish between dealing a new row of cards and // removing complete runs from the tableau. So it we're in demo mode and // newCards() is called, we should check to see if there are any complete // runs to move before dealing a new row. if ( isDemoActive() ) { for ( int i = 0; i < 10; ++i ) { if ( pileHasFullRun( stack[i] ) ) { moveFullRunToLeg( stack[i] ); return true; } } } if ( m_redeal > 4 ) return false; redeals[m_redeal]->setVisible(false); recalculatePileLayouts(); for ( int column = 0; column < 10; ++column ) { KCard * c = redeals[m_redeal]->topCard(); if ( !c ) break; flipCardToPileAtSpeed( c, stack[column], DEAL_SPEED ); c->setZValue( c->zValue() + 10 - column ); } ++m_redeal; if (m_redeal > 4) emit newCardsPossible(false); return true; } void Spider::animationDone() { if ( !m_pilesWithRuns.isEmpty() ) moveFullRunToLeg( m_pilesWithRuns.takeFirst() ); else DealerScene::animationDone(); } void Spider::mapOldId(int id) { switch (id) { case DealerInfo::SpiderOneSuitId : setSuits(1); break; case DealerInfo::SpiderTwoSuitId : setSuits(2); break; case DealerInfo::SpiderFourSuitId : setSuits(4); break; } } int Spider::oldId() const { switch (m_suits) { case 1 : return DealerInfo::SpiderOneSuitId; case 2 : return DealerInfo::SpiderTwoSuitId; case 4 : default : return DealerInfo::SpiderFourSuitId; } } static class SpideDealerInfo : public DealerInfo { public: SpideDealerInfo() : DealerInfo(I18N_NOOP("Spider"), SpiderGeneralId) { addSubtype( SpiderOneSuitId, I18N_NOOP( "Spider (1 Suit)" ) ); addSubtype( SpiderTwoSuitId, I18N_NOOP( "Spider (2 Suit)" ) ); addSubtype( SpiderFourSuitId, I18N_NOOP( "Spider (4 Suit)" ) ); } - DealerScene *createGame() const Q_DECL_OVERRIDE + DealerScene *createGame() const override { return new Spider( this ); } } spideDealerInfo; diff --git a/spider.h b/spider.h index c2ea915..33b14ee 100644 --- a/spider.h +++ b/spider.h @@ -1,96 +1,96 @@ /* * Copyright (C) 2003 Josh Metzler * Copyright (C) 2000-2009 Stephan Kulow * * License of original code: * ------------------------------------------------------------------------- * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, * provided that the above copyright notice appear in all copies and that * both that copyright notice and this permission notice appear in * supporting documentation. * * This file is provided AS IS with no warranties of any kind. The author * shall have no liability with respect to the infringement of copyrights, * trade secrets or any patents by this file or any part thereof. In no * event will the author be liable for any lost revenue or profits or * other special, indirect and consequential damages. * ------------------------------------------------------------------------- * * License of modifications/additions made after 2009-01-01: * ------------------------------------------------------------------------- * 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, see . * ------------------------------------------------------------------------- */ #ifndef SPIDER_H #define SPIDER_H #include "dealer.h" class KSelectAction; class Spider : public DealerScene { Q_OBJECT public: explicit Spider( const DealerInfo * di ); - void initialize() Q_DECL_OVERRIDE; - void mapOldId(int id) Q_DECL_OVERRIDE; - int oldId() const Q_DECL_OVERRIDE; - QList configActions() const Q_DECL_OVERRIDE; + void initialize() override; + void mapOldId(int id) override; + int oldId() const override; + QList configActions() const override; protected: - QString getGameState() const Q_DECL_OVERRIDE; - void setGameState( const QString & state ) Q_DECL_OVERRIDE; - QString getGameOptions() const Q_DECL_OVERRIDE; - void setGameOptions( const QString & options ) Q_DECL_OVERRIDE; - bool checkAdd(const PatPile * pile, const QList & oldCards, const QList & newCards) const Q_DECL_OVERRIDE; - bool checkRemove(const PatPile * pile, const QList & cards) const Q_DECL_OVERRIDE; - void cardsMoved( const QList & cards, KCardPile * oldPile, KCardPile * newPile ) Q_DECL_OVERRIDE; - void restart( const QList & cards ) Q_DECL_OVERRIDE; + QString getGameState() const override; + void setGameState( const QString & state ) override; + QString getGameOptions() const override; + void setGameOptions( const QString & options ) override; + bool checkAdd(const PatPile * pile, const QList & oldCards, const QList & newCards) const override; + bool checkRemove(const PatPile * pile, const QList & cards) const override; + void cardsMoved( const QList & cards, KCardPile * oldPile, KCardPile * newPile ) override; + void restart( const QList & cards ) override; protected slots: - bool newCards() Q_DECL_OVERRIDE; - void animationDone() Q_DECL_OVERRIDE; + bool newCards() override; + void animationDone() override; private slots: void gameTypeChanged(); private: bool pileHasFullRun( KCardPile * pile ); void moveFullRunToLeg( KCardPile * pile ); void setSuits(int s); void createDeck(); QPointF randomPos(); PatPile *stack[10]; PatPile *legs[8]; int m_leg; PatPile *redeals[5]; int m_redeal; int m_suits; QList m_pilesWithRuns; KSelectAction *options; KSelectAction *m_stackFaceupOption; int m_stackFaceup; friend class SpiderSolver; }; #endif diff --git a/view.h b/view.h index b424ef7..97f330b 100644 --- a/view.h +++ b/view.h @@ -1,65 +1,65 @@ /* * Copyright (C) 1995 Paul Olav Tvete * Copyright (C) 2000-2008 Stephan Kulow * Copyright (C) 2009 Parker Coates * * License of original code: * ------------------------------------------------------------------------- * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, * provided that the above copyright notice appear in all copies and that * both that copyright notice and this permission notice appear in * supporting documentation. * * This file is provided AS IS with no warranties of any kind. The author * shall have no liability with respect to the infringement of copyrights, * trade secrets or any patents by this file or any part thereof. In no * event will the author be liable for any lost revenue or profits or * other special, indirect and consequential damages. * ------------------------------------------------------------------------- * * License of modifications/additions made after 2009-01-01: * ------------------------------------------------------------------------- * 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, see . * ------------------------------------------------------------------------- */ #ifndef VIEW_H #define VIEW_H #include #include class PatienceView: public QGraphicsView, public KGameRendererClient { public: explicit PatienceView ( QWidget * parent ); virtual ~PatienceView(); void setScene( QGraphicsScene * scene ); protected: - void resizeEvent( QResizeEvent * e ) Q_DECL_OVERRIDE; - void drawBackground( QPainter * painter, const QRectF & rect ) Q_DECL_OVERRIDE; - void receivePixmap( const QPixmap & pixmap ) Q_DECL_OVERRIDE; + void resizeEvent( QResizeEvent * e ) override; + void drawBackground( QPainter * painter, const QRectF & rect ) override; + void receivePixmap( const QPixmap & pixmap ) override; private: void updateSceneSize(); QPixmap m_background; }; #endif diff --git a/yukon.cpp b/yukon.cpp index 55e0db1..2d3f442 100644 --- a/yukon.cpp +++ b/yukon.cpp @@ -1,142 +1,142 @@ /* * Copyright (C) 2000-2009 Stephan Kulow * Copyright (C) 2010 Parker Coates * * License of original code: * ------------------------------------------------------------------------- * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, * provided that the above copyright notice appear in all copies and that * both that copyright notice and this permission notice appear in * supporting documentation. * * This file is provided AS IS with no warranties of any kind. The author * shall have no liability with respect to the infringement of copyrights, * trade secrets or any patents by this file or any part thereof. In no * event will the author be liable for any lost revenue or profits or * other special, indirect and consequential damages. * ------------------------------------------------------------------------- * * License of modifications/additions made after 2009-01-01: * ------------------------------------------------------------------------- * 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, see . * ------------------------------------------------------------------------- */ #include "yukon.h" #include "dealerinfo.h" #include "pileutils.h" #include "patsolve/yukonsolver.h" #include Yukon::Yukon( const DealerInfo * di ) : DealerScene( di ) { } void Yukon::initialize() { const qreal dist_x = 1.11; const qreal dist_y = 1.11; setDeckContents(); for ( int i = 0; i < 4; ++i ) { target[i] = new PatPile( this, i + 1, QStringLiteral("target%1").arg(i) ); target[i]->setPileRole(PatPile::Foundation); target[i]->setLayoutPos(0.11+7*dist_x, dist_y *i); target[i]->setKeyboardSelectHint( KCardPile::NeverFocus ); target[i]->setKeyboardDropHint( KCardPile::ForceFocusTop ); } for ( int i = 0; i < 7; ++i ) { store[i] = new PatPile( this, 5 + i, QStringLiteral("store%1").arg(i) ); store[i]->setPileRole(PatPile::Tableau); store[i]->setLayoutPos(dist_x*i, 0); store[i]->setAutoTurnTop(true); store[i]->setBottomPadding( 3 * dist_y ); store[i]->setHeightPolicy( KCardPile::GrowDown ); store[i]->setKeyboardSelectHint( KCardPile::FreeFocus ); store[i]->setKeyboardDropHint( KCardPile::AutoFocusTop ); } setActions(DealerScene::Hint | DealerScene::Demo); setSolver( new YukonSolver( this ) ); setNeededFutureMoves( 10 ); // it's a bit hard to judge as there are so many nonsense moves } bool Yukon::checkAdd(const PatPile * pile, const QList & oldCards, const QList & newCards) const { if (pile->pileRole() == PatPile::Tableau) { if (oldCards.isEmpty()) return newCards.first()->rank() == KCardDeck::King; else return newCards.first()->rank() == oldCards.last()->rank() - 1 && newCards.first()->color() != oldCards.last()->color(); } else { return checkAddSameSuitAscendingFromAce(oldCards, newCards); } } bool Yukon::checkRemove(const PatPile * pile, const QList & cards) const { return pile->pileRole() == PatPile::Tableau && cards.first()->isFaceUp(); } void Yukon::restart( const QList & cards ) { QList cardList = cards; for ( int round = 0; round < 11; ++round ) { for ( int j = 0; j < 7; ++j ) { if ( ( j == 0 && round == 0 ) || ( j && round < j + 5 ) ) { QPointF initPos = store[j]->pos(); initPos.ry() += ((7 - j / 3.0) + round) * deck()->cardHeight(); addCardForDeal( store[j], cardList.takeLast(), (round >= j || j == 0), initPos ); } } } startDealAnimation(); } static class YukonDealerInfo : public DealerInfo { public: YukonDealerInfo() : DealerInfo(I18N_NOOP("Yukon"), YukonId ) {} - DealerScene *createGame() const Q_DECL_OVERRIDE + DealerScene *createGame() const override { return new Yukon( this ); } } yukonDealerInfo; diff --git a/yukon.h b/yukon.h index 3708339..5d96d66 100644 --- a/yukon.h +++ b/yukon.h @@ -1,64 +1,64 @@ /* * Copyright (C) 2000-2009 Stephan Kulow * * License of original code: * ------------------------------------------------------------------------- * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, * provided that the above copyright notice appear in all copies and that * both that copyright notice and this permission notice appear in * supporting documentation. * * This file is provided AS IS with no warranties of any kind. The author * shall have no liability with respect to the infringement of copyrights, * trade secrets or any patents by this file or any part thereof. In no * event will the author be liable for any lost revenue or profits or * other special, indirect and consequential damages. * ------------------------------------------------------------------------- * * License of modifications/additions made after 2009-01-01: * ------------------------------------------------------------------------- * 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, see . * ------------------------------------------------------------------------- */ #ifndef YUKON_H #define YUKON_H #include "dealer.h" class Yukon : public DealerScene { friend class YukonSolver; Q_OBJECT public: explicit Yukon( const DealerInfo * di ); - void initialize() Q_DECL_OVERRIDE; + void initialize() override; public slots: - void restart( const QList & cards ) Q_DECL_OVERRIDE; + void restart( const QList & cards ) override; protected: - bool checkAdd(const PatPile * pile, const QList & oldCards, const QList & newCards) const Q_DECL_OVERRIDE; - bool checkRemove(const PatPile * pile, const QList & cards) const Q_DECL_OVERRIDE; + bool checkAdd(const PatPile * pile, const QList & oldCards, const QList & newCards) const override; + bool checkRemove(const PatPile * pile, const QList & cards) const override; private: PatPile* store[7]; PatPile* target[4]; }; #endif