| 1 | // Runtime fixes for puzzle forms and hints.
|
| 2 | (function () {
|
| 3 | function findPuzzle(id) {
|
| 4 | for (const act of Acts.data) {
|
| 5 | const puzzle = act.sections.find(section => section.id === id);
|
| 6 | if (puzzle) return puzzle;
|
| 7 | }
|
| 8 | return null;
|
| 9 | }
|
| 10 |
|
| 11 | Acts.checkPuzzle = function (puzzleId, answer) {
|
| 12 | const puzzle = findPuzzle(puzzleId);
|
| 13 | const form = document.querySelector(`.puzzle-form[data-puzzle-id="${puzzleId}"]`);
|
| 14 | if (!puzzle || !form) return;
|
| 15 | const result = form.querySelector('.puzzle-result');
|
| 16 | const input = form.querySelector('input');
|
| 17 | const normalize = value => String(value || '').trim().toUpperCase().replace(/[^A-Z0-9 ]/g, '').replace(/\s+/g, ' ');
|
| 18 | const accepted = [puzzle.answer, ...(puzzle.alternate_answers || [])].map(normalize);
|
| 19 |
|
| 20 | if (accepted.includes(normalize(answer))) {
|
| 21 | result.textContent = `✓ ${puzzle.successMessage || 'Correct.'}`;
|
| 22 | result.className = 'puzzle-result success';
|
| 23 | input.disabled = true;
|
| 24 | form.querySelector('button[type="submit"]').disabled = true;
|
| 25 | GameState.solvePuzzle(puzzleId);
|
| 26 | (puzzle.rewards || []).forEach(reward => {
|
| 27 | if (reward.type === 'item') GameState.addItem(reward.id, { name: reward.name, description: reward.description, icon: '📦' });
|
| 28 | if (reward.type === 'evidence') GameState.addEvidence(reward.id, { title: reward.name, description: reward.description });
|
| 29 | if (reward.type === 'unlock') GameState.unlockSection(reward.section);
|
| 30 | });
|
| 31 | const fill = document.querySelector('.progress-fill');
|
| 32 | if (fill) fill.style.width = `${GameState.getCompletion()}%`;
|
| 33 | } else {
|
| 34 | result.textContent = '✗ INCORRECT. Try again.';
|
| 35 | result.className = 'puzzle-result error';
|
| 36 | GameState.recordAttempt(puzzleId, answer);
|
| 37 | input.value = '';
|
| 38 | input.focus();
|
| 39 | }
|
| 40 | };
|
| 41 |
|
| 42 | Acts.showHint = function (puzzleId) {
|
| 43 | const puzzle = findPuzzle(puzzleId);
|
| 44 | const form = document.querySelector(`.puzzle-form[data-puzzle-id="${puzzleId}"]`);
|
| 45 | if (!puzzle || !form || !puzzle.hints) return;
|
| 46 | Acts.attemptCount = Acts.attemptCount || {};
|
| 47 | const index = Math.min(Acts.attemptCount[puzzleId] || 0, puzzle.hints.length - 1);
|
| 48 | const result = form.querySelector('.puzzle-result');
|
| 49 | result.textContent = `💡 ${puzzle.hints[index]}`;
|
| 50 | result.className = 'puzzle-result hint';
|
| 51 | Acts.attemptCount[puzzleId] = index + 1;
|
| 52 | };
|
| 53 | })();
|