diff --git a/qml/Main.qml b/qml/Main.qml index f89df78..99e4d7a 100644 --- a/qml/Main.qml +++ b/qml/Main.qml @@ -62,6 +62,7 @@ ApplicationWindow { id: scoreBar moves: GameState.moveAmount + score: GameState.score time: 0 height: Math.max(parent.height * 0.08, 50) diff --git a/src/gamestate.cpp b/src/gamestate.cpp index 2f5cd79..0eac776 100644 --- a/src/gamestate.cpp +++ b/src/gamestate.cpp @@ -59,6 +59,7 @@ void GameState::dealCards() { emit columnsChanged(); emit foundationChanged(); emit moveAmountChanged(); + emit scoreChanged(); } void GameState::setupWinningDeck() { @@ -102,6 +103,7 @@ void GameState::setupWinningDeck() { emit columnsChanged(); emit foundationChanged(); emit moveAmountChanged(); + emit scoreChanged(); } bool GameState::drawNextCard() { @@ -153,6 +155,7 @@ bool GameState::moveThrownCardToColumn(int columnId) { qDebug() << "> Moving complete"; incrementMoveAmt(); + increaseScore(5); // Score increase for moving to column emit throwawayPileChanged(); emit columnsChanged(); return true; @@ -183,6 +186,7 @@ bool GameState::moveThrownCardToFoundation(int foundationId) { qDebug() << "> Moving complete"; incrementMoveAmt(); + increaseScore(10); // Score increase for moving to foundation emit throwawayPileChanged(); emit foundationChanged(); return true; @@ -263,6 +267,7 @@ bool GameState::moveColumnCardToFoundation(int columnId, int foundationId) { ensureColumnRevealed(columnId); qDebug() << "> Moving complete"; + increaseScore(10); // Score increase for moving to foundation incrementMoveAmt(); emit columnsChanged(); emit foundationChanged(); @@ -293,8 +298,14 @@ bool GameState::autoMoveThrownCard() { emit throwawayPileChanged(); switch (changed.value().destinationType) { - case AutoMoveResult::DestinationType::Foundation: emit foundationChanged(); break; - case AutoMoveResult::DestinationType::Column: emit columnsChanged(); break; + case AutoMoveResult::DestinationType::Foundation: + increaseScore(10); // Score increase for moving to foundation + emit foundationChanged(); + break; + case AutoMoveResult::DestinationType::Column: + increaseScore(5); // Score increase for moving to column + emit columnsChanged(); + break; default: assert(false); break; } incrementMoveAmt(); @@ -337,6 +348,7 @@ bool GameState::autoMoveColumnCard(int columnId, int cardIndex) { // that's all, if it's to a foundation, also emit foundation change emit columnsChanged(); if (changed.value().destinationType == AutoMoveResult::DestinationType::Foundation) { + increaseScore(10); // Score increase for moving to foundation emit foundationChanged(); } @@ -418,6 +430,7 @@ GameState* GameState::clone(bool enableWinnabilitySim) const { newGameState->m_gameWon = m_gameWon; newGameState->m_prelimWin = m_prelimWin; + newGameState->m_score = m_score; assert(this->generateStateHash() == newGameState->generateStateHash()); return newGameState; @@ -455,6 +468,7 @@ void GameState::cleanupBoard(bool emitChanges) { } m_moveAmt = 0; + m_score = 0; // Note that we don't need to reset gameWon/prelimWin from here, as it's // auto-checked from onFoundationChanged, which the emits trigger. Similarly @@ -562,7 +576,7 @@ std::optional GameState::tryAutoMoveMultipleCards(con m_columns[columnId].append(col); qDebug() << "* Auto-moved card " << card->toString() << " to column " << columnId; } - return true; + return AutoMoveResult{AutoMoveResult::DestinationType::Column, columnId}; } } @@ -637,6 +651,7 @@ void GameState::ensureColumnRevealed(int columnId) { // First slot in the column must always be revealed, reveal it col->reveal(); + increaseScore(5); // Score increase for revealing a card qDebug() << "Revealed card " << col->card()->toString() << " in column " << columnId; } @@ -645,6 +660,11 @@ void GameState::incrementMoveAmt() { emit moveAmountChanged(); } +void GameState::increaseScore(int amount) { + m_score += amount; + emit scoreChanged(); +} + bool GameState::prelimWinCheck() { // Check if the game is preliminarily won: // This occurs when all cards in the tableau are revealed. @@ -906,6 +926,10 @@ QVariant GameState::isWinnable() const { return map; } +int GameState::score() const { + return m_score; +} + std::pair, int> GameState::checkWinnable() { if (!m_enableWinnabilitySim) return {std::nullopt, 0}; diff --git a/src/gamestate.h b/src/gamestate.h index ba0f3d3..5b0508a 100644 --- a/src/gamestate.h +++ b/src/gamestate.h @@ -27,6 +27,7 @@ class GameState : public QObject { Q_PROPERTY(bool gameWon READ gameWon NOTIFY gameWonChanged) Q_PROPERTY(bool preliminaryWin READ preliminaryWin NOTIFY preliminaryWinChanged) Q_PROPERTY(QVariant isWinnable READ isWinnable NOTIFY isWinnableChanged) + Q_PROPERTY(int score READ score NOTIFY scoreChanged) public: explicit GameState(QObject* parent = nullptr, bool preDealCards = true, bool enableWinnabilitySim = true); @@ -41,6 +42,7 @@ class GameState : public QObject { bool preliminaryWin() const; bool gameWon() const; QVariant isWinnable() const; + int score() const; // General functions Q_INVOKABLE void dealCards(); @@ -66,6 +68,7 @@ class GameState : public QObject { void gameWonChanged(); void preliminaryWinChanged(); void isWinnableChanged(); + void scoreChanged(); private slots: void onFoundationChanged(); @@ -82,6 +85,7 @@ class GameState : public QObject { bool m_prelimWin; std::pair, int> m_isWinnable; bool m_enableWinnabilitySim; + int m_score; struct AutoMoveResult { enum class DestinationType { @@ -104,6 +108,7 @@ class GameState : public QObject { void ensureColumnRevealed(int columnId); void incrementMoveAmt(); + void increaseScore(int amount); bool winCheck(); bool prelimWinCheck();