- Author:
- Rebecca
- Twitter:
- @
- GitHub:
- Facebook:
- Google+:
- +
- Reddit:
- /r/
- Pouet:
- Website: 
- 23inch.de
- Compo:
- classic
- Demo link:
- https://js1k.com/2010-first/demo/562
- Shortlink:
- https://js1k.com/562
- Blog post:
- please update here!
- Bytes:
- 1023
- Chars:
- 1023
- Submission
- eval("eval(\"C=document.body.children[0];X=C.getContext(g='2d');o=C.onmousemoveLx=(qX|0)-kQ5;y=qY-w-1Q5;Gp-(p=x*8+y)){n=x/W|yQ3?0:P[M=s[p]];Na,0,1,1);C.height=w*10;C.width=D;X.font='14px Arial';FText('Score: '+S+'  Best: '+((Y=localStorage).h|0),w,320);EaIa<7;V'#ccc',N0,288+a++,D,1))Ec in [2,OBlur=3])Gc|!a)JOColor=[V'#'+'0eb2290'.substr(BH,3),'#000'][c],BHRc!=(nRsHjM)RN(iQ3)*w+2+k-a,z*w+w+a,w,w)}};(C.onclickLGg){W=16;l=W*W;w=32;v=w*W;k=(D-v)Q1;BUEi=n=S=gKMath.random()*4+1|0}Gn){S+=n*n;JGsHjM)l-=2,BHIExIx<B.length;Zx+7]?x+=8:B.splice(x,8))Ei=g=1;i<8;i++)G!Za=i+x]RZb=a-1])Za]=Zb],Zb]=iIk=(D-x*4)Q1}sUPUJ{P[sH=i]IGa=BH)Eb=1;b<9;b+=7)G(bj1Rz||bj8&i>7)RZi-b]ja){gIc=s[i-b];Ed in s)Gc-iRs[d]jc)s[d]=sH,PH++}}Gg){S-=l;GS>(Y.h|0))Y.h=S;k=D-w*12Q1;EiK'@h\0Ph\0\x10x\0x P'.charCodeAt(iQ3)&(1<<(z))?(i-11?4:1):0}p=v;o(e)})(0)\"_zi%8_qe.page_j==_ZB[_VFStyle=_U=[];_R&&_Q>>_OX.shadow_NFRect(_L=function(e){_KIi<8*W;i++)BH=_JEi in B)_I=0;_H[i]_Gif(_FX.fill_Efor(_DinnerWidth)".replace(/_(\w)([^_]*)(?!$)/g,".replace(/$1/g,'$2')"))
 
