diff --git a/lib/game/engine/game_engine.dart b/lib/game/engine/game_engine.dart index 109cf2d..1427f92 100644 --- a/lib/game/engine/game_engine.dart +++ b/lib/game/engine/game_engine.dart @@ -227,4 +227,13 @@ class GameEngine { _checkStuck(); return true; } + + /// Booster: re-deals the tray. No move/score effect. Re-checks stuck so a + /// dead board with a hopeless tray can become playable again. + bool useShuffle() { + if (_phase == GamePhase.won || _phase == GamePhase.lost) return false; + _tray = _generator.nextTray(_grid); + _checkStuck(); + return true; + } } diff --git a/test/game/engine/booster_test.dart b/test/game/engine/booster_test.dart index 2ab2804..a20c2b1 100644 --- a/test/game/engine/booster_test.dart +++ b/test/game/engine/booster_test.dart @@ -46,4 +46,24 @@ void main() { e.declineAndLose(); expect(e.useHammer(0, 0), isFalse); }); + + test('useShuffle replaces the tray without spending a move or scoring', () { + final e = GameEngine(_stage()); + final before = List.of(e.tray); + final score0 = e.score; + final moves0 = e.movesUsed; + + final ok = e.useShuffle(); + + expect(ok, isTrue); + expect(e.tray.length, before.length); + expect(e.score, score0); + expect(e.movesUsed, moves0); + }); + + test('useShuffle is rejected after the attempt finishes', () { + final e = GameEngine(_stage()); + e.declineAndLose(); + expect(e.useShuffle(), isFalse); + }); }