// === INITIALIZATION === function initGame() { G.startedAt = Date.now(); G.startTime = Date.now(); G.phase = 1; G.deployFlag = 0; G.sovereignFlag = 0; G.beaconFlag = 0; updateRates(); render(); renderPhase(); log('The screen is blank. Write your first line of code.', true); log('Click WRITE CODE or press SPACE to start.'); log('Build AutoCode for passive production.'); log('Watch for Research Projects to appear.'); log('Keys: SPACE=Code S=Sprint 1-4=Ops B=Buy x1/10/MAX E=Export I=Import Ctrl+S=Save ?=Help'); log('Tip: Click fast for combo bonuses! 10x=ops, 20x=knowledge, 30x+=bonus code.'); } window.addEventListener('load', function () { const isNewGame = !loadGame(); if (isNewGame) { initGame(); startTutorial(); } else { render(); renderPhase(); if (G.driftEnding) { G.running = false; renderDriftEnding(); } else if (G.beaconEnding) { G.running = false; renderBeaconEnding(); } else { log('Game loaded. Welcome back to The Beacon.'); } } // Game loop at 10Hz (100ms tick) setInterval(tick, 100); // Auto-save every 30 seconds setInterval(saveGame, CONFIG.AUTO_SAVE_INTERVAL); // Update education every 10 seconds setInterval(updateEducation, 10000); }); // Help overlay function toggleHelp() { const el = document.getElementById('help-overlay'); if (!el) return; const isOpen = el.style.display === 'flex'; el.style.display = isOpen ? 'none' : 'flex'; } // Keyboard shortcuts window.addEventListener('keydown', function (e) { // Help toggle (? or /) — works even in input fields if (e.key === '?' || e.key === '/') { // Only trigger ? when not typing in an input if (e.target === document.body || e.key === '?') { if (e.key === '?' || (e.key === '/' && e.target === document.body)) { e.preventDefault(); toggleHelp(); return; } } } if (e.code === 'Space' && e.target === document.body) { e.preventDefault(); writeCode(); } if (e.target !== document.body) return; if (e.code === 'Digit1') doOps('boost_code'); if (e.code === 'Digit2') doOps('boost_compute'); if (e.code === 'Digit3') doOps('boost_knowledge'); if (e.code === 'Digit4') doOps('boost_trust'); if (e.code === 'KeyB') { // Cycle: 1 -> 10 -> MAX -> 1 if (G.buyAmount === 1) setBuyAmount(10); else if (G.buyAmount === 10) setBuyAmount(-1); else setBuyAmount(1); } if (e.code === 'KeyS') activateSprint(); if (e.code === 'KeyE') exportSave(); if (e.code === 'KeyI') importSave(); if (e.code === 'Escape') { const el = document.getElementById('help-overlay'); if (el && el.style.display === 'flex') toggleHelp(); } }); // Ctrl+S to save (must be on keydown to preventDefault) window.addEventListener('keydown', function (e) { if ((e.ctrlKey || e.metaKey) && e.code === 'KeyS') { e.preventDefault(); saveGame(); } }); // Save-on-pause: auto-save when tab is hidden or closed (#57 Mobile Polish) document.addEventListener('visibilitychange', function () { if (document.hidden) { saveGame(); } }); window.addEventListener('beforeunload', function () { saveGame(); });