/*
  Lost In Maze! - Robby vs The Tin Toy Bots
  (c) Norbert Landsteiner 2008; www.masswerk.at
  (based on "JavaScript-PacMan 3D" (c) 1996-2007 N. Landsteiner)
  
  fixed opacity effects for MSIE 03/2009
*/

// preload & setup

var elements = new Object();

var pacimages = [
	'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'k', 'l', 'm', 'n',
	'o', 'p', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'pnt',
	'rb1', 'rb2', 'rb3', 'rf1', 'rf2', 'rf3', 'rl1', 'rl2', 'rl3', 'rr1', 'rr2', 'rr3',
	'rx0', 'rx1', 'rx2', 'rx3', 'rx4',
	'e1', 'e2', 'e4', 'e8',
	'bonus0', 'bonus1', 'bonus2', 'bonus3',
	'gameover', 'gamepaused'
];
var pacimages2 = [
	'life', 'xx', 'newgame_lo', 'newgame_hi', 'newgame_dn',
	'neon_lo', 'neon_hi'
];

var imgRef, imgCnt, imgTotal;
var imgPath='lostinmazeimages/';
var sprites;
var mspacImgsLoaded=false;

function init() {
	elements.maze=getElement('maze');
	if ((!elements.maze) || (!document.images) || (!document.createElement)) {
		if (prompt('Sorry, DOM compatible browser (Mozilla, Firefox, Internet Explorer 5+, Safari, etc) required.\n\nTry the legacy version for older browsers?\n')) {
			self.location.replace('legacy/JS-PacManPlus.htm');
		}
		return;
	}
	setVisibility(getElement('progress'), true);
	elements.scoredisplay=getElement('scoredisplay');
	elements.leveldisplay=getElement('leveldisplay');
	elements.mazedisplay=getElement('mazedisplay');
	preload();
}

function preload() {
	var i;
	for (i=0; i<10; i++) pacimages.push('b0'+i);
	for (i=10; i<=72; i++) pacimages.push('b'+i);
	imgRef=new Object();
	imgCnt=0;
	imgTotal=pacimages.length+pacimages2.length;
	for (i=0; i<pacimages.length; i++) {
		var n=pacimages[i];
		var img=imgRef[n]=new Image();
		img.src=imgPath+n+'.png';
		if (img.complete) {
			imgTotal--;
		}
		else {
			img.onload=preloadHandler;
		}
	}
	for (i=0; i<pacimages2.length; i++) {
		var n=pacimages2[i];
		var img=imgRef[n]=new Image();
		img.src=imgPath+n+'.gif';
		if (img.complete) {
			imgTotal--;
		}
		else {
			img.onload=preloadHandler;
		}
	}
	if (imgTotal==0) preloadComplete();
}

function preloadHandler() {
	imgCnt++;
	var d=getElement('progressbar');
	var v = imgCnt/imgTotal;
	d.style.width=Math.round(160*v)+'px';
	d=getElement('progressvalue');
	d.innerHTML=Math.round(v*100)+'%';
	if (imgCnt==imgTotal) setTimeout('preloadComplete()', 10);
}

function preloadComplete() {
	var d=getElement('progress');
	setVisibility(d, false);
	d.style.display='none';
	initMaze();
	initSprites();
	setVisibility(getElement('controls'), true);
	var select=getElement('mazeselect');
	select.selectedIndex=0;
	setQuality(settingsQualityValue);
	setSpeed(settingsSpeedValue);
	enableKeyboard();
	if (window.activateTouchControls) activateTouchControls();
	setTimeout('newGame()', 10);
}

function initMaze() {
	var r,c, imgsrc, i, id, x, y, z, mpr;
	var maze = elements.maze=document.getElementById('maze');
	var misieFilter="progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+imgPath+"x.png', sizingMethod='crop')";
	for (r=0; r<22; r++) {
		mpr = mazePos[r+1] = new Array();
		for (c=0; c<19; c++) {
			x= 10+(21-r)*14+c*24;
			y= 20+r*11+c*6;
			z= 1+c*6+r*114;
			mpr[c+1]= {x: x-5, y: y-18, z:z};
			id='t'+(r+1)+'_'+(c+1);
			i=document.createElement('img');
			i.id=id;
			if (msieLe6) {
				i.src=imgPath+'xx.gif';
				i.style.filter=misieFilter;
			}
			else {
				i.src=imgPath+'x.png';
			}
			i.width=28; i.height=17;
			i.style.display='block';
			i.style.position='absolute';
			i.style.left=x+'px';
			i.style.top=y+'px';
			i.style.zIndex=z;
			maze.appendChild(i);
			elements[id]=i;
		}
	}
}

function initSprites() {
	var img, id, d, gd, i;
	var maze=elements.maze;
	var xpng=imgPath+'x.png';
	var xgif= imgPath+'xx.gif';
	if (msie) {
		var misieFilter="progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+xpng+"', sizingMethod='crop')";
		var ximg=(msieLe6)? xgif:xpng;
		for (i=1; i<=4; i++) {
			id='g'+i;
			d = elements[id]=document.createElement('div');
			d.style.visibilty='hidden';
			d.style.position='absolute';
			id='igbody'+i;
			img=elements[id]=document.createElement('img');
			img.id=id;
			img.src=ximg;
			img.width=36; img.height=57;
			if (msieLe6) img.style.filter=misieFilter;
			d.appendChild(img);
			maze.appendChild(d);
			
			id='bonus'+i;
			gd = elements[id]=document.createElement('div');
			gd.style.visibilty='hidden';
			gd.style.position='absolute';
			id='ibonus'+i;
			img=elements[id]=document.createElement('img');
			img.id=id;
			img.src=ximg;
			img.width=29; img.height=10;
			if (msieLe6) img.style.filter=misieFilter;
			gd.appendChild(img);
			maze.appendChild(gd);
		}
		d = elements.pac=document.createElement('div');
		d.id='pac';
		d.style.visibilty='hidden';
		d.style.position='absolute';
		img = elements.ipac=document.createElement('img');
		img.id='ipac';
		img.src=ximg;
		img.width=45; img.height=57;
		if (msieLe6) img.style.filter=misieFilter;
		d.appendChild(img);
		maze.appendChild(d);
		sprites = {
			pac: {'div': elements.pac, 'img': elements.ipac},
			g: {
				'1': { 'div': elements.g1, 'img': elements.igbody1 },
				'2': { 'div': elements.g2, 'img': elements.igbody2 },
				'3': { 'div': elements.g3, 'img': elements.igbody3 },
				'4': { 'div': elements.g4, 'img': elements.igbody4 }
			},
			bonus: {
				'1': {'div': elements.bonus1, 'img': elements.ibonus1},
				'2': {'div': elements.bonus2, 'img': elements.ibonus2},
				'3': {'div': elements.bonus3, 'img': elements.ibonus3},
				'4': {'div': elements.bonus4, 'img': elements.ibonus4}
			}
		};
	}
	else {
		for (var i=1; i<=4; i++) {
			id='g'+i;
			img=elements[id]=document.createElement('img');
			img.id=id;
			img.src=xpng;
			img.width=36; img.height=57;
			img.style.visibilty='hidden';
			img.style.position='absolute';
			img.style.display='block';
			img.style.zIndex=1;
			maze.appendChild(img);
			
			id='bonus'+i;
			img=elements[id]=document.createElement('img');
			img.id=id;
			img.src=xpng;
			img.width=29; img.height=10;
			img.style.visibilty='hidden';
			img.style.position='absolute';
			img.style.display='block';
			maze.appendChild(img);
		}
		img = elements.pac=elements.ipac=document.createElement('img');
		img.id='pac';
		img.src=xpng;
		img.width=45; img.height=57;
		img.style.visibilty='hidden';
		img.style.position='absolute';
		img.style.display='block';
		maze.appendChild(img);
		sprites = {
			pac: {'div': elements.pac, 'img': elements.pac},
			g: {
				'1': { 'div': elements.g1, 'img': elements.g1 },
				'2': { 'div': elements.g2, 'img': elements.g2 },
				'3': { 'div': elements.g3, 'img': elements.g3 },
				'4': { 'div': elements.g4, 'img': elements.g4 }
			},
			bonus: {
				'1': {'div': elements.bonus1, 'img': elements.bonus1},
				'2': {'div': elements.bonus2, 'img': elements.bonus2},
				'3': {'div': elements.bonus3, 'img': elements.bonus3},
				'4': {'div': elements.bonus4, 'img': elements.bonus4}
			}
		};
	}
	
	d=elements.gameover=getElement('gameover');
	setVisibility(d, false);
	if (msieLe6) {
		d.innerHTML='<img id="imggameover" src="'+xgif+'" width="216" height="38" alt="">';
		document.all.imggameover.style.filter="progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+imgPath+"gameover.png', sizingMethod='scale')";
	}
	else {
		d.innerHTML='<img src="'+imgPath+'gameover.png" width="216" height="38" alt="">';
	}
	d.style.left='279px';
	d.style.top='154px';
	d.style.zIndex=2998;
	d=elements.gamepaused=getElement('gamepaused');
	setVisibility(d, false);
	if (msieLe6) {
		d.innerHTML='<img id="imggamepaused" src="'+xgif+'" width="231" height="37" alt="">'; document.all.imggamepaused.style.filter="progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+imgPath+"gamepaused.png', sizingMethod='scale')";
	}
	else {
		d.innerHTML='<img src="'+imgPath+'gamepaused.png" width="231" height="37" alt="">';
	}
	d.style.left='271px';
	d.style.top='154px';
	d.style.zIndex=2999;
	if (msieLe6 && elements.g1 && elements.g1.filters /*&& elements.g1.filters.item(0)*/) {
		setSpriteImg=setSpriteImgMsieLe6;
		setMaze=setMazeMsieLe6;
	}
	elements.restartdialog=getElement('restartdialog');
	elements.dialogscreen=getElement('dialogscreen');
	elements.dialogscreenimg=getElement('dialogscreenimg');
}

