diff --git a/package-lock.json b/package-lock.json index c571663..7f31c90 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "vue-nonograms-solid", - "version": "1.15.0", + "version": "1.15.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "vue-nonograms-solid", - "version": "1.15.0", + "version": "1.15.1", "dependencies": { "@capacitor/android": "^8.1.0", "@capacitor/cli": "^8.1.0", diff --git a/package.json b/package.json index 4bb4613..d31236d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vue-nonograms-solid", - "version": "1.15.0", + "version": "1.15.1", "homepage": "https://nonograms.7u.pl/", "type": "module", "scripts": { diff --git a/src/composables/useSolver.js b/src/composables/useSolver.js index cb5a6c1..7851acb 100644 --- a/src/composables/useSolver.js +++ b/src/composables/useSolver.js @@ -1,4 +1,4 @@ -import { ref, computed, onUnmounted } from 'vue'; +import { ref, computed, onUnmounted, watch } from 'vue'; import { usePuzzleStore } from '@/stores/puzzle'; import { useI18n } from '@/composables/useI18n'; @@ -18,6 +18,24 @@ export function useSolver() { let worker = null; let requestId = 0; + // Reset solver state when game resets or changes + watch(() => store.currentLevelId, () => { + resetSolverState(); + }); + + watch(() => store.moves, (newVal) => { + if (newVal === 0) { + resetSolverState(); + } + }); + + function resetSolverState() { + pause(); + isStuck.value = false; + statusText.value = t('guide.waiting'); + isProcessing.value = false; + } + function step() { if (store.isGameWon) { pause(); diff --git a/src/stores/puzzle.js b/src/stores/puzzle.js index f518186..e075e3a 100644 --- a/src/stores/puzzle.js +++ b/src/stores/puzzle.js @@ -432,6 +432,9 @@ export const usePuzzleStore = defineStore('puzzle', () => { guideUsageCount, currentDensity, markGuideUsed, + markBoostUsed, + hasUsedBoost, + boostUsageCount, startInteraction, endInteraction, completedRows, diff --git a/src/utils/solver.js b/src/utils/solver.js index 1e04010..9d8bf45 100644 --- a/src/utils/solver.js +++ b/src/utils/solver.js @@ -446,6 +446,7 @@ export function solvePuzzle(rowHints, colHints, onProgress, initialGrid = null, lookaheadUsed: maxDepth > 0, iterations, maxDepth, - backtracks + backtracks, + solution: grid }; } diff --git a/src/workers/solverWorker.js b/src/workers/solverWorker.js index 92b079f..454e1ed 100644 --- a/src/workers/solverWorker.js +++ b/src/workers/solverWorker.js @@ -1,5 +1,5 @@ import { calculateHints } from '../utils/puzzleUtils.js'; -import { solveLine } from '../utils/solver.js'; +import { solveLine, solvePuzzle } from '../utils/solver.js'; const messages = { pl: { @@ -140,7 +140,54 @@ const handleStep = (playerGrid, solution, locale) => { const handleBoost = (playerGrid, solution, locale) => { const size = solution.length; - // Find first unknown cell and reveal it + + // 1. Try to use the Solver (DFS) to find a logical move + try { + const { rowHints, colHints } = calculateHints(solution); + + // Map Store format (0=Unk, 1=Fill, 2=Cross) to Solver format (-1=Unk, 1=Fill, 0=Empty) + const solverGrid = playerGrid.map(row => row.map(cell => { + if (cell === 0) return -1; + if (cell === 1) return 1; + if (cell === 2) return 0; + return -1; + })); + + // Run full solver (logicOnly=false allows DFS/guessing) + // We pass solverGrid as initial state to respect user's moves + const result = solvePuzzle(rowHints, colHints, null, solverGrid, false); + + if (result && result.solution) { + const solvedGrid = result.solution; + + // Find the first cell that is Unknown in playerGrid but Known in solvedGrid + for (let r = 0; r < size; r++) { + for (let c = 0; c < size; c++) { + if (playerGrid[r][c] === 0) { // Unknown in Player + const solvedVal = solvedGrid[r][c]; // -1=Unk, 0=Empty, 1=Filled + + if (solvedVal !== -1) { + // Found a logical deduction! + const newState = solvedVal === 1 ? 1 : 2; // 1->Filled, 0->Cross + const stateLabel = t(locale, newState === 1 ? 'worker.state.filled' : 'worker.state.empty'); + return { + type: 'move', + r, + c, + state: newState, + statusText: t(locale, 'worker.boosted', { row: r + 1, col: c + 1, state: stateLabel }) + }; + } + } + } + } + } + } catch (e) { + console.warn('Boost Solver failed, falling back to simple reveal:', e); + } + + // 2. Fallback: If solver failed (e.g. contradiction due to user error), + // or no new info found, use the "Cheat" method (reveal from true solution). for (let r = 0; r < size; r++) { for (let c = 0; c < size; c++) { if (playerGrid[r][c] === 0) {