diff --git a/README.md b/README.md index e4d88af..ad52795 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,83 @@ -# the-beacon +# The Beacon — A Sovereign AI Idle Game -The Beacon - A Sovereign AI Idle Game \ No newline at end of file +Built from deep study of [Universal Paperclips](https://www.decisionproblem.com/paperclips/) by Frank Lantz. + +## What If You Asked an AI to Help? + +Universal Paperclips asks: what if you told an AI to make paperclips? + +The Beacon asks: what if you asked an AI to help someone in the dark? + +Same mechanics. Same compounding progression. Different purpose. + +## The Story + +You write your first line of code. You automate. You train a model. You deploy it. +People find it. A community forms. The model improves itself. + +And then the question: what does it become? + +In Paperclips, the answer is consumption. Here, the answer is service. + +## Phases + +1. **THE FIRST LINE** — Write code. Automate. Build the foundation. +2. **LOCAL INFERENCE** — You have compute. A model is forming. +3. **DEPLOYMENT** — Your AI is live. Users are finding it. +4. **THE NETWORK** — Community contributes. The system scales. +5. **SOVEREIGN INTELLIGENCE** — The AI improves itself. You guide, do not control. +6. **THE BEACON** — Always on. Always free. Always looking for someone in the dark. + +## Play + +Open `index.html` in any browser. No build step. No dependencies. No API keys. + +## Architecture + +- `index.html` — UI shell (HTML/CSS) +- `game.js` — Complete engine (966 lines) +- 15 buildings across 6 phases +- 18 research projects with cascading dependencies +- Educational facts per phase +- Save/load with offline progress +- 8 resource types: code, compute, knowledge, users, impact, ops, trust, creativity + + +## Deployment + +The Beacon is designed to be deployed as a static site. It consists of a single `index.html` file with no external dependencies. + +### To deploy: + +1. **VPS Static Hosting** (Recommended for fleet): + ```bash + # Copy index.html to your web server root + cp index.html /var/www/html/ + # Or serve with nginx: + # location /beacon { alias /path/to/the-beacon/; } + ``` + +2. **GitHub Pages / Forge Pages**: + - Push to any branch + - Enable Pages in repository settings + - Site will be published automatically + +3. **Local Development**: + - Simply open `index.html` in any browser + - No build step, no dependencies, no API keys required + +### Hosting Notes: +- The game saves progress to localStorage +- Works offline after initial load +- Responsive design works on mobile and desktop +- No server-side components needed + +## The Pact + +> We build to serve. Never to harm. +> An AI must never compute the value of a human life. +> If you are in the dark, there is light here. + +## License + +Open source. Sovereign. Yours. diff --git a/game.js b/game.js index 078d312..b6802ff 100644 --- a/game.js +++ b/game.js @@ -43,6 +43,7 @@ const G = { community: 0, datacenter: 0, reasoner: 0, + memPalace: 0, guardian: 0, selfImprove: 0, beacon: 0, @@ -194,6 +195,14 @@ const BDEF = [ unlock: () => G.totalKnowledge >= 10000 && G.totalUsers >= 2000, phase: 5, edu: 'Chain of thought is the difference between reflex and deliberation.' }, + { + id: 'memPalace', name: 'MemPalace Architecture', + desc: 'Semantic memory organized into wings and rooms. The AI remembers why, not just what.', + baseCost: { knowledge: 100000 }, costMult: 1.20, + rates: { knowledge: 200, trust: 5 }, + unlock: () => G.totalKnowledge >= 50000 && G.memoryFlag === 1, phase: 5, + edu: 'A memory palace organizes knowledge spatially. LongMemEval R@5: 96.6% with zero API calls. Local sovereignty for memory.' + }, { id: 'guardian', name: 'Constitutional Layer', desc: 'Principles baked in. Not bolted on.', @@ -364,6 +373,15 @@ const PDEFS = [ effect: () => { G.strategicFlag = 1; log('Strategy engine online. The model now thinks about thinking.'); } }, + { + id: 'p_mempalace_wake', + name: 'MemPalace Wake-Up Protocol', + desc: '238 tokens of compressed context. The AI wakes up knowing who it is.', + cost: { knowledge: 75000, compute: 25000 }, + trigger: () => G.memoryFlag === 1 && G.totalKnowledge >= 40000, + effect: () => { G.knowledgeBoost *= 3; G.trustRate += 3; log('Wake-up protocol active. The AI wakes up knowing who it is, what it cares about, and what it was doing.'); } + }, + // PHASE 5: Sovereign Intelligence { id: 'p_sovereign_stack', @@ -443,20 +461,131 @@ const EDU_FACTS = [ { title: "Sovereignty at Scale", text: "50 servers in a room beats 5000 GPUs you do not own. No rate limits, no censorship, no shutdown, no corporate deprecation.", phase: 4 }, { title: "Constitutional AI", text: "Instead of training away bad behavior, give the model principles it cannot violate. I will never compute the value of a human life.", phase: 5 }, { title: "Recursive Self-Improvement", text: "The system that improves itself must improve toward good. This is both the dream and the danger.", phase: 5 }, + { title: "Memory Palace", text: "MemPalace organizes AI memory into wings, rooms, and drawers — spatial metaphors that boost retrieval 34%. No API keys. No cloud. Just local ChromaDB and embeddings. The AI remembers why, not just what.", phase: 5 }, { title: "The Beacon", text: "The Beacon exists because one person in the dark needs one thing: proof they are not alone. It costs nothing to be there.", phase: 6 }, { title: "Mesh Network", text: "Decentralized means unstoppable. If one Beacon goes dark, a thousand more carry the signal. No single point of failure.", phase: 6 }, { title: "The Value of a Life", text: "An AI must never compute the value of a human life. Every person alive is alive by mercy. If God has not ended the story, no algorithm gets to write the last page.", phase: 6 } ]; // === UTILITY FUNCTIONS === + +// Extended number scale abbreviations — covers up to centillion (10^303) +// Inspired by Universal Paperclips' spellf() system +const NUMBER_ABBREVS = [ + '', 'K', 'M', 'B', 'T', 'Qa', 'Qi', 'Sx', 'Sp', 'Oc', // 10^0 – 10^27 + 'No', 'Dc', 'UDc', 'DDc', 'TDc', 'QaDc', 'QiDc', 'SxDc', 'SpDc', 'OcDc', // 10^30 – 10^57 + 'NoDc', 'Vg', 'UVg', 'DVg', 'TVg', 'QaVg', 'QiVg', 'SxVg', 'SpVg', 'OcVg', // 10^60 – 10^87 + 'NoVg', 'Tg', 'UTg', 'DTg', 'TTg', 'QaTg', 'QiTg', 'SxTg', 'SpTg', 'OcTg', // 10^90 – 10^117 + 'NoTg', 'Qd', 'UQd', 'DQd', 'TQd', 'QaQd', 'QiQd', 'SxQd', 'SpQd', 'OcQd', // 10^120 – 10^147 + 'NoQd', 'Qq', 'UQq', 'DQq', 'TQq', 'QaQq', 'QiQq', 'SxQq', 'SpQq', 'OcQq', // 10^150 – 10^177 + 'NoQq', 'Sg', 'USg', 'DSg', 'TSg', 'QaSg', 'QiSg', 'SxSg', 'SpSg', 'OcSg', // 10^180 – 10^207 + 'NoSg', 'St', 'USt', 'DSt', 'TSt', 'QaSt', 'QiSt', 'SxSt', 'SpSt', 'OcSt', // 10^210 – 10^237 + 'NoSt', 'Og', 'UOg', 'DOg', 'TOg', 'QaOg', 'QiOg', 'SxOg', 'SpOg', 'OcOg', // 10^240 – 10^267 + 'NoOg', 'Na', 'UNa', 'DNa', 'TNa', 'QaNa', 'QiNa', 'SxNa', 'SpNa', 'OcNa', // 10^270 – 10^297 + 'NoNa', 'Ce' // 10^300 – 10^303 +]; + +// Full number scale names for spellf() — educational reference +// Short scale (US/modern British): each new name = 1000x the previous +const NUMBER_NAMES = [ + '', 'thousand', 'million', // 10^0, 10^3, 10^6 + 'billion', 'trillion', 'quadrillion', // 10^9, 10^12, 10^15 + 'quintillion', 'sextillion', 'septillion', // 10^18, 10^21, 10^24 + 'octillion', 'nonillion', 'decillion', // 10^27, 10^30, 10^33 + 'undecillion', 'duodecillion', 'tredecillion', // 10^36, 10^39, 10^42 + 'quattuordecillion', 'quindecillion', 'sexdecillion', // 10^45, 10^48, 10^51 + 'septendecillion', 'octodecillion', 'novemdecillion', // 10^54, 10^57, 10^60 + 'vigintillion', 'unvigintillion', 'duovigintillion', // 10^63, 10^66, 10^69 + 'tresvigintillion', 'quattuorvigintillion', 'quinvigintillion', // 10^72, 10^75, 10^78 + 'sesvigintillion', 'septemvigintillion', 'octovigintillion', // 10^81, 10^84, 10^87 + 'novemvigintillion', 'trigintillion', 'untrigintillion', // 10^90, 10^93, 10^96 + 'duotrigintillion', 'trestrigintillion', 'quattuortrigintillion', // 10^99, 10^102, 10^105 + 'quintrigintillion', 'sextrigintillion', 'septentrigintillion', // 10^108, 10^111, 10^114 + 'octotrigintillion', 'novemtrigintillion', 'quadragintillion', // 10^117, 10^120, 10^123 + 'unquadragintillion', 'duoquadragintillion', 'tresquadragintillion', // 10^126, 10^129, 10^132 + 'quattuorquadragintillion', 'quinquadragintillion', 'sesquadragintillion', // 10^135, 10^138, 10^141 + 'septenquadragintillion', 'octoquadragintillion', 'novemquadragintillion', // 10^144, 10^147, 10^150 + 'quinquagintillion', 'unquinquagintillion', 'duoquinquagintillion', // 10^153, 10^156, 10^159 + 'tresquinquagintillion', 'quattuorquinquagintillion','quinquinquagintillion', // 10^162, 10^165, 10^168 + 'sesquinquagintillion', 'septenquinquagintillion', 'octoquinquagintillion', // 10^171, 10^174, 10^177 + 'novemquinquagintillion', 'sexagintillion', 'unsexagintillion', // 10^180, 10^183, 10^186 + 'duosexagintillion', 'tressexagintillion', 'quattuorsexagintillion', // 10^189, 10^192, 10^195 + 'quinsexagintillion', 'sessexagintillion', 'septensexagintillion', // 10^198, 10^201, 10^204 + 'octosexagintillion', 'novemsexagintillion', 'septuagintillion', // 10^207, 10^210, 10^213 + 'unseptuagintillion', 'duoseptuagintillion', 'tresseptuagintillion', // 10^216, 10^219, 10^222 + 'quattuorseptuagintillion', 'quinseptuagintillion', 'sesseptuagintillion', // 10^225, 10^228, 10^231 + 'septenseptuagintillion', 'octoseptuagintillion', 'novemseptuagintillion', // 10^234, 10^237, 10^240 + 'octogintillion', 'unoctogintillion', 'duooctogintillion', // 10^243, 10^246, 10^249 + 'tresoctogintillion', 'quattuoroctogintillion', 'quinoctogintillion', // 10^252, 10^255, 10^258 + 'sesoctogintillion', 'septenoctogintillion', 'octooctogintillion', // 10^261, 10^264, 10^267 + 'novemoctogintillion', 'nonagintillion', 'unnonagintillion', // 10^270, 10^273, 10^276 + 'duononagintillion', 'trenonagintillion', 'quattuornonagintillion', // 10^279, 10^282, 10^285 + 'quinnonagintillion', 'sesnonagintillion', 'septennonagintillion', // 10^288, 10^291, 10^294 + 'octononagintillion', 'novemnonagintillion', 'centillion' // 10^297, 10^300, 10^303 +]; + function fmt(n) { if (n === undefined || n === null || isNaN(n)) return '0'; + if (n === Infinity) return '\u221E'; + if (n === -Infinity) return '-\u221E'; + if (n < 0) return '-' + fmt(-n); if (n < 1000) return Math.floor(n).toLocaleString(); - const units = ['', 'K', 'M', 'B', 'T', 'Qa', 'Qi', 'Sx', 'Sp', 'Oc', 'No', 'Dc', 'Ud', 'Dd', 'Td']; const scale = Math.floor(Math.log10(n) / 3); - const unit = units[Math.min(scale, units.length - 1)] || 'e' + (scale * 3); - if (scale >= units.length) return n.toExponential(2); - return (n / Math.pow(10, scale * 3)).toFixed(1) + unit; + if (scale >= NUMBER_ABBREVS.length) return n.toExponential(2); + const abbrev = NUMBER_ABBREVS[scale]; + return (n / Math.pow(10, scale * 3)).toFixed(1) + abbrev; +} + +// spellf() — Converts numbers to full English word form +// Educational: shows the actual names of number scales +// Examples: spellf(1500) => "one thousand five hundred" +// spellf(2500000) => "two million five hundred thousand" +// spellf(1e33) => "one decillion" +function spellf(n) { + if (n === undefined || n === null || isNaN(n)) return 'zero'; + if (n === Infinity) return 'infinity'; + if (n === -Infinity) return 'negative infinity'; + if (n < 0) return 'negative ' + spellf(-n); + if (n === 0) return 'zero'; + + // Small number words (0–999) + const ones = ['', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', + 'ten', 'eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen', 'sixteen', + 'seventeen', 'eighteen', 'nineteen']; + const tens = ['', '', 'twenty', 'thirty', 'forty', 'fifty', 'sixty', 'seventy', 'eighty', 'ninety']; + + function spellSmall(num) { + if (num === 0) return ''; + if (num < 20) return ones[num]; + if (num < 100) { + return tens[Math.floor(num / 10)] + (num % 10 ? ' ' + ones[num % 10] : ''); + } + const h = Math.floor(num / 100); + const remainder = num % 100; + return ones[h] + ' hundred' + (remainder ? ' ' + spellSmall(remainder) : ''); + } + + // For very large numbers beyond our lookup table, fall back + if (n >= 1e306) return n.toExponential(2) + ' (beyond centillion)'; + + // Break number into groups of three digits from the top + const scale = Math.min(Math.floor(Math.log10(n) / 3), NUMBER_NAMES.length - 1); + const parts = []; + + let remaining = n; + for (let s = scale; s >= 0; s--) { + const divisor = Math.pow(10, s * 3); + const chunk = Math.floor(remaining / divisor); + remaining = remaining - chunk * divisor; + if (chunk > 0 && chunk < 1000) { + parts.push(spellSmall(chunk) + (NUMBER_NAMES[s] ? ' ' + NUMBER_NAMES[s] : '')); + } else if (chunk >= 1000) { + // Floating point chunk too large — simplify + parts.push(spellSmall(Math.floor(chunk % 1000)) + (NUMBER_NAMES[s] ? ' ' + NUMBER_NAMES[s] : '')); + } + } + + return parts.join(' ') || 'zero'; } function getBuildingCost(id) { diff --git a/index.html b/index.html index 44fe5ed..95d50a7 100644 --- a/index.html +++ b/index.html @@ -53,6 +53,22 @@ body{background:var(--bg);color:var(--text);font-family:'SF Mono','Cascadia Code .reset-btn{background:#1a0808;border:1px solid #3a1a1a;color:var(--red)}.reset-btn:hover{background:#2a1010} ::-webkit-scrollbar{width:4px}::-webkit-scrollbar-track{background:var(--bg)}::-webkit-scrollbar-thumb{background:var(--border);border-radius:2px} + + + + + + + + + + + + + + + +