// definitions

var settingsQuality=new Array(5, 6, 7);
var settingsSpeed=new Array(258, 235, 212, 190);
var settingsQualityValue=1;
var settingsSpeedValue=1;
var aStep=6;
var aSpeed=252;
var gameDelay;

var blinkRate=4;
var blinkSteps=6;
var pillFactor=1.75;
var pillMaxLength=26;
var pillDecrement=5;
var eyesFactor=.75;
var bonusLifeScore=10000;
var useInstantTurns=true;
var allwaysStartInScatterMode=false;
var pillMinLength, bonusLength;
var ghomeOfs=16;
var dotsound;

if (typeof window.useSound == 'undefined') useSound=false;

var ghostResetDelay=20;
var ghostResetAlpha=.8;
var ghostResetDelta=.05;

var mazeMode ='Sequentially';

var highscore=0;

var f1= new Array();
var f2= new Array();
var fw= new Array();
var fft= new Array();
var fgh= new Array();
for (var i=1; i<=22; i++) {
	f1[i]=new Array();
	f2[i]=new Array();
	fw[i]=new Array();
	fft[i]=new Array();
}

var pacLevels = [
{
name: "Remember Pac-Man?",
maze: [
	'ahhhhhhhhihhhhhhhhc',
	'v........v........v',
	'vpac.ahc.v.ahc.acpv',
	'v.bd.bhd.o.bhd.bd.v',
	'v.................v',
	'v.lm.n.lhihm.n.lm.v',
	'v....v...v...v....v',
	'bhhc.ehmxoxlhg.ahhd',
	'xxxv.vxxxxxxxv.vxxx',
	'lhhd.oxautwcxo.bhhm',
	'xxxx.xxvxxxvxx.xxxx',
	'lhhc.nxbhhhdxn.ahhm',
	'xxxv.vxxxxxxxv.vxxx',
	'ahhd.oxlhihmxo.bhhc',
	'v........v........v',
	'v.lc.lhm.o.lhm.am.v',
	'vp.v.....x.....v.pv',
	'em.o.n.lhihm.n.o.lg',
	'v....v...v...v....v',
	'v.lhhfhm.o.lhfhhm.v',
	'v.................v',
	'bhhhhhhhhhhhhhhhhhd'
]
},
{
name: "Remember Ms Pac-Man &ndash; Part 1",
maze: [
	'ahhhhihhhhhhhihhhhc',
	'v....v.......v....v',
	'vplm.o.lhhhm.o.lmpv',
	'v.................v',
	'bc.n.ahc.n.ahc.n.ad',
	'ld.v.bhd.v.bhd.v.bm',
	'xx.v.....v.....v.xx',
	'lc.bhmxlhfhmxlhd.am',
	'xv.xxxxxxxxxxxxx.vx',
	'xv.ahmxautwcxlhc.vx',
	'xv.vxxxvxxxvxxxv.vx',
	'ld.oxnxbhhhdxnxo.bm',
	'xx.xxvxxxxxxxvxx.xx',
	'lc.lhfhmxnxlhfhm.am',
	'xv.....xxvxx.....vx',
	'ad.lhm.lhfhm.lhm.bc',
	'v........x........v',
	'v.ac.ahm.n.lhc.ac.v',
	'vpvv.v...v...v.vvpv',
	'v.bd.o.lhfhm.o.bd.v',
	'v.................v',
	'bhhhhhhhhhhhhhhhhhd'
]
},
{
name: "Remember Ms Pac-Man &ndash; Part 2",
maze: [
	'lhhhhihhhhhhhihhhhm',
	'xxxxxv.......vxxxxx',
	'ahhmxo.lhihm.oxlhhc',
	'vp.......v.......pv',
	'v.ahhm.n.v.n.lhhc.v',
	'v.v....v.o.v....v.v',
	'v.o.lcxv...vxam.o.v',
	'v....vxbhhhdxv....v',
	'ehhm.vxxxxxxxv.lhhg',
	'v....oxautwcxo....v',
	'v.lc.xxvxxxvxx.am.v',
	'v..v.nxbhhhdxn.v..v',
	'bc.v.vxxxxxxxv.v.ad',
	'xv.o.bmxahcxld.o.vx',
	'xv......vxv......vx',
	'ld.lhim.bhd.lihm.bm',
	'xx...v..xxx..v...xx',
	'am.n.o.lhihm.o.n.lc',
	'vp.v.....v.....v.pv',
	'v.ld.lhm.o.lhm.bm.v',
	'v.................v',
	'bhhhhhhhhhhhhhhhhhd'
]
},
{
name: "Remember Ms Pac-Man &ndash; Part 3",
maze: [
	'ahhhhhhihhhihhhhhhc',
	'v......v...v......v',
	'vpahhm.o.n.o.lhhcpv',
	'v.o......v......o.v',
	'v...n.ac.v.ac.n...v',
	'bhm.v.bd.o.bd.v.lhd',
	'x...v.........v...x',
	'n.nxbmxlhhhmxldxn.n',
	'v.vxxxxxxxxxxxxxv.v',
	'v.bmxnxautwcxnxld.v',
	'v.xxxvxvxxxvxvxxx.v',
	'v.nxldxbhhhdxbmxn.v',
	'v.vxxxxxxxxxxxxxv.v',
	'v.bmxahmxnxlhcxld.v',
	'v....v...v...v....v',
	'em.n.o.lhfhm.o.n.lg',
	'vp.v.....x.....v.pv',
	'v.ld.ahm.n.lhc.bm.v',
	'v....v...v...v....v',
	'v.lm.v.lhfhm.v.lm.v',
	'v....v.......v....v',
	'bhhhhfhhhhhhhfhhhhd'
]
},
{
name: "Remember Ms Pac-Man &ndash; Part 4",
scatterPos: [[0,0], [3,4], [17,20], [3,20], [17,4]],
maze: [
	'ahhhhhhhhhhhhhhhhhc',
	'v.................v',
	'v.n.ac.ahhhc.ac.n.v',
	'vpv.bd.v...v.bd.vpv',
	'v.v....v.n.v....v.v',
	'v.bm.n.o.v.o.n.ld.v',
	'v....v...v...v....v',
	'bc.lhyhmxoxlhyhm.ad',
	'ld...vxxxxxxxv...bm',
	'xxxn.oxautwcxo.nxxx',
	'lhhg.xxvxxxvxx.ehhm',
	'xxxo.nxbhhhdxn.oxxx',
	'lc...vxxxxxxxv...am',
	'xv.n.bhmxnxlhd.n.vx',
	'xv.v...xxvxx...v.vx',
	'ad.bhm.nxoxn.lhd.bc',
	'v......vxxxv......v',
	'v.am.n.bhhhd.n.lc.v',
	'vpv..v.......v..vpv',
	'v.o.lfhm.n.lhfm.o.v',
	'v........v........v',
	'bhhhhhhhhfhhhhhhhhd'
]
}
];

