isIE = (navigator.appVersion.indexOf("MSIE") != -1);

function DOMTag(tag, attrs, listeners, children) {
	var	i;

	this.tag = tag;

	this.attrs = {};
	if (attrs)
		for (i in attrs) {
			if (i == "children") {
				if (!children)
					children = attrs.children;
			} else
				this.attrs[i] = attrs[i];
		}

	this.children = children ? children : [];

	this.listeners = {};
	if (listeners)
		for (i in listeners)
			this.listeners[i] = (typeof(listeners[i]) == "string") ? new Function(listeners[i]) : listeners[i];
}

DOMTag.peerAttrGetters = {
	_class:function(peer, attr)	{ return peer.className; },
	checked:function(peer, attr)	{ return peer.checked; },
	value:function(peer, attr)		{ return peer.value; }
};

DOMTag.getPeerAttr = function(peer, name) {
	if (name in DOMTag.peerAttrGetters)
		return DOMTag.peerAttrGetters[name](peer, name);
	else
		return peer.getAttribute(name);
};

DOMTag.peerAttrSetters = {
	_class:function(peer, attr, value)		{ peer.className = value; },
	checked:function(peer, attr, value)		{ peer.checked = value ? true : false; },
	innerHTML:function(peer, attr, value)	{ peer.innerHTML = value; },
	value:function(peer, attr, value)		{ peer.value = value ? value : ""; }
};

DOMTag.setPeerAttr = function(peer, name, value) {
	if (name in DOMTag.peerAttrSetters)
		DOMTag.peerAttrSetters[name](peer, name, value);
	else
		peer.setAttribute(name, value);
};

DOMTag.setPeerListener = function(peer, evt, listener) {
	if (evt == "watchChecked") {
		if (isIE) {
			peer.onpropertychange = function() {
				if (event.propertyName == "checked")
					listener();
			};
		} else {
			peer.onchange = listener;
		}
	} else {
		peer[evt] = listener;
	}
};

DOMTag.prototype.appendChild = function(child) {
	this.children.push(child);

	if ("peer" in this) {
		this.peer.appendChild(child.getPeer());
	}
};

DOMTag.prototype.focus = function() {
	this.getPeer().focus();
};

DOMTag.prototype.getAttribute = function(name) {
	if ("peer" in this)
		return DOMTag.getPeerAttr(this.peer, name);
	else
		return this.attrs[name];
};

DOMTag.prototype.getCheck = function() {
	return this.getAttribute("checked");
};

DOMTag.prototype.getPeer = function() {
	var	i, tag;

	if (this.peer)
		return this.peer;

	if (isIE) {
		tag = "<" + this.tag;
		for (i in this.attrs)
			tag += " " + i + "=\"" + this.attrs[i] + "\"";
		tag += ">";
	} else
		tag = this.tag;

	this.peer = document.createElement(tag);

	if ("type" in this.attrs)
		DOMTag.setPeerAttr(this.peer, "type", this.attrs.type);
	if ("name" in this.attrs)
		DOMTag.setPeerAttr(this.peer, "name", this.attrs.name);
	for (i in this.attrs)
		if (i != "type" && i != "name")
			DOMTag.setPeerAttr(this.peer, i, this.attrs[i]);

	for (i in this.listeners)
		DOMTag.setPeerListener(this.peer, i, this.listeners[i]);

	for (i in this.children)
		this.peer.appendChild(this.children[i].getPeer());

	return this.peer;
};

DOMTag.prototype.getSelectedValue = function() {
	var	peer = this.getPeer();

	return peer.options[peer.selectedIndex].value;
};

DOMTag.prototype.getValue = function() {
	return this.getAttribute("value");
};

DOMTag.prototype.setAttribute = function(name, value) {
	this.attrs[name] = value;

	if ("peer" in this)
		DOMTag.setPeerAttr(this.peer, name, value);
};

DOMTag.prototype.setCheck = function(check) {
	this.setAttribute("checked", check);
};

