let board=[],move=0,moveSpeed=3
function setup(){createCanvas(390,390);textAlign(CENTER,CENTER);textSize(30)}
rect(95*(i%4)+10,95*(Math.floor(i/4))+10,85,85)
md=Math.min(md,block.draw(move))
move=Math.max(0,move-4*moveSpeed/60)
move>0||(board=board.filter(x=>x.d==0)).forEach(e=>{e.x=e.nx;e.y=e.ny})
return ([x,3-y,3-x,y])[d]
return ([y,x,3-y,3-x])[d]
return ([x+4*y,y+4*(3-x),(3-x)+4*(3-y),(3-y)+4*x])[d]
let indexing=[],r=0;for(let i=0;i<16;i++)indexing.push(0)
for(let block of board)indexing[block.nx+block.ny*4]++
for(let i=0;i<16;i++)indexing[i]>0||Math.random()>.11||board.push(new Block(i%4,Math.floor(i/4),2+2*Math.round(Math.random()*.69)+0*r++))
r||(indexing.filter(x=>x<1).length&&populate())
case UP_ARROW:shiftBoard(0)
case RIGHT_ARROW:shiftBoard(1)
case DOWN_ARROW:shiftBoard(2)
case LEFT_ARROW:shiftBoard(3)
function mouseReleased(){populate()}
function shiftBoard(dir){
let end=[[],[],[],[]],t=[]
for(let i=0;i<16;i++)t.push(0)
for(let b of board)t[bof(b.x,b.y,dir)]=b.n
t[j]&&(end[i].length&&end[i][end[i].length-1]==t[j]?(end[i][end[i].length-1]*=2):end[i].push(t[j]))
board.forEach(x=>x.d=(x.x!=x.nx||x.y!=x.ny)?0:1)
for(let i=0;i<4;i++)for(let j=0;j<end[i].length;j++)board.push(new Block(xof(i,j,dir),yof(i,j,dir),end[i][j]))
return a*(1.6-a)*(a+.6667)
this.x=x;this.y=y;this.n=n
this.nx=x;this.ny=y;this.d=0
let d=max(abs(this.x-this.nx),abs(this.y-this.ny))||1,x=0,y=0
let f=interp(max(0,move-4+d)/d)
x=this.x*f+this.nx*(1-f);y=this.y*f+this.ny*(1-f)
fill(180,255*(1-this.d*(1-f)));noStroke()
rect(95*x+10,95*y+10,85,85)
fill(0,255*(1-this.d*(1-f)));text(this.n,95*x+52,95*y+52)