It's a xmas puzzle that is solved by dragging the pieces around and it contains a little surprise for finishing.
M=Math.min;function K(x,y,r,u,v){r?a.beginPath()|a.fill(a.arc(x,y,r,u||0,v||7,0)):a.fillStyle='#'+'a000b4bbfff5'.substr(x,3);return K}function P(e){C=k=64;c.height=c.width=E=C*4;K(e?1:6)(0,0,E*2);if(e){for(i in D)i-S&&a[I='putImageData'](D[X[i]],i%4*C,i/4<<6);S+1&&a.fillRect(N+5,O+5,C,C)|a[I](D[T],N,O)}else{for(K(8)(90,590,E*2)(1)(145,y=24,14)(x=150,12,z=10,1,4)(134,y,z)(x,57,i=y);i+9;)K(180+i,71-i*i--/40+Math.sin(A)*y/(33-i),4);for(i=205;--i;i<18&&K(s=C+(i%6-3)*i<<1,t=y+i*z+M(i-4?0:A*A*2,x),4)(0)(s,t,4,6,3))j=i%49*(i%21)/9,K(3)(E/2,l=z-j,j+=i,1.2,2)(8)(E/2,l-j%2,j,1.7,2);for(K(9)(x,21,4,4,7)(x,21,4,8,5);--k;K(8)(j*7%E,j*k%E,k%2+1))j=k*k+A;A+=.3}}P(A=0);for(X=[D=[x=16]];x--;X[x]=x*6%47%16)D[x]=a.getImageData(x%4*C,x/4<<6,63,63);P(R=S=-1);setInterval(c.onmousedown=c.onmousemove=document.onmouseup=function(e){f=e?e.type:P(R);if(f&&R){N=-M(32-M(x=e.clientX,219),0);O=-M(32-M(y=e.clientY,219),0);p=(x|y)>>8;z=x/C|y/C<<2;f[8]!='n'||p?C:T=X[S=z];if(!f[8]&&S+1){p||(X[S]=X[z],X[z]=T);S=-1;R=0;for(i in X)R|=X[i]-i}}},C)
TT1NYXRoLm1pbjtmdW5jdGlvbiBLKHgseSxyLHUsdil7cj9hLmJlZ2luUGF0aCgpfGEuZmlsbChhLmFyYyh4LHkscix1fHwwLHZ8fDcsMCkpOmEuZmlsbFN0eWxlPScjJysnYTAwMGI0YmJmZmY1Jy5zdWJzdHIoeCwzKTtyZXR1cm4gS31mdW5jdGlvbiBQKGUpe0M9az02NDtjLmhlaWdodD1jLndpZHRoPUU9Qyo0O0soZT8xOjYpKDAsMCxFKjIpO2lmKGUpe2ZvcihpIGluIEQpaS1TJiZhW0k9J3B1dEltYWdlRGF0YSddKERbWFtpXV0saSU0KkMsaS80PDw2KTtTKzEmJmEuZmlsbFJlY3QoTis1LE8rNSxDLEMpfGFbSV0oRFtUXSxOLE8pfWVsc2V7Zm9yKEsoOCkoOTAsNTkwLEUqMikoMSkoMTQ1LHk9MjQsMTQpKHg9MTUwLDEyLHo9MTAsMSw0KSgxMzQseSx6KSh4LDU3LGk9eSk7aSs5OylLKDE4MCtpLDcxLWkqaS0tLzQwK01hdGguc2luKEEpKnkvKDMzLWkpLDQpO2ZvcihpPTIwNTstLWk7aTwxOCYmSyhzPUMrKGklNi0zKSppPDwxLHQ9eStpKnorTShpLTQ/MDpBKkEqMix4KSw0KSgwKShzLHQsNCw2LDMpKWo9aSU0OSooaSUyMSkvOSxLKDMpKEUvMixsPXotaixqKz1pLDEuMiwyKSg4KShFLzIsbC1qJTIsaiwxLjcsMik7Zm9yKEsoOSkoeCwyMSw0LDQsNykoeCwyMSw0LDgsNSk7LS1rO0soOCkoaio3JUUsaiprJUUsayUyKzEpKWo9ayprK0E7QSs9LjN9fVAoQT0wKTtmb3IoWD1bRD1beD0xNl1dO3gtLTtYW3hdPXgqNiU0NyUxNilEW3hdPWEuZ2V0SW1hZ2VEYXRhKHglNCpDLHgvNDw8Niw2Myw2Myk7UChSPVM9LTEpO3NldEludGVydmFsKGMub25tb3VzZWRvd249Yy5vbm1vdXNlbW92ZT1kb2N1bWVudC5vbm1vdXNldXA9ZnVuY3Rpb24oZSl7Zj1lP2UudHlwZTpQKFIpO2lmKGYmJlIpe049LU0oMzItTSh4PWUuY2xpZW50WCwyMTkpLDApO089LU0oMzItTSh5PWUuY2xpZW50WSwyMTkpLDApO3A9KHh8eSk+Pjg7ej14L0N8eS9DPDwyO2ZbOF0hPSduJ3x8cD9DOlQ9WFtTPXpdO2lmKCFmWzhdJiZTKzEpe3B8fChYW1NdPVhbel0sWFt6XT1UKTtTPS0xO1I9MDtmb3IoaSBpbiBYKVJ8PVhbaV0taX19fSxDKQ==
// X-Mas Cartoon Puzzle for JS1K by @veubeke
// See http://games.23inch.de/puzzle/ for (ugly) converter script
// Version 1.1 changes:
// - minor drag&drop bugs
// - transparent shadow
// + more animations after finish and snow on the tree
// Optimizations used:
// * Content
// * Interlaced colors in one string
// * Procedurally generated tree, decoration, falling snow
// * Grouped painting of same-color parts
// * Created fake shadow with fillRect instead of using built-in shadow
// * Built whole scene with circle (segments)
// * Syntax
// * Used 'a ? b : c' instead of 'if(a) b; else c'
// * Used 'a && b' and 'a || b' instead of 'if(a) b' and 'if(!a) b'
// * Used '|' instead of '||' and '|' instead of '+' (for different operator priority)
// * Used 'a,b,c' or 'a|b|c' instead of '{a;b;c}'
// * Used 'for(a=b;a--)' instead of 'for(a=0;a<b;a++)' (or '--a' for 'a=1')
// * Used calls w/o parameter for other statements e.g. a.fill(a.rect(...))
// * Used || for default arguments
// * Used 2^n sizes to allow for exsessive shifting
// * Used bit operations for rounding
// * Set height to clear canvas
// * Let often used function return itself to chain calls
// * Exploited operator hierarchy to avoid ()
// * ...
// * Didn't use ~ to check for -1 because opera 10/11 fails after 10th call(bug has been filed)
// * Other
// * Cached often used function (names)
// * Used every function for multiple purpoises
// Global variables:
// a - context, b - body, c - canvas
// C - tile size
// anim - animation step
// data - tile image data
// map - index to tile map
// mousex/y - current mouse position
// running - whether the puzzle is still incomplete
// source - dragged tile source
// tile - dragged tile
mmin = Math.min;
// ark - draw a circle (segment) or set a color
// 1 parameter - set color
// 3,5 parameters - draw circle (segment)
// 4 parameter - draw rectangle
//
// Interlaced colors
// a00 decoration
// 000 cat, border
// 0b4 tree
// bbf sky
// fff snow
// ff5 eye
function ark(x,y,r,u,v) {
r ? a.beginPath() | a.fill(a.arc(x,y,r,u||0,v||7,0))
: a.fillStyle = '#'+'a000b4bbfff5'.substr(x,3);
// Returns itself so calls can be chained
return ark
}
// paint - paint image or rearrange tiles
function paint(e) {
C = k = 64;
// Reset canvas
c.height = c.width = size = C*4;
// Paint sky or tile background/borders
ark(e?1:6)(0,0,size*2);
// Rearrange tiles
if(e) {
// Paste placed tiles
for(i in data)
i-source && a[pimd='putImageData'](data[map[i]], i%4*C, i/4<<6);
// Paste dragged tile if currently dragging
source+1 && a.fillRect(mousex+5, mousey+5, C,C) | a[pimd](data[tile], mousex, mousey)
}
// Paint image / animation
else {
// Snow, cat: head ears body
for(ark(8)(90,590,size*2)(1)(145,y=24,14)(x=150,12,z=10,1,4)(134,y,z)(x,57,i=y); i+9;)
// Tail
ark(180+i,71-i*i--/40+Math.sin(anim)*y/(33-i),4);
// Globes
for(i=205; --i; i<18 && ark(s=C+(i%6-3)*i<<1,t=y+i*z+mmin(i-4?0:anim*anim*2,x),4)(0)(s,t,4,6,3))
j = i%49*(i%21)/9,
// Tree snow on tree
ark(3)(size/2,l=z-j,j+=i,1.2,2)(8)(size/2,l-j%2,j,1.7,2);
// Cat's eye, snowflakes (will fall if painted repeatedly)
for(ark(9)(x,21,4,4,7)(x,21,4,8,5); --k; ark(8)(j*7%size,j*k%size,k%2+1))
j = k*k+anim;
anim += .3
}
}
// Paint initial image
paint(anim=0);
// Create and 'randomize' tiles
for(map=[data=[x=16]]; x--; map[x]=x*6%47%16)
data[x] = a.getImageData(x%4*C,x/4<<6,63,63);
// Draw tiles
paint(running=source=-1);
// Add event handlers and start animation loop
setInterval(
c.onmousedown = c.onmousemove =
// 'Mouse up' has to be catched at the document level to not lose
// actions outside of the page.
document.onmouseup = function(e) {
// Paint tiles / animation when not in an event handler.
// Check for e.type is necessary for firefox as it adds a latency parameter
f = e ? e.type : paint(running);
if(f && running) {
// Handle dragging
mousex = -mmin(32-mmin(x=e.clientX, 219), 0);
mousey = -mmin(32-mmin(y=e.clientY, 219), 0);
// Check boundaries
p = (x|y) >> 8;
// Get tile
z = x/C | y/C<<2;
// Handle grabbing
f[8]!='n' || p ? C : tile = map[source=z];
// Handle drop
if(!f[8] && source+1) { // try ~source here in opera and have fun :D
// Switch tiles
p || (map[source] = map[z], map[z] = tile);
// Reset
source = -1;
// Check if finished.
running = 0;
for(i in map)
running |= map[i]-i
}
}
}
, C)