DOMTag.prototype.setChildren = function(children) {
	this.children = children;

	if ("peer" in this) {
		var	len, len2, i;

		len = this.children.length;
		len2 = this.peer.childNodes.length;

		while (len2 > len)
			this.peer.removeChild(this.peer.childNodes[--len2]);

		for (i = 0 ; i < len ; ++i) {
			if (i < len2)
				this.peer.replaceChild(children[i].getPeer(), this.peer.childNodes[i]);
			else
				this.peer.appendChild(children[i].getPeer());
		}
	}
};

DOMTag.prototype.setListener = function(event, listener) {
	if (typeof(listener) == "string")
		listener = new Function(listener);

	this.listeners[event] = listener;

	if ("peer" in this)
		DOMTag.setPeerListener(this.peer, event, listener);
};

DOMTag.prototype.setValue = function(value) {
	this.setAttribute("value", value);
};

function DOMText(value) {
	this.setValue(value);
}

DOMText.prototype.getPeer = function() {
	if (!this.peer)
		this.peer = document.createTextNode(this.value);

	return this.peer;
};

DOMText.prototype.getValue = function() {
	return this.value;
};

DOMText.prototype.setValue = function(value) {
	this.value = String(value);

	if (this.peer)
		this.peer.replaceData(0, this.peer.length, this.value);
};

var	animationInterval;
var	collection;
var	collectionNum;
var	cookies = new Array();
var	dispRoot;
var	dispImages;
var	eab;
var	eac;
var	eal;
var	ean;
var	ear;
var	eas;
var	eat;
var	eax;
var	eay;
var	images;
var	finished = true;
var	level;
var	levelData;
var	levelNum;
var	levelSize;
var	params = new Array();
var	px;
var	py;
var	selCollection;
var	selLevel;
var	startX;
var	startY;
var	trimRE = /^\s*(.*[^\s])\s*$/;
var	undoStack = [];

function Undo(newX, newY, tfX, tfY, ttX, ttY) {
	this.x1	= px;
	this.y1	= py;
	this.t1	= getTile(px, py);

	this.x2	= newX;
	this.y2	= newY;
	this.t2	= getTile(newX, newY);

	this.x3	= tfX;
	this.y3	= tfY;
	this.t3	= getTile(tfX, tfY);

	this.x4	= ttX;
	this.y4	= ttY;
	this.t4	= getTile(ttX, ttY);

	this.px	= px;
	this.py	= py;
}

function UndoString(s) {
	var	a = s.split(',');

	this.x1	= a[0];
	this.y1	= a[1];
	this.t1	= a[2];
	this.x2	= a[3];
	this.y2	= a[4];
	this.t2	= a[5];

	this.x3	= a[6];
	this.y3	= a[7];
	this.t3	= a[8];

	this.x4	= a[9];
	this.y4	= a[10];
	this.t4	= a[11];

	this.px	= a[12];
	this.py	= a[13];
}

function addUndo(newX, newY, tfX, tfY, ttX, ttY) {
	undoStack[undoStack.length] = new Undo(newX, newY, tfX, tfY, ttX, ttY);
}

function buildTable() {
	var	y, x, rows;

	dispRoot = new DOMTag();
	dispRoot.peer = document.getElementById("main");

	dispImages = [];
	rows = [];

	for (y = 0 ; y < level.height ; ++y) {
		dispImages[y] = [];

		for (x = 0 ; x < level.width ; ++x)
			dispImages[y][x] = new DOMTag("img", { src:"images/startTile.gif", width:32, height:32 }, { onclick:makeOnClick(x, y) });

		rows.push(new DOMTag("div", {}, {}, [ new DOMTag("nobr", {}, {}, dispImages[y]) ]));
	}

	dispRoot.setChildren(rows);
}

function canMoveTo(x, y) {
	var	tested = new Array(level.height), i;

	for (i = 0 ; i < level.height ; ++i)
		tested[i] = new Array(level.width);

	return testMoveTo(tested, px, py, x, y);
}

