Board = function()
{
	var links = [];
	var arrows = [];
	var chara = null;
	var info = null;
	var key_catcher_up = null;
	var key_catcher = null;

	var doors = [
		{ opened:false, frames:2, auto:false, curr:0 },
		{ opened:false, frames:2, auto:false, curr:0 },
		{ opened:false, frames:6, auto:true , curr:0 },
		{ opened:true,  frames:6, auto:true , curr:5 }
	];

	var map_wdt = 18;
	var map_hgt = 16;

	var map = [
		['W ','W ','W ','W ','W ','W ','W ','W ','W ','W ','W ','W ','  ','  ','  ','  ','  ','  '],
		['W ','W ','W ','W ','W ','W ','W ','W ','W ','W ','W ','W ','  ','  ','  ','  ','W ','W '],
		['W ','W ','W ','L3','L3','L3','L3','L3','L3','L3','W ','W ','  ','W ','W ','  ','W ','W '],
		['W ','W ','W ','L3','L3','L3','L3','L3','L3','L3','W ','W ','  ','W ','W ','  ','  ','  '],
		['W ','W ','W ','W ','W ','  ','W ','W ','W ','W ','W ','W ','  ','  ','  ','  ','  ','  '],
		['W ','W ','W ','W ','W ','  ','W ','W ','W ','W ','W ','W ','  ','W ','W ','W ','W ','W '],
		['W ','W ','W ','W ','W ','  ','W ','W ','W ','W ','W ','W ','  ','W ','L1','L1','L1','L1'],
		['  ','  ','  ','  ','  ','  ','  ','  ','  ','  ','  ','  ','  ','D1','L1','L1','L1','L1'],
		['  ','W ','W ','W ','W ','D2','W ','W ','W ','  ','  ','  ','  ','W ','L1','L1','L1','L1'],
		['  ','W ','  ','  ','  ','  ','  ','  ','W ','  ','  ','  ','  ','W ','L1','L1','L1','L1'],
		['  ','W ','W ','  ','  ','  ','  ','W ','W ','  ','  ','W ','W ','W ','W ','D4','W ','W '],
		['  ','W ','W ','W ','D3','W ','W ','W ','W ','  ','  ','W ','  ','  ','  ','  ','W ','  '],
		['  ','  ','  ','W ','  ','W ','  ','  ','  ','  ','  ','W ','W ','W ','W ','W ','W ','W '],
		['W ','W ','W ','W ','  ','W ','W ','W ','W ','  ','  ','  ','  ','  ','  ','  ','  ','  '],
		['W ','W ','L2','L2','L2','L2','L2','L2','W ','  ','  ','  ','  ','  ','W ','W ','  ','  '],
		['W ','L2','L2','L2','L2','L2','L2','L2','W ','  ','  ','  ','  ','  ','W ','W ','  ','  ']
	];

	var xpos = 8;
	var ypos = 7;
	var dir = 3;
	var lv = 0;
	var door_ind = -1;

	var actions = [];
	var h_actions = 0;

	function update_chara()
	{
		var info_str = 'Up: Forward<br />Down: Backward<br />Left: Turn left<br />Right: Turn right<br />';

		chara.top = (16 + 32 * Math.round(ypos)) + 'px';
		chara.left = (16 + 32 * Math.round(xpos)) + 'px';
		chara.backgroundPosition = '-' + String(dir * 32) + 'px 0';

		for (var i = 0; i < arrows.length; i++) arrows[i].display = (i == dir ? '' : 'none');

		if (map[ypos][xpos].charAt(0) == 'L') lv = Number(map[ypos][xpos].charAt(1));
		else lv = 0;

		for (var i = 0; i < links.length; i++) S.rm_class(links[i], 'link-' + (i+1) + '-act');

		if (lv > 0)
		{
			S.add_class(links[lv-1], 'link-' + lv + '-act');
			info_str = 'Space: <span style="color:#FF0000;">Play game</span><br />';
		}

		door_ind = -1;
		var np = get_off(1);

		if (np != null)
		{
			var nx = np[0];
			var ny = np[1];

			if (map[ny][nx].charAt(0) == 'D')
			{
				door_ind = Number(map[ny][nx].charAt(1)) - 1;

				if (doors[door_ind].opened) {
					info_str = 'Space: Close door<br />';
				} else {
					info_str = 'Space: Open door<br />';
				}
			}
		}

		info.innerHTML = info_str;
	}

	function get_off(mult)
	{
		var xoff = 0;
		var yoff = 0;

		switch (dir)
		{
			case 0:
				yoff = -1;
				break;

			case 1:
				yoff = -1;
				xoff = 1;
				break;

			case 2:
				xoff = 1;
				break;

			case 3:
				xoff = 1;
				yoff = 1;
				break;

			case 4:
				yoff = 1;
				break;

			case 5:
				xoff = -1;
				yoff = 1;
				break;

			case 6:
				xoff = -1;
				break;

			case 7:
				xoff = -1;
				yoff = -1;
				break;
		}

		xoff *= mult;
		yoff *= mult;

		var nx = xpos + xoff;
		var ny = ypos + yoff;

		if (nx<0 || nx>=map_wdt || ny<0 || ny>=map_hgt) return null;

		return [nx, ny];
	}

	function move_chara(mult)
	{
		var np = get_off(mult);
		if (np == null) return;

		var nx = np[0];
		var ny = np[1];

		switch (map[ny][nx].charAt(0))
		{
			case 'W':
				return;

			case 'D':
				var ind = Number(map[ny][nx].charAt(1)) - 1;

				if (!doors[ind].opened)
				{
					if (doors[ind].auto)
					{
						actions.push({ action:'open', ind:ind });
						actions.push({ action: (mult>0 ? 'fw' : 'bk') });
						do_actions();
					}

					return;
				}

				break;
		}

		xpos = nx;
		ypos = ny;

		update_chara();
	}

	function process_door(ind, door_dir)
	{
		if (doors[ind].opened && door_dir==1) return;
		if (!doors[ind].opened && door_dir==-1) return;

		var nc = (door_dir>0 ? (doors[ind].frames-1) : 0);

		if (doors[ind].curr == nc)
		{
			doors[ind].opened = (nc > 0);
			update_chara();
			do_actions();
			return;
		}

		doors[ind].curr += door_dir;
		doors[ind].st.backgroundPosition = '-' + String(doors[ind].curr * 32) + 'px 0';

		actions.unshift({ action : (door_dir>0 ? 'open' : 'close'), ind: ind });

		if (h_actions > 0) clearTimeout(h_actions);
		h_actions = setTimeout(process_actions, 50);
	}

	function process_actions()
	{
		h_actions = 0;

		while (actions.length > 0)
		{
			var item = actions.shift();

			switch (item.action)
			{
				case 'lt':
					dir = (dir + 7) % 8;
					update_chara();
					break;

				case 'rt':
					dir = (dir + 1) % 8;
					update_chara();
					break;

				case 'fw':
					move_chara(1);
					break;

				case 'bk':
					move_chara(-1);
					break;

				case 'open':
					process_door(item.ind, 1);
					return;

				case 'close':
					process_door(item.ind, -1);
					return;
			}
		}
	}

	function do_actions()
	{
		if (h_actions != 0)
		{
			clearTimeout(h_actions);
			h_actions = 0;
		}

		process_actions();
	}

	function on_keydown(e)
	{
		if (!e) e = event;

		var ok = true;
		var code = (e.which ? e.which : e.keyCode);

		switch (code)
		{
			case 37:
				if (actions.length == 0) actions.push({ action:'lt' });
				break;

			case 38:
				if (actions.length == 0) actions.push({ action:'fw' });
				break;

			case 39:
				if (actions.length == 0) actions.push({ action:'rt' });
				break;

			case 40:
				if (actions.length == 0) actions.push({ action:'bk' });
				break;

			case 32:
				if (actions.length == 0)
				{
					if (door_ind >= 0) {
						actions.push({ action: (doors[door_ind].opened ? 'close' : 'open'), ind: door_ind });
					} else if (lv > 0) {
						location.href = links[lv-1].href;
					}
				}
				break;

			default:
				ok = false;
		}

		if (ok)
		{
			key_catcher_up.focus();
			key_catcher.focus();
			do_actions();
			return false;
		}

		return true;
	}

	return {
		on_load: function()
		{
			for (var i = 1; i <= 3; i++) links.push(S.get('link-' + i));
			for (var i = 1; i <= 8; i++) arrows.push(S.get('arr-' + i).style);
			for (var i = 1; i <= 4; i++) doors[i-1].st = S.get('door-' + i).style;

			chara = S.get('chara').style;
			info = S.get('info');
			key_catcher_up = S.get('key-catcher-up');
			key_catcher = S.get('key-catcher');

			update_chara();

			S.add_handler(document, 'keydown', on_keydown);
		}
	}
}();

S.add_handler(window, 'load', Board.on_load);
