Worldline
by GlitchKnight20262 lines31.4 KB
// ๊ตญ๊ฐ ์ธ๊ตยท์ ์ ์๋ฎฌ๋ ์ด์
โ GDevelop "JavaScript ์ฝ๋ ์คํ" ์ก์
์ฉ (๋จ์ผ ์คํฌ๋ฆฝํธ)
// ์ฌ์ฉ๋ฒ: ์ด๋ฒคํธ ์ํธ โ ์กฐ๊ฑด "์ฌ ์์ ์" โ ์ก์
"Execute a JavaScript code" ์ ์ด ํ์ผ ์ ์ฒด๋ฅผ ๋ถ์ฌ๋ฃ๊ธฐ
(function(){
if(window.NS)return;
const rnd=Math.random,n=x=>Math.round(x),cl=(x,a,b)=>Math.max(a,Math.min(b,x));
const RN=['๐พ๋ฐ','โ๏ธ์ฒ ','๐์์ฐ','๐ข๏ธ์์ ','๐ชต๋ชฉ์ฌ','๐๊ณผ์ผ'],RP=[4,8,5,12,3,6],RC=['#e8c547','#c5ced8','#5ad0e0','#222','#7a4a24','#ff5d6c'];
const NM=['์๋ฅด์นด','๋ฒจ๋ก','์นด์','๋๋ฅธ','์์คํ','ํ ๋ผ','๊ทธ๋ ์ด','ํ๋ก'],CL=['#e5484d','#3e8bff','#d98e1c','#a96bff','#2fbf71','#e0649c','#27a3a3','#9aab2a'];
const TY=['๊ณต๊ฒฉ์ ','ํํ์ ','๋ฌด์ญ์ค์ฌ','์์์ค์ฌ','๊ตฐ์ฌ์ค์ฌ','์ธ๊ต์ค์ฌ','๊ณ ๋ฆฝ์ฃผ์'];
// [์ ์, ๊ตฐ๋น, ๋๋งน, ์ ๋ฌผ, ๋ฌด์ญํ์ , ํ๋งค]
const PR=[[.07,.4,.03,0,.02,.05],[0,.1,.05,.06,.04,.05],[.005,.2,.04,.04,.12,.15],[.01,.2,.03,.02,.06,.3],[.05,.6,.03,0,.02,.05],[.005,.2,.09,.12,.06,.08],[.01,.2,0,0,0,.02]];
const MK={trade:'๊ต์ญ',help:'์์ฒญ ์น์ธ',refuse:'์์ฒญ ๊ฑฐ์ ',gift:'์ ๋ฌผ',firststrike:'์ ์ ๊ณต๊ฒฉ',brk:'์กฐ์ฝ ์๋ฐ',aid:'์ ํ ์ง์',nuke:'ํต ์ฌ์ฉ',pact:'๋ฌด์ญํ์ '};
const GW=40,GH=26,NC=8,CS=11,SK='nationsim-v1';
let own,reg,RG,coast,C,rel,mem,wars,pend,logs,chat,hist,pacts,turn,aid,H,me,tab='e',spd=0,acc=0,mute=false,showChat=false,cen,fx=[],frame=0,sp=[];
const sel={r:0,q:25,d:150,g:-1};
const wf=(a,b)=>wars.find(w=>(w.a==a&&w.b==b)||(w.a==b&&w.b==a));
const L=(t,m)=>{logs.unshift(`<b>[${t}]</b> T${turn} ${m}`);if(logs.length>80)logs.pop()};
const CH=m=>{chat.unshift(`T${turn} ${m}`);if(chat.length>80)chat.pop()};
const rem=(a,b,k,v)=>{mem[a][b].push({T:turn,k,v});if(mem[a][b].length>14)mem[a][b].shift();rel[a][b]=cl(rel[a][b]+v,-100,100)};
// ---------- ์๋ฆฌ ----------
let AC;function snd(k){if(mute)return;try{AC=AC||new(window.AudioContext||window.webkitAudioContext)();
const f={ok:[660,880],no:[300,200],war:[180,120,90],nuke:[60,40,30,25],click:[500],turn:[440,550]}[k];
f.forEach((fr,i)=>{const o=AC.createOscillator(),g=AC.createGain();o.type=(k=='nuke'||k=='war')?'sawtooth':'square';o.frequency.value=fr;g.gain.value=.05;
o.connect(g);g.connect(AC.destination);const t=AC.currentTime+i*.09;o.start(t);g.gain.exponentialRampToValueAtTime(.001,t+.14);o.stop(t+.15)})}catch(e){}}
// ---------- UI ๋ผ๋ ----------
const root=document.createElement('div');root.id='ns';
root.innerHTML=`<style>
#ns{position:fixed;inset:0;z-index:99999;background:#0b1a2b;color:#e8f0fa;font:13px system-ui,sans-serif;display:flex;flex-direction:column;padding-top:env(safe-area-inset-top,0px);padding-bottom:env(safe-area-inset-bottom,0px)}
#ns *{box-sizing:border-box}#ns canvas{width:100%;display:block;flex:none;image-rendering:pixelated}
#ns button{border:1px solid #2a4160;border-radius:7px;background:#22395a;color:#e8f0fa;font:inherit;padding:5px 8px;margin:2px 2px 0 0}
#ns button.on{background:#3b82f6}#nh{padding:6px 8px;background:#14263d;font-weight:700}#ni{padding:3px 8px;font-size:12px;color:#9ab;min-height:20px}
#np .cd{margin:3px 8px;padding:6px;background:#3a2a14;border:1px solid #c88a2b;border-radius:8px}
#nt{display:flex;background:#14263d}#nt button{flex:1;border-radius:0;margin:0;padding:8px 0;border:0;background:none}#nt button.on{background:#2b4a78}
#nb{flex:1;min-height:0;overflow:auto;padding:6px 10px}#ns .r{padding:6px 0;border-bottom:1px solid #2a4160}
#ns select,#ns input{background:#0e1d30;color:#e8f0fa;border:1px solid #2a4160;border-radius:6px;padding:4px;font:inherit;width:auto}#ns input{width:70px}
#nx{background:#3b82f6!important;padding:12px!important;border-radius:0!important;margin:0!important;font-size:15px;font-weight:700}
</style><div id=nh></div><canvas id=nc width=${GW*CS} height=${GH*CS}></canvas><div id=ni>์ง๋๋ฅผ ํญํ๋ฉด ์ง์ญ ์ ๋ณด๊ฐ ๋ณด์ฌ์</div><div id=np></div>
<div id=nt></div><div id=nb></div><button id=nx onclick="NS.act.nx()">๋ค์ ํด โถ</button>`;
document.body.appendChild(root);
const $=i=>root.querySelector('#'+i),cv=$('nc'),ctx=cv.getContext('2d');
// ---------- ์ธ๊ณ ์์ฑ ----------
function mkCoast(){coast=own.map((o,i)=>{if(o<0)return false;const x=i%GW,y=i/GW|0;return(x>0&&own[i-1]<0)||(x<GW-1&&own[i+1]<0)||(y>0&&own[i-GW]<0)||(y<GH-1&&own[i+GW]<0)})}
function gen(){const sd=[];for(let i=0;i<NC;i++){const cx=(i%4)*10+5,cy=(i>>2)*13+6.5;[[-3,-3],[3,-2],[0,4]].forEach(o=>sd.push({x:cx+o[0]+rnd()*2-1,y:cy+o[1]+rnd()*2-1,o:i}))}
const a=rnd()*6,b=rnd()*6;own=[];reg=[];
for(let y=0;y<GH;y++)for(let x=0;x<GW;x++){
const sea=x<1||y<1||x>=GW-1||y>=GH-1||(Math.abs(y-12.5+Math.sin(x*.45+a)*1.4)<.8&&Math.sin(x*.9+b)>-.3)||Math.sin(x*.5+a)*Math.sin(y*.6+b)>.85;
if(sea){own.push(-1);reg.push(-1);continue}
let bi=0,bd=1e9;sd.forEach((s,i)=>{const d=Math.hypot(s.x-x,s.y-y);if(d<bd){bd=d;bi=i}});own.push(sd[bi].o);reg.push(bi)}
RG=sd.map((s,i)=>({id:i,o:s.o,res:0,dmg:0,n:NM[s.o]+' '+['๋ถ','๋','๋จ'][i%3]+'๋ถ'}));mkCoast()}
function newGame(){gen();
C=NM.map((nm,i)=>({i,n:nm,c:CL[i],st:Array(6).fill(40),D:i?800:1000,tp:50,mil:60,df:0,sh:2,bm:1,ms:2,al:-1,ty:i?rnd()*7|0:-1,pop:0,blk:0,ind:0,si:0,di:0,wc:0}));
C.forEach(c=>{const pl=[0,1,2,3,4,5].sort(()=>rnd()-.5);for(let j=0;j<3;j++)RG[c.i*3+j].res=pl[j]});
rel=C.map(()=>C.map(()=>n(rnd()*30-8)));mem=C.map(()=>C.map(()=>[]));wars=[];pend=[];logs=[];chat=[];hist=[];pacts=[];turn=1;aid=0;
H=C.map((c,i)=>i==0);me=0;stats();C.forEach(c=>c.pop=c.k*1000);fx=[];
L('์์คํ
','๋น์ ์ ์๋ฅด์นด๋ฅผ ์ด๋๋๋ค. ์ง์ญ๋ง๋ค ํน์ฐํ์ด ๋ฌ๋ผ ์์์ด ๋ถ์กฑํด์ โ ์ด์๊ณผ ๊ต์ญํ์ธ์.');render()}
function stats(){C.forEach(c=>{c.k=0;c.p=[0,0,0,0,0,0]});const sx=Array(NC).fill(0),sy=Array(NC).fill(0);
own.forEach((o,i)=>{if(o<0)return;const c=C[o];c.k++;sx[o]+=i%GW;sy[o]+=i/GW|0;if(!RG[reg[i]].dmg)c.p[RG[reg[i]].res]++});
cen=C.map(c=>c.k?[(sx[c.i]/c.k+.5)*CS,(sy[c.i]/c.k+.5)*CS]:[0,0]);
sp=C.map(c=>{const l=[];own.forEach((o,i)=>{if(o==c.i&&coast[i])l.push(i)});return l.length?[l[0],l[l.length>>1],l[l.length-1]]:[]})}
function cand(a,b,am){const r=[];for(let i=0;i<own.length;i++){if(own[i]!=b)continue;if(am){if(coast[i])r.push(i);continue}
const x=i%GW,y=i/GW|0;if((x>0&&own[i-1]==a)||(x<GW-1&&own[i+1]==a)||(y>0&&own[i-GW]==a)||(y<GH-1&&own[i+GW]==a))r.push(i)}return r}
function take(a,b,am,k){let g=0;for(let j=0;j<k;j++){const c=cand(a,b,am);if(!c.length)break;own[c[rnd()*c.length|0]]=a;g++}return g}
function adj(a){const s=new Set();for(let i=0;i<own.length;i++){if(own[i]!=a)continue;const x=i%GW,y=i/GW|0;
[x>0?i-1:-1,x<GW-1?i+1:-1,y>0?i-GW:-1,y<GH-1?i+GW:-1].forEach(j=>{if(j>=0&&own[j]>=0&&own[j]!=a)s.add(own[j])})}return[...s]}
function regsOf(e){const m={};own.forEach((o,i)=>{if(o==e)m[reg[i]]=(m[reg[i]]||0)+1});return Object.keys(m).map(Number).sort((a,b)=>m[b]-m[a])}
const rpos=g=>{const i=reg.findIndex((r,j)=>r==g&&own[j]==RG[g].o);const k=i<0?reg.indexOf(g):i;return[(k%GW+.5)*CS,((k/GW|0)+.5)*CS]};
const fxa=(k,p,q)=>fx.push({k,x0:p[0],y0:p[1],x1:q[0],y1:q[1],t:0,d:k=='nuke'?30:18});
// ---------- ๊ฒฝ์ ยท์ธ๊ต ----------
const acc_=(p,f,ratio)=>C[p].blk>0||C[f].blk>0?0:cl(.3+rel[p][f]/150+C[p].tp/250+(ratio-1)*.8-(C[p].ty==6?.25:0),.05,.95);
function trade(b,s,r,q,d){C[s].st[r]-=q;C[b].st[r]+=q;C[b].D-=d;C[s].D+=d;rem(b,s,'trade',3);rem(s,b,'trade',3);C[b].tp+=.5;C[s].tp+=.5}
function ally(a,b){const A=C[a],B=C[b];if(A.al>=0&&B.al>=0)return 0;if(A.al<0&&B.al<0)A.al=B.al=aid++;else if(A.al<0)A.al=B.al;else B.al=A.al;
L('์ฐํฉ',`${A.n} ยท ${B.n} ์ฐํฉ ๊ฒฐ์ฑ/๊ฐ์
`);return 1}
function declare(a,b,force,skip){if(wf(a,b)||!C[a].k||!C[b].k)return;const A=C[a];
if(!force&&!skip){const ids=A.al>=0?C.filter(v=>v.al==A.al&&v.i!=a&&v.i!=b&&v.k).map(v=>v.i):[...new Set([...adj(a),...adj(b)])].filter(v=>v!=a&&v!=b&&C[v].k);
const vo=v=>rel[v][b]<rel[v][a]+8;
if(A.al>=0&&A.al==C[me].al&&H[me]&&a!=me&&ids.includes(me)){pend.push({t:'wv',to:me,a,b,ids,y0:ids.filter(v=>v!=me&&vo(v)).length});return}
const yes=ids.filter(vo).length,ok=!ids.length||yes*2>=ids.length;
if(a==me||b==me||H[a]||H[b])L('์น์ธ',`${A.al>=0?'์ฐํฉ':'์ฃผ๋ณ๊ตญ'} ํฌํ ${yes}:${ids.length-yes} โ ${ok?'์น์ธ':'๋ถ๊ฒฐ'}`);
if(!ok){if(H[a]||!(A.ty==0&&rnd()<.3))return;force=true}}
pacts=pacts.filter(p=>{if((p.a==a&&p.b==b)||(p.a==b&&p.b==a)){A.tp=Math.max(0,A.tp-8);rem(b,a,'brk',-30);L('์กฐ์ฝ',`${A.n}์ด(๊ฐ) ๋ฌด์ญํ์ ์ ํ๊ธฐ(์ฝ์ ์๋ฐ)`);return false}return true});
const mk=(x,y)=>({a:x,b:y,agg:a,s:0,pu:{},k:[C[x].k,C[y].k],pre:!!force,T:turn});wars.push(mk(a,b));
if(force){A.tp=Math.max(0,A.tp-25);C.forEach(v=>{if(v.i!=a)rel[v.i][a]-=15});rem(b,a,'firststrike',-30);
const t=`${A.n} โ ${C[b].n} ์ ์ ๊ณต๊ฒฉ`;hist.unshift(`T${turn} ${t}`);L('๊ตญ์ ',`๐จ <b>${t}</b>! (๋ฐฉ์ด๊ตญ์ ์น์ธ ์์ด ์ฆ์ ๋ฐฉ์ด ๊ฐ๋ฅ)`)}
else{hist.unshift(`T${turn} ${A.n} โ ${C[b].n} ์น์ธ ์ ์`);L('๊ตญ์ ',`${A.n}์ด(๊ฐ) ์น์ธ์ ๋ฐ์ ${C[b].n}๊ณผ(์) ๊ฐ์ `)}
snd('war');
C.forEach(v=>{if(!v.k||v.i==a||v.i==b||v.al<0)return;
if(v.al==C[b].al&&!wf(a,v.i)&&(H[v.i]||rel[v.i][a]<25)){wars.push(mk(a,v.i));L('์ฐํฉ',`${v.n}์ด(๊ฐ) ์ฐํฉ๊ตญ ${C[b].n}์(๋ฅผ) ์ํด ์ฐธ์ `)}
else if(!force&&v.al==A.al&&v.al!=C[b].al&&!wf(v.i,b)&&rel[v.i][b]<10){wars.push(mk(v.i,b));L('์ฐํฉ',`${v.n}์ด(๊ฐ) ์ฐํฉ๊ตญ ${A.n}์(๋ฅผ) ์ง์ํด ์ฐธ์ `)}})}
function endWar(w,win){wars=wars.filter(x=>x!=w);
if(win<0){L('์ ์',`${C[w.a].n}-${C[w.b].n} ์ ์์ด ๋ฌด์น๋ถ๋ก ์ข
๊ฒฐ`);return}
const lo=win==w.a?w.b:w.a,W=C[win],Lo=C[lo],d=n(Lo.D*.4);Lo.D-=d;W.D+=d;
for(let r=0;r<6;r++){const q=Math.floor(Lo.st[r]*.4);Lo.st[r]-=q;W.st[r]+=q}
Lo.mil*=.8;Lo.sh=Math.floor(Lo.sh*.7);hist.unshift(`T${turn} ${W.n} ์น / ${Lo.n} ํจ`);
L('์ ์',`${W.n} ์น๋ฆฌ โ ${Lo.n}์๊ฒ์ D ${d}์ ์์ 40% ํ๋`);snd('ok');
if(lo==w.agg){Lo.tp=Math.max(0,Lo.tp-20);L('๊ตญ์ ',`์ ์ ๊ณต๊ฒฉ๊ตญ ${Lo.n}์ ์ธ๊ต ์จ๋๊ฐ ํฌ๊ฒ ํ๋ฝ`)}
else{L('๊ตญ์ ',`${Lo.n}์(๋) ์ ์ ๊ณต๊ฒฉ ํผํด๊ตญ์ผ๋ก ์ธ๊ต ํ๋ํฐ๊ฐ ์์ต๋๋ค.`);
C.forEach(v=>{if(v.i==win||v.i==lo||!v.k)return;const al=v.al>=0&&v.al==Lo.al;
if(al||(v.tp>55&&rel[v.i][lo]>=0)){if(H[v.i]){if(al)pend.push({t:'aid',to:v.i,lo});return}
const g=al?200:100;if(v.D<g)return;v.D-=g;Lo.D+=g;v.tp+=2;rem(lo,v.i,'aid',10);L(al?'์ฐํฉ':'๊ตญ์ ',`${v.n}์ด(๊ฐ) ${Lo.n}์ D ${g} ์ง์`)}})}}
// ---------- ๊ตฐ์ฌ ----------
const COST={a:150,n:120,k:100,v:300,b:200,B:200,m:250,h:1500};
function strike(c,e,t){const w=wf(c.i,e.i);if(!w)return -1;
if(t=='a'&&!cand(c.i,e.i,0).length)return -1;if(t=='v'&&(c.sh<3||!cand(c.i,e.i,1).length))return -1;
if((t=='n'&&c.sh<1)||(t=='k'&&c.sh<2)||((t=='b'||t=='B')&&c.bm<1)||(t=='m'&&c.ms<1))return -1;
if(c.D<COST[t])return 0;c.D-=COST[t];const sg=w.a==c.i?1:-1,V=c.i==me||e.i==me,P0=cen[c.i],P1=cen[e.i];let m;
if(t=='a'){const ap=c.mil*(.6+rnd()*.8),dp=e.mil*(1+e.df*.15)*(.6+rnd()*.8);
if(ap>dp){const g=take(c.i,e.i,0,1+(rnd()*3|0));c.mil*=.93;e.mil*=.95;w.s+=sg*g;m=`${c.n}์ ๋๊ฒฉ ์ฑ๊ณต: ${e.n}์ ${g}๊ตฌ์ญ ์ ๋ น`;fxa('boom',P0,P1)}else{c.mil*=.88;m=`${c.n}์ ๋๊ฒฉ์ด ${e.n}์ ๋ฐฉ์ด์ ๋งํ`}}
else if(t=='n'){const ap=c.sh*(.6+rnd()*.8),dp=e.sh*(.6+rnd()*.8);
if(ap>dp){e.sh=Math.floor(e.sh*.6);w.s+=sg;m=`${c.n} ํจ๋๊ฐ ${e.n} ํจ๋๋ฅผ ๊ฒฉํ (ํด์ ํต์ )`}else{c.sh=Math.floor(c.sh*.7);m=`${c.n} ํจ๋๊ฐ ${e.n} ํจ๋์ ํจํด`}fxa('ship',P0,P1)}
else if(t=='k'){e.blk=4;m=`${c.n}์ด(๊ฐ) ${e.n}์(๋ฅผ) ํด์ ๋ด์ โ ๊ต์ญยท์ธ๊ต ์์
๊ฐ์`;fxa('ship',P0,P1)}
else if(t=='v'){const ap=c.mil*.8+c.sh*6,dp=e.mil*(1+e.df*.15)*(.6+rnd()*.8)*(e.sh>c.sh?1.3:1);
if(ap>dp){const g=take(c.i,e.i,1,1+(rnd()*2|0));c.sh--;w.s+=sg*g;m=`${c.n}์ ์๋ฅ์์ ์ฑ๊ณต: ${e.n}์ ${g}๊ตฌ์ญ ์ ๋ น`;fxa('ship',P0,P1)}else{c.sh=Math.max(0,c.sh-2);m=`${c.n}์ ์๋ฅ์์ ์ด ${e.n}์ ๊ฒฉํด๋จ`}}
else if(t=='b'){e.mil*=.82-rnd()*.05;m=`${c.n} ํญ๊ฒฉ๊ธฐ๊ฐ ${e.n}์ ๊ตฐ์ฌ์์ค ํญ๊ฒฉ`;w.s+=sg;fxa('plane',P0,P1)}
else if(t=='B'){e.ind=3;e.D=Math.max(0,e.D-80);m=`${c.n} ํญ๊ฒฉ๊ธฐ๊ฐ ${e.n}์ ์ฐ์
์์ค ํญ๊ฒฉ โ ์์
๊ฐ์`;fxa('plane',P0,P1)}
else if(t=='m'){c.ms--;const rs=regsOf(e.i);let g=sel.g;if(c.i!=me||!rs.includes(g))g=rs[c.i==me?0:rnd()*rs.length|0];
if(g==null){c.ms++;c.D+=COST[t];return -1}RG[g].dmg=3;e.mil*=.93;w.s+=sg;m=`${c.n} ๋ฏธ์ฌ์ผ์ด ${RG[g].n} ์ง์ญ ํ๊ฒฉ โ 3ํด๊ฐ ์์ฐ ์ ์ง`;fxa('miss',P0,rpos(g))}
else{e.mil*=.6;const g=take(c.i,e.i,0,6)||take(c.i,e.i,1,6);w.s+=sg*g;C.forEach(v=>{if(v.i!=c.i)rem(v.i,c.i,'nuke',-40)});c.tp=Math.max(0,c.tp-30);
m=`โข๏ธ ${c.n}์ด(๊ฐ) ${e.n}์ ์์ํญํ ์ฌ์ฉ! ๊ตญ์ ์ฌํ๊ฐ ๊ฒฝ์
ํฉ๋๋ค`;fxa('nuke',P0,P1);snd('nuke')}
if(V||t=='h'){L('์ ์',m);if(V&&t!='h')snd('war')}else CH(m);stats();
const k0=w.a==e.i?w.k[0]:w.k[1];if(wars.includes(w)&&(e.k<k0*.6||!e.k))endWar(w,c.i);return 1}
function aiStrike(c,e){const o=[],land=cand(c.i,e.i,0).length>0;
if(land)o.push('a','a');if(c.sh>=1)o.push('n');if(c.sh>=3&&!land)o.push('v','v');if(c.sh>=2&&rnd()<.3)o.push('k');if(c.bm>0)o.push('b','B');if(c.ms>0)o.push('m');
if(c.ty==0&&c.mil>e.mil*3&&c.D>3000&&rnd()<.1)o.push('h');
if(!o.length||c.D<150){if(c.D>100){c.D-=100;c.df=Math.min(5,c.df+1)}return}
const t=o[rnd()*o.length|0];strike(c,e,t)}
// ---------- AI ----------
function aiTrade(c,pr){let r=0;c.st.forEach((s,i)=>{if(s<c.st[r])r=i});
if(c.st[r]<(c.ty==6?12:25)){const q=25,cd=C.filter(p=>p.k&&p.i!=c.i&&p.st[r]>q+20&&!wf(c.i,p.i)).sort((a,b)=>rel[c.i][b.i]-rel[c.i][a.i])[0];
if(cd){const d=n(q*RP[r]*(.8+rnd()*.5));
if(H[cd.i]){if(pend.length<6)pend.push({t:'req',to:cd.i,f:c.i,r,q,d})}
else{const ok=rnd()<acc_(cd.i,c.i,d/(q*RP[r]));CH(`${c.n}: ${RN[r]} ${q}๊ฐ ํ์ โ ${cd.n}: ${ok?'๊ฑฐ๋ ์น์ธ':'์ฌ๊ณ ๊ฐ ์ถฉ๋ถ์น ์๋ค (๊ฑฐ์ )'}`);
if(ok)trade(c.i,cd.i,r,q,d);else rem(cd.i,c.i,'refuse',-1)}}}
else if(rnd()<pr[5]){let r2=0;c.st.forEach((s,i)=>{if(s>c.st[r2])r2=i});
if(c.st[r2]>70){const cd=C.filter(p=>p.k&&p.i!=c.i&&p.st[r2]<30&&p.D>150&&!wf(c.i,p.i))[0];
if(cd){const q=25,d=n(q*RP[r2]*1.1);if(H[cd.i]){if(pend.length<6)pend.push({t:'offer',to:cd.i,f:c.i,r:r2,q,d})}
else if(rnd()<acc_(c.i,cd.i,1)){trade(cd.i,c.i,r2,q,d);CH(`${c.n}: ${RN[r2]} ${q}๊ฐ ํ๋งค โ ${cd.n}: ๊ตฌ๋งค`)}}}}}
function ai(c){if(!c.k||H[c.i])return;const pr=PR[c.ty<0?1:c.ty],w=wars.find(x=>x.a==c.i||x.b==c.i);
if(w){const e=C[w.a==c.i?w.b:w.a],sc=(w.a==c.i?1:-1)*w.s;aiStrike(c,e);
if(wars.includes(w)&&sc<-2&&rnd()<.35){if(H[e.i]){if(pend.length<6)pend.push({t:'peace',to:e.i,w})}else endWar(w,w.s>0?w.a:w.s<0?w.b:-1)}return}
if(c.D>400&&rnd()<pr[1]){const q=rnd()*4|0;if(q==0){c.D-=200;c.mil+=12}else if(q==1){c.D-=300;c.sh+=2}else if(q==2){c.D-=250;c.bm+=2}else{c.D-=300;c.ms+=3}}
aiTrade(c,pr);
if(c.D<80&&c.ty!=6&&rnd()<.2){const f=C.find(v=>H[v.i]&&v.k&&rel[v.i][c.i]>0);if(f&&pend.length<6)pend.push({t:'dreq',to:f.i,f:c.i})}
if(rnd()<pr[4]){const p=C.find(v=>v.k&&v.i!=c.i&&rel[c.i][v.i]>15&&!pacts.some(q=>(q.a==c.i&&q.b==v.i)||(q.a==v.i&&q.b==c.i))&&!wf(c.i,v.i));
if(p){if(H[p.i]){if(pend.length<6)pend.push({t:'pact',to:p.i,f:c.i})}else{pacts.push({a:c.i,b:p.i,exp:turn+10});CH(`${c.n}-${p.n} ๋ฌด์ญํ์ ์ฒด๊ฒฐ`)}}}
if(rnd()<pr[3]){const p=C.filter(v=>v.k&&v.i!=c.i&&rel[c.i][v.i]>0&&v.D<500).sort((a,b)=>a.D-b.D)[0];
if(p&&c.D>400){c.D-=100;p.D+=100;rem(p.i,c.i,'gift',8);if(H[p.i])L('๊ตญ์ ',`${c.n}์ด(๊ฐ) ๋น์ ์๊ฒ D 100์ ์ง์ํ์ต๋๋ค`);else CH(`${c.n} โ ${p.n} ์ง์๊ธ D 100`)}}
if(rnd()<pr[0]&&turn>3){const gr=v=>mem[c.i][v].filter(m=>m.k=='firststrike').length;
const ts=C.filter(v=>v.k&&v.i!=c.i&&!wf(c.i,v.i)&&(c.sh>=3||adj(c.i).includes(v.i))&&v.mil<c.mil*1.15).sort((a,b)=>(a.mil-gr(a.i)*30)-(b.mil-gr(b.i)*30));
if(ts.length)declare(c.i,ts[0].i,false)}
if(rnd()<pr[2]){const p=C.find(v=>v.k&&v.i!=c.i&&!H[v.i]&&PR[v.ty<0?1:v.ty][2]>0&&rel[c.i][v.i]>20&&rel[v.i][c.i]>20);if(p)ally(c.i,p.i)}}
function next(){turn++;pend=[];wars.forEach(w=>w.pu={});stats();
C.forEach(c=>{if(!c.k)return;const f=c.k/104;c.si=n((20+c.tp*.3)*f*(c.ind>0?.6:1));
c.di=n(c.tp*1.5*f*(c.blk>0?.4:1))+pacts.filter(p=>p.a==c.i||p.b==c.i).length*8;c.wc=wars.filter(w=>w.a==c.i||w.b==c.i).length*40;
c.D+=c.si+c.di-c.wc;let sh=0;
for(let r=0;r<6;r++){c.st[r]+=c.p[r]-c.k*.17;if(c.st[r]<0){c.D-=n(-c.st[r]*RP[r]*.6);c.st[r]=0;sh=1}}
c.pop=n(c.pop*(sh?.99:1.01));c.mil+=c.k*.04;c.tp+=(50-c.tp)*.02;c.D=Math.max(0,c.D);if(c.blk>0)c.blk--;if(c.ind>0)c.ind--});
RG.forEach(g=>{if(g.dmg>0)g.dmg--});
pacts=pacts.filter(p=>{if(p.exp>turn)return true;L('์กฐ์ฝ',`${C[p.a].n}-${C[p.b].n} ๋ฌด์ญํ์ ๋ง๋ฃ`);return false});
C.forEach(ai);
for(let i=0;i<NC;i++)for(let j=0;j<NC;j++)if(i!=j&&rnd()<.15)rel[i][j]=cl(rel[i][j]+(rnd()<.5?1:-1),-100,100);
C.forEach(c=>c.tp=cl(c.tp,0,100));stats();if(!C[me].k&&H[me]){L('์์คํ
','๊ตญ๊ฐ๊ฐ ๋ฉธ๋งํ์ต๋๋ค. ๊ด์ฐฐ ๋ชจ๋๋ก ์ ํํ์ธ์.')}snd('turn');render()}
// ---------- ์ ์ฅ/๋ถ๋ฌ์ค๊ธฐ ----------
function save(){const s=JSON.stringify({own,reg,RG,C,rel,mem,wars,pend,logs,chat,hist,pacts,turn,aid,H,me});
try{localStorage.setItem(SK,s)}catch(e){window.__nsSave=s}L('์์คํ
','์ ์ฅ๋์์ต๋๋ค')}
function load(){let s;try{s=localStorage.getItem(SK)}catch(e){}s=s||window.__nsSave;if(!s){L('์์คํ
','์ ์ฅ ๋ฐ์ดํฐ๊ฐ ์์ต๋๋ค');return}
const d=JSON.parse(s);({own,reg,RG,C,rel,mem,wars,pend,logs,chat,hist,pacts,turn,aid,H,me}=d);mkCoast();stats();L('์์คํ
','๋ถ๋ฌ์์ต๋๋ค')}
// ---------- ํ๋ ์ด์ด ํ๋ ----------
const can=()=>{if(!H[me]){L('์์คํ
','๊ด์ฐฐ ์ค์ธ ๊ตญ๊ฐ๋ ์กฐ์ํ ์ ์์ด์ (๊ตญ๊ฐ ํญ์์ ์กฐ์ข
์ ํ)');render();return false}return true};
const act={
nx(){if(!pend.length||true){next()}},
cyc(d){me=(me+d+NC)%NC;render()},spd(s){spd=s;acc=0;render()},mute(){mute=!mute;render()},save(){save();render()},load(){load();render()},
tog(){H[me]=!H[me];render()},obs(){H=H.map(()=>false);spd=1;L('์์คํ
','๊ด์ฐฐ ๋ชจ๋: ๋ชจ๋ ๊ตญ๊ฐ๋ฅผ AI๊ฐ ์ด์ํฉ๋๋ค');render()},
chat(){showChat=!showChat;render()},ng(){newGame()},
req(b){if(!can())return;const B=C[b],P=C[me],{r,q,d}=sel;
if(P.D<d){L('์ธ๊ต','D๊ฐ ๋ถ์กฑํฉ๋๋ค');return render()}if(B.st[r]<q+15){L('์ธ๊ต',`${B.n}: ์ฌ๊ณ ๋ถ์กฑ์ผ๋ก ์์ฒญ ๋ถ๊ฐ`);return render()}
if(rnd()<acc_(b,me,d/(q*RP[r]))){trade(me,b,r,q,d);L('์ธ๊ต',`${B.n}์ด(๊ฐ) ${RN[r]} ${q}๊ฐ ์์ฒญ์ ์น์ธ`);snd('ok')}else{rem(b,me,'refuse',-1);L('์ธ๊ต',`${B.n}์ด(๊ฐ) ์์ฒญ์ ๊ฑฐ์ `);snd('no')}render()},
sell(b){if(!can())return;const B=C[b],P=C[me],{r,q,d}=sel;if(P.st[r]<q){L('์ธ๊ต','์ฌ๊ณ ๋ถ์กฑ');return render()}if(B.D<d){L('์ธ๊ต',`${B.n}: D ๋ถ์กฑ`);return render()}
const p=acc_(b,me,Math.min(2,q*RP[r]/Math.max(1,d)))*(B.st[r]<45?1:.3);
if(rnd()<p){trade(b,me,r,q,d);L('์ธ๊ต',`${B.n}์ด(๊ฐ) ${RN[r]} ${q}๊ฐ๋ฅผ D ${d}์ ๊ตฌ๋งค`);snd('ok')}else{L('์ธ๊ต',`${B.n}์ด(๊ฐ) ํ๋งค ์ ์์ ๊ฑฐ์ `);snd('no')}render()},
gift(b){if(!can())return;const P=C[me];if(P.D<100)return;P.D-=100;C[b].D+=100;rem(b,me,'gift',8);P.tp+=1;L('์ธ๊ต',`${C[b].n}์ D 100 ์ ๋ฌผ`);render()},
askD(b){if(!can())return;const B=C[b],P=C[me];if(B.D>400&&rnd()<acc_(b,me,1)-.1){B.D-=200;P.D+=200;rem(b,me,'help',4);L('์ธ๊ต',`${B.n}์ด(๊ฐ) D 200์ ์ง์`);snd('ok')}else{L('์ธ๊ต',`${B.n}์ด(๊ฐ) ์ง์ ์์ฒญ์ ๊ฑฐ์ `);snd('no')}render()},
ally(b){if(!can())return;if(rel[b][me]>15&&C[me].tp>40&&C[b].ty!=6&&ally(me,b))snd('ok');else{L('์ฐํฉ',`${C[b].n}์ด(๊ฐ) ์ฐํฉ ์ ์์ ๊ฑฐ์ `);snd('no')}render()},
pact(b){if(!can())return;if(rel[b][me]>5&&!pacts.some(p=>(p.a==me&&p.b==b)||(p.a==b&&p.b==me))&&C[b].blk<1){pacts.push({a:me,b,exp:turn+10});rem(b,me,'pact',5);L('์กฐ์ฝ',`${C[b].n}๊ณผ(์) 10ํด ๋ฌด์ญํ์ ์ฒด๊ฒฐ (๋งคํด D+8)`);snd('ok')}else{L('์กฐ์ฝ',`${C[b].n}์ด(๊ฐ) ๋ฌด์ญํ์ ์ ๊ฑฐ์ /์ด๋ฏธ ์ฒด๊ฒฐ`);snd('no')}render()},
leave(){if(!can())return;C[me].al=-1;C[me].tp-=3;L('์ฐํฉ','์ฐํฉ์์ ํํดํ์ต๋๋ค');render()},
help(b){if(!can())return;const P=C[me];if(P.D<150)return;P.D-=150;C[b].D+=150;P.tp+=2;rem(b,me,'aid',10);L('์ฐํฉ',`${C[b].n}์ ์ง์์ ์ํ: D 150`);render()},
war(b,f){if(!can())return;declare(me,b,f);render()},
buy(k){if(!can())return;const P=C[me],T={m:[200,'mil',12],s:[300,'sh',2],b:[250,'bm',2],x:[300,'ms',3],d:[100,'df',1]}[k];if(P.D<T[0]||(k=='d'&&P.df>=5))return;P.D-=T[0];P[T[1]]+=T[2];snd('click');render()},
hit(e,t){if(!can())return;const w=wf(me,e);if(!w)return;if(w.pu[me]){L('๊ตฐ์ฌ','์ด๋ฒ ํด ์ด๋ฏธ ํ๋ํ์ต๋๋ค');return render()}
w.pu[me]=1;const r=strike(C[me],C[e],t);if(r<1){w.pu[me]=0;L('๊ตฐ์ฌ',r<0?'์ํ ๋ถ๊ฐ: ์กฐ๊ฑด ๋ฏธ์ถฉ์กฑ(๊ตญ๊ฒฝยทํจ์ ยทํญ๊ฒฉ๊ธฐยท๋ฏธ์ฌ์ผ)':'D๊ฐ ๋ถ์กฑํฉ๋๋ค')}render()},
peace(e){if(!can())return;const w=wf(me,e);if(!w)return;const sa=(w.a==e?1:-1)*w.s;
if(rnd()<(sa<=0?.8:.3))endWar(w,w.s>0?w.a:w.s<0?w.b:-1);else{L('์ธ๊ต',`${C[e].n}์ด(๊ฐ) ํํ ํ์ ์ ๊ฑฐ์ `);snd('no')}render()},
ans(i,y){const p=pend.splice(i,1)[0];if(!p)return;const P=C[p.to];
if(p.t=='req'){if(y&&P.st[p.r]>=p.q){trade(p.f,p.to,p.r,p.q,p.d);P.tp+=2;rem(p.f,p.to,'help',6);L('์ธ๊ต',`${C[p.f].n}์ ์์ฒญ ์น์ธ`)}else{rem(p.f,p.to,'refuse',-3);P.tp-=1;L('์ธ๊ต',`${C[p.f].n}์ ์์ฒญ ๊ฑฐ์ `)}}
else if(p.t=='offer'){if(y&&P.D>=p.d){trade(p.to,p.f,p.r,p.q,p.d);L('์ธ๊ต',`${C[p.f].n}์๊ฒ์ ${RN[p.r]} ${p.q}๊ฐ ๊ตฌ๋งค`)}}
else if(p.t=='dreq'){if(y&&P.D>=150){P.D-=150;C[p.f].D+=150;P.tp+=2;rem(p.f,p.to,'help',8);L('์ธ๊ต',`${C[p.f].n}์ D 150 ์ง์`)}}
else if(p.t=='pact'){if(y){pacts.push({a:p.f,b:p.to,exp:turn+10});L('์กฐ์ฝ',`${C[p.f].n}๊ณผ(์) ๋ฌด์ญํ์ ์ฒด๊ฒฐ`)}}
else if(p.t=='peace'){if(y&&wars.includes(p.w))endWar(p.w,p.w.s>0?p.w.a:p.w.s<0?p.w.b:-1)}
else if(p.t=='aid'){if(y&&P.D>=150){P.D-=150;C[p.lo].D+=150;P.tp+=3;rem(p.lo,p.to,'aid',10);L('์ฐํฉ',`${C[p.lo].n} ์ง์์ ์ฐฌ์ฑ: D 150`)}}
else if(p.t=='wv'){const ok=(p.y0+(y?1:0))*2>=p.ids.length;L('์น์ธ',`์ฐํฉ ํฌํ ${p.y0+(y?1:0)}:${p.ids.length-p.y0-(y?1:0)} โ ${ok?'์น์ธ':'๋ถ๊ฒฐ'}`);if(ok)declare(p.a,p.b,false,true)}
render()}};
const PT=p=>{const f=C[p.f]||{},T={
req:()=>`[์ธ๊ต ๋๋ ์ด์
] ${f.n}์์ ${RN[p.r]} ${p.q}๊ฐ๋ฅผ ์์ฒญํ์ต๋๋ค. (์ ๊ณต D ${p.d})`,
offer:()=>`[์ธ๊ต ๋๋ ์ด์
] ${f.n}์ด(๊ฐ) ${RN[p.r]} ${p.q}๊ฐ๋ฅผ D ${p.d}์ ํ๊ฒ ๋ค๊ณ ์ ์ํ์ต๋๋ค.`,
dreq:()=>`[์ธ๊ต ๋๋ ์ด์
] ${f.n}์ด(๊ฐ) D 150 ์ง์์ ์์ฒญํ์ต๋๋ค.`,
pact:()=>`[์กฐ์ฝ ๋๋ ์ด์
] ${f.n}์ด(๊ฐ) 10ํด ๋ฌด์ญํ์ ์ ์ ์ํ์ต๋๋ค.`,
peace:()=>`[์ธ๊ต ๋๋ ์ด์
] ${C[p.w.a==p.to?p.w.b:p.w.a].n}์ด(๊ฐ) ํํ ํ์ ์ ์ ์ํ์ต๋๋ค.`,
aid:()=>`[์ฐํฉ ๋๋ ์ด์
] ${C[p.lo].n} ์ ํ ๋ณต๊ตฌ ์ง์์(D 150)์ด ์ ์ถ๋์์ต๋๋ค.`,
wv:()=>`[์ฐํฉ ๋๋ ์ด์
] ${C[p.a].n}์ ${C[p.b].n} ์ ์ ์๊ฑด ํฌํ (ํ์ฌ ์ฐฌ์ฑ ${p.y0}/${p.ids.length})`};return T[p.t]()};
// ---------- ํ๋ฉด ----------
const al=c=>c.al>=0?`๐ค์ฐํฉ${c.al+1}`:'';
function render(){const P=C[me];
$('nh').innerHTML=`<button onclick="NS.act.cyc(-1)">โ</button><b style="color:${P.c}">${P.n}</b>${H[me]?'':'(๊ด์ฐฐ)'}<button onclick="NS.act.cyc(1)">โถ</button> T${turn} ๐ฐ${n(P.D)} ๐ก๏ธ${n(P.tp)} โ๏ธ${n(P.mil)}<br>`+
[[0,'โธ'],[1,'1x'],[2,'2x'],[4,'4x']].map(s=>`<button class="${spd==s[0]?'on':''}" onclick="NS.act.spd(${s[0]})">${s[1]}</button>`).join('')+`<button onclick="NS.act.mute()">${mute?'๐':'๐'}</button><button onclick="NS.act.save()">๐พ</button><button onclick="NS.act.load()">๐</button>`;
$('np').innerHTML=pend.map((p,i)=>p.to!=me?'':`<div class=cd>${PT(p)}<br><button onclick="NS.act.ans(${i},1)">์น์ธ/์ฐฌ์ฑ</button><button onclick="NS.act.ans(${i},0)">๊ฑฐ์ /๋ฐ๋</button></div>`).join('');
$('nt').innerHTML=[['e','๊ฒฝ์ '],['d','์ธ๊ต'],['m','๊ตฐ์ฌ'],['a','์ฐํฉ'],['i','๊ตญ๊ฐ'],['l','์์']].map(t=>`<button class="${tab==t[0]?'on':''}" onclick="NS.tab('${t[0]}')">${t[1]}</button>`).join('');
let h='';
if(tab=='e')h=`<div class=r>๐ฐ D ${n(P.D)} ยท ์์ฒด +${P.si} ยท ์ธ๊ต +${P.di} ยท ์ ์์ ์ง -${P.wc}<br>๐ก๏ธ ์จ๋ ${n(P.tp)} ยท ๐ฅ ์ธ๊ตฌ ${P.pop.toLocaleString()} ยท ์ํ ${P.k}${P.blk>0?'<br>โ ๋ด์๋นํจ '+P.blk+'ํด':''}${P.ind>0?'<br>๐ญ ์ฐ์
์์ค ํผํด '+P.ind+'ํด':''}</div>`+
[0,1,2,3,4,5].map(r=>`<div class=r>${RN[r]} ์ฌ๊ณ <b>${n(P.st[r])}</b> ยท ์์ฐ ${P.p[r]} ยท ์๋น ${n(P.k*.17)} ${P.p[r]<P.k*.17?'โ ๏ธ๋ถ์กฑ':''}</div>`).join('')+`<div class=r style="color:#9ab">๋ฌด์ญํ์ : ${pacts.filter(p=>p.a==me||p.b==me).map(p=>C[p.a==me?p.b:p.a].n+'('+(p.exp-turn)+'ํด)').join(', ')||'์์'}</div>`;
else if(tab=='d')h=`<div class=r>๊ฑฐ๋ ์ค์ : <select onchange="NS.sel.r=+this.value">${RN.map((x,i)=>`<option value=${i} ${sel.r==i?'selected':''}>${x}</option>`)}</select><select onchange="NS.sel.q=+this.value">${[10,25,50].map(x=>`<option ${sel.q==x?'selected':''}>${x}</option>`)}</select> D <input type=number value=${sel.d} onchange="NS.sel.d=+this.value"></div>`+
C.filter(c=>c.i!=me&&c.k).map(c=>{const m=mem[c.i][me].slice(-1)[0];return `<div class=r><b style="color:${c.c}">${c.n}</b> ${wf(me,c.i)?'โ๏ธ':''}${al(c)} ยท ${TY[c.ty]||'ํ๋ ์ด์ด'} ${c.blk>0?'โ':''}<br>๐ก๏ธ${n(c.tp)} ยท ๊ด๊ณ ${rel[c.i][me]} ยท ๊ตฐ์ฌ ${n(c.mil)}${m?` ยท ๊ธฐ์ต: ${MK[m.k]||m.k}(T${m.T})`:''}<br>
<button onclick="NS.act.req(${c.i})">์์ฒญ(๊ตฌ๋งค)</button><button onclick="NS.act.sell(${c.i})">ํ๋งค</button><button onclick="NS.act.gift(${c.i})">์ ๋ฌผ100</button><button onclick="NS.act.askD(${c.i})">์ง์์์ฒญ</button><button onclick="NS.act.pact(${c.i})">๋ฌด์ญํ์ </button><button onclick="NS.act.ally(${c.i})">์ฐํฉ</button><button onclick="NS.act.war(${c.i},false)">์ ์(์น์ธ)</button><button onclick="NS.act.war(${c.i},true)">์ ์ ๊ณต๊ฒฉ</button></div>`}).join('');
else if(tab=='m'){const myw=wars.filter(w=>w.a==me||w.b==me);
h=`<div class=r>โ๏ธ๊ตฐ์ฌ ${n(P.mil)} ยท ๐ก๏ธ๋ฐฉ์ด์ง์ง Lv.${P.df}/5 ยท โตํจ์ ${P.sh} ยท โ๏ธํญ๊ฒฉ๊ธฐ ${P.bm} ยท ๐๋ฏธ์ฌ์ผ ${P.ms}<br>
<button onclick="NS.act.buy('m')">๊ตฐ์ฌ๋ ฅ+12 (200)</button><button onclick="NS.act.buy('d')">๋ฐฉ์ด์ง์ง (100)</button><button onclick="NS.act.buy('s')">ํจ์ +2 (300)</button><button onclick="NS.act.buy('b')">ํญ๊ฒฉ๊ธฐ+2 (250)</button><button onclick="NS.act.buy('x')">๋ฏธ์ฌ์ผ+3 (300)</button></div>`+
(myw.map(w=>{const e=w.a==me?w.b:w.a,E=C[e],s=(w.a==me?1:-1)*w.s,rs=regsOf(e);return `<div class=r>โ๏ธ vs <b style="color:${E.c}">${E.n}</b> ${w.agg==me?'(๋ด๊ฐ ๊ฐ์ )':'(๋ฐฉ์ด์ )'}${w.pre?' ยท ์ ์ ๊ณต๊ฒฉ ์ ์':''} ยท ์ ๊ตฐ์ฌ ${n(E.mil)} โต${E.sh} ยท ์ ํฉ ${s>0?'+':''}${s}<br>
<button onclick="NS.act.hit(${e},'a')">๋๊ฒฉ150</button><button onclick="NS.act.hit(${e},'n')">ํด์์ 120</button><button onclick="NS.act.hit(${e},'k')">๋ด์100</button><button onclick="NS.act.hit(${e},'v')">์๋ฅ300</button><button onclick="NS.act.hit(${e},'b')">ํญ๊ฒฉ(๊ตฐ์ฌ)200</button><button onclick="NS.act.hit(${e},'B')">ํญ๊ฒฉ(์ฐ์
)200</button><button onclick="NS.act.hit(${e},'m')">๋ฏธ์ฌ์ผ250</button><button onclick="NS.act.hit(${e},'h')">โข๏ธ์์ํญํ1500</button><button onclick="NS.act.peace(${e})">ํํํ์ </button><br>
๋ฏธ์ฌ์ผ ๋ชฉํ: <select onchange="NS.sel.g=+this.value">${rs.map(g=>`<option value=${g} ${sel.g==g?'selected':''}>${RG[g].n} (${RN[RG[g].res]})</option>`)}</select></div>`}).join('')||`<div class=r>ํ์ฌ ์ ์ ์ค์ด ์๋๋๋ค.</div>`)+
`<div class=r style="color:#9ab">ํด๋น ์ ์๋ณ 1ํ ํ๋. ๋๊ฒฉ=๊ตญ๊ฒฝ ์ ๋ น, ํด์์ =ํด์ ํต์ , ์๋ฅ=ํด์ ์นจํฌ, ๋ด์=๊ต์ญ ์ฐจ๋จ, ์์ํญํ=๋๊ท๋ชจ ํ๊ฒฉ+๊ตญ์ ํํญํ.</div>`}
else if(tab=='a'){const ids=[...new Set(C.filter(c=>c.al>=0).map(c=>c.al))];
h=(P.al>=0?`<div class=r>${al(P)} ์์ ยท ์ฐํฉ ๋ด ์ ์์ ๋ค์๊ฒฐ, ์ฐํฉ๊ตญ์ด ๊ณต๊ฒฉ๋ฐ์ผ๋ฉด ์๋ ์ฐธ์ <button onclick="NS.act.leave()">ํํด</button><br>`+C.filter(v=>v.al==P.al&&v.i!=me).map(v=>`${v.n} D${n(v.D)} <button onclick="NS.act.help(${v.i})">์ง์ D150</button>`).join('<br>')+`</div>`:`<div class=r>๊ฐ์
ํ ์ฐํฉ์ด ์์ต๋๋ค. ์ธ๊ต ํญ์์ ์ฐํฉ์ ์ ์ํ์ธ์.</div>`)+
ids.map(id=>`<div class=r>๐ค ์ฐํฉ${id+1}: ${C.filter(c=>c.al==id).map(c=>`<span style="color:${c.c}">${c.n}</span>`).join(', ')}</div>`).join('')}
else if(tab=='i'){h=`<div class=r><b>${P.n}</b> ยท ์ฑํฅ ${TY[P.ty]||'ํ๋ ์ด์ด'} ยท ${H[me]?'์กฐ์ข
์ค':'AI/๊ด์ฐฐ'}<br><button onclick="NS.act.tog()">${H[me]?'AI์๊ฒ ๋งก๊ธฐ๊ธฐ':'์ด ๊ตญ๊ฐ ์ง์ ์กฐ์ข
'}</button><button onclick="NS.act.obs()">๐ ๊ด์ฐฐ ๋ชจ๋</button><button onclick="NS.act.ng()">์ ๊ฒ์</button></div>
<div class=r><b>์ง์ญ</b><br>`+RG.filter(g=>g.o==me).map(g=>`${g.n}: ${RN[g.res]} ${g.dmg?'(ํผํด '+g.dmg+'ํด)':''}`).join('<br>')+`</div><div class=r><b>์ ์ ๊ธฐ๋ก</b><br>${hist.slice(0,10).join('<br>')||'์์'}</div>
<div class=r><b>์ธ๊ต ๊ธฐ๋ก(์๋โ${P.n})</b><br>`+C.filter(c=>c.i!=me).map(c=>mem[c.i][me].slice(-2).map(m=>`${c.n}: ${MK[m.k]||m.k} ${m.v>0?'+':''}${m.v} (T${m.T})`).join('<br>')).filter(x=>x).join('<br>')+`</div>`}
else h=`<button onclick="NS.act.chat()">${showChat?'๋๋ ์ด์
๋ณด๊ธฐ':'AI๋ผ๋ฆฌ์ ๋ํ ๋ณด๊ธฐ(๊ด์ฐฐ)'}</button>`+(showChat?chat:logs).map(x=>`<div class=r>${x}</div>`).join('');
$('nb').innerHTML=h}
// ---------- ์ง๋ ๊ทธ๋ฆฌ๊ธฐ ----------
function draw(){frame++;const W=GW*CS,Hh=GH*CS;ctx.fillStyle='#0c1b2e';ctx.fillRect(0,0,W,Hh);
for(let i=0;i<own.length;i++){const x=i%GW,y=i/GW|0,o=own[i],X=x*CS,Y=y*CS;
if(o<0){ctx.fillStyle=((x+y+(frame>>2))&3)?'#10304f':'#164068';ctx.fillRect(X,Y,CS,CS);continue}
ctx.fillStyle=C[o].c;ctx.fillRect(X,Y,CS,CS);if(coast[i]){ctx.fillStyle='#ffffff30';ctx.fillRect(X,Y,CS,CS)}
const g=RG[reg[i]];if(g.dmg){ctx.fillStyle='#000a';ctx.fillRect(X,Y,CS,CS)}
ctx.fillStyle=RC[g.res];ctx.fillRect(X+4,Y+4,3,3)}
for(let i=0;i<own.length;i++){const x=i%GW,y=i/GW|0;if(own[i]<0)continue;
if(x<GW-1&&own[i+1]>=0&&(own[i+1]!=own[i]||reg[i+1]!=reg[i])){ctx.strokeStyle=own[i+1]!=own[i]?(wf(own[i],own[i+1])?'#ff2a2a':'#000b'):'#fff4';ctx.lineWidth=own[i+1]!=own[i]?2:1;ctx.beginPath();ctx.moveTo((x+1)*CS,y*CS);ctx.lineTo((x+1)*CS,(y+1)*CS);ctx.stroke()}
if(y<GH-1&&own[i+GW]>=0&&(own[i+GW]!=own[i]||reg[i+GW]!=reg[i])){ctx.strokeStyle=own[i+GW]!=own[i]?(wf(own[i],own[i+GW])?'#ff2a2a':'#000b'):'#fff4';ctx.lineWidth=own[i+GW]!=own[i]?2:1;ctx.beginPath();ctx.moveTo(x*CS,(y+1)*CS);ctx.lineTo((x+1)*CS,(y+1)*CS);ctx.stroke()}}
const bob=(frame>>3)&1;C.forEach(c=>{if(!c.k)return;sp[c.i].slice(0,Math.min(3,Math.ceil(c.sh/2))).forEach(i=>{if(own[i]!=c.i)return;const x=(i%GW)*CS,y=(i/GW|0)*CS;ctx.fillStyle='#fff';ctx.fillRect(x+1,y+CS-3+bob,6,2);ctx.fillRect(x+3,y+bob,2,CS-3)})});
ctx.font='bold 12px system-ui';ctx.textAlign='center';ctx.lineWidth=3;ctx.strokeStyle='#000';ctx.fillStyle='#fff';
C.forEach(c=>{if(!c.k)return;const t=(c.i==me?'โ
':'')+c.n+(wars.some(w=>w.a==c.i||w.b==c.i)?'โ':'');ctx.strokeText(t,cen[c.i][0],cen[c.i][1]);ctx.fillText(t,cen[c.i][0],cen[c.i][1])});
fx=fx.filter(f=>{f.t++;const p=Math.min(1,f.t/f.d),x=f.x0+(f.x1-f.x0)*p,y=f.y0+(f.y1-f.y0)*p;
if(f.k=='boom'||(f.k=='nuke'&&f.t>10)){const r=(f.t-(f.k=='nuke'?10:0))*(f.k=='nuke'?1.6:1.1);ctx.fillStyle=f.t%6<3?'#fff':'#ffb020';
for(let a=0;a<8;a++)ctx.fillRect(f.x1+Math.cos(a*.785)*r-2,f.y1+Math.sin(a*.785)*r-2,4,4);if(f.k=='nuke'){ctx.fillStyle='#ffffff'+(f.t<16?'55':'22');ctx.fillRect(0,0,W,Hh)}}
else if(f.k=='miss'){ctx.strokeStyle='#ff6';ctx.lineWidth=2;ctx.beginPath();ctx.moveTo(f.x0,f.y0);ctx.lineTo(x,y);ctx.stroke();ctx.fillStyle='#fff';ctx.fillRect(x-2,y-2,5,5)}
else if(f.k=='ship'||f.k=='plane'){ctx.fillStyle=f.k=='ship'?'#fff':'#ddd';ctx.fillRect(x-4,y-1,9,3);ctx.fillRect(x-1,y-4,3,9)}
if(f.t>=f.d&&f.k!='boom'&&f.k!='nuke'&&f.k!='plane'){if(f.k=='miss'||f.k=='ship')fx.push({k:'boom',x0:0,y0:0,x1:f.x1,y1:f.y1,t:0,d:14})}
return f.t<f.d+(f.k=='nuke'?20:0)})}
cv.addEventListener('pointerdown',e=>{const r=cv.getBoundingClientRect(),x=Math.floor((e.clientX-r.left)/r.width*GW),y=Math.floor((e.clientY-r.top)/r.height*GH),i=y*GW+x;
if(x<0||y<0||x>=GW||y>=GH)return;$('ni').textContent=own[i]<0?'๐ ๋ฐ๋ค':`${RG[reg[i]].n} ยท ์์ ${C[own[i]].n} ยท ํน์ฐ ${RN[RG[reg[i]].res]}${coast[i]?' ยท ํด์':''}${RG[reg[i]].dmg?' ยท ํผํด':''}`;snd('click')});
setInterval(()=>{draw();if(spd&&!pend.length){acc+=70*spd;if(acc>=3000){acc=0;next()}}},70);
window.NS={act,sel,tab:t=>{tab=t;render()}};
newGame();
})();
Game Source: Worldline
Creator: GlitchKnight20
Libraries: none
Complexity: complex (262 lines, 31.4 KB)
The full source code is displayed above on this page.
Remix Instructions
To remix this game, copy the source code above and modify it. Add a ARCADELAB header at the top with "remix_of: worldline-glitchknight20" to link back to the original. Then publish at arcadelab.ai/publish.