var alternateLevels= [
{
	name: 'Starry Night',
	maze: [
	'ahhhhhhhhihhhhhhhhc',
	'v........o........v',
	'vpac.ahc...ahc.acpv',
	'v.bd.bhd.n.bhd.bd.v',
	'v........v........v',
	'v.lm.n.lhyhm.n.lm.v',
	'v....v...v...v....v',
	'bc.lhyhmxoxlhyhm.ad',
	'xv...vxxxxxxxv...vx',
	'ldxn.oxautwcxo.nxbm',
	'xxxv.xxvxxxvxx.vxxx',
	'lcxo.nxbhhhdxn.oxam',
	'xv...vxxxxxxxv...vx',
	'xv.lhyhmxnxlhyhm.vx',
	'xv...vxxxvxxxv...vx',
	'afhm.oxlhfhmxo.lhfc',
	'v........x........v',
	'v.ac.n.lhihm.n.ac.v',
	'vpvv.v...v...v.vvpv',
	'v.bd.bhm.o.lhd.bd.v',
	'v.................v',
	'bhhhhhhhhhhhhhhhhhd'
]
},
{
	name: 'Classic Style',
	maze: [
	'ahhhhhihhhhhihhhhhc',
	'v.....v.....v.....v',
	'vplhc.v.ahc.v.ahmpv',
	'v...o.o.bhd.o.o...v',
	'v.n.............n.v',
	'v.bm.n.lhihm.n.ld.v',
	'v....v...v...v....v',
	'bhhc.bhmxoxlhd.ahhd',
	'xxxv.xxxxxxxxx.vxxx',
	'xxxv.nxautwcxn.vxxx',
	'lhhd.vxvxxxvxv.bhhm',
	'xxxx.oxbhhhdxo.xxxx',
	'lhhc.xxxxxxxxx.ahhm',
	'xxxv.nxlhihmxn.vxxx',
	'xxxv.v...v...v.vxxx',
	'ahhd.bhm.o.lhd.bhhc',
	'v........x........v',
	'v.am.n.lhihm.n.lc.v',
	'vpv..v...v...v..vpv',
	'v.o.ld.n.o.n.bm.o.v',
	'v......v...v......v',
	'bhhhhhhfhhhfhhhhhhd'
]
},
{
	name: 'Modern Times',
	maze: [
	'ahhhhhhhhhhhhhhhhhc',
	'v.................v',
	'vpahc.ahhhhhc.ahcpv',
	'v.bhd.o.....o.bhd.v',
	'v.......ahc.......v',
	'v.lhc.n.bhd.n.ahm.v',
	'v...v.v.....v.v...v',
	'bim.o.bhmxlhd.o.lid',
	'xv....xxxxxxx....vx',
	'ld.lhcxautwcxahm.bm',
	'xx.xxoxvxxxvxoxx.xx',
	'lc.nxxxbhhhdxxxn.am',
	'xv.bhmxxxxxxxlhd.vx',
	'ad.....lhihm.....bc',
	'v..n.n...v...n.n..v',
	'v.ld.ehm.o.lhg.bm.v',
	'v....o...x...o....v',
	'v.ac...lhihm...ac.v',
	'vpvv.n...v...n.vvpv',
	'v.bd.bhm.o.lhd.bd.v',
	'v.................v',
	'bhhhhhhhhhhhhhhhhhd'
]
},
{
	name: 'Duck Soup',
	maze: [
	'ahhhhhhhhhhhhhhhhhc',
	'v.................v',
	'vplm.lhc.n.ahm.lmpv',
	'v......o.o.o......v',
	'v.lc.n.......n.am.v',
	'v..v.bhm.n.lhd.v..v',
	'bc.o.....v.....o.ad',
	'xv...nxlhfhmxn...vx',
	'xv.nxoxxxxxxxoxn.vx',
	'ld.vxxxautwcxxxv.bm',
	'xx.ehmxvxxxvxlhg.xx',
	'lc.vxxxbhhhdxxxv.am',
	'xv.oxnxxxxxxxnxo.vx',
	'xv...vxlhihmxv...vx',
	'xv.n.o...v...o.n.vx',
	'ad.o...n.o.n...o.bc',
	'v....lhg.x.ehm....v',
	'v.am...o.n.o...lc.v',
	'v.v..n...v...n..v.v',
	'vpo.ld.lhfhm.bm.opv',
	'v.................v',
	'bhhhhhhhhhhhhhhhhhd'
]
},
{
	name: 'Yet Another Rorschach-Test',
	maze: [
	'ahhhhhhcxxxahhhhhhc',
	'v......ehhhg......v',
	'vpn.ac.v...v.ac.npv',
	'v.o.bd.o.n.o.bd.o.v',
	'v........v........v',
	'bc.lhm.n.o.n.lhm.ad',
	'xv.....v...v.....vx',
	'ld.lhcxbmxldxahm.bm',
	'xx.xxoxxxxxxxoxx.xx',
	'lc.nxxxautwcxxxn.am',
	'xv.ehmxvxxxvxlhg.vx',
	'ld.oxxxbhhhdxxxo.bm',
	'xx.xxnxxxxxxxnxx.xx',
	'lc.lhdxacxacxbhm.am',
	'xv.....vvxvv.....vx',
	'ad.lim.bdxbd.lim.bc',
	'v...v....x....v...v',
	'v.n.o.lhc.ahm.o.n.v',
	'vpv.....v.v.....vpv',
	'v.bm.lm.o.o.lm.ld.v',
	'v.................v',
	'bhhhhhhhhhhhhhhhhhd'
]
}
];


var spaceLevels = [
{
name: "The Outskirts of Saturn",
maze: [
	'ahhhhhihhhhhihhhhhc',
	'v.....o.....o.....v',
	'v.ahc...ahc...ahc.v',
	'vpvxv.n.bhd.n.vxvpv',
	'v.vxv.v.....v.vxv.v',
	'v.bhd.bm.n.ld.bhd.v',
	'v........v........v',
	'bhhc.amxlfmxlc.ahhd',
	'xxxv.vxxxxxxxv.vxxx',
	'lhhd.oxautwcxo.bhhm',
	'xxxx.xxvxxxvxx.xxxx',
	'lhhc.nxbhhhdxn.ahhm',
	'xxxv.vxxxxxxxv.vxxx',
	'xxxv.bmxlimxld.vxxx',
	'xxxv.....v.....vxxx',
	'ahhd.ahm.o.lhc.bhhc',
	'v....v...x...v....v',
	'v.am.o.lhihm.o.lc.v',
	'vpv......v......vpv',
	'v.o.lhhm.o.lhhm.o.v',
	'v.................v',
	'bhhhhhhhhhhhhhhhhhd'
]
},
{
name: "Space Station One",
maze: [
	'ahhhcahhhhhhhcahhhc',
	'v...vv.......vv...v',
	'v.n.vv.ahhhc.vv.n.v',
	'v.o.bd.bhhhd.bd.o.v',
	'v.................v',
	'v.lm.ahm.n.lhc.lm.v',
	'vp...v...v...v...pv',
	'bhhc.oxlhfhmxo.ahhd',
	'xxxv.xxxxxxxxx.vxxx',
	'lhhd.nxautwcxn.bhhm',
	'xxxx.vxvxxxvxv.xxxx',
	'lhhc.oxbhhhdxo.ahhm',
	'xxxv.xxxxxxxxx.vxxx',
	'ahhd.nxlhihmxn.bhhc',
	'v....vxxxvxxxv....v',
	'v.am.bhmxoxlhd.lc.v',
	'vpv....xxxxx....vpv',
	'v.o.lm.lhihm.lm.o.v',
	'v........v........v',
	'v.z.ac.z.o.z.ac.z.v',
	'v...vv.......vv...v',
	'bhhhdbhhhhhhhdbhhhd'
]
},
{
name: "The Martian Palace",
maze: [
	'ahhhhhhcxxxahhhhhhc',
	'v......vxxxv......v',
	'v.ac.n.bhhhd.n.ac.v',
	'opbd.o.xxxxx.o.bdpo',
	'x......ahhhc......x',
	'n.lhhm.vlhmv.lhhm.n',
	'v......vlhmv......v',
	'bc.ahc.bhhhd.ahc.ad',
	'xv.vxv.xxxxx.vxv.vx',
	'xv.bhd.autwc.bhd.vx',
	'xv.....vxxxv.....vx',
	'xv.ahc.bhhhd.ahc.vx',
	'xv.vxv.xxxxx.vxv.vx',
	'ad.bhd.ahhhc.bhd.bc',
	'v......vxxxv......v',
	'o.lhhc.bhhhd.ahhm.o',
	'x....v.xxxxx.v....x',
	'n.am.o.ahhhc.o.lc.n',
	'vpv....vahcv....vpv',
	'v.o.lm.vvkvv.lm.o.v',
	'v......vbhdv......v',
	'bhhhhhhdxxxbhhhhhhd'
]
},
{
name: "Alien Power Station",
maze: [
	'ahhhhcxahhhcxahhhhc',
	'v....vxv...vxv....v',
	'v.ac.oxo.z.oxo.ac.v',
	'vpbd...........bdpv',
	'v....nxn.n.nxn....v',
	'v.n.lgxv.v.vxem.n.v',
	'v.v..oxoxoxoxo..v.v',
	'v.bm..xxxxxxx..ld.v',
	'v....nxxxxxxxn....v',
	'bmxlhdxautwcxbhmxld',
	'xxxxxxxvxxxvxxxxxxx',
	'amxlhcxbhhhdxahmxlc',
	'v....vxxxxxxxv....v',
	'v.am.oxlhihmxo.lc.v',
	'v.v......v......v.v',
	'v.o.lihm.o.lhim.o.v',
	'v....v...x...v....v',
	'v.ac.o.lhihm.o.ac.v',
	'vpvv.....v.....vvpv',
	'v.bd.nxn.o.nxn.bd.v',
	'v....vxv...vxv....v',
	'bhhhhdxbhhhdxbhhhhd'
]
},
{
name: "Star City",
maze: [
	'ahhhcxahhhhhcxahhhc',
	'o...oxo.....oxo...o',
	'x.z.....lim.....z.x',
	'np..nxn..v..nxn..pn',
	'bm.ldxbm.o.ldxbm.ld',
	'xx...............xx',
	'am.lc.ahcxahc.am.lc',
	'v...o.bhdxbhd.o...v',
	'v.n...xxxxxxx...n.v',
	'v.bhhmxautwcxlhhd.v',
	'v.xxxxxvxxxvxxxxx.v',
	'v.ahhmxbhhhdxlhhc.v',
	'v.o...xxxxxxx...o.v',
	'v...n.amxnxlc.n...v',
	'bm.ld.vxxvxxv.bm.ld',
	'xx.xx.vxlfmxv.xx.xx',
	'am.lc.v..x..v.am.lc',
	'vp..v.v.ahc.v.v..pv',
	'o.n.o.o.vxv.o.o.n.o',
	'x.o.....bhd.....o.x',
	'n...nxn.....nxn...n',
	'bhhhdxbhhhhhdxbhhhd'
]
}
];

var levels, allLevels;

var tx= new Array();
var ty= new Array();

var t1= new Array();
t1[0]=0;
t1[1]= 9; // rd
t1[2]=10; // ld
t1[3]= 5; // ru
t1[4]= 6; // lu
t1[5]=13; // rdu
t1[6]=14; // ldu
t1[7]=11; // rld
t1[8]= 7; // rlu
t1[9]=15; // rlud
tx[0]=0;  ty[0]=0;
tx[1]=1;  ty[1]=0;  //r
tx[2]=-1; ty[2]=0;  //l
tx[4]=0;  ty[4]=-1; //u
tx[8]=0;  ty[8]=1;  //d


var t2 = new Array();
t2[0]= [0];
t2[1]= [1];
t2[2]= [2];
t2[4]= [4];
t2[8]= [8];
t2[3]= [1, 2];
t2[9]= [1, 8];
t2[10]=[2, 8];
t2[12]=[4, 8];
t2[5]= [1, 4];
t2[6]= [2, 4];
t2[7]= [1, 2, 4];
t2[11]=[1, 2, 8];
t2[13]=[1, 4, 8];
t2[14]=[2, 4, 8];
t2[15]=[1, 2, 4, 8];

