﻿// Cloned Tetris
// Pontuação:
// nivel	1 linha		2 linhas		3 linhas		4 linhas
// n		40 * (n + 1)		100 * (n + 1)		300 * (n + 1)	1200 * (n + 1) 
// Performance para Opera:
//  http://dev.opera.com/articles/view/efficient-javascript/
// Performance para IE:
//  http://blogs.msdn.com/ie/archive/2006/08/28/728654.aspx
//  http://blogs.msdn.com/ie/archive/2006/11/16/ie-javascript-performance-recommendations-part-2-javascript-code-inefficiencies.aspx
//  http://blogs.msdn.com/ie/archive/2007/01/04/ie-jscript-performance-recommendations-part-3-javascript-code-inefficiencies.aspx
// Para não perder: http://developer.mozilla.org/En/Other_JavaScript_tools

/* data urls... */
srcPearl = 'data:image/png;base64,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'+
	'AAAASUVORK5CYII=';

/* Overrides... */
if(!Array.prototype.copia) {
	Array.prototype.copia = function () {
		var tmp = [];
		var i;
		for(i=0; i<this.length; ++i) {
			tmp[i] = this[i];
		}
		return tmp;
	};
}
if(!Array.prototype.indexOf) {
	Array.prototype.indexOf = function (q) {
		var r=-1,i;
		for(i=0; i<this.length && r<0; ++i)
			if(this[i]==q) r = i;
		return r;
	};
}
if(!Array.prototype.lastIndexOf) {
	Array.prototype.lastIndexOf = function (q) {
		var r = -1, i;
		for(i=this.length-1; i>=0 && r<0; --i)
			if(this[i]==q) r = i;
		return r;
	};
}
/* FIM - Overrides... */

/* Uteis */
function evParar(e) {
	if(!e) e=window.event;
	if(!e) throw 'Evento inválido! Parando com um erro.';
	var tecla=(e.keyCode)?e.keyCode:((e.which)?e.which:null);
	switch(tecla) {
	case 112: //F1
	case 113: //F2
	case 114: //F3
	case 115: //F4
	case 116: //F5
	case 117: //F6
	case 118: //F7
	case 119: //F8
	case 120: //F9
	case 121: //F10
	case 122: //F11
	case 123: //F12
	case 16: //Shift esq
	case 17: //Ctrl esq
	case 18: //Alt esq
	case 27: //ESC
	case 8: //BackSpace
	case 9: //Tab
		if(!e.preventDefault) {
			if(e.keyCode) e.keyCode=65;
			if(e.which) e.which=65;
		}
	default:
		break;
	};
	if(e.stopPropagation) e.stopPropagation();
	if(e.preventDefault) {
		e.preventDefault();
	} else {
		e.cancelBubble=true;
		e.returnValue=false;
	}
	return false;
}