- Description
- SameGame(http://en.wikipedia.org/wiki/SameGame)
The goal is to remove as many blocks as possible.
Displays score and persistent high score.
Click to start a new game.
Update: Fixed 3 bugs, added bigger board and game over screen.
- Base64 encoded
- ZXZhbCgiZXZhbChcIkM9ZG9jdW1lbnQuYm9keS5jaGlsZHJlblswXTtYPUMuZ2V0Q29udGV4dChnPScyZCcpO289Qy5vbm1vdXNlbW92ZUx4PShxWHwwKS1rUTU7eT1xWS13LTFRNTtHcC0ocD14KjgreSkpe249eC9XfHlRMz8wOlBbTT1zW3BdXTtOYSwwLDEsMSk7Qy5oZWlnaHQ9dyoxMDtDLndpZHRoPUQ7WC5mb250PScxNHB4IEFyaWFsJztGVGV4dCgnU2NvcmU6ICcrUysnICBCZXN0OiAnKygoWT1sb2NhbFN0b3JhZ2UpLmh8MCksdywzMjApO0VhSWE8NztWJyNjY2MnLE4wLDI4OCthKyssRCwxKSlFYyBpbiBbMixPQmx1cj0zXSlHY3whYSlKT0NvbG9yPVtWJyMnKycwZWIyMjkwJy5zdWJzdHIoQkgsMyksJyMwMDAnXVtjXSxCSFJjIT0oblJzSGpNKVJOKGlRMykqdysyK2stYSx6KncrdythLHcsdyl9fTsoQy5vbmNsaWNrTEdnKXtXPTE2O2w9VypXO3c9MzI7dj13Klc7az0oRC12KVExO0JVRWk9bj1TPWdLTWF0aC5yYW5kb20oKSo0KzF8MH1Hbil7Uys9bipuO0pHc0hqTSlsLT0yLEJISUV4SXg8Qi5sZW5ndGg7WngrN10/eCs9ODpCLnNwbGljZSh4LDgpKUVpPWc9MTtpPDg7aSsrKUchWmE9aSt4XVJaYj1hLTFdKVphXT1aYl0sWmJdPWlJaz0oRC14KjQpUTF9c1VQVUp7UFtzSD1pXUlHYT1CSClFYj0xO2I8OTtiKz03KUcoYmoxUnp8fGJqOCZpPjcpUlppLWJdamEpe2dJYz1zW2ktYl07RWQgaW4gcylHYy1pUnNbZF1qYylzW2RdPXNILFBIKyt9fUdnKXtTLT1sO0dTPihZLmh8MCkpWS5oPVM7az1ELXcqMTJRMTtFaUsnQGhcMFBoXDBceDEweFwweCBQJy5jaGFyQ29kZUF0KGlRMykmKDE8PCh6KSk/KGktMTE/NDoxKTowfXA9djtvKGUpfSkoMClcIl96aSU4X3FlLnBhZ2Vfaj09X1pCW19WRlN0eWxlPV9VPVtdO19SJiZfUT4+X09YLnNoYWRvd19ORlJlY3QoX0w9ZnVuY3Rpb24oZSl7X0tJaTw4Klc7aSsrKUJIPV9KRWkgaW4gQilfST0wO19IW2ldX0dpZihfRlguZmlsbF9FZm9yKF9EaW5uZXJXaWR0aCkiLnJlcGxhY2UoL18oXHcpKFteX10qKSg/ISQpL2csIi5yZXBsYWNlKC8kMS9nLCckMicpIikp
 
- Original source
- canvas = document.body.children[0];
context = canvas.getContext(end='2d'); // game ended -> setup new game
/// move handler (drawing)
onmove = canvas.onmousemove = function(e)
{
  /// map to board
  // x defaults to -offset/32 if dummy event supplied
  x = (e.pageX|0)-offset >> 5;
  y = e.pageY-w-1 >> 5;
  // if block already selected
  if(mousep-(mousep=x*8+y)) {
    // get selection and selection size
    // or default to none if pointer outside the board
    numSel = x/W|y>>3 ? 0:selCount[selected=selections[mousep]];
    /// clear canvas
    // Setting size would be enough to redraw but bug 49151 makes chrome
    // clear only the 'active rectangle'. Setting the height to 0 first
    // would fix this but make ff and opera incredibly slow so the shortest
    // workaround is to expand the active space by adding a zero-size square
    // to the top which - according to the specification - 'has no effect'
    // and make chrome clear everything. Oh boy.
    // Update: Safari on the other hand respects the spec but not enough to
    // redraw by itself so I actually had to give the rectangle a size of 1.
    context.fillRect(a,0,1,1);
    canvas.height = w*10;
    canvas.width = innerWidth;
    context.font = '14px Arial';
    /// print score and high score
    context.fillText('Score: '+score+
                   '  Best: '+((Y=localStorage).h|0),w,320);
    /// draw board
    // 7 times for perspective
    for(a=0; a<7; context.fillStyle = '#ccc',context.fillRect(0,288+a++,innerWidth,1))
      // c=0 => selected, c=1 => other
      for(c in [2,context.shadowBlur=3])
        // draw selected only once for flat effect
        if(c|!a)
          for(i in board)
            // hint: colors are interlaced
            context.shadowColor = [context.fillStyle='#'+'0eb2290'.substr(board[i],3),'#000'][c],
            board[i] && c!=(numSel&&selections[i]==selected) && context.fillRect((i>>3)*w+2+offset-a,i%8*w+w+a,w,w)
      // draw separator (see loop head)
  }
};
/// click handler (game logic)
(canvas.onclick = function(e)
{
  /// setup new game
  if(end) {
    // board width in blocks
    W = 16;
    // blocks left * 2
    left = W*W;
    // block size
    w = 32;
    // displayed board width
    v = w*W;
    // offset to center the board
    offset = (innerWidth-v) >> 1;
    /// setup board, #selected, score, game over
    board = [];
    for(i=numSel=score=end=0; i<8*W;i++)
      board[i] = Math.random()*4+1|0
  }
  /// do move
  if(numSel) {
    // update score: (n-1)^2 for n blocks
    score += numSel*numSel;
    /// remove selected blocks
    for(i in board)
      if(selections[i]==selected)
        left -= 2,
        board[i] = 0;
    /// block propagation
    for(x=0; x<board.length; board[x+7]?x+=8:board.splice(x,8))
      /// vertical
      for(i=end=1; i<8; i++)
        if(!board[a=i+x] && board[b=a-1])
          board[a] = board[b],
          board[b] = i = 0;
      // horizontal (see loop head)
    // count remaining columns for offset
    offset = (innerWidth-x*4) >> 1
  }
  /// generate selections equivalence relation
  // equivalence classes
  selections = [];
  // class sizes
  selCount = [];
  for(i in board) {
    selCount[selections[i] = i] = 0;
    if(a=board[i])
      /// check top and left neighbour
      for(b=1; b<9; b+=7)
        if((b==1 && i%8 || b==8 & i>7) && board[i-b]==a) {
          // game not finished
          end = 0;
          /// join classes of i and i-b
          c = selections[i-b];
          for(d in selections)
            if(c-i && selections[d]==c)
              selections[d] = selections[i],
              selCount[i]++
        }
  }
  if(end) {
    // add game end score: -blocks*2
    score -= left;
    // update high score
    if(score>(Y.h|0)) Y.h = score;
    /// create nice game over screen
    offset = innerWidth-w*12 >> 1;
    for(i=0; i<8*W; i++)
      // finish the game to see what's been encoded here ;)
      // \x10 is escaped to avoid binary data
      board[i] = '@h\0Ph\0\x10x\0x P'.charCodeAt(i>>3)&(1<<(i%8)) ? (i-11?4:1):0
  }
  /// mark next blocks immediately
  mousep = v;
  onmove(e)
})(0) // pass dummy event