var tdx=[2, 0, 1];
var tdy=[4, 0, 8];

var t3 = new Array();
t3[0]=0; t3[1]=2; t3[2]=1; t3[4]=8; t3[8]=4;

var mazePos = new Array();

var nextNodes= new Array();
var pacNext=null;
var pacLast=null;

var gHomePos= new Array([11,10], [11,9], [11,11],  [10,10] );
var gbid= new Array(1,2,4,8);
var scatterPos=new Array( [0,0], [3,3], [17,20], [3,20], [17,3]);

var g= new Array();
for (var i=1; i<=4; i++) {
	g[i]=new Ghost();
	g[i].bid=gbid[i-1];
	g[i].bm=15^gbid[i-1];
}
var pac= new Pacman();
var bonus=new Array();
	for (var i=1; i<=4; i++) bonus[i]=0;
var movedir=0;
var runThru=false;
var gameOn= false;
var pill= false;
var pillCnt= 0;
var food= 0;
var nLevel= 0;
var nLife=0;
var gStep, gStep2;
var phaseSet=true;
var bonusLifeCnt=0;
var pacInitDir=0;
var ghostInitDir=0;
var pillPeriode, pillCnt;
var isPause=false;
var restartDialogOn=false;
var gameTimer=null;
var enterTime=0;
var scatterMode, stepCnt, scatterCnt, moved;

var aSpan= new Array();
var gSpan= new Array();
var gSpan2= new Array();

var aSpan3D = new Array();
var gSpan3D= new Array();
var gSpan3D2= new Array();

var pacStr= {
	'0': ['rx0', 'rx0', 'rx0'],
	'1': ['rr1', 'rr2', 'rr3'],
	'2': ['rl1', 'rl2', 'rl3'],
	'4': ['rb1', 'rb2', 'rb3'],
	'8': ['rf1', 'rf2', 'rf3'],
	'x': ['rx1', 'rr2', 'rx2', 'rb2', 'rx3', 'rl2', 'rx4', 'rf2']
};

var ghostStr= {
	'1': {
		'0': [ 'b72', 'b71', 'b70' ],
		'1': [ 'b69', 'b68', 'b67' ],
		'2': [ 'b66', 'b65', 'b64' ],
		'8': [ 'b72', 'b71', 'b70' ],
		'4': [ 'b63', 'b62', 'b61' ]
	},
	'2': {
		'0': [ 'b60', 'b59', 'b58' ],
		'1': [ 'b57', 'b56', 'b55' ],
		'2': [ 'b54', 'b53', 'b52' ],
		'8': [ 'b60', 'b59', 'b58' ],
		'4': [ 'b51', 'b50', 'b49' ]
	},
	'3': {
		'0': [ 'b48', 'b47', 'b46' ],
		'1': [ 'b45', 'b44', 'b43' ],
		'2': [ 'b42', 'b41', 'b40' ],
		'8': [ 'b48', 'b47', 'b46' ],
		'4': [ 'b39', 'b38', 'b37' ]
	},
	'4':{
		'0': [ 'b36', 'b35', 'b34' ],
		'1': [ 'b33', 'b32', 'b31' ],
		'2': [ 'b30', 'b29', 'b28' ],
		'8': [ 'b36', 'b35', 'b34' ],
		'4': [ 'b27', 'b26', 'b25' ]
	},
	'a': {
		'0': [ 'b24', 'b23', 'b22' ],
		'1': [ 'b21', 'b20', 'b19' ],
		'2': [ 'b18', 'b17', 'b16' ],
		'8': [ 'b24', 'b23', 'b22' ],
		'4': [ 'b15', 'b14', 'b13' ]
	},
	'n': {
		'0': [ 'b12', 'b11', 'b10' ],
		'1': [ 'b09', 'b08', 'b07' ],
		'2': [ 'b06', 'b05', 'b04' ],
		'8': [ 'b12', 'b11', 'b10' ],
		'4': [ 'b03', 'b02', 'b01' ]
	},
	'x': {
		'0': [ 'e8', 'e8', 'e8' ],
		'1': [ 'e1', 'e1', 'e1' ],
		'2': [ 'e2', 'e2', 'e2' ],
		'8': [ 'e8', 'e8', 'e8' ],
		'4': [ 'e4', 'e4', 'e4' ]
	},
	'gx': 'b00'
};

var scatterPhase= [
	[0, 25],
	[60, 30],
	[60, 25],
	[90, 20]
];

var dotsounds = ['doteat1', 'doteat2', 'doteat3'];

var lifeStr='life';

var scatterPhaseCnt;

var gameStatus=0;
var statusCnt=0;
var ghostCnt=0;

var ghostBonus=new Array(200,400,800,1600);

var isSpaceTile= {
	pnt:true, x:true, p:true, s:true
};


// constructors

function Ghost() {
	this.r= 0;
	this.c= 0;
	this.s= 0;
	this.d= 0;
	this.p= 0;
	this.pn= 0;
	this.z= 0;
	this.osx=0;
	this.osy=0;
	this.posx=0;
	this.posy=0;
	this.bid=0;
	this.bm=0;
	this.alpha=1;
	this.cMovestrat=0;
	this.cMoveahead=0;
	this.joh=0;
	this.pill=false;
	this.scatter=false;
	this.scnt=0;
}

function Pacman() {
	this.r= 0;
	this.c= 0;
	this.p= 0;
	this.pn= 0;
	this.dir= pacInitDir;
	this.md= 0;
	this.dx= 0;
	this.dy= 0;
	this.osx=0;
	this.osy=0;
	this.posx=0;
	this.posy=0;
	this.reversed=false;
	this.lc='';
}


// basics

function getElement(id) {
	if (document.getElementById) return document.getElementById(id);
	if (document.all) return doucument.all[id];
	return null;
}

function setVisibility(obj, v) {
	obj.style.visibility= (v)? 'visible' : 'hidden';
}

function setOpacity(obj,v) {
	if (!obj) return;
	if (typeof obj.style.opacity != 'undefined') {
		obj.style.opacity=v;
	}
	else if (typeof obj.style.filter != 'undefined') {
		if (!obj.style.filter) {
			if (v<1) obj.style.filter='progid:DXImageTransform.Microsoft.Alpha(Opacity='+Math.floor(v*100)+')';
		}
		else {
			if (v<1) {
				var f=obj.filters.item('DXImageTransform.Microsoft.Alpha');
				f.opacity = Math.floor(v*100);
				f.enabled = true;
			}
			else {
				obj.filters.item('DXImageTransform.Microsoft.Alpha').enabled = false;
			}
		}
	}
	else if (typeof obj.style.MozOpacity != 'undefined') {
		obj.style.MozOpacity=v;
	}
	else if (typeof obj.style.KhtmlOpacity != 'undefined') {
		obj.style.KhtmlOpacity=v;
	}
}

function setImage(id, img) {
	document.images[id].src=imgRef[img].src;
}

function setSpriteImg(obj, img) {
	obj.src=imgRef[img].src;
}

function moveElement(obj,x,y,z) {
	obj.style.left=x+'px';
	obj.style.top=y+'px';
	obj.style.zIndex=z;
}

function setMaze(r,c,s) {
	elements['t'+r+'_'+c].src=imgRef[s].src;
}

// msie-pre-7 png fixes

function setSpriteImgMsieLe6(obj, img) {
	obj.filters.item(0).src=imgRef[img].src;
}

function setMazeMsieLe6(r,c,s) {
	elements['t'+r+'_'+c].filters.item(0).src=imgRef[s].src;
}


// settings

function setQuality(v) {
	var s1=aStep;
	var s2=gStep;
	var s3=gStep2;
	aStep=settingsQuality[v];
	setSpan();
	pillMinLength=pillMaxLength*aStep-8*pillDecrement;
	pillPeriode=(nLevel<6)? pillMaxLength*aStep : Math.max(pillMinLength, pillMaxLength*aStep-(nLevel-5)*pillDecrement);
	bonusLength=10*aStep;
	setImage('neon_q'+settingsQualityValue, 'neon_lo');
	setImage('neon_q'+v, 'neon_hi');
	settingsQualityValue=v;
	var cf1=aStep/s1;
	var cf2=gStep/s2;
	var cf3=gStep2/s3;
	pac.osx=Math.round(pac.osx*cf1);
	pac.osy=Math.round(pac.osy*cf1);
	for (var i=1; i<=4; i++) {
		var gi=g[i];
		if (gi.s==0) continue;
		if (gi.pill && gi.s==2) {
			gi.osx=Math.round(gi.osx*cf2);
			gi.osy=Math.round(gi.osy*cf2);
		}
		else if (gi.s==3) {
			gi.osx=Math.round(gi.osx*cf3);
			gi.osy=Math.round(gi.osy*cf3);
		}
		else {
			gi.osx=Math.round(gi.osx*cf1);
			gi.osy=Math.round(gi.osy*cf1);
		}
	}
	aSpeed=settingsSpeed[settingsSpeedValue];
	gameDelay=Math.round(aSpeed/aStep);
}

function setSpeed(v) {
	aSpeed=settingsSpeed[v];
	setImage('neon_s'+settingsSpeedValue, 'neon_lo');
	setImage('neon_s'+v, 'neon_hi');
	settingsSpeedValue=v;
	gameDelay=Math.round(aSpeed/aStep);
}

// maze & game setup

