Back to Sickman Survival
SOURCE / PINNED RELEASE

Made of little things.

Sickman Survival

Release
7335c9fdf0a8…
Author-recorded commit
cbd2eeafa70d…
License
Check the original source
Author’s source reference
nostr://npub1ye5ptcxfyyxl5vjvdjar2ua3f0hynkjzpx552mu5snj3qmx5pzjscpknpr/wss%3A%2F%2Fgit.napplet.soy%2F/n-8804151df7f

The hash-verified playable HTML, which may contain bundled or minified code. This view does not execute it.

index.html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
    <title>Sickman Survival</title>
    <script type="module" crossorigin>var Ds=Object.defineProperty;var Gs=(i,t,e)=>t in i?Ds(i,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):i[t]=e;var g=(i,t,e)=>Gs(i,typeof t!="symbol"?t+"":t,e);function js(){const i=new Map;function t(s,o){if(i.has(s))throw new Error(`NAP domain "${s}" is already registered`);i.set(s,o)}function e(s){const o=s.type.indexOf(".");if(o<=0)return!1;const a=s.type.slice(0,o),c=i.get(a);return c?(c(s),!0):!1}function n(){return Array.from(i.keys())}return{registerNap:t,dispatch:e,getRegisteredDomains:n}}var Vs=js(),Ns=Vs.registerNap,fs="storage";Ns(fs,i=>{});function Hs(){const i=window;if(!i.napplet)throw new Error("window.napplet is unavailable -- runtime did not inject the napplet namespace");return i.napplet}function N(i){const e=Hs()[i];if(!e)throw new Error(`window.napplet.${String(i)} is unavailable -- runtime did not inject this domain`);return e}var oe={getItem(i){return N("storage").getItem(i)},setItem(i,t){return N("storage").setItem(i,t)},removeItem(i){return N("storage").removeItem(i)},keys(){return N("storage").keys()},instance:{getItem(i){return N("storage").instance.getItem(i)},setItem(i,t){return N("storage").instance.setItem(i,t)},removeItem(i){return N("storage").instance.removeItem(i)},keys(){return N("storage").instance.keys()}}},he={get(){return N("config").get()},subscribe(i){return N("config").subscribe(i)},openSettings(i){N("config").openSettings(i)},registerSchema(i,t){return N("config").registerSchema(i,t)},onSchemaError(i){return N("config").onSchemaError(i)},get schema(){return N("config").schema}};const Fs=5;class qs{constructor(){g(this,"ctx",null);g(this,"master");g(this,"sfx");g(this,"reverbSend");g(this,"surfaceBed");g(this,"caveBed");g(this,"windFilter");g(this,"windGain");g(this,"stormGain");g(this,"digGain");g(this,"noise");g(this,"brown");g(this,"volume",.8);g(this,"muted",!1);g(this,"paused",!1);g(this,"under",0);g(this,"storm",0);g(this,"time",0);g(this,"gust",0);g(this,"nextDrip",1);g(this,"nextBird",2);g(this,"nextThunder",6);g(this,"nextCreak",8);g(this,"whistles",0);g(this,"listener",{x:0,y:0,depth:0});g(this,"listeners",[this.listener]);g(this,"terrainDepth",()=>0)}get isMuted(){return this.muted}unlock(){if(!this.ctx){const t=Ys();if(!t)return;try{this.ctx=new t({latencyHint:"interactive"})}catch{return}this.build(this.ctx)}this.ctx.state==="suspended"&&!this.paused&&this.ctx.resume().catch(()=>{})}setVolume(t){this.volume=Math.max(0,Math.min(1,t)),this.applyMaster()}setMuted(t){this.muted=t,this.applyMaster()}setPaused(t){this.paused=t,this.ctx&&(t?this.ctx.suspend().catch(()=>{}):this.ctx.resume().catch(()=>{}))}update(t,e){const n=t.terrain;this.terrainDepth=(h,f)=>n.depthAt(h,f),this.listeners=t.players.map(h=>{const f=t.focusX(h.slot),u=t.focusY(h.slot);return{x:f,y:u,depth:n.depthAt(f,u)}}),this.listeners.length===0&&(this.listeners=[{x:t.focusX(),y:t.focusY(),depth:0}]),this.listener=this.listeners[0];const s=this.ctx;if(!s||this.paused||e<=0)return;this.time+=e;let o=0;for(const h of this.listeners)o+=Z((h.depth-4)/22,0,1)/this.listeners.length;this.under+=(o-this.under)*(1-Math.exp(-e*2)),this.storm=Math.min(1,t.stormTime()/150);const a=s.currentTime,c=1-this.under;this.gust=Math.max(0,this.gust-e*.35),Math.random()<e*(.08+this.storm*.25)&&(this.gust=Math.random()*.8+.2);const r=.5+.5*Math.sin(this.time*.37)*Math.sin(this.time*.11+1);this.windGain.gain.setTargetAtTime((.05+r*.06+this.gust*.12+this.storm*.1)*c,a,.4),this.windFilter.frequency.setTargetAtTime(260+r*260+this.gust*600+this.storm*300,a,.5),this.stormGain.gain.setTargetAtTime((.02+this.storm*.22)*(c*.8+.2),a,1),this.surfaceBed.gain.setTargetAtTime(.25+c*.75,a,.3),this.caveBed.gain.setTargetAtTime(this.under,a,.4),this.reverbSend.gain.setTargetAtTime(this.under*.55,a,.4);let l=0;for(const h of t.moles)h.state==="burrow"&&(l=Math.max(l,1-this.distance(h.x,h.y)/170));this.digGain.gain.setTargetAtTime(l*(.6+Math.random()*.6)*.22,a,.05),(this.nextBird-=e)<=0&&(this.nextBird=2+Math.random()*6,this.storm<.45&&c>.6&&this.bird(1-this.storm*2)),(this.nextThunder-=e)<=0&&(this.nextThunder=14-this.storm*10+Math.random()*8,this.storm>.08&&this.thunder(.4+this.storm*.6)),(this.nextDrip-=e)<=0&&(this.nextDrip=.5+Math.random()*2.2,this.under>.15&&this.drip()),(this.nextCreak-=e)<=0&&(this.nextCreak=7+Math.random()*12,this.under>.4&&this.creak())}jump(){const t=this.live();if(!t)return;const e=t.currentTime,n=1+(Math.random()-.5)*.12,s=this.osc("triangle",260*n,e);s.frequency.exponentialRampToValueAtTime(560*n,e+.09),this.envelope(s,e,.004,.11,.09),this.noiseHit(e,.05,1800,"bandpass",.05)}land(t){const e=this.live();if(!e)return;const n=e.currentTime,s=Z(t/900,.15,1);this.noiseHit(n,.05+s*.08,500+s*400,"lowpass",.14*s+.04);const o=this.osc("sine",120,n);o.frequency.exponentialRampToValueAtTime(45,n+.12),this.envelope(o,n,.003,.18*s,.14)}footstep(){const t=this.live();if(!t)return;const e=t.currentTime,n=this.under>.5;this.noiseHit(e,.035,n?900:1400+Math.random()*900,"bandpass",.035)}bounce(){const t=this.live();if(!t)return;const e=t.currentTime,n=this.osc("sine",150,e);n.frequency.exponentialRampToValueAtTime(520,e+.16),n.frequency.exponentialRampToValueAtTime(380,e+.32);const s=this.osc("sine",18,e),o=t.createGain();o.gain.value=40,s.connect(o).connect(n.frequency),s.start(e),s.stop(e+.4),this.envelope(n,e,.005,.2,.34)}meteor(t){const e=this.live();if(!e||this.whistles>=Fs)return;const n=t.x+t.vx*t.eta,s=Math.abs(n-this.nearest(n,0,!0).x);if(s>900)return;const o=e.currentTime,a=Z(t.eta,.3,4),c=(1-s/900)**2*.16,r=this.noiseSource(o,a+.1),l=e.createBiquadFilter();l.type="bandpass",l.Q.value=9,l.frequency.setValueAtTime(2600+Math.random()*600,o),l.frequency.exponentialRampToValueAtTime(500,o+a);const h=e.createGain();h.gain.setValueAtTime(1e-4,o),h.gain.exponentialRampToValueAtTime(c*this.occlusion(n,-100),o+a*.85),h.gain.exponentialRampToValueAtTime(1e-4,o+a+.08),r.connect(l).connect(h).connect(this.panner(n)).connect(this.sfx),this.whistles++,r.onended=()=>this.whistles--}explosion(t){const e=this.live();if(!e)return;const n=e.currentTime,s=this.distance(t.x,t.y),o=Z(t.radius/40,.5,1.4),a=Z(1.25/(1+s/220),0,1);if(a<.02)return;const c=this.occlusion(t.x,t.y),r=Z(9e3/(1+s/140),300,9e3)*(c<1?.35:1),l=e.createBiquadFilter();l.type="lowpass",l.frequency.value=r,l.connect(this.panner(t.x)).connect(this.sfx);const h=this.osc("sine",95/o,n);h.frequency.exponentialRampToValueAtTime(28,n+.5*o),this.envelope(h,n,.005,.9*a,.7*o,l);const f=this.noiseSource(n,1.8*o),u=e.createBiquadFilter();u.type="lowpass",u.frequency.setValueAtTime(4200,n),u.frequency.exponentialRampToValueAtTime(140,n+1.4*o);const p=e.createGain();p.gain.setValueAtTime(1e-4,n),p.gain.exponentialRampToValueAtTime(.75*a,n+.012),p.gain.exponentialRampToValueAtTime(1e-4,n+1.7*o),f.connect(u).connect(p).connect(l);const m=this.noiseSource(n,.12),b=e.createBiquadFilter();b.type="highpass",b.frequency.value=1800;const v=e.createGain();v.gain.setValueAtTime(.5*a,n),v.gain.exponentialRampToValueAtTime(1e-4,n+.1),m.connect(b).connect(v).connect(l);for(let A=Math.round(4+o*6);A>0;A--){const x=n+.25+Math.random()*.9*o;this.noiseHit(x,.02+Math.random()*.03,700+Math.random()*2400,"bandpass",.12*a*Math.random(),l)}if(t.proximity>.75){const A=this.osc("sine",3400+Math.random()*300,n);this.envelope(A,n+.05,.08,.025*t.proximity,1.8)}}moleSurface(t){const e=this.live(),n=this.near(t.x,t.y,320);if(!e||n<=0)return;const s=e.currentTime,o=this.panner(t.x);o.connect(this.sfx),this.noiseHit(s,.18,380,"lowpass",.3*n,o),this.noiseHit(s+.03,.08,1200,"bandpass",.12*n,o);const a=this.osc("sine",1300,s+.08);a.frequency.exponentialRampToValueAtTime(2100,s+.16),a.frequency.exponentialRampToValueAtTime(1500,s+.22),this.envelope(a,s+.08,.01,.06*n,.15,o)}moleDive(t){const e=this.live(),n=this.near(t.x,t.y,260);if(!e||n<=0)return;const s=this.panner(t.x);s.connect(this.sfx),this.noiseHit(e.currentTime,.22,300,"lowpass",.22*n,s)}moleArmed(t){const e=this.live(),n=this.near(t.x,t.y,420);if(!e||n<=0)return;const s=e.currentTime,o=Math.max(.05,t.fuse),a=this.panner(t.x);a.connect(this.sfx);const c=this.noiseSource(s,o),r=e.createBiquadFilter();r.type="highpass",r.frequency.setValueAtTime(3e3,s),r.frequency.linearRampToValueAtTime(6e3,s+o);const l=e.createGain();if(l.gain.setValueAtTime(.03*n,s),l.gain.linearRampToValueAtTime(.11*n,s+o),c.connect(r).connect(l).connect(a),!(o<.3))for(let h=0,f=.2;h<o-.04;h+=f,f=Math.max(.05,f*.72)){const u=this.osc("square",880+h/o*700,s+h);this.envelope(u,s+h,.003,.09*n,.05,a)}}death(){const t=this.live();if(!t)return;const e=t.currentTime,n=this.osc("triangle",420,e+.05);n.frequency.exponentialRampToValueAtTime(90,e+.6),this.envelope(n,e+.05,.01,.07,.6)}click(){const t=this.live();if(!t)return;const e=t.currentTime,n=this.osc("square",660,e);n.frequency.exponentialRampToValueAtTime(990,e+.04),this.envelope(n,e,.002,.04,.05)}bird(t){const e=this.live();if(!e)return;const n=e.currentTime,s=this.panner(this.listener.x+(Math.random()-.5)*600);s.connect(this.surfaceBed);const o=2400+Math.random()*1400;for(let a=0,c=2+Math.floor(Math.random()*3);a<c;a++){const r=n+a*(.09+Math.random()*.05),l=this.osc("sine",o,r);l.frequency.exponentialRampToValueAtTime(o*(1.3+Math.random()*.3),r+.05),this.envelope(l,r,.005,.025*t,.07,s)}}thunder(t){const e=this.live();if(!e)return;const n=e.currentTime,s=2.5+Math.random()*2,o=this.noiseSource(n,s,this.brown),a=e.createBiquadFilter();a.type="lowpass",a.frequency.value=160+Math.random()*120;const c=e.createGain();c.gain.setValueAtTime(1e-4,n),c.gain.exponentialRampToValueAtTime(.35*t,n+.3+Math.random()*.5),c.gain.exponentialRampToValueAtTime(1e-4,n+s),o.connect(a).connect(c).connect(this.surfaceBed)}drip(){const t=this.live();if(!t)return;const e=t.currentTime,n=this.panner(this.listener.x+(Math.random()-.5)*500);n.connect(this.caveBed);const s=1300+Math.random()*1500,o=this.osc("sine",s,e);o.frequency.exponentialRampToValueAtTime(s*.55,e+.08),this.envelope(o,e,.002,.06+Math.random()*.05,.12,n)}creak(){const t=this.live();if(!t)return;const e=t.currentTime,n=.8+Math.random()*.8,s=this.noiseSource(e,n,this.brown),o=t.createBiquadFilter();o.type="bandpass",o.Q.value=4,o.frequency.setValueAtTime(140+Math.random()*120,e),o.frequency.linearRampToValueAtTime(90,e+n);const a=t.createGain();a.gain.setValueAtTime(1e-4,e),a.gain.exponentialRampToValueAtTime(.5,e+n*.3),a.gain.exponentialRampToValueAtTime(1e-4,e+n),s.connect(o).connect(a).connect(this.caveBed);for(let c=0;c<5;c++)this.noiseHit(e+n*(.4+Math.random()*.8),.02,1500+Math.random()*1500,"bandpass",.03*Math.random(),this.caveBed)}build(t){this.noise=Ne(t,2,!1),this.brown=Ne(t,4,!0);const e=t.createDynamicsCompressor();e.threshold.value=-14,e.ratio.value=6,e.attack.value=.003,e.release.value=.25,this.master=t.createGain(),this.master.connect(e).connect(t.destination),this.applyMaster();const n=t.createConvolver();n.buffer=$s(t,2.4),n.connect(this.master),this.reverbSend=t.createGain(),this.reverbSend.gain.value=0,this.reverbSend.connect(n),this.sfx=t.createGain(),this.sfx.connect(this.master),this.sfx.connect(this.reverbSend),this.surfaceBed=t.createGain(),this.surfaceBed.connect(this.master);const s=this.loop(this.noise);this.windFilter=t.createBiquadFilter(),this.windFilter.type="bandpass",this.windFilter.Q.value=.8,this.windFilter.frequency.value=400,this.windGain=t.createGain(),this.windGain.gain.value=0,s.connect(this.windFilter).connect(this.windGain).connect(this.surfaceBed);const o=this.loop(this.brown),a=t.createBiquadFilter();a.type="lowpass",a.frequency.value=90,this.stormGain=t.createGain(),this.stormGain.gain.value=0,o.connect(a).connect(this.stormGain).connect(this.surfaceBed),this.caveBed=t.createGain(),this.caveBed.gain.value=0,this.caveBed.connect(this.master);const c=t.createGain();c.gain.value=.7,this.caveBed.connect(c).connect(n);const r=this.loop(this.brown),l=t.createBiquadFilter();l.type="lowpass",l.frequency.value=180;const h=t.createGain();h.gain.value=.22,r.connect(l).connect(h).connect(this.caveBed);const f=this.loop(this.noise),u=t.createBiquadFilter();u.type="bandpass",u.frequency.value=700,u.Q.value=1.4,this.digGain=t.createGain(),this.digGain.gain.value=0,f.connect(u).connect(this.digGain).connect(this.sfx)}applyMaster(){if(!this.ctx)return;const t=this.muted?0:this.volume*.9;this.master.gain.setTargetAtTime(t,this.ctx.currentTime,.05)}live(){const t=this.ctx;return t&&t.state==="running"&&!this.muted&&this.volume>0?t:null}loop(t){const e=this.ctx.createBufferSource();return e.buffer=t,e.loop=!0,e.start(0,Math.random()*t.duration),e}noiseSource(t,e,n=this.noise){const s=this.ctx.createBufferSource();return s.buffer=n,s.loop=!0,s.start(t,Math.random()*n.duration),s.stop(t+e+.05),s}osc(t,e,n){const s=this.ctx.createOscillator();return s.type=t,s.frequency.setValueAtTime(e,n),s}envelope(t,e,n,s,o,a=this.sfx){const c=this.ctx.createGain();c.gain.setValueAtTime(1e-4,e),c.gain.exponentialRampToValueAtTime(Math.max(2e-4,s),e+n),c.gain.exponentialRampToValueAtTime(1e-4,e+n+o),t.connect(c).connect(a),t.start(e),t.stop(e+n+o+.05)}noiseHit(t,e,n,s,o,a=this.sfx){const c=this.ctx,r=this.noiseSource(t,e),l=c.createBiquadFilter();l.type=s,l.frequency.value=n;const h=c.createGain();h.gain.setValueAtTime(Math.max(2e-4,o),t),h.gain.exponentialRampToValueAtTime(1e-4,t+e),r.connect(l).connect(h).connect(a)}panner(t){const e=this.ctx,n=this.listeners.length>1?.4:.8,s=Z((t-this.nearest(t,0,!0).x)/320,-1,1)*n;if(typeof e.createStereoPanner!="function")return e.createGain();const o=e.createStereoPanner();return o.pan.value=s,o}distance(t,e){const n=this.nearest(t,e);return Math.hypot(t-n.x,e-n.y)}nearest(t,e,n=!1){let s=this.listener,o=1/0;for(const a of this.listeners){const c=n?Math.abs(t-a.x):Math.hypot(t-a.x,e-a.y);c<o&&(s=a,o=c)}return s}near(t,e,n){return Z(1-this.distance(t,e)/n,0,1)**1.5}occlusion(t,e){const n=this.terrainDepth(t,e)>6,s=this.nearest(t,e).depth>6;return n===s?1:.45}}function Ys(){const i=window;return i.AudioContext??i.webkitAudioContext??null}function Ne(i,t,e){const n=Math.floor(i.sampleRate*t),s=i.createBuffer(1,n,i.sampleRate),o=s.getChannelData(0);let a=0;for(let c=0;c<n;c++){const r=Math.random()*2-1;e?(a=(a+.02*r)/1.02,o[c]=a*3.5):o[c]=r}return s}function $s(i,t){const e=Math.floor(i.sampleRate*t),n=i.createBuffer(2,e,i.sampleRate);for(let s=0;s<2;s++){const o=n.getChannelData(s);for(let a=0;a<e;a++)o[a]=(Math.random()*2-1)*(1-a/e)**3}return n}function Z(i,t,e){return Math.max(t,Math.min(e,i))}function Ws(i,t){return!!(i!=null&&i[t])}function us(i){return Ws(window.napplet,i)}function Ut(i){let t=i>>>0;const e=()=>{t=t+1831565813>>>0;let n=t;return n=Math.imul(n^n>>>15,n|1),n^=n+Math.imul(n^n>>>7,n|61),((n^n>>>14)>>>0)/4294967296};return{next:e,range:(n,s)=>n+e()*(s-n),int:(n,s)=>Math.floor(n+e()*(s-n+1)),chance:n=>e()<n,sign:()=>e()<.5?-1:1}}const T=4,Xs=1200,zs=260,Ks=160,G=0,ft=1,$=2,Q=3,J=4,z=5,K=6,Qt=7,St=8,Ot=9,ut=10,ge=0,ds=1,ve=2,Ie=3,st=4,ps=5,Jt=6,H=7,It=8,_e=9,ct=0,I=1,Tt=2,Y=new Uint8Array(16);Y[ft]=I;Y[$]=I;Y[Q]=I;Y[J]=I;Y[z]=I;Y[Ot]=I;Y[ut]=I;Y[K]=Tt;Y[Qt]=Tt;Y[St]=Tt;const ie=new Float32Array(16).fill(1);ie[Q]=.8;ie[z]=.9;ie[J]=0;class Us{constructor(t,e,n=1){g(this,"cols");g(this,"rows");g(this,"fg");g(this,"bg");g(this,"noise");g(this,"scorch");g(this,"surface");g(this,"glows",[]);g(this,"dirty",null);this.cols=t,this.rows=e,this.fg=new Uint8Array(t*e),this.bg=new Uint8Array(t*e),this.noise=new Uint8Array(t*e),this.scorch=new Uint8Array(t*e),this.surface=new Int16Array(t).fill(e);const s=Ut(n^2654435769);for(let o=0;o<this.noise.length;o++)this.noise[o]=Math.floor(s.next()*256)}get width(){return this.cols*T}get height(){return this.rows*T}inBounds(t,e){return t>=0&&e>=0&&t<this.cols&&e<this.rows}fgAt(t,e){return t<0||t>=this.cols||e>=this.rows?J:e<0?G:this.fg[e*this.cols+t]}set(t,e,n){this.inBounds(t,e)&&(this.fg[e*this.cols+t]=n)}setBg(t,e,n){this.inBounds(t,e)&&(this.bg[e*this.cols+t]=n)}collisionAt(t,e){return Y[this.fgAt(t,e)]}collisionAtPoint(t,e){return this.collisionAt(Math.floor(t/T),Math.floor(e/T))}depthAt(t,e){const n=Math.max(0,Math.min(this.cols-1,Math.floor(t/T)));return e/T-this.surface[n]}surfaceRow(t){for(let e=0;e<this.rows;e++)if(this.collisionAt(t,e)!==ct)return e;return this.rows}markDirty(t,e,n,s){const o={x0:Math.max(0,t),y0:Math.max(0,e),x1:Math.min(this.cols-1,n),y1:Math.min(this.rows-1,s)};if(!this.dirty){this.dirty=o;return}this.dirty.x0=Math.min(this.dirty.x0,o.x0),this.dirty.y0=Math.min(this.dirty.y0,o.y0),this.dirty.x1=Math.max(this.dirty.x1,o.x1),this.dirty.y1=Math.max(this.dirty.y1,o.y1)}carve(t,e,n){const s=n*1.4,o=Math.floor((t-s)/T),a=Math.floor((t+s)/T),c=Math.floor((e-s)/T),r=Math.floor((e+s)/T);let l=0;const h=[];for(let f=c;f<=r;f++)for(let u=o;u<=a;u++){if(!this.inBounds(u,f))continue;const p=f*this.cols+u,m=(u+.5)*T-t,b=(f+.5)*T-e,v=Math.hypot(m,b),A=n*(.92+this.noise[p]/255*.16),x=this.fg[p];if(x!==G&&v<A*ie[x]&&(this.fg[p]=G,l++,h.length<48&&(l&1)===0&&h.push(x)),this.bg[p]!==ge&&v<A*.95&&(this.bg[p]=ge),v<s){const M=Math.min(1,Math.max(0,1-(v-n*.7)/(s-n*.7)));this.scorch[p]=Math.max(this.scorch[p],Math.round(M*235))}}return this.markDirty(o-1,c-1,a+1,r+1),{removed:l,sample:h}}}function Qs(i,t=Xs,e=zs){const n=Ut(i),s=new Us(t,e,i),o=Js(n,t,Math.min(e,Ks)),a=[],c=[],r=t/600;Zs(n,s,o),tn(n,s,o),s.surface.set(o);let l=0;for(let x=1;x<=t;x++)(x===t||Math.abs(o[x]-o[l])>2)&&(x-l>=fe+4&&a.push({x0:l,x1:x-1}),l=x);const h=new Uint8Array(t),f=(x,M,d)=>{for(let y=Math.max(0,x-d);y<=Math.min(t-1,M+d);y++)if(h[y])return!1;for(let y=Math.max(0,x);y<=Math.min(t-1,M);y++)h[y]=1;return!0},u=Math.floor(t/2);for(let x=u-5;x<=u+5;x++)h[x]=1;for(const x of cn(n,s,o,u,r)){for(let M=Math.max(0,x-8);M<=Math.min(t-1,x+8);M++)h[M]=1;c.push({kind:"cave-mouth",x0:x-5,x1:x+5})}const p=Math.round(6*r);let m=0;for(const x of a.sort(()=>n.next()-.5)){const M=n.int(fe,Math.min(en,x.x1-x.x0-2));if(M<fe)continue;const d=n.int(x.x0+1,x.x1-M-1);if(!(d<24||d+M>t-24||!f(d-be,d+M-1+be,2))&&(nn(n,s,o,d,M),c.push({kind:"building",x0:d,x1:d+M-1}),++m>=p))break}const b=Math.round(n.int(12,18)*r);for(let x=0,M=0;x<200*r&&M<b;x++){const d=n.int(22,t-23),y=s.surfaceRow(d);Math.abs(s.surfaceRow(d+1)-y)>1||s.fgAt(d,y)!==$||f(d-3,d+4,1)&&(dn(n,s,d,y),c.push({kind:"tree",x0:d-3,x1:d+4}),M++)}const v=Math.round(n.int(9,15)*r);for(let x=0,M=0;x<200*r&&M<v;x++){const d=n.int(22,t-23),y=s.surfaceRow(d);s.fgAt(d,y)===$&&f(d-2,d+2,0)&&(ms(n,s,d,y),c.push({kind:"mushroom",x0:d-2,x1:d+2}),M++)}for(let x=Math.round(n.int(6,10)*r);x>0;x--){const M=n.int(25,t-26),d=s.surfaceRow(M);h[M]||h[M+2]||s.fgAt(M,d)!==$||(n.chance(.55)?pn(n,s,M,d):mn(n,s,M,d))}for(let x=Math.round(n.int(3,6)*r);x>0;x--){const M=n.int(9,20),d=n.int(25,t-M-25);let y=e;for(let E=d;E<d+M;E++)y=Math.min(y,s.surfaceRow(E));const S=y-n.int(17,26);S<12||d<=u+6&&d+M>=u-6||(yn(n,s,d,S,M),c.push({kind:"island",x0:d,x1:d+M-1}))}const A=s.surfaceRow(u);for(let x=A-9;x<A;x++)for(let M=u-2;M<=u+2;M++)s.collisionAt(M,x)!==ct&&s.set(M,x,G);return s.dirty={x0:0,y0:0,x1:t-1,y1:e-1},{terrain:s,spawnX:(u+.5)*T,spawnY:s.surfaceRow(u)*T,landmarks:c}}function Js(i,t,e){const n=new Int16Array(t),s=Math.round(e*.4),o=Math.round(e*.74);let a=Math.round(e*.6),c=0;for(;c<t;){const r=i.int(16,52),l=i.next(),h=a;let f=a;l<.28?(a=lt(a+i.sign()*i.int(9,20),s,o),f=a):l<.6&&(f=lt(a+i.sign()*i.int(4,14),s,o));const u=l>.82?i.int(3,9):0;for(let p=0;p<r&&c<t;p++,c++){const m=p/r,b=l<.28?a:Math.round(h+(f-h)*m);n[c]=b-Math.round(Math.sin(m*Math.PI)*u)}a=f}for(let r=0;r<16;r++){const l=Math.round(((16-r)/16)**2*42);n[r]=Math.max(8,n[r]-l),n[t-1-r]=Math.max(8,n[t-1-r]-l)}return n}function Zs(i,t,e){const{cols:n,rows:s}=t;let o=16;for(let a=0;a<n;a++){o=lt(o+i.int(-1,1),10,26);const c=s-3-(i.chance(.4)?1:0);for(let r=e[a];r<s;r++){const l=r-e[a];let h=l===0?$:l<o?ft:Q;r>=c&&(h=J),t.set(a,r,h)}}for(let a=Math.round(i.int(14,24)*(n/600));a>0;a--){const c=i.int(0,n-1),r=e[c]+i.int(4,18),l=i.range(1.5,4);for(let h=-4;h<=4;h++)for(let f=-5;f<=5;f++)f*f*.6+h*h<=l*l&&t.fgAt(c+f,r+h)===ft&&t.set(c+f,r+h,Q)}}function tn(i,t,e){for(let n=20;n<t.cols-20;n++){const s=e[n+1]-e[n];if(Math.abs(s)<9||!i.chance(.7))continue;const o=s>0?1:-1,a=Math.min(e[n],e[n+1]),c=i.int(3,8),r=o>0?n+1:n;for(let l=0;l<c;l++){const h=r+o*l,f=l<c-2?3:2;for(let u=0;u<f;u++)t.set(h,a+u,u===0?$:Q)}}}const fe=28,en=46,be=7,bt=14,sn=9,Nt=2,He=(bt-2)/2,it=3;function nn(i,t,e,n,s){let o=0;for(let p=n;p<n+s;p++)o=Math.max(o,e[p]);const a=Math.max(1,Math.min(i.int(1,3),Math.floor((o-34)/bt))),c=o-a*bt,r=n+s-1,l=n+Nt,h=r-Nt,f=i.chance(.6);for(let p=n-2;p<=r+2;p++){for(let m=c-32;m<o;m++)t.set(p,m,G),t.setBg(p,m,ge);for(let m=o;m<o+3;m++)(t.fgAt(p,m)===G||m===o)&&t.set(p,m,m===o?$:ft);t.surface[p]=o}Fe(t,e,n-3,-1,o),Fe(t,e,r+3,1,o);for(let p=n;p<=r;p++)t.set(p,o,z);for(let p=c;p<o;p++)for(let m=n;m<=r;m++)m<l||m>h?t.set(m,p,z):t.setBg(m,p,ds);let u=i.chance(.5)?-1:1;for(let p=0;p<a;p++){const m=o-p*bt,b=m-bt,v=p===a-1,A=new Uint8Array(s),x=(w,C)=>{for(let k=w;k<=C;k++)if(k<l||k>h||A[k-n])return!1;for(let k=w;k<=C;k++)A[k-n]=1;return!0},M=h-l>30?i.int(l+12,h-12):-1;if(i.chance(.5)||M>0){const w=M>0&&i.chance(.5)?M:l,C=w===M?h:M>0?M:h;for(let k=b+1;k<m;k++)for(let R=w;R<=C;R++)t.setBg(R,k,It)}for(let w=l;w<=h;w++)t.setBg(w,b+1,H);if(M>0){for(let w=b+1;w<m;w++)t.setBg(M,w,H);A[M-n]=1}for(let w=l;w<=h;w++)t.set(w,b,v&&!f?Ot:K);const d=He*it,y=u<0?l+2:h-2-d+1;for(let w=0;w<He;w++){const C=u<0?y+w*it:y+d-(w+1)*it,k=m-2*(w+1);for(let R=0;R<it;R++)t.set(C+R,k,K);t.setBg(u<0?C:C+it-1,k+1,H)}x(y,y+d-1);const S=u<0?y+d-it:y-2,E=v&&!f?K:G;for(let w=0;w<it+2;w++)t.set(S+w,b,E);u=-u;const P=p===0?[-1,1]:[i.chance(.5)?-1:1];for(const w of P){const C=w<0?n:h+1;for(let k=m-sn;k<m;k++)for(let R=0;R<Nt;R++)t.set(C+R,k,G);if(p>0){const k=w<0?n-1:r+1;for(let R=0;R<5;R++)t.set(k+w*R,m,K);for(let R=0;R<3;R++)t.setBg(k+w*R,m+3-R,H)}}for(let w=l+3;w+5<h-1;w+=i.int(9,13)){if(Math.abs(w+2-M)<4)continue;const C=i.chance(.6)?st:ps;for(let k=0;k<5;k++)for(let R=0;R<5;R++)t.setBg(w+R,m-10+k,R===2||k===2?H:C);for(let k=-1;k<=5;k++)t.setBg(w+k,m-5,H)}on(i,t,m,b,l,h,x)}if(i.chance(.5)&&an(i,t,o,l,h),f){const p=n-2,m=r+2,b=M=>c-1-Math.floor(Math.min(M-p,m-M)*.8);for(let M=p;M<=m;M++){const d=b(M);if(t.set(M,d,Ot),t.set(M,d-1,Ot),M>=n&&M<=r)for(let y=d+1;y<c;y++)t.setBg(M,y,It)}const v=Math.floor((n+r)/2);for(let M=0;M<3;M++)for(let d=-1;d<=1;d++)t.setBg(v+d,c-6+M,st);if(i.chance(.6)){const M=i.chance(.5)?l+1:h-4;for(let d=1;d<=3;d++)for(let y=0;y<4;y++)t.set(M+y,c-d,ut)}const A=i.chance(.5)?n+4:r-5,x=b(A+1)-6;for(let M=x;M<b(A+1);M++)for(let d=0;d<2;d++)t.fgAt(A+d,M)===G&&t.set(A+d,M,z)}else{for(let m=c-2;m<c;m++)for(let b=0;b<Nt;b++)t.set(n+b,m,z),t.set(r-b,m,z);const p=i.chance(.5)?l+2:h-8;for(let m=c-6;m<c;m++)t.setBg(p+1,m,H),t.setBg(p+5,m,H);for(let m=0;m<7;m++)t.set(p+m,c-6,K);for(let m=c-11;m<c-6;m++)for(let b=1;b<6;b++)t.setBg(p+b,m,It)}}function Fe(i,t,e,n,s){let o=s;for(let a=0;a<be;a++){const c=e+n*a;if(c<1||c>=i.cols-1)return;const r=t[c];if(Math.abs(r-o)<=2)return;o=r<o?o-2:o+2;for(let l=Math.min(r,o);l<Math.max(r,o);l++)i.set(c,l,r<o?G:ft);i.set(c,o,$),t[c]=o,i.surface[c]=o}}function on(i,t,e,n,s,o,a){for(let c=0,r=0;c<14&&r<3;c++){const l=i.int(0,2),h=l===0?i.int(5,7):l===1?4:3,f=i.int(s+3,o-3-h);if(a(f-1,f+h))if(r++,l===0){for(let u=0;u<h;u++)t.set(f+u,e-3,K);for(let u=1;u<=2;u++)t.setBg(f,e-u,H),t.setBg(f+h-1,e-u,H);i.chance(.5)&&t.setBg(f+i.int(1,h-2),e-4,st)}else if(l===1)for(let u=1;u<=7;u++)for(let p=0;p<h;p++){const m=p===0||p===h-1||u%2===1;t.setBg(f+p,e-u,m?H:_e)}else{for(let u=1;u<=3;u++)for(let p=0;p<3;p++)t.set(f+p,e-u,ut);if(i.chance(.35))for(let u=4;u<=5;u++)for(let p=1;p<3;p++)t.set(f+p,e-u,ut)}}for(let c=i.int(1,2);c>0;c--){const r=i.int(s+3,o-4);for(let l=n+2;l<n+4;l++)t.setBg(r,l,H);t.setBg(r-1,n+4,st),t.setBg(r,n+4,st),t.setBg(r+1,n+4,st)}}function an(i,t,e,n,s){const o=n+2,a=s-2,c=e+bt-1;if(c>=t.rows-6)return;for(let l=e+1;l<=c;l++)for(let h=o-1;h<=a+1;h++){const f=l===c||h===o-1||h===a+1;f&&t.fgAt(h,l)===G||(t.set(h,l,f?z:G),f||t.setBg(h,l,It))}for(let l=o;l<=a;l++)t.setBg(l,e+1,H);const r=i.int(o+2,a-6);for(let l=0;l<4;l++)t.set(r+l,e,K);for(let l=o+1;l+3<=a;l+=i.int(5,9))if(!(l+3>r-1&&l<r+5)&&i.chance(.6))for(let h=1;h<=3;h++)for(let f=0;f<3;f++)t.set(l+f,c-h,ut)}const rn=14,_t=.6;function cn(i,t,e,n,s){const{cols:o,rows:a}=t,c=a-8,r=new Uint8Array(o*a),l=d=>e[lt(Math.round(d),0,o-1)]+rn,h=(d,y,S)=>{const E=S*S;for(let P=Math.floor(y-S);P<=Math.ceil(y+S);P++)for(let w=Math.floor(d-S);w<=Math.ceil(d+S);w++){if(!t.inBounds(w,P)||w<3||w>=o-3)continue;const C=w+.5-d,k=P+.5-y;C*C+k*k>E||t.fgAt(w,P)===J||(t.set(w,P,G),r[P*o+w]=1)}},f=(d,y,S,E,P,w,C=!0)=>{const k=i.range(0,Math.PI*2);for(let R=0;R<E;R++){const D=w(d,y);if(D===null)return;S=un(fn(S,D,.14)+i.range(-.3,.3)),d+=Math.cos(S),y+=Math.sin(S);const Et=P+Math.sin(R*.13+k)*.6;if(C&&(y=lt(y,l(d)+Et+1,c-Et)),d<8||d>o-9)return;h(d,y,Et)}},u=(d,y)=>{const S=i.range(11,22),E=i.range(8,13),P=i.range(0,Math.PI*2),w=i.range(0,Math.PI*2);for(let C=-Math.ceil(E*1.3);C<=Math.floor(E*.55);C++)for(let k=-Math.ceil(S*1.3);k<=Math.ceil(S*1.3);k++){const R=Math.atan2(C/E,k/S),D=1+Math.sin(R*3+P)*.16+Math.sin(R*5+w)*.09;(k/S)**2+(C/E)**2<=D*D&&h(d+k,y+C,.75)}},p=(d,y)=>{const S=Math.round((Math.abs(y.x-d.x)+Math.abs(y.y-d.y))*2.5);f(d.x,d.y,Math.atan2(y.y-d.y,y.x-d.x),S,i.range(4.6,5.6),(E,P)=>Math.hypot(y.x-E,y.y-P)<2?null:Math.atan2(y.y-P,y.x-E))},m=(d,y,S)=>{const E=(o-70)/d,P=[];for(let w=0;w<d;w++){const C=Math.round(35+E*(w+.5+i.range(-.22,.22))),k=P[w-1];let R=i.int(Math.round(y(C)),Math.round(Math.max(y(C),S(C))));if(k){const D=(C-k.x)*.5;R=lt(R,k.y-D,k.y+D)}R=Math.min(R,c-8),P.push({x:C,y:R}),u(C,R),k&&p(k,P[w])}return P},b=m(Math.round(i.int(6,8)*s),d=>l(d)+7,d=>l(d)+26),v=m(Math.round(i.int(5,7)*s),d=>l(d)+46,()=>c-10),A=[...b,...v];for(let d=0,y=0;d<Math.round(3*s)&&y<12*s;y++){const S=v[i.int(0,v.length-1)];let E=null;for(const P of b){const w=Math.abs(P.x-S.x);w*.5<S.y-P.y||w>140||(!E||w<Math.abs(E.x-S.x))&&(E=P)}E&&(p(E,S),d++)}for(let d=Math.round(i.int(4,7)*s);d>0;d--){const y=A[i.int(0,A.length-1)],S=i.sign()*i.range(.2,_t);let E=i.chance(.5)?S:Math.PI-S;f(y.x,y.y,E,i.int(14,38),i.range(3.4,5),()=>E+=i.range(-.1,.1))}const x=r.slice(),M=[];for(let d=0;d<40*s&&M.length<Math.round(3*s);d++){const y=i.int(40,o-41);if(Math.abs(y-n)<45||M.some(P=>Math.abs(P-y)<70))continue;const S=y<o/2?1:-1,E=i.range(.5,_t);f(y,e[y]-2,S>0?E:Math.PI-E,260,i.range(4.8,5.4),(P,w)=>{const C=Math.floor(w)*o+Math.floor(P);return w>l(P)+2&&x[C]||w>=c-6?null:S>0?E:Math.PI-E},!1),M.push(y)}return ln(t,r),hn(i,t,r),M}function ln(i,t){const{cols:e,rows:n}=i;for(let s=0;s<2;s++){const o=[];for(let a=1;a<n-1;a++)for(let c=1;c<e-1;c++){const r=a*e+c;if(t[r]||i.fg[r]===G||i.fg[r]===J||a<=i.surface[c]+1)continue;let l=0;for(let h=-1;h<=1;h++)for(let f=-1;f<=1;f++)l+=t[r+h*e+f];l>=5&&o.push(r)}for(const a of o)i.fg[a]=G,t[a]=1}}function hn(i,t,e){const{cols:n,rows:s,surface:o}=t;for(let a=4;a<n-4;a++)for(let c=o[a]+8;c<s-4;c++){const r=c*n+a;if(!e[r])continue;const l=h=>t.collisionAt(a,h)===I;if(l(c-1)&&i.chance(.07)){let h=0;for(;h<16&&!l(c+h);)h++;if(h<16)continue;const f=i.int(2,5);for(let u=0;u<f;u++)t.set(a,c+u,Q);c+=f}else if(l(c+1)&&!l(c-1)&&i.chance(.035)){const h=i.int(0,2);for(let f=0;f<h;f++)t.setBg(a,c-f,Ie);t.setBg(a,c-h,Jt),t.glows.push((c-h)*n+a)}}}function fn(i,t,e){const n=Math.atan2(Math.sin(t-i),Math.cos(t-i));return i+lt(n,-e,e)}function un(i){const t=Math.cos(i),e=Math.sin(i);return Math.abs(e)<=Math.sin(_t)?i:Math.atan2(Math.sign(e)*Math.sin(_t),(t<0?-1:1)*Math.cos(_t))}function dn(i,t,e,n){const s=i.int(9,20);for(let r=n-s;r<n;r++)t.setBg(e,r,ve),t.setBg(e+1,r,ve);const o=n-s;if(i.chance(.35)){for(let r=0;r<3;r++){const l=o+r*4,h=2+r*2;for(let f=0;f<2;f++)for(let u=-h+f;u<=h+1-f;u++)t.set(e+u,l-f,Qt)}return}const a=i.range(4,8),c=i.range(3,5);for(let r=-Math.ceil(c);r<=Math.ceil(c);r++)for(let l=-Math.ceil(a);l<=Math.ceil(a)+1;l++){const h=(l-.5)/a,f=r/c;h*h+f*f<=1-i.next()*.18&&t.set(e+l,o+r,Qt)}}function ms(i,t,e,n){const s=i.chance(.4),o=s?i.int(5,8):i.int(2,4),a=s?2:1;for(let h=n-o;h<n;h++)for(let f=0;f<a;f++)t.setBg(e+f,h,Ie);const c=s?i.int(4,6):i.int(2,3),r=s?3:2,l=n-o;for(let h=0;h<r;h++){const f=Math.round(c*Math.sqrt(1-(h/r)**2));for(let u=-f;u<=f+a-1;u++)t.set(e+u,l-h,St)}}function pn(i,t,e,n){const s=i.range(1.8,3.6);for(let o=-4;o<=2;o++)for(let a=-4;a<=4;a++)a*a+o*o*1.4<=s*s&&t.set(e+a,n+o,Q)}function mn(i,t,e,n){const s=i.int(1,2);for(let o=0;o<s;o++){const a=e+(o===1?1:0);for(let c=0;c<3;c++)for(let r=0;r<3;r++)t.set(a+r,n-1-o*3-c,ut)}}function yn(i,t,e,n,s){const o=i.int(3,6);for(let a=0;a<s;a++){const c=(a+.5)/s,r=Math.max(1,Math.round(o*Math.sin(c*Math.PI)));for(let l=0;l<=r;l++)t.set(e+a,n+l,l===0?$:l===1?ft:Q)}s>12&&i.chance(.5)&&ms(i,t,e+Math.floor(s/2),n)}function lt(i,t,e){return Math.max(t,Math.min(e,i))}const Xt={[ft]:8014382,[$]:9416252,[Q]:6971e3,[J]:2826804,[z]:11030846,[K]:12749391,[Qt]:4160070,[St]:14172986,[Ot]:5192296,[ut]:11565628},xn={[ds]:4862518,[ve]:5913126,[Ie]:14273456,[st]:16762981,[ps]:3024960,[Jt]:10155478,[H]:3021852,[It]:4141124,[_e]:7028026},Mn=[9059131,4151918,8022586,6176622],gn=3810609,Ct="12, 6, 16",vn="120, 240, 205",bn="#5e4256",wn="#9a7480",Tn="#ff8fa8",An="#f3dcc2",Sn="#fff1d6",qe="255, 92, 60",kn=16181970,En=1839638,Mt="#140e1a",Rn="rgba(255, 236, 210, 0.9)",Pn="#fff4cf",ue="255, 122, 47",Bn="#ff4a3d",gt=[16769162,16753226,16738863,16774351],Ye=3811891,Ht=14268810,Cn=[2890565,9059164,15764043,16765578],Ln=[1707298,7216430,13781034,16751178],On=7223902,In=4859720;function de(i,t,e){const n=(i>>16&255)+((t>>16&255)-(i>>16&255))*e,s=(i>>8&255)+((t>>8&255)-(i>>8&255))*e,o=(i&255)+((t&255)-(i&255))*e;return Math.round(n)<<16|Math.round(s)<<8|Math.round(o)}function pe(i,t=1){return`rgba(${i>>16&255}, ${i>>8&255}, ${i&255}, ${t})`}const wt=["#ffd23f","#4cc9f0","#ff6b9a","#7ae582"],Zt=5,ht=4,_n=30,ys=.8,Dn=30,we=4,Gn=1400,jn=40,Vn=62,Nn=28,Hn=56,$e=35,Fn=230;function qn(i,t,e){return{x:i,y:t,vy:0,dir:e.range(0,Math.PI*2),facing:e.sign(),state:"burrow",grounded:!1,timer:0,minBurrow:e.range(.5,2.5),fuse:0,fuseLength:ys,phase:e.range(0,Math.PI*2),pop:0,dust:e.next()}}function At(i,t,e){const n=Math.floor((t-Zt)/T),s=Math.floor((t+Zt-1e-4)/T),o=Math.floor((e-ht)/T),a=Math.floor((e+ht-1e-4)/T);for(let c=o;c<=a;c++)for(let r=n;r<=s;r++)if(i.collisionAt(r,c)===I)return!0;return!1}function Yn(i,t,e,n){for(let s=0;s<80;s++){const o=t.int(20,i.cols-21),a=i.surface[o]+10;if(a>=i.rows-8)continue;const c=t.int(a,i.rows-8),r=(o+.5)*T,l=(c+.5)*T;if(!(i.collisionAt(o,c)!==I||i.fgAt(o,c)===J)&&!e.some(h=>Math.hypot(r-h.x,l-h.y)<n))return{x:r,y:l}}return null}function $n(i,t,e,n,s){return i.state==="burrow"?Xn(i,t,e,n,s):zn(i,t,e,n,s)}function Wn(i,t,e,n){At(t,i.x,i.y)||(Ms(i,t,e),!(!i.grounded||!n.active||Math.abs(n.x-i.x)<3)&&(i.facing=n.x>i.x?1:-1,xs(i,t,$e*e),i.phase+=$e*e*.45))}function me(i,t,e){i.state="burrow",i.dir=e,i.timer=0,i.minBurrow=t.range(1.2,2.6),i.grounded=!1,i.vy=0}function Xn(i,t,e,n,s){const o=t.depthAt(i.x,i.y),a=s.x-i.x,c=s.y-i.y,r=s.active&&Math.hypot(a,c)<Fn;let l=null;o<we+4?l=Math.PI/2:i.y>(t.rows-8)*T?l=-Math.PI/2:i.x<16*T?l=0:i.x>(t.cols-16)*T?l=Math.PI:r&&(l=Math.atan2(c,a)),i.dir+=e.range(-1,1)*5*n,l!==null&&(i.dir=Un(i.dir,l,(r?2.4:3)*n));const h=r?Vn:jn,f=i.x+Math.cos(i.dir)*h*n,u=i.y+Math.sin(i.dir)*h*n,p=Math.floor(f/T),m=Math.floor(u/T);return t.depthAt(f,u)<we+1||t.fgAt(p,m)===J?(i.dir+=Math.PI*e.range(.6,1.4),null):(i.x=f,i.y=u,i.timer+=n,Math.cos(i.dir)!==0&&(i.facing=Math.cos(i.dir)>0?1:-1),i.timer>=(r?Math.min(i.minBurrow,.35):i.minBurrow)&&t.collisionAt(p,m)===ct&&!At(t,i.x,i.y)?(i.state="walk",i.vy=0,i.grounded=!1,i.pop=0,i.timer=e.range(4,9),"surface"):null)}function zn(i,t,e,n,s){if(i.pop+=n,i.timer-=n,Ms(i,t,n),i.y>t.height)return"gone";const o=s.x-i.x,a=s.active&&Math.abs(o)<170&&Math.abs(s.y-i.y)<60;if(a&&Math.abs(o)>2&&(i.facing=o>0?1:-1),t.depthAt(i.x,i.y)<we-1)return me(i,e,Math.PI/2),"dive";if(!i.grounded)return null;if(i.timer<=0&&!a)return me(i,e,Math.PI/2-i.facing*e.range(.2,.7)),"dive";const c=a?Hn:Nn;return i.phase+=c*n*.45,xs(i,t,c*n)||a?null:e.chance(.35)?(me(i,e,i.facing>0?0:Math.PI),"dive"):(i.facing=i.facing>0?-1:1,null)}function xs(i,t,e){let n=e;for(;n>1e-4;){const s=Math.min(1,n)*i.facing;n-=Math.abs(s);const o=i.x+s;if(!At(t,o,i.y)){i.x=o;continue}let a=!1;for(let c=1;c<=2&&!a;c++){const r=i.y-c*T;!At(t,o,r)&&!At(t,i.x,r)&&(i.x=o,i.y=r,a=!0)}if(!a)return!1}return!0}function Ms(i,t,e){i.vy=Math.min(i.vy+Gn*e,700);let n=i.vy*e;for(i.grounded=!1;Math.abs(n)>1e-4;){const s=Math.max(-1,Math.min(1,n));n-=s;const o=i.y+s;if(s>0){const a=Math.floor((i.y+ht-1e-4)/T),c=Math.floor((o+ht-1e-4)/T);if(c>a&&Kn(t,i.x,c)){i.y=c*T-ht,i.vy=0,i.grounded=!0;return}}else if(At(t,i.x,o)){i.vy=0;return}i.y=o}}function Kn(i,t,e){const n=Math.floor((t-Zt+1)/T),s=Math.floor((t+Zt-1)/T);for(let o=n;o<=s;o++)if(i.collisionAt(o,e)!==ct)return!0;return!1}function Un(i,t,e){const n=Math.atan2(Math.sin(t-i),Math.cos(t-i));return i+Math.max(-e,Math.min(e,n))}const nt=0,rt=1,U=2,Te=3,Ae=4,Se=5,ke=6,te=7,Ee=8,ee=9,Re=10,q=11,gs=[[nt,rt],[rt,U],[rt,Te],[Te,Ae],[rt,Se],[Se,ke],[U,te],[te,Ee],[U,ee],[ee,Re]],V={thigh:7.5,shin:7.5,torso:10,neck:5,upperArm:6.5,forearm:6,headRadius:4};function vs(){return new Float32Array(q*2)}function Qn(i,t=vs()){const{facing:e,time:n,crouch:s}=i;let o=0,a,c,r,l;switch(i.state){case"run":{const y=i.phase,S=.35+i.speed*.55;a={a:Math.sin(y)*S,bend:.25+Math.max(0,Math.cos(y))*1.4*i.speed},c={a:-Math.sin(y)*S,bend:.25+Math.max(0,-Math.cos(y))*1.4*i.speed},r={a:-Math.sin(y)*S*1.1,bend:1},l={a:Math.sin(y)*S*1.1,bend:1},o=.08+i.speed*.18;break}case"jump":a={a:.75,bend:1.5},c={a:.15,bend:1},r={a:2.5,bend:.3},l={a:-2.3,bend:.4},o=.1;break;case"fall":a={a:.35,bend:.5},c={a:-.3,bend:.25},r={a:2.1+Math.sin(n*13)*.45,bend:.3},l={a:-2+Math.cos(n*12)*.45,bend:.3},o=-.05;break;case"tumble":a={a:.9+Math.sin(n*17)*.6,bend:.9},c={a:-.6+Math.cos(n*15)*.6,bend:.6},r={a:2.4+Math.sin(n*19)*.7,bend:.5},l={a:-2.2+Math.cos(n*21)*.7,bend:.5},o=.2;break;case"crawl":{const y=Math.sin(i.phase)*i.speed;a={a:.25+y*.4,bend:1.75+y*.4},c={a:.25-y*.4,bend:1.75-y*.4},r={a:1.15-y*.35,bend:-1},l={a:1.15+y*.35,bend:-1},o=1.45;break}default:{const y=Math.sin(n*2.2);a={a:.13,bend:.06},c={a:-.11,bend:.06},r={a:.2+y*.04,bend:.25},l={a:-.14-y*.04,bend:.2},o=.03+y*.015}}s>0&&i.state!=="crawl"&&(a={a:a.a+s*.5,bend:a.bend+s*1},c={a:c.a+s*.4,bend:c.bend+s*.9},o+=s*.25);const h=(y,S,E)=>{t[y*2]=S,t[y*2+1]=E};h(U,0,0);const f=Math.sin(o)*e*V.torso,u=-Math.cos(o)*V.torso;h(rt,f,u),i.state==="crawl"?h(nt,f+e*4.7,u-1.4):h(nt,f+Math.sin(o)*e*V.neck,u-Math.cos(o)*V.neck),Ft(t,U,te,Ee,a.a,-a.bend,V.thigh,V.shin,e),Ft(t,U,ee,Re,c.a,-c.bend,V.thigh,V.shin,e),Ft(t,rt,Te,Ae,r.a,r.bend,V.upperArm,V.forearm,e),Ft(t,rt,Se,ke,l.a,l.bend,V.upperArm,V.forearm,e);const p=i.state==="crawl",m=p||i.state==="idle"||i.state==="run";let b=Math.max(t[Ee*2+1],t[Re*2+1]);if(p)for(const y of[te,ee,Ae,ke])b=Math.max(b,t[y*2+1]);const v=m?i.y-b:i.y-15,A=p?-e*5:0,x=i.y-15,M=Math.cos(i.spin),d=Math.sin(i.spin);for(let y=0;y<q;y++){let S=t[y*2]+A,E=t[y*2+1]+v-x;if(i.spin!==0){const P=S*M-E*d;E=S*d+E*M,S=P}t[y*2]=i.x+S,t[y*2+1]=x+E}return t}function Ft(i,t,e,n,s,o,a,c,r){const l=i[t*2],h=i[t*2+1],f=l+Math.sin(s)*r*a,u=h+Math.cos(s)*a,p=s+o;i[e*2]=f,i[e*2+1]=u,i[n*2]=f+Math.sin(p)*r*c,i[n*2+1]=u+Math.cos(p)*c}const We=4,Jn=5,ye=1400;class Zn{constructor(t,e,n){g(this,"pos");g(this,"vel");g(this,"prev");g(this,"constraints");g(this,"restTime",0);this.pos=Float32Array.from(t),this.prev=Float32Array.from(t),this.vel=new Float32Array(q*2);for(let o=0;o<q;o++)this.vel[o*2]=e,this.vel[o*2+1]=n;const s=[...gs.map(([o,a])=>[o,a]),[nt,U]];this.constraints=s.map(([o,a])=>({a:o,b:a,length:this.distance(o,a)}))}distance(t,e){return Math.hypot(this.pos[t*2]-this.pos[e*2],this.pos[t*2+1]-this.pos[e*2+1])}impulse(t,e,n,s){for(let o=0;o<q;o++){const a=this.pos[o*2]-t,c=this.pos[o*2+1]-e,r=Math.max(1,Math.hypot(a,c));if(r>=n)continue;const l=1-r/n;this.vel[o*2]+=a/r*s*l,this.vel[o*2+1]+=c/r*s*l-s*.3*l}this.restTime=0}centerX(){let t=0;for(let e=0;e<q;e++)t+=this.pos[e*2];return t/q}centerY(){let t=0;for(let e=0;e<q;e++)t+=this.pos[e*2+1];return t/q}launch(t,e,n){const s=this.centerX(),o=this.centerY();for(let a=0;a<q;a++){const c=this.pos[a*2]-s,r=this.pos[a*2+1]-o;this.vel[a*2]+=t-r*n,this.vel[a*2+1]+=e+c*n}this.restTime=0}step(t,e,n){const s=t/We;for(let a=0;a<We;a++)this.substep(s,e,n);let o=0;for(let a=0;a<this.vel.length;a++)o=Math.max(o,Math.abs(this.vel[a]));this.restTime=o<12?this.restTime+t:0}substep(t,e,n){const{pos:s,prev:o,vel:a}=this;for(let c=0;c<q;c++){const r=c*2,l=r+1;a[l]+=e*t;const h=Math.hypot(a[r],a[l]);h>ye&&(a[r]*=ye/h,a[l]*=ye/h),o[r]=s[r],o[l]=s[l],s[r]+=a[r]*t,s[l]+=a[l]*t}for(let c=0;c<Jn;c++)for(const r of this.constraints){const l=r.a*2,h=r.b*2,f=s[h]-s[l],u=s[h+1]-s[l+1],p=Math.hypot(f,u)||1e-4,m=(p-r.length)/p*.5;s[l]+=f*m,s[l+1]+=u*m,s[h]-=f*m,s[h+1]-=u*m}for(let c=0;c<q;c++){const r=c*2,l=r+1;let h=!1;n(o[r],o[l],s[r],s[l])&&(n(o[r],o[l],s[r],o[l])?n(o[r],o[l],o[r],s[l])?(s[r]=o[r],s[l]=o[l],h=!0):s[r]=o[r]:(s[l]=o[l],h=!0));const f=(s[r]-o[r])/t,u=(s[l]-o[l])/t;a[r]=h?f*.82:f,a[l]=h&&a[l]>160?-a[l]*.22:u}}}const Xe=1400,et=10,Dt=30,to=16,ze=165,Ke=62,eo=640,so=1e3,xe=220,Ue=-300,qt=.7,Me=2.6,Qe=1100,no=1.5,bs=2,Pe={left:!1,right:!1,jump:!1,down:!1,crouch:!1,jumpPressed:!1},zt=0,Lt=1,Kt=2,se=3;function Be(i,t,e){const n=Math.hypot(t-i.x,e-i.y);return Math.max(0,Math.min(1,1-n/(i.radius*9)))}function oo(i){return Math.max(.16,1.9*Math.pow(.5,i/45))}function Je(i){return Math.min(22,11+Math.floor(i/20))}function io(i,t){return 22+Math.min(26,i*.18)+t*14}function Ce(i,t,e,n,s=Dt){const o=e-et/2,a=e+et/2,c=n-s,r=Math.max(o-i,0,i-a),l=Math.max(c-t,0,t-n);return Math.hypot(r,l)}class ao{constructor(t,e=[0]){g(this,"seed");g(this,"terrain");g(this,"players",[]);g(this,"meteors",[]);g(this,"particles",[]);g(this,"blasts",[]);g(this,"moles",[]);g(this,"deathCause",null);g(this,"meteorsEnabled",!1);g(this,"survived",0);g(this,"clock",0);g(this,"listeners",{});g(this,"rng");g(this,"moleRng");g(this,"spawnTimer",2);g(this,"moleTimer",5);g(this,"moleTarget",{x:0,y:0,active:!1});g(this,"spawnX");g(this,"spawnY");g(this,"collidePoint",(t,e,n,s)=>{const o=this.terrain.collisionAtPoint(n,s);return o===I?!0:o===Tt&&s>e&&Math.floor(e/T)<Math.floor(s/T)});this.seed=t,this.rng=Ut(t^1540483477),this.moleRng=Ut(t^668265263);const n=Qs(t);this.terrain=n.terrain,this.spawnX=n.spawnX,this.spawnY=n.spawnY;for(let s=Je(0);s>0;s--)this.spawnMole([{x:n.spawnX,y:n.spawnY}]);for(const s of e)this.addPlayer(s)}get alive(){return this.players.some(t=>t.alive)}player(t){return this.players.find(e=>e.slot===t)}addPlayer(t){var l;const e=this.player(t);if(e)return e;const n=(l=this.players.find(h=>h.alive))==null?void 0:l.body,s=this.players.length>0,o=(n==null?void 0:n.x)??this.spawnX,a=(n==null?void 0:n.y)??this.spawnY,c={x:o+(n!=null&&n.grounded?this.standingRoom(o,a,t):0),y:a,vx:0,vy:0,facing:t%2===0?1:-1,grounded:(n==null?void 0:n.grounded)??!0,floor:(n==null?void 0:n.floor)??I,coyote:0,jumpBuffer:0,jumpHeld:!1,dropTimer:0,stun:0,spin:0,spinVelocity:0,phase:0,crouch:0,ducked:!1,stepOffset:0,state:"idle"},r={slot:t,body:c,pose:vs(),ragdoll:null,alive:!0,deathCause:null,diedAt:0,shield:s?no:0,shake:0};return this.players.push(r),this.players.sort((h,f)=>h.slot-f.slot),this.updatePose(r),s&&this.puff(c.x,c.y,8,70),r}standingRoom(t,e,n){const s=n%2===0?1:-1;for(const o of[14*s,-14*s,7*s,-7*s])if(!this.bodyBlocked(t+o,e)&&this.bodyBlocked(t+o,e+T))return o;return 0}removePlayer(t){var s,o;const e=this.players.findIndex(a=>a.slot===t);if(e<0)return;const[n]=this.players.splice(e,1);n.alive&&this.players.length>0&&!this.alive&&((o=(s=this.listeners).runOver)==null||o.call(s))}viewTarget(t){const e=this.player(t);if(!e)return this.players[0];if(e.alive||this.clock-e.diedAt<bs)return e;const n=at(e),s=W(e);let o,a=1/0;for(const c of this.players){if(!c.alive)continue;const r=Math.hypot(at(c)-n,W(c)-s);r<a&&(o=c,a=r)}return o??e}focusX(t=(e=>(e=this.players[0])==null?void 0:e.slot)()??0){const n=this.viewTarget(t);return n?at(n):this.spawnX}focusY(t=(e=>(e=this.players[0])==null?void 0:e.slot)()??0){const n=this.viewTarget(t);return n?W(n):this.spawnY-Dt/2}stormTime(){return this.survived}update(t,e){var n;this.clock+=t,this.alive&&this.meteorsEnabled&&(this.survived+=t);for(const s of this.players)s.alive?this.updatePlayer(s,t,typeof e=="function"?e(s.slot):e):(n=s.ragdoll)==null||n.step(t,Xe,this.collidePoint),s.shield=Math.max(0,s.shield-t),s.shake*=Math.exp(-t*7);this.updateMoles(t),this.updateMeteors(t),this.updateParticles(t);for(let s=this.blasts.length-1;s>=0;s--)this.blasts[s].age+=t,this.blasts[s].age>.6&&this.blasts.splice(s,1)}updatePlayer(t,e,n){var f,u,p,m,b,v,A,x;const s=t.body;this.unstick(s);const o=(n.right?1:0)-(n.left?1:0),a=s.stun>0;s.stun=Math.max(0,s.stun-e),n.crouch&&(s.grounded||s.ducked)?s.ducked=!0:s.ducked&&!this.bodyBlocked(s.x,s.y,Dt)&&(s.ducked=!1);const c=s.ducked?Ke:ze;if(o!==0){const M=a?.3:1;Math.sign(s.vx)===o&&Math.abs(s.vx)>c?s.vx=Yt(s.vx,o*c,(s.grounded?900:120)*e):s.vx=Yt(s.vx,o*c,(s.grounded?1800:1100)*M*e),a||(s.facing=o>0?1:-1)}else{const M=s.grounded?a?500:1500:120;s.vx=Yt(s.vx,0,M*e)}s.jumpBuffer=n.jumpPressed?.13:Math.max(0,s.jumpBuffer-e),s.coyote=s.grounded?.1:Math.max(0,s.coyote-e),s.dropTimer=Math.max(0,s.dropTimer-e),n.down&&s.grounded&&s.floor===Tt?(s.dropTimer=.22,s.grounded=!1,s.coyote=0):s.jumpBuffer>0&&s.coyote>0&&!s.ducked&&(s.vy=-470,s.jumpHeld=!0,s.jumpBuffer=0,s.coyote=0,s.grounded=!1,this.puff(s.x,s.y,5,60),(u=(f=this.listeners).jump)==null||u.call(f,t.slot)),s.jumpHeld&&!n.jump&&s.vy<0&&(s.vy*=.5,s.jumpHeld=!1),s.vy>=0&&(s.jumpHeld=!1),s.vy=Math.min(s.vy+Xe*e,so);const r=s.grounded,l=s.vy;this.moveX(s,s.vx*e),s.grounded=!1;const h=this.moveY(s,s.vy*e);if(h!==-1&&(h===St&&!n.down&&l>60?(s.vy=-Math.max(eo,l*.9),s.grounded=!1,s.jumpHeld=!1,s.crouch=.6,this.puff(s.x,s.y,6,90),(m=(p=this.listeners).bounce)==null||m.call(p,t.slot)):(s.vy=0,s.grounded=!0,r||(s.crouch=Math.min(1,l/750),l>320&&this.puff(s.x,s.y,Math.round(l/80),l*.12),l>120&&((v=(b=this.listeners).land)==null||v.call(b,l,t.slot))))),s.grounded){s.spin=Ze(s.spin)*Math.exp(-e*20),s.spinVelocity=0;const M=Math.floor(s.phase/Math.PI);s.phase+=Math.abs(s.vx)*e/(s.ducked?5:8.5),Math.floor(s.phase/Math.PI)!==M&&Math.abs(s.vx)>40&&((x=(A=this.listeners).footstep)==null||x.call(A,t.slot))}else s.spinVelocity!==0?(s.spin+=s.spinVelocity*e,s.spinVelocity*=Math.exp(-e*1.5)):s.spin=Ze(s.spin)*Math.exp(-e*10);s.crouch=Math.max(0,s.crouch-e*4),s.stepOffset=Yt(s.stepOffset,0,110*e),s.stun>0&&!s.grounded&&Math.abs(s.spinVelocity)>1?s.state="tumble":s.ducked?s.state="crawl":s.grounded?s.state=Math.abs(s.vx)>18?"run":"idle":s.state=s.vy<0?"jump":"fall",this.updatePose(t)}updatePose(t){const e=t.body;Qn({x:e.x,y:e.y+e.stepOffset,facing:e.facing,state:e.state,phase:e.phase,time:this.clock,speed:Math.min(1,Math.abs(e.vx)/(e.ducked?Ke:ze)),crouch:e.crouch,spin:e.spin},t.pose)}bodyBlocked(t,e,n=Dt){const s=this.terrain,o=Math.floor((t-et/2)/T),a=Math.floor((t+et/2-1e-4)/T),c=Math.floor((e-n)/T),r=Math.floor((e-1e-4)/T);for(let l=c;l<=r;l++)for(let h=o;h<=a;h++)if(s.collisionAt(h,l)===I)return!0;return!1}unstick(t){const e=X(t);if(this.bodyBlocked(t.x,t.y,e)){for(let n=1;n<=6;n++)if(!this.bodyBlocked(t.x,t.y-n*T,e)){t.y-=n*T;return}}}moveX(t,e){const n=X(t);let s=e;for(;Math.abs(s)>1e-4;){const o=Math.max(-1,Math.min(1,s));s-=o;const a=t.x+o;if(!this.bodyBlocked(a,t.y,n)){t.x=a;continue}let c=!1;if(t.grounded||t.coyote>0)for(let r=1;r<=2;r++){const l=t.y-r*T;if(!this.bodyBlocked(a,l,n)&&!this.bodyBlocked(t.x,l,n)){t.x=a,t.y=l,t.stepOffset+=r*T,c=!0;break}}if(!c){t.vx=0;return}}}moveY(t,e){const n=this.terrain;let s=e;for(;Math.abs(s)>1e-4;){const o=Math.max(-1,Math.min(1,s));s-=o;const a=t.y+o;if(o>0){const c=Math.floor((t.y-1e-4)/T),r=Math.floor((a-1e-4)/T);if(r>c){const l=Math.floor((t.x-et/2)/T),h=Math.floor((t.x+et/2-1e-4)/T);let f=ct,u=-1;for(let p=l;p<=h;p++){const m=n.collisionAt(p,r);(m===I||m===Tt&&t.dropTimer<=0)&&(f!==I&&(f=m),(u===-1||n.fgAt(p,r)===St)&&(u=n.fgAt(p,r)))}if(f!==ct)return t.y=r*T,t.floor=f,u}}else{const c=Math.floor((t.y-X(t))/T),r=Math.floor((a-X(t))/T);if(r<c){const l=Math.floor((t.x-et/2)/T),h=Math.floor((t.x+et/2-1e-4)/T);for(let f=l;f<=h;f++)if(n.collisionAt(f,r)===I)return t.vy=0,-1}}t.y=a}return-1}updateMeteors(t){if(this.meteorsEnabled)for(this.spawnTimer-=t;this.spawnTimer<=0;){const n=this.stormTime();this.spawnMeteor(),this.rng.chance(Math.min(.35,n/300))&&this.spawnMeteor(),this.spawnTimer+=oo(n)*this.rng.range(.6,1.3)}const e=this.terrain;for(let n=this.meteors.length-1;n>=0;n--){const s=this.meteors[n];s.vy+=xe*t;const o=Math.max(1,Math.ceil(Math.max(Math.abs(s.vx),Math.abs(s.vy))*t/2));let a=!1;for(let c=0;c<o&&!a&&(s.x+=s.vx*t/o,s.y+=s.vy*t/o,!(s.x<0||s.x>=e.width||s.y>=e.height));c++)(s.y>0&&e.collisionAtPoint(s.x,s.y)!==ct||this.players.some(l=>ro(l,s)))&&(this.explode(s.x,s.y,s.blast),a=!0);if(a||s.x<-60||s.x>e.width+60||s.y>e.height){this.meteors.splice(n,1);continue}this.particles.length<Qe&&(this.addParticle(s.x,s.y,-s.vx*.1+this.rng.range(-20,20),-s.vy*.1,.35,s.size*.9,gt[this.rng.int(0,gt.length-1)],Lt),this.rng.chance(.5)&&this.addParticle(s.x,s.y,this.rng.range(-15,15),-10,.9,s.size*.8,Ye,Kt))}}spawnMeteor(){var p,m;const t=this.stormTime(),e=this.rng,n=this.terrain.width,o=e.chance(Math.min(.7,.25+t/60))?this.meteorAim()+(e.next()-.5)*2*e.range(0,260):e.range(30,n-30),a=Math.max(30,Math.min(n-30,o)),c=e.range(-110,110),r=180+Math.min(260,t*2.4)+e.range(0,80),l=Math.max(0,Math.min(this.terrain.cols-1,Math.floor(a/T))),h=this.terrain.surfaceRow(l)*T-Ue,f=h/r,u={x:a-c*f*.85,y:Ue,vx:c,vy:r,size:3+e.range(0,2.5)+Math.min(3,t/50),blast:io(t,e.next()),eta:(-r+Math.sqrt(r*r+2*xe*h))/xe};this.meteors.push(u),(m=(p=this.listeners).meteor)==null||m.call(p,u)}meteorAim(){const t=this.players.filter(n=>n.alive);return t.length===0?this.focusX():(t.length===1?t[0]:t[this.rng.int(0,t.length-1)]).body.x}explode(t,e,n,s="meteor"){var h,f,u,p,m,b;const o=this.rng,a=this.terrain.carve(t,e,n),c=Math.min(80,8+Math.floor(a.removed/3));for(let v=0;v<c;v++){const A=a.sample.length?a.sample[o.int(0,a.sample.length-1)]:0,x=o.range(0,Math.PI*2),M=o.range(120,460);this.addParticle(t+Math.cos(x)*n*.4,e+Math.sin(x)*n*.4,Math.cos(x)*M,Math.sin(x)*M-160,o.range(.8,1.8),o.range(1.5,3.5),Xt[A]??Ht,zt)}for(let v=0;v<30;v++){const A=o.range(0,Math.PI*2),x=o.range(60,380);this.addParticle(t,e,Math.cos(A)*x,Math.sin(A)*x-80,o.range(.25,.7),o.range(1.5,3.5),gt[o.int(0,gt.length-1)],Lt)}for(let v=0;v<12;v++)this.addParticle(t+o.range(-n,n)*.5,e+o.range(-n,n)*.4,o.range(-40,40),o.range(-70,-10),o.range(1.2,2.4),n*o.range(.3,.6),Ye,Kt);const r={x:t,y:e,radius:n,age:0,proximity:0,cause:s};for(const v of this.players){const A=Be(r,at(v),W(v));r.proximity=Math.max(r.proximity,A),v.shake=Math.min(24,v.shake+(2+n*.3)*(.2+.8*A))}this.blasts.push(r);const l=this.alive;for(const v of this.players)if(v.alive){const A=Ce(t,e,v.body.x,v.body.y,X(v.body));A<n*qt&&v.shield<=0?this.kill(v,t,e,n,s):A<n*Me&&this.knockBack(v.body,t,e,n,Math.max(A,n*qt))}else v.ragdoll&&this.throwBody(v.ragdoll,t,e,n*Me,650);for(const v of this.players){const A=Be(r,at(v),W(v));A>0&&((f=(h=this.listeners).blastNear)==null||f.call(h,v.slot,A,r))}l&&!this.alive&&((p=(u=this.listeners).runOver)==null||p.call(u));for(const v of this.moles)v.state!=="armed"&&Math.hypot(v.x-t,v.y-e)<n*1.5&&this.armMole(v,this.moleRng.range(.06,.24));(b=(m=this.listeners).explosion)==null||b.call(m,r)}knockBack(t,e,n,s,o){const a=1-(o-s*qt)/(s*(Me-qt));let c=t.x-e,r=t.y-X(t)/2-n-s*.35;const l=Math.hypot(c,r)||1;c/=l,r/=l;const h=240+560*a;t.vx+=c*h,t.vy=Math.min(t.vy,0)+r*h-150*a,t.grounded=!1,t.coyote=0,t.stun=.2+.6*a,t.spinVelocity=a>.3?(c>=0?1:-1)*(5+11*a):0}kill(t,e,n,s,o){var c,r;const a=t.body;t.alive=!1,t.deathCause=o,t.diedAt=this.clock,this.deathCause=o,t.ragdoll=new Zn(t.pose,a.vx,a.vy),this.throwBody(t.ragdoll,e,n,s*3.2,1050),(r=(c=this.listeners).death)==null||r.call(c,t.slot,o)}throwBody(t,e,n,s,o){let a=t.centerX()-e,c=t.centerY()-n;const r=Math.hypot(a,c);if(r>=s)return;r<3&&(a=this.rng.sign()*.4,c=-1);const l=Math.hypot(a,c);let h=a/l,f=Math.min(c/l,-.45);const u=Math.hypot(h,f);h/=u,f/=u;const p=1-r/s,m=o*(.45+.55*p),b=(h>=0?1:-1)*this.rng.range(8,16)*(.4+.6*p);t.launch(h*m,f*m,b),t.impulse(e,n,s,o*.25)}spawnMole(t){const e=Yn(this.terrain,this.moleRng,t,300);e&&this.moles.push(qn(e.x,e.y,this.moleRng))}armMole(t,e){var n,s;t.state="armed",t.fuse=e,t.fuseLength=e,(s=(n=this.listeners).moleArmed)==null||s.call(n,t)}updateMoles(t){var o,a,c,r;const e=this.moleTarget,n=this.players.map(l=>({x:at(l),y:W(l)}));this.moleTimer-=t,this.moleTimer<=0&&(this.moleTimer=4,this.moles.length<Je(this.survived)&&this.spawnMole(n));const s=this.moleRng;for(let l=this.moles.length-1;l>=0;l--){const h=this.moles[l];e.active=!1;let f=1/0;for(const m of this.players){if(!m.alive)continue;const b=Math.hypot(m.body.x-h.x,W(m)-h.y);b<f&&(f=b,e.x=m.body.x,e.y=W(m),e.active=!0)}if(h.state==="armed"){Wn(h,this.terrain,t,e),h.fuse-=t,s.chance(t*40)&&this.addParticle(h.x-h.facing*7,h.y-3,s.range(-40,40),s.range(-90,-20),s.range(.15,.35),s.range(1,2),gt[s.int(0,gt.length-1)],Lt),h.fuse<=0&&(this.moles.splice(l,1),this.explode(h.x,h.y,Dn,"mole"));continue}const u=$n(h,this.terrain,s,t,e);if(u==="gone"){this.moles.splice(l,1);continue}const p=n.some(m=>Math.hypot(h.x-m.x,h.y-m.y)<360);if(u==="surface"?(a=(o=this.listeners).moleSurface)==null||a.call(o,h):u==="dive"&&((r=(c=this.listeners).moleDive)==null||r.call(c,h)),u==="surface"||u==="dive")p&&this.dirtBurst(h.x,h.y+(u==="dive"?ht:0),u==="surface"?14:7);else if(h.state==="burrow"&&p)for(h.dust+=t*6;h.dust>=1;){h.dust-=1;const m=this.terrain.fgAt(Math.floor(h.x/T),Math.floor(h.y/T));this.addParticle(h.x+s.range(-4,4),h.y+s.range(-3,3),s.range(-12,12),s.range(-14,4),s.range(.25,.5),s.range(1,1.8),Xt[m]??Ht,se)}if(h.state==="walk"){for(const m of this.players)if(m.alive&&Ce(h.x,h.y,m.body.x,m.body.y,X(m.body))<_n){h.facing=m.body.x>=h.x?1:-1,this.armMole(h,ys);break}}}}dirtBurst(t,e,n){const s=this.moleRng;for(let o=0;o<n;o++){const a=Math.floor((t+s.range(-8,8))/T),c=Math.floor((e+s.range(-8,8))/T),r=this.terrain.fgAt(a,c),l=s.range(-Math.PI,0),h=s.range(40,150);this.addParticle(t,e,Math.cos(l)*h,Math.sin(l)*h,s.range(.4,.9),s.range(1.2,2.6),Xt[r]??Ht,zt)}}addParticle(t,e,n,s,o,a,c,r){this.particles.length>=Qe&&this.particles.shift(),this.particles.push({x:t,y:e,vx:n,vy:s,life:o,max:o,size:a,color:c,kind:r})}puff(t,e,n,s){for(let o=0;o<n;o++){const a=o%2===0?1:-1;this.addParticle(t+a*3,e-1,a*this.rng.range(.4,1)*s,-this.rng.range(10,40),this.rng.range(.3,.6),this.rng.range(1.5,3),Ht,se)}}updateParticles(t){const e=this.terrain,n=this.particles;for(let s=n.length-1;s>=0;s--){const o=n[s];if(o.life-=t,o.life<=0){n[s]=n[n.length-1],n.pop();continue}switch(o.kind){case zt:o.vy+=900*t,e.collisionAtPoint(o.x+o.vx*t,o.y+o.vy*t)===I&&(o.vx*=.3,o.vy=0,o.life=Math.min(o.life,.5));break;case Lt:o.vy+=320*t,o.vx*=Math.exp(-t*2);break;case Kt:o.vy-=18*t,o.vx*=Math.exp(-t*1.5),o.vy*=Math.exp(-t*1.5),o.size+=t*6;break;default:o.vx*=Math.exp(-t*5),o.vy+=60*t}o.x+=o.vx*t,o.y+=o.vy*t}}}function at(i){return i.ragdoll?i.ragdoll.pos[U*2]:i.body.x}function W(i){return i.ragdoll?i.ragdoll.pos[U*2+1]:i.body.y-X(i.body)/2}function X(i){return i.ducked?to:Dt}function ro(i,t){return i.alive?Ce(t.x,t.y,i.body.x,i.body.y,X(i.body))<t.size:i.ragdoll!==null&&Math.hypot(t.x-at(i),t.y-W(i))<t.size+6}function Yt(i,t,e){return i<t?Math.min(t,i+e):Math.max(t,i-e)}function Ze(i){return Math.atan2(Math.sin(i),Math.cos(i))}const co={moveX:[{axis:0},{button:14,scale:-1},{button:15}],moveY:[{axis:1},{button:12,scale:-1},{button:13}],aimX:[{axis:2}],aimY:[{axis:3}],jump:[{button:0}],fire:[{button:7}],pause:[{button:9}]};function ts(i){const t=Object.create(null);for(const[e,n]of Object.entries(i))t[e]=n.map(s=>{const o="button"in s?s.button:s.axis;if(!Number.isInteger(o)||o<0||s.scale!==void 0&&![1,-1].includes(s.scale))throw new Error("Controller bindings need nonnegative integer indices and a scale of 1 or -1.");return{...s}});return t}const es=(i,t=-1)=>Number.isFinite(i)?Math.max(t,Math.min(1,i)):0;function lo(i=co,t={}){const e=ts(i),n=t.deadZone??.18,s=t.buttonThreshold??.5;if(!Number.isFinite(n)||n<0||n>=1||!Number.isFinite(s)||s<=0||s>1)throw new Error("Use a dead zone from 0 up to (excluding) 1 and a button threshold above 0 through 1.");let o=new Map,a=!1,c=!1;const r=new Map,l=()=>{a=!1},h=typeof window<"u"?window:void 0;h==null||h.addEventListener("blur",l),h==null||h.document.addEventListener("visibilitychange",l);const f=t.active??(()=>!!h&&!h.document.hidden&&h.document.hasFocus()),u=t.read??(()=>{if(typeof navigator>"u"||!navigator.getGamepads)throw new Error("Gamepad API unavailable");return navigator.getGamepads()});function p(m){const b=[...o.keys()];return o.clear(),r.clear(),a=!1,{status:m,players:[],connected:[],disconnected:b}}return{poll(){var M;if(c)return p("closed");let m;try{m=Array.from(u()).filter(d=>!!(d!=null&&d.connected))}catch(d){return p(d instanceof Error&&d.name==="SecurityError"?"blocked":"unavailable")}const b=f(),v=new Map,A=[],x=[];for(const d of m){const y=o.get(d.index),S=(y==null?void 0:y.id)===d.id&&y.mapping===d.mapping;S||(A.push(d.index),r.delete(d.index));const E=r.get(d.index),P=d.mapping==="standard"||(E==null?void 0:E.id)===d.id,w=(E==null?void 0:E.bindings)??e,C=d.axes.map(D=>b?es(D):0),k=d.buttons.map(D=>b?es(D.value,0):0),R=Object.create(null);for(const[D,Et]of Object.entries(w)){let Rt=0,Pt=0;if(b&&P)for(const Bt of Et){let xt="button"in Bt?k[Bt.button]??0:C[Bt.axis]??0;"axis"in Bt&&(xt=Math.sign(xt)*Math.max(0,(Math.abs(xt)-n)/(1-n))),xt*=Bt.scale??1,Rt=Math.max(Rt,xt),Pt=Math.min(Pt,xt)}const je=Rt===-Pt?0:Rt>-Pt?Rt:Pt,le=Math.abs(je)>=s,Ve=S&&!!((M=y.actions[D])!=null&&M.down);R[D]={value:je,down:le,pressed:b&&a&&S&&le&&!Ve,released:Ve&&!le}}v.set(d.index,{index:d.index,id:d.id,mapping:d.mapping,mapped:P,axes:C,buttons:k,actions:R})}for(const[d,y]of o){const S=v.get(d);(!S||S.id!==y.id||S.mapping!==y.mapping)&&(x.push(d),S||r.delete(d))}return o=v,a=b,{status:b?v.size?"ready":"waiting":"inactive",players:structuredClone([...v.values()]),connected:A,disconnected:x}},remap(m,b){const v=o.get(m);if(!v||c)throw new Error("Connect and poll this controller before mapping it.");r.set(m,{id:v.id,bindings:ts(b)}),a=!1},reset:l,dispose(){c=!0,p("closed"),h==null||h.removeEventListener("blur",l),h==null||h.document.removeEventListener("visibilitychange",l)}}}const ss={ArrowLeft:"left",KeyA:"left",ArrowRight:"right",KeyD:"right",ArrowUp:"jump",KeyW:"jump",Space:"jump",ArrowDown:"down",KeyS:"down",KeyC:"crouch",ShiftLeft:"crouch",ShiftRight:"crouch"},ns={moveX:[{axis:0},{button:14,scale:-1},{button:15}],moveY:[{axis:1},{button:13}],jump:[{button:0},{button:1},{button:12}],crouch:[{button:2},{button:6}],start:[{button:9}],select:[{button:8}]};class ho{constructor(){g(this,"keys",new Set);g(this,"touches",new Map);g(this,"pads",new Map);g(this,"gamepads",lo(ns,{deadZone:.25,active:()=>!document.hidden}));g(this,"jumpQueued",!1);g(this,"startQueued",!1);g(this,"selectQueued",!1);g(this,"anyWasDown",!1);g(this,"activePad",-1);g(this,"padConnected",!1);g(this,"onGamepadPress",null);g(this,"onTouchSeen",null)}attachKeyboard(t){t.addEventListener("keydown",e=>{const n=ss[e.code];n&&(e.preventDefault(),n==="jump"&&!e.repeat&&!this.keys.has("jump")&&(this.jumpQueued=!0),this.keys.add(n))}),t.addEventListener("keyup",e=>{const n=ss[e.code];n&&this.keys.delete(n)}),t.addEventListener("blur",()=>this.reset())}attachTouchPad(t){const e=n=>{this.touches.delete(n.pointerId)};for(const n of t.querySelectorAll("[data-action]")){const s=n.dataset.action;n.addEventListener("pointerdown",o=>{o.preventDefault(),n.setPointerCapture(o.pointerId),s==="jump"&&!this.isHeld("jump")&&(this.jumpQueued=!0),this.touches.set(o.pointerId,s)}),n.addEventListener("pointerup",e),n.addEventListener("pointercancel",e),n.addEventListener("lostpointercapture",e),n.addEventListener("contextmenu",o=>o.preventDefault())}window.addEventListener("pointerdown",n=>{var s;n.pointerType==="touch"&&((s=this.onTouchSeen)==null||s.call(this))},{capture:!0})}poll(){var n,s,o,a,c,r,l,h;const t=this.gamepads.poll();for(const f of t.players)!f.mapped&&t.connected.includes(f.index)&&this.gamepads.remap(f.index,ns);for(const f of t.disconnected)this.pads.delete(f);let e=!1;for(const f of t.players){const u=f.actions,p=this.pads.get(f.index)??{left:!1,right:!1,jump:!1,down:!1,crouch:!1,jumpQueued:!1},m=((n=u.moveX)==null?void 0:n.value)??0,b=((s=u.moveY)==null?void 0:s.value)??0;p.left=m<-.2,p.right=m>.2,p.down=b>.45,p.jump=!!((o=u.jump)!=null&&o.down),p.crouch=!!((a=u.crouch)!=null&&a.down),(c=u.jump)!=null&&c.pressed&&(p.jumpQueued=!0,this.jumpQueued=!0),(r=u.start)!=null&&r.pressed&&(this.startQueued=!0),(l=u.select)!=null&&l.pressed&&(this.selectQueued=!0),this.pads.set(f.index,p),f.buttons.some(v=>v>=.5)&&(e=!0,this.activePad=f.index)}return e&&!this.anyWasDown&&((h=this.onGamepadPress)==null||h.call(this)),this.anyWasDown=e,this.padConnected=t.players.length>0,t}takeStart(){const t=this.startQueued;return this.startQueued=!1,t}takeSelect(){const t=this.selectQueued;return this.selectQueued=!1,t}rumble(t,e,n){var o,a;const s=t==="solo"?this.activePad:t;if(!(e<=.02||s<0))try{const c=navigator.getGamepads()[s],r=c==null?void 0:c.vibrationActuator;(a=(o=r==null?void 0:r.playEffect)==null?void 0:o.call(r,"dual-rumble",{duration:n,strongMagnitude:Math.min(1,e),weakMagnitude:Math.min(1,e*.7+.1)}))==null||a.catch(()=>{})}catch{}}isHeld(t){if(this.keys.has(t))return!0;for(const e of this.pads.values())if(e[t])return!0;for(const e of this.touches.values())if(e===t)return!0;return!1}controlsFor(t){if(t==="solo"){const s={left:this.isHeld("left"),right:this.isHeld("right"),jump:this.isHeld("jump"),down:this.isHeld("down"),crouch:this.isHeld("crouch"),jumpPressed:this.jumpQueued};this.jumpQueued=!1;for(const o of this.pads.values())o.jumpQueued=!1;return s}const e=this.pads.get(t);if(!e)return{...Pe};const n={left:e.left,right:e.right,jump:e.jump,down:e.down,crouch:e.crouch,jumpPressed:e.jumpQueued};return e.jumpQueued=!1,n}takeAnyJump(){let t=this.jumpQueued;this.jumpQueued=!1;for(const e of this.pads.values())t||(t=e.jumpQueued),e.jumpQueued=!1;return t}reset(){this.keys.clear(),this.touches.clear(),this.jumpQueued=!1,this.startQueued=!1,this.selectQueued=!1;for(const t of this.pads.values())t.jumpQueued=!1}}const fo="http://json-schema.org/draft-07/schema#",uo=1,po="object",mo=!1,yo={screenShake:{type:"boolean",title:"Screen shake",description:"Shake the view when meteors hit. Reduced automatically when the system asks for less motion.",default:!0,"x-napplet-section":"Comfort","x-napplet-order":1},touchControls:{type:"string",title:"Touch controls",description:"Show the on-screen movement and jump pads.",enum:["auto","always","never"],default:"auto","x-napplet-section":"Controls","x-napplet-order":2},soundVolume:{type:"integer",title:"Sound volume",description:"Volume of sound effects and ambience, in percent. There is no music.",minimum:0,maximum:100,default:80,"x-napplet-section":"Sound","x-napplet-order":3},rumble:{type:"boolean",title:"Controller rumble",description:"Vibrate the gamepad on nearby explosions, where the browser supports it.",default:!0,"x-napplet-section":"Controls","x-napplet-order":4}},xo={$schema:fo,$version:uo,type:po,additionalProperties:mo,properties:yo},ot={screenShake:!0,touchControls:"auto",soundVolume:.8,rumble:!0},ws=new Set;function Mo(i){ws.add(i)}us("config")&&(async()=>{he.schema||await he.registerSchema(xo);const i=he.subscribe(t=>{ot.screenShake=t.screenShake!==!1;const e=t.touchControls;ot.touchControls=e==="always"||e==="never"?e:"auto";const n=Number(t.soundVolume);ot.soundVolume=Number.isFinite(n)?Math.max(0,Math.min(100,n))/100:.8,ot.rumble=t.rumble!==!1;for(const s of ws)s()});window.addEventListener("pagehide",()=>i.close(),{once:!0})})().catch(()=>{});const go=340,vo=480,bo=300;class os{constructor(){g(this,"x",0);g(this,"y",0);g(this,"width",1);g(this,"height",1);g(this,"zoom",1);g(this,"camX",0);g(this,"camY",0);g(this,"under",0);g(this,"skyKey","");g(this,"sky",null);g(this,"snapped",!1)}place(t){if(t.x===this.x&&t.y===this.y&&t.width===this.width&&t.height===this.height)return;this.x=t.x,this.y=t.y,this.width=Math.max(1,t.width),this.height=Math.max(1,t.height);const e=this.height>this.width?bo:vo;this.zoom=tt(Math.min(this.height/go,this.width/e),.35,4),this.skyKey=""}}class wo{constructor(t){g(this,"ctx");g(this,"terrainCanvas",document.createElement("canvas"));g(this,"terrainCtx",null);g(this,"image",null);g(this,"terrain",null);g(this,"width",1);g(this,"height",1);g(this,"dpr",1);g(this,"views",new Map);g(this,"v",new os);g(this,"split",!1);g(this,"stars",[]);g(this,"colorCache",new Map);g(this,"fungusSprite",is(vn));g(this,"emberSprite",is(qe));g(this,"options",{shake:1,flashes:!0});this.canvas=t;const e=t.getContext("2d",{alpha:!1});if(!e)throw new Error("Canvas 2D is unavailable");this.ctx=e;for(let n=0;n<70;n++)this.stars.push(Math.random(),Math.random()*.45,Math.random())}resize(t,e,n){this.width=Math.max(1,t),this.height=Math.max(1,e),this.dpr=n,this.canvas.width=Math.round(this.width*n),this.canvas.height=Math.round(this.height*n);for(const s of this.views.values())s.skyKey=""}bind(t){var n;const e=t.terrain;this.terrain=e,this.terrainCanvas.width=e.cols,this.terrainCanvas.height=e.rows,this.terrainCtx=this.terrainCanvas.getContext("2d"),this.image=((n=this.terrainCtx)==null?void 0:n.createImageData(e.cols,e.rows))??null,e.dirty={x0:0,y0:0,x1:e.cols-1,y1:e.rows-1},this.views.clear()}render(t,e,n,s=null){const{ctx:o,dpr:a}=this,c=t.terrain;c!==this.terrain&&this.bind(t),this.paintTerrain(c),this.split=n.length>1;for(const r of[...this.views.keys()])n.some(l=>l.slot===r)||this.views.delete(r);for(const r of n){let l=this.views.get(r.slot);l||(l=new os,this.views.set(r.slot,l)),l.place(r.rect),this.v=l,o.save(),o.setTransform(a,0,0,a,0,0),o.beginPath(),o.rect(l.x,l.y,l.width,l.height),o.clip(),this.renderPane(t,e,r.slot),o.restore()}if(o.setTransform(a,0,0,a,0,0),s&&(o.fillStyle=`rgb(${Ct})`,o.fillRect(s.x,s.y,s.width,s.height)),this.split){o.fillStyle=Mt;for(const r of n){const l=r.rect;l.x>0&&o.fillRect(l.x-1,l.y,2,l.height),l.y>0&&o.fillRect(l.x,l.y-1,l.width,2)}}}renderPane(t,e,n){var d;const{ctx:s,dpr:o,v:a}=this,c=t.terrain,r=t.viewTarget(n);a.snapped||(a.under=this.undergroundTarget(t,n),a.camX=t.focusX(n),a.camY=this.targetY(t,n),a.snapped=!0);const l=r!=null&&r.alive?r.body.vx*.3:0,h=1-Math.exp(-e*5);a.under+=(this.undergroundTarget(t,n)-a.under)*(1-Math.exp(-e*2.5)),a.camX+=(t.focusX(n)+l-a.camX)*h,a.camY+=(this.targetY(t,n)-a.camY)*h,this.clampCamera(c);const f=a.zoom,u=Math.min(1,t.stormTime()/150);this.drawSky(u),this.drawHills(On,.2,70,.0035,1.3,u),this.drawHills(In,.45,50,.006,4.1,u);const p=((r==null?void 0:r.shake)??0)*this.options.shake,m=(Math.random()-.5)*p*f,b=(Math.random()-.5)*p*f,v=a.width/2-a.camX*f+m,A=a.height/2-a.camY*f+b,x=()=>s.setTransform(o*f,0,0,o*f,o*(a.x+v),o*(a.y+A));x(),this.drawTerrain(c,v,A),this.drawParticles(t,!1),this.drawMoles(t);for(const y of t.players)y.slot!==n&&this.drawStickman(y,t.clock);const M=t.player(n);M&&this.drawStickman(M,t.clock),this.drawMeteors(t),this.drawBlasts(t),this.drawParticles(t,!0),this.screen(),this.drawDarkness(t,n,v,A),x(),this.drawLights(t,n,v,A),this.screen(),this.split&&this.drawTags(t,n,v,A),this.drawWarnings(t,v,A),this.drawFlash(t,n),this.split&&!((d=t.player(n))!=null&&d.alive)&&t.alive&&(s.fillStyle=`rgba(${Ct}, 0.3)`,s.fillRect(0,0,a.width,a.height))}screen(){const{dpr:t,v:e}=this;this.ctx.setTransform(t,0,0,t,t*e.x,t*e.y)}targetY(t,e){return t.focusY(e)-(20+this.v.height/this.v.zoom*.1)*(1-this.v.under)}undergroundTarget(t,e){return tt((t.terrain.depthAt(t.focusX(e),t.focusY(e))-4)/22,0,1)}clampCamera(t){const e=this.v,n=e.width/e.zoom,s=e.height/e.zoom;e.camX=n>=t.width?t.width/2:tt(e.camX,n/2,t.width-n/2);const o=-260+s/2,a=t.height-s/2;e.camY=o>=a?a:tt(e.camY,o,a)}drawSky(t){const{ctx:e,v:n}=this,{width:s,height:o}=n,a=`${s}x${o}:${Math.round(t*40)}`;if(a!==n.skyKey||!n.sky){n.skyKey=a;const f=e.createLinearGradient(0,0,0,o);[0,.45,.8,1].forEach((p,m)=>f.addColorStop(p,pe(de(Cn[m],Ln[m],t)))),n.sky=f}this.screen(),e.fillStyle=n.sky,e.fillRect(0,0,s,o),e.fillStyle="rgba(255, 240, 220, 1)";for(let f=0;f<this.stars.length;f+=3)e.globalAlpha=(.25+this.stars[f+2]*.5)*(1-t*.7),e.fillRect(this.stars[f]*s,this.stars[f+1]*o,1.2,1.2);e.globalAlpha=1;const c=Math.min(s,o)*.13,r=s*.72-n.camX*n.zoom*.02%s,l=o*.58,h=e.createRadialGradient(r,l,c*.6,r,l,c*2.6);h.addColorStop(0,"rgba(255, 214, 150, 0.45)"),h.addColorStop(1,"rgba(255, 214, 150, 0)"),e.fillStyle=h,e.fillRect(r-c*3,l-c*3,c*6,c*6),e.fillStyle="rgba(255, 232, 186, 0.92)",e.beginPath(),e.arc(r,l,c,0,Math.PI*2),e.fill()}drawHills(t,e,n,s,o,a){const{ctx:c}=this,{width:r,height:l,zoom:h,camX:f,camY:u}=this.v,p=l/2+(360-u)*h*e-n*h*.2,m=f*h*e;c.fillStyle=pe(de(t,2756386,a*.5)),c.beginPath(),c.moveTo(0,l);for(let b=0;b<=r+8;b+=8){const v=(b+m)/h,A=Math.sin(v*s+o)*.6+Math.sin(v*s*2.3+o*2)*.3+Math.sin(v*s*5.1)*.1;c.lineTo(b,p-A*n*h)}c.lineTo(r,l),c.closePath(),c.fill()}paintTerrain(t){const e=t.dirty;if(!e||!this.image||!this.terrainCtx)return;t.dirty=null;const n=this.image.data,{cols:s,rows:o,fg:a,bg:c,noise:r,scorch:l,surface:h}=t;for(let f=e.y0;f<=e.y1;f++)for(let u=e.x0;u<=e.x1;u++){const p=f*s+u,m=p*4,b=a[p],v=c[p];let A,x=1;if(b){A=b===St&&r[p]>214?kn:Xt[b];const M=f===0||a[p-s]===0,d=u>0&&a[p-1]===0||u<s-1&&a[p+1]===0||f<o-1&&a[p+s]===0;x+=(r[p]-128)/128*.07,M?x+=.24:d&&(x-=.3),x-=Math.min(.4,Math.max(0,f-h[u]-6)*.004)}else if(v)A=v===_e?Mn[r[p]&3]:xn[v],x+=v===st||v===Jt?0:(r[p]-128)/128*.04;else if(f>h[u])A=gn,x=.9+(r[p]-128)/128*.12-Math.min(.3,(f-h[u])*.003);else{n[m+3]=0;continue}l[p]&&(A=de(A,En,l[p]/255*.82)),n[m]=Math.min(255,(A>>16&255)*x),n[m+1]=Math.min(255,(A>>8&255)*x),n[m+2]=Math.min(255,(A&255)*x),n[m+3]=255}this.terrainCtx.putImageData(this.image,0,0,e.x0,e.y0,e.x1-e.x0+1,e.y1-e.y0+1)}drawTerrain(t,e,n){const{ctx:s}=this,{zoom:o,width:a,height:c}=this.v,r=Math.max(0,Math.floor(-e/o/T)-1),l=Math.min(t.cols,Math.ceil((a-e)/o/T)+1),h=Math.max(0,Math.floor(-n/o/T)-1),f=Math.min(t.rows,Math.ceil((c-n)/o/T)+1);l<=r||f<=h||(s.imageSmoothingEnabled=!1,s.drawImage(this.terrainCanvas,r,h,l-r,f-h,r*T,h*T,(l-r)*T,(f-h)*T))}drawStickman(t,e){const n=t.ragdoll?t.ragdoll.pos:t.pose,s=this.ctx;s.lineCap="round",s.lineJoin="round";const o=this.split?[[Mt,4.6,1.2],[wt[t.slot%wt.length],2.5,0]]:[[Rn,4.6,1.2],[Mt,2.5,0]];t.shield>0&&Math.sin(e*30)>0&&(s.globalAlpha=.45);for(const[a,c,r]of o){s.strokeStyle=a,s.lineWidth=c,s.beginPath();for(const[l,h]of gs)s.moveTo(n[l*2],n[l*2+1]),s.lineTo(n[h*2],n[h*2+1]);s.stroke(),s.fillStyle=a,s.beginPath(),s.arc(n[nt*2],n[nt*2+1],V.headRadius+r,0,Math.PI*2),s.fill()}s.globalAlpha=1}drawTags(t,e,n,s){const{ctx:o,v:a}=this;o.font="700 10px system-ui, sans-serif",o.textAlign="center",o.textBaseline="bottom",o.lineJoin="round";const c=[...t.players.filter(r=>r.slot!==e),...t.players.filter(r=>r.slot===e)];for(const r of c){const l=r.ragdoll?r.ragdoll.pos:r.pose,h=tt(n+l[nt*2]*a.zoom,10,a.width-10),f=tt(s+l[nt*2+1]*a.zoom-(V.headRadius+4)*a.zoom,12,a.height-2),u=`P${r.slot+1}`;o.globalAlpha=r.alive?.95:.5,o.lineWidth=3,o.strokeStyle=Mt,o.strokeText(u,h,f),o.fillStyle=wt[r.slot%wt.length],o.fillText(u,h,f)}o.globalAlpha=1}drawMeteors(t){const e=this.ctx;e.globalCompositeOperation="lighter";for(const n of t.meteors){const s=n.size*3.2,o=e.createRadialGradient(n.x,n.y,0,n.x,n.y,s);o.addColorStop(0,`rgba(${ue}, 0.85)`),o.addColorStop(1,`rgba(${ue}, 0)`),e.fillStyle=o,e.fillRect(n.x-s,n.y-s,s*2,s*2),e.strokeStyle=`rgba(${ue}, 0.5)`,e.lineWidth=n.size*1.3,e.lineCap="round",e.beginPath(),e.moveTo(n.x,n.y),e.lineTo(n.x-n.vx*.07,n.y-n.vy*.07),e.stroke()}e.globalCompositeOperation="source-over";for(const n of t.meteors)e.fillStyle="#3a2430",e.beginPath(),e.arc(n.x,n.y,n.size,0,Math.PI*2),e.fill(),e.fillStyle=Pn,e.beginPath(),e.arc(n.x+n.vx*.004,n.y+n.vy*.004,n.size*.62,0,Math.PI*2),e.fill()}drawBlasts(t){const e=this.ctx;for(const n of t.blasts){const s=n.age/.6;if(n.age<.22){const o=n.radius*(1.25-n.age*2),a=e.createRadialGradient(n.x,n.y,0,n.x,n.y,o);a.addColorStop(0,"rgba(255, 250, 220, 0.95)"),a.addColorStop(.5,"rgba(255, 160, 60, 0.8)"),a.addColorStop(1,"rgba(220, 60, 30, 0)"),e.fillStyle=a,e.beginPath(),e.arc(n.x,n.y,o,0,Math.PI*2),e.fill()}e.strokeStyle=`rgba(255, 230, 190, ${.7*(1-s)})`,e.lineWidth=2.5*(1-s)+.5,e.beginPath(),e.arc(n.x,n.y,n.radius*(.8+s*2.2),0,Math.PI*2),e.stroke()}}drawParticles(t,e){const n=this.ctx;e&&(n.globalCompositeOperation="lighter");for(const s of t.particles){if(s.kind===Lt!==e)continue;const a=s.life/s.max;n.fillStyle=this.color(s.color),s.kind===Kt?(n.globalAlpha=.4*a,n.beginPath(),n.arc(s.x,s.y,s.size,0,Math.PI*2),n.fill()):s.kind===zt||s.kind===se?(n.globalAlpha=s.kind===se?.7*a:Math.min(1,a*3),n.fillRect(s.x-s.size/2,s.y-s.size/2,s.size,s.size)):(n.globalAlpha=a,n.fillRect(s.x-s.size/2,s.y-s.size/2,s.size,s.size))}n.globalAlpha=1,n.globalCompositeOperation="source-over"}drawMoles(t){const e=this.ctx,n=t.terrain;for(const s of t.moles){if(s.state==="burrow"||s.state==="armed"&&n.collisionAtPoint(s.x,s.y)===I)continue;const o=Math.min(1,s.pop/.2),a=s.state==="armed"?1-s.fuse/s.fuseLength:0,c=(.7+.45*To(o))*(1+a*.5),r=s.state==="walk"&&s.grounded,l=r?Math.abs(Math.sin(s.phase))*.9:0,h=a>0?(Math.random()-.5)*a*2.4:0,f=a>0&&Math.sin(t.clock*(12+a*40))>0;e.save(),e.translate(s.x+h,s.y+ht-l),e.scale(s.facing*c,c),e.strokeStyle=Mt,e.lineWidth=1.2,e.lineCap="round",e.beginPath(),e.moveTo(-5.5,-4),e.quadraticCurveTo(-9,-4.5,-9.5,-7.5),e.stroke(),e.fillStyle=Mt,vt(e,0,-4.3,7.3,5),e.fillStyle=f?Sn:bn,vt(e,0,-4.3,6.5,4.3),e.fillStyle=f?"#ffb38a":wn,vt(e,1.2,-2.4,4,1.9),e.fillStyle=Tn,vt(e,6.6,-3.8,1.9,1.4);const u=r?Math.sin(s.phase*2)*1.3:0;e.fillStyle=An,vt(e,3.6+u,-.6,1.9,1),vt(e,-2.6-u,-.6,1.7,.9),e.restore()}}drawDarkness(t,e,n,s){const{ctx:o}=this,{zoom:a,width:c,height:r,under:l}=this.v;if(l<.02)return;const h=n+t.focusX(e)*a,f=s+t.focusY(e)*a,u=o.createRadialGradient(h,f,34*a,h,f,210*a);u.addColorStop(0,`rgba(${Ct}, 0)`),u.addColorStop(.55,`rgba(${Ct}, ${.6*l})`),u.addColorStop(1,`rgba(${Ct}, ${.94*l})`),o.fillStyle=u,o.fillRect(0,0,c,r)}drawLights(t,e,n,s){const{ctx:o}=this,{zoom:a,width:c,height:r,under:l}=this.v,h=t.terrain,f=-n/a-30,u=(c-n)/a+30,p=-s/a-30,m=(r-s)/a+30,b=(x,M)=>x>f&&x<u&&M>p&&M<m;o.globalCompositeOperation="lighter",o.globalAlpha=.25+.45*l;for(const x of h.glows){if(h.bg[x]!==Jt)continue;const M=(x%h.cols+.5)*T,d=(Math.floor(x/h.cols)+.5)*T;if(!b(M,d))continue;const y=13+Math.sin(t.clock*1.7+x)*1.5;o.drawImage(this.fungusSprite,M-y,d-y,y*2,y*2)}const v=t.focusX(e),A=t.focusY(e);for(const x of t.moles){if(!b(x.x,x.y))continue;const M=x.state==="burrow"||h.collisionAtPoint(x.x,x.y)===I;if(x.state==="armed"){const E=1-x.fuse/x.fuseLength,P=10+E*22+Math.sin(t.clock*30)*2;o.globalAlpha=.35+E*.55,o.drawImage(this.emberSprite,x.x-P,x.y-P,P*2,P*2)}const d=M?Math.max(0,1-Math.hypot(x.x-v,x.y-A)/200)*.45:1;if(d<=.01)continue;const y=x.x+x.facing*3.4,S=x.y-1.2;o.globalAlpha=d*.5,o.drawImage(this.emberSprite,y-5,S-5,10,10),o.globalAlpha=d,o.fillStyle=`rgb(${qe})`,o.fillRect(y-.8,S-.8,1.6,1.6)}o.globalAlpha=1,o.globalCompositeOperation="source-over"}drawWarnings(t,e,n){const{ctx:s}=this,{zoom:o,width:a,height:c}=this.v;for(const r of t.meteors){const l=n+r.y*o;if(l>0)continue;const h=tt(e+r.x*o,10,a-10),f=tt(1+l/(c*1.6),.15,1),u=4+r.blast*.12*f;s.fillStyle=Bn,s.globalAlpha=.35+f*.6,s.beginPath(),s.moveTo(h,4+u*1.4),s.lineTo(h-u,4),s.lineTo(h+u,4),s.closePath(),s.fill()}s.globalAlpha=1}drawFlash(t,e){if(!this.options.flashes)return;const n=t.focusX(e),s=t.focusY(e);let o=0;for(const a of t.blasts)a.age<.15&&(o=Math.max(o,Be(a,n,s)*.45*(1-a.age/.15)));o<=.01||(this.ctx.fillStyle=`rgba(255, 226, 180, ${o})`,this.ctx.fillRect(0,0,this.v.width,this.v.height))}color(t){let e=this.colorCache.get(t);return e||(e=pe(t),this.colorCache.set(t,e)),e}}function vt(i,t,e,n,s){i.beginPath(),i.ellipse(t,e,n,s,0,0,Math.PI*2),i.fill()}function To(i){return 1+(1.9+1)*(i-1)**3+1.9*(i-1)**2}function is(i){const t=document.createElement("canvas");t.width=t.height=64;const e=t.getContext("2d");if(e){const n=e.createRadialGradient(32,32,0,32,32,32);n.addColorStop(0,`rgba(${i}, 0.9)`),n.addColorStop(.35,`rgba(${i}, 0.35)`),n.addColorStop(1,`rgba(${i}, 0)`),e.fillStyle=n,e.fillRect(0,0,64,64)}return t}function tt(i,t,e){return Math.max(t,Math.min(e,i))}const Ao=4;class So{constructor(){g(this,"mode","solo");g(this,"players",[{slot:0,source:"solo"}])}sync(t,e="ready",n=[]){const s={added:[],removed:[]};if(e==="blocked"||e==="unavailable")return s;const o=new Set(t);if(this.mode==="split"){const a=this.players.filter(c=>typeof c.source=="number"&&(!o.has(c.source)||n.includes(c.source)));a.length===this.players.length&&a.shift();for(const c of a)this.remove(c.slot,s);this.players.length<=1&&(this.mode="solo",this.players[0].source="solo")}if(this.mode==="solo"){if(o.size<2)return s;this.mode="split";const a=[...o].sort((c,r)=>c-r);this.players[0].source=a[0]}for(const a of[...o].sort((c,r)=>c-r)){if(this.players.length>=Ao)break;if(this.players.some(r=>r.source===a))continue;const c=[0,1,2,3].find(r=>!this.players.some(l=>l.slot===r));this.players.push({slot:c,source:a}),s.added.push(c)}return this.players.sort((a,c)=>a.slot-c.slot),s}sourceOf(t){var e;return(e=this.players.find(n=>n.slot===t))==null?void 0:e.source}remove(t,e){this.players=this.players.filter(n=>n.slot!==t),e.removed.push(t)}}const as=480/340;function ko(i,t,e){let n,s;if(i<=1)n=s=1;else if(i===2){const a=Math.abs(Math.log(t/2/e/as)),c=Math.abs(Math.log(t/(e/2)/as));[n,s]=a<c?[2,1]:[1,2]}else n=s=2;const o=[];for(let a=0;a<n*s;a++){const c=a%n,r=Math.floor(a/n),l=Math.floor(c*t/n),h=Math.floor(r*e/s);o.push({x:l,y:h,width:Math.floor((c+1)*t/n)-l,height:Math.floor((r+1)*e/s)-h})}return o}const $t=1/120,Eo=1300,Ts="best-seconds",As="sound-muted",B={app:j("#app"),canvas:j("#scene"),clock:j("#clock"),best:j("#best"),bestLabel:j("#bestLabel"),pause:j("#pauseButton"),sound:j("#soundButton"),overlay:j("#overlay"),kicker:j("#overlayKicker"),headline:j("#overlayHeadline"),detail:j("#overlayDetail"),go:j("#overlayButton"),touchPad:j("#touchPad"),panes:j("#panes")},Gt=new wo(B.canvas),F=new ho,O=new qs,dt=new So,Le=window.matchMedia("(prefers-reduced-motion: reduce)"),Ss=window.matchMedia("(pointer: coarse)");let L="title",_=Ps(),ks=0,pt=!1,mt=0,yt=us(fs),ne=!1,Oe=!1,rs="",Es=1,Rs=1,cs="";function j(i){const t=document.querySelector(i);if(!t)throw new Error(`Missing required element: ${i}`);return t}function Ps(){const i=new ao(Math.random()*4294967296>>>0,dt.players.map(t=>t.slot));return i.listeners={death:t=>{O.death(),ls(t,1,600)},runOver:()=>{L="dead",ks=performance.now(),pt=!1,B.app.dataset.mode=L},explosion:t=>O.explosion(t),blastNear:(t,e,n)=>ls(t,e**1.5,160+n.radius*6),jump:()=>O.jump(),land:t=>O.land(t),bounce:()=>O.bounce(),footstep:()=>O.footstep(),meteor:t=>O.meteor(t),moleSurface:t=>O.moleSurface(t),moleDive:t=>O.moleDive(t),moleArmed:t=>O.moleArmed(t)},i}function jt(i){if(i<60)return`${i.toFixed(1)}s`;const t=Math.floor(i/60),e=i-t*60;return`${t}:${e.toFixed(1).padStart(4,"0")}`}function De(i){L=i,B.app.dataset.mode=i,B.pause.setAttribute("aria-label",i==="paused"?"Resume":"Pause"),F.reset(),O.setPaused(i==="paused")}function ls(i,t,e){ot.rumble&&F.rumble(dt.sourceOf(i)??"solo",t,e)}function Bs(i,t,e,n){B.kicker.textContent=i,B.headline.textContent=t,B.detail.textContent=e,B.go.textContent=n,B.overlay.hidden=!1,B.app.dataset.overlay="on",B.go.focus({preventScroll:!0})}function Cs(){B.overlay.hidden=!0,B.app.dataset.overlay="off",B.canvas.focus({preventScroll:!0})}function ae(){L==="dead"&&(_=Ps(),Gt.bind(_)),_.meteorsEnabled=!0,De("playing"),Cs(),O.click()}function re(){L==="playing"&&(O.click(),De("paused"),Bs("Paused",jt(_.survived),"The storm waits for you.","Resume"))}function kt(){L==="paused"&&(De("playing"),Cs(),O.click())}function Ro(){L==="playing"?re():L==="paused"?kt():(L==="title"||pt)&&ae()}function Po(){pt=!0;const i=_.survived,t=i>mt;t&&(mt=i,Lo(i)),ce();const e=_.players.length>1?["Everyone's down","Squad wiped","Nobody made it"]:_.deathCause==="mole"?["Mole-bombed","Dug up","Ambushed below","Too close"]:["Flattened","Vaporised","Sent flying","Cratered","Gone skyward"],n=e[Math.floor(Math.random()*e.length)];Bs(n,jt(i),Ls(t),"Again")}function Ls(i){const t=ne?" Best time could not be saved.":yt?"":" Best time lasts for this session only.";return(i?"New best!":`Best ${jt(mt)}.`)+t}B.go.addEventListener("click",()=>{L==="paused"?kt():ae()});B.pause.addEventListener("click",()=>{L==="playing"?re():L==="paused"&&kt()});window.addEventListener("keydown",i=>{if(i.code==="KeyM"){Ge();return}if(i.code==="Escape"||i.code==="KeyP"){L==="playing"?re():L==="paused"&&kt();return}if(i.code==="Enter"||i.code==="KeyR"){if(i.target===B.go)return;L==="title"||L==="dead"&&pt?ae():L==="paused"&&i.code==="Enter"&&kt()}});document.addEventListener("visibilitychange",()=>{document.hidden&&re()});for(const i of["keydown","pointerdown"])window.addEventListener(i,()=>O.unlock(),{capture:!0});F.onGamepadPress=()=>O.unlock();B.sound.addEventListener("click",()=>Ge());function Ge(){Os(!O.isMuted),yt&&oe.setItem(As,O.isMuted?"1":"0").catch(()=>{})}function Os(i){O.setMuted(i),B.sound.setAttribute("aria-pressed",String(i)),B.sound.setAttribute("aria-label",i?"Unmute sound":"Mute sound"),B.app.dataset.sound=i?"off":"on"}async function Bo(){if(yt)try{await oe.getItem(As)==="1"&&Os(!0)}catch{}}function ce(){B.best.textContent=mt>0?jt(mt):"–",B.bestLabel.textContent=yt&&!ne?"Best":"Session best"}async function Co(){if(yt){try{const i=await oe.getItem(Ts),t=i?Number.parseFloat(i):0;Number.isFinite(t)&&t>mt&&(mt=t)}catch{yt=!1}ce()}}async function Lo(i){if(yt){try{await oe.setItem(Ts,i.toFixed(2)),ne=!1}catch{ne=!0,L==="dead"&&pt&&(B.detail.textContent=Ls(!0))}ce()}}function Vt(){const i=Le.matches?.25:1;Gt.options={shake:ot.screenShake?i:0,flashes:!Le.matches},O.setVolume(ot.soundVolume);const t=ot.touchControls,e=t==="always"||t==="auto"&&(Ss.matches||Oe);B.app.dataset.touch=e?"on":"off"}Mo(Vt);Le.addEventListener("change",Vt);Ss.addEventListener("change",Vt);F.onTouchSeen=()=>{Oe||(Oe=!0,Vt())};function Is(){const i=B.app.getBoundingClientRect();Es=Math.max(1,i.width),Rs=Math.max(1,i.height),Gt.resize(i.width,i.height,Math.min(2,window.devicePixelRatio||1))}function Oo(i){for(const t of i.removed)_.removePlayer(t);if(L!=="dead")for(const t of i.added)_.addPlayer(t);B.app.dataset.split=dt.mode==="split"?"on":"off"}function Io(){const i=dt.players.length,t=ko(i,Math.round(Es),Math.round(Rs));return{panes:dt.players.map((e,n)=>({slot:e.slot,rect:t[n]})),spare:t.length>i?t[i]:null}}function _o(i,t){const e=i.length>1,n=i.map(o=>{const a=_.player(o.slot);if(!a||a.alive||!_.alive)return"";const c=_.viewTarget(o.slot);return _.clock-a.diedAt>=bs&&c&&c!==a?`watching P${c.slot+1}`:"down"}),s=JSON.stringify([e,i,t,n]);if(s!==cs&&(cs=s,B.panes.replaceChildren(),!!e&&(i.forEach((o,a)=>{const c=document.createElement("div");c.className="pane-label",c.style.cssText=`left:${o.rect.x}px;top:${o.rect.y}px;width:${o.rect.width}px;height:${o.rect.height}px`,c.style.setProperty("--player",wt[o.slot%wt.length]);const r=document.createElement("span");if(r.className="pane-chip",r.textContent=`P${o.slot+1}`,c.append(r),n[a]){const l=document.createElement("span");l.className="pane-state",l.textContent=n[a],c.append(l)}B.panes.append(c)}),t))){const o=document.createElement("div");o.className="pane-spare",o.style.cssText=`left:${t.x}px;top:${t.y}px;width:${t.width}px;height:${t.height}px`,o.textContent="Plug in a controller to join",B.panes.append(o)}}new ResizeObserver(Is).observe(B.app);let hs=performance.now(),Wt=0;function _s(i){const t=Math.min(.1,(i-hs)/1e3);hs=i;const e=F.poll(),n=F.padConnected?"on":"off";B.app.dataset.pad!==n&&(B.app.dataset.pad=n);const s=dt.sync(e.players.map(r=>r.index),e.status,e.disconnected);if((s.added.length||s.removed.length)&&Oo(s),F.takeSelect()&&Ge(),F.takeStart()&&Ro(),L==="paused")F.takeAnyJump()&&kt();else if(Wt+=t,Wt>=$t){(L==="title"||L==="dead"&&pt)&&F.takeAnyJump()&&ae();const r=new Map;for(const f of dt.players)r.set(f.slot,L==="playing"?F.controlsFor(f.source):Pe);F.takeAnyJump();let l=!0;const h=f=>{const u=r.get(f)??Pe;return l||!u.jumpPressed?u:{...u,jumpPressed:!1}};for(;Wt>=$t;)_.update($t,h),l=!1,Wt-=$t}const{panes:o,spare:a}=Io();Gt.render(_,L==="paused"?0:t,o,a),_o(o,a),O.update(_,L==="paused"?0:t);const c=jt(_.survived);c!==rs&&(rs=c,B.clock.value=c),L==="dead"&&!pt&&i-ks>Eo&&Po(),requestAnimationFrame(_s)}F.attachKeyboard(window);F.attachTouchPad(B.touchPad);B.canvas.tabIndex=-1;Is();Gt.bind(_);Vt();ce();Co();Bo();requestAnimationFrame(_s);