function canPush(x, y) {
	var	c = getTile(x, y);

	return (c == '.' || c == ' ');
}

function checkWon() {
	var	x, y, c, expire;

	for (y = 0 ; y < level.height ; y++)
		for (x = 0 ; x < level.width ; x++) {
			c = getTile(x, y);

			if (c == '.' || c == '+')
				return;
		}

	if (levelNum + 1 < collection.levels.length)
		setCookie("collection-" + collectionNum, levelNum + 1);
	else if (collectionNum + 1 < collections.length)
		setCookie("collection", collectionNum + 1);

	finished = true;

	if (Math.random() < 0.5)
		fadeOut1Init();
	else
		fadeOut2Init();
}

function clearCookie(name) {
	var	d = new Date();

	d.setMilliseconds(d.getMilliseconds() - 86400000);

	document.cookie = name + "=; expires=" + d.toUTCString();
}

function click(x, y) {
	if (!finished && (x != px || y != py)) {
		if (canMoveTo(x, y))
			playerJumpTo(x, y);
		else {
			var	dx, dy;

			dx = x - px;
			dy = y - py;

			if (((dx == 1 || dx == -1) && dy == 0) || ((dy == 1 || dy == -1) && dx == 0))
				move(dx, dy, 0);
		}
	}
}

function directions() {
	open("directions.html", "directions", "width=600,height=450,directories=no,location=no,menubar=no,personalbar=no,scrollbars=yes,status=no,toolbar=no");
}

function drawBoard() {
	var	x, y;

	for (y = 0 ; y < level.height ; ++y)
		for (x = 0 ; x < level.width ; ++x)
			setTile(x, y, levelData[y][x]);
}

function fadeIn1Init() {
	eas = 0;
	animationInterval = setInterval(fadeIn1Tick, 100);
}

function fadeIn1Tick() {
	if (eas < level.width) {
		var	x = eas, y = 0;

		while (x >= 0 && y < level.height) {
			setTile(x, y, levelData[y][x]);
			x--;
			y++;
		}

		eas++;
	} else if (eas < (level.width + level.height)) {
		var	x = (level.width - 1), y = eas - level.width;

		while (x >= 0 && y < level.height) {
			setTile(x, y, levelData[y][x]);
			x--;
			y++;
		}

		eas++;
	} else {
		clearInterval(animationInterval);
		finished = false;
	}
}

function fadeIn2Init() {
	eax = 0;
	eay = 0;
	eal = 0;
	ear = level.width - 1;
	eat = 1;
	eab = level.height - 1;
	eac = 0;
	eas = 0;

	if (levelSize > 50)
		ean = Math.round(levelSize / 50);
	else
		ean = 1;

	animationInterval = setInterval(fadeIn2Tick, 25);
}

function fadeIn2Tick() {
	var	i;

	for (i = 0 ; i < ean ; ++i) {
		setTile(eax, eay, levelData[eay][eax]);

		switch (eas) {
			case 0:
				if (++eax == ear) {
					eas = 1;
					ear--;
				}
				break;

			case 1:
				if (++eay == eab) {
					eas = 2;
					eab--;
				}
				break;

			case 2:
				if (--eax == eal) {
					eas = 3;
					eal++;
				}
				break;

			case 3:
				if (--eay == eat) {
					eas = 0;
					eat++;
				}
				break;
		}

		if (++eac == levelSize) {
			clearInterval(animationInterval);
			finished = false;
		}
	}
}

function fadeIn3Init() {
	eas = 0;
	animationInterval = setInterval(fadeIn3Tick, 50);
}

function fadeIn3Tick() {
	var	x, y;

	for (y = 0 ; y < level.height ; y++) {
		x = ((y & 1) == 0) ? eas : ((level.width - 1) - eas);

		setTile(x, y, levelData[y][x]);
	}

	if (++eas == level.width) {
		clearInterval(animationInterval);
		finished = false;
	}
}

function fadeOut1Init() {
	eas = 0;
	animationInterval = setInterval(fadeOut1Tick, 100);
}

