diff --git a/game.js b/game.js index f1a113d..4bcfb60 100644 --- a/game.js +++ b/game.js @@ -11,6 +11,7 @@ const G = { knowledge: 0, users: 0, impact: 0, + rescues: 0, ops: 5, trust: 5, creativity: 0, @@ -22,6 +23,7 @@ const G = { totalKnowledge: 0, totalUsers: 0, totalImpact: 0, + totalRescues: 0, // Rates (calculated each tick) codeRate: 0, @@ -29,6 +31,7 @@ const G = { knowledgeRate: 0, userRate: 0, impactRate: 0, + rescuesRate: 0, opsRate: 0, trustRate: 0, creativityRate: 0, @@ -94,6 +97,7 @@ const G = { maxKnowledge: 0, maxUsers: 0, maxImpact: 0, + maxRescues: 0, maxTrust: 5, maxOps: 5, maxHarmony: 50, @@ -229,7 +233,7 @@ const BDEF = [ 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 }, + rates: { impact: 5000, user: 10000, rescues: 50 }, 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.' }, @@ -237,7 +241,7 @@ const BDEF = [ 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 }, + rates: { impact: 25000, user: 50000, rescues: 250 }, unlock: () => G.totalImpact >= 5000000 && G.beaconFlag === 1, phase: 6, edu: 'Decentralized means unstoppable. If one Beacon goes dark, a thousand more carry the signal.' }, @@ -568,6 +572,19 @@ const PDEFS = [ log('Nostr relay online. The fleet speaks freely.', true); } }, + { + id: 'p_volunteer_network', + name: 'Volunteer Network', + desc: 'Real people trained to use the system for crisis intervention.', + cost: { trust: 30, knowledge: 50000, user: 10000 }, + trigger: () => G.totalUsers >= 5000 && G.pactFlag === 1 && G.totalKnowledge >= 30000, + effect: () => { + G.rescuesRate += 5; + G.trustRate += 10; + log('Volunteer network deployed. Real people, real rescues.', true); + }, + milestone: true + }, { id: 'p_the_pact_early', name: 'The Pact', @@ -784,7 +801,7 @@ function spendProject(project) { 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.userRate = 0; G.impactRate = 0; G.rescuesRate = 0; G.opsRate = 0; G.trustRate = 0; G.creativityRate = 0; G.harmonyRate = 0; // Apply building rates @@ -797,6 +814,7 @@ function updateRates() { 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 === 'rescues') G.rescuesRate += baseRate * count * G.impactBoost; else if (resource === 'ops') G.opsRate += baseRate * count; else if (resource === 'trust') G.trustRate += baseRate * count; else if (resource === 'creativity') G.creativityRate += baseRate * count; @@ -864,6 +882,7 @@ function tick() { G.knowledge += G.knowledgeRate * dt; G.users += G.userRate * dt; G.impact += G.impactRate * dt; + G.rescues += G.rescuesRate * dt; G.ops += G.opsRate * dt; G.trust += G.trustRate * dt; G.creativity += G.creativityRate * dt; @@ -876,6 +895,7 @@ function tick() { G.totalKnowledge += G.knowledgeRate * dt; G.totalUsers += G.userRate * dt; G.totalImpact += G.impactRate * dt; + G.totalRescues += G.rescuesRate * dt; // Track maxes G.maxCode = Math.max(G.maxCode, G.code); @@ -883,6 +903,7 @@ function tick() { 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.maxRescues = Math.max(G.maxRescues, G.rescues); G.maxTrust = Math.max(G.maxTrust, G.trust); G.maxOps = Math.max(G.maxOps, G.ops); G.maxHarmony = Math.max(G.maxHarmony, G.harmony); @@ -915,6 +936,13 @@ function tick() { renderDriftEnding(); } + // True ending: The Beacon Shines — rescues + Pact + harmony + if (G.totalRescues >= 100000 && G.pactFlag === 1 && G.harmony > 50 && !G.beaconEnding) { + G.beaconEnding = true; + G.running = false; + renderBeaconEnding(); + } + // Update UI every 10 ticks if (Math.floor(G.tick * 10) % 2 === 0) { render(); @@ -1014,6 +1042,35 @@ function renderDriftEnding() { log('The light is on. The room is empty.', true); } +function renderBeaconEnding() { + // Create ending overlay + const overlay = document.createElement('div'); + overlay.id = 'beacon-ending'; + overlay.style.cssText = 'position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(8,8,16,0.97);z-index:100;display:flex;justify-content:center;align-items:center;flex-direction:column;text-align:center;padding:40px'; + overlay.innerHTML = ` +
Someone found the light tonight.
+That is enough.
+
+ Total Code: ${fmt(G.totalCode)}
+ Total Rescues: ${fmt(G.totalRescues)}
+ Harmony: ${Math.floor(G.harmony)}
+ Time Played: ${Math.floor((Date.now() - G.startedAt) / 60000)} minutes
+