//
image = null;
R = /image=([^&]*)/; 
if (x=R.exec(location.search)) 
image = unescape(x[1]);
if (!image)
image = "$top/links/chammers/hammers.jpg";
document.f.image.value = image;
scramble = false;
R = /scramble=([^&]*)/; 
if (x=R.exec(location.search) && x[1].toString())
scramble = true;
function makeGame(im) // takes an image node
{
var width, height, tileWidth, tileHeight, 
width = im.width; // or naturalWidth, or computed width...
height = im.height;
// Allow bottom/right of image to be cut off. better than introducing Obvious White Pixels and 
// giving away where the edge is.
tileWidth = parseInt(width/4);
tileHeight = parseInt(height/4);
var tiles = [[],[],[],[]];
var grid = [[],[],[],[]];
var game = document.createElement("div");
game.className = "game";
game.style.position = "absolute"; // give tiles something to "stick" to
game.style.width = width + "px";
game.style.height = height + "px";
var theEmptyT, emptyp, emptyq;
for (var i=0; i<4; ++i)
for (var j=0; j<4; ++j)
{
var t = document.createElement("div");
var x = i * tileWidth;
var y = j * tileHeight;
t.style.position = "absolute";
t.style.width = tileWidth + "px";
t.style.height = tileHeight + "px";
t.style.backgroundImage = "url(" + im.src + ")";
t.style.backgroundAttachment = "scroll";
t.style.backgroundPosition = "-" + x + "px -" + y + "px";
t.style.backgroundRepeat = "no-repeat";
// setting using shorthand works in ie but not in moz:
// t.style.background = "url(" + im.src + ") scroll -" + x + " -" + y + " no-repeat";
t.className = "tile";
if (i == 3 && j == 3)
{
t.style.display = "none"; // hide last block until game is over
t.isEmpty = true;
theEmptyT = t;
t.className = "empty";
}
// i,j is original position. used to determine when you've won.
t.i = i;
t.j = j;
// p,q is current position. initially set by repositionAll();
grid[i][j] = t;
t.onclick = 
function()
{
var p = this.p;
var q = this.q;
if (p == emptyp) // horizontally in line with empty square
{
if (q < emptyq) // empty square is to my right
for (j=emptyq; j!=q; --j)
grid[emptyp][j] = grid[emptyp][j - 1];
else
for (j=emptyq; j!=q; ++j)
grid[emptyp][j] = grid[emptyp][j + 1];
grid[p][q] = theEmptyT;
} 
else if (this.q == emptyq) // vertically in line with empty square
{
if (p < emptyp) // empty square is to my right
for (i=emptyp; i!=p; --i)
grid[i][emptyq] = grid[i - 1][emptyq];
else
for (i=emptyp; i!=p; ++i)
grid[i][emptyq] = grid[i + 1][emptyq];
grid[p][q] = theEmptyT;
}
repositionAll();
}
game.appendChild(t);
} // huge for loop to create tiles
function gradual(ob, prop, start, fin)
{
var n = 5;
var step = (fin - start) / n;
ob[prop] = start;
for (var i=1; i<=n; ++i)
(function(){
var I = i;
setTimeout(function() { ob[prop] = (start + step*I) + "px"; }, 30*i)
})()
}
function repositionAll()
{
var correct = 0, i, j;
for (i=0; i<4; ++i)
for (j=0; j<4; ++j)
{
t = grid[i][j];
if (t.p != i)
{
if (t.p != null && !t.isEmpty)
gradual(t.style, "left", tileWidth * t.p, tileWidth * i)
else
t.style.left = tileWidth * i + "px";
t.p = i;
}
if (t.q != j)
{
if (t.q != null && !t.isEmpty)
gradual(t.style, "top", tileHeight * t.q, tileHeight * j)
else  
t.style.top = tileHeight * j + "px";
t.q = j;
}
if (t.isEmpty)
{
emptyp = i;
emptyq = j;
}
if (t.i == i && t.j == j)
++correct;
}
theEmptyT.style.display = (correct == 16) ? "block" : "none";
game.style.borderColor = (correct == 16) ? "lightgreen" : "black";
}
repositionAll();
if (scramble)
{
// Based on ideas from http://www.dragonflydigital.com/samples/imedia/puzzle.html
for (var s = 0; s < 128; ++s)
{
var r = Math.random();
var sp, sq;
if (r < .5)
{
sp = emptyp + (r < .25 ? 1 : -1);
sq = emptyq;
}
else
{
sp = emptyp;
sq = emptyq + (r > .75 ? 1 : -1);
}
// "reflect" if try to swap with something outside of board
if (sp == -1) sp = 1;
if (sp == 4) sp = 2;
if (sq == -1) sq = 1;
if (sq == 4) sq = 2;
var swaptemp = grid[sp][sq];
grid[sp][sq] = grid[emptyp][emptyq];
grid[emptyp][emptyq] = swaptemp;
emptyp = sp;
emptyq = sq;
}
} // if scramble
repositionAll();
var par = im.parentNode;
par.insertBefore(game, im);
par.removeChild(im);
} // function makeGame
function replaceImage()
{
var url = document.f.image.value;
var im = document.createElement("img");
var h = document.getElementById("imageHolder");
while (h.firstChild)
h.removeChild(h.firstChild);
h.appendChild(im);
im.onload = function() { makeGame(this); }
im.src = url; // do this last so there's no chance of it loading while this thread is still going
}
//