/* FIM - Uteis */
Jogo = {
	Consts:{
		nivelMax:9,
		lBloco:4,
		lCampo:12,
		aCampo:22,
		tDIR:39,
		tESQ:37,
		tCIM:38,
		tBAI:40,
		tPAUSE:19,
		elementos:['A','F','R','T','L','+','*'],
		elNPC:5,
		elNULL:6
	},
	Estado:{
		iniciando:0,
		jogando:1,
		pausa:2,
		finalizado:4,
		girando:8,
		atual:0,
		e:function (e) {
			return e&this.atual;
		},
		set:function (e) {
			switch(e) {
			case this.girando:
				this.atual |= e;
				break;
			default:
				this.atual = e;
				break;
			}
		},
		unset:function (e) {
			this.atual &= ~e;
		}
	},
	Interface:{
		Textos:{
			pontos:"Pontos",
			linhas:"Linhas",
			pausa:"Pausa",
			iniciar:"Iniciar"
		},
		fImages:true,
		cores:['#0000AA','#AA0000','#AA00AA','#00AA00','#AA5500','#CDCDCD','#232323'],
		imagens:new Image(),
		pxBloco:20,
		trapKeys:false,
		idSI:null,
		intervalo:60,
		campoV:null,
		canvas:null,
		table:null,
		elElemental:[],
		elPontos:null,
		elLinhas:null,
		criaTabInfo: function () {
			var d = document;
			var db = d.body;
			var JC = Jogo.Consts,
				IT = this.Textos;

			//Informações...
			var tb, tr, td;
			tb = d.createElement('table');
			tb.className = 'info';

			//tr = d.createElement('tr');
			tr = tb.insertRow(-1);
			tr.className = 'pontos';

			//td = d.createElement('th');
			td = tr.insertCell(-1);
			td.innerHTML = IT.pontos+':';
			//tr.appendChild(td);

			//td = d.createElement('td');
			td = tr.insertCell(-1);
			td.id = 'pontos';
			td.innerHTML = Jogo.pontos;

			this.elPontos = td;
			//tr.appendChild(td);
			//tb.appendChild(tr);

			//tr = d.createElement('tr');
			tr = tb.insertRow(-1);
			tr.className = 'linhas';

			//td = d.createElement('th');
			td = tr.insertCell(-1);
			td.innerHTML = IT.linhas+':';
			//tr.appendChild(td);

			//td = d.createElement('td');
			td = tr.insertCell(-1);
			td.id = 'linhas';
			td.innerHTML = Jogo.linhas;

			this.elLinhas = td;
			//tr.appendChild(td);
			//tb.appendChild(tr);

			for(i=0, t=JC.elementos.length-2; i<t; ++i) {
				j = JC.elementos[i];
				//tr = d.createElement('tr');
				tr = tb.insertRow(-1);
				tr.className = 'elemental';

				//td = d.createElement('th');
				td = tr.insertCell(-1);
				td.innerHTML = j+':';
				//tr.appendChild(td);

				//td = d.createElement('td');
				td = tr.insertCell(-1);
				td.id = 'elemental'+j;
				td.innerHTML = Jogo.elementalCount[i];

				this.elElemental[i] = td;
				//tr.appendChild(td);
				//tb.appendChild(tr);
			}
			db.appendChild(tb);
		},
		criaTabJogo: function () {
			var d = document;
			var db = d.body;
			var JC = Jogo.Consts;
			var i, j, k,
				pb = this.pxBloco,
				wc = JC.lCampo,
				hc = JC.aCampo;
			var tb, tr, td;

			tb = d.createElement('table');
			tb.className = 'jogo';
			tb.cellSpacing = 0;
			tb.cellPadding = 0;
			this.table = [];
			for(i=0; i<hc; ++i) {
				//tr = d.createElement('tr');
				tr = tb.insertRow(-1);
				tr.className = 'lJogo';
				tr.style.height = pb+'px';

				for(j=0; j<wc; ++j) {
					k = i*wc+j;
					//td = d.createElement('td');
					td = tr.insertCell(-1);
					td.id = 'b'+k;
					td.innerHTML = '&nbsp;';//JC.elementos[this.campoV[k]];
					td.style.background = this.cores[this.campoV[k]];
					td.style.width = pb+'px';
					//tr.appendChild(td);
					this.table[k] = td;
				}

				//tb.appendChild(tr);
			}
			db.appendChild(tb);
		},
		desenhaTabular: function () {
			var JC = Jogo.Consts;
			var i, j, k, m,
				pb = this.pxBloco,
				wc = JC.lCampo,
				hc = JC.aCampo,
				en = JC.elNULL,
				ep = JC.elNPC;
			for(i=0; i<hc; ++i) {
				for(j=0; j<wc; ++j) {
					k = i*wc+j;
					if(ec<=k) break;
					this.table[k].innerText = JC.elementos[this.campoV[k]]
				}
			}
			this.elPontos.innerHTML = Jogo.pontos;
			this.elLinhas.innerHTML = Jogo.linhas;
		},
		desenha: function () {
			var JC = Jogo.Consts;
			var i, j, k, m,
				pb = this.pxBloco,
				wc = JC.lCampo,
				hc = JC.aCampo,
				en = JC.elNULL,
				ep = JC.elNPC;

			var ec = this.campoV.length,
				a = hc*pb-pb;

			if(this.canvas) {
				var c = this.canvas.getContext('2d');
				c.fillStyle = this.cores[en];
				c.fillRect (0, 0, wc*pb, hc*pb);
				if(this.fImages) {
					var img = this.imagens;
					var wi = img.width;
					for(i=0; i<hc; ++i) {
						for(j=0; j<wc; ++j) {
							k = i * wc + j;
							if(ec<=k) break;
							m = this.campoV[k];
							if(m == en) continue;
							if(m == ep) {
								c.fillStyle = this.cores[m];
								c.fillRect(j*pb, i*pb, pb, pb);
							} else {
								//drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)
								c.drawImage(img, m*pb%wi, 0, pb, pb, j*pb, a-i*pb, pb, pb);
							}
						}
					}
				} else {
					for(i=0; i<hc; ++i) {
						for(j=0; j<wc; ++j) {
							k = i * wc + j;
							if(ec<=k) break;
							m = this.campoV[k];
							if(m == en) continue;
							//rever performance
							c.fillStyle = this.cores[m];
							c.fillRect(j*pb, a-i*pb, pb, pb);
						}
					}
				}
				this.elPontos.innerHTML = Jogo.pontos;
				this.elLinhas.innerHTML = Jogo.linhas;
			} else if(this.table) {
				var JC = Jogo.Consts;
				var i, j, k, m,
					pb = this.pxBloco,
					wc = JC.lCampo,
					hc = JC.aCampo,
					en = JC.elNULL,
					ep = JC.elNPC;
				for(i=0; i<hc; ++i) {
					for(j=0; j<wc; ++j) {
						k = (hc-1-i)*wc + j;
						if(ec<=k) break;
						//this.table[k].innerHTML = JC.elementos[this.campoV[k]];
						this.table[k].style.background = this.cores[this.campoV[k]];
					}
				}
				this.elPontos.innerHTML = Jogo.pontos;
				this.elLinhas.innerHTML = Jogo.linhas;
			} else {
				var buff = '';
				for(i=0; i<hc; ++i) {
					for(j=0; j<wc; ++j) {
						k = i * wc + j;
						if(ec<=k) break;
						buff += JC.elementos[this.campoV[k]];
					}
					buff += '<br />';
				}
				buff += '<br>Pontos: '+Jogo.pontos;
				buff += '<br>Linhas: '+Jogo.linhas;
				document.body.innerHTML = buff;
			}
		},
		desenhaProx: function () {
			var JB = Jogo.Bloco,
				JC = Jogo.Consts;
			var i, j, k, m,
				wb = JC.lBloco,
				pb = this.pxBloco,
				wc = JC.lCampo,
				hc = JC.aCampo,
				en = JC.elNULL;

			var xp = wc*pb,
				yp = (hc-wb)*pb,
				wpb = wb*pb,
				eb = JB.prox.length;

			if(this.canvas) {
				var c = this.canvas.getContext('2d');
				var a = yp+wb*pb-pb;
				c.fillStyle = this.cores[en];
				c.fillRect (xp, yp, wpb, wpb);
				if(this.fImages) {
					var img = this.imagens;
					var wi = img.width;
					for(i=0; i<wb; ++i) {
						for(j=0; j<wb; ++j) {
							k = i * wb + j;
							if(eb <= k) break;
							m = JB.prox[k];
							if(m == en) continue;
							c.drawImage(img, m*pb%wi, 0, pb, pb, xp+j*pb, a-i*pb, pb, pb);
						}
					}
				} else if(this.table) {
				} else {
					for(i=0; i<wb; ++i) {
						for(j=0; j<wb; ++j) {
							k = i * wb + j;
							if(eb <= k) break;
							m = JB.prox[k];
							if(m == en) continue;
							c.fillStyle = this.cores[m];
							c.fillRect(xp+j*pb, a-i*pb, pb, pb);
						}
					}
				}
			}
		},
		iniciar: function () {
			var d = document;
			var db = d.body;
			var JC = Jogo.Consts,
				IT = this.Textos;
			var i, j, k, m, t,
				pb = this.pxBloco,
				wb = JC.lBloco,
				wc = JC.lCampo,
				hc = JC.aCampo;

			if(this.canvas==null) {
				var excanvas = (!window.G_vmlCanvasManager)?false:((!G_vmlCanvasManager.initElement)?false:true);
				var c = d.createElement('canvas');

				if(c.getContext || excanvas) {
					c.className="jogo";
					if(excanvas) {
			            c.width = (wc+wb)*pb;
			            c.height = hc*pb;
						c.id="canvasJogo";
						db.appendChild(c);
						G_vmlCanvasManager.initElement(c);
						c = d.getElementById("canvasJogo");
						this.fImages=false;
					} else {
						c.setAttribute('width', ((wc+wb)*pb)+'px');
						c.setAttribute('height', (hc*pb)+'px');
						db.appendChild(c);
					}
					this.canvas = c;

					//Informações...
					this.criaTabInfo();

					var img;
					try {
						this.imagens.src = srcPearl;
					} catch(e) {
						this.fImages=false;
					}
				} else {
					this.canvas = false;
					this.criaTabJogo();
					this.criaTabInfo();
				}
			}
		}
	},
	Bloco:{
		base:[
			['*','I','*','*','*','I','*','*','*','I','*','*','*','I','*','*'],
			['*','*','J','*','*','*','J','*','*','J','J','*','*','*','*','*'],
			['*','L','*','*','*','L','*','*','*','L','L','*','*','*','*','*'],
			['*','*','*','*','*','O','O','*','*','O','O','*','*','*','*','*'],
			['*','*','*','*','*','S','S','*','S','S','*','*','*','*','*','*'],
			['*','*','*','*','*','T','*','*','*','T','T','*','*','T','*','*'],
			['*','*','*','*','Z','Z','*','*','*','Z','Z','*','*','*','*','*']
		],
		atual:null,
		prox:null,
		aX:0,
		aY:0,
		pX:1,
		pY:1,
		iniciar: function () {
			var JC = Jogo.Consts;
			var i, j, r, fi, fj,
				en = JC.elNULL,
				ne = JC.elementos.length - 2;
			var cn = JC.elementos[en];
			this.pX = Math.round((JC.lCampo-JC.lBloco)/2);
			for(i=0, fi=this.base.length; i<fi; ++i) {
				for(j=0, fj=this.base[i].length; j<fj; ++j) {
					if(this.base[i][j]!=cn) {
						this.base[i][j] = Math.round(Math.random()*ne)%ne;
					} else {
						this.base[i][j] = en;
					}
				}
			}
			this.seleciona();
		},
		podeMover: function (dir) {
			if(!Jogo.Estado.atual&Jogo.Estado.jogando) return false;
			if(this.atual==null) return false;

			var i, j, k, m,
				bx = this.aX,
				by = this.aY,
				wb = Jogo.Consts.lBloco,
				wc = Jogo.Consts.lCampo,
				en = Jogo.Consts.elNULL,
				ep = Jogo.Consts.elNPC;

			var a = by*wc+bx;
			switch(dir) {
				case Jogo.Consts.tDIR:
					++a;
					for(j=wb-1; j>=0; --j) { //c
						for(i=0; i<wb; ++i) { //l
							if(this.atual[i*wb+j] != en) {
								if(Jogo.campo[a+i*wc+j] != en) {
									return false;
								}
							}
						}
					}
					break;
				case Jogo.Consts.tESQ:
					--a;
					for(j=0; j<wb; ++j) { //c
						for(i=0; i<wb; ++i) { //l
							if(this.atual[i*wb+j] != en) {
								if(Jogo.campo[a+i*wc+j] != en) {
									return false;
								}
							}
						}
					}
					break;
				case Jogo.Consts.tCIM:
					return false;
				case Jogo.Consts.tBAI:
				default:
					a += wc;
					for(i=wb-1; i>=0; --i) {
						for(j=0; j<wb; ++j) {
							if(this.atual[i*wb+j] != en) {
								if(Jogo.campo[a+i*wc+j] != en) {
									return false;
								}
							}
						}
					}
					break;
			}
			return true;
		},
		mover: function (dir) {
			if(Jogo.Estado.atual!=Jogo.Estado.jogando) return;
			if(this.atual==null || Jogo.campo==null) return;

			var i, j, k, m, n, o,
				wb = Jogo.Consts.lBloco,
				wc = Jogo.Consts.lCampo,
				hc = Jogo.Consts.aCampo,
				bx = this.aX,
				by = this.aY,
				en = Jogo.Consts.elNULL,
				ep = Jogo.Consts.elNPC;

			switch(dir) {
			case Jogo.Consts.tESQ:
				--bx;
				break;
			case Jogo.Consts.tDIR:
				++bx;
				break;
			case Jogo.Consts.tBAI:
				++by;
				break;
			case Jogo.Consts.tCIM:
			default:
				return;
			}

			var bx2 = bx+wb-1,
				by2 = by+wb-1,
				a = -by*wb-bx;
			for(i=0; i<hc; ++i) {
				k = i*wc;
				if(i<by || i>by2) { // fora do bloco
					for(j=0; j<wc; ++j) {
						m = k+j;
						Jogo.Interface.campoV[m] = Jogo.campo[m];
					}
				} else {
					n = i*wb+a;
					for(j=0; j<wc; ++j) {
						m = k+j;
						if(j<bx || j>bx2) { //fora do bloco
							Jogo.Interface.campoV[m] = Jogo.campo[m];
						} else {
							o = n+j;
							if(this.atual[o] != en) {
								Jogo.Interface.campoV[m] = this.atual[o];
							} else {
								Jogo.Interface.campoV[m] = Jogo.campo[m];
							}
						}
					}
				}
			}
			this.aY = by;
			this.aX = bx;
		},
		podeGirar: function () {
			if(Jogo.Estado.atual!=Jogo.Estado.jogando) return false;
			if(this.atual==null) return false;

			var i, j,
				bx = this.aX,
				by = this.aY,
				wb = Jogo.Consts.lBloco,
				wc = Jogo.Consts.lCampo,
				en = Jogo.Consts.elNULL;

			var a = (by+wb-1)*wc+bx;
			for(i=0; i<wb; ++i) {
				for(j=0; j<wb; ++j) {
					if(this.atual[i*wb + j] != en) {
						if(Jogo.campo[a - j*wc + i] != en) return false;
					}
				}
			}
			return true;
		},
		girar: function () {
//em torno da origem:
//j'=cos(90)*j-sen(90)*i && i'=sen(90)*j+cos(90)*i && sen(90)=1 && cos(90)=0
//j'=-i && i'=j
			if(!Jogo.Estado.e(Jogo.Estado.jogando)) return;
			if(this.atual==null || Jogo.campo==null) return;

			Jogo.Estado.set(Jogo.Estado.girando);
			var i, j,
				w = Jogo.Consts.lBloco;
			var a = (w-1)*w;
			var tmp = this.atual.copia();
			for(i=0; i<w; ++i) {
				for(j=0; j<w; ++j) {
					this.atual[a - j*w + i] = tmp[i*w + j];
				}
			}
			Jogo.Estado.unset(Jogo.Estado.girando);
		},
		seleciona: function () {
			if(Jogo.Estado.atual!=Jogo.Estado.jogando) return;
			if(Jogo.campo==null) return;

			var i, j, k, r,
				bx = this.pX,
				by = this.pY,
				nb = this.base.length,
				wb = Jogo.Consts.lBloco,
				wc = Jogo.Consts.lCampo,
				en = Jogo.Consts.elNULL;

			do {
				this.atual = this.prox;
				r = Math.round(Math.random()*nb) % nb;
				this.prox = this.base[r].copia();
			} while(this.atual==null);

			//colocar bloco no campo
			this.aY = by;
			this.aX = bx;
			var a = by*wc+bx;
			for(i=0; i<wb; ++i) {
				for(j=0; j<wb; ++j) {
					k = i*wb+j;
					if(this.atual[k] != en) {
						Jogo.Interface.campoV[a+i*wc+j] = this.atual[k];
					}
				}
			}
			Jogo.Interface.desenhaProx();
		}
	},
	nivel:0,
	campo:null,
	pontos:0,
	linhas:0,
	elementalCount:[0,0,0,0,0,0,0],
	removeLinha: function (lin) {
		var i, j, k,
			wc = Jogo.Consts.lCampo;
		for(i=lin; i>1; --i) {
			for(j=1, k=wc-1; j<k; ++j) {
				Jogo.Interface.campoV[i*wc+j]=Jogo.Interface.campoV[(i-1)*wc+j];
			}
		}
	},
	contaElemental: function (arr) {
		var i, j, k;
		for(i=0, k=arr.length; i<k; ++i) {
			j = arr[i];
			if(j>=0) Jogo.Interface.elElemental[j].innerHTML = ++Jogo.elementalCount[j];
		}
	},
	validaLinhas: function () {
		var i, j, k, L = 0, m, n = false,
			wc = Jogo.Consts.lCampo,
			hc = Jogo.Consts.aCampo,
			wb = Jogo.Consts.lBloco,
			en = Jogo.Consts.elNULL,
			ep = Jogo.Consts.elNPC;

		for(i=hc-2; i>1; --i) {
			m = [];
			for(j=1; j<wc-1 && !n; ++j) {
				k = Jogo.Interface.campoV[i*wc+j];
				n = (k==en);
				if(k!=ep) m[m.length] = k;
			}
			if(!n) {
				Jogo.removeLinha(i);
				Jogo.contaElemental(m);
				i++;
				++L;
			} else {
				n = false;
			}
		}
		if(L>0) {
			var pt = (L==1)?40:((L==2)?100:((L==3)?300:1200));
			Jogo.pontos += pt*(Jogo.nivel+1);
			Jogo.linhas += L;
		}
		//rever performance...
		Jogo.campo = Jogo.Interface.campoV.copia();
	},
	verificaDerrota: function () {
		if(Jogo.Bloco.prox==null) return false; // inicio...
		var JC = Jogo.Consts;
		var i, j,
			wc = JC.lCampo,
			wb = JC.lBloco,
			en = JC.elNULL,
			ep = JC.elNPC;

		var ba = Jogo.Bloco.pX+wc,
			wa = wc*2-1;
		for(i=wc+1; i<wa; ++i) {
			if(Jogo.campo[i] != en) return true;
		}
		for(i=0; i<wb; ++i) {
			for(j=0; j<wb; ++j) {
				if(Jogo.Bloco.prox[i*wb+j] != en) {
					if(Jogo.campo[ba+i*wc+j] != en) {
						return true;
					}
				}
			}
		}
		return false;
	},
	fim: function () {
		if(Jogo.Estado.atual != Jogo.Estado.finalizado) {
			if(Jogo.Interface.idSI!=null) clearInterval(Jogo.Interface.idSI);
			Jogo.Estado.atual = Jogo.Estado.finalizado;
			Jogo.campo = [];
		}

		var ec = Jogo.Consts.lCampo*Jogo.Consts.aCampo,
			ne = Jogo.Consts.elementos.length - 2,
			tc = Jogo.campo.length;

		Jogo.Interface.campoV[tc] = Math.round(Math.random()*ne)%ne;
		Jogo.campo[tc] = Jogo.Interface.campoV[tc];
		Jogo.Interface.desenha();

		if(tc < ec) {
			setTimeout(Jogo.fim, Jogo.Interface.intervalo);
		}
	},
	pausar: function () {
		if(Jogo.Estado.atual!=Jogo.Estado.jogando) return;
		if(Jogo.Interface.idSI!=null) clearInterval(Jogo.Interface.idSI);
		Jogo.Estado.atual = Jogo.Estado.pausa;
	},
	continuar: function () {
		if(Jogo.Interface.idSI!=null) clearInterval(Jogo.Interface.idSI);
		Jogo.Interface.idSI = setInterval(Jogo.trataIntervalo, (Jogo.Consts.nivelMax-Jogo.nivel+1)*Jogo.Interface.intervalo);
		Jogo.Estado.atual = Jogo.Estado.jogando;
	},
	iniciar: function (nv) {
		if(Jogo.Estado.atual!=Jogo.Estado.iniciando) return;

		var JC = Jogo.Consts;
		var i, j, k,
			wc = JC.lCampo,
			hc = JC.aCampo,
			en = JC.elNULL,
			ep = JC.elNPC;

		Jogo.nivel = nv%(JC.nivelMax+1);
		Jogo.linhas = 0;
		Jogo.pontos = 0;

		Jogo.campo = [];
		Jogo.Interface.campoV = [];
		for(i=0; i<hc; ++i) {
			for(j=0; j<wc; ++j) {
				k = i * wc + j;
				Jogo.campo[k] = (i==0 || j==0 || i==(hc-1) || j==(wc-1))?ep:en;
				Jogo.Interface.campoV[k] = Jogo.campo[k];
			}
		}
		Jogo.Bloco.iniciar();

		// eventos...
		if(!Jogo.Interface.trapKeys) {
			Jogo.Interface.trapKeys = true;
			if (window.addEventListener) {
				window.addEventListener('keydown', Jogo.trataTeclas, false); 
			} else if (document.attachEvent) {
				document.attachEvent('onkeydown', Jogo.trataTeclas);
			} else if(window.onkeydown) {
				window.onkeydown = Jogo.trataTeclas;
			} else {
				Jogo.Interface.trapKeys = false;
			}
		}

		if(Jogo.Interface.trapKeys) {
			// prepara tela...
			Jogo.Interface.iniciar();
			// inicia movimento
			Jogo.continuar();
		}
	},
	trataIntervalo: function () {
//var ini = (new Date()).getTime();
		if(Jogo.Bloco.podeMover(Jogo.Consts.tBAI)) {
			Jogo.Bloco.mover(Jogo.Consts.tBAI);
		} else {
			Jogo.validaLinhas();
			if(Jogo.verificaDerrota()) {
				Jogo.fim();
			} else {
				Jogo.Bloco.seleciona();
			}
		}
		Jogo.Interface.desenha();
//var fim = (new Date()).getTime();
//var i=document.getElementById('info');
//if(i!=null) i.innerHTML = (fim-ini);
	},
	trataTeclas: function (e) {
		if(!e) e=window.event;
		var tecla=(e.keyCode)?e.keyCode:((e.which)?e.which:null);
		var JC = Jogo.Consts;
		switch(tecla) {
		case JC.tPAUSE: //pausa
			if(Jogo.Estado.atual==Jogo.Estado.pausa) {
				Jogo.continuar();
			} else {
				Jogo.pausar();
			}
			return evParar(e);
		case JC.tESQ: //seta à esquerda
		case JC.tDIR: //seta à direita
			if(Jogo.Bloco.podeMover(tecla)) {
				Jogo.Bloco.mover(tecla);
				Jogo.Interface.desenha();//retirar daqui!
			}
			return evParar(e);
		case JC.tCIM: //seta acima (inverte!)
			if(Jogo.Bloco.podeMover(JC.tBAI)) {
				Jogo.Bloco.mover(JC.tBAI);
				Jogo.pontos++;
				Jogo.Interface.desenha();//retirar daqui!
			}
			return evParar(e);
		case JC.tBAI: //seta abaixo (inverte!)
			if(Jogo.Bloco.podeGirar()) {
				Jogo.Bloco.girar();
				Jogo.Interface.desenha();//retirar daqui!
			}
			return evParar(e);
		default:
			//alert(tecla); //diminuindo a curva de aprendizado...
			break;
		}
		return true;
	}
};

window.onerror = function () {try {Jogo.pausar();} catch(e) {}; alert('Ocorreu um erro inesperado!'+arguments[0]+' L:'+arguments[2]);};
window.onload = function () {
	var d = document;
	if(d.createElement && d.getElementById) {
		var i, j,
			f, l, s, b;
		f = d.createElement('form');
		l = d.createElement('label');
		l.innerHTML = 'Selecione o nível (0 = lesma)';
		l.htmlFor = 'nivel';
		s = d.createElement('select');
		s.id = 'nivel';
		for(i=0, j=Jogo.Consts.nivelMax+1; i<j; ++i) {
			s.options[i]=new Option(i, i);
		}
		b = d.createElement('input');
		b.type = 'button';
		b.value = 'iniciar';
		b.onclick = function () {
			this.form.style.display='none';
			Jogo.iniciar(d.getElementById('nivel').selectedIndex);
		};
		f.appendChild(l);
		f.appendChild(s);
		f.appendChild(b);
		d.getElementById('info').appendChild(f);
		d.getElementById('ultima').style.display='none';
	} else {
		alert('Seu navegador é problemático... Tente outro dia.');
	}
};