function fadeOut1Tick() {
	if (eas < level.height)
		fadeOut1TickHelp(level.width - 1, level.height - 1 - eas);
	else if (eas < (level.width + level.height))
		fadeOut1TickHelp(level.width - 1 - (eas - level.height), 0);
	else {
		clearInterval(animationInterval);
		nextLevel();
	}

	eas++;
}

function fadeOut1TickHelp(x, y) {
	while (x >= 0 && y < level.height)
		dispImages[y++][x--].setAttribute("src", "images/startTile.gif");
}

function fadeOut2Init() {
	eas = 0;
	animationInterval = setInterval(fadeOut2Tick, 50);
}

function fadeOut2Tick() {
	var	x, y;

	for (x = 0 ; x < level.width ; ++x) {
		y = ((x & 1) == 0) ? eas : ((level.height - 1) - eas);

		dispImages[y][x].setAttribute("src", "images/startTile.gif");
	}

	if (++eas == level.height) {
		clearInterval(animationInterval);
		nextLevel();
	}
}

function getHighLevel(c) {
	var	tmp;

	tmp = cookies["collection-" + c];
	if (tmp && !isNaN(tmp)) {
		tmp = Number(tmp);

		if (tmp >= collections[c].levels.length)
			tmp = collections[c].levels.length - 1;

		return tmp;
	}

	return 0;
}

function getTile(x, y) {
	if (y < 0 || y >= levelData.length || x < 0 || x >= levelData[y].length)
		return '!';
	else
		return levelData[y][x];
}

function ieOnKeyDown() {
	var	howMuch;

	if (window.event.shiftKey)
		howMuch = 2;
	else if (window.event.ctrlKey)
		howMuch = 1;
	else
		howMuch = 0;

	if (window.event.keyCode == 37)
		move(-1, 0, howMuch);
	else if (window.event.keyCode == 38)
		move(0, -1, howMuch);
	else if (window.event.keyCode == 39)
		move(1, 0, howMuch);
	else if (window.event.keyCode == 40)
		move(0, 1, howMuch);
	else if (window.event.keyCode == 85)
		undo();
	else if (window.event.keyCode == 27)
		restart();
	else
		return;

	window.event.cancelBubble = true;
}

function init() {
	var	rnd;

	initLevelInfo();
	preload();
	buildTable();
	initSelCollection();
	initSelLevel();
	initHandlers();

	rnd = Math.random();
	if (rnd <= 0.33)
		fadeIn1Init();
	else if (rnd <= 0.66)
		fadeIn2Init();
	else
		fadeIn3Init();
}

function initHandlers() {
	if (navigator.appName == "Netscape" && navigator.appVersion >= "5")
		document.onkeydown = mozOnKeyDown;
	else if (document.all)
		document.onkeydown = ieOnKeyDown;

	finished = true;
}

function initLevelData() {
	var	i, j, k;

	levelData = new Array(level.height);
	levelSize = level.width * level.height;

	for (i = k = 0 ; i < level.height ; ++i) {
		levelData[i] = new Array(level.width);

		for (j = 0 ; j < level.width ; ++j) {
			var	c = level.data.charAt(k++);

			levelData[i][j] = c;

			if (c == "@" || c == "+") {
				px = startX = j;
				py = startY = i;
			}
		}
	}
}

function initLevelInfo() {
	var	tmp, hi;

	initRequestVars();

	collectionNum = -1;
	tmp = params["c"];
	if (tmp && !isNaN(tmp))
		collectionNum = Number(tmp);
	if (collectionNum < 0) {
		tmp = cookies["collection"];
		if (tmp && !isNaN(tmp))
			collectionNum = Number(tmp);
	}
	if (collectionNum < 0 || collectionNum >= collections.length)
		collectionNum = 0;
	collection = collections[collectionNum];

	levelNum = -1;
	tmp = params["l"];
	if (tmp && !isNaN(tmp))
		levelNum = Number(tmp);
	if (levelNum < 0) {
		tmp = cookies["collection-" + collectionNum];
		if (tmp && !isNaN(tmp))
			levelNum = Number(tmp);
	}
	if (levelNum < 0)
		levelNum = 0;
	else if (levelNum > (hi = getHighLevel(collectionNum)))
		levelNum = hi;
	level = collection.levels[levelNum];

	if (levelNum > 1) {
	}

	initLevelData();

	tmp = cookies["savedState"];
	if (tmp) {
		restoreState(tmp);
		clearCookie("savedState");
	}
}