function buildMaze(lvl) {
	var r, c, d, f1r, fwr, z, m;
	if (lvl.name) {
		displayMazeName(lvl.name);
	}
	else {
		displayMazeName('');
	}
	m=lvl.maze;
	food=0;
	for (r=1; r<=22; r++) {
		fwr=fw[r];
		f1r=f1[r];
		for (c=1; c<=19; c++) {
			f1r[c]=0;
			z=m[r-1].charAt(c-1);
			if (z=='.') {
				setMaze(r,c,"pnt");
				f1r[c]=9;
				food++;
				fwr[c]=true;
			}
			else {
				setMaze(r,c,z);
				if (z=='p') {
					f1r[c]=8;
					food++;
				}
				fwr[c]=isSpaceTile[z];
			}
		}
	}
	pacInitDir=0;
	if (fw[17][9]) pacInitDir|=2;
	if (fw[17][11]) pacInitDir|=1;
	if (fw[18][10]) pacInitDir|=8;
	if (fw[16][10]) pacInitDir|=4;
	ghostInitDir=0;
	if (fw[9][9]) ghostInitDir|=2;
	if (fw[9][11]) ghostInitDir|=1;
	if (fw[8][10]) ghostInitDir|=4;
	
	// calc directions
	f2=new Array();
	for (r=1; r<=22; r++) {
		f2[r]=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];
		fgh[r]=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];
	}
	for (r=2; r<22; r++) {
		for (c=2; c<19; c++) {
			if (fw[r][c] && (r<10 || r>12 || c<8 || c>12))  {
				d=0;
				if (fw[r-1][c]) d|=4;
				if (fw[r+1][c]) d|=8;
				if (fw[r][c-1]) d|=2;
				if (fw[r][c+1]) d|=1;
				if ((d==3) || (d==12)) d=0;
				f2[r][c]=d;
			}
		}
	}
}

function calcNextNodes() {
	var dirs=t2[15];
	var fm,fr,dx,dy,x,y;
	for (var m=0; m<dirs.length; m++) {
		var d=dirs[m];
		fd=nextNodes[d]=new Array();
		for (var r=1; r<=22; r++) {
			fr=fd[r]=new Array();
			for (var c=1; c<=19; c++) {
				if (f2[r][c] & d) {
					dx=tx[d];
					dy=ty[d];
					y=r;
					x=c;
					while (true) {
						if (y==1) {fr[c]=[21,c]; break;}
						if (y==22) {fr[c]=[2,c]; break;}
						if (x==1) {fr[c]=[r,18]; break;}
						if (x==19) {fr[c]=[r,2]; break;}
						x+=dx;
						y+=dy;
						if (f2[y][x]) {fr[c]=[y,x]; break;}
					}
				}
				else {
					fr[c]=null;
				}
			}
		}
	}
}

function calcHomePaths() {
	var i, d, d2, d3, r, c, p, n;
	var paths=new Array();
	var a=t2[ghostInitDir];
	for (i=0; i<a.length; i++) {
		paths.push([9, 10, a[i]]);
	}
	while (paths.length) {
		var newpaths=new Array();
		for (i=0; i<paths.length; i++) {
			p=paths[i];
			d=p[2];
			r=p[0]+ty[d];
			c=p[1]+tx[d];
			if (r<1) {
				r=22;
			}
			else if (r>22) {
				r=1;
			}
			if (c<1) {
				c=19;
			}
			else if (c>19) {
				c=1;
			}
			if (!fgh[r][c]) {
				d2=f2[r][c];
				d3=t3[d];
				fgh[r][c]=d3;
				if (d2) {
					d2&=(15^d3);
					if (d2) {
						a=t2[d2];
						for (n=0; n<a.length; n++) {
							newpaths.push([r, c, a[n]]);
						}
					}
				}
				else {
					newpaths.push([r, c, d]);
				}
			}
		}
		paths=newpaths;
	}
}


// general


function pHome(initial, initscatter) {
	pill=false; pillCnt=0;
	movedir=0;
	with (pac) {
		r=17; c=10;
		osx=0; osy=ghomeOfs;
		md=0; dir= pacInitDir;
		dx=0; dy=0;
		pn=1; p=0;
		reversed=false;
		pacLast=[r,c];
		pacNext=null;
		lc='';
	}
	dotsound=0;
	if (moved) resetScatter();
	moved=false;
	var sp=sprites.pac;
	setOpacity(sp.div, .1);
	setSpriteImg(sp.img, pacStr[0][0]);
	var pos=mazePos[17][10];
	moveElement(sp.div, pos.x-4, pos.y+ghomeOfs+1, pos.z+5);
	if (initscatter) {
		stepCnt=0;
		scatterMode=true;
		scatterCnt=(initial)? scatterPhase[0][1] : Math.max(15, scatterPhase[0][1]-nLevel*2);
	}
	gameStatus=5;
	if (useSound) playSound((initial || nLife>1)? 'appear':'warning');
}

function gHome(i, initial, up) {
	with (g[i]) {
		for (var k=0; k<gHomePos.length; k++) {
			if (tileFree(i,gHomePos[k][0],gHomePos[k][1])) {
				r=gHomePos[k][0];
				c=gHomePos[k][1];
				break
			}
		};
		osx=0;
		osy=(up)? ghomeOfs:-ghomeOfs;
		s=5;
		p=0; pn=1;
		z= (initial)? Math.max(3, 8-nLevel):2+getRand(3);
		d=0;
		pill=false;
		joh=3;
		alpha=1;
		scatter=scatterMode;
		scnt=0;
		setGhost(i,r,c);
	}
	var gs=sprites.g[i];
	setOpacity(gs.div, .1);
	setVisibility(gs.div, true);
}

function newGame() {
	if (gameTimer) clearTimeout(gameTimer);
	isPause=false;
	setRestartDialogVisible(false);
	setVisibility(elements.gameover, false);
	setVisibility(elements.gamepaused, false);
	if (msie) {
		setVisibility(elements.maze,true);
	}
	else {
		setOpacity(elements.maze, 1);
	}
	switch (mazeMode) {
		case 'PacLevels':
			levels=pacLevels;
			break;
		case 'AlternateLevels':
			levels=alternateLevels;
			break;
		case 'SpaceLevels':
			levels=spaceLevels;
			break;
		case 'Shuffle':
		case 'Sequentially':
		default:
			if (!allLevels) allLevels=spaceLevels.concat(alternateLevels, pacLevels);
			if (mazeMode=='Shuffle') {
				var b=new Array();
				for (var i=0; i<allLevels.length; i++) b.push({ r: Math.random(), i:i });
				b.sort(levelSorter);
				levels=new Array();
				for (var i=0; i<b.length; i++) levels.push( allLevels[b[i].i] );
			}
			else {
				levels=allLevels;
			}
			break;
	}
	nLife=3;
	setImage('life1',lifeStr);
	setImage('life2',lifeStr);
	setImage('life3','xx');
	setImage('life4','xx');
	setImage('life5','xx');
	nScore=0;
	nLevel=0;
	displayLevel();
	displayScore();
	bonusLifeCnt=0;
	startLevel();
	gameTimer=setTimeout('gameStep()', gameDelay);
}

function levelSorter(a,b) {
	return a.r-b.r;
}

function startLevel() {
	gameOn=false;
	moved=false;
	setVisibility(sprites.pac.div, false);
	for (i=1; i<=4; i++) {
		setVisibility(sprites.g[i].div, false);
		setVisibility(sprites.bonus[i].div, false);
		bonus[i]=0;
	}
	runThru=false;
	nLevel++;
	displayLevel();
	displayScore();
	statusCnt=0;
	var cl=nLevel/10;
	g[1].cMovestrat=Math.min(0.85, 0.55+cl);
	g[1].cMoveahead=1;
	g[2].cMovestrat=Math.min(0.75, 0.25+cl);
	g[2].cMoveahead=Math.min(0.65, 0.15+cl);
	g[3].cMovestrat=Math.min(0.7, 0.2+cl);
	g[3].cMoveahead=Math.min(0.5, 0.1+cl);
	g[4].cMovestrat=Math.min(0.85, 0.6+cl);
	g[4].cMoveahead=-1;
	
	pGstrat=Math.min(0.75, 0.25+nLevel/10);
	pGstrat2=Math.min(0.85, 0.5+nLevel/5);
	pGsLookahead=Math.min(0.6, 0.2+nLevel/10);
	pillPeriode=(nLevel<6)? pillMaxLength*aStep : Math.max(pillMinLength, pillMaxLength*aStep-(nLevel-5)*pillDecrement);
	buildMaze(levels[(nLevel-1)%levels.length]);
	calcNextNodes();
	calcHomePaths();
	for (var r=1; r<=22; r++) {
		for (var c=1; c<=19; c++) {
			fft[r][c]=0;
		}
	}
	scatterPhaseCnt=0;
	phaseSet=true;
	pHome(true, true);
	for (var i=1; i<=4; i++) gHome(i, true, true);
	pac.lfx=pac.lfy=0;
	setVisibility(sprites.pac.div, true);
	gameOn=true;
}

