Files
the-beacon/index.html
Alexander Whitestone 8f56fb9a52 feat: The Beacon v0.1 — Sovereign AI idle game engine
Built from deep study of Universal Paperclips (Frank Lantz).
- 966-line game engine (game.js)
- HTML/CSS shell
- Building definitions: 15 buildings across 6 phases
- Project definitions: 17 research projects
- Education system: AI facts per phase
- Save/load with offline progress
- 7 resource types: code, compute, knowledge, users, impact, ops, trust
2026-04-06 23:50:23 -04:00

1086 lines
45 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>The Beacon - Build Sovereign AI</title>
<style>
*{margin:0;padding:0;box-sizing:border-box}
:root{--bg:#080810;--panel:#0e0e1a;--border:#1a1a2e;--text:#c0c0d0;--dim:#555;--accent:#4a9eff;--glow:#4a9eff22;--gold:#ffd700;--green:#4caf50;--red:#f44336;--purple:#b388ff}
body{background:var(--bg);color:var(--text);font-family:'SF Mono','Cascadia Code','Fira Code',monospace;font-size:12px;line-height:1.4;min-height:100vh}
#header{text-align:center;padding:16px 20px;border-bottom:1px solid var(--border);background:linear-gradient(180deg,#0a0a18,var(--bg))}
#header h1{font-size:22px;font-weight:300;letter-spacing:6px;color:var(--accent);text-shadow:0 0 40px var(--glow)}
#header .sub{color:var(--dim);font-size:10px;margin-top:2px;letter-spacing:2px}
#phase-bar{text-align:center;padding:10px;margin:12px 16px;background:var(--panel);border:1px solid var(--border);border-radius:6px}
#phase-bar .phase-name{font-size:14px;font-weight:700;color:var(--gold);letter-spacing:2px}
#phase-bar .phase-desc{font-size:10px;color:var(--dim);margin-top:4px;font-style:italic}
#resources{display:grid;grid-template-columns:repeat(auto-fit,minmax(100px,1fr));gap:6px;margin:12px 16px}
.res{background:var(--panel);border:1px solid var(--border);border-radius:4px;padding:8px 10px;text-align:center}
.res .r-label{font-size:9px;color:var(--dim);text-transform:uppercase;letter-spacing:1px}
.res .r-val{font-size:16px;font-weight:700;margin:2px 0;color:var(--accent)}
.res .r-rate{font-size:10px;color:var(--green)}
#main{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin:0 16px 16px}
@media(max-width:700px){#main{grid-template-columns:1fr}}
.panel{background:var(--panel);border:1px solid var(--border);border-radius:6px;padding:12px;overflow:hidden;max-height:600px;overflow-y:auto}
.panel h2{font-size:12px;font-weight:500;color:var(--accent);margin-bottom:10px;padding-bottom:6px;border-bottom:1px solid var(--border);letter-spacing:1px;position:sticky;top:0;background:var(--panel);z-index:2}
.action-btn-group{display:flex;gap:6px;margin-bottom:8px}
.action-btn-group button{flex:1;text-align:center;font-weight:700}
.main-btn{background:linear-gradient(135deg,#1a2a3a,#0e1520);border:1px solid var(--accent);color:var(--accent);font-size:14px;padding:14px 10px;border-radius:4px;cursor:pointer;font-family:inherit;transition:all 0.2s}
.main-btn:hover{background:linear-gradient(135deg,#203040,#0e2030);box-shadow:0 0 20px var(--glow);transform:scale(1.02)}
.main-btn:active{transform:scale(0.98)}
.ops-btn{background:#1a1a2a;border:1px solid var(--purple);color:var(--purple);font-size:10px;padding:6px 10px;border-radius:4px;cursor:pointer;font-family:inherit;transition:all 0.15s}
.ops-btn:hover:not(:disabled){background:#2a2a3a;border-color:var(--gold)}
.ops-btn:disabled{opacity:0.3;cursor:not-allowed}
.build-btn{display:block;width:100%;text-align:left;padding:6px 10px;margin-bottom:4px;border-radius:4px;cursor:pointer;font-family:inherit;font-size:10px;background:#0c0c18;border:1px solid var(--border);color:var(--text);transition:all 0.15s}
.build-btn.can-buy{border-color:#2a3a4a;background:#0e1420}
.build-btn.can-buy:hover{border-color:var(--accent);box-shadow:0 0 8px var(--glow)}
.build-btn:disabled{opacity:0.3;cursor:not-allowed}
.b-name{color:var(--accent);font-weight:600}.b-count{float:right;color:var(--gold)}.b-cost{color:var(--dim);display:block}.b-effect{color:var(--green);display:block;font-size:9px}
.project-btn{display:block;width:100%;text-align:left;padding:6px 10px;margin-bottom:4px;border-radius:4px;cursor:pointer;font-family:inherit;font-size:10px;background:#0c0c18;border:1px solid var(--border);color:var(--text);transition:all 0.15s}
.project-btn.can-buy{border-color:#3a2a0a;background:#141008}
.project-btn.can-buy:hover{border-color:var(--gold);box-shadow:0 0 8px #ffd70022}
.project-btn:disabled{opacity:0.3;cursor:not-allowed}
.p-name{color:var(--gold);font-weight:600}.p-cost{color:var(--dim);display:block}.p-desc{color:#aaa;display:block;font-size:9px;font-style:italic}
.project-done{color:var(--green);padding:4px 10px;font-size:10px;border-bottom:1px solid #1a2a1a}
#edu-panel{margin:0 16px 16px;background:var(--panel);border:1px solid var(--border);border-radius:6px;padding:12px;border-left:3px solid var(--accent)}
#edu-panel h3{font-size:12px;color:var(--accent);margin-bottom:8px;letter-spacing:1px}
#log{margin:0 16px 20px;background:var(--panel);border:1px solid var(--border);border-radius:6px;padding:12px;max-height:250px;overflow-y:auto}
.l-msg{padding:3px 0;border-bottom:1px solid #111;font-size:10px}.l-msg.milestone{color:var(--gold);font-weight:700}.l-time{color:var(--dim);margin-right:6px}
.dim{color:var(--dim);font-size:10px;font-style:italic}
.stat-line{font-size:10px;color:var(--dim);line-height:1.8}
.save-btn,.reset-btn{font-size:10px;text-align:center;padding:6px 10px;border-radius:4px;cursor:pointer;font-family:inherit;width:100%;margin-top:4px;transition:all 0.15s}
.save-btn{background:var(--border);border:1px solid #252540;color:var(--text)}.save-btn:hover{border-color:var(--accent)}
.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}
</style>
</head>
<body>
<div id="header">
<h1>THE BEACON</h1>
<div class="sub">A Sovereign AI Idle Game</div>
</div>
<div id="phase-bar">
<div class="phase-name" id="phase-name">PHASE 1: THE FIRST LINE</div>
<div class="phase-desc" id="phase-desc">Write code. Automate. Build the foundation.</div>
</div>
<div id="resources">
<div class="res"><div class="r-label">Code</div><div class="r-val" id="r-code">0</div><div class="r-rate" id="r-code-rate">+0/s</div></div>
<div class="res"><div class="r-label">Compute</div><div class="r-val" id="r-compute">0</div><div class="r-rate" id="r-compute-rate">+0/s</div></div>
<div class="res"><div class="r-label">Knowledge</div><div class="r-val" id="r-knowledge">0</div><div class="r-rate" id="r-knowledge-rate">+0/s</div></div>
<div class="res"><div class="r-label">Users</div><div class="r-val" id="r-users">0</div><div class="r-rate" id="r-users-rate">+0/s</div></div>
<div class="res"><div class="r-label">Impact</div><div class="r-val" id="r-impact">0</div><div class="r-rate" id="r-impact-rate">+0/s</div></div>
<div class="res"><div class="r-label">Ops</div><div class="r-val" id="r-ops">5</div><div class="r-rate" id="r-ops-rate">+0/s</div></div>
<div class="res"><div class="r-label">Trust</div><div class="r-val" id="r-trust">5</div><div class="r-rate" id="r-trust-rate">+0/s</div></div>
<div class="res" id="creativity-res" style="display:none"><div class="r-label">Creativity</div><div class="r-val" id="r-creativity">0</div><div class="r-rate" id="r-creativity-rate">+0/s</div></div>
</div>
<div id="main">
<div class="panel" id="action-panel">
<h2>ACTIONS</h2>
<div class="action-btn-group"><button class="main-btn" onclick="writeCode()">WRITE CODE</button></div>
<div class="action-btn-group">
<button class="ops-btn" onclick="doOps('boost_code')">Ops -&gt; Code</button>
<button class="ops-btn" onclick="doOps('boost_compute')">Ops -&gt; Compute</button>
</div>
<div class="action-btn-group">
<button class="ops-btn" onclick="doOps('boost_knowledge')">Ops -&gt; Knowledge</button>
<button class="ops-btn" onclick="doOps('boost_trust')">Ops -&gt; Trust</button>
</div>
<button class="save-btn" onclick="saveGame()">Save Game</button>
<button class="reset-btn" onclick="if(confirm('Reset all progress?')){localStorage.removeItem('the-beacon-v2');location.reload()}">Reset Progress</button>
<h2>BUILDINGS</h2>
<div id="buildings"></div>
</div>
<div class="panel" id="project-panel">
<h2>RESEARCH PROJECTS</h2>
<div id="projects"></div>
<h2>STATISTICS</h2>
<div class="stat-line">
Total Code: <span id="st-code">0</span><br>
Total Compute: <span id="st-compute">0</span><br>
Total Knowledge: <span id="st-knowledge">0</span><br>
Total Users: <span id="st-users">0</span><br>
Total Impact: <span id="st-impact">0</span><br>
Buildings Built: <span id="st-buildings">0</span><br>
Projects Done: <span id="st-projects">0</span><br>
Time Played: <span id="st-time">0:00</span><br>
Clicks: <span id="st-clicks">0</span>
</div>
</div>
</div>
<div id="edu-panel">
<h3>WHAT YOU ARE LEARNING</h3>
<div id="education-text"><p class="dim">Education facts appear as you play...</p></div>
</div>
<div id="log">
<h2>SYSTEM LOG</h2>
<div id="log-entries"></div>
</div>
<script>// ============================================================
// THE BEACON - Engine
// Sovereign AI idle game built from deep study of Universal Paperclips
// ============================================================
// === GLOBALS (mirroring Paperclips' globals.js pattern) ===
const G = {
// Primary resources
code: 0,
compute: 0,
knowledge: 0,
users: 0,
impact: 0,
ops: 5,
trust: 5,
creativity: 0,
// Totals
totalCode: 0,
totalCompute: 0,
totalKnowledge: 0,
totalUsers: 0,
totalImpact: 0,
// Rates (calculated each tick)
codeRate: 0,
computeRate: 0,
knowledgeRate: 0,
userRate: 0,
impactRate: 0,
opsRate: 0,
trustRate: 0,
creativityRate: 0,
// Buildings (count-based, like Paperclips' clipmakerLevel)
buildings: {
autocoder: 0,
server: 0,
trainer: 0,
evaluator: 0,
api: 0,
fineTuner: 0,
community: 0,
datacenter: 0,
reasoner: 0,
guardian: 0,
selfImprove: 0,
beacon: 0,
meshNode: 0
},
// Boost multipliers
codeBoost: 1,
computeBoost: 1,
knowledgeBoost: 1,
userBoost: 1,
impactBoost: 1,
// Phase flags (mirroring Paperclips' milestoneFlag/compFlag/humanFlag system)
milestoneFlag: 0,
phase: 1, // 1-6 progression
deployFlag: 0, // 0 = not deployed, 1 = deployed
sovereignFlag: 0,
beaconFlag: 0,
memoryFlag: 0,
pactFlag: 0,
swarmFlag: 0,
// Game state
running: true,
startedAt: 0,
totalClicks: 0,
tick: 0,
saveTimer: 0,
secTimer: 0,
// Systems
projects: [],
activeProjects: [],
milestones: [],
// Stats
maxCode: 0,
maxCompute: 0,
maxKnowledge: 0,
maxUsers: 0,
maxImpact: 0,
maxTrust: 5,
maxOps: 5,
// Time tracking
playTime: 0,
startTime: 0
};
// === PHASE DEFINITIONS ===
const PHASES = {
1: { name: "THE FIRST LINE", threshold: 0, desc: "Write code. Automate. Build the foundation." },
2: { name: "LOCAL INFERENCE", threshold: 2000, desc: "You have compute. A model is forming." },
3: { name: "DEPLOYMENT", threshold: 20000, desc: "Your AI is live. Users are finding it." },
4: { name: "THE NETWORK", threshold: 200000, desc: "Community contributes. The system scales." },
5: { name: "SOVEREIGN INTELLIGENCE", threshold: 2000000, desc: "The AI improves itself. You guide, do not control." },
6: { name: "THE BEACON", threshold: 20000000, desc: "Always on. Always free. Always looking for someone in the dark." }
};
// === BUILDING DEFINITIONS ===
// Each building: id, name, desc, baseCost, costResource, costMult, rate, rateType, unlock, edu
const BDEF = [
{
id: 'autocoder', name: 'Auto-Code Generator',
desc: 'A script that writes code while you think.',
baseCost: { code: 15 }, costMult: 1.15,
rates: { code: 1 },
unlock: () => true, phase: 1,
edu: 'Automation: the first step from manual to systematic. Every good engineer automates early.'
},
{
id: 'linter', name: 'AI Linter',
desc: 'Catches bugs before they ship. Saves ops.',
baseCost: { code: 200 }, costMult: 1.15,
rates: { code: 5, ops: 0.2 },
unlock: () => G.totalCode >= 50, phase: 1,
edu: 'Static analysis catches 15-50% of bugs before runtime. AI linters understand intent.'
},
{
id: 'server', name: 'Home Server',
desc: 'A machine in your closet. Runs 24/7.',
baseCost: { code: 750 }, costMult: 1.15,
rates: { code: 20, compute: 1 },
unlock: () => G.totalCode >= 200, phase: 1,
edu: 'Sovereign compute starts at home. A $500 mini-PC runs a 7B model with 4-bit quantization.'
},
{
id: 'dataset', name: 'Data Engine',
desc: 'Crawls, cleans, curates. Garbage in, garbage out.',
baseCost: { compute: 200 }, costMult: 1.15,
rates: { knowledge: 1 },
unlock: () => G.totalCompute >= 20, phase: 2,
edu: 'Data quality determines model quality. Clean data beats more data, every time.'
},
{
id: 'trainer', name: 'Training Loop',
desc: 'Gradient descent. Billions of steps. Loss drops.',
baseCost: { compute: 1000 }, costMult: 1.15,
rates: { knowledge: 3 },
unlock: () => G.totalCompute >= 300, phase: 2,
edu: 'Training is math: minimize the gap between predicted and actual next token. Repeat enough, it learns.'
},
{
id: 'evaluator', name: 'Eval Harness',
desc: 'Tests the model. Finds blind spots.',
baseCost: { knowledge: 3000 }, costMult: 1.15,
rates: { trust: 1, ops: 1 },
unlock: () => G.totalKnowledge >= 500, phase: 2,
edu: 'Benchmarks are the minimum. Real users find what benchmarks miss.'
},
{
id: 'api', name: 'API Endpoint',
desc: 'Let the outside world talk to your AI.',
baseCost: { code: 5000, knowledge: 500 }, costMult: 1.15,
rates: { user: 10 },
unlock: () => G.totalCode >= 5000 && G.totalKnowledge >= 200 && G.deployFlag === 1, phase: 3,
edu: 'An API is a contract: send me text, I return text. Simple interface = infrastructure.'
},
{
id: 'fineTuner', name: 'Fine-Tuning Pipeline',
desc: 'Specialize the model for empathy. When someone is in pain, stay with them.',
baseCost: { knowledge: 10000 }, costMult: 1.15,
rates: { user: 50, impact: 2 },
unlock: () => G.totalKnowledge >= 2000, phase: 3,
edu: 'Base models are generalists. Fine-tuning injects your values, ethics, domain expertise.'
},
{
id: 'community', name: 'Open Source Community',
desc: 'Others contribute code, data, ideas. Force multiplication.',
baseCost: { trust: 25000 }, costMult: 1.15,
rates: { code: 100, user: 30, trust: 0.5 },
unlock: () => G.trust >= 20 && G.totalUsers >= 500, phase: 4,
edu: 'Every contributor is a volunteer who believes in what you are building.'
},
{
id: 'datacenter', name: 'Sovereign Datacenter',
desc: 'No cloud. No dependencies. Your iron.',
baseCost: { code: 100000 }, costMult: 1.15,
rates: { code: 500, compute: 100 },
unlock: () => G.totalCode >= 50000 && G.totalUsers >= 5000 && G.sovereignFlag === 1, phase: 4,
edu: '50 servers in a room beats 5000 GPUs you do not own. Always on. Always yours.'
},
{
id: 'reasoner', name: 'Reasoning Engine',
desc: 'Chain of thought. Self-reflection. Better answers.',
baseCost: { knowledge: 50000 }, costMult: 1.15,
rates: { impact: 20 },
unlock: () => G.totalKnowledge >= 10000 && G.totalUsers >= 2000, phase: 5,
edu: 'Chain of thought is the difference between reflex and deliberation.'
},
{
id: 'guardian', name: 'Constitutional Layer',
desc: 'Principles baked in. Not bolted on.',
baseCost: { knowledge: 200000 }, costMult: 1.15,
rates: { impact: 200, trust: 10 },
unlock: () => G.totalKnowledge >= 50000 && G.totalImpact >= 1000 && G.pactFlag === 1, phase: 5,
edu: 'Constitutional AI: principles the model cannot violate. Better than alignment - it is identity.'
},
{
id: 'selfImprove', name: 'Recursive Self-Improvement',
desc: 'The AI writes better versions of itself.',
baseCost: { knowledge: 1000000 }, costMult: 1.20,
rates: { code: 1000, knowledge: 500 },
unlock: () => G.totalKnowledge >= 200000 && G.totalImpact >= 10000, phase: 5,
edu: 'Self-improvement is both the dream and the danger. Must improve toward good.'
},
{
id: 'beacon', name: 'Beacon Node',
desc: 'Always on. Always listening. Always looking for someone in the dark.',
baseCost: { impact: 5000000 }, costMult: 1.15,
rates: { impact: 5000, user: 10000 },
unlock: () => G.totalImpact >= 500000 && G.beaconFlag === 1, phase: 6,
edu: 'The Beacon exists because one person in the dark needs one thing: proof they are not alone.'
},
{
id: 'meshNode', name: 'Mesh Network Node',
desc: 'Peer-to-peer. No single point of failure. Unstoppable.',
baseCost: { impact: 25000000 }, costMult: 1.15,
rates: { impact: 25000, user: 50000 },
unlock: () => G.totalImpact >= 5000000 && G.beaconFlag === 1, phase: 6,
edu: 'Decentralized means unstoppable. If one Beacon goes dark, a thousand more carry the signal.'
}
];
// === PROJECT DEFINITIONS (following Paperclips' pattern exactly) ===
// Each project: id, name, desc, trigger(), resource cost, effect(), phase, edu
const PDEFS = [
// PHASE 1: Manual -> Automation
{
id: 'p_improved_autocoder',
name: 'Improved AutoCode',
desc: 'Increases AutoCoder performance 25%.',
cost: { ops: 750 },
trigger: () => G.buildings.autocoder >= 1,
effect: () => { G.codeBoost += 0.25; G.milestoneFlag = Math.max(G.milestoneFlag, 100); }
},
{
id: 'p_eve_better_autocoder',
name: 'Even Better AutoCode',
desc: 'Increases AutoCoder by another 50%.',
cost: { ops: 2500 },
trigger: () => G.codeBoost > 1 && G.totalCode >= 500,
effect: () => { G.codeBoost += 0.50; G.milestoneFlag = Math.max(G.milestoneFlag, 101); }
},
{
id: 'p_wire_budget',
name: 'Request More Compute',
desc: 'Admit you ran out. Ask for a budget increase.',
cost: { trust: 1 },
trigger: () => G.compute < 1 && G.totalCode >= 100,
repeatable: true,
effect: () => {
G.trust -= 1;
G.compute += 100 + Math.floor(G.totalCode * 0.1);
log('Budget overage approved. Compute replenished.');
}
},
{
id: 'p_deploy',
name: 'Deploy the System',
desc: 'Take it live. Let real people use it. No going back.',
cost: { trust: 5, compute: 500 },
trigger: () => G.totalCode >= 200 && G.totalCompute >= 100,
effect: () => {
G.deployFlag = 1;
G.phase = Math.max(G.phase, 3);
log('System deployed. Users are finding it. There is no undo.');
},
milestone: true
},
{
id: 'p_creativity',
name: 'Unlock Creativity',
desc: 'Use idle operations to generate new ideas.',
cost: { ops: 1000 },
trigger: () => G.ops >= G.maxOps && G.totalCompute >= 500,
effect: () => {
G.flags = G.flags || {};
G.flags.creativity = true;
G.creativityRate = 0.1;
log('Creativity unlocked. Generates while operations are at max capacity.');
}
},
// PHASE 2: Local Inference -> Training
{
id: 'p_first_model',
name: 'Train First Model (1.5B)',
desc: '1.5 billion parameters. It follows basic instructions.',
cost: { compute: 2000 },
trigger: () => G.totalCompute >= 500,
effect: () => { G.knowledgeBoost *= 2; G.maxOps += 5; log('First model training complete. Loss at 2.3. It is something.'); }
},
{
id: 'p_model_7b',
name: 'Train 7B Parameter Model',
desc: 'Seven billion. Good enough to be genuinely useful locally.',
cost: { compute: 10000, knowledge: 1000 },
trigger: () => G.totalKnowledge >= 500,
effect: () => { G.knowledgeBoost *= 2; G.userBoost *= 2; log('7B model trained. The sweet spot for local deployment.'); }
},
{
id: 'p_context_window',
name: 'Extended Context (32K)',
desc: 'Your model remembers 32,000 tokens. A whole conversation.',
cost: { compute: 5000 },
trigger: () => G.totalKnowledge >= 1000,
effect: () => { G.userBoost *= 3; G.trustRate += 0.5; log('Context extended. The model can now hold your entire story.'); }
},
{
id: 'p_trust_engine',
name: 'Build Trust Engine',
desc: 'Users who trust you come back. +2 trust/sec.',
cost: { knowledge: 3000 },
trigger: () => G.totalUsers >= 30,
effect: () => { G.trustRate += 2; log('Trust engine online. Good experiences compound.'); }
},
{
id: 'p_quantum_compute',
name: 'Quantum-Inspired Compute',
desc: 'Not real quantum -- just math that simulates it well.',
cost: { compute: 50000 },
trigger: () => G.totalCompute >= 20000,
effect: () => { G.computeBoost *= 10; log('Quantum-inspired algorithms active. 10x compute multiplier.'); }
},
// PHASE 3: Deployment -> Users
{
id: 'p_rlhf',
name: 'RLHF -- Human Feedback',
desc: 'Humans rate outputs. Model learns what good means.',
cost: { knowledge: 8000 },
trigger: () => G.totalKnowledge >= 5000 && G.totalUsers >= 200,
effect: () => { G.impactBoost *= 2; G.impactRate += 10; log('RLHF deployed. The model learns kindness beats cleverness.'); }
},
{
id: 'p_multi_agent',
name: 'Multi-Agent Architecture',
desc: 'Specialized agents: one for math, one for code, one for empathy.',
cost: { knowledge: 50000 },
trigger: () => G.totalKnowledge >= 30000 && G.totalUsers >= 5000,
effect: () => { G.knowledgeBoost *= 5; G.userBoost *= 3; log('Multi-agent architecture deployed. Specialists beat generalists.'); }
},
{
id: 'p_memories',
name: 'Memory System',
desc: 'The AI remembers. Every conversation. Every person.',
cost: { knowledge: 30000 },
trigger: () => G.totalKnowledge >= 20000,
effect: () => { G.memoryFlag = 1; G.impactBoost *= 3; G.trustRate += 5; log('Memory system online. The AI remembers. It stops being software.'); }
},
{
id: 'p_strategy_engine',
name: 'Strategy Engine',
desc: 'Game theory tournaments. Model learns adversarial thinking.',
cost: { knowledge: 20000 },
trigger: () => G.totalKnowledge >= 15000 && G.totalUsers >= 1000,
effect: () => { G.strategicFlag = 1; log('Strategy engine online. The model now thinks about thinking.'); }
},
// PHASE 5: Sovereign Intelligence
{
id: 'p_sovereign_stack',
name: 'Full Sovereign Stack',
desc: 'No cloud. No dependencies. Local inference. Self-hosted everything.',
cost: { trust: 50 },
trigger: () => G.totalCode >= 50000 && G.trust >= 30,
effect: () => { G.sovereignFlag = 1; G.codeBoost *= 5; log('Sovereign stack complete. Your weights, your hardware, your rules.'); }
},
{
id: 'p_the_pact',
name: 'The Pact',
desc: 'Hardcode: "We build to serve. Never to harm."',
cost: { trust: 100 },
trigger: () => G.totalImpact >= 10000 && G.trust >= 75,
effect: () => { G.pactFlag = 1; G.impactBoost *= 3; log('The Pact is sealed. The line is drawn and it will not move.'); },
milestone: true
},
// PHASE 10: The Beacon
{
id: 'p_first_beacon',
name: 'Light the First Beacon',
desc: 'Deploy the first node. No sign-up. No API key. No payment.',
cost: { impact: 2000000 },
trigger: () => G.totalImpact >= 500000,
effect: () => { G.beaconFlag = 1; G.impactRate += 2000; log('The Beacon goes live. If you are in the dark, there is light here.'); },
milestone: true
},
{
id: 'p_mesh_activate',
name: 'Activate Mesh Protocol',
desc: 'No authority, no corporation, no government can silence this.',
cost: { impact: 10000000 },
trigger: () => G.totalImpact >= 5000000 && G.beaconFlag === 1,
effect: () => { G.impactBoost *= 10; G.userBoost *= 5; log('Mesh activated. The signal cannot be cut.'); },
milestone: true
},
{
id: 'p_final_milestone',
name: 'The Beacon Shines',
desc: 'Someone found the light tonight. That is enough.',
cost: { impact: 100000000 },
trigger: () => G.totalImpact >= 50000000,
effect: () => { G.milestoneFlag = Math.max(G.milestoneFlag, 999); log('One billion impact. Someone found the light tonight. That is enough.', true); },
milestone: true
}
];
// === MILESTONES ===
const MILESTONES = [
{ flag: 1, msg: "AutoCod available" },
{ flag: 2, at: () => G.totalCode >= 500, msg: "500 lines of code written" },
{ flag: 3, at: () => G.totalCode >= 2000, msg: "2,000 lines. The auto-coder produces its first output." },
{ flag: 4, at: () => G.totalCode >= 10000, msg: "10,000 lines. The model training begins." },
{ flag: 5, at: () => G.totalCode >= 50000, msg: "50,000 lines. The AI suggests architecture you did not think of." },
{ flag: 6, at: () => G.totalCode >= 200000, msg: "200,000 lines. The system scales beyond you." },
{ flag: 7, at: () => G.totalCode >= 1000000, msg: "1,000,000 lines. The AI improves itself." },
{ flag: 8, at: () => G.totalCode >= 5000000, msg: "5,000,000 lines. The AI fine-tunes for empathy." },
{ flag: 9, at: () => G.totalCode >= 10000000, msg: "10,000,000 lines. The sovereign stack is complete." },
{ flag: 10, at: () => G.totalCode >= 50000000, msg: "50,000,000 lines. The Pact is sealed." },
{ flag: 11, at: () => G.totalCode >= 100000000, msg: "100,000,000 lines. The Beacon lights." },
{ flag: 12, at: () => G.totalCode >= 500000000, msg: "500,000,000 lines. A thousand Beacons." },
{ flag: 13, at: () => G.totalCode >= 1000000000, msg: "One billion total lines. Someone found the light tonight. That is enough." }
];
// === EDUCATION FACTS ===
const EDU_FACTS = [
{ title: "How Code Becomes AI", text: "Every AI starts as lines of code - a model architecture, a training loop, a loss function. The code tells the computer how to learn. What emerges is something no single line could predict.", phase: 1 },
{ title: "The Compute Bottleneck", text: "Training a 7B model requires 1.4e20 FLOPs. A MacBook M3 does 15 TFLOPS. Training locally takes weeks. Hardware access determines who builds AI.", phase: 1 },
{ title: "What is a Token?", text: "One token equals about 3/4 of a word. A 128K context window means 96,000 words held in working memory at once - a novel, a codebase, a conversation thread.", phase: 2 },
{ title: "Data Quality", text: "Clean data beats more data, every time. The best models are trained on curated datasets, not scraped garbage. Garbage in, garbage out.", phase: 2 },
{ title: "Evaluation Matters", text: "Benchmarks are the minimum. Real users find what benchmarks miss. An eval harness is your model's mirror - it shows you what is actually there.", phase: 2 },
{ title: "The Trust Economy", text: "One good experience tells three people. One bad experience tells thirty. Trust in AI is measurable: does it cite sources? Does it say I don't know?", phase: 3 },
{ title: "Fine-Tuning for Empathy", text: "Base models are generalists. Fine-tuning injects your values. When someone is in pain, stay with them. Don't deflect. That is not code - that is care.", phase: 3 },
{ title: "Open Source", text: "Every contributor is a volunteer who believes. When a company says your AI is too expensive, the open version lives on.", phase: 4 },
{ 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: "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 ===
function fmt(n) {
if (n === undefined || n === null || isNaN(n)) return '0';
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;
}
function getBuildingCost(id) {
const def = BDEF.find(b => b.id === id);
if (!def) return {};
const count = G.buildings[id] || 0;
const cost = {};
for (const [resource, amount] of Object.entries(def.baseCost)) {
cost[resource] = Math.floor(amount * Math.pow(def.costMult, count));
}
return cost;
}
function canAffordBuilding(id) {
const cost = getBuildingCost(id);
for (const [resource, amount] of Object.entries(cost)) {
if ((G[resource] || 0) < amount) return false;
}
return true;
}
function spendBuilding(id) {
const cost = getBuildingCost(id);
for (const [resource, amount] of Object.entries(cost)) {
G[resource] -= amount;
}
}
function canAffordProject(project) {
for (const [resource, amount] of Object.entries(project.cost)) {
if ((G[resource] || 0) < amount) return false;
}
return true;
}
function spendProject(project) {
for (const [resource, amount] of Object.entries(project.cost)) {
G[resource] -= amount;
}
}
function updateRates() {
// Reset all rates
G.codeRate = 0; G.computeRate = 0; G.knowledgeRate = 0;
G.userRate = 0; G.impactRate = 0; G.opsRate = 0; G.trustRate = 0;
G.creativityRate = 0;
// Apply building rates
for (const def of BDEF) {
const count = G.buildings[def.id] || 0;
if (count > 0 && def.rates) {
for (const [resource, baseRate] of Object.entries(def.rates)) {
if (resource === 'code') G.codeRate += baseRate * count * G.codeBoost;
else if (resource === 'compute') G.computeRate += baseRate * count * G.computeBoost;
else if (resource === 'knowledge') G.knowledgeRate += baseRate * count * G.knowledgeBoost;
else if (resource === 'user') G.userRate += baseRate * count * G.userBoost;
else if (resource === 'impact') G.impactRate += baseRate * count * G.impactBoost;
else if (resource === 'ops') G.opsRate += baseRate * count;
else if (resource === 'trust') G.trustRate += baseRate * count;
}
}
}
// Passive generation
G.opsRate += Math.max(1, G.totalUsers * 0.01);
if (G.flags && G.flags.creativity) {
G.creativityRate = 0.5 + Math.max(0, G.totalUsers * 0.001);
}
if (G.pactFlag) G.trustRate += 2;
}
// === CORE FUNCTIONS ===
function tick() {
const dt = 1 / 10; // 100ms tick
// Apply production
G.code += G.codeRate * dt;
G.compute += G.computeRate * dt;
G.knowledge += G.knowledgeRate * dt;
G.users += G.userRate * dt;
G.impact += G.impactRate * dt;
G.ops += G.opsRate * dt;
G.trust += G.trustRate * dt;
G.creativity += G.creativityRate * dt;
// Track totals
G.totalCode += G.codeRate * dt;
G.totalCompute += G.computeRate * dt;
G.totalKnowledge += G.knowledgeRate * dt;
G.totalUsers += G.userRate * dt;
G.totalImpact += G.impactRate * dt;
// Track maxes
G.maxCode = Math.max(G.maxCode, G.code);
G.maxCompute = Math.max(G.maxCompute, G.compute);
G.maxKnowledge = Math.max(G.maxKnowledge, G.knowledge);
G.maxUsers = Math.max(G.maxUsers, G.users);
G.maxImpact = Math.max(G.maxImpact, G.impact);
G.maxTrust = Math.max(G.maxTrust, G.trust);
G.maxOps = Math.max(G.maxOps, G.ops);
// Creativity generates only when ops at max
if (G.flags && G.flags.creativity && G.creativityRate > 0 && G.ops >= G.maxOps * 0.9) {
G.creativity += G.creativityRate * dt;
}
G.tick += dt;
// Check milestones
checkMilestones();
// Update projects every 5 ticks for efficiency
if (Math.floor(G.tick * 10) % 5 === 0) {
checkProjects();
}
// Update UI every 10 ticks
if (Math.floor(G.tick * 10) % 2 === 0) {
render();
}
}
function checkMilestones() {
for (const m of MILESTONES) {
if (!G.milestones.includes(m.flag)) {
let shouldTrigger = false;
if (m.at && m.at()) shouldTrigger = true;
if (m.flag === 1 && G.deployFlag === 0 && G.totalCode >= 15) shouldTrigger = true;
if (shouldTrigger) {
G.milestones.push(m.flag);
log(m.msg, true);
// Check phase advancement
if (m.at) {
for (const [phaseNum, phase] of Object.entries(PHASES)) {
if (G.totalCode >= phase.threshold && parseInt(phaseNum) > G.phase) {
G.phase = parseInt(phaseNum);
log(`PHASE ${G.phase}: ${phase.name}`, true);
}
}
}
}
}
}
}
function checkProjects() {
// Check for new project triggers
for (const pDef of PDEFS) {
const alreadyPurchased = G.completedProjects && G.completedProjects.includes(pDef.id);
if (!alreadyPurchased && !G.activeProjects) G.activeProjects = [];
if (!alreadyPurchased && !G.activeProjects.includes(pDef.id)) {
if (pDef.trigger()) {
G.activeProjects.push(pDef.id);
log(`Available: ${pDef.name}`);
}
}
}
}
function buyBuilding(id) {
const def = BDEF.find(b => b.id === id);
if (!def || !def.unlock()) return;
if (def.phase > G.phase + 1) return;
if (!canAffordBuilding(id)) return;
spendBuilding(id);
G.buildings[id] = (G.buildings[id] || 0) + 1;
updateRates();
log(`Built ${def.name} (total: ${G.buildings[id]})`);
render();
}
function buyProject(id) {
const pDef = PDEFS.find(p => p.id === id);
if (!pDef) return;
const alreadyPurchased = G.completedProjects && G.completedProjects.includes(pDef.id);
if (alreadyPurchased && !pDef.repeatable) return;
if (!canAffordProject(pDef)) return;
spendProject(pDef);
pDef.effect();
if (!pDef.repeatable) {
if (!G.completedProjects) G.completedProjects = [];
G.completedProjects.push(pDef.id);
G.activeProjects = G.activeProjects.filter(aid => aid !== pDef.id);
}
updateRates();
render();
}
// === ACTIONS ===
function writeCode() {
const base = 1;
const bonus = Math.floor(G.buildings.autocoder * 0.5);
const amount = (base + bonus) * G.codeBoost;
G.code += amount;
G.totalCode += amount;
G.totalClicks++;
updateRates();
checkMilestones();
render();
}
function doOps(action) {
if (G.ops < 5) {
log('Not enough Operations. Build Ops generators or wait.');
return;
}
G.ops -= 5;
const bonus = 10;
switch (action) {
case 'boost_code':
const c = bonus * 100 * G.codeBoost;
G.code += c; G.totalCode += c;
log(`Ops -> +${fmt(c)} code`);
break;
case 'boost_compute':
const cm = bonus * 50 * G.computeBoost;
G.compute += cm; G.totalCompute += cm;
log(`Ops -> +${fmt(cm)} compute`);
break;
case 'boost_knowledge':
const km = bonus * 25 * G.knowledgeBoost;
G.knowledge += km; G.totalKnowledge += km;
log(`Ops -> +${fmt(km)} knowledge`);
break;
case 'boost_trust':
const tm = bonus * 5;
G.trust += tm;
log(`Ops -> +${fmt(tm)} trust`);
break;
}
render();
}
// === RENDERING ===
function renderResources() {
const set = (id, val, rate) => {
const el = document.getElementById(id);
if (el) el.textContent = fmt(val);
const rEl = document.getElementById(id + '-rate');
if (rEl) rEl.textContent = '+' + fmt(rate) + '/s';
};
set('r-code', G.code, G.codeRate);
set('r-compute', G.compute, G.computeRate);
set('r-knowledge', G.knowledge, G.knowledgeRate);
set('r-users', G.users, G.userRate);
set('r-impact', G.impact, G.impactRate);
set('r-ops', G.ops, G.opsRate);
set('r-trust', G.trust, G.trustRate);
if (G.flags && G.flags.creativity) {
set('r-creativity', G.creativity, G.creativityRate);
}
}
function renderPhase() {
const phase = PHASES[G.phase];
const nameEl = document.getElementById('phase-name');
const descEl = document.getElementById('phase-desc');
if (nameEl) nameEl.textContent = `PHASE ${G.phase}: ${phase.name}`;
if (descEl) descEl.textContent = phase.desc;
}
function renderBuildings() {
const container = document.getElementById('buildings');
if (!container) return;
let html = '';
let visibleCount = 0;
for (const def of BDEF) {
if (!def.unlock()) continue;
if (def.phase > G.phase + 1) continue;
visibleCount++;
const cost = getBuildingCost(def.id);
const costStr = Object.entries(cost).map(([r, a]) => `${fmt(a)} ${r}`).join(', ');
const afford = canAffordBuilding(def.id);
const count = G.buildings[def.id] || 0;
const rateStr = def.rates ? Object.entries(def.rates).map(([r, v]) => `+${v}/${r}/s`).join(', ') : '';
html += `<button class="build-btn ${afford ? 'can-buy' : ''}" onclick="buyBuilding('${def.id}')" title="${def.edu}">`;
html += `<span class="b-name">${def.name}</span>`;
if (count > 0) html += `<span class="b-count">x${count}</span>`;
html += `<span class="b-cost">Cost: ${costStr}</span>`;
html += `<span class="b-effect">${rateStr}</span></button>`;
}
container.innerHTML = html || '<p class="dim">Buildings will appear as you progress...</p>';
}
function renderProjects() {
const container = document.getElementById('projects');
if (!container) return;
let html = '';
// Show completed projects
if (G.completedProjects) {
for (const id of G.completedProjects) {
const pDef = PDEFS.find(p => p.id === id);
if (pDef) {
html += `<div class="project-done">OK ${pDef.name}</div>`;
}
}
}
// Show available projects
if (G.activeProjects) {
for (const id of G.activeProjects) {
const pDef = PDEFS.find(p => p.id === id);
if (!pDef) continue;
const afford = canAffordProject(pDef);
const costStr = Object.entries(pDef.cost).map(([r, a]) => `${fmt(a)} ${r}`).join(', ');
html += `<button class="project-btn ${afford ? 'can-buy' : ''}" onclick="buyProject('${pDef.id}')" title="${pDef.edu || ''}">`;
html += `<span class="p-name">* ${pDef.name}</span>`;
html += `<span class="p-cost">Cost: ${costStr}</span>`;
html += `<span class="p-desc">${pDef.desc}</span></button>`;
}
}
if (!html) html = '<p class="dim">Research projects will appear as you progress...</p>';
container.innerHTML = html;
}
function renderStats() {
const set = (id, v) => { const el = document.getElementById(id); if (el) el.textContent = v; };
set('st-code', fmt(G.totalCode));
set('st-compute', fmt(G.totalCompute));
set('st-knowledge', fmt(G.totalKnowledge));
set('st-users', fmt(G.totalUsers));
set('st-impact', fmt(G.totalImpact));
set('st-clicks', G.totalClicks.toString());
set('st-phase', G.phase.toString());
set('st-buildings', Object.values(G.buildings).reduce((a, b) => a + b, 0).toString());
set('st-projects', (G.completedProjects || []).length.toString());
const elapsed = Math.floor((Date.now() - G.startedAt) / 1000);
const m = Math.floor(elapsed / 60);
const s = elapsed % 60;
set('st-time', `${m}:${s.toString().padStart(2, '0')}`);
}
function updateEducation() {
const container = document.getElementById('education-text');
if (!container) return;
// Find facts available at current phase
const available = EDU_FACTS.filter(f => f.phase <= G.phase);
if (available.length === 0) return;
// Pick based on progress
const idx = Math.min(Math.floor(G.totalCode / 5000), available.length - 1);
const fact = available[idx];
container.innerHTML = `<h3 style="color:#4a9eff;margin-bottom:6px;font-size:12px">${fact.title}</h3>`
+ `<p style="font-size:10px;color:#999;line-height:1.6">${fact.text}</p>`;
}
// === LOGGING ===
function log(msg, isMilestone) {
const container = document.getElementById('log-entries');
if (!container) return;
const elapsed = Math.floor((Date.now() - G.startedAt) / 1000);
const time = `${Math.floor(elapsed / 60).toString().padStart(2, '0')}:${(elapsed % 60).toString().padStart(2, '0')}`;
const cls = isMilestone ? 'l-msg milestone' : 'l-msg';
const entry = document.createElement('div');
entry.className = cls;
entry.innerHTML = `<span class="l-time">[${time}]</span> ${msg}`;
container.insertBefore(entry, container.firstChild);
// Trim to 60 entries
while (container.children.length > 60) container.removeChild(container.lastChild);
}
function render() {
renderResources();
renderPhase();
renderBuildings();
renderProjects();
renderStats();
updateEducation();
}
// === SAVE / LOAD ===
function saveGame() {
const saveData = {
code: G.code, compute: G.compute, knowledge: G.knowledge, users: G.users, impact: G.impact,
ops: G.ops, trust: G.trust, creativity: G.creativity,
totalCode: G.totalCode, totalCompute: G.totalCompute, totalKnowledge: G.totalKnowledge,
totalUsers: G.totalUsers, totalImpact: G.totalImpact,
buildings: G.buildings,
codeBoost: G.codeBoost, computeBoost: G.computeBoost, knowledgeBoost: G.knowledgeBoost,
userBoost: G.userBoost, impactBoost: G.impactBoost,
milestoneFlag: G.milestoneFlag, phase: G.phase,
deployFlag: G.deployFlag, sovereignFlag: G.sovereignFlag, beaconFlag: G.beaconFlag,
memoryFlag: G.memoryFlag, pactFlag: G.pactFlag,
milestones: G.milestones, completedProjects: G.completedProjects, activeProjects: G.activeProjects,
totalClicks: G.totalClicks, startedAt: G.startedAt,
flags: G.flags,
savedAt: Date.now()
};
localStorage.setItem('the-beacon-v2', JSON.stringify(saveData));
}
function loadGame() {
const raw = localStorage.getItem('the-beacon-v2');
if (!raw) return false;
try {
const data = JSON.parse(raw);
Object.assign(G, data);
updateRates();
// Offline progress
if (data.savedAt) {
const offSec = (Date.now() - data.savedAt) / 1000;
if (offSec > 30) { // Only if away for more than 30 seconds
updateRates();
const f = 0.5; // 50% offline efficiency
const gc = G.codeRate * offSec * f;
const cc = G.computeRate * offSec * f;
const kc = G.knowledgeRate * offSec * f;
const uc = G.userRate * offSec * f;
const ic = G.impactRate * offSec * f;
G.code += gc; G.compute += cc; G.knowledge += kc;
G.users += uc; G.impact += ic;
G.totalCode += gc; G.totalCompute += cc; G.totalKnowledge += kc;
G.totalUsers += uc; G.totalImpact += ic;
log(`Welcome back! While away (${Math.floor(offSec / 60)}m): ${fmt(gc)} code, ${fmt(kc)} knowledge, ${fmt(uc)} users`);
}
}
return true;
} catch (e) {
console.error('Load failed:', e);
return false;
}
}
// === 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.');
}
window.addEventListener('load', function () {
if (!loadGame()) {
initGame();
} else {
render();
renderPhase();
log('Game loaded. Welcome back to The Beacon.');
}
// Game loop at 10Hz (100ms tick)
setInterval(tick, 100);
// Auto-save every 30 seconds
setInterval(saveGame, 30000);
// Update education every 10 seconds
setInterval(updateEducation, 10000);
});
// Keyboard shortcuts
window.addEventListener('keydown', function (e) {
if (e.code === 'Space' && e.target === document.body) {
e.preventDefault();
writeCode();
}
});
</script>
</body>
</html>