function initRequestVars() {
	var	tmp, i, eq, name, val;

	tmp = document.cookie.split(";");

	for (i = 0 ; i < tmp.length ; ++i)
		if ((eq = tmp[i].indexOf("=")) > 0) {
			name = trim(tmp[i].substr(0, eq));
			val = trim(tmp[i].substr(eq + 1));

			if (name.length > 0 && val.length > 0)
				cookies[name] = val;
		}

	if (location.search && location.search.length > 0) {
		if (location.search.charAt(0) != "?")
			tmp = location.search;
		else
			tmp = location.search.substr(1);

		tmp = tmp.split("&");

		for (i = 0 ; i < tmp.length ; ++i)
			if ((eq = tmp[i].indexOf("=")) > 0) {
				name = trim(tmp[i].substr(0, eq));
				val = trim(tmp[i].substr(eq + 1));

				if (name.length > 0 && val.length > 0)
					params[name] = val;
			}
	}
}

function initSelCollection() {
	var	i, sel = [], attrs;

	selCollection = new DOMTag();
	selCollection.peer = document.getElementById("collection");

	for (i = 0 ; i < collections.length ; ++i) {
		attrs = { value:i + 1 };
		if (i == collectionNum)
			attrs.selected = true;
		sel.push(new DOMTag("option", attrs, {}, [ new DOMText(collections[i].title) ]));
	}

	selCollection.setChildren(sel);
}

function initSelLevel() {
	var	hiLevel = getHighLevel(collectionNum), i, sel = [], attrs;

	selLevel = new DOMTag();
	selLevel.peer = document.getElementById("level");

	if (isNaN(hiLevel) || hiLevel < 0)
		hiLevel = 0;

	for (i = 0 ; i <= hiLevel ; ++i) {
		attrs = { value:i + 1 };
		if (i == levelNum)
			attrs.selected = true;

		sel.push(new DOMTag("option", attrs, {}, [ new DOMText("Level " + String(i + 1)) ]));
	}

	selLevel.setChildren(sel);
}

function loadImage(i) {
	var	img;

	img = new Image();
	img.src = "images/" + i + ".gif";

	return img;
}

function makeOnClick(x, y) {
	return function() {
		click(x, y);
		return false;
	};
}

function move(dx, dy, howMuch) {
	if (!finished) 
		if (howMuch == 1)
			moveTil(dx, dy)
		else if (howMuch == 2)
			moveAll(dx, dy) 
		else {
			var	x, y, c;

			x = px + dx;
			y = py + dy;

			c = getTile(x, y);

			if (c == ' ' || c == '.')
				playerJumpTo(x, y);
			else if (c == '$' || c == '*') {
				if (canPush(x + dx, y + dy)) {
					addUndo(x, y, x, y, x + dx, y + dy);

					pushTo(x + dx, y + dy);
					playerJumpTo(x, y);

					checkWon();
				}
			}
		}
}

function moveAll(dx, dy) {
	var	x = px, y = py, c;

	while (true) {
		c = getTile(x + dx, y + dy);

		if (c != ' ' && c != '.')
			break;

		x += dx;
		y += dy;
	}

	if (c == '$' || c == '*') {
		var	tfX = x + dx, tfY = y + dy;

		while (true) {
			c = getTile(x + dx + dx, y + dy + dy);

			if (c != ' ' && c != '.')
				break;

			x += dx;
			y += dy;
		}

		if (x + dx != tfX || y + dy != tfY) {
			addUndo(x, y, tfX, tfY, x + dx, y + dy);

			pushFrom(tfX, tfY);
			pushTo(x + dx, y + dy);
			playerJumpTo(x, y);

			checkWon();

			return;
		}
	} 

	if (x != px || y != py)
		playerJumpTo(x, y);
}