</script>
    <style>:root{--ink: #140e1a;--ink-soft: rgba(20, 14, 26, .5);--cream: #fff1dc;--cream-dim: rgba(255, 241, 220, .78);--molten: #ff7a2f;--molten-deep: #9c3a14;--ember: #ff4a3d;--sky-top: #2c1b45;--font-display: "Bahnschrift Condensed", "Oswald", "Roboto Condensed", "Arial Narrow", Impact, sans-serif;--font-body: ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;--pad: clamp(4px, 1.6vmin, 14px);--pad-button: clamp(44px, 13vmin, 76px);--napplet-text-selection: none;color-scheme:dark;font:14px/1.35 var(--font-body)}*{box-sizing:border-box}:where(html,body,body *){-webkit-user-select:var(--napplet-text-selection, none);user-select:var(--napplet-text-selection, none)}html,body,#app{height:100%;margin:0;background:var(--sky-top);color:var(--cream)}.app{position:relative;overflow:hidden;touch-action:none;-webkit-tap-highlight-color:transparent}.scene{position:absolute;top:0;right:0;bottom:0;left:0;display:block;width:100%;height:100%;outline:none}button{font:inherit;color:inherit;cursor:pointer}button:focus-visible{outline:3px solid var(--cream);outline-offset:2px}.hud{position:absolute;inset:0 0 auto;display:flex;align-items:flex-start;gap:clamp(8px,3vmin,28px);padding:var(--pad) var(--pad) 0;pointer-events:none;font-family:var(--font-display);text-transform:uppercase;text-shadow:0 1px 0 var(--ink),0 0 6px var(--ink-soft)}.readout{display:grid;line-height:1}.hud-label{font-size:clamp(9px,2vmin,12px);letter-spacing:.18em;color:var(--cream-dim)}.clock{font-size:clamp(18px,6vmin,40px);font-weight:700;font-variant-numeric:tabular-nums;letter-spacing:.02em}.best{font-size:clamp(13px,3.4vmin,22px);font-weight:700;font-variant-numeric:tabular-nums;color:var(--molten)}.hud-button{pointer-events:auto;display:grid;place-items:center;width:44px;height:44px;margin-top:-4px;margin-right:-4px;padding:0;border:2px solid rgba(255,241,220,.4);border-radius:50%;background:var(--ink-soft);font-size:13px;letter-spacing:-.1em}.sound{margin-left:auto}.sound svg{width:18px;height:18px;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}.sound .speaker{fill:currentColor}.app[data-sound=on] .sound .cross,.app[data-sound=off] .sound .waves{display:none}.app:not([data-mode=playing],[data-mode=paused]) .hud-button,.app[data-overlay=on] .readout{visibility:hidden}.overlay{position:absolute;top:0;right:0;bottom:0;left:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:clamp(4px,1.8vmin,14px);padding:var(--pad);text-align:center;background:radial-gradient(ellipse at center,#140e1a73,#140e1ad9)}.overlay[hidden]{display:none}.overlay p{margin:0}.kicker{font-family:var(--font-display);font-size:clamp(11px,2.8vmin,18px);font-weight:700;letter-spacing:.24em;text-transform:uppercase;color:var(--molten)}.headline{font-family:var(--font-display);font-size:clamp(26px,11vmin,92px);font-weight:700;line-height:.95;text-transform:uppercase;font-variant-numeric:tabular-nums;text-shadow:0 3px 0 var(--ink)}.detail{max-width:36ch;font-size:clamp(12px,2.6vmin,16px);color:var(--cream-dim)}.go{min-width:132px;min-height:44px;margin-top:clamp(2px,1vmin,8px);padding:0 28px;border:0;border-radius:4px;background:var(--molten);box-shadow:0 4px 0 var(--molten-deep);color:var(--ink);font-family:var(--font-display);font-size:clamp(15px,3.2vmin,22px);font-weight:700;letter-spacing:.12em;text-transform:uppercase}.go:hover{background:#ff8c47}.go:active{transform:translateY(3px);box-shadow:0 1px 0 var(--molten-deep)}.hint{font-size:clamp(10px,2.2vmin,13px);color:var(--cream-dim);opacity:.85}.app[data-touch=on] .hint-keys,.app[data-touch=off] .hint-touch,.app[data-pad=off] .hint-pad,.app[data-pad=on] .hint-keys,.app[data-pad=on] .hint-touch{display:none}.panes{position:absolute;top:0;right:0;bottom:0;left:0;pointer-events:none;font-family:var(--font-display);text-transform:uppercase}.pane-label{position:absolute;display:flex;align-items:flex-end;gap:6px;padding:6px;overflow:hidden}.pane-chip{padding:1px 6px;border-radius:3px;background:var(--player);color:var(--ink);font-size:clamp(11px,2.4vmin,15px);font-weight:700;letter-spacing:.08em}.pane-state{font-size:clamp(10px,2.2vmin,13px);letter-spacing:.12em;color:var(--cream);text-shadow:0 1px 0 var(--ink),0 0 6px var(--ink-soft);white-space:nowrap}.pane-spare{position:absolute;display:grid;place-items:center;padding:var(--pad);text-align:center;font-size:clamp(10px,2.4vmin,14px);letter-spacing:.14em;color:var(--cream-dim)}.app[data-split=on] .touch-pad,.app[data-split=on] .hint-keys,.app[data-split=on] .hint-touch{display:none!important}.touch-pad{position:absolute;inset:auto 0 0;display:none;justify-content:space-between;gap:8px;padding:0 max(var(--pad),env(safe-area-inset-right)) max(var(--pad),env(safe-area-inset-bottom)) max(var(--pad),env(safe-area-inset-left));pointer-events:none}.app[data-touch=on][data-mode=playing] .touch-pad{display:flex}.pad-group{display:flex;gap:clamp(6px,2vmin,16px)}.pad-stack{display:flex;gap:inherit}.touch-pad button{pointer-events:auto;touch-action:none;display:grid;place-items:center;width:var(--pad-button);height:var(--pad-button);padding:0;border:2px solid rgba(255,241,220,.45);border-radius:50%;background:#140e1a52;color:var(--cream);font-size:calc(var(--pad-button) * .36);opacity:.8}.touch-pad button:active{background:#ff7a2f8c;opacity:1}.touch-pad .pad-jump{border-color:#ff7a2fcc}@media(max-height:300px),(max-width:300px){.detail,.hint,.readout-best .hud-label{display:none}.hud-button{position:relative;width:30px;height:30px;margin:0;font-size:10px}.hud-button:after{content:"";position:absolute;top:-7px;right:-7px;bottom:-7px;left:-7px}}@media(max-width:240px){:root{--pad-button: 40px}.pad-group{gap:4px}}@media(max-width:280px){.pad-group{align-items:flex-end}.pad-stack{flex-direction:column}}
</style>
    <meta name="napplet-type" content="sickman-survival">
    <meta name="napplet-config-schema" content="{&quot;$schema&quot;:&quot;http://json-schema.org/draft-07/schema#&quot;,&quot;$version&quot;:1,&quot;type&quot;:&quot;object&quot;,&quot;additionalProperties&quot;:false,&quot;properties&quot;:{&quot;screenShake&quot;:{&quot;type&quot;:&quot;boolean&quot;,&quot;title&quot;:&quot;Screen shake&quot;,&quot;description&quot;:&quot;Shake the view when meteors hit. Reduced automatically when the system asks for less motion.&quot;,&quot;default&quot;:true,&quot;x-napplet-section&quot;:&quot;Comfort&quot;,&quot;x-napplet-order&quot;:1},&quot;touchControls&quot;:{&quot;type&quot;:&quot;string&quot;,&quot;title&quot;:&quot;Touch controls&quot;,&quot;description&quot;:&quot;Show the on-screen movement and jump pads.&quot;,&quot;enum&quot;:[&quot;auto&quot;,&quot;always&quot;,&quot;never&quot;],&quot;default&quot;:&quot;auto&quot;,&quot;x-napplet-section&quot;:&quot;Controls&quot;,&quot;x-napplet-order&quot;:2},&quot;soundVolume&quot;:{&quot;type&quot;:&quot;integer&quot;,&quot;title&quot;:&quot;Sound volume&quot;,&quot;description&quot;:&quot;Volume of sound effects and ambience, in percent. There is no music.&quot;,&quot;minimum&quot;:0,&quot;maximum&quot;:100,&quot;default&quot;:80,&quot;x-napplet-section&quot;:&quot;Sound&quot;,&quot;x-napplet-order&quot;:3},&quot;rumble&quot;:{&quot;type&quot;:&quot;boolean&quot;,&quot;title&quot;:&quot;Controller rumble&quot;,&quot;description&quot;:&quot;Vibrate the gamepad on nearby explosions, where the browser supports it.&quot;,&quot;default&quot;:true,&quot;x-napplet-section&quot;:&quot;Controls&quot;,&quot;x-napplet-order&quot;:4}}}">
  </head>
  <body>
    <!--
      The runtime frames this napplet and shows its name, so the game fills the
      frame from the first pixel. The HUD floats over the scene.
    -->
    <main id="app" class="app" data-mode="title" data-touch="off" data-pad="off" data-split="off" data-sound="on" data-overlay="on">
      <canvas id="scene" class="scene" aria-label="Game world"></canvas>
      <div id="panes" class="panes" aria-hidden="true"></div>

      <div class="hud">
        <div class="readout">
          <span class="hud-label">Alive</span>
          <output id="clock" class="clock">0.0s</output>
        </div>
        <div class="readout readout-best">
          <span id="bestLabel" class="hud-label">Best</span>
          <span id="best" class="best">–</span>
        </div>
        <button id="soundButton" class="hud-button sound" type="button" aria-label="Mute sound" aria-pressed="false">
          <svg viewBox="0 0 24 24" aria-hidden="true">
            <path class="speaker" d="M4 9h4l5-4v14l-5-4H4z" />
            <path class="waves" d="M16 8.5a5 5 0 0 1 0 7M18.5 6a8.5 8.5 0 0 1 0 12" />
            <path class="cross" d="M16.5 9.5l5 5m0-5l-5 5" />
          </svg>
        </button>
        <button id="pauseButton" class="hud-button pause" type="button" aria-label="Pause">
          <span aria-hidden="true">❚❚</span>
        </button>
      </div>

      <section id="overlay" class="overlay" aria-live="polite">
        <p id="overlayKicker" class="kicker">Meteor storm incoming</p>
        <p id="overlayHeadline" class="headline">Stay alive.</p>
        <p id="overlayDetail" class="detail">
          Meteors fall faster the longer you last. The caves below are shelter, but the moles in
          them explode when you get close.
        </p>
        <button id="overlayButton" class="go" type="button">Start</button>
        <p class="hint hint-keys">←/→ or A/D run · Space jump · C or Shift crawl · ↓ drop through planks · M sound</p>
        <p class="hint hint-pad">Stick or D-pad run · Ⓐ jump · ▼, Ⓧ or LT crawl · ▼ on planks drops · Start pause · Select sound</p>
        <p class="hint hint-join">Up to 4 controllers join automatically for split screen. Press a button if one isn't detected.</p>
        <p class="hint hint-touch">Hold ◀ ▶ to run · ▲ jump · ▂ crawl · ▼ drop through planks</p>
      </section>

      <div id="touchPad" class="touch-pad">
        <div class="pad-group">
          <button type="button" data-action="left" aria-label="Run left"><span aria-hidden="true">◀</span></button>
          <button type="button" data-action="right" aria-label="Run right"><span aria-hidden="true">▶</span></button>
        </div>
        <div class="pad-group">
          <div class="pad-stack">
            <button type="button" data-action="crouch" aria-label="Crouch and crawl"><span aria-hidden="true">▂</span></button>
            <button type="button" data-action="down" aria-label="Drop down"><span aria-hidden="true">▼</span></button>
          </div>
          <button type="button" data-action="jump" class="pad-jump" aria-label="Jump"><span aria-hidden="true">▲</span></button>
        </div>
      </div>
    </main>
  </body>
</html>