function setSpan() {
	for (var n=1-aStep; n<aStep; n++) aSpan[n]= (n==0)? 0 : n/aStep;
	gStep=Math.round(aStep*pillFactor);
	for (n=1-gStep; n<gStep; n++) gSpan[n]= (n==0)? 0 : n/gStep;
	gStep2=Math.round(aStep*eyesFactor);
	for (n=1-gStep2; n<gStep2; n++) gSpan2[n]= (n==0)? 0 : n/gStep2;
	
	var min, a, r, c, dx, dy;
	min=1-aStep;
	for (r=min; r<aStep; r++) {
		a=aSpan3D[r]=new Array();
		dx= (r==0)? 0:-14*r/aStep;
		dy= (r==0)? 0:11*r/aStep;
		for (c=min; c<aStep; c++) {
			if (c==0) {
				a[c]= { x: Math.round(dx), y: Math.round(dy) };
			}
			else {
				a[c] = { x: Math.round(dx + 24*c/aStep), y: Math.round(dy+6*c/aStep) };
			}
		}
	}
	min=1-gStep;
	for (r=min; r<gStep; r++) {
		a=gSpan3D[r]=new Array();
		dx= (r==0)? 0:-14*r/gStep;
		dy= (r==0)? 0:11*r/gStep;
		for (c=min; c<gStep; c++) {
			if (c==0) {
				a[c]= { x: Math.round(dx), y: Math.round(dy) };
			}
			else {
				a[c] = { x: Math.round(dx + 24*c/gStep), y: Math.round(dy+6*c/gStep) };
			}
		}
	}
	min=1-gStep2;
	for (r=min; r<gStep2; r++) {
		a=gSpan3D2[r]=new Array();
		dx= (r==0)? 0:-14*r/gStep2;
		dy= (r==0)? 0:11*r/gStep2;
		for (c=min; c<gStep2; c++) {
			if (c==0) {
				a[c]= { x: Math.round(dx), y: Math.round(dy) };
			}
			else {
				a[c] = { x: Math.round(dx + 24*c/gStep2), y: Math.round(dy+6*c/gStep2) };
			}
		}
	}
}

function limitOffsets(obj,limit) {
	if (obj.osx>=limit) obj.osx=limit-1;
	if (obj.osy>=limit) obj.osy=limit-1;
	if (obj.osx<=-limit) obj.osx=1-limit;
	if (obj.osy<=-limit) obj.osy=1-limit;
}

function getRand(x) {
	return Math.floor(Math.random() * x);
}

function trunkBy(v,m) {
	v%=m;
	return (v==0)? m:v;
}

function tileFree(n, r,c) {
	if (n) {
		return (fft[r][c]&g[n].bm)? false:true;
	}
	else {
		return (fft[r][c])? false:true;
	}
}

function isCollision(x1,y1,x2,y2, radius) {
	return (Math.abs(x1-x2)+Math.abs(y1-y2)<radius);
}

function addScore(n) {
	nScore+=n;
	bonusLifeCnt+=n;
	if (bonusLifeCnt>=bonusLifeScore) {
		bonusLife();
		bonusLifeCnt-=bonusLifeScore;
	}
	displayScore();
}

function displayLevel() {
	elements.leveldisplay.innerHTML=nLevel;
}

function displayScore() {
	elements.scoredisplay.innerHTML=nScore;
}

function displayMazeName(t) {
	elements.mazedisplay.innerHTML=(t)? 'Now playing: &raquo;'+t+'&laquo;' : '';
}


// main

function gameStep() {
	if (gameTimer) clearTimeout(gameTimer);
	var now=new Date();
	enterTime=now.getTime();
	if (gameOn) {
		phaseSet=(!phaseSet);
		if (moved && !pill && gameStatus==0 && ++stepCnt>=aStep) {
			stepCnt=0;
			if (--scatterCnt<0) setScatter();
		}
		switch(gameStatus) {
			case 0: doMove(); break;
			case 1: resetGhost(); break;
			case 2: resetPac(); return;
			case 3: endLevel(); break;
			case 4: startLevel(); break;
			case 5: enterPac(); break;
		}
	}
	if (gameOn || isPause) gameTimer=setTimeout('reLoop()', 1);
}

function reLoop() {
	if (gameTimer) clearTimeout(gameTimer);
	var now=new Date();
	var delay = gameDelay + enterTime - now.getTime();
	gameTimer=setTimeout('gameStep()', (delay>0)? delay:1);
}

function setScatter() {
	if (scatterMode) {
		if (scatterPhaseCnt < scatterPhase.length-1) scatterPhaseCnt++;
		scatterMode=false;
		scatterCnt=scatterPhase[scatterPhaseCnt][0]+nLevel*10;
		for (var i=1; i<=4; i++) {
			g[i].scnt=0;
			g[i].scatter=false;
		}
	}
	else {
		scatterMode=true;
		scatterCnt=Math.max(10, scatterPhase[scatterPhaseCnt][1] - (nLevel-1));
		for (var i=1; i<=4; i++) {
			g[i].scnt=0;
			g[i].scatter=true;
		}
	}
}

function resetScatter() {
	if (scatterMode) {
		setScatter();
	}
	else {
		scatterCnt=scatterPhase[scatterPhaseCnt][0]+nLevel*10;
	}
}

function enterPac() {
	var sp=sprites.pac;
	pac.osy--;
	if (pac.osy==0) {
		setOpacity(sp.div,1);
		pac.osy=0;
		gameStatus=0;
	}
	else {
		setOpacity(sp.div, .1+.9*(1-(pac.osy/ghomeOfs)));
	}
	var p = mazePos[pac.r][pac.c];
	moveElement(sp.div, p.x-4, p.y+pac.osy+1, p.z+5);
	gmove();
}

function doMove() {
	var sb=sprites.bonus;
	for (var i=1; i<=4; i++) {
		if (bonus[i]>0) {
			bonus[i]--;
			if (bonus[i]==0) {
				setVisibility(sb[i].div, false);
			}
			else {
				setOpacity(sb[i].div, bonus[i]/bonusLength);
			}
		}
	}
	with (pac) {
		if (osx+osy==0) {
			pMove();
		}
		else if (useInstantTurns && reversed==false && movedir && movedir==t3[md] && f1[r][c]==0) {
			if (dx) dx=-dx;
			if (dy) dy=-dy;
			md=t3[md];
			movedir=0;
			reversed=true;
			var temp=pacNext;
			pacNext=pacLast;
			pacLast=temp;
			touchX=window.touchLastX;
			touchY=window.touchLastY;
		}
		if (runThru) {
			osx+=dx;
			osy+=dy;
			if ((c+dx)%20==0) osx=0;
			if ((r+dy)%23==0) osy=0;
			osx%=aStep;
			osy%=aStep;
			if (reversed==false) {
				if (osx==0) c=trunkBy(c+dx,19);
				if (osy==0) r=trunkBy(r+dy,22);
			};
			if (phaseSet) {
				p+=pn;
				if (p==2) pn=-1;
				if (p==0) pn=1;
			};
			setPac(r,c,pacStr[md][p]);
			if (osx+osy==0 && f2[r][c]) dir=f2[r][c];
		}
	}
	var r=pac.r+Math.round(pac.osy/aStep*.75);
	var c=pac.c+Math.round(pac.osx/aStep*.75);
	if (f1[r][c]>=8) {
		setMaze(r,c,'x');
		if (f1[r][c]==8) {
			pill=true;
			for (var i=1; i<=4; i++) {
				var gi=g[i];
				if (!gi.pill && gi.s<3) {
					gi.pill=true;
					translateGPos(i,false);
				}
			}
			pillCnt=pillPeriode;
			addScore(40);
			ghostCnt=0;
			if (useSound) playSound('pillbeam');
			if (scatterMode) setScatter();
		}
		else {
			addScore(15);
			if (useSound) {
				playSound((dotsounds[dotsound])?'doteat1':'doteat2');
				dotsound=(dotsound+1)%3;
			}
		}
		f1[r][c]=0;
		food--;
		if (food==0) {
			statusCnt=blinkSteps*blinkRate;
			gameStatus=3;
			g[1].alpha=.75;
			for (i=1; i<=4; i++) {
				var gs=sprites.g[i];
				setOpacity(gs.div, .75);
			}
			if (useSound) playSound('endlevel');
			return;
		}
	}
	gmove();
	checkHits();
	if (gameStatus>0) return;
	if (pill) {
		pillCnt--;
		if (pillCnt==0) {
			pill=false;
			for (i=1; i<=4; i++) {
				var gi=g[i];
				if (gi.pill) {
					gi.pill=false;
					if (gi.s!=4) translateGPos(i,true);
				}
			}
		}
	}
}


// pacman

function setPac(r,c,s) {
	pac.posx=c+aSpan[pac.osx];
	pac.posy=r+aSpan[pac.osy];
	if (s!=pac.lc) {
		setSpriteImg(sprites.pac.img, s);
		pac.lc=s;
	}
	var p = mazePos[r][c];
	var ofs = aSpan3D[pac.osy][pac.osx];
	moveElement(sprites.pac.div, p.x+ofs.x-4, p.y+ofs.y+1, p.z+5);
}

function pMove() {
	with (pac) {
		if (dir&movedir) {
			md= dir&movedir;
			touchX=window.touchLastX;
			touchY=window.touchLastY;
			moved=true;
		}
		else {
			md&=dir;
			if (md==0) runThru=false;
		}
		if (md) {
			runThru=true;
			dx=(md&3);
			dy=(md&12);
			if (dx) {
				dir=3;
				dx=tx[dx];
			}
			if (dy) {
				dir=12;
				dy=ty[dy];
			}
		}
		reversed=false;
		if (f2[r][c]) {
			setPacNextNode();
			pacLast=[r,c];
		}
	}
}

function setPacNextNode() {
	with (pac) {
		if (md) {
			var n=nextNodes[md][r][c];
			if (n) {
				var d=f2[n[0]][n[1]] & (15^t3[md]);
				while (d && t2[d].length<2) {
					var nn=nextNodes[d][n[0]][n[1]];
					if (nn) {
						n=nn;
						d=f2[n[0]][n[1]] & (15^t3[d]);
					}
					else {
						break;
					}
				}
				pacNext=n;
				return;
			}
		}
		pacNext=null;
	}
}


// ghosts