function moveTil(dx, dy) {
	var	x = px, y = py, c;

	while (true) {
		c = getTile(x + dx, y + dy);

		if (c != ' ' && c != '.')
			break;

		x += dx;
		y += dy;
	}

	if (x != px || y != py)
		playerJumpTo(x, y);
}

function mozOnKeyDown(e) {
	var	howMuch;

	if (e.shiftKey)
		howMuch = 2;
	else if (e.ctrlKey)
		howMuch = 1;
	else
		howMuch = 0;

	if (e.which == 37)
		move(-1, 0, howMuch);
	else if (e.which == 38)
		move(0, -1, howMuch);
	else if (e.which == 39)
		move(1, 0, howMuch);
	else if (e.which == 40)
		move(0, 1, howMuch);
	else if (e.which == 85)
		undo();
	else if (e.which == 27)
		restart();
	else
		return;

	e.stopPropagation();
	e.preventDefault();
}

function nextLevel() {
	if (levelNum + 1 < collection.levels.length)
		request(collectionNum, levelNum + 1);
	else if (collectionNum + 1 < collections.length)
		request(collectionNum + 1, 0);
	else
		alert("This is the last level");
}

function playerJumpTo(x, y) {
	var	c;

	if (getTile(px, py) == '+')
		setTile(px, py, '.');
	else
		setTile(px, py, ' ');

	px = x;
	py = y;

	c = getTile(px, py);

	if (c == '.' || c == '*')
		setTile(px, py, '+');
	else
		setTile(px, py, '@');
}

function preload() {
	images = new Array(8);

	images[0]	= loadImage("wall1");
	images[1]	= loadImage("wall2");
	images[2]	= loadImage("home");
	images[3]	= loadImage("gemHome");
	images[4]	= loadImage("gem");
	images[5]	= loadImage("guy");
	images[6]	= loadImage("guyHome");
	images[7]	= loadImage("background");
}

function pushFrom(x, y) {
	if (getTile(x, y) == '*')
		setTile(x, y, '.');
	else
		setTile(x, y, ' ');
}

function pushTo(x, y) {
	if (getTile(x, y) == '.')
		setTile(x, y, '*');
	else
		setTile(x, y, '$');
}

function request(col, lev) {
	location = location.pathname + "?c=" + col + "&l=" + lev;
}

function reset() {
	if (!finished) {
		var	x, y, k;

		for (y = k = 0 ; y < level.height ; y++)
			for (x = 0 ; x < level.width ; x++)
				setTile(x, y, level.data.charAt(k++));

		undoStack.length = 0;
		px = startX;
		py = startY;
	}
}

function restart() {
	status = "Restarting the level can not be undone";

	if (confirm("Are you sure you want to restart this level?"))
		reset();

	status = "";
}

function restoreState(state) {
	var	tmp = unescape(state).replace(/_/g, " ").split(":"), x, y, i;

	if (tmp.length < 4)
		return;
	--tmp.length;

	if (isNaN(tmp[0]) || Number(tmp[0]) != collectionNum)
		return;

	if (isNaN(tmp[1]) || Number(tmp[1]) != levelNum)
		return;

	if (tmp[2].length != levelSize)
		return;

	for (y = i = 0 ; y < level.height ; ++y)
		for (x = 0 ; x < level.width ; ++x) {
			var	c = tmp[2].charAt(i++);

			levelData[y][x] = c;

			if (c == "@" || c == "+") {
				px = x;
				py = y;
			}
		}

	undoStack.length = 0;
	for (i = 3 ; i < tmp.length ; ++i)
		undoStack[undoStack.length] = new UndoString(tmp[i]);
}

function saveAndQuit() {
	saveState();

	window.close();
	location = "http://google.com";
}

