diff --git a/README.md b/README.md index b01d32d..8f64af7 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ > **"मोक्ष प्राप्ति का एकमात्र मार्ग — त्याग।"** > *The only path to liberation — is let it go.* -An HTML5 browser game rooted in **Sanatan Shastra** and **Karmic Philosophy**. +An HTML5 browser game rooted in **Sanatan shaashtra** and **Karmic Philosophy**. Control your chariot through the cosmic field, master your senses, burn your karma, and attain **Moksha**. 🎮 **[Play on itch.io](https://weirdcodes.itch.io/moksha)** | @@ -51,11 +51,11 @@ The game is built on **Katha Upanishad's chariot metaphor** (Nachiketopakhyana): | Naam Samarpana | `W`, `↑` | RB (5) | Only in final phase (samaya < 100) | | Pralaya (Sacrifice) | `Q` | LB (4) | Voluntary chariot dissolution | | Pure Rebirth | `R` | LT (6) | Zero karma → new life | -| Shastra (Knowledge) | `ESC` | BACK (8) | Open wisdom scroll | +| shaashtra (Knowledge) | `ESC` | BACK (8) | Open wisdom scroll | | Pause | `F` | START (9) | Stillness | | Shankha (Conch) | `Y` | Y (0) | Dispel chakravaata (यंत्र-मार्ग, when Naam unavailable) | | Jyoti (Lamp) | `B` | B (1) | Restore vision in bad-karma darkness | -| Shastra Scroll | `↑` / `↓` (hold) | DPAD U/D | Navigate wisdom text | +| shaashtra Scroll | `↑` / `↓` (hold) | DPAD U/D | Navigate wisdom text | --- @@ -69,7 +69,7 @@ The game is built on **Katha Upanishad's chariot metaphor** (Nachiketopakhyana): - 🏆 **Three End States** — Moksha (liberation), Pralaya (dissolution), Punarjanma (rebirth) - 🎮 **Full Gamepad Support** — Xbox/generic controller with deadzone handling - ⚡ **60fps Performance** — Pool-based architecture (no GC pressure), sprite caching, emoji sprite cache, gradient buckets -- 📜 **In-Game Shastra** — Full philosophical treatise accessible via ESC +- 📜 **In-Game shaashtra** — Full philosophical treatise accessible via ESC - 🔔 **Canvas Alert Queue** — Contextual slide-in alert cards (top-right), category-colored, auto-dismiss; de-duplicated (no per-second flood) - ⚖️ **Prarabdha Bhog System** — Endure past karma over time; unit-break explosion; MAX 15 cap; samaya penalty ×1.15 - 🧘 **Chetanaa Immunity** — चेतना-जागृति grants karma immunity (गीता 4.37 — ज्ञानाग्निः सर्वकर्माणि भस्मसात्) @@ -155,7 +155,7 @@ MOKSHA/ ├── audio.js — AudioManager: 28-mp3 preload, ambient layers, duck system ├── engine.js — KarmaEngine: slim orchestrator, core loop, pools, state transitions ├── i18n.js — भाषा-प्रबंधक: 134 keys (hi/en), persistence, late-binding resolveAlert - ├── shastra.js — शास्त्र-ग्रंथ: 3 pages, संरचित blocks, श्लोक-कोश (भाषा-निरपेक्ष) + ├── shaashtra.js — शास्त्र-ग्रंथ: 3 pages, संरचित blocks, श्लोक-कोश (भाषा-निरपेक्ष) ├── karma.js — KarmaMixin: Vedic logic, maya spawn, kripa, keyboard actions ├── physics.js — PhysicsMixin: glow-rings, particles, floating text, pool helpers ├── state.js — StateMixin: HUD updates, alert queue, triggerAlert, animations @@ -376,7 +376,7 @@ getEmojiSprite(emoji, fontSize) // orbit/innerOrbit emoji cache (नई) | ज्योति | B | B (1) | पाप-अंधकार में दृष्टि | | शास्त्र-नेविगेशन | ↑↓ (held) | DPAD U/D (12/13) | scroll; DPAD = PageUp/Down | -> ⚠️ `handleShastraGamepadNav()` अब `pollGamepadOnStartScreen()` से भी कॉल होता है। +> ⚠️ `handleshaashtraGamepadNav()` अब `pollGamepadOnStartScreen()` से भी कॉल होता है। --- @@ -404,7 +404,7 @@ RUNNING_HORSES_DUCK_REDUCTION = 0.15 ### 4.3 गेटिंग ```js // AudioManager internal — game state getter से poll -isGameStarted && !gameOver && !won && !isPaused && !isShastraVisible +isGameStarted && !gameOver && !won && !isPaused && !isshaashtraVisible // setTargetAtTime() से smooth fade — कोई click/pop नहीं ``` @@ -429,7 +429,7 @@ Deferred load (6): bgMusic, chetanaJaagrita, pralaya, jaagritaSwaansa, ### 4.6 AudioManager dependency injection (main.js में) ```js Audio.setGameStateGetter(() => ({ isGameStarted, gameOver, won, - isPaused, isShastraVisible, chetanaaJaagrita })); + isPaused, isshaashtraVisible, chetanaaJaagrita })); Audio.setVibrateCallback(vibrateGamepad); Audio.setReadinessGetters({ getFontsReady: () => isFontsReady, getScaleGameDone: () => isScaleGameDone }); @@ -562,7 +562,7 @@ AM.updateAmbientVolumes(); | ~220 | `setCallbacks()`, `setUI()` | | ~240 | `init()` — pool + stars initialization | | ~280 | `update(dt, keys, frameNow)` — मुख्य game logic tick | -| ~730 | `toggleShastra()` | +| ~730 | `toggleshaashtra()` | | ~760 | `showEndScreen(reason)` | | ~830 | `reset()` — punahaPrarambha | | ~930 | `getState()` — renderer snapshot | @@ -647,7 +647,7 @@ AM.updateAmbientVolumes(); | ~44 | UI DOM references | | ~100 | Event listeners (keyboard, gamepad, buttons, wheel) | | ~200 | Gamepad module (pollGamepad, vibrateGamepad) | -| ~300 | `toggleShastra()`, `updateShastraPage()` | +| ~300 | `toggleshaashtra()`, `updateshaashtraPage()` | | ~360 | `draw()` — engine state + Renderer calls | | ~430 | `gameLoop()` — RAF loop | | ~470 | `scaleGame()`, `debounce()` | diff --git a/scripts/scripts_replace-nonenglish.js b/scripts/scripts_replace-nonenglish.js deleted file mode 100644 index 7dd5ca6..0000000 --- a/scripts/scripts_replace-nonenglish.js +++ /dev/null @@ -1,193 +0,0 @@ -#!/usr/bin/env node -/** - * replace-nonenglish.js - * - * Usage: - * node scripts/replace-nonenglish.js # dry-run, lists candidate files and sample diffs - * node scripts/replace-nonenglish.js --apply # actually write changes - * node scripts/replace-nonenglish.js --apply --commit --branch replace-nonenglish-text --message "Replace non-English tokens" - * node scripts/replace-nonenglish.js --apply --commit --push - * - * Notes: - * - Skips node_modules, .git, dist, build by default. - * - Targets common text file extensions. - * - Removes Unicode diacritics (NFD -> strip combining marks -> NFC). - * - Applies mapping table (customize `mapping` below). - */ - -const fs = require('fs'); -const path = require('path'); -const child = require('child_process'); - -const args = process.argv.slice(2); -const APPLY = args.includes('--apply'); -const COMMIT = args.includes('--commit'); -const PUSH = args.includes('--push'); -const BRANCH = (args.find(a => a.startsWith('--branch=')) || '--branch=replace-nonenglish-text').split('=')[1]; -const MESSAGE = (args.find(a => a.startsWith('--message=')) || '--message=Replace non-English tokens').split('=')[1]; - -const exts = new Set([ - '.js','.jsx','.ts','.tsx','.html','.htm','.css','.scss','.md','.markdown', - '.json','.yml','.yaml','.txt','.vue','.py','.java','.c','.cpp','.h','.cs','.xml','.svg','.html' -]); - -const excludeDirs = new Set(['node_modules', '.git', 'dist', 'build', 'vendor', '.next', 'out']); - -const mapping = { - // Add or edit mappings here. Use exact tokens with diacritics as keys. - 'Name': 'Name', - 'name': 'name' -}; - -function escapeRegExp(s) { - return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); -} - -function isBinaryFile(buf) { - for (let i = 0; i < Math.min(buf.length, 512); i++) { - if (buf[i] === 0) return true; - } - return false; -} - -function walk(dir, cb) { - const entries = fs.readdirSync(dir, { withFileTypes: true }); - for (const ent of entries) { - if (excludeDirs.has(ent.name)) continue; - const full = path.join(dir, ent.name); - if (ent.isDirectory()) walk(full, cb); - else cb(full); - } -} - -function previewDiff(orig, updated) { - const origLines = orig.split(/\r?\n/); - const updLines = updated.split(/\r?\n/); - // find first differing line - let i = 0; - while (i < origLines.length && i < updLines.length && origLines[i] === updLines[i]) i++; - const start = Math.max(0, i - 3); - const end = Math.min(origLines.length, i + 3); - const context = []; - for (let j = start; j < end; j++) { - const o = origLines[j] || ''; - const u = updLines[j] || ''; - if (o === u) context.push(' ' + o); - else { - context.push('- ' + o); - context.push('+ ' + u); - } - } - return context.join('\n'); -} - -const repoRoot = process.cwd(); -const candidates = []; - -walk(repoRoot, (filePath) => { - const ext = path.extname(filePath).toLowerCase(); - if (!exts.has(ext)) return; - try { - const buf = fs.readFileSync(filePath); - if (isBinaryFile(buf)) return; - const content = buf.toString('utf8'); - if (!/[^\x00-\x7F]/.test(content)) return; // no non-ascii -> skip - candidates.push({ filePath, content }); - } catch (err) { - // ignore unreadable files - } -}); - -if (candidates.length === 0) { - console.log('No candidate files with non-ASCII characters found in the scanned paths.'); - process.exit(0); -} - -const changes = []; - -for (const c of candidates) { - let newContent = c.content; - - // First apply explicit mapping on original content - for (const [k,v] of Object.entries(mapping)) { - const re = new RegExp('\\b' + escapeRegExp(k) + '\\b', 'g'); - newContent = newContent.replace(re, v); - } - - // Then remove diacritics - try { - newContent = newContent.normalize('NFD').replace(/\p{M}/gu, '').normalize('NFC'); - } catch (e) { - // Fallback if environment doesn't support \p{M} - newContent = newContent.normalize('NFD').replace(/[\u0300-\u036f]/g, '').normalize('NFC'); - } - - // Apply mapping again in case the normalized form should be mapped (e.g., Name -> Name -> Name) - for (const [k,v] of Object.entries(mapping)) { - const plainKey = k.normalize('NFD').replace(/\p{M}/gu, '').normalize('NFC'); - const re = new RegExp('\\b' + escapeRegExp(plainKey) + '\\b', 'g'); - newContent = newContent.replace(re, v); - } - - if (newContent !== c.content) { - changes.push({ - path: path.relative(repoRoot, c.filePath), - before: c.content, - after: newContent - }); - } -} - -if (changes.length === 0) { - console.log('No replacements would be made after normalization and mapping.'); - process.exit(0); -} - -console.log(`Found ${changes.length} files with changes.\n`); - -for (const ch of changes) { - console.log('===', ch.path); - console.log(previewDiff(ch.before, ch.after)); - console.log('---\n'); -} - -if (!APPLY) { - console.log('Dry-run only. Re-run with --apply to write changes.'); - process.exit(0); -} - -// Write files -for (const ch of changes) { - fs.writeFileSync(path.join(repoRoot, ch.path), ch.after, 'utf8'); -} - -console.log(`Wrote ${changes.length} files.`); - -// Optional git commit -function run(cmd) { - try { - return child.execSync(cmd, { stdio: 'pipe' }).toString().trim(); - } catch (e) { - return null; - } -} - -if (COMMIT) { - // ensure inside git repo - const insideGit = run('git rev-parse --is-inside-work-tree'); - if (!insideGit) { - console.warn('Not inside a git repository; skipping commit.'); - process.exit(0); - } - // create branch - run(`git checkout -b ${BRANCH}`); - run('git add .'); - run(`git commit -m "${MESSAGE.replace(/"/g, '\\"')}"`); - console.log(`Committed changes on branch ${BRANCH}.`); - if (PUSH) { - run(`git push -u origin ${BRANCH}`); - console.log(`Pushed branch ${BRANCH} to origin.`); - } -} - -console.log('Done.'); \ No newline at end of file diff --git a/src/main.js b/src/main.js index 4cab04b..5b01320 100644 --- a/src/main.js +++ b/src/main.js @@ -107,7 +107,7 @@ const touch = new TouchControls(keys); let isFontsReady = false; let isScaleGameDone = false; -// ====================== SHASTRA STATE ====================== +// ====================== SHAASHTRA STATE ====================== let currentShaashtraPage = 1; // 🛠️ key-repeat बिना continuous scroll (dpad-stick जैसी consistency) let shaashtraKeyState = { up: false, down: false }; @@ -229,7 +229,7 @@ function pollGamepad() { handleDiscreteButton(gp, GAMEPAD_BUTTON.BACK, 'Escape'); // शास्त्र } -// ====================== SHASTRA UI ====================== +// ====================== SHAASHTRA UI ====================== function updateShaashtraPage() { const lang = getLang(); @@ -281,7 +281,7 @@ function toggleShaashtra() { } } -// ====================== CONTINUOUS SHASTRA SCROLL ====================== +// ====================== CONTINUOUS SHAASHTRA SCROLL ====================== // ArrowUp/Down को OS key-repeat पर निर्भर न रखकर — held-flag से smooth scroll let _shaashtraScrollRafId = null; function continuousShaashtraScrollLoop() { diff --git a/src/shaashtra.js b/src/shaashtra.js index 5eed493..8c99af7 100644 --- a/src/shaashtra.js +++ b/src/shaashtra.js @@ -19,7 +19,7 @@ * * ── शास्त्रीय नियम ────────────────────────────────────────── * type:'shloka' के blocks दोनों भाषाओं में समान रहते हैं। - * इसलिए वे SHASTRA_SHLOKAS में एक ही बार लिखे जाते हैं और + * इसलिए वे SHAASHTRA_SHLOKAS में एक ही बार लिखे जाते हैं और * दोनों भाषाओं से id द्वारा referenced होते हैं — duplication * नहीं, इसलिए एक जगह सुधारने पर दोनों भाषाओं में सुधरता है। * ============================================================ @@ -27,7 +27,7 @@ // ── श्लोक-कोश — भाषा-निरपेक्ष (नियम E-1) ───────────────────── // अर्थ भाषा के अनुसार बदलता है; मूल पाठ कभी नहीं। -export const SHASTRA_SHLOKAS = { +export const SHAASHTRA_SHLOKAS = { gita437: { text: 'ज्ञानाग्निः सर्वकर्माणि भस्मसात् कुरुते', credit: { hi: 'गीता ४.३७', en: 'Bhagavad Gita 4.37' }, @@ -196,7 +196,7 @@ const PAGE_3 = { // ── सम्पूर्ण ग्रंथ ─────────────────────────────────────────── // ⚠️ PAGE_2, PAGE_3 अगले पैच में जुड़ेंगे। // ⚠️ PAGE_3 अगले पैच में जुड़ेगा। -export const SHASTRA_PAGES = [PAGE_1, PAGE_2, PAGE_3]; +export const SHAASHTRA_PAGES = [PAGE_1, PAGE_2, PAGE_3]; /** * escapeHtml — पाठ को सुरक्षित बनाएँ। @@ -217,8 +217,8 @@ function escapeHtml(s) { * @returns {string} — HTML string */ export function renderShaashtraPage(pageIndex, lang) { - const page = SHASTRA_PAGES[pageIndex]?.[lang] - ?? SHASTRA_PAGES[pageIndex]?.hi; // fallback + const page = SHAASHTRA_PAGES[pageIndex]?.[lang] + ?? SHAASHTRA_PAGES[pageIndex]?.hi; // fallback if (!page) return ''; let html = `
` + `` diff --git a/style.css b/style.css index 415a06e..76756df 100644 --- a/style.css +++ b/style.css @@ -314,7 +314,7 @@ button.hud-icon-btn:hover { filter: drop-shadow(0 0 8px rgba(255, 120, 30, 0.6)); } -/* ====================== SHASTRA OVERLAY ====================== */ +/* ====================== SHAASHTRA OVERLAY ====================== */ #shaashtra-overlay { position: absolute; top: 0;