function setGhost(i,r,c) {
	var eyes;
	var gi=g[i];
	var s=gi.s;
	var gc, ofs;
	var p = mazePos[gi.r][gi.c];
	if (gi.pill && s<3) {
		if (s==0) {
			gi.posx=c;
			gi.posy=r;
			ofs = {x:0,y:0};
		}
		else {
			gi.posx=c+gSpan[gi.osx];
			gi.posy=r+gSpan[gi.osy];
			ofs=gSpan3D[gi.osy][gi.osx];
		}
		if (pillCnt>4*aStep) {
			gc=ghostStr.a;
		}
		else {
			gc=(pillCnt%6<3)? ghostStr.n:ghostStr.a;
		}
	}
	else if (s==0) {
		gi.posx=c;
		gi.posy=r;
		ofs = {x:0,y:0};
		gc=ghostStr[i];
	}
	else if (s==3) {
		gi.posx=c+gSpan2[gi.osx];
		gi.posy=r+gSpan2[gi.osy];
		ofs=gSpan3D2[gi.osy][gi.osx];
		gc=ghostStr.x;
	}
	else if (s==5) {
		gs=sprites.g[i];
		setSpriteImg(gs.img, ghostStr[i][8][0]);
		moveElement(gs.div, p.x, p.y+gi.osy, p.z+i);
		fft[gi.r][gi.c]|=gi.bid;
		return;
	}
	else {
		gi.posx=c+aSpan[gi.osx];
		gi.posy=r+aSpan[gi.osy];
		ofs=aSpan3D[gi.osy][gi.osx];
		gc=ghostStr[i];
	}
	var gs=sprites.g[i];
	if (s==0) {
		setSpriteImg(gs.img, gc[8][gi.p]);
	}
	else {
		setSpriteImg(gs.img, gc[gi.d][gi.p]);
	}
	if (s<3) fft[gi.r][gi.c]|=gi.bid;
	moveElement(gs.div, p.x+ofs.x, p.y+ofs.y, p.z+i);
}

function gmove() {
	for (i=1; i<=4; i++) {
		if (gameOn) {
			with (g[i]) {
				fft[r][c]&=bm;
				if (phaseSet) {
					p+=pn;
					if (p==2) pn=-1;
					if (p==0) pn=1;
				}
				switch (s) {
					case 1: gMove1(i); break;
					case 2: gMove2(i); break;
					case 3: gMove3(i); break;
					case 4: gMove4(i); break;
					case 5: gMove5(i); break;
					default: gMove0(i); break;
				}
			}
		}
		if (g[i].s!=4) displayGhost(i);
	}
}

function displayGhost(i) {
	with (g[i]) {
		setGhost(i,r,c);
	}
}

function gMove0(i) {
	with (g[i]) {
		if (moved) {
			if (r==10 && tileFree(i,9,10)) {
				s++;
				d=4;
				z=0;
			}
			if (r==11 && c==10 && tileFree(i,10,10)) {
				if (z==0) {
					d=4;
					if (--osy==-aStep) {
						osy=0;
						r=10;
					}
				}
				else if (stepCnt==0) {
					z--;
				}
			}
			else if (r==11 && c==9 && tileFree(i,11,10)) {
				d=2;
				if (++osx==aStep) {
					osx=0;
					c=10;
				}
			}
			else if (r==11 && c==11 && tileFree(i,11,10)) {
				if (--osx==-aStep) {
					osx=0;
					c=10;
				}
			}
		}
	}
}

function gMove1(i) {
	with (g[i]) {
		if (tileFree(i,9,10)) {
			if (osy==0) osy--
			else {
				osy--;
				if (osy==-aStep) {
					r=9;
					c=10;
					osx=osy=0;
					if (scatter) {
						gmoveScatter(i, ghostInitDir);
					}
					else {
						d=t2[ghostInitDir][getRand(t2[ghostInitDir].length)];
					}
					s++;
				}
			}
		}
	}
}

function gMove2(i) {
	with (g[i]) {
		if (osx+osy==0) {
			var x= f2[r][c];
			if (joh) {
				joh--;
				x&=11;
			}
			if (x>0) {
				var gdm= x&(15^t3[d]);
				if (scatter && !pill) {
					gmoveScatter(i,gdm);
				}
				else if (i==3 && !pill && scatterCnt%4) {
					var delta=Math.abs(pac.r-r)+Math.abs(pac.c-c);
					if (delta>10 || Math.random()>=cMovestrat) {
						gmoveRand(i,gdm);
					}
					else {
						gmoveStrat(i,gdm);
					}
				}
				else if (Math.random()<cMovestrat) {
					gmoveStrat(i,gdm);
				}
				else {
					gmoveRand(i,gdm);
				}
			}
			if (d>0) {
				if (tileFree(i,trunkBy(r+ty[d],22),trunkBy(c+tx[d],19))) {
					gSet(i);
				}
				else {
					reverseStuck(i,x);
				}
			}
		}
		else {
			gSet(i);
		}
	}
}

function gMove3(i) {
	with (g[i]) {
		if (osx+osy==0) {
			if (r==9 && c==10) {
				setVisibility(sprites.g[i].div, false);
				gHome(i, false, false);
				return;
			}
			d= fgh[r][c];
		}
		gSet(i);
	}
}

function gMove4(i) {
	var gi=g[i];
	gi.z--;
	var gs=sprites.g[i];
	if (gi.z==0) {
		gi.s=3;
		var cf=gStep2/gStep;
		gi.osx=Math.round(gi.osx*cf);
		gi.osy=Math.round(gi.osy*cf);
		var hd = fgh[gi.r][gi.c];
		if (((gi.d & 3) && (hd & 3)) || ((gi.d & 12) && (hd & 12))) gi.d=hd;
		setGhost(i,gi.r,gi.c);
		setSpriteImg(gs.img, ghostStr.x[gi.d][0]);
		setOpacity(gs.div,1);
	}
	else {
		gi.alpha-= (gi.z<ghostResetDelay/2)? ghostResetDelta*2 : ghostResetDelta;
		setOpacity(gs.div, gi.alpha);
		var st=sprites.g[i].div.style;
		st.top=(parseInt(st.top)+1)+'px';
	}
}

function gMove5() {
	var gi=g[i];
	gi.osy+= (gi.osy>0)? -1:1;
	if (gi.osy==0) {
		setOpacity(sprites.g[i].div,1);
		gi.osy=0;
		gi.s=0;
		gi.p=Math.floor(Math.random()*3);
		gi.pn = (gi.p==2)? -1:1;
	}
	else {
		var a=.1+.9*(1-Math.abs(gi.osy)/ghomeOfs);
		setOpacity(sprites.g[i].div, a*a);
	}
}

function gSet(i) {
	with (g[i]) {
		osy+=ty[d];
		osx+=tx[d];
		if (s==3) {
			osx%=gStep2;
			osy%=gStep2;
		}
		else if (pill && s==2) {
			osx%=gStep;
			osy%=gStep;
		}
		else {
			osx%=aStep;
			osy%=aStep;
		}
		if ((c==1 && tx[d]==-1) || (c==19 && tx[d]==1)) osx=0;
		if ((r==1 && ty[d]==-1) || (r==22 && ty[d]==1)) osy=0;
		if (osx==0) c=trunkBy(c+tx[d],19);
		if (osy==0) r=trunkBy(r+ty[d],22);
	}
}

function gmoveRand(i,k) {
	g[i].d=t2[k][getRand(t2[k].length)];
}

function gmoveStrat(i,gdm) {
	var desx, desy, px, py;
	var gi=g[i];
	if (gi.pill) {
		desy=gi.r-pac.r;
		desx=gi.c-pac.c;
	}
	else if (pacNext && Math.random()<gi.cMoveahead) {
		py=pacNext[0];
		px=pacNext[1];
		desy=py-gi.r;
		desx=px-gi.c;
		if (desx==0 && desy==0) {
			desy=pac.r-gi.r;
			desx=pac.c-gi.c;
		}
	}
	else {
		desy=pac.r-gi.r;
		desx=pac.c-gi.c;
	}
	var nd=0;
	if (desx!=0) nd= (desx>0)? 1:2;
	if (desy!=0) nd|= (desy>0)? 8:4;
	nd&=gdm;
	gmoveRand(i, (nd)? nd:gdm);
}

function gmoveScatter(i,gdm) {
	var gi=g[i];
	var p=scatterPos[i];
	var desx=p[0]-gi.c;
	var desy=p[1]-gi.r;
	if (gi.scnt) {
		if (--gi.scnt==0) gi.scatter=false;
	}
	else if (Math.abs(desx)+Math.abs(desy)<3) {
		gi.scnt=4;
	}
	var nd=0;
	if (desx!=0) nd= (desx>0)? 1:2;
	if (desy!=0) nd|= (desy>0)? 8:4;
	var dxy=Math.abs(desx)-Math.abs(desy);
	nd&=gdm;
	if (dxy<-2 && nd&12) {
		nd&=12;
	}
	else if (dxy>2 && nd&3) {
		nd&=3;
	}
	gmoveRand(i,(nd)? nd:gdm);
}

function reverseStuck(i,x) {
	with (g[i]) {
		if (x==0) {
			if (tileFree(i,trunkBy(r-ty[d],22),trunkBy(c-tx[d],19))) d=t3[d];
		}
		else {
			var vd= t2[x][getRand(t2[x].length)];
			if (tileFree(i,r+ty[vd],c+tx[vd])) {
				d=vd;
				gSet(i);
			}
		}
	}
}