function saveState() {
	if (!finished) {
		var	state, y, x;

		state = "";

		for (y = 0 ; y < levelData.length ; y++)
			for (x = 0 ; x < levelData[y].length ; x++)
				state = state + levelData[y][x];

		state = state + ":";

		for (x = 0 ; x < undoStack.length ; x++) {
			var	u = undoStack[x];

			state = state + u.x1 + "," + u.y1 + "," + u.t1 + ",";
			state = state + u.x2 + "," + u.y2 + "," + u.t2 + ",";
			state = state + u.x3 + "," + u.y3 + "," + u.t3 + ",";
			state = state + u.x4 + "," + u.y4 + "," + u.t4 + ",";
			state = state + u.px + "," + u.py + ":";
		}

		state = state.replace(/ /g, "_");
		setCookie("savedState", collectionNum + ":" + levelNum + ":" + state);
	}
}

function selectCollection() {
	var	sel = document.forms[0].elements[0];
	var	opt = sel.options[sel.selectedIndex];

	if (parseInt(opt.value) - 1 != collectionNum) {
		var	expire = new Date();

		expire.setTime(expire.getTime() + 31536000000);
		document.cookie = "collection=" + opt.value + "; expires=" + expire.toGMTString();

		location = location.pathname + "?c=" + (opt.value - 1);
	}
}

function selectLevel() {
	var	sel = document.forms[0].elements[1];
	var	opt = sel.options[sel.selectedIndex];

	if (parseInt(opt.value) - 1 != levelNum)
		request(collectionNum, opt.value - 1);
}

function setCookie(name, value) {
	var	d = new Date();

	d.setMilliseconds(d.getMilliseconds() + 31536000000);	// 1 year

	document.cookie = name + "=" + escape(value) + "; expires=" + d.toUTCString();
}

function setTile(x, y, tile) {
	var	gif;

	switch (tile) {
		case '#':
			if (x > 0 && levelData[y][x - 1] == '#')
				gif = "wall2";
			else
				gif = "wall1";
			break;

		case '.':
			gif = "home";
			break;

		case '*':
			gif = "gemHome";
			break;

		case '$':
			gif = "gem";
			break;

		case '@':
			gif = "guy";
			break;

		case '+':
			gif = "guyHome";
			break;

		default:
			tile = ' ';
			gif = "background";
			break;
	}

	levelData[y][x] = tile;
	dispImages[y][x].setAttribute("src", "images/" + gif + ".gif");
}

function skipLevels() {
	open("skipLevels.html", "skipper", "width=600,height=450,directories=no,location=no,menubar=no,personalbar=no,scrollbars=yes,status=no,toolbar=no");
}

function testMoveTo(tested, tx, ty, x, y) {
	var	c;

	if (tx < 0 || tx >= level.width || ty < 0 || ty >= level.height || tested[ty][tx])
		return false;

	c = getTile(tx, ty);

	if (c != '.' && c != ' ' && c != '@' && c != '+')
		return false;

	if (tx == x && ty == y)
		return true;

	tested[ty][tx] = 1;

	if (testMoveTo(tested, tx - 1, ty, x, y))
		return true;
	else if (testMoveTo(tested, tx + 1, ty, x, y))
		return true;
	else if (testMoveTo(tested, tx, ty - 1, x, y))
		return true;
	else 
		return testMoveTo(tested, tx, ty + 1, x, y);
}

function trim(str) {
	var	tmp;

	tmp = trimRE.exec(str);

	if (tmp == null)
		return "";
	else
		return tmp[1];
}

function undo() {
	if (!finished && undoStack.length > 0) {
		var	u = undoStack[undoStack.length - 1];

		undoStack.length--;

		if (getTile(px, py) == '+')
			setTile(px, py, '.');
		else
			setTile(px, py, ' ');

		px = u.px;
		py = u.py;

		setTile(u.x1, u.y1, u.t1);
		setTile(u.x2, u.y2, u.t2);
		setTile(u.x3, u.y3, u.t3);
		setTile(u.x4, u.y4, u.t4);
	}
}
