From a52681c0b3ed540e61c997a121dd1c821827cad9 Mon Sep 17 00:00:00 2001 From: ItsDrike Date: Thu, 12 Dec 2024 20:45:34 +0100 Subject: [PATCH] Make automove return what changed This allows us to optimize the emitted signals, as we will know what has changed after an automove. --- src/gamestate.cpp | 39 +++++++++++++++++++++------------------ src/gamestate.h | 13 +++++++++++-- 2 files changed, 32 insertions(+), 20 deletions(-) diff --git a/src/gamestate.cpp b/src/gamestate.cpp index f00427a..2f5cd79 100644 --- a/src/gamestate.cpp +++ b/src/gamestate.cpp @@ -280,7 +280,8 @@ bool GameState::autoMoveThrownCard() { qDebug() << "Attempting auto-move of thrown card " << cardToMove->toString(); // Try moving the card into the foundation - if (!tryAutoMoveSingleCard(*cardToMove)) { + auto changed = tryAutoMoveSingleCard(*cardToMove); + if (!changed.has_value()) { qDebug() << "> Moving failed, no available move found"; return false; } @@ -291,11 +292,11 @@ bool GameState::autoMoveThrownCard() { emit throwawayPileChanged(); - // We don't know which pile the card was moved to, to be safe, emit - // a change from both - // NOTE: consider returning what changed from tryAutoMoveSingleCard - emit columnsChanged(); - emit foundationChanged(); + switch (changed.value().destinationType) { + case AutoMoveResult::DestinationType::Foundation: emit foundationChanged(); break; + case AutoMoveResult::DestinationType::Column: emit columnsChanged(); break; + default: assert(false); break; + } incrementMoveAmt(); return true; @@ -320,7 +321,8 @@ bool GameState::autoMoveColumnCard(int columnId, int cardIndex) { // This is a single card move (last card) PlayingCard* cardToMove = col->card(); qDebug() << "Attempting auto-move of column " << columnId << " card " << cardToMove->toString(); - if (!tryAutoMoveSingleCard(*cardToMove, columnId)) { + auto changed = tryAutoMoveSingleCard(*cardToMove, columnId); + if (!changed.has_value()) { qDebug() << "> Moving failed, no available move found"; return false; } @@ -331,12 +333,13 @@ bool GameState::autoMoveColumnCard(int columnId, int cardIndex) { ensureColumnRevealed(columnId); qDebug() << "> Moving complete"; + // Columns always change, we're moving from them, if the move is to another column + // that's all, if it's to a foundation, also emit foundation change emit columnsChanged(); + if (changed.value().destinationType == AutoMoveResult::DestinationType::Foundation) { + emit foundationChanged(); + } - // we don't know where the card was moved, it could've been the foundation too - // to be safe, emit a change signal for it too - // NOTE: consider returning what changed from tryAutoMoveSingleCard - emit foundationChanged(); incrementMoveAmt(); return true; @@ -350,7 +353,7 @@ bool GameState::autoMoveColumnCard(int columnId, int cardIndex) { selectedCards.append(curCol->card()); } - if (!tryAutoMoveMultipleCards(selectedCards, columnId)) { + if (!tryAutoMoveMultipleCards(selectedCards, columnId).has_value()) { qDebug() << "> Moving failed, no available move found"; return false; } @@ -512,13 +515,13 @@ QString GameState::generateStateHash() const { return stateHash; } -bool GameState::tryAutoMoveSingleCard(PlayingCard& cardToMove, int skipColumnId) { +std::optional GameState::tryAutoMoveSingleCard(PlayingCard& cardToMove, int skipColumnId) { // 1. Try moving the card to the foundation const int foundationId = static_cast(cardToMove.suit()); if (isFoundationMoveValid(cardToMove, foundationId)) { m_foundation[foundationId].prepend(&cardToMove); qDebug() << "* Auto-moved card " << cardToMove.toString() << " to foundation " << foundationId; - return true; + return AutoMoveResult{AutoMoveResult::DestinationType::Foundation, foundationId}; } // 2. Try moving the card to another column @@ -530,16 +533,16 @@ bool GameState::tryAutoMoveSingleCard(PlayingCard& cardToMove, int skipColumnId) ColumnSlot* col = new ColumnSlot(&cardToMove, true, this); m_columns[columnId].append(col); qDebug() << "* Auto-moved card " << cardToMove.toString() << " to column " << columnId; - return true; + return AutoMoveResult{AutoMoveResult::DestinationType::Column, columnId}; } } // No available auto-move qDebug() << "* Auto-move failed, no available moves"; - return false; + return std::nullopt; } -bool GameState::tryAutoMoveMultipleCards(const QList& cards, int skipColumnId) { +std::optional GameState::tryAutoMoveMultipleCards(const QList& cards, int skipColumnId) { assert(cards.size() > 1); // If we can move the first (selected) card to another column, @@ -564,7 +567,7 @@ bool GameState::tryAutoMoveMultipleCards(const QList& cards, int s } qDebug() << "* Auto-move failed, no available moves"; - return false; + return std::nullopt; } bool GameState::isFoundationMoveValid(const PlayingCard& cardToMove, int foundationId) const { diff --git a/src/gamestate.h b/src/gamestate.h index a27e5ad..ba0f3d3 100644 --- a/src/gamestate.h +++ b/src/gamestate.h @@ -83,12 +83,21 @@ class GameState : public QObject { std::pair, int> m_isWinnable; bool m_enableWinnabilitySim; + struct AutoMoveResult { + enum class DestinationType { + Foundation, + Column + }; + DestinationType destinationType; + int destinationId; + }; + GameState* clone(bool enableWinnabilitySim = false) const; void cleanupBoard(bool emitChanges); QString generateStateHash() const; - bool tryAutoMoveSingleCard(PlayingCard& cardToMove, int skipColumnId = -1); - bool tryAutoMoveMultipleCards(const QList& cards, int skipColumnId); + std::optional tryAutoMoveSingleCard(PlayingCard& cardToMove, int skipColumnId = -1); + std::optional tryAutoMoveMultipleCards(const QList& cards, int skipColumnId); bool isFoundationMoveValid(const PlayingCard& cardToMove, int foundationId) const; bool isColumnMoveValid(const PlayingCard& cardToMove, int columnId) const;