function translateGPos(i,reset) {
	with (g[i]) {
		if (s==3) return;
		if ((reset) && (s==2)) {
			osx= Math.round(osx/pillFactor-tx[d]*.1);
			osy= Math.round(osy/pillFactor-ty[d]*.1);
			limitOffsets(g[i], aStep);
		}
		else if (s==2) {
			osx= Math.round(osx*pillFactor+tx[d]*.1);
			osy= Math.round(osy*pillFactor+ty[d]*.1);
			limitOffsets(g[i], gStep);
		}
	}
}

// hit-test

function checkHits() {
	var crash=false;
	var ghostcatch=false;
	for (i=1; i<=4; i++) {
		var gi=g[i];
		if (gi.s==2 && isCollision(gi.posx,gi.posy, pac.posx,pac.posy, 0.9)) {
			var gs=sprites.g[i];
			if (gi.pill) {
				bonus[i]=bonusLength;
				var b=sprites.bonus[i];
				var pos = mazePos[gi.r][gi.c];
				var ofs=gSpan3D[gi.osy][gi.osx];
				var ofs2 = i*3;
				moveElement(b.div, pos.x+ofs.x+ofs2+9, pos.y+ofs.y-ofs2+12, pos.z+5);
				setSpriteImg(b.img, 'bonus'+ghostCnt);
				setOpacity(b.div, 1);
				setVisibility(b.div, true);
				addScore(ghostBonus[ghostCnt]);
				if (ghostCnt<3) ghostCnt++;
				translateGPos(i,true);
				setSpriteImg(gs.img, ghostStr.gx);
				setOpacity(gs.div, ghostResetAlpha);
				gi.alpha=ghostResetAlpha;
				gi.z=ghostResetDelay;
				gi.s=4;
				fft[gi.r][gi.c]&=gi.bm;
				ghostcatch=true;
			}
			else {
				crash=true;
				setOpacity(gs.div, .5);
			}
		}
	}
	if (crash) {
		setSpriteImg(sprites.pac.img, 'rx0');
		pac.p=0;
		gameStatus=2;
		if (useSound) playSound('pacend');
	}
	else if (ghostcatch) {
		gameStatus=1;
		statusCnt=2;
		if (useSound) playSound('ghostcatch');
	}
}

function resetGhost() {
	statusCnt--;
	if (statusCnt==0) gameStatus=0;
}

function resetPac() {
	if (gameTimer) clearTimeout(gameTimer);
	pac.p++;
	if (pac.p<=25) {
		var sp=sprites.pac;
		if (pac.p>1) setSpriteImg(sp.img, pacStr.x[pac.p%8]);
		setOpacity(sp.div, 1-pac.p/25);
		var st=sp.div.style;
		st.top=(parseInt(st.top)+1)+'px';
		gameTimer=setTimeout('resetPac()', 98-pac.p);
	}
	else {
		nLife--;
		if (nLife>0) {
			setImage('life'+nLife,'xx');
			pHome(false, allwaysStartInScatterMode);
			for (var i=1; i<=4; i++) {
				var gi=g[i];
				fft[gi.r][gi.c]&=gi.bm;
				gHome(i, false, true);
			}
			gameTimer=setTimeout('gameStep()', 100);
		}
		else gameOver();
	}
}

function bonusLife() {
	if (nLife<6) {
		setImage('life'+nLife,lifeStr);
		nLife++;
		if (useSound) playSound('bonuslife');
	}
}

function gameOver() {
	gameOn=false;
	gameStatus=-1;
	setOpacity(elements.gameover, .1);
	setVisibility(elements.gameover, true);
	setVisibility(sprites.pac.div, false);
	setVisibility(elements.gamepaused, false);
	for (var i=1; i<=4; i++) {
		var gs=sprites.g[i];
		setOpacity(gs.div, .6);
	}
	statusCnt=.1
	gameTimer=setTimeout('showGameOver()', 8);
	if (useSound) playSound('scifi');
}

function showGameOver() {
	if (statusCnt<1) {
		statusCnt+=.01;
		setOpacity(elements.gameover, statusCnt);
		gameTimer=setTimeout('showGameOver()', 8);
	}
}

function endLevel() {
	if (statusCnt>0) {
		var a=g[1].alpha-=.015;
		for (var i=1; i<=4; i++) {
			setOpacity(sprites.g[i].div, a);
		}
		if (statusCnt%blinkRate==0) {
			if (msie || window.opera) {
				setVisibility(elements.maze, ((statusCnt/blinkRate)%2==blinkSteps%2)? false:true);
			}
			else {
				if ((statusCnt/blinkRate)%2==blinkSteps%2) {
					setOpacity(elements.maze, 0.6);
				}
				else {
					setOpacity(elements.maze, 1);
				}
			}
		}
		statusCnt--;
		if (statusCnt==0) {
			if (msie || window.opera) {
				setVisibility(elements.maze,true);
			}
			else {
				setOpacity(elements.maze, 1);
			}
			for (var i=1; i<=4; i++) setVisibility(sprites.g[i].div, false);
			setPac(pac.r, pac.c, pacStr[pac.md][2]);
			statusCnt--;
			if (useSound) playSound('leavelevel');
		}
	}
	else {
		var st=sprites.pac.div.style;
		var p=parseInt(st.top)-4;
		st.top=p+'px';
		if (p<=0) {
			statusCnt=0;
			gameStatus=4;
		}
		else if (p<40) {
			setOpacity(sprites.pac.div, p/40);
		}
	}
}

function doPause() {
	if (gameStatus>=0) {
		if (gameOn) {
			setVisibility(elements.gamepaused, true);
			gameOn=false;
			isPause=true;
		}
		else {
			setVisibility(elements.gamepaused, false);
			gameOn=true;
			isPause=false;
		}
	}
}

function showRestartDialog() {
	if (gameTimer) clearTimeout(gameTimer);
	setRestartDialogVisible(true);
}

function hideRestartDialog(ok) {
	setRestartDialogVisible(false);
	if (ok) {
		setTimeout('newGame()', 10);
	}
	else {
		setTimeout('reLoop()', 10);
	}
}

function setRestartDialogVisible(v) {
	setVisibility(elements.restartdialog, v);
	setVisibility(elements.dialogscreen, v);
	elements.dialogscreen.display= (v)? 'block':'none';
	if (v) setOpacity(elements.dialogscreenimg, .25);
	restartDialogOn=v;
}


// keyboard

function enableKeyboard() {
	if (document.addEventListener) document.addEventListener("keypress", keyHandler, true)
	else {
		if (self.Event && self.Event.KEYPRESS) document.captureEvents(Event.KEYPRESS);
		document.onkeypress = keyHandler;
	}
	window.document.onkeydown=keyFix;
}

function keyFix(e) {
	// remap some keyCodes
	if (window.event) {
		if (window.event.ctrlKey || window.event.metaKey || window.event.altKey) return true;
		var k=window.event.keyCode;
		if (k==8) keyHandler({which:8})
		else if (k==37) keyHandler({which:28})
		else if (k==39) keyHandler({which:29})
		else if (k==38) keyHandler({which:30})
		else if (k==40) keyHandler({which:31})
		//else if (k==27) keyHandler({which:27})
		else if (k>=57373 && k<=57376) {
			if (k==57373) keyHandler({which:30})
			else if (k==57374) keyHandler({which:31})
			else if (k==57375) keyHandler({which:28})
			else if (k==57376) keyHandler({which:29});
		}
		else {
			window.event.cancleBubble=false;
			return true;
		}
		if (window.event.preventDefault) window.event.preventDefault();
		if (window.event.stopPropagation) window.event.stopPropagation();
		window.event.cancleBubble=true;
		window.event.returnValue=false;
		return false;
	}
	return true;
}

var keyLock=false;

function keyHandler(e) {
	if (keyLock) return;
	var k;
	var ctrl=false;
	if (e) {
		k=e.which;
		ctrl=(e.ctrlKey || e.metaKey || e.altKey || e.metaKey || e.modifiers);
	}
	else if (window.event) {
		k=window.event.keyCode;
		ctrl= (window.event.ctrlKey || window.event.altKey || window.event.metaKey);
	}
	else return true;
	if (ctrl)  return true;
	if (k=='') {
		// map specials
		if (e==null) e=window.event;
		if (e.charCode==0 && e.keyCode) {
			if (e.keyCode==37) k=28
			else if (e.keyCode==39) k=29
			else if (e.keyCode==38) k=30
			else if (e.keyCode==40) k=31
			else if (e.keyCode==27) k=27;
		}
	}
	var ch= (k>=32 && k<127)? String.fromCharCode(k):'';
	ch=ch.toLowerCase();
	
	if (restartDialogOn) {
		if (ch=='n' || k==27) {
			hideRestartDialog(false);
		}
		else if (ch=='y' || k==13) {
			hideRestartDialog(true);
		}
	}
	else {
		if (ch=="8" || ch=="w" || ch=="i" || k==30) {
			movedir=4;
		}
		else if (ch=="4" || ch=="a" || ch=="j" || k==28) {
			movedir=2;
		}
		else if (ch=="6" || ch=="d" || ch=="l" || k==29) {
			movedir=1;
		}
		else if (ch=="5" || ch=="s" || ch=="k" || k==31 || ch=="2" || k==98) {
			movedir=8;
		}
		else if (ch=="p" || k==27) {
			doPause();
		}
		else if (ch=="n") {
			if ((gameOn || isPause) && nScore>0) {
				showRestartDialog();
			}
			else {
				newGame();
			}
		}
	}
	
	if (window.event) e=window.event;
	if (e.preventDefault) e.preventDefault();
	if (e.stopPropagation) e.stopPropagation();
	e.cancleBubble=true;
	e.returnValue=false;
	return false;
}

// trigger

setTimeout('init()', 500);


onunload=function() { elements=sprites=null; }

// eof