untitled

Pasted Oct 17, 2026, 11:56 AM1 file219 lines

Scan to open on your phone

Point a camera at the QR code - it opens this exact paste, no app needed.

https://codepastes.com/zzgstcbrzv7d87p3
untitled
<!DOCTYPE html>
<html lang="en"><head><meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
<title>Graveyard Guard</title>
<style>
:root{--bg:#14161f;--panel:#232738;--ink:#f3efe2;--dim:#9aa0b8;--gold:#ffc83d;--red:#ff5d6c;--green:#66d98a;--accent:#7c5cff;color-scheme:dark;box-sizing:border-box;padding-top:env(safe-area-inset-top,0px);padding-bottom:env(safe-area-inset-bottom,0px)}
*{box-sizing:border-box;-webkit-tap-highlight-color:transparent;user-select:none}
html,body{height:100%;margin:0;background:var(--bg);color:var(--ink);font-family:"Lilita One","Trebuchet MS",Verdana,sans-serif;overflow:hidden}
#app{height:100%;display:flex;flex-direction:column;max-width:560px;margin:auto}
#hud{display:flex;gap:6px;padding:8px;align-items:center}
.chip{background:var(--panel);border-radius:12px;padding:6px 10px;font-size:18px;display:flex;gap:6px;align-items:center;flex:1;justify-content:center;white-space:nowrap}
.chip small{color:var(--dim);font-size:12px}
#gear{flex:0 0 42px;height:38px;border:0;border-radius:12px;background:var(--panel);color:var(--ink);font-size:20px}
#stage{flex:1;min-height:0;position:relative}
canvas{width:100%;height:100%;display:block;touch-action:none}
#info{position:absolute;left:8px;right:8px;bottom:8px;background:#232738ee;border-radius:14px;padding:8px 10px;display:none;gap:8px;align-items:center;font-size:15px}
#info .t{flex:1;line-height:1.15}#info small{color:var(--dim);font-size:12px}
.btn{border:0;border-radius:10px;padding:9px 12px;font:inherit;font-size:15px;color:#1a1a1a;background:var(--gold)}
.btn.sell{background:var(--red);color:#fff}.btn.off{opacity:.4}
#bar{display:flex;gap:6px;padding:8px 8px 6px}
.shop{flex:1;border:2px solid transparent;border-radius:12px;background:var(--panel);color:var(--ink);padding:4px 0 5px;font:inherit;font-size:13px;display:flex;flex-direction:column;align-items:center;gap:0}
.shop span{font-size:26px;line-height:1.1}.shop.sel{border-color:var(--gold);background:#33385a}.shop.poor{opacity:.45}
#ctl{display:flex;gap:6px;padding:0 8px 8px}
#ctl button{flex:1}
#go{flex:2;background:var(--green)}
#ov{position:fixed;inset:0;background:#0009;display:none;align-items:flex-end;justify-content:center;z-index:5}
#panel{width:100%;max-width:560px;background:var(--panel);border-radius:22px 22px 0 0;padding:18px 18px calc(18px + env(safe-area-inset-bottom,0px))}
#panel h2{margin:0 0 10px;font-weight:400;font-size:26px}
.row{display:flex;justify-content:space-between;align-items:center;padding:9px 0;border-bottom:1px solid #ffffff14;font-size:17px}
.seg{display:flex;gap:4px}.seg button{border:0;border-radius:9px;padding:7px 11px;font:inherit;font-size:15px;background:#343a58;color:var(--ink)}
.seg button.on{background:var(--accent)}
.sw{width:50px;height:28px;border-radius:14px;background:#343a58;position:relative;border:0}
.sw:after{content:"";position:absolute;left:3px;top:3px;width:22px;height:22px;border-radius:50%;background:#fff;transition:.15s}
.sw.on{background:var(--accent)}.sw.on:after{left:25px}
#msg{position:absolute;inset:0;display:none;flex-direction:column;align-items:center;justify-content:center;gap:12px;background:#000a;text-align:center;font-size:34px}
#msg p{font-size:18px;color:var(--dim);margin:0}
</style></head><body>
<div id="app">
 <div id="hud">
  <div class="chip">đŸĒ™<b id="gold">0</b></div>
  <div class="chip">â¤ī¸<b id="lives">0</b></div>
  <div class="chip"><small>Wave</small><b id="wave">0</b>/<span id="maxw">20</span></div>
  <button id="gear" aria-label="Settings">âš™ī¸</button>
 </div>
 <div id="stage"><canvas id="c"></canvas>
  <div id="sc" style="position:absolute;left:8px;top:6px;background:#232738cc;border-radius:10px;padding:3px 9px;font-size:13px;pointer-events:none">Score <b id="scv">0</b> &middot; Best <b id="best">0</b></div><div id="info"><div class="t" id="itxt"></div><button class="btn" id="up"></button><button class="btn" id="rep" style="background:#66d98a"></button><button class="btn sell" id="sell"></button></div>
  <div id="msg"><div id="mt"></div><p id="ms"></p><button class="btn" id="again" style="font-size:20px">Play again</button></div>
 </div>
 <div id="bar"></div>
 <div id="ctl"><button class="btn" id="pause" style="background:#343a58;color:#fff">⏸</button><button class="btn" id="spd" style="background:#343a58;color:#fff">1x</button><button class="btn" id="go">Send wave</button></div>
</div>
<div id="mp"><style>#mp{position:fixed;inset:0;z-index:9;background:#0d1018f2;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:14px;padding:16px;text-align:center}#mp h1{margin:0;font-weight:400;font-size:34px}#mp p{margin:0;color:var(--dim);font-size:15px}.cards{display:flex;gap:12px;width:100%;max-width:520px}.card{flex:1;background:var(--panel);border:2px solid #ffffff22;border-radius:16px;padding:10px;color:var(--ink);font:inherit;display:flex;flex-direction:column;align-items:center;gap:6px}.card canvas{width:100%;height:auto;aspect-ratio:3/4;border-radius:10px}.card b{font-weight:400;font-size:19px}.card small{color:var(--dim);font-size:12px;line-height:1.2}.card:active{border-color:var(--gold)}</style><h1>Graveyard Guard</h1><p>Choose your battlefield</p><div class='cards'><button class='card' data-m='0'><canvas width='150' height='200'></canvas><b>Haunted Graveyard</b><small>Winding path through mossy tombstones</small></button><button class='card' data-m='1'><canvas width='150' height='200'></canvas><b>Frozen Graveyard</b><small>Snowy trail. Zombies in winter gear</small></button></div></div>
<div id="ov"><div id="panel">
 <h2>Settings</h2>
 <div class="row">Game speed<div class="seg" data-k="speed"><button data-v="1">1x</button><button data-v="2">2x</button><button data-v="3">3x</button></div></div>
 <div class="row">Difficulty<div class="seg" data-k="diff"><button data-v="easy">Easy</button><button data-v="normal">Normal</button><button data-v="hard">Hard</button></div></div>
 <div class="row">Sound<button class="sw" data-k="sound"></button></div>
 <div class="row">Show tower range<button class="sw" data-k="range"></button></div>
 <div class="row">Health bars<button class="sw" data-k="hp"></button></div>
 <div class="row">Auto-send next wave<button class="sw" data-k="auto"></button></div>
 <div class="row">High score<span><b id="hs2">0</b> <button class="btn" id="rhs" style="padding:4px 9px;font-size:13px">Reset</button></span></div><div style="display:flex;gap:8px;margin-top:14px"><button class="btn" id="chmap" style="flex:1;background:#7c5cff;color:#fff">Maps</button><button class="btn sell" id="restart" style="flex:1">Restart game</button><button class="btn" id="close" style="flex:1">Resume</button></div>
</div></div>
<script>
const COLS=9,ROWS=12,$=id=>document.getElementById(id);
let WP=[[0,1],[1,1],[1,4],[3,4],[3,1],[5,1],[5,6],[1,6],[1,8],[7,8],[7,10],[3,10],[3,11],[-1,11]];
const pathTiles=new Set();
for(let i=0;i<WP.length-1;i++){let[a,b]=WP[i],[c,d]=WP[i+1];const sx=Math.sign(c-a),sy=Math.sign(d-b);let x=a,y=b;pathTiles.add(x+','+y);while(x!=c||y!=d){x+=sx;y+=sy;pathTiles.add(x+','+y)}}
const hh=(x,y)=>(((x*374761393+y*668265263)^(x*y*31+7))>>>0)%100;const trees=new Set(),deco=new Map();for(let y=0;y<ROWS;y++)for(let x=0;x<COLS;x++){const k=x+','+y;if(pathTiles.has(k)||(x==0&&y<3))continue;const h=hh(x,y),kd=h<9?0:h<16?1:h<22?2:h<27?3:h<31?4:-1;if(kd>=0){deco.set(k,kd);trees.add(k)}}
const TW={
 archer:{n:'Archer',e:'🏹',cost:100,range:2.7,dmg:9,rate:.45,proj:9,col:'#e8d9a0',d:'Fast single shots'},
 fire:{n:'Flame',e:'đŸ”Ĩ',cost:150,range:2.2,dmg:5,rate:.3,proj:7,col:'#ff8a3d',burn:1,d:'Sets zombies on fire'},
 frost:{n:'Frost',e:'â„ī¸',cost:175,range:2.4,dmg:5,rate:.7,proj:7,col:'#7fd8ff',slow:1,d:'Slows zombies down'},
 cannon:{n:'Cannon',e:'đŸ’Ŗ',cost:250,range:2.9,dmg:34,rate:1.3,proj:6,col:'#bbb',splash:1.1,d:'Area damage'},
 tesla:{n:'Tesla',e:'⚡',cost:500,range:2.6,dmg:22,rate:.9,col:'#c9a8ff',chain:4,d:'Chain lightning'}
};
TW.shovel={n:'Shovel',e:'â›ī¸',cost:800,d:'Dig up a grave so zombies cannot rise from it'};const S={speed:1,diff:'normal',sound:true,range:true,hp:true,auto:false};
const DIFF={easy:{g:1.3,l:25,h:.8},normal:{g:1,l:20,h:1},hard:{g:.8,l:12,h:1.3}};
let G,sel=null,pick=null,hover=null,paused=false,T=40,ox=0,oy=0,W=0,H=0;
const cv=$('c'),cx=cv.getContext('2d');
function newGame(){if(typeof G!=='undefined'&&G&&G.score>HS){HS=G.score;try{localStorage.setItem('ggHS',HS)}catch(e){}}if(!deco0)deco0=new Map(deco);deco.clear();for(const[k,v]of deco0)deco.set(k,v);trees.clear();for(const k of deco.keys())trees.add(k);const d=DIFF[S.diff];G={gold:Math.round(400*d.g),lives:d.l,wave:0,max:30,score:0,towers:[],en:[],pr:[],fx:[],dying:[],decals:[],queue:[],spawnT:0,running:false,over:false,time:0};sel=null;pick=null;$('msg').style.display='none';info();ui()}
function ui(){$('scv').textContent=G.score;$('best').textContent=$('hs2').textContent=Math.max(HS,G.score);$('gold').textContent=G.gold;$('lives').textContent=G.lives;$('wave').textContent=G.wave;$('maxw').textContent=G.max;
 document.querySelectorAll('.shop').forEach(b=>{b.classList.toggle('poor',G.gold<TW[b.dataset.t].cost);b.classList.toggle('sel',pick==b.dataset.t)});
 $('go').textContent=G.running&&G.queue.length+G.en.length>0?'Wave '+G.wave+' running':'Send wave '+(G.wave+1)}
const bar=$('bar');for(const k in TW){const t=TW[k],b=document.createElement('button');b.className='shop';b.dataset.t=k;b.innerHTML=`<span>${t.e}</span>${t.n}<b style="color:var(--gold)">${t.cost}</b>`;
 b.onclick=()=>{pick=pick==k?null:k;sel=null;info();ui();if(pick)tip(t.n+': '+t.d)};bar.appendChild(b)}
function tip(s){const i=$('info');i.style.display='flex';$('itxt').innerHTML=s+'<br><small>'+(pick=='shovel'?'Tap a gravestone to dig it up (red tiles)':'Tap a green tile to build')+'</small>';$('up').style.display=$('sell').style.display=$('rep').style.display='none';clearTimeout(tip.t);tip.t=setTimeout(()=>{if(!sel)i.style.display='none'},2500)}
function size(){const r=cv.getBoundingClientRect(),dp=devicePixelRatio||1;cv.width=r.width*dp;cv.height=r.height*dp;cx.setTransform(dp,0,0,dp,0,0);W=r.width;H=r.height;T=Math.floor(Math.min(W/COLS,H/ROWS));ox=(W-T*COLS)/2;oy=(H-T*ROWS)/2}
addEventListener('resize',size);
const lvlCost=t=>Math.round(TW[t.k].cost*.7*t.lv);
const sellVal=t=>Math.round(t.inv*.7);
function stats(t){const d=TW[t.k],m=1+.5*(t.lv-1);return{dmg:d.dmg*m,range:d.range*(1+.1*(t.lv-1)),rate:d.rate*(1-.1*(t.lv-1))}}
function info(){const i=$('info');if(!sel){i.style.display='none';return}const d=TW[sel.k],s=stats(sel);i.style.display='flex';
 $('itxt').innerHTML=`${d.e} ${d.n} ¡ Lv ${sel.lv}<br><small>Damage ${Math.round(s.dmg)} ¡ Range ${s.range.toFixed(1)}</small>`;
 const u=$('up'),sl=$('sell');u.style.display=sl.style.display='';
 if(sel.lv>=3){u.textContent='Max';u.classList.add('off')}else{u.textContent='âŦ† '+lvlCost(sel);u.classList.toggle('off',G.gold<lvlCost(sel))}
 sl.textContent='Sell '+sellVal(sel);const rp=$('rep');rp.style.display=sel.mx-sel.hp>0?'':'none';rp.textContent='Repair '+repCost(sel);rp.classList.toggle('off',G.gold<repCost(sel));$('itxt').innerHTML+='<br><small>HP '+Math.ceil(sel.hp)+'/'+sel.mx+'</small>'}
$('up').onclick=()=>{if(!sel||sel.lv>=3||G.gold<lvlCost(sel))return;const c=lvlCost(sel);G.gold-=c;sel.inv+=c;sel.lv++;sel.mx=Math.round(THP[sel.k]*(1+.5*(sel.lv-1)));sel.hp=sel.mx;snd(600,.08);info();ui()};
$('sell').onclick=()=>{if(!sel)return;G.gold+=sellVal(sel);G.towers=G.towers.filter(t=>t!==sel);sel=null;snd(300,.08);info();ui()};
cv.addEventListener('pointerdown',e=>{if(G.over)return;const r=cv.getBoundingClientRect(),x=Math.floor((e.clientX-r.left-ox)/T),y=Math.floor((e.clientY-r.top-oy)/T);hover=[x,y];
 if(x<0||y<0||x>=COLS||y>=ROWS)return;const tw=G.towers.find(t=>t.x==x&&t.y==y);if(pick=='shovel'){const key=x+','+y;if(deco.get(key)===3){if(G.gold<TW.shovel.cost){flash('Shovel costs '+TW.shovel.cost);return}G.gold-=TW.shovel.cost;deco.delete(key);trees.delete(key);burst(x*T+T/2,y*T+T/2,'#6b4a2b',16);snd(180,.2,'sawtooth');const left=[...deco.values()].filter(v=>v===3).length;G.fl=[left?'Grave removed! '+left+' left':'All graves cleared!',2.2];ui()}else flash('Tap a gravestone');return}
 if(tw){sel=tw;pick=null;info();ui();return}
 const key=x+','+y;
 if(pick&&!pathTiles.has(key)&&!trees.has(key)){const d=TW[pick];if(G.gold<d.cost){flash('Not enough gold');return}
  G.gold-=d.cost;const t={k:pick,x,y,lv:1,cd:0,inv:d.cost,ang:0,hp:THP[pick],mx:THP[pick]};G.towers.push(t);sel=t;pick=null;snd(450,.1);burst(x*T+T/2,y*T+T/2,'#fff',8);info();ui()}
 else if(pick){flash("Can't build there")}else{sel=null;info();ui()}});
function flash(s){G.fl=[s,1.2]}
let ac;function snd(f,d=.06,type='square'){if(!S.sound)return;try{ac=ac||new AudioContext();const o=ac.createOscillator(),g=ac.createGain();o.type=type;o.frequency.value=f;g.gain.value=.04;g.gain.exponentialRampToValueAtTime(.001,ac.currentTime+d);o.connect(g);g.connect(ac.destination);o.start();o.stop(ac.currentTime+d)}catch(e){}}
function burst(x,y,c,n=6){for(let i=0;i<n;i++){const a=Math.random()*6.28,s=30+Math.random()*60;G.fx.push({x,y,vx:Math.cos(a)*s,vy:Math.sin(a)*s,l:.4,c})}}
function startWave(){if(G.over||(G.running&&G.queue.length))return;if(G.wave>=G.max)return;G.wave++;const n=G.wave,h=DIFF[S.diff].h,q=[];
 const cnt=5+Math.floor(n*1.6);for(let i=0;i<cnt;i++){let ty='walk';if(n>=2&&i%3==2)ty='crawler';if(n>=3&&i%4==3)ty='fast';if(n>=2&&i%7==5)ty='kid';if(n>=3&&i%6==1)ty='short';if(n>=4&&i%7==2)ty='dog';if(n>=4&&i%9==4)ty='fat';if(n>=6&&i%8==6)ty='tall';if(n>=5&&i%5==4)ty='tank';q.push(ty)}
 if(n%5==0)q.push(n%10==0?'giant':'boss');if(n%10==0){const hz=['walk','walk','fast','kid','dog','short','fat','tall'];for(let i=0;i<10+n;i++)q.push('g:'+hz[Math.random()*8|0]);G.fl=['HUGE WAVE! '+(graveSpot()?'Graves are opening!':'They come in hordes!'),3.5];G.shake=.6;snd(80,.6,'sawtooth')}G.queue=q;G.spawnT=0;G.running=true;G.hm=h;ui()}
const ET={walk:{e:'🧟',hp:40,sp:1.1,s:.8,g:8},fast:{e:'đŸ§Ÿâ€â™€ī¸',hp:26,sp:2,s:.7,g:10},tank:{e:'👹',hp:130,sp:.7,s:.95,g:20},boss:{e:'💀',hp:600,sp:.55,s:1.25,g:100}};
Object.assign(ET,{walk:{hp:40,sp:1.0,s:.9,g:8,skin:'#5fb3b0',cloth:'#5a4a7a'},fast:{hp:26,sp:2.0,s:.85,g:10,skin:'#5aa8c0',cloth:'#a6402f'},tank:{hp:150,sp:.65,s:1.2,g:20,skin:'#4a8f95',cloth:'#3d4658'},crawler:{hp:22,sp:1.5,s:.8,g:7,skin:'#6bbfae',cloth:'#6b5538'},boss:{hp:650,sp:.5,s:1.7,g:100,skin:'#3f7f8a',cloth:'#2c2236'},fat:{hp:220,sp:.55,s:1.05,g:25,skin:'#6fae86',cloth:'#7a5a3a'},short:{hp:60,sp:.9,s:.8,g:9,skin:'#5fb3b0',cloth:'#3a5a7a'},tall:{hp:75,sp:1.25,s:1.05,g:14,skin:'#6aa8bd',cloth:'#4a3a5a'},kid:{hp:16,sp:2.5,s:.6,g:8,skin:'#7cc4b4',cloth:'#c0502f'},giant:{hp:900,sp:.42,s:2.0,g:140,skin:'#4f8f78',cloth:'#4a3030'},dog:{hp:30,sp:2.3,s:.75,g:10,skin:'#6c7a62',cloth:'#4a4a3a'}});function spawn(ty,gr){const d=ET[ty],hp=d.hp*(1+G.wave*.28)*G.hm,off=(Math.random()-.5)*.4,p=posAt(0,off);let ex={};if(gr){let b=1e9,d0=0,tp=[0,0];for(let s=0;s<tot;s+=.1){const q=posAt(s,0),dd=Math.hypot(q[0]-gr[0],q[1]-gr[1]);if(dd<b){b=dd;d0=s;tp=q}}ex={gx:gr[0],tgx:tp[0],tgy:tp[1],d0};p[0]=gr[0];p[1]=gr[1];burst(gr[0]*T+T/2,gr[1]*T+T/2,'#6b4a2b',14)}G.en.push({...ex,ty,hp,max:hp,sp:d.sp*(.9+Math.random()*.2),d:ex.d0||0,x:p[0],y:p[1],ux:1,uy:0,face:1,off,slow:0,burn:0,gold:d.g+Math.floor(G.wave/2),z:Math.random()*6,age:0,hit:0,stag:0,rise:.5,v:Math.random()*100|0})}
const segs=[];let tot=0;for(let i=0;i<WP.length-1;i++){const[a,b]=WP[i],[c,d]=WP[i+1],l=Math.hypot(c-a,d-b);segs.push({a,b,c,d,l,s:tot});tot+=l}
function posAt(d,o=0){const s=segs.find(s=>d<=s.s+s.l)||segs.at(-1),f=Math.min(1,(d-s.s)/s.l),ux=Math.sign(s.c-s.a),uy=Math.sign(s.d-s.b);return[s.a+(s.c-s.a)*f-uy*o,s.b+(s.d-s.b)*f+ux*o,ux,uy]}
function hit(e,dmg,t){e.hp-=dmg;e.hit=.12;e.ld=dmg;if(dmg>=25&&e.ty!='boss'&&e.ty!='tank')e.stag=.4;if(t&&t.burn)e.burn=3;if(t&&t.slow)e.slow=2;burst(e.x*T+T/2,e.y*T+T/2,'#8a1626',2)}
function update(dt){G.time+=dt;
 if(G.fl){G.fl[1]-=dt;if(G.fl[1]<=0)G.fl=null}
 if(G.queue.length){G.spawnT-=dt;if(G.spawnT<=0){{const qi=G.queue.shift();if(qi.startsWith('g:'))spawn(qi.slice(2),graveSpot());else spawn(qi)}G.spawnT=Math.max(.35,.9-G.wave*.02)}}
 for(const e of G.en){if(e.burn>0){e.burn-=dt;e.hp-=4*G.wave*.35*dt+3*dt}if(e.slow>0)e.slow-=dt;
  e.age+=dt;if(e.rise>0)e.rise-=dt;if(e.hit>0)e.hit-=dt;let m=e.slow>0?.5:1;if(['walk','tank','fat','giant','short','tall'].includes(e.ty))m*=.5+.95*Math.abs(Math.sin(e.z*.5));if(e.ty=='fast'||e.ty=='kid')m*=(e.age%3<.9)?1.5:.9;if(e.ty=='dog')m*=.6+.8*Math.abs(Math.sin(e.z*.6));if(e.ty=='crawler')m*=.7+.6*Math.abs(Math.sin(e.z));if(e.burn>0)m*=1.35;if(e.stag>0){e.stag-=dt;m*=.15}if(e.rise>0)m=0;m*=atkLogic(e,dt);if(e.gx!==undefined&&!e.onp){const dx=e.tgx-e.x,dy=e.tgy-e.y,dl=Math.hypot(dx,dy);if(dl<.1){e.onp=1;e.d=e.d0}else{e.x+=dx/dl*e.sp*m*dt;e.y+=dy/dl*e.sp*m*dt;e.ux=dx/dl;e.uy=0}}else{e.d+=e.sp*m*dt;[e.x,e.y,e.ux,e.uy]=posAt(e.d,e.off)}e.z+=dt*(5+e.sp*3)*(e.slow>0?.6:1);if(e.ux)e.face=e.ux>0?1:-1;if(Math.random()<dt*.06)snd(60+Math.random()*40,.4,'sawtooth');if((e.ty=='boss'||e.ty=='giant')&&Math.sin(e.z)<-.97)G.shake=Math.max(G.shake||0,.08);
  if(e.d>=tot){e.dead=1;e.esc=1;G.lives-=(e.ty=='giant'?5:e.ty=='boss'?3:1);snd(120,.2,'sawtooth');G.shake=.25}}
 for(const t of G.towers){const s=stats(t),d=TW[t.k];t.cd-=dt;
  let best=null,bd=-1;for(const e of G.en){if(e.dead)continue;const dx=e.x-t.x,dy=e.y-t.y;if(Math.hypot(dx,dy)<=s.range&&e.d>bd){best=e;bd=e.d}}
  if(best){t.ang=Math.atan2(best.y-t.y,best.x-t.x);if(t.cd<=0){t.cd=s.rate;
   if(d.chain){let cur=best,hs=[best];for(let i=0;i<d.chain&&cur;i++){hit(cur,s.dmg*(1-i*.15));const nx=G.en.filter(e=>!e.dead&&!hs.includes(e)&&Math.hypot(e.x-cur.x,e.y-cur.y)<1.6).sort((a,b)=>b.d-a.d)[0];G.fx.push({bolt:[hs.at(-1)===best&&i==0?[t.x,t.y]:[cur.x,cur.y],[cur.x,cur.y]],l:.18});if(nx)G.fx.push({bolt:[[cur.x,cur.y],[nx.x,nx.y]],l:.18});if(nx)hs.push(nx);cur=nx}snd(900,.08,'sawtooth')}
   else{G.pr.push({x:t.x,y:t.y,tg:best,d:s.dmg,sp:d.proj,t:d,col:d.col});snd(d.splash?150:d.slow?700:500,.05)}}}}
 for(const p of G.pr){if(p.tg.dead){p.dead=1;continue}const dx=p.tg.x-p.x,dy=p.tg.y-p.y,l=Math.hypot(dx,dy),st=p.sp*dt;
  if(l<=st+.1){p.dead=1;if(p.t.splash){burst(p.tg.x*T+T/2,p.tg.y*T+T/2,'#ffb347',10);for(const e of G.en)if(Math.hypot(e.x-p.tg.x,e.y-p.tg.y)<=p.t.splash)hit(e,p.d)}else hit(p.tg,p.d,p.t)}
  else{p.x+=dx/l*st;p.y+=dy/l*st}}
 for(const e of G.en)if(e.hp<=0&&!e.dead){e.dead=1;G.gold+=e.gold;G.score+=e.gold*5+G.wave;burst(e.x*T+T/2,e.y*T+T/2,'#7bd36b',8);G.dying.push(mkRag(e));G.decals.push({x:e.x,y:e.y,l:12,r:.2+Math.random()*.15});snd(220,.06)}
 G.en=G.en.filter(e=>!e.dead);G.pr=G.pr.filter(p=>!p.dead);
 for(const f of G.fx){f.l-=dt;if(f.vx){f.x+=f.vx*dt;f.y+=f.vy*dt}}G.fx=G.fx.filter(f=>f.l>0);
 if(G.shake>0)G.shake-=dt;for(const d of G.dying)stepRag(d,dt);G.dying=G.dying.filter(d=>d.t<3.2);for(const d of G.decals)d.l-=dt;G.decals=G.decals.filter(d=>d.l>0);
 if(G.lives<=0){end(false)}
 else if(G.running&&!G.queue.length&&!G.en.length){G.running=false;G.gold+=20+G.wave*5;G.score+=G.wave*50;for(const t of G.towers)t.hp=Math.min(t.mx,t.hp+t.mx*.25);
  if(G.wave>=G.max)end(true);else if(S.auto)setTimeout(startWave,800)}
 ui();if(sel)info()}
function end(win){if(G.over)return;G.over=true;if(G.score>HS){HS=G.score;G.newHS=1;try{localStorage.setItem('ggHS',HS)}catch(e){}}$('msg').style.display='flex';$('mt').textContent=win?'🏆 Victory!':'💀 Overrun';$('ms').textContent=(win?'The graveyard is safe.':'You reached wave '+G.wave+' of '+G.max+'.')+'  Score '+G.score+(G.newHS?' - NEW HIGH SCORE!':'  Best '+HS)}
function draw(){cx.clearRect(0,0,W,H);cx.fillStyle='#14161f';cx.fillRect(0,0,W,H);cx.save();
 if(G.shake>0)cx.translate((Math.random()-.5)*6,(Math.random()-.5)*6);cx.translate(ox,oy);
 for(let y=0;y<ROWS;y++)for(let x=0;x<COLS;x++){const k=x+','+y,p=pathTiles.has(k);
  cx.drawImage(tileImg(x,y,p),x*T,y*T,T+.5,T+.5);
  if(pick&&pick!='shovel'&&!p&&!trees.has(k)&&!G.towers.some(t=>t.x==x&&t.y==y)){cx.fillStyle='#66d98a22';cx.fillRect(x*T+1,y*T+1,T-2,T-2)}
  if(false){cx.font=T*.7+'px serif';cx.textAlign='center';cx.textBaseline='middle';cx.fillText((x+y)%3?'🌲':'đŸĒĻ',x*T+T/2,y*T+T/2)}}
 cx.font=T*.5+'px serif';cx.textAlign='center';cx.textBaseline='middle';if(MAPN)cx.font='0.1px serif';cx.fillText('đŸ•ŗī¸',T*.5,T*1.5-T);
 drawDecor();if(S.range&&sel){const s=stats(sel);cx.beginPath();cx.arc(sel.x*T+T/2,sel.y*T+T/2,s.range*T,0,6.28);cx.fillStyle='#ffffff18';cx.fill();cx.strokeStyle='#ffffff66';cx.stroke()}
 for(const t of G.towers){const px=t.x*T+T/2,py=t.y*T+T/2;
  drawTower(t,px,py);if(t.hp<t.mx){const w=T*.8;cx.fillStyle='#000a';cx.fillRect(px-w/2,py+T*.42,w,4);cx.fillStyle=t.hp/t.mx>.4?'#66d98a':'#ff5d6c';cx.fillRect(px-w/2,py+T*.42,w*Math.max(0,t.hp/t.mx),4)}if(t.hit>0){t.hit-=.016;cx.fillStyle='rgba(255,80,60,.35)';cx.beginPath();cx.arc(px,py,T*.45,0,6.28);cx.fill()}
  for(let i=0;i<t.lv;i++){cx.fillStyle='#ffc83d';cx.beginPath();cx.arc(px-T*.14*(t.lv-1)+i*T*.28,py+T*.38,T*.05,0,6.28);cx.fill()}}
 drawZ();for(const e of []){const d=ET[e.ty],px=e.x*T+T/2,py=e.y*T+T/2+Math.sin(e.z)*T*.03;cx.font=T*d.s+'px serif';cx.fillText(d.e,px,py);
  if(e.slow>0){cx.fillStyle='#7fd8ff55';cx.beginPath();cx.arc(px,py,T*.3,0,6.28);cx.fill()}
  if(e.burn>0){cx.font=T*.3+'px serif';cx.fillText('đŸ”Ĩ',px+T*.2,py-T*.2)}
  if(S.hp){const w=T*.6*d.s;cx.fillStyle='#000a';cx.fillRect(px-w/2,py-T*.5*d.s-4,w,4);cx.fillStyle=e.hp/e.max>.4?'#66d98a':'#ff5d6c';cx.fillRect(px-w/2,py-T*.5*d.s-4,w*Math.max(0,e.hp/e.max),4)}}
 for(const p of G.pr){cx.fillStyle=p.col;cx.beginPath();cx.arc(p.x*T+T/2,p.y*T+T/2,p.t.splash?T*.13:T*.07,0,6.28);cx.fill()}
 for(const f of G.fx){if(f.bolt){cx.strokeStyle='#d9c2ff';cx.lineWidth=3;cx.beginPath();cx.moveTo(f.bolt[0][0]*T+T/2,f.bolt[0][1]*T+T/2);cx.lineTo(f.bolt[1][0]*T+T/2,f.bolt[1][1]*T+T/2);cx.stroke()}else{cx.globalAlpha=f.l*2.5;cx.fillStyle=f.c;cx.fillRect(f.x-2,f.y-2,4,4);cx.globalAlpha=1}}
 cx.restore();
 snowFx();if(G.fl){cx.font='20px "Lilita One",sans-serif';cx.fillStyle='#ff5d6c';cx.textAlign='center';cx.fillText(G.fl[0],W/2,40)}
 if(paused){cx.fillStyle='#0008';cx.fillRect(0,0,W,H);cx.fillStyle='#fff';cx.font='34px "Lilita One",sans-serif';cx.fillText('Paused',W/2,H/2)}}
let HS=0;try{HS=+localStorage.getItem('ggHS')||0}catch(e){}
const OFS=t=>t.lv==1?[0]:t.lv==2?[-6,6]:[-10,0,10];
function graveSpot(){const gs=[...deco].filter(([k,v])=>v==3).map(([k])=>k.split(',').map(Number));if(!gs.length)return null;return gs[Math.random()*gs.length|0]}
function dogZ(e,dy){const d=ET.dog,u=T*d.s*1.15,px=e.x*T+T/2,py=e.y*T+T/2+T*.3,f=e.face||1,ph=e.z,t=e.t||0,k=dy?0:1,fur=MAPN?'#8d9aa0':'#6c7a62',dk=MAPN?'#59656b':'#3f4a3a',O='#0c1a14';cx.save();cx.translate(px,py);cx.globalAlpha=dy?Math.min(1,Math.max(0,3-t)):1;cx.fillStyle='#0007';cx.beginPath();cx.ellipse(0,0,u*.38,u*.08,0,0,6.28);cx.fill();if(!dy&&e.rise>0){const rs=Math.min(1,1-e.rise/.5);cx.beginPath();cx.rect(-u,-u*1.5,u*2,u*1.5);cx.clip();cx.translate(0,(1-rs)*u*.7)}if(dy){const q=Math.min(1,t*3);cx.translate(0,-u*.1*q);cx.rotate(-f*q*2.9)}else if(e.hit>0)cx.translate(-f*u*.05,0);if(e.bt>0)cx.translate(f*Math.abs(Math.sin(G.time*11))*u*.14,0);cx.scale(f,1);cx.translate(0,-Math.abs(Math.sin(ph*1.2))*u*.05*k);const lg=(x,i)=>{const a=ph*1.2+i*1.9,fx=x+Math.sin(a)*u*.14*k,fy=-Math.max(0,Math.cos(a))*u*.08*k;cx.lineCap='round';cx.strokeStyle=O;cx.lineWidth=u*.1;cx.beginPath();cx.moveTo(x,-u*.25);cx.lineTo(fx,fy);cx.stroke();cx.strokeStyle=i%2?dk:fur;cx.lineWidth=u*.07;cx.beginPath();cx.moveTo(x,-u*.25);cx.lineTo(fx,fy);cx.stroke();cx.fillStyle=O;cx.beginPath();cx.ellipse(fx+u*.03,fy,u*.06,u*.035,0,0,6.28);cx.fill()};lg(-u*.25,1);lg(u*.22,3);cx.strokeStyle=O;cx.lineWidth=u*.07;cx.beginPath();cx.moveTo(-u*.32,-u*.38);cx.quadraticCurveTo(-u*.5,-u*.55,-u*.55+Math.sin(ph*2)*u*.06*k,-u*.45);cx.stroke();cx.fillStyle=fur;cx.lineWidth=1.8;cx.beginPath();cx.ellipse(0,-u*.33,u*.36,u*.19,0,0,6.28);cx.fill();cx.stroke();cx.fillStyle='rgba(255,255,255,.14)';cx.beginPath();cx.ellipse(-u*.05,-u*.4,u*.25,u*.07,0,0,6.28);cx.fill();cx.strokeStyle='#e8f0ea';cx.lineWidth=1.3;for(let i=0;i<4;i++){cx.beginPath();cx.moveTo(-u*.12+i*u*.08,-u*.3);cx.lineTo(-u*.1+i*u*.08,-u*.2);cx.stroke()}cx.fillStyle='#3d8c90';cx.beginPath();cx.ellipse(u*.12,-u*.4,u*.07,u*.05,0,0,6.28);cx.fill();if(MAPN){cx.fillStyle='#b8323a';cx.strokeStyle=O;cx.lineWidth=1.5;cx.beginPath();cx.ellipse(-u*.02,-u*.33,u*.21,u*.17,0,0,6.28);cx.fill();cx.stroke();cx.strokeStyle='rgba(255,255,255,.6)';cx.lineWidth=1.4;for(let i=-2;i<=2;i++){cx.beginPath();cx.moveTo(-u*.02+i*u*.07,-u*.46);cx.lineTo(-u*.02+i*u*.07,-u*.21);cx.stroke()}cx.fillStyle='#fff';cx.beginPath();cx.ellipse(u*.26,-u*.36,u*.05,u*.1,0,0,6.28);cx.fill()}lg(-u*.18,0);lg(u*.29,2);cx.save();cx.translate(u*.4,-u*.45);cx.rotate(dy?.3:Math.sin(ph*1.2)*.12);cx.fillStyle=fur;cx.strokeStyle=O;cx.lineWidth=1.8;cx.beginPath();cx.ellipse(0,0,u*.14,u*.12,0,0,6.28);cx.fill();cx.stroke();const jw=dy?.3:Math.abs(Math.sin(ph*.9))*.35;cx.fillStyle=dk;cx.beginPath();cx.ellipse(u*.17,u*.07+jw*u*.05,u*.11,u*.04,jw,0,6.28);cx.fill();cx.stroke();cx.fillStyle=fur;cx.beginPath();cx.ellipse(u*.17,-u*.01,u*.11,u*.05,0,0,6.28);cx.fill();cx.stroke();cx.fillStyle='#fff';for(let i=0;i<3;i++){cx.beginPath();cx.moveTo(u*.12+i*u*.04,u*.03);cx.lineTo(u*.14+i*u*.04,u*.075);cx.lineTo(u*.16+i*u*.04,u*.03);cx.fill()}cx.fillStyle='#111';cx.beginPath();cx.arc(u*.27,-u*.02,u*.025,0,6.28);cx.fill();cx.fillStyle=dk;cx.beginPath();cx.moveTo(-u*.04,-u*.1);cx.lineTo(-u*.12,-u*.26);cx.lineTo(u*.04,-u*.12);cx.fill();cx.stroke();cx.fillStyle='#fff';cx.beginPath();cx.arc(u*.07,-u*.04,u*.045,0,6.28);cx.fill();cx.stroke();cx.fillStyle=dy?'#fff':'#e0302f';cx.beginPath();cx.arc(u*.085,-u*.04,u*.022,0,6.28);cx.fill();cx.restore();if(e.slow>0&&!dy){cx.fillStyle='#8fe0ff55';cx.beginPath();cx.ellipse(0,-u*.3,u*.45,u*.3,0,0,6.28);cx.fill()}if(e.hit>0&&!dy){cx.fillStyle='#ffffff77';cx.beginPath();cx.ellipse(0,-u*.3,u*.42,u*.28,0,0,6.28);cx.fill()}if(e.burn>0&&!dy){for(let i=0;i<4;i++){const q=G.time*14+i*2+e.z;cx.fillStyle=i%2?'#ffd34d':'#ff7a2a';cx.beginPath();cx.ellipse(Math.sin(q)*u*.3,-u*(.35+.08*i)-Math.abs(Math.cos(q))*u*.08,u*.07,u*.12,0,0,6.28);cx.fill()}}cx.restore();if(S.hp&&!dy){const w=u*.6,x=px-w/2,y=py-u*.85;cx.fillStyle='#000a';cx.fillRect(x,y,w,4);cx.fillStyle=e.hp/e.max>.4?'#66d98a':'#ff5d6c';cx.fillRect(x,y,w*Math.max(0,e.hp/e.max),4)}}
const THP={archer:120,fire:140,frost:120,cannon:180,tesla:160},ATKD={walk:3,short:3,tall:8,dog:6,fat:12,tank:14,boss:25,giant:40};const repCost=t=>Math.ceil((t.mx-t.hp)/t.mx*TW[t.k].cost*.6);
function killTower(t){G.towers=G.towers.filter(x=>x!==t);if(sel===t){sel=null;info()}G.decals.push({x:t.x,y:t.y,l:15,r:.35,c:'#2f313a'});burst(t.x*T+T/2,t.y*T+T/2,'#9aa1b2',18);snd(90,.4,'sawtooth');G.shake=.3;G.fl=['Tower destroyed!',1.8]}
function atkLogic(e,dt){const a=ATKD[e.ty];if(!a||(e.gx!==undefined&&!e.onp))return 1;e.bt=Math.max(0,(e.bt||0)-dt);let tg=null,bd=1.2;for(const t of G.towers){const d=Math.hypot(t.x-e.x,t.y-e.y);if(d<bd){bd=d;tg=t}}if(!tg)return 1;if(!G.warn){G.warn=1;G.fl=['Zombies attack towers beside the path! Tap a tower to repair',3.5]}e.face=tg.x>e.x?1:-1;e.bt=.25;e.ac=(e.ac||0)-dt;if(e.ac<=0){e.ac=.9;tg.hp-=a;tg.hit=.2;burst(tg.x*T+T/2,tg.y*T+T/2,'#ffb347',4);snd(140,.08,'sawtooth');if(tg.hp<=0)killTower(tg)}return 0}
let MAPN=0,ET0=null;const MAPS=[{wp:[[0,1],[1,1],[1,4],[3,4],[3,1],[5,1],[5,6],[1,6],[1,8],[7,8],[7,10],[3,10],[3,11],[-1,11]]},{wp:[[8,1],[2,1],[2,3],[6,3],[6,6],[1,6],[1,9],[4,9],[4,11],[9,11]]}];
function mkPath(wp){const s=new Set();for(let i=0;i<wp.length-1;i++){let[a,b]=wp[i],[c,d]=wp[i+1];const sx=Math.sign(c-a),sy=Math.sign(d-b);let x=a,y=b;s.add(x+','+y);while(x!=c||y!=d){x+=sx;y+=sy;s.add(x+','+y)}}return s}
function setMap(m){MAPN=m;WP=MAPS[m].wp;pathTiles.clear();for(const k of mkPath(WP))pathTiles.add(k);trees.clear();deco.clear();for(let y=0;y<ROWS;y++)for(let x=0;x<COLS;x++){const k=x+','+y;if(pathTiles.has(k)||(m==0&&x==0&&y<3)||(m==1&&x==8&&y<3))continue;const h=hh(x+m*5,y+m*3),kd=h<9?0:h<16?1:h<22?2:h<27?3:h<31?4:-1;if(kd>=0){deco.set(k,kd);trees.add(k)}}segs.length=0;tot=0;for(let i=0;i<WP.length-1;i++){const[a,b]=WP[i],[c,d]=WP[i+1],l=Math.hypot(c-a,d-b);segs.push({a,b,c,d,l,s:tot});tot+=l}for(const k in TC)delete TC[k];for(const k in SP)delete SP[k];deco0=null;if(!ET0){ET0={};for(const k in ET)ET0[k]=ET[k].skin}let i=0;for(const k in ET)ET[k].skin=m?['#7fc4d0','#6fb4d8','#8fd0d8','#78c0c8'][i++%4]:ET0[k]}
function drawPrev(cv,m){const g=cv.getContext('2d'),cw=cv.width/9,ch=cv.height/12,ps=mkPath(MAPS[m].wp);g.fillStyle=m?'#dfeaf5':'#3b6e46';g.fillRect(0,0,cv.width,cv.height);for(let i=0;i<30;i++){const x=(i*37+m*5)%9,y=(i*53+m*3)%12;if(ps.has(x+','+y))continue;g.fillStyle=m?(i%3?'#f7fbff':'#2f6a50'):(i%3?'#2c5a3a':'#8c92a6');g.beginPath();g.arc((x+.5)*cw,(y+.5)*ch,cw*.3,0,6.28);g.fill()}g.strokeStyle=m?'#9b8d80':'#8a6e4c';g.lineWidth=cw*.9;g.lineCap='square';g.lineJoin='miter';g.beginPath();MAPS[m].wp.forEach(([x,y],i)=>{const px=(x+.5)*cw,py=(y+.5)*ch;i?g.lineTo(px,py):g.moveTo(px,py)});g.stroke();g.fillStyle='#66d98a';g.beginPath();g.arc((MAPS[m].wp[0][0]+.5)*cw,(MAPS[m].wp[0][1]+.5)*ch,cw*.4,0,6.28);g.fill()}
function snowFx(){if(!MAPN)return;cx.fillStyle='rgba(120,160,230,.08)';cx.fillRect(0,0,W,H);cx.fillStyle='#fff';for(let i=0;i<70;i++){const x=((i*97.3+G.time*20*(1+(i%3)*.4)+Math.sin(G.time*.8+i)*18)%W+W)%W,y=(i*53.7+G.time*(28+(i%5)*14))%H;cx.globalAlpha=.4+(i%4)*.15;cx.beginPath();cx.arc(x,y,1+(i%3)*.7,0,6.28);cx.fill()}cx.globalAlpha=1}
function snowTile(x,y,p,m,par,v,key){const c=document.createElement('canvas');c.width=c.height=64;const g=c.getContext('2d'),R=rng(key.split('').reduce((a,ch)=>(a*31+ch.charCodeAt(0))>>>0,7));const blob=(r,col)=>{const bx=R()*64,by=R()*64;for(const dx of[-64,0,64])for(const dy of[-64,0,64]){const gr=g.createRadialGradient(bx+dx,by+dy,0,bx+dx,by+dy,r);gr.addColorStop(0,col);gr.addColorStop(1,'rgba(0,0,0,0)');g.fillStyle=gr;g.fillRect(0,0,64,64)}};const dot=(x,y,rx,ry,col)=>{g.fillStyle=col;g.beginPath();g.ellipse(x,y,rx,ry,0,0,6.28);g.fill()};if(!p){g.fillStyle=par?'#e6eff8':'#dfeaf5';g.fillRect(0,0,64,64);for(let i=0;i<8;i++)blob(10+R()*14,i%2?'rgba(255,255,255,.55)':'rgba(120,150,200,.25)');g.strokeStyle='rgba(150,175,210,.35)';g.lineWidth=1.2;for(let i=0;i<5;i++){const yy=R()*60+2,xx=R()*40;g.beginPath();g.moveTo(xx,yy);g.quadraticCurveTo(xx+10,yy-3,xx+22,yy);g.stroke()}for(let i=0;i<70;i++){g.fillStyle=R()<.5?'rgba(255,255,255,.95)':'rgba(170,200,240,.8)';g.fillRect(R()*64,R()*64,1.2,1.2)}g.strokeStyle='#8a8f6a';g.lineWidth=1.2;g.lineCap='round';for(let i=0;i<(v+1)*2;i++){const bx=R()*56+4,by=R()*56+8;for(let k=-1;k<=1;k++){g.beginPath();g.moveTo(bx+k*2,by);g.lineTo(bx+k*3,by-5-R()*3);g.stroke()}}if(v==2){g.fillStyle='rgba(170,215,245,.55)';g.beginPath();g.ellipse(32+R()*10,32,12,6,.3,0,6.28);g.fill();g.strokeStyle='rgba(255,255,255,.8)';g.lineWidth=1;g.stroke()}dot(R()*50+7,R()*50+7,8,3,'rgba(255,255,255,.9)')}else{g.fillStyle=par?'#8f8378':'#897d72';g.fillRect(0,0,64,64);for(let i=0;i<9;i++)blob(9+R()*13,i%2?'rgba(200,190,175,.3)':'rgba(50,40,35,.3)');for(let i=0;i<260;i++){g.fillStyle=['#a89a8c','#6e6258','#b9ab9c','#5b5047'][R()*4|0];g.globalAlpha=.5+R()*.5;g.fillRect(R()*64,R()*64,1+R()*1.5,1+R()*1.5)}g.globalAlpha=1;for(let i=0;i<4;i++)dot(R()*64,R()*64,3+R()*6,2+R()*3,'rgba(235,245,255,.55)');for(let i=0;i<2;i++){g.fillStyle='rgba(170,210,240,.45)';g.beginPath();g.ellipse(R()*50+7,R()*50+7,7,3,R(),0,6.28);g.fill();g.strokeStyle='rgba(255,255,255,.7)';g.lineWidth=.8;g.stroke()}g.strokeStyle='rgba(40,30,25,.25)';g.lineWidth=2;for(const yy of[20,44]){g.beginPath();g.moveTo(0,yy);g.lineTo(64,yy+(v-1)*2);g.stroke()}for(let i=0;i<7;i++){const px=6+R()*52,py=6+R()*52,rx=1.5+R()*3;dot(px+1,py+1.4,rx,rx*.7,'rgba(20,15,10,.4)');dot(px,py,rx,rx*.7,['#8c8a88','#6f6d6b','#a09d98'][R()*3|0]);dot(px-rx*.3,py-rx*.25,rx*.4,rx*.3,'rgba(255,255,255,.4)')}for(let i=0;i<4;i++){if(m&(1<<i))continue;g.save();g.translate(32,32);g.rotate(i*Math.PI/2);g.translate(-32,-32);const gr=g.createLinearGradient(0,0,0,14);gr.addColorStop(0,'rgba(60,80,120,.55)');gr.addColorStop(1,'rgba(60,80,120,0)');g.fillStyle=gr;g.fillRect(0,0,64,14);g.fillStyle='#eef5fc';g.beginPath();g.moveTo(0,0);for(let k=0;k<=8;k++)g.lineTo(k*8,5+Math.sin(k*1.9+v)*2.5);g.lineTo(64,0);g.closePath();g.fill();g.strokeStyle='rgba(140,170,210,.8)';g.lineWidth=1.2;g.beginPath();for(let k=0;k<=8;k++){const yy=5+Math.sin(k*1.9+v)*2.5;k?g.lineTo(k*8,yy):g.moveTo(0,yy)}g.stroke();for(let k=0;k<10;k++)dot(R()*64,1+R()*5,1,1,'#fff');g.restore()}}return TC[key]=c}
function snowify(g,kd,R){const E=(x,y,a,b,col)=>{g.fillStyle=col;g.beginPath();g.ellipse(x,y,a,b,0,0,6.28);g.fill()};E(48,99,30,7,'#eef5fb');E(48,100,26,4,'rgba(130,160,210,.5)');if(kd==0){for(let i=0;i<4;i++){const by=90-i*19,w=36-i*7,tp=by-32+i*2,yb=tp+(by-tp)*.62;g.fillStyle='#f4f9ff';g.beginPath();g.moveTo(48,tp-1);g.lineTo(48+w*.7,yb);for(let k=3;k>=-3;k--)g.lineTo(48+k*w*.23,yb+(k%2?4:0));g.lineTo(48-w*.7,yb);g.closePath();g.fill();g.fillStyle='rgba(150,180,225,.45)';g.beginPath();g.moveTo(48,tp-1);g.lineTo(48-w*.7,yb);g.lineTo(48,yb);g.closePath();g.fill()}}else if(kd==1){for(let i=0;i<22;i++)E(26+R()*44,20+R()*34,4+R()*6,3+R()*4,'rgba(240,248,255,.88)');for(let i=0;i<10;i++)E(28+R()*40,48+R()*14,3+R()*4,2.5,'rgba(215,232,250,.7)')}else if(kd==2){for(const[x,y,s]of[[40,86,24],[66,92,13],[28,96,9]])E(x,y-s*.38,s*.78,s*.32,'#f6faff')}else if(kd==3){E(48,40,15.5,5.5,'#f6faff');E(48,41,13,3,'rgba(150,180,225,.5)');E(33,94,6,3,'#fff');E(63,94,6,3,'#fff')}else{for(const[x,y]of[[27,34],[18,25],[30,19],[72,33],[80,26],[76,18],[48,50],[48,28],[44,14],[50,67]])E(x,y,4+R()*2,2,'#f6faff')}}
function winterHead(e,r,cy,top){const v=e.v||0,h=(e.ty=='boss'||e.ty=='giant')?1:v%3,col=['#d94a3a','#2e7dd7','#3fae6a','#e8c43c'][v%4],E=(x,y,a,b,c)=>{cx.fillStyle=c;cx.beginPath();cx.ellipse(x,y,a,b,0,0,6.28);cx.fill()};cx.strokeStyle='#0c2b30';cx.lineWidth=1.5;if(h==0){cx.fillStyle=col;cx.beginPath();cx.arc(0,cy-r*.1,r*1.06,Math.PI,0);cx.closePath();cx.fill();cx.stroke();cx.fillStyle='rgba(255,255,255,.25)';for(let i=-3;i<=3;i++)cx.fillRect(i*r*.28-.5,top-r*.1,1.4,r*.55);cx.fillStyle='#f3f3f3';cx.fillRect(-r*1.08,cy-r*.62,r*2.16,r*.3);cx.strokeRect(-r*1.08,cy-r*.62,r*2.16,r*.3);cx.fillStyle=col;for(let i=-4;i<=4;i++)cx.fillRect(i*r*.25,cy-r*.62,1.4,r*.3);E(0,top-r*.2,r*.28,r*.28,'#fff');cx.stroke()}else if(h==1){cx.fillStyle='#8c8f9a';cx.beginPath();cx.arc(0,cy-r*.1,r*1.12,Math.PI*1.02,Math.PI*1.98);cx.closePath();cx.fill();cx.stroke();for(let i=0;i<26;i++){cx.fillStyle=i%2?'#b3b6c0':'#6f727e';cx.fillRect(Math.cos(i*2.4)*r*.9,cy-r*.15-Math.abs(Math.sin(i*1.7))*r*.9,2,2)}E(-r*1.0,cy+r*.05,r*.28,r*.55,'#8c8f9a');cx.stroke();E(r*.95,cy-r*.45,r*.5,r*.2,'#8c8f9a');cx.stroke();cx.fillStyle='#d33';cx.beginPath();cx.arc(r*.2,top+r*.15,r*.13,0,6.28);cx.fill();cx.stroke()}else{cx.strokeStyle='#2a2a34';cx.lineWidth=r*.16;cx.lineCap='round';cx.beginPath();cx.arc(0,cy,r*1.02,Math.PI*1.08,Math.PI*1.92);cx.stroke();cx.strokeStyle='#0c2b30';cx.lineWidth=1.5;E(-r*1.0,cy+r*.05,r*.3,r*.34,col);cx.stroke();E(0,top+r*.05,r*.3,r*.14,'#3a2a22')}E(r*.55,cy+r*.12,r*.1,r*.08,'#ee6a6a');cx.fillStyle='rgba(255,255,255,.4)';for(let i=0;i<3;i++){const q=(G.time*1.3+i/3+v*.1)%1;cx.beginPath();cx.arc(r*.95+q*r*.7,cy+r*.5-q*r*.5,r*.06+q*r*.09,0,6.28);cx.fill()}}
function winterBody(e,u,tw,cl){const w=u*tw,v=e.v||0,sc=['#d94a3a','#2e7dd7','#e8c43c','#3fae6a'][(v+1)%4];cx.save();cx.fillStyle=cl;cx.beginPath();cx.ellipse(0,-u*.2,w,u*.24,0,0,6.28);cx.fill();cx.clip();for(let i=0;i<5;i++){const yy=-u*(.05+.085*i);cx.strokeStyle='rgba(0,0,0,.28)';cx.lineWidth=1.3;cx.beginPath();cx.moveTo(-w,yy);cx.quadraticCurveTo(0,yy+u*.03,w,yy);cx.stroke();cx.strokeStyle='rgba(255,255,255,.2)';cx.beginPath();cx.moveTo(-w,yy-1.5);cx.quadraticCurveTo(0,yy+u*.03-1.5,w,yy-1.5);cx.stroke()}cx.fillStyle='rgba(255,255,255,.14)';cx.beginPath();cx.ellipse(-w*.4,-u*.27,w*.45,u*.14,0,0,6.28);cx.fill();cx.fillStyle='#2a2220';cx.fillRect(-w,-u*.12,w*2,u*.04);cx.restore();cx.strokeStyle='#0c2b30';cx.lineWidth=1.8;cx.beginPath();cx.ellipse(0,-u*.2,w,u*.24,0,0,6.28);cx.stroke();cx.lineCap='round';cx.strokeStyle='#0c2b30';cx.lineWidth=u*.11+2.4;cx.beginPath();cx.moveTo(-w*.8,-u*.4);cx.lineTo(w*.8,-u*.4);cx.stroke();cx.strokeStyle=sc;cx.lineWidth=u*.11;cx.stroke();const sw=Math.sin(G.time*5+v)*u*.02;cx.fillStyle=sc;cx.strokeStyle='#0c2b30';cx.lineWidth=1.3;cx.beginPath();cx.moveTo(w*.35,-u*.38);cx.lineTo(w*.6+sw,-u*.12);cx.lineTo(w*.25+sw,-u*.1);cx.lineTo(w*.1,-u*.38);cx.closePath();cx.fill();cx.stroke();cx.strokeStyle='rgba(255,255,255,.5)';cx.lineWidth=1.2;for(let i=0;i<3;i++){cx.beginPath();cx.moveTo(w*.38+sw*.5,-u*(.3-i*.07));cx.lineTo(w*.2+sw*.3,-u*(.3-i*.07));cx.stroke()}}
let deco0;const TS={};
function tsp(k,lv,hd){const key=k+lv+hd;if(TS[key])return TS[key];const c=document.createElement('canvas');c.width=c.height=64;const g=c.getContext('2d'),R=rng(k.length*31+lv*7+hd);const ac=['#c0392b','#2e7dd7','#ffc83d'][lv-1],rim=['#a4733c','#c9cfdc','#ffc83d'][lv-1];const E=(x,y,a,b,col)=>{g.fillStyle=col;g.beginPath();g.ellipse(x,y,a,b,0,0,6.28);g.fill()};const LG=(x0,y0,x1,y1,s)=>{const q=g.createLinearGradient(x0,y0,x1,y1);s.forEach((v,i)=>q.addColorStop(i/(s.length-1),v));return q};const RR=(x,y,w,h,r,f,st)=>{g.beginPath();if(g.roundRect)g.roundRect(x,y,w,h,r);else g.rect(x,y,w,h);g.fillStyle=f;g.fill();g.strokeStyle=st||'#10161c';g.lineWidth=1.4;g.stroke()};const rv=(x,y)=>{E(x,y,1.5,1.5,'#cfd4e0');E(x-.4,y-.4,.6,.6,'#fff')};g.lineJoin='round';
if(!hd){E(33,36,29,26,'rgba(0,0,0,.35)');const pg=g.createRadialGradient(26,24,4,32,32,30);pg.addColorStop(0,'#99a0b4');pg.addColorStop(1,'#4d5366');g.fillStyle=pg;g.beginPath();g.arc(32,32,28,0,6.28);g.fill();g.strokeStyle='#23273a';g.lineWidth=2;g.stroke();g.strokeStyle='rgba(20,22,32,.55)';g.lineWidth=1;for(let i=0;i<14;i++){const a=i*.4488;g.beginPath();g.moveTo(32+Math.cos(a)*20,32+Math.sin(a)*20);g.lineTo(32+Math.cos(a)*28,32+Math.sin(a)*28);g.stroke()}g.beginPath();g.arc(32,32,20,0,6.28);g.stroke();for(let i=0;i<140;i++){const a=R()*6.28,d=R()*27;g.fillStyle=R()<.5?'rgba(255,255,255,.18)':'rgba(0,0,0,.22)';g.fillRect(32+Math.cos(a)*d,32+Math.sin(a)*d,1.3,1.3)}for(let i=0;i<4;i++){const a=R()*6.28;g.fillStyle='rgba(88,140,72,.7)';g.beginPath();g.ellipse(32+Math.cos(a)*25,32+Math.sin(a)*25,4,2,a,0,6.28);g.fill()}g.strokeStyle=rim;g.lineWidth=3;g.beginPath();g.arc(32,32,27,0,6.28);g.stroke();g.strokeStyle='rgba(255,255,255,.35)';g.lineWidth=1;g.beginPath();g.arc(32,32,28.5,3.6,5.2);g.stroke();if(lv>1)for(let i=0;i<8;i++)rv(32+Math.cos(i*.785)*27,32+Math.sin(i*.785)*27);
if(k=='archer'){RR(17,17,30,30,3,LG(17,17,47,47,['#b07a44','#8a5a30','#6a4424']));g.strokeStyle='rgba(40,24,10,.6)';g.lineWidth=1;for(let i=1;i<5;i++){g.beginPath();g.moveTo(17,17+i*6);g.lineTo(47,17+i*6);g.stroke()}for(let i=0;i<40;i++){g.fillStyle='rgba(40,24,10,.35)';g.fillRect(18+R()*28,18+R()*28,3+R()*4,.8)}for(const[x,y]of[[17,17],[47,17],[17,47],[47,47]]){E(x,y,3.4,3.4,'#3a2412');E(x-.6,y-.6,1.6,1.6,'#7a5230')}g.fillStyle='#5a5f70';g.fillRect(17,31,30,2);rv(20,32);rv(44,32);g.fillStyle='#3a2412';g.fillRect(20,9,2,14);g.fillStyle=ac;g.beginPath();g.moveTo(22,9);g.lineTo(31,12);g.lineTo(22,16);g.closePath();g.fill();g.strokeStyle='#10161c';g.lineWidth=1;g.stroke();E(42,51,5,2.5,'#b9a77a');E(48,48,4,2.2,'#a8966a')}
else if(k=='fire'){const tg=g.createRadialGradient(28,27,2,32,32,15);tg.addColorStop(0,'#f0a060');tg.addColorStop(.6,'#c4502f');tg.addColorStop(1,'#6a2216');g.fillStyle=tg;g.beginPath();g.arc(32,32,15,0,6.28);g.fill();g.strokeStyle='#2a0f0a';g.lineWidth=2;g.stroke();g.strokeStyle='rgba(30,10,6,.7)';g.lineWidth=1.6;for(const r of[6,11]){g.beginPath();g.arc(32,32,r,0,6.28);g.stroke()}for(let i=0;i<8;i++)rv(32+Math.cos(i*.785)*13,32+Math.sin(i*.785)*13);E(32,32,4,4,'#2a1a14');E(32,32,2.5,2.5,'#d9dde8');g.strokeStyle='#e33';g.lineWidth=1;g.beginPath();g.moveTo(32,32);g.lineTo(34.5,30);g.stroke();RR(10,38,9,12,2,LG(10,0,19,0,['#c43c2c','#8a2418']));g.fillStyle='#e8e0c8';g.fillRect(12,40,5,3)}
else if(k=='frost'){g.fillStyle=LG(14,14,50,50,['#c9e8f5','#8fb8cc','#5d86a0']);g.beginPath();for(let i=0;i<8;i++){const a=i*.785+.39,x=32+Math.cos(a)*17,y=32+Math.sin(a)*17;i?g.lineTo(x,y):g.moveTo(x,y)}g.closePath();g.fill();g.strokeStyle='#2a5a78';g.lineWidth=2;g.stroke();for(let i=0;i<30;i++)E(20+R()*24,20+R()*24,.8,.8,'rgba(255,255,255,.7)');const sh=(x,y,h,w,rot)=>{g.save();g.translate(x,y);g.rotate(rot);g.fillStyle=LG(-w,0,w,0,['#e8fbff','#8fdcf8','#4aa8d8']);g.beginPath();g.moveTo(-w,0);g.lineTo(-w*.5,-h*.8);g.lineTo(0,-h);g.lineTo(w*.5,-h*.8);g.lineTo(w,0);g.closePath();g.fill();g.strokeStyle='#1f6a8f';g.lineWidth=1.3;g.stroke();g.fillStyle='rgba(255,255,255,.55)';g.beginPath();g.moveTo(-w*.6,-2);g.lineTo(-w*.35,-h*.7);g.lineTo(-w*.1,-h*.9);g.lineTo(-w*.1,-2);g.closePath();g.fill();g.restore()};const n=2+lv*2;for(let i=0;i<n;i++){const a=i/n*6.28;sh(32+Math.cos(a)*10,34+Math.sin(a)*9,10+R()*4,3.5,Math.cos(a)*.5)}sh(32,38,22+lv*3,6,0)}
else if(k=='cannon'){E(32,32,15,15,'#3a3f4c');g.strokeStyle='#10161c';g.lineWidth=2;g.beginPath();g.arc(32,32,15,0,6.28);g.stroke();g.strokeStyle='#6b7284';g.lineWidth=3;g.beginPath();g.arc(32,32,11,0,6.28);g.stroke();for(let i=0;i<8;i++)rv(32+Math.cos(i*.785)*13.5,32+Math.sin(i*.785)*13.5);for(const y of[14,50]){RR(24,y-4,16,8,3,LG(0,y-4,0,y+4,['#a07040','#5a3a1c']));g.strokeStyle='#2a1a0c';g.lineWidth=1;for(let i=1;i<4;i++){g.beginPath();g.moveTo(24+i*4,y-4);g.lineTo(24+i*4,y+4);g.stroke()}}for(const[x,y]of[[47,46],[51,43],[50,49]]){E(x,y,3.4,3.4,'#20232c');E(x-1,y-1,1.2,1.2,'#7a8094')}}
else{g.fillStyle=LG(0,16,0,48,['#4a5068','#2e3244']);g.beginPath();for(let i=0;i<6;i++){const a=i*1.047,x=32+Math.cos(a)*16,y=32+Math.sin(a)*16;i?g.lineTo(x,y):g.moveTo(x,y)}g.closePath();g.fill();g.strokeStyle='#10161c';g.lineWidth=2;g.stroke();for(let i=0;i<6;i++)rv(32+Math.cos(i*1.047)*13,32+Math.sin(i*1.047)*13);for(let r=11;r>3;r-=3){g.strokeStyle=LG(20,20,44,44,['#f0a860','#b8682c','#6a3a18']);g.lineWidth=2.6;g.beginPath();g.arc(32,32,r,0,6.28);g.stroke();g.strokeStyle='rgba(16,22,28,.35)';g.lineWidth=.8;g.beginPath();g.arc(32,32,r+1.3,0,6.28);g.stroke()}const sc=lv==1?[]:lv==2?[.9,3.4]:[.9,3.4,2.2,5.3];for(const a of sc){const x=32+Math.cos(a)*21,y=32+Math.sin(a)*21;E(x,y,5,5,'#3a3f50');g.strokeStyle='#c97b3c';g.lineWidth=2;g.beginPath();g.arc(x,y,3,0,6.28);g.stroke()}}}
else{if(k=='archer'){RR(16,29,30,6,2,LG(0,29,0,35,['#d09a5c','#8a5a30']));g.strokeStyle='rgba(40,24,10,.5)';g.lineWidth=.8;for(let i=0;i<5;i++){g.beginPath();g.moveTo(18+i*6,30);g.lineTo(20+i*6,34);g.stroke()}RR(24,28,6,8,1,ac);g.lineCap='round';g.strokeStyle='#10161c';g.lineWidth=5;g.beginPath();g.moveTo(38,32);g.quadraticCurveTo(44,18,52,12);g.moveTo(38,32);g.quadraticCurveTo(44,46,52,52);g.stroke();g.strokeStyle=LG(38,12,52,12,['#9aa1b2','#e4e8f2']);g.lineWidth=3;g.stroke();g.strokeStyle='#eee';g.lineWidth=1;g.beginPath();g.moveTo(52,12);g.lineTo(30,32);g.lineTo(52,52);g.stroke()}else if(k=='fire'){RR(14,29,13,6,2,'#3a3a42');RR(26,28,22,8,2,LG(0,28,0,36,['#e6c36a','#a07a2a','#6a4a14']));for(const x of[30,38])RR(x,27,3,10,1,'#4a4a52');RR(46,26,6,12,2,LG(0,26,0,38,['#ffd37a','#b87a2a']));g.fillStyle='#1a1008';g.beginPath();g.ellipse(52,32,1.6,4,0,0,6.28);g.fill();E(32,32,3.5,3.5,'#d33')}else{g.fillStyle=LG(0,24,0,40,['#6b7284','#2b2f3a','#14161c']);g.beginPath();g.moveTo(14,25);g.lineTo(46,27);g.lineTo(46,37);g.lineTo(14,39);g.closePath();g.fill();g.strokeStyle='#0a0c10';g.lineWidth=1.5;g.stroke();RR(44,24,8,16,2,LG(0,24,0,40,['#7a8094','#2b2f3a']));for(const x of[22,34])RR(x,23,3,18,1,lv>1?(lv>2?'#ffc83d':'#c9cfdc'):'#59617a');g.fillStyle='rgba(255,255,255,.35)';g.fillRect(16,27,28,2);E(30,32,2,2,'#0a0c10');E(14,32,4.5,6,'#2b2f3a');E(51,32,2.6,4,'#050608')}}
return TS[key]=c}
function drawTower(t,px,py){const k=t.k,sc=T/64*1.12*(1+.13*(t.lv-1)),fr=Math.max(0,t.cd/stats(t).rate),tm=G.time;cx.save();cx.translate(px,py);cx.scale(sc,sc);if(sel===t){cx.strokeStyle='#ffc83d';cx.lineWidth=4;cx.beginPath();cx.arc(0,0,34,0,6.28);cx.stroke()}if(t.lv>2){cx.strokeStyle='rgba(255,200,60,'+(.3+.25*Math.sin(tm*4))+')';cx.lineWidth=2;cx.beginPath();cx.arc(0,0,31,0,6.28);cx.stroke()}cx.drawImage(tsp(k,t.lv,0),-32,-32);if(k=='archer'||k=='fire'||k=='cannon'){const hs=tsp(k,t.lv,1);for(const oy of OFS(t)){cx.save();cx.rotate(t.ang);cx.translate(-fr*(k=='cannon'?5:3),oy*.8);cx.drawImage(hs,-32,-32);if(k=='archer'&&fr<.6){cx.strokeStyle='#d9d2c0';cx.lineWidth=2;cx.beginPath();cx.moveTo(-6,0);cx.lineTo(22,0);cx.stroke();cx.fillStyle='#b8bfce';cx.beginPath();cx.moveTo(22,-3);cx.lineTo(30,0);cx.lineTo(22,3);cx.fill()}if(k=='fire'&&fr>.3){cx.fillStyle='rgba(255,140,40,.85)';cx.beginPath();cx.moveTo(21,0);cx.lineTo(34+14*fr,-8*fr-3);cx.lineTo(34+14*fr,8*fr+3);cx.fill();cx.fillStyle='rgba(255,230,120,.9)';cx.beginPath();cx.moveTo(21,0);cx.lineTo(28+8*fr,-3);cx.lineTo(28+8*fr,3);cx.fill()}if(k=='cannon'&&fr>.55){cx.fillStyle='rgba(190,190,200,'+(fr-.4)+')';for(let i=0;i<3;i++){cx.beginPath();cx.arc(26+i*5,(i-1)*3,4+i*2,0,6.28);cx.fill()}}cx.restore()}}else if(k=='frost'){cx.save();cx.rotate(tm*.4);cx.strokeStyle='rgba(191,234,255,.7)';cx.lineWidth=1.5;for(let i=0;i<6;i++){cx.rotate(1.047);cx.beginPath();cx.moveTo(17,0);cx.lineTo(27,0);cx.moveTo(22,0);cx.lineTo(25,-3);cx.moveTo(22,0);cx.lineTo(25,3);cx.stroke()}cx.restore();const og=cx.createRadialGradient(0,2,0,0,2,10+fr*6);og.addColorStop(0,'rgba(255,255,255,.9)');og.addColorStop(.5,'rgba(150,225,255,.45)');og.addColorStop(1,'rgba(150,225,255,0)');cx.fillStyle=og;cx.fillRect(-20,-18,40,40)}else{const og=cx.createRadialGradient(0,0,0,0,0,9+fr*5);og.addColorStop(0,'#fff');og.addColorStop(.4,'#b48bff');og.addColorStop(1,'rgba(155,107,255,0)');cx.fillStyle=og;cx.fillRect(-16,-16,32,32);cx.strokeStyle='rgba(225,205,255,'+(.3+fr*.7)+')';cx.lineWidth=1.5;if(fr>.05||Math.sin(tm*20)>.6){for(let i=0;i<3;i++){const a=Math.random()*6.28;cx.beginPath();cx.moveTo(0,0);cx.lineTo(Math.cos(a)*9,Math.sin(a)*9);cx.lineTo(Math.cos(a)*17+Math.random()*4,Math.sin(a)*17);cx.stroke()}}}cx.restore()}
const TC={};function rng(s){return()=>(s=(s*1664525+1013904223)>>>0)/4294967296}
function tileImg(x,y,p){const par=(x+y)&1,v=hh(x,y)%4;let m=0;if(p){const q=(a,b)=>pathTiles.has(a+','+b)||a<0;m=(q(x,y-1)?1:0)|(q(x+1,y)?2:0)|(q(x,y+1)?4:0)|(q(x-1,y)?8:0)}const key=MAPN+(p?'p'+m+'_'+v:'g'+par+'_'+v);if(TC[key])return TC[key];if(MAPN==1)return snowTile(x,y,p,m,par,v,key);const c=document.createElement('canvas');c.width=c.height=64;const g=c.getContext('2d'),R=rng(key.split('').reduce((a,ch)=>(a*31+ch.charCodeAt(0))>>>0,7));const blob=(r,col)=>{const bx=R()*64,by=R()*64;for(const dx of[-64,0,64])for(const dy of[-64,0,64]){const gr=g.createRadialGradient(bx+dx,by+dy,0,bx+dx,by+dy,r);gr.addColorStop(0,col);gr.addColorStop(1,'rgba(0,0,0,0)');g.fillStyle=gr;g.fillRect(0,0,64,64)}};const dot=(x,y,rx,ry,col)=>{g.fillStyle=col;g.beginPath();g.ellipse(x,y,rx,ry,0,0,6.28);g.fill()};if(!p){g.fillStyle=par?'#41754b':'#3b6e46';g.fillRect(0,0,64,64);for(let i=0;i<8;i++)blob(10+R()*14,i%2?'rgba(110,170,90,.22)':'rgba(15,50,30,.28)');const gc=['#2d5a3a','#4c8a56','#62a564','#356b43','#78b46a'];g.lineWidth=1.3;g.lineCap='round';for(let i=0;i<150;i++){const bx=R()*64,by=R()*64,h=3+R()*6,l=(R()-.5)*4;g.strokeStyle=gc[R()*5|0];g.beginPath();g.moveTo(bx,by);g.quadraticCurveTo(bx+l*.3,by-h*.6,bx+l,by-h);g.stroke()}for(let i=0;i<3;i++){const cx0=R()*56+4,cy0=R()*56+4;for(let k=0;k<3;k++)dot(cx0+Math.cos(k*2.1)*2.2,cy0+Math.sin(k*2.1)*2.2,2.2,2.2,'#58a863');dot(cx0,cy0,1,1,'#7cc47f')}const nf=v%3;for(let i=0;i<nf;i++){const fx=R()*54+5,fy=R()*54+5,fc=['#fff','#ffe066','#ffb3d9','#c9b3ff'][R()*4|0];for(let k=0;k<5;k++)dot(fx+Math.cos(k*1.26)*2.4,fy+Math.sin(k*1.26)*2.4,1.8,1.8,fc);dot(fx,fy,1.4,1.4,'#e0a020')}}else{g.fillStyle=par?'#8e7250':'#876b4a';g.fillRect(0,0,64,64);for(let i=0;i<9;i++)blob(9+R()*14,i%2?'rgba(190,160,115,.28)':'rgba(60,40,24,.3)');const sc=['#a58862','#6e553a','#9a7d57','#5d4630','#b79a72'];for(let i=0;i<300;i++){g.fillStyle=sc[R()*5|0];g.globalAlpha=.5+R()*.5;g.fillRect(R()*64,R()*64,1+R()*1.5,1+R()*1.5)}g.globalAlpha=1;for(let i=0;i<2;i++){g.strokeStyle='rgba(60,40,24,.5)';g.lineWidth=1;g.beginPath();let cx1=R()*64,cy1=R()*64;g.moveTo(cx1,cy1);for(let k=0;k<5;k++){cx1+=(R()-.5)*14;cy1+=(R()-.3)*10;g.lineTo(cx1,cy1)}g.stroke()}const pc=['#9a8f84','#7d7368','#b0a79b','#8c8478'];for(let i=0;i<8;i++){const px=6+R()*52,py=6+R()*52,rx=1.6+R()*3.2,ry=rx*(.6+R()*.3);dot(px+1.2,py+1.6,rx,ry,'rgba(30,20,10,.45)');dot(px,py,rx,ry,pc[R()*4|0]);dot(px-rx*.3,py-ry*.3,rx*.45,ry*.4,'rgba(255,255,255,.35)')}for(let i=0;i<4;i++){if(m&(1<<i))continue;g.save();g.translate(32,32);g.rotate(i*Math.PI/2);g.translate(-32,-32);const gr=g.createLinearGradient(0,0,0,14);gr.addColorStop(0,'rgba(30,20,10,.75)');gr.addColorStop(1,'rgba(30,20,10,0)');g.fillStyle=gr;g.fillRect(0,0,64,14);g.fillStyle='#3b6e46';g.fillRect(0,0,64,3);for(let k=0;k<5;k++)dot(R()*64,3+R()*4,3+R()*4,1.5,'rgba(25,18,10,.5)');const bc=['#2d5a3a','#4c8a56','#62a564','#356b43'];g.lineWidth=1.7;g.lineCap='round';for(let k=0;k<26;k++){const bx=R()*64,l=5+R()*8,lean=(R()-.5)*5;g.strokeStyle=bc[R()*4|0];g.beginPath();g.moveTo(bx,-1);g.quadraticCurveTo(bx+lean*.3,l*.6,bx+lean,l);g.stroke()}g.restore()}}return TC[key]=c}
function torsoArt(e,u,tw,cl,sk){const w=u*tw,v=e.v||0;cx.save();cx.beginPath();cx.ellipse(0,-u*.2,w,u*.24,0,0,6.28);cx.clip();cx.fillStyle='rgba(255,255,255,.13)';cx.beginPath();cx.ellipse(-w*.4,-u*.27,w*.45,u*.14,0,0,6.28);cx.fill();cx.fillStyle='rgba(0,0,0,.25)';cx.beginPath();cx.ellipse(w*.5,-u*.12,w*.6,u*.2,0,0,6.28);cx.fill();cx.fillStyle='#2a2220';cx.fillRect(-w,-u*.1,w*2,u*.05);cx.fillStyle='#d9b23c';cx.fillRect(-w*.2,-u*.105,w*.4,u*.06);if(v%3==0){cx.fillStyle=sk;cx.fillRect(-w*.1,-u*.38,w*.7,u*.18);cx.strokeStyle='#e8f4f0';cx.lineWidth=1.2;for(let i=0;i<3;i++){cx.beginPath();cx.moveTo(-w*.05,-u*.35+i*u*.045);cx.lineTo(w*.55,-u*.35+i*u*.045);cx.stroke()}}else if(v%3==1){cx.fillStyle='#d94a3a';cx.beginPath();cx.moveTo(0,-u*.4);cx.lineTo(w*.2,-u*.36);cx.lineTo(w*.12,-u*.15);cx.lineTo(0,-u*.12);cx.lineTo(-w*.1,-u*.15);cx.fill()}else{cx.fillStyle='#8a7a5a';cx.fillRect(-w*.7,-u*.3,w*.5,u*.1);cx.strokeStyle='#efe3b0';cx.setLineDash([2,2]);cx.lineWidth=1;cx.strokeRect(-w*.7,-u*.3,w*.5,u*.1);cx.setLineDash([])}cx.fillStyle=sk;for(let i=0;i<5;i++){cx.beginPath();cx.moveTo(-w+i*w*.4,u*.02);cx.lineTo(-w+i*w*.4+w*.2,-u*.04);cx.lineTo(-w+(i+1)*w*.4,u*.02);cx.fill()}cx.restore()}
let _b;function baseImg(){if(_b)return _b;const c=document.createElement('canvas');c.width=c.height=64;const g=c.getContext('2d'),R=rng(11);g.fillStyle='rgba(0,0,0,.35)';g.beginPath();g.ellipse(33,36,29,26,0,0,6.28);g.fill();const gr=g.createRadialGradient(26,24,4,32,32,30);gr.addColorStop(0,'#939aae');gr.addColorStop(1,'#515769');g.fillStyle=gr;g.beginPath();g.arc(32,32,28,0,6.28);g.fill();g.strokeStyle='#23273a';g.lineWidth=2;g.stroke();g.strokeStyle='rgba(20,22,32,.55)';g.lineWidth=1;for(let i=0;i<14;i++){const a=i*.4488;g.beginPath();g.moveTo(32+Math.cos(a)*20,32+Math.sin(a)*20);g.lineTo(32+Math.cos(a)*28,32+Math.sin(a)*28);g.stroke()}g.beginPath();g.arc(32,32,20,0,6.28);g.stroke();for(let i=0;i<140;i++){const a=R()*6.28,d=R()*27;g.fillStyle=R()<.5?'rgba(255,255,255,.18)':'rgba(0,0,0,.22)';g.fillRect(32+Math.cos(a)*d,32+Math.sin(a)*d,1.3,1.3)}for(let i=0;i<4;i++){const a=R()*6.28;g.fillStyle='rgba(88,140,72,.75)';g.beginPath();g.ellipse(32+Math.cos(a)*25,32+Math.sin(a)*25,4,2,a,0,6.28);g.fill()}return _b=c}
function drawTowerOld(t,px,py){const k=t.k,s=T/64,fr=Math.max(0,t.cd/stats(t).rate),tm=G.time;cx.save();cx.translate(px,py);cx.scale(s*(1+.15*(t.lv-1)),s*(1+.15*(t.lv-1)));cx.lineJoin='round';if(sel===t){cx.strokeStyle='#ffc83d';cx.lineWidth=4;cx.beginPath();cx.arc(0,0,34,0,6.28);cx.stroke()}cx.drawImage(baseImg(),-32,-32);cx.strokeStyle=['#a4733c','#c9cfdc','#ffc83d'][t.lv-1];cx.lineWidth=3;cx.beginPath();cx.arc(0,0,27,0,6.28);cx.stroke();const O='#10161c';if(t.lv>1){cx.fillStyle=t.lv>2?'#ffc83d':'#c9cfdc';for(let i=0;i<8;i++){const a=i*.785;cx.beginPath();cx.arc(Math.cos(a)*27,Math.sin(a)*27,2.4,0,6.28);cx.fill()}}if(t.lv>2){cx.strokeStyle='rgba(255,200,60,'+(.35+.25*Math.sin(tm*4))+')';cx.lineWidth=2;cx.beginPath();cx.arc(0,0,31,0,6.28);cx.stroke()}if(k=='archer'){cx.fillStyle='#8a5e36';cx.fillRect(-13,-13,26,26);cx.strokeStyle='#4a2f18';cx.lineWidth=2;cx.strokeRect(-13,-13,26,26);cx.beginPath();for(const i of[-6,0,6]){cx.moveTo(-13,i);cx.lineTo(13,i)}cx.stroke();cx.fillStyle='#c0392b';cx.fillRect(-13,-20,7,11);for(const oy of OFS(t)){cx.save();cx.rotate(t.ang);cx.translate(-fr*4,oy);cx.fillStyle='#b88650';cx.fillRect(-10,-3,28,6);cx.strokeStyle='#4a2f18';cx.lineWidth=1.5;cx.strokeRect(-10,-3,28,6);cx.strokeStyle='#e0bd85';cx.lineWidth=4;cx.beginPath();cx.arc(10,0,14,-1.2,1.2);cx.stroke();cx.strokeStyle='#eee';cx.lineWidth=1;cx.beginPath();cx.moveTo(10+14*Math.cos(1.2),14*Math.sin(1.2));cx.lineTo(fr>.5?10:4,0);cx.lineTo(10+14*Math.cos(1.2),-14*Math.sin(1.2));cx.stroke();if(fr<.6){cx.strokeStyle='#d9d2c0';cx.lineWidth=2;cx.beginPath();cx.moveTo(4,0);cx.lineTo(24,0);cx.stroke();cx.fillStyle='#9aa1b2';cx.beginPath();cx.moveTo(24,-3);cx.lineTo(30,0);cx.lineTo(24,3);cx.fill()}cx.restore()}}else if(k=='fire'){cx.fillStyle='#7a2a1a';cx.beginPath();cx.arc(0,0,14,0,6.28);cx.fill();cx.strokeStyle='#2a0f0a';cx.lineWidth=2;cx.stroke();cx.fillStyle='#c4502f';cx.beginPath();cx.arc(-3,-3,8,0,6.28);cx.fill();for(const oy of OFS(t)){cx.save();cx.rotate(t.ang);cx.translate(0,oy*.8);cx.fillStyle='#4a4a52';cx.fillRect(4,-5,20,10);cx.strokeStyle=O;cx.lineWidth=1.5;cx.strokeRect(4,-5,20,10);cx.fillStyle='#ffb347';cx.fillRect(20,-6,4,12);if(fr>.3){cx.fillStyle='rgba(255,140,40,.85)';cx.beginPath();cx.moveTo(24,0);cx.lineTo(38+14*fr,-8*fr-3);cx.lineTo(38+14*fr,8*fr+3);cx.fill();cx.fillStyle='rgba(255,230,120,.9)';cx.beginPath();cx.moveTo(24,0);cx.lineTo(32+8*fr,-3);cx.lineTo(32+8*fr,3);cx.fill()}cx.restore()}cx.fillStyle='#ff8a3d';cx.beginPath();cx.ellipse(-6,-9-Math.sin(tm*12)*1.5,3,5,0,0,6.28);cx.fill();cx.fillStyle='#ffe27a';cx.beginPath();cx.ellipse(-6,-8,1.5,3,0,0,6.28);cx.fill()}else if(k=='frost'){cx.save();cx.rotate(tm*.4);cx.strokeStyle='#bfeaff99';cx.lineWidth=1.5;for(let i=0;i<6;i++){cx.rotate(1.047);cx.beginPath();cx.moveTo(15,0);cx.lineTo(25,0);cx.stroke()}cx.restore();const sh=(x,h,w)=>{cx.fillStyle='#7fd0f0';cx.beginPath();cx.moveTo(x-w,9);cx.lineTo(x,9-h);cx.lineTo(x+w,9);cx.closePath();cx.fill();cx.fillStyle='#c8f0ff';cx.beginPath();cx.moveTo(x-w,9);cx.lineTo(x,9-h);cx.lineTo(x,9);cx.closePath();cx.fill();cx.strokeStyle='#2a6a8a';cx.lineWidth=1.5;cx.beginPath();cx.moveTo(x-w,9);cx.lineTo(x,9-h);cx.lineTo(x+w,9);cx.closePath();cx.stroke()};sh(-9,16,5);sh(9,14,5);sh(0,26+(t.lv-1)*4,7);if(t.lv>1){sh(-15,10,4);sh(15,10,4)}if(t.lv>2){sh(-4,20,4);sh(5,22,4)}const og=cx.createRadialGradient(0,-4,0,0,-4,10+fr*5);og.addColorStop(0,'rgba(255,255,255,.95)');og.addColorStop(.5,'rgba(150,225,255,.6)');og.addColorStop(1,'rgba(150,225,255,0)');cx.fillStyle=og;cx.fillRect(-18,-22,36,36)}else if(k=='cannon'){for(const sx of[-13,13]){cx.fillStyle='#7a5230';cx.beginPath();cx.arc(sx,9,7,0,6.28);cx.fill();cx.strokeStyle='#2a1a0c';cx.lineWidth=1.5;cx.stroke();cx.beginPath();for(let i=0;i<4;i++){cx.moveTo(sx,9);cx.lineTo(sx+Math.cos(i*.785)*7,9+Math.sin(i*.785)*7);cx.moveTo(sx,9);cx.lineTo(sx-Math.cos(i*.785)*7,9-Math.sin(i*.785)*7)}cx.stroke()}for(const oy of OFS(t)){cx.save();cx.rotate(t.ang);cx.translate(-fr*5,oy*.7);cx.fillStyle='#2b2f3a';cx.fillRect(-10,-8,34,16);cx.strokeStyle='#0e1016';cx.lineWidth=1.5;cx.strokeRect(-10,-8,34,16);cx.fillStyle='#59617a';cx.fillRect(-8,-6,30,3);cx.fillStyle='#6b7284';cx.fillRect(0,-8,3,16);cx.fillRect(16,-8,3,16);cx.fillStyle='#3a3f4c';cx.fillRect(22,-10,5,20);if(fr>.55){cx.fillStyle='rgba(180,180,190,'+(fr-.4)+')';for(let i=0;i<3;i++){cx.beginPath();cx.arc(30+i*5,(i-1)*3,4+i*2,0,6.28);cx.fill()}}cx.restore()}cx.fillStyle='#4a4f5e';cx.beginPath();cx.arc(0,0,8,0,6.28);cx.fill();cx.strokeStyle='#0e1016';cx.stroke()}else{cx.fillStyle='#3a3f50';cx.beginPath();cx.moveTo(-12,13);cx.lineTo(-7,-8);cx.lineTo(7,-8);cx.lineTo(12,13);cx.closePath();cx.fill();cx.strokeStyle=O;cx.lineWidth=2;cx.stroke();cx.strokeStyle='#c97b3c';cx.lineWidth=3;for(const y of[-4,2,8]){cx.beginPath();cx.moveTo(-9+(y+8)*.15,y);cx.lineTo(9-(y+8)*.15,y);cx.stroke()}if(t.lv>1)for(const sx of[-17,17]){cx.fillStyle='#3a3f50';cx.fillRect(sx-3,-2,6,14);cx.strokeStyle=O;cx.lineWidth=1.5;cx.strokeRect(sx-3,-2,6,14);cx.fillStyle='#b48bff';cx.beginPath();cx.arc(sx,-4,4,0,6.28);cx.fill()}const og=cx.createRadialGradient(0,-13,0,0,-13,13+fr*5);og.addColorStop(0,'#fff');og.addColorStop(.4,'#b48bff');og.addColorStop(1,'rgba(155,107,255,0)');cx.fillStyle=og;cx.fillRect(-20,-30,40,34);cx.strokeStyle='rgba(225,205,255,'+(.3+fr*.7)+')';cx.lineWidth=1.5;if(fr>.05||Math.sin(tm*20)>.6){for(let i=0;i<3;i++){const a=Math.random()*6.28;cx.beginPath();cx.moveTo(0,-13);cx.lineTo(Math.cos(a)*8,-13+Math.sin(a)*8);cx.lineTo(Math.cos(a)*15+Math.random()*4,-13+Math.sin(a)*15);cx.stroke()}}}cx.restore()}
const SP={};function spr(kd,v){const key=MAPN+'_'+kd+'_'+v;if(SP[key])return SP[key];const c=document.createElement('canvas');c.width=96;c.height=112;const g=c.getContext('2d'),R=rng(kd*97+v*13+5);const E=(x,y,a,b,col)=>{g.fillStyle=col;g.beginPath();g.ellipse(x,y,a,b,0,0,6.28);g.fill()};const P=(pts,col,st)=>{g.fillStyle=col;g.beginPath();pts.forEach((p,i)=>i?g.lineTo(p[0],p[1]):g.moveTo(p[0],p[1]));g.closePath();g.fill();if(st){g.strokeStyle=st;g.lineWidth=1.5;g.lineJoin='round';g.stroke()}};E(48,100,32,8,'rgba(0,0,0,.4)');if(kd==0){g.fillStyle='#4b3322';g.fillRect(43,82,10,19);g.fillStyle='#33231a';g.fillRect(43,82,4,19);const cl=[['#14382a','#1c4d3a'],['#17412f','#215a43'],['#1b4a37','#2a6a4e'],['#205641','#327a5a']];for(let i=0;i<4;i++){const by=90-i*19,w=36-i*7,tp=by-32+i*2;P([[48-w,by],[48,tp],[48,by]],cl[i][0]);P([[48,tp],[48+w,by],[48,by]],cl[i][1]);for(let k=0;k<8;k++){const x0=48-w+k*w/4;P([[x0,by-1],[x0+w/8,by+6],[x0+w/4,by-1]],cl[i][k<4?0:1])}g.strokeStyle='rgba(180,230,170,.35)';g.lineWidth=1;for(let k=0;k<22;k++){const px=48+(R()-.5)*w*1.2,py=tp+8+R()*(by-tp-8);g.beginPath();g.moveTo(px,py);g.lineTo(px+(R()-.5)*5,py+4);g.stroke()}g.strokeStyle='#0d1f17';g.lineWidth=1.5;g.beginPath();g.moveTo(48-w,by);g.lineTo(48,tp);g.lineTo(48+w,by);g.stroke()}}else if(kd==1){g.fillStyle='#5b3f2b';g.beginPath();g.moveTo(38,102);g.quadraticCurveTo(44,92,43,70);g.lineTo(53,70);g.quadraticCurveTo(52,92,60,102);g.closePath();g.fill();g.strokeStyle='#2a1c12';g.lineWidth=1.5;g.stroke();g.fillStyle='#3d2a1c';g.fillRect(43,72,4,26);const gc=['#1f5a34','#2a6b3e','#357d49','#43925a','#58aa6c'],bl=[];for(let i=0;i<34;i++){const a=R()*6.28,d=R()*26;bl.push([48+Math.cos(a)*d*1.2,44+Math.sin(a)*d*.85,9+R()*8,R()])}bl.sort((a,b)=>b[1]-a[1]);for(const b of bl)E(b[0],b[1],b[2]+1.5,b[2]+1.5,'#10301c');for(const b of bl)E(b[0],b[1],b[2],b[2],gc[Math.max(0,Math.min(4,Math.floor((1-(b[1]-20)/50)*4+b[3]*.8)))]);for(let i=0;i<30;i++)E(30+R()*36,26+R()*30,1.6,1.1,'rgba(200,255,180,.4)');if(v==2)for(let i=0;i<5;i++)E(32+R()*32,36+R()*22,2.4,2.4,'#d9372f')}else if(kd==2){const rk=(x0,y0,s)=>{const n=7,pts=[];for(let i=0;i<n;i++){const a=i/n*6.28,rr=s*(.75+R()*.35);pts.push([x0+Math.cos(a)*rr,y0+Math.sin(a)*rr*.72])}const gr=g.createLinearGradient(x0-s,y0-s,x0+s,y0+s);gr.addColorStop(0,'#aab0c0');gr.addColorStop(1,'#5b6174');P(pts,gr,'#1e2230');for(let i=0;i<n;i++)P([[x0-s*.1,y0-s*.15],pts[i],pts[(i+1)%n]],i<3?'rgba(255,255,255,.14)':'rgba(0,0,0,.18)');g.strokeStyle='rgba(20,24,36,.6)';g.lineWidth=1;g.beginPath();g.moveTo(x0-s*.2,y0-s*.3);g.lineTo(x0,y0);g.lineTo(x0+s*.15,y0+s*.25);g.stroke();for(let i=0;i<18;i++)E(x0+(R()-.5)*s*1.4,y0+(R()-.5)*s,.8,.8,R()<.5?'rgba(255,255,255,.3)':'rgba(0,0,0,.3)');E(x0-s*.35,y0+s*.3,s*.3,s*.12,'rgba(95,150,80,.8)')};rk(40,86,24);rk(66,92,13);rk(28,96,9)}else if(kd==3){E(48,98,26,8,'#3a2f22');E(48,96,22,5,'#4a3b2b');const st=g.createLinearGradient(30,0,66,0);st.addColorStop(0,'#aeb4c4');st.addColorStop(.5,'#8a91a4');st.addColorStop(1,'#5f6578');g.fillStyle=st;g.beginPath();g.moveTo(33,96);g.lineTo(33,52);g.arc(48,52,15,Math.PI,0);g.lineTo(63,96);g.closePath();g.fill();g.strokeStyle='#1e2230';g.lineWidth=2;g.stroke();g.strokeStyle='rgba(255,255,255,.25)';g.beginPath();g.moveTo(35,94);g.lineTo(35,52);g.stroke();g.strokeStyle='#3a4054';g.lineWidth=2.5;g.lineCap='round';if(v==0){g.beginPath();g.moveTo(48,48);g.lineTo(48,70);g.moveTo(40,56);g.lineTo(56,56);g.stroke()}else{g.font='bold 11px Georgia,serif';g.fillStyle='#3a4054';g.textAlign='center';g.fillText('RIP',48,62);g.beginPath();g.moveTo(41,70);g.lineTo(55,70);g.stroke()}g.strokeStyle='rgba(20,24,36,.7)';g.lineWidth=1;g.beginPath();g.moveTo(58,60);g.lineTo(54,70);g.lineTo(57,80);g.stroke();E(40,95,10,4,'#4f7a3f');E(58,88,4,6,'#5f8a4a');for(let i=0;i<14;i++)E(34+R()*28,56+R()*38,.9,.9,'rgba(0,0,0,.3)');g.strokeStyle='#4f8a46';g.lineWidth=1.5;for(let i=0;i<14;i++){const x0=24+R()*48;g.beginPath();g.moveTo(x0,99);g.lineTo(x0+(R()-.5)*6,92-R()*5);g.stroke()}if(v==2){E(30,96,2,2,'#fff');E(66,95,2,2,'#ffe066')}}else{g.lineCap='round';const br=(x1,y1,x2,y2,w)=>{g.lineWidth=w+2;g.strokeStyle='#150f0c';g.beginPath();g.moveTo(x1,y1);g.lineTo(x2,y2);g.stroke();g.lineWidth=w;g.strokeStyle='#4a3a34';g.beginPath();g.moveTo(x1,y1);g.lineTo(x2,y2);g.stroke();g.lineWidth=w*.3;g.strokeStyle='#6b564c';g.beginPath();g.moveTo(x1-w*.2,y1);g.lineTo(x2-w*.2,y2);g.stroke()};br(46,102,50,70,10);br(50,70,46,50,8);br(48,60,26,36,5);br(26,36,16,24,3);br(26,36,30,20,3);br(49,52,72,34,5);br(72,34,82,26,3);br(72,34,76,18,3);br(47,52,50,28,4);br(50,28,44,14,3);if(v==1){E(74,31,5,3.5,'#14141a');P([[78,29],[84,30],[78,32]],'#d9a23c')}g.strokeStyle='rgba(120,160,100,.7)';g.lineWidth=1.5;for(let i=0;i<4;i++){g.beginPath();g.moveTo(30+i*6,38+i);g.lineTo(30+i*6,50+R()*6);g.stroke()}}if(MAPN==1)snowify(g,kd,R);return SP[key]=c}
function drawSpr(kd,x,y,X,Y,sw){if(pick=='shovel'&&kd==3){cx.fillStyle='rgba(255,90,90,'+(.18+.12*Math.sin(G.time*6))+')';cx.fillRect(x*T+1,y*T+1,T-2,T-2)}const im=spr(kd,hh(x,y)%3),w=T*1.5,h=w*112/96;cx.save();cx.translate(X,Y+T*.38);if(kd==0||kd==1||kd==4)cx.rotate(sw/T*.5);cx.drawImage(im,-w/2,-h*100/112,w,h);cx.restore()}
function drawDecor(){for(let y=0;y<ROWS;y++)for(let x=0;x<COLS;x++){const k=x+','+y,X=x*T+T/2,Y=y*T+T/2,h=hh(x,y),kd=deco.get(k);if(pathTiles.has(k)){if(h%5==0){cx.fillStyle='#8a7765';cx.beginPath();cx.ellipse(x*T+(h%7+1)*T/9,y*T+(h%5+2)*T/8,T*.04,T*.03,0,0,6.28);cx.fill()}continue}if(kd===undefined){if(h%3==0){cx.strokeStyle=MAPN?'#9ab4c8':'#4f7a5a';cx.lineWidth=1.5;for(let i=-1;i<=1;i++){cx.beginPath();cx.moveTo(X+i*4,Y+8);cx.lineTo(X+i*5-1,Y+1);cx.stroke()}}if(h%9==0){cx.fillStyle=MAPN?['#ffffff','#bfe4ff','#e6f4ff'][h%3]:['#ffd1e8','#fff3a3','#c9b3ff'][h%3];cx.beginPath();cx.arc(X+T*.2,Y+T*.15,T*.04,0,6.28);cx.fill()}continue}const sw=Math.sin(G.time*1.6+x*2+y)*T*.025;drawSpr(kd,x,y,X,Y,sw);continue;cx.fillStyle='#0005';cx.beginPath();cx.ellipse(X,Y+T*.3,T*.3,T*.09,0,0,6.28);cx.fill();if(kd==0||kd==1){cx.fillStyle='#5b3f2b';cx.fillRect(X-T*.05,Y+T*.05,T*.1,T*.25)}if(kd==0){const c=['#1f4d3a','#26604a','#2f7357'];for(let i=0;i<3;i++){const w=T*(.34-i*.07),b=Y+T*.14-i*T*.22;cx.fillStyle=c[i];cx.beginPath();cx.moveTo(X-w,b);cx.lineTo(X+w,b);cx.lineTo(X+sw*(i+1)*.6,b-T*.36);cx.fill()}}else if(kd==1){cx.fillStyle='#2f6b45';cx.beginPath();cx.arc(X+sw,Y-T*.15,T*.27,0,6.28);cx.fill();cx.fillStyle='#3a7d50';cx.beginPath();cx.arc(X-T*.17+sw,Y-T*.05,T*.18,0,6.28);cx.arc(X+T*.17+sw,Y-T*.04,T*.18,0,6.28);cx.fill();cx.fillStyle='#4b9a63';cx.beginPath();cx.arc(X-T*.06+sw,Y-T*.26,T*.1,0,6.28);cx.fill()}else if(kd==2){cx.fillStyle='#7b8190';cx.beginPath();cx.ellipse(X-T*.05,Y+T*.1,T*.3,T*.2,0,0,6.28);cx.fill();cx.fillStyle='#9aa1b2';cx.beginPath();cx.ellipse(X-T*.1,Y+T*.03,T*.16,T*.09,-.3,0,6.28);cx.fill();cx.fillStyle='#656b7a';cx.beginPath();cx.ellipse(X+T*.2,Y+T*.2,T*.12,T*.08,0,0,6.28);cx.fill()}else if(kd==3){cx.fillStyle='#3b3b2a';cx.beginPath();cx.ellipse(X,Y+T*.25,T*.28,T*.1,0,0,6.28);cx.fill();cx.fillStyle='#8c92a6';cx.beginPath();cx.moveTo(X-T*.16,Y+T*.22);cx.lineTo(X-T*.16,Y-T*.06);cx.arc(X,Y-T*.06,T*.16,Math.PI,0);cx.lineTo(X+T*.16,Y+T*.22);cx.fill();cx.strokeStyle='#5b6073';cx.lineWidth=2;cx.beginPath();cx.moveTo(X,Y-T*.12);cx.lineTo(X,Y+T*.06);cx.moveTo(X-T*.06,Y-T*.05);cx.lineTo(X+T*.06,Y-T*.05);cx.stroke();cx.fillStyle='#5f8a52';cx.fillRect(X-T*.16,Y+T*.16,T*.12,T*.06)}else{cx.strokeStyle='#4a3a34';cx.lineCap='round';cx.lineWidth=T*.09;cx.beginPath();cx.moveTo(X,Y+T*.3);cx.lineTo(X+sw*.5,Y-T*.3);cx.stroke();cx.lineWidth=T*.045;cx.beginPath();cx.moveTo(X+sw*.4,Y-T*.15);cx.lineTo(X-T*.22+sw,Y-T*.42);cx.moveTo(X+sw*.5,Y-T*.25);cx.lineTo(X+T*.22+sw,Y-T*.4);cx.moveTo(X-T*.02,Y+T*.05);cx.lineTo(X+T*.16,Y-T*.1);cx.stroke()}}}
function headArt(e,u,sk,ph,dead){const ty=e.ty,r=u*({boss:.23,kid:.26,giant:.2}[ty]||.19),cy=-u*.07,top=cy-r,acc=MAPN?'none':ty=='boss'?'pirate':ty=='tank'?'helmet':ty=='crawler'?'brain':ty=='fast'||ty=='kid'?'cap':ty=='fat'?'pot':ty=='tall'?'cowboy':ty=='giant'?'mohawk':ty=='short'?'beret':['cop','afro','pot','cowboy','cleaver','mohawk','arrows','beret'][(e.v||0)%8];const C=(x,y,rr,c,st)=>{cx.fillStyle=c;cx.beginPath();cx.arc(x,y,rr,0,6.28);cx.fill();if(st){cx.strokeStyle='#0c2b30';cx.lineWidth=1.5;cx.stroke()}};const E=(x,y,a,b,c,rt=0)=>{cx.fillStyle=c;cx.beginPath();cx.ellipse(x,y,a,b,rt,0,6.28);cx.fill()};const dome=(c,k)=>{cx.fillStyle=c;cx.beginPath();cx.arc(0,cy-r*.1,r*k,Math.PI,0);cx.closePath();cx.fill();cx.strokeStyle='#0c2b30';cx.lineWidth=1.5;cx.stroke()};if(acc=='afro')C(0,cy-r*.3,r*1.35,'#1d1d22');if(acc=='mohawk'){cx.fillStyle='#6b3a3a';for(let i=0;i<4;i++){cx.beginPath();cx.moveTo(-r*.5+i*r*.35,top+r*.15);cx.lineTo(-r*.35+i*r*.35,top-r*.5);cx.lineTo(-r*.2+i*r*.35,top+r*.1);cx.fill()}}C(-r*.95,cy+r*.1,r*.22,sk,1);C(0,cy,r,sk,1);C(-r*.3,cy+r*.45,r*.07,'#3d8c90');C(r*.35,cy+r*.5,r*.06,'#3d8c90');cx.save();cx.beginPath();cx.arc(0,cy,r,0,6.28);cx.clip();const hg=cx.createRadialGradient(-r*.35,cy-r*.35,r*.1,0,cy,r*1.05);hg.addColorStop(0,'rgba(255,255,255,.25)');hg.addColorStop(.55,'rgba(255,255,255,0)');hg.addColorStop(1,'rgba(0,40,50,.4)');cx.fillStyle=hg;cx.fillRect(-r*1.2,cy-r*1.2,r*2.4,r*2.4);for(let i=0;i<6;i++)E(Math.sin(i*2.3+(e.v||0))*r*.6,cy+Math.cos(i*1.7+(e.v||0))*r*.6,r*.05,r*.05,'rgba(0,60,70,.35)');if((e.v||0)%3==1){cx.strokeStyle='#1b3a40';cx.lineWidth=1.3;cx.beginPath();cx.moveTo(-r*.7,cy-r*.45);cx.lineTo(r*.2,cy-r*.65);cx.stroke();for(let i=0;i<5;i++){cx.beginPath();cx.moveTo(-r*.6+i*r*.17,cy-r*.52-i*r*.04);cx.lineTo(-r*.6+i*r*.17,cy-r*.66-i*r*.04);cx.stroke()}}cx.restore();const wob=dead?0:Math.sin(ph*.7)*r*.04;for(const ex of[-r*.28,r*.4]){C(ex,cy-r*.1,r*.3,'#fff',1);if(dead){cx.strokeStyle='#10343a';cx.lineWidth=1.5;cx.beginPath();cx.moveTo(ex-r*.12,cy-r*.22);cx.lineTo(ex+r*.12,cy);cx.moveTo(ex+r*.12,cy-r*.22);cx.lineTo(ex-r*.12,cy);cx.stroke()}else C(ex+r*.08+wob,cy-r*.08,r*.1,'#12262b')}cx.strokeStyle='#b0303a';cx.lineWidth=.8;for(const ex of[-r*.28,r*.4])for(let i=0;i<3;i++){cx.beginPath();cx.moveTo(ex+Math.cos(i*2.1)*r*.3,cy-r*.1+Math.sin(i*2.1)*r*.3);cx.lineTo(ex+Math.cos(i*2.1)*r*.14,cy-r*.1+Math.sin(i*2.1)*r*.14);cx.stroke()}cx.strokeStyle='#0c2b30';cx.lineWidth=2;cx.beginPath();cx.moveTo(-r*.6,cy-r*.42);cx.lineTo(-r*.05,cy-r*.5);cx.moveTo(r*.15,cy-r*.5);cx.lineTo(r*.7,cy-r*.38);cx.stroke();E(r*.15,cy+r*.55,r*.3,r*.16+(dead?0:Math.abs(Math.sin(ph*.7))*r*.05),'#1a0e12');cx.fillStyle='#f3efe2';cx.fillRect(0,cy+r*.4,r*.12,r*.1);cx.fillRect(r*.2,cy+r*.4,r*.12,r*.1);E(r*.25,cy+r*.78+wob*2,r*.13,r*.2,'#e0607a');if(MAPN)winterHead(e,r,cy,top);if(acc=='cap'){dome('#e8412c',1.06);cx.fillStyle='#fff';cx.beginPath();cx.arc(0,cy-r*.1,r*1.04,Math.PI*1.4,Math.PI*1.85);cx.lineTo(0,cy-r*.1);cx.fill();E(r*.85,cy-r*.62,r*.55,r*.13,'#c9301f');C(r*.1,top+r*.2,r*.1,'#e8412c')}else if(acc=='cop'){dome('#1f3f8f',1.1);E(r*.7,cy-r*.62,r*.7,r*.13,'#111');C(r*.05,top+r*.15,r*.13,'#ffc83d',1)}else if(acc=='helmet'){dome('#2b2b30',1.12);E(0,cy-r*.52,r*1.2,r*.1,'#1a1a1e');C(r*.05,top+r*.1,r*.14,'#ffc83d',1)}else if(acc=='pirate'){cx.fillStyle='#7a1520';cx.beginPath();cx.moveTo(-r*1.5,cy-r*.45);cx.lineTo(-r*.5,top-r*1.0);cx.lineTo(r*1.5,top-r*.2);cx.lineTo(r*1.3,cy-r*.5);cx.lineTo(0,cy-r*.75);cx.closePath();cx.fill();cx.strokeStyle='#0c2b30';cx.lineWidth=1.5;cx.stroke();C(-r*.1,top-r*.15,r*.3,'#f3efe2',1);C(r*.4,cy-r*.1,r*.32,'#111')}else if(acc=='pot'){cx.fillStyle='#f3f3f6';cx.fillRect(-r*.9,top-r*.55,r*1.8,r*.75);cx.strokeStyle='#0c2b30';cx.lineWidth=1.5;cx.strokeRect(-r*.9,top-r*.55,r*1.8,r*.75);cx.strokeStyle='#2b2b30';cx.lineWidth=r*.15;cx.beginPath();cx.moveTo(-r*.9,top-r*.1);cx.lineTo(-r*1.7,top+r*.2);cx.stroke()}else if(acc=='cowboy'){E(0,cy-r*.62,r*1.7,r*.26,'#efe6d6');cx.fillStyle='#efe6d6';cx.fillRect(-r*.6,top-r*.5,r*1.2,r*.6);cx.fillStyle='#8a4a4a';cx.fillRect(-r*.6,top-r*.05,r*1.2,r*.12)}else if(acc=='cleaver'){cx.save();cx.translate(-r*.1,top);cx.rotate(-.25);cx.fillStyle='#c9ced8';cx.fillRect(-r*.55,-r*.9,r*1.1,r*.85);cx.fillStyle='#3a2a2a';cx.fillRect(r*.5,-r*.8,r*.9,r*.2);cx.restore()}else if(acc=='arrows'){for(const a of[-.9,-1.5,-2.2]){cx.strokeStyle='#b98a4a';cx.lineWidth=2;cx.beginPath();cx.moveTo(Math.cos(a)*r*.8,cy+Math.sin(a)*r*.8);cx.lineTo(Math.cos(a)*r*1.9,cy+Math.sin(a)*r*1.9);cx.stroke();cx.strokeStyle='#fff';cx.beginPath();cx.moveTo(Math.cos(a)*r*1.9,cy+Math.sin(a)*r*1.9);cx.lineTo(Math.cos(a)*r*1.6+r*.15,cy+Math.sin(a)*r*1.6);cx.stroke()}}else if(acc=='beret'){E(-r*.1,top+r*.1,r*1.1,r*.32,'#3a3f45',-.15)}else if(acc=='brain'){E(0,top+r*.1,r*.7,r*.28,'#e38aa0');cx.strokeStyle='#b05a74';cx.lineWidth=1.5;cx.beginPath();cx.moveTo(-r*.5,top+r*.1);cx.quadraticCurveTo(-r*.2,top-r*.1,0,top+r*.1);cx.quadraticCurveTo(r*.2,top-r*.1,r*.5,top+r*.1);cx.stroke()}}
function mkRag(e){if(e.ty=='dog')return{ty:'dog',x:e.x,y:e.y,face:e.face,z:e.z,t:0,v:e.v};const d=ET[e.ty],u=T*d.s*1.15,f=e.face||1,bx=e.x*T+T/2,gr=e.y*T+T/2+T*.3,P=(x,y)=>({x:bx+x*u,y:gr+y*u,px:0,py:0});const R={hip:P(0,-.36),chest:P(f*.1,-.7),head:P(f*.15,-.92),hA:P(f*.38,-.62),hB:P(f*.3,-.5),fA:P(.08,0),fB:P(-.08,0)};const pts=Object.values(R);const C=[['hip','chest'],['chest','hA'],['chest','hB'],['hip','fA'],['hip','fB'],['fA','fB'],['chest','fA']].map(([a,b])=>[R[a],R[b],Math.hypot(R[a].x-R[b].x,R[a].y-R[b].y)]);const kick=Math.min(2,.5+(e.ld||10)/25);for(const p of pts){const vx=-f*u*(3+Math.random()*2)*kick,vy=-u*(6+Math.random()*3)*kick*(p.y<gr-u*.5?1.1:.8);p.px=p.x-vx*.008;p.py=p.y-vy*.008}R.head.py+=u*.5;R.head.px+=f*u*.35;return{ha:0,P:R,pts,C,gr,u,ty:e.ty,v:e.v,f,t:0,burnD:e.burn>0,x:e.x,y:e.y}}
function stepRag(d,dt){d.t+=dt;if(d.ty=='dog')return;d.ha+=(d.P.head.x-d.P.head.px)/(d.u*.19);if(d.t<.7&&Math.random()<.6)G.fx.push({x:d.P.chest.x,y:d.P.chest.y,vx:(Math.random()-.5)*50,vy:-60*Math.random(),l:.4,c:'#b01830'});const h=dt/2,g=T*30;for(let s=0;s<2;s++){for(const p of d.pts){const vx=(p.x-p.px)*.995,vy=(p.y-p.py)*.995;p.px=p.x;p.py=p.y;p.x+=vx;p.y+=vy+g*h*h}for(let i=0;i<6;i++){for(const[a,b,L]of d.C){const dx=b.x-a.x,dy=b.y-a.y,ds=Math.hypot(dx,dy)||1,df=(ds-L)/ds*.5;a.x+=dx*df;a.y+=dy*df;b.x-=dx*df;b.y-=dy*df}for(const p of d.pts)if(p.y>d.gr){const vy=p.y-p.py;p.y=d.gr;p.py=d.gr+vy*.35;p.px=p.x-(p.x-p.px)*.6}}}}
function drawRag(d){if(d.ty=='dog')return dogZ(d,1);const u=d.u,D=ET[d.ty],P=d.P,a=Math.min(1,Math.max(0,(3.2-d.t)/1.2));cx.save();cx.globalAlpha=a;cx.fillStyle='#0006';cx.beginPath();cx.ellipse((P.hip.x+P.chest.x)/2,d.gr,u*.3,u*.07,0,0,6.28);cx.fill();const L=(A,B,w,c)=>{cx.lineCap='round';cx.strokeStyle='#0c2b30';cx.lineWidth=w+2.4;cx.beginPath();cx.moveTo(A.x,A.y);cx.lineTo(B.x,B.y);cx.stroke();cx.strokeStyle=c;cx.lineWidth=w;cx.beginPath();cx.moveTo(A.x,A.y);cx.lineTo(B.x,B.y);cx.stroke();cx.strokeStyle='rgba(255,255,255,.18)';cx.lineWidth=w*.3;cx.beginPath();cx.moveTo(A.x,A.y-w*.2);cx.lineTo(B.x,B.y-w*.2);cx.stroke()};L(P.hip,P.fB,u*.1,'#2b2a38');L(P.hip,P.fA,u*.1,'#3a384a');L(P.hip,P.chest,u*({tank:.4,boss:.46,fat:.55,giant:.55,kid:.2}[d.ty]||.26),MAPN?['#2f5d8a','#8a2f3a','#3d6b4a','#6b4a2f','#5a3d7a'][((d.v||0)+d.ty.length)%5]:D.cloth);L(P.chest,P.hB,u*.08,'#3f8c90');L(P.chest,P.hA,u*.08,D.skin);for(const q of[P.hA,P.hB]){cx.fillStyle=D.skin;cx.beginPath();cx.arc(q.x,q.y,u*.05,0,6.28);cx.fill()}cx.fillStyle='#8a1626';cx.strokeStyle='#0c2b30';cx.lineWidth=1.2;cx.beginPath();cx.ellipse(P.chest.x+(P.chest.x-P.hip.x)*.25,P.chest.y+(P.chest.y-P.hip.y)*.25,u*.07,u*.05,0,0,6.28);cx.fill();cx.stroke();cx.save();cx.translate(P.head.x,P.head.y);cx.rotate(d.ha);cx.scale(d.f,1);headArt(d,u,D.skin,0,1);cx.restore();if(d.burnD&&d.t<2){for(let i=0;i<4;i++){const q=G.time*14+i*2;cx.fillStyle=i%2?'#ffd34d':'#ff7a2a';cx.beginPath();cx.ellipse(P.chest.x+Math.sin(q)*u*.15,P.chest.y-u*.1*i-Math.abs(Math.cos(q))*u*.08,u*.07,u*.12,0,0,6.28);cx.fill()}}cx.restore()}
function drawZ(){for(const d of G.decals){cx.globalAlpha=Math.min(.55,d.l/6);cx.fillStyle=d.c||'#5a1020';cx.beginPath();cx.ellipse(d.x*T+T/2,d.y*T+T/2+T*.25,T*d.r*1.4,T*d.r*.8,0,0,6.28);cx.fill()}cx.globalAlpha=1;const pp=1+Math.sin(G.time*3)*.12;cx.fillStyle='#66d98a55';cx.beginPath();cx.ellipse(WP[0][0]*T+T/2,WP[0][1]*T+T*.8,T*.45*pp,T*.15*pp,0,0,6.28);cx.fill();const L=[...G.dying.map(d=>[d,1]),...G.en.map(e=>[e,0])].sort((a,b)=>a[0].y-b[0].y);for(const o of L)o[1]?drawRag(o[0]):zom(o[0],0)}
function zom(e,dy){if(e.ty=='dog')return dogZ(e,0);const d=ET[e.ty],u=T*d.s*1.15,px=e.x*T+T/2,py=e.y*T+T/2+T*.3,f=e.face||1,ph=e.z,t=e.t||0,sn=Math.sin(ph),cs=Math.cos(ph),k=dy?0:1,sk=d.skin,cl=MAPN?['#2f5d8a','#8a2f3a','#3d6b4a','#6b4a2f','#5a3d7a'][((e.v||0)+e.ty.length)%5]:d.cloth,crawl=e.ty=='crawler';const rise=dy?1:Math.min(1,1-Math.max(0,e.rise)/.5);cx.save();cx.translate(px,py);cx.globalAlpha=dy?Math.min(1,Math.max(0,(1.1-t)*2)):1;cx.fillStyle='#0007';cx.beginPath();cx.ellipse(0,0,u*.28,u*.08,0,0,6.28);cx.fill();if(rise<1){cx.beginPath();cx.rect(-u,-u*1.5,u*2,u*1.5);cx.clip();cx.translate(0,(1-rise)*u*.9)}if(dy)cx.rotate(-f*Math.min(1,t*2.6)*1.5);else if(e.hit>0)cx.translate(-f*u*.05,0);if(e.bt>0)cx.translate(f*Math.abs(Math.sin(G.time*11))*u*.14,0);cx.scale(f*({fat:1.1}[e.ty]||1),{tall:1.3,short:.85,fat:.92}[e.ty]||1);const lean={walk:.28,fast:.55,tank:.12,boss:.16,crawler:1.2,fat:.1,short:.25,tall:.2,kid:.35,giant:.1}[e.ty];cx.translate(0,dy?0:-Math.abs(cs)*u*.04);const line=(x1,y1,x2,y2,w,c)=>{cx.lineCap='round';cx.strokeStyle='#0c2b30';cx.lineWidth=w+2.4;cx.beginPath();cx.moveTo(x1,y1);cx.lineTo(x2,y2);cx.stroke();cx.strokeStyle=c;cx.lineWidth=w;cx.beginPath();cx.moveTo(x1,y1);cx.lineTo(x2,y2);cx.stroke();cx.strokeStyle='rgba(255,255,255,.18)';cx.lineWidth=w*.3;cx.beginPath();cx.moveTo(x1,y1-w*.2);cx.lineTo(x2,y2-w*.2);cx.stroke()};if(!crawl){const hy=-u*.36;for(let i=0;i<2;i++){const sg=i?-1:1,sw=(e.ty=='walk'&&i)?.45:1,fx=sn*sg*u*.2*sw*k,fy=-Math.max(0,cs*sg)*u*.07*k;line(0,hy,fx,fy,u*.1,i?'#2b2a38':'#3a384a');cx.fillStyle=e.ty=='fast'?'#f3f3f3':'#2a2a35';cx.strokeStyle='#0c2b30';cx.lineWidth=1.5;cx.beginPath();cx.ellipse(fx+u*.04,fy,u*.09,u*.05,0,0,6.28);cx.fill();cx.stroke();cx.fillStyle='#d33';cx.fillRect(fx+u*.01,fy-u*.01,u*.06,u*.02)}}else line(-u*.28,-u*.1,-u*.5,-u*.02,u*.08,sk);cx.save();cx.translate(crawl?-u*.1:0,crawl?-u*.12:-u*.36);cx.rotate(lean+(dy?0:sn*.04));const tw={tank:.23,boss:.26,fat:.34,giant:.3,short:.18,tall:.11,kid:.12}[e.ty]||.14;cx.fillStyle=cl;cx.beginPath();cx.ellipse(0,-u*.2,u*tw,u*.24,0,0,6.28);cx.fill();cx.strokeStyle='#0c2b30';cx.lineWidth=1.8;cx.stroke();torsoArt(e,u,tw,cl,sk);if(MAPN)winterBody(e,u,tw,cl);cx.fillStyle='#0004';cx.fillRect(-u*tw*.7,-u*.2,u*tw*.5,u*.04);cx.fillStyle=sk;cx.beginPath();cx.ellipse(u*tw*.4,-u*.16,u*.05,u*.07,0,0,6.28);cx.fill();if(e.ty=='tank'||e.ty=='boss'){cx.fillStyle='#5b6275';cx.fillRect(-u*.1,-u*.46,u*.26,u*.08)}const ab={walk:-.15,fast:2.4,tank:1.25,boss:1,crawler:-.4,fat:.9,short:-.1,tall:-.2,kid:2.1,giant:.9}[e.ty],aa={walk:.18,fast:.55,tank:.3,boss:.25,crawler:.7,fat:.25,short:.2,tall:.2,kid:.6,giant:.25}[e.ty];for(let i=0;i<2;i++){const a=ab+Math.sin(ph+i*Math.PI)*aa*k,L=u*.3*(e.ty=='boss'?1.2:1),sy=-u*.38,ex=Math.cos(a)*L,ey=sy+Math.sin(a)*L;line(0,sy,ex,ey,u*.08*(tw>.2?1.4:1),i?sk:'#3f8c90');cx.fillStyle=sk;cx.strokeStyle='#0c2b30';cx.lineWidth=1.5;cx.beginPath();cx.arc(ex,ey,u*.055,0,6.28);cx.fill();cx.stroke();cx.lineWidth=2;cx.lineCap='round';for(let q=-1;q<=1;q++){cx.beginPath();cx.moveTo(ex,ey);cx.lineTo(ex+Math.cos(a+q*.5)*u*.1,ey+Math.sin(a+q*.5)*u*.1);cx.stroke()}}cx.translate(u*.02,-u*.5);cx.rotate(-lean*.6+(dy?.3:Math.sin(ph*.5)*.18));cx.fillStyle=sk;cx.beginPath();cx.arc(0,0,u*(e.ty=='boss'?.15:.12),0,6.28);cx.fill();cx.fillStyle='#1a1018';cx.beginPath();cx.ellipse(u*.06,u*.06,u*.04,u*(.02+.02*Math.abs(Math.sin(ph*.7))),0,0,6.28);cx.fill();cx.fillStyle=dy?'#555':(e.ty=='boss'?'#ffb020':'#ff3b3b');cx.beginPath();cx.arc(u*.06,-u*.02,u*.025,0,6.28);cx.fill();if(e.ty=='boss'){cx.fillStyle='#d9d2c0';for(const s of[-1,1]){cx.beginPath();cx.moveTo(s*u*.07,-u*.1);cx.lineTo(s*u*.14,-u*.28);cx.lineTo(s*u*.02,-u*.12);cx.fill()}}headArt(e,u,sk,ph,dy);cx.restore();if(e.slow>0&&!dy){cx.fillStyle='#8fe0ff55';cx.beginPath();cx.ellipse(0,-u*.4,u*.3,u*.5,0,0,6.28);cx.fill()}if(e.hit>0&&!dy){cx.fillStyle='#ffffff77';cx.beginPath();cx.ellipse(0,-u*.4,u*.28,u*.46,0,0,6.28);cx.fill()}if((e.burn>0&&!dy)||(dy&&e.burnD)){for(let i=0;i<5;i++){const q=G.time*14+i*2+e.z;cx.fillStyle=i%2?'#ffd34d':'#ff7a2a';cx.beginPath();cx.ellipse(Math.sin(q)*u*.2,-u*(.2+.1*i)-Math.abs(Math.cos(q))*u*.1,u*.07,u*.12,0,0,6.28);cx.fill()}}cx.restore();if(S.hp&&!dy){const w=u*.6,x=px-w/2,y=py-u*({tall:1.4,giant:1.1}[e.ty]||1.0);cx.fillStyle='#000a';cx.fillRect(x,y,w,4);cx.fillStyle=e.hp/e.max>.4?'#66d98a':'#ff5d6c';cx.fillRect(x,y,w*Math.max(0,e.hp/e.max),4)}}
let last=performance.now();
function loop(n){const dt=Math.min(.05,(n-last)/1000);last=n;if(!paused&&!G.over&&$('mp').style.display!='none'&&false){}if(!paused&&!G.over&&$('mp').style.display!='flex'&&!$('ov').style.display.includes('flex')){for(let i=0;i<S.speed;i++)update(dt)}draw();requestAnimationFrame(loop)}
$('go').onclick=()=>{startWave();snd(500,.1)};
$('pause').onclick=()=>{paused=!paused;$('pause').textContent=paused?'â–ļ':'⏸'};
$('spd').onclick=()=>{S.speed=S.speed%3+1;sync()};
$('again').onclick=$('restart').onclick=()=>{newGame();$('ov').style.display='none'};
$('gear').onclick=()=>$('ov').style.display='flex';
$('close').onclick=()=>$('ov').style.display='none';
$('ov').onclick=e=>{if(e.target.id=='ov')$('ov').style.display='none'};
document.querySelectorAll('#panel [data-k]').forEach(el=>{
 if(el.classList.contains('seg'))el.onclick=e=>{const v=e.target.dataset.v;if(!v)return;const k=el.dataset.k;S[k]=k=='speed'?+v:v;sync()};
 else el.onclick=()=>{S[el.dataset.k]=!S[el.dataset.k];sync()}});
function sync(){$('spd').textContent=S.speed+'x';document.querySelectorAll('#panel [data-k]').forEach(el=>{const k=el.dataset.k;
 if(el.classList.contains('seg'))el.querySelectorAll('button').forEach(b=>b.classList.toggle('on',String(S[k])==b.dataset.v));else el.classList.toggle('on',S[k])});
 try{localStorage.setItem('gg',JSON.stringify(S))}catch(e){}}
try{Object.assign(S,JSON.parse(localStorage.getItem('gg')||'{}'))}catch(e){}
document.querySelectorAll('.card').forEach(b=>{drawPrev(b.querySelector('canvas'),+b.dataset.m);b.onclick=()=>{setMap(+b.dataset.m);newGame();$('mp').style.display='none'}});$('rep').onclick=()=>{if(!sel)return;const c=repCost(sel);if(sel.mx-sel.hp<=0||G.gold<c)return;G.gold-=c;sel.hp=sel.mx;snd(520,.1);info();ui()};$('chmap').onclick=()=>{$('ov').style.display='none';$('mp').style.display='flex'};$('rhs').onclick=()=>{HS=0;try{localStorage.removeItem('ggHS')}catch(e){}ui()};size();newGame();sync();requestAnimationFrame(loop);
</script></body></html>

79,679 chars ¡ codepastes.com